thrift-0.19.0/0000755000000000000000000000000014472652702013110 5ustar00rootroot00000000000000thrift-0.19.0/aclocal/0000755000000000000000000000000014472652641014510 5ustar00rootroot00000000000000thrift-0.19.0/aclocal/libtool.m40000777017777601777760000112617114114740175017552 0ustar00nobodynogroup00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # 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. m4_define([_LT_COPYING], [dnl # 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 . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; 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-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # 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 ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl 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, # which needs '.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 _LT_CC_BASENAME([$compiler]) # 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 _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# 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' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # 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' _LT_CONFIG_STATUS_DECLARATIONS 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 lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); 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 lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); 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 _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [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 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### 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 _LT_PROG_LTMAIN # 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" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # 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 ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl 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* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl 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* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [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" >&AS_MESSAGE_LOG_FD $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 >&AS_MESSAGE_LOG_FD # 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 >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [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" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $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 >&AS_MESSAGE_LOG_FD 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 >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) 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*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _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 ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_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 _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="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" _LT_TAGVAR(module_expsym_cmds, $1)="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" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$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" _LT_TAGVAR(archive_expsym_cmds, $1)="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 _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`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_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # 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*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ 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" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. 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|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) 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 AC_TRY_EVAL(ac_compile); then case `/usr/bin/file 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 AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file 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 AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file 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 AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file 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" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) 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 AC_TRY_EVAL(ac_compile); then case `/usr/bin/file 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 ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # 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 _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## 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\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD 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 $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" 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>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl 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* | 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 ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] 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 AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl 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 AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; 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_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; 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" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) 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 _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=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\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD 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_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $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* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) 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 AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [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]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # 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, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; 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 _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# 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@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ 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 AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) 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' m4_if([$1], [],[ 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*) # Native MSVC 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 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`' m4_if([$1], [],[ 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*) # 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. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-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 AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) 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 AC_MSG_RESULT([$dynamic_linker]) 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 _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[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]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [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 dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" 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]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) 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 AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [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 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [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]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [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"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [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='/usr/bin/file -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*) 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=/usr/bin/file 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=/usr/bin/file 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=/usr/bin/file 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 ]) 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 _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [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]) 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 AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [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 ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # 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++, # 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 AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && 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@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_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@&t@_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_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && 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" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD 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 ]) 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 AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) 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 _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-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 m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; 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_TAGVAR(lt_prog_compiler_pic, $1)=-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_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--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). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+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_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-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_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-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 m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; 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_TAGVAR(lt_prog_compiler_pic, $1)='-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_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-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). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-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_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_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 _LT_TAGVAR(export_symbols_cmds, $1)='$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 _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 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*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # 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'. _LT_TAGVAR(exclude_expsyms, $1)=['_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. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$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 _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= 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 _LT_TAGVAR(ld_shlibs, $1)=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 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$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)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+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 _LT_TAGVAR(archive_cmds, $1)='$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... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$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 _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(archive_expsym_cmds, $1)='$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' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$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. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(whole_archive_flag_spec, $1)='$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 _LT_TAGVAR(whole_archive_flag_spec, $1)='$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 _LT_TAGVAR(whole_archive_flag_spec, $1)= 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 _LT_TAGVAR(whole_archive_flag_spec, $1)='$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' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$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' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='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*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(ld_shlibs, $1)=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 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$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. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=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 _LT_TAGVAR(export_symbols_cmds, $1)='$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 _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 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. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$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. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=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 _LT_TAGVAR(hardcode_direct, $1)=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 _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= 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 _LT_TAGVAR(export_dynamic_flag_spec, $1)='$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. _LT_TAGVAR(always_export_symbols, $1)=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. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$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. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$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. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$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. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$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 _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$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 _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$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)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # 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. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$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, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='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 wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=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. _LT_TAGVAR(archive_cmds, $1)='$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. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=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*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$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*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # 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) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$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. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(archive_expsym_cmds, $1)='$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' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='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='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='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' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=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 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=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. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$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. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) 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. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [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]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$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);}' _LT_TAG_COMPILER # 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 _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## 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_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) 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 AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$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. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # 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 _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) 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_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_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 _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$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' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$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 _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= 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. _LT_TAGVAR(archive_cmds, $1)='$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 AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=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. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$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. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=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 _LT_TAGVAR(hardcode_direct, $1)=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 _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= 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 _LT_TAGVAR(export_dynamic_flag_spec, $1)='$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. _LT_TAGVAR(always_export_symbols, $1)=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. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$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. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$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. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$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. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$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 _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$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 _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # 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. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$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, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='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, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$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... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$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 _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(archive_expsym_cmds, $1)='$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' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=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 _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=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 _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$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*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$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. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='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++ _LT_TAGVAR(archive_cmds, $1)='$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. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=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. _LT_TAGVAR(archive_cmds, $1)='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' _LT_TAGVAR(archive_expsym_cmds, $1)='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"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$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."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='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`"' _LT_TAGVAR(old_archive_cmds, $1)='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' _LT_TAGVAR(archive_cmds, $1)='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' _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$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++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # 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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$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' _LT_TAGVAR(compiler_needs_object, $1)=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. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=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*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=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. _LT_TAGVAR(archive_cmds, $1)='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' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$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' _LT_TAGVAR(archive_expsym_cmds, $1)='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' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # 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 _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$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' ;; *) _LT_TAGVAR(archive_cmds, $1)='$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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # 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 _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='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' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=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?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=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. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$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. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='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. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='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 _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$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. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$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 _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$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... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) 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_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # 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). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _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 dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); 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 "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $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 "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $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 "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [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. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 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_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) 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 AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$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... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC 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_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) 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 AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$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... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## 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_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## 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_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # 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 _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [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 ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#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 ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS thrift-0.19.0/aclocal/ax_cxx_compile_stdcxx.m40000644000000000000000000004545614303740367021363 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) # or '14' (for the C++14 standard). # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016, 2018 Krzesimir Nowak # # 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 10 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual void f() {} }; struct Derived : public Base { virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201703L #error "This is not a C++17 compiler" #else #include #include #include namespace cxx17 { namespace test_constexpr_lambdas { constexpr int foo = [](){return 42;}(); } namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } namespace test_template_argument_deduction_for_class_templates { template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } namespace test_structured_bindings { int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } namespace test_exception_spec_type_system { struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus < 201703L ]]) thrift-0.19.0/aclocal/lt~obsolete.m40000777017777601777760000001377414114740176020464 0ustar00nobodynogroup00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # 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. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) thrift-0.19.0/aclocal/ax_boost_base.m40000644000000000000000000003262414303740367017565 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_boost_base.html # =========================================================================== # # SYNOPSIS # # AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # DESCRIPTION # # Test for the Boost C++ libraries of a particular version (or newer) # # If no path to the installed boost library is given the macro searchs # under /usr, /usr/local, /opt and /opt/local and evaluates the # $BOOST_ROOT environment variable. Further documentation is available at # . # # This macro calls: # # AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) # # And sets: # # HAVE_BOOST # # LICENSE # # Copyright (c) 2008 Thomas Porschberg # Copyright (c) 2009 Peter Adolphs # # 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 45 # example boost program (need to pass version) m4_define([_AX_BOOST_BASE_PROGRAM], [AC_LANG_PROGRAM([[ #include ]],[[ (void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))])); ]])]) AC_DEFUN([AX_BOOST_BASE], [ AC_ARG_WITH([boost], [AS_HELP_STRING([--with-boost@<:@=ARG@:>@], [use Boost library from a standard location (ARG=yes), from the specified location (ARG=), or disable it (ARG=no) @<:@ARG=yes@:>@ ])], [ AS_CASE([$withval], [no],[want_boost="no";_AX_BOOST_BASE_boost_path=""], [yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""], [want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"]) ], [want_boost="yes"]) AC_ARG_WITH([boost-libdir], [AS_HELP_STRING([--with-boost-libdir=LIB_DIR], [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.])], [ AS_IF([test -d "$withval"], [_AX_BOOST_BASE_boost_lib_path="$withval"], [AC_MSG_ERROR([--with-boost-libdir expected directory name])]) ], [_AX_BOOST_BASE_boost_lib_path=""]) BOOST_LDFLAGS="" BOOST_CPPFLAGS="" AS_IF([test "x$want_boost" = "xyes"], [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])]) AC_SUBST(BOOST_CPPFLAGS) AC_SUBST(BOOST_LDFLAGS) ]) # convert a version string in $2 to numeric and affect to polymorphic var $1 AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[ AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"]) _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'` _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'` AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"], [AC_MSG_ERROR([You should at least specify libboost major version])]) _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'` AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"], [_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"]) _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"], [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"]) _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor` AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET) ]) dnl Run the detection of boost should be run only if $want_boost AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[ _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1]) succeeded=no AC_REQUIRE([AC_CANONICAL_HOST]) dnl On 64-bit systems check for system libraries in both lib64 and lib. dnl The former is specified by FHS, but e.g. Debian does not adhere to dnl this (as it rises problems for generic multi-arch support). dnl The last entry in the list is chosen by default when no libraries dnl are found, e.g. when only header-only libraries are installed! AS_CASE([${host_cpu}], [x86_64],[libsubdirs="lib64 libx32 lib lib64"], [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"], [libsubdirs="lib"] ) dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give dnl them priority over the other paths since, if libs are found there, they dnl are almost assuredly the ones desired. AS_CASE([${host_cpu}], [i?86],[multiarch_libsubdir="lib/i386-${host_os}"], [multiarch_libsubdir="lib/${host_cpu}-${host_os}"] ) dnl first we check the system location for boost libraries dnl this location ist chosen if boost libraries are installed with the --layout=system option dnl or if you install boost with RPM AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[ AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"]) AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[ AC_MSG_RESULT([yes]) BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include" for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"]) AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[ AC_MSG_RESULT([yes]) BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"; break; ], [AC_MSG_RESULT([no])]) done],[ AC_MSG_RESULT([no])]) ],[ if test X"$cross_compiling" = Xyes; then search_libsubdirs=$multiarch_libsubdir else search_libsubdirs="$multiarch_libsubdir $libsubdirs" fi for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then for libsubdir in $search_libsubdirs ; do if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir" BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include" break; fi done ]) dnl overwrite ld flags if we have required special directory with dnl --with-boost-libdir parameter AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"], [BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"]) AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)]) CPPFLAGS_SAVED="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS LDFLAGS_SAVED="$LDFLAGS" LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" export LDFLAGS AC_REQUIRE([AC_PROG_CXX]) AC_LANG_PUSH(C++) AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes ],[ ]) AC_LANG_POP([C++]) dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version if test "x$succeeded" != "xyes" ; then CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" BOOST_CPPFLAGS= if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then BOOST_LDFLAGS= fi _version=0 if test -n "$_AX_BOOST_BASE_boost_path" ; then if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp fi VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE" done dnl if nothing found search for layout used in Windows distributions if test -z "$BOOST_CPPFLAGS"; then if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path" fi fi dnl if we found something and BOOST_LDFLAGS was unset before dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here. if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then for libsubdir in $libsubdirs ; do if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir" fi fi else if test "x$cross_compiling" != "xyes" ; then for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp best_path=$_AX_BOOST_BASE_boost_path fi done fi done VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then for libsubdir in $libsubdirs ; do if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done BOOST_LDFLAGS="-L$best_path/$libsubdir" fi fi if test -n "$BOOST_ROOT" ; then for libsubdir in $libsubdirs ; do if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` V_CHECK=`expr $stage_version_shorten \>\= $_version` if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) BOOST_CPPFLAGS="-I$BOOST_ROOT" BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" fi fi fi fi CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" export LDFLAGS AC_LANG_PUSH(C++) AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes ],[ ]) AC_LANG_POP([C++]) fi if test "x$succeeded" != "xyes" ; then if test "x$_version" = "x0" ; then AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) else AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) fi # execute ACTION-IF-NOT-FOUND (if present): ifelse([$3], , :, [$3]) else AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) # execute ACTION-IF-FOUND (if present): ifelse([$2], , :, [$2]) fi CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" ]) thrift-0.19.0/aclocal/ax_dmd.m40000644000000000000000000000656314303740367016214 0ustar00rootroot00000000000000dnl @synopsis AX_DMD dnl dnl Test for the presence of a DMD-compatible D2 compiler, and (optionally) dnl specified modules on the import path. dnl dnl If "DMD" is defined in the environment, that will be the only dnl dmd command tested. Otherwise, a hard-coded list will be used. dnl dnl After AX_DMD runs, the shell variables "success" and "ax_dmd" are set to dnl "yes" or "no", and "DMD" is set to the appropriate command. Furthermore, dnl "dmd_optlink" will be set to "yes" or "no" depending on whether OPTLINK is dnl used as the linker (DMD/Windows), and "dmd_of_dirsep" will be set to the dnl directory separator to use when passing -of to DMD (OPTLINK requires a dnl backslash). dnl dnl AX_CHECK_D_MODULE must be run after AX_DMD. It tests for the presence of a dnl module in the import path of the chosen compiler, and sets the shell dnl variable "success" to "yes" or "no". dnl dnl @category D dnl @version 2011-05-31 dnl @license AllPermissive dnl dnl Copyright (C) 2009 David Reiss dnl Copyright (C) 2011 David Nadlinger dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. AC_DEFUN([AX_DMD], [ dnl Hard-coded default commands to test. DMD_PROGS="dmd,gdmd,ldmd" dnl Allow the user to specify an alternative. if test -n "$DMD" ; then DMD_PROGS="$DMD" fi AC_MSG_CHECKING(for DMD) # std.algorithm as a quick way to check for D2/Phobos. echo "import std.algorithm; void main() {}" > configtest_ax_dmd.d success=no oIFS="$IFS" IFS="," for DMD in $DMD_PROGS ; do IFS="$oIFS" echo "Running \"$DMD configtest_ax_dmd.d\"" >&AS_MESSAGE_LOG_FD if $DMD configtest_ax_dmd.d >&AS_MESSAGE_LOG_FD 2>&1 ; then success=yes break fi done if test "$success" != "yes" ; then AC_MSG_RESULT(no) DMD="" else AC_MSG_RESULT(yes) fi ax_dmd="$success" # Test whether OPTLINK is used by trying if DMD accepts -L/? without # erroring out. if test "$success" == "yes" ; then AC_MSG_CHECKING(whether DMD uses OPTLINK) echo "Running \â€$DMD -L/? configtest_ax_dmd.d\"" >&AS_MESSAGE_LOG_FD if $DMD -L/? configtest_ax_dmd.d >&AS_MESSAGE_LOG_FD 2>&1 ; then AC_MSG_RESULT(yes) dmd_optlink="yes" # This actually produces double slashes in the final configure # output, but at least it works. dmd_of_dirsep="\\\\" else AC_MSG_RESULT(no) dmd_optlink="no" dmd_of_dirsep="/" fi fi rm -f configtest_ax_dmd* ]) AC_DEFUN([AX_CHECK_D_MODULE], [ AC_MSG_CHECKING(for D module [$1]) echo "import $1; void main() {}" > configtest_ax_dmd.d echo "Running \"$DMD configtest_ax_dmd.d\"" >&AS_MESSAGE_LOG_FD if $DMD -c configtest_ax_dmd.d >&AS_MESSAGE_LOG_FD 2>&1 ; then AC_MSG_RESULT(yes) success=yes else AC_MSG_RESULT(no) success=no fi rm -f configtest_ax_dmd* ]) thrift-0.19.0/aclocal/ltsugar.m40000777017777601777760000001044014114740175017555 0ustar00nobodynogroup00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # 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. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) thrift-0.19.0/aclocal/ax_lib_event.m40000644000000000000000000001524514303740367017414 0ustar00rootroot00000000000000dnl @synopsis AX_LIB_EVENT([MINIMUM-VERSION]) dnl dnl Test for the libevent library of a particular version (or newer). dnl dnl If no path to the installed libevent is given, the macro will first try dnl using no -I or -L flags, then searches under /usr, /usr/local, /opt, dnl and /opt/libevent. dnl If these all fail, it will try the $LIBEVENT_ROOT environment variable. dnl dnl This macro requires that #include works and defines u_char. dnl dnl This macro calls: dnl AC_SUBST(LIBEVENT_CPPFLAGS) dnl AC_SUBST(LIBEVENT_LDFLAGS) dnl AC_SUBST(LIBEVENT_LIBS) dnl dnl And (if libevent is found): dnl AC_DEFINE(HAVE_LIBEVENT) dnl dnl It also leaves the shell variables "success" and "ax_have_libevent" dnl set to "yes" or "no". dnl dnl NOTE: This macro does not currently work for cross-compiling, dnl but it can be easily modified to allow it. (grep "cross"). dnl dnl @category InstalledPackages dnl @category C dnl @version 2007-09-12 dnl @license AllPermissive dnl dnl Copyright (C) 2009 David Reiss dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. dnl Input: ax_libevent_path, WANT_LIBEVENT_VERSION dnl Output: success=yes/no AC_DEFUN([AX_LIB_EVENT_DO_CHECK], [ # Save our flags. CPPFLAGS_SAVED="$CPPFLAGS" LDFLAGS_SAVED="$LDFLAGS" LIBS_SAVED="$LIBS" LD_LIBRARY_PATH_SAVED="$LD_LIBRARY_PATH" # Set our flags if we are checking a specific directory. if test -n "$ax_libevent_path" ; then LIBEVENT_CPPFLAGS="-I$ax_libevent_path/include" LIBEVENT_LDFLAGS="-L$ax_libevent_path/lib" LD_LIBRARY_PATH="$ax_libevent_path/lib:$LD_LIBRARY_PATH" else LIBEVENT_CPPFLAGS="" LIBEVENT_LDFLAGS="" fi # Required flag for libevent. LIBEVENT_LIBS="-levent" # Prepare the environment for compilation. CPPFLAGS="$CPPFLAGS $LIBEVENT_CPPFLAGS" LDFLAGS="$LDFLAGS $LIBEVENT_LDFLAGS" LIBS="$LIBS $LIBEVENT_LIBS" export CPPFLAGS export LDFLAGS export LIBS export LD_LIBRARY_PATH success=no # Compile, link, and run the program. This checks: # - event.h is available for including. # - event_get_version() is available for linking. # - The event version string is lexicographically greater # than the required version. AC_LANG_PUSH([C]) dnl This can be changed to AC_LINK_IFELSE if you are cross-compiling, dnl but then the version cannot be checked. AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[ const char* lib_version = event_get_version(); const char* wnt_version = "$WANT_LIBEVENT_VERSION"; int lib_digits; int wnt_digits; for (;;) { /* If we reached the end of the want version. We have it. */ if (*wnt_version == '\0' || *wnt_version == '-') { return 0; } /* If the want version continues but the lib version does not, */ /* we are missing a letter. We don't have it. */ if (*lib_version == '\0' || *lib_version == '-') { return 1; } /* In the 1.4 version numbering style, if there are more digits */ /* in one version than the other, that one is higher. */ for (lib_digits = 0; lib_version[lib_digits] >= '0' && lib_version[lib_digits] <= '9'; lib_digits++) ; for (wnt_digits = 0; wnt_version[wnt_digits] >= '0' && wnt_version[wnt_digits] <= '9'; wnt_digits++) ; if (lib_digits > wnt_digits) { return 0; } if (lib_digits < wnt_digits) { return 1; } /* If we have greater than what we want. We have it. */ if (*lib_version > *wnt_version) { return 0; } /* If we have less, we don't. */ if (*lib_version < *wnt_version) { return 1; } lib_version++; wnt_version++; } return 0; ]])], [ success=yes ]) AC_LANG_POP([C]) # Restore flags. CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" LIBS="$LIBS_SAVED" LD_LIBRARY_PATH="$LD_LIBRARY_PATH_SAVED" ]) AC_DEFUN([AX_LIB_EVENT], [ dnl Allow search path to be overridden on the command line. AC_ARG_WITH([libevent], AS_HELP_STRING([--with-libevent@<:@=DIR@:>@], [use libevent [default=yes]. Optionally specify the root prefix dir where libevent is installed]), [ if test "x$withval" = "xno"; then want_libevent="no" elif test "x$withval" = "xyes"; then want_libevent="yes" ax_libevent_path="" else want_libevent="yes" ax_libevent_path="$withval" fi ], [ want_libevent="yes" ; ax_libevent_path="" ]) if test "$want_libevent" = "yes"; then WANT_LIBEVENT_VERSION=ifelse([$1], ,1.2,$1) AC_MSG_CHECKING(for libevent >= $WANT_LIBEVENT_VERSION) # Run tests. if test -n "$ax_libevent_path"; then AX_LIB_EVENT_DO_CHECK else for ax_libevent_path in "" $lt_sysroot/usr $lt_sysroot/usr/local $lt_sysroot/opt $lt_sysroot/opt/local $lt_sysroot/opt/libevent "$LIBEVENT_ROOT" ; do AX_LIB_EVENT_DO_CHECK if test "$success" = "yes"; then break; fi done fi if test "$success" != "yes" ; then AC_MSG_RESULT(no) LIBEVENT_CPPFLAGS="" LIBEVENT_LDFLAGS="" LIBEVENT_LIBS="" else AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LIBEVENT,,[define if libevent is available]) ax_have_libevent_[]m4_translit([$1], [.], [_])="yes" fi ax_have_libevent="$success" AC_SUBST(LIBEVENT_CPPFLAGS) AC_SUBST(LIBEVENT_LDFLAGS) AC_SUBST(LIBEVENT_LIBS) fi ]) thrift-0.19.0/aclocal/ax_prog_haxe_version.m40000644000000000000000000000340714303740367021163 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_haxe_version.html # =========================================================================== # # SYNOPSIS # # AX_PROG_HAXE_VERSION([VERSION],[ACTION-IF-TRUE],[ACTION-IF-FALSE]) # # DESCRIPTION # # Makes sure that haxe supports the version indicated. If true the shell # commands in ACTION-IF-TRUE are executed. If not the shell commands in # ACTION-IF-FALSE are run. The $HAXE_VERSION variable will be filled with # the detected version. # # This macro uses the $HAXE variable to perform the check. If $HAXE is not # set prior to calling this macro, the macro will fail. # # Example: # # AC_PATH_PROG([HAXE],[haxe]) # AC_PROG_HAXE_VERSION([3.1.3],[ ... ],[ ... ]) # # Searches for Haxe, then checks if at least version 3.1.3 is present. # # LICENSE # # Copyright (c) 2015 Jens Geyer # # 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 2 AC_DEFUN([AX_PROG_HAXE_VERSION],[ AC_REQUIRE([AC_PROG_SED]) AS_IF([test -n "$HAXE"],[ ax_haxe_version="$1" AC_MSG_CHECKING([for haxe version]) haxe_version=`$HAXE -version 2>&1 | $SED -e 's/^.* \( @<:@0-9@:>@*\.@<:@0-9@:>@*\.@<:@0-9@:>@*\) .*/\1/'` AC_MSG_RESULT($haxe_version) AC_SUBST([HAXE_VERSION],[$haxe_version]) AX_COMPARE_VERSION([$ax_haxe_version],[le],[$haxe_version],[ : $2 ],[ : $3 ]) ],[ AC_MSG_WARN([could not find Haxe]) $3 ]) ]) thrift-0.19.0/aclocal/ax_thrift_internal.m40000644000000000000000000000210514303740367020630 0ustar00rootroot00000000000000dnl @synopsis AX_THRIFT_GEN(SHORT_LANGUAGE, LONG_LANGUAGE, DEFAULT) dnl @synopsis AX_THRIFT_LIB(SHORT_LANGUAGE, LONG_LANGUAGE, DEFAULT) dnl dnl Allow a particular language generator to be disabled. dnl Allow a particular language library to be disabled. dnl dnl These macros have poor error handling and are poorly documented. dnl They are intended only for internal use by the Thrift compiler. dnl dnl @version 2008-02-20 dnl @license AllPermissive dnl dnl Copyright (C) 2009 David Reiss dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. AC_DEFUN([AX_THRIFT_LIB], [ AC_ARG_WITH($1, AC_HELP_STRING([--with-$1], [build the $2 library @<:@default=$3@:>@]), [with_$1="$withval"], [with_$1=$3] ) have_$1=no dnl What we do here is going to vary from library to library, dnl so we can't really generalize (yet!). ]) thrift-0.19.0/aclocal/ax_prog_perl_modules.m40000644000000000000000000000431414303740367021161 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_perl_modules.html # =========================================================================== # # SYNOPSIS # # AX_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # # DESCRIPTION # # Checks to see if the given perl modules are available. If true the shell # commands in ACTION-IF-TRUE are executed. If not the shell commands in # ACTION-IF-FALSE are run. Note if $PERL is not set (for example by # calling AC_CHECK_PROG, or AC_PATH_PROG), AC_CHECK_PROG(PERL, perl, perl) # will be run. # # MODULES is a space separated list of module names. To check for a # minimum version of a module, append the version number to the module # name, separated by an equals sign. # # Example: # # AX_PROG_PERL_MODULES( Text::Wrap Net::LDAP=1.0.3, , # AC_MSG_WARN(Need some Perl modules) # # LICENSE # # Copyright (c) 2009 Dean Povey # # 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 8 AU_ALIAS([AC_PROG_PERL_MODULES], [AX_PROG_PERL_MODULES]) AC_DEFUN([AX_PROG_PERL_MODULES],[dnl m4_define([ax_perl_modules]) m4_foreach([ax_perl_module], m4_split(m4_normalize([$1])), [ m4_append([ax_perl_modules], [']m4_bpatsubst(ax_perl_module,=,[ ])[' ]) ]) # Make sure we have perl if test -z "$PERL"; then AC_CHECK_PROG(PERL,perl,perl) fi if test "x$PERL" != x; then ax_perl_modules_failed=0 for ax_perl_module in ax_perl_modules; do AC_MSG_CHECKING(for perl module $ax_perl_module) # Would be nice to log result here, but can't rely on autoconf internals $PERL -e "use $ax_perl_module; exit" > /dev/null 2>&1 if test $? -ne 0; then AC_MSG_RESULT(no); ax_perl_modules_failed=1 else AC_MSG_RESULT(ok); fi done # Run optional shell commands if test "$ax_perl_modules_failed" = 0; then : $2 else : $3 fi else AC_MSG_WARN(could not find perl) fi])dnl thrift-0.19.0/aclocal/ax_compare_version.m40000644000000000000000000001465314303740367020642 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_compare_version.html # =========================================================================== # # SYNOPSIS # # AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # # DESCRIPTION # # This macro compares two version strings. Due to the various number of # minor-version numbers that can exist, and the fact that string # comparisons are not compatible with numeric comparisons, this is not # necessarily trivial to do in a autoconf script. This macro makes doing # these comparisons easy. # # The six basic comparisons are available, as well as checking equality # limited to a certain number of minor-version levels. # # The operator OP determines what type of comparison to do, and can be one # of: # # eq - equal (test A == B) # ne - not equal (test A != B) # le - less than or equal (test A <= B) # ge - greater than or equal (test A >= B) # lt - less than (test A < B) # gt - greater than (test A > B) # # Additionally, the eq and ne operator can have a number after it to limit # the test to that number of minor versions. # # eq0 - equal up to the length of the shorter version # ne0 - not equal up to the length of the shorter version # eqN - equal up to N sub-version levels # neN - not equal up to N sub-version levels # # When the condition is true, shell commands ACTION-IF-TRUE are run, # otherwise shell commands ACTION-IF-FALSE are run. The environment # variable 'ax_compare_version' is always set to either 'true' or 'false' # as well. # # Examples: # # AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8]) # AX_COMPARE_VERSION([3.15],[lt],[3.15.8]) # # would both be true. # # AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8]) # AX_COMPARE_VERSION([3.15],[gt],[3.15.8]) # # would both be false. # # AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8]) # # would be true because it is only comparing two minor versions. # # AX_COMPARE_VERSION([3.15.7],[eq0],[3.15]) # # would be true because it is only comparing the lesser number of minor # versions of the two values. # # Note: The characters that separate the version numbers do not matter. An # empty string is the same as version 0. OP is evaluated by autoconf, not # configure, so must be a string, not a variable. # # The author would like to acknowledge Guido Draheim whose advice about # the m4_case and m4_ifvaln functions make this macro only include the # portions necessary to perform the specific comparison specified by the # OP argument in the final configure script. # # LICENSE # # Copyright (c) 2008 Tim Toolan # # 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 12 dnl ######################################################################### AC_DEFUN([AX_COMPARE_VERSION], [ AC_REQUIRE([AC_PROG_AWK]) # Used to indicate true or false condition ax_compare_version=false # Convert the two version strings to be compared into a format that # allows a simple string comparison. The end result is that a version # string of the form 1.12.5-r617 will be converted to the form # 0001001200050617. In other words, each number is zero padded to four # digits, and non digits are removed. AS_VAR_PUSHDEF([A],[ax_compare_version_A]) A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/[[^0-9]]//g'` AS_VAR_PUSHDEF([B],[ax_compare_version_B]) B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \ -e 's/[[^0-9]]//g'` dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary dnl # then the first line is used to determine if the condition is true. dnl # The sed right after the echo is to remove any indented white space. m4_case(m4_tolower($2), [lt],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"` ], [gt],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"` ], [le],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"` ], [ge],[ ax_compare_version=`echo "x$A x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"` ],[ dnl Split the operator from the subversion count if present. m4_bmatch(m4_substr($2,2), [0],[ # A count of zero means use the length of the shorter version. # Determine the number of characters in A and B. ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'` ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'` # Set A to no more than B's length and B to no more than A's length. A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"` B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"` ], [[0-9]+],[ # A count greater than zero means use only that many subversions A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"` ], [.+],[ AC_WARNING( [illegal OP numeric parameter: $2]) ],[]) # Pad zeros at end of numbers to make same length. ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`" B="$B`echo $A | sed 's/./0/g'`" A="$ax_compare_version_tmp_A" # Check for equality or inequality as necessary. m4_case(m4_tolower(m4_substr($2,0,2)), [eq],[ test "x$A" = "x$B" && ax_compare_version=true ], [ne],[ test "x$A" != "x$B" && ax_compare_version=true ],[ AC_WARNING([illegal OP parameter: $2]) ]) ]) AS_VAR_POPDEF([A])dnl AS_VAR_POPDEF([B])dnl dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE. if test "$ax_compare_version" = "true" ; then m4_ifvaln([$4],[$4],[:])dnl m4_ifvaln([$5],[else $5])dnl fi ]) dnl AX_COMPARE_VERSION thrift-0.19.0/aclocal/ax_javac_and_java.m40000644000000000000000000001004514303740367020345 0ustar00rootroot00000000000000dnl @synopsis AX_JAVAC_AND_JAVA dnl @synopsis AX_CHECK_JAVA_CLASS(CLASSNAME) dnl dnl Test for the presence of a JDK, and (optionally) specific classes. dnl dnl If "JAVA" is defined in the environment, that will be the only dnl java command tested. Otherwise, a hard-coded list will be used. dnl Similarly for "JAVAC". dnl dnl AX_JAVAC_AND_JAVA does not currently support testing for a particular dnl Java version, testing for only one of "java" and "javac", or dnl compiling or running user-provided Java code. dnl dnl After AX_JAVAC_AND_JAVA runs, the shell variables "success" and dnl "ax_javac_and_java" are set to "yes" or "no", and "JAVAC" and dnl "JAVA" are set to the appropriate commands. dnl dnl AX_CHECK_JAVA_CLASS must be run after AX_JAVAC_AND_JAVA. dnl It tests for the presence of a class based on a fully-qualified name. dnl It sets the shell variable "success" to "yes" or "no". dnl dnl @category Java dnl @version 2009-02-09 dnl @license AllPermissive dnl dnl Copyright (C) 2009 David Reiss dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. AC_DEFUN([AX_JAVAC_AND_JAVA], [ dnl Hard-coded default commands to test. JAVAC_PROGS="javac,jikes,gcj -C" JAVA_PROGS="java,kaffe" dnl Allow the user to specify an alternative. if test -n "$JAVAC" ; then JAVAC_PROGS="$JAVAC" fi if test -n "$JAVA" ; then JAVA_PROGS="$JAVA" fi AC_MSG_CHECKING(for javac and java) echo "public class configtest_ax_javac_and_java { public static void main(String args@<:@@:>@) { } }" > configtest_ax_javac_and_java.java success=no oIFS="$IFS" IFS="," for JAVAC in $JAVAC_PROGS ; do IFS="$oIFS" echo "Running \"$JAVAC configtest_ax_javac_and_java.java\"" >&AS_MESSAGE_LOG_FD if $JAVAC configtest_ax_javac_and_java.java >&AS_MESSAGE_LOG_FD 2>&1 ; then # prevent $JAVA VM issues with UTF-8 path names (THRIFT-3271) oLC_ALL="$LC_ALL" LC_ALL="" IFS="," for JAVA in $JAVA_PROGS ; do IFS="$oIFS" echo "Running \"$JAVA configtest_ax_javac_and_java\"" >&AS_MESSAGE_LOG_FD if $JAVA configtest_ax_javac_and_java >&AS_MESSAGE_LOG_FD 2>&1 ; then success=yes break 2 fi done # restore LC_ALL LC_ALL="$oLC_ALL" oLC_ALL="" fi done rm -f configtest_ax_javac_and_java.java configtest_ax_javac_and_java.class if test "$success" != "yes" ; then AC_MSG_RESULT(no) JAVAC="" JAVA="" else AC_MSG_RESULT(yes) fi ax_javac_and_java="$success" ]) AC_DEFUN([AX_CHECK_JAVA_CLASS], [ AC_MSG_CHECKING(for Java class [$1]) echo "import $1; public class configtest_ax_javac_and_java { public static void main(String args@<:@@:>@) { } }" > configtest_ax_javac_and_java.java echo "Running \"$JAVAC configtest_ax_javac_and_java.java\"" >&AS_MESSAGE_LOG_FD if $JAVAC configtest_ax_javac_and_java.java >&AS_MESSAGE_LOG_FD 2>&1 ; then AC_MSG_RESULT(yes) success=yes else AC_MSG_RESULT(no) success=no fi rm -f configtest_ax_javac_and_java.java configtest_ax_javac_and_java.class ]) AC_DEFUN([AX_CHECK_ANT_VERSION], [ AC_MSG_CHECKING(for ant version > $2) ANT_VALID=`expr "x$(printf "$2\n$($1 -version 2>/dev/null | sed -n 's/.*version \(@<:@0-9\.@:>@*\).*/\1/p')" | sort -t '.' -k 1,1 -k 2,2 -k 3,3 -g | sed -n 1p)" = "x$2"` if test "x$ANT_VALID" = "x1" ; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) ANT="" fi ]) thrift-0.19.0/aclocal/ax_lua.m40000644000000000000000000006360314303740367016227 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_lua.html # =========================================================================== # # SYNOPSIS # # AX_PROG_LUA[([MINIMUM-VERSION], [TOO-BIG-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # AX_LUA_HEADERS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # AX_LUA_LIBS[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # AX_LUA_READLINE[([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])] # # DESCRIPTION # # Detect a Lua interpreter, optionally specifying a minimum and maximum # version number. Set up important Lua paths, such as the directories in # which to install scripts and modules (shared libraries). # # Also detect Lua headers and libraries. The Lua version contained in the # header is checked to match the Lua interpreter version exactly. When # searching for Lua libraries, the version number is used as a suffix. # This is done with the goal of supporting multiple Lua installs (5.1, # 5.2, and 5.3 side-by-side). # # A note on compatibility with previous versions: This file has been # mostly rewritten for serial 18. Most developers should be able to use # these macros without needing to modify configure.ac. Care has been taken # to preserve each macro's behavior, but there are some differences: # # 1) AX_WITH_LUA is deprecated; it now expands to the exact same thing as # AX_PROG_LUA with no arguments. # # 2) AX_LUA_HEADERS now checks that the version number defined in lua.h # matches the interpreter version. AX_LUA_HEADERS_VERSION is therefore # unnecessary, so it is deprecated and does not expand to anything. # # 3) The configure flag --with-lua-suffix no longer exists; the user # should instead specify the LUA precious variable on the command line. # See the AX_PROG_LUA description for details. # # Please read the macro descriptions below for more information. # # This file was inspired by Andrew Dalke's and James Henstridge's # python.m4 and Tom Payne's, Matthieu Moy's, and Reuben Thomas's ax_lua.m4 # (serial 17). Basically, this file is a mash-up of those two files. I # like to think it combines the best of the two! # # AX_PROG_LUA: Search for the Lua interpreter, and set up important Lua # paths. Adds precious variable LUA, which may contain the path of the Lua # interpreter. If LUA is blank, the user's path is searched for an # suitable interpreter. # # If MINIMUM-VERSION is supplied, then only Lua interpreters with a # version number greater or equal to MINIMUM-VERSION will be accepted. If # TOO-BIG-VERSION is also supplied, then only Lua interpreters with a # version number greater or equal to MINIMUM-VERSION and less than # TOO-BIG-VERSION will be accepted. # # The Lua version number, LUA_VERSION, is found from the interpreter, and # substituted. LUA_PLATFORM is also found, but not currently supported (no # standard representation). # # Finally, the macro finds four paths: # # luadir Directory to install Lua scripts. # pkgluadir $luadir/$PACKAGE # luaexecdir Directory to install Lua modules. # pkgluaexecdir $luaexecdir/$PACKAGE # # These paths are found based on $prefix, $exec_prefix, Lua's # package.path, and package.cpath. The first path of package.path # beginning with $prefix is selected as luadir. The first path of # package.cpath beginning with $exec_prefix is used as luaexecdir. This # should work on all reasonable Lua installations. If a path cannot be # determined, a default path is used. Of course, the user can override # these later when invoking make. # # luadir Default: $prefix/share/lua/$LUA_VERSION # luaexecdir Default: $exec_prefix/lib/lua/$LUA_VERSION # # These directories can be used by Automake as install destinations. The # variable name minus 'dir' needs to be used as a prefix to the # appropriate Automake primary, e.g. lua_SCRIPS or luaexec_LIBRARIES. # # If an acceptable Lua interpreter is found, then ACTION-IF-FOUND is # performed, otherwise ACTION-IF-NOT-FOUND is preformed. If ACTION-IF-NOT- # FOUND is blank, then it will default to printing an error. To prevent # the default behavior, give ':' as an action. # # AX_LUA_HEADERS: Search for Lua headers. Requires that AX_PROG_LUA be # expanded before this macro. Adds precious variable LUA_INCLUDE, which # may contain Lua specific include flags, e.g. -I/usr/include/lua5.1. If # LUA_INCLUDE is blank, then this macro will attempt to find suitable # flags. # # LUA_INCLUDE can be used by Automake to compile Lua modules or # executables with embedded interpreters. The *_CPPFLAGS variables should # be used for this purpose, e.g. myprog_CPPFLAGS = $(LUA_INCLUDE). # # This macro searches for the header lua.h (and others). The search is # performed with a combination of CPPFLAGS, CPATH, etc, and LUA_INCLUDE. # If the search is unsuccessful, then some common directories are tried. # If the headers are then found, then LUA_INCLUDE is set accordingly. # # The paths automatically searched are: # # * /usr/include/luaX.Y # * /usr/include/lua/X.Y # * /usr/include/luaXY # * /usr/local/include/luaX.Y # * /usr/local/include/lua-X.Y # * /usr/local/include/lua/X.Y # * /usr/local/include/luaXY # # (Where X.Y is the Lua version number, e.g. 5.1.) # # The Lua version number found in the headers is always checked to match # the Lua interpreter's version number. Lua headers with mismatched # version numbers are not accepted. # # If headers are found, then ACTION-IF-FOUND is performed, otherwise # ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then # it will default to printing an error. To prevent the default behavior, # set the action to ':'. # # AX_LUA_LIBS: Search for Lua libraries. Requires that AX_PROG_LUA be # expanded before this macro. Adds precious variable LUA_LIB, which may # contain Lua specific linker flags, e.g. -llua5.1. If LUA_LIB is blank, # then this macro will attempt to find suitable flags. # # LUA_LIB can be used by Automake to link Lua modules or executables with # embedded interpreters. The *_LIBADD and *_LDADD variables should be used # for this purpose, e.g. mymod_LIBADD = $(LUA_LIB). # # This macro searches for the Lua library. More technically, it searches # for a library containing the function lua_load. The search is performed # with a combination of LIBS, LIBRARY_PATH, and LUA_LIB. # # If the search determines that some linker flags are missing, then those # flags will be added to LUA_LIB. # # If libraries are found, then ACTION-IF-FOUND is performed, otherwise # ACTION-IF-NOT-FOUND is performed. If ACTION-IF-NOT-FOUND is blank, then # it will default to printing an error. To prevent the default behavior, # set the action to ':'. # # AX_LUA_READLINE: Search for readline headers and libraries. Requires the # AX_LIB_READLINE macro, which is provided by ax_lib_readline.m4 from the # Autoconf Archive. # # If a readline compatible library is found, then ACTION-IF-FOUND is # performed, otherwise ACTION-IF-NOT-FOUND is performed. # # LICENSE # # Copyright (c) 2015 Reuben Thomas # Copyright (c) 2014 Tim Perkins # # 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 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, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 40 dnl ========================================================================= dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION], dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_PROG_LUA], [ dnl Check for required tools. AC_REQUIRE([AC_PROG_GREP]) AC_REQUIRE([AC_PROG_SED]) dnl Make LUA a precious variable. AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1]) dnl Find a Lua interpreter. m4_define_default([_AX_LUA_INTERPRETER_LIST], [lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50]) m4_if([$1], [], [ dnl No version check is needed. Find any Lua interpreter. AS_IF([test "x$LUA" = 'x'], [AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])]) ax_display_LUA='lua' AS_IF([test "x$LUA" != 'x:'], [ dnl At least check if this is a Lua interpreter. AC_MSG_CHECKING([if $LUA is a Lua interpreter]) _AX_LUA_CHK_IS_INTRP([$LUA], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([not a Lua interpreter]) ]) ]) ], [ dnl A version check is needed. AS_IF([test "x$LUA" != 'x'], [ dnl Check if this is a Lua interpreter. AC_MSG_CHECKING([if $LUA is a Lua interpreter]) _AX_LUA_CHK_IS_INTRP([$LUA], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([not a Lua interpreter]) ]) dnl Check the version. m4_if([$2], [], [_ax_check_text="whether $LUA version >= $1"], [_ax_check_text="whether $LUA version >= $1, < $2"]) AC_MSG_CHECKING([$_ax_check_text]) _AX_LUA_CHK_VER([$LUA], [$1], [$2], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([version is out of range for specified LUA])]) ax_display_LUA=$LUA ], [ dnl Try each interpreter until we find one that satisfies VERSION. m4_if([$2], [], [_ax_check_text="for a Lua interpreter with version >= $1"], [_ax_check_text="for a Lua interpreter with version >= $1, < $2"]) AC_CACHE_CHECK([$_ax_check_text], [ax_cv_pathless_LUA], [ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do test "x$ax_cv_pathless_LUA" = 'xnone' && break _AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue]) _AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break]) done ]) dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA. AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'], [LUA=':'], [AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])]) ax_display_LUA=$ax_cv_pathless_LUA ]) ]) AS_IF([test "x$LUA" = 'x:'], [ dnl Run any user-specified action, or abort. m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])]) ], [ dnl Query Lua for its version number. AC_CACHE_CHECK([for $ax_display_LUA version], [ax_cv_lua_version], [ dnl Get the interpreter version in X.Y format. This should work for dnl interpreters version 5.0 and beyond. ax_cv_lua_version=[`$LUA -e ' -- return a version number in X.Y format local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)") print(ver)'`] ]) AS_IF([test "x$ax_cv_lua_version" = 'x'], [AC_MSG_ERROR([invalid Lua version number])]) AC_SUBST([LUA_VERSION], [$ax_cv_lua_version]) AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`]) dnl The following check is not supported: dnl At times (like when building shared libraries) you may want to know dnl which OS platform Lua thinks this is. AC_CACHE_CHECK([for $ax_display_LUA platform], [ax_cv_lua_platform], [ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]]) AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct dnl variables so they can be overridden if need be. However, the general dnl consensus is that you shouldn't need this ability. AC_SUBST([LUA_PREFIX], ['${prefix}']) AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}']) dnl Lua provides no way to query the script directory, and instead dnl provides LUA_PATH. However, we should be able to make a safe educated dnl guess. If the built-in search path contains a directory which is dnl prefixed by $prefix, then we can store scripts there. The first dnl matching path will be used. AC_CACHE_CHECK([for $ax_display_LUA script directory], [ax_cv_lua_luadir], [ AS_IF([test "x$prefix" = 'xNONE'], [ax_lua_prefix=$ac_default_prefix], [ax_lua_prefix=$prefix]) dnl Initialize to the default path. ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION" dnl Try to find a path with the prefix. _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script]) AS_IF([test "x$ax_lua_prefixed_path" != 'x'], [ dnl Fix the prefix. _ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'` ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \ $SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"` ]) ]) AC_SUBST([luadir], [$ax_cv_lua_luadir]) AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE]) dnl Lua provides no way to query the module directory, and instead dnl provides LUA_PATH. However, we should be able to make a safe educated dnl guess. If the built-in search path contains a directory which is dnl prefixed by $exec_prefix, then we can store modules there. The first dnl matching path will be used. AC_CACHE_CHECK([for $ax_display_LUA module directory], [ax_cv_lua_luaexecdir], [ AS_IF([test "x$exec_prefix" = 'xNONE'], [ax_lua_exec_prefix=$ax_lua_prefix], [ax_lua_exec_prefix=$exec_prefix]) dnl Initialize to the default path. ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION" dnl Try to find a path with the prefix. _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_exec_prefix], [module]) AS_IF([test "x$ax_lua_prefixed_path" != 'x'], [ dnl Fix the prefix. _ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'` ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \ $SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"` ]) ]) AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir]) AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE]) dnl Run any user specified action. $3 ]) ]) dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA. AC_DEFUN([AX_WITH_LUA], [ AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]]) AX_PROG_LUA ]) dnl ========================================================================= dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl ========================================================================= AC_DEFUN([_AX_LUA_CHK_IS_INTRP], [ dnl A minimal Lua factorial to prove this is an interpreter. This should work dnl for Lua interpreters version 5.0 and beyond. _ax_lua_factorial=[`$1 2>/dev/null -e ' -- a simple factorial function fact (n) if n == 0 then return 1 else return n * fact(n-1) end end print("fact(5) is " .. fact(5))'`] AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'], [$2], [$3]) ]) dnl ========================================================================= dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION], dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE]) dnl ========================================================================= AC_DEFUN([_AX_LUA_CHK_VER], [ dnl Check that the Lua version is within the bounds. Only the major and minor dnl version numbers are considered. This should work for Lua interpreters dnl version 5.0 and beyond. _ax_lua_good_version=[`$1 -e ' -- a script to compare versions function verstr2num(verstr) local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)") if majorver and minorver then return tonumber(majorver) * 100 + tonumber(minorver) end end local minver = verstr2num("$2") local _, _, trimver = string.find(_VERSION, "^Lua (.*)") local ver = verstr2num(trimver) local maxver = verstr2num("$3") or 1e9 if minver <= ver and ver < maxver then print("yes") else print("no") end'`] AS_IF([test "x$_ax_lua_good_version" = "xyes"], [$4], [$5]) ]) dnl ========================================================================= dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR) dnl ========================================================================= AC_DEFUN([_AX_LUA_FND_PRFX_PTH], [ dnl Get the script or module directory by querying the Lua interpreter, dnl filtering on the given prefix, and selecting the shallowest path. If no dnl path is found matching the prefix, the result will be an empty string. dnl The third argument determines the type of search, it can be 'script' or dnl 'module'. Supplying 'script' will perform the search with package.path dnl and LUA_PATH, and supplying 'module' will search with package.cpath and dnl LUA_CPATH. This is done for compatibility with Lua 5.0. ax_lua_prefixed_path=[`$1 -e ' -- get the path based on search type local searchtype = "$3" local paths = "" if searchtype == "script" then paths = (package and package.path) or LUA_PATH elseif searchtype == "module" then paths = (package and package.cpath) or LUA_CPATH end -- search for the prefix local prefix = "'$2'" local minpath = "" local mindepth = 1e9 string.gsub(paths, "(@<:@^;@:>@+)", function (path) path = string.gsub(path, "%?.*$", "") path = string.gsub(path, "/@<:@^/@:>@*$", "") if string.find(path, prefix) then local depth = string.len(string.gsub(path, "@<:@^/@:>@", "")) if depth < mindepth then minpath = path mindepth = depth end end end) print(minpath)'`] ]) dnl ========================================================================= dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_LUA_HEADERS], [ dnl Check for LUA_VERSION. AC_MSG_CHECKING([if LUA_VERSION is defined]) AS_IF([test "x$LUA_VERSION" != 'x'], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION]) ]) dnl Make LUA_INCLUDE a precious variable. AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1]) dnl Some default directories to search. LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'` m4_define_default([_AX_LUA_INCLUDE_LIST], [ /usr/include/lua$LUA_VERSION \ /usr/include/lua-$LUA_VERSION \ /usr/include/lua/$LUA_VERSION \ /usr/include/lua$LUA_SHORT_VERSION \ /usr/local/include/lua$LUA_VERSION \ /usr/local/include/lua-$LUA_VERSION \ /usr/local/include/lua/$LUA_VERSION \ /usr/local/include/lua$LUA_SHORT_VERSION \ ]) dnl Try to find the headers. _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) CPPFLAGS=$_ax_lua_saved_cppflags dnl Try some other directories if LUA_INCLUDE was not set. AS_IF([test "x$LUA_INCLUDE" = 'x' && test "x$ac_cv_header_lua_h" != 'xyes'], [ dnl Try some common include paths. for _ax_include_path in _AX_LUA_INCLUDE_LIST; do test ! -d "$_ax_include_path" && continue AC_MSG_CHECKING([for Lua headers in]) AC_MSG_RESULT([$_ax_include_path]) AS_UNSET([ac_cv_header_lua_h]) AS_UNSET([ac_cv_header_lualib_h]) AS_UNSET([ac_cv_header_lauxlib_h]) AS_UNSET([ac_cv_header_luaconf_h]) _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS -I$_ax_include_path" AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h]) CPPFLAGS=$_ax_lua_saved_cppflags AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], [ LUA_INCLUDE="-I$_ax_include_path" break ]) done ]) AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'], [ dnl Make a program to print LUA_VERSION defined in the header. dnl TODO It would be really nice if we could do this without compiling a dnl program, then it would work when cross compiling. But I'm not sure how dnl to do this reliably. For now, assume versions match when cross compiling. AS_IF([test "x$cross_compiling" != 'xyes'], [ AC_CACHE_CHECK([for Lua header version], [ax_cv_lua_header_version], [ _ax_lua_saved_cppflags=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LUA_INCLUDE" AC_RUN_IFELSE( [ AC_LANG_SOURCE([[ #include #include #include int main(int argc, char ** argv) { if(argc > 1) printf("%s", LUA_VERSION); exit(EXIT_SUCCESS); } ]]) ], [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \ $SED -n "s|^Lua \(@<:@0-9@:>@\{1,\}\.@<:@0-9@:>@\{1,\}\).\{0,\}|\1|p"` ], [ax_cv_lua_header_version='unknown']) CPPFLAGS=$_ax_lua_saved_cppflags ]) dnl Compare this to the previously found LUA_VERSION. AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION]) AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"], [ AC_MSG_RESULT([yes]) ax_header_version_match='yes' ], [ AC_MSG_RESULT([no]) ax_header_version_match='no' ]) ], [ AC_MSG_WARN([cross compiling so assuming header version number matches]) ax_header_version_match='yes' ]) ]) dnl Was LUA_INCLUDE specified? AS_IF([test "x$ax_header_version_match" != 'xyes' && test "x$LUA_INCLUDE" != 'x'], [AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])]) dnl Test the final result and run user code. AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1], [m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])]) ]) dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS. AC_DEFUN([AX_LUA_HEADERS_VERSION], [ AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]]) ]) dnl ========================================================================= dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_LUA_LIBS], [ dnl TODO Should this macro also check various -L flags? dnl Check for LUA_VERSION. AC_MSG_CHECKING([if LUA_VERSION is defined]) AS_IF([test "x$LUA_VERSION" != 'x'], [AC_MSG_RESULT([yes])], [ AC_MSG_RESULT([no]) AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION]) ]) dnl Make LUA_LIB a precious variable. AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1]) AS_IF([test "x$LUA_LIB" != 'x'], [ dnl Check that LUA_LIBS works. _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" AC_SEARCH_LIBS([lua_load], [], [_ax_found_lua_libs='yes'], [_ax_found_lua_libs='no']) LIBS=$_ax_lua_saved_libs dnl Check the result. AS_IF([test "x$_ax_found_lua_libs" != 'xyes'], [AC_MSG_ERROR([cannot find libs for specified LUA_LIB])]) ], [ dnl First search for extra libs. _ax_lua_extra_libs='' _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" AC_SEARCH_LIBS([exp], [m]) AC_SEARCH_LIBS([dlopen], [dl]) LIBS=$_ax_lua_saved_libs AS_IF([test "x$ac_cv_search_exp" != 'xno' && test "x$ac_cv_search_exp" != 'xnone required'], [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"]) AS_IF([test "x$ac_cv_search_dlopen" != 'xno' && test "x$ac_cv_search_dlopen" != 'xnone required'], [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"]) dnl Try to find the Lua libs. _ax_lua_saved_libs=$LIBS LIBS="$LIBS $LUA_LIB" AC_SEARCH_LIBS([lua_load], [ lua$LUA_VERSION \ lua$LUA_SHORT_VERSION \ lua-$LUA_VERSION \ lua-$LUA_SHORT_VERSION \ lua \ ], [_ax_found_lua_libs='yes'], [_ax_found_lua_libs='no'], [$_ax_lua_extra_libs]) LIBS=$_ax_lua_saved_libs AS_IF([test "x$ac_cv_search_lua_load" != 'xno' && test "x$ac_cv_search_lua_load" != 'xnone required'], [LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"]) ]) dnl Test the result and run user code. AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1], [m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])]) ]) dnl ========================================================================= dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ========================================================================= AC_DEFUN([AX_LUA_READLINE], [ AX_LIB_READLINE AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' && test "x$ac_cv_header_readline_history_h" != 'x'], [ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS" $1 ], [$2]) ]) thrift-0.19.0/aclocal/ax_check_openssl.m40000644000000000000000000001013514303740367020256 0ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_check_openssl.html # =========================================================================== # # SYNOPSIS # # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) # # DESCRIPTION # # Look for OpenSSL in a number of default spots, or in a user-selected # spot (via --with-openssl). Sets # # OPENSSL_INCLUDES to the include directives required # OPENSSL_LIBS to the -l directives required # OPENSSL_LDFLAGS to the -L or -R flags required # # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately # # This macro sets OPENSSL_INCLUDES such that source files should use the # openssl/ directory in include directives: # # #include # # LICENSE # # Copyright (c) 2009,2010 Zmanda Inc. # Copyright (c) 2009,2010 Dustin J. Mitchell # # 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 10 AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) AC_DEFUN([AX_CHECK_OPENSSL], [ found=false AC_ARG_WITH([openssl], [AS_HELP_STRING([--with-openssl=DIR], [root of the OpenSSL directory])], [ case "$withval" in "" | y | ye | yes | n | no) AC_MSG_ERROR([Invalid --with-openssl value]) ;; *) ssldirs="$withval" ;; esac ], [ # if pkg-config is installed and openssl has installed a .pc file, # then use that information and don't search ssldirs AC_CHECK_TOOL([PKG_CONFIG], [pkg-config]) if test x"$PKG_CONFIG" != x""; then OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` if test $? = 0; then OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` found=true fi fi # no such luck; use some default ssldirs if ! $found; then ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" fi ] ) # note that we #include , so the OpenSSL headers have to be in # an 'openssl' subdirectory if ! $found; then OPENSSL_INCLUDES= for ssldir in $ssldirs; do AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) if test -f "$ssldir/include/openssl/ssl.h"; then OPENSSL_INCLUDES="-I$ssldir/include" OPENSSL_LDFLAGS="-L$ssldir/lib" OPENSSL_LIBS="-lssl -lcrypto" found=true AC_MSG_RESULT([yes]) break else AC_MSG_RESULT([no]) fi done # if the file wasn't found, well, go ahead and try the link anyway -- maybe # it will just work! fi # try the preprocessor and linker with our new flags, # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD save_LIBS="$LIBS" save_LDFLAGS="$LDFLAGS" save_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" LIBS="$OPENSSL_LIBS $LIBS" CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], [ AC_MSG_RESULT([yes]) $1 ], [ AC_MSG_RESULT([no]) $2 ]) CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" AC_SUBST([OPENSSL_INCLUDES]) AC_SUBST([OPENSSL_LIBS]) AC_SUBST([OPENSSL_LDFLAGS]) ]) thrift-0.19.0/aclocal/tar.m40000644000000000000000000001070314303740367015535 0ustar00rootroot00000000000000# Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2018 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 --hard-dereference --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --hard-dereference --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 --hard-dereference - "$$tardir"' am__tar_='tar chf --hard-dereference - "$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 thrift-0.19.0/aclocal/ax_signed_right_shift.m40000644000000000000000000001264714303740367021313 0ustar00rootroot00000000000000dnl @synopsis AX_SIGNED_RIGHT_SHIFT dnl dnl Tests the behavior of a right shift on a negative signed int. dnl dnl This macro calls: dnl AC_DEFINE(SIGNED_RIGHT_SHIFT_IS) dnl AC_DEFINE(ARITHMETIC_RIGHT_SHIFT) dnl AC_DEFINE(LOGICAL_RIGHT_SHIFT) dnl AC_DEFINE(UNKNOWN_RIGHT_SHIFT) dnl dnl SIGNED_RIGHT_SHIFT_IS will be equal to one of the other macros. dnl It also leaves the shell variables "ax_signed_right_shift" dnl set to "arithmetic", "logical", or "unknown". dnl dnl NOTE: This macro does not work for cross-compiling. dnl dnl @category C dnl @version 2009-03-25 dnl @license AllPermissive dnl dnl Copyright (C) 2009 David Reiss dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. AC_DEFUN([AX_SIGNED_RIGHT_SHIFT], [ AC_MSG_CHECKING(the behavior of a signed right shift) success_arithmetic=no AC_RUN_IFELSE([AC_LANG_PROGRAM([[]], [[ return /* 0xffffffff */ -1 >> 1 != -1 || -1 >> 2 != -1 || -1 >> 3 != -1 || -1 >> 4 != -1 || -1 >> 8 != -1 || -1 >> 16 != -1 || -1 >> 24 != -1 || -1 >> 31 != -1 || /* 0x80000000 */ (-2147483647 - 1) >> 1 != -1073741824 || (-2147483647 - 1) >> 2 != -536870912 || (-2147483647 - 1) >> 3 != -268435456 || (-2147483647 - 1) >> 4 != -134217728 || (-2147483647 - 1) >> 8 != -8388608 || (-2147483647 - 1) >> 16 != -32768 || (-2147483647 - 1) >> 24 != -128 || (-2147483647 - 1) >> 31 != -1 || /* 0x90800000 */ -1870659584 >> 1 != -935329792 || -1870659584 >> 2 != -467664896 || -1870659584 >> 3 != -233832448 || -1870659584 >> 4 != -116916224 || -1870659584 >> 8 != -7307264 || -1870659584 >> 16 != -28544 || -1870659584 >> 24 != -112 || -1870659584 >> 31 != -1 || 0; ]])], [ success_arithmetic=yes ]) success_logical=no AC_RUN_IFELSE([AC_LANG_PROGRAM([[]], [[ return /* 0xffffffff */ -1 >> 1 != (signed)((unsigned)-1 >> 1) || -1 >> 2 != (signed)((unsigned)-1 >> 2) || -1 >> 3 != (signed)((unsigned)-1 >> 3) || -1 >> 4 != (signed)((unsigned)-1 >> 4) || -1 >> 8 != (signed)((unsigned)-1 >> 8) || -1 >> 16 != (signed)((unsigned)-1 >> 16) || -1 >> 24 != (signed)((unsigned)-1 >> 24) || -1 >> 31 != (signed)((unsigned)-1 >> 31) || /* 0x80000000 */ (-2147483647 - 1) >> 1 != (signed)((unsigned)(-2147483647 - 1) >> 1) || (-2147483647 - 1) >> 2 != (signed)((unsigned)(-2147483647 - 1) >> 2) || (-2147483647 - 1) >> 3 != (signed)((unsigned)(-2147483647 - 1) >> 3) || (-2147483647 - 1) >> 4 != (signed)((unsigned)(-2147483647 - 1) >> 4) || (-2147483647 - 1) >> 8 != (signed)((unsigned)(-2147483647 - 1) >> 8) || (-2147483647 - 1) >> 16 != (signed)((unsigned)(-2147483647 - 1) >> 16) || (-2147483647 - 1) >> 24 != (signed)((unsigned)(-2147483647 - 1) >> 24) || (-2147483647 - 1) >> 31 != (signed)((unsigned)(-2147483647 - 1) >> 31) || /* 0x90800000 */ -1870659584 >> 1 != (signed)((unsigned)-1870659584 >> 1) || -1870659584 >> 2 != (signed)((unsigned)-1870659584 >> 2) || -1870659584 >> 3 != (signed)((unsigned)-1870659584 >> 3) || -1870659584 >> 4 != (signed)((unsigned)-1870659584 >> 4) || -1870659584 >> 8 != (signed)((unsigned)-1870659584 >> 8) || -1870659584 >> 16 != (signed)((unsigned)-1870659584 >> 16) || -1870659584 >> 24 != (signed)((unsigned)-1870659584 >> 24) || -1870659584 >> 31 != (signed)((unsigned)-1870659584 >> 31) || 0; ]])], [ success_logical=yes ]) AC_DEFINE([ARITHMETIC_RIGHT_SHIFT], 1, [Possible value for SIGNED_RIGHT_SHIFT_IS]) AC_DEFINE([LOGICAL_RIGHT_SHIFT], 2, [Possible value for SIGNED_RIGHT_SHIFT_IS]) AC_DEFINE([UNKNOWN_RIGHT_SHIFT], 3, [Possible value for SIGNED_RIGHT_SHIFT_IS]) if test "$success_arithmetic" = "yes" && test "$success_logical" = "yes" ; then AC_MSG_ERROR("Right shift appears to be both arithmetic and logical!") elif test "$success_arithmetic" = "yes" ; then ax_signed_right_shift=arithmetic AC_DEFINE([SIGNED_RIGHT_SHIFT_IS], 1, [Indicates the effect of the right shift operator on negative signed integers]) elif test "$success_logical" = "yes" ; then ax_signed_right_shift=logical AC_DEFINE([SIGNED_RIGHT_SHIFT_IS], 2, [Indicates the effect of the right shift operator on negative signed integers]) else ax_signed_right_shift=unknown AC_DEFINE([SIGNED_RIGHT_SHIFT_IS], 3, [Indicates the effect of the right shift operator on negative signed integers]) fi AC_MSG_RESULT($ax_signed_right_shift) ]) thrift-0.19.0/aclocal/ax_prog_dotnetcore_version.m40000644000000000000000000000361514303740367022405 0ustar00rootroot00000000000000# =============================================================================== # https://www.gnu.org/software/autoconf-archive/ax_prog_dotnetcore_version.html # =============================================================================== # # SYNOPSIS # # AX_PROG_DOTNETCORE_VERSION([VERSION],[ACTION-IF-TRUE],[ACTION-IF-FALSE]) # # DESCRIPTION # # Makes sure that .NET Core supports the version indicated. If true the # shell commands in ACTION-IF-TRUE are executed. If not the shell commands # in ACTION-IF-FALSE are run. The $dotnetcore_version variable will be # filled with the detected version. # # This macro uses the $DOTNETCORE variable to perform the check. If # $DOTNETCORE is not set prior to calling this macro, the macro will fail. # # Example: # # AC_PATH_PROG([DOTNETCORE],[dotnet]) # AC_PROG_DOTNETCORE_VERSION([1.0.2],[ ... ],[ ... ]) # # Searches for .NET Core, then checks if at least version 1.0.2 is # present. # # LICENSE # # Copyright (c) 2016 Jens Geyer # # 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 2 AC_DEFUN([AX_PROG_DOTNETCORE_VERSION],[ AC_REQUIRE([AC_PROG_SED]) AS_IF([test -n "$DOTNETCORE"],[ ax_dotnetcore_version="$1" AC_MSG_CHECKING([for .NET Core version]) dotnetcore_version=`$DOTNETCORE --version 2>&1 | $SED -e 's/\(@<:@0-9@:>@*\.@<:@0-9@:>@*\.@<:@0-9@:>@*\)\(.*\)/\1/'` AC_MSG_RESULT($dotnetcore_version) AC_SUBST([DOTNETCORE_VERSION],[$dotnetcore_version]) AX_COMPARE_VERSION([$ax_dotnetcore_version],[le],[$dotnetcore_version],[ : $2 ],[ : $3 ]) ],[ AC_MSG_WARN([could not find .NET Core]) $3 ]) ]) thrift-0.19.0/aclocal/ax_lib_zlib.m40000644000000000000000000001337714303740367017237 0ustar00rootroot00000000000000dnl @synopsis AX_LIB_ZLIB([MINIMUM-VERSION]) dnl dnl Test for the libz library of a particular version (or newer). dnl dnl If no path to the installed zlib is given, the macro will first try dnl using no -I or -L flags, then searches under /usr, /usr/local, /opt, dnl and /opt/zlib. dnl If these all fail, it will try the $ZLIB_ROOT environment variable. dnl dnl This macro calls: dnl AC_SUBST(ZLIB_CPPFLAGS) dnl AC_SUBST(ZLIB_LDFLAGS) dnl AC_SUBST(ZLIB_LIBS) dnl dnl And (if zlib is found): dnl AC_DEFINE(HAVE_ZLIB) dnl dnl It also leaves the shell variables "success" and "ax_have_zlib" dnl set to "yes" or "no". dnl dnl NOTE: This macro does not currently work for cross-compiling, dnl but it can be easily modified to allow it. (grep "cross"). dnl dnl @category InstalledPackages dnl @category C dnl @version 2007-09-12 dnl @license AllPermissive dnl dnl Copyright (C) 2009 David Reiss dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. dnl Input: ax_zlib_path, WANT_ZLIB_VERSION dnl Output: success=yes/no AC_DEFUN([AX_LIB_ZLIB_DO_CHECK], [ # Save our flags. CPPFLAGS_SAVED="$CPPFLAGS" LDFLAGS_SAVED="$LDFLAGS" LIBS_SAVED="$LIBS" LD_LIBRARY_PATH_SAVED="$LD_LIBRARY_PATH" # Set our flags if we are checking a specific directory. if test -n "$ax_zlib_path" ; then ZLIB_CPPFLAGS="-I$ax_zlib_path/include" ZLIB_LDFLAGS="-L$ax_zlib_path/lib" LD_LIBRARY_PATH="$ax_zlib_path/lib:$LD_LIBRARY_PATH" else ZLIB_CPPFLAGS="" ZLIB_LDFLAGS="" fi # Required flag for zlib. ZLIB_LIBS="-lz" # Prepare the environment for compilation. CPPFLAGS="$CPPFLAGS $ZLIB_CPPFLAGS" LDFLAGS="$LDFLAGS $ZLIB_LDFLAGS" LIBS="$LIBS $ZLIB_LIBS" export CPPFLAGS export LDFLAGS export LIBS export LD_LIBRARY_PATH success=no # Compile, link, and run the program. This checks: # - zlib.h is available for including. # - zlibVersion() is available for linking. # - ZLIB_VERNUM is greater than or equal to the desired version. # - ZLIB_VERSION (defined in zlib.h) matches zlibVersion() # (defined in the library). AC_LANG_PUSH([C]) dnl This can be changed to AC_LINK_IFELSE if you are cross-compiling. AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #if ZLIB_VERNUM >= 0x$WANT_ZLIB_VERSION #else # error zlib is too old #endif ]], [[ const char* lib_version = zlibVersion(); const char* hdr_version = ZLIB_VERSION; for (;;) { if (*lib_version != *hdr_version) { /* If this happens, your zlib header doesn't match your zlib */ /* library. That is really bad. */ return 1; } if (*lib_version == '\0') { break; } lib_version++; hdr_version++; } return 0; ]])], [ success=yes ]) AC_LANG_POP([C]) # Restore flags. CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" LIBS="$LIBS_SAVED" LD_LIBRARY_PATH="$LD_LIBRARY_PATH_SAVED" ]) AC_DEFUN([AX_LIB_ZLIB], [ dnl Allow search path to be overridden on the command line. AC_ARG_WITH([zlib], AS_HELP_STRING([--with-zlib@<:@=DIR@:>@], [use zlib (default is yes) - it is possible to specify an alternate root directory for zlib]), [ if test "x$withval" = "xno"; then want_zlib="no" elif test "x$withval" = "xyes"; then want_zlib="yes" ax_zlib_path="" else want_zlib="yes" ax_zlib_path="$withval" fi ], [want_zlib="yes" ; ax_zlib_path="" ]) if test "$want_zlib" = "yes"; then # Parse out the version. zlib_version_req=ifelse([$1], ,1.2.3,$1) zlib_version_req_major=`expr $zlib_version_req : '\([[0-9]]*\)'` zlib_version_req_minor=`expr $zlib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` zlib_version_req_patch=`expr $zlib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` if test -z "$zlib_version_req_patch" ; then zlib_version_req_patch="0" fi WANT_ZLIB_VERSION=`expr $zlib_version_req_major \* 1000 \+ $zlib_version_req_minor \* 100 \+ $zlib_version_req_patch \* 10` AC_MSG_CHECKING(for zlib >= $zlib_version_req) # Run tests. if test -n "$ax_zlib_path"; then AX_LIB_ZLIB_DO_CHECK else for ax_zlib_path in "" /usr /usr/local /opt /opt/zlib "$ZLIB_ROOT" ; do AX_LIB_ZLIB_DO_CHECK if test "$success" = "yes"; then break; fi done fi if test "$success" != "yes" ; then AC_MSG_RESULT(no) ZLIB_CPPFLAGS="" ZLIB_LDFLAGS="" ZLIB_LIBS="" else AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ZLIB,,[define if zlib is available]) fi ax_have_zlib="$success" AC_SUBST(ZLIB_CPPFLAGS) AC_SUBST(ZLIB_LDFLAGS) AC_SUBST(ZLIB_LIBS) fi ]) thrift-0.19.0/aclocal/ltversion.m40000777017777601777760000000127314114740176020126 0ustar00nobodynogroup00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # 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. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) thrift-0.19.0/aclocal/ltoptions.m40000777017777601777760000003426214114740175020137 0ustar00nobodynogroup00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # 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. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [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], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [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], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [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], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) 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 _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [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], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) thrift-0.19.0/aclocal/ax_cxx_compile_stdcxx_11.m40000644000000000000000000000321514303740367021647 0ustar00rootroot00000000000000# ============================================================================= # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html # ============================================================================= # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++11 # standard; if necessary, add switches to CXX and CXXCPP to enable # support. # # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX # macro with the version set to C++11. The two optional arguments are # forwarded literally as the second and third argument respectively. # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for # more information. If you want to use this macro, you also need to # download the ax_cxx_compile_stdcxx.m4 file. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # # 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 18 AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])]) thrift-0.19.0/aclocal/ac_prog_bison.m40000644000000000000000000000331314303740367017552 0ustar00rootroot00000000000000dnl dnl Check Bison version dnl AC_PROG_BISON([MIN_VERSION=2.4]) dnl dnl Will define BISON_USE_PARSER_H_EXTENSION if Automake is < 1.11 dnl for use with .h includes. dnl AC_DEFUN([AC_PROG_BISON], [ if test "x$1" = "x" ; then bison_required_version="2.4" else bison_required_version="$1" fi AC_CHECK_PROG(have_prog_bison, [bison], [yes],[no]) AC_DEFINE_UNQUOTED([BISON_VERSION], [0.0], [Bison version if bison is not available]) #Do not use *.h extension for parser header files, use newer *.hh bison_use_parser_h_extension=false if test "$have_prog_bison" = "yes" ; then AC_MSG_CHECKING([for bison version >= $bison_required_version]) bison_version=`bison --version | head -n 1 | cut '-d ' -f 4` AC_DEFINE_UNQUOTED([BISON_VERSION], [$bison_version], [Defines bison version]) if test "$bison_version" \< "$bison_required_version" ; then BISON=: AC_MSG_RESULT([no]) AC_MSG_ERROR([Bison version $bison_required_version or higher must be installed on the system!]) else AC_MSG_RESULT([yes]) BISON=bison AC_SUBST(BISON) #Verify automake version 1.11 headers for yy files are .h, > 1.12 uses .hh automake_version=`automake --version | head -n 1 | cut '-d ' -f 4` AC_DEFINE_UNQUOTED([AUTOMAKE_VERSION], [$automake_version], [Defines automake version]) if test "$automake_version" \< "1.12" ; then #Use *.h extension for parser header file bison_use_parser_h_extension=true echo "Automake version < 1.12" AC_DEFINE([BISON_USE_PARSER_H_EXTENSION], [1], [Use *.h extension for parser header file]) fi fi else BISON=: AC_MSG_RESULT([NO]) fi AM_CONDITIONAL([BISON_USE_PARSER_H_EXTENSION], [test x$bison_use_parser_h_extension = xtrue]) AC_SUBST(BISON) ]) thrift-0.19.0/configure.ac0000644000000000000000000010125714454461475015411 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) AC_INIT([thrift], [0.19.0]) AC_CONFIG_AUX_DIR([.]) AM_INIT_AUTOMAKE([1.13 subdir-objects tar-ustar foreign]) PKG_PROG_PKG_CONFIG AC_ARG_VAR([PY_PREFIX], [Prefix for installing Python modules. (Normal --prefix is ignored for Python because Python has different conventions.) Default = "/usr"]) AS_IF([test "x$PY_PREFIX" = x], [PY_PREFIX="/usr"]) AC_ARG_VAR([JAVA_PREFIX], [Prefix for installing the Java lib jar. Default = "/usr/local/lib"]) AS_IF([test "x$JAVA_PREFIX" != x], [JAVA_PREFIX="$JAVA_PREFIX/usr/local/lib"], [test "x$PREFIX" != x], [JAVA_PREFIX="$PREFIX/usr/local/lib"], [JAVA_PREFIX="/usr/local/lib"]) AC_ARG_VAR([RUBY_PREFIX], [Prefix for installing Ruby modules. (Normal --prefix is ignored for Ruby because Ruby has different conventions.) Default = none, let ruby setup decide]) AC_ARG_VAR([PHP_PREFIX], [Prefix for installing PHP modules. (Normal --prefix is ignored for PHP because PHP has different conventions.) Default = "/usr/lib/php"]) AS_IF([test "x$PHP_PREFIX" = x], [PHP_PREFIX="/usr/lib/php"]) AC_ARG_VAR([PHP_CONFIG_PREFIX], [Prefix for installing PHP extension module .ini file. (Normal --prefix is ignored for PHP because PHP has different conventions.) Default = "/etc/php.d"]) AS_IF([test "x$PHP_CONFIG_PREFIX" = x], [PHP_CONFIG_PREFIX="/etc/php.d"]) AC_ARG_VAR([INSTALLDIRS], [When installing Perl modules, specifies which of the sets of installation directories to choose: perl, site or vendor. Default = "vendor"]) AS_IF([test "x$INSTALLDIRS" = x], [INSTALLDIRS="vendor"]) AC_ARG_VAR([PERL_PREFIX], [Prefix for installing Perl modules. (Normal --prefix is ignored for Perl because Perl has different conventions.) Ignored, when INSTALLDIRS set to site or vendor. Default = "/usr/local/lib"]) AS_IF([test "x$PERL_PREFIX" = x], [PERL_PREFIX="/usr/local"]) AC_ARG_VAR([D_IMPORT_PREFIX], [Prefix for installing D modules. [INCLUDEDIR/d2]]) AS_IF([test "x$D_IMPORT_PREFIX" = x], [D_IMPORT_PREFIX="${includedir}/d2"]) AC_ARG_VAR([DMD_LIBEVENT_FLAGS], [DMD flags for linking libevent (auto-detected if not set).]) AC_ARG_VAR([DMD_OPENSSL_FLAGS], [DMD flags for linking OpenSSL (auto-detected if not set).]) AC_ARG_VAR([THRIFT], [Path to the thrift tool (needed for cross-compilation).]) AS_IF([test "x$THRIFT" = x], [THRIFT=`pwd`/compiler/cpp/thrift]) AC_PROG_CC AC_PROG_CPP AC_PROG_CXX AC_PROG_INSTALL AC_PROG_LIBTOOL AC_PROG_MAKE_SET AC_PROG_BISON(2.5) AC_PROG_YACC AC_PROG_LEX AM_PROG_LEX AC_PROG_LN_S AC_PROG_MKDIR_P AC_PROG_AWK AC_PROG_RANLIB AC_LANG([C++]) AX_CXX_COMPILE_STDCXX_11([noext], [mandatory]) AM_EXTRA_RECURSIVE_TARGETS([style]) AC_SUBST(CPPSTYLE_CMD, 'find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \;') # ' # The above comment is to fix editor syntax highlighting AC_ARG_ENABLE([libs], AS_HELP_STRING([--enable-libs], [build the Apache Thrift libraries [default=yes]]), [], enable_libs=yes ) have_libs=yes if test "$enable_libs" = "no"; then have_libs="no" with_cpp="no" with_c_glib="no" with_cl="no" with_java="no" with_kotlin="no" with_python="no" with_py3="no" with_ruby="no" with_haxe="no" with_netstd="no" with_perl="no" with_php="no" with_php_extension="no" with_dart="no" with_erlang="no" with_go="no" with_d="no" with_nodejs="no" with_nodets="no" with_lua="no" with_rs="no" with_swift="no" fi AX_THRIFT_LIB(cpp, [C++], yes) have_cpp=no if test "$with_cpp" = "yes"; then AX_BOOST_BASE([1.56.0]) if test "x$succeeded" = "xyes" ; then AC_SUBST([BOOST_LIB_DIR], [$(echo "$BOOST_LDFLAGS" | sed -e 's/^\-L//')]) AC_SUBST([BOOST_CHRONO_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_chrono.a")]) AC_SUBST([BOOST_FILESYSTEM_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_filesystem.a")]) AC_SUBST([BOOST_SYSTEM_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_system.a")]) AC_SUBST([BOOST_TEST_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_unit_test_framework.a")]) AC_SUBST([BOOST_THREAD_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_thread.a")]) have_cpp="yes" fi AX_LIB_EVENT([2.0]) have_libevent=$success AX_LIB_ZLIB([1.2.3]) have_zlib=$success AX_THRIFT_LIB(qt5, [Qt5], yes) have_qt5=no qt_reduce_reloc="" if test "$with_qt5" = "yes"; then PKG_CHECK_MODULES([QT5], [Qt5Core >= 5.0, Qt5Network >= 5.0], [have_qt5=yes;qt_reduce_reloc=`$PKG_CONFIG --variable=qt_config Qt5Core | grep "reduce_relocations"`], [have_qt5=no]) fi if test "$have_qt5" = "yes"; then AC_PATH_PROGS([QT5_MOC], [moc-qt5 moc], "fail") if test "$QT5_MOC" = "fail"; then have_qt5=no fi fi fi AM_CONDITIONAL([WITH_CPP], [test "$have_cpp" = "yes"]) AM_CONDITIONAL([AMX_HAVE_LIBEVENT], [test "$have_libevent" = "yes"]) AM_CONDITIONAL([AMX_HAVE_ZLIB], [test "$have_zlib" = "yes"]) AM_CONDITIONAL([AMX_HAVE_QT5], [test "$have_qt5" = "yes"]) AM_CONDITIONAL([QT5_REDUCE_RELOCATIONS], [test "x$qt_reduce_reloc" != "x"]) AX_THRIFT_LIB(c_glib, [C (GLib)], yes) if test "$with_c_glib" = "yes"; then PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.0], have_glib2=yes, have_glib2=no) PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.0], have_gobject2=yes, have_gobject2=no) if test "$have_glib2" = "yes" -a "$have_gobject2" = "yes" ; then AC_PATH_PROG([GSETTINGS], [gsettings]) have_c_glib="yes" fi fi AM_CONDITIONAL(WITH_C_GLIB, [test "$have_glib2" = "yes" -a "$have_gobject2" = "yes"]) # echo "OpenSSL check" if test "$have_cpp" = "yes" -o "$have_c_glib" = "yes"; then # echo "Have cpp or c so we check for OpenSSL" AX_CHECK_OPENSSL() fi AX_THRIFT_LIB(java, [Java], yes) if test "$with_java" = "yes"; then AX_JAVAC_AND_JAVA AC_PATH_PROG([ANT], [ant]) AC_PATH_PROG([GRADLE], [gradle]) AX_CHECK_ANT_VERSION($ANT, 1.7) AC_SUBST(CLASSPATH) AC_SUBST(ANT_FLAGS) AC_SUBST(GRADLE_OPTS) if test "x$JAVA" != "x" && test "x$JAVAC" != "x" && test "x$ANT" != "x" && test "x$GRADLE" != "x" ; then have_java="yes" fi fi AM_CONDITIONAL([WITH_JAVA], [test "$have_java" = "yes"]) AX_THRIFT_LIB(kotlin, [Kotlin], yes) if test "$with_kotlin" = "yes"; then AX_JAVAC_AND_JAVA AC_PATH_PROG([GRADLE], [gradle]) AC_SUBST(CLASSPATH) AC_SUBST(GRADLE_OPTS) if test "x$JAVA" != "x" && test "x$JAVAC" != "x" && "x$GRADLE" != "x" ; then have_kotlin="yes" fi fi AM_CONDITIONAL([WITH_KOTLIN], [test "$have_kotlin" = "yes"]) AX_THRIFT_LIB(erlang, [Erlang], yes) if test "$with_erlang" = "yes"; then AC_ERLANG_PATH_ERL AC_ERLANG_PATH_ERLC AC_PATH_PROG([REBAR], [rebar3]) if test -n "$ERLC" ; then AC_ERLANG_SUBST_LIB_DIR # Install into the detected Erlang directory instead of $libdir/erlang/lib ERLANG_INSTALL_LIB_DIR="$ERLANG_LIB_DIR" AC_ERLANG_SUBST_INSTALL_LIB_SUBDIR(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) fi if test -n "$ERL" -a -n "$ERLC" && test "x$REBAR" != "x" ; then have_erlang="yes" fi fi AM_CONDITIONAL(WITH_ERLANG, [test "$have_erlang" = "yes"]) AX_THRIFT_LIB(nodejs, [Nodejs], yes) have_nodejs=no if test "$with_nodejs" = "yes"; then AC_PATH_PROGS([NODEJS], [nodejs node]) AC_PATH_PROG([NPM], [npm]) if test "x$NODEJS" != "x" -a "x$NPM" != "x"; then have_nodejs="yes" fi fi AM_CONDITIONAL(WITH_NODEJS, [test "$have_nodejs" = "yes"]) AM_CONDITIONAL(HAVE_NPM, [test "x$NPM" != "x"]) AX_THRIFT_LIB(nodets, [Nodets], yes) have_nodets=no if test "$with_nodets" = "yes"; then AC_PATH_PROGS([NODETS], [nodets node]) AC_PATH_PROG([NPM], [npm]) if test "x$NODETS" != "x" -a "x$NPM" != "x"; then have_nodets="yes" fi fi AM_CONDITIONAL(WITH_NODETS, [test "$have_nodets" = "yes"]) AM_CONDITIONAL(HAVE_NPM, [test "x$NPM" != "x"]) AX_THRIFT_LIB(lua, [Lua], yes) have_lua=no if test "$with_lua" = "yes"; then AX_PROG_LUA(5.2,, have_lua="yes", have_lua="no") if test "$have_lua" = "yes"; then AX_LUA_HEADERS(, have_lua="no") AX_LUA_LIBS(, have_lua="no") fi fi AM_CONDITIONAL(WITH_LUA, [test "$have_lua" = "yes"]) # Find python regardless of with_python value, because it's needed by make cross AM_PATH_PYTHON(2.6,, :) AX_THRIFT_LIB(python, [Python], yes) if test "$with_python" = "yes"; then if test -n "$PYTHON"; then have_python="yes" fi AC_PATH_PROG([TRIAL], [trial]) if test -n "$TRIAL"; then have_trial="yes" fi fi AM_CONDITIONAL(WITH_PYTHON, [test "$have_python" = "yes"]) AM_CONDITIONAL(WITH_TWISTED_TEST, [test "$have_trial" = "yes"]) # Find "python3" executable. # It's distro specific and far from ideal but needed to cross test py2-3 at once. # TODO: find "python2" if it's 3.x have_py3="no" AX_THRIFT_LIB(py3, [Py3], yes) if test "$with_py3" = "yes"; then # if $PYTHON is 2.x then search for python 3. otherwise, $PYTHON is already 3.x if $PYTHON --version 2>&1 | grep -q "Python 2"; then AC_PATH_PROGS([PYTHON3], [python3 python3.8 python38 python3.7 python37 python3.6 python36 python3.5 python35 python3.4 python34]) if test -n "$PYTHON3"; then have_py3="yes" fi elif $PYTHON --version 2>&1 | grep -q "Python 3"; then have_py3="yes" PYTHON3=$PYTHON fi fi AM_CONDITIONAL(WITH_PY3, [test "$have_py3" = "yes"]) AX_THRIFT_LIB(perl, [Perl], yes) if test "$with_perl" = "yes"; then AC_PATH_PROG([PERL], [perl]) if test -n "$PERL" ; then AC_PROG_PERL_MODULES([Bit::Vector], success="yes", success="no") have_perl_bit_vector="$success" AC_PROG_PERL_MODULES([Class::Accessor], success="yes", success="no") have_perl_class_accessor="$success" fi if test -n "$PERL" -a "$have_perl_bit_vector" = "yes" ; then if test -n "$PERL" -a "$have_perl_class_accessor" = "yes" ; then have_perl="yes" fi fi fi AM_CONDITIONAL(WITH_PERL, [test "$have_perl" = "yes"]) AX_THRIFT_LIB(php, [PHP], yes) if test "$with_php" = "yes"; then AC_PATH_PROG([PHP], [php]) if test -n "$PHP" ; then have_php="yes" fi fi AM_CONDITIONAL(WITH_PHP, [test "$have_php" = "yes"]) AX_THRIFT_LIB(php_extension, [PHP_EXTENSION], yes) if test "$with_php_extension" = "yes"; then if test -f "lib/php/src/ext/thrift_protocol/configure"; then AC_PATH_PROG([PHP_CONFIG], [php-config]) if test -n "$PHP_CONFIG" ; then AC_CONFIG_SUBDIRS([lib/php/src/ext/thrift_protocol]) have_php_extension="yes" fi fi fi AM_CONDITIONAL(WITH_PHP_EXTENSION, [test "$have_php_extension" = "yes"]) AX_THRIFT_LIB(dart, [DART], yes) if test "$with_dart" = "yes"; then AC_PATH_PROG([DART], [dart]) AC_PATH_PROG([DARTPUB], [pub]) if test "x$DART" != "x" -a "x$DARTPUB" != "x"; then have_dart="yes" fi fi AM_CONDITIONAL(WITH_DART, [test "$have_dart" = "yes"]) AX_THRIFT_LIB(ruby, [Ruby], yes) have_ruby=no if test "$with_ruby" = "yes"; then AC_PATH_PROG([RUBY], [ruby]) AC_PATH_PROG([BUNDLER], [bundle]) if test "x$RUBY" != "x" -a "x$BUNDLER" != "x"; then have_ruby="yes" fi fi AM_CONDITIONAL(WITH_RUBY, [test "$have_ruby" = "yes"]) AM_CONDITIONAL(HAVE_BUNDLER, [test "x$BUNDLER" != "x"]) AX_THRIFT_LIB(go, [Go], yes) if test "$with_go" = "yes"; then AC_PATH_PROG([GO], [go]) if [[ -x "$GO" ]] ; then AS_IF([test -n "$GO"],[ ax_go_version="1.4" ax_go17_version="1.7" ax_go118_version="1.18" AC_MSG_CHECKING([for Go version]) golang_version=`$GO version 2>&1 | $SED -e 's/\(go \)\(version \)\(go\)\(@<:@0-9@:>@.@<:@0-9@:>@.@<:@0-9@:>@\)\(@<:@\*@:>@*\).*/\4/'` AC_MSG_RESULT($golang_version) AC_SUBST([golang_version],[$golang_version]) AX_COMPARE_VERSION([$ax_go_version],[le],[$golang_version],[ : have_go="yes" ],[ : have_go="no" ]) AX_COMPARE_VERSION([$golang_version],[lt],[$ax_go17_version],[ : go_version_lt_17="yes" ],[ : go_version_lt_17="no" ]) AX_COMPARE_VERSION([$golang_version],[ge],[$ax_go118_version],[ : go_version_ge_118="yes" ],[ : go_version_ge_118="no" ]) ],[ AC_MSG_WARN([could not find Go ]) have_go="no" ]) fi fi AM_CONDITIONAL(WITH_GO, [test "$have_go" = "yes"]) AM_CONDITIONAL([GOVERSION_LT_17], [test "$go_version_lt_17" = "yes"]) AM_CONDITIONAL([GOVERSION_GE_118], [test "$go_version_ge_118" = "yes"]) AX_THRIFT_LIB(swift, [Swift], yes) have_swift="no" if test "$with_swift" = "yes"; then AC_PATH_PROG([SWIFT], [swift]) if test "x$SWIFT" != "x" -a "x$SWIFT" != "x"; then have_swift="yes" fi fi AM_CONDITIONAL([WITH_SWIFT], [test "$have_swift" = "yes"]) AX_THRIFT_LIB(rs, [Rust], yes) have_rs="no" if test "$with_rs" = "yes"; then AC_PATH_PROG([CARGO], [cargo]) AC_PATH_PROG([RUSTC], [rustc]) if [[ -x "$CARGO" ]] && [[ -x "$RUSTC" ]]; then min_rustc_version="1.13" AC_MSG_CHECKING([for rustc version]) rustc_version=`$RUSTC --version 2>&1 | $SED -e 's/\(rustc \)\([0-9]\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*/\2.\3/'` AC_MSG_RESULT($rustc_version) AC_SUBST([rustc_version],[$rustc_version]) AX_COMPARE_VERSION([$min_rustc_version],[le],[$rustc_version],[ : have_rs="yes" ],[ : have_rs="no" ]) fi fi AM_CONDITIONAL(WITH_RS, [test "$have_rs" = "yes"]) AX_THRIFT_LIB(cl, [Common Lisp], yes) have_cl="no" if test "$with_cl" = "yes"; then AC_PATH_PROG([SBCL], [sbcl]) if test "x$SBCL" != "x"; then have_cl="yes" fi fi AM_CONDITIONAL(WITH_CL, [test "$have_cl" = "yes"]) AX_THRIFT_LIB(haxe, [Haxe], yes) if test "$with_haxe" = "yes"; then AC_PATH_PROG([HAXE], [haxe]) if [[ -x "$HAXE" ]] ; then AX_PROG_HAXE_VERSION( [4.2.1], have_haxe="yes", have_haxe="no") fi fi AM_CONDITIONAL(WITH_HAXE, [test "$have_haxe" = "yes"]) AX_THRIFT_LIB(netstd, [.NET Core], yes) if test "$with_netstd" = "yes"; then AC_PATH_PROG([DOTNETCORE], [dotnet]) if [[ -x "$DOTNETCORE" ]] ; then AX_PROG_DOTNETCORE_VERSION( [7.0.0], have_netstd="yes", have_netstd="no") fi fi AM_CONDITIONAL(WITH_DOTNET, [test "$have_netstd" = "yes"]) AX_THRIFT_LIB(d, [D], yes) if test "$with_d" = "yes"; then AX_DMD AC_SUBST(DMD) if test "x$DMD" != "x"; then have_d="yes" fi fi # Determine actual name of the generated D library for use in the command line # when compiling tests. This is needed because the -l syntax doesn't work # with OPTLINK (Windows). lib_prefix=lib lib_suffix=a case "$host_os" in cygwin* | mingw* | pw32* | cegcc*) lib_prefix="" lib_suffix=lib ;; esac D_LIB_NAME="${lib_prefix}thriftd.${lib_suffix}" AC_SUBST(D_LIB_NAME) D_EVENT_LIB_NAME="${lib_prefix}thriftd-event.${lib_suffix}" AC_SUBST(D_EVENT_LIB_NAME) D_SSL_LIB_NAME="${lib_prefix}thriftd-ssl.${lib_suffix}" AC_SUBST(D_SSL_LIB_NAME) if test "$have_d" = "yes"; then AX_CHECK_D_MODULE(deimos.event2.event) have_deimos_event2=$success with_d_event_tests="no" if test "$have_deimos_event2" = "yes"; then if test "x$DMD_LIBEVENT_FLAGS" = "x"; then if test "$dmd_optlink" = "yes"; then AC_MSG_WARN([D libevent interface found, but cannot auto-detect \ linker flags for OPTLINK. Please set DMD_LIBEVENT_FLAGS manually.]) else AX_LIB_EVENT([2.0]) if test "$success" = "yes"; then DMD_LIBEVENT_FLAGS=$(echo "-fuse-ld=gold $LIBEVENT_LDFLAGS $LIBEVENT_LIBS" | \ sed -e 's/^ *//g;s/ *$//g;s/^\(.\)/-L\1/g;s/ */ -L/g') with_d_event_tests="yes" else AC_MSG_WARN([D libevent interface present, but libevent library not found.]) fi fi else with_d_event_tests="yes" fi fi AX_CHECK_D_MODULE(deimos.openssl.ssl) have_deimos_openssl=$success with_d_ssl_tests="no" if test "$have_deimos_openssl" = "yes"; then if test "x$DMD_OPENSSL_FLAGS" = "x"; then if test "$dmd_optlink" = "yes"; then AC_MSG_WARN([D OpenSSL interface found, but cannot auto-detect \ linker flags for OPTLINK. Please set DMD_OPENSSL_FLAGS manually.]) else AX_CHECK_OPENSSL([with_d_ssl_tests="yes"]) if test "$with_d_ssl_tests" = "yes"; then DMD_OPENSSL_FLAGS=$(echo "-fuse-ld=gold $OPENSSL_LDFLAGS $OPENSSL_LIBS" | \ sed -e 's/^ *//g;s/ *$//g;s/^\(.\)/-L\1/g;s/ */ -L/g') else AC_MSG_WARN([D OpenSSL interface present, but OpenSSL library not found.]) fi fi else with_d_ssl_tests="yes" fi fi fi AM_CONDITIONAL(WITH_D, [test "$have_d" = "yes"]) AM_CONDITIONAL(DMD_OPTLINK, [test "$dmd_optlink" = "yes"]) AC_SUBST(DMD_OF_DIRSEP, "$dmd_of_dirsep") AM_CONDITIONAL(HAVE_DEIMOS_EVENT2, [test "$have_deimos_event2" = "yes"]) AM_CONDITIONAL(WITH_D_EVENT_TESTS, [test "$with_d_event_tests" = "yes"]) AC_SUBST(DMD_LIBEVENT_FLAGS) AM_CONDITIONAL(HAVE_DEIMOS_OPENSSL, [test "$have_deimos_openssl" = "yes"]) AM_CONDITIONAL(WITH_D_SSL_TESTS, [test "$with_d_ssl_tests" = "yes"]) AC_SUBST(DMD_OPENSSL_FLAGS) AC_ARG_ENABLE([tests], AS_HELP_STRING([--enable-tests], [build tests [default=yes]]), [], enable_tests=yes ) have_tests=yes if test "$enable_tests" = "no"; then have_tests="no" fi AM_CONDITIONAL(WITH_TESTS, [test "$have_tests" = "yes"]) AC_ARG_ENABLE([tutorial], AS_HELP_STRING([--enable-tutorial], [build tutorial [default=yes]]), [], enable_tutorial=yes ) have_tutorial=yes if test "$enable_tutorial" = "no"; then have_tutorial="no" fi AM_CONDITIONAL(WITH_TUTORIAL, [test "$have_tutorial" = "yes"]) AM_CONDITIONAL(MINGW, false) case "${host_os}" in *mingw*) mingw32_support="yes" AC_CHECK_HEADER(windows.h) AM_CONDITIONAL(MINGW, true) ;; *) AC_ISC_POSIX ;; esac AC_C_CONST AC_C_INLINE AC_C_VOLATILE AC_HEADER_STDBOOL AC_HEADER_STDC AC_HEADER_TIME AC_HEADER_SYS_WAIT AC_TYPE_SIGNAL AC_CHECK_HEADERS([arpa/inet.h]) AC_CHECK_HEADERS([fcntl.h]) AC_CHECK_HEADERS([inttypes.h]) AC_CHECK_HEADERS([libintl.h]) AC_CHECK_HEADERS([limits.h]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) AC_CHECK_HEADERS([netinet/in.h]) AC_CHECK_HEADERS([openssl/rand.h]) AC_CHECK_HEADERS([openssl/ssl.h]) AC_CHECK_HEADERS([openssl/x509v3.h]) AC_CHECK_HEADERS([poll.h]) AC_CHECK_HEADERS([pthread.h]) AC_CHECK_HEADERS([sched.h]) AC_CHECK_HEADERS([signal.h]) AC_CHECK_HEADERS([stddef.h]) AC_CHECK_HEADERS([stdint.h]) AC_CHECK_HEADERS([stdlib.h]) AC_CHECK_HEADERS([strings.h]) AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([sys/poll.h]) AC_CHECK_HEADERS([sys/resource.h]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/un.h]) AC_CHECK_HEADERS([unistd.h]) AC_CHECK_HEADERS([wchar.h]) AC_CHECK_LIB(pthread, pthread_create) dnl NOTE(dreiss): I haven't been able to find any really solid docs dnl on what librt is and how it fits into various Unix systems. dnl My best guess is that it is where glibc stashes its implementation dnl of the POSIX Real-Time Extensions. This seems necessary on Linux, dnl and we haven't yet found a system where this is a problem. AC_CHECK_LIB(rt, clock_gettime) AC_CHECK_LIB(socket, setsockopt) AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_INT8_T AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T AC_TYPE_UINT8_T AC_CHECK_TYPES([ptrdiff_t], [], [echo "ptrdiff_t not found or g++ not installed - cannot continue" && exit 1]) AC_STRUCT_TM dnl NOTE(dreiss): AI_ADDRCONFIG is not defined on OpenBSD. AC_CHECK_DECL([AI_ADDRCONFIG], [], [AC_DEFINE([AI_ADDRCONFIG], 0, [Define if the AI_ADDRCONFIG symbol is unavailable])], [ #include #include #include ]) AC_FUNC_ALLOCA AC_FUNC_FORK AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_FUNC_REALLOC AC_FUNC_SELECT_ARGTYPES AC_FUNC_STAT AC_FUNC_STRERROR_R AC_FUNC_STRFTIME AC_FUNC_VPRINTF AC_CHECK_FUNCS([strtoul]) AC_CHECK_FUNCS([bzero]) AC_CHECK_FUNCS([ftruncate]) AC_CHECK_FUNCS([gethostbyname]) AC_CHECK_FUNCS([gethostbyname_r]) AC_CHECK_FUNCS([gettimeofday]) AC_CHECK_FUNCS([memmove]) AC_CHECK_FUNCS([memset]) AC_CHECK_FUNCS([mkdir]) AC_CHECK_FUNCS([realpath]) AC_CHECK_FUNCS([select]) AC_CHECK_FUNCS([setlocale]) AC_CHECK_FUNCS([socket]) AC_CHECK_FUNCS([strchr]) AC_CHECK_FUNCS([strdup]) AC_CHECK_FUNCS([strerror]) AC_CHECK_FUNCS([strstr]) AC_CHECK_FUNCS([strtol]) AC_CHECK_FUNCS([sqrt]) dnl The following functions are optional. AC_CHECK_FUNCS([alarm]) AC_CHECK_FUNCS([clock_gettime]) AC_CHECK_FUNCS([sched_get_priority_min]) AC_CHECK_FUNCS([sched_get_priority_max]) AC_CHECK_FUNCS([inet_ntoa]) AC_CHECK_FUNCS([pow]) if test "$cross_compiling" = "no" ; then AX_SIGNED_RIGHT_SHIFT fi dnl autoscan thinks we need this macro because we have a member function dnl called "error". Invoke the macro but don't run the check so autoscan dnl thinks we are in the clear. It's highly unlikely that we will ever dnl actually use the function that this checks for. if false ; then AC_FUNC_ERROR_AT_LINE fi # --- Coverage hooks --- AC_ARG_ENABLE(coverage, [ --enable-coverage turn on -fprofile-arcs -ftest-coverage], [case "${enableval}" in yes) ENABLE_COVERAGE=1 ;; no) ENABLE_COVERAGE=0 ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-cov) ;; esac], [ENABLE_COVERAGE=2]) if test "x[$]ENABLE_COVERAGE" = "x1"; then AC_MSG_WARN(enable coverage) GCOV_CFLAGS="`echo \"[$]CFLAGS\" | perl -pe 's/-O\d+//g;'` -fprofile-arcs -ftest-coverage" GCOV_CXXFLAGS="`echo \"[$]CXXFLAGS\" | perl -pe 's/-O\d+//g;'` -fprofile-arcs -ftest-coverage" GCOV_LDFLAGS="-XCClinker -fprofile-arcs -XCClinker -ftest-coverage" fi AC_SUBST(ENABLE_COVERAGE) AC_SUBST(GCOV_CFLAGS) AC_SUBST(GCOV_CXXFLAGS) AC_SUBST(GCOV_LDFLAGS) AC_CONFIG_HEADERS(config.h:config.hin) AC_CONFIG_HEADERS(lib/cpp/src/thrift/config.h:config.hin) AC_CONFIG_HEADERS(lib/c_glib/src/thrift/config.h:config.hin) # guard against pre defined config.h AH_TOP([ #ifndef CONFIG_H #define CONFIG_H ]) AH_BOTTOM([ #endif ]) AC_CONFIG_FILES([ Makefile compiler/cpp/Makefile compiler/cpp/src/Makefile compiler/cpp/test/Makefile lib/Makefile lib/cl/Makefile lib/cpp/Makefile lib/cpp/test/Makefile lib/cpp/thrift-nb.pc lib/cpp/thrift-z.pc lib/cpp/thrift-qt5.pc lib/cpp/thrift.pc lib/c_glib/Makefile lib/c_glib/thrift_c_glib.pc lib/c_glib/test/Makefile lib/d/Makefile lib/d/test/Makefile lib/erl/Makefile lib/go/Makefile lib/go/test/Makefile lib/go/test/fuzz/Makefile lib/haxe/test/Makefile lib/java/Makefile lib/js/Makefile lib/js/test/Makefile lib/json/Makefile lib/json/test/Makefile lib/kotlin/Makefile lib/netstd/Makefile lib/nodejs/Makefile lib/nodets/Makefile lib/perl/Makefile lib/perl/t/Makefile lib/php/Makefile lib/php/test/Makefile lib/dart/Makefile lib/py/Makefile lib/rb/Makefile lib/rs/Makefile lib/rs/test/Makefile lib/rs/test_recursive/Makefile lib/rs/test_recursive/src/Makefile lib/rs/test_recursive/src/maintenance/Makefile lib/rs/test_recursive/src/transit/Makefile lib/rs/test_recursive/src/transit/light/Makefile lib/rs/test_recursive/src/transit/services/Makefile lib/lua/Makefile lib/swift/Makefile lib/ts/Makefile lib/xml/Makefile lib/xml/test/Makefile test/Makefile test/features/Makefile test/c_glib/Makefile test/cl/Makefile test/cpp/Makefile test/erl/Makefile test/go/Makefile test/haxe/Makefile test/lua/Makefile test/netstd/Makefile test/php/Makefile test/dart/Makefile test/perl/Makefile test/py/Makefile test/py.twisted/Makefile test/py.tornado/Makefile test/rb/Makefile test/rs/Makefile test/swift/Makefile test/swift/CrossTests/Makefile tutorial/Makefile tutorial/c_glib/Makefile tutorial/cl/Makefile tutorial/cpp/Makefile tutorial/d/Makefile tutorial/go/Makefile tutorial/haxe/Makefile tutorial/java/Makefile tutorial/js/Makefile tutorial/netstd/Makefile tutorial/nodejs/Makefile tutorial/dart/Makefile tutorial/perl/Makefile tutorial/php/Makefile tutorial/py/Makefile tutorial/py.twisted/Makefile tutorial/py.tornado/Makefile tutorial/rb/Makefile tutorial/rs/Makefile tutorial/swift/Makefile ]) if test "$have_cpp" = "yes" ; then MAYBE_CPP="cpp" ; else MAYBE_CPP="" ; fi AC_SUBST([MAYBE_CPP]) if test "$have_c_glib" = "yes" ; then MAYBE_C_GLIB="c_glib" ; else MAYBE_C_GLIB="" ; fi AC_SUBST([MAYBE_C_GLIB]) if test "$have_d" = "yes" -a "$have_deimos_event2" = "yes" -a "$have_deimos_openssl" = "yes"; then MAYBE_D="d" ; else MAYBE_D="" ; fi AC_SUBST([MAYBE_D]) if test "$have_java" = "yes" ; then MAYBE_JAVA="java" ; else MAYBE_JAVA="" ; fi AC_SUBST([MAYBE_JAVA]) if test "$have_kotlin" = "yes" ; then MAYBE_KOTLIN="kotlin" ; else MAYBE_KOTLIN="" ; fi AC_SUBST([MAYBE_KOTLIN]) if test "$have_python" = "yes" ; then MAYBE_PYTHON="py" ; else MAYBE_PYTHON="" ; fi AC_SUBST([MAYBE_PYTHON]) if test "$have_py3" = "yes" ; then MAYBE_PY3="py3" ; else MAYBE_PY3="" ; fi AC_SUBST([MAYBE_PY3]) if test "$have_ruby" = "yes" ; then MAYBE_RUBY="rb" ; else MAYBE_RUBY="" ; fi AC_SUBST([MAYBE_RUBY]) if test "$have_perl" = "yes" ; then MAYBE_PERL="perl" ; else MAYBE_PERL="" ; fi AC_SUBST([MAYBE_PERL]) if test "$have_php" = "yes" ; then MAYBE_PHP="php" ; else MAYBE_PHP="" ; fi AC_SUBST([MAYBE_PHP]) if test "$have_dart" = "yes" ; then MAYBE_DART="dart" ; else MAYBE_DART="" ; fi AC_SUBST([MAYBE_DART]) if test "$have_go" = "yes" ; then MAYBE_GO="go" ; else MAYBE_GO="" ; fi AC_SUBST([MAYBE_GO]) if test "$have_nodejs" = "yes" ; then MAYBE_NODEJS="nodejs" ; else MAYBE_NODEJS="" ; fi AC_SUBST([MAYBE_NODEJS]) if test "$have_nodets" = "yes" ; then MAYBE_NODETS="nodets" ; else MAYBE_NODETS="" ; fi AC_SUBST([MAYBE_NODETS]) if test "$have_erlang" = "yes" ; then MAYBE_ERLANG="erl" ; else MAYBE_ERLANG="" ; fi AC_SUBST([MAYBE_ERLANG]) if test "$have_lua" = "yes" ; then MAYBE_LUA="lua" ; else MAYBE_LUA="" ; fi AC_SUBST([MAYBE_LUA]) if test "$have_rs" = "yes" ; then MAYBE_RS="rs" ; else MAYBE_RS="" ; fi AC_SUBST([MAYBE_RS]) if test "$have_swift" = "yes" ; then MAYBE_SWIFT="swift" ; else MAYBE_SWIFT="" ; fi AC_SUBST([MAYBE_SWIFT]) if test "$have_netstd" = "yes" ; then MAYBE_NETSTD="netstd" ; else MAYBE_NETSTD="" ; fi AC_SUBST([MAYBE_NETSTD]) if test "$have_cl" = "yes" ; then MAYBE_CL="cl" ; else MAYBE_CL="" ; fi AC_SUBST([MAYBE_CL]) AC_OUTPUT echo echo "$PACKAGE $VERSION" echo echo "Building C (GLib) Library .... : $have_c_glib" echo "Building C++ Library ......... : $have_cpp" echo "Building Common Lisp Library.. : $have_cl" echo "Building D Library ........... : $have_d" echo "Building Dart Library ........ : $have_dart" echo "Building .NET Standard Library : $have_netstd" echo "Building Erlang Library ...... : $have_erlang" echo "Building Go Library .......... : $have_go" echo "Building Haxe Library ........ : $have_haxe" echo "Building Java Library ........ : $have_java" echo "Building Kotlin Library ...... : $have_kotlin" echo "Building Lua Library ......... : $have_lua" echo "Building NodeJS Library ...... : $have_nodejs" echo "Building Perl Library ........ : $have_perl" echo "Building PHP Library ......... : $have_php" echo "Building Python Library ...... : $have_python" echo "Building Py3 Library ......... : $have_py3" echo "Building Ruby Library ........ : $have_ruby" echo "Building Rust Library ........ : $have_rs" echo "Building Swift Library ....... : $have_swift" if test "$have_c_glib" = "yes" ; then echo echo "C (glib):" echo " Using glib version ........ : $($GSETTINGS --version)" fi if test "$have_cpp" = "yes" ; then echo echo "C++ Library:" echo " C++ compiler .............. : $CXX" echo " Build TZlibTransport ...... : $have_zlib" echo " Build TNonblockingServer .. : $have_libevent" echo " Build TQTcpServer (Qt5) ... : $have_qt5" echo " C++ compiler version ...... : $($CXX --version | head -1)" fi if test "$have_cl" = "yes" ; then echo echo "Common Lisp Library:" echo " Using Common Lisp ......... : $SBCL" echo " Using Common Lisp version . : $($SBCL --version)" fi if test "$have_d" = "yes" ; then echo echo "D Library:" echo " Using D Compiler .......... : $DMD" echo " Building D libevent tests . : $with_d_event_tests" echo " Building D SSL tests ...... : $with_d_ssl_tests" echo " Using D version ........... : $($DMD --version | head -1)" fi if test "$have_dart" = "yes" ; then echo echo "Dart Library:" echo " Using Dart ................ : $DART" echo " Using Pub ................. : $DARTPUB" echo " Using Dart version ........ : $($DART --version 2>&1)" fi if test "$have_netstd" = "yes" ; then echo echo ".NET Standard Library:" echo " Using dotnet .............. : $DOTNETCORE" echo " Using dotnet version ...... : $DOTNETCORE_VERSION" fi if test "$have_erlang" = "yes" ; then echo echo "Erlang Library:" echo " Using erlc ................ : $ERLC" echo " Using rebar ............... : $REBAR" echo " Using erlc version ........ : $($ERL -eval 'erlang:display(erlang:system_info(otp_release)), halt().' -noshell | tr -d '\"')" fi if test "$have_go" = "yes" ; then echo echo "Go Library:" echo " Using Go................... : $GO" echo " Using Go version........... : $($GO version)" fi if test "$have_haxe" = "yes" ; then echo echo "Haxe Library:" echo " Using Haxe ................ : $HAXE" echo " Using Haxe version ........ : $HAXE_VERSION" fi if test "$have_java" = "yes" ; then echo echo "Java Library:" echo " Using gradle .............. : $GRADLE" echo " Using java ................ : $JAVA" echo " Using javac ............... : $JAVAC" echo " Using Gradle version ...... : $($GRADLE --version --quiet | grep Gradle 2>&1)" echo " Using java version ........ : $($JAVA -version 2>&1 | grep 'version ')" fi if test "$have_kotlin" = "yes" ; then echo echo "Kotlin (Test Only) Library:" echo " Using gradle .............. : $GRADLE" echo " Using java ................ : $JAVA" echo " Using javac ............... : $JAVAC" echo " Using Gradle version ...... : $($GRADLE --version --quiet | grep Gradle 2>&1)" echo " Using java version ........ : $($JAVA -version 2>&1 | grep 'version ')" fi if test "$have_lua" = "yes" ; then echo echo "Lua Library:" echo " Using Lua ................. : $LUA" echo " Using Lua version.......... : $($LUA -v)" fi if test "$have_nodejs" = "yes" ; then echo echo "NodeJS Library:" echo " Using NodeJS .............. : $NODEJS" echo " Using NodeJS version....... : $($NODEJS --version)" fi if test "$have_perl" = "yes" ; then echo echo "Perl Library:" echo " Using Perl ................ : $PERL" echo " Using Perl version ........ : $($PERL -v | grep 'version ')" fi if test "$have_php" = "yes" ; then echo echo "PHP Library:" echo " Using php-config .......... : $PHP_CONFIG" echo " Using php version ......... : $($PHP --version | head -1)" fi if test "$have_python" = "yes" ; then echo echo "Python Library:" echo " Using Python .............. : $PYTHON" echo " Using Python version ...... : $($PYTHON --version 2>&1)" if test "$have_py3" = "yes" ; then echo " Using Python3 ............. : $PYTHON3" echo " Using Python3 version ..... : $($PYTHON3 --version)" fi if test "$have_trial" = "yes"; then echo " Using trial ............... : $TRIAL" fi fi if test "$have_ruby" = "yes" ; then echo echo "Ruby Library:" echo " Using Ruby ................ : $RUBY" echo " Using Ruby version ........ : $($RUBY --version)" fi if test "$have_rs" = "yes" ; then echo echo "Rust Library:" echo " Using Cargo................ : $CARGO" echo " Using rustc................ : $RUSTC" echo " Using Rust version......... : $($RUSTC --version)" fi if test "$have_swift" = "yes" ; then echo echo "Swift Library:" echo " Using Swift ............... : $SWIFT" echo " Using Swift version ....... : $($SWIFT --version | head -1)" fi echo echo "If something is missing that you think should be present," echo "please skim the output of configure to find the missing" echo "component. Details are present in config.log." echo thrift-0.19.0/rust-toolchain0000644000000000000000000000000714370300523015767 0ustar00rootroot000000000000001.61.0 thrift-0.19.0/ltmain.sh0000644000000000000000000117147414472652503014746 0ustar00rootroot00000000000000#! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 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.6 Debian-2.4.6-2" package_revision=2.4.6 ## ------ ## ## 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=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 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. # 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 3 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. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES 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 . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## 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 # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # 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 ## ------------------------- ## ## 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" ## ----------------- ## ## 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='eval 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. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _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. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes 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_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_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_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg 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. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # 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_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_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_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_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 # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 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. # 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 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 . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## 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 '# warranty; '. # # 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 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 # to the main code. A hook is just a named list of of function, 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 functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is 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 case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # 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=: ;; # # 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 # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # 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_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse 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 [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_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 propogate 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+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # 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+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break 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 ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # 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+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## 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#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' 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. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # 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: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # 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.6-2 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= # 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 ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _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; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } 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_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_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_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_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_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_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 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 -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_for_eval "$nonopt" install_prog="$func_quote_for_eval_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_for_eval "$arg" func_append install_prog "$func_quote_for_eval_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_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_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_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_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_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_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\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $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_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_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 ;; 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*) # 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*) # 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 ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-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_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_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_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_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 -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=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_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_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_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_for_eval "$arg" arg=$func_quote_for_eval_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|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) 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*) # 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_for_expand "$cmd" eval "func_echo $func_quote_for_expand_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_for_expand "$cmd" eval "func_echo $func_quote_for_expand_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_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` 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_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` 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: thrift-0.19.0/CONTRIBUTING.md0000644000000000000000000001647214303740367015351 0ustar00rootroot00000000000000# How to Contribute # Thank you for your interest in contributing to the Apache Thrift project! Information on why and how to contribute is available on the Apache Software Foundation (ASF) web site. In particular, we recommend the following to become acquainted with Apache Contributions: * [Contributors Tech Guide](http://www.apache.org/dev/contributors) * [Get involved!](http://www.apache.org/foundation/getinvolved.html) * [Legal aspects on Submission of Contributions (Patches)](http://www.apache.org/licenses/LICENSE-2.0.html#contributions) ## GitHub pull requests ## This is the preferred method of submitting changes. When you submit a pull request through github, it activates the continuous integration (CI) build systems at Appveyor and Travis to build your changesxi on a variety of Linux and Windows configurations and run all the test suites. Follow these requirements for a successful pull request: 1. All significant changes require an [Apache Jira THRIFT Issue](http://issues.apache.org/jira/browse/THRIFT) ticket. Trivial changes such as fixing a typo or a compiler warning do not. 1. All pull requests should contain a single commit per issue, or we will ask you to squash it. 1. The pull request title must begin with the Jira THRIFT ticket identifier if it has an associated ticket, for example: THRIFT-9999: an example pull request title 1. Commit messages must follow this pattern for code changes (deviations will not be merged): THRIFT-9999: [summary of fix, one line if possible] Client: [language(s) affected, comma separated, for example: "cpp,erl,perl"] Instructions: 1. Create a fork in your GitHub account of http://github.com/apache/thrift 1. Clone the fork to your development system. 1. Create a branch for your changes (best practice is issue as branch name, e.g. THRIFT-9999). 1. Modify the source to include the improvement/bugfix, and: * Remember to provide *tests* for all submitted changes! * Use test-driven development (TDD): add a test that will isolate the bug *before* applying the change that fixes it. * Verify that you follow [Thrift Coding Standards](/docs/coding_standards) (you can run 'make style', which ensures proper format for some languages). * [*optional*] Verify that your change works on other platforms by adding a GitHub service hook to [Travis CI](http://docs.travis-ci.com/user/getting-started/#Step-one%3A-Sign-in) and [AppVeyor](http://www.appveyor.com/docs). You can use this technique to run the Thrift CI jobs in your account to check your changes before they are made public. Every GitHub pull request into Thrift will run the full CI build and test suite on your changes. 1. Squash your changes to a single commit. This maintains clean change history. 1. Commit and push changes to your branch (please use issue name and description as commit title, e.g. "THRIFT-9999: make it perfect"), with the affected languages on the next line of the description. 1. Use GitHub to create a pull request going from your branch to apache:master. Ensure that the Jira ticket number is at the beginning of the title of your pull request, same as the commit title. 1. Wait for other contributors or committers to review your new addition, and for a CI build to complete. 1. Wait for a committer to commit your patch. You can nudge the committers if necessary by sending a message to the [Apache Thrift mailing list](https://thrift.apache.org/mailing). ## If you want to build the project locally ## For Windows systems, see our detailed instructions on the [CMake README](/build/cmake/README.md). For Windows Native C++ builds, see our detailed instructions on the [WinCPP README](/build/wincpp/README.md). For unix systems, see our detailed instructions on the [Docker README](/build/docker/README.md). ## If you want to review open issues... ## 1. Review the [GitHub Pull Request Backlog](https://github.com/apache/thrift/pulls). Code reviews are open to all. 2. Review the [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT). You can search for tickets relating to languages you are interested in or currently using with thrift, for example a Jira search (Issues -> Search For Issues) query of ``project = THRIFT AND component in ("Erlang - Library") and status not in (resolved, closed)`` will locate all the open Erlang Library issues. ## If you discovered a defect... ## 1. Check to see if the issue is already in the [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT). 1. If not, create a ticket describing the change you're proposing in the Jira issue tracker. 1. Contribute your code changes using the GitHub pull request method: ## Contributing via Patch ## To create a patch from changes in your local directory: git diff > ../THRIFT-NNNN.patch then wait for contributors or committers to review your changes, and then for a committer to apply your patch. This is not the preferred way to submit changes and incurs additional overhead for committers who must then create a pull request for you. ## GitHub recipes for Pull Requests ## Sometimes commmitters may ask you to take actions in your pull requests. Here are some recipes that will help you accomplish those requests. These examples assume you are working on Jira issue THRIFT-9999. You should also be familiar with the [upstream](https://help.github.com/articles/syncing-a-fork/) repository concept. ### Squash your changes ### If you have not submitted a pull request yet, or if you have not yet rebased your existing pull request, you can squash all your commits down to a single commit. This makes life easier for the committers. If your pull request on GitHub has more than one commit, you should do this. 1. Use the command ``git log`` to identify how many commits you made since you began. 2. Use the command ``git rebase -i HEAD~N`` where N is the number of commits. 3. Leave "pull" in the first line. 4. Change all other lines from "pull" to "fixup". 5. All your changes are now in a single commit. If you already have a pull request outstanding, you will need to do a "force push" to overwrite it since you changed your commit history: git push -u origin THRIFT-9999 --force A more detailed walkthrough of a squash can be found at [Git Ready](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html). ### Rebase your pull request ### If your pull request has a conflict with master, it needs to be rebased: git checkout THRIFT-9999 git rebase upstream master (resolve any conflicts, make sure it builds) git push -u origin THRIFT-9999 --force ### Fix a bad merge ### If your pull request contains commits that are not yours, then you should use the following technique to fix the bad merge in your branch: git checkout master git pull upstream master git checkout -b THRIFT-9999-take-2 git cherry-pick ... (pick only your commits from your original pull request in ascending chronological order) squash your changes to a single commit if there is more than one (see above) git push -u origin THRIFT-9999-take-2:THRIFT-9999 This procedure will apply only your commits in order to the current master, then you will squash them to a single commit, and then you force push your local THRIFT-9999-take-2 into remote THRIFT-9999 which represents your pull request, replacing all the commits with the new one. thrift-0.19.0/sonar-project.properties0000644000000000000000000001037014454461475020022 0ustar00rootroot00000000000000# Apache Thrift © The Apache Software Foundation # http://www.apache.org/licenses/LICENSE-2.0 # SPDX-License-Identifier: Apache-2.0 # File: sonar-project.properties # Apache Thrift configuration file for Sonar https://analysis.apache.org/ # Sonar is an open platform to manage code quality http://www.sonarsource.org/ # required metadata sonar.projectKey=org.apache.thrift sonar.projectName=Apache Thrift sonar.projectDescription= The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version sonar.projectVersion=0.19.0 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases #sonar.projectDate=yyyy-MM-dd # TODO add website (sonar.projectUrl does not work) #sonar.XXXX=http//thrift.apache.org # Some properties that will be inherited by the modules sonar.sources=src sonar.language=java,js,c++,py,c sonar.sourceEncoding=UTF-8 # scm sonar.scm.url=scm:git:https://github.com/apache/thrift.git # cppcheck -q --error-exitcode=0 --xml . 2> cppcheck-result.xml sonar.cxx.cppcheck.reportPath=cppcheck-result.xml # List of the module identifiers sonar.modules=module1,module3,module4,module5,module6,module7,module8,module9,module10,module11,module12 # we need sonar-runner 2.1 for this, see http://jira.codehaus.org/browse/SONARPLUGINS-2421 #sonar.modules=module2 # delph plugin is broken #sonar.modules=module13 # phpunit plugin is broken #sonar.modules=module14 module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test module1.sonar.binaries=build/libs/libthrift-0.19.0.jar module1.sonar.libraries=build/deps/*.jar module1.sonar.language=java module2.sonar.projectName=Apache Thrift - Java Tutorial module2.sonar.projectBaseDir=. module2.sonar.sources=tutorial/java/src, tutorial/java/gen-java module2.sonar.binaries=tutorial/java/tutorial.jar module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-0.19.0.jar module2.sonar.language=java module3.sonar.projectName=Apache Thrift - JavaScript Library module3.sonar.projectBaseDir=lib/js module3.sonar.sources=. module3.sonar.exclusions=test/**/* module3.sonar.language=js module4.sonar.projectName=Apache Thrift - JavaScript Tutorial module4.sonar.projectBaseDir=tutorial/js module4.sonar.sources=. module4.sonar.language=web module5.sonar.projectName=Apache Thrift - C++ Library module5.sonar.projectBaseDir=lib/cpp module5.sonar.sources=src module5.sonar.tests=test module5.sonar.language=c++ module6.sonar.projectName=Apache Thrift - C++ Tutorial module6.sonar.projectBaseDir=tutorial/cpp module6.sonar.sources=. module6.sonar.exclusions=gen-cpp/**/* module6.sonar.language=c++ module7.sonar.projectName=Apache Thrift - C++ Cross Language Test module7.sonar.projectBaseDir=test/cpp module7.sonar.sources=src module7.sonar.language=c++ module8.sonar.projectName=Apache Thrift - Compiler module8.sonar.projectBaseDir=compiler/cpp module8.sonar.sources=src module8.sonar.language=c++ module9.sonar.projectName=Apache Thrift - Python Library module9.sonar.projectBaseDir=lib/py module9.sonar.sources=src module9.sonar.language=py module10.sonar.projectName=Apache Thrift - Python Tutorial module10.sonar.projectBaseDir=tutorial/py module10.sonar.sources=. module10.sonar.exclusions=gen-py/**/* module10.sonar.language=py module11.sonar.projectName=Apache Thrift - Python Cross Language Test module11.sonar.projectBaseDir=test/py module11.sonar.sources=. module11.sonar.exclusions=gen-*/**/* module11.sonar.language=py module12.sonar.projectName=Apache Thrift - c_glib Library module12.sonar.projectBaseDir=lib/c_glib module12.sonar.sources=src module12.sonar.language=c module13.sonar.projectName=Apache Thrift - Delphi Library module13.sonar.projectBaseDir=lib/delphi module13.sonar.sources=src module13.sonar.tests=test module13.sonar.language=delph module14.sonar.projectName=Apache Thrift - PHP Library module14.sonar.projectBaseDir=lib/php module14.sonar.sources=src module14.sonar.language=php # TODO add some more languages here thrift-0.19.0/.asf.yaml0000644000000000000000000000037214303740366014622 0ustar00rootroot00000000000000notifications: commits: commits@thrift.apache.org issues: dev@thrift.apache.org pullrequests_status: dev@thrift.apache.org pullrequests_comment: notifications@thrift.apache.org jira_options: link label worklog thrift-0.19.0/package.json0000644000000000000000000000354714454461475015414 0ustar00rootroot00000000000000{ "name": "thrift", "description": "node.js bindings for the Apache Thrift RPC system", "homepage": "http://thrift.apache.org/", "repository": { "type": "git", "url": "https://github.com/apache/thrift.git" }, "version": "0.19.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", "url": "http://thrift.apache.org" }, "license": "Apache-2.0", "licenses": [ { "type": "Apache-2.0", "url": "http://www.apache.org/licenses/LICENSE-2.0" } ], "bugs": { "mail": "dev@thrift.apache.org", "url": "https://issues.apache.org/jira/browse/THRIFT" }, "files": [ "lib/nodejs/lib/thrift", "lib/nodejs/README.md" ], "directories": { "lib": "./lib/nodejs/lib/thrift" }, "browser": "./lib/nodejs/lib/thrift/browser.js", "main": "./lib/nodejs/lib/thrift", "engines": { "node": ">= 10.18.0" }, "dependencies": { "browser-or-node": "^1.2.1", "isomorphic-ws": "^4.0.1", "node-int64": "^0.4.0", "q": "^1.5.0", "ws": "^5.2.3" }, "devDependencies": { "@types/node": "^10.12.6", "@types/node-int64": "^0.4.29", "@types/q": "^1.5.1", "buffer-equals": "^1.0.4", "commander": "^2.14.1", "connect": "^3.6.6", "eslint": "^5.7.0", "eslint-config-prettier": "^3.1.0", "eslint-plugin-prettier": "^3.0.0", "html-validator-cli": "^2.0.0", "jsdoc": "^4.0.2", "json-int64": "^1.0.2", "nyc": "^15.0.0", "prettier": "^1.14.3", "tape": "^4.9.0", "typescript": "^3.1.6", "utf-8-validate": "^5.0.0" }, "scripts": { "cover": "lib/nodejs/test/testAll.sh COVER", "test": "lib/nodejs/test/testAll.sh", "test-ts": "lib/nodets/test/testAll.sh", "prettier": "prettier --write '**/*.js'", "lint": "eslint lib/nodejs/. --ext .js", "lint-tests": "eslint lib/nodejs/test/. --ext .js" } } thrift-0.19.0/aclocal.m40000644000000000000000000016337014472652510014757 0ustar00rootroot00000000000000# generated automatically by aclocal 1.15.1 -*- Autoconf -*- # Copyright (C) 1996-2017 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.69],, [m4_warning([this file was generated for autoconf 2.69. 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'.])]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- dnl serial 11 (pkg-config-0.29.1) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2017 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.15' 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.15.1], [], [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.15.1])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-2017 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-2017 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-2017 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-2017 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. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _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. FIXME. This creates each '.P' file that we will # 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" ac_aux_dir="$ac_aux_dir"]) ]) # AM_EXTRA_RECURSIVE_TARGETS -*- Autoconf -*- # Copyright (C) 2012-2017 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_EXTRA_RECURSIVE_TARGETS # -------------------------- # Define the list of user recursive targets. This macro exists only to # be traced by Automake, which will ensure that a proper definition of # user-defined recursive targets (and associated rules) is propagated # into all the generated Makefiles. # TODO: We should really reject non-literal arguments here... AC_DEFUN([AM_EXTRA_RECURSIVE_TARGETS], []) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2017 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 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_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([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 ]) 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-2017 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-2017 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])]) # Copyright (C) 1998-2017 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_LEX # ----------- # Autoconf leaves LEX=: if lex or flex can't be found. Change that to a # "missing" invocation, for better error output. AC_DEFUN([AM_PROG_LEX], [AC_PREREQ([2.50])dnl AC_REQUIRE([AM_MISSING_HAS_RUN])dnl AC_REQUIRE([AC_PROG_LEX])dnl if test "$LEX" = :; then LEX=${am_missing_run}flex fi]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2017 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 to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2017 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 case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac 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-2017 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-2017 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) 1999-2017 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_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). dnl FIXME: Remove the need to hard-code Python versions here. m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 python3.2 python3.1 python3.0 python2.7 dnl python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Getting [:3] seems to be dnl the best way to do this; it's what "site.py" does in the standard dnl library. AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl Use the values of $prefix and $exec_prefix for the corresponding dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made dnl distinct variables so they can be overridden if need be. However, dnl general consensus is that you shouldn't need this ability. AC_SUBST([PYTHON_PREFIX], ['${prefix}']) AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}']) dnl At times (like when building shared libraries) you may want dnl to know which OS platform Python thinks this is. AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) # Just factor out some code duplication. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl Set up 4 directories: dnl pythondir -- where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON script directory], [am_cv_python_pythondir], [if test "x$prefix" = xNONE then am_py_prefix=$ac_default_prefix else am_py_prefix=$prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl pkgpythondir -- $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl pyexecdir -- directory for installing python extension modules dnl (shared libraries) dnl Query distutils for this directory. AC_CACHE_CHECK([for $am_display_PYTHON extension module directory], [am_cv_python_pyexecdir], [if test "x$exec_prefix" = xNONE then am_py_exec_prefix=$am_py_prefix else am_py_exec_prefix=$exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2017 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-2017 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-2017 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-2017 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-2017 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($@)]) m4_include([aclocal/ac_prog_bison.m4]) m4_include([aclocal/ax_boost_base.m4]) m4_include([aclocal/ax_check_openssl.m4]) m4_include([aclocal/ax_compare_version.m4]) m4_include([aclocal/ax_cxx_compile_stdcxx.m4]) m4_include([aclocal/ax_cxx_compile_stdcxx_11.m4]) m4_include([aclocal/ax_dmd.m4]) m4_include([aclocal/ax_javac_and_java.m4]) m4_include([aclocal/ax_lib_event.m4]) m4_include([aclocal/ax_lib_zlib.m4]) m4_include([aclocal/ax_lua.m4]) m4_include([aclocal/ax_prog_dotnetcore_version.m4]) m4_include([aclocal/ax_prog_haxe_version.m4]) m4_include([aclocal/ax_prog_perl_modules.m4]) m4_include([aclocal/ax_signed_right_shift.m4]) m4_include([aclocal/ax_thrift_internal.m4]) m4_include([aclocal/libtool.m4]) m4_include([aclocal/ltoptions.m4]) m4_include([aclocal/ltsugar.m4]) m4_include([aclocal/ltversion.m4]) m4_include([aclocal/lt~obsolete.m4]) m4_include([aclocal/tar.m4]) thrift-0.19.0/Makefile.am0000644000000000000000000000740614370300523015137 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ACLOCAL_AMFLAGS = -I ./aclocal SUBDIRS = compiler/cpp lib if WITH_TESTS SUBDIRS += test endif if WITH_TUTORIAL SUBDIRS += tutorial endif clean-local: $(RM) -r vendor/ distclean-local: $(RM) -r .dub/ $(RM) -r autom4te.cache/ CLEANFILES = \ composer.lock \ dub.selections.json DISTCLEANFILES = \ Makefile \ Makefile.in \ aclocal.m4 \ apache-thrift-test-library \ autoscan.log \ compile \ config.guess \ config.hin \ config.hin~ \ config.log \ config.status \ config.sub \ configure \ configure.scan \ debcomp \ install-sh \ ltmain.sh \ missing \ ylwrap dist-hook: find $(distdir) -type f \( -iname ".DS_Store" -or -iname "._*" -or -iname ".gitignore" \) | xargs rm -f find $(distdir) -type d \( -iname ".deps" -or -iname ".libs" \) | xargs rm -rf find $(distdir) -type d \( -iname ".svn" -or -iname ".git" \) | xargs rm -rf print-version: @echo $(PACKAGE_VERSION) .PHONY: precross cross precross-%: all $(MAKE) -C $* precross precross: all precross-test precross-lib empty := space := $(empty) $(empty) comma := , CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ @MAYBE_KOTLIN@ @MAYBE_SWIFT@ CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS)) if WITH_PY3 CROSS_PY=$(PYTHON3) else CROSS_PY=$(PYTHON) endif if WITH_PYTHON crossfeature: precross $(CROSS_PY) test/test.py --retry-count 5 --features .* --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED) else # feature test needs python build crossfeature: endif cross-%: precross crossfeature $(CROSS_PY) test/test.py --retry-count 5 --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED) --client $(CROSS_LANGS_COMMA_SEPARATED) --regex "$*" cross: cross-.* TIMES = 1 2 3 fail: precross $(CROSS_PY) test/test.py || true $(CROSS_PY) test/test.py --update-expected-failures=overwrite $(foreach var,$(TIMES),test/test.py -s || true;test/test.py --update-expected-failures=merge;) codespell_skip_files = \ *.jar \ *.class \ *.so \ *.a \ *.la \ *.o \ *.p12 \ *OCamlMakefile \ .keystore \ .truststore \ CHANGES \ config.sub \ configure \ depcomp \ libtool.m4 \ output.* \ rebar \ thrift skipped_files = $(subst $(space),$(comma),$(codespell_skip_files)) style-local: codespell --write-changes --skip=$(skipped_files) --disable-colors EXTRA_DIST = \ .asf.yaml \ .clang-format \ .dockerignore \ .editorconfig \ .eslintignore \ .eslintrc.json \ .flake8 \ .gitattributes \ .gitignore \ .travis.yml \ ApacheThrift.nuspec \ appveyor.yml \ bootstrap.sh \ bower.json \ build \ CHANGES.md \ CMakeLists.txt \ composer.json \ contrib \ CONTRIBUTING.md \ debian \ doap.rdf \ doc \ dub.json \ go.mod \ jitpack.yml \ LANGUAGES.md \ LICENSE \ NOTICE \ package.json \ package-lock.json \ phpcs.xml.dist \ README.md \ rust-toolchain \ sonar-project.properties \ Thrift.podspec thrift-0.19.0/CMakeLists.txt0000644000000000000000000000753014454461475015662 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # cmake_minimum_required(VERSION 3.4) if(POLICY CMP0048) cmake_policy(SET CMP0048 NEW) # package version behavior added in cmake 3.0 endif() if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) # find_package behavior added in cmake 3.12 endif() # PACKAGE_VERSION is used by cpack scripts currently # Both thrift_VERSION and PACKAGE_VERSION should be the same for now set(thrift_VERSION "0.19.0") set(PACKAGE_VERSION ${thrift_VERSION}) project("thrift" VERSION ${PACKAGE_VERSION}) message(STATUS "Configuring ${CMAKE_PROJECT_NAME} ${thrift_VERSION}") set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") # Some default settings include(DefineCMakeDefaults) # Build time options are defined here include(DefineOptions) include(DefineInstallationPaths) # Based on the options set some platform specifics include(DefinePlatformSpecifc) # Add CMake targets for static code analysis include(StaticCodeAnalysis) # Generate the config.h file include(ConfigureChecks) # Generate the ThriftConfig.cmake module include(GenerateConfigModule) # Packaging include(CPackConfig) # Dependencies include(BoostMacros) find_package(Threads) include(CTest) if(BUILD_TESTING) message(STATUS "Building with unittests") enable_testing() # Define "make check" as alias for "make test" add_custom_target(check COMMAND ctest) else () message(STATUS "Building without tests") endif () if(BUILD_COMPILER) if(NOT EXISTS ${THRIFT_COMPILER}) set(THRIFT_COMPILER $) endif() add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/compiler/cpp) elseif(EXISTS ${THRIFT_COMPILER}) add_executable(thrift-compiler IMPORTED) set_property(TARGET thrift-compiler PROPERTY IMPORTED_LOCATION ${THRIFT_COMPILER}) endif() if(BUILD_CPP) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/cpp) if(BUILD_TUTORIALS) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/tutorial/cpp) endif() if(BUILD_TESTING) if(WITH_LIBEVENT AND WITH_ZLIB AND WITH_OPENSSL) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test/cpp) else() message(WARNING "libevent and/or ZLIB and/or OpenSSL not found or disabled; will not build some tests") endif() endif() endif() if(BUILD_C_GLIB) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/c_glib) if(BUILD_TESTING) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test/c_glib) endif() endif() if(BUILD_JAVA) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/java) endif() if(BUILD_JAVASCRIPT) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/js) endif() if(BUILD_KOTLIN) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/kotlin) endif() if(BUILD_NODEJS) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/nodejs) endif() if(BUILD_PYTHON) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/py) if(BUILD_TESTING) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test/py) endif() endif() # Create the uninstall target add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/build/cmake/uninstall.cmake") PRINT_CONFIG_SUMMARY() thrift-0.19.0/compile0000755000000000000000000001624514472652513014476 0ustar00rootroot00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 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*) 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/*) 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 ) 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 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: thrift-0.19.0/bower.json0000644000000000000000000000046414454461475015132 0ustar00rootroot00000000000000{ "name": "thrift", "version": "0.19.0", "homepage": "https://github.com/apache/thrift.git", "authors": [ "Apache Thrift " ], "description": "Apache Thrift", "main": "lib/js/src/thrift.js", "keywords": [ "thrift" ], "license": "Apache v2", "ignore": [] } thrift-0.19.0/config.sub0000755000000000000000000010645014472652513015101 0ustar00rootroot00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-02-22' # 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/gitweb/?p=config.git;a=blob_plain;f=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. 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-2018 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" 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 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo "$1" | sed 's/-[^-]*$//'` if [ "$basic_machine" != "$1" ] then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -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*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2*) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; nsv-tandem) basic_machine=nsv-tandem ;; nsx-tandem) basic_machine=nsx-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh5el) basic_machine=sh5le-unknown ;; simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; x64) basic_machine=x86_64-pc ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; none) basic_machine=none-none os=-none ;; # 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) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases that might get confused # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # es1800 is here to avoid being matched by es* (a different OS) -es1800*) os=-ose ;; # Now accept the basic system types. # The portable systems comes first. # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -xray | -os68k* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4*) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -pikeos*) # Until real need of OS specific support for # particular features comes up, bare metal # configurations are quite functional. case $basic_machine in arm*) os=-eabi ;; *) os=-elf ;; esac ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; pru-*) os=-elf ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $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 ;; -mvs* | -opened*) vendor=ibm ;; -os400*) 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 basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac echo "$basic_machine$os" exit # Local variables: # eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: thrift-0.19.0/.clang-format0000644000000000000000000000324414303740366015463 0ustar00rootroot00000000000000--- Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 ConstructorInitializerIndentWidth: 2 AlignEscapedNewlinesLeft: false AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AllowShortFunctionsOnASingleLine: Inline AlwaysBreakTemplateDeclarations: true AlwaysBreakBeforeMultilineStrings: true BreakBeforeBinaryOperators: true BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BinPackParameters: false ColumnLimit: 100 ConstructorInitializerAllOnOneLineOrOnePerLine: true DerivePointerAlignment: false IndentCaseLabels: false IndentWrappedFunctionNames: false IndentFunctionDeclarationAfterType: false MaxEmptyLinesToKeep: 1 KeepEmptyLinesAtTheStartOfBlocks: true NamespaceIndentation: None ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakBeforeFirstCallParameter: 190 PenaltyBreakComment: 300 PenaltyBreakString: 10000 PenaltyBreakFirstLessLess: 120 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 1200 PointerAlignment: Left SpacesBeforeTrailingComments: 1 Cpp11BracedListStyle: true Standard: Auto IndentWidth: 2 TabWidth: 4 UseTab: Never BreakBeforeBraces: Attach SpacesInParentheses: false SpacesInAngles: false SpaceInEmptyParentheses: false SpacesInCStyleCastParentheses: false SpacesInContainerLiterals: true SpaceBeforeAssignmentOperators: true ContinuationIndentWidth: 4 CommentPragmas: '^ IWYU pragma:' ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] SpaceBeforeParens: ControlStatements DisableFormat: false ... thrift-0.19.0/go.mod0000644000000000000000000000005114472647462014221 0ustar00rootroot00000000000000module github.com/apache/thrift go 1.20 thrift-0.19.0/ApacheThrift.nuspec0000644000000000000000000000343214454461475016700 0ustar00rootroot00000000000000 ApacheThrift 0.19.0 Apache Thrift 0.19.0 Apache Thrift Developers Apache Software Foundation Apache-2.0 http://thrift.apache.org/ true Apache Thrift .NET Library Contains runtime libraries from lib/netstd for netstandard2.0 framework development. Apache Thrift RPC thrift-0.19.0/debian/0000777000000000000000000000000014454463742014342 5ustar00rootroot00000000000000thrift-0.19.0/debian/changelog0000644000000000000000000000703014454463742016210 0ustar00rootroot00000000000000thrift (0.19.0) stable; urgency=low * update to 0.19.0 -- Apache Thrift Developers Sat, 15 Jul 2023 11:00:00 +0100 thrift (0.18.1) stable; urgency=low * update to 0.18.1 -- Apache Thrift Developers Wed, 15 Feb 2023 22:15:00 +0100 thrift (0.18.0) stable; urgency=low * update to 0.18.0 -- Apache Thrift Developers Mon, 06 Feb 2023 23:30:00 +0100 thrift (0.17.0) stable; urgency=low * update to 0.17.0 -- Apache Thrift Developers Tue, 30 Aug 2022 23:00:00 +0200 thrift (0.16.0) stable; urgency=low * update to 0.16.0 -- Apache Thrift Developers Wed, 20 Jan 2022 21:00:00 +0100 thrift (0.15.0) stable; urgency=low * update to 0.15.0 -- Apache Thrift Developers Wed, 03 Aug 2021 23:00:00 +0100 thrift (0.14.2) stable; urgency=low * update to 0.14.2 -- Apache Thrift Developers Wed, 11 Jun 2021 01:00:00 +0100 thrift (0.14.1) stable; urgency=low * update to 0.14.1 -- Apache Thrift Developers Tue, 02 Mar 2021 21:00:00 +0100 thrift (0.14.0) stable; urgency=low * update to 0.14.0 -- Apache Thrift Developers Thu, 04 Feb 2021 17:00:00 -0500 thrift (0.13.0) stable; urgency=low * update to 0.13.0 -- Apache Thrift Developers Wed, 11 Nov 2019 12:00:00 -0500 thrift (0.12.0) stable; urgency=low * update to 0.12.0 -- Apache Thrift Developers Wed, 28 Dec 2018 12:00:00 -0500 thrift (0.11.0) stable; urgency=low * update to 0.11.0 -- Jake Farrell Wed, 07 Dec 2017 20:07:00 -0500 thrift (0.10.0) stable; urgency=low * update to 0.10.0 -- Jake Farrell Wed, 03 Jan 2017 16:52:00 -0500 thrift (0.9.3) stable; urgency=low * update to 0.9.3 -- Jake Farrell Wed, 11 Oct 2015 17:22:00 -0500 thrift (0.9.0) stable; urgency=low * update to 0.9.0 -- Jake Farrell Wed, 10 Oct 2012 12:00:00 -0500 thrift (0.7.0) stable; urgency=low * update to 0.7.0 -- Jake Farrell Tue, 10 Aug 2011 17:01:53 -0500 thrift (0.7.0-dev1) stable; urgency=low * added glib * fix location of libthrift.jar -- Roger Meier Tue, 12 Apr 2011 21:41:18 +0200 thrift (0.6.0-dev1) stable; urgency=low * update version field * added debian folder to thrift/contrib * changed a few details in control file * update copyright file -- Roger Meier Tue, 14 Dec 2010 12:12:33 -0800 thrift (0.5.0+nmu2) stable; urgency=low * Non-maintainer upload. * Merged THRIFT-71_v9.patch to skip ./bootstrap.sh if not exists. https://issues.apache.org/jira/secure/attachment/12465360/THRIFT-71_v9.patch -- Yamashita Yuu Tue, 07 Dec 2010 15:00:55 +0900 thrift (0.5.0+nmu1) stable; urgency=low * Non-maintainer upload. * Imported package information for php5-thrift from https://github.com/simplegeo/thrift. -- Yamashita Yuu Tue, 07 Dec 2010 01:00:17 +0900 thrift (0.5.0) stable; urgency=low * update to 0.5.0 -- Roger Meier Fri, 08 Oct 2010 11:23:53 +0200 thrift (0.4.0) stable; urgency=low * update to 0.4.0 -- Roger Meier Sun, 22 Aug 2010 21:26:00 +0100 thrift (0.2008.12.30~8.04) hardy; urgency=low * Initial release. -- Esteve Fernandez Thu, 15 Jan 2009 11:34:24 +0100 thrift-0.19.0/debian/libthrift-dev.install0000644000000000000000000000006714303740367020466 0ustar00rootroot00000000000000usr/lib/*.a usr/lib/*.la usr/lib/pkgconfig usr/include thrift-0.19.0/debian/rules0000777000000000000000000001566714303472263015430 0ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # # Modified to make a template file for a multi-binary package with separated # build-arch and build-indep targets by Bill Allombert 2001 # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # This has to be exported to make some magic below work. export DH_OPTIONS PYVERS := $(shell pyversions -r) export CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS) export CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) export CXXFLAGS:=$(shell dpkg-buildflags --get CXXFLAGS) export LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) configure: configure-stamp configure-stamp: dh_testdir # Add here commands to configure the package. if [ -f bootstrap.sh ]; then $(CURDIR)/bootstrap.sh; fi $(CURDIR)/configure --prefix=/usr --enable-plugin=no touch configure-stamp #Architecture build: build-arch build-indep # Tests disabled # $(MAKE) -C test check build-arch: build-arch-stamp $(CURDIR)/compiler/cpp/thrift build-arch-stamp: configure-stamp # Compile compiler $(MAKE) -C $(CURDIR)/compiler/cpp # Compile C++ library $(MAKE) -C $(CURDIR)/lib/cpp # Compile C (glib) library $(MAKE) -C $(CURDIR)/lib/c_glib # Python library cd $(CURDIR)/lib/py && \ for py in $(PYVERS); do \ $$py setup.py build; \ $$py-dbg setup.py build; \ done # PHP cd $(CURDIR)/lib/php/src/ext/thrift_protocol && \ phpize && \ ./configure && $(MAKE) touch $@ build-indep: build-indep-stamp build-indep-stamp: configure-stamp $(CURDIR)/compiler/cpp/thrift # Add here commands to compile the indep part of the package. #$(MAKE) doc # Java cd $(CURDIR)/lib/java && \ gradle --no-daemon -Prelease=true jar # C# $(MAKE) -C $(CURDIR)/lib/netstd # Ruby $(MAKE) -C $(CURDIR)/lib/rb # Perl $(MAKE) -C $(CURDIR)/lib/perl INSTALLDIRS=vendor touch $@ clean: dh_testdir dh_testroot rm -f build-arch-stamp build-indep-stamp configure-stamp cd $(CURDIR)/lib/py && python setup.py clean --all # Add here commands to clean up after the build process. -$(MAKE) clean dh_clean install: install-indep install-arch install-indep: dh_testdir dh_testroot dh_prep -i dh_installdirs -i # Add here commands to install the indep part of the package into # debian/-doc. #INSTALLDOC# # Java mkdir -p $(CURDIR)/debian/libthrift-java/usr/share/java/ && \ cp $(CURDIR)/lib/java/build/libs/libthrift*.jar \ $(CURDIR)/debian/libthrift-java/usr/share/java/ # Ruby mkdir -p $(CURDIR)/debian/ruby-thrift/usr/lib/ruby/1.9.1 && \ cp $(CURDIR)/lib/rb/lib/thrift.rb \ $(CURDIR)/debian/ruby-thrift/usr/lib/ruby/1.9.1 cp -r $(CURDIR)/lib/rb/lib/thrift \ $(CURDIR)/debian/ruby-thrift/usr/lib/ruby/1.9.1 # C# mkdir -p $(CURDIR)/debian/libthrift-netstd/usr/lib/cli/thrift/ && \ cp $(CURDIR)/lib/netstd/Thrift/bin/Release/netstandard2.0/Thrift.dll \ $(CURDIR)/debian/libthrift-netstd/usr/lib/cli/thrift/Thrift.dll # Perl $(MAKE) -C $(CURDIR)/lib/perl install DESTDIR=$(CURDIR)/debian/libthrift-perl mkdir -p $(CURDIR)/debian/libthrift-perl/usr/share mv $(CURDIR)/debian/libthrift-perl/usr/local/lib/perl5 $(CURDIR)/debian/libthrift-perl/usr/share rmdir $(CURDIR)/debian/libthrift-perl/usr/local/lib rmdir $(CURDIR)/debian/libthrift-perl/usr/local dh_install -i install-arch: dh_testdir dh_testroot dh_clean -k -s dh_installdirs -s # Add here commands to install the arch part of the package into # debian/tmp. #$(MAKE) DESTDIR=$(CURDIR)/debian/thrift install # Compiler mkdir -p $(CURDIR)/debian/thrift-compiler/usr/bin && \ cp $(CURDIR)/compiler/cpp/thrift \ $(CURDIR)/debian/thrift-compiler/usr/bin/thrift && \ rmdir $(CURDIR)/debian/thrift-compiler/usr/sbin # Python cd $(CURDIR)/lib/py && \ python2 setup.py install --install-layout=deb --no-compile --root=$(CURDIR)/debian/python-thrift && \ python2-dbg setup.py install --install-layout=deb --no-compile --root=$(CURDIR)/debian/python-thrift-dbg && \ python3 setup.py install --install-layout=deb --no-compile --root=$(CURDIR)/debian/python3-thrift && \ python3-dbg setup.py install --install-layout=deb --no-compile --root=$(CURDIR)/debian/python3-thrift-dbg find $(CURDIR)/debian/python-thrift -name "*.py[co]" -print0 | xargs -0 rm -f find $(CURDIR)/debian/python-thrift -name "__pycache__" -print0 | xargs -0 rm -fr find $(CURDIR)/debian/python-thrift-dbg -name "__pycache__" -print0 | xargs -0 rm -fr find $(CURDIR)/debian/python-thrift-dbg -name "*.py[co]" -print0 | xargs -0 rm -f find $(CURDIR)/debian/python-thrift-dbg -name "*.py" -print0 | xargs -0 rm -f find $(CURDIR)/debian/python-thrift-dbg -name "*.egg-info" -print0 | xargs -0 rm -rf find $(CURDIR)/debian/python-thrift-dbg -depth -type d -empty -exec rmdir {} \; find $(CURDIR)/debian/python3-thrift -name "*.py[co]" -print0 | xargs -0 rm -f find $(CURDIR)/debian/python3-thrift -name "__pycache__" -print0 | xargs -0 rm -fr find $(CURDIR)/debian/python3-thrift-dbg -name "__pycache__" -print0 | xargs -0 rm -fr find $(CURDIR)/debian/python3-thrift-dbg -name "*.py[co]" -print0 | xargs -0 rm -f find $(CURDIR)/debian/python3-thrift-dbg -name "*.py" -print0 | xargs -0 rm -f find $(CURDIR)/debian/python3-thrift-dbg -name "*.egg-info" -print0 | xargs -0 rm -rf find $(CURDIR)/debian/python3-thrift-dbg -depth -type d -empty -exec rmdir {} \; # PHP mkdir -p $(CURDIR)/debian/php5-thrift cd $(CURDIR)/lib/php && \ $(MAKE) DESTDIR=$(CURDIR)/debian/php5-thrift install # C++ and C (glib) mkdir -p $(CURDIR)/debian/tmp; \ cd $(CURDIR)/lib/cpp && \ $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install cd $(CURDIR)/lib/c_glib && \ $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install dh_install --sourcedir=debian/tmp -s # Must not depend on anything. This is to be called by # binary-arch/binary-indep # in another 'make' thread. binary-common: dh_testdir dh_testroot dh_installchangelogs dh_installdocs dh_installexamples dh_installman dh_link dh_strip -plibthrift0 --dbg-package=libthrift0-dbg dh_strip -ppython-thrift --dbg-package=python-thrift-dbg dh_strip -ppython3-thrift --dbg-package=python3-thrift-dbg dh_strip -pthrift-compiler dh_compress dh_fixperms dh_makeshlibs dh_installdeb dh_perl dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb # Build architecture independent packages using the common target. binary-indep: build-indep install-indep $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common # Build architecture dependent packages using the common target. binary-arch: build-arch install-arch echo "php:Depends=phpapi-$(shell php-config5 --phpapi)" > $(CURDIR)/debian/substvars $(MAKE) -f debian/rules DH_OPTIONS=-s binary-common binary: binary-arch binary-indep .PHONY: build clean binary-indep binary-arch binary install install-indep install-arch configure thrift-0.19.0/debian/thrift-doc.docs0000644000000000000000000000001014303740367017234 0ustar00rootroot00000000000000#DOCS# thrift-0.19.0/debian/README.md0000644000000000000000000000131214303740367015604 0ustar00rootroot00000000000000## Some tips on Debian Packaging - Debian New Maintainers' Guide [http://www.debian.org/doc/debian-policy/] - Debian Policy Manual [http://www.debian.org/doc/manuals/maint-guide/] - Machine-readable debian/copyright file [http://dep.debian.net/deps/dep5/] - DebSrc 3.0 guidelines [https://wiki.debian.org/Projects/DebSrc3.0] ## Build using dpkg-buildpackage: ```bash $ dpkg-buildpackage -d -tc -d # do not check build dependencies and conflicts. -tc # clean source tree when finished. ``` ## Update changelog: ```bash $ date -R ``` One can also install `devscripts` package and run: ```bash $ dch -i ``` ## Check packages: ```bash $ dpkg -c *.deb $ lintian *.deb ``` ## TODO Make it perfect! thrift-0.19.0/debian/copyright0000644000000000000000000000763214370300523016261 0ustar00rootroot00000000000000This package was debianized by Thrift Developer's . This package and the Debian packaging is licensed under the Apache License, see `/usr/share/common-licenses/Apache-2.0'. The following information was copied from Apache Thrift LICENSE file. -------------------------------------------------- SOFTWARE DISTRIBUTED WITH THRIFT: The Apache Thrift software includes a number of subcomponents with separate copyright notices and license terms. Your use of the source code for the these subcomponents is subject to the terms and conditions of the following licenses. -------------------------------------------------- Portions of the following files are licensed under the MIT License: lib/erl/Makefile.am Please see doc/licenses/otp-base-license.txt for the full terms of this license. -------------------------------------------------- The following files contain some portions of code contributed under the Thrift Software License (see doc/licenses/old-thrift-license.txt), and relicensed under the Apache 2.0 License: compiler/cpp/Makefile.am compiler/cpp/src/thrift/generate/t_cpp_generator.cc compiler/cpp/src/thrift/generate/t_netstd_generator.cc compiler/cpp/src/thrift/generate/t_erl_generator.cc compiler/cpp/src/thrift/generate/t_hs_generator.cc compiler/cpp/src/thrift/generate/t_java_generator.cc compiler/cpp/src/thrift/generate/t_ocaml_generator.cc compiler/cpp/src/thrift/generate/t_perl_generator.cc compiler/cpp/src/thrift/generate/t_php_generator.cc compiler/cpp/src/thrift/generate/t_py_generator.cc compiler/cpp/src/thrift/generate/t_rb_generator.cc compiler/cpp/src/thrift/generate/t_st_generator.cc compiler/cpp/src/thrift/generate/t_xsd_generator.cc compiler/cpp/src/thrift/main.cc compiler/cpp/src/thrift/parse/t_field.h compiler/cpp/src/thrift/parse/t_program.h compiler/cpp/src/thrift/platform.h compiler/cpp/src/thrift/thriftl.ll compiler/cpp/src/thrift/thrifty.yy lib/netstd/Thrift/Protocol/TBinaryProtocol.cs lib/netstd/Thrift/Protocol/Entities/TField.cs lib/netstd/Thrift/Protocol/Entities/TList.cs lib/netstd/Thrift/Protocol/Entities/TMap.cs lib/netstd/Thrift/Protocol/Entities/TMessage.cs lib/netstd/Thrift/Protocol/Entities/TMessageType.cs lib/netstd/Thrift/Protocol/TProtocol.cs lib/netstd/Thrift/Protocol/TProtocolException.cs lib/netstd/Thrift/Protocol/TProtocolFactory.cs lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs lib/netstd/Thrift/Protocol/Entities/TSet.cs lib/netstd/Thrift/Protocol/Entities/TStruct.cs lib/netstd/Thrift/Protocol/Entities/TType.cs lib/netstd/Thrift/Server/TServer.cs lib/netstd/Thrift/Server/TSimpleAsyncServer.cs lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs lib/netstd/Thrift/TApplicationException.cs lib/netstd/Thrift/Thrift.csproj lib/netstd/Thrift.sln lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs lib/netstd/Thrift/Transport/Server/TServerTransport.cs lib/netstd/Thrift/Transport/Client/TSocketTransport.cs lib/netstd/Thrift/Transport/Client/TStreamTransport.cs lib/netstd/Thrift/Transport/TTransport.cs lib/netstd/Thrift/Transport/TTransportException.cs lib/netstd/Thrift/Transport/TTransportFactory.cs lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj lib/rb/lib/thrift.rb lib/st/README.md lib/st/thrift.st lib/cpp/test/OptionalRequiredTest.cpp test/OptionalRequiredTest.thrift test/ThriftTest.thrift test/v0.16/ThriftTest.thrift -------------------------------------------------- For the aclocal/ax_boost_base.m4 and contrib/fb303/aclocal/ax_boost_base.m4 components: # Copyright (c) 2007 Thomas Porschberg # # 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. thrift-0.19.0/debian/dirs0000644000000000000000000000002114303740367015205 0ustar00rootroot00000000000000usr/bin usr/sbin thrift-0.19.0/debian/docs0000644000000000000000000000001214303740367015174 0ustar00rootroot00000000000000README.md thrift-0.19.0/debian/libthrift0.install0000644000000000000000000000017014303740367017765 0ustar00rootroot00000000000000usr/lib/libthrift.so* usr/lib/libthrift-*.so* usr/lib/libthriftnb*.so* usr/lib/libthriftqt*.so* usr/lib/libthriftz*.so* thrift-0.19.0/debian/substvars0000644000000000000000000000003414303740367016304 0ustar00rootroot00000000000000php:Depends=phpapi-20121212 thrift-0.19.0/debian/php5-thrift.dirs0000644000000000000000000000002014303740367017355 0ustar00rootroot00000000000000etc/php5/conf.d thrift-0.19.0/debian/thrift-doc.install0000644000000000000000000000001014303740367017752 0ustar00rootroot00000000000000#DOCS# thrift-0.19.0/debian/control0000644000000000000000000002111714370300523015723 0ustar00rootroot00000000000000Source: thrift Section: devel Priority: extra Build-Depends: dotnet-runtime-6.0, dotnet-sdk-6.0, debhelper (>= 9), build-essential, python-dev, ant, ruby-dev | ruby1.9.1-dev, ruby-bundler ,autoconf, automake, pkg-config, libtool, bison, flex, libboost-dev | libboost1.56-dev | libboost1.63-all-dev, python-all, python-setuptools, python-all-dev, python-all-dbg, python3-all, python3-setuptools, python3-all-dev, python3-all-dbg, openjdk-17-jdk | openjdk-17-jdk-headless | default-jdk, libboost-test-dev | libboost-test1.56-dev | libboost-test1.63-dev, libevent-dev, libssl-dev, perl (>= 5.8.0-7), php (>= 5), php-dev (>= 5), libglib2.0-dev, qtchooser, qtbase5-dev-tools Maintainer: Thrift Developer's Homepage: http://thrift.apache.org/ Vcs-Git: https://github.com/apache/thrift.git Vcs-Browser: https://github.com/apache/thrift Standards-Version: 3.9.7 X-Python-Version: >= 2.6 X-Python3-Version: >= 3.3 Package: thrift-compiler Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Compiler for Thrift definition files Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Thrift compiler that is used for translating from .thrift files (containing the definitions) to the language binding for the supported languages. Package: python-thrift Architecture: any Section: python Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, python-six Recommends: python-twisted-web, python-backports.ssl-match-hostname, python-ipaddress Provides: ${python:Provides} Description: Python bindings for Thrift (Python 2) Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Python bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Python classes, and then the modules in this package will allow you to use those classes in your programs. . This package installs the library for Python 2. Package: python-thrift-dbg Architecture: any Section: debug Depends: ${shlibs:Depends}, ${misc:Depends}, python-thrift (= ${binary:Version}), python-all-dbg Provides: ${python:Provides} Description: Python bindings for Thrift (debug version) Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Python bindings for Thrift with debugging symbols. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Python classes, and then the modules in this package will allow you to use those classes in your programs. Package: python3-thrift Architecture: any Section: python Depends: ${python3:Depends}, ${shlibs:Depends}, ${misc:Depends}, python3-six Recommends: python3-twisted-web Provides: ${python:Provides} Description: Python bindings for Thrift (Python 3) Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Python bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Python classes, and then the modules in this package will allow you to use those classes in your programs. . This package installs the library for Python 3. Package: python3-thrift-dbg Architecture: any Section: debug Depends: ${shlibs:Depends}, ${misc:Depends}, python3-thrift (= ${binary:Version}), python3-all-dbg Provides: ${python:Provides} Description: Python bindings for Thrift (debug version) Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Python bindings for Thrift with debugging symbols. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Python classes, and then the modules in this package will allow you to use those classes in your programs. Package: ruby-thrift Architecture: all Section: libs Depends: ruby | ruby-interpreter, ${shlibs:Depends}, ${misc:Depends} Provides: libthrift-ruby Replaces: libthrift-ruby Breaks: libthrift-ruby Description: Ruby bindings for Thrift Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Ruby bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Ruby classes, and then the modules in this package will allow you to use those classes in your programs. Package: libthrift-java Architecture: all Section: java Depends: ${misc:Depends} Description: Java bindings for Thrift Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Java bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Java classes, and then the modules in this package will allow you to use those classes in your programs. Package: libthrift-netstd Architecture: all Section: netstd Depends: dotnet-runtime-6.0, ${misc:Depends} Description: NET Standard bindings for Thrift Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the NET Standard bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to C# classes, and then the modules in this package will allow you to use those classes in your programs. Package: libthrift-perl Architecture: all Section: perl Depends: perl (>= 5.8.0-7), ${misc:Depends} Description: Perl bindings for Thrift Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the Perl bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to Perl classes, and then the modules in this package will allow you to use those classes in your programs. Package: libthrift0 Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Thrift C++ library Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the runtime libraries needed for C++ applications using Thrift. Package: libthrift0-dbg Architecture: any Section: debug Depends: ${shlibs:Depends}, ${misc:Depends}, libthrift0 (= ${binary:Version}) Description: Thrift C++ library debug symbols Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the debug symbols for the Thrift C++ runtime libraries. Package: libthrift-dev Architecture: any Section: libdevel Depends: ${shlibs:Depends}, ${misc:Depends}, libthrift0 (= ${binary:Version}), libglib2.0-dev Description: Thrift C++ library (development headers) Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the development libraries required for writing C++ applications using Thrift. Package: php5-thrift Architecture: any Section: php Depends: ${php:Depends}, ${shlibs:Depends}, ${misc:Depends} Provides: ${php:Provides} Description: PHP bindings for Thrift Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . This package contains the PHP bindings for Thrift. thrift-0.19.0/debian/compat0000644000000000000000000000000214303740367015526 0ustar00rootroot000000000000009 thrift-0.19.0/composer.json0000644000000000000000000000175214303740367015635 0ustar00rootroot00000000000000{ "name": "apache/thrift", "description": "Apache Thrift RPC system", "homepage": "http://thrift.apache.org", "type": "library", "keywords": ["RPC"], "license": "Apache-2.0", "readme": "README.md", "authors": [ { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", "homepage": "http://thrift.apache.org" } ], "support": { "email": "dev@thrift.apache.org", "issues": "https://issues.apache.org/jira/browse/THRIFT" }, "require": { "php": "^5.5 || ^7.0 || ^8.0" }, "require-dev": { "phpunit/phpunit": "~4.8.36", "squizlabs/php_codesniffer": "3.*" }, "autoload": { "psr-4": {"Thrift\\": "lib/php/lib/"} }, "autoload-dev": { "psr-4": {"Test\\Thrift\\": "lib/php/test/"} }, "minimum-stability": "stable", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } } } thrift-0.19.0/jitpack.yml0000644000000000000000000000007614303740367015261 0ustar00rootroot00000000000000install: - gradle -Prelease=true -p lib/java/ clean install thrift-0.19.0/.flake80000644000000000000000000000024014303740366014254 0ustar00rootroot00000000000000[flake8] exclude = .git,__pycache__,**/gen-*/**,contrib/**,docs/source/conf.py,old,build,dist ignore = W504,E402,E501 max-complexity = 30 max-line-length = 120 thrift-0.19.0/tutorial/0000755000000000000000000000000014472652701014752 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/haxe/0000755000000000000000000000000014472652700015676 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/haxe/make_all.bat0000644000000000000000000000350514303740367020136 0ustar00rootroot00000000000000@echo off rem /* rem * Licensed to the Apache Software Foundation (ASF) under one rem * or more contributor license agreements. See the NOTICE file rem * distributed with this work for additional information rem * regarding copyright ownership. The ASF licenses this file rem * to you under the Apache License, Version 2.0 (the rem * "License"); you may not use this file except in compliance rem * with the License. You may obtain a copy of the License at rem * rem * http://www.apache.org/licenses/LICENSE-2.0 rem * rem * Unless required by applicable law or agreed to in writing, rem * software distributed under the License is distributed on an rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY rem * KIND, either express or implied. See the License for the rem * specific language governing permissions and limitations rem * under the License. rem */ setlocal if "%HOMEDRIVE%"=="" goto MISSINGVARS if "%HOMEPATH%"=="" goto MISSINGVARS if "%HAXEPATH%"=="" goto NOTINSTALLED set path=%HAXEPATH%;%HAXEPATH%\..\neko;%path% rem # invoke Thrift comnpiler thrift -r -gen haxe ..\tutorial.thrift if errorlevel 1 goto STOP rem # invoke Haxe compiler for all targets for %%a in (*.hxml) do ( rem * filter Python, as it is not supported by Haxe 3.1.3 (but will be in 3.1.4) if not "%%a"=="python.hxml" ( echo -------------------------- echo Building %%a ... echo -------------------------- haxe --cwd . %%a ) ) echo. echo done. pause goto eof :NOTINSTALLED echo FATAL: Either Haxe is not installed, or the HAXEPATH variable is not set. pause goto eof :MISSINGVARS echo FATAL: Unable to locate home folder. echo. echo Both HOMEDRIVE and HOMEPATH need to be set to point to your Home folder. echo The current values are: echo HOMEDRIVE=%HOMEDRIVE% echo HOMEPATH=%HOMEPATH% pause goto eof :STOP pause goto eof :eof thrift-0.19.0/tutorial/haxe/php.hxml0000644000000000000000000000207514370300523017351 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #PHP target -php bin/php/ -D php-front=Main-debug.php # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce full thrift-0.19.0/tutorial/haxe/router.php0000644000000000000000000000171414303740367017732 0ustar00rootroot00000000000000(); public function new() { } public function ping() : Void { trace("ping()"); } public function add( num1 : haxe.Int32, num2 : haxe.Int32) : haxe.Int32 { trace('add( $num1, $num2)'); return num1 + num2; } public function calculate( logid : haxe.Int32, work : Work) : haxe.Int32 { trace('calculate( $logid, '+work.op+","+work.num1+","+work.num2+")"); var val : haxe.Int32 = 0; switch (work.op) { case Operation.ADD: val = work.num1 + work.num2; case Operation.SUBTRACT: val = work.num1 - work.num2; case Operation.MULTIPLY: val = work.num1 * work.num2; case Operation.DIVIDE: if (work.num2 == 0) { var io = new InvalidOperation(); io.whatOp = work.op; io.why = "Cannot divide by 0"; throw io; } val = Std.int( work.num1 / work.num2); default: var io = new InvalidOperation(); io.whatOp = work.op; io.why = "Unknown operation"; throw io; } var entry = new SharedStruct(); entry.key = logid; entry.value = '$val'; log.set(logid, entry); return val; } public function getStruct( key : haxe.Int32) : SharedStruct { trace('getStruct($key)'); return log.get(key); } // oneway method, no args public function zip() : Void { trace("zip()"); } } thrift-0.19.0/tutorial/haxe/cpp.hxml0000644000000000000000000000217514370300523017345 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #CPP target -cpp bin #To produce 64 bit binaries the file should define the HXCPP_M64 compile variable: #-D HXCPP_M64 # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/tutorial/haxe/javascript.hxml0000644000000000000000000000252114370300523020724 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #JavaScript target -js bin/Tutorial.js #You can use -D source-map-content (requires Haxe 3.1+) to have the .hx #files directly embedded into the map file, this way you only have to #upload it, and it will be always in sync with the compiled .js even if #you modify your .hx files. -D source-map-content # libs -lib uuid #Generate source map and add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/tutorial/haxe/make_all.sh0000644000000000000000000000222214303740367017775 0ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # invoke Thrift comnpiler thrift -r -gen haxe ../tutorial.thrift # output folder if [ ! -d bin ]; then mkdir bin fi # invoke Haxe compoiler for target in *.hxml; do echo -------------------------- echo Building ${target} ... echo -------------------------- if [ ! -d bin/${target} ]; then mkdir bin/${target} fi haxe --cwd . ${target} done #eof thrift-0.19.0/tutorial/haxe/project.hide0000644000000000000000000000522414303740367020202 0ustar00rootroot00000000000000{ "type" : 0 ,"target" : 4 ,"name" : "Apache Thrift Tutorial" ,"main" : null ,"projectPackage" : "" ,"company" : "Apache Software Foundation (ASF)" ,"license" : "Apache License, Version 2.0" ,"url" : "http://www.apache.org/licenses/LICENSE-2.0" ,"targetData" : [ { "pathToHxml" : "flash.hxml" ,"runActionType" : 1 ,"runActionText" : "bin/Tutorial.swf" } ,{ "pathToHxml" : "javascript.hxml" ,"runActionType" : 1 ,"runActionText" : "bin\\index.html" } ,{ "pathToHxml" : "neko.hxml" ,"runActionType" : 2 ,"runActionText" : "neko bin/Tutorial.n" } ,{ "pathToHxml" : "php.hxml" } ,{ "pathToHxml" : "cpp.hxml" ,"runActionType" : 2 ,"runActionText" : "bin/Main-debug.exe" } ,{ "pathToHxml" : "java.hxml" } ,{ "pathToHxml" : "csharp.hxml" ,"runActionType" : 2 ,"runActionText" : "bin\\Tutorial.exe\\bin\\Main-Debug.exe" } ,{ "pathToHxml" : "python.hxml" ,"runActionType" : 2 ,"runActionText" : "python bin/Tutorial.py" } ] ,"files" : [ { "path" : "src\\org\\apache\\thrift\\server\\TServer.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 76 } ,{ "path" : "src\\org\\apache\\thrift\\server\\TSimpleServer.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 100 } ,{ "path" : "src\\shared\\SharedServiceProcessor.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 20 } ,{ "path" : "src\\tutorial\\CalculatorProcessor.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 79 } ,{ "path" : "src\\Main.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 0 } ] ,"activeFile" : "src\\Main.hx" ,"openFLTarget" : null ,"openFLBuildMode" : "Debug" ,"runActionType" : null ,"runActionText" : null ,"buildActionCommand" : null ,"hiddenItems" : [ ] ,"showHiddenItems" : false }thrift-0.19.0/tutorial/haxe/php-web-server.hxml0000644000000000000000000000214214370300523021423 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #PHP target -php bin/php-web-server/ -D php-front=Main-debug.php #defines -D phpwebserver # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce full thrift-0.19.0/tutorial/haxe/neko.hxml0000644000000000000000000000205014370300523017507 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #neko target -neko bin/Tutorial.n # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/tutorial/haxe/python.hxml0000644000000000000000000000205514370300523020101 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #Python target -python bin/Tutorial.py # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/tutorial/haxe/Makefile.in0000644000000000000000000004520514472652522017753 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/haxe ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ BIN_CPP = bin/Main-debug BIN_PHP = bin/php/Main-debug.php BIN_PHP_WEB = bin/php-web-server/Main-debug.php EXTRA_DIST = \ src \ cpp.hxml \ csharp.hxml \ flash.hxml \ java.hxml \ javascript.hxml \ php-web-server.hxml \ neko.hxml \ php.hxml \ python.hxml \ router.php \ project.hide \ Tutorial.hxproj \ make_all.bat \ make_all.sh all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/haxe/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/haxe/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-haxe/tutorial/calculator.hx gen-haxe/shared/shared_service.hx: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen haxe -r $< all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB) check: gen-haxe/tutorial/calculator.hx $(BIN_CPP): \ src/*.hx \ ../../lib/haxe/src/org/apache/thrift/**/*.hx \ gen-haxe/tutorial/calculator.hx $(HAXE) --cwd . cpp.hxml $(BIN_PHP): \ src/*.hx \ ../../lib/haxe/src/org/apache/thrift/**/*.hx \ gen-haxe/tutorial/calculator.hx $(HAXE) --cwd . php.hxml $(BIN_PHP_WEB): \ src/*.hx \ ../../lib/haxe/src/org/apache/thrift/**/*.hx \ gen-haxe/tutorial/calculator.hx $(HAXE) --cwd . php-web-server.hxml tutorialserver: all $(BIN_CPP) server tutorialserver_php: all php -f $(BIN_PHP) server tutorialclient: all $(BIN_CPP) tutorialclient_php: all php -f $(BIN_PHP) tutorialsecureserver: all $(BIN_CPP) server secure tutorialsecureserver_php: all php -f $(BIN_PHP) server secure tutorialsecureclient: all $(BIN_CPP) secure tutorialsecureclient_php: all php -f $(BIN_PHP) secure tutorialserver_php_http: all php -S 127.0.0.1:9090 router.php tutorialclient_http: all $(BIN_CPP) client http clean-local: $(RM) -r gen-haxe bin # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/haxe/Tutorial.hxproj0000644000000000000000000000374114303740367020742 0ustar00rootroot00000000000000 thrift -r -gen haxe ../tutorial.thrift thrift-0.19.0/tutorial/Makefile.am0000644000000000000000000000355514370300523017003 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = if MINGW # do nothing, just build the compiler else if WITH_C_GLIB SUBDIRS += c_glib endif if WITH_CPP SUBDIRS += cpp endif if WITH_D SUBDIRS += d endif if WITH_JAVA SUBDIRS += java SUBDIRS += js endif if WITH_PYTHON SUBDIRS += py SUBDIRS += py.twisted SUBDIRS += py.tornado endif if WITH_RUBY SUBDIRS += rb endif if WITH_HAXE SUBDIRS += haxe endif if WITH_DOTNET SUBDIRS += netstd endif if WITH_GO SUBDIRS += go endif if WITH_NODEJS SUBDIRS += nodejs endif if WITH_DART SUBDIRS += dart endif if WITH_RS SUBDIRS += rs endif if WITH_CL SUBDIRS += cl endif if WITH_PERL SUBDIRS += perl endif if WITH_PHP SUBDIRS += php endif if WITH_SWIFT SUBDIRS += swift endif # # generate html for tutorial.thrift # all-local: $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/tutorial/tutorial.thrift clean-local: rm -rf $(top_srcdir)/tutorial/gen-html endif # Any folders or files not listed above being added to SUBDIR need to be placed here in # EXTRA_DIST to be included in the release EXTRA_DIST = \ d \ delphi \ erl \ ocaml \ shared.thrift \ tutorial.thrift \ README.md thrift-0.19.0/tutorial/tutorial.thrift0000644000000000000000000001153214370300523020026 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ # Thrift Tutorial # Mark Slee (mcslee@facebook.com) # # This file aims to teach you how to use Thrift, in a .thrift file. Neato. The # first thing to notice is that .thrift files support standard shell comments. # This lets you make your thrift file executable and include your Thrift build # step on the top line. And you can place comments like this anywhere you like. # # Before running this file, you will need to have installed the thrift compiler # into /usr/local/bin. /** * The first thing to know about are types. The available types in Thrift are: * * bool Boolean, one byte * i8 (byte) Signed 8-bit integer * i16 Signed 16-bit integer * i32 Signed 32-bit integer * i64 Signed 64-bit integer * double 64-bit floating point value * string String * binary Blob (byte array) * map Map from one type to another * list Ordered list of one type * set Set of unique elements of one type * * Did you also notice that Thrift supports C style comments? */ // Just in case you were wondering... yes. We support simple C comments too. /** * Thrift files can reference other Thrift files to include common struct * and service definitions. These are found using the current path, or by * searching relative to any paths specified with the -I compiler flag. * * Included objects are accessed using the name of the .thrift file as a * prefix. i.e. shared.SharedObject */ include "shared.thrift" /** * Thrift files can namespace, package, or prefix their output in various * target languages. */ namespace cl tutorial namespace cpp tutorial namespace d tutorial namespace dart tutorial namespace java tutorial namespace php tutorial namespace perl tutorial namespace haxe tutorial namespace netstd tutorial /** * Thrift lets you do typedefs to get pretty names for your types. Standard * C style here. */ typedef i32 MyInteger /** * Thrift also lets you define constants for use across languages. Complex * types and structs are specified using JSON notation. */ const i32 INT32CONSTANT = 9853 const map MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} /** * You can define enums, which are just 32 bit integers. Values are optional * and start at 1 if not supplied, C style again. */ enum Operation { ADD = 1, SUBTRACT = 2, MULTIPLY = 3, DIVIDE = 4 } /** * Structs are the basic complex data structures. They are comprised of fields * which each have an integer identifier, a type, a symbolic name, and an * optional default value. * * Fields can be declared "optional", which ensures they will not be included * in the serialized output if they aren't set. Note that this requires some * manual management in some languages. */ struct Work { 1: i32 num1 = 0, 2: i32 num2, 3: Operation op, 4: optional string comment, } /** * Structs can also be exceptions, if they are nasty. */ exception InvalidOperation { 1: i32 whatOp, 2: string why } /** * Ahh, now onto the cool part, defining a service. Services just need a name * and can optionally inherit from another service using the extends keyword. */ service Calculator extends shared.SharedService { /** * A method definition looks like C code. It has a return type, arguments, * and optionally a list of exceptions that it may throw. Note that argument * lists and exception lists are specified using the exact same syntax as * field lists in struct or exception definitions. */ void ping(), i32 add(1:i32 num1, 2:i32 num2), i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), /** * This method has a oneway modifier. That means the client only makes * a request and does not listen for any response at all. Oneway methods * must be void. */ oneway void zip() } /** * That just about covers the basics. Take a look in the test/ folder for more * detailed examples. After you run this file, your generated code shows up * in folders with names gen-. The generated code isn't too scary * to look at. It even has pretty indentation. */ thrift-0.19.0/tutorial/py/0000755000000000000000000000000014472652677015416 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/py/Makefile.am0000644000000000000000000000217214303740367017437 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-py/tutorial/Calculator.py gen-py/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen py -r $< all-local: gen-py/tutorial/Calculator.py tutorialserver: all ${PYTHON} PythonServer.py tutorialclient: all ${PYTHON} PythonClient.py clean-local: $(RM) -r gen-* EXTRA_DIST = \ setup.cfg \ PythonServer.py \ PythonClient.py thrift-0.19.0/tutorial/py/setup.cfg0000644000000000000000000000002714303740367017221 0ustar00rootroot00000000000000[flake8] ignore = E402 thrift-0.19.0/tutorial/py/Makefile.in0000644000000000000000000004275014472652522017460 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/py ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ setup.cfg \ PythonServer.py \ PythonClient.py all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/py/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/py/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-py/tutorial/Calculator.py gen-py/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen py -r $< all-local: gen-py/tutorial/Calculator.py tutorialserver: all ${PYTHON} PythonServer.py tutorialclient: all ${PYTHON} PythonClient.py clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/py/PythonClient.py0000777000000000000000000000446214062750227020406 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import sys import glob sys.path.append('gen-py') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from tutorial.ttypes import InvalidOperation, Operation, Work from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol def main(): # Make socket transport = TSocket.TSocket('localhost', 9090) # Buffering is critical. Raw sockets are very slow transport = TTransport.TBufferedTransport(transport) # Wrap in a protocol protocol = TBinaryProtocol.TBinaryProtocol(transport) # Create a client to use the protocol encoder client = Calculator.Client(protocol) # Connect! transport.open() client.ping() print('ping()') sum_ = client.add(1, 1) print('1+1=%d' % sum_) work = Work() work.op = Operation.DIVIDE work.num1 = 1 work.num2 = 0 try: quotient = client.calculate(1, work) print('Whoa? You know how to divide by zero?') print('FYI the answer is %d' % quotient) except InvalidOperation as e: print('InvalidOperation: %r' % e) work.op = Operation.SUBTRACT work.num1 = 15 work.num2 = 10 diff = client.calculate(1, work) print('15-10=%d' % diff) log = client.getStruct(1) print('Check log: %s' % log.value) # Close! transport.close() if __name__ == '__main__': try: main() except Thrift.TException as tx: print('%s' % tx.message) thrift-0.19.0/tutorial/py/PythonServer.py0000777000000000000000000000563514062750227020441 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import sys sys.path.append('gen-py') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from tutorial.ttypes import InvalidOperation, Operation from shared.ttypes import SharedStruct from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.server import TServer class CalculatorHandler: def __init__(self): self.log = {} def ping(self): print('ping()') def add(self, n1, n2): print('add(%d,%d)' % (n1, n2)) return n1 + n2 def calculate(self, logid, work): print('calculate(%d, %r)' % (logid, work)) if work.op == Operation.ADD: val = work.num1 + work.num2 elif work.op == Operation.SUBTRACT: val = work.num1 - work.num2 elif work.op == Operation.MULTIPLY: val = work.num1 * work.num2 elif work.op == Operation.DIVIDE: if work.num2 == 0: raise InvalidOperation(work.op, 'Cannot divide by 0') val = work.num1 / work.num2 else: raise InvalidOperation(work.op, 'Invalid operation') log = SharedStruct() log.key = logid log.value = '%d' % (val) self.log[logid] = log return val def getStruct(self, key): print('getStruct(%d)' % (key)) return self.log[key] def zip(self): print('zip()') if __name__ == '__main__': handler = CalculatorHandler() processor = Calculator.Processor(handler) transport = TSocket.TServerSocket(host='127.0.0.1', port=9090) tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) # You could do one of these for a multithreaded server # server = TServer.TThreadedServer( # processor, transport, tfactory, pfactory) # server = TServer.TThreadPoolServer( # processor, transport, tfactory, pfactory) print('Starting the server...') server.serve() print('done.') thrift-0.19.0/tutorial/swift/0000755000000000000000000000000014472652701016106 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/swift/Makefile.am0000644000000000000000000000206314370300523020130 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Common thrift code generation rules # gen_swift: $(THRIFT) --gen swift -r -o Sources/Common $(top_srcdir)/tutorial/tutorial.thrift tutorial: gen_swift swift run TutorialRunner tutorialserver: gen_swift swift run TutorialServer tutorialclient: gen_swift swift run TutorialClient thrift-0.19.0/tutorial/swift/Makefile.in0000644000000000000000000004257314472652523020170 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/swift ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/swift/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/swift/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile # # Common thrift code generation rules # gen_swift: $(THRIFT) --gen swift -r -o Sources/Common $(top_srcdir)/tutorial/tutorial.thrift tutorial: gen_swift swift run TutorialRunner tutorialserver: gen_swift swift run TutorialServer tutorialclient: gen_swift swift run TutorialClient # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/py.twisted/0000755000000000000000000000000014472652677017100 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/py.twisted/Makefile.am0000644000000000000000000000221114303740367021113 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-py/tutorial/Calculator.py gen-py/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen py:twisted -r $< all-local: gen-py/tutorial/Calculator.py tutorialserver: all ${PYTHON} PythonServer.py tutorialclient: all ${PYTHON} PythonClient.py clean-local: $(RM) -r gen-* EXTRA_DIST = \ PythonClient.py \ PythonServer.py \ PythonServer.tac thrift-0.19.0/tutorial/py.twisted/PythonServer.tac0000777000000000000000000000324214062750227022232 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from twisted.application import internet, service from thrift.transport import TTwisted import glob import sys sys.path.append('gen-py.twisted') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from PythonServer import CalculatorHandler from thrift.protocol import TBinaryProtocol def make_application(): application = service.Application('CalcServer') handler = CalculatorHandler() processor = Calculator.Processor(handler) serverFactory = TTwisted.ThriftServerFactory( processor, TBinaryProtocol.TBinaryProtocolFactory()) calcService = internet.TCPServer(9090, serverFactory) multiService = service.MultiService() calcService.setServiceParent(multiService) multiService.setServiceParent(application) return application if __name__ == '__main__': application = make_application() thrift-0.19.0/tutorial/py.twisted/Makefile.in0000644000000000000000000004301714472652522021137 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/py.twisted ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ PythonClient.py \ PythonServer.py \ PythonServer.tac all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/py.twisted/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/py.twisted/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-py/tutorial/Calculator.py gen-py/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen py:twisted -r $< all-local: gen-py/tutorial/Calculator.py tutorialserver: all ${PYTHON} PythonServer.py tutorialclient: all ${PYTHON} PythonClient.py clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/py.twisted/PythonClient.py0000777000000000000000000000442714062750227022071 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import sys sys.path.append('gen-py.twisted') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from tutorial.ttypes import InvalidOperation, Operation, Work from twisted.internet.defer import inlineCallbacks from twisted.internet import reactor from twisted.internet.protocol import ClientCreator from thrift.transport import TTwisted from thrift.protocol import TBinaryProtocol @inlineCallbacks def main(client): yield client.ping() print('ping()') sum = yield client.add(1, 1) print(('1+1=%d' % (sum))) work = Work() work.op = Operation.DIVIDE work.num1 = 1 work.num2 = 0 try: quotient = yield client.calculate(1, work) print('Whoa? You know how to divide by zero?') print('FYI the answer is %d' % quotient) except InvalidOperation as e: print(('InvalidOperation: %r' % e)) work.op = Operation.SUBTRACT work.num1 = 15 work.num2 = 10 diff = yield client.calculate(1, work) print(('15-10=%d' % (diff))) log = yield client.getStruct(1) print(('Check log: %s' % (log.value))) reactor.stop() if __name__ == '__main__': d = ClientCreator(reactor, TTwisted.ThriftClientProtocol, Calculator.Client, TBinaryProtocol.TBinaryProtocolFactory(), ).connectTCP("127.0.0.1", 9090) d.addCallback(lambda conn: conn.client) d.addCallback(main) reactor.run() thrift-0.19.0/tutorial/py.twisted/PythonServer.py0000777000000000000000000000513414062750227022115 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import sys sys.path.append('gen-py.twisted') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from tutorial.ttypes import InvalidOperation, Operation from shared.ttypes import SharedStruct from zope.interface import implements from twisted.internet import reactor from thrift.transport import TTwisted from thrift.protocol import TBinaryProtocol class CalculatorHandler: implements(Calculator.Iface) def __init__(self): self.log = {} def ping(self): print('ping()') def add(self, n1, n2): print('add(%d,%d)' % (n1, n2)) return n1 + n2 def calculate(self, logid, work): print('calculate(%d, %r)' % (logid, work)) if work.op == Operation.ADD: val = work.num1 + work.num2 elif work.op == Operation.SUBTRACT: val = work.num1 - work.num2 elif work.op == Operation.MULTIPLY: val = work.num1 * work.num2 elif work.op == Operation.DIVIDE: if work.num2 == 0: raise InvalidOperation(work.op, 'Cannot divide by 0') val = work.num1 / work.num2 else: raise InvalidOperation(work.op, 'Invalid operation') log = SharedStruct() log.key = logid log.value = '%d' % (val) self.log[logid] = log return val def getStruct(self, key): print('getStruct(%d)' % (key)) return self.log[key] def zip(self): print('zip()') if __name__ == '__main__': handler = CalculatorHandler() processor = Calculator.Processor(handler) pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = reactor.listenTCP( 9090, TTwisted.ThriftServerFactory(processor, pfactory), interface="127.0.0.1") reactor.run() thrift-0.19.0/tutorial/c_glib/0000755000000000000000000000000014472652676016204 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/c_glib/Makefile.am0000644000000000000000000000504214303740367020225 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = \ gen-c_glib/calculator.h \ gen-c_glib/shared_service.h \ gen-c_glib/shared_types.h \ gen-c_glib/tutorial_types.h AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) @GCOV_CFLAGS@ -I$(top_builddir)/lib/c_glib/src/thrift AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@ noinst_LTLIBRARIES = \ libtutorialgencglib.la nodist_libtutorialgencglib_la_SOURCES = \ gen-c_glib/calculator.c \ gen-c_glib/calculator.h \ gen-c_glib/shared_service.c \ gen-c_glib/shared_service.h \ gen-c_glib/shared_types.c \ gen-c_glib/shared_types.h \ gen-c_glib/tutorial_types.c \ gen-c_glib/tutorial_types.h libtutorialgencglib_la_LIBADD = \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la libtutorialgencglib_la_CFLAGS = \ $(AM_CFLAGS) -Wno-unused-function noinst_PROGRAMS = \ tutorial_server \ tutorial_client tutorial_server_SOURCES = \ c_glib_server.c tutorial_server_LDFLAGS = $(OPENSSL_LIBS) tutorial_server_LDADD = \ libtutorialgencglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la tutorial_client_SOURCES = \ c_glib_client.c tutorial_client_LDADD = \ libtutorialgencglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la gen-c_glib/calculator.c gen-c_glib/calculator.h gen-c_glib/shared_service.c gen-c_glib/shared_service.h gen-c_glib/shared_types.c gen-c_glib/shared_types.h gen-c_glib/tutorial_types.c gen-c_glib/tutorial_types.h: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen c_glib -r $< clean-local: $(RM) gen-c_glib/* tutorialserver: all ./tutorial_server tutorialclient: all ./tutorial_client EXTRA_DIST = \ c_glib_server.c \ c_glib_client.c thrift-0.19.0/tutorial/c_glib/c_glib_server.c0000644000000000000000000004443414303740367021152 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "gen-c_glib/calculator.h" G_BEGIN_DECLS /* In the C (GLib) implementation of Thrift, the actual work done by a server---that is, the code that runs when a client invokes a service method---is defined in a separate "handler" class that implements the service interface. Here we define the TutorialCalculatorHandler class, which implements the CalculatorIf interface and provides the behavior expected by tutorial clients. (Typically this code would be placed in its own module but for clarity this tutorial is presented entirely in a single file.) For each service the Thrift compiler generates an abstract base class from which handler implementations should inherit. In our case TutorialCalculatorHandler inherits from CalculatorHandler, defined in gen-c_glib/calculator.h. If you're new to GObject, try not to be intimidated by the quantity of code here---much of it is boilerplate and can mostly be copied-and-pasted from existing work. For more information refer to the GObject Reference Manual, available online at https://developer.gnome.org/gobject/. */ #define TYPE_TUTORIAL_CALCULATOR_HANDLER \ (tutorial_calculator_handler_get_type ()) #define TUTORIAL_CALCULATOR_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ TYPE_TUTORIAL_CALCULATOR_HANDLER, \ TutorialCalculatorHandler)) #define TUTORIAL_CALCULATOR_HANDLER_CLASS(c) \ (G_TYPE_CHECK_CLASS_CAST ((c), \ TYPE_TUTORIAL_CALCULATOR_HANDLER, \ TutorialCalculatorHandlerClass)) #define IS_TUTORIAL_CALCULATOR_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ TYPE_TUTORIAL_CALCULATOR_HANDLER)) #define IS_TUTORIAL_CALCULATOR_HANDLER_CLASS(c) \ (G_TYPE_CHECK_CLASS_TYPE ((c), \ TYPE_TUTORIAL_CALCULATOR_HANDLER)) #define TUTORIAL_CALCULATOR_HANDLER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ TYPE_TUTORIAL_CALCULATOR_HANDLER, \ TutorialCalculatorHandlerClass)) struct _TutorialCalculatorHandler { CalculatorHandler parent_instance; /* private */ GHashTable *log; }; typedef struct _TutorialCalculatorHandler TutorialCalculatorHandler; struct _TutorialCalculatorHandlerClass { CalculatorHandlerClass parent_class; }; typedef struct _TutorialCalculatorHandlerClass TutorialCalculatorHandlerClass; GType tutorial_calculator_handler_get_type (void); G_END_DECLS /* ---------------------------------------------------------------- */ /* The implementation of TutorialCalculatorHandler follows. */ G_DEFINE_TYPE (TutorialCalculatorHandler, tutorial_calculator_handler, TYPE_CALCULATOR_HANDLER) /* Each of a handler's methods accepts at least two parameters: A pointer to the service-interface implementation (the handler object itself) and a handle to a GError structure to receive information about any error that occurs. On success, a handler method returns TRUE. A return value of FALSE indicates an error occurred and the error parameter has been set. (Methods should not return FALSE without first setting the error parameter.) */ static gboolean tutorial_calculator_handler_ping (CalculatorIf *iface, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); puts ("ping()"); return TRUE; } /* Service-method parameters are passed through as parameters to the handler method. If the service method returns a value an output parameter, _return, is additionally passed to the handler method. This parameter should be set appropriately before the method returns, whenever it succeeds. The return value from this method happens to be of a base type, i32, but note if a method returns a complex type such as a map or list *_return will point to a pre-allocated data structure that does not need to be re-allocated and should not be destroyed. */ static gboolean tutorial_calculator_handler_add (CalculatorIf *iface, gint32 *_return, const gint32 num1, const gint32 num2, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("add(%d,%d)\n", num1, num2); *_return = num1 + num2; return TRUE; } /* Any handler method can return a ThriftApplicationException to the client by setting its error parameter appropriately and returning FALSE. See the ThriftApplicationExceptionError enumeration defined in thrift_application_exception.h for a list of recognized exception types (GError codes). If a service method can also throw a custom exception (that is, one defined in the .thrift file) an additional output parameter will be provided (here, "ouch") to hold an instance of the exception, when necessary. Note there will be a separate parameter added for each type of exception the method can throw. Unlike return values, exception objects are never pre-created; this is always the responsibility of the handler method. */ static gboolean tutorial_calculator_handler_calculate (CalculatorIf *iface, gint32 *_return, const gint32 logid, const Work *w, InvalidOperation **ouch, GError **error) { TutorialCalculatorHandler *self; gint *log_key; gchar log_value[12]; SharedStruct *log_struct; gint num1; gint num2; Operation op; gboolean result = TRUE; THRIFT_UNUSED_VAR (error); g_return_val_if_fail (IS_TUTORIAL_CALCULATOR_HANDLER (iface), FALSE); self = TUTORIAL_CALCULATOR_HANDLER (iface); /* Remember: Exception objects are never pre-created */ g_assert (*ouch == NULL); /* Fetch the contents of our Work parameter. Note that integer properties of thirty-two bits or fewer in width are _always_ of type gint, regardless of the range of values they hold. A common error is trying to retrieve, say, a structure member defined in the .thrift file as type i16 into a variable of type gint16, which will clobber variables adjacent on the stack. Remember: If you're retrieving an integer property the receiving variable must be of either type gint or gint64, as appropriate. */ g_object_get ((Work *)w, "num1", &num1, "num2", &num2, "op", &op, NULL); printf ("calculate(%d,{%d,%d,%d})\n", logid, op, num1, num2); switch (op) { case OPERATION_ADD: *_return = num1 + num2; break; case OPERATION_SUBTRACT: *_return = num1 - num2; break; case OPERATION_MULTIPLY: *_return = num1 * num2; break; case OPERATION_DIVIDE: if (num2 == 0) { /* For each custom exception type a subclass of ThriftStruct is generated by the Thrift compiler. Throw an exception by setting the corresponding output parameter to a new instance of its type and returning FALSE. */ *ouch = g_object_new (TYPE_INVALID_OPERATION, "whatOp", op, "why", g_strdup ("Cannot divide by 0"), NULL); result = FALSE; /* Note the call to g_strdup above: All the memory used by a ThriftStruct's properties belongs to the object itself and will be freed on destruction. Removing this call to g_strdup will lead to a segmentation fault as the object tries to release memory allocated statically to the program. */ } else { *_return = num1 / num2; } break; default: *ouch = g_object_new (TYPE_INVALID_OPERATION, "whatOp", op, "why", g_strdup ("Invalid Operation"), NULL); result = FALSE; } /* On success, log a record of the result to our hash table */ if (result) { log_key = g_malloc (sizeof *log_key); *log_key = logid; snprintf (log_value, sizeof log_value, "%d", *_return); log_struct = g_object_new (TYPE_SHARED_STRUCT, "key", *log_key, "value", g_strdup (log_value), NULL); g_hash_table_replace (self->log, log_key, log_struct); } return result; } /* A one-way method has the same signature as an equivalent, regular method that returns no value. */ static gboolean tutorial_calculator_handler_zip (CalculatorIf *iface, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); puts ("zip()"); return TRUE; } /* As specified in the .thrift file (tutorial.thrift), the Calculator service extends the SharedService service. Correspondingly, in the generated code the Calculator interface, CalculatorIf, extends the SharedService interface, SharedServiceIf, and subclasses of CalculatorHandler should implement its methods as well. Here we provide an implementation for the getStruct method from the parent service. */ static gboolean tutorial_calculator_handler_get_struct (SharedServiceIf *iface, SharedStruct **_return, const gint32 key32, GError **error) { gint key = (gint)key32; TutorialCalculatorHandler *self; SharedStruct *log_struct; gint log_key; gchar *log_value; THRIFT_UNUSED_VAR (error); g_return_val_if_fail (IS_TUTORIAL_CALCULATOR_HANDLER (iface), FALSE); self = TUTORIAL_CALCULATOR_HANDLER (iface); /* Remember: Complex return types are always pre-created and need only be populated */ g_assert (*_return != NULL); printf ("getStruct(%d)\n", key); /* If the key exists in our log, return the corresponding logged data (or an empty SharedStruct structure if it does not). Incidentally, note we _must_ here copy the values from the hash table into the return structure. All memory used by the return structure belongs to the structure itself and will be freed once a response is sent to the client. If we merely freed *_return and set it to point to our hash-table entry, that would mean memory would be released (effectively, data erased) out of the hash table! */ log_struct = g_hash_table_lookup (self->log, &key); if (log_struct != NULL) { g_object_get (log_struct, "key", &log_key, "value", &log_value, NULL); g_object_set (*_return, "key", log_key, "value", g_strdup (log_value), NULL); } return TRUE; } /* TutorialCalculatorHandler's instance finalizer (destructor) */ static void tutorial_calculator_handler_finalize (GObject *object) { TutorialCalculatorHandler *self = TUTORIAL_CALCULATOR_HANDLER (object); /* Free our calculation-log hash table */ g_hash_table_unref (self->log); self->log = NULL; /* Chain up to the parent class */ G_OBJECT_CLASS (tutorial_calculator_handler_parent_class)-> finalize (object); } /* TutorialCalculatorHandler's instance initializer (constructor) */ static void tutorial_calculator_handler_init (TutorialCalculatorHandler *self) { /* Create our calculation-log hash table */ self->log = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_object_unref); } /* TutorialCalculatorHandler's class initializer */ static void tutorial_calculator_handler_class_init (TutorialCalculatorHandlerClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); SharedServiceHandlerClass *shared_service_handler_class = SHARED_SERVICE_HANDLER_CLASS (klass); CalculatorHandlerClass *calculator_handler_class = CALCULATOR_HANDLER_CLASS (klass); /* Register our destructor */ gobject_class->finalize = tutorial_calculator_handler_finalize; /* Register our implementations of CalculatorHandler's methods */ calculator_handler_class->ping = tutorial_calculator_handler_ping; calculator_handler_class->add = tutorial_calculator_handler_add; calculator_handler_class->calculate = tutorial_calculator_handler_calculate; calculator_handler_class->zip = tutorial_calculator_handler_zip; /* Register our implementation of SharedServiceHandler's method */ shared_service_handler_class->get_struct = tutorial_calculator_handler_get_struct; } /* ---------------------------------------------------------------- */ /* That ends the implementation of TutorialCalculatorHandler. Everything below is fairly generic code that sets up a minimal Thrift server for tutorial clients. */ /* Our server object, declared globally so it is accessible within the SIGINT signal handler */ ThriftServer *server = NULL; /* A flag that indicates whether the server was interrupted with SIGINT (i.e. Ctrl-C) so we can tell whether its termination was abnormal */ gboolean sigint_received = FALSE; /* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the server */ static void sigint_handler (int signal_number) { THRIFT_UNUSED_VAR (signal_number); /* Take note we were called */ sigint_received = TRUE; /* Shut down the server gracefully */ if (server != NULL) thrift_server_stop (server); } int main (void) { TutorialCalculatorHandler *handler; CalculatorProcessor *processor; ThriftServerTransport *server_transport; ThriftTransportFactory *transport_factory; ThriftProtocolFactory *protocol_factory; struct sigaction sigint_action; GError *error = NULL; int exit_status = 0; #if (!GLIB_CHECK_VERSION (2, 36, 0)) g_type_init (); #endif /* Create an instance of our handler, which provides the service's methods' implementation */ handler = g_object_new (TYPE_TUTORIAL_CALCULATOR_HANDLER, NULL); /* Create an instance of the service's processor, automatically generated by the Thrift compiler, which parses incoming messages and dispatches them to the appropriate method in the handler */ processor = g_object_new (TYPE_CALCULATOR_PROCESSOR, "handler", handler, NULL); /* Create our server socket, which binds to the specified port and listens for client connections */ server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", 9090, NULL); /* Create our transport factory, used by the server to wrap "raw" incoming connections from the client (in this case with a ThriftBufferedTransport to improve performance) */ transport_factory = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, NULL); /* Create our protocol factory, which determines which wire protocol the server will use (in this case, Thrift's binary protocol) */ protocol_factory = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, NULL); /* Create the server itself */ server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, "processor", processor, "server_transport", server_transport, "input_transport_factory", transport_factory, "output_transport_factory", transport_factory, "input_protocol_factory", protocol_factory, "output_protocol_factory", protocol_factory, NULL); /* Install our SIGINT handler, which handles Ctrl-C being pressed by stopping the server gracefully (not strictly necessary, but a nice touch) */ memset (&sigint_action, 0, sizeof (sigint_action)); sigint_action.sa_handler = sigint_handler; sigint_action.sa_flags = SA_RESETHAND; sigaction (SIGINT, &sigint_action, NULL); /* Start the server, which will run until its stop method is invoked (from within the SIGINT handler, in this case) */ puts ("Starting the server..."); thrift_server_serve (server, &error); /* If the server stopped for any reason other than having been interrupted by the user, report the error */ if (!sigint_received) { g_message ("thrift_server_serve: %s", error != NULL ? error->message : "(null)"); g_clear_error (&error); } puts ("done."); g_object_unref (server); g_object_unref (transport_factory); g_object_unref (protocol_factory); g_object_unref (server_transport); g_object_unref (processor); g_object_unref (handler); return exit_status; } thrift-0.19.0/tutorial/c_glib/Makefile.in0000644000000000000000000010301614472652521020237 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = tutorial_server$(EXEEXT) tutorial_client$(EXEEXT) subdir = tutorial/c_glib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtutorialgencglib_la_DEPENDENCIES = \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la am__dirstamp = $(am__leading_dot)dirstamp nodist_libtutorialgencglib_la_OBJECTS = \ gen-c_glib/libtutorialgencglib_la-calculator.lo \ gen-c_glib/libtutorialgencglib_la-shared_service.lo \ gen-c_glib/libtutorialgencglib_la-shared_types.lo \ gen-c_glib/libtutorialgencglib_la-tutorial_types.lo libtutorialgencglib_la_OBJECTS = \ $(nodist_libtutorialgencglib_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libtutorialgencglib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ PROGRAMS = $(noinst_PROGRAMS) am_tutorial_client_OBJECTS = c_glib_client.$(OBJEXT) tutorial_client_OBJECTS = $(am_tutorial_client_OBJECTS) tutorial_client_DEPENDENCIES = libtutorialgencglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la am_tutorial_server_OBJECTS = c_glib_server.$(OBJEXT) tutorial_server_OBJECTS = $(am_tutorial_server_OBJECTS) tutorial_server_DEPENDENCIES = libtutorialgencglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la tutorial_server_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(tutorial_server_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(nodist_libtutorialgencglib_la_SOURCES) \ $(tutorial_client_SOURCES) $(tutorial_server_SOURCES) DIST_SOURCES = $(tutorial_client_SOURCES) $(tutorial_server_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = \ gen-c_glib/calculator.h \ gen-c_glib/shared_service.h \ gen-c_glib/shared_types.h \ gen-c_glib/tutorial_types.h AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) @GCOV_CFLAGS@ -I$(top_builddir)/lib/c_glib/src/thrift AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@ noinst_LTLIBRARIES = \ libtutorialgencglib.la nodist_libtutorialgencglib_la_SOURCES = \ gen-c_glib/calculator.c \ gen-c_glib/calculator.h \ gen-c_glib/shared_service.c \ gen-c_glib/shared_service.h \ gen-c_glib/shared_types.c \ gen-c_glib/shared_types.h \ gen-c_glib/tutorial_types.c \ gen-c_glib/tutorial_types.h libtutorialgencglib_la_LIBADD = \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la libtutorialgencglib_la_CFLAGS = \ $(AM_CFLAGS) -Wno-unused-function tutorial_server_SOURCES = \ c_glib_server.c tutorial_server_LDFLAGS = $(OPENSSL_LIBS) tutorial_server_LDADD = \ libtutorialgencglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la tutorial_client_SOURCES = \ c_glib_client.c tutorial_client_LDADD = \ libtutorialgencglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la EXTRA_DIST = \ c_glib_server.c \ c_glib_client.c all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/c_glib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/c_glib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } gen-c_glib/$(am__dirstamp): @$(MKDIR_P) gen-c_glib @: > gen-c_glib/$(am__dirstamp) gen-c_glib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) gen-c_glib/$(DEPDIR) @: > gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/libtutorialgencglib_la-calculator.lo: \ gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/libtutorialgencglib_la-shared_service.lo: \ gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/libtutorialgencglib_la-shared_types.lo: \ gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/libtutorialgencglib_la-tutorial_types.lo: \ gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) libtutorialgencglib.la: $(libtutorialgencglib_la_OBJECTS) $(libtutorialgencglib_la_DEPENDENCIES) $(EXTRA_libtutorialgencglib_la_DEPENDENCIES) $(AM_V_CCLD)$(libtutorialgencglib_la_LINK) $(libtutorialgencglib_la_OBJECTS) $(libtutorialgencglib_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list tutorial_client$(EXEEXT): $(tutorial_client_OBJECTS) $(tutorial_client_DEPENDENCIES) $(EXTRA_tutorial_client_DEPENDENCIES) @rm -f tutorial_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tutorial_client_OBJECTS) $(tutorial_client_LDADD) $(LIBS) tutorial_server$(EXEEXT): $(tutorial_server_OBJECTS) $(tutorial_server_DEPENDENCIES) $(EXTRA_tutorial_server_DEPENDENCIES) @rm -f tutorial_server$(EXEEXT) $(AM_V_CCLD)$(tutorial_server_LINK) $(tutorial_server_OBJECTS) $(tutorial_server_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f gen-c_glib/*.$(OBJEXT) -rm -f gen-c_glib/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_glib_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/c_glib_server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-calculator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-tutorial_types.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< gen-c_glib/libtutorialgencglib_la-calculator.lo: gen-c_glib/calculator.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -MT gen-c_glib/libtutorialgencglib_la-calculator.lo -MD -MP -MF gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-calculator.Tpo -c -o gen-c_glib/libtutorialgencglib_la-calculator.lo `test -f 'gen-c_glib/calculator.c' || echo '$(srcdir)/'`gen-c_glib/calculator.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-calculator.Tpo gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-calculator.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gen-c_glib/calculator.c' object='gen-c_glib/libtutorialgencglib_la-calculator.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -c -o gen-c_glib/libtutorialgencglib_la-calculator.lo `test -f 'gen-c_glib/calculator.c' || echo '$(srcdir)/'`gen-c_glib/calculator.c gen-c_glib/libtutorialgencglib_la-shared_service.lo: gen-c_glib/shared_service.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -MT gen-c_glib/libtutorialgencglib_la-shared_service.lo -MD -MP -MF gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_service.Tpo -c -o gen-c_glib/libtutorialgencglib_la-shared_service.lo `test -f 'gen-c_glib/shared_service.c' || echo '$(srcdir)/'`gen-c_glib/shared_service.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_service.Tpo gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_service.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gen-c_glib/shared_service.c' object='gen-c_glib/libtutorialgencglib_la-shared_service.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -c -o gen-c_glib/libtutorialgencglib_la-shared_service.lo `test -f 'gen-c_glib/shared_service.c' || echo '$(srcdir)/'`gen-c_glib/shared_service.c gen-c_glib/libtutorialgencglib_la-shared_types.lo: gen-c_glib/shared_types.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -MT gen-c_glib/libtutorialgencglib_la-shared_types.lo -MD -MP -MF gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_types.Tpo -c -o gen-c_glib/libtutorialgencglib_la-shared_types.lo `test -f 'gen-c_glib/shared_types.c' || echo '$(srcdir)/'`gen-c_glib/shared_types.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_types.Tpo gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-shared_types.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gen-c_glib/shared_types.c' object='gen-c_glib/libtutorialgencglib_la-shared_types.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -c -o gen-c_glib/libtutorialgencglib_la-shared_types.lo `test -f 'gen-c_glib/shared_types.c' || echo '$(srcdir)/'`gen-c_glib/shared_types.c gen-c_glib/libtutorialgencglib_la-tutorial_types.lo: gen-c_glib/tutorial_types.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -MT gen-c_glib/libtutorialgencglib_la-tutorial_types.lo -MD -MP -MF gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-tutorial_types.Tpo -c -o gen-c_glib/libtutorialgencglib_la-tutorial_types.lo `test -f 'gen-c_glib/tutorial_types.c' || echo '$(srcdir)/'`gen-c_glib/tutorial_types.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-tutorial_types.Tpo gen-c_glib/$(DEPDIR)/libtutorialgencglib_la-tutorial_types.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gen-c_glib/tutorial_types.c' object='gen-c_glib/libtutorialgencglib_la-tutorial_types.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtutorialgencglib_la_CFLAGS) $(CFLAGS) -c -o gen-c_glib/libtutorialgencglib_la-tutorial_types.lo `test -f 'gen-c_glib/tutorial_types.c' || echo '$(srcdir)/'`gen-c_glib/tutorial_types.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf gen-c_glib/.libs gen-c_glib/_libs style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f gen-c_glib/$(DEPDIR)/$(am__dirstamp) -rm -f gen-c_glib/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) gen-c_glib/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) gen-c_glib/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-local clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am style-am style-local tags tags-am \ uninstall uninstall-am .PRECIOUS: Makefile gen-c_glib/calculator.c gen-c_glib/calculator.h gen-c_glib/shared_service.c gen-c_glib/shared_service.h gen-c_glib/shared_types.c gen-c_glib/shared_types.h gen-c_glib/tutorial_types.c gen-c_glib/tutorial_types.h: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen c_glib -r $< clean-local: $(RM) gen-c_glib/* tutorialserver: all ./tutorial_server tutorialclient: all ./tutorial_client # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/c_glib/c_glib_client.c0000644000000000000000000001345514303740367021121 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include "gen-c_glib/calculator.h" int main (void) { ThriftSocket *socket; ThriftTransport *transport; ThriftProtocol *protocol; CalculatorIf *client; GError *error = NULL; InvalidOperation *invalid_operation = NULL; Work *work; gint32 sum; gint32 diff; int exit_status = 0; #if (!GLIB_CHECK_VERSION (2, 36, 0)) g_type_init (); #endif socket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", "port", 9090, NULL); transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport", socket, NULL); protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL); thrift_transport_open (transport, &error); /* In the C (GLib) implementation of Thrift, service methods on the server are accessed via a generated client class that implements the service interface. In this tutorial, we access a Calculator service through an instance of CalculatorClient, which implements CalculatorIf. */ client = g_object_new (TYPE_CALCULATOR_CLIENT, "input_protocol", protocol, "output_protocol", protocol, NULL); /* Each of the client methods requires at least two parameters: A pointer to the client-interface implementation (the client object), and a handle to a GError structure to receive information about any error that occurs. On success, client methods return TRUE. A return value of FALSE indicates an error occurred and the error parameter has been set. */ if (!error && calculator_if_ping (client, &error)) { puts ("ping()"); } /* Service methods that return a value do so by passing the result back via an output parameter (here, "sum"). */ if (!error && calculator_if_add (client, &sum, 1, 1, &error)) { printf ("1+1=%d\n", sum); } /* Thrift structs are implemented as GObjects, with each of the struct's members exposed as an object property. */ work = g_object_new (TYPE_WORK, NULL); if (!error) { g_object_set (work, "num1", 1, "num2", 0, "op", OPERATION_DIVIDE, NULL); /* Exceptions are passed back from service methods in a manner similar to return values. */ if (calculator_if_calculate (client, NULL, 1, work, &invalid_operation, &error)) { puts ("Whoa? We can divide by zero!"); } else { if (invalid_operation) { gchar *why; /* Like structs, exceptions are implemented as objects with properties. */ g_object_get (invalid_operation, "why", &why, NULL); printf ("InvalidOperation: %s\n", why); if (why != NULL) g_free (why); g_object_unref (invalid_operation); invalid_operation = NULL; } g_clear_error (&error); } } if (!error) { /* Struct objects can be reused across method invocations. */ g_object_set (work, "num1", 15, "num2", 10, "op", OPERATION_SUBTRACT, NULL); if (calculator_if_calculate (client, &diff, 1, work, &invalid_operation, &error)) { printf ("15-10=%d\n", diff); } } g_object_unref (work); if (!error) { SharedStruct *shared_struct; gchar *value; shared_struct = g_object_new (TYPE_SHARED_STRUCT, NULL); /* As defined in the Thrift file, the Calculator service extends the SharedService service. Correspondingly, in the generated code CalculatorIf inherits from SharedServiceIf, and the parent service's methods are accessible through a simple cast. */ if (shared_service_client_get_struct (SHARED_SERVICE_IF (client), &shared_struct, 1, &error)) { g_object_get (shared_struct, "value", &value, NULL); printf ("Check log: %s\n", value); g_free (value); } g_object_unref (shared_struct); } if (error) { printf ("ERROR: %s\n", error->message); g_clear_error (&error); exit_status = 1; } thrift_transport_close (transport, NULL); g_object_unref (client); g_object_unref (protocol); g_object_unref (transport); g_object_unref (socket); return exit_status; } thrift-0.19.0/tutorial/d/0000777000000000000000000000000014472652607015206 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/d/Makefile.am0000644000000000000000000000326114303740367017232 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # LIB_D_DIR = $(top_srcdir)/lib/d GEN_SRC = gen-d/share/SharedService.d gen-d/share/shared_types.d \ gen-d/tutorial/tutorial_types.d gen-d/tutorial/Calculator.d $(GEN_SRC): $(top_srcdir)/tutorial/tutorial.thrift $(top_builddir)/compiler/cpp/thrift --gen d -r $< server: server.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd server.d ${GEN_SRC} client: client.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd client.d ${GEN_SRC} PROGS = server client if WITH_D_EVENT_TESTS async_client: async_client.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd-event -L-lthriftd -L-levent async_client.d ${GEN_SRC} PROGS += async_client endif all-local: $(PROGS) clean: $(RM) -f $(PROGS) $(RM) -r gen-d/ find . -type f -name '*.o' | xargs rm -f dist-hook: $(RM) -f $(distdir)/$(PROGS) $(RM) -r $(distdir)/gen-d/ find $(destdir) -type f -name '*.o' | xargs rm -f thrift-0.19.0/tutorial/d/Makefile0000644000000000000000000004501614472652607016650 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # tutorial/d/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu am__append_1 = async_client subdir = tutorial/d ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/tutorial/d abs_srcdir = /thrift/src/tutorial/d abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. LIB_D_DIR = $(top_srcdir)/lib/d GEN_SRC = gen-d/share/SharedService.d gen-d/share/shared_types.d \ gen-d/tutorial/tutorial_types.d gen-d/tutorial/Calculator.d PROGS = server client $(am__append_1) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/d/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/d/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile $(GEN_SRC): $(top_srcdir)/tutorial/tutorial.thrift $(top_builddir)/compiler/cpp/thrift --gen d -r $< server: server.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd server.d ${GEN_SRC} client: client.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd client.d ${GEN_SRC} async_client: async_client.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd-event -L-lthriftd -L-levent async_client.d ${GEN_SRC} all-local: $(PROGS) clean: $(RM) -f $(PROGS) $(RM) -r gen-d/ find . -type f -name '*.o' | xargs rm -f dist-hook: $(RM) -f $(distdir)/$(PROGS) $(RM) -r $(distdir)/gen-d/ find $(destdir) -type f -name '*.o' | xargs rm -f # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/d/server.d0000644000000000000000000000563014303740367016653 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ module server; import std.conv : to; import std.stdio; import thrift.codegen.processor; import thrift.protocol.binary; import thrift.server.simple; import thrift.server.transport.socket; import thrift.transport.buffered; import share.SharedService; import share.shared_types; import tutorial.Calculator; import tutorial.tutorial_types; /** * The actual implementation of the Calculator interface that is called by * the server to answer the requests. */ class CalculatorHandler : Calculator { void ping() { writeln("ping()"); } int add(int n1, int n2) { writefln("add(%s,%s)", n1, n2); return n1 + n2; } int calculate(int logid, ref const(Work) work) { writefln("calculate(%s, {%s, %s, %s})", logid, work.op, work.num1, work.num2); int val; switch (work.op) { case Operation.ADD: val = work.num1 + work.num2; break; case Operation.SUBTRACT: val = work.num1 - work.num2; break; case Operation.MULTIPLY: val = work.num1 * work.num2; break; case Operation.DIVIDE: if (work.num2 == 0) { auto io = new InvalidOperation(); io.whatOp = work.op; io.why = "Cannot divide by 0"; throw io; } val = work.num1 / work.num2; break; default: auto io = new InvalidOperation(); io.whatOp = work.op; io.why = "Invalid Operation"; throw io; } auto ss = SharedStruct(); ss.key = logid; ss.value = to!string(val); log[logid] = ss; return val; } SharedStruct getStruct(int logid) { writefln("getStruct(%s)", logid); return log[logid]; } void zip() { writeln("zip()"); } protected: SharedStruct[int] log; } void main() { auto protocolFactory = new TBinaryProtocolFactory!(); auto processor = new TServiceProcessor!Calculator(new CalculatorHandler); auto serverTransport = new TServerSocket(9090); auto transportFactory = new TBufferedTransportFactory; auto server = new TSimpleServer( processor, serverTransport, transportFactory, protocolFactory); writeln("Starting the server on port 9090..."); server.serve(); writeln("done."); } thrift-0.19.0/tutorial/d/client.d0000644000000000000000000000350214303740367016617 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ module client; import std.stdio; import thrift.base; import thrift.codegen.client; import thrift.protocol.binary; import thrift.transport.buffered; import thrift.transport.socket; import tutorial.Calculator; import tutorial.tutorial_types; void main() { auto socket = new TSocket("localhost", 9090); auto transport = new TBufferedTransport(socket); auto protocol = tBinaryProtocol(transport); auto client = tClient!Calculator(protocol); transport.open(); client.ping(); writeln("ping()"); int sum = client.add(1, 1); writefln("1 + 1 = %s", sum); auto work = Work(); work.op = Operation.DIVIDE; work.num1 = 1; work.num2 = 0; try { int quotient = client.calculate(1, work); writeln("Whoa we can divide by 0"); } catch (InvalidOperation io) { writeln("Invalid operation: " ~ io.why); } work.op = Operation.SUBTRACT; work.num1 = 15; work.num2 = 10; int diff = client.calculate(1, work); writefln("15 - 10 = %s", diff); auto log = client.getStruct(1); writefln("Check log: %s", log.value); } thrift-0.19.0/tutorial/d/async_client.d0000644000000000000000000000465414303740367020025 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ module async_client; import std.exception; import std.stdio; import thrift.async.libevent; import thrift.async.socket; import thrift.base; import thrift.codegen.async_client; import thrift.protocol.binary; import thrift.transport.buffered; import tutorial.Calculator; import tutorial.tutorial_types; void main() { auto asyncManager = new TLibeventAsyncManager; // If we are done, gracefully stop the async manager to avoid hanging on // appplication shutdown. scope (exit) asyncManager.stop(); auto socket = new TAsyncSocket(asyncManager, "localhost", 9090); auto client = new TAsyncClient!Calculator( socket, new TBufferedTransportFactory, new TBinaryProtocolFactory!TBufferedTransport ); socket.open(); // Invoke all the methods. auto pingResult = client.ping(); auto addResult = client.add(1, 1); auto work = Work(); work.op = Operation.DIVIDE; work.num1 = 1; work.num2 = 0; auto quotientResult = client.calculate(1, work); work.op = Operation.SUBTRACT; work.num1 = 15; work.num2 = 10; auto diffResult = client.calculate(1, work); auto logResult = client.getStruct(1); // Await the responses. pingResult.waitGet(); writeln("ping()"); int sum = addResult.waitGet(); writefln("1 + 1 = %s", sum); try { quotientResult.waitGet(); writeln("Whoa we can divide by 0"); } catch (InvalidOperation io) { writeln("Invalid operation: " ~ io.why); } writefln("15 - 10 = %s", diffResult.waitGet()); // TFuture is implicitly convertible to the result type via »alias this«, // for which it (eagerly, of course) awaits completion. writefln("Check log: %s", logResult.value); } thrift-0.19.0/tutorial/d/Makefile.in0000644000000000000000000004423614472652522017254 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_D_EVENT_TESTS_TRUE@am__append_1 = async_client subdir = tutorial/d ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ LIB_D_DIR = $(top_srcdir)/lib/d GEN_SRC = gen-d/share/SharedService.d gen-d/share/shared_types.d \ gen-d/tutorial/tutorial_types.d gen-d/tutorial/Calculator.d PROGS = server client $(am__append_1) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/d/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/d/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile $(GEN_SRC): $(top_srcdir)/tutorial/tutorial.thrift $(top_builddir)/compiler/cpp/thrift --gen d -r $< server: server.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd server.d ${GEN_SRC} client: client.d $(GEN_SRC) $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd client.d ${GEN_SRC} @WITH_D_EVENT_TESTS_TRUE@async_client: async_client.d $(GEN_SRC) @WITH_D_EVENT_TESTS_TRUE@ $(DMD) -I${LIB_D_DIR}/src -L-L${LIB_D_DIR} -L-lthriftd-event -L-lthriftd -L-levent async_client.d ${GEN_SRC} all-local: $(PROGS) clean: $(RM) -f $(PROGS) $(RM) -r gen-d/ find . -type f -name '*.o' | xargs rm -f dist-hook: $(RM) -f $(distdir)/$(PROGS) $(RM) -r $(distdir)/gen-d/ find $(destdir) -type f -name '*.o' | xargs rm -f # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/README.md0000644000000000000000000000260514303740367016233 0ustar00rootroot00000000000000Thrift Tutorial License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Tutorial ======== 1) First things first, you'll need to install the Thrift compiler and the language libraries. Do that using the instructions in the top level README.md file. 2) Read tutorial.thrift to learn about the syntax of a Thrift file 3) Compile the code for the language of your choice: ``` $ thrift $ thrift -r --gen cpp tutorial.thrift ``` 4) Take a look at the generated code. 5) Look in the language directories for sample client/server code. 6) That's about it for now. This tutorial is intentionally brief. It should be just enough to get you started and ready to build your own project. thrift-0.19.0/tutorial/js/0000755000000000000000000000000014472652677015402 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/js/Makefile.am0000644000000000000000000000221714303742350017415 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean all-local: $(ANT) $(ANT_FLAGS) compile check-local: all $(ANT) $(ANT_FLAGS) test tutorialserver: all $(ANT) $(ANT_FLAGS) tutorialserver EXTRA_DIST = \ build.properties \ build.xml \ src \ tutorial.html thrift-0.19.0/tutorial/js/src/0000777000000000000000000000000014303740367016160 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/js/src/Httpd.java0000644000000000000000000003030114303740367020077 0ustar00rootroot00000000000000/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ import java.io.File; import java.io.IOException; import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.URLDecoder; import java.util.Locale; import org.apache.http.ConnectionClosedException; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpServerConnection; import org.apache.http.HttpStatus; import org.apache.http.MethodNotSupportedException; import org.apache.http.entity.ContentProducer; import org.apache.http.entity.EntityTemplate; import org.apache.http.entity.FileEntity; import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.impl.DefaultHttpServerConnection; import org.apache.http.impl.NoConnectionReuseStrategy; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.BasicHttpProcessor; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpProcessor; import org.apache.http.protocol.HttpRequestHandler; import org.apache.http.protocol.HttpRequestHandlerRegistry; import org.apache.http.protocol.HttpService; import org.apache.http.util.EntityUtils; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TJSONProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TMemoryBuffer; // Generated code import tutorial.*; import shared.*; import java.util.HashMap; /** * Basic, yet fully functional and spec compliant, HTTP/1.1 file server. *

* Please note the purpose of this application is demonstrate the usage of * HttpCore APIs. It is NOT intended to demonstrate the most efficient way of * building an HTTP file server. * * */ public class Httpd { public static void main(String[] args) throws Exception { if (args.length < 1) { System.err.println("Please specify document root directory"); System.exit(1); } Thread t = new RequestListenerThread(8088, args[0]); t.setDaemon(false); t.start(); } static class HttpFileHandler implements HttpRequestHandler { private final String docRoot; public HttpFileHandler(final String docRoot) { super(); this.docRoot = docRoot; } public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException { String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH); if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) { throw new MethodNotSupportedException(method + " method not supported"); } String target = request.getRequestLine().getUri(); if (request instanceof HttpEntityEnclosingRequest && target.equals("/thrift/service/tutorial/")) { HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); byte[] entityContent = EntityUtils.toByteArray(entity); System.out.println("Incoming content: " + new String(entityContent)); final String output = this.thriftRequest(entityContent); System.out.println("Outgoing content: "+output); EntityTemplate body = new EntityTemplate(new ContentProducer() { public void writeTo(final OutputStream outstream) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); writer.write(output); writer.flush(); } }); body.setContentType("text/html; charset=UTF-8"); response.setEntity(body); } else { final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8")); if (!file.exists()) { response.setStatusCode(HttpStatus.SC_NOT_FOUND); EntityTemplate body = new EntityTemplate(new ContentProducer() { public void writeTo(final OutputStream outstream) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); writer.write("

"); writer.write("File "); writer.write(file.getPath()); writer.write(" not found"); writer.write("

"); writer.flush(); } }); body.setContentType("text/html; charset=UTF-8"); response.setEntity(body); System.out.println("File " + file.getPath() + " not found"); } else if (!file.canRead() || file.isDirectory()) { response.setStatusCode(HttpStatus.SC_FORBIDDEN); EntityTemplate body = new EntityTemplate(new ContentProducer() { public void writeTo(final OutputStream outstream) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); writer.write("

"); writer.write("Access denied"); writer.write("

"); writer.flush(); } }); body.setContentType("text/html; charset=UTF-8"); response.setEntity(body); System.out.println("Cannot read file " + file.getPath()); } else { response.setStatusCode(HttpStatus.SC_OK); FileEntity body = new FileEntity(file, "text/html"); response.setEntity(body); System.out.println("Serving file " + file.getPath()); } } } private String thriftRequest(byte[] input){ try{ //Input TMemoryBuffer inbuffer = new TMemoryBuffer(input.length); inbuffer.write(input); TProtocol inprotocol = new TJSONProtocol(inbuffer); //Output TMemoryBuffer outbuffer = new TMemoryBuffer(100); TProtocol outprotocol = new TJSONProtocol(outbuffer); TProcessor processor = new Calculator.Processor(new CalculatorHandler()); processor.process(inprotocol, outprotocol); byte[] output = new byte[outbuffer.length()]; outbuffer.readAll(output, 0, output.length); return new String(output,"UTF-8"); }catch(Throwable t){ return "Error:"+t.getMessage(); } } } static class RequestListenerThread extends Thread { private final ServerSocket serversocket; private final HttpParams params; private final HttpService httpService; public RequestListenerThread(int port, final String docroot) throws IOException { this.serversocket = new ServerSocket(port); this.params = new BasicHttpParams(); this.params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 1000).setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false).setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1"); // Set up the HTTP protocol processor HttpProcessor httpproc = new BasicHttpProcessor(); // Set up request handlers HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry(); reqistry.register("*", new HttpFileHandler(docroot)); // Set up the HTTP service this.httpService = new HttpService(httpproc, new NoConnectionReuseStrategy(), new DefaultHttpResponseFactory()); this.httpService.setParams(this.params); this.httpService.setHandlerResolver(reqistry); } public void run() { System.out.println("Listening on port " + this.serversocket.getLocalPort()); System.out.println("Point your browser to http://localhost:8088/tutorial/js/tutorial.html"); while (!Thread.interrupted()) { try { // Set up HTTP connection Socket socket = this.serversocket.accept(); DefaultHttpServerConnection conn = new DefaultHttpServerConnection(); System.out.println("Incoming connection from " + socket.getInetAddress()); conn.bind(socket, this.params); // Start worker thread Thread t = new WorkerThread(this.httpService, conn); t.setDaemon(true); t.start(); } catch (InterruptedIOException ex) { break; } catch (IOException e) { System.err.println("I/O error initialising connection thread: " + e.getMessage()); break; } } } } static class WorkerThread extends Thread { private final HttpService httpservice; private final HttpServerConnection conn; public WorkerThread(final HttpService httpservice, final HttpServerConnection conn) { super(); this.httpservice = httpservice; this.conn = conn; } public void run() { System.out.println("New connection thread"); HttpContext context = new BasicHttpContext(null); try { while (!Thread.interrupted() && this.conn.isOpen()) { this.httpservice.handleRequest(this.conn, context); } } catch (ConnectionClosedException ex) { System.err.println("Client closed connection"); } catch (IOException ex) { System.err.println("I/O error: " + ex.getMessage()); } catch (HttpException ex) { System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage()); } finally { try { this.conn.shutdown(); } catch (IOException ignore) { } } } } } thrift-0.19.0/tutorial/js/tutorial.html0000644000000000000000000000756314303740367020131 0ustar00rootroot00000000000000 Thrift Javascript Bindings - Tutorial Example

Thrift Javascript Bindings

num1
Operation
num2
result
autoupdate

This Java Script example uses tutorial.thrift and a Thrift server using JSON protocol and HTTP transport.

Valid XHTML 1.0!

thrift-0.19.0/tutorial/js/build.xml0000644000000000000000000001165214303740367017213 0ustar00rootroot00000000000000 Thrift JavaScript Tutorial thrift-0.19.0/tutorial/js/build.properties0000644000000000000000000000036414303740367020605 0ustar00rootroot00000000000000# Maven Ant tasks Jar details mvn.ant.task.version=2.1.3 mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar thrift-0.19.0/tutorial/js/Makefile.in0000644000000000000000000004306714472652522017446 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/js ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ build.properties \ build.xml \ src \ tutorial.html all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/js/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/js/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean all-local: $(ANT) $(ANT_FLAGS) compile check-local: all $(ANT) $(ANT_FLAGS) test tutorialserver: all $(ANT) $(ANT_FLAGS) tutorialserver # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/delphi/0000777000000000000000000000000014303740367016222 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/delphi/Tutorial.groupproj0000644000000000000000000000400114303740367021765 0ustar00rootroot00000000000000 {3D042C7F-3EF2-4574-8304-AB7FB79F814C} Default.Personality.12 thrift-0.19.0/tutorial/delphi/DelphiClient/0000777000000000000000000000000014454461475020575 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/delphi/DelphiClient/DelphiClient.dproj0000644000000000000000000001505514454461475024203 0ustar00rootroot00000000000000 {2B8FB3A1-2F9E-4883-8C53-0F56220B34F6} DelphiClient.dpr 12.3 True Debug Win32 Console None DCC32 true true Base true true Base true ..\..\..\lib\delphi\src;$(DCC_UnitSearchPath) 00400000 .\dcu\$(Config)\$(Platform) WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias) ..\bin\$(Config)\$(Platform) false false false false false DEBUG;$(DCC_Define) false true false RELEASE;$(DCC_Define) 0 false MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 True False 0 12 0 0 False False False False False 1033 1252 Thrift Tutorial 0.19.0.0 DelphiClient Copyright © 2012 The Apache Software Foundation DelphiClient.exe Thrift 0.19.0.0 DelphiClient.dpr --transport framed --http http://example.org True 12 thrift-0.19.0/tutorial/delphi/DelphiClient/DelphiClient.dpr0000644000000000000000000000667514303740367023653 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program DelphiClient; {$APPTYPE CONSOLE} {$D 'Copyright (c) 2012 The Apache Software Foundation'} uses SysUtils, Generics.Collections, Thrift in '..\..\..\lib\delphi\src\Thrift.pas', Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\..\lib\delphi\src\Thrift.Configuration.pas', Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas', Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas', Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas', Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas', Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas', Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas', Thrift.Transport.WinHTTP in '..\..\..\lib\delphi\src\Thrift.Transport.WinHTTP.pas', Thrift.Transport.MsxmlHTTP in '..\..\..\lib\delphi\src\Thrift.Transport.MsxmlHTTP.pas', Thrift.WinHTTP in '..\..\..\lib\delphi\src\Thrift.WinHTTP.pas', Shared in '..\gen-delphi\Shared.pas', Tutorial in '..\gen-delphi\Tutorial.pas'; type DelphiTutorialClient = class public class procedure Main; end; //--- DelphiTutorialClient --------------------------------------- class procedure DelphiTutorialClient.Main; var transport : ITransport; protocol : IProtocol; client : TCalculator.Iface; work : IWork; sum, quotient, diff : Integer; log : ISharedStruct; begin try transport := TSocketImpl.Create( 'localhost', 9090); protocol := TBinaryProtocolImpl.Create( transport); client := TCalculator.TClient.Create( protocol); transport.Open; client.ping; WriteLn('ping()'); sum := client.add( 1, 1); WriteLn( Format( '1+1=%d', [sum])); work := TWorkImpl.Create; work.Op := TOperation.DIVIDE; work.Num1 := 1; work.Num2 := 0; try quotient := client.calculate(1, work); WriteLn( 'Whoa we can divide by 0'); WriteLn( Format('1/0=%d',[quotient])); except on io: TInvalidOperation do WriteLn( 'Invalid operation: ' + io.Why); end; work.Op := TOperation.SUBTRACT; work.Num1 := 15; work.Num2 := 10; try diff := client.calculate( 1, work); WriteLn( Format('15-10=%d', [diff])); except on io: TInvalidOperation do WriteLn( 'Invalid operation: ' + io.Why); end; log := client.getStruct(1); WriteLn( Format( 'Check log: %s', [log.Value])); transport.Close(); except on e : Exception do WriteLn( e.ClassName+': '+e.Message); end; end; begin try DelphiTutorialClient.Main; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. thrift-0.19.0/tutorial/delphi/DelphiServer/0000777000000000000000000000000014454461475020625 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/delphi/DelphiServer/DelphiServer.dpr0000644000000000000000000001121314303740367023713 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program DelphiServer; {$APPTYPE CONSOLE} {$D 'Copyright (c) 2012 The Apache Software Foundation'} {$Q+} // throws exceptions on numeric overflows uses SysUtils, Generics.Collections, Thrift in '..\..\..\lib\delphi\src\Thrift.pas', Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\..\lib\delphi\src\Thrift.Configuration.pas', Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas', Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas', Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas', Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas', Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas', Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas', Thrift.WinHTTP in '..\..\..\lib\delphi\src\Thrift.WinHTTP.pas', Shared in '..\gen-delphi\Shared.pas', Tutorial in '..\gen-delphi\Tutorial.pas'; type TCalculatorHandler = class( TInterfacedObject, TCalculator.Iface) protected FLog : TDictionary< Integer, ISharedStruct>; // TSharedService.Iface function getStruct(key: Integer): ISharedStruct; // TCalculator.Iface procedure ping(); function add(num1: Integer; num2: Integer): Integer; function calculate(logid: Integer; const w: IWork): Integer; procedure zip(); public constructor Create; destructor Destroy; override; end; DelphiTutorialServer = class public class procedure Main; end; //--- TCalculatorHandler --------------------------------------------------- constructor TCalculatorHandler.Create; begin inherited Create; FLog := TDictionary< Integer, ISharedStruct>.Create(); end; destructor TCalculatorHandler.Destroy; begin try FreeAndNil( FLog); finally inherited Destroy; end; end; procedure TCalculatorHandler.ping; begin WriteLn( 'ping()'); end; function TCalculatorHandler.add(num1: Integer; num2: Integer): Integer; begin WriteLn( Format( 'add( %d, %d)', [num1, num2])); result := num1 + num2; end; function TCalculatorHandler.calculate(logid: Integer; const w: IWork): Integer; var entry : ISharedStruct; begin try WriteLn( Format('calculate( %d, [%d,%d,%d])', [logid, Ord(w.Op), w.Num1, w.Num2])); case w.Op of TOperation.ADD : result := w.Num1 + w.Num2; TOperation.SUBTRACT : result := w.Num1 - w.Num2; TOperation.MULTIPLY : result := w.Num1 * w.Num2; TOperation.DIVIDE : result := Round( w.Num1 / w.Num2); else raise TInvalidOperation.Create( Ord(w.Op), 'Unknown operation'); end; except on e:Thrift.TException do raise; // let Thrift Exceptions pass through on e:Exception do raise TInvalidOperation.Create( Ord(w.Op), e.Message); // repackage all other end; entry := TSharedStructImpl.Create; entry.Key := logid; entry.Value := IntToStr( result); FLog.AddOrSetValue( logid, entry); end; function TCalculatorHandler.getStruct(key: Integer): ISharedStruct; begin WriteLn( Format( 'getStruct(%d)', [key])); result := FLog[key]; end; procedure TCalculatorHandler.zip; begin WriteLn( 'zip()'); end; //--- DelphiTutorialServer ---------------------------------------------------------------------- class procedure DelphiTutorialServer.Main; var handler : TCalculator.Iface; processor : IProcessor; transport : IServerTransport; server : IServer; begin try handler := TCalculatorHandler.Create; processor := TCalculator.TProcessorImpl.Create( handler); transport := TServerSocketImpl.Create( 9090); server := TSimpleServer.Create( processor, transport); WriteLn( 'Starting the server...'); server.Serve(); except on e: Exception do WriteLn( e.Message); end; WriteLn('done.'); end; begin try DelphiTutorialServer.Main; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. thrift-0.19.0/tutorial/delphi/DelphiServer/DelphiServer.dproj0000644000000000000000000001425314454461475024262 0ustar00rootroot00000000000000 {2B8FB3A1-2F9E-4883-8C53-0F56220B34F6} DelphiServer.dpr 12.3 True Debug Win32 Console None DCC32 true true Base true true Base true 00400000 .\dcu\$(Config)\$(Platform) WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias) ..\bin\$(Config)\$(Platform) false false false false false DEBUG;$(DCC_Define) false true false RELEASE;$(DCC_Define) 0 false MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 True False 0 12 0 0 False False False False False 1033 1252 Thrift Tutorial 0.19.0.0 DelphiServer Copyright © 2012 The Apache Software Foundation DelphiServer.exe Thrift 0.19.0.0 DelphiServer.dpr True 12 thrift-0.19.0/tutorial/perl/0000755000000000000000000000000014472652701015714 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/perl/Makefile.am0000644000000000000000000000215114303740367017746 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-perl/tutorial/Calculator.pm gen-perl/shared/SharedService.pm: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen perl -r $< all-local: gen-perl/tutorial/Calculator.pm tutorialserver: all ${PERL} PerlServer.pl tutorialclient: all ${PERL} PerlClient.pl clean-local: $(RM) -r gen-* EXTRA_DIST = \ PerlServer.pl \ PerlClient.pl thrift-0.19.0/tutorial/perl/PerlServer.pl0000644000000000000000000000553114303740367020345 0ustar00rootroot00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use strict; use lib '../../lib/perl/lib'; use lib 'gen-perl'; use Thrift::Socket; use Thrift::Server; use Thrift::ServerSocket; use tutorial::Calculator; package CalculatorHandler; use base qw(tutorial::CalculatorIf); sub new { my $classname = shift; my $self = {}; return bless($self,$classname); } sub ping { print "ping()\n"; } sub add { my($self, $n1, $n2) = @_; printf("add(%d,%d)\n", $n1, $n2); return $n1 + $n2; } sub calculate { my($self, $logid, $work) = @_; my $op = $work->{op}; my $num1 = $work->{num1}; my $num2 = $work->{num2}; printf("calculate(%d, %d %d %d)\n", $logid, $num1, $num2, $op); my $val; if ($op == tutorial::Operation::ADD) { $val = $num1 + $num2; } elsif ($op == tutorial::Operation::SUBTRACT) { $val = $num1 - $num2; } elsif ($op == tutorial::Operation::MULTIPLY) { $val = $num1 * $num2; } elsif ($op == tutorial::Operation::DIVIDE) { if ($num2 == 0) { my $x = tutorial::InvalidOperation->new(); $x->whatOp($op); $x->why('Cannot divide by 0'); die $x; } $val = $num1 / $num2; } else { my $x = tutorial::InvalidOperation->new(); $x->whatOp($op); $x->why('Invalid operation'); die $x; } my $log = shared::SharedStruct->new(); $log->key($logid); $log->value(int($val)); $self->{log}->{$logid} = $log; return $val; } sub getStruct { my($self, $key) = @_; printf("getStruct(%d)\n", $key); return $self->{log}->{$key}; } sub zip { my($self) = @_; print "zip()\n"; } eval { my $handler = CalculatorHandler->new(); my $processor = tutorial::CalculatorProcessor->new($handler); my $serversocket = Thrift::ServerSocket->new(9090); my $forkingserver = Thrift::ForkingServer->new($processor, $serversocket); print "Starting the server...\n"; $forkingserver->serve(); print "done.\n"; }; if ($@) { if ($@ =~ m/TException/ and exists $@->{message}) { my $message = $@->{message}; my $code = $@->{code}; my $out = $code . ':' . $message; die $out; } else { die $@; } } thrift-0.19.0/tutorial/perl/PerlClient.pl0000644000000000000000000000400114303740367020304 0ustar00rootroot00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use strict; use warnings; use lib '../../lib/perl/lib'; use lib 'gen-perl'; use Thrift; use Thrift::BinaryProtocol; use Thrift::Socket; use Thrift::BufferedTransport; use shared::SharedService; use tutorial::Calculator; use shared::Types; use tutorial::Types; use Data::Dumper; my $socket = Thrift::Socket->new('localhost',9090); my $transport = Thrift::BufferedTransport->new($socket,1024,1024); my $protocol = Thrift::BinaryProtocol->new($transport); my $client = tutorial::CalculatorClient->new($protocol); eval{ $transport->open(); $client->ping(); print "ping()\n"; my $sum = $client->add(1,1); print "1+1=$sum\n"; my $work = tutorial::Work->new(); $work->op(tutorial::Operation::DIVIDE); $work->num1(1); $work->num2(0); eval { $client->calculate(1, $work); print "Whoa! We can divide by zero?\n"; }; if($@) { warn 'InvalidOperation: '.Dumper($@); } $work->op(tutorial::Operation::SUBTRACT); $work->num1(15); $work->num2(10); my $diff = $client->calculate(1, $work); print "15-10=$diff\n"; my $log = $client->getStruct(1); print "Log: $log->{value}\n"; $transport->close(); }; if($@){ warn(Dumper($@)); } thrift-0.19.0/tutorial/perl/Makefile.in0000644000000000000000000004273514472652522017775 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/perl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ PerlServer.pl \ PerlClient.pl all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/perl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/perl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-perl/tutorial/Calculator.pm gen-perl/shared/SharedService.pm: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen perl -r $< all-local: gen-perl/tutorial/Calculator.pm tutorialserver: all ${PERL} PerlServer.pl tutorialclient: all ${PERL} PerlClient.pl clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/ocaml/0000777000000000000000000000000014454461475016057 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/ocaml/CalcClient.ml0000777000000000000000000000447414062750227020415 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Arg open Thrift open Tutorial_types open Shared_types exception Die;; let sod = function Some v -> v | None -> raise Die;; type connection = { trans : Transport.t ; proto : Thrift.Protocol.t; calc : Calculator.client ; } let connect ~host port = let tx = new TSocket.t host port in let proto = new TBinaryProtocol.t tx in let calc = new Calculator.client proto proto in tx#opn; { trans = tx ; proto = proto; calc = calc } ;; let doclient () = let cli = connect ~host:"127.0.0.1" 9090 in try cli.calc#ping ; Printf.printf "ping()\n" ; flush stdout ; (let sum = cli.calc#add (Int32.of_int 1) (Int32.of_int 1) in Printf.printf "1+1=%ld\n" sum ; flush stdout) ; (let w = new work in w#set_op Operation.DIVIDE ; w#set_num1 (Int32.of_int 1) ; w#set_num2 (Int32.of_int 0) ; try let quotient = cli.calc#calculate (Int32.of_int 1) w in Printf.printf "Whoa? We can divide by zero!\n" ; flush stdout with InvalidOperation io -> Printf.printf "InvalidOperation: %s\n" io#grab_why ; flush stdout) ; (let w = new work in w#set_op Operation.SUBTRACT ; w#set_num1 (Int32.of_int 15) ; w#set_num2 (Int32.of_int 10) ; let diff = cli.calc#calculate (Int32.of_int 1) w in Printf.printf "15-10=%ld\n" diff ; flush stdout) ; (let ss = cli.calc#getStruct (Int32.of_int 1) in Printf.printf "Check log: %s\n" ss#grab_value ; flush stdout) ; cli.trans#close with Transport.E (_,what) -> Printf.printf "ERROR: %s\n" what ; flush stdout ;; doclient();; thrift-0.19.0/tutorial/ocaml/_oasis0000644000000000000000000000143414454461475017255 0ustar00rootroot00000000000000Name: tutorial Version: 0.19.0 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers License: Apache-2.0 Homepage: http://thrift.apache.org BuildTools: ocamlbuild Plugins: META (0.3), DevFiles (0.3) Library tutorial_thrift Path: gen-ocaml FindlibName: tutorial_thrift buildTools: ocamlbuild BuildDepends: threads,thrift Modules: Calculator,Shared_consts,Tutorial_consts,SharedService,Shared_types,Tutorial_types XMETARequires: threads Executable CalcClient Path: . MainIs: CalcClient.ml Build$: true CompiledObject: best BuildDepends: thrift, tutorial_thrift, threads Executable CalcServer Path: . MainIs: CalcServer.ml Build$: true CompiledObject: best BuildDepends: thrift, tutorial_thrift, threads thrift-0.19.0/tutorial/ocaml/README.md0000644000000000000000000000111014303740367017314 0ustar00rootroot00000000000000 This is the ocaml tutorial example. It assumes that you've already built and installed the thrift ocaml runtime libraries in lib/ocaml. To compile this, you will need to generate the Thrift sources for ocaml in this directory (due to limitations in the OASIS build-tool): % thrift -r --gen ocaml ../tutorial.thrift % oasis setup % make This will produce two executables Calc{Server,Client}. where is one of "byte" or "native", depending on your ocaml installation. Just run the server in the background, then the client (as you would do for the C++ example). thrift-0.19.0/tutorial/ocaml/CalcServer.ml0000777000000000000000000000473514062750227020445 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Arg open Thrift open Tutorial_types open Shared_types exception Die;; let sod = function Some v -> v | None -> raise Die;; class calc_handler = object (self) inherit Calculator.iface val log = Hashtbl.create 23 method ping = Printf.printf "ping()\n" ; flush stdout method add a b = Printf.printf"add(%ld,%ld)\n" (sod a) (sod b); flush stdout ; Int32.add (sod a) (sod b) method calculate logid w = let w = sod w in Printf.printf "calculate(%ld,{%ld,%ld,%ld})\n" (sod logid) (Operation.to_i w#grab_op) w#grab_num1 w#grab_num2; flush stdout ; let rv = match w#grab_op with Operation.ADD -> Int32.add w#grab_num1 w#grab_num2 | Operation.SUBTRACT -> Int32.sub w#grab_num1 w#grab_num2 | Operation.MULTIPLY -> Int32.mul w#grab_num1 w#grab_num2 | Operation.DIVIDE -> if w#grab_num2 = Int32.zero then let io = new invalidOperation in io#set_whatOp (Operation.to_i w#grab_op) ; io#set_why "Cannot divide by 0" ; raise (InvalidOperation io) else Int32.div w#grab_num1 w#grab_num2 in let ss = new sharedStruct in ss#set_key (sod logid) ; let buffer = Int32.to_string rv in ss#set_value buffer ; Hashtbl.add log (sod logid) ss ; rv method zip = Printf.printf "zip()\n"; flush stdout method getStruct logid = Printf.printf "getStruct(%ld)\n" (sod logid) ; flush stdout ; Hashtbl.find log (sod logid) end let doserver () = let h = new calc_handler in let proc = new Calculator.processor h in let port = 9090 in let pf = new TBinaryProtocol.factory in let server = new TThreadedServer.t proc (new TServerSocket.t port) (new Transport.factory) pf pf in server#serve ;; doserver();; thrift-0.19.0/tutorial/go/0000755000000000000000000000000014472652700015356 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/go/Makefile.am0000644000000000000000000000327114370300523017403 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # GOBUILDEXTRA = -buildvcs=false gen-go/tutorial/calculator.go gen-go/shared/shared_service.go: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/tutorial/go/gen-go/$(COMPILER_EXTRAFLAG) -r $< all-local: gen-go/tutorial/calculator.go check: thirdparty-dep all $(GO) build $(GOBUILDEXTRA) -o go-tutorial ./src $(GO) build $(GOBUILDEXTRA) -o calculator-remote ./gen-go/tutorial/calculator-remote/calculator-remote.go thirdparty-dep: tutorialserver: all $(GO) run src/*.go -server=true tutorialclient: all $(GO) run src/*.go tutorialsecureserver: all $(GO) run src/*.go -server=true -secure=true tutorialsecureclient: all $(GO) run src/*.go -secure=true clean-local: $(RM) -r gen-* go-tutorial calculator-remote EXTRA_DIST = \ src/client.go \ src/handler.go \ src/server.go \ src/main.go \ server.crt \ server.key thrift-0.19.0/tutorial/go/src/0000755000000000000000000000000014472652700016145 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/go/src/main.go0000644000000000000000000000517114303740367017424 0ustar00rootroot00000000000000package main /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import ( "crypto/tls" "flag" "fmt" "os" "github.com/apache/thrift/lib/go/thrift" ) func Usage() { fmt.Fprint(os.Stderr, "Usage of ", os.Args[0], ":\n") flag.PrintDefaults() fmt.Fprint(os.Stderr, "\n") } func main() { flag.Usage = Usage server := flag.Bool("server", false, "Run server") protocol := flag.String("P", "binary", "Specify the protocol (binary, compact, json, simplejson)") framed := flag.Bool("framed", false, "Use framed transport") buffered := flag.Bool("buffered", false, "Use buffered transport") addr := flag.String("addr", "localhost:9090", "Address to listen to") secure := flag.Bool("secure", false, "Use tls secure transport") flag.Parse() var protocolFactory thrift.TProtocolFactory switch *protocol { case "compact": protocolFactory = thrift.NewTCompactProtocolFactoryConf(nil) case "simplejson": protocolFactory = thrift.NewTSimpleJSONProtocolFactoryConf(nil) case "json": protocolFactory = thrift.NewTJSONProtocolFactory() case "binary", "": protocolFactory = thrift.NewTBinaryProtocolFactoryConf(nil) default: fmt.Fprint(os.Stderr, "Invalid protocol specified", protocol, "\n") Usage() os.Exit(1) } var transportFactory thrift.TTransportFactory cfg := &thrift.TConfiguration{ TLSConfig: &tls.Config{ InsecureSkipVerify: true, }, } if *buffered { transportFactory = thrift.NewTBufferedTransportFactory(8192) } else { transportFactory = thrift.NewTTransportFactory() } if *framed { transportFactory = thrift.NewTFramedTransportFactoryConf(transportFactory, cfg) } if *server { if err := runServer(transportFactory, protocolFactory, *addr, *secure); err != nil { fmt.Println("error running server:", err) } } else { if err := runClient(transportFactory, protocolFactory, *addr, *secure, cfg); err != nil { fmt.Println("error running client:", err) } } } thrift-0.19.0/tutorial/go/src/server.go0000644000000000000000000000337314303740367020010 0ustar00rootroot00000000000000package main /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import ( "crypto/tls" "fmt" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/tutorial/go/gen-go/tutorial" ) func runServer(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string, secure bool) error { var transport thrift.TServerTransport var err error if secure { cfg := new(tls.Config) if cert, err := tls.LoadX509KeyPair("server.crt", "server.key"); err == nil { cfg.Certificates = append(cfg.Certificates, cert) } else { return err } transport, err = thrift.NewTSSLServerSocket(addr, cfg) } else { transport, err = thrift.NewTServerSocket(addr) } if err != nil { return err } fmt.Printf("%T\n", transport) handler := NewCalculatorHandler() processor := tutorial.NewCalculatorProcessor(handler) server := thrift.NewTSimpleServer4(processor, transport, transportFactory, protocolFactory) fmt.Println("Starting the simple server... on ", addr) return server.Serve() } thrift-0.19.0/tutorial/go/src/handler.go0000644000000000000000000000537414303740367020122 0ustar00rootroot00000000000000package main /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import ( "context" "fmt" "strconv" "github.com/apache/thrift/tutorial/go/gen-go/shared" "github.com/apache/thrift/tutorial/go/gen-go/tutorial" ) type CalculatorHandler struct { log map[int]*shared.SharedStruct } func NewCalculatorHandler() *CalculatorHandler { return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)} } func (p *CalculatorHandler) Ping(ctx context.Context) (err error) { fmt.Print("ping()\n") return nil } func (p *CalculatorHandler) Add(ctx context.Context, num1 int32, num2 int32) (retval17 int32, err error) { fmt.Print("add(", num1, ",", num2, ")\n") return num1 + num2, nil } func (p *CalculatorHandler) Calculate(ctx context.Context, logid int32, w *tutorial.Work) (val int32, err error) { fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") switch w.Op { case tutorial.Operation_ADD: val = w.Num1 + w.Num2 case tutorial.Operation_SUBTRACT: val = w.Num1 - w.Num2 case tutorial.Operation_MULTIPLY: val = w.Num1 * w.Num2 case tutorial.Operation_DIVIDE: if w.Num2 == 0 { ouch := tutorial.NewInvalidOperation() ouch.WhatOp = int32(w.Op) ouch.Why = "Cannot divide by 0" err = ouch return } val = w.Num1 / w.Num2 default: ouch := tutorial.NewInvalidOperation() ouch.WhatOp = int32(w.Op) ouch.Why = "Unknown operation" err = ouch return } entry := shared.NewSharedStruct() entry.Key = logid entry.Value = strconv.Itoa(int(val)) k := int(logid) /* oldvalue, exists := p.log[k] if exists { fmt.Print("Replacing ", oldvalue, " with ", entry, " for key ", k, "\n") } else { fmt.Print("Adding ", entry, " for key ", k, "\n") } */ p.log[k] = entry return val, err } func (p *CalculatorHandler) GetStruct(ctx context.Context, key int32) (*shared.SharedStruct, error) { fmt.Print("getStruct(", key, ")\n") v := p.log[int(key)] return v, nil } func (p *CalculatorHandler) Zip(ctx context.Context) (err error) { fmt.Print("zip()\n") return nil } thrift-0.19.0/tutorial/go/src/client.go0000644000000000000000000000540714303740367017760 0ustar00rootroot00000000000000package main /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import ( "context" "fmt" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/tutorial/go/gen-go/tutorial" ) var defaultCtx = context.Background() func handleClient(client *tutorial.CalculatorClient) (err error) { client.Ping(defaultCtx) fmt.Println("ping()") sum, _ := client.Add(defaultCtx, 1, 1) fmt.Print("1+1=", sum, "\n") work := tutorial.NewWork() work.Op = tutorial.Operation_DIVIDE work.Num1 = 1 work.Num2 = 0 quotient, err := client.Calculate(defaultCtx, 1, work) if err != nil { switch v := err.(type) { case *tutorial.InvalidOperation: fmt.Println("Invalid operation:", v) default: fmt.Println("Error during operation:", err) } } else { fmt.Println("Whoa we can divide by 0 with new value:", quotient) } work.Op = tutorial.Operation_SUBTRACT work.Num1 = 15 work.Num2 = 10 diff, err := client.Calculate(defaultCtx, 1, work) if err != nil { switch v := err.(type) { case *tutorial.InvalidOperation: fmt.Println("Invalid operation:", v) default: fmt.Println("Error during operation:", err) } return err } else { fmt.Print("15-10=", diff, "\n") } log, err := client.GetStruct(defaultCtx, 1) if err != nil { fmt.Println("Unable to get struct:", err) return err } else { fmt.Println("Check log:", log.Value) } return err } func runClient(transportFactory thrift.TTransportFactory, protocolFactory thrift.TProtocolFactory, addr string, secure bool, cfg *thrift.TConfiguration) error { var transport thrift.TTransport if secure { transport = thrift.NewTSSLSocketConf(addr, cfg) } else { transport = thrift.NewTSocketConf(addr, cfg) } transport, err := transportFactory.GetTransport(transport) if err != nil { return err } defer transport.Close() if err := transport.Open(); err != nil { return err } iprot := protocolFactory.GetProtocol(transport) oprot := protocolFactory.GetProtocol(transport) return handleClient(tutorial.NewCalculatorClient(thrift.NewTStandardClient(iprot, oprot))) } thrift-0.19.0/tutorial/go/server.crt0000644000000000000000000000276114303740367017404 0ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg 2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD 1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 -----END CERTIFICATE----- thrift-0.19.0/tutorial/go/server.key0000644000000000000000000000325014303740367017376 0ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqE9TE9wEXp5LR tLQVDSGQGV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCy SN8I2Xw6L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/H jKNg6ZKg2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQB GmZmMIUwAinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xk u62LipkXwCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDm trhVQF4nAgMBAAECggEAW/y52YYW6ypROGbZ94DQpFV0kLO7qT8q0Ksxw5sPNaIt fEPRIymDa8ikyHWJS5Oxmw84wo5jnJV26jaLmwe2Lupq7Xf1lqej8f5LJtuv7cQR xfzp1vM65KJFFJHp6WqjGqJ6HSSZOpVDsnQYcXQjQCdpyAmaSWd3p+FqYSZ1mQmD bFNI7jqpczWSZhTdotQ7p7Hn9TVCehflP3yGIB3bQ+wCcCB85dOBz201L+YgaIck Sz43A4NvWaQIRLRDw7s9GW4jY5T0Jv282WIeAlVpVxLIwu48r4R4yGTIx9Ydowvq 57+Y5iPPjAXxu0V9t00oS3bYxDaKh2DUfc/5zowq8QKBgQDYNVPXmaG0aIH4vjQ9 7fRdw/UDkYcQbn6CnglQOu77/S8ogQzpKCVJgJgkZNqOVtQMEPzekGEcLTbje1gU 8Bky2k+PL9UwbFy0emnOVh4rqrNXHsRvJcehNT/PRb5hjF3MUMFV/0iD4b+naFaE jrSWiZ2ZXj2qfwAK52GFbtOuBQKBgQDJYQuGiY0r22E4waJmCSKczoBT3cwlVzWj V2ljgA9RHLNTVkvNNYQLGu2qngFrtwpeaSnsMDerVG4wKAQWyCnYzxVrlnC4uDrJ HXuFEltBWi9Ffbgfsnd3749AT0oBP1NT2tMleguyf5DFgjCR3VRJLdrVaaZ8row/ LqKcFMqnOwKBgB+OIO99l7E584Y3VG6ZdSneOLtNmRXX2pT7tcZE465ZdHGH7Dd3 SYHhx9K/+Xn+yDH+pLli/xlarAEldmSP6k2WuTfftlC78AfTOfAId5zN7CDR9791 Fx67I9X/itq33tS8EIuZl57P6uXm/4GXRloWOa8xpvRkVsBApuYPl8t1AoGATQDS y2sllDObBXzlgGbV2WgNIgSZ311toTv3jJiXQsjauW8yJRHln+l4H9mzaWDgkiFc ang1kUoDqF5k0eFQPxtQcYdhKwEnWWfwp33RbzfxA32DPnubuzzbZhfrkHaKgnIW cyor9uFYlm2l7ODZLfJez2RKyTplXnOSsmQw6akCgYAz3dj9Hskyj+HVJ+ht1OcE c7ai/ESkSA7Vajp0tjJp0EKjW/zq8DvUSXOtcdnJgkKycFluLwbmnaN4txBds1C1 Qr8Rt2sUCCBNZe1L6DHe3XBdbkJe9sgZVNTjtUSQrzy8UhvsCqG4YWeCu07Szcbc rdPUV9/uQkdx8VrShxlD8A== -----END PRIVATE KEY----- thrift-0.19.0/tutorial/go/Makefile.in0000644000000000000000000004404514472652522017434 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/go ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ GOBUILDEXTRA = -buildvcs=false EXTRA_DIST = \ src/client.go \ src/handler.go \ src/server.go \ src/main.go \ server.crt \ server.key all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/go/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/go/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-go/tutorial/calculator.go gen-go/shared/shared_service.go: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/tutorial/go/gen-go/$(COMPILER_EXTRAFLAG) -r $< all-local: gen-go/tutorial/calculator.go check: thirdparty-dep all $(GO) build $(GOBUILDEXTRA) -o go-tutorial ./src $(GO) build $(GOBUILDEXTRA) -o calculator-remote ./gen-go/tutorial/calculator-remote/calculator-remote.go thirdparty-dep: tutorialserver: all $(GO) run src/*.go -server=true tutorialclient: all $(GO) run src/*.go tutorialsecureserver: all $(GO) run src/*.go -server=true -secure=true tutorialsecureclient: all $(GO) run src/*.go -secure=true clean-local: $(RM) -r gen-* go-tutorial calculator-remote # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/py.tornado/0000755000000000000000000000000014472652677017063 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/py.tornado/Makefile.am0000644000000000000000000000221514303740367021102 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-py.tornado/tutorial/Calculator.py gen-py.tornado/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen py:tornado -r $< all-local: gen-py.tornado/tutorial/Calculator.py tutorialserver: all ${PYTHON} PythonServer.py tutorialclient: all ${PYTHON} PythonClient.py clean-local: $(RM) -r gen-* EXTRA_DIST = \ PythonServer.py \ PythonClient.py thrift-0.19.0/tutorial/py.tornado/Makefile.in0000644000000000000000000004302314472652522021117 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/py.tornado ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ PythonServer.py \ PythonClient.py all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/py.tornado/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/py.tornado/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-py.tornado/tutorial/Calculator.py gen-py.tornado/shared/SharedService.py: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen py:tornado -r $< all-local: gen-py.tornado/tutorial/Calculator.py tutorialserver: all ${PYTHON} PythonServer.py tutorialclient: all ${PYTHON} PythonClient.py clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/py.tornado/PythonClient.py0000777000000000000000000000560714062750227022055 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import logging import sys sys.path.append('gen-py.tornado') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from tutorial.ttypes import Operation, Work, InvalidOperation from thrift import TTornado from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from tornado import gen from tornado import ioloop @gen.coroutine def communicate(): # create client transport = TTornado.TTornadoStreamTransport('localhost', 9090) # open the transport, bail on error try: yield transport.open() print('Transport is opened') except TTransport.TTransportException as ex: logging.error(ex) raise gen.Return() pfactory = TBinaryProtocol.TBinaryProtocolFactory() client = Calculator.Client(transport, pfactory) # ping yield client.ping() print("ping()") # add sum_ = yield client.add(1, 1) print("1 + 1 = {0}".format(sum_)) # make a oneway call without a callback (schedule the write and continue # without blocking) client.zip() print("zip() without callback") # make a oneway call with a callback (we'll wait for the stream write to # complete before continuing) client.zip() print("zip() with callback") # calculate 1/0 work = Work() work.op = Operation.DIVIDE work.num1 = 1 work.num2 = 0 try: quotient = yield client.calculate(1, work) print("Whoa? You know how to divide by zero ? -> {0}".format(quotient)) except InvalidOperation as io: print("InvalidOperation: {0}".format(io)) # calculate 15-10 work.op = Operation.SUBTRACT work.num1 = 15 work.num2 = 10 diff = yield client.calculate(1, work) print("15 - 10 = {0}".format(diff)) # getStruct log = yield client.getStruct(1) print("Check log: {0}".format(log.value)) # close the transport client._transport.close() raise gen.Return() def main(): # create an ioloop, do the above, then stop ioloop.IOLoop.current().run_sync(communicate) if __name__ == "__main__": main() thrift-0.19.0/tutorial/py.tornado/PythonServer.py0000777000000000000000000000512514062750227022100 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import sys sys.path.append('gen-py.tornado') sys.path.insert(0, glob.glob('../../lib/py/build/lib*')[0]) from tutorial import Calculator from tutorial.ttypes import Operation, InvalidOperation from shared.ttypes import SharedStruct from thrift import TTornado from thrift.protocol import TBinaryProtocol from tornado import ioloop class CalculatorHandler(object): def __init__(self): self.log = {} def ping(self): print("ping()") def add(self, n1, n2): print("add({}, {})".format(n1, n2)) return n1 + n2 def calculate(self, logid, work): print("calculate({}, {})".format(logid, work)) if work.op == Operation.ADD: val = work.num1 + work.num2 elif work.op == Operation.SUBTRACT: val = work.num1 - work.num2 elif work.op == Operation.MULTIPLY: val = work.num1 * work.num2 elif work.op == Operation.DIVIDE: if work.num2 == 0: raise InvalidOperation(work.op, "Cannot divide by 0") val = work.num1 / work.num2 else: raise InvalidOperation(work.op, "Invalid operation") log = SharedStruct() log.key = logid log.value = '%d' % (val) self.log[logid] = log return val def getStruct(self, key): print("getStruct({})".format(key)) return self.log[key] def zip(self): print("zip()") def main(): handler = CalculatorHandler() processor = Calculator.Processor(handler) pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TTornado.TTornadoServer(processor, pfactory) print("Starting the server...") server.bind(9090) server.start(1) ioloop.IOLoop.instance().start() print("done.") if __name__ == "__main__": main() thrift-0.19.0/tutorial/dart/0000755000000000000000000000000014472652700015703 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/console_client/0000755000000000000000000000000014472652700020703 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/console_client/bin/0000755000000000000000000000000014472652700021453 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/console_client/bin/main.dart0000644000000000000000000000741114303740367023256 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. import 'dart:async'; import 'dart:io'; import 'package:args/args.dart'; import 'package:logging/logging.dart'; import 'package:thrift/thrift.dart'; import 'package:thrift/thrift_console.dart'; import 'package:tutorial/tutorial.dart'; TTransport _transport; Calculator _calculator; int logid = 0; const Map operationLookup = const { '+': Operation.ADD, '-': Operation.SUBTRACT, '*': Operation.MULTIPLY, '/': Operation.DIVIDE }; main(List args) { Logger.root.level = Level.ALL; Logger.root.onRecord.listen((LogRecord rec) { print('${rec.level.name}: ${rec.time}: ${rec.message}'); }); var parser = new ArgParser(); parser.addOption('port', defaultsTo: '9090', help: 'The port to connect to'); ArgResults results; try { results = parser.parse(args); } catch (e) { results = null; } if (results == null) { print(parser.usage); exit(0); } int port = int.parse(results['port']); _initConnection(port).then((_) => _run()); } Future _initConnection(int port) async { var socket = await Socket.connect('127.0.0.1', port); _transport = new TAsyncClientSocketTransport( new TTcpSocket(socket), new TMessageReader(new TBinaryProtocolFactory())); TProtocol protocol = new TBinaryProtocol(_transport); await _transport.open(); _calculator = new CalculatorClient(protocol); } Future _run() async { _help(); while (true) { stdout.write("> "); var input = stdin.readLineSync(); var parts = input.split(' '); var command = parts[0]; var args = parts.length > 1 ? parts.sublist(1) : []; switch (command) { case 'ping': await _ping(); break; case 'add': await _add(int.parse(args[0]), int.parse(args[1])); break; case 'calc': int op = operationLookup[args[1]]; if (!Operation.VALID_VALUES.contains(op)) { stdout.writeln('Unknown operator ${args[1]}'); break; } var work = new Work() ..num1 = int.parse(args[0]) ..op = op ..num2 = int.parse(args[2]) ..comment = args.length > 3 ? args[3] : ''; await _calc(work); break; case 'struct': await _struct(int.parse(args[0])); break; case 'help': default: _help(); break; } } } void _help() { stdout.writeln('Commands:'); stdout.writeln(' help'); stdout.writeln(' ping'); stdout.writeln(' add x y'); stdout.writeln(' calc x op y [comment]'); stdout.writeln(' struct id'); stdout.writeln(''); } Future _ping() async { await _calculator.ping(); stdout.writeln('ping succeeded'); } Future _add(int x, int y) async { int result = await _calculator.add(x, y); stdout.writeln('= $result'); } Future _calc(Work work) async { int result = await _calculator.calculate(logid++, work); stdout.writeln('= $result'); } Future _struct(int key) async { var struct = await _calculator.getStruct(key); stdout.writeln(struct.toString()); } thrift-0.19.0/tutorial/dart/console_client/pubspec.yaml0000644000000000000000000000231214454461475023235 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # 'License'); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. name: tutorial_console_client version: 0.19.0 description: > A Dart console client to implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org environment: sdk: ">=1.13.0 <3.0.0" dependencies: args: ">=0.13.0 <2.0.0" collection: ^1.1.0 shared: path: ../gen-dart/shared thrift: path: ../../../lib/dart tutorial: path: ../gen-dart/tutorial thrift-0.19.0/tutorial/dart/Makefile.am0000644000000000000000000000466614303740367017753 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # BUILT_SOURCES = gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen dart -r $< all-local: gen-dart/tutorial/lib/tutorial.dart pub-get clean-local: $(RM) -r gen-*/ find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) dist-hook: $(RM) -r $(distdir)/gen-*/ find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type d -name "packages" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) find $(distdir) -type f -name "pubspec.lock" | xargs $(RM) pub-get: pub-get-gen pub-get-client pub-get-console-client pub-get-server pub-get-gen: pub-get-tutorial pub-get-shared pub-get-tutorial: gen-dart/tutorial/lib/tutorial.dart cd gen-dart/tutorial; ${DARTPUB} get pub-get-shared: gen-dart/shared/lib/shared.dart cd gen-dart/shared; ${DARTPUB} get pub-get-client: cd client; ${DARTPUB} get pub-get-console-client: cd console_client; ${DARTPUB} get pub-get-server: cd server; ${DARTPUB} get tutorialserver: pub-get-gen pub-get-server ${DART} server/bin/main.dart tutorialclient: pub-get-gen pub-get-client cd client; ${DARTPUB} serve tutorialconsoleclient: pub-get-console-client ${DART} console_client/bin/main.dart EXTRA_DIST = \ client/web/client.dart \ client/web/index.html \ client/web/styles.css \ client/pubspec.yaml \ console_client/bin/main.dart \ console_client/pubspec.yaml \ server/bin/main.dart \ server/pubspec.yaml \ build.sh thrift-0.19.0/tutorial/dart/client/0000755000000000000000000000000014472652700017161 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/client/web/0000755000000000000000000000000014472652700017736 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/client/web/styles.css0000644000000000000000000000205614303740367021776 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ @import url(https://fonts.googleapis.com/css?family=Roboto); html, body { width: 100%; height: 100%; margin: 0; padding: 10px; font-family: 'Roboto', sans-serif; } h3 { border-bottom: solid; border-width: thin; padding-top: 20px; } thrift-0.19.0/tutorial/dart/client/web/client.dart0000644000000000000000000002001214303740367022063 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. import 'dart:html'; import 'package:thrift/thrift.dart'; import 'package:thrift/thrift_browser.dart'; import 'package:shared/shared.dart'; import 'package:tutorial/tutorial.dart'; /// Adapted from the AS3 tutorial void main() { new CalculatorUI(querySelector('#output')).start(); } class CalculatorUI { final DivElement output; CalculatorUI(this.output); TTransport _transport; Calculator _calculatorClient; void start() { _buildInterface(); _initConnection(); } void _validate() { if (!_transport.isOpen) { window.alert("The transport is not open!"); } } void _initConnection() { _transport = new TAsyncClientSocketTransport( new TWebSocket(Uri.parse('ws://127.0.0.1:9090/ws')), new TMessageReader(new TBinaryProtocolFactory())); TProtocol protocol = new TBinaryProtocol(_transport); _transport.open(); _calculatorClient = new CalculatorClient(protocol); } void _buildInterface() { output.children.forEach((e) { e.remove(); }); _buildPingComponent(); _buildAddComponent(); _buildCalculatorComponent(); _buildGetStructComponent(); } void _buildPingComponent() { output.append(new HeadingElement.h3()..text = "Ping"); ButtonElement pingButton = new ButtonElement() ..text = "PING" ..onClick.listen(_onPingClick); output.append(pingButton); } void _onPingClick(MouseEvent e) { _validate(); _calculatorClient.ping(); } void _buildAddComponent() { output.append(new HeadingElement.h3()..text = "Add"); InputElement num1 = new InputElement() ..id = "add1" ..type = "number" ..style.fontSize = "14px" ..style.width = "50px"; output.append(num1); SpanElement op = new SpanElement() ..text = "+" ..style.fontSize = "14px" ..style.marginLeft = "10px"; output.append(op); InputElement num2 = new InputElement() ..id = "add2" ..type = "number" ..style.fontSize = "14px" ..style.width = "50px" ..style.marginLeft = "10px"; output.append(num2); ButtonElement addButton = new ButtonElement() ..text = "=" ..style.fontSize = "14px" ..style.marginLeft = "10px" ..onClick.listen(_onAddClick); output.append(addButton); SpanElement result = new SpanElement() ..id = "addResult" ..style.fontSize = "14px" ..style.marginLeft = "10px"; output.append(result); } void _onAddClick(MouseEvent e) { _validate(); InputElement num1 = querySelector("#add1"); InputElement num2 = querySelector("#add2"); SpanElement result = querySelector("#addResult"); _calculatorClient .add(int.parse(num1.value), int.parse(num2.value)) .then((int n) { result.text = "$n"; }); } void _buildCalculatorComponent() { output.append(new HeadingElement.h3()..text = "Calculator"); InputElement num1 = new InputElement() ..id = "calc1" ..type = "number" ..style.fontSize = "14px" ..style.width = "50px"; output.append(num1); SelectElement op = new SelectElement() ..id = "calcOp" ..multiple = false ..selectedIndex = 0 ..style.fontSize = "16px" ..style.marginLeft = "10px" ..style.width = "50px"; OptionElement addOp = new OptionElement() ..text = "+" ..value = Operation.ADD.toString(); op.add(addOp, 0); OptionElement subtractOp = new OptionElement() ..text = "-" ..value = Operation.SUBTRACT.toString(); op.add(subtractOp, 1); OptionElement multiplyOp = new OptionElement() ..text = "*" ..value = Operation.MULTIPLY.toString(); op.add(multiplyOp, 2); OptionElement divideOp = new OptionElement() ..text = "/" ..value = Operation.DIVIDE.toString(); op.add(divideOp, 3); output.append(op); InputElement num2 = new InputElement() ..id = "calc2" ..type = "number" ..style.fontSize = "14px" ..style.width = "50px" ..style.marginLeft = "10px"; output.append(num2); ButtonElement calcButton = new ButtonElement() ..text = "=" ..style.fontSize = "14px" ..style.marginLeft = "10px" ..onClick.listen(_onCalcClick); output.append(calcButton); SpanElement result = new SpanElement() ..id = "calcResult" ..style.fontSize = "14px" ..style.marginLeft = "10px"; output.append(result); output.append(new BRElement()); output.append(new BRElement()); LabelElement logIdLabel = new LabelElement() ..text = "Log ID:" ..style.fontSize = "14px"; output.append(logIdLabel); InputElement logId = new InputElement() ..id = "logId" ..type = "number" ..value = "1" ..style.fontSize = "14px" ..style.width = "50px" ..style.marginLeft = "10px"; output.append(logId); LabelElement commentLabel = new LabelElement() ..text = "Comment:" ..style.fontSize = "14px" ..style.marginLeft = "10px"; output.append(commentLabel); InputElement comment = new InputElement() ..id = "comment" ..style.fontSize = "14px" ..style.width = "100px" ..style.marginLeft = "10px"; output.append(comment); } void _onCalcClick(MouseEvent e) { _validate(); InputElement num1 = querySelector("#calc1"); InputElement num2 = querySelector("#calc2"); SelectElement op = querySelector("#calcOp"); SpanElement result = querySelector("#calcResult"); InputElement logId = querySelector("#logId"); InputElement comment = querySelector("#comment"); int logIdValue = int.parse(logId.value); logId.value = (logIdValue + 1).toString(); Work work = new Work(); work.num1 = int.parse(num1.value); work.num2 = int.parse(num2.value); work.op = int.parse(op.options[op.selectedIndex].value); work.comment = comment.value; _calculatorClient.calculate(logIdValue, work).then((int n) { result.text = "$n"; }); } void _buildGetStructComponent() { output.append(new HeadingElement.h3()..text = "Get Struct"); LabelElement logIdLabel = new LabelElement() ..text = "Struct Key:" ..style.fontSize = "14px"; output.append(logIdLabel); InputElement logId = new InputElement() ..id = "structKey" ..type = "number" ..value = "1" ..style.fontSize = "14px" ..style.width = "50px" ..style.marginLeft = "10px"; output.append(logId); ButtonElement getStructButton = new ButtonElement() ..text = "GET" ..style.fontSize = "14px" ..style.marginLeft = "10px" ..onClick.listen(_onGetStructClick); output.append(getStructButton); output.append(new BRElement()); output.append(new BRElement()); TextAreaElement result = new TextAreaElement() ..id = "getStructResult" ..style.fontSize = "14px" ..style.width = "300px" ..style.height = "50px" ..style.marginLeft = "10px"; output.append(result); } void _onGetStructClick(MouseEvent e) { _validate(); InputElement structKey = querySelector("#structKey"); TextAreaElement result = querySelector("#getStructResult"); _calculatorClient .getStruct(int.parse(structKey.value)) .then((SharedStruct s) { result.text = "${s.toString()}"; }); } } thrift-0.19.0/tutorial/dart/client/web/index.html0000644000000000000000000000224014303740367021731 0ustar00rootroot00000000000000 Thrift Tutorial
thrift-0.19.0/tutorial/dart/client/pubspec.yaml0000644000000000000000000000220414454461475021513 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # 'License'); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. name: tutorial_client version: 0.19.0 description: A Dart client implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org environment: sdk: ">=1.13.0 <3.0.0" dependencies: shared: path: ../gen-dart/shared thrift: path: ../../../lib/dart tutorial: path: ../gen-dart/tutorial thrift-0.19.0/tutorial/dart/server/0000755000000000000000000000000014472652700017211 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/server/bin/0000755000000000000000000000000014472652700017761 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/dart/server/bin/main.dart0000644000000000000000000001035714303740367021567 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. import 'dart:async'; import 'dart:io'; import 'package:args/args.dart'; import 'package:logging/logging.dart'; import 'package:thrift/thrift.dart'; import 'package:thrift/thrift_console.dart'; import 'package:tutorial/tutorial.dart'; import 'package:shared/shared.dart'; TProtocol _protocol; TProcessor _processor; WebSocket _webSocket; main(List args) { Logger.root.level = Level.ALL; Logger.root.onRecord.listen((LogRecord rec) { print('${rec.level.name}: ${rec.time}: ${rec.message}'); }); var parser = new ArgParser(); parser.addOption('port', defaultsTo: '9090', help: 'The port to listen on'); parser.addOption('type', defaultsTo: 'ws', allowed: ['ws', 'tcp'], help: 'The type of socket', allowedHelp: {'ws': 'WebSocket', 'tcp': 'TCP Socket'}); ArgResults results; try { results = parser.parse(args); } catch (e) { results = null; } if (results == null) { print(parser.usage); exit(0); } int port = int.parse(results['port']); String socketType = results['type']; if (socketType == 'tcp') { _runTcpServer(port); } else if (socketType == 'ws') { _runWebSocketServer(port); } } Future _runWebSocketServer(int port) async { var httpServer = await HttpServer.bind('127.0.0.1', port); print('listening for WebSocket connections on $port'); httpServer.listen((HttpRequest request) async { if (request.uri.path == '/ws') { _webSocket = await WebSocketTransformer.upgrade(request); await _initProcessor(new TWebSocket(_webSocket)); } else { print('Invalid path: ${request.uri.path}'); } }); } Future _runTcpServer(int port) async { var serverSocket = await ServerSocket.bind('127.0.0.1', port); print('listening for TCP connections on $port'); Socket socket = await serverSocket.first; await _initProcessor(new TTcpSocket(socket)); } Future _initProcessor(TSocket socket) async { TServerSocketTransport transport = new TServerSocketTransport(socket); transport.onIncomingMessage.listen(_processMessage); _processor = new CalculatorProcessor(new CalculatorServer()); _protocol = new TBinaryProtocol(transport); await _protocol.transport.open(); print('connected'); } Future _processMessage(_) async { _processor.process(_protocol, _protocol); } class CalculatorServer implements Calculator { final Map _log = {}; Future ping() async { print('ping()'); } Future add(int num1, int num2) async { print('add($num1, $num2)'); return num1 + num2; } Future calculate(int logid, Work work) async { print('calulate($logid, ${work.toString()})'); int val; switch (work.op) { case Operation.ADD: val = work.num1 + work.num2; break; case Operation.SUBTRACT: val = work.num1 - work.num2; break; case Operation.MULTIPLY: val = work.num1 * work.num2; break; case Operation.DIVIDE: if (work.num2 == 0) { var x = new InvalidOperation(); x.whatOp = work.op; x.why = 'Cannot divide by 0'; throw x; } val = (work.num1 / work.num2).floor(); break; } var log = new SharedStruct(); log.key = logid; log.value = '$val "${work.comment}"'; this._log[logid] = log; return val; } Future zip() async { print('zip()'); } Future getStruct(int key) async { print('getStruct($key)'); return _log[key]; } } thrift-0.19.0/tutorial/dart/server/pubspec.yaml0000644000000000000000000000222714454461475021550 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # 'License'); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. name: tutorial_server version: 0.19.0 description: A Dart server to support the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org environment: sdk: ">=1.13.0 <3.0.0" dependencies: args: ">=0.13.0 <2.0.0" shared: path: ../gen-dart/shared thrift: path: ../../../lib/dart tutorial: path: ../gen-dart/tutorial thrift-0.19.0/tutorial/dart/Makefile.in0000644000000000000000000004613114472652522017757 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/dart ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ BUILT_SOURCES = gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart EXTRA_DIST = \ client/web/client.dart \ client/web/index.html \ client/web/styles.css \ client/pubspec.yaml \ console_client/bin/main.dart \ console_client/pubspec.yaml \ server/bin/main.dart \ server/pubspec.yaml \ build.sh all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/dart/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/dart/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile all-local installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check install install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen dart -r $< all-local: gen-dart/tutorial/lib/tutorial.dart pub-get clean-local: $(RM) -r gen-*/ find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) dist-hook: $(RM) -r $(distdir)/gen-*/ find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type d -name "packages" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) find $(distdir) -type f -name "pubspec.lock" | xargs $(RM) pub-get: pub-get-gen pub-get-client pub-get-console-client pub-get-server pub-get-gen: pub-get-tutorial pub-get-shared pub-get-tutorial: gen-dart/tutorial/lib/tutorial.dart cd gen-dart/tutorial; ${DARTPUB} get pub-get-shared: gen-dart/shared/lib/shared.dart cd gen-dart/shared; ${DARTPUB} get pub-get-client: cd client; ${DARTPUB} get pub-get-console-client: cd console_client; ${DARTPUB} get pub-get-server: cd server; ${DARTPUB} get tutorialserver: pub-get-gen pub-get-server ${DART} server/bin/main.dart tutorialclient: pub-get-gen pub-get-client cd client; ${DARTPUB} serve tutorialconsoleclient: pub-get-console-client ${DART} console_client/bin/main.dart # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/dart/build.sh0000644000000000000000000000262314303740367017341 0ustar00rootroot00000000000000#!/bin/sh # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # 'License'); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. set -e; rm -r gen-dart || true; thrift --gen dart ../shared.thrift; cd gen-dart/shared; pub get; cd ../..; thrift --gen dart ../tutorial.thrift; cd gen-dart/tutorial; pub get; cd ../..; cd client; pub get; cd ..; cd console_client; pub get; cd ..; cd server; pub get; cd ..; dartfmt -w gen-dart; echo "\nEnjoy the Dart tutorial!"; echo "\nTo run the server:"; echo "> dart server/bin/main.dart"; echo "\nTo run the client:"; echo "# Serve the app from the client directory and view in a browser"; echo "> cd client;"; echo "> pub serve;"; echo "\nTo run the console client:"; echo "> dart console_client/bin/main.dart"; echo ""; thrift-0.19.0/tutorial/java/0000755000000000000000000000000014472652677015707 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/java/Makefile.am0000644000000000000000000000236114303742350017722 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean all-local: $(ANT) $(ANT_FLAGS) compile check-local: all $(ANT) $(ANT_FLAGS) test tutorial: all $(ANT) $(ANT_FLAGS) tutorial tutorialserver: all $(ANT) $(ANT_FLAGS) tutorialserver tutorialclient: all $(ANT) $(ANT_FLAGS) tutorialclient EXTRA_DIST = \ build.properties \ build.xml \ src \ README.md thrift-0.19.0/tutorial/java/src/0000777000000000000000000000000014303740367016465 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/java/src/CalculatorHandler.java0000644000000000000000000000464114303740367022720 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.thrift.TException; // Generated code import tutorial.*; import shared.*; import java.util.HashMap; public class CalculatorHandler implements Calculator.Iface { private HashMap log; public CalculatorHandler() { log = new HashMap(); } public void ping() { System.out.println("ping()"); } public int add(int n1, int n2) { System.out.println("add(" + n1 + "," + n2 + ")"); return n1 + n2; } public int calculate(int logid, Work work) throws InvalidOperation { System.out.println("calculate(" + logid + ", {" + work.op + "," + work.num1 + "," + work.num2 + "})"); int val = 0; switch (work.op) { case ADD: val = work.num1 + work.num2; break; case SUBTRACT: val = work.num1 - work.num2; break; case MULTIPLY: val = work.num1 * work.num2; break; case DIVIDE: if (work.num2 == 0) { InvalidOperation io = new InvalidOperation(); io.whatOp = work.op.getValue(); io.why = "Cannot divide by 0"; throw io; } val = work.num1 / work.num2; break; default: InvalidOperation io = new InvalidOperation(); io.whatOp = work.op.getValue(); io.why = "Unknown operation"; throw io; } SharedStruct entry = new SharedStruct(); entry.key = logid; entry.value = Integer.toString(val); log.put(logid, entry); return val; } public SharedStruct getStruct(int key) { System.out.println("getStruct(" + key + ")"); return log.get(key); } public void zip() { System.out.println("zip()"); } } thrift-0.19.0/tutorial/java/src/JavaClient.java0000644000000000000000000000667514303740367021362 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Generated code import tutorial.*; import shared.*; import org.apache.thrift.TException; import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; public class JavaClient { public static void main(String [] args) { if (args.length != 1) { System.out.println("Please enter 'simple' or 'secure'"); System.exit(0); } try { TTransport transport; if (args[0].contains("simple")) { transport = new TSocket("localhost", 9090); transport.open(); } else { /* * Similar to the server, you can use the parameters to setup client parameters or * use the default settings. On the client side, you will need a TrustStore which * contains the trusted certificate along with the public key. * For this example it's a self-signed cert. */ TSSLTransportParameters params = new TSSLTransportParameters(); params.setTrustStore("../../lib/java/test/resources/.truststore", "thrift", "SunX509", "JKS"); /* * Get a client transport instead of a server transport. The connection is opened on * invocation of the factory method, no need to specifically call open() */ transport = TSSLTransportFactory.getClientSocket("localhost", 9091, 0, params); } TProtocol protocol = new TBinaryProtocol(transport); Calculator.Client client = new Calculator.Client(protocol); perform(client); transport.close(); } catch (TException x) { x.printStackTrace(); } } private static void perform(Calculator.Client client) throws TException { client.ping(); System.out.println("ping()"); int sum = client.add(1,1); System.out.println("1+1=" + sum); Work work = new Work(); work.op = Operation.DIVIDE; work.num1 = 1; work.num2 = 0; try { int quotient = client.calculate(1, work); System.out.println("Whoa we can divide by 0"); } catch (InvalidOperation io) { System.out.println("Invalid operation: " + io.why); } work.op = Operation.SUBTRACT; work.num1 = 15; work.num2 = 10; try { int diff = client.calculate(1, work); System.out.println("15-10=" + diff); } catch (InvalidOperation io) { System.out.println("Invalid operation: " + io.why); } SharedStruct log = client.getStruct(1); System.out.println("Check log: " + log.value); } } thrift-0.19.0/tutorial/java/src/JavaServer.java0000644000000000000000000000761214303740367021402 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.thrift.server.TServer; import org.apache.thrift.server.TServer.Args; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.server.TThreadPoolServer; import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters; // Generated code import tutorial.*; import shared.*; import java.util.HashMap; public class JavaServer { public static CalculatorHandler handler; public static Calculator.Processor processor; public static void main(String [] args) { try { handler = new CalculatorHandler(); processor = new Calculator.Processor(handler); Runnable simple = new Runnable() { public void run() { simple(processor); } }; Runnable secure = new Runnable() { public void run() { secure(processor); } }; new Thread(simple).start(); new Thread(secure).start(); } catch (Exception x) { x.printStackTrace(); } } public static void simple(Calculator.Processor processor) { try { TServerTransport serverTransport = new TServerSocket(9090); TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); // Use this for a multithreaded server // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); System.out.println("Starting the simple server..."); server.serve(); } catch (Exception e) { e.printStackTrace(); } } public static void secure(Calculator.Processor processor) { try { /* * Use TSSLTransportParameters to setup the required SSL parameters. In this example * we are setting the keystore and the keystore password. Other things like algorithms, * cipher suites, client auth etc can be set. */ TSSLTransportParameters params = new TSSLTransportParameters(); // The Keystore contains the private key params.setKeyStore("../../lib/java/test/resources/.keystore", "thrift", null, null); /* * Use any of the TSSLTransportFactory to get a server transport with the appropriate * SSL configuration. You can use the default settings if properties are set in the command line. * Ex: -Djavax.net.ssl.keyStore=.keystore and -Djavax.net.ssl.keyStorePassword=thrift * * Note: You need not explicitly call open(). The underlying server socket is bound on return * from the factory class. */ TServerTransport serverTransport = TSSLTransportFactory.getServerSocket(9091, 0, null, params); TServer server = new TSimpleServer(new Args(serverTransport).processor(processor)); // Use this for a multi threaded server // TServer server = new TThreadPoolServer(new TThreadPoolServer.Args(serverTransport).processor(processor)); System.out.println("Starting the secure server..."); server.serve(); } catch (Exception e) { e.printStackTrace(); } } } thrift-0.19.0/tutorial/java/README.md0000644000000000000000000000070614303740367017154 0ustar00rootroot00000000000000Thrift Java Tutorial ================================================== 1) Compile the Java library thrift/lib/java$ make or: thrift/lib/java$ ant 4) Run the tutorial: start server and client with one step: thrift/tutorial/java$ make tutorial or: thrift/tutorial/java$ make tutorialserver thrift/tutorial/java$ make tutorialclient or: thrift/tutorial/java$ ant tutorialserver thrift/tutorial/java$ ant tutorialclient thrift-0.19.0/tutorial/java/build.xml0000644000000000000000000001335414303740367017521 0ustar00rootroot00000000000000 Thrift Java Tutorial tutorial client simple: tutorial client secure: tutorial client simple: tutorial client secure: thrift-0.19.0/tutorial/java/build.properties0000644000000000000000000000036414303740367021112 0ustar00rootroot00000000000000# Maven Ant tasks Jar details mvn.ant.task.version=2.1.3 mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar thrift-0.19.0/tutorial/java/Makefile.in0000644000000000000000000004323714472652522017752 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/java ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ build.properties \ build.xml \ src \ README.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/java/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/java/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean all-local: $(ANT) $(ANT_FLAGS) compile check-local: all $(ANT) $(ANT_FLAGS) test tutorial: all $(ANT) $(ANT_FLAGS) tutorial tutorialserver: all $(ANT) $(ANT_FLAGS) tutorialserver tutorialclient: all $(ANT) $(ANT_FLAGS) tutorialclient # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/nodejs/0000755000000000000000000000000014472652700016233 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/nodejs/Makefile.am0000644000000000000000000000312014303740367020263 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-nodejs/Calculator.js gen-nodejs/SharedService.js: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen js:node -r $< all-local: gen-nodejs/Calculator.js tutorialserver: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeServer.js tutorialclient: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeClient.js tutorialserver_promise: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeServerPromise.js tutorialclient_promise: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeClientPromise.js clean-local: $(RM) -r gen-* EXTRA_DIST = \ NodeServer.js \ NodeClient.js \ NodeServerPromise.js \ NodeClientPromise.js thrift-0.19.0/tutorial/nodejs/NodeClientPromise.js0000644000000000000000000000416114452237057022160 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'); var Calculator = require('./gen-nodejs/Calculator'); var ttypes = require('./gen-nodejs/tutorial_types'); const assert = require('assert'); var transport = thrift.TBufferedTransport; var protocol = thrift.TBinaryProtocol; var connection = thrift.createConnection("localhost", 9090, { transport : transport, protocol : protocol }); connection.on('error', function(err) { assert(false, err); }); // Create a Calculator client with the connection var client = thrift.createClient(Calculator, connection); client.ping() .then(function() { console.log('ping()'); }); client.add(1,1) .then(function(response) { console.log("1+1=" + response); }); work = new ttypes.Work(); work.op = ttypes.Operation.DIVIDE; work.num1 = 1; work.num2 = 0; client.calculate(1, work) .then(function(message) { console.log('Whoa? You know how to divide by zero?'); }) .catch(function(err) { console.log("InvalidOperation " + err); }); work.op = ttypes.Operation.SUBTRACT; work.num1 = 15; work.num2 = 10; client.calculate(1, work) .then(function(value) { console.log('15-10=' + value); return client.getStruct(1); }) .then(function(message) { console.log('Check log: ' + message.value); }) .finally(function() { //close the connection once we're done connection.end(); }); thrift-0.19.0/tutorial/nodejs/NodeServerPromise.js0000644000000000000000000000436514303740367022214 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require("thrift"); var Calculator = require("./gen-nodejs/Calculator"); var ttypes = require("./gen-nodejs/tutorial_types"); var SharedStruct = require("./gen-nodejs/shared_types").SharedStruct; var data = {}; var server = thrift.createServer(Calculator, { ping: function() { console.log("ping()"); }, add: function(n1, n2) { console.log("add(", n1, ",", n2, ")"); return n1 + n2; }, calculate: function(logid, work) { console.log("calculate(", logid, ",", work, ")"); var val = 0; if (work.op == ttypes.Operation.ADD) { val = work.num1 + work.num2; } else if (work.op === ttypes.Operation.SUBTRACT) { val = work.num1 - work.num2; } else if (work.op === ttypes.Operation.MULTIPLY) { val = work.num1 * work.num2; } else if (work.op === ttypes.Operation.DIVIDE) { if (work.num2 === 0) { var x = new ttypes.InvalidOperation(); x.whatOp = work.op; x.why = 'Cannot divide by 0'; throw x; } val = work.num1 / work.num2; } else { var x = new ttypes.InvalidOperation(); x.whatOp = work.op; x.why = 'Invalid operation'; throw x; } var entry = new SharedStruct(); entry.key = logid; entry.value = ""+val; data[logid] = entry; return val; }, getStruct: function(key) { console.log("getStruct(", key, ")"); return data[key]; }, zip: function() { console.log("zip()"); } }); server.listen(9090); thrift-0.19.0/tutorial/nodejs/NodeClient.js0000644000000000000000000000407314303740367020621 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'); var Calculator = require('./gen-nodejs/Calculator'); var ttypes = require('./gen-nodejs/tutorial_types'); const assert = require('assert'); var transport = thrift.TBufferedTransport; var protocol = thrift.TBinaryProtocol; var connection = thrift.createConnection("localhost", 9090, { transport : transport, protocol : protocol }); connection.on('error', function(err) { assert(false, err); }); // Create a Calculator client with the connection var client = thrift.createClient(Calculator, connection); client.ping(function(err, response) { console.log('ping()'); }); client.add(1,1, function(err, response) { console.log("1+1=" + response); }); work = new ttypes.Work(); work.op = ttypes.Operation.DIVIDE; work.num1 = 1; work.num2 = 0; client.calculate(1, work, function(err, message) { if (err) { console.log("InvalidOperation " + err); } else { console.log('Whoa? You know how to divide by zero?'); } }); work.op = ttypes.Operation.SUBTRACT; work.num1 = 15; work.num2 = 10; client.calculate(1, work, function(err, message) { console.log('15-10=' + message); client.getStruct(1, function(err, message){ console.log('Check log: ' + message.value); //close the connection once we're done connection.end(); }); }); thrift-0.19.0/tutorial/nodejs/NodeServer.js0000644000000000000000000000454314303740367020653 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require("thrift"); var Calculator = require("./gen-nodejs/Calculator"); var ttypes = require("./gen-nodejs/tutorial_types"); var SharedStruct = require("./gen-nodejs/shared_types").SharedStruct; var data = {}; var server = thrift.createServer(Calculator, { ping: function(result) { console.log("ping()"); result(null); }, add: function(n1, n2, result) { console.log("add(", n1, ",", n2, ")"); result(null, n1 + n2); }, calculate: function(logid, work, result) { console.log("calculate(", logid, ",", work, ")"); var val = 0; if (work.op == ttypes.Operation.ADD) { val = work.num1 + work.num2; } else if (work.op === ttypes.Operation.SUBTRACT) { val = work.num1 - work.num2; } else if (work.op === ttypes.Operation.MULTIPLY) { val = work.num1 * work.num2; } else if (work.op === ttypes.Operation.DIVIDE) { if (work.num2 === 0) { var x = new ttypes.InvalidOperation(); x.whatOp = work.op; x.why = 'Cannot divide by 0'; result(x); return; } val = work.num1 / work.num2; } else { var x = new ttypes.InvalidOperation(); x.whatOp = work.op; x.why = 'Invalid operation'; result(x); return; } var entry = new SharedStruct(); entry.key = logid; entry.value = ""+val; data[logid] = entry; result(null, val); }, getStruct: function(key, result) { console.log("getStruct(", key, ")"); result(null, data[key]); }, zip: function() { console.log("zip()"); } }); server.listen(9090); thrift-0.19.0/tutorial/nodejs/Makefile.in0000644000000000000000000004371114472652522020310 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/nodejs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ NodeServer.js \ NodeClient.js \ NodeServerPromise.js \ NodeClientPromise.js all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/nodejs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/nodejs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-nodejs/Calculator.js gen-nodejs/SharedService.js: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen js:node -r $< all-local: gen-nodejs/Calculator.js tutorialserver: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeServer.js tutorialclient: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeClient.js tutorialserver_promise: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeServerPromise.js tutorialclient_promise: all NODE_PATH="$(top_builddir)/lib/nodejs:$(top_builddir)/lib/nodejs/lib:$(NODEPATH)" $(NODEJS) NodeClientPromise.js clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/rs/0000755000000000000000000000000014472652701015376 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/rs/Makefile.am0000644000000000000000000000275114303740367017436 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = $(top_builddir)/compiler/cpp/thrift gen-rs/tutorial.rs gen-rs/shared.rs: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) -out src --gen rs -r $< all-local: gen-rs/tutorial.rs $(CARGO) build $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings [ -d bin ] || mkdir bin cp target/debug/tutorial_server bin/tutorial_server cp target/debug/tutorial_client bin/tutorial_client check: all tutorialserver: all bin/tutorial_server tutorialclient: all bin/tutorial_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/shared.rs -$(RM) src/tutorial.rs -$(RM) -r bin EXTRA_DIST = \ Cargo.toml \ src/lib.rs \ src/bin/tutorial_server.rs \ src/bin/tutorial_client.rs \ README.md thrift-0.19.0/tutorial/rs/Cargo.toml0000644000000000000000000000047714370300523017323 0ustar00rootroot00000000000000[package] name = "thrift-tutorial" version = "0.1.0" edition = "2021" license = "Apache-2.0" authors = ["Apache Thrift Developers "] exclude = ["Makefile*", "shared.rs", "tutorial.rs"] publish = false [dependencies] clap = "~2.33" bitflags = "=1.2" [dependencies.thrift] path = "../../lib/rs" thrift-0.19.0/tutorial/rs/src/0000755000000000000000000000000014472652701016165 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/rs/src/bin/0000755000000000000000000000000014472652701016735 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/rs/src/bin/tutorial_client.rs0000644000000000000000000001044214303740367022504 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use clap::{clap_app, value_t}; use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; use thrift::transport::{ ReadHalf, TFramedReadTransport, TFramedWriteTransport, TIoChannel, TTcpChannel, WriteHalf, }; use thrift_tutorial::shared::TSharedServiceSyncClient; use thrift_tutorial::tutorial::{CalculatorSyncClient, Operation, TCalculatorSyncClient, Work}; fn main() { match run() { Ok(()) => println!("tutorial client ran successfully"), Err(e) => { println!("tutorial client failed with error {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { let options = clap_app!(rust_tutorial_client => (version: "0.1.0") (author: "Apache Thrift Developers ") (about: "Thrift Rust tutorial client") (@arg host: --host +takes_value "host on which the tutorial server listens") (@arg port: --port +takes_value "port on which the tutorial server listens") ); let matches = options.get_matches(); // get any passed-in args or the defaults let host = matches.value_of("host").unwrap_or("127.0.0.1"); let port = value_t!(matches, "port", u16).unwrap_or(9090); // build our client and connect to the host:port let mut client = new_client(host, port)?; // alright! // let's start making some calls // let's start with a ping; the server should respond println!("ping!"); client.ping()?; // simple add println!("add"); let res = client.add(1, 2)?; println!("added 1, 2 and got {}", res); let logid = 32; // let's do...a multiply! let res = client.calculate(logid, Work::new(7, 8, Operation::MULTIPLY, None))?; println!("multiplied 7 and 8 and got {}", res); // let's get the log for it let res = client.get_struct(logid /* 32 */)?; println!("got log {:?} for operation {}", res, logid); // ok - let's be bad :( // do a divide by 0 // logid doesn't matter; won't be recorded let res = client.calculate(77, Work::new(2, 0, Operation::DIVIDE, "we bad".to_owned())); // we should have gotten an exception back match res { Ok(v) => panic!("should not have succeeded with result {}", v), Err(e) => println!("divide by zero failed with error {:?}", e), } // let's do a one-way call println!("zip"); client.zip()?; // and then close out with a final ping println!("ping!"); client.ping()?; Ok(()) } type ClientInputProtocol = TCompactInputProtocol>>; type ClientOutputProtocol = TCompactOutputProtocol>>; fn new_client( host: &str, port: u16, ) -> thrift::Result> { let mut c = TTcpChannel::new(); // open the underlying TCP stream println!("connecting to tutorial server on {}:{}", host, port); c.open(&format!("{}:{}", host, port))?; // clone the TCP channel into two halves, one which // we'll use for reading, the other for writing let (i_chan, o_chan) = c.split()?; // wrap the raw sockets (slow) with a buffered transport of some kind let i_tran = TFramedReadTransport::new(i_chan); let o_tran = TFramedWriteTransport::new(o_chan); // now create the protocol implementations let i_prot = TCompactInputProtocol::new(i_tran); let o_prot = TCompactOutputProtocol::new(o_tran); // we're done! Ok(CalculatorSyncClient::new(i_prot, o_prot)) } thrift-0.19.0/tutorial/rs/src/bin/tutorial_server.rs0000644000000000000000000001405314303740367022536 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::collections::HashMap; use std::convert::{From, Into}; use std::default::Default; use std::sync::Mutex; use clap::{clap_app, value_t}; use thrift::protocol::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory}; use thrift::server::TServer; use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory}; use thrift_tutorial::shared::{SharedServiceSyncHandler, SharedStruct}; use thrift_tutorial::tutorial::{CalculatorSyncHandler, CalculatorSyncProcessor}; use thrift_tutorial::tutorial::{InvalidOperation, Operation, Work}; fn main() { match run() { Ok(()) => println!("tutorial server ran successfully"), Err(e) => { println!("tutorial server failed with error {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { let options = clap_app!(rust_tutorial_server => (version: "0.1.0") (author: "Apache Thrift Developers ") (about: "Thrift Rust tutorial server") (@arg port: --port +takes_value "port on which the tutorial server listens") ); let matches = options.get_matches(); let port = value_t!(matches, "port", u16).unwrap_or(9090); let listen_address = format!("127.0.0.1:{}", port); println!("binding to {}", listen_address); let i_tran_fact = TFramedReadTransportFactory::new(); let i_prot_fact = TCompactInputProtocolFactory::new(); let o_tran_fact = TFramedWriteTransportFactory::new(); let o_prot_fact = TCompactOutputProtocolFactory::new(); // demux incoming messages let processor = CalculatorSyncProcessor::new(CalculatorServer { ..Default::default() }); // create the server and start listening let mut server = TServer::new( i_tran_fact, i_prot_fact, o_tran_fact, o_prot_fact, processor, 10, ); server.listen(&listen_address) } /// Handles incoming Calculator service calls. struct CalculatorServer { log: Mutex>, } impl Default for CalculatorServer { fn default() -> CalculatorServer { CalculatorServer { log: Mutex::new(HashMap::new()), } } } // since Calculator extends SharedService we have to implement the // handler for both traits. // // SharedService handler impl SharedServiceSyncHandler for CalculatorServer { fn handle_get_struct(&self, key: i32) -> thrift::Result { let log = self.log.lock().unwrap(); log.get(&key) .cloned() .ok_or_else(|| format!("could not find log for key {}", key).into()) } } // Calculator handler impl CalculatorSyncHandler for CalculatorServer { fn handle_ping(&self) -> thrift::Result<()> { println!("pong!"); Ok(()) } fn handle_add(&self, num1: i32, num2: i32) -> thrift::Result { println!("handling add: n1:{} n2:{}", num1, num2); Ok(num1 + num2) } fn handle_calculate(&self, logid: i32, w: Work) -> thrift::Result { println!("handling calculate: l:{}, w:{:?}", logid, w); let res = if let Some(ref op) = w.op { if w.num1.is_none() || w.num2.is_none() { Err(InvalidOperation { what_op: Some(op.into()), why: Some("no operands specified".to_owned()), }) } else { // so that I don't have to call unwrap() multiple times below let num1 = w.num1.as_ref().expect("operands checked"); let num2 = w.num2.as_ref().expect("operands checked"); match *op { Operation::ADD => Ok(num1 + num2), Operation::SUBTRACT => Ok(num1 - num2), Operation::MULTIPLY => Ok(num1 * num2), Operation::DIVIDE => { if *num2 == 0 { Err(InvalidOperation { what_op: Some(op.into()), why: Some("divide by 0".to_owned()), }) } else { Ok(num1 / num2) } } _ => { let op_val: i32 = op.into(); Err(InvalidOperation { what_op: Some(op_val), why: Some(format!("unsupported operation type '{}'", op_val)), }) } } } } else { Err(InvalidOperation::new( None, "no operation specified".to_owned(), )) }; // if the operation was successful log it if let Ok(ref v) = res { let mut log = self.log.lock().unwrap(); log.insert(logid, SharedStruct::new(logid, format!("{}", v))); } // the try! macro automatically maps errors // but, since we aren't using that here we have to map errors manually // // exception structs defined in the IDL have an auto-generated // impl of From::from res.map_err(From::from) } fn handle_zip(&self) -> thrift::Result<()> { println!("handling zip"); Ok(()) } } thrift-0.19.0/tutorial/rs/src/lib.rs0000644000000000000000000000150014303740367017274 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. pub mod shared; pub mod tutorial; thrift-0.19.0/tutorial/rs/README.md0000644000000000000000000001454614303740367016666 0ustar00rootroot00000000000000# Rust Language Bindings for Thrift ## Getting Started 1. Get the [Thrift compiler](https://thrift.apache.org). 2. Add the thrift crate to your `Cargo.toml`. ```toml thrift = "x.y.z" # x.y.z is the version of the thrift compiler ``` 3. Generate Rust sources for your IDL (for example, `Tutorial.thrift`). ```shell thrift -out my_rust_program/src --gen rs -r Tutorial.thrift ``` 4. Use the generated source in your code. ```rust // generated Rust module from Thrift IDL mod tutorial; use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; use thrift::protocol::{TInputProtocol, TOutputProtocol}; use thrift::transport::{TFramedReadTransport, TFramedWriteTransport}; use thrift::transport::{TIoChannel, TTcpChannel}; use tutorial::{CalculatorSyncClient, TCalculatorSyncClient}; use tutorial::{Operation, Work}; fn main() { match run() { Ok(()) => println!("client ran successfully"), Err(e) => { println!("client failed with {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { // // build client // println!("connect to server on 127.0.0.1:9090"); let mut c = TTcpChannel::new(); c.open("127.0.0.1:9090")?; let (i_chan, o_chan) = c.split()?; let i_prot = TCompactInputProtocol::new( TFramedReadTransport::new(i_chan) ); let o_prot = TCompactOutputProtocol::new( TFramedWriteTransport::new(o_chan) ); let mut client = CalculatorSyncClient::new(i_prot, o_prot); // // alright! - let's make some calls // // two-way, void return client.ping()?; // two-way with some return let res = client.calculate( 72, Work::new(7, 8, Operation::Multiply, None) )?; println!("multiplied 7 and 8, got {}", res); // two-way and returns a Thrift-defined exception let res = client.calculate( 77, Work::new(2, 0, Operation::Divide, None) ); match res { Ok(v) => panic!("shouldn't have succeeded with result {}", v), Err(e) => println!("divide by zero failed with {:?}", e), } // one-way client.zip()?; // done! Ok(()) } ``` ## Code Generation ### Thrift Files and Generated Modules The Thrift code generator takes each Thrift file and generates a Rust module with the same name snake-cased. For example, running the compiler on `ThriftTest.thrift` creates `thrift_test.rs`. To use these generated files add `mod ...` and `use ...` declarations to your `lib.rs` or `main.rs` - one for each generated file. ### Results and Errors The Thrift runtime library defines a `thrift::Result` and a `thrift::Error` type, both of which are used throughout the runtime library and in all generated code. Conversions are defined from `std::io::Error`, `str` and `String` into `thrift::Error`. ### Thrift Type and their Rust Equivalents Thrift defines a number of types, each of which is translated into its Rust equivalent by the code generator. * Primitives (bool, i8, i16, i32, i64, double, string, binary) * Typedefs * Enums * Containers * Structs * Unions * Exceptions * Services * Constants (primitives, containers, structs) In addition, unless otherwise noted, thrift includes are translated into `use ...` statements in the generated code, and all declarations, parameters, traits and types in the generated code are namespaced appropriately. The following subsections cover each type and their generated Rust equivalent. ### Primitives Thrift primitives have straightforward Rust equivalents. * bool: `bool` * i8: `i8` * i16: `i16` * i32: `i32` * i64: `i64` * double: `OrderedFloat` * string: `String` * binary: `Vec` ### Typedefs A typedef is translated to a `pub type` declaration. ```thrift typedef i64 UserId typedef map MapType ``` ```rust pub type UserId = i64; pub type MapType = BTreeMap; ``` ### Enums A Thrift enum is represented as a Rust enum, and each variant is transcribed 1:1. ```thrift enum Numberz { ONE = 1, TWO, THREE, FIVE = 5, SIX, EIGHT = 8 } ``` ```rust #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub enum Numberz { ONE = 1, TWO = 2, THREE = 3, FIVE = 5, SIX = 6, EIGHT = 8, } impl TryFrom for Numberz { // ... } ``` ### Containers Thrift has three container types: list, set and map. They are translated into Rust `Vec`, `BTreeSet` and `BTreeMap` respectively. Any Thrift type (this includes structs, enums and typedefs) can be a list/set element or a map key/value. #### List ```thrift list numbers ``` ```rust numbers: Vec ``` #### Set ```thrift set numbers ``` ```rust numbers: BTreeSet ``` #### Map ```thrift map numbers ``` ```rust numbers: BTreeMap ``` ### Structs A Thrift struct is represented as a Rust struct, and each field transcribed 1:1. ```thrift struct CrazyNesting { 1: string string_field, 2: optional set set_field, 3: required list< map, map>>>> > 4: binary binary_field } ``` ```rust #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct CrazyNesting { pub string_field: Option, pub set_field: Option>, pub list_field: Vec< BTreeMap< BTreeSet, BTreeMap>>> > >, pub binary_field: Option>, } impl CrazyNesting { pub fn read_from_in_protocol(i_prot: &mut TInputProtocol) -> thrift::Result { // ... } pub fn write_to_out_protocol(&self, o_prot: &mut TOutputProtocol) -> thrift::Result<()> { // ... } } ``` ##### Optionality Thrift has 3 "optionality" types: 1. Required 2. Optional 3. Default The Rust code generator encodes *Required* fields as the bare type itself, while *Optional* and *Default* fields are encoded as `Option`. ```thrift struct Foo { 1: required string bar // 1. required 2: optional string baz // 2. optional 3: string qux // 3. default } ``` ```rust pub struct Foo { bar: String, // 1. required baz: Option, // 2. optional qux: Option, // 3. default } ``` ## Known Issues * Struct constants are not supported * Map, list and set constants require a const holder struct thrift-0.19.0/tutorial/rs/Makefile.in0000644000000000000000000004350314472652522017451 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/rs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ Cargo.toml \ src/lib.rs \ src/bin/tutorial_server.rs \ src/bin/tutorial_client.rs \ README.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/rs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/rs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-rs/tutorial.rs gen-rs/shared.rs: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) -out src --gen rs -r $< all-local: gen-rs/tutorial.rs $(CARGO) build $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings [ -d bin ] || mkdir bin cp target/debug/tutorial_server bin/tutorial_server cp target/debug/tutorial_client bin/tutorial_client check: all tutorialserver: all bin/tutorial_server tutorialclient: all bin/tutorial_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/shared.rs -$(RM) src/tutorial.rs -$(RM) -r bin # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/rb/0000755000000000000000000000000014472652677015371 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/rb/Makefile.am0000644000000000000000000000211114303740367017403 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-rb/calculator.rb gen-rb/shared_service.rb: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen rb -r $< all-local: gen-rb/calculator.rb tutorialserver: all ${RUBY} RubyServer.rb tutorialclient: all ${RUBY} RubyClient.rb clean-local: $(RM) -r gen-* EXTRA_DIST = \ RubyServer.rb \ RubyClient.rb thrift-0.19.0/tutorial/rb/RubyClient.rb0000777000000000000000000000347514062750227017777 0ustar00rootroot00000000000000#!/usr/bin/env ruby # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.push('gen-rb') $:.unshift '../../lib/rb/lib' require 'thrift' require 'calculator' begin port = ARGV[0] || 9090 transport = Thrift::BufferedTransport.new(Thrift::Socket.new('localhost', port)) protocol = Thrift::BinaryProtocol.new(transport) client = Calculator::Client.new(protocol) transport.open() client.ping() print "ping()\n" sum = client.add(1,1) print "1+1=", sum, "\n" sum = client.add(1,4) print "1+4=", sum, "\n" work = Work.new() work.op = Operation::SUBTRACT work.num1 = 15 work.num2 = 10 diff = client.calculate(1, work) print "15-10=", diff, "\n" log = client.getStruct(1) print "Log: ", log.value, "\n" begin work.op = Operation::DIVIDE work.num1 = 1 work.num2 = 0 quot = client.calculate(1, work) puts "Whoa, we can divide by 0 now?" rescue InvalidOperation => io print "InvalidOperation: ", io.why, "\n" end client.zip() print "zip\n" transport.close() rescue Thrift::Exception => tx print 'Thrift::Exception: ', tx.message, "\n" end thrift-0.19.0/tutorial/rb/RubyServer.rb0000777000000000000000000000445414062750227020025 0ustar00rootroot00000000000000#!/usr/bin/env ruby # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.push('gen-rb') $:.unshift '../../lib/rb/lib' require 'thrift' require 'calculator' require 'shared_types' class CalculatorHandler def initialize() @log = {} end def ping() puts "ping()" end def add(n1, n2) print "add(", n1, ",", n2, ")\n" return n1 + n2 end def calculate(logid, work) print "calculate(", logid, ", {", work.op, ",", work.num1, ",", work.num2,"})\n" if work.op == Operation::ADD val = work.num1 + work.num2 elsif work.op == Operation::SUBTRACT val = work.num1 - work.num2 elsif work.op == Operation::MULTIPLY val = work.num1 * work.num2 elsif work.op == Operation::DIVIDE if work.num2 == 0 x = InvalidOperation.new() x.whatOp = work.op x.why = "Cannot divide by 0" raise x end val = work.num1 / work.num2 else x = InvalidOperation.new() x.whatOp = work.op x.why = "Invalid operation" raise x end entry = SharedStruct.new() entry.key = logid entry.value = "#{val}" @log[logid] = entry return val end def getStruct(key) print "getStruct(", key, ")\n" return @log[key] end def zip() print "zip\n" end end handler = CalculatorHandler.new() processor = Calculator::Processor.new(handler) transport = Thrift::ServerSocket.new(9090) transportFactory = Thrift::BufferedTransportFactory.new() server = Thrift::SimpleServer.new(processor, transport, transportFactory) puts "Starting the server..." server.serve() puts "done." thrift-0.19.0/tutorial/rb/Makefile.in0000644000000000000000000004266714472652522017442 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/rb ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ RubyServer.rb \ RubyClient.rb all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/rb/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/rb/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-rb/calculator.rb gen-rb/shared_service.rb: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen rb -r $< all-local: gen-rb/calculator.rb tutorialserver: all ${RUBY} RubyServer.rb tutorialclient: all ${RUBY} RubyClient.rb clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/cl/0000755000000000000000000000000014472652701015350 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/cl/load-locally.lisp0000644000000000000000000000166014370300523020605 0ustar00rootroot00000000000000(in-package #:cl-user) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. ;;;; Just a script for loading the library itself, using bundled dependencies. ;;;; This is an identical copy of the file in lib/cl. (require "asdf") (load (merge-pathnames "externals/bundle.lisp" *load-truename*)) (asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*)) (asdf:load-system :thrift) thrift-0.19.0/tutorial/cl/tutorial-implementation.lisp0000644000000000000000000000325014370300523023114 0ustar00rootroot00000000000000(in-package #:tutorial-implementation) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (defun tutorial.calculator-implementation:ping () (format t "ping()~%")) (defun tutorial.calculator-implementation:add (num1 num2) (format t "add(~a, ~a)~%" num1 num2) (+ num1 num2)) (defun tutorial.calculator-implementation:calculate (logid work) (format t "calculate(~a, ~a)~%" logid work) (handler-case (let* ((num1 (tutorial:work-num1 work)) (num2 (tutorial:work-num2 work)) (op (tutorial:work-op work)) (result (cond ((= op tutorial:operation.add) (+ num1 num2)) ((= op tutorial:operation.subtract) (- num1 num2)) ((= op tutorial:operation.multiply) (* num1 num2)) ((= op tutorial:operation.divide) (/ num1 num2))))) (shared-implementation::add-log logid result) result) (division-by-zero () (error 'tutorial:invalidoperation :why "Division by zero." :what-op (tutorial:work-op work))))) (defun tutorial.calculator-implementation:zip () (format t "zip()~%")) thrift-0.19.0/tutorial/cl/Makefile.am0000755000000000000000000000407314370300523017400 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. setup-local-lisp-env: ../../lib/cl/ensure-externals.sh bash ../../lib/cl/ensure-externals.sh gen-cl: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen cl -r $< ALL_FILE_PREREQS = \ load-locally.lisp \ make-tutorial-server.lisp \ make-tutorial-client.lisp \ shared-implementation.lisp \ thrift-tutorial.asd \ tutorial-implementation.lisp # NOTE: the server and client cannot be built in parallel # because on loading the make-tutorial-* scripts SBCL will # attempt to compile their dependencies. Unfortunately, # because their dependencies are shared, parallel jobs can # end up overwriting or corrupting the compiled files all-local: gen-cl setup-local-lisp-env $(ALL_FILE_PREREQS) $(SBCL) --script make-tutorial-server.lisp $(SBCL) --script make-tutorial-client.lisp tutorialserver: all ./TutorialServer tutorialclient: all ./TutorialClient clean-local: -$(RM) -r gen-* -$(RM) -r externals -$(RM) -r quicklisp -$(RM) -r lib -$(RM) quicklisp.lisp -$(RM) backport-update.zip -$(RM) shared-implementation.fasl -$(RM) tutorial-implementation.fasl -$(RM) TutorialServer -$(RM) TutorialClient EXTRA_DIST = \ tutorial-implementation.lisp \ shared-implementation.lisp \ thrift-tutorial.asd \ make-tutorial-server.lisp \ make-tutorial-client.lisp \ load-locally.lisp thrift-0.19.0/tutorial/cl/make-tutorial-client.lisp0000644000000000000000000000534614370300523022270 0ustar00rootroot00000000000000(in-package #:cl-user) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (require "asdf") (load (merge-pathnames "load-locally.lisp" *load-truename*)) (require "sb-grovel") ;; necessary for :net.didierverna.clon.termio (asdf:load-asd (first (directory (merge-pathnames "../../lib/cl/externals/software/clon-*/termio/net.didierverna.clon.termio.asd" *load-truename*)))) (asdf:load-system :net.didierverna.clon) (asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*)) (asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*)) (asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*)) (asdf:load-system :thrift-tutorial) (net.didierverna.clon:nickname-package) (defun main () "Entry point for the binary." (thrift:with-client (prot #u"thrift://127.0.0.1:9090") (tutorial.calculator:ping prot) (format t "ping()~%") (format t "1 + 1 = ~a~%" (tutorial.calculator:add prot 1 1)) (let ((work-instance (tutorial:make-work :num1 5 :num2 0 :op tutorial:operation.divide :comment "Booya!"))) (handler-case (format t "5 / 0 = ~a - Oh, really? An exception should have been thrown here.~%" (tutorial.calculator:calculate prot 1 work-instance)) (tutorial:invalidoperation (e) (format t "---~%(Expected) Invalid Operation caught: ~%~a~%---~%" e)))) (let ((work-instance (tutorial:make-work :num1 15 :num2 10 :op tutorial:operation.subtract :comment "Playing nice this time."))) (handler-case (format t "15 - 10 = ~a~%" (tutorial.calculator:calculate prot 1 work-instance)) (tutorial:invalidoperation (e) (format t "---~%(Unexpected) Invalid Operation caught: ~%~a~%---~%" e)))) (format t "Check log: ~a~%" (shared.shared-service:get-struct prot 1)))) (clon:dump "TutorialClient" main) thrift-0.19.0/tutorial/cl/thrift-tutorial.asd0000644000000000000000000000137014370300523021170 0ustar00rootroot00000000000000;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (asdf:defsystem #:thrift-tutorial :depends-on (#:thrift-gen-tutorial) :serial t :components ((:file "shared-implementation") (:file "tutorial-implementation"))) thrift-0.19.0/tutorial/cl/Makefile.in0000644000000000000000000004465114472652521017427 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/cl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ALL_FILE_PREREQS = \ load-locally.lisp \ make-tutorial-server.lisp \ make-tutorial-client.lisp \ shared-implementation.lisp \ thrift-tutorial.asd \ tutorial-implementation.lisp EXTRA_DIST = \ tutorial-implementation.lisp \ shared-implementation.lisp \ thrift-tutorial.asd \ make-tutorial-server.lisp \ make-tutorial-client.lisp \ load-locally.lisp all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/cl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/cl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile setup-local-lisp-env: ../../lib/cl/ensure-externals.sh bash ../../lib/cl/ensure-externals.sh gen-cl: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen cl -r $< # NOTE: the server and client cannot be built in parallel # because on loading the make-tutorial-* scripts SBCL will # attempt to compile their dependencies. Unfortunately, # because their dependencies are shared, parallel jobs can # end up overwriting or corrupting the compiled files all-local: gen-cl setup-local-lisp-env $(ALL_FILE_PREREQS) $(SBCL) --script make-tutorial-server.lisp $(SBCL) --script make-tutorial-client.lisp tutorialserver: all ./TutorialServer tutorialclient: all ./TutorialClient clean-local: -$(RM) -r gen-* -$(RM) -r externals -$(RM) -r quicklisp -$(RM) -r lib -$(RM) quicklisp.lisp -$(RM) backport-update.zip -$(RM) shared-implementation.fasl -$(RM) tutorial-implementation.fasl -$(RM) TutorialServer -$(RM) TutorialClient # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/cl/shared-implementation.lisp0000644000000000000000000000171214370300523022520 0ustar00rootroot00000000000000(in-package #:shared-implementation) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (defvar *structs* (make-hash-table)) (defun shared.shared-service-implementation:get-struct (key) (format t "getStruct(~a)~%" key) (gethash key *structs*)) (defun add-log (key value) (setf (gethash key *structs*) (make-instance 'shared:sharedstruct :key key :value (write-to-string value)))) thrift-0.19.0/tutorial/cl/make-tutorial-server.lisp0000644000000000000000000000267314370300523022320 0ustar00rootroot00000000000000(in-package #:cl-user) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (require "asdf") (load (merge-pathnames "load-locally.lisp" *load-truename*)) (require "sb-grovel") ;; necessary for :net.didierverna.clon.termio (asdf:load-asd (first (directory (merge-pathnames "../../lib/cl/externals/software/clon-*/termio/net.didierverna.clon.termio.asd" *load-truename*)))) (asdf:load-system :net.didierverna.clon) (asdf:load-asd (merge-pathnames "gen-cl/shared/thrift-gen-shared.asd" *load-truename*)) (asdf:load-asd (merge-pathnames "gen-cl/tutorial/thrift-gen-tutorial.asd" *load-truename*)) (asdf:load-asd (merge-pathnames "thrift-tutorial.asd" *load-truename*)) (asdf:load-system :thrift-tutorial) (net.didierverna.clon:nickname-package) (defun main () "Entry point for the binary." (thrift:serve #u"thrift://127.0.0.1:9090" tutorial:calculator)) (clon:dump "TutorialServer" main) thrift-0.19.0/tutorial/shared.thrift0000644000000000000000000000240214370300523017425 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * This Thrift file can be included by other Thrift files that want to share * these definitions. */ namespace cl shared namespace cpp shared namespace d share // "shared" would collide with the eponymous D keyword. namespace dart shared namespace java shared namespace perl shared namespace php shared namespace haxe shared namespace netstd shared struct SharedStruct { 1: i32 key 2: string value } service SharedService { SharedStruct getStruct(1: i32 key) } thrift-0.19.0/tutorial/php/0000755000000000000000000000000014472652701015541 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/php/Makefile.am0000644000000000000000000000220614303740367017574 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-php/tutorial/Calculator.php gen-php/shared/SharedService.php: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen php:server -r $< all-local: gen-php/tutorial/Calculator.php tutorialserver: all ${PYTHON} runserver.py tutorialclient: all ${PHP} PhpClient.php --http clean-local: $(RM) -r gen-* EXTRA_DIST = \ PhpServer.php \ PhpClient.php \ runserver.py thrift-0.19.0/tutorial/php/runserver.py0000777000000000000000000000214414062750227020153 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os import BaseHTTPServer import CGIHTTPServer # chdir(2) into the tutorial directory. os.chdir(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) class Handler(CGIHTTPServer.CGIHTTPRequestHandler): cgi_directories = ['/php'] BaseHTTPServer.HTTPServer(('', 8080), Handler).serve_forever() thrift-0.19.0/tutorial/php/PhpServer.php0000777000000000000000000000737014062750227020203 0ustar00rootroot00000000000000#!/usr/bin/env php registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib'); $loader->registerNamespace('shared', $GEN_DIR); $loader->registerNamespace('tutorial', $GEN_DIR); $loader->register(); /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This is not a stand-alone server. It should be run as a normal * php web script (like through Apache's mod_php) or as a cgi script * (like with the included runserver.py). You can connect to it with * THttpClient in any language that supports it. The PHP tutorial client * will work if you pass it the argument "--http". */ if (php_sapi_name() == 'cli') { ini_set("display_errors", "stderr"); } use Thrift\Protocol\TBinaryProtocol; use Thrift\Transport\TPhpStream; use Thrift\Transport\TBufferedTransport; class CalculatorHandler implements \tutorial\CalculatorIf { protected $log = array(); public function ping() { error_log("ping()"); } public function add($num1, $num2) { error_log("add({$num1}, {$num2})"); return $num1 + $num2; } public function calculate($logid, \tutorial\Work $w) { error_log("calculate({$logid}, {{$w->op}, {$w->num1}, {$w->num2}})"); switch ($w->op) { case \tutorial\Operation::ADD: $val = $w->num1 + $w->num2; break; case \tutorial\Operation::SUBTRACT: $val = $w->num1 - $w->num2; break; case \tutorial\Operation::MULTIPLY: $val = $w->num1 * $w->num2; break; case \tutorial\Operation::DIVIDE: if ($w->num2 == 0) { $io = new \tutorial\InvalidOperation(); $io->whatOp = $w->op; $io->why = "Cannot divide by 0"; throw $io; } $val = $w->num1 / $w->num2; break; default: $io = new \tutorial\InvalidOperation(); $io->whatOp = $w->op; $io->why = "Invalid Operation"; throw $io; } $log = new \shared\SharedStruct(); $log->key = $logid; $log->value = (string)$val; $this->log[$logid] = $log; return $val; } public function getStruct($key) { error_log("getStruct({$key})"); // This actually doesn't work because the PHP interpreter is // restarted for every request. //return $this->log[$key]; return new \shared\SharedStruct(array("key" => $key, "value" => "PHP is stateless!")); } public function zip() { error_log("zip()"); } }; header('Content-Type', 'application/x-thrift'); if (php_sapi_name() == 'cli') { echo "\r\n"; } $handler = new CalculatorHandler(); $processor = new \tutorial\CalculatorProcessor($handler); $transport = new TBufferedTransport(new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W)); $protocol = new TBinaryProtocol($transport, true, true); $transport->open(); $processor->process($protocol, $protocol); $transport->close(); thrift-0.19.0/tutorial/php/Makefile.in0000644000000000000000000004276714472652522017627 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/php ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ PhpServer.php \ PhpClient.php \ runserver.py all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/php/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/php/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-php/tutorial/Calculator.php gen-php/shared/SharedService.php: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen php:server -r $< all-local: gen-php/tutorial/Calculator.php tutorialserver: all ${PYTHON} runserver.py tutorialclient: all ${PHP} PhpClient.php --http clean-local: $(RM) -r gen-* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/php/PhpClient.php0000777000000000000000000000467714062750227020162 0ustar00rootroot00000000000000#!/usr/bin/env php registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib'); $loader->registerNamespace('shared', $GEN_DIR); $loader->registerNamespace('tutorial', $GEN_DIR); $loader->register(); /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ use Thrift\Protocol\TBinaryProtocol; use Thrift\Transport\TSocket; use Thrift\Transport\THttpClient; use Thrift\Transport\TBufferedTransport; use Thrift\Exception\TException; try { if (array_search('--http', $argv)) { $socket = new THttpClient('localhost', 8080, '/php/PhpServer.php'); } else { $socket = new TSocket('localhost', 9090); } $transport = new TBufferedTransport($socket, 1024, 1024); $protocol = new TBinaryProtocol($transport); $client = new \tutorial\CalculatorClient($protocol); $transport->open(); $client->ping(); print "ping()\n"; $sum = $client->add(1,1); print "1+1=$sum\n"; $work = new \tutorial\Work(); $work->op = \tutorial\Operation::DIVIDE; $work->num1 = 1; $work->num2 = 0; try { $client->calculate(1, $work); print "Whoa! We can divide by zero?\n"; } catch (\tutorial\InvalidOperation $io) { print "InvalidOperation: $io->why\n"; } $work->op = \tutorial\Operation::SUBTRACT; $work->num1 = 15; $work->num2 = 10; $diff = $client->calculate(1, $work); print "15-10=$diff\n"; $log = $client->getStruct(1); print "Log: $log->value\n"; $transport->close(); } catch (TException $tx) { print 'TException: '.$tx->getMessage()."\n"; } ?> thrift-0.19.0/tutorial/erl/0000777000000000000000000000000014303740367015537 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/erl/client.sh0000777000000000000000000000233414062750227017354 0ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ERL_THRIFT=../../lib/erl if ! [ -d ${ERL_THRIFT}/ebin ]; then echo "Please build the Thrift library by running \`make' in ${ERL_THRIFT}" exit 1 fi if ! [ -d gen-erl ]; then ../../compiler/cpp/thrift -r --gen erl ../tutorial.thrift fi erlc -I ${ERL_THRIFT}/include -I ${ERL_THRIFT}/ebin \ -I gen-erl -o gen-erl gen-erl/*.erl && erlc -I ${ERL_THRIFT}/include -I gen-erl *.erl && erl +K true -pa ${ERL_THRIFT}/ebin -pa gen-erl thrift-0.19.0/tutorial/erl/server.erl0000644000000000000000000000463114303740367017551 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(server). -include("calculator_thrift.hrl"). -export([start/0, start/1, handle_function/2, stop/1, ping/0, add/2, calculate/2, getStruct/1, zip/0]). debug(Format, Data) -> error_logger:info_msg(Format, Data). ping() -> debug("ping()",[]), ok. add(N1, N2) -> debug("add(~p,~p)",[N1,N2]), N1+N2. calculate(Logid, Work) -> { Op, Num1, Num2 } = { Work#'Work'.op, Work#'Work'.num1, Work#'Work'.num2 }, debug("calculate(~p, {~p,~p,~p})", [Logid, Op, Num1, Num2]), case Op of ?TUTORIAL_OPERATION_ADD -> Num1 + Num2; ?TUTORIAL_OPERATION_SUBTRACT -> Num1 - Num2; ?TUTORIAL_OPERATION_MULTIPLY -> Num1 * Num2; ?TUTORIAL_OPERATION_DIVIDE when Num2 == 0 -> throw(#'InvalidOperation'{whatOp=Op, why="Cannot divide by 0"}); ?TUTORIAL_OPERATION_DIVIDE -> Num1 div Num2; _Else -> throw(#'InvalidOperation'{whatOp=Op, why="Invalid operation"}) end. getStruct(Key) -> debug("getStruct(~p)", [Key]), #'SharedStruct'{key=Key, value="RARG"}. zip() -> debug("zip", []), ok. %% start() -> start(9090). start(Port) -> Handler = ?MODULE, thrift_socket_server:start([{handler, Handler}, {service, calculator_thrift}, {port, Port}, {name, tutorial_server}]). stop(Server) -> thrift_socket_server:stop(Server). handle_function(Function, Args) when is_atom(Function), is_tuple(Args) -> case apply(?MODULE, Function, tuple_to_list(Args)) of ok -> ok; Reply -> {reply, Reply} end. thrift-0.19.0/tutorial/erl/json_client.erl0000644000000000000000000000614614303740367020555 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% The JSON protocol over HTTP implementation was created by %% Peter Neumark based on %% the binary protocol + socket tutorial. Use with the same server %% that the Javascript tutorial uses! -module(json_client). -include("calculator_thrift.hrl"). -export([t/0]). %% Client constructor for the http transports %% with the json protocol new_client(Host, Path, Service, _Options) -> {ProtoOpts, TransOpts} = {[],[]}, TransportFactory = fun() -> thrift_http_transport:new(Host, Path, TransOpts) end, {ok, ProtocolFactory} = thrift_json_protocol:new_protocol_factory( TransportFactory, ProtoOpts), {ok, Protocol} = ProtocolFactory(), thrift_client:new(Protocol, Service). p(X) -> io:format("~p~n", [X]), ok. t() -> inets:start(), {ok, Client0} = new_client("127.0.0.1:8088", "/thrift/service/tutorial/", calculator_thrift, []), {Client1, {ok, ok}} = thrift_client:call(Client0, ping, []), io:format("ping~n", []), {Client2, {ok, Sum}} = thrift_client:call(Client1, add, [1, 1]), io:format("1+1=~p~n", [Sum]), {Client3, {ok, Sum1}} = thrift_client:call(Client2, add, [1, 4]), io:format("1+4=~p~n", [Sum1]), Work = #'Work'{op=?TUTORIAL_OPERATION_SUBTRACT, num1=15, num2=10}, {Client4, {ok, Diff}} = thrift_client:call(Client3, calculate, [1, Work]), io:format("15-10=~p~n", [Diff]), {Client5, {ok, Log}} = thrift_client:call(Client4, getStruct, [1]), io:format("Log: ~p~n", [Log]), Client6 = try Work1 = #'Work'{op=?TUTORIAL_OPERATION_DIVIDE, num1=1, num2=0}, {ClientS1, {ok, _Quot}} = thrift_client:call(Client5, calculate, [2, Work1]), io:format("LAME: exception handling is broken~n", []), ClientS1 catch throw:{ClientS2, Z} -> io:format("Got exception where expecting - the " ++ "following is NOT a problem!!!~n"), p(Z), ClientS2 end, {Client7, {ok, ok}} = thrift_client:call(Client6, zip, []), io:format("zip~n", []), {_Client8, ok} = thrift_client:close(Client7), ok. thrift-0.19.0/tutorial/erl/client.erl0000644000000000000000000000473314303740367017524 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(client). -include("calculator_thrift.hrl"). -export([t/0]). p(X) -> io:format("~p~n", [X]), ok. t() -> Port = 9090, {ok, Client0} = thrift_client_util:new("127.0.0.1", Port, calculator_thrift, []), {Client1, {ok, ok}} = thrift_client:call(Client0, ping, []), io:format("ping~n", []), {Client2, {ok, Sum}} = thrift_client:call(Client1, add, [1, 1]), io:format("1+1=~p~n", [Sum]), {Client3, {ok, Sum1}} = thrift_client:call(Client2, add, [1, 4]), io:format("1+4=~p~n", [Sum1]), Work = #'Work'{op=?TUTORIAL_OPERATION_SUBTRACT, num1=15, num2=10}, {Client4, {ok, Diff}} = thrift_client:call(Client3, calculate, [1, Work]), io:format("15-10=~p~n", [Diff]), {Client5, {ok, Log}} = thrift_client:call(Client4, getStruct, [1]), io:format("Log: ~p~n", [Log]), Client6 = try Work1 = #'Work'{op=?TUTORIAL_OPERATION_DIVIDE, num1=1, num2=0}, {ClientS1, {ok, _Quot}} = thrift_client:call(Client5, calculate, [2, Work1]), io:format("LAME: exception handling is broken~n", []), ClientS1 catch throw:{ClientS2, Z} -> io:format("Got exception where expecting - the " ++ "following is NOT a problem!!!~n"), p(Z), ClientS2 end, {Client7, {ok, ok}} = thrift_client:call(Client6, zip, []), io:format("zip~n", []), {_Client8, ok} = thrift_client:close(Client7), ok. thrift-0.19.0/tutorial/erl/README.md0000644000000000000000000000031714303740367017013 0ustar00rootroot00000000000000To try things out, run % ./server.sh Erlang R14B (erts-5.8.1) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.8.1 (abort with ^G) > server:start(). > client:t(). thrift-0.19.0/tutorial/erl/server.sh0000777000000000000000000000233414062750227017404 0ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ERL_THRIFT=../../lib/erl if ! [ -d ${ERL_THRIFT}/ebin ]; then echo "Please build the Thrift library by running \`make' in ${ERL_THRIFT}" exit 1 fi if ! [ -d gen-erl ]; then ../../compiler/cpp/thrift -r --gen erl ../tutorial.thrift fi erlc -I ${ERL_THRIFT}/include -I ${ERL_THRIFT}/ebin \ -I gen-erl -o gen-erl gen-erl/*.erl && erlc -I ${ERL_THRIFT}/include -I gen-erl *.erl && erl +K true -pa ${ERL_THRIFT}/ebin -pa gen-erl thrift-0.19.0/tutorial/Makefile.in0000644000000000000000000006207214472652521017026 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # do nothing, just build the compiler @MINGW_FALSE@@WITH_C_GLIB_TRUE@am__append_1 = c_glib @MINGW_FALSE@@WITH_CPP_TRUE@am__append_2 = cpp @MINGW_FALSE@@WITH_D_TRUE@am__append_3 = d @MINGW_FALSE@@WITH_JAVA_TRUE@am__append_4 = java js @MINGW_FALSE@@WITH_PYTHON_TRUE@am__append_5 = py py.twisted py.tornado @MINGW_FALSE@@WITH_RUBY_TRUE@am__append_6 = rb @MINGW_FALSE@@WITH_HAXE_TRUE@am__append_7 = haxe @MINGW_FALSE@@WITH_DOTNET_TRUE@am__append_8 = netstd @MINGW_FALSE@@WITH_GO_TRUE@am__append_9 = go @MINGW_FALSE@@WITH_NODEJS_TRUE@am__append_10 = nodejs @MINGW_FALSE@@WITH_DART_TRUE@am__append_11 = dart @MINGW_FALSE@@WITH_RS_TRUE@am__append_12 = rs @MINGW_FALSE@@WITH_CL_TRUE@am__append_13 = cl @MINGW_FALSE@@WITH_PERL_TRUE@am__append_14 = perl @MINGW_FALSE@@WITH_PHP_TRUE@am__append_15 = php @MINGW_FALSE@@WITH_SWIFT_TRUE@am__append_16 = swift subdir = tutorial ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = c_glib cpp d java js py py.twisted py.tornado rb haxe \ netstd go nodejs dart rs cl perl php swift am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) $(am__append_6) \ $(am__append_7) $(am__append_8) $(am__append_9) \ $(am__append_10) $(am__append_11) $(am__append_12) \ $(am__append_13) $(am__append_14) $(am__append_15) \ $(am__append_16) # Any folders or files not listed above being added to SUBDIR need to be placed here in # EXTRA_DIST to be included in the release EXTRA_DIST = \ d \ delphi \ erl \ ocaml \ shared.thrift \ tutorial.thrift \ README.md all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive @MINGW_TRUE@all-local: all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @MINGW_TRUE@clean-local: clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ check check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # # generate html for tutorial.thrift # @MINGW_FALSE@all-local: @MINGW_FALSE@ $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/tutorial/tutorial.thrift @MINGW_FALSE@clean-local: @MINGW_FALSE@ rm -rf $(top_srcdir)/tutorial/gen-html # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/netstd/0000755000000000000000000000000014472652700016252 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Makefile.am0000644000000000000000000000214014303740367020303 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . all-local: $(DOTNETCORE) build -c Release clean-local: $(RM) Interfaces.dll $(RM) -r Client/bin $(RM) -r Client/obj $(RM) -r Server/bin $(RM) -r Server/obj $(RM) -r Interfaces/bin $(RM) -r Interfaces/obj EXTRA_DIST = \ Client \ Interfaces \ README.md \ Server \ Tutorial.sln \ build.cmd \ build.sh thrift-0.19.0/tutorial/netstd/Client/0000777000000000000000000000000014454461475017503 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Client/ThriftTest.pfx0000644000000000000000000000514514303740367022314 0ustar00rootroot000000000000000‚ a0‚  *†H†÷  ‚ ‚ 0‚ 0‚ *†H†÷  ‚‚ü0‚ø0‚ô *†H†÷   ‚þ0‚ú0 *†H†÷  0PÓ:ÙD’ЂØ9—Ëÿ)ÝùwÆ®g;b ­B_Š4Æ·Õuº­"¯³þwÛëKbEá†KªþÚ€ ˜ÆcX&Hl>A0;ÐÃß{aú2v«ŒLÜáÞÆOçðl­»¡‡ Ì7¢V/]ÀÂóa Fçùð¤¦÷Nx4÷ïÓTÀ-nÈÉ`‚PEu6‰;=…Ÿ¯Cµ&³¸Ø ·öÏ–Þ-ºÇêIÇy┹ˆ!–—ĤGϲ°'ɵ¤¥AàÍ XQ€2Qïû²žšëFRÈêÉNü†_jà-?@hç'ð­üö‰”‚y®UH e¬íÕn®HþV©¾ßŠ‚Ë%ó§}:´ƒsñŠ­Ñy€Á%eêPjå‘¡_«eòÂÐs)P´ê·Ã‡&V¬‡KåP;ù§0Ö‰`ñH:—£àv7Üp+îŸì™«ÚÝñFÁ¥§ÐͦxßÉY嫈îf~$`fÌZlr¢.ìì«sžÌQ1úÇ“ àvã ¿6Úv .]Hc“ƒ·ùÛ4ÍÓ¿¶‘;Š˜í}•¼á·éw^õ¤wŸïë)­U⋉f.ž] $=Gr)da‘]ž`iº ¥Œú¢ìnû·œ?õa²æ`×—ýZ HOÒ«Øžå‹ê&lI‘øý2ÓøùJÓt÷;xHµP±‰–Rzüžƒ×# 騲í ]ÓRÍøÞÓëGdšñ=Gì“®ºW@J¡šäÅGSƒì‘G³:øº±}ß¶KMÕÎmÚ|(µ§U&HôáãÙç–“FzÿÅ¿6xÞ>y²°£:»Ë®Ã¤…L>C8obó×û gx,‘P~³h~®†ÅÀ¥³i~tÅ$ªaøNÌtÛ"„4¾”Û¥ŽˆÔjÿ_Ô1ø˜ òBwd^RѸ׆ä^jö:ue.Ë®wȤv ø8ÒÆ/°ö1o{ÉicÂ/›|ÜbZ'ÛŽ®ù*FëfÜÇ0÷¯5¡$,¿™¾U ¦J(‹ \`[l¶=]$2‡ƒOl`H p`|fxèU9«Gxw÷oÕ±´»ðU,çŽ$·ôDü±“Ngb‚‹Ï];­,bæš}+„Ý7`æ`rlײlë¾5&™xÇ|•Šà€1>Ú{Z\N¤¬ i¸ÇÔ„ÍëT>Ñ×aeÊÙ¼óqEÂÐ-sB^'Ôˆ:Ö_dÒ^!gâŒæºúš*‰6g¼Å)»(šéE⽓÷»5“xÔ…ï·2ÊJL¢‘†Ðª¥²*¬¨ºït¨»M•ÒU9ÞÈGB™ø¤Ò¨Ù l+÷@í™Ór@äéÂÉÅ)¶5_îòAh Æ€òS:“ õûú¯z[:#&·aY<ñ ü\›ƒ,„ÆIøŠŽ%ÐXŒ4#¼Ã­óMŸ ‚¥•ý (£©1“]7;ªF¦È9òË÷:6 ¡}QÚšî¸ÓrˆÉ=ŽÚsê&imVôðÅ7öÂøR7ª)ÁR¥5Í6V ÈF§êoà{Ñ"¼É!ëóêôÜÏ£W6¶sÿÇû@œ+·Òé®;-Pa-¦„õrÅX>StVSÌ€ça¾xÃÍ¡›_6«.gpÇr:¯Ù¨Z&½‹±A—püµw@’XÓqþ?1â0  +‚710 *†H†÷  10] *†H†÷  1PNte-017de0ac-82d9-4478-8b4f-a6370451f3bf0] +‚71PNMicrosoft Software Key Storage Provider0‚ï *†H†÷  ‚à0‚Ü0‚Õ *†H†÷ 0 *†H†÷  0ˆvŒ¸Þ´]Ѐ‚¨¯×¤Wc!ûÁ¨¶i›}˜%bHö æ û”Ñ—·ÑòåhR‘€-íÞx¦0j¼q ¯ç!§)$³Þº~¸Ž=Ø; E×;÷}É' Áº¯‚šü+ÇR°?tºåõ‹€ÃýÅf¯RmF@œ"x†<¯·ýùÓ÷¸JQ¥Ý-À¨ö¨æ# ’ÜÉ]©‹ƒÐ2L5«F³cxwHépÿõÝúd ‘çóدá\ƒ{Wp:eÇr#ƒû8Ï¿ð9†øPäpÂQQek Ì ")$)NúûuV!°"ð8ûƒeÈŒ»K @5ª«µ¤”¹„0Ì‚r?dͺ‡]:ŽV?n¶åØ+¦­cꈯÓD›À‚Vª8·T!:7üªG(}]T+j`ê’¼È?WV´C­À’=µþtH'Àðv%eöˆ£¢#éæy{JÆ}Ž&¯åë<´˜U§=Ej³@C×ïÚ©L ÝuiÜ"‘HÎqèZG3B"J~À?Ì.øæ@øcÈ…WàÍ8lä9­¿µF«¸ˆ±¬…’9gòðgKÁ8xÝû{½yñ^GdŒ@Ê=ʉL\äô´Ýw%C¦øúö¢©Ý"ɽ¡a¨™²Fx 7<;elÂNiîìtåÔP¢²·ö{ºí]ÜòSò½jµÄeÚ01 hææÊ—d=Ř@+³µCÈ…GF=µ#ä8…‡iï6™Ÿ¼ƒ_Ôè'™j®à¯-÷ ý\éñ@L„0¼@`,¹’+ —ǵÏl‚ÚilÕ(Ï'öïùѿڛj8—î0sµ^¨µ0fÃ×}VX‘>Oº/] ûŒÓ´¤eŠ=È|Ÿ$0˜ëƒ~&õMqôI‚†:ãþÖ®%òÁúµÍwùßZ –GióÆìÃŒ-u± Õ…'·èâ)#”H"±%å‚Rµ…s„vÙé!í)r3m†'ºç•Änc† 6•fœÿ}U+Obˆë}Áw­BDÿrú³\÷~ÅÁL#nÚõÖŠöªÚ蕎‘xnÞ\fYZ÷»7Òbh@X*øÚʃšˆéF›V4a$Û«\M3Yd0ÕÙÝuj•~ð„Úfi$ñs”lÒà û|]H=±õØ.½y@<¢|ã’ÌÓnÌ^þÒŽ¦tÃݧ,ƒW­'p-T‰×h9â·\Ö¸jd~SiÑÒIëØßÞdÕÑLbfÀîbzú÷‘V~FFl L90;00++á7×î…ìI–Äî¹%-j3á^?¬8›]ð9 3«Ý޹Ðthrift-0.19.0/tutorial/netstd/Client/Client.csproj0000644000000000000000000000333214454461475022140 0ustar00rootroot00000000000000 net7.0 9.0 Client Client Exe 0.19.0.0 false false false false thrift-0.19.0/tutorial/netstd/Client/Properties/0000777000000000000000000000000014303740367021630 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Client/Properties/AssemblyInfo.cs0000644000000000000000000000326114303740367024550 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("The Apache Software Foundation")] [assembly: AssemblyProduct("Thrift")] [assembly: AssemblyCopyright("The Apache Software Foundation")] [assembly: AssemblyTrademark("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("de78a01b-f7c6-49d1-97da-669d2ed37641")]thrift-0.19.0/tutorial/netstd/Client/Program.cs0000644000000000000000000003370214303740367021433 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using Thrift; using Thrift.Protocol; using Thrift.Transport; using Thrift.Transport.Client; using tutorial; using shared; #pragma warning disable IDE0063 // using #pragma warning disable IDE0057 // substr namespace Client { public static class LoggingHelper { public static ILoggerFactory LogFactory { get; } = LoggerFactory.Create(builder => { ConfigureLogging(builder); }); public static void ConfigureLogging(ILoggingBuilder logging) { logging.SetMinimumLevel(LogLevel.Trace); logging.AddConsole(); logging.AddDebug(); } public static ILogger CreateLogger() => LogFactory.CreateLogger(); } public class Program { private static readonly ILogger Logger = LoggingHelper.CreateLogger(); private static readonly TConfiguration Configuration = null; // new TConfiguration() if needed private static void DisplayHelp() { Logger.LogInformation(@" Usage: Client -help will diplay help information Client -tr: -bf: -pr: [-mc:] [-multiplex] will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client Options: -tr (transport): tcp - (default) tcp transport (localhost:9090) tcptls - tcp tls transport (localhost:9090) namedpipe - namedpipe transport (pipe "".test"") http - http transport (http://localhost:9090) -bf (buffering): none - (default) no buffering buffered - buffered transport framed - framed transport -pr (protocol): binary - (default) binary protocol compact - compact protocol json - json protocol -multiplex - adds multiplexed protocol -mc (multiple clients): - number of multiple clients to connect to server (max 100, default 1) Sample: Client -tr:tcp -pr:binary "); } public static void Main(string[] args) { args ??= Array.Empty(); if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) { DisplayHelp(); return; } Logger.LogInformation("Starting client..."); using (var source = new CancellationTokenSource()) { RunAsync(args, source.Token).GetAwaiter().GetResult(); } } private static async Task RunAsync(string[] args, CancellationToken cancellationToken) { var numClients = GetNumberOfClients(args); Logger.LogInformation("Selected # of clients: {numClients}", numClients); var transport = GetTransport(args); Logger.LogInformation("Selected client transport: {transport}", transport); var protocol = MakeProtocol( args, MakeTransport(args)); Logger.LogInformation("Selected client protocol: {GetProtocol(args)}", GetProtocol(args)); var mplex = GetMultiplex(args); Logger.LogInformation("Multiplex {mplex}", mplex); var tasks = new Task[numClients]; for (int i = 0; i < numClients; i++) { var task = RunClientAsync(protocol, mplex, cancellationToken); tasks[i] = task; } Task.WaitAll(tasks,cancellationToken); await Task.CompletedTask; } private static bool GetMultiplex(string[] args) { var mplex = args.FirstOrDefault(x => x.StartsWith("-multiplex")); return !string.IsNullOrEmpty(mplex); } private static Protocol GetProtocol(string[] args) { var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; if (string.IsNullOrEmpty(protocol)) return Protocol.Binary; protocol = protocol.Substring(0, 1).ToUpperInvariant() + protocol.Substring(1).ToLowerInvariant(); if (Enum.TryParse(protocol, true, out Protocol selectedProtocol)) return selectedProtocol; else return Protocol.Binary; } private static Buffering GetBuffering(string[] args) { var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1]; if (string.IsNullOrEmpty(buffering)) return Buffering.None; buffering = buffering.Substring(0, 1).ToUpperInvariant() + buffering.Substring(1).ToLowerInvariant(); if (Enum.TryParse(buffering, out var selectedBuffering)) return selectedBuffering; else return Buffering.None; } private static Transport GetTransport(string[] args) { var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; if (string.IsNullOrEmpty(transport)) return Transport.Tcp; transport = transport.Substring(0, 1).ToUpperInvariant() + transport.Substring(1).ToLowerInvariant(); if (Enum.TryParse(transport, true, out Transport selectedTransport)) return selectedTransport; else return Transport.Tcp; } private static TTransport MakeTransport(string[] args) { // construct endpoint transport TTransport transport = null; Transport selectedTransport = GetTransport(args); { switch (selectedTransport) { case Transport.Tcp: transport = new TSocketTransport(IPAddress.Loopback, 9090, Configuration); break; case Transport.NamedPipe: transport = new TNamedPipeTransport(".test", Configuration); break; case Transport.Http: transport = new THttpTransport(new Uri("http://localhost:9090"), Configuration); break; case Transport.TcpTls: transport = new TTlsSocketTransport(IPAddress.Loopback, 9090, Configuration, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); break; default: Debug.Assert(false, "unhandled case"); break; } } // optionally add layered transport(s) Buffering selectedBuffering = GetBuffering(args); switch (selectedBuffering) { case Buffering.Buffered: transport = new TBufferedTransport(transport); break; case Buffering.Framed: transport = new TFramedTransport(transport); break; default: // layered transport(s) are optional Debug.Assert(selectedBuffering == Buffering.None, "unhandled case"); break; } return transport; } private static int GetNumberOfClients(string[] args) { var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':')?[1]; Logger.LogInformation("Selected # of clients: {numClients}", numClients); if (int.TryParse(numClients, out int c) && (0 < c) && (c <= 100)) return c; else return 1; } private static X509Certificate2 GetCertificate() { // due to files location in net core better to take certs from top folder var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); return new X509Certificate2(certFile, "ThriftTest"); } private static string GetCertPath(DirectoryInfo di, int maxCount = 6) { var topDir = di; var certFile = topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) .FirstOrDefault(); if (certFile == null) { if (maxCount == 0) throw new FileNotFoundException("Cannot find file in directories"); return GetCertPath(di.Parent, maxCount - 1); } return certFile.FullName; } private static X509Certificate LocalCertificateSelectionCallback(object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { return GetCertificate(); } private static bool CertValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } private static TProtocol MakeProtocol(string[] args, TTransport transport) { Protocol selectedProtocol = GetProtocol(args); return selectedProtocol switch { Protocol.Binary => new TBinaryProtocol(transport), Protocol.Compact => new TCompactProtocol(transport), Protocol.Json => new TJsonProtocol(transport), _ => throw new Exception("unhandled protocol"), }; } private static async Task RunClientAsync(TProtocol protocol, bool multiplex, CancellationToken cancellationToken) { try { try { if( multiplex) protocol = new TMultiplexedProtocol(protocol, nameof(Calculator)); var client = new Calculator.Client(protocol); await ExecuteCalculatorClientOperations(client, cancellationToken); } catch (Exception ex) { Logger.LogError("{ex}",ex); } finally { protocol.Transport.Close(); } } catch (TApplicationException x) { Logger.LogError("{x}",x); } } private static async Task ExecuteCalculatorClientOperations( Calculator.Client client, CancellationToken cancellationToken) { await client.OpenTransportAsync(cancellationToken); // Async version Logger.LogInformation("{client.ClientId} Ping()", client.ClientId); await client.ping(cancellationToken); Logger.LogInformation("{client.ClientId} Add(1,1)", client.ClientId); var sum = await client.add(1, 1, cancellationToken); Logger.LogInformation("{client.ClientId} Add(1,1)={sum}", client.ClientId, sum); var work = new Work { Op = Operation.DIVIDE, Num1 = 1, Num2 = 0 }; try { Logger.LogInformation("{client.ClientId} Calculate(1)", client.ClientId); await client.calculate(1, work, cancellationToken); Logger.LogInformation("{client.ClientId} Whoa we can divide by 0", client.ClientId); } catch (InvalidOperation io) { Logger.LogInformation("{client.ClientId} Invalid operation: {io}", client.ClientId, io); } work.Op = Operation.SUBTRACT; work.Num1 = 15; work.Num2 = 10; try { Logger.LogInformation("{client.ClientId} Calculate(1)", client.ClientId); var diff = await client.calculate(1, work, cancellationToken); Logger.LogInformation("{client.ClientId} 15-10={diff}", client.ClientId, diff); } catch (InvalidOperation io) { Logger.LogInformation("{client.ClientId} Invalid operation: {io}", client.ClientId, io); } Logger.LogInformation("{client.ClientId} GetStruct(1)", client.ClientId); var log = await client.getStruct(1, cancellationToken); Logger.LogInformation("{client.ClientId} Check log: {log.Value}", client.ClientId, log.Value); Logger.LogInformation("{client.ClientId} Zip() with delay 100mc on server side", client.ClientId); await client.zip(cancellationToken); } private enum Transport { Tcp, NamedPipe, Http, TcpBuffered, Framed, TcpTls } private enum Protocol { Binary, Compact, Json, } private enum Buffering { None, Buffered, Framed } } } thrift-0.19.0/tutorial/netstd/Tutorial.sln0000644000000000000000000001177014303740367020601 0ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26114.2 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.Build.0 = Release|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|Any CPU {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.Build.0 = Release|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|Any CPU {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.Build.0 = Debug|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.ActiveCfg = Release|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.Build.0 = Release|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|Any CPU {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {070A5D1D-B29D-4603-999D-693DB444AD0D} EndGlobalSection EndGlobal thrift-0.19.0/tutorial/netstd/README.md0000644000000000000000000002022714303740367017534 0ustar00rootroot00000000000000# Building of samples for different platforms # Requirements - NET Core Standard 3.1 (LTS) runtime or SDK (see below for further info) # How to build - Download and install the latest .NET Core SDK for your platform https://dotnet.microsoft.com/download/dotnet-core - Ensure that you have thrift.exe which supports netstd lib and it added to PATH - Go to current folder - Run **build.sh** or **build.cmd** from the root of cloned repository - Check tests in **src/Tests** folder - Continue with /tutorials/netstd # How to run Depending on the platform, the name of the generated executables will vary. On Linux, it is just "Client" or "Server", on Windows it is "Client.exe" and "Server.exe". In the following, we use the abbreviated form "Client" and "Server". - build - go to folder (Client/Server) - run the generated executables: server first, then client from a second console # Known issues - In trace logging mode you can see some not important internal exceptions # Running of samples On machines that do not have the SDK installed, you need to install the NET Core runtime first. The SDK is only needed to build programs, otherwise the runtime is sufficient. # NetCore Server Usage: Server -help will diplay help information Server -tr: -pr: will run server with specified arguments (tcp transport and binary protocol by default) Options: -tr (transport): tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) namedpipe - namedpipe transport will be used (pipe address - "".test"") http - http transport will be used (http address - ""localhost:9090"") tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) -bf (buffering): none - (default) no transport factory will be used buffered - buffered transport factory will be used framed - framed transport factory will be used (this must match the client) -pr (protocol): binary - (default) binary protocol will be used compact - compact protocol will be used json - json protocol will be used multiplexed - multiplexed protocol will be used Sample: Server -tr:tcp **Remarks**: For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). Password for certificate - "ThriftTest". # NetCore Client Usage: Client -help will diplay help information Client -tr: -pr: -mc: will run client with specified arguments (tcp transport and binary protocol by default) Options: -tr (transport): tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) namedpipe - namedpipe transport will be used (pipe address - "".test"") http - http transport will be used (address - ""http://localhost:9090"") tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) -bf (buffering): none - (default) no transport factory will be used buffered - buffered transport factory will be used framed - framed transport factory will be used (this must match the client) -pr (protocol): binary - (default) binary protocol will be used compact - compact protocol will be used json - json protocol will be used multiplexed - multiplexed protocol will be used -mc (multiple clients): - number of multiple clients to connect to server (max 100, default 1) Sample: Client -tr:tcp -pr:binary -mc:10 Remarks: For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). Password for certificate - "ThriftTest". # How to test communication between NetCore and Python * Generate code with the latest **thrift** utility * Ensure that **thrift** generated folder **gen-py** with generated code for Python exists * Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** * Run netstd samples (client and server) and python samples (client and server) Remarks: Samples of client and server code below use correct methods (operations) and fields (properties) according to generated contracts from *.thrift files At Windows 10 add record **127.0.0.1 testserver** to **C:\Windows\System32\drivers\etc\hosts** file for correct work of python server **Python Client:** ```python import sys import glob sys.path.append('gen-py') from tutorial import Calculator from tutorial.ttypes import InvalidOperation, Operation, Work from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol def main(): # Make socket transport = TSocket.TSocket('127.0.0.1', 9090) # Buffering is critical. Raw sockets are very slow transport = TTransport.TBufferedTransport(transport) # Wrap in a protocol protocol = TBinaryProtocol.TBinaryProtocol(transport) # Create a client to use the protocol encoder client = Calculator.Client(protocol) # Connect! transport.open() client.Ping() print('ping()') sum = client.Add(1, 1) print(('1+1=%d' % (sum))) work = Work() work.Op = Operation.Divide work.Num1 = 1 work.Num2 = 0 try: quotient = client.Calculate(1, work) print('Whoa? You know how to divide by zero?') print('FYI the answer is %d' % quotient) except InvalidOperation as e: print(('InvalidOperation: %r' % e)) work.Op = Operation.Substract work.Num1 = 15 work.Num2 = 10 diff = client.Calculate(1, work) print(('15-10=%d' % (diff))) log = client.GetStruct(1) print(('Check log: %s' % (log.Value))) client.Zip() print('zip()') # Close! transport.close() if __name__ == '__main__': try: main() except Thrift.TException as tx: print('%s' % tx.message) ``` **Python Server:** ```python import glob import sys sys.path.append('gen-py') from tutorial import Calculator from tutorial.ttypes import InvalidOperation, Operation from shared.ttypes import SharedStruct from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.server import TServer class CalculatorHandler: def __init__(self): self.log = {} def Ping(self): print('ping()') def Add(self, n1, n2): print('add(%d,%d)' % (n1, n2)) return n1 + n2 def Calculate(self, logid, work): print('calculate(%d, %r)' % (logid, work)) if work.Op == Operation.Add: val = work.Num1 + work.Num2 elif work.Op == Operation.Substract: val = work.Num1 - work.Num2 elif work.Op == Operation.Multiply: val = work.Num1 * work.Num2 elif work.Op == Operation.Divide: if work.Num2 == 0: raise InvalidOperation(work.Op, 'Cannot divide by 0') val = work.Num1 / work.Num2 else: raise InvalidOperation(work.Op, 'Invalid operation') log = SharedStruct() log.Key = logid log.Value = '%d' % (val) self.log[logid] = log return val def GetStruct(self, key): print('getStruct(%d)' % (key)) return self.log[key] def Zip(self): print('zip()') if __name__ == '__main__': handler = CalculatorHandler() processor = Calculator.Processor(handler) transport = TSocket.TServerSocket(host="testserver", port=9090) tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) print('Starting the server...') server.serve() print('done.') # You could do one of these for a multithreaded server # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) ``` thrift-0.19.0/tutorial/netstd/build.cmd0000644000000000000000000000164114303740367020040 0ustar00rootroot00000000000000@echo off rem /* rem * Licensed to the Apache Software Foundation (ASF) under one rem * or more contributor license agreements. See the NOTICE file rem * distributed with this work for additional information rem * regarding copyright ownership. The ASF licenses this file rem * to you under the Apache License, Version 2.0 (the rem * "License"); you may not use this file except in compliance rem * with the License. You may obtain a copy of the License at rem * rem * http://www.apache.org/licenses/LICENSE-2.0 rem * rem * Unless required by applicable law or agreed to in writing, rem * software distributed under the License is distributed on an rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY rem * KIND, either express or implied. See the License for the rem * specific language governing permissions and limitations rem * under the License. rem */ setlocal dotnet --info dotnet build :eof thrift-0.19.0/tutorial/netstd/Interfaces/0000777000000000000000000000000014454461475020350 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Interfaces/GlobalSuppressions.cs0000644000000000000000000000240514303740367024523 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Performance", "CA1822", Justification = "", Scope = "module")] [assembly: SuppressMessage("Style", "IDE0083", Justification = "", Scope = "module")] thrift-0.19.0/tutorial/netstd/Interfaces/Interfaces.csproj0000644000000000000000000000451614454461475023657 0ustar00rootroot00000000000000 net7.0 Interfaces Interfaces 0.19.0.0 false false false false thrift-0.19.0/tutorial/netstd/Interfaces/Properties/0000777000000000000000000000000014303740367022475 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs0000644000000000000000000000326114303740367025415 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("The Apache Software Foundation")] [assembly: AssemblyProduct("Thrift")] [assembly: AssemblyCopyright("The Apache Software Foundation")] [assembly: AssemblyTrademark("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("4d13163d-9067-4c9c-8af0-64e08451397d")]thrift-0.19.0/tutorial/netstd/Server/0000777000000000000000000000000014454461475017533 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Server/ThriftTest.pfx0000644000000000000000000000514514303740367022344 0ustar00rootroot000000000000000‚ a0‚  *†H†÷  ‚ ‚ 0‚ 0‚ *†H†÷  ‚‚ü0‚ø0‚ô *†H†÷   ‚þ0‚ú0 *†H†÷  0PÓ:ÙD’ЂØ9—Ëÿ)ÝùwÆ®g;b ­B_Š4Æ·Õuº­"¯³þwÛëKbEá†KªþÚ€ ˜ÆcX&Hl>A0;ÐÃß{aú2v«ŒLÜáÞÆOçðl­»¡‡ Ì7¢V/]ÀÂóa Fçùð¤¦÷Nx4÷ïÓTÀ-nÈÉ`‚PEu6‰;=…Ÿ¯Cµ&³¸Ø ·öÏ–Þ-ºÇêIÇy┹ˆ!–—ĤGϲ°'ɵ¤¥AàÍ XQ€2Qïû²žšëFRÈêÉNü†_jà-?@hç'ð­üö‰”‚y®UH e¬íÕn®HþV©¾ßŠ‚Ë%ó§}:´ƒsñŠ­Ñy€Á%eêPjå‘¡_«eòÂÐs)P´ê·Ã‡&V¬‡KåP;ù§0Ö‰`ñH:—£àv7Üp+îŸì™«ÚÝñFÁ¥§ÐͦxßÉY嫈îf~$`fÌZlr¢.ìì«sžÌQ1úÇ“ àvã ¿6Úv .]Hc“ƒ·ùÛ4ÍÓ¿¶‘;Š˜í}•¼á·éw^õ¤wŸïë)­U⋉f.ž] $=Gr)da‘]ž`iº ¥Œú¢ìnû·œ?õa²æ`×—ýZ HOÒ«Øžå‹ê&lI‘øý2ÓøùJÓt÷;xHµP±‰–Rzüžƒ×# 騲í ]ÓRÍøÞÓëGdšñ=Gì“®ºW@J¡šäÅGSƒì‘G³:øº±}ß¶KMÕÎmÚ|(µ§U&HôáãÙç–“FzÿÅ¿6xÞ>y²°£:»Ë®Ã¤…L>C8obó×û gx,‘P~³h~®†ÅÀ¥³i~tÅ$ªaøNÌtÛ"„4¾”Û¥ŽˆÔjÿ_Ô1ø˜ òBwd^RѸ׆ä^jö:ue.Ë®wȤv ø8ÒÆ/°ö1o{ÉicÂ/›|ÜbZ'ÛŽ®ù*FëfÜÇ0÷¯5¡$,¿™¾U ¦J(‹ \`[l¶=]$2‡ƒOl`H p`|fxèU9«Gxw÷oÕ±´»ðU,çŽ$·ôDü±“Ngb‚‹Ï];­,bæš}+„Ý7`æ`rlײlë¾5&™xÇ|•Šà€1>Ú{Z\N¤¬ i¸ÇÔ„ÍëT>Ñ×aeÊÙ¼óqEÂÐ-sB^'Ôˆ:Ö_dÒ^!gâŒæºúš*‰6g¼Å)»(šéE⽓÷»5“xÔ…ï·2ÊJL¢‘†Ðª¥²*¬¨ºït¨»M•ÒU9ÞÈGB™ø¤Ò¨Ù l+÷@í™Ór@äéÂÉÅ)¶5_îòAh Æ€òS:“ õûú¯z[:#&·aY<ñ ü\›ƒ,„ÆIøŠŽ%ÐXŒ4#¼Ã­óMŸ ‚¥•ý (£©1“]7;ªF¦È9òË÷:6 ¡}QÚšî¸ÓrˆÉ=ŽÚsê&imVôðÅ7öÂøR7ª)ÁR¥5Í6V ÈF§êoà{Ñ"¼É!ëóêôÜÏ£W6¶sÿÇû@œ+·Òé®;-Pa-¦„õrÅX>StVSÌ€ça¾xÃÍ¡›_6«.gpÇr:¯Ù¨Z&½‹±A—püµw@’XÓqþ?1â0  +‚710 *†H†÷  10] *†H†÷  1PNte-017de0ac-82d9-4478-8b4f-a6370451f3bf0] +‚71PNMicrosoft Software Key Storage Provider0‚ï *†H†÷  ‚à0‚Ü0‚Õ *†H†÷ 0 *†H†÷  0ˆvŒ¸Þ´]Ѐ‚¨¯×¤Wc!ûÁ¨¶i›}˜%bHö æ û”Ñ—·ÑòåhR‘€-íÞx¦0j¼q ¯ç!§)$³Þº~¸Ž=Ø; E×;÷}É' Áº¯‚šü+ÇR°?tºåõ‹€ÃýÅf¯RmF@œ"x†<¯·ýùÓ÷¸JQ¥Ý-À¨ö¨æ# ’ÜÉ]©‹ƒÐ2L5«F³cxwHépÿõÝúd ‘çóدá\ƒ{Wp:eÇr#ƒû8Ï¿ð9†øPäpÂQQek Ì ")$)NúûuV!°"ð8ûƒeÈŒ»K @5ª«µ¤”¹„0Ì‚r?dͺ‡]:ŽV?n¶åØ+¦­cꈯÓD›À‚Vª8·T!:7üªG(}]T+j`ê’¼È?WV´C­À’=µþtH'Àðv%eöˆ£¢#éæy{JÆ}Ž&¯åë<´˜U§=Ej³@C×ïÚ©L ÝuiÜ"‘HÎqèZG3B"J~À?Ì.øæ@øcÈ…WàÍ8lä9­¿µF«¸ˆ±¬…’9gòðgKÁ8xÝû{½yñ^GdŒ@Ê=ʉL\äô´Ýw%C¦øúö¢©Ý"ɽ¡a¨™²Fx 7<;elÂNiîìtåÔP¢²·ö{ºí]ÜòSò½jµÄeÚ01 hææÊ—d=Ř@+³µCÈ…GF=µ#ä8…‡iï6™Ÿ¼ƒ_Ôè'™j®à¯-÷ ý\éñ@L„0¼@`,¹’+ —ǵÏl‚ÚilÕ(Ï'öïùѿڛj8—î0sµ^¨µ0fÃ×}VX‘>Oº/] ûŒÓ´¤eŠ=È|Ÿ$0˜ëƒ~&õMqôI‚†:ãþÖ®%òÁúµÍwùßZ –GióÆìÃŒ-u± Õ…'·èâ)#”H"±%å‚Rµ…s„vÙé!í)r3m†'ºç•Änc† 6•fœÿ}U+Obˆë}Áw­BDÿrú³\÷~ÅÁL#nÚõÖŠöªÚ蕎‘xnÞ\fYZ÷»7Òbh@X*øÚʃšˆéF›V4a$Û«\M3Yd0ÕÙÝuj•~ð„Úfi$ñs”lÒà û|]H=±õØ.½y@<¢|ã’ÌÓnÌ^þÒŽ¦tÃݧ,ƒW­'p-T‰×h9â·\Ö¸jd~SiÑÒIëØßÞdÕÑLbfÀîbzú÷‘V~FFl L90;00++á7×î…ìI–Äî¹%-j3á^?¬8›]ð9 3«Ý޹Ðthrift-0.19.0/tutorial/netstd/Server/Server.csproj0000644000000000000000000000374414454461475022227 0ustar00rootroot00000000000000 net7.0 9.0 Server Server Exe 0.19.0.0 false false false false thrift-0.19.0/tutorial/netstd/Server/Properties/0000777000000000000000000000000014303740367021660 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/netstd/Server/Properties/AssemblyInfo.cs0000644000000000000000000000326114303740367024600 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("The Apache Software Foundation")] [assembly: AssemblyProduct("Thrift")] [assembly: AssemblyCopyright("The Apache Software Foundation")] [assembly: AssemblyTrademark("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("e210fc10-5aff-4b04-ac21-58afc7b74b0c")]thrift-0.19.0/tutorial/netstd/Server/Program.cs0000644000000000000000000004133614452237057021467 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Thrift; using Thrift.Protocol; using Thrift.Server; using Thrift.Transport; using Thrift.Transport.Server; using tutorial; using shared; using Thrift.Processor; using System.Diagnostics; #pragma warning disable IDE0057 // substr namespace Server { public static class LoggingHelper { public static ILoggerFactory LogFactory { get; } = LoggerFactory.Create(builder => { ConfigureLogging(builder); }); public static void ConfigureLogging(ILoggingBuilder logging) { logging.SetMinimumLevel(LogLevel.Trace); logging.AddConsole(); logging.AddDebug(); } public static ILogger CreateLogger() => LogFactory.CreateLogger(); } public class Program { private static readonly ILogger Logger = LoggingHelper.CreateLogger(); private static readonly TConfiguration Configuration = null; // new TConfiguration() if needed public static void Main(string[] args) { args ??= Array.Empty(); if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) { DisplayHelp(); return; } using (var source = new CancellationTokenSource()) { RunAsync(args, source.Token).GetAwaiter().GetResult(); Logger.LogInformation("Press any key to stop..."); Console.ReadLine(); source.Cancel(); } Logger.LogInformation("Server stopped"); } private static void DisplayHelp() { Logger.LogInformation(@" Usage: Server -help will diplay help information Server -tr: -bf: -pr: [-multiplex] will run server with specified arguments (tcp transport, no buffering, and binary protocol by default) Options: -tr (transport): tcp - (default) tcp transport (localhost:9090) tcptls - tcp transport with tls (localhost:9090) namedpipe - namedpipe transport (pipe "".test"") http - http transport (localhost:9090) -bf (buffering): none - (default) no buffering buffered - buffered transport framed - framed transport -pr (protocol): binary - (default) binary protocol compact - compact protocol json - json protocol -multiplex - adds multiplexed protocol Sample: Server -tr:tcp "); } private static async Task RunAsync(string[] args, CancellationToken cancellationToken) { var selectedTransport = GetTransport(args); var selectedBuffering = GetBuffering(args); var selectedProtocol = GetProtocol(args); var multiplex = GetMultiplex(args); if (selectedTransport == Transport.Http) { if (multiplex) throw new Exception("This tutorial sample code does not yet allow multiplex over http (although Thrift itself of course does)"); new HttpServerSample().Run(cancellationToken); } else { await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, multiplex, cancellationToken); } } private static bool GetMultiplex(string[] args) { var mplex = args.FirstOrDefault(x => x.StartsWith("-multiplex")); return !string.IsNullOrEmpty(mplex); } private static Protocol GetProtocol(string[] args) { var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; if (string.IsNullOrEmpty(protocol)) return Protocol.Binary; protocol = protocol.Substring(0, 1).ToUpperInvariant() + protocol.Substring(1).ToLowerInvariant(); if (Enum.TryParse(protocol, true, out Protocol selectedProtocol)) return selectedProtocol; else return Protocol.Binary; } private static Buffering GetBuffering(string[] args) { var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1]; if (string.IsNullOrEmpty(buffering)) return Buffering.None; buffering = buffering.Substring(0, 1).ToUpperInvariant() + buffering.Substring(1).ToLowerInvariant(); if( Enum.TryParse(buffering, out var selectedBuffering)) return selectedBuffering; else return Buffering.None; } private static Transport GetTransport(string[] args) { var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; if (string.IsNullOrEmpty(transport)) return Transport.Tcp; transport = transport.Substring(0, 1).ToUpperInvariant() + transport.Substring(1).ToLowerInvariant(); if( Enum.TryParse(transport, true, out Transport selectedTransport)) return selectedTransport; else return Transport.Tcp; } private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, bool multiplex, CancellationToken cancellationToken) { TServerTransport serverTransport = transport switch { Transport.Tcp => new TServerSocketTransport(9090, Configuration), Transport.NamedPipe => new TNamedPipeServerTransport(".test", Configuration, NamedPipeServerFlags.None, 64), Transport.TcpTls => new TTlsServerSocketTransport(9090, Configuration, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback), _ => throw new ArgumentException("unsupported value $transport", nameof(transport)), }; TTransportFactory transportFactory = buffering switch { Buffering.Buffered => new TBufferedTransport.Factory(), Buffering.Framed => new TFramedTransport.Factory(), // layered transport(s) are optional Buffering.None => null, _ => throw new ArgumentException("unsupported value $buffering", nameof(buffering)), }; TProtocolFactory protocolFactory = protocol switch { Protocol.Binary => new TBinaryProtocol.Factory(), Protocol.Compact => new TCompactProtocol.Factory(), Protocol.Json => new TJsonProtocol.Factory(), _ => throw new ArgumentException("unsupported value $protocol", nameof(protocol)), }; var handler = new CalculatorAsyncHandler(); ITAsyncProcessor processor = new Calculator.AsyncProcessor(handler); if (multiplex) { var multiplexedProcessor = new TMultiplexedProcessor(); multiplexedProcessor.RegisterProcessor(nameof(Calculator), processor); processor = multiplexedProcessor; } try { Logger.LogInformation( "TSimpleAsyncServer with \n{transport} transport\n{buffering} buffering\nmultiplex = {multiplex}\n{protocol} protocol", transport, buffering, multiplex ? "yes" : "no", protocol ); var server = new TSimpleAsyncServer( itProcessorFactory: new TSingletonProcessorFactory(processor), serverTransport: serverTransport, inputTransportFactory: transportFactory, outputTransportFactory: transportFactory, inputProtocolFactory: protocolFactory, outputProtocolFactory: protocolFactory, logger: LoggingHelper.CreateLogger()); Logger.LogInformation("Starting the server..."); await server.ServeAsync(cancellationToken); } catch (Exception x) { Logger.LogInformation("{x}",x); } } private static X509Certificate2 GetCertificate() { // due to files location in net core better to take certs from top folder var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); return new X509Certificate2(certFile, "ThriftTest"); } private static string GetCertPath(DirectoryInfo di, int maxCount = 6) { var topDir = di; var certFile = topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) .FirstOrDefault(); if (certFile == null) { if (maxCount == 0) throw new FileNotFoundException("Cannot find file in directories"); return GetCertPath(di.Parent, maxCount - 1); } return certFile.FullName; } private static X509Certificate LocalCertificateSelectionCallback(object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) { return GetCertificate(); } private static bool ClientCertValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; } private enum Transport { Tcp, NamedPipe, Http, TcpTls, } private enum Buffering { None, Buffered, Framed, } private enum Protocol { Binary, Compact, Json, } public class HttpServerSample { public void Run(CancellationToken cancellationToken) { var config = new ConfigurationBuilder() .AddEnvironmentVariables(prefix: "ASPNETCORE_") .Build(); var host = new WebHostBuilder() .UseConfiguration(config) .UseKestrel() .UseUrls("http://localhost:9090") .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() .ConfigureLogging((ctx,logging) => LoggingHelper.ConfigureLogging(logging)) .Build(); Logger.LogTrace("test"); Logger.LogCritical("test"); host.RunAsync(cancellationToken).GetAwaiter().GetResult(); } public class Startup { public Startup(IWebHostEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfigurationRoot Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // NOTE: this is not really the recommended way to do it // because the HTTP server cannot be configured properly to e.g. accept framed or multiplex services.AddTransient(); services.AddTransient(); services.AddTransient(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { _ = env; _ = loggerFactory; app.UseMiddleware(); } } } public class CalculatorAsyncHandler : Calculator.IAsync { private readonly Dictionary _log = new(); public CalculatorAsyncHandler() { } public async Task getStruct(int key, CancellationToken cancellationToken) { Logger.LogInformation("GetStruct({key})", key); return await Task.FromResult(_log[key]); } public async Task ping(CancellationToken cancellationToken) { Logger.LogInformation("Ping()"); await Task.CompletedTask; } public async Task add(int num1, int num2, CancellationToken cancellationToken) { Logger.LogInformation("Add({num1},{num2})", num1, num2); return await Task.FromResult(num1 + num2); } public async Task calculate(int logid, Work w, CancellationToken cancellationToken) { Logger.LogInformation("Calculate({logid}, [{w.Op},{w.Num1},{w.Num2}])", logid, w.Op, w.Num1, w.Num2); int val; switch (w.Op) { case Operation.ADD: val = w.Num1 + w.Num2; break; case Operation.SUBTRACT: val = w.Num1 - w.Num2; break; case Operation.MULTIPLY: val = w.Num1 * w.Num2; break; case Operation.DIVIDE: if (w.Num2 == 0) { var io = new InvalidOperation { WhatOp = (int) w.Op, Why = "Cannot divide by 0" }; throw io; } val = w.Num1 / w.Num2; break; default: { var io = new InvalidOperation { WhatOp = (int) w.Op, Why = "Unknown operation" }; throw io; } } var entry = new SharedStruct { Key = logid, Value = val.ToString() }; _log[logid] = entry; return await Task.FromResult(val); } public async Task zip(CancellationToken cancellationToken) { Logger.LogInformation("Zip() with delay 100mc"); await Task.Delay(100, CancellationToken.None); } } public class SharedServiceAsyncHandler : SharedService.IAsync { public async Task getStruct(int key, CancellationToken cancellationToken) { Logger.LogInformation("GetStruct({key})", key); return await Task.FromResult(new SharedStruct() { Key = key, Value = "GetStruct" }); } } } } thrift-0.19.0/tutorial/netstd/Makefile.in0000644000000000000000000005731014472652522020327 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = tutorial/netstd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . EXTRA_DIST = \ Client \ Interfaces \ README.md \ Server \ Tutorial.sln \ build.cmd \ build.sh all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/netstd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/netstd/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ check check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile all-local: $(DOTNETCORE) build -c Release clean-local: $(RM) Interfaces.dll $(RM) -r Client/bin $(RM) -r Client/obj $(RM) -r Server/bin $(RM) -r Server/obj $(RM) -r Interfaces/bin $(RM) -r Interfaces/obj # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/tutorial/netstd/build.sh0000777000000000000000000000154514062750227017717 0ustar00rootroot00000000000000#!/usr/bin/env bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #exit if any command fails set -e dotnet --info dotnet build thrift-0.19.0/tutorial/cpp/0000755000000000000000000000000014472652676015547 5ustar00rootroot00000000000000thrift-0.19.0/tutorial/cpp/Makefile.am0000644000000000000000000000440414303740367017571 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/shared_types.cpp \ gen-cpp/tutorial_types.cpp noinst_LTLIBRARIES = libtutorialgencpp.la nodist_libtutorialgencpp_la_SOURCES = \ gen-cpp/Calculator.cpp \ gen-cpp/Calculator.h \ gen-cpp/SharedService.cpp \ gen-cpp/SharedService.h \ gen-cpp/shared_types.cpp \ gen-cpp/shared_types.h \ gen-cpp/tutorial_constants.cpp \ gen-cpp/tutorial_constants.h \ gen-cpp/tutorial_types.cpp \ gen-cpp/tutorial_types.h libtutorialgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la noinst_PROGRAMS = \ TutorialServer \ TutorialClient TutorialServer_SOURCES = \ CppServer.cpp TutorialServer_LDADD = \ libtutorialgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la TutorialClient_SOURCES = \ CppClient.cpp TutorialClient_LDADD = \ libtutorialgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la # # Common thrift code generation rules # gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen cpp -r $< AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp AM_CXXFLAGS = -Wall -Wextra -pedantic AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) clean-local: $(RM) gen-cpp/* tutorialserver: all ./TutorialServer tutorialclient: all ./TutorialClient style-local: $(CPPSTYLE_CMD) EXTRA_DIST = \ CMakeLists.txt \ CppClient.cpp \ CppServer.cpp thrift-0.19.0/tutorial/cpp/CMakeLists.txt0000644000000000000000000000401114303740367020267 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include(BoostMacros) REQUIRE_BOOST_HEADERS() #Make sure gen-cpp files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp") include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src") include(ThriftMacros) set(tutorialgencpp_SOURCES gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp ) add_library(tutorialgencpp STATIC ${tutorialgencpp_SOURCES}) target_link_libraries(tutorialgencpp thrift) add_custom_command(OUTPUT gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp COMMAND ${THRIFT_COMPILER} --gen cpp -r ${PROJECT_SOURCE_DIR}/tutorial/tutorial.thrift ) add_executable(TutorialServer CppServer.cpp) target_link_libraries(TutorialServer tutorialgencpp) target_link_libraries(TutorialServer thrift) if (ZLIB_FOUND) target_link_libraries(TutorialServer ${ZLIB_LIBRARIES}) endif () add_executable(TutorialClient CppClient.cpp) target_link_libraries(TutorialClient tutorialgencpp) target_link_libraries(TutorialClient thrift) if (ZLIB_FOUND) target_link_libraries(TutorialClient ${ZLIB_LIBRARIES}) endif () thrift-0.19.0/tutorial/cpp/CppClient.cpp0000644000000000000000000000465414303740367020131 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include "../gen-cpp/Calculator.h" using namespace std; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace tutorial; using namespace shared; int main() { std::shared_ptr socket(new TSocket("localhost", 9090)); std::shared_ptr transport(new TBufferedTransport(socket)); std::shared_ptr protocol(new TBinaryProtocol(transport)); CalculatorClient client(protocol); try { transport->open(); client.ping(); cout << "ping()" << endl; cout << "1 + 1 = " << client.add(1, 1) << endl; Work work; work.op = Operation::DIVIDE; work.num1 = 1; work.num2 = 0; try { client.calculate(1, work); cout << "Whoa? We can divide by zero!" << endl; } catch (InvalidOperation& io) { cout << "InvalidOperation: " << io.why << endl; // or using generated operator<<: cout << io << endl; // or by using std::exception native method what(): cout << io.what() << endl; } work.op = Operation::SUBTRACT; work.num1 = 15; work.num2 = 10; int32_t diff = client.calculate(1, work); cout << "15 - 10 = " << diff << endl; // Note that C++ uses return by reference for complex types to avoid // costly copy construction SharedStruct ss; client.getStruct(ss, 1); cout << "Received log: " << ss << endl; transport->close(); } catch (TException& tx) { cout << "ERROR: " << tx.what() << endl; } } thrift-0.19.0/tutorial/cpp/CppServer.cpp0000644000000000000000000001314714303740367020156 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../gen-cpp/Calculator.h" using namespace std; using namespace apache::thrift; using namespace apache::thrift::concurrency; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::server; using namespace tutorial; using namespace shared; class CalculatorHandler : public CalculatorIf { public: CalculatorHandler() = default; void ping() override { cout << "ping()" << endl; } int32_t add(const int32_t n1, const int32_t n2) override { cout << "add(" << n1 << ", " << n2 << ")" << endl; return n1 + n2; } int32_t calculate(const int32_t logid, const Work& work) override { cout << "calculate(" << logid << ", " << work << ")" << endl; int32_t val; switch (work.op) { case Operation::ADD: val = work.num1 + work.num2; break; case Operation::SUBTRACT: val = work.num1 - work.num2; break; case Operation::MULTIPLY: val = work.num1 * work.num2; break; case Operation::DIVIDE: if (work.num2 == 0) { InvalidOperation io; io.whatOp = work.op; io.why = "Cannot divide by 0"; throw io; } val = work.num1 / work.num2; break; default: InvalidOperation io; io.whatOp = work.op; io.why = "Invalid Operation"; throw io; } SharedStruct ss; ss.key = logid; ss.value = to_string(val); log[logid] = ss; return val; } void getStruct(SharedStruct& ret, const int32_t logid) override { cout << "getStruct(" << logid << ")" << endl; ret = log[logid]; } void zip() override { cout << "zip()" << endl; } protected: map log; }; /* CalculatorIfFactory is code generated. CalculatorCloneFactory is useful for getting access to the server side of the transport. It is also useful for making per-connection state. Without this CloneFactory, all connections will end up sharing the same handler instance. */ class CalculatorCloneFactory : virtual public CalculatorIfFactory { public: ~CalculatorCloneFactory() override = default; CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override { std::shared_ptr sock = std::dynamic_pointer_cast(connInfo.transport); cout << "Incoming connection\n"; cout << "\tSocketInfo: " << sock->getSocketInfo() << "\n"; cout << "\tPeerHost: " << sock->getPeerHost() << "\n"; cout << "\tPeerAddress: " << sock->getPeerAddress() << "\n"; cout << "\tPeerPort: " << sock->getPeerPort() << "\n"; return new CalculatorHandler; } void releaseHandler( ::shared::SharedServiceIf* handler) override { delete handler; } }; int main() { TThreadedServer server( std::make_shared(std::make_shared()), std::make_shared(9090), //port std::make_shared(), std::make_shared()); /* // if you don't need per-connection state, do the following instead TThreadedServer server( std::make_shared(std::make_shared()), std::make_shared(9090), //port std::make_shared(), std::make_shared()); */ /** * Here are some alternate server types... // This server only allows one connection at a time, but spawns no threads TSimpleServer server( std::make_shared(std::make_shared()), std::make_shared(9090), std::make_shared(), std::make_shared()); const int workerCount = 4; std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); threadManager->threadFactory( std::make_shared()); threadManager->start(); // This server allows "workerCount" connection at a time, and reuses threads TThreadPoolServer server( std::make_shared(std::make_shared()), std::make_shared(9090), std::make_shared(), std::make_shared(), threadManager); */ cout << "Starting the server..." << endl; server.serve(); cout << "Done." << endl; return 0; } thrift-0.19.0/tutorial/cpp/Makefile.in0000644000000000000000000006767414472652521017625 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = TutorialServer$(EXEEXT) TutorialClient$(EXEEXT) subdir = tutorial/cpp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtutorialgencpp_la_DEPENDENCIES = \ $(top_builddir)/lib/cpp/libthrift.la am__dirstamp = $(am__leading_dot)dirstamp nodist_libtutorialgencpp_la_OBJECTS = gen-cpp/Calculator.lo \ gen-cpp/SharedService.lo gen-cpp/shared_types.lo \ gen-cpp/tutorial_constants.lo gen-cpp/tutorial_types.lo libtutorialgencpp_la_OBJECTS = $(nodist_libtutorialgencpp_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = PROGRAMS = $(noinst_PROGRAMS) am_TutorialClient_OBJECTS = CppClient.$(OBJEXT) TutorialClient_OBJECTS = $(am_TutorialClient_OBJECTS) TutorialClient_DEPENDENCIES = libtutorialgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la am_TutorialServer_OBJECTS = CppServer.$(OBJEXT) TutorialServer_OBJECTS = $(am_TutorialServer_OBJECTS) TutorialServer_DEPENDENCIES = libtutorialgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(nodist_libtutorialgencpp_la_SOURCES) \ $(TutorialClient_SOURCES) $(TutorialServer_SOURCES) DIST_SOURCES = $(TutorialClient_SOURCES) $(TutorialServer_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/shared_types.cpp \ gen-cpp/tutorial_types.cpp noinst_LTLIBRARIES = libtutorialgencpp.la nodist_libtutorialgencpp_la_SOURCES = \ gen-cpp/Calculator.cpp \ gen-cpp/Calculator.h \ gen-cpp/SharedService.cpp \ gen-cpp/SharedService.h \ gen-cpp/shared_types.cpp \ gen-cpp/shared_types.h \ gen-cpp/tutorial_constants.cpp \ gen-cpp/tutorial_constants.h \ gen-cpp/tutorial_types.cpp \ gen-cpp/tutorial_types.h libtutorialgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la TutorialServer_SOURCES = \ CppServer.cpp TutorialServer_LDADD = \ libtutorialgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la TutorialClient_SOURCES = \ CppClient.cpp TutorialClient_LDADD = \ libtutorialgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp AM_CXXFLAGS = -Wall -Wextra -pedantic AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) EXTRA_DIST = \ CMakeLists.txt \ CppClient.cpp \ CppServer.cpp all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tutorial/cpp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tutorial/cpp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } gen-cpp/$(am__dirstamp): @$(MKDIR_P) gen-cpp @: > gen-cpp/$(am__dirstamp) gen-cpp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) gen-cpp/$(DEPDIR) @: > gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/Calculator.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/SharedService.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/shared_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/tutorial_constants.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/tutorial_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) libtutorialgencpp.la: $(libtutorialgencpp_la_OBJECTS) $(libtutorialgencpp_la_DEPENDENCIES) $(EXTRA_libtutorialgencpp_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libtutorialgencpp_la_OBJECTS) $(libtutorialgencpp_la_LIBADD) $(LIBS) clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list TutorialClient$(EXEEXT): $(TutorialClient_OBJECTS) $(TutorialClient_DEPENDENCIES) $(EXTRA_TutorialClient_DEPENDENCIES) @rm -f TutorialClient$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TutorialClient_OBJECTS) $(TutorialClient_LDADD) $(LIBS) TutorialServer$(EXEEXT): $(TutorialServer_OBJECTS) $(TutorialServer_DEPENDENCIES) $(EXTRA_TutorialServer_DEPENDENCIES) @rm -f TutorialServer$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TutorialServer_OBJECTS) $(TutorialServer_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f gen-cpp/*.$(OBJEXT) -rm -f gen-cpp/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CppClient.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CppServer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/Calculator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/SharedService.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/shared_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/tutorial_constants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/tutorial_types.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf gen-cpp/.libs gen-cpp/_libs style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f gen-cpp/$(DEPDIR)/$(am__dirstamp) -rm -f gen-cpp/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) gen-cpp/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) gen-cpp/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-local clean-noinstLTLIBRARIES \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am style-am style-local tags tags-am \ uninstall uninstall-am .PRECIOUS: Makefile # # Common thrift code generation rules # gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen cpp -r $< clean-local: $(RM) gen-cpp/* tutorialserver: all ./TutorialServer tutorialclient: all ./TutorialClient style-local: $(CPPSTYLE_CMD) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/NOTICE0000644000000000000000000000025614303740367014015 0ustar00rootroot00000000000000Apache Thrift Copyright (C) 2006 - 2019, The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). thrift-0.19.0/install-sh0000755000000000000000000003546314472652514015130 0ustar00rootroot00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2014-09-12.12; # 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 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 the last 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. -s $stripprog installed files. -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 " 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;; -s) stripcmd=$stripprog;; -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=$? 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; won't work # if double slashes aren't ignored. 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 dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # 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 case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible to # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # As "mkdir -p" follows symlinks and we work in /tmp possibly; so # create the $tmpdir first (and fail if unsuccessful) to make sure # that nobody tries to guess the $tmpdir name. 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;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or 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=$dstdir/_inst.$$_ rmtmp=$dstdir/_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 && $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 # 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 -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$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 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: thrift-0.19.0/package-lock.json0000644000000000000000000042750214454461475016343 0ustar00rootroot00000000000000{ "name": "thrift", "version": "0.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "thrift", "version": "0.19.0", "license": "Apache-2.0", "dependencies": { "browser-or-node": "^1.2.1", "isomorphic-ws": "^4.0.1", "node-int64": "^0.4.0", "q": "^1.5.0", "ws": "^5.2.3" }, "devDependencies": { "@types/node": "^10.12.6", "@types/node-int64": "^0.4.29", "@types/q": "^1.5.1", "buffer-equals": "^1.0.4", "commander": "^2.14.1", "connect": "^3.6.6", "eslint": "^5.7.0", "eslint-config-prettier": "^3.1.0", "eslint-plugin-prettier": "^3.0.0", "html-validator-cli": "^2.0.0", "jsdoc": "^4.0.2", "json-int64": "^1.0.2", "nyc": "^15.0.0", "prettier": "^1.14.3", "tape": "^4.9.0", "typescript": "^3.1.6", "utf-8-validate": "^5.0.0" }, "engines": { "node": ">= 10.18.0" } }, "node_modules/@babel/code-frame": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "dependencies": { "@babel/highlight": "^7.0.0" } }, "node_modules/@babel/core": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/generator": "^7.8.4", "@babel/helpers": "^7.8.4", "@babel/parser": "^7.8.4", "@babel/template": "^7.8.3", "@babel/traverse": "^7.8.4", "@babel/types": "^7.8.3", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", "json5": "^2.1.0", "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "engines": { "node": ">=6.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/babel" } }, "node_modules/@babel/core/node_modules/@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "dependencies": { "@babel/highlight": "^7.8.3" } }, "node_modules/@babel/core/node_modules/@babel/highlight": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "dev": true, "dependencies": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, "node_modules/@babel/core/node_modules/debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" } }, "node_modules/@babel/core/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/@babel/core/node_modules/resolve": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "dependencies": { "path-parse": "^1.0.6" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/@babel/core/node_modules/resolve/node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/@babel/core/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/@babel/generator": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", "dev": true, "dependencies": { "@babel/types": "^7.8.3", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" } }, "node_modules/@babel/generator/node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/@babel/helper-function-name": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", "dev": true, "dependencies": { "@babel/helper-get-function-arity": "^7.8.3", "@babel/template": "^7.8.3", "@babel/types": "^7.8.3" } }, "node_modules/@babel/helper-get-function-arity": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "dev": true, "dependencies": { "@babel/types": "^7.8.3" } }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "dev": true, "dependencies": { "@babel/types": "^7.8.3" } }, "node_modules/@babel/helpers": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", "dev": true, "dependencies": { "@babel/template": "^7.8.3", "@babel/traverse": "^7.8.4", "@babel/types": "^7.8.3" } }, "node_modules/@babel/highlight": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "dependencies": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, "node_modules/@babel/parser": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz", "integrity": "sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==", "dev": true, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/template": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/parser": "^7.8.3", "@babel/types": "^7.8.3" } }, "node_modules/@babel/template/node_modules/@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "dependencies": { "@babel/highlight": "^7.8.3" } }, "node_modules/@babel/template/node_modules/@babel/highlight": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "dev": true, "dependencies": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, "node_modules/@babel/traverse": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.8.3", "@babel/generator": "^7.8.4", "@babel/helper-function-name": "^7.8.3", "@babel/helper-split-export-declaration": "^7.8.3", "@babel/parser": "^7.8.4", "@babel/types": "^7.8.3", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" } }, "node_modules/@babel/traverse/node_modules/@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "dependencies": { "@babel/highlight": "^7.8.3" } }, "node_modules/@babel/traverse/node_modules/@babel/highlight": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "dev": true, "dependencies": { "chalk": "^2.0.0", "esutils": "^2.0.2", "js-tokens": "^4.0.0" } }, "node_modules/@babel/traverse/node_modules/debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" } }, "node_modules/@babel/traverse/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/@babel/types": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", "dev": true, "dependencies": { "esutils": "^2.0.2", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", "dev": true, "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@istanbuljs/schema": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/@jsdoc/salty": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/@jsdoc/salty/-/salty-0.2.5.tgz", "integrity": "sha512-TfRP53RqunNe2HBobVBJ0VLhK1HbfvBYeTC1ahnN64PWvyYyGebmMiPkuwvD9fpw2ZbkoPb8Q7mwy0aR8Z9rvw==", "dev": true, "dependencies": { "lodash": "^4.17.21" }, "engines": { "node": ">=v12.0.0" } }, "node_modules/@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, "node_modules/@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", "dev": true }, "node_modules/@types/markdown-it": { "version": "12.2.3", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", "dev": true, "dependencies": { "@types/linkify-it": "*", "@types/mdurl": "*" } }, "node_modules/@types/mdurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", "dev": true }, "node_modules/@types/node": { "version": "10.12.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.6.tgz", "integrity": "sha512-+ZWB5Ec1iki99xQFzBlivlKxSZQ+fuUKBott8StBOnLN4dWbRHlgdg1XknpW6g0tweniN5DcOqA64CJyOUPSAw==", "dev": true }, "node_modules/@types/node-int64": { "version": "0.4.29", "resolved": "https://registry.npmjs.org/@types/node-int64/-/node-int64-0.4.29.tgz", "integrity": "sha512-rHXvenLTj/CcsmNAebaBOhxQ2MqEGl3yXZZcZ21XYR+gzGTTcpOy2N4IxpvTCz48loyQNatHvfn6GhIbbZ1R3Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==", "dev": true }, "node_modules/acorn": { "version": "6.4.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true, "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-jsx": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.0.tgz", "integrity": "sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg==", "dev": true, "peerDependencies": { "acorn": "^6.0.0" } }, "node_modules/aggregate-error": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ajv/node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "node_modules/ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/ansi-regex": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/append-transform": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, "dependencies": { "default-require-extensions": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "dependencies": { "array-uniq": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "dev": true, "dependencies": { "safer-buffer": "~2.1.0" } }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, "engines": { "node": ">=0.8" } }, "node_modules/async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", "dev": true, "engines": { "node": "*" } }, "node_modules/aws4": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", "dev": true }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "dev": true, "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/browser-or-node": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" }, "node_modules/buffer-equals": { "version": "1.0.4", "resolved": "http://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", "integrity": "sha1-A1O1T9B/2VZBcGca5vZrnPENJ/U=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, "dependencies": { "hasha": "^5.0.0", "make-dir": "^3.0.0", "package-hash": "^4.0.0", "write-file-atomic": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "dependencies": { "callsites": "^0.2.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/callsites": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", "dev": true }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dev": true, "dependencies": { "lodash": "^4.17.15" }, "engines": { "node": ">= 10" } }, "node_modules/chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, "node_modules/circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "deprecated": "CircularJSON is in maintenance only, flatted is its successor.", "dev": true }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "dependencies": { "restore-cursor": "^2.0.0" }, "engines": { "node": ">=4" } }, "node_modules/cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "node_modules/cliui/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/cliui/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/cliui/node_modules/string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, "node_modules/cliui/node_modules/strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/commander": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "node_modules/connect": { "version": "3.6.6", "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", "dev": true, "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.0", "parseurl": "~1.3.2", "utils-merge": "1.0.1" }, "engines": { "node": ">= 0.10.0" } }, "node_modules/convert-source-map": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", "dev": true, "dependencies": { "safe-buffer": "~5.1.1" } }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, "node_modules/cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" }, "engines": { "node": ">=4.8" } }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", "dev": true, "dependencies": { "assert-plus": "^1.0.0" }, "engines": { "node": ">=0.10" } }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { "ms": "2.0.0" } }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, "node_modules/default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", "dev": true, "dependencies": { "strip-bom": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "dependencies": { "object-keys": "^1.0.12" }, "engines": { "node": ">= 0.4" } }, "node_modules/defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, "node_modules/del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "dependencies": { "globby": "^5.0.0", "is-path-cwd": "^1.0.0", "is-path-in-cwd": "^1.0.0", "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "rimraf": "^2.2.8" }, "engines": { "node": ">=0.10.0" } }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "dependencies": { "esutils": "^2.0.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", "dev": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true, "engines": { "node": ">= 0.8" } }, "node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/es-abstract": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", "dev": true, "dependencies": { "es-to-primitive": "^1.1.1", "function-bind": "^1.1.1", "has": "^1.0.1", "is-callable": "^1.1.3", "is-regex": "^1.0.4" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-to-primitive": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/eslint": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz", "integrity": "sha512-zYCeFQahsxffGl87U2aJ7DPyH8CbWgxBC213Y8+TCanhUTf2gEvfq3EKpHmEcozTLyPmGe9LZdMAwC/CpJBM5A==", "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "ajv": "^6.5.3", "chalk": "^2.1.0", "cross-spawn": "^6.0.5", "debug": "^4.0.1", "doctrine": "^2.1.0", "eslint-scope": "^4.0.0", "eslint-utils": "^1.3.1", "eslint-visitor-keys": "^1.0.0", "espree": "^4.0.0", "esquery": "^1.0.1", "esutils": "^2.0.2", "file-entry-cache": "^2.0.0", "functional-red-black-tree": "^1.0.1", "glob": "^7.1.2", "globals": "^11.7.0", "ignore": "^4.0.6", "imurmurhash": "^0.1.4", "inquirer": "^6.1.0", "is-resolvable": "^1.1.0", "js-yaml": "^3.12.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.3.0", "lodash": "^4.17.5", "minimatch": "^3.0.4", "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", "optionator": "^0.8.2", "path-is-inside": "^1.0.2", "pluralize": "^7.0.0", "progress": "^2.0.0", "regexpp": "^2.0.1", "require-uncached": "^1.0.3", "semver": "^5.5.1", "strip-ansi": "^4.0.0", "strip-json-comments": "^2.0.1", "table": "^5.0.2", "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { "node": "^6.14.0 || ^8.10.0 || >=9.10.0" } }, "node_modules/eslint-config-prettier": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz", "integrity": "sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w==", "dev": true, "dependencies": { "get-stdin": "^6.0.0" }, "bin": { "eslint-config-prettier-check": "bin/cli.js" }, "peerDependencies": { "eslint": ">=3.14.1" } }, "node_modules/eslint-plugin-prettier": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.0.tgz", "integrity": "sha512-4g11opzhqq/8+AMmo5Vc2Gn7z9alZ4JqrbZ+D4i8KlSyxeQhZHlmIrY8U9Akf514MoEhogPa87Jgkq87aZ2Ohw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0" }, "engines": { "node": ">=6.0.0" }, "peerDependencies": { "eslint": ">= 5.0.0", "prettier": ">= 1.13.0" } }, "node_modules/eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", "dev": true, "dependencies": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" }, "engines": { "node": ">=4.0.0" } }, "node_modules/eslint-utils": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "dependencies": { "eslint-visitor-keys": "^1.1.0" }, "engines": { "node": ">=6" } }, "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/eslint/node_modules/debug": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint/node_modules/ms": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "node_modules/espree": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", "dev": true, "dependencies": { "acorn": "^6.0.2", "acorn-jsx": "^5.0.0", "eslint-visitor-keys": "^1.0.0" }, "engines": { "node": ">=6.0.0" } }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, "node_modules/esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", "dev": true, "dependencies": { "estraverse": "^4.0.0" }, "engines": { "node": ">=0.6" } }, "node_modules/esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "dependencies": { "estraverse": "^4.1.0" }, "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "node_modules/external-editor": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", "dev": true, "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" }, "engines": { "node": ">=4" } }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true, "engines": [ "node >=0.6.0" ] }, "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, "node_modules/fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, "node_modules/figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5" }, "engines": { "node": ">=4" } }, "node_modules/file-entry-cache": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "dependencies": { "flat-cache": "^1.2.1", "object-assign": "^4.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/finalhandler": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "dev": true, "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.1", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.2", "statuses": "~1.3.1", "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/find-cache-dir": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz", "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==", "dev": true, "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.0", "pkg-dir": "^4.1.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "dependencies": { "circular-json": "^0.3.1", "del": "^2.0.2", "graceful-fs": "^4.1.2", "write": "^0.2.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, "dependencies": { "is-callable": "^1.1.3" } }, "node_modules/foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^3.0.2" }, "engines": { "node": ">=8.0.0" } }, "node_modules/foreground-child/node_modules/cross-spawn": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/foreground-child/node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/foreground-child/node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/foreground-child/node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/foreground-child/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", "dev": true, "engines": { "node": "*" } }, "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" }, "engines": { "node": ">= 0.12" } }, "node_modules/fromentries": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", "dev": true }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "node_modules/gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-stdin": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", "dev": true, "dependencies": { "assert-plus": "^1.0.0" } }, "node_modules/glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" } }, "node_modules/globals": { "version": "11.8.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/globby": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "dependencies": { "array-union": "^1.0.1", "arrify": "^1.0.0", "glob": "^7.0.3", "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", "dev": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" }, "engines": { "node": ">=6" } }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { "function-bind": "^1.1.1" }, "engines": { "node": ">= 0.4.0" } }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/has-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/hasha": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", "dev": true, "dependencies": { "is-stream": "^2.0.0", "type-fest": "^0.8.0" }, "engines": { "node": ">=8" } }, "node_modules/html-escaper": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", "dev": true }, "node_modules/html-validator": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/html-validator/-/html-validator-0.0.8.tgz", "integrity": "sha512-7iL7tXUZ73BpRgb9n9dkLCIFbMLUu+liJVOmGwltrMjZf1eVwoIGfpBxnLLCSq9iefAoWb/I1DUiRJWUj9tbUA==", "dev": true, "dependencies": { "minimist": "^1.1.0", "request": "^2.42.0", "valid-url": "^1.0.9" }, "bin": { "html-validator": "cli.js" }, "engines": { "node": ">=0.10.0" } }, "node_modules/html-validator-cli": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-validator-cli/-/html-validator-cli-2.0.0.tgz", "integrity": "sha512-bfWxpGvVdenUqpJrI4HSCiVP+QPtik86epTTnXGtUU1USAi2sGfJOHTf8cLFqPKsooF+9i0xcH8h7fILnFxEbA==", "dev": true, "dependencies": { "html-validator": "^0.0.8", "minimist": "^1.2.0" }, "bin": { "html-validator": "index.js" }, "engines": { "node": ">=0.12.0" } }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dev": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" }, "engines": { "node": ">=0.8", "npm": ">=1.3.7" } }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true, "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "node_modules/inquirer": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", "dev": true, "dependencies": { "ansi-escapes": "^3.0.0", "chalk": "^2.0.0", "cli-cursor": "^2.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.0", "figures": "^2.0.0", "lodash": "^4.17.10", "mute-stream": "0.0.7", "run-async": "^2.2.0", "rxjs": "^6.1.0", "string-width": "^2.1.0", "strip-ansi": "^4.0.0", "through": "^2.3.6" }, "engines": { "node": ">=6.0.0" } }, "node_modules/is-callable": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-path-in-cwd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "dependencies": { "is-path-inside": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-path-inside": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "dependencies": { "path-is-inside": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, "node_modules/is-regex": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "dependencies": { "has": "^1.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, "node_modules/is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "dependencies": { "has-symbols": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "node_modules/isomorphic-ws": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", "peerDependencies": { "ws": "*" } }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-hook": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "dependencies": { "append-transform": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", "dev": true, "dependencies": { "@babel/core": "^7.7.5", "@babel/parser": "^7.7.5", "@babel/template": "^7.7.4", "@babel/traverse": "^7.7.4", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/istanbul-lib-processinfo": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", "dev": true, "dependencies": { "archy": "^1.0.0", "cross-spawn": "^7.0.0", "istanbul-lib-coverage": "^3.0.0-alpha.1", "make-dir": "^3.0.0", "p-map": "^3.0.0", "rimraf": "^3.0.0", "uuid": "^3.3.3" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-processinfo/node_modules/cross-spawn": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/istanbul-lib-processinfo/node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/istanbul-lib-processinfo/node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-processinfo/node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-processinfo/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-report/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-report/node_modules/supports-color": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", "dev": true, "dependencies": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" }, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-source-maps/node_modules/debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", "dev": true, "dependencies": { "ms": "^2.1.1" } }, "node_modules/istanbul-lib-source-maps/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/istanbul-lib-source-maps/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/istanbul-reports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.0.tgz", "integrity": "sha512-2osTcC8zcOSUkImzN2EWQta3Vdi4WjjKw99P2yWx5mLnigAM0Rd5uYFn1cf2i/Ois45GkNjaoTqc5CxgMSX80A==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, "node_modules/js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/js2xmlparser": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "dev": true, "dependencies": { "xmlcreate": "^2.0.4" } }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, "node_modules/jsdoc": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.2.tgz", "integrity": "sha512-e8cIg2z62InH7azBBi3EsSEqrKx+nUtAS5bBcYTSpZFA+vhNPyhv8PTFZ0WsjOPDj04/dOLlm08EDcQJDqaGQg==", "dev": true, "dependencies": { "@babel/parser": "^7.20.15", "@jsdoc/salty": "^0.2.1", "@types/markdown-it": "^12.2.3", "bluebird": "^3.7.2", "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", "klaw": "^3.0.0", "markdown-it": "^12.3.2", "markdown-it-anchor": "^8.4.1", "marked": "^4.0.10", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", "strip-json-comments": "^3.1.0", "underscore": "~1.13.2" }, "bin": { "jsdoc": "jsdoc.js" }, "engines": { "node": ">=12.0.0" } }, "node_modules/jsdoc/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/jsdoc/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" } }, "node_modules/jsdoc/node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=4" } }, "node_modules/json-int64": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.2.tgz", "integrity": "sha512-uGrIXtRehbksM17S2lJRLPljufK52KL2ewbJi0xgcRPONoRLXa4yAUIKAUxF69dbnqIoBu33fB28MAWSxupB8Q==", "dev": true, "dependencies": { "node-int64": "0.4.0" } }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" }, "engines": { "node": ">=0.6.0" } }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "dev": true, "dependencies": { "graceful-fs": "^4.1.9" } }, "node_modules/levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dev": true, "dependencies": { "uc.micro": "^1.0.1" } }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "node_modules/lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, "node_modules/make-dir": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", "dev": true, "dependencies": { "semver": "^6.0.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true, "bin": { "semver": "bin/semver.js" } }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "dev": true, "dependencies": { "argparse": "^2.0.1", "entities": "~2.1.0", "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" }, "bin": { "markdown-it": "bin/markdown-it.js" } }, "node_modules/markdown-it-anchor": { "version": "8.6.5", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.5.tgz", "integrity": "sha512-PI1qEHHkTNWT+X6Ip9w+paonfIQ+QZP9sCeMYi47oqhH+EsW8CrJ8J7CzV19QVOj6il8ATGbK2nTECj22ZHGvQ==", "dev": true, "peerDependencies": { "@types/markdown-it": "*", "markdown-it": "*" } }, "node_modules/markdown-it/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, "node_modules/marked": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", "dev": true, "bin": { "marked": "bin/marked.js" }, "engines": { "node": ">= 12" } }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "dev": true }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "dependencies": { "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "node_modules/mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, "node_modules/node-gyp-build": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", "dev": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "dependencies": { "process-on-spawn": "^1.0.0" }, "engines": { "node": ">=8" } }, "node_modules/nyc": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.0.0.tgz", "integrity": "sha512-qcLBlNCKMDVuKb7d1fpxjPR8sHeMVX0CHarXAVzrVWoFrigCkYR8xcrjfXSPi5HXM7EU78L6ywO7w1c5rZNCNg==", "dev": true, "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "caching-transform": "^4.0.0", "convert-source-map": "^1.7.0", "decamelize": "^1.2.0", "find-cache-dir": "^3.2.0", "find-up": "^4.1.0", "foreground-child": "^2.0.0", "glob": "^7.1.6", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-hook": "^3.0.0", "istanbul-lib-instrument": "^4.0.0", "istanbul-lib-processinfo": "^2.0.2", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.0", "js-yaml": "^3.13.1", "make-dir": "^3.0.0", "node-preload": "^0.2.0", "p-map": "^3.0.0", "process-on-spawn": "^1.0.0", "resolve-from": "^5.0.0", "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "spawn-wrap": "^2.0.0", "test-exclude": "^6.0.0", "uuid": "^3.3.3", "yargs": "^15.0.2" }, "bin": { "nyc": "bin/nyc.js" }, "engines": { "node": ">=8.9" } }, "node_modules/nyc/node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/nyc/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/nyc/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, "engines": { "node": "*" } }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", "dev": true }, "node_modules/object-keys": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", "dev": true, "engines": { "node": ">= 0.4" } }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "dependencies": { "ee-first": "1.1.1" }, "engines": { "node": ">= 0.8" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "dependencies": { "mimic-fn": "^1.0.0" }, "engines": { "node": ">=4" } }, "node_modules/optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", "levn": "~0.3.0", "prelude-ls": "~1.1.2", "type-check": "~0.3.2", "wordwrap": "~1.0.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/p-limit": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "dev": true, "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/package-hash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "dependencies": { "graceful-fs": "^4.1.15", "hasha": "^5.0.0", "lodash.flattendeep": "^4.4.0", "release-zalgo": "^1.0.0" }, "engines": { "node": ">=8" } }, "node_modules/package-hash/node_modules/graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, "node_modules/parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true, "engines": { "node": ">= 0.8" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, "node_modules/path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, "node_modules/pify": { "version": "2.3.0", "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "dependencies": { "pinkie": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "dependencies": { "find-up": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "1.14.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.14.3.tgz", "integrity": "sha512-qZDVnCrnpsRJJq5nSsiHCE3BYMED2OtsI+cmzIzF1QIfqm5ALf8tEJcO27zV1gKNKRPdhjO0dNWnrzssDQ1tFg==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=4" } }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "dependencies": { "fast-diff": "^1.1.2" }, "engines": { "node": ">=6.0.0" } }, "node_modules/process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", "dev": true, "dependencies": { "fromentries": "^1.2.0" }, "engines": { "node": ">=8" } }, "node_modules/progress": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "engines": { "node": ">=0.6.0", "teleport": ">=0.2.0" } }, "node_modules/qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true, "engines": { "node": ">=0.6" } }, "node_modules/regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true, "engines": { "node": ">=6.5.0" } }, "node_modules/release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", "dev": true, "dependencies": { "es6-error": "^4.0.1" }, "engines": { "node": ">=4" } }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, "engines": { "node": ">= 6" } }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "node_modules/require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "dependencies": { "caller-path": "^0.1.0", "resolve-from": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", "dev": true, "dependencies": { "lodash": "^4.17.14" } }, "node_modules/resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" }, "engines": { "node": ">=4" } }, "node_modules/resumer": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", "dev": true, "dependencies": { "through": "~2.3.4" } }, "node_modules/rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "dependencies": { "glob": "^7.0.5" }, "bin": { "rimraf": "bin.js" } }, "node_modules/run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "dependencies": { "is-promise": "^2.1.0" }, "engines": { "node": ">=0.12.0" } }, "node_modules/rxjs": { "version": "6.3.3", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "dependencies": { "tslib": "^1.9.0" }, "engines": { "npm": ">=2.0.0" } }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "node_modules/semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "dependencies": { "shebang-regex": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "node_modules/slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "dependencies": { "is-fullwidth-code-point": "^2.0.0" }, "engines": { "node": ">=4" } }, "node_modules/spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "dependencies": { "foreground-child": "^2.0.0", "is-windows": "^1.0.2", "make-dir": "^3.0.0", "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "which": "^2.0.1" }, "engines": { "node": ">=8" } }, "node_modules/spawn-wrap/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/spawn-wrap/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "node_modules/sshpk": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", "sshpk-sign": "bin/sshpk-sign", "sshpk-verify": "bin/sshpk-verify" }, "engines": { "node": ">=0.10.0" } }, "node_modules/statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "dependencies": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" }, "engines": { "node": ">=4" } }, "node_modules/string.prototype.trim": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", "dev": true, "dependencies": { "define-properties": "^1.1.2", "es-abstract": "^1.5.0", "function-bind": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "dependencies": { "ansi-regex": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/table": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/table/-/table-5.1.0.tgz", "integrity": "sha512-e542in22ZLhD/fOIuXs/8yDZ9W61ltF8daM88rkRNtgTIct+vI2fTnAyu/Db2TCfEcI8i7mjZz6meLq0nW7TYg==", "dev": true, "dependencies": { "ajv": "^6.5.3", "lodash": "^4.17.10", "slice-ansi": "1.0.0", "string-width": "^2.1.1" }, "engines": { "node": ">=6.0.0" } }, "node_modules/tape": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz", "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", "dev": true, "dependencies": { "deep-equal": "~1.0.1", "defined": "~1.0.0", "for-each": "~0.3.3", "function-bind": "~1.1.1", "glob": "~7.1.2", "has": "~1.0.3", "inherits": "~2.0.3", "minimist": "~1.2.0", "object-inspect": "~1.6.0", "resolve": "~1.7.1", "resumer": "~0.0.0", "string.prototype.trim": "~1.1.2", "through": "~2.3.8" }, "bin": { "tape": "bin/tape" } }, "node_modules/tape/node_modules/resolve": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", "dev": true, "dependencies": { "path-parse": "^1.0.5" } }, "node_modules/tape/node_modules/resolve/node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, "node_modules/test-exclude/node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "node_modules/through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, "engines": { "node": ">=0.6.0" } }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" }, "engines": { "node": ">=0.8" } }, "node_modules/tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, "dependencies": { "safe-buffer": "^5.0.1" }, "engines": { "node": "*" } }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "dependencies": { "prelude-ls": "~1.1.2" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "dependencies": { "is-typedarray": "^1.0.0" } }, "node_modules/typescript": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=4.2.0" } }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, "node_modules/underscore": { "version": "1.13.6", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", "dev": true }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true, "engines": { "node": ">= 0.8" } }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "dependencies": { "punycode": "^2.1.0" } }, "node_modules/utf-8-validate": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", "dev": true, "hasInstallScript": true, "dependencies": { "node-gyp-build": "~3.7.0" } }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true, "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, "bin": { "uuid": "bin/uuid" } }, "node_modules/valid-url": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA==", "dev": true }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "dev": true, "engines": [ "node >=0.6.0" ], "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, "node_modules/wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "dependencies": { "@types/color-name": "^1.1.1", "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/wrap-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=8" } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "node_modules/write": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "dependencies": { "mkdirp": "^0.5.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/write-file-atomic": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", "signal-exit": "^3.0.2", "typedarray-to-buffer": "^3.1.5" } }, "node_modules/ws": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz", "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", "dependencies": { "async-limiter": "~1.0.0" } }, "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "dev": true }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" }, "engines": { "node": ">=8" } }, "node_modules/yargs/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/yargs/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/yargs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/yargs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/yargs/node_modules/yargs-parser": { "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" }, "engines": { "node": ">=6" } } } } thrift-0.19.0/LICENSE0000644000000000000000000003616014303740367014121 0ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -------------------------------------------------- SOFTWARE DISTRIBUTED WITH THRIFT: The Apache Thrift software includes a number of subcomponents with separate copyright notices and license terms. Your use of the source code for the these subcomponents is subject to the terms and conditions of the following licenses. -------------------------------------------------- Portions of the following files are licensed under the MIT License: lib/erl/src/Makefile.am Please see doc/otp-base-license.txt for the full terms of this license. -------------------------------------------------- For the aclocal/ax_boost_base.m4 and contrib/fb303/aclocal/ax_boost_base.m4 components: # Copyright (c) 2007 Thomas Porschberg # # 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. -------------------------------------------------- For the lib/nodejs/lib/thrift/json_parse.js: /* json_parse.js 2015-05-02 Public Domain. NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. */ (By Douglas Crockford ) -------------------------------------------------- For lib/cpp/src/thrift/windows/SocketPair.cpp /* socketpair.c * Copyright 2007 by Nathan C. Myers ; some rights reserved. * This code is Free Software. It may be copied freely, in original or * modified form, subject only to the restrictions that (1) the author is * relieved from all responsibilities for any use for any purpose, and (2) * this copyright notice must be retained, unchanged, in its entirety. If * for any reason the author might be held responsible for any consequences * of copying or use, license is withheld. */ -------------------------------------------------- For lib/py/compat/win32/stdint.h // ISO C9x compliant stdint.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006-2008 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// -------------------------------------------------- Codegen template in t_html_generator.h * Bootstrap v2.0.3 * * Copyright 2012 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Designed and built with all the love in the world @twitter by @mdo and @fat. --------------------------------------------------- For t_cl_generator.cc * Copyright (c) 2008- Patrick Collison * Copyright (c) 2006- Facebook --------------------------------------------------- thrift-0.19.0/LANGUAGES.md0000644000000000000000000013507314472647462014760 0ustar00rootroot00000000000000# Apache Thrift Language Support # Guidance For: 0.17.0 | [0.16.0](https://github.com/apache/thrift/blob/v0.16.0/LANGUAGES.md) | [0.15.0](https://github.com/apache/thrift/blob/v0.15.0/LANGUAGES.md) | [0.14.0](https://github.com/apache/thrift/blob/v0.14.0/LANGUAGES.md) | [0.13.0](https://github.com/apache/thrift/blob/v0.13.0/LANGUAGES.md) | [0.12.0](https://github.com/apache/thrift/blob/v0.12.0/LANGUAGES.md) | [0.11.0](https://github.com/apache/thrift/blob/0.11.0/LANGUAGES.md) Thrift supports many programming languages and has an impressive test suite that exercises most of the languages, protocols, and transports. Each build exercises a matrix of thousands of possible combinations. Each language typically has a minimum required version as well as support libraries - some mandatory and some optional. The information provided below will help you assess whether you can use Apache Thrift with your project. Obviously this is a complex matrix to maintain and may not be correct in all cases - if you spot an error please inform the developers using the mailing list, or better yet, [Edit on GitHub](https://github.com/apache/thrift/edit/master/LANGUAGES.md). Apache Thrift currently uses two build systems. The `autoconf` build system is the most complete and builds all supported languages, however it does not support Windows.. The `cmake` build system works on Linux and Windows, and has been designated by the project to replace `autoconf` however this transition will take quite some time to complete. During that transition, the cmake build will not support all languages. The Language/Library Levels indicate the minimum and maximum versions that are used in the [continuous integration environments](build/docker/README.md) (Appveyor, Travis) for Apache Thrift. Other language levels may be supported for each language, however tested less thoroughly; check the README file inside each lib directory for additional details. Note: while a language may contain support for protocols, transports, and servers, the extent to which each is tested as part of the overall build process varies. The definitive integration test for the project is called the "cross" test which executes a test matrix with clients and servers communicating across languages. Thrift's core transport (supported by all languages) is TSocket. Thrift's core protocol is TBinary, supported by all languages except for JavaScript.
Language Since Build Systems Lang/Lib Levels (Tested) Field types Low-Level Transports Transport Wrappers Protocols Servers Open Issues
autoconfcmake MinMax Uuid Domain File Memory Pipe Socket TLS  FramedHeader http  zlib  BinaryCompact JSON Multiplex ForkingNonblockingSimpleThreadedThreadPool
C (glib) 0.6.0 YesYes 2.48.22.56.4 YesYesYesYesYes Yes YesYesYes Yes C (glib)
C++ 0.2.0 YesYes C++11 YesYesYesYesYesYes YesYesYesYes YesYesYesYes YesYesYesYes C++
Common LISP 0.12.0 Yes SBCL 1.4.xSBCL 1.5.3 YesYes Yes YesYesYes Yes Common LISP
Dlang 0.9.0 Yes 2.087.02.087.0 YesYesYesYesYes YesYesYes YesYesYes YesYesYesYes D
Dart 0.10.0 Yes 2.0.02.4.0 Yes YesYes YesYesYesYes Dart
Delphi 0.8.0 2010Alexandria 11.2 Yes Yes YesYes YesYesYesYes Yes Delphi
.NET Standard 0.13.0 Yes .NET Standard 2.x, .NET 6 Yes YesYesYesYes YesYes YesYesYesYes Yes .NET Standard
Erlang 0.3.0 Yes 18.322.0 YesYesYesYes YesYes YesYesYesYes Yes Erlang
Go 0.7.0 Yes 1.201.21 YesYesYes YesYesYesYes YesYesYesYes Yes Go
Haxe 0.9.3 Yes 4.1.54.2.5 YesYes YesYes YesYesYesYes Yes Haxe
Java (SE) 0.2.0 YesYes 1119 YesYesYesYes YesYesYes YesYesYesYes YesYesYesYes Java SE
Java (ME) 0.5.0 unknown YesYesYes Yes YesYes Java ME
Javascript 0.3.0 Yes ES5ES6 YesYes Yes YesYes Javascript
Lua 0.9.2 Yes 5.1.55.2.4 YesYes YesYes YesYesYes Yes Lua
node.js 0.6.0 Yes 10.x10.x YesYesYes YesYesYes YesYesYesYes Yes node.js
node.ts 0.12.0 Yes 3.1.6 YesYes Yes Yes node.ts
OCaml 0.2.0 4.04.0 Yes Yes Yes YesYes OCaml
Perl 0.2.0 Yes 5.22.15.26.1 YesYesYesYes YesYes YesYesYes YesYes Perl
PHP 0.2.0 Yes 7.0.227.2.19 YesYesYes YesYes YesYesYesYes YesYes PHP
Python 0.2.0 YesYes 2.7.12, 3.5.22.7.15, 3.6.8 YesYesYes YesYesYes YesYesYesYes YesYesYes Python
Ruby 0.2.0 Yes 2.3.1p1122.5.1p57 YesYesYesYes YesYes YesYesYesYes YesYesYesYes Ruby
Rust 0.11.0 Yes 1.61.01.xx.x YesYes Yes YesYesYes Yes Rust
Smalltalk 0.2.0 unknown Yes Yes Smalltalk
Swift 0.12.0 Yes 5.7 YesYesYesYes YesYes YesYesYes Yes Swift
Language Since autoconfcmake MinMax Uuid Domain File Memory Pipe Socket TLS  FramedHeader http  zlib  BinaryCompact JSON Multiplex ForkingNonblockingSimpleThreadedThreadPool Open Issues
Build Systems Lang/Lib Levels (Tested) Field types Low-Level Transports Transport Wrappers Protocols Servers
thrift-0.19.0/doc/0000777000000000000000000000000014303740367013657 5ustar00rootroot00000000000000thrift-0.19.0/doc/licenses/0000777000000000000000000000000014303740367015464 5ustar00rootroot00000000000000thrift-0.19.0/doc/licenses/lgpl-2.1.txt0000644000000000000000000006350414303740367017465 0ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! thrift-0.19.0/doc/licenses/otp-base-license.txt0000644000000000000000000000216414303740367021356 0ustar00rootroot00000000000000Tue Oct 24 12:28:44 CDT 2006 Copyright (c) <2006> Permission is hereby granted, free of charge, to any person obtaining a copy of this software (OTP Base, fslib, G.A.S) 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. thrift-0.19.0/doc/specs/0000777000000000000000000000000014454461475015003 5ustar00rootroot00000000000000thrift-0.19.0/doc/specs/idl.md0000644000000000000000000002732514454461475016102 0ustar00rootroot00000000000000## Thrift interface description language For Thrift version 0.19.0. The Thrift interface definition language (IDL) allows for the definition of [Thrift Types](/docs/types). A Thrift IDL file is processed by the Thrift code generator to produce code for the various target languages to support the defined structs and services in the IDL file. ## Description Here is a description of the Thrift IDL. ## Document Every Thrift document contains 0 or more headers followed by 0 or more definitions. [1] Document ::= Header* Definition* ## Header A header is either a Thrift include, a C++ include, or a namespace declaration. [2] Header ::= Include | CppInclude | Namespace ### Thrift Include An include makes all the symbols from another file visible (with a prefix) and adds corresponding include statements into the code generated for this Thrift document. [3] Include ::= 'include' Literal ### C++ Include A C++ include adds a custom C++ include to the output of the C++ code generator for this Thrift document. [4] CppInclude ::= 'cpp_include' Literal ### Namespace A namespace declares which namespaces/package/module/etc. the type definitions in this file will be declared in for the target languages. The namespace scope indicates which language the namespace applies to; a scope of '*' indicates that the namespace applies to all target languages. [5] Namespace ::= ( 'namespace' ( NamespaceScope Identifier ) ) [6] NamespaceScope ::= '*' | 'c_glib' | 'cpp' | 'delphi' | 'haxe' | 'go' | 'java' | 'js' | 'lua' | 'netstd' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd' ## Definition [7] Definition ::= Const | Typedef | Enum | Struct | Union | Exception | Service ### Const [8] Const ::= 'const' FieldType Identifier '=' ConstValue ListSeparator? ### Typedef A typedef creates an alternate name for a type. [9] Typedef ::= 'typedef' DefinitionType Identifier ### Enum An enum creates an enumerated type, with named values. If no constant value is supplied, the value is either 0 for the first element, or one greater than the preceding value for any subsequent element. Any constant value that is supplied must be non-negative. [10] Enum ::= 'enum' Identifier '{' (Identifier ('=' IntConstant)? ListSeparator?)* '}' ### Struct Structs are the fundamental compositional type in Thrift. The name of each field must be unique within the struct. [11] Struct ::= 'struct' Identifier 'xsd_all'? '{' Field* '}' N.B.: The `xsd_all` keyword has some purpose internal to Facebook but serves no purpose in Thrift itself. Use of this feature is strongly discouraged ### Union Unions are similar to structs, except that they provide a means to transport exactly one field of a possible set of fields, just like union {} in C++. Consequently, union members are implicitly considered optional (see requiredness). [12] Union ::= 'union' Identifier 'xsd_all'? '{' Field* '}' N.B.: The `xsd_all` keyword has some purpose internal to Facebook but serves no purpose in Thrift itself. Use of this feature is strongly discouraged ### Exception Exceptions are similar to structs except that they are intended to integrate with the native exception handling mechanisms in the target languages. The name of each field must be unique within the exception. [13] Exception ::= 'exception' Identifier '{' Field* '}' ### Service A service provides the interface for a set of functionality provided by a Thrift server. The interface is simply a list of functions. A service can extend another service, which simply means that it provides the functions of the extended service in addition to its own. [14] Service ::= 'service' Identifier ( 'extends' Identifier )? '{' Function* '}' ## Field [15] Field ::= FieldID? FieldReq? FieldType Identifier ('=' ConstValue)? XsdFieldOptions ListSeparator? ### Field ID [16] FieldID ::= IntConstant ':' ### Field Requiredness There are two explicit requiredness values, and a third one that is applied implicitly if neither *required* nor *optional* are given: *default* requiredness. [17] FieldReq ::= 'required' | 'optional' The general rules for requiredness are as follows: #### required - Write: Required fields are always written and are expected to be set. - Read: Required fields are always read and are expected to be contained in the input stream. - Defaults values: are always written If a required field is missing during read, the expected behaviour is to indicate an unsuccessful read operation to the caller, e.g. by throwing an exception or returning an error. Because of this behaviour, required fields drastically limit the options with regard to soft versioning. Because they must be present on read, the fields cannot be deprecated. If a required field would be removed (or changed to optional), the data are no longer compatible between versions. #### optional - Write: Optional fields are only written when they are set - Read: Optional fields may, or may not be part of the input stream. - Default values: are written when the isset flag is set Most language implementations use the recommended practice of so-called "isset" flags to indicate whether a particular optional field is set or not. Only fields with this flag set are written, and conversely the flag is only set when a field value has been read from the input stream. #### default requiredness (implicit) - Write: In theory, the fields are always written. There are some exceptions to that rule, see below. - Read: Like optional, the field may, or may not be part of the input stream. - Default values: may not be written (see next section) Default requiredness is a good starting point. The desired behaviour is a mix of optional and required, hence the internal name "opt-in, req-out". Although in theory these fields are supposed to be written ("req-out"), in reality unset fields are not always written. This is especially the case, when the field contains a value, which by definition cannot be transported through thrift. The only way to achieve this is by not writing that field at all, and that's what most languages do. #### Semantics of Default Values There are ongoing discussions about that topic, see JIRA for details. Not all implementations treat default values in the very same way, but the current status quo is more or less that default fields are typically set at initialization time. Therefore, a value that equals the default may not be written, because the read end will set the value implicitly. On the other hand, an implementation is free to write the default value anyways, as there is no hard restriction that prevents this. The major point to keep in mind here is the fact, that any unwritten default value implicitly becomes part of the interface version. If that default is changed, the interface changes. If, in contrast, the default value is written into the output data, the default in the IDL can change at any time without affecting serialized data. ### XSD Options N.B.: These have some internal purpose at Facebook but serve no current purpose in Thrift. The use of these options is strongly discouraged. [18] XsdFieldOptions ::= 'xsd_optional'? 'xsd_nillable'? XsdAttrs? [19] XsdAttrs ::= 'xsd_attrs' '{' Field* '}' ## Functions [20] Function ::= 'oneway'? FunctionType Identifier '(' Field* ')' Throws? ListSeparator? [21] FunctionType ::= FieldType | 'void' [22] Throws ::= 'throws' '(' Field* ')' ## Types [23] FieldType ::= Identifier | BaseType | ContainerType [24] DefinitionType ::= BaseType | ContainerType [25] BaseType ::= 'bool' | 'byte' | 'i8' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary' | 'uuid' [26] ContainerType ::= MapType | SetType | ListType [27] MapType ::= 'map' CppType? '<' FieldType ',' FieldType '>' [28] SetType ::= 'set' CppType? '<' FieldType '>' [29] ListType ::= 'list' CppType? '<' FieldType '>' [30] CppType ::= 'cpp_type' Literal ## Constant Values [31] ConstValue ::= IntConstant | DoubleConstant | Literal | Identifier | ConstList | ConstMap [32] IntConstant ::= ('+' | '-')? Digit+ [33] DoubleConstant ::= ('+' | '-')? Digit* ('.' Digit+)? ( ('E' | 'e') IntConstant )? [34] ConstList ::= '[' (ConstValue ListSeparator?)* ']' [35] ConstMap ::= '{' (ConstValue ':' ConstValue ListSeparator?)* '}' ## Basic Definitions ### Literal [36] Literal ::= ('"' [^"]* '"') | ("'" [^']* "'") ### Identifier [37] Identifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' )* [38] STIdentifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' | '-' )* ### List Separator [39] ListSeparator ::= ',' | ';' ### Letters and Digits [40] Letter ::= ['A'-'Z'] | ['a'-'z'] [41] Digit ::= ['0'-'9'] ## Reserved keywords "BEGIN", "END", "__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__", "__LINE__", "__METHOD__", "__NAMESPACE__", "abstract", "alias", "and", "args", "as", "assert", "begin", "break", "case", "catch", "class", "clone", "continue", "declare", "def", "default", "del", "delete", "do", "dynamic", "elif", "else", "elseif", "elsif", "end", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "ensure", "except", "exec", "finally", "float", "for", "foreach", "from", "function", "global", "goto", "if", "implements", "import", "in", "inline", "instanceof", "interface", "is", "lambda", "module", "native", "new", "next", "nil", "not", "or", "package", "pass", "public", "print", "private", "protected", "raise", "redo", "rescue", "retry", "register", "return", "self", "sizeof", "static", "super", "switch", "synchronized", "then", "this", "throw", "transient", "try", "undef", "unless", "unsigned", "until", "use", "var", "virtual", "volatile", "when", "while", "with", "xor", "yield" ## Examples Here are some examples of Thrift definitions, using the Thrift IDL: * [ThriftTest.thrift][] used by the Thrift TestFramework * Thrift [tutorial][] * Facebook's [fb303.thrift][] * [Apache Cassandra's][] Thrift IDL: [cassandra.thrift][] * [Evernote API][] [ThriftTest.thrift]: https://raw.githubusercontent.com/apache/thrift/master/test/ThriftTest.thrift [tutorial]: /tutorial/ [fb303.thrift]: https://raw.githubusercontent.com/apache/thrift/master/contrib/fb303/if/fb303.thrift [Apache Cassandra's]: http://cassandra.apache.org/ [cassandra.thrift]: https://gitbox.apache.org/repos/asf?p=cassandra.git;a=blob_plain;f=interface/cassandra.thrift;hb=refs/heads/cassandra-3.0 [Evernote API]: https://github.com/evernote/evernote-thrift ## To Do/Questions Initialization of Base Types for all Languages? * Do all Languages initialize them to 0, bool=false and string=""? or null, undefined? Why does position of `CppType` vary between `SetType` and `ListType`? * std::set does sort the elements automatically, that's the design. see [Thrift Types](/docs/types) or the [C++ std:set reference][] for further details * The question is, how other languages are doing that? What about custom objects, do they have a Compare function to set the order correctly? [C++ std:set reference]: http://www.cplusplus.com/reference/stl/set/ Why can't `DefinitionType` be the same as `FieldType` (i.e. include `Identifier`)? Examine the `smalltalk.prefix` and `smalltalk.category` status (esp `smalltalk.category`, which takes `STIdentifier` as its argument)... What to do about `ListSeparator`? Do we really want to be as lax as we currently are? Should `Field*` really be `Field+` in `Struct`, `Enum`, etc.? thrift-0.19.0/doc/specs/thrift-rpc.md0000644000000000000000000002154714303740367017405 0ustar00rootroot00000000000000Thrift Remote Procedure Call ============================ This document describes the high-level message exchange between the Thrift RPC client and server. See [thrift-binary-protocol.md] and [thrift-compact-protocol.md] for a description of how the exchanges are encoded on the wire. In addition, this document compares the binary protocol with the compact protocol. Finally, it describes the framed vs. unframed transport. The information here is _mostly_ based on the Java implementation in the Apache thrift library (version 0.9.1 and 0.9.3). Other implementation, however, should behave the same. For background on Thrift see the [Thrift whitepaper (pdf)](https://thrift.apache.org/static/files/thrift-20070401.pdf). # Contents * Thrift Message exchange for Remote Procedure Call * Message * Request struct * Response struct * Protocol considerations * Comparing binary and compact protocol * Compatibility * Framed vs unframed transport # Thrift Remote Procedure Call Message exchange Both the binary protocol and the compact protocol assume a transport layer that exposes a bi-directional byte stream, for example a TCP socket. Both use the following exchange: 1. Client sends a `Message` (type `Call` or `Oneway`). The TMessage contains some metadata and the name of the method to invoke. 2. Client sends method arguments (a struct defined by the generate code). 3. Server sends a `Message` (type `Reply` or `Exception`) to start the response. 4. Server sends a struct containing the method result or exception. The pattern is a simple half duplex protocol where the parties alternate in sending a `Message` followed by a struct. What these are is described below. Although the standard Apache Thrift Java clients do not support pipelining (sending multiple requests without waiting for an response), the standard Apache Thrift Java servers do support it. ## Message A *Message* contains: * _Name_, a string (can be empty). * _Message type_, a message types, one of `Call`, `Reply`, `Exception` and `Oneway`. * _Sequence id_, a signed int32 integer. The *sequence id* is a simple message id assigned by the client. The server will use the same sequence id in the message of the response. The client uses this number to detect out of order responses. Each client has an int32 field which is increased for each message. The sequence id simply wraps around when it overflows. The *name* indicates the service method name to invoke. The server copies the name in the response message. When the *multiplexed protocol* is used, the name contains the service name, a colon `:` and the method name. The multiplexed protocol is not compatible with other protocols. The *message type* indicates what kind of message is sent. Clients send requests with TMessages of type `Call` or `Oneway` (step 1 in the protocol exchange). Servers send responses with messages of type `Exception` or `Reply` (step 3). Type `Reply` is used when the service method completes normally. That is, it returns a value or it throws one of the exceptions defined in the Thrift IDL file. Type `Exception` is used for other exceptions. That is: when the service method throws an exception that is not declared in the Thrift IDL file, or some other part of the Thrift stack throws an exception. For example when the server could not encode or decode a message or struct. In the Java implementation (0.9.3) there is different behavior for the synchronous and asynchronous server. In the async server all exceptions are sent as a `TApplicationException` (see 'Response struct' below). In the synchronous Java implementation only (undeclared) exceptions that extend `TException` are send as a `TApplicationException`. Unchecked exceptions lead to an immediate close of the connection. Type `Oneway` is only used starting from Apache Thrift 0.9.3. Earlier versions do _not_ send TMessages of type `Oneway`, even for service methods defined with the `oneway` modifier. When the client sends a request with type `Oneway`, the server must _not_ send a response (steps 3 and 4 are skipped). Note that the Thrift IDL enforces a return type of `void` and does not allow exceptions for oneway services. ## Request struct The struct that follows the message of type `Call` or `Oneway` contains the arguments of the service method. The argument ids correspond to the field ids. The name of the struct is the name of the method with `_args` appended. For methods without arguments an struct is sent without fields. ## Response struct The struct that follows the message of type `Reply` are structs in which exactly 1 of the following fields is encoded: * A field with name `success` and id `0`, used in case the method completed normally. * An exception field, name and id are as defined in the `throws` clause in the Thrift IDL's service method definition. When the message is of type `Exception` the struct is encoded as if it was declared by the following IDL: ``` exception TApplicationException { 1: string message, 2: i32 type } ``` The following exception types are defined in the java implementation (0.9.3): * _unknown_: 0, used in case the type from the peer is unknown. * _unknown method_: 1, used in case the method requested by the client is unknown by the server. * _invalid message type_: 2, no usage was found. * _wrong method name_: 3, no usage was found. * _bad sequence id_: 4, used internally by the client to indicate a wrong sequence id in the response. * _missing result_: 5, used internally by the client to indicate a response without any field (result nor exception). * _internal error_: 6, used when the server throws an exception that is not declared in the Thrift IDL file. * _protocol error_: 7, used when something goes wrong during decoding. For example when a list is too long or a required field is missing. * _invalid transform_: 8, no usage was found. * _invalid protocol_: 9, no usage was found. * _unsupported client type_: 10, no usage was found. # Protocol considerations ## Comparing binary and compact protocol The binary protocol is fairly simple and therefore easy to process. The compact protocol needs less bytes to send the same data at the cost of additional processing. As bandwidth is usually the bottleneck, the compact protocol is almost always slightly faster. ## Compatibility A server could automatically determine whether a client talks the binary protocol or the compact protocol by investigating the first byte. If the value is `1000 0000` or `0000 0000` (assuming a name shorter than ±16 MB) it is the binary protocol. When the value is `1000 0010` it is talking the compact protocol. ## Framed vs. unframed transport The first thrift binary wire format was unframed. This means that information is sent out in a single stream of bytes. With unframed transport the (generated) processors will read directly from the socket (though Apache Thrift does try to grab all available bytes from the socket in a buffer when it can). Later, Thrift introduced the framed transport. With framed transport the full request and response (the TMessage and the following struct) are first written to a buffer. Then when the struct is complete (transport method `flush` is hijacked for this), the length of the buffer is written to the socket first, followed by the buffered bytes. The combination is called a _frame_. On the receiver side the complete frame is first read in a buffer before the message is passed to a processor. The length prefix is a 4 byte signed int, send in network (big endian) order. The following must be true: `0` <= length <= `16384000` (16M). Framed transport was introduced to ease the implementation of async processors. An async processor is only invoked when all data is received. Unfortunately, framed transport is not ideal for large messages as the entire frame stays in memory until the message has been processed. In addition, the java implementation merges the incoming data to a single, growing byte array. Every time the byte array is full it needs to be copied to a new larger byte array. Framed and unframed transports are not compatible with each other. thrift-0.19.0/doc/specs/thrift-sasl-spec.txt0000644000000000000000000001355014303740367020725 0ustar00rootroot00000000000000A Thrift SASL message shall be a byte array of the following form: | 1-byte status code | 4-byte payload length | variable-length payload | The length fields shall be interpreted as integers, with the high byte sent first. This indicates the length of the field immediately following it, not including the status code or the length bytes. The possible status codes are: 0x01 - START - Hello, let's go on a date. 0x02 - OK - Everything's been going alright so far, let's see each other again. 0x03 - BAD - I understand what you're saying. I really do. I just don't like it. We have to break up. 0x04 - ERROR - We can't go on like this. It's like you're speaking another language. 0x05 - COMPLETE - Will you marry me? The Thrift SASL communication will proceed as follows: 1. The client is configured at instantiation of the transport with a single underlying SASL security mechanism that it supports. 2. The server is configured with a mapping of underlying security mechanism name -> mechanism options. 3. At connection time, the client will initiate communication by sending the server a START message. The payload of this message will be the name of the underlying security mechanism that the client would like to use. This mechanism name shall be 1-20 characters in length, and follow the specifications for SASL mechanism names specified in RFC 2222. 4. The server receives this message and, if the mechanism name provided is among the set of mechanisms this server transport is configured to accept, appropriate initialization of the underlying security mechanism may take place. If the mechanism name is not one which the server is configured to support, the server shall return the BAD byte, followed by a 4-byte, potentially zero-value message length, followed by the potentially zero-length payload which may be a status code or message indicating failure. No further communication may take place via this transport. If the mechanism name is one which the server supports, then proceed to step 5. 5. Following the START message, the client must send another message containing the "initial response" of the chosen SASL implementation. The client may send this message piggy-backed on the "START" message of step 3. The message type of this message must be either "OK" or "COMPLETE", depending on whether the SASL implementation indicates that this side of the authentication has been satisfied. 6. The server then provides the byte array of the payload received to its underlying security mechanism. A challenge is generated by the underlying security mechanism on the server, and this is used as the payload for a message sent to the client. This message shall consist of an OK byte, followed by the non-zero message length word, followed by the payload. 7. The client receives this message from the server and passes the payload to its underlying security mechanism to generate a response. The client then sends the server an OK byte, followed by the non-zero-value length of the response, followed by the bytes of the response as the payload. 8. Steps 6 and 7 are repeated until both security mechanisms are satisfied with the challenge/response exchange. When either side has completed its security protocol, its next message shall be the COMPLETE byte, followed by a 4-byte potentially zero-value length word, followed by a potentially zero-length payload. This payload will be empty except for those underlying security mechanisms which provide additional data with success. If at any point in time either side is able to interpret the challenge or response sent by the other, but is dissatisfied with the contents thereof, this side should send the other a BAD byte, followed by a 4-byte potentially zero-value length word, followed by an optional, potentially zero-length message encoded in UTF-8 indicating failure. This message should be passed to the protocol above the thrift transport by whatever mechanism is appropriate and idiomatic for the particular language these thrift bindings are for. If at any point in time either side fails to interpret the challenge or response sent by the other, this side should send the other an ERROR byte, followed by a 4-byte potentially zero-value length word, followed by an optional, potentially zero-length message encoded in UTF-8. This message should be passed to the protocol above the thrift transport by whatever mechanism is appropriate and idiomatic for the particular language these thrift bindings are for. If step 8 completes successfully, then the communication is considered authenticated and subsequent communication may commence. If step 8 fails to complete successfully, then no further communication may take place via this transport. 8. All writes to the underlying transport must be prefixed by the 4-byte length of the payload data, followed by the payload. All reads from this transport should read the 4-byte length word, then read the full quantity of bytes specified by this length word. If no SASL QOP (quality of protection) is negotiated during steps 6 and 7, then all subsequent writes to/reads from this transport are written/read unaltered, save for the length prefix, to the underlying transport. If a SASL QOP is negotiated, then this must be used by the Thrift transport for all subsequent communication. This is done by wrapping subsequent writes to the transport using the underlying security mechanism, and unwrapping subsequent reads from the underlying transport. Note that in this case, the length prefix of the write to the underlying transport is the length of the data after it has been wrapped by the underlying security mechanism. Note that the complete message must be read before giving this data to the underlying security mechanism for unwrapping. If at any point in time reading of a message fails either because of a malformed length word or failure to unwrap by the underlying security mechanism, then all further communication on this transport must cease. thrift-0.19.0/doc/specs/SequenceNumbers.md0000644000000000000000000000232014303740367020413 0ustar00rootroot00000000000000# Sequence Number # Apache Thrift built sequence numbers into every protocol exchange to allow for clients that may submit multiple outstanding requests on a single transport connection. This is typically done by asynchronous clients. The following rules apply to sequence numbers: 1. A sequence number is a signed 32-bit integer. Negative values are allowed. 1. Sequence numbers `MUST` be unique across all outstanding requests on a given transport connection. There is no requirement for unique numbers between different transport connections even if they are from the same client. 1. A server `MUST` reply to a client with the same sequence number that was used in the request. This includes any exception-based reply. 1. A client `MAY` use sequence numbers if it needs them for proper operation. 1. A client `SHOULD` set the sequence number to zero if it does not rely on them. 1. Wrapped protocols (such as THeaderProtocol) `SHOULD` use the same sequence number on the wrapping as is used on the payload protocol. Servers will not inspect or make any logic choices based on the sequence number sent by the client. The server's only job is to process the request and reply with the same sequence number. thrift-0.19.0/doc/specs/thrift-tconfiguration.md0000644000000000000000000001277014303740367021652 0ustar00rootroot00000000000000Thrift TConfiguration ==================================================================== Last Modified: 2019-Dec-03 Starting with THRIFT-5021 the need to centralize certain limit settings that are used throughout the whole protocol / transport stack became an obvious need. Previous patches already added some of these limits, but they were not consistently managed and just randomly distributed across the code base. # Design goals Following the tradition of similar experience across languages in Thrift, any implementation should meet these design goals: * There MUST be a standard CTOR (or equivalent thereof) that provides a default TConfiguration instance. * The default values used SHOULD be implemented as outlined below. * For backwards compatibility, the protocol / transport stack should accept null TConfiguration argument, in which case it should fallback to a default instance automatically. This is to prevent from code-breaking changes as much as possible. # Implementation The new TConfiguration class or struct currently holds three settings: ## MaxMessageSize The MaxMessageSize member defines the maximum size of a (received) message, in bytes. The default value is represented by a constant named DEFAULT_MAX_MESSAGE_SIZE, whose value is 100 * 1024 * 1024 bytes. ## MaxFrameSize MaxFrameSize limits the size of one frame of data for the TFramedTransport. Since all implementations currently send messages in one frame only if TFramedTransport is used, this value may interfere with MaxMessageSize. In the case of an conflict, the smaller value of the two is used (see remark below). The default value is called DEFAULT_MAX_FRAME_SIZE and has a value of 16384000 bytes. ## RecursionLimit The RecursionLimit defines, how deep structures may be nested into each other. The default named DEFAULT_RECURSION_DEPTH allows for structures nested up to 64 levels deep. # Further considerations ## MaxFrameSize vs. MaxMessageSize The difference between the two options is, that MaxFrameSize exists much longer and it is used only in conjunction with TFramedTransport. In contrast, MaxMessageSize is intended to be a general device to be used with any transport or protocol. In order to combine both approaches in the most optimal way when using TFramedTransport, it is recommended that the implementation SHOULD update the remaining number of bytes to read based on the received frame size value for the current message. For calculation purposes it is important to know, that MaxFrameSize excludes the 4 bytes that hold the frame size, while MaxMessageSize is always looking at the whole data. Hence, when updating the remaining read byte count, the known message size should be set to frameSize + sizeof(i32). ## Error handling If any limit is exceeded, an error should be thrown. Additionally, it may be helpful to check larger memory allocations against the remaining max number of bytes before the allocation attempt takes place. # Q&A ## Is this a breaking change or not? There is actually two answers to that question. 1. If done right, it should not be a breaking change vis-á-vis compiling your source code that uses Thrift. 1. It may, however, be a breaking change in the way it limits the accepted overall size of messages or the accepted frame size. This behaviour is by design. If your application hits any of these limits during normal operation, it may require you to instantiate an actual TConfiguration and tweak the settings according to your needs. ## Is splitting the general transport base class into Endpoint and Layered transport base classes necessary? No, it's not. However, it turned out that this split is a great help when it comes to managing the TConfiguration instance that is passed through the stack. Having two distinct base classes for each of the different transport types not only allows to implement a shared solution for this. The added benefit is, that a clear distinction between the two transport types makes the Thrift architectural idea much more clear to "newbie" developers. ## I want to contribute an implementation of TConfiguration and I am not sure whether to pick class or struct? Short answer: Pick whatever is more efficient in the language of your choice. Technically, remember that the instance is passed down the stack and should therefore be cheap on copying. To ensure this and to make sure all pieces of the protocol / transport stack are really pointing to the same TConfiguration instance, we want to pass the instance **by reference** rather than by value. For example, in the C# language a class is a suitable choice for this, because classes are naturally reference parameters, while structs are not. thrift-0.19.0/doc/specs/thrift-binary-protocol.md0000644000000000000000000002366714452237057021753 0ustar00rootroot00000000000000Thrift Binary protocol encoding =============================== This document describes the wire encoding for RPC using the older Thrift *binary protocol*. The information here is _mostly_ based on the Java implementation in the Apache thrift library (version 0.9.1 and 0.9.3). Other implementation, however, should behave the same. For background on Thrift see the [Thrift whitepaper (pdf)](https://thrift.apache.org/static/files/thrift-20070401.pdf). # Contents * Binary protocol * Base types * Message * Struct * List and Set * Map * BNF notation used in this document # Binary protocol ## Base types ### Integer encoding In the _binary protocol_ integers are encoded with the most significant byte first (big endian byte order, aka network order). An `int8` needs 1 byte, an `int16` 2, an `int32` 4 and an `int64` needs 8 bytes. The CPP version has the option to use the binary protocol with little endian order. Little endian gives a small but noticeable performance boost because contemporary CPUs use little endian when storing integers to RAM. ### Enum encoding The generated code encodes `Enum`s by taking the ordinal value and then encoding that as an int32. ### Binary encoding Binary is sent as follows: ``` Binary protocol, binary data, 4+ bytes: +--------+--------+--------+--------+--------+...+--------+ | byte length | bytes | +--------+--------+--------+--------+--------+...+--------+ ``` Where: * `byte length` is the length of the byte array, a signed 32 bit integer encoded in network (big endian) order (must be >= 0). * `bytes` are the bytes of the byte array. ### String encoding *String*s are first encoded to UTF-8, and then send as binary. ### Double encoding Values of type `double` are first converted to an int64 according to the IEEE 754 floating-point "double format" bit layout. Most run-times provide a library to make this conversion. Both the binary protocol and the compact protocol then encode the int64 in 8 bytes in big endian order. ### Boolean encoding Values of `bool` type are first converted to an int8. True is converted to `1`, false to `0`. ### Universal unique identifier encoding Values of `uuid` type are expected as 16-byte binary in big endian (or "network") order. Byte order conversion might be necessary on certain platforms, e.g. Windows holds GUIDs in a complex record-like structure whose memory layout differs. *Note*: Since the length is fixed, no `byte length` prefix is necessary and the field is always 16 bytes long. ## Message A `Message` can be encoded in two different ways: ``` Binary protocol Message, strict encoding, 12+ bytes: +--------+--------+--------+--------+--------+--------+--------+--------+--------+...+--------+--------+--------+--------+--------+ |1vvvvvvv|vvvvvvvv|unused |00000mmm| name length | name | seq id | +--------+--------+--------+--------+--------+--------+--------+--------+--------+...+--------+--------+--------+--------+--------+ ``` Where: * `vvvvvvvvvvvvvvv` is the version, an unsigned 15 bit number fixed to `1` (in binary: `000 0000 0000 0001`). The leading bit is `1`. * `unused` is an ignored byte. * `mmm` is the message type, an unsigned 3 bit integer. The 5 leading bits must be `0` as some clients (checked for java in 0.9.1) take the whole byte. * `name length` is the byte length of the name field, a signed 32 bit integer encoded in network (big endian) order (must be >= 0). * `name` is the method name, a UTF-8 encoded string. * `seq id` is the sequence id, a signed 32 bit integer encoded in network (big endian) order. The second, older encoding (aka non-strict) is: ``` Binary protocol Message, old encoding, 9+ bytes: +--------+--------+--------+--------+--------+...+--------+--------+--------+--------+--------+--------+ | name length | name |00000mmm| seq id | +--------+--------+--------+--------+--------+...+--------+--------+--------+--------+--------+--------+ ``` Where `name length`, `name`, `mmm`, `seq id` are as above. Because `name length` must be positive (therefore the first bit is always `0`), the first bit allows the receiver to see whether the strict format or the old format is used. Therefore a server and client using the different variants of the binary protocol can transparently talk with each other. However, when strict mode is enforced, the old format is rejected. Message types are encoded with the following values: * _Call_: 1 * _Reply_: 2 * _Exception_: 3 * _Oneway_: 4 ## Struct A *Struct* is a sequence of zero or more fields, followed by a stop field. Each field starts with a field header and is followed by the encoded field value. The encoding can be summarized by the following BNF: ``` struct ::= ( field-header field-value )* stop-field field-header ::= field-type field-id ``` Because each field header contains the field-id (as defined by the Thrift IDL file), the fields can be encoded in any order. Thrift's type system is not extensible; you can only encode the primitive types and structs. Therefore is also possible to handle unknown fields while decoding; these are simply ignored. While decoding the field type can be used to determine how to decode the field value. Note that the field name is not encoded so field renames in the IDL do not affect forward and backward compatibility. The default Java implementation (Apache Thrift 0.9.1) has undefined behavior when it tries to decode a field that has another field-type than what is expected. Theoretically, this could be detected at the cost of some additional checking. Other implementation may perform this check and then either ignore the field, or return a protocol exception. A *Union* is encoded exactly the same as a struct with the additional restriction that at most 1 field may be encoded. An *Exception* is encoded exactly the same as a struct. ### Struct encoding In the binary protocol field headers and the stop field are encoded as follows: ``` Binary protocol field header and field value: +--------+--------+--------+--------+...+--------+ |tttttttt| field id | field value | +--------+--------+--------+--------+...+--------+ Binary protocol stop field: +--------+ |00000000| +--------+ ``` Where: * `tttttttt` the field-type, a signed 8 bit integer. * `field id` the field-id, a signed 16 bit integer in big endian order. * `field-value` the encoded field value. The following field-types are used: * `BOOL`, encoded as `2` * `I8`, encoded as `3` * `DOUBLE`, encoded as `4` * `I16`, encoded as `6` * `I32`, encoded as `8` * `I64`, encoded as `10` * `BINARY`, used for binary and string fields, encoded as `11` * `STRUCT`, used for structs and union fields, encoded as `12` * `MAP`, encoded as `13` * `SET`, encoded as `14` * `LIST`, encoded as `15` * `UUID`, encoded as `16` ## List and Set List and sets are encoded the same: a header indicating the size and the element-type of the elements, followed by the encoded elements. ``` Binary protocol list (5+ bytes) and elements: +--------+--------+--------+--------+--------+--------+...+--------+ |tttttttt| size | elements | +--------+--------+--------+--------+--------+--------+...+--------+ ``` Where: * `tttttttt` is the element-type, encoded as an int8 * `size` is the size, encoded as an int32, positive values only * `elements` the element values The element-type values are the same as field-types. The full list is included in the struct section above. The maximum list/set size is configurable. By default, there is no limit (meaning the limit is the maximum int32 value: 2147483647). ## Map Maps are encoded with a header indicating the size, the element-type of the keys and the element-type of the elements, followed by the encoded elements. The encoding follows this BNF: ``` map ::= key-element-type value-element-type size ( key value )* ``` ``` Binary protocol map (6+ bytes) and key value pairs: +--------+--------+--------+--------+--------+--------+--------+...+--------+ |kkkkkkkk|vvvvvvvv| size | key value pairs | +--------+--------+--------+--------+--------+--------+--------+...+--------+ ``` Where: * `kkkkkkkk` is the key element-type, encoded as an int8 * `vvvvvvvv` is the value element-type, encoded as an int8 * `size` is the size of the map, encoded as an int32, positive values only * `key value pairs` are the encoded keys and values The element-type values are the same as field-types. The full list is included in the struct section above. The maximum map size is configurable. By default there is no limit (meaning the limit is the maximum int32 value: 2147483647). # BNF notation used in this document The following BNF notation is used: * a plus `+` appended to an item represents repetition; the item is repeated 1 or more times * a star `*` appended to an item represents optional repetition; the item is repeated 0 or more times * a pipe `|` between items represents choice, the first matching item is selected * parenthesis `(` and `)` are used for grouping multiple items thrift-0.19.0/doc/specs/thrift-protocol-spec.md0000644000000000000000000000613614303740367021407 0ustar00rootroot00000000000000Thrift Protocol Structure ==================================================================== Last Modified: 2007-Jun-29 This document describes the structure of the Thrift protocol without specifying the encoding. Thus, the order of elements could in some cases be rearranged depending upon the TProtocol implementation, but this document specifies the minimum required structure. There are some "dumb" terminals like STRING and INT that take the place of an actual encoding specification. The key point to notice is that ALL messages are just one wrapped ``. Depending upon the message type, the `` can be interpreted as the argument list to a function, the return value of a function, or an exception. -------------------------------------------------------------------- ``` ::= ::= ::= STRING ::= T_CALL | T_REPLY | T_EXCEPTION | T_ONEWAY ::= I32 ::= * ::= ::= STRING ::= T_STOP ::= ::= ::= STRING ::= T_BOOL | T_BYTE | T_I8 | T_I16 | T_I32 | T_I64 | T_DOUBLE | T_STRING | T_BINARY | T_STRUCT | T_MAP | T_SET | T_LIST | T_UUID ::= I16 ::= I8 | I16 | I32 | I64 | DOUBLE | STRING | BINARY | | | ::= * ::= ::= ::= ::= I32 ::= * ::= ::= ::= I32 ::= * ::= ::= ::= I32 ``` thrift-0.19.0/doc/specs/HeaderFormat.md0000644000000000000000000000763314303740367017664 0ustar00rootroot00000000000000 Header format for the THeader.h =============================== 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 4 5 6 7 8 9 a b c d e f +----------------------------------------------------------------+ | 0| LENGTH | +----------------------------------------------------------------+ | 0| HEADER MAGIC | FLAGS | +----------------------------------------------------------------+ | SEQUENCE NUMBER | +----------------------------------------------------------------+ | 0| Header Size(/32) | ... +--------------------------------- Header is of variable size: (and starts at offset 14) +----------------------------------------------------------------+ | PROTOCOL ID (varint) | NUM TRANSFORMS (varint) | +----------------------------------------------------------------+ | TRANSFORM 0 ID (varint) | TRANSFORM 0 DATA ... +----------------------------------------------------------------+ | ... ... | +----------------------------------------------------------------+ | INFO 0 ID (varint) | INFO 0 DATA ... +----------------------------------------------------------------+ | ... ... | +----------------------------------------------------------------+ | | | PAYLOAD | | | +----------------------------------------------------------------+ The `LENGTH` field is 32 bits, and counts the remaining bytes in the packet, NOT including the length field. The header size field is 16 bits, and defines the size of the header remaining NOT including the `HEADER MAGIC`, `FLAGS`, `SEQUENCE NUMBER` and header size fields. The Header size field is in bytes/4. The transform ID's are varints. The data for each transform is defined by the transform ID in the code - no size is given in the header. If a transform ID is specified from a client and the server doesn't know about the transform ID, an error MUST be returned as we don't know how to transform the data. Conversely, data in the info headers is ignorable. This should only be things like timestamps, debugging tracing, etc. Using the header size you should be able to skip this data and read the payload safely if you don't know the info ID. Info's should be oldest supported to newest supported order, so that if we read an info ID we don't support, none of the remaining info ID's will be supported either, and we can safely skip to the payload. Info ID's and transform ID's should share the same ID space. ### PADDING: Header will be padded out to next 4-byte boundary with `0x00`. Max frame size is `0x3FFFFFFF`, which is slightly less than `HTTP_MAGIC`. This allows us to distinguish between different (older) transports. ### Transform IDs: ZLIB_TRANSFORM 0x01 - No data for this. Use zlib to (de)compress the data. HMAC_TRANSFORM 0x02 - Variable amount of mac data. One byte to specify size. Mac data is appended at the end of the packet. SNAPPY_TRANSFORM 0x03 - No data for this. Use snappy to (de)compress the data. ### Info IDs: INFO_KEYVALUE 0x01 - varint32 number of headers. - key/value pairs of varstrings (varint16 length plus no-trailing-null string). Implementations MUST NOT alter either key or value in any way. thrift-0.19.0/doc/specs/thrift-parameter-validation-proposal.md0000644000000000000000000002671114370300523024552 0ustar00rootroot00000000000000# Thrift Parameter Validation Proposal > Version 1.1 > > Dec 15, 2021 > > duanyi.aster@bytedance.com, wangtieju@bytedance.com ### 1. Abstract *** This document presents a proposed set of annotations to the Thrift IDL. The new annotations will supports parameter validation using build-in or third-party validators. The goal of this proposal is to define semantics and behavior of validation annotations, rather than to discuss their implementation. ### 2. Background *** Parameter validation is a common need for web service. In the past, we usually write our validating logics after a RPC message deserialized by thrift. This ways works flexibly enough but restrict poorly: It is dangerous that service A and service B using the same IDL have two different validating rule, which often misdirects developers. Even if we extract our validating codes to a single module, simple and repeated work (ex. `if xx.Field1 > 1 then ...`) is really disturbing. If we can use build tool to generating codes for simple and unchangeable restraint, the web service will be more robust and developers will benefits from lighter work. Compared to other IDL, the parameter validation gradually gets strong community supports like PGV ([protoc-gen-validate](https://github.com/envoyproxy/protoc-gen-validate)), benefiting from pb's strong plugin mechanism (lacking official plugin mechanism is one reason for we submit this proposal). Take a long-term view, auto-generated parameter validation may be a step towards code-less web service. ### 3. Proposal *** This proposal includes three part: Validate Annotation Semantics, Validate Rule and Validate Feedback. The first declare how to write a validate annotation, the middle explain how every annotation should behave, the last introduces a mechanism of validating feedback. #### 3.1 Validate Annotation Semantics This semantics uses same rule of [Thrift IDL](https://thrift.apache.org/docs/idl). The validate option only works on struct fields, thus we must start from Field semantics part. - Field ```peg Field <- FieldID? FieldReq? FieldType Identifier ('=' ConstValue)? ValidateAnnotations? ListSeparator? ``` - ValidateAnnotations ```peg ValidateAnnotations <- '(' ValidateRule+ ListSeparator? ')' ``` - ValidateRule ```peg ValidateRule <- ('validate' | 'vt') Validator+ = '"' ValidatingValue? '"' ``` - Validator Build-in validating logics. See [Supported Validator](#321-supported-validator) part. ```peg Validator <- '.' Identifier ``` - ValidatingValue ```peg ValidatingValue <- (ToolFunction '(' )? Arguments ')'? ``` - ToolFunction Build-in or user-defined tool functions. See [Tool Function](#325-tool-function) part. ```peg ToolFunction <- '@' Identifier ``` - Arguments ```peg Arguments <- (DynamicValue ListSeparator?)* ``` - DynamicValue ```peg DynamicValue <- ConstValue | FieldReference ``` - FieldReference See [Field Reference](#324-field-reference) part. ```apache FieldReference <- '$' ReferPath ReferPath <- FieldName? ( ('['IntConstant']') | ('.'Identifier) )? ``` - All other semantics keep same with [standard definition](https://thrift.apache.org/docs/idl) ### 3.2 Validate Rule The validate rule is works as a Boolean Expression, and Validator is core logic for one validate rule. Every Validator works like an Operator, calculating the Validating Value and Field Value, and then compare. For example, `gt` (greater than) will compare the right Validating Value with value of the field it belongs to, and return `true` if field value is greater than value or `false` if field value is not. We appoint that: Only if the validate rule returns true, the validated parameter is valid. If there are several validate rules defined in annotations of a field, Validator will take the logical relation as "and". Simply put, commas in annotations can be treated as "and". #### 3.2.1 Supported Validator Below lists the support validators. Value type means the type of validating value, field type means type of validated field. | validator | behavior | value type | field type | secondary validator | | ------------ | ------------------------------------- | ------------------------------------ | ---------------------- | ------------------- | | const | must be constant | string, bool | same with value | - | | defined_only | must be defined value | enum | enum | - | | not_nil | must not be empty | "true" | any | - | | skip | skip validate | "true" | any | - | | eq | equals to (`==`) | i8, i16, i32, i64, f64, string, bool | same with value | - | | ne | not equals to (`!=`) | i8, i16, i32, i64, f64, string, bool | same with value | - | | lt | less than (`<`) | i8, i16, i32, i64, f64 | same with value | - | | le | less equal (`<=`) | i8, i16, i32, i64, f64 | same with value | - | | gt | greater than (`>`) | i8, i16, i32, i64, f64 | same with value | - | | ge | greater equal (`>=`) | i8, i16, i32, i64, f64 | same with value | - | | in | within given container | i8, i16, i32, i64, f64, enum | same with value | - | | not_in | not within given container | i8, i16, i32, i64, f64, enum | same with value | - | | elem | field's element constraint | any | list, set | support | | key | field's element key constraint | any | map | support | | value | field's element value constraint | any | map | support | | min_size | minimal length | i8, i16, i32, i64 | string, list, set, map | - | | max_size | maximal length | i8, i16, i32, i64 | string, list, set, map | - | | prefix | field prefix must be (case-sensitive) | string | string | - | | suffix | suffix must be (case-sensitive) | string | string | - | | contains | must contain (case-sensitive) | string | string | - | | not_contains | must not contain (case-sensitive) | string | string | - | | pattern | basic regular expression | string | string | - | - Basic Regular Expression (BRE), the syntax of BRE can be found in [manual](https://www.gnu.org/software/sed/manual/html_node/BRE-syntax.html) of GNU sed. - Secondary validator (`elem`, `key` and `value`) is a successive validator, usually used at container-type field. See below Set/List/Map examples. - Add suffix "_escape" to validators to prevent value of rule conflicting with tool function. For example, you can use `"vt.eq_escape" = "@len(A)"` to match literal `@len(A)`. #### 3.2.2 IDL example - Number ``` struct NumericDemo{ 1: double Value (validator.ge = "1000.1", validator.le = "10000.1") 2: i8 Type (validator.in = "[1, 2, 4]") } ``` - String/Binary ``` struct StringDemo{ 1: string Uninitialized (vt.const = "abc") 2: string Name (vt.min_size = "6", vt.max_size = "12") 3: string SomeStuffs (vt.pattern = "[0-9A-Za-z]+") 4: string DebugInfo (vt.prefix = "[Debug]") 5: string ErrorMessage (vt.contains = "Error") } ``` - Bool ``` struct BoolDemo { 1: bool AMD (vt.const = "true") } ``` - Enum ``` enum Type { Bool I8 I16 I32 I64 String Struct List Set Map } struct EnumDemo { 1: Type AddressType (vt.in = "[String]") 2: Type ValueType (vt.defined_only = "true") } ``` - Set/List ``` struct SetListDemo { 1: list Persons (vt.min_size = "5", vt.max_size = "10") 2: set HealthPoints (vt.elem.gt = "0") } ``` - Map ``` struct MapDemo { 1: map IdName (vt.min_size = "5", vt.max_size = "10") 2: map Some (vt.key.gt = "0", vt.value.lt = "1000") } ``` #### 3.2.3 Arguments Arguments can by static literals or dynamic variables. If one literal expression contains any Field Reference or Tool Function, it becomes dynamic variables. Every dynamic variables finally get calculated and finally become a Thrift Constant Value. #### 3.2.4 Field Reference Field Reference is used to refer to another field's value in Validating Value, therefore user can compare more than one field. The referenced field must be within same struct. Identifier must be the field name referred. - Field Reference Rule 1. `$x` represents a variable named x, and its scope is within current struct 2. `$` indicates the current field in which the validator is located 3. `$x['k']` indicates a reference to the key k of variable x (which must be map) 4. `$x[i]` indicates a reference to the i + 1 element of variable x (which must be list) - Example ``` struct FieldReferenceExample { 1: string A (vt.eq = "$B") //field A must equal to field B 2: list C } ``` #### 3.2.5 Tool Function Tool Function is use to enhance the operating of Validating Value. For example, if we want to ensure one field is larger than the length of string field A, we can use `len()` function: `vt.gt = "@len($A)"`. The arguments can be either literals or variables, and no size limit. However, we won't suggest any build-in function here, because the category is too big and always language-related. Instead, we only propose one mechanism for thrift developers to extends their implementation according to used language. Supported functions: | function | behavior | arguments | results | supported language | | -------- | ----------------------- | ----------------------------------- | -------- | ------------------ | | len | the length of the field | 1: string, binary, list, set or map | 1. int64 | go | ### 3.3 Feedback The generated validating codes should be included in struct's `Validate() TApplicationException` method. If all validate rule declared by one struct get passed, the struct's `Validate() TApplicationException` method returns nil (or just returns without exception, depending on specific language implementation); Otherwise it returns `TApplicationException` and report feedback message indicating failure reason. Due to language function implementations are different, we won't constrain the interface of feedback messages. However, by practice we suggest developers to give below three detail information: - The position where first validating failure happens. - The validator who reports the failure. - The red-handed field value and validating value when the failure happens thrift-0.19.0/doc/specs/thrift-compact-protocol.md0000644000000000000000000002761414303740367022107 0ustar00rootroot00000000000000Thrift Compact protocol encoding ================================ This documents describes the wire encoding for RPC using the Thrift *compact protocol*. The information here is _mostly_ based on the Java implementation in the Apache thrift library (version 0.9.1) and [THRIFT-110 A more compact format](https://issues.apache.org/jira/browse/THRIFT-110). Other implementation however, should behave the same. For background on Thrift see the [Thrift whitepaper (pdf)](https://thrift.apache.org/static/files/thrift-20070401.pdf). # Contents * Compact protocol * Base types * Message * Struct * List and Set * Map * BNF notation used in this document # Compact protocol ## Base types ### Integer encoding The _compact protocol_ uses multiple encodings for ints: the _zigzag int_, and the _var int_. Values of type `int32` and `int64` are first transformed to a *zigzag int*. A zigzag int folds positive and negative numbers into the positive number space. When we read 0, 1, 2, 3, 4 or 5 from the wire, this is translated to 0, -1, 1, -2 or 2 respectively. Here are the (Scala) formulas to convert from int32/int64 to a zigzag int and back: ```scala def intToZigZag(n: Int): Int = (n << 1) ^ (n >> 31) def zigzagToInt(n: Int): Int = (n >>> 1) ^ - (n & 1) def longToZigZag(n: Long): Long = (n << 1) ^ (n >> 63) def zigzagToLong(n: Long): Long = (n >>> 1) ^ - (n & 1) ``` The zigzag int is then encoded as a *var int*, also known as *Unsigned LEB128*. Var ints take 1 to 5 bytes (int32) or 1 to 10 bytes (int64). The process consists in taking a Big Endian unsigned integer, left-padding the bit-string to make it a multiple of 7 bits, splitting it into 7-bit groups, prefixing the most-significant 7-bit group with the 0 bit, prefixing the remaining 7-bit groups with the 1 bit and encoding the resulting bit-string in Little Endian. For example, the integer 50399 is encoded as follows: ``` 50399 = 1100 0100 1101 1111 (Big Endian representation) = 00000 1100 0100 1101 1111 (Left-padding) = 0000011 0001001 1011111 (7-bit groups) = 00000011 10001001 11011111 (Most-significant bit prefixes) = 11011111 10001001 00000011 (Little Endian representation) = 0xDF 0x89 0x03 ``` Var ints are sometimes used directly inside the compact protocol to represent positive numbers. To encode an `int16` as zigzag int, it is first converted to an `int32` and then encoded as such. The type `int8` simply uses a single byte as in the binary protocol. ### Enum encoding The generated code encodes `Enum`s by taking the ordinal value and then encoding that as an int32. ### Binary encoding Binary is sent as follows: ``` Binary protocol, binary data, 1+ bytes: +--------+...+--------+--------+...+--------+ | byte length | bytes | +--------+...+--------+--------+...+--------+ ``` Where: * `byte length` is the length of the byte array, using var int encoding (must be >= 0). * `bytes` are the bytes of the byte array. ### String encoding *String*s are first encoded to UTF-8, and then send as binary. They do not include a NUL delimiter. ### Double encoding Values of type `double` are first converted to an int64 according to the IEEE 754 floating-point "double format" bit layout. Most run-times provide a library to make this conversion. But while the binary protocol encodes the int64 in 8 bytes in big endian order, the compact protocol encodes it in little endian order - this is due to an early implementation bug that finally became the de-facto standard. ### Boolean encoding Booleans are encoded differently depending on whether it is a field value (in a struct) or an element value (in a set, list or map). Field values are encoded directly in the field header. Element values of type `bool` are sent as an int8; true as `1` and false as `0`. ### Universal unique identifier encoding Values of `uuid` type are expected as 16-byte binary in big endian (or "network") order. Byte order conversion might be necessary on certain platforms, e.g. Windows holds GUIDs in a complex record-like structure whose memory layout differs. *Note*: Since the length is fixed, no `byte length` prefix is necessary and the field is always 16 bytes long. ## Message A `Message` on the wire looks as follows: ``` Compact protocol Message (4+ bytes): +--------+--------+--------+...+--------+--------+...+--------+--------+...+--------+ |pppppppp|mmmvvvvv| seq id | name length | name | +--------+--------+--------+...+--------+--------+...+--------+--------+...+--------+ ``` Where: * `pppppppp` is the protocol id, fixed to `1000 0010`, 0x82. * `mmm` is the message type, an unsigned 3 bit integer. * `vvvvv` is the version, an unsigned 5 bit integer, fixed to `00001`. * `seq id` is the sequence id, a signed 32 bit integer encoded as a var int. * `name length` is the byte length of the name field, a signed 32 bit integer encoded as a var int (must be >= 0). * `name` is the method name to invoke, a UTF-8 encoded string. Message types are encoded with the following values: * _Call_: 1 * _Reply_: 2 * _Exception_: 3 * _Oneway_: 4 ### Struct A *Struct* is a sequence of zero or more fields, followed by a stop field. Each field starts with a field header and is followed by the encoded field value. The encoding can be summarized by the following BNF: ``` struct ::= ( field-header field-value )* stop-field field-header ::= field-type field-id ``` Because each field header contains the field-id (as defined by the Thrift IDL file), the fields can be encoded in any order. Thrift's type system is not extensible; you can only encode the primitive types and structs. Therefore is also possible to handle unknown fields while decoding; these are simply ignored. While decoding the field type can be used to determine how to decode the field value. Note that the field name is not encoded so field renames in the IDL do not affect forward and backward compatibility. The default Java implementation (Apache Thrift 0.9.1) has undefined behavior when it tries to decode a field that has another field-type than what is expected. Theoretically this could be detected at the cost of some additional checking. Other implementation may perform this check and then either ignore the field, or return a protocol exception. A *Union* is encoded exactly the same as a struct with the additional restriction that at most 1 field may be encoded. An *Exception* is encoded exactly the same as a struct. ### Struct encoding ``` Compact protocol field header (short form) and field value: +--------+--------+...+--------+ |ddddtttt| field value | +--------+--------+...+--------+ Compact protocol field header (1 to 3 bytes, long form) and field value: +--------+--------+...+--------+--------+...+--------+ |0000tttt| field id | field value | +--------+--------+...+--------+--------+...+--------+ Compact protocol stop field: +--------+ |00000000| +--------+ ``` Where: * `dddd` is the field id delta, an unsigned 4 bits integer, strictly positive. * `tttt` is field-type id, an unsigned 4 bit integer. * `field id` the field id, a signed 16 bit integer encoded as zigzag int. * `field-value` the encoded field value. The field id delta can be computed by `current-field-id - previous-field-id`, or just `current-field-id` if this is the first of the struct. The short form should be used when the field id delta is in the range 1 - 15 (inclusive). The following field-types can be encoded: * `BOOLEAN_TRUE`, encoded as `1` * `BOOLEAN_FALSE`, encoded as `2` * `I8`, encoded as `3` * `I16`, encoded as `4` * `I32`, encoded as `5` * `I64`, encoded as `6` * `DOUBLE`, encoded as `7` * `BINARY`, used for binary and string fields, encoded as `8` * `LIST`, encoded as `9` * `SET`, encoded as `10` * `MAP`, encoded as `11` * `STRUCT`, used for both structs and union fields, encoded as `12` * `UUID`, encoded as `13` Note that because there are 2 specific field types for the boolean values, the encoding of a boolean field value has no length (0 bytes). ## List and Set List and sets are encoded the same: a header indicating the size and the element-type of the elements, followed by the encoded elements. ``` Compact protocol list header (1 byte, short form) and elements: +--------+--------+...+--------+ |sssstttt| elements | +--------+--------+...+--------+ Compact protocol list header (2+ bytes, long form) and elements: +--------+--------+...+--------+--------+...+--------+ |1111tttt| size | elements | +--------+--------+...+--------+--------+...+--------+ ``` Where: * `ssss` is the size, 4 bit unsigned int, values `0` - `14` * `tttt` is the element-type, a 4 bit unsigned int * `size` is the size, a var int (int32), positive values `15` or higher * `elements` are the encoded elements The short form should be used when the length is in the range 0 - 14 (inclusive). The following element-types are used (see note below): * `BOOL`, encoded as `2` * `I8`, encoded as `3` * `I16`, encoded as `4` * `I32`, encoded as `5` * `I64`, encoded as `6` * `DOUBLE`, encoded as `7` * `BINARY`, used for binary and string fields, encoded as `8` * `LIST`, encoded as `9` * `SET`, encoded as `10` * `MAP`, encoded as `11` * `STRUCT`, used for structs and union fields, encoded as `12` * `UUID`, encoded as `13` *Note*: Although field-types and element-types lists are currently very similar, there is _no guarantee_ that this will remain true after new types are added. The maximum list/set size is configurable. By default there is no limit (meaning the limit is the maximum int32 value: 2147483647). ## Map Maps are encoded with a header indicating the size, the type of the keys and the element-type of the elements, followed by the encoded elements. The encoding follows this BNF: ``` map ::= empty-map | non-empty-map empty-map ::= `0` non-empty-map ::= size key-element-type value-element-type (key value)+ ``` ``` Compact protocol map header (1 byte, empty map): +--------+ |00000000| +--------+ Compact protocol map header (2+ bytes, non empty map) and key value pairs: +--------+...+--------+--------+--------+...+--------+ | size |kkkkvvvv| key value pairs | +--------+...+--------+--------+--------+...+--------+ ``` Where: * `size` is the size, a var int (int32), strictly positive values * `kkkk` is the key element-type, a 4 bit unsigned int * `vvvv` is the value element-type, a 4 bit unsigned int * `key value pairs` are the encoded keys and values The element-types are the same as for lists. The full list is included in the 'List and set' section. The maximum map size is configurable. By default there is no limit (meaning the limit is the maximum int32 value: 2147483647). # BNF notation used in this document The following BNF notation is used: * a plus `+` appended to an item represents repetition; the item is repeated 1 or more times * a star `*` appended to an item represents optional repetition; the item is repeated 0 or more times * a pipe `|` between items represents choice, the first matching item is selected * parenthesis `(` and `)` are used for grouping multiple items thrift-0.19.0/doc/specs/thrift.tex0000644000000000000000000013710314303740367017017 0ustar00rootroot00000000000000%----------------------------------------------------------------------------- % % Thrift whitepaper % % Name: thrift.tex % % Authors: Mark Slee (mcslee@facebook.com) % % Created: 05 March 2007 % % You will need a copy of sigplanconf.cls to format this document. % It is available at . % %----------------------------------------------------------------------------- \documentclass[nocopyrightspace,blockstyle]{sigplanconf} \usepackage{amssymb} \usepackage{amsfonts} \usepackage{amsmath} \usepackage{url} \begin{document} % \conferenceinfo{WXYZ '05}{date, City.} % \copyrightyear{2007} % \copyrightdata{[to be supplied]} % \titlebanner{banner above paper title} % These are ignored unless % \preprintfooter{short description of paper} % 'preprint' option specified. \title{Thrift: Scalable Cross-Language Services Implementation} \subtitle{} \authorinfo{Mark Slee, Aditya Agarwal and Marc Kwiatkowski} {Facebook, 156 University Ave, Palo Alto, CA} {\{mcslee,aditya,marc\}@facebook.com} \maketitle \begin{abstract} Thrift is a software library and set of code-generation tools developed at Facebook to expedite development and implementation of efficient and scalable backend services. Its primary goal is to enable efficient and reliable communication across programming languages by abstracting the portions of each language that tend to require the most customization into a common library that is implemented in each language. Specifically, Thrift allows developers to define datatypes and service interfaces in a single language-neutral file and generate all the necessary code to build RPC clients and servers. This paper details the motivations and design choices we made in Thrift, as well as some of the more interesting implementation details. It is not intended to be taken as research, but rather it is an exposition on what we did and why. \end{abstract} % \category{D.3.3}{Programming Languages}{Language constructs and features} %\terms %Languages, serialization, remote procedure call %\keywords %Data description language, interface definition language, remote procedure call \section{Introduction} As Facebook's traffic and network structure have scaled, the resource demands of many operations on the site (i.e. search, ad selection and delivery, event logging) have presented technical requirements drastically outside the scope of the LAMP framework. In our implementation of these services, various programming languages have been selected to optimize for the right combination of performance, ease and speed of development, availability of existing libraries, etc. By and large, Facebook's engineering culture has tended towards choosing the best tools and implementations available over standardizing on any one programming language and begrudgingly accepting its inherent limitations. Given this design choice, we were presented with the challenge of building a transparent, high-performance bridge across many programming languages. We found that most available solutions were either too limited, did not offer sufficient datatype freedom, or suffered from subpar performance. \footnote{See Appendix A for a discussion of alternative systems.} The solution that we have implemented combines a language-neutral software stack implemented across numerous programming languages and an associated code generation engine that transforms a simple interface and data definition language into client and server remote procedure call libraries. Choosing static code generation over a dynamic system allows us to create validated code that can be run without the need for any advanced introspective run-time type checking. It is also designed to be as simple as possible for the developer, who can typically define all the necessary data structures and interfaces for a complex service in a single short file. Surprised that a robust open solution to these relatively common problems did not yet exist, we committed early on to making the Thrift implementation open source. In evaluating the challenges of cross-language interaction in a networked environment, some key components were identified: \textit{Types.} A common type system must exist across programming languages without requiring that the application developer use custom Thrift datatypes or write their own serialization code. That is, a C++ programmer should be able to transparently exchange a strongly typed STL map for a dynamic Python dictionary. Neither programmer should be forced to write any code below the application layer to achieve this. Section 2 details the Thrift type system. \textit{Transport.} Each language must have a common interface to bidirectional raw data transport. The specifics of how a given transport is implemented should not matter to the service developer. The same application code should be able to run against TCP stream sockets, raw data in memory, or files on disk. Section 3 details the Thrift Transport layer. \textit{Protocol.} Datatypes must have some way of using the Transport layer to encode and decode themselves. Again, the application developer need not be concerned by this layer. Whether the service uses an XML or binary protocol is immaterial to the application code. All that matters is that the data can be read and written in a consistent, deterministic matter. Section 4 details the Thrift Protocol layer. \textit{Versioning.} For robust services, the involved datatypes must provide a mechanism for versioning themselves. Specifically, it should be possible to add or remove fields in an object or alter the argument list of a function without any interruption in service (or, worse yet, nasty segmentation faults). Section 5 details Thrift's versioning system. \textit{Processors.} Finally, we generate code capable of processing data streams to accomplish remote procedure calls. Section 6 details the generated code and TProcessor paradigm. Section 7 discusses implementation details, and Section 8 describes our conclusions. \section{Types} The goal of the Thrift type system is to enable programmers to develop using completely natively defined types, no matter what programming language they use. By design, the Thrift type system does not introduce any special dynamic types or wrapper objects. It also does not require that the developer write any code for object serialization or transport. The Thrift IDL (Interface Definition Language) file is logically a way for developers to annotate their data structures with the minimal amount of extra information necessary to tell a code generator how to safely transport the objects across languages. \subsection{Base Types} The type system rests upon a few base types. In considering which types to support, we aimed for clarity and simplicity over abundance, focusing on the key types available in all programming languages, omitting any niche types available only in specific languages. The base types supported by Thrift are: \begin{itemize} \item \texttt{bool} A boolean value, true or false \item \texttt{byte} A signed byte \item \texttt{i16} A 16-bit signed integer \item \texttt{i32} A 32-bit signed integer \item \texttt{i64} A 64-bit signed integer \item \texttt{double} A 64-bit floating point number \item \texttt{string} An encoding-agnostic text or binary string \item \texttt{binary} A byte array representation for blobs \end{itemize} Of particular note is the absence of unsigned integer types. Because these types have no direct translation to native primitive types in many languages, the advantages they afford are lost. Further, there is no way to prevent the application developer in a language like Python from assigning a negative value to an integer variable, leading to unpredictable behavior. From a design standpoint, we observed that unsigned integers were very rarely, if ever, used for arithmetic purposes, but in practice were much more often used as keys or identifiers. In this case, the sign is irrelevant. Signed integers serve this same purpose and can be safely cast to their unsigned counterparts (most commonly in C++) when absolutely necessary. \subsection{Structs} A Thrift struct defines a common object to be used across languages. A struct is essentially equivalent to a class in object oriented programming languages. A struct has a set of strongly typed fields, each with a unique name identifier. The basic syntax for defining a Thrift struct looks very similar to a C struct definition. Fields may be annotated with an integer field identifier (unique to the scope of that struct) and optional default values. Field identifiers will be automatically assigned if omitted, though they are strongly encouraged for versioning reasons discussed later. \subsection{Containers} Thrift containers are strongly typed containers that map to the most commonly used containers in common programming languages. They are annotated using the C++ template (or Java Generics) style. There are three types available: \begin{itemize} \item \texttt{list} An ordered list of elements. Translates directly into an STL \texttt{vector}, Java \texttt{ArrayList}, or native array in scripting languages. May contain duplicates. \item \texttt{set} An unordered set of unique elements. Translates into an STL \texttt{set}, Java \texttt{HashSet}, \texttt{set} in Python, or native dictionary in PHP/Ruby. \item \texttt{map} A map of strictly unique keys to values Translates into an STL \texttt{map}, Java \texttt{HashMap}, PHP associative array, or Python/Ruby dictionary. \end{itemize} While defaults are provided, the type mappings are not explicitly fixed. Custom code generator directives have been added to substitute custom types in destination languages (i.e. \texttt{hash\_map} or Google's sparse hash map can be used in C++). The only requirement is that the custom types support all the necessary iteration primitives. Container elements may be of any valid Thrift type, including other containers or structs. \begin{verbatim} struct Example { 1:i32 number=10, 2:i64 bigNumber, 3:double decimals, 4:string name="thrifty" }\end{verbatim} In the target language, each definition generates a type with two methods, \texttt{read} and \texttt{write}, which perform serialization and transport of the objects using a Thrift TProtocol object. \subsection{Exceptions} Exceptions are syntactically and functionally equivalent to structs except that they are declared using the \texttt{exception} keyword instead of the \texttt{struct} keyword. The generated objects inherit from an exception base class as appropriate in each target programming language, in order to seamlessly integrate with native exception handling in any given language. Again, the design emphasis is on making the code familiar to the application developer. \subsection{Services} Services are defined using Thrift types. Definition of a service is semantically equivalent to defining an interface (or a pure virtual abstract class) in object oriented programming. The Thrift compiler generates fully functional client and server stubs that implement the interface. Services are defined as follows: \begin{verbatim} service { () [throws ()] ... }\end{verbatim} An example: \begin{verbatim} service StringCache { void set(1:i32 key, 2:string value), string get(1:i32 key) throws (1:KeyNotFound knf), void delete(1:i32 key) } \end{verbatim} Note that \texttt{void} is a valid type for a function return, in addition to all other defined Thrift types. Additionally, an \texttt{async} modifier keyword may be added to a \texttt{void} function, which will generate code that does not wait for a response from the server. Note that a pure \texttt{void} function will return a response to the client which guarantees that the operation has completed on the server side. With \texttt{async} method calls the client will only be guaranteed that the request succeeded at the transport layer. (In many transport scenarios this is inherently unreliable due to the Byzantine Generals' Problem. Therefore, application developers should take care only to use the async optimization in cases where dropped method calls are acceptable or the transport is known to be reliable.) Also of note is the fact that argument lists and exception lists for functions are implemented as Thrift structs. All three constructs are identical in both notation and behavior. \section{Transport} The transport layer is used by the generated code to facilitate data transfer. \subsection{Interface} A key design choice in the implementation of Thrift was to decouple the transport layer from the code generation layer. Though Thrift is typically used on top of the TCP/IP stack with streaming sockets as the base layer of communication, there was no compelling reason to build that constraint into the system. The performance tradeoff incurred by an abstracted I/O layer (roughly one virtual method lookup / function call per operation) was immaterial compared to the cost of actual I/O operations (typically invoking system calls). Fundamentally, generated Thrift code only needs to know how to read and write data. The origin and destination of the data are irrelevant; it may be a socket, a segment of shared memory, or a file on the local disk. The Thrift transport interface supports the following methods: \begin{itemize} \item \texttt{open} Opens the transport \item \texttt{close} Closes the transport \item \texttt{isOpen} Indicates whether the transport is open \item \texttt{read} Reads from the transport \item \texttt{write} Writes to the transport \item \texttt{flush} Forces any pending writes \end{itemize} There are a few additional methods not documented here which are used to aid in batching reads and optionally signaling the completion of a read or write operation from the generated code. In addition to the above \texttt{TTransport} interface, there is a\\ \texttt{TServerTransport} interface used to accept or create primitive transport objects. Its interface is as follows: \begin{itemize} \item \texttt{open} Opens the transport \item \texttt{listen} Begins listening for connections \item \texttt{accept} Returns a new client transport \item \texttt{close} Closes the transport \end{itemize} \subsection{Implementation} The transport interface is designed for simple implementation in any programming language. New transport mechanisms can be easily defined as needed by application developers. \subsubsection{TSocket} The \texttt{TSocket} class is implemented across all target languages. It provides a common, simple interface to a TCP/IP stream socket. \subsubsection{TFileTransport} The \texttt{TFileTransport} is an abstraction of an on-disk file to a data stream. It can be used to write out a set of incoming Thrift requests to a file on disk. The on-disk data can then be replayed from the log, either for post-processing or for reproduction and/or simulation of past events. \subsubsection{Utilities} The Transport interface is designed to support easy extension using common OOP techniques, such as composition. Some simple utilities include the \texttt{TBufferedTransport}, which buffers the writes and reads on an underlying transport, the \texttt{TFramedTransport}, which transmits data with frame size headers for chunking optimization or nonblocking operation, and the \texttt{TMemoryBuffer}, which allows reading and writing directly from the heap or stack memory owned by the process. \section{Protocol} A second major abstraction in Thrift is the separation of data structure from transport representation. Thrift enforces a certain messaging structure when transporting data, but it is agnostic to the protocol encoding in use. That is, it does not matter whether data is encoded as XML, human-readable ASCII, or a dense binary format as long as the data supports a fixed set of operations that allow it to be deterministically read and written by generated code. \subsection{Interface} The Thrift Protocol interface is very straightforward. It fundamentally supports two things: 1) bidirectional sequenced messaging, and 2) encoding of base types, containers, and structs. \begin{verbatim} writeMessageBegin(name, type, seq) writeMessageEnd() writeStructBegin(name) writeStructEnd() writeFieldBegin(name, type, id) writeFieldEnd() writeFieldStop() writeMapBegin(ktype, vtype, size) writeMapEnd() writeListBegin(etype, size) writeListEnd() writeSetBegin(etype, size) writeSetEnd() writeBool(bool) writeByte(byte) writeI16(i16) writeI32(i32) writeI64(i64) writeDouble(double) writeString(string) name, type, seq = readMessageBegin() readMessageEnd() name = readStructBegin() readStructEnd() name, type, id = readFieldBegin() readFieldEnd() k, v, size = readMapBegin() readMapEnd() etype, size = readListBegin() readListEnd() etype, size = readSetBegin() readSetEnd() bool = readBool() byte = readByte() i16 = readI16() i32 = readI32() i64 = readI64() double = readDouble() string = readString() \end{verbatim} Note that every \texttt{write} function has exactly one \texttt{read} counterpart, with the exception of \texttt{writeFieldStop()}. This is a special method that signals the end of a struct. The procedure for reading a struct is to \texttt{readFieldBegin()} until the stop field is encountered, and then to \texttt{readStructEnd()}. The generated code relies upon this call sequence to ensure that everything written by a protocol encoder can be read by a matching protocol decoder. Further note that this set of functions is by design more robust than necessary. For example, \texttt{writeStructEnd()} is not strictly necessary, as the end of a struct may be implied by the stop field. This method is a convenience for verbose protocols in which it is cleaner to separate these calls (e.g. a closing \texttt{} tag in XML). \subsection{Structure} Thrift structures are designed to support encoding into a streaming protocol. The implementation should never need to frame or compute the entire data length of a structure prior to encoding it. This is critical to performance in many scenarios. Consider a long list of relatively large strings. If the protocol interface required reading or writing a list to be an atomic operation, then the implementation would need to perform a linear pass over the entire list before encoding any data. However, if the list can be written as iteration is performed, the corresponding read may begin in parallel, theoretically offering an end-to-end speedup of $(kN - C)$, where $N$ is the size of the list, $k$ the cost factor associated with serializing a single element, and $C$ is fixed offset for the delay between data being written and becoming available to read. Similarly, structs do not encode their data lengths a priori. Instead, they are encoded as a sequence of fields, with each field having a type specifier and a unique field identifier. Note that the inclusion of type specifiers allows the protocol to be safely parsed and decoded without any generated code or access to the original IDL file. Structs are terminated by a field header with a special \texttt{STOP} type. Because all the basic types can be read deterministically, all structs (even those containing other structs) can be read deterministically. The Thrift protocol is self-delimiting without any framing and regardless of the encoding format. In situations where streaming is unnecessary or framing is advantageous, it can be very simply added into the transport layer, using the \texttt{TFramedTransport} abstraction. \subsection{Implementation} Facebook has implemented and deployed a space-efficient binary protocol which is used by most backend services. Essentially, it writes all data in a flat binary format. Integer types are converted to network byte order, strings are prepended with their byte length, and all message and field headers are written using the primitive integer serialization constructs. String names for fields are omitted - when using generated code, field identifiers are sufficient. We decided against some extreme storage optimizations (i.e. packing small integers into ASCII or using a 7-bit continuation format) for the sake of simplicity and clarity in the code. These alterations can easily be made if and when we encounter a performance-critical use case that demands them. \section{Versioning} Thrift is robust in the face of versioning and data definition changes. This is critical to enable staged rollouts of changes to deployed services. The system must be able to support reading of old data from log files, as well as requests from out-of-date clients to new servers, and vice versa. \subsection{Field Identifiers} Versioning in Thrift is implemented via field identifiers. The field header for every member of a struct in Thrift is encoded with a unique field identifier. The combination of this field identifier and its type specifier is used to uniquely identify the field. The Thrift definition language supports automatic assignment of field identifiers, but it is good programming practice to always explicitly specify field identifiers. Identifiers are specified as follows: \begin{verbatim} struct Example { 1:i32 number=10, 2:i64 bigNumber, 3:double decimals, 4:string name="thrifty" }\end{verbatim} To avoid conflicts between manually and automatically assigned identifiers, fields with identifiers omitted are assigned identifiers decrementing from -1, and the language only supports the manual assignment of positive identifiers. When data is being deserialized, the generated code can use these identifiers to properly identify the field and determine whether it aligns with a field in its definition file. If a field identifier is not recognized, the generated code can use the type specifier to skip the unknown field without any error. Again, this is possible due to the fact that all datatypes are self delimiting. Field identifiers can (and should) also be specified in function argument lists. In fact, argument lists are not only represented as structs on the backend, but actually share the same code in the compiler frontend. This allows for version-safe modification of method parameters \begin{verbatim} service StringCache { void set(1:i32 key, 2:string value), string get(1:i32 key) throws (1:KeyNotFound knf), void delete(1:i32 key) } \end{verbatim} The syntax for specifying field identifiers was chosen to echo their structure. Structs can be thought of as a dictionary where the identifiers are keys, and the values are strongly-typed named fields. Field identifiers internally use the \texttt{i16} Thrift type. Note, however, that the \texttt{TProtocol} abstraction may encode identifiers in any format. \subsection{Isset} When an unexpected field is encountered, it can be safely ignored and discarded. When an expected field is not found, there must be some way to signal to the developer that it was not present. This is implemented via an inner \texttt{isset} structure inside the defined objects. (Isset functionality is implicit with a \texttt{null} value in PHP, \texttt{None} in Python and \texttt{nil} in Ruby.) Essentially, the inner \texttt{isset} object of each Thrift struct contains a boolean value for each field which denotes whether or not that field is present in the struct. When a reader receives a struct, it should check for a field being set before operating directly on it. \begin{verbatim} class Example { public: Example() : number(10), bigNumber(0), decimals(0), name("thrifty") {} int32_t number; int64_t bigNumber; double decimals; std::string name; struct __isset { __isset() : number(false), bigNumber(false), decimals(false), name(false) {} bool number; bool bigNumber; bool decimals; bool name; } __isset; ... } \end{verbatim} \subsection{Case Analysis} There are four cases in which version mismatches may occur. \begin{enumerate} \item \textit{Added field, old client, new server.} In this case, the old client does not send the new field. The new server recognizes that the field is not set, and implements default behavior for out-of-date requests. \item \textit{Removed field, old client, new server.} In this case, the old client sends the removed field. The new server simply ignores it. \item \textit{Added field, new client, old server.} The new client sends a field that the old server does not recognize. The old server simply ignores it and processes as normal. \item \textit{Removed field, new client, old server.} This is the most dangerous case, as the old server is unlikely to have suitable default behavior implemented for the missing field. It is recommended that in this situation the new server be rolled out prior to the new clients. \end{enumerate} \subsection{Protocol/Transport Versioning} The \texttt{TProtocol} abstractions are also designed to give protocol implementations the freedom to version themselves in whatever manner they see fit. Specifically, any protocol implementation is free to send whatever it likes in the \texttt{writeMessageBegin()} call. It is entirely up to the implementor how to handle versioning at the protocol level. The key point is that protocol encoding changes are safely isolated from interface definition version changes. Note that the exact same is true of the \texttt{TTransport} interface. For example, if we wished to add some new checksumming or error detection to the \texttt{TFileTransport}, we could simply add a version header into the data it writes to the file in such a way that it would still accept old log files without the given header. \section{RPC Implementation} \subsection{TProcessor} The last core interface in the Thrift design is the \texttt{TProcessor}, perhaps the most simple of the constructs. The interface is as follows: \begin{verbatim} interface TProcessor { bool process(TProtocol in, TProtocol out) throws TException } \end{verbatim} The key design idea here is that the complex systems we build can fundamentally be broken down into agents or services that operate on inputs and outputs. In most cases, there is actually just one input and output (an RPC client) that needs handling. \subsection{Generated Code} When a service is defined, we generate a \texttt{TProcessor} instance capable of handling RPC requests to that service, using a few helpers. The fundamental structure (illustrated in pseudo-C++) is as follows: \begin{verbatim} Service.thrift => Service.cpp interface ServiceIf class ServiceClient : virtual ServiceIf TProtocol in TProtocol out class ServiceProcessor : TProcessor ServiceIf handler ServiceHandler.cpp class ServiceHandler : virtual ServiceIf TServer.cpp TServer(TProcessor processor, TServerTransport transport, TTransportFactory tfactory, TProtocolFactory pfactory) serve() \end{verbatim} From the Thrift definition file, we generate the virtual service interface. A client class is generated, which implements the interface and uses two \texttt{TProtocol} instances to perform the I/O operations. The generated processor implements the \texttt{TProcessor} interface. The generated code has all the logic to handle RPC invocations via the \texttt{process()} call, and takes as a parameter an instance of the service interface, as implemented by the application developer. The user provides an implementation of the application interface in separate, non-generated source code. \subsection{TServer} Finally, the Thrift core libraries provide a \texttt{TServer} abstraction. The \texttt{TServer} object generally works as follows. \begin{itemize} \item Use the \texttt{TServerTransport} to get a \texttt{TTransport} \item Use the \texttt{TTransportFactory} to optionally convert the primitive transport into a suitable application transport (typically the \texttt{TBufferedTransportFactory} is used here) \item Use the \texttt{TProtocolFactory} to create an input and output protocol for the \texttt{TTransport} \item Invoke the \texttt{process()} method of the \texttt{TProcessor} object \end{itemize} The layers are appropriately separated such that the server code needs to know nothing about any of the transports, encodings, or applications in play. The server encapsulates the logic around connection handling, threading, etc. while the processor deals with RPC. The only code written by the application developer lives in the definitional Thrift file and the interface implementation. Facebook has deployed multiple \texttt{TServer} implementations, including the single-threaded \texttt{TSimpleServer}, thread-per-connection \texttt{TThreadedServer}, and thread-pooling \texttt{TThreadPoolServer}. The \texttt{TProcessor} interface is very general by design. There is no requirement that a \texttt{TServer} take a generated \texttt{TProcessor} object. Thrift allows the application developer to easily write any type of server that operates on \texttt{TProtocol} objects (for instance, a server could simply stream a certain type of object without any actual RPC method invocation). \section{Implementation Details} \subsection{Target Languages} Thrift currently supports five target languages: C++, Java, Python, Ruby, and PHP. At Facebook, we have deployed servers predominantly in C++, Java, and Python. Thrift services implemented in PHP have also been embedded into the Apache web server, providing transparent backend access to many of our frontend constructs using a \texttt{THttpClient} implementation of the \texttt{TTransport} interface. Though Thrift was explicitly designed to be much more efficient and robust than typical web technologies, as we were designing our XML-based REST web services API we noticed that Thrift could be easily used to define our service interface. Though we do not currently employ SOAP envelopes (in the authors' opinions there is already far too much repetitive enterprise Java software to do that sort of thing), we were able to quickly extend Thrift to generate XML Schema Definition files for our service, as well as a framework for versioning different implementations of our web service. Though public web services are admittedly tangential to Thrift's core use case and design, Thrift facilitated rapid iteration and affords us the ability to quickly migrate our entire XML-based web service onto a higher performance system should the need arise. \subsection{Generated Structs} We made a conscious decision to make our generated structs as transparent as possible. All fields are publicly accessible; there are no \texttt{set()} and \texttt{get()} methods. Similarly, use of the \texttt{isset} object is not enforced. We do not include any \texttt{FieldNotSetException} construct. Developers have the option to use these fields to write more robust code, but the system is robust to the developer ignoring the \texttt{isset} construct entirely and will provide suitable default behavior in all cases. This choice was motivated by the desire to ease application development. Our stated goal is not to make developers learn a rich new library in their language of choice, but rather to generate code that allow them to work with the constructs that are most familiar in each language. We also made the \texttt{read()} and \texttt{write()} methods of the generated objects public so that the objects can be used outside of the context of RPC clients and servers. Thrift is a useful tool simply for generating objects that are easily serializable across programming languages. \subsection{RPC Method Identification} Method calls in RPC are implemented by sending the method name as a string. One issue with this approach is that longer method names require more bandwidth. We experimented with using fixed-size hashes to identify methods, but in the end concluded that the savings were not worth the headaches incurred. Reliably dealing with conflicts across versions of an interface definition file is impossible without a meta-storage system (i.e. to generate non-conflicting hashes for the current version of a file, we would have to know about all conflicts that ever existed in any previous version of the file). We wanted to avoid too many unnecessary string comparisons upon method invocation. To deal with this, we generate maps from strings to function pointers, so that invocation is effectively accomplished via a constant-time hash lookup in the common case. This requires the use of a couple interesting code constructs. Because Java does not have function pointers, process functions are all private member classes implementing a common interface. \begin{verbatim} private class ping implements ProcessFunction { public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException { ...} } HashMap processMap_ = new HashMap(); \end{verbatim} In C++, we use a relatively esoteric language construct: member function pointers. \begin{verbatim} std::map processMap_; \end{verbatim} Using these techniques, the cost of string processing is minimized, and we reap the benefit of being able to easily debug corrupt or misunderstood data by inspecting it for known string method names. \subsection{Servers and Multithreading} Thrift services require basic multithreading to handle simultaneous requests from multiple clients. For the Python and Java implementations of Thrift server logic, the standard threading libraries distributed with the languages provide adequate support. For the C++ implementation, no standard multithread runtime library exists. Specifically, robust, lightweight, and portable thread manager and timer class implementations do not exist. We investigated existing implementations, namely \texttt{boost::thread}, \texttt{boost::threadpool}, \texttt{ACE\_Thread\_Manager} and \texttt{ACE\_Timer}. While \texttt{boost::threads}\cite{boost.threads} provides clean, lightweight and robust implementations of multi-thread primitives (mutexes, conditions, threads) it does not provide a thread manager or timer implementation. \texttt{boost::threadpool}\cite{boost.threadpool} also looked promising but was not far enough along for our purposes. We wanted to limit the dependency on third-party libraries as much as possible. Because\\ \texttt{boost::threadpool} is not a pure template library and requires runtime libraries and because it is not yet part of the official Boost distribution we felt it was not ready for use in Thrift. As \texttt{boost::threadpool} evolves and especially if it is added to the Boost distribution we may reconsider our decision to not use it. ACE has both a thread manager and timer class in addition to multi-thread primitives. The biggest problem with ACE is that it is ACE. Unlike Boost, ACE API quality is poor. Everything in ACE has large numbers of dependencies on everything else in ACE - thus forcing developers to throw out standard classes, such as STL collections, in favor of ACE's homebrewed implementations. In addition, unlike Boost, ACE implementations demonstrate little understanding of the power and pitfalls of C++ programming and take no advantage of modern templating techniques to ensure compile time safety and reasonable compiler error messages. For all these reasons, ACE was rejected. Instead, we chose to implement our own library, described in the following sections. \subsection{Thread Primitives} The Thrift thread libraries are implemented in the namespace\\ \texttt{facebook::thrift::concurrency} and have three components: \begin{itemize} \item primitives \item thread pool manager \item timer manager \end{itemize} As mentioned above, we were hesitant to introduce any additional dependencies on Thrift. We decided to use \texttt{boost::shared\_ptr} because it is so useful for multithreaded application, it requires no link-time or runtime libraries (i.e. it is a pure template library) and it is due to become part of the C++0x standard. We implement standard \texttt{Mutex} and \texttt{Condition} classes, and a \texttt{Monitor} class. The latter is simply a combination of a mutex and condition variable and is analogous to the \texttt{Monitor} implementation provided for the Java \texttt{Object} class. This is also sometimes referred to as a barrier. We provide a \texttt{Synchronized} guard class to allow Java-like synchronized blocks. This is just a bit of syntactic sugar, but, like its Java counterpart, clearly delimits critical sections of code. Unlike its Java counterpart, we still have the ability to programmatically lock, unlock, block, and signal monitors. \begin{verbatim} void run() { {Synchronized s(manager->monitor); if (manager->state == TimerManager::STARTING) { manager->state = TimerManager::STARTED; manager->monitor.notifyAll(); } } } \end{verbatim} We again borrowed from Java the distinction between a thread and a runnable class. A \texttt{Thread} is the actual schedulable object. The \texttt{Runnable} is the logic to execute within the thread. The \texttt{Thread} implementation deals with all the platform-specific thread creation and destruction issues, while the \texttt{Runnable} implementation deals with the application-specific per-thread logic. The benefit of this approach is that developers can easily subclass the Runnable class without pulling in platform-specific super-classes. \subsection{Thread, Runnable, and shared\_ptr} We use \texttt{boost::shared\_ptr} throughout the \texttt{ThreadManager} and \texttt{TimerManager} implementations to guarantee cleanup of dead objects that can be accessed by multiple threads. For \texttt{Thread} class implementations, \texttt{boost::shared\_ptr} usage requires particular attention to make sure \texttt{Thread} objects are neither leaked nor dereferenced prematurely while creating and shutting down threads. Thread creation requires calling into a C library. (In our case the POSIX thread library, \texttt{libpthread}, but the same would be true for WIN32 threads). Typically, the OS makes few, if any, guarantees about when \texttt{ThreadMain}, a C thread's entry-point function, will be called. Therefore, it is possible that our thread create call, \texttt{ThreadFactory::newThread()} could return to the caller well before that time. To ensure that the returned \texttt{Thread} object is not prematurely cleaned up if the caller gives up its reference prior to the \texttt{ThreadMain} call, the \texttt{Thread} object makes a weak reference to itself in its \texttt{start} method. With the weak reference in hand the \texttt{ThreadMain} function can attempt to get a strong reference before entering the \texttt{Runnable::run} method of the \texttt{Runnable} object bound to the \texttt{Thread}. If no strong references to the thread are obtained between exiting \texttt{Thread::start} and entering \texttt{ThreadMain}, the weak reference returns \texttt{null} and the function exits immediately. The need for the \texttt{Thread} to make a weak reference to itself has a significant impact on the API. Since references are managed through the \texttt{boost::shared\_ptr} templates, the \texttt{Thread} object must have a reference to itself wrapped by the same \texttt{boost::shared\_ptr} envelope that is returned to the caller. This necessitated the use of the factory pattern. \texttt{ThreadFactory} creates the raw \texttt{Thread} object and a \texttt{boost::shared\_ptr} wrapper, and calls a private helper method of the class implementing the \texttt{Thread} interface (in this case, \texttt{PosixThread::weakRef}) to allow it to make add weak reference to itself through the \texttt{boost::shared\_ptr} envelope. \texttt{Thread} and \texttt{Runnable} objects reference each other. A \texttt{Runnable} object may need to know about the thread in which it is executing, and a Thread, obviously, needs to know what \texttt{Runnable} object it is hosting. This interdependency is further complicated because the lifecycle of each object is independent of the other. An application may create a set of \texttt{Runnable} object to be reused in different threads, or it may create and forget a \texttt{Runnable} object once a thread has been created and started for it. The \texttt{Thread} class takes a \texttt{boost::shared\_ptr} reference to the hosted \texttt{Runnable} object in its constructor, while the \texttt{Runnable} class has an explicit \texttt{thread} method to allow explicit binding of the hosted thread. \texttt{ThreadFactory::newThread} binds the objects to each other. \subsection{ThreadManager} \texttt{ThreadManager} creates a pool of worker threads and allows applications to schedule tasks for execution as free worker threads become available. The \texttt{ThreadManager} does not implement dynamic thread pool resizing, but provides primitives so that applications can add and remove threads based on load. This approach was chosen because implementing load metrics and thread pool size is very application specific. For example some applications may want to adjust pool size based on running-average of work arrival rates that are measured via polled samples. Others may simply wish to react immediately to work-queue depth high and low water marks. Rather than trying to create a complex API abstract enough to capture these different approaches, we simply leave it up to the particular application and provide the primitives to enact the desired policy and sample current status. \subsection{TimerManager} \texttt{TimerManager} allows applications to schedule \texttt{Runnable} objects for execution at some point in the future. Its specific task is to allows applications to sample \texttt{ThreadManager} load at regular intervals and make changes to the thread pool size based on application policy. Of course, it can be used to generate any number of timer or alarm events. The default implementation of \texttt{TimerManager} uses a single thread to execute expired \texttt{Runnable} objects. Thus, if a timer operation needs to do a large amount of work and especially if it needs to do blocking I/O, that should be done in a separate thread. \subsection{Nonblocking Operation} Though the Thrift transport interfaces map more directly to a blocking I/O model, we have implemented a high performance \texttt{TNonBlockingServer} in C++ based on \texttt{libevent} and the \texttt{TFramedTransport}. We implemented this by moving all I/O into one tight event loop using a state machine. Essentially, the event loop reads framed requests into \texttt{TMemoryBuffer} objects. Once entire requests are ready, they are dispatched to the \texttt{TProcessor} object which can read directly from the data in memory. \subsection{Compiler} The Thrift compiler is implemented in C++ using standard \texttt{lex}/\texttt{yacc} lexing and parsing. Though it could have been implemented with fewer lines of code in another language (i.e. Python Lex-Yacc (PLY) or \texttt{ocamlyacc}), using C++ forces explicit definition of the language constructs. Strongly typing the parse tree elements (debatably) makes the code more approachable for new developers. Code generation is done using two passes. The first pass looks only for include files and type definitions. Type definitions are not checked during this phase, since they may depend upon include files. All included files are sequentially scanned in a first pass. Once the include tree has been resolved, a second pass over all files is taken that inserts type definitions into the parse tree and raises an error on any undefined types. The program is then generated against the parse tree. Due to inherent complexities and potential for circular dependencies, we explicitly disallow forward declaration. Two Thrift structs cannot each contain an instance of the other. (Since we do not allow \texttt{null} struct instances in the generated C++ code, this would actually be impossible.) \subsection{TFileTransport} The \texttt{TFileTransport} logs Thrift requests/structs by framing incoming data with its length and writing it out to disk. Using a framed on-disk format allows for better error checking and helps with the processing of a finite number of discrete events. The\\ \texttt{TFileWriterTransport} uses a system of swapping in-memory buffers to ensure good performance while logging large amounts of data. A Thrift log file is split up into chunks of a specified size; logged messages are not allowed to cross chunk boundaries. A message that would cross a chunk boundary will cause padding to be added until the end of the chunk and the first byte of the message are aligned to the beginning of the next chunk. Partitioning the file into chunks makes it possible to read and interpret data from a particular point in the file. \section{Facebook Thrift Services} Thrift has been employed in a large number of applications at Facebook, including search, logging, mobile, ads and the developer platform. Two specific usages are discussed below. \subsection{Search} Thrift is used as the underlying protocol and transport layer for the Facebook Search service. The multi-language code generation is well suited for search because it allows for application development in an efficient server side language (C++) and allows the Facebook PHP-based web application to make calls to the search service using Thrift PHP libraries. There is also a large variety of search stats, deployment and testing functionality that is built on top of generated Python code. Additionally, the Thrift log file format is used as a redo log for providing real-time search index updates. Thrift has allowed the search team to leverage each language for its strengths and to develop code at a rapid pace. \subsection{Logging} The Thrift \texttt{TFileTransport} functionality is used for structured logging. Each service function definition along with its parameters can be considered to be a structured log entry identified by the function name. This log can then be used for a variety of purposes, including inline and offline processing, stats aggregation and as a redo log. \section{Conclusions} Thrift has enabled Facebook to build scalable backend services efficiently by enabling engineers to divide and conquer. Application developers can focus on application code without worrying about the sockets layer. We avoid duplicated work by writing buffering and I/O logic in one place, rather than interspersing it in each application. Thrift has been employed in a wide variety of applications at Facebook, including search, logging, mobile, ads, and the developer platform. We have found that the marginal performance cost incurred by an extra layer of software abstraction is far eclipsed by the gains in developer efficiency and systems reliability. \appendix \section{Similar Systems} The following are software systems similar to Thrift. Each is (very!) briefly described: \begin{itemize} \item \textit{SOAP.} XML-based. Designed for web services via HTTP, excessive XML parsing overhead. \item \textit{CORBA.} Relatively comprehensive, debatably overdesigned and heavyweight. Comparably cumbersome software installation. \item \textit{COM.} Embraced mainly in Windows client software. Not an entirely open solution. \item \textit{Pillar.} Lightweight and high-performance, but missing versioning and abstraction. \item \textit{Protocol Buffers.} Closed-source, owned by Google. Described in Sawzall paper. \end{itemize} \acks Many thanks for feedback on Thrift (and extreme trial by fire) are due to Martin Smith, Karl Voskuil and Yishan Wong. Thrift is a successor to Pillar, a similar system developed by Adam D'Angelo, first while at Caltech and continued later at Facebook. Thrift simply would not have happened without Adam's insights. \begin{thebibliography}{} \bibitem{boost.threads} Kempf, William, ``Boost.Threads'', \url{http://www.boost.org/doc/html/threads.html} \bibitem{boost.threadpool} Henkel, Philipp, ``threadpool'', \url{http://threadpool.sourceforge.net} \end{thebibliography} \end{document} thrift-0.19.0/doc/coding_standards.md0000644000000000000000000000435014303740367017505 0ustar00rootroot00000000000000# Thrift Coding Standards Any fool can write code that a computer can understand. Good programmers write code that humans can understand. -- Martin Fowler, 1999 The purpose of this document is to make everyone's life easier. It's easier when you read good, well-formatted, with a clearly defined purpose, code. But the only way to read clean code is to write such. This document can help achieve that, but keep in mind that those are not silver-bullet, fix-all-at-once rules. Just think about readability while writing code. Write code like you would have to read it ten years from now. ## General Coding Standards Thrift has some history. Not all existing code follows those rules. But we want to improve over time. When making a small change / bugfix - like a single line fix - do *not* refactor the whole function. That disturbs code repository history. Whenever adding something new and / or making bigger refactoring - follow those rules as strictly as you can. When in doubt - contact other developers (using dev@ mailing list or IRC). Code review is the best way to improve readability. ### Basics * Use spaces, not tabs * Use only ASCII characters in file and directory names * Commit to the repository using Unix-style line endings (LF) On Windows: git config core.autocrlf true * Maximum line width - 100 characters * If not specified otherwise in language specific standard - use 2 spaces as indent/tab ### Comments * Each file has to start with a comment containing [Apache License](http://www.apache.org/licenses/LICENSE-2.0) * Public API of a library should be documented, preferably using format native for language-specific documentation generation tools (Javadoc, Doxygen etc.) * Other comments are discouraged - comments are lies. When one has to make comment it means one failed to write readable code. Instead of "I should write a comment here" think "I should clean it up" * Do not leave "TODO/FIXME" comments - file [Jira](http://issues.apache.org/jira/browse/THRIFT) issue instead ### Naming Finding proper names is the most important and most difficult task in software development. ## Language-Specific Coding Standards For detailed information see `lib/LANG/coding_standards.md` thrift-0.19.0/doc/committers.md0000644000000000000000000000317314303740367016367 0ustar00rootroot00000000000000## Process used by committers to review and submit patches 1. Make sure that there is an issue for the patch(s) you are about to commit in our [Jira issue tracker](http://issues.apache.org/jira/browse/THRIFT) 1. Check out the latest version of the source code * git clone https://github.com/apache/thrift.git thrift 1. Apply the patch * curl https://issues.apache.org/jira/... |git apply --ignore-space-change or * curl https://github.com//thrift/commit/.patch |git apply --ignore-space-change 1. Inspect the applied patch to ensure that all [Legal aspects on Submission of Contributions (Patches)](http://www.apache.org/licenses/LICENSE-2.0.html#contributions) are met 1. Run the necessary unit tests and cross-language test cases to verify the patch 1. Commit the patch git --config user.name "Your Name" git --config user.email "YourApacheID@apache.org" git add -A git commit 1. The commit message should be in the format: THRIFT-####: Client: Patch: Description of what was fixed or addressed. If this is a github pull request then add the below comment to automatically close the GitHub request, where #NNNN is the PR number: This closes #NNNN 1. Double check the patch committed and that nothing was missed then push the patch git status git show HEAD git push origin master 1. Resolve the Jira issue and set the following for the changelog * Component the patch is for * fixVersion to the current version on master thrift-0.19.0/doc/images/0000777000000000000000000000000014303740367015124 5ustar00rootroot00000000000000thrift-0.19.0/doc/images/cred.png0000644000000000000000000000222114303740367016540 0ustar00rootroot00000000000000‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEá :'.IDATHÇÕ–_hÖeÇ¿ï»ßÞù®¹-ËTƒéèÂW`1ºi¡“¤¥»(YA°‘„Y͉/¢PºÛ.‡W›Ál5ô¡t¡¤dmNËönÉl[sÛûþþ<ÿÏéâ÷›3ÞfzáE~ÏÃçó;ç{žç<)fÆÃi<äáÝksìü™fÞ™·’£?ã¬Yû]'¢>gÝÀ³»ÚÜJ>R+¥hìü™f>VóDýÖ²òGày¼Ò @E!d¡07‹ÙÉñ‹dìÞmm{¯ß7àê¹ÓRàÃk7mΖe³¬ˆz­ÖÃF†9²i/S—.ñšJ³ÙöüÂBãÄÏ—9:Ôôú[GÿpõÜé/jŸÜôaye%¬ˆ:³“¿ô°U€µ`c­ÁJ•ŒÆüÓ/t”U=Ú==1©׿|éíwºVŒœýnOÍãõÇ+*«¡‚üË«§F†@8;7¬5XI@kÜÚ¼­¹¢¦öû?~Çìø¯m;öt¢¨Š®œ9•!GG2™ ¢Å¹ÎÕ—‡ ÕòßjÖ P¼4O¢YóÃàÐÂÍÉÎêêJ°‡>íÊÈÚÖªÚµëm\¨ÿ±‡¥‹XÄ!ÀR‚¥¤K HˆÎöõèÅù ë6ÔCÉÖbÑö4«d/D–ÑÃ]óx-H–al‘#Dï*ÏC*ò·gÝÁ=LBD8ÑönLœ*ƒXÄ`«õpII i=W°Ö®!«AFç8 fÜØQRE°&Öä€PNŠ\:» ¬y}€Œ…8©@³3±sfÀQ plt,¶’Iš–ÒƒTà#­`Iÿ[ÓVë*v¶Ž…¼ZŠÀ‚­¿ZZ‚u"°`%c]”[SgR 68(,›Ÿûp˜¬ÃIÅQÀY íµÛéi,X)û ·çnD"jüíùW:8(€ü<Ø_PP>(ôÁQˆ,Dœ2£1²û½«£F3æôv¼û¦08´0wDÔ=öâžfòà ‰&,€#?v…É5!ÁZct÷þfd3ÝöÖ-ø¸åë~½âe7ppß‘ÒÚÇTUW¤ì|êøW=0:ÑÂaY0ctïÁò¼nóçMèÉÂÑ–þþ÷ïÙpRA¾‹ÿšŸ·üIéÆÝ£¯ík'­{aô0ŒÍ%q×!nâÒ²v›Ÿk”cÓÀg>¿ï†óí­ ójÊ·zkÖ©4¼ly|ê}Lvff:¼àÍ–þþ«ÔÑàTÛ«% ìÐ  [’­KÌœpÀ7;Ož|ð–ù¿yUü Y3TJÎÑÚéIEND®B`‚thrift-0.19.0/doc/images/thrift-layers.png0000644000000000000000000006511314303740367020431 0ustar00rootroot00000000000000‰PNG  IHDR1¡f±ÊØsRGB®ÎégAMA± üaPLTE $$ ($,H,DD0Pm]Y0Y}4]4a‰uÎÿü¿uNU?¨šHII OjLJJRcRR¢“’…Ô˜””(¤Æ¤¤D!5&%% ©1))QHII‰BjLJJRcRR¢“’…ØÆÔ}i< À»QÝ—šqÛ5ïK|Ÿ]óBg«ªHJJD<Æ ™C¨àoÌdP,:çgÌÀ¼eãx<0o£z„Ly?/÷o‚Û{ œø¯I¹°ñS·(\®øCWFøn$ù](cü›à®OjLJTÜÆ Ìk®û/òDéЄԘ”|qÓø¥=j†_·è\Ý—¾¤R¯“,IÂã4ëÂH>¬ÆÌ ðLÌ–‹vcŒêa«eã(ŸKÀ“jú&™n¦¼¹«yj‡tg•/¥Ø÷H7Ú±7Am­«4¶š0k`'[k”z´­vß)ncæ-:'guÿ…³œ·ô`kð,¯¨Fò!¡Žó“]´Þ~ø¶cn„â(‹9ùÆkW*ëi¶ò¥Û3\!ä°z9áh‚ìÈ[i®ˆÔÀ*ÎÜRÖ8Œñì;åÄe 'Š:º×ñÑÙÊj•6rä§Õ”>ü$§§i °cnT÷%.ˆÃðFFbã€o•/¥ØžQšgãh‚Ú®Ò|#5°Š3·”5c<ûN¹q#ÉDy¥£*o ~ÖʵšÝH;cCÛVÖF’{j¹1+À†U¾*ÅöŒìÊör{Ô>u•V›©‚¬â¬-å9çãÚwÊ…ˆÓ˜ã|Œíâ¼QÙe¥'¡ä °’Þ\!’6†¦?´‰½|UŠí)Ãz¹£ jŸºJÛ±Š³¶”G^c¼­M¹ p£ g¿È»1˜ÿä™.ùxbï cÌ]¡”Eçhs{ùFÖšÏÈ‹ùr<²5!¬1ÆzkKy¤3ÆØ$å‚ÄiŒJW€¬PÙEɯÛ2ƈ ¶ä³'¾"¾1¶]ñ«ÉWûfªÛ3²+y9p4AíSWi»1VqÖ–òœ×{mR.@Æ'-|±JèÒ!U%‰JcóÔØJ>ëTÇ ¾1ö]Q5hÑ^¾*ÅþŒªyæïl‚TVSi»1¶âÌ-¥n¼•°4ûN¹qcÎ8(Ep°Þˆü@šp’`þNIÉ“žãóhµ™|rÒ ¯!±'Ÿý)ÙUC^o–/¥Øžá:Ï»K½\ n‚ä¿®Òâ×À*ÎÜRÖð #Õðî;åÄaŒy„¥¼Cv!U$oð`@%%¿‡G¶äSÏÙR(¤1ü:ÚÈ õFû®°±RÊ*ßpÀ¶Gze³ñ WŒÞœ*aÕ‡+bÔÀ*ÎØÒXÃ¥wA!í¾S.<œç1vTvM*怑’R*”´1%P…”'¥lŒý<'%¥4(ecÓ³…”’Ãߘ””/©1))QHII‰BjLJJRcRR¢“’…Ô˜”ÈŒƒó ‚â¤äÉWŠÑÔ,5&%ãçϽ3 ^K÷Ës8žË.¢SˆJ1šš¥Æ¤D¹‰Ä!^N *ìµÑ_žŒ=Ì¢RŒ®f©1) ÜDj"™%åæððèÉ“ñ”)L¥MÍRcR"À¹id泉@% Ÿ ŸµïRäSBT-Ü÷ÔãÈËõë·`òÙ¥ñ³T©Ù”å Ruµ¦fʘá9ߊÉ?ZÜËÜãå›.„gn«÷màÛd]¾ÜÉEß)Kùr—Ö:WódnŠëI¨°˹nÉÄ­~Íš½lÌ”7'Á¥Ê˜Ì÷7¯]¿¥³ÿàÏ£žÈˆ1T©¹IUŠ™1¥j†¦fʘ#s¿‘ÿÛË?Ù¸ßÎcD1Ó1^õ"”­žß&ëòdÁTôø d9On;G¥µ&TÚÜžóãã=se)O,ç–&·zøb3uNFr!/—ʘ‡×®ß@yu1/zö 1æfTji"dn6ŒqÖŒhŒ(bGLaD…^òEDQèt ZϺŒ?Ÿ˜1gÏ#Þ‰ó+¤e‚ÆœMÒ1‘¸)cºûؘ›—~;–ZÆ<´zÖüI¢RÌRËGÍ¢#ŠØSE§‹Ÿ/l ÒÚÎø¹ÄŒAŽ'gÌ(™ó sþ|rÆüê|2q aÌÒ‘ûä‘ïJØ”¬1îšE5F±!¦(Dëbø"²„œ,hEg;?›˜1Èññs‰3Œ¹¯1÷޾7÷ÉbNævþ*ic’ˆ[=+£7æ;£Ô=cÙ¸Æ|ï¡Õë¶ì*Ecœ5‹dŒ8bGLaD…C—h'/6 k f>g‹eÌpó$3Zc@Ç6.,cD;b #¢Z]ž¼Ø¨c²¿¾É  $O–î|)gc¨eß^:t`bÏ·;&&ÓS{Z¾–¾pŒEìˆ)Œx"„Ó%„/•dLKvsÿh ýÝ;²ÿ›™_û9ålÌáogÆî[:U¾3|ß·4óªÌáìHË·;Æ.cÄbŠBDQ°.ù¼Ø¨ cî½ÆdöcIÉÃãÌ6µÞMyÏÊð·t¨ËÔaxŽîgó ÙÔ Gìˆ)Œˆ¢pèûäÅFóÍìÓ˜feLeŽ16c0΀ïŒÞ‡áæ1F±#¦0"Š Õ%ÆÉ‹J2æþQLÃÌYÙ…` ©2påÀáìhåÏÊD;b #žát‰æK‰”Ú&¹ù&Nþ­3ÿäéð™áùØ.çJYŠh MÇpÊÿ혔 ݇…=CÅ4Æ;¢ÙZIíˆaŒ8bCLQˆ( Ö%±““`Ì=CØ‹#ù$]²4¡ò%ؘ¨ø£N}´U oÌýæ['ò„†8ÆÄ  Æ„kh)u6ùá Ž1âˆ1…Q]’8y±1)Æ`8pàLŠc &8ßÌúÔ&ÒC¶«œÆpç‹aL3©Ëy‘Eìˆ)Œˆ"huÉïäÅÆä£fO÷ e'èÂÖ½#ÍH2ã]ÜN uÏ€ª b¿¾o„ãš$ÀÄG3úøÃÍá6ÊKïå·N¨ñ‡áˆ'K ÜŒ¡ö¾5DÆ|ûÀz[wÑŒEìˆ)Œx"„Ó%¶/“d öÒ,gè÷ qÝaØ~åþa䈊6+£‘„ª²í›Ù1ºdêmÃ_ žDž™õ¾/êo 7‡Ûh{)¬¤Ò¸ô—M§`ågLη†È˜ïŒ¶àŸí.’1âˆQ…Q¬K!N^lLÚ#ï›ð¼”K”¦|¾>™Æ zTU:öseé!evÇ6GuïðÍÊðÇm4^J÷‡›Õ‡àä9×xå8+Ã_Ð[C|Ó ‰ðøÀ¹ oŒ(bGLaD”ûÆCÇÉ µLòÒL²1Íb _å2¡©‹'/‹e yìk UÚK(cÔKi̺Ø0F=WÆèßâY ;¸9Ð,w!Eìˆ) «‚Ma Œ:¬ÑEfcÙý÷ÜóßGanÞº€I3Æœ•±1÷u kLc2ÞÃx±Œé ÓuJe3fW³2仆0ÆÈKùÊÂá* ³2õ—]ž³2ËŸ·†Ä˜8³2‘ÄBLaH—ûÿi„Æ–{”1b‹M2|k¤Ûî¹wHÛ{‰l eB8Bžù+c¬;þøâ¬ût!ÈW¥¨˜øCÃŽü.cÔõìsÌÙÜ„1Æx)ŠRolCÿÉs²âÃI¨¡XÆø¼5$ÆÄ9óO D†}¡¡å¸ÅØ’=¬=ycp4¾‡ŽJÉÁêk™ƒÐÆp±¨#o$HBbI¦lŠzcœùsŨN9Þß)c*þÌßë ëbøÂïºôÎ -Ž7öéЙ(á‰L€1Þ{ØÏΘhÞßñ7&FÝŒ‰XZc¢QchÞ!ÊEncD…C÷ç`,\Ÿƒ¡p$ˤCg~_Bñ%c4ïïø§nþÆD-­LA3¿}€?%\ƈ)Šº$ð¹±\Lš1@½©Cßá™Õ~ÛšãrÆh4Dª[°1 tiel @«cCjÄé8l{B3…7&œ.I|Ì2“5+C¢È›:tIÇI¼í E2&NÝge‘J+ßY”¯ÈÐ×eÐÌ¥C-¶'4„4†u‰xòRH&ÇäÊX @tÈU×»(‰lOh(–11êtæ­´r5VH3÷àaË·—Ž.¶'4„1Æ¡Kè“—‚2IÆààk¼©Ãiƒ¥m|ÍÜxÂKÑŒ‰^· c¢•V¶ÆÐ»¨òK{ŒïÌÄ6&¤.Åôe’ŒQ_B‘7u8mîÆ­ý /E2&NÝü‰ZZ™ÓAS¯fùŠ ò4óÛö'¼ä2&”.E^˜I1Æø ¿©ÃisÏ"Ûžð`LŒ ¾ÆÄ©›¿1QKËaLŒ‹¸E1†~ã ·J ‚sØb{ÂKnc4ºLÞlÌ`Òfe‘ñ7§™‘/ÎÊ¢<+‹B°1hh䋸E›•E&—1_DÅdè*Å€ç!/—­1í’k¶4â丈[ÞÆˆ,“~òb£Œ‰sA¸,‰s·ŒYJáäÅFE+¢^.Oc`EÔ‹¸åkŒ¥KIÌÆ *Øh—p‰25&úEÜ27¦Ät•`Lœ ÂeiLœ‹¸ålL霼بcâ\.Kcâ\Ä-_cJéäÅF¥ÌÊ¢R¶³²¨”¯1"Š¢Dt©1 ‡ðÆ”Ž. 5&`ÌÙñó¿JÚ˜9þqû©ÒàßÄyèœPi¿:7ú²œ³T’96*ÿÕCû“jxA!COtïíÛW?WžüY¸o_ïÎöúµ«ã3n“Y(E&Ä ŒÙÔ°vyíº-fÍ”1çEiX‚ŒþÊm ²2¡ºâ4Æ8X$ÀèY †ãçHÀ}çÑ‘—_6ì’Îñ#d1Ïcˆ1Ù´¦~á¥'ËÍ –ر1'fþa‰²…ëç 8uyBvgÑ‹¬+,µæ'?ž~ò©}+ªª¦L›65Ó¢3¥êRõÈW¯£kV??êç÷'ÊÌu[¶oßÞÙÙf0Æ£b5ÔÞÞ¶iÍmhºäzL:3³%Ú1æèÌ¿ŒÎ_ôp;ó…/üG“?wñ™Ï|æS&Ÿ>Î|ÌÍL¤›?”ý‡À[Agå¤F [½P¡™GewÛÃGIš°{þØÌ·ÇÅút!Œ¹dfá¹dZÕÅꃺˑ»þ¼_ßÚÿü_üâúOÿ×çê3b¶›?¤ô~¿i×®þþþÝìK aÔ'1;žèδµ}bÊ”Kfþþ¿ýýþ-‡:þ7‹ß¿dꔫV¨÷c\cLtcôº(_bêâõ…Œy›+hãí°ÆxkèªTIáÐÌì÷ì9´1yˆJÆœ$cŒO°“18/ŽÏ|'kñ×û©wYƨ÷Þ}ŒùKjÛí·S¤Öf7ºûQ¬1GœÜ²}ÿþƒü922úœLŒyö‰î™Ììª)—Ø[åÏ_üå_þ¡zI%ˆð—L©š±iÍš†÷'1_ŒhL .þ¾ 9¼¾¸ÂìdfíI÷;i'CU—/ÿøÌ]î=¿ΘH{öìø“‡1'=ÆHºçBTPHrüõ_ÿ Q|•ù2£ª÷Õ?q3¸Ë¯µÜ<4ÈÕ–ÿSÚ!ýjïX1‡ùwÿÎ0†d.`bøb3fÇŽÙU¿yÉß:›ªGZ/!@ ÌÜ%>Ç|‘ŒÉ`®×ð}ÓeŒßñDK€.¶¼§‹ÄU"êƸõã!ŒÑÔÐY9©’B£ ˜Ùã1fKî(EUökßóÇfž8y.–1b U—-¢ %‹Y=PÆÐçýA#¹eôZÉ1߀ QéR Ò00æÛÏ˘'{{ɘù9ÍáC‚aDƒù*³cGÛ&ݧýßo RBã‹ÚG€.Î(ªôÈ© ˆcL~º¨JaÏ=î=ç4& Q?þ±?™yôäÛ1ŒY€dÊ—Ûoÿ¢Û˜ýƒ=­µµ”^mxãj¢Ë£Òµsâd|]€eÌ>2¦V‚àE"b 1¨p`8$EÆðG15ßÁ mŒVµƒ˜ºúBÆœˆfŒ·†®ÚI•~ºÐž£“Œ¨È¢8ÆHR’¾“1•¯1GƒŒùKc⯠¤•Œ4 ª©ÒJˆ°bæöñm!l3X6F"âF¢ãŠ#BiÒ•1ü²ØÆèä‹„L°¢FHÔü‰fLT]\Yë¨S4c5Ž1’ @r 9º0_øâL‡1MÁÆ8[+e­•6šØÏoÌŽ·µÖçˆØŒ™`Œ„I‚#Hh‰IóejiŒî{þ!ŒIRgjÁM •“*)‚uŒ‰«‹~Ïá<`$ ˜`]œ¾`>õ¹Æ$gͧ¤#Ή‘=JÚØ:ž(c8$ÑA4¾P±ºØÃGÚ˜\Ý訛§U¥dŸŠ°Æ$œ@‘4 $4³13¼³1ÔS] kL~­ÕǹàÆH„€„È#+BÒ¢¼ŒÑꢊ©KX_Âã­¡«vR%EˆnáŒI<"#IÀH"ÿÑÅ«‹áKXcüâ,u67\k oŒDH„؉cEÈ ¸Æèä Âåõ…#A˜¨º¸úѯN!Œ)„¨¡‘,’Œ¿/VýLL_B·µ¹ã\Hc$F@"䉑Èj‘˘˜ºØÓÒÌß’ËM •“)BërS QC#Y$ ·.F2ˆ/\?Î]ìä2¦ q.˜1"çì^ôâ÷c"ƒ i|1Ê“@‰’Irº€`cru££nžnT•’y4¦p ÂÉBÒ€pŸ¼p.X¾Põ,œº€`còkmÎ8Æ éu_8,ž¨ÆhuQåÆÔ%†/ÆxkèªTI­A€1…L \ÆH’„¿.fõ,\à `Œ_œ¥±ÎæFnmŒ‘å]!«E‚žHÆèä Âåõ…#OàgLT]\ý¢N~ÆXT½1œ@Ò€< \º8žîtÐèüŒ‰ÛÚHqNÚ‰³1[xÂS{Zšù&dhÑÔÐY9©‘"Ž.@kLáEÕãñEÒ tà %eWÏÄG 5¦XqN؉Q8]8.Žð„4AÒø"åÅÓ%_|Œ‘Z™¸*'Ub<ݨ*%¥¡5FvhâܳìS3üŒ‘, $ ½.” fõ,ü}ñ1†Ë°¡ ‘Ææhm”8'kŒ;H®XdµÈÀPÆhuQÅr¤æÝåŽUvâø]ùè’m”zrcÕŽ‘j)lõ²UJŠÎAncœ;NHTcTIÆ• ._80~³1ƒÜƨb¤­fk³]¸q·6ÛØÚ%Ÿ•GD!Œ‘øÝèbÃ-4ñÉmŒ¿.ó‡h£‰‰®Z2F… ÌêúóùGí¾d±Ññ»Œü•!ù#­•^”ªµÒf]þÔOêÅý(•’‚s’Ãçž©á”;ŠûEÔõk@Nd'>û…Ïåi ·–Jâ¶uóî~ÄÚjmŽ>-Ž1®EO.c$86(NV^1pÄn %Çò.à sç#ñ cŒ½r@ªDÀÕfÒF;È+üqî;Ìš9RÕ•ŒË™kd»¾ŒŸ«‡úPé.Û5Ôø¹¼Œ1Z‹’êÐÚå]-öÖR˜éOµVâ<¹ÆHŒAR”£wñl,dx¢Ce"Rfbð„uþТ g>ÿùe£8}ÉvÑð–¥9›:ÂÐp cîäÕûü3P˜n'Bµ¤îm‹ñŒ‘ÚIÝ캠a̧æÞE]ùyUat£ÚŸªbõ±a+Ù‡cœ;æ=ÏQÇ‘Ï`H;ùÔüìu vˆ÷üùç¹ ÎdñGQС5†Ó€qûºÐL£Kž·£>twûòãw!0 ˆo —£Z›í¢±#)áC˜ŒÓü"ÛÅSö.:Xš-¥>•Ö.Á22ÂlüâщãëèI!ŒñŽÀ|@é¢ÙÂó… ðD2†K´'ÆT§xó‡  òmþÈãtp‘1†}¡áÈK¬¦˜!pXRRKêþ.çJ´Æ8+ÇÙj@yuóYò> œùü3Ü“ªfÔŸ¦NváƒÖížqìÂ-vÌÓ@iÿ#Æž±·Vj¸Ê% €»ýÑMÆž›w}ñöåÐ)1Ê)ñÔ É€JÅ5ÆÑZ”„vâOŒùÔ§”1j.NK 6µÔl%”Û"Ý«>0IÚ˜¿ÕÄH…ç‹ÑÂÞ*Ξ*3ÄäMi⡌Q“15EYTd𥇜ÆÒ⣴εÒ½1ºô ºqà³èÅÏá(oÎZ»j¹fd‹Ôý1º=#ôjÏ”BŸB£ðO=hÏl µ”@ÕdÇ‘Œa_ô£‹yi,ËãK+âÏ)ñ…Ï}N¥Äçp,kŒ½µ”\u˜ñò¤×f u?u=Œ1Zжq+ï|ž˜£‚±È÷f0É#áf„Üá¡Kc¹ÂÒ*Ö« 0¡ÁØ4æ“K”1¤ ‡ƒ òÃ)…±$ár®ôGkŒÔÌé‹u .ýä'âßÈÈûÂt2†ÿx¾h‘ý:E•hp ñyþ©XОÍêƒÏâ§Î͵)aÇÏi' ÈN ¡d M/è|„–Ü6ÆuèëÅ;G0-¨1*!ù•‹¸áÉe —ë§ Èv!;lÆPjb6ÆÆ`ÌUqƒ;š…ðŒç%º·-Æ1Fª¤pé‚*9ó§²Mc09˜8¾Î4f‰T8­1²O…µg¹^ôqi”˹‚¤j@k)fÌÆ'ÎI#‘!ò8˜„0F,1 Ð¥H¾øãîFU)yERh)|éñŒ%¢ ÐS¬8'lŒÄ†È'<9M JA 5FjeÏZÙÆP 5F*TXÊݱ¥4t©1+·ß.½X0Rc<„2¦Ät©1©19˜1æ ‘ëÿ(+E]Àn ²€ŒùêWÿ¢ÀüÕÿ^)ƨOû'Àßä2¦ué³¢ªjÚ%E`š2¦~-³½lgeï’æ$À»~3À˜£3ÿ°Dù®;oÇO§®·¼è1¦çYWX>ë6¦H\¼¯—Œ©UcÌ`qâ<óÅ䌙--IŒ1ã'¾ø|Iò"²‡jhAu-Fe±gWO¾]œ(½xô3rèÐÝÈ‚M—J9=RÆ,Nk½qŽŒ1bµðbiJBL]¨"Ëk½Æœ@–"G=ÆL©®È[WOŽŸ.ÆžÑä“* ž¥,Ø·ja‘È =65ØŒ)Vœ%¾1·Œé]!MIŠ^ †Ýu[úÆàðyâhIrâ¤'žoŸ<)+ ô²C“"EéäÉ·ÇÏ" :ºwöí+"½;2kp£Œ9Qœ”@k%¼1áX (VFHhžê0fiXš¼í²‹TWïž‹¥·ß§,x™³ ·Wú®Ðô‚̦úóŘŸá`UòÆ2fGÒ±²…Äc eÃx ¢ñ…µ…D¿ç¢D‰ö#ÆdßQD2mõ K c§‹ÔÚüP±ÚÜžÉH3’$Ó¶†C²²©ÓmLJ)adA[[†h+›êV,¶#•)q¬Xq°TS’ÂIjL‰cdÁ&bMq¨¯o@vØŒ‘º”:öXIS’ IjL‰cfõÚª"±bÅ’Å ,ǘÖÍí…ÕŠ&5¦  ,8cÜmEaÁ‚…c¤.¥Ž+òEš’*$©1¥Ïø¹×8 6! fÏ(WÏ^è4¦lÆ+„jÁÍÒ–„¸z!‡DkÌs[KU=ƒ²ª°<'{³³[Ö–cFt`n¾f᥉ œ³²ýRŸÂ¢‹s$lG—¹Ò’Äx?‡„Ùå4æØGn)M>²ˆëç 8uýÈK²;‹ÝEÙóGgÉ'?†žènkÛ´pêÔiï*<Ó¦M½Ó$ˆ2fÿÏŸ›´8GCŪ½½mÓšÛÕ´©SgpHtÆ<÷ÑÿPš|TcÌe]aù¨÷à·µ(Qúã[ÆŒOvg2m §L¹äÃ…ç½Ó¦\¼ª¡a…õ~ÌîH… ‹&ÎÑàXu VmmŸH4VÓ§M™a„¤œŒ9ô1Vc>²ß³çbóÖ˜aÌÎ;VM¹äOÿôߘ?ýè´ª‹7­YÓ`¼ç¿°HÆ|dÿ˜„7&f¬2™ÙUS¦'ª?½ì¢ªþ”ŒÛ˜âD':]ô–; o˘·d‡cE2棇O˧ý»Ÿìí]Põ0¦Ðΰ1Ll¬ObÍwœ#b;ºÌ®úÍé–T¨þŒŒ1B²®ÉùÙå±ý¥kÌáÉ2æ‡nW‹f̱S6cVˆ1…åÏþÆìØÑÆÔUcÌ‹dÌ2±"c>--Ê›¯\c($õk—{¾SÊÆ¼êš͘W'Ýõ²ß¸äÏ€ôcø4ß;dc¶Õ˜ü¦e–1ûȘ¯$ª¯¼ÆpH4ß(Kñò‘ºG·É5¦°|…Œ1¾>Uì1&cÔw0Ù˜d`c8$©1¡(%c>ýiéÅ‚acþ2F93· Æè¾çŸãåB4Æþ[2ekLR±RÆøü2FjŒ—Ô˜Ô˜Ô˜(¤Æ¤Æ¤ÆD!5&5&5& ©1©1©1QHII‰BjLjLjLRcRcRc¢““…Ô˜Ô˜ Ϙ=Çç©?VÜ*ÜÒÿ½‚r5fO#ßUñ¶ŽŠ0¦ú=91ÑЯ¹hæ¤ØÃEH,ãŘfZmßÕ2R…o|I̘=´EØv&oÌžFu[ý Wuâ§꾫7Ççñ6A$cLõú+EcbÄ'ê7Ë×q¢V¿£n£ÅÐN$c gõ;u²81³3Ac¢Ä«pÆX·rO7͹•¹PŒ±nsÆ§ØÆTAê.;þS¾-ž1Žz¯¤'øÆ— ˜êsE2†(Ccôñ‰eLõÑÆóÇçÑ$ ]ŒÈ;|J°¯èºµúEY4VÓ¶Ëh>§"G²æÆf, “UA²©õJ]ÎxG5fÙyÚ UràVš(5òs²€m'Žo¤Zbãh'<´oàÓGìm̱WPvÆ Euü™i’ 3æêwJ@âdÈàEœ­ÐHüöàž¶52 e1ÎÐÑtO*È(Éx¥³òJa'òy ¬1Œ±ÆÇÌšBx÷hÏ{;y©ú ŽZȽ‚xƨ*ê3bÏ@Î×ç9Ƭ¤Ô@4Qg±¡(’1jÛ(ñ‰i ˸¯U"Ê©/bJMº—mUæzê(=‹[[A(Éx¥Y„:çáe#“è³2Å8ŒqìÀXà{®½–8gþö° X¢€`/!÷ cP­ÜÂäi §„i 5ÔÛ“~LöƒôñÉÃu-cð,ºFd¸÷q/A2Á#JÖ=<ÌÈJU’Sã?íÌ7ƒÈÆ`ZfVÔ2ƾc+Î7ZbŽ1Ü#b´D+°—{ÉÏÊBŸ1|I”Š?³wCR³2=ñ¡SûCk1 ó"Ž˜ü 6” ©Ì!š»ÔI ݪ•R’ñJ\<àã.ÐÄ9!cì;0øÞ?wó0ÆŒ-Ñ ì%ä^AùCs2ÕPü©N¥„£B©~Çi úÝ< y‡"%éÁèà¨Ê¯¦[+“P’þ<Hv¢ÏÊpCýF§ ¦1ŽX u¨Q¡ŒáˆÑ­@ÔBî”12M§†RäKó<&z|ò˜•áŒúøF˺T r¡ëu¾­Ò†¨ÔP¡Ã-OVª’¬WZP$ÉÇ[Ù‰sæO5Xf7ƹY ªòfzò™•£%1&ä^AÙà Ñhóbãù2»V¦'ª19aba¾2DQŒI–ˆÆ$G,cò%¿ó˜|(Ž11H‰HjLjLjLRcRc’5¦8¤Æ¤Æä 5ÆAjLjLRc¤Æ¤Æä 5ÆAjLjLRc¤Æ¤Æä 5ÆAjLjLRc¤Æ¤Æä 5ÆAjÌfÌî&-Ûeµ†Ô©1˜1g6Þõ% ‹ü•Iqs3v*ª2©1Rc.4cþõXDeRc¤Æ\hƼuìÇÑ”Iqs3qæÕ—¢)“ã 5†ŒùJáù÷¥bÌØ[•1Œécã=©1‘¸@ǘGÔÿç¿«ÿèÖÉ1&²2ncþ„øÊ•ÁÆüqi¢5FÖ­1²®°¸©švÉ%ï*8±1mõ+Ș ==ýÛ‹“c¢*c›•Í®úÍi‰…ê’iUÆûʬ¥ÑkÌ]²ªÀüøUwO>'k Ì]bÌ¡gŸVƉ‹÷õî€1µ`CgOOT§ÐüØmLDeĘnÄj®´$1®Þ×ûøêuƼõÒŸ+I~ü’;o'Þ:V”ºþø%ϱï_‹¥³1#0†² m†ô^¡™:W3Ƭn1`‹Û·oߺu?:ÇçÇÇÞ’øZDRÆ VlÌŠK¥- qéB6Õu[úÆLP K“cž#]L)/½êîɱ·ŽiϧÇÏŽàÀÙ½·oß¾¶UÅ¡¾ÆljX±ʬ^ßÚÚëÔϺH¥có’{ADQfÜ2fß&iKB¬ÙÇ!у+I^õƒº–•E³ç3ʼnÒá·Æ,cE£wGfMÃ’Å‹çÏ_Þš–f×ÑÁÁ—^’ZÇ­•ðÚ‰  ÅêÐPG÷N]‡CòÎìÜÆLŒy«$9£;¥²g4YœcÏʘŽ' LßSy#½L/È`R¶˜XÑPßÞ¾Ù–¦§çÅ£ƒ¿xõÍSRñXœÓ E˘Þ^iKBpH6ñŒYѰêæ)S.AYA`g¿û»pãMúЇ?üâÇ©ù‡§›Æ|Æ\þ;ï»þÆ›n’¶9áísÆm¿þ-Lƒ ex|2>‰™É´}"wΉ„ËÆåÓ§M™QßÐÀïǬsÏÊJؘ7Ý=“˘PEƼ Ïä4&\i×MñËiLÈÒ.û.„17\Ãu×ýŽ?ïyÏ{T\)Hl fe kÖÜV5å’ÿQ>üGbW>*°7&lÏGÝÆ\çcLÈ–NßãP(óÜwuÆÜµì9Ê Ã˜;vÌÓÆ?ú£›núæ†?¸á#…‡ÐИêÕÓôÓýÙå3»K×ϧýO²£®»ößÜr 'I§‚ ]ÚµÓ!ÇÏÃ¥™ÅII„«´ë®}÷w_;ýÝËnä­ë4\Ë\e"öÀeÌŠ5mmŸ¨úK>¢F‹ „èažÐ:Õ†„2ÆÑÐà¸måÁ9€±Aaösn˜ŸöïíMmäv¡¤1k”8 ÔPUíF2&Cïaò'1Ëǘc.cμ`Œ†œuíµ—Ã˜±± c¸´P ¦bÈ:`Œ³´•{÷wÒ¾{½À±­z¥³*×]'Öï½ü²YdLCãטÃiÃoÊeLõÖ[oº©zàV³¥ÙF©¬OܶÒPÄÿôæ‡?æ—»ŒÉÑFnPòH§(œæÜp³cGfSýZï÷cJÚ®¦ÅØ«~Æí•àW]uù-/ã,-G‚£¸éƒ¯ŽMœò5&biï^†##/sãÔÈm —qÕU¿ó^1æÿ“lÒ#ÉäÅL.« ¡ ·­žo@9ù…¯0/¶1ê;˜¾mtµRµÌy†f æ|ˆŒéíÍh¿QVÆ ÛQlÌ›ccoê‰\Z 1ÑK3Œqö¥ Š!¤à*‰°“é Î& ©daf”­ Àsæï0²l…,0æÕ[›'&æ]}s]m×5³znõ‹[c^÷fë_Rß k !M3 JÅ4PWÝðA2†¾Q¦ûÖrÙc¶Ó•Gþ)dLœÒüáÒÌâ¤$ÂU'…YÆØŠ°Á¥I1RŠ•f³#—1’B†/ª¶*С×Ç^OÆ|€m¼¾vàVs}¶®¹NªEPÕ¬¸“S»1s£´‘[HxG™›è’1•i ·ÑÈȰ cÞ«5†K‹šà@oŒ³´ð•sc±4˘œÇ_I#ÆL$å ïT¸ñF?cŒõ0ædÌõx€¿k`ÌûªG®‘šyãhLnaÜÆü±4Hƒ4O¡é×J£ÆŸ_Æ(ccŒ&FMp½1ÎÒÂ'8п41ÑK{O8c$‡fÉðÂ{e°çn¸‘ÉkŒ±†—oýÀõ6cÞ‡á¥úœaŒU7ƒ@cBÖiž`µÒã µ‚Îc*Ò«‰¡“ÈàÊ+ËcL>¥]é1&~i(Îc —f'%®Ò¸8)&”1’BgRIöjeíÙL$·1¤ŒQ5¾6Fd þ®k®›ud^s£TÍ·cÂÎiž ô¶’[A­|­¬²Œ1›È% DäLI~¯ÂeLüÒTqNc¸4³8)‰p•æHp—¦;‰^¹+«Ë¾ÆH ŽLR;Ì<âDróØ«6ëÈÄD×5vc Kõè<Ÿ–J˜ÆHën$/îVZ$*Íibì¿ò »1\Š›uä8fá×cÞ}«¶4¿¿òŠ+lƥŨœQšÝ˜Æ„ÆmŒ4Hë Zio&Ú‰VVš1±RÒÙQ–1×ÚJ›Õóé#ó®¯îª¸¦ºëšë²ó0¯».{üVwm¼+®ªmD9Ù:zXóâ­5]×HA Ø<܆aLìÒ¸81’Aá‰ö+y¤3æ}\1OÕ¸nR)Áªš‰Þ˜ðÂh‘Ö f#=˯. ’Œ Ρpe3ÆVl¨~ñÓ[¯!cèz(fe[¯¹¶¹S1Øyxxå•ÍuÍuRŽ`\9ª›o‚Û0Œ‰Zš³©^c$‡f&¹É1£D’$"<Æ\uR&dK¥j&Zc"ã5FZ'p#µ­tOÆì­Å2&ëJ¤<ñ1†zHˆÙQvc¤$Þ—¥‘³2zÓíÚkaÌUbŒ1+#cjúo•rÓ)ŠÈY7ßÊ™ÆHI„«4.NŠÜ¥yŒ‘,*‘|†I"‚v,)¤ps9“³¥ªjš–ꌉ"L 1®F†]Œiéúmy¤%x53ë•:1\P´ÆPûþÕŒssàÛQ6c¤,* 6\)Șë0-;~«Ý˜«øÌÿJ<¤ºÛf#eÅIp†1Rðo*³.Mi¾Æ˜‰äÖ%\"¹3\)…«j„¦nc" ã1FšÌVr#[39¼Ò:E5Æñ "Î×£É!Vµîªl£2& £<ƸJË•àÙyòÀ@Œù-Uš§rR3ªš¦4.cÌÒªÏQ `r–Þ&¼Ê(•/Ü5שE)èq%e’KŸ¢D ¡ì:­-„Çš–zã’..úÆÍ'!¼ÆDÆÏM+mÍ$S¸™h§4ÌM¥ãÊHé( ×µ_ c\ÅQiÎ~w•V3à<ïw£)mÖyWUÎs”P9»1®ÒšéB7‰W[c¸Ô+k^äs+,^Q3j¹¬3†3 ©då‘¢¹Ž?E‰Lªíºæ† ×øe’Íúe Ë Ïy¯ Ž›1…Ñc4RÛÌÂ43Ž1tÀB^ÐRÍ(Ò¸V’Ĺ:KKX%‹.cj^\tîø­²nÖºQ±9vÙõÛ³z>­e5o[Çö£¤1š”äŽc  ýs”äÁ2Ư4ÕíAýn3F_åöUÙ:T¿7BCBPõLc\¥¡8=1käŠQ©Wf뮬¥’ZØû!ÇmŒuäu'Ò76ãxk¦’錹–*†Ðã¬Çõ®UuWV½…s¾QQ½šíh³glvU¯1ÜFŸV†nf c߈þÀ55ƒ·^Q»‘KOØVãa-bÇÆ¢Û˜Q6Eõã¬Ø†Q‰€[È5lI;¢m­Ý(´Æø'8ɇS 6¦†jãî†1WæÐ%÷a’1Œq'¸”F¹M—P¯Ñ:‚«g£i*ƒÞ6J½’ÂÉ)c$ºŒÆë¸ëÌ$I¥kh𒍓¬Ñ 1†ºþŽ–fëäúH5Z™=~«1×vý6ŒÁ×8Œy½i‘a´ÆX­”jä7ÍÄØØÌÆpÓ0ÄSB·ÔmGbK÷ªÕÜ1èxZÇÆ¢Ç#'ð*.ÅòˆEÆ`;’mC£Ò‡áâäahŒAv³1-´µ£0'¦1Rá,§ 0Œ‘’{åÄe2y;Ú›\=Ã)‰0J³Œ¹òJUê\$Ë&c,]¬T’s`I%dÒïý}¼Nòƃǘ+` jF¡§‹ïò®ª„¶^gQ1ÔŠA5UUm¸Œܽ{÷V/»}…ñc?(8„q6M jfÆPGl¿&;G j9–•1|¥ñÏ\ÔÃ+-cð,Ò #9d¢GWµÔµØBÆ\!…9\Á¶„Ѹq•†Öra–1Õsc+͘•QiC•Ë’Y™ 1v¥x9‘8•èãÆ’.YßïۘˮÀ ƒº±1Õ/ÞŠ³+LçQ+ÑD2†ÆŒ¨áŒ1þëDúMè?ÿóÆmŒyT2Ö•±°ÍÌǘšêùíZ+Åcð¯ü4úÉ\ÔSs7x•i ÀdN3xk\clI$ ƒ` ^…º¢Ôž|q£+‘­sâ0Æ[šCõÂK£r`õœÆ8J#c0²ãü€&º3%„1ÎLR󡹎? Tiž‡£ï<•6^´Æ6&Ûu fd4Q´ƒMÆÃsÆxÿ·Ñ—^Òü'‹‚Ç—/öF†of cxîDçõ³à,¦fàˆÑj5Ÿ}0Ùè{sÑǘšQ§1ˆ©qcìÈ0†‹7ð3Æ›’œÞÔA€¡Éöà‹ÍoiŽá¥æ&äøSK>،ѕFÆÐf”7êü7°zbÌ»5Må«€rµD)B§D Œ1’E„=0­oÆágê¨Ý6JÚxñCÓ2À3Â:´”ÏüÙ 1æŠìÄÄÆ =Æü뫯ºÿ»ÑW_}ËW1n_¤…¦œa›Íz ’ DîŠ`Öó(«9Bôd-ÏÆE1œM–1R.R.ÉŽÄLáŒ"€Öw{‚‡Ä4Æ[šê}ÙN5Ål—†1ÞʹêæÉ†1~¥9šŠÌÔã1FÒ¸3IÒ$7.c¦ÿÖå2ÈoÕrã2fb쌟ÿ,“ñ#-$ì­D#÷D0¦H¸ˆZ|Œ‘ât”eÌ¿ñ¦$m³&ºtÕ±Œ‘rªnöÊE4FÊ<¥X5¸ù°‘G.]¢d’ÖrFWµ¸‰ŒÛÕFj¤½•‘Ž L%£’GˆÙQ–1—KAŒ*Mfß2‹ ·×ùj<ôýÍAÝ0F R¨âd‹(ÆH9ŠÈ¥¹ù;“¢wØË.›þîË¡Œì7 IcÌfÆh%¨Lcâw”Ö£4™•‰1Æ#ï Xgp¼Æ¥ÅÁkLœÒ¼Æ8¼±Éa 21êf´1ê¨ -$âùRŠÆ„"И|:ÊkŒ­4ž•òR›1Æ œ~$Æ9n+-.cTi‘‹sóAW&InDBg ”‘=F'qcÜ…X­gL¼²á0ÆYKÁïÂ9ŒQcKcTiùTÎaLìÒ|É3‘\Æ@™ø$m̳±¸Í¬4cbç ËUš­8cŒ…&týOfeêZ@NcÜ¥ÅÁ2&ŸÒÜÆÜdf’dE JÞÕÆ| ŠJ2&Ÿ$²0ñ–f\]®˜h´Æ¾J~k.c¼¥ÅÁ0&¿ÒtÆä›IÑŒ¡!:˜“¯/gŒ¬ÎØßJ¤4›1òD^ØŒ‘gâà1&ïo°1ôy(ØÑj’6Gje¾Í¬,cd]ž˜ÆÈržÆÈbžÆÈbLÜÆÜ(É6cj\ÆÐÇa68Ç”I0& [ˆÔ7©1±Èa Ý¡—0‡ÅÝqúxŸ bð¡©®ÚÀAâÆH=ó&5ÆMjL,ŒÁ¬ “2úP.}óEQj¶WCõNV‘Æ©gޤƸI‰E1WЧkù«Ù:5àԌʇNiI)©1ùPtcX6fž³}判ƃԘ|(²1-ô¢yƬŒ¿1…ó˜–®ßVïd¥ÆƒÔ˜|(²1ôµ Œ&ræÏï^ѵ²¬ñU¥–ôÌ¿ð¤ÆäÃ$ÌÊ"““,E4†ß^¿¼Œ1>A’¶ÿ9¶$I¢ ý7ì©1vœÆ\yåå±agÊÁ˜÷J…óá=%nLmdÞkó°Ö˜w—&ÓuÆÈº<™.ÆHqÓ/‹Ët.AŒIªrʘ|K›.ÆüÿlÌEÓ’à¢*$R/sÛÌK¦3²·X$cÌ¡gŸ†1‰µ‘‘†Â˜½Æ¼ºè+%ÊV¯1IÕuѱScc§–Ý¥–îª ¿~sfcR•Ûý ó\Þ¥Qõæ7lÚIÇß三´iÅâùµ55Õ@öŽ[>À˜ÓÍcLÂPCÛë[aÌö~‡1c¯îßýÃRdÿ 2ÇÁØ›/=—H]÷?ÇÆ{nÿ¸uwO\¶lß¾}ëÖÝûß„1\Zþ ´WÏà@6˜gi[·÷ô´´nîÞÙ·oÕŒ©IqéŠ}½;ÛæÃÆeßݸuëVÙ[v?‡‘^º6ãçFG0-ëÞ›hÕÐúµ«½Æ¼ylð¹çö—Ïiây u•Õù€¢‘”ÈÊ—Ðòƒ,L Ñz½r×nò=TZÞ<÷Üà1´›y–†v)cžÚ·¯71ö=Õ—io a–5mܺ{·ì,h)â––1‰¶‘Q }hu­Û˜‰3o;öR)rŒ²ÚÉ™S¿H¢®Ç޽z 2ŽzõØààÑŸþù! &Dé?:ø Š'J“òóâØ±7©Ýgò-ÖÚÚÝý$¥Sb<…Ùý#kaÌʦí8V Êîbpì§<= 6f¨#é6*¨¡ß{¨Ök ÒðÔ›%ȩӚpŽ%RÙS§Îðè…ÒNžÆaêгÄ‘èè g0ÈýÇ3™ºQå¨ngNçWÚëhÙó4È zŸJzûÇ‘WÓ aþ竲»è½ãçG_{yÊììK¬ŒÙÐåbÌi»12ãçy\?ô4±—莜2/«#Pi1~ò—£#8qÞ¹óñÇûO†L¦½žŽ¼f7z'·åtêÙ7qG²dÚ6Õ7@:2 J§ÆÀ„üefïÞ'™¾<ù$Ùµ¹µƒÌð‰IN-ã'G‡‡pn¶¹ng’áíí@˜Õ|ä¥Dšäv¿ÃG…ööö6ª^[‚lZS߀#ŒÙ•c‰ðkJ˜¾>CÓ×··»™–•ãçi¡Ë›‘QíßO€G}´~sëZ¦©ÓœÝO"t"c6·?òÈšd©ohX±„. ®kâCï.5F.¶01ΟêÛÙ¾™Œé?Zºƒ Ne›€ÊYûàêÕH£’bTÿ¡m߯G†'ËŠK“1+­ÿÔ»1ûzW­ˆÄš}û`Ì£<È,ÉAfâüIœü÷XWÍ׿Ëzfõ:³k 1çÏaRÝÚú¨Fz&!–,^¼˜Æ˜Ô;ãˆ8÷عO‘7¯Â1c;ÞÝ0f}gÏAcØ.-ÆO²2êÝ&•í °aÆ-ý»©Í“o Mª‡0)#c$Ó“b ”Á ³Á6ýcî.QΪúÙ¡ÿø-4¯ÿ\øCï^ò{Oí»T>–) èŠ}½ºÐº±³¿_ŠÔ±b¿< Ãþh]òºÙýýý»:;·mßÒD Õ‘ì|–ÎNy àbˆíÛ;u-~}â yŠƒÒ«±QS„Žövœ¦':-3¤™_»zC§ù±21æ¦(MVîæú9ˆR×¶5ý³<ôã>Ðúÿ<úHfÇ`Ì”iï Í”ªª…ûz3kx²[SSûÀÜ'…jh:¥â+÷GÚzÛJy†•M‘¶îì‰ññmÈã04½.Ýe̳ÝÝti Ò$ȪU,ÎòÕ4…póµÒäúǹ‚v¢Ôõ¾mM5òЗ¯ýëÿõ¿®Éd2dÌ´9w‡fó£Ìšú%KæH™šö¯”Gax ?Z3Gax )ÊÖ+{"Våì¶ûäqšNH·ÆÅ0fg&³iöŒD¹y!]^nÀ©Û–×µ²6Æ3-;©ÿ+Š1sÅ—@cú hÌc4¦ÿH´ª¼͘Ÿj&ÞQP§¡0fÇŽ…Se¶œSnδmzDÓï0fü§¥kÌîA&š1ÍÑù»pˆ1˜•…3få®HÆtИH[G6fø±HƼ’§1æ§ý{{?$—/·$Á”ª«wìhÛTÿðƒë·tö-c:ßpt¼lé‰d̶ ÇïÄ; –1ûfWM™qsrL«šÑÛ›ùÃËÔeÁÔ˜¢ÓŘŽfLsþ9¢1¯D3æ•¢c|kyvÕE7C¦Ìyóc|Óvy95&5&˜22f.Œ Û}9¹›Æ“¡ïùoØ’:öàæŽ‘š²0õ”GtÆpë´äaL`-˜ 3F~£b阘k–ÇL.c²‡ÉNLþ†dÄßYÙß=ƒ3Ò$¬1|æ7¦dt@Wû°ð5†kïÆa U³2ÕÔ c(“#¡‘,7Z­3F­ 5+Se5.²OïƒS˜#{0Î`ôÂæ8KǘÂbV†.8|=‚3ëüßÀ:óÇäÁ8§sQ:Ãc|Ïü¡ 6Ä8Ú˜9\ÇR'zc¸Þœgþ¨ü§¹©l ž±{f?ó§s}eŒÚÞ0ÆhµÎYæÌŸË’ #âm‘6cB‘“,áÎüý±Œ±ASu[J_ ïù[­ö㊈‡1¹I™\’5†¦ë ‹#ªm(º@Œ¡qDµZ?Æ8g‹Ô˜tŒq‘~®,Ô˜$Œq^Â- ©1¡HIRcB‘Òºbá÷AA©1¾¸Œ ÿ‹Ô %mLà]Äu5÷ŽÙu}‘/RŽñåO~[D®öª§é¢§ÿù¥Å7æfIý¤Æh(ec‚ß’vQcäý·;Àz=°C}–ˆŒ1Ö«§±x8òè¤5fešroýÀ´¶þ¿dvô’1SÂS%Æ¨ßæ%"u4uʃp„¨¸H¯|LîCÑcäa(š_‰Vü‘âüAA›•u¨7¡É¥…eŒ¬Ïª§y5¿å1o4Eú9¬Çrý6ý^Ù}ô{e2&S(cϯÉý{e/Dú™°hçl¥#Â@ßó—‡ax ù•æHtÄÝÉn ÎûAA1†§[–1î1FÖgeŒá%Í›ÊAh‰2J5mûy䋚•aZ¶cß—FbîŽ};2k–„š•5½»*6š¢l¼2Úï•E›•íŠöËÍG¢ÍÊŽx~-(å4+ãAÃ6Æð„ò cÌ¡1F=­#R\c~$?ØÞ #º)SCéñ<æ…BS´1&øƒ‚. eÌ#–1ôù<"KŸ7c°Þø¤!ŸÇDD{“°1_ûúœ9¢Looï~ô#ú?CC²ÂØOüScJyŒ þ  ‹„¡WæÏàɇiyÆO“%xš>ѪÖ×ÈÓP÷´]x¼ÆL̺\ö8þB³¾dÖ8&eAÆé,c ü{e¯•sŒ‰B²Æèᯠ²:|žEñŒ!eÖl¢»Í&Ú¸Þ!LYSZW—‹x­,E1†¦_òíZ>O‡"cB¤)Œ!eê׬i¨oŸuCCÊ% œ0…5¦³|¹0>%£ÇgÖc2f’¼1æ«,H™¿ÿ{Êþ‡è&va’0F*˜ËG;´ÆÐ÷X´$dŒ¾üÔ˜É%§1ò“¾„2Fe;²¿vù|(–ùóÏuø2‡ŒáK… GN•¼1šïIc‹‘“,ÅcD™9sjkkå‘Em<ðP[{§<2 ²\aRÒÆÐ7ñScTª1ôµcÌùšùk„ô»Xö¯Ðj¡žÆŸ}SIx˘ÚÕëVbÔY·nåòuëjéonðTíê•ô¬ÚÈieÏîÝsædOOÐ×ØÇŽ˜?áe}âXÆÈ—ƒq7Fß‚§Ûx¶% tÆÜA?F äråçÈdá4F¶æ;ºr©^kas÷ž‘‰Ã5ô›H¨Ñõóbü…d^¡¶qû6È«ÀËz¯1ŽW`~>zåÛz05&YBC·KéGJøçæÔÝ)ü¡cS•øp`¥³¥fÎ5s Æòšj–4á™%M5s–×Ò ~–62驞ÓR½ôÔÌÉò[QÍü£\¨ ²ÅJUÓz› Öç…–òÇ"²cÍü#zcH€fõS( h o-¿-&K²Ž°ŒÁþ²ô{"ÙoÐÃ× d³Æ/—1d¬a –à <ã5Æz1:c JcèíúÅN(µ +A€1öMUæÏYf=Z«—ì÷µÔÜGÆÐ þšjøYdLc¶Á•êo잃"駆šùG¹˜ët˜ÇjÓÎþ)"ZâZÐO«à8Íɤ7Ûf›i[µ‡ÆðÖÒNY’u„e  ñÈŽ°1ì#•Û‘Uj2.c¨YŽ‚%ð^cì¯Ã}jL! aŒüvrm,˜øãÜT¥þÊ&1´Vÿ=¦Zs0zð=Ý´6c…z–¨])Æì"cHcŒ™P¿Ó%©í2†æê0÷‘°Æ¨r5k:èóç÷xI5C­`rƒšØëd =P_±HI–Æð4wAW &Zcl¿þenÊ©¿ò±øžh­žÓ:88XÝ:ØŒûfZ€+´‚ž¥VŠ1_ï‡1Íü»þ˜©!‰ð>õpý*”q]Ý=+£;5/̆cxDzÑ’m3…wV†­ÍÄV„µ°ÍÊPeU!œlˆ?|“àQ0ÞÄÇ~/¦Æ”0³2êbÌ1aÆ Y0ÑC§Ü{M®MÙØPÆ(¤;<ÆxÎü1Ç¢+T‹ÜÆ`3ó%¹á­McÔk-cŒuçƒ× ŒZ¨Àh‘Wð °oŸ“,!ÏüýñØ͘ûä‘Ö¤«Ì΢Pxgehfe&Þ׺ Ž¡Ã-ÆhĸÉEjL²ä0†¿þHcñŒ‘WS‚Æ„"§12WRc&—œcL."ãȼ\Ày†|ŒÉE´z'lŒ“É6&áÿ965&˜ˆÆ4§Æx˜dcüßÉgLcNñ%5ÆKYsèÙ§aÌ쪪)S¦\”UU0Fþwòr6&êw0;£t_‰´yjL8`ÌŒé†1 §ª,IŠ‹ç˜öúV³½\ÿ¯åññó0æëá1ò( È/Dê¿ä>G†#eÇ ¯¼eó]ÃI3ÔÑÝýd_ïS‰ÒÛÛÛ÷øê¿÷P­×˜³ÃG޼P‚92lŽ1ftôµDç™dÃ-Co«6²˜ƒ¼½,ääÀg@®íÕÒüÐA÷…ï@Ú:4G޼2üJ„ Ë¢$6w_Ú‰Œy Æ`ÙùøŽ¤É´=Òa”1§-c&ξAQ)=^0r"a^yùå— Qò•¡êÍÊæ‡æ Cmã៾ñÓÙ1<üÆäLH¨‡UdžNý‡Z7··ÿ “iK˜M4¬X^[»r]çîA5Ĉ1ãgß(QÎñTÂ"ží¨\”7H¥aJ½’àìÙhÙuóü&e†1­íííê'~äwK¡¡aÅb 1+›ÜÆ3¥‰N{I˜§Ÿ}öÙ'* x$"]$a(dï3²ôX”­óõÅ4æQÊïDY–,cö»)uÔ‘CO{£Ð-÷å@7ÑÑÑÚòüðð‰“y|/ cŒO’Å`~yCay™„Ù»÷É †¬ÙÜÚÒeNªJÉÅy:óoÝü}šB)_(Ï“ƒÙUnƨ!æÙgŸÞÛ×'×þ*’¾¾½Ýí­¬Ì‰Ô˜P¨«Ë­í°1 1$ýç@[zÊԘx›ª”xªo'2=GO¤ƒL(Tjt´oÚ´¦~ÕªU$M¢,Á‰Ìêr6f_fáìJeîÂÌ>ƒA¦§§Xz(%1¦;ÓÖ¶f¡|ì8!æ.\EãÖòÕ«7”1t#·›Mÿ›^…rñÂ}O±1-=»Ž¦Ó²PŒŸS©±3“Yx±Ä1!¦Þ¶iÍš††‡VcŒé?ê4fã¿”(ÇTý`Ìˇ=AÆ\Ze~ û7‹B±vt0æqÓ˜cƒŠf£êàøÓ;v|YžX_]„þ¸:Ó¶iMÃÚWoètóæ¢ýÄs 2˜·rýÔõ6fFÕ´YÕÉ%ÙŒé9úóÝÿ½’l¿ø"/6‹ÞT=súÑÛ;»ªê’ꚤ˜5­jÆŽm›ê~p=Œq~JæÍeo¾ùæ)Å[~œñeÌ.>>[ÆtwãÄFÕ»¶«'+Z6¦/£Œ9øóÝÑ+f¿é¤?n BjS$–%` }Æì›]uQõéÄXcz{3ôQÌÕ¶8?‰IÆH§ÄF­ƒ Ͻ1MêÉJ£Z1™ïon]ßÙsðglŒt ~ðGú#é– ¤.E#)cè[Ë0¦FžM2†¾ƒYÿ°Ö˜\½"!× ‘ÖÀEçÇoŒôK±|)º0‰3· ÆÐ÷üýŒ‘Ø{‘k@ëà’óÄ2føÂ3fëFîF:Â鎤W‘Š“7Æç·dÄ ¾ ¹ ´.7oRcé¤?n BªQ\ÊØ‰½ ¹ ´.5.PcÖ:Œ‘~ðGú#é– ¤Ŧl‘Ø{‘kHkà2!5¦H¾L–0gŒ„\ƒZ™ ©1ÒþH Ý„Ô`¨,c$â$Ð:¸À¤¸Ð‘ŽðGú#é– dÿ“BE#!÷"ÖÁÅ%ÇnŒt„/ÒH·!{Ÿ$*È ¹‰´.,IRcî@º%ÙùdQ1ÆHÈ5H upY‰’ãôGÒ-AÈ®'J1FBîE­ƒKJ˜Ô?¤?n Bv<™T†1r i \Nâ¤Æè‘î@º%ÙíäR ÆHÈ5H¤up1É“£Cº#é•@d¯“Lù#!× ÖÁ…‚Ô ÒH·!ûœtÊÞ ¹ ´.¢0L¾1MçäQÁ gŒôGÒ-AÈK€É1&L¯†2FBnиhÑ¢eÃüP"­ 8ÖØÌ÷PÄyƒ"ÓÈÁkl:O·ýºñ1~֤ČáÎDº%Ù!£zÎÞ¾Y dL½Â ¹ÁñÆfÜ6.z!ÇCñõ òñÆ=¿Þ誻úÁ˜eÃTOu{¤´QˆtK²;¡2I Ws#·hl:©îÞ–Hk Å—+Œù5¤F=¿Ë·ÞÚ–’1Ü-H·!;3ñST dL½šË ¹ÅñF .;<Öx´Ó³±±c˜§A ã[±È çèvQ3EüXc?m…êà~@~³<:â†Ö46áÏþš_Ž-𪦷Õ+=ã<†*×øUT=Bͬ†,ÛJ±•ºÒz5)àÔó“#‡1܈AÈ®l˜Æ˜ý‡P–áØLk L¡ÎcòïÕÆHÌm Ðt ½ÀÆ@Œ5®Çèþ8;Ç_PáæsÄQìþxã.ËkTA4‡õò,[Ä%oÝtîx#Îu¨âŠa Eu£Ø¡ª[Õª"UϨë9ªÿÀFzÌ)•4ÆpŸ"N"{²c3F5›c€{jtá)”1ù÷j 9bKËtè¢ýzã¹Æ#i6©ŸGæ¿1Ò%pW#{q£7ºä : eLþ½Ù˜34<ƒ1ÿø)6cj¢5†Làrr£µe(c¤f¥`L§ß:bKUtÄv`ãàÆó<;F’ÂÏé¸W‚‘}x¡.Dßír3°hcÒ=…3&ß^lÌØÀ"R†Naç1¾i æƒ0†Bn3†Ô6 ZphnÆÏ`‰_À³HPÆ`¸£š+Ím±åÁR]@ý¨Ö¿nÄ|w`#­§×Å鎨Or!»Ð0°h‡¦Ø¡Þán*83&ï^h E™ º¶,WQÔµ2ìLÍÊðxÙVì•’keqÚÈdh#ªÁ]Ö´wX +\¶¤ºOž1|Nˆ[®€-¶TÑ&«\žRsލ ¥)‰¢5Fú#6"Ùj 5Ýn 5±§j^ fLÞ½É ´ÏÊÞ>®£;ÿc‹bL© 1Fú#é– ¤øÒ¤`ÆäMc$Ò&–1¼uÔ,ÍeLÌ!þ7FúÃé– ¤ðR¥Œ‘HÛ0ás!Ó-YRÐÙRc‚PŒ”]²”¿1h¼iqI @º%)¹„)wc$Ð:xÃb“ã‹tKRnISæÆH¤5ðfÅ'5Æé–@¤ØÒ¦¬‘@ëà­&Ô=Ò-AH¡¥N#ÖÁÛL ©1:¤[‚"KŸ²5F­ƒ·˜$Rc¼H·!–•g ¯Ÿ4RcÜH·"å•g ¯žX»rƒÕåb Nýa ”ioïÎd2?¨PÚÛ¿_ßúŒéé?š1á8AfhˆŽ¦Ý”IæF; ³¼¶veSçþAé21fâüÉáŸ<eZ߯Xêë7¯}hõê [v™=”’LËøhJ‡Ó„S£¾þ{k1'[‰IYÙ3~ò—ÃÏ÷P\™‡þ^Eòðíkzpõêu<)K æ£êhšpn<üðÚµa„¡!Æêr1fâäIÓÓ‚À¬_ûP¥ò t0:yˆI äBr)ž Ôf]“bÊ̘ñ“'H™ž–õë×SZU,ë6lèìÙŸ1À”½P¹AS2Æê²1fâ4”yaéܲ¬«H6@— [:wõL‡˜ŒcÂÊ 764mïìßmëò1füôë?>ØOqéÜR©lïì„/û¦CLh2Ü¿+ñÜØ¾Òïìò1£Ìë'~vôàþ~°«B¡¶qÿ¤ÂD‡ÓÃGRø’Ì *n·«?ÊʘÓ'_ÿùϬhŽþ´tN Ο"7ÜýQNÆP\^ÒT6hbêKt –®þ(/c(.™ †Z(M‰DarÃÝåf  &T2ÒÌ”HEŠ6(CcRR&‘Ô˜””(¤Æ¤¤„gbâÕOEöLëŸIEND®B`‚thrift-0.19.0/doc/images/credfull.png0000644000000000000000000000204114303740367017423 0ustar00rootroot00000000000000‰PNG  IHDRàw=ø pHYs  šœÓIDATHÇÕ–Ï‹•UÇ?÷Þ¹wî½Î¤ã8£æFrrF‚`µ‹VBÜ(Zý FJ$Eê"ÝD‹Z)D†Cу̀«J,ÄwgtæÞ¹÷}Ï{~>-Î;NrÓ…‹^8¼/x>çûý>眷 "<ΧÈc~ú49òpI‚¼*!4‚÷ãâÂNïÁº‹ÞØKÞºÓÁ¸ŸÆ}éW«QXÍ¢ù“‡ÇEäDeÇË»û‡†)Uúé«Õ!L{Ó^¤ó÷%–.ž¿à­{û™£'.=4`îëCû@ެÙÓ¨Uö¢¤s1újÊe ë6Ðn^cæçï•·îàóŸwü?³_}ôi}×Þ÷jF),Î#ÝÛˆÓàb-ƒhh ÖP"<¹•ù‹SÜ:öèî“¿ì_0óÅoTŸ{åÛ'F6n7Áv ð>·1r€è,Ò¶\šd~òÜ›/MLêé¢ëŸ¨çÕªÂÌeHï€Ñ+«5:Ú£3dù{YÍR7}ŽáÑ x•9ûÂÖJ X×èÛ¹¥ÔšCÒ’)D¥¥ˆŠ¥,C2Y†dd TŠtÚT¯_fèéíc>M=mê­Ý[ñé.€ÓˆH´'pq¬‹ƒhÕh“¥ žµ}Eši²øæ€ÓvWÉh‚é‚ww‹Kžîß9Ø{‹«4¬¡^¯2µ§W6›Š&Eºy°Ë ¼G|Ȼȳ1“{ h…XC¹¼Ÿ±¥à´An"­ÎŠ5"àCxX“½—,ÍGa5’,æ> ì¬MÕÚ’Öà<„eq.¾“!&X+DgÑ!´QCó~M«nw|ÐX‚Ê øÜžX—ïk"`Ù&“ÝmáB¹H¢Ä1ÝkQÒ™h͆·ëHÚçVÎÆ \ÞAÖÄ}`õ](ÁC½ÎÜÍ&zÝÎé;­Å×mÛ6ºyý¾-k×зÔ!$*®ÖGËV²ñ B±^ÁÔ«\kqã/Ž7¼¼ûÀ ǧÝýÍ?®;>|jûÆÊ¦j¬oã@¡X)!õ7UÊŸ¿µ pøä¡/œ3ë ãâ91²‘Ý##ëèûK B'5dæfRnÍpx§áå÷GºÑ~¨Jx ¡!1„]ùÔ´®§€_yô+óóWñôû&¿sÐîÆIEND®B`‚thrift-0.19.0/doc/images/cgrn.png0000644000000000000000000000214514303740367016561 0ustar00rootroot00000000000000‰PNG  IHDRàw=øbKGDÿÿÿ ½§“ pHYs  šœtIMEá : ‘fRœòIDATHÇÕ–K¨VUÇû|ûè^»jŠdAé |@$4m˜”A!jA4I0 iQä j8J"ÁIRâ$•Ô7ùŠ›v}|^ï=çì×Z«Á÷u¯òqµ‰ƒ6öyÀÿwÖÚë¿övfƃx4ïõñÈÙµ 5{É”MQuUNnOŸÜ‰X7NûÈ~Ü·6—ù4Ü|):rví*5Ûëxa}Ñ\A³Ù¦Ý (”º,™N:Óã\¾üû!òê»[ŽþÏ€ÃgÖlvî¡¡MR*ÉV“¤D,P¸…kÑnŽqýÆ'N®C²»^;¶ç¾€ÆW¤î•í##‹H®ƒH‰š`&ˆ”HÖˆZB5Ól 1X<Æ…+?ñËÉÓïyó×ó¾ùyõæfk×£#+¨™ÄD2E-‘,¡–0$"&] Àhë)Îüq”ñßÎlù|ë•}}€¯Ž®m;gçǾ¼œÆæNAœÜA »—…Þœ0œ,æûo êŸÞ»=ĻʴnÓ@{ýrkÞ$iEVЛ­&[¨'«'X=+,Ôã­$¹ }då“*¶©Ï!h rE¶SO–@Ö “@’šÜ{gÈÖ}F=XMöj)1³¡ÏupϨÔº‹šPºéSÔæÒÔMQ&âAOŽŠx#ˆ04Yy®k·L OÎJ¸ `=ˆZê®…F²$$*9Ñ+Q 1(dey ôÓ5j™73!CW\39éÑÔ›ÓLåÈÿ–Ö€¹Zåêas©ûÇ Ù fFN†™‘‚!YI±+œ£’“‘5t h†˜‘•‰>€v¼,ËUᮀ¡˜‚fæ ÉˆÉæ¢Èé™N,¡Îým€ã}U”Sypò¢R˜ A•’f”P Õ´àK¡ª”ºB-ä<烬‘„–kЙNûQÊý_›873 Ñ+~F™)…ê¶âKÁWН29G’Ô³e+D¬WÉWLvì‚™íï|¶õÏXå™ÏßDÅ øÅ׉1ú^ë{˜ëGÍÆW;5À;‡v§8o³ÛüAû“¥ccÛ–,YLŠJPßí?NPí® èìý@£…£É•ë·øë†íùnwzûžNVvL\¿uóÒä­÷_6Ü^0º$ŠjÆ™€Z@«(hƒLMu8{Å"ð>ðá=Ûµs®P<¿­¹²=ä¾X4ƳKG‡Ð¢à¡á ¥ªf@#W§„;+^?üi´k!Óùí^TMÀ /t­u›FxѵOÔS2Í,ÞwËüßœ*þ®Yòœ·ÇIEND®B`‚thrift-0.19.0/doc/images/cyel.png0000644000000000000000000000166214303740367016567 0ustar00rootroot00000000000000‰PNG  IHDRàw=ø pHYs  šœdIDATHÇÕ–Oh\UÆ÷ÍÌ›IšÚI*±° ‚D—.ƒ4X-".t-´X©-bÅ…(íεDZȦ….¡[©K¡ÚÒÖ$¤ÅH:i3é›ysÿœãâ¾ÉL2è¦ îã=î÷óïûŒªò(¯„G|•·{)KÇK¨¾È4!LäEõ¼¿Œ÷×Õ¹Y¼?_~u& Â0ƒ$’¥ã¨Î˜êÔË íÅ”ªPÙš¯B^GëW‘•‹—pþýòkg¯ÿgYüì0èWf×C¦: ¶aì-J£`R¨îEî-nüÐÂù•©s§ÿ•@æ?ýÆŒ¼ý‰Ù1vÜM âºÚ1ÄCeÞÜþ™ÿéÛÊ[$Gš‘gÌÈäW@€ hˆ`ÁöØîªÀîIÂÂ%ÂâÏï¤ï]=ÛG~ÿ8Ř?“уãÆ_mƒj$ê!¸XM°àÛ]i:´ò nnæ&¾µ?ýèo»Ù¦ÞO›Úä¸q×À7 ´ŠhÆðÍžg-¤ Ò„[ô#{~Ÿºlºß¦ÎMÓ—ÅhQA‘(ÑF\!Q^$ÅœÃT+à²)àÇMêÜKÈzÜ ¡Ð^7÷@:2ù-àY\¥Mb*àyåaõª+šìz´ *Q’Â\+̳}çAzè²Å6N„ú `ãps÷Á­½®I½‚§+‹¨@¸ À±Új»öwC§J{ª‡K%ߺ@º%ˆÀ’@X…°ÌéÚI=²ýãò£á¯|ÕßáóÊ8i©Æ†C6VJ9šÉ-`/¯·ׯ˜¤Øž,ã¹±a¾/ïa2Ù &$-¦nÇd÷À¯òëÝŒŸ:Å:UU¤EUeÀ<û8•Ùw9ðäN^OK<&¼`W|`ñvƒsožáü­UlQ›¼ê6=øßýUüG\‰ýP±÷IEND®B`‚thrift-0.19.0/doc/install/0000777000000000000000000000000014452237057015327 5ustar00rootroot00000000000000thrift-0.19.0/doc/install/os_x.md0000644000000000000000000000164414303740367016620 0ustar00rootroot00000000000000## OS X Setup The following command install all the required tools and libraries to build and install the Apache Thrift compiler on a OS X based system. ### Install Boost Download the boost library from [boost.org](http://www.boost.org) untar compile with ./bootstrap.sh sudo ./b2 threading=multi address-model=64 variant=release stage install ### Install libevent Download [libevent](http://monkey.org/~provos/libevent), untar and compile with ./configure --prefix=/usr/local make sudo make install ### Building Apache Thrift Download the latest version of [Apache Thrift](/download), untar and compile with ./configure --prefix=/usr/local/ --with-boost=/usr/local --with-libevent=/usr/local ## Additional reading For more information on the requirements see: [Apache Thrift Requirements](/docs/install) For more information on building and installing Thrift see: [Building from source](/docs/BuildingFromSource) thrift-0.19.0/doc/install/README.md0000644000000000000000000000235514452237057016607 0ustar00rootroot00000000000000 ## Basic requirements * A relatively POSIX-compliant *NIX system * Cygwin or MinGW can be used on Windows (but there are better options, see below) * g++ 4.2 * boost 1.56.0 * Runtime libraries for lex and yacc might be needed for the compiler. ## Requirements for building from source * GNU build tools: * autoconf 2.65 * automake 1.13 * libtool 1.5.24 * pkg-config autoconf macros (pkg.m4) * lex and yacc (developed primarily with flex and bison) * libssl-dev ## Requirements for building the compiler from source on Windows * Visual Studio C++ * Flex and Bison (e.g. the WinFlexBison package) ## Language requirements These are only required if you choose to build the libraries for the given language * C++ * Boost 1.56.0 * libevent (optional, to build the nonblocking server) * zlib (optional) * Qt (optional) * Java * Java 17 (latest LTS) * Gradle 8.0.2 * C#: Mono 1.2.4 (and pkg-config to detect it) or Visual Studio 2005+ * Python 2.6 (including header files for extension modules) * PHP 5.0 (optionally including header files for extension modules) * Ruby 1.8 * bundler gem * Erlang R12 (R11 works but not recommended) * Perl 5 * Bit::Vector * Class::Accessor * Haxe 3.1.3 * Go 1.4 * Delphi 2010 thrift-0.19.0/doc/install/debian.md0000644000000000000000000000434714452237057017077 0ustar00rootroot00000000000000## Debian/Ubuntu install The following command will install tools and libraries required to build and install the Apache Thrift compiler and C++ libraries on a Debian/Ubuntu Linux based system. sudo apt-get install automake bison flex g++ git libboost-all-dev libevent-dev libssl-dev libtool make pkg-config Debian 7/Ubuntu 12 users need to manually install a more recent version of automake and (for C++ library and test support) boost: wget http://ftp.debian.org/debian/pool/main/a/automake-1.15/automake_1.15-3_all.deb sudo dpkg -i automake_1.15-3_all.deb wget http://sourceforge.net/projects/boost/files/boost/1.60.0/boost_1_60_0.tar.gz tar xvf boost_1_60_0.tar.gz cd boost_1_60_0 ./bootstrap.sh sudo ./b2 install ## Optional packages If you would like to build Apache Thrift libraries for other programming languages you may need to install additional packages. The following languages require the specified additional packages: * Java * packages: gradle (version 8.0.2) * You will also need Java JDK v1.8 or higher. Type **javac** to see a list of available packages, pick the one you prefer and **apt-get install** it (e.g. default-jdk). * Ruby * ruby-full ruby-dev ruby-rspec rake rubygems bundler * Python * python-all python-all-dev python-all-dbg * Perl * libbit-vector-perl libclass-accessor-class-perl * Php, install * php5-dev php5-cli phpunit * C_glib * libglib2.0-dev * Erlang * erlang-base erlang-eunit erlang-dev rebar * NetStd * apt-transport-https dotnet-sdk-6.0 aspnetcore-runtime-6.0 * Thrift Compiler for Windows * mingw-w64 mingw-w64-x86-64-dev nsis * Rust * rustc cargo * Haxe * haxe * Lua * lua5.3 liblua5.3-dev * NodeJs * nodejs npm * dotnetcore * https://www.microsoft.com/net/learn/get-started/linuxubuntu * d-lang * curl -fsS https://dlang.org/install.sh | bash -s dmd * dart & pub * https://www.dartlang.org/install/linux * https://www.dartlang.org/tools/pub/installing ## Additional reading For more information on the requirements see: [Apache Thrift Requirements](/docs/install) For more information on building and installing Thrift see: [Building from source](/docs/BuildingFromSource) thrift-0.19.0/doc/install/windows.md0000644000000000000000000001774014303740367017346 0ustar00rootroot00000000000000## Windows Setup The Thrift environment consists of two main parts: The Thrift compiler EXE and the language-dependent libraries. Most of these libraries will require some kind of build and/or installation. But regarding the Thrift compiler utility, there are a number of different alternatives. The first one of these alternatives is to download the **pre-built Thrift Compiler EXE** and only build the libraries needed from source, following one of the "Setup from source" methods outlined below. The other two options are to build the Thrift compiler from source. The most recommended way to achieve this is by means of the **Visual Studio C++ build project**. Alternatively, the Thrift compiler can also be built via **Cygwin** or **MinGW** build environments, however this method is not only less comfortable, but more time-consuming and requires much more manual effort. ## Prebuilt Thrift compiler The windows Thrift compiler is available as a prebuilt exe available [here](/download). Note that there is no installation tool, rather this EXE file *is* already the Thrift compiler utility. Download the file and put it into some suitable location of your choice. Now pick one of the "Build and install target libraries" below to continue. ## Setup from source via Visual Studio C++ (recommended) ### Requirements Thrift's compiler is written in C++ and designed to be portable, but there are some system requirements. Thrift's runtime libraries are written in various languages, which are also required for the particular language interface. * Visual Studio C++, any recent version should do * Flex and Bison, e.g. the WinFlexBison package * [Apache Thrift Requirements](/docs/install) ### Build and install the compiler After all requirements are in place, use the `compiler/cpp/compiler.vcxproj` build project to build the Thrift compiler. Copy the resulting EXE file to a location of your choice. ### Build and install target libraries A few of the target language libraries also do provide Visual Studio project files, such as C++ and C#. These are located in the `lib//` folders. Most of the language packages must be built and installed manually using build tools better suited to those languages. Typical examples are Java, Ruby, Delphi, or PHP. Look for the `README.md` file in the `lib//` folder for more details on how to build and install each language's library package. ## Setup from source via Cygwin ### Requirements Thrift's compiler is written in C++ and designed to be portable, but there are some system requirements. Thrift's runtime libraries are written in various languages, which are also required for the particular language interface. * Cygwin or MinGW * [Apache Thrift Requirements](/docs/install) ### Installing from source If you are building from the first time out of the source repository, you will need to generate the configure scripts. (This is not necessary if you downloaded a tarball.) From the top directory, do: ./bootstrap.sh Once the configure scripts are generated, thrift can be configured. From the top directory, do: export CXXFLAGS="-D PTHREAD_MUTEX_RECURSIVE_NP=PTHREAD_MUTEX_RECURSIVE" ./configure Setting the CXXFLAGS environmental variable works around compile errors with PTHREAD_MUTEX_RECURSIVE_NP being undeclared, by replacing it with the newer, portable PTHREAD_MUTEX_RECURSIVE. (Tested on cygwin 20100320, Thrift r760184, latest pthread.) **Optional:** You **may not** be able to make from the root Thrift directory due to errors (see below to resolve). To make the compiler only, change to the compiler directory before running make: cd compiler/cpp Now make the thrift compiler (& runtime libraries if make is run from the thrift root directory): make make install ### Build and install target libraries Some language packages must be installed manually using build tools better suited to those languages. Typical examples are Java, Ruby, or PHP. Look for the README file in the `lib//` folder for more details on the installation of each language library package. ### Possible issues with Cygwin install See also Possible issues with MinGW install. #### Syntax error in ./configure The following error occurs for some users when running ./configure: ./configure: line 21183: syntax error near unexpected token `MONO,' ./configure: line 21183: ` PKG_CHECK_MODULES(MONO, mono >= 1.2.6, have_mono=yes, have_mono=no)' To resolve this, you'll need to find your pkg.m4 (installed by the pkg-config package) file and copy it to the thrift/aclocal directory. From the top-level thrift directory, you can copy the file by running cp /usr/share/aclocal/pkg.m4 aclocal Finally, re-run ./bootstrap.sh and ./configure. (Note that pkg.m4 is created by the pkg-config tool. If your /usr/share/aclocal directory doesn't contain the pkg.m4 file, you may not have pkg-config installed.) #### Installing perl runtime libraries Sometimes, there will be an error during the install of the perl libraries with chmod. A workaround is to avoid installing the perl libraries if they are not needed. If you don't need perl, run configure with --without-perl. If you need perl, and are happy to manually install it, replace the contents of thrift/lib/perl/Makefile with the following, after building thrift: TODO #### Linking to installed C++ runtime libraries Sometimes, the installed libthrift.a will not link using g++, with linker errors about missing vtables and exceptions for Thrift classes. A workaround is to link the compiled object files directly from your Thrift build, corresponding to the missing classes. This can be implemented in a Makefile using the following lines: THRIFT_O=/thrift/lib/cpp LTHRIFT=$(THRIFT_O)/Thrift.o $(THRIFT_O)/TSocket.o $(THRIFT_O)/TBinaryProtocol.o $(THRIFT_O)/TBufferTransports.o Then linking using $(LTHRIFT) instead of -lthrift. TODO - diagnose the issue further #### C++ runtime segfault with cygwin 1.7.5-1, g++-4.3.4, fork() and throw If your thrift C++ programs segfault on throw after fork()ing, compile them with g++-3. The issue and patch are described on the Cygwin mailing list at http://cygwin.com/ml/cygwin/2010-05/msg00203.html This issue should be fixed in Cygwin versions after 1.7.5-1, or g++ 4.5.0. ## Setup from source via MinGW ### Requirements To compile the Thrift generator & runtime libraries (untested) without the cygwin.dll dependency you need to install MinGW (www.mingw.org). * MinGW * [Apache Thrift Requirements](/docs/install) In addition, you need to add the following entry to your windows PATH variable. C:\MINGW\BIN Next, open compiler/cpp/Makefile.am and add the following line to thrift_CXXFLAGS -DMINGW -mno-cygwin -lfl Run bootstrap.sh: ./bootstrap.sh Make sure you have java in your $PATH variable, if not do(adjust path if necessary): export PATH=$PATH:"/cygdrive/c/program files/java/jre1.8.0_191/bin" Run configure - using CXXFLAGS to work around an issue with an old pthreads define (untested on MinGW - works on Cygwin): export CXXFLAGS="-D PTHREAD_MUTEX_RECURSIVE_NP=PTHREAD_MUTEX_RECURSIVE" ./configure ''Optional:'' To make the compiler only, change to the compiler directory before running make: cd compiler/cpp Run make: mingw32-make.exe ### Possible issues with MinGW install See also Possible issues with Cygwin install, including the discussion about PTHREAD_MUTEX_RECURSIVE_NP. #### yywrap is not found Make sure you add -lfl in your cxxflags in Makefile, also try adding -Lc:/cygwin/libs #### boost is not found Try and change the include dir to use the windows path from c like this: Edit compiler/cpp/Makefile, look for the declaration of BOOST_CPPFLAGS, change that line for BOOST_CPPFLAGS = -Ic:/cygwin/usr/include/boost-1_53_0 #### realpath is not found add -DMINGW -mno-cygwin to the CXXDEFS variable in Makefile ## Additional reading For more information on the requirements see: [Apache Thrift Requirements](/docs/install) For more information on building and installing Thrift see: [Building from source](/docs/BuildingFromSource) thrift-0.19.0/doc/install/centos.md0000644000000000000000000000431714303740367017143 0ustar00rootroot00000000000000# Building Apache Thrift on CentOS 6.5 Starting with a minimal installation, the following steps are required to build Apache Thrift on Centos 6.5. This example builds from source, using the current development master branch. These instructions should also work with Apache Thrift releases beginning with 0.9.2. ## Update the System sudo yum -y update ## Install the Platform Development Tools sudo yum -y groupinstall "Development Tools" ## Upgrade autoconf/automake/bison sudo yum install -y wget ### Upgrade autoconf wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz tar xvf autoconf-2.69.tar.gz cd autoconf-2.69 ./configure --prefix=/usr make sudo make install cd .. ### Upgrade automake wget http://ftp.gnu.org/gnu/automake/automake-1.14.tar.gz tar xvf automake-1.14.tar.gz cd automake-1.14 ./configure --prefix=/usr make sudo make install cd .. ### Upgrade bison wget http://ftp.gnu.org/gnu/bison/bison-2.5.1.tar.gz tar xvf bison-2.5.1.tar.gz cd bison-2.5.1 ./configure --prefix=/usr make sudo make install cd .. ## Add Optional C++ Language Library Dependencies All languages require the Apache Thrift IDL Compiler and at this point everything needed to make the IDL Compiler is installed (if you only need the compiler you can skip to the Build step). If you will be developing Apache Thrift clients/servers in C++ you will also need additional packages to support the C++ shared library build. ### Install C++ Lib Dependencies sudo yum -y install libevent-devel zlib-devel openssl-devel ### Upgrade Boost >= 1.56 wget http://sourceforge.net/projects/boost/files/boost/1.56.0/boost_1_56_0.tar.gz tar xvf boost_1_56_0.tar.gz cd boost_1_56_0 ./bootstrap.sh sudo ./b2 install ## Build and Install the Apache Thrift IDL Compiler git clone https://github.com/apache/thrift.git cd thrift ./bootstrap.sh ./configure --with-lua=no make sudo make install This will build the compiler (thrift/compiler/cpp/thrift --version) and any language libraries supported. The make install step installs the compiler on the path: /usr/local/bin/thrift You can use the ./configure --enable-libs=no switch to build the Apache Thrift IDL Compiler only without lib builds. To run tests use "make check". thrift-0.19.0/doc/ReleaseManagement.md0000644000000000000000000006103614303740367017560 0ustar00rootroot00000000000000# Apache Thrift Release Management Instructions for preparing and distributing a release of Apache Thrift are fairly complex. These procedures are documented here, and we're working to automate as much of this as possible. There are few projects like ours that integrate with 28 programming languages. Given the extreme number of package management systems that Apache Thrift integrates with (compared to perhaps any), part of the burden of releasing Apache Thrift is to manually package and upload some of these [language-specific packages](http://thrift.apache.org/lib). It is important to note here that Apache Thrift is designed for version interoperability, so one can use a version 0.7.0 client with a 0.12.0 server. A particular version number does not make any guarantees as to the features available in any given language. See the [Language Feature Matrix](https://github.com/apache/thrift/blob/master/LANGUAGES.md) to learn more. ## Concepts ### Versioning Apache Thrift and the vast majority of package management systems out there conform to the [SemVer 2.0](https://semver.org/spec/v2.0.0.html) version numbering specification. Apache Thrift uses the following versioning rules: - *major* is currently always zero; - *minor* is increased for each release cycle; - *patch* is increased for patch builds between release cycles to address critical defect, security, or packaging issues Further, if there are only packaging changes for a single third-party distribution point to correct an issue, the major.minor.patch may remain the same while adding a suffix compatible with that distribution point, for example, "0.12.0.1" for nuget, or "0.12.0-1" for maven. #### External Package Patches It is common to have language-specific critical defects or packaging errors that need to be resolved between releases of Apache Thrift. The project handles these on a case-by-case basis for languages that have their own [package management systems](http://thrift.apache.org/lib). When a language-specific patch is made, the patch level of the distribution pushed to the external package manager is bumped. As such, there may be cases between Apache Thrift releases where there are (for example) a `0.12.1` and `0.12.2` version of a Haskell Hackage package, and perhaps also a `0.12.3` version of a dlang dub package. You will not find a tag or an official project release in these cases, however, the code changes will be reflected in the release branch and in master. In these cases we would not release a version of Apache Thrift nor would we refresh all the external language packages. #### Version in the master branch The master branch will always contain the next anticipated release version. When a release cycle begins, a branch is cut from master. The release branch will already have all of the correct versions, and therefore release branches can be easily merged back into master. (This was not true of releases before 0.12.0). ### Code Repository The authoritative repository for Apache Thrift is stored in [GitHub](https://github.com/apache/thrift). It is mirrored by [GitBox](https://gitbox.apache.org/repos/asf?p=thrift.git). ### Branches All code (submitted via pull request or direct push) is committed to the `master` branch. Until version 1.0 of Apache Thrift each release branch was named ``, for example in version `0.12.0` there is a branch named the same. For version 1.0 releases any beyond, releases will have a branch named `release/`. ### Tags Up to version `0.12.0` each release of Apache Thrift was tagged with a `` tag. Starting with the `0.12.0` release, each release of Apache Thrift will be tagged with a `v` tag to satisfy external package management tools (such as ones for dlang and golang). For example the tag of version `0.12.0` is `v0.12.0`. ## Release Procedures ### Release Schedule Apache Thrift has no official release schedule, however the project aims to release at least twice per year. A complete release cycle will take about 1 week to complete, if things go well, with half of that time waiting for a vote. ### Release Manager Before a release cycle begins, someone must nominate themselves on the development mailing list as the release manager for that release. In order to be a release manager you must meet the following criteria: 1. You are a [member](http://people.apache.org/phonebook.html?pmc=thrift) of the Apache PMC group. 1. Your profile at https://id.apache.org/ is valid and contains a PGP key. If it does not, see the [Apache OpenPGP Instructions](https://www.apache.org/dev/openpgp.html). If your PGP private key creation seems to hang indefinitely while creating entropy, try these fixes: - Generate disk I/O with: `dd if=/dev/sda of=/dev/zero` - Install the `rng-tools` package. 1. Your PGP key is visible in the [Apache Committer Keys](http://people.apache.org/keys/committer/) for code signing. This list is updated periodically from your Apache ID (see previous step). 1. You have read and agree with the contents of the [ASF Release Distribution Policy](https://www.apache.org/dev/release-distribution.html). 1. You have access and the ability to use subversion. All distribution artifacts are released through a subversion commit. 1. You can build in the Linux Docker Container, and you have Visual Studio 2017. 1. You have sufficient time to complete a release distribution. ### Release Candidate All Apache Thrift releases go through a 72-hour final release candidate voting procedure. Votes from members of the Apache Thrift PMC are binding, and all others are non-binding. For these examples, the `master` branch is at version 1.0.0 and that is the next release. 1. Scrub the Apache Jira backlog. There are a couple things to do: 1. [Open Issues without a Component](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20status%20!%3D%20Closed%20and%20component%20is%20empty) - make sure everything has an assigned component, as the release notes are grouped together by language. 1. [Open Issues with a Fix Version](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20status%20in%20(OPEN%2C%20%27IN%20PROGRESS%27%2C%20REOPENED)%20and%20fixVersion%20is%20not%20empty) - these will be issues that someone placed a fixVersion on in Jira, but have not been resolved or closed yet. They are likely stale somehow. Resolutions for these issues include resolving or closing the issue in Jira, or simply removing the fixVersion if the issue hasn't been fixed. 1. [Open Blocking Issues](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20priority%20in%20(blocker)%20and%20status%20not%20in%20(closed)%20order%20by%20component%20ASC) - blocking issues should block a release. Scrub the list to see if they are really blocking the release, and if not change their priority. 1. [Open Critical Issues](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20priority%20in%20(critical)%20and%20status%20not%20in%20(closed)%20and%20type%20not%20in%20(%22wish%22)%20order%20by%20component%20ASC) - this list will end up in the known critical issues list in the changes file. Scrub it to make sure everything is actually critical. It is healthy to scrub these periodically, whether or not you are making a new release. 1. Check that the version number in the `master` branch matches the version number of the upcoming release. To check the `master` branch version, run: ```bash thrift$ grep AC_INIT configure.ac | cut -d'[' -f3 | cut -d']' -f1 1.0.0 ``` If it does not match (this should be extremely rare), you need to submit a pull request setting the `master` branch to the desired version of the upcoming release. In the following example, we prepare to commit a branch where the version number is changed from `1.0.0` to `1.1.0`: ```bash thrift$ git checkout -b fix-version-for-release thrift$ build/veralign.sh 1.0.0 1.1.0 # check to see if any of the manually modified files needs changes thrift$ git push ... # make a pull request ``` 1. Create a release branch for the release, in this example `1.0.0`: ```bash thrift$ git checkout master thrift$ git pull thrift$ git checkout -b "release/1.0.0" thrift$ git push ``` Now there is a `release/1.0.0` branch in GitHub for Apache Thrift. By creating a release branch we allow work to continue on the `master` branch for the next release while we finalize this one. Note that `release/1.0.0` and `master` in this example are now identical, and therefore it is possible to merge the release branch back into `master` at the end of the release! 1. Modify these files manually, inserting the release into them at the appropriate location. Follow existing patterns in each file: - `doap.rdf` - `debian/changelog` 1. Generate the content for `CHANGES.md` - this is one of the most time-consuming parts of the release cycle. It is a lot of work, but the result is well worth it to the consumers of Apache Thrift: 1. Find all [Issues Fixed but not Closed in 1.0.0](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20thrift%20and%20fixVersion%20%3D%201.0.0%20and%20status%20!%3D%20closed) (adjust the version in the link to suit your needs). 1. Export the list of issues to a CSV (Current Fields) and open in Excel (or a similar spreadsheet). 1. Hide all columns except for the issue id (i.e. THRIFT-nnnn), the component (first one), and the summary. 1. Sort by component ascending and then by id ascending. 1. Create a fourth column that will contain the contents of each line that goes into the release notes. Once you have the formula working in one cell paste it into the other rows to populate them. Use a formula to get the column to look like this: ```vcol Issue Component Summary RelNote THRIFT-123 C++ - Library Drop C++03 [THRIFT-123](https://issues.apache.org/jira/browse/THRIFT-3978) - Drop C++03 ``` For example, if the row above was row "B" in EXCEL it would look something like: ```text =CONCAT("[", B1, "]", "https://issues.apache.org/jira/browse/", B1, " - ", B3) ``` 1. Create a level 3 section in `CHANGES.md` under the release for each component and copy the items from the RelNote column into the changes file. 1. Find all [Open Critical Issues](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20priority%20in%20(critical)%20and%20status%20not%20in%20(closed)%20and%20type%20not%20in%20(%22wish%22)%20order%20by%20component%20ASC) and add them to `CHANGES.md` in the list of known critical issues for the release. 1. Commit all changes to the release branch. 1. Generate the source tarball. 1. On a linux system get a clean copy of the release branch, for example: ```bash ~$ git clone -b "release/1.0.0" git@github.com:apache/thrift.git thrift-1.0.0-src ``` 1. In the clean copy of the release branch, start a docker build container and run `make dist`: ```code ~$ cd thrift-1.0.0-src ~/thrift-1.0.0-src$ docker run -v $(pwd):/thrift/src:rw \ -it thrift/thrift-build:ubuntu-bionic /bin/bash root@8b4101188aa2:/thrift/src# ./bootstrap.sh && ./configure && make dist ``` The result will be a file named `thrift-1.0.0.tar.gz`. Check the size and make sure it is roughly 4MB. It could get larger over time, but it shouldn't jump by orders of magnitude. Once satisfied you can exit the docker container with `exit`. 1. Generate signatures and checksums for the tarball: ```bash gpg --armor --output thrift-1.0.0.tar.gz.asc --detach-sig thrift-1.0.0.tar.gz md5sum thrift-1.0.0.tar.gz > thrift-1.0.0.tar.gz.md5 sha1sum thrift-1.0.0.tar.gz > thrift-1.0.0.tar.gz.sha1 sha256sum thrift-1.0.0.tar.gz > thrift-1.0.0.tar.gz.sha256 1. Generate the Windows Thrift Compiler. This is a statically linked compiler that is portable and folks find it useful to be able to download one, especially if they are using third-party distributed runtime libraries for interpreted languages on Windows. There are two ways to generate this: - Using a Development VM 1. On a Windows machine with Visual Studio, pull down the source code and checkout the release branch. 1. Open an x64 Native Tools Command Prompt for VS 2017 and create an out-of-tree build directory. 1. Install the latest version of cmake. 1. Install chocolatey and install winflexbison with chocolatey. 1. Run cmake to generate an out-of-tree build environment: ```cmd C:\build> cmake ..\thrift -DBISON_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DFLEX_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe -DWITH_MT=ON -DWITH_SHARED_LIB=OFF -DWITH_CPP=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DBUILD_TESTING=OFF -DBUILD_TUTORIALS=OFF -DBUILD_COMPILER=ON C:\build> cmake --build . --config Release ``` - Using [Docker for Windows](../build/docker/msvc2017/README.md), follow the instructions for building the compiler. - In both cases: 1. Verify the executable only depends on kernel32.dll using [depends.exe](http://www.dependencywalker.com/). 1. Copy the executable `thrift.exe` to your linux system where the signed tarball lives and rename it to `thrift-1.0.0.exe` (substitute the correct version, of course). 1. Sign the executable the same way you signed the tarball. 1. Upload the release artifacts to the Apache Dist/Dev site. This requires subversion: ```bash ~$ mkdir -p dist/dev ~$ cd dist/dev ~/dist/dev$ svn co "https://dist.apache.org/repos/dist/dev/thrift" thrift ~/dist/dev$ cd thrift ``` Copy the tarball, windows compiler executable, and 8 additional signing files into a new directory for the release: ``` bash ~/dist/dev/thrift$ mkdir 1.0.0-rc0 # copy the files into the directory ~/dist/dev/thrift$ svn add 1.0.0-rc0 ``` The layout of the files should match the [current release](https://www.apache.org/dist/thrift/). Once done, add the release candidate and check it in: ```bash ~/dist/dev/thrift$ svn status # verify everything is correct ~/dist/dev/thrift$ svn commit -m "Apache Thrift 1.0.0-rc0 in dist dev" \ --username --password ``` 1. Verify the release candidate artifacts are available at: [https://dist.apache.org/repos/dist/dev/thrift/](https://dist.apache.org/repos/dist/dev/thrift/) 1. Send a voting announcement message to `dev@thrift.apache.org` following this template as a guide: ```code To: dev@thrift.apache.org Subject: [VOTE] Apache Thrift 1.0.0-rc0 release candidate --- All, I propose that we accept the following release candidate as the official Apache Thrift 1.0.0 release: https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.tar.gz The release candidate was created from the release/1.0.0 branch and can be cloned using: git clone -b release/1.0.0 https://github.com/apache/thrift.git The release candidates GPG signature can be found at: https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.tar.gz.asc The release candidates checksums are: md5: sha1: sha256: A prebuilt statically-linked Windows compiler is available at: https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.exe Prebuilt statically-linked Windows compiler GPG signature: https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.exe.asc Prebuilt statically-linked Windows compiler checksums are: md5: sha1: sha256: The source tree as ZIP file to be published via Github releases: https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.zip ZIP source tree GPG signature: https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.zip.asc ZIP source tree checksums are: md5: sha1: sha256: The CHANGES list for this release is available at: https://github.com/apache/thrift/blob/release/1.0.0/CHANGES.md Please download, verify sig/sum, install and test the libraries and languages of your choice. This vote will close in 72 hours on 2019-07-06 21:00 UTC [ ] +1 Release this as Apache Thrift 1.0.0 [ ] +0 [ ] -1 Do not release this as Apache Thrift 1.0.0 because... ``` 1. If any issues are brought up with the release candidate, you will need to package another and reset the voting clock. Voting on the development mailing list provides additional benefits (wisdom from [Christopher Tubbs](https://issues.apache.org/jira/browse/THRIFT-4506?focusedCommentId=16791902&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-16791902)): - It creates a public record for the vote, - It allows for participation/evaluation from our wider user audience (more diversity in evaluators improves quality), and - It provides more entry points for potential future committers/PMC members to earn merit through participation. ### Official Release 1. Send a message to `dev@thrift.apache.org` with the voting results. Use this template as a guide: ```code To: dev~thrift.apache.org Subject: [VOTE][RESULT] Release Apache Thrift 1.0.0 --- All, Including my own vote of +1 we have N binding +1 and no -1. The vote for the Apache Thrift 1.0.0 release is ***successful***. Thank you to all who helped test and verify. ``` 1. Use svn to checkout the release part of thrift (similar to dev) and copy the files over from dev, matching the previous release structure: ```bash ~$ mkdir -p dist/release ~$ cd dist/release ~/dist/release$ svn co "https://dist.apache.org/repos/dist/release/thrift" thrift ~/dist/release$ cd thrift ~/dist/release/thrift$ mkdir 1.0.0 ~/dist/release/thrift$ cp -p ../../dev/thrift/1.0.0-rc0/* 1.0.0/ ~/dist/release/thrift$ svn status # verify everything is correct ~/dist/release/thrift$ svn commit -m "Apache Thrift 1.0.0 official release" \ --username --password ``` **NOTE** Once you check-in, you need to wait about a day for all the mirrors to update. You cannot send the announcement email or update the web site until the mirrors are updated. 1. Create and push a tag for the release, for example "v1.0.0". **NOTE:** All new releases must have the "v" prefix to satisfy third-party package managers (dlang dub, golang, etc..) **NOTE:** You **should** [sign the release tag](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work). Since you already have a GPG signing key for publishing the Apache Release, you want to [upload that key to your GitHub account](https://help.github.com/en/articles/adding-a-new-gpg-key-to-your-github-account). Once the key is known by GitHub you can sign the tag. ```bash ~/thrift$ # make sure you are on the release branch ~/thrift$ git checkout release/1.0.0 ~/thrift$ git pull ~/thrift$ git tag -s v1.0.0 -m "Version 1.0.0" ~/thrift$ git push --tags ``` **NOTE:** If you get the error "gpg failed to sign the data" when tagging, try this fix: ```export GPG_TTY=$(tty)```. Alternatively, it may be necessary to specify the ```-u ``` as an additional argument. 1. Create a new release from the [GitHub Tags Page](https://github.com/apache/thrift/tags). Attach the statically built Windows thrift compiler as a binary here. 1. Merge the release branch into master. This ensures all changes made to fix up the release are in master. ```bash ~/thrift$ git checkout master ~/thrift$ git pull ~/thrift$ git merge release/1.0.0 ``` The merge of 1.0.0 into master should proceed as a fast-forward since the 1.0.0 release branch. If there are discrepancies the best thing to do is resolve them and then submit a pull request. This pull request must be *MERGED* and not *REBASED* after the CI build is successful. You may want to do this yourself and mark the pull request as `[DO NOT MERGE]`. 1. Update the web site content to include the new release. The repository is located at https://github.com/apache/thrift-website and there are plenty of instructions how to update both staging and live web site. With regard to the release, its actually quite simple: check out the main branch and edit two lines in _config.yml, then commit. The build bot will update staging. After checking everything is right, simply fast-forward "asf-site" to "asf-staging" and push, then production site will automatically get updated as well 1. Make an announcement on the dev@ and user@ mailing lists of the release. There's no template to follow, but you can point folks to the official web site at https://thrift.apache.org, and to the GitHub site at https://github.org/apache.thrift. ### Post-Release 1. Visit https://reporter.apache.org/addrelease.html?thrift and register it. You will get an automated reminder as the one who committed into dist. This informs the Apache Board of Directors of releases through project reports. 1. Create a local branch to bump the release number to the next anticipated release: ```bash ~/thrift$ git checkout -b bump-master ~/thrift$ build/veralign.sh 1.0.0 1.1.0 ``` The veralign script will set the version number in all of the language packaging files and headers. You do not need to worry about the manually modified files at this time. You should however ensure everything is correct by looking at the diff. 1. Create a pull request to advance master to the next anticipated release. 1. In Apache Jira, select all tickets where the fix version is the release and the status is not closed ([example](https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20fixVersion%20%3D%201.0%20%20and%20status%20!%3D%20Closed)) and use the bulk editing tool to close them. 1. **FIXME** Ask someone with admin access to Apache Jira to change the fixVersion in question from unreleased to released, for example: https://issues.apache.org/jira/browse/THRIFT-4686 1. Ensure that the [Jira release page](https://issues.apache.org/jira/projects/THRIFT?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page&status=unreleased) for the version has the same number of issues in the version as issues done, and that there are no issues in progress and no issues to do, and no warnings. Finally, mark it as released and set the date of the release. * [Report any CVEs](https://apache.org/security/committers.html) that were fixed. You can email `security@apache.org` if you are not sure if there are any CVEs to report. #### Third Party Package Managers See https://thrift.apache.org/lib/ for the current status of each external package manager's distribution. The information below is from the 0.12.0 release: > This section needs to be updated with detailed instructions for each language, or pointers to the README.md files in each language directory with detailed release instructions for the given package management system. * [dart] Releasing this requires a google account. * You will need to install the same version of dart that is used in the docker image. * Go into lib/dart and run "pub publish --dry-run" and resolve any warnings. * Run "pub publish" and go through the google account authorization to allow it. * [dlang] Within a day, the dlang dub site https://code.dlang.org/packages/apache-thrift?tab=info should pick up the release based on the tag. No action is needed. * [npmjs] @jfarrell is the only one who can do this right now. https://issues.apache.org/jira/browse/THRIFT-4688 * [perl] A submission to CPAN is necessary (normally jeking3 does this): * Checkout the release branch or tag on a linux system. * Fire up the docker build container. * Run "make clean" and remove any gen-perl directories. * Inside `lib/perl` run the script `build-cpan-dist.sh`. * Upload the resulting package. If there's a mistake that needs to be corrected, increase the suffix. (_1, _2, ...) and upload another. You cannot replace a release on CPAN. * [php] @jfarrell, @bufferoverflow, @jeking3 are the only ones who can do this right now. * Once the release is tagged, one just has to hit the "Update" button to pick it up. * [pypi] @jfarrell is the only one who can do this right now. https://issues.apache.org/jira/browse/THRIFT-4687 * [rust] Any thrift project committer is allowed to upload a new crate. If you have any questions email `dev@thrift.apache.org`. thrift-0.19.0/README.md0000644000000000000000000001573714370300523014370 0ustar00rootroot00000000000000Apache Thrift ============= Introduction ============ Thrift is a lightweight, language-independent software stack for point-to-point RPC implementation. Thrift provides clean abstractions and implementations for data transport, data serialization, and application level processing. The code generation system takes a simple definition language as input and generates code across programming languages that uses the abstracted stack to build interoperable RPC clients and servers. ![Apache Thrift Layered Architecture](doc/images/thrift-layers.png) Thrift makes it easy for programs written in different programming languages to share data and call remote procedures. With support for [28 programming languages](LANGUAGES.md), chances are Thrift supports the languages that you currently use. Thrift is specifically designed to support non-atomic version changes across client and server code. This allows you to upgrade your server while still being able to service older clients; or have newer clients issue requests to older servers. An excellent community-provided write-up about thrift and compatibility when versioning an API can be found in the [Thrift Missing Guide](https://diwakergupta.github.io/thrift-missing-guide/#_versioning_compatibility). For more details on Thrift's design and implementation, see the Thrift whitepaper included in this distribution, or at the README.md file in your particular subdirectory of interest. Status ====== | Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website | | :----- | :----- | :------- | :------------ | :--------- | :------ | | [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://api.travis-ci.com/apache/thrift.svg?branch=master)](https://app.travis-ci.com/apache/thrift/branches) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) | | [`0.17.0`](https://github.com/apache/thrift/tree/0.17.0) | [![Build Status](https://api.travis-ci.com/apache/thrift.svg?branch=0.17.0)](https://app.travis-ci.com/apache/thrift/branches) | | | | | Releases ======== Thrift does not maintain a specific release calendar at this time. We strive to release twice yearly. Download the [current release](http://thrift.apache.org/download). License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Project Hierarchy ================= thrift/ compiler/ Contains the Thrift compiler, implemented in C++. lib/ Contains the Thrift software library implementation, subdivided by language of implementation. cpp/ go/ java/ php/ py/ rb/ ... test/ Contains sample Thrift files and test code across the target programming languages. tutorial/ Contains a basic tutorial that will teach you how to develop software using Thrift. Development =========== To build the same way Travis CI builds the project you should use docker. We have [comprehensive building instructions for docker](build/docker/README.md). Requirements ============ See http://thrift.apache.org/docs/install for a list of build requirements (may be stale). Alternatively, see the docker build environments for a list of prerequisites. Resources ========= More information about Thrift can be obtained on the Thrift webpage at: http://thrift.apache.org Acknowledgments =============== Thrift was inspired by pillar, a lightweight RPC tool written by Adam D'Angelo, and also by Google's protocol buffers. Installation ============ If you are building from the first time out of the source repository, you will need to generate the configure scripts. (This is not necessary if you downloaded a tarball.) From the top directory, do: ./bootstrap.sh Once the configure scripts are generated, thrift can be configured. From the top directory, do: ./configure You may need to specify the location of the boost files explicitly. If you installed boost in `/usr/local`, you would run configure as follows: ./configure --with-boost=/usr/local Note that by default the thrift C++ library is typically built with debugging symbols included. If you want to customize these options you should use the CXXFLAGS option in configure, as such: ./configure CXXFLAGS='-g -O2' ./configure CFLAGS='-g -O2' ./configure CPPFLAGS='-DDEBUG_MY_FEATURE' To enable gcov required options -fprofile-arcs -ftest-coverage enable them: ./configure --enable-coverage Run ./configure --help to see other configuration options Please be aware that the Python library will ignore the --prefix option and just install wherever Python's distutils puts it (usually along the lines of `/usr/lib/pythonX.Y/site-packages/`). If you need to control where the Python modules are installed, set the PY_PREFIX variable. (DESTDIR is respected for Python and C++.) Make thrift: make From the top directory, become superuser and do: make install Uninstall thrift: make uninstall Note that some language packages must be installed manually using build tools better suited to those languages (at the time of this writing, this applies to Java, Ruby, PHP). Look for the README.md file in the lib// folder for more details on the installation of each language library package. Package Managers ================ Apache Thrift is available via a number of package managers, a list which is is steadily growing. A more detailed overview can be found [at the Apache Thrift web site under "Libraries"](http://thrift.apache.org/lib/) and/or in the respective READMEs for each language under /lib Testing ======= There are a large number of client library tests that can all be run from the top-level directory. make -k check This will make all of the libraries (as necessary), and run through the unit tests defined in each of the client libraries. If a single language fails, the make check will continue on and provide a synopsis at the end. To run the cross-language test suite, please run: make cross This will run a set of tests that use different language clients and servers. thrift-0.19.0/appveyor.yml0000644000000000000000000000653414454461475015515 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # build Apache Thrift on AppVeyor - https://ci.appveyor.com version: '0.19.0.{build}' shallow_clone: true branches: only: - master - /^(release/)?\d+\.\d+\.\d+$/ # Note: We could abort all jobs on the first error, but then it # becomes hard to learn from the other jobs results. Therefore disabled: #matrix: # fast_finish: true environment: matrix: - PROFILE: MSVC2017 PROFILE_CLASS: MSVC APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 PLATFORM: x64 CONFIGURATION: Release BUILD_SHARED_LIBS: ON BOOST_VERSION: 1.67.0 LIBEVENT_VERSION: 2.1.8 PYTHON_VERSION: 3.6 QT_VERSION: 5.10 ZLIB_VERSION: 1.2.11 - PROFILE: MSVC2015 PROFILE_CLASS: MSVC APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 PLATFORM: x86 CONFIGURATION: Debug BUILD_SHARED_LIBS: OFF BOOST_VERSION: 1.62.0 LIBEVENT_VERSION: 2.0.22 PYTHON_VERSION: 3.5 QT_VERSION: 5.8 ZLIB_VERSION: 1.2.8 - PROFILE: MINGW PROFILE_CLASS: MINGW # Currently the the latest MSYS2 is in the following image: APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 PLATFORM: x64 CONFIGURATION: RelWithDebInfo DISABLED_TESTS: (StalenessCheckTest) # As of 2021.08.06, the Cygwin build is broken with a missing dll exception. # See for an example https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/builds/40263513/job/a69xt6m4o0y9x1bw?fullLog=true # - PROFILE: CYGWIN # PROFILE_CLASS: CYGWIN # PLATFORM: x64 # CONFIGURATION: RelWithDebInfo # DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest) build_script: - cd %APPVEYOR_BUILD_FOLDER% - call build\appveyor\%PROFILE_CLASS%-appveyor-full.bat # artifact capture disabled as it might increase service cost for little gain: # # artifacts: # - path: local-thrift-inst # name: cmake installed content # type: zip # # - path: local-thrift-build\Testing # name: ctest output # type: zip # RDP support: use one or the other... # # enables RDP for each build job so you can inspect the environment at the beginning of the job: # init: # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) # # enables RDP at the end of the build job so you can login and re-run # commands to see why something failed... # on_finish: # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) # # also need: # environment: # APPVEYOR_RDP_PASSWORD: thr1FT2345$xyzZ thrift-0.19.0/config.guess0000755000000000000000000012637314472652513015444 0ustar00rootroot00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2018 Free Software Foundation, Inc. timestamp='2018-02-24' # 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/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . 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-2018 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 trap 'exit 1' 1 2 15 # 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. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { 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) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; 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 ; set_cc_for_build= ;' # 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) >/dev/null 2>&1 ; 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/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval "$set_cc_for_build" cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" # If ldd exists, use it to detect musl libc. if command -v ldd >/dev/null && \ ldd --version 2>&1 | grep -q ^musl then LIBC=musl 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". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)` case "$UNAME_MACHINE_ARCH" in 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) eval "$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. echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) 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. echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval "$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 [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; 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. echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; 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'. echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; 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) echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # 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:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval "$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; } echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ [ "$TARGET_BINARY_INTERFACE"x = x ] then echo m88k-dg-dgux"$UNAME_RELEASE" else echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval "$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 echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *: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 [ -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 echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 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 [ -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 [ "$HP_ARCH" = "" ]; then eval "$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 [ "$HP_ARCH" = hppa2.0w ] then eval "$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 echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) eval "$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; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo "$UNAME_MACHINE"-unknown-osf1mk else echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; 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*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; 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:*:*:*) echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; 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/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 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/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) case "$UNAME_MACHINE" in x86) echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` 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 echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval "$set_cc_for_build" sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) if objdump -f /bin/sh | grep -q elf32-x86-64; then echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 else echo "$UNAME_MACHINE"-pc-linux-"$LIBC" fi exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; 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. echo i386-sequent-sysv4 exit ;; 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. echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; i*86:*:4.*:*) UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; 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 echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; 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 echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; 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. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; 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*:*) echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv"$UNAME_RELEASE" else echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then if [ "$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 fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *: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 else UNAME_MACHINE="$cputype" fi echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac 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 </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 exit 1 # Local variables: # eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: thrift-0.19.0/build/0000777000000000000000000000000014370302016014176 5ustar00rootroot00000000000000thrift-0.19.0/build/fixchanges.sh0000777000000000000000000000303214062750226016662 0ustar00rootroot00000000000000#!/usr/bin/env bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # fixchanges will take a file as input and look for text matching # the pattern [THRIFT-nnnn] (the number of digits is not important) # which is not a markdown link, and change it to be a markdown link. # The tool writes to stdout so you can redirect it to a temporary # file and then compare against the original file before replacing # it. # # This tool was developed after the 0.12.0 release to assist with # generation of CHANGES.md content. # while IFS='' read -r line || [[ -n "$line" ]]; do if [[ "$line" =~ ^(.*)\[(THRIFT-[[:digit:]]+)\][^\(](.*)$ ]]; then echo "${BASH_REMATCH[1]}[${BASH_REMATCH[2]}](https://issues.apache.org/jira/browse/${BASH_REMATCH[2]}) ${BASH_REMATCH[3]}" else echo "$line" fi done < "$1" thrift-0.19.0/build/docker/0000777000000000000000000000000014452237057015462 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/ubuntu-bionic/0000777000000000000000000000000014452237057020245 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/ubuntu-bionic/Dockerfile0000644000000000000000000002411114452237057022232 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Bionic # with some updated packages. # FROM buildpack-deps:bionic-scm LABEL MAINTAINER='Apache Thrift ' ENV DEBIAN_FRONTEND noninteractive ### Add apt repos RUN apt-get update -yq && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends --fix-missing \ apt \ apt-transport-https \ apt-utils \ curl \ dirmngr \ software-properties-common \ wget # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list # dotnet (netcore) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \ chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \ chown root:root /etc/apt/sources.list.d/microsoft-prod.list # node.js RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_10.x bionic main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ libasound2 \ libatk-bridge2.0-0 \ libgtk-3-0 \ llvm \ ninja-build \ pkg-config \ unzip \ valgrind \ vim ENV PATH /usr/lib/llvm-6.0/bin:$PATH # lib/as3 (ActionScript) RUN mkdir -p /usr/local/adobe/flex/4.6 && \ cd /usr/local/adobe/flex/4.6 && \ wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ unzip flex_sdk_4.6.zip ENV FLEX_HOME /usr/local/adobe/flex/4.6 # TODO: "apt-get install" without "apt-get update" in the same "RUN" step can cause cache issues if modified later. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \ tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ cd sbcl-${SBCL_VERSION}-x86-64-linux && \ ./install.sh && \ sbcl --version && \ cd .. && \ rm -rf sbcl* ENV D_VERSION 2.087.0 ENV DMD_DEB dmd_2.087.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-libevent-2.0 && \ git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.1.0h ENV DART_VERSION 2.7.2-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ dotnet-sdk-7.0 \ dotnet-runtime-7.0 \ aspnetcore-runtime-7.0 \ dotnet-apphost-pack-7.0 # Erlang dependencies ARG ERLANG_OTP_VERSION=23.3.4.11 ARG ERLANG_REBAR_VERSION=3.18.0 RUN apt-get update && apt-get install -y --no-install-recommends libncurses5-dev && \ curl -ssLo /usr/local/bin/kerl https://raw.githubusercontent.com/kerl/kerl/master/kerl && chmod +x /usr/local/bin/kerl && \ kerl build $ERLANG_OTP_VERSION && kerl install $ERLANG_OTP_VERSION /usr/local/lib/otp/ && . /usr/local/lib/otp/activate && \ curl -ssLo /usr/local/bin/rebar3 https://github.com/erlang/rebar3/releases/download/${ERLANG_REBAR_VERSION}/rebar3 && chmod +x /usr/local/bin/rebar3 && \ rebar3 --version ENV PATH /usr/local/lib/otp/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.19.5 ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 36519702ae2fd573c9869461990ae550c8c0d955cd28d2827a6b159fda81ff95 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev && \ haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp 2>&1 > /dev/null ENV GRADLE_VERSION="8.0.2" RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ maven \ openjdk-17-jdk-headless && \ `# Gradle` \ wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \ (echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \ unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \ mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \ ln -s /usr/local/gradle/bin/gradle /usr/local/bin RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives! # need to update our luasocket code, lua doesn't have luaL_openlib any more RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs # Test dependencies for running puppeteer RUN apt-get install -y --no-install-recommends \ `# JS dependencies` \ libxss1 \ libxtst6 RUN apt-get install -y --no-install-recommends \ `# OCaml dependencies` \ ocaml \ opam && \ opam init --yes && \ opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl \ libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php \ php-cli \ php-dev \ php-json \ php-pear \ re2c \ composer RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-ipaddress \ python-pip \ python-setuptools \ python-six \ python-tornado \ python-twisted \ python-wheel \ python-zope.interface && \ pip install --upgrade backports.ssl_match_hostname RUN apt-get install -y --no-install-recommends \ `# Python3 dependencies` \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-pip \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler # Rust dependencies RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y ENV PATH /root/.cargo/bin:$PATH # Swift on Linux for cross tests RUN apt-get install -yq \ libedit-dev \ libz3-dev \ libpython-dev \ libxml2-dev && \ cd / && \ wget --quiet https://download.swift.org/swift-5.7-release/ubuntu1804/swift-5.7-RELEASE/swift-5.7-RELEASE-ubuntu18.04.tar.gz && \ tar xf swift-5.7-RELEASE-ubuntu18.04.tar.gz && \ mv swift-5.7-RELEASE-ubuntu18.04 /usr/share/swift && \ rm swift-5.7-RELEASE-ubuntu18.04.tar.gz ENV PATH /usr/share/swift/usr/bin:$PATH RUN swift --version # Locale(s) for cpp unit tests RUN apt-get install -y --no-install-recommends \ `# Locale dependencies` \ locales && \ locale-gen en_US.UTF-8 && \ locale-gen de_DE.UTF-8 && \ update-locale RUN apt-get install -y --no-install-recommends \ `# Static Code Analysis dependencies` \ cppcheck \ sloccount && \ pip install flake8 # NOTE: this does not reduce the image size but adds an additional layer. # # Clean up # RUN rm -rf /var/cache/apt/* && \ # rm -rf /var/lib/apt/lists/* && \ # rm -rf /tmp/* && \ # rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/msvc2017/0000777000000000000000000000000014303740367016742 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/msvc2017/Dockerfile0000644000000000000000000000764114303740367020740 0ustar00rootroot00000000000000# escape=` # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # FROM microsoft/dotnet-framework:4.7.1 # Restore the default Windows shell for correct batch processing below. SHELL ["cmd", "/S", "/C"] # Install Build Tools excluding workloads and components with known issues. ADD https://aka.ms/vs/15/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ` --installPath C:\BuildTools ` --all ` --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 ` --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 ` --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 ` --remove Microsoft.VisualStudio.Component.Windows81SDK ` || IF "%ERRORLEVEL%"=="3010" EXIT 0 RUN DEL C:\TEMP\vs_buildtools.exe # Install CMake ADD https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-win64-x64.msi C:\TEMP\cmake.msi RUN msiexec.exe /i C:\TEMP\cmake.msi /qn && ` SETX PATH "%PATH%;C:\Program Files\CMake\bin" && ` DEL C:\TEMP\cmake.msi # Install boost (for the thrift runtime library build) ADD https://boost.teeks99.com/bin/1.69.0/boost_1_69_0-msvc-14.1-64.exe C:\TEMP\boost.exe RUN C:\TEMP\boost.exe /DIR="C:\Libraries\boost_1_69_0" /SILENT && ` DEL C:\TEMP\boost.exe # Install chocolatey RUN @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" ` -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command ` "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" ` && SETX PATH "%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" # Install winflexbison (for the thrift compiler build) RUN choco install winflexbison3 -y # Install 7zip and curl (used by the libevent and zlib build scripts) RUN choco install 7zip curl -y # Install libevent COPY appveyor\build-libevent.bat C:\TEMP\build-libevent.bat ENV LIBEVENT_VERSION=2.1.8 ENV WIN3P=C:\TEMP\WIN3P RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && ` MKDIR C:\TEMP\WIN3P && ` C:\TEMP\build-libevent.bat && ` MKDIR C:\Libraries\libevent-%LIBEVENT_VERSION% && ` MOVE C:\TEMP\WIN3P\libevent-%LIBEVENT_VERSION%-stable\include C:\Libraries\libevent-%LIBEVENT_VERSION% && ` MOVE C:\TEMP\WIN3P\libevent-%LIBEVENT_VERSION%-stable\lib C:\Libraries\libevent-%LIBEVENT_VERSION% && ` RMDIR /S /Q C:\TEMP\WIN3P # Install zlib COPY appveyor\build-zlib.bat C:\TEMP\build-zlib.bat ENV ZLIB_VERSION=1.2.11 ENV WIN3P=C:\TEMP\WIN3P RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && ` MKDIR C:\TEMP\WIN3P && ` C:\TEMP\build-zlib.bat && ` MOVE C:\TEMP\WIN3P\zlib-inst C:\Libraries\zlib-%ZLIB_VERSION% && ` RMDIR /S /Q C:\TEMP\WIN3P # Install OpenSSL 1.1.0 ADD http://slproweb.com/download/Win64OpenSSL-1_1_0j.exe C:\TEMP\openssl.exe RUN C:\TEMP\openssl.exe /silent && ` DEL C:\TEMP\openssl.exe # Install java RUN choco install jdk8 -y # Install python3 RUN choco install python3 -y # Install Adobe Flex 4.6 SDK and set FLEX_HOME so it can be found ADD http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip C:\Adobe\Flex\SDK\4.6\SDK.zip RUN CD C:\Adobe\Flex\SDK\4.6 && ` 7z x SDK.zip && ` DEL SDK.zip && ` SETX FLEX_HOME "C:\Adobe\Flex\SDK\4.6" # Start developer command prompt with any other commands specified. ENTRYPOINT C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && # Default to PowerShell if no other command specified. CMD ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"] thrift-0.19.0/build/docker/msvc2017/README.md0000644000000000000000000000325314303740367020220 0ustar00rootroot00000000000000# Building Thrift using Docker for Windows The build image is very large (just under 30GB) so plan accordingly. Once Microsoft supports build tools in nano, it should get better. Install Docker for Windows and switch to Windows container mode. Pull from docker hub: PS C:\> docker pull thrift/thrift-build:msvc2017 or build in a docker for windows environment: PS C:\Thrift> docker build -t thrift/thrift-build:msvc2017 -f build\docker\msvc2017\Dockerfile build\ The following directories are used inside the container: C:\Build the out-of-tree build directory C:\Install the install target directory C:\Thrift the source tree You can override these as docker volumes if desired. ### Compiler To build a portable windows thrift compiler (with a statically linked runtime) and get it placed into C:\install: docker run -v C:\thrift:C:\thrift^ -v C:\install:C:\install^ --rm -t thrift/thrift-build:msvc2017^ C:\thrift\build\docker\msvc2017\build-compiler.bat The end result is a portable windows thrift compiler located at C:\Install\bin\thrift.exe If you run it through the [Dependency Walker](http://www.dependencywalker.com/) you will see it only depends on KERNEL32.DLL which means the runtime is statically linked, so the executable is portable and self-contained. This is how the windows thrift compiler is built for each Apache Thrift release. ### Libraries To build, test everything and get the C++ SDK placed into C:\install: docker run -v C:\thrift:C:\thrift^ -v C:\install:C:\install^ -m 4096 --rm -t thrift/thrift-build:msvc2017^ C:\thrift\build\docker\msvc2017\build.batthrift-0.19.0/build/docker/msvc2017/build-compiler.bat0000644000000000000000000000244714303740367022344 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Build script example for inside the windows docker container :: :: C:\build is the out-of-tree build directory :: C:\install is the location where artifacts are placed :: C:\thrift is where the sources are :: :: Make and go into the out-of-tree directory IF NOT EXIST C:\build (MKDIR C:\build) cd c:\build :: Generate the out-of-tree build files cmake^ -DBOOST_ROOT=C:\Libraries\boost_1_69_0^ -DBOOST_LIBRARYDIR=C:\Libraries\boost_1_69_0\lib64-msvc-14.1^ -DBUILD_LIBRARIES=OFF^ -DCMAKE_BUILD_TYPE=Release^ -DCMAKE_INSTALL_PREFIX=C:\install^ -DWITH_MT=ON^ c:\thrift || EXIT /B :: Build cmake --build . --target thrift-compiler --config Release || EXIT /B :: Test cmake --build . --target check || EXIT /B :: Install cmake --install .thrift-0.19.0/build/docker/msvc2017/build.bat0000644000000000000000000000254214303740367020530 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Build script example for inside the windows docker container :: :: C:\build is the out-of-tree build directory :: C:\install is the location where artifacts are placed :: C:\thrift is where the sources are :: :: Make and go into the out-of-tree directory IF NOT EXIST C:\build (MKDIR C:\build) cd c:\build :: Generate the out-of-tree build files cmake^ -DBOOST_ROOT=C:\Libraries\boost_1_69_0^ -DBOOST_LIBRARYDIR=C:\Libraries\boost_1_69_0\lib64-msvc-14.1^ -DFLEX_HOME=C:\Adobe\Flex\SDK\4.6^ -DLIBEVENT_ROOT=C:\Libraries\libevent-2.1.8^ -DZLIB_ROOT=C:\Libraries\zlib-1.2.11^ -DCMAKE_BUILD_TYPE=Release^ -DCMAKE_INSTALL_PREFIX=C:\install^ c:\thrift || EXIT /B :: Build cmake --build . --config Release || EXIT /B :: Test cmake --build . --target check || EXIT /B :: Install cmake --install . thrift-0.19.0/build/docker/ubuntu-jammy/0000755000000000000000000000000014452237057020113 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/ubuntu-jammy/Dockerfile0000644000000000000000000002224214452237057022107 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Jammy # with some updated packages. # FROM buildpack-deps:jammy-scm LABEL MAINTAINER="Apache Thrift " ENV DEBIAN_FRONTEND=noninteractive ### Add apt repos RUN apt-get update -yq && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends --fix-missing \ apt \ apt-transport-https \ apt-utils \ curl \ dirmngr \ software-properties-common \ wget # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list # dotnet (netcore) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \ chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \ chown root:root /etc/apt/sources.list.d/microsoft-prod.list # node.js RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_16.x focal main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update -yq && \ apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ libasound2 \ libatk-bridge2.0-0 \ libgtk-3-0 \ llvm \ ninja-build \ pkg-config \ unzip \ valgrind \ vim ENV PATH /usr/lib/llvm-6.0/bin:$PATH # lib/as3 (ActionScript) RUN mkdir -p /usr/local/adobe/flex/4.6 && \ cd /usr/local/adobe/flex/4.6 && \ wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ unzip flex_sdk_4.6.zip ENV FLEX_HOME /usr/local/adobe/flex/4.6 # TODO: "apt-get install" without "apt-get update" in the same "RUN" step can cause cache issues if modified later. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \ tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ cd sbcl-${SBCL_VERSION}-x86-64-linux && \ ./install.sh && \ sbcl --version && \ cd .. && \ rm -rf sbcl* ENV D_VERSION 2.087.0 ENV DMD_DEB dmd_2.087.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-libevent-2.0 && \ git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.1.0h ENV DART_VERSION 2.7.2-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ dotnet-sdk-7.0 \ dotnet-runtime-7.0 \ aspnetcore-runtime-7.0 \ dotnet-apphost-pack-7.0 # Erlang dependencies ARG ERLANG_OTP_VERSION=23.3.4.11 ARG ERLANG_REBAR_VERSION=3.18.0 RUN apt-get update && apt-get install -y --no-install-recommends libncurses5-dev && \ curl -ssLo /usr/local/bin/kerl https://raw.githubusercontent.com/kerl/kerl/master/kerl && chmod +x /usr/local/bin/kerl && \ kerl build $ERLANG_OTP_VERSION && kerl install $ERLANG_OTP_VERSION /usr/local/lib/otp/ && . /usr/local/lib/otp/activate && \ curl -ssLo /usr/local/bin/rebar3 https://github.com/erlang/rebar3/releases/download/${ERLANG_REBAR_VERSION}/rebar3 && chmod +x /usr/local/bin/rebar3 && \ rebar3 --version ENV PATH /usr/local/lib/otp/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.20 ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 5a9ebcc65c1cce56e0d2dc616aff4c4cedcfbda8cc6f0288cc08cda3b18dcbf1 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev && \ haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp 2>&1 > /dev/null ENV GRADLE_VERSION="8.0.2" RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ maven \ openjdk-11-jdk-headless && \ `# Gradle` \ wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \ (echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \ unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \ mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \ ln -s /usr/local/gradle/bin/gradle /usr/local/bin RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives! # need to update our luasocket code, lua doesn't have luaL_openlib any more RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs # Test dependencies for running puppeteer RUN apt-get install -y --no-install-recommends \ `# JS dependencies` \ libxss1 \ libxtst6 RUN apt-get install -y --no-install-recommends \ `# OCaml dependencies` \ ocaml \ opam && \ `# disable sandboxing see https://github.com/ocaml/opam/issues/4327` \ opam init --yes --disable-sandboxing && \ opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl \ libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php \ php-cli \ php-dev \ php-json \ php-pear \ re2c \ composer RUN apt-get install -y --no-install-recommends \ `# Python3 dependencies` \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-pip \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler # Rust dependencies RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y ENV PATH /root/.cargo/bin:$PATH # Swift on Linux for cross tests RUN apt-get install -yq \ libedit-dev \ libz3-dev \ libpython2-dev \ libxml2-dev && \ cd / && \ wget --quiet https://download.swift.org/swift-5.7-release/ubuntu2204/swift-5.7-RELEASE/swift-5.7-RELEASE-ubuntu22.04.tar.gz && \ tar xf swift-5.7-RELEASE-ubuntu22.04.tar.gz && \ mv swift-5.7-RELEASE-ubuntu22.04 /usr/share/swift && \ rm swift-5.7-RELEASE-ubuntu22.04.tar.gz ENV PATH /usr/share/swift/usr/bin:$PATH RUN swift --version # Locale(s) for cpp unit tests RUN apt-get install -y --no-install-recommends \ `# Locale dependencies` \ locales && \ locale-gen en_US.UTF-8 && \ locale-gen de_DE.UTF-8 && \ update-locale RUN apt-get install -y --no-install-recommends \ `# Static Code Analysis dependencies` \ cppcheck \ sloccount && \ pip install flake8 # NOTE: this does not reduce the image size but adds an additional layer. # # Clean up # RUN rm -rf /var/cache/apt/* && \ # rm -rf /var/lib/apt/lists/* && \ # rm -rf /tmp/* && \ # rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/ubuntu-focal/0000755000000000000000000000000014452237057020062 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/ubuntu-focal/Dockerfile0000644000000000000000000002345214452237057022062 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Focal # with some updated packages. # FROM buildpack-deps:focal-scm LABEL MAINTAINER="Apache Thrift " ENV DEBIAN_FRONTEND=noninteractive ### Add apt repos RUN apt-get update -yq && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends --fix-missing \ apt \ apt-transport-https \ apt-utils \ curl \ dirmngr \ software-properties-common \ wget # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list # dotnet (netcore) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \ chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \ chown root:root /etc/apt/sources.list.d/microsoft-prod.list # node.js RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_16.x focal main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update -yq && \ apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ libasound2 \ libatk-bridge2.0-0 \ libgtk-3-0 \ llvm \ ninja-build \ pkg-config \ unzip \ valgrind \ vim ENV PATH /usr/lib/llvm-6.0/bin:$PATH # lib/as3 (ActionScript) RUN mkdir -p /usr/local/adobe/flex/4.6 && \ cd /usr/local/adobe/flex/4.6 && \ wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ unzip flex_sdk_4.6.zip ENV FLEX_HOME /usr/local/adobe/flex/4.6 # TODO: "apt-get install" without "apt-get update" in the same "RUN" step can cause cache issues if modified later. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \ tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ cd sbcl-${SBCL_VERSION}-x86-64-linux && \ ./install.sh && \ sbcl --version && \ cd .. && \ rm -rf sbcl* ENV D_VERSION 2.087.0 ENV DMD_DEB dmd_2.087.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-libevent-2.0 && \ git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.1.0h ENV DART_VERSION 2.7.2-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ dotnet-sdk-7.0 \ dotnet-runtime-7.0 \ aspnetcore-runtime-7.0 \ dotnet-apphost-pack-7.0 # Erlang dependencies ARG ERLANG_OTP_VERSION=23.3.4.11 ARG ERLANG_REBAR_VERSION=3.18.0 RUN apt-get update && apt-get install -y --no-install-recommends libncurses5-dev && \ curl -ssLo /usr/local/bin/kerl https://raw.githubusercontent.com/kerl/kerl/master/kerl && chmod +x /usr/local/bin/kerl && \ kerl build $ERLANG_OTP_VERSION && kerl install $ERLANG_OTP_VERSION /usr/local/lib/otp/ && . /usr/local/lib/otp/activate && \ curl -ssLo /usr/local/bin/rebar3 https://github.com/erlang/rebar3/releases/download/${ERLANG_REBAR_VERSION}/rebar3 && chmod +x /usr/local/bin/rebar3 && \ rebar3 --version ENV PATH /usr/local/lib/otp/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.20 ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 5a9ebcc65c1cce56e0d2dc616aff4c4cedcfbda8cc6f0288cc08cda3b18dcbf1 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev && \ haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp 2>&1 > /dev/null ENV GRADLE_VERSION="8.0.2" RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ maven \ openjdk-17-jdk-headless && \ `# Gradle` \ wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \ (echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \ unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \ mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \ ln -s /usr/local/gradle/bin/gradle /usr/local/bin RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives! # need to update our luasocket code, lua doesn't have luaL_openlib any more RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs # Test dependencies for running puppeteer RUN apt-get install -y --no-install-recommends \ `# JS dependencies` \ libxss1 \ libxtst6 RUN apt-get install -y --no-install-recommends \ `# OCaml dependencies` \ ocaml \ opam && \ `# disable sandboxing see https://github.com/ocaml/opam/issues/4327` \ opam init --yes --disable-sandboxing && \ opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl \ libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php \ php-cli \ php-dev \ php-json \ php-pear \ re2c \ composer RUN apt-get install -y --no-install-recommends \ `# Python3 dependencies` \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-pip \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler # Rust dependencies RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y ENV PATH /root/.cargo/bin:$PATH # Swift on Linux for cross tests RUN apt-get install -yq \ libedit-dev \ libz3-dev \ libpython2-dev \ libxml2-dev && \ cd / && \ wget --quiet https://download.swift.org/swift-5.7-release/ubuntu2004/swift-5.7-RELEASE/swift-5.7-RELEASE-ubuntu20.04.tar.gz && \ tar xf swift-5.7-RELEASE-ubuntu20.04.tar.gz && \ mv swift-5.7-RELEASE-ubuntu20.04 /usr/share/swift && \ rm swift-5.7-RELEASE-ubuntu20.04.tar.gz ENV PATH /usr/share/swift/usr/bin:$PATH RUN swift --version # Locale(s) for cpp unit tests RUN apt-get install -y --no-install-recommends \ `# Locale dependencies` \ locales && \ locale-gen en_US.UTF-8 && \ locale-gen de_DE.UTF-8 && \ update-locale RUN apt-get install -y --no-install-recommends \ `# Static Code Analysis dependencies` \ cppcheck \ sloccount && \ pip install flake8 # NOTE: this does not reduce the image size but adds an additional layer. # # Clean up # RUN rm -rf /var/cache/apt/* && \ # rm -rf /var/lib/apt/lists/* && \ # rm -rf /tmp/* && \ # rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/README.md0000644000000000000000000001753114452237057016744 0ustar00rootroot00000000000000# Docker Integration # Due to the large number of languages supported by Apache Thrift, docker containers are used to build and test the project on a variety of platforms to provide maximum test coverage. ## Appveyor Integration ## At this time the Appveyor scripts do not use docker containers. Once Microsoft supports Visual Studio Build Tools running inside nano containers (instead of Core, which is huge) then we will consider using containers for the Windows builds as well. ## Travis CI Integration ## The Travis CI scripts use the following environment variables and logic to determine their behavior: ### Environment Variables ### | Variable | Default | Usage | | -------- | ----- | ------- | | `DISTRO` | `ubuntu-bionic` | Set by various build jobs in `.travis.yml` to run builds in different containers. Not intended to be set externally.| | `DOCKER_REPO` | `thrift/thrift-build` | The name of the Docker Hub repository to obtain and store docker images. | | `DOCKER_USER` | `` | The Docker Hub account name containing the repository. | | `DOCKER_PASS` | `` | The Docker Hub account password to use when pushing new tags. | For example, the default docker image that is used in builds if no overrides are specified would be: `thrift/thrift-build:ubuntu-bionic` ### Forks ### If you have forked the Apache Thrift repository and you would like to use your own Docker Hub account to store thrift build images, you can use the Travis CI web interface to set the `DOCKER_USER`, `DOCKER_PASS`, and `DOCKER_REPO` variables in a secure manner. Your fork builds will then pull, push, and tag the docker images in your account. ### Logic ### The Travis CI build runs in two phases - first the docker images are rebuilt for each of the supported containers if they do not match the Dockerfile that was used to build the most recent tag. If a `DOCKER_PASS` environment variable is specified, the docker stage builds will attempt to log into Docker Hub and push the resulting tags. ## Supported Containers ## The Travis CI (continuous integration) builds use the Ubuntu Bionic (18.04 LTS) and Xenial (16.04 LTS) images to maximize language level coverage. ### Ubuntu ### * focal (stable, current) * bionic (previous stable) * jammy (next stable, WIP) ## Unsupported Containers ## These containers may be in various states, and may not build everything. They can be found in the `old/` subdirectory. ### CentOS ### * 7.3 * make check in lib/py may hang in test_sslsocket - root cause unknown ### Debian ### * jessie * stretch * make check in lib/cpp fails due to https://svn.boost.org/trac10/ticket/12507 ## Building like Travis CI does, locally ## We recommend you build locally the same way Travis CI does, so that when you submit your pull request you will run into fewer surprises. To make it a little easier, put the following into your `~/.bash_aliases` file: # Kill all running containers. alias dockerkillall='docker kill $(docker ps -q)' # Delete all stopped containers. alias dockercleanc='printf "\n>>> Deleting stopped containers\n\n" && docker rm $(docker ps -a -q)' # Delete all untagged images. alias dockercleani='printf "\n>>> Deleting untagged images\n\n" && docker rmi $(docker images -q -f dangling=true)' # Delete all stopped containers and untagged images. alias dockerclean='dockercleanc || true && dockercleani' # Build a thrift docker image (run from top level of git repo): argument #1 is image type (ubuntu, centos, etc). function dockerbuild { docker build -t $1 build/docker/$1 } # Run a thrift docker image: argument #1 is image type (ubuntu, centos, etc). function dockerrun { docker run -v $(pwd):/thrift/src -it $1 /bin/bash } Then, to pull down the current image being used to build (the same way Travis CI does it) - if it is out of date in any way it will build a new one for you: thrift$ DOCKER_REPO=thrift/thrift-build DISTRO=ubuntu-bionic build/docker/refresh.sh To run all unit tests (just like Travis CI does): thrift$ dockerrun thrift/thrift-build:ubuntu-bionic root@8caf56b0ce7b:/thrift/src# build/docker/scripts/autotools.sh To run the cross tests (just like Travis CI does): thrift$ dockerrun thrift/thrift-build:ubuntu-bionic root@8caf56b0ce7b:/thrift/src# build/docker/scripts/cross-test.sh When you are done, you want to clean up occasionally so that docker isn't using lots of extra disk space: thrift$ dockerclean You need to run the docker commands from the root of the local clone of the thrift git repository for them to work. When you are done in the root docker shell you can `exit` to go back to your user host shell. Once the unit tests and cross test passes locally, submit the changes, and if desired squash the pull request to one commit to make it easier to merge (the committers can squash at commit time now that GitHub is the master repository). Now you are building like Travis CI does! ## Raw Commands for Building with Docker ## If you do not want to use the same scripts Travis CI does, you can do it manually: Build the image: thrift$ docker build -t thrift build/docker/ubuntu-bionic Open a command prompt in the image: thrift$ docker run -v $(pwd):/thrift/src -it thrift /bin/bash ## Core Tool Versions per Dockerfile ## Last updated: October 1, 2017 | Tool | ubuntu-xenial | ubuntu-bionic | Notes | | :-------- | :------------ | :------------ | :---- | | ant | 1.9.6 | 1.10.3 | | | autoconf | 2.69 | 2.69 | | | automake | 1.15 | 1.15.1 | | | bison | 3.0.4 | 3.0.4 | | | boost | 1.58.0 | 1.65.1 | | | cmake | 3.5.1 | 3.10.2 | | | cppcheck | 1.72 | 1.82 | | | flex | 2.6.0 | 2.6.4 | | | libc6 | 2.23 | 2.27 | glibc | | libevent | 2.0.21 | 2.1.8 | | | libstdc++ | 5.4.0 | 7.3.0 | | | make | 4.1 | 4.1 | | | openssl | 1.0.2g | 1.1.0g | | | qt5 | 5.5.1 | 5.9.5 | | ## Compiler/Language Versions per Dockerfile ## | Language | ubuntu-xenial | ubuntu-bionic | Notes | | :-------- | :------------ | :------------ | :---- | | as of | Mar 06, 2018 | Jul 1, 2019 | | | as3 | | 4.6.0 | | | C++ gcc | 5.4.0 | 7.4.0 | | | C++ clang | 3.8 | 6.0 | | | C# (mono) | 4.2.1.0 | 4.6.2.7 | | | c\_glib | 2.48.2 | 2.56.4 | | | cl (sbcl) | | 1.5.3 | | | d | 2.087.0 | 2.087.0 | | | dart | 2.0.0 | 2.4.0 | | | delphi | | | Not in CI | | erlang | OTP-18 | OTP-23 | | | go | 1.15.10 | 1.16.2 | | | haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | | java | 1.8.0\_191 | 17 | | | js | Node.js 6.17.1, V8 5.1.281.111, npm 3.10.10 | Node.js 10.18.0, V8 6.8.275.32, npm 6.13.4 | | | lua | | 5.2.4 | Lua 5.3: see THRIFT-4386 | | netstd | 7.0 | 7.0 | | | nodejs | 6.16.0 | 10.16.0 | | | ocaml | | 4.05.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken | | perl | 5.22.1 | 5.26.1 | | | php | 7.0.32 | 7.2.19 | | | python | 2.7.12 | 2.7.15 | | | python3 | 3.5.2 | 3.6.8 | | | ruby | 2.3.1p112 | 2.5.1p57 | | | rust | 1.61.0 | 1.61.0 | | | smalltalk | | | Not in CI | | swift | | 5.1.4 | | thrift-0.19.0/build/docker/refresh.sh0000777000000000000000000000543014062750226017454 0ustar00rootroot00000000000000#!/bin/bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # The build has two stages: "docker" and "test" # The "docker" stage is meant to rebuild the docker images # if needed. If we cannot push that result however then # there is no reason to do anything. # The "test" stage is an actual test job. Even if the docker # image doesn't match what's in the repo, we still build # the image so the build job can run properly. # set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DOCKER_TAG=$DOCKER_REPO:$DISTRO function dockerfile_changed { # image may not exist yet, so we have to let it fail silently: docker pull $DOCKER_TAG || true docker run $DOCKER_TAG bash -c 'cd .. && sha512sum Dockerfile' > .Dockerfile.sha512 sha512sum -c .Dockerfile.sha512 } # # If this build has no DOCKER_PASS and it is in the docker stage # then there's no reason to do any processing because we cannot # push the result if the Dockerfile changed. # if [[ "$TRAVIS_BUILD_STAGE" == "docker" ]] && [[ -z "$DOCKER_PASS" ]]; then echo Detected docker stage build and no defined DOCKER_PASS, this build job will be skipped. echo Subsequent jobs in the test stage may each rebuild the docker image. exit 0 fi pushd ${SCRIPT_DIR}/$DISTRO if dockerfile_changed; then echo Dockerfile has not changed. No need to rebuild. exit 0 else echo Dockerfile has changed. fi popd # # Dockerfile has changed - rebuild it for the current build job. # If it is a "docker" stage build then we want to push it back # to the DOCKER_REPO. If it is a "test" stage build then we do # not. If nobody defined a DOCKER_PASS then it doesn't matter. # echo Rebuilding docker image $DISTRO docker build --tag $DOCKER_TAG build/docker/$DISTRO if [[ "$TRAVIS_BUILD_STAGE" == "docker" ]] && [[ ! -z "$DOCKER_USER" ]] && [[ ! -z "$DOCKER_PASS" ]]; then echo Pushing docker image $DOCKER_TAG docker login -u $DOCKER_USER -p $DOCKER_PASS docker push $DOCKER_TAG else echo Not pushing docker image: either not a docker stage build job, or one of DOCKER_USER or DOCKER_PASS is undefined. fi thrift-0.19.0/build/docker/scripts/0000777000000000000000000000000014370300523017135 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/scripts/autotools.sh0000755000000000000000000000054314370300523021523 0ustar00rootroot00000000000000#!/bin/sh set -ev mkdir -p ~/.m2 tee >~/.m2/settings.xml < secure-central https://repo.maven.apache.org/maven2 central EOF ./bootstrap.sh ./configure $* make check -j3 thrift-0.19.0/build/docker/scripts/cross-test.sh0000777000000000000000000000056514062750226021617 0ustar00rootroot00000000000000#!/bin/sh set -ev ./bootstrap.sh ./configure --enable-tutorial=no make -j3 precross set +e make cross$1 RET=$? if [ $RET -ne 0 ]; then if [ -f "test/features/log/unexpected_failures.log" ]; then cat "test/features/log/unexpected_failures.log" fi if [ -f "test/log/unexpected_failures.log" ]; then cat "test/log/unexpected_failures.log" fi fi exit $RET thrift-0.19.0/build/docker/scripts/coverity.sh0000777000000000000000000000251614062750226021353 0ustar00rootroot00000000000000#! /bin/bash # # This script allows you to run coverity on the project and submit the # results. Do this inside the docker build container. Only works if # you are a coverity scan thrift project admin with access to the # necessary security token. # # Environment Variables # # COVERITY_SCAN_NOTIFICATION_EMAIL - email address to notify # COVERITY_SCAN_TOKEN - the Coverity Scan token (should be secure) # VERSION - the version to report we scanned set -ex wget -nv https://entrust.com/root-certificates/entrust_l1k.cer -O /tmp/scanca.cer pushd /tmp if [[ "$1" != "--skipdownload" ]]; then rm -rf coverity_tool.tgz cov-analysis* wget -nv -O coverity_tool.tgz https://scan.coverity.com/download/cxx/linux64 --post-data "project=thrift&token=$COVERITY_SCAN_TOKEN" tar xzf coverity_tool.tgz fi COVBIN=$(echo $(pwd)/cov-analysis*/bin) export PATH=$COVBIN:$PATH popd ./bootstrap.sh ./configure $* rm -rf cov-int/ cov-build --dir cov-int make check -j3 tail -50 cov-int/build-log.txt tar cJf cov-int.tar.xz cov-int/ curl --cacert /tmp/scanca.cer \ --form token="$COVERITY_SCAN_TOKEN" \ --form email="$COVERITY_SCAN_NOTIFICATION_EMAIL" \ --form file=@cov-int.tar.xz \ --form version="$VERSION" \ --form description="thrift master" \ https://scan.coverity.com/builds?project=thrift thrift-0.19.0/build/docker/scripts/ubsan.sh0000777000000000000000000000175014062750226020616 0ustar00rootroot00000000000000#!/bin/sh set -e # Wraps autotools.sh, but each binary crashes if it exhibits undefined behavior. # Set the undefined behavior flags. This crashes on all undefined behavior except for # undefined casting, aka "vptr". # TODO: fix undefined vptr behavior and turn this option back on. export CFLAGS="-fsanitize=undefined -fno-sanitize-recover=undefined -O0 -ggdb3 -fno-omit-frame-pointer" export CXXFLAGS="${CFLAGS}" export LDFLAGS="-lubsan" export UBSAN_OPTIONS=print_stacktrace=1 # # work around https://svn.boost.org/trac10/ticket/11632 if present # sed -i 's/, stream_t(rdbuf()) /, stream_t(pbase_type::member.get())/g' /usr/include/boost/format/alt_sstream.hpp # llvm-symbolizer must be on PATH to get a stack trace on error CLANG_PATH="$(mktemp -d)" trap "rm -rf ${CLANG_PATH}" EXIT ln -s "$(whereis llvm-symbolizer-4.0 | rev | cut -d ' ' -f 1 | rev)" \ "${CLANG_PATH}/llvm-symbolizer" export PATH="${CLANG_PATH}:${PATH}" llvm-symbolizer -version build/docker/scripts/autotools.sh $* thrift-0.19.0/build/docker/scripts/sca.sh0000777000000000000000000000331414062750226020252 0ustar00rootroot00000000000000#!/bin/bash set -ev # # Generate thrift files so the static code analysis includes an analysis # of the files the thrift compiler spits out. If running interactively # set the NOBUILD environment variable to skip the boot/config/make phase. # if [[ -z "$NOBUILD" ]]; then ./bootstrap.sh ./configure --enable-tutorial=no make -j3 precross fi # # C/C++ static code analysis with cppcheck # add --error-exitcode=1 to --enable=all as soon as everything is fixed # # Python code style check with flake8 # # search for TODO etc within source tree # some statistics about the code base # some info about the build machine # Compiler cppcheck (All) cppcheck --force --quiet --inline-suppr --enable=all -j2 compiler/cpp/src # C++ cppcheck (All) cppcheck --force --quiet --inline-suppr --enable=all -j2 lib/cpp/src lib/cpp/test test/cpp tutorial/cpp # C Glib cppcheck (All) cppcheck --force --quiet --inline-suppr --enable=all -j2 lib/c_glib/src lib/c_glib/test test/c_glib/src tutorial/c_glib # Silent error checks # See THRIFT-4371 : flex generated code triggers "possible null pointer dereference" in yy_init_buffer cppcheck --force --quiet --inline-suppr --suppress="*:thrift/thriftl.cc" --error-exitcode=1 -j2 compiler/cpp/src cppcheck --force --quiet --inline-suppr --error-exitcode=1 -j2 lib/cpp/src lib/cpp/test test/cpp tutorial/cpp cppcheck --force --quiet --inline-suppr --error-exitcode=1 -j2 lib/c_glib/src lib/c_glib/test test/c_glib/src tutorial/c_glib # Python code style flake8 # PHP code style composer install --quiet ./vendor/bin/phpcs # TODO etc echo FIXMEs: `grep -r FIXME * | wc -l` echo HACKs: `grep -r HACK * | wc -l` echo TODOs: `grep -r TODO * | wc -l` # LoC sloccount . # System Info dpkg -l uname -a thrift-0.19.0/build/docker/scripts/dpkg.sh0000777000000000000000000000007314062750226020430 0ustar00rootroot00000000000000#!/bin/sh set -ev dpkg-buildpackage -tc -us -uc ls -al .. thrift-0.19.0/build/docker/scripts/cmake.sh0000777000000000000000000000057714062750226020574 0ustar00rootroot00000000000000#!/bin/sh set -ev CMAKE_FLAGS=$* MAKEPROG=make if ninja --version >/dev/null 2>&1; then MAKEPROG=ninja CMAKE_FLAGS="-GNinja $CMAKE_FLAGS" fi mkdir -p cmake_build && cd cmake_build cmake $CMAKE_FLAGS .. for LIB in $BUILD_LIBS; do if ! grep "^BUILD_${LIB}:BOOL=ON$" CMakeCache.txt ; then echo "failed to configure $LIB" exit 1 fi done $MAKEPROG -j3 cpack ctest -VV thrift-0.19.0/build/docker/scripts/make-dist.sh0000777000000000000000000000017714062750226021366 0ustar00rootroot00000000000000#!/bin/sh set -ev ./bootstrap.sh ./configure $* make dist tar xvf thrift-*.tar.gz cd thrift-* ./build/docker/scripts/cmake.sh thrift-0.19.0/build/docker/scripts/covscan.sh0000777000000000000000000000336214062750226021143 0ustar00rootroot00000000000000# # Coverity Scan Travis build script # To run this interactively, set the environment variables yourself, # and run this inside a docker container. # # Command-Line Arguments # # --skipdownload to skip re-downloading the Coverity Scan build package (large) # # Environment Variables (required) # # COVERITY_SCAN_NOTIFICATION_EMAIL - email address to notify # COVERITY_SCAN_TOKEN - the Coverity Scan token (should be secure) # # Environment Variables (defaulted) # # COVERITY_SCAN_BUILD_COMMAND - defaults to "build/docker/scripts/autotools.sh" # COVERITY_SCAN_DESCRIPTION - defaults to TRAVIS_BRANCH or "master" if empty # COVERITY_SCAN_PROJECT - defaults to "thrift" set -ex COVERITY_SCAN_BUILD_COMMAND=${COVERITY_SCAN_BUILD_COMMAND:-build/docker/scripts/autotools.sh} COVERITY_SCAN_DESCRIPTION=${COVERITY_SCAN_DESCRIPTION:-${TRAVIS_BRANCH:-master}} COVERITY_SCAN_PROJECT=${COVERITY_SCAN_PROJECT:-thrift} # download the coverity scan package pushd /tmp if [[ "$1" != "--skipdownload" ]]; then rm -rf coverity_tool.tgz cov-analysis* wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=$COVERITY_SCAN_PROJECT" -O coverity_tool.tgz tar xzf coverity_tool.tgz fi COVBIN=$(echo $(pwd)/cov-analysis*/bin) export PATH=$COVBIN:$PATH popd # build the project with coverity scan rm -rf cov-int/ cov-build --dir cov-int $COVERITY_SCAN_BUILD_COMMAND tar cJf cov-int.tar.xz cov-int/ curl --form token="$COVERITY_SCAN_TOKEN" \ --form email="$COVERITY_SCAN_NOTIFICATION_EMAIL" \ --form file=@cov-int.tar.xz \ --form version="$(git describe --tags)" \ --form description="$COVERITY_SCAN_DESCRIPTION" \ https://scan.coverity.com/builds?project="$COVERITY_SCAN_PROJECT" thrift-0.19.0/build/docker/run.sh0000777000000000000000000000204214062750226016616 0ustar00rootroot00000000000000#!/bin/bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DOCKER_TAG=$DOCKER_REPO:$DISTRO printenv | sort docker run --net=host -e BUILD_LIBS="$BUILD_LIBS" $BUILD_ENV -v $(pwd):/thrift/src \ -it $DOCKER_TAG build/docker/scripts/$SCRIPT $BUILD_ARG thrift-0.19.0/build/docker/old/0000777000000000000000000000000014370300523016224 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/Vagrantfile0000644000000000000000000000374514303740367020430 0ustar00rootroot00000000000000# -*- mode: ruby -*- # vi: set ft=ruby : # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Base system bootstrap script $bootstrap_script = <<__BOOTSTRAP__ echo "Provisioning defaults" sudo apt-get update -y sudo apt-get upgrade -y # Install default packages sudo apt-get install -y build-essential curl git # Install latest Docker version sudo curl -sSL https://get.docker.io/gpg | sudo apt-key add - sudo echo "deb http://get.docker.io/ubuntu docker main" > /etc/apt/sources.list.d/docker.list sudo apt-get update -y sudo apt-get install -y linux-image-extra-`uname -r` aufs-tools sudo apt-get install -y lxc-docker echo "Finished provisioning defaults" __BOOTSTRAP__ Vagrant.configure("2") do |config| config.vm.box = "trusty64" config.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box" config.ssh.forward_agent = true config.vm.provider :virtualbox do |vbox| vbox.customize ["modifyvm", :id, "--memory", "1024"] vbox.customize ["modifyvm", :id, "--cpus", "2"] end # Setup the default bootstrap script for our ubuntu base box image config.vm.provision "shell", inline: $bootstrap_script # Setup the custom docker image from our Ubuntu Dockerfile config.vm.provision "docker" do |d| d.build_image "/vagrant/ubuntu", args: "-t thrift" end # Setup the custom docker image from our Centos Dockerfile #config.vm.provision "docker" do |d| # d.build_image "/vagrant/centos", args: "-t thrift-centos" #end end thrift-0.19.0/build/docker/old/debian-jessie/0000777000000000000000000000000014303740367020740 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/debian-jessie/Dockerfile0000644000000000000000000001401114303740367022723 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Apache Thrift Docker build environment for Debian # # Known missing client libraries: # - dotnetcore # - rust FROM buildpack-deps:jessie-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive # Add apt sources # jessie-backports for cmake and some ruby bits RUN echo "deb http://ftp.debian.org/debian jessie-backports main" > /etc/apt/sources.list.d/jessie-backports.list # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \ sed -i /etc/apt/sources.list.d/dart_stable.list -e 's/https:/http:/g' RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ bison \ build-essential \ clang \ debhelper \ flex \ pkg-config && \ apt-get -t jessie-backports install -y --no-install-recommends cmake RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-dev \ libboost-filesystem-dev \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ libboost-thread-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ openjdk-7-jdk \ maven RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-pip \ python-setuptools \ python-twisted \ python-zope.interface \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-setuptools \ python3-pip RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-bundler \ ruby-dev \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl RUN apt-get -t jessie-backports install -y ruby-bundler RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php5 \ php5-dev \ php5-cli \ php-pear \ re2c \ phpunit \ `# GlibC dependencies` \ libglib2.0-dev RUN apt-get update && apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ erlang-base \ erlang-eunit \ erlang-dev \ erlang-tools \ rebar RUN apt-get update && apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ neko \ neko-dev \ libneko0 RUN apt-get update && apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs \ nodejs-dev \ nodejs-legacy \ npm RUN apt-get update && apt-get install -y --no-install-recommends \ `# D dependencies` \ xdg-utils \ `# Dart dependencies` \ dart \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev \ `# MinGW dependencies` \ mingw32 \ mingw32-binutils \ `# mingw32-runtime` \ nsis \ `# Clean up` \ && rm -rf /var/cache/apt/* && \ rm -rf /var/lib/apt/lists/* && \ rm -rf /tmp/* && \ rm -rf /var/tmp/* # Ruby RUN gem install bundler --no-ri --no-rdoc # Python optional dependencies RUN pip2 install -U ipaddress backports.ssl_match_hostname tornado RUN pip3 install -U backports.ssl_match_hostname tornado # Go RUN curl -sSL https://storage.googleapis.com/golang/go1.4.3.linux-amd64.tar.gz | tar -C /usr/local/ -xz ENV PATH /usr/local/go/bin:$PATH # Haxe RUN mkdir -p /usr/lib/haxe && \ wget -O - https://github.com/HaxeFoundation/haxe/releases/download/3.2.1/haxe-3.2.1-linux64.tar.gz | \ tar -C /usr/lib/haxe --strip-components=1 -xz && \ ln -s /usr/lib/haxe/haxe /usr/bin/haxe && \ ln -s /usr/lib/haxe/haxelib /usr/bin/haxelib && \ mkdir -p /usr/lib/haxe/lib && \ chmod -R 777 /usr/lib/haxe/lib && \ haxelib setup /usr/lib/haxe/lib && \ haxelib install hxcpp # D RUN curl -sSL http://downloads.dlang.org/releases/2.x/2.070.0/dmd_2.070.0-0_amd64.deb -o /tmp/dmd_2.070.0-0_amd64.deb && \ dpkg -i /tmp/dmd_2.070.0-0_amd64.deb && \ rm /tmp/dmd_2.070.0-0_amd64.deb && \ curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ mv libevent-master/deimos/* openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv libevent-master/C/* openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf libevent-master openssl-master && \ echo 'gcc -Wl,--no-as-needed $*' > /usr/local/bin/gcc-dmd && \ chmod 755 /usr/local/bin/gcc-dmd && \ echo 'CC=/usr/local/bin/gcc-dmd' >> /etc/dmd.conf # Dart ENV PATH /usr/lib/dart/bin:$PATH # OCaml RUN echo 'deb http://ppa.launchpad.net/avsm/ppa/ubuntu trusty main' > /etc/apt/sources.list.d/avsm-official-ocaml.list && \ gpg --keyserver keyserver.ubuntu.com --recv 61707B09 && \ gpg --export --armor 61707B09 | apt-key add - && \ apt-get update && \ apt-get install -y ocaml opam && \ opam init && \ opam install oasis # Force utf8 locale to successfully build Haskell tf-random ENV LC_ALL C.UTF-8 ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/old/ubuntu-xenial/0000755000000000000000000000000014452237057021034 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/ubuntu-xenial/Dockerfile0000644000000000000000000002266114452237057023035 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Xenial # Using all stock Ubuntu Xenial packaging except for: # - d: does not come with Ubuntu so we're installing 2.087.0 for coverage # - dart: does not come with Ubuntu so we're installing 2.0.0-1 for coverage # - dotnet: does not come with Ubuntu # - go: Xenial comes with 1.6, but we need 1.10 or later # - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 10.x # - ocaml: causes stack overflow error, just started March 2018 not sure why # FROM buildpack-deps:xenial-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive ### Add apt repos RUN apt-get update && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends \ apt \ apt-transport-https \ apt-utils \ curl \ software-properties-common \ wget && \ # Dart curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list && \ # dotnet (core) curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > \ /etc/apt/sources.list.d/dotnetdev.list && \ # node.js curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_10.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list && \ # ruby 2.4 apt-add-repository ppa:brightbox/ruby-ng ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ llvm \ ninja-build \ pkg-config \ valgrind \ vim ENV PATH /usr/lib/llvm-3.8/bin:$PATH ### languages # TODO: "apt-get install" without "apt-get update" in the same "RUN" step can cause cache issues if modified later. # See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#run RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-dev \ libboost-filesystem-dev \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ libboost-thread-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools ENV D_VERSION 2.087.0 ENV DMD_DEB dmd_2.087.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-libevent-2.0 && \ git clone -b 'v1.1.6+1.0.1g' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.0.1g && \ mv deimos-openssl-1.0.1g/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-openssl-1.0.1g/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.0.1g ENV DART_VERSION 2.7.2-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ dotnet-sdk-7.0 \ dotnet-runtime-7.0 \ aspnetcore-runtime-7.0 \ dotnet-apphost-pack-7.0 # Erlang dependencies ARG ERLANG_OTP_VERSION=18.3.4.11 ARG ERLANG_REBAR_VERSION=3.13.2 RUN apt-get update && apt-get install -y --no-install-recommends automake libncurses5-dev && \ curl https://raw.githubusercontent.com/kerl/kerl/master/kerl -o /usr/local/bin/kerl && chmod +x /usr/local/bin/kerl && \ kerl build $ERLANG_OTP_VERSION && kerl install $ERLANG_OTP_VERSION /usr/local/lib/otp/ && . /usr/local/lib/otp/activate && \ curl https://s3.amazonaws.com/rebar3/rebar3 -o /usr/local/bin/rebar3 && chmod +x /usr/local/bin/rebar3 && \ curl -ssLo /usr/local/bin/rebar3 https://github.com/erlang/rebar3/releases/download/${ERLANG_REBAR_VERSION}/rebar3 && chmod +x /usr/local/bin/rebar3 && \ rebar3 --version ENV PATH /usr/local/lib/otp/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.18.5 ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 9e5de37f9c49942c601b191ac5fba404b868bfc21d446d6960acc12283d6e5f2 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev \ libneko0 && \ haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp 3.4.64 2>&1 > /dev/null # note: hxcpp 3.4.185 (latest) no longer ships static libraries, and caused a build failure ENV GRADLE_VERSION="8.0.2" RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ openjdk-8-jdk \ maven \ unzip && \ `# Gradle` \ wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \ (echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \ unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \ mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \ ln -s /usr/local/gradle/bin/gradle /usr/local/bin # disabled: same as ubuntu-bionic jobs # RUN apt-get install -y --no-install-recommends \ # `# Lua dependencies` \ # lua5.2 \ # lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives so stick with 5.2 here RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs # Test dependencies for running puppeteer RUN apt-get install -y --no-install-recommends \ `# JS dependencies` \ libxss1 \ libxtst6 \ libatk-bridge2.0-0 \ libgtk-3-0 # THRIFT-4517: causes stack overflows; version too old; skip ocaml in xenial # RUN apt-get install -y --no-install-recommends \ # `# OCaml dependencies` \ # ocaml \ # opam && \ # opam init --yes && \ # opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl \ libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php7.0 \ php7.0-cli \ php7.0-dev \ php-json \ php-pear \ re2c \ composer RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-backports.ssl-match-hostname \ python-ipaddress \ python-pip \ python-setuptools \ python-six \ python-tornado \ python-twisted \ python-wheel \ python-zope.interface \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface && \ pip install --upgrade backports.ssl_match_hostname RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby2.4 \ ruby2.4-dev \ ruby-bundler # Rust dependencies RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y # Locale(s) for cpp unit tests RUN apt-get install -y --no-install-recommends \ `# Locale dependencies` \ locales && \ locale-gen en_US.UTF-8 && \ locale-gen de_DE.UTF-8 && \ update-locale # NOTE: this does not reduce the image size but adds an additional layer. # # Clean up # RUN rm -rf /var/cache/apt/* && \ # rm -rf /var/lib/apt/lists/* && \ # rm -rf /tmp/* && \ # rm -rf /var/tmp/* ENV DOTNET_CLI_TELEMETRY_OPTOUT 1 ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/old/centos-7.3/0000777000000000000000000000000014303740367020036 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/centos-7.3/Dockerfile0000644000000000000000000001274714303740367022037 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Apache Thrift Docker build environment for CentOS # # Known missing client libraries: # - dotnet (will update to 2.0.0 separately) # - haxe (not in centos) FROM centos:7.3.1611 MAINTAINER Apache Thrift RUN yum install -y epel-release # General dependencies RUN yum install -y \ autoconf \ bison \ bison-devel \ clang \ clang-analyzer \ cmake3 \ curl \ flex \ gcc \ gcc-c++ \ gdb \ git \ libtool \ m4 \ make \ tar \ unzip \ valgrind \ wget && \ ln -s /usr/bin/cmake3 /usr/bin/cmake && \ ln -s /usr/bin/cpack3 /usr/bin/cpack && \ ln -s /usr/bin/ctest3 /usr/bin/ctest # C++ dependencies RUN yum install -y \ boost-devel-static \ zlib-devel \ openssl-devel \ libevent-devel && \ cd /usr/lib64 && \ ln -s libboost_thread-mt.a libboost_thread.a # C# Dependencies RUN yum install -y \ mono-core \ mono-devel \ mono-web-devel \ mono-extras # D Dependencies RUN yum install -y http://downloads.dlang.org/releases/2.x/2.076.0/dmd-2.076.0-0.fedora.x86_64.rpm xdg-utils RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ mv libevent-master/deimos/* openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv libevent-master/C/* openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf libevent-master openssl-master # Dart RUN cd /usr/local && \ wget -q https://storage.googleapis.com/dart-archive/channels/stable/release/1.24.2/sdk/dartsdk-linux-x64-release.zip && \ unzip -q dartsdk-linux-x64-release.zip && \ rm dartsdk-linux-x64-release.zip ENV PATH /usr/local/dart-sdk/bin:$PATH # Erlang Dependencies RUN curl -sSL http://packages.erlang-solutions.com/rpm/centos/erlang_solutions.repo -o /etc/yum.repos.d/erlang_solutions.repo && \ yum install -y \ erlang-kernel \ erlang-erts \ erlang-stdlib \ erlang-eunit \ erlang-rebar \ erlang-tools # GLibC Dependencies RUN yum install -y glib2-devel # Go Dependencies RUN curl -sSL https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz | tar -C /usr/local/ -xz ENV PATH /usr/local/go/bin:$PATH # Haxe Dependencies # Not in debian/stretch # Java Dependencies RUN yum install -y \ ant \ junit \ ant-junit \ java-1.8.0-openjdk-devel # Lua Dependencies # Lua in epel is too old (5.1.4, need 5.2) so we get the latest RUN yum install -y readline-devel && \ wget -q http://www.lua.org/ftp/lua-5.3.4.tar.gz && \ tar xzf lua-5.3.4.tar.gz && \ cd lua-5.3.4 && \ sed -i 's/CFLAGS= /CFLAGS= -fPIC /g' src/Makefile && \ make linux && \ make install && \ cd .. && \ rm -rf lua-5* # MinGW Dependencies RUN yum install -y \ mingw32-binutils \ mingw32-crt \ mingw32-nsis # Node.js Dependencies # Work around epel issue where they removed http-parser that nodejs depends on! RUN yum -y install https://opensource.enda.eu/packages/http-parser-2.7.1-3.el7.x86_64.rpm RUN yum install -y \ nodejs \ npm # Ocaml Dependencies RUN yum install -y \ ocaml \ ocaml-ocamldoc && \ wget -q https://raw.github.com/ocaml/opam/master/shell/opam_installer.sh -O - | sh -s /usr/local/bin && \ opam init --yes && \ opam install --yes oasis && \ echo '. /root/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true' >> ~/.bashrc # Perl Dependencies RUN yum install -y \ perl \ perl-version \ perl-Bit-Vector \ perl-Class-Accessor \ perl-ExtUtils-MakeMaker \ perl-Test-Simple \ perl-IO-Socket-SSL \ perl-Net-SSLeay \ perl-Crypt-SSLeay # PHP Dependencies RUN yum install -y \ php \ php-devel \ php-pear \ re2c \ php-phpunit-PHPUnit \ bzip2 # Python Dependencies RUN yum install -y \ python \ python-devel \ python-pip \ python-setuptools \ python34 \ python34-devel \ python34-pip \ python34-setuptools RUN pip2 install --upgrade pip RUN pip2 install --upgrade backports.ssl_match_hostname ipaddress setuptools six tornado tornado-testing twisted virtualenv zope-interface RUN pip3 install --upgrade pip RUN pip3 install --upgrade backports.ssl_match_hostname ipaddress setuptools six tornado tornado-testing twisted virtualenv zope-interface # Ruby Dependencies RUN yum install -y \ ruby \ ruby-devel \ rubygems && \ gem install bundler rake # Rust RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.17.0 ENV PATH /root/.cargo/bin:$PATH # Clean up RUN rm -rf /tmp/* && \ yum clean all ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/old/ubuntu-disco/0000755000000000000000000000000014452237057020655 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/ubuntu-disco/Dockerfile0000644000000000000000000002344014452237057022652 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Disco # with some updated packages. # FROM buildpack-deps:disco-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive ### Add apt repos RUN apt-get update && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends \ apt \ apt-transport-https \ apt-utils \ curl \ dirmngr \ software-properties-common \ wget # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list # dotnet (netcore) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \ chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \ chown root:root /etc/apt/sources.list.d/microsoft-prod.list # erlang RUN wget -O- https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc | apt-key add - && \ echo "deb https://packages.erlang-solutions.com/ubuntu disco contrib" | tee /etc/apt/sources.list.d/erlang.list # node.js RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_10.x disco main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ libasound2 \ libatk-bridge2.0-0 \ libgtk-3-0 \ llvm \ ninja-build \ pkg-config \ unzip \ valgrind \ vim ENV PATH /usr/lib/llvm-6.0/bin:$PATH # lib/as3 (ActionScript) RUN mkdir -p /usr/local/adobe/flex/4.6 && \ cd /usr/local/adobe/flex/4.6 && \ wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ unzip flex_sdk_4.6.zip ENV FLEX_HOME /usr/local/adobe/flex/4.6 RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \ tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ cd sbcl-${SBCL_VERSION}-x86-64-linux && \ ./install.sh && \ sbcl --version && \ cd .. && \ rm -rf sbcl* ENV D_VERSION 2.087.0 ENV DMD_DEB dmd_2.087.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-libevent-2.0 && \ git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.1.0h ENV DART_VERSION 2.7.2-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ dotnet-sdk-7.0 \ dotnet-runtime-7.0 \ aspnetcore-runtime-7.0 \ dotnet-apphost-pack-7.0 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ erlang && \ wget https://s3.amazonaws.com/rebar3/rebar3 -O /usr/bin/rebar3 && \ chmod 755 /usr/bin/rebar3 && \ rebar3 --version RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.19 ENV GOLANG_DOWNLOAD_URL https://go.dev/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 464b6b66591f6cf055bc5df90a9750bf5fbc9d038722bb84a9d56a2bea974be6 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev && \ haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp 2>&1 > /dev/null ENV GRADLE_VERSION="8.0.2" RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ maven \ openjdk-11-jdk-headless && \ `# Gradle` \ wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip && \ (echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c -) && \ unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip && \ mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle && \ ln -s /usr/local/gradle/bin/gradle /usr/local/bin RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives! # need to update our luasocket code, lua doesn't have luaL_openlib any more RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs # Test dependencies for running puppeteer RUN apt-get install -y --no-install-recommends \ `# JS dependencies` \ libxss1 \ libxtst6 # does not work on disco? # RUN apt-get install -y --no-install-recommends \ # `# OCaml dependencies` \ # ocaml \ # opam && \ # opam init --yes && \ # opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl \ libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php \ php-cli \ php-dev \ php-json \ php-pear \ re2c \ composer RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-ipaddress \ python-pip \ python-setuptools \ python-six \ python-tornado \ python-twisted \ python-wheel \ python-zope.interface && \ pip install --upgrade backports.ssl_match_hostname RUN apt-get install -y --no-install-recommends \ `# Python3 dependencies` \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-pip \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler # Rust dependencies RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.61.0 -y ENV PATH /root/.cargo/bin:$PATH # Swift on Linux for cross tests # does not work on disco # RUN cd / && \ # wget --quiet https://swift.org/builds/swift-4.2.1-release/ubuntu1804/swift-4.2.1-RELEASE/swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ # tar xf swift-4.2.1-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \ # rm swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ # swift --version # Locale(s) for cpp unit tests RUN apt-get install -y --no-install-recommends \ `# Locale dependencies` \ locales && \ locale-gen en_US.UTF-8 && \ locale-gen de_DE.UTF-8 && \ update-locale # cppcheck-1.82 has a nasty cpp parser bug, so we're using something newer # don't need this on disco, nobody uses it # RUN apt-get install -y --no-install-recommends \ # `# Static Code Analysis dependencies` \ # cppcheck \ # sloccount && \ # pip install flake8 && \ # wget -q "https://launchpad.net/ubuntu/+source/cppcheck/1.83-2/+build/14874703/+files/cppcheck_1.83-2_amd64.deb" && \ # dpkg -i cppcheck_1.83-2_amd64.deb && \ # rm cppcheck_1.83-2_amd64.deb # Clean up RUN rm -rf /var/cache/apt/* && \ rm -rf /var/lib/apt/lists/* && \ rm -rf /tmp/* && \ rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/old/ubuntu-artful/0000777000000000000000000000000014452237057021055 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/ubuntu-artful/Dockerfile0000644000000000000000000001755214452237057023055 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Artful # Using all stock Ubuntu Artful packaging except for: # - cpp: stock boost 1.62 in artful has a nasty bug so we use stock boost 1.63 # - d: dmd does not come with Ubuntu # - dart: does not come with Ubuntu. Pinned to last 1.x release # - dotnet: does not come with Ubuntu # - haxe: version 3.4.2 that comes with Ubuntu cores in our CI build # - go: artful comes with 1.9, we want the latest (supported) # - nodejs: want v8, artful comes with v6 # FROM buildpack-deps:artful-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive ### Add apt repos RUN apt-get update && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends \ apt \ apt-transport-https \ apt-utils \ curl \ dirmngr \ software-properties-common \ wget # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list ENV DART_VERSION 1.24.3-1 # dotnet (netcore) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-artful-prod artful main" > \ /etc/apt/sources.list.d/dotnetdev.list # haxe (https://haxe.org/download/linux/) RUN add-apt-repository ppa:haxe/releases -y # node.js RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_8.x artful main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ llvm \ ninja-build \ pkg-config \ valgrind \ vim ENV PATH /usr/lib/llvm-3.8/bin:$PATH # boost-1.62 has a terrible bug in boost::test, see https://svn.boost.org/trac10/ticket/12507 RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost1.63-all-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools ENV SBCL_VERSION 1.4.5 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ curl -O -J -L https://kent.dl.sourceforge.net/project/sbcl/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ cd sbcl-${SBCL_VERSION}-x86-64-linux && \ ./install.sh && \ sbcl --version && \ rm -rf sbcl* ENV D_VERSION 2.080.0 ENV DMD_DEB dmd_2.080.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf libevent-master && \ curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf openssl-master RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ dotnet-sdk-7.0 \ dotnet-runtime-7.0 \ aspnetcore-runtime-7.0 \ dotnet-apphost-pack-7.0 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ erlang-base \ erlang-eunit \ erlang-dev \ erlang-tools \ rebar RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.10 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 b5a64335f1490277b585832d1f6c7f8c6c11206cba5cd3f771dcb87b98ad1a33 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev && \ haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp 2>&1 > /dev/null RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ openjdk-8-jdk \ maven RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives! # need to update our luasocket code, lua doesn't have luaL_openlib any more RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs # Test dependencies for running puppeteer RUN apt-get install -y --no-install-recommends \ `# JS dependencies` \ libxss1 RUN apt-get install -y --no-install-recommends \ `# OCaml dependencies` \ ocaml \ opam && \ opam init --yes && \ opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php \ php-cli \ php-dev \ php-pear \ re2c \ composer RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-ipaddress \ python-pip \ python-setuptools \ python-six \ python-tornado \ python-twisted \ python-wheel \ python-zope.interface && \ pip install --upgrade backports.ssl_match_hostname RUN apt-get install -y --no-install-recommends \ `# Python3 dependencies` \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-pip \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler RUN apt-get install -y --no-install-recommends \ `# Rust dependencies` \ cargo \ rustc RUN apt-get install -y --no-install-recommends \ `# Static Code Analysis dependencies` \ cppcheck \ sloccount && \ pip install flake8 # Clean up RUN rm -rf /var/cache/apt/* && \ rm -rf /var/lib/apt/lists/* && \ rm -rf /tmp/* && \ rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/old/debian-stretch/0000777000000000000000000000000014452237057021134 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/debian-stretch/Dockerfile0000644000000000000000000001515514452237057023131 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Apache Thrift Docker build environment for Debian Stretch # # Known issues: # - d: deimos for libevent and openssl disabled - build errors # - dotnetcore, because netcore is for 1.0.0-preview and 2.0.0 is out # - rust: cargo not in debian repo - perhaps not needed? FROM buildpack-deps:stretch-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive ### Add apt repos RUN apt-get update && apt-get install -y --no-install-recommends apt apt-transport-https curl wget apt-utils # D RUN wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \ apt-get update && apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list && \ sed -i /etc/apt/sources.list.d/dart_stable.list -e 's/https:/http:/g' # dotnet (core) 2.0.0 - project isn't ready for this yet: # RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ # echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list # node.js (this step runs apt-get update internally) RUN curl -sL https://deb.nodesource.com/setup_8.x | bash ### install general dependencies RUN apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ ninja-build \ pkg-config \ valgrind \ vim ### languages RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-dev \ libboost-filesystem-dev \ libboost-program-options-dev \ libboost-system-dev \ libboost-test-dev \ libboost-thread-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools RUN apt-get install -y --no-install-recommends \ `# D dependencies` \ dmd-bin \ libevent-dev \ libssl-dev \ xdg-utils # libevent deimos disabled - build errors # RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ # curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ # mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ # mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \ # rm -rf libevent-master # openssl deimos doesn't work with openssl-1.1.0 - disabling it for now: # RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ # mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ # mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \ # rm -rf openssl-master RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart ENV PATH /usr/lib/dart/bin:$PATH # project isn't ready for this quite yet: # RUN apt-get install -y --no-install-recommends \ # `# dotnet core dependencies` \ # dotnet-sdk-7.0 \ # dotnet-runtime-7.0 \ # aspnetcore-runtime-7.0 \ # dotnet-apphost-pack-7.0 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ erlang-base \ erlang-eunit \ erlang-dev \ erlang-tools \ rebar RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev RUN apt-get install -y --no-install-recommends \ `# golang (go) dependencies` \ golang-go RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ haxe \ neko \ neko-dev RUN haxelib setup --always /usr/share/haxe/lib && \ haxelib install --always hxcpp RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ openjdk-8-jdk \ maven RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.2 \ lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # same for debian stretch # lua5.3 does not install alternatives so stick with 5.2 here RUN apt-get install -y --no-install-recommends \ `# Node.js dependencies` \ nodejs RUN apt-get install -y --no-install-recommends \ `# OCaml dependencies` \ ocaml \ opam && \ opam init --yes && \ opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php7.0 \ php7.0-cli \ php7.0-dev \ php-pear \ re2c \ phpunit RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-backports.ssl-match-hostname \ python-ipaddress \ python-pip \ python-setuptools \ python-six \ python-tornado \ python-twisted \ python-wheel \ python-zope.interface \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-setuptools \ python3-six \ python3-tornado \ python3-twisted \ python3-wheel \ python3-zope.interface && \ pip install --upgrade backports.ssl_match_hostname RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler RUN gem install bundler --no-ri --no-rdoc RUN apt-get install -y --no-install-recommends \ `# Rust dependencies` \ rustc # Update anything else left hanging RUN apt-get dist-upgrade -y # Clean up RUN rm -rf /var/cache/apt/* && \ rm -rf /var/lib/apt/lists/* && \ rm -rf /tmp/* && \ rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/docker/old/ubuntu-trusty/0000777000000000000000000000000014303740367021130 5ustar00rootroot00000000000000thrift-0.19.0/build/docker/old/ubuntu-trusty/Dockerfile0000644000000000000000000001703214303740367023121 0ustar00rootroot00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # Apache Thrift Docker build environment for Ubuntu Trusty # Using all stock Ubuntu Trusty packaging except for: # - d: does not come with Ubuntu so we're installing 2.070.0 # - dart: does not come with Ubuntu so we're installing 1.20.1 # - dotnetcore, disabled because netcore is for 1.0.0-preview and 2.0.0 is out # - haxe, disabled because the distro comes with 3.0.0 and it cores while installing # - node.js, disabled because it is at 0.10.0 in the distro which is too old (need 4+) # - ocaml, disabled because it fails to install properly # FROM buildpack-deps:trusty-scm MAINTAINER Apache Thrift ENV DEBIAN_FRONTEND noninteractive ### Add apt repos RUN apt-get update && \ apt-get dist-upgrade -y && \ apt-get install -y --no-install-recommends \ apt \ apt-transport-https \ apt-utils \ curl \ dirmngr \ software-properties-common \ wget # D RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \ wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \ wget -qO - https://dlang.org/d-keyring.gpg | apt-key add - # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list RUN apt-get update && apt-get install -y --no-install-recommends \ `# General dependencies` \ bash-completion \ bison \ build-essential \ clang \ cmake \ debhelper \ flex \ gdb \ llvm \ ninja-build \ pkg-config \ valgrind \ vim ENV PATH /usr/lib/llvm-3.8/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ libevent-dev \ libssl-dev \ qt5-default \ qtbase5-dev \ qtbase5-dev-tools RUN apt-get install -y --no-install-recommends \ `# D dependencies` \ dmd-bin=2.070.2-0 \ libphobos2-dev=2.070.2-0 \ dub \ dfmt \ dscanner \ xdg-utils RUN mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf libevent-master RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/master.tar.gz| tar xz && \ mv openssl-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv openssl-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf openssl-master RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=1.20.1-1 ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ erlang-base \ erlang-eunit \ erlang-dev \ erlang-tools \ rebar RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang ENV GOLANG_VERSION 1.7.6 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz ENV GOLANG_DOWNLOAD_SHA256 ad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz # disabled because it cores while installing # RUN apt-get install -y --no-install-recommends \ # `# Haxe dependencies` \ # haxe \ # neko \ # neko-dev && \ # haxelib setup /usr/share/haxe/lib && \ # haxelib install hxcpp 3.2.102 RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ openjdk-7-jdk \ maven RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ lua5.1 \ lua5.1-dev # disabled because it is too old # RUN apt-get install -y --no-install-recommends \ # `# Node.js dependencies` \ # nodejs \ # npm # disabled because it fails to install properly # RUN apt-get install -y --no-install-recommends \ # `# OCaml dependencies` \ # ocaml \ # opam && \ # opam init --yes && \ # opam install --yes oasis RUN apt-get install -y --no-install-recommends \ `# Perl dependencies` \ libbit-vector-perl \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ libnet-ssleay-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ php5 \ php5-cli \ php5-dev \ php-pear \ re2c && \ wget https://getcomposer.org/installer -O - -q | php -- --quiet --install-dir=/usr/local/bin/ --filename=composer RUN apt-get install -y --no-install-recommends \ `# Python dependencies` \ python-all \ python-all-dbg \ python-all-dev \ python-pip \ python-setuptools \ python-six \ python-twisted \ python-wheel \ python-zope.interface \ python3-all \ python3-all-dbg \ python3-all-dev \ python3-pip \ python3-setuptools \ python3-six \ python3-wheel \ python3-zope.interface && \ pip install -U ipaddress backports.ssl_match_hostname tornado && \ pip3 install -U backports.ssl_match_hostname tornado # installing tornado by pip/pip3 instead of debian package # if we install the debian package, the build fails in py2 RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ ruby-dev \ ruby-bundler RUN gem install bundler --no-ri --no-rdoc RUN apt-get install -y --no-install-recommends \ `# Rust dependencies` \ cargo \ rustc RUN apt-get install -y --no-install-recommends \ `# Static Code Analysis dependencies` \ cppcheck \ sloccount && \ pip install flake8 # Install BouncyCastle provider to fix Java builds issues with JDK 7 # Builds accessing repote repositories fail as seen here: https://github.com/travis-ci/travis-ci/issues/8503 RUN apt-get install -y --no-install-recommends \ `# BouncyCastle JCE Provider dependencies` \ libbcprov-java && \ ln -s /usr/share/java/bcprov.jar /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/ext/bcprov.jar && \ awk -F . -v OFS=. 'BEGIN{n=2}/^security\.provider/ {split($3, posAndEquals, "=");$3=n++"="posAndEquals[2];print;next} 1' /etc/java-7-openjdk/security/java.security > /tmp/java.security && \ echo "security.provider.1=org.bouncycastle.jce.provider.BouncyCastleProvider" >> /tmp/java.security && \ mv /tmp/java.security /etc/java-7-openjdk/security/java.security # Clean up RUN rm -rf /var/cache/apt/* && \ rm -rf /var/lib/apt/lists/* && \ rm -rf /tmp/* && \ rm -rf /var/tmp/* ENV THRIFT_ROOT /thrift RUN mkdir -p $THRIFT_ROOT/src COPY Dockerfile $THRIFT_ROOT/ WORKDIR $THRIFT_ROOT/src thrift-0.19.0/build/cmake/0000777000000000000000000000000014452237057015273 5ustar00rootroot00000000000000thrift-0.19.0/build/cmake/DefineInstallationPaths.cmake0000644000000000000000000000344614303740367023052 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Define the default install paths set(BIN_INSTALL_DIR "bin" CACHE PATH "The binary install dir (default: bin)") if(MSVC) set(LIB_INSTALL_DIR "bin${LIB_SUFFIX}" CACHE PATH "The library install dir (default: bin${LIB_SUFFIX})") else() set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The library install dir (default: lib${LIB_SUFFIX})") endif() set(INCLUDE_INSTALL_DIR "include" CACHE PATH "The library install dir (default: include)") set(CMAKE_INSTALL_DIR "lib/cmake" CACHE PATH "The subdirectory to install cmake config files (default: cmake)") set(PKGCONFIG_INSTALL_DIR "lib/pkgconfig" CACHE PATH "The subdirectory to install pkgconfig config files (default: lib/pkgconfig)") set(DOC_INSTALL_DIR "share/doc" CACHE PATH "The subdirectory to install documentation files (default: share/doc)") set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "${CMAKE_INSTALL_PREFIX}/bin") set(libdir "${CMAKE_INSTALL_PREFIX}/lib") set(includedir "${CMAKE_INSTALL_PREFIX}/include") set(cmakedir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DIR}") thrift-0.19.0/build/cmake/uninstall.cmake0000644000000000000000000000275014303740367020304 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # cmake_minimum_required(VERSION 3.4) set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") if(NOT EXISTS ${MANIFEST}) message(FATAL_ERROR "Cannot find install mainfest: ${MANIFEST}") endif() file(STRINGS ${MANIFEST} files) foreach(file ${files}) if(EXISTS ${file} OR IS_SYMLINK ${file}) message(STATUS "Removing: ${file}") execute_process( COMMAND ${CMAKE_COMMAND} -E remove ${file} RESULT_VARIABLE result OUTPUT_QUIET ERROR_VARIABLE stderr ERROR_STRIP_TRAILING_WHITESPACE ) if(NOT ${result} EQUAL 0) message(FATAL_ERROR "${stderr}") endif() else() message(STATUS "Does-not-exist: ${file}") endif() endforeach(file) thrift-0.19.0/build/cmake/DefineOptions.cmake0000644000000000000000000002152514303740367021042 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include(CMakeDependentOption) set(THRIFT_COMPILER "" CACHE FILEPATH "External Thrift compiler to use during build") # Additional components option(BUILD_COMPILER "Build Thrift compiler" ON) if(BUILD_COMPILER OR EXISTS ${THRIFT_COMPILER}) set(HAVE_COMPILER ON) endif() CMAKE_DEPENDENT_OPTION(BUILD_TESTING "Build with unit tests" ON "HAVE_COMPILER" OFF) CMAKE_DEPENDENT_OPTION(BUILD_TUTORIALS "Build Thrift tutorials" ON "HAVE_COMPILER" OFF) option(BUILD_LIBRARIES "Build Thrift libraries" ON) # Libraries to build # Each language library can be enabled or disabled using the WITH_ flag. # By default CMake checks if the required dependencies for a language are present # and enables the library if all are found. This means the default is to build as # much as possible but leaving out libraries if their dependencies are not met. if (NOT Boost_USE_STATIC_LIBS) add_definitions(-DBOOST_ALL_DYN_LINK) add_definitions(-DBOOST_TEST_DYN_LINK) endif() # as3 option(WITH_AS3 "Build ActionScript 3 Thrift Library" ON) if (WITH_AS3) set(POSSIBLE_PATHS "${FLEX_HOME}/bin" "$ENV{FLEX_HOME}/bin") find_program(HAVE_COMPC NAMES compc HINTS ${POSSIBLE_PATHS}) endif () CMAKE_DEPENDENT_OPTION(BUILD_AS3 "Build as3 library" ON "BUILD_LIBRARIES;WITH_AS3;HAVE_COMPC" OFF) # C++ option(WITH_CPP "Build C++ Thrift library" ON) if(WITH_CPP) # NOTE: Currently the following options are C++ specific, # but in future other libraries might reuse them. # So they are not dependent on WITH_CPP but setting them without WITH_CPP currently # has no effect. if(ZLIB_LIBRARY) # FindZLIB.cmake does not normalize path so we need to do it ourselves. file(TO_CMAKE_PATH ${ZLIB_LIBRARY} ZLIB_LIBRARY) endif() find_package(ZLIB QUIET) CMAKE_DEPENDENT_OPTION(WITH_ZLIB "Build with ZLIB support" ON "ZLIB_FOUND" OFF) find_package(Libevent QUIET) CMAKE_DEPENDENT_OPTION(WITH_LIBEVENT "Build with libevent support" ON "Libevent_FOUND" OFF) find_package(Qt5 QUIET COMPONENTS Core Network) CMAKE_DEPENDENT_OPTION(WITH_QT5 "Build with Qt5 support" ON "Qt5_FOUND" OFF) endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON "BUILD_LIBRARIES;WITH_CPP" OFF) # C GLib option(WITH_C_GLIB "Build C (GLib) Thrift library" ON) if(WITH_C_GLIB) find_package(GLIB QUIET COMPONENTS gobject) endif() CMAKE_DEPENDENT_OPTION(BUILD_C_GLIB "Build C (GLib) library" ON "BUILD_LIBRARIES;WITH_C_GLIB;GLIB_FOUND" OFF) # OpenSSL if(WITH_CPP OR WITH_C_GLIB) find_package(OpenSSL QUIET) CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON "OPENSSL_FOUND" OFF) endif() # Java option(WITH_JAVA "Build Java Thrift library" ON) if(ANDROID) find_package(Gradle QUIET) CMAKE_DEPENDENT_OPTION(BUILD_JAVA "Build Java library" ON "BUILD_LIBRARIES;WITH_JAVA;GRADLE_FOUND" OFF) else() find_package(Gradle QUIET) find_package(Java QUIET) CMAKE_DEPENDENT_OPTION(BUILD_JAVA "Build Java library" ON "BUILD_LIBRARIES;WITH_JAVA;JAVA_FOUND;GRADLE_FOUND" OFF) endif() # Javascript option(WITH_JAVASCRIPT "Build Javascript Thrift library" ON) CMAKE_DEPENDENT_OPTION(BUILD_JAVASCRIPT "Build Javascript library" ON "BUILD_LIBRARIES;WITH_JAVASCRIPT;NOT WIN32; NOT CYGWIN" OFF) # NodeJS option(WITH_NODEJS "Build NodeJS Thrift library" ON) CMAKE_DEPENDENT_OPTION(BUILD_NODEJS "Build NodeJS library" ON "BUILD_LIBRARIES;WITH_NODEJS" OFF) # Python option(WITH_PYTHON "Build Python Thrift library" ON) find_package(PythonInterp QUIET) # for Python executable find_package(PythonLibs QUIET) # for Python.h CMAKE_DEPENDENT_OPTION(BUILD_PYTHON "Build Python library" ON "BUILD_LIBRARIES;WITH_PYTHON;PYTHONINTERP_FOUND;PYTHONLIBS_FOUND" OFF) # Common library options # https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html # Default on Windows is static, shared mode library support needs work... if(WIN32) set(DEFAULT_BUILD_SHARED_LIBS ON) else() set(DEFAULT_BUILD_SHARED_LIBS OFF) endif() option(BUILD_SHARED_LIBS "Build shared libraries" ${DEFAULT_BUILD_SHARED_LIBS}) if (WITH_SHARED_LIB) message(WARNING "WITH_SHARED_LIB is deprecated; use -DBUILD_SHARED_LIBS=ON instead") set(BUILD_SHARED_LIBS ON) elseif (WITH_STATIC_LIB) if (WITH_SHARED_LIB) message(FATAL_ERROR "Cannot build shared and static together; set BUILD_SHARED_LIBS instead.") endif () message(WARNING "WITH_STATIC_LIB is deprecated; use -DBUILD_SHARED_LIBS=OFF instead") set(BUILD_SHARED_LIBS OFF) endif () # Visual Studio only options if(MSVC) option(WITH_MT "Build using the static runtime 'MT' instead of the shared DLL-specific runtime 'MD' (MSVC only)" OFF) endif(MSVC) macro(MESSAGE_DEP flag summary) if(NOT ${flag}) message(STATUS " - ${summary}") endif() endmacro(MESSAGE_DEP flag summary) macro(PRINT_CONFIG_SUMMARY) message(STATUS "----------------------------------------------------------") message(STATUS "Thrift version: ${thrift_VERSION} (${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH})") message(STATUS "Thrift package version: ${PACKAGE_VERSION}") message(STATUS) message(STATUS "Build configuration summary") message(STATUS " Build compiler: ${BUILD_COMPILER}") message(STATUS " Build libraries: ${BUILD_LIBRARIES}") message(STATUS " Build tests: ${BUILD_TESTING}") MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_COMPILER=OFF and no valid THRIFT_COMPILER is given") message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") message(STATUS) message(STATUS "Language libraries:") message(STATUS) message(STATUS " Build as3 library: ${BUILD_AS3}") MESSAGE_DEP(WITH_AS3 "Disabled by WITH_AS3=OFF") MESSAGE_DEP(HAVE_COMPC "Adobe Flex compc was not found - did you set env var FLEX_HOME?") message(STATUS) message(STATUS " Build with OpenSSL: ${WITH_OPENSSL}") if(WITH_OPENSSL) message(STATUS " Version: ${OPENSSL_VERSION}") endif() message(STATUS) message(STATUS " Build C++ library: ${BUILD_CPP}") MESSAGE_DEP(WITH_CPP "Disabled by WITH_CPP=OFF") if (BUILD_CPP) message(STATUS " C++ Language Level: ${CXX_LANGUAGE_LEVEL}") message(STATUS " Build shared libraries: ${BUILD_SHARED_LIBS}") message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") message(STATUS " Build with Qt5 support: ${WITH_QT5}") message(STATUS " Build with ZLIB support: ${WITH_ZLIB}") endif () message(STATUS) message(STATUS " Build C (GLib) library: ${BUILD_C_GLIB}") MESSAGE_DEP(WITH_C_GLIB "Disabled by WITH_C_GLIB=OFF") MESSAGE_DEP(GLIB_FOUND "GLib missing") message(STATUS) message(STATUS " Build Java library: ${BUILD_JAVA}") MESSAGE_DEP(WITH_JAVA "Disabled by WITH_JAVA=OFF") if(ANDROID) MESSAGE_DEP(GRADLE_FOUND "Gradle missing") else() MESSAGE_DEP(JAVA_FOUND "Java Runtime missing") MESSAGE_DEP(GRADLE_FOUND "Gradle missing") endif() message(STATUS " Build Javascript library: ${BUILD_JAVASCRIPT}") MESSAGE_DEP(WITH_JAVASCRIPT "Disabled by WITH_JAVASCRIPT=OFF") message(STATUS " Build NodeJS library: ${BUILD_NODEJS}") MESSAGE_DEP(WITH_NODEJS "Disabled by WITH_NODEJS=OFF") message(STATUS) message(STATUS " Build Python library: ${BUILD_PYTHON}") MESSAGE_DEP(WITH_PYTHON "Disabled by WITH_PYTHON=OFF") MESSAGE_DEP(PYTHONLIBS_FOUND "Python libraries missing") if(MSVC) message(STATUS " Using static runtime library: ${WITH_MT}") endif(MSVC) message(STATUS) message(STATUS) message(STATUS "----------------------------------------------------------") endmacro(PRINT_CONFIG_SUMMARY) thrift-0.19.0/build/cmake/StaticCodeAnalysis.cmake0000644000000000000000000000065414303740367022022 0ustar00rootroot00000000000000find_package(ClangTools QUIET) if(clang-tidy_FOUND AND run-clang-tidy_FOUND AND NOT TARGET do_run_clang_tidy) add_custom_target( do_run_clang_tidy COMMAND ClangTools::run-clang-tidy -clang-tidy-binary "$" -p ${CMAKE_BINARY_DIR} "-quiet" > ./run-clang-tidy.txt DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) endif() thrift-0.19.0/build/cmake/android-toolchain.cmake0000644000000000000000000000201314303740367021661 0ustar00rootroot00000000000000set(ANDROID_NDK "/opt/android-ndk" CACHE) set(ANDROID_PLATFORM "android-15" CACHE) set(ANDROID_ARCH "arch-arm" CACHE) set(ANDROID_TOOL_ARCH "android-arm" CACHE) set(ANDROID_CPU "armeabi-v7a" CACHE) set(ANDROID_GCC_VERSION 4.9 CACHE) set(HOST_ARCH linux-x86_64 CACHE) set(CMAKE_SYSTEM_NAME Android) set(ANDROID_SYSROOT "${ANDROID_NDK}/platforms/${ANDROID_PLATFORM}/${ANDROID_ARCH}") set(ANDROID_TRIPLET arm-linux-androideabi) set(ANDROID_STL "${ANDROID_NDK}/sources/cxx-stl/gnu-libstd++/${ANDROID_GCC_VERSION}") set(_COMPILER_ROOT ${ANDROID_NDK}/prebuilt/${ANDROID_TRIPLET}-${ANDROID_GCC_VERSION}/prebuilt/${HOST_ARCH}) set(CMAKE_C_COMPILER ${_COMPILER_ROOT}/bin/${ANDROID_TRIPLET}-gcc) set(CMAKE_CXCX_COMPILER ${_COMPILER_ROOT}/bin/${ANDROID_TRIPLET}-g++) include_directories( ${ANDROID_STL}/include ${ANDROID_STL}/libs/${ANDROID_CPU}/include) set(CMAKE_FIND_ROOT_PATH ${ANDROID_SYSROOT}) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) thrift-0.19.0/build/cmake/FindGLIB.cmake0000644000000000000000000001256214303740367017613 0ustar00rootroot00000000000000# - Try to find Glib and its components (gio, gobject etc) # Once done, this will define # # GLIB_FOUND - system has Glib # GLIB_INCLUDE_DIRS - the Glib include directories # GLIB_LIBRARIES - link these to use Glib # # Optionally, the COMPONENTS keyword can be passed to find_package() # and Glib components can be looked for. Currently, the following # components can be used, and they define the following variables if # found: # # gio: GLIB_GIO_LIBRARIES # gobject: GLIB_GOBJECT_LIBRARIES # gmodule: GLIB_GMODULE_LIBRARIES # gthread: GLIB_GTHREAD_LIBRARIES # # Note that the respective _INCLUDE_DIR variables are not set, since # all headers are in the same directory as GLIB_INCLUDE_DIRS. # # Copyright (C) 2012 Raphael Kubo da Costa # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS # IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. find_package(PkgConfig) pkg_check_modules(PC_GLIB QUIET glib-2.0) find_library(GLIB_LIBRARIES NAMES glib-2.0 HINTS ${PC_GLIB_LIBDIR} ${PC_GLIB_LIBRARY_DIRS} ) # Files in glib's main include path may include glibconfig.h, which, # for some odd reason, is normally in $LIBDIR/glib-2.0/include. get_filename_component(_GLIB_LIBRARY_DIR ${GLIB_LIBRARIES} PATH) find_path(GLIBCONFIG_INCLUDE_DIR NAMES glibconfig.h HINTS ${PC_LIBDIR} ${PC_LIBRARY_DIRS} ${_GLIB_LIBRARY_DIR} ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0/include ) find_path(GLIB_INCLUDE_DIR NAMES glib.h HINTS ${PC_GLIB_INCLUDEDIR} ${PC_GLIB_INCLUDE_DIRS} PATH_SUFFIXES glib-2.0 ) set(GLIB_INCLUDE_DIRS ${GLIB_INCLUDE_DIR} ${GLIBCONFIG_INCLUDE_DIR}) if(GLIBCONFIG_INCLUDE_DIR) # Version detection file(READ "${GLIBCONFIG_INCLUDE_DIR}/glibconfig.h" GLIBCONFIG_H_CONTENTS) string(REGEX MATCH "#define GLIB_MAJOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MAJOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MINOR_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MINOR "${CMAKE_MATCH_1}") string(REGEX MATCH "#define GLIB_MICRO_VERSION ([0-9]+)" _dummy "${GLIBCONFIG_H_CONTENTS}") set(GLIB_VERSION_MICRO "${CMAKE_MATCH_1}") set(GLIB_VERSION "${GLIB_VERSION_MAJOR}.${GLIB_VERSION_MINOR}.${GLIB_VERSION_MICRO}") endif() # Additional Glib components. We only look for libraries, as not all of them # have corresponding headers and all headers are installed alongside the main # glib ones. foreach (_component ${GLIB_FIND_COMPONENTS}) if (${_component} STREQUAL "gio") find_library(GLIB_GIO_LIBRARIES NAMES gio-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GIO_LIBRARIES) elseif (${_component} STREQUAL "gobject") find_library(GLIB_GOBJECT_LIBRARIES NAMES gobject-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GOBJECT_LIBRARIES) elseif (${_component} STREQUAL "gmodule") find_library(GLIB_GMODULE_LIBRARIES NAMES gmodule-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GMODULE_LIBRARIES) elseif (${_component} STREQUAL "gthread") find_library(GLIB_GTHREAD_LIBRARIES NAMES gthread-2.0 HINTS ${_GLIB_LIBRARY_DIR}) set(ADDITIONAL_REQUIRED_VARS ${ADDITIONAL_REQUIRED_VARS} GLIB_GTHREAD_LIBRARIES) elseif (${_component} STREQUAL "gio-unix") # gio-unix is compiled as part of the gio library, but the include paths # are separate from the shared glib ones. Since this is currently only used # by WebKitGTK+ we don't go to extraordinary measures beyond pkg-config. pkg_check_modules(GIO_UNIX QUIET gio-unix-2.0) endif () endforeach () include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLIB REQUIRED_VARS GLIB_INCLUDE_DIRS GLIB_LIBRARIES ${ADDITIONAL_REQUIRED_VARS} VERSION_VAR GLIB_VERSION) mark_as_advanced( GLIBCONFIG_INCLUDE_DIR GLIB_GIO_LIBRARIES GLIB_GIO_UNIX_LIBRARIES GLIB_GMODULE_LIBRARIES GLIB_GOBJECT_LIBRARIES GLIB_GTHREAD_LIBRARIES GLIB_INCLUDE_DIR GLIB_INCLUDE_DIRS GLIB_LIBRARIES ) thrift-0.19.0/build/cmake/CPackConfig.cmake0000644000000000000000000000502514303740367020400 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #TODO: Should we bundle system libraries for DLLs? #include(InstallRequiredSystemLibraries) # For help take a look at: # http://www.cmake.org/Wiki/CMake:CPackConfiguration ### general settings set(CPACK_PACKAGE_NAME "thrift") set(CPACK_PACKAGE_VERSION "${PACKAGE_VERSION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Apache Thrift") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_VENDOR "Apache Software Foundation") set(CPACK_PACKAGE_CONTACT "dev@thrift.apache.org") set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") set(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}") ### versions set(CPACK_PACKAGE_VERSION_MAJOR ${thrift_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${thrift_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${thrift_VERSION_PATCH}) ### source generator set(CPACK_SOURCE_GENERATOR "TGZ") set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") ### zip generator set(CPACK_GENERATOR "ZIP") set(CPACK_PACKAGE_INSTALL_DIRECTORY "thrift") if(CMAKE_SYSTEM_NAME STREQUAL "Windows") set(CPACK_GENERATOR "NSIS") set(CPACK_NSIS_HELP_LINK "http://thrift.apache.org") set(CPACK_NSIS_MENU_LINKS "http://thrift.apache.org" "Apache Thrift - Web Site" "https://issues.apache.org/jira/browse/THRIFT" "Apache Thrift - Issues") set(CPACK_NSIS_CONTACT ${CPACK_PACKAGE_CONTACT}) set(CPACK_NSIS_MODIFY_PATH "ON") set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_NAME}") else() set(CPACK_GENERATOR "DEB" ) set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_CONTACT}) endif() include(CPack) thrift-0.19.0/build/cmake/FindInttypes.cmake0000644000000000000000000000254314303740367020713 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # find msinttypes on compilers that don't provide it, for example # VS2010 # Usage: # Provide INTTYPES_ROOT if you need it # Result: INTTYPES_INCLUDE_DIRS, where to find inttypes.h # Result: Inttypes_FOUND, If false, inttypes.h was not found find_path(INTTYPES_INCLUDE_DIRS inttypes.h HINTS ${INTTYPES_ROOT}) if (INTTYPES_INCLUDE_DIRS) set(Inttypes_FOUND TRUE) else () set(Inttypes_FOUND FALSE) if (Inttypes_FIND_REQUIRED) message(FATAL_ERROR "Could NOT find inttypes.h") endif () message(STATUS "inttypes.h NOT found") endif () mark_as_advanced( INTTYPES_INCLUDE_DIRS ) thrift-0.19.0/build/cmake/README.md0000644000000000000000000000363514303740367016553 0ustar00rootroot00000000000000# Apache Thrift - CMake Build ## Goal Extend Apache Thrift's *make cross* approach to the build system. Due to growing the field of operating system support, a proper executable and library detection mechanism running on as much platforms as possible becomes required. The other aspect to simplify the release process and package generation process. As nice side benefit of CMake is the generation of development environment specific soultion files. => No solution files within source tree. ## Prerequisites These are language-specific, however for C++ you must provide: - Boost - OpenSSL You may optionally provide: - libevent - zlib ## Usage To use CMake you first create an out-of-tree build directory, then use CMake to generate a build framework, then build: mkdir /tmp/build cd /tmp/build cmake /location/to/thrift if you use a specific toolchain pass it to cmake, the same for options: cmake -DCMAKE_TOOLCHAIN_FILE=../build/cmake/mingw32-toolchain.cmake .. cmake -DCMAKE_C_COMPILER=clang-3.5 -DCMAKE_CXX_COMPILER=clang++-3.5 .. cmake -DTHRIFT_COMPILER_HS=OFF .. cmake -DWITH_ZLIB=ON .. and open the development environment you like with the solution or do this: make make check make cross make dist or on Windows, the following will produce a solution file you can use inside Visual Studio: cmake -G "Visual Studio 15 2017 Win64" \ -DBOOST_ROOT=C:/3rdparty/boost_1_69_0 \ -DBOOST_LIBRARYDIR=C:/3rdparty/boost_1_69_0/lib64-msvc-14.1^ -DZLIB_ROOT=C:/3rdparty/zlib-1.2.11 ## TODO * git hash or tag based versioning depending on source state * build tutorial * build test * enable/disable * make cross * make dist (create an alias to make package_source) * make doc * cpack (C++ and make dist only ?) * thrift-compiler * libthrift * tutorial * test * merge into /README.mdthrift-0.19.0/build/cmake/ThriftMacros.cmake0000644000000000000000000000371614303740367020703 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # macro(ADD_PKGCONFIG_THRIFT name) configure_file("${name}.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc" @ONLY) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc" DESTINATION "${PKGCONFIG_INSTALL_DIR}") endmacro(ADD_PKGCONFIG_THRIFT) macro(ADD_LIBRARY_THRIFT name) add_library(${name} ${ARGN}) target_include_directories(${name} INTERFACE $) set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}${THRIFT_RUNTIME_POSTFIX} # windows link variants (/MT, /MD, /MTd, /MDd) get different names VERSION ${thrift_VERSION}) # set_target_properties(${name} PROPERTIES PUBLIC_HEADER "${thriftcpp_HEADERS}") install(TARGETS ${name} EXPORT "${name}Targets" RUNTIME DESTINATION "${BIN_INSTALL_DIR}" LIBRARY DESTINATION "${LIB_INSTALL_DIR}" ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" PUBLIC_HEADER DESTINATION "${INCLUDE_INSTALL_DIR}") export(EXPORT "${name}Targets" FILE "${CMAKE_CURRENT_BINARY_DIR}/${name}/${name}Targets.cmake" NAMESPACE "${name}::") install(EXPORT "${name}Targets" FILE "${name}Targets.cmake" NAMESPACE "${name}::" DESTINATION "${CMAKE_INSTALL_DIR}/thrift") endmacro()thrift-0.19.0/build/cmake/ConfigureChecks.cmake0000644000000000000000000000641414303740367021336 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include(CheckFunctionExists) include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckSymbolExists) include(CheckStructHasMember) include(CheckCSourceCompiles) include(CheckCXXSourceCompiles) if (Inttypes_FOUND) # This allows the inttypes.h and stdint.h checks to succeed on platforms that # do not natively provide there. set (CMAKE_REQUIRED_INCLUDES ${INTTYPES_INCLUDE_DIRS}) endif () check_include_file(arpa/inet.h HAVE_ARPA_INET_H) check_include_file(fcntl.h HAVE_FCNTL_H) check_include_file(getopt.h HAVE_GETOPT_H) check_include_file(inttypes.h HAVE_INTTYPES_H) check_include_file(netdb.h HAVE_NETDB_H) check_include_file(netinet/in.h HAVE_NETINET_IN_H) check_include_file(signal.h HAVE_SIGNAL_H) check_include_file(stdint.h HAVE_STDINT_H) check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(pthread.h HAVE_PTHREAD_H) check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H) check_include_file(sys/param.h HAVE_SYS_PARAM_H) check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H) check_include_file(sys/socket.h HAVE_SYS_SOCKET_H) check_include_file(sys/stat.h HAVE_SYS_STAT_H) check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(sys/un.h HAVE_SYS_UN_H) check_include_file(poll.h HAVE_POLL_H) check_include_file(sys/poll.h HAVE_SYS_POLL_H) check_include_file(sys/select.h HAVE_SYS_SELECT_H) check_include_file(sched.h HAVE_SCHED_H) check_include_file(string.h HAVE_STRING_H) check_include_file(strings.h HAVE_STRINGS_H) # Check for afunix.h on Windows (since Windows 10 Insider Build 17063): check_cxx_source_compiles( " #define WIN32_LEAN_AND_MEAN #include #include #include int main(){(void)sizeof(((struct sockaddr_un *)0)->sun_path); return 0;} " HAVE_AF_UNIX_H) check_function_exists(gethostbyname HAVE_GETHOSTBYNAME) check_function_exists(gethostbyname_r HAVE_GETHOSTBYNAME_R) check_function_exists(strerror_r HAVE_STRERROR_R) check_function_exists(sched_get_priority_max HAVE_SCHED_GET_PRIORITY_MAX) check_function_exists(sched_get_priority_min HAVE_SCHED_GET_PRIORITY_MIN) check_cxx_source_compiles( " #include int main(){char b;char *a = strerror_r(0, &b, 0); static_cast(a); return(0);} " STRERROR_R_CHAR_P) set(PACKAGE ${PACKAGE_NAME}) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(VERSION ${thrift_VERSION}) # generate a config.h file configure_file("${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/thrift/config.h") include_directories("${CMAKE_CURRENT_BINARY_DIR}") thrift-0.19.0/build/cmake/BuildType.cmake0000644000000000000000000000271414303740367020174 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # originally from: # https://raw.githubusercontent.com/OpenChemistry/tomviz/master/cmake/BuildType.cmake # Set a default build type if none was specified set(default_build_type "RelWithDebInfo") if(EXISTS "${CMAKE_SOURCE_DIR}/.git") set(default_build_type "Debug") endif() if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to '${default_build_type}' as none was specified.") set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() thrift-0.19.0/build/cmake/GenerateConfigModule.cmake0000644000000000000000000000347714452237057022332 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include(CMakePackageConfigHelpers) set(PACKAGE_INCLUDE_INSTALL_DIR "${includedir}/thrift") set(PACKAGE_CMAKE_INSTALL_DIR "${cmakedir}/thrift") set(PACKAGE_BIN_INSTALL_DIR "${exec_prefix}") # In CYGWIN enviroment below commands does not work properly if (NOT CYGWIN) configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/ThriftConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfig.cmake" INSTALL_DESTINATION "${CMAKE_INSTALL_DIR}/thrift" PATH_VARS PACKAGE_INCLUDE_INSTALL_DIR PACKAGE_CMAKE_INSTALL_DIR PACKAGE_BIN_INSTALL_DIR ) write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/ThriftConfigVersion.cmake" VERSION ${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH} COMPATIBILITY SameMajorVersion ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfigVersion.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/FindLibevent.cmake" DESTINATION "${CMAKE_INSTALL_DIR}/thrift") endif() thrift-0.19.0/build/cmake/FindClangTools.cmake0000644000000000000000000000242114303740367021134 0ustar00rootroot00000000000000# - Try to find Clang tools # # The following are set after configuration is done: # clang-tidy_FOUND # ClangTools::clang-tidy # clang-apply-replacements_FOUND # ClangTools::clang-apply-replacements # run-clang-tidy_FOUND # ClangTools::run-clang-tidy include_guard() include(FindPackageHandleStandardArgs) foreach(program_name IN ITEMS clang-tidy clang-apply-replacements) find_program(${program_name}_BINARY NAMES ${program_name}-devel ${program_name}-8 ${program_name} PATH_SUFFIXES "LLVM/bin") find_package_handle_standard_args(${program_name} DEFAULT_MSG ${program_name}_BINARY) if(${program_name}_FOUND AND NOT TARGET ClangTools::${program_name}) add_executable(ClangTools::${program_name} IMPORTED) set_property(TARGET ClangTools::${program_name} PROPERTY IMPORTED_LOCATION "${${program_name}_BINARY}") endif() endforeach() find_program(run-clang-tidy_BINARY NAMES run-clang-tidy run-clang-tidy.py PATH_SUFFIXES "LLVM/bin" "llvm-devel/share/clang") find_package_handle_standard_args(run-clang-tidy DEFAULT_MSG run-clang-tidy_BINARY) if(run-clang-tidy_FOUND AND NOT TARGET ClangTools::run-clang-tidy) add_executable(ClangTools::run-clang-tidy IMPORTED) set_property(TARGET ClangTools::run-clang-tidy PROPERTY IMPORTED_LOCATION "${run-clang-tidy_BINARY}") endif() thrift-0.19.0/build/cmake/FindLibevent.cmake0000644000000000000000000000275514303740367020651 0ustar00rootroot00000000000000# find LibEvent # an event notification library (http://libevent.org/) # # Usage: # LIBEVENT_INCLUDE_DIRS, where to find LibEvent headers # LIBEVENT_LIBRARIES, LibEvent libraries # Libevent_FOUND, If false, do not try to use libevent set(LIBEVENT_ROOT CACHE PATH "Root directory of libevent installation") set(LibEvent_EXTRA_PREFIXES /usr/local /opt/local "$ENV{HOME}" ${LIBEVENT_ROOT}) foreach(prefix ${LibEvent_EXTRA_PREFIXES}) list(APPEND LibEvent_INCLUDE_PATHS "${prefix}/include") list(APPEND LibEvent_LIBRARIES_PATHS "${prefix}/lib") endforeach() # Looking for "event.h" will find the Platform SDK include dir on windows # so we also look for a peer header like evhttp.h to get the right path find_path(LIBEVENT_INCLUDE_DIRS evhttp.h event.h PATHS ${LibEvent_INCLUDE_PATHS}) # "lib" prefix is needed on Windows in some cases # newer versions of libevent use three libraries find_library(LIBEVENT_LIBRARIES NAMES event event_core event_extra libevent PATHS ${LibEvent_LIBRARIES_PATHS}) if (LIBEVENT_LIBRARIES AND LIBEVENT_INCLUDE_DIRS) set(Libevent_FOUND TRUE) set(LIBEVENT_LIBRARIES ${LIBEVENT_LIBRARIES}) else () set(Libevent_FOUND FALSE) endif () if (Libevent_FOUND) if (NOT Libevent_FIND_QUIETLY) message(STATUS "Found libevent: ${LIBEVENT_LIBRARIES}") endif () else () if (LibEvent_FIND_REQUIRED) message(FATAL_ERROR "Could NOT find libevent.") endif () message(STATUS "libevent NOT found.") endif () mark_as_advanced( LIBEVENT_LIBRARIES LIBEVENT_INCLUDE_DIRS ) thrift-0.19.0/build/cmake/NewPlatformDebug.cmake0000644000000000000000000000254014303740367021475 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # For debugging new platforms, just to see what some environment flags are... # macro(SHOWFLAG flag) message(STATUS "${flag} = ${${flag}}") endmacro(SHOWFLAG) set(NEWPLATFORMDEBUG ON) if(NEWPLATFORMDEBUG) SHOWFLAG("APPLE") SHOWFLAG("BORLAND") SHOWFLAG("CMAKE_C_COMPILER_ID") SHOWFLAG("CMAKE_CXX_COMPILER_ID") SHOWFLAG("CMAKE_COMPILER_IS_GNUCC") SHOWFLAG("CMAKE_COMPILER_IS_GNUCXX") SHOWFLAG("CYGWIN") SHOWFLAG("MINGW") SHOWFLAG("MSVC") SHOWFLAG("MSVC_VERSION") SHOWFLAG("MSYS") SHOWFLAG("UNIX") SHOWFLAG("WATCOM") SHOWFLAG("WIN32") endif(NEWPLATFORMDEBUG) thrift-0.19.0/build/cmake/FindGradle.cmake0000644000000000000000000000223714303740367020272 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # GRADLE_FOUND - system has Gradle # GRADLE_EXECUTABLE - the Gradle executable # # It will search the environment variable GRADLE_HOME if it is set include(FindPackageHandleStandardArgs) find_program(GRADLE_EXECUTABLE NAMES gradle PATHS $ENV{GRADLE_HOME}/bin NO_CMAKE_FIND_ROOT_PATH) find_package_handle_standard_args(Gradle DEFAULT_MSG GRADLE_EXECUTABLE) mark_as_advanced(GRADLE_EXECUTABLE) thrift-0.19.0/build/cmake/BoostMacros.cmake0000644000000000000000000000311414303740367020521 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # set(BOOST_MINREV 1.56) macro(REQUIRE_BOOST_HEADERS) find_package(Boost ${BOOST_MINREV} QUIET REQUIRED) if (NOT Boost_FOUND) message(FATAL_ERROR "Boost ${BOOST_MINREV} or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}") endif() if (DEFINED Boost_INCLUDE_DIRS) # pre-boost 1.70.0 aware cmake, otherwise it is using targets include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") endif() endmacro() macro(REQUIRE_BOOST_LIBRARIES libs) message(STATUS "Locating boost libraries required by sources in ${CMAKE_CURRENT_SOURCE_DIR}") find_package(Boost ${BOOST_MINREV} REQUIRED COMPONENTS ${${libs}}) if (NOT Boost_FOUND) message(FATAL_ERROR "Boost ${BOOST_MINREV} or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}, or use -DBUILD_TESTING=OFF") endif() endmacro() thrift-0.19.0/build/cmake/FindAnt.cmake0000644000000000000000000000214614303740367017615 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # ANT_FOUND - system has Ant # Ant_EXECUTABLE - the Ant executable # # It will search the environment variable ANT_HOME if it is set include(FindPackageHandleStandardArgs) find_program(Ant_EXECUTABLE NAMES ant PATHS $ENV{ANT_HOME}/bin) find_package_handle_standard_args(Ant DEFAULT_MSG Ant_EXECUTABLE) mark_as_advanced(Ant_EXECUTABLE) thrift-0.19.0/build/cmake/config.h.in0000644000000000000000000001201114303740367017303 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* config.h generated by CMake from config.h.in */ #ifndef CONFIG_H #define CONFIG_H /* Name of package */ #cmakedefine PACKAGE "${PACKAGE}" /* Define to the address where bug reports for this package should be sent. */ #cmakedefine PACKAGE_BUGREPORT "${PACKAGE_BUGREPORT}" /* Define to the full name of this package. */ #cmakedefine PACKAGE_NAME "${PACKAGE_NAME}" /* Define to the one symbol short name of this package. */ #cmakedefine PACKAGE_TARNAME "${PACKAGE_TARNAME}" /* Define to the home page for this package. */ #cmakedefine PACKAGE_URL "${PACKAGE_URL}" /* Define to the version of this package. */ #define PACKAGE_VERSION "${PACKAGE_VERSION}" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "${PACKAGE_STRING}" /************************** DEFINES *************************/ /* Define if the AI_ADDRCONFIG symbol is unavailable */ #cmakedefine AI_ADDRCONFIG 0 /* Possible value for SIGNED_RIGHT_SHIFT_IS */ /* TODO: This is just set to 1 for the moment port the macro aclocal/ax_signed_right_shift.m4 to CMake to make this work */ #define ARITHMETIC_RIGHT_SHIFT 1 /* Indicates the effect of the right shift operator on negative signed integers */ /* TODO: This is just set to 1 for the moment */ #define SIGNED_RIGHT_SHIFT_IS 1 /* Use *.h extension for parser header file */ /* TODO: This might now be necessary anymore as it is set only for automake < 1.11 see: aclocal/ac_prog_bison.m4 */ #cmakedefine BISON_USE_PARSER_H_EXTENSION 1 /* Define to 1 if strerror_r returns char *. */ #cmakedefine STRERROR_R_CHAR_P 1 /************************** HEADER FILES *************************/ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_ARPA_INET_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_FCNTL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_INTTYPES_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETDB_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_NETINET_IN_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SIGNAL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UNISTD_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_PTHREAD_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_IOCTL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_RESOURCE_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SOCKET_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_UN_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_POLL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_POLL_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SELECT_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SCHED_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #cmakedefine HAVE_AF_UNIX_H 1 /*************************** FUNCTIONS ***************************/ /* Define to 1 if you have the `gethostbyname' function. */ #cmakedefine HAVE_GETHOSTBYNAME 1 /* Define to 1 if you have the `gethostbyname_r' function. */ #cmakedefine HAVE_GETHOSTBYNAME_R 1 /* Define to 1 if you have the `strerror_r' function. */ #cmakedefine HAVE_STRERROR_R 1 /* Define to 1 if you have the `sched_get_priority_max' function. */ #cmakedefine HAVE_SCHED_GET_PRIORITY_MAX 1 /* Define to 1 if you have the `sched_get_priority_min' function. */ #cmakedefine HAVE_SCHED_GET_PRIORITY_MIN 1 /* Define to 1 if strerror_r returns char *. */ #cmakedefine STRERROR_R_CHAR_P 1 #endif thrift-0.19.0/build/cmake/README-MSYS2.md0000644000000000000000000000472314303740367017425 0ustar00rootroot00000000000000 # Building thrift on Windows (MinGW64/MSYS2) Thrift uses cmake to make it easier to build the project on multiple platforms, however to build a fully functional and production ready thrift on Windows requires a number of third party libraries to be obtained. Once third party libraries are ready, the right combination of options must be passed to cmake in order to generate the correct environment. > Note: libevent and libevent-devel do not work with this toolchain as they do not properly detect mingw64 and expect some headers to exist that do not, so the non-blocking server is not currently built into this solution. ## MSYS2 Download and fully upgrade msys2 following the instructions at: https://msys2.github.io/ Install the necessary toolchain items for C++: $ pacman --needed -S bison flex make mingw-w64-x86_64-openssl \ mingw-w64-x86_64-boost mingw-w64-x86_64-cmake \ mingw-w64-x86_64-toolchain mingw-w64-x86_64-zlib Update your msys2 bash path to include /mingw64/bin by adding a line to your ~/.bash_profiles using this command: echo "export PATH=/mingw64/bin:\$PATH" >> ~/.bash_profile After that, close your shell and open a new one. Use cmake to create a MinGW makefile, out of tree (assumes you are in the top level of the thrift source tree): mkdir ../thrift-build cd ../thrift-build cmake -G"MinGW Makefiles" -DCMAKE_MAKE_PROGRAM=/mingw64/bin/mingw32-make \ -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc.exe \ -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++.exe \ -DWITH_LIBEVENT=OFF \ -DWITH_SHARED_LIB=OFF -DWITH_STATIC_LIB=ON \ -DWITH_JAVA=OFF -DWITH_PYTHON=OFF -DWITH_PERL=OFF \ ../thrift Build thrift (inside thrift-build): cmake --build . Run the tests (inside thrift-build): ctest > If you run into issues, check Apache Jira THRIFT-4046 for patches relating to MinGW64/MSYS2 builds. ## Tested With msys2 64-bit 2016-10-26 distribution thrift-0.19.0/build/cmake/mingw32-toolchain.cmake0000644000000000000000000000153114303740367021533 0ustar00rootroot00000000000000# CMake mingw32 cross compile toolchain file # the name of the target operating system SET(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ SET(CMAKE_C_COMPILER i586-mingw32msvc-gcc) SET(CMAKE_CXX_COMPILER i586-mingw32msvc-g++) SET(CMAKE_RC_COMPILER i586-mingw32msvc-windres) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH /usr/i586-mingw32msvc) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(BUILD_SHARED_LIBS OFF) SET(CMAKE_EXE_LINKER_FLAGS "-static") set(CMAKE_C_FLAGS ${CMAKE_C_FLAGS} "-static-libgcc") set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-static-libstdc++") thrift-0.19.0/build/cmake/DefineCMakeDefaults.cmake0000644000000000000000000000651614303740367022062 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Always include srcdir and builddir in include path # This saves typing ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY} in # about every subdir # since cmake 2.4.0 set(CMAKE_INCLUDE_CURRENT_DIR ON) # Put the include dirs which are in the source or build tree # before all other include dirs, so the headers in the sources # are preferred over the already installed ones # since cmake 2.4.1 set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) # Use colored output # since cmake 2.4.0 set(CMAKE_COLOR_MAKEFILE ON) # Create the compile command database for clang by default set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Set the CMAKE_BUILD_TYPE if it is not already defined include(BuildType) # Put the libraries and binaries that get built into directories at the # top of the build tree rather than in hard-to-find leaf # directories. This simplifies manual testing and the use of the build # tree rather than installed thrift libraries. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # # "rpath" support. # See http://www.itk.org/Wiki/index.php?title=CMake_RPATH_handling # # On MacOSX, for shared libraries, enable rpath support. set(CMAKE_MACOSX_RPATH TRUE) # # On any OS, for executables, allow linking with shared libraries in non-system # locations and running the executables without LD_PRELOAD or similar. # This requires the library to be built with rpath support. set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # # C++ Language Level Defaults - this depends on the compiler capabilities # if (NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 11) # C++11 message(STATUS "Setting C++11 as the default language level.") message(STATUS "To specify a different C++ language level, set CMAKE_CXX_STANDARD") endif() if (CMAKE_CXX_STANDARD EQUAL 98) message(FATAL_ERROR "only C++11 or above C++ standard is supported") elseif (CMAKE_CXX_STANDARD EQUAL 11) # should not fallback to C++98 set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() if (NOT DEFINED CMAKE_CXX_EXTENSIONS) set(CMAKE_CXX_EXTENSIONS OFF) # use standards compliant language level for portability endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") include(CheckCXXCompilerFlag) set(CMAKE_REQUIRED_QUIET ON) check_cxx_compiler_flag("/Zc:__cplusplus" res_var) if (res_var) # Make MSVC reporting correct value for __cplusplus # See https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ add_compile_options("/Zc:__cplusplus") endif() endif() thrift-0.19.0/build/cmake/DefinePlatformSpecifc.cmake0000644000000000000000000001100114303740367022454 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Uncomment this to show some basic cmake variables about platforms # include (NewPlatformDebug) # For Debug build types, default to "d"-suffix in library names. set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix") # basic options foreach(lang IN ITEMS C CXX) if("CMAKE_${lang}_COMPILER_ID" STREQUAL "MSVC" OR "${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "MSVC") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /MP") # parallel build set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /W3") # warning level 3 include(CheckCXXCompilerFlag) set(CMAKE_REQUIRED_QUIET ON) check_cxx_compiler_flag("/source-charset:utf-8" res_var) if (res_var) set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /source-charset:utf-8") endif() check_cxx_compiler_flag("/execution-charset:utf-8" res_var) if (res_var) set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /execution-charset:utf-8") endif() add_definitions("-DUNICODE -D_UNICODE") elseif("CMAKE_${lang}_COMPILER_ID" STREQUAL "Clang") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -ferror-limit=1") elseif("CMAKE_${lang}_COMPILER_ID" STREQUAL "GNU") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall -Wextra") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -fmax-errors=1") endif() endforeach() # Visual Studio specific options if(MSVC) # Allow for shared library builds if(BUILD_SHARED_LIBS) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON CACHE TYPE BOOL FORCE) endif() #For visual studio the library naming is as following: # Dynamic libraries: # - thrift.dll for release library # - thriftd.dll for debug library # # Static libraries: # - thriftmd.lib for /MD release build # - thriftmt.lib for /MT release build # # - thriftmdd.lib for /MD debug build # - thriftmtd.lib for /MT debug build # # the same holds for other libraries like libthriftz etc. # Build using /MT option instead of /MD if the WITH_MT options is set if(WITH_MT) set(CompilerFlags CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO ) foreach(CompilerFlag ${CompilerFlags}) string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") endforeach() set(THRIFT_RUNTIME_POSTFIX "mt" CACHE STRING "Set runtime library postfix" FORCE) else(WITH_MT) set(THRIFT_RUNTIME_POSTFIX "md" CACHE STRING "Set runtime library postfix" FORCE) endif(WITH_MT) # Disable boost auto linking pragmas - cmake includes the right files add_definitions("-DBOOST_ALL_NO_LIB") elseif(UNIX) find_program( MEMORYCHECK_COMMAND valgrind ) set( MEMORYCHECK_COMMAND_OPTIONS "--gen-suppressions=all --leak-check=full" ) set( MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/test/valgrind.suppress" ) endif() add_definitions("-D__STDC_FORMAT_MACROS") add_definitions("-D__STDC_LIMIT_MACROS") # C++ Language Level set(CXX_LANGUAGE_LEVEL "C++${CMAKE_CXX_STANDARD}") if (CMAKE_CXX_STANDARD_REQUIRED) string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [compiler must support it]") else() string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [fallback to earlier if compiler does not support it]") endif() if (CMAKE_CXX_EXTENSIONS) string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [with compiler-specific extensions]") endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-register") endif() thrift-0.19.0/build/cmake/ThriftConfig.cmake.in0000644000000000000000000000452414452237057021271 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # set(THRIFT_VERSION @thrift_VERSION@) @PACKAGE_INIT@ set_and_check(THRIFT_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(THRIFT_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@") set_and_check(THRIFT_BIN_DIR "@PACKAGE_BIN_INSTALL_DIR@") if(NOT DEFINED THRIFT_COMPILER) set(THRIFT_COMPILER "${THRIFT_BIN_DIR}/thrift@CMAKE_EXECUTABLE_SUFFIX@") endif() if (NOT TARGET thrift::thrift) include("${THRIFT_CMAKE_DIR}/thriftTargets.cmake") endif() set(THRIFT_LIBRARIES thrift::thrift) if(@ZLIB_FOUND@ AND @WITH_ZLIB@) if (NOT TARGET thriftz::thriftz) include("${THRIFT_CMAKE_DIR}/thriftzTargets.cmake") endif() set(THRIFT_LIBRARIES thriftz::thriftz) endif() if ("${THRIFT_LIBRARIES}" STREQUAL "") message(FATAL_ERROR "thrift libraries were not found") endif() if (NOT Thrift_FIND_QUIETLY) message(STATUS "Found thrift: ${PACKAGE_PREFIX_DIR}") endif() include(CMakeFindDependencyMacro) if(@ZLIB_FOUND@ AND @WITH_ZLIB@) find_dependency(ZLIB) endif() if(@OPENSSL_FOUND@ AND @WITH_OPENSSL@) find_dependency(OpenSSL) endif() if(@Libevent_FOUND@ AND @WITH_LIBEVENT@) if(DEFINED CMAKE_MODULE_PATH) set(THRIFT_CMAKE_MODULE_PATH_OLD ${CMAKE_MODULE_PATH}) else() unset(THRIFT_CMAKE_MODULE_PATH_OLD) endif() set(CMAKE_MODULE_PATH "${THRIFT_CMAKE_DIR}") find_dependency(Libevent) if(DEFINED THRIFT_CMAKE_MODULE_PATH_OLD) set(CMAKE_MODULE_PATH ${THRIFT_CMAKE_MODULE_PATH_OLD}) unset(THRIFT_CMAKE_MODULE_PATH_OLD) else() unset(CMAKE_MODULE_PATH) endif() endif() check_required_components(Thrift) thrift-0.19.0/build/veralign.sh0000755000000000000000000002433614370302016016350 0ustar00rootroot00000000000000#!/usr/bin/env bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # The veralign script sets the appropriate versions in all of # the package configuration files for all of the supported # languages. It is used to prepare a release or move master # forward to the next anticipated version. # # USAGE # ----------------------------------------------------------- # usage: veralign.sh # # EXAMPLE # ----------------------------------------------------------- # $ ./veralign.sh 0.12.0 1.0.0 # $ ./veralign.sh 1.0.0 1.1.0 # # IMPORTANT USAGE NOTE # ----------------------------------------------------------- # Define the environment variable DRYRUN to have the script # print out all matches to the oldVersion hilighted so that # you can verify it will change the right things. # declare -A FILES # These files require a manual touch: FILES[CHANGES.md]=manual FILES[debian/changelog]=manual FILES[doap.rdf]=manual # These files can be updated automatically: FILES[ApacheThrift.nuspec]=simpleReplace FILES[appveyor.yml]=simpleReplace FILES[bower.json]=jsonReplace FILES[CMakeLists.txt]=simpleReplace FILES[compiler/cpp/src/thrift/version.h]=simpleReplace FILES[configure.ac]=configureReplace FILES[contrib/Rebus/Properties/AssemblyInfo.cs]=simpleReplace FILES[contrib/thrift.spec]=simpleReplace FILES[contrib/zeromq/csharp/AssemblyInfo.cs]=simpleReplace FILES[contrib/thrift-maven-plugin/pom.xml]=pomReplace FILES[doc/specs/idl.md]=simpleReplace FILES[lib/d/src/thrift/base.d]=simpleReplace FILES[lib/dart/pubspec.yaml]=pubspecReplace FILES[lib/delphi/src/Thrift.pas]=simpleReplace FILES[lib/erl/src/thrift.app.src]=simpleReplace FILES[lib/haxe/haxelib.json]=simpleReplace FILES[lib/java/gradle.properties]=simpleReplace FILES[lib/js/package-lock.json]=jsonReplace FILES[lib/js/package.json]=jsonReplace FILES[lib/js/src/thrift.js]=simpleReplace FILES[lib/lua/Thrift.lua]=simpleReplace FILES[lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj]=simpleReplace FILES[lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj]=simpleReplace FILES[lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj]=simpleReplace FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netstd/Thrift/Thrift.csproj]=simpleReplace FILES[lib/ocaml/_oasis]=simpleReplace FILES[lib/perl/lib/Thrift.pm]=simpleReplace FILES[lib/py/setup.py]=simpleReplace FILES[lib/rb/thrift.gemspec]=simpleReplace FILES[lib/rs/Cargo.toml]=simpleReplace FILES[lib/st/package.xml]=simpleReplace FILES[lib/swift/Sources/Thrift.swift]=simpleReplace FILES[lib/swift/Tests/ThriftTests/ThriftTests.swift]=simpleReplace FILES[lib/ts/package-lock.json]=jsonReplace FILES[lib/ts/package.json]=jsonReplace FILES[package-lock.json]=jsonReplace FILES[package.json]=jsonReplace FILES[sonar-project.properties]=simpleReplace FILES[test/dart/test_client/pubspec.yaml]=pubspecReplace FILES[test/erl/src/thrift_test.app.src]=simpleReplace FILES[test/netstd/Client/Client.csproj]=simpleReplace FILES[test/netstd/Server/Server.csproj]=simpleReplace FILES[Thrift.podspec]=simpleReplace FILES[tutorial/dart/client/pubspec.yaml]=pubspecReplace FILES[tutorial/dart/console_client/pubspec.yaml]=pubspecReplace FILES[tutorial/dart/server/pubspec.yaml]=pubspecReplace FILES[tutorial/delphi/DelphiClient/DelphiClient.dproj]=simpleReplace FILES[tutorial/delphi/DelphiServer/DelphiServer.dproj]=simpleReplace FILES[tutorial/netstd/Client/Client.csproj]=simpleReplace FILES[tutorial/netstd/Interfaces/Interfaces.csproj]=simpleReplace FILES[tutorial/netstd/Server/Server.csproj]=simpleReplace FILES[tutorial/ocaml/_oasis]=simpleReplace if [ ! -f "CHANGES.md" ]; then >&2 echo "error: run veralign.sh while in the thrift root directory" exit 1 fi if [ $# -ne 2 ]; then >&2 echo "usage: veralign.sh " exit 1 fi jq --version 1>/dev/null 2>/dev/null if [ $? -ne 0 ]; then >&2 echo "error: the 'jq' package is not installed" exit 1 fi # # validateVersion: check that a version matches the major.minor.patch # format which is the lowest common denominator supported by all # project systems. # \param $1 the version # \returns 0 if the version is compliant # function validateVersion { local result local valid valid=$(echo "$1" | sed '/^[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+$/!{q22}') result=$? if [ $result -eq 22 ]; then >&2 echo "error: version '$1' does not conform to the required major.minor.patch format" return ${result} fi } OLDVERSION=$1 NEWVERSION=$2 validateVersion "${OLDVERSION}" || exit $? validateVersion "${NEWVERSION}" || exit $? # # escapeVersion: escape the version for use as a sed search # \param $1 the version to escape # \output the escaped string # \returns 0 # \example VERSEARCH=$(escapeVersion "[1.0.0]"); echo $VERSEARCH; => "\[1\.0\.0\]" # function escapeVersion { echo "$(echo "$1" | sed 's/\./\\./g' | sed 's/\[/\\\[/g' | sed 's/\]/\\\]/g')" } # Set up verbose hilighting if running interactive if [ "$(tput colors)" -ne 0 ]; then reverse=$(tput rev) red=$(tput setaf 1) green=$(tput setaf 2) yellow=$(tput setaf 3) normal=$(tput sgr0) fi declare -A MANUAL # # manual: note that update of said file is manual # \param $1 filename to do replacements on # \returns 0 # function manual { MANUAL["$1"]="" return 0 } # # configureReplace: replace the AC_INIT field in configure.ac # \param $1 filename to do replacements on # \returns 0 on success # function configureReplace { replace "$1" "[thrift], [${OLDVERSION}]" "[thrift], [${NEWVERSION}]" } # # jsonReplace: replace a specific version field in a JSON file # must be a top level "version" field in the json structure # \param $1 filename to do replacements on # \returns 0 on success # function jsonReplace { local result local output if [ ! -z "$DRYRUN" ]; then output=$(jq -e ".version" "$1") else output=$(jq -e ".version = \"${NEWVERSION}\"" "$1" > tmp.$$.json && mv tmp.$$.json "$1") fi result=$? if [ $? -ne 0 ]; then printf "%-60s | %5d | ${red}ERROR${normal}: version tag not found" "$1" "$count" echo return 1 elif [ ! -z "$DRYRUN" ]; then output=${output%\"} output=${output#\"} printf "%-60s | %5d | MATCHES: version: \"${reverse}${green}${output}${normal}\"" "$1" 1 echo return 0 fi printf "%-60s | %5d | ${green}OK${normal}" "$1" 1 echo return 0 } # # pubspecReplace: replace a specific version field in a YAML file # must be a top level "version" field in the yaml structure # did not find a package that preserves comments so this is # somewhat brain-dead, but it gets the job done # \param $1 filename to do replacements on # \returns 0 on success # function pubspecReplace { replace "$1" "version: ${OLDVERSION}" "version: ${NEWVERSION}" } # # pomReplace: replace a specific version field in a maven pom file # must be a top level "version" field in the xml structure # \param $1 filename to do replacements on # \returns 0 on success # function pomReplace { replace "$1" "^ ${OLDVERSION}<\/version>" " ${NEWVERSION}<\/version>" } # # replace: replace occurrences of one string with another # the file specified must contain the old string at least once # in order to be successful. # \param $1 filename to do replacements on # \param $2 the "old" string to be replaced # \param $3 the "new" striing to replace it with # \returns 0 on success # function replace { local result local output local oldString="$2" local newString="$3" local oldRegex=$(escapeVersion "${oldString}") local count=$(grep -Ec "${oldRegex}" "$1") local verbose if [ $count -eq 0 ]; then printf "%-60s | %5d | ${red}NOT FOUND${normal}: ${oldString}" "$1" 0 echo return 1 elif [ ! -z "$DRYRUN" ]; then printf "%-60s | %5d | MATCHES:" "$1" "$count" echo while read -r line; do echo " > $(echo "$line" | sed "s/${oldRegex}/${reverse}${green}${oldString}${normal}/g")" done < <(grep -E "${oldRegex}" "$1") return 0 fi output=$(sed -i "s/${oldRegex}/${newString}/g" "$1") result=$? if [ $result -ne 0 ]; then printf "%-60s | %5d | ${red}ERROR${normal}: %s" "$1" "$count" "$output" echo return 1 fi printf "%-60s | %5d | ${green}OK${normal}" "$1" "$count" echo return 0 } # # simpleReplace: replace occurrences of ${OLDVERSION} with ${NEWVERSION} # the file specified must contain OLDVERSION at least once # in order to be successful. # \param $1 filename to do replacements on # \param $2 the "old" string to be replaced # \param $3 the "new" striing to replace it with # \returns 0 on success # function simpleReplace { replace "$1" "${OLDVERSION}" "${NEWVERSION}" } echo "" echo "Apache Thrift Version Alignment Tool" echo "------------------------------------" echo "" echo "Previous Version: ${OLDVERSION}" echo " New Version: ${NEWVERSION}" echo "" echo "-------------------------------------------------------------+-------+----------------------" echo "Filename | Count | Status " echo "-------------------------------------------------------------+-------+----------------------" for file in $(echo "${!FILES[@]}" | sort); do ${FILES[$file]} $file || exit $? done echo echo "Files that must be modified manually:" echo for manu in $(echo "${!MANUAL[@]}" | sort); do echo " > ${yellow}${manu}${normal}" done exit 0 thrift-0.19.0/build/appveyor/0000777000000000000000000000000014303740367016056 5ustar00rootroot00000000000000thrift-0.19.0/build/appveyor/MINGW-appveyor-full.bat0000644000000000000000000000776014303740367022240 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Appveyor script for MINGW on MSYS2 :: :: :: Installs third party packages we need for a cmake build :: @ECHO ON SETLOCAL EnableDelayedExpansion CD build\appveyor || EXIT /B SET APPVEYOR_SCRIPTS=%APPVEYOR_BUILD_FOLDER%\build\appveyor SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM% SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\..\install\%PROFILE%\%PLATFORM% SET SRCDIR=%APPVEYOR_BUILD_FOLDER% :: PLATFORM is x86 or x64 :: NORM_PLATFORM is 32 or 64 IF "%PLATFORM%" == "x86" ( SET NORM_PLATFORM=32 ) ELSE ( SET NORM_PLATFORM=64 ) :: PLATFORM = x86 means MINGWPLAT i686 :: PLATFORM = x64 means MINGWPLAT x86_64 IF "%PLATFORM%" == "x86" ( SET MINGWPLAT=i686 ) ELSE ( SET MINGWPLAT=x86_64 ) :: compiler and generator detection SET COMPILER=gcc SET GENERATOR=MinGW Makefiles SET BASH=C:\msys64\usr\bin\bash.exe !BASH! -lc "sed -i '/export PATH=\/mingw32\/bin/d' ~/.bash_profile && sed -i '/export PATH=\/mingw64\/bin/d' ~/.bash_profile && echo 'export PATH=/mingw%NORM_PLATFORM%/bin:$PATH' >> ~/.bash_profile" || EXIT /B SET BUILDDIR=%BUILDDIR:\=/% SET BUILDDIR=/c!BUILDDIR:~2! SET INSTDIR=%INSTDIR:\=/% SET INSTDIR=/c!INSTDIR:~2! SET SRCDIR=%SRCDIR:\=/% SET SRCDIR=/c!SRCDIR:~2! CALL win_showenv.bat || EXIT /B SET PACKAGES=^ base-devel ^ mingw-w64-x86_64-toolchain ^ bison ^ flex ^ make ^ mingw-w64-%MINGWPLAT%-boost ^ mingw-w64-%MINGWPLAT%-cmake ^ mingw-w64-%MINGWPLAT%-libevent ^ mingw-w64-%MINGWPLAT%-openssl ^ mingw-w64-%MINGWPLAT%-toolchain ^ mingw-w64-%MINGWPLAT%-zlib ::mingw-w64-%MINGWPLAT%-qt5 : WAY too large (1GB download!) - tested in cygwin builds anyway :: Upgrade things %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B %BASH% -lc "pacman --noconfirm --needed -S %PACKAGES%" || EXIT /B :: These instructions are for a manual update of specific package versions. :: Fall back to this in case the above does not work anymore (broken upstream). :::: Updata the new key ::%BASH% -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-1~20210213-2-any.pkg.tar.xz" || EXIT /B ::%BASH% -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-1~20210213-2-any.pkg.tar.xz.sig" || EXIT /B ::%BASH% -lc "pacman-key --verify msys2-keyring-1~20210213-2-any.pkg.tar.xz.sig" || EXIT /B ::%BASH% -lc "pacman --noconfirm -U --config <(echo) msys2-keyring-1~20210213-2-any.pkg.tar.xz" || EXIT /B :::: Upgrade things ::%BASH% -lc "pacman --noconfirm -Sy" || EXIT /B ::%BASH% -lc "pacman --noconfirm -Udd https://repo.msys2.org/msys/x86_64/pacman-5.2.2-5-x86_64.pkg.tar.xz" || EXIT /B ::%BASH% -lc "pacman --noconfirm --needed -S %PACKAGES%" || EXIT /B :: :: Configure and build our software with cmake :: SET CMAKEARGS=^ -G'%GENERATOR%' ^ -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^ -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^ -DCMAKE_MAKE_PROGRAM=/mingw%NORM_PLATFORM%/bin/mingw32-make ^ -DCMAKE_C_COMPILER=/mingw%NORM_PLATFORM%/bin/gcc.exe ^ -DCMAKE_CXX_COMPILER=/mingw%NORM_PLATFORM%/bin/g++.exe ^ -DOPENSSL_ROOT_DIR=/mingw%NORM_PLATFORM% ^ -DWITH_PYTHON=OFF %BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% && cmake --install . --config %CONFIGURATION%" || EXIT /B :: :: Execute our tests :: SET DISABLED_TESTS_COMMAND=--exclude-regex '%DISABLED_TESTS%' %BASH% -lc "cd %BUILDDIR% && ctest.exe --build-config %CONFIGURATION% --timeout 300 --extra-verbose %DISABLED_TESTS_COMMAND%" || EXIT /B thrift-0.19.0/build/appveyor/CYGWIN-appveyor-full.bat0000644000000000000000000000516714303740367022356 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Appveyor script for CYGWIN :: :: :: Installs third party packages we need for a cmake build :: @ECHO ON SETLOCAL EnableDelayedExpansion CD build\appveyor || EXIT /B SET APPVEYOR_SCRIPTS=%APPVEYOR_BUILD_FOLDER%\build\appveyor SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM% SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\..\install\%PROFILE%\%PLATFORM% SET SRCDIR=%APPVEYOR_BUILD_FOLDER% :: compiler and generator detection SET COMPILER=gcc SET GENERATOR=Unix Makefiles IF "%PLATFORM%" == "x64" ( SET CYGWINROOT=C:\cygwin64 ) ELSE ( SET CYGWINROOT=C:\cygwin ) IF "%PLATFORM%" == "x64" ( SET SETUP=!CYGWINROOT!\setup-x86_64.exe ) ELSE ( SET SETUP=!CYGWINROOT!\setup-x86.exe ) SET BASH=!CYGWINROOT!\bin\bash.exe SET BUILDDIR=%BUILDDIR:\=/% SET BUILDDIR=/cygdrive/c!BUILDDIR:~2! SET INSTDIR=%INSTDIR:\=/% SET INSTDIR=/cygdrive/c!INSTDIR:~2! SET SRCDIR=%SRCDIR:\=/% SET SRCDIR=/cygdrive/c!SRCDIR:~2! CALL win_showenv.bat || EXIT /B :: :: Install apt-cyg for package management because its easier to use :: than Cygwins setup.exe. But both are possible to use. :: %BASH% -lc "wget https://rawgit.com/transcode-open/apt-cyg/master/apt-cyg && install apt-cyg /bin && rm -f apt-cyg" || EXIT /B %BASH% -lc "apt-cyg update" || EXIT /B %BASH% -lc "apt-cyg install unzip xz cmake make bison flex gcc-g++ libboost-devel libevent-devel openssl-devel zlib-devel" || EXIT /B :: :: Configure and build our software with cmake :: SET CMAKEARGS=^ -G'%GENERATOR%' ^ -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^ -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^ -DCMAKE_CXX_FLAGS="-D_GNU_SOURCE" ^ -DWITH_JAVA=OFF ^ -DWITH_PYTHON=OFF :: -DCMAKE_CXX_EXTENSIONS=ON ^ :: -DCMAKE_CXX_STANDARD=11 ^ %BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% && cmake --install . --config %CONFIGURATION%" || EXIT /B :: :: Execute our tests :: SET DISABLED_TESTS_COMMAND=--exclude-regex '%DISABLED_TESTS%' %BASH% -lc "cd %BUILDDIR% && ctest.exe --build-config %CONFIGURATION% --timeout 300 --extra-verbose %DISABLED_TESTS_COMMAND%" || EXIT /B thrift-0.19.0/build/appveyor/MSVC-appveyor-full.bat0000644000000000000000000001451514303740367022123 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Appveyor script for MSVC :: :: :: Installs (or builds) third party packages we need :: @ECHO ON SETLOCAL EnableDelayedExpansion CD build\appveyor || EXIT /B SET APPVEYOR_SCRIPTS=%APPVEYOR_BUILD_FOLDER%\build\appveyor SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM% SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\..\install\%PROFILE%\%PLATFORM% SET SRCDIR=%APPVEYOR_BUILD_FOLDER% IF "%PROFILE%" == "MSVC2015" ( IF "%PLATFORM%" == "x86" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 || EXIT /B ) ELSE ( CALL "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x64 || EXIT /B CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64 || EXIT /B ) ) ELSE IF "%PROFILE%" == "MSVC2017" ( IF "%PLATFORM%" == "x86" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat" || EXIT /B ) ELSE ( CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat" || EXIT /B ) ) ELSE IF "%PROFILE%" == "MSVC2019" ( IF "%PLATFORM%" == "x86" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat" || EXIT /B ) ELSE ( CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat" || EXIT /B ) ) ELSE ( ECHO Unsupported PROFILE=%PROFILE% or PLATFORM=%PLATFORM% EXIT /B 1 ) :: compiler and generator detection IF /i "%PLATFORM%" == "x64" SET GENARCH= Win64 IF "%PROFILE%" == "MSVC2015" ( SET GENERATOR=Visual Studio 14 2015!GENARCH! SET COMPILER=vc140 ) ELSE IF "%PROFILE%" == "MSVC2017" ( SET GENERATOR=Visual Studio 15 2017!GENARCH! SET COMPILER=vc141 ) ELSE IF "%PROFILE%" == "MSVC2019" ( SET GENERATOR=Visual Studio 16 2019!GENARCH! SET COMPILER=vc142 ) ELSE ( ECHO [error] unable to determine the CMake generator and compiler to use from MSVC profile %PROFILE% EXIT /B 1 ) :: PLATFORM is x86 or x64 :: NORM_PLATFORM is 32 or 64 IF "%PLATFORM%" == "x86" ( SET NORM_PLATFORM=32 ) ELSE ( SET NORM_PLATFORM=64 ) :: FindBoost needs forward slashes so cmake doesn't see something as an escaped character SET BOOST_ROOT=C:/Libraries/boost_%BOOST_VERSION:.=_% SET BOOST_LIBRARYDIR=!BOOST_ROOT!/lib%NORM_PLATFORM%-msvc-%COMPILER:~-3,2%.%COMPILER:~-1,1% SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM% SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty IF "%PYTHON_VERSION%" == "" ( SET WITH_PYTHON=OFF ) ELSE ( SET WITH_PYTHON=ON IF /i "%PLATFORM%" == "x64" (SET PTEXT=-x64) SET PATH=C:\Python%PYTHON_VERSION:.=%!PTEXT!\scripts;C:\Python%PYTHON_VERSION:.=%!PTEXT!;!PATH! ) IF "%CONFIGURATION%" == "Debug" (SET ZLIB_LIB_SUFFIX=d) IF NOT "%QT_VERSION%" == "" ( IF /i "%PLATFORM%" == "x64" (SET QTEXT=_64) SET PATH=C:\Qt\%QT_VERSION%\%PROFILE%!QTEXT!\bin;!PATH! ) CALL win_showenv.bat || EXIT /B MKDIR "%WIN3P%" || EXIT /B choco feature enable -n allowGlobalConfirmation || EXIT /B :: Things to install when NOT running in appveyor: IF "%APPVEYOR_BUILD_ID%" == "" ( cup -y chocolatey || EXIT /B cinst -y curl || EXIT /B cinst -y 7zip || EXIT /B cinst -y python3 || EXIT /B cinst -y openssl.light || EXIT /B ) cinst -y jdk8 || EXIT /B cinst -y winflexbison3 || EXIT /B :: zlib - not available through chocolatey CD "%APPVEYOR_SCRIPTS%" || EXIT /B call build-zlib.bat || EXIT /B :: libevent - not available through chocolatey CD "%APPVEYOR_SCRIPTS%" || EXIT /B call build-libevent.bat || EXIT /B :: python packages (correct path to pip set above) pip.exe ^ install backports.ssl_match_hostname ^ ipaddress ^ six ^ tornado ^ twisted || EXIT /B :: Adobe Flex SDK 4.6 for ActionScript MKDIR "C:\Adobe\Flex\SDK\4.6" || EXIT /B appveyor DownloadFile http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip -FileName C:\Adobe\Flex\SDK\4.6\SDK.zip || EXIT /B CD "C:\Adobe\Flex\SDK\4.6" || EXIT /B 7z x SDK.zip || EXIT /B SETX FLEX_HOME "C:\Adobe\Flex\SDK\4.6" :: :: Configure and build our software with cmake :: MKDIR "%BUILDDIR%" || EXIT /B CD "%BUILDDIR%" || EXIT /B :: When libraries cannot be found, things might have been updated :: so uncomment this and submit a pull request to see what's there :: now... :: DIR C:\Libraries :: DIR C:\Libraries\boost_1_69_0\lib* :: DIR C:\Libraries\boost_1_68_0\lib* :: DIR C:\Libraries\boost_1_67_0\lib* :: DIR C:\Libraries\boost_1_66_0\lib* :: DIR C:\Libraries\boost_1_65_0\lib* :: DIR C:\Libraries\boost_1_64_0\lib* :: DIR C:\Libraries\boost_1_63_0\lib* :: DIR C:\Libraries\boost_1_62_0\lib* :: DIR C:\Libraries\boost_1_61_0\lib* :: DIR C:\Libraries\boost_1_60_0\lib* cmake.exe "%SRCDIR%" ^ -G"%GENERATOR%" ^ -DBISON_EXECUTABLE="C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_bison.exe" ^ -DBOOST_ROOT="%BOOST_ROOT%" ^ -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" ^ -DBUILD_SHARED_LIBS="%BUILD_SHARED_LIBS%" ^ -DCMAKE_BUILD_TYPE="%CONFIGURATION%" ^ -DCMAKE_INSTALL_PREFIX="%INSTDIR%" ^ -DFLEX_EXECUTABLE="C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_flex.exe" ^ -DLIBEVENT_ROOT="%WIN3P%\libevent-%LIBEVENT_VERSION%-stable" ^ -DOPENSSL_ROOT_DIR="%OPENSSL_ROOT%" ^ -DOPENSSL_USE_STATIC_LIBS=OFF ^ -DZLIB_LIBRARY="%WIN3P%\zlib-inst\lib\zlib%ZLIB_LIB_SUFFIX%.lib" ^ -DZLIB_ROOT="%WIN3P%\zlib-inst" ^ -DWITH_PYTHON=%WITH_PYTHON% || EXIT /B cmake.exe --build . --config "%CONFIGURATION%" || EXIT /B cmake.exe --install . --config "%CONFIGURATION%" || EXIT /B :: :: Execute our tests :: :: Add directories to the path to find DLLs of third party libraries so tests run properly! SET PATH=%BOOST_LIBRARYDIR:/=\%;%OPENSSL_ROOT%\bin;%WIN3P%\zlib-inst\bin;%PATH% SET DISABLED_TESTS_COMMAND=--exclude-regex '%DISABLED_TESTS%' ctest.exe --build-config %CONFIGURATION% --timeout 300 --extra-verbose %DISABLED_TESTS_COMMAND% || EXIT /B thrift-0.19.0/build/appveyor/simulate-appveyor.bat0000644000000000000000000000166114303740367022234 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Helps build thrift by pretending to be appveyor :: Usage: :: cd build\appveyor :: simulate-appveyor.bat [Debug|Release] [x86|x64] [CYGWIN|MINGW|MSVC201?] :: SETLOCAL EnableDelayedExpansion SET APPVEYOR_BUILD_FOLDER=%~dp0..\.. SET CONFIGURATION=%1 SET PLATFORM=%2 SET PROFILE=%3 CD %APPVEYOR_BUILD_FOLDER% CALL build\appveyor\%PROFILE_CLASS%-appveyor-full.bat || EXIT /B thrift-0.19.0/build/appveyor/README.md0000644000000000000000000000160514303740367017333 0ustar00rootroot00000000000000 # AppVeyor Build AppVeyor is capable of building MSVC as well as MSYS2, MinGW and Cygwin builds targeting the MS Windows platform. It has many versions of boost and python installed as well. See what appveyor has [installed on build workers](https://www.appveyor.com/docs/installed-software/). We run a matrix build on AppVeyor. See appveyor.yml for more details. thrift-0.19.0/build/appveyor/build-libevent.bat0000644000000000000000000000257014303740367021453 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: SETLOCAL EnableDelayedExpansion SET URLFILE=libevent-%LIBEVENT_VERSION%-stable.tar.gz SET URL=https://github.com/libevent/libevent/releases/download/release-%LIBEVENT_VERSION%-stable/%URLFILE% :: Download - support running a local build or a build in appveyor CD "%WIN3P%" || EXIT /B IF "%APPVEYOR_BUILD_ID%" == "" ( curl -L -f -o "%URLFILE%" "%URL%" ) ELSE ( appveyor DownloadFile "%URL%" ) 7z x "%URLFILE%" -so | 7z x -si -ttar > nul || EXIT /B CD "libevent-%LIBEVENT_VERSION%-stable" || EXIT /B nmake -f Makefile.nmake static_libs || EXIT /B :: in libevent 2.0 there is no nmake subdirectory in WIN32-Code, but in 2.1 there is mkdir lib || EXIT /B move *.lib lib\ || EXIT /B move WIN32-Code\event2\* include\event2\ || move WIN32-Code\nmake\event2\* include\event2\ || EXIT /B move *.h include\ || EXIT /B ENDLOCAL thrift-0.19.0/build/appveyor/MSYS-appveyor-full.bat0000644000000000000000000000532214303740367022142 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: :: :: Appveyor script for MSYS :: :: :: Installs third party packages we need for a cmake build :: @ECHO ON SETLOCAL EnableDelayedExpansion CD build\appveyor || EXIT /B SET APPVEYOR_SCRIPTS=%APPVEYOR_BUILD_FOLDER%\build\appveyor SET BUILDDIR=%APPVEYOR_BUILD_FOLDER%\..\build\%PROFILE%\%PLATFORM% SET INSTDIR=%APPVEYOR_BUILD_FOLDER%\..\install\%PROFILE%\%PLATFORM% SET SRCDIR=%APPVEYOR_BUILD_FOLDER% ECHO Unsupported PROFILE=%PROFILE% or PLATFORM=%PLATFORM% EXIT /B 1 SET BASH=C:\msys64\usr\bin\bash SET CMAKE=/c/msys64/mingw64/bin/cmake.exe CALL win_showenv.bat || EXIT /B SET PACKAGES=^ base-devel ^ mingw-w64-x86_64-toolchain ^ bison ^ flex ^ make ^ mingw-w64-x86_64-cmake ^ mingw-w64-x86_64-libevent ^ mingw-w64-x86_64-openssl ^ mingw-w64-x86_64-zlib :: Upgrade things %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B %BASH% -lc "pacman --noconfirm --needed -S %PACKAGES%" || EXIT /B :: :: Configure and build our software with cmake :: SET CMAKEARGS=^ -G'%GENERATOR%' ^ -DBoost_DEBUG=ON ^ -DBoost_NAMESPACE=libboost ^ -DBOOST_INCLUDEDIR=%BOOST_INCLUDEDIR% ^ -DBOOST_LIBRARYDIR=%BOOST_LIBRARYDIR% ^ -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^ -DCMAKE_C_COMPILER=gcc.exe ^ -DCMAKE_CXX_COMPILER=g++.exe ^ -DCMAKE_MAKE_PROGRAM=make.exe ^ -DCMAKE_INSTALL_PREFIX=%INSTDIR_MSYS% ^ -DLIBEVENT_ROOT=%LIBEVENT_ROOT% ^ -DOPENSSL_LIBRARIES=%OPENSSL_LIBRARIES% ^ -DOPENSSL_ROOT_DIR=%OPENSSL_ROOT% ^ -DOPENSSL_USE_STATIC_LIBS=ON ^ -DWITH_BOOST_STATIC=ON ^ -DWITH_JAVA=OFF ^ -DWITH_LIBEVENT=ON ^ -DWITH_PYTHON=%WITH_PYTHON% ^ -DWITH_SHARED_LIB=OFF ^ -DWITH_STATIC_LIB=ON %BASH% -lc "mkdir %BUILDDIR% && cd %BUILDDIR% && %CMAKE% %SRCDIR_MSYS% %CMAKEARGS% && %CMAKE% --build . --config %CONFIGURATION% && %CMAKE% --install . --config %CONFIGURATION%" || EXIT /B :: :: Execute our tests :: :: This test randomly fails on mingw; see Jira THRIFT-4106 SET DISABLED_TESTS=(concurrency_test) SET DISABLED_TESTS_COMMAND=--exclude-regex '%DISABLED_TESTS%' %BASH% -lc "cd %BUILDDIR% && ctest.exe --build-config %CONFIGURATION% --timeout 300 --extra-verbose %DISABLED_TESTS_COMMAND%" || EXIT /B thrift-0.19.0/build/appveyor/build-zlib.bat0000644000000000000000000000320614303740367020600 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: SETLOCAL EnableDelayedExpansion SET PACKAGE=zlib-%ZLIB_VERSION% SET BUILDDIR=%WIN3P%\zlib-build SET INSTDIR=%WIN3P%\zlib-inst SET SRCDIR=%WIN3P%\%PACKAGE% SET URLFILE=%PACKAGE%.tar.gz :: This allows us to tolerate when the current version is archived SET URL=http://zlib.net/%URLFILE% SET FURL=http://zlib.net/fossils/%URLFILE% :: Download - support running a local build or a build in appveyor CD "%WIN3P%" || EXIT /B IF "%APPVEYOR_BUILD_ID%" == "" ( curl -L -f -o "%URLFILE%" "%URL%" IF ERRORLEVEL 1 ( curl -L -f -o "%URLFILE%" "%FURL%" ) ) ELSE ( appveyor DownloadFile "%URL%" IF ERRORLEVEL 1 ( appveyor DownloadFile "%FURL%" || EXIT /B ) ) 7z x "%URLFILE%" -so | 7z x -si -ttar > nul || EXIT /B :: Generate MKDIR "%BUILDDIR%" || EXIT /B CD "%BUILDDIR%" || EXIT /B cmake "%SRCDIR%" ^ -G"NMake Makefiles" ^ -DCMAKE_INSTALL_PREFIX="%INSTDIR%" ^ -DCMAKE_BUILD_TYPE="%CONFIGURATION%" || EXIT /B :: Build nmake /fMakefile install || EXIT /B IF "%CONFIGURATION%" == "Debug" ( COPY "%BUILDDIR%\zlibd.pdb" "%INSTDIR%\bin\" || EXIT /B ) ENDLOCAL thrift-0.19.0/build/appveyor/win_showenv.bat0000644000000000000000000000465414303740367021121 0ustar00rootroot00000000000000:: :: Licensed under the Apache License, Version 2.0 (the "License"); :: you may not use this file except in compliance with the License. :: You may obtain a copy of the License at :: :: http://www.apache.org/licenses/LICENSE-2.0 :: :: Unless required by applicable law or agreed to in writing, software :: distributed under the License is distributed on an "AS IS" BASIS, :: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. :: See the License for the specific language governing permissions and :: limitations under the License. :: ECHO/ ECHO =============================================================================== IF "%PROFILE_CLASS%" == "MSVC" ( ECHO Versions ECHO ------------------------------------------------------------------------------- ECHO boost = %BOOST_VERSION% ECHO libevent = %LIBEVENT_VERSION% ECHO python = %PYTHON_VERSION% ECHO qt = %QT_VERSION% ECHO zlib = %ZLIB_VERSION% ECHO/ ) ECHO Appveyor Variables ECHO ------------------------------------------------------------------------------- ECHO APPVEYOR_BUILD_FOLDER = %APPVEYOR_BUILD_FOLDER% ECHO CONFIGURATION = %CONFIGURATION% ECHO PLATFORM = %PLATFORM% ECHO PROFILE = %PROFILE% ECHO/ ECHO Our Variables ECHO ------------------------------------------------------------------------------- ECHO APPVEYOR_SCRIPTS = %APPVEYOR_SCRIPTS% ECHO BASH = %BASH% ECHO BOOST_ROOT = %BOOST_ROOT% ECHO BOOST_INCLUDEDIR = %BOOST_INCLUDEDIR% ECHO BOOST_LIBRARYDIR = %BOOST_LIBRARYDIR% ECHO BUILDDIR = %BUILDDIR% ECHO COMPILER = %COMPILER% ECHO GENERATOR = %GENERATOR% ECHO INSTDIR = %INSTDIR% ECHO JAVA_HOME = %JAVA_HOME% ECHO OPENSSL_ROOT = %OPENSSL_ROOT% ECHO SETUP = %SETUP% ECHO SRCDIR = %SRCDIR% ECHO WIN3P = %WIN3P% ECHO WITH_PYTHON = %WITH_PYTHON% ECHO ZLIB_STATIC_SUFFIX = %ZLIB_STATIC_SUFFIX% IF NOT "%PROFILE_CLASS%" == "MSVC" ( ECHO/ ECHO UNIXy PATH ECHO ------------------------------------------------------------------------------- %BASH% -lc "echo $PATH" ) ECHO/ ECHO Windows PATH ECHO ------------------------------------------------------------------------------- ECHO %PATH% ECHO =============================================================================== ECHO/ thrift-0.19.0/phpcs.xml.dist0000644000000000000000000000135514303740367015713 0ustar00rootroot00000000000000 The coding standard for thrift. lib/php/lib lib/php/test lib/php/test/packages/* lib/php/test/* lib/php/test/* thrift-0.19.0/test/0000755000000000000000000000000014472652675014100 5ustar00rootroot00000000000000thrift-0.19.0/test/DoubleConstantsTest.thrift0000644000000000000000000000361114370300523021245 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test namespace cpp thrift.test // more tests on double constants (precision and type checks) const double DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST = 1 const double DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST = -100 const double DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST = 9223372036854775807 const double DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST = -9223372036854775807 const double DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST = 3.14159265359 const double DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST = 1000000.1 const double DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST = -1000000.1 const double DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST = 1.7e+308 const double DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST = 9223372036854775816.43 const double DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST = -1.7e+308 const double DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST = -9223372036854775816.43 const list DOUBLE_LIST_TEST = [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43] thrift-0.19.0/test/threads/0000777000000000000000000000000014303740367015523 5ustar00rootroot00000000000000thrift-0.19.0/test/threads/Makefile0000644000000000000000000000331414303740367017160 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Default target is everything ifndef thrift_home thrift_home=../../ endif #thrift_home target: all ifndef boost_home boost_home=/usr/local/include/boost-1_33_1 endif #boost_home target: all include_paths = $(thrift_home)/lib/cpp/src \ $(boost_home) include_flags = $(patsubst %,-I%, $(include_paths)) # Tools ifndef THRIFT THRIFT = ../../compiler/cpp/thrift endif # THRIFT CC = g++ LD = g++ # Compiler flags LFL = -L$(thrift_home)/lib/cpp/.libs -lthrift CCFL = -Wall -O3 -g -I./gen-cpp $(include_flags) CFL = $(CCFL) $(LFL) all: server client stubs: ThreadsTest.thrift $(THRIFT) --gen cpp --gen py ThreadsTest.thrift server: stubs $(CC) -o ThreadsServer $(CFL) ThreadsServer.cpp ./gen-cpp/ThreadsTest.cpp ./gen-cpp/ThreadsTest_types.cpp client: stubs $(CC) -o ThreadsClient $(CFL) ThreadsClient.cpp ./gen-cpp/ThreadsTest.cpp ./gen-cpp/ThreadsTest_types.cpp clean: $(RM) -r *.o ThreadsServer ThreadsClient gen-cpp gen-py thrift-0.19.0/test/threads/ThreadsTest.thrift0000644000000000000000000000172714303740367021202 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ service ThreadsTest { i32 threadOne(1: i32 sleep=15), i32 threadTwo(2: i32 sleep=15), i32 threadThree(3: i32 sleep=15), i32 threadFour(4: i32 sleep=15) i32 stop(); } thrift-0.19.0/test/threads/ThreadsClient.cpp0000644000000000000000000000416514303740367020762 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This autogenerated skeleton file illustrates how to build a server. // You should copy it to another filename to avoid overwriting it. #include "ThreadsTest.h" #include #include #include #include #include #include #include #if _WIN32 #include #endif using boost::shared_ptr; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::server; using namespace apache::thrift::concurrency; int main(int argc, char **argv) { #if _WIN32 transport::TWinsockSingleton::create(); #endif int port = 9090; std::string host = "localhost"; shared_ptr transport(new TSocket(host, port)); shared_ptr protocol(new TBinaryProtocol(transport)); transport->open(); ThreadsTestClient client(protocol); int val; val = client.threadOne(5); fprintf(stderr, "%d\n", val); val = client.stop(); fprintf(stderr, "%d\n", val); val = client.threadTwo(5); fprintf(stderr, "%d\n", val); transport->close(); fprintf(stderr, "done.\n"); return 0; } thrift-0.19.0/test/threads/ThreadsServer.cpp0000644000000000000000000001043414303740367021006 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This autogenerated skeleton file illustrates how to build a server. // You should copy it to another filename to avoid overwriting it. #include "ThreadsTest.h" #include #include #include #include #include #include #include #include #if _WIN32 #include #endif using boost::shared_ptr; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::server; using namespace apache::thrift::concurrency; class ThreadsTestHandler : virtual public ThreadsTestIf { public: ThreadsTestHandler() { // Your initialization goes here } int32_t threadOne(const int32_t sleep) { // Your implementation goes here printf("threadOne\n"); go2sleep(1, sleep); return 1; } int32_t threadTwo(const int32_t sleep) { // Your implementation goes here printf("threadTwo\n"); go2sleep(2, sleep); return 1; } int32_t threadThree(const int32_t sleep) { // Your implementation goes here printf("threadThree\n"); go2sleep(3, sleep); return 1; } int32_t threadFour(const int32_t sleep) { // Your implementation goes here printf("threadFour\n"); go2sleep(4, sleep); return 1; } int32_t stop() { printf("stop\n"); server_->stop(); return 1; } void setServer(boost::shared_ptr server) { server_ = server; } protected: void go2sleep(int thread, int seconds) { Monitor m; Synchronized s(m); for (int i = 0; i < seconds; ++i) { fprintf(stderr, "Thread %d: sleep %d\n", thread, i); try { m.wait(1000); } catch(const TimedOutException&) { } } fprintf(stderr, "THREAD %d DONE\n", thread); } private: boost::shared_ptr server_; }; int main(int argc, char **argv) { #if _WIN32 transport::TWinsockSingleton::create(); #endif int port = 9090; shared_ptr handler(new ThreadsTestHandler()); shared_ptr processor(new ThreadsTestProcessor(handler)); shared_ptr serverTransport(new TServerSocket(port)); shared_ptr transportFactory(new TBufferedTransportFactory()); shared_ptr protocolFactory(new TBinaryProtocolFactory()); /* shared_ptr threadManager = ThreadManager::newSimpleThreadManager(10); shared_ptr threadFactory = shared_ptr(new ThreadFactory()); threadManager->threadFactory(threadFactory); threadManager->start(); shared_ptr server = shared_ptr(new TThreadPoolServer(processor, serverTransport, transportFactory, protocolFactory, threadManager)); */ shared_ptr server = shared_ptr(new TThreadedServer(processor, serverTransport, transportFactory, protocolFactory)); handler->setServer(server); server->serve(); fprintf(stderr, "done.\n"); return 0; } thrift-0.19.0/test/ManyTypedefs.thrift0000644000000000000000000000323714303740367017724 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This is to make sure you don't mess something up when you change typedef code. // Generate it with the old and new thrift and make sure they are the same. /* rm -rf gen-* orig-* mkdir old new thrift --gen cpp --gen java --gen php --gen phpi --gen py --gen rb --gen xsd --gen perl --gen ocaml --gen erl --gen hs --strict ManyTypedefs.thrift mv gen-* old ../compiler/cpp/thrift --gen cpp --gen java --gen php --gen phpi --gen py --gen rb --gen xsd --gen perl --gen ocaml --gen erl --gen hs --strict ManyTypedefs.thrift mv gen-* new diff -ur old new rm -rf old new # There should be no output. */ typedef i32 int32 typedef list> biglist struct struct1 { 1: int32 myint; 2: biglist mylist; } exception exception1 { 1: biglist alist; 2: struct1 mystruct; } service AService { struct1 method1(1: int32 myint) throws (1: exception1 exn); biglist method2(); } thrift-0.19.0/test/rebuild_known_failures.sh0000644000000000000000000000106214303740367021154 0ustar00rootroot00000000000000#!/bin/bash if [ -z $1 ]; then echo Usage: $0 LANGUAGE echo Re-list all failures of a specific LANGUAGE into known_failures_Linux.json echo LANGUAGE should be library name like cpp, java, py etc exit 1 fi if [ -z $PYTHON]; then PYTHON=python fi TARGET_LANG=$1 OUT_FILE=known_failures_Linux.json echo Rebuilding known failures for $TARGET_LANG TMPFILE=.__tmp__rebuild__ grep -v -e "\"$1-" -e "\-$1_" $OUT_FILE > $TMPFILE mv $TMPFILE $OUT_FILE $PYTHON test.py --client $1 $PYTHON test.py -U merge $PYTHON test.py --server $1 $PYTHON test.py -U merge thrift-0.19.0/test/lua/0000777000000000000000000000000014472652606014657 5ustar00rootroot00000000000000thrift-0.19.0/test/lua/Makefile.am0000644000000000000000000000220014370300523016662 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = $(top_builddir)/compiler/cpp/thrift # Remove "MapType =" line to ignore some map bug for now stubs: ../v0.16/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen lua $< $(SED) -i.bak 's/MapType =//g' gen-lua/ThriftTest_ttypes.lua $(RM) gen-lua/ThriftTest_ttypes.lua.bak precross: stubs clean-local: $(RM) -r gen-lua/ dist-hook: $(RM) -r $(distdir)/gen-lua/ thrift-0.19.0/test/lua/Makefile0000644000000000000000000004370514472652606016324 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/lua/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/lua ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/lua abs_srcdir = /thrift/src/test/lua abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/lua/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/lua/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # Remove "MapType =" line to ignore some map bug for now stubs: ../v0.16/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen lua $< $(SED) -i.bak 's/MapType =//g' gen-lua/ThriftTest_ttypes.lua $(RM) gen-lua/ThriftTest_ttypes.lua.bak precross: stubs clean-local: $(RM) -r gen-lua/ dist-hook: $(RM) -r $(distdir)/gen-lua/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/lua/test_basic_server.lua0000644000000000000000000000704214303740367021062 0ustar00rootroot00000000000000-- Licensed to the Apache Software Foundation (ASF) under one -- or more contributor license agreements. See the NOTICE file -- distributed with this work for additional information -- regarding copyright ownership. The ASF licenses this file -- to you under the Apache License, Version 2.0 (the -- "License"); you may not use this file except in compliance -- with the License. You may obtain a copy of the License at -- http://www.apache.org/licenses/LICENSE-2.0 -- Unless required by applicable law or agreed to in writing, -- software distributed under the License is distributed on an -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -- KIND, either express or implied. See the License for the -- specific language governing permissions and limitations -- under the License. require('ThriftTest_ThriftTest') require('TSocket') require('TBufferedTransport') require('TFramedTransport') require('THttpTransport') require('TCompactProtocol') require('TJsonProtocol') require('TBinaryProtocol') require('TServer') require('liblualongnumber') -------------------------------------------------------------------------------- -- Handler TestHandler = ThriftTestIface:new{} -- Stops the server function TestHandler:testVoid() end function TestHandler:testString(str) return str end function TestHandler:testBool(bool) return bool end function TestHandler:testByte(byte) return byte end function TestHandler:testI32(i32) return i32 end function TestHandler:testI64(i64) return i64 end function TestHandler:testDouble(d) return d end function TestHandler:testBinary(by) return by end function TestHandler:testStruct(thing) return thing end function TestHandler:testOneway(secondsToSleep) print("testOneway secondsToSleep:", secondsToSleep) end -------------------------------------------------------------------------------- -- Test local server function teardown() if server then server:close() end end function parseArgs(rawArgs) local opt = { protocol='binary', transport='buffered', port='9090', } for i, str in pairs(rawArgs) do if i > 0 then k, v = string.match(str, '--(%w+)=(%w+)') assert(opt[k] ~= nil, 'Unknown argument') opt[k] = v end end return opt end function testBasicServer(rawArgs) local opt = parseArgs(rawArgs) -- Handler & Processor local handler = TestHandler:new{} assert(handler, 'Failed to create handler') local processor = ThriftTestProcessor:new{ handler = handler } assert(processor, 'Failed to create processor') -- Server Socket local socket = TServerSocket:new{ port = opt.port } assert(socket, 'Failed to create server socket') -- Transport & Factory local transports = { buffered = TBufferedTransportFactory, framed = TFramedTransportFactory, http = THttpTransportFactory, } assert(transports[opt.transport], 'Failed to create framed transport factory') local trans_factory = transports[opt.transport]:new{} local protocols = { binary = TBinaryProtocolFactory, compact = TCompactProtocolFactory, json = TJSONProtocolFactory, } local prot_factory = protocols[opt.protocol]:new{} assert(prot_factory, 'Failed to create binary protocol factory') -- Simple Server server = TSimpleServer:new{ processor = processor, serverTransport = socket, transportFactory = trans_factory, protocolFactory = prot_factory } assert(server, 'Failed to create server') server:setExceptionHandler(function (err) error(err) end) -- Serve server:serve() server = nil end testBasicServer(arg) teardown() thrift-0.19.0/test/lua/test_basic_client.lua0000644000000000000000000001351214303740367021031 0ustar00rootroot00000000000000-- Licensed to the Apache Software Foundation (ASF) under one -- or more contributor license agreements. See the NOTICE file -- distributed with this work for additional information -- regarding copyright ownership. The ASF licenses this file -- to you under the Apache License, Version 2.0 (the -- "License"); you may not use this file except in compliance -- with the License. You may obtain a copy of the License at -- http://www.apache.org/licenses/LICENSE-2.0 -- Unless required by applicable law or agreed to in writing, -- software distributed under the License is distributed on an -- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -- KIND, either express or implied. See the License for the -- specific language governing permissions and limitations -- under the License. require('TSocket') require('TBufferedTransport') require('TFramedTransport') require('THttpTransport') require('TCompactProtocol') require('TJsonProtocol') require('TBinaryProtocol') require('ThriftTest_ThriftTest') require('liblualongnumber') local client function teardown() if client then -- close the connection client:close() end end function parseArgs(rawArgs) local opt = { protocol='binary', transport='buffered', port='9090', } for i, str in pairs(rawArgs) do if i > 0 then k, v = string.match(str, '--(%w+)=(%w+)') assert(opt[k] ~= nil, 'Unknown argument') opt[k] = v end end return opt end function assertEqual(val1, val2, msg) assert(val1 == val2, msg) end function testBasicClient(rawArgs) local opt = parseArgs(rawArgs) local socket = TSocket:new{ port = tonumber(opt.port) } assert(socket, 'Failed to create client socket') socket:setTimeout(5000) local transports = { buffered = TBufferedTransport, framed = TFramedTransport, http = THttpTransport, } assert(transports[opt.transport] ~= nil) local transport = transports[opt.transport]:new{ trans = socket, isServer = false } local protocols = { binary = TBinaryProtocol, compact = TCompactProtocol, json = TJSONProtocol, } assert(protocols[opt.protocol] ~= nil) local protocol = protocols[opt.protocol]:new{ trans = transport } assert(protocol, 'Failed to create binary protocol') client = ThriftTestClient:new{ protocol = protocol } assert(client, 'Failed to create client') -- Open the transport local status, _ = pcall(transport.open, transport) assert(status, 'Failed to connect to server') -- String assertEqual(client:testString('lala'), 'lala', 'Failed testString') assertEqual(client:testString('wahoo'), 'wahoo', 'Failed testString') -- Bool assertEqual(client:testBool(true), true, 'Failed testBool true') assertEqual(client:testBool(false), false, 'Failed testBool false') -- Byte assertEqual(client:testByte(0x01), 1, 'Failed testByte 1') assertEqual(client:testByte(0x40), 64, 'Failed testByte 2') assertEqual(client:testByte(0x7f), 127, 'Failed testByte 3') assertEqual(client:testByte(0x80), -128, 'Failed testByte 4') assertEqual(client:testByte(0xbf), -65, 'Failed testByte 5') assertEqual(client:testByte(0xff), -1, 'Failed testByte 6') assertEqual(client:testByte(128), -128, 'Failed testByte 7') assertEqual(client:testByte(255), -1, 'Failed testByte 8') -- I32 assertEqual(client:testI32(0x00000001), 1, 'Failed testI32 1') assertEqual(client:testI32(0x40000000), 1073741824, 'Failed testI32 2') assertEqual(client:testI32(0x7fffffff), 2147483647, 'Failed testI32 3') assertEqual(client:testI32(0x80000000), -2147483648, 'Failed testI32 4') assertEqual(client:testI32(0xbfffffff), -1073741825, 'Failed testI32 5') assertEqual(client:testI32(0xffffffff), -1, 'Failed testI32 6') assertEqual(client:testI32(2147483648), -2147483648, 'Failed testI32 7') assertEqual(client:testI32(4294967295), -1, 'Failed testI32 8') -- I64 (lua only supports 16 decimal precision so larger numbers are -- initialized by their string value) local long = liblualongnumber.new assertEqual(client:testI64(long(0x0000000000000001)), long(1), 'Failed testI64 1') assertEqual(client:testI64(long(0x4000000000000000)), long(4611686018427387904), 'Failed testI64 2') assertEqual(client:testI64(long('0x7fffffffffffffff')), long('9223372036854775807'), 'Failed testI64 3') assertEqual(client:testI64(long(0x8000000000000000)), long(-9223372036854775808), 'Failed testI64 4') assertEqual(client:testI64(long('0xbfffffffffffffff')), long('-4611686018427387905'), 'Failed testI64 5') assertEqual(client:testI64(long('0xffffffffffffffff')), long(-1), 'Failed testI64 6') -- Double assertEqual( client:testDouble(1.23456789), 1.23456789, 'Failed testDouble 1') assertEqual( client:testDouble(0.123456789), 0.123456789, 'Failed testDouble 2') assertEqual( client:testDouble(0.123456789), 0.123456789, 'Failed testDouble 3') -- TODO testBinary() ... -- Accuracy of 16 decimal digits (rounds) local a, b = 1.12345678906666663, 1.12345678906666661 assertEqual(a, b) assertEqual(client:testDouble(a), b, 'Failed testDouble 5') -- Struct local o = Xtruct:new{ string_thing = 'Zero', byte_thing = 1, i32_thing = -3, i64_thing = long(-5) } local r = client:testStruct(o) assertEqual(o.string_thing, r.string_thing, 'Failed testStruct 1') assertEqual(o.byte_thing, r.byte_thing, 'Failed testStruct 2') assertEqual(o.i32_thing, r.i32_thing, 'Failed testStruct 3') assertEqual(o.i64_thing, r.i64_thing, 'Failed testStruct 4') -- oneway client:testOneway(3) -- TODO add list map set exception etc etc end testBasicClient(arg) teardown() thrift-0.19.0/test/lua/Makefile.in0000644000000000000000000004304714472652520016723 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/lua ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/lua/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/lua/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # Remove "MapType =" line to ignore some map bug for now stubs: ../v0.16/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen lua $< $(SED) -i.bak 's/MapType =//g' gen-lua/ThriftTest_ttypes.lua $(RM) gen-lua/ThriftTest_ttypes.lua.bak precross: stubs clean-local: $(RM) -r gen-lua/ dist-hook: $(RM) -r $(distdir)/gen-lua/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/crossrunner/0000777000000000000000000000000014370300523016442 5ustar00rootroot00000000000000thrift-0.19.0/test/crossrunner/compat.py0000644000000000000000000000106614303740367020310 0ustar00rootroot00000000000000import os import sys if sys.version_info[0] == 2: _ENCODE = sys.getfilesystemencoding() def path_join(*args): bin_args = map(lambda a: a.decode(_ENCODE), args) return os.path.join(*bin_args).encode(_ENCODE) def str_join(left, right): bin_args = map(lambda a: a.decode(_ENCODE), right) b = left.decode(_ENCODE) return b.join(bin_args).encode(_ENCODE) logfile_open = open else: path_join = os.path.join str_join = str.join def logfile_open(*args): return open(*args, errors='replace') thrift-0.19.0/test/crossrunner/__init__.py0000644000000000000000000000175714303740367020573 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from .test import test_name # noqa from .collect import collect_cross_tests, collect_feature_tests # noqa from .run import TestDispatcher # noqa from .report import generate_known_failures, load_known_failures # noqa thrift-0.19.0/test/crossrunner/test.py0000644000000000000000000001217114303740367020003 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import copy import multiprocessing import os import sys from .compat import path_join from .util import merge_dict, domain_socket_path class TestProgram(object): def __init__(self, kind, name, protocol, transport, socket, workdir, stop_signal, command, env=None, extra_args=[], extra_args2=[], join_args=False, **kwargs): self.kind = kind self.name = name self.protocol = protocol self.transport = transport self.socket = socket self.workdir = workdir self.stop_signal = stop_signal self.command = None self._base_command = self._fix_cmd_path(command) if env: self.env = copy.copy(os.environ) self.env.update(env) else: self.env = os.environ self._extra_args = extra_args self._extra_args2 = extra_args2 self._join_args = join_args def _fix_cmd_path(self, cmd): # if the arg is a file in the current directory, make it path def abs_if_exists(arg): p = path_join(self.workdir, arg) return p if os.path.exists(p) else arg if cmd[0] == 'python': cmd[0] = sys.executable else: cmd[0] = abs_if_exists(cmd[0]) return cmd def _socket_args(self, socket, port): return { 'ip-ssl': ['--ssl'], 'domain': ['--domain-socket=%s' % domain_socket_path(port)], 'abstract': ['--abstract-namespace', '--domain-socket=%s' % domain_socket_path(port)], }.get(socket, None) def _transport_args(self, transport): return { 'zlib': ['--zlib'], }.get(transport, None) def build_command(self, port): cmd = copy.copy(self._base_command) args = copy.copy(self._extra_args2) args.append('--protocol=' + self.protocol) args.append('--transport=' + self.transport) transport_args = self._transport_args(self.transport) if transport_args: args += transport_args socket_args = self._socket_args(self.socket, port) if socket_args: args += socket_args args.append('--port=%d' % port) if self._join_args: cmd.append('%s' % " ".join(args)) else: cmd.extend(args) if self._extra_args: cmd.extend(self._extra_args) self.command = cmd return self.command class TestEntry(object): def __init__(self, testdir, server, client, delay, timeout, **kwargs): self.testdir = testdir self._log = multiprocessing.get_logger() self._config = kwargs self.protocol = kwargs['protocol'] self.transport = kwargs['transport'] self.socket = kwargs['socket'] srv_dict = self._fix_workdir(merge_dict(self._config, server)) cli_dict = self._fix_workdir(merge_dict(self._config, client)) cli_dict['extra_args2'] = srv_dict.pop('remote_args', []) srv_dict['extra_args2'] = cli_dict.pop('remote_args', []) self.server = TestProgram('server', **srv_dict) self.client = TestProgram('client', **cli_dict) self.delay = delay self.timeout = timeout self._name = None # results self.success = None self.as_expected = None self.returncode = None self.expired = False self.retry_count = 0 def _fix_workdir(self, config): key = 'workdir' path = config.get(key, None) if not path: path = self.testdir if os.path.isabs(path): path = os.path.realpath(path) else: path = os.path.realpath(path_join(self.testdir, path)) config.update({key: path}) return config @classmethod def get_name(cls, server, client, protocol, transport, socket, *args, **kwargs): return '%s-%s_%s_%s-%s' % (server, client, protocol, transport, socket) @property def name(self): if not self._name: self._name = self.get_name( self.server.name, self.client.name, self.protocol, self.transport, self.socket) return self._name @property def transport_name(self): return '%s-%s' % (self.transport, self.socket) def test_name(server, client, protocol, transport, socket, **kwargs): return TestEntry.get_name(server['name'], client['name'], protocol, transport, socket) thrift-0.19.0/test/crossrunner/collect.py0000644000000000000000000001441014303740367020447 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import platform import re from itertools import product from .util import merge_dict from .test import TestEntry # Those keys are passed to execution as is. # Note that there are keys other than these, namely: # delay: After server is started, client start is delayed for the value # (seconds). # timeout: Test timeout after client is started (seconds). # platforms: Supported platforms. Should match platform.system() value. # protocols: list of supported protocols # transports: list of supported transports # sockets: list of supported sockets # # protocols and transports entries can be colon separated "spec:impl" pair # (e.g. binary:accel) where test is run for any matching "spec" while actual # argument passed to test executable is "impl". # Otherwise "spec" is equivalent to "spec:spec" pair. # (e.g. "binary" is equivalent to "binary:binary" in tests.json) # VALID_JSON_KEYS = [ 'name', # name of the library, typically a language name 'workdir', # work directory where command is executed 'command', # test command 'extra_args', # args appended to command after other args are appended 'remote_args', # args added to the other side of the program 'join_args', # whether args should be passed as single concatenated string 'env', # additional environmental variable ] DEFAULT_MAX_DELAY = 5 DEFAULT_SIGNAL = 1 DEFAULT_TIMEOUT = 5 def _collect_testlibs(config, server_match, client_match=[None]): """Collects server/client configurations from library configurations""" def expand_libs(config): for lib in config: sv = lib.pop('server', None) cl = lib.pop('client', None) yield lib, sv, cl def yield_testlibs(base_configs, configs, match): for base, conf in zip(base_configs, configs): if conf: if not match or base['name'] in match: platforms = conf.get('platforms') or base.get('platforms') if not platforms or platform.system() in platforms: yield merge_dict(base, conf) libs, svs, cls = zip(*expand_libs(config)) servers = list(yield_testlibs(libs, svs, server_match)) clients = list(yield_testlibs(libs, cls, client_match)) return servers, clients def collect_features(config, match): res = list(map(re.compile, match)) return list(filter(lambda c: any(map(lambda r: r.search(c['name']), res)), config)) def _do_collect_tests(servers, clients): def intersection(key, o1, o2): """intersection of two collections. collections are replaced with sets the first time""" def cached_set(o, key): v = o[key] if not isinstance(v, set): v = set(v) o[key] = v return v return cached_set(o1, key) & cached_set(o2, key) def intersect_with_spec(key, o1, o2): # store as set of (spec, impl) tuple def cached_set(o): def to_spec_impl_tuples(values): for v in values: spec, _, impl = v.partition(':') yield spec, impl or spec v = o[key] if not isinstance(v, set): v = set(to_spec_impl_tuples(set(v))) o[key] = v return v for spec1, impl1 in cached_set(o1): for spec2, impl2 in cached_set(o2): if spec1 == spec2: name = impl1 if impl1 == impl2 else '%s-%s' % (impl1, impl2) yield name, impl1, impl2 def maybe_max(key, o1, o2, default): """maximum of two if present, otherwise default value""" v1 = o1.get(key) v2 = o2.get(key) return max(v1, v2) if v1 and v2 else v1 or v2 or default def filter_with_validkeys(o): ret = {} for key in VALID_JSON_KEYS: if key in o: ret[key] = o[key] return ret def merge_metadata(o, **ret): for key in VALID_JSON_KEYS: if key in o: ret[key] = o[key] return ret for sv, cl in product(servers, clients): for proto, proto1, proto2 in intersect_with_spec('protocols', sv, cl): for trans, trans1, trans2 in intersect_with_spec('transports', sv, cl): for sock in intersection('sockets', sv, cl): yield { 'server': merge_metadata(sv, **{'protocol': proto1, 'transport': trans1}), 'client': merge_metadata(cl, **{'protocol': proto2, 'transport': trans2}), 'delay': maybe_max('delay', sv, cl, DEFAULT_MAX_DELAY), 'stop_signal': maybe_max('stop_signal', sv, cl, DEFAULT_SIGNAL), 'timeout': maybe_max('timeout', sv, cl, DEFAULT_TIMEOUT), 'protocol': proto, 'transport': trans, 'socket': sock } def _filter_entries(tests, regex): if regex: return filter(lambda t: re.search(regex, TestEntry.get_name(**t)), tests) return tests def collect_cross_tests(tests_dict, server_match, client_match, regex): sv, cl = _collect_testlibs(tests_dict, server_match, client_match) return list(_filter_entries(_do_collect_tests(sv, cl), regex)) def collect_feature_tests(tests_dict, features_dict, server_match, feature_match, regex): sv, _ = _collect_testlibs(tests_dict, server_match) ft = collect_features(features_dict, feature_match) return list(_filter_entries(_do_collect_tests(sv, ft), regex)) thrift-0.19.0/test/crossrunner/run.py0000644000000000000000000004066414303740367017640 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import contextlib import multiprocessing import multiprocessing.managers import os import platform import random import socket import subprocess import sys import time from .compat import str_join from .report import ExecReporter, SummaryReporter from .test import TestEntry from .util import domain_socket_path RESULT_ERROR = 64 RESULT_TIMEOUT = 128 SIGNONE = 0 SIGKILL = 15 # globals ports = None stop = None class ExecutionContext(object): def __init__(self, cmd, cwd, env, stop_signal, is_server, report): self._log = multiprocessing.get_logger() self.cmd = cmd self.cwd = cwd self.env = env self.stop_signal = stop_signal self.is_server = is_server self.report = report self.expired = False self.killed = False self.proc = None def _popen_args(self): args = { 'cwd': self.cwd, 'env': self.env, 'stdout': self.report.out, 'stderr': subprocess.STDOUT, } # make sure child processes doesn't remain after killing if platform.system() == 'Windows': DETACHED_PROCESS = 0x00000008 args.update(creationflags=DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP) else: args.update(preexec_fn=os.setsid) return args def start(self): joined = str_join(' ', self.cmd) self._log.debug('COMMAND: %s', joined) self._log.debug('WORKDIR: %s', self.cwd) self._log.debug('LOGFILE: %s', self.report.logpath) self.report.begin() self.proc = subprocess.Popen(self.cmd, **self._popen_args()) self._log.debug(' PID: %d', self.proc.pid) self._log.debug(' PGID: %d', os.getpgid(self.proc.pid)) return self._scoped() @contextlib.contextmanager def _scoped(self): yield self if self.is_server: # the server is supposed to run until we stop it if self.returncode is not None: self.report.died() else: if self.stop_signal != SIGNONE: if self.sigwait(self.stop_signal): self.report.end(self.returncode) else: self.report.killed() else: self.sigwait(SIGKILL) else: # the client is supposed to exit normally if self.returncode is not None: self.report.end(self.returncode) else: self.sigwait(SIGKILL) self.report.killed() self._log.debug('[{0}] exited with return code {1}'.format(self.proc.pid, self.returncode)) # Send a signal to the process and then wait for it to end # If the signal requested is SIGNONE, no signal is sent, and # instead we just wait for the process to end; further if it # does not end normally with SIGNONE, we mark it as expired. # If the process fails to end and the signal is not SIGKILL, # it re-runs with SIGKILL so that a real process kill occurs # returns True if the process ended, False if it may not have def sigwait(self, sig=SIGKILL, timeout=2): try: if sig != SIGNONE: self._log.debug('[{0}] send signal {1}'.format(self.proc.pid, sig)) if sig == SIGKILL: self.killed = True try: if platform.system() != 'Windows': os.killpg(os.getpgid(self.proc.pid), sig) else: self.proc.send_signal(sig) except Exception: self._log.info('[{0}] Failed to kill process'.format(self.proc.pid), exc_info=sys.exc_info()) self._log.debug('[{0}] wait begin, timeout {1} sec(s)'.format(self.proc.pid, timeout)) self.proc.communicate(timeout=timeout) self._log.debug('[{0}] process ended with return code {1}'.format(self.proc.pid, self.returncode)) self.report.end(self.returncode) return True except subprocess.TimeoutExpired: self._log.info('[{0}] timeout waiting for process to end'.format(self.proc.pid)) if sig == SIGNONE: self.expired = True return False if sig == SIGKILL else self.sigwait(SIGKILL, 1) # called on the client process to wait for it to end naturally def wait(self, timeout): self.sigwait(SIGNONE, timeout) @property def returncode(self): return self.proc.returncode if self.proc else None def exec_context(port, logdir, test, prog, is_server): report = ExecReporter(logdir, test, prog) prog.build_command(port) return ExecutionContext(prog.command, prog.workdir, prog.env, prog.stop_signal, is_server, report) def run_test(testdir, logdir, test_dict, max_retry, async_mode=True): logger = multiprocessing.get_logger() def ensure_socket_open(sv, port, test): slept = 0.1 time.sleep(slept) sleep_step = 0.1 while True: if slept > test.delay: logger.warn('[{0}] slept for {1} seconds but server is not open'.format(sv.proc.pid, slept)) return False if test.socket == 'domain': if not os.path.exists(domain_socket_path(port)): logger.debug('[{0}] domain(unix) socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept)) time.sleep(sleep_step) slept += sleep_step elif test.socket == 'abstract': return True else: # Create sockets every iteration because refused sockets cannot be # reused on some systems. sock4 = socket.socket() sock6 = socket.socket(family=socket.AF_INET6) try: if sock4.connect_ex(('127.0.0.1', port)) == 0 \ or sock6.connect_ex(('::1', port)) == 0: return True if sv.proc.poll() is not None: logger.warn('[{0}] server process is exited'.format(sv.proc.pid)) return False logger.debug('[{0}] socket not available yet. slept for {1} seconds so far'.format(sv.proc.pid, slept)) time.sleep(sleep_step) slept += sleep_step finally: sock4.close() sock6.close() logger.debug('[{0}] server ready - waited for {1} seconds'.format(sv.proc.pid, slept)) return True try: max_bind_retry = 3 retry_count = 0 bind_retry_count = 0 test = TestEntry(testdir, **test_dict) while True: if stop.is_set(): logger.debug('Skipping because shutting down') return (retry_count, None) logger.debug('Start') with PortAllocator.alloc_port_scoped(ports, test.socket) as port: logger.debug('Start with port %d' % port) sv = exec_context(port, logdir, test, test.server, True) cl = exec_context(port, logdir, test, test.client, False) logger.debug('Starting server') with sv.start(): port_ok = ensure_socket_open(sv, port, test) if port_ok: connect_retry_count = 0 max_connect_retry = 12 connect_retry_wait = 0.25 while True: if sv.proc.poll() is not None: logger.info('not starting client because server process is absent') break logger.debug('Starting client') cl.start() logger.debug('Waiting client (up to %d secs)' % test.timeout) cl.wait(test.timeout) if not cl.report.maybe_false_positive() or connect_retry_count >= max_connect_retry: if connect_retry_count > 0 and connect_retry_count < max_connect_retry: logger.info('[%s]: Connected after %d retry (%.2f sec each)' % (test.server.name, connect_retry_count, connect_retry_wait)) # Wait for 50ms to see if server does not die at the end. time.sleep(0.05) break logger.debug('Server may not be ready, waiting %.2f second...' % connect_retry_wait) time.sleep(connect_retry_wait) connect_retry_count += 1 if sv.report.maybe_false_positive() and bind_retry_count < max_bind_retry: logger.warn('[%s]: Detected socket bind failure, retrying...', test.server.name) bind_retry_count += 1 else: result = RESULT_TIMEOUT if cl.expired else cl.returncode if (cl.proc and cl.proc.poll()) is not None else RESULT_ERROR # For servers that handle a controlled shutdown by signal # if they are killed, or return an error code, that is a # problem. For servers that are not signal-aware, we simply # kill them off; if we didn't kill them off, something else # happened (crashed?) if test.server.stop_signal != 0: # for bash scripts, 128+N is the exit code for signal N, since we are sending # DEFAULT_SIGNAL=1, 128 + 1 is the expected err code # http://www.gnu.org/software/bash/manual/html_node/Exit-Status.html allowed_return_code = set([-1, 0, 128 + 1]) if sv.killed or sv.returncode not in allowed_return_code: result |= RESULT_ERROR else: if not sv.killed: result |= RESULT_ERROR if result == 0 or retry_count >= max_retry: return (retry_count, result) else: logger.info('[%s-%s]: test failed, retrying...', test.server.name, test.client.name) retry_count += 1 except Exception: if not async_mode: raise logger.warn('Error executing [%s]', test.name, exc_info=True) return (retry_count, RESULT_ERROR) except Exception: logger.info('Interrupted execution', exc_info=True) if not async_mode: raise stop.set() return (retry_count, RESULT_ERROR) class PortAllocator(object): def __init__(self): self._log = multiprocessing.get_logger() self._lock = multiprocessing.Lock() self._ports = set() self._dom_ports = set() self._last_alloc = 0 def _get_tcp_port(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('', 0)) port = sock.getsockname()[1] self._lock.acquire() try: ok = port not in self._ports if ok: self._ports.add(port) self._last_alloc = time.time() finally: self._lock.release() sock.close() return port if ok else self._get_tcp_port() def _get_domain_port(self): port = random.randint(1024, 65536) self._lock.acquire() try: ok = port not in self._dom_ports if ok: self._dom_ports.add(port) finally: self._lock.release() return port if ok else self._get_domain_port() def alloc_port(self, socket_type): if socket_type in ('domain', 'abstract'): return self._get_domain_port() else: return self._get_tcp_port() # static method for inter-process invokation @staticmethod @contextlib.contextmanager def alloc_port_scoped(allocator, socket_type): port = allocator.alloc_port(socket_type) yield port allocator.free_port(socket_type, port) def free_port(self, socket_type, port): self._log.debug('free_port') self._lock.acquire() try: if socket_type == 'domain': self._dom_ports.remove(port) path = domain_socket_path(port) if os.path.exists(path): os.remove(path) elif socket_type == 'abstract': self._dom_ports.remove(port) else: self._ports.remove(port) except IOError: self._log.info('Error while freeing port', exc_info=sys.exc_info()) finally: self._lock.release() class NonAsyncResult(object): def __init__(self, value): self._value = value def get(self, timeout=None): return self._value def wait(self, timeout=None): pass def ready(self): return True def successful(self): return self._value == 0 class TestDispatcher(object): def __init__(self, testdir, basedir, logdir_rel, concurrency): self._log = multiprocessing.get_logger() self.testdir = testdir self._report = SummaryReporter(basedir, logdir_rel, concurrency > 1) self.logdir = self._report.testdir # seems needed for python 2.x to handle keyboard interrupt self._stop = multiprocessing.Event() self._async = concurrency > 1 if not self._async: self._pool = None global stop global ports stop = self._stop ports = PortAllocator() else: self._m = multiprocessing.managers.BaseManager() self._m.register('ports', PortAllocator) self._m.start() self._pool = multiprocessing.Pool(concurrency, self._pool_init, (self._m.address,)) self._log.debug( 'TestDispatcher started with %d concurrent jobs' % concurrency) def _pool_init(self, address): global stop global m global ports stop = self._stop m = multiprocessing.managers.BaseManager(address) m.connect() ports = m.ports() def _dispatch_sync(self, test, cont, max_retry): r = run_test(self.testdir, self.logdir, test, max_retry, async_mode=False) cont(r) return NonAsyncResult(r) def _dispatch_async(self, test, cont, max_retry): self._log.debug('_dispatch_async') return self._pool.apply_async(func=run_test, args=(self.testdir, self.logdir, test, max_retry), callback=cont) def dispatch(self, test, max_retry): index = self._report.add_test(test) def cont(result): if not self._stop.is_set(): if result and len(result) == 2: retry_count, returncode = result else: retry_count = 0 returncode = RESULT_ERROR self._log.debug('freeing port') self._log.debug('adding result') self._report.add_result(index, returncode, returncode == RESULT_TIMEOUT, retry_count) self._log.debug('finish continuation') fn = self._dispatch_async if self._async else self._dispatch_sync return fn(test, cont, max_retry) def wait(self): if self._async: self._pool.close() self._pool.join() self._m.shutdown() return self._report.end() def terminate(self): self._stop.set() if self._async: self._pool.terminate() self._pool.join() self._m.shutdown() thrift-0.19.0/test/crossrunner/setup.cfg0000644000000000000000000000003714303740367020271 0ustar00rootroot00000000000000[flake8] max-line-length = 100 thrift-0.19.0/test/crossrunner/util.py0000644000000000000000000000222114370300523017762 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import copy def domain_socket_path(port): return '/tmp/v0.16/ThriftTest.thrift.%d' % port def merge_dict(base, update): """Update dict concatenating list values""" res = copy.deepcopy(base) for k, v in list(update.items()): if k in list(res.keys()) and isinstance(v, list): res[k].extend(v) else: res[k] = v return res thrift-0.19.0/test/crossrunner/report.py0000644000000000000000000004020114303740367020332 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import print_function import datetime import json import multiprocessing import os import platform import re import subprocess import sys import time import traceback from .compat import logfile_open, path_join, str_join from .test import TestEntry LOG_DIR = 'log' RESULT_HTML = 'index.html' RESULT_JSON = 'results.json' FAIL_JSON = 'known_failures_%s.json' def generate_known_failures(testdir, overwrite, save, out): def collect_failures(results): success_index = 5 for r in results: if not r[success_index]: yield TestEntry.get_name(*r) try: with logfile_open(path_join(testdir, RESULT_JSON), 'r') as fp: results = json.load(fp) except IOError: sys.stderr.write('Unable to load last result. Did you run tests ?\n') return False fails = collect_failures(results['results']) if not overwrite: known = load_known_failures(testdir) known.extend(fails) fails = known fails_json = json.dumps(sorted(set(fails)), indent=2, separators=(',', ': ')) if save: with logfile_open(os.path.join(testdir, FAIL_JSON % platform.system()), 'w+') as fp: fp.write(fails_json) sys.stdout.write('Successfully updated known failures.\n') if out: sys.stdout.write(fails_json) sys.stdout.write('\n') return True def load_known_failures(testdir): try: with logfile_open(path_join(testdir, FAIL_JSON % platform.system()), 'r') as fp: return json.load(fp) except IOError: return [] class TestReporter(object): # Unfortunately, standard library doesn't handle timezone well # DATETIME_FORMAT = '%a %b %d %H:%M:%S %Z %Y' DATETIME_FORMAT = '%a %b %d %H:%M:%S %Y' def __init__(self): self._log = multiprocessing.get_logger() self._lock = multiprocessing.Lock() @classmethod def test_logfile(cls, test_name, prog_kind, dir=None): relpath = path_join('log', '%s_%s.log' % (test_name, prog_kind)) return relpath if not dir else os.path.realpath(path_join(dir, relpath)) def _start(self): self._start_time = time.time() @property def _elapsed(self): return time.time() - self._start_time @classmethod def _format_date(cls): return '%s' % datetime.datetime.now().strftime(cls.DATETIME_FORMAT) def _print_date(self): print(self._format_date(), file=self.out) def _print_bar(self, out=None): print( '===============================================================================', file=(out or self.out)) def _print_exec_time(self): print('Test execution took {:.1f} seconds.'.format(self._elapsed), file=self.out) class ExecReporter(TestReporter): def __init__(self, testdir, test, prog): super(ExecReporter, self).__init__() self._test = test self._prog = prog self.logpath = self.test_logfile(test.name, prog.kind, testdir) self.out = None def begin(self): self._start() self._open() if self.out and not self.out.closed: self._print_header() else: self._log.debug('Output stream is not available.') def end(self, returncode): self._lock.acquire() try: if self.out and not self.out.closed: self._print_footer(returncode) self._close() self.out = None else: self._log.debug('Output stream is not available.') finally: self._lock.release() def killed(self): print(file=self.out) print('Server process is successfully killed.', file=self.out) self.end(None) def died(self): print(file=self.out) print('*** Server process has died unexpectedly ***', file=self.out) self.end(None) _init_failure_exprs = { 'server': list(map(re.compile, [ '[Aa]ddress already in use', 'Could not bind', 'EADDRINUSE', ])), 'client': list(map(re.compile, [ '[Cc]onnection refused', 'Could not connect to', 'Could not open UNIX ', # domain socket (rb) 'ECONNREFUSED', 'econnrefused', # erl 'CONNECTION-REFUSED-ERROR', # cl 'connect ENOENT', # nodejs domain socket 'No such file or directory', # domain socket 'Sockets.TcpClient.Connect', # csharp ])), } def maybe_false_positive(self): """Searches through log file for socket bind error. Returns True if suspicious expression is found, otherwise False""" try: if self.out and not self.out.closed: self.out.flush() exprs = self._init_failure_exprs[self._prog.kind] def match(line): for expr in exprs: if expr.search(line): self._log.info("maybe false positive: %s" % line) return True with logfile_open(self.logpath, 'r') as fp: if any(map(match, fp)): return True except (KeyboardInterrupt, SystemExit): raise except Exception as ex: self._log.warn('[%s]: Error while detecting false positive: %s' % (self._test.name, str(ex))) self._log.info(traceback.print_exc()) return False def _open(self): self.out = logfile_open(self.logpath, 'w+') def _close(self): self.out.close() def _print_header(self): self._print_date() print('Executing: %s' % str_join(' ', self._prog.command), file=self.out) print('Directory: %s' % self._prog.workdir, file=self.out) print('config:delay: %s' % self._test.delay, file=self.out) print('config:timeout: %s' % self._test.timeout, file=self.out) self._print_bar() self.out.flush() def _print_footer(self, returncode=None): self._print_bar() if returncode is not None: print('Return code: %d (negative values indicate kill by signal)' % returncode, file=self.out) else: print('Process is killed.', file=self.out) self._print_exec_time() self._print_date() class SummaryReporter(TestReporter): def __init__(self, basedir, testdir_relative, concurrent=True): super(SummaryReporter, self).__init__() self._basedir = basedir self._testdir_rel = testdir_relative self.logdir = path_join(self.testdir, LOG_DIR) self.out_path = path_join(self.testdir, RESULT_JSON) self.concurrent = concurrent self.out = sys.stdout self._platform = platform.system() self._revision = self._get_revision() self._tests = [] if not os.path.exists(self.logdir): os.mkdir(self.logdir) self._known_failures = load_known_failures(self.testdir) self._unexpected_success = [] self._flaky_success = [] self._unexpected_failure = [] self._expected_failure = [] self._print_header() @property def testdir(self): return path_join(self._basedir, self._testdir_rel) def _result_string(self, test): if test.success: if test.retry_count == 0: return 'success' elif test.retry_count == 1: return 'flaky(1 retry)' else: return 'flaky(%d retries)' % test.retry_count elif test.expired: return 'failure(timeout)' else: return 'failure(%d)' % test.returncode def _get_revision(self): p = subprocess.Popen(['git', 'rev-parse', '--short', 'HEAD'], cwd=self.testdir, stdout=subprocess.PIPE) out, _ = p.communicate() return out.strip() def _format_test(self, test, with_result=True): name = '%s-%s' % (test.server.name, test.client.name) trans = '%s-%s' % (test.transport, test.socket) if not with_result: return '{:24s}{:18s}{:25s}'.format(name[:23], test.protocol[:17], trans[:24]) else: return '{:24s}{:18s}{:25s}{:s}\n'.format(name[:23], test.protocol[:17], trans[:24], self._result_string(test)) def _print_test_header(self): self._print_bar() print( '{:24s}{:18s}{:25s}{:s}'.format('server-client:', 'protocol:', 'transport:', 'result:'), file=self.out) def _print_header(self): self._start() print('Apache Thrift - Integration Test Suite', file=self.out) self._print_date() self._print_test_header() def _print_unexpected_failure(self): if len(self._unexpected_failure) > 0: self.out.writelines([ '*** Following %d failures were unexpected ***:\n' % len(self._unexpected_failure), 'If it is introduced by you, please fix it before submitting the code.\n', # 'If not, please report at https://issues.apache.org/jira/browse/THRIFT\n', ]) self._print_test_header() for i in self._unexpected_failure: self.out.write(self._format_test(self._tests[i])) self._print_bar() else: print('No unexpected failures.', file=self.out) def _print_flaky_success(self): if len(self._flaky_success) > 0: print( 'Following %d tests were expected to cleanly succeed but needed retry:' % len(self._flaky_success), file=self.out) self._print_test_header() for i in self._flaky_success: self.out.write(self._format_test(self._tests[i])) self._print_bar() def _print_unexpected_success(self): if len(self._unexpected_success) > 0: print( 'Following %d tests were known to fail but succeeded (maybe flaky):' % len(self._unexpected_success), file=self.out) self._print_test_header() for i in self._unexpected_success: self.out.write(self._format_test(self._tests[i])) self._print_bar() def _http_server_command(self, port): if sys.version_info[0] < 3: return 'python -m SimpleHTTPServer %d' % port else: return 'python -m http.server %d' % port def _print_footer(self): fail_count = len(self._expected_failure) + len(self._unexpected_failure) self._print_bar() self._print_unexpected_success() self._print_flaky_success() self._print_unexpected_failure() self._write_html_data() self._assemble_log('unexpected failures', self._unexpected_failure) self._assemble_log('known failures', self._expected_failure) self.out.writelines([ 'You can browse results at:\n', '\tfile://%s/%s\n' % (self.testdir, RESULT_HTML), '# If you use Chrome, run:\n', '# \tcd %s\n#\t%s\n' % (self._basedir, self._http_server_command(8001)), '# then browse:\n', '# \thttp://localhost:%d/%s/\n' % (8001, self._testdir_rel), 'Full log for each test is here:\n', '\ttest/log/server_client_protocol_transport_client.log\n', '\ttest/log/server_client_protocol_transport_server.log\n', '%d failed of %d tests in total.\n' % (fail_count, len(self._tests)), ]) self._print_exec_time() self._print_date() def _render_result(self, test): return [ test.server.name, test.client.name, test.protocol, test.transport, test.socket, test.success, test.as_expected, test.returncode, { 'server': self.test_logfile(test.name, test.server.kind), 'client': self.test_logfile(test.name, test.client.kind), }, ] def _write_html_data(self): """Writes JSON data to be read by result html""" results = [self._render_result(r) for r in self._tests] with logfile_open(self.out_path, 'w+') as fp: fp.write(json.dumps({ 'date': self._format_date(), 'revision': str(self._revision), 'platform': self._platform, 'duration': '{:.1f}'.format(self._elapsed), 'results': results, }, indent=2)) def _assemble_log(self, title, indexes): if len(indexes) > 0: def add_prog_log(fp, test, prog_kind): print('*************************** %s message ***************************' % prog_kind, file=fp) path = self.test_logfile(test.name, prog_kind, self.testdir) if os.path.exists(path): with logfile_open(path, 'r') as prog_fp: print(prog_fp.read(), file=fp) filename = title.replace(' ', '_') + '.log' with logfile_open(os.path.join(self.logdir, filename), 'w+') as fp: for test in map(self._tests.__getitem__, indexes): fp.write('TEST: [%s]\n' % test.name) add_prog_log(fp, test, test.server.kind) add_prog_log(fp, test, test.client.kind) fp.write('**********************************************************************\n\n') print('%s are logged to %s/%s/%s' % (title.capitalize(), self._testdir_rel, LOG_DIR, filename)) def end(self): self._print_footer() return len(self._unexpected_failure) == 0 def add_test(self, test_dict): test = TestEntry(self.testdir, **test_dict) self._lock.acquire() try: if not self.concurrent: self.out.write(self._format_test(test, False)) self.out.flush() self._tests.append(test) return len(self._tests) - 1 finally: self._lock.release() def add_result(self, index, returncode, expired, retry_count): self._lock.acquire() try: failed = returncode is None or returncode != 0 flaky = not failed and retry_count != 0 test = self._tests[index] known = test.name in self._known_failures if failed: if known: self._log.debug('%s failed as expected' % test.name) self._expected_failure.append(index) else: self._log.info('unexpected failure: %s' % test.name) self._unexpected_failure.append(index) elif flaky and not known: self._log.info('unexpected flaky success: %s' % test.name) self._flaky_success.append(index) elif not flaky and known: self._log.info('unexpected success: %s' % test.name) self._unexpected_success.append(index) test.success = not failed test.returncode = returncode test.retry_count = retry_count test.expired = expired test.as_expected = known == failed if not self.concurrent: self.out.write(self._result_string(test) + '\n') else: self.out.write(self._format_test(test)) finally: self._lock.release() thrift-0.19.0/test/OptionalRequiredTest.thrift0000644000000000000000000000420414303740367021435 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace c_glib TTest namespace cpp thrift.test namespace java thrift.test struct OldSchool { 1: i16 im_int; 2: string im_str; 3: list> im_big; } struct Simple { 1: /* :) */ i16 im_default; 2: required i16 im_required; 3: optional i16 im_optional; } struct Tricky1 { 1: /* :) */ i16 im_default; } struct Tricky2 { 1: optional i16 im_optional; } struct Tricky3 { 1: required i16 im_required; } struct OptionalDefault { 1: optional i16 opt_int = 1234; 2: optional string opt_str = "default"; } struct Complex { 1: i16 cp_default; 2: required i16 cp_required; 3: optional i16 cp_optional; 4: map the_map; 5: required Simple req_simp; 6: optional Simple opt_simp; } struct ManyOpt { 1: optional i32 opt1; 2: optional i32 opt2; 3: optional i32 opt3; 4: i32 def4; 5: optional i32 opt5; 6: optional i32 opt6; } struct JavaTestHelper { 1: required i32 req_int; 2: optional i32 opt_int; 3: required string req_obj; 4: optional string opt_obj; 5: required binary req_bin; 6: optional binary opt_bin; } struct Binaries { 4: binary bin; 5: required binary req_bin; 6: optional binary opt_bin; } thrift-0.19.0/test/haxe/0000755000000000000000000000000014472652674015024 5ustar00rootroot00000000000000thrift-0.19.0/test/haxe/make_all.bat0000644000000000000000000000354614303740367017257 0ustar00rootroot00000000000000@echo off rem /* rem * Licensed to the Apache Software Foundation (ASF) under one rem * or more contributor license agreements. See the NOTICE file rem * distributed with this work for additional information rem * regarding copyright ownership. The ASF licenses this file rem * to you under the Apache License, Version 2.0 (the rem * "License"); you may not use this file except in compliance rem * with the License. You may obtain a copy of the License at rem * rem * http://www.apache.org/licenses/LICENSE-2.0 rem * rem * Unless required by applicable law or agreed to in writing, rem * software distributed under the License is distributed on an rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY rem * KIND, either express or implied. See the License for the rem * specific language governing permissions and limitations rem * under the License. rem */ setlocal if "%HOMEDRIVE%"=="" goto MISSINGVARS if "%HOMEPATH%"=="" goto MISSINGVARS if "%HAXEPATH%"=="" goto NOTINSTALLED set path=%HAXEPATH%;%HAXEPATH%\..\neko;%path% rem # invoke Thrift comnpiler thrift -r -gen haxe ..\ThriftTest.thrift if errorlevel 1 goto STOP rem # invoke Haxe compiler for all targets rd .buildtemp /S /Q for %%a in (*.hxml) do ( echo -------------------------- echo Building %%a ... echo -------------------------- haxe --cwd . %%a if not exist ".buildtemp" mkdir ".buildtemp" move bin ".buildtemp\%%a" if errorlevel 1 pause ) rd bin /S /Q rename .buildtemp bin echo. echo done. pause goto eof :NOTINSTALLED echo FATAL: Either Haxe is not installed, or the HAXEPATH variable is not set. pause goto eof :MISSINGVARS echo FATAL: Unable to locate home folder. echo. echo Both HOMEDRIVE and HOMEPATH need to be set to point to your Home folder. echo The current values are: echo HOMEDRIVE=%HOMEDRIVE% echo HOMEPATH=%HOMEPATH% pause goto eof :STOP pause goto eof :eof thrift-0.19.0/test/haxe/php.hxml0000644000000000000000000000207414370300523016464 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #PHP target -php bin/php -D php-front=Main-debug.php # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce full thrift-0.19.0/test/haxe/router.php0000644000000000000000000000171414303740367017046 0ustar00rootroot00000000000000 0) { trace('==========================='); trace('FAILED TESTS: $failedTests'); } trace('==========================='); } } class TestClient { public static function Execute(args : Arguments) : Void { var exitCode = 0xFF; try { var difft = Timer.stamp(); if ( args.numThreads > 1) { #if cpp exitCode = MultiThreadClient(args); #else trace('Threads not supported/implemented for this platform.'); exitCode = SingleThreadClient(args); #end } else { exitCode = SingleThreadClient(args); } difft = Math.round( 1000 * (Timer.stamp() - difft)) / 1000; trace('total test time: $difft seconds'); } catch (e : TException) { trace('TException: $e'); exitCode = 0xFF; } catch (e : Dynamic) { trace('Exception: $e'); exitCode = 0xFF; } #if sys Sys.exit( exitCode); #end } public static function SingleThreadClient(args : Arguments) : Int { var rslt = new TestResults(true); RunClient(args,rslt); rslt.PrintSummary(); return rslt.CalculateExitCode(); } #if cpp public static function MultiThreadClient(args : Arguments) : Int { var threads = new List(); for( test in 0 ... args.numThreads) { threads.add( StartThread( args)); } var exitCode : Int = 0; for( thread in threads) { exitCode |= Thread.readMessage(true); } return exitCode; } #end #if cpp private static function StartThread(args : Arguments) : Thread { var thread = Thread.create( function() : Void { var rslt = new TestResults(false); var main : Thread = Thread.readMessage(true); try { RunClient(args,rslt); } catch (e : TException) { rslt.Expect( false, '$e'); trace('$e'); } catch (e : Dynamic) { rslt.Expect( false, '$e'); trace('$e'); } main.sendMessage( rslt.CalculateExitCode()); }); thread.sendMessage(Thread.current()); return thread; } #end public static function RunClient(args : Arguments, rslt : TestResults) { var transport : TTransport = null; switch (args.transport) { case socket: transport = new TSocket(args.host, args.port); case http: var uri = 'http://${args.host}:${args.port}'; trace('- http client : ${uri}'); transport = new THttpClient(uri); default: throw "Unhandled transport"; } // optional: layered transport if ( args.framed) { trace("- framed transport"); transport = new TFramedTransport(transport); } if ( args.buffered) { trace("- buffered transport"); transport = new TBufferedTransport(transport); } // protocol var protocol : TProtocol = null; switch( args.protocol) { case binary: trace("- binary protocol"); protocol = new TBinaryProtocol(transport); case json: trace("- json protocol"); protocol = new TJSONProtocol(transport); case compact: trace("- compact protocol"); protocol = new TCompactProtocol(transport); } // some quick and basic unit tests HaxeBasicsTest( args, rslt); ModuleUnitTests( args, rslt); // now run the test code trace('- ${args.numIterations} iterations'); for( i in 0 ... args.numIterations) { ClientTest( transport, protocol, args, rslt); } } public static function HaxeBasicsTest( args : Arguments, rslt : TestResults) : Void { // We need to test a few basic things used in the ClientTest // Anything else beyond this scope should go into /lib/haxe/ instead rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); var map32 = new IntMap(); var map64 = new Int64Map(); rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map Test #1"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map Test #2"); rslt.Expect( map32.remove( 4711) == map64.remove( Int64.make(47,11)), "Int64Map Test #3"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map Test #4"); map32.set( 42, 815); map64.set( Int64.make(0,42), 815); map32.set( -517, 23); map64.set( Int64.neg(Int64.make(0,517)), 23); map32.set( 0, -123); map64.set( Int64.make(0,0), -123); //trace('map32 = $map32'); //trace('map64 = $map64'); rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map Test #10"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map Test #11"); rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map Test #12"); rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map Test #13"); rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map Test #14"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map Test #15"); rslt.Expect( map32.get( -517) == map64.get( Int64.neg(Int64.make(0,517))), "Int64Map Test #16"); rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map Test #Int64.make(-5,17)"); rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map Test #18"); rslt.Expect( map32.remove( 4711) == map64.remove( Int64.make(47,11)), "Int64Map Test #19"); rslt.Expect( map32.remove( -517) == map64.remove( Int64.neg(Int64.make(0,517))), "Int64Map Test #20"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map Test #21"); rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map Test #22"); rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map Test #23"); rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map Test #24"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map Test #25"); rslt.Expect( map32.get( -517) == map64.get( Int64.neg(Int64.make(0,517))), "Int64Map Test #26"); rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map Test #27"); rslt.Expect( map32.get( 0) == map64.get( Int64.make(0,0)), "Int64Map Test #28"); map32.set( 42, 1); map64.set( Int64.make(0,42), 1); map32.set( -517, -2); map64.set( Int64.neg(Int64.make(0,517)), -2); map32.set( 0, 3); map64.set( Int64.make(0,0), 3); var c32 = 0; var ksum32 = 0; for (key in map32.keys()) { ++c32; ksum32 += key; } var c64 = 0; var ksum64 = Int64.make(0,0); for (key in map64.keys()) { ++c64; ksum64 = Int64.add( ksum64, key); } rslt.Expect( c32 == c64, "Int64Map Test #30"); rslt.Expect( '$ksum64' == '$ksum32', '$ksum64 == $ksum32 Test #31'); //compare without spaces because differ in php and cpp var s32 = map32.toString().replace(' ', ''); var s64 = map64.toString().replace(' ', ''); rslt.Expect( s32 == s64, "Int64Map.toString(): " + ' ("$s32" == "$s64") Test #32'); map32.remove( 42); map64.remove( Int64.make(0,42)); map32.remove( -517); map64.remove( Int64.neg(Int64.make(0,517))); map32.remove( 0); map64.remove( Int64.make(0,0)); rslt.Expect( map32.keys().hasNext() == map64.keys().hasNext(), "Int64Map Test #90"); rslt.Expect( map32.exists( 4711) == map64.exists( Int64.make(47,11)), "Int64Map Test #91"); rslt.Expect( map32.exists( -517) == map64.exists( Int64.neg(Int64.make(0,517))), "Int64Map Test #92"); rslt.Expect( map32.exists( 42) == map64.exists( Int64.make(0,42)), "Int64Map Test #93"); rslt.Expect( map32.exists( 0) == map64.exists( Int64.make(0,0)), "Int64Map Test #94"); rslt.Expect( map32.get( 4711) == map64.get( Int64.make(47,11)), "Int64Map Test #95"); rslt.Expect( map32.get( -517) == map64.get( Int64.make(-5,17)), "Int64Map Test #96"); rslt.Expect( map32.get( 42) == map64.get( Int64.make(0,42)), "Int64Map Test #97"); rslt.Expect( map32.get( 0) == map64.get( Int64.make(0, 0)), "Int64Map Test #98"); } // core module unit tests public static function ModuleUnitTests( args : Arguments, rslt : TestResults) : Void { #if debug try { BitConverter.UnitTest(); rslt.Expect( true, 'BitConverter.UnitTest Test #100'); } catch( e : Dynamic) { rslt.Expect( false, 'BitConverter.UnitTest: $e Test #100'); } try { ZigZag.UnitTest(); rslt.Expect( true, 'ZigZag.UnitTest Test #101'); } catch( e : Dynamic) { rslt.Expect( false, 'ZigZag.UnitTest: $e Test #101'); } try { UuidHelper.UnitTest(); rslt.Expect( true, 'UuidHelper.UnitTest Test #102'); } catch( e : Dynamic) { rslt.Expect( false, 'UuidHelper.UnitTest: $e Test #102'); } #end } public static function BytesToHex(data : Bytes) : String { var hex = ""; for ( i in 0 ... data.length) { hex += StringTools.hex( data.get(i), 2); } return hex; } public static function PrepareTestData(randomDist : Bool) : Bytes { var retval = Bytes.alloc(0x100); var initLen : Int = (retval.length > 0x100 ? 0x100 : retval.length); // linear distribution, unless random is requested if (!randomDist) { for (i in 0 ... initLen) { retval.set(i, i % 0x100); } return retval; } // random distribution for (i in 0 ... initLen) { retval.set(i, 0); } for (i in 1 ... initLen) { while( true) { var nextPos = Std.random(initLen); if (retval.get(nextPos) == 0) { retval.set( nextPos, i % 0x100); break; } } } return retval; } public static function ClientTest( transport : TTransport, protocol : TProtocol, args : Arguments, rslt : TestResults) : Void { var client = new ThriftTestImpl(protocol,protocol); try { if (!transport.isOpen()) { transport.open(); } } catch (e : TException) { rslt.Expect( false, 'unable to open transport: $e'); return; } catch (e : Dynamic) { rslt.Expect( false, 'unable to open transport: $e'); return; } var start = Date.now(); rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_EXCEPTIONS); // if arg == "Xception" throw Xception with errorCode = 1001 and message = arg trace('testException("Xception")'); try { client.testException("Xception"); rslt.Expect( false, 'testException("Xception") should throw'); } catch (e : Xception) { rslt.Expect( e.message == "Xception", 'testException("Xception") - e.message == "Xception"'); rslt.Expect( e.errorCode == 1001, 'testException("Xception") - e.errorCode == 1001'); } catch (e : TException) { rslt.Expect( false, 'testException("Xception") - ${e} : ${e.errorMsg}'); } catch (e : Dynamic) { rslt.Expect( false, 'testException("Xception") - $e'); } // if arg == "TException" throw TException trace('testException("TException")'); try { client.testException("TException"); rslt.Expect( false, 'testException("TException") should throw'); } catch (e : TException) { rslt.Expect( true, 'testException("TException") - $e : ${e.errorMsg}'); } catch (e : Dynamic) { rslt.Expect( false, 'testException("TException") - $e'); } // reopen the transport, just in case the server closed his end if (transport.isOpen()) transport.close(); transport.open(); // else do not throw anything trace('testException("bla")'); try { client.testException("bla"); rslt.Expect( true, 'testException("bla") should not throw'); } catch (e : TException) { rslt.Expect( false, 'testException("bla") - ${e} : ${e.errorMsg}'); } catch (e : Dynamic) { rslt.Expect( false, 'testException("bla") - $e'); } rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); trace('testVoid()'); client.testVoid(); trace(' = void'); rslt.Expect(true,"testVoid()"); // bump counter trace('testBool(${true})'); var b = client.testBool(true); trace(' = $b'); rslt.Expect(b, '$b == "${true}"'); trace('testBool(${false})'); b = client.testBool(false); trace(' = $b'); rslt.Expect( ! b, '$b == "${false}"'); trace('testString("Test")'); var s = client.testString("Test"); trace(' = "$s"'); rslt.Expect(s == "Test", '$s == "Test"'); trace('testByte(1)'); var i8 = client.testByte(1); trace(' = $i8'); rslt.Expect(i8 == 1, '$i8 == 1'); trace('testI32(-1)'); var i32 = client.testI32(-1); trace(' = $i32'); rslt.Expect(i32 == -1, '$i32 == -1'); trace('testI64(-34359738368)'); var i64 = client.testI64( Int64.make( 0xFFFFFFF8, 0x00000000)); // -34359738368 trace(' = $i64'); rslt.Expect( Int64.compare( i64, Int64.make( 0xFFFFFFF8, 0x00000000)) == 0, Int64.toStr(i64) +" == "+Int64.toStr(Int64.make( 0xFFFFFFF8, 0x00000000))); // edge case: the largest negative Int64 has no positive Int64 equivalent trace('testI64(-9223372036854775808)'); i64 = client.testI64( Int64.make( 0x80000000, 0x00000000)); // -9223372036854775808 trace(' = $i64'); rslt.Expect( Int64.compare( i64, Int64.make( 0x80000000, 0x00000000)) == 0, Int64.toStr(i64) +" == "+Int64.toStr(Int64.make( 0x80000000, 0x00000000))); trace('testDouble(5.325098235)'); var dub = client.testDouble(5.325098235); trace(' = $dub'); rslt.Expect(dub == 5.325098235, '$dub == 5.325098235'); var uuidOut : String = UuidHelper.CanonicalUuid("{00112233-4455-6677-8899-AABBCCDDEEFF}"); trace('testUuid(${uuidOut}'); try { var uuidIn = client.testUuid(uuidOut); trace('testUuid() = ${uuidIn}'); rslt.Expect( uuidIn == uuidOut, '${uuidIn} == ${uuidOut}'); } catch (e : TApplicationException) { trace('testUuid(${uuidOut}): '+e.errorMsg); // may not be supported by the server } var binOut = PrepareTestData(true); trace('testBinary('+BytesToHex(binOut)+')'); try { var binIn = client.testBinary(binOut); trace('testBinary() = '+BytesToHex(binIn)); rslt.Expect( binIn.length == binOut.length, '${binIn.length} == ${binOut.length}'); var len = ((binIn.length < binOut.length) ? binIn.length : binOut.length); for (ofs in 0 ... len) { if (binIn.get(ofs) != binOut.get(ofs)) { rslt.Expect( false, 'testBinary('+BytesToHex(binOut)+'): content mismatch at offset $ofs'); } } } catch (e : TApplicationException) { trace('testBinary('+BytesToHex(binOut)+'): '+e.errorMsg); // may not be supported by the server } rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_STRUCTS); trace('testStruct({"Zero", 1, -3, -5})'); var o = new Xtruct(); o.string_thing = "Zero"; o.byte_thing = 1; o.i32_thing = -3; o.i64_thing = Int64.make(0,-5); var i = client.testStruct(o); trace(' = {"' + i.string_thing + '", ' + i.byte_thing +', ' + i.i32_thing +', '+ Int64.toStr(i.i64_thing) + '}'); rslt.Expect( i.string_thing == o.string_thing, "i.string_thing == o.string_thing"); rslt.Expect( i.byte_thing == o.byte_thing, "i.byte_thing == o.byte_thing"); rslt.Expect( i.i32_thing == o.i32_thing, "i.i64_thing == o.i64_thing"); rslt.Expect( i.i32_thing == o.i32_thing, "i.i64_thing == o.i64_thing"); trace('testNest({1, {\"Zero\", 1, -3, -5}, 5})'); var o2 = new Xtruct2(); o2.byte_thing = 1; o2.struct_thing = o; o2.i32_thing = 5; var i2 = client.testNest(o2); i = i2.struct_thing; trace(" = {" + i2.byte_thing + ", {\"" + i.string_thing + "\", " + i.byte_thing + ", " + i.i32_thing + ", " + Int64.toStr(i.i64_thing) + "}, " + i2.i32_thing + "}"); rslt.Expect( i2.byte_thing == o2.byte_thing, "i2.byte_thing == o2.byte_thing"); rslt.Expect( i2.i32_thing == o2.i32_thing, "i2.i32_thing == o2.i32_thing"); rslt.Expect( i.string_thing == o.string_thing, "i.string_thing == o.string_thing"); rslt.Expect( i.byte_thing == o.byte_thing, "i.byte_thing == o.byte_thing"); rslt.Expect( i.i32_thing == o.i32_thing, "i.i32_thing == o.i32_thing"); rslt.Expect( Int64.compare( i.i64_thing, o.i64_thing) == 0, "i.i64_thing == o.i64_thing"); rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_CONTAINERS); var mapout = new IntMap< haxe.Int32>(); for ( j in 0 ... 5) { mapout.set(j, j - 10); } trace("testMap({"); var first : Bool = true; for( key in mapout.keys()) { if (first) { first = false; } else { trace(", "); } trace(key + " => " + mapout.get(key)); } trace("})"); var mapin = client.testMap(mapout); trace(" = {"); first = true; for( key in mapin.keys()) { if (first) { first = false; } else { trace(", "); } trace(key + " => " + mapin.get(key)); rslt.Expect( mapin.get(key) == mapout.get(key), ' mapin.get($key) == mapout.get($key)'); } trace("}"); for( key in mapout.keys()) { rslt.Expect(mapin.exists(key), 'mapin.exists($key)'); } var listout = new List(); for (j in -2 ... 3) { listout.add(j); } trace("testList({"); first = true; for( j in listout) { if (first) { first = false; } else { trace(", "); } trace(j); } trace("})"); var listin = client.testList(listout); trace(" = {"); first = true; for( j in listin) { if (first) { first = false; } else { trace(", "); } trace(j); } trace("}"); rslt.Expect(listin.length == listout.length, "listin.length == listout.length"); var literout = listout.iterator(); var literin = listin.iterator(); while( literin.hasNext()) { rslt.Expect(literin.next() == literout.next(), "literin[i] == literout[i]"); } //set var setout = new IntSet(); for (j in -2 ... 3) { setout.add(j); } trace("testSet({"); first = true; for( j in setout) { if (first) { first = false; } else { trace(", "); } trace(j); } trace("})"); var setin = client.testSet(setout); trace(" = {"); first = true; for( j in setin) { if (first) { first = false; } else { trace(", "); } trace(j); rslt.Expect(setout.contains(j), 'setout.contains($j)'); } trace("}"); rslt.Expect(setin.size == setout.size, "setin.length == setout.length"); rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_BASETYPES); trace("testEnum(ONE)"); var ret = client.testEnum(Numberz.ONE); trace(" = " + ret); rslt.Expect(ret == Numberz.ONE, '$ret == Numberz.ONE'); trace("testEnum(TWO)"); ret = client.testEnum(Numberz.TWO); trace(" = " + ret); rslt.Expect(ret == Numberz.TWO, '$ret == Numberz.TWO'); trace("testEnum(THREE)"); ret = client.testEnum(Numberz.THREE); trace(" = " + ret); rslt.Expect(ret == Numberz.THREE, '$ret == Numberz.THREE'); trace("testEnum(FIVE)"); ret = client.testEnum(Numberz.FIVE); trace(" = " + ret); rslt.Expect(ret == Numberz.FIVE, '$ret == Numberz.FIVE'); trace("testEnum(EIGHT)"); ret = client.testEnum(Numberz.EIGHT); trace(" = " + ret); rslt.Expect(ret == Numberz.EIGHT, '$ret == Numberz.EIGHT'); trace("testTypedef(309858235082523)"); var uid = client.testTypedef( Int64.make( 0x119D0, 0x7E08671B)); // 309858235082523 trace(" = " + uid); rslt.Expect( Int64.compare( uid, Int64.make( 0x119D0, 0x7E08671B)) == 0, Int64.toStr(uid)+" == "+Int64.toStr(Int64.make( 0x119D0, 0x7E08671B))); rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_CONTAINERS); trace("testMapMap(1)"); var mm = client.testMapMap(1); trace(" = {"); for( key in mm.keys()) { trace(key + " => {"); var m2 = mm.get(key); for( k2 in m2.keys()) { trace(k2 + " => " + m2.get(k2) + ", "); } trace("}, "); } trace("}"); var pos = mm.get(4); var neg = mm.get(-4); rslt.Expect( (pos != null) && (neg != null), "(pos != null) && (neg != null)"); for (i in 1 ... 5) { rslt.Expect( pos.get(i) == i, 'pos.get($i) == $i'); rslt.Expect( neg.get(-i) == -i, 'neg.get(-$i) == -$i'); } rslt.Expect( ! pos.exists(0), '!pos.exists(0)'); rslt.Expect( ! neg.exists(-0), '!neg.exists(-0)'); rslt.Expect( ! pos.exists(42), '!pos.exists(42)'); rslt.Expect( ! neg.exists(-42), '!neg.exists(-42)'); rslt.StartTestGroup( TestResults.EXITCODE_FAILBIT_STRUCTS); var insane = new Insanity(); insane.userMap = new IntMap< Int64>(); insane.userMap.set( Numberz.FIVE, Int64.make(0,5000)); var truck = new Xtruct(); truck.string_thing = "Truck"; truck.byte_thing = 8; truck.i32_thing = 8; truck.i64_thing = Int64.make(0,8); insane.xtructs = new List(); insane.xtructs.add(truck); trace("testInsanity()"); var whoa = client.testInsanity(insane); trace(" = {"); for( key in whoa.keys()) { var val = whoa.get(key); trace(key + " => {"); for( k2 in val.keys()) { var v2 = val.get(k2); trace(k2 + " => {"); var userMap = v2.userMap; trace("{"); if (userMap != null) { for( k3 in userMap.keys()) { trace(k3 + " => " + userMap.get(k3) + ", "); } } else { trace("null"); } trace("}, "); var xtructs = v2.xtructs; trace("{"); if (xtructs != null) { for( x in xtructs) { trace("{\"" + x.string_thing + "\", " + x.byte_thing + ", " + x.i32_thing + ", " + x.i32_thing + "}, "); } } else { trace("null"); } trace("}"); trace("}, "); } trace("}, "); } trace("}"); /** * So you think you've got this all worked, out eh? * * Creates a the returned map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, * 2 => { 6 => , }, * } * @return map> - a map with the above values */ var first_map = whoa.get(Int64.make(0,1)); var second_map = whoa.get(Int64.make(0,2)); rslt.Expect( (first_map != null) && (second_map != null), "(first_map != null) && (second_map != null)"); if ((first_map != null) && (second_map != null)) { var crazy2 = first_map.get(Numberz.TWO); var crazy3 = first_map.get(Numberz.THREE); var looney = second_map.get(Numberz.SIX); rslt.Expect( (crazy2 != null) && (crazy3 != null) && (looney != null), "(crazy2 != null) && (crazy3 != null) && (looney != null)"); var crz2iter = crazy2.xtructs.iterator(); var crz3iter = crazy3.xtructs.iterator(); rslt.Expect( crz2iter.hasNext() && crz3iter.hasNext(), "crz2iter.hasNext() && crz3iter.hasNext()"); var goodbye2 = crz2iter.next(); var goodbye3 = crz3iter.next(); rslt.Expect( ! (crz2iter.hasNext() || crz3iter.hasNext()), "! (crz2iter.hasNext() || crz3iter.hasNext())"); rslt.Expect( Int64.compare( crazy2.userMap.get(Numberz.FIVE), insane.userMap.get(Numberz.FIVE)) == 0, "crazy2.userMap[5] == insane.userMap[5]"); rslt.Expect( truck.string_thing == goodbye2.string_thing, "truck.string_thing == goodbye2.string_thing"); rslt.Expect( truck.byte_thing == goodbye2.byte_thing, "truck.byte_thing == goodbye2.byte_thing"); rslt.Expect( truck.i32_thing == goodbye2.i32_thing, "truck.i32_thing == goodbye2.i32_thing"); rslt.Expect( Int64.compare( truck.i64_thing, goodbye2.i64_thing) == 0, "truck.i64_thing == goodbye2.i64_thing"); rslt.Expect( Int64.compare( crazy3.userMap.get(Numberz.FIVE), insane.userMap.get(Numberz.FIVE)) == 0, "crazy3.userMap[5] == insane.userMap[5]"); rslt.Expect( truck.string_thing == goodbye3.string_thing, "truck.string_thing == goodbye3.string_thing"); rslt.Expect( truck.byte_thing == goodbye3.byte_thing, "truck.byte_thing == goodbye3.byte_thing"); rslt.Expect( truck.i32_thing == goodbye3.i32_thing, "truck.i32_thing == goodbye3.i32_thing"); rslt.Expect( Int64.compare( truck.i64_thing, goodbye3.i64_thing) == 0, "truck.i64_thing == goodbye3.i64_thing"); rslt.Expect( ! looney.isSet(1), "! looney.isSet(1)"); rslt.Expect( ! looney.isSet(2), "! looney.isSet(2)"); } var arg0 = 1; var arg1 = 2; var arg2 = Int64.make( 0x7FFFFFFF,0xFFFFFFFF); var multiDict = new IntMap< String>(); multiDict.set(1, "one"); var arg4 = Numberz.FIVE; var arg5 = Int64.make(0,5000000); trace("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + "," + multiDict + "," + arg4 + "," + arg5 + ")"); var multiResponse = client.testMulti(arg0, arg1, arg2, multiDict, arg4, arg5); trace(" = Xtruct(byte_thing:" + multiResponse.byte_thing + ",string_thing:" + multiResponse.string_thing + ",i32_thing:" + multiResponse.i32_thing + ",i64_thing:" + Int64.toStr(multiResponse.i64_thing) + ")"); rslt.Expect( multiResponse.string_thing == "Hello2", 'multiResponse.String_thing == "Hello2"'); rslt.Expect( multiResponse.byte_thing == arg0, 'multiResponse.Byte_thing == arg0'); rslt.Expect( multiResponse.i32_thing == arg1, 'multiResponse.I32_thing == arg1'); rslt.Expect( Int64.compare( multiResponse.i64_thing, arg2) == 0, 'multiResponse.I64_thing == arg2'); rslt.StartTestGroup( 0); trace("Test Oneway(1)"); client.testOneway(1); if( ! args.skipSpeedTest) { trace("Test Calltime()"); var difft = Timer.stamp(); for ( k in 0 ... 1000) { client.testVoid(); } difft = Math.round( 1000 * (Timer.stamp() - difft)) / 1000; trace('$difft ms per testVoid() call'); } } } thrift-0.19.0/test/haxe/src/TestMacro.hx0000644000000000000000000000256614303740367020054 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package ; import haxe.macro.Context; import haxe.macro.Expr; /**** * If you call the Thrift compiler this way (e.g. by changing the prebuild command) * * thrift -r -gen haxe:buildmacro=TestMacro.handle() ../ThriftTest.thrift * * the TestMacro.handle() function implemented below is called for each generated class * and interface. Use "thrift --help" to get more info about other available options. */ class TestMacro { public static function handle( ) : Array< Field> { trace('TestMacro called for ' + Context.getLocalType()); return Context.getBuildFields(); } } thrift-0.19.0/test/haxe/src/Main.hx0000644000000000000000000000445014303740367017031 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package; import org.apache.thrift.*; import org.apache.thrift.protocol.*; import org.apache.thrift.transport.*; import org.apache.thrift.server.*; import org.apache.thrift.meta_data.*; import thrift.test.*; // generated code class Main { static function main() { #if phpwebserver initPhpWebServer(); //check method if(php.Web.getMethod() != 'POST') { Sys.println('http endpoint for thrift test server'); return; } #end try { var args = new Arguments(); if( args.printHelpOnly) return; if (args.server) TestServer.Execute(args); else TestClient.Execute(args); trace("Completed."); } catch (e : String) { trace(e); } } #if phpwebserver private static function initPhpWebServer() { //remap trace to error log haxe.Log.trace = function(v:Dynamic, ?infos:haxe.PosInfos) { // handle trace var newValue : Dynamic; if (infos != null && infos.customParams!=null) { var extra:String = ""; for( v in infos.customParams ) extra += "," + v; newValue = v + extra; } else { newValue = v; } var msg = infos != null ? infos.fileName + ':' + infos.lineNumber + ': ' : ''; Sys.stderr().writeString('${msg}${newValue}\n'); } } #end } thrift-0.19.0/test/haxe/src/Arguments.hx0000644000000000000000000002601114303740367020107 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package; import org.apache.thrift.*; import org.apache.thrift.protocol.*; import org.apache.thrift.transport.*; import org.apache.thrift.server.*; import org.apache.thrift.meta_data.*; import haxe.io.Path; using StringTools; enum ProtocolType { binary; json; compact; } enum EndpointTransport { socket; http; } enum ServerType { simple; /* threadpool; threaded; nonblocking; */ } class Arguments { public var printHelpOnly(default,null) : Bool = false; public var server(default,null) : Bool = false; public var servertype(default,null) : ServerType = simple; public var host(default,null) : String = "localhost"; public var port(default,null) : Int = 9090; public var protocol(default,null) : ProtocolType = binary; public var transport(default,null) : EndpointTransport = socket; public var framed(default,null) : Bool = false; public var buffered(default,null) : Bool = false; public var numIterations(default,null) : Int = 1; public var numThreads(default,null) : Int = 1; public var skipSpeedTest(default,null) : Bool = false; public function new() { #if sys #if !phpwebserver try { ParseArgs(); } catch (e : String) { trace(GetHelp()); throw e; } #else //forcing server server = true; transport = http; #end #else trace("WN: Platform does not support program arguments, using defaults."); #end } #if sys private static function GetHelp() : String { var sProg = Path.withoutDirectory( Sys.programPath()); return "\n" +sProg+" [client|server] [options]\n" +"\n" +"Modus: Either client or server, the default is client.\n" +"\n" +"Common options:\n" +" -h [ --help ] produce help message\n" +" --port arg (=9090) Port number to listen / connect to\n" /* not supported yet +" --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)\n" +" --pipe arg Windows Named Pipe (e.g. MyThriftPipe)\n" */ +" --protocol arg (=binary) protocol: binary, compact, json\n" /* not supported yet +" --ssl Encrypted Transport using SSL\n" */ +"\n" +"Server only options:\n" +" --transport arg (=sockets) Transport: buffered, framed, http, anonpipe\n" /* not supported yet +" --processor-events processor-events\n" +" --server-type arg (=simple) type of server, \"simple\", \"thread-pool\", \n" +" \"threaded\", or \"nonblocking\"\n" +" -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for \n" +" thread-pool server type\n" */ +"\n" +"Client only options:\n" +" --host arg (=localhost) Host to connect\n" +" --transport arg (=sockets) Transport: buffered, framed, http, evhttp\n" /* not supported yet +" --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)\n" */ +" -n [ --testloops ] arg (=1) Number of Tests\n" +" -t [ --threads ] arg (=1) Number of Test threads\n" +" --skip-speed-test Skip the speed test\n" +"\n" +"All arguments are optional.\n" ; } private function ParseArgs() : Void { var args = Sys.args().copy(); if( (args == null) || (args.length <= 0)) { server = false; numThreads = 1; return; } var arg = args.shift(); if ( arg == "client") { server = false; numThreads = 1; } else if ( arg == "server") { server = true; numThreads = 4; } else if ( (arg == "-h") || (arg == "--help")) { // -h [ --help ] produce help message Sys.println( GetHelp()); printHelpOnly = true; return; } else { throw "First argument must be 'server' or 'client'"; } while( args.length > 0) { arg = args.shift(); if ( (arg == "-h") || (arg == "--help")) { // -h [ --help ] produce help message Sys.println( GetHelp()); printHelpOnly = true; return; } else if (arg == "--port") { // --port arg (=9090) Port number to listen arg = args.shift(); var tmp = Std.parseInt(arg); if( tmp != null) { port = tmp; } else { throw "Invalid port number "+arg; } } else if (arg == "--domain-socket") { // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) throw "domain sockets not supported yet"; } else if (arg == "--pipe") { // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) throw "named pipes not supported yet"; } else if (arg == "--protocol") { // --protocol arg (=binary) protocol: binary, compact, json arg = args.shift(); if( arg == "binary") { protocol = binary; } else if( arg == "compact") { protocol = compact; } else if( arg == "json") { protocol = json; } else { InvalidArg(arg); } } else if (arg == "--ssl") { // --ssl Encrypted Transport using SSL throw "SSL not supported yet"; } else { //Server only options: if( server) { ParseServerArgument( arg, args); } else { ParseClientArgument( arg, args); } } } } private function ParseServerArgument( arg : String, args : Array) : Void { if (arg == "--transport") { // --transport arg (=sockets) Transport: buffered, framed, http, anonpipe arg = args.shift(); if( arg == "buffered") { buffered = true; } else if( arg == "framed") { framed = true; } else if( arg == "http") { transport = http; } else if( arg == "anonpipe") { throw "Anon pipes transport not supported yet"; } else { InvalidArg(arg); } } else if (arg == "--processor-events") { throw "Processor events not supported yet"; } else if (arg == "--server-type") { // --server-type arg (=simple) type of server, // one of "simple", "thread-pool", "threaded", "nonblocking" arg = args.shift(); if( arg == "simple") { servertype = simple; } else if( arg == "thread-pool") { throw arg+" server not supported yet"; } else if( arg == "threaded") { throw arg+" server not supported yet"; } else if( arg == "nonblocking") { throw arg+" server not supported yet"; } else { InvalidArg(arg); } } else if ((arg == "-n") || (arg == "--workers")) { // -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for // thread-pool server type arg = args.shift(); var tmp = Std.parseInt(arg); if( tmp != null) { numThreads = tmp; } else{ throw "Invalid number "+arg; } } else { InvalidArg(arg); } } private function ParseClientArgument( arg : String, args : Array) : Void { if (arg == "--host") { // --host arg (=localhost) Host to connect host = args.shift(); } else if (arg == "--transport") { // --transport arg (=sockets) Transport: buffered, framed, http, evhttp arg = args.shift(); if( arg == "buffered") { buffered = true; } else if( arg == "framed") { framed = true; } else if( arg == "http") { transport = http; } else if( arg == "evhttp") { throw "evhttp transport not supported yet"; } else { InvalidArg(arg); } } else if (arg == "--anon-pipes") { // --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) throw "Anon pipes transport not supported yet"; } else if ((arg == "-n") || (arg == "--testloops")) { // -n [ --testloops ] arg (=1) Number of Tests arg = args.shift(); var tmp = Std.parseInt(arg); if( tmp != null) { numIterations = tmp; } else { throw "Invalid number "+arg; } } else if ((arg == "-t") || (arg == "--threads")) { // -t [ --threads ] arg (=1) Number of Test threads arg = args.shift(); var tmp = Std.parseInt(arg); if( tmp != null) { numThreads = tmp; } else { throw "Invalid number "+arg; } } else if (arg == "--skip-speed-test") { // --skip-speed-test Skip the speed test skipSpeedTest = true; } else { InvalidArg(arg); } } #end private function InvalidArg( arg : String) : Void { throw 'Invalid argument $arg'; } } thrift-0.19.0/test/haxe/src/TestServerHandler.hx0000644000000000000000000003337314370300523021545 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package; import org.apache.thrift.*; import org.apache.thrift.protocol.*; import org.apache.thrift.transport.*; import org.apache.thrift.server.*; import org.apache.thrift.meta_data.*; import org.apache.thrift.helper.*; import uuid.Uuid; import haxe.Int32; import haxe.Int64; import haxe.io.Bytes; import haxe.ds.IntMap; import haxe.ds.StringMap; import haxe.ds.ObjectMap; import thrift.test.*; // generated code class TestServerHandler implements ThriftTest_service { public var server:TServer; public function new() { } /** * Prints "testVoid()" and returns nothing. */ public function testVoid():Void { trace("testVoid()"); } /** * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false' * @param bool thing - the bool data to print * @return bool - returns the bool 'thing' * * @param thing */ public function testBool(thing : Bool) : Bool { trace('testBool($thing)'); return thing; } /** * Prints 'testString("%s")' with thing as '%s' * @param string thing - the string to print * @return string - returns the string 'thing' * * @param thing */ public function testString(thing:String):String { trace("teststring(\"" + thing + "\")"); return thing; } /** * Prints 'testByte("%d")' with thing as '%d' * @param byte thing - the byte to print * @return byte - returns the byte 'thing' * * @param thing */ public function testByte(thing:haxe.Int32):haxe.Int32 { trace("testByte(" + thing + ")"); return thing; } /** * Prints 'testI32("%d")' with thing as '%d' * @param i32 thing - the i32 to print * @return i32 - returns the i32 'thing' * * @param thing */ public function testI32(thing:haxe.Int32):haxe.Int32 { trace("testI32(" + thing + ")"); return thing; } /** * Prints 'testI64("%d")' with thing as '%d' * @param i64 thing - the i64 to print * @return i64 - returns the i64 'thing' * * @param thing */ public function testI64(thing:haxe.Int64):haxe.Int64 { trace("testI64(" + thing + ")"); return thing; } /** * Prints 'testDouble("%f")' with thing as '%f' * @param double thing - the double to print * @return double - returns the double 'thing' * * @param thing */ public function testDouble(thing:Float):Float { trace("testDouble(" + thing + ")"); return thing; } /** * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data * @param binary thing - the binary data to print * @return binary - returns the binary 'thing' * * @param thing */ public function testBinary(thing : haxe.io.Bytes) : haxe.io.Bytes { var hex = ""; for ( i in 0 ... thing.length) { hex += StringTools.hex( thing.get(i), 2); } trace('testBinary($hex)'); return thing; } /** * Prints 'testUuid("%s")' * @param Uuid thing - the uuid to print * @return Uuid - returns the uuid 'thing' * * @param thing */ public function testUuid(thing : String) : String { trace('testUuid($thing)'); return thing; } /** * Prints 'testStruct("{%s}")' where thing has been formatted * into a string of comma separated values * @param Xtruct thing - the Xtruct to print * @return Xtruct - returns the Xtruct 'thing' * * @param thing */ public function testStruct(thing:Xtruct):Xtruct { trace("testStruct({" + "\"" + thing.string_thing + "\", " + thing.byte_thing + ", " + thing.i32_thing + ", " + Int64.toStr(thing.i64_thing) + "})"); return thing; } /** * Prints 'testNest("{%s}")' where thing has been formatted * into a string of the nested struct * @param Xtruct2 thing - the Xtruct2 to print * @return Xtruct2 - returns the Xtruct2 'thing' * * @param thing */ public function testNest(nest:Xtruct2):Xtruct2 { var thing:Xtruct = nest.struct_thing; trace("testNest({" + nest.byte_thing + ", {" + "\"" + thing.string_thing + "\", " + thing.byte_thing + ", " + thing.i32_thing + ", " + Int64.toStr(thing.i64_thing) + "}, " + nest.i32_thing + "})"); return nest; } /** * Prints 'testMap("{%s")' where thing has been formatted * into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' * * @param thing */ public function testMap(thing:IntMap):IntMap { trace("testMap({"); var first:Bool = true; for (key in thing.keys()) { if (first) { first = false; } else { trace(", "); }; trace(key + " => " + thing.get(key)); }; trace("})"); return thing; } /** * Prints 'testStringMap("{%s}")' where thing has been formatted * into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' * * @param thing */ public function testStringMap(thing:StringMap):StringMap { trace("testStringMap({"); var first:Bool = true; for (key in thing.keys()) { if (first) { first = false; } else { trace(", "); }; trace(key + " => " + thing.get(key)); }; trace("})"); return thing; } /** * Prints 'testSet("{%s}")' where thing has been formatted * into a string of values * separated by commas and new lines * @param set thing - the set to print * @return set - returns the set 'thing' * * @param thing */ public function testSet(thing:IntSet):IntSet { trace("testSet({"); var first:Bool = true; for (elem in thing) { if (first) { first = false; } else { trace(", "); }; trace(elem); }; trace("})"); return thing; } /** * Prints 'testList("{%s}")' where thing has been formatted * into a string of values * separated by commas and new lines * @param list thing - the list to print * @return list - returns the list 'thing' * * @param thing */ public function testList(thing:List):List { trace("testList({"); var first:Bool = true; for (elem in thing) { if (first) { first = false; } else { trace(", "); }; trace(elem); }; trace("})"); return thing; } /** * Prints 'testEnum("%d")' where thing has been formatted into it's numeric value * @param Numberz thing - the Numberz to print * @return Numberz - returns the Numberz 'thing' * * @param thing */ public function testEnum(thing:Int):Int { trace("testEnum(" + thing + ")"); return thing; } /** * Prints 'testTypedef("%d")' with thing as '%d' * @param UserId thing - the UserId to print * @return UserId - returns the UserId 'thing' * * @param thing */ public function testTypedef(thing:haxe.Int64):haxe.Int64 { trace("testTypedef(" + thing + ")"); return thing; } /** * Prints 'testMapMap("%d")' with hello as '%d' * @param i32 hello - the i32 to print * @return map> - returns a dictionary with these values: * {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, * 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } * * @param hello */ public function testMapMap(hello:haxe.Int32):IntMap> { trace("testMapMap(" + hello + ")"); var mapmap = new IntMap>(); var pos = new IntMap(); var neg = new IntMap(); for (i in 1 ... 5) { pos.set(i, i); neg.set(-i, -i); }; mapmap.set(4, pos); mapmap.set(-4, neg); return mapmap; } /** * So you think you've got this all worked, out eh? * * Creates a the returned map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, * 2 => { 6 => , }, * } * @return map> - a map with the above values * * @param argument */ public function testInsanity(argument : Insanity) : Int64Map< IntMap< Insanity>> { trace("testInsanity()"); var first_map = new IntMap< Insanity>(); first_map.set(Numberz.TWO, argument); first_map.set(Numberz.THREE, argument); var second_map = new IntMap< Insanity>(); var looney = new Insanity(); second_map.set(Numberz.SIX, looney); var insane = new Int64Map< IntMap< Insanity>>(); insane.set( Int64.make(0,1), first_map); insane.set( Int64.make(0,2), second_map); return insane; } /** * Prints 'testMulti()' * @param byte arg0 - * @param i32 arg1 - * @param i64 arg2 - * @param map arg3 - * @param Numberz arg4 - * @param UserId arg5 - * @return Xtruct - returns an Xtruct * with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 * and i64_thing = arg2 * * @param arg0 * @param arg1 * @param arg2 * @param arg3 * @param arg4 * @param arg5 */ public function testMulti(arg0:haxe.Int32, arg1:haxe.Int32, arg2:haxe.Int64, arg3:IntMap, arg4:Int, arg5:haxe.Int64):Xtruct { trace("testMulti()"); var hello = new Xtruct(); hello.string_thing = "Hello2"; hello.byte_thing = arg0; hello.i32_thing = arg1; hello.i64_thing = arg2; return hello; } /** * Print 'testException(%s)' with arg as '%s' * @param string arg - a string indication what type of exception to throw * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg * elsen if arg == "TException" throw TException * else do not throw anything * * @param arg */ public function testException(arg:String):Void { trace("testException(" + arg + ")"); if (arg == "Xception") { var x = new Xception(); x.errorCode = 1001; x.message = arg; throw x; }; if (arg == "TException") { throw new TException(); }; return; } /** * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' * @param string arg - a string indication what type of exception to throw * if arg0 == "Xception" * throw Xception with errorCode = 1001 and message = "This is an Xception" * else if arg0 == "Xception2" * throw Xception2 with errorCode = 2002 and message = "This is an Xception2" * else do not throw anything * @return Xtruct - an Xtruct with string_thing = arg1 * * @param arg0 * @param arg1 */ public function testMultiException(arg0:String, arg1:String):Xtruct { trace("testMultiException(" + arg0 + ", " + arg1 + ")"); if (arg0 == "Xception") { var x = new Xception(); x.errorCode = 1001; x.message = "This is an Xception"; throw x; } else if (arg0 == "Xception2") { var x = new Xception2(); x.errorCode = 2002; x.struct_thing = new Xtruct(); x.struct_thing.string_thing = "This is an Xception2"; throw x; }; var result = new Xtruct(); result.string_thing = arg1; return result; } /** * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' * sleep 'secondsToSleep' * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' * @param i32 secondsToSleep - the number of seconds to sleep * * @param secondsToSleep */ public function testOneway(secondsToSleep:haxe.Int32):Void { #if sys trace("testOneway(" + secondsToSleep + "), sleeping..."); Sys.sleep(secondsToSleep); #end trace("testOneway finished"); } public function testStop():Void { if (server != null) { server.Stop(); }; } } thrift-0.19.0/test/haxe/src/TestServer.hx0000644000000000000000000001010414303740367020244 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package; import org.apache.thrift.*; import org.apache.thrift.protocol.*; import org.apache.thrift.transport.*; import org.apache.thrift.server.*; import org.apache.thrift.meta_data.*; import thrift.test.*; // generated code class TestServer { public static function Execute(args : Arguments) : Void { try { // Transport var transport : TServerTransport = null; switch( args.transport) { case socket: trace("- socket port "+args.port); #if (flash || html5 || js) throw "Transport not supported on this platform"; #else transport = new TServerSocket( args.port); #end case http: trace("- http"); #if phpwebserver transport = new TWrappingServerTransport( new TStreamTransport( new TFileStream("php://input", Read), new TFileStream("php://output", Append), null ) ); #else throw "Transport not supported on this platform"; //transport = new THttpServer( targetHost); #end default: throw "Unhandled transport"; } // optional: layered transport var transfactory : TTransportFactory = null; if ( args.framed) { trace("- framed transport"); transfactory = new TFramedTransportFactory(); } if ( args.buffered) { trace("- buffered transport"); transfactory = new TBufferedTransportFactory(); } // protocol var protfactory : TProtocolFactory = null; switch( args.protocol) { case binary: trace("- binary protocol"); protfactory = new TBinaryProtocolFactory(); case json: trace("- json protocol"); protfactory = new TJSONProtocolFactory(); case compact: trace("- compact protocol"); protfactory = new TCompactProtocolFactory(); } // Processor var handler : ThriftTest_service = new TestServerHandler(); var processor = new ThriftTestProcessor(handler); // Simple Server var server : TServer = null; switch( args.servertype) { case simple: var simpleServer = new TSimpleServer( processor, transport, transfactory, protfactory); #if phpwebserver simpleServer.runOnce = true; #end server = simpleServer; default: throw "Unhandled server type"; } /* // Server event handler if( args.serverEvents) { var events = new TestServerEventHandler(); server.setEventHandler(serverEvents); handler.server = serverEngine; } */ // Run it server.Serve(); trace("done."); } catch (x : TException) { trace('$x ${x.errorID} ${x.errorMsg}'); } catch (x : Dynamic) { trace('$x'); } } } thrift-0.19.0/test/haxe/src/TestServerEventHandler.hx0000644000000000000000000000311714303740367022552 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package; import org.apache.thrift.*; import org.apache.thrift.protocol.*; import org.apache.thrift.transport.*; import org.apache.thrift.server.*; import org.apache.thrift.meta_data.*; import thrift.test.*; // generated code class TestServerEventHandler : TServerEventHandler { public int callCount = 0; public void preServe() { callCount++; } public Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) { callCount++; return null; } public void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) { callCount++; } public void processContext(Object serverContext, Thrift.Transport.TTransport transport) { callCount++; } } thrift-0.19.0/test/haxe/cpp.hxml0000644000000000000000000000217514370300523016461 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #CPP target -cpp bin #To produce 64 bit binaries the file should define the HXCPP_M64 compile variable: #-D HXCPP_M64 # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/test/haxe/javascript.hxml0000644000000000000000000000252314370300523020042 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #JavaScript target -js bin/ThriftTest.js #You can use -D source-map-content (requires Haxe 3.1+) to have the .hx #files directly embedded into the map file, this way you only have to #upload it, and it will be always in sync with the compiled .js even if #you modify your .hx files. -D source-map-content # libs -lib uuid #Generate source map and add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/test/haxe/make_all.sh0000777000000000000000000000224614062750226017123 0ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # invoke Thrift comnpiler ../../compiler/cpp/thrift -r -gen haxe ../ThriftTest.thrift # output folder if [ ! -d bin ]; then mkdir bin fi # invoke Haxe compiler for target in *.hxml; do echo -------------------------- echo Building ${target} ... echo -------------------------- if [ ! -d bin/${target} ]; then mkdir bin/${target} fi haxe --cwd . ${target} done #eof thrift-0.19.0/test/haxe/project.hide0000644000000000000000000000364714303740367017325 0ustar00rootroot00000000000000{ "type" : 0 ,"target" : 4 ,"name" : "Apache Thrift cross-platform test client/server" ,"main" : null ,"projectPackage" : "" ,"company" : "Apache Software Foundation (ASF)" ,"license" : "Apache License, Version 2.0" ,"url" : "http://www.apache.org/licenses/LICENSE-2.0" ,"targetData" : [ { "pathToHxml" : "flash.hxml" ,"runActionType" : 1 ,"runActionText" : "bin/Tutorial.swf" } ,{ "pathToHxml" : "javascript.hxml" ,"runActionType" : 1 ,"runActionText" : "bin\\index.html" } ,{ "pathToHxml" : "neko.hxml" ,"runActionType" : 2 ,"runActionText" : "neko bin/Tutorial.n" } ,{ "pathToHxml" : "php.hxml" } ,{ "pathToHxml" : "cpp.hxml" ,"runActionType" : 2 ,"runActionText" : "bin/Main-debug.exe client --protocol json" } ,{ "pathToHxml" : "java.hxml" } ,{ "pathToHxml" : "csharp.hxml" } ,{ "pathToHxml" : "python.hxml" ,"runActionType" : 2 ,"runActionText" : "python bin/Tutorial.py" } ] ,"files" : [ { "path" : "src\\TestClient.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 188 } ,{ "path" : "src\\TestServer.hx" ,"useTabs" : true ,"indentSize" : 4 ,"foldedRegions" : [ ] ,"activeLine" : 88 } ] ,"activeFile" : "src\\TestClient.hx" ,"openFLTarget" : null ,"openFLBuildMode" : "Debug" ,"runActionType" : null ,"runActionText" : null ,"buildActionCommand" : null ,"hiddenItems" : [ ] ,"showHiddenItems" : false }thrift-0.19.0/test/haxe/php-web-server.hxml0000644000000000000000000000214114370300523020536 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #PHP target -php bin/php-web-server -D php-front=Main-debug.php #defines -D phpwebserver # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce full thrift-0.19.0/test/haxe/TestClientServer.hxproj0000644000000000000000000000406514370300523021506 0ustar00rootroot00000000000000 thrift -r -gen haxe ../ThriftTest.thrift thrift-0.19.0/test/haxe/neko.hxml0000644000000000000000000000205214370300523016625 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #neko target -neko bin/ThriftTest.n # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/test/haxe/python.hxml0000644000000000000000000000205714370300523017217 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #integrate files to classpath -cp src -cp gen-haxe -cp ../../lib/haxe/src #this class wil be used as entry point for your app. -main Main #Python target -python bin/ThriftTest.py # libs -lib uuid #Add debug information -debug #dead code elimination : remove unused code -dce fullthrift-0.19.0/test/haxe/Makefile.in0000644000000000000000000004527714472652520017076 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/haxe ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ THRIFTCMD = $(THRIFT) --gen haxe -r THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift BIN_CPP = bin/Main-debug BIN_PHP = bin/php/Main-debug.php BIN_PHP_WEB = bin/php-web-server/Main-debug.php EXTRA_DIST = \ src \ cpp.hxml \ csharp.hxml \ flash.hxml \ java.hxml \ javascript.hxml \ neko.hxml \ php.hxml \ python.hxml \ router.php \ project.hide \ php-web-server.hxml \ TestClientServer.hxproj \ make_all.bat \ make_all.sh all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/haxe/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/haxe/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-haxe/thrift/test/ThriftTest.hx: $(THRIFTTEST) $(THRIFTCMD) $(THRIFTTEST) all-local: $(BIN_CPP) $(BIN_PHP) $(BIN_PHP_WEB) $(BIN_CPP): \ src/*.hx \ ../../lib/haxe/src/org/apache/thrift/**/*.hx \ gen-haxe/thrift/test/ThriftTest.hx $(HAXE) --cwd . cpp.hxml # $(HAXE) --cwd . csharp # $(HAXE) --cwd . flash # $(HAXE) --cwd . java # $(HAXE) --cwd . javascript # $(HAXE) --cwd . neko # $(HAXE) --cwd . python $(BIN_PHP): \ src/*.hx \ ../../lib/haxe/src/org/apache/thrift/**/*.hx \ gen-haxe/thrift/test/ThriftTest.hx $(HAXE) --cwd . php.hxml $(BIN_PHP_WEB): \ src/*.hx \ ../../lib/haxe/src/org/apache/thrift/**/*.hx \ gen-haxe/thrift/test/ThriftTest.hx $(HAXE) --cwd . php-web-server.hxml clean-local: $(RM) -r gen-haxe bin .NOTPARALLEL: check: check_cpp \ check_php \ check_php_web check_cpp: $(BIN_CPP) timeout 20 $(BIN_CPP) server & sleep 1 $(BIN_CPP) client sleep 10 check_php: $(BIN_PHP) timeout 20 php -f $(BIN_PHP) server & sleep 1 php -f $(BIN_PHP) client sleep 10 check_php_web: $(BIN_PHP_WEB) $(BIN_CPP) timeout 20 php -S 127.0.0.1:9090 router.php & sleep 1 $(BIN_CPP) client --transport http sleep 10 # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/v0.16/0000755000000000000000000000000014472652672014647 5ustar00rootroot00000000000000thrift-0.19.0/test/v0.16/DebugProtoTest.thrift0000644000000000000000000002413114370300523020762 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace c_glib TTest namespace cpp thrift.test.debug namespace java thrift.test namespace rb thrift.test struct Doubles { 1: double nan, 2: double inf, 3: double neginf, 4: double repeating, 5: double big, 6: double tiny, 7: double zero, 8: double negzero, } struct OneOfEach { 1: bool im_true, 2: bool im_false, 3: i8 a_bite = 0x7f, 4: i16 integer16 = 0x7fff, 5: i32 integer32, 6: i64 integer64 = 10000000000, 7: double double_precision, 8: string some_characters, 9: string zomg_unicode, 10: bool what_who, 11: binary base64, 12: list byte_list = [1, 2, 3], 13: list i16_list = [1,2,3], 14: list i64_list = [1,2,3] } struct Bonk { 1: i32 type, 2: string message, } struct Nesting { 1: Bonk my_bonk, 2: OneOfEach my_ooe, } struct HolyMoley { 1: list big, 2: set (python.immutable = "")> contain, 3: map> bonks, } struct Backwards { 2: i32 first_tag2, 1: i32 second_tag1, } struct Empty { } ( python.immutable = "", ) struct Wrapper { 1: Empty foo } ( python.immutable = "", ) struct RandomStuff { 1: i32 a, 2: i32 b, 3: i32 c, 4: i32 d, 5: list myintlist, 6: map maps, 7: i64 bigint, 8: double triple, } struct Base64 { 1: i32 a, 2: binary b1, 3: binary b2, 4: binary b3, 5: binary b4, 6: binary b5, 7: binary b6, } struct CompactProtoTestStruct { // primitive fields 1: i8 a_byte; 2: i16 a_i16; 3: i32 a_i32; 4: i64 a_i64; 5: double a_double; 6: string a_string; 7: binary a_binary; 8: bool true_field; 9: bool false_field; 10: Empty empty_struct_field; // primitives in lists 11: list byte_list; 12: list i16_list; 13: list i32_list; 14: list i64_list; 15: list double_list; 16: list string_list; 17: list binary_list; 18: list boolean_list; 19: list struct_list; // primitives in sets 20: set byte_set; 21: set i16_set; 22: set i32_set; 23: set i64_set; 24: set double_set; 25: set string_set; 26: set binary_set; 27: set boolean_set; 28: set struct_set; // maps // primitives as keys 29: map byte_byte_map; 30: map i16_byte_map; 31: map i32_byte_map; 32: map i64_byte_map; 33: map double_byte_map; 34: map string_byte_map; 35: map binary_byte_map; 36: map boolean_byte_map; // primitives as values 37: map byte_i16_map; 38: map byte_i32_map; 39: map byte_i64_map; 40: map byte_double_map; 41: map byte_string_map; 42: map byte_binary_map; 43: map byte_boolean_map; // collections as keys 44: map (python.immutable = ""), i8> list_byte_map; 45: map (python.immutable = ""), i8> set_byte_map; 46: map (python.immutable = ""), i8> map_byte_map; // collections as values 47: map> byte_map_map; 48: map> byte_set_map; 49: map> byte_list_map; // large field IDs 500 : i64 field500; 5000 : i64 field5000; 20000 : i64 field20000; } // To be used to test the serialization of an empty map struct SingleMapTestStruct { 1: required map i32_map; } const CompactProtoTestStruct COMPACT_TEST = { 'a_byte' : 127, 'a_i16' : 32000, 'a_i32' : 1000000000, 'a_i64' : 0xffffffffff, 'a_double' : 5.6789, 'a_string' : "my string", //'a_binary,' 'true_field' : 1, 'false_field' : 0, 'empty_struct_field' : {}, 'byte_list' : [-127, -1, 0, 1, 127], 'i16_list' : [-1, 0, 1, 0x7fff], 'i32_list' : [-1, 0, 0xff, 0xffff, 0xffffff, 0x7fffffff], 'i64_list' : [-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], 'double_list' : [0.1, 0.2, 0.3], 'string_list' : ["first", "second", "third"], //'binary_list,' 'boolean_list' : [1, 1, 1, 0, 0, 0], 'struct_list' : [{}, {}], 'byte_set' : [-127, -1, 0, 1, 127], 'i16_set' : [-1, 0, 1, 0x7fff], 'i32_set' : [1, 2, 3], 'i64_set' : [-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], 'double_set' : [0.1, 0.2, 0.3], 'string_set' : ["first", "second", "third"], //'binary_set,' 'boolean_set' : [1, 0], 'struct_set' : [{}], 'byte_byte_map' : {1 : 2}, 'i16_byte_map' : {1 : 1, -1 : 1, 0x7fff : 1}, 'i32_byte_map' : {1 : 1, -1 : 1, 0x7fffffff : 1}, 'i64_byte_map' : {0 : 1, 1 : 1, -1 : 1, 0x7fffffffffffffff : 1}, 'double_byte_map' : {-1.1 : 1, 1.1 : 1}, 'string_byte_map' : {"first" : 1, "second" : 2, "third" : 3, "" : 0}, //'binary_byte_map,' 'boolean_byte_map' : {1 : 1, 0 : 0}, 'byte_i16_map' : {1 : 1, 2 : -1, 3 : 0x7fff}, 'byte_i32_map' : {1 : 1, 2 : -1, 3 : 0x7fffffff}, 'byte_i64_map' : {1 : 1, 2 : -1, 3 : 0x7fffffffffffffff}, 'byte_double_map' : {1 : 0.1, 2 : -0.1, 3 : 1000000.1}, 'byte_string_map' : {1 : "", 2 : "blah", 3 : "loooooooooooooong string"}, //'byte_binary_map,' 'byte_boolean_map' : {1 : 1, 2 : 0}, 'list_byte_map' : {[1, 2, 3] : 1, [0, 1] : 2, [] : 0}, 'set_byte_map' : {[1, 2, 3] : 1, [0, 1] : 2, [] : 0}, 'map_byte_map' : {{1 : 1} : 1, {2 : 2} : 2, {} : 0}, 'byte_map_map' : {0 : {}, 1 : {1 : 1}, 2 : {1 : 1, 2 : 2}}, 'byte_set_map' : {0 : [], 1 : [1], 2 : [1, 2]}, 'byte_list_map' : {0 : [], 1 : [1], 2 : [1, 2]}, 'field500' : 500, 'field5000' : 5000, 'field20000' : 20000, } const i32 MYCONST = 2 exception ExceptionWithAMap { 1: string blah; 2: map map_field; } exception MutableException { 1: string msg; } (python.immutable = "false") exception ExceptionWithoutFields {} service ServiceForExceptionWithAMap { void methodThatThrowsAnException() throws (1: ExceptionWithAMap xwamap); } service Srv { i32 Janky(1: i32 arg); // return type only methods void voidMethod(); i32 primitiveMethod(); CompactProtoTestStruct structMethod(); void methodWithDefaultArgs(1: i32 something = MYCONST); oneway void onewayMethod(); bool declaredExceptionMethod(1: bool shouldThrow) throws (1: ExceptionWithAMap xwamap); } service Inherited extends Srv { i32 identity(1: i32 arg) } service EmptyService {} // The only purpose of this thing is to increase the size of the generated code // so that ZlibTest has more highly compressible data to play with. struct BlowUp { 1: map(python.immutable = ""),set (python.immutable = "")>> b1; 2: map(python.immutable = ""),set (python.immutable = "")>> b2; 3: map(python.immutable = ""),set (python.immutable = "")>> b3; 4: map(python.immutable = ""),set (python.immutable = "")>> b4; } struct ReverseOrderStruct { 4: string first; 3: i16 second; 2: i32 third; 1: i64 fourth; } service ReverseOrderService { void myMethod(4: string first, 3: i16 second, 2: i32 third, 1: i64 fourth); } enum SomeEnum { ONE = 1 TWO = 2 } /** This is a docstring on a constant! */ const SomeEnum MY_SOME_ENUM = SomeEnum.ONE const SomeEnum MY_SOME_ENUM_1 = 1 /*const SomeEnum MY_SOME_ENUM_2 = 7*/ const map MY_ENUM_MAP = { SomeEnum.ONE : SomeEnum.TWO } struct StructWithSomeEnum { 1: SomeEnum blah; } const map EXTRA_CRAZY_MAP = { SomeEnum.ONE : {"blah" : SomeEnum.TWO} } union TestUnion { /** * A doc string */ 1: string string_field; 2: i32 i32_field; 3: OneOfEach struct_field; 4: list struct_list; 5: i32 other_i32_field; 6: SomeEnum enum_field; 7: set i32_set; 8: map i32_map; } union TestUnionMinusStringField { 2: i32 i32_field; 3: OneOfEach struct_field; 4: list struct_list; 5: i32 other_i32_field; 6: SomeEnum enum_field; 7: set i32_set; 8: map i32_map; } union ComparableUnion { 1: string string_field; 2: binary binary_field; } struct StructWithAUnion { 1: TestUnion test_union; } struct PrimitiveThenStruct { 1: i32 blah; 2: i32 blah2; 3: Backwards bw; } typedef map SomeMap struct StructWithASomemap { 1: required SomeMap somemap_field; } struct BigFieldIdStruct { 1: string field1; 45: string field2; } struct BreaksRubyCompactProtocol { 1: string field1; 2: BigFieldIdStruct field2; 3: i32 field3; } struct TupleProtocolTestStruct { optional i32 field1; optional i32 field2; optional i32 field3; optional i32 field4; optional i32 field5; optional i32 field6; optional i32 field7; optional i32 field8; optional i32 field9; optional i32 field10; optional i32 field11; optional i32 field12; } struct ListDoublePerf { 1: list field; } thrift-0.19.0/test/v0.16/ThriftTest.thrift0000644000000000000000000002627114370300523020157 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace c_glib TTest namespace cpp thrift.test namespace delphi Thrift.Test namespace go thrifttest namespace java thrift.test namespace js ThriftTest namespace lua ThriftTest namespace netstd ThriftTest namespace perl ThriftTest namespace php ThriftTest namespace py ThriftTest namespace py.twisted ThriftTest namespace rb Thrift.Test namespace st ThriftTest namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest') // Presence of namespaces and sub-namespaces for which there is // no generator should compile with warnings only namespace noexist ThriftTest namespace cpp.noexist ThriftTest namespace * thrift.test /** * Docstring! */ enum Numberz { ONE = 1, TWO, THREE, FIVE = 5, SIX, EIGHT = 8 } const Numberz myNumberz = Numberz.ONE; // the following is expected to fail: // const Numberz urNumberz = ONE; typedef i64 UserId struct Bonk { 1: string message, 2: i32 type } typedef map MapType struct Bools { 1: bool im_true, 2: bool im_false, } struct Xtruct { 1: string string_thing, 4: i8 byte_thing, 9: i32 i32_thing, 11: i64 i64_thing } struct Xtruct2 { 1: i8 byte_thing, // used to be byte, hence the name 2: Xtruct struct_thing, 3: i32 i32_thing } struct Xtruct3 { 1: string string_thing, 4: i32 changed, 9: i32 i32_thing, 11: i64 i64_thing } struct Insanity { 1: map userMap, 2: list xtructs } (python.immutable= "") struct CrazyNesting { 1: string string_field, 2: optional set set_field, // Do not insert line break as test/go/Makefile.am is removing this line with pattern match 3: required list (python.immutable = ""), map(python.immutable = "")> (python.immutable = "")>>>> list_field, 4: binary binary_field } union SomeUnion { 1: map map_thing, 2: string string_thing, 3: i32 i32_thing, 4: Xtruct3 xtruct_thing, 5: Insanity insanity_thing } exception Xception { 1: i32 errorCode, 2: string message } exception Xception2 { 1: i32 errorCode, 2: Xtruct struct_thing } struct EmptyStruct {} struct OneField { 1: EmptyStruct field } service ThriftTest { /** * Prints "testVoid()" and returns nothing. */ void testVoid(), /** * Prints 'testString("%s")' with thing as '%s' * @param string thing - the string to print * @return string - returns the string 'thing' */ string testString(1: string thing), /** * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false' * @param bool thing - the bool data to print * @return bool - returns the bool 'thing' */ bool testBool(1: bool thing), /** * Prints 'testByte("%d")' with thing as '%d' * The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility. * @param byte thing - the i8/byte to print * @return i8 - returns the i8/byte 'thing' */ i8 testByte(1: i8 thing), /** * Prints 'testI32("%d")' with thing as '%d' * @param i32 thing - the i32 to print * @return i32 - returns the i32 'thing' */ i32 testI32(1: i32 thing), /** * Prints 'testI64("%d")' with thing as '%d' * @param i64 thing - the i64 to print * @return i64 - returns the i64 'thing' */ i64 testI64(1: i64 thing), /** * Prints 'testDouble("%f")' with thing as '%f' * @param double thing - the double to print * @return double - returns the double 'thing' */ double testDouble(1: double thing), /** * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data * @param binary thing - the binary data to print * @return binary - returns the binary 'thing' */ binary testBinary(1: binary thing), /** * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values * @param Xtruct thing - the Xtruct to print * @return Xtruct - returns the Xtruct 'thing' */ Xtruct testStruct(1: Xtruct thing), /** * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct * @param Xtruct2 thing - the Xtruct2 to print * @return Xtruct2 - returns the Xtruct2 'thing' */ Xtruct2 testNest(1: Xtruct2 thing), /** * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' */ map testMap(1: map thing), /** * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' */ map testStringMap(1: map thing), /** * Prints 'testSet("{%s}")' where thing has been formatted into a string of values * separated by commas and new lines * @param set thing - the set to print * @return set - returns the set 'thing' */ set testSet(1: set thing), /** * Prints 'testList("{%s}")' where thing has been formatted into a string of values * separated by commas and new lines * @param list thing - the list to print * @return list - returns the list 'thing' */ list testList(1: list thing), /** * Prints 'testEnum("%d")' where thing has been formatted into its numeric value * @param Numberz thing - the Numberz to print * @return Numberz - returns the Numberz 'thing' */ Numberz testEnum(1: Numberz thing), /** * Prints 'testTypedef("%d")' with thing as '%d' * @param UserId thing - the UserId to print * @return UserId - returns the UserId 'thing' */ UserId testTypedef(1: UserId thing), /** * Prints 'testMapMap("%d")' with hello as '%d' * @param i32 hello - the i32 to print * @return map> - returns a dictionary with these values: * {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } */ map> testMapMap(1: i32 hello), /** * So you think you've got this all worked out, eh? * * Creates a map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, * 2 => { 6 => , }, * } * @return map> - a map with the above values */ map> testInsanity(1: Insanity argument), /** * Prints 'testMulti()' * @param i8 arg0 - * @param i32 arg1 - * @param i64 arg2 - * @param map arg3 - * @param Numberz arg4 - * @param UserId arg5 - * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 * and i64_thing = arg2 */ Xtruct testMulti(1: i8 arg0, 2: i32 arg1, 3: i64 arg2, 4: map arg3, 5: Numberz arg4, 6: UserId arg5), /** * Print 'testException(%s)' with arg as '%s' * @param string arg - a string indication what type of exception to throw * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg * else if arg == "TException" throw TException * else do not throw anything */ void testException(1: string arg) throws(1: Xception err1), /** * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' * @param string arg - a string indicating what type of exception to throw * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2" * else do not throw anything * @return Xtruct - an Xtruct with string_thing = arg1 */ Xtruct testMultiException(1: string arg0, 2: string arg1) throws(1: Xception err1, 2: Xception2 err2) /** * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' * sleep 'secondsToSleep' * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' * @param i32 secondsToSleep - the number of seconds to sleep */ oneway void testOneway(1:i32 secondsToSleep) } service SecondService { /** * Prints 'testString("%s")' with thing as '%s' * @param string thing - the string to print * @return string - returns the string 'thing' */ string secondtestString(1: string thing) } struct VersioningTestV1 { 1: i32 begin_in_both, 3: string old_string, 12: i32 end_in_both } struct VersioningTestV2 { 1: i32 begin_in_both, 2: i32 newint, 3: i8 newbyte, 4: i16 newshort, 5: i64 newlong, 6: double newdouble 7: Bonk newstruct, 8: list newlist, 9: set newset, 10: map newmap, 11: string newstring, 12: i32 end_in_both } struct ListTypeVersioningV1 { 1: list myints; 2: string hello; } struct ListTypeVersioningV2 { 1: list strings; 2: string hello; } struct GuessProtocolStruct { 7: map map_field, } struct LargeDeltas { 1: Bools b1, 10: Bools b10, 100: Bools b100, 500: bool check_true, 1000: Bools b1000, 1500: bool check_false, 2000: VersioningTestV2 vertwo2000, 2500: set a_set2500, 3000: VersioningTestV2 vertwo3000, 4000: list big_numbers } struct NestedListsI32x2 { 1: list> integerlist } struct NestedListsI32x3 { 1: list>> integerlist } struct NestedMixedx2 { 1: list> int_set_list 2: map> map_int_strset 3: list>> map_int_strset_list } struct ListBonks { 1: list bonk } struct NestedListsBonk { 1: list>> bonk } struct BoolTest { 1: optional bool b = true; 2: optional string s = "true"; } struct StructA { 1: required string s; } struct StructB { 1: optional StructA aa; 2: required StructA ab; } struct OptionalSetDefaultTest { 1: optional set with_default = [ "test" ] } struct OptionalBinary { 1: optional set bin_set = {} 2: optional map bin_map = {} } thrift-0.19.0/test/audit/0000777000000000000000000000000014303740367015177 5ustar00rootroot00000000000000thrift-0.19.0/test/audit/break23.thrift0000644000000000000000000001232414303740367017650 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break23 - required struct field added to struct4 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2, 3: required i64 struct4_member3 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break22.thrift0000644000000000000000000001223314303740367017646 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break22 - in-between enum value removed from enum1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break14.thrift0000644000000000000000000001227414303740367017654 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // derived1_function6 return type changed from string to double namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), double derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break10.thrift0000644000000000000000000001221514303740367017643 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break10 - Struct field removed from struct2 id =1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 2: list struct2_member2, 3: list struct2_member3 = [23, 32], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break17.thrift0000644000000000000000000001234214303740367017653 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break17 - derived2_function6 return type changed from map to map namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break34.thrift0000644000000000000000000001241014303740367017646 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break34 - Field added to struct with Field ID being in between two existing field IDs namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 6: map struct3_member6, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break13.thrift0000644000000000000000000001227614303740367017655 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // derived1_function6 return type changed from struct1 to struct2 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct2 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break19.thrift0000644000000000000000000001225614303740367017661 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break19 - oneway added to base_function1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), oneway void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break5.thrift0000644000000000000000000001230214303740367017564 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // member field type changed in test_struct1(bool to list) namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: list struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break6.thrift0000644000000000000000000001227314303740367017574 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Field type changed in test_struct2 (list to list) namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break24.thrift0000644000000000000000000001223614303740367017653 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break24 - removed inheritance from derived1. namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break27.thrift0000644000000000000000000001231114303740367017650 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // break27 - argument changed base_function2 list to list id =8 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/thrift_audit_test.pl0000644000000000000000000002133714303740367021263 0ustar00rootroot00000000000000#!/usr/bin/perl -w # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. #break1 - Thrift method removed from service base #break2 - Struct field changed in test_struct1(i16 to i32) #break3 - Struct field changed in test_struct1(enum1 to enum2) #break4 - Field type changed in test_struct1(bool to string) #break5- member field type changed in test_struct1(bool to list) #break6- Field type changed in test_struct2 (list to list) #break7 - requiredness removed in struct6 #break8 - requiredness addedd in struct5 #break9 - Struct field removed from struct1 #break10 - Struct field removed from struct2 id = 1 #break11 - Struct field removed from struct3 last id #break12 - derived1_function1 return type changed from enum1 to enum2 #break13 - derived1_function6 return type changed from struct1 to struct2 #break14 - derived1_function4 return type changed from string to double #break15 - derived2_function1 return type changed from list to list #break16 - derived2_function5 return type changed from map to map #break17 - derived2_function6 return type changed from map to map #break18- oneway removed from base_oneway #break19 - oneway added to base_function1 #break20 - first enum value removed from enum1 #break21- last enum value removed from enum2 #break22 - in-between enum value removed from enum1 #break23 - required struct field added to struct4 #break24 - removed inheritance of derived1. #break25 - changed inheritance of derived2. #break26 - Field type changed in base_function1 argument id=3 #break27 - argument changed base_function2 list to list id =8 #break28- derived1_function5 arguement type changed map to list #break29 - base_function2 arguemnt type changed list to string #break30- derived1_function6 argument changed struct1 to map #break31 - Exception removed to base_function2 #break32- Exception1 field type changed for id =1 #break33 - derived1_function1 exception type changed. #break34 - Field added to struct with Field ID being in between two existing field IDs #warning.thrift #Changing defaults #Id=1 struct5 #id=2 struct5 #id=4 struct2(list) #id=3 struct2(list default values removed) #id 4 struct1 change in double value #id 5 struct1 (default string value removed) #id=1 struct3 (change in map values) #id2 struct3 (change in map keys) #change in inheritance for derived1 and derived2 #change in struct field names #id9 struct1 #id2 struct2 use strict; use warnings; use Getopt::Std; # globals my $gArguments = ""; # arguments that will be passed to AuditTool my $gAuditToolPath = ""; my $gPreviousThriftPath; # previous thrift path my $gCurrentThriftPath; # current thrift path my $gThriftFileFolder; my $gBreakingFilesCount =34; my $gVerbose = 0; #functions sub auditBreakingChanges; sub auditNonBreakingChanges; main(); sub main { parseOptions(); auditBreakingChanges(); auditNonBreakingChanges(); } sub parseOptions { my %options = (); if ( getopts ('vf:o:t:',\%options) ) { # current (new) thrift folder if ($options{'f'}) { $gThriftFileFolder = $options{'f'}; $gPreviousThriftPath = $gThriftFileFolder."/test.thrift"; } else { die "Missing Folder containing thrift files\n"; } if($options{'t'}) { $gAuditToolPath = $options{'t'}; } else { die "Audit Tool Path required \n"; } if ($options{'v'}) { $gVerbose = 1; } } } sub auditBreakingChanges { my $breakingFileBaseName = $gThriftFileFolder."/break"; my $newThriftFile; for(my $i=1; $i <= $gBreakingFilesCount; $i++) { $newThriftFile = $breakingFileBaseName."$i.thrift"; my $arguments = $gPreviousThriftPath." ".$newThriftFile; my ($exitCode, $output) = callThriftAuditTool($arguments); print $output if $gVerbose eq 1; if($exitCode == 1) { # thrift_audit returns 1 when it is not able to find files or other non-audit failures print "exiting with exit code =1 i = ".$i."\n"; print $output; exit $exitCode; } if($exitCode != 2) { # thrift-audit return 2 for audit failures. So for Breaking changes we should get 2 as return value. print $output; die "\nTEST FAILURE: Breaking Change not detected for thrift file $newThriftFile, code=$exitCode \n"; } if(index($output,getMessageSubString("break$i")) == -1) { #Audit tool detected failure, but not the expected one. The change in breaking thrift file does not match getMessageSubString() print $output; die "\nTest FAILURE: Audit tool detected failure, but not the expected one!\n"; } else { #Thrift audit tool has detected audit failure and has returned exited to status code 2 print "Test Pass: Audit Failure detected for thrift file break$i.thrift \n"; } } } sub auditNonBreakingChanges { my $breakingFileBaseName = $gThriftFileFolder."/warning"; my $newThriftFile; $newThriftFile = $breakingFileBaseName.".thrift"; my $arguments = $gPreviousThriftPath." ".$newThriftFile; my ($exitCode, $output) = callThriftAuditTool($arguments); print $output if $gVerbose eq 1; if($exitCode == 1) { # thrift_audit returns 1 when it is not able to find files or other non-audit failures print "exiting with exit code = 1 for file warning.thrift\n"; exit $exitCode; } elsif($exitCode != 0) { # thrift-audit return 0 if there are no audit failures. die "\nTEST FAILURE: Non Breaking changes returned failure for thrift file $newThriftFile \n"; } else { #Thrift audit tool has exited with status 0. print "Test Pass: Audit tool exits with success for warnings \n"; } } # ----------------------------------------------------------------------------------------------------- # call thriftAuditTool script sub callThriftAuditTool ( $ ) { my $args = shift; my $command = "$gAuditToolPath --audit $args"; my $output = `$command 2>&1`; my $exitCode = $? >> 8; return ($exitCode,$output); } sub getMessageSubString( $ ) { my $fileName = shift; my %lookupTable = ( "break1" => "base_function3", "break2" => "test_struct1", "break3" => "test_struct1", "break4" => "test_struct1", "break5" => "test_struct1", "break6" => "test_struct2", "break7" => "test_struct6", "break8" => "test_struct5", "break9" => "test_struct1", "break10" => "test_struct2", "break11" => "test_struct3", "break12" => "derived1_function1", "break13" => "derived1_function6", "break14" => "derived1_function4", "break15" => "derived2_function1", "break16" => "derived2_function5", "break17" => "derived2_function6", "break18" => "base_oneway", "break19" => "base_function1", "break20" => "test_enum1", "break21" => "test_enum2", "break22" => "test_enum1", "break23" => "test_struct4", "break24" => "derived1", "break25" => "derived2", "break26" => "base_function1", "break27" => "base_function2_args", "break28" => "derived1_function5_args", "break29" => "base_function2_args", "break30" => "derived1_function6", "break31" => "base_function2_exception", "break32" => "test_exception1", "break33" => "derived1_function1_exception", "break34" => "test_struct3", ); if (not exists $lookupTable{ $fileName }) { print "in the null case\n"; return "NULL"; } my $retval = $lookupTable{ $fileName }; print "$fileName => $retval\n"; return $lookupTable{ $fileName }; } thrift-0.19.0/test/audit/README.md0000644000000000000000000000203714303740367016454 0ustar00rootroot00000000000000Typical usage ============= ``` thrift.exe --audit ``` Example run =========== ``` > thrift.exe --audit test.thrift break1.thrift [Thrift Audit Failure:break1.thrift] New Thrift File has missing function base_function3 [Thrift Audit Warning:break1.thrift] Constant const3 has different value ``` Problems that the audit tool can catch ====================================== Errors * Removing an enum value * Changing the type of a struct field * Changing the required-ness of a struct field * Removing a struct field * Adding a required struct field * Adding a struct field 'in the middle'. This usually indicates an old ID has been recycled * Struct removed * Oneway-ness change * Return type change * Missing function * Missing service * Change in service inheritance Warnings * Removing a language namespace declaration * Changing a namespace * Changing an enum value's name * Removing an enum class * Default value changed * Struct field name change * Removed constant * Type of constant changed * Value of constant changed thrift-0.19.0/test/audit/break2.thrift0000644000000000000000000001224114303740367017563 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //Struct field changed in test_struct1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i32 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break11.thrift0000644000000000000000000001220514303740367017643 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break11 - Struct field removed from struct3 id =7 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break21.thrift0000644000000000000000000001222514303740367017646 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break21- last enum value removed from enum2 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break25.thrift0000644000000000000000000001224214303740367017651 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //Changed inheritance of derived2 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends derived1 { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break1.thrift0000644000000000000000000001221014303740367017556 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //Thrift Method removed from service base. namespace cpp test //constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3= [23, 32], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break9.thrift0000644000000000000000000001221414303740367017572 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break9 - Struct field removed from struct1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break16.thrift0000644000000000000000000001236114303740367017653 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // break 16 - derived2_function5 return type changed from map to map namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break4.thrift0000644000000000000000000001226014303740367017566 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //Field type changed in test_struct1(bool to string) namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: string struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 =[23, 32], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break33.thrift0000644000000000000000000001226314303740367017653 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break33 - derived1_function1 exception type changed. namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception1 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break15.thrift0000644000000000000000000001231314303740367017647 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // break15 - derived2_function1 return type changed from list to list namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break3.thrift0000644000000000000000000001227314303740367017571 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break3 - Struct field changed in test_struct1(enum1 to enum2) namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum2 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break26.thrift0000644000000000000000000001227614303740367017661 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break26 - Field type changed in base_function1 argument id=3 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: double function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break18.thrift0000644000000000000000000001224014303740367017651 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break18- oneway removed from base_oneway namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break8.thrift0000644000000000000000000001225714303740367017600 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break8 - requiredness addedd in struct5 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: required string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break20.thrift0000644000000000000000000001223014303740367017641 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // break 20 - first enum value removed from enum1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break29.thrift0000644000000000000000000001227614303740367017664 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break29 - base_function2 arguemnt type changed list to string namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: string function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break31.thrift0000644000000000000000000001221714303740367017650 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break31 - Exception removed to base_function2 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break28.thrift0000644000000000000000000001230714303740367017656 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break28- derived1_function5 arguement type changed map to list namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: list function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break32.thrift0000644000000000000000000001225714303740367017655 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break32- Exception1 field type changed for id =1 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i64 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break30.thrift0000644000000000000000000001233514303740367017650 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // break30- derived1_function6 argument changed struct1 to map namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), map derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break7.thrift0000644000000000000000000001223514303740367017573 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //break7 - requiredness removed in struct6 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/warning.thrift0000644000000000000000000001214614303740367020066 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.2; const map const3 = {"hello":"class", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.4, 5: string struct1_member5, 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 changed19 } struct test_struct2 { 1: list struct2_member1, 2: list changed22, 3: list struct2_member3, 4: list struct2_member4 =[1.0, 2.1], 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:10, 2:20}, 2: map struct3_member2 = {1:1.1, 2:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1 = 1.1, 2: string struct5_member2 = "Thrift Audit Tess" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base{ test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/test.thrift0000644000000000000000000001217314303740367017400 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum1 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/audit/break12.thrift0000644000000000000000000001227214303740367017650 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // derived1_function1 return type changed from enum1 to enum2 namespace cpp test //Constants const i32 const1 = 123; const double const2 = 23.3; const map const3 = {"hello":"world", "thrift":"audit"}; //Exception exception test_exception1 { 1: i32 code; 2: string json; } exception test_exception2 { 1: i32 code; 2: string json; } //Enums enum test_enum1 { enum1_value0 = 0, enum1_value1 = 1, enum1_value2 = 2, enum1_value5 = 5, enum1_value7 = 7, enum1_value8 = 8 } enum test_enum2 { enum2_value0 = 0, enum2_value1 = 1, enum2_value2 = 2, enum2_value3 = 3 } enum test_enum3 { enum3_value1 = 0, enum3_value2 = 1 } struct test_struct1 { 1: i16 struct1_member1, 2: i32 struct1_member2, 3: i64 struct1_member3, 4: double struct1_member4 = 2.5, 5: string struct1_member5 = "Audit test", 6: bool struct1_member6, 7: byte struct1_member7, 8: binary struct1_member8, 9: test_enum1 struct1_member9 } struct test_struct2 { 1: list struct2_member1, 2: list struct2_member2, 3: list struct2_member3 = [23, 32 ], 4: list struct2_member4, 5: list struct2_member5, 6: list struct2_member6, 7: list struct2_member7, 8: list struct2_member8, 9: list struct2_member9 } struct test_struct3 { 1: map struct3_member1 = {1:2, 3:4}, 2: map struct3_member2 = {10:1.1, 20:2.1}, 3: map struct3_member3, 4: map struct3_member4, 5: map struct3_member5, 7: map struct3_member7 } struct test_struct4 { 1: i32 struct4_member1, 2: optional i32 struct4_member2 } struct test_struct5{ 1: double struct5_member1, 2: string struct5_member2 = "Thrift Audit Test" } struct test_struct6 { 1: i32 struct6_member1, 2: required i32 struct6_member2 } service base { oneway void base_oneway( 1: i32 arg1), void base_function1( 1: i16 function1_arg1, 2: i32 function1_arg2, 3: i64 function1_arg3, 4: double function1_arg4, 5: string function1_arg5, 6: bool function1_arg6, 7: test_enum1 function1_arg7, 8: test_struct1 function1_arg8), void base_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5, 6: list function2_arg6, 7: list function2_arg7, 8: list function2_arg8, 9: list function2_arg9) throws (1:test_exception2 e), void base_function3(), } service derived1 extends base { test_enum2 derived1_function1( 1: i64 function1_arg1, 2: double function1_arg2, 3: test_enum1 function1_arg3) throws (1:test_exception2 e), i64 derived1_function2( 1: list function2_arg1, 2: list function2_arg2, 3: list function2_arg3, 4: list function2_arg4, 5: list function2_arg5) throws (1:test_exception2 e), double derived1_function3( 1: string function3_arg1, 2: bool function3_arg2) throws (1:test_exception2 e), string derived1_function4( 1: string function4_arg1, 2: bool function4_arg2) throws (1:test_exception2 e), bool derived1_function5( 1: map function5_arg1, 2: map function5_arg2, 3: map function5_arg3) throws (1:test_exception2 e), test_struct1 derived1_function6( 1: double function6_arg1) throws (1:test_exception2 e), } service derived2 extends base { list derived2_function1( 1: i32 function1_arg1) throws (1:test_exception2 e), list derived2_function2( 1:i64 function2_arg2) throws (1:test_exception2 e), list derived2_function3( 1:double function3_arg1) throws(1:test_exception2 e), map derived2_function4( 1:string function4_arg1) throws(1:test_exception2 e), map derived2_function5( 1:bool function5_arg1) throws(1:test_exception2 e), map derived2_function6( 1:bool function6_arg1) throws(1:test_exception2 e), } thrift-0.19.0/test/JsDeepConstructorTest.thrift0000644000000000000000000000243314370300523021557 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct Simple { 1: string value } struct Complex { 1: Simple struct_field 2: list struct_list_field 3: set struct_set_field 4: map struct_map_field 5: list>>> struct_nested_containers_field 6: map> > struct_nested_containers_field2 7: list> list_of_list_field 8: list>> list_of_list_of_list_field } struct ComplexList { 1: list struct_list_field; } thrift-0.19.0/test/test.py0000777000000000000000000002052714303472263015430 0ustar00rootroot00000000000000#!/usr/bin/env python3 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Apache Thrift - integration (cross) test suite # # tests different server-client, protocol and transport combinations # # This script requires python 3.x due to the improvements in # subprocess management that are needed for reliability. # from __future__ import print_function from itertools import chain import json import logging import multiprocessing import argparse import os import sys import crossrunner from crossrunner.compat import path_join # 3.3 introduced subprocess timeouts on waiting for child req_version = (3, 3) cur_version = sys.version_info assert (cur_version >= req_version), "Python 3.3 or later is required for proper operation." ROOT_DIR = os.path.dirname(os.path.realpath(os.path.dirname(__file__))) TEST_DIR_RELATIVE = 'test' TEST_DIR = path_join(ROOT_DIR, TEST_DIR_RELATIVE) FEATURE_DIR_RELATIVE = path_join(TEST_DIR_RELATIVE, 'features') CONFIG_FILE = 'tests.json' def run_cross_tests(server_match, client_match, jobs, skip_known_failures, only_known_failures, retry_count, regex): logger = multiprocessing.get_logger() logger.debug('Collecting tests') with open(path_join(TEST_DIR, CONFIG_FILE), 'r') as fp: j = json.load(fp) tests = crossrunner.collect_cross_tests(j, server_match, client_match, regex) if not tests: print('No test found that matches the criteria', file=sys.stderr) print(' servers: %s' % server_match, file=sys.stderr) print(' clients: %s' % client_match, file=sys.stderr) return False if only_known_failures: logger.debug('Only running known failures') known = crossrunner.load_known_failures(TEST_DIR) tests = list(filter(lambda t: crossrunner.test_name(**t) in known, tests)) if skip_known_failures: logger.debug('Skipping known failures') known = crossrunner.load_known_failures(TEST_DIR) tests = list(filter(lambda t: crossrunner.test_name(**t) not in known, tests)) dispatcher = crossrunner.TestDispatcher(TEST_DIR, ROOT_DIR, TEST_DIR_RELATIVE, jobs) logger.debug('Executing %d tests' % len(tests)) try: for r in [dispatcher.dispatch(test, retry_count) for test in tests]: r.wait() logger.debug('Waiting for completion') return dispatcher.wait() except (KeyboardInterrupt, SystemExit): logger.debug('Interrupted, shutting down') dispatcher.terminate() return False def run_feature_tests(server_match, feature_match, jobs, skip_known_failures, only_known_failures, retry_count, regex): basedir = path_join(ROOT_DIR, FEATURE_DIR_RELATIVE) logger = multiprocessing.get_logger() logger.debug('Collecting tests') with open(path_join(TEST_DIR, CONFIG_FILE), 'r') as fp: j = json.load(fp) with open(path_join(basedir, CONFIG_FILE), 'r') as fp: j2 = json.load(fp) tests = crossrunner.collect_feature_tests(j, j2, server_match, feature_match, regex) if not tests: print('No test found that matches the criteria', file=sys.stderr) print(' servers: %s' % server_match, file=sys.stderr) print(' features: %s' % feature_match, file=sys.stderr) return False if only_known_failures: logger.debug('Only running known failures') known = crossrunner.load_known_failures(basedir) tests = list(filter(lambda t: crossrunner.test_name(**t) in known, tests)) if skip_known_failures: logger.debug('Skipping known failures') known = crossrunner.load_known_failures(basedir) tests = list(filter(lambda t: crossrunner.test_name(**t) not in known, tests)) dispatcher = crossrunner.TestDispatcher(TEST_DIR, ROOT_DIR, FEATURE_DIR_RELATIVE, jobs) logger.debug('Executing %d tests' % len(tests)) try: for r in [dispatcher.dispatch(test, retry_count) for test in tests]: r.wait() logger.debug('Waiting for completion') return dispatcher.wait() except (KeyboardInterrupt, SystemExit): logger.debug('Interrupted, shutting down') dispatcher.terminate() return False def default_concurrency(): try: return int(os.environ.get('THRIFT_CROSSTEST_CONCURRENCY')) except (TypeError, ValueError): # Since much time is spent sleeping, use many threads return int(multiprocessing.cpu_count() * 1.25) + 1 def main(argv): parser = argparse.ArgumentParser() parser.add_argument('--server', default='', nargs='*', help='list of servers to test') parser.add_argument('--client', default='', nargs='*', help='list of clients to test') parser.add_argument('-F', '--features', nargs='*', default=None, help='run server feature tests instead of cross language tests') parser.add_argument('-R', '--regex', help='test name pattern to run') parser.add_argument('-o', '--only-known_failures', action='store_true', dest='only_known_failures', help='only execute tests that are known to fail') parser.add_argument('-s', '--skip-known-failures', action='store_true', dest='skip_known_failures', help='do not execute tests that are known to fail') parser.add_argument('-r', '--retry-count', type=int, default=0, help='maximum retry on failure') parser.add_argument('-j', '--jobs', type=int, default=default_concurrency(), help='number of concurrent test executions') g = parser.add_argument_group(title='Advanced') g.add_argument('-v', '--verbose', action='store_const', dest='log_level', const=logging.DEBUG, default=logging.WARNING, help='show debug output for test runner') g.add_argument('-P', '--print-expected-failures', choices=['merge', 'overwrite'], dest='print_failures', help="generate expected failures based on last result and print to stdout") g.add_argument('-U', '--update-expected-failures', choices=['merge', 'overwrite'], dest='update_failures', help="generate expected failures based on last result and save to default file location") options = parser.parse_args(argv) logger = multiprocessing.log_to_stderr() logger.setLevel(options.log_level) if options.features is not None and options.client: print('Cannot specify both --features and --client ', file=sys.stderr) return 1 # Allow multiple args separated with ',' for backward compatibility server_match = list(chain(*[x.split(',') for x in options.server])) client_match = list(chain(*[x.split(',') for x in options.client])) if options.update_failures or options.print_failures: dire = path_join(ROOT_DIR, FEATURE_DIR_RELATIVE) if options.features is not None else TEST_DIR res = crossrunner.generate_known_failures( dire, options.update_failures == 'overwrite', options.update_failures, options.print_failures) elif options.features is not None: features = options.features or ['.*'] res = run_feature_tests(server_match, features, options.jobs, options.skip_known_failures, options.only_known_failures, options.retry_count, options.regex) else: res = run_cross_tests(server_match, client_match, options.jobs, options.skip_known_failures, options.only_known_failures, options.retry_count, options.regex) return 0 if res else 1 if __name__ == '__main__': sys.exit(main(sys.argv[1:])) thrift-0.19.0/test/DebugProtoTest.thrift0000644000000000000000000002416114370300523020213 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace c_glib TTest namespace cpp thrift.test.debug namespace java thrift.test namespace rb thrift.test struct Doubles { 1: double nan, 2: double inf, 3: double neginf, 4: double repeating, 5: double big, 6: double tiny, 7: double zero, 8: double negzero, } struct OneOfEach { 1: bool im_true, 2: bool im_false, 3: i8 a_bite = 0x7f, 4: i16 integer16 = 0x7fff, 5: i32 integer32, 6: i64 integer64 = 10000000000, 7: double double_precision, 8: string some_characters, 9: string zomg_unicode, 10: bool what_who, 11: binary base64, 12: list byte_list = [1, 2, 3], 13: list i16_list = [1,2,3], 14: list i64_list = [1,2,3] 15: uuid rfc4122_uuid } struct Bonk { 1: i32 type, 2: string message, } struct Nesting { 1: Bonk my_bonk, 2: OneOfEach my_ooe, } struct HolyMoley { 1: list big, 2: set (python.immutable = "")> contain, 3: map> bonks, } struct Backwards { 2: i32 first_tag2, 1: i32 second_tag1, } struct Empty { } ( python.immutable = "", ) struct Wrapper { 1: Empty foo } ( python.immutable = "", ) struct RandomStuff { 1: i32 a, 2: i32 b, 3: i32 c, 4: i32 d, 5: list myintlist, 6: map maps, 7: i64 bigint, 8: double triple, } struct Base64 { 1: i32 a, 2: binary b1, 3: binary b2, 4: binary b3, 5: binary b4, 6: binary b5, 7: binary b6, } struct CompactProtoTestStruct { // primitive fields 1: i8 a_byte; 2: i16 a_i16; 3: i32 a_i32; 4: i64 a_i64; 5: double a_double; 6: string a_string; 7: binary a_binary; 8: bool true_field; 9: bool false_field; 10: Empty empty_struct_field; // primitives in lists 11: list byte_list; 12: list i16_list; 13: list i32_list; 14: list i64_list; 15: list double_list; 16: list string_list; 17: list binary_list; 18: list boolean_list; 19: list struct_list; // primitives in sets 20: set byte_set; 21: set i16_set; 22: set i32_set; 23: set i64_set; 24: set double_set; 25: set string_set; 26: set binary_set; 27: set boolean_set; 28: set struct_set; // maps // primitives as keys 29: map byte_byte_map; 30: map i16_byte_map; 31: map i32_byte_map; 32: map i64_byte_map; 33: map double_byte_map; 34: map string_byte_map; 35: map binary_byte_map; 36: map boolean_byte_map; // primitives as values 37: map byte_i16_map; 38: map byte_i32_map; 39: map byte_i64_map; 40: map byte_double_map; 41: map byte_string_map; 42: map byte_binary_map; 43: map byte_boolean_map; // collections as keys 44: map (python.immutable = ""), i8> list_byte_map; 45: map (python.immutable = ""), i8> set_byte_map; 46: map (python.immutable = ""), i8> map_byte_map; // collections as values 47: map> byte_map_map; 48: map> byte_set_map; 49: map> byte_list_map; // large field IDs 500 : i64 field500; 5000 : i64 field5000; 20000 : i64 field20000; } // To be used to test the serialization of an empty map struct SingleMapTestStruct { 1: required map i32_map; } const CompactProtoTestStruct COMPACT_TEST = { 'a_byte' : 127, 'a_i16' : 32000, 'a_i32' : 1000000000, 'a_i64' : 0xffffffffff, 'a_double' : 5.6789, 'a_string' : "my string", //'a_binary,' 'true_field' : 1, 'false_field' : 0, 'empty_struct_field' : {}, 'byte_list' : [-127, -1, 0, 1, 127], 'i16_list' : [-1, 0, 1, 0x7fff], 'i32_list' : [-1, 0, 0xff, 0xffff, 0xffffff, 0x7fffffff], 'i64_list' : [-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], 'double_list' : [0.1, 0.2, 0.3], 'string_list' : ["first", "second", "third"], //'binary_list,' 'boolean_list' : [1, 1, 1, 0, 0, 0], 'struct_list' : [{}, {}], 'byte_set' : [-127, -1, 0, 1, 127], 'i16_set' : [-1, 0, 1, 0x7fff], 'i32_set' : [1, 2, 3], 'i64_set' : [-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], 'double_set' : [0.1, 0.2, 0.3], 'string_set' : ["first", "second", "third"], //'binary_set,' 'boolean_set' : [1, 0], 'struct_set' : [{}], 'byte_byte_map' : {1 : 2}, 'i16_byte_map' : {1 : 1, -1 : 1, 0x7fff : 1}, 'i32_byte_map' : {1 : 1, -1 : 1, 0x7fffffff : 1}, 'i64_byte_map' : {0 : 1, 1 : 1, -1 : 1, 0x7fffffffffffffff : 1}, 'double_byte_map' : {-1.1 : 1, 1.1 : 1}, 'string_byte_map' : {"first" : 1, "second" : 2, "third" : 3, "" : 0}, //'binary_byte_map,' 'boolean_byte_map' : {1 : 1, 0 : 0}, 'byte_i16_map' : {1 : 1, 2 : -1, 3 : 0x7fff}, 'byte_i32_map' : {1 : 1, 2 : -1, 3 : 0x7fffffff}, 'byte_i64_map' : {1 : 1, 2 : -1, 3 : 0x7fffffffffffffff}, 'byte_double_map' : {1 : 0.1, 2 : -0.1, 3 : 1000000.1}, 'byte_string_map' : {1 : "", 2 : "blah", 3 : "loooooooooooooong string"}, //'byte_binary_map,' 'byte_boolean_map' : {1 : 1, 2 : 0}, 'list_byte_map' : {[1, 2, 3] : 1, [0, 1] : 2, [] : 0}, 'set_byte_map' : {[1, 2, 3] : 1, [0, 1] : 2, [] : 0}, 'map_byte_map' : {{1 : 1} : 1, {2 : 2} : 2, {} : 0}, 'byte_map_map' : {0 : {}, 1 : {1 : 1}, 2 : {1 : 1, 2 : 2}}, 'byte_set_map' : {0 : [], 1 : [1], 2 : [1, 2]}, 'byte_list_map' : {0 : [], 1 : [1], 2 : [1, 2]}, 'field500' : 500, 'field5000' : 5000, 'field20000' : 20000, } const i32 MYCONST = 2 exception ExceptionWithAMap { 1: string blah; 2: map map_field; } exception MutableException { 1: string msg; } (python.immutable = "false") exception ExceptionWithoutFields {} service ServiceForExceptionWithAMap { void methodThatThrowsAnException() throws (1: ExceptionWithAMap xwamap); } service Srv { i32 Janky(1: i32 arg); // return type only methods void voidMethod(); i32 primitiveMethod(); CompactProtoTestStruct structMethod(); void methodWithDefaultArgs(1: i32 something = MYCONST); oneway void onewayMethod(); bool declaredExceptionMethod(1: bool shouldThrow) throws (1: ExceptionWithAMap xwamap); } service Inherited extends Srv { i32 identity(1: i32 arg) } service EmptyService {} // The only purpose of this thing is to increase the size of the generated code // so that ZlibTest has more highly compressible data to play with. struct BlowUp { 1: map(python.immutable = ""),set (python.immutable = "")>> b1; 2: map(python.immutable = ""),set (python.immutable = "")>> b2; 3: map(python.immutable = ""),set (python.immutable = "")>> b3; 4: map(python.immutable = ""),set (python.immutable = "")>> b4; } struct ReverseOrderStruct { 4: string first; 3: i16 second; 2: i32 third; 1: i64 fourth; } service ReverseOrderService { void myMethod(4: string first, 3: i16 second, 2: i32 third, 1: i64 fourth); } enum SomeEnum { ONE = 1 TWO = 2 } /** This is a docstring on a constant! */ const SomeEnum MY_SOME_ENUM = SomeEnum.ONE const SomeEnum MY_SOME_ENUM_1 = 1 /*const SomeEnum MY_SOME_ENUM_2 = 7*/ const map MY_ENUM_MAP = { SomeEnum.ONE : SomeEnum.TWO } struct StructWithSomeEnum { 1: SomeEnum blah; } const map EXTRA_CRAZY_MAP = { SomeEnum.ONE : {"blah" : SomeEnum.TWO} } union TestUnion { /** * A doc string */ 1: string string_field; 2: i32 i32_field; 3: OneOfEach struct_field; 4: list struct_list; 5: i32 other_i32_field; 6: SomeEnum enum_field; 7: set i32_set; 8: map i32_map; } union TestUnionMinusStringField { 2: i32 i32_field; 3: OneOfEach struct_field; 4: list struct_list; 5: i32 other_i32_field; 6: SomeEnum enum_field; 7: set i32_set; 8: map i32_map; } union ComparableUnion { 1: string string_field; 2: binary binary_field; } struct StructWithAUnion { 1: TestUnion test_union; } struct PrimitiveThenStruct { 1: i32 blah; 2: i32 blah2; 3: Backwards bw; } typedef map SomeMap struct StructWithASomemap { 1: required SomeMap somemap_field; } struct BigFieldIdStruct { 1: string field1; 45: string field2; } struct BreaksRubyCompactProtocol { 1: string field1; 2: BigFieldIdStruct field2; 3: i32 field3; } struct TupleProtocolTestStruct { optional i32 field1; optional i32 field2; optional i32 field3; optional i32 field4; optional i32 field5; optional i32 field6; optional i32 field7; optional i32 field8; optional i32 field9; optional i32 field10; optional i32 field11; optional i32 field12; } struct ListDoublePerf { 1: list field; } thrift-0.19.0/test/VoidMethExceptionsTest.thrift0000644000000000000000000000254314370300523021722 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test.voidmethexceptions exception TExampleException { 1: required string message; } service TAppService01 { string returnString(1: string msg, 2: bool throwException) throws (1:TExampleException error); void returnVoidThrows(1: string msg, 2: bool throwException) throws (1:TExampleException error); void returnVoidNoThrowsRuntimeException(1: string msg, 2: bool throwException); void returnVoidNoThrowsTApplicationException(1: string msg, 2: bool throwException); oneway void onewayVoidNoThrows(1: string msg, 2: bool throwException); } thrift-0.19.0/test/valgrind.suppress0000644000000000000000000000344614303740367017510 0ustar00rootroot00000000000000{ boost/get_once_per_thread_epoch/ignore Memcheck:Leak match-leak-kinds: reachable fun:malloc fun:_ZN5boost6detail25get_once_per_thread_epochEv } { boostthreads/once/ignore Helgrind:Race fun:_ZN5boost13thread_detail17enter_once_regionERNS_9once_flagE fun:_ZN5boost6detail23get_current_thread_dataEv fun:_ZN5boost6detail20interruption_checkerC1EP15pthread_mutex_tP14pthread_cond_t fun:_ZN5boost22condition_variable_any4waitINS_11unique_lockINS_11timed_mutexEEEEEvRT_ fun:_ZN6apache6thrift11concurrency7Monitor4Impl11waitForeverEv fun:_ZN6apache6thrift11concurrency7Monitor4Impl19waitForTimeRelativeEl fun:_ZN6apache6thrift11concurrency7Monitor4Impl4waitEl fun:_ZNK6apache6thrift11concurrency7Monitor4waitEl fun:_ZN6apache6thrift11concurrency11BoostThread5startEv fun:_ZN6apache6thrift11concurrency4test18ThreadFactoryTests12reapNThreadsEii fun:main } { pthread/creation-tls/ignore Helgrind:Race fun:mempcpy fun:_dl_allocate_tls_init fun:get_cached_stack fun:allocate_stack fun:pthread_create@@GLIBC_2.2* obj:/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so fun:_ZN6apache6thrift11concurrency13PthreadThread5startEv fun:_ZN6apache6thrift11concurrency4test18ThreadFactoryTests12reapNThreadsEii fun:main } { boost-thread/creation-tls/ignore Helgrind:Race fun:mempcpy fun:_dl_allocate_tls_init fun:get_cached_stack fun:allocate_stack fun:pthread_create@@GLIBC_2.2.5 obj:/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so fun:_ZN5boost6thread21start_thread_noexceptEv fun:_ZN5boost6thread12start_threadEv fun:_ZN5boost6threadC1ISt5_BindIFPFPvS3_ES3_EEEEOT_ fun:_ZN6apache6thrift11concurrency11BoostThread5startEv fun:_ZN6apache6thrift11concurrency4test18ThreadFactoryTests12reapNThreadsEii fun:main } thrift-0.19.0/test/Makefile.am0000644000000000000000000000736014370300523016115 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = features PRECROSS_TARGET = if WITH_C_GLIB SUBDIRS += c_glib PRECROSS_TARGET += precross-c_glib endif if WITH_CL SUBDIRS += cl PRECROSS_TARGET += precross-cl endif if WITH_CPP SUBDIRS += cpp PRECROSS_TARGET += precross-cpp endif if WITH_PERL SUBDIRS += perl PRECROSS_TARGET += precross-perl endif if WITH_PHP SUBDIRS += php PRECROSS_TARGET += precross-php endif if WITH_DART SUBDIRS += dart PRECROSS_TARGET += precross-dart endif if WITH_PYTHON SUBDIRS += py PRECROSS_TARGET += precross-py SUBDIRS += py.tornado if WITH_TWISTED_TEST SUBDIRS += py.twisted endif endif if WITH_RUBY SUBDIRS += rb PRECROSS_TARGET += precross-rb endif if WITH_HAXE SUBDIRS += haxe endif if WITH_DOTNET SUBDIRS += netstd endif if WITH_GO SUBDIRS += go PRECROSS_TARGET += precross-go endif if WITH_ERLANG SUBDIRS += erl PRECROSS_TARGET += precross-erl endif if WITH_LUA SUBDIRS += lua PRECROSS_TARGET += precross-lua endif if WITH_RS SUBDIRS += rs PRECROSS_TARGET += precross-rs endif if WITH_SWIFT SUBDIRS += swift PRECROSS_TARGET += precross-swift endif # # generate html for ThriftTest.thrift AND validate it! # if WITH_NODEJS check-local: $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift $(top_builddir)/node_modules/.bin/html-validator --file=gen-html/index.html --verbose $(top_builddir)/node_modules/.bin/html-validator --file=gen-html/ThriftTest.html --verbose else check-local: $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift endif clean-local: $(RM) -r $(top_srcdir)/test/gen-html/ find . -type d -name "__pycache__" | xargs rm -rf find . -type f -name "*.pyc" | xargs rm -f dist-hook: $(RM) -r $(distdir)/gen-html/ find $(distdir) -type d -name "__pycache__" | xargs rm -rf find $(distdir) -type f -name "*.pyc" | xargs rm -f EXTRA_DIST = \ audit \ c_glib \ cl \ cpp \ crossrunner \ dart \ erl \ keys \ lua \ ocaml \ perl \ php \ py \ py.tornado \ py.twisted \ rb \ rs \ swift \ threads \ partial \ AnnotationTest.thrift \ BrokenConstants.thrift \ ConstantsDemo.thrift \ DebugProtoTest.thrift \ v0.16/DebugProtoTest.thrift \ DenseLinkingTest.thrift \ DocTest.thrift \ DoubleConstantsTest.thrift \ EnumContainersTest.thrift \ EnumTest.thrift \ FullCamelTest.thrift \ Include.thrift \ Identifiers.thrift \ Int64Test.thrift \ JsDeepConstructorTest.thrift \ ManyOptionals.thrift \ ManyTypedefs.thrift \ NameConflictTest.thrift \ OptionalRequiredTest.thrift \ Recursive.thrift \ ReuseObjects.thrift \ SmallTest.thrift \ StressTest.thrift \ ThriftTest.thrift \ v0.16/ThriftTest.thrift \ TypedefTest.thrift \ Types.thrift \ UnsafeTypes.thrift \ Service.thrift \ SpecificNameTest.thrift \ VoidMethExceptionsTest.thrift \ partial/thrift_test_schema.thrift \ keys/keygen/.gitignore \ known_failures_Linux.json \ test.py \ tests.json \ rebuild_known_failures.sh \ result.js \ index.html \ README.md \ valgrind.suppress precross-%: $(MAKE) -C $* precross precross: $(PRECROSS_TARGET) thrift-0.19.0/test/ConstantsDemo.thrift0000644000000000000000000000555714370300523020072 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace cpp yozone namespace erl consts_ namespace haxe constantsDemo namespace go constantsdemo typedef uuid myUUID struct thing { 1: i32 hello, 2: i32 goodbye 3: uuid id 4: myUUID my_id 5: optional myUUID my_optional_id } enum enumconstants { ONE = 1, TWO = 2 } // struct thing2 { // /** standard docstring */ // 1: enumconstants val = TWO // } typedef i32 myIntType const myIntType myInt = 3 //const map GEN_ENUM_NAMES = {ONE : "HOWDY", TWO: "PARTNER"} const i32 hex_const = 0x0001F const i32 negative_hex_constant = -0x0001F const i32 GEN_ME = -3523553 const double GEn_DUB = 325.532 const double GEn_DU = 085.2355 const string GEN_STRING = "asldkjasfd" const double e10 = 1e10 // fails with 0.9.3 and earlier const double e11 = -1e10 // uuids are accepted with or without curly braces const uuid GEN_UUID = '00000000-4444-CCCC-ffff-0123456789ab' const uuid GEN_GUID = '{00112233-4455-6677-8899-aaBBccDDeeFF}' const myUUID MY_UUID = '00000000-4444-CCCC-ffff-0123456789ab' const myUUID MY_GUID = '{00112233-4455-6677-8899-aaBBccDDeeFF}' const map GEN_MAP = { 35532 : 233, 43523 : 853 } const list GEN_LIST = [ 235235, 23598352, 3253523 ] const map> GEN_MAPMAP = { 235 : { 532 : 53255, 235:235}} const map GEN_MAP2 = { "hello" : 233, "lkj98d" : 853, 'lkjsdf' : 098325 } const thing GEN_THING = { 'hello' : 325, 'goodbye' : 325352, 'id' : '{00112233-4455-6677-8899-aaBBccDDeeFF}', 'my_id': '00000000-4444-CCCC-ffff-0123456789ab', 'my_optional_id': '00000000-4444-CCCC-ffff-0123456789ab' } const map GEN_WHAT = { 35 : { 'hello' : 325, 'goodbye' : 325352, 'id' : '00000000-4444-CCCC-ffff-0123456789ab', 'my_id': '00000000-4444-CCCC-ffff-0123456789ab', 'my_optional_id': '00000000-4444-CCCC-ffff-0123456789ab' } } const set GEN_SET = [ 235, 235, 53235 ] const set GUID_SET = [ '{00112233-4455-6677-8899-aaBBccDDeeFF}', '00000000-4444-CCCC-ffff-0123456789ab' ] exception Blah { 1: i32 bing } exception Gak {} service yowza { void blingity(), i32 blangity() throws (1: Blah hoot ) } thrift-0.19.0/test/AnnotationTest.thrift0000644000000000000000000000371514303740367020267 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ typedef list ( cpp.template = "std::list" ) int_linked_list struct foo { 1: i32 bar ( presence = "required" ); 2: i32 baz ( presence = "manual", cpp.use_pointer = "", ); 3: i32 qux; 4: i32 bop; } ( cpp.type = "DenseFoo", python.type = "DenseFoo", java.final = "", annotation.without.value, ) exception foo_error { 1: i32 error_code ( foo="bar" ) 2: string error_msg } (foo = "bar") typedef string ( unicode.encoding = "UTF-16" ) non_latin_string (foo="bar") typedef list< double ( cpp.fixed_point = "16" ) > tiny_float_list enum weekdays { SUNDAY ( weekend = "yes" ), MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY ( weekend = "yes" ) } (foo.bar="baz") struct ostr_default { 1: i32 bar; } struct ostr_custom { 1: i32 bar; } (cpp.customostream) service foo_service { void foo() ( foo = "bar" ) } (a.b="c") service deprecate_everything { void Foo( ) ( deprecated = "This method has neither 'x' nor \"y\"" ) void Bar( ) ( deprecated = "Fails to deliver 中文 колбаÑа" ) void Baz( ) ( deprecated = "Need this to work with tabs (\t) or Umlauts (äöüÄÖÜß) too" ) void Deprecated() ( deprecated ) // no comment } thrift-0.19.0/test/Identifiers.thrift0000644000000000000000000000164714370300523017552 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // THRIFT-4953 struct NoFieldIdentifiersTest { string field_without_id1, string field_without_id2, 1: string field_with_id }thrift-0.19.0/test/py/0000777000000000000000000000000014472652606014526 5ustar00rootroot00000000000000thrift-0.19.0/test/py/TestRenderedDoubleConstants.py0000644000000000000000000002452014303740367022512 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import unittest from DoubleConstantsTest import constants # # In order to run the test under Windows. We need to create symbolic link # name 'thrift' to '../src' folder by using: # # mklink /D thrift ..\src # class TestRenderedDoubleConstants(unittest.TestCase): ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST = \ "failed to verify a double constant generated by Thrift (expected = %f, got = %f)" ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST =\ "failed to verify a list item by Thrift (expected = %f, got = %f)" ASSERTION_MESSAGE_FOR_TYPE_CHECKS = "the rendered variable with name %s is not of double type" # to make sure the variables inside Thrift files are generated correctly def test_rendered_double_constants(self): EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0 EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0 EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0 EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0 EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359 EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1 EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1 EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308 EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43 EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308 EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43 self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)) self.assertAlmostEqual( constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, places=7, msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST % ( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)) self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST") self.assertTrue( isinstance(constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, float), msg=TestRenderedDoubleConstants.ASSERTION_MESSAGE_FOR_TYPE_CHECKS % "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST") # to make sure the variables inside Thrift files are generated correctly def test_rendered_double_list(self): EXPECTED_DOUBLE_LIST = [1.0, -100.0, 100.0, 9223372036854775807.0, -9223372036854775807.0, 3.14159265359, 1000000.1, -1000000.1, 1.7e+308, -1.7e+308, 9223372036854775816.43, -9223372036854775816.43] self.assertEqual(len(constants.DOUBLE_LIST_TEST), len(EXPECTED_DOUBLE_LIST)) for i, expectedValue in enumerate(EXPECTED_DOUBLE_LIST): self.assertAlmostEqual(constants.DOUBLE_LIST_TEST[i], expectedValue, places=7) def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(TestRenderedDoubleConstants)) return suite if __name__ == "__main__": unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) thrift-0.19.0/test/py/TestEof.py0000777000000000000000000001077614062750227016460 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from ThriftTest.ttypes import Xtruct from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol from thrift.protocol import TCompactProtocol import unittest class TestEof(unittest.TestCase): def make_data(self, pfactory=None): trans = TTransport.TMemoryBuffer() if pfactory: prot = pfactory.getProtocol(trans) else: prot = TBinaryProtocol.TBinaryProtocol(trans) x = Xtruct() x.string_thing = "Zero" x.byte_thing = 0 x.write(prot) x = Xtruct() x.string_thing = "One" x.byte_thing = 1 x.write(prot) return trans.getvalue() def testTransportReadAll(self): """Test that readAll on any type of transport throws an EOFError""" trans = TTransport.TMemoryBuffer(self.make_data()) trans.readAll(1) try: trans.readAll(10000) except EOFError: return self.fail("Should have gotten EOFError") def eofTestHelper(self, pfactory): trans = TTransport.TMemoryBuffer(self.make_data(pfactory)) prot = pfactory.getProtocol(trans) x = Xtruct() x.read(prot) self.assertEqual(x.string_thing, "Zero") self.assertEqual(x.byte_thing, 0) x = Xtruct() x.read(prot) self.assertEqual(x.string_thing, "One") self.assertEqual(x.byte_thing, 1) try: x = Xtruct() x.read(prot) except EOFError: return self.fail("Should have gotten EOFError") def eofTestHelperStress(self, pfactory): """Test the ability of TBinaryProtocol to deal with the removal of every byte in the file""" # TODO: we should make sure this covers more of the code paths data = self.make_data(pfactory) for i in range(0, len(data) + 1): trans = TTransport.TMemoryBuffer(data[0:i]) prot = pfactory.getProtocol(trans) try: x = Xtruct() x.read(prot) x.read(prot) x.read(prot) except EOFError: continue self.fail("Should have gotten an EOFError") def testBinaryProtocolEof(self): """Test that TBinaryProtocol throws an EOFError when it reaches the end of the stream""" self.eofTestHelper(TBinaryProtocol.TBinaryProtocolFactory()) self.eofTestHelperStress(TBinaryProtocol.TBinaryProtocolFactory()) def testBinaryProtocolAcceleratedBinaryEof(self): """Test that TBinaryProtocolAccelerated throws an EOFError when it reaches the end of the stream""" self.eofTestHelper(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False)) self.eofTestHelperStress(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False)) def testCompactProtocolEof(self): """Test that TCompactProtocol throws an EOFError when it reaches the end of the stream""" self.eofTestHelper(TCompactProtocol.TCompactProtocolFactory()) self.eofTestHelperStress(TCompactProtocol.TCompactProtocolFactory()) def testCompactProtocolAcceleratedCompactEof(self): """Test that TCompactProtocolAccelerated throws an EOFError when it reaches the end of the stream""" self.eofTestHelper(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False)) self.eofTestHelperStress(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False)) def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(TestEof)) return suite if __name__ == "__main__": unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) thrift-0.19.0/test/py/FastbinaryTest.py0000777000000000000000000001717614062750227020052 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # r""" PYTHONPATH=./gen-py:../../lib/py/build/lib... ./FastbinaryTest.py """ # TODO(dreiss): Test error cases. Check for memory leaks. from __future__ import print_function import math import os import sys import timeit from copy import deepcopy from pprint import pprint from thrift.transport import TTransport from thrift.protocol.TBinaryProtocol import TBinaryProtocol, TBinaryProtocolAccelerated from thrift.protocol.TCompactProtocol import TCompactProtocol, TCompactProtocolAccelerated from DebugProtoTest import Srv from DebugProtoTest.ttypes import Backwards, Bonk, Empty, HolyMoley, OneOfEach, RandomStuff, Wrapper class TDevNullTransport(TTransport.TTransportBase): def __init__(self): pass def isOpen(self): return True ooe1 = OneOfEach() ooe1.im_true = True ooe1.im_false = False ooe1.a_bite = 0xd6 ooe1.integer16 = 27000 ooe1.integer32 = 1 << 24 ooe1.integer64 = 6000 * 1000 * 1000 ooe1.double_precision = math.pi ooe1.some_characters = "Debug THIS!" ooe1.zomg_unicode = u"\xd7\n\a\t" ooe2 = OneOfEach() ooe2.integer16 = 16 ooe2.integer32 = 32 ooe2.integer64 = 64 ooe2.double_precision = (math.sqrt(5) + 1) / 2 ooe2.some_characters = ":R (me going \"rrrr\")" ooe2.zomg_unicode = u"\xd3\x80\xe2\x85\xae\xce\x9d\x20"\ u"\xd0\x9d\xce\xbf\xe2\x85\xbf\xd0\xbe"\ u"\xc9\xa1\xd0\xb3\xd0\xb0\xcf\x81\xe2\x84\x8e"\ u"\x20\xce\x91\x74\x74\xce\xb1\xe2\x85\xbd\xce\xba"\ u"\xc7\x83\xe2\x80\xbc" if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): ooe1.zomg_unicode = ooe1.zomg_unicode.encode('utf8') ooe2.zomg_unicode = ooe2.zomg_unicode.encode('utf8') hm = HolyMoley(**{"big": [], "contain": set(), "bonks": {}}) hm.big.append(ooe1) hm.big.append(ooe2) hm.big[0].a_bite = 0x22 hm.big[1].a_bite = 0x22 hm.contain.add(("and a one", "and a two")) hm.contain.add(("then a one, two", "three!", "FOUR!")) if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): hm.contain.add((u"\xd7\n\a\t".encode('utf8'),)) else: hm.contain.add((u"\xd7\n\a\t",)) hm.contain.add(()) hm.bonks["nothing"] = [] hm.bonks["something"] = [ Bonk(**{"type": 1, "message": "Wait."}), Bonk(**{"type": 2, "message": "What?"}), ] hm.bonks["poe"] = [ Bonk(**{"type": 3, "message": "quoth"}), Bonk(**{"type": 4, "message": "the raven"}), Bonk(**{"type": 5, "message": "nevermore"}), ] rs = RandomStuff() rs.a = 1 rs.b = 2 rs.c = 3 rs.myintlist = list(range(20)) rs.maps = {1: Wrapper(**{"foo": Empty()}), 2: Wrapper(**{"foo": Empty()})} rs.bigint = 124523452435 rs.triple = 3.14 # make sure this splits two buffers in a buffered protocol rshuge = RandomStuff() rshuge.myintlist = list(range(10000)) my_zero = Srv.Janky_result(**{"success": 5}) class Test(object): def __init__(self, fast, slow): self._fast = fast self._slow = slow def _check_write(self, o): trans_fast = TTransport.TMemoryBuffer() trans_slow = TTransport.TMemoryBuffer() prot_fast = self._fast(trans_fast, fallback=False) prot_slow = self._slow(trans_slow) o.write(prot_fast) o.write(prot_slow) ORIG = trans_slow.getvalue() MINE = trans_fast.getvalue() if ORIG != MINE: print("actual : %s\nexpected: %s" % (repr(MINE), repr(ORIG))) raise Exception('write value mismatch') def _check_read(self, o): prot = self._slow(TTransport.TMemoryBuffer()) o.write(prot) slow_version_binary = prot.trans.getvalue() prot = self._fast( TTransport.TMemoryBuffer(slow_version_binary), fallback=False) c = o.__class__() c.read(prot) if c != o: print("actual : ") pprint(repr(c)) print("expected: ") pprint(repr(o)) raise Exception('read value mismatch') prot = self._fast( TTransport.TBufferedTransport( TTransport.TMemoryBuffer(slow_version_binary)), fallback=False) c = o.__class__() c.read(prot) if c != o: print("actual : ") pprint(repr(c)) print("expected: ") pprint(repr(o)) raise Exception('read value mismatch') def do_test(self): self._check_write(HolyMoley()) self._check_read(HolyMoley()) self._check_write(hm) no_set = deepcopy(hm) no_set.contain = set() self._check_read(no_set) self._check_read(hm) self._check_write(rs) self._check_read(rs) self._check_write(rshuge) self._check_read(rshuge) self._check_write(my_zero) self._check_read(my_zero) self._check_read(Backwards(**{"first_tag2": 4, "second_tag1": 2})) # One case where the serialized form changes, but only superficially. o = Backwards(**{"first_tag2": 4, "second_tag1": 2}) trans_fast = TTransport.TMemoryBuffer() trans_slow = TTransport.TMemoryBuffer() prot_fast = self._fast(trans_fast, fallback=False) prot_slow = self._slow(trans_slow) o.write(prot_fast) o.write(prot_slow) ORIG = trans_slow.getvalue() MINE = trans_fast.getvalue() assert id(ORIG) != id(MINE) prot = self._fast(TTransport.TMemoryBuffer(), fallback=False) o.write(prot) prot = self._slow( TTransport.TMemoryBuffer(prot.trans.getvalue())) c = o.__class__() c.read(prot) if c != o: print("copy: ") pprint(repr(c)) print("orig: ") pprint(repr(o)) def do_test(fast, slow): Test(fast, slow).do_test() def do_benchmark(protocol, iters=5000, skip_slow=False): setup = """ from __main__ import hm, rs, TDevNullTransport from thrift.protocol.{0} import {0}{1} trans = TDevNullTransport() prot = {0}{1}(trans{2}) """ setup_fast = setup.format(protocol, 'Accelerated', ', fallback=False') if not skip_slow: setup_slow = setup.format(protocol, '', '') print("Starting Benchmarks") if not skip_slow: print("HolyMoley Standard = %f" % timeit.Timer('hm.write(prot)', setup_slow).timeit(number=iters)) print("HolyMoley Acceler. = %f" % timeit.Timer('hm.write(prot)', setup_fast).timeit(number=iters)) if not skip_slow: print("FastStruct Standard = %f" % timeit.Timer('rs.write(prot)', setup_slow).timeit(number=iters)) print("FastStruct Acceler. = %f" % timeit.Timer('rs.write(prot)', setup_fast).timeit(number=iters)) if __name__ == '__main__': print('Testing TBinaryAccelerated') do_test(TBinaryProtocolAccelerated, TBinaryProtocol) do_benchmark('TBinaryProtocol') print('Testing TCompactAccelerated') do_test(TCompactProtocolAccelerated, TCompactProtocol) do_benchmark('TCompactProtocol') thrift-0.19.0/test/py/Makefile.am0000644000000000000000000001237414370300523016546 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = serial-tests py_unit_tests = RunClientServer.py thrift_gen = \ gen-py/ThriftTest/__init__.py \ gen-py/DebugProtoTest/__init__.py \ gen-py/DoubleConstantsTest/__init__.py \ gen-py/Recursive/__init__.py \ gen-py-default/ThriftTest/__init__.py \ gen-py-default/DebugProtoTest/__init__.py \ gen-py-default/DoubleConstantsTest/__init__.py \ gen-py-default/Recursive/__init__.py \ gen-py-slots/ThriftTest/__init__.py \ gen-py-slots/DebugProtoTest/__init__.py \ gen-py-slots/DoubleConstantsTest/__init__.py \ gen-py-slots/Recursive/__init__.py \ gen-py-oldstyle/ThriftTest/__init__.py \ gen-py-oldstyle/DebugProtoTest/__init__.py \ gen-py-oldstyle/DoubleConstantsTest/__init__.py \ gen-py-oldstyle/Recursive/__init__.py \ gen-py-no_utf8strings/ThriftTest/__init__.py \ gen-py-no_utf8strings/DebugProtoTest/__init__.py \ gen-py-no_utf8strings/DoubleConstantsTest/__init__.py \ gen-py-no_utf8strings/Recursive/__init__.py \ gen-py-dynamic/ThriftTest/__init__.py \ gen-py-dynamic/DebugProtoTest/__init__.py \ gen-py-dynamic/DoubleConstantsTest/__init__.py \ gen-py-dynamic/Recursive/__init__.py \ gen-py-dynamicslots/ThriftTest/__init__.py \ gen-py-dynamicslots/DebugProtoTest/__init__.py \ gen-py-dynamicslots/DoubleConstantsTest/__init__.py \ gen-py-dynamicslots/Recursive/__init__.py \ gen-py-enum/ThriftTest/__init__.py \ gen-py-enum/DebugProtoTest/__init__.py \ gen-py-enum/DoubleConstantsTest/__init__.py \ gen-py-enum/Recursive/__init__.py precross: $(thrift_gen) BUILT_SOURCES = $(thrift_gen) helper_scripts= \ TestClient.py \ TestServer.py check_SCRIPTS= \ $(thrift_gen) \ $(py_unit_tests) \ $(helper_scripts) TESTS= $(py_unit_tests) gen-py/%/__init__.py: ../%.thrift $(THRIFT) test -f ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py $< gen-py-default/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-default || $(MKDIR_P) gen-py-default test -f ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py -out gen-py-default ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py -out gen-py-default $< gen-py-slots/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-slots || $(MKDIR_P) gen-py-slots test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:slots -out gen-py-slots ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:slots -out gen-py-slots $< gen-py-oldstyle/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-oldstyle || $(MKDIR_P) gen-py-oldstyle test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:old_style -out gen-py-oldstyle ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:old_style -out gen-py-oldstyle $< gen-py-no_utf8strings/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-no_utf8strings || $(MKDIR_P) gen-py-no_utf8strings test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings $< gen-py-dynamic/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-dynamic || $(MKDIR_P) gen-py-dynamic test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:dynamic -out gen-py-dynamic ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:dynamic -out gen-py-dynamic $< gen-py-dynamicslots/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-dynamicslots || $(MKDIR_P) gen-py-dynamicslots test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots $< gen-py-enum/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-enum || $(MKDIR_P) gen-py-enum test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:enum -out gen-py-enum ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:enum -out gen-py-enum $< clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ thrift-0.19.0/test/py/CMakeLists.txt0000644000000000000000000000253514303740367017262 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # add_test(NAME python_test_generate COMMAND ${CMAKE_COMMAND} -DTHRIFTCOMPILER=$ -DMY_PROJECT_DIR=${PROJECT_SOURCE_DIR} -DMY_CURRENT_SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DMY_CURRENT_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/generate.cmake ) add_test(NAME python_test COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/RunClientServer.py --gen-base=${CMAKE_CURRENT_BINARY_DIR} DEPENDS python_test_generate WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) thrift-0.19.0/test/py/setup.cfg0000644000000000000000000000003714303740367016336 0ustar00rootroot00000000000000[flake8] max-line-length = 100 thrift-0.19.0/test/py/Makefile0000644000000000000000000006320014472652606016163 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/py/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/py ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/py abs_srcdir = /thrift/src/test/py abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = serial-tests py_unit_tests = RunClientServer.py thrift_gen = \ gen-py/ThriftTest/__init__.py \ gen-py/DebugProtoTest/__init__.py \ gen-py/DoubleConstantsTest/__init__.py \ gen-py/Recursive/__init__.py \ gen-py-default/ThriftTest/__init__.py \ gen-py-default/DebugProtoTest/__init__.py \ gen-py-default/DoubleConstantsTest/__init__.py \ gen-py-default/Recursive/__init__.py \ gen-py-slots/ThriftTest/__init__.py \ gen-py-slots/DebugProtoTest/__init__.py \ gen-py-slots/DoubleConstantsTest/__init__.py \ gen-py-slots/Recursive/__init__.py \ gen-py-oldstyle/ThriftTest/__init__.py \ gen-py-oldstyle/DebugProtoTest/__init__.py \ gen-py-oldstyle/DoubleConstantsTest/__init__.py \ gen-py-oldstyle/Recursive/__init__.py \ gen-py-no_utf8strings/ThriftTest/__init__.py \ gen-py-no_utf8strings/DebugProtoTest/__init__.py \ gen-py-no_utf8strings/DoubleConstantsTest/__init__.py \ gen-py-no_utf8strings/Recursive/__init__.py \ gen-py-dynamic/ThriftTest/__init__.py \ gen-py-dynamic/DebugProtoTest/__init__.py \ gen-py-dynamic/DoubleConstantsTest/__init__.py \ gen-py-dynamic/Recursive/__init__.py \ gen-py-dynamicslots/ThriftTest/__init__.py \ gen-py-dynamicslots/DebugProtoTest/__init__.py \ gen-py-dynamicslots/DoubleConstantsTest/__init__.py \ gen-py-dynamicslots/Recursive/__init__.py \ gen-py-enum/ThriftTest/__init__.py \ gen-py-enum/DebugProtoTest/__init__.py \ gen-py-enum/DoubleConstantsTest/__init__.py \ gen-py-enum/Recursive/__init__.py BUILT_SOURCES = $(thrift_gen) helper_scripts = \ TestClient.py \ TestServer.py check_SCRIPTS = \ $(thrift_gen) \ $(py_unit_tests) \ $(helper_scripts) TESTS = $(py_unit_tests) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/py/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/py/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check check-am install install-am install-strip .PHONY: all all-am check check-TESTS check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile precross: $(thrift_gen) gen-py/%/__init__.py: ../%.thrift $(THRIFT) test -f ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py $< gen-py-default/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-default || $(MKDIR_P) gen-py-default test -f ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py -out gen-py-default ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py -out gen-py-default $< gen-py-slots/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-slots || $(MKDIR_P) gen-py-slots test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:slots -out gen-py-slots ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:slots -out gen-py-slots $< gen-py-oldstyle/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-oldstyle || $(MKDIR_P) gen-py-oldstyle test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:old_style -out gen-py-oldstyle ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:old_style -out gen-py-oldstyle $< gen-py-no_utf8strings/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-no_utf8strings || $(MKDIR_P) gen-py-no_utf8strings test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings $< gen-py-dynamic/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-dynamic || $(MKDIR_P) gen-py-dynamic test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:dynamic -out gen-py-dynamic ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:dynamic -out gen-py-dynamic $< gen-py-dynamicslots/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-dynamicslots || $(MKDIR_P) gen-py-dynamicslots test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots $< gen-py-enum/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-enum || $(MKDIR_P) gen-py-enum test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:enum -out gen-py-enum ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:enum -out gen-py-enum $< clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/py/SerializationTest.py0000777000000000000000000004237114303472263020557 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from ThriftTest.ttypes import ( Bonk, Bools, LargeDeltas, ListBonks, NestedListsBonk, NestedListsI32x2, NestedListsI32x3, NestedMixedx2, Numberz, VersioningTestV1, VersioningTestV2, Xtruct, Xtruct2, ) from Recursive.ttypes import RecTree from Recursive.ttypes import RecList from Recursive.ttypes import CoRec from Recursive.ttypes import CoRec2 from Recursive.ttypes import VectorTest from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol, TCompactProtocol, TJSONProtocol from thrift.TSerialization import serialize, deserialize import sys import unittest class AbstractTest(unittest.TestCase): def setUp(self): self.v1obj = VersioningTestV1( begin_in_both=12345, old_string='aaa', end_in_both=54321, ) self.v2obj = VersioningTestV2( begin_in_both=12345, newint=1, newbyte=2, newshort=3, newlong=4, newdouble=5.0, newstruct=Bonk(message="Hello!", type=123), newlist=[7, 8, 9], newset=set([42, 1, 8]), newmap={1: 2, 2: 3}, newstring="Hola!", end_in_both=54321, ) self.bools = Bools(im_true=True, im_false=False) self.bools_flipped = Bools(im_true=False, im_false=True) self.large_deltas = LargeDeltas( b1=self.bools, b10=self.bools_flipped, b100=self.bools, check_true=True, b1000=self.bools_flipped, check_false=False, vertwo2000=VersioningTestV2(newstruct=Bonk(message='World!', type=314)), a_set2500=set(['lazy', 'brown', 'cow']), vertwo3000=VersioningTestV2(newset=set([2, 3, 5, 7, 11])), big_numbers=[2 ** 8, 2 ** 16, 2 ** 31 - 1, -(2 ** 31 - 1)] ) self.compact_struct = CompactProtoTestStruct( a_byte=127, a_i16=32000, a_i32=1000000000, a_i64=0xffffffffff, a_double=5.6789, a_string="my string", true_field=True, false_field=False, empty_struct_field=Empty(), byte_list=[-127, -1, 0, 1, 127], i16_list=[-1, 0, 1, 0x7fff], i32_list=[-1, 0, 0xff, 0xffff, 0xffffff, 0x7fffffff], i64_list=[-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff], double_list=[0.1, 0.2, 0.3], string_list=["first", "second", "third"], boolean_list=[True, True, True, False, False, False], struct_list=[Empty(), Empty()], byte_set=set([-127, -1, 0, 1, 127]), i16_set=set([-1, 0, 1, 0x7fff]), i32_set=set([1, 2, 3]), i64_set=set([-1, 0, 0xff, 0xffff, 0xffffff, 0xffffffff, 0xffffffffff, 0xffffffffffff, 0xffffffffffffff, 0x7fffffffffffffff]), double_set=set([0.1, 0.2, 0.3]), string_set=set(["first", "second", "third"]), boolean_set=set([True, False]), # struct_set=set([Empty()]), # unhashable instance byte_byte_map={1: 2}, i16_byte_map={1: 1, -1: 1, 0x7fff: 1}, i32_byte_map={1: 1, -1: 1, 0x7fffffff: 1}, i64_byte_map={0: 1, 1: 1, -1: 1, 0x7fffffffffffffff: 1}, double_byte_map={-1.1: 1, 1.1: 1}, string_byte_map={"first": 1, "second": 2, "third": 3, "": 0}, boolean_byte_map={True: 1, False: 0}, byte_i16_map={1: 1, 2: -1, 3: 0x7fff}, byte_i32_map={1: 1, 2: -1, 3: 0x7fffffff}, byte_i64_map={1: 1, 2: -1, 3: 0x7fffffffffffffff}, byte_double_map={1: 0.1, 2: -0.1, 3: 1000000.1}, byte_string_map={1: "", 2: "blah", 3: "loooooooooooooong string"}, byte_boolean_map={1: True, 2: False}, # list_byte_map # unhashable # set_byte_map={set([1, 2, 3]) : 1, set([0, 1]) : 2, set([]) : 0}, # unhashable # map_byte_map # unhashable byte_map_map={0: {}, 1: {1: 1}, 2: {1: 1, 2: 2}}, byte_set_map={0: set([]), 1: set([1]), 2: set([1, 2])}, byte_list_map={0: [], 1: [1], 2: [1, 2]}, ) self.nested_lists_i32x2 = NestedListsI32x2( [ [1, 1, 2], [2, 7, 9], [3, 5, 8] ] ) self.nested_lists_i32x3 = NestedListsI32x3( [ [ [2, 7, 9], [3, 5, 8] ], [ [1, 1, 2], [1, 4, 9] ] ] ) self.nested_mixedx2 = NestedMixedx2(int_set_list=[ set([1, 2, 3]), set([1, 4, 9]), set([1, 2, 3, 5, 8, 13, 21]), set([-1, 0, 1]) ], # note, the sets below are sets of chars, since the strings are iterated map_int_strset={10: set('abc'), 20: set('def'), 30: set('GHI')}, map_int_strset_list=[ {10: set('abc'), 20: set('def'), 30: set('GHI')}, {100: set('lmn'), 200: set('opq'), 300: set('RST')}, {1000: set('uvw'), 2000: set('wxy'), 3000: set('XYZ')}] ) self.nested_lists_bonk = NestedListsBonk( [ [ [ Bonk(message='inner A first', type=1), Bonk(message='inner A second', type=1) ], [ Bonk(message='inner B first', type=2), Bonk(message='inner B second', type=2) ] ] ] ) self.list_bonks = ListBonks( [ Bonk(message='inner A', type=1), Bonk(message='inner B', type=2), Bonk(message='inner C', type=0) ] ) def _serialize(self, obj): trans = TTransport.TMemoryBuffer() prot = self.protocol_factory.getProtocol(trans) obj.write(prot) return trans.getvalue() def _deserialize(self, objtype, data): prot = self.protocol_factory.getProtocol(TTransport.TMemoryBuffer(data)) ret = objtype() ret.read(prot) return ret def testForwards(self): obj = self._deserialize(VersioningTestV2, self._serialize(self.v1obj)) self.assertEquals(obj.begin_in_both, self.v1obj.begin_in_both) self.assertEquals(obj.end_in_both, self.v1obj.end_in_both) def testBackwards(self): obj = self._deserialize(VersioningTestV1, self._serialize(self.v2obj)) self.assertEquals(obj.begin_in_both, self.v2obj.begin_in_both) self.assertEquals(obj.end_in_both, self.v2obj.end_in_both) def testSerializeV1(self): obj = self._deserialize(VersioningTestV1, self._serialize(self.v1obj)) self.assertEquals(obj, self.v1obj) def testSerializeV2(self): obj = self._deserialize(VersioningTestV2, self._serialize(self.v2obj)) self.assertEquals(obj, self.v2obj) def testBools(self): self.assertNotEquals(self.bools, self.bools_flipped) self.assertNotEquals(self.bools, self.v1obj) obj = self._deserialize(Bools, self._serialize(self.bools)) self.assertEquals(obj, self.bools) obj = self._deserialize(Bools, self._serialize(self.bools_flipped)) self.assertEquals(obj, self.bools_flipped) rep = repr(self.bools) self.assertTrue(len(rep) > 0) def testLargeDeltas(self): # test large field deltas (meaningful in CompactProto only) obj = self._deserialize(LargeDeltas, self._serialize(self.large_deltas)) self.assertEquals(obj, self.large_deltas) rep = repr(self.large_deltas) self.assertTrue(len(rep) > 0) def testNestedListsI32x2(self): obj = self._deserialize(NestedListsI32x2, self._serialize(self.nested_lists_i32x2)) self.assertEquals(obj, self.nested_lists_i32x2) rep = repr(self.nested_lists_i32x2) self.assertTrue(len(rep) > 0) def testNestedListsI32x3(self): obj = self._deserialize(NestedListsI32x3, self._serialize(self.nested_lists_i32x3)) self.assertEquals(obj, self.nested_lists_i32x3) rep = repr(self.nested_lists_i32x3) self.assertTrue(len(rep) > 0) def testNestedMixedx2(self): obj = self._deserialize(NestedMixedx2, self._serialize(self.nested_mixedx2)) self.assertEquals(obj, self.nested_mixedx2) rep = repr(self.nested_mixedx2) self.assertTrue(len(rep) > 0) def testNestedListsBonk(self): obj = self._deserialize(NestedListsBonk, self._serialize(self.nested_lists_bonk)) self.assertEquals(obj, self.nested_lists_bonk) rep = repr(self.nested_lists_bonk) self.assertTrue(len(rep) > 0) def testListBonks(self): obj = self._deserialize(ListBonks, self._serialize(self.list_bonks)) self.assertEquals(obj, self.list_bonks) rep = repr(self.list_bonks) self.assertTrue(len(rep) > 0) def testCompactStruct(self): # test large field deltas (meaningful in CompactProto only) obj = self._deserialize(CompactProtoTestStruct, self._serialize(self.compact_struct)) self.assertEquals(obj, self.compact_struct) rep = repr(self.compact_struct) self.assertTrue(len(rep) > 0) def testIntegerLimits(self): if (sys.version_info[0] == 2 and sys.version_info[1] <= 6): print('Skipping testIntegerLimits for Python 2.6') return bad_values = [CompactProtoTestStruct(a_byte=128), CompactProtoTestStruct(a_byte=-129), CompactProtoTestStruct(a_i16=32768), CompactProtoTestStruct(a_i16=-32769), CompactProtoTestStruct(a_i32=2147483648), CompactProtoTestStruct(a_i32=-2147483649), CompactProtoTestStruct(a_i64=9223372036854775808), CompactProtoTestStruct(a_i64=-9223372036854775809) ] for value in bad_values: self.assertRaises(Exception, self._serialize, value) def testRecTree(self): """Ensure recursive tree node can be created.""" children = [] for idx in range(1, 5): node = RecTree(item=idx, children=None) children.append(node) parent = RecTree(item=0, children=children) serde_parent = self._deserialize(RecTree, self._serialize(parent)) self.assertEquals(0, serde_parent.item) self.assertEquals(4, len(serde_parent.children)) for child in serde_parent.children: # Cannot use assertIsInstance in python 2.6? self.assertTrue(isinstance(child, RecTree)) def _buildLinkedList(self): head = cur = RecList(item=0) for idx in range(1, 5): node = RecList(item=idx) cur.nextitem = node cur = node return head def _collapseLinkedList(self, head): out_list = [] cur = head while cur is not None: out_list.append(cur.item) cur = cur.nextitem return out_list def testRecList(self): """Ensure recursive linked list can be created.""" rec_list = self._buildLinkedList() serde_list = self._deserialize(RecList, self._serialize(rec_list)) out_list = self._collapseLinkedList(serde_list) self.assertEquals([0, 1, 2, 3, 4], out_list) def testCoRec(self): """Ensure co-recursive structures can be created.""" item1 = CoRec() item2 = CoRec2() item1.other = item2 item2.other = item1 # NOTE [econner724,2017-06-21]: These objects cannot be serialized as serialization # results in an infinite loop. fbthrift also suffers from this # problem. def testRecVector(self): """Ensure a list of recursive nodes can be created.""" mylist = [self._buildLinkedList(), self._buildLinkedList()] myvec = VectorTest(lister=mylist) serde_vec = self._deserialize(VectorTest, self._serialize(myvec)) golden_list = [0, 1, 2, 3, 4] for cur_list in serde_vec.lister: out_list = self._collapseLinkedList(cur_list) self.assertEqual(golden_list, out_list) class NormalBinaryTest(AbstractTest): protocol_factory = TBinaryProtocol.TBinaryProtocolFactory() class AcceleratedBinaryTest(AbstractTest): protocol_factory = TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False) class CompactProtocolTest(AbstractTest): protocol_factory = TCompactProtocol.TCompactProtocolFactory() class AcceleratedCompactTest(AbstractTest): protocol_factory = TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False) class JSONProtocolTest(AbstractTest): protocol_factory = TJSONProtocol.TJSONProtocolFactory() class AcceleratedFramedTest(unittest.TestCase): def testSplit(self): """Test FramedTransport and BinaryProtocolAccelerated Tests that TBinaryProtocolAccelerated and TFramedTransport play nicely together when a read spans a frame""" protocol_factory = TBinaryProtocol.TBinaryProtocolAcceleratedFactory() bigstring = "".join(chr(byte) for byte in range(ord("a"), ord("z") + 1)) databuf = TTransport.TMemoryBuffer() prot = protocol_factory.getProtocol(databuf) prot.writeI32(42) prot.writeString(bigstring) prot.writeI16(24) data = databuf.getvalue() cutpoint = len(data) // 2 parts = [data[:cutpoint], data[cutpoint:]] framed_buffer = TTransport.TMemoryBuffer() framed_writer = TTransport.TFramedTransport(framed_buffer) for part in parts: framed_writer.write(part) framed_writer.flush() self.assertEquals(len(framed_buffer.getvalue()), len(data) + 8) # Recreate framed_buffer so we can read from it. framed_buffer = TTransport.TMemoryBuffer(framed_buffer.getvalue()) framed_reader = TTransport.TFramedTransport(framed_buffer) prot = protocol_factory.getProtocol(framed_reader) self.assertEqual(prot.readI32(), 42) self.assertEqual(prot.readString(), bigstring) self.assertEqual(prot.readI16(), 24) class SerializersTest(unittest.TestCase): def testSerializeThenDeserialize(self): obj = Xtruct2(i32_thing=1, struct_thing=Xtruct(string_thing="foo")) s1 = serialize(obj) for i in range(10): self.assertEquals(s1, serialize(obj)) objcopy = Xtruct2() deserialize(objcopy, serialize(obj)) self.assertEquals(obj, objcopy) obj = Xtruct(string_thing="bar") objcopy = Xtruct() deserialize(objcopy, serialize(obj)) self.assertEquals(obj, objcopy) # test booleans obj = Bools(im_true=True, im_false=False) objcopy = Bools() deserialize(objcopy, serialize(obj)) self.assertEquals(obj, objcopy) # test enums def _enumerate_enum(enum_class): if hasattr(enum_class, '_VALUES_TO_NAMES'): # old-style enums for num, name in enum_class._VALUES_TO_NAMES.items(): yield (num, name) else: # assume Python 3.4+ IntEnum-based from enum import IntEnum self.assertTrue((issubclass(enum_class, IntEnum))) for num in enum_class: yield (num.value, num.name) for num, name in _enumerate_enum(Numberz): obj = Bonk(message='enum Numberz value %d is string %s' % (num, name), type=num) objcopy = Bonk() deserialize(objcopy, serialize(obj)) self.assertEquals(obj, objcopy) def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(NormalBinaryTest)) suite.addTest(loader.loadTestsFromTestCase(AcceleratedBinaryTest)) suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest)) suite.addTest(loader.loadTestsFromTestCase(CompactProtocolTest)) suite.addTest(loader.loadTestsFromTestCase(JSONProtocolTest)) suite.addTest(loader.loadTestsFromTestCase(AcceleratedFramedTest)) suite.addTest(loader.loadTestsFromTestCase(SerializersTest)) return suite if __name__ == "__main__": unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) thrift-0.19.0/test/py/explicit_module/0000777000000000000000000000000014452237057017711 5ustar00rootroot00000000000000thrift-0.19.0/test/py/explicit_module/shared_types.thrift0000644000000000000000000000157214452237057023626 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace py shared_types enum SharedEnum { SharedEnum0 = 0, SharedEnum1 = 1 } thrift-0.19.0/test/py/explicit_module/EnumSerializationTest.py0000644000000000000000000000656714452237057024577 0ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import annotations import sys from shared_types.ttypes import SharedEnum from thrift.TSerialization import serialize, deserialize from thrift.protocol import TBinaryProtocol from thrift.transport import TTransport def deserialize_immutable(base, buf, protocol_factory=TBinaryProtocol.TBinaryProtocolFactory()): transport = TTransport.TMemoryBuffer(buf) protocol = protocol_factory.getProtocol(transport) return base.read(protocol) def serialization_deserialization_struct_enum_test(): test_obj = TestStruct(param1="test_string", param2=TestEnum.TestEnum1, param3=SharedEnum.SharedEnum1) test_obj_serialized = serialize(test_obj) test_obj2 = deserialize(TestStruct(), test_obj_serialized) assert test_obj.param1 == test_obj2.param1 assert test_obj.param2 == test_obj2.param2 assert test_obj.param3 == test_obj2.param3 def serialization_deserialization_struct_enum_as_string_test(): test_obj = TestStruct(param1="test_string", param2=TestEnum.TestEnum1.name, param3=SharedEnum.SharedEnum1.name) test_obj_serialized = serialize(test_obj) test_obj2 = deserialize(TestStruct(), test_obj_serialized) assert test_obj.param1 == test_obj2.param1 assert test_obj.param2 == test_obj2.param2 assert test_obj.param3 == test_obj2.param3 def serialization_deserialization_exception_enum_as_string_test(): test_obj = TestException(whatOp=0, why=SharedEnum.SharedEnum0.name, who=TestEnum.TestEnum0.name) test_obj_serialized = serialize(test_obj) test_obj2 = deserialize_immutable(TestException, test_obj_serialized) assert test_obj.whatOp == test_obj2.whatOp assert test_obj.why == test_obj2.why assert test_obj.who == test_obj2.who def serialization_deserialization_exception_enum_test(): test_obj = TestException(whatOp=0, why=SharedEnum.SharedEnum0, who=TestEnum.TestEnum0) test_obj_serialized = serialize(test_obj) test_obj2 = deserialize_immutable(TestException, test_obj_serialized) assert test_obj.whatOp == test_obj2.whatOp assert test_obj.why == test_obj2.why assert test_obj.who == test_obj2.who if __name__ == "__main__": args = sys.argv[1:] if args: from test5_slots.test5.ttypes import TestEnum, TestStruct, TestException else: from test5.ttypes import TestEnum, TestStruct, TestException serialization_deserialization_struct_enum_test() serialization_deserialization_struct_enum_as_string_test() serialization_deserialization_exception_enum_as_string_test() serialization_deserialization_exception_enum_test()thrift-0.19.0/test/py/explicit_module/test2.thrift0000644000000000000000000000155614303740367022175 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ include "test1.thrift" struct another { 1: test1.astruct something; } thrift-0.19.0/test/py/explicit_module/test4.thrift0000644000000000000000000000205614452237057022175 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace py test4 include "shared_types.thrift" enum TestEnum { TestEnum0 = 0, TestEnum1 = 1, } const map typeConversion = { TestEnum.TestEnum0: shared_types.SharedEnum0, TestEnum.TestEnum1: shared_types.SharedEnum1, }thrift-0.19.0/test/py/explicit_module/runtest.sh0000755000000000000000000000375614452237057021763 0ustar00rootroot00000000000000#!/bin/bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # rm -rf gen-py ../../../compiler/cpp/thrift --gen py test1.thrift || exit 1 ../../../compiler/cpp/thrift --gen py test2.thrift || exit 1 ../../../compiler/cpp/thrift --gen py test3.thrift && exit 1 # Fail since test3.thrift has python keywords ../../../compiler/cpp/thrift --gen py:enum shared_types.thrift || exit 1 ../../../compiler/cpp/thrift --gen py:enum test4.thrift || exit 1 ../../../compiler/cpp/thrift --gen py:enum test5.thrift || exit 1 mkdir -p ./gen-py/test5_slots ../../../compiler/cpp/thrift --gen py:enum,slots -out ./gen-py/test5_slots test5.thrift || exit 1 PYTHONPATH=./gen-py python -c 'import foo.bar.baz' || exit 1 PYTHONPATH=./gen-py python -c 'import test2' || exit 1 PYTHONPATH=./gen-py python -c 'import test1' &>/dev/null && exit 1 # Should fail. PYTHONPATH=./gen-py python -c 'import test4.constants' || exit 1 PYTHONPATH=./gen-py python EnumSerializationTest.py || exit 1 PYTHONPATH=./gen-py python EnumSerializationTest.py slot|| exit 1 cp -r gen-py simple ../../../compiler/cpp/thrift -r --gen py test2.thrift || exit 1 PYTHONPATH=./gen-py python -c 'import test2' || exit 1 diff -ur simple gen-py > thediffs file thediffs | grep -s -q empty || exit 1 rm -rf simple thediffs echo 'All tests pass!' thrift-0.19.0/test/py/explicit_module/test5.thrift0000644000000000000000000000225614452237057022200 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace py test5 include "shared_types.thrift" enum TestEnum { TestEnum0 = 0, TestEnum1 = 1, } struct TestStruct { 1: optional string param1 2: optional TestEnum param2 3: optional shared_types.SharedEnum param3 } /** * Structs can also be exceptions, if they are nasty. */ exception TestException { 1: i32 whatOp, 2: shared_types.SharedEnum why 3: TestEnum who }thrift-0.19.0/test/py/explicit_module/test3.thrift0000644000000000000000000000153614303740367022174 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace py validations struct from { 1: i32 def; } thrift-0.19.0/test/py/explicit_module/test1.thrift0000644000000000000000000000155314303740367022171 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace py foo.bar.baz struct astruct { 1: i32 how_unoriginal; } thrift-0.19.0/test/py/generate.cmake0000644000000000000000000000532414370300523017303 0ustar00rootroot00000000000000macro(GENERATE FILENAME GENERATOR OUTPUTDIR) file(MAKE_DIRECTORY ${MY_CURRENT_BINARY_DIR}/${OUTPUTDIR}) execute_process(COMMAND ${THRIFTCOMPILER} --gen ${GENERATOR} -out ${MY_CURRENT_BINARY_DIR}/${OUTPUTDIR} ${FILENAME} RESULT_VARIABLE CMD_RESULT) if(CMD_RESULT) message(FATAL_ERROR "Error generating ${FILENAME} with generator ${GENERATOR}") endif() endmacro(GENERATE) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py gen-py-default) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py:slots gen-py-slots) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py:old_style gen-py-oldstyle) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py:no_utf8strings gen-py-no_utf8strings) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py:dynamic gen-py-dynamic) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py:dynamic,slots gen-py-dynamicslots) generate(${MY_PROJECT_DIR}/test/v0.16/ThriftTest.thrift py:enum gen-py-enum) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py gen-py-default) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py:slots gen-py-slots) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py:old_style gen-py-oldstyle) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py:no_utf8strings gen-py-no_utf8strings) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py:dynamic gen-py-dynamic) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py:dynamic,slots gen-py-dynamicslots) generate(${MY_PROJECT_DIR}/test/v0.16/DebugProtoTest.thrift py:enum gen-py-enum) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py gen-py-default) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:slots gen-py-slots) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:old_style gen-py-oldstyle) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:no_utf8strings gen-py-no_utf8strings) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic gen-py-dynamic) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:dynamic,slots gen-py-dynamicslots) generate(${MY_PROJECT_DIR}/test/DoubleConstantsTest.thrift py:enum gen-py-enum) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py gen-py-default) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:slots gen-py-slots) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:old_style gen-py-oldstyle) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:no_utf8strings gen-py-no_utf8strings) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:dynamic gen-py-dynamic) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:dynamic,slots gen-py-dynamicslots) generate(${MY_PROJECT_DIR}/test/Recursive.thrift py:enum gen-py-enum) thrift-0.19.0/test/py/util.py0000644000000000000000000000223114303740367016042 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import os import sys _SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) _ROOT_DIR = os.path.dirname(os.path.dirname(_SCRIPT_DIR)) def local_libpath(): globdir = os.path.join(_ROOT_DIR, 'lib', 'py', 'build', 'lib.*') for libpath in glob.glob(globdir): if libpath.endswith('-%d.%d' % (sys.version_info[0], sys.version_info[1])): return libpath thrift-0.19.0/test/py/TestSyntax.py0000777000000000000000000000172414062750227017226 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Just import these generated files to make sure they are syntactically valid from DebugProtoTest import EmptyService # noqa from DebugProtoTest import Inherited # noqa thrift-0.19.0/test/py/TestServer.py0000777000000000000000000003672314062750227017215 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import division import logging import os import signal import sys import time from optparse import OptionParser from util import local_libpath sys.path.insert(0, local_libpath()) from thrift.protocol import TProtocol, TProtocolDecorator SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) class TestHandler(object): def testVoid(self): if options.verbose > 1: logging.info('testVoid()') def testString(self, str): if options.verbose > 1: logging.info('testString(%s)' % str) return str def testBool(self, boolean): if options.verbose > 1: logging.info('testBool(%s)' % str(boolean).lower()) return boolean def testByte(self, byte): if options.verbose > 1: logging.info('testByte(%d)' % byte) return byte def testI16(self, i16): if options.verbose > 1: logging.info('testI16(%d)' % i16) return i16 def testI32(self, i32): if options.verbose > 1: logging.info('testI32(%d)' % i32) return i32 def testI64(self, i64): if options.verbose > 1: logging.info('testI64(%d)' % i64) return i64 def testDouble(self, dub): if options.verbose > 1: logging.info('testDouble(%f)' % dub) return dub def testBinary(self, thing): if options.verbose > 1: logging.info('testBinary()') # TODO: hex output return thing def testStruct(self, thing): if options.verbose > 1: logging.info('testStruct({%s, %s, %s, %s})' % (thing.string_thing, thing.byte_thing, thing.i32_thing, thing.i64_thing)) return thing def testException(self, arg): # if options.verbose > 1: logging.info('testException(%s)' % arg) if arg == 'Xception': raise Xception(errorCode=1001, message=arg) elif arg == 'TException': raise TException(message='This is a TException') def testMultiException(self, arg0, arg1): if options.verbose > 1: logging.info('testMultiException(%s, %s)' % (arg0, arg1)) if arg0 == 'Xception': raise Xception(errorCode=1001, message='This is an Xception') elif arg0 == 'Xception2': raise Xception2( errorCode=2002, struct_thing=Xtruct(string_thing='This is an Xception2')) return Xtruct(string_thing=arg1) def testOneway(self, seconds): if options.verbose > 1: logging.info('testOneway(%d) => sleeping...' % seconds) time.sleep(seconds / 3) # be quick if options.verbose > 1: logging.info('done sleeping') def testNest(self, thing): if options.verbose > 1: logging.info('testNest(%s)' % thing) return thing def testMap(self, thing): if options.verbose > 1: logging.info('testMap(%s)' % thing) return thing def testStringMap(self, thing): if options.verbose > 1: logging.info('testStringMap(%s)' % thing) return thing def testSet(self, thing): if options.verbose > 1: logging.info('testSet(%s)' % thing) return thing def testList(self, thing): if options.verbose > 1: logging.info('testList(%s)' % thing) return thing def testEnum(self, thing): if options.verbose > 1: logging.info('testEnum(%s)' % thing) return thing def testTypedef(self, thing): if options.verbose > 1: logging.info('testTypedef(%s)' % thing) return thing def testMapMap(self, thing): if options.verbose > 1: logging.info('testMapMap(%s)' % thing) return { -4: { -4: -4, -3: -3, -2: -2, -1: -1, }, 4: { 4: 4, 3: 3, 2: 2, 1: 1, }, } def testInsanity(self, argument): if options.verbose > 1: logging.info('testInsanity(%s)' % argument) return { 1: { 2: argument, 3: argument, }, 2: {6: Insanity()}, } def testMulti(self, arg0, arg1, arg2, arg3, arg4, arg5): if options.verbose > 1: logging.info('testMulti(%s, %s, %s, %s, %s, %s)' % (arg0, arg1, arg2, arg3, arg4, arg5)) return Xtruct(string_thing='Hello2', byte_thing=arg0, i32_thing=arg1, i64_thing=arg2) class SecondHandler(object): def secondtestString(self, argument): return "testString(\"" + argument + "\")" # LAST_SEQID is a global because we have one transport and multiple protocols # running on it (when multiplexed) LAST_SEQID = None class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): """ Wraps any protocol with sequence ID checking: looks for outbound uniqueness as well as request/response alignment. """ def __init__(self, protocol): # TProtocolDecorator.__new__ does all the heavy lifting pass def readMessageBegin(self): global LAST_SEQID (name, type, seqid) =\ super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() if LAST_SEQID is not None and LAST_SEQID == seqid: raise TProtocol.TProtocolException( TProtocol.TProtocolException.INVALID_DATA, "We received the same seqid {0} twice in a row".format(seqid)) LAST_SEQID = seqid return (name, type, seqid) def make_pedantic(proto): """ Wrap a protocol in the pedantic sequence ID wrapper. """ # NOTE: this is disabled for now as many clients send seqid # of zero and that is okay, need a way to identify # clients that MUST send seqid unique to function right # or just force all implementations to send unique seqids (preferred) return proto # TPedanticSequenceIdProtocolWrapper(proto) class TPedanticSequenceIdProtocolFactory(TProtocol.TProtocolFactory): def __init__(self, encapsulated): super(TPedanticSequenceIdProtocolFactory, self).__init__() self.encapsulated = encapsulated def getProtocol(self, trans): return make_pedantic(self.encapsulated.getProtocol(trans)) def main(options): # common header allowed client types allowed_client_types = [ THeaderTransport.THeaderClientType.HEADERS, THeaderTransport.THeaderClientType.FRAMED_BINARY, THeaderTransport.THeaderClientType.UNFRAMED_BINARY, THeaderTransport.THeaderClientType.FRAMED_COMPACT, THeaderTransport.THeaderClientType.UNFRAMED_COMPACT, ] # set up the protocol factory form the --protocol option prot_factories = { 'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(), 'multia': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(), 'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory(), 'multiac': TCompactProtocol.TCompactProtocolAcceleratedFactory(), 'binary': TPedanticSequenceIdProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()), 'multi': TPedanticSequenceIdProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()), 'compact': TCompactProtocol.TCompactProtocolFactory(), 'multic': TCompactProtocol.TCompactProtocolFactory(), 'header': THeaderProtocol.THeaderProtocolFactory(allowed_client_types), 'multih': THeaderProtocol.THeaderProtocolFactory(allowed_client_types), 'json': TJSONProtocol.TJSONProtocolFactory(), 'multij': TJSONProtocol.TJSONProtocolFactory(), } pfactory = prot_factories.get(options.proto, None) if pfactory is None: raise AssertionError('Unknown --protocol option: %s' % options.proto) try: pfactory.string_length_limit = options.string_limit pfactory.container_length_limit = options.container_limit except Exception: # Ignore errors for those protocols that does not support length limit pass # get the server type (TSimpleServer, TNonblockingServer, etc...) if len(args) > 1: raise AssertionError('Only one server type may be specified, not multiple types.') server_type = args[0] if options.trans == 'http': server_type = 'THttpServer' # Set up the handler and processor objects handler = TestHandler() processor = ThriftTest.Processor(handler) if options.proto.startswith('multi'): secondHandler = SecondHandler() secondProcessor = SecondService.Processor(secondHandler) multiplexedProcessor = TMultiplexedProcessor() multiplexedProcessor.registerDefault(processor) multiplexedProcessor.registerProcessor('ThriftTest', processor) multiplexedProcessor.registerProcessor('SecondService', secondProcessor) processor = multiplexedProcessor global server # Handle THttpServer as a special case if server_type == 'THttpServer': if options.ssl: __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "server.crt") __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "server.key") server = THttpServer.THttpServer(processor, ('', options.port), pfactory, cert_file=__certfile, key_file=__keyfile) else: server = THttpServer.THttpServer(processor, ('', options.port), pfactory) server.serve() sys.exit(0) # set up server transport and transport factory abs_key_path = os.path.join(os.path.dirname(SCRIPT_DIR), 'keys', 'server.pem') host = None if options.ssl: from thrift.transport import TSSLSocket transport = TSSLSocket.TSSLServerSocket(host, options.port, certfile=abs_key_path) else: transport = TSocket.TServerSocket(host, options.port, options.domain_socket) tfactory = TTransport.TBufferedTransportFactory() if options.trans == 'buffered': tfactory = TTransport.TBufferedTransportFactory() elif options.trans == 'framed': tfactory = TTransport.TFramedTransportFactory() elif options.trans == '': raise AssertionError('Unknown --transport option: %s' % options.trans) else: tfactory = TTransport.TBufferedTransportFactory() # if --zlib, then wrap server transport, and use a different transport factory if options.zlib: transport = TZlibTransport.TZlibTransport(transport) # wrap with zlib tfactory = TZlibTransport.TZlibTransportFactory() # do server-specific setup here: if server_type == "TNonblockingServer": server = TNonblockingServer.TNonblockingServer(processor, transport, inputProtocolFactory=pfactory) elif server_type == "TProcessPoolServer": import signal from thrift.server import TProcessPoolServer server = TProcessPoolServer.TProcessPoolServer(processor, transport, tfactory, pfactory) server.setNumWorkers(5) def set_alarm(): def clean_shutdown(signum, frame): for worker in server.workers: if options.verbose > 0: logging.info('Terminating worker: %s' % worker) worker.terminate() if options.verbose > 0: logging.info('Requesting server to stop()') try: server.stop() except Exception: pass signal.signal(signal.SIGALRM, clean_shutdown) signal.alarm(4) set_alarm() else: # look up server class dynamically to instantiate server ServerClass = getattr(TServer, server_type) server = ServerClass(processor, transport, tfactory, pfactory) # enter server main loop server.serve() def exit_gracefully(signum, frame): print("SIGINT received\n") server.shutdown() # doesn't work properly, yet sys.exit(0) if __name__ == '__main__': signal.signal(signal.SIGINT, exit_gracefully) parser = OptionParser() parser.add_option('--libpydir', type='string', dest='libpydir', help='include this directory to sys.path for locating library code') parser.add_option('--genpydir', type='string', dest='genpydir', default='gen-py', help='include this directory to sys.path for locating generated code') parser.add_option("--port", type="int", dest="port", help="port number for server to listen on") parser.add_option("--zlib", action="store_true", dest="zlib", help="use zlib wrapper for compressed transport") parser.add_option("--ssl", action="store_true", dest="ssl", help="use SSL for encrypted transport") parser.add_option('-v', '--verbose', action="store_const", dest="verbose", const=2, help="verbose output") parser.add_option('-q', '--quiet', action="store_const", dest="verbose", const=0, help="minimal output") parser.add_option('--protocol', dest="proto", type="string", help="protocol to use, one of: accel, accelc, binary, compact, json, multi, multia, multiac, multic, multih, multij") parser.add_option('--transport', dest="trans", type="string", help="transport to use, one of: buffered, framed, http") parser.add_option('--domain-socket', dest="domain_socket", type="string", help="Unix domain socket path") parser.add_option('--container-limit', dest='container_limit', type='int', default=None) parser.add_option('--string-limit', dest='string_limit', type='int', default=None) parser.set_defaults(port=9090, verbose=1, proto='binary', transport='buffered') options, args = parser.parse_args() # Print TServer log to stdout so that the test-runner can redirect it to log files logging.basicConfig(level=options.verbose) sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir)) from ThriftTest import ThriftTest, SecondService from ThriftTest.ttypes import Xtruct, Xception, Xception2, Insanity from thrift.Thrift import TException from thrift.TMultiplexedProcessor import TMultiplexedProcessor from thrift.transport import THeaderTransport from thrift.transport import TTransport from thrift.transport import TSocket from thrift.transport import TZlibTransport from thrift.protocol import TBinaryProtocol from thrift.protocol import TCompactProtocol from thrift.protocol import THeaderProtocol from thrift.protocol import TJSONProtocol from thrift.server import TServer, TNonblockingServer, THttpServer sys.exit(main(options)) thrift-0.19.0/test/py/TSimpleJSONProtocolTest.py0000644000000000000000000000755714303740367021536 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from ThriftTest.ttypes import Bonk, VersioningTestV1, VersioningTestV2 from thrift.protocol import TJSONProtocol from thrift.transport import TTransport import json import unittest class SimpleJSONProtocolTest(unittest.TestCase): protocol_factory = TJSONProtocol.TSimpleJSONProtocolFactory() def _assertDictEqual(self, a, b, msg=None): if hasattr(self, 'assertDictEqual'): # assertDictEqual only in Python 2.7. Depends on your machine. self.assertDictEqual(a, b, msg) return # Substitute implementation not as good as unittest library's self.assertEquals(len(a), len(b), msg) for k, v in a.iteritems(): self.assertTrue(k in b, msg) self.assertEquals(b.get(k), v, msg) def _serialize(self, obj): trans = TTransport.TMemoryBuffer() prot = self.protocol_factory.getProtocol(trans) obj.write(prot) return trans.getvalue() def _deserialize(self, objtype, data): prot = self.protocol_factory.getProtocol(TTransport.TMemoryBuffer(data)) ret = objtype() ret.read(prot) return ret def testWriteOnly(self): self.assertRaises(NotImplementedError, self._deserialize, VersioningTestV1, b'{}') def testSimpleMessage(self): v1obj = VersioningTestV1( begin_in_both=12345, old_string='aaa', end_in_both=54321) expected = dict(begin_in_both=v1obj.begin_in_both, old_string=v1obj.old_string, end_in_both=v1obj.end_in_both) actual = json.loads(self._serialize(v1obj).decode('ascii')) self._assertDictEqual(expected, actual) def testComplicated(self): v2obj = VersioningTestV2( begin_in_both=12345, newint=1, newbyte=2, newshort=3, newlong=4, newdouble=5.0, newstruct=Bonk(message="Hello!", type=123), newlist=[7, 8, 9], newset=set([42, 1, 8]), newmap={1: 2, 2: 3}, newstring="Hola!", end_in_both=54321) expected = dict(begin_in_both=v2obj.begin_in_both, newint=v2obj.newint, newbyte=v2obj.newbyte, newshort=v2obj.newshort, newlong=v2obj.newlong, newdouble=v2obj.newdouble, newstruct=dict(message=v2obj.newstruct.message, type=v2obj.newstruct.type), newlist=v2obj.newlist, newset=list(v2obj.newset), newmap=v2obj.newmap, newstring=v2obj.newstring, end_in_both=v2obj.end_in_both) # Need to load/dump because map keys get escaped. expected = json.loads(json.dumps(expected)) actual = json.loads(self._serialize(v2obj).decode('ascii')) self._assertDictEqual(expected, actual) if __name__ == '__main__': unittest.main() thrift-0.19.0/test/py/RunClientServer.py0000777000000000000000000003037114303472263020171 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import division from __future__ import print_function import platform import copy import os import signal import socket import subprocess import sys import time from optparse import OptionParser from util import local_libpath SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) SCRIPTS = [ 'FastbinaryTest.py', 'TestFrozen.py', 'TestRenderedDoubleConstants.py', 'TSimpleJSONProtocolTest.py', 'SerializationTest.py', 'TestEof.py', 'TestSyntax.py', 'TestSocket.py', ] FRAMED = ["TNonblockingServer"] SKIP_ZLIB = ['TNonblockingServer', 'THttpServer'] SKIP_SSL = ['THttpServer'] EXTRA_DELAY = dict(TProcessPoolServer=5.5) PROTOS = [ 'accel', 'accelc', 'binary', 'compact', 'json', 'header', ] def default_servers(): servers = [ 'TSimpleServer', 'TThreadedServer', 'TThreadPoolServer', 'TNonblockingServer', 'THttpServer', ] if platform.system() != 'Windows': servers.append('TProcessPoolServer') servers.append('TForkingServer') return servers def relfile(fname): return os.path.join(SCRIPT_DIR, fname) def setup_pypath(libdir, gendir): dirs = [libdir, gendir] env = copy.deepcopy(os.environ) pypath = env.get('PYTHONPATH', None) if pypath: dirs.append(pypath) env['PYTHONPATH'] = os.pathsep.join(dirs) if gendir.endswith('gen-py-no_utf8strings'): env['THRIFT_TEST_PY_NO_UTF8STRINGS'] = '1' return env def runScriptTest(libdir, genbase, genpydir, script): env = setup_pypath(libdir, os.path.join(genbase, genpydir)) script_args = [sys.executable, relfile(script)] print('\nTesting script: %s\n----' % (' '.join(script_args))) ret = subprocess.call(script_args, env=env) if ret != 0: print('*** FAILED ***', file=sys.stderr) print('LIBDIR: %s' % libdir, file=sys.stderr) print('PY_GEN: %s' % genpydir, file=sys.stderr) print('SCRIPT: %s' % script, file=sys.stderr) raise Exception("Script subprocess failed, retcode=%d, args: %s" % (ret, ' '.join(script_args))) def runServiceTest(libdir, genbase, genpydir, server_class, proto, port, use_zlib, use_ssl, verbose): env = setup_pypath(libdir, os.path.join(genbase, genpydir)) # Build command line arguments server_args = [sys.executable, relfile('TestServer.py')] cli_args = [sys.executable, relfile('TestClient.py')] for which in (server_args, cli_args): which.append('--protocol=%s' % proto) # accel, binary, compact or json which.append('--port=%d' % port) # default to 9090 if use_zlib: which.append('--zlib') if use_ssl: which.append('--ssl') if verbose == 0: which.append('-q') if verbose == 2: which.append('-v') # server-specific option to select server class server_args.append(server_class) # client-specific cmdline options if server_class in FRAMED: cli_args.append('--transport=framed') else: cli_args.append('--transport=buffered') if server_class == 'THttpServer': cli_args.append('--http=/') if verbose > 0: print('Testing server %s: %s' % (server_class, ' '.join(server_args))) serverproc = subprocess.Popen(server_args, env=env) def ensureServerAlive(): if serverproc.poll() is not None: print(('FAIL: Server process (%s) failed with retcode %d') % (' '.join(server_args), serverproc.returncode)) raise Exception('Server subprocess %s died, args: %s' % (server_class, ' '.join(server_args))) # Wait for the server to start accepting connections on the given port. sleep_time = 0.1 # Seconds max_attempts = 100 attempt = 0 while True: sock4 = socket.socket() sock6 = socket.socket(socket.AF_INET6) try: if sock4.connect_ex(('127.0.0.1', port)) == 0 \ or sock6.connect_ex(('::1', port)) == 0: break attempt += 1 if attempt >= max_attempts: raise Exception("TestServer not ready on port %d after %.2f seconds" % (port, sleep_time * attempt)) ensureServerAlive() time.sleep(sleep_time) finally: sock4.close() sock6.close() try: if verbose > 0: print('Testing client: %s' % (' '.join(cli_args))) ret = subprocess.call(cli_args, env=env) if ret != 0: print('*** FAILED ***', file=sys.stderr) print('LIBDIR: %s' % libdir, file=sys.stderr) print('PY_GEN: %s' % genpydir, file=sys.stderr) raise Exception("Client subprocess failed, retcode=%d, args: %s" % (ret, ' '.join(cli_args))) finally: # check that server didn't die ensureServerAlive() extra_sleep = EXTRA_DELAY.get(server_class, 0) if extra_sleep > 0 and verbose > 0: print('Giving %s (proto=%s,zlib=%s,ssl=%s) an extra %d seconds for child' 'processes to terminate via alarm' % (server_class, proto, use_zlib, use_ssl, extra_sleep)) time.sleep(extra_sleep) sig = signal.SIGKILL if platform.system() != 'Windows' else signal.SIGABRT os.kill(serverproc.pid, sig) serverproc.wait() class TestCases(object): def __init__(self, genbase, libdir, port, gendirs, servers, verbose): self.genbase = genbase self.libdir = libdir self.port = port self.verbose = verbose self.gendirs = gendirs self.servers = servers def default_conf(self): return { 'gendir': self.gendirs[0], 'server': self.servers[0], 'proto': PROTOS[0], 'zlib': False, 'ssl': False, } def run(self, conf, test_count): with_zlib = conf['zlib'] with_ssl = conf['ssl'] try_server = conf['server'] try_proto = conf['proto'] genpydir = conf['gendir'] # skip any servers that don't work with the Zlib transport if with_zlib and try_server in SKIP_ZLIB: return False # skip any servers that don't work with SSL if with_ssl and try_server in SKIP_SSL: return False if self.verbose > 0: print('\nTest run #%d: (includes %s) Server=%s, Proto=%s, zlib=%s, SSL=%s' % (test_count, genpydir, try_server, try_proto, with_zlib, with_ssl)) runServiceTest(self.libdir, self.genbase, genpydir, try_server, try_proto, self.port, with_zlib, with_ssl, self.verbose) if self.verbose > 0: print('OK: Finished (includes %s) %s / %s proto / zlib=%s / SSL=%s. %d combinations tested.' % (genpydir, try_server, try_proto, with_zlib, with_ssl, test_count)) return True def test_feature(self, name, values): test_count = 0 conf = self.default_conf() for try_server in values: conf[name] = try_server if self.run(conf, test_count): test_count += 1 return test_count def run_all_tests(self): test_count = 0 for try_server in self.servers: for genpydir in self.gendirs: for try_proto in PROTOS: for with_zlib in (False, True): # skip any servers that don't work with the Zlib transport if with_zlib and try_server in SKIP_ZLIB: continue for with_ssl in (False, True): # skip any servers that don't work with SSL if with_ssl and try_server in SKIP_SSL: continue test_count += 1 if self.verbose > 0: print('\nTest run #%d: (includes %s) Server=%s, Proto=%s, zlib=%s, SSL=%s' % (test_count, genpydir, try_server, try_proto, with_zlib, with_ssl)) runServiceTest(self.libdir, self.genbase, genpydir, try_server, try_proto, self.port, with_zlib, with_ssl) if self.verbose > 0: print('OK: Finished (includes %s) %s / %s proto / zlib=%s / SSL=%s. %d combinations tested.' % (genpydir, try_server, try_proto, with_zlib, with_ssl, test_count)) return test_count def main(): parser = OptionParser() parser.add_option('--all', action="store_true", dest='all') parser.add_option('--genpydirs', type='string', dest='genpydirs', default='default,slots,oldstyle,no_utf8strings,dynamic,dynamicslots,enum', help='directory extensions for generated code, used as suffixes for \"gen-py-*\" added sys.path for individual tests') parser.add_option("--port", type="int", dest="port", default=9090, help="port number for server to listen on") parser.add_option('-v', '--verbose', action="store_const", dest="verbose", const=2, help="verbose output") parser.add_option('-q', '--quiet', action="store_const", dest="verbose", const=0, help="minimal output") parser.add_option('-L', '--libdir', dest="libdir", default=local_libpath(), help="directory path that contains Thrift Python library") parser.add_option('--gen-base', dest="gen_base", default=SCRIPT_DIR, help="directory path that contains Thrift Python library") parser.set_defaults(verbose=1) options, args = parser.parse_args() generated_dirs = [] for gp_dir in options.genpydirs.split(','): generated_dirs.append('gen-py-%s' % (gp_dir)) # commandline permits a single class name to be specified to override SERVERS=[...] servers = default_servers() if len(args) == 1: if args[0] in servers: servers = args else: print('Unavailable server type "%s", please choose one of: %s' % (args[0], servers)) sys.exit(0) tests = TestCases(options.gen_base, options.libdir, options.port, generated_dirs, servers, options.verbose) # run tests without a client/server first print('----------------') print(' Executing individual test scripts with various generated code directories') print(' Directories to be tested: ' + ', '.join(generated_dirs)) print(' Scripts to be tested: ' + ', '.join(SCRIPTS)) print('----------------') for genpydir in generated_dirs: for script in SCRIPTS: runScriptTest(options.libdir, options.gen_base, genpydir, script) print('----------------') print(' Executing Client/Server tests with various generated code directories') print(' Servers to be tested: ' + ', '.join(servers)) print(' Directories to be tested: ' + ', '.join(generated_dirs)) print(' Protocols to be tested: ' + ', '.join(PROTOS)) print(' Options to be tested: ZLIB(yes/no), SSL(yes/no)') print('----------------') if options.all: tests.run_all_tests() else: tests.test_feature('gendir', generated_dirs) tests.test_feature('server', servers) tests.test_feature('proto', PROTOS) tests.test_feature('zlib', [False, True]) tests.test_feature('ssl', [False, True]) if __name__ == '__main__': sys.exit(main()) thrift-0.19.0/test/py/Makefile.in0000644000000000000000000006231614472652521016573 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/py ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = serial-tests py_unit_tests = RunClientServer.py thrift_gen = \ gen-py/ThriftTest/__init__.py \ gen-py/DebugProtoTest/__init__.py \ gen-py/DoubleConstantsTest/__init__.py \ gen-py/Recursive/__init__.py \ gen-py-default/ThriftTest/__init__.py \ gen-py-default/DebugProtoTest/__init__.py \ gen-py-default/DoubleConstantsTest/__init__.py \ gen-py-default/Recursive/__init__.py \ gen-py-slots/ThriftTest/__init__.py \ gen-py-slots/DebugProtoTest/__init__.py \ gen-py-slots/DoubleConstantsTest/__init__.py \ gen-py-slots/Recursive/__init__.py \ gen-py-oldstyle/ThriftTest/__init__.py \ gen-py-oldstyle/DebugProtoTest/__init__.py \ gen-py-oldstyle/DoubleConstantsTest/__init__.py \ gen-py-oldstyle/Recursive/__init__.py \ gen-py-no_utf8strings/ThriftTest/__init__.py \ gen-py-no_utf8strings/DebugProtoTest/__init__.py \ gen-py-no_utf8strings/DoubleConstantsTest/__init__.py \ gen-py-no_utf8strings/Recursive/__init__.py \ gen-py-dynamic/ThriftTest/__init__.py \ gen-py-dynamic/DebugProtoTest/__init__.py \ gen-py-dynamic/DoubleConstantsTest/__init__.py \ gen-py-dynamic/Recursive/__init__.py \ gen-py-dynamicslots/ThriftTest/__init__.py \ gen-py-dynamicslots/DebugProtoTest/__init__.py \ gen-py-dynamicslots/DoubleConstantsTest/__init__.py \ gen-py-dynamicslots/Recursive/__init__.py \ gen-py-enum/ThriftTest/__init__.py \ gen-py-enum/DebugProtoTest/__init__.py \ gen-py-enum/DoubleConstantsTest/__init__.py \ gen-py-enum/Recursive/__init__.py BUILT_SOURCES = $(thrift_gen) helper_scripts = \ TestClient.py \ TestServer.py check_SCRIPTS = \ $(thrift_gen) \ $(py_unit_tests) \ $(helper_scripts) TESTS = $(py_unit_tests) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/py/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/py/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check check-am install install-am install-strip .PHONY: all all-am check check-TESTS check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile precross: $(thrift_gen) gen-py/%/__init__.py: ../%.thrift $(THRIFT) test -f ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py $< gen-py-default/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-default || $(MKDIR_P) gen-py-default test -f ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py -out gen-py-default ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py -out gen-py-default $< gen-py-slots/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-slots || $(MKDIR_P) gen-py-slots test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:slots -out gen-py-slots ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:slots -out gen-py-slots $< gen-py-oldstyle/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-oldstyle || $(MKDIR_P) gen-py-oldstyle test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:old_style -out gen-py-oldstyle ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:old_style -out gen-py-oldstyle $< gen-py-no_utf8strings/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-no_utf8strings || $(MKDIR_P) gen-py-no_utf8strings test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:no_utf8strings -out gen-py-no_utf8strings $< gen-py-dynamic/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-dynamic || $(MKDIR_P) gen-py-dynamic test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:dynamic -out gen-py-dynamic ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:dynamic -out gen-py-dynamic $< gen-py-dynamicslots/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-dynamicslots || $(MKDIR_P) gen-py-dynamicslots test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots $< gen-py-enum/%/__init__.py: ../%.thrift $(THRIFT) test -d gen-py-enum || $(MKDIR_P) gen-py-enum test ../v0.16/$(notdir $<) \ && $(THRIFT) --gen py:enum -out gen-py-enum ../v0.16/$(notdir $<) \ || $(THRIFT) --gen py:enum -out gen-py-enum $< clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/py/TestSocket.py0000777000000000000000000000457214062750227017174 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from thrift.transport import TSocket import unittest import time import socket import random class TimeoutTest(unittest.TestCase): def setUp(self): for i in range(50): try: # find a port we can use self.listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.port = random.randint(10000, 30000) self.listen_sock.bind(('localhost', self.port)) self.listen_sock.listen(5) break except Exception: if i == 49: raise def testConnectTimeout(self): starttime = time.time() try: leaky = [] for i in range(100): socket = TSocket.TSocket('localhost', self.port) socket.setTimeout(10) socket.open() leaky.append(socket) except Exception: self.assert_(time.time() - starttime < 5.0) def testWriteTimeout(self): starttime = time.time() try: socket = TSocket.TSocket('localhost', self.port) socket.setTimeout(10) socket.open() lsock = self.listen_sock.accept() while True: lsock.write("hi" * 100) except Exception: self.assert_(time.time() - starttime < 5.0) if __name__ == '__main__': suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(TimeoutTest)) testRunner = unittest.TextTestRunner(verbosity=2) testRunner.run(suite) thrift-0.19.0/test/py/TestFrozen.py0000777000000000000000000001260214102321351017163 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from DebugProtoTest import Srv from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty, Wrapper from DebugProtoTest.ttypes import ExceptionWithAMap, MutableException, ExceptionWithoutFields from thrift.Thrift import TFrozenDict from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol, TCompactProtocol import collections import unittest class TestFrozenBase(unittest.TestCase): def _roundtrip(self, src, dst): otrans = TTransport.TMemoryBuffer() optoro = self.protocol(otrans) src.write(optoro) itrans = TTransport.TMemoryBuffer(otrans.getvalue()) iproto = self.protocol(itrans) return dst.read(iproto) or dst def test_dict_is_hashable_only_after_frozen(self): d0 = {} self.assertFalse(isinstance(d0, collections.Hashable)) d1 = TFrozenDict(d0) self.assertTrue(isinstance(d1, collections.Hashable)) def test_struct_with_collection_fields(self): pass def test_set(self): """Test that annotated set field can be serialized and deserialized""" x = CompactProtoTestStruct(set_byte_map={ frozenset([42, 100, -100]): 99, frozenset([0]): 100, frozenset([]): 0, }) x2 = self._roundtrip(x, CompactProtoTestStruct()) self.assertEqual(x2.set_byte_map[frozenset([42, 100, -100])], 99) self.assertEqual(x2.set_byte_map[frozenset([0])], 100) self.assertEqual(x2.set_byte_map[frozenset([])], 0) def test_map(self): """Test that annotated map field can be serialized and deserialized""" x = CompactProtoTestStruct(map_byte_map={ TFrozenDict({42: 42, 100: -100}): 99, TFrozenDict({0: 0}): 100, TFrozenDict({}): 0, }) x2 = self._roundtrip(x, CompactProtoTestStruct()) self.assertEqual(x2.map_byte_map[TFrozenDict({42: 42, 100: -100})], 99) self.assertEqual(x2.map_byte_map[TFrozenDict({0: 0})], 100) self.assertEqual(x2.map_byte_map[TFrozenDict({})], 0) def test_list(self): """Test that annotated list field can be serialized and deserialized""" x = CompactProtoTestStruct(list_byte_map={ (42, 100, -100): 99, (0,): 100, (): 0, }) x2 = self._roundtrip(x, CompactProtoTestStruct()) self.assertEqual(x2.list_byte_map[(42, 100, -100)], 99) self.assertEqual(x2.list_byte_map[(0,)], 100) self.assertEqual(x2.list_byte_map[()], 0) def test_empty_struct(self): """Test that annotated empty struct can be serialized and deserialized""" x = CompactProtoTestStruct(empty_struct_field=Empty()) x2 = self._roundtrip(x, CompactProtoTestStruct()) self.assertEqual(x2.empty_struct_field, Empty()) def test_struct(self): """Test that annotated struct can be serialized and deserialized""" x = Wrapper(foo=Empty()) self.assertEqual(x.foo, Empty()) x2 = self._roundtrip(x, Wrapper) self.assertEqual(x2.foo, Empty()) def test_frozen_exception(self): exc = ExceptionWithAMap(blah='foo') with self.assertRaises(TypeError): exc.blah = 'bar' mutexc = MutableException(msg='foo') mutexc.msg = 'bar' self.assertEqual(mutexc.msg, 'bar') def test_frozen_exception_with_no_fields(self): ExceptionWithoutFields() def test_frozen_exception_serialization(self): result = Srv.declaredExceptionMethod_result( xwamap=ExceptionWithAMap(blah="error")) deserialized = self._roundtrip( result, Srv.declaredExceptionMethod_result()) self.assertEqual(result, deserialized) class TestFrozen(TestFrozenBase): def protocol(self, trans): return TBinaryProtocol.TBinaryProtocolFactory().getProtocol(trans) class TestFrozenAcceleratedBinary(TestFrozenBase): def protocol(self, trans): return TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(trans) class TestFrozenAcceleratedCompact(TestFrozenBase): def protocol(self, trans): return TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(trans) def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(TestFrozen)) suite.addTest(loader.loadTestsFromTestCase(TestFrozenAcceleratedBinary)) suite.addTest(loader.loadTestsFromTestCase(TestFrozenAcceleratedCompact)) return suite if __name__ == "__main__": unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) thrift-0.19.0/test/py/TestClient.py0000755000000000000000000005542714452237057017167 0ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import os import sys import time import unittest from optparse import OptionParser from util import local_libpath sys.path.insert(0, local_libpath()) from thrift.protocol import TProtocol, TProtocolDecorator SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) class AbstractTest(unittest.TestCase): def setUp(self): if options.trans == 'http': uri = '{0}://{1}:{2}{3}'.format(('https' if options.ssl else 'http'), options.host, options.port, (options.http_path if options.http_path else '/')) if options.ssl: __cafile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "CA.pem") __certfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "client.crt") __keyfile = os.path.join(os.path.dirname(SCRIPT_DIR), "keys", "client.key") self.transport = THttpClient.THttpClient(uri, cafile=__cafile, cert_file=__certfile, key_file=__keyfile) else: self.transport = THttpClient.THttpClient(uri) else: if options.ssl: from thrift.transport import TSSLSocket socket = TSSLSocket.TSSLSocket(options.host, options.port, validate=False) else: socket = TSocket.TSocket(options.host, options.port, options.domain_socket) # frame or buffer depending upon args self.transport = TTransport.TBufferedTransport(socket) if options.trans == 'framed': self.transport = TTransport.TFramedTransport(socket) elif options.trans == 'buffered': self.transport = TTransport.TBufferedTransport(socket) elif options.trans == '': raise AssertionError('Unknown --transport option: %s' % options.trans) if options.zlib: self.transport = TZlibTransport.TZlibTransport(self.transport, 9) self.transport.open() protocol = self.get_protocol(self.transport) self.client = ThriftTest.Client(protocol) # for multiplexed services: protocol2 = self.get_protocol2(self.transport) self.client2 = SecondService.Client(protocol2) if protocol2 is not None else None def tearDown(self): self.transport.close() def testVoid(self): print('testVoid') self.client.testVoid() def testString(self): print('testString') self.assertEqual(self.client.testString('Python' * 20), 'Python' * 20) self.assertEqual(self.client.testString(''), '') s1 = u'\b\t\n/\\\\\r{}:パイソン"' s2 = u"""Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪ Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語""" if sys.version_info[0] == 2 and os.environ.get('THRIFT_TEST_PY_NO_UTF8STRINGS'): s1 = s1.encode('utf8') s2 = s2.encode('utf8') self.assertEqual(self.client.testString(s1), s1) self.assertEqual(self.client.testString(s2), s2) def testMultiplexed(self): if self.client2 is not None: print('testMultiplexed') self.assertEqual(self.client2.secondtestString('foobar'), 'testString("foobar")') def testBool(self): print('testBool') self.assertEqual(self.client.testBool(True), True) self.assertEqual(self.client.testBool(False), False) def testByte(self): print('testByte') self.assertEqual(self.client.testByte(63), 63) self.assertEqual(self.client.testByte(-127), -127) def testI32(self): print('testI32') self.assertEqual(self.client.testI32(-1), -1) self.assertEqual(self.client.testI32(0), 0) def testI64(self): print('testI64') self.assertEqual(self.client.testI64(1), 1) self.assertEqual(self.client.testI64(-34359738368), -34359738368) def testDouble(self): print('testDouble') self.assertEqual(self.client.testDouble(-5.235098235), -5.235098235) self.assertEqual(self.client.testDouble(0), 0) self.assertEqual(self.client.testDouble(-1), -1) self.assertEqual(self.client.testDouble(-0.000341012439638598279), -0.000341012439638598279) def testBinary(self): print('testBinary') val = bytearray([i for i in range(0, 256)]) self.assertEqual(bytearray(self.client.testBinary(bytes(val))), val) def testStruct(self): print('testStruct') x = Xtruct() x.string_thing = "Zero" x.byte_thing = 1 x.i32_thing = -3 x.i64_thing = -5 y = self.client.testStruct(x) self.assertEqual(y, x) def testNest(self): print('testNest') inner = Xtruct(string_thing="Zero", byte_thing=1, i32_thing=-3, i64_thing=-5) x = Xtruct2(struct_thing=inner, byte_thing=0, i32_thing=0) y = self.client.testNest(x) self.assertEqual(y, x) def testMap(self): print('testMap') x = {0: 1, 1: 2, 2: 3, 3: 4, -1: -2} y = self.client.testMap(x) self.assertEqual(y, x) def testSet(self): print('testSet') x = set([8, 1, 42]) y = self.client.testSet(x) self.assertEqual(y, x) def testList(self): print('testList') x = [1, 4, 9, -42] y = self.client.testList(x) self.assertEqual(y, x) def testEnum(self): print('testEnum') x = Numberz.FIVE y = self.client.testEnum(x) self.assertEqual(y, x) def testTypedef(self): print('testTypedef') x = 0xffffffffffffff # 7 bytes of 0xff y = self.client.testTypedef(x) self.assertEqual(y, x) def testMapMap(self): print('testMapMap') x = { -4: {-4: -4, -3: -3, -2: -2, -1: -1}, 4: {4: 4, 3: 3, 2: 2, 1: 1}, } y = self.client.testMapMap(42) self.assertEqual(y, x) def testMulti(self): print('testMulti') xpected = Xtruct(string_thing='Hello2', byte_thing=74, i32_thing=0xff00ff, i64_thing=0xffffffffd0d0) y = self.client.testMulti(xpected.byte_thing, xpected.i32_thing, xpected.i64_thing, {0: 'abc'}, Numberz.FIVE, 0xf0f0f0) self.assertEqual(y, xpected) def testException(self): print('testException') self.client.testException('Safe') try: self.client.testException('Xception') self.fail("should have gotten exception") except Xception as x: self.assertEqual(x.errorCode, 1001) self.assertEqual(x.message, 'Xception') # TODO ensure same behavior for repr within generated python variants # ensure exception's repr method works # x_repr = repr(x) # self.assertEqual(x_repr, 'Xception(errorCode=1001, message=\'Xception\')') try: self.client.testException('TException') self.fail("should have gotten exception") except TException as x: pass # Should not throw self.client.testException('success') def testMultiException(self): print('testMultiException') try: self.client.testMultiException('Xception', 'ignore') except Xception as ex: self.assertEqual(ex.errorCode, 1001) self.assertEqual(ex.message, 'This is an Xception') try: self.client.testMultiException('Xception2', 'ignore') except Xception2 as ex: self.assertEqual(ex.errorCode, 2002) self.assertEqual(ex.struct_thing.string_thing, 'This is an Xception2') y = self.client.testMultiException('success', 'foobar') self.assertEqual(y.string_thing, 'foobar') def testException__traceback__(self): print('testException__traceback__') self.client.testException('Safe') expect_slots = uses_slots = False expect_dynamic = uses_dynamic = False try: self.client.testException('Xception') self.fail("should have gotten exception") except Xception as x: uses_slots = hasattr(x, '__slots__') uses_dynamic = (not isinstance(x, TException)) # We set expected values here so that we get clean tracebackes when # the assertions fail. try: x.__traceback__ = x.__traceback__ # If `__traceback__` was set without errors than we expect that # the slots option was used and that dynamic classes were not. expect_slots = True expect_dynamic = False except Exception as e: self.assertTrue(isinstance(e, TypeError)) # There are no other meaningful tests we can preform because we # are unable to determine the desired state of either `__slots__` # or `dynamic`. return self.assertEqual(expect_slots, uses_slots) self.assertEqual(expect_dynamic, uses_dynamic) def testOneway(self): print('testOneway') start = time.time() self.client.testOneway(1) # type is int, not float end = time.time() self.assertTrue(end - start < 3, "oneway sleep took %f sec" % (end - start)) def testOnewayThenNormal(self): print('testOnewayThenNormal') self.client.testOneway(1) # type is int, not float self.assertEqual(self.client.testString('Python'), 'Python') # LAST_SEQID is a global because we have one transport and multiple protocols # running on it (when multiplexed) LAST_SEQID = None class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): """ Wraps any protocol with sequence ID checking: looks for outbound uniqueness as well as request/response alignment. """ def __init__(self, protocol): # TProtocolDecorator.__new__ does all the heavy lifting pass def writeMessageBegin(self, name, type, seqid): global LAST_SEQID if LAST_SEQID and LAST_SEQID == seqid: raise TProtocol.TProtocolException( TProtocol.TProtocolException.INVALID_DATA, "Python client reused sequence ID {0}".format(seqid)) LAST_SEQID = seqid super(TPedanticSequenceIdProtocolWrapper, self).writeMessageBegin( name, type, seqid) def readMessageBegin(self): global LAST_SEQID (name, type, seqid) =\ super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() if LAST_SEQID != seqid: raise TProtocol.TProtocolException( TProtocol.TProtocolException.INVALID_DATA, "We sent seqid {0} and server returned seqid {1}".format( self.last, seqid)) return (name, type, seqid) def make_pedantic(proto): """ Wrap a protocol in the pedantic sequence ID wrapper. """ return TPedanticSequenceIdProtocolWrapper(proto) class MultiplexedOptionalTest(AbstractTest): def get_protocol2(self, transport): return None class BinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): return make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) class MultiplexedBinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class AcceleratedBinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): return make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) class MultiplexedAcceleratedBinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class CompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): return make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) class MultiplexedCompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class AcceleratedCompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): return make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) class MultiplexedAcceleratedCompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class JSONTest(MultiplexedOptionalTest): def get_protocol(self, transport): return make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) class MultiplexedJSONTest(MultiplexedOptionalTest): def get_protocol(self, transport): wrapped_proto = make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): wrapped_proto = make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class HeaderTest(MultiplexedOptionalTest): def get_protocol(self, transport): factory = THeaderProtocol.THeaderProtocolFactory() return make_pedantic(factory.getProtocol(transport)) class MultiplexedHeaderTest(MultiplexedOptionalTest): def get_protocol(self, transport): wrapped_proto = make_pedantic(THeaderProtocol.THeaderProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): wrapped_proto = make_pedantic(THeaderProtocol.THeaderProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() if options.proto == 'binary': # look for --proto on cmdline suite.addTest(loader.loadTestsFromTestCase(BinaryTest)) elif options.proto == 'accel': suite.addTest(loader.loadTestsFromTestCase(AcceleratedBinaryTest)) elif options.proto == 'accelc': suite.addTest(loader.loadTestsFromTestCase(AcceleratedCompactTest)) elif options.proto == 'compact': suite.addTest(loader.loadTestsFromTestCase(CompactTest)) elif options.proto == 'header': suite.addTest(loader.loadTestsFromTestCase(HeaderTest)) elif options.proto == 'json': suite.addTest(loader.loadTestsFromTestCase(JSONTest)) elif options.proto == 'multi': suite.addTest(loader.loadTestsFromTestCase(MultiplexedBinaryTest)) elif options.proto == 'multia': suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedBinaryTest)) elif options.proto == 'multiac': suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedCompactTest)) elif options.proto == 'multic': suite.addTest(loader.loadTestsFromTestCase(MultiplexedCompactTest)) elif options.proto == 'multih': suite.addTest(loader.loadTestsFromTestCase(MultiplexedHeaderTest)) elif options.proto == 'multij': suite.addTest(loader.loadTestsFromTestCase(MultiplexedJSONTest)) else: raise AssertionError('Unknown protocol given with --protocol: %s' % options.proto) return suite class OwnArgsTestProgram(unittest.TestProgram): def parseArgs(self, argv): if args: self.testNames = args else: self.testNames = ([self.defaultTest]) self.createTests() if __name__ == "__main__": parser = OptionParser() parser.add_option('--libpydir', type='string', dest='libpydir', help='include this directory in sys.path for locating library code') parser.add_option('--genpydir', type='string', dest='genpydir', help='include this directory in sys.path for locating generated code') parser.add_option("--port", type="int", dest="port", help="connect to server at port") parser.add_option("--host", type="string", dest="host", help="connect to server") parser.add_option("--zlib", action="store_true", dest="zlib", help="use zlib wrapper for compressed transport") parser.add_option("--ssl", action="store_true", dest="ssl", help="use SSL for encrypted transport") parser.add_option("--http", dest="http_path", help="Use the HTTP transport with the specified path") parser.add_option('-v', '--verbose', action="store_const", dest="verbose", const=2, help="verbose output") parser.add_option('-q', '--quiet', action="store_const", dest="verbose", const=0, help="minimal output") parser.add_option('--protocol', dest="proto", type="string", help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multih, multij") parser.add_option('--transport', dest="trans", type="string", help="transport to use, one of: buffered, framed, http") parser.add_option('--domain-socket', dest="domain_socket", type="string", help="Unix domain socket path") parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary') options, args = parser.parse_args() if options.genpydir: sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir)) if options.http_path: options.trans = 'http' from ThriftTest import SecondService from ThriftTest import ThriftTest from ThriftTest.ttypes import Xtruct, Xtruct2, Numberz, Xception, Xception2 from thrift.Thrift import TException from thrift.transport import TTransport from thrift.transport import TSocket from thrift.transport import THttpClient from thrift.transport import TZlibTransport from thrift.protocol import TBinaryProtocol from thrift.protocol import TCompactProtocol from thrift.protocol import THeaderProtocol from thrift.protocol import TJSONProtocol from thrift.protocol import TMultiplexedProtocol OwnArgsTestProgram(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=1)) thrift-0.19.0/test/ManyOptionals.thrift0000644000000000000000000001021014303740367020076 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // The java codegenerator has a few different codepaths depending // on how many optionals the struct has; this attempts to exercise // them. namespace java thrift.test struct Opt4 { 1: i32 def1; 2: i32 def2; 3: i32 def3; 4: i32 def4; } struct Opt13 { 1: i32 def1; 2: i32 def2; 3: i32 def3; 4: i32 def4; 5: i32 def5; 6: i32 def6; 7: i32 def7; 8: i32 def8; 9: i32 def9; 10: i32 def10; 11: i32 def11; 12: i32 def12; 13: i32 def13; } struct Opt30 { 1: i32 def1; 2: i32 def2; 3: i32 def3; 4: i32 def4; 5: i32 def5; 6: i32 def6; 7: i32 def7; 8: i32 def8; 9: i32 def9; 10: i32 def10; 11: i32 def11; 12: i32 def12; 13: i32 def13; 14: i32 def14; 15: i32 def15; 16: i32 def16; 17: i32 def17; 18: i32 def18; 19: i32 def19; 20: i32 def20; 21: i32 def21; 22: i32 def22; 23: i32 def23; 24: i32 def24; 25: i32 def25; 26: i32 def26; 27: i32 def27; 28: i32 def28; 29: i32 def29; 30: i32 def30; } struct Opt64 { 1: i32 def1; 2: i32 def2; 3: i32 def3; 4: i32 def4; 5: i32 def5; 6: i32 def6; 7: i32 def7; 8: i32 def8; 9: i32 def9; 10: i32 def10; 11: i32 def11; 12: i32 def12; 13: i32 def13; 14: i32 def14; 15: i32 def15; 16: i32 def16; 17: i32 def17; 18: i32 def18; 19: i32 def19; 20: i32 def20; 21: i32 def21; 22: i32 def22; 23: i32 def23; 24: i32 def24; 25: i32 def25; 26: i32 def26; 27: i32 def27; 28: i32 def28; 29: i32 def29; 30: i32 def30; 31: i32 def31; 32: i32 def32; 33: i32 def33; 34: i32 def34; 35: i32 def35; 36: i32 def36; 37: i32 def37; 38: i32 def38; 39: i32 def39; 40: i32 def40; 41: i32 def41; 42: i32 def42; 43: i32 def43; 44: i32 def44; 45: i32 def45; 46: i32 def46; 47: i32 def47; 48: i32 def48; 49: i32 def49; 50: i32 def50; 51: i32 def51; 52: i32 def52; 53: i32 def53; 54: i32 def54; 55: i32 def55; 56: i32 def56; 57: i32 def57; 58: i32 def58; 59: i32 def59; 60: i32 def60; 61: i32 def61; 62: i32 def62; 63: i32 def63; 64: i32 def64; } struct Opt80 { 1: i32 def1; 2: i32 def2; 3: i32 def3; 4: i32 def4; 5: i32 def5; 6: i32 def6; 7: i32 def7; 8: i32 def8; 9: i32 def9; 10: i32 def10; 11: i32 def11; 12: i32 def12; 13: i32 def13; 14: i32 def14; 15: i32 def15; 16: i32 def16; 17: i32 def17; 18: i32 def18; 19: i32 def19; 20: i32 def20; 21: i32 def21; 22: i32 def22; 23: i32 def23; 24: i32 def24; 25: i32 def25; 26: i32 def26; 27: i32 def27; 28: i32 def28; 29: i32 def29; 30: i32 def30; 31: i32 def31; 32: i32 def32; 33: i32 def33; 34: i32 def34; 35: i32 def35; 36: i32 def36; 37: i32 def37; 38: i32 def38; 39: i32 def39; 40: i32 def40; 41: i32 def41; 42: i32 def42; 43: i32 def43; 44: i32 def44; 45: i32 def45; 46: i32 def46; 47: i32 def47; 48: i32 def48; 49: i32 def49; 50: i32 def50; 51: i32 def51; 52: i32 def52; 53: i32 def53; 54: i32 def54; 55: i32 def55; 56: i32 def56; 57: i32 def57; 58: i32 def58; 59: i32 def59; 60: i32 def60; 61: i32 def61; 62: i32 def62; 63: i32 def63; 64: i32 def64; 65: i32 def65; 66: i32 def66; 67: i32 def67; 68: i32 def68; 69: i32 def69; 70: i32 def70; 71: i32 def71; 72: i32 def72; 73: i32 def73; 74: i32 def74; 75: i32 def75; 76: i32 def76; 77: i32 def77; 78: i32 def78; 79: i32 def79; 80: i32 def80; } thrift-0.19.0/test/swift/0000755000000000000000000000000014472652607015227 5ustar00rootroot00000000000000thrift-0.19.0/test/swift/Makefile.am0000644000000000000000000000152314370300523017244 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = CrossTests precross: $(MAKE) -C CrossTests precross thrift-0.19.0/test/swift/Makefile0000644000000000000000000005747714472652607016713 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/swift/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/swift ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/swift abs_srcdir = /thrift/src/test/swift abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. SUBDIRS = CrossTests all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/swift/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/swift/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile precross: $(MAKE) -C CrossTests precross # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/swift/Makefile.in0000644000000000000000000005660414472652521017302 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/swift ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = CrossTests all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/swift/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/swift/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile precross: $(MAKE) -C CrossTests precross # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/swift/CrossTests/0000755000000000000000000000000014472652607017343 5ustar00rootroot00000000000000thrift-0.19.0/test/swift/CrossTests/Sources/0000755000000000000000000000000014370300523020746 5ustar00rootroot00000000000000thrift-0.19.0/test/swift/CrossTests/Sources/TestClient/0000755000000000000000000000000014370300523023024 5ustar00rootroot00000000000000thrift-0.19.0/test/swift/CrossTests/Sources/TestClient/main.swift0000644000000000000000000002762214370300523025037 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. import Foundation import Thrift import Common import XCTest enum Error: Int32 { case baseTypes = 1 case structs = 2 case containers = 4 case exceptions = 8 case unknown = 64 case timeout = 128 } class TestClient { var client: ThriftTestClient var resultCode: Int32 = 0 public init(parameters: TestClientParameters) throws { let transport = try TestClient.getTransport(parameters: parameters) let proto = try TestClient.getProtocol(parameters: parameters, transport: transport) client = ThriftTestClient(inoutProtocol: proto) } static func getTransport(parameters: TestClientParameters) throws -> TTransport { let socketTransport = try TSocketTransport(hostname: parameters.host!, port: parameters.port!) if parameters.transport == .framed { return TFramedTransport(transport: socketTransport) } if parameters.transport == .buffered { return socketTransport } throw ParserError.unsupportedOption } static func getProtocol(parameters: TestClientParameters, transport: TTransport) throws -> TProtocol { if parameters.proto == .binary { return TBinaryProtocol(on: transport) } if parameters.proto == .compact { return TCompactProtocol(on: transport) } throw ParserError.unsupportedOption } func run() throws { do { try testVoid() try testString() try testBool() try testByte() try testI32() try testI64() try testDouble() try testBinary() try testStruct() try testNest() try testMap() try testSet() try testList() try testEnum() try testTypedef() try testMapMap() try testInsanity() try testMulti() try testException() try testMultiException() // Swift generator doesn't yet support one way functions (THRIFT-5468) /*try testOneway() try testOnewayThenNormal()*/ try testUuid() } catch let error { print("\(error)") resultCode |= Error.unknown.rawValue } exit(resultCode) } func testVoid() throws { print("testVoid") try client.testVoid() } func testString1(_ s1: String) throws { print("testString(\(s1))") let r1 = try client.testString(thing: s1) print(r1) if s1 != r1 { resultCode |= Error.baseTypes.rawValue } } func testString() throws { try testString1(String(repeating: "Python", count: 20)) try testString1("") try testString1("\t\n/\\\\\r{}:パイソン") try testString1(""" Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪ Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語 """) } func testBool1(_ s1: Bool) throws { print("testBool(\(s1))") let r1 = try client.testBool(thing: s1) print(r1) if s1 != r1 { resultCode |= Error.baseTypes.rawValue } } func testBool() throws { try testBool1(true) try testBool1(false) } func testByte() throws { print("testByte") if try client.testByte(thing: 63) != 63 { resultCode |= Error.baseTypes.rawValue } if try client.testByte(thing: -127) != -127 { resultCode |= Error.baseTypes.rawValue } } func testI32() throws { print("testI32") if try client.testI32(thing: -1) != -1 { resultCode |= Error.baseTypes.rawValue } if try client.testI32(thing: 0) != 0 { resultCode |= Error.baseTypes.rawValue } } func testI64() throws { print("testI64") if try client.testI64(thing: 1) != 1 || client.testI64(thing: -34359738368) != -34359738368 { resultCode |= Error.baseTypes.rawValue } } func testDouble() throws { print("testDouble") for testValue in [-5.235098235, 0, -1, -0.000341012439638598279] { if try client.testDouble(thing: testValue) != testValue { resultCode |= Error.baseTypes.rawValue } } } func testBinary() throws { print("testBinary") let val = Data(Array(0...255)) if try client.testBinary(thing: val) != val { resultCode |= Error.baseTypes.rawValue } } func testStruct() throws { print("testStruct") let x = Xtruct(string_thing: "Zero", byte_thing: 1, i32_thing: -3, i64_thing: -5) if try client.testStruct(thing: x) != x { resultCode |= Error.structs.rawValue } } func testNest() throws { print("testNest") let inner = Xtruct(string_thing: "Zero", byte_thing: 1, i32_thing: -3, i64_thing: -5) let x = Xtruct2(byte_thing: 0, struct_thing: inner, i32_thing: 0) if try client.testNest(thing: x) != x { resultCode |= Error.structs.rawValue } } func testMap() throws { print("testMap") let x = TMap([0: 1, 1: 2, 2: 3, 3: 4, -1: -2]) if try client.testMap(thing: x) != x { resultCode |= Error.containers.rawValue } } func testSet() throws { print("testSet") let x = TSet([8, 1, 42]) if try client.testSet(thing: x) != x { resultCode |= Error.containers.rawValue } } func testList() throws { print("testList") let x = TList([1, 4, 9, -42]) if try client.testList(thing: x) != x { resultCode |= Error.containers.rawValue } } func testEnum() throws { print("testEnum") let x = Numberz.five if try client.testEnum(thing: x) != x { resultCode |= Error.containers.rawValue } } func testTypedef() throws { print("testTypedef") let x = UserId(bitPattern: 0xffffffffffffff) if try client.testTypedef(thing: x) != x { resultCode |= Error.containers.rawValue } } func testMapMap() throws { print("testMapMap") let x = TMap>([ -4: [-4: -4, -3: -3, -2: -2, -1: -1], 4: [4: 4, 3: 3, 2: 2, 1: 1] ]) if try client.testMapMap(hello: 42) != x { resultCode |= Error.containers.rawValue } } func testInsanity() throws { print("testInsanity()") let argument = Insanity(userMap: [.eight: 8], xtructs: []) let expected = TMap>([ 1: [ .two: argument, .three: argument ], 2: [ .six: Insanity(userMap: [:], xtructs: []) ] ]) if try client.testInsanity(argument: argument) != expected { resultCode |= Error.containers.rawValue } } func testMulti() throws { print("testMulti") let x = Xtruct(string_thing: "Hello2", byte_thing: 74, i32_thing: 0xff00ff, i64_thing: 0xffffffffd0d0) if try client.testMulti(arg0: x.byte_thing, arg1: x.i32_thing, arg2: x.i64_thing, arg3: .init([0: "abc"]), arg4: Numberz.five, arg5: 0xf0f0f0) != x { resultCode |= Error.containers.rawValue } } func testException() throws { print("testException") try client.testException(arg: "Safe") do { try client.testException(arg: "Xception") resultCode |= Error.exceptions.rawValue } catch let error as Xception { guard error.errorCode == 1001, error.message == "Xception" else { resultCode |= Error.exceptions.rawValue return } } catch { resultCode |= Error.exceptions.rawValue } do { try client.testException(arg: "TException") resultCode |= Error.exceptions.rawValue } catch is TError { } catch { resultCode |= Error.exceptions.rawValue } try client.testException(arg: "success") } func testMultiException() throws { print("testMultiException") do { _ = try client.testMultiException(arg0: "Xception", arg1: "ignore") } catch let error as Xception { guard error.errorCode == 1001, error.message == "This is an Xception" else { resultCode |= Error.exceptions.rawValue return } } catch { resultCode |= Error.exceptions.rawValue } do { _ = try client.testMultiException(arg0: "Xception2", arg1: "ignore") } catch let error as Xception2 { guard error.errorCode == 2002, error.struct_thing.string_thing == "This is an Xception2" else { resultCode |= Error.exceptions.rawValue return } } let y = try client.testMultiException(arg0: "success", arg1: "foobar") if y.string_thing != "foobar" { resultCode |= Error.exceptions.rawValue } } // Swift generator doesn't yet support one way functions (THRIFT-5468) /*func testOneway() throws { print("testOneway") let start = CACurrentMediaTime() try client.testOneway(secondsToSleep: 1) let end = CACurrentMediaTime() let duration = end - start let delta = abs(1 - duration) print("oneway sleep took \(end - start) sec") guard delta < 0.5 else { print("oneway sleep took \(end - start) sec") resultCode |= Error.unknown.rawValue return } } func testOnewayThenNormal() throws { print("testOnewayThenNormal") try client.testOneway(secondsToSleep: 1) if try client.testString(thing: "Swift") != "Swift" { resultCode |= Error.baseTypes.rawValue } }*/ func testUuid() throws { let uuid = UUID() guard try client.testUuid(thing: uuid) == uuid else { resultCode |= Error.baseTypes.rawValue return } } } let parameters = try TestClientParameters(arguments: CommandLine.arguments) if parameters.showHelp { parameters.printHelp() exit(0) } Thread.sleep(forTimeInterval: 1) try TestClient(parameters: parameters).run() thrift-0.19.0/test/swift/CrossTests/Sources/TestServer/0000755000000000000000000000000014370300523023054 5ustar00rootroot00000000000000thrift-0.19.0/test/swift/CrossTests/Sources/TestServer/main.swift0000644000000000000000000000411714370300523025061 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. import Foundation import Thrift import Common class TestServer { var server: Any? func run() throws { let parameters = try TestServerParameters(arguments: CommandLine.arguments) if parameters.showHelp { parameters.printHelp() return } let service = ThriftTestImpl() let processor = ThriftTestProcessor(service: service) switch (parameters.proto, parameters.transport) { case (.binary, .buffered): let proto = TBinaryProtocol.self server = try TSocketServer(port: parameters.port!, inProtocol: proto, outProtocol: proto, processor: processor) case (.binary, .framed): let proto = TBinaryProtocol.self server = try TFramedSocketServer(port: parameters.port!, inProtocol: proto, outProtocol: proto, processor: processor) case (.compact, .buffered): let proto = TCompactProtocol.self server = try TSocketServer(port: parameters.port!, inProtocol: proto, outProtocol: proto, processor: processor) case (.compact, .framed): let proto = TCompactProtocol.self server = try TFramedSocketServer(port: parameters.port!, inProtocol: proto, outProtocol: proto, processor: processor) default: throw ParserError.unsupportedOption } } } let server = TestServer() try server.run() RunLoop.main.run() thrift-0.19.0/test/swift/CrossTests/Sources/TestServer/ThriftTestService.swift0000644000000000000000000002720114370300523027555 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. import Foundation import Thrift import Common class ThriftTestImpl : ThriftTest { /// Prints "testVoid()" and returns nothing. /// /// - Throws: func testVoid() throws { print("testVoid()") } /// Prints 'testString("%s")' with thing as '%s' /// @param string thing - the string to print /// @return string - returns the string 'thing' /// /// - Parameters: /// - thing: /// - Returns: String /// - Throws: func testString(thing: String) throws -> String { print("testString(\"\(thing)\")") return thing } /// Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false' /// @param bool thing - the bool data to print /// @return bool - returns the bool 'thing' /// /// - Parameters: /// - thing: /// - Returns: Bool /// - Throws: func testBool(thing: Bool) throws -> Bool { print("testBool\"(\(thing ? "true" : "false")\")") return thing } /// Prints 'testByte("%d")' with thing as '%d' /// The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility. /// @param byte thing - the i8/byte to print /// @return i8 - returns the i8/byte 'thing' /// /// - Parameters: /// - thing: /// - Returns: Int8 /// - Throws: func testByte(thing: Int8) throws -> Int8 { print("testByte(\"\(thing)\")") return thing } /// Prints 'testI32("%d")' with thing as '%d' /// @param i32 thing - the i32 to print /// @return i32 - returns the i32 'thing' /// /// - Parameters: /// - thing: /// - Returns: Int32 /// - Throws: func testI32(thing: Int32) throws -> Int32 { print("testI32(\"\(thing)\")") return thing } /// Prints 'testI64("%d")' with thing as '%d' /// @param i64 thing - the i64 to print /// @return i64 - returns the i64 'thing' /// /// - Parameters: /// - thing: /// - Returns: Int64 /// - Throws: func testI64(thing: Int64) throws -> Int64 { print("testI64(\"\(thing)\")") return thing } /// Prints 'testDouble("%f")' with thing as '%f' /// @param double thing - the double to print /// @return double - returns the double 'thing' /// /// - Parameters: /// - thing: /// - Returns: Double /// - Throws: func testDouble(thing: Double) throws -> Double { print("testDouble(\"\(thing)\")") return thing } /// Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data /// @param binary thing - the binary data to print /// @return binary - returns the binary 'thing' /// /// - Parameters: /// - thing: /// - Returns: Data /// - Throws: func testBinary(thing: Data) throws -> Data { print("testBinary(\"\(thing)\")") return thing } /// Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values /// @param Xtruct thing - the Xtruct to print /// @return Xtruct - returns the Xtruct 'thing' /// /// - Parameters: /// - thing: /// - Returns: Xtruct /// - Throws: func testStruct(thing: Xtruct) throws -> Xtruct { print("testStruct({\([thing.string_thing, "\(thing.byte_thing)", "\(thing.i32_thing)", "\(thing.i64_thing)"].joined(separator: ", "))})") return thing } /// Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct /// @param Xtruct2 thing - the Xtruct2 to print /// @return Xtruct2 - returns the Xtruct2 'thing' /// /// - Parameters: /// - thing: /// - Returns: Xtruct2 /// - Throws: func testNest(thing: Xtruct2) throws -> Xtruct2 { print("testNest(\(thing)") return thing } /// Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs /// separated by commas and new lines /// @param map thing - the map to print /// @return map - returns the map 'thing' /// /// - Parameters: /// - thing: /// - Returns: TMap /// - Throws: func testMap(thing: TMap) throws -> TMap { print("testMap(\(thing)") return thing } /// Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs /// separated by commas and new lines /// @param map thing - the map to print /// @return map - returns the map 'thing' /// /// - Parameters: /// - thing: /// - Returns: TMap /// - Throws: func testStringMap(thing: TMap) throws -> TMap { print("testStringMap(\(thing)") return thing } /// Prints 'testSet("{%s}")' where thing has been formatted into a string of values /// separated by commas and new lines /// @param set thing - the set to print /// @return set - returns the set 'thing' /// /// - Parameters: /// - thing: /// - Returns: TSet /// - Throws: func testSet(thing: TSet) throws -> TSet { print("testSet\(thing)") return thing } /// Prints 'testList("{%s}")' where thing has been formatted into a string of values /// separated by commas and new lines /// @param list thing - the list to print /// @return list - returns the list 'thing' /// /// - Parameters: /// - thing: /// - Returns: TList /// - Throws: func testList(thing: TList) throws -> TList { print("testList\(thing)") return thing } /// Prints 'testEnum("%d")' where thing has been formatted into its numeric value /// @param Numberz thing - the Numberz to print /// @return Numberz - returns the Numberz 'thing' /// /// - Parameters: /// - thing: /// - Returns: Numberz /// - Throws: func testEnum(thing: Numberz) throws -> Numberz { print("testEnum\(thing.rawValue)") return thing } /// Prints 'testTypedef("%d")' with thing as '%d' /// @param UserId thing - the UserId to print /// @return UserId - returns the UserId 'thing' /// /// - Parameters: /// - thing: /// - Returns: UserId /// - Throws: func testTypedef(thing: UserId) throws -> UserId { print("testTypedef(\(thing)") return thing } /// Prints 'testMapMap("%d")' with hello as '%d' /// @param i32 hello - the i32 to print /// @return map> - returns a dictionary with these values: /// {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } /// /// - Parameters: /// - hello: /// - Returns: TMap> /// - Throws: func testMapMap(hello: Int32) throws -> TMap> { print("testMapMap(\(hello)") return TMap>([ -4: [-4: -4, -3: -3, -2: -2, -1: -1], 4: [4: 4, 3: 3, 2: 2, 1: 1] ]) } /// So you think you've got this all worked out, eh? /// Creates a map with these values and prints it out: /// { 1 => { 2 => argument, /// 3 => argument, /// }, /// 2 => { 6 => , }, /// } /// @return map> - a map with the above values /// /// - Parameters: /// - argument: /// - Returns: TMap> /// - Throws: func testInsanity(argument: Insanity) throws -> TMap> { return TMap>([ 1: [ .two: argument, .three: argument ], 2: [ .six: Insanity(userMap: [:], xtructs: []) ] ]) } /// Prints 'testMulti()' /// @param i8 arg0 - /// @param i32 arg1 - /// @param i64 arg2 - /// @param map arg3 - /// @param Numberz arg4 - /// @param UserId arg5 - /// @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 /// and i64_thing = arg2 /// /// - Parameters: /// - arg0: /// - arg1: /// - arg2: /// - arg3: /// - arg4: /// - arg5: /// - Returns: Xtruct /// - Throws: func testMulti(arg0: Int8, arg1: Int32, arg2: Int64, arg3: TMap, arg4: Numberz, arg5: UserId) throws -> Xtruct { print("testMulti()") return Xtruct(string_thing: "Hello2", byte_thing: arg0, i32_thing: arg1, i64_thing: arg2) } /// Print 'testException(%s)' with arg as '%s' /// @param string arg - a string indication what type of exception to throw /// if arg == "Xception" throw Xception with errorCode = 1001 and message = arg /// else if arg == "TException" throw TException /// else do not throw anything /// /// - Parameters: /// - arg: /// - Throws: Xception func testException(arg: String) throws { print("testException(\(arg)") if arg == "Xception" { throw Xception(errorCode: 1001, message: arg) } else if arg == "TException" { throw TApplicationError() // is type TError (TException Swift equiv) } } /// Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' /// @param string arg - a string indicating what type of exception to throw /// if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" /// else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2" /// else do not throw anything /// @return Xtruct - an Xtruct with string_thing = arg1 /// /// - Parameters: /// - arg0: /// - arg1: /// - Returns: Xtruct /// - Throws: Xception, Xception2 func testMultiException(arg0: String, arg1: String) throws -> Xtruct { print("testMultiException(\(arg0), \(arg1)") if arg0 == "Xception" { throw Xception(errorCode: 1001, message: "This is an Xception") } else if arg0 == "Xception2" { throw Xception2(errorCode: 2002, struct_thing: Xtruct(string_thing: "This is an Xception2", byte_thing: 0, i32_thing: 0, i64_thing: 0)) } return Xtruct(string_thing: arg1, byte_thing: 0, i32_thing: 0, i64_thing: 0) } /// Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' /// sleep 'secondsToSleep' /// Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' /// @param i32 secondsToSleep - the number of seconds to sleep /// /// - Parameters: /// - secondsToSleep: /// - Throws: func testOneway(secondsToSleep: Int32) throws { print("testOneway(\(secondsToSleep): Sleeping...") Thread.sleep(forTimeInterval: TimeInterval(secondsToSleep)) } func testUuid(thing: UUID) throws -> UUID { print("testUuid(\(thing))") return thing } } class SecondServiceImpl : SecondService { /// Prints 'testString("%s")' with thing as '%s' /// @param string thing - the string to print /// @return string - returns the string 'thing' /// /// - Parameters: /// - thing: /// - Returns: String /// - Throws: func secondtestString(thing: String) throws -> String { print("testString(\"\(thing)\")") return thing } } thrift-0.19.0/test/swift/CrossTests/Sources/Common/0000755000000000000000000000000014370300523022176 5ustar00rootroot00000000000000thrift-0.19.0/test/swift/CrossTests/Sources/Common/Parameters.swift0000644000000000000000000002117114370300523025361 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. import Foundation import Thrift public enum Protocol: String { case binary case compact case header case json } public enum Transport: String { case buffered case framed case http case anonpipe case zlib } public enum ServerType: String { case simple case threadPool = "thread-pool" case threaded case nonblocking } public enum ParserError: Error { case unknownArgument(argument: String) case missingParameter(argument: String) case invalidParameter(argument: String, parameter: String) case unsupportedOption } public class ParametersBase { public var showHelp = false public var port: Int? public var domainSocket: String? public var namedPipe: String? public var proto: Protocol? public var transport: Transport? public var multiplex = false public var abstractNamespace = false public var ssl = false public var zlib = false public init (arguments: [String]) throws { if arguments.count > 1 { for argument in arguments[1...] { let equalSignPos = argument.firstIndex(of: "=") ?? argument.endIndex let name = String(argument[..&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/swift/CrossTests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/swift/CrossTests abs_srcdir = /thrift/src/test/swift/CrossTests abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../../ top_builddir = ../../.. top_srcdir = ../../.. TESTTHRIFT = ../../ThriftTest.thrift all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/swift/CrossTests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/swift/CrossTests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: $(THRIFT) $(TESTTHRIFT) $(THRIFT) -o Sources/Common --gen swift $(TESTTHRIFT) precross: stubs swift build check: stubs clean-local: $(RM) -r Sources/Common/gen-swift/ dist-hook: $(RM) -r $(distdir)/gen-swift/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/swift/CrossTests/Makefile.in0000644000000000000000000004277014472652521021415 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/swift/CrossTests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ TESTTHRIFT = ../../ThriftTest.thrift all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/swift/CrossTests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/swift/CrossTests/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: $(THRIFT) $(TESTTHRIFT) $(THRIFT) -o Sources/Common --gen swift $(TESTTHRIFT) precross: stubs swift build check: stubs clean-local: $(RM) -r Sources/Common/gen-swift/ dist-hook: $(RM) -r $(distdir)/gen-swift/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/FullCamelTest.thrift0000644000000000000000000000220414303740367020011 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test.fullcamel struct OneOfEachZZ { 1: bool im_true, 2: bool im_false, 3: byte a_bite, 4: i16 integer16, 5: i32 integer32, 6: i64 integer64, 7: double double_precision, 8: string some_characters, 9: string zomg_unicode, 10: bool what_who, } service UnderscoreSrv { i64 some_rpc_call(1: string message) } thrift-0.19.0/test/py.twisted/0000777000000000000000000000000014472652606016210 5ustar00rootroot00000000000000thrift-0.19.0/test/py.twisted/Makefile.am0000644000000000000000000000254014370300523020222 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # TRIAL ?= trial stubs: ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen py:twisted ../v0.16/ThriftTest.thrift $(THRIFT) --gen py:twisted ../SmallTest.thrift check: stubs $(TRIAL) ./test_suite.py clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ thrift-0.19.0/test/py.twisted/setup.cfg0000644000000000000000000000005514303740367020020 0ustar00rootroot00000000000000[flake8] ignore = E402 max-line-length = 100 thrift-0.19.0/test/py.twisted/Makefile0000644000000000000000000004437114472652606017655 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/py.twisted/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/py.twisted ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/py.twisted abs_srcdir = /thrift/src/test/py.twisted abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/py.twisted/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/py.twisted/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile TRIAL ?= trial stubs: ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen py:twisted ../v0.16/ThriftTest.thrift $(THRIFT) --gen py:twisted ../SmallTest.thrift check: stubs $(TRIAL) ./test_suite.py clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/py.twisted/test_suite.py0000777000000000000000000001312614062750227020751 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import os import sys import time basepath = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(0, os.path.join(basepath, 'gen-py.twisted')) sys.path.insert(0, glob.glob(os.path.join(basepath, '../../lib/py/build/lib.*'))[0]) from thrift.Thrift import TApplicationException from ThriftTest import ThriftTest from ThriftTest.ttypes import Xception, Xtruct from thrift.transport import TTwisted from thrift.protocol import TBinaryProtocol from twisted.trial import unittest from twisted.internet import defer, reactor from twisted.internet.protocol import ClientCreator from zope.interface import implementer @implementer(ThriftTest.Iface) class TestHandler: def __init__(self): self.onewaysQueue = defer.DeferredQueue() def testVoid(self): pass def testString(self, s): return s def testByte(self, b): return b def testI16(self, i16): return i16 def testI32(self, i32): return i32 def testI64(self, i64): return i64 def testDouble(self, dub): return dub def testBinary(self, thing): return thing def testStruct(self, thing): return thing def testException(self, s): if s == 'Xception': raise Xception(1001, s) elif s == "throw_undeclared": raise ValueError("foo") def testOneway(self, seconds): def fireOneway(t): self.onewaysQueue.put((t, time.time(), seconds)) reactor.callLater(seconds, fireOneway, time.time()) raise Exception('') def testNest(self, thing): return thing def testMap(self, thing): return thing def testSet(self, thing): return thing def testList(self, thing): return thing def testEnum(self, thing): return thing def testTypedef(self, thing): return thing class ThriftTestCase(unittest.TestCase): @defer.inlineCallbacks def setUp(self): self.handler = TestHandler() self.processor = ThriftTest.Processor(self.handler) self.pfactory = TBinaryProtocol.TBinaryProtocolFactory() self.server = reactor.listenTCP( 0, TTwisted.ThriftServerFactory(self.processor, self.pfactory), interface="127.0.0.1") self.portNo = self.server.getHost().port self.txclient = yield ClientCreator(reactor, TTwisted.ThriftClientProtocol, ThriftTest.Client, self.pfactory).connectTCP("127.0.0.1", self.portNo) self.client = self.txclient.client @defer.inlineCallbacks def tearDown(self): yield self.server.stopListening() self.txclient.transport.loseConnection() @defer.inlineCallbacks def testVoid(self): self.assertEquals((yield self.client.testVoid()), None) @defer.inlineCallbacks def testString(self): self.assertEquals((yield self.client.testString('Python')), 'Python') @defer.inlineCallbacks def testByte(self): self.assertEquals((yield self.client.testByte(63)), 63) @defer.inlineCallbacks def testI32(self): self.assertEquals((yield self.client.testI32(-1)), -1) self.assertEquals((yield self.client.testI32(0)), 0) @defer.inlineCallbacks def testI64(self): self.assertEquals((yield self.client.testI64(-34359738368)), -34359738368) @defer.inlineCallbacks def testDouble(self): self.assertEquals((yield self.client.testDouble(-5.235098235)), -5.235098235) # TODO: def testBinary(self) ... @defer.inlineCallbacks def testStruct(self): x = Xtruct() x.string_thing = "Zero" x.byte_thing = 1 x.i32_thing = -3 x.i64_thing = -5 y = yield self.client.testStruct(x) self.assertEquals(y.string_thing, "Zero") self.assertEquals(y.byte_thing, 1) self.assertEquals(y.i32_thing, -3) self.assertEquals(y.i64_thing, -5) @defer.inlineCallbacks def testException(self): try: yield self.client.testException('Xception') self.fail("should have gotten exception") except Xception as x: self.assertEquals(x.errorCode, 1001) self.assertEquals(x.message, 'Xception') try: yield self.client.testException("throw_undeclared") self.fail("should have gotten exception") except TApplicationException: pass yield self.client.testException('Safe') @defer.inlineCallbacks def testOneway(self): yield self.client.testOneway(1) start, end, seconds = yield self.handler.onewaysQueue.get() self.assertAlmostEquals(seconds, (end - start), places=1) self.assertEquals((yield self.client.testI32(-1)), -1) thrift-0.19.0/test/py.twisted/Makefile.in0000644000000000000000000004345714472652521020262 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/py.twisted ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/py.twisted/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/py.twisted/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile TRIAL ?= trial stubs: ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen py:twisted ../v0.16/ThriftTest.thrift $(THRIFT) --gen py:twisted ../SmallTest.thrift check: stubs $(TRIAL) ./test_suite.py clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/c_glib/0000777000000000000000000000000014472652673015321 5ustar00rootroot00000000000000thrift-0.19.0/test/c_glib/Makefile.am0000644000000000000000000000513714370300523017334 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc noinst_LTLIBRARIES = libtestcglib.la nodist_libtestcglib_la_SOURCES = \ gen-c_glib/t_test_second_service.c \ gen-c_glib/t_test_second_service.h \ gen-c_glib/t_test_thrift_test.c \ gen-c_glib/t_test_thrift_test.h \ gen-c_glib/t_test_thrift_test_types.c \ gen-c_glib/t_test_thrift_test_types.h libtestcglib_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la precross: libtestcglib.la test_client test_server check_PROGRAMS = \ test_client \ test_server test_client_SOURCES = \ src/test_client.c test_client_LDADD = \ libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la test_server_SOURCES = \ src/thrift_test_handler.c \ src/thrift_test_handler.h \ src/thrift_second_service_handler.c \ src/thrift_second_service_handler.h \ src/test_server.c test_server_LDADD = \ libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la # # Common thrift code generation rules # gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen c_glib -r $< AM_CFLAGS = -g -Wall -Wextra $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) AM_CXXFLAGS = $(AM_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@ clean-local: $(RM) -r gen-c_glib/ $(RM) test_client $(RM) test_server $(RM) libtestcglib.la find . -type f -iname "*.o" | xargs rm -f dist-hook: $(RM) -r $(distdir)/gen-c_glib/ $(RM) $(distdir)/test_client $(RM) $(distdir)/test_server $(RM) $(distdir)/libtestcglib.la find $(distdir) -type f -iname "*.o" | xargs rm -f EXTRA_DIST = \ src thrift-0.19.0/test/c_glib/CMakeLists.txt0000644000000000000000000000460014370300523020032 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Contains the thrift specific target_link_libraries include(ThriftMacros) find_package(GLIB REQUIRED COMPONENTS gobject) include_directories(SYSTEM "${GLIB_INCLUDE_DIR}") include_directories(SYSTEM "${GLIBCONFIG_INCLUDE_DIR}") #Make sure gen-c_glib files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") include_directories("${PROJECT_SOURCE_DIR}/lib/c_glib/src") include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") set(crosstestgencglib_SOURCES gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h ) add_library(crosstestgencglib STATIC ${crosstestgencglib_SOURCES}) target_link_libraries(crosstestgencglib thrift_c_glib) if (WITH_ZLIB) target_link_libraries(crosstestgencglib thrift_c_glib_zlib) endif () add_executable(test_server src/test_server.c src/thrift_test_handler.c src/thrift_second_service_handler.c) target_link_libraries(test_server crosstestgencglib ${ZLIB_LIBRARIES}) add_executable(test_client src/test_client.c) target_link_libraries(test_client crosstestgencglib "${OPENSSL_LIBRARIES}") # # Common thrift code generation rules # add_custom_command(OUTPUT gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h COMMAND ${THRIFT_COMPILER} --gen c_glib -r ${PROJECT_SOURCE_DIR}/test/v0.16/ThriftTest.thrift ) thrift-0.19.0/test/c_glib/Makefile0000644000000000000000000006703514472652606016764 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/c_glib/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu check_PROGRAMS = test_client$(EXEEXT) test_server$(EXEEXT) subdir = test/c_glib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtestcglib_la_DEPENDENCIES = \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la am__dirstamp = $(am__leading_dot)dirstamp nodist_libtestcglib_la_OBJECTS = gen-c_glib/t_test_second_service.lo \ gen-c_glib/t_test_thrift_test.lo \ gen-c_glib/t_test_thrift_test_types.lo libtestcglib_la_OBJECTS = $(nodist_libtestcglib_la_OBJECTS) AM_V_lt = $(am__v_lt_$(V)) am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) am__v_lt_0 = --silent am__v_lt_1 = am_test_client_OBJECTS = src/test_client.$(OBJEXT) test_client_OBJECTS = $(am_test_client_OBJECTS) test_client_DEPENDENCIES = libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la am_test_server_OBJECTS = src/thrift_test_handler.$(OBJEXT) \ src/thrift_second_service_handler.$(OBJEXT) \ src/test_server.$(OBJEXT) test_server_OBJECTS = $(am_test_server_OBJECTS) test_server_DEPENDENCIES = libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_$(V)) am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_$(V)) am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(nodist_libtestcglib_la_SOURCES) $(test_client_SOURCES) \ $(test_server_SOURCES) DIST_SOURCES = $(test_client_SOURCES) $(test_server_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/c_glib abs_srcdir = /thrift/src/test/c_glib abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc noinst_LTLIBRARIES = libtestcglib.la nodist_libtestcglib_la_SOURCES = \ gen-c_glib/t_test_second_service.c \ gen-c_glib/t_test_second_service.h \ gen-c_glib/t_test_thrift_test.c \ gen-c_glib/t_test_thrift_test.h \ gen-c_glib/t_test_thrift_test_types.c \ gen-c_glib/t_test_thrift_test_types.h libtestcglib_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la test_client_SOURCES = \ src/test_client.c test_client_LDADD = \ libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la test_server_SOURCES = \ src/thrift_test_handler.c \ src/thrift_test_handler.h \ src/thrift_second_service_handler.c \ src/thrift_second_service_handler.h \ src/test_server.c test_server_LDADD = \ libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la AM_CFLAGS = -g -Wall -Wextra $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) AM_CXXFLAGS = $(AM_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) EXTRA_DIST = \ src all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/c_glib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/c_glib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } gen-c_glib/$(am__dirstamp): @$(MKDIR_P) gen-c_glib @: > gen-c_glib/$(am__dirstamp) gen-c_glib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) gen-c_glib/$(DEPDIR) @: > gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/t_test_second_service.lo: gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/t_test_thrift_test.lo: gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/t_test_thrift_test_types.lo: gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) libtestcglib.la: $(libtestcglib_la_OBJECTS) $(libtestcglib_la_DEPENDENCIES) $(EXTRA_libtestcglib_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtestcglib_la_OBJECTS) $(libtestcglib_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) src/test_client.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) $(EXTRA_test_client_DEPENDENCIES) @rm -f test_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS) src/thrift_test_handler.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/thrift_second_service_handler.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/test_server.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) $(EXTRA_test_server_DEPENDENCIES) @rm -f test_server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f gen-c_glib/*.$(OBJEXT) -rm -f gen-c_glib/*.lo -rm -f src/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c include gen-c_glib/$(DEPDIR)/t_test_second_service.Plo include gen-c_glib/$(DEPDIR)/t_test_thrift_test.Plo include gen-c_glib/$(DEPDIR)/t_test_thrift_test_types.Plo include src/$(DEPDIR)/test_client.Po include src/$(DEPDIR)/test_server.Po include src/$(DEPDIR)/thrift_second_service_handler.Po include src/$(DEPDIR)/thrift_test_handler.Po .c.o: $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ $(am__mv) $$depbase.Tpo $$depbase.Po # $(AM_V_CC)source='$<' object='$@' libtool=no \ # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ # $(AM_V_CC_no)$(COMPILE) -c -o $@ $< .c.obj: $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ $(am__mv) $$depbase.Tpo $$depbase.Po # $(AM_V_CC)source='$<' object='$@' libtool=no \ # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ # $(AM_V_CC_no)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ $(am__mv) $$depbase.Tpo $$depbase.Plo # $(AM_V_CC)source='$<' object='$@' libtool=yes \ # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \ # $(AM_V_CC_no)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf gen-c_glib/.libs gen-c_glib/_libs style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f gen-c_glib/$(DEPDIR)/$(am__dirstamp) -rm -f gen-c_glib/$(am__dirstamp) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf gen-c_glib/$(DEPDIR) src/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf gen-c_glib/$(DEPDIR) src/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am dist-hook \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile precross: libtestcglib.la test_client test_server # # Common thrift code generation rules # gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen c_glib -r $< clean-local: $(RM) -r gen-c_glib/ $(RM) test_client $(RM) test_server $(RM) libtestcglib.la find . -type f -iname "*.o" | xargs rm -f dist-hook: $(RM) -r $(distdir)/gen-c_glib/ $(RM) $(distdir)/test_client $(RM) $(distdir)/test_server $(RM) $(distdir)/libtestcglib.la find $(distdir) -type f -iname "*.o" | xargs rm -f # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/c_glib/src/0000777000000000000000000000000014472652702016101 5ustar00rootroot00000000000000thrift-0.19.0/test/c_glib/src/thrift_second_service_handler.c0000644000000000000000000000405014303740367024306 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include "thrift_second_service_handler.h" /* A handler that implements the TTestSecondServiceIf interface */ G_DEFINE_TYPE (SecondServiceHandler, second_service_handler, T_TEST_TYPE_SECOND_SERVICE_HANDLER); gboolean second_service_handler_secondtest_string (TTestSecondServiceIf *iface, gchar **_return, const gchar *thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); gchar buffer[256]; printf ("testSecondServiceMultiplexSecondTestString(\"%s\")\n", thing); snprintf(buffer, 255, "testString(\"%s\")", thing); *_return = g_strdup (buffer); return TRUE; } static void second_service_handler_init (SecondServiceHandler *self) { THRIFT_UNUSED_VAR (self); } static void second_service_handler_class_init (SecondServiceHandlerClass *klass) { TTestSecondServiceHandlerClass *base_class = T_TEST_SECOND_SERVICE_HANDLER_CLASS (klass); base_class->secondtest_string = second_service_handler_secondtest_string; } thrift-0.19.0/test/c_glib/src/test_server.c0000644000000000000000000002647314303740367020620 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../gen-c_glib/t_test_thrift_test.h" #include "../gen-c_glib/t_test_second_service.h" #include "thrift_test_handler.h" #include "thrift_second_service_handler.h" /* Our server object, declared globally so it is accessible within the SIGINT signal handler */ ThriftServer *server = NULL; /* A flag that indicates whether the server was interrupted with SIGINT (i.e. Ctrl-C) so we can tell whether its termination was abnormal */ gboolean sigint_received = FALSE; /* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the server */ static void sigint_handler (int signal_number) { THRIFT_UNUSED_VAR (signal_number); /* Take note we were called */ sigint_received = TRUE; /* Shut down the server gracefully */ if (server != NULL) thrift_server_stop (server); } int main (int argc, char **argv) { static gint port = 9090; static gchar *path_option = NULL; static gchar *server_type_option = NULL; static gchar *transport_option = NULL; static gchar *protocol_option = NULL; static gint string_limit = 0; static gint container_limit = 0; static GOptionEntry option_entries[] = { { "port", 0, 0, G_OPTION_ARG_INT, &port, "Port number to connect (=9090)", NULL }, { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path_option, "Unix socket domain path to connect", NULL }, { "server-type", 0, 0, G_OPTION_ARG_STRING, &server_type_option, "Type of server: simple (=simple)", NULL }, { "transport", 0, 0, G_OPTION_ARG_STRING, &transport_option, "Transport: buffered, framed, zlib (=buffered)", NULL }, { "protocol", 0, 0, G_OPTION_ARG_STRING, &protocol_option, "Protocol: binary, compact (=binary)", NULL }, { "string-limit", 0, 0, G_OPTION_ARG_INT, &string_limit, "Max string length (=none)", NULL }, { "container-limit", 0, 0, G_OPTION_ARG_INT, &container_limit, "Max container length (=none)", NULL }, { NULL } }; gchar *server_name = "simple"; gchar *transport_name = "buffered"; GType transport_factory_type = THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY; gchar *protocol_name = "binary"; GType protocol_factory_type = THRIFT_TYPE_BINARY_PROTOCOL_FACTORY; TTestThriftTestHandler *handler; TTestThriftTestHandler *handler_second_service = NULL; ThriftProcessor *processor; ThriftProcessor *processor_test = NULL; ThriftProcessor *processor_second_service = NULL; ThriftServerTransport *server_transport; ThriftTransportFactory *transport_factory; ThriftProtocolFactory *protocol_factory; struct sigaction sigint_action; GOptionContext *option_context; gboolean options_valid = TRUE; GError *error = NULL; #if (!GLIB_CHECK_VERSION (2, 36, 0)) g_type_init (); #endif /* Configure and parse our command-line options */ option_context = g_option_context_new (NULL); g_option_context_add_main_entries (option_context, option_entries, NULL); if (g_option_context_parse (option_context, &argc, &argv, &error) == FALSE) { fprintf (stderr, "%s\n", error->message); g_clear_error (&error); g_option_context_free (option_context); return 255; } g_option_context_free (option_context); /* Validate the parsed options */ if (server_type_option != NULL && strncmp (server_type_option, "simple", 7) != 0) { fprintf (stderr, "Unknown server type %s\n", protocol_option); options_valid = FALSE; } if (protocol_option != NULL) { if (strncmp (protocol_option, "compact", 8) == 0) { protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY; protocol_name = "compact"; } else if (strncmp (protocol_option, "multi", 6) == 0) { protocol_name = "binary:multi"; } else if (strncmp (protocol_option, "multic", 7) == 0) { protocol_factory_type = THRIFT_TYPE_COMPACT_PROTOCOL_FACTORY; protocol_name = "compact:multic"; } else if (strncmp (protocol_option, "binary", 7) != 0) { fprintf (stderr, "Unknown protocol type %s\n", protocol_option); options_valid = FALSE; } } if (transport_option != NULL) { if (strncmp (transport_option, "framed", 7) == 0) { transport_factory_type = THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY; transport_name = "framed"; } else if (strncmp (transport_option, "zlib", 5) == 0) { transport_factory_type = THRIFT_TYPE_ZLIB_TRANSPORT_FACTORY; transport_name = "zlib"; } else if (strncmp (transport_option, "buffered", 9) != 0) { fprintf (stderr, "Unknown transport type %s\n", transport_option); options_valid = FALSE; } } if (!options_valid) return 254; /* Establish all our connection objects */ handler = g_object_new (TYPE_THRIFT_TEST_HANDLER, NULL); if(strstr(protocol_name, ":multi")){ /* When a multiplexed processor is involved the handler is not registered as usual. We create the processor and the real processor is registered. Multiple processors can be registered at once. This is why we don't have a constructor property */ processor = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROCESSOR, NULL); handler_second_service = g_object_new (TYPE_SECOND_SERVICE_HANDLER, NULL); processor_test = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR, "handler", handler, NULL); processor_second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_PROCESSOR, "handler", handler_second_service, NULL); /* We register a test processor with Multiplexed name ThriftTest */ if(!thrift_multiplexed_processor_register_processor(processor, "ThriftTest", processor_test, &error)){ g_message ("thrift_server_serve: %s", error != NULL ? error->message : "(null)"); g_clear_error (&error); } /* We register a second test processor with Multiplexed name SecondService * we are responsible of freeing the processor when it's not used anymore */ if(!thrift_multiplexed_processor_register_processor(processor, "SecondService", processor_second_service, &error)){ g_message ("thrift_server_serve: %s", error != NULL ? error->message : "(null)"); g_clear_error (&error); } }else{ processor = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR, "handler", handler, NULL); } if (path_option) { server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "path", path_option, NULL); } else { server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); } transport_factory = g_object_new (transport_factory_type, NULL); if (strstr (protocol_name, "compact") != NULL) { protocol_factory = g_object_new (protocol_factory_type, "string_limit", string_limit, "container_limit", container_limit, NULL); } else { protocol_factory = g_object_new (protocol_factory_type, NULL); } server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, "processor", processor, "server_transport", server_transport, "input_transport_factory", transport_factory, "output_transport_factory", transport_factory, "input_protocol_factory", protocol_factory, "output_protocol_factory", protocol_factory, NULL); /* Install our SIGINT handler, which handles Ctrl-C being pressed by stopping the server gracefully */ memset (&sigint_action, 0, sizeof (sigint_action)); sigint_action.sa_handler = sigint_handler; sigint_action.sa_flags = SA_RESETHAND; sigaction (SIGINT, &sigint_action, NULL); if (path_option) { printf ("Starting \"%s\" server (%s/%s) listen on: %s\n", server_name, transport_name, protocol_name, path_option); } else { printf ("Starting \"%s\" server (%s/%s) listen on: %d\n", server_name, transport_name, protocol_name, port); } fflush (stdout); /* Serve clients until SIGINT is received (Ctrl-C is pressed) */ thrift_server_serve (server, &error); /* If the server stopped for any reason other than being interrupted by the user, report the error */ if (!sigint_received) { g_message ("thrift_server_serve: %s", error != NULL ? error->message : "(null)"); } puts ("done."); g_clear_error (&error); g_object_unref (server); g_object_unref (protocol_factory); g_object_unref (transport_factory); g_object_unref (server_transport); g_object_unref (processor); g_object_unref (handler); if(handler_second_service){ g_object_unref (handler_second_service); } if(processor_test){ g_object_unref (processor_test); } if(processor_second_service){ g_object_unref (processor_second_service); } return 0; } thrift-0.19.0/test/c_glib/src/thrift_test_handler.c0000644000000000000000000005631714303740367022307 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include "thrift_test_handler.h" /* A handler that implements the TTestThriftTestIf interface */ G_DEFINE_TYPE (ThriftTestHandler, thrift_test_handler, T_TEST_TYPE_THRIFT_TEST_HANDLER) gboolean thrift_test_handler_test_void (TTestThriftTestIf *iface, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testVoid()\n"); return TRUE; } gboolean thrift_test_handler_test_string (TTestThriftTestIf *iface, gchar **_return, const gchar *thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testString(\"%s\")\n", thing); *_return = g_strdup (thing); return TRUE; } gboolean thrift_test_handler_test_bool (TTestThriftTestIf *iface, gboolean *_return, const gboolean thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testBool(%s)\n", thing ? "true" : "false"); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_byte (TTestThriftTestIf *iface, gint8 *_return, const gint8 thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testByte(%d)\n", (gint)thing); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_i32 (TTestThriftTestIf *iface, gint32 *_return, const gint32 thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testI32(%d)\n", thing); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_i64 (TTestThriftTestIf *iface, gint64 *_return, const gint64 thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testI64(%" PRId64 ")\n", thing); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_double (TTestThriftTestIf *iface, gdouble *_return, const gdouble thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testDouble(%f)\n", thing); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_binary (TTestThriftTestIf *iface, GByteArray ** _return, const GByteArray * thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testBinary()\n"); // TODO: hex output g_byte_array_ref((GByteArray *)thing); *_return = (GByteArray *)thing; return TRUE; } gboolean thrift_test_handler_test_struct (TTestThriftTestIf *iface, TTestXtruct **_return, const TTestXtruct *thing, GError **error) { gchar *string_thing = NULL; gint byte_thing; gint i32_thing; gint64 i64_thing; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); g_object_get ((TTestXtruct *)thing, "string_thing", &string_thing, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); printf ("testStruct({\"%s\", %d, %d, %" PRId64 "})\n", string_thing, (gint)byte_thing, i32_thing, i64_thing); g_object_set (*_return, "string_thing", string_thing, "byte_thing", byte_thing, "i32_thing", i32_thing, "i64_thing", i64_thing, NULL); if (string_thing != NULL) g_free (string_thing); return TRUE; } gboolean thrift_test_handler_test_nest (TTestThriftTestIf *iface, TTestXtruct2 **_return, const TTestXtruct2 *thing, GError **error) { gchar *inner_string_thing = NULL; gint byte_thing, inner_byte_thing; gint i32_thing, inner_i32_thing; gint64 inner_i64_thing; TTestXtruct *struct_thing; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); g_object_get ((TTestXtruct2 *)thing, "byte_thing", &byte_thing, "struct_thing", &struct_thing, "i32_thing", &i32_thing, NULL); g_object_get (struct_thing, "string_thing", &inner_string_thing, "byte_thing", &inner_byte_thing, "i32_thing", &inner_i32_thing, "i64_thing", &inner_i64_thing, NULL); printf ("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n", byte_thing, inner_string_thing, inner_byte_thing, inner_i32_thing, inner_i64_thing, i32_thing); g_object_set (*_return, "byte_thing", byte_thing, "struct_thing", struct_thing, "i32_thing", i32_thing, NULL); if (inner_string_thing != NULL) g_free (inner_string_thing); g_object_unref (struct_thing); return TRUE; } gboolean thrift_test_handler_test_map (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error) { GHashTableIter hash_table_iter; gpointer key; gpointer value; gboolean first = TRUE; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testMap({"); g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { gint32 *new_key; gint32 *new_value; if (first) first = FALSE; else printf (", "); printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); new_key = g_malloc (sizeof *new_key); *new_key = *(gint32 *)key; new_value = g_malloc (sizeof *new_value); *new_value = *(gint32 *)value; g_hash_table_insert (*_return, new_key, new_value); } printf ("})\n"); return TRUE; } gboolean thrift_test_handler_test_string_map (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error) { GHashTableIter hash_table_iter; gpointer key; gpointer value; gboolean first = TRUE; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testStringMap({"); g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { gchar *new_key; gchar *new_value; if (first) first = FALSE; else printf (", "); printf ("%s => %s", (gchar *)key, (gchar *)value); new_key = g_strdup ((gchar *)key); new_value = g_strdup ((gchar *)value); g_hash_table_insert (*_return, new_key, new_value); } printf ("})\n"); return TRUE; } gboolean thrift_test_handler_test_set (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error) { GHashTableIter hash_table_iter; gpointer key; gboolean first = TRUE; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testSet({"); g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing); while (g_hash_table_iter_next (&hash_table_iter, &key, NULL)) { gint32 *new_key; if (first) first = FALSE; else printf (", "); printf ("%d", *(gint32 *)key); new_key = g_malloc (sizeof *new_key); *new_key = *(gint32 *)key; g_hash_table_insert (*_return, new_key, NULL); } printf ("})\n"); return TRUE; } gboolean thrift_test_handler_test_list (TTestThriftTestIf *iface, GArray **_return, const GArray *thing, GError **error) { guint i; gboolean first = TRUE; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testList({"); for (i = 0; i < thing->len; i += 1) { gint32 value; gint32 new_value; if (first) first = FALSE; else printf (", "); value = g_array_index (thing, gint32, i); printf ("%d", value); new_value = value; g_array_append_val (*_return, new_value); } printf ("})\n"); return TRUE; } gboolean thrift_test_handler_test_enum (TTestThriftTestIf *iface, TTestNumberz *_return, const TTestNumberz thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testEnum(%d)\n", thing); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_typedef (TTestThriftTestIf *iface, TTestUserId *_return, const TTestUserId thing, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testTypedef(%" PRId64 ")\n", thing); *_return = thing; return TRUE; } gboolean thrift_test_handler_test_map_map (TTestThriftTestIf *iface, GHashTable **_return, const gint32 hello, GError **error) { GHashTable *positive; GHashTable *negative; gint32 *key; gint32 *value; guint i; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testMapMap(%d)\n", hello); positive = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); negative = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); for (i = 1; i < 5; i += 1) { key = g_malloc (sizeof *key); value = g_malloc (sizeof *value); *key = i; *value = i; g_hash_table_insert (positive, key, value); key = g_malloc (sizeof *key); value = g_malloc (sizeof *value); *key = -i; *value = -i; g_hash_table_insert (negative, key, value); } key = g_malloc (sizeof *key); *key = 4; g_hash_table_insert (*_return, key, positive); key = g_malloc (sizeof *key); *key = -4; g_hash_table_insert (*_return, key, negative); return TRUE; } gboolean thrift_test_handler_test_insanity (TTestThriftTestIf *iface, GHashTable **_return, const TTestInsanity *argument, GError **error) { TTestXtruct *xtruct_in; gchar *string_thing = NULL; gint byte_thing; gint i32_thing; gint64 i64_thing; GPtrArray *xtructs; TTestInsanity *looney; GHashTable *user_map; GHashTable *first_map; GHashTable *second_map; GHashTableIter hash_table_iter; GHashTableIter inner_hash_table_iter; GHashTableIter user_map_iter; gpointer key; gpointer value; TTestUserId *user_id; guint i; THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testInsanity()\n"); first_map = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); second_map = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); g_hash_table_insert (first_map, GINT_TO_POINTER (T_TEST_NUMBERZ_TWO), (gpointer)argument); g_hash_table_insert (first_map, GINT_TO_POINTER (T_TEST_NUMBERZ_THREE), (gpointer)argument); /* Increment argument's ref count by two because first_map now holds two references to it and the caller is not aware we have made any additional references to argument. (That is, caller owns argument and will unref it explicitly in addition to unref-ing *_return.) We do this instead of creating a copy of argument in order to mimic the C++ implementation (and since, frankly, the world needs less argument, not more). */ g_object_ref ((gpointer)argument); g_object_ref ((gpointer)argument); looney = g_object_new (T_TEST_TYPE_INSANITY, NULL); g_hash_table_insert (second_map, GINT_TO_POINTER (T_TEST_NUMBERZ_SIX), looney); user_id = g_malloc (sizeof *user_id); *user_id = 1; g_hash_table_insert (*_return, user_id, first_map); user_id = g_malloc (sizeof *user_id); *user_id = 2; g_hash_table_insert (*_return, user_id, second_map); printf ("return"); printf (" = {"); g_hash_table_iter_init (&hash_table_iter, *_return); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { printf ("%" PRId64 " => {", *(TTestUserId *)key); g_hash_table_iter_init (&inner_hash_table_iter, (GHashTable *)value); while (g_hash_table_iter_next (&inner_hash_table_iter, &key, &value)) { printf ("%d => {", (TTestNumberz)key); g_object_get ((TTestInsanity *)value, "userMap", &user_map, "xtructs", &xtructs, NULL); printf ("{"); g_hash_table_iter_init (&user_map_iter, user_map); while (g_hash_table_iter_next (&user_map_iter, &key, &value)) { printf ("%d => %" PRId64 ", ", (TTestNumberz)key, *(TTestUserId *)value); } printf ("}, "); g_hash_table_unref (user_map); printf ("{"); for (i = 0; i < xtructs->len; ++i) { xtruct_in = g_ptr_array_index (xtructs, i); g_object_get (xtruct_in, "string_thing", &string_thing, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); printf ("{\"%s\", %d, %d, %" PRId64 "}, ", string_thing, byte_thing, i32_thing, i64_thing); if (string_thing != NULL) { g_free (string_thing); } } printf ("}"); g_ptr_array_unref (xtructs); printf ("}, "); } printf ("}, "); } printf ("}\n"); return TRUE; } gboolean thrift_test_handler_test_multi (TTestThriftTestIf *iface, TTestXtruct **_return, const gint8 arg0, const gint32 arg1, const gint64 arg2, const GHashTable *arg3, const TTestNumberz arg4, const TTestUserId arg5, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); THRIFT_UNUSED_VAR (arg3); THRIFT_UNUSED_VAR (arg4); THRIFT_UNUSED_VAR (arg5); printf ("testMulti()\n"); g_object_set (*_return, "string_thing", "Hello2", "byte_thing", arg0, "i32_thing", arg1, "i64_thing", arg2, NULL); return TRUE; } gboolean thrift_test_handler_test_exception (TTestThriftTestIf *iface, const gchar *arg, TTestXception **err1, GError **error) { THRIFT_UNUSED_VAR (iface); TTestXtruct *xtruct; gboolean result; printf ("testException(%s)\n", arg); /* Unlike argument objects, exception objects are not pre-created */ g_assert (*err1 == NULL); if (strncmp (arg, "Xception", 9) == 0) { /* "Throw" a custom exception: Set the corresponding exception argument, set *error to NULL and return FALSE */ *err1 = g_object_new (T_TEST_TYPE_XCEPTION, "errorCode", 1001, "message", arg, NULL); *error = NULL; result = FALSE; } else if (strncmp (arg, "TException", 11) == 0) { /* "Throw" a generic TException (ThriftApplicationException): Set all exception arguments to NULL, set *error and return FALSE */ *err1 = NULL; g_set_error (error, thrift_application_exception_error_quark (), THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, "Default TException."); result = FALSE; } else { *err1 = NULL; *error = NULL; /* This code is duplicated from the C++ test suite, though it appears to serve no purpose */ xtruct = g_object_new (T_TEST_TYPE_XTRUCT, "string_thing", arg, NULL); g_object_unref (xtruct); result = TRUE; } return result; } gboolean thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, TTestXtruct **_return, const gchar *arg0, const gchar *arg1, TTestXception **err1, TTestXception2 **err2, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); TTestXtruct *struct_thing; gboolean result; printf ("testMultiException(%s, %s)\n", arg0, arg1); g_assert (*err1 == NULL); g_assert (*err2 == NULL); if (strncmp (arg0, "Xception", 8) == 0 && strlen(arg0) == 8) { *err1 = g_object_new (T_TEST_TYPE_XCEPTION, "errorCode", 1001, "message", "This is an Xception", NULL); result = FALSE; } else if (strncmp (arg0, "Xception2", 9) == 0) { *err2 = g_object_new (T_TEST_TYPE_XCEPTION2, "errorCode", 2002, NULL); g_object_get (*err2, "struct_thing", &struct_thing, NULL); g_object_set (struct_thing, "string_thing", "This is an Xception2", NULL); g_object_set (*err2, "struct_thing", struct_thing, NULL); g_object_unref (struct_thing); result = FALSE; } else { g_object_set (*_return, "string_thing", arg1, NULL); result = TRUE; } return result; } gboolean thrift_test_handler_test_oneway (TTestThriftTestIf *iface, const gint32 secondsToSleep, GError **error) { THRIFT_UNUSED_VAR (iface); THRIFT_UNUSED_VAR (error); printf ("testOneway(%d): Sleeping...\n", secondsToSleep); sleep (secondsToSleep); printf ("testOneway(%d): done sleeping!\n", secondsToSleep); return TRUE; } static void thrift_test_handler_init (ThriftTestHandler *self) { THRIFT_UNUSED_VAR (self); } static void thrift_test_handler_class_init (ThriftTestHandlerClass *klass) { TTestThriftTestHandlerClass *base_class = T_TEST_THRIFT_TEST_HANDLER_CLASS (klass); base_class->test_void = klass->test_void = thrift_test_handler_test_void; base_class->test_string = klass->test_string = thrift_test_handler_test_string; base_class->test_bool = klass->test_bool = thrift_test_handler_test_bool; base_class->test_byte = klass->test_byte = thrift_test_handler_test_byte; base_class->test_i32 = klass->test_i32 = thrift_test_handler_test_i32; base_class->test_i64 = klass->test_i64 = thrift_test_handler_test_i64; base_class->test_double = klass->test_double = thrift_test_handler_test_double; base_class->test_binary = klass->test_binary = thrift_test_handler_test_binary; base_class->test_struct = klass->test_struct = thrift_test_handler_test_struct; base_class->test_nest = klass->test_nest = thrift_test_handler_test_nest; base_class->test_map = klass->test_map = thrift_test_handler_test_map; base_class->test_string_map = klass->test_string_map = thrift_test_handler_test_string_map; base_class->test_set = klass->test_set = thrift_test_handler_test_set; base_class->test_list = klass->test_list = thrift_test_handler_test_list; base_class->test_enum = klass->test_enum = thrift_test_handler_test_enum; base_class->test_typedef = klass->test_typedef = thrift_test_handler_test_typedef; base_class->test_map_map = klass->test_map_map = thrift_test_handler_test_map_map; base_class->test_insanity = klass->test_insanity = thrift_test_handler_test_insanity; base_class->test_multi = klass->test_multi = thrift_test_handler_test_multi; base_class->test_exception = klass->test_exception = thrift_test_handler_test_exception; base_class->test_multi_exception = klass->test_multi_exception = thrift_test_handler_test_multi_exception; base_class->test_oneway = klass->test_oneway = thrift_test_handler_test_oneway; } thrift-0.19.0/test/c_glib/src/test_client.c0000644000000000000000000016437414303740367020573 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../gen-c_glib/t_test_second_service.h" #include "../gen-c_glib/t_test_thrift_test.h" /* Handle SIGPIPE signals (indicating the server has closed the connection prematurely) by outputting an error message before exiting. */ static void sigpipe_handler (int signal_number) { THRIFT_UNUSED_VAR (signal_number); /* Flush standard output to make sure the test results so far are logged */ fflush (stdout); fputs ("Broken pipe (server closed connection prematurely)\n", stderr); fflush (stderr); /* Re-raise the signal, this time invoking the default signal handler, to terminate the program */ raise (SIGPIPE); } /* Compare two gint32 values. Used for sorting and finding integer values within a GList. */ static gint gint32_compare (gconstpointer a, gconstpointer b) { gint32 int32_a = *(gint32 *)a; gint32 int32_b = *(gint32 *)b; int result = 0; if (int32_a < int32_b) result = -1; else if (int32_a > int32_b) result = 1; return result; } int main (int argc, char **argv) { static gchar * host = NULL; static gint port = 9090; static gchar * path = NULL; static gboolean ssl = FALSE; static gchar * transport_option = NULL; static gchar * protocol_option = NULL; static gint num_tests = 1; static GOptionEntry option_entries[] ={ { "host", 'h', 0, G_OPTION_ARG_STRING, &host, "Host to connect (=localhost)", NULL }, { "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port number to connect (=9090)", NULL }, { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path, "Unix socket domain path to connect", NULL }, { "ssl", 's', 0, G_OPTION_ARG_NONE, &ssl, "Enable SSL", NULL }, { "transport", 't', 0, G_OPTION_ARG_STRING, &transport_option, "Transport: buffered, framed (=buffered)", NULL }, { "protocol", 'r', 0, G_OPTION_ARG_STRING, &protocol_option, "Protocol: binary, compact, multi, multic (=binary)", NULL }, { "testloops", 'n', 0, G_OPTION_ARG_INT, &num_tests, "Number of tests (=1)", NULL }, { NULL } }; struct sigaction sigpipe_action; GType socket_type = THRIFT_TYPE_SOCKET; gchar *socket_name = "ip"; GType transport_type = THRIFT_TYPE_BUFFERED_TRANSPORT; gchar *transport_name = "buffered"; GType protocol_type = THRIFT_TYPE_BINARY_PROTOCOL; gchar *protocol_name = "binary"; ThriftSocket *socket = NULL; ThriftTransport *transport = NULL; ThriftProtocol *protocol = NULL; ThriftProtocol *protocol2 = NULL; // for multiplexed tests ThriftProtocol *multiplexed_protocol = NULL; TTestThriftTestIf *test_client = NULL; TTestSecondServiceIf *second_service = NULL; // for multiplexed tests struct timeval time_start, time_stop, time_elapsed; guint64 time_elapsed_usec, time_total_usec = 0; guint64 time_min_usec = G_MAXUINT64, time_max_usec = 0, time_avg_usec; GOptionContext *option_context; gboolean options_valid = TRUE; int test_num = 0; int fail_count = 0; GError *error = NULL; #if (!GLIB_CHECK_VERSION (2, 36, 0)) g_type_init (); #endif /* Configure and parse our command-line options */ option_context = g_option_context_new (NULL); g_option_context_add_main_entries (option_context, option_entries, NULL); if (!g_option_context_parse (option_context, &argc, &argv, &error)) { fprintf (stderr, "%s\n", error->message); g_clear_error (&error); g_option_context_free (option_context); return 255; } g_option_context_free (option_context); /* Set remaining default values for unspecified options */ if (host == NULL) host = g_strdup ("localhost"); /* Validate the parsed options */ if (protocol_option != NULL) { if (strncmp (protocol_option, "compact", 8) == 0) { protocol_type = THRIFT_TYPE_COMPACT_PROTOCOL; protocol_name = "compact"; } else if (strncmp (protocol_option, "multi", 6) == 0) { protocol_type = THRIFT_TYPE_MULTIPLEXED_PROTOCOL; protocol_name = "binary:multi"; } else if (strncmp (protocol_option, "multic", 7) == 0) { protocol_type = THRIFT_TYPE_MULTIPLEXED_PROTOCOL; protocol_name = "compact:multic"; } else if (strncmp (protocol_option, "binary", 7) == 0) { printf("We are going with default protocol\n"); } else { fprintf (stderr, "Unknown protocol type %s\n", protocol_option); options_valid = FALSE; } } if (transport_option != NULL) { if (strncmp (transport_option, "framed", 7) == 0) { transport_type = THRIFT_TYPE_FRAMED_TRANSPORT; transport_name = "framed"; } else if (strncmp (transport_option, "buffered", 9) != 0) { fprintf (stderr, "Unknown transport type %s\n", transport_option); options_valid = FALSE; } } if (ssl) { socket_type = THRIFT_TYPE_SSL_SOCKET; socket_name = "ip-ssl"; printf("Type name %s\n", g_type_name (socket_type)); } if (!options_valid) return 254; if (path) { printf ("Connecting (%s/%s) to: %s/%s\n", transport_name, protocol_name, socket_name, path); } else { printf ("Connecting (%s/%s) to: %s/%s:%d\n", transport_name, protocol_name, socket_name, host, port); } /* Install our SIGPIPE handler, which outputs an error message to standard error before exiting so testers can know what happened */ memset (&sigpipe_action, 0, sizeof (sigpipe_action)); sigpipe_action.sa_handler = sigpipe_handler; sigpipe_action.sa_flags = SA_RESETHAND; sigaction (SIGPIPE, &sigpipe_action, NULL); if (ssl) { thrift_ssl_socket_initialize_openssl(); } /* Establish all our connection objects */ if (path) { socket = g_object_new (socket_type, "path", path, NULL); } else { socket = g_object_new (socket_type, "hostname", host, "port", port, NULL); } if (ssl && !thrift_ssl_load_cert_from_file(THRIFT_SSL_SOCKET(socket), "../keys/CA.pem")) { fprintf(stderr, "Unable to load validation certificate ../keys/CA.pem - did you run in the test/c_glib directory?\n"); g_clear_object (&socket); return 253; } transport = g_object_new (transport_type, "transport", socket, NULL); if (protocol_type == THRIFT_TYPE_MULTIPLEXED_PROTOCOL) { // TODO: A multiplexed test should also test "Second" (see Java TestServer) // The context comes from the name of the thrift file. If multiple thrift // schemas are used we have to redo the way this is done. if (strncmp(protocol_name, "binary:", 7) == 0) { multiplexed_protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL); } else if (strncmp(protocol_name, "compact:", 8) == 0) { multiplexed_protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", transport, NULL); } else { fprintf(stderr, "Unknown multiplex protocol name: %s\n", protocol_name); g_clear_object (&transport); g_clear_object (&socket); return 252; } protocol = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, "transport", transport, "protocol", multiplexed_protocol, "service-name", "ThriftTest", NULL);; if (NULL == protocol) { g_clear_object (&multiplexed_protocol); g_clear_object (&transport); g_clear_object (&socket); return 251; } // Make a second protocol and client running on the same multiplexed transport protocol2 = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, "transport", transport, "protocol", multiplexed_protocol, "service-name", "SecondService", NULL); second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_CLIENT, "input_protocol", protocol2, "output_protocol", protocol2, NULL); }else{ protocol = g_object_new (protocol_type, "transport", transport, NULL); } test_client = g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, NULL); /* Execute the actual tests */ for (test_num = 0; test_num < num_tests; ++test_num) { if (thrift_transport_open (transport, &error)) { gchar *string = NULL; gboolean boolean = 0; gint8 byte = 0; gint32 int32 = 0; gint64 int64 = 0; gdouble dub = 0; gint byte_thing, i32_thing, inner_byte_thing, inner_i32_thing; gint64 i64_thing, inner_i64_thing; TTestXtruct *xtruct_out, *xtruct_out2, *xtruct_in, *inner_xtruct_in; TTestXtruct2 *xtruct2_out, *xtruct2_in; GHashTable *map_out, *map_in, *inner_map_in; GHashTable *set_out, *set_in; gpointer key, value; gint32 *i32_key_ptr, *i32_value_ptr; GHashTableIter hash_table_iter, inner_hash_table_iter; GList *keys_out, *keys_in, *keys_elem; GArray *list_out, *list_in; TTestNumberz numberz; TTestNumberz numberz2; TTestUserId user_id, *user_id_ptr, *user_id_ptr2; TTestInsanity *insanity_out, *insanity_in; GHashTable *user_map; GHashTableIter user_map_iter; GPtrArray *xtructs; TTestXception *xception = NULL; TTestXception2 *xception2 = NULL; gboolean oneway_result; struct timeval oneway_start, oneway_end, oneway_elapsed; gint oneway_elapsed_usec; gboolean first; gint32 i, j; if (path) { printf ("Test #%d, connect %s\n", test_num + 1, path); } else { printf ("Test #%d, connect %s:%d\n", test_num + 1, host, port); } gettimeofday (&time_start, NULL); /* These test routines have been ported from the C++ test client, care being taken to ensure their output remains as close as possible to the original to facilitate diffs. For simplicity comments have been omitted, but every routine has the same basic structure: - Create and populate data structures as necessary. - Format and output (to the console) a representation of the outgoing data. - Issue the remote method call to the server. - Format and output a representation of the returned data. - Verify the returned data matches what was expected. - Deallocate any created data structures. Note the recognized values and expected behaviour of each remote method are described in ThriftTest.thrift, which you'll find in the top-level "test" folder. */ /** * VOID TEST */ printf ("testVoid()"); if (t_test_thrift_test_if_test_void (test_client, &error)) { printf (" = void\n"); } else { if(error!=NULL){ printf ("%s\n", error->message); g_error_free (error); error = NULL; } fail_count++; } /** * STRING TEST */ printf ("testString(\"Test\")"); if (t_test_thrift_test_if_test_string (test_client, &string, "Test", &error)) { printf (" = \"%s\"\n", string); if (strncmp (string, "Test", 5) != 0) fail_count++; g_free (string); string = NULL; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * Multiplexed Test - do this right in the middle of the normal Test Client run */ if (second_service) { printf ("testSecondServiceMultiplexSecondTestString(\"2nd\")"); if (t_test_second_service_if_secondtest_string (second_service, &string, "2nd", &error)) { printf (" = \"%s\"\n", string); if (strcmp (string, "testString(\"2nd\")") != 0) { ++fail_count; } g_free (string); string = NULL; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; ++fail_count; } } /** * BOOL TEST */ printf ("testByte(true)"); if (t_test_thrift_test_if_test_bool (test_client, &boolean, 1, &error)) { printf (" = %s\n", boolean ? "true" : "false"); if (boolean != 1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf ("testByte(false)"); if (t_test_thrift_test_if_test_bool (test_client, &boolean, 0, &error)) { printf (" = %s\n", boolean ? "true" : "false"); if (boolean != 0) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * BYTE TEST */ printf ("testByte(1)"); if (t_test_thrift_test_if_test_byte (test_client, &byte, 1, &error)) { printf (" = %d\n", byte); if (byte != 1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf ("testByte(-1)"); if (t_test_thrift_test_if_test_byte (test_client, &byte, -1, &error)) { printf (" = %d\n", byte); if (byte != -1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * I32 TEST */ printf ("testI32(-1)"); if (t_test_thrift_test_if_test_i32 (test_client, &int32, -1, &error)) { printf (" = %d\n", int32); if (int32 != -1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * I64 TEST */ printf ("testI64(-34359738368)"); if (t_test_thrift_test_if_test_i64 (test_client, &int64, (gint64)-34359738368, &error)) { printf (" = %" PRId64 "\n", int64); if (int64 != (gint64)-34359738368) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * DOUBLE TEST */ printf("testDouble(-5.2098523)"); if (t_test_thrift_test_if_test_double (test_client, &dub, -5.2098523, &error)) { printf (" = %f\n", dub); if ((dub - (-5.2098523)) > 0.001) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * BINARY TEST */ printf ("testBinary(empty)"); GByteArray *emptyArray = g_byte_array_new(); GByteArray *result = NULL; if (t_test_thrift_test_if_test_binary (test_client, &result, emptyArray, &error)) { GBytes *response = g_byte_array_free_to_bytes(result); // frees result result = NULL; gsize siz = g_bytes_get_size(response); if (siz == 0) { printf(" = empty\n"); } else { printf(" = not empty (%ld bytes)\n", (long)siz); ++fail_count; } g_bytes_unref(response); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_byte_array_unref(emptyArray); emptyArray = NULL; // TODO: add testBinary() with data printf ("testBinary([-128..127]) = {"); const signed char bin_data[256] = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127}; GByteArray *fullArray = g_byte_array_new(); g_byte_array_append(fullArray, (guint8 *)(&bin_data[0]), 256); if (t_test_thrift_test_if_test_binary (test_client, &result, fullArray, &error)) { GBytes *response = g_byte_array_free_to_bytes(result); // frees result result = NULL; gsize siz = g_bytes_get_size(response); gconstpointer ptr = g_bytes_get_data(response, &siz); if (siz == 256) { gboolean first = 1; gboolean failed = 0; int i; for (i = 0; i < 256; ++i) { if (!first) printf(","); else first = 0; int val = ((signed char *)ptr)[i]; printf("%d", val); if (!failed && val != i - 128) { failed = 1; } } printf("} "); if (failed) { printf("FAIL (bad content) size %ld OK\n", (long)siz); ++fail_count; } else { printf("OK size %ld OK\n", (long)siz); } } else { printf(" = bad size %ld\n", (long)siz); ++fail_count; } g_bytes_unref(response); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_byte_array_unref(fullArray); fullArray = NULL; /** * STRUCT TEST */ printf ("testStruct({\"Zero\", 1, -3, -5})"); xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, "string_thing", "Zero", "byte_thing", 1, "i32_thing", -3, "i64_thing", -5LL, NULL); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (t_test_thrift_test_if_test_struct (test_client, &xtruct_in, xtruct_out, &error)) { g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); printf (" = {\"%s\", %d, %d, %" PRId64 "}\n", string, byte_thing, i32_thing, i64_thing); if ((string == NULL || strncmp (string, "Zero", 5) != 0) || byte_thing != 1 || i32_thing != -3 || i64_thing != (gint64)-5) fail_count++; if (string) { g_free (string); string = NULL; } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } // g_clear_object(&xtruct_out); used below g_clear_object(&xtruct_in); /** * NESTED STRUCT TEST */ printf ("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); xtruct2_out = g_object_new (T_TEST_TYPE_XTRUCT2, "byte_thing", 1, "struct_thing", xtruct_out, "i32_thing", 5, NULL); xtruct2_in = g_object_new (T_TEST_TYPE_XTRUCT2, NULL); if (t_test_thrift_test_if_test_nest (test_client, &xtruct2_in, xtruct2_out, &error)) { g_object_get (xtruct2_in, "byte_thing", &byte_thing, "struct_thing", &xtruct_in, "i32_thing", &i32_thing, NULL); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &inner_byte_thing, "i32_thing", &inner_i32_thing, "i64_thing", &inner_i64_thing, NULL); printf (" = {%d, {\"%s\", %d, %d, %" PRId64 "}, %d}\n", byte_thing, string, inner_byte_thing, inner_i32_thing, inner_i64_thing, i32_thing); if (byte_thing != 1 || (string == NULL || strncmp (string, "Zero", 5) != 0) || inner_byte_thing != 1 || inner_i32_thing != -3 || inner_i64_thing != (gint64)-5 || i32_thing != 5) fail_count++; if (string) { g_free(string); string = NULL; } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_clear_object(&xtruct_in); g_clear_object(&xtruct2_in); g_clear_object(&xtruct2_out); g_clear_object(&xtruct_out); /** * MAP TEST */ map_out = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); for (i = 0; i < 5; ++i) { i32_key_ptr = g_malloc (sizeof *i32_key_ptr); i32_value_ptr = g_malloc (sizeof *i32_value_ptr); *i32_key_ptr = i; *i32_value_ptr = i - 10; g_hash_table_insert (map_out, i32_key_ptr, i32_value_ptr); } printf ("testMap({"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); } printf ("})"); map_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); if (t_test_thrift_test_if_test_map (test_client, &map_in, map_out, &error)) { printf (" = {"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_in); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); } printf ("}\n"); if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) fail_count++; else { g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { gpointer in_value = g_hash_table_lookup (map_in, key); if (in_value == NULL || *(gint32 *)in_value != *(gint32 *)value) { fail_count++; break; } } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); g_hash_table_unref (map_out); /** * STRING MAP TEST */ map_out = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert (map_out, "a", "2"); g_hash_table_insert (map_out, "b", "blah"); g_hash_table_insert (map_out, "some", "thing"); printf ("testStringMap({"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); } printf (")}"); map_in = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); if (t_test_thrift_test_if_test_string_map (test_client, &map_in, map_out, &error)) { printf (" = {"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_in); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); } printf ("}\n"); if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) fail_count++; else { g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { gpointer in_value = g_hash_table_lookup (map_in, key); if (in_value == NULL || strcmp ((gchar *)in_value, (gchar *)value) != 0) { fail_count++; break; } } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); g_hash_table_unref (map_out); /** * SET TEST */ set_out = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); for (i = -2; i < 3; ++i) { i32_key_ptr = g_malloc (sizeof *i32_key_ptr); *i32_key_ptr = i; g_hash_table_insert (set_out, i32_key_ptr, NULL); } printf ("testSet({"); first = TRUE; keys_out = g_hash_table_get_keys (set_out); keys_elem = keys_out; while (keys_elem != NULL) { if (first) first = FALSE; else printf (", "); printf ("%d", *(gint32 *)keys_elem->data); keys_elem = keys_elem->next; } printf ("})"); set_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); if (t_test_thrift_test_if_test_set (test_client, &set_in, set_out, &error)) { printf(" = {"); first = TRUE; keys_in = g_hash_table_get_keys (set_in); keys_elem = keys_in; while (keys_elem != NULL) { if (first) first = FALSE; else printf (", "); printf ("%d", *(gint32 *)keys_elem->data); keys_elem = keys_elem->next; } printf ("}\n"); if (g_list_length (keys_in) != g_list_length (keys_out)) fail_count++; else { keys_elem = keys_out; while (keys_elem != NULL) { if (g_list_find_custom (keys_in, keys_elem->data, gint32_compare) == NULL) { fail_count++; break; } keys_elem = keys_elem->next; } } g_list_free (keys_in); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (set_in); g_list_free (keys_out); g_hash_table_unref (set_out); /** * LIST TEST */ list_out = g_array_new (FALSE, TRUE, sizeof (gint32)); for (i = -2; i < 3; ++i) { g_array_append_val (list_out, i); } printf ("testList({"); first = TRUE; for (i = 0; i < (gint32)list_out->len; ++i) { if (first) first = FALSE; else printf (", "); printf ("%d", g_array_index (list_out, gint32, i)); } printf ("})"); list_in = g_array_new (FALSE, TRUE, sizeof (gint32)); if (t_test_thrift_test_if_test_list (test_client, &list_in, list_out, &error)) { printf (" = {"); first = TRUE; for (i = 0; i < (gint32)list_in->len; ++i) { if (first) first = FALSE; else printf (", "); printf ("%d", g_array_index (list_in, gint32, i)); } printf ("}\n"); if (list_in->len != list_out->len || memcmp (list_in->data, list_out->data, list_in->len * sizeof (gint32)) != 0) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_array_unref (list_in); g_array_unref (list_out); /** * ENUM TEST */ printf("testEnum(ONE)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_ONE, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_ONE) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(TWO)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_TWO, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_TWO) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(THREE)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_THREE, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_THREE) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(FIVE)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_FIVE, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_FIVE) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(EIGHT)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_EIGHT, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_EIGHT) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * TYPEDEF TEST */ printf ("testTypedef(309858235082523)"); if (t_test_thrift_test_if_test_typedef (test_client, &user_id, 309858235082523LL, &error)) { printf(" = %" PRId64 "\n", user_id); if (user_id != 309858235082523LL) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * NESTED MAP TEST */ printf ("testMapMap(1)"); map_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, (GDestroyNotify)g_hash_table_unref); if (t_test_thrift_test_if_test_map_map (test_client, &map_in, 1, &error)) { g_hash_table_iter_init (&hash_table_iter, map_in); printf (" = {"); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { printf ("%d => {", *(gint32 *)key); g_hash_table_iter_init (&inner_hash_table_iter, (GHashTable *)value); while (g_hash_table_iter_next (&inner_hash_table_iter, &key, &value)) { printf ("%d => %d, ", *(gint32 *)key, *(gint32 *)value); } printf ("}, "); } printf ("}\n"); if (g_hash_table_size (map_in) != 2) fail_count++; else { gint32 inner_keys[] = {1, 2, 3, 4}; gint32 i32_key; i32_key = -4; inner_map_in = g_hash_table_lookup (map_in, &i32_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 4) fail_count++; else { keys_in = g_hash_table_get_keys (inner_map_in); keys_in = g_list_sort (keys_in, gint32_compare); for (i = 0; i < 4; i++) { keys_elem = g_list_nth (keys_in, 3 - i); if (*(gint32 *)keys_elem->data != (-1 * inner_keys[i]) || *(gint32 *)g_hash_table_lookup (inner_map_in, keys_elem->data) != (-1 * inner_keys[i])) { fail_count++; break; } } g_list_free (keys_in); } i32_key = 4; inner_map_in = g_hash_table_lookup (map_in, &i32_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 4) fail_count++; else { keys_in = g_hash_table_get_keys (inner_map_in); keys_in = g_list_sort (keys_in, gint32_compare); for (i = 0; i < 4; i++) { keys_elem = g_list_nth (keys_in, i); if (*(gint32 *)keys_elem->data != inner_keys[i] || *(gint32 *)g_hash_table_lookup (inner_map_in, keys_elem->data) != inner_keys[i]) { fail_count++; break; } } g_list_free (keys_in); } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); /** * INSANITY TEST */ insanity_out = g_object_new (T_TEST_TYPE_INSANITY, NULL); g_object_get (insanity_out, "userMap", &user_map, "xtructs", &xtructs, NULL); numberz = T_TEST_NUMBERZ_FIVE; numberz2 = T_TEST_NUMBERZ_EIGHT; user_id_ptr = g_malloc (sizeof *user_id_ptr); *user_id_ptr = 5; user_id_ptr2 = g_malloc (sizeof *user_id_ptr); *user_id_ptr2 = 8; g_hash_table_insert (user_map, (gpointer)numberz, user_id_ptr); g_hash_table_insert (user_map, (gpointer)numberz2, user_id_ptr2); g_hash_table_unref (user_map); xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, "string_thing", "Hello2", "byte_thing", 2, "i32_thing", 2, "i64_thing", 2LL, NULL); xtruct_out2 = g_object_new (T_TEST_TYPE_XTRUCT, "string_thing", "Goodbye4", "byte_thing", 4, "i32_thing", 4, "i64_thing", 4LL, NULL); g_ptr_array_add (xtructs, xtruct_out2); g_ptr_array_add (xtructs, xtruct_out); g_ptr_array_unref (xtructs); map_in = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, (GDestroyNotify)g_hash_table_unref); printf("testInsanity()"); if (t_test_thrift_test_if_test_insanity (test_client, &map_in, insanity_out, &error)) { printf (" = {"); g_hash_table_iter_init (&hash_table_iter, map_in); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { printf ("%" PRId64 " => {", *(TTestUserId *)key); g_hash_table_iter_init (&inner_hash_table_iter, (GHashTable *)value); while (g_hash_table_iter_next (&inner_hash_table_iter, &key, &value)) { printf ("%d => {", (TTestNumberz)key); g_object_get ((TTestInsanity *)value, "userMap", &user_map, "xtructs", &xtructs, NULL); printf ("{"); g_hash_table_iter_init (&user_map_iter, user_map); while (g_hash_table_iter_next (&user_map_iter, &key, &value)) { printf ("%d => %" PRId64 ", ", (TTestNumberz)key, *(TTestUserId *)value); } printf ("}, "); g_hash_table_unref (user_map); printf("{"); for (i = 0; i < (gint32)xtructs->len; ++i) { xtruct_in = g_ptr_array_index (xtructs, i); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); printf ("{\"%s\", %d, %d, %" PRId64 "}, ", string, byte_thing, i32_thing, i64_thing); if (string != NULL) g_free (string); } printf ("}"); g_ptr_array_unref (xtructs); printf ("}, "); } printf("}, "); } printf("}\n"); if (g_hash_table_size (map_in) != 2) fail_count++; else { TTestNumberz numberz_key_values[] = { T_TEST_NUMBERZ_TWO, T_TEST_NUMBERZ_THREE }; gint user_map_values[] = { 5, 8 }; TTestUserId user_id_key; user_id_key = 1; inner_map_in = g_hash_table_lookup (map_in, &user_id_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 2) fail_count++; else { TTestNumberz numberz_key; for (i = 0; i < 2; ++i) { numberz_key = numberz_key_values[i]; insanity_in = g_hash_table_lookup (inner_map_in, (gconstpointer)numberz_key); if (insanity_in == NULL) fail_count++; else { g_object_get (insanity_in, "userMap", &user_map, "xtructs", &xtructs, NULL); if (user_map == NULL) fail_count++; else { if (g_hash_table_size (user_map) != 2) fail_count++; else { for (j = 0; j < 2; ++j) { numberz_key = (TTestNumberz)user_map_values[j]; value = g_hash_table_lookup (user_map, (gconstpointer)numberz_key); if (value == NULL || *(TTestUserId *)value != (TTestUserId)user_map_values[j]) fail_count++; } } g_hash_table_unref (user_map); } if (xtructs == NULL) fail_count++; else { if (xtructs->len != 2) fail_count++; else { xtruct_in = g_ptr_array_index (xtructs, 0); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); if ((string == NULL || strncmp (string, "Goodbye4", 9) != 0) || byte_thing != 4 || i32_thing != 4 || i64_thing != 4) fail_count++; if (string != NULL) g_free (string); xtruct_in = g_ptr_array_index (xtructs, 1); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); if ((string == NULL || strncmp (string, "Hello2", 7) != 0) || byte_thing != 2 || i32_thing != 2 || i64_thing != 2) fail_count++; if (string != NULL) g_free (string); } g_ptr_array_unref (xtructs); } } } } user_id_key = 2; inner_map_in = g_hash_table_lookup (map_in, &user_id_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 1) fail_count++; else { insanity_in = g_hash_table_lookup (inner_map_in, (gconstpointer)T_TEST_NUMBERZ_SIX); if (insanity_in == NULL) fail_count++; else { g_object_get (insanity_in, "userMap", &user_map, "xtructs", &xtructs, NULL); if (user_map == NULL) fail_count++; else { if (g_hash_table_size (user_map) != 0) fail_count++; g_hash_table_unref (user_map); } if (xtructs == NULL) fail_count++; else { if (xtructs->len != 0) fail_count++; g_ptr_array_unref (xtructs); } } } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); g_clear_object (&insanity_out); /* test exception */ printf ("testClient.testException(\"Xception\") =>"); if (!t_test_thrift_test_if_test_exception (test_client, "Xception", &xception, &error) && xception != NULL) { g_object_get (xception, "errorCode", &int32, "message", &string, NULL); printf (" {%u, \"%s\"}\n", int32, string); g_free (string); g_clear_object (&xception); g_error_free (error); error = NULL; } else { printf (" void\nFAILURE\n"); fail_count++; if (xception != NULL) { g_object_unref (xception); xception = NULL; } if (error != NULL) { g_error_free (error); error = NULL; } } printf ("testClient.testException(\"TException\") =>"); if (!t_test_thrift_test_if_test_exception (test_client, "TException", &xception, &error) && xception == NULL && error != NULL) { printf (" Caught TException\n"); g_error_free (error); error = NULL; } else { printf (" void\nFAILURE\n"); fail_count++; g_clear_object (&xception); if (error != NULL) { g_error_free (error); error = NULL; } } printf ("testClient.testException(\"success\") =>"); if (t_test_thrift_test_if_test_exception (test_client, "success", &xception, &error)) printf (" void\n"); else { printf (" void\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_error_free (error); error = NULL; } g_assert (error == NULL); /* test multi exception */ printf ("testClient.testMultiException(\"Xception\", \"test 1\") =>"); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (!t_test_thrift_test_if_test_multi_exception (test_client, &xtruct_in, "Xception", "test 1", &xception, &xception2, &error) && xception != NULL && xception2 == NULL) { g_object_get (xception, "errorCode", &int32, "message", &string, NULL); printf (" {%u, \"%s\"}\n", int32, string); g_free (string); g_object_unref (xception); xception = NULL; g_error_free (error); error = NULL; } else { printf (" result\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_clear_object (&xception2); if (error != NULL) { g_error_free (error); error = NULL; } } g_object_unref (xtruct_in); printf ("testClient.testMultiException(\"Xception2\", \"test 2\") =>"); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (!t_test_thrift_test_if_test_multi_exception (test_client, &xtruct_in, "Xception2", "test 2", &xception, &xception2, &error) && xception == NULL && xception2 != NULL) { g_object_get (xception2, "errorCode", &int32, "struct_thing", &inner_xtruct_in, NULL); g_object_get (inner_xtruct_in, "string_thing", &string, NULL); printf (" {%u, {\"%s\"}}\n", int32, string); g_free (string); g_clear_object (&inner_xtruct_in); g_clear_object (&xception2); g_error_free (error); error = NULL; } else { printf (" result\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_clear_object (&xception2); if (error != NULL) { g_error_free (error); error = NULL; } } g_clear_object (&xtruct_in); printf ("testClient.testMultiException(\"success\", \"test 3\") =>"); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (t_test_thrift_test_if_test_multi_exception (test_client, &xtruct_in, "success", "test 3", &xception, &xception2, &error) && xception == NULL && xception2 == NULL) { g_object_get (xtruct_in, "string_thing", &string, NULL); printf (" {{\"%s\"}}\n", string); g_free (string); } else { printf (" result\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_clear_object (&xception2); if (error != NULL) { g_error_free (error); error = NULL; } } g_clear_object (&xtruct_in); /* test oneway void */ printf ("testClient.testOneway(1) =>"); gettimeofday (&oneway_start, NULL); oneway_result = t_test_thrift_test_if_test_oneway (test_client, 1, &error); gettimeofday (&oneway_end, NULL); timersub (&oneway_end, &oneway_start, &oneway_elapsed); oneway_elapsed_usec = oneway_elapsed.tv_sec * 1000 * 1000 + oneway_elapsed.tv_usec; if (oneway_result) { if (oneway_elapsed_usec > 200 * 1000) { printf (" FAILURE - took %.2f ms\n", (double)oneway_elapsed_usec / 1000.0); fail_count++; } else printf (" success - took %.2f ms\n", (double)oneway_elapsed_usec / 1000.0); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * redo a simple test after the oneway to make sure we aren't "off by * one" -- if the server treated oneway void like normal void, this next * test will fail since it will get the void confirmation rather than * the correct result. In this circumstance, the client will receive the * error: * * application error: Wrong method name */ /** * I32 TEST */ printf ("re-test testI32(-1)"); if (t_test_thrift_test_if_test_i32 (test_client, &int32, -1, &error)) { printf (" = %d\n", int32); if (int32 != -1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } gettimeofday (&time_stop, NULL); timersub (&time_stop, &time_start, &time_elapsed); time_elapsed_usec = time_elapsed.tv_sec * 1000 * 1000 + time_elapsed.tv_usec; printf("Total time: %" PRIu64 " us\n", time_elapsed_usec); time_total_usec += time_elapsed_usec; if (time_elapsed_usec < time_min_usec) time_min_usec = time_elapsed_usec; if (time_elapsed_usec > time_max_usec) time_max_usec = time_elapsed_usec; thrift_transport_close (transport, &error); } else { printf ("Connect failed: %s\n", error->message); g_error_free (error); error = NULL; goto out; } } /* All done---output statistics */ puts ("\nAll tests done."); printf("Number of failures: %d\n", fail_count); time_avg_usec = time_total_usec / num_tests; printf ("Min time: %" PRIu64 " us\n", time_min_usec); printf ("Max time: %" PRIu64 " us\n", time_max_usec); printf ("Avg time: %" PRIu64 " us\n", time_avg_usec); out: g_clear_object(&second_service); g_clear_object(&protocol2); g_clear_object(&test_client); g_clear_object(&protocol); g_clear_object(&multiplexed_protocol); g_clear_object(&transport); g_clear_object(&socket); if (ssl) { thrift_ssl_socket_finalize_openssl(); } return fail_count; } thrift-0.19.0/test/c_glib/src/thrift_test_handler.h0000644000000000000000000003530014303740367022301 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_HANDLER_H #define _THRIFT_TEST_HANDLER_H #include #include #include "../gen-c_glib/t_test_thrift_test.h" G_BEGIN_DECLS /* A handler that implements the TTestThriftTestIf interface */ #define TYPE_THRIFT_TEST_HANDLER (thrift_test_handler_get_type ()) #define THRIFT_TEST_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ TYPE_THRIFT_TEST_HANDLER, \ ThriftTestHandler)) #define IS_THRIFT_TEST_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ TYPE_THRIFT_TEST_HANDLER)) #define THRIFT_TEST_HANDLER_CLASS(c) \ (G_TYPE_CHECK_CLASS_CAST ((c), \ TYPE_THRIFT_TEST_HANDLER, \ ThriftTestHandlerClass)) #define IS_THRIFT_TEST_HANDLER_CLASS(c) \ (G_TYPE_CHECK_CLASS_TYPE ((c), \ TYPE_THRIFT_TEST_HANDLER)) #define THRIFT_TEST_HANDLER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ TYPE_THRIFT_TEST_HANDLER, \ ThriftTestHandlerClass)) typedef struct _ThriftTestHandler ThriftTestHandler; typedef struct _ThriftTestHandlerClass ThriftTestHandlerClass; struct _ThriftTestHandler { TTestThriftTestHandler parent; }; struct _ThriftTestHandlerClass { TTestThriftTestHandlerClass parent; gboolean (*test_void) (TTestThriftTestIf *iface, GError **error); gboolean (*test_string) (TTestThriftTestIf *iface, gchar **_return, const gchar *thing, GError **error); gboolean (*test_bool) (TTestThriftTestIf *iface, gboolean*_return, const gboolean thing, GError **error); gboolean (*test_byte) (TTestThriftTestIf *iface, gint8*_return, const gint8 thing, GError **error); gboolean (*test_i32) (TTestThriftTestIf *iface, gint32*_return, const gint32 thing, GError **error); gboolean (*test_i64) (TTestThriftTestIf *iface, gint64*_return, const gint64 thing, GError **error); gboolean (*test_double) (TTestThriftTestIf *iface, gdouble*_return, const gdouble thing, GError **error); gboolean (*test_binary) (TTestThriftTestIf *iface, GByteArray **_return, const GByteArray *thing, GError **error); gboolean (*test_struct) (TTestThriftTestIf *iface, TTestXtruct **_return, const TTestXtruct *thing, GError **error); gboolean (*test_nest) (TTestThriftTestIf *iface, TTestXtruct2 **_return, const TTestXtruct2 *thing, GError **error); gboolean (*test_map) (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error); gboolean (*test_string_map) (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error); gboolean (*test_set) (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error); gboolean (*test_list) (TTestThriftTestIf *iface, GArray **_return, const GArray *thing, GError **error); gboolean (*test_enum) (TTestThriftTestIf *iface, TTestNumberz*_return, const TTestNumberz thing, GError **error); gboolean (*test_typedef) (TTestThriftTestIf *iface, TTestUserId*_return, const TTestUserId thing, GError **error); gboolean (*test_map_map) (TTestThriftTestIf *iface, GHashTable **_return, const gint32 hello, GError **error); gboolean (*test_insanity) (TTestThriftTestIf *iface, GHashTable **_return, const TTestInsanity *argument, GError **error); gboolean (*test_multi) (TTestThriftTestIf *iface, TTestXtruct **_return, const gint8 arg0, const gint32 arg1, const gint64 arg2, const GHashTable *arg3, const TTestNumberz arg4, const TTestUserId arg5, GError **error); gboolean (*test_exception) (TTestThriftTestIf *iface, const gchar *arg, TTestXception **err1, GError **error); gboolean (*test_multi_exception) (TTestThriftTestIf *iface, TTestXtruct **_return, const gchar *arg0, const gchar *arg1, TTestXception **err1, TTestXception2 **err2, GError **error); gboolean (*test_oneway) (TTestThriftTestIf *iface, const gint32 secondsToSleep, GError **error); }; /* Used by THRIFT_TEST_HANDLER_GET_TYPE */ GType thrift_test_handler_get_type (void); gboolean thrift_test_handler_test_void (TTestThriftTestIf *iface, GError **error); gboolean thrift_test_handler_test_string (TTestThriftTestIf *iface, gchar **_return, const gchar *thing, GError **error); gboolean thrift_test_handler_test_byte (TTestThriftTestIf *iface, gint8*_return, const gint8 thing, GError **error); gboolean t_test_thrift_test_if_test_i32 (TTestThriftTestIf *iface, gint32*_return, const gint32 thing, GError **error); gboolean thrift_test_handler_test_i64 (TTestThriftTestIf *iface, gint64*_return, const gint64 thing, GError **error); gboolean thrift_test_handler_test_double (TTestThriftTestIf *iface, gdouble*_return, const gdouble thing, GError **error); gboolean thrift_test_handler_test_struct (TTestThriftTestIf *iface, TTestXtruct **_return, const TTestXtruct *thing, GError **error); gboolean thrift_test_handler_test_nest (TTestThriftTestIf *iface, TTestXtruct2 **_return, const TTestXtruct2 *thing, GError **error); gboolean thrift_test_handler_test_map (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error); gboolean thrift_test_handler_test_string_map (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error); gboolean thrift_test_handler_test_set (TTestThriftTestIf *iface, GHashTable **_return, const GHashTable *thing, GError **error); gboolean thrift_test_handler_test_list (TTestThriftTestIf *iface, GArray **_return, const GArray *thing, GError **error); gboolean thrift_test_handler_test_typedef (TTestThriftTestIf *iface, TTestUserId*_return, const TTestUserId thing, GError **error); gboolean thrift_test_handler_test_map_map (TTestThriftTestIf *iface, GHashTable **_return, const gint32 hello, GError **error); gboolean thrift_test_handler_test_insanity (TTestThriftTestIf *iface, GHashTable **_return, const TTestInsanity *argument, GError **error); gboolean thrift_test_handler_test_multi (TTestThriftTestIf *iface, TTestXtruct **_return, const gint8 arg0, const gint32 arg1, const gint64 arg2, const GHashTable *arg3, const TTestNumberz arg4, const TTestUserId arg5, GError **error); gboolean thrift_test_handler_test_exception (TTestThriftTestIf *iface, const gchar *arg, TTestXception **err1, GError **error); gboolean thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, TTestXtruct **_return, const gchar *arg0, const gchar *arg1, TTestXception **err1, TTestXception2 **err2, GError **error); gboolean thrift_test_handler_test_oneway (TTestThriftTestIf *iface, const gint32 secondsToSleep, GError **error); G_END_DECLS #endif /* _THRIFT_TEST_HANDLER_H */ thrift-0.19.0/test/c_glib/src/thrift_second_service_handler.h0000644000000000000000000000551614303740367024323 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _SECOND_SERVICE_HANDLER_H #define _SECOND_SERVICE_HANDLER_H #include #include #include "../gen-c_glib/t_test_second_service.h" G_BEGIN_DECLS /* A handler that implements the TTestSecondServiceIf interface */ #define TYPE_SECOND_SERVICE_HANDLER (second_service_handler_get_type ()) #define SECOND_SERVICE_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ TYPE_SECOND_SERVICE_HANDLER, \ SecondServiceHandler)) #define IS_SECOND_SERVICE_HANDLER(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ TYPE_SECOND_SERVICE_HANDLER)) #define SECOND_SERVICE_HANDLER_CLASS(c) \ (G_TYPE_CHECK_CLASS_CAST ((c), \ TYPE_SECOND_SERVICE_HANDLER, \ SecondServiceHandlerClass)) #define IS_SECOND_SERVICE_HANDLER_CLASS(c) \ (G_TYPE_CHECK_CLASS_TYPE ((c), \ TYPE_SECOND_SERVICE_HANDLER)) #define SECOND_SERVICE_HANDLER_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ TYPE_SECOND_SERVICE_HANDLER, \ SecondServiceHandlerClass)) typedef struct _SecondServiceHandler SecondServiceHandler; typedef struct _SecondServiceHandlerClass SecondServiceHandlerClass; struct _SecondServiceHandler { TTestSecondServiceHandler parent; }; struct _SecondServiceHandlerClass { TTestSecondServiceHandlerClass parent; }; /* Used by SECOND_SERVICE_HANDLER_GET_TYPE */ GType second_service_handler_get_type (void); gboolean second_service_handler_blah_blah (TTestSecondServiceIf *iface, GError **error); gboolean second_service_handler_secondtest_string (TTestSecondServiceIf *iface, gchar ** _return, const gchar * thing, GError **error); G_END_DECLS #endif /* _SECOND_SERVICE_HANDLER_H */ thrift-0.19.0/test/c_glib/Makefile.in0000644000000000000000000006762214472652520017366 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ check_PROGRAMS = test_client$(EXEEXT) test_server$(EXEEXT) subdir = test/c_glib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libtestcglib_la_DEPENDENCIES = \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la am__dirstamp = $(am__leading_dot)dirstamp nodist_libtestcglib_la_OBJECTS = gen-c_glib/t_test_second_service.lo \ gen-c_glib/t_test_thrift_test.lo \ gen-c_glib/t_test_thrift_test_types.lo libtestcglib_la_OBJECTS = $(nodist_libtestcglib_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_test_client_OBJECTS = src/test_client.$(OBJEXT) test_client_OBJECTS = $(am_test_client_OBJECTS) test_client_DEPENDENCIES = libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la am_test_server_OBJECTS = src/thrift_test_handler.$(OBJEXT) \ src/thrift_second_service_handler.$(OBJEXT) \ src/test_server.$(OBJEXT) test_server_OBJECTS = $(am_test_server_OBJECTS) test_server_DEPENDENCIES = libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(nodist_libtestcglib_la_SOURCES) $(test_client_SOURCES) \ $(test_server_SOURCES) DIST_SOURCES = $(test_client_SOURCES) $(test_server_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc noinst_LTLIBRARIES = libtestcglib.la nodist_libtestcglib_la_SOURCES = \ gen-c_glib/t_test_second_service.c \ gen-c_glib/t_test_second_service.h \ gen-c_glib/t_test_thrift_test.c \ gen-c_glib/t_test_thrift_test.h \ gen-c_glib/t_test_thrift_test_types.c \ gen-c_glib/t_test_thrift_test_types.h libtestcglib_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la test_client_SOURCES = \ src/test_client.c test_client_LDADD = \ libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la test_server_SOURCES = \ src/thrift_test_handler.c \ src/thrift_test_handler.h \ src/thrift_second_service_handler.c \ src/thrift_second_service_handler.h \ src/test_server.c test_server_LDADD = \ libtestcglib.la \ $(top_builddir)/lib/c_glib/libthrift_c_glib.la AM_CFLAGS = -g -Wall -Wextra $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) AM_CXXFLAGS = $(AM_CFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@ EXTRA_DIST = \ src all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/c_glib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/c_glib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } gen-c_glib/$(am__dirstamp): @$(MKDIR_P) gen-c_glib @: > gen-c_glib/$(am__dirstamp) gen-c_glib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) gen-c_glib/$(DEPDIR) @: > gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/t_test_second_service.lo: gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/t_test_thrift_test.lo: gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) gen-c_glib/t_test_thrift_test_types.lo: gen-c_glib/$(am__dirstamp) \ gen-c_glib/$(DEPDIR)/$(am__dirstamp) libtestcglib.la: $(libtestcglib_la_OBJECTS) $(libtestcglib_la_DEPENDENCIES) $(EXTRA_libtestcglib_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(libtestcglib_la_OBJECTS) $(libtestcglib_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list src/$(am__dirstamp): @$(MKDIR_P) src @: > src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/$(DEPDIR) @: > src/$(DEPDIR)/$(am__dirstamp) src/test_client.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) test_client$(EXEEXT): $(test_client_OBJECTS) $(test_client_DEPENDENCIES) $(EXTRA_test_client_DEPENDENCIES) @rm -f test_client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_client_OBJECTS) $(test_client_LDADD) $(LIBS) src/thrift_test_handler.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/thrift_second_service_handler.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/test_server.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) test_server$(EXEEXT): $(test_server_OBJECTS) $(test_server_DEPENDENCIES) $(EXTRA_test_server_DEPENDENCIES) @rm -f test_server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_server_OBJECTS) $(test_server_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f gen-c_glib/*.$(OBJEXT) -rm -f gen-c_glib/*.lo -rm -f src/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/t_test_second_service.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/t_test_thrift_test.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-c_glib/$(DEPDIR)/t_test_thrift_test_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/test_server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/thrift_second_service_handler.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/thrift_test_handler.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf gen-c_glib/.libs gen-c_glib/_libs style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f gen-c_glib/$(DEPDIR)/$(am__dirstamp) -rm -f gen-c_glib/$(am__dirstamp) -rm -f src/$(DEPDIR)/$(am__dirstamp) -rm -f src/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf gen-c_glib/$(DEPDIR) src/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf gen-c_glib/$(DEPDIR) src/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am dist-hook \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile precross: libtestcglib.la test_client test_server # # Common thrift code generation rules # gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen c_glib -r $< clean-local: $(RM) -r gen-c_glib/ $(RM) test_client $(RM) test_server $(RM) libtestcglib.la find . -type f -iname "*.o" | xargs rm -f dist-hook: $(RM) -r $(distdir)/gen-c_glib/ $(RM) $(distdir)/test_client $(RM) $(distdir)/test_server $(RM) $(distdir)/libtestcglib.la find $(distdir) -type f -iname "*.o" | xargs rm -f # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/result.js0000644000000000000000000000472514303740367015751 0ustar00rootroot00000000000000/* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ $.getJSON('results.json', function(results) { $(document).ready(function() { var transport = 3; var socket = 4; var success = 5; var expected = 6; var returnCode = 7; var logFile = 8; testTable = $('#test_results').DataTable({ data: results['results'], columnDefs: [ { targets: 3, render: function(data, type, row) { return row[transport] + '-' + row[socket]; }, }, { targets: 4, render: function(data, type, row) { return (row[success] ? 'success' : 'failure') + '(' + (row[returnCode] == 128 ? 'timeout' : row[returnCode]) + ')' + '(Server, ' + 'Client)'; }, }, { targets: 5, render: function(data, type, row) { // 'yes' rather than 'expected' to ease search return row[expected] ? 'yes' : 'unexpected'; }, } ], }); $('#test_results_filter label input').focus().val('unexpected failure'); $('#test_info').text( "Test Date: " + results['date'] + "\n" + "Revision: " + results['revision'] + "\n" + "Platform: " + results['platform'] + "\n" + "Test duration: " + results['duration']) + " seconds"; }); }); thrift-0.19.0/test/known_failures_Linux.json0000644000000000000000000012270014303740367021167 0ustar00rootroot00000000000000[ "cl-c_glib_binary_buffered-ip", "cl-c_glib_binary_framed-ip", "cl-c_glib_multi-binary_buffered-ip", "cl-c_glib_multi-binary_framed-ip", "cl-c_glib_multi_buffered-ip", "cl-c_glib_multi_framed-ip", "cl-go_binary_buffered-ip", "cl-go_binary_framed-ip", "cl-netstd_binary_buffered-ip", "cl-netstd_binary_framed-ip", "cl-rb_binary-accel_buffered-ip", "cl-rb_binary-accel_framed-ip", "cl-rb_binary_buffered-ip", "cl-rb_binary_framed-ip", "cl-rs_binary_buffered-ip", "cl-rs_binary_framed-ip", "cl-rs_multi-binary_buffered-ip", "cl-rs_multi-binary_framed-ip", "cl-rs_multi_buffered-ip", "cl-rs_multi_framed-ip", "cpp-cpp_binary_websocket-domain", "cpp-cpp_binary_websocket-ip", "cpp-cpp_binary_websocket-ip-ssl", "cpp-cpp_compact_websocket-domain", "cpp-cpp_compact_websocket-ip", "cpp-cpp_compact_websocket-ip-ssl", "cpp-cpp_header_websocket-domain", "cpp-cpp_header_websocket-ip", "cpp-cpp_header_websocket-ip-ssl", "cpp-cpp_json_websocket-domain", "cpp-cpp_json_websocket-ip", "cpp-cpp_json_websocket-ip-ssl", "cpp-cpp_multi-binary_websocket-domain", "cpp-cpp_multi-binary_websocket-ip", "cpp-cpp_multi-binary_websocket-ip-ssl", "cpp-cpp_multic-compact_websocket-domain", "cpp-cpp_multic-compact_websocket-ip", "cpp-cpp_multic-compact_websocket-ip-ssl", "cpp-cpp_multic_websocket-domain", "cpp-cpp_multic_websocket-ip", "cpp-cpp_multic_websocket-ip-ssl", "cpp-cpp_multih-header_websocket-domain", "cpp-cpp_multih-header_websocket-ip", "cpp-cpp_multih-header_websocket-ip-ssl", "cpp-cpp_multih_websocket-domain", "cpp-cpp_multih_websocket-ip", "cpp-cpp_multih_websocket-ip-ssl", "cpp-cpp_multij-json_websocket-domain", "cpp-cpp_multij-json_websocket-ip", "cpp-cpp_multij-json_websocket-ip-ssl", "cpp-cpp_multij_websocket-domain", "cpp-cpp_multij_websocket-ip", "cpp-cpp_multij_websocket-ip-ssl", "cpp-cpp_multi_websocket-domain", "cpp-cpp_multi_websocket-ip", "cpp-cpp_multi_websocket-ip-ssl", "cpp-dart_binary_http-ip", "cpp-dart_compact_http-ip", "cpp-dart_json_http-ip", "cpp-dart_multi-binary_http-ip", "cpp-dart_multic-compact_http-ip", "cpp-dart_multij-json_http-ip", "cpp-go_binary_http-ip", "cpp-go_binary_http-ip-ssl", "cpp-go_compact_http-ip", "cpp-go_compact_http-ip-ssl", "cpp-go_header_http-ip", "cpp-go_header_http-ip-ssl", "cpp-go_json_http-ip", "cpp-go_json_http-ip-ssl", "cpp-go_multi-binary_http-ip", "cpp-go_multi-binary_http-ip-ssl", "cpp-go_multic-compact_http-ip", "cpp-go_multic-compact_http-ip-ssl", "cpp-go_multih-header_http-ip", "cpp-go_multih-header_http-ip-ssl", "cpp-go_multij-json_http-ip", "cpp-go_multij-json_http-ip-ssl", "cpp-java_binary_http-ip", "cpp-java_binary_http-ip-ssl", "cpp-java_compact_http-ip", "cpp-java_compact_http-ip-ssl", "cpp-java_json_http-ip", "cpp-java_json_http-ip-ssl", "cpp-java_multi-binary_http-ip", "cpp-java_multi-binary_http-ip-ssl", "cpp-java_multic-compact_http-ip", "cpp-java_multic-compact_http-ip-ssl", "cpp-java_multic_http-ip", "cpp-java_multic_http-ip-ssl", "cpp-java_multij-json_http-ip", "cpp-java_multij-json_http-ip-ssl", "cpp-java_multij_http-ip", "cpp-java_multij_http-ip-ssl", "cpp-java_multi_http-ip", "cpp-java_multi_http-ip-ssl", "cpp-netstd_binary_buffered-ip", "cpp-netstd_binary_buffered-ip-ssl", "cpp-netstd_binary_framed-ip", "cpp-netstd_binary_framed-ip-ssl", "cpp-netstd_compact_buffered-ip", "cpp-netstd_compact_buffered-ip-ssl", "cpp-netstd_compact_framed-ip", "cpp-netstd_compact_framed-ip-ssl", "cpp-netstd_json_buffered-ip", "cpp-netstd_json_buffered-ip-ssl", "cpp-netstd_json_framed-ip", "cpp-netstd_json_framed-ip-ssl", "cpp-netstd_multi-binary_buffered-ip", "cpp-netstd_multi-binary_buffered-ip-ssl", "cpp-netstd_multi-binary_framed-ip", "cpp-netstd_multi-binary_framed-ip-ssl", "cpp-netstd_multic-compact_buffered-ip", "cpp-netstd_multic-compact_buffered-ip-ssl", "cpp-netstd_multic-compact_framed-ip", "cpp-netstd_multic-compact_framed-ip-ssl", "cpp-netstd_multij-json_buffered-ip", "cpp-netstd_multij-json_buffered-ip-ssl", "cpp-netstd_multij-json_framed-ip", "cpp-netstd_multij-json_framed-ip-ssl", "cpp-nodejs_binary_http-domain", "cpp-nodejs_binary_http-ip", "cpp-nodejs_binary_http-ip-ssl", "cpp-nodejs_binary_websocket-domain", "cpp-nodejs_compact_http-domain", "cpp-nodejs_compact_http-ip", "cpp-nodejs_compact_http-ip-ssl", "cpp-nodejs_compact_websocket-domain", "cpp-nodejs_header_http-domain", "cpp-nodejs_header_http-ip", "cpp-nodejs_header_http-ip-ssl", "cpp-nodejs_header_websocket-domain", "cpp-nodejs_header_websocket-ip", "cpp-nodejs_header_websocket-ip-ssl", "cpp-nodejs_json_http-domain", "cpp-nodejs_json_http-ip", "cpp-nodejs_json_http-ip-ssl", "cpp-nodejs_json_websocket-domain", "cpp-nodejs_multi-binary_http-domain", "cpp-nodejs_multi-binary_http-ip", "cpp-nodejs_multi-binary_http-ip-ssl", "cpp-nodejs_multi-binary_websocket-domain", "cpp-nodejs_multic-compact_http-domain", "cpp-nodejs_multic-compact_http-ip", "cpp-nodejs_multic-compact_http-ip-ssl", "cpp-nodejs_multic-compact_websocket-domain", "cpp-nodejs_multih-header_http-domain", "cpp-nodejs_multih-header_http-ip", "cpp-nodejs_multih-header_http-ip-ssl", "cpp-nodejs_multih-header_websocket-domain", "cpp-nodejs_multih-header_websocket-ip", "cpp-nodejs_multih-header_websocket-ip-ssl", "cpp-nodejs_multij-json_http-domain", "cpp-nodejs_multij-json_http-ip", "cpp-nodejs_multij-json_http-ip-ssl", "cpp-nodejs_multij-json_websocket-domain", "cpp-php_binary-accel_buffered-ip", "cpp-php_binary-accel_framed-ip", "cpp-php_json_buffered-ip", "cpp-php_json_framed-ip", "cpp-php_multi-accel_buffered-ip", "cpp-php_multi-accel_framed-ip", "cpp-php_multij-json_buffered-ip", "cpp-php_multij-json_framed-ip", "cpp-py3_binary-accel_http-domain", "cpp-py3_binary-accel_http-ip", "cpp-py3_binary-accel_http-ip-ssl", "cpp-py3_binary_http-domain", "cpp-py3_binary_http-ip", "cpp-py3_binary_http-ip-ssl", "cpp-py3_compact-accelc_http-domain", "cpp-py3_compact-accelc_http-ip", "cpp-py3_compact-accelc_http-ip-ssl", "cpp-py3_compact_http-domain", "cpp-py3_compact_http-ip", "cpp-py3_compact_http-ip-ssl", "cpp-py3_header_http-domain", "cpp-py3_header_http-ip", "cpp-py3_header_http-ip-ssl", "cpp-py3_json_http-domain", "cpp-py3_json_http-ip", "cpp-py3_json_http-ip-ssl", "cpp-py3_multi-accel_http-domain", "cpp-py3_multi-accel_http-ip", "cpp-py3_multi-accel_http-ip-ssl", "cpp-py3_multi-binary_http-domain", "cpp-py3_multi-binary_http-ip", "cpp-py3_multi-binary_http-ip-ssl", "cpp-py3_multi-multia_http-domain", "cpp-py3_multi-multia_http-ip", "cpp-py3_multi-multia_http-ip-ssl", "cpp-py3_multic-accelc_http-domain", "cpp-py3_multic-accelc_http-ip", "cpp-py3_multic-accelc_http-ip-ssl", "cpp-py3_multic-compact_http-domain", "cpp-py3_multic-compact_http-ip", "cpp-py3_multic-compact_http-ip-ssl", "cpp-py3_multic-multiac_http-domain", "cpp-py3_multic-multiac_http-ip", "cpp-py3_multic-multiac_http-ip-ssl", "cpp-py3_multic_http-domain", "cpp-py3_multic_http-ip", "cpp-py3_multic_http-ip-ssl", "cpp-py3_multih-header_http-domain", "cpp-py3_multih-header_http-ip", "cpp-py3_multih-header_http-ip-ssl", "cpp-py3_multih_http-domain", "cpp-py3_multih_http-ip", "cpp-py3_multih_http-ip-ssl", "cpp-py3_multij-json_http-domain", "cpp-py3_multij-json_http-ip", "cpp-py3_multij-json_http-ip-ssl", "cpp-py3_multij_http-domain", "cpp-py3_multij_http-ip", "cpp-py3_multij_http-ip-ssl", "cpp-py3_multi_http-domain", "cpp-py3_multi_http-ip", "cpp-py3_multi_http-ip-ssl", "cpp-py_binary-accel_http-domain", "cpp-py_binary-accel_http-ip", "cpp-py_binary-accel_http-ip-ssl", "cpp-py_binary_http-domain", "cpp-py_binary_http-ip", "cpp-py_binary_http-ip-ssl", "cpp-py_compact-accelc_http-domain", "cpp-py_compact-accelc_http-ip", "cpp-py_compact-accelc_http-ip-ssl", "cpp-py_compact_http-domain", "cpp-py_compact_http-ip", "cpp-py_compact_http-ip-ssl", "cpp-py_header_http-domain", "cpp-py_header_http-ip", "cpp-py_header_http-ip-ssl", "cpp-py_json_http-domain", "cpp-py_json_http-ip", "cpp-py_json_http-ip-ssl", "cpp-py_multi-accel_http-domain", "cpp-py_multi-accel_http-ip", "cpp-py_multi-accel_http-ip-ssl", "cpp-py_multi-binary_http-domain", "cpp-py_multi-binary_http-ip", "cpp-py_multi-binary_http-ip-ssl", "cpp-py_multi-multia_http-domain", "cpp-py_multi-multia_http-ip", "cpp-py_multi-multia_http-ip-ssl", "cpp-py_multic-accelc_http-domain", "cpp-py_multic-accelc_http-ip", "cpp-py_multic-accelc_http-ip-ssl", "cpp-py_multic-compact_http-domain", "cpp-py_multic-compact_http-ip", "cpp-py_multic-compact_http-ip-ssl", "cpp-py_multic-multiac_http-domain", "cpp-py_multic-multiac_http-ip", "cpp-py_multic-multiac_http-ip-ssl", "cpp-py_multic_http-domain", "cpp-py_multic_http-ip", "cpp-py_multic_http-ip-ssl", "cpp-py_multih-header_http-domain", "cpp-py_multih-header_http-ip", "cpp-py_multih-header_http-ip-ssl", "cpp-py_multih_http-domain", "cpp-py_multih_http-ip", "cpp-py_multih_http-ip-ssl", "cpp-py_multij-json_http-domain", "cpp-py_multij-json_http-ip", "cpp-py_multij-json_http-ip-ssl", "cpp-py_multij_http-domain", "cpp-py_multij_http-ip", "cpp-py_multij_http-ip-ssl", "cpp-py_multi_http-domain", "cpp-py_multi_http-ip", "cpp-py_multi_http-ip-ssl", "c_glib-netstd_binary_buffered-ip", "c_glib-netstd_binary_framed-ip", "c_glib-netstd_compact_buffered-ip", "c_glib-netstd_compact_framed-ip", "c_glib-netstd_multi-binary_buffered-ip", "c_glib-netstd_multi-binary_framed-ip", "c_glib-netstd_multic-compact_buffered-ip", "c_glib-netstd_multic-compact_framed-ip", "d-cl_binary_buffered-ip", "d-cl_binary_framed-ip", "d-cpp_binary_buffered-ip", "d-cpp_binary_buffered-ip-ssl", "d-cpp_binary_framed-ip", "d-cpp_binary_framed-ip-ssl", "d-cpp_binary_http-ip", "d-cpp_binary_http-ip-ssl", "d-cpp_binary_zlib-ip", "d-cpp_binary_zlib-ip-ssl", "d-cpp_compact_buffered-ip", "d-cpp_compact_buffered-ip-ssl", "d-cpp_compact_framed-ip", "d-cpp_compact_framed-ip-ssl", "d-cpp_compact_http-ip", "d-cpp_compact_http-ip-ssl", "d-cpp_compact_zlib-ip", "d-cpp_compact_zlib-ip-ssl", "d-cpp_json_buffered-ip", "d-cpp_json_buffered-ip-ssl", "d-cpp_json_framed-ip", "d-cpp_json_framed-ip-ssl", "d-cpp_json_http-ip", "d-cpp_json_http-ip-ssl", "d-cpp_json_zlib-ip", "d-cpp_json_zlib-ip-ssl", "d-dart_binary_http-ip", "d-dart_compact_http-ip", "d-dart_json_http-ip", "d-d_binary_http-ip", "d-d_compact_http-ip", "d-d_json_http-ip", "d-go_binary_http-ip", "d-go_binary_http-ip-ssl", "d-go_compact_http-ip", "d-go_compact_http-ip-ssl", "d-go_json_http-ip", "d-go_json_http-ip-ssl", "d-java_binary_http-ip", "d-java_binary_http-ip-ssl", "d-java_compact_http-ip", "d-java_compact_http-ip-ssl", "d-java_json_http-ip", "d-java_json_http-ip-ssl", "d-js_json_http-ip", "d-netstd_binary_buffered-ip", "d-netstd_binary_buffered-ip-ssl", "d-netstd_binary_framed-ip", "d-netstd_binary_framed-ip-ssl", "d-netstd_compact_buffered-ip", "d-netstd_compact_buffered-ip-ssl", "d-netstd_compact_framed-ip", "d-netstd_compact_framed-ip-ssl", "d-netstd_json_buffered-ip", "d-netstd_json_buffered-ip-ssl", "d-netstd_json_framed-ip", "d-netstd_json_framed-ip-ssl", "d-nodejs_binary_buffered-ip", "d-nodejs_binary_buffered-ip-ssl", "d-nodejs_binary_framed-ip", "d-nodejs_binary_framed-ip-ssl", "d-nodejs_binary_http-ip", "d-nodejs_binary_http-ip-ssl", "d-nodejs_compact_buffered-ip", "d-nodejs_compact_buffered-ip-ssl", "d-nodejs_compact_framed-ip", "d-nodejs_compact_framed-ip-ssl", "d-nodejs_compact_http-ip", "d-nodejs_compact_http-ip-ssl", "d-nodejs_json_buffered-ip", "d-nodejs_json_buffered-ip-ssl", "d-nodejs_json_framed-ip", "d-nodejs_json_framed-ip-ssl", "d-nodejs_json_http-ip", "d-nodejs_json_http-ip-ssl", "d-nodets_binary_buffered-ip", "d-py3_binary-accel_buffered-ip", "d-py3_binary-accel_buffered-ip-ssl", "d-py3_binary-accel_framed-ip", "d-py3_binary-accel_framed-ip-ssl", "d-py3_binary-accel_http-ip", "d-py3_binary-accel_http-ip-ssl", "d-py3_binary-accel_zlib-ip", "d-py3_binary-accel_zlib-ip-ssl", "d-py3_binary_buffered-ip", "d-py3_binary_buffered-ip-ssl", "d-py3_binary_framed-ip", "d-py3_binary_framed-ip-ssl", "d-py3_binary_http-ip", "d-py3_binary_http-ip-ssl", "d-py3_binary_zlib-ip", "d-py3_binary_zlib-ip-ssl", "d-py3_compact-accelc_buffered-ip", "d-py3_compact-accelc_buffered-ip-ssl", "d-py3_compact-accelc_framed-ip", "d-py3_compact-accelc_framed-ip-ssl", "d-py3_compact-accelc_http-ip", "d-py3_compact-accelc_http-ip-ssl", "d-py3_compact-accelc_zlib-ip", "d-py3_compact-accelc_zlib-ip-ssl", "d-py3_compact_buffered-ip", "d-py3_compact_buffered-ip-ssl", "d-py3_compact_framed-ip", "d-py3_compact_framed-ip-ssl", "d-py3_compact_http-ip", "d-py3_compact_http-ip-ssl", "d-py3_compact_zlib-ip", "d-py3_compact_zlib-ip-ssl", "d-py3_json_buffered-ip", "d-py3_json_buffered-ip-ssl", "d-py3_json_framed-ip", "d-py3_json_framed-ip-ssl", "d-py3_json_http-ip", "d-py3_json_http-ip-ssl", "d-py3_json_zlib-ip", "d-py3_json_zlib-ip-ssl", "d-py_binary-accel_buffered-ip", "d-py_binary-accel_buffered-ip-ssl", "d-py_binary-accel_framed-ip", "d-py_binary-accel_framed-ip-ssl", "d-py_binary-accel_http-ip", "d-py_binary-accel_http-ip-ssl", "d-py_binary-accel_zlib-ip", "d-py_binary-accel_zlib-ip-ssl", "d-py_binary_buffered-ip", "d-py_binary_buffered-ip-ssl", "d-py_binary_framed-ip", "d-py_binary_framed-ip-ssl", "d-py_binary_http-ip", "d-py_binary_http-ip-ssl", "d-py_binary_zlib-ip", "d-py_binary_zlib-ip-ssl", "d-py_compact-accelc_buffered-ip", "d-py_compact-accelc_buffered-ip-ssl", "d-py_compact-accelc_framed-ip", "d-py_compact-accelc_framed-ip-ssl", "d-py_compact-accelc_http-ip", "d-py_compact-accelc_http-ip-ssl", "d-py_compact-accelc_zlib-ip", "d-py_compact-accelc_zlib-ip-ssl", "d-py_compact_buffered-ip", "d-py_compact_buffered-ip-ssl", "d-py_compact_framed-ip", "d-py_compact_framed-ip-ssl", "d-py_compact_http-ip", "d-py_compact_http-ip-ssl", "d-py_compact_zlib-ip", "d-py_compact_zlib-ip-ssl", "d-py_json_buffered-ip", "d-py_json_buffered-ip-ssl", "d-py_json_framed-ip", "d-py_json_framed-ip-ssl", "d-py_json_http-ip", "d-py_json_http-ip-ssl", "d-py_json_zlib-ip", "d-py_json_zlib-ip-ssl", "erl-cpp_binary_buffered-ip", "erl-cpp_compact_buffered-ip", "erl-netstd_binary_buffered-ip", "erl-netstd_binary_buffered-ip-ssl", "erl-netstd_binary_framed-ip", "erl-netstd_binary_framed-ip-ssl", "erl-netstd_compact_buffered-ip", "erl-netstd_compact_buffered-ip-ssl", "erl-netstd_compact_framed-ip", "erl-netstd_compact_framed-ip-ssl", "erl-nodejs_binary_buffered-ip", "erl-nodejs_compact_buffered-ip", "erl-nodets_binary_buffered-ip", "erl-rb_binary-accel_buffered-ip", "erl-rb_binary-accel_buffered-ip-ssl", "erl-rb_binary-accel_framed-ip", "erl-rb_binary-accel_framed-ip-ssl", "erl-rb_binary_buffered-ip", "erl-rb_binary_buffered-ip-ssl", "erl-rb_binary_framed-ip", "erl-rb_binary_framed-ip-ssl", "erl-rb_compact_buffered-ip", "erl-rb_compact_buffered-ip-ssl", "erl-rb_compact_framed-ip", "erl-rb_compact_framed-ip-ssl", "go-cpp_binary_http-ip", "go-cpp_binary_http-ip-ssl", "go-cpp_compact_http-ip", "go-cpp_compact_http-ip-ssl", "go-cpp_header_http-ip", "go-cpp_header_http-ip-ssl", "go-cpp_json_http-ip", "go-cpp_json_http-ip-ssl", "go-dart_binary_http-ip", "go-dart_compact_http-ip", "go-dart_json_http-ip", "go-d_binary_http-ip", "go-d_binary_http-ip-ssl", "go-d_compact_http-ip", "go-d_compact_http-ip-ssl", "go-d_json_http-ip", "go-d_json_http-ip-ssl", "go-java_binary_http-ip", "go-java_binary_http-ip-ssl", "go-java_compact_http-ip", "go-java_compact_http-ip-ssl", "go-java_json_http-ip", "go-java_json_http-ip-ssl", "go-netstd_binary_buffered-ip", "go-netstd_binary_buffered-ip-ssl", "go-netstd_binary_framed-ip", "go-netstd_binary_framed-ip-ssl", "go-netstd_compact_buffered-ip", "go-netstd_compact_buffered-ip-ssl", "go-netstd_compact_framed-ip", "go-netstd_compact_framed-ip-ssl", "go-netstd_json_buffered-ip", "go-netstd_json_buffered-ip-ssl", "go-netstd_json_framed-ip", "go-netstd_json_framed-ip-ssl", "go-py3_binary-accel_zlib-ip-ssl", "go-py3_compact-accelc_zlib-ip-ssl", "go-py_binary-accel_zlib-ip-ssl", "go-py_compact-accelc_zlib-ip-ssl", "hs-netstd_binary_buffered-ip", "hs-netstd_binary_framed-ip", "hs-netstd_compact_buffered-ip", "hs-netstd_compact_framed-ip", "hs-netstd_json_buffered-ip", "hs-netstd_json_framed-ip", "hs-php_binary-accel_buffered-ip", "hs-php_binary-accel_framed-ip", "hs-php_json_buffered-ip", "hs-php_json_framed-ip", "java-erl_binary_buffered-ip-ssl", "java-erl_binary_fastframed-framed-ip-ssl", "java-erl_binary_framed-ip-ssl", "java-erl_compact_buffered-ip-ssl", "java-erl_compact_fastframed-framed-ip-ssl", "java-erl_compact_framed-ip-ssl", "java-erl_multi-binary_buffered-ip-ssl", "java-erl_multi-binary_fastframed-framed-ip-ssl", "java-erl_multi-binary_framed-ip-ssl", "java-erl_multic-compact_buffered-ip-ssl", "java-erl_multic-compact_fastframed-framed-ip-ssl", "java-erl_multic-compact_framed-ip-ssl", "java-netstd_binary_buffered-ip", "java-netstd_binary_buffered-ip-ssl", "java-netstd_binary_fastframed-framed-ip", "java-netstd_binary_fastframed-framed-ip-ssl", "java-netstd_binary_framed-ip", "java-netstd_binary_framed-ip-ssl", "java-netstd_compact_buffered-ip", "java-netstd_compact_buffered-ip-ssl", "java-netstd_compact_fastframed-framed-ip", "java-netstd_compact_fastframed-framed-ip-ssl", "java-netstd_compact_framed-ip", "java-netstd_compact_framed-ip-ssl", "java-netstd_json_buffered-ip", "java-netstd_json_buffered-ip-ssl", "java-netstd_json_fastframed-framed-ip", "java-netstd_json_fastframed-framed-ip-ssl", "java-netstd_json_framed-ip", "java-netstd_json_framed-ip-ssl", "java-netstd_multi-binary_buffered-ip", "java-netstd_multi-binary_buffered-ip-ssl", "java-netstd_multi-binary_fastframed-framed-ip", "java-netstd_multi-binary_fastframed-framed-ip-ssl", "java-netstd_multi-binary_framed-ip", "java-netstd_multi-binary_framed-ip-ssl", "java-netstd_multic-compact_buffered-ip", "java-netstd_multic-compact_buffered-ip-ssl", "java-netstd_multic-compact_fastframed-framed-ip", "java-netstd_multic-compact_fastframed-framed-ip-ssl", "java-netstd_multic-compact_framed-ip", "java-netstd_multic-compact_framed-ip-ssl", "java-netstd_multij-json_buffered-ip", "java-netstd_multij-json_buffered-ip-ssl", "java-netstd_multij-json_fastframed-framed-ip", "java-netstd_multij-json_fastframed-framed-ip-ssl", "java-netstd_multij-json_framed-ip", "java-netstd_multij-json_framed-ip-ssl", "java-php_binary-accel_buffered-ip", "java-php_binary-accel_fastframed-framed-ip", "java-php_binary-accel_framed-ip", "java-php_json_buffered-ip", "java-php_json_fastframed-framed-ip", "java-php_json_framed-ip", "java-php_multi-accel_buffered-ip", "java-php_multi-accel_fastframed-framed-ip", "java-php_multi-accel_framed-ip", "java-php_multij-json_buffered-ip", "java-php_multij-json_fastframed-framed-ip", "java-php_multij-json_framed-ip", "kotlin-netstd_binary_framed-ip", "kotlin-netstd_compact_framed-ip", "kotlin-netstd_json_framed-ip", "netstd-cl_binary_buffered-ip", "netstd-cl_binary_framed-ip", "netstd-cpp_binary_buffered-ip", "netstd-cpp_binary_buffered-ip-ssl", "netstd-cpp_binary_framed-ip", "netstd-cpp_binary_framed-ip-ssl", "netstd-cpp_compact_buffered-ip", "netstd-cpp_compact_buffered-ip-ssl", "netstd-cpp_compact_framed-ip", "netstd-cpp_compact_framed-ip-ssl", "netstd-cpp_json_buffered-ip", "netstd-cpp_json_buffered-ip-ssl", "netstd-cpp_json_framed-ip", "netstd-cpp_json_framed-ip-ssl", "netstd-c_glib_binary_buffered-ip", "netstd-c_glib_binary_buffered-ip-ssl", "netstd-c_glib_binary_framed-ip", "netstd-c_glib_binary_framed-ip-ssl", "netstd-c_glib_compact_buffered-ip", "netstd-c_glib_compact_buffered-ip-ssl", "netstd-c_glib_compact_framed-ip", "netstd-c_glib_compact_framed-ip-ssl", "netstd-dart_binary_buffered-ip", "netstd-dart_binary_framed-ip", "netstd-dart_compact_buffered-ip", "netstd-dart_compact_framed-ip", "netstd-dart_json_buffered-ip", "netstd-dart_json_framed-ip", "netstd-d_binary_buffered-ip", "netstd-d_binary_buffered-ip-ssl", "netstd-d_binary_framed-ip", "netstd-d_binary_framed-ip-ssl", "netstd-d_compact_buffered-ip", "netstd-d_compact_buffered-ip-ssl", "netstd-d_compact_framed-ip", "netstd-d_compact_framed-ip-ssl", "netstd-d_json_buffered-ip", "netstd-d_json_buffered-ip-ssl", "netstd-d_json_framed-ip", "netstd-d_json_framed-ip-ssl", "netstd-erl_binary_buffered-ip", "netstd-erl_binary_buffered-ip-ssl", "netstd-erl_binary_framed-ip", "netstd-erl_binary_framed-ip-ssl", "netstd-erl_compact_buffered-ip", "netstd-erl_compact_buffered-ip-ssl", "netstd-erl_compact_framed-ip", "netstd-erl_compact_framed-ip-ssl", "netstd-go_binary_buffered-ip", "netstd-go_binary_buffered-ip-ssl", "netstd-go_binary_framed-ip", "netstd-go_binary_framed-ip-ssl", "netstd-go_compact_buffered-ip", "netstd-go_compact_buffered-ip-ssl", "netstd-go_compact_framed-ip", "netstd-go_compact_framed-ip-ssl", "netstd-go_json_buffered-ip", "netstd-go_json_buffered-ip-ssl", "netstd-go_json_framed-ip", "netstd-go_json_framed-ip-ssl", "netstd-hs_binary_buffered-ip", "netstd-hs_binary_framed-ip", "netstd-hs_compact_buffered-ip", "netstd-hs_compact_framed-ip", "netstd-hs_json_buffered-ip", "netstd-hs_json_framed-ip", "netstd-java_binary_buffered-ip", "netstd-java_binary_buffered-ip-ssl", "netstd-java_binary_framed-fastframed-ip", "netstd-java_binary_framed-fastframed-ip-ssl", "netstd-java_binary_framed-ip", "netstd-java_binary_framed-ip-ssl", "netstd-java_compact_buffered-ip", "netstd-java_compact_buffered-ip-ssl", "netstd-java_compact_framed-fastframed-ip", "netstd-java_compact_framed-fastframed-ip-ssl", "netstd-java_compact_framed-ip", "netstd-java_compact_framed-ip-ssl", "netstd-java_json_buffered-ip", "netstd-java_json_buffered-ip-ssl", "netstd-java_json_framed-fastframed-ip", "netstd-java_json_framed-fastframed-ip-ssl", "netstd-java_json_framed-ip", "netstd-java_json_framed-ip-ssl", "netstd-kotlin_binary_framed-ip", "netstd-kotlin_compact_framed-ip", "netstd-kotlin_json_framed-ip", "netstd-lua_binary_buffered-ip", "netstd-lua_binary_framed-ip", "netstd-lua_compact_buffered-ip", "netstd-lua_compact_framed-ip", "netstd-lua_json_buffered-ip", "netstd-lua_json_framed-ip", "netstd-netstd_binary_buffered-ip", "netstd-netstd_binary_buffered-ip-ssl", "netstd-netstd_binary_framed-ip", "netstd-netstd_binary_framed-ip-ssl", "netstd-netstd_compact_buffered-ip", "netstd-netstd_compact_buffered-ip-ssl", "netstd-netstd_compact_framed-ip", "netstd-netstd_compact_framed-ip-ssl", "netstd-netstd_json_buffered-ip", "netstd-netstd_json_buffered-ip-ssl", "netstd-netstd_json_framed-ip", "netstd-netstd_json_framed-ip-ssl", "netstd-nodejs_binary_buffered-ip", "netstd-nodejs_binary_buffered-ip-ssl", "netstd-nodejs_binary_framed-ip", "netstd-nodejs_binary_framed-ip-ssl", "netstd-nodejs_compact_buffered-ip", "netstd-nodejs_compact_buffered-ip-ssl", "netstd-nodejs_compact_framed-ip", "netstd-nodejs_compact_framed-ip-ssl", "netstd-nodejs_json_buffered-ip", "netstd-nodejs_json_buffered-ip-ssl", "netstd-nodejs_json_framed-ip", "netstd-nodejs_json_framed-ip-ssl", "netstd-nodets_binary_buffered-ip", "netstd-perl_binary_buffered-ip", "netstd-perl_binary_buffered-ip-ssl", "netstd-perl_binary_framed-ip", "netstd-perl_binary_framed-ip-ssl", "netstd-php_binary-accel_buffered-ip", "netstd-php_binary-accel_framed-ip", "netstd-php_binary_buffered-ip", "netstd-php_binary_framed-ip", "netstd-php_compact_buffered-ip", "netstd-php_compact_framed-ip", "netstd-php_json_buffered-ip", "netstd-php_json_framed-ip", "netstd-py3_binary-accel_buffered-ip", "netstd-py3_binary-accel_buffered-ip-ssl", "netstd-py3_binary-accel_framed-ip", "netstd-py3_binary-accel_framed-ip-ssl", "netstd-py3_binary_buffered-ip", "netstd-py3_binary_buffered-ip-ssl", "netstd-py3_binary_framed-ip", "netstd-py3_binary_framed-ip-ssl", "netstd-py3_compact-accelc_buffered-ip", "netstd-py3_compact-accelc_buffered-ip-ssl", "netstd-py3_compact-accelc_framed-ip", "netstd-py3_compact-accelc_framed-ip-ssl", "netstd-py3_compact_buffered-ip", "netstd-py3_compact_buffered-ip-ssl", "netstd-py3_compact_framed-ip", "netstd-py3_compact_framed-ip-ssl", "netstd-py3_json_buffered-ip", "netstd-py3_json_buffered-ip-ssl", "netstd-py3_json_framed-ip", "netstd-py3_json_framed-ip-ssl", "netstd-py_binary-accel_buffered-ip", "netstd-py_binary-accel_buffered-ip-ssl", "netstd-py_binary-accel_framed-ip", "netstd-py_binary-accel_framed-ip-ssl", "netstd-py_binary_buffered-ip", "netstd-py_binary_buffered-ip-ssl", "netstd-py_binary_framed-ip", "netstd-py_binary_framed-ip-ssl", "netstd-py_compact-accelc_buffered-ip", "netstd-py_compact-accelc_buffered-ip-ssl", "netstd-py_compact-accelc_framed-ip", "netstd-py_compact-accelc_framed-ip-ssl", "netstd-py_compact_buffered-ip", "netstd-py_compact_buffered-ip-ssl", "netstd-py_compact_framed-ip", "netstd-py_compact_framed-ip-ssl", "netstd-py_json_buffered-ip", "netstd-py_json_buffered-ip-ssl", "netstd-py_json_framed-ip", "netstd-py_json_framed-ip-ssl", "netstd-rb_binary-accel_buffered-ip", "netstd-rb_binary-accel_buffered-ip-ssl", "netstd-rb_binary-accel_framed-ip", "netstd-rb_binary-accel_framed-ip-ssl", "netstd-rb_binary_buffered-ip", "netstd-rb_binary_buffered-ip-ssl", "netstd-rb_binary_framed-ip", "netstd-rb_binary_framed-ip-ssl", "netstd-rb_compact_buffered-ip", "netstd-rb_compact_buffered-ip-ssl", "netstd-rb_compact_framed-ip", "netstd-rb_compact_framed-ip-ssl", "netstd-rb_json_buffered-ip", "netstd-rb_json_buffered-ip-ssl", "netstd-rb_json_framed-ip", "netstd-rb_json_framed-ip-ssl", "netstd-rs_binary_buffered-ip", "netstd-rs_binary_framed-ip", "netstd-rs_compact_buffered-ip", "netstd-rs_compact_framed-ip", "nodejs-cpp_binary_http-domain", "nodejs-cpp_binary_http-ip", "nodejs-cpp_binary_http-ip-ssl", "nodejs-cpp_binary_websocket-domain", "nodejs-cpp_binary_websocket-ip", "nodejs-cpp_binary_websocket-ip-ssl", "nodejs-cpp_compact_http-domain", "nodejs-cpp_compact_http-ip", "nodejs-cpp_compact_http-ip-ssl", "nodejs-cpp_compact_websocket-domain", "nodejs-cpp_compact_websocket-ip", "nodejs-cpp_compact_websocket-ip-ssl", "nodejs-cpp_header_http-domain", "nodejs-cpp_header_http-ip", "nodejs-cpp_header_http-ip-ssl", "nodejs-cpp_header_websocket-domain", "nodejs-cpp_header_websocket-ip", "nodejs-cpp_header_websocket-ip-ssl", "nodejs-cpp_json_buffered-ip-ssl", "nodejs-cpp_json_http-domain", "nodejs-cpp_json_http-ip", "nodejs-cpp_json_http-ip-ssl", "nodejs-cpp_json_websocket-domain", "nodejs-cpp_json_websocket-ip", "nodejs-cpp_json_websocket-ip-ssl", "nodejs-dart_binary_http-ip", "nodejs-dart_compact_http-ip", "nodejs-dart_json_http-ip", "nodejs-d_binary_http-ip", "nodejs-d_binary_http-ip-ssl", "nodejs-d_compact_http-ip", "nodejs-d_compact_http-ip-ssl", "nodejs-d_json_http-ip", "nodejs-d_json_http-ip-ssl", "nodejs-go_binary_http-ip", "nodejs-go_binary_http-ip-ssl", "nodejs-go_compact_http-ip", "nodejs-go_compact_http-ip-ssl", "nodejs-go_header_http-ip", "nodejs-go_header_http-ip-ssl", "nodejs-go_json_http-ip", "nodejs-go_json_http-ip-ssl", "nodejs-hs_binary_http-ip", "nodejs-hs_compact_http-ip", "nodejs-hs_header_http-ip", "nodejs-hs_json_http-ip", "nodejs-java_binary_http-ip", "nodejs-java_binary_http-ip-ssl", "nodejs-java_compact_http-ip", "nodejs-java_compact_http-ip-ssl", "nodejs-java_json_http-ip", "nodejs-java_json_http-ip-ssl", "nodejs-js_json_http-ip", "nodejs-lua_binary_http-ip", "nodejs-lua_compact_http-ip", "nodejs-lua_json_http-ip", "nodejs-netstd_binary_buffered-ip", "nodejs-netstd_binary_buffered-ip-ssl", "nodejs-netstd_binary_framed-ip", "nodejs-netstd_binary_framed-ip-ssl", "nodejs-netstd_compact_buffered-ip", "nodejs-netstd_compact_buffered-ip-ssl", "nodejs-netstd_compact_framed-ip", "nodejs-netstd_compact_framed-ip-ssl", "nodejs-netstd_json_buffered-ip", "nodejs-netstd_json_buffered-ip-ssl", "nodejs-netstd_json_framed-ip", "nodejs-netstd_json_framed-ip-ssl", "nodejs-nodejs_binary_websocket-domain", "nodejs-nodejs_compact_websocket-domain", "nodejs-nodejs_header_websocket-domain", "nodejs-nodejs_json_websocket-domain", "nodejs-php_binary-accel_buffered-ip", "nodejs-php_binary-accel_framed-ip", "nodejs-php_json_buffered-ip", "nodejs-php_json_framed-ip", "nodejs-py3_binary-accel_http-domain", "nodejs-py3_binary-accel_http-ip", "nodejs-py3_binary-accel_http-ip-ssl", "nodejs-py3_binary_http-domain", "nodejs-py3_binary_http-ip", "nodejs-py3_binary_http-ip-ssl", "nodejs-py3_compact-accelc_http-domain", "nodejs-py3_compact-accelc_http-ip", "nodejs-py3_compact-accelc_http-ip-ssl", "nodejs-py3_compact_http-domain", "nodejs-py3_compact_http-ip", "nodejs-py3_compact_http-ip-ssl", "nodejs-py3_header_http-domain", "nodejs-py3_header_http-ip", "nodejs-py3_header_http-ip-ssl", "nodejs-py3_json_http-domain", "nodejs-py3_json_http-ip", "nodejs-py3_json_http-ip-ssl", "nodejs-py_binary-accel_http-domain", "nodejs-py_binary-accel_http-ip", "nodejs-py_binary-accel_http-ip-ssl", "nodejs-py_binary_http-domain", "nodejs-py_binary_http-ip", "nodejs-py_binary_http-ip-ssl", "nodejs-py_compact-accelc_http-domain", "nodejs-py_compact-accelc_http-ip", "nodejs-py_compact-accelc_http-ip-ssl", "nodejs-py_compact_http-domain", "nodejs-py_compact_http-ip", "nodejs-py_compact_http-ip-ssl", "nodejs-py_header_http-domain", "nodejs-py_header_http-ip", "nodejs-py_header_http-ip-ssl", "nodejs-py_json_http-domain", "nodejs-py_json_http-ip", "nodejs-py_json_http-ip-ssl", "nodets-netstd_binary_buffered-ip", "nodets-php_binary-accel_buffered-ip", "perl-netstd_binary_buffered-ip", "perl-netstd_binary_buffered-ip-ssl", "perl-netstd_binary_framed-ip", "perl-netstd_binary_framed-ip-ssl", "perl-netstd_multi-binary_buffered-ip", "perl-netstd_multi-binary_buffered-ip-ssl", "perl-netstd_multi-binary_framed-ip", "perl-netstd_multi-binary_framed-ip-ssl", "py-cpp_accel-binary_http-domain", "py-cpp_accel-binary_http-ip", "py-cpp_accel-binary_http-ip-ssl", "py-cpp_accel-binary_zlib-domain", "py-cpp_accel-binary_zlib-ip", "py-cpp_accel-binary_zlib-ip-ssl", "py-cpp_accelc-compact_http-domain", "py-cpp_accelc-compact_http-ip", "py-cpp_accelc-compact_http-ip-ssl", "py-cpp_accelc-compact_zlib-domain", "py-cpp_accelc-compact_zlib-ip", "py-cpp_accelc-compact_zlib-ip-ssl", "py-cpp_binary_http-domain", "py-cpp_binary_http-ip", "py-cpp_binary_http-ip-ssl", "py-cpp_compact_http-domain", "py-cpp_compact_http-ip", "py-cpp_compact_http-ip-ssl", "py-cpp_header_http-domain", "py-cpp_header_http-ip", "py-cpp_header_http-ip-ssl", "py-cpp_json_http-domain", "py-cpp_json_http-ip", "py-cpp_json_http-ip-ssl", "py-cpp_multi-binary_http-domain", "py-cpp_multi-binary_http-ip", "py-cpp_multi-binary_http-ip-ssl", "py-cpp_multia-binary_http-domain", "py-cpp_multia-binary_http-ip", "py-cpp_multia-binary_http-ip-ssl", "py-cpp_multia-binary_zlib-domain", "py-cpp_multia-binary_zlib-ip", "py-cpp_multia-binary_zlib-ip-ssl", "py-cpp_multia-multi_http-domain", "py-cpp_multia-multi_http-ip", "py-cpp_multia-multi_http-ip-ssl", "py-cpp_multia-multi_zlib-domain", "py-cpp_multia-multi_zlib-ip", "py-cpp_multia-multi_zlib-ip-ssl", "py-cpp_multiac-compact_http-domain", "py-cpp_multiac-compact_http-ip", "py-cpp_multiac-compact_http-ip-ssl", "py-cpp_multiac-compact_zlib-domain", "py-cpp_multiac-compact_zlib-ip", "py-cpp_multiac-compact_zlib-ip-ssl", "py-cpp_multiac-multic_http-domain", "py-cpp_multiac-multic_http-ip", "py-cpp_multiac-multic_http-ip-ssl", "py-cpp_multiac-multic_zlib-domain", "py-cpp_multiac-multic_zlib-ip", "py-cpp_multiac-multic_zlib-ip-ssl", "py-cpp_multic-compact_http-domain", "py-cpp_multic-compact_http-ip", "py-cpp_multic-compact_http-ip-ssl", "py-cpp_multic_http-domain", "py-cpp_multic_http-ip", "py-cpp_multic_http-ip-ssl", "py-cpp_multih-header_http-domain", "py-cpp_multih-header_http-ip", "py-cpp_multih-header_http-ip-ssl", "py-cpp_multih_http-domain", "py-cpp_multih_http-ip", "py-cpp_multih_http-ip-ssl", "py-cpp_multij-json_http-domain", "py-cpp_multij-json_http-ip", "py-cpp_multij-json_http-ip-ssl", "py-cpp_multij_http-domain", "py-cpp_multij_http-ip", "py-cpp_multij_http-ip-ssl", "py-cpp_multi_http-domain", "py-cpp_multi_http-ip", "py-cpp_multi_http-ip-ssl", "py-dart_accel-binary_http-ip", "py-dart_accelc-compact_http-ip", "py-dart_binary_http-ip", "py-dart_compact_http-ip", "py-dart_json_http-ip", "py-d_accel-binary_http-ip", "py-d_accel-binary_http-ip-ssl", "py-d_accelc-compact_http-ip", "py-d_accelc-compact_http-ip-ssl", "py-d_binary_http-ip", "py-d_binary_http-ip-ssl", "py-d_compact_http-ip", "py-d_compact_http-ip-ssl", "py-d_json_http-ip", "py-d_json_http-ip-ssl", "py-hs_accel-binary_http-ip", "py-hs_accelc-compact_http-ip", "py-hs_binary_http-ip", "py-hs_compact_http-ip", "py-hs_header_http-ip", "py-hs_json_http-ip", "py-java_accel-binary_http-ip-ssl", "py-java_accelc-compact_http-ip-ssl", "py-java_binary_http-ip-ssl", "py-java_compact_http-ip-ssl", "py-java_json_http-ip-ssl", "py-java_multi-binary_http-ip-ssl", "py-java_multia-binary_http-ip-ssl", "py-java_multia-multi_http-ip-ssl", "py-java_multiac-compact_http-ip-ssl", "py-java_multiac-multic_http-ip-ssl", "py-java_multic-compact_http-ip-ssl", "py-java_multic_http-ip-ssl", "py-java_multij-json_http-ip-ssl", "py-java_multij_http-ip-ssl", "py-java_multi_http-ip-ssl", "py-lua_accel-binary_http-ip", "py-lua_accelc-compact_http-ip", "py-lua_binary_http-ip", "py-lua_compact_http-ip", "py-lua_json_http-ip", "py-netstd_accel-binary_buffered-ip", "py-netstd_accel-binary_buffered-ip-ssl", "py-netstd_accel-binary_framed-ip", "py-netstd_accel-binary_framed-ip-ssl", "py-netstd_accelc-compact_buffered-ip", "py-netstd_accelc-compact_buffered-ip-ssl", "py-netstd_accelc-compact_framed-ip", "py-netstd_accelc-compact_framed-ip-ssl", "py-netstd_binary_buffered-ip", "py-netstd_binary_buffered-ip-ssl", "py-netstd_binary_framed-ip", "py-netstd_binary_framed-ip-ssl", "py-netstd_compact_buffered-ip", "py-netstd_compact_buffered-ip-ssl", "py-netstd_compact_framed-ip", "py-netstd_compact_framed-ip-ssl", "py-netstd_json_buffered-ip", "py-netstd_json_buffered-ip-ssl", "py-netstd_json_framed-ip", "py-netstd_json_framed-ip-ssl", "py-nodejs_accel-binary_http-domain", "py-nodejs_accelc-compact_http-domain", "py-nodejs_binary_http-domain", "py-nodejs_compact_http-domain", "py-nodejs_header_http-domain", "py-nodejs_json_http-domain", "py-php_accel_buffered-ip", "py-php_accel_framed-ip", "py-php_binary-accel_buffered-ip", "py-php_binary-accel_framed-ip", "py-php_json_buffered-ip", "py-php_json_framed-ip", "py-rs_multia-multi_buffered-ip", "py-rs_multia-multi_framed-ip", "py-rs_multiac-multic_buffered-ip", "py-rs_multiac-multic_framed-ip", "py-rs_multic_buffered-ip", "py-rs_multic_framed-ip", "py-rs_multi_buffered-ip", "py-rs_multi_framed-ip", "py3-cpp_accel-binary_http-domain", "py3-cpp_accel-binary_http-ip", "py3-cpp_accel-binary_http-ip-ssl", "py3-cpp_accel-binary_zlib-domain", "py3-cpp_accel-binary_zlib-ip", "py3-cpp_accel-binary_zlib-ip-ssl", "py3-cpp_accelc-compact_http-domain", "py3-cpp_accelc-compact_http-ip", "py3-cpp_accelc-compact_http-ip-ssl", "py3-cpp_accelc-compact_zlib-domain", "py3-cpp_accelc-compact_zlib-ip", "py3-cpp_accelc-compact_zlib-ip-ssl", "py3-cpp_binary_http-domain", "py3-cpp_binary_http-ip", "py3-cpp_binary_http-ip-ssl", "py3-cpp_compact_http-domain", "py3-cpp_compact_http-ip", "py3-cpp_compact_http-ip-ssl", "py3-cpp_header_http-domain", "py3-cpp_header_http-ip", "py3-cpp_header_http-ip-ssl", "py3-cpp_json_http-domain", "py3-cpp_json_http-ip", "py3-cpp_json_http-ip-ssl", "py3-cpp_multi-binary_http-domain", "py3-cpp_multi-binary_http-ip", "py3-cpp_multi-binary_http-ip-ssl", "py3-cpp_multia-binary_http-domain", "py3-cpp_multia-binary_http-ip", "py3-cpp_multia-binary_http-ip-ssl", "py3-cpp_multia-binary_zlib-domain", "py3-cpp_multia-binary_zlib-ip", "py3-cpp_multia-binary_zlib-ip-ssl", "py3-cpp_multia-multi_http-domain", "py3-cpp_multia-multi_http-ip", "py3-cpp_multia-multi_http-ip-ssl", "py3-cpp_multia-multi_zlib-domain", "py3-cpp_multia-multi_zlib-ip", "py3-cpp_multia-multi_zlib-ip-ssl", "py3-cpp_multiac-compact_http-domain", "py3-cpp_multiac-compact_http-ip", "py3-cpp_multiac-compact_http-ip-ssl", "py3-cpp_multiac-compact_zlib-domain", "py3-cpp_multiac-compact_zlib-ip", "py3-cpp_multiac-compact_zlib-ip-ssl", "py3-cpp_multiac-multic_http-domain", "py3-cpp_multiac-multic_http-ip", "py3-cpp_multiac-multic_http-ip-ssl", "py3-cpp_multiac-multic_zlib-domain", "py3-cpp_multiac-multic_zlib-ip", "py3-cpp_multiac-multic_zlib-ip-ssl", "py3-cpp_multic-compact_http-domain", "py3-cpp_multic-compact_http-ip", "py3-cpp_multic-compact_http-ip-ssl", "py3-cpp_multic_http-domain", "py3-cpp_multic_http-ip", "py3-cpp_multic_http-ip-ssl", "py3-cpp_multih-header_http-domain", "py3-cpp_multih-header_http-ip", "py3-cpp_multih-header_http-ip-ssl", "py3-cpp_multih_http-domain", "py3-cpp_multih_http-ip", "py3-cpp_multih_http-ip-ssl", "py3-cpp_multij-json_http-domain", "py3-cpp_multij-json_http-ip", "py3-cpp_multij-json_http-ip-ssl", "py3-cpp_multij_http-domain", "py3-cpp_multij_http-ip", "py3-cpp_multij_http-ip-ssl", "py3-cpp_multi_http-domain", "py3-cpp_multi_http-ip", "py3-cpp_multi_http-ip-ssl", "py3-dart_accel-binary_http-ip", "py3-dart_accelc-compact_http-ip", "py3-dart_binary_http-ip", "py3-dart_compact_http-ip", "py3-dart_json_http-ip", "py3-d_accel-binary_http-ip", "py3-d_accel-binary_http-ip-ssl", "py3-d_accelc-compact_http-ip", "py3-d_accelc-compact_http-ip-ssl", "py3-d_binary_http-ip", "py3-d_binary_http-ip-ssl", "py3-d_compact_http-ip", "py3-d_compact_http-ip-ssl", "py3-d_json_http-ip", "py3-d_json_http-ip-ssl", "py3-hs_accel-binary_http-ip", "py3-hs_accelc-compact_http-ip", "py3-hs_binary_http-ip", "py3-hs_compact_http-ip", "py3-hs_header_http-ip", "py3-hs_json_http-ip", "py3-java_accel-binary_http-ip-ssl", "py3-java_accelc-compact_http-ip-ssl", "py3-java_binary_http-ip-ssl", "py3-java_compact_http-ip-ssl", "py3-java_json_http-ip-ssl", "py3-java_multi-binary_http-ip-ssl", "py3-java_multia-binary_http-ip-ssl", "py3-java_multia-multi_http-ip-ssl", "py3-java_multiac-compact_http-ip-ssl", "py3-java_multiac-multic_http-ip-ssl", "py3-java_multic-compact_http-ip-ssl", "py3-java_multic_http-ip-ssl", "py3-java_multij-json_http-ip-ssl", "py3-java_multij_http-ip-ssl", "py3-java_multi_http-ip-ssl", "py3-lua_accel-binary_http-ip", "py3-lua_accelc-compact_http-ip", "py3-lua_binary_http-ip", "py3-lua_compact_http-ip", "py3-lua_json_http-ip", "py3-netstd_accel-binary_buffered-ip", "py3-netstd_accel-binary_buffered-ip-ssl", "py3-netstd_accel-binary_framed-ip", "py3-netstd_accel-binary_framed-ip-ssl", "py3-netstd_accelc-compact_buffered-ip", "py3-netstd_accelc-compact_buffered-ip-ssl", "py3-netstd_accelc-compact_framed-ip", "py3-netstd_accelc-compact_framed-ip-ssl", "py3-netstd_binary_buffered-ip", "py3-netstd_binary_buffered-ip-ssl", "py3-netstd_binary_framed-ip", "py3-netstd_binary_framed-ip-ssl", "py3-netstd_compact_buffered-ip", "py3-netstd_compact_buffered-ip-ssl", "py3-netstd_compact_framed-ip", "py3-netstd_compact_framed-ip-ssl", "py3-netstd_json_buffered-ip", "py3-netstd_json_buffered-ip-ssl", "py3-netstd_json_framed-ip", "py3-netstd_json_framed-ip-ssl", "py3-nodejs_accel-binary_http-domain", "py3-nodejs_accelc-compact_http-domain", "py3-nodejs_binary_http-domain", "py3-nodejs_compact_http-domain", "py3-nodejs_header_http-domain", "py3-nodejs_json_http-domain", "py3-php_accel_buffered-ip", "py3-php_accel_framed-ip", "py3-php_binary-accel_buffered-ip", "py3-php_binary-accel_framed-ip", "py3-php_json_buffered-ip", "py3-php_json_framed-ip", "rb-cpp_json_buffered-domain", "rb-cpp_json_buffered-ip", "rb-cpp_json_buffered-ip-ssl", "rb-cpp_json_framed-domain", "rb-cpp_json_framed-ip", "rb-cpp_json_framed-ip-ssl", "rb-netstd_accel-binary_buffered-ip", "rb-netstd_accel-binary_buffered-ip-ssl", "rb-netstd_accel-binary_framed-ip", "rb-netstd_accel-binary_framed-ip-ssl", "rb-netstd_binary_buffered-ip", "rb-netstd_binary_buffered-ip-ssl", "rb-netstd_binary_framed-ip", "rb-netstd_binary_framed-ip-ssl", "rb-netstd_compact_buffered-ip", "rb-netstd_compact_buffered-ip-ssl", "rb-netstd_compact_framed-ip", "rb-netstd_compact_framed-ip-ssl", "rb-netstd_json_buffered-ip", "rb-netstd_json_buffered-ip-ssl", "rb-netstd_json_framed-ip", "rb-netstd_json_framed-ip-ssl", "rs-netstd_binary_buffered-ip", "rs-netstd_binary_framed-ip", "rs-netstd_compact_buffered-ip", "rs-netstd_compact_buffered-ip", "rs-netstd_compact_framed-ip", "rs-netstd_multi-binary_buffered-ip", "rs-netstd_multi-binary_framed-ip", "rs-netstd_multic-compact_buffered-ip", "rs-netstd_multic-compact_framed-ip" ] thrift-0.19.0/test/README.md0000644000000000000000000001604314303740367015350 0ustar00rootroot00000000000000# Apache Thrift - integration test suite This is the cross everything integration test suite for Apache Thrift. ## Run ### A. Using Make The test can be executed by: make cross This starts the [test.py](test.py) script which does the real cross test with different transports, protocols and languages. Note that this skips any language that is not built locally. It also skips tests that are known to be failing. If you need more control over which tests to run, read following section. ### B. Using test script directly Alternatively, you can invoke [test.py](test.py) directly. You need to run`make precross` once before executing it for the first time. For example, if you changed something in `nodejs` library and need to verify the patch, you can skip everything except `nodejs` itself and some reference implementation (currently `cpp` and `java` are recommended) like this: ./configure --without-c_glib --without-erlang --without-lua ... make precross -j8 test/test.py --server cpp,java --client nodejs test/test.py --server nodejs --client cpp,java Another useful flag is --regex. For example, to run all tests that involve Java TBinaryProtocol: test/test.py --regex "java.*binary" ## Test case definition file The cross test cases are defined in [tests.json](tests.json). The root element is collection of test target definitions. Each test target definition looks like this: { "name": "somelib", "client": { "command": ["somelib_client_executable"], "workdir": "somelib/bin", "protocols": ["binary"], "transports": ["buffered"], "sockets": ["ip"], }, "server": { "command": ["somelib_server_executable"], "workdir": "somelib/bin", "protocols": ["binary"], "transports": ["buffered"], "sockets": ["ip", "ip-ssl"], } } Either client or server definition or both should be present. Parameters that are common to both `client` and `server` can be put to target definition root: { "name": "somelib", "workdir": "somelib/bin", "protocols": ["binary"], "transports": ["buffered"], "sockets": ["ip"], "client": { "command": ["somelib_client_executable"] }, "server": { "command": ["somelib_server_executable"], "sockets": ["ip-ssl"] } } For the complete list of supported keys and their effect, see source code comment at the opt of [crossrunner/collect.py](crossrunner/collect.py). ## List of known failures Since many cross tests currently fail (mainly due to partial incompatibility around exception handling), the test script specifically report for "not known before" failures. For this purpose, test cases known to (occasionally) fail are listed in `known_failures_.json` where `` matches with python `platform.system()` string. Currently, only Linux version is included. FYI, the file is initially generated by test/test.py --update-expected-failures=overwrite after a full test run, then repeatedly test/test.py --skip-known-failures test/test.py --update-expected-failures=merge to update the known failures, run make fail ## Test executable specification ### Command line parameters Unit tests for languages are usually located under lib//test/ cross language tests according to [ThriftTest.thrift](ThriftTest.thrift) shall be provided for every language including executables with the following command line interface: **Server command line interface:** $ ./TestServer -h Allowed options: -h | --help produce help message --port=arg (9090) Port number to listen --domain-socket=arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) --pipe=arg Windows Named Pipe (e.g. MyThriftPipe) --server-type=arg (simple) type of server, "simple", "thread-pool", "threaded", or "nonblocking" --transport=arg (buffered) transport: buffered, framed, http, anonpipe, zlib --protocol=arg (binary) protocol: binary, compact, header, json --multiplex Add TMultiplexedProtocol service name "ThriftTest" --abstract-namespace Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames) --ssl Encrypted Transport using SSL --zlib Wrapped Transport using Zlib --processor-events processor-events -n=arg | --workers=arg (=4) Number of thread pools workers. Only valid for thread-pool server type **Client command line interface:** $ ./TestClient -h Allowed options: -h | --help produce help message --host=arg (localhost) Host to connect --port=arg (9090) Port number to connect --domain-socket=arg Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port --pipe=arg Windows Named Pipe (e.g. MyThriftPipe) --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) --abstract-namespace Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames) --transport=arg (buffered) Transport: buffered, framed, http, evhttp, zlib --protocol=arg (binary) Protocol: binary, compact, header, json --multiplex Add TMultiplexedProtocol service name "ThriftTest" --ssl Encrypted Transport using SSL --zlib Wrap Transport with Zlib -n=arg | --testloops=arg (1) Number of Tests -t=arg | --threads=arg (1) Number of Test threads If you have executed the **make check** or **make cross** then you will be able to browse [gen-html/ThriftTest.html](gen-html/ThriftTest.html) with the test documentation. ### Return code The return code (exit code) shall be 0 on success, or an integer in the range 1 - 255 on errors. In order to signal failed tests, the return code shall be composed from these bits to indicate failing tests: #define TEST_BASETYPES 1 // 0000 0001 #define TEST_STRUCTS 2 // 0000 0010 #define TEST_CONTAINERS 4 // 0000 0100 #define TEST_EXCEPTIONS 8 // 0000 1000 #define TEST_UNKNOWN 64 // 0100 0000 (Failed to prepare environment etc.) #define TEST_TIMEOUT 128 // 1000 0000 #define TEST_NOTUSED 48 // 0011 0000 (reserved bits) Tests that have not been executed at all count as errors. **Example:** During tests, the test client notices that some of the Struct tests fail. Furthermore, due to some other problem none of the Exception tests is executed. Therefore, the test client returns the code `10 = 2 | 8`, indicating the failure of both test 2 (TEST_STRUCTS) and test 8 (TEST_EXCEPTIONS). ## SSL Test Keys and Certificates are provided in multiple formats under the following directory [test/keys](keys) thrift-0.19.0/test/TypedefTest.thrift0000644000000000000000000000226214303740367017551 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace cpp thrift.test typedef i32 MyInt32 typedef string MyString; struct TypedefTestStruct { 1: MyInt32 field_MyInt32; 2: MyString field_MyString; 3: i32 field_Int32; 4: string field_String; } typedef TypedefTestStruct MyStruct,thrift-0.19.0/test/partial/0000777000000000000000000000000014303740367015525 5ustar00rootroot00000000000000thrift-0.19.0/test/partial/thrift_test_schema.thrift0000644000000000000000000001034014303740367022620 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java org.apache.thrift.partial // This thrift file is meant for testing partial deserialization. // It includes all field types and most combinations of complex types. // Those fields help ensure correctness of partial deserialization. enum TstEnum { UNKNOWN = 0, E_ONE = 1, E_TWO = 2 } struct SmallStruct { // Primitive fields 1: optional byte byteField; 2: optional i16 i16Field; 3: optional i32 i32Field; 4: optional i64 i64Field; 5: optional double doubleField; 6: optional string stringField; // Enum 7: optional TstEnum enumField; } // TODO(kpandit): Need to add bool field struct TestStruct { // Primitive fields 1: optional byte byteField; 2: optional i16 i16Field; 3: optional i32 i32Field; 4: optional i64 i64Field; 5: optional double doubleField; 6: optional string stringField; // Enum 7: optional TstEnum enumField; 8: optional binary binaryField; // List 10: optional list byteList; 11: optional list i16List; 12: optional list i32List; 13: optional list i64List; 14: optional list doubleList; 15: optional list stringList; 16: optional list enumList; 17: optional list> listList; 18: optional list> setList; 19: optional list> mapList; 20: optional list structList; 21: optional list binaryList; // Set 30: optional set byteSet; 31: optional set i16Set; 32: optional set i32Set; 33: optional set i64Set; 34: optional set doubleSet; 35: optional set stringSet; 36: optional set enumSet; 37: optional set> listSet (nolint = "set.value.type"); 38: optional set> setSet (nolint = "set.value.type"); 39: optional set> mapSet (nolint = "set.value.type"); 40: optional set structSet (nolint = "set.value.type"); 41: optional set binarySet; // Map 50: optional map byteMap; 51: optional map i16Map; 52: optional map i32Map; 53: optional map i64Map; 54: optional map doubleMap; 55: optional map stringMap; 56: optional map enumMap; 57: optional map> listMap; 58: optional map> setMap; 59: optional map> mapMap; 60: optional map structMap (nolint = "map.key.type"); 61: optional map binaryMap; 70: optional SmallStruct structField; } struct InnermostStruct { 1: optional string value; 2: optional i32 intValue; } struct InnerStruct { 1: optional InnermostStruct value; 2: optional i32 intValue; } struct OuterStruct { 1: optional InnerStruct value; 2: optional map structMap; } union SimpleUnion { 1: optional i32 intValue; 2: optional string stringValue; } struct StructWithUnions { 1: optional i32 intValue; 2: optional SmallStruct smallStruct; 3: optional SimpleUnion simpleUnion; 4: optional list unionList; 5: optional set unionSet (nolint = "set.value.type"); 6: optional map keyUnionMap (nolint = "map.key.type"); 7: optional map valUnionMap; 8: optional map unionMap (nolint = "map.key.type"); } thrift-0.19.0/test/DenseLinkingTest.thrift0000644000000000000000000000443614303740367020530 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* ../compiler/cpp/thrift -gen cpp:dense DebugProtoTest.thrift ../compiler/cpp/thrift -gen cpp:dense DenseLinkingTest.thrift g++ -Wall -g -I../lib/cpp/src -I/usr/local/include/boost-1_33_1 \ DebugProtoTest.cpp gen-cpp/DebugProtoTest_types.cpp \ gen-cpp/DenseLinkingTest_types.cpp \ ../lib/cpp/.libs/libthrift.a -o DebugProtoTest ./DebugProtoTest */ /* The idea of this test is that everything is structurally identical to DebugProtoTest. If I messed up the naming of the reflection local typespecs, then compiling this should give errors because of doubly defined symbols. */ namespace cpp thrift.test namespace java thrift.test struct OneOfEachZZ { 1: bool im_true, 2: bool im_false, 3: byte a_bite, 4: i16 integer16, 5: i32 integer32, 6: i64 integer64, 7: double double_precision, 8: string some_characters, 9: string zomg_unicode, 10: bool what_who, } struct BonkZZ { 1: i32 type, 2: string message, } struct NestingZZ { 1: BonkZZ my_bonk, 2: OneOfEachZZ my_ooe, } struct HolyMoleyZZ { 1: list big, 2: set> contain, 3: map> bonks, } struct BackwardsZZ { 2: i32 first_tag2, 1: i32 second_tag1, } struct EmptyZZ { } struct WrapperZZ { 1: EmptyZZ foo } struct RandomStuffZZ { 1: i32 a, 2: i32 b, 3: i32 c, 4: i32 d, 5: list myintlist, 6: map maps, 7: i64 bigint, 8: double triple, } service Srv { i32 Janky(1: i32 arg) } service UnderscoreSrv { i64 some_rpc_call(1: string message) } thrift-0.19.0/test/Types.thrift0000644000000000000000000000153314303740367016415 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct Type1 { 1: i32 number, 2: string message, }thrift-0.19.0/test/SpecificNameTest.thrift0000644000000000000000000000176614303740367020507 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace cpp test.specificname struct a { 1: i32 number, 2: string message, } struct b { 1: i32 number, 2: string message, } service EchoService { void echoA(1: a arg), void echoB(2: b arg), } thrift-0.19.0/test/Int64Test.thrift0000644000000000000000000000350014303740367017051 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace js Int64Test const i64 SMALL_INT64 = 42 const i64 MAX_JS_SAFE_INT64 = 9007199254740991 const i64 MIN_JS_SAFE_INT64 = -9007199254740991 const i64 MAX_JS_SAFE_PLUS_ONE_INT64 = 9007199254740992 const i64 MIN_JS_SAFE_MINUS_ONE_INT64 = -9007199254740992 const i64 MAX_SIGNED_INT64 = 9223372036854775807 const i64 MIN_SIGNED_INT64 = -9223372036854775808 const list INT64_LIST = [SMALL_INT64, MAX_JS_SAFE_INT64, MIN_JS_SAFE_INT64, MAX_JS_SAFE_PLUS_ONE_INT64, MIN_JS_SAFE_MINUS_ONE_INT64, MAX_SIGNED_INT64, MIN_SIGNED_INT64] const map INT64_2_INT64_MAP = { SMALL_INT64: SMALL_INT64, MAX_JS_SAFE_INT64: MAX_JS_SAFE_INT64, MIN_JS_SAFE_INT64: MIN_JS_SAFE_INT64, MAX_JS_SAFE_PLUS_ONE_INT64: MAX_JS_SAFE_PLUS_ONE_INT64, MIN_JS_SAFE_MINUS_ONE_INT64: MIN_JS_SAFE_MINUS_ONE_INT64, MAX_SIGNED_INT64: MAX_SIGNED_INT64, MIN_SIGNED_INT64: MIN_SIGNED_INT64 } thrift-0.19.0/test/DocTest.thrift0000644000000000000000000001416714303740367016665 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Program doctext. * * Seriously, this is the documentation for this whole program. */ namespace java thrift.test namespace cpp thrift.test // C++ comment /* c style comment */ # the new unix comment /** Some doc text goes here. Wow I am [nesting these] (no more nesting.) */ enum Numberz { /** This is how to document a parameter */ ONE = 1, /** And this is a doc for a parameter that has no specific value assigned */ TWO, THREE, FIVE = 5, SIX, EIGHT = 8 } /** This is how you would do a typedef doc */ typedef i64 UserId /** And this is where you would document a struct */ struct Xtruct { /** And the members of a struct */ 1: string string_thing /** doct text goes before a comma */ 4: i8 byte_thing, 9: i32 i32_thing, 11: i64 i64_thing } /** * You can document constants now too. Yeehaw! */ const i32 INT32CONSTANT = 9853 const i16 INT16CONSTANT = 1616 /** Everyone get in on the docu-action! */ const map MAPCONSTANT = {'hello':'world', 'goodnight':'moon'} struct Xtruct2 { 1: i8 byte_thing, 2: Xtruct struct_thing, 3: i32 i32_thing } /** Struct insanity */ struct Insanity { /** This is doc for field 1 */ 1: map userMap, /** And this is doc for field 2 */ 2: list xtructs } exception Xception { 1: i32 errorCode, 2: string message } exception Xception2 { 1: i32 errorCode, 2: Xtruct struct_thing } /* C1 */ /** Doc */ /* C2 */ /* C3 */ struct EmptyStruct {} struct OneField { 1: EmptyStruct field } /** This is where you would document a Service */ service ThriftTest { /** And this is how you would document functions in a service */ void testVoid(), string testString(1: string thing), i8 testByte(1: byte thing), i32 testI32(1: i32 thing), /** Like this one */ i64 testI64(1: i64 thing), double testDouble(1: double thing), Xtruct testStruct(1: Xtruct thing), Xtruct2 testNest(1: Xtruct2 thing), map testMap(1: map thing), set testSet(1: set thing), list testList(1: list thing), /** This is an example of a function with params documented */ Numberz testEnum( /** This param is a thing */ 1: Numberz thing ), UserId testTypedef(1: UserId thing), map> testMapMap(1: i32 hello), /* So you think you've got this all worked, out eh? */ map> testInsanity(1: Insanity argument), } /// This style of Doxy-comment doesn't work. typedef i32 SorryNoGo /** * This is a trivial example of a multiline docstring. */ typedef i32 TrivialMultiLine /** * This is the canonical example * of a multiline docstring. */ typedef i32 StandardMultiLine /** * The last line is non-blank. * I said non-blank! */ typedef i32 LastLine /** Both the first line * are non blank. ;-) * and the last line */ typedef i32 FirstAndLastLine /** * INDENTED TITLE * The text is less indented. */ typedef i32 IndentedTitle /** First line indented. * Unfortunately, this does not get indented. */ typedef i32 FirstLineIndent /** * void code_in_comment() { * printf("hooray code!"); * } */ typedef i32 CodeInComment /** * Indented Docstring. * This whole docstring is indented. * This line is indented further. */ typedef i32 IndentedDocstring /** Irregular docstring. * We will have to punt * on this thing */ typedef i32 Irregular1 /** * note the space * before these lines * but not this * one */ typedef i32 Irregular2 /** * Flush against * the left. */ typedef i32 Flush /** No stars in this one. It should still work fine, though. Including indenting. */ typedef i32 NoStars /** Trailing whitespace Sloppy trailing whitespace is truncated. */ typedef i32 TrailingWhitespace /** * This is a big one. * * We'll have some blank lines in it. * * void as_well_as(some code) { * puts("YEEHAW!"); * } */ typedef i32 BigDog /** * * */ typedef i32 TotallyDegenerate /**no room for newline here*/ /* * / */ typedef i32 TestFor3501a /** * / */ typedef i32 TestFor3501b /* Comment-end tokens can of course have more than one asterisk */ struct TestFor3709_00 { /* ? */ 1: i32 foo } /* Comment-end tokens can of course have more than one asterisk **/ struct TestFor3709_01 { /* ? */ 1: i32 foo } /* Comment-end tokens can of course have more than one asterisk ***/ struct TestFor3709_02 { /* ? */ 1: i32 foo } /** Comment-end tokens can of course have more than one asterisk */ struct TestFor3709_03 { /* ? */ 1: i32 foo } /** Comment-end tokens can of course have more than one asterisk **/ struct TestFor3709_04 { /* ? */ 1: i32 foo } /** Comment-end tokens can of course have more than one asterisk ***/ struct TestFor3709_05 { /* ? */ 1: i32 foo } /*** Comment-end tokens can of course have more than one asterisk */ struct TestFor3709_06 { /* ? */ 1: i32 foo } /*** Comment-end tokens can of course have more than one asterisk **/ struct TestFor3709_07 { /* ? */ 1: i32 foo } /*** Comment-end tokens can of course have more than one asterisk ***/ struct TestFor3709_08 { /* ? */ 1: i32 foo } struct TestFor3709 { /** This is a comment */ 1: required string id, /** This is also a comment **/ 2: required string typeId, /** Yet another comment! */ 3: required i32 endTimestamp } /* THE END */ thrift-0.19.0/test/perl/0000777000000000000000000000000014472652606015040 5ustar00rootroot00000000000000thrift-0.19.0/test/perl/Makefile.am0000644000000000000000000000172114370300523017052 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # stubs: ../v0.16/ThriftTest.thrift $(THRIFT) --gen perl ../v0.16/ThriftTest.thrift precross: stubs check: stubs clean-local: $(RM) -r gen-perl/ dist-hook: $(RM) -r $(distdir)/gen-perl/ thrift-0.19.0/test/perl/Makefile0000644000000000000000000004350614472652606016504 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/perl/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/perl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/perl abs_srcdir = /thrift/src/test/perl abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/perl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/perl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../v0.16/ThriftTest.thrift $(THRIFT) --gen perl ../v0.16/ThriftTest.thrift precross: stubs check: stubs clean-local: $(RM) -r gen-perl/ dist-hook: $(RM) -r $(distdir)/gen-perl/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/perl/TestServer.pl0000644000000000000000000002323614303740367017500 0ustar00rootroot00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Data::Dumper; use Getopt::Long qw(GetOptions); use Time::HiRes qw(gettimeofday); $SIG{INT} = \&sigint_handler; use lib '../../lib/perl/lib'; use lib 'gen-perl'; use Thrift; use Thrift::BinaryProtocol; use Thrift::BufferedTransport; use Thrift::FramedTransport; use Thrift::MultiplexedProcessor; use Thrift::SSLServerSocket; use Thrift::ServerSocket; use Thrift::Server; use Thrift::UnixServerSocket; use ThriftTest::SecondService; use ThriftTest::ThriftTest; use ThriftTest::Types; $|++; sub usage { print <<"EOF"; Usage: $0 [OPTIONS] Options: (default) --ca Certificate authority file (optional). --cert Certificate file. Required if using --ssl. --ciphers Acceptable cipher list. --domain-socket Use a unix domain socket. --help Show usage. --key Private key file for certificate. Required if using --ssl and private key is not in the certificate file. --port 9090 Port to use. --protocol {binary} binary Protocol to use. --ssl If present, use SSL/TLS. --transport {buffered|framed} buffered Transport to use. EOF } my %opts = ( 'port' => 9090, 'protocol' => 'binary', 'transport' => 'buffered' ); GetOptions(\%opts, qw ( ca=s cert=s ciphers=s domain-socket=s help host=s key=s port=i protocol=s ssl transport=s )) || exit 1; if ($opts{help}) { usage(); exit 0; } if ($opts{ssl} and not defined $opts{cert}) { usage(); exit 1; } my $handler = ThriftTestHandler->new(); my $handler2 = SecondServiceHandler->new(); my $processor = ThriftTest::ThriftTestProcessor->new($handler); my $processor2 = ThriftTest::SecondServiceProcessor->new($handler2); my $serversocket; if ($opts{'domain-socket'}) { unlink($opts{'domain-socket'}); $serversocket = Thrift::UnixServerSocket->new($opts{'domain-socket'}); } elsif ($opts{ssl}) { $serversocket = Thrift::SSLServerSocket->new(\%opts); } else { $serversocket = Thrift::ServerSocket->new(\%opts); } my $transport; if ($opts{transport} eq 'buffered') { $transport = Thrift::BufferedTransportFactory->new(); } elsif ($opts{transport} eq 'framed') { $transport = Thrift::FramedTransportFactory->new(); } else { usage(); exit 1; } my $protocol; if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') { $protocol = Thrift::BinaryProtocolFactory->new(); } else { usage(); exit 1; } if (index($opts{protocol}, 'multi') == 0) { my $newProcessor = Thrift::MultiplexedProcessor->new($protocol); $newProcessor->defaultProcessor($processor); $newProcessor->registerProcessor('ThriftTest', $processor); $newProcessor->registerProcessor('SecondService', $processor2); $processor = $newProcessor; } my $ssltag = ''; if ($opts{ssl}) { $ssltag = '(SSL)'; } my $listening_on = "$opts{port} $ssltag"; if ($opts{'domain-socket'}) { $listening_on = $opts{'domain-socket'}; } my $server = Thrift::SimpleServer->new($processor, $serversocket, $transport, $protocol); print qq|Starting "simple" server ($opts{transport}/$opts{protocol}) listen on: $listening_on\n|; $server->serve(); print "done.\n"; sub sigint_handler { print "received SIGINT, stopping...\n"; $server->stop(); } ### ### Test server implementation ### package ThriftTestHandler; use base qw( ThriftTest::ThriftTestIf ); sub new { my $classname = shift; my $self = {}; return bless($self, $classname); } sub testVoid { print("testVoid()\n"); } sub testString { my $self = shift; my $thing = shift; print("testString($thing)\n"); return $thing; } sub testBool { my $self = shift; my $thing = shift; my $str = $thing ? 'true' : 'false'; print("testBool($str)\n"); return $thing; } sub testByte { my $self = shift; my $thing = shift; print("testByte($thing)\n"); return $thing; } sub testI32 { my $self = shift; my $thing = shift; print("testI32($thing)\n"); return $thing; } sub testI64 { my $self = shift; my $thing = shift; print("testI64($thing)\n"); return $thing; } sub testDouble { my $self = shift; my $thing = shift; print("testDouble($thing)\n"); return $thing; } sub testBinary { my $self = shift; my $thing = shift; my @bytes = split //, $thing; print 'testBinary('; printf( '%02lx', ord $_ ) foreach (@bytes); print ")\n"; return $thing; } sub testStruct { my $self = shift; my $thing = shift; printf(qq|testStruct({"%s", %d, %d, %lld})\n|, $thing->{string_thing}, $thing->{byte_thing}, $thing->{i32_thing}, $thing->{i64_thing}); return $thing; } sub testNest { my $self = shift; my $nest = shift; my $thing = $nest->{struct_thing}; printf(qq|testNest({%d, {"%s", %d, %d, %lld}, %d})\n|, $nest->{byte_thing}, $thing->{string_thing}, $thing->{byte_thing}, $thing->{i32_thing}, $thing->{i64_thing}, $nest->{i32_thing}); return $nest; } sub testMap { my $self = shift; my $thing = shift; printf "testMap({%s})\n", join( ', ', map { $_ . ' => ' . $thing->{$_} } sort keys %$thing ); return $thing; } sub testStringMap { my $self = shift; my $thing = shift; printf "testStringMap({%s})\n", join( ', ', map { $_ . ' => ' . $thing->{$_} } sort keys %$thing ); return $thing; } sub testSet { my $self = shift; my $thing = shift; my @result = sort keys %$thing; printf "testSet({%s})\n", join(', ', @result ); return \@result; } sub testList { my $self = shift; my $thing = shift; print "testList({%s})\n", join(', ', @$thing); return $thing; } sub testEnum { my $self = shift; my $thing = shift; print "testEnum($thing)\n"; return $thing; } sub testTypedef { my $self = shift; my $thing = shift; print("testTypedef($thing)\n"); return $thing; } sub testMapMap { my $self = shift; my $hello = shift; printf("testMapMap(%d)\n", $hello); my $result = { 4 => { 1 => 1, 2 => 2, 3 => 3, 4 => 4 }, -4 => { -1 => -1, -2 => -2, -3 => -3, -4 => -4 } }; return $result; } sub testInsanity { my $self = shift; my $argument = shift; print("testInsanity()\n"); my $hello = ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => 2, i32_thing => 2, i64_thing => 2}); my @hellos; push(@hellos, $hello); my $goodbye = ThriftTest::Xtruct->new({string_thing => 'Goodbye4', byte_thing => 4, i32_thing => 4, i64_thing => 4}); my @goodbyes; push(@goodbyes, $goodbye); my $crazy = ThriftTest::Insanity->new({userMap => { ThriftTest::Numberz::EIGHT => 8 }, xtructs => \@goodbyes}); my $loony = ThriftTest::Insanity->new(); my $result = { 1 => { ThriftTest::Numberz::TWO => $argument, ThriftTest::Numberz::THREE => $argument }, 2 => { ThriftTest::Numberz::SIX => $loony } }; return $result; } sub testMulti { my $self = shift; my $arg0 = shift; my $arg1 = shift; my $arg2 = shift; my $arg3 = shift; my $arg4 = shift; my $arg5 = shift; print("testMulti()\n"); return ThriftTest::Xtruct->new({string_thing => 'Hello2', byte_thing => $arg0, i32_thing => $arg1, i64_thing => $arg2}); } sub testException { my $self = shift; my $arg = shift; print("testException($arg)\n"); if ($arg eq 'Xception') { die ThriftTest::Xception->new({errorCode => 1001, message => $arg}); } elsif ($arg eq 'TException') { die 'astring'; # all unhandled exceptions become TExceptions } else { return ThriftTest::Xtruct->new({string_thing => $arg}); } } sub testMultiException { my $self = shift; my $arg0 = shift; my $arg1 = shift; printf("testMultiException(%s, %s)\n", $arg0, $arg1); if ($arg0 eq 'Xception') { die ThriftTest::Xception->new({errorCode => 1001, message => 'This is an Xception'}); } elsif ($arg0 eq 'Xception2') { my $struct_thing = ThriftTest::Xtruct->new({string_thing => 'This is an Xception2'}); die ThriftTest::Xception2->new({errorCode => 2002, struct_thing => $struct_thing}); } else { return ThriftTest::Xtruct->new({string_thing => $arg1}); } } sub testOneway { my $self = shift; my $num = shift; print("testOneway($num): received\n"); } ### ### Test server implementation ### package SecondServiceHandler; use base qw( ThriftTest::SecondServiceIf ); sub new { my $classname = shift; my $self = {}; return bless($self, $classname); } sub secondtestString { my $self = shift; my $thing = shift; print("testString($thing)\n"); return qq|testString("$thing")|; } 1; thrift-0.19.0/test/perl/TestClient.pl0000777000000000000000000002435414062750227017457 0ustar00rootroot00000000000000#!/usr/bin/env perl # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Data::Dumper; use Getopt::Long qw(GetOptions); use Time::HiRes qw(gettimeofday); use lib '../../lib/perl/lib'; use lib 'gen-perl'; use Thrift; use Thrift::BinaryProtocol; use Thrift::BufferedTransport; use Thrift::FramedTransport; use Thrift::MultiplexedProtocol; use Thrift::SSLSocket; use Thrift::Socket; use Thrift::UnixSocket; use ThriftTest::SecondService; use ThriftTest::ThriftTest; use ThriftTest::Types; $|++; sub usage { print <<"EOF"; Usage: $0 [OPTIONS] Options: (default) --ca CA to validate server with. --cert Certificate to use. Required if using --ssl. --ciphers Acceptable cipher list. --domain-socket Use a unix domain socket. --help Show usage. --key Certificate key. Required if using --ssl. --port 9090 Port to use. --protocol {binary} binary Protocol to use. --ssl If present, use SSL. --transport {buffered|framed} buffered Transport to use. EOF } my %opts = ( 'port' => 9090, 'protocol' => 'binary', 'transport' => 'buffered' ); GetOptions(\%opts, qw ( ca=s cert=s ciphers=s key=s domain-socket=s help host=s port=i protocol=s ssl transport=s )) || exit 1; if ($opts{help}) { usage(); exit 0; } my $socket = undef; if ($opts{'domain-socket'}) { $socket = Thrift::UnixSocket->new($opts{'domain-socket'}); } elsif ($opts{ssl}) { $socket = Thrift::SSLSocket->new(\%opts); } else { $socket = Thrift::Socket->new($opts{host}, $opts{port}); } my $transport; if ($opts{transport} eq 'buffered') { $transport = Thrift::BufferedTransport->new($socket, 1024, 1024); } elsif ($opts{transport} eq 'framed') { $transport = Thrift::FramedTransport->new($socket); } else { usage(); exit 1; } my $protocol; my $protocol2; if ($opts{protocol} eq 'binary' || $opts{protocol} eq 'multi') { $protocol = Thrift::BinaryProtocol->new($transport); } else { usage(); exit 1; } my $secondService = undef; if (index($opts{protocol}, 'multi') == 0) { $protocol2 = Thrift::MultiplexedProtocol->new($protocol, 'SecondService'); $protocol = Thrift::MultiplexedProtocol->new($protocol, 'ThriftTest'); $secondService = ThriftTest::SecondServiceClient->new($protocol2); } my $testClient = ThriftTest::ThriftTestClient->new($protocol); eval { $transport->open(); }; if($@){ die(Dumper($@)); } use constant ERR_BASETYPES => 1; use constant ERR_STRUCTS => 2; use constant ERR_CONTAINERS => 4; use constant ERR_EXCEPTIONS => 8; use constant ERR_PROTOCOL => 16; use constant ERR_UNKNOWN => 64; my $start = gettimeofday(); # # VOID TEST # print('testVoid()'); $testClient->testVoid(); print(" = void\n"); # # STRING TEST # print('testString("Test")'); my $s = $testClient->testString('Test'); print(qq| = "$s"\n|); exit(ERR_BASETYPES) if ($s ne 'Test'); # # MULTIPLEXED TEST # if (index($opts{protocol}, 'multi') == 0) { print('secondtestString("Test2")'); $s = $secondService->secondtestString('Test2'); print(qq| = "$s"\n|); exit(ERR_PROTOCOL) if ($s ne 'testString("Test2")'); } # # BOOL TEST # print('testBool(1)'); my $t = $testClient->testBool(1); print(" = $t\n"); exit(ERR_BASETYPES) if ($t ne 1); print('testBool(0)'); my $f = $testClient->testBool(0); print(" = $f\n"); exit(ERR_BASETYPES) if ($f ne q||); # # BYTE TEST # print('testByte(1)'); my $u8 = $testClient->testByte(1); print(" = $u8\n"); # # I32 TEST # print('testI32(-1)'); my $i32 = $testClient->testI32(-1); print(" = $i32\n"); exit(ERR_BASETYPES) if ($i32 ne -1); # # I64 TEST # print('testI64(-34359738368)'); my $i64 = $testClient->testI64(-34359738368); print(" = $i64\n"); exit(ERR_BASETYPES) if ($i64 ne -34359738368); # # DOUBLE TEST # print('testDouble(-852.234234234)'); my $dub = $testClient->testDouble(-852.234234234); print(" = $dub\n"); exit(ERR_BASETYPES) if ($dub ne -852.234234234); # # BINARY TEST # print("testBinary(pack('C*', 0..255))"); my $bin = $testClient->testBinary(pack('C*', 0..255)); printf(" = %s\n", join ' ', map { sprintf '%02x', $_ } unpack('C*', $bin)); exit(ERR_BASETYPES) if ($bin ne pack('C*', 0..255)); # # STRUCT TEST # print('testStruct({"Zero", 1, -3, -5})'); my $out = ThriftTest::Xtruct->new(); $out->string_thing('Zero'); $out->byte_thing(1); $out->i32_thing(-3); $out->i64_thing(-5); my $in = $testClient->testStruct($out); print(' = {"'.$in->string_thing.'", '. $in->byte_thing.', '. $in->i32_thing.', '. $in->i64_thing."}\n"); # # NESTED STRUCT TEST # print('testNest({1, {"Zero", 1, -3, -5}, 5}'); my $out2 = ThriftTest::Xtruct2->new(); $out2->byte_thing(1); $out2->struct_thing($out); $out2->i32_thing(5); my $in2 = $testClient->testNest($out2); $in = $in2->struct_thing; print(' = {'.$in2->byte_thing.', {"'. $in->string_thing.'", '. $in->byte_thing.', '. $in->i32_thing.', '. $in->i64_thing.'}, '. $in2->i32_thing."}\n"); # # MAP TEST # my $mapout = {}; for (my $i = 0; $i < 5; ++$i) { $mapout->{$i} = $i-10; } print('testMap({'); my $first = 1; while( my($key,$val) = each %$mapout) { if ($first) { $first = 0; } else { print(', '); } print("$key => $val"); } print('})'); my $mapin = $testClient->testMap($mapout); print(' = {'); $first = 1; while( my($key,$val) = each %$mapin){ if ($first) { $first = 0; } else { print(', '); } print("$key => $val"); } print("}\n"); # # SET TEST # my $setout = []; for (my $i = -2; $i < 3; ++$i) { push(@$setout, $i); } print('testSet({'.join(',',@$setout).'})'); my $setin = $testClient->testSet($setout); print(' = {'.join(',',@$setout)."}\n"); # # LIST TEST # my $listout = []; for (my $i = -2; $i < 3; ++$i) { push(@$listout, $i); } print('testList({'.join(',',@$listout).'})'); my $listin = $testClient->testList($listout); print(' = {'.join(',',@$listin)."}\n"); # # ENUM TEST # print('testEnum(ONE)'); my $ret = $testClient->testEnum(ThriftTest::Numberz::ONE); print(" = $ret\n"); print('testEnum(TWO)'); $ret = $testClient->testEnum(ThriftTest::Numberz::TWO); print(" = $ret\n"); print('testEnum(THREE)'); $ret = $testClient->testEnum(ThriftTest::Numberz::THREE); print(" = $ret\n"); print('testEnum(FIVE)'); $ret = $testClient->testEnum(ThriftTest::Numberz::FIVE); print(" = $ret\n"); print('testEnum(EIGHT)'); $ret = $testClient->testEnum(ThriftTest::Numberz::EIGHT); print(" = $ret\n"); # # TYPEDEF TEST # print('testTypedef(309858235082523)'); my $uid = $testClient->testTypedef(309858235082523); print(" = $uid\n"); # # NESTED MAP TEST # print('testMapMap(1)'); my $mm = $testClient->testMapMap(1); print(' = {'); while( my ($key,$val) = each %$mm) { print("$key => {"); while( my($k2,$v2) = each %$val) { print("$k2 => $v2, "); } print('}, '); } print("}\n"); # # INSANITY TEST # my $insane = ThriftTest::Insanity->new(); $insane->{userMap}->{ThriftTest::Numberz::FIVE} = 5000; my $truck = ThriftTest::Xtruct->new(); $truck->string_thing('Hello2'); $truck->byte_thing(2); $truck->i32_thing(2); $truck->i64_thing(2); my $truck2 = ThriftTest::Xtruct->new(); $truck2->string_thing('Goodbye4'); $truck2->byte_thing(4); $truck2->i32_thing(4); $truck2->i64_thing(4); push(@{$insane->{xtructs}}, $truck); push(@{$insane->{xtructs}}, $truck2); print('testInsanity()'); my $whoa = $testClient->testInsanity($insane); print(' = {'); while( my ($key,$val) = each %$whoa) { print("$key => {"); while( my($k2,$v2) = each %$val) { print("$k2 => {"); my $userMap = $v2->{userMap}; print('{'); if (ref($userMap) eq 'HASH') { while( my($k3,$v3) = each %$userMap) { print("$k3 => $v3, "); } } print('}, '); my $xtructs = $v2->{xtructs}; print('{'); if (ref($xtructs) eq 'ARRAY') { foreach my $x (@$xtructs) { print('{"'.$x->{string_thing}.'", '. $x->{byte_thing}.', '.$x->{i32_thing}.', '.$x->{i64_thing}.'}, '); } } print('}'); print('}, '); } print('}, '); } print("}\n"); # # EXCEPTION TEST # print(q|testException('Xception')|); eval { $testClient->testException('Xception'); print(" void\nFAILURE\n"); }; if($@ && $@->UNIVERSAL::isa('ThriftTest::Xception')) { print(' caught xception '.$@->{errorCode}.': '.$@->{message}."\n"); } # # Normal tests done. # my $stop = gettimeofday(); my $elp = sprintf('%d',1000*($stop - $start), 0); print("Total time: $elp ms\n"); # # Extraneous "I don't trust PHP to pack/unpack integer" tests # # Max I32 my $num = 2**30 + 2**30 - 1; my $num2 = $testClient->testI32($num); if ($num != $num2) { print "Missed max32 $num = $num2\n"; } # Min I32 $num = 0 - 2**31; $num2 = $testClient->testI32($num); if ($num != $num2) { print "Missed min32 $num = $num2\n"; } # Max Number I can get out of my perl $num = 2**40; $num2 = $testClient->testI64($num); if ($num != $num2) { print "Missed max64 $num = $num2\n"; } # Max Number I can get out of my perl $num = 0 - 2**40; $num2 = $testClient->testI64($num); if ($num != $num2) { print "Missed min64 $num = $num2\n"; } $transport->close(); thrift-0.19.0/test/perl/Makefile.in0000644000000000000000000004261614472652520017105 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/perl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/perl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/perl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../v0.16/ThriftTest.thrift $(THRIFT) --gen perl ../v0.16/ThriftTest.thrift precross: stubs check: stubs clean-local: $(RM) -r gen-perl/ dist-hook: $(RM) -r $(distdir)/gen-perl/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/ocaml/0000777000000000000000000000000014303740367015164 5ustar00rootroot00000000000000thrift-0.19.0/test/ocaml/client/0000777000000000000000000000000014303740367016442 5ustar00rootroot00000000000000thrift-0.19.0/test/ocaml/client/TestClient.ml0000644000000000000000000000443614303740367021055 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift;; open ThriftTest_types;; let s = new TSocket.t "127.0.0.1" 9090;; let p = new TBinaryProtocol.t s;; let c = new ThriftTest.client p p;; let sod = function Some v -> v | None -> raise Thrift_error;; s#opn; print_string (c#testString "bya"); print_char '\n'; print_int (c#testByte 8); print_char '\n'; print_int (c#testByte (-8)); print_char '\n'; print_int (c#testI32 32); print_char '\n'; print_string (Int64.to_string (c#testI64 64L)); print_char '\n'; print_float (c#testDouble 3.14); print_char '\n'; let l = [1;2;3;4] in if l = (c#testList l) then print_string "list ok\n" else print_string "list fail\n";; let h = Hashtbl.create 5 in let a = Hashtbl.add h in for i=1 to 10 do a i (10*i) done; let r = c#testMap h in for i=1 to 10 do try let g = Hashtbl.find r i in print_int i; print_char ' '; print_int g; print_char '\n' with Not_found -> print_string ("Can't find "^(string_of_int i)^"\n") done;; let s = Hashtbl.create 5 in let a = Hashtbl.add s in for i = 1 to 10 do a i true done; let r = c#testSet s in for i = 1 to 10 do try let g = Hashtbl.find r i in print_int i; print_char '\n' with Not_found -> print_string ("Can't find "^(string_of_int i)^"\n") done;; try c#testException "Xception" with Xception _ -> print_string "testException ok\n";; try ignore(c#testMultiException "Xception" "bya") with Xception e -> Printf.printf "%d %s\n" (sod e#get_errorCode) (sod e#get_message);; thrift-0.19.0/test/ocaml/client/Makefile0000644000000000000000000000211314303740367020073 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SOURCES = ../gen-ocaml/ThriftTest_types.ml ../gen-ocaml/ThriftTest_consts.ml ../gen-ocaml/SecondService.ml ../gen-ocaml/ThriftTest.ml TestClient.ml RESULT = tc INCDIRS = "../../../lib/ocaml/src/" "../gen-ocaml/" LIBS = unix thrift all: nc OCAMLMAKEFILE = ../../../lib/ocaml/OCamlMakefile include $(OCAMLMAKEFILE) thrift-0.19.0/test/ocaml/Makefile0000644000000000000000000000157514303740367016630 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # all: cd client; make; cd ..; cd server; make clean: cd client; make clean; cd ..; cd server; make clean thrift-0.19.0/test/ocaml/server/0000777000000000000000000000000014303740367016472 5ustar00rootroot00000000000000thrift-0.19.0/test/ocaml/server/Makefile0000644000000000000000000000212414303740367020125 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SOURCES = ../gen-ocaml/ThriftTest_types.ml ../gen-ocaml/ThriftTest_consts.ml ../gen-ocaml/SecondService.ml ../gen-ocaml/ThriftTest.ml TestServer.ml RESULT = ts INCDIRS = "../../../lib/ocaml/src/" "../gen-ocaml/" LIBS = thrift THREADS = yes all: nc OCAMLMAKEFILE = ../../../lib/ocaml/OCamlMakefile include $(OCAMLMAKEFILE) thrift-0.19.0/test/ocaml/server/TestServer.ml0000644000000000000000000001064214303740367021131 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift open ThriftTest_types let p = Printf.printf;; exception Die;; let sod = function Some v -> v | None -> raise Die;; class test_handler = object (self) inherit ThriftTest.iface method testVoid = p "testVoid()\n" method testString x = p "testString(%s)\n" (sod x); (sod x) method testByte x = p "testByte(%d)\n" (sod x); (sod x) method testI32 x = p "testI32(%d)\n" (sod x); (sod x) method testI64 x = p "testI64(%s)\n" (Int64.to_string (sod x)); (sod x) method testDouble x = p "testDouble(%f)\n" (sod x); (sod x) method testBinary x = p "testBinary(%s)\n" (sod x); (sod x) method testStruct x = p "testStruct(---)\n"; (sod x) method testNest x = p "testNest(---)\n"; (sod x) method testMap x = p "testMap(---)\n"; (sod x) method testSet x = p "testSet(---)\n"; (sod x) method testList x = p "testList(---)\n"; (sod x) method testEnum x = p "testEnum(---)\n"; (sod x) method testTypedef x = p "testTypedef(---)\n"; (sod x) method testMapMap x = p "testMapMap(%d)\n" (sod x); let mm = Hashtbl.create 3 in let pos = Hashtbl.create 7 in let neg = Hashtbl.create 7 in for i=1 to 4 do Hashtbl.add pos i i; Hashtbl.add neg (-i) (-i); done; Hashtbl.add mm 4 pos; Hashtbl.add mm (-4) neg; mm method testInsanity x = p "testInsanity()\n"; p "testinsanity()\n"; let hello = new xtruct in let goodbye = new xtruct in let crazy = new insanity in let looney = new insanity in let cumap = Hashtbl.create 7 in let insane = Hashtbl.create 7 in let firstmap = Hashtbl.create 7 in let secondmap = Hashtbl.create 7 in hello#set_string_thing "Hello2"; hello#set_byte_thing 2; hello#set_i32_thing 2; hello#set_i64_thing 2L; goodbye#set_string_thing "Goodbye4"; goodbye#set_byte_thing 4; goodbye#set_i32_thing 4; goodbye#set_i64_thing 4L; Hashtbl.add cumap Numberz.EIGHT 8L; Hashtbl.add cumap Numberz.FIVE 5L; crazy#set_userMap cumap; crazy#set_xtructs [goodbye; hello]; Hashtbl.add firstmap Numberz.TWO crazy; Hashtbl.add firstmap Numberz.THREE crazy; Hashtbl.add secondmap Numberz.SIX looney; Hashtbl.add insane 1L firstmap; Hashtbl.add insane 2L secondmap; insane method testMulti a0 a1 a2 a3 a4 a5 = p "testMulti()\n"; let hello = new xtruct in hello#set_string_thing "Hello2"; hello#set_byte_thing (sod a0); hello#set_i32_thing (sod a1); hello#set_i64_thing (sod a2); hello method testException s = p "testException(%S)\n" (sod s); if (sod s) = "Xception" then let x = new xception in x#set_errorCode 1001; x#set_message "This is an Xception"; raise (Xception x) else () method testMultiException a0 a1 = p "testMultiException(%S, %S)\n" (sod a0) (sod a1); if (sod a0) = "Xception" then let x = new xception in x#set_errorCode 1001; x#set_message "This is an Xception"; raise (Xception x) else (if (sod a0) = "Xception2" then let x = new xception2 in let s = new xtruct in x#set_errorCode 2002; s#set_string_thing "This as an Xception2"; x#set_struct_thing s; raise (Xception2 x) else ()); let res = new xtruct in res#set_string_thing (sod a1); res method testOneway i = Unix.sleep (sod i) end;; let h = new test_handler in let proc = new ThriftTest.processor h in let port = 9090 in let pf = new TBinaryProtocol.factory in let server = new TThreadedServer.t proc (new TServerSocket.t port) (new Transport.factory) pf pf in server#serve thrift-0.19.0/test/ThriftTest.thrift0000644000000000000000000002670714370300523017411 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace c_glib TTest namespace cpp thrift.test namespace delphi Thrift.Test namespace go thrifttest namespace java thrift.test namespace js ThriftTest namespace lua ThriftTest namespace netstd ThriftTest namespace perl ThriftTest namespace php ThriftTest namespace py ThriftTest namespace py.twisted ThriftTest namespace rb Thrift.Test namespace st ThriftTest namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest') // Presence of namespaces and sub-namespaces for which there is // no generator should compile with warnings only namespace noexist ThriftTest namespace cpp.noexist ThriftTest namespace * thrift.test /** * Docstring! */ enum Numberz { ONE = 1, TWO, THREE, FIVE = 5, SIX, EIGHT = 8 } const Numberz myNumberz = Numberz.ONE; // the following is expected to fail: // const Numberz urNumberz = ONE; typedef i64 UserId struct Bonk { 1: string message, 2: i32 type } typedef map MapType struct Bools { 1: bool im_true, 2: bool im_false, } struct Xtruct { 1: string string_thing, 4: i8 byte_thing, 9: i32 i32_thing, 11: i64 i64_thing } struct Xtruct2 { 1: i8 byte_thing, // used to be byte, hence the name 2: Xtruct struct_thing, 3: i32 i32_thing } struct Xtruct3 { 1: string string_thing, 4: i32 changed, 9: i32 i32_thing, 11: i64 i64_thing } struct Insanity { 1: map userMap, 2: list xtructs } (python.immutable= "") struct CrazyNesting { 1: string string_field, 2: optional set set_field, // Do not insert line break as test/go/Makefile.am is removing this line with pattern match 3: required list (python.immutable = ""), map(python.immutable = "")> (python.immutable = "")>>>> list_field, 4: binary binary_field 5: uuid uuid_field } union SomeUnion { 1: map map_thing, 2: string string_thing, 3: i32 i32_thing, 4: Xtruct3 xtruct_thing, 5: Insanity insanity_thing } exception Xception { 1: i32 errorCode, 2: string message } exception Xception2 { 1: i32 errorCode, 2: Xtruct struct_thing } struct EmptyStruct {} struct OneField { 1: EmptyStruct field } service ThriftTest { /** * Prints "testVoid()" and returns nothing. */ void testVoid(), /** * Prints 'testString("%s")' with thing as '%s' * @param string thing - the string to print * @return string - returns the string 'thing' */ string testString(1: string thing), /** * Prints 'testBool("%s")' where '%s' with thing as 'true' or 'false' * @param bool thing - the bool data to print * @return bool - returns the bool 'thing' */ bool testBool(1: bool thing), /** * Prints 'testByte("%d")' with thing as '%d' * The types i8 and byte are synonyms, use of i8 is encouraged, byte still exists for the sake of compatibility. * @param byte thing - the i8/byte to print * @return i8 - returns the i8/byte 'thing' */ i8 testByte(1: i8 thing), /** * Prints 'testI32("%d")' with thing as '%d' * @param i32 thing - the i32 to print * @return i32 - returns the i32 'thing' */ i32 testI32(1: i32 thing), /** * Prints 'testI64("%d")' with thing as '%d' * @param i64 thing - the i64 to print * @return i64 - returns the i64 'thing' */ i64 testI64(1: i64 thing), /** * Prints 'testDouble("%f")' with thing as '%f' * @param double thing - the double to print * @return double - returns the double 'thing' */ double testDouble(1: double thing), /** * Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data * @param binary thing - the binary data to print * @return binary - returns the binary 'thing' */ binary testBinary(1: binary thing), /** * Prints 'testUuid("%s")' where '%s' is the uuid given. Note that the uuid byte order should be correct. * @param uuid thing - the uuid to print * @return uuid - returns the uuid 'thing' */ uuid testUuid(1: uuid thing), /** * Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values * @param Xtruct thing - the Xtruct to print * @return Xtruct - returns the Xtruct 'thing' */ Xtruct testStruct(1: Xtruct thing), /** * Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct * @param Xtruct2 thing - the Xtruct2 to print * @return Xtruct2 - returns the Xtruct2 'thing' */ Xtruct2 testNest(1: Xtruct2 thing), /** * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' */ map testMap(1: map thing), /** * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' */ map testStringMap(1: map thing), /** * Prints 'testSet("{%s}")' where thing has been formatted into a string of values * separated by commas and new lines * @param set thing - the set to print * @return set - returns the set 'thing' */ set testSet(1: set thing), /** * Prints 'testList("{%s}")' where thing has been formatted into a string of values * separated by commas and new lines * @param list thing - the list to print * @return list - returns the list 'thing' */ list testList(1: list thing), /** * Prints 'testEnum("%d")' where thing has been formatted into its numeric value * @param Numberz thing - the Numberz to print * @return Numberz - returns the Numberz 'thing' */ Numberz testEnum(1: Numberz thing), /** * Prints 'testTypedef("%d")' with thing as '%d' * @param UserId thing - the UserId to print * @return UserId - returns the UserId 'thing' */ UserId testTypedef(1: UserId thing), /** * Prints 'testMapMap("%d")' with hello as '%d' * @param i32 hello - the i32 to print * @return map> - returns a dictionary with these values: * {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } */ map> testMapMap(1: i32 hello), /** * So you think you've got this all worked out, eh? * * Creates a map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, * 2 => { 6 => , }, * } * @return map> - a map with the above values */ map> testInsanity(1: Insanity argument), /** * Prints 'testMulti()' * @param i8 arg0 - * @param i32 arg1 - * @param i64 arg2 - * @param map arg3 - * @param Numberz arg4 - * @param UserId arg5 - * @return Xtruct - returns an Xtruct with string_thing = "Hello2, byte_thing = arg0, i32_thing = arg1 * and i64_thing = arg2 */ Xtruct testMulti(1: i8 arg0, 2: i32 arg1, 3: i64 arg2, 4: map arg3, 5: Numberz arg4, 6: UserId arg5), /** * Print 'testException(%s)' with arg as '%s' * @param string arg - a string indication what type of exception to throw * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg * else if arg == "TException" throw TException * else do not throw anything */ void testException(1: string arg) throws(1: Xception err1), /** * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' * @param string arg - a string indicating what type of exception to throw * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2" * else do not throw anything * @return Xtruct - an Xtruct with string_thing = arg1 */ Xtruct testMultiException(1: string arg0, 2: string arg1) throws(1: Xception err1, 2: Xception2 err2) /** * Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' * sleep 'secondsToSleep' * Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' * @param i32 secondsToSleep - the number of seconds to sleep */ oneway void testOneway(1:i32 secondsToSleep) } service SecondService { /** * Prints 'testString("%s")' with thing as '%s' * @param string thing - the string to print * @return string - returns the string 'thing' */ string secondtestString(1: string thing) } struct VersioningTestV1 { 1: i32 begin_in_both, 3: string old_string, 12: i32 end_in_both } struct VersioningTestV2 { 1: i32 begin_in_both, 2: i32 newint, 3: i8 newbyte, 4: i16 newshort, 5: i64 newlong, 6: double newdouble 7: Bonk newstruct, 8: list newlist, 9: set newset, 10: map newmap, 11: string newstring, 12: i32 end_in_both } struct ListTypeVersioningV1 { 1: list myints; 2: string hello; } struct ListTypeVersioningV2 { 1: list strings; 2: string hello; } struct GuessProtocolStruct { 7: map map_field, } struct LargeDeltas { 1: Bools b1, 10: Bools b10, 100: Bools b100, 500: bool check_true, 1000: Bools b1000, 1500: bool check_false, 2000: VersioningTestV2 vertwo2000, 2500: set a_set2500, 3000: VersioningTestV2 vertwo3000, 4000: list big_numbers } struct NestedListsI32x2 { 1: list> integerlist } struct NestedListsI32x3 { 1: list>> integerlist } struct NestedMixedx2 { 1: list> int_set_list 2: map> map_int_strset 3: list>> map_int_strset_list } struct ListBonks { 1: list bonk } struct NestedListsBonk { 1: list>> bonk } struct BoolTest { 1: optional bool b = true; 2: optional string s = "true"; } struct StructA { 1: required string s; } struct StructB { 1: optional StructA aa; 2: required StructA ab; } struct OptionalSetDefaultTest { 1: optional set with_default = [ "test" ] } struct OptionalBinary { 1: optional set bin_set = {} 2: optional map bin_map = {} } thrift-0.19.0/test/go/0000755000000000000000000000000014472652675014505 5ustar00rootroot00000000000000thrift-0.19.0/test/go/Makefile.am0000644000000000000000000000400114370300523016507 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # BUILT_SOURCES = gopath GOBUILDEXTRA = -buildvcs=false THRIFTCMD = $(THRIFT) -out src/gen --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/test/go/src/gen/$(COMPILER_EXTRAFLAG) THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift precross: bin/testclient bin/testserver ThriftTest.thrift: $(THRIFTTEST) grep -v list.*map.*list.*map $(THRIFTTEST) > ThriftTest.thrift .PHONY: gopath # Thrift for GO has problems with complex map keys: THRIFT-2063 gopath: $(THRIFT) ThriftTest.thrift mkdir -p src/gen $(THRIFTCMD) ThriftTest.thrift $(THRIFTCMD) ../StressTest.thrift $(THRIFTCMD) ../ConstantsDemo.thrift touch gopath bin/testclient: gopath $(GO) build $(GOBUILDEXTRA) -o bin/testclient ./src/bin/testclient bin/testserver: gopath $(GO) build $(GOBUILDEXTRA) -o bin/testserver ./src/bin/testserver bin/stress: gopath $(GO) build $(GOBUILDEXTRA) -o bin/stress ./src/bin/stress clean-local: $(RM) -r src/gen src/github.com/golang src/thrift bin pkg gopath ThriftTest.thrift check_PROGRAMS: bin/testclient bin/testserver bin/stress check: gopath genmock $(GO) test -v ./src/common/... $(GO) test -v ./src/gen/... genmock: gopath sh genmock.sh EXTRA_DIST = \ src/bin \ src/common \ genmock.sh thrift-0.19.0/test/go/src/0000755000000000000000000000000014472652675015274 5ustar00rootroot00000000000000thrift-0.19.0/test/go/src/bin/0000777000000000000000000000000014062750226016032 5ustar00rootroot00000000000000thrift-0.19.0/test/go/src/bin/testclient/0000777000000000000000000000000014370300523020201 5ustar00rootroot00000000000000thrift-0.19.0/test/go/src/bin/testclient/main.go0000644000000000000000000002411314370300523021451 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package main import ( "context" "flag" t "log" "reflect" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/test/go/src/common" "github.com/apache/thrift/test/go/src/gen/thrifttest" ) var host = flag.String("host", "localhost", "Host to connect") var port = flag.Int64("port", 9090, "Port number to connect") var domain_socket = flag.String("domain-socket", "", "Domain Socket (e.g. /tmp/thrifttest.thrift), instead of host and port") var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib") var _ = flag.Bool("zlib", false, "For compatibility. Ignored.") var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json") var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL") var testloops = flag.Int("testloops", 1, "Number of Tests") func main() { flag.Parse() client, _, err := common.StartClient(*host, *port, *domain_socket, *transport, *protocol, *ssl) if err != nil { t.Fatalf("Unable to start client: ", err) } for i := 0; i < *testloops; i++ { callEverything(client) } } var rmapmap = map[int32]map[int32]int32{ -4: {-4: -4, -3: -3, -2: -2, -1: -1}, 4: {4: 4, 3: 3, 2: 2, 1: 1}, } var xxs = &thrifttest.Xtruct{ StringThing: "Hello2", ByteThing: 42, I32Thing: 4242, I64Thing: 424242, } var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "Xception"} var defaultCtx = context.Background() func callEverything(client *thrifttest.ThriftTestClient) { var err error if err = client.TestVoid(defaultCtx); err != nil { t.Fatalf("Unexpected error in TestVoid() call: ", err) } thing, err := client.TestString(defaultCtx, "thing") if err != nil { t.Fatalf("Unexpected error in TestString() call: ", err) } if thing != "thing" { t.Fatalf("Unexpected TestString() result, expected 'thing' got '%s' ", thing) } bl, err := client.TestBool(defaultCtx, true) if err != nil { t.Fatalf("Unexpected error in TestBool() call: ", err) } if !bl { t.Fatalf("Unexpected TestBool() result expected true, got %f ", bl) } bl, err = client.TestBool(defaultCtx, false) if err != nil { t.Fatalf("Unexpected error in TestBool() call: ", err) } if bl { t.Fatalf("Unexpected TestBool() result expected false, got %f ", bl) } b, err := client.TestByte(defaultCtx, 42) if err != nil { t.Fatalf("Unexpected error in TestByte() call: ", err) } if b != 42 { t.Fatalf("Unexpected TestByte() result expected 42, got %d ", b) } i32, err := client.TestI32(defaultCtx, 4242) if err != nil { t.Fatalf("Unexpected error in TestI32() call: ", err) } if i32 != 4242 { t.Fatalf("Unexpected TestI32() result expected 4242, got %d ", i32) } i64, err := client.TestI64(defaultCtx, 424242) if err != nil { t.Fatalf("Unexpected error in TestI64() call: ", err) } if i64 != 424242 { t.Fatalf("Unexpected TestI64() result expected 424242, got %d ", i64) } d, err := client.TestDouble(defaultCtx, 42.42) if err != nil { t.Fatalf("Unexpected error in TestDouble() call: ", err) } if d != 42.42 { t.Fatalf("Unexpected TestDouble() result expected 42.42, got %f ", d) } binout := make([]byte, 256) for i := 0; i < 256; i++ { binout[i] = byte(i) } bin, err := client.TestBinary(defaultCtx, binout) if err != nil { t.Fatalf("TestBinary failed with %v", err) } for i := 0; i < 256; i++ { if binout[i] != bin[i] { t.Fatalf("Unexpected TestBinary() result expected %d, got %d ", binout[i], bin[i]) } } uout := thrift.Tuuid{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, } u, err := client.TestUuid(defaultCtx, uout) if err != nil { t.Fatalf("TestUuid failed with %v", err) } if u != uout { t.Fatalf("Unexpected TestUuid() result expected %v, got %v", uout, u) } xs := thrifttest.NewXtruct() xs.StringThing = "thing" xs.ByteThing = 42 xs.I32Thing = 4242 xs.I64Thing = 424242 xsret, err := client.TestStruct(defaultCtx, xs) if err != nil { t.Fatalf("Unexpected error in TestStruct() call: ", err) } if *xs != *xsret { t.Fatalf("Unexpected TestStruct() result expected %#v, got %#v ", xs, xsret) } x2 := thrifttest.NewXtruct2() x2.StructThing = xs x2ret, err := client.TestNest(defaultCtx, x2) if err != nil { t.Fatalf("Unexpected error in TestNest() call: ", err) } if !reflect.DeepEqual(x2, x2ret) { t.Fatalf("Unexpected TestNest() result expected %#v, got %#v ", x2, x2ret) } m := map[int32]int32{1: 2, 3: 4, 5: 42} mret, err := client.TestMap(defaultCtx, m) if err != nil { t.Fatalf("Unexpected error in TestMap() call: ", err) } if !reflect.DeepEqual(m, mret) { t.Fatalf("Unexpected TestMap() result expected %#v, got %#v ", m, mret) } sm := map[string]string{"a": "2", "b": "blah", "some": "thing"} smret, err := client.TestStringMap(defaultCtx, sm) if err != nil { t.Fatalf("Unexpected error in TestStringMap() call: ", err) } if !reflect.DeepEqual(sm, smret) { t.Fatalf("Unexpected TestStringMap() result expected %#v, got %#v ", sm, smret) } s := []int32{1, 2, 42} sret, err := client.TestSet(defaultCtx, s) if err != nil { t.Fatalf("Unexpected error in TestSet() call: ", err) } // Sets can be in any order, but Go slices are ordered, so reflect.DeepEqual won't work. stemp := map[int32]struct{}{} for _, val := range s { stemp[val] = struct{}{} } for _, val := range sret { if _, ok := stemp[val]; !ok { t.Fatalf("Unexpected TestSet() result expected %#v, got %#v ", s, sret) } } l := []int32{1, 2, 42} lret, err := client.TestList(defaultCtx, l) if err != nil { t.Fatalf("Unexpected error in TestList() call: ", err) } if !reflect.DeepEqual(l, lret) { t.Fatalf("Unexpected TestList() result expected %#v, got %#v ", l, lret) } eret, err := client.TestEnum(defaultCtx, thrifttest.Numberz_TWO) if err != nil { t.Fatalf("Unexpected error in TestEnum() call: ", err) } if eret != thrifttest.Numberz_TWO { t.Fatalf("Unexpected TestEnum() result expected %#v, got %#v ", thrifttest.Numberz_TWO, eret) } tret, err := client.TestTypedef(defaultCtx, thrifttest.UserId(42)) if err != nil { t.Fatalf("Unexpected error in TestTypedef() call: ", err) } if tret != thrifttest.UserId(42) { t.Fatalf("Unexpected TestTypedef() result expected %#v, got %#v ", thrifttest.UserId(42), tret) } mapmap, err := client.TestMapMap(defaultCtx, 42) if err != nil { t.Fatalf("Unexpected error in TestMapMap() call: ", err) } if !reflect.DeepEqual(mapmap, rmapmap) { t.Fatalf("Unexpected TestMapMap() result expected %#v, got %#v ", rmapmap, mapmap) } crazy := thrifttest.NewInsanity() crazy.UserMap = map[thrifttest.Numberz]thrifttest.UserId{ thrifttest.Numberz_FIVE: 5, thrifttest.Numberz_EIGHT: 8, } truck1 := thrifttest.NewXtruct() truck1.StringThing = "Goodbye4" truck1.ByteThing = 4 truck1.I32Thing = 4 truck1.I64Thing = 4 truck2 := thrifttest.NewXtruct() truck2.StringThing = "Hello2" truck2.ByteThing = 2 truck2.I32Thing = 2 truck2.I64Thing = 2 crazy.Xtructs = []*thrifttest.Xtruct{ truck1, truck2, } insanity, err := client.TestInsanity(defaultCtx, crazy) if err != nil { t.Fatalf("Unexpected error in TestInsanity() call: ", err) } if !reflect.DeepEqual(crazy, insanity[1][2]) { t.Fatalf("Unexpected TestInsanity() first result expected %#v, got %#v ", crazy, insanity[1][2]) } if !reflect.DeepEqual(crazy, insanity[1][3]) { t.Fatalf("Unexpected TestInsanity() second result expected %#v, got %#v ", crazy, insanity[1][3]) } if len(insanity[2][6].UserMap) > 0 || len(insanity[2][6].Xtructs) > 0 { t.Fatalf("Unexpected TestInsanity() non-empty result got %#v ", insanity[2][6]) } xxsret, err := client.TestMulti(defaultCtx, 42, 4242, 424242, map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)) if err != nil { t.Fatalf("Unexpected error in TestMulti() call: ", err) } if !reflect.DeepEqual(xxs, xxsret) { t.Fatalf("Unexpected TestMulti() result expected %#v, got %#v ", xxs, xxsret) } err = client.TestException(defaultCtx, "Xception") if err == nil { t.Fatalf("Expecting exception in TestException() call") } if !reflect.DeepEqual(err, xcept) { t.Fatalf("Unexpected TestException() result expected %#v, got %#v ", xcept, err) } err = client.TestException(defaultCtx, "TException") _, ok := err.(thrift.TApplicationException) if err == nil || !ok { t.Fatalf("Unexpected TestException() result expected ApplicationError, got %#v ", err) } ign, err := client.TestMultiException(defaultCtx, "Xception", "ignoreme") if ign != nil || err == nil { t.Fatalf("Expecting exception in TestMultiException() call") } if !reflect.DeepEqual(err, &thrifttest.Xception{ErrorCode: 1001, Message: "This is an Xception"}) { t.Fatalf("Unexpected TestMultiException() %#v ", err) } ign, err = client.TestMultiException(defaultCtx, "Xception2", "ignoreme") if ign != nil || err == nil { t.Fatalf("Expecting exception in TestMultiException() call") } expecting := &thrifttest.Xception2{ErrorCode: 2002, StructThing: &thrifttest.Xtruct{StringThing: "This is an Xception2"}} if !reflect.DeepEqual(err, expecting) { t.Fatalf("Unexpected TestMultiException() %#v ", err) } err = client.TestOneway(defaultCtx, 2) if err != nil { t.Fatalf("Unexpected error in TestOneway() call: ", err) } //Make sure the connection still alive if err = client.TestVoid(defaultCtx); err != nil { t.Fatalf("Unexpected error in TestVoid() call: ", err) } } thrift-0.19.0/test/go/src/bin/testserver/0000777000000000000000000000000014303740367020243 5ustar00rootroot00000000000000thrift-0.19.0/test/go/src/bin/testserver/main.go0000644000000000000000000000471414303740367021520 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package main import ( "flag" "fmt" "log" "net/http" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/test/go/src/common" ) var host = flag.String("host", "localhost", "Host to connect") var port = flag.Int64("port", 9090, "Port number to connect") var domain_socket = flag.String("domain-socket", "", "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port") var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib") var _ = flag.Bool("zlib", false, "For compatibility. Ignored.") var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json, header") var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL") var certPath = flag.String("certPath", "keys", "Directory that contains SSL certificates") func main() { flag.Parse() processor, serverTransport, transportFactory, protocolFactory, err := common.GetServerParams(*host, *port, *domain_socket, *transport, *protocol, *ssl, *certPath, common.PrintingHandler) if err != nil { log.Fatalf("Unable to process server params: %v", err) } if *transport == "http" { http.HandleFunc("/", thrift.NewThriftHandlerFunc(processor, protocolFactory, protocolFactory)) if *ssl { err := http.ListenAndServeTLS(fmt.Sprintf(":%d", *port), *certPath+"/server.pem", *certPath+"/server.key", nil) if err != nil { fmt.Println(err) return } } else { http.ListenAndServe(fmt.Sprintf(":%d", *port), nil) } } else { server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) if err = server.Listen(); err != nil { return } go server.AcceptLoop() server.Serve() } } thrift-0.19.0/test/go/src/bin/stress/0000777000000000000000000000000014303740367017360 5ustar00rootroot00000000000000thrift-0.19.0/test/go/src/bin/stress/main.go0000644000000000000000000001551414303740367020635 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package main import ( "context" "flag" "fmt" "log" _ "net/http/pprof" "os" "runtime" "runtime/pprof" "sync" "sync/atomic" "time" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/test/go/src/gen/stress" ) var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to this file") var memprofile = flag.String("memprofile", "", "write memory profile to this file") var ( host = flag.String("host", "localhost", "Host to connect") port = flag.Int64("port", 9091, "Port number to connect") loop = flag.Int("loops", 50000, "The number of remote thrift calls each client makes") runserver = flag.Int("server", 1, "Run the Thrift server in this process") clients = flag.Int("clients", 20, "Number of client threads to create - 0 implies no clients, i.e. server only") callName = flag.String("call", "echoVoid", "Service method to call, one of echoVoid, echoByte, echoI32, echoI64, echoString, echiList, echoSet, echoMap") compact = flag.Bool("compact", false, "Use compact protocol instead of binary.") framed = flag.Bool("framed", false, "Use framed transport instead of buffered.") ) var hostPort string type callT int64 const ( echoVoid callT = iota echoByte echoI32 echoI64 echoString echiList echoSet echoMap ) var callTMap = map[string]callT{ "echoVoid": echoVoid, "echoByte": echoByte, "echoI32": echoI32, "echoI64": echoI64, "echoString": echoString, "echiList": echiList, "echoSet": echoSet, "echoMap": echoMap, } var callType callT var ready, done sync.WaitGroup var clicounter int64 = 0 var counter int64 = 0 func main() { flag.Parse() if *memprofile != "" { runtime.MemProfileRate = 100 } var ok bool if callType, ok = callTMap[*callName]; !ok { log.Fatal("Unknown service call", *callName) } if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } hostPort = fmt.Sprintf("%s:%d", *host, *port) var protocolFactory thrift.TProtocolFactory var transportFactory thrift.TTransportFactory if *compact { protocolFactory = thrift.NewTCompactProtocolFactoryConf(nil) } else { protocolFactory = thrift.NewTBinaryProtocolFactoryConf(nil) } if *framed { transportFactory = thrift.NewTTransportFactory() transportFactory = thrift.NewTFramedTransportFactoryConf(transportFactory, nil) } else { transportFactory = thrift.NewTBufferedTransportFactory(8192) } if *runserver > 0 { serverTransport, err := thrift.NewTServerSocket(hostPort) if err != nil { log.Fatalf("Unable to create server socket: %s", err) } processor := stress.NewServiceProcessor(&handler{}) server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) if *clients == 0 { server.Serve() } else { go server.Serve() } } //start clients if *clients != 0 { ready.Add(*clients + 1) done.Add(*clients) for i := 0; i < *clients; i++ { go client(protocolFactory) } ready.Done() ready.Wait() //run! startTime := time.Now() //wait for completion done.Wait() endTime := time.Now() duration := endTime.Sub(startTime) log.Printf("%d calls in %v (%f calls per second)\n", clicounter, duration, float64(clicounter)/duration.Seconds()) } if *memprofile != "" { f, err := os.Create(*memprofile) if err != nil { log.Fatal(err) } pprof.WriteHeapProfile(f) f.Close() return } } func client(protocolFactory thrift.TProtocolFactory) { ctx := context.Background() trans := thrift.NewTSocketConf(hostPort, nil) btrans := thrift.NewTBufferedTransport(trans, 2048) client := stress.NewServiceClientFactory(btrans, protocolFactory) err := trans.Open() if err != nil { log.Fatalf("Unable to open connection: %s", err) } ready.Done() ready.Wait() switch callType { case echoVoid: for i := 0; i < *loop; i++ { client.EchoVoid(ctx) atomic.AddInt64(&clicounter, 1) } case echoByte: for i := 0; i < *loop; i++ { client.EchoByte(ctx, 42) atomic.AddInt64(&clicounter, 1) } case echoI32: for i := 0; i < *loop; i++ { client.EchoI32(ctx, 4242) atomic.AddInt64(&clicounter, 1) } case echoI64: for i := 0; i < *loop; i++ { client.EchoI64(ctx, 424242) atomic.AddInt64(&clicounter, 1) } case echoString: for i := 0; i < *loop; i++ { client.EchoString(ctx, "TestString") atomic.AddInt64(&clicounter, 1) } case echiList: l := []int8{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8} for i := 0; i < *loop; i++ { client.EchoList(ctx, l) atomic.AddInt64(&clicounter, 1) } case echoSet: s := []int8{-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8} for i := 0; i < *loop; i++ { client.EchoSet(ctx, s) atomic.AddInt64(&clicounter, 1) } case echoMap: m := map[int8]int8{-10: 10, -9: 9, -8: 8, -7: 7, -6: 6, -5: 5, -4: 4, -3: 3, -2: 2, -1: 1, 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8} for i := 0; i < *loop; i++ { client.EchoMap(ctx, m) atomic.AddInt64(&clicounter, 1) } } done.Done() } type handler struct{} func (h *handler) EchoVoid(ctx context.Context) (err error) { atomic.AddInt64(&counter, 1) return nil } func (h *handler) EchoByte(ctx context.Context, arg int8) (r int8, err error) { atomic.AddInt64(&counter, 1) return arg, nil } func (h *handler) EchoI32(ctx context.Context, arg int32) (r int32, err error) { atomic.AddInt64(&counter, 1) return arg, nil } func (h *handler) EchoI64(ctx context.Context, arg int64) (r int64, err error) { atomic.AddInt64(&counter, 1) return arg, nil } func (h *handler) EchoString(ctx context.Context, arg string) (r string, err error) { atomic.AddInt64(&counter, 1) return arg, nil } func (h *handler) EchoList(ctx context.Context, arg []int8) (r []int8, err error) { atomic.AddInt64(&counter, 1) return arg, nil } func (h *handler) EchoSet(ctx context.Context, arg []int8) (r []int8, err error) { atomic.AddInt64(&counter, 1) return arg, nil } func (h *handler) EchoMap(ctx context.Context, arg map[int8]int8) (r map[int8]int8, err error) { atomic.AddInt64(&counter, 1) return arg, nil } thrift-0.19.0/test/go/src/common/0000777000000000000000000000000014370300523016543 5ustar00rootroot00000000000000thrift-0.19.0/test/go/src/common/simple_handler.go0000644000000000000000000001021114370300523022047 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package common import ( "errors" "time" "github.com/apache/thrift/lib/go/thrift" //lint:ignore ST1001 allow dot import here . "github.com/apache/thrift/test/go/src/gen/thrifttest" ) var SimpleHandler = &simpleHandler{} type simpleHandler struct{} func (p *simpleHandler) TestVoid() (err error) { return nil } func (p *simpleHandler) TestString(thing string) (r string, err error) { return thing, nil } func (p *simpleHandler) TestBool(thing []byte) (r []byte, err error) { return thing, nil } func (p *simpleHandler) TestByte(thing int8) (r int8, err error) { return thing, nil } func (p *simpleHandler) TestI32(thing int32) (r int32, err error) { return thing, nil } func (p *simpleHandler) TestI64(thing int64) (r int64, err error) { return thing, nil } func (p *simpleHandler) TestDouble(thing float64) (r float64, err error) { return thing, nil } func (p *simpleHandler) TestBinary(thing []byte) (r []byte, err error) { return thing, nil } func (p *simpleHandler) TestUuid(thing thrift.Tuuid) (r thrift.Tuuid, err error) { return thing, nil } func (p *simpleHandler) TestStruct(thing *Xtruct) (r *Xtruct, err error) { return r, err } func (p *simpleHandler) TestNest(nest *Xtruct2) (r *Xtruct2, err error) { return nest, nil } func (p *simpleHandler) TestMap(thing map[int32]int32) (r map[int32]int32, err error) { return thing, nil } func (p *simpleHandler) TestStringMap(thing map[string]string) (r map[string]string, err error) { return thing, nil } func (p *simpleHandler) TestSet(thing []int32) (r []int32, err error) { return thing, nil } func (p *simpleHandler) TestList(thing []int32) (r []int32, err error) { return thing, nil } func (p *simpleHandler) TestEnum(thing Numberz) (r Numberz, err error) { return thing, nil } func (p *simpleHandler) TestTypedef(thing UserId) (r UserId, err error) { return thing, nil } func (p *simpleHandler) TestMapMap(hello int32) (r map[int32]map[int32]int32, err error) { r = map[int32]map[int32]int32{ -4: {-4: -4, -3: -3, -2: -2, -1: -1}, 4: {4: 4, 3: 3, 2: 2, 1: 1}, } return } func (p *simpleHandler) TestInsanity(argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) { //lint:ignore ST1005 To be consistent with other language libraries. return nil, errors.New("No Insanity") } func (p *simpleHandler) TestMulti(arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) { r = NewXtruct() r.StringThing = "Hello2" r.ByteThing = arg0 r.I32Thing = arg1 r.I64Thing = arg2 return } func (p *simpleHandler) TestException(arg string) (err error) { switch arg { case "Xception": e := NewXception() e.ErrorCode = 1001 e.Message = arg return e case "TException": //lint:ignore ST1005 To be consistent with other language libraries. return errors.New("Just TException") } return } func (p *simpleHandler) TestMultiException(arg0 string, arg1 string) (r *Xtruct, err error) { switch arg0 { case "Xception": e := NewXception() e.ErrorCode = 1001 e.Message = "This is an Xception" return nil, e case "Xception2": e := NewXception2() e.ErrorCode = 2002 e.StructThing.StringThing = "This is an Xception2" return nil, e default: r = NewXtruct() r.StringThing = arg1 return } } func (p *simpleHandler) TestOneway(secondsToSleep int32) (err error) { time.Sleep(time.Second * time.Duration(secondsToSleep)) return } thrift-0.19.0/test/go/src/common/context_test.go0000644000000000000000000000531614303740367021630 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package common import ( "context" "fmt" "net" "net/http" "net/url" "os" "syscall" "testing" "time" "github.com/apache/thrift/lib/go/thrift" ) type slowHttpHandler struct{} func (slowHttpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { time.Sleep(1 * time.Second) } func TestHttpContextTimeout(t *testing.T) { unit := test_unit{"127.0.0.1", 9096, "", "http", "binary", false} server := &http.Server{Addr: unit.host + fmt.Sprintf(":%d", unit.port), Handler: slowHttpHandler{}} go server.ListenAndServe() client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl) if err != nil { t.Errorf("Unable to start client: %v", err) return } defer trans.Close() unwrapErr := func(err error) error { for { //lint:ignore S1034 type switch is more appropriate here. switch err.(type) { case thrift.TTransportException: err = err.(thrift.TTransportException).Err() case *url.Error: err = err.(*url.Error).Err case *net.OpError: err = err.(*net.OpError).Err case *os.SyscallError: err = err.(*os.SyscallError).Err default: return err } } } serverStartupDeadline := time.Now().Add(5 * time.Second) for { ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond) err = client.TestVoid(ctx) err = unwrapErr(err) if err != syscall.ECONNREFUSED || time.Now().After(serverStartupDeadline) { break } time.Sleep(time.Millisecond) } if err == nil { t.Errorf("Request completed (should have timed out)") return } // We've got to switch on `err.Error()` here since go1.7 doesn't properly return // `context.DeadlineExceeded` error and `http.errRequestCanceled` is not exported. // See https://github.com/golang/go/issues/17711 switch err.Error() { case context.DeadlineExceeded.Error(), "net/http: request canceled": // Expected error default: t.Errorf("Unexpected error: %s", err) } } thrift-0.19.0/test/go/src/common/server.go0000644000000000000000000000674414303740367020421 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package common import ( "compress/zlib" "crypto/tls" "flag" "fmt" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/test/go/src/gen/thrifttest" ) var ( debugServerProtocol bool ) func init() { flag.BoolVar(&debugServerProtocol, "debug_server_protocol", false, "turn server protocol trace on") } func GetServerParams( host string, port int64, domain_socket string, transport string, protocol string, ssl bool, certPath string, handler thrifttest.ThriftTest, ) (thrift.TProcessor, thrift.TServerTransport, thrift.TTransportFactory, thrift.TProtocolFactory, error) { var err error hostPort := fmt.Sprintf("%s:%d", host, port) var cfg *thrift.TConfiguration = nil var protocolFactory thrift.TProtocolFactory switch protocol { case "compact": protocolFactory = thrift.NewTCompactProtocolFactoryConf(cfg) case "simplejson": protocolFactory = thrift.NewTSimpleJSONProtocolFactoryConf(cfg) case "json": protocolFactory = thrift.NewTJSONProtocolFactory() case "binary": protocolFactory = thrift.NewTBinaryProtocolFactoryConf(nil) case "header": protocolFactory = thrift.NewTHeaderProtocolFactoryConf(nil) default: return nil, nil, nil, nil, fmt.Errorf("invalid protocol specified %s", protocol) } if debugServerProtocol { protocolFactory = thrift.NewTDebugProtocolFactoryWithLogger(protocolFactory, "server:", thrift.StdLogger(nil)) } var serverTransport thrift.TServerTransport if ssl { cfg := new(tls.Config) if cert, err := tls.LoadX509KeyPair(certPath+"/server.crt", certPath+"/server.key"); err != nil { return nil, nil, nil, nil, err } else { cfg.Certificates = append(cfg.Certificates, cert) } serverTransport, err = thrift.NewTSSLServerSocket(hostPort, cfg) } else { if domain_socket != "" { serverTransport, err = thrift.NewTServerSocket(domain_socket) } else { serverTransport, err = thrift.NewTServerSocket(hostPort) } } if err != nil { return nil, nil, nil, nil, err } var transportFactory thrift.TTransportFactory switch transport { case "http": // there is no such factory, and we don't need any transportFactory = nil case "framed": transportFactory = thrift.NewTTransportFactory() transportFactory = thrift.NewTFramedTransportFactoryConf(transportFactory, nil) case "buffered": transportFactory = thrift.NewTBufferedTransportFactory(8192) case "zlib": transportFactory = thrift.NewTZlibTransportFactory(zlib.BestCompression) case "": transportFactory = thrift.NewTTransportFactory() default: return nil, nil, nil, nil, fmt.Errorf("invalid transport specified %s", transport) } processor := thrifttest.NewThriftTestProcessor(handler) return processor, serverTransport, transportFactory, protocolFactory, nil } thrift-0.19.0/test/go/src/common/printing_handler.go0000644000000000000000000002755514370300523022433 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package common import ( "context" "encoding/hex" "errors" "fmt" "time" "github.com/apache/thrift/lib/go/thrift" //lint:ignore ST1001 allow dot import here . "github.com/apache/thrift/test/go/src/gen/thrifttest" ) var PrintingHandler = &printingHandler{} type printingHandler struct{} // Prints "testVoid()" and returns nothing. func (p *printingHandler) TestVoid(ctx context.Context) (err error) { fmt.Println("testVoid()") return nil } // Prints 'testString("%s")' with thing as '%s' // @param string thing - the string to print // @return string - returns the string 'thing' // // Parameters: // - Thing func (p *printingHandler) TestString(ctx context.Context, thing string) (r string, err error) { fmt.Printf("testString(\"%s\")\n", thing) return thing, nil } // Prints 'testBool("%t")' with thing as 'true' or 'false' // @param bool thing - the bool to print // @return bool - returns the bool 'thing' // // Parameters: // - Thing func (p *printingHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) { fmt.Printf("testBool(%t)\n", thing) return thing, nil } // Prints 'testByte("%d")' with thing as '%d' // @param byte thing - the byte to print // @return byte - returns the byte 'thing' // // Parameters: // - Thing func (p *printingHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) { fmt.Printf("testByte(%d)\n", thing) return thing, nil } // Prints 'testI32("%d")' with thing as '%d' // @param i32 thing - the i32 to print // @return i32 - returns the i32 'thing' // // Parameters: // - Thing func (p *printingHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) { fmt.Printf("testI32(%d)\n", thing) return thing, nil } // Prints 'testI64("%d")' with thing as '%d' // @param i64 thing - the i64 to print // @return i64 - returns the i64 'thing' // // Parameters: // - Thing func (p *printingHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) { fmt.Printf("testI64(%d)\n", thing) return thing, nil } // Prints 'testDouble("%f")' with thing as '%f' // @param double thing - the double to print // @return double - returns the double 'thing' // // Parameters: // - Thing func (p *printingHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) { fmt.Printf("testDouble(%f)\n", thing) return thing, nil } // Prints 'testBinary("%s")' where '%s' is a hex-formatted string of thing's data // @param []byte thing - the binary to print // @return []byte - returns the binary 'thing' // // Parameters: // - Thing func (p *printingHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) { fmt.Printf("testBinary(%s)\n", hex.EncodeToString(thing)) return thing, nil } // Prints 'testUuid("%s")' where '%s' is the uuid given. Note that the uuid byte order should be correct. // @param uuid thing - the uuid to print // @return uuid - returns the uuid 'thing' // // Parameters: // - Thing func (p *printingHandler) TestUuid(ctx context.Context, thing thrift.Tuuid) (r thrift.Tuuid, err error) { fmt.Printf("testUuid(%s)\n", thing.String()) return thing, nil } // Prints 'testStruct("{%s}")' where thing has been formatted into a string of comma separated values // @param Xtruct thing - the Xtruct to print // @return Xtruct - returns the Xtruct 'thing' // // Parameters: // - Thing func (p *printingHandler) TestStruct(ctx context.Context, thing *Xtruct) (r *Xtruct, err error) { fmt.Printf("testStruct({\"%s\", %d, %d, %d})\n", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing) return thing, err } // Prints 'testNest("{%s}")' where thing has been formatted into a string of the nested struct // @param Xtruct2 thing - the Xtruct2 to print // @return Xtruct2 - returns the Xtruct2 'thing' // // Parameters: // - Thing func (p *printingHandler) TestNest(ctx context.Context, nest *Xtruct2) (r *Xtruct2, err error) { thing := nest.StructThing fmt.Printf("testNest({%d, {\"%s\", %d, %d, %d}, %d})\n", nest.ByteThing, thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing, nest.I32Thing) return nest, nil } // Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs // // separated by commas and new lines // // @param map thing - the map to print // @return map - returns the map 'thing' // // Parameters: // - Thing func (p *printingHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) { fmt.Printf("testMap({") first := true for k, v := range thing { if first { first = false } else { fmt.Printf(", ") } fmt.Printf("%d => %d", k, v) } fmt.Printf("})\n") return thing, nil } // Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs // // separated by commas and new lines // // @param map thing - the map to print // @return map - returns the map 'thing' // // Parameters: // - Thing func (p *printingHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) { fmt.Printf("testStringMap({") first := true for k, v := range thing { if first { first = false } else { fmt.Printf(", ") } fmt.Printf("%s => %s", k, v) } fmt.Printf("})\n") return thing, nil } // Prints 'testSet("{%s}")' where thing has been formatted into a string of values // // separated by commas and new lines // // @param set thing - the set to print // @return set - returns the set 'thing' // // Parameters: // - Thing func (p *printingHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) { fmt.Printf("testSet({") first := true for k := range thing { if first { first = false } else { fmt.Printf(", ") } fmt.Printf("%d", k) } fmt.Printf("})\n") return thing, nil } // Prints 'testList("{%s}")' where thing has been formatted into a string of values // // separated by commas and new lines // // @param list thing - the list to print // @return list - returns the list 'thing' // // Parameters: // - Thing func (p *printingHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) { fmt.Printf("testList({") for i, v := range thing { if i != 0 { fmt.Printf(", ") } fmt.Printf("%d", v) } fmt.Printf("})\n") return thing, nil } // Prints 'testEnum("%d")' where thing has been formatted into it's numeric value // @param Numberz thing - the Numberz to print // @return Numberz - returns the Numberz 'thing' // // Parameters: // - Thing func (p *printingHandler) TestEnum(ctx context.Context, thing Numberz) (r Numberz, err error) { fmt.Printf("testEnum(%d)\n", thing) return thing, nil } // Prints 'testTypedef("%d")' with thing as '%d' // @param UserId thing - the UserId to print // @return UserId - returns the UserId 'thing' // // Parameters: // - Thing func (p *printingHandler) TestTypedef(ctx context.Context, thing UserId) (r UserId, err error) { fmt.Printf("testTypedef(%d)\n", thing) return thing, nil } // Prints 'testMapMap("%d")' with hello as '%d' // @param i32 hello - the i32 to print // @return map> - returns a dictionary with these values: // // {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => 2, 3 => 3, 4 => 4, }, } // // Parameters: // - Hello func (p *printingHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) { fmt.Printf("testMapMap(%d)\n", hello) r = map[int32]map[int32]int32{ -4: {-4: -4, -3: -3, -2: -2, -1: -1}, 4: {4: 4, 3: 3, 2: 2, 1: 1}, } return } // So you think you've got this all worked, out eh? // // Creates a the returned map with these values and prints it out: // // { 1 => { 2 => argument, // 3 => argument, // }, // 2 => { 6 => , }, // } // // @return map> - a map with the above values // // Parameters: // - Argument func (p *printingHandler) TestInsanity(ctx context.Context, argument *Insanity) (r map[UserId]map[Numberz]*Insanity, err error) { fmt.Printf("testInsanity()\n") r = make(map[UserId]map[Numberz]*Insanity) r[1] = map[Numberz]*Insanity{ 2: argument, 3: argument, } r[2] = map[Numberz]*Insanity{ 6: NewInsanity(), } return } // Prints 'testMulti()' // @param byte arg0 - // @param i32 arg1 - // @param i64 arg2 - // @param map arg3 - // @param Numberz arg4 - // @param UserId arg5 - // @return Xtruct - returns an Xtruct with StringThing = "Hello2, ByteThing = arg0, I32Thing = arg1 // // and I64Thing = arg2 // // Parameters: // - Arg0 // - Arg1 // - Arg2 // - Arg3 // - Arg4 // - Arg5 func (p *printingHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 Numberz, arg5 UserId) (r *Xtruct, err error) { fmt.Printf("testMulti()\n") r = NewXtruct() r.StringThing = "Hello2" r.ByteThing = arg0 r.I32Thing = arg1 r.I64Thing = arg2 return } // Print 'testException(%s)' with arg as '%s' // @param string arg - a string indication what type of exception to throw // if arg == "Xception" throw Xception with errorCode = 1001 and message = arg // elsen if arg == "TException" throw TException // else do not throw anything // // Parameters: // - Arg func (p *printingHandler) TestException(ctx context.Context, arg string) (err error) { fmt.Printf("testException(%s)\n", arg) switch arg { case "Xception": e := NewXception() e.ErrorCode = 1001 e.Message = arg return e case "TException": //lint:ignore ST1005 To be consistent with other language libraries. return errors.New("Just TException") } return } // Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' // @param string arg - a string indication what type of exception to throw // if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" // elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and message = "This is an Xception2" // else do not throw anything // @return Xtruct - an Xtruct with StringThing = arg1 // // Parameters: // - Arg0 // - Arg1 func (p *printingHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *Xtruct, err error) { fmt.Printf("testMultiException(%s, %s)\n", arg0, arg1) switch arg0 { case "Xception": e := NewXception() e.ErrorCode = 1001 e.Message = "This is an Xception" return nil, e case "Xception2": e := NewXception2() e.ErrorCode = 2002 e.StructThing = NewXtruct() e.StructThing.StringThing = "This is an Xception2" return nil, e default: r = NewXtruct() r.StringThing = arg1 return } } // Print 'testOneway(%d): Sleeping...' with secondsToSleep as '%d' // sleep 'secondsToSleep' // Print 'testOneway(%d): done sleeping!' with secondsToSleep as '%d' // @param i32 secondsToSleep - the number of seconds to sleep // // Parameters: // - SecondsToSleep func (p *printingHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) { fmt.Printf("testOneway(%d): Sleeping...\n", secondsToSleep) time.Sleep(time.Second * time.Duration(secondsToSleep)) fmt.Printf("testOneway(%d): done sleeping!\n", secondsToSleep) return } thrift-0.19.0/test/go/src/common/clientserver_test.go0000644000000000000000000003060314370300523022634 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package common import ( "context" "errors" "reflect" "sync" "testing" "github.com/golang/mock/gomock" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/test/go/src/gen/thrifttest" ) type test_unit struct { host string port int64 domain_socket string transport string protocol string ssl bool } var units = []test_unit{ {"127.0.0.1", 9095, "", "", "binary", false}, {"127.0.0.1", 9091, "", "", "compact", false}, {"127.0.0.1", 9092, "", "", "binary", true}, {"127.0.0.1", 9093, "", "", "compact", true}, } func TestAllConnection(t *testing.T) { wg := &sync.WaitGroup{} wg.Add(len(units)) for _, unit := range units { go func(u test_unit) { defer wg.Done() doUnit(t, &u) }(unit) } wg.Wait() } func doUnit(t *testing.T, unit *test_unit) { ctrl := gomock.NewController(t) defer ctrl.Finish() handler := NewMockThriftTest(ctrl) processor, serverTransport, transportFactory, protocolFactory, err := GetServerParams(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl, "../../../keys", handler) if err != nil { t.Errorf("GetServerParams failed: %v", err) } server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) if err = server.Listen(); err != nil { t.Errorf("Unable to start server: %v", err) return } go server.Serve() defer server.Stop() client, trans, err := StartClient(unit.host, unit.port, unit.domain_socket, unit.transport, unit.protocol, unit.ssl) if err != nil { t.Errorf("Unable to start client: %v", err) return } defer trans.Close() callEverythingWithMock(t, client, handler) } var rmapmap = map[int32]map[int32]int32{ -4: {-4: -4, -3: -3, -2: -2, -1: -1}, 4: {4: 4, 3: 3, 2: 2, 1: 1}, } var xxs = &thrifttest.Xtruct{ StringThing: "Hello2", ByteThing: 42, I32Thing: 4242, I64Thing: 424242, } var xcept = &thrifttest.Xception{ErrorCode: 1001, Message: "some"} var defaultCtx = context.Background() func callEverythingWithMock(t *testing.T, client *thrifttest.ThriftTestClient, handler *MockThriftTest) { u := thrift.Tuuid{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, } gomock.InOrder( handler.EXPECT().TestVoid(gomock.Any()), handler.EXPECT().TestString(gomock.Any(), "thing").Return("thing", nil), handler.EXPECT().TestBool(gomock.Any(), true).Return(true, nil), handler.EXPECT().TestBool(gomock.Any(), false).Return(false, nil), handler.EXPECT().TestByte(gomock.Any(), int8(42)).Return(int8(42), nil), handler.EXPECT().TestI32(gomock.Any(), int32(4242)).Return(int32(4242), nil), handler.EXPECT().TestI64(gomock.Any(), int64(424242)).Return(int64(424242), nil), // TODO: add TestBinary() handler.EXPECT().TestUuid(gomock.Any(), u).Return(u, nil), handler.EXPECT().TestDouble(gomock.Any(), float64(42.42)).Return(float64(42.42), nil), handler.EXPECT().TestStruct(gomock.Any(), &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}).Return(&thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}, nil), handler.EXPECT().TestNest(gomock.Any(), &thrifttest.Xtruct2{StructThing: &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}}).Return(&thrifttest.Xtruct2{StructThing: &thrifttest.Xtruct{StringThing: "thing", ByteThing: 42, I32Thing: 4242, I64Thing: 424242}}, nil), handler.EXPECT().TestMap(gomock.Any(), map[int32]int32{1: 2, 3: 4, 5: 42}).Return(map[int32]int32{1: 2, 3: 4, 5: 42}, nil), handler.EXPECT().TestStringMap(gomock.Any(), map[string]string{"a": "2", "b": "blah", "some": "thing"}).Return(map[string]string{"a": "2", "b": "blah", "some": "thing"}, nil), handler.EXPECT().TestSet(gomock.Any(), []int32{1, 2, 42}).Return([]int32{1, 2, 42}, nil), handler.EXPECT().TestList(gomock.Any(), []int32{1, 2, 42}).Return([]int32{1, 2, 42}, nil), handler.EXPECT().TestEnum(gomock.Any(), thrifttest.Numberz_TWO).Return(thrifttest.Numberz_TWO, nil), handler.EXPECT().TestTypedef(gomock.Any(), thrifttest.UserId(42)).Return(thrifttest.UserId(42), nil), handler.EXPECT().TestMapMap(gomock.Any(), int32(42)).Return(rmapmap, nil), // TODO: not testing insanity handler.EXPECT().TestMulti(gomock.Any(), int8(42), int32(4242), int64(424242), map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)).Return(xxs, nil), handler.EXPECT().TestException(gomock.Any(), "some").Return(xcept), handler.EXPECT().TestException(gomock.Any(), "TException").Return(errors.New("Just random exception")), handler.EXPECT().TestMultiException(gomock.Any(), "Xception", "ignoreme").Return(nil, &thrifttest.Xception{ErrorCode: 1001, Message: "This is an Xception"}), handler.EXPECT().TestMultiException(gomock.Any(), "Xception2", "ignoreme").Return(nil, &thrifttest.Xception2{ErrorCode: 2002, StructThing: &thrifttest.Xtruct{StringThing: "This is an Xception2"}}), handler.EXPECT().TestOneway(gomock.Any(), int32(2)).Return(nil), handler.EXPECT().TestVoid(gomock.Any()), ) var err error if err = client.TestVoid(defaultCtx); err != nil { t.Errorf("Unexpected error in TestVoid() call: %s", err) } thing, err := client.TestString(defaultCtx, "thing") if err != nil { t.Errorf("Unexpected error in TestString() call: %s", err) } if thing != "thing" { t.Errorf("Unexpected TestString() result, expected 'thing' got '%s' ", thing) } bl, err := client.TestBool(defaultCtx, true) if err != nil { t.Errorf("Unexpected error in TestBool() call: %s", err) } if !bl { t.Errorf("Unexpected TestBool() result expected true, got %v ", bl) } bl, err = client.TestBool(defaultCtx, false) if err != nil { t.Errorf("Unexpected error in TestBool() call: %s", err) } if bl { t.Errorf("Unexpected TestBool() result expected false, got %v ", bl) } b, err := client.TestByte(defaultCtx, 42) if err != nil { t.Errorf("Unexpected error in TestByte() call: %s", err) } if b != 42 { t.Errorf("Unexpected TestByte() result expected 42, got %d ", b) } i32, err := client.TestI32(defaultCtx, 4242) if err != nil { t.Errorf("Unexpected error in TestI32() call: %s", err) } if i32 != 4242 { t.Errorf("Unexpected TestI32() result expected 4242, got %d ", i32) } i64, err := client.TestI64(defaultCtx, 424242) if err != nil { t.Errorf("Unexpected error in TestI64() call: %s", err) } if i64 != 424242 { t.Errorf("Unexpected TestI64() result expected 424242, got %d ", i64) } // TODO: add TestBinary() call uret, err := client.TestUuid(defaultCtx, u) if err != nil { t.Errorf("Unexpected error in TestUuid() call: %s", err) } if uret != u { t.Errorf("Unexpected TestUuid() result expected %v, got %v ", uret, u) } d, err := client.TestDouble(defaultCtx, 42.42) if err != nil { t.Errorf("Unexpected error in TestDouble() call: %s", err) } if d != 42.42 { t.Errorf("Unexpected TestDouble() result expected 42.42, got %f ", d) } xs := thrifttest.NewXtruct() xs.StringThing = "thing" xs.ByteThing = 42 xs.I32Thing = 4242 xs.I64Thing = 424242 xsret, err := client.TestStruct(defaultCtx, xs) if err != nil { t.Errorf("Unexpected error in TestStruct() call: %s", err) } if *xs != *xsret { t.Errorf("Unexpected TestStruct() result expected %#v, got %#v ", xs, xsret) } x2 := thrifttest.NewXtruct2() x2.StructThing = xs x2ret, err := client.TestNest(defaultCtx, x2) if err != nil { t.Errorf("Unexpected error in TestNest() call: %s", err) } if !reflect.DeepEqual(x2, x2ret) { t.Errorf("Unexpected TestNest() result expected %#v, got %#v ", x2, x2ret) } m := map[int32]int32{1: 2, 3: 4, 5: 42} mret, err := client.TestMap(defaultCtx, m) if err != nil { t.Errorf("Unexpected error in TestMap() call: %s", err) } if !reflect.DeepEqual(m, mret) { t.Errorf("Unexpected TestMap() result expected %#v, got %#v ", m, mret) } sm := map[string]string{"a": "2", "b": "blah", "some": "thing"} smret, err := client.TestStringMap(defaultCtx, sm) if err != nil { t.Errorf("Unexpected error in TestStringMap() call: %s", err) } if !reflect.DeepEqual(sm, smret) { t.Errorf("Unexpected TestStringMap() result expected %#v, got %#v ", sm, smret) } s := []int32{1, 2, 42} sret, err := client.TestSet(defaultCtx, s) if err != nil { t.Errorf("Unexpected error in TestSet() call: %s", err) } // Sets can be in any order, but Go slices are ordered, so reflect.DeepEqual won't work. stemp := map[int32]struct{}{} for _, val := range s { stemp[val] = struct{}{} } for _, val := range sret { if _, ok := stemp[val]; !ok { t.Fatalf("Unexpected TestSet() result expected %#v, got %#v ", s, sret) } } l := []int32{1, 2, 42} lret, err := client.TestList(defaultCtx, l) if err != nil { t.Errorf("Unexpected error in TestList() call: %s", err) } if !reflect.DeepEqual(l, lret) { t.Errorf("Unexpected TestList() result expected %#v, got %#v ", l, lret) } eret, err := client.TestEnum(defaultCtx, thrifttest.Numberz_TWO) if err != nil { t.Errorf("Unexpected error in TestEnum() call: %s", err) } if eret != thrifttest.Numberz_TWO { t.Errorf("Unexpected TestEnum() result expected %#v, got %#v ", thrifttest.Numberz_TWO, eret) } tret, err := client.TestTypedef(defaultCtx, thrifttest.UserId(42)) if err != nil { t.Errorf("Unexpected error in TestTypedef() call: %s", err) } if tret != thrifttest.UserId(42) { t.Errorf("Unexpected TestTypedef() result expected %#v, got %#v ", thrifttest.UserId(42), tret) } mapmap, err := client.TestMapMap(defaultCtx, 42) if err != nil { t.Errorf("Unexpected error in TestMapmap() call: %s", err) } if !reflect.DeepEqual(mapmap, rmapmap) { t.Errorf("Unexpected TestMapmap() result expected %#v, got %#v ", rmapmap, mapmap) } xxsret, err := client.TestMulti(defaultCtx, 42, 4242, 424242, map[int16]string{1: "blah", 2: "thing"}, thrifttest.Numberz_EIGHT, thrifttest.UserId(24)) if err != nil { t.Errorf("Unexpected error in TestMulti() call: %s", err) } if !reflect.DeepEqual(xxs, xxsret) { t.Errorf("Unexpected TestMulti() result expected %#v, got %#v ", xxs, xxsret) } err = client.TestException(defaultCtx, "some") if err == nil { t.Errorf("Expecting exception in TestException() call") } if !reflect.DeepEqual(err, xcept) { t.Errorf("Unexpected TestException() result expected %#v, got %#v ", xcept, err) } // TODO: connection is being closed on this err = client.TestException(defaultCtx, "TException") if err == nil { t.Error("expected exception got nil") } else if tex, ok := err.(thrift.TApplicationException); !ok { t.Errorf("Unexpected TestException() result expected ApplicationError, got %T ", err) } else if tex.TypeId() != thrift.INTERNAL_ERROR { t.Errorf("expected internal_error got %v", tex.TypeId()) } ign, err := client.TestMultiException(defaultCtx, "Xception", "ignoreme") if ign != nil || err == nil { t.Errorf("Expecting exception in TestMultiException() call") } if !reflect.DeepEqual(err, &thrifttest.Xception{ErrorCode: 1001, Message: "This is an Xception"}) { t.Errorf("Unexpected TestMultiException() %#v ", err) } ign, err = client.TestMultiException(defaultCtx, "Xception2", "ignoreme") if ign != nil || err == nil { t.Errorf("Expecting exception in TestMultiException() call") } expecting := &thrifttest.Xception2{ErrorCode: 2002, StructThing: &thrifttest.Xtruct{StringThing: "This is an Xception2"}} if !reflect.DeepEqual(err, expecting) { t.Errorf("Unexpected TestMultiException() %#v ", err) } err = client.TestOneway(defaultCtx, 2) if err != nil { t.Errorf("Unexpected error in TestOneway() call: %s", err) } //Make sure the connection still alive if err = client.TestVoid(defaultCtx); err != nil { t.Errorf("Unexpected error in TestVoid() call: %s", err) } } thrift-0.19.0/test/go/src/common/client.go0000644000000000000000000000660314303740367020363 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package common import ( "compress/zlib" "crypto/tls" "flag" "fmt" "net/http" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/test/go/src/gen/thrifttest" ) var debugClientProtocol bool func init() { flag.BoolVar(&debugClientProtocol, "debug_client_protocol", false, "turn client protocol trace on") } func StartClient( host string, port int64, domain_socket string, transport string, protocol string, ssl bool, ) (client *thrifttest.ThriftTestClient, trans thrift.TTransport, err error) { hostPort := fmt.Sprintf("%s:%d", host, port) cfg := &thrift.TConfiguration{ TLSConfig: &tls.Config{ InsecureSkipVerify: true, }, } var protocolFactory thrift.TProtocolFactory switch protocol { case "compact": protocolFactory = thrift.NewTCompactProtocolFactoryConf(cfg) case "simplejson": protocolFactory = thrift.NewTSimpleJSONProtocolFactoryConf(cfg) case "json": protocolFactory = thrift.NewTJSONProtocolFactory() case "binary": protocolFactory = thrift.NewTBinaryProtocolFactoryConf(cfg) case "header": protocolFactory = thrift.NewTHeaderProtocolFactoryConf(cfg) default: return nil, nil, fmt.Errorf("invalid protocol specified %s", protocol) } if debugClientProtocol { protocolFactory = thrift.NewTDebugProtocolFactoryWithLogger(protocolFactory, "client:", thrift.StdLogger(nil)) } if ssl { trans = thrift.NewTSSLSocketConf(hostPort, cfg) } else { if domain_socket != "" { trans = thrift.NewTSocketConf(domain_socket, nil) } else { trans = thrift.NewTSocketConf(hostPort, nil) } } if err != nil { return nil, nil, err } switch transport { case "http": if ssl { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: tr} trans, err = thrift.NewTHttpClientWithOptions(fmt.Sprintf("https://%s/", hostPort), thrift.THttpClientOptions{Client: client}) fmt.Println(hostPort) } else { trans, err = thrift.NewTHttpClient(fmt.Sprintf("http://%s/", hostPort)) } case "framed": trans = thrift.NewTFramedTransportConf(trans, cfg) case "buffered": trans = thrift.NewTBufferedTransport(trans, 8192) case "zlib": trans, err = thrift.NewTZlibTransport(trans, zlib.BestCompression) case "": // Do nothing default: return nil, nil, fmt.Errorf("invalid transport specified %s", transport) } if err != nil { return nil, nil, err } if err = trans.Open(); err != nil { return nil, nil, err } iprot := protocolFactory.GetProtocol(trans) oprot := protocolFactory.GetProtocol(trans) client = thrifttest.NewThriftTestClient(thrift.NewTStandardClient(iprot, oprot)) return } thrift-0.19.0/test/go/Makefile.in0000644000000000000000000004502014472652520016540 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/go ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ BUILT_SOURCES = gopath GOBUILDEXTRA = -buildvcs=false THRIFTCMD = $(THRIFT) -out src/gen --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/test/go/src/gen/$(COMPILER_EXTRAFLAG) THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift EXTRA_DIST = \ src/bin \ src/common \ genmock.sh all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/go/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/go/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check install install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile precross: bin/testclient bin/testserver ThriftTest.thrift: $(THRIFTTEST) grep -v list.*map.*list.*map $(THRIFTTEST) > ThriftTest.thrift .PHONY: gopath # Thrift for GO has problems with complex map keys: THRIFT-2063 gopath: $(THRIFT) ThriftTest.thrift mkdir -p src/gen $(THRIFTCMD) ThriftTest.thrift $(THRIFTCMD) ../StressTest.thrift $(THRIFTCMD) ../ConstantsDemo.thrift touch gopath bin/testclient: gopath $(GO) build $(GOBUILDEXTRA) -o bin/testclient ./src/bin/testclient bin/testserver: gopath $(GO) build $(GOBUILDEXTRA) -o bin/testserver ./src/bin/testserver bin/stress: gopath $(GO) build $(GOBUILDEXTRA) -o bin/stress ./src/bin/stress clean-local: $(RM) -r src/gen src/github.com/golang src/thrift bin pkg gopath ThriftTest.thrift check_PROGRAMS: bin/testclient bin/testserver bin/stress check: gopath genmock $(GO) test -v ./src/common/... $(GO) test -v ./src/gen/... genmock: gopath sh genmock.sh # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/go/genmock.sh0000644000000000000000000000045214370300523016440 0ustar00rootroot00000000000000#!/bin/sh set -e export GOPATH=$(mktemp -d -t gopath-XXXXXXXXXX) go install github.com/golang/mock/mockgen `go env GOPATH`/bin/mockgen -destination=src/common/mock_handler.go -package=common github.com/apache/thrift/test/go/src/gen/thrifttest ThriftTest chmod a+w -R $GOPATH && rm -Rf $GOPATH thrift-0.19.0/test/py.tornado/0000777000000000000000000000000014472652607016174 5ustar00rootroot00000000000000thrift-0.19.0/test/py.tornado/Makefile.am0000644000000000000000000000257514370300523020215 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = $(top_srcdir)/compiler/cpp/thrift thrift_gen: ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen py:tornado ../v0.16/ThriftTest.thrift $(THRIFT) --gen py:tornado ../SmallTest.thrift check: thrift_gen ./test_suite.py clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ thrift-0.19.0/test/py.tornado/setup.cfg0000644000000000000000000000005514303740367020003 0ustar00rootroot00000000000000[flake8] ignore = E402 max-line-length = 100 thrift-0.19.0/test/py.tornado/Makefile0000644000000000000000000004435414472652607017642 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/py.tornado/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/py.tornado ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = $(top_srcdir)/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/py.tornado abs_srcdir = /thrift/src/test/py.tornado abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/py.tornado/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/py.tornado/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile thrift_gen: ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen py:tornado ../v0.16/ThriftTest.thrift $(THRIFT) --gen py:tornado ../SmallTest.thrift check: thrift_gen ./test_suite.py clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/py.tornado/test_suite.py0000777000000000000000000001427714062750227020744 0ustar00rootroot00000000000000#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import datetime import glob import os import sys import time import unittest basepath = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(0, basepath + '/gen-py.tornado') sys.path.insert(0, glob.glob(os.path.join(basepath, '../../lib/py/build/lib*'))[0]) try: __import__('tornado') except ImportError: print("module `tornado` not found, skipping test") sys.exit(0) from tornado import gen from tornado.testing import AsyncTestCase, get_unused_port, gen_test from thrift import TTornado from thrift.Thrift import TApplicationException from thrift.protocol import TBinaryProtocol from ThriftTest import ThriftTest from ThriftTest.ttypes import Xception, Xtruct class TestHandler(object): def __init__(self, test_instance): self.test_instance = test_instance def testVoid(self): pass def testString(self, s): if s == 'unexpected_error': raise Exception(s) return s def testByte(self, b): return b def testI16(self, i16): return i16 def testI32(self, i32): return i32 def testI64(self, i64): return i64 def testDouble(self, dub): return dub def testBinary(self, thing): return thing def testStruct(self, thing): return thing def testException(self, s): if s == 'Xception': raise Xception(1001, s) elif s == 'throw_undeclared': raise ValueError('testing undeclared exception') def testOneway(self, seconds): start = time.time() def fire_oneway(): end = time.time() self.test_instance.stop((start, end, seconds)) self.test_instance.io_loop.add_timeout( datetime.timedelta(seconds=seconds), fire_oneway) raise Exception('testing exception in oneway method') def testNest(self, thing): return thing @gen.coroutine def testMap(self, thing): yield gen.moment raise gen.Return(thing) def testSet(self, thing): return thing def testList(self, thing): return thing def testEnum(self, thing): return thing def testTypedef(self, thing): return thing class ThriftTestCase(AsyncTestCase): def setUp(self): super(ThriftTestCase, self).setUp() self.port = get_unused_port() # server self.handler = TestHandler(self) self.processor = ThriftTest.Processor(self.handler) self.pfactory = TBinaryProtocol.TBinaryProtocolFactory() self.server = TTornado.TTornadoServer(self.processor, self.pfactory, io_loop=self.io_loop) self.server.bind(self.port) self.server.start(1) # client transport = TTornado.TTornadoStreamTransport('localhost', self.port, io_loop=self.io_loop) pfactory = TBinaryProtocol.TBinaryProtocolFactory() self.io_loop.run_sync(transport.open) self.client = ThriftTest.Client(transport, pfactory) @gen_test def test_void(self): v = yield self.client.testVoid() self.assertEqual(v, None) @gen_test def test_string(self): v = yield self.client.testString('Python') self.assertEqual(v, 'Python') @gen_test def test_byte(self): v = yield self.client.testByte(63) self.assertEqual(v, 63) @gen_test def test_i32(self): v = yield self.client.testI32(-1) self.assertEqual(v, -1) v = yield self.client.testI32(0) self.assertEqual(v, 0) @gen_test def test_i64(self): v = yield self.client.testI64(-34359738368) self.assertEqual(v, -34359738368) @gen_test def test_double(self): v = yield self.client.testDouble(-5.235098235) self.assertEqual(v, -5.235098235) @gen_test def test_struct(self): x = Xtruct() x.string_thing = "Zero" x.byte_thing = 1 x.i32_thing = -3 x.i64_thing = -5 y = yield self.client.testStruct(x) self.assertEqual(y.string_thing, "Zero") self.assertEqual(y.byte_thing, 1) self.assertEqual(y.i32_thing, -3) self.assertEqual(y.i64_thing, -5) @gen_test def test_oneway(self): self.client.testOneway(1) v = yield self.client.testI32(-1) self.assertEqual(v, -1) @gen_test def test_map(self): """ TestHandler.testMap is a coroutine, this test checks if gen.Return() from a coroutine works. """ expected = {1: 1} res = yield self.client.testMap(expected) self.assertEqual(res, expected) @gen_test def test_exception(self): try: yield self.client.testException('Xception') except Xception as ex: self.assertEqual(ex.errorCode, 1001) self.assertEqual(ex.message, 'Xception') else: self.fail("should have gotten exception") try: yield self.client.testException('throw_undeclared') except TApplicationException: pass else: self.fail("should have gotten exception") yield self.client.testException('Safe') def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(ThriftTestCase)) return suite if __name__ == '__main__': unittest.TestProgram(defaultTest='suite', testRunner=unittest.TextTestRunner(verbosity=1)) thrift-0.19.0/test/py.tornado/Makefile.in0000644000000000000000000004347114472652521020241 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/py.tornado ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_srcdir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/py.tornado/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/py.tornado/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile thrift_gen: ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen py:tornado ../v0.16/ThriftTest.thrift $(THRIFT) --gen py:tornado ../SmallTest.thrift check: thrift_gen ./test_suite.py clean-local: $(RM) -r build find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r gen-py*/ dist-hook: find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf $(RM) -r $(distdir)/gen-py*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/keys/0000777000000000000000000000000014303740367015044 5ustar00rootroot00000000000000thrift-0.19.0/test/keys/client.pem0000644000000000000000000001003514303740367017020 0ustar00rootroot00000000000000Bag Attributes localKeyID: 16 42 EA 1B 7C AC BD 29 96 5A A8 B6 3C AB 85 E3 7D 12 C3 D4 subject=CN = localhost, emailAddress = dev@thrift.apache.org, OU = Apache Thrift, O = The Apache Software Foundation, L = Forest Hill, ST = Maryland, C = US issuer=CN = localhost, emailAddress = dev@thrift.apache.org, OU = Apache Thrift, O = The Apache Software Foundation, L = Forest Hill, ST = Maryland, C = US -----BEGIN CERTIFICATE----- MIIE2DCCAsACAQEwDQYJKoZIhvcNAQELBQAwgbExEjAQBgNVBAMMCWxvY2FsaG9z dDEkMCIGCSqGSIb3DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMRYwFAYDVQQL DA1BcGFjaGUgVGhyaWZ0MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZv dW5kYXRpb24xFDASBgNVBAcMC0ZvcmVzdCBIaWxsMREwDwYDVQQIDAhNYXJ5bGFu ZDELMAkGA1UEBhMCVVMwHhcNMjIwNjMwMjIzNzMxWhcNMzAwOTE2MjIzNzMxWjCB sTESMBAGA1UEAwwJbG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0 LmFwYWNoZS5vcmcxFjAUBgNVBAsMDUFwYWNoZSBUaHJpZnQxJzAlBgNVBAoMHlRo ZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbjEUMBIGA1UEBwwLRm9yZXN0IEhp bGwxETAPBgNVBAgMCE1hcnlsYW5kMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMkGl9ZGVq/mTrcojrq7eqZTww1gmgOPNWN1QNzv i+cPI8Egbik04n/AFWvgtnvKKnKQfOLkBHJHyTdXmPqvdU9w8Zd9dvXk75mBvbtx yse6UZCxZnXrqv5YfMGb2BEvcsL5I5s6d3gL4eNObYzFD7vUjAbpamUSE7NOeMn7 qO0rPIcODDXL+Okr9/TBcO/XvRSUK0exsX03FC07gtTddV9lEYCkJvQMCCQmFdQ5 al7Vz4iLleG5hsCwz/W5zHcsqVtzm8CEQzr00AoR8Ar/WkGh1ibmissi5Bo2DcvR Ko3pvDVOAY+gj9Ypxe2z7MImn1T7ZVdr0JXUu9jmMgKMQz8CAwEAATANBgkqhkiG 9w0BAQsFAAOCAgEAH3QwBNbb2IP+ozcM5w4WppG7W/ha0WUcEKgf8Ay7w4/+X79Y Z7mxltoCz5Bc54EMXDaoTg5PbwPSmTNDqoFSRf07Fhp8IG5n19CvrTCMFcM8BbDx g5CZ6W1WoHpCW6/zNlflsSVFbGSrkwzmpgnn3+EJcVWzMDcQXufpkefbH2x7bHC/ 0JsfEYh5iPyJeDWx0CyiyoqfRx08cDuB/OLZgq63dkDNnd4zqDTT8zLT6zMTq1Ka pApb+5o0rapgHQP5+O3QAZrfnWLYXOPk17yQTekvwVpiSzwdPlOija5X+BLrLyNu EEYlR7Vz2qj/DAUN9vhCIdF4Bk8Yfk9txH5oJUmC0c2bfUkrCJgfbyK1GL00BkON aso8whDf8LF5BAl/ooofzvZXt+bw4Sp+LuX+OAcJUlqeK7IUdHQqnhhw5FOfenVO Z7MkMt2qtm3BlPzMWlZoeLNrkx4BzsBElFJ0Ds37uLk+LIg3whg+MYMFJPwXqUhs 6Ss76/cu/AhoHoX8k5wT5eNpzyWL8hNyDSosGDAgejjYFBXMlNzFYvG5zVE0EP7C i78cIdgSARKocOOeFpA3GEJL+ISi0g1ut8A1/kxgFp5dxGjfOAGHeDeaVWhWuhjz m7CjPwlfAvIBJJlC96MhPakY6tbyA0hW0/GiOfaoanJvVdWJF7lEdKle1Zs= -----END CERTIFICATE----- Bag Attributes localKeyID: 16 42 EA 1B 7C AC BD 29 96 5A A8 B6 3C AB 85 E3 7D 12 C3 D4 Key Attributes: -----BEGIN ENCRYPTED PRIVATE KEY----- MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIXssR4DibuUICAggA MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECG0hY3ghCtwkBIIEyLAZKLA15mz3 ig2qipY2rD8xMs5/kP0bixjxwzpWsTAjkUTZq6UYWgQxE2CnAAysCUveftySMg5A Fs0gvi6pTh7yGheqpJf7+tEjs7qhaIHdT39gS6d9A2+rAye0/FybW/3zGInQVQmb 47SF9lq93gevzR3nBFF6RWSeX3jCwhp6HpbuI0nt1XeJbmEW8ol+RqFHuzclj6UL jXIgNBayW89HfSzIRCUDTlG9MTPIE+rdx5FyRVFgw5Z1lYJbm5rBEY7tQU6Ut7Kt Is4KRTs5hAQkfe0K0i0hZn7Don5Go4EIBQQ4IZIaOm0F3SWpe9AuZi3NtwiBOTsn ObKTZGI7v+j6IVwVRSTy61u1EiRvNzUBnoItuOZXbCMe/1VdqET1Gc909rSdkeYg dEQ3XmGN09+0OKEcspEdtRC22T44LATm5RHiA3wkIqc7hI9IZ4tD0P5OzOrWkMLC GXUmkWUodzLwQAASwUNrez4LVI4fA4mZNTdT0Kgo9H/xRq95I32E6pkP5GX+IklA f7Yj5pfQHeL2ZygerApgaNwTvUhT+GyD6Ukd7eB21r599bn+FsTIYqkbBvE+Nle4 ZQfZ31lzUxkfkxfXMSbFufupAe6McfU3RdbPZL/4YEW/ukn96olThgJADSmtjxZI +5EifMdjmZlPsd6xmcSFIe0GgqYegpprj7niT0HUKH+1+1T7EmwSXaN18vDFtNlz sVmM6ElSvdRR0VKlzGQ5E9JkeHN5ELqtZGPG0OeblCfu40t84t5N+Fyi2Ykdp7Yx 6AkBGuXNVnfCFPRgumtFTtUdSc/BdEWLnvE3spfolYpIfOsrw3bMjlr9sm5JpCfX zZxlxjiSXjNrIIaG7VFUdBXsT1ctL/Oa6JbIzCW7nnPTfCHmlqsOczpF6pXP+gPR tFy2nlk6dNPPyiEhiOdv8c9YlwmRi477bnz++jYJATFNbrtLQdN/jN3Txu6gDEcH +xvgibcVA7LG8U9T/olOqHdboOIcvOnHdBeOPZVmBQi+4+FPet42fzeP7d+wARED Wou/+EXCqMDW8bhukkac7/1CBZmvnC3mlNtmjAEbi5NT0vPP0sv5ff5zr9KJZnFD 1ltO/Qk5GPuxm/2jW05WrUWv6Po0k25rlAKGnT54VoA+6Sl2288NgeZ9ZPC5WByU BF68xMiyeiAyrkRg8sV7raxF6GX3pK+iNcgh63TI8Mko22tHyXsVB3z7mfNnpM+W aSiHrXKQkX9vxjLj4GxkMTfVT9zZfMOMKkKS3EYVVulixJ7NYafw+nGv2018CZiA FeTb0dBh1ATMhoxwpb5kdmzAjnf67wQejQhrI0mBPhn2gmO2ilQdRWydG6sXEi0s dsBXyfSSE3pdC9MD7j98tG/KeXErjWlyfx3FP5YCTbhUKqzd8grwwtBp3Vb1iP8X t9N2YaQq5djme+afg2A2iDahSgXCNuB0RV+roqq0Rroehgytt7QSMkva+AenX6t8 lJrAivnHAz7464eD8vzRPRUfxwgX7A1zyE0wV3n45NN9Fv0rrVTo1vaAeakurGWw H5vqFcd2WVN/iKMzQ6S1IUDxUneoyf9qmgsGu4XxAtsOe2myaHaPylwS7fujQaz9 bk0ymLXuco7mflouywgROQ== -----END ENCRYPTED PRIVATE KEY----- thrift-0.19.0/test/keys/client_v3.key0000644000000000000000000000321714303740367017443 0ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAsqPCAkuOxPmJ773z1KWaJyYWswj7zTVITm/uF0pIMSTzJh13 6Y7qJDMfKHZuO0EEEuvWgjxuDQCoi9G8lIyq3TV04scUmC0eQpZDizz3XRqW7F2n Mzapyp9I2dG0mRwVTb/iWlSIvGfIiWQZaX32P9V7/0CWH3zYBk7Sve9N5rymcjMQ FR7aNlNpU4tw2Oa8Jz8d4CjsljeZQ8K2fE+R9fUN+aq0DQlvhiBuKHHUCpypNneL dc5XB6dUUAsTlq8OjbWLbUqAiK3gdrsIgfx9dxKcBoQxXrkjKM3/VAM2PNFVZ4nz 6Klxt5n0QlZBsq4EQmcUxUr7JoVBFkeaJABiQwIDAQABAoIBAQCv5F/1xJHJzu6L OVxpJ7mWDIHTPOg50NnmKX2kPwbAJOKox+E2/fn7NL7cJ2g4PbcWLlKjH384nEpY iWYGWk8uyiDR3jWf9OTTqYLOCXSCnti12Sz1V0BtetLPbhVFoIo1aNcmHBAaepHQ /dersFQT3E9gMCbg0BsgcuI8E/F/WuFOI0LT0KikYH3r7QUE8yxoL37c+02X1DuP mpMhYSI3fUy33ix0Nkoeuy/br0j+5tRiKvSG6VAbGeFFRU6QZAyEhnpIZf8MjwcX DH2O5xuA6TnFosBsMlvVhrjqPUB/j/aGMb2+kyBl2JUEvwaeuatYdwdoOdARJ7gI L80776sJAoGBAOFr1//7VAF11qNYRHSc+y9wUTUTv5UXTNSuCBMRTQl9kgJSBFO3 SqmkhwrvBNKlvuGQGuYOHo0nQgDClegyf6FcOVvfWsSwDQdjOyw6PKgDL6vOZaAe Jrmp5Fs2n93GornHI87YPm2Gj274654UcOIG1eWzaOIyuEN7cqrUdY7/AoGBAMrf VwY/94YJFC9GCRzoeiAxserDqsdSquHlMA+TgZCQmsq7GPvVBa99gFYX5v6RkMh9 rEDaSb51ECMUo1Yot+UYjyRP1i3goDr/nAqGQxFEJm8JGhibDIfUWSdRh0cQ8OfT /M7FqhhYWCTCY3L4H2k+xGWmUsfpC+bijjvHmjC9AoGBAN/rDGkO8udwcoFXkMh1 l14MJ96de1VSC9PH++VU7j1bKsp7RikSjWvuLubBfvzv/6h4SP/1TovQT1QJ9nbs krNqtN96AuQWLRsFiyXnw5DxeU0kfPaMfNM428lvfWYDhmkcU4mIbJrHa3tEcGha zbb4K0k86hanYzpFSiY/XXdpAoGAaHJV7ozOVf6kmrYXCQATqDGNpQ16BkbkXYrO lKZfxVr9prRu53DEDZaylSCXN6cgAGjbX0RDRUAlv7nnYftyugtL3ukPnu0P8XAa GT0ImIIau33XJqXk7KWCBQEvgYISVXjJpncT3JbXQo2l/9II8flzydW4tt2f2A36 JoLcOo0CgYEAiDBPwbiwPf2paFan/Av52KDB6Lsq4EYYLeqTApACqkQLw9lDsCml dLD3t/ElCVTwhgRYFlo0rgC33TGGz7Kq+twcgZJ+7O7x+qa3YWTqtAYadyGZhl/p xGYwSQcKFWqu7TLrW9WK+SnV2Ku2G1IySlFUK4++9nNC2jRX13LaPMo= -----END RSA PRIVATE KEY----- thrift-0.19.0/test/keys/client.crt0000644000000000000000000000331414303740367017031 0ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIE2DCCAsACAQEwDQYJKoZIhvcNAQELBQAwgbExEjAQBgNVBAMMCWxvY2FsaG9z dDEkMCIGCSqGSIb3DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMRYwFAYDVQQL DA1BcGFjaGUgVGhyaWZ0MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZv dW5kYXRpb24xFDASBgNVBAcMC0ZvcmVzdCBIaWxsMREwDwYDVQQIDAhNYXJ5bGFu ZDELMAkGA1UEBhMCVVMwHhcNMjIwNjMwMjIzNzMxWhcNMzAwOTE2MjIzNzMxWjCB sTESMBAGA1UEAwwJbG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0 LmFwYWNoZS5vcmcxFjAUBgNVBAsMDUFwYWNoZSBUaHJpZnQxJzAlBgNVBAoMHlRo ZSBBcGFjaGUgU29mdHdhcmUgRm91bmRhdGlvbjEUMBIGA1UEBwwLRm9yZXN0IEhp bGwxETAPBgNVBAgMCE1hcnlsYW5kMQswCQYDVQQGEwJVUzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAMkGl9ZGVq/mTrcojrq7eqZTww1gmgOPNWN1QNzv i+cPI8Egbik04n/AFWvgtnvKKnKQfOLkBHJHyTdXmPqvdU9w8Zd9dvXk75mBvbtx yse6UZCxZnXrqv5YfMGb2BEvcsL5I5s6d3gL4eNObYzFD7vUjAbpamUSE7NOeMn7 qO0rPIcODDXL+Okr9/TBcO/XvRSUK0exsX03FC07gtTddV9lEYCkJvQMCCQmFdQ5 al7Vz4iLleG5hsCwz/W5zHcsqVtzm8CEQzr00AoR8Ar/WkGh1ibmissi5Bo2DcvR Ko3pvDVOAY+gj9Ypxe2z7MImn1T7ZVdr0JXUu9jmMgKMQz8CAwEAATANBgkqhkiG 9w0BAQsFAAOCAgEAH3QwBNbb2IP+ozcM5w4WppG7W/ha0WUcEKgf8Ay7w4/+X79Y Z7mxltoCz5Bc54EMXDaoTg5PbwPSmTNDqoFSRf07Fhp8IG5n19CvrTCMFcM8BbDx g5CZ6W1WoHpCW6/zNlflsSVFbGSrkwzmpgnn3+EJcVWzMDcQXufpkefbH2x7bHC/ 0JsfEYh5iPyJeDWx0CyiyoqfRx08cDuB/OLZgq63dkDNnd4zqDTT8zLT6zMTq1Ka pApb+5o0rapgHQP5+O3QAZrfnWLYXOPk17yQTekvwVpiSzwdPlOija5X+BLrLyNu EEYlR7Vz2qj/DAUN9vhCIdF4Bk8Yfk9txH5oJUmC0c2bfUkrCJgfbyK1GL00BkON aso8whDf8LF5BAl/ooofzvZXt+bw4Sp+LuX+OAcJUlqeK7IUdHQqnhhw5FOfenVO Z7MkMt2qtm3BlPzMWlZoeLNrkx4BzsBElFJ0Ds37uLk+LIg3whg+MYMFJPwXqUhs 6Ss76/cu/AhoHoX8k5wT5eNpzyWL8hNyDSosGDAgejjYFBXMlNzFYvG5zVE0EP7C i78cIdgSARKocOOeFpA3GEJL+ISi0g1ut8A1/kxgFp5dxGjfOAGHeDeaVWhWuhjz m7CjPwlfAvIBJJlC96MhPakY6tbyA0hW0/GiOfaoanJvVdWJF7lEdKle1Zs= -----END CERTIFICATE----- thrift-0.19.0/test/keys/client.p120000644000000000000000000000543514303740367016651 0ustar00rootroot000000000000000‚ 0‚ ß *†H†÷  ‚ Ђ Ì0‚ È0‚ *†H†÷  ‚p0‚l0‚e *†H†÷ 0 *†H†÷  0æÜñ­¤#9€‚8µèùMš¤ðjËœXlír‰6Äà>w]À‚xŠ’I\k„ø 5 $GköÆoà2Nèy&é#ùé«aáÑ»Êüaª P®á”<,I}Ê=g`þY‚§Ý¨®tma+»º{œ†³”—»“Ÿ¦| h—"T@ .‹Qº’]DLàP]^ÈoòT€ª´!£,Þ.£‚fÏ~ÖgÖŽkú0¹Š¦ª9$NQ•^¾ðÔˆrÿ hC9ãúühÉŽ¥Œ º:Ÿ×§e¼ðk»g¿©2jÕWkEzîeöˆiTd^W§-»®‰|:±yZ0±;ã7Úk\þZÒŠ˜3_ ŒL<°6³¨ …%1šmÀdóßG>ZÊ14á=#Ü*æ–³ä`ôASÌŸosk–B‡·gV%XD¶yÂÊJ*Òì ¹ô¢Ééû\üãR‘“ˆXö:ün‰Ç]ÿ_íCËU(d§ï,°J´Œñ©x‹d£.[¦rËpžÃ$>òO'jx#óéþWê£9# ÷¶ðÃýRu‡.tØ>˜ ©ÜŠmé¸ü¨1ª2ÚÑ¢x¤0hš•WOwE/¥8Œ„U †òÙ¡/dš–ô¼É¡³¬Öг\—Oäµÿû£Ÿ^~î…z<àzî-å?®Ç!›gÙ¹#¶#¨by†öxékÝFᳪˆ !íÞÈĵ«5g{¬„´F‚ißàðA•†§ú¹Î·ïiÎÀ²ˆÔí?å ðßúÇ?` ¸—q»’ĹIÓ®júŸGgpÇ…Ÿl+UÔ)ª€þ÷=›ðY² QQÅëÄÌNµ£Ü¯Óúèáô=ŠÄ#ØÒÑ|ÂaƒÐ¼ 7TcxÓr¦¼‘Í<|® ]>eÓ)±iÆëî°"ç|¤%R¢ä§?u?Ã%ËckxóÐô’ÆXm[·Ë}ÄɲFy5R¶÷ï¨NŸ‰•WÀ«_a'X 0 UÖ³=òöaz|³óÙ3›írÖ¸%sÀêlû©3¦øŠJf^f*ÊËdÄ^’Ûôí1”‰–•>ỳ”Ó½‹àäPÈßKÂÙŒd,µŸ" ƒé.Ò¬àŽÊž_VTϹƒ_IÞêÕ¶Ù{: Ðì™8«;Î$[<&ý@¦fVì˜È„Ô<Í*GÜkùõnc¡Á¸è¤B5Jöåà’øñÃbªOä^zئ¬_¯`d¥«"äõ™=rgJá8›£š5T®ËÌ3cq² «LÚ¡ªrlòŽI¤J±8é¤Ç¶ð"úÀqÑáÃùÑ2x$™/«2&4±r U+àPKŸ¦…ûPâIWßK%qaž²™)Sºª R °J_0*·_µGAûÅš~ÆÉöïä‡C“’ÙË!7aÙÒ» ì)»É=2@§Å%È´`}à|¦YÞò2y€Éì¸vÙ‹Ò{/}#®¿+5ÿÒ‰Dzfó¦Ñ"¨rí(BÝ(äå Òÿh-R¦sÕd Ä5­!A$ªàðéÇ#õ¸÷™ºxD7-\=¨öí0îm®t7`œéÔºëkn2EÌ“Úüª@^]I$™wo#-²mâ±ö ‡x_íÌàÄè“tWÔYýO˜7ˆçš[}ÊÈþÆ”Ç ­Ïƒ"D® >‡2Jžé†˜ù¡P“!X!bwN­üUZÖ M®fÙ0‚A *†H†÷  ‚2‚.0‚*0‚& *†H†÷   ‚î0‚ê0 *†H†÷  0Û¡s#uæI÷‚È· ‘8~ðC÷.“R@¯kŠ‘—¨YØõúó¤—çI‰p&Œ¢®^,¹A¹Y0É`Qy‚iÕDé¦É‡ï¨è+Fpò¼*Û5ÆÒÜ3 —â®áu@°Š’‚EB·L‘T jä3ûÔ*WŽª8+í€kɃ¨ïæº)#š'"ÅiÄ•3ˆÖ‡MÖw‚uΧšcå²voÜŒ™©1wÒ1¨u VžÃ>ë{@xnÒbamL±Ï%"ךøEåAîžJà ,%º‚3ØõiÑ,m\YúºrkB¸ú¦lÕWk2š@/ULem-µFɤœiDÿHò(0å^­ß3 #µ*‰3ÁNvC¤o~ØD‰Z9ò™JuåÈÊV¿ ÏòE[<oµ½7™‚â]àçž"(qæ-6–ߤhä%¢HöÆ&‹36jpc±úmN–T;je›~ÝÌRíJ2ócCj3Ž« $jC•¾A ‘Ú58‘ÂÃ.‘ÍK@k|t¾Ã?„ÚÛ)!-!Zn&»}mþ×F‡QÍÕ6é/¼¦§dÜÿŒµ¹QµœPìwò);%@jPq[ÁÉï7Æç"ÓõxfPÇIç¶Ø©w¼§ ÅÞ'jé“×6'ݸ?ò Ê`[XO—A>5m½‡$œAbn1DzÏFð˜`HÎW+Ø}ÚÜòZ6$…÷6þq ª³¾v³ÖÂIìƒóüEÆËƒsT|r M ì†) g¾§Š¼—C T:¿»·Z££¼â‹Î%(¥å¨¬àÇë|gñ@¬t ¬z :‚£&wi…â5t*ŽÝ(œ¥?Ú• ™ˆT4Å[€W¤]€TìLý¼ùŸl·V*ˆ6h7¤ä³ƒë{çÏcÕǪõl#®.uëâ"3Rw g1„…¨¸!´°j$’gÄç(ETA†aŸ¿¥NðW"¬ˆ*ınѪMl÷ŸÐÅ/n2’¤{ψì°@šƒÅ£=‡S±j .¤;Þ覑œG@_äèè\¸1Åqï+ó_V\4ƒýŽ †¨#ÉQëØkùj?ê“ã#¤šËwþç b)ç6AOàÉ—,Èáà|Õ×2Â󤢮”°Ç\ñü™¡˜ºÊ"ˆ¤€”DZÁíç&¦sõPúmé:i¡fß«¦†é]AÐ1;N4öEg…§¢ÅÀúDå#x‘~‚µÚ[1Ç|±×ë° âNtŸúà«c†¾T-}ë؉—ÒdˆUîœêl÷ŽÖ]âÛ@‰£{UÐŽt—Ô·£r(¶sƾ¯T[¿FK¬±ó^Ä|3À¾Ãë.åÑ-C«K#š? F8Y®Î,ŸÀ×V3a’ךÂëéêøD³Tf`‹ýYQÌ bïÏ×Åà-OF›`îÁe³öÂp ‡’þÑ)-XbBÈÆ³u¾d=s$¤ANW‰i\D¢øüÁÊ›ü†ñ|»Y€‰9¼zùqœË…ŃäR ÞW<Öô‹•ÂÔ]<ï†AÂℱôÚác³_í§DúÁÃoeE…˜ƒí X¸rÚ—¹ŸôˆÌøvReÐö~T‰…P;IþÉw³Qc91%0# *†H†÷  1Bê|¬½)–Z¨¶<«…ã}ÃÔ010!0 +üÍ¿’§îèä2êB'ì!(ý'²¥‹Ï¤Àthrift-0.19.0/test/keys/README.md0000644000000000000000000000603014303740367016316 0ustar00rootroot00000000000000# Test Keys and Certificates This folder is dedicated to test keys and certificates provided in multiple formats. Primary use are unit test suites and cross language tests. test/keys **The files in this directory must never be used on production systems.** ## SSL Keys and Certificates ## create certificates we use the following parameters for test key and certificate creation C=US, ST=Maryland, L=Forest Hill, O=The Apache Software Foundation, OU=Apache Thrift, CN=localhost/emailAddress=dev@thrift.apache.org ### create self-signed server key and certificate openssl req -new -x509 -nodes -days 3000 -out server.crt -keyout server.key openssl x509 -in server.crt -text > CA.pem cat server.crt server.key > server.pem Export password is "thrift" without the quotes openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12 ### create client key and certificate openssl genrsa -out client.key create a signing request: openssl req -new -key client.key -out client.csr sign the client certificate with the server.key openssl x509 -req -days 3000 -in client.csr -CA CA.pem -CAkey server.key -set_serial 01 -out client.crt export certificate in PKCS12 format (Export password is "thrift" without the quotes) openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 export certificate in PEM format for OpenSSL usage openssl pkcs12 -in client.p12 -out client.pem -clcerts ### create client key and certificate with altnames copy openssl.cnf from your system e.g. /etc/ssl/openssl.cnf and append following to the end of [ v3_req ] subjectAltName=@alternate_names [ alternate_names ] IP.1=127.0.0.1 IP.2=::1 IP.3=::ffff:127.0.0.1 create a signing request: openssl req -new -key client_v3.key -out client_v3.csr -config openssl.cnf \ -subj "/C=US/ST=Maryland/L=Forest Hill/O=The Apache Software Foundation/OU=Apache Thrift/CN=localhost" -extensions v3_req sign the client certificate with the server.key openssl x509 -req -days 3000 -in client_v3.csr -CA CA.pem -CAkey server.key -set_serial 01 -out client_v3.crt -extensions v3_req -extfile openssl.cnf ## Java key and certificate import Java Test Environment uses key and trust store password "thrift" without the quotes list keystore entries keytool -list -storepass thrift -keystore ../../lib/java/test/.keystore list truststore entries keytool -list -storepass thrift -keystore ../../lib/java/test/.truststore delete an entry keytool -delete -storepass thrift -keystore ../../lib/java/test/.truststore -alias ssltest import certificate into truststore keytool -importcert -storepass thrift -keystore ../../lib/java/test/.truststore -alias localhost --file server.crt import key into keystore keytool -importkeystore -storepass thrift -keystore ../../lib/java/test/.keystore -srcstoretype pkcs12 -srckeystore server.p12 # Test SSL server and clients openssl s_client -connect localhost:9090 openssl s_server -accept 9090 -www thrift-0.19.0/test/keys/client.key0000644000000000000000000000321714303740367017033 0ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEpQIBAAKCAQEAyQaX1kZWr+ZOtyiOurt6plPDDWCaA481Y3VA3O+L5w8jwSBu KTTif8AVa+C2e8oqcpB84uQEckfJN1eY+q91T3Dxl3129eTvmYG9u3HKx7pRkLFm deuq/lh8wZvYES9ywvkjmzp3eAvh405tjMUPu9SMBulqZRITs054yfuo7Ss8hw4M Ncv46Sv39MFw79e9FJQrR7GxfTcULTuC1N11X2URgKQm9AwIJCYV1DlqXtXPiIuV 4bmGwLDP9bnMdyypW3ObwIRDOvTQChHwCv9aQaHWJuaKyyLkGjYNy9Eqjem8NU4B j6CP1inF7bPswiafVPtlV2vQldS72OYyAoxDPwIDAQABAoIBAQC/2ez68LI2uaQS JUDicZ6CMpqKn9Ec6IXZX8QBlxR79fT3kc3QwcoQhe9rv1ApIC4WnFKz701XC6+7 g3xacy2QHYhUPcdUsaMBa9L5m4Ydy3Ggl83jaIEOsMCPvf4dmJz7+u3CbbAq/5wb ZXQjzsZPSnBBAG8r+m6Wx6N7kRQNE28MUD/dgiKUmLaTlsFb+YnTcVIWjqrip5Z3 gpeGpUcPUjGo4/KTHm9Lx+4HuiHC8I32qyy02Zh6s5/S5n0edsqePFnUXe9j9eSb gARUNFGBq6VOMQ+9hxAVuyNrIj32PCskuw1Oh7Ce29FOXIf9niLazaiiRrwBuC1V aDjxcQ4RAoGBAOzqz6rRzarhXpX0GprpvNIyMBiQvgGlSA6lQ3IP2+lcQN5hCvmg ULcaLak6D6BuJ4+UZN7kMqjNt9WOAG2xpTC1AQfZqXQEMrQ9v/2VLs7VFVX5MALy HEEKPkkY5MDprj9byg8lK7CQ4x3SSLQe5596gfAqYLqULpyeOF1foG8FAoGBANk3 tNbFMZK9lTr8qODuya5DX6eTva2YWe0EkDr4rDFmNgyez1y6Sibli8XF/5vMs7bf 4uNseFkKV9XHargiTRvqTiqPzD9g6SdCzz4KWLQAf1eC5Q9dOeQUkDgg1GxbeZKa tCEiieWvqL2HcQ5wOO6C/SO9/JysDCO1acVe9hRzAoGBAKavSe5X8AiCyYZdGP7W 5mdIsjgGVfhYbgsH0R0F9WYI5wbOZeddGIzKmUePtwDbn2/QKuv6x32mRum0H68N pjhPkOsSA7vBXF8ddt+Vvzn8ByfWyyW3a5OC/nF1VzQ29MZU8SOYtlViirgng8le WP4GNjdfyXBb4zODygo/xmN1AoGAU1no7rDkgOZ2qRfixc1bXp9DyU4L7t0TRLwH jFl32cza2KTn9TEW2y4iIFYF64b1PytSKOqqk6BAbCwFa3reE+Qo8nQTcA6D6Sjd 1XSq7Qdz1eTIeMjROhAZ9y/B04KWeAcdL8nNGHH7Uh7y5xNxBTUGZfy1PnlWfy1R 1QbHbrkCgYEAimg6HLaW5lan6vcYA30/u8WuypWiBtCjqiTW3BM5OIl7FUH/4opx sCopQoHE6PuA7ky1DD/8UZfdqYC34vmSWg+90HmgUfU0WCmRAgfDQ7SitwC0eicT U2Kf5i1v92whfzkS0Josz40pugRFBwBY7e4VV8O+okoKmTylIblph8I= -----END RSA PRIVATE KEY----- thrift-0.19.0/test/keys/server.p120000644000000000000000000001057514303740367016702 0ustar00rootroot000000000000000‚y0‚? *†H†÷  ‚0‚,0‚(0‚_ *†H†÷  ‚P0‚L0‚E *†H†÷ 0 *†H†÷  0Û¡÷«:ºß€‚ª3}CdWÐö=wB<îÆôäŒÒš|ÃîNž°`ëìM´]®Òá÷z!ìc4&]ö‰9?/ÁÆúKDì 5G ôÛ÷¼Qⱞ¦ç­¸Omö 7”!’²ÚìoU¸“•õ.`êSÈ7n¾Ë]þÊx\0”dì—Æf»{›xjKh< ôFbMÜã›x³’ƒíå}%=†Ž«?OuþN:ÕhÁ)Ç’'Š¡€Qì[4À^BóNœ (Ô½Þñ[ò¶pÖä¶8Nz]m`IªËí|¥—“·´3¢ÊDöíÝ,EÅòx3VúŠkc±xSŠVæ¨ïG„ EÞh¾èešÆÄœÔ²¨È‹Ó]@0ñ¤Ô¨H>ôwbØ]Ð Í!J<À¸uf zå{ 9y–ºž¨ ÍXÓ iÜIoªž£•×ú£þ¼¡²‘ˆàŠø%J5¦‡iħ¼9¿¹§‰q+¼ÙÏQæ{òÕéH¥P¢;wŒH´¯0tr˜)^”5Í̺Si¼¦“ÖïìÙÿÅ}}¬xh|„i{†Ê¢bv2˜´I2À$‰£[œd;%°°Ï4Cß=¾|Œ1ê¯Z K3&å•;'¸Ëf¾Y’È;N‰†k¬}z~•tájSUµÂF—7¡ñõûxÇ¡…MÌ k°6ð"µúÐÔüÂŒ–€8Å«\HÖ½‘œb-ý¸ƒ@Ó UÖn¬ŒWÓ<ÐQð”ÊbY\ùI%Ùã±UØ+ŠÂ›¶µ kódÌŒSK‡¡Œ C1¬@ãIƒž/^rÍwÌÖ¦µm½^wµ0ãÕÿ^fbÙZ£B…;‰^zã-vŽ:°´R gþ?çÕ#.Š|)1]èr5’²”j¨(&¶,}x#› v¹xj›ôü0¦ª+t¤Â7…+¨²Þ«ŒñPJ¾4Ò¨æx8 ¹³9|·)Á¦ ´sÜ(Œ•¦)ipu E”u·Ýó×Ë‘am”¼‰¤¯„ø÷ýÈÓ¥B R³zÞG Ô&?ªr\Ÿä̰2©#þ°Z¯tÚZöÙA“m%Î2ÚŸñˆ\‡à „w”ÄòýO‡A/òÄZ;y©YÑÀ¸ä›lðâXÎ6·ËM@ÈžûIO…Ÿ®ê+ŸÐ•PNÙ‘aî#MÈ%ó¿zFÿY!¨#28w®óˆ`áY¾‡ws+ïÍòª¦”êØæóõÀ¨ˆr†s1Ïåðôa€¨)Gζ£éÑÇG¾Ëû. ¯Ž_/`øßËU€= ˆø²¡þÕ1îÔRs#„õH- 1:Ùã _¤_ºS´M{Ù°£´69;°? ƒ–`*÷œ7bnSå„zu(’bª¬–ÈB⬠á´ÍÍÖ”üp/@ÎT¶’¯;H^)ÚR$ÚÏH;jçÌ}ûÈ(Ô]ºÆ xˆ”e–¹R:PCt!éa5áÖoϱ!ÁÄÒ?©»=ÏË­¿Ìªd6æºÕ“GV>zÊ`ólppÿ¾‡nñÈ w´Õ± •ë*q¨R(Ø6ñQ-ï—±R`é^å4Pö¥ûEZ½ýÄ®½jÝÚ™F³=LñI檔œÌvÎ…]kÌ‹¤´0WRn\òQ—zÄk±a(™ŽøjŽô‰†õ—±•¢@pÃy Á³íQ2¾«½Ñ{Œ£Gø µøÃø[ORùÊj?è}É£þ¡8çZ·Sš^·-*§“ŒŸ1ÎW¹nsžŒ¾ˆÑ“rÕ¢O\˜¡ bìOƒ>qÎøõõhmiõêQÖtLŽfDêŸ2PT¥c•0è/­jÑÖ‰ËõªÁë»9ñoj4œG£…,T¤YÔâ‚þðp¬š§RP BO!†s²÷êd3åF–¢ý¥Œ•1㊡/6± ô{—›­‹ÍB¥ÀÛwóDç![éý²ôT„_ÝÜ‹¹é—ÈÖ÷5.=uQ7È/öàk<ˆtùcl.ÑÈe «@X×®fŽh¸N’¤ •T³ÄÇT”:b‚– ¿ÙÒs9UÝ-Ü£(9‹éÑ7O’]ÐСÝ2:&è `ߺ@q*ýgo“—ÙÀ”Ž™SÝàsF q6*Ø£üt$-ÉëŠSÛ¦³Á¢ÀAV…GÆR¸vÂY"mÉ‘Xr¦j£0@×÷$wKc±cÛZOm×v“ß÷ îz³Á\A°2ï ¿EíË¢êÔVQõ‹¨d+Þ×p­uÅh†(™-`¬¡>Þ4±[^UÐ y^ºuo>mã× ¹ºüá’)Q‘)€áþ0¯y½(N†²a9FQnUc bâ­U^xkzŒ •‹ãœÕW•ÖÛû«fgSòN¦/=,uË#}’=e´šÜþ®æý7p¤¨ÊÈUúê¯årXK$’t«X¯—…e,‰‚…fù9üp¦?âÃÍàO{køÙ¦¢ßðÈö?ð¥˜jê‚Ek뾫·ÙXð‡ÃMÐ|³2Š{¯RQ"tÕÁ„ Ý0ÎU¡g·@D°ö)Y3$›¿´`\B™&©U=þ‹"ªzþï§,±›z-æÎÒÁÒ/Â7¯‡1Ôù€Vú¸æ0á­|ÔcÞ%ËVþ즧8nsbËÖÚAÜQ½š2^öêS¦¤®ûJcauLF¬E¸ƒV2kÑcàÁ‰_{¢Îü@Gy¸P Ø¡Xœ†÷¸Ó´¬,ßß½’Ûša-óœ¶Gº¿V¡)#w«ªÉí%Ä‡â¦Æ¹¸lñßôº læ§*‘K‘EÕIIä‡-?ÉÅö‹+< ª„އ„°§qÔe¦K.¹,‰6;_Òi²¶\_Ö¹¤=7*áôÙìÆÅ#ë:¡µºsõaÉ__5 ‹ÞS™Lt1 ˆmí{EŠ&¥¬^*»­r ¸³qÛÝßOvZ}uÑÂ1ò]bIÚÆÁÇ)ÕÀÎ_n¶ørðô%=ðØù>µBM¹C*ÚÇF¹º›Û¸0˳]·ÛoÙ¨VH§¯ÜZÈ{_Èñ焹ý•uä:° Ãûmˆ£SRpòRù¢]Yñ_ò¼˜ËxwoD®mcÌ“èm¿$À¶¬uéŸ ìÞ˜»9ÌÊ0·u6™vÎ=\~JaúÃ¥ YWÛáH€[ìk®xŠ”„{ 'U Ž¥®Gå3½ªXõ¦0y’/¡û0ß‹H³¨ñ«©OpT÷ÅÆSÓ“@—«öy¯|Üž=Áƒä R(a¾Ä[QBY½fè\ˆ÷¦on!7ß›ýÒ„t©¹±Zð ¥éÎd5]¤®KÄ•ÁŒ 6TFÕ»f!€Ùòr¿ß6©ôµ$ì,û 1EUÌ…û›ß¤ñ´g:ÏÇïC&«4»wE>Òænc!:÷Íæ¹^·¿º©…à•­L¡ÂÒЭp ZEþÆ‘[|g~ %~Ê›ñ~‹K29“ˆ8…so/ŠQdÙÎÐå«LHTWÂk¨½ÑhAm˜ßëµ€5ÙÂ,ü`w˜/¥Rz ç2;sÓê+ü¾I%¢`,(Œ·ãOj¯ëÃo[)S€Òò L ÂIŸ505™j–ÖìX4Ž?÷ЇâE´ÀÒ¿Ï?âᢑ¢HC÷ƒJfÛÅžÈÅ}ŒÞ²ì²`D|ß$Š@5­®D;ˆëØ4s®òøòRn6è fÁ7CÇÖš±Ü,¦ÜëõÓª­Cî«ß{Wn%=ýªÞŸÆÎÄS¶@ |.’G¾»ÖS‹èwŽ-‘û"½¡l…æÌ^ó.‡£œùÒ-wé )«ëûèªqÛò‹Q]¿'Ú"g8ùOÜ„c Gñ[z|ý—1!ö+ºç¿€NgCm¶ü¹ j‡²vöU?1 "*zØ1A+•üÀ3ç:³Ü¯ùRdä×G¢#À/ÌpêMµÊ[xuuy+žÓtŒhœVòòËC^œOd …f£hÌÑ1é—À³Bà4O»kÙŸ1ê–çÁy Åä1—<1%0# *†H†÷  1ª}Ô×\¥T¤Ï ]Fue©Ù‚F010!0 +ÚM°!ªäÖfS'ЍÀe<ô‚mÊ™¹Ãlthrift-0.19.0/test/keys/server.crt0000644000000000000000000000452614303740367017067 0ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIGuTCCBKGgAwIBAgIUDG+EIHE1EFeuj0ddWtxGQAPatt8wDQYJKoZIhvcNAQEL BQAwgbExEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3DQEJARYVZGV2QHRo cmlmdC5hcGFjaGUub3JnMRYwFAYDVQQLDA1BcGFjaGUgVGhyaWZ0MScwJQYDVQQK DB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFDASBgNVBAcMC0ZvcmVz dCBIaWxsMREwDwYDVQQIDAhNYXJ5bGFuZDELMAkGA1UEBhMCVVMwHhcNMjIwNjMw MjIzNzI4WhcNMzAwOTE2MjIzNzI4WjCBsTESMBAGA1UEAwwJbG9jYWxob3N0MSQw IgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcxFjAUBgNVBAsMDUFw YWNoZSBUaHJpZnQxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRh dGlvbjEUMBIGA1UEBwwLRm9yZXN0IEhpbGwxETAPBgNVBAgMCE1hcnlsYW5kMQsw CQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM/uam3B XjI0x6hfdqdr4ATbiDA7niD8MShpyqBmdpMWu7ng91grZPCDl7T/6xCrdT92NI7m CpnA5hBK/0W8+5Y8NnKjkwZym9H5kO18FQ+hH1mJq3bx57mxsZAE1Iwbr21W/Kxh 6Jx279ayywVAU6l9cH/aS5t3pl0qZUysBi3me2J88z6oYA3FNRaxX3kO4I8iJjYu vIfpWmXf8By/TOLzNkR1pJLXe849tAGrTtm+goLw59RMhIgxlS05DH3nGNKamWQ4 gr2H5do+2pFzKoom4vCryKgc/NXyEQNc/1FRJsi3/XK/NlezoPw+xV33AeDopmmK VsQ4RJONyVlgksCD2Q2odrCR/ryqirA5BTH8pQFfvCQfr4G6zkSzSDBTC9ZI2IIx JFs87mVpcu+0n+u482vdwsUAeByE3opA99MYrlrZDjLYl40Y0kzWHK42Is3iBz03 B4VFKUrsUXa5bcquYPkr1oVycamH1QTwXtgkU6DspAjuR3tUQT4i7sSEnoV8pGl0 gLWpGABxhGde0Z0V/x14BNFJ+ZG2uiUpLvMJshqBle1kIj+CqySQMc3mFpkdBTUZ nyVVuVRc6+oGGfBujOvqFKuS9rOhpCSBBVwbq5/lPSgtvy2uBiiTwlFLMgPvV66X xQGbbgTxOjIdrL1i6smD/6RXkbIMKOFb/o4NAgMBAAGjgcYwgcMwHQYDVR0OBBYE FKgE4SRwWu2cxDhjzef4eUmUnR3aMB8GA1UdIwQYMBaAFKgE4SRwWu2cxDhjzef4 eUmUnR3aMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgHmMB0GA1Ud JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA+BgNVHREENzA1hwR/AAABhxAAAAAA AAAAAAAAAAAAAAABhxAAAAAAAAAAAAAA//9/AAABgglsb2NhbGhvc3QwDQYJKoZI hvcNAQELBQADggIBAIsl4jTS2dbrt7CStvwInf8InjaGqOrj4c0HDYVYBi33JkHx WasCJbjs+YWsQYcK3/rE9iYyZA/cwIE89x2ec1JX42SrayPLIdUF5VSo+DP3knTH Si7zt3igmziyKTsLoliISwOKwF5mdc+qeOE8CuExi7xIV4xlJxfM+XW6aeHdskof KSTd4qqzyO+wMezKb8u9/b0rMGNCvaM1etcWNlrfP2SXayLAfFkKypSbER1uIUzg ZnhSGyfYee6DrIATihPyOofjbUbqfF7MJtDTqTLhqhkndF+T7IR2LcR4XdtkxtdT F1WwKcM2FX/cjpdtGX76U6hPD6uWXDISk8IiS8HX10x0wamlVvK3zz9UsWwQp5DD EjG/XtMU59oAyiiGIbZllUWKOOabCcId8dvYZw4zoObCrYiYb2qvPcJPyUOzcCPn wsOS22lgTqEfoNzlrmh39YI8pvNDh+t0SkK8Nhllm4o/hIQkIxYlqsp4IkCnyxpO dgRMt2H+98FCNLGs3EIkmaeKD42OyglvdzM0IYHT2VDRfhwpjPvSEw/lJyYIi3R0 BEWNGA9Jx+BKZRxmyOerUqCMmImwMoLtKudEHpWz5bXcUkmqsmGXaHabVW7Z3nfN ZwdSLNHgHLNYBGe6Ak198CFHGmP/9XbV41cGNXctfe92baDv5IMgWOi35X5w -----END CERTIFICATE----- thrift-0.19.0/test/keys/client_v3.crt0000644000000000000000000000351614303740367017445 0ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIFOTCCAyGgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBsTESMBAGA1UEAwwJbG9j YWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcxFjAU BgNVBAsMDUFwYWNoZSBUaHJpZnQxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh cmUgRm91bmRhdGlvbjEUMBIGA1UEBwwLRm9yZXN0IEhpbGwxETAPBgNVBAgMCE1h cnlsYW5kMQswCQYDVQQGEwJVUzAeFw0yMjA2MzAyMjM3MzlaFw0zMDA5MTYyMjM3 MzlaMIGxMRIwEAYDVQQDDAlsb2NhbGhvc3QxJDAiBgkqhkiG9w0BCQEWFWRldkB0 aHJpZnQuYXBhY2hlLm9yZzEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDEnMCUGA1UE CgweVGhlIEFwYWNoZSBTb2Z0d2FyZSBGb3VuZGF0aW9uMRQwEgYDVQQHDAtGb3Jl c3QgSGlsbDERMA8GA1UECAwITWFyeWxhbmQxCzAJBgNVBAYTAlVTMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsqPCAkuOxPmJ773z1KWaJyYWswj7zTVI Tm/uF0pIMSTzJh136Y7qJDMfKHZuO0EEEuvWgjxuDQCoi9G8lIyq3TV04scUmC0e QpZDizz3XRqW7F2nMzapyp9I2dG0mRwVTb/iWlSIvGfIiWQZaX32P9V7/0CWH3zY Bk7Sve9N5rymcjMQFR7aNlNpU4tw2Oa8Jz8d4CjsljeZQ8K2fE+R9fUN+aq0DQlv hiBuKHHUCpypNneLdc5XB6dUUAsTlq8OjbWLbUqAiK3gdrsIgfx9dxKcBoQxXrkj KM3/VAM2PNFVZ4nz6Klxt5n0QlZBsq4EQmcUxUr7JoVBFkeaJABiQwIDAQABo1ow WDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DA+BgNVHREENzA1hwR/AAABhxAAAAAA AAAAAAAAAAAAAAABhxAAAAAAAAAAAAAA//9/AAABgglsb2NhbGhvc3QwDQYJKoZI hvcNAQELBQADggIBAH8vPs4l8VITIOvuxPPtRngiUteSxU+MQ/oYbuASguNQ7s4f ZmCnBFQm7n0TvFkaR8nSCKrKy0ok3Dm+RflCySq37K/aI+6okQXPkBk4VVcCnd/l Z0V966pqibxrH5oLH69nOBelZPxpmcWy8ZgTYyNGph6GXQ0G5bFRpSNDjrMZjjtu Om40MEMO/k8eD1xXJnuVxdIic8XcSFSLAeTV2ye/stFkU50ZNJy8zAa4D97tTc9z AFgNgb3i08P6Rs8HYOmBY8DxOwFi32kEgsNDnh5oZMj69UwQUSYaFzh+uVPr1b9F qEN66unWJl1/bb9XATfIvLU2nmVXZ32O5POIRdx/mhPSDUtO11OHlnfyrWqjYIUk Q6+iKznR88w+aTQReL+85C71xtFa5UYeEjrsew9YdJZnfURh2gX8Lf8wxpiHatd9 msX5er86hqWsV/cbhTkeZiJyh2qP/LZF32VH1ztUkauK7/l3r15pKp9b0pDJl69O KC6MzRWIS7cn/m3Hl9Ghcp3wAS3jgmwNg0PQKlCsWTQ/cmd+9Piy/wx4sdvu8N/M b1lUrduLwO+NisfT+U4lI1aY100S5EjjyUXettorvdmt/947PbLxZgd4ydzXN1q8 jmoDZYxLFsbXR5NcbmJ8ldkKDf7E0NTGmHPuk5jM4EwmnnGttHMOnlgn+G5C -----END CERTIFICATE----- thrift-0.19.0/test/keys/server.pem0000644000000000000000000001303214303740367017050 0ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIGuTCCBKGgAwIBAgIUDG+EIHE1EFeuj0ddWtxGQAPatt8wDQYJKoZIhvcNAQEL BQAwgbExEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3DQEJARYVZGV2QHRo cmlmdC5hcGFjaGUub3JnMRYwFAYDVQQLDA1BcGFjaGUgVGhyaWZ0MScwJQYDVQQK DB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFDASBgNVBAcMC0ZvcmVz dCBIaWxsMREwDwYDVQQIDAhNYXJ5bGFuZDELMAkGA1UEBhMCVVMwHhcNMjIwNjMw MjIzNzI4WhcNMzAwOTE2MjIzNzI4WjCBsTESMBAGA1UEAwwJbG9jYWxob3N0MSQw IgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcxFjAUBgNVBAsMDUFw YWNoZSBUaHJpZnQxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRh dGlvbjEUMBIGA1UEBwwLRm9yZXN0IEhpbGwxETAPBgNVBAgMCE1hcnlsYW5kMQsw CQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM/uam3B XjI0x6hfdqdr4ATbiDA7niD8MShpyqBmdpMWu7ng91grZPCDl7T/6xCrdT92NI7m CpnA5hBK/0W8+5Y8NnKjkwZym9H5kO18FQ+hH1mJq3bx57mxsZAE1Iwbr21W/Kxh 6Jx279ayywVAU6l9cH/aS5t3pl0qZUysBi3me2J88z6oYA3FNRaxX3kO4I8iJjYu vIfpWmXf8By/TOLzNkR1pJLXe849tAGrTtm+goLw59RMhIgxlS05DH3nGNKamWQ4 gr2H5do+2pFzKoom4vCryKgc/NXyEQNc/1FRJsi3/XK/NlezoPw+xV33AeDopmmK VsQ4RJONyVlgksCD2Q2odrCR/ryqirA5BTH8pQFfvCQfr4G6zkSzSDBTC9ZI2IIx JFs87mVpcu+0n+u482vdwsUAeByE3opA99MYrlrZDjLYl40Y0kzWHK42Is3iBz03 B4VFKUrsUXa5bcquYPkr1oVycamH1QTwXtgkU6DspAjuR3tUQT4i7sSEnoV8pGl0 gLWpGABxhGde0Z0V/x14BNFJ+ZG2uiUpLvMJshqBle1kIj+CqySQMc3mFpkdBTUZ nyVVuVRc6+oGGfBujOvqFKuS9rOhpCSBBVwbq5/lPSgtvy2uBiiTwlFLMgPvV66X xQGbbgTxOjIdrL1i6smD/6RXkbIMKOFb/o4NAgMBAAGjgcYwgcMwHQYDVR0OBBYE FKgE4SRwWu2cxDhjzef4eUmUnR3aMB8GA1UdIwQYMBaAFKgE4SRwWu2cxDhjzef4 eUmUnR3aMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgHmMB0GA1Ud JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA+BgNVHREENzA1hwR/AAABhxAAAAAA AAAAAAAAAAAAAAABhxAAAAAAAAAAAAAA//9/AAABgglsb2NhbGhvc3QwDQYJKoZI hvcNAQELBQADggIBAIsl4jTS2dbrt7CStvwInf8InjaGqOrj4c0HDYVYBi33JkHx WasCJbjs+YWsQYcK3/rE9iYyZA/cwIE89x2ec1JX42SrayPLIdUF5VSo+DP3knTH Si7zt3igmziyKTsLoliISwOKwF5mdc+qeOE8CuExi7xIV4xlJxfM+XW6aeHdskof KSTd4qqzyO+wMezKb8u9/b0rMGNCvaM1etcWNlrfP2SXayLAfFkKypSbER1uIUzg ZnhSGyfYee6DrIATihPyOofjbUbqfF7MJtDTqTLhqhkndF+T7IR2LcR4XdtkxtdT F1WwKcM2FX/cjpdtGX76U6hPD6uWXDISk8IiS8HX10x0wamlVvK3zz9UsWwQp5DD EjG/XtMU59oAyiiGIbZllUWKOOabCcId8dvYZw4zoObCrYiYb2qvPcJPyUOzcCPn wsOS22lgTqEfoNzlrmh39YI8pvNDh+t0SkK8Nhllm4o/hIQkIxYlqsp4IkCnyxpO dgRMt2H+98FCNLGs3EIkmaeKD42OyglvdzM0IYHT2VDRfhwpjPvSEw/lJyYIi3R0 BEWNGA9Jx+BKZRxmyOerUqCMmImwMoLtKudEHpWz5bXcUkmqsmGXaHabVW7Z3nfN ZwdSLNHgHLNYBGe6Ak198CFHGmP/9XbV41cGNXctfe92baDv5IMgWOi35X5w -----END CERTIFICATE----- -----BEGIN PRIVATE KEY----- MIIJPwIBADANBgkqhkiG9w0BAQEFAASCCSkwggklAgEAAoICAQDP7mptwV4yNMeo X3ana+AE24gwO54g/DEoacqgZnaTFru54PdYK2Twg5e0/+sQq3U/djSO5gqZwOYQ Sv9FvPuWPDZyo5MGcpvR+ZDtfBUPoR9Ziat28ee5sbGQBNSMG69tVvysYeicdu/W sssFQFOpfXB/2kubd6ZdKmVMrAYt5ntifPM+qGANxTUWsV95DuCPIiY2LryH6Vpl 3/Acv0zi8zZEdaSS13vOPbQBq07ZvoKC8OfUTISIMZUtOQx95xjSmplkOIK9h+Xa PtqRcyqKJuLwq8ioHPzV8hEDXP9RUSbIt/1yvzZXs6D8PsVd9wHg6KZpilbEOEST jclZYJLAg9kNqHawkf68qoqwOQUx/KUBX7wkH6+Bus5Es0gwUwvWSNiCMSRbPO5l aXLvtJ/ruPNr3cLFAHgchN6KQPfTGK5a2Q4y2JeNGNJM1hyuNiLN4gc9NweFRSlK 7FF2uW3KrmD5K9aFcnGph9UE8F7YJFOg7KQI7kd7VEE+Iu7EhJ6FfKRpdIC1qRgA cYRnXtGdFf8deATRSfmRtrolKS7zCbIagZXtZCI/gqskkDHN5haZHQU1GZ8lVblU XOvqBhnwbozr6hSrkvazoaQkgQVcG6uf5T0oLb8trgYok8JRSzID71eul8UBm24E 8ToyHay9YurJg/+kV5GyDCjhW/6ODQIDAQABAoICABd4zF7TYzS7rIYfMJ+5l7I0 rezz7ee/UDVFq+/rYRs9h7d147X6QAy+bhOqh/h7wmKFj21KHow4sD/Kl4Jh0Oym o2bRfDlQGrLbPzbvuNjo0UckOUzWBdh6bJbbVLr0LRtkpGU5MC7pZi2QRUa0ej05 wcdM9xf3q7n8nS7IhHIOAIOfoz3BeAZV6qZDI4ng2gyOSE35fKLC/sddPhegqKc9 2TRlK0zAMmOXp4hAtEf0L3tkgmb+tD9DiZlvRS+5NJ4hgYtErc2DV7kJO1cL7xNl TFzqp14C16+3AaClkNS3Gm+yBVQ8rX+88UFIPLNcvMOMv6xOR3ki+OrHKKGEO0x3 vd0Q5gcgbwxD2sEHajlbo9UkSEJnaUeUD0s/kQBYWCLIcosayPQh3Z3xLE4+ir+r bbvAK4b2bJHeww2X9NrHB3dA8xjISIvzGoGL6M6nrgEgiov+L9rAyAlFhpY6872R ttfgN3aP2ZK7tmfz+7G/cfWyPfSRJpTVIrtfpJw9CWuzFrAgOuPUTP5eOjjxPXeQ eZuaABXVkM+V8xoqVE9KiD6UrE2401lPpoLevxm/i/oJePtFSdruu9ARBxVt2/gz No2PKXYuJaoyOPKPqSWnJiI0ZI9KpvMBXdUcuI3dv8y5dumKfKqAKliAvaXNMdfU 8HeeVqDsh3eotH56YUFpAoIBAQD+rP491LtjrF/cCX6wdAAgkgfpQ7nnM8XM+606 xbeepHJllhTfsE7K69Gs0GSDHRjh6q/GYnr2GnZ2q1kTVUeJ0gXmlPVOudxlxHlw W2vfVBivoMC2z5pb1shdmcwyuxG+NJWogW3nn3JzbPY5ZKIT3O+YMF71NeAiAMqF h0MuKpIysfqUqMHD2dOz3kb2pci048WTnMH4GnHnz7g6oB5nV9cz/BTr2XJN9kye FfDhBSZX4IMcPLcUvzuv3NAW+lNGASCyrfCxx5SDZcx45jdpTqyK2mXLrmUKB+tZ /4RRKuMrngydZYT73T+Qy5b9KM1O/yPLfNm++f0jPJlpn2dXAoIBAQDRAzMZ97SY ELqwx3pnTdQoKV7q5hXv03SZOGuh4yhyOXdiWTZAftA0xQ7UkoH1nKF9FaLDupD6 8tnG4kaZB7OiKUf9rFM42MS2be7bz7Q9Cg9s0rWAtUowTWMDi5bRX9zOhiphPFuY 71TdI59YhVQPpK0roZcKeCxEDaKpywfAbAkApHaGUpZJAx4Gx/97iQZZdBCw24Ec EyD1Xxsl1q54tJwiYncxlghpy4aVO5zXeDyHuH9jtDoM+dxvobytrHMtbwu6YGK4 6RI/1sggoZ+89ZONFrXz8o0/0f+uP9bLL4ds4b0PINHKGV1AG1SBfOmLkhKx/y76 BhY1zsHuFws7AoIBAHAxN4N3nuGnA0fE6wnC4Hd4vYF2c4Q125KU4Nh+V4jMuxSj jCiK2/sq7eCqoUzdWaPUpoDHy5F1UPCwRXpt3CkL28ubnYGEAWLXrgPgUmI9Au8D 60HdrQt+UCBj64ABxyw6sB9efVNHe7z7qHDaM0h60RYDYSG3DTkNjipKzz6cRHGO 1Gv+9/VWlZusdSidGhEOMnD34r9wrvNHH8q71QkDumtNRs4rqd5Mfa46zjXi9eRK pJeg66p5IEs2BHnK5zp0rrnoRJuc54EHLI+qI4kBvqMg2S1kc2B64qRwGxNCyHbj ln0URwRJkIIyHh8ChYeigFtZcfde27RVMuRD89sCggEABJ41etVmQBXeihleMvod PeXsGvSKd4oMgXYlqqYCNsPeR2YBNNuYbhIMidXS2UJkrwbTWc+9dE35UdOeC7OH 3IVc+dXc4NypO/6h0Gl+afrW7GibagSXZwnOrj1fT7D2h/me5hcXTwG6tkgbNTF8 8fuJd/VSCQEuuTIz7dx2h2HbsQ/xLnaUq3hOKYgxtOEKKt/Nnpq694vUppc7WlKr +C7FZF0YlRfjh7Lfflya0oftjnIdHm7U+YRrwmuoZ43v3YkekTef9sXviUmNkmr/ xIUIhY2C56jsRgS1yXvPmx2puFYkfzkSaYy16ryv2UyRPGw1zYj92LhZtUakMkaA EQKB/wLQfRkaMz0RtxzyroTLcc1mlJmSyE/Cb6032R4BmA0t2MDFUePmRYsp7f2I 47z5a9R1oJtY0lNl1JeSWqNvL9iAmFAkN96hC0mk4xvWZBOhIPfMx6hVKms9Zbwd yHVfUFudAjp/cY4zXBKbSj7emz/L+yM0E0Dz07HqvqX3CcWrR0gbC6GE3wRr5XM2 asZAQXYadPjO4W9vsiT0UWrj6zKWwr0mH7gLk+VXzqE/25+aSx4Z6N1IAkR7gW23 2I5xxNtaanZH6jmJ1CGZA3mWazQCl0vOc3QoyzH9TqQbL+VL7Y75lUTSwW8IPPL1 OV2cxV8xD52Pk7JlPVRIgWOT2Q== -----END PRIVATE KEY----- thrift-0.19.0/test/keys/keygen/0000777000000000000000000000000014472652702016330 5ustar00rootroot00000000000000thrift-0.19.0/test/keys/keygen/make-serverkey.sh0000644000000000000000000000776014303740367021622 0ustar00rootroot00000000000000#!/bin/bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # tested with git bash on Windows # probably needs a bit of tweaking for other environments # re the "//SKIP=this" in sub see at https://stackoverflow.com/a/54924640/499466 echo init folder rm *.p12 2> /dev/null rm *.pem 2> /dev/null rm *.crt 2> /dev/null rm *.key 2> /dev/null rm *.cfg 2> /dev/null rm *.csr 2> /dev/null #cp ../*.key . echo writing config echo '[ req ]' > my.cfg echo 'default_bits= 4096' >> my.cfg echo 'distinguished_name=req' >> my.cfg echo 'x509_extensions = v3_ca' >> my.cfg echo 'req_extensions = v3_req' >> my.cfg echo '' >> my.cfg echo '[ v3_req ]' >> my.cfg echo 'basicConstraints = CA:FALSE' >> my.cfg echo 'keyUsage = nonRepudiation, digitalSignature, keyEncipherment' >> my.cfg echo 'subjectAltName=@alternate_names' >> my.cfg echo '' >> my.cfg echo '[ alternate_names ]' >> my.cfg echo 'IP.1=127.0.0.1' >> my.cfg echo 'IP.2=::1' >> my.cfg echo 'IP.3=::ffff:127.0.0.1' >> my.cfg echo 'DNS.1=localhost' >> my.cfg echo '' >> my.cfg echo '[ v3_ca ]' >> my.cfg echo 'subjectKeyIdentifier=hash' >> my.cfg echo 'authorityKeyIdentifier=keyid:always,issuer' >> my.cfg echo 'basicConstraints = critical, CA:TRUE, pathlen:0' >> my.cfg echo 'keyUsage = critical, cRLSign, keyCertSign, nonRepudiation, digitalSignature, keyEncipherment' >> my.cfg echo 'extendedKeyUsage = serverAuth, clientAuth' >> my.cfg echo 'subjectAltName=@alternate_names' >> my.cfg echo '' >> my.cfg echo echo step 1a winpty openssl req \ -new \ -x509 \ -nodes \ -days 3000 \ -out server.crt \ -keyout server.key \ -subj '//SKIP=this/CN=localhost/emailAddress=dev@thrift.apache.org/OU=Apache Thrift/O=The Apache Software Foundation/L=Forest Hill/ST=Maryland/C=US' \ -extensions v3_ca \ -config my.cfg echo echo step 1b openssl x509 -in server.crt -text > CA.pem echo echo step 1c cat server.crt server.key > server.pem echo echo step 2 echo 'Use "thrift" as password (without the quotes)' winpty openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12 echo echo step 3 winpty openssl genrsa -out client.key echo echo step 4 winpty openssl req \ -new \ -subj '//SKIP=this/CN=localhost/emailAddress=dev@thrift.apache.org/OU=Apache Thrift/O=The Apache Software Foundation/L=Forest Hill/ST=Maryland/C=US' \ -key client.key \ -out client.csr echo echo step 5 winpty openssl x509 -req -days 3000 -in client.csr -CA CA.pem -CAkey server.key -set_serial 01 -out client.crt echo echo step 6 winpty openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12 echo echo step 7 winpty openssl pkcs12 -in client.p12 -out client.pem -clcerts echo echo step 8a openssl genrsa -out client_v3.key echo echo step 8b winpty openssl req \ -new \ -subj '//SKIP=this/CN=localhost/emailAddress=dev@thrift.apache.org/OU=Apache Thrift/O=The Apache Software Foundation/L=Forest Hill/ST=Maryland/C=US' \ -key client_v3.key \ -out client_v3.csr \ -extensions v3_req \ -config my.cfg echo echo step 9 winpty openssl x509 -req -days 3000 -in client_v3.csr -CA CA.pem -CAkey server.key -set_serial 01 -out client_v3.crt -extensions v3_req -extfile my.cfg echo echo cleanup rm *.cfg 2> /dev/null rm *.csr 2> /dev/null echo echo test openssl s_client -connect localhost:9090 & openssl s_server -accept 9090 -www echo echo done thrift-0.19.0/test/keys/server.key0000644000000000000000000000630414303740367017063 0ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIJPwIBADANBgkqhkiG9w0BAQEFAASCCSkwggklAgEAAoICAQDP7mptwV4yNMeo X3ana+AE24gwO54g/DEoacqgZnaTFru54PdYK2Twg5e0/+sQq3U/djSO5gqZwOYQ Sv9FvPuWPDZyo5MGcpvR+ZDtfBUPoR9Ziat28ee5sbGQBNSMG69tVvysYeicdu/W sssFQFOpfXB/2kubd6ZdKmVMrAYt5ntifPM+qGANxTUWsV95DuCPIiY2LryH6Vpl 3/Acv0zi8zZEdaSS13vOPbQBq07ZvoKC8OfUTISIMZUtOQx95xjSmplkOIK9h+Xa PtqRcyqKJuLwq8ioHPzV8hEDXP9RUSbIt/1yvzZXs6D8PsVd9wHg6KZpilbEOEST jclZYJLAg9kNqHawkf68qoqwOQUx/KUBX7wkH6+Bus5Es0gwUwvWSNiCMSRbPO5l aXLvtJ/ruPNr3cLFAHgchN6KQPfTGK5a2Q4y2JeNGNJM1hyuNiLN4gc9NweFRSlK 7FF2uW3KrmD5K9aFcnGph9UE8F7YJFOg7KQI7kd7VEE+Iu7EhJ6FfKRpdIC1qRgA cYRnXtGdFf8deATRSfmRtrolKS7zCbIagZXtZCI/gqskkDHN5haZHQU1GZ8lVblU XOvqBhnwbozr6hSrkvazoaQkgQVcG6uf5T0oLb8trgYok8JRSzID71eul8UBm24E 8ToyHay9YurJg/+kV5GyDCjhW/6ODQIDAQABAoICABd4zF7TYzS7rIYfMJ+5l7I0 rezz7ee/UDVFq+/rYRs9h7d147X6QAy+bhOqh/h7wmKFj21KHow4sD/Kl4Jh0Oym o2bRfDlQGrLbPzbvuNjo0UckOUzWBdh6bJbbVLr0LRtkpGU5MC7pZi2QRUa0ej05 wcdM9xf3q7n8nS7IhHIOAIOfoz3BeAZV6qZDI4ng2gyOSE35fKLC/sddPhegqKc9 2TRlK0zAMmOXp4hAtEf0L3tkgmb+tD9DiZlvRS+5NJ4hgYtErc2DV7kJO1cL7xNl TFzqp14C16+3AaClkNS3Gm+yBVQ8rX+88UFIPLNcvMOMv6xOR3ki+OrHKKGEO0x3 vd0Q5gcgbwxD2sEHajlbo9UkSEJnaUeUD0s/kQBYWCLIcosayPQh3Z3xLE4+ir+r bbvAK4b2bJHeww2X9NrHB3dA8xjISIvzGoGL6M6nrgEgiov+L9rAyAlFhpY6872R ttfgN3aP2ZK7tmfz+7G/cfWyPfSRJpTVIrtfpJw9CWuzFrAgOuPUTP5eOjjxPXeQ eZuaABXVkM+V8xoqVE9KiD6UrE2401lPpoLevxm/i/oJePtFSdruu9ARBxVt2/gz No2PKXYuJaoyOPKPqSWnJiI0ZI9KpvMBXdUcuI3dv8y5dumKfKqAKliAvaXNMdfU 8HeeVqDsh3eotH56YUFpAoIBAQD+rP491LtjrF/cCX6wdAAgkgfpQ7nnM8XM+606 xbeepHJllhTfsE7K69Gs0GSDHRjh6q/GYnr2GnZ2q1kTVUeJ0gXmlPVOudxlxHlw W2vfVBivoMC2z5pb1shdmcwyuxG+NJWogW3nn3JzbPY5ZKIT3O+YMF71NeAiAMqF h0MuKpIysfqUqMHD2dOz3kb2pci048WTnMH4GnHnz7g6oB5nV9cz/BTr2XJN9kye FfDhBSZX4IMcPLcUvzuv3NAW+lNGASCyrfCxx5SDZcx45jdpTqyK2mXLrmUKB+tZ /4RRKuMrngydZYT73T+Qy5b9KM1O/yPLfNm++f0jPJlpn2dXAoIBAQDRAzMZ97SY ELqwx3pnTdQoKV7q5hXv03SZOGuh4yhyOXdiWTZAftA0xQ7UkoH1nKF9FaLDupD6 8tnG4kaZB7OiKUf9rFM42MS2be7bz7Q9Cg9s0rWAtUowTWMDi5bRX9zOhiphPFuY 71TdI59YhVQPpK0roZcKeCxEDaKpywfAbAkApHaGUpZJAx4Gx/97iQZZdBCw24Ec EyD1Xxsl1q54tJwiYncxlghpy4aVO5zXeDyHuH9jtDoM+dxvobytrHMtbwu6YGK4 6RI/1sggoZ+89ZONFrXz8o0/0f+uP9bLL4ds4b0PINHKGV1AG1SBfOmLkhKx/y76 BhY1zsHuFws7AoIBAHAxN4N3nuGnA0fE6wnC4Hd4vYF2c4Q125KU4Nh+V4jMuxSj jCiK2/sq7eCqoUzdWaPUpoDHy5F1UPCwRXpt3CkL28ubnYGEAWLXrgPgUmI9Au8D 60HdrQt+UCBj64ABxyw6sB9efVNHe7z7qHDaM0h60RYDYSG3DTkNjipKzz6cRHGO 1Gv+9/VWlZusdSidGhEOMnD34r9wrvNHH8q71QkDumtNRs4rqd5Mfa46zjXi9eRK pJeg66p5IEs2BHnK5zp0rrnoRJuc54EHLI+qI4kBvqMg2S1kc2B64qRwGxNCyHbj ln0URwRJkIIyHh8ChYeigFtZcfde27RVMuRD89sCggEABJ41etVmQBXeihleMvod PeXsGvSKd4oMgXYlqqYCNsPeR2YBNNuYbhIMidXS2UJkrwbTWc+9dE35UdOeC7OH 3IVc+dXc4NypO/6h0Gl+afrW7GibagSXZwnOrj1fT7D2h/me5hcXTwG6tkgbNTF8 8fuJd/VSCQEuuTIz7dx2h2HbsQ/xLnaUq3hOKYgxtOEKKt/Nnpq694vUppc7WlKr +C7FZF0YlRfjh7Lfflya0oftjnIdHm7U+YRrwmuoZ43v3YkekTef9sXviUmNkmr/ xIUIhY2C56jsRgS1yXvPmx2puFYkfzkSaYy16ryv2UyRPGw1zYj92LhZtUakMkaA EQKB/wLQfRkaMz0RtxzyroTLcc1mlJmSyE/Cb6032R4BmA0t2MDFUePmRYsp7f2I 47z5a9R1oJtY0lNl1JeSWqNvL9iAmFAkN96hC0mk4xvWZBOhIPfMx6hVKms9Zbwd yHVfUFudAjp/cY4zXBKbSj7emz/L+yM0E0Dz07HqvqX3CcWrR0gbC6GE3wRr5XM2 asZAQXYadPjO4W9vsiT0UWrj6zKWwr0mH7gLk+VXzqE/25+aSx4Z6N1IAkR7gW23 2I5xxNtaanZH6jmJ1CGZA3mWazQCl0vOc3QoyzH9TqQbL+VL7Y75lUTSwW8IPPL1 OV2cxV8xD52Pk7JlPVRIgWOT2Q== -----END PRIVATE KEY----- thrift-0.19.0/test/keys/CA.pem0000644000000000000000000001771514303740367016041 0ustar00rootroot00000000000000Certificate: Data: Version: 3 (0x2) Serial Number: 0c:6f:84:20:71:35:10:57:ae:8f:47:5d:5a:dc:46:40:03:da:b6:df Signature Algorithm: sha256WithRSAEncryption Issuer: CN = localhost, emailAddress = dev@thrift.apache.org, OU = Apache Thrift, O = The Apache Software Foundation, L = Forest Hill, ST = Maryland, C = US Validity Not Before: Jun 30 22:37:28 2022 GMT Not After : Sep 16 22:37:28 2030 GMT Subject: CN = localhost, emailAddress = dev@thrift.apache.org, OU = Apache Thrift, O = The Apache Software Foundation, L = Forest Hill, ST = Maryland, C = US Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: 00:cf:ee:6a:6d:c1:5e:32:34:c7:a8:5f:76:a7:6b: e0:04:db:88:30:3b:9e:20:fc:31:28:69:ca:a0:66: 76:93:16:bb:b9:e0:f7:58:2b:64:f0:83:97:b4:ff: eb:10:ab:75:3f:76:34:8e:e6:0a:99:c0:e6:10:4a: ff:45:bc:fb:96:3c:36:72:a3:93:06:72:9b:d1:f9: 90:ed:7c:15:0f:a1:1f:59:89:ab:76:f1:e7:b9:b1: b1:90:04:d4:8c:1b:af:6d:56:fc:ac:61:e8:9c:76: ef:d6:b2:cb:05:40:53:a9:7d:70:7f:da:4b:9b:77: a6:5d:2a:65:4c:ac:06:2d:e6:7b:62:7c:f3:3e:a8: 60:0d:c5:35:16:b1:5f:79:0e:e0:8f:22:26:36:2e: bc:87:e9:5a:65:df:f0:1c:bf:4c:e2:f3:36:44:75: a4:92:d7:7b:ce:3d:b4:01:ab:4e:d9:be:82:82:f0: e7:d4:4c:84:88:31:95:2d:39:0c:7d:e7:18:d2:9a: 99:64:38:82:bd:87:e5:da:3e:da:91:73:2a:8a:26: e2:f0:ab:c8:a8:1c:fc:d5:f2:11:03:5c:ff:51:51: 26:c8:b7:fd:72:bf:36:57:b3:a0:fc:3e:c5:5d:f7: 01:e0:e8:a6:69:8a:56:c4:38:44:93:8d:c9:59:60: 92:c0:83:d9:0d:a8:76:b0:91:fe:bc:aa:8a:b0:39: 05:31:fc:a5:01:5f:bc:24:1f:af:81:ba:ce:44:b3: 48:30:53:0b:d6:48:d8:82:31:24:5b:3c:ee:65:69: 72:ef:b4:9f:eb:b8:f3:6b:dd:c2:c5:00:78:1c:84: de:8a:40:f7:d3:18:ae:5a:d9:0e:32:d8:97:8d:18: d2:4c:d6:1c:ae:36:22:cd:e2:07:3d:37:07:85:45: 29:4a:ec:51:76:b9:6d:ca:ae:60:f9:2b:d6:85:72: 71:a9:87:d5:04:f0:5e:d8:24:53:a0:ec:a4:08:ee: 47:7b:54:41:3e:22:ee:c4:84:9e:85:7c:a4:69:74: 80:b5:a9:18:00:71:84:67:5e:d1:9d:15:ff:1d:78: 04:d1:49:f9:91:b6:ba:25:29:2e:f3:09:b2:1a:81: 95:ed:64:22:3f:82:ab:24:90:31:cd:e6:16:99:1d: 05:35:19:9f:25:55:b9:54:5c:eb:ea:06:19:f0:6e: 8c:eb:ea:14:ab:92:f6:b3:a1:a4:24:81:05:5c:1b: ab:9f:e5:3d:28:2d:bf:2d:ae:06:28:93:c2:51:4b: 32:03:ef:57:ae:97:c5:01:9b:6e:04:f1:3a:32:1d: ac:bd:62:ea:c9:83:ff:a4:57:91:b2:0c:28:e1:5b: fe:8e:0d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: A8:04:E1:24:70:5A:ED:9C:C4:38:63:CD:E7:F8:79:49:94:9D:1D:DA X509v3 Authority Key Identifier: keyid:A8:04:E1:24:70:5A:ED:9C:C4:38:63:CD:E7:F8:79:49:94:9D:1D:DA X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment, Certificate Sign, CRL Sign X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Subject Alternative Name: IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1, IP Address:0:0:0:0:0:FFFF:7F00:1, DNS:localhost Signature Algorithm: sha256WithRSAEncryption 8b:25:e2:34:d2:d9:d6:eb:b7:b0:92:b6:fc:08:9d:ff:08:9e: 36:86:a8:ea:e3:e1:cd:07:0d:85:58:06:2d:f7:26:41:f1:59: ab:02:25:b8:ec:f9:85:ac:41:87:0a:df:fa:c4:f6:26:32:64: 0f:dc:c0:81:3c:f7:1d:9e:73:52:57:e3:64:ab:6b:23:cb:21: d5:05:e5:54:a8:f8:33:f7:92:74:c7:4a:2e:f3:b7:78:a0:9b: 38:b2:29:3b:0b:a2:58:88:4b:03:8a:c0:5e:66:75:cf:aa:78: e1:3c:0a:e1:31:8b:bc:48:57:8c:65:27:17:cc:f9:75:ba:69: e1:dd:b2:4a:1f:29:24:dd:e2:aa:b3:c8:ef:b0:31:ec:ca:6f: cb:bd:fd:bd:2b:30:63:42:bd:a3:35:7a:d7:16:36:5a:df:3f: 64:97:6b:22:c0:7c:59:0a:ca:94:9b:11:1d:6e:21:4c:e0:66: 78:52:1b:27:d8:79:ee:83:ac:80:13:8a:13:f2:3a:87:e3:6d: 46:ea:7c:5e:cc:26:d0:d3:a9:32:e1:aa:19:27:74:5f:93:ec: 84:76:2d:c4:78:5d:db:64:c6:d7:53:17:55:b0:29:c3:36:15: 7f:dc:8e:97:6d:19:7e:fa:53:a8:4f:0f:ab:96:5c:32:12:93: c2:22:4b:c1:d7:d7:4c:74:c1:a9:a5:56:f2:b7:cf:3f:54:b1: 6c:10:a7:90:c3:12:31:bf:5e:d3:14:e7:da:00:ca:28:86:21: b6:65:95:45:8a:38:e6:9b:09:c2:1d:f1:db:d8:67:0e:33:a0: e6:c2:ad:88:98:6f:6a:af:3d:c2:4f:c9:43:b3:70:23:e7:c2: c3:92:db:69:60:4e:a1:1f:a0:dc:e5:ae:68:77:f5:82:3c:a6: f3:43:87:eb:74:4a:42:bc:36:19:65:9b:8a:3f:84:84:24:23: 16:25:aa:ca:78:22:40:a7:cb:1a:4e:76:04:4c:b7:61:fe:f7: c1:42:34:b1:ac:dc:42:24:99:a7:8a:0f:8d:8e:ca:09:6f:77: 33:34:21:81:d3:d9:50:d1:7e:1c:29:8c:fb:d2:13:0f:e5:27: 26:08:8b:74:74:04:45:8d:18:0f:49:c7:e0:4a:65:1c:66:c8: e7:ab:52:a0:8c:98:89:b0:32:82:ed:2a:e7:44:1e:95:b3:e5: b5:dc:52:49:aa:b2:61:97:68:76:9b:55:6e:d9:de:77:cd:67: 07:52:2c:d1:e0:1c:b3:58:04:67:ba:02:4d:7d:f0:21:47:1a: 63:ff:f5:76:d5:e3:57:06:35:77:2d:7d:ef:76:6d:a0:ef:e4: 83:20:58:e8:b7:e5:7e:70 -----BEGIN CERTIFICATE----- MIIGuTCCBKGgAwIBAgIUDG+EIHE1EFeuj0ddWtxGQAPatt8wDQYJKoZIhvcNAQEL BQAwgbExEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3DQEJARYVZGV2QHRo cmlmdC5hcGFjaGUub3JnMRYwFAYDVQQLDA1BcGFjaGUgVGhyaWZ0MScwJQYDVQQK DB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFDASBgNVBAcMC0ZvcmVz dCBIaWxsMREwDwYDVQQIDAhNYXJ5bGFuZDELMAkGA1UEBhMCVVMwHhcNMjIwNjMw MjIzNzI4WhcNMzAwOTE2MjIzNzI4WjCBsTESMBAGA1UEAwwJbG9jYWxob3N0MSQw IgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcxFjAUBgNVBAsMDUFw YWNoZSBUaHJpZnQxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdhcmUgRm91bmRh dGlvbjEUMBIGA1UEBwwLRm9yZXN0IEhpbGwxETAPBgNVBAgMCE1hcnlsYW5kMQsw CQYDVQQGEwJVUzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAM/uam3B XjI0x6hfdqdr4ATbiDA7niD8MShpyqBmdpMWu7ng91grZPCDl7T/6xCrdT92NI7m CpnA5hBK/0W8+5Y8NnKjkwZym9H5kO18FQ+hH1mJq3bx57mxsZAE1Iwbr21W/Kxh 6Jx279ayywVAU6l9cH/aS5t3pl0qZUysBi3me2J88z6oYA3FNRaxX3kO4I8iJjYu vIfpWmXf8By/TOLzNkR1pJLXe849tAGrTtm+goLw59RMhIgxlS05DH3nGNKamWQ4 gr2H5do+2pFzKoom4vCryKgc/NXyEQNc/1FRJsi3/XK/NlezoPw+xV33AeDopmmK VsQ4RJONyVlgksCD2Q2odrCR/ryqirA5BTH8pQFfvCQfr4G6zkSzSDBTC9ZI2IIx JFs87mVpcu+0n+u482vdwsUAeByE3opA99MYrlrZDjLYl40Y0kzWHK42Is3iBz03 B4VFKUrsUXa5bcquYPkr1oVycamH1QTwXtgkU6DspAjuR3tUQT4i7sSEnoV8pGl0 gLWpGABxhGde0Z0V/x14BNFJ+ZG2uiUpLvMJshqBle1kIj+CqySQMc3mFpkdBTUZ nyVVuVRc6+oGGfBujOvqFKuS9rOhpCSBBVwbq5/lPSgtvy2uBiiTwlFLMgPvV66X xQGbbgTxOjIdrL1i6smD/6RXkbIMKOFb/o4NAgMBAAGjgcYwgcMwHQYDVR0OBBYE FKgE4SRwWu2cxDhjzef4eUmUnR3aMB8GA1UdIwQYMBaAFKgE4SRwWu2cxDhjzef4 eUmUnR3aMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgHmMB0GA1Ud JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA+BgNVHREENzA1hwR/AAABhxAAAAAA AAAAAAAAAAAAAAABhxAAAAAAAAAAAAAA//9/AAABgglsb2NhbGhvc3QwDQYJKoZI hvcNAQELBQADggIBAIsl4jTS2dbrt7CStvwInf8InjaGqOrj4c0HDYVYBi33JkHx WasCJbjs+YWsQYcK3/rE9iYyZA/cwIE89x2ec1JX42SrayPLIdUF5VSo+DP3knTH Si7zt3igmziyKTsLoliISwOKwF5mdc+qeOE8CuExi7xIV4xlJxfM+XW6aeHdskof KSTd4qqzyO+wMezKb8u9/b0rMGNCvaM1etcWNlrfP2SXayLAfFkKypSbER1uIUzg ZnhSGyfYee6DrIATihPyOofjbUbqfF7MJtDTqTLhqhkndF+T7IR2LcR4XdtkxtdT F1WwKcM2FX/cjpdtGX76U6hPD6uWXDISk8IiS8HX10x0wamlVvK3zz9UsWwQp5DD EjG/XtMU59oAyiiGIbZllUWKOOabCcId8dvYZw4zoObCrYiYb2qvPcJPyUOzcCPn wsOS22lgTqEfoNzlrmh39YI8pvNDh+t0SkK8Nhllm4o/hIQkIxYlqsp4IkCnyxpO dgRMt2H+98FCNLGs3EIkmaeKD42OyglvdzM0IYHT2VDRfhwpjPvSEw/lJyYIi3R0 BEWNGA9Jx+BKZRxmyOerUqCMmImwMoLtKudEHpWz5bXcUkmqsmGXaHabVW7Z3nfN ZwdSLNHgHLNYBGe6Ak198CFHGmP/9XbV41cGNXctfe92baDv5IMgWOi35X5w -----END CERTIFICATE----- thrift-0.19.0/test/dart/0000777000000000000000000000000014472652606015030 5ustar00rootroot00000000000000thrift-0.19.0/test/dart/test_client/0000777000000000000000000000000014454461475017347 5ustar00rootroot00000000000000thrift-0.19.0/test/dart/test_client/bin/0000777000000000000000000000000014303740367020110 5ustar00rootroot00000000000000thrift-0.19.0/test/dart/test_client/bin/main.dart0000644000000000000000000002373014303740367021711 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// 'License'); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:args/args.dart'; import 'package:collection/collection.dart'; import 'package:http/http.dart' as http; import 'package:thrift/thrift.dart'; import 'package:thrift/thrift_console.dart'; import 'package:thrift_test/thrift_test.dart'; const TEST_BASETYPES = 1; // 0000 0001 const TEST_STRUCTS = 2; // 0000 0010 const TEST_CONTAINERS = 4; // 0000 0100 const TEST_EXCEPTIONS = 8; // 0000 1000 const TEST_UNKNOWN = 64; // 0100 0000 (Failed to prepare environemt etc.) const TEST_TIMEOUT = 128; // 1000 0000 const TEST_NOTUSED = 48; // 0011 0000 (reserved bits) typedef Future FutureFunction(); class TTest { final int errorCode; final String name; final FutureFunction func; TTest(this.errorCode, this.name, this.func); } class TTestError extends Error { final actual; final expected; TTestError(this.actual, this.expected); String toString() => '$actual != $expected'; } List _tests; ThriftTestClient client; bool verbose; /// Adapted from TestClient.php main(List args) async { ArgResults results = _parseArgs(args); if (results == null) { exit(TEST_UNKNOWN); } verbose = results['verbose'] == true; await _initTestClient( host: results['host'], port: int.parse(results['port']), transportType: results['transport'], protocolType: results['protocol']).catchError((e) { stdout.writeln('Error:'); stdout.writeln('$e'); if (e is Error) { stdout.writeln('${e.stackTrace}'); } exit(TEST_UNKNOWN); }); // run tests _tests = _createTests(); int result = 0; for (TTest test in _tests) { if (verbose) stdout.write('${test.name}... '); try { await test.func(); if (verbose) stdout.writeln('success!'); } catch (e) { if (verbose) stdout.writeln('$e'); result = result | test.errorCode; } } exit(result); } ArgResults _parseArgs(List args) { var parser = new ArgParser(); parser.addOption('host', defaultsTo: 'localhost', help: 'The server host'); parser.addOption('port', defaultsTo: '9090', help: 'The port to connect to'); parser.addOption('transport', defaultsTo: 'buffered', allowed: ['buffered', 'framed', 'http'], help: 'The transport name', allowedHelp: { 'buffered': 'TBufferedTransport', 'framed': 'TFramedTransport' }); parser.addOption('protocol', defaultsTo: 'binary', allowed: ['binary', 'compact', 'json'], help: 'The protocol name', allowedHelp: { 'binary': 'TBinaryProtocol', 'compact': 'TCompactProtocol', 'json': 'TJsonProtocol' }); parser.addFlag('verbose', defaultsTo: true); ArgResults results; try { results = parser.parse(args); } catch (e) { stdout.writeln('$e\n'); } if (results == null) stdout.write(parser.usage); return results; } TProtocolFactory getProtocolFactory(String protocolType) { if (protocolType == 'binary') { return new TBinaryProtocolFactory(); } else if (protocolType == 'compact') { return new TCompactProtocolFactory(); } else if (protocolType == 'json') { return new TJsonProtocolFactory(); } throw new ArgumentError.value(protocolType); } Future _initTestClient( {String host, int port, String transportType, String protocolType}) async { TTransport transport; var protocolFactory = getProtocolFactory(protocolType); if (transportType == 'http') { var httpClient = new http.IOClient(); var uri = Uri.parse('http://$host:$port'); var config = new THttpConfig(uri, {}); transport = new THttpClientTransport(httpClient, config); } else { var socket = await Socket.connect(host, port); transport = new TClientSocketTransport(new TTcpSocket(socket)); if (transportType == 'framed') { transport = new TFramedTransport(transport); } } var protocol = protocolFactory.getProtocol(transport); client = new ThriftTestClient(protocol); await transport.open(); } List _createTests() { List tests = []; var xtruct = new Xtruct() ..string_thing = 'Zero' ..byte_thing = 1 ..i32_thing = -3 ..i64_thing = -5; tests.add(new TTest(TEST_BASETYPES, 'testVoid', () async { await client.testVoid(); })); tests.add(new TTest(TEST_BASETYPES, 'testString', () async { var input = 'Test'; var result = await client.testString(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_BASETYPES, 'testBool', () async { var input = true; var result = await client.testBool(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_BASETYPES, 'testByte', () async { var input = 64; var result = await client.testByte(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_BASETYPES, 'testI32', () async { var input = 2147483647; var result = await client.testI32(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_BASETYPES, 'testI64', () async { var input = 9223372036854775807; var result = await client.testI64(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_BASETYPES, 'testDouble', () async { var input = 3.1415926; var result = await client.testDouble(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_BASETYPES, 'testBinary', () async { var utf8Codec = const Utf8Codec(); var input = utf8Codec.encode('foo'); var result = await client.testBinary(input); var equality = const ListEquality(); if (!equality.equals(result, input)) throw new TTestError(result, input); })); tests.add(new TTest(TEST_CONTAINERS, 'testStruct', () async { var result = await client.testStruct(xtruct); if ('$result' != '$xtruct') throw new TTestError(result, xtruct); })); tests.add(new TTest(TEST_CONTAINERS, 'testNest', () async { var input = new Xtruct2() ..byte_thing = 1 ..struct_thing = xtruct ..i32_thing = -3; var result = await client.testNest(input); if ('$result' != '$input') throw new TTestError(result, input); })); tests.add(new TTest(TEST_CONTAINERS, 'testMap', () async { Map input = {1: -10, 2: -9, 3: -8, 4: -7, 5: -6}; var result = await client.testMap(input); var equality = const MapEquality(); if (!equality.equals(result, input)) throw new TTestError(result, input); })); tests.add(new TTest(TEST_CONTAINERS, 'testSet', () async { var input = new Set.from([-2, -1, 0, 1, 2]); var result = await client.testSet(input); var equality = const SetEquality(); if (!equality.equals(result, input)) throw new TTestError(result, input); })); tests.add(new TTest(TEST_CONTAINERS, 'testList', () async { var input = [-2, -1, 0, 1, 2]; var result = await client.testList(input); var equality = const ListEquality(); if (!equality.equals(result, input)) throw new TTestError(result, input); })); tests.add(new TTest(TEST_CONTAINERS, 'testEnum', () async { await _testEnum(Numberz.ONE); await _testEnum(Numberz.TWO); await _testEnum(Numberz.THREE); await _testEnum(Numberz.FIVE); await _testEnum(Numberz.EIGHT); })); tests.add(new TTest(TEST_BASETYPES, 'testTypedef', () async { var input = 309858235082523; var result = await client.testTypedef(input); if (result != input) throw new TTestError(result, input); })); tests.add(new TTest(TEST_CONTAINERS, 'testMapMap', () async { Map> result = await client.testMapMap(1); if (result.isEmpty || result[result.keys.first].isEmpty) { throw new TTestError(result, 'Map>'); } })); tests.add(new TTest(TEST_CONTAINERS, 'testInsanity', () async { var input = new Insanity(); input.userMap = {Numberz.FIVE: 5000}; input.xtructs = [xtruct]; Map> result = await client.testInsanity(input); if (result.isEmpty || result[result.keys.first].isEmpty) { throw new TTestError(result, 'Map>'); } })); tests.add(new TTest(TEST_CONTAINERS, 'testMulti', () async { var input = new Xtruct() ..string_thing = 'Hello2' ..byte_thing = 123 ..i32_thing = 456 ..i64_thing = 789; var result = await client.testMulti(input.byte_thing, input.i32_thing, input.i64_thing, {1: 'one'}, Numberz.EIGHT, 5678); if ('$result' != '$input') throw new TTestError(result, input); })); tests.add(new TTest(TEST_EXCEPTIONS, 'testException', () async { try { await client.testException('Xception'); } on Xception catch (_) { return; } throw new TTestError(null, 'Xception'); })); tests.add(new TTest(TEST_EXCEPTIONS, 'testMultiException', () async { try { await client.testMultiException('Xception2', 'foo'); } on Xception2 catch (_) { return; } throw new TTestError(null, 'Xception2'); })); return tests; } Future _testEnum(int input) async { var result = await client.testEnum(input); if (result != input) throw new TTestError(result, input); } thrift-0.19.0/test/dart/test_client/pubspec.yaml0000644000000000000000000000227114454461475021672 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # 'License'); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. name: thrift_test_client version: 0.19.0 description: A client integration test for the Dart Thrift library author: Apache Thrift Developers homepage: http://thrift.apache.org environment: sdk: ">=1.24.3 <3.0.0" dependencies: args: ">=0.13.0 <2.0.0" http: ^0.13.3 thrift: path: ../../../lib/dart thrift_test: path: ../gen-dart/thrift_test dev_dependencies: test: ">=0.12.30 <2.0.0" thrift-0.19.0/test/dart/Makefile.am0000644000000000000000000000327414370300523017047 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gen-dart/thrift_test/lib/thrift_test.dart: ../v0.16/ThriftTest.thrift $(THRIFT) --gen dart ../v0.16/ThriftTest.thrift pub-get-gen: gen-dart/thrift_test/lib/thrift_test.dart cd gen-dart/thrift_test; ${DARTPUB} get pub-get: pub-get-gen cd test_client; ${DARTPUB} get stubs: gen-dart/thrift_test/lib/thrift_test.dart pub-get precross: stubs check: stubs clean-local: $(RM) -r gen-dart/ test_client/.pub find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) dist-hook: $(RM) -r $(distdir)/gen-dart/ $(distdir)/test_client/.pub find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type d -name "packages" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) client: stubs ${DART} test_client/bin/main.dart EXTRA_DIST = \ test_client thrift-0.19.0/test/dart/Makefile0000644000000000000000000004506114472652606016472 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/dart/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/dart ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/dart abs_srcdir = /thrift/src/test/dart abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. EXTRA_DIST = \ test_client all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/dart/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/dart/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-dart/thrift_test/lib/thrift_test.dart: ../v0.16/ThriftTest.thrift $(THRIFT) --gen dart ../v0.16/ThriftTest.thrift pub-get-gen: gen-dart/thrift_test/lib/thrift_test.dart cd gen-dart/thrift_test; ${DARTPUB} get pub-get: pub-get-gen cd test_client; ${DARTPUB} get stubs: gen-dart/thrift_test/lib/thrift_test.dart pub-get precross: stubs check: stubs clean-local: $(RM) -r gen-dart/ test_client/.pub find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) dist-hook: $(RM) -r $(distdir)/gen-dart/ $(distdir)/test_client/.pub find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type d -name "packages" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) client: stubs ${DART} test_client/bin/main.dart # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/dart/Makefile.in0000644000000000000000000004417114472652520017073 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/dart ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ test_client all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/dart/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/dart/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile gen-dart/thrift_test/lib/thrift_test.dart: ../v0.16/ThriftTest.thrift $(THRIFT) --gen dart ../v0.16/ThriftTest.thrift pub-get-gen: gen-dart/thrift_test/lib/thrift_test.dart cd gen-dart/thrift_test; ${DARTPUB} get pub-get: pub-get-gen cd test_client; ${DARTPUB} get stubs: gen-dart/thrift_test/lib/thrift_test.dart pub-get precross: stubs check: stubs clean-local: $(RM) -r gen-dart/ test_client/.pub find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) dist-hook: $(RM) -r $(distdir)/gen-dart/ $(distdir)/test_client/.pub find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type d -name "packages" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) client: stubs ${DART} test_client/bin/main.dart # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/Include.thrift0000644000000000000000000000160314370300523016660 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ include "v0.16/ThriftTest.thrift" struct IncludeTest { 1: required ThriftTest.Bools bools }thrift-0.19.0/test/SmallTest.thrift0000644000000000000000000000306414303740367017222 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace rb TestNamespace struct Goodbyez { 1: i32 val = 325; } struct BoolPasser { 1: bool value = 1 } struct Hello { 1: i32 simple = 53, 2: map complex = {23:532, 6243:632, 2355:532}, 3: map> complexer, 4: string words = "words", 5: Goodbyez thinz = {'val' : 36632} } const map> CMAP = { 235: {235:235}, 53:{53:53} } const i32 CINT = 325; const Hello WHOA = {'simple' : 532} exception Goodbye { 1: i32 simple, 2: map complex, 3: map> complexer, } struct Thinger { 1: i32 dummy } service SmallService { Thinger testThinger(1:Thinger bootz), Hello testMe(1:i32 hello=64, 2: Hello wonk) throws (1: Goodbye g), void testVoid() throws (1: Goodbye g), i32 testI32(1:i32 boo) } thrift-0.19.0/test/tests.json0000644000000000000000000003154414370300523016117 0ustar00rootroot00000000000000[ { "name": "c_glib", "platforms": [ "Linux" ], "server": { "command": [ "test_server", "--lt-debug" ], "protocols": [ "binary:multi", "compact:multic" ] }, "client": { "command": [ "test_client", "--lt-debug" ], "protocols": [ "multi:binary", "multic:compact" ], "sockets": [ "ip-ssl" ] }, "transports": [ "buffered", "framed" ], "sockets": [ "ip", "domain" ], "protocols": [ "binary", "compact", "multi", "multic" ], "workdir": "c_glib" }, { "name": "cl", "server": { "command": ["TestServer"], "workdir": "cl", "protocols": ["binary", "multi"], "transports": ["buffered", "framed"], "sockets": ["ip"] }, "client": { "command": ["TestClient"], "workdir": "cl", "protocols": ["binary", "multi"], "transports": ["buffered", "framed"], "sockets": ["ip"] } }, { "name": "d", "server": { "command": [ "thrift_test_server", "--trace" ] }, "client": { "command": [ "thrift_test_client" ] }, "transports": [ "http", "buffered", "framed", "zlib" ], "sockets": [ "ip", "ip-ssl" ], "protocols": [ "binary", "compact", "json" ], "workdir": "../lib/d/test" }, { "name": "go", "server": { "command": [ "testserver", "--certPath=../../keys" ] }, "client": { "timeout": 6, "command": [ "testclient" ] }, "transports": [ "buffered", "framed", "http", "zlib" ], "sockets": [ "ip", "ip-ssl" ], "protocols": [ "binary", "compact", "json", "header" ], "workdir": "go/bin" }, { "name": "java", "join_args": false, "server": { "delay": 15, "command": [ "build/runserver" ], "protocols": [ "binary:multi", "compact:multic", "json:multij" ] }, "client": { "timeout": 13, "command": [ "build/runclient" ], "transports": [ "http" ], "protocols": [ "multi:binary", "multic:compact", "multij:json" ] }, "transports": [ "buffered", "framed", "framed:fastframed", "zlib" ], "sockets": [ "ip", "ip-ssl" ], "protocols": [ "binary", "compact", "json", "multi", "multic", "multij" ], "workdir": "../lib/java" }, { "name": "kotlin", "join_args": false, "server": { "delay": 15, "command": [ "cross-test-server/build/install/TestServer/bin/TestServer" ], "protocols": [ "binary" ] }, "client": { "timeout": 13, "command": [ "cross-test-client/build/install/TestClient/bin/TestClient" ], "transports": [ "framed" ], "protocols": [ "binary" ] }, "transports": [ "framed" ], "sockets": [ "ip" ], "protocols": [ "binary", "compact", "json" ], "workdir": "../lib/kotlin" }, { "name": "nodejs", "env": { "NODE_PATH": "../lib" }, "server": { "command": [ "node", "server.js", "--type=tcp" ] }, "client": { "timeout": 6, "command": [ "node", "client.js", "--type=tcp" ] }, "transports": [ "buffered", "framed", "http", "websocket" ], "sockets": [ "ip", "ip-ssl", "domain" ], "protocols": [ "compact", "binary", "json", "header" ], "workdir": "../lib/nodejs/test" }, { "name": "hs", "server": { "command": [ "TestServer" ] }, "client": { "timeout": 6, "transports": [ "http" ], "command": [ "TestClient" ] }, "transports": [ "buffered", "framed" ], "sockets": [ "ip" ], "protocols": [ "header", "compact", "binary", "json" ], "workdir": "hs" }, { "name": "py", "server": { "extra_args": ["TSimpleServer"], "command": [ "TestServer.py", "--verbose", "--genpydir=gen-py" ] }, "client": { "timeout": 10, "command": [ "TestClient.py", "--verbose", "--host=localhost", "--genpydir=gen-py" ] }, "transports": [ "buffered", "framed", "http", "zlib" ], "sockets": [ "ip", "ip-ssl", "domain" ], "protocols": [ "binary", "binary:accel", "compact", "compact:accelc", "header", "json", "multi", "multi:multia", "multia", "multiac", "multic", "multic:multiac", "multih", "multij" ], "workdir": "py" }, { "comment": "Using 'python3' executable to test py2 and 3 at once", "name": "py3", "server": { "extra_args": ["TSimpleServer"], "command": [ "python3", "TestServer.py", "--verbose", "--genpydir=gen-py" ] }, "client": { "timeout": 10, "command": [ "python3", "TestClient.py", "--host=localhost", "--genpydir=gen-py" ] }, "transports": [ "buffered", "framed", "http", "zlib" ], "sockets": [ "ip", "ip-ssl", "domain" ], "protocols": [ "binary", "binary:accel", "compact", "compact:accelc", "header", "json", "multi", "multi:multia", "multia", "multiac", "multic", "multic:multiac", "multih", "multij" ], "workdir": "py" }, { "name": "cpp", "server": { "command": [ "TestServer" ], "protocols": [ "binary:multi", "compact:multic", "header:multih", "json:multij" ] }, "client": { "timeout": 8, "command": [ "TestClient" ], "protocols": [ "multi:binary", "multic:compact", "multih:header", "multij:json" ] }, "transports": [ "buffered", "http", "framed", "zlib", "websocket" ], "sockets": [ "ip", "ip-ssl", "domain" ], "protocols": [ "compact", "binary", "json", "header", "multi", "multic", "multih", "multij" ], "workdir": "cpp" }, { "name": "rb", "server": { "command": [ "ruby", "../integration/TestServer.rb" ] }, "client": { "timeout": 10, "command": [ "ruby", "../integration/TestClient.rb", "--" ] }, "transports": [ "buffered", "framed" ], "sockets": [ "domain", "ip", "ip-ssl" ], "protocols": [ "binary", "binary:accel", "compact", "json" ], "workdir": "rb/gen-rb" }, { "name": "netstd", "transports": [ "buffered", "framed" ], "sockets": [ "ip", "ip-ssl" ], "protocols": [ "binary", "compact", "json" ], "server": { "command": [ "dotnet", "run", "--no-build", "--project=Server/Server.csproj", "server" ] }, "client": { "timeout": 10, "command": [ "dotnet", "run", "--no-build", "--project=Client/Client.csproj", "client" ] }, "workdir": "netstd" }, { "name": "perl", "transports": [ "buffered", "framed" ], "sockets": [ "ip", "ip-ssl", "domain" ], "protocols": [ "binary", "multi" ], "client": { "command": [ "perl", "-Igen-perl/", "-I../../lib/perl/lib/", "TestClient.pl", "--ca=../keys/CA.pem", "--cert=../keys/client.crt", "--key=../keys/client.key" ], "protocols": [ "multi:binary" ] }, "server": { "command": [ "perl", "-Igen-perl/", "-I../../lib/perl/lib/", "TestServer.pl", "--cert=../keys/server.crt", "--key=../keys/server.key" ], "protocols": [ "binary:multi" ] }, "workdir": "perl" }, { "name": "php", "client": { "timeout": 6, "transports": [ "buffered", "framed" ], "sockets": [ "ip" ], "protocols": [ "binary", "binary:accel", "compact", "json" ], "command": [ "php", "-dextension_dir=php_ext_dir", "--php-ini=test_php.ini", "--no-php-ini", "-ddisplay_errors=stderr", "-dlog_errors=0", "-derror_reporting=E_ALL", "TestClient.php" ] }, "workdir": "php" }, { "name": "dart", "client": { "timeout": 30, "transports": [ "buffered", "framed", "http" ], "sockets": [ "ip" ], "protocols": [ "binary", "compact", "json" ], "command": [ "dart", "--enable-asserts", "test_client/bin/main.dart", "--verbose" ] }, "workdir": "dart" }, { "name": "erl", "transports": [ "buffered", "framed" ], "sockets": [ "ip", "ip-ssl" ], "protocols": [ "binary", "compact" ], "client": { "command": [ "erl", "+K", "true", "-noshell", "-pa", "../../lib/erl/_build/default/lib/thrift/ebin/", "-pa", "./_build/default/lib/thrift_test/ebin", "-s", "test_client", "-s", "init", "stop", "-extra" ] }, "server": { "command": [ "erl", "+K", "true", "-noshell", "-pa", "../../lib/erl/_build/default/lib/thrift/ebin/", "-pa", "./_build/default/lib/thrift_test/ebin", "-s", "test_thrift_server", "-extra" ] }, "workdir": "erl" }, { "name": "js", "transports": [ "http" ], "sockets": [ "ip" ], "protocols": [ "json" ], "client": { "command": [ "phantomjs", "test/phantom-client.js" ] }, "workdir": "../lib/js" }, { "name": "lua", "TODO": "Add dll to LUA_CPATH", "env": { "LUA_PATH": ";;gen-lua/?.lua;../../lib/lua/?.lua", "LUA_CPATH": ";;../../lib/lua/.libs/?.so" }, "client": { "timeout": 5, "transports": [ "buffered", "framed", "http" ], "sockets": [ "ip" ], "protocols": [ "binary", "compact", "json" ], "command": [ "lua", "test_basic_client.lua" ] }, "workdir": "lua" }, { "name": "rs", "env": { "RUST_BACKTRACE": "1", "RUST_LOG": "info" }, "server": { "command": [ "test_server" ], "protocols": [ "binary:multi", "compact:multic" ] }, "client": { "timeout": 6, "command": [ "test_client" ], "protocols": [ "multi:binary", "multic:compact" ] }, "sockets": [ "ip", "domain" ], "transports": [ "buffered", "framed" ], "protocols": [ "binary", "compact", "multi", "multic" ], "workdir": "rs/bin" }, { "name": "nodets", "env": { "NODE_PATH": "../lib" }, "server": { "command": [ "runServer.sh" ] }, "client": { "timeout": 6, "command": [ "runClient.sh" ] }, "protocols": [ "binary" ], "sockets": [ "ip" ], "transports": [ "buffered" ], "workdir": "../lib/nodets/test" }, { "name": "swift", "server": { "command": ["TestServer"], "workdir": "swift/CrossTests/.build/x86_64-unknown-linux-gnu/debug", "protocols": ["binary", "compact"], "transports": ["buffered", "framed"], "sockets": ["ip"] }, "client": { "command": ["TestClient"], "workdir": "swift/CrossTests/.build/x86_64-unknown-linux-gnu/debug", "protocols": ["binary", "compact"], "transports": ["buffered", "framed"], "sockets": ["ip"] } } ] thrift-0.19.0/test/rs/0000777000000000000000000000000014472652607014523 5ustar00rootroot00000000000000thrift-0.19.0/test/rs/Makefile.am0000644000000000000000000000241414370300523016534 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # stubs: ../v0.16/ThriftTest.thrift $(THRIFT) -I ./thrifts -out src --gen rs ../v0.16/ThriftTest.thrift precross: stubs $(CARGO) build $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings [ -d bin ] || mkdir bin cp target/debug/test_server bin/test_server cp target/debug/test_client bin/test_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/thrift_test.rs -$(RM) -r bin EXTRA_DIST = \ Cargo.toml \ src/lib.rs \ src/bin/test_server.rs \ src/bin/test_client.rs thrift-0.19.0/test/rs/Makefile0000644000000000000000000004401014472652607016156 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/rs/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/rs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/rs abs_srcdir = /thrift/src/test/rs abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. EXTRA_DIST = \ Cargo.toml \ src/lib.rs \ src/bin/test_server.rs \ src/bin/test_client.rs all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/rs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/rs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../v0.16/ThriftTest.thrift $(THRIFT) -I ./thrifts -out src --gen rs ../v0.16/ThriftTest.thrift precross: stubs $(CARGO) build $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings [ -d bin ] || mkdir bin cp target/debug/test_server bin/test_server cp target/debug/test_client bin/test_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/thrift_test.rs -$(RM) -r bin # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/rs/Cargo.toml0000644000000000000000000000044614370300523016433 0ustar00rootroot00000000000000[package] name = "thrift-test" version = "0.1.0" edition = "2021" license = "Apache-2.0" authors = ["Apache Thrift Developers "] publish = false [dependencies] clap = "~2.33" bitflags = "=1.2" env_logger = "0.8" log = "0.4" [dependencies.thrift] path = "../../lib/rs" thrift-0.19.0/test/rs/src/0000777000000000000000000000000014370300523015272 5ustar00rootroot00000000000000thrift-0.19.0/test/rs/src/bin/0000777000000000000000000000000014370300523016042 5ustar00rootroot00000000000000thrift-0.19.0/test/rs/src/bin/test_server.rs0000644000000000000000000003231714370300523020757 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use clap::{clap_app, value_t}; use log::*; use std::collections::{BTreeMap, BTreeSet}; use std::thread; use std::time::Duration; use thrift::protocol::{ TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory, TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory, }; use thrift::server::{TMultiplexedProcessor, TServer}; use thrift::transport::{ TBufferedReadTransportFactory, TBufferedWriteTransportFactory, TFramedReadTransportFactory, TFramedWriteTransportFactory, TReadTransportFactory, TWriteTransportFactory, }; use thrift::OrderedFloat; use thrift_test::*; fn main() { env_logger::init(); debug!("initialized logger - running cross-test server"); match run() { Ok(()) => info!("cross-test server succeeded"), Err(e) => { info!("cross-test server failed with error {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { // unsupported options: // --pipe // --ssl let matches = clap_app!(rust_test_client => (version: "1.0") (author: "Apache Thrift Developers ") (about: "Rust Thrift test server") (@arg port: --port +takes_value "port on which the test server listens") (@arg domain_socket: --("domain-socket") +takes_value "Unix Domain Socket on which the test server listens") (@arg transport: --transport +takes_value "transport implementation to use (\"buffered\", \"framed\")") (@arg protocol: --protocol +takes_value "protocol implementation to use (\"binary\", \"compact\")") (@arg server_type: --("server-type") +takes_value "type of server instantiated (\"simple\", \"thread-pool\")") (@arg workers: -n --workers +takes_value "number of thread-pool workers (\"4\")") ) .get_matches(); let port = value_t!(matches, "port", u16).unwrap_or(9090); let domain_socket = matches.value_of("domain_socket"); let transport = matches.value_of("transport").unwrap_or("buffered"); let protocol = matches.value_of("protocol").unwrap_or("binary"); let server_type = matches.value_of("server_type").unwrap_or("thread-pool"); let workers = value_t!(matches, "workers", usize).unwrap_or(4); let listen_address = format!("127.0.0.1:{}", port); match domain_socket { None => info!("Server is binding to {}", listen_address), Some(domain_socket) => info!("Server is binding to {} (UDS)", domain_socket), } let (i_transport_factory, o_transport_factory): ( Box, Box, ) = match &*transport { "buffered" => ( Box::new(TBufferedReadTransportFactory::new()), Box::new(TBufferedWriteTransportFactory::new()), ), "framed" => ( Box::new(TFramedReadTransportFactory::new()), Box::new(TFramedWriteTransportFactory::new()), ), unknown => { return Err(format!("unsupported transport type {}", unknown).into()); } }; let (i_protocol_factory, o_protocol_factory): ( Box, Box, ) = match &*protocol { "binary" | "multi" | "multi:binary" => ( Box::new(TBinaryInputProtocolFactory::new()), Box::new(TBinaryOutputProtocolFactory::new()), ), "compact" | "multic" | "multi:compact" => ( Box::new(TCompactInputProtocolFactory::new()), Box::new(TCompactOutputProtocolFactory::new()), ), unknown => { return Err(format!("unsupported transport type {}", unknown).into()); } }; let test_processor = ThriftTestSyncProcessor::new(ThriftTestSyncHandlerImpl {}); match &*server_type { "simple" | "thread-pool" => { if protocol == "multi" || protocol == "multic" { let second_service_processor = SecondServiceSyncProcessor::new(SecondServiceSyncHandlerImpl {}); let mut multiplexed_processor = TMultiplexedProcessor::new(); multiplexed_processor.register("ThriftTest", Box::new(test_processor), true)?; multiplexed_processor.register( "SecondService", Box::new(second_service_processor), false, )?; let mut server = TServer::new( i_transport_factory, i_protocol_factory, o_transport_factory, o_protocol_factory, multiplexed_processor, workers, ); match domain_socket { None => server.listen(&listen_address), Some(domain_socket) => server.listen_uds(domain_socket), } } else { let mut server = TServer::new( i_transport_factory, i_protocol_factory, o_transport_factory, o_protocol_factory, test_processor, workers, ); match domain_socket { None => server.listen(&listen_address), Some(domain_socket) => server.listen_uds(domain_socket), } } } unknown => Err(format!("unsupported server type {}", unknown).into()), } } struct ThriftTestSyncHandlerImpl; impl ThriftTestSyncHandler for ThriftTestSyncHandlerImpl { fn handle_test_void(&self) -> thrift::Result<()> { info!("testVoid()"); Ok(()) } fn handle_test_string(&self, thing: String) -> thrift::Result { info!("testString({})", &thing); Ok(thing) } fn handle_test_bool(&self, thing: bool) -> thrift::Result { info!("testBool({})", thing); Ok(thing) } fn handle_test_byte(&self, thing: i8) -> thrift::Result { info!("testByte({})", thing); Ok(thing) } fn handle_test_i32(&self, thing: i32) -> thrift::Result { info!("testi32({})", thing); Ok(thing) } fn handle_test_i64(&self, thing: i64) -> thrift::Result { info!("testi64({})", thing); Ok(thing) } fn handle_test_double(&self, thing: OrderedFloat) -> thrift::Result> { info!("testDouble({})", thing); Ok(thing) } fn handle_test_binary(&self, thing: Vec) -> thrift::Result> { info!("testBinary({:?})", thing); Ok(thing) } fn handle_test_struct(&self, thing: Xtruct) -> thrift::Result { info!("testStruct({:?})", thing); Ok(thing) } fn handle_test_nest(&self, thing: Xtruct2) -> thrift::Result { info!("testNest({:?})", thing); Ok(thing) } fn handle_test_map(&self, thing: BTreeMap) -> thrift::Result> { info!("testMap({:?})", thing); Ok(thing) } fn handle_test_string_map( &self, thing: BTreeMap, ) -> thrift::Result> { info!("testStringMap({:?})", thing); Ok(thing) } fn handle_test_set(&self, thing: BTreeSet) -> thrift::Result> { info!("testSet({:?})", thing); Ok(thing) } fn handle_test_list(&self, thing: Vec) -> thrift::Result> { info!("testList({:?})", thing); Ok(thing) } fn handle_test_enum(&self, thing: Numberz) -> thrift::Result { info!("testEnum({:?})", thing); Ok(thing) } fn handle_test_typedef(&self, thing: UserId) -> thrift::Result { info!("testTypedef({})", thing); Ok(thing) } /// @return map> - returns a dictionary with these values: /// {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 => /// 2, 3 => 3, 4 => 4, }, } fn handle_test_map_map(&self, hello: i32) -> thrift::Result>> { info!("testMapMap({})", hello); let mut inner_map_0: BTreeMap = BTreeMap::new(); for i in -4..0_i32 { inner_map_0.insert(i, i); } let mut inner_map_1: BTreeMap = BTreeMap::new(); for i in 1..5 { inner_map_1.insert(i, i); } let mut ret_map: BTreeMap> = BTreeMap::new(); ret_map.insert(-4, inner_map_0); ret_map.insert(4, inner_map_1); Ok(ret_map) } /// Creates a the returned map with these values and prints it out: /// { 1 => { 2 => argument, /// 3 => argument, /// }, /// 2 => { 6 => , }, /// } /// return map> - a map with the above values fn handle_test_insanity( &self, argument: Insanity, ) -> thrift::Result>> { info!("testInsanity({:?})", argument); let mut map_0: BTreeMap = BTreeMap::new(); map_0.insert(Numberz::TWO, argument.clone()); map_0.insert(Numberz::THREE, argument); let mut map_1: BTreeMap = BTreeMap::new(); let insanity = Insanity { user_map: None, xtructs: None, }; map_1.insert(Numberz::SIX, insanity); let mut ret: BTreeMap> = BTreeMap::new(); ret.insert(1, map_0); ret.insert(2, map_1); Ok(ret) } /// returns an Xtruct with: /// string_thing = "Hello2", byte_thing = arg0, i32_thing = arg1 and /// i64_thing = arg2 fn handle_test_multi( &self, arg0: i8, arg1: i32, arg2: i64, _: BTreeMap, _: Numberz, _: UserId, ) -> thrift::Result { let x_ret = Xtruct { string_thing: Some("Hello2".to_owned()), byte_thing: Some(arg0), i32_thing: Some(arg1), i64_thing: Some(arg2), }; Ok(x_ret) } /// if arg == "Xception" throw Xception with errorCode = 1001 and message = /// arg /// else if arg == "TException" throw TException /// else do not throw anything fn handle_test_exception(&self, arg: String) -> thrift::Result<()> { info!("testException({})", arg); match &*arg { "Xception" => Err((Xception { error_code: Some(1001), message: Some(arg), }) .into()), "TException" => Err("this is a random error".into()), _ => Ok(()), } } /// if arg0 == "Xception": /// throw Xception with errorCode = 1001 and message = "This is an /// Xception" /// else if arg0 == "Xception2": /// throw Xception2 with errorCode = 2002 and struct_thing.string_thing = /// "This is an Xception2" // else: // do not throw anything and return Xtruct with string_thing = arg1 fn handle_test_multi_exception(&self, arg0: String, arg1: String) -> thrift::Result { match &*arg0 { "Xception" => Err((Xception { error_code: Some(1001), message: Some("This is an Xception".to_owned()), }) .into()), "Xception2" => Err((Xception2 { error_code: Some(2002), struct_thing: Some(Xtruct { string_thing: Some("This is an Xception2".to_owned()), byte_thing: None, i32_thing: None, i64_thing: None, }), }) .into()), _ => Ok(Xtruct { string_thing: Some(arg1), byte_thing: None, i32_thing: None, i64_thing: None, }), } } fn handle_test_oneway(&self, seconds_to_sleep: i32) -> thrift::Result<()> { thread::sleep(Duration::from_secs(seconds_to_sleep as u64)); Ok(()) } } struct SecondServiceSyncHandlerImpl; impl SecondServiceSyncHandler for SecondServiceSyncHandlerImpl { fn handle_secondtest_string(&self, thing: String) -> thrift::Result { info!("(second)testString({})", &thing); let ret = format!("testString(\"{}\")", &thing); Ok(ret) } } thrift-0.19.0/test/rs/src/bin/test_client.rs0000644000000000000000000005236714370300523020736 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use clap::{clap_app, value_t}; use log::*; use std::collections::{BTreeMap, BTreeSet}; use std::fmt::Debug; use std::net::{TcpStream, ToSocketAddrs}; #[cfg(unix)] use std::os::unix::net::UnixStream; #[cfg(unix)] use std::path::Path; use thrift::protocol::{ TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol, TInputProtocol, TMultiplexedOutputProtocol, TOutputProtocol, }; use thrift::transport::{ TBufferedReadTransport, TBufferedWriteTransport, TFramedReadTransport, TFramedWriteTransport, TIoChannel, TReadTransport, TTcpChannel, TWriteTransport, }; use thrift::OrderedFloat; use thrift_test::*; type ThriftClientPair = ( ThriftTestSyncClient, Box>, Option, Box>>, ); fn main() { env_logger::init(); debug!("initialized logger - running cross-test client"); match run() { Ok(()) => info!("cross-test client succeeded"), Err(e) => { info!("cross-test client failed with error {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { // unsupported options: // --pipe // --anon-pipes // --ssl // --threads let matches = clap_app!(rust_test_client => (version: "1.0") (author: "Apache Thrift Developers ") (about: "Rust Thrift test client") (@arg host: --host +takes_value "Host on which the Thrift test server is located") (@arg port: --port +takes_value "Port on which the Thrift test server is listening") (@arg domain_socket: --("domain-socket") +takes_value "Unix Domain Socket on which the Thrift test server is listening") (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\", \"multi\", \"multic\")") (@arg transport: --transport +takes_value "Thrift transport implementation to use (\"buffered\", \"framed\")") (@arg testloops: -n --testloops +takes_value "Number of times to run tests") ) .get_matches(); let host = matches.value_of("host").unwrap_or("127.0.0.1"); let port = value_t!(matches, "port", u16).unwrap_or(9090); let domain_socket = matches.value_of("domain_socket"); let protocol = matches.value_of("protocol").unwrap_or("binary"); let transport = matches.value_of("transport").unwrap_or("buffered"); let testloops = value_t!(matches, "testloops", u8).unwrap_or(1); let (mut thrift_test_client, mut second_service_client) = match domain_socket { None => { let listen_address = format!("{}:{}", host, port); info!( "Client binds to {} with {}+{} stack", listen_address, protocol, transport ); bind(listen_address.as_str(), protocol, transport)? } Some(domain_socket) => { info!( "Client binds to {} (UDS) with {}+{} stack", domain_socket, protocol, transport ); bind_uds(domain_socket, protocol, transport)? } }; for _ in 0..testloops { make_thrift_calls(&mut thrift_test_client, &mut second_service_client)? } Ok(()) } fn bind( listen_address: A, protocol: &str, transport: &str, ) -> Result { // create a TCPStream that will be shared by all Thrift clients // service calls from multiple Thrift clients will be interleaved over the same connection // this isn't a problem for us because we're single-threaded and all calls block to completion let shared_stream = TcpStream::connect(listen_address)?; let second_service_client = if protocol.starts_with("multi") { let shared_stream_clone = shared_stream.try_clone()?; let channel = TTcpChannel::with_stream(shared_stream_clone); let (i_prot, o_prot) = build(channel, transport, protocol, "SecondService")?; Some(SecondServiceSyncClient::new(i_prot, o_prot)) } else { None }; let thrift_test_client = { let channel = TTcpChannel::with_stream(shared_stream); let (i_prot, o_prot) = build(channel, transport, protocol, "ThriftTest")?; ThriftTestSyncClient::new(i_prot, o_prot) }; Ok((thrift_test_client, second_service_client)) } #[cfg(unix)] fn bind_uds>( domain_socket: P, protocol: &str, transport: &str, ) -> Result { // create a UnixStream that will be shared by all Thrift clients // service calls from multiple Thrift clients will be interleaved over the same connection // this isn't a problem for us because we're single-threaded and all calls block to completion let shared_stream = UnixStream::connect(domain_socket)?; let second_service_client = if protocol.starts_with("multi") { let shared_stream_clone = shared_stream.try_clone()?; let (i_prot, o_prot) = build(shared_stream_clone, transport, protocol, "SecondService")?; Some(SecondServiceSyncClient::new(i_prot, o_prot)) } else { None }; let thrift_test_client = { let (i_prot, o_prot) = build(shared_stream, transport, protocol, "ThriftTest")?; ThriftTestSyncClient::new(i_prot, o_prot) }; Ok((thrift_test_client, second_service_client)) } fn build( channel: C, transport: &str, protocol: &str, service_name: &str, ) -> thrift::Result<(Box, Box)> { let (i_chan, o_chan) = channel.split()?; let (i_tran, o_tran): (Box, Box) = match transport { "buffered" => ( Box::new(TBufferedReadTransport::new(i_chan)), Box::new(TBufferedWriteTransport::new(o_chan)), ), "framed" => ( Box::new(TFramedReadTransport::new(i_chan)), Box::new(TFramedWriteTransport::new(o_chan)), ), unmatched => return Err(format!("unsupported transport {}", unmatched).into()), }; let (i_prot, o_prot): (Box, Box) = match protocol { "binary" => ( Box::new(TBinaryInputProtocol::new(i_tran, true)), Box::new(TBinaryOutputProtocol::new(o_tran, true)), ), "multi" => ( Box::new(TBinaryInputProtocol::new(i_tran, true)), Box::new(TMultiplexedOutputProtocol::new( service_name, TBinaryOutputProtocol::new(o_tran, true), )), ), "compact" => ( Box::new(TCompactInputProtocol::new(i_tran)), Box::new(TCompactOutputProtocol::new(o_tran)), ), "multic" => ( Box::new(TCompactInputProtocol::new(i_tran)), Box::new(TMultiplexedOutputProtocol::new( service_name, TCompactOutputProtocol::new(o_tran), )), ), unmatched => return Err(format!("unsupported protocol {}", unmatched).into()), }; Ok((i_prot, o_prot)) } type BuildThriftTestClient = ThriftTestSyncClient, Box>; type BuiltSecondServiceClient = SecondServiceSyncClient, Box>; #[allow(clippy::cognitive_complexity)] fn make_thrift_calls( thrift_test_client: &mut BuildThriftTestClient, second_service_client: &mut Option, ) -> Result<(), thrift::Error> { info!("testVoid"); thrift_test_client.test_void()?; info!("testString"); verify_expected_result( thrift_test_client.test_string("thing".to_owned()), "thing".to_owned(), )?; info!("testBool"); verify_expected_result(thrift_test_client.test_bool(true), true)?; info!("testBool"); verify_expected_result(thrift_test_client.test_bool(false), false)?; info!("testByte"); verify_expected_result(thrift_test_client.test_byte(42), 42)?; info!("testi32"); verify_expected_result(thrift_test_client.test_i32(1_159_348_374), 1_159_348_374)?; info!("testi64"); // try!(verify_expected_result(thrift_test_client.test_i64(-8651829879438294565), // -8651829879438294565)); verify_expected_result( thrift_test_client.test_i64(i64::min_value()), i64::min_value(), )?; info!("testDouble"); verify_expected_result( thrift_test_client.test_double(OrderedFloat::from(42.42)), OrderedFloat::from(42.42), )?; info!("testTypedef"); { let u_snd: UserId = 2348; let u_cmp: UserId = 2348; verify_expected_result(thrift_test_client.test_typedef(u_snd), u_cmp)?; } info!("testEnum"); { verify_expected_result(thrift_test_client.test_enum(Numberz::TWO), Numberz::TWO)?; } info!("testBinary"); { let b_snd = vec![0x77, 0x30, 0x30, 0x74, 0x21, 0x20, 0x52, 0x75, 0x73, 0x74]; let b_cmp = vec![0x77, 0x30, 0x30, 0x74, 0x21, 0x20, 0x52, 0x75, 0x73, 0x74]; verify_expected_result(thrift_test_client.test_binary(b_snd), b_cmp)?; } info!("testStruct"); { let x_snd = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(12), i32_thing: Some(219_129), i64_thing: Some(12_938_492_818), }; let x_cmp = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(12), i32_thing: Some(219_129), i64_thing: Some(12_938_492_818), }; verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)?; } // Xtruct again, with optional values // FIXME: apparently the erlang thrift server does not like opt-in-req-out // parameters that are undefined. Joy. // { // let x_snd = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: None, // i32_thing: None, i64_thing: Some(12938492818) }; // let x_cmp = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: // Some(0), i32_thing: Some(0), i64_thing: Some(12938492818) }; // the C++ // server is responding correctly // try!(verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)); // } // info!("testNest"); // (FIXME: try Xtruct2 with optional values) { let x_snd = Xtruct2 { byte_thing: Some(32), struct_thing: Some(Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(1), i32_thing: Some(324_382_098), i64_thing: Some(12_938_492_818), }), i32_thing: Some(293_481_098), }; let x_cmp = Xtruct2 { byte_thing: Some(32), struct_thing: Some(Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(1), i32_thing: Some(324_382_098), i64_thing: Some(12_938_492_818), }), i32_thing: Some(293_481_098), }; verify_expected_result(thrift_test_client.test_nest(x_snd), x_cmp)?; } // do the multiplexed calls while making the main ThriftTest calls if let Some(ref mut client) = second_service_client.as_mut() { info!("SecondService secondtestString"); { verify_expected_result( client.secondtest_string("test_string".to_owned()), "testString(\"test_string\")".to_owned(), )?; } } info!("testList"); { let v_snd: Vec = vec![29384, 238, 32498]; let v_cmp: Vec = vec![29384, 238, 32498]; verify_expected_result(thrift_test_client.test_list(v_snd), v_cmp)?; } info!("testSet"); { let s_snd: BTreeSet = BTreeSet::from([293_481, 23, 3234]); let s_cmp: BTreeSet = BTreeSet::from([293_481, 23, 3234]); verify_expected_result(thrift_test_client.test_set(s_snd), s_cmp)?; } info!("testMap"); { let m_snd: BTreeMap = BTreeMap::from([(2, 4), (4, 6), (8, 7)]); let m_cmp: BTreeMap = BTreeMap::from([(2, 4), (4, 6), (8, 7)]); verify_expected_result(thrift_test_client.test_map(m_snd), m_cmp)?; } info!("testStringMap"); { let m_snd: BTreeMap = BTreeMap::from([ ("2".to_owned(), "4_string".to_owned()), ("4".to_owned(), "6_string".to_owned()), ("8".to_owned(), "7_string".to_owned()), ]); let m_rcv: BTreeMap = BTreeMap::from([ ("2".to_owned(), "4_string".to_owned()), ("4".to_owned(), "6_string".to_owned()), ("8".to_owned(), "7_string".to_owned()), ]); verify_expected_result(thrift_test_client.test_string_map(m_snd), m_rcv)?; } // nested map // expect : {-4 => {-4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => {1 => 1, 2 // => 2, 3 => 3, 4 => 4, }, } info!("testMapMap"); { let m_cmp_nested_0: BTreeMap = (-4..0).map(|i| (i, i)).collect(); let m_cmp_nested_1: BTreeMap = (1..5).map(|i| (i, i)).collect(); let m_cmp: BTreeMap> = BTreeMap::from([(-4, m_cmp_nested_0), (4, m_cmp_nested_1)]); verify_expected_result(thrift_test_client.test_map_map(42), m_cmp)?; } info!("testMulti"); { let m_snd: BTreeMap = BTreeMap::from([(1298, "fizz".to_owned()), (-148, "buzz".to_owned())]); let s_cmp = Xtruct { string_thing: Some("Hello2".to_owned()), byte_thing: Some(1), i32_thing: Some(-123_948), i64_thing: Some(-19_234_123_981), }; verify_expected_result( thrift_test_client.test_multi(1, -123_948, -19_234_123_981, m_snd, Numberz::EIGHT, 81), s_cmp, )?; } // Insanity // returns: // { 1 => { 2 => argument, // 3 => argument, // }, // 2 => { 6 => , }, // } { let arg_map_usermap: BTreeMap = BTreeMap::from([(Numberz::ONE, 4289), (Numberz::EIGHT, 19)]); let arg_vec_xtructs: Vec = vec![ Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(8), i32_thing: Some(29), i64_thing: Some(92384), }, Xtruct { string_thing: Some("bar".to_owned()), byte_thing: Some(28), i32_thing: Some(2), i64_thing: Some(-1281), }, Xtruct { string_thing: Some("baz".to_owned()), byte_thing: Some(0), i32_thing: Some(3_948_539), i64_thing: Some(-12_938_492), }, ]; let insanity = Insanity { user_map: Some(arg_map_usermap), xtructs: Some(arg_vec_xtructs), }; let s_cmp_nested_1: BTreeMap = BTreeMap::from([ (Numberz::TWO, insanity.clone()), (Numberz::THREE, insanity.clone()), ]); let empty_insanity = Insanity { user_map: Some(BTreeMap::new()), xtructs: Some(Vec::new()), }; let s_cmp_nested_2: BTreeMap = BTreeMap::from([(Numberz::SIX, empty_insanity)]); let s_cmp: BTreeMap> = BTreeMap::from([(1, s_cmp_nested_1), (2, s_cmp_nested_2)]); verify_expected_result(thrift_test_client.test_insanity(insanity), s_cmp)?; } info!("testException - remote throws Xception"); { let r = thrift_test_client.test_exception("Xception".to_owned()); let x = match r { Err(thrift::Error::User(ref e)) => match e.downcast_ref::() { Some(x) => Ok(x), None => Err(thrift::Error::User( "did not get expected Xception struct".into(), )), }, _ => Err(thrift::Error::User("did not get exception".into())), }?; let x_cmp = Xception { error_code: Some(1001), message: Some("Xception".to_owned()), }; verify_expected_result(Ok(x), &x_cmp)?; } info!("testException - remote throws TApplicationException"); { let r = thrift_test_client.test_exception("TException".to_owned()); match r { Err(thrift::Error::Application(ref e)) => { info!("received an {:?}", e); Ok(()) } _ => Err(thrift::Error::User("did not get exception".into())), }?; } info!("testException - remote succeeds"); { let r = thrift_test_client.test_exception("foo".to_owned()); match r { Ok(_) => Ok(()), _ => Err(thrift::Error::User("received an exception".into())), }?; } info!("testMultiException - remote throws Xception"); { let r = thrift_test_client.test_multi_exception("Xception".to_owned(), "ignored".to_owned()); let x = match r { Err(thrift::Error::User(ref e)) => match e.downcast_ref::() { Some(x) => Ok(x), None => Err(thrift::Error::User( "did not get expected Xception struct".into(), )), }, _ => Err(thrift::Error::User("did not get exception".into())), }?; let x_cmp = Xception { error_code: Some(1001), message: Some("This is an Xception".to_owned()), }; verify_expected_result(Ok(x), &x_cmp)?; } info!("testMultiException - remote throws Xception2"); { let r = thrift_test_client.test_multi_exception("Xception2".to_owned(), "ignored".to_owned()); let x = match r { Err(thrift::Error::User(ref e)) => match e.downcast_ref::() { Some(x) => Ok(x), None => Err(thrift::Error::User( "did not get expected Xception struct".into(), )), }, _ => Err(thrift::Error::User("did not get exception".into())), }?; let x_cmp = Xception2 { error_code: Some(2002), struct_thing: Some(Xtruct { string_thing: Some("This is an Xception2".to_owned()), // since this is an OPT_IN_REQ_OUT field the sender sets a default byte_thing: Some(0), // since this is an OPT_IN_REQ_OUT field the sender sets a default i32_thing: Some(0), // since this is an OPT_IN_REQ_OUT field the sender sets a default i64_thing: Some(0), }), }; verify_expected_result(Ok(x), &x_cmp)?; } info!("testMultiException - remote succeeds"); { let r = thrift_test_client.test_multi_exception("haha".to_owned(), "RETURNED".to_owned()); let x = match r { Err(e) => Err(thrift::Error::User( format!("received an unexpected exception {:?}", e).into(), )), _ => r, }?; let x_cmp = Xtruct { string_thing: Some("RETURNED".to_owned()), // since this is an OPT_IN_REQ_OUT field the sender sets a default byte_thing: Some(0), // since this is an OPT_IN_REQ_OUT field the sender sets a default i32_thing: Some(0), // since this is an OPT_IN_REQ_OUT field the sender sets a default i64_thing: Some(0), }; verify_expected_result(Ok(x), x_cmp)?; } info!("testOneWay - remote sleeps for 1 second"); { thrift_test_client.test_oneway(1)?; } // final test to verify that the connection is still writable after the one-way // call thrift_test_client.test_void() } fn verify_expected_result( actual: Result, expected: T, ) -> Result<(), thrift::Error> { info!("*** EXPECTED: Ok({:?})", expected); info!("*** ACTUAL : {:?}", actual); match actual { Ok(v) => { if v == expected { info!("*** OK ***"); Ok(()) } else { info!("*** FAILED ***"); Err(thrift::Error::User( format!("expected {:?} but got {:?}", &expected, &v).into(), )) } } Err(e) => Err(e), } } thrift-0.19.0/test/rs/src/lib.rs0000644000000000000000000000176514370300523016413 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // FIXME - need changes in gen before lifting this exception #![allow( clippy::match_single_binding, clippy::unnecessary_wraps, clippy::derivable_impls )] mod thrift_test; pub use crate::thrift_test::*; thrift-0.19.0/test/rs/Makefile.in0000644000000000000000000004312614472652521016565 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/rs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ Cargo.toml \ src/lib.rs \ src/bin/test_server.rs \ src/bin/test_client.rs all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/rs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/rs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../v0.16/ThriftTest.thrift $(THRIFT) -I ./thrifts -out src --gen rs ../v0.16/ThriftTest.thrift precross: stubs $(CARGO) build $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings [ -d bin ] || mkdir bin cp target/debug/test_server bin/test_server cp target/debug/test_client bin/test_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/thrift_test.rs -$(RM) -r bin # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/rb/0000777000000000000000000000000014472652607014502 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/Makefile.am0000644000000000000000000000221614370300523016513 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # stubs: $(THRIFT) ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen rb ../v0.16/ThriftTest.thrift $(THRIFT) --gen rb ../SmallTest.thrift $(THRIFT) --gen rb ../Recursive.thrift precross: stubs check: stubs if HAVE_BUNDLER $(BUNDLER) install $(BUNDLER) exec $(RUBY) -I. test_suite.rb endif clean-local: $(RM) -r gen-rb/ dist-hook: $(RM) -r $(distdir)/gen-rb/ thrift-0.19.0/test/rb/test_helper.rb0000644000000000000000000000232514303740367017335 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.unshift File.dirname(__FILE__) + '/gen-rb' $:.unshift File.join(File.dirname(__FILE__), '../../lib/rb/lib') $:.unshift File.join(File.dirname(__FILE__), '../../lib/rb/ext') require 'test/unit' module Thrift module Struct def ==(other) return false unless other.is_a? self.class self.class.const_get(:FIELDS).collect {|fid, data| data[:name] }.all? do |field| send(field) == other.send(field) end end end end thrift-0.19.0/test/rb/test_suite.rb0000644000000000000000000000151014303740367017202 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # Dir["{core,generation}/**/*.rb"].each {|f| require f }thrift-0.19.0/test/rb/Makefile0000644000000000000000000004374114472652607016147 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/rb/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/rb ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/rb abs_srcdir = /thrift/src/test/rb abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/rb/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/rb/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: $(THRIFT) ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen rb ../v0.16/ThriftTest.thrift $(THRIFT) --gen rb ../SmallTest.thrift $(THRIFT) --gen rb ../Recursive.thrift precross: stubs check: stubs $(BUNDLER) install $(BUNDLER) exec $(RUBY) -I. test_suite.rb clean-local: $(RM) -r gen-rb/ dist-hook: $(RM) -r $(distdir)/gen-rb/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/rb/generation/0000777000000000000000000000000014303740367016627 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/generation/test_enum.rb0000644000000000000000000000237514303740367021162 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.join(File.dirname(__FILE__), '../test_helper') require 'thrift_test' class TestEnumGeneration < Test::Unit::TestCase include Thrift::Test def test_enum_valid_values assert_equal(Numberz::VALID_VALUES, Set.new([Numberz::ONE, Numberz::TWO, Numberz::THREE, Numberz::FIVE, Numberz::SIX, Numberz::EIGHT])) end def test_enum_hash Numberz::VALID_VALUES.each do |value| assert_equal(Numberz.const_get(Numberz::VALUE_MAP[value].to_sym), value) end end endthrift-0.19.0/test/rb/generation/test_struct.rb0000644000000000000000000000302614303740367021534 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.join(File.dirname(__FILE__), '../test_helper') require 'small_service' class TestStructGeneration < Test::Unit::TestCase def test_default_values hello = TestNamespace::Hello.new assert_kind_of(TestNamespace::Hello, hello) assert_nil(hello.complexer) assert_equal(hello.simple, 53) assert_equal(hello.words, 'words') assert_kind_of(TestNamespace::Goodbyez, hello.thinz) assert_equal(hello.thinz.val, 36632) assert_kind_of(Hash, hello.complex) assert_equal(hello.complex, { 6243 => 632, 2355 => 532, 23 => 532}) bool_passer = TestNamespace::BoolPasser.new(:value => false) assert_equal false, bool_passer.value end def test_goodbyez assert_equal(TestNamespace::Goodbyez.new.val, 325) end end thrift-0.19.0/test/rb/generation/test_recursive.rb0000644000000000000000000000260514303740367022221 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.join(File.dirname(__FILE__), '../test_helper') require 'recursive_types' class TestRecursiveGeneration < Test::Unit::TestCase CHILD_ITEM = "child item" PARENT_ITEM = "parent item" def test_can_create_recursive_tree child_tree = RecTree.new child_tree.item = CHILD_ITEM parent_tree = RecTree.new parent_tree.item = PARENT_ITEM parent_tree.children = [child_tree] assert_equal(PARENT_ITEM, parent_tree.item) assert_equal(1, parent_tree.children.length) assert_equal(CHILD_ITEM, parent_tree.children.first.item) assert_nil(parent_tree.children.first.children) end end thrift-0.19.0/test/rb/integration/0000777000000000000000000000000014062750227017015 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/integration/TestServer.rb0000777000000000000000000001250214062750227021453 0ustar00rootroot00000000000000#!/usr/bin/env ruby # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.push File.dirname(__FILE__) + '/..' require 'test_helper' require 'thrift' require 'thrift_test' require 'thrift_test_types' class SimpleHandler [:testVoid, :testString, :testBool, :testByte, :testI32, :testI64, :testDouble, :testBinary, :testStruct, :testMap, :testStringMap, :testSet, :testList, :testNest, :testEnum, :testTypedef, :testEnum, :testTypedef, :testMultiException].each do |meth| define_method(meth) do |thing| p meth p thing thing end end def testVoid() end def testInsanity(thing) return { 1 => { 2 => thing, 3 => thing }, 2 => { 6 => Thrift::Test::Insanity::new() } } end def testMapMap(thing) return { -4 => { -4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => { 4 => 4, 3 => 3, 2 => 2, 1 => 1, } } end def testMulti(arg0, arg1, arg2, arg3, arg4, arg5) return Thrift::Test::Xtruct.new({ 'string_thing' => 'Hello2', 'byte_thing' => arg0, 'i32_thing' => arg1, 'i64_thing' => arg2, }) end def testException(thing) if thing == "Xception" raise Thrift::Test::Xception, :errorCode => 1001, :message => thing elsif thing == "TException" raise Thrift::Exception, :message => thing else # no-op end end def testMultiException(arg0, arg1) if arg0 == "Xception2" raise Thrift::Test::Xception2, :errorCode => 2002, :struct_thing => ::Thrift::Test::Xtruct.new({ :string_thing => 'This is an Xception2' }) elsif arg0 == "Xception" raise Thrift::Test::Xception, :errorCode => 1001, :message => 'This is an Xception' else return ::Thrift::Test::Xtruct.new({'string_thing' => arg1}) end end def testOneway(arg0) sleep(arg0) end end domain_socket = nil port = 9090 protocol = "binary" @protocolFactory = nil ssl = false transport = "buffered" @transportFactory = nil ARGV.each do|a| if a == "--help" puts "Allowed options:" puts "\t -h [ --help ] \t produce help message" puts "\t--domain-socket arg (=) \t Unix domain socket path" puts "\t--port arg (=9090) \t Port number to listen \t not valid with domain-socket" puts "\t--protocol arg (=binary) \t protocol: accel, binary, compact, json" puts "\t--ssl \t use ssl \t not valid with domain-socket" puts "\t--transport arg (=buffered) transport: buffered, framed, http" exit elsif a.start_with?("--domain-socket") domain_socket = a.split("=")[1] elsif a.start_with?("--protocol") protocol = a.split("=")[1] elsif a == "--ssl" ssl = true elsif a.start_with?("--transport") transport = a.split("=")[1] elsif a.start_with?("--port") port = a.split("=")[1].to_i end end if protocol == "binary" || protocol.to_s.strip.empty? @protocolFactory = Thrift::BinaryProtocolFactory.new elsif protocol == "compact" @protocolFactory = Thrift::CompactProtocolFactory.new elsif protocol == "json" @protocolFactory = Thrift::JsonProtocolFactory.new elsif protocol == "accel" @protocolFactory = Thrift::BinaryProtocolAcceleratedFactory.new else raise 'Unknown protocol type' end if transport == "buffered" || transport.to_s.strip.empty? @transportFactory = Thrift::BufferedTransportFactory.new elsif transport == "framed" @transportFactory = Thrift::FramedTransportFactory.new else raise 'Unknown transport type' end @handler = SimpleHandler.new @processor = Thrift::Test::ThriftTest::Processor.new(@handler) @transport = nil if domain_socket.to_s.strip.empty? if ssl # the working directory for ruby crosstest is test/rb/gen-rb keysDir = File.join(File.dirname(File.dirname(Dir.pwd)), "keys") ctx = OpenSSL::SSL::SSLContext.new ctx.ca_file = File.join(keysDir, "CA.pem") ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keysDir, "server.crt"))) ctx.cert_store = OpenSSL::X509::Store.new ctx.cert_store.add_file(File.join(keysDir, 'client.pem')) ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keysDir, "server.key"))) ctx.options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 ctx.ssl_version = :SSLv23 ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER @transport = Thrift::SSLServerSocket.new(nil, port, ctx) else @transport = Thrift::ServerSocket.new(port) end else @transport = Thrift::UNIXServerSocket.new(domain_socket) end @server = Thrift::ThreadedServer.new(@processor, @transport, @transportFactory, @protocolFactory) puts "Starting TestServer #{@server.to_s}" @server.serve puts "done." thrift-0.19.0/test/rb/integration/TestClient.rb0000777000000000000000000003025514062750227021430 0ustar00rootroot00000000000000#!/usr/bin/env ruby # encoding: utf-8 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.push File.dirname(__FILE__) + '/..' require 'test_helper' require 'thrift' require 'thrift_test' $domain_socket = nil $host = "localhost" $port = 9090 $protocolType = "binary" $ssl = false $transport = "buffered" ARGV.each do|a| if a == "--help" puts "Allowed options:" puts "\t -h [ --help ] \t produce help message" puts "\t--domain-socket arg (=) \t Unix domain socket path" puts "\t--host arg (=localhost) \t Host to connect \t not valid with domain-socket" puts "\t--port arg (=9090) \t Port number to listen \t not valid with domain-socket" puts "\t--protocol arg (=binary) \t protocol: accel, binary, compact, json" puts "\t--ssl \t use ssl \t not valid with domain-socket" puts "\t--transport arg (=buffered) transport: buffered, framed, http" exit elsif a.start_with?("--domain-socket") $domain_socket = a.split("=")[1] elsif a.start_with?("--host") $host = a.split("=")[1] elsif a.start_with?("--protocol") $protocolType = a.split("=")[1] elsif a == "--ssl" $ssl = true elsif a.start_with?("--transport") $transport = a.split("=")[1] elsif a.start_with?("--port") $port = a.split("=")[1].to_i end end class SimpleClientTest < Test::Unit::TestCase def setup unless @socket if $domain_socket.to_s.strip.empty? if $ssl # the working directory for ruby crosstest is test/rb/gen-rb keysDir = File.join(File.dirname(File.dirname(Dir.pwd)), "keys") ctx = OpenSSL::SSL::SSLContext.new ctx.ca_file = File.join(keysDir, "CA.pem") ctx.cert = OpenSSL::X509::Certificate.new(File.open(File.join(keysDir, "client.crt"))) ctx.cert_store = OpenSSL::X509::Store.new ctx.cert_store.add_file(File.join(keysDir, 'server.pem')) ctx.key = OpenSSL::PKey::RSA.new(File.open(File.join(keysDir, "client.key"))) ctx.options = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 ctx.ssl_version = :SSLv23 ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER @socket = Thrift::SSLSocket.new($host, $port, nil, ctx) else @socket = Thrift::Socket.new($host, $port) end else @socket = Thrift::UNIXSocket.new($domain_socket) end if $transport == "buffered" transportFactory = Thrift::BufferedTransport.new(@socket) elsif $transport == "framed" transportFactory = Thrift::FramedTransport.new(@socket) else raise 'Unknown transport type' end if $protocolType == "binary" @protocol = Thrift::BinaryProtocol.new(transportFactory) elsif $protocolType == "compact" @protocol = Thrift::CompactProtocol.new(transportFactory) elsif $protocolType == "json" @protocol = Thrift::JsonProtocol.new(transportFactory) elsif $protocolType == "accel" @protocol = Thrift::BinaryProtocolAccelerated.new(transportFactory) else raise 'Unknown protocol type' end @client = Thrift::Test::ThriftTest::Client.new(@protocol) @socket.open end end def teardown @socket.close end def test_void p 'test_void' @client.testVoid() end def test_string p 'test_string' test_string = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><' + ' char-to-test-json-parsing: ]] \"]] \\" }}}{ [[[ ' test_string = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " + "Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, " + "БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, " + "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, " + "Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, " + "Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, " + "Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, " + "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " + "Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, " + "Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, " + "Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, " + "ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, " + "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " + "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa " + "Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa " + "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" + "Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, " + "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " + "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " + "РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " + "English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, " + "Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " + "Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, " + "Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " + "Bân-lâm-gú, 粵語" result_string = @client.testString(test_string) assert_equal(test_string, result_string.force_encoding(Encoding::UTF_8)) end def test_bool p 'test_bool' assert_equal(@client.testBool(true), true) assert_equal(@client.testBool(false), false) end def test_byte p 'test_byte' val = 120 assert_equal(@client.testByte(val), val) assert_equal(@client.testByte(-val), -val) end def test_i32 p 'test_i32' val = 2000000032 assert_equal(@client.testI32(val), val) assert_equal(@client.testI32(-val), -val) end def test_i64 p 'test_i64' val = 9000000000000000064 assert_equal(@client.testI64(val), val) assert_equal(@client.testI64(-val), -val) end def test_double p 'test_double' val = 3.14159265358979323846 assert_equal(@client.testDouble(val), val) assert_equal(@client.testDouble(-val), -val) assert_kind_of(Float, @client.testDouble(val)) end def test_binary p 'test_binary' val = (0...256).reverse_each.to_a ret = @client.testBinary(val.pack('C*')) assert_equal(val, ret.bytes.to_a) end def test_map p 'test_map' val = {1 => 1, 2 => 2, 3 => 3} assert_equal(@client.testMap(val), val) assert_kind_of(Hash, @client.testMap(val)) end def test_string_map p 'test_string_map' val = {'a' => '2', 'b' => 'blah', 'some' => 'thing'} ret = @client.testStringMap(val) assert_equal(val, ret) assert_kind_of(Hash, ret) end def test_list p 'test_list' val = [1,2,3,4,5] assert_equal(@client.testList(val), val) assert_kind_of(Array, @client.testList(val)) end def test_enum p 'test_enum' val = Thrift::Test::Numberz::SIX ret = @client.testEnum(val) assert_equal(ret, 6) assert_kind_of(Fixnum, ret) end def test_typedef p 'test_typedef' #UserId testTypedef(1: UserId thing), assert_equal(@client.testTypedef(309858235082523), 309858235082523) assert_kind_of(Fixnum, @client.testTypedef(309858235082523)) true end def test_set p 'test_set' val = Set.new([1,2,3]) assert_equal(@client.testSet(val), val) assert_kind_of(Set, @client.testSet(val)) end def get_struct Thrift::Test::Xtruct.new({'string_thing' => 'hi!', 'i32_thing' => 4 }) end def test_struct p 'test_struct' ret = @client.testStruct(get_struct) # TODO: not sure what unspecified "default" requiredness values should be assert(ret.byte_thing == nil || ret.byte_thing == 0) assert(ret.i64_thing == nil || ret.i64_thing == 0) assert_equal(ret.string_thing, 'hi!') assert_equal(ret.i32_thing, 4) assert_kind_of(Thrift::Test::Xtruct, ret) end def test_nest p 'test_nest' struct2 = Thrift::Test::Xtruct2.new({'struct_thing' => get_struct, 'i32_thing' => 10}) ret = @client.testNest(struct2) # TODO: not sure what unspecified "default" requiredness values should be assert(ret.struct_thing.byte_thing == nil || ret.struct_thing.byte_thing == 0) assert(ret.struct_thing.i64_thing == nil || ret.struct_thing.i64_thing == 0) assert_equal(ret.struct_thing.string_thing, 'hi!') assert_equal(ret.struct_thing.i32_thing, 4) assert_equal(ret.i32_thing, 10) assert_kind_of(Thrift::Test::Xtruct, ret.struct_thing) assert_kind_of(Thrift::Test::Xtruct2, ret) end def test_insanity p 'test_insanity' insane = Thrift::Test::Insanity.new({ 'userMap' => { Thrift::Test::Numberz::FIVE => 5, Thrift::Test::Numberz::EIGHT => 8, }, 'xtructs' => [ Thrift::Test::Xtruct.new({ 'string_thing' => 'Goodbye4', 'byte_thing' => 4, 'i32_thing' => 4, 'i64_thing' => 4, }), Thrift::Test::Xtruct.new({ 'string_thing' => 'Hello2', 'byte_thing' => 2, 'i32_thing' => 2, 'i64_thing' => 2, }) ] }) ret = @client.testInsanity(insane) assert_equal(insane, ret[1][2]) assert_equal(insane, ret[1][3]) assert(ret[2][6].userMap == nil || ret[2][6].userMap.length == 0) assert(ret[2][6].xtructs == nil || ret[2][6].xtructs.length == 0) end def test_map_map p 'test_map_map' ret = @client.testMapMap(4) assert_kind_of(Hash, ret) expected = { -4 => { -4 => -4, -3 => -3, -2 => -2, -1 => -1, }, 4 => { 4 => 4, 3 => 3, 2 => 2, 1 => 1, } } assert_equal(expected, ret) end def test_multi p 'test_multi' ret = @client.testMulti(42, 4242, 424242, {1 => 'blah', 2 => 'thing'}, Thrift::Test::Numberz::EIGHT, 24) expected = Thrift::Test::Xtruct.new({ :string_thing => 'Hello2', :byte_thing => 42, :i32_thing => 4242, :i64_thing => 424242 }) assert_equal(expected, ret) end def test_exception p 'test_exception' assert_raise Thrift::Test::Xception do @client.testException('Xception') end begin @client.testException('TException') rescue => e assert e.class.ancestors.include?(Thrift::Exception) end assert_nothing_raised do @client.testException('test') end end def test_multi_exception p 'test_multi_exception' assert_raise Thrift::Test::Xception do @client.testMultiException("Xception", "test 1") end assert_raise Thrift::Test::Xception2 do @client.testMultiException("Xception2", "test 2") end assert_equal( @client.testMultiException("Success", "test 3").string_thing, "test 3") end def test_oneway p 'test_oneway' time1 = Time.now.to_f @client.testOneway(1) time2 = Time.now.to_f assert_operator (time2-time1), :<, 0.1 end end thrift-0.19.0/test/rb/Gemfile0000644000000000000000000000023214303740367015760 0ustar00rootroot00000000000000source "http://rubygems.org" require "rubygems" gem 'rack', '~> 2.0', '>= 2.0.4' gem 'thin', '~> 1.7', '>= 1.7.2' gem 'test-unit', '~> 3.2', '>= 3.2.7' thrift-0.19.0/test/rb/fixtures/0000777000000000000000000000000014303740367016345 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/fixtures/structs.rb0000644000000000000000000002441314303740367020401 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'thrift' module Fixtures module Structs class OneBool include Thrift::Struct attr_accessor :bool FIELDS = { 1 => {:type => Thrift::Types::BOOL, :name => 'bool'} } def validate end end class OneByte include Thrift::Struct attr_accessor :byte FIELDS = { 1 => {:type => Thrift::Types::BYTE, :name => 'byte'} } def validate end end class OneI16 include Thrift::Struct attr_accessor :i16 FIELDS = { 1 => {:type => Thrift::Types::I16, :name => 'i16'} } def validate end end class OneI32 include Thrift::Struct attr_accessor :i32 FIELDS = { 1 => {:type => Thrift::Types::I32, :name => 'i32'} } def validate end end class OneI64 include Thrift::Struct attr_accessor :i64 FIELDS = { 1 => {:type => Thrift::Types::I64, :name => 'i64'} } def validate end end class OneDouble include Thrift::Struct attr_accessor :double FIELDS = { 1 => {:type => Thrift::Types::DOUBLE, :name => 'double'} } def validate end end class OneString include Thrift::Struct attr_accessor :string FIELDS = { 1 => {:type => Thrift::Types::STRING, :name => 'string'} } def validate end end class OneMap include Thrift::Struct attr_accessor :map FIELDS = { 1 => {:type => Thrift::Types::MAP, :name => 'map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRING}} } def validate end end class NestedMap include Thrift::Struct attr_accessor :map FIELDS = { 0 => {:type => Thrift::Types::MAP, :name => 'map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::I32}}} } def validate end end class OneList include Thrift::Struct attr_accessor :list FIELDS = { 1 => {:type => Thrift::Types::LIST, :name => 'list', :element => {:type => Thrift::Types::STRING}} } def validate end end class NestedList include Thrift::Struct attr_accessor :list FIELDS = { 0 => {:type => Thrift::Types::LIST, :name => 'list', :element => {:type => Thrift::Types::LIST, :element => { :type => Thrift::Types::I32 } } } } def validate end end class OneSet include Thrift::Struct attr_accessor :set FIELDS = { 1 => {:type => Thrift::Types::SET, :name => 'set', :element => {:type => Thrift::Types::STRING}} } def validate end end class NestedSet include Thrift::Struct attr_accessor :set FIELDS = { 1 => {:type => Thrift::Types::SET, :name => 'set', :element => {:type => Thrift::Types::SET, :element => { :type => Thrift::Types::STRING } }} } def validate end end # struct OneOfEach { # 1: bool im_true, # 2: bool im_false, # 3: byte a_bite, # 4: i16 integer16, # 5: i32 integer32, # 6: i64 integer64, # 7: double double_precision, # 8: string some_characters, # 9: string zomg_unicode, # 10: bool what_who, # 11: binary base64, # } class OneOfEach include Thrift::Struct attr_accessor :im_true, :im_false, :a_bite, :integer16, :integer32, :integer64, :double_precision, :some_characters, :zomg_unicode, :what_who, :base64 FIELDS = { 1 => {:type => Thrift::Types::BOOL, :name => 'im_true'}, 2 => {:type => Thrift::Types::BOOL, :name => 'im_false'}, 3 => {:type => Thrift::Types::BYTE, :name => 'a_bite'}, 4 => {:type => Thrift::Types::I16, :name => 'integer16'}, 5 => {:type => Thrift::Types::I32, :name => 'integer32'}, 6 => {:type => Thrift::Types::I64, :name => 'integer64'}, 7 => {:type => Thrift::Types::DOUBLE, :name => 'double_precision'}, 8 => {:type => Thrift::Types::STRING, :name => 'some_characters'}, 9 => {:type => Thrift::Types::STRING, :name => 'zomg_unicode'}, 10 => {:type => Thrift::Types::BOOL, :name => 'what_who'}, 11 => {:type => Thrift::Types::STRING, :name => 'base64'} } # Added for assert_equal def ==(other) [:im_true, :im_false, :a_bite, :integer16, :integer32, :integer64, :double_precision, :some_characters, :zomg_unicode, :what_who, :base64].each do |f| var = "@#{f}" return false if instance_variable_get(var) != other.instance_variable_get(var) end true end def validate end end # struct Nested1 { # 1: list a_list # 2: map i32_map # 3: map i64_map # 4: map dbl_map # 5: map str_map # } class Nested1 include Thrift::Struct attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map FIELDS = { 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}}, 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => OneOfEach}} } def validate end end # struct Nested2 { # 1: list a_list # 2: map i32_map # 3: map i64_map # 4: map dbl_map # 5: map str_map # } class Nested2 include Thrift::Struct attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map FIELDS = { 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => Nested1}}, 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}}, 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}}, 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}}, 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => Nested1}} } def validate end end # struct Nested3 { # 1: list a_list # 2: map i32_map # 3: map i64_map # 4: map dbl_map # 5: map str_map # } class Nested3 include Thrift::Struct attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map FIELDS = { 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => Nested2}}, 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}}, 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}}, 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}}, 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => Nested2}} } def validate end end # struct Nested4 { # 1: list a_list # 2: map i32_map # 3: map i64_map # 4: map dbl_map # 5: map str_map # } class Nested4 include Thrift::Struct attr_accessor :a_list, :i32_map, :i64_map, :dbl_map, :str_map FIELDS = { 1 => {:type => Thrift::Types::LIST, :name => 'a_list', :element => {:type => Thrift::Types::STRUCT, :class => Nested3}}, 2 => {:type => Thrift::Types::MAP, :name => 'i32_map', :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}}, 3 => {:type => Thrift::Types::MAP, :name => 'i64_map', :key => {:type => Thrift::Types::I64}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}}, 4 => {:type => Thrift::Types::MAP, :name => 'dbl_map', :key => {:type => Thrift::Types::DOUBLE}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}}, 5 => {:type => Thrift::Types::MAP, :name => 'str_map', :key => {:type => Thrift::Types::STRING}, :value => {:type => Thrift::Types::STRUCT, :class => Nested3}} } def validate end end end end thrift-0.19.0/test/rb/core/0000777000000000000000000000000014303740367015424 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/core/test_exceptions.rb0000644000000000000000000000201614303740367021164 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.join(File.dirname(__FILE__), '../test_helper') require 'thrift' class TestException < Test::Unit::TestCase def test_has_accessible_message msg = "hi there thrift" assert_equal msg, Thrift::Exception.new(msg).message end end thrift-0.19.0/test/rb/core/test_backwards_compatability.rb0000644000000000000000000000202414303740367023664 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.join(File.dirname(__FILE__), '../test_helper') require 'thrift' class TestThriftException < Test::Unit::TestCase def test_has_accessible_message msg = "hi there thrift" assert_equal msg, Thrift::Exception.new(msg).message end end thrift-0.19.0/test/rb/core/transport/0000777000000000000000000000000014303740367017460 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/core/transport/test_transport.rb0000644000000000000000000000350114303740367023073 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.join(File.dirname(__FILE__), '../../test_helper') require 'thrift' class DummyTransport < Thrift::BaseTransport def initialize(data) @data = data end def read(size) @data.slice!(0, size) end end # TTransport is basically an abstract class, but isn't raising NotImplementedError class TestThriftTransport < Test::Unit::TestCase def setup @trans = Thrift::BaseTransport.new end def test_open? assert_nil @trans.open? end def test_open assert_nil @trans.open end def test_close assert_nil @trans.close end # TODO: # This doesn't necessarily test he right thing. # It _looks_ like read isn't guaranteed to return the length # you ask for and read_all is. This means our test needs to check # for blocking. -- Kevin Clark 3/27/08 def test_read_all # Implements read t = DummyTransport.new("hello") assert_equal "hello", t.read_all(5) end def test_write assert_nil @trans.write(5) # arbitrary value end def test_flush assert_nil @trans.flush end end thrift-0.19.0/test/rb/benchmarks/0000777000000000000000000000000014303740367016611 5ustar00rootroot00000000000000thrift-0.19.0/test/rb/benchmarks/protocol_benchmark.rb0000644000000000000000000001075114303740367023011 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. .. .. lib rb lib]) $LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w[.. .. .. lib rb ext]) require 'thrift' require 'benchmark' require 'rubygems' require 'set' require 'pp' # require 'ruby-debug' # require 'ruby-prof' require File.join(File.dirname(__FILE__), '../fixtures/structs') transport1 = Thrift::MemoryBuffer.new ruby_binary_protocol = Thrift::BinaryProtocol.new(transport1) transport2 = Thrift::MemoryBuffer.new c_fast_binary_protocol = Thrift::BinaryProtocolAccelerated.new(transport2) ooe = Fixtures::Structs::OneOfEach.new ooe.im_true = true ooe.im_false = false ooe.a_bite = -42 ooe.integer16 = 27000 ooe.integer32 = 1<<24 ooe.integer64 = 6000 * 1000 * 1000 ooe.double_precision = Math::PI ooe.some_characters = "Debug THIS!" ooe.zomg_unicode = "\xd7\n\a\t" n1 = Fixtures::Structs::Nested1.new n1.a_list = [] n1.a_list << ooe << ooe << ooe << ooe n1.i32_map = {} n1.i32_map[1234] = ooe n1.i32_map[46345] = ooe n1.i32_map[-34264] = ooe n1.i64_map = {} n1.i64_map[43534986783945] = ooe n1.i64_map[-32434639875122] = ooe n1.dbl_map = {} n1.dbl_map[324.65469834] = ooe n1.dbl_map[-9458672340.4986798345112] = ooe n1.str_map = {} n1.str_map['sdoperuix'] = ooe n1.str_map['pwoerxclmn'] = ooe n2 = Fixtures::Structs::Nested2.new n2.a_list = [] n2.a_list << n1 << n1 << n1 << n1 << n1 n2.i32_map = {} n2.i32_map[398345] = n1 n2.i32_map[-2345] = n1 n2.i32_map[12312] = n1 n2.i64_map = {} n2.i64_map[2349843765934] = n1 n2.i64_map[-123234985495] = n1 n2.i64_map[0] = n1 n2.dbl_map = {} n2.dbl_map[23345345.38927834] = n1 n2.dbl_map[-1232349.5489345] = n1 n2.dbl_map[-234984574.23498725] = n1 n2.str_map = {} n2.str_map[''] = n1 n2.str_map['sdflkertpioux'] = n1 n2.str_map['sdfwepwdcjpoi'] = n1 n3 = Fixtures::Structs::Nested3.new n3.a_list = [] n3.a_list << n2 << n2 << n2 << n2 << n2 n3.i32_map = {} n3.i32_map[398345] = n2 n3.i32_map[-2345] = n2 n3.i32_map[12312] = n2 n3.i64_map = {} n3.i64_map[2349843765934] = n2 n3.i64_map[-123234985495] = n2 n3.i64_map[0] = n2 n3.dbl_map = {} n3.dbl_map[23345345.38927834] = n2 n3.dbl_map[-1232349.5489345] = n2 n3.dbl_map[-234984574.23498725] = n2 n3.str_map = {} n3.str_map[''] = n2 n3.str_map['sdflkertpioux'] = n2 n3.str_map['sdfwepwdcjpoi'] = n2 n4 = Fixtures::Structs::Nested4.new n4.a_list = [] n4.a_list << n3 n4.i32_map = {} n4.i32_map[-2345] = n3 n4.i64_map = {} n4.i64_map[2349843765934] = n3 n4.dbl_map = {} n4.dbl_map[-1232349.5489345] = n3 n4.str_map = {} n4.str_map[''] = n3 # prof = RubyProf.profile do # n4.write(c_fast_binary_protocol) # Fixtures::Structs::Nested4.new.read(c_fast_binary_protocol) # end # # printer = RubyProf::GraphHtmlPrinter.new(prof) # printer.print(STDOUT, :min_percent=>0) Benchmark.bmbm do |x| x.report("ruby write large (1MB) structure once") do n4.write(ruby_binary_protocol) end x.report("ruby read large (1MB) structure once") do Fixtures::Structs::Nested4.new.read(ruby_binary_protocol) end x.report("c write large (1MB) structure once") do n4.write(c_fast_binary_protocol) end x.report("c read large (1MB) structure once") do Fixtures::Structs::Nested4.new.read(c_fast_binary_protocol) end x.report("ruby write 10_000 small structures") do 10_000.times do ooe.write(ruby_binary_protocol) end end x.report("ruby read 10_000 small structures") do 10_000.times do Fixtures::Structs::OneOfEach.new.read(ruby_binary_protocol) end end x.report("c write 10_000 small structures") do 10_000.times do ooe.write(c_fast_binary_protocol) end end x.report("c read 10_000 small structures") do 10_000.times do Fixtures::Structs::OneOfEach.new.read(c_fast_binary_protocol) end end end thrift-0.19.0/test/rb/Makefile.in0000644000000000000000000004312514472652521016543 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/rb ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/rb/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/rb/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: $(THRIFT) ../v0.16/ThriftTest.thrift ../SmallTest.thrift $(THRIFT) --gen rb ../v0.16/ThriftTest.thrift $(THRIFT) --gen rb ../SmallTest.thrift $(THRIFT) --gen rb ../Recursive.thrift precross: stubs check: stubs @HAVE_BUNDLER_TRUE@ $(BUNDLER) install @HAVE_BUNDLER_TRUE@ $(BUNDLER) exec $(RUBY) -I. test_suite.rb clean-local: $(RM) -r gen-rb/ dist-hook: $(RM) -r $(distdir)/gen-rb/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/cl/0000777000000000000000000000000014472652606014474 5ustar00rootroot00000000000000thrift-0.19.0/test/cl/make-test-client.lisp0000644000000000000000000000752014370300523020514 0ustar00rootroot00000000000000(in-package #:cl-user) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. #+(or) (when (not (boundp 'sb-impl::default-external-format) (setf sb-impl::default-external-format :UTF-8))) (require "asdf") (load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) (require "sb-grovel") ;; necessary for :net.didierverna.clon.termio (asdf:load-asd (first (directory (merge-pathnames "../../lib/cl/externals/software/clon-*/termio/net.didierverna.clon.termio.asd" *load-truename*)))) (asdf:load-system :net.didierverna.clon) (asdf:load-system :fiasco) (asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*)) (asdf:load-system :thrift-gen-thrifttest) (net.didierverna.clon:nickname-package) (defpackage #:thrift-cross (:use #:common-lisp #:fiasco) (:export #:cross-test)) (in-package #:thrift-cross) (defparameter *prot* nil) (load (merge-pathnames "tests.lisp" *load-truename*) :external-format :UTF-8) (clon:defsynopsis () (text :contents "The Common Lisp client for Thrift's cross-language test suite.") (group (:header "Allowed options:") (flag :short-name "h" :long-name "help" :description "Print this help and exit.") (stropt :long-name "host" :description "The host to connect to." :default-value "localhost" :argument-name "ARG") (stropt :long-name "port" :description "Number of the port to listen for connections on." :default-value "9090" :argument-name "ARG" :argument-type :optional) (stropt :long-name "transport" :description "Transport: transport to use (\"buffered\", \"framed\")" :default-value "buffered" :argument-name "ARG") (stropt :long-name "protocol" :description "Protocol: protocol to use (\"binary\", \"multi\")" :default-value "binary" :argument-name "ARG"))) (defun main () "Entry point for our standalone application." (clon:make-context) (when (clon:getopt :short-name "h") (clon:help) (clon:exit)) (let ((port "9090") (host "localhost") (framed nil) (multiplexed nil)) (clon:do-cmdline-options (option name value source) (print (list option name value source)) (if (string= name "host") (setf host value)) (if (string= name "port") (setf port value)) (if (string= name "transport") (cond ((string= value "buffered") (setf framed nil)) ((string= value "framed") (setf framed t)) (t (error "Unsupported transport.")))) (if (string= name "protocol") (cond ((string= value "binary") (setf multiplexed nil)) ((string= value "multi") (setf multiplexed t)) (t (error "Unsupported protocol."))))) (terpri) (setf *prot* (thrift.implementation::client (puri:parse-uri (concatenate 'string "thrift://" host ":" port)) :framed framed :multiplexed multiplexed)) (let ((result (cross-test :multiplexed multiplexed))) (thrift.implementation::close *prot*) (clon:exit result)))) (clon:dump "TestClient" main) thrift-0.19.0/test/cl/Makefile.am0000755000000000000000000000235214370300523016512 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: ../ThriftTest.thrift $(THRIFT) --gen cl ../ThriftTest.thrift TestServer: make-test-server.lisp $(SBCL) --script make-test-server.lisp TestClient: make-test-client.lisp $(SBCL) --script make-test-client.lisp precross: stubs TestServer TestClient clean-local: $(RM) -r gen-cl $(RM) TestServer $(RM) TestClient EXTRA_DIST = \ implementation.lisp \ make-test-client.lisp \ make-test-server.lisp \ tests.lisp thrift-0.19.0/test/cl/make-test-server.lisp0000644000000000000000000000703514370300523020545 0ustar00rootroot00000000000000(in-package #:cl-user) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (require "asdf") (load (merge-pathnames "../../lib/cl/load-locally.lisp" *load-truename*)) (require "sb-grovel") ;; necessary for :net.didierverna.clon.termio (asdf:load-asd (first (directory (merge-pathnames "../../lib/cl/externals/software/clon-*/termio/net.didierverna.clon.termio.asd" *load-truename*)))) (asdf:load-system :net.didierverna.clon) (asdf:load-asd (merge-pathnames "gen-cl/ThriftTest/thrift-gen-ThriftTest.asd" *load-truename*)) (asdf:load-system :thrift-gen-thrifttest) (load (merge-pathnames "implementation.lisp" *load-truename*)) (net.didierverna.clon:nickname-package) (clon:defsynopsis () (text :contents "The Common Lisp server for Thrift's cross-language test suite.") (group (:header "Allowed options:") (flag :short-name "h" :long-name "help" :description "Print this help and exit.") (stropt :long-name "port" :description "Number of the port to listen for connections on." :default-value "9090" :argument-name "ARG" :argument-type :optional) (stropt :long-name "server-type" :description "The type of server, currently only \"simple\" is available." :default-value "simple" :argument-name "ARG") (stropt :long-name "transport" :description "Transport: transport to use (\"buffered\" or \"framed\")" :default-value "buffered" :argument-name "ARG") (stropt :long-name "protocol" :description "Protocol: protocol to use (\"binary\" or \"multi\")" :default-value "binary" :argument-name "ARG"))) (defun main () "Entry point for our standalone application." (clon:make-context) (when (clon:getopt :short-name "h") (clon:help) (clon:exit)) (let ((port "9090") (framed nil) (multiplexed nil)) (clon:do-cmdline-options (option name value source) (print (list option name value source)) (if (string= name "port") (setf port value)) (if (string= name "transport") (cond ((string= value "buffered") (setf framed nil)) ((string= value "framed") (setf framed t)) (t (error "Unsupported transport.")))) (if (string= name "protocol") (cond ((string= value "binary") (setf multiplexed nil)) ((string= value "multi") (setf multiplexed t)) (t (error "Unsupported protocol."))))) (terpri) (let ((services (if multiplexed (list thrift.test:thrift-test thrift.test:second-service) thrift.test:thrift-test))) (thrift:serve (puri:parse-uri (concatenate 'string "thrift://127.0.0.1:" port)) services :framed framed :multiplexed multiplexed))) (clon:exit)) (clon:dump "TestServer" main) thrift-0.19.0/test/cl/Makefile0000644000000000000000000004367514472652606016147 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # test/cl/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = test/cl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/test/cl abs_srcdir = /thrift/src/test/cl abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. EXTRA_DIST = \ implementation.lisp \ make-test-client.lisp \ make-test-server.lisp \ tests.lisp all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/cl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/cl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../ThriftTest.thrift $(THRIFT) --gen cl ../ThriftTest.thrift TestServer: make-test-server.lisp $(SBCL) --script make-test-server.lisp TestClient: make-test-client.lisp $(SBCL) --script make-test-client.lisp precross: stubs TestServer TestClient clean-local: $(RM) -r gen-cl $(RM) TestServer $(RM) TestClient # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/cl/implementation.lisp0000644000000000000000000001205714370300523020374 0ustar00rootroot00000000000000(in-package #:thrift.test-implementation) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. (defun thrift.test.thrift-test-implementation:test-void () (format t "testVoid()~%")) (defun thrift.test.thrift-test-implementation:test-string (thing) (format t "testString(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-bool (thing) (format t "testBool(~a)~%" (if thing "true" "false")) thing) (defun thrift.test.thrift-test-implementation:test-byte (thing) (format t "testByte(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-i32 (thing) (format t "testI32(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-i64 (thing) (format t "testI64(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-double (thing) (format t "testDouble(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-binary (thing) (format t "testBinary(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-struct (thing) (format t "testStruct(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-nest (thing) (format t "testNest(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-map (thing) (format t "testMap(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-string-map (thing) (format t "testStringMap(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-set (thing) (format t "testSet(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-list (thing) (format t "testList(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-enum (thing) (format t "testEnum(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-typedef (thing) (format t "testTypedef(~a)~%" thing) thing) (defun thrift.test.thrift-test-implementation:test-map-map (hello) (format t "testMapMap(~a)~%" hello) '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4))))) (defun thrift.test.thrift-test-implementation:test-insanity (argument) (let ((result `((1 . ((2 . ,argument) (3 . ,argument))) (2 . ((6 . ,(thrift.test::make-insanity :user-map nil :xtructs nil))))))) (format t "~a~%" result) result)) (defun thrift.test.thrift-test-implementation:test-multi (arg0 arg1 arg2 arg3 arg4 arg5) (declare (ignorable arg3 arg4 arg5)) (format t "testMulti()~%") (thrift.test:make-xtruct :string-thing "Hello2" :byte-thing arg0 :i32-thing arg1 :i64-thing arg2)) (defun thrift.test.thrift-test-implementation:test-exception (arg) (format t "testException(~a)~%" arg) (cond ((string= arg "Xception") (error 'thrift.test:xception :error-code 1001 :message arg)) ((string= arg "TException") (error 'thrift.test:xception :error-code 0 :message "Stuff!")))) (defun thrift.test.thrift-test-implementation:test-multi-exception (arg0 arg1) (format t "testMultiException(~a, ~a)~%" arg0 arg1) (cond ((string= arg0 "Xception") (error 'thrift.test:xception :error-code 1001 :message "This is an Xception")) ((string= arg0 "Xception2") (error 'thrift.test:xception2 :error-code 2002 :struct-thing (thrift.test:make-xtruct :string-thing "This is an Xception2" :byte-thing 0 :i32-thing 0 :i64-thing 0)))) (thrift.test:make-xtruct :string-thing arg1 :byte-thing 0 :i32-thing 0 :i64-thing 0)) (defun thrift.test.thrift-test-implementation:test-oneway (seconds) (format t "testOneway(~a): Sleeping...~%" seconds) (sleep seconds) (format t "testOneway(~a): done sleeping!~%" seconds)) ;;; Removed from the IDL definition. #+(or) (defun thrift.test.second-service-implementation:blah-blah () (format t "blahBlah()~%")) (defun thrift.test.second-service-implementation:secondtest-string (thing) (format t "secondtestString(~a)~%" thing) (concatenate 'string "testString(\"" thing "\")")) thrift-0.19.0/test/cl/Makefile.in0000644000000000000000000004304214472652520016533 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/cl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ implementation.lisp \ make-test-client.lisp \ make-test-server.lisp \ tests.lisp all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/cl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/cl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../ThriftTest.thrift $(THRIFT) --gen cl ../ThriftTest.thrift TestServer: make-test-server.lisp $(SBCL) --script make-test-server.lisp TestClient: make-test-client.lisp $(SBCL) --script make-test-client.lisp precross: stubs TestServer TestClient clean-local: $(RM) -r gen-cl $(RM) TestServer $(RM) TestClient # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/cl/tests.lisp0000644000000000000000000003423114370300523016507 0ustar00rootroot00000000000000(in-package #:thrift-cross) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. ;;;; The tests here only make sense in the context of a TestServer ;;;; running and the dynamic variable thrift-cross::*prot* ;;;; being set with a client connection to the TestServer. Normally, ;;;; this is handled in make-test-client.lisp. ;;; Standard Thrift cross-test error codes (defparameter *test_basetypes* 1) (defparameter *test_structs* 2) (defparameter *test_containers* 4) (defparameter *test_exceptions* 8) (defparameter *test_unknown* 64) (defparameter *test_timeout* 128) (defun cross-test (&key (multiplexed nil)) "The main cross-test runner." (let ((result nil)) (handler-case (progn (unless (run-package-tests :package :base-types) (pushnew *test_basetypes* result)) (unless (run-package-tests :package :structs) (pushnew *test_structs* result)) (unless (run-package-tests :package :containers) (pushnew *test_containers* result)) (unless (run-package-tests :package :exceptions) (pushnew *test_exceptions* result)) (unless (run-package-tests :package :misc) (pushnew *test_unknown* result)) ;; It doesn't seem like anyone actually uses ;; the second test service when testing multiplexing, ;; so this would fail against servers in other ;; languages. For now, anyway. #+(or) (when multiplexed (unless (run-package-tests :package :multiplex) (pushnew *test_unknown* result)))) (error (e) (pushnew *test_unknown* result))) (apply #'+ result))) (fiasco:define-test-package #:base-types) (in-package #:base-types) (defconstant *lang-string* "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語") (defparameter *trick-string* (format nil "quote: \" backslash: \\ newline: ~% backspace: ~C ~ tab: ~T junk: !@#$%&()(&%$#{}{}<><><" #\backspace)) (defconstant *binary-sequence* #(128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127)) (deftest void-test () (is (null (thrift.test.thrift-test:test-void thrift-cross::*prot*)))) (deftest boolean-test () (is (thrift.test.thrift-test:test-bool thrift-cross::*prot* t)) (is (not (thrift.test.thrift-test:test-bool thrift-cross::*prot* nil)))) (deftest integer-test () (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 127) 127)) (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* -128) -128)) (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 42) 42)) (is (= (thrift.test.thrift-test:test-byte thrift-cross::*prot* 0) 0)) (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 0) 0)) (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* 2147483647) 2147483647)) (is (= (thrift.test.thrift-test:test-i32 thrift-cross::*prot* -2147483648) -2147483648)) (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 0) 0)) (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* 9223372036854775807) 9223372036854775807)) (is (= (thrift.test.thrift-test:test-i64 thrift-cross::*prot* -9223372036854775808) -9223372036854775808))) (deftest double-test () (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 0.0) 0)) (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* 42.0) 42)) (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -555.0) -555)) (is (= (thrift.test.thrift-test:test-double thrift-cross::*prot* -52.3678) -52.3678))) (deftest string-test () (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "") "")) (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* "(defun botsbuildbots () (botsbuilsbots))") "(defun botsbuildbots () (botsbuilsbots))")) (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *lang-string*) *lang-string*)) (is (string= (thrift.test.thrift-test:test-string thrift-cross::*prot* *trick-string*) *trick-string*))) (deftest binary-test () (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* #()) #())) (is (equalp (thrift.test.thrift-test:test-binary thrift-cross::*prot* *binary-sequence*) *binary-sequence*))) (deftest enum-test () (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.five) thrift.test:numberz.five)) (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.eight) thrift.test:numberz.eight)) (is (= (thrift.test.thrift-test:test-enum thrift-cross::*prot* thrift.test:numberz.one) thrift.test:numberz.one))) (deftest typedef-test () (is (= (thrift.test.thrift-test:test-typedef thrift-cross::*prot* 309858235082523) 309858235082523))) (fiasco:define-test-package #:structs) (in-package #:structs) (defparameter *test-struct* (thrift.test:make-xtruct :string-thing "Hell is empty." :byte-thing -2 :i32-thing 42 :i64-thing 42424242)) (defparameter *test-nest* (thrift.test:make-xtruct2 :byte-thing 42 :struct-thing *test-struct* :i32-thing -42)) (deftest struct-test () (let ((rec-struct (thrift.test.thrift-test:test-struct thrift-cross::*prot* *test-struct*))) (is (string= (thrift.test:xtruct-string-thing *test-struct*) (thrift.test:xtruct-string-thing rec-struct))) (is (= (thrift.test:xtruct-byte-thing *test-struct*) (thrift.test:xtruct-byte-thing rec-struct))) (is (= (thrift.test:xtruct-i32-thing *test-struct*) (thrift.test:xtruct-i32-thing rec-struct))) (is (= (thrift.test:xtruct-i64-thing *test-struct*) (thrift.test:xtruct-i64-thing rec-struct))))) (deftest nest-test () (let* ((rec-nest (thrift.test.thrift-test:test-nest thrift-cross::*prot* *test-nest*)) (rec-struct (thrift.test:xtruct2-struct-thing rec-nest))) (is (string= (thrift.test:xtruct-string-thing *test-struct*) (thrift.test:xtruct-string-thing rec-struct))) (is (= (thrift.test:xtruct-byte-thing *test-struct*) (thrift.test:xtruct-byte-thing rec-struct))) (is (= (thrift.test:xtruct-i32-thing *test-struct*) (thrift.test:xtruct-i32-thing rec-struct))) (is (= (thrift.test:xtruct-i64-thing *test-struct*) (thrift.test:xtruct-i64-thing rec-struct))) (is (= (thrift.test:xtruct2-byte-thing *test-nest*) (thrift.test:xtruct2-byte-thing rec-nest))) (is (= (thrift.test:xtruct2-i32-thing *test-nest*) (thrift.test:xtruct2-i32-thing rec-nest))))) (fiasco:define-test-package #:containers) (in-package #:containers) (deftest list-test () (is (null (thrift.test.thrift-test:test-list thrift-cross::*prot* nil))) (is (equal (thrift.test.thrift-test:test-list thrift-cross::*prot* '(42 -42 0 5)) '(42 -42 0 5)))) (deftest set-test () (is (null (thrift.test.thrift-test:test-set thrift-cross::*prot* nil))) (is (equal (sort (thrift.test.thrift-test:test-set thrift-cross::*prot* (list 42 -42 0 5)) #'<) '(-42 0 5 42)))) (defun map= (map1 map2 &key (car-predicate #'equal) (cdr-predicate #'equal)) "Compare two assoc maps according to the predicates given." (not (set-exclusive-or map1 map2 :test (lambda (el1 el2) (and (funcall car-predicate (car el1) (car el2)) (funcall cdr-predicate (cdr el1) (cdr el2))))))) (deftest map-test () (is (null (thrift.test.thrift-test:test-map thrift-cross::*prot* nil))) (is (map= (thrift.test.thrift-test:test-map thrift-cross::*prot* '((0 . 1) (42 . -42) (5 . 5))) '((0 . 1) (42 . -42) (5 . 5)))) (is (map= (thrift.test.thrift-test:test-map-map thrift-cross::*prot* 42) '((-4 . ((-4 . -4) (-3 . -3) (-2 . -2) (-1 . -1))) (4 . ((1 . 1) (2 . 2) (3 . 3) (4 . 4)))) :cdr-predicate #'map=))) (fiasco:define-test-package #:exceptions) (in-package #:exceptions) (defun test-xception (expected-code expected-message function &rest args) "A helper function to test whether xception is signalled, and whether its fields have the expected values." (handler-case (progn (apply function args) nil) (thrift.test:xception (ex) (and (= (thrift.test::xception-error-code ex) expected-code) (string= (thrift.test::xception-message ex) expected-message))))) (defun test-xception2 (expected-code expected-message function &rest args) "A helper function to test whether xception2 is signalled, and whether its fields have the expected values." (handler-case (progn (apply function args) nil) (thrift.test:xception2 (ex) (and (= (thrift.test::xception2-error-code ex) expected-code) (string= (thrift.test::xtruct-string-thing (thrift.test::xception2-struct-thing ex)) expected-message))))) (deftest exception-test () (is (test-xception 1001 "Xception" #'thrift.test.thrift-test:test-exception thrift-cross::*prot* "Xception")) (signals thrift:application-error (thrift.test.thrift-test:test-exception thrift-cross::*prot* "TException")) (finishes (thrift.test.thrift-test:test-exception thrift-cross::*prot* "success"))) (deftest multi-exception-test () (is (test-xception 1001 "This is an Xception" #'thrift.test.thrift-test:test-multi-exception thrift-cross::*prot* "Xception" "meaningless")) (is (test-xception2 2002 "This is an Xception2" #'thrift.test.thrift-test:test-multi-exception thrift-cross::*prot* "Xception2" "meaningless too!")) (is (string= "foobar" (thrift.test:xtruct-string-thing (thrift.test.thrift-test:test-multi-exception thrift-cross::*prot* "success!" "foobar"))))) (fiasco:define-test-package #:misc) (in-package #:misc) (deftest oneway-test () (is (null (thrift.test.thrift-test:test-oneway thrift-cross::*prot* 1)))) (fiasco:define-test-package #:multiplex) (in-package #:multiplex) (deftest multiplex-test () ;; Removed from the IDL definition. ;; (finishes (thrift.test.second-service:blah-blah thrift-cross::*prot*)) (is (string= "asd" (thrift.test.second-service:secondtest-string thrift-cross::*prot* "asd")))) thrift-0.19.0/test/EnumTest.thrift0000644000000000000000000000701014303740367017051 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace c_glib TTest enum MyEnum1 { ME1_0 = 0, ME1_1 = 1, ME1_2, ME1_3, ME1_5 = 5, ME1_6, } enum MyEnum2 { ME2_0, ME2_1, ME2_2, } enum MyEnum2_again { // enum value identifiers may appear again in another enum type ME0_1, ME1_1, ME2_1, ME3_1, } enum MyEnum3 { ME3_0, ME3_1, ME3_N2 = -2, ME3_N1, ME3_D0, ME3_D1, ME3_9 = 9, ME3_10, } enum MyEnum4 { ME4_A = 0x7ffffffd ME4_B ME4_C // attempting to define another enum value here fails // with an overflow error, as we overflow values that can be // represented with an i32. } enum MyEnum5 { e1 // fails with 0.9.3 and earlier e2 = 42 // fails with 0.9.3 and earlier } enum MyEnumWithCustomOstream { custom1 = 1, CustoM2 } (cpp.customostream) struct MyStruct { 1: MyEnum2 me2_2 = MyEnum1.ME2_2 2: MyEnum3 me3_n2 = MyEnum3.ME3_N2 3: MyEnum3 me3_d1 = MyEnum3.ME3_D1 } struct EnumTestStruct { 1: MyEnum3 a_enum; 2: list enum_list; 3: set enum_set; 4: map enum_enum_map; // collections as keys 44: map (python.immutable = ""), MyEnum3> list_enum_map; 45: map (python.immutable = ""), MyEnum3> set_enum_map; 46: map (python.immutable = ""), MyEnum3> map_enum_map; // collections as values 47: map> enum_map_map; 48: map> enum_set_map; 49: map> enum_list_map; } const EnumTestStruct ENUM_TEST = { 'a_enum': MyEnum3.ME3_D1, 'enum_list': [MyEnum3.ME3_D1, MyEnum3.ME3_0, MyEnum3.ME3_N2], 'enum_set': [MyEnum3.ME3_D1, MyEnum3.ME3_N1], 'enum_enum_map': {MyEnum3.ME3_D1: MyEnum3.ME3_0, MyEnum3.ME3_0: MyEnum3.ME3_D1}, 'list_enum_map': {[MyEnum3.ME3_D1, MyEnum3.ME3_0]: MyEnum3.ME3_0, [MyEnum3.ME3_D1]: MyEnum3.ME3_0, [MyEnum3.ME3_0]: MyEnum3.ME3_D1}, 'set_enum_map': {[MyEnum3.ME3_D1, MyEnum3.ME3_0]: MyEnum3.ME3_0, [MyEnum3.ME3_D1]: MyEnum3.ME3_0}, 'map_enum_map': {{MyEnum3.ME3_N1: MyEnum3.ME3_10}: MyEnum3.ME3_1}, 'enum_map_map': {MyEnum3.ME3_N1: {MyEnum3.ME3_D1: MyEnum3.ME3_D1}}, 'enum_set_map': {MyEnum3.ME3_N2: [MyEnum3.ME3_D1, MyEnum3.ME3_N1], MyEnum3.ME3_10: [MyEnum3.ME3_D1, MyEnum3.ME3_N1]}, 'enum_list_map': {MyEnum3.ME3_D1: [MyEnum3.ME3_10], MyEnum3.ME3_0: [MyEnum3.ME3_9, MyEnum3.ME3_10]}, } service EnumTestService { MyEnum3 testEnum(1: MyEnum3 enum1), list testEnumList(1: list enum1), set testEnumSet(1: set enum1), map testEnumMap(1: map enum1), EnumTestStruct testEnumStruct(1: EnumTestStruct enum1), } thrift-0.19.0/test/ReuseObjects.thrift0000644000000000000000000000174714370300523017703 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // The java codegenerator has option to reuse objects for deserialization namespace java thrift.test include "v0.16/ThriftTest.thrift" struct Reuse { 1: i32 val1; 2: set val2; } thrift-0.19.0/test/features/0000755000000000000000000000000014472652673015714 5ustar00rootroot00000000000000thrift-0.19.0/test/features/nosslv3.sh0000777000000000000000000000213014062750226017646 0ustar00rootroot00000000000000#!/bin/bash # # Checks to make sure SSLv3 is not allowed by a server. # THRIFTHOST=localhost THRIFTPORT=9090 while [[ $# -ge 1 ]]; do arg="$1" argIN=(${arg//=/ }) case ${argIN[0]} in -h|--host) THRIFTHOST=${argIN[1]} shift # past argument ;; -p|--port) THRIFTPORT=${argIN[1]} shift # past argument ;; *) # unknown option ignored ;; esac shift # past argument or value done function nosslv3 { local nego local negodenied local opensslv opensslv=$(openssl version | cut -d' ' -f2) if [[ $opensslv > "1.0" ]]; then echo "[pass] OpenSSL 1.1 or later - no need to check ssl3" return 0 fi # echo "openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -ssl3 2>&1 < /dev/null" nego=$(openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -ssl3 2>&1 < /dev/null) negodenied=$? if [[ $negodenied -ne 0 ]]; then echo "[pass] SSLv3 negotiation disabled" echo $nego return 0 fi echo "[fail] SSLv3 negotiation enabled! stdout:" echo $nego return 1 } nosslv3 exit $? thrift-0.19.0/test/features/local_thrift/0000777000000000000000000000000014303740367020361 5ustar00rootroot00000000000000thrift-0.19.0/test/features/local_thrift/__init__.py0000644000000000000000000000230614303740367022467 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import glob import os import sys _SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__)) _ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(_SCRIPT_DIR))) _LIBDIR = os.path.join(_ROOT_DIR, 'lib', 'py', 'build', 'lib.*') for libpath in glob.glob(_LIBDIR): if libpath.endswith('-%d.%d' % (sys.version_info[0], sys.version_info[1])): sys.path.insert(0, libpath) thrift = __import__('thrift') break thrift-0.19.0/test/features/Makefile.am0000644000000000000000000000160414303740367017740 0ustar00rootroot00000000000000# distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # EXTRA_DIST = \ local_thrift \ index.html \ container_limit.py \ index.html \ known_failures_Linux.json \ Makefile.am \ nosslv3.sh \ string_limit.py \ tests.json \ theader_binary.py \ setup.cfg \ tls.sh \ util.py thrift-0.19.0/test/features/setup.cfg0000644000000000000000000000003714303740367017524 0ustar00rootroot00000000000000[flake8] max-line-length = 100 thrift-0.19.0/test/features/string_limit.py0000644000000000000000000000322414303740367020762 0ustar00rootroot00000000000000#!/usr/bin/env python import argparse import sys from util import add_common_args, init_protocol from local_thrift import thrift # noqa from thrift.Thrift import TMessageType, TType # TODO: generate from ThriftTest.thrift def test_string(proto, value): method_name = 'testString' ttype = TType.STRING proto.writeMessageBegin(method_name, TMessageType.CALL, 3) proto.writeStructBegin(method_name + '_args') proto.writeFieldBegin('thing', ttype, 1) proto.writeString(value) proto.writeFieldEnd() proto.writeFieldStop() proto.writeStructEnd() proto.writeMessageEnd() proto.trans.flush() _, mtype, _ = proto.readMessageBegin() assert mtype == TMessageType.REPLY proto.readStructBegin() _, ftype, fid = proto.readFieldBegin() assert fid == 0 assert ftype == ttype result = proto.readString() proto.readFieldEnd() _, ftype, _ = proto.readFieldBegin() assert ftype == TType.STOP proto.readStructEnd() proto.readMessageEnd() assert value == result def main(argv): p = argparse.ArgumentParser() add_common_args(p) p.add_argument('--limit', type=int) args = p.parse_args() proto = init_protocol(args) test_string(proto, 'a' * (args.limit - 1)) test_string(proto, 'a' * (args.limit - 1)) print('[OK]: limit - 1') test_string(proto, 'a' * args.limit) test_string(proto, 'a' * args.limit) print('[OK]: just limit') try: test_string(proto, 'a' * (args.limit + 1)) except Exception: print('[OK]: limit + 1') else: print('[ERROR]: limit + 1') assert False if __name__ == '__main__': main(sys.argv[1:]) thrift-0.19.0/test/features/util.py0000644000000000000000000000235014303740367017232 0ustar00rootroot00000000000000import argparse import socket from local_thrift import thrift # noqa from thrift.transport.TSocket import TSocket from thrift.transport.TTransport import TBufferedTransport, TFramedTransport from thrift.transport.THttpClient import THttpClient from thrift.protocol.TBinaryProtocol import TBinaryProtocol from thrift.protocol.TCompactProtocol import TCompactProtocol from thrift.protocol.TJSONProtocol import TJSONProtocol def add_common_args(p): p.add_argument('--host', default='localhost') p.add_argument('--port', type=int, default=9090) p.add_argument('--protocol', default='binary') p.add_argument('--transport', default='buffered') p.add_argument('--ssl', action='store_true') def parse_common_args(argv): p = argparse.ArgumentParser() add_common_args(p) return p.parse_args(argv) def init_protocol(args): sock = TSocket(args.host, args.port, socket_family=socket.AF_INET) sock.setTimeout(500) trans = { 'buffered': TBufferedTransport, 'framed': TFramedTransport, 'http': THttpClient, }[args.transport](sock) trans.open() return { 'binary': TBinaryProtocol, 'compact': TCompactProtocol, 'json': TJSONProtocol, }[args.protocol](trans) thrift-0.19.0/test/features/known_failures_Linux.json0000644000000000000000000000523514303740367023010 0ustar00rootroot00000000000000[ "c_glib-limit_container_length_binary_buffered-ip", "c_glib-limit_string_length_binary_buffered-ip", "cl-limit_string_length_binary_buffered-ip", "cl-limit_container_length_binary_buffered-ip", "cpp-theader_framed_binary_multih-header_buffered-ip", "cpp-theader_framed_compact_multih-header_buffered-ip", "cpp-theader_unframed_binary_multih-header_buffered-ip", "cpp-theader_unframed_compact_multih-header_buffered-ip", "netstd-limit_container_length_binary_buffered-ip", "netstd-limit_container_length_compact_buffered-ip", "netstd-limit_string_length_binary_buffered-ip", "netstd-limit_string_length_compact_buffered-ip", "netstd-tls_binary_buffered-ip-ssl", "d-limit_container_length_binary_buffered-ip", "d-limit_container_length_compact_buffered-ip", "d-limit_string_length_binary_buffered-ip", "d-limit_string_length_compact_buffered-ip", "erl-limit_container_length_binary_buffered-ip", "erl-limit_container_length_compact_buffered-ip", "erl-limit_string_length_binary_buffered-ip", "erl-limit_string_length_compact_buffered-ip", "go-limit_container_length_binary_buffered-ip", "go-limit_container_length_compact_buffered-ip", "go-limit_string_length_binary_buffered-ip", "go-limit_string_length_compact_buffered-ip", "hs-limit_container_length_binary_buffered-ip", "hs-limit_container_length_compact_buffered-ip", "hs-limit_string_length_binary_buffered-ip", "hs-limit_string_length_compact_buffered-ip", "nodejs-limit_container_length_binary_buffered-ip", "nodejs-limit_container_length_compact_buffered-ip", "nodejs-limit_string_length_binary_buffered-ip", "nodejs-limit_string_length_compact_buffered-ip", "perl-limit_container_length_binary_buffered-ip", "perl-limit_string_length_binary_buffered-ip", "rb-limit_container_length_accel-binary_buffered-ip", "rb-limit_container_length_binary_buffered-ip", "rb-limit_container_length_compact_buffered-ip", "rb-limit_string_length_accel-binary_buffered-ip", "rb-limit_string_length_binary_buffered-ip", "rb-limit_string_length_compact_buffered-ip", "rs-limit_container_length_binary_buffered-ip", "rs-limit_container_length_compact_buffered-ip", "rs-limit_container_length_multic-compact_buffered-ip", "rs-limit_string_length_binary_buffered-ip", "rs-limit_string_length_compact_buffered-ip", "rs-limit_string_length_multic-compact_buffered-ip", "netstd-limit_string_length_compact_buffered-ip", "netstd-limit_container_length_compact_buffered-ip", "nodejs-theader_framed_binary_header_buffered-ip", "nodejs-theader_framed_compact_header_buffered-ip" ] thrift-0.19.0/test/features/container_limit.py0000644000000000000000000000370614303740367021443 0ustar00rootroot00000000000000#!/usr/bin/env python import argparse import sys from util import add_common_args, init_protocol from local_thrift import thrift # noqa from thrift.Thrift import TMessageType, TType # TODO: generate from ThriftTest.thrift def test_list(proto, value): method_name = 'testList' ttype = TType.LIST etype = TType.I32 proto.writeMessageBegin(method_name, TMessageType.CALL, 3) proto.writeStructBegin(method_name + '_args') proto.writeFieldBegin('thing', ttype, 1) proto.writeListBegin(etype, len(value)) for e in value: proto.writeI32(e) proto.writeListEnd() proto.writeFieldEnd() proto.writeFieldStop() proto.writeStructEnd() proto.writeMessageEnd() proto.trans.flush() _, mtype, _ = proto.readMessageBegin() assert mtype == TMessageType.REPLY proto.readStructBegin() _, ftype, fid = proto.readFieldBegin() assert fid == 0 assert ftype == ttype etype2, len2 = proto.readListBegin() assert etype == etype2 assert len2 == len(value) for i in range(len2): v = proto.readI32() assert v == value[i] proto.readListEnd() proto.readFieldEnd() _, ftype, _ = proto.readFieldBegin() assert ftype == TType.STOP proto.readStructEnd() proto.readMessageEnd() def main(argv): p = argparse.ArgumentParser() add_common_args(p) p.add_argument('--limit', type=int) args = p.parse_args() proto = init_protocol(args) # TODO: test set and map test_list(proto, list(range(args.limit - 1))) test_list(proto, list(range(args.limit - 1))) print('[OK]: limit - 1') test_list(proto, list(range(args.limit))) test_list(proto, list(range(args.limit))) print('[OK]: just limit') try: test_list(proto, list(range(args.limit + 1))) except Exception: print('[OK]: limit + 1') else: print('[ERROR]: limit + 1') assert False if __name__ == '__main__': sys.exit(main(sys.argv[1:])) thrift-0.19.0/test/features/theader_binary.py0000644000000000000000000000417414303740367021243 0ustar00rootroot00000000000000#!/usr/bin/env python import argparse import socket import sys from util import add_common_args from local_thrift import thrift # noqa from thrift.Thrift import TMessageType, TType from thrift.transport.TSocket import TSocket from thrift.transport.TTransport import TBufferedTransport, TFramedTransport from thrift.protocol.TBinaryProtocol import TBinaryProtocol from thrift.protocol.TCompactProtocol import TCompactProtocol def test_void(proto): proto.writeMessageBegin('testVoid', TMessageType.CALL, 3) proto.writeStructBegin('testVoid_args') proto.writeFieldStop() proto.writeStructEnd() proto.writeMessageEnd() proto.trans.flush() _, mtype, _ = proto.readMessageBegin() assert mtype == TMessageType.REPLY proto.readStructBegin() _, ftype, _ = proto.readFieldBegin() assert ftype == TType.STOP proto.readStructEnd() proto.readMessageEnd() # THeader stack should accept binary protocol with optionally framed transport def main(argv): p = argparse.ArgumentParser() add_common_args(p) # Since THeaderTransport acts as framed transport when detected frame, we # cannot use --transport=framed as it would result in 2 layered frames. p.add_argument('--override-transport') p.add_argument('--override-protocol') args = p.parse_args() assert args.protocol == 'header' assert args.transport == 'buffered' assert not args.ssl sock = TSocket(args.host, args.port, socket_family=socket.AF_INET) if not args.override_transport or args.override_transport == 'buffered': trans = TBufferedTransport(sock) elif args.override_transport == 'framed': print('TFRAMED') trans = TFramedTransport(sock) else: raise ValueError('invalid transport') trans.open() if not args.override_protocol or args.override_protocol == 'binary': proto = TBinaryProtocol(trans) elif args.override_protocol == 'compact': proto = TCompactProtocol(trans) else: raise ValueError('invalid transport') test_void(proto) test_void(proto) trans.close() if __name__ == '__main__': sys.exit(main(sys.argv[1:])) thrift-0.19.0/test/features/tests.json0000644000000000000000000000501514303740367017741 0ustar00rootroot00000000000000[ { "description": "THeader detects unframed binary wire format", "name": "theader_unframed_binary", "command": [ "python", "theader_binary.py", "--override-protocol=binary", "--override-transport=buffered" ], "protocols": ["header"], "transports": ["buffered"], "sockets": ["ip"], "workdir": "features" }, { "description": "THeader detects framed binary wire format", "name": "theader_framed_binary", "command": [ "python", "theader_binary.py", "--override-protocol=binary", "--override-transport=framed" ], "protocols": ["header"], "transports": ["buffered"], "sockets": ["ip"], "workdir": "features" }, { "description": "THeader detects unframed compact wire format", "name": "theader_unframed_compact", "command": [ "python", "theader_binary.py", "--override-protocol=compact", "--override-transport=buffered" ], "protocols": ["header"], "transports": ["buffered"], "sockets": ["ip"], "workdir": "features" }, { "description": "THeader detects framed compact wire format", "name": "theader_framed_compact", "command": [ "python", "theader_binary.py", "--override-protocol=compact", "--override-transport=framed" ], "protocols": ["header"], "transports": ["buffered"], "sockets": ["ip"], "workdir": "features" }, { "name": "limit_string_length", "command": [ "python", "string_limit.py", "--limit=50" ], "remote_args": [ "--string-limit=50" ], "protocols": [ "compact" ], "transports": ["buffered"], "sockets": ["ip"], "workdir": "features" }, { "name": "limit_container_length", "command": [ "python", "container_limit.py", "--limit=50" ], "remote_args": [ "--container-limit=50" ], "protocols": [ "compact" ], "transports": ["buffered"], "sockets": ["ip"], "workdir": "features" }, { "name": "nosslv3", "comment": "check to make sure SSLv3 is not supported", "command": [ "nosslv3.sh" ], "protocols": ["binary"], "transports": ["buffered"], "sockets": ["ip-ssl"], "workdir": "features" }, { "name": "tls", "comment": "check to make sure TLSv1.0 or later is supported", "command": [ "tls.sh" ], "protocols": ["binary"], "transports": ["buffered"], "sockets": ["ip-ssl"], "workdir": "features" } ] thrift-0.19.0/test/features/Makefile.in0000644000000000000000000004231114472652520017751 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = test/features ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ local_thrift \ index.html \ container_limit.py \ index.html \ known_failures_Linux.json \ Makefile.am \ nosslv3.sh \ string_limit.py \ tests.json \ theader_binary.py \ setup.cfg \ tls.sh \ util.py all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/features/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/features/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/test/features/tls.sh0000777000000000000000000000277314062750226017056 0ustar00rootroot00000000000000#!/bin/bash # # Checks to make sure TLSv1.0 or later is allowed by a server. # THRIFTHOST=localhost THRIFTPORT=9090 while [[ $# -ge 1 ]]; do arg="$1" argIN=(${arg//=/ }) case ${argIN[0]} in -h|--host) THRIFTHOST=${argIN[1]} shift # past argument ;; -p|--port) THRIFTPORT=${argIN[1]} shift # past argument ;; *) # unknown option ignored ;; esac shift # past argument or value done declare -A EXPECT_NEGOTIATE EXPECT_NEGOTIATE[tls1]=1 EXPECT_NEGOTIATE[tls1_1]=1 EXPECT_NEGOTIATE[tls1_2]=1 EXPECT_NEGOTIATE[tls1_3]=1 failures=0 function tls { for PROTO in "${!EXPECT_NEGOTIATE[@]}"; do local nego local negodenied local res echo "openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -$PROTO 2>&1 < /dev/null" nego=$(openssl s_client -connect $THRIFTHOST:$THRIFTPORT -CAfile ../keys/CA.pem -$PROTO 2>&1 < /dev/null) negodenied=$? echo "result of command: $negodenied" res="enabled"; if [[ ${EXPECT_NEGOTIATE[$PROTO]} -eq 0 ]]; then res="disabled"; fi if [[ $negodenied -ne ${EXPECT_NEGOTIATE[$PROTO]} ]]; then echo "$PROTO negotiation allowed" else echo "[warn] $PROTO negotiation did not work" echo $nego ((failures++)) fi done } tls if [[ $failures -eq 4 ]]; then echo "[fail] At least one of TLSv1.0, TLSv1.1, TLSv1.2, or TLSv1.3 needs to work, but does not" exit $failures fi echo "[pass] At least one of TLSv1.0, TLSv1.1, TLSv1.2, or TLSv1.3 worked" exit 0 thrift-0.19.0/test/features/index.html0000644000000000000000000000326614303740367017707 0ustar00rootroot00000000000000 Apache Thrift - integration test suite

Apache Thrift - integration test suite: Results

Server Client Protocol Transport Result (log) Expected

Test Information



browse raw log files



thrift-0.19.0/test/BrokenConstants.thrift0000644000000000000000000000164314303740367020430 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

const i64 myint = 68719476736
const i64 broken = 9876543210987654321  // A little over 2^63

enum foo {
  bar = 68719476736
}
thrift-0.19.0/test/EnumContainersTest.thrift0000644000000000000000000000264514303740367021110 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

namespace java thrift.test.enumcontainers

enum GreekGodGoddess {
    ARES,
    APHRODITE,
    ZEUS,
    POSEIDON,
    HERA,
}

typedef GreekGodGoddess GreekGodGoddessType
typedef i32 Power

struct GodBean {
    1: optional map power,
    2: optional set goddess,
    3: optional map byAlias,
    4: optional set images,
}

const map ATTRIBUTES =
{
    GreekGodGoddess.ZEUS: "lightning bolt",
    GreekGodGoddess.POSEIDON: "trident",
}

const set BEAUTY = [ GreekGodGoddess.APHRODITE, GreekGodGoddess.HERA ]
thrift-0.19.0/test/php/0000777000000000000000000000000014472652606014665 5ustar00rootroot00000000000000thrift-0.19.0/test/php/test_php.ini0000644000000000000000000000010414303740367017176 0ustar00rootroot00000000000000extension=thrift_protocol.so
extension=json.so
extension=sockets.so
thrift-0.19.0/test/php/Makefile.am0000644000000000000000000000274614370300523016707 0ustar00rootroot00000000000000#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

stubs: ../v0.16/ThriftTest.thrift
	$(THRIFT) --gen php ../v0.16/ThriftTest.thrift
	$(THRIFT) --gen php:inlined ../v0.16/ThriftTest.thrift
	$(MKDIR_P) gen-php-classmap
	$(THRIFT) -out gen-php-classmap --gen php:classmap ../v0.16/ThriftTest.thrift

php_ext_dir:
	mkdir -p php_ext_dir
	ln -s ../../../lib/php/src/ext/thrift_protocol/modules/thrift_protocol.so php_ext_dir/
	ln -s "$$(php-config --extension-dir)/json.so" php_ext_dir/
	ln -s "$$(php-config --extension-dir)/sockets.so" php_ext_dir/

precross: stubs php_ext_dir

check: stubs php_ext_dir

clean-local:
	$(RM) -r gen-*/
	$(RM) -r php_ext_dir

dist-hook:
	$(RM) -r $(distdir)/gen-*/
	$(RM) -r $(distdir)/php_ext_dir/

client: stubs php_ext_dir
	php TestClient.php
thrift-0.19.0/test/php/Makefile0000644000000000000000000004452514472652606016333 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# test/php/Makefile.  Generated from Makefile.in by configure.

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.



#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/thrift
pkgincludedir = $(includedir)/thrift
pkglibdir = $(libdir)/thrift
pkglibexecdir = $(libexecdir)/thrift
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = x86_64-pc-linux-gnu
host_triplet = x86_64-pc-linux-gnu
subdir = test/php
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_$(V))
am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_$(V))
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15
ALLOCA = 
AMTAR = $${TAR-tar}
AM_DEFAULT_VERBOSITY = 1
ANT = /usr/bin/ant
ANT_FLAGS = 
AR = ar
AUTOCONF = ${SHELL} /thrift/src/missing autoconf
AUTOHEADER = ${SHELL} /thrift/src/missing autoheader
AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15
AWK = mawk
BISON = bison
BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a
BOOST_CPPFLAGS = -I/usr/include
BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a
BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu
BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu
BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a
BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a
BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a
BUNDLER = /usr/bin/bundle
CARGO = /root/.cargo/bin/cargo
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -g -O2
CLASSPATH = 
CPP = gcc -E
CPPFLAGS = 
CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \;
CXX = g++ -std=c++11
CXXCPP = g++ -E -std=c++11
CXXDEPMODE = depmode=gcc3
CXXFLAGS = -g -O2
CYGPATH_W = echo
DART = /usr/lib/dart/bin/dart
DARTPUB = /usr/lib/dart/bin/pub
DEFS = -DHAVE_CONFIG_H
DEPDIR = .deps
DLLTOOL = false
DMD = dmd
DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent
DMD_OF_DIRSEP = /
DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto
DOTNETCORE = /usr/bin/dotnet
DOTNETCORE_VERSION = 6.0.405
DSYMUTIL = 
DUMPBIN = 
D_EVENT_LIB_NAME = libthriftd-event.a
D_IMPORT_PREFIX = ${prefix}/include/d2
D_LIB_NAME = libthriftd.a
D_SSL_LIB_NAME = libthriftd-ssl.a
ECHO_C = 
ECHO_N = -n
ECHO_T = 
EGREP = /bin/grep -E
ENABLE_COVERAGE = 2
ERL = /usr/local/lib/otp/bin/erl
ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib
ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0
ERLANG_LIB_DIR = /usr/local/lib/otp/lib
ERLC = /usr/local/lib/otp/bin/erlc
ERLCFLAGS = 
EXEEXT = 
FGREP = /bin/grep -F
GCOV_CFLAGS = 
GCOV_CXXFLAGS = 
GCOV_LDFLAGS = 
GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
GLIB_LIBS = -lglib-2.0
GO = /usr/local/bin/go
GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0
GRADLE = /usr/local/bin/gradle
GRADLE_OPTS = 
GREP = /bin/grep
GSETTINGS = /usr/bin/gsettings
HAVE_CXX11 = 1
HAXE = /usr/bin/haxe
HAXE_VERSION = 3.4.4
INSTALL = /usr/bin/install -c
INSTALLDIRS = vendor
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_PROGRAM = ${INSTALL}
INSTALL_SCRIPT = ${INSTALL}
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
JAVA_PREFIX = /usr/local/lib
LD = /usr/bin/ld -m elf_x86_64
LDFLAGS = 
LEX = flex
LEXLIB = 
LEX_OUTPUT_ROOT = lex.yy
LIBEVENT_CPPFLAGS = 
LIBEVENT_LDFLAGS = 
LIBEVENT_LIBS = -levent
LIBOBJS = 
LIBS = -lrt -lpthread 
LIBTOOL = $(SHELL) $(top_builddir)/libtool
LIPO = 
LN_S = ln -s
LTLIBOBJS = 
LT_SYS_LIBRARY_PATH = 
LUA = /usr/bin/lua
LUA_EXEC_PREFIX = ${exec_prefix}
LUA_INCLUDE = -I/usr/include/lua5.2
LUA_LIB = -llua5.2  -ldl
LUA_PLATFORM = unknown
LUA_PREFIX = ${prefix}
LUA_SHORT_VERSION = 52
LUA_VERSION = 5.2
MAKEINFO = ${SHELL} /thrift/src/missing makeinfo
MANIFEST_TOOL = :
MAYBE_CL = cl
MAYBE_CPP = cpp
MAYBE_C_GLIB = c_glib
MAYBE_D = d
MAYBE_DART = dart
MAYBE_ERLANG = erl
MAYBE_GO = go
MAYBE_JAVA = java
MAYBE_KOTLIN = 
MAYBE_LUA = lua
MAYBE_NETSTD = 
MAYBE_NODEJS = nodejs
MAYBE_NODETS = nodets
MAYBE_PERL = perl
MAYBE_PHP = php
MAYBE_PY3 = py3
MAYBE_PYTHON = py
MAYBE_RS = rs
MAYBE_RUBY = rb
MAYBE_SWIFT = swift
MKDIR_P = /bin/mkdir -p
NM = /usr/bin/nm -B
NMEDIT = 
NODEJS = /usr/bin/nodejs
NODETS = /usr/bin/node
NPM = /usr/bin/npm
OBJDUMP = objdump
OBJEXT = o
OPENSSL_INCLUDES = 
OPENSSL_LDFLAGS = 
OPENSSL_LIBS = -lssl -lcrypto
OTOOL = 
OTOOL64 = 
PACKAGE = thrift
PACKAGE_BUGREPORT = 
PACKAGE_NAME = thrift
PACKAGE_STRING = thrift 0.19.0
PACKAGE_TARNAME = thrift
PACKAGE_URL = 
PACKAGE_VERSION = 0.19.0
PATH_SEPARATOR = :
PERL = /usr/bin/perl
PERL_PREFIX = /usr/local
PHP = /usr/bin/php
PHP_CONFIG = /usr/bin/php-config
PHP_CONFIG_PREFIX = /etc/php.d
PHP_PREFIX = /usr/lib/php
PKG_CONFIG = /usr/bin/pkg-config
PKG_CONFIG_LIBDIR = 
PKG_CONFIG_PATH = 
PYTHON = /usr/bin/python
PYTHON3 = /usr/bin/python3
PYTHON_EXEC_PREFIX = ${exec_prefix}
PYTHON_PLATFORM = linux2
PYTHON_PREFIX = ${prefix}
PYTHON_VERSION = 2.7
PY_PREFIX = /usr
QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5
QT5_LIBS = -lQt5Network -lQt5Core
QT5_MOC = /usr/bin/moc
RANLIB = ranlib
REBAR = /usr/local/bin/rebar3
RUBY = /usr/bin/ruby
RUBY_PREFIX = 
RUSTC = /root/.cargo/bin/rustc
SBCL = /usr/local/bin/sbcl
SED = /bin/sed
SET_MAKE = 
SHELL = /bin/bash
STRIP = strip
SWIFT = /usr/share/swift/usr/bin/swift
THRIFT = /thrift/src/compiler/cpp/thrift
TRIAL = /usr/bin/trial
VERSION = 0.19.0
YACC = bison -y
YFLAGS = 
ZLIB_CPPFLAGS = 
ZLIB_LDFLAGS = 
ZLIB_LIBS = -lz
abs_builddir = /thrift/src/test/php
abs_srcdir = /thrift/src/test/php
abs_top_builddir = /thrift/src
abs_top_srcdir = /thrift/src
ac_ct_AR = ar
ac_ct_CC = gcc
ac_ct_CXX = g++
ac_ct_DUMPBIN = 
am__include = include
am__leading_dot = .
am__quote = 
am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir"
am__untar = tar -xf -
bindir = ${exec_prefix}/bin
build = x86_64-pc-linux-gnu
build_alias = 
build_cpu = x86_64
build_os = linux-gnu
build_vendor = pc
builddir = .
datadir = ${datarootdir}
datarootdir = ${prefix}/share
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
dvidir = ${docdir}
exec_prefix = ${prefix}
golang_version = go version go1.19.5 linux/amd64
have_prog_bison = yes
host = x86_64-pc-linux-gnu
host_alias = 
host_cpu = x86_64
host_os = linux-gnu
host_vendor = pc
htmldir = ${docdir}
includedir = ${prefix}/include
infodir = ${datarootdir}/info
install_sh = ${SHELL} /thrift/src/install-sh
libdir = ${exec_prefix}/lib
libexecdir = ${exec_prefix}/libexec
localedir = ${datarootdir}/locale
localstatedir = ${prefix}/var
luadir = ${prefix}/share/lua/5.2
luaexecdir = ${exec_prefix}/lib/lua/5.2
mandir = ${datarootdir}/man
mkdir_p = $(MKDIR_P)
oldincludedir = /usr/include
pdfdir = ${docdir}
pkgluadir = ${luadir}/thrift
pkgluaexecdir = ${luaexecdir}/thrift
pkgpyexecdir = ${pyexecdir}/thrift
pkgpythondir = ${pythondir}/thrift
prefix = /usr/local
program_transform_name = s,x,x,
psdir = ${docdir}
pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages
pythondir = ${prefix}/lib/python2.7/dist-packages
runstatedir = ${localstatedir}/run
rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18)
sbindir = ${exec_prefix}/sbin
sharedstatedir = ${prefix}/com
srcdir = .
subdirs =  lib/php/src/ext/thrift_protocol
sysconfdir = ${prefix}/etc
target_alias = 
top_build_prefix = ../../
top_builddir = ../..
top_srcdir = ../..
all: all-am

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/php/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/php/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs
style-local: 
tags TAGS:

ctags CTAGS:

cscope cscopelist:


distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	$(MAKE) $(AM_MAKEFLAGS) \
	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
	  dist-hook
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-am

clean-am: clean-generic clean-libtool clean-local mostlyclean-am

distclean: distclean-am
	-rm -f Makefile
distclean-am: clean-am distclean-generic

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

style: style-am

style-am: style-local

uninstall-am:

.MAKE: install-am install-strip

.PHONY: all all-am check check-am clean clean-generic clean-libtool \
	clean-local cscopelist-am ctags-am dist-hook distclean \
	distclean-generic distclean-libtool distdir dvi dvi-am html \
	html-am info info-am install install-am install-data \
	install-data-am install-dvi install-dvi-am install-exec \
	install-exec-am install-html install-html-am install-info \
	install-info-am install-man install-pdf install-pdf-am \
	install-ps install-ps-am install-strip installcheck \
	installcheck-am installdirs maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \
	tags-am uninstall uninstall-am

.PRECIOUS: Makefile


stubs: ../v0.16/ThriftTest.thrift
	$(THRIFT) --gen php ../v0.16/ThriftTest.thrift
	$(THRIFT) --gen php:inlined ../v0.16/ThriftTest.thrift
	$(MKDIR_P) gen-php-classmap
	$(THRIFT) -out gen-php-classmap --gen php:classmap ../v0.16/ThriftTest.thrift

php_ext_dir:
	mkdir -p php_ext_dir
	ln -s ../../../lib/php/src/ext/thrift_protocol/modules/thrift_protocol.so php_ext_dir/
	ln -s "$$(php-config --extension-dir)/json.so" php_ext_dir/
	ln -s "$$(php-config --extension-dir)/sockets.so" php_ext_dir/

precross: stubs php_ext_dir

check: stubs php_ext_dir

clean-local:
	$(RM) -r gen-*/
	$(RM) -r php_ext_dir

dist-hook:
	$(RM) -r $(distdir)/gen-*/
	$(RM) -r $(distdir)/php_ext_dir/

client: stubs php_ext_dir
	php TestClient.php

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/php/TestClient.php0000777000000000000000000003111214062750227017446 0ustar00rootroot00000000000000addPsr4('', $GEN_DIR);
} else {
  $loader = new ThriftClassLoader();
  $loader->registerDefinition('ThriftTest', $GEN_DIR);
  $loader->register();
}

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/** Include the Thrift base */
/** Include the protocols */
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Protocol\TBinaryProtocolAccelerated;
use Thrift\Protocol\TCompactProtocol;
use Thrift\Protocol\TJSONProtocol;

/** Include the socket layer */
use Thrift\Transport\TSocket;
use Thrift\Transport\TSocketPool;

/** Include the socket layer */
use Thrift\Transport\TFramedTransport;
use Thrift\Transport\TBufferedTransport;

function makeProtocol($transport, $PROTO)
{
  if ($PROTO == 'binary') {
    return new TBinaryProtocol($transport);
  } else if ($PROTO == 'compact') {
    return new TCompactProtocol($transport);
  } else if ($PROTO == 'json') {
    return new TJSONProtocol($transport);
  } else if ($PROTO == 'accel') {
    if (!function_exists('thrift_protocol_write_binary')) {
      echo "Acceleration extension is not loaded\n";
      exit(1);
    }
    return new TBinaryProtocolAccelerated($transport);
  }

  echo "--protocol must be one of {binary|compact|json|accel}\n";
  exit(1);
}

$host = 'localhost';
$port = 9090;

if ($argc > 1) {
  $host = $argv[0];
}

if ($argc > 2) {
  $host = $argv[1];
}

foreach ($argv as $arg) {
  if (substr($arg, 0, 7) == '--port=') {
    $port = substr($arg, 7);
  } else if (substr($arg, 0, 12) == '--transport=') {
    $MODE = substr($arg, 12);
  } else if (substr($arg, 0, 11) == '--protocol=') {
    $PROTO = substr($arg, 11);
  }
}

$hosts = array('localhost');

$socket = new TSocket($host, $port);
$socket = new TSocketPool($hosts, $port);
$socket->setDebug(TRUE);

if ($MODE == 'inline') {
  $transport = $socket;
  $testClient = new \ThriftTest\ThriftTestClient($transport);
} else if ($MODE == 'framed') {
  $framedSocket = new TFramedTransport($socket);
  $transport = $framedSocket;
  $protocol = makeProtocol($transport, $PROTO);
  $testClient = new \ThriftTest\ThriftTestClient($protocol);
} else {
  $bufferedSocket = new TBufferedTransport($socket, 1024, 1024);
  $transport = $bufferedSocket;
  $protocol = makeProtocol($transport, $PROTO);
  $testClient = new \ThriftTest\ThriftTestClient($protocol);
}

$transport->open();

$start = microtime(true);

define('ERR_BASETYPES', 1);
define('ERR_STRUCTS', 2);
define('ERR_CONTAINERS', 4);
define('ERR_EXCEPTIONS', 8);
define('ERR_UNKNOWN', 64);
$exitcode = 0;
/**
 * VOID TEST
 */
print_r("testVoid()");
$testClient->testVoid();
print_r(" = void\n");

function roundtrip($testClient, $method, $value) {
  global $exitcode;
  print_r("$method($value)");
  $ret = $testClient->$method($value);
  print_r(" = \"$ret\"\n");
  if ($value !== $ret) {
    print_r("*** FAILED ***\n");
    $exitcode |= ERR_BASETYPES;
  }
}

/**
 * STRING TEST
 */
roundtrip($testClient, 'testString', "Test");

/**
 * BOOL TEST
 */
roundtrip($testClient, 'testBool', true);
roundtrip($testClient, 'testBool', false);

/**
 * BYTE TEST
 */
roundtrip($testClient, 'testByte', 1);
roundtrip($testClient, 'testByte', -1);
roundtrip($testClient, 'testByte', 127);
roundtrip($testClient, 'testByte', -128);

/**
 * I32 TEST
 */
roundtrip($testClient, 'testI32', -1);

/**
 * I64 TEST
 */
roundtrip($testClient, 'testI64', 0);
roundtrip($testClient, 'testI64', 1);
roundtrip($testClient, 'testI64', -1);
roundtrip($testClient, 'testI64', -34359738368);

/**
 * DOUBLE TEST
 */
roundtrip($testClient, 'testDouble', -852.234234234);

/**
 * BINARY TEST  --  TODO
 */

/**
 * STRUCT TEST
 */
print_r("testStruct({\"Zero\", 1, -3, -5})");
$out = new \ThriftTest\Xtruct();
$out->string_thing = "Zero";
$out->byte_thing = 1;
$out->i32_thing = -3;
$out->i64_thing = -5;
$in = $testClient->testStruct($out);
print_r(" = {\"".$in->string_thing."\", ".
        $in->byte_thing.", ".
        $in->i32_thing.", ".
        $in->i64_thing."}\n");

if ($in != $out) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

/**
 * NESTED STRUCT TEST
 */
print_r("testNest({1, {\"Zero\", 1, -3, -5}), 5}");
$out2 = new \ThriftTest\Xtruct2();
$out2->byte_thing = 1;
$out2->struct_thing = $out;
$out2->i32_thing = 5;
$in2 = $testClient->testNest($out2);
$in = $in2->struct_thing;
print_r(" = {".$in2->byte_thing.", {\"".
        $in->string_thing."\", ".
        $in->byte_thing.", ".
        $in->i32_thing.", ".
        $in->i64_thing."}, ".
        $in2->i32_thing."}\n");

if ($in2 != $out2) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

/**
 * MAP TEST
 */
$mapout = array();
for ($i = 0; $i < 5; ++$i) {
  $mapout[$i] = $i-10;
}
print_r("testMap({");
$first = true;
foreach ($mapout as $key => $val) {
  if ($first) {
    $first = false;
  } else {
    print_r(", ");
  }
  print_r("$key => $val");
}
print_r("})");

$mapin = $testClient->testMap($mapout);
print_r(" = {");
$first = true;
foreach ($mapin as $key => $val) {
  if ($first) {
    $first = false;
  } else {
    print_r(", ");
  }
  print_r("$key => $val");
}
print_r("}\n");

if ($mapin != $mapout) {
    echo "**FAILED**\n";
    $exitcode |= ERR_CONTAINERS;
}

$mapout = array();
for ($i = 0; $i < 10; $i++) {
    $mapout["key$i"] = "val$i";
}
print_r('testStringMap({');
$first = true;
foreach ($mapout as $key => $val) {
  if ($first) {
    $first = false;
  } else {
    print_r(", ");
  }
  print_r("\"$key\" => \"$val\"");
}
print_r("})");
$mapin = $testClient->testStringMap($mapout);
print_r(" = {");
$first = true;
foreach ($mapin as $key => $val) {
  if ($first) {
    $first = false;
  } else {
    print_r(", ");
  }
  print_r("\"$key\" => \"$val\"");
}
print_r("}\n");
ksort($mapin);
if ($mapin != $mapout) {
    echo "**FAILED**\n";
    $exitcode |= ERR_CONTAINERS;
}

/**
 * SET TEST
 */
$setout = array();;
for ($i = -2; $i < 3; ++$i) {
  $setout[$i]= true;
}
print_r("testSet({");
echo implode(',', array_keys($setout));
print_r("})");
$setin = $testClient->testSet($setout);
print_r(" = {");
echo implode(', ', array_keys($setin));
print_r("}\n");
// Order of keys in set does not matter
ksort($setin);
if ($setout !== $setin) {
    echo "**FAILED**\n";
    $exitcode |= ERR_CONTAINERS;
}
// Regression test for corrupted array
if ($setin[2] !== $setout[2] || is_int($setin[2])) {
    echo "**FAILED**\n";
    $exitcode |= ERR_CONTAINERS;
}

/**
 * LIST TEST
 */
$listout = array();
for ($i = -2; $i < 3; ++$i) {
  $listout []= $i;
}
print_r("testList({");
$first = true;
foreach ($listout as $val) {
  if ($first) {
    $first = false;
  } else {
    print_r(", ");
  }
  print_r($val);
}
print_r("})");
$listin = $testClient->testList($listout);
print_r(" = {");
$first = true;
foreach ($listin as $val) {
  if ($first) {
    $first = false;
  } else {
    print_r(", ");
  }
  print_r($val);
}
print_r("}\n");
if ($listin !== $listout) {
    echo "**FAILED**\n";
    $exitcode |= ERR_CONTAINERS;
}

/**
 * ENUM TEST
 */
print_r("testEnum(ONE)");
$ret = $testClient->testEnum(\ThriftTest\Numberz::ONE);
print_r(" = $ret\n");
if ($ret != \ThriftTest\Numberz::ONE) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

print_r("testEnum(TWO)");
$ret = $testClient->testEnum(\ThriftTest\Numberz::TWO);
print_r(" = $ret\n");
if ($ret != \ThriftTest\Numberz::TWO) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

print_r("testEnum(THREE)");
$ret = $testClient->testEnum(\ThriftTest\Numberz::THREE);
print_r(" = $ret\n");
if ($ret != \ThriftTest\Numberz::THREE) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

print_r("testEnum(FIVE)");
$ret = $testClient->testEnum(\ThriftTest\Numberz::FIVE);
print_r(" = $ret\n");
if ($ret != \ThriftTest\Numberz::FIVE) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

print_r("testEnum(EIGHT)");
$ret = $testClient->testEnum(\ThriftTest\Numberz::EIGHT);
print_r(" = $ret\n");
if ($ret != \ThriftTest\Numberz::EIGHT) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

/**
 * TYPEDEF TEST
 */
print_r("testTypedef(309858235082523)");
$uid = $testClient->testTypedef(309858235082523);
print_r(" = $uid\n");
if ($uid !== 309858235082523) {
    echo "**FAILED**\n";
    $exitcode |= ERR_STRUCTS;
}

/**
 * NESTED MAP TEST
 */
print_r("testMapMap(1)");
$mm = $testClient->testMapMap(1);
print_r(" = {");
foreach ($mm as $key => $val) {
  print_r("$key => {");
  foreach ($val as $k2 => $v2) {
    print_r("$k2 => $v2, ");
  }
  print_r("}, ");
}
print_r("}\n");
$expected_mm = [
  -4 => [-4 => -4, -3 => -3, -2 => -2, -1 => -1],
  4 => [4 => 4, 3 => 3, 2 => 2, 1 => 1],
];
if ($mm != $expected_mm) {
    echo "**FAILED**\n";
    $exitcode |= ERR_CONTAINERS;
}

/**
 * INSANITY TEST
 */
$insane = new \ThriftTest\Insanity();
$insane->userMap[\ThriftTest\Numberz::FIVE] = 5000;
$truck = new \ThriftTest\Xtruct();
$truck->string_thing = "Truck";
$truck->byte_thing = 8;
$truck->i32_thing = 8;
$truck->i64_thing = 8;
$insane->xtructs []= $truck;
print_r("testInsanity()");
$whoa = $testClient->testInsanity($insane);
print_r(" = {");
foreach ($whoa as $key => $val) {
  print_r("$key => {");
  foreach ($val as $k2 => $v2) {
    print_r("$k2 => {");
    $userMap = $v2->userMap;
    print_r("{");
    if (is_array($userMap)) {
      foreach ($userMap as $k3 => $v3) {
        print_r("$k3 => $v3, ");
      }
    }
    print_r("}, ");

    $xtructs = $v2->xtructs;
    print_r("{");
    if (is_array($xtructs)) {
      foreach ($xtructs as $x) {
        print_r("{\"".$x->string_thing."\", ".
                $x->byte_thing.", ".$x->i32_thing.", ".$x->i64_thing."}, ");
      }
    }
    print_r("}");

    print_r("}, ");
  }
  print_r("}, ");
}
print_r("}\n");

/**
 * EXCEPTION TEST
 */
print_r("testException('Xception')");
try {
  $testClient->testException('Xception');
  print_r("  void\nFAILURE\n");
  $exitcode |= ERR_EXCEPTIONS;
} catch (\ThriftTest\Xception $x) {
  print_r(' caught xception '.$x->errorCode.': '.$x->message."\n");
}

// Regression test for THRIFT-4263
print_r("testBinarySerializer_Deserialize('foo')");
try {
  \Thrift\Serializer\TBinarySerializer::deserialize(base64_decode('foo'), \ThriftTest\Xtruct2::class);
  echo "**FAILED**\n";
  $exitcode |= ERR_STRUCTS;
} catch (\Thrift\Exception\TTransportException $happy_exception) {
  // We expected this due to binary data of base64_decode('foo') is less then 4
  // bytes and it tries to find thrift version number in the transport by
  // reading i32() at the beginning.  Casting to string validates that
  // exception is still accessible in memory and not corrupted.  Without patch,
  // PHP will error log that the exception doesn't have any tostring method,
  // which is a lie due to corrupted memory.
  for($i=99; $i > 0; $i--) {
    (string)$happy_exception;
  }
  print_r("  SUCCESS\n");
}

/**
 * Normal tests done.
 */

$stop = microtime(true);
$elp = round(1000*($stop - $start), 0);
print_r("Total time: $elp ms\n");

/**
 * Extraneous "I don't trust PHP to pack/unpack integer" tests
 */

if ($protocol instanceof TBinaryProtocolAccelerated) {
    // Regression check: check that method name is not double-freed
    // Method name should not be an interned string.
    $method_name = "Void";
    $method_name = "test$method_name";

    $seqid = 0;
    $args = new \ThriftTest\ThriftTest_testVoid_args();
    thrift_protocol_write_binary($protocol, $method_name, \Thrift\Type\TMessageType::CALL, $args, $seqid, $protocol->isStrictWrite());
    $testClient->recv_testVoid();

}

// Max I32
$num = pow(2, 30) + (pow(2, 30) - 1);
roundtrip($testClient, 'testI32', $num);

// Min I32
$num = 0 - pow(2, 31);
roundtrip($testClient, 'testI32', $num);

// Max I64
$num = pow(2, 62) + (pow(2, 62) - 1);
roundtrip($testClient, 'testI64', $num);

// Min I64
$num = 0 - pow(2, 62) - pow(2, 62);
roundtrip($testClient, 'testI64', $num);

$transport->close();
exit($exitcode);
thrift-0.19.0/test/php/TestInline.php0000644000000000000000000000156714303740367017454 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


thrift-0.19.0/test/php/TestClassmap.php0000644000000000000000000000155514303740367017776 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


thrift-0.19.0/test/php/Makefile.in0000644000000000000000000004364014472652521016731 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.

@SET_MAKE@

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = test/php
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANT = @ANT@
ANT_FLAGS = @ANT_FLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BISON = @BISON@
BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_LIB_DIR = @BOOST_LIB_DIR@
BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@
BOOST_TEST_LDADD = @BOOST_TEST_LDADD@
BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@
BUNDLER = @BUNDLER@
CARGO = @CARGO@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CLASSPATH = @CLASSPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPSTYLE_CMD = @CPPSTYLE_CMD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DART = @DART@
DARTPUB = @DARTPUB@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DMD = @DMD@
DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@
DMD_OF_DIRSEP = @DMD_OF_DIRSEP@
DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@
DOTNETCORE = @DOTNETCORE@
DOTNETCORE_VERSION = @DOTNETCORE_VERSION@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@
D_IMPORT_PREFIX = @D_IMPORT_PREFIX@
D_LIB_NAME = @D_LIB_NAME@
D_SSL_LIB_NAME = @D_SSL_LIB_NAME@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_COVERAGE = @ENABLE_COVERAGE@
ERL = @ERL@
ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@
ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@
ERLANG_LIB_DIR = @ERLANG_LIB_DIR@
ERLC = @ERLC@
ERLCFLAGS = @ERLCFLAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GCOV_CFLAGS = @GCOV_CFLAGS@
GCOV_CXXFLAGS = @GCOV_CXXFLAGS@
GCOV_LDFLAGS = @GCOV_LDFLAGS@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GO = @GO@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
GOBJECT_LIBS = @GOBJECT_LIBS@
GRADLE = @GRADLE@
GRADLE_OPTS = @GRADLE_OPTS@
GREP = @GREP@
GSETTINGS = @GSETTINGS@
HAVE_CXX11 = @HAVE_CXX11@
HAXE = @HAXE@
HAXE_VERSION = @HAXE_VERSION@
INSTALL = @INSTALL@
INSTALLDIRS = @INSTALLDIRS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JAVA_PREFIX = @JAVA_PREFIX@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@
LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@
LIBEVENT_LIBS = @LIBEVENT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
LUA = @LUA@
LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@
LUA_INCLUDE = @LUA_INCLUDE@
LUA_LIB = @LUA_LIB@
LUA_PLATFORM = @LUA_PLATFORM@
LUA_PREFIX = @LUA_PREFIX@
LUA_SHORT_VERSION = @LUA_SHORT_VERSION@
LUA_VERSION = @LUA_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MAYBE_CL = @MAYBE_CL@
MAYBE_CPP = @MAYBE_CPP@
MAYBE_C_GLIB = @MAYBE_C_GLIB@
MAYBE_D = @MAYBE_D@
MAYBE_DART = @MAYBE_DART@
MAYBE_ERLANG = @MAYBE_ERLANG@
MAYBE_GO = @MAYBE_GO@
MAYBE_JAVA = @MAYBE_JAVA@
MAYBE_KOTLIN = @MAYBE_KOTLIN@
MAYBE_LUA = @MAYBE_LUA@
MAYBE_NETSTD = @MAYBE_NETSTD@
MAYBE_NODEJS = @MAYBE_NODEJS@
MAYBE_NODETS = @MAYBE_NODETS@
MAYBE_PERL = @MAYBE_PERL@
MAYBE_PHP = @MAYBE_PHP@
MAYBE_PY3 = @MAYBE_PY3@
MAYBE_PYTHON = @MAYBE_PYTHON@
MAYBE_RS = @MAYBE_RS@
MAYBE_RUBY = @MAYBE_RUBY@
MAYBE_SWIFT = @MAYBE_SWIFT@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NODEJS = @NODEJS@
NODETS = @NODETS@
NPM = @NPM@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PERL_PREFIX = @PERL_PREFIX@
PHP = @PHP@
PHP_CONFIG = @PHP_CONFIG@
PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@
PHP_PREFIX = @PHP_PREFIX@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PYTHON = @PYTHON@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
PY_PREFIX = @PY_PREFIX@
QT5_CFLAGS = @QT5_CFLAGS@
QT5_LIBS = @QT5_LIBS@
QT5_MOC = @QT5_MOC@
RANLIB = @RANLIB@
REBAR = @REBAR@
RUBY = @RUBY@
RUBY_PREFIX = @RUBY_PREFIX@
RUSTC = @RUSTC@
SBCL = @SBCL@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SWIFT = @SWIFT@
THRIFT = @THRIFT@
TRIAL = @TRIAL@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@
ZLIB_LDFLAGS = @ZLIB_LDFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
golang_version = @golang_version@
have_prog_bison = @have_prog_bison@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
luadir = @luadir@
luaexecdir = @luaexecdir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgluadir = @pkgluadir@
pkgluaexecdir = @pkgluaexecdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
rustc_version = @rustc_version@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
all: all-am

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/php/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/php/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs
style-local: 
tags TAGS:

ctags CTAGS:

cscope cscopelist:


distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	$(MAKE) $(AM_MAKEFLAGS) \
	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
	  dist-hook
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-am

clean-am: clean-generic clean-libtool clean-local mostlyclean-am

distclean: distclean-am
	-rm -f Makefile
distclean-am: clean-am distclean-generic

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

style: style-am

style-am: style-local

uninstall-am:

.MAKE: install-am install-strip

.PHONY: all all-am check check-am clean clean-generic clean-libtool \
	clean-local cscopelist-am ctags-am dist-hook distclean \
	distclean-generic distclean-libtool distdir dvi dvi-am html \
	html-am info info-am install install-am install-data \
	install-data-am install-dvi install-dvi-am install-exec \
	install-exec-am install-html install-html-am install-info \
	install-info-am install-man install-pdf install-pdf-am \
	install-ps install-ps-am install-strip installcheck \
	installcheck-am installdirs maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \
	tags-am uninstall uninstall-am

.PRECIOUS: Makefile


stubs: ../v0.16/ThriftTest.thrift
	$(THRIFT) --gen php ../v0.16/ThriftTest.thrift
	$(THRIFT) --gen php:inlined ../v0.16/ThriftTest.thrift
	$(MKDIR_P) gen-php-classmap
	$(THRIFT) -out gen-php-classmap --gen php:classmap ../v0.16/ThriftTest.thrift

php_ext_dir:
	mkdir -p php_ext_dir
	ln -s ../../../lib/php/src/ext/thrift_protocol/modules/thrift_protocol.so php_ext_dir/
	ln -s "$$(php-config --extension-dir)/json.so" php_ext_dir/
	ln -s "$$(php-config --extension-dir)/sockets.so" php_ext_dir/

precross: stubs php_ext_dir

check: stubs php_ext_dir

clean-local:
	$(RM) -r gen-*/
	$(RM) -r php_ext_dir

dist-hook:
	$(RM) -r $(distdir)/gen-*/
	$(RM) -r $(distdir)/php_ext_dir/

client: stubs php_ext_dir
	php TestClient.php

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/erl/0000777000000000000000000000000014472652606014660 5ustar00rootroot00000000000000thrift-0.19.0/test/erl/Makefile.am0000644000000000000000000000263314370300523016675 0ustar00rootroot00000000000000#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

THRIFT_FILES = $(wildcard ../*.thrift)

ERL_FLAG = erl
# make sure ThriftTest.thrift is generated last to prevent conflicts with other *.thrift files
.generated: $(THRIFT_FILES)
	for f in $(THRIFT_FILES) ; do \
	  $(THRIFT) --gen $(ERL_FLAG) -o src $$f ; \
	done ; \
	$(THRIFT) --gen $(ERL_FLAG) -o src ../v0.16/ThriftTest.thrift
	touch .generated

precross: .generated
	$(REBAR) compile

maintainer-clean-local:
	$(RM) -r ebin/

clean:
	$(REBAR) clean
	$(RM)    .generated
	$(RM) -r .rebar/
	$(RM) -r src/gen-erl/

dist-hook:
	$(RM)    $(distdir)/.generated
	$(RM) -r $(distdir)/.rebar/
	$(RM) -r $(distdir)/ebin/
	$(RM) -r $(distdir)/src/gen-erl/
thrift-0.19.0/test/erl/Makefile0000644000000000000000000004442014472652606016320 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# test/erl/Makefile.  Generated from Makefile.in by configure.

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.



#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/thrift
pkgincludedir = $(includedir)/thrift
pkglibdir = $(libdir)/thrift
pkglibexecdir = $(libexecdir)/thrift
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = x86_64-pc-linux-gnu
host_triplet = x86_64-pc-linux-gnu
subdir = test/erl
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_$(V))
am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_$(V))
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15
ALLOCA = 
AMTAR = $${TAR-tar}
AM_DEFAULT_VERBOSITY = 1
ANT = /usr/bin/ant
ANT_FLAGS = 
AR = ar
AUTOCONF = ${SHELL} /thrift/src/missing autoconf
AUTOHEADER = ${SHELL} /thrift/src/missing autoheader
AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15
AWK = mawk
BISON = bison
BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a
BOOST_CPPFLAGS = -I/usr/include
BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a
BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu
BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu
BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a
BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a
BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a
BUNDLER = /usr/bin/bundle
CARGO = /root/.cargo/bin/cargo
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -g -O2
CLASSPATH = 
CPP = gcc -E
CPPFLAGS = 
CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \;
CXX = g++ -std=c++11
CXXCPP = g++ -E -std=c++11
CXXDEPMODE = depmode=gcc3
CXXFLAGS = -g -O2
CYGPATH_W = echo
DART = /usr/lib/dart/bin/dart
DARTPUB = /usr/lib/dart/bin/pub
DEFS = -DHAVE_CONFIG_H
DEPDIR = .deps
DLLTOOL = false
DMD = dmd
DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent
DMD_OF_DIRSEP = /
DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto
DOTNETCORE = /usr/bin/dotnet
DOTNETCORE_VERSION = 6.0.405
DSYMUTIL = 
DUMPBIN = 
D_EVENT_LIB_NAME = libthriftd-event.a
D_IMPORT_PREFIX = ${prefix}/include/d2
D_LIB_NAME = libthriftd.a
D_SSL_LIB_NAME = libthriftd-ssl.a
ECHO_C = 
ECHO_N = -n
ECHO_T = 
EGREP = /bin/grep -E
ENABLE_COVERAGE = 2
ERL = /usr/local/lib/otp/bin/erl
ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib
ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0
ERLANG_LIB_DIR = /usr/local/lib/otp/lib
ERLC = /usr/local/lib/otp/bin/erlc
ERLCFLAGS = 
EXEEXT = 
FGREP = /bin/grep -F
GCOV_CFLAGS = 
GCOV_CXXFLAGS = 
GCOV_LDFLAGS = 
GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
GLIB_LIBS = -lglib-2.0
GO = /usr/local/bin/go
GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0
GRADLE = /usr/local/bin/gradle
GRADLE_OPTS = 
GREP = /bin/grep
GSETTINGS = /usr/bin/gsettings
HAVE_CXX11 = 1
HAXE = /usr/bin/haxe
HAXE_VERSION = 3.4.4
INSTALL = /usr/bin/install -c
INSTALLDIRS = vendor
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_PROGRAM = ${INSTALL}
INSTALL_SCRIPT = ${INSTALL}
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
JAVA_PREFIX = /usr/local/lib
LD = /usr/bin/ld -m elf_x86_64
LDFLAGS = 
LEX = flex
LEXLIB = 
LEX_OUTPUT_ROOT = lex.yy
LIBEVENT_CPPFLAGS = 
LIBEVENT_LDFLAGS = 
LIBEVENT_LIBS = -levent
LIBOBJS = 
LIBS = -lrt -lpthread 
LIBTOOL = $(SHELL) $(top_builddir)/libtool
LIPO = 
LN_S = ln -s
LTLIBOBJS = 
LT_SYS_LIBRARY_PATH = 
LUA = /usr/bin/lua
LUA_EXEC_PREFIX = ${exec_prefix}
LUA_INCLUDE = -I/usr/include/lua5.2
LUA_LIB = -llua5.2  -ldl
LUA_PLATFORM = unknown
LUA_PREFIX = ${prefix}
LUA_SHORT_VERSION = 52
LUA_VERSION = 5.2
MAKEINFO = ${SHELL} /thrift/src/missing makeinfo
MANIFEST_TOOL = :
MAYBE_CL = cl
MAYBE_CPP = cpp
MAYBE_C_GLIB = c_glib
MAYBE_D = d
MAYBE_DART = dart
MAYBE_ERLANG = erl
MAYBE_GO = go
MAYBE_JAVA = java
MAYBE_KOTLIN = 
MAYBE_LUA = lua
MAYBE_NETSTD = 
MAYBE_NODEJS = nodejs
MAYBE_NODETS = nodets
MAYBE_PERL = perl
MAYBE_PHP = php
MAYBE_PY3 = py3
MAYBE_PYTHON = py
MAYBE_RS = rs
MAYBE_RUBY = rb
MAYBE_SWIFT = swift
MKDIR_P = /bin/mkdir -p
NM = /usr/bin/nm -B
NMEDIT = 
NODEJS = /usr/bin/nodejs
NODETS = /usr/bin/node
NPM = /usr/bin/npm
OBJDUMP = objdump
OBJEXT = o
OPENSSL_INCLUDES = 
OPENSSL_LDFLAGS = 
OPENSSL_LIBS = -lssl -lcrypto
OTOOL = 
OTOOL64 = 
PACKAGE = thrift
PACKAGE_BUGREPORT = 
PACKAGE_NAME = thrift
PACKAGE_STRING = thrift 0.19.0
PACKAGE_TARNAME = thrift
PACKAGE_URL = 
PACKAGE_VERSION = 0.19.0
PATH_SEPARATOR = :
PERL = /usr/bin/perl
PERL_PREFIX = /usr/local
PHP = /usr/bin/php
PHP_CONFIG = /usr/bin/php-config
PHP_CONFIG_PREFIX = /etc/php.d
PHP_PREFIX = /usr/lib/php
PKG_CONFIG = /usr/bin/pkg-config
PKG_CONFIG_LIBDIR = 
PKG_CONFIG_PATH = 
PYTHON = /usr/bin/python
PYTHON3 = /usr/bin/python3
PYTHON_EXEC_PREFIX = ${exec_prefix}
PYTHON_PLATFORM = linux2
PYTHON_PREFIX = ${prefix}
PYTHON_VERSION = 2.7
PY_PREFIX = /usr
QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5
QT5_LIBS = -lQt5Network -lQt5Core
QT5_MOC = /usr/bin/moc
RANLIB = ranlib
REBAR = /usr/local/bin/rebar3
RUBY = /usr/bin/ruby
RUBY_PREFIX = 
RUSTC = /root/.cargo/bin/rustc
SBCL = /usr/local/bin/sbcl
SED = /bin/sed
SET_MAKE = 
SHELL = /bin/bash
STRIP = strip
SWIFT = /usr/share/swift/usr/bin/swift
THRIFT = /thrift/src/compiler/cpp/thrift
TRIAL = /usr/bin/trial
VERSION = 0.19.0
YACC = bison -y
YFLAGS = 
ZLIB_CPPFLAGS = 
ZLIB_LDFLAGS = 
ZLIB_LIBS = -lz
abs_builddir = /thrift/src/test/erl
abs_srcdir = /thrift/src/test/erl
abs_top_builddir = /thrift/src
abs_top_srcdir = /thrift/src
ac_ct_AR = ar
ac_ct_CC = gcc
ac_ct_CXX = g++
ac_ct_DUMPBIN = 
am__include = include
am__leading_dot = .
am__quote = 
am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir"
am__untar = tar -xf -
bindir = ${exec_prefix}/bin
build = x86_64-pc-linux-gnu
build_alias = 
build_cpu = x86_64
build_os = linux-gnu
build_vendor = pc
builddir = .
datadir = ${datarootdir}
datarootdir = ${prefix}/share
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
dvidir = ${docdir}
exec_prefix = ${prefix}
golang_version = go version go1.19.5 linux/amd64
have_prog_bison = yes
host = x86_64-pc-linux-gnu
host_alias = 
host_cpu = x86_64
host_os = linux-gnu
host_vendor = pc
htmldir = ${docdir}
includedir = ${prefix}/include
infodir = ${datarootdir}/info
install_sh = ${SHELL} /thrift/src/install-sh
libdir = ${exec_prefix}/lib
libexecdir = ${exec_prefix}/libexec
localedir = ${datarootdir}/locale
localstatedir = ${prefix}/var
luadir = ${prefix}/share/lua/5.2
luaexecdir = ${exec_prefix}/lib/lua/5.2
mandir = ${datarootdir}/man
mkdir_p = $(MKDIR_P)
oldincludedir = /usr/include
pdfdir = ${docdir}
pkgluadir = ${luadir}/thrift
pkgluaexecdir = ${luaexecdir}/thrift
pkgpyexecdir = ${pyexecdir}/thrift
pkgpythondir = ${pythondir}/thrift
prefix = /usr/local
program_transform_name = s,x,x,
psdir = ${docdir}
pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages
pythondir = ${prefix}/lib/python2.7/dist-packages
runstatedir = ${localstatedir}/run
rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18)
sbindir = ${exec_prefix}/sbin
sharedstatedir = ${prefix}/com
srcdir = .
subdirs =  lib/php/src/ext/thrift_protocol
sysconfdir = ${prefix}/etc
target_alias = 
top_build_prefix = ../../
top_builddir = ../..
top_srcdir = ../..
THRIFT_FILES = $(wildcard ../*.thrift)
ERL_FLAG = erl
all: all-am

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/erl/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/erl/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs
style-local: 
tags TAGS:

ctags CTAGS:

cscope cscopelist:


distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	$(MAKE) $(AM_MAKEFLAGS) \
	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
	  dist-hook
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean-am: clean-generic clean-libtool mostlyclean-am

distclean: distclean-am
	-rm -f Makefile
distclean-am: clean-am distclean-generic

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic \
	maintainer-clean-local

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

style: style-am

style-am: style-local

uninstall-am:

.MAKE: install-am install-strip

.PHONY: all all-am check check-am clean clean-generic clean-libtool \
	cscopelist-am ctags-am dist-hook distclean distclean-generic \
	distclean-libtool distdir dvi dvi-am html html-am info info-am \
	install install-am install-data install-data-am install-dvi \
	install-dvi-am install-exec install-exec-am install-html \
	install-html-am install-info install-info-am install-man \
	install-pdf install-pdf-am install-ps install-ps-am \
	install-strip installcheck installcheck-am installdirs \
	maintainer-clean maintainer-clean-generic \
	maintainer-clean-local mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \
	tags-am uninstall uninstall-am

.PRECIOUS: Makefile

# make sure ThriftTest.thrift is generated last to prevent conflicts with other *.thrift files
.generated: $(THRIFT_FILES)
	for f in $(THRIFT_FILES) ; do \
	  $(THRIFT) --gen $(ERL_FLAG) -o src $$f ; \
	done ; \
	$(THRIFT) --gen $(ERL_FLAG) -o src ../v0.16/ThriftTest.thrift
	touch .generated

precross: .generated
	$(REBAR) compile

maintainer-clean-local:
	$(RM) -r ebin/

clean:
	$(REBAR) clean
	$(RM)    .generated
	$(RM) -r .rebar/
	$(RM) -r src/gen-erl/

dist-hook:
	$(RM)    $(distdir)/.generated
	$(RM) -r $(distdir)/.rebar/
	$(RM) -r $(distdir)/ebin/
	$(RM) -r $(distdir)/src/gen-erl/

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/erl/src/0000777000000000000000000000000014454461475015451 5ustar00rootroot00000000000000thrift-0.19.0/test/erl/src/thrift_test.app.src0000644000000000000000000000376014454461475021302 0ustar00rootroot00000000000000%%
%% Licensed to the Apache Software Foundation (ASF) under one
%% or more contributor license agreements. See the NOTICE file
%% distributed with this work for additional information
%% regarding copyright ownership. The ASF licenses this file
%% to you under the Apache License, Version 2.0 (the
%% "License"); you may not use this file except in compliance
%% with the License. You may obtain a copy of the License at
%%
%%   http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied. See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%
%%% -*- mode:erlang -*-
{application, thrift_test, [
  % A quick description of the application.
  {description, "Thrift cross language test"},

  % The version of the applicaton
  {vsn, "0.19.0"},

  % All modules used by the application.
  {modules, [
    test_client,
    test_thrift_server
  ]},

  % All of the registered names the application uses. This can be ignored.
  {registered, []},

  % Applications that are to be started prior to this one. This can be ignored
  % leave it alone unless you understand it well and let the .rel files in
  % your release handle this.
  {applications, [kernel, stdlib]},

  % OTP application loader will load, but not start, included apps. Again
  % this can be ignored as well.  To load but not start an application it
  % is easier to include it in the .rel file followed by the atom 'none'
  {included_applications, []},

  % configuration parameters similar to those in the config file specified
  % on the command line. can be fetched with gas:get_env
  {env, [
    % If an error/crash occurs during processing of a function,
    % should the TApplicationException serialized back to the client
    % include the erlang backtrace?
    {exceptions_include_traces, true}
  ]}
]}.
thrift-0.19.0/test/erl/src/test_thrift_server.erl0000644000000000000000000002025714303740367022075 0ustar00rootroot00000000000000%%
%% Licensed to the Apache Software Foundation (ASF) under one
%% or more contributor license agreements. See the NOTICE file
%% distributed with this work for additional information
%% regarding copyright ownership. The ASF licenses this file
%% to you under the Apache License, Version 2.0 (the
%% "License"); you may not use this file except in compliance
%% with the License. You may obtain a copy of the License at
%%
%%   http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied. See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%

-module(test_thrift_server).

-export([start/0, start/1, start_link/2, handle_function/2, handle_error/2]).

-include("thrift_constants.hrl").
-include("gen-erl/thrift_test_types.hrl").

-record(options, {port = 9090,
                  server_opts = []}).

parse_args(Args) -> parse_args(Args, #options{}).
parse_args([], Opts) ->
  Opts;
parse_args([Head | Rest], Opts) ->
    NewOpts =
        case Head of
            "--port=" ++ Port ->
                case string:to_integer(Port) of
                  {IntPort,_} when is_integer(IntPort) ->
                    Opts#options{port = IntPort};
                  _Else ->
                    erlang:error({bad_arg, Head})
                end;
            "--transport=" ++ Trans ->
                case Trans of
                    "framed" ->
                        Opts#options{server_opts = [{framed, true} | Opts#options.server_opts]};
                    _Else ->
                        Opts
                end;
            "--ssl" ->
                ssl:start(),
                SslOptions =
                    {ssloptions, [
                         {certfile, "../keys/server.pem"}
                        ,{keyfile,  "../keys/server.key"}
                    ]},
                Opts#options{server_opts = [{ssltransport, true} | [SslOptions | Opts#options.server_opts]]};
            "--protocol=" ++ Proto ->
                Opts#options{server_opts = [{protocol, list_to_atom(Proto)} | Opts#options.server_opts]};
            _Else ->
                erlang:error({bad_arg, Head})
        end,
    parse_args(Rest, NewOpts).

start() -> start(init:get_plain_arguments()).
start(Args) ->
    #options{port = Port, server_opts = ServerOpts} = parse_args(Args),
    spawn(fun() -> start_link(Port, ServerOpts), receive after infinity -> ok end end).

start_link(Port, ServerOpts) ->
    thrift_socket_server:start([{handler, ?MODULE},
                                {service, thrift_test_thrift},
                                {port, Port}] ++
                               ServerOpts).


handle_function(testVoid, {}) ->
    io:format("testVoid~n"),
    ok;

handle_function(testString, {S}) when is_binary(S) ->
    io:format("testString: ~p~n", [S]),
    {reply, S};

handle_function(testBool, {B}) when is_boolean(B) ->
    io:format("testBool: ~p~n", [B]),
    {reply, B};

handle_function(testByte, {I8}) when is_integer(I8) ->
    io:format("testByte: ~p~n", [I8]),
    {reply, I8};

handle_function(testI32, {I32}) when is_integer(I32) ->
    io:format("testI32: ~p~n", [I32]),
    {reply, I32};

handle_function(testI64, {I64}) when is_integer(I64) ->
    io:format("testI64: ~p~n", [I64]),
    {reply, I64};

handle_function(testDouble, {Double}) when is_float(Double) ->
    io:format("testDouble: ~p~n", [Double]),
    {reply, Double};

handle_function(testBinary, {S}) when is_binary(S) ->
    io:format("testBinary: ~p~n", [S]),
    {reply, S};

handle_function(testStruct,
                {Struct = #'thrift.test.Xtruct'{string_thing = String,
                                                byte_thing = Byte,
                                                i32_thing = I32,
                                                i64_thing = I64}})
when is_binary(String),
     is_integer(Byte),
     is_integer(I32),
     is_integer(I64) ->
    io:format("testStruct: ~p~n", [Struct]),
    {reply, Struct};

handle_function(testNest,
                {Nest}) when is_record(Nest, 'thrift.test.Xtruct2'),
                             is_record(Nest#'thrift.test.Xtruct2'.struct_thing, 'thrift.test.Xtruct') ->
    io:format("testNest: ~p~n", [Nest]),
    {reply, Nest};

handle_function(testMap, {Map}) ->
    io:format("testMap: ~p~n", [dict:to_list(Map)]),
    {reply, Map};

handle_function(testStringMap, {Map}) ->
    io:format("testStringMap: ~p~n", [dict:to_list(Map)]),
    {reply, Map};

handle_function(testSet, {Set}) ->
    true = sets:is_set(Set),
    io:format("testSet: ~p~n", [sets:to_list(Set)]),
    {reply, Set};

handle_function(testList, {List}) when is_list(List) ->
    io:format("testList: ~p~n", [List]),
    {reply, List};

handle_function(testEnum, {Enum}) when is_integer(Enum) ->
    io:format("testEnum: ~p~n", [Enum]),
    {reply, Enum};

handle_function(testTypedef, {UserID}) when is_integer(UserID) ->
    io:format("testTypedef: ~p~n", [UserID]),
    {reply, UserID};

handle_function(testMapMap, {Hello}) ->
    io:format("testMapMap: ~p~n", [Hello]),

    PosList = [{I, I}   || I <- lists:seq(1, 4)],
    NegList = [{-I, -I} || I <- lists:seq(1, 4)],

    MapMap = dict:from_list([{4,  dict:from_list(PosList)},
                             {-4, dict:from_list(NegList)}]),
    {reply, MapMap};

handle_function(testInsanity, {Insanity}) when is_record(Insanity, 'thrift.test.Insanity') ->
    Hello = #'thrift.test.Xtruct'{string_thing = <<"Hello2">>,
                                  byte_thing = 2,
                                  i32_thing = 2,
                                  i64_thing = 2},

    Goodbye = #'thrift.test.Xtruct'{string_thing = <<"Goodbye4">>,
                                   byte_thing = 4,
                                    i32_thing = 4,
                                    i64_thing = 4},
    Crazy = #'thrift.test.Insanity'{
               userMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_EIGHT, 8}]),
               xtructs = [Goodbye]
              },

    Looney = #'thrift.test.Insanity'{},

    FirstMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_TWO, Insanity},
                               {?THRIFT_TEST_NUMBERZ_THREE, Insanity}]),

    SecondMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_SIX, Looney}]),

    Insane = dict:from_list([{1, FirstMap},
                             {2, SecondMap}]),

    io:format("Return = ~p~n", [Insane]),

    {reply, Insane};

handle_function(testMulti, Args = {Arg0, Arg1, Arg2, _Arg3, Arg4, Arg5})
  when is_integer(Arg0),
       is_integer(Arg1),
       is_integer(Arg2),
       is_integer(Arg4),
       is_integer(Arg5) ->

    io:format("testMulti(~p)~n", [Args]),
    {reply, #'thrift.test.Xtruct'{string_thing = <<"Hello2">>,
                                  byte_thing = Arg0,
                                  i32_thing = Arg1,
                                  i64_thing = Arg2}};

handle_function(testException, {String}) when is_binary(String) ->
    io:format("testException(~p)~n", [String]),
    case String of
        <<"Xception">> ->
            throw(#'thrift.test.Xception'{errorCode = 1001,
                            message = String});
        <<"TException">> ->
            throw({?TApplicationException_Structure});
        _ ->
            ok
    end;

handle_function(testMultiException, {Arg0, Arg1}) ->
    io:format("testMultiException(~p, ~p)~n", [Arg0, Arg1]),
    case Arg0 of
        <<"Xception">> ->
            throw(#'thrift.test.Xception'{errorCode = 1001,
                                   message = <<"This is an Xception">>});
        <<"Xception2">> ->
            throw(#'thrift.test.Xception2'{errorCode = 2002,
                                    struct_thing =
                                    #'thrift.test.Xtruct'{string_thing = <<"This is an Xception2">>}});
        _ ->
            {reply, #'thrift.test.Xtruct'{string_thing = Arg1}}
    end;

handle_function(testOneway, {Seconds}) ->
    io:format("testOneway: ~p~n", [Seconds]),
    timer:sleep(1000 * Seconds),
    ok.

% This is not mandatory but improving test logs.
handle_error(Arg1, Arg2) ->
  io:format("handle_error is called: ~p ~p~n", [Arg1, Arg2]).
thrift-0.19.0/test/erl/src/test_client.erl0000644000000000000000000001630614303740367020465 0ustar00rootroot00000000000000%%
%% Licensed to the Apache Software Foundation (ASF) under one
%% or more contributor license agreements. See the NOTICE file
%% distributed with this work for additional information
%% regarding copyright ownership. The ASF licenses this file
%% to you under the Apache License, Version 2.0 (the
%% "License"); you may not use this file except in compliance
%% with the License. You may obtain a copy of the License at
%%
%%   http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing,
%% software distributed under the License is distributed on an
%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
%% KIND, either express or implied. See the License for the
%% specific language governing permissions and limitations
%% under the License.
%%

-module(test_client).

-export([start/0, start/1]).

-include("gen-erl/thrift_test_types.hrl").

-record(options, {port = 9090,
                  client_opts = []}).

parse_args(Args) -> parse_args(Args, #options{}).
parse_args([], Opts) ->
  Opts;
parse_args([Head | Rest], Opts) ->
    NewOpts =
        case Head of
            "--port=" ++ Port ->
                case string:to_integer(Port) of
                  {IntPort,_} when is_integer(IntPort) ->
                    Opts#options{port = IntPort};
                  _Else ->
                    erlang:error({bad_arg, Head})
                end;
            "--transport=" ++ Trans ->
                % TODO: Enable Buffered and HTTP transport
                case Trans of
                    "framed" ->
                        Opts#options{client_opts = [{framed, true} | Opts#options.client_opts]};
                    _Else ->
                        Opts
                end;
            "--ssl" ->
                ssl:start(),
                SslOptions =
                    {ssloptions, [
                        {cacertfile, "../keys/CA.pem"},
                        {certfile, "../keys/client.pem"},
                        {keyfile, "../keys/client.key"}
                    ]},
                Opts#options{client_opts = [{ssltransport, true} | [SslOptions | Opts#options.client_opts]]};
            "--protocol=" ++ Proto ->
                Opts#options{client_opts = [{protocol, list_to_atom(Proto)}]};
            _Else ->
                erlang:error({bad_arg, Head})
        end,
    parse_args(Rest, NewOpts).

start() -> start(init:get_plain_arguments()).
start(Args) ->
  #options{port = Port, client_opts = ClientOpts} = parse_args(Args),
  {ok, Client0} = thrift_client_util:new(
    "127.0.0.1", Port, thrift_test_thrift, ClientOpts),

  DemoXtruct = #'thrift.test.Xtruct'{
                  string_thing = <<"Zero">>,
                  byte_thing = 1,
                  i32_thing = 9128361,
                  i64_thing = 9223372036854775807},

  DemoNest = #'thrift.test.Xtruct2'{
    byte_thing = 7,
    struct_thing = DemoXtruct,
    % Note that we don't set i32_thing, it will come back as undefined
    % from the Python server, but 0 from the C++ server, since it is not
    % optional
    i32_thing = 2},

  % Is it safe to match these things?
  DemoDict = dict:from_list([ {Key, Key-10} || Key <- lists:seq(0,10) ]),
  DemoSet = sets:from_list([ Key || Key <- lists:seq(-3,3) ]),

  DemoInsane = #'thrift.test.Insanity'{
    userMap = dict:from_list([{?THRIFT_TEST_NUMBERZ_FIVE, 5000}]),
    xtructs = [#'thrift.test.Xtruct'{ string_thing = <<"Truck">>, byte_thing = 8, i32_thing = 8, i64_thing = 8}]},

  error_logger:info_msg("testVoid"),
  {Client01, {ok, ok}} = thrift_client:call(Client0, testVoid, []),

  error_logger:info_msg("testString"),
  {Client02, {ok, <<"Test">>}}      = thrift_client:call(Client01, testString, ["Test"]),
  error_logger:info_msg("testString"),
  {Client03, {ok, <<"Test">>}}      = thrift_client:call(Client02, testString, [<<"Test">>]),
  error_logger:info_msg("testByte"),
  {Client04, {ok, 63}}              = thrift_client:call(Client03, testByte, [63]),
  error_logger:info_msg("testI32"),
  {Client05, {ok, -1}}              = thrift_client:call(Client04, testI32, [-1]),
  error_logger:info_msg("testI32"),
  {Client06, {ok, 0}}               = thrift_client:call(Client05, testI32, [0]),
  error_logger:info_msg("testI64"),
  {Client07, {ok, -34359738368}}    = thrift_client:call(Client06, testI64, [-34359738368]),
  error_logger:info_msg("testDouble"),
  {Client08, {ok, -5.2098523}}      = thrift_client:call(Client07, testDouble, [-5.2098523]),
  %% TODO: add testBinary() call
  error_logger:info_msg("testStruct"),
  {Client09, {ok, DemoXtruct}}      = thrift_client:call(Client08, testStruct, [DemoXtruct]),
  error_logger:info_msg("testNest"),
  {Client10, {ok, DemoNest}}        = thrift_client:call(Client09, testNest, [DemoNest]),
  error_logger:info_msg("testMap"),
  {Client11, {ok, DemoDict}}        = thrift_client:call(Client10, testMap, [DemoDict]),
  error_logger:info_msg("testSet"),
  {Client12, {ok, DemoSet}}         = thrift_client:call(Client11, testSet, [DemoSet]),
  error_logger:info_msg("testList"),
  {Client13, {ok, [-1,2,3]}}        = thrift_client:call(Client12, testList, [[-1,2,3]]),
  error_logger:info_msg("testEnum"),
  {Client14, {ok, 1}}               = thrift_client:call(Client13, testEnum, [?THRIFT_TEST_NUMBERZ_ONE]),
  error_logger:info_msg("testTypedef"),
  {Client15, {ok, 309858235082523}} = thrift_client:call(Client14, testTypedef, [309858235082523]),
  error_logger:info_msg("testInsanity"),
  {Client16, {ok, InsaneResult}}    = thrift_client:call(Client15, testInsanity, [DemoInsane]),
  io:format("~p~n", [InsaneResult]),

  {Client17, {ok, #'thrift.test.Xtruct'{string_thing = <<"Message">>}}} =
    thrift_client:call(Client16, testMultiException, ["Safe", "Message"]),

  Client18 =
    try
      {ClientS1, Result1} = thrift_client:call(Client17, testMultiException, ["Xception", "Message"]),
      io:format("Unexpected return! ~p~n", [Result1]),
      ClientS1
    catch
      throw:{ClientS2, {exception, ExnS1 = #'thrift.test.Xception'{}}} ->
        #'thrift.test.Xception'{errorCode = 1001, message = <<"This is an Xception">>} = ExnS1,
        ClientS2;
      throw:{ClientS2, {exception, _ExnS1 = #'thrift.test.Xception2'{}}} ->
        io:format("Wrong exception type!~n", []),
        ClientS2
    end,

  Client19 =
    try
      {ClientS3, Result2} = thrift_client:call(Client18, testMultiException, ["Xception2", "Message"]),
      io:format("Unexpected return! ~p~n", [Result2]),
      ClientS3
    catch
      throw:{ClientS4, {exception, _ExnS2 = #'thrift.test.Xception'{}}} ->
        io:format("Wrong exception type!~n", []),
        ClientS4;
      throw:{ClientS4, {exception, ExnS2 = #'thrift.test.Xception2'{}}} ->
        #'thrift.test.Xception2'{errorCode = 2002,
                   struct_thing = #'thrift.test.Xtruct'{
                     string_thing = <<"This is an Xception2">>}} = ExnS2,
        ClientS4
    end,

  %% Started = erlang:monotonic_time(milli_seconds),
  {_, StartSec, StartUSec} = erlang:timestamp(),
  error_logger:info_msg("testOneway"),
  {Client20, {ok, ok}} = thrift_client:call(Client19, testOneway, [1]),
  {_, EndSec, EndUSec} = erlang:timestamp(),
  Elapsed = (EndSec - StartSec) * 1000 + (EndUSec - StartUSec) / 1000,
  if
    Elapsed > 1000 -> exit(1);
    true -> true
  end,

  thrift_client:close(Client20).
thrift-0.19.0/test/erl/rebar.config0000644000000000000000000000013614303740367017131 0ustar00rootroot00000000000000{sub_dirs, ["../../lib/erl"]}.

{erl_opts, [
  debug_info,
  {i, "../../lib/erl/include"}
]}.
thrift-0.19.0/test/erl/Makefile.in0000644000000000000000000004353314472652520016724 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.

@SET_MAKE@

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = test/erl
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANT = @ANT@
ANT_FLAGS = @ANT_FLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BISON = @BISON@
BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_LIB_DIR = @BOOST_LIB_DIR@
BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@
BOOST_TEST_LDADD = @BOOST_TEST_LDADD@
BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@
BUNDLER = @BUNDLER@
CARGO = @CARGO@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CLASSPATH = @CLASSPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPSTYLE_CMD = @CPPSTYLE_CMD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DART = @DART@
DARTPUB = @DARTPUB@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DMD = @DMD@
DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@
DMD_OF_DIRSEP = @DMD_OF_DIRSEP@
DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@
DOTNETCORE = @DOTNETCORE@
DOTNETCORE_VERSION = @DOTNETCORE_VERSION@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@
D_IMPORT_PREFIX = @D_IMPORT_PREFIX@
D_LIB_NAME = @D_LIB_NAME@
D_SSL_LIB_NAME = @D_SSL_LIB_NAME@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_COVERAGE = @ENABLE_COVERAGE@
ERL = @ERL@
ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@
ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@
ERLANG_LIB_DIR = @ERLANG_LIB_DIR@
ERLC = @ERLC@
ERLCFLAGS = @ERLCFLAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GCOV_CFLAGS = @GCOV_CFLAGS@
GCOV_CXXFLAGS = @GCOV_CXXFLAGS@
GCOV_LDFLAGS = @GCOV_LDFLAGS@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GO = @GO@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
GOBJECT_LIBS = @GOBJECT_LIBS@
GRADLE = @GRADLE@
GRADLE_OPTS = @GRADLE_OPTS@
GREP = @GREP@
GSETTINGS = @GSETTINGS@
HAVE_CXX11 = @HAVE_CXX11@
HAXE = @HAXE@
HAXE_VERSION = @HAXE_VERSION@
INSTALL = @INSTALL@
INSTALLDIRS = @INSTALLDIRS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JAVA_PREFIX = @JAVA_PREFIX@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@
LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@
LIBEVENT_LIBS = @LIBEVENT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
LUA = @LUA@
LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@
LUA_INCLUDE = @LUA_INCLUDE@
LUA_LIB = @LUA_LIB@
LUA_PLATFORM = @LUA_PLATFORM@
LUA_PREFIX = @LUA_PREFIX@
LUA_SHORT_VERSION = @LUA_SHORT_VERSION@
LUA_VERSION = @LUA_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MAYBE_CL = @MAYBE_CL@
MAYBE_CPP = @MAYBE_CPP@
MAYBE_C_GLIB = @MAYBE_C_GLIB@
MAYBE_D = @MAYBE_D@
MAYBE_DART = @MAYBE_DART@
MAYBE_ERLANG = @MAYBE_ERLANG@
MAYBE_GO = @MAYBE_GO@
MAYBE_JAVA = @MAYBE_JAVA@
MAYBE_KOTLIN = @MAYBE_KOTLIN@
MAYBE_LUA = @MAYBE_LUA@
MAYBE_NETSTD = @MAYBE_NETSTD@
MAYBE_NODEJS = @MAYBE_NODEJS@
MAYBE_NODETS = @MAYBE_NODETS@
MAYBE_PERL = @MAYBE_PERL@
MAYBE_PHP = @MAYBE_PHP@
MAYBE_PY3 = @MAYBE_PY3@
MAYBE_PYTHON = @MAYBE_PYTHON@
MAYBE_RS = @MAYBE_RS@
MAYBE_RUBY = @MAYBE_RUBY@
MAYBE_SWIFT = @MAYBE_SWIFT@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NODEJS = @NODEJS@
NODETS = @NODETS@
NPM = @NPM@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PERL_PREFIX = @PERL_PREFIX@
PHP = @PHP@
PHP_CONFIG = @PHP_CONFIG@
PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@
PHP_PREFIX = @PHP_PREFIX@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PYTHON = @PYTHON@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
PY_PREFIX = @PY_PREFIX@
QT5_CFLAGS = @QT5_CFLAGS@
QT5_LIBS = @QT5_LIBS@
QT5_MOC = @QT5_MOC@
RANLIB = @RANLIB@
REBAR = @REBAR@
RUBY = @RUBY@
RUBY_PREFIX = @RUBY_PREFIX@
RUSTC = @RUSTC@
SBCL = @SBCL@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SWIFT = @SWIFT@
THRIFT = @THRIFT@
TRIAL = @TRIAL@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@
ZLIB_LDFLAGS = @ZLIB_LDFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
golang_version = @golang_version@
have_prog_bison = @have_prog_bison@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
luadir = @luadir@
luaexecdir = @luaexecdir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgluadir = @pkgluadir@
pkgluaexecdir = @pkgluaexecdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
rustc_version = @rustc_version@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
THRIFT_FILES = $(wildcard ../*.thrift)
ERL_FLAG = erl
all: all-am

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/erl/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/erl/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs
style-local: 
tags TAGS:

ctags CTAGS:

cscope cscopelist:


distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	$(MAKE) $(AM_MAKEFLAGS) \
	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
	  dist-hook
check-am: all-am
check: check-am
all-am: Makefile
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean-am: clean-generic clean-libtool mostlyclean-am

distclean: distclean-am
	-rm -f Makefile
distclean-am: clean-am distclean-generic

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic \
	maintainer-clean-local

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

style: style-am

style-am: style-local

uninstall-am:

.MAKE: install-am install-strip

.PHONY: all all-am check check-am clean clean-generic clean-libtool \
	cscopelist-am ctags-am dist-hook distclean distclean-generic \
	distclean-libtool distdir dvi dvi-am html html-am info info-am \
	install install-am install-data install-data-am install-dvi \
	install-dvi-am install-exec install-exec-am install-html \
	install-html-am install-info install-info-am install-man \
	install-pdf install-pdf-am install-ps install-ps-am \
	install-strip installcheck installcheck-am installdirs \
	maintainer-clean maintainer-clean-generic \
	maintainer-clean-local mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \
	tags-am uninstall uninstall-am

.PRECIOUS: Makefile

# make sure ThriftTest.thrift is generated last to prevent conflicts with other *.thrift files
.generated: $(THRIFT_FILES)
	for f in $(THRIFT_FILES) ; do \
	  $(THRIFT) --gen $(ERL_FLAG) -o src $$f ; \
	done ; \
	$(THRIFT) --gen $(ERL_FLAG) -o src ../v0.16/ThriftTest.thrift
	touch .generated

precross: .generated
	$(REBAR) compile

maintainer-clean-local:
	$(RM) -r ebin/

clean:
	$(REBAR) clean
	$(RM)    .generated
	$(RM) -r .rebar/
	$(RM) -r src/gen-erl/

dist-hook:
	$(RM)    $(distdir)/.generated
	$(RM) -r $(distdir)/.rebar/
	$(RM) -r $(distdir)/ebin/
	$(RM) -r $(distdir)/src/gen-erl/

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/NameConflictTest.thrift0000644000000000000000000000540414370300523020502 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

// Naming testcases, sepcifically for these tickets (but not limited to them)
// THRIFT-2508 Uncompileable C# code due to language keywords in IDL
// THRIFT-2557 error CS0542 member names cannot be the same as their enclosing type


struct using {
    1: double single
    2: double integer
}

struct delegate {
    1: string partial
    2: delegate delegate
}

struct get {
    1: bool sbyte
}

struct partial {
    1: using using
    2: bool read
    3: bool write
}

enum Maybe {
  JUST = 1,
  TRUE = 2,
  FALSE = 3
}

enum Either {
  LEFT = 1,
  RIGHT = 2
}

struct foldr {
  1: string id
}

struct of {
  1: string let
  2: string where
}

struct ofOf {
  1: of Of
}


struct ClassAndProp {
  1: bool ClassAndProp
  2: bool ClassAndProp_
  3: bool ClassAndProp__
  4: bool ClassAndProper
}

struct second_chance {
  1: bool SECOND_CHANCE
  2: bool SECOND_CHANCE_
  3: bool SECOND_CHANCE__
  4: bool SECOND_CHANCES
}

struct NOW_EAT_THIS {
  1: bool now_eat_this
  2: bool now_eat_this_
  3: bool now_eat_this__
  4: bool now_eat_this_and_this
}

struct TheEdgeCase {
  1: bool theEdgeCase
  2: bool theEdgeCase_
  3: bool theEdgeCase__
  4: bool TheEdgeCase
  5: bool TheEdgeCase_
  6: bool TheEdgeCase__
}

struct Tricky_ {
  1: bool tricky
  2: bool Tricky
}

struct Nested {
  1: ClassAndProp ClassAndProp
  2: second_chance second_chance
  3: NOW_EAT_THIS NOW_EAT_THIS
  4: TheEdgeCase TheEdgeCase
  5: Tricky_ Tricky_
  6: Nested Nested
}

exception Problem_ {
  1: bool problem
  2: bool Problem
}

struct Thrift5626 {
   1: i8       i8
   2: i16      i16
   3: i32      i32
   4: i64      i64
   5: uuid     uuid
   6: string   string
   7: binary   binary
   8: bool     bool
   9: byte     byte
  10: list        list
  11: set         set
  12: map  map
}

service extern {
    delegate event(1: partial get)
    void Foo(1: Nested Foo_args) throws (1: Problem_ Foo_result)
}

service qualified {
    Maybe maybe(1: Maybe foldr)
    Either either(1: foldr of)
}
// eof
thrift-0.19.0/test/StressTest.thrift0000644000000000000000000000220714303740367017433 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

namespace cpp test.stress
namespace d thrift.test.stress
namespace go stress

service Service {

  void echoVoid(),
  i8 echoByte(1: i8 arg),
  i32 echoI32(1: i32 arg),
  i64 echoI64(1: i64 arg),
  string echoString(1: string arg),
  list  echoList(1: list arg),
  set  echoSet(1: set arg),
  map  echoMap(1: map arg),
}

thrift-0.19.0/test/Makefile.in0000644000000000000000000006645514472652520016152 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.

@SET_MAKE@

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@WITH_C_GLIB_TRUE@am__append_1 = c_glib
@WITH_C_GLIB_TRUE@am__append_2 = precross-c_glib
@WITH_CL_TRUE@am__append_3 = cl
@WITH_CL_TRUE@am__append_4 = precross-cl
@WITH_CPP_TRUE@am__append_5 = cpp
@WITH_CPP_TRUE@am__append_6 = precross-cpp
@WITH_PERL_TRUE@am__append_7 = perl
@WITH_PERL_TRUE@am__append_8 = precross-perl
@WITH_PHP_TRUE@am__append_9 = php
@WITH_PHP_TRUE@am__append_10 = precross-php
@WITH_DART_TRUE@am__append_11 = dart
@WITH_DART_TRUE@am__append_12 = precross-dart
@WITH_PYTHON_TRUE@am__append_13 = py py.tornado
@WITH_PYTHON_TRUE@am__append_14 = precross-py
@WITH_PYTHON_TRUE@@WITH_TWISTED_TEST_TRUE@am__append_15 = py.twisted
@WITH_RUBY_TRUE@am__append_16 = rb
@WITH_RUBY_TRUE@am__append_17 = precross-rb
@WITH_HAXE_TRUE@am__append_18 = haxe
@WITH_DOTNET_TRUE@am__append_19 = netstd
@WITH_GO_TRUE@am__append_20 = go
@WITH_GO_TRUE@am__append_21 = precross-go
@WITH_ERLANG_TRUE@am__append_22 = erl
@WITH_ERLANG_TRUE@am__append_23 = precross-erl
@WITH_LUA_TRUE@am__append_24 = lua
@WITH_LUA_TRUE@am__append_25 = precross-lua
@WITH_RS_TRUE@am__append_26 = rs
@WITH_RS_TRUE@am__append_27 = precross-rs
@WITH_SWIFT_TRUE@am__append_28 = swift
@WITH_SWIFT_TRUE@am__append_29 = precross-swift
subdir = test
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
	ctags-recursive dvi-recursive html-recursive info-recursive \
	install-data-recursive install-dvi-recursive \
	install-exec-recursive install-html-recursive \
	install-info-recursive install-pdf-recursive \
	install-ps-recursive install-recursive installcheck-recursive \
	installdirs-recursive pdf-recursive ps-recursive \
	tags-recursive uninstall-recursive
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
  distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
  $(RECURSIVE_TARGETS) \
  $(RECURSIVE_CLEAN_TARGETS) \
  $(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
	distdir
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = features c_glib cl cpp perl php dart py py.tornado \
	py.twisted rb haxe netstd go erl lua rs swift
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
  dir0=`pwd`; \
  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
  sed_rest='s,^[^/]*/*,,'; \
  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
  sed_butlast='s,/*[^/]*$$,,'; \
  while test -n "$$dir1"; do \
    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
    if test "$$first" != "."; then \
      if test "$$first" = ".."; then \
        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
      else \
        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
        if test "$$first2" = "$$first"; then \
          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
        else \
          dir2="../$$dir2"; \
        fi; \
        dir0="$$dir0"/"$$first"; \
      fi; \
    fi; \
    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
  done; \
  reldir="$$dir2"
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANT = @ANT@
ANT_FLAGS = @ANT_FLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BISON = @BISON@
BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_LIB_DIR = @BOOST_LIB_DIR@
BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@
BOOST_TEST_LDADD = @BOOST_TEST_LDADD@
BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@
BUNDLER = @BUNDLER@
CARGO = @CARGO@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CLASSPATH = @CLASSPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPSTYLE_CMD = @CPPSTYLE_CMD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DART = @DART@
DARTPUB = @DARTPUB@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DMD = @DMD@
DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@
DMD_OF_DIRSEP = @DMD_OF_DIRSEP@
DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@
DOTNETCORE = @DOTNETCORE@
DOTNETCORE_VERSION = @DOTNETCORE_VERSION@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@
D_IMPORT_PREFIX = @D_IMPORT_PREFIX@
D_LIB_NAME = @D_LIB_NAME@
D_SSL_LIB_NAME = @D_SSL_LIB_NAME@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_COVERAGE = @ENABLE_COVERAGE@
ERL = @ERL@
ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@
ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@
ERLANG_LIB_DIR = @ERLANG_LIB_DIR@
ERLC = @ERLC@
ERLCFLAGS = @ERLCFLAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GCOV_CFLAGS = @GCOV_CFLAGS@
GCOV_CXXFLAGS = @GCOV_CXXFLAGS@
GCOV_LDFLAGS = @GCOV_LDFLAGS@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GO = @GO@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
GOBJECT_LIBS = @GOBJECT_LIBS@
GRADLE = @GRADLE@
GRADLE_OPTS = @GRADLE_OPTS@
GREP = @GREP@
GSETTINGS = @GSETTINGS@
HAVE_CXX11 = @HAVE_CXX11@
HAXE = @HAXE@
HAXE_VERSION = @HAXE_VERSION@
INSTALL = @INSTALL@
INSTALLDIRS = @INSTALLDIRS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JAVA_PREFIX = @JAVA_PREFIX@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@
LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@
LIBEVENT_LIBS = @LIBEVENT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
LUA = @LUA@
LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@
LUA_INCLUDE = @LUA_INCLUDE@
LUA_LIB = @LUA_LIB@
LUA_PLATFORM = @LUA_PLATFORM@
LUA_PREFIX = @LUA_PREFIX@
LUA_SHORT_VERSION = @LUA_SHORT_VERSION@
LUA_VERSION = @LUA_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MAYBE_CL = @MAYBE_CL@
MAYBE_CPP = @MAYBE_CPP@
MAYBE_C_GLIB = @MAYBE_C_GLIB@
MAYBE_D = @MAYBE_D@
MAYBE_DART = @MAYBE_DART@
MAYBE_ERLANG = @MAYBE_ERLANG@
MAYBE_GO = @MAYBE_GO@
MAYBE_JAVA = @MAYBE_JAVA@
MAYBE_KOTLIN = @MAYBE_KOTLIN@
MAYBE_LUA = @MAYBE_LUA@
MAYBE_NETSTD = @MAYBE_NETSTD@
MAYBE_NODEJS = @MAYBE_NODEJS@
MAYBE_NODETS = @MAYBE_NODETS@
MAYBE_PERL = @MAYBE_PERL@
MAYBE_PHP = @MAYBE_PHP@
MAYBE_PY3 = @MAYBE_PY3@
MAYBE_PYTHON = @MAYBE_PYTHON@
MAYBE_RS = @MAYBE_RS@
MAYBE_RUBY = @MAYBE_RUBY@
MAYBE_SWIFT = @MAYBE_SWIFT@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NODEJS = @NODEJS@
NODETS = @NODETS@
NPM = @NPM@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PERL_PREFIX = @PERL_PREFIX@
PHP = @PHP@
PHP_CONFIG = @PHP_CONFIG@
PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@
PHP_PREFIX = @PHP_PREFIX@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PYTHON = @PYTHON@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
PY_PREFIX = @PY_PREFIX@
QT5_CFLAGS = @QT5_CFLAGS@
QT5_LIBS = @QT5_LIBS@
QT5_MOC = @QT5_MOC@
RANLIB = @RANLIB@
REBAR = @REBAR@
RUBY = @RUBY@
RUBY_PREFIX = @RUBY_PREFIX@
RUSTC = @RUSTC@
SBCL = @SBCL@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SWIFT = @SWIFT@
THRIFT = @THRIFT@
TRIAL = @TRIAL@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@
ZLIB_LDFLAGS = @ZLIB_LDFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
golang_version = @golang_version@
have_prog_bison = @have_prog_bison@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
luadir = @luadir@
luaexecdir = @luaexecdir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgluadir = @pkgluadir@
pkgluaexecdir = @pkgluaexecdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
rustc_version = @rustc_version@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = features $(am__append_1) $(am__append_3) $(am__append_5) \
	$(am__append_7) $(am__append_9) $(am__append_11) \
	$(am__append_13) $(am__append_15) $(am__append_16) \
	$(am__append_18) $(am__append_19) $(am__append_20) \
	$(am__append_22) $(am__append_24) $(am__append_26) \
	$(am__append_28)
PRECROSS_TARGET = $(am__append_2) $(am__append_4) $(am__append_6) \
	$(am__append_8) $(am__append_10) $(am__append_12) \
	$(am__append_14) $(am__append_17) $(am__append_21) \
	$(am__append_23) $(am__append_25) $(am__append_27) \
	$(am__append_29)
EXTRA_DIST = \
	audit \
	c_glib \
	cl \
	cpp \
	crossrunner \
	dart \
	erl \
	keys \
	lua \
	ocaml \
	perl \
	php \
	py \
	py.tornado \
	py.twisted \
	rb \
	rs \
	swift \
	threads \
	partial \
	AnnotationTest.thrift \
	BrokenConstants.thrift \
	ConstantsDemo.thrift \
	DebugProtoTest.thrift \
	v0.16/DebugProtoTest.thrift \
	DenseLinkingTest.thrift \
	DocTest.thrift \
	DoubleConstantsTest.thrift \
	EnumContainersTest.thrift \
	EnumTest.thrift \
	FullCamelTest.thrift \
	Include.thrift \
	Identifiers.thrift \
	Int64Test.thrift \
	JsDeepConstructorTest.thrift \
	ManyOptionals.thrift \
	ManyTypedefs.thrift \
	NameConflictTest.thrift \
	OptionalRequiredTest.thrift \
	Recursive.thrift \
	ReuseObjects.thrift \
	SmallTest.thrift \
	StressTest.thrift \
	ThriftTest.thrift \
	v0.16/ThriftTest.thrift \
	TypedefTest.thrift \
	Types.thrift \
	UnsafeTypes.thrift \
	Service.thrift \
	SpecificNameTest.thrift \
	VoidMethExceptionsTest.thrift \
	partial/thrift_test_schema.thrift \
	keys/keygen/.gitignore \
	known_failures_Linux.json \
	test.py \
	tests.json \
	rebuild_known_failures.sh \
	result.js \
	index.html \
	README.md \
	valgrind.suppress

all: all-recursive

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
#     (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
	@fail=; \
	if $(am__make_keepgoing); then \
	  failcom='fail=yes'; \
	else \
	  failcom='exit 1'; \
	fi; \
	dot_seen=no; \
	target=`echo $@ | sed s/-recursive//`; \
	case "$@" in \
	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
	  *) list='$(SUBDIRS)' ;; \
	esac; \
	for subdir in $$list; do \
	  echo "Making $$target in $$subdir"; \
	  if test "$$subdir" = "."; then \
	    dot_seen=yes; \
	    local_target="$$target-am"; \
	  else \
	    local_target="$$target"; \
	  fi; \
	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
	  || eval $$failcom; \
	done; \
	if test "$$dot_seen" = "no"; then \
	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
	fi; test -z "$$fail"
style-local: 

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
	  include_option=--etags-include; \
	  empty_fix=.; \
	else \
	  include_option=--include; \
	  empty_fix=; \
	fi; \
	list='$(SUBDIRS)'; for subdir in $$list; do \
	  if test "$$subdir" = .; then :; else \
	    test ! -f $$subdir/TAGS || \
	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
	  fi; \
	done; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-recursive

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
	  if test "$$subdir" = .; then :; else \
	    $(am__make_dryrun) \
	      || test -d "$(distdir)/$$subdir" \
	      || $(MKDIR_P) "$(distdir)/$$subdir" \
	      || exit 1; \
	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
	    $(am__relativize); \
	    new_distdir=$$reldir; \
	    dir1=$$subdir; dir2="$(top_distdir)"; \
	    $(am__relativize); \
	    new_top_distdir=$$reldir; \
	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
	    ($(am__cd) $$subdir && \
	      $(MAKE) $(AM_MAKEFLAGS) \
	        top_distdir="$$new_top_distdir" \
	        distdir="$$new_distdir" \
		am__remove_distdir=: \
		am__skip_length_check=: \
		am__skip_mode_fix=: \
	        distdir) \
	      || exit 1; \
	  fi; \
	done
	$(MAKE) $(AM_MAKEFLAGS) \
	  top_distdir="$(top_distdir)" distdir="$(distdir)" \
	  dist-hook
check-am: all-am
	$(MAKE) $(AM_MAKEFLAGS) check-local
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-recursive
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive

clean-am: clean-generic clean-libtool clean-local mostlyclean-am

distclean: distclean-recursive
	-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags

dvi: dvi-recursive

dvi-am:

html: html-recursive

html-am:

info: info-recursive

info-am:

install-data-am:

install-dvi: install-dvi-recursive

install-dvi-am:

install-exec-am:

install-html: install-html-recursive

install-html-am:

install-info: install-info-recursive

install-info-am:

install-man:

install-pdf: install-pdf-recursive

install-pdf-am:

install-ps: install-ps-recursive

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-recursive
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-recursive

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-recursive

pdf-am:

ps: ps-recursive

ps-am:

style: style-recursive

style-am: style-local

uninstall-am:

.MAKE: $(am__recursive_targets) check-am install-am install-strip

.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
	check-am check-local clean clean-generic clean-libtool \
	clean-local cscopelist-am ctags ctags-am dist-hook distclean \
	distclean-generic distclean-libtool distclean-tags distdir dvi \
	dvi-am html html-am info info-am install install-am \
	install-data install-data-am install-dvi install-dvi-am \
	install-exec install-exec-am install-html install-html-am \
	install-info install-info-am install-man install-pdf \
	install-pdf-am install-ps install-ps-am install-strip \
	installcheck installcheck-am installdirs installdirs-am \
	maintainer-clean maintainer-clean-generic mostlyclean \
	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
	style-am style-local tags tags-am uninstall uninstall-am

.PRECIOUS: Makefile


#
# generate html for ThriftTest.thrift AND validate it!
#
@WITH_NODEJS_TRUE@check-local:
@WITH_NODEJS_TRUE@	$(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift
@WITH_NODEJS_TRUE@	$(top_builddir)/node_modules/.bin/html-validator --file=gen-html/index.html --verbose
@WITH_NODEJS_TRUE@	$(top_builddir)/node_modules/.bin/html-validator --file=gen-html/ThriftTest.html --verbose
@WITH_NODEJS_FALSE@check-local:
@WITH_NODEJS_FALSE@	$(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift

clean-local:
	$(RM) -r $(top_srcdir)/test/gen-html/
	find . -type d -name "__pycache__" | xargs rm -rf
	find . -type f -name "*.pyc" | xargs rm -f

dist-hook:
	$(RM) -r $(distdir)/gen-html/
	find $(distdir) -type d -name "__pycache__" | xargs rm -rf
	find $(distdir) -type f -name "*.pyc" | xargs rm -f

precross-%:
	$(MAKE) -C $* precross
precross: $(PRECROSS_TARGET)

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/Recursive.thrift0000644000000000000000000000222714303740367017261 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

struct RecTree {
  1: list children
  2: i16 item
}

struct RecList {
  1: RecList & nextitem
  3: i16 item
}

struct CoRec {
  1:  CoRec2 & other
}

struct CoRec2 {
  1: CoRec other
}

struct VectorTest {
  1: list lister;
}

service TestService
{
  RecTree echoTree(1:RecTree tree)
  RecList echoList(1:RecList lst)
  CoRec echoCoRec(1:CoRec item)
}
thrift-0.19.0/test/netstd/0000755000000000000000000000000014472652675015401 5ustar00rootroot00000000000000thrift-0.19.0/test/netstd/Makefile.am0000644000000000000000000000212214303740367017417 0ustar00rootroot00000000000000#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

SUBDIRS = . 

all-local:
	$(DOTNETCORE) build -c Release

precross:
	$(DOTNETCORE) build -c Release

clean-local:
	$(RM) -r Client/bin
	$(RM) -r Server/bin
	$(RM) -r Client/obj
	$(RM) -r Server/obj
	$(RM) -r ThriftTest/ThriftTest

EXTRA_DIST = \
	Client \
	README.md \
	Server \
	ThriftTest.sln \
	build.cmd \
	build.sh
thrift-0.19.0/test/netstd/Client/0000777000000000000000000000000014454461475016617 5ustar00rootroot00000000000000thrift-0.19.0/test/netstd/Client/TestClient.cs0000644000000000000000000011256414452237057021224 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

#pragma warning disable IDE0066 // switch expression
#pragma warning disable IDE0057 // substring
#pragma warning disable CS1998  // no await in async method

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Thrift;
using Thrift.Collections;
using Thrift.Protocol;
using Thrift.Transport;
using Thrift.Transport.Client;

namespace ThriftTest
{
    internal enum ProtocolChoice
    {
        Binary,
        Compact,
        Json
    }

    // it does not make much sense to use buffered when we already use framed
    internal enum LayeredChoice
    {
        None,
        Buffered,
        Framed
    }

    internal enum TransportChoice
    {
        Socket,
        TlsSocket,
        Http,
        NamedPipe
    }

    public class TestClient
    {
        private class TestParams
        {
            public int numIterations = 1;
            public string host = "localhost";
            public int port = 9090;
            public int numThreads = 1;
            public string url = string.Empty;
            public string pipe = string.Empty;
            public LayeredChoice layered = LayeredChoice.None;
            public ProtocolChoice protocol = ProtocolChoice.Binary;
            public TransportChoice transport = TransportChoice.Socket;
            private readonly TConfiguration Configuration = new();

            internal void Parse(List args)
            {
                for (var i = 0; i < args.Count; ++i)
                {
                    if (args[i] == "-u")
                    {
                        url = args[++i];
                        transport = TransportChoice.Http;
                    }
                    else if (args[i] == "-n")
                    {
                        numIterations = Convert.ToInt32(args[++i]);
                    }
                    else if (args[i].StartsWith("--pipe="))
                    {
                        pipe = args[i].Substring(args[i].IndexOf("=") + 1);
                        transport = TransportChoice.NamedPipe;
                    }
                    else if (args[i].StartsWith("--host="))
                    {
                        // check there for ipaddress
                        host = args[i].Substring(args[i].IndexOf("=") + 1);
                        if (transport != TransportChoice.TlsSocket)
                            transport = TransportChoice.Socket;
                    }
                    else if (args[i].StartsWith("--port="))
                    {
                        port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1));
                        if (transport != TransportChoice.TlsSocket)
                            transport = TransportChoice.Socket;
                    }
                    else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered")
                    {
                        layered = LayeredChoice.Buffered;
                    }
                    else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed")
                    {
                        layered = LayeredChoice.Framed;
                    }
                    else if (args[i] == "-t")
                    {
                        numThreads = Convert.ToInt32(args[++i]);
                    }
                    else if (args[i] == "--binary" || args[i] == "--protocol=binary")
                    {
                        protocol = ProtocolChoice.Binary;
                    }
                    else if (args[i] == "--compact" || args[i] == "--protocol=compact")
                    {
                        protocol = ProtocolChoice.Compact;
                    }
                    else if (args[i] == "--json" || args[i] == "--protocol=json")
                    {
                        protocol = ProtocolChoice.Json;
                    }
                    else if (args[i] == "--ssl")
                    {
                        transport = TransportChoice.TlsSocket;
                    }
                    else if (args[i] == "--help")
                    {
                        PrintOptionsHelp();
                        return;
                    }
                    else
                    {
                        Console.WriteLine("Invalid argument: {0}", args[i]);
                        PrintOptionsHelp();
                        return;
                    }
                }

                switch (transport)
                {
                    case TransportChoice.Socket:
                        Console.WriteLine("Using socket transport");
                        break;
                    case TransportChoice.TlsSocket:
                        Console.WriteLine("Using encrypted transport");
                        break;
                    case TransportChoice.Http:
                        Console.WriteLine("Using HTTP transport");
                        break;
                    case TransportChoice.NamedPipe:
                        Console.WriteLine("Using named pipes transport");
                        break;
                    default:  // unhandled case
                        Debug.Assert(false);
                        break;
                }

                switch (layered)
                {
                    case LayeredChoice.Framed:
                        Console.WriteLine("Using framed transport");
                        break;
                    case LayeredChoice.Buffered:
                        Console.WriteLine("Using buffered transport");
                        break;
                    default:  // unhandled case?
                        Debug.Assert(layered == LayeredChoice.None);
                        break;
                }

                switch (protocol)
                {
                    case ProtocolChoice.Binary:
                        Console.WriteLine("Using binary protocol");
                        break;
                    case ProtocolChoice.Compact:
                        Console.WriteLine("Using compact protocol");
                        break;
                    case ProtocolChoice.Json:
                        Console.WriteLine("Using JSON protocol");
                        break;
                    default:  // unhandled case?
                        Debug.Assert(false);
                        break;
                }
            }

            private static X509Certificate2 GetClientCert()
            {
                var clientCertName = "client.p12";
                var possiblePaths = new List
                {
                    "../../../keys/",
                    "../../keys/",
                    "../keys/",
                    "keys/",
                };

                var existingPath = string.Empty;
                foreach (var possiblePath in possiblePaths)
                {
                    var path = Path.GetFullPath(possiblePath + clientCertName);
                    if (File.Exists(path))
                    {
                        existingPath = path;
                        break;
                    }
                }

                if (string.IsNullOrEmpty(existingPath))
                {
                    throw new FileNotFoundException($"Cannot find file: {clientCertName}");
                }

                var cert = new X509Certificate2(existingPath, "thrift");

                return cert;
            }

            public TTransport CreateTransport()
            {
                // endpoint transport
                TTransport trans;
                switch (transport)
                {
                    case TransportChoice.Http:
                        Debug.Assert(url != null);
                        trans = new THttpTransport(new Uri(url), Configuration);
                        break;

                    case TransportChoice.NamedPipe:
                        Debug.Assert(pipe != null);
                        trans = new TNamedPipeTransport(pipe,Configuration);
                        break;

                    case TransportChoice.TlsSocket:
                        var cert = GetClientCert();
                        if (cert == null || !cert.HasPrivateKey)
                        {
                            throw new InvalidOperationException("Certificate doesn't contain private key");
                        }

                        trans = new TTlsSocketTransport(host, port, Configuration, 0,
                            cert,
                            (sender, certificate, chain, errors) => true,
                            null, SslProtocols.Tls12);
                        break;

                    case TransportChoice.Socket:
                    default:
                        trans = new TSocketTransport(host, port, Configuration);
                        break;
                }


                // layered transport
                switch (layered)
                {
                    case LayeredChoice.Buffered:
                        trans = new TBufferedTransport(trans);
                        break;
                    case LayeredChoice.Framed:
                        trans = new TFramedTransport(trans);
                        break;
                    default:
                        Debug.Assert(layered == LayeredChoice.None);
                        break;
                }

                return trans;
            }

            public TProtocol CreateProtocol(TTransport transport)
            {
                switch (protocol)
                {
                    case ProtocolChoice.Compact:
                        return new TCompactProtocol(transport);
                    case ProtocolChoice.Json:
                        return new TJsonProtocol(transport);
                    case ProtocolChoice.Binary:
                    default:
                        return new TBinaryProtocol(transport);
                }
            }
        }


        private const int ErrorBaseTypes = 1;
        private const int ErrorStructs = 2;
        private const int ErrorContainers = 4;
        private const int ErrorExceptions = 8;
        private const int ErrorUnknown = 64;

        private class ClientTest
        {
            private readonly TTransport transport;
            private readonly ThriftTest.Client client;
            private readonly int numIterations;
            private bool done;

            public int ReturnCode { get; set; }

            public ClientTest(TestParams param)
            {
                transport = param.CreateTransport();
                client = new ThriftTest.Client(param.CreateProtocol(transport));
                numIterations = param.numIterations;
            }

            public async Task Execute()
            {
                if (done)
                {
                    Console.WriteLine("Execute called more than once");
                    throw new InvalidOperationException();
                }

                for (var i = 0; i < numIterations; i++)
                {
                    try
                    {
                        if (!transport.IsOpen)
                            await transport.OpenAsync(MakeTimeoutToken());
                    }
                    catch (TTransportException ex)
                    {
                        Console.WriteLine("*** FAILED ***");
                        Console.WriteLine("Connect failed: " + ex.Message);
                        ReturnCode |= ErrorUnknown;
                        Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                        continue;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("*** FAILED ***");
                        Console.WriteLine("Connect failed: " + ex.Message);
                        ReturnCode |= ErrorUnknown;
                        Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                        continue;
                    }

                    try
                    {
                        ReturnCode |= await ExecuteClientTest(client);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("*** FAILED ***");
                        Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                        ReturnCode |= ErrorUnknown;
                    }
                }
                try
                {
                    transport.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Error while closing transport");
                    Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                }
                done = true;
            }
        }

        internal static void PrintOptionsHelp()
        {
            Console.WriteLine("Client options:");
            Console.WriteLine("  -u ");
            Console.WriteLine("  -t <# of threads to run>        default = 1");
            Console.WriteLine("  -n <# of iterations>            per thread");
            Console.WriteLine("  --pipe=");
            Console.WriteLine("  --host=");
            Console.WriteLine("  --port=");
            Console.WriteLine("  --transport=    one of buffered,framed  (defaults to none)");
            Console.WriteLine("  --protocol=      one of compact,json  (defaults to binary)");
            Console.WriteLine("  --ssl");
            Console.WriteLine();
        }

        public static async Task Execute(List args)
        {
            try
            {
                var param = new TestParams();

                try
                {
                    param.Parse(args);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("*** FAILED ***");
                    Console.WriteLine("Error while parsing arguments");
                    Console.WriteLine("{0} {1}\nStack:\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace);
                    return ErrorUnknown;
                }

                //issue tests on separate threads simultaneously
                var nThreads = Math.Max(param.numThreads, 1);
                Console.Write("Starting {0} test thread(s) ", nThreads);
                var tasks = new Task[nThreads];
                var start = DateTime.Now;
                var retcode = 0;
                for (var i = 0; i < tasks.Length; ++i)
                {
                    Console.Write('.');
                    tasks[i] = Task.Run(async () =>
                    {
                        var test = new ClientTest(param);
                        await test.Execute();
                        lock (tasks)
                            retcode |= test.ReturnCode;
                    });
                }
                Console.WriteLine(" OK");
                Task.WaitAll(tasks);
                Console.WriteLine("Total time: " + (DateTime.Now - start));
                Console.WriteLine();
                return retcode;
            }
            catch (Exception outerEx)
            {
                Console.WriteLine("*** FAILED ***");
                Console.WriteLine("Unexpected error");
                Console.WriteLine(outerEx.Message + "\n" + outerEx.StackTrace);
                return ErrorUnknown;
            }
        }

        public static string BytesToHex(byte[] data)
        {
            return BitConverter.ToString(data).Replace("-", string.Empty);
        }


        public enum BinaryTestSize
        {
            Empty,           // Edge case: the zero-length empty binary
            Normal,          // Fairly small array of usual size (256 bytes)
            Large,           // Large writes/reads may cause range check errors
            PipeWriteLimit,  // Windows Limit: Pipe write operations across a network are limited to 65,535 bytes per write.
            FifteenMB        // that's quite a bit of data
        };

        public static byte[] PrepareTestData(bool randomDist, BinaryTestSize testcase)
        {
            int amount;
            switch (testcase)
            {
                case BinaryTestSize.Empty:
                    amount = 0;
                    break;
                case BinaryTestSize.Normal:
                    amount = 0x100;
                    break;
                case BinaryTestSize.Large:
                    amount = 0x8000 + 128;
                    break;
                case BinaryTestSize.PipeWriteLimit:
                    amount = 0xFFFF + 128;
                    break;
                case BinaryTestSize.FifteenMB:
                    amount = 15 * 1024 * 1024;
                    break;
                default:
                    throw new ArgumentException("invalid argument",nameof(testcase));
            }

            var retval = new byte[amount];

            // linear distribution, unless random is requested
            if (!randomDist)
            {
                for (var i = 0; i < retval.Length; ++i)
                {
                    retval[i] = (byte)i;
                }
                return retval;
            }

            // random distribution
            var rnd = new Random();
            for (var i = 1; i < retval.Length; ++i)
            {
                retval[i] = (byte)rnd.Next(0x100);
            }
            return retval;
        }

        private static CancellationToken MakeTimeoutToken(int msec = 15_000)
        {
            var token = new CancellationTokenSource(msec);
            return token.Token;
        }

        public static async Task ExecuteClientTest(ThriftTest.Client client)
        {
            var returnCode = 0;

            Console.Write("testVoid()");
            await client.testVoid(MakeTimeoutToken());
            Console.WriteLine(" = void");

            Console.Write("testString(\"Test\")");
            var s = await client.testString("Test", MakeTimeoutToken());
            Console.WriteLine(" = \"" + s + "\"");
            if ("Test" != s)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            Console.Write("testBool(true)");
            var t = await client.testBool((bool)true, MakeTimeoutToken());
            Console.WriteLine(" = " + t);
            if (!t)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }
            Console.Write("testBool(false)");
            var f = await client.testBool((bool)false, MakeTimeoutToken());
            Console.WriteLine(" = " + f);
            if (f)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            Console.Write("testByte(1)");
            var i8 = await client.testByte((sbyte)1, MakeTimeoutToken());
            Console.WriteLine(" = " + i8);
            if (1 != i8)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            Console.Write("testI32(-1)");
            var i32 = await client.testI32(-1, MakeTimeoutToken());
            Console.WriteLine(" = " + i32);
            if (-1 != i32)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            Console.Write("testI64(-34359738368)");
            var i64 = await client.testI64(-34359738368, MakeTimeoutToken());
            Console.WriteLine(" = " + i64);
            if (-34359738368 != i64)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            // TODO: Validate received message
            Console.Write("testDouble(5.325098235)");
            var dub = await client.testDouble(5.325098235, MakeTimeoutToken());
            Console.WriteLine(" = " + dub);
            if (5.325098235 != dub)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }
            Console.Write("testDouble(-0.000341012439638598279)");
            dub = await client.testDouble(-0.000341012439638598279, MakeTimeoutToken());
            Console.WriteLine(" = " + dub);
            if (-0.000341012439638598279 != dub)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            // testUuid()
            var uuidOut = new Guid("{00112233-4455-6677-8899-AABBCCDDEEFF}");
            Console.Write("testUuid({0})", uuidOut);
            try
            {
                var uuidIn = await client.testUuid(uuidOut, MakeTimeoutToken());
                Console.WriteLine(" = {0}", uuidIn);
                if (!uuidIn.Equals(uuidOut))
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorBaseTypes;
                }
            }
            catch (Thrift.TApplicationException ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }

            // testBinary()
            foreach (BinaryTestSize binTestCase in Enum.GetValues(typeof(BinaryTestSize)))
            {
                var binOut = PrepareTestData(true, binTestCase);

                Console.Write("testBinary({0} bytes)", binOut.Length);
                try
                {
                    var binIn = await client.testBinary(binOut, MakeTimeoutToken());
                    Console.WriteLine(" = {0} bytes", binIn.Length);
                    if (binIn.Length != binOut.Length)
                    {
                        Console.WriteLine("*** FAILED ***");
                        returnCode |= ErrorBaseTypes;
                    }
                    for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs)
                    {
                        if (binIn[ofs] != binOut[ofs])
                        {
                            Console.WriteLine("*** FAILED ***");
                            returnCode |= ErrorBaseTypes;
                        }
                    }
                }
                catch (Thrift.TApplicationException ex)
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorBaseTypes;
                    Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                }
            }

            // CrazyNesting
            Console.WriteLine("Test CrazyNesting");
            var one = new CrazyNesting();
            var two = new CrazyNesting();
            one.String_field = "crazy";
            two.String_field = "crazy";
            one.Binary_field = new byte[] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF };
            two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF };
            if (typeof(CrazyNesting).GetMethod("Equals")?.DeclaringType == typeof(CrazyNesting))
            {
                if (!one.Equals(two))
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorContainers;
                }
            }

            // TODO: Validate received message
            Console.Write("testStruct({\"Zero\", 1, -3, -5})");
            var o = new Xtruct
            {
                String_thing = "Zero",
                Byte_thing = (sbyte)1,
                I32_thing = -3,
                I64_thing = -5
            };
            var i = await client.testStruct(o, MakeTimeoutToken());
            Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}");

            // TODO: Validate received message
            Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})");
            var o2 = new Xtruct2
            {
                Byte_thing = (sbyte)1,
                Struct_thing = o,
                I32_thing = 5
            };
            Xtruct2 i2 = await client.testNest(o2, MakeTimeoutToken());
            i = i2.Struct_thing;
            Console.WriteLine(" = {" + i2.Byte_thing + ", {\""
                            + (i?.String_thing ?? "") + "\", "
                            + (i?.Byte_thing ?? 0) + ", "
                            + (i?.I32_thing ?? 0) + ", "
                            + (i?.I64_thing ?? 0) + "}, "
                            + i2.I32_thing + "}");

            var mapout = new Dictionary();
            for (var j = 0; j < 5; j++)
            {
                mapout[j] = j - 10;
            }
            Console.Write("testMap({");
            Console.Write(string.Join(", ", mapout.Select((pair) => { return pair.Key + " => " + pair.Value; })));
            Console.Write("})");

            var mapin = await client.testMap(mapout, MakeTimeoutToken());

            Console.Write(" = {");
            Console.Write(string.Join(", ", mapin.Select((pair) => { return pair.Key + " => " + pair.Value; })));
            Console.WriteLine("}");

            // TODO: Validate received message
            var listout = new List();
            for (var j = -2; j < 3; j++)
            {
                listout.Add(j);
            }
            Console.Write("testList({");
            Console.Write(string.Join(", ", listout));
            Console.Write("})");

            var listin = await client.testList(listout, MakeTimeoutToken());

            Console.Write(" = {");
            Console.Write(string.Join(", ", listin));
            Console.WriteLine("}");

            //set
            // TODO: Validate received message
            var setout = new HashSet();
            for (var j = -2; j < 3; j++)
            {
                setout.Add(j);
            }
            Console.Write("testSet({");
            Console.Write(string.Join(", ", setout));
            Console.Write("})");

            var setin = await client.testSet(setout, MakeTimeoutToken());

            Console.Write(" = {");
            Console.Write(string.Join(", ", setin));
            Console.WriteLine("}");


            Console.Write("testEnum(ONE)");
            var ret = await client.testEnum(Numberz.ONE, MakeTimeoutToken());
            Console.WriteLine(" = " + ret);
            if (Numberz.ONE != ret)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorStructs;
            }

            Console.Write("testEnum(TWO)");
            ret = await client.testEnum(Numberz.TWO, MakeTimeoutToken());
            Console.WriteLine(" = " + ret);
            if (Numberz.TWO != ret)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorStructs;
            }

            Console.Write("testEnum(THREE)");
            ret = await client.testEnum(Numberz.THREE, MakeTimeoutToken());
            Console.WriteLine(" = " + ret);
            if (Numberz.THREE != ret)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorStructs;
            }

            Console.Write("testEnum(FIVE)");
            ret = await client.testEnum(Numberz.FIVE, MakeTimeoutToken());
            Console.WriteLine(" = " + ret);
            if (Numberz.FIVE != ret)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorStructs;
            }

            Console.Write("testEnum(EIGHT)");
            ret = await client.testEnum(Numberz.EIGHT, MakeTimeoutToken());
            Console.WriteLine(" = " + ret);
            if (Numberz.EIGHT != ret)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorStructs;
            }

            Console.Write("testTypedef(309858235082523)");
            var uid = await client.testTypedef(309858235082523L, MakeTimeoutToken());
            Console.WriteLine(" = " + uid);
            if (309858235082523L != uid)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorStructs;
            }

            // TODO: Validate received message
            Console.Write("testMapMap(1)");
            var mm = await client.testMapMap(1, MakeTimeoutToken());
            Console.Write(" = {");
            foreach (var key in mm.Keys)
            {
                Console.Write(key + " => {");
                var m2 = mm[key];
                foreach (var k2 in m2.Keys)
                {
                    Console.Write(k2 + " => " + m2[k2] + ", ");
                }
                Console.Write("}, ");
            }
            Console.WriteLine("}");

            // TODO: Validate received message
            var insane = new Insanity
            {
                UserMap = new Dictionary
                {
                    [Numberz.FIVE] = 5000L
                }
            };
            var truck = new Xtruct
            {
                String_thing = "Truck",
                Byte_thing = (sbyte)8,
                I32_thing = 8,
                I64_thing = 8
            };
            insane.Xtructs = new List
            {
                truck
            };
            Console.Write("testInsanity()");
            var whoa = await client.testInsanity(insane, MakeTimeoutToken());
            Console.Write(" = {");
            foreach (var key in whoa.Keys)
            {
                var val = whoa[key];
                Console.Write(key + " => {");

                foreach (var k2 in val.Keys)
                {
                    var v2 = val[k2];

                    Console.Write(k2 + " => {");
                    var userMap = v2.UserMap;

                    Console.Write("{");
                    if (userMap != null)
                    {
                        foreach (var k3 in userMap.Keys)
                        {
                            Console.Write(k3 + " => " + userMap[k3] + ", ");
                        }
                    }
                    else
                    {
                        Console.Write("null");
                    }
                    Console.Write("}, ");

                    var xtructs = v2.Xtructs;

                    Console.Write("{");
                    if (xtructs != null)
                    {
                        foreach (var x in xtructs)
                        {
                            Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, ");
                        }
                    }
                    else
                    {
                        Console.Write("null");
                    }
                    Console.Write("}");

                    Console.Write("}, ");
                }
                Console.Write("}, ");
            }
            Console.WriteLine("}");

            sbyte arg0 = 1;
            var arg1 = 2;
            var arg2 = long.MaxValue;
            var multiDict = new Dictionary
            {
                [1] = "one"
            };

            var tmpMultiDict = new List();
            foreach (var pair in multiDict)
                tmpMultiDict.Add(pair.Key +" => "+ pair.Value);

            var arg4 = Numberz.FIVE;
            long arg5 = 5000000;
            Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + ",{" + string.Join(",", tmpMultiDict) + "}," + arg4 + "," + arg5 + ")");
            var multiResponse = await client.testMulti(arg0, arg1, arg2, multiDict, arg4, arg5, MakeTimeoutToken());
            Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing
                          + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n");

            try
            {
                Console.WriteLine("testException(\"Xception\")");
                await client.testException("Xception", MakeTimeoutToken());
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
            }
            catch (Xception ex)
            {
                if (ex.ErrorCode != 1001 || ex.Message != "Xception")
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorExceptions;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
            try
            {
                Console.WriteLine("testException(\"TException\")");
                await client.testException("TException", MakeTimeoutToken());
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
            }
            catch (Thrift.TException)
            {
                // OK
            }
            catch (Exception ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
            try
            {
                Console.WriteLine("testException(\"ok\")");
                await client.testException("ok", MakeTimeoutToken());
                // OK
            }
            catch (Exception ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }

            try
            {
                Console.WriteLine("testMultiException(\"Xception\", ...)");
                await client.testMultiException("Xception", "ignore", MakeTimeoutToken());
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
            }
            catch (Xception ex)
            {
                if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception")
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorExceptions;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
            try
            {
                Console.WriteLine("testMultiException(\"Xception2\", ...)");
                await client.testMultiException("Xception2", "ignore", MakeTimeoutToken());
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
            }
            catch (Xception2 ex)
            {
                if (ex.ErrorCode != 2002 || ex.Struct_thing?.String_thing != "This is an Xception2")
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorExceptions;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
            try
            {
                Console.WriteLine("testMultiException(\"success\", \"OK\")");
                if ("OK" != (await client.testMultiException("success", "OK", MakeTimeoutToken())).String_thing)
                {
                    Console.WriteLine("*** FAILED ***");
                    returnCode |= ErrorExceptions;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorExceptions;
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }

            Console.WriteLine("Test Oneway(1)");
            var sw = new Stopwatch();
            sw.Start();
            await client.testOneway(1, MakeTimeoutToken());
            sw.Stop();
            if (sw.ElapsedMilliseconds > 1000)
            {
                Console.WriteLine("*** FAILED ***");
                returnCode |= ErrorBaseTypes;
            }

            Console.Write("Test Calltime()");
            var times = 50;
            sw.Reset();
            sw.Start();
            var token = MakeTimeoutToken(20000);
            for (var k = 0; k < times; ++k)
                await client.testVoid(token);
            sw.Stop();
            Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times);
            return returnCode;
        }
    }
}
thrift-0.19.0/test/netstd/Client/Performance/0000777000000000000000000000000014303740367021051 5ustar00rootroot00000000000000thrift-0.19.0/test/netstd/Client/Performance/PerformanceTests.cs0000644000000000000000000001320614303740367024662 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Collections.Generic;
using System.Text;
using ThriftTest;
using Thrift.Collections;
using Thrift;
using Thrift.Protocol;
using System.Threading;
using Thrift.Transport.Client;
using System.Threading.Tasks;
using System.Diagnostics;
using Thrift.Transport;

#pragma warning disable CS1998  // no await in async method

namespace Client.Tests
{
    public class PerformanceTests
    {
        private CancellationTokenSource Cancel = new();
        private CrazyNesting? Testdata;
        private TMemoryBufferTransport? MemBuffer;
        private TTransport? Transport;
        private LayeredChoice Layered;
        private readonly TConfiguration Configuration = new();

        internal static async Task Execute()
        {
            var instance = new PerformanceTests();
            instance.ProtocolPeformanceTestAsync().Wait();

            // debug only
            if (Debugger.IsAttached)
            {
                Console.Write("Hit ENTER ...");
                Console.ReadKey();
            }

            return 0;
        }

        public PerformanceTests()
        {
            Configuration.MaxFrameSize = Configuration.MaxMessageSize;  // default frame size is too small for this test
        }

        private async Task ProtocolPeformanceTestAsync()
        {
            Console.WriteLine("Setting up for ProtocolPeformanceTestAsync ...");
            Cancel = new CancellationTokenSource();
            Testdata = TestDataFactory.CreateCrazyNesting();

            foreach (var layered in Enum.GetValues(typeof(LayeredChoice)))
            {
                Layered = (LayeredChoice)layered;
                await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); });
                await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); });
                await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); });
            }
        }

        private async Task GenericProtocolFactory(bool forWrite)
            where T : TProtocol
        {
            var oldTrans = Transport;
            try
            {
                Transport = null;

                // read happens after write here, so let's take over the written bytes
                if (forWrite)
                    MemBuffer = new TMemoryBufferTransport(Configuration);  
                else
                    MemBuffer = new TMemoryBufferTransport(MemBuffer?.GetBuffer(), Configuration);

                //  layered transports anyone?
                Transport = Layered switch
                {
                    LayeredChoice.None => MemBuffer,
                    LayeredChoice.Framed => new TFramedTransport(MemBuffer),
                    LayeredChoice.Buffered => new TBufferedTransport(MemBuffer),
                    _ => throw new Exception("Unhandled case " + Layered.ToString()),
                };
                ;

                if (!Transport.IsOpen)
                    Transport.OpenAsync().Wait();

                if (Activator.CreateInstance(typeof(T), Transport) is T instance)
                    return instance;

                throw new Exception("Unexpected.");
            }
            finally
            {
                oldTrans?.Dispose();
            }
        }

        private string GetProtocolTransportName(TProtocol proto)
        {
            var name = Transport?.GetType().Name;
            var bufnm = MemBuffer?.GetType().Name;
            if ((name is null) || name.Equals(bufnm))
                name = string.Empty;
            else
                name = " + " + name;

            name = proto.GetType().Name + name;
            return name;
        }


        private async Task RunTestAsync(Func> factory)
        {
            var stop = new Stopwatch();

            if (Testdata is null)
                throw new Exception("unexpected internal state");

            var proto = await factory(true);
            if (Transport is null)
                throw new Exception("unexpected internal state");
            stop.Start();
            await Testdata.WriteAsync(proto, Cancel.Token);
            await Transport.FlushAsync(Cancel.Token);
            stop.Stop();
            Console.WriteLine("RunTestAsync({0}): write = {1} msec",
                GetProtocolTransportName(proto),
                stop.ElapsedMilliseconds);

            var restored = new CrazyNesting();
            proto = await factory(false);
            if (Transport is null)
                throw new Exception("unexpected internal state");
            stop.Start();
            await restored.ReadAsync(proto, Cancel.Token);
            stop.Stop();
            Console.WriteLine("RunTestAsync({0}): read = {1} msec",
                GetProtocolTransportName(proto),
                stop.ElapsedMilliseconds);
        }

    }
}
thrift-0.19.0/test/netstd/Client/Performance/TestDataFactory.cs0000644000000000000000000001275414303740367024446 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Collections.Generic;
using System.Text;
using ThriftTest;
using Thrift.Collections;

namespace Client.Tests
{
    
    static class TestDataFactory
    {
        public static CrazyNesting? CreateCrazyNesting(int count = 10)
        {
            if (count <= 0)
                return null;

            return new CrazyNesting()
            {
                Binary_field = CreateBytesArray(count),
                List_field = CreateListField(count),
                Set_field = CreateSetField(count),
                String_field = string.Format("data level {0}", count)
            };
        }

        private static HashSet CreateSetField(int count)
        {
            var retval = new HashSet();
            for (var i = 0; i < count; ++i)
                retval.Add(CreateInsanity(count));
            return retval;
        }

        private static Insanity CreateInsanity(int count)
        {
            return new Insanity()
            {
                UserMap = CreateUserMap(count),
                Xtructs = CreateXtructs(count)
            };
        }

        private static List CreateXtructs(int count)
        {
            var retval = new List();
            for (var i = 0; i < count; ++i)
                retval.Add(CreateXtruct(count));
            return retval;
        }

        private static Xtruct CreateXtruct(int count)
        {
            return new Xtruct()
            {
                Byte_thing = (sbyte)(count % 128),
                I32_thing = count,
                I64_thing = count,
                String_thing = string.Format("data level {0}", count)
            };
        }

        private static Dictionary CreateUserMap(int count)
        {
            var retval = new Dictionary
            {
                { Numberz.ONE, count },
                { Numberz.TWO, count },
                { Numberz.THREE, count },
                { Numberz.FIVE, count },
                { Numberz.SIX, count },
                { Numberz.EIGHT, count }
            };
            return retval;
        }

        private static List, Dictionary>>>>> CreateListField(int count)
        {
            var retval = new List, Dictionary>>>>>();
            for (var i = 0; i < count; ++i)
                retval.Add(CreateListFieldData(count));
            return retval;
        }

        private static Dictionary, Dictionary>>>> CreateListFieldData(int count)
        {
            var retval = new Dictionary, Dictionary>>>>();
            for (var i = 0; i < count; ++i)
                retval.Add( CreateIntHashSet(count), CreateListFieldDataDict(count));
            return retval;
        }

        private static HashSet CreateIntHashSet(int count)
        {
            var retval = new HashSet();
            for (var i = 0; i < count; ++i)
                retval.Add(i);
            return retval;
        }

        private static Dictionary>>> CreateListFieldDataDict(int count)
        {
            var retval = new Dictionary>>>();
            for (var i = 0; i < count; ++i)
                retval.Add(i, CreateListFieldDataDictValue(count));
            return retval;
        }

        private static HashSet>> CreateListFieldDataDictValue(int count)
        {
            var retval = new HashSet>>();
            for (var i = 0; i < count; ++i)
                retval.Add( CreateListFieldDataDictValueList(count));
            return retval;
        }

        private static List> CreateListFieldDataDictValueList(int count)
        {
            var retval = new List>();
            for (var i = 0; i < count; ++i)
                retval.Add(CreateListFieldDataDictValueListDict(count));
            return retval;
        }

        private static Dictionary CreateListFieldDataDictValueListDict(int count)
        {
            return new Dictionary
            {
                { CreateInsanity(count), string.Format("data level {0}", count) }
            };
        }

        private static byte[] CreateBytesArray(int count)
        {
            var retval = new byte[count];
            for (var i = 0; i < count; ++i)
                retval[i] = (byte)(i % 0xFF);
            return retval;
        }
    }
}
thrift-0.19.0/test/netstd/Client/Client.csproj0000644000000000000000000000555114454461475021261 0ustar00rootroot00000000000000
  

  
    net7.0
    9.0
    Client
    Client
    Exe
    0.19.0.0
    false
    false
    false
    false
    false
    false
    enable
  

  
    
    
    
    
  

  
    
  

  
    
      
    
    
    
    
  

thrift-0.19.0/test/netstd/Client/Properties/0000777000000000000000000000000014303740367020744 5ustar00rootroot00000000000000thrift-0.19.0/test/netstd/Client/Properties/AssemblyInfo.cs0000644000000000000000000000343014303740367023662 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.

[assembly: AssemblyTitle("Client")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("The Apache Software Foundation")]
[assembly: AssemblyProduct("Thrift")]
[assembly: AssemblyCopyright("The Apache Software Foundation")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.

[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM

[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")]

thrift-0.19.0/test/netstd/Client/Program.cs0000644000000000000000000000506714303740367020552 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ThriftTest;

namespace Client
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                try
                {
                    Console.SetBufferSize(Console.BufferWidth, 4096);
                }
                catch (Exception)
                {
                    Console.WriteLine("Failed to grow scroll-back buffer");
                }
            }

            // run whatever mode is choosen, default to test impl
            var argslist = new List(args);
            switch (argslist.FirstOrDefault())
            {
                case "client":  // crosstest wants to pass this, so just emit a hint and ignore
                    Console.WriteLine("Hint: The 'client' argument is no longer required.");
                    argslist.RemoveAt(0);
                    return await TestClient.Execute(argslist);
                case "--performance":
                case "--performance-test":
                    return await Tests.PerformanceTests.Execute();
                case "--help":
                    PrintHelp();
                    return 0;
                default:
                    return await TestClient.Execute(argslist);
            }
        }

        private static void PrintHelp()
        {
            Console.WriteLine("Usage:");
            Console.WriteLine("  Client  [options]");
            Console.WriteLine("  Client  --performance-test");
            Console.WriteLine("  Client  --help");
            Console.WriteLine("");

            TestClient.PrintOptionsHelp();
        }
    }
}
thrift-0.19.0/test/netstd/README.md0000644000000000000000000000112314303740367016642 0ustar00rootroot00000000000000# Apache Thrift net-core-lib tests

Tests for Thrift client library ported to Microsoft .NET Core 

# Content
- ThriftTest - tests for Thrift library 

# Reused components 
- NET Core SDK 3.1 (LTS)

# How to build on Windows
- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable
- Open ThriftTest.sln in Visual Studio and build
or 
- Build with scripts

# How to build on Unix
- Ensure you have .NET Core 3.0 SDK installed or use the Ubuntu Xenial docker image
- Follow common build practice for Thrift: bootstrap, configure, and make precross

thrift-0.19.0/test/netstd/ThriftTest.sln0000644000000000000000000002074414303740367020213 0ustar00rootroot00000000000000
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30104.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.IntegrationTests", "..\..\lib\netstd\Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj", "{C8148BFF-B943-4474-8D33-A641C6FD3DAB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "..\..\lib\netstd\Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{5D86C1B6-0CDA-4D1D-80A5-240583B21148}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "..\..\lib\netstd\Tests\Thrift.Tests\Thrift.Tests.csproj", "{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Benchmarks", "..\..\lib\netstd\Benchmarks\Thrift.Benchmarks\Thrift.Benchmarks.csproj", "{66946544-8DE7-45E9-8D0E-93EADA028D44}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Debug|x64 = Debug|x64
		Debug|x86 = Debug|x86
		Release|Any CPU = Release|Any CPU
		Release|x64 = Release|x64
		Release|x86 = Release|x86
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU
		{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU
		{21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU
		{0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Debug|x64.ActiveCfg = Debug|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Debug|x64.Build.0 = Debug|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Debug|x86.ActiveCfg = Debug|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Debug|x86.Build.0 = Debug|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Release|Any CPU.Build.0 = Release|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Release|x64.ActiveCfg = Release|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Release|x64.Build.0 = Release|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Release|x86.ActiveCfg = Release|Any CPU
		{C8148BFF-B943-4474-8D33-A641C6FD3DAB}.Release|x86.Build.0 = Release|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Debug|x64.ActiveCfg = Debug|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Debug|x64.Build.0 = Debug|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Debug|x86.ActiveCfg = Debug|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Debug|x86.Build.0 = Debug|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Release|Any CPU.Build.0 = Release|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Release|x64.ActiveCfg = Release|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Release|x64.Build.0 = Release|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Release|x86.ActiveCfg = Release|Any CPU
		{5D86C1B6-0CDA-4D1D-80A5-240583B21148}.Release|x86.Build.0 = Release|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Debug|x64.ActiveCfg = Debug|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Debug|x64.Build.0 = Debug|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Debug|x86.ActiveCfg = Debug|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Debug|x86.Build.0 = Debug|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Release|Any CPU.Build.0 = Release|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Release|x64.ActiveCfg = Release|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Release|x64.Build.0 = Release|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Release|x86.ActiveCfg = Release|Any CPU
		{37FDED71-F8FB-434B-B2A8-1C53CCD9FD38}.Release|x86.Build.0 = Release|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Debug|Any CPU.Build.0 = Debug|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Debug|x64.ActiveCfg = Debug|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Debug|x64.Build.0 = Debug|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Debug|x86.ActiveCfg = Debug|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Debug|x86.Build.0 = Debug|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Release|Any CPU.ActiveCfg = Release|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Release|Any CPU.Build.0 = Release|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Release|x64.ActiveCfg = Release|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Release|x64.Build.0 = Release|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Release|x86.ActiveCfg = Release|Any CPU
		{66946544-8DE7-45E9-8D0E-93EADA028D44}.Release|x86.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
		SolutionGuid = {52CE9A12-F6CB-4F0C-BB42-0105612F5FF4}
	EndGlobalSection
EndGlobal
thrift-0.19.0/test/netstd/build.cmd0000644000000000000000000000164114303740367017154 0ustar00rootroot00000000000000@echo off
rem /*
rem  * Licensed to the Apache Software Foundation (ASF) under one
rem  * or more contributor license agreements. See the NOTICE file
rem  * distributed with this work for additional information
rem  * regarding copyright ownership. The ASF licenses this file
rem  * to you under the Apache License, Version 2.0 (the
rem  * "License"); you may not use this file except in compliance
rem  * with the License. You may obtain a copy of the License at
rem  *
rem  *   http://www.apache.org/licenses/LICENSE-2.0
rem  *
rem  * Unless required by applicable law or agreed to in writing,
rem  * software distributed under the License is distributed on an
rem  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
rem  * KIND, either express or implied. See the License for the
rem  * specific language governing permissions and limitations
rem  * under the License.
rem  */
setlocal

dotnet --info
dotnet build

:eof
thrift-0.19.0/test/netstd/Server/0000777000000000000000000000000014454461475016647 5ustar00rootroot00000000000000thrift-0.19.0/test/netstd/Server/TestServer.cs0000644000000000000000000006416514452237057021307 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Thrift;
using Thrift.Collections;
using Thrift.Processor;
using Thrift.Protocol;
using Thrift.Server;
using Thrift.Transport;
using Thrift.Transport.Server;

#pragma warning disable IDE0063  // using can be simplified, we don't
#pragma warning disable IDE0057  // substr can be simplified, we don't
#pragma warning disable CS1998   // await missing

namespace ThriftTest
{
    internal enum ProtocolChoice
    {
        Binary,
        Compact,
        Json
    }

    internal enum TransportChoice
    {
        Socket,
        TlsSocket,
        NamedPipe
    }

    internal enum BufferChoice
    {
        None,
        Buffered,
        Framed
    }

    internal enum ServerChoice
    {
        Simple,
        ThreadPool
    }


    internal class ServerParam
    {
        internal BufferChoice buffering = BufferChoice.None;
        internal ProtocolChoice protocol = ProtocolChoice.Binary;
        internal TransportChoice transport = TransportChoice.Socket;
        internal ServerChoice server = ServerChoice.Simple;
        internal int port = 9090;
        internal string pipe = string.Empty;

        internal void Parse(List args)
        {
            for (var i = 0; i < args.Count; i++)
            {
                if (args[i].StartsWith("--pipe="))
                {
                    pipe = args[i].Substring(args[i].IndexOf("=") + 1);
                    transport = TransportChoice.NamedPipe;
                }
                else if (args[i].StartsWith("--port="))
                {
                    port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1));
                    if(transport != TransportChoice.TlsSocket)
                        transport = TransportChoice.Socket;
                }
                else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered")
                {
                    buffering = BufferChoice.Buffered;
                }
                else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed")
                {
                    buffering = BufferChoice.Framed;
                }
                else if (args[i] == "--binary" || args[i] == "--protocol=binary")
                {
                    protocol = ProtocolChoice.Binary;
                }
                else if (args[i] == "--compact" || args[i] == "--protocol=compact")
                {
                    protocol = ProtocolChoice.Compact;
                }
                else if (args[i] == "--json" || args[i] == "--protocol=json")
                {
                    protocol = ProtocolChoice.Json;
                }
                else if (args[i] == "--server-type=simple")
                {
                    server = ServerChoice.Simple;
                }
                else if (args[i] == "--threaded" || args[i] == "--server-type=threaded")
                {
                    throw new NotImplementedException(args[i]);
                }
                else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool")
                {
                    server = ServerChoice.ThreadPool;
                }
                else if (args[i] == "--prototype" || args[i] == "--processor=prototype")
                {
                    throw new NotImplementedException(args[i]);
                }
                else if (args[i] == "--ssl")
                {
                    transport = TransportChoice.TlsSocket;
                }
                else if (args[i] == "--help")
                {
                    PrintOptionsHelp();
                    return;
                }
                else
                {
                    Console.WriteLine("Invalid argument: {0}", args[i]);
                    PrintOptionsHelp();
                    return;
                }
            }

        }

        internal static void PrintOptionsHelp()
        {
            Console.WriteLine("Server options:");
            Console.WriteLine("  --pipe=");
            Console.WriteLine("  --port=");
            Console.WriteLine("  --transport=    one of buffered,framed  (defaults to none)");
            Console.WriteLine("  --protocol=      one of compact,json  (defaults to binary)");
            Console.WriteLine("  --server-type=            one of threaded,threadpool  (defaults to simple)");
            Console.WriteLine("  --processor=");
            Console.WriteLine("  --ssl");
            Console.WriteLine();
        }
    }

    public class TestServer
    {
        #pragma warning disable CA2211
        public static int _clientID = -1;  // use with Interlocked only!
        #pragma warning restore CA2211

        private static readonly TConfiguration Configuration = new(); 

        public delegate void TestLogDelegate(string msg, params object[] values);

        public class MyServerEventHandler : TServerEventHandler
        {
            public int callCount = 0;

            public Task PreServeAsync(CancellationToken cancellationToken)
            {
                callCount++;
                return Task.CompletedTask;
            }

            public async Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken)
            {
                callCount++;
                return null;
            }

            public Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, CancellationToken cancellationToken)
            {
                callCount++;
                return Task.CompletedTask;
            }

            public Task ProcessContextAsync(object serverContext, TTransport transport, CancellationToken cancellationToken)
            {
                callCount++;
                return Task.CompletedTask;
            }
        }

        public class TestHandlerAsync : ThriftTest.IAsync
        {
            //public TServer Server { get; set; }
            private readonly int handlerID;
            private readonly TestLogDelegate logger;

            public TestHandlerAsync()
            {
                handlerID = Interlocked.Increment(ref _clientID);
                logger += TestConsoleLogger;
                logger.Invoke("New TestHandler instance created");
            }

            public void TestConsoleLogger(string msg, params object[] values)
            {
                var sb = new StringBuilder();
                sb.AppendFormat("handler{0:D3}:", handlerID);
                sb.AppendFormat(msg, values);
                sb.AppendLine();
                lock (typeof(Console))
                    Console.Write(sb.ToString());
            }

            public Task testVoid(CancellationToken cancellationToken)
            {
                logger.Invoke("testVoid()");
                return Task.CompletedTask;
            }

            public Task testString(string? thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testString({0})", thing ?? "");
                return Task.FromResult(thing ?? string.Empty);
            }

            public Task testBool(bool thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testBool({0})", thing);
                return Task.FromResult(thing);
            }

            public Task testByte(sbyte thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testByte({0})", thing);
                return Task.FromResult(thing);
            }

            public Task testI32(int thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testI32({0})", thing);
                return Task.FromResult(thing);
            }

            public Task testI64(long thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testI64({0})", thing);
                return Task.FromResult(thing);
            }

            public Task testDouble(double thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testDouble({0})", thing);
                return Task.FromResult(thing);
            }

            public Task testBinary(byte[]? thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testBinary({0} bytes)", thing?.Length ?? 0);
                return Task.FromResult(thing ?? Array.Empty());
            }

            public Task testUuid(Guid thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testUuid({0})", thing.ToString("B"));
                return Task.FromResult(thing);
            }

            public Task testStruct(Xtruct? thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing?.String_thing ?? "", thing?.Byte_thing ?? 0, thing?.I32_thing ?? 0, thing?.I64_thing ?? 0);
                return Task.FromResult(thing ?? new Xtruct());   // null returns are not allowed in Thrift
            }

            public Task testNest(Xtruct2? nest, CancellationToken cancellationToken)
            {
                var thing = nest?.Struct_thing;
                logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})",
                    nest?.Byte_thing ?? 0,
                    thing?.String_thing ?? "",
                    thing?.Byte_thing ?? 0,
                    thing?.I32_thing ?? 0,
                    thing?.I64_thing ?? 0,
                    nest?.I32_thing ?? 0);
                return Task.FromResult(nest ?? new Xtruct2());   // null returns are not allowed in Thrift
            }

            public Task> testMap(Dictionary? thing, CancellationToken cancellationToken)
            {
                var sb = new StringBuilder();
                sb.Append("testMap({{");
                if (thing != null)
                {
                    var first = true;
                    foreach (var key in thing.Keys)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            sb.Append(", ");
                        }
                        sb.AppendFormat("{0} => {1}", key, thing[key]);
                    }
                }
                sb.Append("}})");
                logger.Invoke(sb.ToString());
                return Task.FromResult(thing ?? new Dictionary());   // null returns are not allowed in Thrift
            }

            public Task> testStringMap(Dictionary? thing, CancellationToken cancellationToken)
            {
                var sb = new StringBuilder();
                sb.Append("testStringMap({{");
                if (thing != null)
                {
                    var first = true;
                    foreach (var key in thing.Keys)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            sb.Append(", ");
                        }
                        sb.AppendFormat("{0} => {1}", key, thing[key]);
                    }
                }
                sb.Append("}})");
                logger.Invoke(sb.ToString());
                return Task.FromResult(thing ?? new Dictionary());   // null returns are not allowed in Thrift
            }

            public Task> testSet(HashSet? thing, CancellationToken cancellationToken)
            {
                var sb = new StringBuilder();
                sb.Append("testSet({{");
                if (thing != null)
                {
                    var first = true;
                    foreach (int elem in thing)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            sb.Append(", ");
                        }
                        sb.AppendFormat("{0}", elem);
                    }
                }
                sb.Append("}})");
                logger.Invoke(sb.ToString());
                return Task.FromResult(thing ?? new HashSet());   // null returns are not allowed in Thrift
            }

            public Task> testList(List? thing, CancellationToken cancellationToken)
            {
                var sb = new StringBuilder();
                sb.Append("testList({{");
                if (thing != null)
                {
                    var first = true;
                    foreach (var elem in thing)
                    {
                        if (first)
                        {
                            first = false;
                        }
                        else
                        {
                            sb.Append(", ");
                        }
                        sb.AppendFormat("{0}", elem);
                    }
                }
                sb.Append("}})");
                logger.Invoke(sb.ToString());
                return Task.FromResult(thing ?? new List());   // null returns are not allowed in Thrift
            }

            public Task testEnum(Numberz thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testEnum({0})", thing);
                return Task.FromResult(thing);
            }

            public Task testTypedef(long thing, CancellationToken cancellationToken)
            {
                logger.Invoke("testTypedef({0})", thing);
                return Task.FromResult(thing);
            }

            public Task>> testMapMap(int hello, CancellationToken cancellationToken)
            {
                logger.Invoke("testMapMap({0})", hello);
                var mapmap = new Dictionary>();

                var pos = new Dictionary();
                var neg = new Dictionary();
                for (var i = 1; i < 5; i++)
                {
                    pos[i] = i;
                    neg[-i] = -i;
                }

                mapmap[4] = pos;
                mapmap[-4] = neg;

                return Task.FromResult(mapmap);
            }

            public Task>> testInsanity(Insanity? argument, CancellationToken cancellationToken)
            {
                logger.Invoke("testInsanity()");

                /** from ThriftTest.thrift:
                 * So you think you've got this all worked, out eh?
                 *
                 * Creates a the returned map with these values and prints it out:
                 *   { 1 => { 2 => argument,
                 *            3 => argument,
                 *          },
                 *     2 => { 6 => , },
                 *   }
                 * @return map> - a map with the above values
                 */

                var first_map = new Dictionary();
                var second_map = new Dictionary(); ;

                // null dict keys/values are not allowed in Thrift
                first_map[Numberz.TWO] = argument ?? new Insanity();
                first_map[Numberz.THREE] = argument ?? new Insanity();

                second_map[Numberz.SIX] = new Insanity();

                var insane = new Dictionary>
                {
                    [1] = first_map,
                    [2] = second_map
                };

                return Task.FromResult(insane);
            }

            public Task testMulti(sbyte arg0, int arg1, long arg2, Dictionary? arg3, Numberz arg4, long arg5,
                CancellationToken cancellationToken)
            {
                logger.Invoke("testMulti()");

                var hello = new Xtruct(); ;
                hello.String_thing = "Hello2";
                hello.Byte_thing = arg0;
                hello.I32_thing = arg1;
                hello.I64_thing = arg2;
                return Task.FromResult(hello);
            }

            public Task testException(string? arg, CancellationToken cancellationToken)
            {
                logger.Invoke("testException({0})", arg ?? "");
                if (arg == "Xception")
                {
                    var x = new Xception
                    {
                        ErrorCode = 1001,
                        Message = arg
                    };
                    throw x;
                }
                if (arg == "TException")
                {
                    throw new TException();
                }
                return Task.CompletedTask;
            }

            public Task testMultiException(string? arg0, string? arg1, CancellationToken cancellationToken)
            {
                logger.Invoke("testMultiException({0}, {1})", arg0 ?? "", arg1 ?? "");
                if (arg0 == "Xception")
                {
                    var x = new Xception
                    {
                        ErrorCode = 1001,
                        Message = "This is an Xception"
                    };
                    throw x;
                }

                if (arg0 == "Xception2")
                {
                    var x = new Xception2
                    {
                        ErrorCode = 2002,
                        Struct_thing = new Xtruct { String_thing = "This is an Xception2" }
                    };
                    throw x;
                }

                var result = new Xtruct { String_thing = arg1 };
                return Task.FromResult(result);
            }

            public async Task testOneway(int secondsToSleep, CancellationToken cancellationToken)
            {
                logger.Invoke("testOneway({0}), sleeping...", secondsToSleep);
                await Task.Delay(secondsToSleep * 1000, cancellationToken);
                logger.Invoke("testOneway finished");
            }
        }


        private static X509Certificate2 GetServerCert()
        {
            var serverCertName = "server.p12";
            var possiblePaths = new List
            {
                "../../../keys/",
                "../../keys/",
                "../keys/",
                "keys/",
            };
                        
            var existingPath = string.Empty;
            foreach (var possiblePath in possiblePaths)
            {
                var path = Path.GetFullPath(possiblePath + serverCertName);
                if (File.Exists(path))
                {
                    existingPath = path;
                    break;
                }
            }
                        
            if (string.IsNullOrEmpty(existingPath))
            {
                throw new FileNotFoundException($"Cannot find file: {serverCertName}");
            }
                                    
            var cert = new X509Certificate2(existingPath, "thrift");
                        
            return cert;
        }

        public static async Task Execute(List args)
        {
            using (var loggerFactory = new LoggerFactory()) //.AddConsole().AddDebug();
            {
                var logger = loggerFactory.CreateLogger("Test");

                try
                {
                    var param = new ServerParam();

                    try
                    {
                        param.Parse(args);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("*** FAILED ***");
                        Console.WriteLine("Error while  parsing arguments");
                        Console.WriteLine("{0} {1}\nStack:\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace);
                        return 1;
                    }


                    // Endpoint transport (mandatory)
                    TServerTransport trans;
                    switch (param.transport)
                    {
                        case TransportChoice.NamedPipe:
                            Debug.Assert(param.pipe != null);
                            var numListen = (param.server == ServerChoice.Simple) ? 1 : 16;
                            trans = new TNamedPipeServerTransport(param.pipe, Configuration, NamedPipeServerFlags.OnlyLocalClients, numListen);
                            break;


                        case TransportChoice.TlsSocket:
                            var cert = GetServerCert();
                            if (cert == null || !cert.HasPrivateKey)
                            {
                                cert?.Dispose();
                                throw new InvalidOperationException("Certificate doesn't contain private key");
                            }

                            trans = new TTlsServerSocketTransport(param.port, Configuration,
                                cert,
                                (sender, certificate, chain, errors) => true,
                                null, SslProtocols.Tls12);
                            break;

                        case TransportChoice.Socket:
                        default:
                            trans = new TServerSocketTransport(param.port, Configuration);
                            break;
                    }

                    // Layered transport (mandatory)
                    TTransportFactory? transFactory;
                    switch (param.buffering)
                    {
                        case BufferChoice.Framed:
                            transFactory = new TFramedTransport.Factory();
                            break;
                        case BufferChoice.Buffered:
                            transFactory = new TBufferedTransport.Factory();
                            break;
                        default:
                            Debug.Assert(param.buffering == BufferChoice.None, "unhandled case");
                            transFactory = null;  // no layered transprt
                            break;
                    }

                    TProtocolFactory proto = param.protocol switch
                    {
                        ProtocolChoice.Compact => new TCompactProtocol.Factory(),
                        ProtocolChoice.Json => new TJsonProtocol.Factory(),
                        ProtocolChoice.Binary => new TBinaryProtocol.Factory(),
                        _ => new TBinaryProtocol.Factory(),
                    };

                    // Processor
                    var testHandler = new TestHandlerAsync();
                    var testProcessor = new ThriftTest.AsyncProcessor(testHandler);
                    var processorFactory = new TSingletonProcessorFactory(testProcessor);

                    var poolconfig = new TThreadPoolAsyncServer.Configuration();  // use platform defaults
                    TServer serverEngine = param.server switch
                    {
                        ServerChoice.Simple => new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger),
                        ServerChoice.ThreadPool => new TThreadPoolAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, poolconfig, logger),
                        _ => new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger)
                    };

                    //Server event handler
                    var serverEvents = new MyServerEventHandler();
                    serverEngine.SetEventHandler(serverEvents);

                    // Run it
                    var where = (!string.IsNullOrEmpty(param.pipe)) ? "pipe " + param.pipe : "port " + param.port;
                    Console.WriteLine("Running "+ serverEngine.GetType().Name +
                                      " at "+ where +
                                      " using "+ processorFactory.GetType().Name + " processor prototype factory " +
                                      (param.buffering == BufferChoice.Buffered ? " with buffered transport" : "") +
                                      (param.buffering == BufferChoice.Framed ? " with framed transport" : "") +
                                      (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") +
                                      (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") +
                                      (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") +
                                      "...");
                    await serverEngine.ServeAsync(CancellationToken.None);
                    Console.ReadLine();
                }
                catch (Exception x)
                {
                    Console.Error.Write(x);
                    return 1;
                }

                Console.WriteLine("done.");
                return 0;
            }
        }
    }

}
thrift-0.19.0/test/netstd/Server/Server.csproj0000644000000000000000000000577514454461475021351 0ustar00rootroot00000000000000
  

  
    net7.0
    9.0
    Server
    Server
    Exe
    0.19.0.0
    false
    false
    false
    false
    false
    false
    enable
  

  
    
    
    
    
    
    
  

  
    
  

  
    
      
    
    
    
    
  

thrift-0.19.0/test/netstd/Server/Properties/0000777000000000000000000000000014303740367020774 5ustar00rootroot00000000000000thrift-0.19.0/test/netstd/Server/Properties/AssemblyInfo.cs0000644000000000000000000000343014303740367023712 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.

[assembly: AssemblyTitle("Server")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("The Apache Software Foundation")]
[assembly: AssemblyProduct("Thrift")]
[assembly: AssemblyCopyright("The Apache Software Foundation")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.

[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM

[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")]

thrift-0.19.0/test/netstd/Server/Program.cs0000644000000000000000000000454514303740367020602 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one
// or more contributor license agreements.See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using ThriftTest;
using System.Threading.Tasks;

namespace Server
{
    public class Program
    {
        static async Task Main(string[] args)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                try
                {
                    Console.SetBufferSize(Console.BufferWidth, 4096);
                }
                catch (Exception)
                {
                    Console.WriteLine("Failed to grow scroll-back buffer");
                }
            }

            // run whatever mode is choosen, default to test impl
            var argslist = new List(args);
            switch (argslist.FirstOrDefault())
            {
                case "server":  // crosstest wants to pass this, so just emit a hint and ignore
                    Console.WriteLine("Hint: The 'server' argument is no longer required.");
                    argslist.RemoveAt(0);
                    return await TestServer.Execute(argslist);
                case "--help":
                    PrintHelp();
                    return 0;
                default:
                    return await TestServer.Execute(argslist);
            }
        }

        private static void PrintHelp()
        {
            Console.WriteLine("Usage:");
            Console.WriteLine("  Server  [options]");
            Console.WriteLine("  Server  --help");
            Console.WriteLine("");

            ServerParam.PrintOptionsHelp();
        }
    }
}
thrift-0.19.0/test/netstd/Makefile.in0000644000000000000000000005726314472652520017450 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.

@SET_MAKE@

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = test/netstd
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
	ctags-recursive dvi-recursive html-recursive info-recursive \
	install-data-recursive install-dvi-recursive \
	install-exec-recursive install-html-recursive \
	install-info-recursive install-pdf-recursive \
	install-ps-recursive install-recursive installcheck-recursive \
	installdirs-recursive pdf-recursive ps-recursive \
	tags-recursive uninstall-recursive
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
  distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
  $(RECURSIVE_TARGETS) \
  $(RECURSIVE_CLEAN_TARGETS) \
  $(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
	distdir
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
  dir0=`pwd`; \
  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
  sed_rest='s,^[^/]*/*,,'; \
  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
  sed_butlast='s,/*[^/]*$$,,'; \
  while test -n "$$dir1"; do \
    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
    if test "$$first" != "."; then \
      if test "$$first" = ".."; then \
        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
      else \
        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
        if test "$$first2" = "$$first"; then \
          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
        else \
          dir2="../$$dir2"; \
        fi; \
        dir0="$$dir0"/"$$first"; \
      fi; \
    fi; \
    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
  done; \
  reldir="$$dir2"
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANT = @ANT@
ANT_FLAGS = @ANT_FLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BISON = @BISON@
BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_LIB_DIR = @BOOST_LIB_DIR@
BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@
BOOST_TEST_LDADD = @BOOST_TEST_LDADD@
BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@
BUNDLER = @BUNDLER@
CARGO = @CARGO@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CLASSPATH = @CLASSPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPSTYLE_CMD = @CPPSTYLE_CMD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DART = @DART@
DARTPUB = @DARTPUB@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DMD = @DMD@
DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@
DMD_OF_DIRSEP = @DMD_OF_DIRSEP@
DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@
DOTNETCORE = @DOTNETCORE@
DOTNETCORE_VERSION = @DOTNETCORE_VERSION@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@
D_IMPORT_PREFIX = @D_IMPORT_PREFIX@
D_LIB_NAME = @D_LIB_NAME@
D_SSL_LIB_NAME = @D_SSL_LIB_NAME@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_COVERAGE = @ENABLE_COVERAGE@
ERL = @ERL@
ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@
ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@
ERLANG_LIB_DIR = @ERLANG_LIB_DIR@
ERLC = @ERLC@
ERLCFLAGS = @ERLCFLAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GCOV_CFLAGS = @GCOV_CFLAGS@
GCOV_CXXFLAGS = @GCOV_CXXFLAGS@
GCOV_LDFLAGS = @GCOV_LDFLAGS@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GO = @GO@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
GOBJECT_LIBS = @GOBJECT_LIBS@
GRADLE = @GRADLE@
GRADLE_OPTS = @GRADLE_OPTS@
GREP = @GREP@
GSETTINGS = @GSETTINGS@
HAVE_CXX11 = @HAVE_CXX11@
HAXE = @HAXE@
HAXE_VERSION = @HAXE_VERSION@
INSTALL = @INSTALL@
INSTALLDIRS = @INSTALLDIRS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JAVA_PREFIX = @JAVA_PREFIX@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@
LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@
LIBEVENT_LIBS = @LIBEVENT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
LUA = @LUA@
LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@
LUA_INCLUDE = @LUA_INCLUDE@
LUA_LIB = @LUA_LIB@
LUA_PLATFORM = @LUA_PLATFORM@
LUA_PREFIX = @LUA_PREFIX@
LUA_SHORT_VERSION = @LUA_SHORT_VERSION@
LUA_VERSION = @LUA_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MAYBE_CL = @MAYBE_CL@
MAYBE_CPP = @MAYBE_CPP@
MAYBE_C_GLIB = @MAYBE_C_GLIB@
MAYBE_D = @MAYBE_D@
MAYBE_DART = @MAYBE_DART@
MAYBE_ERLANG = @MAYBE_ERLANG@
MAYBE_GO = @MAYBE_GO@
MAYBE_JAVA = @MAYBE_JAVA@
MAYBE_KOTLIN = @MAYBE_KOTLIN@
MAYBE_LUA = @MAYBE_LUA@
MAYBE_NETSTD = @MAYBE_NETSTD@
MAYBE_NODEJS = @MAYBE_NODEJS@
MAYBE_NODETS = @MAYBE_NODETS@
MAYBE_PERL = @MAYBE_PERL@
MAYBE_PHP = @MAYBE_PHP@
MAYBE_PY3 = @MAYBE_PY3@
MAYBE_PYTHON = @MAYBE_PYTHON@
MAYBE_RS = @MAYBE_RS@
MAYBE_RUBY = @MAYBE_RUBY@
MAYBE_SWIFT = @MAYBE_SWIFT@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NODEJS = @NODEJS@
NODETS = @NODETS@
NPM = @NPM@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PERL_PREFIX = @PERL_PREFIX@
PHP = @PHP@
PHP_CONFIG = @PHP_CONFIG@
PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@
PHP_PREFIX = @PHP_PREFIX@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PYTHON = @PYTHON@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
PY_PREFIX = @PY_PREFIX@
QT5_CFLAGS = @QT5_CFLAGS@
QT5_LIBS = @QT5_LIBS@
QT5_MOC = @QT5_MOC@
RANLIB = @RANLIB@
REBAR = @REBAR@
RUBY = @RUBY@
RUBY_PREFIX = @RUBY_PREFIX@
RUSTC = @RUSTC@
SBCL = @SBCL@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SWIFT = @SWIFT@
THRIFT = @THRIFT@
TRIAL = @TRIAL@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@
ZLIB_LDFLAGS = @ZLIB_LDFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
golang_version = @golang_version@
have_prog_bison = @have_prog_bison@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
luadir = @luadir@
luaexecdir = @luaexecdir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgluadir = @pkgluadir@
pkgluaexecdir = @pkgluaexecdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
rustc_version = @rustc_version@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = . 
EXTRA_DIST = \
	Client \
	README.md \
	Server \
	ThriftTest.sln \
	build.cmd \
	build.sh

all: all-recursive

.SUFFIXES:
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/netstd/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/netstd/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs

# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
#     (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
	@fail=; \
	if $(am__make_keepgoing); then \
	  failcom='fail=yes'; \
	else \
	  failcom='exit 1'; \
	fi; \
	dot_seen=no; \
	target=`echo $@ | sed s/-recursive//`; \
	case "$@" in \
	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
	  *) list='$(SUBDIRS)' ;; \
	esac; \
	for subdir in $$list; do \
	  echo "Making $$target in $$subdir"; \
	  if test "$$subdir" = "."; then \
	    dot_seen=yes; \
	    local_target="$$target-am"; \
	  else \
	    local_target="$$target"; \
	  fi; \
	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
	  || eval $$failcom; \
	done; \
	if test "$$dot_seen" = "no"; then \
	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
	fi; test -z "$$fail"
style-local: 

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
	  include_option=--etags-include; \
	  empty_fix=.; \
	else \
	  include_option=--include; \
	  empty_fix=; \
	fi; \
	list='$(SUBDIRS)'; for subdir in $$list; do \
	  if test "$$subdir" = .; then :; else \
	    test ! -f $$subdir/TAGS || \
	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
	  fi; \
	done; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-recursive

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
	  if test "$$subdir" = .; then :; else \
	    $(am__make_dryrun) \
	      || test -d "$(distdir)/$$subdir" \
	      || $(MKDIR_P) "$(distdir)/$$subdir" \
	      || exit 1; \
	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
	    $(am__relativize); \
	    new_distdir=$$reldir; \
	    dir1=$$subdir; dir2="$(top_distdir)"; \
	    $(am__relativize); \
	    new_top_distdir=$$reldir; \
	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
	    ($(am__cd) $$subdir && \
	      $(MAKE) $(AM_MAKEFLAGS) \
	        top_distdir="$$new_top_distdir" \
	        distdir="$$new_distdir" \
		am__remove_distdir=: \
		am__skip_length_check=: \
		am__skip_mode_fix=: \
	        distdir) \
	      || exit 1; \
	  fi; \
	done
check-am: all-am
check: check-recursive
all-am: Makefile all-local
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-recursive
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive

clean-am: clean-generic clean-libtool clean-local mostlyclean-am

distclean: distclean-recursive
	-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags

dvi: dvi-recursive

dvi-am:

html: html-recursive

html-am:

info: info-recursive

info-am:

install-data-am:

install-dvi: install-dvi-recursive

install-dvi-am:

install-exec-am:

install-html: install-html-recursive

install-html-am:

install-info: install-info-recursive

install-info-am:

install-man:

install-pdf: install-pdf-recursive

install-pdf-am:

install-ps: install-ps-recursive

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-recursive
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-recursive

mostlyclean-am: mostlyclean-generic mostlyclean-libtool

pdf: pdf-recursive

pdf-am:

ps: ps-recursive

ps-am:

style: style-recursive

style-am: style-local

uninstall-am:

.MAKE: $(am__recursive_targets) install-am install-strip

.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \
	check check-am clean clean-generic clean-libtool clean-local \
	cscopelist-am ctags ctags-am distclean distclean-generic \
	distclean-libtool distclean-tags distdir dvi dvi-am html \
	html-am info info-am install install-am install-data \
	install-data-am install-dvi install-dvi-am install-exec \
	install-exec-am install-html install-html-am install-info \
	install-info-am install-man install-pdf install-pdf-am \
	install-ps install-ps-am install-strip installcheck \
	installcheck-am installdirs installdirs-am maintainer-clean \
	maintainer-clean-generic mostlyclean mostlyclean-generic \
	mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \
	tags tags-am uninstall uninstall-am

.PRECIOUS: Makefile


all-local:
	$(DOTNETCORE) build -c Release

precross:
	$(DOTNETCORE) build -c Release

clean-local:
	$(RM) -r Client/bin
	$(RM) -r Server/bin
	$(RM) -r Client/obj
	$(RM) -r Server/obj
	$(RM) -r ThriftTest/ThriftTest

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/netstd/build.sh0000644000000000000000000000154514303740367017026 0ustar00rootroot00000000000000#!/usr/bin/env bash

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

#exit if any command fails
set -e

dotnet --info
dotnet build
thrift-0.19.0/test/index.html0000644000000000000000000000325514303740367016067 0ustar00rootroot00000000000000




Apache Thrift - integration test suite






Apache Thrift - integration test suite: Results

Server Client Protocol Transport Result (log) Expected

Test Information



browse raw log



thrift-0.19.0/test/cpp/0000777000000000000000000000000014472652613014656 5ustar00rootroot00000000000000thrift-0.19.0/test/cpp/Makefile.am0000644000000000000000000000734014370300523016675 0ustar00rootroot00000000000000#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc

BUILT_SOURCES = gen-cpp/ThriftTest.cpp \
                gen-cpp/ThriftTest_types.cpp \
                gen-cpp/ThriftTest_constants.cpp \
                gen-cpp/SecondService.cpp \
                gen-cpp/Service.cpp

noinst_LTLIBRARIES = libtestgencpp.la libstresstestgencpp.la
nodist_libtestgencpp_la_SOURCES = \
	gen-cpp/SecondService.cpp \
	gen-cpp/SecondService.h \
	gen-cpp/SecondService.tcc \
	gen-cpp/ThriftTest_constants.cpp \
	gen-cpp/ThriftTest_constants.h \
	gen-cpp/ThriftTest_types.cpp \
	gen-cpp/ThriftTest_types.h \
	gen-cpp/ThriftTest_types.tcc \
	gen-cpp/ThriftTest.cpp \
	gen-cpp/ThriftTest.h \
	gen-cpp/ThriftTest.tcc \
	src/ThriftTest_extras.cpp

libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la

nodist_libstresstestgencpp_la_SOURCES = \
	gen-cpp/StressTest_types.h \
	gen-cpp/Service.cpp \
	gen-cpp/Service.h

libstresstestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la

precross: TestServer TestClient

check_PROGRAMS = \
	TestServer \
	TestClient \
	StressTest \
	StressTestNonBlocking

# we currently do not run the testsuite, stop c++ server issue
# TESTS = \
#	$(check_PROGRAMS)

TestServer_SOURCES = \
	src/TestServer.cpp

TestServer_LDADD = \
	libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)

TestClient_SOURCES = \
	src/TestClient.cpp

TestClient_LDADD = \
	libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)

StressTest_SOURCES = \
	src/StressTest.cpp

StressTest_LDADD = \
	libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la

StressTestNonBlocking_SOURCES = \
	src/StressTestNonBlocking.cpp

StressTestNonBlocking_LDADD = \
	libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent
#
# Common thrift code generation rules
#
gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/SecondService.tcc: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT)
	$(THRIFT) --gen cpp:templates,cob_style -r $<

gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT)
	$(THRIFT) --gen cpp $<

gen-cpp/SpecificNameTest_types.cpp gen-cpp/EchoService.cpp: $(top_srcdir)/test/SpecificName.thrift $(THRIFT)
	$(THRIFT) --gen cpp $<

AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I.
AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS)

clean-local:
	$(RM) -r gen-cpp/

style-local:
	$(CPPSTYLE_CMD)

EXTRA_DIST = \
	src/TestClient.cpp \
	src/TestServer.cpp \
	src/StressTest.cpp \
	src/StressTestNonBlocking.cpp
thrift-0.19.0/test/cpp/CMakeLists.txt0000644000000000000000000001052114370300523017374 0ustar00rootroot00000000000000#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

# The test executables still depend on Boost
include(BoostMacros)
REQUIRE_BOOST_HEADERS()
set(BOOST_COMPONENTS filesystem program_options random)
REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS)

# Contains the thrift specific target_link_libraries
include(ThriftMacros)

find_package(OpenSSL REQUIRED)
include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}")

find_package(Libevent REQUIRED)  # Libevent comes with CMake support from upstream
include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS})

find_package(ZLIB REQUIRED)
include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS})

#Make sure gen-cpp files can be included
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp")
include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src")

set(crosstestgencpp_SOURCES
    gen-cpp/SecondService.cpp
    gen-cpp/ThriftTest.cpp
    gen-cpp/ThriftTest_types.cpp
    gen-cpp/ThriftTest_constants.cpp
    src/ThriftTest_extras.cpp
)
add_library(crosstestgencpp STATIC ${crosstestgencpp_SOURCES})
target_link_libraries(crosstestgencpp thrift)

set(crossstressgencpp_SOURCES
    gen-cpp/Service.cpp
)
add_library(crossstressgencpp STATIC ${crossstressgencpp_SOURCES})
target_link_libraries(crossstressgencpp thrift)

set(crossspecificnamegencpp_SOURCES
    gen-cpp/EchoService.cpp
    gen-cpp/SpecificNameTest_types.cpp
)
add_library(crossspecificnamegencpp STATIC ${crossspecificnamegencpp_SOURCES})
target_link_libraries(crossspecificnamegencpp thrift)

add_executable(TestServer src/TestServer.cpp)
target_link_libraries(TestServer crosstestgencpp ${Boost_LIBRARIES})
target_link_libraries(TestServer thriftnb)
target_link_libraries(TestServer thriftz)

add_executable(TestClient src/TestClient.cpp)
target_link_libraries(TestClient crosstestgencpp ${Boost_LIBRARIES})
target_link_libraries(TestClient thriftnb)
target_link_libraries(TestClient thriftz)

add_executable(StressTest src/StressTest.cpp)
target_link_libraries(StressTest crossstressgencpp ${Boost_LIBRARIES})
target_link_libraries(StressTest thriftnb)
add_test(NAME StressTest COMMAND StressTest)
add_test(NAME StressTestConcurrent COMMAND StressTest --client-type=concurrent)

# As of https://jira.apache.org/jira/browse/THRIFT-4282, StressTestNonBlocking
# is broken on Windows. Contributions welcome.
if (NOT WIN32 AND NOT CYGWIN)
    add_executable(StressTestNonBlocking src/StressTestNonBlocking.cpp)
    target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES})
    target_link_libraries(StressTestNonBlocking thriftnb)
    target_link_libraries(StressTestNonBlocking thriftz)
    add_test(NAME StressTestNonBlocking COMMAND StressTestNonBlocking)
endif()

add_executable(SpecificNameTest src/SpecificNameTest.cpp)
target_link_libraries(SpecificNameTest crossspecificnamegencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB})
target_link_libraries(SpecificNameTest thrift)
target_link_libraries(SpecificNameTest thriftnb)
add_test(NAME SpecificNameTest COMMAND SpecificNameTest)

#
# Common thrift code generation rules
#

add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest.h gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp
    COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style -r ${PROJECT_SOURCE_DIR}/test/v0.16/ThriftTest.thrift
)

add_custom_command(OUTPUT gen-cpp/Service.cpp
    COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/StressTest.thrift
)

add_custom_command(OUTPUT gen-cpp/EchoService.cpp gen-cpp/SpecificNameTest_types.cpp
    COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/SpecificNameTest.thrift
)
thrift-0.19.0/test/cpp/Makefile0000644000000000000000000007671514472652606016334 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# test/cpp/Makefile.  Generated from Makefile.in by configure.

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.




am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/thrift
pkgincludedir = $(includedir)/thrift
pkglibdir = $(libdir)/thrift
pkglibexecdir = $(libexecdir)/thrift
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = x86_64-pc-linux-gnu
host_triplet = x86_64-pc-linux-gnu
check_PROGRAMS = TestServer$(EXEEXT) TestClient$(EXEEXT) \
	StressTest$(EXEEXT) StressTestNonBlocking$(EXEEXT)
subdir = test/cpp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libstresstestgencpp_la_DEPENDENCIES =  \
	$(top_builddir)/lib/cpp/libthrift.la
am__dirstamp = $(am__leading_dot)dirstamp
nodist_libstresstestgencpp_la_OBJECTS = gen-cpp/Service.lo
libstresstestgencpp_la_OBJECTS =  \
	$(nodist_libstresstestgencpp_la_OBJECTS)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
am__v_lt_1 = 
libtestgencpp_la_DEPENDENCIES = $(top_builddir)/lib/cpp/libthrift.la
nodist_libtestgencpp_la_OBJECTS = gen-cpp/SecondService.lo \
	gen-cpp/ThriftTest_constants.lo gen-cpp/ThriftTest_types.lo \
	gen-cpp/ThriftTest.lo src/ThriftTest_extras.lo
libtestgencpp_la_OBJECTS = $(nodist_libtestgencpp_la_OBJECTS)
am_StressTest_OBJECTS = src/StressTest.$(OBJEXT)
StressTest_OBJECTS = $(am_StressTest_OBJECTS)
StressTest_DEPENDENCIES = libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la
am_StressTestNonBlocking_OBJECTS =  \
	src/StressTestNonBlocking.$(OBJEXT)
StressTestNonBlocking_OBJECTS = $(am_StressTestNonBlocking_OBJECTS)
StressTestNonBlocking_DEPENDENCIES = libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthriftnb.la
am_TestClient_OBJECTS = src/TestClient.$(OBJEXT)
TestClient_OBJECTS = $(am_TestClient_OBJECTS)
am__DEPENDENCIES_1 =
TestClient_DEPENDENCIES = libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1)
am_TestServer_OBJECTS = src/TestServer.$(OBJEXT)
TestServer_OBJECTS = $(am_TestServer_OBJECTS)
TestServer_DEPENDENCIES = libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_$(V))
am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY))
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_$(V))
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
am__v_at_0 = @
am__v_at_1 = 
DEFAULT_INCLUDES = 
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_$(V))
am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
am__v_CXX_0 = @echo "  CXX     " $@;
am__v_CXX_1 = 
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_$(V))
am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
am__v_CXXLD_0 = @echo "  CXXLD   " $@;
am__v_CXXLD_1 = 
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_$(V))
am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
am__v_CC_0 = @echo "  CC      " $@;
am__v_CC_1 = 
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
	$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_$(V))
am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
am__v_CCLD_0 = @echo "  CCLD    " $@;
am__v_CCLD_1 = 
SOURCES = $(nodist_libstresstestgencpp_la_SOURCES) \
	$(nodist_libtestgencpp_la_SOURCES) $(StressTest_SOURCES) \
	$(StressTestNonBlocking_SOURCES) $(TestClient_SOURCES) \
	$(TestServer_SOURCES)
DIST_SOURCES = $(StressTest_SOURCES) $(StressTestNonBlocking_SOURCES) \
	$(TestClient_SOURCES) $(TestServer_SOURCES)
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15
ALLOCA = 
AMTAR = $${TAR-tar}
AM_DEFAULT_VERBOSITY = 1
ANT = /usr/bin/ant
ANT_FLAGS = 
AR = ar
AUTOCONF = ${SHELL} /thrift/src/missing autoconf
AUTOHEADER = ${SHELL} /thrift/src/missing autoheader
AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15
AWK = mawk
BISON = bison
BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a
BOOST_CPPFLAGS = -I/usr/include
BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a
BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu
BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu
BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a
BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a
BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a
BUNDLER = /usr/bin/bundle
CARGO = /root/.cargo/bin/cargo
CC = gcc
CCDEPMODE = depmode=gcc3
CFLAGS = -g -O2
CLASSPATH = 
CPP = gcc -E
CPPFLAGS = 
CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \;
CXX = g++ -std=c++11
CXXCPP = g++ -E -std=c++11
CXXDEPMODE = depmode=gcc3
CXXFLAGS = -g -O2
CYGPATH_W = echo
DART = /usr/lib/dart/bin/dart
DARTPUB = /usr/lib/dart/bin/pub
DEFS = -DHAVE_CONFIG_H
DEPDIR = .deps
DLLTOOL = false
DMD = dmd
DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent
DMD_OF_DIRSEP = /
DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto
DOTNETCORE = /usr/bin/dotnet
DOTNETCORE_VERSION = 6.0.405
DSYMUTIL = 
DUMPBIN = 
D_EVENT_LIB_NAME = libthriftd-event.a
D_IMPORT_PREFIX = ${prefix}/include/d2
D_LIB_NAME = libthriftd.a
D_SSL_LIB_NAME = libthriftd-ssl.a
ECHO_C = 
ECHO_N = -n
ECHO_T = 
EGREP = /bin/grep -E
ENABLE_COVERAGE = 2
ERL = /usr/local/lib/otp/bin/erl
ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib
ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0
ERLANG_LIB_DIR = /usr/local/lib/otp/lib
ERLC = /usr/local/lib/otp/bin/erlc
ERLCFLAGS = 
EXEEXT = 
FGREP = /bin/grep -F
GCOV_CFLAGS = 
GCOV_CXXFLAGS = 
GCOV_LDFLAGS = 
GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
GLIB_LIBS = -lglib-2.0
GO = /usr/local/bin/go
GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0
GRADLE = /usr/local/bin/gradle
GRADLE_OPTS = 
GREP = /bin/grep
GSETTINGS = /usr/bin/gsettings
HAVE_CXX11 = 1
HAXE = /usr/bin/haxe
HAXE_VERSION = 3.4.4
INSTALL = /usr/bin/install -c
INSTALLDIRS = vendor
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_PROGRAM = ${INSTALL}
INSTALL_SCRIPT = ${INSTALL}
INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
JAVA_PREFIX = /usr/local/lib
LD = /usr/bin/ld -m elf_x86_64
LDFLAGS = 
LEX = flex
LEXLIB = 
LEX_OUTPUT_ROOT = lex.yy
LIBEVENT_CPPFLAGS = 
LIBEVENT_LDFLAGS = 
LIBEVENT_LIBS = -levent
LIBOBJS = 
LIBS = -lrt -lpthread 
LIBTOOL = $(SHELL) $(top_builddir)/libtool
LIPO = 
LN_S = ln -s
LTLIBOBJS = 
LT_SYS_LIBRARY_PATH = 
LUA = /usr/bin/lua
LUA_EXEC_PREFIX = ${exec_prefix}
LUA_INCLUDE = -I/usr/include/lua5.2
LUA_LIB = -llua5.2  -ldl
LUA_PLATFORM = unknown
LUA_PREFIX = ${prefix}
LUA_SHORT_VERSION = 52
LUA_VERSION = 5.2
MAKEINFO = ${SHELL} /thrift/src/missing makeinfo
MANIFEST_TOOL = :
MAYBE_CL = cl
MAYBE_CPP = cpp
MAYBE_C_GLIB = c_glib
MAYBE_D = d
MAYBE_DART = dart
MAYBE_ERLANG = erl
MAYBE_GO = go
MAYBE_JAVA = java
MAYBE_KOTLIN = 
MAYBE_LUA = lua
MAYBE_NETSTD = 
MAYBE_NODEJS = nodejs
MAYBE_NODETS = nodets
MAYBE_PERL = perl
MAYBE_PHP = php
MAYBE_PY3 = py3
MAYBE_PYTHON = py
MAYBE_RS = rs
MAYBE_RUBY = rb
MAYBE_SWIFT = swift
MKDIR_P = /bin/mkdir -p
NM = /usr/bin/nm -B
NMEDIT = 
NODEJS = /usr/bin/nodejs
NODETS = /usr/bin/node
NPM = /usr/bin/npm
OBJDUMP = objdump
OBJEXT = o
OPENSSL_INCLUDES = 
OPENSSL_LDFLAGS = 
OPENSSL_LIBS = -lssl -lcrypto
OTOOL = 
OTOOL64 = 
PACKAGE = thrift
PACKAGE_BUGREPORT = 
PACKAGE_NAME = thrift
PACKAGE_STRING = thrift 0.19.0
PACKAGE_TARNAME = thrift
PACKAGE_URL = 
PACKAGE_VERSION = 0.19.0
PATH_SEPARATOR = :
PERL = /usr/bin/perl
PERL_PREFIX = /usr/local
PHP = /usr/bin/php
PHP_CONFIG = /usr/bin/php-config
PHP_CONFIG_PREFIX = /etc/php.d
PHP_PREFIX = /usr/lib/php
PKG_CONFIG = /usr/bin/pkg-config
PKG_CONFIG_LIBDIR = 
PKG_CONFIG_PATH = 
PYTHON = /usr/bin/python
PYTHON3 = /usr/bin/python3
PYTHON_EXEC_PREFIX = ${exec_prefix}
PYTHON_PLATFORM = linux2
PYTHON_PREFIX = ${prefix}
PYTHON_VERSION = 2.7
PY_PREFIX = /usr
QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5
QT5_LIBS = -lQt5Network -lQt5Core
QT5_MOC = /usr/bin/moc
RANLIB = ranlib
REBAR = /usr/local/bin/rebar3
RUBY = /usr/bin/ruby
RUBY_PREFIX = 
RUSTC = /root/.cargo/bin/rustc
SBCL = /usr/local/bin/sbcl
SED = /bin/sed
SET_MAKE = 
SHELL = /bin/bash
STRIP = strip
SWIFT = /usr/share/swift/usr/bin/swift
THRIFT = /thrift/src/compiler/cpp/thrift
TRIAL = /usr/bin/trial
VERSION = 0.19.0
YACC = bison -y
YFLAGS = 
ZLIB_CPPFLAGS = 
ZLIB_LDFLAGS = 
ZLIB_LIBS = -lz
abs_builddir = /thrift/src/test/cpp
abs_srcdir = /thrift/src/test/cpp
abs_top_builddir = /thrift/src
abs_top_srcdir = /thrift/src
ac_ct_AR = ar
ac_ct_CC = gcc
ac_ct_CXX = g++
ac_ct_DUMPBIN = 
am__include = include
am__leading_dot = .
am__quote = 
am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir"
am__untar = tar -xf -
bindir = ${exec_prefix}/bin
build = x86_64-pc-linux-gnu
build_alias = 
build_cpu = x86_64
build_os = linux-gnu
build_vendor = pc
builddir = .
datadir = ${datarootdir}
datarootdir = ${prefix}/share
docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
dvidir = ${docdir}
exec_prefix = ${prefix}
golang_version = go version go1.19.5 linux/amd64
have_prog_bison = yes
host = x86_64-pc-linux-gnu
host_alias = 
host_cpu = x86_64
host_os = linux-gnu
host_vendor = pc
htmldir = ${docdir}
includedir = ${prefix}/include
infodir = ${datarootdir}/info
install_sh = ${SHELL} /thrift/src/install-sh
libdir = ${exec_prefix}/lib
libexecdir = ${exec_prefix}/libexec
localedir = ${datarootdir}/locale
localstatedir = ${prefix}/var
luadir = ${prefix}/share/lua/5.2
luaexecdir = ${exec_prefix}/lib/lua/5.2
mandir = ${datarootdir}/man
mkdir_p = $(MKDIR_P)
oldincludedir = /usr/include
pdfdir = ${docdir}
pkgluadir = ${luadir}/thrift
pkgluaexecdir = ${luaexecdir}/thrift
pkgpyexecdir = ${pyexecdir}/thrift
pkgpythondir = ${pythondir}/thrift
prefix = /usr/local
program_transform_name = s,x,x,
psdir = ${docdir}
pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages
pythondir = ${prefix}/lib/python2.7/dist-packages
runstatedir = ${localstatedir}/run
rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18)
sbindir = ${exec_prefix}/sbin
sharedstatedir = ${prefix}/com
srcdir = .
subdirs =  lib/php/src/ext/thrift_protocol
sysconfdir = ${prefix}/etc
target_alias = 
top_build_prefix = ../../
top_builddir = ../..
top_srcdir = ../..

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc
BUILT_SOURCES = gen-cpp/ThriftTest.cpp \
                gen-cpp/ThriftTest_types.cpp \
                gen-cpp/ThriftTest_constants.cpp \
                gen-cpp/SecondService.cpp \
                gen-cpp/Service.cpp

noinst_LTLIBRARIES = libtestgencpp.la libstresstestgencpp.la
nodist_libtestgencpp_la_SOURCES = \
	gen-cpp/SecondService.cpp \
	gen-cpp/SecondService.h \
	gen-cpp/SecondService.tcc \
	gen-cpp/ThriftTest_constants.cpp \
	gen-cpp/ThriftTest_constants.h \
	gen-cpp/ThriftTest_types.cpp \
	gen-cpp/ThriftTest_types.h \
	gen-cpp/ThriftTest_types.tcc \
	gen-cpp/ThriftTest.cpp \
	gen-cpp/ThriftTest.h \
	gen-cpp/ThriftTest.tcc \
	src/ThriftTest_extras.cpp

libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
nodist_libstresstestgencpp_la_SOURCES = \
	gen-cpp/StressTest_types.h \
	gen-cpp/Service.cpp \
	gen-cpp/Service.h

libstresstestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la

# we currently do not run the testsuite, stop c++ server issue
# TESTS = \
#	$(check_PROGRAMS)
TestServer_SOURCES = \
	src/TestServer.cpp

TestServer_LDADD = \
	libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)

TestClient_SOURCES = \
	src/TestClient.cpp

TestClient_LDADD = \
	libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)

StressTest_SOURCES = \
	src/StressTest.cpp

StressTest_LDADD = \
	libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la

StressTestNonBlocking_SOURCES = \
	src/StressTestNonBlocking.cpp

StressTestNonBlocking_LDADD = \
	libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent

AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I.
AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS)
EXTRA_DIST = \
	src/TestClient.cpp \
	src/TestServer.cpp \
	src/StressTest.cpp \
	src/StressTestNonBlocking.cpp

all: $(BUILT_SOURCES)
	$(MAKE) $(AM_MAKEFLAGS) all-am

.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/cpp/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/cpp/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

clean-noinstLTLIBRARIES:
	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
	@list='$(noinst_LTLIBRARIES)'; \
	locs=`for p in $$list; do echo $$p; done | \
	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
	      sort -u`; \
	test -z "$$locs" || { \
	  echo rm -f $${locs}; \
	  rm -f $${locs}; \
	}
gen-cpp/$(am__dirstamp):
	@$(MKDIR_P) gen-cpp
	@: > gen-cpp/$(am__dirstamp)
gen-cpp/$(DEPDIR)/$(am__dirstamp):
	@$(MKDIR_P) gen-cpp/$(DEPDIR)
	@: > gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/Service.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)

libstresstestgencpp.la: $(libstresstestgencpp_la_OBJECTS) $(libstresstestgencpp_la_DEPENDENCIES) $(EXTRA_libstresstestgencpp_la_DEPENDENCIES) 
	$(AM_V_CXXLD)$(CXXLINK)  $(libstresstestgencpp_la_OBJECTS) $(libstresstestgencpp_la_LIBADD) $(LIBS)
gen-cpp/SecondService.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/ThriftTest_constants.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/ThriftTest_types.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/ThriftTest.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
src/$(am__dirstamp):
	@$(MKDIR_P) src
	@: > src/$(am__dirstamp)
src/$(DEPDIR)/$(am__dirstamp):
	@$(MKDIR_P) src/$(DEPDIR)
	@: > src/$(DEPDIR)/$(am__dirstamp)
src/ThriftTest_extras.lo: src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

libtestgencpp.la: $(libtestgencpp_la_OBJECTS) $(libtestgencpp_la_DEPENDENCIES) $(EXTRA_libtestgencpp_la_DEPENDENCIES) 
	$(AM_V_CXXLD)$(CXXLINK)  $(libtestgencpp_la_OBJECTS) $(libtestgencpp_la_LIBADD) $(LIBS)

clean-checkPROGRAMS:
	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
	echo " rm -f" $$list; \
	rm -f $$list || exit $$?; \
	test -n "$(EXEEXT)" || exit 0; \
	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
	echo " rm -f" $$list; \
	rm -f $$list
src/StressTest.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

StressTest$(EXEEXT): $(StressTest_OBJECTS) $(StressTest_DEPENDENCIES) $(EXTRA_StressTest_DEPENDENCIES) 
	@rm -f StressTest$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(StressTest_OBJECTS) $(StressTest_LDADD) $(LIBS)
src/StressTestNonBlocking.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

StressTestNonBlocking$(EXEEXT): $(StressTestNonBlocking_OBJECTS) $(StressTestNonBlocking_DEPENDENCIES) $(EXTRA_StressTestNonBlocking_DEPENDENCIES) 
	@rm -f StressTestNonBlocking$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(StressTestNonBlocking_OBJECTS) $(StressTestNonBlocking_LDADD) $(LIBS)
src/TestClient.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

TestClient$(EXEEXT): $(TestClient_OBJECTS) $(TestClient_DEPENDENCIES) $(EXTRA_TestClient_DEPENDENCIES) 
	@rm -f TestClient$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(TestClient_OBJECTS) $(TestClient_LDADD) $(LIBS)
src/TestServer.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

TestServer$(EXEEXT): $(TestServer_OBJECTS) $(TestServer_DEPENDENCIES) $(EXTRA_TestServer_DEPENDENCIES) 
	@rm -f TestServer$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(TestServer_OBJECTS) $(TestServer_LDADD) $(LIBS)

mostlyclean-compile:
	-rm -f *.$(OBJEXT)
	-rm -f gen-cpp/*.$(OBJEXT)
	-rm -f gen-cpp/*.lo
	-rm -f src/*.$(OBJEXT)
	-rm -f src/*.lo

distclean-compile:
	-rm -f *.tab.c

include gen-cpp/$(DEPDIR)/SecondService.Plo
include gen-cpp/$(DEPDIR)/Service.Plo
include gen-cpp/$(DEPDIR)/ThriftTest.Plo
include gen-cpp/$(DEPDIR)/ThriftTest_constants.Plo
include gen-cpp/$(DEPDIR)/ThriftTest_types.Plo
include src/$(DEPDIR)/StressTest.Po
include src/$(DEPDIR)/StressTestNonBlocking.Po
include src/$(DEPDIR)/TestClient.Po
include src/$(DEPDIR)/TestServer.Po
include src/$(DEPDIR)/ThriftTest_extras.Plo

.cpp.o:
	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
	$(am__mv) $$depbase.Tpo $$depbase.Po
#	$(AM_V_CXX)source='$<' object='$@' libtool=no \
#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
#	$(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ $<

.cpp.obj:
	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
	$(am__mv) $$depbase.Tpo $$depbase.Po
#	$(AM_V_CXX)source='$<' object='$@' libtool=no \
#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
#	$(AM_V_CXX_no)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`

.cpp.lo:
	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
	$(am__mv) $$depbase.Tpo $$depbase.Plo
#	$(AM_V_CXX)source='$<' object='$@' libtool=yes \
#	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
#	$(AM_V_CXX_no)$(LTCXXCOMPILE) -c -o $@ $<

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs
	-rm -rf gen-cpp/.libs gen-cpp/_libs
	-rm -rf src/.libs src/_libs
style-local: 

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-am

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
check-am: all-am
	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
check: $(BUILT_SOURCES)
	$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: $(BUILT_SOURCES)
	$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
	-rm -f gen-cpp/$(DEPDIR)/$(am__dirstamp)
	-rm -f gen-cpp/$(am__dirstamp)
	-rm -f src/$(DEPDIR)/$(am__dirstamp)
	-rm -f src/$(am__dirstamp)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am

clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \
	clean-noinstLTLIBRARIES mostlyclean-am

distclean: distclean-am
	-rm -rf gen-cpp/$(DEPDIR) src/$(DEPDIR)
	-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
	distclean-tags

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -rf gen-cpp/$(DEPDIR) src/$(DEPDIR)
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-compile mostlyclean-generic \
	mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

style: style-am

style-am: style-local

uninstall-am:

.MAKE: all check check-am install install-am install-strip

.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
	clean-checkPROGRAMS clean-generic clean-libtool clean-local \
	clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
	distclean-compile distclean-generic distclean-libtool \
	distclean-tags distdir dvi dvi-am html html-am info info-am \
	install install-am install-data install-data-am install-dvi \
	install-dvi-am install-exec install-exec-am install-html \
	install-html-am install-info install-info-am install-man \
	install-pdf install-pdf-am install-ps install-ps-am \
	install-strip installcheck installcheck-am installdirs \
	maintainer-clean maintainer-clean-generic mostlyclean \
	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
	pdf pdf-am ps ps-am style-am style-local tags tags-am \
	uninstall uninstall-am

.PRECIOUS: Makefile


precross: TestServer TestClient
#
# Common thrift code generation rules
#
gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/SecondService.tcc: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT)
	$(THRIFT) --gen cpp:templates,cob_style -r $<

gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT)
	$(THRIFT) --gen cpp $<

gen-cpp/SpecificNameTest_types.cpp gen-cpp/EchoService.cpp: $(top_srcdir)/test/SpecificName.thrift $(THRIFT)
	$(THRIFT) --gen cpp $<

clean-local:
	$(RM) -r gen-cpp/

style-local:
	$(CPPSTYLE_CMD)

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/cpp/src/0000777000000000000000000000000014472652702015444 5ustar00rootroot00000000000000thrift-0.19.0/test/cpp/src/TestClient.cpp0000644000000000000000000012264414303740367020231 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include  // 

#ifdef HAVE_STDINT_H
#include 
#endif
#ifdef HAVE_INTTYPES_H
#include 
#endif

#include 
#include 
#include 
#include 
#if _WIN32
#include 
#endif

#include "SecondService.h"
#include "ThriftTest.h"

using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::async;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace thrift::test;

//
// A pedantic protocol that checks to make sure the response sequence ID
// is the same as the sent sequence ID.  lib/cpp always sends zero for
// synchronous clients, so this bumps the number to make sure it gets
// returned properly from the remote server.  Any server that does not
// respond with the same sequence number is violating the sequence ID
// agreement between client and server.
//

template
class TPedanticProtocol : public Proto 
{
    public:
        TPedanticProtocol(std::shared_ptr& transport)
          : Proto(transport), m_last_seqid((std::numeric_limits::max)() - 10) { }

        virtual uint32_t writeMessageBegin_virt(const std::string& name,
                                           const TMessageType messageType,
                                           const int32_t in_seqid) override
        {
            int32_t seqid = in_seqid;
            if (!seqid) { // this is typical for normal cpp generated code
                seqid = ++m_last_seqid;
            }

            return Proto::writeMessageBegin_virt(name, messageType, seqid);
        }

        virtual uint32_t readMessageBegin_virt(std::string& name,
                                          TMessageType& messageType,
                                          int32_t& seqid) override
        {
            uint32_t result = Proto::readMessageBegin_virt(name, messageType, seqid);
            if (seqid != m_last_seqid) {
                std::stringstream ss;
                ss << "ERROR: send request with seqid " << m_last_seqid << " and got reply with seqid " << seqid;
                throw std::logic_error(ss.str());
            } /* else {
                std::cout << "verified seqid " << m_last_seqid << " round trip OK" << std::endl;
            } */
            return result;
        }

    private:
        int32_t m_last_seqid;
};

// Current time, microseconds since the epoch
uint64_t now() {
  int64_t ret;
  struct timeval tv;

  THRIFT_GETTIMEOFDAY(&tv, nullptr);
  ret = tv.tv_sec;
  ret = ret * 1000 * 1000 + tv.tv_usec;
  return ret;
}

static void testString_clientReturn(event_base* base,
                                    int testNr,
                                    ThriftTestCobClient* client) {
  try {
    string s;
    client->recv_testString(s);
    std::ostringstream os;
    os << "test" << testNr;
    const bool ok = (s == os.str());
    cout << "testString: " << s << " " << ((ok) ? "ok" : "failed") << endl;
  } catch (TException& exn) {
    cout << "Error: " << exn.what() << endl;
  }

  if (testNr == 9)
    event_base_loopbreak(base); // end test
}

static void testVoid_clientReturn(event_base* base, ThriftTestCobClient* client) {
  try {
    client->recv_testVoid();
    cout << "testVoid" << endl;

    for (int testNr = 0; testNr < 10; ++testNr) {
      std::ostringstream os;
      os << "test" << testNr;
      client->testString(std::bind(testString_clientReturn,
                                    base,
                                    testNr,
                                    std::placeholders::_1),
                       os.str());
    }
  } catch (TException& exn) {
    cout << "Error: " << exn.what() << endl;
  }
}

// Workaround for absense of C++11 "auto" keyword.
template 
bool print_eq(T expected, T actual) {
  cout << "(" << actual << ")" << endl;
  if (expected != actual) {
    cout << "*** FAILED ***" << endl << "Expected: " << expected << " but got: " << actual << endl;
    return false;
  }
  return true;
}

#define BASETYPE_IDENTITY_TEST(func, value)                                                        \
  cout << #func "(" << value << ") = ";                                                            \
  try {                                                                                            \
    if (!print_eq(value, testClient.func(value)))                                                  \
      return_code |= ERR_BASETYPES;                                                                \
  } catch (TTransportException&) {                                                                 \
    throw;                                                                                         \
  } catch (exception & ex) {                                                                       \
    cout << "*** FAILED ***" << endl << ex.what() << endl;                                         \
    return_code |= ERR_BASETYPES;                                                                  \
  }

int binary_test(ThriftTestClient& testClient, string::size_type siz);

BOOST_CONSTEXPR_OR_CONST int ERR_BASETYPES = 1;
BOOST_CONSTEXPR_OR_CONST int ERR_STRUCTS = 2;
BOOST_CONSTEXPR_OR_CONST int ERR_CONTAINERS = 4;
BOOST_CONSTEXPR_OR_CONST int ERR_EXCEPTIONS = 8;
BOOST_CONSTEXPR_OR_CONST int ERR_UNKNOWN = 64;

int main(int argc, char** argv) {
  cout.precision(19);

  string testDir  = boost::filesystem::system_complete(argv[0]).parent_path().parent_path().parent_path().string();
  string caPath   = testDir + "/keys/CA.pem";
  string certPath = testDir + "/keys/client.crt";
  string keyPath  = testDir + "/keys/client.key";

#if _WIN32
  transport::TWinsockSingleton::create();
#endif
  string host = "localhost";
  int port = 9090;
  int numTests = 1;
  bool ssl = false;
  bool zlib = false;
  string transport_type = "buffered";
  string protocol_type = "binary";
  string domain_socket = "";
  bool abstract_namespace = false;
  bool noinsane = false;

  int return_code = 0;

  boost::program_options::options_description desc("Allowed options");
  desc.add_options()
      ("help,h", "produce help message")
      ("host",
          boost::program_options::value(&host)->default_value(host),
          "Host to connect")
      ("port",
          boost::program_options::value(&port)->default_value(port),
          "Port number to connect")
      ("domain-socket",
          boost::program_options::value(&domain_socket)->default_value(domain_socket),
          "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port")
      ("abstract-namespace",
          "Look for the domain socket in the Abstract Namespace"
          " (no connection with filesystem pathnames)")
      ("transport",
          boost::program_options::value(&transport_type)->default_value(transport_type),
          "Transport: buffered, framed, http, evhttp, zlib")
      ("protocol",
          boost::program_options::value(&protocol_type)->default_value(protocol_type),
          "Protocol: binary, compact, header, json, multi, multic, multih, multij")
      ("ssl",
          "Encrypted Transport using SSL")
      ("zlib",
          "Wrap Transport with Zlib")
      ("testloops,n",
          boost::program_options::value(&numTests)->default_value(numTests),
          "Number of Tests")
      ("noinsane",
          "Do not run insanity test");

  boost::program_options::variables_map vm;
  boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
  boost::program_options::notify(vm);

  if (vm.count("help")) {
    cout << desc << endl;
    return ERR_UNKNOWN;
  }

  try {
    if (!protocol_type.empty()) {
      if (protocol_type == "binary") {
      } else if (protocol_type == "compact") {
      } else if (protocol_type == "header") {
      } else if (protocol_type == "json") {
      } else if (protocol_type == "multi") {
      } else if (protocol_type == "multic") {
      } else if (protocol_type == "multih") {
      } else if (protocol_type == "multij") {
      } else {
        throw invalid_argument("Unknown protocol type " + protocol_type);
      }
    }

    if (!transport_type.empty()) {
      if (transport_type == "buffered") {
      } else if (transport_type == "framed") {
      } else if (transport_type == "http") {
      } else if (transport_type == "evhttp") {
      } else if (transport_type == "zlib") {
        // crosstest will pass zlib as a transport and as a flag right now..
      } else {
        throw invalid_argument("Unknown transport type " + transport_type);
      }
    }

  } catch (exception& e) {
    cerr << e.what() << endl;
    cout << desc << endl;
    return ERR_UNKNOWN;
  }

  if (vm.count("ssl")) {
    ssl = true;
  }

  if (vm.count("zlib")) {
    zlib = true;
  }

  if (vm.count("abstract-namespace")) {
    abstract_namespace = true;
  }

  if (vm.count("noinsane")) {
    noinsane = true;
  }

  // THRIFT-4164: The factory MUST outlive any sockets it creates for correct behavior!
  std::shared_ptr factory;
  std::shared_ptr socket;
  std::shared_ptr transport;
  std::shared_ptr protocol;
  std::shared_ptr protocol2;  // SecondService for multiplexed

  if (ssl) {
    cout << "Client Certificate File: " << certPath << endl;
    cout << "Client Key         File: " << keyPath << endl;
    cout << "CA                 File: " << caPath << endl;

    factory = std::shared_ptr(new TSSLSocketFactory());
    factory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
    factory->loadTrustedCertificates(caPath.c_str());
    factory->loadCertificate(certPath.c_str());
    factory->loadPrivateKey(keyPath.c_str());
    factory->authenticate(true);
    socket = factory->createSocket(host, port);
  } else {
    if (domain_socket != "") {
      if (abstract_namespace) {
        std::string abstract_socket("\0", 1);
        abstract_socket += domain_socket;
        socket = std::shared_ptr(new TSocket(abstract_socket));
      } else {
        socket = std::shared_ptr(new TSocket(domain_socket));
      }
      port = 0;
    } else {
      socket = std::shared_ptr(new TSocket(host, port));
    }
  }

  if (transport_type.compare("http") == 0) {
    transport = std::make_shared(socket, host, "/service");
  } else if (transport_type.compare("framed") == 0) {
    transport = std::make_shared(socket);
  } else {
    transport = std::make_shared(socket);
  }

  if (zlib) {
    transport = std::make_shared(transport);
  }

  if (protocol_type == "json" || protocol_type == "multij") {
    typedef TPedanticProtocol TPedanticJSONProtocol;
    protocol = std::make_shared(transport);
  } else if (protocol_type == "compact" || protocol_type == "multic") {
    typedef TPedanticProtocol TPedanticCompactProtocol;
    protocol = std::make_shared(transport);
  } else if (protocol_type == "header" || protocol_type == "multih") {
    typedef TPedanticProtocol TPedanticHeaderProtocol;
    protocol = std::make_shared(transport);
  } else {
    typedef TPedanticProtocol TPedanticBinaryProtocol;
    protocol = std::make_shared(transport);
  }

  if (boost::starts_with(protocol_type, "multi")) {
    protocol2 = std::make_shared(protocol, "SecondService");
    // we don't need access to the original protocol any more, so...
    protocol = std::make_shared(protocol, "ThriftTest");
  }

  // Connection info
  cout << "Connecting (" << transport_type << "/" << protocol_type << ") to: ";
  if (abstract_namespace) {
    cout << '@';
  }
  cout << domain_socket;
  if (port != 0) {
    cout << host << ":" << port;
  }
  cout << endl;

  if (transport_type.compare("evhttp") == 0) {
    event_base* base = event_base_new();
    cout << "Libevent Version: " << event_get_version() << endl;
    cout << "Libevent Method: " << event_base_get_method(base) << endl;
#if LIBEVENT_VERSION_NUMBER >= 0x02000000
    cout << "Libevent Features: 0x" << hex << event_base_get_features(base) << endl;
#endif

    std::shared_ptr protocolFactory(new TBinaryProtocolFactory());

    std::shared_ptr channel(
        new TEvhttpClientChannel(host.c_str(), "/", host.c_str(), port, base));
    ThriftTestCobClient* client = new ThriftTestCobClient(channel, protocolFactory.get());
    client->testVoid(std::bind(testVoid_clientReturn,
                                base,
                                std::placeholders::_1));

    event_base_loop(base, 0);
    return 0;
  }

  ThriftTestClient testClient(protocol);

  uint64_t time_min = 0;
  uint64_t time_max = 0;
  uint64_t time_tot = 0;

  int test = 0;
  for (test = 0; test < numTests; ++test) {

    try {
      transport->open();
    } catch (TTransportException& ex) {
      cout << "Connect failed: " << ex.what() << endl;
      return ERR_UNKNOWN;
    }

    /**
     * CONNECT TEST
     */
    printf("Test #%d, connect %s:%d\n", test + 1, host.c_str(), port);

    uint64_t start = now();

    /**
     * VOID TEST
     */
    try {
      cout << "testVoid()" << flush;
      testClient.testVoid();
      cout << " = void" << endl;
    } catch (TTransportException&) {
      // Stop here if transport got broken
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_BASETYPES;
    }

    /**
     * STRING TEST
     */
    cout << "testString(\"Test\")" << flush;
    string s;
    testClient.testString(s, "Test");
    cout << " = " << s << endl;
    if (s != "Test") {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_BASETYPES;
    }

    //
    // Multiplexed protocol - call another service method
    // in the middle of the ThriftTest
    //
    if (boost::starts_with(protocol_type, "multi")) {
    SecondServiceClient ssc(protocol2);
    // transport is already open...

        try {
          cout << "secondService.secondTestString(\"foo\") => " << flush;
        std::string result;
      ssc.secondtestString(result, "foo");
      cout << "{" << result << "}" << endl;
      } catch (std::exception& e) {
      cout << "  *** FAILED *** " << e.what() << endl;
      return_code |= ERR_EXCEPTIONS;
    }
    }

    try {
#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4566 )
#endif
      string str(
          "}{Afrikaans, Alemannisch, Aragonés, العربية, مصرى, "
          "Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, "
          "БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, "
          "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, "
          "Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, "
          "Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, "
          "Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, "
          "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, "
          "Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, "
          "Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, "
          "Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, "
          "ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, "
          "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, "
          "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa "
          "Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa "
          "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪"
          "Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, "
          "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, "
          "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, "
          "РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple "
          "English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, "
          "Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, "
          "Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, "
          "Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, "
          "Bân-lâm-gú, 粵語");
#ifdef _MSC_VER
#pragma warning( pop )
#endif
      cout << "testString(" << str << ") = " << flush;
      testClient.testString(s, str);
      cout << s << endl;
      if (s != str) {
        cout.imbue(locale("en_US.UTF8"));
        cout << "*** FAILED ***" << endl << "Expected string: " << str << " but got: " << s << endl << "CLEAR";
        return_code |= ERR_BASETYPES;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_BASETYPES;
      return return_code;
    }
    try {
      string str(
          "quote: \" backslash:"
          " forwardslash-escaped: \\/ "
          " backspace: \b formfeed: \f newline: \n return: \r tab: "
          " now-all-of-them-together: \"\\\\/\b\n\r\t"
          " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><"
          " char-to-test-json-parsing: ]] \"]] \\\" }}}{ [[[ ");
      cout << "testString(" << str << ") = " << flush;
      testClient.testString(s, str);
      cout << s << endl;
      if (s != str) {
        cout.imbue(locale("en_US.UTF8"));
        cout << "*** FAILED ***" << endl
             << "Expected string: " << str << " but got: " << s << endl
             << "CLEAR";
        ;
        return_code |= ERR_BASETYPES;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_BASETYPES;
      return return_code;
    }

    /**
     * BOOL TEST
     */
    cout << boolalpha;
    BASETYPE_IDENTITY_TEST(testBool, true);
    BASETYPE_IDENTITY_TEST(testBool, false);

    /**
     * BYTE TEST
     */
    BASETYPE_IDENTITY_TEST(testByte, (int8_t)0);
    BASETYPE_IDENTITY_TEST(testByte, (int8_t)-1);
    BASETYPE_IDENTITY_TEST(testByte, (int8_t)42);
    BASETYPE_IDENTITY_TEST(testByte, (int8_t)-42);
    BASETYPE_IDENTITY_TEST(testByte, (int8_t)127);
    BASETYPE_IDENTITY_TEST(testByte, (int8_t)-128);

    /**
     * I32 TEST
     */
    BASETYPE_IDENTITY_TEST(testI32, 0);
    BASETYPE_IDENTITY_TEST(testI32, -1);
    BASETYPE_IDENTITY_TEST(testI32, 190000013);
    BASETYPE_IDENTITY_TEST(testI32, -190000013);
    BASETYPE_IDENTITY_TEST(testI32, (numeric_limits::max)());
    BASETYPE_IDENTITY_TEST(testI32, (numeric_limits::min)());

    /**
     * I64 TEST
     */
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)0);
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)-1);
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)7000000000000000123LL);
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)-7000000000000000123LL);
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)pow(static_cast(2LL), 32));
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)-pow(static_cast(2LL), 32));
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)pow(static_cast(2LL), 32) + 1);
    BASETYPE_IDENTITY_TEST(testI64, (int64_t)-pow(static_cast(2LL), 32) - 1);
    BASETYPE_IDENTITY_TEST(testI64, (numeric_limits::max)());
    BASETYPE_IDENTITY_TEST(testI64, (numeric_limits::min)());

    /**
     * DOUBLE TEST
     */
    // Comparing double values with plain equality because Thrift handles full precision of double
    BASETYPE_IDENTITY_TEST(testDouble, 0.0);
    BASETYPE_IDENTITY_TEST(testDouble, -1.0);
    BASETYPE_IDENTITY_TEST(testDouble, -5.2098523);
    BASETYPE_IDENTITY_TEST(testDouble, -0.000341012439638598279);
    BASETYPE_IDENTITY_TEST(testDouble, pow(static_cast(2), 32));
    BASETYPE_IDENTITY_TEST(testDouble, pow(static_cast(2), 32) + 1);
    BASETYPE_IDENTITY_TEST(testDouble, pow(static_cast(2), 53) - 1);
    BASETYPE_IDENTITY_TEST(testDouble, -pow(static_cast(2), 32));
    BASETYPE_IDENTITY_TEST(testDouble, -pow(static_cast(2), 32) - 1);
    BASETYPE_IDENTITY_TEST(testDouble, -pow(static_cast(2), 53) + 1);

    try {
      double expected = pow(static_cast(10), 307);
      cout << "testDouble(" << expected << ") = " << flush;
      double actual = testClient.testDouble(expected);
      cout << "(" << actual << ")" << endl;
      if (expected - actual > pow(static_cast(10), 292)) {
        cout << "*** FAILED ***" << endl
             << "Expected: " << expected << " but got: " << actual << endl;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_BASETYPES;
    }

    try {
      double expected = pow(static_cast(10), -292);
      cout << "testDouble(" << expected << ") = " << flush;
      double actual = testClient.testDouble(expected);
      cout << "(" << actual << ")" << endl;
      if (expected - actual > pow(static_cast(10), -307)) {
        cout << "*** FAILED ***" << endl
             << "Expected: " << expected << " but got: " << actual << endl;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_BASETYPES;
    }

    /**
     * BINARY TEST
     */
    for (string::size_type i = 0; i < 131073 && !return_code; ) {
      return_code |= binary_test(testClient, i);
      if (i > 0) { i *= 2; } else { ++i; }
    }


    /**
     * STRUCT TEST
     */
    cout << "testStruct({\"Zero\", 1, -3, -5})" << flush;
    Xtruct out;
    out.string_thing = "Zero";
    out.byte_thing = 1;
    out.i32_thing = -3;
    out.i64_thing = -5;
    Xtruct in;
    testClient.testStruct(in, out);
    printf(" = {\"%s\", %d, %d, %" PRId64 "}\n",
           in.string_thing.c_str(),
           (int)in.byte_thing,
           in.i32_thing,
           in.i64_thing);
    if (in != out) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    /**
     * NESTED STRUCT TEST
     */
    cout << "testNest({1, {\"Zero\", 1, -3, -5}), 5}" << flush;
    Xtruct2 out2;
    out2.byte_thing = 1;
    out2.struct_thing = out;
    out2.i32_thing = 5;
    Xtruct2 in2;
    testClient.testNest(in2, out2);
    in = in2.struct_thing;
    printf(" = {%d, {\"%s\", %d, %d, %" PRId64 "}, %d}\n",
           in2.byte_thing,
           in.string_thing.c_str(),
           (int)in.byte_thing,
           in.i32_thing,
           in.i64_thing,
           in2.i32_thing);
    if (in2 != out2) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    /**
     * MAP TEST
     */
    map mapout;
    for (int32_t i = 0; i < 5; ++i) {
      mapout.insert(make_pair(i, i - 10));
    }
    cout << "testMap({" << flush;
    map::const_iterator m_iter;
    bool first = true;
    for (m_iter = mapout.begin(); m_iter != mapout.end(); ++m_iter) {
      if (first) {
        first = false;
      } else {
        cout << ",";
      }
      cout << m_iter->first << " => " << m_iter->second;
    }
    cout << "})";
    map mapin;
    testClient.testMap(mapin, mapout);
    cout << " = {";
    first = true;
    for (m_iter = mapin.begin(); m_iter != mapin.end(); ++m_iter) {
      if (first) {
        first = false;
      } else {
        cout << ",";
      }
      cout << m_iter->first << " => " << m_iter->second;
    }
    cout << "}" << endl;
    if (mapin != mapout) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_CONTAINERS;
    }

    /**
     * STRING MAP TEST
     */
    cout << "testStringMap({a => 2, b => blah, some => thing}) = {" << flush;
    map smapin;
    map smapout;
    smapin["a"] = "2";
    smapin["b"] = "blah";
    smapin["some"] = "thing";
    try {
      testClient.testStringMap(smapout, smapin);
      first = true;
      for (map::const_iterator it = smapout.begin(); it != smapout.end(); ++it) {
        if (first)
          cout << ",";
        else
          first = false;
        cout << it->first << " => " << it->second;
      }
      cout << "}" << endl;
      if (smapin != smapout) {
        cout << "*** FAILED ***" << endl;
        return_code |= ERR_CONTAINERS;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_CONTAINERS;
    }

    /**
     * SET TEST
     */
    set setout;
    for (int32_t i = -2; i < 3; ++i) {
      setout.insert(i);
    }
    cout << "testSet({" << flush;
    set::const_iterator s_iter;
    first = true;
    for (s_iter = setout.begin(); s_iter != setout.end(); ++s_iter) {
      if (first) {
        first = false;
      } else {
        cout << ",";
      }
      cout << *s_iter;
    }
    cout << "})";
    set setin;
    testClient.testSet(setin, setout);
    cout << " = {";
    first = true;
    for (s_iter = setin.begin(); s_iter != setin.end(); ++s_iter) {
      if (first) {
        first = false;
      } else {
        cout << ",";
      }
      cout << *s_iter;
    }
    cout << "}" << endl;
    if (setin != setout) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_CONTAINERS;
    }

    /**
     * LIST TEST
     */
    cout << "testList(empty)" << flush;
    try {
      vector listout;
      testClient.testList(listout, vector());
      if (!listout.empty()) {
        cout << "*** FAILED ***" << endl;
        cout << "invalid length: " << listout.size() << endl;
        return_code |= ERR_CONTAINERS;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_CONTAINERS;
    }
    try {
      vector listout;
      for (int32_t i = -2; i < 3; ++i) {
        listout.push_back(i);
      }
      cout << "testList({" << flush;
      vector::const_iterator l_iter;
      first = true;
      for (l_iter = listout.begin(); l_iter != listout.end(); ++l_iter) {
        if (first) {
          first = false;
        } else {
          cout << ",";
        }
        cout << *l_iter;
      }
      cout << "})";
      vector listin;
      testClient.testList(listin, listout);
      cout << " = {";
      first = true;
      for (l_iter = listin.begin(); l_iter != listin.end(); ++l_iter) {
        if (first) {
          first = false;
        } else {
          cout << ",";
        }
        cout << *l_iter;
      }
      cout << "}" << endl;
      if (listin != listout) {
        cout << "*** FAILED ***" << endl;
        return_code |= ERR_CONTAINERS;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_CONTAINERS;
    }

    /**
     * ENUM TEST
     */
    cout << "testEnum(ONE)" << flush;
    Numberz::type ret = testClient.testEnum(Numberz::ONE);
    cout << " = " << ret << endl;
    if (ret != Numberz::ONE) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    cout << "testEnum(TWO)" << flush;
    ret = testClient.testEnum(Numberz::TWO);
    cout << " = " << ret << endl;
    if (ret != Numberz::TWO) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    cout << "testEnum(THREE)" << flush;
    ret = testClient.testEnum(Numberz::THREE);
    cout << " = " << ret << endl;
    if (ret != Numberz::THREE) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    cout << "testEnum(FIVE)" << flush;
    ret = testClient.testEnum(Numberz::FIVE);
    cout << " = " << ret << endl;
    if (ret != Numberz::FIVE) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    cout << "testEnum(EIGHT)" << flush;
    ret = testClient.testEnum(Numberz::EIGHT);
    cout << " = " << ret << endl;
    if (ret != Numberz::EIGHT) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    /**
     * TYPEDEF TEST
     */
    cout << "testTypedef(309858235082523)" << flush;
    UserId uid = testClient.testTypedef(309858235082523LL);
    cout << " = " << uid << endl;
    if (uid != 309858235082523LL) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_STRUCTS;
    }

    /**
     * NESTED MAP TEST
     */
    cout << "testMapMap(1)" << flush;
    map > mm;
    testClient.testMapMap(mm, 1);
    cout << " = {";
    map >::const_iterator mi;
    for (mi = mm.begin(); mi != mm.end(); ++mi) {
      printf("%d => {", mi->first);
      map::const_iterator mi2;
      for (mi2 = mi->second.begin(); mi2 != mi->second.end(); ++mi2) {
        cout << mi2->first << " => " << mi2->second;
      }
      cout << "}, ";
    }
    cout << "}" << endl;
    if (mm.size() != 2 ||
        mm[-4][-4] != -4 ||
        mm[-4][-3] != -3 ||
        mm[-4][-2] != -2 ||
        mm[-4][-1] != -1 ||
        mm[4][4] != 4 ||
        mm[4][3] != 3 ||
        mm[4][2] != 2 ||
        mm[4][1] != 1) {
      cout << "*** FAILED ***" << endl;
      return_code |= ERR_CONTAINERS;
    }

    /**
     * INSANITY TEST
     */
    if (!noinsane) {
      Insanity insane;
      insane.userMap.insert(make_pair(Numberz::FIVE, 5));
      insane.userMap.insert(make_pair(Numberz::EIGHT, 8));
      Xtruct truck;
      truck.string_thing = "Goodbye4";
      truck.byte_thing = 4;
      truck.i32_thing = 4;
      truck.i64_thing = 4;
      Xtruct truck2;
      truck2.string_thing = "Hello2";
      truck2.byte_thing = 2;
      truck2.i32_thing = 2;
      truck2.i64_thing = 2;
      insane.xtructs.push_back(truck);
      insane.xtructs.push_back(truck2);
      cout << "testInsanity()" << flush;
      map > whoa;
      testClient.testInsanity(whoa, insane);
      cout << " = {";
      map >::const_iterator i_iter;
      for (i_iter = whoa.begin(); i_iter != whoa.end(); ++i_iter) {
        printf("%" PRId64 " => {", i_iter->first);
        map::const_iterator i2_iter;
        for (i2_iter = i_iter->second.begin(); i2_iter != i_iter->second.end(); ++i2_iter) {
          printf("%d => {", i2_iter->first);
          map userMap = i2_iter->second.userMap;
          map::const_iterator um;
          cout << "{";
          for (um = userMap.begin(); um != userMap.end(); ++um) {
            cout << um->first << " => " << um->second;
          }
          cout << "}, ";

          vector xtructs = i2_iter->second.xtructs;
          vector::const_iterator x;
          cout << "{";
          for (x = xtructs.begin(); x != xtructs.end(); ++x) {
            printf("{\"%s\", %d, %d, %" PRId64 "}, ",
                   x->string_thing.c_str(),
                   (int)x->byte_thing,
                   x->i32_thing,
                   x->i64_thing);
          }
          cout << "}";

          cout << "}, ";
        }
        cout << "}, ";
      }
      cout << "}" << endl;
      bool failed = false;
      map >::const_iterator it1 = whoa.find(UserId(1));
      if (whoa.size() != 2) {
        failed = true;
      }
      if (it1 == whoa.end()) {
        failed = true;
      } else {
        auto it12 = it1->second.find(Numberz::TWO);
        if (it12 == it1->second.end() || it12->second != insane) {
          failed = true;
        }
        auto it13 = it1->second.find(Numberz::THREE);
        if (it13 == it1->second.end() || it13->second != insane) {
          failed = true;
        }
      }
      map >::const_iterator it2 = whoa.find(UserId(2));
      if (it2 == whoa.end()) {
        failed = true;
      } else {
        auto it26 = it2->second.find(Numberz::SIX);
        if (it26 == it2->second.end() || it26->second != Insanity()) {
          failed = true;
        }
      }
      if (failed) {
        cout << "*** FAILED ***" << endl;
        return_code |= ERR_STRUCTS;
      }
    }

    /**
     * MULTI TEST
     */
    cout << "testMulti()" << endl;
    try {
      map mul_map;
      Xtruct mul_result;
      mul_map[1] = "blah";
      mul_map[2] = "thing";
      testClient.testMulti(mul_result, 42, 4242, 424242, mul_map, Numberz::EIGHT, UserId(24));
      Xtruct xxs;
      xxs.string_thing = "Hello2";
      xxs.byte_thing = 42;
      xxs.i32_thing = 4242;
      xxs.i64_thing = 424242;
      if (mul_result != xxs) {
        cout << "*** FAILED ***" << endl;
        return_code |= ERR_STRUCTS;
      }
    } catch (TTransportException&) {
      throw;
    } catch (exception& ex) {
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_STRUCTS;
    }

    /* test exception */

    try {
      cout << "testClient.testException(\"Xception\") =>" << flush;
      testClient.testException("Xception");
      cout << "  void\n*** FAILED ***" << endl;
      return_code |= ERR_EXCEPTIONS;

    } catch (Xception& e) {
      printf("  {%u, \"%s\"}\n", e.errorCode, e.message.c_str());
    }

    try {
      cout << "testClient.testException(\"TException\") =>" << flush;
      testClient.testException("TException");
      cout << "  void\n*** FAILED ***" << endl;
      return_code |= ERR_EXCEPTIONS;

    } catch (const TException&) {
      cout << "  Caught TException" << endl;
    }

    try {
      cout << "testClient.testException(\"success\") =>" << flush;
      testClient.testException("success");
      cout << "  void" << endl;
    } catch (exception & ex) {                                                                       \
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_EXCEPTIONS;
    }

    /* test multi exception */

    try {
      cout << "testClient.testMultiException(\"Xception\", \"test 1\") =>" << flush;
      Xtruct result;
      testClient.testMultiException(result, "Xception", "test 1");
      cout << "  result\n*** FAILED ***" << endl;
      return_code |= ERR_EXCEPTIONS;
    } catch (Xception& e) {
      printf("  {%u, \"%s\"}\n", e.errorCode, e.message.c_str());
    }

    try {
      cout << "testClient.testMultiException(\"Xception2\", \"test 2\") =>" << flush;
      Xtruct result;
      testClient.testMultiException(result, "Xception2", "test 2");
      cout << "  result\n*** FAILED ***" << endl;
      return_code |= ERR_EXCEPTIONS;

    } catch (Xception2& e) {
      printf("  {%u, {\"%s\"}}\n", e.errorCode, e.struct_thing.string_thing.c_str());
    }

    try {
      cout << "testClient.testMultiException(\"success\", \"test 3\") =>" << flush;
      Xtruct result;
      testClient.testMultiException(result, "success", "test 3");
      printf("  {{\"%s\"}}\n", result.string_thing.c_str());
    } catch (exception & ex) {                                                                       \
      cout << "*** FAILED ***" << endl << ex.what() << endl;
      return_code |= ERR_EXCEPTIONS;
    }

    /* test oneway void */
    {
      cout << "testClient.testOneway(1) =>" << flush;
      uint64_t startOneway = now();
      testClient.testOneway(1);
      uint64_t elapsed = now() - startOneway;
      if (elapsed > 200 * 1000) { // 0.2 seconds
        printf("*** FAILED *** - took %.2f ms\n", (double)elapsed / 1000.0);
      return_code |= ERR_BASETYPES;
      } else {
        printf("  success - took %.2f ms\n", (double)elapsed / 1000.0);
      }
    }

    /**
     * redo a simple test after the oneway to make sure we aren't "off by one" --
     * if the server treated oneway void like normal void, this next test will
     * fail since it will get the void confirmation rather than the correct
     * result. In this circumstance, the client will throw the exception:
     *
     *   TApplicationException: Wrong method namea
     */
    /**
     * I32 TEST
     */
    cout << "re-test testI32(-1)" << flush;
    int i32 = testClient.testI32(-1);
    cout << " = " << i32 << endl;
    if (i32 != -1)
      return_code |= ERR_BASETYPES;

    cout << endl << "All tests done." << endl << flush;

    uint64_t stop = now();
    uint64_t tot = stop - start;

    cout << "Total time: " << stop - start << " us" << endl;

    time_tot += tot;
    if (time_min == 0 || tot < time_min) {
      time_min = tot;
    }
    if (tot > time_max) {
      time_max = tot;
    }

    cout << flush;
    transport->close();
  }


  uint64_t time_avg = time_tot / numTests;

  cout << "Min time: " << time_min << " us" << endl;
  cout << "Max time: " << time_max << " us" << endl;
  cout << "Avg time: " << time_avg << " us" << endl;

  return return_code;
}

void binary_fill(std::string& str, string::size_type siz)
{
    static const signed char bin_data[256]
        = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114,
           -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99,
           -98,  -97,  -96,  -95,  -94,  -93,  -92,  -91,  -90,  -89,  -88,  -87,  -86,  -85,  -84,
           -83,  -82,  -81,  -80,  -79,  -78,  -77,  -76,  -75,  -74,  -73,  -72,  -71,  -70,  -69,
           -68,  -67,  -66,  -65,  -64,  -63,  -62,  -61,  -60,  -59,  -58,  -57,  -56,  -55,  -54,
           -53,  -52,  -51,  -50,  -49,  -48,  -47,  -46,  -45,  -44,  -43,  -42,  -41,  -40,  -39,
           -38,  -37,  -36,  -35,  -34,  -33,  -32,  -31,  -30,  -29,  -28,  -27,  -26,  -25,  -24,
           -23,  -22,  -21,  -20,  -19,  -18,  -17,  -16,  -15,  -14,  -13,  -12,  -11,  -10,  -9,
           -8,   -7,   -6,   -5,   -4,   -3,   -2,   -1,   0,    1,    2,    3,    4,    5,    6,
           7,    8,    9,    10,   11,   12,   13,   14,   15,   16,   17,   18,   19,   20,   21,
           22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32,   33,   34,   35,   36,
           37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48,   49,   50,   51,
           52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64,   65,   66,
           67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80,   81,
           82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,   96,
           97,   98,   99,   100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110,  111,
           112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126,
           127};

    str.resize(siz);
    char *ptr = &str[0];
    string::size_type pos = 0;
    for (string::size_type i = 0; i < siz; ++i)
    {
        if (pos == 255) { pos = 0; } else { ++pos; }
        *ptr++ = bin_data[pos];
    }
}

int binary_test(ThriftTestClient& testClient, string::size_type siz)
{
    string bin_request;
    string bin_result;

    cout << "testBinary(siz = " << siz << ")" << endl;
    binary_fill(bin_request, siz);
    try {
        testClient.testBinary(bin_result, bin_request);

        if (bin_request.size() != bin_result.size()) {
            cout << "*** FAILED: request size " << bin_request.size() << "; result size " << bin_result.size() << endl;
            return ERR_BASETYPES;
        }

        for (string::size_type i = 0; i < siz; ++i) {
            if (bin_request.at(i) != bin_result.at(i)) {
                cout << "*** FAILED: at position " << i << " request[i] is h" << hex << bin_request.at(i) << " result[i] is h" << hex << bin_result.at(i) << endl;
                return ERR_BASETYPES;
            }
        }
    } catch (TTransportException&) {
        throw;
    } catch (exception& ex) {
        cout << "*** FAILED ***" << endl << ex.what() << endl;
        return ERR_BASETYPES;
    }

    return 0;
}
thrift-0.19.0/test/cpp/src/TestServer.cpp0000644000000000000000000006744414303740367020267 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "SecondService.h"
#include "ThriftTest.h"

#ifdef HAVE_STDINT_H
#include 
#endif
#ifdef HAVE_INTTYPES_H
#include 
#endif
#ifdef HAVE_SIGNAL_H
#include 
#endif

#include 
#include 
#include 

#include 
#include 
#include 

#if _WIN32
#include 
#endif

using namespace std;

using namespace apache::thrift;
using namespace apache::thrift::async;
using namespace apache::thrift::concurrency;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;

using namespace thrift::test;

// to handle a controlled shutdown, signal handling is mandatory
#ifdef HAVE_SIGNAL_H
apache::thrift::concurrency::Monitor gMonitor;
void signal_handler(int signum)
{
  if (signum == SIGINT) {
    gMonitor.notifyAll();
  }
}
#endif

class TestHandler : public ThriftTestIf {
public:
  TestHandler() = default;

  void testVoid() override { printf("testVoid()\n"); }

  void testString(string& out, const string& thing) override {
    printf("testString(\"%s\")\n", thing.c_str());
    out = thing;
  }

  bool testBool(const bool thing) override {
    printf("testBool(%s)\n", thing ? "true" : "false");
    return thing;
  }

  int8_t testByte(const int8_t thing) override {
    printf("testByte(%d)\n", (int)thing);
    return thing;
  }

  int32_t testI32(const int32_t thing) override {
    printf("testI32(%d)\n", thing);
    return thing;
  }

  int64_t testI64(const int64_t thing) override {
    printf("testI64(%" PRId64 ")\n", thing);
    return thing;
  }

  double testDouble(const double thing) override {
    printf("testDouble(%f)\n", thing);
    return thing;
  }

  void testBinary(std::string& _return, const std::string& thing) override {
    std::ostringstream hexstr;
    hexstr << std::hex << thing;
    printf("testBinary(%lu: %s)\n", safe_numeric_cast(thing.size()), hexstr.str().c_str());
    _return = thing;
  }

  void testStruct(Xtruct& out, const Xtruct& thing) override {
    printf("testStruct({\"%s\", %d, %d, %" PRId64 "})\n",
           thing.string_thing.c_str(),
           (int)thing.byte_thing,
           thing.i32_thing,
           thing.i64_thing);
    out = thing;
  }

  void testNest(Xtruct2& out, const Xtruct2& nest) override {
    const Xtruct& thing = nest.struct_thing;
    printf("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n",
           (int)nest.byte_thing,
           thing.string_thing.c_str(),
           (int)thing.byte_thing,
           thing.i32_thing,
           thing.i64_thing,
           nest.i32_thing);
    out = nest;
  }

  void testMap(map& out, const map& thing) override {
    printf("testMap({");
    map::const_iterator m_iter;
    bool first = true;
    for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) {
      if (first) {
        first = false;
      } else {
        printf(", ");
      }
      printf("%d => %d", m_iter->first, m_iter->second);
    }
    printf("})\n");
    out = thing;
  }

  void testStringMap(map& out,
                     const map& thing) override {
    printf("testMap({");
    map::const_iterator m_iter;
    bool first = true;
    for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) {
      if (first) {
        first = false;
      } else {
        printf(", ");
      }
      printf("%s => %s", (m_iter->first).c_str(), (m_iter->second).c_str());
    }
    printf("})\n");
    out = thing;
  }

  void testSet(set& out, const set& thing) override {
    printf("testSet({");
    set::const_iterator s_iter;
    bool first = true;
    for (s_iter = thing.begin(); s_iter != thing.end(); ++s_iter) {
      if (first) {
        first = false;
      } else {
        printf(", ");
      }
      printf("%d", *s_iter);
    }
    printf("})\n");
    out = thing;
  }

  void testList(vector& out, const vector& thing) override {
    printf("testList({");
    vector::const_iterator l_iter;
    bool first = true;
    for (l_iter = thing.begin(); l_iter != thing.end(); ++l_iter) {
      if (first) {
        first = false;
      } else {
        printf(", ");
      }
      printf("%d", *l_iter);
    }
    printf("})\n");
    out = thing;
  }

  Numberz::type testEnum(const Numberz::type thing) override {
    printf("testEnum(%d)\n", thing);
    return thing;
  }

  UserId testTypedef(const UserId thing) override {
    printf("testTypedef(%" PRId64 ")\n", thing);
    return thing;
  }

  void testMapMap(map >& mapmap, const int32_t hello) override {
    printf("testMapMap(%d)\n", hello);

    map pos;
    map neg;
    for (int i = 1; i < 5; i++) {
      pos.insert(make_pair(i, i));
      neg.insert(make_pair(-i, -i));
    }

    mapmap.insert(make_pair(4, pos));
    mapmap.insert(make_pair(-4, neg));
  }

  void testInsanity(map >& insane, const Insanity& argument) override {
    printf("testInsanity()\n");

    Insanity looney;
    map first_map;
    map second_map;

    first_map.insert(make_pair(Numberz::TWO, argument));
    first_map.insert(make_pair(Numberz::THREE, argument));

    second_map.insert(make_pair(Numberz::SIX, looney));

    insane.insert(make_pair(1, first_map));
    insane.insert(make_pair(2, second_map));

    printf("return");
    printf(" = {");
    map >::const_iterator i_iter;
    for (i_iter = insane.begin(); i_iter != insane.end(); ++i_iter) {
      printf("%" PRId64 " => {", i_iter->first);
      map::const_iterator i2_iter;
      for (i2_iter = i_iter->second.begin(); i2_iter != i_iter->second.end(); ++i2_iter) {
        printf("%d => {", i2_iter->first);
        map userMap = i2_iter->second.userMap;
        map::const_iterator um;
        printf("{");
        for (um = userMap.begin(); um != userMap.end(); ++um) {
          printf("%d => %" PRId64 ", ", um->first, um->second);
        }
        printf("}, ");

        vector xtructs = i2_iter->second.xtructs;
        vector::const_iterator x;
        printf("{");
        for (x = xtructs.begin(); x != xtructs.end(); ++x) {
          printf("{\"%s\", %d, %d, %" PRId64 "}, ",
                 x->string_thing.c_str(),
                 (int)x->byte_thing,
                 x->i32_thing,
                 x->i64_thing);
        }
        printf("}");

        printf("}, ");
      }
      printf("}, ");
    }
    printf("}\n");
  }

  void testMulti(Xtruct& hello,
                 const int8_t arg0,
                 const int32_t arg1,
                 const int64_t arg2,
                 const std::map& arg3,
                 const Numberz::type arg4,
                 const UserId arg5) override {
    (void)arg3;
    (void)arg4;
    (void)arg5;

    printf("testMulti()\n");

    hello.string_thing = "Hello2";
    hello.byte_thing = arg0;
    hello.i32_thing = arg1;
    hello.i64_thing = (int64_t)arg2;
  }

  void testException(const std::string& arg) override {
    printf("testException(%s)\n", arg.c_str());
    if (arg.compare("Xception") == 0) {
      Xception e;
      e.errorCode = 1001;
      e.message = arg;
      throw e;
    } else if (arg.compare("TException") == 0) {
      apache::thrift::TException e;
      throw e;
    } else {
      Xtruct result;
      result.string_thing = arg;
      return;
    }
  }

  void testMultiException(Xtruct& result,
                          const std::string& arg0,
                          const std::string& arg1) override {

    printf("testMultiException(%s, %s)\n", arg0.c_str(), arg1.c_str());

    if (arg0.compare("Xception") == 0) {
      Xception e;
      e.errorCode = 1001;
      e.message = "This is an Xception";
      throw e;
    } else if (arg0.compare("Xception2") == 0) {
      Xception2 e;
      e.errorCode = 2002;
      e.struct_thing.string_thing = "This is an Xception2";
      throw e;
    } else {
      result.string_thing = arg1;
      return;
    }
  }

  void testOneway(const int32_t aNum) override {
    printf("testOneway(%d): call received\n", aNum);
  }
};

class SecondHandler : public SecondServiceIf
{
  public:
    void secondtestString(std::string& result, const std::string& thing) override
    { result = "testString(\"" + thing + "\")"; }
};

class TestProcessorEventHandler : public TProcessorEventHandler {
  void* getContext(const char* fn_name, void* serverContext) override {
    (void)serverContext;
    return new std::string(fn_name);
  }
  void freeContext(void* ctx, const char* fn_name) override {
    (void)fn_name;
    delete static_cast(ctx);
  }
  void preRead(void* ctx, const char* fn_name) override { communicate("preRead", ctx, fn_name); }
  void postRead(void* ctx, const char* fn_name, uint32_t bytes) override {
    (void)bytes;
    communicate("postRead", ctx, fn_name);
  }
  void preWrite(void* ctx, const char* fn_name) override { communicate("preWrite", ctx, fn_name); }
  void postWrite(void* ctx, const char* fn_name, uint32_t bytes) override {
    (void)bytes;
    communicate("postWrite", ctx, fn_name);
  }
  void asyncComplete(void* ctx, const char* fn_name) override {
    communicate("asyncComplete", ctx, fn_name);
  }
  void handlerError(void* ctx, const char* fn_name) override {
    communicate("handlerError", ctx, fn_name);
  }

  void communicate(const char* event, void* ctx, const char* fn_name) {
    std::cout << event << ": " << *static_cast(ctx) << " = " << fn_name << std::endl;
  }
};

class TestHandlerAsync : public ThriftTestCobSvIf {
public:
  TestHandlerAsync(std::shared_ptr& handler) : _delegate(handler) {}
  ~TestHandlerAsync() override = default;

  void testVoid(std::function cob) override {
    _delegate->testVoid();
    cob();
  }

  void testString(std::function cob,
                          const std::string& thing) override {
    std::string res;
    _delegate->testString(res, thing);
    cob(res);
  }

  void testBool(std::function cob, const bool thing) override {
    bool res = _delegate->testBool(thing);
    cob(res);
  }

  void testByte(std::function cob, const int8_t thing) override {
    int8_t res = _delegate->testByte(thing);
    cob(res);
  }

  void testI32(std::function cob, const int32_t thing) override {
    int32_t res = _delegate->testI32(thing);
    cob(res);
  }

  void testI64(std::function cob, const int64_t thing) override {
    int64_t res = _delegate->testI64(thing);
    cob(res);
  }

  void testDouble(std::function cob, const double thing) override {
    double res = _delegate->testDouble(thing);
    cob(res);
  }

  void testBinary(std::function cob,
                          const std::string& thing) override {
    std::string res;
    _delegate->testBinary(res, thing);
    cob(res);
  }

  void testStruct(std::function cob, const Xtruct& thing) override {
    Xtruct res;
    _delegate->testStruct(res, thing);
    cob(res);
  }

  void testNest(std::function cob, const Xtruct2& thing) override {
    Xtruct2 res;
    _delegate->testNest(res, thing);
    cob(res);
  }

  void testMap(std::function const& _return)> cob,
                       const std::map& thing) override {
    std::map res;
    _delegate->testMap(res, thing);
    cob(res);
  }

  void testStringMap(
      std::function const& _return)> cob,
      const std::map& thing) override {
    std::map res;
    _delegate->testStringMap(res, thing);
    cob(res);
  }

  void testSet(std::function const& _return)> cob,
                       const std::set& thing) override {
    std::set res;
    _delegate->testSet(res, thing);
    cob(res);
  }

  void testList(std::function const& _return)> cob,
                        const std::vector& thing) override {
    std::vector res;
    _delegate->testList(res, thing);
    cob(res);
  }

  void testEnum(std::function cob,
                        const Numberz::type thing) override {
    Numberz::type res = _delegate->testEnum(thing);
    cob(res);
  }

  void testTypedef(std::function cob, const UserId thing) override {
    UserId res = _delegate->testTypedef(thing);
    cob(res);
  }

  void testMapMap(
      std::function > const& _return)> cob,
      const int32_t hello) override {
    std::map > res;
    _delegate->testMapMap(res, hello);
    cob(res);
  }

  void testInsanity(
      std::function > const& _return)> cob,
      const Insanity& argument) override {
    std::map > res;
    _delegate->testInsanity(res, argument);
    cob(res);
  }

  void testMulti(std::function cob,
                         const int8_t arg0,
                         const int32_t arg1,
                         const int64_t arg2,
                         const std::map& arg3,
                         const Numberz::type arg4,
                         const UserId arg5) override {
    Xtruct res;
    _delegate->testMulti(res, arg0, arg1, arg2, arg3, arg4, arg5);
    cob(res);
  }

  void testException(
      std::function cob,
      std::function exn_cob,
      const std::string& arg) override {
    try {
      _delegate->testException(arg);
    } catch (const apache::thrift::TException& e) {
      exn_cob(apache::thrift::TDelayedException::delayException(e));
      return;
    }
    cob();
  }

  void testMultiException(
      std::function cob,
      std::function exn_cob,
      const std::string& arg0,
      const std::string& arg1) override {
    Xtruct res;
    try {
      _delegate->testMultiException(res, arg0, arg1);
    } catch (const apache::thrift::TException& e) {
      exn_cob(apache::thrift::TDelayedException::delayException(e));
      return;
    }
    cob(res);
  }

  void testOneway(std::function cob, const int32_t secondsToSleep) override {
    _delegate->testOneway(secondsToSleep);
    cob();
  }

protected:
  std::shared_ptr _delegate;
};

namespace po = boost::program_options;

int main(int argc, char** argv) {

  string testDir = boost::filesystem::system_complete(argv[0]).parent_path().parent_path().parent_path().string();
  string certPath = testDir + "/keys/server.crt";
  string keyPath = testDir + "/keys/server.key";

#if _WIN32
  transport::TWinsockSingleton::create();
#endif
  int port = 9090;
  bool ssl = false;
  bool zlib = false;
  string transport_type = "buffered";
  string protocol_type = "binary";
  string server_type = "simple";
  string domain_socket = "";
  bool abstract_namespace = false;
  size_t workers = 4;
  int string_limit = 0;
  int container_limit = 0;

  po::options_description desc("Allowed options");
  desc.add_options()
    ("help,h", "produce help message")
    ("port", po::value(&port)->default_value(port), "Port number to listen")
    ("domain-socket", po::value(&domain_socket) ->default_value(domain_socket), "Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)")
    ("abstract-namespace", "Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames)")
    ("server-type", po::value(&server_type)->default_value(server_type), "type of server, \"simple\", \"thread-pool\", \"threaded\", or \"nonblocking\"")
    ("transport", po::value(&transport_type)->default_value(transport_type), "transport: buffered, framed, http, websocket, zlib")
    ("protocol", po::value(&protocol_type)->default_value(protocol_type), "protocol: binary, compact, header, json, multi, multic, multih, multij")
    ("ssl", "Encrypted Transport using SSL")
    ("zlib", "Wrapped Transport using Zlib")
    ("processor-events", "processor-events")
    ("workers,n", po::value(&workers)->default_value(workers), "Number of thread pools workers. Only valid for thread-pool server type")
    ("string-limit", po::value(&string_limit))
    ("container-limit", po::value(&container_limit));

  po::variables_map vm;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);

  if (vm.count("help")) {
    cout << desc << "\n";
    return 1;
  }

  try {
    if (!server_type.empty()) {
      if (server_type == "simple") {
      } else if (server_type == "thread-pool") {
      } else if (server_type == "threaded") {
      } else if (server_type == "nonblocking") {
      } else {
        throw invalid_argument("Unknown server type " + server_type);
      }
    }

    if (!protocol_type.empty()) {
      if (protocol_type == "binary") {
      } else if (protocol_type == "compact") {
      } else if (protocol_type == "json") {
      } else if (protocol_type == "header") {
      } else if (protocol_type == "multi") {  // multiplexed binary
      } else if (protocol_type == "multic") { // multiplexed compact
      } else if (protocol_type == "multih") { // multiplexed header
      } else if (protocol_type == "multij") { // multiplexed json
      } else {
        throw invalid_argument("Unknown protocol type " + protocol_type);
      }
    }

    if (!transport_type.empty()) {
      if (transport_type == "buffered") {
      } else if (transport_type == "framed") {
      } else if (transport_type == "http") {
      } else if (transport_type == "websocket") {
      } else if (transport_type == "zlib") {
        // crosstester will pass zlib as a flag and a transport right now...
      } else {
        throw invalid_argument("Unknown transport type " + transport_type);
      }
    }

  } catch (std::exception& e) {
    cerr << e.what() << endl;
    cout << desc << "\n";
    return 1;
  }

  if (vm.count("ssl")) {
    ssl = true;
  }

  if (vm.count("zlib")) {
    zlib = true;
  }

#if defined(HAVE_SIGNAL_H) && defined(SIGPIPE)
  if (ssl) {
    signal(SIGPIPE, SIG_IGN); // for OpenSSL, otherwise we end abruptly
  }
#endif

  if (vm.count("abstract-namespace")) {
    abstract_namespace = true;
  }

  // Dispatcher
  std::shared_ptr protocolFactory;
  if (protocol_type == "json" || protocol_type == "multij") {
    std::shared_ptr jsonProtocolFactory(new TJSONProtocolFactory());
    protocolFactory = jsonProtocolFactory;
  } else if (protocol_type == "compact" || protocol_type == "multic") {
    auto *compactProtocolFactory = new TCompactProtocolFactoryT();
    compactProtocolFactory->setContainerSizeLimit(container_limit);
    compactProtocolFactory->setStringSizeLimit(string_limit);
    protocolFactory.reset(compactProtocolFactory);
  } else if (protocol_type == "header" || protocol_type == "multih") {
    std::shared_ptr headerProtocolFactory(new THeaderProtocolFactory());
    protocolFactory = headerProtocolFactory;
  } else {
    auto* binaryProtocolFactory = new TBinaryProtocolFactoryT();
    binaryProtocolFactory->setContainerSizeLimit(container_limit);
    binaryProtocolFactory->setStringSizeLimit(string_limit);
    protocolFactory.reset(binaryProtocolFactory);
  }

  // Processors
  std::shared_ptr testHandler(new TestHandler());
  std::shared_ptr testProcessor(new ThriftTestProcessor(testHandler));

  if (vm.count("processor-events")) {
    testProcessor->setEventHandler(
        std::shared_ptr(new TestProcessorEventHandler()));
  }

  // Transport
  std::shared_ptr sslSocketFactory;
  std::shared_ptr serverSocket;

  if (ssl) {
    sslSocketFactory = std::shared_ptr(new TSSLSocketFactory());
    sslSocketFactory->loadCertificate(certPath.c_str());
    sslSocketFactory->loadPrivateKey(keyPath.c_str());
    sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
    if (server_type != "nonblocking") {
      serverSocket = std::shared_ptr(new TSSLServerSocket(port, sslSocketFactory));
    }
  } else {
    if (domain_socket != "") {
      if (abstract_namespace) {
        std::string abstract_socket("\0", 1);
        abstract_socket += domain_socket;
        serverSocket = std::shared_ptr(new TServerSocket(abstract_socket));
      } else {
        unlink(domain_socket.c_str());
        serverSocket = std::shared_ptr(new TServerSocket(domain_socket));
      }
      port = 0;
    } else {
      serverSocket = std::shared_ptr(new TServerSocket(port));
    }
  }

  // Factory
  std::shared_ptr transportFactory;

  if (transport_type == "http" && server_type != "nonblocking") {
    transportFactory = std::make_shared();
  } else if (transport_type == "websocket" && server_type != "nonblocking") {
    if (protocol_type == "json" || protocol_type == "multij") {
      transportFactory = std::make_shared();
    } else {
      transportFactory = std::make_shared();
    }
  } else if (transport_type == "framed") {
    transportFactory = std::make_shared();
  } else {
    transportFactory = std::make_shared();
  }

  if (zlib) {
    // currently TZlibTransportFactory is the only factory than can wrap another:
    transportFactory = std::make_shared(transportFactory);
  }

  // Server Info
  cout << "Starting \"" << server_type << "\" server (" << transport_type << "/" << protocol_type
       << ") listen on: ";
  if (abstract_namespace) {
    cout << '@';
  }
  cout << domain_socket;
  if (port != 0) {
    cout << port;
  }
  cout << endl;

  // Multiplexed Processor if needed
  if (boost::starts_with(protocol_type, "multi")) {
    std::shared_ptr secondHandler(new SecondHandler());
    std::shared_ptr secondProcessor(new SecondServiceProcessor(secondHandler));

    std::shared_ptr multiplexedProcessor(new TMultiplexedProcessor());
    multiplexedProcessor->registerDefault(testProcessor); // non-multi clients go to the default processor (multi:binary, multic:compact, ...)
    multiplexedProcessor->registerProcessor("ThriftTest", testProcessor);
    multiplexedProcessor->registerProcessor("SecondService", secondProcessor);
    testProcessor = std::dynamic_pointer_cast(multiplexedProcessor);
  }

  // Server
  std::shared_ptr server;

  if (server_type == "simple") {
    server.reset(new TSimpleServer(testProcessor, serverSocket, transportFactory, protocolFactory));
  } else if (server_type == "thread-pool") {

    std::shared_ptr threadFactory
        = std::shared_ptr(new ThreadFactory());

    std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workers);
    threadManager->threadFactory(threadFactory);
    threadManager->start();

    server.reset(new TThreadPoolServer(testProcessor,
                                       serverSocket,
                                       transportFactory,
                                       protocolFactory,
                                       threadManager));
  } else if (server_type == "threaded") {
    server.reset(
        new TThreadedServer(testProcessor, serverSocket, transportFactory, protocolFactory));
  } else if (server_type == "nonblocking") {
    if (transport_type == "http") {
      std::shared_ptr testHandlerAsync(new TestHandlerAsync(testHandler));
      std::shared_ptr testProcessorAsync(
          new ThriftTestAsyncProcessor(testHandlerAsync));
      std::shared_ptr testBufferProcessor(
          new TAsyncProtocolProcessor(testProcessorAsync, protocolFactory));

      // not loading nonblockingServer into "server" because
      // TEvhttpServer doesn't inherit from TServer, and doesn't
      // provide a stop method.
      TEvhttpServer nonblockingServer(testBufferProcessor, port);
      nonblockingServer.serve();
    } else if (transport_type == "framed") {
      std::shared_ptr nbSocket;
      nbSocket.reset(
          ssl ? new transport::TNonblockingSSLServerSocket(port, sslSocketFactory)
              : new transport::TNonblockingServerSocket(port));
      server.reset(new TNonblockingServer(testProcessor, protocolFactory, nbSocket));
    } else {
      cerr << "server-type nonblocking requires transport of http or framed" << endl;
      exit(1);
    }
  }

  if (server.get() != nullptr) {
    if (protocol_type == "header") {
      // Tell the server to use the same protocol for input / output
      // if using header
      server->setOutputProtocolFactory(std::shared_ptr());
    }

    apache::thrift::concurrency::ThreadFactory factory;
    factory.setDetached(false);
    std::shared_ptr serverThreadRunner(server);
    std::shared_ptr thread
        = factory.newThread(serverThreadRunner);

#ifdef HAVE_SIGNAL_H
    signal(SIGINT, signal_handler);
#endif

    thread->start();
    gMonitor.waitForever();         // wait for a shutdown signal

#ifdef HAVE_SIGNAL_H
    signal(SIGINT, SIG_DFL);
#endif

    server->stop();
    thread->join();
    server.reset();
  }

  cout << "done." << endl;
  return 0;
}
thrift-0.19.0/test/cpp/src/StressTestNonBlocking.cpp0000644000000000000000000003702114303740367022414 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "Service.h"

#include 
#include 
#include 
#include 
#include 
#if _WIN32
#include 
#endif

using namespace std;

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using namespace apache::thrift::concurrency;

using namespace test::stress;

struct eqstr {
  bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; }
};

struct ltstr {
  bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
};

// typedef hash_map, eqstr> count_map;
typedef map count_map;

class Server : public ServiceIf {
public:
  Server() = default;

  void count(const char* method) {
    Guard m(lock_);
    int ct = counts_[method];
    counts_[method] = ++ct;
  }

  void echoVoid() override {
    count("echoVoid");
    // Sleep to simulate work
    THRIFT_SLEEP_USEC(1);
    return;
  }

  count_map getCount() {
    Guard m(lock_);
    return counts_;
  }

  int8_t echoByte(const int8_t arg) override { return arg; }
  int32_t echoI32(const int32_t arg) override { return arg; }
  int64_t echoI64(const int64_t arg) override { return arg; }
  void echoString(string& out, const string& arg) override {
    if (arg != "hello") {
      T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str());
    }
    out = arg;
  }
  void echoList(vector& out, const vector& arg) override { out = arg; }
  void echoSet(set& out, const set& arg) override { out = arg; }
  void echoMap(map& out, const map& arg) override { out = arg; }

private:
  count_map counts_;
  Mutex lock_;
};

class ClientThread : public Runnable {
public:
  ClientThread(std::shared_ptr transport,
               std::shared_ptr client,
               Monitor& monitor,
               size_t& workerCount,
               size_t loopCount,
               TType loopType)
    : _transport(transport),
      _client(client),
      _monitor(monitor),
      _workerCount(workerCount),
      _loopCount(loopCount),
      _loopType(loopType) {}

  void run() override {

    // Wait for all worker threads to start

    {
      Synchronized s(_monitor);
      while (_workerCount == 0) {
        _monitor.wait();
      }
    }

    _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();

    _transport->open();

    switch (_loopType) {
    case T_VOID:
      loopEchoVoid();
      break;
    case T_BYTE:
      loopEchoByte();
      break;
    case T_I32:
      loopEchoI32();
      break;
    case T_I64:
      loopEchoI64();
      break;
    case T_STRING:
      loopEchoString();
      break;
    default:
      cerr << "Unexpected loop type" << _loopType << endl;
      break;
    }

    _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();

    _transport->close();

    _done = true;

    {
      Synchronized s(_monitor);

      _workerCount--;

      if (_workerCount == 0) {

        _monitor.notify();
      }
    }
  }

  void loopEchoVoid() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      _client->echoVoid();
    }
  }

  void loopEchoByte() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      int8_t arg = 1;
      int8_t result;
      result = _client->echoByte(arg);
      (void)result;
      assert(result == arg);
    }
  }

  void loopEchoI32() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      int32_t arg = 1;
      int32_t result;
      result = _client->echoI32(arg);
      (void)result;
      assert(result == arg);
    }
  }

  void loopEchoI64() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      int64_t arg = 1;
      int64_t result;
      result = _client->echoI64(arg);
      (void)result;
      assert(result == arg);
    }
  }

  void loopEchoString() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      string arg = "hello";
      string result;
      _client->echoString(result, arg);
      assert(result == arg);
    }
  }

  std::shared_ptr _transport;
  std::shared_ptr _client;
  Monitor& _monitor;
  size_t& _workerCount;
  size_t _loopCount;
  TType _loopType;
  int64_t _startTime;
  int64_t _endTime;
  bool _done;
  Monitor _sleep;
};

int main(int argc, char** argv) {
#if _WIN32
  transport::TWinsockSingleton::create();
#endif

  int port = 9091;
  string serverType = "simple";
  string protocolType = "binary";
  uint32_t workerCount = 4;
  uint32_t clientCount = 20;
  uint32_t loopCount = 1000;
  TType loopType = T_VOID;
  string callName = "echoVoid";
  bool runServer = true;
  bool logRequests = false;
  string requestLogPath = "./requestlog.tlog";
  bool replayRequests = false;

  ostringstream usage;

  usage << argv[0] << " [--port=] [--server] [--server-type=] "
                      "[--protocol-type=] [--workers=] "
                      "[--clients=] [--loop=]" << endl
        << "\tclients        Number of client threads to create - 0 implies no clients, i.e. "
           "server only.  Default is " << clientCount << endl
        << "\thelp           Prints this help text." << endl
        << "\tcall           Service method to call.  Default is " << callName << endl
        << "\tloop           The number of remote thrift calls each client makes.  Default is "
        << loopCount << endl << "\tport           The port the server and clients should bind to "
                                "for thrift network connections.  Default is " << port << endl
        << "\tserver         Run the Thrift server in this process.  Default is " << runServer
        << endl << "\tserver-type    Type of server, \"simple\" or \"thread-pool\".  Default is "
        << serverType << endl
        << "\tprotocol-type  Type of protocol, \"binary\", \"ascii\", or \"xml\".  Default is "
        << protocolType << endl
        << "\tlog-request    Log all request to ./requestlog.tlog. Default is " << logRequests
        << endl << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is "
        << replayRequests << endl << "\tworkers        Number of thread pools workers.  Only valid "
                                     "for thread-pool server type.  Default is " << workerCount
        << endl;

  map args;

  for (int ix = 1; ix < argc; ix++) {

    string arg(argv[ix]);

    if (arg.compare(0, 2, "--") == 0) {

      size_t end = arg.find_first_of("=", 2);

      string key = string(arg, 2, end - 2);

      if (end != string::npos) {
        args[key] = string(arg, end + 1);
      } else {
        args[key] = "true";
      }
    } else {
      throw invalid_argument("Unexcepted command line token: " + arg);
    }
  }

  try {

    if (!args["clients"].empty()) {
      clientCount = atoi(args["clients"].c_str());
    }

    if (!args["help"].empty()) {
      cerr << usage.str();
      return 0;
    }

    if (!args["loop"].empty()) {
      loopCount = atoi(args["loop"].c_str());
    }

    if (!args["call"].empty()) {
      callName = args["call"];
    }

    if (!args["port"].empty()) {
      port = atoi(args["port"].c_str());
    }

    if (!args["server"].empty()) {
      runServer = args["server"] == "true";
    }

    if (!args["log-request"].empty()) {
      logRequests = args["log-request"] == "true";
    }

    if (!args["replay-request"].empty()) {
      replayRequests = args["replay-request"] == "true";
    }

    if (!args["server-type"].empty()) {
      serverType = args["server-type"];
    }

    if (!args["workers"].empty()) {
      workerCount = atoi(args["workers"].c_str());
    }

  } catch (std::exception& e) {
    cerr << e.what() << endl;
    cerr << usage.str();
  }

  std::shared_ptr threadFactory
      = std::shared_ptr(new ThreadFactory());

  // Dispatcher
  std::shared_ptr serviceHandler(new Server());

  if (replayRequests) {
    std::shared_ptr serviceHandler(new Server());
    std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler));

    // Transports
    std::shared_ptr fileTransport(new TFileTransport(requestLogPath));
    fileTransport->setChunkSize(2 * 1024 * 1024);
    fileTransport->setMaxEventSize(1024 * 16);
    fileTransport->seekToEnd();

    // Protocol Factory
    std::shared_ptr protocolFactory(new TBinaryProtocolFactory());

    TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);

    fileProcessor.process(0, true);
    exit(0);
  }

  if (runServer) {

    std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler));

    // Protocol Factory
    std::shared_ptr protocolFactory(new TBinaryProtocolFactory());

    // Transport Factory
    std::shared_ptr transportFactory;

    if (logRequests) {
      // initialize the log file
      std::shared_ptr fileTransport(new TFileTransport(requestLogPath));
      fileTransport->setChunkSize(2 * 1024 * 1024);
      fileTransport->setMaxEventSize(1024 * 16);

      transportFactory
          = std::shared_ptr(new TPipedTransportFactory(fileTransport));
    }

    std::shared_ptr serverThread;
    std::shared_ptr serverThread2;
    std::shared_ptr nbSocket1;
    std::shared_ptr nbSocket2;

    if (serverType == "simple") {

      nbSocket1.reset(new transport::TNonblockingServerSocket(port));
      serverThread = threadFactory->newThread(std::shared_ptr(
          new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1)));
      nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1));
      serverThread2 = threadFactory->newThread(std::shared_ptr(
          new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2)));

    } else if (serverType == "thread-pool") {

      std::shared_ptr threadManager
          = ThreadManager::newSimpleThreadManager(workerCount);

      threadManager->threadFactory(threadFactory);
      threadManager->start();
      nbSocket1.reset(new transport::TNonblockingServerSocket(port));
      serverThread = threadFactory->newThread(std::shared_ptr(
          new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1, threadManager)));
      nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1));
      serverThread2 = threadFactory->newThread(std::shared_ptr(
          new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2, threadManager)));
    }

    cerr << "Starting the server on port " << port << " and " << (port + 1) << endl;
    serverThread->start();
    serverThread2->start();

    // If we aren't running clients, just wait forever for external clients

    if (clientCount == 0) {
      serverThread->join();
      serverThread2->join();
    }
  }
  THRIFT_SLEEP_SEC(1);

  if (clientCount > 0) {

    Monitor monitor;

    size_t threadCount = 0;

    set > clientThreads;

    if (callName == "echoVoid") {
      loopType = T_VOID;
    } else if (callName == "echoByte") {
      loopType = T_BYTE;
    } else if (callName == "echoI32") {
      loopType = T_I32;
    } else if (callName == "echoI64") {
      loopType = T_I64;
    } else if (callName == "echoString") {
      loopType = T_STRING;
    } else {
      throw invalid_argument("Unknown service call " + callName);
    }

    for (uint32_t ix = 0; ix < clientCount; ix++) {

      std::shared_ptr socket(new TSocket("127.0.0.1", port + (ix % 2)));
      std::shared_ptr framedSocket(new TFramedTransport(socket));
      std::shared_ptr protocol(new TBinaryProtocol(framedSocket));
      std::shared_ptr serviceClient(new ServiceClient(protocol));

      clientThreads.insert(threadFactory->newThread(std::shared_ptr(
          new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType))));
    }

    for (auto thread = clientThreads.begin();
         thread != clientThreads.end();
         thread++) {
      (*thread)->start();
    }

    int64_t time00;
    int64_t time01;

    {
      Synchronized s(monitor);
      threadCount = clientCount;

      cerr << "Launch " << clientCount << " client threads" << endl;

      time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();

      monitor.notifyAll();

      while (threadCount > 0) {
        monitor.wait();
      }

      time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();
    }

    int64_t firstTime = 9223372036854775807LL;
    int64_t lastTime = 0;

    double averageTime = 0;
    int64_t minTime = 9223372036854775807LL;
    int64_t maxTime = 0;

    for (auto ix = clientThreads.begin();
         ix != clientThreads.end();
         ix++) {

      std::shared_ptr client
          = std::dynamic_pointer_cast((*ix)->runnable());

      int64_t delta = client->_endTime - client->_startTime;

      assert(delta > 0);

      if (client->_startTime < firstTime) {
        firstTime = client->_startTime;
      }

      if (client->_endTime > lastTime) {
        lastTime = client->_endTime;
      }

      if (delta < minTime) {
        minTime = delta;
      }

      if (delta > maxTime) {
        maxTime = delta;
      }

      averageTime += delta;
    }

    averageTime /= clientCount;

    cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount
         << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl;

    count_map count = serviceHandler->getCount();
    count_map::iterator iter;
    for (iter = count.begin(); iter != count.end(); ++iter) {
      printf("%s => %d\n", iter->first, iter->second);
    }
    cerr << "done." << endl;
  }

  return 0;
}
thrift-0.19.0/test/cpp/src/SpecificNameTest.cpp0000644000000000000000000000200714303740367021327 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

int main(int argc, char** argv) {
  
  //Empty in main function, 
  //because we just want to test  
  //whether the generated source code
  //(IDL file contains struct named as
  //'a' or 'b') can be compiled.

  return 0;
}
thrift-0.19.0/test/cpp/src/StressTest.cpp0000644000000000000000000004266114303740367020276 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "Service.h"
#include 
#include 
#include 
#include 
#include 
#if _WIN32
#include 
#endif

using namespace std;

using namespace apache::thrift;
using namespace apache::thrift::async;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::thrift::server;
using namespace apache::thrift::concurrency;

using namespace test::stress;

struct eqstr {
  bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) == 0; }
};

struct ltstr {
  bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; }
};

// typedef hash_map, eqstr> count_map;
typedef map count_map;

class Server : public ServiceIf {
public:
  Server() = default;

  void count(const char* method) {
    Guard m(lock_);
    int ct = counts_[method];
    counts_[method] = ++ct;
  }

  void echoVoid() override {
    count("echoVoid");
    return;
  }

  count_map getCount() {
    Guard m(lock_);
    return counts_;
  }

  int8_t echoByte(const int8_t arg) override { return arg; }
  int32_t echoI32(const int32_t arg) override { return arg; }
  int64_t echoI64(const int64_t arg) override { return arg; }
  void echoString(string& out, const string& arg) override {
    if (arg != "hello") {
      T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str());
    }
    out = arg;
  }
  void echoList(vector& out, const vector& arg) override { out = arg; }
  void echoSet(set& out, const set& arg) override { out = arg; }
  void echoMap(map& out, const map& arg) override { out = arg; }

private:
  count_map counts_;
  Mutex lock_;
};

enum TransportOpenCloseBehavior {
  OpenAndCloseTransportInThread,
  DontOpenAndCloseTransportInThread
};
class ClientThread : public Runnable {
public:
  ClientThread(std::shared_ptr transport,
               std::shared_ptr client,
               Monitor& monitor,
               size_t& workerCount,
               size_t loopCount,
               TType loopType,
               TransportOpenCloseBehavior behavior)
    : _transport(transport),
      _client(client),
      _monitor(monitor),
      _workerCount(workerCount),
      _loopCount(loopCount),
      _loopType(loopType),
      _behavior(behavior) {}

  void run() override {

    // Wait for all worker threads to start

    {
      Synchronized s(_monitor);
      while (_workerCount == 0) {
        _monitor.wait();
      }
    }

    _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();
    if(_behavior == OpenAndCloseTransportInThread) {
      _transport->open();
    }

    switch (_loopType) {
    case T_VOID:
      loopEchoVoid();
      break;
    case T_BYTE:
      loopEchoByte();
      break;
    case T_I32:
      loopEchoI32();
      break;
    case T_I64:
      loopEchoI64();
      break;
    case T_STRING:
      loopEchoString();
      break;
    default:
      cerr << "Unexpected loop type" << _loopType << endl;
      break;
    }

    _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();

    if(_behavior == OpenAndCloseTransportInThread) {
      _transport->close();
    }

    _done = true;

    {
      Synchronized s(_monitor);

      _workerCount--;

      if (_workerCount == 0) {

        _monitor.notify();
      }
    }
  }

  void loopEchoVoid() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      _client->echoVoid();
    }
  }

  void loopEchoByte() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      int8_t arg = 1;
      int8_t result;
      result = _client->echoByte(arg);
      (void)result;
      assert(result == arg);
    }
  }

  void loopEchoI32() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      int32_t arg = 1;
      int32_t result;
      result = _client->echoI32(arg);
      (void)result;
      assert(result == arg);
    }
  }

  void loopEchoI64() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      int64_t arg = 1;
      int64_t result;
      result = _client->echoI64(arg);
      (void)result;
      assert(result == arg);
    }
  }

  void loopEchoString() {
    for (size_t ix = 0; ix < _loopCount; ix++) {
      string arg = "hello";
      string result;
      _client->echoString(result, arg);
      assert(result == arg);
    }
  }

  std::shared_ptr _transport;
  std::shared_ptr _client;
  Monitor& _monitor;
  size_t& _workerCount;
  size_t _loopCount;
  TType _loopType;
  int64_t _startTime;
  int64_t _endTime;
  bool _done;
  Monitor _sleep;
  TransportOpenCloseBehavior _behavior;
};

class TStartObserver : public apache::thrift::server::TServerEventHandler {
public:
  TStartObserver() : awake_(false) {}
  void preServe() override {
    apache::thrift::concurrency::Synchronized s(m_);
    awake_ = true;
    m_.notifyAll();
  }
  void waitForService() {
    apache::thrift::concurrency::Synchronized s(m_);
    while (!awake_)
      m_.waitForever();
  }

private:
  apache::thrift::concurrency::Monitor m_;
  bool awake_;
};

int main(int argc, char** argv) {
#if _WIN32
  transport::TWinsockSingleton::create();
#endif

  int port = 9091;
  string clientType = "regular";
  string serverType = "thread-pool";
  string protocolType = "binary";
  size_t workerCount = 8;
  size_t clientCount = 4;
  size_t loopCount = 50000;
  TType loopType = T_VOID;
  string callName = "echoVoid";
  bool runServer = true;
  bool logRequests = false;
  string requestLogPath = "./requestlog.tlog";
  bool replayRequests = false;

  ostringstream usage;

  usage << argv[0] << " [--port=] [--server] [--server-type=] "
                      "[--protocol-type=] [--workers=] "
                      "[--clients=] [--loop=] "
                      "[--client-type=]" << endl
        << "\tclients        Number of client threads to create - 0 implies no clients, i.e. "
                            "server only.  Default is " << clientCount << endl
        << "\thelp           Prints this help text." << endl
        << "\tcall           Service method to call.  Default is " << callName << endl
        << "\tloop           The number of remote thrift calls each client makes.  Default is " << loopCount << endl
        << "\tport           The port the server and clients should bind to "
                            "for thrift network connections.  Default is " << port << endl
        << "\tserver         Run the Thrift server in this process.  Default is " << runServer << endl
        << "\tserver-type    Type of server, \"simple\" or \"thread-pool\".  Default is " << serverType << endl
        << "\tprotocol-type  Type of protocol, \"binary\", \"ascii\", or \"xml\".  Default is " << protocolType << endl
        << "\tlog-request    Log all request to ./requestlog.tlog. Default is " << logRequests << endl
        << "\treplay-request Replay requests from log file (./requestlog.tlog) Default is " << replayRequests << endl
        << "\tworkers        Number of thread pools workers.  Only valid "
                            "for thread-pool server type.  Default is " << workerCount << endl
        << "\tclient-type    Type of client, \"regular\" or \"concurrent\".  Default is " << clientType << endl
        << endl;

  map args;

  for (int ix = 1; ix < argc; ix++) {

    string arg(argv[ix]);

    if (arg.compare(0, 2, "--") == 0) {

      size_t end = arg.find_first_of("=", 2);

      string key = string(arg, 2, end - 2);

      if (end != string::npos) {
        args[key] = string(arg, end + 1);
      } else {
        args[key] = "true";
      }
    } else {
      throw invalid_argument("Unexcepted command line token: " + arg);
    }
  }

  try {

    if (!args["clients"].empty()) {
      clientCount = atoi(args["clients"].c_str());
    }

    if (!args["help"].empty()) {
      cerr << usage.str();
      return 0;
    }

    if (!args["loop"].empty()) {
      loopCount = atoi(args["loop"].c_str());
    }

    if (!args["call"].empty()) {
      callName = args["call"];
    }

    if (!args["port"].empty()) {
      port = atoi(args["port"].c_str());
    }

    if (!args["server"].empty()) {
      runServer = args["server"] == "true";
    }

    if (!args["log-request"].empty()) {
      logRequests = args["log-request"] == "true";
    }

    if (!args["replay-request"].empty()) {
      replayRequests = args["replay-request"] == "true";
    }

    if (!args["server-type"].empty()) {
      serverType = args["server-type"];

      if (serverType == "simple") {

      } else if (serverType == "thread-pool") {

      } else if (serverType == "threaded") {

      } else {

        throw invalid_argument("Unknown server type " + serverType);
      }
    }
    if (!args["client-type"].empty()) {
      clientType = args["client-type"];

      if (clientType == "regular") {

      } else if (clientType == "concurrent") {

      } else {

        throw invalid_argument("Unknown client type " + clientType);
      }
    }
    if (!args["workers"].empty()) {
      workerCount = atoi(args["workers"].c_str());
    }

  } catch (std::exception& e) {
    cerr << e.what() << endl;
    cerr << usage.str();
  }

  std::shared_ptr threadFactory
      = std::shared_ptr(new ThreadFactory());

  // Dispatcher
  std::shared_ptr serviceHandler(new Server());

  if (replayRequests) {
    std::shared_ptr serviceHandler(new Server());
    std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler));

    // Transports
    std::shared_ptr fileTransport(new TFileTransport(requestLogPath));
    fileTransport->setChunkSize(2 * 1024 * 1024);
    fileTransport->setMaxEventSize(1024 * 16);
    fileTransport->seekToEnd();

    // Protocol Factory
    std::shared_ptr protocolFactory(new TBinaryProtocolFactory());

    TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport);

    fileProcessor.process(0, true);
    exit(0);
  }

  if (runServer) {

    std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler));

    // Transport
    std::shared_ptr serverSocket(new TServerSocket(port));

    // Transport Factory
    std::shared_ptr transportFactory(new TBufferedTransportFactory());

    // Protocol Factory
    std::shared_ptr protocolFactory(new TBinaryProtocolFactory());

    if (logRequests) {
      // initialize the log file
      std::shared_ptr fileTransport(new TFileTransport(requestLogPath));
      fileTransport->setChunkSize(2 * 1024 * 1024);
      fileTransport->setMaxEventSize(1024 * 16);

      transportFactory
          = std::shared_ptr(new TPipedTransportFactory(fileTransport));
    }

    std::shared_ptr server;

    if (serverType == "simple") {

      server.reset(
          new TSimpleServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));

    } else if (serverType == "threaded") {

      server.reset(
          new TThreadedServer(serviceProcessor, serverSocket, transportFactory, protocolFactory));

    } else if (serverType == "thread-pool") {

      std::shared_ptr threadManager
          = ThreadManager::newSimpleThreadManager(workerCount);

      threadManager->threadFactory(threadFactory);
      threadManager->start();
      server.reset(new TThreadPoolServer(serviceProcessor,
                                         serverSocket,
                                         transportFactory,
                                         protocolFactory,
                                         threadManager));
    }

    std::shared_ptr observer(new TStartObserver);
    server->setServerEventHandler(observer);
    std::shared_ptr serverThread = threadFactory->newThread(server);

    cerr << "Starting the server on port " << port << endl;

    serverThread->start();
    observer->waitForService();

    // If we aren't running clients, just wait forever for external clients
    if (clientCount == 0) {
      serverThread->join();
    }
  }

  if (clientCount > 0) { //FIXME: start here for client type?

    Monitor monitor;

    size_t threadCount = 0;

    set > clientThreads;

    if (callName == "echoVoid") {
      loopType = T_VOID;
    } else if (callName == "echoByte") {
      loopType = T_BYTE;
    } else if (callName == "echoI32") {
      loopType = T_I32;
    } else if (callName == "echoI64") {
      loopType = T_I64;
    } else if (callName == "echoString") {
      loopType = T_STRING;
    } else {
      throw invalid_argument("Unknown service call " + callName);
    }

    if(clientType == "regular") {
      for (size_t ix = 0; ix < clientCount; ix++) {

        std::shared_ptr socket(new TSocket("127.0.0.1", port));
        std::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048));
        std::shared_ptr protocol(new TBinaryProtocol(bufferedSocket));
        std::shared_ptr serviceClient(new ServiceClient(protocol));

        clientThreads.insert(threadFactory->newThread(std::shared_ptr(
            new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, OpenAndCloseTransportInThread))));
      }
    } else if(clientType == "concurrent") {
      std::shared_ptr socket(new TSocket("127.0.0.1", port));
      std::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048));
      std::shared_ptr protocol(new TBinaryProtocol(bufferedSocket));
      auto sync = std::make_shared();
      std::shared_ptr serviceClient(new ServiceConcurrentClient(protocol, sync));
      socket->open();
      for (size_t ix = 0; ix < clientCount; ix++) {
        clientThreads.insert(threadFactory->newThread(std::shared_ptr(
            new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, DontOpenAndCloseTransportInThread))));
      }
    }

    for (auto thread = clientThreads.begin();
         thread != clientThreads.end();
         thread++) {
      (*thread)->start();
    }

    int64_t time00;
    int64_t time01;

    {
      Synchronized s(monitor);
      threadCount = clientCount;

      cerr << "Launch " << clientCount << " " << clientType << " client threads" << endl;

      time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();

      monitor.notifyAll();

      while (threadCount > 0) {
        monitor.wait();
      }

      time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count();
    }

    int64_t firstTime = 9223372036854775807LL;
    int64_t lastTime = 0;

    double averageTime = 0;
    int64_t minTime = 9223372036854775807LL;
    int64_t maxTime = 0;

    for (auto ix = clientThreads.begin();
         ix != clientThreads.end();
         ix++) {

      std::shared_ptr client
          = std::dynamic_pointer_cast((*ix)->runnable());

      int64_t delta = client->_endTime - client->_startTime;

      assert(delta > 0);

      if (client->_startTime < firstTime) {
        firstTime = client->_startTime;
      }

      if (client->_endTime > lastTime) {
        lastTime = client->_endTime;
      }

      if (delta < minTime) {
        minTime = delta;
      }

      if (delta > maxTime) {
        maxTime = delta;
      }

      averageTime += delta;
    }

    averageTime /= clientCount;

    cout << "workers :" << workerCount << ", client : " << clientCount << ", loops : " << loopCount
         << ", rate : " << (clientCount * loopCount * 1000) / ((double)(time01 - time00)) << endl;

    count_map count = serviceHandler->getCount();
    count_map::iterator iter;
    for (iter = count.begin(); iter != count.end(); ++iter) {
      printf("%s => %d\n", iter->first, iter->second);
    }
    cerr << "done." << endl;
  }

  return 0;
}
thrift-0.19.0/test/cpp/src/ThriftTest_extras.cpp0000644000000000000000000000221414303740367021627 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

// Extra functions required for ThriftTest_types to work

#include 
#include "gen-cpp/ThriftTest_types.h"

namespace thrift {
namespace test {

bool Insanity::operator<(thrift::test::Insanity const& other) const {
  using apache::thrift::ThriftDebugString;
  return ThriftDebugString(*this) < ThriftDebugString(other);
}
}
}
thrift-0.19.0/test/cpp/gen-cpp/0000755000000000000000000000000014472652702016202 5ustar00rootroot00000000000000thrift-0.19.0/test/cpp/Makefile.in0000644000000000000000000007767114472652520016736 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am.
# @configure_input@

# Copyright (C) 1994-2017 Free Software Foundation, Inc.

# This Makefile.in 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.

@SET_MAKE@

VPATH = @srcdir@
am__is_gnu_make = { \
  if test -z '$(MAKELEVEL)'; then \
    false; \
  elif test -n '$(MAKE_HOST)'; then \
    true; \
  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
    true; \
  else \
    false; \
  fi; \
}
am__make_running_with_option = \
  case $${target_option-} in \
      ?) ;; \
      *) echo "am__make_running_with_option: internal error: invalid" \
              "target option '$${target_option-}' specified" >&2; \
         exit 1;; \
  esac; \
  has_opt=no; \
  sane_makeflags=$$MAKEFLAGS; \
  if $(am__is_gnu_make); then \
    sane_makeflags=$$MFLAGS; \
  else \
    case $$MAKEFLAGS in \
      *\\[\ \	]*) \
        bs=\\; \
        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    esac; \
  fi; \
  skip_next=no; \
  strip_trailopt () \
  { \
    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
  }; \
  for flg in $$sane_makeflags; do \
    test $$skip_next = yes && { skip_next=no; continue; }; \
    case $$flg in \
      *=*|--*) continue;; \
        -*I) strip_trailopt 'I'; skip_next=yes;; \
      -*I?*) strip_trailopt 'I';; \
        -*O) strip_trailopt 'O'; skip_next=yes;; \
      -*O?*) strip_trailopt 'O';; \
        -*l) strip_trailopt 'l'; skip_next=yes;; \
      -*l?*) strip_trailopt 'l';; \
      -[dEDm]) skip_next=yes;; \
      -[JT]) skip_next=yes;; \
    esac; \
    case $$flg in \
      *$$target_option*) has_opt=yes; break;; \
    esac; \
  done; \
  test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
check_PROGRAMS = TestServer$(EXEEXT) TestClient$(EXEEXT) \
	StressTest$(EXEEXT) StressTestNonBlocking$(EXEEXT)
subdir = test/cpp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \
	$(top_srcdir)/aclocal/ax_boost_base.m4 \
	$(top_srcdir)/aclocal/ax_check_openssl.m4 \
	$(top_srcdir)/aclocal/ax_compare_version.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \
	$(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \
	$(top_srcdir)/aclocal/ax_dmd.m4 \
	$(top_srcdir)/aclocal/ax_javac_and_java.m4 \
	$(top_srcdir)/aclocal/ax_lib_event.m4 \
	$(top_srcdir)/aclocal/ax_lib_zlib.m4 \
	$(top_srcdir)/aclocal/ax_lua.m4 \
	$(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \
	$(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \
	$(top_srcdir)/aclocal/ax_signed_right_shift.m4 \
	$(top_srcdir)/aclocal/ax_thrift_internal.m4 \
	$(top_srcdir)/aclocal/libtool.m4 \
	$(top_srcdir)/aclocal/ltoptions.m4 \
	$(top_srcdir)/aclocal/ltsugar.m4 \
	$(top_srcdir)/aclocal/ltversion.m4 \
	$(top_srcdir)/aclocal/lt~obsolete.m4 \
	$(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
	$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
	$(top_builddir)/lib/cpp/src/thrift/config.h \
	$(top_builddir)/lib/c_glib/src/thrift/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libstresstestgencpp_la_DEPENDENCIES =  \
	$(top_builddir)/lib/cpp/libthrift.la
am__dirstamp = $(am__leading_dot)dirstamp
nodist_libstresstestgencpp_la_OBJECTS = gen-cpp/Service.lo
libstresstestgencpp_la_OBJECTS =  \
	$(nodist_libstresstestgencpp_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 = 
libtestgencpp_la_DEPENDENCIES = $(top_builddir)/lib/cpp/libthrift.la
nodist_libtestgencpp_la_OBJECTS = gen-cpp/SecondService.lo \
	gen-cpp/ThriftTest_constants.lo gen-cpp/ThriftTest_types.lo \
	gen-cpp/ThriftTest.lo src/ThriftTest_extras.lo
libtestgencpp_la_OBJECTS = $(nodist_libtestgencpp_la_OBJECTS)
am_StressTest_OBJECTS = src/StressTest.$(OBJEXT)
StressTest_OBJECTS = $(am_StressTest_OBJECTS)
StressTest_DEPENDENCIES = libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la
am_StressTestNonBlocking_OBJECTS =  \
	src/StressTestNonBlocking.$(OBJEXT)
StressTestNonBlocking_OBJECTS = $(am_StressTestNonBlocking_OBJECTS)
StressTestNonBlocking_DEPENDENCIES = libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthriftnb.la
am_TestClient_OBJECTS = src/TestClient.$(OBJEXT)
TestClient_OBJECTS = $(am_TestClient_OBJECTS)
am__DEPENDENCIES_1 =
TestClient_DEPENDENCIES = libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1)
am_TestServer_OBJECTS = src/TestServer.$(OBJEXT)
TestServer_OBJECTS = $(am_TestServer_OBJECTS)
TestServer_DEPENDENCIES = libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo "  GEN     " $@;
am__v_GEN_1 = 
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 = 
DEFAULT_INCLUDES = 
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
	$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_@AM_V@)
am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
am__v_CXX_0 = @echo "  CXX     " $@;
am__v_CXX_1 = 
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
	$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo "  CXXLD   " $@;
am__v_CXXLD_1 = 
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
	$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
	$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo "  CC      " $@;
am__v_CC_1 = 
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
	$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo "  CCLD    " $@;
am__v_CCLD_1 = 
SOURCES = $(nodist_libstresstestgencpp_la_SOURCES) \
	$(nodist_libtestgencpp_la_SOURCES) $(StressTest_SOURCES) \
	$(StressTestNonBlocking_SOURCES) $(TestClient_SOURCES) \
	$(TestServer_SOURCES)
DIST_SOURCES = $(StressTest_SOURCES) $(StressTestNonBlocking_SOURCES) \
	$(TestClient_SOURCES) $(TestServer_SOURCES)
am__can_run_installinfo = \
  case $$AM_UPDATE_INFO_DIR in \
    n|no|NO) false;; \
    *) (install-info --version) >/dev/null 2>&1;; \
  esac
am__extra_recursive_targets = style-recursive
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates.  Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
  BEGIN { nonempty = 0; } \
  { items[$$0] = 1; nonempty = 1; } \
  END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique.  This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
  list='$(am__tagged_files)'; \
  unique=`for i in $$list; do \
    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
  done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ANT = @ANT@
ANT_FLAGS = @ANT_FLAGS@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BISON = @BISON@
BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@
BOOST_CPPFLAGS = @BOOST_CPPFLAGS@
BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@
BOOST_LDFLAGS = @BOOST_LDFLAGS@
BOOST_LIB_DIR = @BOOST_LIB_DIR@
BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@
BOOST_TEST_LDADD = @BOOST_TEST_LDADD@
BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@
BUNDLER = @BUNDLER@
CARGO = @CARGO@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CLASSPATH = @CLASSPATH@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPSTYLE_CMD = @CPPSTYLE_CMD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DART = @DART@
DARTPUB = @DARTPUB@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DMD = @DMD@
DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@
DMD_OF_DIRSEP = @DMD_OF_DIRSEP@
DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@
DOTNETCORE = @DOTNETCORE@
DOTNETCORE_VERSION = @DOTNETCORE_VERSION@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@
D_IMPORT_PREFIX = @D_IMPORT_PREFIX@
D_LIB_NAME = @D_LIB_NAME@
D_SSL_LIB_NAME = @D_SSL_LIB_NAME@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_COVERAGE = @ENABLE_COVERAGE@
ERL = @ERL@
ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@
ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@
ERLANG_LIB_DIR = @ERLANG_LIB_DIR@
ERLC = @ERLC@
ERLCFLAGS = @ERLCFLAGS@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GCOV_CFLAGS = @GCOV_CFLAGS@
GCOV_CXXFLAGS = @GCOV_CXXFLAGS@
GCOV_LDFLAGS = @GCOV_LDFLAGS@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GO = @GO@
GOBJECT_CFLAGS = @GOBJECT_CFLAGS@
GOBJECT_LIBS = @GOBJECT_LIBS@
GRADLE = @GRADLE@
GRADLE_OPTS = @GRADLE_OPTS@
GREP = @GREP@
GSETTINGS = @GSETTINGS@
HAVE_CXX11 = @HAVE_CXX11@
HAXE = @HAXE@
HAXE_VERSION = @HAXE_VERSION@
INSTALL = @INSTALL@
INSTALLDIRS = @INSTALLDIRS@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
JAVA_PREFIX = @JAVA_PREFIX@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@
LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@
LIBEVENT_LIBS = @LIBEVENT_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
LUA = @LUA@
LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@
LUA_INCLUDE = @LUA_INCLUDE@
LUA_LIB = @LUA_LIB@
LUA_PLATFORM = @LUA_PLATFORM@
LUA_PREFIX = @LUA_PREFIX@
LUA_SHORT_VERSION = @LUA_SHORT_VERSION@
LUA_VERSION = @LUA_VERSION@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MAYBE_CL = @MAYBE_CL@
MAYBE_CPP = @MAYBE_CPP@
MAYBE_C_GLIB = @MAYBE_C_GLIB@
MAYBE_D = @MAYBE_D@
MAYBE_DART = @MAYBE_DART@
MAYBE_ERLANG = @MAYBE_ERLANG@
MAYBE_GO = @MAYBE_GO@
MAYBE_JAVA = @MAYBE_JAVA@
MAYBE_KOTLIN = @MAYBE_KOTLIN@
MAYBE_LUA = @MAYBE_LUA@
MAYBE_NETSTD = @MAYBE_NETSTD@
MAYBE_NODEJS = @MAYBE_NODEJS@
MAYBE_NODETS = @MAYBE_NODETS@
MAYBE_PERL = @MAYBE_PERL@
MAYBE_PHP = @MAYBE_PHP@
MAYBE_PY3 = @MAYBE_PY3@
MAYBE_PYTHON = @MAYBE_PYTHON@
MAYBE_RS = @MAYBE_RS@
MAYBE_RUBY = @MAYBE_RUBY@
MAYBE_SWIFT = @MAYBE_SWIFT@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NODEJS = @NODEJS@
NODETS = @NODETS@
NPM = @NPM@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
OPENSSL_LIBS = @OPENSSL_LIBS@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PERL_PREFIX = @PERL_PREFIX@
PHP = @PHP@
PHP_CONFIG = @PHP_CONFIG@
PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@
PHP_PREFIX = @PHP_PREFIX@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PYTHON = @PYTHON@
PYTHON3 = @PYTHON3@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
PY_PREFIX = @PY_PREFIX@
QT5_CFLAGS = @QT5_CFLAGS@
QT5_LIBS = @QT5_LIBS@
QT5_MOC = @QT5_MOC@
RANLIB = @RANLIB@
REBAR = @REBAR@
RUBY = @RUBY@
RUBY_PREFIX = @RUBY_PREFIX@
RUSTC = @RUSTC@
SBCL = @SBCL@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
SWIFT = @SWIFT@
THRIFT = @THRIFT@
TRIAL = @TRIAL@
VERSION = @VERSION@
YACC = @YACC@
YFLAGS = @YFLAGS@
ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@
ZLIB_LDFLAGS = @ZLIB_LDFLAGS@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
golang_version = @golang_version@
have_prog_bison = @have_prog_bison@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
luadir = @luadir@
luaexecdir = @luaexecdir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgluadir = @pkgluadir@
pkgluaexecdir = @pkgluaexecdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
rustc_version = @rustc_version@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc
BUILT_SOURCES = gen-cpp/ThriftTest.cpp \
                gen-cpp/ThriftTest_types.cpp \
                gen-cpp/ThriftTest_constants.cpp \
                gen-cpp/SecondService.cpp \
                gen-cpp/Service.cpp

noinst_LTLIBRARIES = libtestgencpp.la libstresstestgencpp.la
nodist_libtestgencpp_la_SOURCES = \
	gen-cpp/SecondService.cpp \
	gen-cpp/SecondService.h \
	gen-cpp/SecondService.tcc \
	gen-cpp/ThriftTest_constants.cpp \
	gen-cpp/ThriftTest_constants.h \
	gen-cpp/ThriftTest_types.cpp \
	gen-cpp/ThriftTest_types.h \
	gen-cpp/ThriftTest_types.tcc \
	gen-cpp/ThriftTest.cpp \
	gen-cpp/ThriftTest.h \
	gen-cpp/ThriftTest.tcc \
	src/ThriftTest_extras.cpp

libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
nodist_libstresstestgencpp_la_SOURCES = \
	gen-cpp/StressTest_types.h \
	gen-cpp/Service.cpp \
	gen-cpp/Service.h

libstresstestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la

# we currently do not run the testsuite, stop c++ server issue
# TESTS = \
#	$(check_PROGRAMS)
TestServer_SOURCES = \
	src/TestServer.cpp

TestServer_LDADD = \
	libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)

TestClient_SOURCES = \
	src/TestClient.cpp

TestClient_LDADD = \
	libtestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la \
	$(top_builddir)/lib/cpp/libthriftz.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)

StressTest_SOURCES = \
	src/StressTest.cpp

StressTest_LDADD = \
	libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthrift.la

StressTestNonBlocking_SOURCES = \
	src/StressTestNonBlocking.cpp

StressTestNonBlocking_LDADD = \
	libstresstestgencpp.la \
	$(top_builddir)/lib/cpp/libthriftnb.la \
	-levent

AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I.
AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS)
EXTRA_DIST = \
	src/TestClient.cpp \
	src/TestServer.cpp \
	src/StressTest.cpp \
	src/StressTestNonBlocking.cpp

all: $(BUILT_SOURCES)
	$(MAKE) $(AM_MAKEFLAGS) all-am

.SUFFIXES:
.SUFFIXES: .cpp .lo .o .obj
$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
	@for dep in $?; do \
	  case '$(am__configure_deps)' in \
	    *$$dep*) \
	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
	        && { if test -f $@; then exit 0; else break; fi; }; \
	      exit 1;; \
	  esac; \
	done; \
	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign test/cpp/Makefile'; \
	$(am__cd) $(top_srcdir) && \
	  $(AUTOMAKE) --foreign test/cpp/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
	@case '$?' in \
	  *config.status*) \
	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
	  *) \
	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
	esac;

$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

$(top_srcdir)/configure:  $(am__configure_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):

clean-noinstLTLIBRARIES:
	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
	@list='$(noinst_LTLIBRARIES)'; \
	locs=`for p in $$list; do echo $$p; done | \
	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
	      sort -u`; \
	test -z "$$locs" || { \
	  echo rm -f $${locs}; \
	  rm -f $${locs}; \
	}
gen-cpp/$(am__dirstamp):
	@$(MKDIR_P) gen-cpp
	@: > gen-cpp/$(am__dirstamp)
gen-cpp/$(DEPDIR)/$(am__dirstamp):
	@$(MKDIR_P) gen-cpp/$(DEPDIR)
	@: > gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/Service.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)

libstresstestgencpp.la: $(libstresstestgencpp_la_OBJECTS) $(libstresstestgencpp_la_DEPENDENCIES) $(EXTRA_libstresstestgencpp_la_DEPENDENCIES) 
	$(AM_V_CXXLD)$(CXXLINK)  $(libstresstestgencpp_la_OBJECTS) $(libstresstestgencpp_la_LIBADD) $(LIBS)
gen-cpp/SecondService.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/ThriftTest_constants.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/ThriftTest_types.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
gen-cpp/ThriftTest.lo: gen-cpp/$(am__dirstamp) \
	gen-cpp/$(DEPDIR)/$(am__dirstamp)
src/$(am__dirstamp):
	@$(MKDIR_P) src
	@: > src/$(am__dirstamp)
src/$(DEPDIR)/$(am__dirstamp):
	@$(MKDIR_P) src/$(DEPDIR)
	@: > src/$(DEPDIR)/$(am__dirstamp)
src/ThriftTest_extras.lo: src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

libtestgencpp.la: $(libtestgencpp_la_OBJECTS) $(libtestgencpp_la_DEPENDENCIES) $(EXTRA_libtestgencpp_la_DEPENDENCIES) 
	$(AM_V_CXXLD)$(CXXLINK)  $(libtestgencpp_la_OBJECTS) $(libtestgencpp_la_LIBADD) $(LIBS)

clean-checkPROGRAMS:
	@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
	echo " rm -f" $$list; \
	rm -f $$list || exit $$?; \
	test -n "$(EXEEXT)" || exit 0; \
	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
	echo " rm -f" $$list; \
	rm -f $$list
src/StressTest.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

StressTest$(EXEEXT): $(StressTest_OBJECTS) $(StressTest_DEPENDENCIES) $(EXTRA_StressTest_DEPENDENCIES) 
	@rm -f StressTest$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(StressTest_OBJECTS) $(StressTest_LDADD) $(LIBS)
src/StressTestNonBlocking.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

StressTestNonBlocking$(EXEEXT): $(StressTestNonBlocking_OBJECTS) $(StressTestNonBlocking_DEPENDENCIES) $(EXTRA_StressTestNonBlocking_DEPENDENCIES) 
	@rm -f StressTestNonBlocking$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(StressTestNonBlocking_OBJECTS) $(StressTestNonBlocking_LDADD) $(LIBS)
src/TestClient.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

TestClient$(EXEEXT): $(TestClient_OBJECTS) $(TestClient_DEPENDENCIES) $(EXTRA_TestClient_DEPENDENCIES) 
	@rm -f TestClient$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(TestClient_OBJECTS) $(TestClient_LDADD) $(LIBS)
src/TestServer.$(OBJEXT): src/$(am__dirstamp) \
	src/$(DEPDIR)/$(am__dirstamp)

TestServer$(EXEEXT): $(TestServer_OBJECTS) $(TestServer_DEPENDENCIES) $(EXTRA_TestServer_DEPENDENCIES) 
	@rm -f TestServer$(EXEEXT)
	$(AM_V_CXXLD)$(CXXLINK) $(TestServer_OBJECTS) $(TestServer_LDADD) $(LIBS)

mostlyclean-compile:
	-rm -f *.$(OBJEXT)
	-rm -f gen-cpp/*.$(OBJEXT)
	-rm -f gen-cpp/*.lo
	-rm -f src/*.$(OBJEXT)
	-rm -f src/*.lo

distclean-compile:
	-rm -f *.tab.c

@AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/SecondService.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/Service.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ThriftTest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ThriftTest_constants.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ThriftTest_types.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/StressTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/StressTestNonBlocking.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/TestClient.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/TestServer.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/ThriftTest_extras.Plo@am__quote@

.cpp.o:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<

.cpp.obj:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
@am__fastdepCXX_TRUE@	$(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`

.cpp.lo:
@am__fastdepCXX_TRUE@	$(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
@am__fastdepCXX_TRUE@	$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
@am__fastdepCXX_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<

mostlyclean-libtool:
	-rm -f *.lo

clean-libtool:
	-rm -rf .libs _libs
	-rm -rf gen-cpp/.libs gen-cpp/_libs
	-rm -rf src/.libs src/_libs
style-local: 

ID: $(am__tagged_files)
	$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags

tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	set x; \
	here=`pwd`; \
	$(am__define_uniq_tagged_files); \
	shift; \
	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
	  test -n "$$unique" || unique=$$empty_fix; \
	  if test $$# -gt 0; then \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      "$$@" $$unique; \
	  else \
	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
	      $$unique; \
	  fi; \
	fi
ctags: ctags-am

CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
	$(am__define_uniq_tagged_files); \
	test -z "$(CTAGS_ARGS)$$unique" \
	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
	     $$unique

GTAGS:
	here=`$(am__cd) $(top_builddir) && pwd` \
	  && $(am__cd) $(top_srcdir) \
	  && gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am

cscopelist-am: $(am__tagged_files)
	list='$(am__tagged_files)'; \
	case "$(srcdir)" in \
	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
	  *) sdir=$(subdir)/$(srcdir) ;; \
	esac; \
	for i in $$list; do \
	  if test -f "$$i"; then \
	    echo "$(subdir)/$$i"; \
	  else \
	    echo "$$sdir/$$i"; \
	  fi; \
	done >> $(top_builddir)/cscope.files

distclean-tags:
	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags

distdir: $(DISTFILES)
	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
	list='$(DISTFILES)'; \
	  dist_files=`for file in $$list; do echo $$file; done | \
	  sed -e "s|^$$srcdirstrip/||;t" \
	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
	case $$dist_files in \
	  */*) $(MKDIR_P) `echo "$$dist_files" | \
			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
			   sort -u` ;; \
	esac; \
	for file in $$dist_files; do \
	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
	  if test -d $$d/$$file; then \
	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
	    if test -d "$(distdir)/$$file"; then \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
	    fi; \
	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
	  else \
	    test -f "$(distdir)/$$file" \
	    || cp -p $$d/$$file "$(distdir)/$$file" \
	    || exit 1; \
	  fi; \
	done
check-am: all-am
	$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
check: $(BUILT_SOURCES)
	$(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: $(BUILT_SOURCES)
	$(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am

install-am: all-am
	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am

installcheck: installcheck-am
install-strip:
	if test -z '$(STRIP)'; then \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	      install; \
	else \
	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
	fi
mostlyclean-generic:

clean-generic:

distclean-generic:
	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
	-rm -f gen-cpp/$(DEPDIR)/$(am__dirstamp)
	-rm -f gen-cpp/$(am__dirstamp)
	-rm -f src/$(DEPDIR)/$(am__dirstamp)
	-rm -f src/$(am__dirstamp)

maintainer-clean-generic:
	@echo "This command is intended for maintainers to use"
	@echo "it deletes files that may require special tools to rebuild."
	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am

clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \
	clean-noinstLTLIBRARIES mostlyclean-am

distclean: distclean-am
	-rm -rf gen-cpp/$(DEPDIR) src/$(DEPDIR)
	-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
	distclean-tags

dvi: dvi-am

dvi-am:

html: html-am

html-am:

info: info-am

info-am:

install-data-am:

install-dvi: install-dvi-am

install-dvi-am:

install-exec-am:

install-html: install-html-am

install-html-am:

install-info: install-info-am

install-info-am:

install-man:

install-pdf: install-pdf-am

install-pdf-am:

install-ps: install-ps-am

install-ps-am:

installcheck-am:

maintainer-clean: maintainer-clean-am
	-rm -rf gen-cpp/$(DEPDIR) src/$(DEPDIR)
	-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic

mostlyclean: mostlyclean-am

mostlyclean-am: mostlyclean-compile mostlyclean-generic \
	mostlyclean-libtool

pdf: pdf-am

pdf-am:

ps: ps-am

ps-am:

style: style-am

style-am: style-local

uninstall-am:

.MAKE: all check check-am install install-am install-strip

.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
	clean-checkPROGRAMS clean-generic clean-libtool clean-local \
	clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
	distclean-compile distclean-generic distclean-libtool \
	distclean-tags distdir dvi dvi-am html html-am info info-am \
	install install-am install-data install-data-am install-dvi \
	install-dvi-am install-exec install-exec-am install-html \
	install-html-am install-info install-info-am install-man \
	install-pdf install-pdf-am install-ps install-ps-am \
	install-strip installcheck installcheck-am installdirs \
	maintainer-clean maintainer-clean-generic mostlyclean \
	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
	pdf pdf-am ps ps-am style-am style-local tags tags-am \
	uninstall uninstall-am

.PRECIOUS: Makefile


precross: TestServer TestClient
#
# Common thrift code generation rules
#
gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/SecondService.tcc: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT)
	$(THRIFT) --gen cpp:templates,cob_style -r $<

gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT)
	$(THRIFT) --gen cpp $<

gen-cpp/SpecificNameTest_types.cpp gen-cpp/EchoService.cpp: $(top_srcdir)/test/SpecificName.thrift $(THRIFT)
	$(THRIFT) --gen cpp $<

clean-local:
	$(RM) -r gen-cpp/

style-local:
	$(CPPSTYLE_CMD)

# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
thrift-0.19.0/test/UnsafeTypes.thrift0000644000000000000000000000155314303740367017561 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

namespace java thrift.test

struct UnsafeBytes {
  1: binary bytes;
}
thrift-0.19.0/test/Service.thrift0000644000000000000000000000157614303740367016720 0ustar00rootroot00000000000000/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

include "Types.thrift"

service Service {
  Types.Type1 testEpisode(1:Types.Type1 arg)
}
thrift-0.19.0/missing0000755000000000000000000001533014472652514014512 0ustar00rootroot00000000000000#! /bin/sh
# Common wrapper for a few potentially missing GNU programs.

scriptversion=2013-10-28.13; # UTC

# Copyright (C) 1996-2014 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=http://www.perl.org/
flex_URL=http://flex.sourceforge.net/
gnu_software_URL=http://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 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:
thrift-0.19.0/.eslintignore0000644000000000000000000000031614303740366015610 0ustar00rootroot00000000000000# TODO: Use eslint on js lib and generated code

# Ignore lib/js for now, which uses jshint currently
lib/js/*
# Ignore all generated code for now
**/gen-*

# Don't lint nested node_modules
**/node_modules
thrift-0.19.0/config.h0000644000000000000000000003275414472652610014537 0ustar00rootroot00000000000000/* config.h.  Generated from config.hin by configure.  */
/* config.hin.  Generated from configure.ac by autoheader.  */


#ifndef CONFIG_H
#define CONFIG_H


/* Define if the AI_ADDRCONFIG symbol is unavailable */
/* #undef AI_ADDRCONFIG */

/* Possible value for SIGNED_RIGHT_SHIFT_IS */
#define ARITHMETIC_RIGHT_SHIFT 1

/* Defines automake version */
#define AUTOMAKE_VERSION 1.15.1

/* Use *.h extension for parser header file */
/* #undef BISON_USE_PARSER_H_EXTENSION */

/* Defines bison version */
#define BISON_VERSION 3.0.4

/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
   systems. This function is required for `alloca.c' support on those systems.
   */
/* #undef CRAY_STACKSEG_END */

/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */

/* Define to 1 if you have the `alarm' function. */
#define HAVE_ALARM 1

/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1

/* Define to 1 if you have  and it should be used (not on Ultrix).
   */
#define HAVE_ALLOCA_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_ARPA_INET_H 1

/* define if the Boost library is available */
#define HAVE_BOOST /**/

/* Define to 1 if you have the `bzero' function. */
#define HAVE_BZERO 1

/* Define to 1 if you have the `clock_gettime' function. */
#define HAVE_CLOCK_GETTIME 1

/* define if the compiler supports basic C++11 syntax */
#define HAVE_CXX11 1

/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
   don't. */
#define HAVE_DECL_STRERROR_R 1

/* Define to 1 if you have the  header file. */
#define HAVE_DLFCN_H 1

/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
/* #undef HAVE_DOPRNT */

/* Define to 1 if you have the  header file. */
#define HAVE_FCNTL_H 1

/* Define to 1 if you have the `fork' function. */
#define HAVE_FORK 1

/* Define to 1 if you have the `ftruncate' function. */
#define HAVE_FTRUNCATE 1

/* Define to 1 if you have the `gethostbyname' function. */
#define HAVE_GETHOSTBYNAME 1

/* Define to 1 if you have the `gethostbyname_r' function. */
#define HAVE_GETHOSTBYNAME_R 1

/* Define to 1 if you have the `gettimeofday' function. */
#define HAVE_GETTIMEOFDAY 1

/* Define to 1 if you have the `inet_ntoa' function. */
#define HAVE_INET_NTOA 1

/* Define to 1 if you have the  header file. */
#define HAVE_INTTYPES_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_LAUXLIB_H 1

/* define if libevent is available */
#define HAVE_LIBEVENT /**/

/* Define to 1 if you have the  header file. */
#define HAVE_LIBINTL_H 1

/* Define to 1 if you have the `pthread' library (-lpthread). */
#define HAVE_LIBPTHREAD 1

/* Define to 1 if you have the `rt' library (-lrt). */
#define HAVE_LIBRT 1

/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */

/* Define to 1 if you have the  header file. */
#define HAVE_LIMITS_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_LUACONF_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_LUALIB_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_LUA_H 1

/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
   to 0 otherwise. */
#define HAVE_MALLOC 1

/* Define to 1 if you have the  header file. */
#define HAVE_MALLOC_H 1

/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1

/* Define to 1 if you have the  header file. */
#define HAVE_MEMORY_H 1

/* Define to 1 if you have the `memset' function. */
#define HAVE_MEMSET 1

/* Define to 1 if you have the `mkdir' function. */
#define HAVE_MKDIR 1

/* Define to 1 if you have the  header file. */
#define HAVE_NETDB_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_NETINET_IN_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_OPENSSL_RAND_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_OPENSSL_SSL_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_OPENSSL_X509V3_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_POLL_H 1

/* Define to 1 if you have the `pow' function. */
#define HAVE_POW 1

/* Define to 1 if you have the  header file. */
#define HAVE_PTHREAD_H 1

/* Define to 1 if the system has the type `ptrdiff_t'. */
#define HAVE_PTRDIFF_T 1

/* Define to 1 if your system has a GNU libc compatible `realloc' function,
   and to 0 otherwise. */
#define HAVE_REALLOC 1

/* Define to 1 if you have the `realpath' function. */
#define HAVE_REALPATH 1

/* Define to 1 if you have the `sched_get_priority_max' function. */
#define HAVE_SCHED_GET_PRIORITY_MAX 1

/* Define to 1 if you have the `sched_get_priority_min' function. */
#define HAVE_SCHED_GET_PRIORITY_MIN 1

/* Define to 1 if you have the  header file. */
#define HAVE_SCHED_H 1

/* Define to 1 if you have the `select' function. */
#define HAVE_SELECT 1

/* Define to 1 if you have the `setlocale' function. */
#define HAVE_SETLOCALE 1

/* Define to 1 if you have the  header file. */
#define HAVE_SIGNAL_H 1

/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1

/* Define to 1 if you have the `sqrt' function. */
#define HAVE_SQRT 1

/* Define to 1 if `stat' has the bug that it succeeds when given the
   zero-length file name argument. */
/* #undef HAVE_STAT_EMPTY_STRING_BUG */

/* Define to 1 if stdbool.h conforms to C99. */
/* #undef HAVE_STDBOOL_H */

/* Define to 1 if you have the  header file. */
#define HAVE_STDDEF_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_STDINT_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_STDLIB_H 1

/* Define to 1 if you have the `strchr' function. */
#define HAVE_STRCHR 1

/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1

/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1

/* Define to 1 if you have the `strerror_r' function. */
#define HAVE_STRERROR_R 1

/* Define to 1 if you have the `strftime' function. */
#define HAVE_STRFTIME 1

/* Define to 1 if you have the  header file. */
#define HAVE_STRINGS_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_STRING_H 1

/* Define to 1 if you have the `strstr' function. */
#define HAVE_STRSTR 1

/* Define to 1 if you have the `strtol' function. */
#define HAVE_STRTOL 1

/* Define to 1 if you have the `strtoul' function. */
#define HAVE_STRTOUL 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_IOCTL_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_PARAM_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_POLL_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_RESOURCE_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_SELECT_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_SOCKET_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_STAT_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_TIME_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_TYPES_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_SYS_UN_H 1

/* Define to 1 if you have  that is POSIX.1 compatible. */
#define HAVE_SYS_WAIT_H 1

/* Define to 1 if you have the  header file. */
#define HAVE_UNISTD_H 1

/* Define to 1 if you have the `vfork' function. */
#define HAVE_VFORK 1

/* Define to 1 if you have the  header file. */
/* #undef HAVE_VFORK_H */

/* Define to 1 if you have the `vprintf' function. */
#define HAVE_VPRINTF 1

/* Define to 1 if you have the  header file. */
#define HAVE_WCHAR_H 1

/* Define to 1 if `fork' works. */
#define HAVE_WORKING_FORK 1

/* Define to 1 if `vfork' works. */
#define HAVE_WORKING_VFORK 1

/* define if zlib is available */
#define HAVE_ZLIB /**/

/* Define to 1 if the system has the type `_Bool'. */
/* #undef HAVE__BOOL */

/* Possible value for SIGNED_RIGHT_SHIFT_IS */
#define LOGICAL_RIGHT_SHIFT 2

/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
   slash. */
#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1

/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"

/* Name of package */
#define PACKAGE "thrift"

/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""

/* Define to the full name of this package. */
#define PACKAGE_NAME "thrift"

/* Define to the full name and version of this package. */
#define PACKAGE_STRING "thrift 0.19.0"

/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "thrift"

/* Define to the home page for this package. */
#define PACKAGE_URL ""

/* Define to the version of this package. */
#define PACKAGE_VERSION "0.19.0"

/* Define as the return type of signal handlers (`int' or `void'). */
#define RETSIGTYPE void

/* Define to the type of arg 1 for `select'. */
#define SELECT_TYPE_ARG1 int

/* Define to the type of args 2, 3 and 4 for `select'. */
#define SELECT_TYPE_ARG234 (fd_set *)

/* Define to the type of arg 5 for `select'. */
#define SELECT_TYPE_ARG5 (struct timeval *)

/* Indicates the effect of the right shift operator on negative signed
   integers */
#define SIGNED_RIGHT_SHIFT_IS 1

/* If using the C implementation of alloca, define if you know the
   direction of stack growth for your system; otherwise it will be
   automatically deduced at runtime.
	STACK_DIRECTION > 0 => grows toward higher addresses
	STACK_DIRECTION < 0 => grows toward lower addresses
	STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */

/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1

/* Define to 1 if strerror_r returns char *. */
#define STRERROR_R_CHAR_P 1

/* Define to 1 if you can safely include both  and . */
#define TIME_WITH_SYS_TIME 1

/* Define to 1 if your  declares `struct tm'. */
/* #undef TM_IN_SYS_TIME */

/* Possible value for SIGNED_RIGHT_SHIFT_IS */
#define UNKNOWN_RIGHT_SHIFT 3

/* Version number of package */

/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
   `char[]'. */
/* #undef YYTEXT_POINTER */

/* Define for Solaris 2.5.1 so the uint32_t typedef from ,
   , or  is not used. If the typedef were allowed, the
   #define below would cause a syntax error. */
/* #undef _UINT32_T */

/* Define for Solaris 2.5.1 so the uint64_t typedef from ,
   , or  is not used. If the typedef were allowed, the
   #define below would cause a syntax error. */
/* #undef _UINT64_T */

/* Define for Solaris 2.5.1 so the uint8_t typedef from ,
   , or  is not used. If the typedef were allowed, the
   #define below would cause a syntax error. */
/* #undef _UINT8_T */

/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */

/* Define to `__inline__' or `__inline' if that's what the C compiler
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
/* #undef inline */
#endif

/* Define to the type of a signed integer type of width exactly 16 bits if
   such a type exists and the standard includes do not define it. */
/* #undef int16_t */

/* Define to the type of a signed integer type of width exactly 32 bits if
   such a type exists and the standard includes do not define it. */
/* #undef int32_t */

/* Define to the type of a signed integer type of width exactly 64 bits if
   such a type exists and the standard includes do not define it. */
/* #undef int64_t */

/* Define to the type of a signed integer type of width exactly 8 bits if such
   a type exists and the standard includes do not define it. */
/* #undef int8_t */

/* Define to rpl_malloc if the replacement function should be used. */
/* #undef malloc */

/* Define to `int' if  does not define. */
/* #undef mode_t */

/* Define to `long int' if  does not define. */
/* #undef off_t */

/* Define to `int' if  does not define. */
/* #undef pid_t */

/* Define to rpl_realloc if the replacement function should be used. */
/* #undef realloc */

/* Define to `unsigned int' if  does not define. */
/* #undef size_t */

/* Define to `int' if  does not define. */
/* #undef ssize_t */

/* Define to the type of an unsigned integer type of width exactly 16 bits if
   such a type exists and the standard includes do not define it. */
/* #undef uint16_t */

/* Define to the type of an unsigned integer type of width exactly 32 bits if
   such a type exists and the standard includes do not define it. */
/* #undef uint32_t */

/* Define to the type of an unsigned integer type of width exactly 64 bits if
   such a type exists and the standard includes do not define it. */
/* #undef uint64_t */

/* Define to the type of an unsigned integer type of width exactly 8 bits if
   such a type exists and the standard includes do not define it. */
/* #undef uint8_t */

/* Define as `fork' if `vfork' does not work. */
/* #undef vfork */

/* Define to empty if the keyword `volatile' does not work. Warning: valid
   code using `volatile' can become incorrect without. Disable with care. */
/* #undef volatile */


#endif

thrift-0.19.0/.eslintrc.json0000644000000000000000000000056614303740366015710 0ustar00rootroot00000000000000{
  "env": {
    "es6": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:prettier/recommended"
  ],
  "parserOptions": {
    "ecmaVersion": 2017
  },
  "rules": {
    "no-console": "off",
    "no-var": "error",
    "prefer-const": "error",
    "no-constant-condition": [
      "error",
      {
        "checkLoops": false
      }
    ]
  }
}
thrift-0.19.0/CHANGES.md0000644000000000000000000145502414472650170014512 0ustar00rootroot00000000000000# Apache Thrift Changelog

## 0.19.0

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway
- [THRIFT-5654](https://issues.apache.org/jira/browse/THRIFT-5654) - LNK4042 and LNK2019 in go_validator_generator.cc

## Build Process

- [THRIFT-5701](https://issues.apache.org/jira/browse/THRIFT-5701) - Add dependabot

## C++

- [THRIFT-5725](https://issues.apache.org/jira/browse/THRIFT-5725) - Thrift SSL server stops working if the file descriptor returned is zero
- [THRIFT-5716](https://issues.apache.org/jira/browse/THRIFT-5716) - TMemoryBuffer resizing might shrink the buffer size due to uint32_t overflow

## Compiler (General)	

- [THRIFT-5690](https://issues.apache.org/jira/browse/THRIFT-5690) - Constant expects type to be defined before

## Delphi

- [THRIFT-5686](https://issues.apache.org/jira/browse/THRIFT-5686) - Add comparer and capacity arguments to container classes

## Go
- [THRIFT-5731](https://issues.apache.org/jira/browse/THRIFT-5731) - Handle ErrAbandonRequest automatically


## Haxe

- [THRIFT-5717](https://issues.apache.org/jira/browse/THRIFT-5717) - uuid sets and map keys may throw on some Haxe targets
- [THRIFT-5704](https://issues.apache.org/jira/browse/THRIFT-5704) - Superfluous block scope in generated write() code
- [THRIFT-5703](https://issues.apache.org/jira/browse/THRIFT-5703) - Haxe 4.30 emits "Local variable retval used without being initialized" on generated code
- [THRIFT-5692](https://issues.apache.org/jira/browse/THRIFT-5692) - Support for deprecated methods (via annotation)
- [THRIFT-5707](https://issues.apache.org/jira/browse/THRIFT-5707) - deprecation warning fixes for @:extern and @:enum

## Java 

- [THRIFT-5700](https://issues.apache.org/jira/browse/THRIFT-5700) - Migration to JakartaEE and Apache HttpComponents 5
- [THRIFT-5711](https://issues.apache.org/jira/browse/THRIFT-5711) - FutureClient does not extend when service extends from another service 
- [THRIFT-5702](https://issues.apache.org/jira/browse/THRIFT-5702) - Support Java 8
- [THRIFT-5696](https://issues.apache.org/jira/browse/THRIFT-5696) - TByteBuffer.java does not allow non-default TConfiguration
- [THRIFT-5653](https://issues.apache.org/jira/browse/THRIFT-5653) - Fix Java UUID typeid


## JavaScript

- [THRIFT-5674](https://issues.apache.org/jira/browse/THRIFT-5674) - Server implementation exceptions are not sent to client in ES6 promise-style invocation

## netstd 

- [THRIFT-5684](https://issues.apache.org/jira/browse/THRIFT-5684) - Upgrade to net7.0

## Node.js 

- [THRIFT-5710](https://issues.apache.org/jira/browse/THRIFT-5710) - NodeJS header transport leaks headers between all instances

## PHP 

- [THRIFT-5723](https://issues.apache.org/jira/browse/THRIFT-5723) - Php8.1 fix warnings

## Swift 

- [THRIFT-5714](https://issues.apache.org/jira/browse/THRIFT-5714) - add TJSONProtocol support in thrift-swift


## 0.18.1

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway

### Reopened issues

- [THRIFT-5601](https://issues.apache.org/jira/browse/THRIFT-5601) - Typedef after first use causes incorrect go code

### Go

- [THRIFT-5685](https://issues.apache.org/jira/browse/THRIFT-5685) - Compiler generates wrong go code for forward defined types in optional fields
- [THRIFT-5679](https://issues.apache.org/jira/browse/THRIFT-5679) - libthrift-0.17.0 has wrong version numbers in MANIFEST.MF



## 0.18.0

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway

### Compiler (General)

- [THRIFT-5587](https://issues.apache.org/jira/browse/THRIFT-5587) - Introduce uuid as additional builtin type
- [THRIFT-5591](https://issues.apache.org/jira/browse/THRIFT-5591) - Add uuid type to IDL and implement reference code
- [THRIFT-5626](https://issues.apache.org/jira/browse/THRIFT-5626) - Parser should not confuse data types and field names
- [THRIFT-5627](https://issues.apache.org/jira/browse/THRIFT-5627) - More consistent syntax for cpp_type
- [THRIFT-5652](https://issues.apache.org/jira/browse/THRIFT-5652) - IDL uuid literals can be improved 
- [THRIFT-5669](https://issues.apache.org/jira/browse/THRIFT-5669) - "required" keyword is illegal in a "throws" clause 

### C++ 

- [THRIFT-5661](https://issues.apache.org/jira/browse/THRIFT-5661) - TOutput: add zephyr-specific strerror_s implementation
- [THRIFT-5658](https://issues.apache.org/jira/browse/THRIFT-5658) - TProtocol: support zephyr byteorder 
- [THRIFT-5659](https://issues.apache.org/jira/browse/THRIFT-5659) - protocol: declare when methods override

### D language

- [THRIFT-5647](https://issues.apache.org/jira/browse/THRIFT-5647) - Fix undeclared identifier ECONNRESET on macOS

### Delphi

- [THRIFT-5618](https://issues.apache.org/jira/browse/THRIFT-5618) - More consistent naming of container classes
- [THRIFT-5620](https://issues.apache.org/jira/browse/THRIFT-5620) - Option to force usage of COM types to allow for cross-module references
- [THRIFT-5656](https://issues.apache.org/jira/browse/THRIFT-5656) - Escape Delphi keywords with '&' prefix instead of '_' suffix
- [THRIFT-5619](https://issues.apache.org/jira/browse/THRIFT-5619) - make sure CheckReadBytesAvailable() and CountConsumedMessageBytes() handle negative sizes properly
- [THRIFT-5622](https://issues.apache.org/jira/browse/THRIFT-5622) - Garbled test output with multithreaded clients
- [THRIFT-5625](https://issues.apache.org/jira/browse/THRIFT-5625) - SysUtils.TGuidHelper collides with ThriftUtils.TGuidHelper

### Erlang

- [THRIFT-5636](https://issues.apache.org/jira/browse/THRIFT-5636) - Broken client in erlang client library

### Go

- [THRIFT-5601](https://issues.apache.org/jira/browse/THRIFT-5601) - Typedef after first use causes incorrect go code
- [THRIFT-5650](https://issues.apache.org/jira/browse/THRIFT-5650) - Add UUID support in go

### Haxe

- [THRIFT-5593](https://issues.apache.org/jira/browse/THRIFT-5593) - Implement uuid for hx

### Java
- [THRIFT-3956](https://issues.apache.org/jira/browse/THRIFT-3956) - Java keywords that are legal in IDL can lead to generated code that will not compile
- [THRIFT-4655](https://issues.apache.org/jira/browse/THRIFT-4655) - Parser fails on the word "from"
- [THRIFT-5631](https://issues.apache.org/jira/browse/THRIFT-5631) - Execution failed for task ':generateBeanJava'.
- [THRIFT-5632](https://issues.apache.org/jira/browse/THRIFT-5632) - Fix java lib pmd main offending errors

### Kotlin

- [THRIFT-5646](https://issues.apache.org/jira/browse/THRIFT-5646) - Kotlin library should check to see if Gradle is present

### netstd

- [THRIFT-5610](https://issues.apache.org/jira/browse/THRIFT-5610) - Inconsistent constructors TSocketTransport
- [THRIFT-5623](https://issues.apache.org/jira/browse/THRIFT-5623) - ref to disposed instance should be set to null
- [THRIFT-5624](https://issues.apache.org/jira/browse/THRIFT-5624) - suboptimal performance of the c# named pipe server transport in multithread servers
- [THRIFT-5628](https://issues.apache.org/jira/browse/THRIFT-5628) - MaxMessageSize is never reset on a read buffer
- [THRIFT-5639](https://issues.apache.org/jira/browse/THRIFT-5639) - ToString() should use InvariantCulture

### OCaml

- [THRIFT-5208](https://issues.apache.org/jira/browse/THRIFT-5208) - OCaml codegen exception pattern match syntax error
- [THRIFT-5642](https://issues.apache.org/jira/browse/THRIFT-5642) - OCaml in docker build environment is broken

### Python

- [THRIFT-5617](https://issues.apache.org/jira/browse/THRIFT-5617) - T(SSL)Socket TCP keep-alive incorrectly applies SO_KEEPALIVE to IPPROTO_TCP

### Rust

- [THRIFT-5124](https://issues.apache.org/jira/browse/THRIFT-5124) - Cannot use reserved language keyword
- [THRIFT-5606](https://issues.apache.org/jira/browse/THRIFT-5606) - Wrong indent for const double
- [THRIFT-5600](https://issues.apache.org/jira/browse/THRIFT-5600) - Upgrade rust toolchain to 1.61 and edition 2021
- [THRIFT-5643](https://issues.apache.org/jira/browse/THRIFT-5643) - Please publish latest version of the Rust lib to crates.io

### Swift

- [THRIFT-5629](https://issues.apache.org/jira/browse/THRIFT-5629) - Add UUID support for Swift
- [THRIFT-4547](https://issues.apache.org/jira/browse/THRIFT-4547) - Finish the conversion to native swift (LANGUAGES.md, cross test)
- [THRIFT-5621](https://issues.apache.org/jira/browse/THRIFT-5621) - Create Swift Tutorial
- [THRIFT-5630](https://issues.apache.org/jira/browse/THRIFT-5630) - Swift TSocketServer not working on Linux

### Website	

- [THRIFT-5634](https://issues.apache.org/jira/browse/THRIFT-5634) - thrift docs picture was broken


## 0.17.0

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway

### Removed Languages

- [THRIFT-5476](https://issues.apache.org/jira/browse/THRIFT-5476) - Deprecate Common Lisp support

NB. CL had been finally dropped from 0.17.0 due to lack of active maintainers. In the meantime there is some ongoing work to reintegrate CL support in 0.18.0 version.

### Build Process

- [THRIFT-5565](https://issues.apache.org/jira/browse/THRIFT-5565) - upgrade travis ci base image to xenial
- [THRIFT-5572](https://issues.apache.org/jira/browse/THRIFT-5572) - current travis build is broken (error timeout) within kerl erlang build step
- [THRIFT-5575](https://issues.apache.org/jira/browse/THRIFT-5575) - Create a GitHub workflow using CMake

### C++

- [THRIFT-5093](https://issues.apache.org/jira/browse/THRIFT-5093) - lib: cpp: test: clarify effect of MemoryPolicy on TMemoryBuffer
- [THRIFT-5510](https://issues.apache.org/jira/browse/THRIFT-5510) - On Windows NOMINMAX and WIN32_LEAN_AND_MEAN are unset even if set before
- [THRIFT-5515](https://issues.apache.org/jira/browse/THRIFT-5515) - Oneway requests can stuck in TNonblockingServer with TSSLSocket
- [THRIFT-5529](https://issues.apache.org/jira/browse/THRIFT-5529) - Missing space "<::" in C++ generator
- [THRIFT-5576](https://issues.apache.org/jira/browse/THRIFT-5576) - fix old-style cast at const value ctor/copy and redundant copy at ctor

### Common LISP

- [THRIFT-5501](https://issues.apache.org/jira/browse/THRIFT-5501) - Remove Common Lisp support
- [THRIFT-5567](https://issues.apache.org/jira/browse/THRIFT-5567) - remove reference to common lisp namespace

### Compiler (General)

- [THRIFT-5506](https://issues.apache.org/jira/browse/THRIFT-5506) - C26495 variable "t_field::req_" not initialized, t_field.h:40
- [THRIFT-5540](https://issues.apache.org/jira/browse/THRIFT-5540) - Can't use a typedef for a container type containing enums in a constant
- [THRIFT-5588](https://issues.apache.org/jira/browse/THRIFT-5588) - Remove slist/senum from IDL

### Contributed

- [THRIFT-5599](https://issues.apache.org/jira/browse/THRIFT-5599) - contrib/fb303 does not compile after C++ library refactorings

### Delphi

- [THRIFT-5531](https://issues.apache.org/jira/browse/THRIFT-5531) - duplicate constant declarations
- [THRIFT-5586](https://issues.apache.org/jira/browse/THRIFT-5586) - User-Agent header not conforming to RFC 7231

### Documentation

- [THRIFT-5592](https://issues.apache.org/jira/browse/THRIFT-5592) - Update documentation and IDL definition files for uuid type

### Erlang

- [THRIFT-5536](https://issues.apache.org/jira/browse/THRIFT-5536) - Fix cross language tests

### Go

- [THRIFT-5495](https://issues.apache.org/jira/browse/THRIFT-5495) - Go lib server not close client when shutdown
- [THRIFT-5527](https://issues.apache.org/jira/browse/THRIFT-5527) - generated Process function in go will swallow exceptions defined in thrift IDL
- [THRIFT-5539](https://issues.apache.org/jira/browse/THRIFT-5539) - Performance penalty of using TDebugProtocol.DuplicateTo
- [THRIFT-5569](https://issues.apache.org/jira/browse/THRIFT-5569) - generated Go code crashes when reading invalid map/set/list
- [THRIFT-5583](https://issues.apache.org/jira/browse/THRIFT-5583) - Add a skip_remote arg to go compiler
- [THRIFT-5605](https://issues.apache.org/jira/browse/THRIFT-5605) - Go client middleware has no (easy) access to IDL exceptions
- [THRIFT-5609](https://issues.apache.org/jira/browse/THRIFT-5609) - TJSONProtocol is unsafe to be used with TDeserializerPool

### Haxe

- [THRIFT-5589](https://issues.apache.org/jira/browse/THRIFT-5589) - Misc *.hx source files do not compile anymore
- [THRIFT-5590](https://issues.apache.org/jira/browse/THRIFT-5590) - Complex initialisations (sets, maps, etc) are broken in Haxe

### HTML

- [THRIFT-5528](https://issues.apache.org/jira/browse/THRIFT-5528) - Incorrect HTML link for referenced typedefs

### Java

- [THRIFT-4086](https://issues.apache.org/jira/browse/THRIFT-4086) - Java compiler generates different meta data depending on order of structures in file
- [THRIFT-5485](https://issues.apache.org/jira/browse/THRIFT-5485) - @SuppressWarnings is placed above Javadoc
- [THRIFT-5494](https://issues.apache.org/jira/browse/THRIFT-5494) - byte count of FrameBuffer(AbstractNonblockingServer.readBufferBytesAllocated) is not subtracted
- [THRIFT-5502](https://issues.apache.org/jira/browse/THRIFT-5502) - Is it necessary to report CONNECTION RESET as an ERROR?
- [THRIFT-5519](https://issues.apache.org/jira/browse/THRIFT-5519) - Java async client loses exceptions in void methods
- [THRIFT-5520](https://issues.apache.org/jira/browse/THRIFT-5520) - add method to convert Option type to java Optional
- [THRIFT-5521](https://issues.apache.org/jira/browse/THRIFT-5521) - In Java lib, add param for option_type to generate JDK8 optional types
- [THRIFT-5522](https://issues.apache.org/jira/browse/THRIFT-5522) - Upgrade to gradle 6 for Java build
- [THRIFT-5525](https://issues.apache.org/jira/browse/THRIFT-5525) - java gen to use reuse_objects instead of reuse-objects as a consistent param casing
- [THRIFT-5526](https://issues.apache.org/jira/browse/THRIFT-5526) - java gen to use private_members instead of private-members as a consistent param casing
- [THRIFT-5533](https://issues.apache.org/jira/browse/THRIFT-5533) - Fix Java warnings: @param, @return and deprecation
- [THRIFT-5543](https://issues.apache.org/jira/browse/THRIFT-5543) - Java lib FieldMetaData should be more type-safe by adding type parameter to metadata registerations
- [THRIFT-5544](https://issues.apache.org/jira/browse/THRIFT-5544) - add java code gen param to support including field annotation as metadata
- [THRIFT-5545](https://issues.apache.org/jira/browse/THRIFT-5545) - Follow newer gradle convention in organizing source code directories
- [THRIFT-5552](https://issues.apache.org/jira/browse/THRIFT-5552) - Apply clang-format to java code gen file
- [THRIFT-5553](https://issues.apache.org/jira/browse/THRIFT-5553) - java library to use newer gradle API
- [THRIFT-5555](https://issues.apache.org/jira/browse/THRIFT-5555) - Java codegen and library to support future-returning client interface and implementation
- [THRIFT-5557](https://issues.apache.org/jira/browse/THRIFT-5557) - Move Java-only tests from /test to /lib/java
- [THRIFT-5560](https://issues.apache.org/jira/browse/THRIFT-5560) - Use JUnit 5 (Jupiter) for Java unit tests
- [THRIFT-5562](https://issues.apache.org/jira/browse/THRIFT-5562) - remove gradle wrapper jar file from source tree
- [THRIFT-5563](https://issues.apache.org/jira/browse/THRIFT-5563) - fix deprecation and enable xlint for java library
- [THRIFT-5568](https://issues.apache.org/jira/browse/THRIFT-5568) - Use spotless gradle plugin and google-java-format to enforce a consistent code format
- [THRIFT-5570](https://issues.apache.org/jira/browse/THRIFT-5570) - update java lib document about gradle usage
- [THRIFT-5581](https://issues.apache.org/jira/browse/THRIFT-5581) - Upgrade gradle version to 7.4+
- [THRIFT-5582](https://issues.apache.org/jira/browse/THRIFT-5582) - Improve TProtocol.java
- [THRIFT-5584](https://issues.apache.org/jira/browse/THRIFT-5584) - Use gradle toolchain to specify build time Java version

### JSON

- [THRIFT-5549](https://issues.apache.org/jira/browse/THRIFT-5549) - Json generator should indent properly while generating includes

### Kotlin

- [THRIFT-5548](https://issues.apache.org/jira/browse/THRIFT-5548) - Kotlin code generator
- [THRIFT-5571](https://issues.apache.org/jira/browse/THRIFT-5571) - add metadata map building to kotlin generator
- [THRIFT-5580](https://issues.apache.org/jira/browse/THRIFT-5580) - Enhance the kotlin cross test suite

### netstd

- [THRIFT-5505](https://issues.apache.org/jira/browse/THRIFT-5505) - error: 'close_generator' overrides a member function but is not marked 'override' [-Werror,-Winconsistent-missing-override]
- [THRIFT-5511](https://issues.apache.org/jira/browse/THRIFT-5511) - Full support for the new net6 "nullability" semantics 
- [THRIFT-5514](https://issues.apache.org/jira/browse/THRIFT-5514) - C# test client slow in multithread mode
- [THRIFT-5577](https://issues.apache.org/jira/browse/THRIFT-5577) - netstd namespace directive creates matching subfolders
- [THRIFT-5578](https://issues.apache.org/jira/browse/THRIFT-5578) - #nullable disable collides with C# lang versions < 8 (error CS8370)
- [THRIFT-5585](https://issues.apache.org/jira/browse/THRIFT-5585) - net5.0 end of support May 2022

### Node.js

- [THRIFT-5535](https://issues.apache.org/jira/browse/THRIFT-5535) - Ability to support connection on OpenHarmonyOS

### Perl

- [THRIFT-5532](https://issues.apache.org/jira/browse/THRIFT-5532) - Perl Thrift/HttpClient.pm headers bug

### Python

- [THRIFT-2059](https://issues.apache.org/jira/browse/THRIFT-2059) - Support for Python 3.4 enums
- [THRIFT-5449](https://issues.apache.org/jira/browse/THRIFT-5449) - Use select.poll instead of select.select in Python TNonblockingServer if available
- [THRIFT-5467](https://issues.apache.org/jira/browse/THRIFT-5467) - CannotSendHeader exception with 0.15
- [THRIFT-5595](https://issues.apache.org/jira/browse/THRIFT-5595) - TSocket errors with SSLSocket

### Rust

- [THRIFT-4100](https://issues.apache.org/jira/browse/THRIFT-4100) - Extract Rust read/write struct methods into a trait

### Wish List

- [THRIFT-3461](https://issues.apache.org/jira/browse/THRIFT-3461) - Support Method Deprecation


## 0.16.0

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++ library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5468](https://issues.apache.org/jira/browse/THRIFT-5468) - Swift service generator doesn't support oneway

### Deprecated Languages

- [THRIFT-5476](https://issues.apache.org/jira/browse/THRIFT-5476) - Deprecate Common Lisp support

### Breaking Changes

- (none)

### C++

- [THRIFT-5187](https://issues.apache.org/jira/browse/THRIFT-5187) - Add support for Unix domain sockets on Windows 10 or later
- [THRIFT-5418](https://issues.apache.org/jira/browse/THRIFT-5418) - C++ to_string and ostream operator not always generated
- [THRIFT-5456](https://issues.apache.org/jira/browse/THRIFT-5456) - ServerSocket doesn't ignore SIGPIPE

### Common LISP

- [THRIFT-5476](https://issues.apache.org/jira/browse/THRIFT-5476) - Deprecate Common Lisp support

### Erlang

- [THRIFT-5471](https://issues.apache.org/jira/browse/THRIFT-5471) - Introduce delimiter and app_prefix options to erl generator

### Go

- [THRIFT-5461](https://issues.apache.org/jira/browse/THRIFT-5461) - Invalid golang code generated for optional set with a default value
- [THRIFT-5469](https://issues.apache.org/jira/browse/THRIFT-5469) - Go lib skip map value may cause stack overflow
- [THRIFT-5490](https://issues.apache.org/jira/browse/THRIFT-5490) - Improve memory efficiency in go THeader implementation
- [THRIFT-5509](https://issues.apache.org/jira/browse/THRIFT-5509) - Potential connection leaks caused by the connectivity check

### Haxe

- [THRIFT-5470](https://issues.apache.org/jira/browse/THRIFT-5470) - Error: Constraint check failure for haxe.ds.ObjectMap.K

### Java

- [THRIFT-5443](https://issues.apache.org/jira/browse/THRIFT-5443) - add support for partial deserialization of Thrift
- [THRIFT-5486](https://issues.apache.org/jira/browse/THRIFT-5486) - fix issues found by spotbugs 
- [THRIFT-5512](https://issues.apache.org/jira/browse/THRIFT-5512) - Update java dependencies

### JavaScript

- [THRIFT-5448](https://issues.apache.org/jira/browse/THRIFT-5448) - Wrong type mapping of thrift binary type

### netstd

- [THRIFT-5401](https://issues.apache.org/jira/browse/THRIFT-5401) - MaxMessageSize reached exception thrown in TEndpointTransport
- [THRIFT-5408](https://issues.apache.org/jira/browse/THRIFT-5408) - Support for deprecated methods (via annotation)
- [THRIFT-5479](https://issues.apache.org/jira/browse/THRIFT-5479) - Add net 6 support
- [THRIFT-5480](https://issues.apache.org/jira/browse/THRIFT-5480) - TThreadPoolAsyncServer using TFramedTransport mistakenly drops client
- [THRIFT-5481](https://issues.apache.org/jira/browse/THRIFT-5481) - consolidate netstd server implementation details into one common model
- [THRIFT-5500](https://issues.apache.org/jira/browse/THRIFT-5500) - Uncompilable code when .thrift struct 'System' exists
- [THRIFT-5504](https://issues.apache.org/jira/browse/THRIFT-5504) - CA2254 Message template should be compile time constant

### Perl

- [THRIFT-5055](https://issues.apache.org/jira/browse/THRIFT-5055) - Fix build-cpan-dist.sh to create a CPAN distribution correctly
- [THRIFT-5416](https://issues.apache.org/jira/browse/THRIFT-5416) - Allow UDP Socket Client In Perl

### Python

- [THRIFT-5454](https://issues.apache.org/jira/browse/THRIFT-5454) - Python TProcessPoolServer does not spawn expected number of worker processes
- [THRIFT-5488](https://issues.apache.org/jira/browse/THRIFT-5488) - SystemError when using fast binary or compact protocol in python 3.10

### Rust

- [THRIFT-5452](https://issues.apache.org/jira/browse/THRIFT-5452) - Make server optional
- [THRIFT-5457](https://issues.apache.org/jira/browse/THRIFT-5457) - Travis fails consistently on a Rust dependency

### Test Suite

- [THRIFT-5450](https://issues.apache.org/jira/browse/THRIFT-5450) - AppVeyor CI does not run any MSVC tests?


## 0.15.0

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement)

### Removed Languages

- [THRIFT-5229](https://issues.apache.org/jira/browse/THRIFT-5229) - ActionScript 3 support dropped
- [THRIFT-5347](https://issues.apache.org/jira/browse/THRIFT-5347) - Haskell support dropped

### Breaking Changes

- [THRIFT-5381](https://issues.apache.org/jira/browse/THRIFT-5381) - possible collisions at VOID type with some 3rd-party libraries on Haxe cpp targets
- [THRIFT-5396](https://issues.apache.org/jira/browse/THRIFT-5396) - deprecate netstd "Async" method postfix
- [THRIFT-5453](https://issues.apache.org/jira/browse/THRIFT-5453) - go: NewTSocketConf and NewTSSLSocketConf no longer return an error

### AS3

- [THRIFT-5229](https://issues.apache.org/jira/browse/THRIFT-5229) - Deprecate/remove ActionScript 3 support

### Build Process

- [THRIFT-5334](https://issues.apache.org/jira/browse/THRIFT-5334) - version of thrift-maven-plugin is not sync with the main project
- [THRIFT-5394](https://issues.apache.org/jira/browse/THRIFT-5394) - AppVeyor CI tries to download outdated cmake
- [THRIFT-5429](https://issues.apache.org/jira/browse/THRIFT-5429) - build: autotools: add foreign to AM_INIT_AUTOMAKE

### C glib

- [THRIFT-5244](https://issues.apache.org/jira/browse/THRIFT-5244) - Dynamic exception specifications are deprecated in C++11[-Wdeprecated]
- [THRIFT-5265](https://issues.apache.org/jira/browse/THRIFT-5265) - Add the zlib transport to c_glib
- [THRIFT-5399](https://issues.apache.org/jira/browse/THRIFT-5399) - Fix socket leak in abnormal situation
- [THRIFT-5421](https://issues.apache.org/jira/browse/THRIFT-5421) - Fix the problem of incorrect setting of errno in some files

### C++

- [THRIFT-5341](https://issues.apache.org/jira/browse/THRIFT-5341) - Fix Old-Style-Cast, Missing override and Possible noexcept
- [THRIFT-5342](https://issues.apache.org/jira/browse/THRIFT-5342) - Apply 'noexcept' attribute to Init/Copy/Move Constructors and Assignments
- [THRIFT-5355](https://issues.apache.org/jira/browse/THRIFT-5355) - Do not rely on compiler and check boundaries

### D language

- [THRIFT-4303](https://issues.apache.org/jira/browse/THRIFT-4303) - D deprecation warnings
- [THRIFT-4979](https://issues.apache.org/jira/browse/THRIFT-4979) - Still D deprecation warnings about std.datetime.* in current master
- [THRIFT-5376](https://issues.apache.org/jira/browse/THRIFT-5376) - Fix deprecation warnings in D library

### Dart

- [THRIFT-5285](https://issues.apache.org/jira/browse/THRIFT-5285) - Update to dart 2, widen range on http package

### Delphi

- [THRIFT-5350](https://issues.apache.org/jira/browse/THRIFT-5350) - 0.14.0 fails to build on non-x86
- [THRIFT-5438](https://issues.apache.org/jira/browse/THRIFT-5438) - Inconsistent handling of exceptions during message read vs. message write phase
- [THRIFT-5384](https://issues.apache.org/jira/browse/THRIFT-5384) - Improved error message for HTTP transports
- [THRIFT-5385](https://issues.apache.org/jira/browse/THRIFT-5385) - XML-HTTP client reports IsOpen=TRUE even if it is not
- [THRIFT-5386](https://issues.apache.org/jira/browse/THRIFT-5386) - XML-HTTP client may throw "max message size reached" incorrectly
- [THRIFT-5387](https://issues.apache.org/jira/browse/THRIFT-5387) - Improved and simplified Delphi test setup
- [THRIFT-5390](https://issues.apache.org/jira/browse/THRIFT-5390) - Named Pipes transport hardening
- [THRIFT-5428](https://issues.apache.org/jira/browse/THRIFT-5428) - Prevent costly reallocations to improve performance
- [THRIFT-5437](https://issues.apache.org/jira/browse/THRIFT-5437) - Make TProtocolImpl CTOR virtual

### Documentation

- [THRIFT-5332](https://issues.apache.org/jira/browse/THRIFT-5332) - Question: list all the reserved words in thrift doc
- [THRIFT-5348](https://issues.apache.org/jira/browse/THRIFT-5348) - Update debian/copyright

### Erlang

- [THRIFT-5377](https://issues.apache.org/jira/browse/THRIFT-5377) - Remove Erlang R16 support

### Go

- [THRIFT-5337](https://issues.apache.org/jira/browse/THRIFT-5337) - Go set fields write improvement
- [THRIFT-5353](https://issues.apache.org/jira/browse/THRIFT-5353) - Namespace from type is ignored in generated code
- [THRIFT-5358](https://issues.apache.org/jira/browse/THRIFT-5358) - Add go.mod file(s)
- [THRIFT-5369](https://issues.apache.org/jira/browse/THRIFT-5369) - Malformed payload can still cause huge allocations
- [THRIFT-5389](https://issues.apache.org/jira/browse/THRIFT-5389) - Thrift compiler generates uncompilable go code around optional constants
- [THRIFT-5404](https://issues.apache.org/jira/browse/THRIFT-5404) - TTransportException.Timeout would correctly return true when it's connect timeout during TSocket.Open call
- [THRIFT-5447](https://issues.apache.org/jira/browse/THRIFT-5447) - Update supported Go versions before 0.15.0 release
- [THRIFT-5453](https://issues.apache.org/jira/browse/THRIFT-5453) - go: NewTSocketConf should not call net.ResolveTCPAddr
- [THRIFT-5459](https://issues.apache.org/jira/browse/THRIFT-5459) - Adding a new exception to an endpoint is kinda breaking in go
- [THRIFT-5453](https://issues.apache.org/jira/browse/THRIFT-5453) - Defer DNS lookups from NewTSocketConf (without any timeout check) to TSocket.Open (subject to ConnectTimeout set in TConfiguration)
- [THRIFT-5459](https://issues.apache.org/jira/browse/THRIFT-5459) - Client calls will return TApplicationException with MISSING_RESULT when the result is a struct but is unset, and no other error is known.

### Haskell

- [THRIFT-5347](https://issues.apache.org/jira/browse/THRIFT-5347) - Deprecate Haskell bindings

### Haxe

- [THRIFT-5370](https://issues.apache.org/jira/browse/THRIFT-5370) - Haxe 4 compatibility
- [THRIFT-5381](https://issues.apache.org/jira/browse/THRIFT-5381) - possible collisions at VOID type with some 3rd-party libraries on Haxe cpp targets
- [THRIFT-5393](https://issues.apache.org/jira/browse/THRIFT-5393) - Incorrect namespaces for included types
- [THRIFT-3036](https://issues.apache.org/jira/browse/THRIFT-3036) - create official haxelib Thrift package
- [THRIFT-5413](https://issues.apache.org/jira/browse/THRIFT-5413) - Int vs String in method get_size required by property size

### Java

- [THRIFT-5375](https://issues.apache.org/jira/browse/THRIFT-5375) - Put org.apache.tomcat.embed:tomcat-embed-core into scope test
- [THRIFT-5383](https://issues.apache.org/jira/browse/THRIFT-5383) - TJSONProtocol Java readString throws on bounds check
- [THRIFT-5400](https://issues.apache.org/jira/browse/THRIFT-5400) - Java library does not export the .annotation package
- [THRIFT-5425](https://issues.apache.org/jira/browse/THRIFT-5425) - Throw an exception when reading TSimpleJson in Java
- [THRIFT-5430](https://issues.apache.org/jira/browse/THRIFT-5430) - FieldMetaData synchronized method can trigger deadlock during static class initialization in JVM native code
- [THRIFT-5432](https://issues.apache.org/jira/browse/THRIFT-5432) - TSaslTransport throw TTransportException of MaxMessageSize reached
- [THRIFT-5433](https://issues.apache.org/jira/browse/THRIFT-5433) - Add Counter To Thread Name of TThreadPoolServer

### JavaScript

- [THRIFT-3508](https://issues.apache.org/jira/browse/THRIFT-3508) - JS:TS Generator set all fields of the struct as required

### Lua

- [THRIFT-5417](https://issues.apache.org/jira/browse/THRIFT-5417) - Fix Lua compiler omitting default values in Lua service functions
- [THRIFT-5439](https://issues.apache.org/jira/browse/THRIFT-5439) - Lua Generator does not support const i64

### netstd

- [THRIFT-5354](https://issues.apache.org/jira/browse/THRIFT-5354) - disable IDE0083 warning
- [THRIFT-5382](https://issues.apache.org/jira/browse/THRIFT-5382) - Netstd default list/set enums values are generated incorrectly in some cases
- [THRIFT-5395](https://issues.apache.org/jira/browse/THRIFT-5395) - inconsistent treatment of methods ending in "Async"
- [THRIFT-5396](https://issues.apache.org/jira/browse/THRIFT-5396) - deprecate "Async" method postfix
- [THRIFT-5408](https://issues.apache.org/jira/browse/THRIFT-5408) - Support for deprecated methods (via annotation)
- [THRIFT-5414](https://issues.apache.org/jira/browse/THRIFT-5414) - Use of specific parameter names generates uncompileable code
- [THRIFT-5442](https://issues.apache.org/jira/browse/THRIFT-5442) - Separate client service calls into send/recv methods and make them public
- [THRIFT-5444](https://issues.apache.org/jira/browse/THRIFT-5444) - Netstd generator produces uncompileable code for enums ending with "_result" or "_args"
- [THRIFT-5445](https://issues.apache.org/jira/browse/THRIFT-5445) - "cancellationToken" cannot be used as argument name
- [THRIFT-5236](https://issues.apache.org/jira/browse/THRIFT-5236) - THttpTransport.cs still has bad timeout code
- [THRIFT-5349](https://issues.apache.org/jira/browse/THRIFT-5349) - Add net5.0 as supported platform
- [THRIFT-5373](https://issues.apache.org/jira/browse/THRIFT-5373) - HTTP status in case of Protocol/Transport exceptions
- [THRIFT-5391](https://issues.apache.org/jira/browse/THRIFT-5391) - Named pipes transport hardening
- [THRIFT-5398](https://issues.apache.org/jira/browse/THRIFT-5398) - ThreadPoolServer not stoppable via CancellationToken
- [THRIFT-5407](https://issues.apache.org/jira/browse/THRIFT-5407) - Keep support for .NET Core 3.1
- [THRIFT-5419](https://issues.apache.org/jira/browse/THRIFT-5419) - Incorrect usage of thread pool in TThreadPoolAsyncServer may lead to poor performance
- [THRIFT-5422](https://issues.apache.org/jira/browse/THRIFT-5422) - add threadpool server to netstd test suite impl
- [THRIFT-5431](https://issues.apache.org/jira/browse/THRIFT-5431) - Response should include 'content-type' header
- [THRIFT-5436](https://issues.apache.org/jira/browse/THRIFT-5436) - Timeout.Infinite is not a good default

### PHP

- [THRIFT-5318](https://issues.apache.org/jira/browse/THRIFT-5318) - PHP 8 compatible version of binary protocol
- [THRIFT-5440](https://issues.apache.org/jira/browse/THRIFT-5440) - Add php8 to composer.json

### Python

- [THRIFT-5352](https://issues.apache.org/jira/browse/THRIFT-5352) - Python: IDL exceptions with no fields can't be instantiated

### Ruby

- [THRIFT-5312](https://issues.apache.org/jira/browse/THRIFT-5312) - The Ruby compilation configuration in the .gemspec file is modified to be compatible with later bundler versions.
- [THRIFT-5367](https://issues.apache.org/jira/browse/THRIFT-5367) - Ruby library crashes when using GC.compact

### Rust

- [THRIFT-4098](https://issues.apache.org/jira/browse/THRIFT-4098) - Support user-defined output namespaces in generated Rust modules
- [THRIFT-4101](https://issues.apache.org/jira/browse/THRIFT-4101) - Make auto-generated Rust enums and unions more user-extensible
- [THRIFT-5314](https://issues.apache.org/jira/browse/THRIFT-5314) - Enum forward compatibility
- [THRIFT-5363](https://issues.apache.org/jira/browse/THRIFT-5363) - All-caps constant rendered incorrectly


## 0.14.2

### Java

- [THRIFT-5383](https://issues.apache.org/jira/browse/THRIFT-5383) - THRIFT-5383 TJSONProtocol Java readString throws on bounds check

### Go

- [THRIFT-5369](https://issues.apache.org/jira/browse/THRIFT-5369) - TConfiguration.GetMaxMessageSize() now also applies to container sizes in TProtocol implementations provided


## 0.14.1

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5098](https://issues.apache.org/jira/browse/THRIFT-5098) - Deprecated: "The high level Network interface is no longer supported. Please use Network.Socket." and other Haskell issues
- [THRIFT-5245](https://issues.apache.org/jira/browse/THRIFT-5245) - NPE when the value of map's key is null

### Deprecated Languages

- [THRIFT-5347](https://issues.apache.org/jira/browse/THRIFT-5347) - Deprecate Haskell bindings

### Build Process

- [THRIFT-5334](https://issues.apache.org/jira/browse/THRIFT-5334) - version of thrift-maven-plugin is not sync with the main project

### Delphi

- [THRIFT-5350](https://issues.apache.org/jira/browse/THRIFT-5350) - 0.14.0 fails to build on non-x86

### Go

- [THRIFT-5353](https://issues.apache.org/jira/browse/THRIFT-5353) - Namespace from type is ignored in generated code

### Python

- [THRIFT-5352](https://issues.apache.org/jira/browse/THRIFT-5352) - Python: IDL exceptions with no fields can't be instantiated

### Rust

- [THRIFT-5299](https://issues.apache.org/jira/browse/THRIFT-5299) - rs implementation compact protocol seq_id should not use zigzag encoding.


## 0.14.0

### Deprecated Languages

- [THRIFT-5229](https://issues.apache.org/jira/browse/THRIFT-5229) - Deprecate ActionScript 3 support

### Removed Languages

- [THRIFT-4980](https://issues.apache.org/jira/browse/THRIFT-4980) - Remove deprecated C# and netcore bindings from the code base
- [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base
- [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated C# bindings from the code base

### Breaking Changes

- [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base
- [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated csharp bindings from the code base
- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS)
- [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport
- [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - In Go library TDeserializer.Transport is now typed \*TMemoryBuffer instead of TTransport
- [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers
- [THRIFT-5116](https://issues.apache.org/jira/browse/THRIFT-5116) - Upgrade NodeJS to 10.x
- [THRIFT-5138](https://issues.apache.org/jira/browse/THRIFT-5138) - Swift generator does not escape keywords properly
- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - In Go library TProcessor interface now includes ProcessorMap and AddToProcessorMap functions.
- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - cpp: use all getaddrinfo() results when retrying failed bind() in T{Nonblocking,}ServerSocket
- [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - go: Now all Read*, Write* and Skip functions in TProtocol accept context arg
- [THRIFT-5152](https://issues.apache.org/jira/browse/THRIFT-5152) - go: TSocket and TSSLSocket now have separated connect timeout and socket timeout
- c++: dropped support for Windows XP
- [THRIFT-5326](https://issues.apache.org/jira/browse/THRIFT-5326) - go: TException interface now has a new function: TExceptionType
- [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - go: TClient.Call now returns ResponseMeta in addition to error

### Known Open Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement)
- [THRIFT-5098](https://issues.apache.org/jira/browse/THRIFT-5098) - Deprecated: "The high level Network interface is no longer supported. Please use Network.Socket." and other Haskell issues
- [THRIFT-5245](https://issues.apache.org/jira/browse/THRIFT-5245) - NPE when the value of map's key is null
- [THRIFT-4687](https://issues.apache.org/jira/browse/THRIFT-4687) - Add thrift 0.12.0 to pypi and/or enable more maintainers

### Build Process

- [THRIFT-4976](https://issues.apache.org/jira/browse/THRIFT-4976) - Docker build: Test failure for `StalenessCheckTest` on MacOS
- [THRIFT-5087](https://issues.apache.org/jira/browse/THRIFT-5087) - test/test.py fails with "AssertionError: Python 3.3 or later is required for proper operation."
- [THRIFT-5097](https://issues.apache.org/jira/browse/THRIFT-5097) - Incorrect THRIFT_VERSION in ThriftConfig.cmake
- [THRIFT-5109](https://issues.apache.org/jira/browse/THRIFT-5109) - Misc CMake improvements
- [THRIFT-5147](https://issues.apache.org/jira/browse/THRIFT-5147) - Add uninstall function
- [THRIFT-5218](https://issues.apache.org/jira/browse/THRIFT-5218) - Automated Github release artifacts do not match checksums provided
- [THRIFT-5249](https://issues.apache.org/jira/browse/THRIFT-5249) - travis-ci : Failed to run FastbinaryTest.py

### C glib

- [THRIFT-4873](https://issues.apache.org/jira/browse/THRIFT-4873) - Memory leak in c_glib
- [THRIFT-5118](https://issues.apache.org/jira/browse/THRIFT-5118) - Fix memory leak when the handler method return a exception
- [THRIFT-5134](https://issues.apache.org/jira/browse/THRIFT-5134) - Fix memory leak when the handler method return FALSE
- [THRIFT-5144](https://issues.apache.org/jira/browse/THRIFT-5144) - Fix memory leak when generate deserialize list element
- [THRIFT-4272](https://issues.apache.org/jira/browse/THRIFT-4272) - warnings in glibc library
- [THRIFT-4952](https://issues.apache.org/jira/browse/THRIFT-4952) - Modified ssl_read feedback value break all the time error.
- [THRIFT-5076](https://issues.apache.org/jira/browse/THRIFT-5076) - Improve CMake OpenSSL usage
- [THRIFT-5094](https://issues.apache.org/jira/browse/THRIFT-5094) - Fix memory leak in thrift_server_set_property()
- [THRIFT-5101](https://issues.apache.org/jira/browse/THRIFT-5101) - Return NULL install of FALSE for thrift_server_socket_accept()
- [THRIFT-5102](https://issues.apache.org/jira/browse/THRIFT-5102) - Fix memory leak in thrift_simple_server_serve()
- [THRIFT-5136](https://issues.apache.org/jira/browse/THRIFT-5136) - Fix memory leak in thrift_multiplexed_processor_process_impl()
- [THRIFT-5221](https://issues.apache.org/jira/browse/THRIFT-5221) - Fix stack overflow when reading buffer
- [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class
- [THRIFT-5255](https://issues.apache.org/jira/browse/THRIFT-5255) - Fix stack overflow in framed transport
- [THRIFT-5256](https://issues.apache.org/jira/browse/THRIFT-5256) - Fix some compile warnings
- [THRIFT-5268](https://issues.apache.org/jira/browse/THRIFT-5268) - Fix some file loss ')' in define

### C++

- [THRIFT-1513](https://issues.apache.org/jira/browse/THRIFT-1513) - Thrift compiler generates inconsistent code with some complex values (causing g++ to error: "has no member named '__isset')
- [THRIFT-5168](https://issues.apache.org/jira/browse/THRIFT-5168) - Useless generated code when .thrift file only has service type
- [THRIFT-5179](https://issues.apache.org/jira/browse/THRIFT-5179) - Thrift compiler will generate wrong code if IDL struct's name is 'a' or  'b'
- [THRIFT-5200](https://issues.apache.org/jira/browse/THRIFT-5200) - Thrift compiler will generate incorrect code when add 'cob_style' option.
- [THRIFT-4282](https://issues.apache.org/jira/browse/THRIFT-4282) - StressTestNonBlocking is disabled in Appveyor as it is unstable on Windows in general
- [THRIFT-4682](https://issues.apache.org/jira/browse/THRIFT-4682) - C++ TBinaryProtocol crashes on port scan
- [THRIFT-4963](https://issues.apache.org/jira/browse/THRIFT-4963) - TNonblockingServer blocked int addTask(IOThread) and notify(workerThread)
- [THRIFT-5047](https://issues.apache.org/jira/browse/THRIFT-5047) - fix cmake support to build cpp server without OPENSSL
- [THRIFT-5076](https://issues.apache.org/jira/browse/THRIFT-5076) - Improve CMake OpenSSL usage
- [THRIFT-5078](https://issues.apache.org/jira/browse/THRIFT-5078) - Handle named pipe clients quickly disconnecting
- [THRIFT-5086](https://issues.apache.org/jira/browse/THRIFT-5086) - CMake target thrift::thrift has no INTERFACE_INCLUDE_DIRECTORIES property
- [THRIFT-5110](https://issues.apache.org/jira/browse/THRIFT-5110) - Added a number of required libs for using static OpenSSL
- [THRIFT-5114](https://issues.apache.org/jira/browse/THRIFT-5114) - Simplify the computation of the size of TMemoryBuffer
- [THRIFT-5177](https://issues.apache.org/jira/browse/THRIFT-5177) - getaddrinfo() should not be used for Unix sockets
- [THRIFT-5178](https://issues.apache.org/jira/browse/THRIFT-5178) - THttpClient should work without specifying host
- [THRIFT-5185](https://issues.apache.org/jira/browse/THRIFT-5185) - C++: Add WebSocket Server Transport
- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - AI_ADDRCONFIG: Thrift libraries crash with localhost-only network.
- [THRIFT-5215](https://issues.apache.org/jira/browse/THRIFT-5215) - C++: Remove portable_endian.h
- [THRIFT-5217](https://issues.apache.org/jira/browse/THRIFT-5217) - Deprecated boost header
- [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class
- [THRIFT-5290](https://issues.apache.org/jira/browse/THRIFT-5290) - Adjusting cpp *.cproj msvcrt options according to LEGAL-538
- [THRIFT-5295](https://issues.apache.org/jira/browse/THRIFT-5295) - Thread and ThreadFactory should be extensible
- [THRIFT-5344](https://issues.apache.org/jira/browse/THRIFT-5344) - TTransport may throw raw pointer exceptions

### Compiler (General)

- [THRIFT-4173](https://issues.apache.org/jira/browse/THRIFT-4173) - Go: thrift compiler generates wrong code for list of aliased type
- [THRIFT-4938](https://issues.apache.org/jira/browse/THRIFT-4938) - Issues with version.h treatment
- [THRIFT-4973](https://issues.apache.org/jira/browse/THRIFT-4973) - Add deprecation messages for csharp and netcore
- [THRIFT-4980](https://issues.apache.org/jira/browse/THRIFT-4980) - Remove deprecated C# and netcore bindings from the code base
- [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated C# bindings from the code baseï…‚
- [THRIFT-5153](https://issues.apache.org/jira/browse/THRIFT-5153) - Deprecate byte
- [THRIFT-5225](https://issues.apache.org/jira/browse/THRIFT-5225) - Use nullptr instead of NULL
- [THRIFT-5302](https://issues.apache.org/jira/browse/THRIFT-5302) - Add recursive function name uniqueness check

### D

- [THRIFT-5059](https://issues.apache.org/jira/browse/THRIFT-5059) - Add cross tests for TZlibTransport in D
- [THRIFT-5156](https://issues.apache.org/jira/browse/THRIFT-5156) - D: Fix library compilation on Windows and compiler warnings
- [THRIFT-5166](https://issues.apache.org/jira/browse/THRIFT-5166) - Add WebSocket Server Transport
- [THRIFT-5184](https://issues.apache.org/jira/browse/THRIFT-5184) - D: WebSocket Server Transport Fix for Firefox

### Delphi

- [THRIFT-5044](https://issues.apache.org/jira/browse/THRIFT-5044) - Improve serialization support for TApplicationExceptions and custom exceptions
- [THRIFT-5154](https://issues.apache.org/jira/browse/THRIFT-5154) - Generate interface IDs (IID) for Windows platforms
- [THRIFT-5235](https://issues.apache.org/jira/browse/THRIFT-5235) - Add property setter for isset flags
- [THRIFT-5261](https://issues.apache.org/jira/browse/THRIFT-5261) - Support for deprecated methods (via annotation)
- [THRIFT-5004](https://issues.apache.org/jira/browse/THRIFT-5004) - Make exception implementations more consistent
- [THRIFT-5005](https://issues.apache.org/jira/browse/THRIFT-5005) - Refactoring of the Delphi libs
- [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport
- [THRIFT-5007](https://issues.apache.org/jira/browse/THRIFT-5007) - Implement MAX_MESSAGE_SIZE and remaining read bytes control
- [THRIFT-5009](https://issues.apache.org/jira/browse/THRIFT-5009) - Serializer implemtation lacks support for layered transports
- [THRIFT-5012](https://issues.apache.org/jira/browse/THRIFT-5012) - Centralize configuration aspects into a commonly used configuration object
- [THRIFT-5015](https://issues.apache.org/jira/browse/THRIFT-5015) - WinHTTP QueryDataAvailable cannot be used to retrieve total response size
- [THRIFT-5036](https://issues.apache.org/jira/browse/THRIFT-5036) - buffered transport over sockets may run into unexpected timeouts
- [THRIFT-5048](https://issues.apache.org/jira/browse/THRIFT-5048) - EnumUtils.ToString() throws for elements not known to the receiving end
- [THRIFT-5088](https://issues.apache.org/jira/browse/THRIFT-5088) - Memory leak in TEndpointTransportBase
- [THRIFT-5123](https://issues.apache.org/jira/browse/THRIFT-5123) - add possibility to query HTTP status code with WinHTTP
- [THRIFT-5146](https://issues.apache.org/jira/browse/THRIFT-5146) - Align Delphi to the test suite arguments rules (its "--switch=value", not "--switch value")
- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - AI_ADDRCONFIG: Thrift libraries crash with localhost-only network.
- [THRIFT-5188](https://issues.apache.org/jira/browse/THRIFT-5188) - Occasional ERROR_INSUFFICIENT_BUFFER at WinHttpQueryHeaders()
- [THRIFT-5251](https://issues.apache.org/jira/browse/THRIFT-5251) - StringUtils.ToString() raises an exception for enum values outside range
- [THRIFT-5304](https://issues.apache.org/jira/browse/THRIFT-5304) - TWinHTTPClientImpl may incorrectly report that the message size is reached

### Documentation

- [THRIFT-5037](https://issues.apache.org/jira/browse/THRIFT-5037) - Documentation for TConfiguration
- [THRIFT-5065](https://issues.apache.org/jira/browse/THRIFT-5065) - Fix broken links in the IDL document
- [THRIFT-5074](https://issues.apache.org/jira/browse/THRIFT-5074) - Cleanup test suite command line options

### Go

- [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - Compiler generated service clients now provide a new function, LastResponseMeta_(), to get the response metadata (e.g. headers from THeader) from the last client call.
- [THRIFT-4984](https://issues.apache.org/jira/browse/THRIFT-4984) - Scary and spammy "error processing request: EOF" logs from TSimpleServer
- [THRIFT-4985](https://issues.apache.org/jira/browse/THRIFT-4985) - Clean up logging in go library
- [THRIFT-5002](https://issues.apache.org/jira/browse/THRIFT-5002) - remote client fails to compile when extending services
- [THRIFT-5019](https://issues.apache.org/jira/browse/THRIFT-5019) - Multiple import same namespace for go included files
- [THRIFT-5046](https://issues.apache.org/jira/browse/THRIFT-5046) - Custom tags remove db and json tags
- [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - Add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer.
- [THRIFT-5092](https://issues.apache.org/jira/browse/THRIFT-5092) - Panic on nil buffer writes
- [THRIFT-5152](https://issues.apache.org/jira/browse/THRIFT-5152) - Separate timeout in TSocket
- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Go middleware support
- [THRIFT-5214](https://issues.apache.org/jira/browse/THRIFT-5214) - go: Implement connection check in TSocket
- [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - I/O timeout handling in go library
- [THRIFT-5240](https://issues.apache.org/jira/browse/THRIFT-5240) - The context passed into server handler implementations will be canceled when we detected that the client closed the connection.
- [THRIFT-5257](https://issues.apache.org/jira/browse/THRIFT-5257) - Go THeader implementation doesn't handle endOfFrame correctly
- [THRIFT-5270](https://issues.apache.org/jira/browse/THRIFT-5270) - Go library unit test is broken in go 1.15
- [THRIFT-5278](https://issues.apache.org/jira/browse/THRIFT-5278) - Expose API to use THeader+TCompactProtocol in go library client code
- [THRIFT-5279](https://issues.apache.org/jira/browse/THRIFT-5279) - Cleanups/small optimizations for go's serializer/deserializer code
- [THRIFT-5294](https://issues.apache.org/jira/browse/THRIFT-5294) - Go: TSimpleJSONProtocol could panic on WriteMessageEnd without matching WriteMessageBegin
- [THRIFT-5322](https://issues.apache.org/jira/browse/THRIFT-5322) - Add support to TConfiguration, and also fix a bug that could cause excessive memory usage when reading malformed messages from TCompactProtocol.
- [THRIFT-5338](https://issues.apache.org/jira/browse/THRIFT-5338) - Proposal: Raise minimal supported Go version with upcoming 0.14.0 release

### Haskell

- [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers
- [THRIFT-4959](https://issues.apache.org/jira/browse/THRIFT-4959) - cabal.exe: --enable-tests was specified, but tests can't be enabled in a remote package
- [THRIFT-5211](https://issues.apache.org/jira/browse/THRIFT-5211) - Handle incomplete reads correctly

### Java

- [THRIFT-4252](https://issues.apache.org/jira/browse/THRIFT-4252) - Cannot shutdown Java server when clients are still connected
- [THRIFT-4889](https://issues.apache.org/jira/browse/THRIFT-4889) - Add SASL support for non-blocking server
- [THRIFT-4937](https://issues.apache.org/jira/browse/THRIFT-4937) - Apache HttpCore 4.4.1 reached EoS
- [THRIFT-4949](https://issues.apache.org/jira/browse/THRIFT-4949) - improve HTTP/1 server test case
- [THRIFT-5008](https://issues.apache.org/jira/browse/THRIFT-5008) - Add a logger line in case of failing to dispose sasl
- [THRIFT-5013](https://issues.apache.org/jira/browse/THRIFT-5013) - Use Java Objects RequireNonNull
- [THRIFT-5016](https://issues.apache.org/jira/browse/THRIFT-5016) - Do Not Check 'other' For Null in Equals
- [THRIFT-5022](https://issues.apache.org/jira/browse/THRIFT-5022) - TIOStreamTransport.isOpen returns true for one-sided transports (see THRIFT-2530).
- [THRIFT-5031](https://issues.apache.org/jira/browse/THRIFT-5031) - Fix javadoc of TIOStreamTransport
- [THRIFT-5115](https://issues.apache.org/jira/browse/THRIFT-5115) - PR #2022 Updated gradle to 6.2 broke CI
- [THRIFT-5190](https://issues.apache.org/jira/browse/THRIFT-5190) - StringUtils haven't take `(offset + length) > bytes.length` into account
- [THRIFT-5197](https://issues.apache.org/jira/browse/THRIFT-5197) - TSSLTransportFactory Do Not Wrap NOT_OPEN Exception Type for Client
- [THRIFT-5201](https://issues.apache.org/jira/browse/THRIFT-5201) - Use Apache Parent Pom for Thrift Maven Plugin
- [THRIFT-5202](https://issues.apache.org/jira/browse/THRIFT-5202) - TNonblockingMultiFetchClient Use SLF4J Parameterized Logging
- [THRIFT-5203](https://issues.apache.org/jira/browse/THRIFT-5203) - Remove Unused toString Method in TSerializer
- [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class
- [THRIFT-5247](https://issues.apache.org/jira/browse/THRIFT-5247) - Avoiding meaningless System.copy
- [THRIFT-5274](https://issues.apache.org/jira/browse/THRIFT-5274) - Thrift 0.13.0 does not work with JDK8
- [THRIFT-5287](https://issues.apache.org/jira/browse/THRIFT-5287) - Log When Client Connections are Dropped
- [THRIFT-5288](https://issues.apache.org/jira/browse/THRIFT-5288) - Move Support for ByteBuffer into TTransport

### JavaScript

- [THRIFT-5234](https://issues.apache.org/jira/browse/THRIFT-5234) - Fix a number of js/ts generation issues

### Lua

- [THRIFT-5106](https://issues.apache.org/jira/browse/THRIFT-5106) - Fix various Lua library and compiler issues
- [THRIFT-5260](https://issues.apache.org/jira/browse/THRIFT-5260) - Fix the thrift compiler generate problematic lua code for the oneway method
- [THRIFT-4992](https://issues.apache.org/jira/browse/THRIFT-4992) - thrift lua TcompactProtocol bug fix  #1881
- [THRIFT-5262](https://issues.apache.org/jira/browse/THRIFT-5262) - Fix a encoding struct bug in the compact protocol implementation to lua
- [THRIFT-5282](https://issues.apache.org/jira/browse/THRIFT-5282) - Add IPv6 client support to Lua library
- [THRIFT-5286](https://issues.apache.org/jira/browse/THRIFT-5286) - Fix Lua library readBool() in TCompactProtocol
- [THRIFT-5325](https://issues.apache.org/jira/browse/THRIFT-5325) - Fix Lua library writeStructEnd() in TCompactProtocol

### Markdown

- [THRIFT-5289](https://issues.apache.org/jira/browse/THRIFT-5289) - Add markdown compiler

### netstd

- [THRIFT-5032](https://issues.apache.org/jira/browse/THRIFT-5032) - Allows PascalCase properties for netstd
- [THRIFT-5091](https://issues.apache.org/jira/browse/THRIFT-5091) - Netstd generator produces uncompileable code for struct names ending with "_result" or "_args"
- [THRIFT-5095](https://issues.apache.org/jira/browse/THRIFT-5095) - ToString() should print entire structure, not just the top-level data
- [THRIFT-5198](https://issues.apache.org/jira/browse/THRIFT-5198) - Fix certain Visual Studio hints in generated netstd code
- [THRIFT-5216](https://issues.apache.org/jira/browse/THRIFT-5216) - generate DeepCopy methods
- [THRIFT-5220](https://issues.apache.org/jira/browse/THRIFT-5220) - DeepCopy() extension methods not generated when the IDL contains no service
- [THRIFT-5238](https://issues.apache.org/jira/browse/THRIFT-5238) - GetHashCode can throw NullReferenceException
- [THRIFT-5253](https://issues.apache.org/jira/browse/THRIFT-5253) - using Result in result name generates wrong IAsync interface
- [THRIFT-5254](https://issues.apache.org/jira/browse/THRIFT-5254) - Member name cannot be Isset (unless it is an "required" member)
- [THRIFT-5316](https://issues.apache.org/jira/browse/THRIFT-5316) - Netstd compiler generates wrong ToString() method: .ToString(sb)
- [THRIFT-5317](https://issues.apache.org/jira/browse/THRIFT-5317) - netstd compiler does not escape keywords
- [THRIFT-5320](https://issues.apache.org/jira/browse/THRIFT-5320) - Usage of "Task" as IDL identifier generates uncompileable code
- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS)
- [THRIFT-5010](https://issues.apache.org/jira/browse/THRIFT-5010) - BinaryPrimitives.Read/WriteInt32BigEndian should be used to convert to/from network byte order
- [THRIFT-5020](https://issues.apache.org/jira/browse/THRIFT-5020) - Refactoring & minor fixes for netstd library
- [THRIFT-5021](https://issues.apache.org/jira/browse/THRIFT-5021) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class
- [THRIFT-5026](https://issues.apache.org/jira/browse/THRIFT-5026) - TestClient/Server ignores first cmdline argument
- [THRIFT-5027](https://issues.apache.org/jira/browse/THRIFT-5027) - Implement remaining read bytes checks
- [THRIFT-5053](https://issues.apache.org/jira/browse/THRIFT-5053) - Fix the netstd tutorial console logging and README
- [THRIFT-5083](https://issues.apache.org/jira/browse/THRIFT-5083) - NetStd JSON Protocol left in incorrect state
- [THRIFT-5133](https://issues.apache.org/jira/browse/THRIFT-5133) - TCompactProtocol string allocation improvement
- [THRIFT-5172](https://issues.apache.org/jira/browse/THRIFT-5172) - NetStd TBaseClient open output transport multiple times
- [THRIFT-5210](https://issues.apache.org/jira/browse/THRIFT-5210) - further performance optimizations
- [THRIFT-5239](https://issues.apache.org/jira/browse/THRIFT-5239) - THttpTransport should support passing in an HttpClient
- [THRIFT-5252](https://issues.apache.org/jira/browse/THRIFT-5252) - Make CreateHttpClientHandler() method virtual
- [THRIFT-5275](https://issues.apache.org/jira/browse/THRIFT-5275) - Compilation error with Thrift when used in .Net Framework 4.6.1 or above
- [THRIFT-5343](https://issues.apache.org/jira/browse/THRIFT-5343) - TTlsSocketTransport does not resolve IPv4 addresses or validate hostnames correctly

### Node.js

- [THRIFT-3356](https://issues.apache.org/jira/browse/THRIFT-3356) - TypeError: 'undefined' is not a function (evaluating 'Error.captureStackTrace(this, this.constructor)')
- [THRIFT-4994](https://issues.apache.org/jira/browse/THRIFT-4994) - TWebSocketTransport false scope in forEach in browser
- [THRIFT-5003](https://issues.apache.org/jira/browse/THRIFT-5003) - Websocket Connection in Browsers with nodejs code
- [THRIFT-5116](https://issues.apache.org/jira/browse/THRIFT-5116) - Ubuntu xenial NodeJS 6.x is too old, 10.x required
- [THRIFT-5163](https://issues.apache.org/jira/browse/THRIFT-5163) - adds Q to exports for browserify

### Perl

- [THRIFT-5050](https://issues.apache.org/jira/browse/THRIFT-5050) - Fix MemoryBuffer.pm to raise a proper exception if no data is available
- [THRIFT-5066](https://issues.apache.org/jira/browse/THRIFT-5066) - Implement testBinary invocation in TestClient.pl

### PHP

- [THRIFT-4942](https://issues.apache.org/jira/browse/THRIFT-4942) - Set PHP struct generated field values as private with getters and setters
- [THRIFT-5082](https://issues.apache.org/jira/browse/THRIFT-5082) - Add a Class reference for PHP enum $_TSPEC
- [THRIFT-5103](https://issues.apache.org/jira/browse/THRIFT-5103) - PHP 7.4 THttpClient deprecated error
- [THRIFT-5130](https://issues.apache.org/jira/browse/THRIFT-5130) - Use Apcu instead of APC
- [THRIFT-5132](https://issues.apache.org/jira/browse/THRIFT-5132) - Warning in TSocket when using ssl connection
- [THRIFT-5199](https://issues.apache.org/jira/browse/THRIFT-5199) - Infinite loop in PHP TSocket::write when peer closes connection
- [THRIFT-5336](https://issues.apache.org/jira/browse/THRIFT-5336) - Add possibility to setup connection timeout in TCurlClient

### Python

- [THRIFT-2087](https://issues.apache.org/jira/browse/THRIFT-2087) - unicode decode errors
- [THRIFT-4002](https://issues.apache.org/jira/browse/THRIFT-4002) - Thrift exceptions are not hashable in Python 3
- [THRIFT-5107](https://issues.apache.org/jira/browse/THRIFT-5107) - Travis build fails with missing Python 3.3 or newer?
- [THRIFT-5165](https://issues.apache.org/jira/browse/THRIFT-5165) - Python THttpClient saves cookie when Set-Cookie response header is present
- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - AI_ADDRCONFIG: Thrift libraries crash with localhost-only network.
- [THRIFT-5248](https://issues.apache.org/jira/browse/THRIFT-5248) - Python: Make TSocket.isOpen check if the other end is still connected
- [THRIFT-5303](https://issues.apache.org/jira/browse/THRIFT-5303) - Unicode decode errors in _fast_decode
- [THRIFT-5331](https://issues.apache.org/jira/browse/THRIFT-5331) - Python: allow THeaderProtocol to choose which subprotocol to use for outbound connections

### Ruby

- [THRIFT-5281](https://issues.apache.org/jira/browse/THRIFT-5281) -  Some warning messages need to be fixed
- [THRIFT-4707](https://issues.apache.org/jira/browse/THRIFT-4707) - Enable maintainers to upload newer versions of Ruby Gem of Thrift
- [THRIFT-5061](https://issues.apache.org/jira/browse/THRIFT-5061) - Pin Ruby's rack version to 2.0.8
- [THRIFT-5100](https://issues.apache.org/jira/browse/THRIFT-5100) - Gem::InstallError: byebug requires Ruby version >= 2.4.0.
- [THRIFT-5266](https://issues.apache.org/jira/browse/THRIFT-5266) - release ruby library thrift 0.13.0

### Rust

- [THRIFT-4764](https://issues.apache.org/jira/browse/THRIFT-4764) - Rust frontend emits deprecated clippy suppression attributes
- [THRIFT-5071](https://issues.apache.org/jira/browse/THRIFT-5071) - Rust: rust tutorial can not be compiled with rust edition 2018
- [THRIFT-5158](https://issues.apache.org/jira/browse/THRIFT-5158) - Update Rust Compiler to generate 2018 edition code only
- [THRIFT-5307](https://issues.apache.org/jira/browse/THRIFT-5307) - Rust generated code should compile cleanly with clippy
- [THRIFT-4915](https://issues.apache.org/jira/browse/THRIFT-4915) - Deserializing double into OrderedFloat always returns zero when using TCompactProtocol
- [THRIFT-4995](https://issues.apache.org/jira/browse/THRIFT-4995) - [Rust] Use `ToSocketAddrs` for expressing network addresses
- [THRIFT-5042](https://issues.apache.org/jira/browse/THRIFT-5042) - Fix failing cargo tests
- [THRIFT-5043](https://issues.apache.org/jira/browse/THRIFT-5043) - Make TBufferChannel clonable
- [THRIFT-5111](https://issues.apache.org/jira/browse/THRIFT-5111) - CI fails with error[E0721]: `await` is a keyword in the 2018 edition
- [THRIFT-5131](https://issues.apache.org/jira/browse/THRIFT-5131) - i64 maxint decoding panics with integer-encoding >= 1.1.0
- [THRIFT-5306](https://issues.apache.org/jira/browse/THRIFT-5306) - Rust library, tutorial, test, cross-test code should not throw any clippy errors

### Swift

- [THRIFT-4989](https://issues.apache.org/jira/browse/THRIFT-4989) - Run time exception when using TCompactProtocol
- [THRIFT-5128](https://issues.apache.org/jira/browse/THRIFT-5128) - Swift TFramedTransport does not work using present code
- [THRIFT-5138](https://issues.apache.org/jira/browse/THRIFT-5138) - Swift generator does not escape keywords properly
- [THRIFT-5155](https://issues.apache.org/jira/browse/THRIFT-5155) - Swift 5.1 support
- [THRIFT-5070](https://issues.apache.org/jira/browse/THRIFT-5070) - Swift: Hashable.hashValue is deprecated as a protocol requirement
- [THRIFT-5084](https://issues.apache.org/jira/browse/THRIFT-5084) - Swift: Server-side support for Multiplexing Services
- [THRIFT-5121](https://issues.apache.org/jira/browse/THRIFT-5121) - Logic bug in TMultiplexedProcessor – Swift
- [THRIFT-5125](https://issues.apache.org/jira/browse/THRIFT-5125) - Swift server does not work using present code.
- [THRIFT-5129](https://issues.apache.org/jira/browse/THRIFT-5129) - Swift TSocketTransport cannot be used to connect to client
- [THRIFT-5150](https://issues.apache.org/jira/browse/THRIFT-5150) - TSet does not compile with Swift 5.2

### Test Suite

- [THRIFT-4974](https://issues.apache.org/jira/browse/THRIFT-4974) - Add cross test for Python's Unix domain socket transport
- [THRIFT-5145](https://issues.apache.org/jira/browse/THRIFT-5145) - Streamline  --pipe and --named-pipe options in the code base
- [THRIFT-5171](https://issues.apache.org/jira/browse/THRIFT-5171) - Fix maven-ant-tasks to use HTTPS instead of HTTP

### TypeScript) - Library

- [THRIFT-5003](https://issues.apache.org/jira/browse/THRIFT-5003) - Websocket Connection in Browsers with nodejs code

### Tutorial

- [THRIFT-4972](https://issues.apache.org/jira/browse/THRIFT-4972) - Add Makefile.am to the Perl tutorial
- [THRIFT-4975](https://issues.apache.org/jira/browse/THRIFT-4975) - Add Makefile.am to the PHP tutorial
- [THRIFT-5051](https://issues.apache.org/jira/browse/THRIFT-5051) - Fix Python tutorials to address THRIFT-4002
- [THRIFT-5052](https://issues.apache.org/jira/browse/THRIFT-5052) - Make the Go tutorial executable to the end
- [THRIFT-5122](https://issues.apache.org/jira/browse/THRIFT-5122) - Fix memory leak in c_glib tutorial server


## 0.13.0

### New Languages

- (none)

### Deprecated Languages

- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - CSharp and Netcore targets are deprecated and will be removed with the next release) - use NetStd instead.

### Removed Languages

- [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Cocoa language was removed) - use swift instead.

### Breaking Changes

- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - compiler: removed the plug-in mechanism
- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - cpp: C++03/C++98 support has been removed; also removed boost as a runtime dependency
- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - cpp: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed
- [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - cpp: CMake build changed to use BUILD_SHARED_LIBS
- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - cpp: Removed Qt4 support
- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - cpp: Use std::chrono::duration for timeouts
- [THRIFT-4762](https://issues.apache.org/jira/browse/THRIFT-4762) - cpp: TTransport::getOrigin() is now const
- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - java: class org.apache.thrift.AutoExpandingBuffer is no longer public
- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - java: changes to UTF-8 handling require JDK 1.7 at a minimum
- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public
- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods
- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - java: replaced TSaslTransportException with TTransportException
- [THRIFT-2530](https://issues.apache.org/jira/browse/THRIFT-2530) - java: TIOStreamTransport's "isOpen" now returns false after "close" is called
- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants
- [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - delphi: old THTTPTransport is now TMsxmlHTTPTransport
- [THRIFT-4536](https://issues.apache.org/jira/browse/THRIFT-4536) - rust: convert from try-from crate to rust stable (1.34+), re-export ordered-float

### Known Issues (Blocker or Critical)

- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement)

### As3

- [THRIFT-4784](https://issues.apache.org/jira/browse/THRIFT-4784) - Thrift should throw when skipping over unexpected data

### Build Process

- [THRIFT-2333](https://issues.apache.org/jira/browse/THRIFT-2333) - RPMBUILD: Abort build if user did not disable ruby but ruby build will fail later on
- [THRIFT-4689](https://issues.apache.org/jira/browse/THRIFT-4689) - Pull changes from 0.12.0 release branch into master
- [THRIFT-4690](https://issues.apache.org/jira/browse/THRIFT-4690) - Update dlang deimos for OpenSSL 1.1 (use 1.1.0h tagged release instead of master)
- [THRIFT-4694](https://issues.apache.org/jira/browse/THRIFT-4694) - Upgrade Java to Java 1.8
- [THRIFT-4716](https://issues.apache.org/jira/browse/THRIFT-4716) - Create a version alignment tool to make releases easier
- [THRIFT-4760](https://issues.apache.org/jira/browse/THRIFT-4760) - Install pkgconfig when using cmake
- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact
- [THRIFT-4811](https://issues.apache.org/jira/browse/THRIFT-4811) - Add cmake config module
- [THRIFT-4855](https://issues.apache.org/jira/browse/THRIFT-4855) - go CI fails with "cannot find package "golang.org/x/tools/go/packages" in any of ..."
- [THRIFT-4864](https://issues.apache.org/jira/browse/THRIFT-4864) - CI fails at netstd
- [THRIFT-4874](https://issues.apache.org/jira/browse/THRIFT-4874) - Thrift 0.12.0 Source Distribution (.tar.gz) Contains Hardlinks) - Extract Fails
- [THRIFT-4896](https://issues.apache.org/jira/browse/THRIFT-4896) - cpp and c_glib include paths are added to source files when building
- [THRIFT-4966](https://issues.apache.org/jira/browse/THRIFT-4966) - Git ignore files generated by the build

### C glib

- [THRIFT-4842](https://issues.apache.org/jira/browse/THRIFT-4842) - Multiplexed protocol has a memory leak in set c_glib
- [THRIFT-4878](https://issues.apache.org/jira/browse/THRIFT-4878) - c_glib ThriftSocket support for unix domain sockets
- [THRIFT-4950](https://issues.apache.org/jira/browse/THRIFT-4950) - fix bind print  error and Macro call errors thrift_server_socket

### C#

- [THRIFT-3587](https://issues.apache.org/jira/browse/THRIFT-3587) - C# TTLSSocket does not use timeout for opening the socket
- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types
- [THRIFT-4684](https://issues.apache.org/jira/browse/THRIFT-4684) - Missing namespace and un-used private fields in WCF fault classes when enable WCF in C# code generation
- [THRIFT-4715](https://issues.apache.org/jira/browse/THRIFT-4715) - C# union "data" should be strongly-typed
- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - Consolidate C# and netcore into new netstd language target (and finally deprecate both C# and netcore bindings)
- [THRIFT-4741](https://issues.apache.org/jira/browse/THRIFT-4741) - Missing "inner" argument from one CTOR
- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact
- [THRIFT-4859](https://issues.apache.org/jira/browse/THRIFT-4859) - Enables changing 'UserAgent'
- [THRIFT-4907](https://issues.apache.org/jira/browse/THRIFT-4907) - strong named assemblies wanted

### C++

- [THRIFT-4384](https://issues.apache.org/jira/browse/THRIFT-4384) - Using a concurrent client with cpp async is not safe.
- [THRIFT-4441](https://issues.apache.org/jira/browse/THRIFT-4441) - C++: support building lib without Boost
- [THRIFT-4487](https://issues.apache.org/jira/browse/THRIFT-4487) - gettimeofday: windows implementation not quoting source, applying license to foreign code
- [THRIFT-4593](https://issues.apache.org/jira/browse/THRIFT-4593) - Unit Tests failing on Alpine Linux due to non-portable mutex initializers
- [THRIFT-4678](https://issues.apache.org/jira/browse/THRIFT-4678) - add noexcept cpp generator option
- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - Drop support for C++03/C++98 and begin refactoring
- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - Remove pthread and boost::thread library support and use std::thread for C++11
- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - Remove C++ Qt4 support (leave Qt5) - Qt4 LTS ended in 2014
- [THRIFT-4739](https://issues.apache.org/jira/browse/THRIFT-4739) - Good old concurrency_test failing on windows builds again with some regularity
- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - Use std::chrono for timeout and remove old structures.
- [THRIFT-4762](https://issues.apache.org/jira/browse/THRIFT-4762) - C++: Applied some C++11 refactorings to the runtime library and compiler
- [THRIFT-4776](https://issues.apache.org/jira/browse/THRIFT-4776) - Modernize c++11 code by clang-tidy
- [THRIFT-4830](https://issues.apache.org/jira/browse/THRIFT-4830) - Add to_string function for enum in C++ file generate
- [THRIFT-4861](https://issues.apache.org/jira/browse/THRIFT-4861) - Fix use of deprecated boost endian header; move to minimum boost 1.56.0
- [THRIFT-4936](https://issues.apache.org/jira/browse/THRIFT-4936) - add depth limit type exception description
- [THRIFT-4962](https://issues.apache.org/jira/browse/THRIFT-4962) - Deadlock in TimerManager::stop

### cocoa

- [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Remove cocoa language support

## Compiler (General)

- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - Remove the compiler plug-in mode

### contributed

- [THRIFT-4897](https://issues.apache.org/jira/browse/THRIFT-4897) - UT of thrift-maven-plugin failed

## D language

- [THRIFT-4690](https://issues.apache.org/jira/browse/THRIFT-4690) - Update dlang deimos for OpenSSL 1.1 (use 1.1.0h tagged release instead of master)
- [THRIFT-4724](https://issues.apache.org/jira/browse/THRIFT-4724) - dlang dub.json dependency for openssl is too restrictive
- [THRIFT-4918](https://issues.apache.org/jira/browse/THRIFT-4918) - dlang name conflict

### dart

- [THRIFT-4654](https://issues.apache.org/jira/browse/THRIFT-4654) - Thrift Dart port is not compatible with Dart 2

### Delphi

- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types
- [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - THTTPTransport relies on activeX component
- [THRIFT-4843](https://issues.apache.org/jira/browse/THRIFT-4843) - http:// and https:// schemes are switched in test client
- [THRIFT-4862](https://issues.apache.org/jira/browse/THRIFT-4862) - better ToString() support for enums and container types
- [THRIFT-4863](https://issues.apache.org/jira/browse/THRIFT-4863) - better indication of WinHTTP errors
- [THRIFT-4881](https://issues.apache.org/jira/browse/THRIFT-4881) - Allow TLS1.1 and TLS1.2 over WinHTTP even when not configured as systemwide default
- [THRIFT-4882](https://issues.apache.org/jira/browse/THRIFT-4882) - Autodetect proxy settings with WinHTTP
- [THRIFT-4884](https://issues.apache.org/jira/browse/THRIFT-4884) - Add serialisation performance test for Delphi
- [THRIFT-4886](https://issues.apache.org/jira/browse/THRIFT-4886) - More detailed error information for WinHTTP transport
- [THRIFT-4894](https://issues.apache.org/jira/browse/THRIFT-4894) - Enable automatic content encoding handling for gzip,deflate in the WinHTTP client
- [THRIFT-4939](https://issues.apache.org/jira/browse/THRIFT-4939) - TThriftListImpl.Sort() does not use comparer
- [THRIFT-4944](https://issues.apache.org/jira/browse/THRIFT-4944) - Field IDs > 255 fail with compact protocol

### Documentation

- [THRIFT-4697](https://issues.apache.org/jira/browse/THRIFT-4697) - Create updated release procedures
- [THRIFT-4808](https://issues.apache.org/jira/browse/THRIFT-4808) - Update LANGUAGES.md on master to reflect master
- [THRIFT-4933](https://issues.apache.org/jira/browse/THRIFT-4933) - Incorrect description in the 0.12.0 version of the documentation

### Erlang

- [THRIFT-4583](https://issues.apache.org/jira/browse/THRIFT-4583) - Support rebar3 for erlang builds
- [THRIFT-4744](https://issues.apache.org/jira/browse/THRIFT-4744) - Erlang help intendation not aligned

### Go

- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types
- [THRIFT-4612](https://issues.apache.org/jira/browse/THRIFT-4612) - Add THeader for Go
- [THRIFT-4747](https://issues.apache.org/jira/browse/THRIFT-4747) - The 'omitempty' tag should not be appended to optional fields that have a default value
- [THRIFT-4797](https://issues.apache.org/jira/browse/THRIFT-4797) - Generated Go code produces name collisions on imports
- [THRIFT-4908](https://issues.apache.org/jira/browse/THRIFT-4908) - reader&writer in golang's TBinaryProtocol is not necessary and misleading

### haskell

- [THRIFT-4834](https://issues.apache.org/jira/browse/THRIFT-4834) - CI error at Haskell: Failed to load interface for `Network'
- [THRIFT-4955](https://issues.apache.org/jira/browse/THRIFT-4955) - Haskell test broken due to extension to CompactProtoTestStruct
- [THRIFT-4956](https://issues.apache.org/jira/browse/THRIFT-4956) - DebugProtoTest_Main.hs: Invalid ThriftType 128

### haxe

- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types
- [THRIFT-4812](https://issues.apache.org/jira/browse/THRIFT-4812) - haxelib readme still points to old ASF git repo

### HTML

- [THRIFT-4763](https://issues.apache.org/jira/browse/THRIFT-4763) - HTML compiler produces invalid HTML document

### Java

- [THRIFT-2530](https://issues.apache.org/jira/browse/THRIFT-2530) - TIOStreamTransport's isOpen() always be true even if close() was called.
- [THRIFT-4368](https://issues.apache.org/jira/browse/THRIFT-4368) - Guaranteed NPE in TBaseAsyncProcessor.java
- [THRIFT-4469](https://issues.apache.org/jira/browse/THRIFT-4469) - isServing is not thread safe
- [THRIFT-4481](https://issues.apache.org/jira/browse/THRIFT-4481) - TBinaryProtocol.writeMessageEnd isn't throwable exception
- [THRIFT-4695](https://issues.apache.org/jira/browse/THRIFT-4695) - Pre-Size Java Collections in Union
- [THRIFT-4696](https://issues.apache.org/jira/browse/THRIFT-4696) - NonBlocking Server: Use case-switch Statement Instead of if-else Clauses
- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Improve AutoExpandingBuffer
- [THRIFT-4704](https://issues.apache.org/jira/browse/THRIFT-4704) - Streamline TDeserializer Implementation
- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Use StandardCharset UTF-8
- [THRIFT-4711](https://issues.apache.org/jira/browse/THRIFT-4711) - Improve Immutable None Type Instantiation
- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Improve Performance of ShortStack
- [THRIFT-4713](https://issues.apache.org/jira/browse/THRIFT-4713) - Review of TBaseHelper.java
- [THRIFT-4714](https://issues.apache.org/jira/browse/THRIFT-4714) - Java TFramedTransport calls write twice for each flush
- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - Change Return Type Signature of Process Methods
- [THRIFT-4726](https://issues.apache.org/jira/browse/THRIFT-4726) - Remove SLF4J Logging Guards
- [THRIFT-4748](https://issues.apache.org/jira/browse/THRIFT-4748) - Add Jitpack support
- [THRIFT-4766](https://issues.apache.org/jira/browse/THRIFT-4766) - JDK9+ fails on missing annotations
- [THRIFT-4773](https://issues.apache.org/jira/browse/THRIFT-4773) - TSaslTransport should relay underlying TTransportException to TSaslTransportException
- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - Suppress excessive logging of SASL TTransportExceptions in case of END_OF_FILE
- [THRIFT-4849](https://issues.apache.org/jira/browse/THRIFT-4849) - Do not Ignore InterruptedException
- [THRIFT-4851](https://issues.apache.org/jira/browse/THRIFT-4851) - Remove All Calls To printStackTrace
- [THRIFT-4857](https://issues.apache.org/jira/browse/THRIFT-4857) - Java field hash code implementation inconsistent with equals.
- [THRIFT-4858](https://issues.apache.org/jira/browse/THRIFT-4858) - Java TThreadPoolServer: confusing error message on closed socket
- [THRIFT-4865](https://issues.apache.org/jira/browse/THRIFT-4865) - warning: [deprecation] UTF_8 in Charsets has been deprecated
- [THRIFT-4899](https://issues.apache.org/jira/browse/THRIFT-4899) - Generated TypeScript declarations incorrectly references types when there is more than 1 include
- [THRIFT-4945](https://issues.apache.org/jira/browse/THRIFT-4945) - Log output mode is not standardized
- [THRIFT-4957](https://issues.apache.org/jira/browse/THRIFT-4957) - testSanePartsOfCompactProtoTestStruct FAILED

### JavaScript

- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings
- [THRIFT-4728](https://issues.apache.org/jira/browse/THRIFT-4728) - Cleanup for the double rendering test in JS
- [THRIFT-4737](https://issues.apache.org/jira/browse/THRIFT-4737) - thrift.js does not use customHeaders in jqRequest
- [THRIFT-4745](https://issues.apache.org/jira/browse/THRIFT-4745) - warning C4305: 'initializing' : truncation from '"__int64' to 'long'
- [THRIFT-4757](https://issues.apache.org/jira/browse/THRIFT-4757) - grunt-shell-spawn drags in sync-exec which has a security notice

### netcore

- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types
- [THRIFT-4722](https://issues.apache.org/jira/browse/THRIFT-4722) - Netcore union "data" should be strongly-typed
- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - Consolidate C# and netcore into new netstd language target (and finally deprecate both C# and netcore bindings)
- [THRIFT-4742](https://issues.apache.org/jira/browse/THRIFT-4742) - Typo "cannot read from null input stream" on write
- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact
- [THRIFT-4919](https://issues.apache.org/jira/browse/THRIFT-4919) - THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code

### netstd

- [THRIFT-4768](https://issues.apache.org/jira/browse/THRIFT-4768) - Remove "nullable" option from the code base (netstd ONLY)
- [THRIFT-4772](https://issues.apache.org/jira/browse/THRIFT-4772) - fully enable server-side usage of framed/buffered transports
- [THRIFT-4813](https://issues.apache.org/jira/browse/THRIFT-4813) - NamedPipes may not work in all cases
- [THRIFT-4816](https://issues.apache.org/jira/browse/THRIFT-4816) - JSONTransports Context.WriteAsync/ReadAsync are badly named
- [THRIFT-4817](https://issues.apache.org/jira/browse/THRIFT-4817) - Add string CTOR to TTlsSocketTransport
- [THRIFT-4818](https://issues.apache.org/jira/browse/THRIFT-4818) - Test client should use cancellation token
- [THRIFT-4821](https://issues.apache.org/jira/browse/THRIFT-4821) - Normalize TServerSocketTransport constructors in netstd
- [THRIFT-4822](https://issues.apache.org/jira/browse/THRIFT-4822) - Refactor bool CTOR flags into enum type
- [THRIFT-4824](https://issues.apache.org/jira/browse/THRIFT-4824) - Logger deprecation warnings in tutorial
- [THRIFT-4825](https://issues.apache.org/jira/browse/THRIFT-4825) - Align TTlsServerSocketTransport constructors with TServerSocketTransport) - Breaking Change
- [THRIFT-4829](https://issues.apache.org/jira/browse/THRIFT-4829) - HTTP server transport lacks TransportFactory arguments
- [THRIFT-4831](https://issues.apache.org/jira/browse/THRIFT-4831) - interface ITProtocolFactory should be class TProtocolFactory again
- [THRIFT-4832](https://issues.apache.org/jira/browse/THRIFT-4832) - superfluous backing field causes CS0169 "field never used"
- [THRIFT-4839](https://issues.apache.org/jira/browse/THRIFT-4839) - Remove embedded buffering/framed options from TCP transports
- [THRIFT-4840](https://issues.apache.org/jira/browse/THRIFT-4840) - Update the README in the netstd tutorial to include references to the new buffering arguments
- [THRIFT-4848](https://issues.apache.org/jira/browse/THRIFT-4848) - Add ability to set Content-Type,Accept headers in HTTP client
- [THRIFT-4853](https://issues.apache.org/jira/browse/THRIFT-4853) - TServerFramedTransport is now obsolete and can be removed
- [THRIFT-4854](https://issues.apache.org/jira/browse/THRIFT-4854) - oneway calls do not work over HTTP
- [THRIFT-4860](https://issues.apache.org/jira/browse/THRIFT-4860) - Allow changing "User-Agent"
- [THRIFT-4879](https://issues.apache.org/jira/browse/THRIFT-4879) - general performance improvements for netstd library
- [THRIFT-4891](https://issues.apache.org/jira/browse/THRIFT-4891) - Align HTTP test client with all other variants
- [THRIFT-4893](https://issues.apache.org/jira/browse/THRIFT-4893) - Enable automatic content encoding handling for gzip,deflate in the HTTP client
- [THRIFT-4898](https://issues.apache.org/jira/browse/THRIFT-4898) - Pipe write operations across a network are limited to 65,535 bytes per write.
- [THRIFT-4919](https://issues.apache.org/jira/browse/THRIFT-4919) - THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code

### node.js

- [THRIFT-3060](https://issues.apache.org/jira/browse/THRIFT-3060) - Node.js client retry logic doesn't flush offline queue on reconnect
- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings
- [THRIFT-4738](https://issues.apache.org/jira/browse/THRIFT-4738) - Generated typescript type definition files are incorrect
- [THRIFT-4771](https://issues.apache.org/jira/browse/THRIFT-4771) - THeader for node.js
- [THRIFT-4809](https://issues.apache.org/jira/browse/THRIFT-4809) - Javascript episodic code generation
- [THRIFT-4844](https://issues.apache.org/jira/browse/THRIFT-4844) - createConnection ignores connect_timeout option

### perl

- [THRIFT-4691](https://issues.apache.org/jira/browse/THRIFT-4691) - The perl CPAN module contains no tests

### PHP

- [THRIFT-4751](https://issues.apache.org/jira/browse/THRIFT-4751) - Missing imports in TProtocol (phpdoc related only)
- [THRIFT-4794](https://issues.apache.org/jira/browse/THRIFT-4794) - Finish adding json protocol to the php cross test
- [THRIFT-4807](https://issues.apache.org/jira/browse/THRIFT-4807) - PHP extension segfaults if reference is used in input
- [THRIFT-4845](https://issues.apache.org/jira/browse/THRIFT-4845) - PHP's TCurlClient ignores timeout values smaller that 1 second

### python

- [THRIFT-1549](https://issues.apache.org/jira/browse/THRIFT-1549) - Python TSSLSocket: Shutdown cleanly
- [THRIFT-4733](https://issues.apache.org/jira/browse/THRIFT-4733) - Address already in use with python unit test
- [THRIFT-4767](https://issues.apache.org/jira/browse/THRIFT-4767) - support tcp keepalive in python
- [THRIFT-4778](https://issues.apache.org/jira/browse/THRIFT-4778) - Python protocol factories do not derive from TProtocolFactory
- [THRIFT-4779](https://issues.apache.org/jira/browse/THRIFT-4779) - Python, Java TMultiplexedProcessor do not raise TProtocolException
- [THRIFT-4780](https://issues.apache.org/jira/browse/THRIFT-4780) - TMultiplexedProcessor is not fully tested or implemented in Python
- [THRIFT-4783](https://issues.apache.org/jira/browse/THRIFT-4783) - Thrift should throw when skipping over unexpected data
- [THRIFT-4798](https://issues.apache.org/jira/browse/THRIFT-4798) - Fix python THttpServer to honor correct oneway reply semantics
- [THRIFT-4892](https://issues.apache.org/jira/browse/THRIFT-4892) - SASL data type exception for PLAIN
- [THRIFT-4920](https://issues.apache.org/jira/browse/THRIFT-4920) - Binary constants emit non-binary Python literals

### ruby

- [THRIFT-4721](https://issues.apache.org/jira/browse/THRIFT-4721) - Installing the ruby gem on systems without make fails in the build_ext task.
- [THRIFT-4971](https://issues.apache.org/jira/browse/THRIFT-4971) - Fix lib/rb/spec/union_spec.rb so that CI succeeds

### rust

- [THRIFT-4953](https://issues.apache.org/jira/browse/THRIFT-4953) - Unspecified Field Identifier Creates Non Compiling Rust Code
- [THRIFT-4960](https://issues.apache.org/jira/browse/THRIFT-4960) - Bare Trait Warnings

### Swift

- [THRIFT-4902](https://issues.apache.org/jira/browse/THRIFT-4902) - Swift compatibility with Swift 4.2, 5.0 and 5.1

### Test suite

- [THRIFT-4301](https://issues.apache.org/jira/browse/THRIFT-4301) - configuring --without-python and --without-py3 still invokes py3 tests in make cross
- [THRIFT-4405](https://issues.apache.org/jira/browse/THRIFT-4405) - Incorrect handling of sequence numbers that wrap to negative
- [THRIFT-4794](https://issues.apache.org/jira/browse/THRIFT-4794) - Finish adding json protocol to the php cross test
- [THRIFT-4969](https://issues.apache.org/jira/browse/THRIFT-4969) - PHP test doesn't check the code generation with php:classmap

### Tutorial

- [THRIFT-4426](https://issues.apache.org/jira/browse/THRIFT-4426) - repository should not include symbolic links
- [THRIFT-4965](https://issues.apache.org/jira/browse/THRIFT-4965) - Perl tutorial server doesn't work due to the lack of use statement
- [THRIFT-4967](https://issues.apache.org/jira/browse/THRIFT-4967) - Node.js tutorial server fails if the zip function invoked
- [THRIFT-4968](https://issues.apache.org/jira/browse/THRIFT-4968) - Makefile.am in the Ruby tutorial refers to Python directory
- [THRIFT-4970](https://issues.apache.org/jira/browse/THRIFT-4970) - PHP tutorial doesn't work with Thrift v0.12.0+

### Typescript

- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings

## 0.12.0

Released 2019-JAN-04

### New Languages
- Common LISP (cl)
- Swift
- Typescript (nodets)

### Deprecated Languages
- C++03/C++98 (move to C++11)
- Cocoa (move to Swift)

### Breaking Changes (since 0.11.0)
- [THRIFT-4529](https://issues.apache.org/jira/browse/THRIFT-4529) - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions
- [THRIFT-4448](https://issues.apache.org/jira/browse/THRIFT-4448) - Support for golang 1.6 and earlier has been dropped.
- [THRIFT-4474](https://issues.apache.org/jira/browse/THRIFT-4474) - PHP now uses the PSR-4 loader by default instead of class maps.
- [THRIFT-4532](https://issues.apache.org/jira/browse/THRIFT-4532) - method signatures changed in the compiler's t_oop_generator.
- [THRIFT-4648](https://issues.apache.org/jira/browse/THRIFT-4648) - The C (GLib) compiler's handling of namespaces has been improved.

### Known Issues (Blocker or Critical)
- [THRIFT-4037](https://issues.apache.org/jira/browse/THRIFT-4037) - build: use a single build system for thrift
- [THRIFT-4119](https://issues.apache.org/jira/browse/THRIFT-4119) - build: bootstrap.sh is missing from source tarball
- [THRIFT-3289](https://issues.apache.org/jira/browse/THRIFT-3289) - csharp: socket exhaustion in csharp implementation
- [THRIFT-3029](https://issues.apache.org/jira/browse/THRIFT-3029) - cocoa: Getters for fields defined with uppercase names do not work
- [THRIFT-3325](https://issues.apache.org/jira/browse/THRIFT-3325) - cocoa: Extended services aren't subclasses in generated Cocoa
- [THRIFT-4116](https://issues.apache.org/jira/browse/THRIFT-4116) - cocoa: Thrift de-capitalizes the name of IsSet property in Cocoa
- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - cpp: the http implementation is not standard; interop with other languages is spotty at best
- [THRIFT-4180](https://issues.apache.org/jira/browse/THRIFT-4180) - cpp: Impossible to build Thrift C++ library for Android (NDK)
- [THRIFT-4384](https://issues.apache.org/jira/browse/THRIFT-4384) - cpp: Using multiple async services simultaneously is not thread-safe
- [THRIFT-3108](https://issues.apache.org/jira/browse/THRIFT-3108) - haskell: Defaulted struct parameters on a service generates invalid Haskell
- [THRIFT-3990](https://issues.apache.org/jira/browse/THRIFT-3990) - nodejs: Exception swallowed by deserialization function
- [THRIFT-4214](https://issues.apache.org/jira/browse/THRIFT-4214) - nodejs: map key treated as hex value in JavaScript
- [THRIFT-4602](https://issues.apache.org/jira/browse/THRIFT-4602) - nodejs: ERROR in ./node_modules/thrift/lib/nodejs/lib/thrift/connection.js Module not found: Error: Can't resolve 'child_process'
- [THRIFT-4639](https://issues.apache.org/jira/browse/THRIFT-4639) - nodejs: Sequence numbering for multiplexed protocol broken
- [THRIFT-1310](https://issues.apache.org/jira/browse/THRIFT-1310) - php: sequence and reconnection management issues
- [THRIFT-1538](https://issues.apache.org/jira/browse/THRIFT-1538) - php: Error during deserialization int64 on 32-bit architecture
- [THRIFT-1580](https://issues.apache.org/jira/browse/THRIFT-1580) - php: thrift type i64 java to php serialize/deserealize not working
- [THRIFT-1950](https://issues.apache.org/jira/browse/THRIFT-1950) - php: PHP gets stuck in infinite loop
- [THRIFT-2954](https://issues.apache.org/jira/browse/THRIFT-2954) - python: sending int or float in a double field breaks the connection
- [THRIFT-4080](https://issues.apache.org/jira/browse/THRIFT-4080) - python: unix sockets can get stuck forever
- [THRIFT-4281](https://issues.apache.org/jira/browse/THRIFT-4281) - python: generated code is out of order and causes load issues
- [THRIFT-4677](https://issues.apache.org/jira/browse/THRIFT-4677) - py3: UnicodeDecideError in Python3

### Build Process
- [THRIFT-4067](https://issues.apache.org/jira/browse/THRIFT-4067) - Windows thrift compiler distributed on the apache web site has runtime dependencies
- [THRIFT-4308](https://issues.apache.org/jira/browse/THRIFT-4308) - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang
- [THRIFT-4579](https://issues.apache.org/jira/browse/THRIFT-4579) - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10)
- [THRIFT-4508](https://issues.apache.org/jira/browse/THRIFT-4508) - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more
- [THRIFT-4397](https://issues.apache.org/jira/browse/THRIFT-4397) - ubuntu install instructions broken on 16.04
- [THRIFT-4545](https://issues.apache.org/jira/browse/THRIFT-4545) - Appveyor builds are failing due to a haskell / cabal update in chocolatey
- [THRIFT-4452](https://issues.apache.org/jira/browse/THRIFT-4452) - optimize Dockerfile (only onetime apt-get update)
- [THRIFT-4440](https://issues.apache.org/jira/browse/THRIFT-4440) - rm `build/docker/ubuntu-trusty/Dockerfile.orig`
- [THRIFT-4352](https://issues.apache.org/jira/browse/THRIFT-4352) - Ubuntu Artful doesn't appear to be compatible with Thrift and Haxe 3.4.2
- [THRIFT-4666](https://issues.apache.org/jira/browse/THRIFT-4666) - DLang Client Pool Test fails sporadically
- [THRIFT-4676](https://issues.apache.org/jira/browse/THRIFT-4676) - CL tutorial build fails sporadically
- [THRIFT-4456](https://issues.apache.org/jira/browse/THRIFT-4456) - Make haxelib download quiet so it doesn't blow up the build log
- [THRIFT-4605](https://issues.apache.org/jira/browse/THRIFT-4605) - bootstrap.sh fails if automake=1.16.1

### c_glib
- [THRIFT-4648](https://issues.apache.org/jira/browse/THRIFT-4648) - The C (GLib) compiler's handling of namespaces has been improved.
- [THRIFT-4622](https://issues.apache.org/jira/browse/THRIFT-4622) - glibC compilation issue
- [THRIFT-4671](https://issues.apache.org/jira/browse/THRIFT-4671) - c glib is unable to handle client close unexpectedly

### cl (new language support in 0.12.0)
- [THRIFT-82](https://issues.apache.org/jira/browse/THRIFT-82) - Common Lisp support

### csharp
- [THRIFT-4558](https://issues.apache.org/jira/browse/THRIFT-4558) - reserved Csharp keywords are not escaped in some cases
- [THRIFT-4637](https://issues.apache.org/jira/browse/THRIFT-4637) - C# async mode generates incorrect code with inherited services
- [THRIFT-4672](https://issues.apache.org/jira/browse/THRIFT-4672) - IAsyncResult style methods not being supported by certain transports leads to issues in mixed ISync/IAsync use cases
- [THRIFT-4539](https://issues.apache.org/jira/browse/THRIFT-4539) - Allow TBufferedTransport to be used as base class
- [THRIFT-4535](https://issues.apache.org/jira/browse/THRIFT-4535) - XML docs; code cleanup (tabs->spaces; String->string)
- [THRIFT-4492](https://issues.apache.org/jira/browse/THRIFT-4492) - protected ExceptionType type member of TApplicationException cannot be accessed
- [THRIFT-4446](https://issues.apache.org/jira/browse/THRIFT-4446) - JSONProtocol Base64 Encoding Trims Padding
- [THRIFT-4455](https://issues.apache.org/jira/browse/THRIFT-4455) - Missing dispose calls in ThreadedServer & ThreadpoolServer
- [THRIFT-4609](https://issues.apache.org/jira/browse/THRIFT-4609) - keep InnerException wherever appropriate
- [THRIFT-4673](https://issues.apache.org/jira/browse/THRIFT-4673) - IAsyncResult not supported by layered transports (buffered/framed)

### cpp
- [THRIFT-4476](https://issues.apache.org/jira/browse/THRIFT-4476) - Typecasting problem on list items
- [THRIFT-4465](https://issues.apache.org/jira/browse/THRIFT-4465) - TNonblockingServer throwing THRIFT LOGGER: TConnection::workSocket(): THRIFT_EAGAIN (unavailable resources)
- [THRIFT-4680](https://issues.apache.org/jira/browse/THRIFT-4680) - TBufferTransports.h does not compile under Visual Studio 2017
- [THRIFT-4618](https://issues.apache.org/jira/browse/THRIFT-4618) - TNonblockingServer crash because of limitation of select()
- [THRIFT-4620](https://issues.apache.org/jira/browse/THRIFT-4620) - TZlibTransport.cpp doesn't ensure that there is enough space for the zlib flush marker in the buffer.
- [THRIFT-4571](https://issues.apache.org/jira/browse/THRIFT-4571) - ZeroMQ contrib library needs a refresh
- [THRIFT-4559](https://issues.apache.org/jira/browse/THRIFT-4559) - TSSLServerSocket incorrectly prints errors
- [THRIFT-4578](https://issues.apache.org/jira/browse/THRIFT-4578) - Move `TAsyncProtocolProcessor` into main thrift library
- [THRIFT-4418](https://issues.apache.org/jira/browse/THRIFT-4418) - evhttp_connection_new is deprecated; use evhttp_connection_base_new

### compiler
- [THRIFT-4644](https://issues.apache.org/jira/browse/THRIFT-4644) - Compiler cannot be compiled on macOS(maybe also on other platforms with clang)
- [THRIFT-4531](https://issues.apache.org/jira/browse/THRIFT-4531) - Thrift generates wrong Python code for immutable structures with optional members
- [THRIFT-4513](https://issues.apache.org/jira/browse/THRIFT-4513) - thrift generated code is not stable for constants
- [THRIFT-4532](https://issues.apache.org/jira/browse/THRIFT-4532) - Avoid updating Thrift compiler generated code if the output has not changed
- [THRIFT-4400](https://issues.apache.org/jira/browse/THRIFT-4400) - Visual Studio Compiler project should link runtime statically in release builds
- [THRIFT-4399](https://issues.apache.org/jira/browse/THRIFT-4399) - plugin.thrift t_const_value is not used as a union in C++ code -- fix this
- [THRIFT-4496](https://issues.apache.org/jira/browse/THRIFT-4496) - Dealing with language keywords in Thrift (e.g. service method names)
- [THRIFT-4393](https://issues.apache.org/jira/browse/THRIFT-4393) - repeated runs of compiler produce different binary output at plugin interface

### dlang
- [THRIFT-4478](https://issues.apache.org/jira/browse/THRIFT-4478) - Thrift will not build with dlang 2.078 or later
- [THRIFT-4503](https://issues.apache.org/jira/browse/THRIFT-4503) - dlang servers logError on normal client disconnection
- [THRIFT-4308](https://issues.apache.org/jira/browse/THRIFT-4308) - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang

### dart
- [THRIFT-4646](https://issues.apache.org/jira/browse/THRIFT-4646) - Effective Dart and Exceptions
- [THRIFT-4439](https://issues.apache.org/jira/browse/THRIFT-4439) - Shouldn't download dart.deb directly.

### delphi
- [THRIFT-4562](https://issues.apache.org/jira/browse/THRIFT-4562) - Calling wrong exception CTOR leads to "call failed: unknown result" instead of the real exception being thrown
- [THRIFT-4554](https://issues.apache.org/jira/browse/THRIFT-4554) - uncompileable code with member names that are also types under specific conditions
- [THRIFT-4422](https://issues.apache.org/jira/browse/THRIFT-4422) - Add Async implementation via IFuture
- [THRIFT-4485](https://issues.apache.org/jira/browse/THRIFT-4485) - Possible invalid ptr AV with overlapped read/write on pipes
- [THRIFT-4549](https://issues.apache.org/jira/browse/THRIFT-4549) - Thrift exceptions should derive from TException
- [THRIFT-4540](https://issues.apache.org/jira/browse/THRIFT-4540) - buffered transport broken when trying to re-open a formerly closed transport
- [THRIFT-4473](https://issues.apache.org/jira/browse/THRIFT-4473) - Move Thrift.Console.pas out of the Library
- [THRIFT-4490](https://issues.apache.org/jira/browse/THRIFT-4490) - Allow a default service as fallback for multiplex processors connected by old clients
- [THRIFT-4454](https://issues.apache.org/jira/browse/THRIFT-4454) - Large writes/reads may cause range check errors in debug mode
- [THRIFT-4461](https://issues.apache.org/jira/browse/THRIFT-4461) - Compiler directive should match Delphi XE4
- [THRIFT-4462](https://issues.apache.org/jira/browse/THRIFT-4462) - First line in Console duplicated
- [THRIFT-4642](https://issues.apache.org/jira/browse/THRIFT-4642) - FPU ctrl word settings may cause an unexpected "denormalized" error
- [THRIFT-4589](https://issues.apache.org/jira/browse/THRIFT-4589) - HTTP client timeouts are a) incomplete and b) not used at all
- [THRIFT-4590](https://issues.apache.org/jira/browse/THRIFT-4590) - running the test client using HTTP transport leads to "CoInitialize not called"

### erlang
- [THRIFT-4497](https://issues.apache.org/jira/browse/THRIFT-4497) - Erlang records should use map() for map type
- [THRIFT-4495](https://issues.apache.org/jira/browse/THRIFT-4495) - Erlang records should allow 'undefined' for non-required fields
- [THRIFT-4580](https://issues.apache.org/jira/browse/THRIFT-4580) - Fix erlang tutorial unpack on Windows
- [THRIFT-4582](https://issues.apache.org/jira/browse/THRIFT-4582) - Ubuntu Xenial erlang 18.3 "make check" fails

### golang
- [THRIFT-4448](https://issues.apache.org/jira/browse/THRIFT-4448) - Support for golang 1.6 and earlier has been dropped.
- [THRIFT-4253](https://issues.apache.org/jira/browse/THRIFT-4253) - Go generator assigns strings to field in const instead of pointers.
- [THRIFT-4573](https://issues.apache.org/jira/browse/THRIFT-4573) - Unions Field Count Does Not Consider Binary
- [THRIFT-4447](https://issues.apache.org/jira/browse/THRIFT-4447) - Golang: Panic on p.c.Call when using deprecated initializers
- [THRIFT-4650](https://issues.apache.org/jira/browse/THRIFT-4650) - Required field incorrectly marked as set when fieldType does not match
- [THRIFT-4486](https://issues.apache.org/jira/browse/THRIFT-4486) - Golang: -remote.go client cleanup
- [THRIFT-4537](https://issues.apache.org/jira/browse/THRIFT-4537) - TSimpleServer can exit Accept loop with lock still acquired
- [THRIFT-4516](https://issues.apache.org/jira/browse/THRIFT-4516) - Add support for go 1.10
- [THRIFT-4421](https://issues.apache.org/jira/browse/THRIFT-4421) - golang tests rely on gomock, which has change behaviour, causing tests to fail
- [THRIFT-4626](https://issues.apache.org/jira/browse/THRIFT-4626) - Communication crash when using binary/compact protocol and zlib transport
- [THRIFT-4659](https://issues.apache.org/jira/browse/THRIFT-4659) - golang race detected when closing listener socket

### haskell
- [THRIFT-4634](https://issues.apache.org/jira/browse/THRIFT-4634) - Haskell builds with older cabal cannot reconcile complex version requirements

### java
- [THRIFT-4259](https://issues.apache.org/jira/browse/THRIFT-4259) - Thrift does not compile due to Ant Maven task errors
- [THRIFT-1418](https://issues.apache.org/jira/browse/THRIFT-1418) - Compiling Thrift from source: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element
- [THRIFT-4530](https://issues.apache.org/jira/browse/THRIFT-4530) - proposal: add nullability annotations to generated Java code
- [THRIFT-4614](https://issues.apache.org/jira/browse/THRIFT-4614) - Generate missing @Nullable annotations for Java iterator getters
- [THRIFT-4555](https://issues.apache.org/jira/browse/THRIFT-4555) - Getter of binary field in Java creates unnecessary copy
- [THRIFT-3983](https://issues.apache.org/jira/browse/THRIFT-3983) - libthrift is deployed on central with pom packaging instead of jar
- [THRIFT-4294](https://issues.apache.org/jira/browse/THRIFT-4294) - Java Configure Fails for Ant >= 1.10
- [THRIFT-4178](https://issues.apache.org/jira/browse/THRIFT-4178) - Java libraries missing from package when using cmake
- [THRIFT-4120](https://issues.apache.org/jira/browse/THRIFT-4120) - pom files are not generated or provided in the build
- [THRIFT-1507](https://issues.apache.org/jira/browse/THRIFT-1507) - Maven can't download resource from central when behind a proxy and won't use local repository
- [THRIFT-4556](https://issues.apache.org/jira/browse/THRIFT-4556) - Optional rethrow of unhandled exceptions in java processor
- [THRIFT-4337](https://issues.apache.org/jira/browse/THRIFT-4337) - Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters
- [THRIFT-4566](https://issues.apache.org/jira/browse/THRIFT-4566) - Pass message of unhandled exception to optional rethrow.
- [THRIFT-4506](https://issues.apache.org/jira/browse/THRIFT-4506) - Remove assertion in Java SASL code that would be ignored in release builds
- [THRIFT-4470](https://issues.apache.org/jira/browse/THRIFT-4470) - Include popular IDE file templates to gitignore
- [THRIFT-4429](https://issues.apache.org/jira/browse/THRIFT-4429) - Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization
- [THRIFT-3769](https://issues.apache.org/jira/browse/THRIFT-3769) - Fix logic of THRIFT-2268
- [THRIFT-4494](https://issues.apache.org/jira/browse/THRIFT-4494) - Increase Java Socket Buffer Size
- [THRIFT-4499](https://issues.apache.org/jira/browse/THRIFT-4499) - Remove Magic Number In TFIleTransport

### js
- [THRIFT-4406](https://issues.apache.org/jira/browse/THRIFT-4406) - JavaScript: Use modern Promise implementations
- [THRIFT-4625](https://issues.apache.org/jira/browse/THRIFT-4625) - let / const variable decorators for es6 compiler
- [THRIFT-4653](https://issues.apache.org/jira/browse/THRIFT-4653) - ES6 Classes
- [THRIFT-4592](https://issues.apache.org/jira/browse/THRIFT-4592) - JS: readI32 performance on large arrays is very poor in Chrome
- [THRIFT-4509](https://issues.apache.org/jira/browse/THRIFT-4509) - js and nodejs libraries need to be refreshed with current libraries
- [THRIFT-4403](https://issues.apache.org/jira/browse/THRIFT-4403) - thrift.js: Incorrect usage of 'this' in TWebSocketTransport.__onOpen
- [THRIFT-4436](https://issues.apache.org/jira/browse/THRIFT-4436) - Deserialization of nested list discards content
- [THRIFT-4437](https://issues.apache.org/jira/browse/THRIFT-4437) - JS WebSocket client callbacks invoked twice on parallel requests
- [THRIFT-4679](https://issues.apache.org/jira/browse/THRIFT-4679) - Duplicate declaration of InputBufferUnderrunError in lib/nodejs/lib/thrift/json_protocol.js
- [THRIFT-4551](https://issues.apache.org/jira/browse/THRIFT-4551) - Add prettier for consistent JS code formatting

### lua
- [THRIFT-4591](https://issues.apache.org/jira/browse/THRIFT-4591) - lua client uses two write() calls per framed message send
- [THRIFT-3863](https://issues.apache.org/jira/browse/THRIFT-3863) - Can't "make install" Lua Library

### netcore
- [THRIFT-4524](https://issues.apache.org/jira/browse/THRIFT-4524) - .NET Core Server doesn't close properly when cancelled
- [THRIFT-4434](https://issues.apache.org/jira/browse/THRIFT-4434) - Update .NET Core components, add tests for .Net Core library and .Net Core compiler, fix bugs and build process
- [THRIFT-4446](https://issues.apache.org/jira/browse/THRIFT-4446) - JSONProtocol Base64 Encoding Trims Padding

### node.js
- [THRIFT-4225](https://issues.apache.org/jira/browse/THRIFT-4225) - Error handling malformed arguments leaks memory, corrupts transport buffers causing next RPC to fail
- [THRIFT-3950](https://issues.apache.org/jira/browse/THRIFT-3950) - Memory leak while calling oneway method
- [THRIFT-3143](https://issues.apache.org/jira/browse/THRIFT-3143) - add typescript directory support
- [THRIFT-4564](https://issues.apache.org/jira/browse/THRIFT-4564) - TBufferedTransport can leave corrupt data in the buffer
- [THRIFT-4647](https://issues.apache.org/jira/browse/THRIFT-4647) - Node.js Fileserver webroot path
- [THRIFT-4489](https://issues.apache.org/jira/browse/THRIFT-4489) - Unix domain socket support for NodeJS client
- [THRIFT-4443](https://issues.apache.org/jira/browse/THRIFT-4443) - node.js json_protocol throws error in skip function
- [THRIFT-4604](https://issues.apache.org/jira/browse/THRIFT-4604) - NodeJS: Expose Int64 from browser.js for consumption by browser
- [THRIFT-4480](https://issues.apache.org/jira/browse/THRIFT-4480) - NodeJS warning on binary_protocol writeMessageEnd when seqid = 0

### perl
- [THRIFT-4382](https://issues.apache.org/jira/browse/THRIFT-4382) - Replace the use of Perl Indirect Object Syntax calls to new()
- [THRIFT-4471](https://issues.apache.org/jira/browse/THRIFT-4471) - Thrift CPAN release is missing Makefile.PL and the clients are unable to build the module
- [THRIFT-4416](https://issues.apache.org/jira/browse/THRIFT-4416) - Perl CPAN Packaging Improvements

### php
- [THRIFT-4474](https://issues.apache.org/jira/browse/THRIFT-4474) - PHP generator use PSR-4 default
- [THRIFT-4463](https://issues.apache.org/jira/browse/THRIFT-4463) - PHP generated code match PSR-2
- [THRIFT-4373](https://issues.apache.org/jira/browse/THRIFT-4373) - Extending Thrift class results in "Attempt serialize from non-Thrift object"
- [THRIFT-4354](https://issues.apache.org/jira/browse/THRIFT-4354) - TSocket block on read
- [THRIFT-4423](https://issues.apache.org/jira/browse/THRIFT-4423) - migrate php library to psr-4
- [THRIFT-4656](https://issues.apache.org/jira/browse/THRIFT-4656) - infinite loop in latest PHP library
- [THRIFT-4477](https://issues.apache.org/jira/browse/THRIFT-4477) - TBufferedTransport must have underlying transport
- [THRIFT-4475](https://issues.apache.org/jira/browse/THRIFT-4475) - lib/php/test should be checked for PSR-2
- [THRIFT-4498](https://issues.apache.org/jira/browse/THRIFT-4498) - add phpcs back
- [THRIFT-4460](https://issues.apache.org/jira/browse/THRIFT-4460) - php library use PSR-2
- [THRIFT-4641](https://issues.apache.org/jira/browse/THRIFT-4641) - TCurlClient doesn't check for HTTP status code
- [THRIFT-4645](https://issues.apache.org/jira/browse/THRIFT-4645) - TCurlClient: show actual error message when throwing TTransportException
- [THRIFT-4674](https://issues.apache.org/jira/browse/THRIFT-4674) - Add stream context support into PHP/THttpClient
- [THRIFT-4459](https://issues.apache.org/jira/browse/THRIFT-4459) - reduce php library directory depth

### python
- [THRIFT-4670](https://issues.apache.org/jira/browse/THRIFT-4670) - Twisted, slots, and void method fails with "object has no attribute 'success'"
- [THRIFT-4464](https://issues.apache.org/jira/browse/THRIFT-4464) - Potentially server-crashing typo in Python TNonblockingServer
- [THRIFT-4548](https://issues.apache.org/jira/browse/THRIFT-4548) - Supporting TBinaryProtocolAccelerated protocol when using TMultiplexedProcessor in Python
- [THRIFT-4577](https://issues.apache.org/jira/browse/THRIFT-4577) - Outdated cipher string in python unit test
- [THRIFT-4505](https://issues.apache.org/jira/browse/THRIFT-4505) - python build on Vagrant Windows boxes fails
- [THRIFT-4621](https://issues.apache.org/jira/browse/THRIFT-4621) - THeader for Python
- [THRIFT-4668](https://issues.apache.org/jira/browse/THRIFT-4668) - make socket backlog configurable for python
- [THRIFT-4561](https://issues.apache.org/jira/browse/THRIFT-4561) - Python: cleanup socket timeout settings

### ruby
- [THRIFT-4289](https://issues.apache.org/jira/browse/THRIFT-4289) - Thrift RSpec test suite fails with Ruby 2.4.x due to Fixnum deprecation
- [THRIFT-4342](https://issues.apache.org/jira/browse/THRIFT-4342) - Support ruby rspec 3
- [THRIFT-4525](https://issues.apache.org/jira/browse/THRIFT-4525) - Add ssl socket option to ruby cross tests
- [THRIFT-4450](https://issues.apache.org/jira/browse/THRIFT-4450) - Add seek support to TCompactInputProtocol in Rust
- [THRIFT-4631](https://issues.apache.org/jira/browse/THRIFT-4631) - Codegen Creates Invalid Ruby for Recursive Structs
- [THRIFT-4472](https://issues.apache.org/jira/browse/THRIFT-4472) - Fix the genspec for ruby so it does not complain about an invalid license

### rust
- [THRIFT-4662](https://issues.apache.org/jira/browse/THRIFT-4662) - Rust const string calls function at compile time
- [THRIFT-4661](https://issues.apache.org/jira/browse/THRIFT-4661) - Rust enum name wrong case in generated structs
- [THRIFT-4617](https://issues.apache.org/jira/browse/THRIFT-4617) - Avoid generating conflicting struct names in Rust code
- [THRIFT-4529](https://issues.apache.org/jira/browse/THRIFT-4529) - Rust generation should include #![allow(non_snake_case)] or force conform to Rust style guidelines
- [THRIFT-4390](https://issues.apache.org/jira/browse/THRIFT-4390) - Rust binary protocol and buffered transport cannot handle writes above 4096 bytes
- [THRIFT-4419](https://issues.apache.org/jira/browse/THRIFT-4419) - Rust framed transport cannot handle writes above 4096 bytes
- [THRIFT-4658](https://issues.apache.org/jira/browse/THRIFT-4658) - Rust's TBinaryInputProtocol fails when strict is false
- [THRIFT-4187](https://issues.apache.org/jira/browse/THRIFT-4187) - Dart -> Rust Framed cross tests fail
- [THRIFT-4664](https://issues.apache.org/jira/browse/THRIFT-4664) - Rust cannot create ReadHalf/WriteHalf to implement custom tranports
- [THRIFT-4665](https://issues.apache.org/jira/browse/THRIFT-4665) - Keep Rust library up-to-date on crates.io

### swift (new language support in 0.12.0)
- [THRIFT-3773](https://issues.apache.org/jira/browse/THRIFT-3773) - Swift Library

### test suite
- [THRIFT-4515](https://issues.apache.org/jira/browse/THRIFT-4515) - Gracefully shutdown cross-test servers to fully test teardown
- [THRIFT-4085](https://issues.apache.org/jira/browse/THRIFT-4085) - Add .NET Core to the make cross standard test suite
- [THRIFT-4358](https://issues.apache.org/jira/browse/THRIFT-4358) - Add unix domain sockets in ruby to cross test) - code exists

### typescript (new language support in 0.12.0)
- [THRIFT-3143](https://issues.apache.org/jira/browse/THRIFT-3143) - add typescript directory support

## 0.11.0

Released 2017-DEC-27

### Sub-task
- [THRIFT-2733](https://issues.apache.org/jira/browse/THRIFT-2733) - Erlang coding standards
- [THRIFT-2740](https://issues.apache.org/jira/browse/THRIFT-2740) - Perl coding standards
- [THRIFT-3610](https://issues.apache.org/jira/browse/THRIFT-3610) - Streamline exception handling in Python server handler
- [THRIFT-3686](https://issues.apache.org/jira/browse/THRIFT-3686) - Java processor should report internal error on uncaught exception
- [THRIFT-4049](https://issues.apache.org/jira/browse/THRIFT-4049) - Skip() should throw TProtocolException.INVALID_DATA on unknown data types
- [THRIFT-4053](https://issues.apache.org/jira/browse/THRIFT-4053) - Skip() should throw TProtocolException.INVALID_DATA on unknown data types
- [THRIFT-4136](https://issues.apache.org/jira/browse/THRIFT-4136) - Align is_binary() method with is_string() to simplify those checks
- [THRIFT-4137](https://issues.apache.org/jira/browse/THRIFT-4137) - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler
- [THRIFT-4138](https://issues.apache.org/jira/browse/THRIFT-4138) - Fix remaining undefined behavior invalid vptr casts in C++ library
- [THRIFT-4296](https://issues.apache.org/jira/browse/THRIFT-4296) - Fix Ubuntu Xenial build environment for the python language
- [THRIFT-4298](https://issues.apache.org/jira/browse/THRIFT-4298) - Fix Ubuntu Xenial build environment for the go 1.6 language
- [THRIFT-4299](https://issues.apache.org/jira/browse/THRIFT-4299) - Fix Ubuntu Xenial build environment for the D language
- [THRIFT-4300](https://issues.apache.org/jira/browse/THRIFT-4300) - Fix make cross in Ubuntu Xenial docker environment, once all language support issues are fixed
- [THRIFT-4302](https://issues.apache.org/jira/browse/THRIFT-4302) - Fix Ubuntu Xenial make cross testing for lua and php7
- [THRIFT-4398](https://issues.apache.org/jira/browse/THRIFT-4398) - Update EXTRA_DIST for "make dist"

### Bug
- [THRIFT-381](https://issues.apache.org/jira/browse/THRIFT-381) - Fail fast if configure detects C++ problems
- [THRIFT-1677](https://issues.apache.org/jira/browse/THRIFT-1677) - MinGW support broken
- [THRIFT-1805](https://issues.apache.org/jira/browse/THRIFT-1805) - Thrift should not swallow ALL exceptions
- [THRIFT-2026](https://issues.apache.org/jira/browse/THRIFT-2026) - Fix TCompactProtocol 64 bit builds
- [THRIFT-2642](https://issues.apache.org/jira/browse/THRIFT-2642) - Recursive structs don't work in python
- [THRIFT-2889](https://issues.apache.org/jira/browse/THRIFT-2889) - stable release 0.9.2, erlang tutorial broken
- [THRIFT-2913](https://issues.apache.org/jira/browse/THRIFT-2913) - Ruby Server Thrift::ThreadPoolServer should serve inside a thread
- [THRIFT-2998](https://issues.apache.org/jira/browse/THRIFT-2998) - Node.js: Missing header from http request
- [THRIFT-3000](https://issues.apache.org/jira/browse/THRIFT-3000) - .NET implementation has trouble with mixed IP modes
- [THRIFT-3281](https://issues.apache.org/jira/browse/THRIFT-3281) - Travis CI build passed but the log says BUILD FAILED
- [THRIFT-3358](https://issues.apache.org/jira/browse/THRIFT-3358) - Makefile:1362: *** missing separator. Stop.
- [THRIFT-3600](https://issues.apache.org/jira/browse/THRIFT-3600) - Make TTwisted server send exception on unexpected handler error
- [THRIFT-3602](https://issues.apache.org/jira/browse/THRIFT-3602) - Make Tornado server send exception on unexpected handler error
- [THRIFT-3657](https://issues.apache.org/jira/browse/THRIFT-3657) - D TFileWriterTransport close should use non-priority send
- [THRIFT-3700](https://issues.apache.org/jira/browse/THRIFT-3700) - Go Map has wrong default value when optional
- [THRIFT-3703](https://issues.apache.org/jira/browse/THRIFT-3703) - Unions Field Count Does Not Consider Map/Set/List Fields
- [THRIFT-3730](https://issues.apache.org/jira/browse/THRIFT-3730) - server log error twice
- [THRIFT-3778](https://issues.apache.org/jira/browse/THRIFT-3778) - go client can not pass method parameter to server of other language if no field_id is given
- [THRIFT-3784](https://issues.apache.org/jira/browse/THRIFT-3784) - thrift-maven-plugin generates invalid include directories for IDL in dependency JARs
- [THRIFT-3801](https://issues.apache.org/jira/browse/THRIFT-3801) - Node Thrift client throws exception with multiplexer and responses that are bigger than a single buffer
- [THRIFT-3821](https://issues.apache.org/jira/browse/THRIFT-3821) - TMemoryBuffer buffer may overflow when resizing
- [THRIFT-3832](https://issues.apache.org/jira/browse/THRIFT-3832) - Thrift version 0.9.3 example on Windows, Visual Studio, linking errors during compiling
- [THRIFT-3847](https://issues.apache.org/jira/browse/THRIFT-3847) - thrift/config.h includes a #define for VERSION which will likely conflict with existing user environment or code
- [THRIFT-3873](https://issues.apache.org/jira/browse/THRIFT-3873) - Fix various build warnings when using Visual Studio
- [THRIFT-3891](https://issues.apache.org/jira/browse/THRIFT-3891) - TNonblockingServer configured with more than one IO threads does not always return from serve() upon stop()
- [THRIFT-3892](https://issues.apache.org/jira/browse/THRIFT-3892) - Thrift uses TLS SNI extension provided by OpenSSL library. Older version of OpenSSL(< 0.9.8f) may create problem because they do not support 'SSL_set_tlsext_host_name()'.
- [THRIFT-3895](https://issues.apache.org/jira/browse/THRIFT-3895) - Build fails using Java 1.8 with Ant < 1.9
- [THRIFT-3896](https://issues.apache.org/jira/browse/THRIFT-3896) - map data with number string key cannot access that deserialized by php extension
- [THRIFT-3938](https://issues.apache.org/jira/browse/THRIFT-3938) - Python TNonblockingServer does not work with SSL
- [THRIFT-3944](https://issues.apache.org/jira/browse/THRIFT-3944) - TSSLSocket has dead code in checkHandshake
- [THRIFT-3946](https://issues.apache.org/jira/browse/THRIFT-3946) - Java 1.5 compatibility broken for binary fields (java5 option)
- [THRIFT-3960](https://issues.apache.org/jira/browse/THRIFT-3960) - Inherited services in Lua generator are not named correctly
- [THRIFT-3962](https://issues.apache.org/jira/browse/THRIFT-3962) - Ant build.xml broken on Windows for Java library
- [THRIFT-3963](https://issues.apache.org/jira/browse/THRIFT-3963) - Thrift.cabal filename does not match module name
- [THRIFT-3967](https://issues.apache.org/jira/browse/THRIFT-3967) - gobject/gparam.h:166:33: warning: enumerator value for ‘G_PARAM_DEPRECATED’ is not an integer constant expression
- [THRIFT-3968](https://issues.apache.org/jira/browse/THRIFT-3968) - Deserializing empty string/binary fields
- [THRIFT-3974](https://issues.apache.org/jira/browse/THRIFT-3974) - Using clang-3.8 and ThreadSanitizer on the concurrency_test claims bad PThread behavior
- [THRIFT-3984](https://issues.apache.org/jira/browse/THRIFT-3984) - PHP7 extension causes segfault
- [THRIFT-4008](https://issues.apache.org/jira/browse/THRIFT-4008) - broken ci due to upstream dependency versioning break
- [THRIFT-4009](https://issues.apache.org/jira/browse/THRIFT-4009) - Use @implementer instead of implements in TTwisted.py
- [THRIFT-4010](https://issues.apache.org/jira/browse/THRIFT-4010) - Q.fcall messing up with *this* pointer inside called function
- [THRIFT-4011](https://issues.apache.org/jira/browse/THRIFT-4011) - Sets of Thrift structs generate Go code that can't be serialized to JSON
- [THRIFT-4012](https://issues.apache.org/jira/browse/THRIFT-4012) - Python Twisted implementation uses implements, not compatible with Py3
- [THRIFT-4014](https://issues.apache.org/jira/browse/THRIFT-4014) - align C# meta data in AssemblyInfo.cs
- [THRIFT-4015](https://issues.apache.org/jira/browse/THRIFT-4015) - Fix wrongly spelled "Thirft"s
- [THRIFT-4016](https://issues.apache.org/jira/browse/THRIFT-4016) - testInsanity() impl does not conform to test spec in ThriftTest.thrift
- [THRIFT-4023](https://issues.apache.org/jira/browse/THRIFT-4023) - Skip unexpected field types on read/write
- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types
- [THRIFT-4026](https://issues.apache.org/jira/browse/THRIFT-4026) - TSSLSocket doesn't work with Python < 2.7.9
- [THRIFT-4029](https://issues.apache.org/jira/browse/THRIFT-4029) - Accelerated protocols do not build from thrift-py 0.10.0 on PyPI
- [THRIFT-4031](https://issues.apache.org/jira/browse/THRIFT-4031) - Go plugin generates invalid code for lists of typedef'ed built-in types
- [THRIFT-4033](https://issues.apache.org/jira/browse/THRIFT-4033) - Default build WITH_PLUGIN=ON for all builds results in packaging errors
- [THRIFT-4034](https://issues.apache.org/jira/browse/THRIFT-4034) - CMake doesn't work to build compiler on MacOS
- [THRIFT-4036](https://issues.apache.org/jira/browse/THRIFT-4036) - Add .NET Core environment/build support to the docker image
- [THRIFT-4038](https://issues.apache.org/jira/browse/THRIFT-4038) - socket check: checking an unsigned number against >= 0 never fails
- [THRIFT-4042](https://issues.apache.org/jira/browse/THRIFT-4042) - ExtractionError when using accelerated thrift in a multiprocess test
- [THRIFT-4043](https://issues.apache.org/jira/browse/THRIFT-4043) - thrift perl debian package is placing files in the wrong place
- [THRIFT-4044](https://issues.apache.org/jira/browse/THRIFT-4044) - Build job 17 failing on every pull request; hspec core (haskell) 2.4 issue
- [THRIFT-4046](https://issues.apache.org/jira/browse/THRIFT-4046) - MinGW with gcc 6.2 does not compile on Windows
- [THRIFT-4060](https://issues.apache.org/jira/browse/THRIFT-4060) - Thrift printTo ostream overload mechanism breaks down when types are nested
- [THRIFT-4062](https://issues.apache.org/jira/browse/THRIFT-4062) - Remove debug print from TServiceClient
- [THRIFT-4065](https://issues.apache.org/jira/browse/THRIFT-4065) - Document Perl ForkingServer signal restriction imposed by THRIFT-3848 and remove unnecessary code
- [THRIFT-4068](https://issues.apache.org/jira/browse/THRIFT-4068) - A code comment in Java ServerSocket is wrong around accept()
- [THRIFT-4073](https://issues.apache.org/jira/browse/THRIFT-4073) - enum files are still being generated with unused imports
- [THRIFT-4076](https://issues.apache.org/jira/browse/THRIFT-4076) - Appveyor builds failing because ant 1.9.8 was removed from apache servers
- [THRIFT-4077](https://issues.apache.org/jira/browse/THRIFT-4077) - AI_ADDRCONFIG redefined after recent change to PlatformSocket header
- [THRIFT-4079](https://issues.apache.org/jira/browse/THRIFT-4079) - Generated perl code that returns structures from included thrift files is missing a necessary use clause
- [THRIFT-4087](https://issues.apache.org/jira/browse/THRIFT-4087) - Spurious exception destroying TThreadedServer because of incorrect join() call
- [THRIFT-4102](https://issues.apache.org/jira/browse/THRIFT-4102) - TBufferedTransport performance issue since 0.10.0
- [THRIFT-4106](https://issues.apache.org/jira/browse/THRIFT-4106) - concurrency_test fails randomly
- [THRIFT-4108](https://issues.apache.org/jira/browse/THRIFT-4108) - c_glib thrift ssl has multiple bugs and deprecated functions
- [THRIFT-4109](https://issues.apache.org/jira/browse/THRIFT-4109) - Configure Script uses string comparison for versions
- [THRIFT-4129](https://issues.apache.org/jira/browse/THRIFT-4129) - C++ TNonblockingServer fd leak when failing to dispatch new connections
- [THRIFT-4131](https://issues.apache.org/jira/browse/THRIFT-4131) - Javascript with WebSocket handles oneway methods wrong
- [THRIFT-4134](https://issues.apache.org/jira/browse/THRIFT-4134) - Fix remaining undefined behavior invalid vptr casts
- [THRIFT-4140](https://issues.apache.org/jira/browse/THRIFT-4140) - Use of non-thread-safe function gmtime()
- [THRIFT-4141](https://issues.apache.org/jira/browse/THRIFT-4141) - Installation of haxe in docker files refers to a redirect link and fails
- [THRIFT-4147](https://issues.apache.org/jira/browse/THRIFT-4147) - Rust: protocol should accept transports with non-static lifetime
- [THRIFT-4148](https://issues.apache.org/jira/browse/THRIFT-4148) - [maven-thrift-plugin] compile error while import a thrift in dependency jar file.
- [THRIFT-4149](https://issues.apache.org/jira/browse/THRIFT-4149) - System.out pollutes log files
- [THRIFT-4154](https://issues.apache.org/jira/browse/THRIFT-4154) - PHP close() of a TSocket needs to close any type of socket
- [THRIFT-4158](https://issues.apache.org/jira/browse/THRIFT-4158) - minor issue in README-MSYS2.md
- [THRIFT-4159](https://issues.apache.org/jira/browse/THRIFT-4159) - Building tests fails on MSYS2 (MinGW64) due to a (small?) linker error
- [THRIFT-4160](https://issues.apache.org/jira/browse/THRIFT-4160) - TNonblocking server fix use of closed/freed connections
- [THRIFT-4161](https://issues.apache.org/jira/browse/THRIFT-4161) - TNonBlocking server using uninitialized event in error paths
- [THRIFT-4162](https://issues.apache.org/jira/browse/THRIFT-4162) - TNonBlocking handling of TSockets in error state is incorrect after fd is closed
- [THRIFT-4164](https://issues.apache.org/jira/browse/THRIFT-4164) - Core in TSSLSocket cleanupOpenSSL when destroying a mutex used by openssl
- [THRIFT-4165](https://issues.apache.org/jira/browse/THRIFT-4165) - C++ build has many warnings under c++03 due to recent changes, cmake needs better platform-independent language level control
- [THRIFT-4166](https://issues.apache.org/jira/browse/THRIFT-4166) - Recent fix to remove boost::lexical_cast usage broke VS2010
- [THRIFT-4167](https://issues.apache.org/jira/browse/THRIFT-4167) - Missing compile flag
- [THRIFT-4170](https://issues.apache.org/jira/browse/THRIFT-4170) - Support lua 5.1 or earlier properly for object length determination
- [THRIFT-4172](https://issues.apache.org/jira/browse/THRIFT-4172) - node.js tutorial client does not import assert, connection issues are not handled properly
- [THRIFT-4177](https://issues.apache.org/jira/browse/THRIFT-4177) - Java compiler produces deep copy constructor that could make shallow copy instead
- [THRIFT-4184](https://issues.apache.org/jira/browse/THRIFT-4184) - Building on Appveyor: invalid escape sequence \L
- [THRIFT-4185](https://issues.apache.org/jira/browse/THRIFT-4185) - fb303 counter encoding fix
- [THRIFT-4189](https://issues.apache.org/jira/browse/THRIFT-4189) - Framed/buffered transport Dispose() does not dispose the nested transport
- [THRIFT-4193](https://issues.apache.org/jira/browse/THRIFT-4193) - Lower the default maxReadBufferBytes for non-blocking servers
- [THRIFT-4195](https://issues.apache.org/jira/browse/THRIFT-4195) - Compilation to GO produces broken code
- [THRIFT-4196](https://issues.apache.org/jira/browse/THRIFT-4196) - Cannot generate recursive Rust types
- [THRIFT-4204](https://issues.apache.org/jira/browse/THRIFT-4204) - typo in compact spec
- [THRIFT-4206](https://issues.apache.org/jira/browse/THRIFT-4206) - Strings in container fields are not decoded properly with py:dynamic and py:utf8strings
- [THRIFT-4208](https://issues.apache.org/jira/browse/THRIFT-4208) - C# NamedPipesServer not really working in some scenarios
- [THRIFT-4211](https://issues.apache.org/jira/browse/THRIFT-4211) - Fix GError glib management under Thrift
- [THRIFT-4212](https://issues.apache.org/jira/browse/THRIFT-4212) - c_glib flush tries to close SSL even if socket is invalid
- [THRIFT-4213](https://issues.apache.org/jira/browse/THRIFT-4213) - Travis build fails at curl -sSL https://www.npmjs.com/install.sh | sh
- [THRIFT-4215](https://issues.apache.org/jira/browse/THRIFT-4215) - Golang TTransportFactory Pattern Squelches Errors
- [THRIFT-4216](https://issues.apache.org/jira/browse/THRIFT-4216) - Golang Http Clients Do Not Respect User Options
- [THRIFT-4218](https://issues.apache.org/jira/browse/THRIFT-4218) - Set TCP_NODELAY for PHP client socket
- [THRIFT-4219](https://issues.apache.org/jira/browse/THRIFT-4219) - Golang HTTP clients created with Nil buffer
- [THRIFT-4231](https://issues.apache.org/jira/browse/THRIFT-4231) - TJSONProtocol throws unexpected non-Thrift-exception on null strings
- [THRIFT-4232](https://issues.apache.org/jira/browse/THRIFT-4232) - ./configure does bad ant version check
- [THRIFT-4234](https://issues.apache.org/jira/browse/THRIFT-4234) - Travis build fails cross language tests with "Unsupported security protocol type"
- [THRIFT-4237](https://issues.apache.org/jira/browse/THRIFT-4237) - Go TServerSocket Race Conditions
- [THRIFT-4240](https://issues.apache.org/jira/browse/THRIFT-4240) - Go TSimpleServer does not close properly
- [THRIFT-4243](https://issues.apache.org/jira/browse/THRIFT-4243) - Go TSimpleServer race on wait in Stop() method
- [THRIFT-4245](https://issues.apache.org/jira/browse/THRIFT-4245) - Golang TFramedTransport's writeBuffer increases if writes to transport failed
- [THRIFT-4246](https://issues.apache.org/jira/browse/THRIFT-4246) - Sequence number mismatch on multiplexed clients
- [THRIFT-4247](https://issues.apache.org/jira/browse/THRIFT-4247) - Compile fails with openssl 1.1
- [THRIFT-4248](https://issues.apache.org/jira/browse/THRIFT-4248) - Compile fails) - strncpy, memcmp, memset not declared in src/thrift/transport/TSSLSocket.cpp
- [THRIFT-4251](https://issues.apache.org/jira/browse/THRIFT-4251) - Java Epoll Selector Bug
- [THRIFT-4257](https://issues.apache.org/jira/browse/THRIFT-4257) - Typescript async callbacks do not provide the correct types
- [THRIFT-4258](https://issues.apache.org/jira/browse/THRIFT-4258) - Boost/std thread wrapping faultiness
- [THRIFT-4260](https://issues.apache.org/jira/browse/THRIFT-4260) - Go context generation issue. Context is parameter in Interface not in implementation
- [THRIFT-4261](https://issues.apache.org/jira/browse/THRIFT-4261) - Go context generation issue: breaking change in generated code regarding thrift.TProcessorFunction interface
- [THRIFT-4262](https://issues.apache.org/jira/browse/THRIFT-4262) - Invalid binding to InterlockedCompareExchange64() with 64-bit targets
- [THRIFT-4263](https://issues.apache.org/jira/browse/THRIFT-4263) - Fix use after free bug for thrown exceptions
- [THRIFT-4266](https://issues.apache.org/jira/browse/THRIFT-4266) - Erlang library throws during skipping fields of composite type (maps, lists, structs, sets)
- [THRIFT-4268](https://issues.apache.org/jira/browse/THRIFT-4268) - Erlang library emits debugging output in transport layer
- [THRIFT-4273](https://issues.apache.org/jira/browse/THRIFT-4273) - erlang:now/0: Deprecated BIF.
- [THRIFT-4274](https://issues.apache.org/jira/browse/THRIFT-4274) - Python feature tests for SSL/TLS failing
- [THRIFT-4279](https://issues.apache.org/jira/browse/THRIFT-4279) - Wrong path in include directive in generated Thrift sources
- [THRIFT-4283](https://issues.apache.org/jira/browse/THRIFT-4283) - TNamedPipeServer race condition in interrupt
- [THRIFT-4284](https://issues.apache.org/jira/browse/THRIFT-4284) - File contains a NBSP: lib/nodejs/lib/thrift/web_server.js
- [THRIFT-4290](https://issues.apache.org/jira/browse/THRIFT-4290) - C# nullable option generates invalid code for non-required enum field with default value
- [THRIFT-4292](https://issues.apache.org/jira/browse/THRIFT-4292) - TimerManager::remove() is not implemented
- [THRIFT-4307](https://issues.apache.org/jira/browse/THRIFT-4307) - Make ssl-open timeout effective in golang client
- [THRIFT-4312](https://issues.apache.org/jira/browse/THRIFT-4312) - Erlang client cannot connect to Python server: exception error: econnrefused
- [THRIFT-4313](https://issues.apache.org/jira/browse/THRIFT-4313) - Program code of the Erlang tutorial files contain syntax errors
- [THRIFT-4316](https://issues.apache.org/jira/browse/THRIFT-4316) - TByteBuffer.java will read too much data if a previous read returns fewer bytes than requested
- [THRIFT-4319](https://issues.apache.org/jira/browse/THRIFT-4319) - command line switch for "evhttp" incorrectly resolved to anon pipes
- [THRIFT-4323](https://issues.apache.org/jira/browse/THRIFT-4323) - range check errors or NPE in edge cases
- [THRIFT-4324](https://issues.apache.org/jira/browse/THRIFT-4324) - field names can conflict with local vars in generated code
- [THRIFT-4328](https://issues.apache.org/jira/browse/THRIFT-4328) - Travis CI builds are timing out (job 1) and haxe builds are failing since 9/11
- [THRIFT-4329](https://issues.apache.org/jira/browse/THRIFT-4329) - c_glib Doesn't have a multiplexed processor
- [THRIFT-4331](https://issues.apache.org/jira/browse/THRIFT-4331) - C++: TSSLSockets bug in handling huge messages, bug in handling polling
- [THRIFT-4332](https://issues.apache.org/jira/browse/THRIFT-4332) - Binary protocol has memory leaks
- [THRIFT-4334](https://issues.apache.org/jira/browse/THRIFT-4334) - Perl indentation incorrect when defaulting field attribute to a struct
- [THRIFT-4339](https://issues.apache.org/jira/browse/THRIFT-4339) - Thrift Framed Transport in Erlang crashes server when client disconnects
- [THRIFT-4340](https://issues.apache.org/jira/browse/THRIFT-4340) - Erlang fix a crash on client close
- [THRIFT-4355](https://issues.apache.org/jira/browse/THRIFT-4355) - Javascript indentation incorrect when defaulting field attribute to a struct
- [THRIFT-4356](https://issues.apache.org/jira/browse/THRIFT-4356) - thrift_protocol call Transport cause Segmentation fault
- [THRIFT-4359](https://issues.apache.org/jira/browse/THRIFT-4359) - Haxe compiler looks like it is producing incorrect code for map or set key that is binary type
- [THRIFT-4362](https://issues.apache.org/jira/browse/THRIFT-4362) - Missing size-check can lead to huge memory allocation
- [THRIFT-4364](https://issues.apache.org/jira/browse/THRIFT-4364) - Website contributing guide erroneously recommends submitting patches in JIRA
- [THRIFT-4365](https://issues.apache.org/jira/browse/THRIFT-4365) - Perl generated code uses indirect object syntax, which occasionally causes compilation errors.
- [THRIFT-4367](https://issues.apache.org/jira/browse/THRIFT-4367) - python TProcessor.process is missing "self"
- [THRIFT-4370](https://issues.apache.org/jira/browse/THRIFT-4370) - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures
- [THRIFT-4372](https://issues.apache.org/jira/browse/THRIFT-4372) - Pipe write operations across a network are limited to 65,535 bytes per write.
- [THRIFT-4374](https://issues.apache.org/jira/browse/THRIFT-4374) - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE
- [THRIFT-4375](https://issues.apache.org/jira/browse/THRIFT-4375) - TMemory throw bad_alloc due to counter overflow
- [THRIFT-4376](https://issues.apache.org/jira/browse/THRIFT-4376) - Coverity high impact issue resolution
- [THRIFT-4377](https://issues.apache.org/jira/browse/THRIFT-4377) - haxe. socket handles leak in TSimpleServer
- [THRIFT-4381](https://issues.apache.org/jira/browse/THRIFT-4381) - Wrong isset bitfield value after transmission
- [THRIFT-4385](https://issues.apache.org/jira/browse/THRIFT-4385) - Go remote client -u flag is broken
- [THRIFT-4392](https://issues.apache.org/jira/browse/THRIFT-4392) - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator
- [THRIFT-4395](https://issues.apache.org/jira/browse/THRIFT-4395) - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20
- [THRIFT-4396](https://issues.apache.org/jira/browse/THRIFT-4396) - inconsistent (or plain wrong) version numbers in master/trunk

### Documentation
- [THRIFT-4157](https://issues.apache.org/jira/browse/THRIFT-4157) - outdated readme about Haxe installation on Linux

### Improvement
- [THRIFT-105](https://issues.apache.org/jira/browse/THRIFT-105) - make a thrift_spec for a structures with negative tags
- [THRIFT-281](https://issues.apache.org/jira/browse/THRIFT-281) - Cocoa library code needs comments, badly
- [THRIFT-775](https://issues.apache.org/jira/browse/THRIFT-775) - performance improvements for Perl
- [THRIFT-2221](https://issues.apache.org/jira/browse/THRIFT-2221) - Generate c++ code with std::shared_ptr instead of boost::shared_ptr.
- [THRIFT-2364](https://issues.apache.org/jira/browse/THRIFT-2364) - OCaml: Use Oasis exclusively for build process
- [THRIFT-2504](https://issues.apache.org/jira/browse/THRIFT-2504) - TMultiplexedProcessor should allow registering default processor called if no service name is present
- [THRIFT-3207](https://issues.apache.org/jira/browse/THRIFT-3207) - Enable build with OpenSSL 1.1.0 series
- [THRIFT-3272](https://issues.apache.org/jira/browse/THRIFT-3272) - Perl SSL Authentication Support
- [THRIFT-3357](https://issues.apache.org/jira/browse/THRIFT-3357) - Generate EnumSet/EnumMap where elements/keys are enums
- [THRIFT-3369](https://issues.apache.org/jira/browse/THRIFT-3369) - Implement SSL/TLS support on C with c_glib
- [THRIFT-3467](https://issues.apache.org/jira/browse/THRIFT-3467) - Go Maps for Thrift Sets Should Have Values of Type struct{}
- [THRIFT-3580](https://issues.apache.org/jira/browse/THRIFT-3580) - THeader for Haskell
- [THRIFT-3627](https://issues.apache.org/jira/browse/THRIFT-3627) - Missing basic code style consistency of JavaScript.
- [THRIFT-3706](https://issues.apache.org/jira/browse/THRIFT-3706) - There's no support for Multiplexed protocol on c_glib library
- [THRIFT-3766](https://issues.apache.org/jira/browse/THRIFT-3766) - Add getUnderlyingTransport() to TZlibTransport
- [THRIFT-3776](https://issues.apache.org/jira/browse/THRIFT-3776) - Go code from multiple thrift files with the same namespace
- [THRIFT-3823](https://issues.apache.org/jira/browse/THRIFT-3823) - Escape documentation while generating non escaped documetation
- [THRIFT-3854](https://issues.apache.org/jira/browse/THRIFT-3854) - allow users to clear read buffers
- [THRIFT-3859](https://issues.apache.org/jira/browse/THRIFT-3859) - Unix Domain Socket Support in Objective-C
- [THRIFT-3921](https://issues.apache.org/jira/browse/THRIFT-3921) - C++ code should print enums as strings
- [THRIFT-3926](https://issues.apache.org/jira/browse/THRIFT-3926) - There should be an error emitted when http status code is not 200
- [THRIFT-4007](https://issues.apache.org/jira/browse/THRIFT-4007) - Micro-optimization of TTransport.py
- [THRIFT-4040](https://issues.apache.org/jira/browse/THRIFT-4040) - Add real cause of TNonblockingServerSocket error to exception
- [THRIFT-4064](https://issues.apache.org/jira/browse/THRIFT-4064) - Update node library dependencies
- [THRIFT-4069](https://issues.apache.org/jira/browse/THRIFT-4069) - All perl packages should have proper namespace, version syntax, and use proper thrift exceptions
- [THRIFT-4071](https://issues.apache.org/jira/browse/THRIFT-4071) - Consolidate the Travis CI jobs where possible to put less stress on the Apache Foundation's allocation of CI build slaves
- [THRIFT-4072](https://issues.apache.org/jira/browse/THRIFT-4072) - Add the possibility to send custom headers in TCurlClient
- [THRIFT-4075](https://issues.apache.org/jira/browse/THRIFT-4075) - Better MinGW support for headers-only boost (without thread library)
- [THRIFT-4081](https://issues.apache.org/jira/browse/THRIFT-4081) - Provide a MinGW 64-bit Appveyor CI build for better pull request validation
- [THRIFT-4084](https://issues.apache.org/jira/browse/THRIFT-4084) - Improve SSL security in thrift by adding a make cross client that checks to make sure SSLv3 protocol cannot be negotiated
- [THRIFT-4095](https://issues.apache.org/jira/browse/THRIFT-4095) - Add multiplexed protocol to Travis CI for make cross
- [THRIFT-4099](https://issues.apache.org/jira/browse/THRIFT-4099) - Auto-derive Hash for generated Rust structs
- [THRIFT-4110](https://issues.apache.org/jira/browse/THRIFT-4110) - The debian build files do not produce a "-dbg" package for debug symbols of libthrift0
- [THRIFT-4114](https://issues.apache.org/jira/browse/THRIFT-4114) - Space after '///' in doc comments
- [THRIFT-4126](https://issues.apache.org/jira/browse/THRIFT-4126) - Validate objects in php extension
- [THRIFT-4130](https://issues.apache.org/jira/browse/THRIFT-4130) - Ensure Apache Http connection is released back to pool after use
- [THRIFT-4151](https://issues.apache.org/jira/browse/THRIFT-4151) - Thrift Mutex Contention Profiling (pthreads) should be disabled by default
- [THRIFT-4176](https://issues.apache.org/jira/browse/THRIFT-4176) - Implement a threaded and threadpool server type for Rust
- [THRIFT-4183](https://issues.apache.org/jira/browse/THRIFT-4183) - Named pipe client blocks forever on Open() when there is no server at the other end
- [THRIFT-4190](https://issues.apache.org/jira/browse/THRIFT-4190) - improve C# TThreadPoolServer defaults
- [THRIFT-4197](https://issues.apache.org/jira/browse/THRIFT-4197) - Implement transparent gzip compression for HTTP transport
- [THRIFT-4198](https://issues.apache.org/jira/browse/THRIFT-4198) - Ruby should log Thrift internal errors to global logger
- [THRIFT-4203](https://issues.apache.org/jira/browse/THRIFT-4203) - thrift server stop gracefully
- [THRIFT-4205](https://issues.apache.org/jira/browse/THRIFT-4205) - c_glib is not linking against glib + gobject
- [THRIFT-4209](https://issues.apache.org/jira/browse/THRIFT-4209) - warning CS0414 in T[TLS]ServerSocket.cs
- [THRIFT-4210](https://issues.apache.org/jira/browse/THRIFT-4210) - include Thrift.45.csproj into CI runs
- [THRIFT-4217](https://issues.apache.org/jira/browse/THRIFT-4217) - HttpClient should support gzip and deflate
- [THRIFT-4222](https://issues.apache.org/jira/browse/THRIFT-4222) - Support Unix Domain Sockets in Golang TServerSocket
- [THRIFT-4233](https://issues.apache.org/jira/browse/THRIFT-4233) - Make THsHaServer.invoker available (get method only) in inherited classes
- [THRIFT-4236](https://issues.apache.org/jira/browse/THRIFT-4236) - Support context in go generated code.
- [THRIFT-4238](https://issues.apache.org/jira/browse/THRIFT-4238) - JSON generator: make annotation-aware
- [THRIFT-4269](https://issues.apache.org/jira/browse/THRIFT-4269) - Don't append '.' to Erlang namespace if it ends in '_'.
- [THRIFT-4270](https://issues.apache.org/jira/browse/THRIFT-4270) - Generate Erlang mapping functions for const maps and lists
- [THRIFT-4275](https://issues.apache.org/jira/browse/THRIFT-4275) - Add support for zope.interface only, apart from twisted support.
- [THRIFT-4285](https://issues.apache.org/jira/browse/THRIFT-4285) - Pull generated send/recv into library to allow behaviour to be customised
- [THRIFT-4287](https://issues.apache.org/jira/browse/THRIFT-4287) - Add c++ compiler "no_skeleton" flag option
- [THRIFT-4288](https://issues.apache.org/jira/browse/THRIFT-4288) - Implement logging levels properly for node.js
- [THRIFT-4295](https://issues.apache.org/jira/browse/THRIFT-4295) - Refresh the Docker image file suite for Ubuntu, Debian, and CentOS
- [THRIFT-4305](https://issues.apache.org/jira/browse/THRIFT-4305) - Emit ddoc for generated items
- [THRIFT-4306](https://issues.apache.org/jira/browse/THRIFT-4306) - Thrift imports not replicated to D service output
- [THRIFT-4315](https://issues.apache.org/jira/browse/THRIFT-4315) - Add default message for TApplicationException
- [THRIFT-4318](https://issues.apache.org/jira/browse/THRIFT-4318) - Delphi performance improvements
- [THRIFT-4325](https://issues.apache.org/jira/browse/THRIFT-4325) - Simplify automake cross compilation by relying on one global THRIFT compiler path
- [THRIFT-4327](https://issues.apache.org/jira/browse/THRIFT-4327) - Improve TimerManager API to allow removing specific task
- [THRIFT-4330](https://issues.apache.org/jira/browse/THRIFT-4330) - Allow unused crates in Rust files
- [THRIFT-4333](https://issues.apache.org/jira/browse/THRIFT-4333) - Erlang tutorial examples are using a different port (9999)
- [THRIFT-4343](https://issues.apache.org/jira/browse/THRIFT-4343) - Change CI builds to use node.js 8.x LTS once available
- [THRIFT-4345](https://issues.apache.org/jira/browse/THRIFT-4345) - Create a docker build environment that uses the minimum supported language levels
- [THRIFT-4346](https://issues.apache.org/jira/browse/THRIFT-4346) - Allow Zlib transport factory to wrap other transports
- [THRIFT-4348](https://issues.apache.org/jira/browse/THRIFT-4348) - Perl HTTP Client custom HTTP headers
- [THRIFT-4350](https://issues.apache.org/jira/browse/THRIFT-4350) - Update netcore build for dotnet 2.0 sdk and make cross validation
- [THRIFT-4351](https://issues.apache.org/jira/browse/THRIFT-4351) - Use Travis CI Build Stages to optimize the CI build
- [THRIFT-4353](https://issues.apache.org/jira/browse/THRIFT-4353) - cannot read via thrift_protocol at server side
- [THRIFT-4378](https://issues.apache.org/jira/browse/THRIFT-4378) - add set stopTimeoutUnit method to TThreadPoolServer

### New Feature
- [THRIFT-750](https://issues.apache.org/jira/browse/THRIFT-750) - C++ Compiler Virtual Function Option
- [THRIFT-2945](https://issues.apache.org/jira/browse/THRIFT-2945) - Implement support for Rust language
- [THRIFT-3857](https://issues.apache.org/jira/browse/THRIFT-3857) - thrift js:node compiler support an object as parameter not an instance of struct
- [THRIFT-3933](https://issues.apache.org/jira/browse/THRIFT-3933) - Port official C# .NET library for Thrift to C# .NET Core library
- [THRIFT-4039](https://issues.apache.org/jira/browse/THRIFT-4039) - Update of Apache Thrift .Net Core lib
- [THRIFT-4113](https://issues.apache.org/jira/browse/THRIFT-4113) - Provide a buffer transport for reading/writing in memory byte stream

### Question
- [THRIFT-2956](https://issues.apache.org/jira/browse/THRIFT-2956) - autoconf) - possibly undefined macro) - AC_PROG_BISON
- [THRIFT-4223](https://issues.apache.org/jira/browse/THRIFT-4223) - Add support to the isServing() method for the C++ library

### Task
- [THRIFT-3622](https://issues.apache.org/jira/browse/THRIFT-3622) - Fix deprecated uses of std::auto_ptr
- [THRIFT-4028](https://issues.apache.org/jira/browse/THRIFT-4028) - Please remove System.out.format from the source code
- [THRIFT-4186](https://issues.apache.org/jira/browse/THRIFT-4186) - Build and test rust client in Travis

### Test
- [THRIFT-4264](https://issues.apache.org/jira/browse/THRIFT-4264) - PHP) - Support both shared & static linking of sockets library

### Wish
- [THRIFT-4344](https://issues.apache.org/jira/browse/THRIFT-4344) - Define and maintain the minimum language level for all languages in one place

## 0.10.0

### Bug
- [THRIFT-1840](https://issues.apache.org/jira/browse/THRIFT-1840) - Thrift Generated Code Causes Global Variable Leaks
- [THRIFT-1828](https://issues.apache.org/jira/browse/THRIFT-1828) - moc_TQTcpServer.cpp was removed from source tree but is in thrift-0.9.0.tar.gz
- [THRIFT-1790](https://issues.apache.org/jira/browse/THRIFT-1790) - cocoa: Duplicate interface definition error
- [THRIFT-1776](https://issues.apache.org/jira/browse/THRIFT-1776) - TPipeServer should implement "listen", so that TServerEventHandler preServe will work right
- [THRIFT-1351](https://issues.apache.org/jira/browse/THRIFT-1351) - Compiler does not care about binary strings
- [THRIFT-1229](https://issues.apache.org/jira/browse/THRIFT-1229) - Python fastbinary.c can not handle unicode as generated python code
- [THRIFT-749](https://issues.apache.org/jira/browse/THRIFT-749) - C++ TBufferedTransports do not flush their buffers on delete
- [THRIFT-747](https://issues.apache.org/jira/browse/THRIFT-747) - C++ TSocket->close calls shutdown breaking forked parent process
- [THRIFT-732](https://issues.apache.org/jira/browse/THRIFT-732) - server exits abnormally when client calls send_xxx function without calling recv_xxx function
- [THRIFT-3942](https://issues.apache.org/jira/browse/THRIFT-3942) - TSSLSocket does not honor send and receive timeouts
- [THRIFT-3941](https://issues.apache.org/jira/browse/THRIFT-3941) - WinXP version of thrift_poll() relies on undefined behavior by passing a destructed variable to select()
- [THRIFT-3940](https://issues.apache.org/jira/browse/THRIFT-3940) - Visual Studio project file for compiler is broken
- [THRIFT-3943](https://issues.apache.org/jira/browse/THRIFT-3943) - Coverity Scan identified some high severity defects
- [THRIFT-3929](https://issues.apache.org/jira/browse/THRIFT-3929) - PHP "nsglobal" Option Results in Syntax Error in Generated Code (Trailing Backslash)
- [THRIFT-3936](https://issues.apache.org/jira/browse/THRIFT-3936) - Cannot compile 0.10.0 development tip with VS2013 and earlier (snprintf, uint32_t)
- [THRIFT-3935](https://issues.apache.org/jira/browse/THRIFT-3935) - Incorrect skipping of map and set
- [THRIFT-3920](https://issues.apache.org/jira/browse/THRIFT-3920) - Ruby: Ensuring that HTTP failures will clear the http transport outbuf var
- [THRIFT-3919](https://issues.apache.org/jira/browse/THRIFT-3919) - C# TTLSServerSocket does not use clientTimeout
- [THRIFT-3917](https://issues.apache.org/jira/browse/THRIFT-3917) - Check backports.ssl_match_hostname module version
- [THRIFT-3909](https://issues.apache.org/jira/browse/THRIFT-3909) - Fix c_glib static lib CMake build
- [THRIFT-3904](https://issues.apache.org/jira/browse/THRIFT-3904) - Typo in node tutorial leads to wrong transport being used
- [THRIFT-3848](https://issues.apache.org/jira/browse/THRIFT-3848) - As an implementer of a perl socket server, I do not want to have to remember to ignore SIGCHLD for it to work properly
- [THRIFT-3844](https://issues.apache.org/jira/browse/THRIFT-3844) - thrift_protocol cannot compile in 7.0.7
- [THRIFT-3843](https://issues.apache.org/jira/browse/THRIFT-3843) - integer issues with Haxe PHP targets cause ZigZag encoding to fail
- [THRIFT-3842](https://issues.apache.org/jira/browse/THRIFT-3842) - Dart generates incorrect code for a const struct
- [THRIFT-3841](https://issues.apache.org/jira/browse/THRIFT-3841) - dart compact protocol incorrectly serializes/deserialized doubles
- [THRIFT-3708](https://issues.apache.org/jira/browse/THRIFT-3708) - NameError: global name 'TProtocol' is not defined
- [THRIFT-3704](https://issues.apache.org/jira/browse/THRIFT-3704) - "TConnectedClient died: Could not refill buffer" message shown when using HTTP Server
- [THRIFT-3678](https://issues.apache.org/jira/browse/THRIFT-3678) - Fix javadoc errors on JDK 8
- [THRIFT-3014](https://issues.apache.org/jira/browse/THRIFT-3014) - AppVeyor support
- [THRIFT-2994](https://issues.apache.org/jira/browse/THRIFT-2994) - Node.js TJSONProtocol cannot be used for object serialization.
- [THRIFT-2974](https://issues.apache.org/jira/browse/THRIFT-2974) - writeToParcel throws NPE for optional enum fields
- [THRIFT-2948](https://issues.apache.org/jira/browse/THRIFT-2948) - Python TJSONProtocol doesn't handle structs with binary fields containing invalid unicode.
- [THRIFT-2845](https://issues.apache.org/jira/browse/THRIFT-2845) - ChildService.Plo: No such file or directory
- [THRIFT-3276](https://issues.apache.org/jira/browse/THRIFT-3276) - Binary data does not decode correctly using the TJSONProtocol when the base64 encoded data is padded.
- [THRIFT-3253](https://issues.apache.org/jira/browse/THRIFT-3253) - Using latest version of D gives deprecation notices
- [THRIFT-2883](https://issues.apache.org/jira/browse/THRIFT-2883) - TTwisted.py, during ConnectionLost processing: exceptions.RuntimeError: dictionary changed size during iteration
- [THRIFT-2019](https://issues.apache.org/jira/browse/THRIFT-2019) - Writing on a disconnected socket on Mac causes SIG PIPE
- [THRIFT-2020](https://issues.apache.org/jira/browse/THRIFT-2020) - Thrift library has some empty files that haven't really been deleted
- [THRIFT-2049](https://issues.apache.org/jira/browse/THRIFT-2049) - Go compiler doesn't build on native Windows
- [THRIFT-2024](https://issues.apache.org/jira/browse/THRIFT-2024) - TServer.cpp warns on 64-bit platforms about truncating an rlim_t into an int
- [THRIFT-2023](https://issues.apache.org/jira/browse/THRIFT-2023) - gettimeofday implementation on Windows errors when no time zone is passed in.
- [THRIFT-2022](https://issues.apache.org/jira/browse/THRIFT-2022) - CoB and dense code generation still uses TR1 bind, even though that doesn't work with clang
- [THRIFT-2027](https://issues.apache.org/jira/browse/THRIFT-2027) - Minor 64-bit and NOMINMAX issues in C++ library
- [THRIFT-2156](https://issues.apache.org/jira/browse/THRIFT-2156) - TServerSocket::listen() is throwing exceptions with misleading information
- [THRIFT-2154](https://issues.apache.org/jira/browse/THRIFT-2154) - Missing #deepCopy should return T
- [THRIFT-3157](https://issues.apache.org/jira/browse/THRIFT-3157) - TBase signature should be TBase, F extends TFieldIdEnum>
- [THRIFT-3156](https://issues.apache.org/jira/browse/THRIFT-3156) - Node TLS: server executes processing logic two full times
- [THRIFT-3154](https://issues.apache.org/jira/browse/THRIFT-3154) - tutorial/py.tornado throw EOF exception
- [THRIFT-3063](https://issues.apache.org/jira/browse/THRIFT-3063) - C++ build -Wunused-parameter warnings on processor_test, TransportTest
- [THRIFT-3056](https://issues.apache.org/jira/browse/THRIFT-3056) - Add string/collection length limits for Python protocol readers
- [THRIFT-3237](https://issues.apache.org/jira/browse/THRIFT-3237) - Fix TNamedPipeServer::createNamedPipe memory leak
- [THRIFT-3233](https://issues.apache.org/jira/browse/THRIFT-3233) - Fix C++ ThreadManager::Impl::removeWorker worker join
- [THRIFT-3232](https://issues.apache.org/jira/browse/THRIFT-3232) - Cannot deserialize json messages created with fieldNamesAsString
- [THRIFT-3206](https://issues.apache.org/jira/browse/THRIFT-3206) - Fix Visual Studio build failure due 'pthread_self': identifier not found
- [THRIFT-3200](https://issues.apache.org/jira/browse/THRIFT-3200) - JS and nodejs do not encode JSON protocol binary fields as base64
- [THRIFT-3199](https://issues.apache.org/jira/browse/THRIFT-3199) - Exception field has basic metadata
- [THRIFT-3182](https://issues.apache.org/jira/browse/THRIFT-3182) - TFramedTransport is in an invalid state after frame size exception
- [THRIFT-2536](https://issues.apache.org/jira/browse/THRIFT-2536) - new TSocket, uninitialised value reported by valgrind
- [THRIFT-2527](https://issues.apache.org/jira/browse/THRIFT-2527) - Apache Thrift IDL Compiler code generated for Node.js should be jshint clean
- [THRIFT-2519](https://issues.apache.org/jira/browse/THRIFT-2519) - "processor" class is not being generated
- [THRIFT-2431](https://issues.apache.org/jira/browse/THRIFT-2431) - TFileTransportTest fails with "check delta < XXX failed"
- [THRIFT-2708](https://issues.apache.org/jira/browse/THRIFT-2708) - Erlang library does not support "oneway" message type
- [THRIFT-3377](https://issues.apache.org/jira/browse/THRIFT-3377) - Deep copy is actually shallow when using typedef members
- [THRIFT-3376](https://issues.apache.org/jira/browse/THRIFT-3376) - C# and Python JSON protocol double values lose precision
- [THRIFT-3373](https://issues.apache.org/jira/browse/THRIFT-3373) - Various fixes for cross test servers and clients
- [THRIFT-3370](https://issues.apache.org/jira/browse/THRIFT-3370) - errno extern variable redefined. Not compiling for Android
- [THRIFT-3379](https://issues.apache.org/jira/browse/THRIFT-3379) -  Potential out of range panic in Go JSON protocols
- [THRIFT-3371](https://issues.apache.org/jira/browse/THRIFT-3371) - Abstract namespace Unix domain sockets broken in C++
- [THRIFT-3380](https://issues.apache.org/jira/browse/THRIFT-3380) - nodejs: 0.9.2 -> 0.9.3 upgrade breaks Protocol and Transport requires
- [THRIFT-3367](https://issues.apache.org/jira/browse/THRIFT-3367) - Fix bad links to coding_standards.md #634
- [THRIFT-3401](https://issues.apache.org/jira/browse/THRIFT-3401) - Nested collections emit Objective-C code that cannot compile
- [THRIFT-3403](https://issues.apache.org/jira/browse/THRIFT-3403) - JSON String reader doesn't recognize UTF-16 surrogate pairs
- [THRIFT-3362](https://issues.apache.org/jira/browse/THRIFT-3362) - make check fails for C++ at the SecurityTest
- [THRIFT-3395](https://issues.apache.org/jira/browse/THRIFT-3395) - Cocoa compiler produces corrupt code when boxing enums inside map.
- [THRIFT-3394](https://issues.apache.org/jira/browse/THRIFT-3394) - compiler generates uncompilable code
- [THRIFT-3388](https://issues.apache.org/jira/browse/THRIFT-3388) - hash doesn't work on set/list
- [THRIFT-3391](https://issues.apache.org/jira/browse/THRIFT-3391) - Wrong bool formatting in test server
- [THRIFT-3390](https://issues.apache.org/jira/browse/THRIFT-3390) - TTornado server doesn't handle closed connections properly
- [THRIFT-3382](https://issues.apache.org/jira/browse/THRIFT-3382) - TBase class for C++ Library
- [THRIFT-3392](https://issues.apache.org/jira/browse/THRIFT-3392) - Java TZlibTransport does not close its wrapper streams upon close()
- [THRIFT-3383](https://issues.apache.org/jira/browse/THRIFT-3383) - i64 related warnings
- [THRIFT-3386](https://issues.apache.org/jira/browse/THRIFT-3386) - misc. warnings with make check
- [THRIFT-3385](https://issues.apache.org/jira/browse/THRIFT-3385) - warning: format ‘%lu’ expects ‘long unsigned int’, but has type ‘std::basic_string::size_type {aka unsigned int}
- [THRIFT-3355](https://issues.apache.org/jira/browse/THRIFT-3355) - npm WARN package.json thrift@1.0.0-dev No license field.
- [THRIFT-3360](https://issues.apache.org/jira/browse/THRIFT-3360) - Improve cross test servers and clients further
- [THRIFT-3359](https://issues.apache.org/jira/browse/THRIFT-3359) - Binary field incompatibilities
- [THRIFT-3354](https://issues.apache.org/jira/browse/THRIFT-3354) - Fix word-extraction substr bug in initialism code
- [THRIFT-3350](https://issues.apache.org/jira/browse/THRIFT-3350) - Python JSON protocol does not encode binary as Base64
- [THRIFT-3577](https://issues.apache.org/jira/browse/THRIFT-3577) - assertion failed at line 512 of testcontainertest.c
- [THRIFT-3576](https://issues.apache.org/jira/browse/THRIFT-3576) - Boost test --log_format arg does not accept lowercase
- [THRIFT-3575](https://issues.apache.org/jira/browse/THRIFT-3575) - Go compiler tries to use unexported library methods when using read_write_private
- [THRIFT-3574](https://issues.apache.org/jira/browse/THRIFT-3574) - Cocoa generator makes uncompilable imports
- [THRIFT-3570](https://issues.apache.org/jira/browse/THRIFT-3570) - Remove duplicate instances that are added by upstream
- [THRIFT-3571](https://issues.apache.org/jira/browse/THRIFT-3571) - Make feature test result browsable
- [THRIFT-3569](https://issues.apache.org/jira/browse/THRIFT-3569) - c_glib protocols do not check number of bytes read by transport
- [THRIFT-3568](https://issues.apache.org/jira/browse/THRIFT-3568) - THeader server crashes on readSlow
- [THRIFT-3567](https://issues.apache.org/jira/browse/THRIFT-3567) - GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
- [THRIFT-3566](https://issues.apache.org/jira/browse/THRIFT-3566) - C++/Qt: TQTcpServerTest::test_communicate() is never executed
- [THRIFT-3564](https://issues.apache.org/jira/browse/THRIFT-3564) - C++/Qt: potential core dump in TQTcpServer in case an exception occurs in TAsyncProcessor::process()
- [THRIFT-3558](https://issues.apache.org/jira/browse/THRIFT-3558) - typos in c_glib tests
- [THRIFT-3559](https://issues.apache.org/jira/browse/THRIFT-3559) - Fix awkward extra semi-colons with Cocoa container literals
- [THRIFT-3555](https://issues.apache.org/jira/browse/THRIFT-3555) - 'configure' script does not honor --with-openssl= for libcrypto for BN_init
- [THRIFT-3554](https://issues.apache.org/jira/browse/THRIFT-3554) - Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct"
- [THRIFT-3552](https://issues.apache.org/jira/browse/THRIFT-3552) - glib_c Memory Leak
- [THRIFT-3551](https://issues.apache.org/jira/browse/THRIFT-3551) - Thrift perl library missing package declaration
- [THRIFT-3549](https://issues.apache.org/jira/browse/THRIFT-3549) - Exceptions are not properly stringified in Perl library
- [THRIFT-3546](https://issues.apache.org/jira/browse/THRIFT-3546) - NodeJS code should not be namespaced (and is currently not strict-mode compliant)
- [THRIFT-3545](https://issues.apache.org/jira/browse/THRIFT-3545) - Container type literals do not compile
- [THRIFT-3538](https://issues.apache.org/jira/browse/THRIFT-3538) - Remove UnboundMethodType in TProtocolDecorator
- [THRIFT-3536](https://issues.apache.org/jira/browse/THRIFT-3536) - Error 'char' does not contain a definition for 'IsLowSurrogate' for WP7 target
- [THRIFT-3534](https://issues.apache.org/jira/browse/THRIFT-3534) - Link error when building with Qt5
- [THRIFT-3533](https://issues.apache.org/jira/browse/THRIFT-3533) - Can not send nil pointer as service method argument
- [THRIFT-3507](https://issues.apache.org/jira/browse/THRIFT-3507) - THttpClient does not use proxy from http_proxy, https_proxy environment variables
- [THRIFT-3502](https://issues.apache.org/jira/browse/THRIFT-3502) - C++ TServerSocket passes small buffer to getsockname
- [THRIFT-3501](https://issues.apache.org/jira/browse/THRIFT-3501) - Forward slash in comment causes compiler error
- [THRIFT-3498](https://issues.apache.org/jira/browse/THRIFT-3498) - C++ library assumes optional function pthread_attr_setschedpolicy is available
- [THRIFT-3497](https://issues.apache.org/jira/browse/THRIFT-3497) - Build fails with "invalid use of incomplete type"
- [THRIFT-3496](https://issues.apache.org/jira/browse/THRIFT-3496) - C++: Cob style client fails when sending a consecutive request
- [THRIFT-3493](https://issues.apache.org/jira/browse/THRIFT-3493) - libthrift does not compile on windows using visual studio
- [THRIFT-3488](https://issues.apache.org/jira/browse/THRIFT-3488) - warning: unused variable 'program'
- [THRIFT-3489](https://issues.apache.org/jira/browse/THRIFT-3489) - warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
- [THRIFT-3487](https://issues.apache.org/jira/browse/THRIFT-3487) - Full support for newer Delphi versions
- [THRIFT-3528](https://issues.apache.org/jira/browse/THRIFT-3528) - Fix warnings in thrift.ll
- [THRIFT-3527](https://issues.apache.org/jira/browse/THRIFT-3527) - -gen py:dynamic,utf8strings ignores utf8strings option
- [THRIFT-3526](https://issues.apache.org/jira/browse/THRIFT-3526) - Code generated by py:utf8strings does not work for Python3
- [THRIFT-3524](https://issues.apache.org/jira/browse/THRIFT-3524) - dcc32 warning "W1000 Symbol 'IsLowSurrogate' is deprecated: 'Use TCharHelper'" in Thrift.Protocol.JSON.pas
- [THRIFT-3525](https://issues.apache.org/jira/browse/THRIFT-3525) - py:dynamic fails to handle binary list/set/map element
- [THRIFT-3521](https://issues.apache.org/jira/browse/THRIFT-3521) - TSimpleJSONProtocolTest is not deterministic (fails when run on JDK 8)
- [THRIFT-3520](https://issues.apache.org/jira/browse/THRIFT-3520) - Dart TSocket onError stream should be typed as Object
- [THRIFT-3519](https://issues.apache.org/jira/browse/THRIFT-3519) - fastbinary does not work with -gen py:utf8strings
- [THRIFT-3518](https://issues.apache.org/jira/browse/THRIFT-3518) - TConcurrentClientSyncInfo files were missing for Visual Studio
- [THRIFT-3512](https://issues.apache.org/jira/browse/THRIFT-3512) - c_glib: Build fails due to missing features.h
- [THRIFT-3483](https://issues.apache.org/jira/browse/THRIFT-3483) - Incorrect empty binary handling introduced by THRIFT-3359
- [THRIFT-3479](https://issues.apache.org/jira/browse/THRIFT-3479) - Oneway calls should not return exceptions to clients
- [THRIFT-3478](https://issues.apache.org/jira/browse/THRIFT-3478) - Restore dropped method to THsHaServer.java
- [THRIFT-3477](https://issues.apache.org/jira/browse/THRIFT-3477) - Parser fails on enum item that starts with 'E' letter and continues with number
- [THRIFT-3476](https://issues.apache.org/jira/browse/THRIFT-3476) - Missing include in ./src/thrift/protocol/TJSONProtocol.cpp
- [THRIFT-3474](https://issues.apache.org/jira/browse/THRIFT-3474) - Docker: thrift-compiler
- [THRIFT-3473](https://issues.apache.org/jira/browse/THRIFT-3473) - When "optional' is used with a struct member, C++ server seems to not return it correctly
- [THRIFT-3468](https://issues.apache.org/jira/browse/THRIFT-3468) - Dart TSocketTransport onError handler is too restrictive
- [THRIFT-3451](https://issues.apache.org/jira/browse/THRIFT-3451) - thrift_protocol PHP extension missing config.m4 file
- [THRIFT-3456](https://issues.apache.org/jira/browse/THRIFT-3456) - rounding issue in static assert
- [THRIFT-3455](https://issues.apache.org/jira/browse/THRIFT-3455) - struct write method's return value is incorrect
- [THRIFT-3454](https://issues.apache.org/jira/browse/THRIFT-3454) - Python Tornado tutorial is broken
- [THRIFT-3463](https://issues.apache.org/jira/browse/THRIFT-3463) - Java can't be disabled in CMake build
- [THRIFT-3450](https://issues.apache.org/jira/browse/THRIFT-3450) - NPE when using SSL
- [THRIFT-3449](https://issues.apache.org/jira/browse/THRIFT-3449) - TBaseAsyncProcessor fb.responseReady() never called for oneway functions
- [THRIFT-3471](https://issues.apache.org/jira/browse/THRIFT-3471) - Dart generator does not handle uppercase argument names
- [THRIFT-3470](https://issues.apache.org/jira/browse/THRIFT-3470) - Sporadic timeouts with pipes
- [THRIFT-3465](https://issues.apache.org/jira/browse/THRIFT-3465) - Go Code With Complex Const Initializer Compilation Depends On Struct Order
- [THRIFT-3464](https://issues.apache.org/jira/browse/THRIFT-3464) - Fix several defects in c_glib code generator
- [THRIFT-3462](https://issues.apache.org/jira/browse/THRIFT-3462) - Cocoa generates Incorrect #import header names
- [THRIFT-3453](https://issues.apache.org/jira/browse/THRIFT-3453) - remove rat_exclude
- [THRIFT-3418](https://issues.apache.org/jira/browse/THRIFT-3418) - Use of ciphers in ssl.wrap_socket() breaks python 2.6 compatibility
- [THRIFT-3417](https://issues.apache.org/jira/browse/THRIFT-3417) - "namespace xsd" is not really working
- [THRIFT-3413](https://issues.apache.org/jira/browse/THRIFT-3413) - Thrift code generation bug in Go when extending service
- [THRIFT-3420](https://issues.apache.org/jira/browse/THRIFT-3420) - C++: TSSLSockets are not interruptable
- [THRIFT-3415](https://issues.apache.org/jira/browse/THRIFT-3415) - include unistd.h conditionally
- [THRIFT-3414](https://issues.apache.org/jira/browse/THRIFT-3414) - #include  in THeaderTransport.h breaks windows build
- [THRIFT-3411](https://issues.apache.org/jira/browse/THRIFT-3411) - Go generates remotes with wrong package qualifiers when including
- [THRIFT-3430](https://issues.apache.org/jira/browse/THRIFT-3430) - Go THttpClient does not read HTTP response body to completion when closing
- [THRIFT-3423](https://issues.apache.org/jira/browse/THRIFT-3423) - First call to thrift_transport:read_exact fails to dispatch correct function
- [THRIFT-3422](https://issues.apache.org/jira/browse/THRIFT-3422) - Go TServerSocket doesn't close on Interrupt
- [THRIFT-3421](https://issues.apache.org/jira/browse/THRIFT-3421) - rebar as dependency instead of bundling (was:  rebar fails if PWD contains Unicode)
- [THRIFT-3428](https://issues.apache.org/jira/browse/THRIFT-3428) - Go test fails when running make check
- [THRIFT-3445](https://issues.apache.org/jira/browse/THRIFT-3445) - Throwable messages are hidden from JVM stack trace output
- [THRIFT-3443](https://issues.apache.org/jira/browse/THRIFT-3443) - Thrift include can generate uncompilable code
- [THRIFT-3444](https://issues.apache.org/jira/browse/THRIFT-3444) - Large 64 bit Integer does not preserve value through Node.js JSONProtocol
- [THRIFT-3436](https://issues.apache.org/jira/browse/THRIFT-3436) - misc. cross test issues with UTF-8 path names
- [THRIFT-3435](https://issues.apache.org/jira/browse/THRIFT-3435) - Put generated Java code for fullcamel tests in a separate package/namespace
- [THRIFT-3433](https://issues.apache.org/jira/browse/THRIFT-3433) - Doubles aren't interpreted correctly
- [THRIFT-3437](https://issues.apache.org/jira/browse/THRIFT-3437) - Mingw-w64 build fail
- [THRIFT-3434](https://issues.apache.org/jira/browse/THRIFT-3434) - Dart generator produces empty name in pubspec.yaml for includes without namespaces
- [THRIFT-3408](https://issues.apache.org/jira/browse/THRIFT-3408) - JSON generator emits incorrect types
- [THRIFT-3406](https://issues.apache.org/jira/browse/THRIFT-3406) - Cocoa client should not schedule streams on main runloop
- [THRIFT-3404](https://issues.apache.org/jira/browse/THRIFT-3404) - JSON String reader doesn't recognize UTF-16 surrogate pair
- [THRIFT-3636](https://issues.apache.org/jira/browse/THRIFT-3636) - Double precision is not fully preserved in C++ TJSONProtocol
- [THRIFT-3632](https://issues.apache.org/jira/browse/THRIFT-3632) - c_glib testserialization fails with glib assertion
- [THRIFT-3619](https://issues.apache.org/jira/browse/THRIFT-3619) - Using Thrift 0.9.3 with googletest on Linux gcc 4.9 / C++11
- [THRIFT-3617](https://issues.apache.org/jira/browse/THRIFT-3617) - CMake does not build gv/xml generators
- [THRIFT-3615](https://issues.apache.org/jira/browse/THRIFT-3615) - Fix Python SSL client resource leak on connection failure
- [THRIFT-3616](https://issues.apache.org/jira/browse/THRIFT-3616) - lib/py/test/test_sslsocket.py is flaky
- [THRIFT-3643](https://issues.apache.org/jira/browse/THRIFT-3643) - Perl SSL server crushes if a client disconnect without handshake
- [THRIFT-3639](https://issues.apache.org/jira/browse/THRIFT-3639) - C# Thrift library forces TLS 1.0, thwarting TLS 1.2 usage
- [THRIFT-3633](https://issues.apache.org/jira/browse/THRIFT-3633) - Travis "C C++) - GCC" build was using clang
- [THRIFT-3634](https://issues.apache.org/jira/browse/THRIFT-3634) - Fix Python TSocket resource leak on connection failure
- [THRIFT-3630](https://issues.apache.org/jira/browse/THRIFT-3630) - Debian/Ubuntu install docs need an update
- [THRIFT-3629](https://issues.apache.org/jira/browse/THRIFT-3629) - Parser sets exitcode on errors, but generator does not
- [THRIFT-3608](https://issues.apache.org/jira/browse/THRIFT-3608) - lib/cpp/test/SecurityTest is flaky in jenkins Thrift-precommit build.
- [THRIFT-3601](https://issues.apache.org/jira/browse/THRIFT-3601) - Better conformance to PEP8 for generated code
- [THRIFT-3599](https://issues.apache.org/jira/browse/THRIFT-3599) - Validate client IP address against cert's SubjectAltName
- [THRIFT-3598](https://issues.apache.org/jira/browse/THRIFT-3598) - TBufferedTransport doesn't instantiate client connection
- [THRIFT-3597](https://issues.apache.org/jira/browse/THRIFT-3597) - `make check` hangs in go tests
- [THRIFT-3589](https://issues.apache.org/jira/browse/THRIFT-3589) - Dart generator uses wrong name in constructor for uppercase arguments with defaults
- [THRIFT-3588](https://issues.apache.org/jira/browse/THRIFT-3588) - Using TypeScript with --noImplicitAny fails
- [THRIFT-3584](https://issues.apache.org/jira/browse/THRIFT-3584) - boolean false value cannot be transferred
- [THRIFT-3578](https://issues.apache.org/jira/browse/THRIFT-3578) - Make THeaderTransport detect TCompact framed and unframed
- [THRIFT-3323](https://issues.apache.org/jira/browse/THRIFT-3323) - Python library does not handle escaped forward slash ("/") in JSON
- [THRIFT-3322](https://issues.apache.org/jira/browse/THRIFT-3322) - CMake generated "make check" failes on python_test
- [THRIFT-3321](https://issues.apache.org/jira/browse/THRIFT-3321) - Thrift can't be added as a subdirectory of another CMake-based project
- [THRIFT-3314](https://issues.apache.org/jira/browse/THRIFT-3314) - Dots in file names of includes causes dots in javascript variable names
- [THRIFT-3307](https://issues.apache.org/jira/browse/THRIFT-3307) - Segfault in Ruby serializer
- [THRIFT-3309](https://issues.apache.org/jira/browse/THRIFT-3309) - Missing TConstant.php in /lib/php/Makefile.am
- [THRIFT-3810](https://issues.apache.org/jira/browse/THRIFT-3810) - unresolved external symbol public: virtual void __cdecl apache::thrift::server::TServerFramework::serve(void)
- [THRIFT-3736](https://issues.apache.org/jira/browse/THRIFT-3736) - C++ library build fails if OpenSSL does not surrpot SSLv3
- [THRIFT-3878](https://issues.apache.org/jira/browse/THRIFT-3878) - Compile error in TSSLSocket.cpp with new OpenSSL [CRYPTO_num_locks]
- [THRIFT-3949](https://issues.apache.org/jira/browse/THRIFT-3949) - missing make dist entry for compiler/cpp/test
- [THRIFT-449](https://issues.apache.org/jira/browse/THRIFT-449) - The wire format of the JSON Protocol may not always be valid JSON if it contains non-UTF8 encoded strings
- [THRIFT-162](https://issues.apache.org/jira/browse/THRIFT-162) - Thrift structures are unhashable, preventing them from being used as set elements
- [THRIFT-3961](https://issues.apache.org/jira/browse/THRIFT-3961) - TConnectedClient does not terminate the connection to the client if an exception while processing the received message occures.
- [THRIFT-3881](https://issues.apache.org/jira/browse/THRIFT-3881) - Travis CI builds are failing due to docker failures (three retries, and gives up)
- [THRIFT-3937](https://issues.apache.org/jira/browse/THRIFT-3937) - Cannot compile 0.10.0 development tip with gcc-4.6.x
- [THRIFT-3964](https://issues.apache.org/jira/browse/THRIFT-3964) - Unsupported mechanism type ????? due to dependency on default OS-dependent charset
- [THRIFT-3038](https://issues.apache.org/jira/browse/THRIFT-3038) - Use of volatile in cpp library
- [THRIFT-3301](https://issues.apache.org/jira/browse/THRIFT-3301) - Java generated code uses imports that can lead to class name collisions with IDL defined types
- [THRIFT-3348](https://issues.apache.org/jira/browse/THRIFT-3348) - PHP TCompactProtocol bool&int64 readvalue bug
- [THRIFT-3955](https://issues.apache.org/jira/browse/THRIFT-3955) - TThreadedServer Memory Leak
- [THRIFT-3829](https://issues.apache.org/jira/browse/THRIFT-3829) - Thrift does not install Python Libraries if Twisted is not installed
- [THRIFT-3932](https://issues.apache.org/jira/browse/THRIFT-3932) - C++ ThreadManager has a rare termination race
- [THRIFT-3828](https://issues.apache.org/jira/browse/THRIFT-3828) - cmake fails when Boost_INCLUDE_DIRS (and other variables passed to include_directories()) is empty
- [THRIFT-3958](https://issues.apache.org/jira/browse/THRIFT-3958) - CMake WITH_MT option for windows static runtime linking does not support the cmake build type RelWithDebInfo
- [THRIFT-3957](https://issues.apache.org/jira/browse/THRIFT-3957) - TConnectedClient does not disconnect from clients when their timeout is reached.
- [THRIFT-3953](https://issues.apache.org/jira/browse/THRIFT-3953) - TSSLSocket::close should handle exceptions from waitForEvent because it is called by the destructor.
- [THRIFT-3977](https://issues.apache.org/jira/browse/THRIFT-3977) - PHP extension creates undefined values when deserializing sets
- [THRIFT-3947](https://issues.apache.org/jira/browse/THRIFT-3947) - sockaddr type isn't always large enough for the return of getsockname
- [THRIFT-2755](https://issues.apache.org/jira/browse/THRIFT-2755) - ThreadSanitizer reports data race in ThreadManager::Impl::addWorker
- [THRIFT-3948](https://issues.apache.org/jira/browse/THRIFT-3948) - errno is not the correct method of getting the error in windows
- [THRIFT-4008](https://issues.apache.org/jira/browse/THRIFT-4008) - broken ci due to upstream dependency versioning break
- [THRIFT-3999](https://issues.apache.org/jira/browse/THRIFT-3999) - Fix Debian & Ubuntu package dependencies
- [THRIFT-3886](https://issues.apache.org/jira/browse/THRIFT-3886) - PHP cross test client returns 0 even when failing
- [THRIFT-3997](https://issues.apache.org/jira/browse/THRIFT-3997) - building thrift libs does not support new openssl

### Documentation
- [THRIFT-3867](https://issues.apache.org/jira/browse/THRIFT-3867) - Specify BinaryProtocol and CompactProtocol

### Epic
- [THRIFT-3049](https://issues.apache.org/jira/browse/THRIFT-3049) - As an iOS developer, I want a generator and library that produces Swift code
- [THRIFT-2336](https://issues.apache.org/jira/browse/THRIFT-2336) - UTF-8 sent by PHP as JSON is not understood by TJsonProtocol

### Improvement
- [THRIFT-1867](https://issues.apache.org/jira/browse/THRIFT-1867) - Python client/server should support client-side certificates.
- [THRIFT-1313](https://issues.apache.org/jira/browse/THRIFT-1313) - c_glib compact support
- [THRIFT-1385](https://issues.apache.org/jira/browse/THRIFT-1385) - make install doesn't install java library in the setted folder
- [THRIFT-1437](https://issues.apache.org/jira/browse/THRIFT-1437) - Update RPM spec
- [THRIFT-847](https://issues.apache.org/jira/browse/THRIFT-847) - Test Framework harmonization across all languages
- [THRIFT-819](https://issues.apache.org/jira/browse/THRIFT-819) - add Enumeration for protocol, transport and server types
- [THRIFT-3927](https://issues.apache.org/jira/browse/THRIFT-3927) - Emit an error instead of throw an error in the async callback
- [THRIFT-3931](https://issues.apache.org/jira/browse/THRIFT-3931) - TSimpleServer: If process request encounter UNKNOWN_METHOD, don't close transport.
- [THRIFT-3934](https://issues.apache.org/jira/browse/THRIFT-3934) - Automatically resolve OpenSSL binary version on Windows CI
- [THRIFT-3918](https://issues.apache.org/jira/browse/THRIFT-3918) - Run subset of make cross
- [THRIFT-3908](https://issues.apache.org/jira/browse/THRIFT-3908) - Remove redundant dependencies from Dockerfile
- [THRIFT-3907](https://issues.apache.org/jira/browse/THRIFT-3907) - Skip Docker image build on CI when unchanged
- [THRIFT-3868](https://issues.apache.org/jira/browse/THRIFT-3868) - Java struct equals should do identity check before field comparison
- [THRIFT-3849](https://issues.apache.org/jira/browse/THRIFT-3849) - Port Go serializer and deserializer to dart
- [THRIFT-2989](https://issues.apache.org/jira/browse/THRIFT-2989) - Complete CMake build for Apache Thrift
- [THRIFT-2980](https://issues.apache.org/jira/browse/THRIFT-2980) - ThriftMemoryBuffer doesn't have a constructor option to take an existing buffer
- [THRIFT-2856](https://issues.apache.org/jira/browse/THRIFT-2856) - refactor erlang basic transports and unify interfaces
- [THRIFT-2877](https://issues.apache.org/jira/browse/THRIFT-2877) - Optimize generated hashCode
- [THRIFT-2869](https://issues.apache.org/jira/browse/THRIFT-2869) - JSON: run schema validation from tests
- [THRIFT-3112](https://issues.apache.org/jira/browse/THRIFT-3112) - [Java] AsyncMethodCallback should be typed in generated AsyncIface
- [THRIFT-3263](https://issues.apache.org/jira/browse/THRIFT-3263) - PHP jsonSerialize() should cast scalar types
- [THRIFT-2905](https://issues.apache.org/jira/browse/THRIFT-2905) - Cocoa compiler should have option to produce "modern" Objective-C
- [THRIFT-2821](https://issues.apache.org/jira/browse/THRIFT-2821) - Enable the use of custom HTTP-Header in the Transport
- [THRIFT-2093](https://issues.apache.org/jira/browse/THRIFT-2093) - added the ability to set compression level in C++ zlib transport
- [THRIFT-2089](https://issues.apache.org/jira/browse/THRIFT-2089) - Compiler ignores duplicate typenames
- [THRIFT-2056](https://issues.apache.org/jira/browse/THRIFT-2056) - Moved all #include config.h statements to #include 
- [THRIFT-2031](https://issues.apache.org/jira/browse/THRIFT-2031) - Make SO_KEEPALIVE configurable for C++ lib
- [THRIFT-2021](https://issues.apache.org/jira/browse/THRIFT-2021) - Improve large binary protocol string performance
- [THRIFT-2028](https://issues.apache.org/jira/browse/THRIFT-2028) - Cleanup threading headers / libraries
- [THRIFT-2014](https://issues.apache.org/jira/browse/THRIFT-2014) - Change C++ lib includes to use  style throughout
- [THRIFT-2312](https://issues.apache.org/jira/browse/THRIFT-2312) - travis.yml: build everything
- [THRIFT-1915](https://issues.apache.org/jira/browse/THRIFT-1915) - Multiplexing Services
- [THRIFT-1736](https://issues.apache.org/jira/browse/THRIFT-1736) - Visual Studio top level project files within msvc
- [THRIFT-1735](https://issues.apache.org/jira/browse/THRIFT-1735) - integrate tutorial into regular build
- [THRIFT-1533](https://issues.apache.org/jira/browse/THRIFT-1533) - Make TTransport should be Closeable
- [THRIFT-35](https://issues.apache.org/jira/browse/THRIFT-35) - Move language tests into their appropriate library directory
- [THRIFT-1079](https://issues.apache.org/jira/browse/THRIFT-1079) - Support i64 in AS3
- [THRIFT-1108](https://issues.apache.org/jira/browse/THRIFT-1108) - SSL support for the Ruby library
- [THRIFT-3856](https://issues.apache.org/jira/browse/THRIFT-3856) - update debian package deependencies
- [THRIFT-3833](https://issues.apache.org/jira/browse/THRIFT-3833) - haxe http server implementation (by embeding into php web server)
- [THRIFT-3839](https://issues.apache.org/jira/browse/THRIFT-3839) - Performance issue with big message deserialization using php extension
- [THRIFT-3820](https://issues.apache.org/jira/browse/THRIFT-3820) - Erlang: Detect OTP >= 18 to use new time correction
- [THRIFT-3816](https://issues.apache.org/jira/browse/THRIFT-3816) - Reduce docker build duration on Travis-CI
- [THRIFT-3815](https://issues.apache.org/jira/browse/THRIFT-3815) - Put appveyor dependency versions to one place
- [THRIFT-3788](https://issues.apache.org/jira/browse/THRIFT-3788) - Compatibility improvements and Win64 support
- [THRIFT-3792](https://issues.apache.org/jira/browse/THRIFT-3792) - Timeouts for anonymous pipes should be configurable
- [THRIFT-3794](https://issues.apache.org/jira/browse/THRIFT-3794) - Split Delphi application, protocol and transport exception subtypes into separate exceptions
- [THRIFT-3774](https://issues.apache.org/jira/browse/THRIFT-3774) - The generated code should have exception_names meta info
- [THRIFT-3762](https://issues.apache.org/jira/browse/THRIFT-3762) - Fix build warnings for deprecated Thrift "byte" fields
- [THRIFT-3756](https://issues.apache.org/jira/browse/THRIFT-3756) - Improve requiredness documentation
- [THRIFT-3761](https://issues.apache.org/jira/browse/THRIFT-3761) - Add debian package for Python3
- [THRIFT-3742](https://issues.apache.org/jira/browse/THRIFT-3742) - haxe php cli support
- [THRIFT-3733](https://issues.apache.org/jira/browse/THRIFT-3733) - Socket timeout improvements
- [THRIFT-3728](https://issues.apache.org/jira/browse/THRIFT-3728) - http transport for thrift-lua
- [THRIFT-3905](https://issues.apache.org/jira/browse/THRIFT-3905) - Dart compiler does not initialize bool, int, and double properties
- [THRIFT-3911](https://issues.apache.org/jira/browse/THRIFT-3911) - Loosen Ruby dev dependency version requirements
- [THRIFT-3906](https://issues.apache.org/jira/browse/THRIFT-3906) - Run C# tests with make check
- [THRIFT-3900](https://issues.apache.org/jira/browse/THRIFT-3900) - Add Python SSL flags
- [THRIFT-3897](https://issues.apache.org/jira/browse/THRIFT-3897) - Provide meaningful exception type based on WebExceptionStatus in case of timeout
- [THRIFT-3808](https://issues.apache.org/jira/browse/THRIFT-3808) - Missing `DOUBLE` in thrift type enumeration
- [THRIFT-3803](https://issues.apache.org/jira/browse/THRIFT-3803) - Remove "file" attribute from XML generator
- [THRIFT-3660](https://issues.apache.org/jira/browse/THRIFT-3660) - Add V4 mapped address to test client cert's altname
- [THRIFT-3661](https://issues.apache.org/jira/browse/THRIFT-3661) - Use https to download meck in erlang test build
- [THRIFT-3659](https://issues.apache.org/jira/browse/THRIFT-3659) - Check configure result of CMake on CI
- [THRIFT-3667](https://issues.apache.org/jira/browse/THRIFT-3667) - Add TLS SNI support to clients
- [THRIFT-3651](https://issues.apache.org/jira/browse/THRIFT-3651) - Make backports.match_hostname and ipaddress optional
- [THRIFT-3666](https://issues.apache.org/jira/browse/THRIFT-3666) - Build D tutorial as part of Autotools build
- [THRIFT-3665](https://issues.apache.org/jira/browse/THRIFT-3665) - Add D libevent and OpenSSL to docker images
- [THRIFT-3664](https://issues.apache.org/jira/browse/THRIFT-3664) - Remove md5.c
- [THRIFT-3662](https://issues.apache.org/jira/browse/THRIFT-3662) - Add Haskell to debian docker image
- [THRIFT-3711](https://issues.apache.org/jira/browse/THRIFT-3711) - Add D to cross language test
- [THRIFT-3691](https://issues.apache.org/jira/browse/THRIFT-3691) - Run flake8 Python style check on Travis-CI
- [THRIFT-3692](https://issues.apache.org/jira/browse/THRIFT-3692) - (Re)enable Appveyor C++ and Python build
- [THRIFT-3677](https://issues.apache.org/jira/browse/THRIFT-3677) - Improve CMake Java build
- [THRIFT-3679](https://issues.apache.org/jira/browse/THRIFT-3679) - Add stdout log to testBinary in Java test server
- [THRIFT-3718](https://issues.apache.org/jira/browse/THRIFT-3718) - Reduce size of docker image for build environment
- [THRIFT-3698](https://issues.apache.org/jira/browse/THRIFT-3698) - [Travis-CI] Introduce retry to apt commands
- [THRIFT-3127](https://issues.apache.org/jira/browse/THRIFT-3127) - switch -recurse to --recurse and reserve -r
- [THRIFT-3087](https://issues.apache.org/jira/browse/THRIFT-3087) - Pass on errors like "connection closed"
- [THRIFT-3240](https://issues.apache.org/jira/browse/THRIFT-3240) - Thrift Python client should support subjectAltName and wildcard certs in TSSLSocket
- [THRIFT-3213](https://issues.apache.org/jira/browse/THRIFT-3213) - make cross should indicate when it skips a known failing test
- [THRIFT-3208](https://issues.apache.org/jira/browse/THRIFT-3208) - Fix Visual Studio solution build failure due to missing source
- [THRIFT-3186](https://issues.apache.org/jira/browse/THRIFT-3186) - Add TServerHTTP to Go library
- [THRIFT-2342](https://issues.apache.org/jira/browse/THRIFT-2342) - Add __FILE__ and __LINE__ to Thrift C++ excpetions
- [THRIFT-3372](https://issues.apache.org/jira/browse/THRIFT-3372) - Add dart generator to Visual Studio project
- [THRIFT-3366](https://issues.apache.org/jira/browse/THRIFT-3366) - ThriftTest to implement standard return values
- [THRIFT-3402](https://issues.apache.org/jira/browse/THRIFT-3402) - Provide a perl Unix Socket implementation
- [THRIFT-3361](https://issues.apache.org/jira/browse/THRIFT-3361) - Improve C# library
- [THRIFT-3393](https://issues.apache.org/jira/browse/THRIFT-3393) - Introduce i8 to provide consistent set of Thrift IDL integer types
- [THRIFT-3339](https://issues.apache.org/jira/browse/THRIFT-3339) - Support for database/sql
- [THRIFT-3565](https://issues.apache.org/jira/browse/THRIFT-3565) - C++: T[Async]Processor::getEventHandler() should be declared as const member functions
- [THRIFT-3563](https://issues.apache.org/jira/browse/THRIFT-3563) - C++/Qt: removed usage of macro QT_PREPEND_NAMESPACE as it isn't consequently used for all references to Qt types.
- [THRIFT-3562](https://issues.apache.org/jira/browse/THRIFT-3562) - Removed unused TAsyncProcessor::getAsyncServer()
- [THRIFT-3561](https://issues.apache.org/jira/browse/THRIFT-3561) - C++/Qt: make use of Q_DISABLE_COPY() to get rid of copy ctor and assignment operator
- [THRIFT-3556](https://issues.apache.org/jira/browse/THRIFT-3556) - c_glib file descriptor transport
- [THRIFT-3544](https://issues.apache.org/jira/browse/THRIFT-3544) - Make cross test fail when server process died unexpectedly
- [THRIFT-3540](https://issues.apache.org/jira/browse/THRIFT-3540) - Make python tutorial more in line with PEP8
- [THRIFT-3535](https://issues.apache.org/jira/browse/THRIFT-3535) - Dart generator argument to produce a file structure usable in parent library
- [THRIFT-3505](https://issues.apache.org/jira/browse/THRIFT-3505) - Enhance Python TSSLSocket
- [THRIFT-3506](https://issues.apache.org/jira/browse/THRIFT-3506) - Eliminate old style classes from library code
- [THRIFT-3503](https://issues.apache.org/jira/browse/THRIFT-3503) - Enable py:utf8string by default
- [THRIFT-3499](https://issues.apache.org/jira/browse/THRIFT-3499) - Add package_prefix to python generator
- [THRIFT-3495](https://issues.apache.org/jira/browse/THRIFT-3495) - Minor enhancements and fixes for cross test
- [THRIFT-3486](https://issues.apache.org/jira/browse/THRIFT-3486) - Java generated `getFieldValue` is incompatible with `setFieldValue` for binary values.
- [THRIFT-3484](https://issues.apache.org/jira/browse/THRIFT-3484) - Consolidate temporary buffers in Java's TCompactProtocol
- [THRIFT-3516](https://issues.apache.org/jira/browse/THRIFT-3516) - Add feature test for THeader TBinaryProtocol interop
- [THRIFT-3515](https://issues.apache.org/jira/browse/THRIFT-3515) - Python 2.6 compatibility and test on CI
- [THRIFT-3514](https://issues.apache.org/jira/browse/THRIFT-3514) - PHP 7 compatible version of binary protocol
- [THRIFT-3469](https://issues.apache.org/jira/browse/THRIFT-3469) - Docker: Debian support
- [THRIFT-3416](https://issues.apache.org/jira/browse/THRIFT-3416) - Retire old "xxx_namespace" declarations from the IDL
- [THRIFT-3426](https://issues.apache.org/jira/browse/THRIFT-3426) - Align autogen comment in XSD
- [THRIFT-3424](https://issues.apache.org/jira/browse/THRIFT-3424) - Add CMake android build option
- [THRIFT-3439](https://issues.apache.org/jira/browse/THRIFT-3439) - Run make cross using Python3 when available
- [THRIFT-3440](https://issues.apache.org/jira/browse/THRIFT-3440) - Python make check takes too much time
- [THRIFT-3441](https://issues.apache.org/jira/browse/THRIFT-3441) - Stabilize Travis-CI builds
- [THRIFT-3431](https://issues.apache.org/jira/browse/THRIFT-3431) - Avoid "schemes" HashMap lookups during struct reads/writes
- [THRIFT-3432](https://issues.apache.org/jira/browse/THRIFT-3432) - Add a TByteBuffer transport to the Java library
- [THRIFT-3438](https://issues.apache.org/jira/browse/THRIFT-3438) - Enable py:new_style by default
- [THRIFT-3405](https://issues.apache.org/jira/browse/THRIFT-3405) - Go THttpClient misuses http.Client objects
- [THRIFT-3614](https://issues.apache.org/jira/browse/THRIFT-3614) - Improve logging of test_sslsocket.py
- [THRIFT-3647](https://issues.apache.org/jira/browse/THRIFT-3647) - Fix php extension build warnings
- [THRIFT-3642](https://issues.apache.org/jira/browse/THRIFT-3642) - Speed up cross test runner
- [THRIFT-3637](https://issues.apache.org/jira/browse/THRIFT-3637) - Implement compact protocol for dart
- [THRIFT-3613](https://issues.apache.org/jira/browse/THRIFT-3613) - Port Python C extension to Python 3
- [THRIFT-3612](https://issues.apache.org/jira/browse/THRIFT-3612) - Add Python C extension for compact protocol
- [THRIFT-3611](https://issues.apache.org/jira/browse/THRIFT-3611) - Add --regex filter to cross test runner
- [THRIFT-3631](https://issues.apache.org/jira/browse/THRIFT-3631) - JSON protocol implementation for Lua
- [THRIFT-3609](https://issues.apache.org/jira/browse/THRIFT-3609) - Remove or replace TestPortFixture.h
- [THRIFT-3605](https://issues.apache.org/jira/browse/THRIFT-3605) - Have the compiler complain about invalid arguments and options
- [THRIFT-3596](https://issues.apache.org/jira/browse/THRIFT-3596) - Better conformance to PEP8
- [THRIFT-3585](https://issues.apache.org/jira/browse/THRIFT-3585) - Compact protocol implementation for Lua
- [THRIFT-3582](https://issues.apache.org/jira/browse/THRIFT-3582) - Erlang libraries should have service metadata
- [THRIFT-3579](https://issues.apache.org/jira/browse/THRIFT-3579) - Introduce retry to make cross
- [THRIFT-3306](https://issues.apache.org/jira/browse/THRIFT-3306) - Java: TBinaryProtocol: Use 1 temp buffer instead of allocating 8
- [THRIFT-3910](https://issues.apache.org/jira/browse/THRIFT-3910) - Do not invoke pip as part of build process
- [THRIFT-1857](https://issues.apache.org/jira/browse/THRIFT-1857) - Python 3.X Support
- [THRIFT-1944](https://issues.apache.org/jira/browse/THRIFT-1944) - Binding to zero port
- [THRIFT-3954](https://issues.apache.org/jira/browse/THRIFT-3954) - Enable the usage of structs called "Object" in Java
- [THRIFT-3981](https://issues.apache.org/jira/browse/THRIFT-3981) - Enable analyzer strong mode in Dart library
- [THRIFT-3998](https://issues.apache.org/jira/browse/THRIFT-3998) - Document ability to add custom tags to thrift structs
- [THRIFT-4006](https://issues.apache.org/jira/browse/THRIFT-4006) - Add a removeEventListener method on TSocket

### New Feature
- [THRIFT-640](https://issues.apache.org/jira/browse/THRIFT-640) - Support deprecation
- [THRIFT-948](https://issues.apache.org/jira/browse/THRIFT-948) - SSL socket support for PHP
- [THRIFT-764](https://issues.apache.org/jira/browse/THRIFT-764) - add Support for Vala language
- [THRIFT-3046](https://issues.apache.org/jira/browse/THRIFT-3046) - Allow PSR4 class loading for generated classes (PHP)
- [THRIFT-2113](https://issues.apache.org/jira/browse/THRIFT-2113) - Erlang SSL Socket Support
- [THRIFT-1482](https://issues.apache.org/jira/browse/THRIFT-1482) - Unix domain socket support under PHP
- [THRIFT-519](https://issues.apache.org/jira/browse/THRIFT-519) - Support collections of types without having to explicitly define it
- [THRIFT-468](https://issues.apache.org/jira/browse/THRIFT-468) - Rack Middleware Application for Rails
- [THRIFT-1708](https://issues.apache.org/jira/browse/THRIFT-1708) - Add event handlers for processor events
- [THRIFT-3834](https://issues.apache.org/jira/browse/THRIFT-3834) - Erlang namespacing and exception metadata
- [THRIFT-2510](https://issues.apache.org/jira/browse/THRIFT-2510) - Implement TNonblockingServer's ability to listen on unix domain sockets
- [THRIFT-3397](https://issues.apache.org/jira/browse/THRIFT-3397) - Implement TProcessorFactory in C# to enable per-client processors
- [THRIFT-3523](https://issues.apache.org/jira/browse/THRIFT-3523) - XML Generator
- [THRIFT-3510](https://issues.apache.org/jira/browse/THRIFT-3510) - Add HttpTaskAsyncHandler implementation
- [THRIFT-3318](https://issues.apache.org/jira/browse/THRIFT-3318) - PHP: SimpleJSONProtocol Implementation
- [THRIFT-3299](https://issues.apache.org/jira/browse/THRIFT-3299) - Dart language bindings in Thrift
- [THRIFT-2835](https://issues.apache.org/jira/browse/THRIFT-2835) - Add possibility to distribute generators separately from thrift core, and load them dynamically
- [THRIFT-184](https://issues.apache.org/jira/browse/THRIFT-184) - Add OSGi Manifest headers to the libthrift java library to be able to use Thrift in the OSGi runtime
- [THRIFT-141](https://issues.apache.org/jira/browse/THRIFT-141) - If a required field is not present on serialization, throw an exception
- [THRIFT-1891](https://issues.apache.org/jira/browse/THRIFT-1891) - Add Windows ALPC transport which is right counterpart of Unix domain sockets

### Question
- [THRIFT-1808](https://issues.apache.org/jira/browse/THRIFT-1808) - The Thrift struct should be considered self-contained?
- [THRIFT-2895](https://issues.apache.org/jira/browse/THRIFT-2895) - Tutorial cpp
- [THRIFT-3860](https://issues.apache.org/jira/browse/THRIFT-3860) - Elephant-bird application Test fails for Thrift
- [THRIFT-3811](https://issues.apache.org/jira/browse/THRIFT-3811) - HTTPS Support for C++ applications
- [THRIFT-3509](https://issues.apache.org/jira/browse/THRIFT-3509) - "make check" error

### Story
- [THRIFT-3452](https://issues.apache.org/jira/browse/THRIFT-3452) - .travis.yml: Migrating from legacy to container-based infrastructure

### Sub-task
- [THRIFT-1811](https://issues.apache.org/jira/browse/THRIFT-1811) - ruby tutorial as part of the regular build
- [THRIFT-2779](https://issues.apache.org/jira/browse/THRIFT-2779) - PHP TJSONProtocol encode unicode into UCS-4LE which can't be parsed by other language bindings
- [THRIFT-2110](https://issues.apache.org/jira/browse/THRIFT-2110) - Erlang: Support for Multiplexing Services on any Transport, Protocol and Server
- [THRIFT-3852](https://issues.apache.org/jira/browse/THRIFT-3852) - A Travis-CI job fails with "write error"
- [THRIFT-3740](https://issues.apache.org/jira/browse/THRIFT-3740) - Fix haxelib.json classpath
- [THRIFT-3653](https://issues.apache.org/jira/browse/THRIFT-3653) - incorrect union serialization
- [THRIFT-3652](https://issues.apache.org/jira/browse/THRIFT-3652) - incorrect serialization of optionals
- [THRIFT-3655](https://issues.apache.org/jira/browse/THRIFT-3655) - incorrect union serialization
- [THRIFT-3654](https://issues.apache.org/jira/browse/THRIFT-3654) - incorrect serialization of optionals
- [THRIFT-3656](https://issues.apache.org/jira/browse/THRIFT-3656) - incorrect serialization of optionals
- [THRIFT-3699](https://issues.apache.org/jira/browse/THRIFT-3699) - Fix integer limit symbol includes in Python C extension
- [THRIFT-3693](https://issues.apache.org/jira/browse/THRIFT-3693) - Fix include issue in C++ TSSLSocketInterruptTest on Windows
- [THRIFT-3694](https://issues.apache.org/jira/browse/THRIFT-3694) - [Windows] Disable tests of a few servers that are not supported
- [THRIFT-3696](https://issues.apache.org/jira/browse/THRIFT-3696) - Install pip to CentOS Docker images to fix Python builds
- [THRIFT-3638](https://issues.apache.org/jira/browse/THRIFT-3638) - Fix haxelib.json
- [THRIFT-3251](https://issues.apache.org/jira/browse/THRIFT-3251) - Add http transport for server to Go lib
- [THRIFT-2424](https://issues.apache.org/jira/browse/THRIFT-2424) - Recursive Types
- [THRIFT-2423](https://issues.apache.org/jira/browse/THRIFT-2423) - THeader
- [THRIFT-2413](https://issues.apache.org/jira/browse/THRIFT-2413) - Python: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol
- [THRIFT-2409](https://issues.apache.org/jira/browse/THRIFT-2409) - Java: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol
- [THRIFT-2412](https://issues.apache.org/jira/browse/THRIFT-2412) - D: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol
- [THRIFT-2411](https://issues.apache.org/jira/browse/THRIFT-2411) - C++: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol
- [THRIFT-2410](https://issues.apache.org/jira/browse/THRIFT-2410) - JavaMe: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol
- [THRIFT-2668](https://issues.apache.org/jira/browse/THRIFT-2668) - TestSuite: detailed result on passed tests by feature
- [THRIFT-2659](https://issues.apache.org/jira/browse/THRIFT-2659) - python Test Server fails when throwing TException
- [THRIFT-3398](https://issues.apache.org/jira/browse/THRIFT-3398) - Add CMake build  for Haskell library and tests
- [THRIFT-3396](https://issues.apache.org/jira/browse/THRIFT-3396) - DART: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol
- [THRIFT-3364](https://issues.apache.org/jira/browse/THRIFT-3364) -   Fix ruby binary field encoding in TJSONProtocol
- [THRIFT-3381](https://issues.apache.org/jira/browse/THRIFT-3381) - Fix for misc. codegen issues with THRIFT-2905
- [THRIFT-3573](https://issues.apache.org/jira/browse/THRIFT-3573) - No rule to make target `../../../test/c_glib/src/.deps/testthrifttest-thrift_test_handler.Po'.
- [THRIFT-3572](https://issues.apache.org/jira/browse/THRIFT-3572) - "Unable to determine the behavior of a signed right shift"
- [THRIFT-3542](https://issues.apache.org/jira/browse/THRIFT-3542) - Add length limit support to Java test server
- [THRIFT-3537](https://issues.apache.org/jira/browse/THRIFT-3537) - Remove the (now obsolete) csharp:asyncctp flag
- [THRIFT-3532](https://issues.apache.org/jira/browse/THRIFT-3532) - Add configurable string and container read size limit to Python protocols
- [THRIFT-3531](https://issues.apache.org/jira/browse/THRIFT-3531) - Create cross lang feature test for string and container read length limit
- [THRIFT-3482](https://issues.apache.org/jira/browse/THRIFT-3482) - Haskell JSON protocol does not encode binary field as Base64
- [THRIFT-3425](https://issues.apache.org/jira/browse/THRIFT-3425) - Minor fixes + simplification for CentOS Dockerfile
- [THRIFT-3442](https://issues.apache.org/jira/browse/THRIFT-3442) - Run CMake tests on Appveyor
- [THRIFT-3409](https://issues.apache.org/jira/browse/THRIFT-3409) - NodeJS binary field issues
- [THRIFT-3621](https://issues.apache.org/jira/browse/THRIFT-3621) - Fix lib/cpp/test/SecurityTest.cpp to use ephemeral ports
- [THRIFT-3628](https://issues.apache.org/jira/browse/THRIFT-3628) - Fix lib/cpp/test/TServerIntegrationTest.cpp to use ephemeral ports
- [THRIFT-3625](https://issues.apache.org/jira/browse/THRIFT-3625) - Kill unused #include "TestPortFixture.h" in lib/cpp/test/TServerTransportTest.cpp.
- [THRIFT-3646](https://issues.apache.org/jira/browse/THRIFT-3646) - Fix Python extension build warnings
- [THRIFT-3626](https://issues.apache.org/jira/browse/THRIFT-3626) - Fix lib/cpp/test/TSocketInterruptTest.cpp to use ephemeral ports.
- [THRIFT-3624](https://issues.apache.org/jira/browse/THRIFT-3624) - Fix lib/cpp/test/TServerSocketTest.cpp to use ephemeral ports
- [THRIFT-3623](https://issues.apache.org/jira/browse/THRIFT-3623) - Fix Fix cpp/lib/test/TSSLSocketInterruptTest.cpp to use ephemeral ports
- [THRIFT-3592](https://issues.apache.org/jira/browse/THRIFT-3592) - Add basic test client
- [THRIFT-3980](https://issues.apache.org/jira/browse/THRIFT-3980) - add TExtendedBinaryProtocol.java

### Task
- [THRIFT-1801](https://issues.apache.org/jira/browse/THRIFT-1801) - Sync up TApplicationException codes across languages and thrift implementations
- [THRIFT-1259](https://issues.apache.org/jira/browse/THRIFT-1259) - Automate versioning

### Test
- [THRIFT-3400](https://issues.apache.org/jira/browse/THRIFT-3400) - Add Erlang to cross test
- [THRIFT-3504](https://issues.apache.org/jira/browse/THRIFT-3504) - Fix FastbinaryTest.py

### Wish
- [THRIFT-3923](https://issues.apache.org/jira/browse/THRIFT-3923) - Maybe remove Aereo from the "Powered by" list
- [THRIFT-2149](https://issues.apache.org/jira/browse/THRIFT-2149) - Add an option to disable the generation of default operators

## 0.9.3.1

Released March 13, 2019 to backport a CVE fix to the popular 0.9.3 release.

### Bug
- [THRIFT-4506](https://issues.apache.org/jira/browse/THRIFT-4506) - CVE-2018-1320 for Java SASL backported from 0.12.0

## 0.9.3

### Bug
- [THRIFT-2441](https://issues.apache.org/jira/browse/THRIFT-2441) - Cannot shutdown TThreadedServer when clients are still connected
- [THRIFT-2465](https://issues.apache.org/jira/browse/THRIFT-2465) - TBinaryProtocolT breaks if copied/moved
- [THRIFT-2474](https://issues.apache.org/jira/browse/THRIFT-2474) - thrift.h causes a compile failure
- [THRIFT-2540](https://issues.apache.org/jira/browse/THRIFT-2540) - Running configure from outside the source directory fails
- [THRIFT-2598](https://issues.apache.org/jira/browse/THRIFT-2598) - Add check for minimum Go version to configure.ac
- [THRIFT-2647](https://issues.apache.org/jira/browse/THRIFT-2647) - compiler-hs: don't decapitalize field names, do decapitalize argument bindings
- [THRIFT-2773](https://issues.apache.org/jira/browse/THRIFT-2773) - Generated Java code for 'oneway' methods is incorrect.
- [THRIFT-2789](https://issues.apache.org/jira/browse/THRIFT-2789) - TNonblockingServer leaks socket FD's under load
- [THRIFT-2682](https://issues.apache.org/jira/browse/THRIFT-2682) - TThreadedServer leaks per-thread memory
- [THRIFT-2674](https://issues.apache.org/jira/browse/THRIFT-2674) - JavaScript: declare Accept: and Content-Type: in request
- [THRIFT-3078](https://issues.apache.org/jira/browse/THRIFT-3078) - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket
- [THRIFT-3077](https://issues.apache.org/jira/browse/THRIFT-3077) - C++ TFileTransport ignores return code from ftruncate
- [THRIFT-3067](https://issues.apache.org/jira/browse/THRIFT-3067) - C++ cppcheck performance related warnings
- [THRIFT-3066](https://issues.apache.org/jira/browse/THRIFT-3066) - C++ TDenseProtocol assert modifies instead of checks
- [THRIFT-3071](https://issues.apache.org/jira/browse/THRIFT-3071) - bootstrap.sh on Ubuntu 12.04 (Precise) automake error
- [THRIFT-3069](https://issues.apache.org/jira/browse/THRIFT-3069) - C++ TServerSocket leaks socket on fcntl get or set flags error
- [THRIFT-3079](https://issues.apache.org/jira/browse/THRIFT-3079) - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket
- [THRIFT-3080](https://issues.apache.org/jira/browse/THRIFT-3080) - C++ TNonblockingServer connection leak while accept huge number connections.
- [THRIFT-3086](https://issues.apache.org/jira/browse/THRIFT-3086) - C++ Valgrind Error Cleanup
- [THRIFT-3085](https://issues.apache.org/jira/browse/THRIFT-3085) - thrift_reconnecting_client never try to reconnect
- [THRIFT-3123](https://issues.apache.org/jira/browse/THRIFT-3123) - Missing include in compiler/cpp/src/main.h breaks build in some environments
- [THRIFT-3125](https://issues.apache.org/jira/browse/THRIFT-3125) - Fix the list of exported headers in automake input
- [THRIFT-3126](https://issues.apache.org/jira/browse/THRIFT-3126) - PHP JSON serializer converts empty or int-indexed maps to lists
- [THRIFT-3132](https://issues.apache.org/jira/browse/THRIFT-3132) - Properly format date in Java @Generated annotations
- [THRIFT-3137](https://issues.apache.org/jira/browse/THRIFT-3137) - Travis build hangs after failure
- [THRIFT-3138](https://issues.apache.org/jira/browse/THRIFT-3138) - "make check" parallel execution is underministic
- [THRIFT-3139](https://issues.apache.org/jira/browse/THRIFT-3139) - JS library test is flaky
- [THRIFT-3140](https://issues.apache.org/jira/browse/THRIFT-3140) - ConcurrentModificationException is thrown by JavaScript test server
- [THRIFT-3124](https://issues.apache.org/jira/browse/THRIFT-3124) - Some signed/unsigned warnings while building compiler
- [THRIFT-3128](https://issues.apache.org/jira/browse/THRIFT-3128) - Go generated code produces name collisions between services
- [THRIFT-3146](https://issues.apache.org/jira/browse/THRIFT-3146) - Graphviz generates function name collisions between services
- [THRIFT-3147](https://issues.apache.org/jira/browse/THRIFT-3147) - Segfault while receiving data
- [THRIFT-3148](https://issues.apache.org/jira/browse/THRIFT-3148) - Markdown links to coding_standards are dead
- [THRIFT-3090](https://issues.apache.org/jira/browse/THRIFT-3090) - cmake build is broken on MacOSX
- [THRIFT-3097](https://issues.apache.org/jira/browse/THRIFT-3097) - cmake targets unconditionally depend on optional libraries
- [THRIFT-3094](https://issues.apache.org/jira/browse/THRIFT-3094) - master as of 2015-APR-13 fails -DBOOST_THREADS cmake build
- [THRIFT-3099](https://issues.apache.org/jira/browse/THRIFT-3099) - cmake build is broken on FreeBSD
- [THRIFT-3089](https://issues.apache.org/jira/browse/THRIFT-3089) - Assigning default ENUM values results in non-compilable java code if java namespace is not defined
- [THRIFT-3093](https://issues.apache.org/jira/browse/THRIFT-3093) - mingw compile fixes for c++ library 0.9.2
- [THRIFT-3098](https://issues.apache.org/jira/browse/THRIFT-3098) - Thrift does not pretty print binary typedefs the way it does binary fields
- [THRIFT-3091](https://issues.apache.org/jira/browse/THRIFT-3091) - c_glib service method should return result from handler method
- [THRIFT-3088](https://issues.apache.org/jira/browse/THRIFT-3088) - TThreadPoolServer with Sasl auth may leak CLOSE_WAIT socket
- [THRIFT-3109](https://issues.apache.org/jira/browse/THRIFT-3109) - Cross test log file cannot be browsed when served in HTTP server
- [THRIFT-3113](https://issues.apache.org/jira/browse/THRIFT-3113) - m4 C++11 macro issue
- [THRIFT-3105](https://issues.apache.org/jira/browse/THRIFT-3105) - C++ libthriftnb library on Windows build failure
- [THRIFT-3115](https://issues.apache.org/jira/browse/THRIFT-3115) - Uncompileable code due to name collision with predefined used types
- [THRIFT-3117](https://issues.apache.org/jira/browse/THRIFT-3117) - Java TSSLTransportFactory can't load certificates within JAR archive
- [THRIFT-3102](https://issues.apache.org/jira/browse/THRIFT-3102) - could not make check for Go Library
- [THRIFT-3120](https://issues.apache.org/jira/browse/THRIFT-3120) - Minor spelling errors and an outdated URL
- [THRIFT-3121](https://issues.apache.org/jira/browse/THRIFT-3121) - Librt does not exist on OS X
- [THRIFT-3152](https://issues.apache.org/jira/browse/THRIFT-3152) - Compiler error on Mac OSX (missing #include )
- [THRIFT-3162](https://issues.apache.org/jira/browse/THRIFT-3162) - make fails for dmd 2.067
- [THRIFT-3164](https://issues.apache.org/jira/browse/THRIFT-3164) - Thrift C++ library SSL socket by default allows for unsecure SSLv3 negotiation
- [THRIFT-3168](https://issues.apache.org/jira/browse/THRIFT-3168) - Fix Maven POM
- [THRIFT-3170](https://issues.apache.org/jira/browse/THRIFT-3170) - Initialism code in the Go compiler causes chaos
- [THRIFT-3169](https://issues.apache.org/jira/browse/THRIFT-3169) - Do not export thrift.TestStruct and thrift.TestEnum in thrift Go library
- [THRIFT-3191](https://issues.apache.org/jira/browse/THRIFT-3191) - Perl compiler does not add support for unexpected exception handling
- [THRIFT-3178](https://issues.apache.org/jira/browse/THRIFT-3178) - glib C does not compile
- [THRIFT-3189](https://issues.apache.org/jira/browse/THRIFT-3189) - Perl ServerSocket should allow a specific interface to be listened to
- [THRIFT-3252](https://issues.apache.org/jira/browse/THRIFT-3252) - Missing TConcurrentClientSyncInfo.h in cpp Makefile, so doesn't install
- [THRIFT-3255](https://issues.apache.org/jira/browse/THRIFT-3255) - Thrift generator doesn't exclude 'package' keyword for thrift property names breaking java builds
- [THRIFT-3260](https://issues.apache.org/jira/browse/THRIFT-3260) - multiple warnings in c_glib tutorial
- [THRIFT-3256](https://issues.apache.org/jira/browse/THRIFT-3256) - Some D test timings are too aggressive for slow machines
- [THRIFT-3257](https://issues.apache.org/jira/browse/THRIFT-3257) - warning: extra tokens at end of #endif directive
- [THRIFT-3184](https://issues.apache.org/jira/browse/THRIFT-3184) - Thrift Go leaves file descriptors open
- [THRIFT-3203](https://issues.apache.org/jira/browse/THRIFT-3203) - DOAP) - please fix "Ocaml" => "OCaml"
- [THRIFT-3210](https://issues.apache.org/jira/browse/THRIFT-3210) - (uncompileable) code generated for server events while are events not enabled
- [THRIFT-3215](https://issues.apache.org/jira/browse/THRIFT-3215) - TJSONProtocol '(c++) uses "throw new" to throw exceptions instead of "throw"
- [THRIFT-3202](https://issues.apache.org/jira/browse/THRIFT-3202) - Allow HSHAServer to configure min and max worker threads separately.
- [THRIFT-3205](https://issues.apache.org/jira/browse/THRIFT-3205) - TCompactProtocol return a wrong error when the io.EOF happens
- [THRIFT-3209](https://issues.apache.org/jira/browse/THRIFT-3209) - LGPL mentioned in license file
- [THRIFT-3197](https://issues.apache.org/jira/browse/THRIFT-3197) - keepAliveTime is hard coded as 60 sec in TThreadPoolServer
- [THRIFT-3196](https://issues.apache.org/jira/browse/THRIFT-3196) - Misspelling in lua TBinaryProtocol (stirctWrite => strictWrite)
- [THRIFT-3198](https://issues.apache.org/jira/browse/THRIFT-3198) - Allow construction of TTransportFactory with a specified maxLength
- [THRIFT-3192](https://issues.apache.org/jira/browse/THRIFT-3192) - Go import paths changed in 1.4, and expired June 1
- [THRIFT-3271](https://issues.apache.org/jira/browse/THRIFT-3271) - Could not find or load main class configtest_ax_javac_and_java on some non-english systems
- [THRIFT-3273](https://issues.apache.org/jira/browse/THRIFT-3273) - c_glib: Generated code tries to convert between function and void pointers
- [THRIFT-3264](https://issues.apache.org/jira/browse/THRIFT-3264) - Fix Erlang 16 namespaced types
- [THRIFT-3270](https://issues.apache.org/jira/browse/THRIFT-3270) - reusing TNonblockingServer::TConnection cause dirty TSocket
- [THRIFT-3267](https://issues.apache.org/jira/browse/THRIFT-3267) - c_glib: "Critical" failure during unit tests
- [THRIFT-3277](https://issues.apache.org/jira/browse/THRIFT-3277) - THttpClient leaks connections if it's used for multiple requests
- [THRIFT-3278](https://issues.apache.org/jira/browse/THRIFT-3278) - NodeJS: Fix exception stack traces and names
- [THRIFT-3279](https://issues.apache.org/jira/browse/THRIFT-3279) - Fix a bug in retry_max_delay (NodeJS)
- [THRIFT-3280](https://issues.apache.org/jira/browse/THRIFT-3280) - Initialize retry variables on construction
- [THRIFT-3283](https://issues.apache.org/jira/browse/THRIFT-3283) - c_glib: Tutorial server always exits with warning
- [THRIFT-3284](https://issues.apache.org/jira/browse/THRIFT-3284) - c_glib: Empty service produces unused-variable warning
- [THRIFT-1925](https://issues.apache.org/jira/browse/THRIFT-1925) - c_glib generated code does not compile
- [THRIFT-1849](https://issues.apache.org/jira/browse/THRIFT-1849) - after transport->open() opens isOpen returns true and next open() goes thru when it shall not
- [THRIFT-1866](https://issues.apache.org/jira/browse/THRIFT-1866) - java compiler generates non-compiling code with const's defined in a thrift when name includes non-identifier chars
- [THRIFT-1938](https://issues.apache.org/jira/browse/THRIFT-1938) - FunctionRunner.h -- uses wrong path for Thread.h when installed
- [THRIFT-1844](https://issues.apache.org/jira/browse/THRIFT-1844) - Password string not cleared
- [THRIFT-2004](https://issues.apache.org/jira/browse/THRIFT-2004) - Thrift::Union violates :== method contract and crashes
- [THRIFT-2073](https://issues.apache.org/jira/browse/THRIFT-2073) - Thrift C++ THttpClient error: cannot refill buffer
- [THRIFT-2127](https://issues.apache.org/jira/browse/THRIFT-2127) - Autoconf scripting does not properly account for cross-compile
- [THRIFT-2180](https://issues.apache.org/jira/browse/THRIFT-2180) - Integer types issues in Cocoa lib on ARM64
- [THRIFT-2189](https://issues.apache.org/jira/browse/THRIFT-2189) - Go needs "isset" to fully support "union" type (and optionals)
- [THRIFT-2192](https://issues.apache.org/jira/browse/THRIFT-2192) - autotools on Redhat based systems
- [THRIFT-2546](https://issues.apache.org/jira/browse/THRIFT-2546) - cross language tests fails at 'TestMultiException' when using nodejs server
- [THRIFT-2547](https://issues.apache.org/jira/browse/THRIFT-2547) - nodejs servers and clients fails to connect with cpp using compact protocol
- [THRIFT-2548](https://issues.apache.org/jira/browse/THRIFT-2548) - Nodejs servers and clients does not work properly with  -ssl
- [THRIFT-1471](https://issues.apache.org/jira/browse/THRIFT-1471) - toString() does not print ByteBuffer values when nested in a List
- [THRIFT-1201](https://issues.apache.org/jira/browse/THRIFT-1201) - getaddrinfo resource leak
- [THRIFT-615](https://issues.apache.org/jira/browse/THRIFT-615) - TThreadPoolServer doesn't call task_done after pulling tasks from it's clients queue
- [THRIFT-162](https://issues.apache.org/jira/browse/THRIFT-162) - Thrift structures are unhashable, preventing them from being used as set elements
- [THRIFT-810](https://issues.apache.org/jira/browse/THRIFT-810) - Crashed client on TSocket::close under loads
- [THRIFT-557](https://issues.apache.org/jira/browse/THRIFT-557) - charset problem with file Autogenerated by Thrift
- [THRIFT-233](https://issues.apache.org/jira/browse/THRIFT-233) - IDL doesn't support negative hex literals
- [THRIFT-1649](https://issues.apache.org/jira/browse/THRIFT-1649) - contrib/zeromq does not build in 0.8.0
- [THRIFT-1642](https://issues.apache.org/jira/browse/THRIFT-1642) - Miscalculation lead to throw unexpected "TTransportException::TIMED_OUT"(or called "EAGAIN (timed out)") exception
- [THRIFT-1587](https://issues.apache.org/jira/browse/THRIFT-1587) - TSocket::setRecvTimeout error
- [THRIFT-1248](https://issues.apache.org/jira/browse/THRIFT-1248) - pointer subtraction in TMemoryBuffer relies on undefined behavior
- [THRIFT-1774](https://issues.apache.org/jira/browse/THRIFT-1774) - Sasl Transport client would hang when trying to connect non-sasl transport server
- [THRIFT-1754](https://issues.apache.org/jira/browse/THRIFT-1754) - RangeError in buffer handling
- [THRIFT-1618](https://issues.apache.org/jira/browse/THRIFT-1618) - static structMap in FieldMetaData is not thread safe and can lead to deadlocks
- [THRIFT-2335](https://issues.apache.org/jira/browse/THRIFT-2335) - thrift incompatibility with py:tornado as server, java as client
- [THRIFT-2803](https://issues.apache.org/jira/browse/THRIFT-2803) - TCP_DEFER_ACCEPT not supported with domain sockets
- [THRIFT-2799](https://issues.apache.org/jira/browse/THRIFT-2799) - Build Problem(s): ld: library not found for -l:libboost_unit_test_framework.a
- [THRIFT-2801](https://issues.apache.org/jira/browse/THRIFT-2801) - C++ test suite compilation warnings
- [THRIFT-2802](https://issues.apache.org/jira/browse/THRIFT-2802) - C++ tutorial compilation warnings
- [THRIFT-2795](https://issues.apache.org/jira/browse/THRIFT-2795) - thrift_binary_protocol.c: 'dereferencing type-punned pointer will break strict-aliasing rules'
- [THRIFT-2817](https://issues.apache.org/jira/browse/THRIFT-2817) - TSimpleJSONProtocol reads beyond end of message
- [THRIFT-2826](https://issues.apache.org/jira/browse/THRIFT-2826) - html:standalone sometimes ignored
- [THRIFT-2829](https://issues.apache.org/jira/browse/THRIFT-2829) - Support haxelib installation via github
- [THRIFT-2828](https://issues.apache.org/jira/browse/THRIFT-2828) - slightly wrong help screen indent
- [THRIFT-2831](https://issues.apache.org/jira/browse/THRIFT-2831) - Removes dead code in web_server.js introduced in THRIFT-2819
- [THRIFT-2823](https://issues.apache.org/jira/browse/THRIFT-2823) - All JS-tests are failing when run with grunt test
- [THRIFT-2827](https://issues.apache.org/jira/browse/THRIFT-2827) - Thrift 0.9.2 fails to compile on Yosemite due to tr1/functional include in ProcessorTest.cpp
- [THRIFT-2843](https://issues.apache.org/jira/browse/THRIFT-2843) - Automake configure.ac has possible typo related to Java
- [THRIFT-2813](https://issues.apache.org/jira/browse/THRIFT-2813) - multiple haxe library fixes/improvements
- [THRIFT-2825](https://issues.apache.org/jira/browse/THRIFT-2825) - Supplying unicode to python Thrift client can cause next request arguments to get overwritten
- [THRIFT-2840](https://issues.apache.org/jira/browse/THRIFT-2840) - Cabal file points to LICENSE file outside the path of the Haskell project.
- [THRIFT-2818](https://issues.apache.org/jira/browse/THRIFT-2818) - Trailing commas in array
- [THRIFT-2830](https://issues.apache.org/jira/browse/THRIFT-2830) - Clean up ant warnings in tutorial dir
- [THRIFT-2842](https://issues.apache.org/jira/browse/THRIFT-2842) - Erlang thrift client has infinite timeout
- [THRIFT-2810](https://issues.apache.org/jira/browse/THRIFT-2810) - Do not leave the underlying ServerSocket open if construction of TServerSocket fails
- [THRIFT-2812](https://issues.apache.org/jira/browse/THRIFT-2812) - Go server adding redundant buffering layer
- [THRIFT-2839](https://issues.apache.org/jira/browse/THRIFT-2839) - TFramedTransport read bug
- [THRIFT-2844](https://issues.apache.org/jira/browse/THRIFT-2844) - Nodejs support broken when running under Browserify
- [THRIFT-2814](https://issues.apache.org/jira/browse/THRIFT-2814) - args/result classes not found when no namespace is set
- [THRIFT-2847](https://issues.apache.org/jira/browse/THRIFT-2847) - function IfValue() is a duplicate of System.StrUtils.IfThen
- [THRIFT-2848](https://issues.apache.org/jira/browse/THRIFT-2848) - certain Delphi tests do not build if TypeRegistry is used
- [THRIFT-2854](https://issues.apache.org/jira/browse/THRIFT-2854) - Go Struct writer and reader looses important error information
- [THRIFT-2858](https://issues.apache.org/jira/browse/THRIFT-2858) - Enable header field case insensitive match in THttpServer
- [THRIFT-2857](https://issues.apache.org/jira/browse/THRIFT-2857) - C# generator creates uncompilable code for struct constants
- [THRIFT-2860](https://issues.apache.org/jira/browse/THRIFT-2860) - Delphi server closes connection on unexpected exceptions
- [THRIFT-2868](https://issues.apache.org/jira/browse/THRIFT-2868) - Enhance error handling in the Go client
- [THRIFT-2879](https://issues.apache.org/jira/browse/THRIFT-2879) - TMemoryBuffer: using lua string in wrong way
- [THRIFT-2851](https://issues.apache.org/jira/browse/THRIFT-2851) - Remove strange public Peek() from Go transports
- [THRIFT-2852](https://issues.apache.org/jira/browse/THRIFT-2852) - Better Open/IsOpen/Close behavior for StreamTransport.
- [THRIFT-2871](https://issues.apache.org/jira/browse/THRIFT-2871) - Missing semicolon in thrift.js
- [THRIFT-2872](https://issues.apache.org/jira/browse/THRIFT-2872) - ThreadManager deadlock for task expiration
- [THRIFT-2881](https://issues.apache.org/jira/browse/THRIFT-2881) - Handle errors from Accept() correctly
- [THRIFT-2849](https://issues.apache.org/jira/browse/THRIFT-2849) - Spell errors reported by codespell tool
- [THRIFT-2870](https://issues.apache.org/jira/browse/THRIFT-2870) - C++ TJSONProtocol using locale dependent formatting
- [THRIFT-2882](https://issues.apache.org/jira/browse/THRIFT-2882) - Lua Generator: using string.len function to get struct(map,list,set) size
- [THRIFT-2864](https://issues.apache.org/jira/browse/THRIFT-2864) - JSON generator missing from Visual Studio build project
- [THRIFT-2878](https://issues.apache.org/jira/browse/THRIFT-2878) - Go validation support of required fields
- [THRIFT-2873](https://issues.apache.org/jira/browse/THRIFT-2873) - TPipe and TPipeServer don't compile on Windows with UNICODE enabled
- [THRIFT-2888](https://issues.apache.org/jira/browse/THRIFT-2888) - import of  is missing in JSON generator
- [THRIFT-2900](https://issues.apache.org/jira/browse/THRIFT-2900) - Python THttpClient does not reset socket timeout on exception
- [THRIFT-2907](https://issues.apache.org/jira/browse/THRIFT-2907) - 'ntohll' macro redefined
- [THRIFT-2884](https://issues.apache.org/jira/browse/THRIFT-2884) - Map does not serialize correctly for JSON protocol in Go library
- [THRIFT-2887](https://issues.apache.org/jira/browse/THRIFT-2887) - --with-openssl configure flag is ignored
- [THRIFT-2894](https://issues.apache.org/jira/browse/THRIFT-2894) - PHP json serializer skips maps with int/bool keys
- [THRIFT-2904](https://issues.apache.org/jira/browse/THRIFT-2904) - json_protocol_test.go fails
- [THRIFT-2906](https://issues.apache.org/jira/browse/THRIFT-2906) - library not found for -l:libboost_unit_test_framework.a
- [THRIFT-2890](https://issues.apache.org/jira/browse/THRIFT-2890) - binary data may lose bytes with JSON transport under specific circumstances
- [THRIFT-2891](https://issues.apache.org/jira/browse/THRIFT-2891) - binary data may cause a failure with JSON transport under specific circumstances
- [THRIFT-2901](https://issues.apache.org/jira/browse/THRIFT-2901) - Fix for generated TypeScript functions + indentation of JavaScript maps
- [THRIFT-2916](https://issues.apache.org/jira/browse/THRIFT-2916) - make check fails for D language
- [THRIFT-2918](https://issues.apache.org/jira/browse/THRIFT-2918) - Race condition in Python TProcessPoolServer test
- [THRIFT-2920](https://issues.apache.org/jira/browse/THRIFT-2920) - Erlang Thrift test uses wrong IDL file
- [THRIFT-2922](https://issues.apache.org/jira/browse/THRIFT-2922) - $TRIAL is used with Python tests but not tested accordingly
- [THRIFT-2912](https://issues.apache.org/jira/browse/THRIFT-2912) - Autotool build for C++ Qt library is invalid
- [THRIFT-2914](https://issues.apache.org/jira/browse/THRIFT-2914) - explicit dependency to Lua5.2 fails on some systems
- [THRIFT-2910](https://issues.apache.org/jira/browse/THRIFT-2910) - libevent is not really optional
- [THRIFT-2911](https://issues.apache.org/jira/browse/THRIFT-2911) - fix c++ version zeromq transport, the old version cannot work
- [THRIFT-2915](https://issues.apache.org/jira/browse/THRIFT-2915) - Lua generator missing from Visual Studio build project
- [THRIFT-2917](https://issues.apache.org/jira/browse/THRIFT-2917) - "make clean" breaks test/c_glib
- [THRIFT-2919](https://issues.apache.org/jira/browse/THRIFT-2919) - Haxe test server timeout too large
- [THRIFT-2923](https://issues.apache.org/jira/browse/THRIFT-2923) - JavaScript client assumes a message being written
- [THRIFT-2924](https://issues.apache.org/jira/browse/THRIFT-2924) - TNonblockingServer crashes when user-provided event_base is used
- [THRIFT-2925](https://issues.apache.org/jira/browse/THRIFT-2925) - CMake build does not work with OpenSSL nor anything installed in non-system location
- [THRIFT-2931](https://issues.apache.org/jira/browse/THRIFT-2931) - Access to undeclared static property: Thrift\Protocol\TProtocol::$TBINARYPROTOCOLACCELERATED
- [THRIFT-2893](https://issues.apache.org/jira/browse/THRIFT-2893) - CMake build fails with boost thread or std thread
- [THRIFT-2902](https://issues.apache.org/jira/browse/THRIFT-2902) - Generated c_glib code does not compile with clang
- [THRIFT-2903](https://issues.apache.org/jira/browse/THRIFT-2903) - Qt4 library built with CMake does not work
- [THRIFT-2942](https://issues.apache.org/jira/browse/THRIFT-2942) - CSharp generate invalid code for property named read or write
- [THRIFT-2932](https://issues.apache.org/jira/browse/THRIFT-2932) - Node.js Thrift connection libraries throw Exceptions into event emitter
- [THRIFT-2933](https://issues.apache.org/jira/browse/THRIFT-2933) - v0.9.2: doubles encoded in node with compact protocol cannot be decoded by python
- [THRIFT-2934](https://issues.apache.org/jira/browse/THRIFT-2934) - createServer signature mismatch
- [THRIFT-2981](https://issues.apache.org/jira/browse/THRIFT-2981) - IDL with no namespace produces unparsable PHP
- [THRIFT-2999](https://issues.apache.org/jira/browse/THRIFT-2999) - Addition of .gitattributes text auto in THRIFT-2724 causes modified files on checkout
- [THRIFT-2949](https://issues.apache.org/jira/browse/THRIFT-2949) - typo in compiler/cpp/README.md
- [THRIFT-2957](https://issues.apache.org/jira/browse/THRIFT-2957) - warning: source file %s is in a subdirectory, but option 'subdir-objects' is disabled
- [THRIFT-2953](https://issues.apache.org/jira/browse/THRIFT-2953) - TNamedPipeServerTransport is not Stop()able
- [THRIFT-2962](https://issues.apache.org/jira/browse/THRIFT-2962) - Docker Thrift env for development and testing
- [THRIFT-2971](https://issues.apache.org/jira/browse/THRIFT-2971) - C++ test and tutorial parallel build is unstable
- [THRIFT-2972](https://issues.apache.org/jira/browse/THRIFT-2972) - Missing backslash in lib/cpp/test/Makefile.am
- [THRIFT-2951](https://issues.apache.org/jira/browse/THRIFT-2951) - Fix Erlang name conflict test
- [THRIFT-2955](https://issues.apache.org/jira/browse/THRIFT-2955) - Using list of typedefs does not compile on Go
- [THRIFT-2960](https://issues.apache.org/jira/browse/THRIFT-2960) - namespace regression for Ruby
- [THRIFT-2959](https://issues.apache.org/jira/browse/THRIFT-2959) - nodejs: fix binary unit tests
- [THRIFT-2966](https://issues.apache.org/jira/browse/THRIFT-2966) - nodejs: Fix bad references to TProtocolException and TProtocolExceptionType
- [THRIFT-2970](https://issues.apache.org/jira/browse/THRIFT-2970) - grunt-jsdoc fails due to dependency issues
- [THRIFT-3001](https://issues.apache.org/jira/browse/THRIFT-3001) - C# Equals fails for binary fields (byte[])
- [THRIFT-3003](https://issues.apache.org/jira/browse/THRIFT-3003) - Missing LICENSE file prevents package from being installed
- [THRIFT-3008](https://issues.apache.org/jira/browse/THRIFT-3008) - Node.js server does not fully support exception
- [THRIFT-3007](https://issues.apache.org/jira/browse/THRIFT-3007) - Travis build is broken because of directory conflict
- [THRIFT-3009](https://issues.apache.org/jira/browse/THRIFT-3009) - TSSLSocket does not use the correct hostname (breaks certificate checks)
- [THRIFT-3011](https://issues.apache.org/jira/browse/THRIFT-3011) - C# test server testException() not implemented according to specs
- [THRIFT-3012](https://issues.apache.org/jira/browse/THRIFT-3012) - Timing problems in NamedPipe implementation due to unnecessary open/close
- [THRIFT-3019](https://issues.apache.org/jira/browse/THRIFT-3019) - Golang generator missing docstring for structs
- [THRIFT-3021](https://issues.apache.org/jira/browse/THRIFT-3021) - Service remote tool does not import stub package with package prefix
- [THRIFT-3026](https://issues.apache.org/jira/browse/THRIFT-3026) - TMultiplexedProcessor does not have a constructor
- [THRIFT-3028](https://issues.apache.org/jira/browse/THRIFT-3028) - Regression caused by THRIFT-2180
- [THRIFT-3017](https://issues.apache.org/jira/browse/THRIFT-3017) - order of map key/value types incorrect for one CTOR
- [THRIFT-3020](https://issues.apache.org/jira/browse/THRIFT-3020) - Cannot compile thrift as C++03
- [THRIFT-3024](https://issues.apache.org/jira/browse/THRIFT-3024) - User-Agent "BattleNet" used in some Thrift library files
- [THRIFT-3047](https://issues.apache.org/jira/browse/THRIFT-3047) - Uneven calls to indent_up and indent_down in Cocoa generator
- [THRIFT-3048](https://issues.apache.org/jira/browse/THRIFT-3048) - NodeJS decoding of I64 is inconsistent across protocols
- [THRIFT-3043](https://issues.apache.org/jira/browse/THRIFT-3043) - go compiler generator uses non C++98 code
- [THRIFT-3044](https://issues.apache.org/jira/browse/THRIFT-3044) - Docker README.md paths to Dockerfiles are incorrect
- [THRIFT-3040](https://issues.apache.org/jira/browse/THRIFT-3040) - bower.json wrong "main" path
- [THRIFT-3051](https://issues.apache.org/jira/browse/THRIFT-3051) - Go Thrift generator creates bad go code
- [THRIFT-3057](https://issues.apache.org/jira/browse/THRIFT-3057) - Java compiler build is broken
- [THRIFT-3061](https://issues.apache.org/jira/browse/THRIFT-3061) - C++ TSSLSocket shutdown delay/vulnerability
- [THRIFT-3062](https://issues.apache.org/jira/browse/THRIFT-3062) - C++ TServerSocket invalid port number (over 999999) causes stack corruption
- [THRIFT-3065](https://issues.apache.org/jira/browse/THRIFT-3065) - Update libthrift dependencies (slf4j, httpcore, httpclient)
- [THRIFT-3244](https://issues.apache.org/jira/browse/THRIFT-3244) - TypeScript: fix namespace of included types
- [THRIFT-3246](https://issues.apache.org/jira/browse/THRIFT-3246) - Reduce the number of trivial warnings in Windows C++ CMake builds
- [THRIFT-3224](https://issues.apache.org/jira/browse/THRIFT-3224) - Fix TNamedPipeServer unpredictable behavior on accept
- [THRIFT-3230](https://issues.apache.org/jira/browse/THRIFT-3230) - Python compiler generates wrong code if there is function throwing a typedef of exception with another namespace
- [THRIFT-3236](https://issues.apache.org/jira/browse/THRIFT-3236) - MaxSkipDepth never checked
- [THRIFT-3239](https://issues.apache.org/jira/browse/THRIFT-3239) - Limit recursion depth
- [THRIFT-3241](https://issues.apache.org/jira/browse/THRIFT-3241) - fatal error: runtime: cannot map pages in arena address space
- [THRIFT-3242](https://issues.apache.org/jira/browse/THRIFT-3242) - OSGi Import-Package directive is missing the Apache HTTP packages
- [THRIFT-3234](https://issues.apache.org/jira/browse/THRIFT-3234) - Limit recursion depth
- [THRIFT-3222](https://issues.apache.org/jira/browse/THRIFT-3222) - TypeScript: Generated Enums are quoted
- [THRIFT-3229](https://issues.apache.org/jira/browse/THRIFT-3229) - unexpected Timeout exception when desired bytes are only partially available
- [THRIFT-3231](https://issues.apache.org/jira/browse/THRIFT-3231) - CPP: Limit recursion depth to 64
- [THRIFT-3235](https://issues.apache.org/jira/browse/THRIFT-3235) - Limit recursion depth
- [THRIFT-3175](https://issues.apache.org/jira/browse/THRIFT-3175) - fastbinary.c python deserialize can cause huge allocations from garbage
- [THRIFT-3176](https://issues.apache.org/jira/browse/THRIFT-3176) - Union incorrectly implements ==
- [THRIFT-3177](https://issues.apache.org/jira/browse/THRIFT-3177) - Fails to run rake test
- [THRIFT-3180](https://issues.apache.org/jira/browse/THRIFT-3180) - lua plugin: framed transport do not work
- [THRIFT-3179](https://issues.apache.org/jira/browse/THRIFT-3179) - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost
- [THRIFT-3248](https://issues.apache.org/jira/browse/THRIFT-3248) - TypeScript: additional comma in method signature without parameters
- [THRIFT-3302](https://issues.apache.org/jira/browse/THRIFT-3302) - Go JSON protocol should encode Thrift byte type as signed integer string
- [THRIFT-3297](https://issues.apache.org/jira/browse/THRIFT-3297) - c_glib: an abstract base class is not generated
- [THRIFT-3294](https://issues.apache.org/jira/browse/THRIFT-3294) - TZlibTransport for Java does not write data correctly
- [THRIFT-3296](https://issues.apache.org/jira/browse/THRIFT-3296) - Go cross test does not conform to spec
- [THRIFT-3295](https://issues.apache.org/jira/browse/THRIFT-3295) - C# library does not build on Mono 4.0.2.5 or later
- [THRIFT-3293](https://issues.apache.org/jira/browse/THRIFT-3293) - JavaScript: null values turn into empty structs in constructor
- [THRIFT-3310](https://issues.apache.org/jira/browse/THRIFT-3310) - lib/erl/README.md has incorrect formatting
- [THRIFT-3319](https://issues.apache.org/jira/browse/THRIFT-3319) - CSharp tutorial will not build using the *.sln
- [THRIFT-3335](https://issues.apache.org/jira/browse/THRIFT-3335) - Ruby server does not handle processor exception
- [THRIFT-3338](https://issues.apache.org/jira/browse/THRIFT-3338) - Stray underscore in generated go when service name starts with "New"
- [THRIFT-3324](https://issues.apache.org/jira/browse/THRIFT-3324) - Update Go Docs for pulling all packages
- [THRIFT-3345](https://issues.apache.org/jira/browse/THRIFT-3345) - Clients blocked indefinitely when a java.lang.Error is thrown
- [THRIFT-3332](https://issues.apache.org/jira/browse/THRIFT-3332) - make dist fails on clean build
- [THRIFT-3326](https://issues.apache.org/jira/browse/THRIFT-3326) - Tests do not compile under *BSD
- [THRIFT-3334](https://issues.apache.org/jira/browse/THRIFT-3334) - Markdown notation of protocol spec is malformed
- [THRIFT-3331](https://issues.apache.org/jira/browse/THRIFT-3331) - warning: ‘etype’ may be used uninitialized in this function
- [THRIFT-3349](https://issues.apache.org/jira/browse/THRIFT-3349) - Python server does not handle processor exception
- [THRIFT-3343](https://issues.apache.org/jira/browse/THRIFT-3343) - Fix haskell README
- [THRIFT-3340](https://issues.apache.org/jira/browse/THRIFT-3340) - Python: enable json tests again
- [THRIFT-3311](https://issues.apache.org/jira/browse/THRIFT-3311) - Top level README.md has incorrect formmating
- [THRIFT-2936](https://issues.apache.org/jira/browse/THRIFT-2936) - Minor memory leak in SSL
- [THRIFT-3290](https://issues.apache.org/jira/browse/THRIFT-3290) - Using from in variable names causes the generated Python code to have errors
- [THRIFT-3225](https://issues.apache.org/jira/browse/THRIFT-3225) - Fix TPipeServer unpredictable behavior on interrupt()
- [THRIFT-3354](https://issues.apache.org/jira/browse/THRIFT-3354) - Fix word-extraction substr bug in initialism code
- [THRIFT-2006](https://issues.apache.org/jira/browse/THRIFT-2006) - TBinaryProtocol message header call name length is not validated and can be used to core the server
- [THRIFT-3329](https://issues.apache.org/jira/browse/THRIFT-3329) - C++ library unit tests don't compile against the new boost-1.59 unit test framework
- [THRIFT-2630](https://issues.apache.org/jira/browse/THRIFT-2630) - windows7 64bit pc. ipv4 and ipv6 pc.can't use
- [THRIFT-3336](https://issues.apache.org/jira/browse/THRIFT-3336) - Thrift generated streaming operators added in 0.9.2 cannot be overridden
- [THRIFT-2681](https://issues.apache.org/jira/browse/THRIFT-2681) - Core of unwind_cleanup
- [THRIFT-3317](https://issues.apache.org/jira/browse/THRIFT-3317) - cpp namespace org.apache issue appears in 0.9

### Documentation
- [THRIFT-3286](https://issues.apache.org/jira/browse/THRIFT-3286) - Apache Ant is a necessary dependency

### Improvement
- [THRIFT-227](https://issues.apache.org/jira/browse/THRIFT-227) - Byte[] in collections aren't pretty printed like regular binary fields
- [THRIFT-2744](https://issues.apache.org/jira/browse/THRIFT-2744) - Vagrantfile for Centos 6.5
- [THRIFT-2644](https://issues.apache.org/jira/browse/THRIFT-2644) - Haxe support
- [THRIFT-2756](https://issues.apache.org/jira/browse/THRIFT-2756) - register Media Type @ IANA
- [THRIFT-3076](https://issues.apache.org/jira/browse/THRIFT-3076) - Compatibility with Haxe 3.2.0
- [THRIFT-3081](https://issues.apache.org/jira/browse/THRIFT-3081) - C++ Consolidate client processing loops in TServers
- [THRIFT-3083](https://issues.apache.org/jira/browse/THRIFT-3083) - C++ Consolidate server processing loops in TSimpleServer, TThreadedServer, TThreadPoolServer
- [THRIFT-3084](https://issues.apache.org/jira/browse/THRIFT-3084) - C++ add concurrent client limit to threaded servers
- [THRIFT-3074](https://issues.apache.org/jira/browse/THRIFT-3074) -     Add compiler/cpp/lex.yythriftl.cc to gitignore.
- [THRIFT-3134](https://issues.apache.org/jira/browse/THRIFT-3134) - Remove use of deprecated "phantom.args"
- [THRIFT-3133](https://issues.apache.org/jira/browse/THRIFT-3133) - Allow "make cross" and "make precross" to run without building all languages
- [THRIFT-3142](https://issues.apache.org/jira/browse/THRIFT-3142) - Make JavaScript use downloaded libraries
- [THRIFT-3141](https://issues.apache.org/jira/browse/THRIFT-3141) - Improve logging of JavaScript test
- [THRIFT-3144](https://issues.apache.org/jira/browse/THRIFT-3144) - Proposal: make String representation of enums in generated go code less verbose
- [THRIFT-3130](https://issues.apache.org/jira/browse/THRIFT-3130) - Remove the last vestiges of THRIFT_OVERLOAD_IF from THRIFT-1316
- [THRIFT-3131](https://issues.apache.org/jira/browse/THRIFT-3131) - Consolidate suggested import path for go thrift library to git.apache.org in docs and code
- [THRIFT-3092](https://issues.apache.org/jira/browse/THRIFT-3092) - Generated Haskell types should derive Generic
- [THRIFT-3110](https://issues.apache.org/jira/browse/THRIFT-3110) -  Print error log after cross test failures on Travis
- [THRIFT-3114](https://issues.apache.org/jira/browse/THRIFT-3114) - Using local temp variables to not pollute the global table
- [THRIFT-3106](https://issues.apache.org/jira/browse/THRIFT-3106) - CMake summary should give more information why a library is set to off
- [THRIFT-3119](https://issues.apache.org/jira/browse/THRIFT-3119) - Java's TThreadedSelectorServer has indistinguishable log messages in run()
- [THRIFT-3122](https://issues.apache.org/jira/browse/THRIFT-3122) - Javascript struct constructor should properly initialize struct and container members from plain js arguments
- [THRIFT-3151](https://issues.apache.org/jira/browse/THRIFT-3151) - Fix links to git-wip*) - should be git.apache.org
- [THRIFT-3167](https://issues.apache.org/jira/browse/THRIFT-3167) - Windows build from source instructions need to be revised
- [THRIFT-3155](https://issues.apache.org/jira/browse/THRIFT-3155) - move contrib/mingw32-toolchain.cmake to build/cmake/
- [THRIFT-3160](https://issues.apache.org/jira/browse/THRIFT-3160) - Make generated go enums implement TextMarshaller and TextUnmarshaller interfaces
- [THRIFT-3150](https://issues.apache.org/jira/browse/THRIFT-3150) - Add an option to thrift go generator to make Read and Write methods private
- [THRIFT-3149](https://issues.apache.org/jira/browse/THRIFT-3149) - Make ReadFieldN methods in generated Go code private
- [THRIFT-3172](https://issues.apache.org/jira/browse/THRIFT-3172) - Add tutorial to Thrift web site
- [THRIFT-3214](https://issues.apache.org/jira/browse/THRIFT-3214) - Add Erlang option for using maps instead of dicts
- [THRIFT-3201](https://issues.apache.org/jira/browse/THRIFT-3201) - Capture github test artifacts for failed builds
- [THRIFT-3266](https://issues.apache.org/jira/browse/THRIFT-3266) - c_glib: Multiple compiler warnings building unit tests
- [THRIFT-3285](https://issues.apache.org/jira/browse/THRIFT-3285) - c_glib: Build library with all warnings enabled, no warnings generated
- [THRIFT-1954](https://issues.apache.org/jira/browse/THRIFT-1954) - Allow for a separate connection timeout value
- [THRIFT-2098](https://issues.apache.org/jira/browse/THRIFT-2098) - Add support for Qt5+
- [THRIFT-2199](https://issues.apache.org/jira/browse/THRIFT-2199) - Remove Dense protocol (was: move to Contrib)
- [THRIFT-406](https://issues.apache.org/jira/browse/THRIFT-406) - C++ Test suite cleanup
- [THRIFT-902](https://issues.apache.org/jira/browse/THRIFT-902) - socket and connect timeout in TSocket should be distinguished
- [THRIFT-388](https://issues.apache.org/jira/browse/THRIFT-388) - Use a separate wire format for async calls
- [THRIFT-727](https://issues.apache.org/jira/browse/THRIFT-727) - support native C++ language specific exception message
- [THRIFT-1784](https://issues.apache.org/jira/browse/THRIFT-1784) - pep-3110 compliance for exception handling
- [THRIFT-1025](https://issues.apache.org/jira/browse/THRIFT-1025) - C++ ServerSocket should inherit from Socket with the necessary Ctor to listen on connections from a specific host
- [THRIFT-2269](https://issues.apache.org/jira/browse/THRIFT-2269) - Can deploy libthrift-source.jar to maven center repository
- [THRIFT-2804](https://issues.apache.org/jira/browse/THRIFT-2804) - Pull an interface out of TBaseAsyncProcessor
- [THRIFT-2806](https://issues.apache.org/jira/browse/THRIFT-2806) - more whitespace fixups
- [THRIFT-2811](https://issues.apache.org/jira/browse/THRIFT-2811) - Make remote socket address accessible
- [THRIFT-2809](https://issues.apache.org/jira/browse/THRIFT-2809) - .gitignore update for compiler's visual project
- [THRIFT-2846](https://issues.apache.org/jira/browse/THRIFT-2846) - Expose ciphers parameter from ssl.wrap_socket()
- [THRIFT-2859](https://issues.apache.org/jira/browse/THRIFT-2859) - JSON generator: output complete descriptors
- [THRIFT-2861](https://issues.apache.org/jira/browse/THRIFT-2861) - add buffered transport
- [THRIFT-2865](https://issues.apache.org/jira/browse/THRIFT-2865) - Test case for Go: SeqId out of sequence
- [THRIFT-2866](https://issues.apache.org/jira/browse/THRIFT-2866) - Go generator source code is hard to read and maintain
- [THRIFT-2880](https://issues.apache.org/jira/browse/THRIFT-2880) - Read the network address from the listener if available.
- [THRIFT-2875](https://issues.apache.org/jira/browse/THRIFT-2875) - Typo in TDenseProtocol.h comment
- [THRIFT-2874](https://issues.apache.org/jira/browse/THRIFT-2874) - TBinaryProtocol  member variable "string_buf_" is never used.
- [THRIFT-2855](https://issues.apache.org/jira/browse/THRIFT-2855) - Move contributing.md to the root of the repository
- [THRIFT-2862](https://issues.apache.org/jira/browse/THRIFT-2862) - Enable RTTI and/or build macros for generated code
- [THRIFT-2876](https://issues.apache.org/jira/browse/THRIFT-2876) -  Add test for THRIFT-2526 Assignment operators and copy constructors in c++ don't copy the __isset struct
- [THRIFT-2897](https://issues.apache.org/jira/browse/THRIFT-2897) - Generate -isEqual: and -hash methods
- [THRIFT-2909](https://issues.apache.org/jira/browse/THRIFT-2909) - Improve travis build
- [THRIFT-2921](https://issues.apache.org/jira/browse/THRIFT-2921) - Make Erlang impl ready for OTP 18 release (dict/0 and set/0 are deprecated)
- [THRIFT-2928](https://issues.apache.org/jira/browse/THRIFT-2928) - Rename the erlang test_server module
- [THRIFT-2940](https://issues.apache.org/jira/browse/THRIFT-2940) - Allow installing Thrift from git as NPM module by providing package.json in top level directory
- [THRIFT-2937](https://issues.apache.org/jira/browse/THRIFT-2937) - Allow setting a maximum frame size in TFramedTransport
- [THRIFT-2976](https://issues.apache.org/jira/browse/THRIFT-2976) - nodejs: xhr and websocket support for browserify
- [THRIFT-2996](https://issues.apache.org/jira/browse/THRIFT-2996) - Test for Haxe 3.1.3 or better
- [THRIFT-2969](https://issues.apache.org/jira/browse/THRIFT-2969) - nodejs: DRY up library tests
- [THRIFT-2973](https://issues.apache.org/jira/browse/THRIFT-2973) - Update Haxe lib readme regarding Haxe 3.1.3
- [THRIFT-2952](https://issues.apache.org/jira/browse/THRIFT-2952) - Improve handling of Server.Stop()
- [THRIFT-2964](https://issues.apache.org/jira/browse/THRIFT-2964) - nodejs: move protocols and transports into separate files
- [THRIFT-2963](https://issues.apache.org/jira/browse/THRIFT-2963) - nodejs) - add test coverage
- [THRIFT-3006](https://issues.apache.org/jira/browse/THRIFT-3006) - Attach 'omitempty' json tag for optional fields in Go
- [THRIFT-3027](https://issues.apache.org/jira/browse/THRIFT-3027) - Go compiler does not ensure common initialisms have consistent case
- [THRIFT-3030](https://issues.apache.org/jira/browse/THRIFT-3030) - TThreadedServer: Property for number of clientThreads
- [THRIFT-3023](https://issues.apache.org/jira/browse/THRIFT-3023) - Go compiler is a little overly conservative with names of attributes
- [THRIFT-3018](https://issues.apache.org/jira/browse/THRIFT-3018) - Compact protocol for Delphi
- [THRIFT-3025](https://issues.apache.org/jira/browse/THRIFT-3025) - Change pure Int constants into @enums (where possible)
- [THRIFT-3031](https://issues.apache.org/jira/browse/THRIFT-3031) - migrate "shouldStop" flag to TServer
- [THRIFT-3022](https://issues.apache.org/jira/browse/THRIFT-3022) - Compact protocol for Haxe
- [THRIFT-3041](https://issues.apache.org/jira/browse/THRIFT-3041) - Generate asynchronous clients for Cocoa
- [THRIFT-3053](https://issues.apache.org/jira/browse/THRIFT-3053) - Perl SSL Socket Support (Encryption)
- [THRIFT-3247](https://issues.apache.org/jira/browse/THRIFT-3247) - Generate a C++ thread-safe client
- [THRIFT-3217](https://issues.apache.org/jira/browse/THRIFT-3217) - Provide a little endian variant of the binary protocol in C++
- [THRIFT-3223](https://issues.apache.org/jira/browse/THRIFT-3223) - TypeScript: Add initial support for Enum Maps
- [THRIFT-3220](https://issues.apache.org/jira/browse/THRIFT-3220) - Option to suppress @Generated Annotation entirely
- [THRIFT-3300](https://issues.apache.org/jira/browse/THRIFT-3300) - Reimplement TZlibTransport in Java using streams
- [THRIFT-3288](https://issues.apache.org/jira/browse/THRIFT-3288) - c_glib: Build unit tests with all warnings enabled, no warnings generated
- [THRIFT-3347](https://issues.apache.org/jira/browse/THRIFT-3347) - Improve cross test servers and clients
- [THRIFT-3342](https://issues.apache.org/jira/browse/THRIFT-3342) - Improve ruby cross test client and server compatibility
- [THRIFT-2296](https://issues.apache.org/jira/browse/THRIFT-2296) - Add C++ Base class for service
- [THRIFT-3337](https://issues.apache.org/jira/browse/THRIFT-3337) - Add testBool method to cross tests
- [THRIFT-3303](https://issues.apache.org/jira/browse/THRIFT-3303) - Disable concurrent cabal jobs on Travis to avoid GHC crash
- [THRIFT-2623](https://issues.apache.org/jira/browse/THRIFT-2623) - Docker container for Thrift
- [THRIFT-3298](https://issues.apache.org/jira/browse/THRIFT-3298) - thrift endian converters may conflict with other libraries
- [THRIFT-1559](https://issues.apache.org/jira/browse/THRIFT-1559) - Provide memory pool for TBinaryProtocol to eliminate memory fragmentation
- [THRIFT-424](https://issues.apache.org/jira/browse/THRIFT-424) - Steal ProtocolBuffers' VarInt implementation for C++

### New Feature
- [THRIFT-3070](https://issues.apache.org/jira/browse/THRIFT-3070) - Add ability to set the LocalCertificateSelectionCallback
- [THRIFT-1909](https://issues.apache.org/jira/browse/THRIFT-1909) - Java: Add compiler flag to use the "option pattern" for optional fields
- [THRIFT-2099](https://issues.apache.org/jira/browse/THRIFT-2099) - Stop TThreadPoolServer with alive connections.
- [THRIFT-123](https://issues.apache.org/jira/browse/THRIFT-123) - implement TZlibTransport in Java
- [THRIFT-2368](https://issues.apache.org/jira/browse/THRIFT-2368) - New option: reuse-objects for Java generator
- [THRIFT-2836](https://issues.apache.org/jira/browse/THRIFT-2836) - Optionally generate C++11 MoveConstructible types
- [THRIFT-2824](https://issues.apache.org/jira/browse/THRIFT-2824) - Flag to disable html escaping doctext
- [THRIFT-2819](https://issues.apache.org/jira/browse/THRIFT-2819) - Add WebsSocket client to node.js
- [THRIFT-3050](https://issues.apache.org/jira/browse/THRIFT-3050) - Client certificate authentication for non-http TLS in C#
- [THRIFT-3292](https://issues.apache.org/jira/browse/THRIFT-3292) - Implement TZlibTransport in Go

### Question
- [THRIFT-2583](https://issues.apache.org/jira/browse/THRIFT-2583) - Thrift on xPC target (SpeedGoat)
- [THRIFT-2592](https://issues.apache.org/jira/browse/THRIFT-2592) - thrift server using c_glib
- [THRIFT-2832](https://issues.apache.org/jira/browse/THRIFT-2832) - c_glib: Handle string lists correctly
- [THRIFT-3136](https://issues.apache.org/jira/browse/THRIFT-3136) - thrift installation problem on mac
- [THRIFT-3346](https://issues.apache.org/jira/browse/THRIFT-3346) - c_glib: Tutorials example crashes saying Calculator.ping implementation returned FALSE but did not set an error

### Sub-task
- [THRIFT-2578](https://issues.apache.org/jira/browse/THRIFT-2578) - Moving 'make cross' from test.sh to test.py
- [THRIFT-2734](https://issues.apache.org/jira/browse/THRIFT-2734) - Go coding standards
- [THRIFT-2748](https://issues.apache.org/jira/browse/THRIFT-2748) - Add Vagrantfile for Centos 6.5
- [THRIFT-2753](https://issues.apache.org/jira/browse/THRIFT-2753) - Misc. Haxe improvements
- [THRIFT-2640](https://issues.apache.org/jira/browse/THRIFT-2640) - Compact Protocol in Cocoa
- [THRIFT-3262](https://issues.apache.org/jira/browse/THRIFT-3262) - warning: overflow in implicit constant conversion in DenseProtoTest.cpp
- [THRIFT-3194](https://issues.apache.org/jira/browse/THRIFT-3194) - Can't build with go enabled.  gomock SCC path incorrect.
- [THRIFT-3275](https://issues.apache.org/jira/browse/THRIFT-3275) - c_glib tutorial warnings in generated code
- [THRIFT-1125](https://issues.apache.org/jira/browse/THRIFT-1125) - Multiplexing support for the Ruby Library
- [THRIFT-2807](https://issues.apache.org/jira/browse/THRIFT-2807) - PHP Code Style
- [THRIFT-2841](https://issues.apache.org/jira/browse/THRIFT-2841) - Add comprehensive integration tests for the whole Go stack
- [THRIFT-2815](https://issues.apache.org/jira/browse/THRIFT-2815) - Haxe: Support for Multiplexing Services on any Transport, Protocol and Server
- [THRIFT-2886](https://issues.apache.org/jira/browse/THRIFT-2886) - Integrate binary type in standard Thrift cross test
- [THRIFT-2946](https://issues.apache.org/jira/browse/THRIFT-2946) - Enhance usability of cross test framework
- [THRIFT-2967](https://issues.apache.org/jira/browse/THRIFT-2967) - Add .editorconfig to root
- [THRIFT-3033](https://issues.apache.org/jira/browse/THRIFT-3033) - Perl: Support for Multiplexing Services on any Transport, Protocol and Server
- [THRIFT-3174](https://issues.apache.org/jira/browse/THRIFT-3174) - Initialism code in the Go compiler doesn't check first word
- [THRIFT-3193](https://issues.apache.org/jira/browse/THRIFT-3193) - Option to suppress date value in @Generated annotation
- [THRIFT-3305](https://issues.apache.org/jira/browse/THRIFT-3305) - Missing dist files for 0.9.3 release candidate
- [THRIFT-3341](https://issues.apache.org/jira/browse/THRIFT-3341) - Add testBool methods
- [THRIFT-3308](https://issues.apache.org/jira/browse/THRIFT-3308) - Fix broken test cases for 0.9.3 release candidate

### Task
- [THRIFT-2834](https://issues.apache.org/jira/browse/THRIFT-2834) - Remove semi-colons from python code generator
- [THRIFT-2853](https://issues.apache.org/jira/browse/THRIFT-2853) - Adjust comments not applying anymore after THRIFT-2852

### Test
- [THRIFT-3211](https://issues.apache.org/jira/browse/THRIFT-3211) - Add make cross support for php TCompactProtocol

### Wish
- [THRIFT-2838](https://issues.apache.org/jira/browse/THRIFT-2838) - TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number

## 0.9.2

### Bug
- [THRIFT-2793](https://issues.apache.org/jira/browse/THRIFT-2793) - Go compiler produces uncompilable code
- [THRIFT-1481](https://issues.apache.org/jira/browse/THRIFT-1481) - Unix domain sockets in C++ do not support the abstract namespace
- [THRIFT-1455](https://issues.apache.org/jira/browse/THRIFT-1455) - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms
- [THRIFT-1579](https://issues.apache.org/jira/browse/THRIFT-1579) - PHP Extension) - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize
- [THRIFT-1584](https://issues.apache.org/jira/browse/THRIFT-1584) - Error: could not SetMinThreads in ThreadPool on single-core machines
- [THRIFT-1614](https://issues.apache.org/jira/browse/THRIFT-1614) - Thrift build from svn repo sources fails with automake-1.12
- [THRIFT-1047](https://issues.apache.org/jira/browse/THRIFT-1047) - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string
- [THRIFT-1639](https://issues.apache.org/jira/browse/THRIFT-1639) - Java/Python: Serialization/Deserialization of double type using CompactProtocol
- [THRIFT-1647](https://issues.apache.org/jira/browse/THRIFT-1647) - NodeJS BufferedTransport does not work beyond the hello-world example
- [THRIFT-2130](https://issues.apache.org/jira/browse/THRIFT-2130) - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha
- [THRIFT-2140](https://issues.apache.org/jira/browse/THRIFT-2140) - Error compiling cpp tutorials
- [THRIFT-2139](https://issues.apache.org/jira/browse/THRIFT-2139) - MSVC 2012 Error) - Cannot compile due to BoostThreadFactory
- [THRIFT-2138](https://issues.apache.org/jira/browse/THRIFT-2138) - pkgconfig file created with wrong include path
- [THRIFT-2160](https://issues.apache.org/jira/browse/THRIFT-2160) - Warning in thrift.h when compiling with -Wunused and NDEBUG
- [THRIFT-2158](https://issues.apache.org/jira/browse/THRIFT-2158) - Compact, JSON, and SimpleJSON protocols are not working correctly
- [THRIFT-2167](https://issues.apache.org/jira/browse/THRIFT-2167) - nodejs lib throws error if options argument isn't passed
- [THRIFT-2288](https://issues.apache.org/jira/browse/THRIFT-2288) - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools
- [THRIFT-2147](https://issues.apache.org/jira/browse/THRIFT-2147) - Thrift IDL grammar allows for dotted identifier names
- [THRIFT-2145](https://issues.apache.org/jira/browse/THRIFT-2145) - Rack and Thin are not just development dependencies
- [THRIFT-2267](https://issues.apache.org/jira/browse/THRIFT-2267) - Should be able to choose socket family in Python TSocket
- [THRIFT-2276](https://issues.apache.org/jira/browse/THRIFT-2276) - java path in spec file needs updating
- [THRIFT-2281](https://issues.apache.org/jira/browse/THRIFT-2281) - Generated send/recv code ignores errors returned by the underlying protocol
- [THRIFT-2280](https://issues.apache.org/jira/browse/THRIFT-2280) - TJSONProtocol.Flush() does not really flush the transport
- [THRIFT-2274](https://issues.apache.org/jira/browse/THRIFT-2274) - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors
- [THRIFT-2265](https://issues.apache.org/jira/browse/THRIFT-2265) - php library doesn't build
- [THRIFT-2232](https://issues.apache.org/jira/browse/THRIFT-2232) - IsSet* broken in Go
- [THRIFT-2246](https://issues.apache.org/jira/browse/THRIFT-2246) - Unset enum value is printed by ToString()
- [THRIFT-2240](https://issues.apache.org/jira/browse/THRIFT-2240) - thrift.vim (contrib) does not correctly handle 'union'
- [THRIFT-2243](https://issues.apache.org/jira/browse/THRIFT-2243) - TNonblockingServer in thrift crashes when TFramedTransport opens
- [THRIFT-2230](https://issues.apache.org/jira/browse/THRIFT-2230) - Cannot Build on RHEL/Centos/Amazon Linux 6.x
- [THRIFT-2247](https://issues.apache.org/jira/browse/THRIFT-2247) - Go generator doesn't deal well with map keys of type binary
- [THRIFT-2253](https://issues.apache.org/jira/browse/THRIFT-2253) - Python Tornado TTornadoServer base class change
- [THRIFT-2261](https://issues.apache.org/jira/browse/THRIFT-2261) - java: error: unmappable character for encoding ASCII
- [THRIFT-2259](https://issues.apache.org/jira/browse/THRIFT-2259) - C#: unexpected null logDelegate() pointer causes AV in TServer.serve()
- [THRIFT-2225](https://issues.apache.org/jira/browse/THRIFT-2225) - SSLContext destroy before cleanupOpenSSL
- [THRIFT-2224](https://issues.apache.org/jira/browse/THRIFT-2224) - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too
- [THRIFT-2229](https://issues.apache.org/jira/browse/THRIFT-2229) - thrift failed to build on OSX 10.9 GM
- [THRIFT-2227](https://issues.apache.org/jira/browse/THRIFT-2227) - Thrift compiler generates spurious warnings with Xlint
- [THRIFT-2219](https://issues.apache.org/jira/browse/THRIFT-2219) - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies
- [THRIFT-2226](https://issues.apache.org/jira/browse/THRIFT-2226) - TServerSocket) - keepAlive wrong initialization order
- [THRIFT-2285](https://issues.apache.org/jira/browse/THRIFT-2285) - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/)
- [THRIFT-2216](https://issues.apache.org/jira/browse/THRIFT-2216) - Extraneous semicolon in TProtocolUtil.h makes clang mad
- [THRIFT-2215](https://issues.apache.org/jira/browse/THRIFT-2215) - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN.
- [THRIFT-2211](https://issues.apache.org/jira/browse/THRIFT-2211) - Exception constructor does not contain namespace prefix.
- [THRIFT-2210](https://issues.apache.org/jira/browse/THRIFT-2210) - lib/java TSimpleJSONProtocol can emit invalid JSON
- [THRIFT-2209](https://issues.apache.org/jira/browse/THRIFT-2209) - Ruby generator -- please namespace classes
- [THRIFT-2202](https://issues.apache.org/jira/browse/THRIFT-2202) - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105
- [THRIFT-2201](https://issues.apache.org/jira/browse/THRIFT-2201) - Ternary operator returns different types (build error for some compilers)
- [THRIFT-2200](https://issues.apache.org/jira/browse/THRIFT-2200) - nested structs cause generate_fingerprint() to slow down at excessive CPU load
- [THRIFT-2197](https://issues.apache.org/jira/browse/THRIFT-2197) - fix jar output directory in rpm spec file
- [THRIFT-2196](https://issues.apache.org/jira/browse/THRIFT-2196) - Fix invalid dependency in Makefile.am
- [THRIFT-2194](https://issues.apache.org/jira/browse/THRIFT-2194) - Node: Not actually prepending residual data in TFramedTransport.receiver
- [THRIFT-2193](https://issues.apache.org/jira/browse/THRIFT-2193) - Java code generator emits spurious semicolon when deep copying binary data
- [THRIFT-2191](https://issues.apache.org/jira/browse/THRIFT-2191) - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture)
- [THRIFT-2214](https://issues.apache.org/jira/browse/THRIFT-2214) - System header sys/param.h is included inside the Thrift namespace
- [THRIFT-2178](https://issues.apache.org/jira/browse/THRIFT-2178) - Thrift generator returns error exit code on --version
- [THRIFT-2171](https://issues.apache.org/jira/browse/THRIFT-2171) - NodeJS implementation has extremely low test coverage
- [THRIFT-2183](https://issues.apache.org/jira/browse/THRIFT-2183) - gem install fails on zsh
- [THRIFT-2182](https://issues.apache.org/jira/browse/THRIFT-2182) - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write)
- [THRIFT-2181](https://issues.apache.org/jira/browse/THRIFT-2181) - oneway calls don't work in NodeJS
- [THRIFT-2169](https://issues.apache.org/jira/browse/THRIFT-2169) - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time
- [THRIFT-2168](https://issues.apache.org/jira/browse/THRIFT-2168) - Node.js appears broken (at least, examples don't work as intended)
- [THRIFT-2293](https://issues.apache.org/jira/browse/THRIFT-2293) - TSSLTransportFactory.createSSLContext() leaves files open
- [THRIFT-2279](https://issues.apache.org/jira/browse/THRIFT-2279) - TSerializer only returns the first 1024 bytes serialized
- [THRIFT-2278](https://issues.apache.org/jira/browse/THRIFT-2278) - Buffered transport doesn't support writes > buffer size
- [THRIFT-2275](https://issues.apache.org/jira/browse/THRIFT-2275) - Fix memory leak in golang compact_protocol.
- [THRIFT-2282](https://issues.apache.org/jira/browse/THRIFT-2282) - Incorect code generated for some typedefs
- [THRIFT-2009](https://issues.apache.org/jira/browse/THRIFT-2009) - Go redeclaration error
- [THRIFT-1964](https://issues.apache.org/jira/browse/THRIFT-1964) - 'Isset' causes problems with C#/.NET serializers
- [THRIFT-2026](https://issues.apache.org/jira/browse/THRIFT-2026) - Fix TCompactProtocol 64 bit builds
- [THRIFT-2108](https://issues.apache.org/jira/browse/THRIFT-2108) - Fix TAsyncClientManager timeout race
- [THRIFT-2068](https://issues.apache.org/jira/browse/THRIFT-2068) - Multiple calls from same connection are not processed in node
- [THRIFT-1750](https://issues.apache.org/jira/browse/THRIFT-1750) - Make compiler build cleanly under visual studio 10
- [THRIFT-1755](https://issues.apache.org/jira/browse/THRIFT-1755) - Comment parsing bug
- [THRIFT-1771](https://issues.apache.org/jira/browse/THRIFT-1771) - "make check" fails on x64 for libboost_unit_test_framework.a
- [THRIFT-1841](https://issues.apache.org/jira/browse/THRIFT-1841) - NodeJS Thrift incorrectly parses non-UTF8-string types
- [THRIFT-1908](https://issues.apache.org/jira/browse/THRIFT-1908) - Using php thrift_protocol accelerated transfer causes core dump
- [THRIFT-1892](https://issues.apache.org/jira/browse/THRIFT-1892) - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds
- [THRIFT-2303](https://issues.apache.org/jira/browse/THRIFT-2303) - TBufferredTransport not properly closing underlying transport
- [THRIFT-2313](https://issues.apache.org/jira/browse/THRIFT-2313) - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol
- [THRIFT-2311](https://issues.apache.org/jira/browse/THRIFT-2311) - Go: invalid code generated when exception name is a go keyword
- [THRIFT-2308](https://issues.apache.org/jira/browse/THRIFT-2308) - node: TJSONProtocol parse error when reading from buffered message
- [THRIFT-2316](https://issues.apache.org/jira/browse/THRIFT-2316) - ccp: TFileTransportTest
- [THRIFT-2352](https://issues.apache.org/jira/browse/THRIFT-2352) - msvc failed to compile thrift tests
- [THRIFT-2337](https://issues.apache.org/jira/browse/THRIFT-2337) - Golang does not report TIMED_OUT exceptions
- [THRIFT-2340](https://issues.apache.org/jira/browse/THRIFT-2340) - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception
- [THRIFT-2354](https://issues.apache.org/jira/browse/THRIFT-2354) - Connection errors can lead to case_clause exceptions
- [THRIFT-2339](https://issues.apache.org/jira/browse/THRIFT-2339) - Uncaught exception in thrift c# driver
- [THRIFT-2356](https://issues.apache.org/jira/browse/THRIFT-2356) - c++ thrift client not working with ssl (SSL_connect hangs)
- [THRIFT-2331](https://issues.apache.org/jira/browse/THRIFT-2331) - Missing call to ReadStructBegin() in TApplicationException.Read()
- [THRIFT-2323](https://issues.apache.org/jira/browse/THRIFT-2323) - Uncompileable Delphi code generated for typedef'd structs
- [THRIFT-2322](https://issues.apache.org/jira/browse/THRIFT-2322) - Correctly show the number of times ExecutorService (java) has rejected the client.
- [THRIFT-2389](https://issues.apache.org/jira/browse/THRIFT-2389) - namespaces handled wrongly in acrionscript 3.0 implementation
- [THRIFT-2388](https://issues.apache.org/jira/browse/THRIFT-2388) - GoLang) - Fix data races in simple_server and server_socket
- [THRIFT-2386](https://issues.apache.org/jira/browse/THRIFT-2386) - Thrift refuses to link yylex
- [THRIFT-2375](https://issues.apache.org/jira/browse/THRIFT-2375) - Excessive 
's in generated HTML - [THRIFT-2373](https://issues.apache.org/jira/browse/THRIFT-2373) - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used - [THRIFT-2372](https://issues.apache.org/jira/browse/THRIFT-2372) - thrift/json_protocol.go:160: function ends without a return statement - [THRIFT-2371](https://issues.apache.org/jira/browse/THRIFT-2371) - ruby bundler version fails on ~1.3.1, remove and take latest avail - [THRIFT-2370](https://issues.apache.org/jira/browse/THRIFT-2370) - Compiler SEGFAULTs generating HTML documentation for complex strucre - [THRIFT-2384](https://issues.apache.org/jira/browse/THRIFT-2384) - Binary map keys produce uncompilable code in go - [THRIFT-2380](https://issues.apache.org/jira/browse/THRIFT-2380) - unreachable code (CID 1174546, CID 1174679) - [THRIFT-2378](https://issues.apache.org/jira/browse/THRIFT-2378) - service method arguments of binary type lead to uncompileable Go code - [THRIFT-2363](https://issues.apache.org/jira/browse/THRIFT-2363) - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS - [THRIFT-2359](https://issues.apache.org/jira/browse/THRIFT-2359) - TBufferedTransport doesn't clear it's buffer on a failed flush call - [THRIFT-2428](https://issues.apache.org/jira/browse/THRIFT-2428) - Python 3 setup.py support - [THRIFT-2367](https://issues.apache.org/jira/browse/THRIFT-2367) - Build failure: stdlib and boost both define uint64_t - [THRIFT-2365](https://issues.apache.org/jira/browse/THRIFT-2365) - C# decodes too many binary bytes from JSON - [THRIFT-2402](https://issues.apache.org/jira/browse/THRIFT-2402) - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated - [THRIFT-2396](https://issues.apache.org/jira/browse/THRIFT-2396) - Build Error on MacOSX - [THRIFT-2395](https://issues.apache.org/jira/browse/THRIFT-2395) - thrift Ruby gem requires development dependency 'thin' regardless of environment - [THRIFT-2414](https://issues.apache.org/jira/browse/THRIFT-2414) - c_glib fix several bug. - [THRIFT-2420](https://issues.apache.org/jira/browse/THRIFT-2420) - Go argument parser for methods without arguments does not skip fields - [THRIFT-2439](https://issues.apache.org/jira/browse/THRIFT-2439) - Bug in TProtocolDecorator Class causes parsing errors - [THRIFT-2419](https://issues.apache.org/jira/browse/THRIFT-2419) - golang) - Fix fmt.Errorf in generated code - [THRIFT-2418](https://issues.apache.org/jira/browse/THRIFT-2418) - Go handler function panics on internal error - [THRIFT-2405](https://issues.apache.org/jira/browse/THRIFT-2405) - Node.js Multiplexer tests fail (silently) - [THRIFT-2581](https://issues.apache.org/jira/browse/THRIFT-2581) - TFDTransport destructor should not throw - [THRIFT-2575](https://issues.apache.org/jira/browse/THRIFT-2575) - Thrift includes siginfo_t within apache::thrift::protocol namespace - [THRIFT-2577](https://issues.apache.org/jira/browse/THRIFT-2577) - TFileTransport missuse of closesocket on windows platform - [THRIFT-2576](https://issues.apache.org/jira/browse/THRIFT-2576) - Implement Thrift.Protocol.prototype.skip method in JavaScript library - [THRIFT-2588](https://issues.apache.org/jira/browse/THRIFT-2588) - Thrift compiler is not buildable in Visual Studio 2010 - [THRIFT-2594](https://issues.apache.org/jira/browse/THRIFT-2594) - JS Compiler: Single quotes are not being escaped in constants. - [THRIFT-2591](https://issues.apache.org/jira/browse/THRIFT-2591) - TFramedTransport does not handle payloads split across packets correctly - [THRIFT-2599](https://issues.apache.org/jira/browse/THRIFT-2599) - Uncompileable Delphi code due to naming conflicts with IDL - [THRIFT-2590](https://issues.apache.org/jira/browse/THRIFT-2590) - C++ Visual Studio solution doesn't include Multiplexing support - [THRIFT-2595](https://issues.apache.org/jira/browse/THRIFT-2595) - Node.js: Fix global leaks and copy-paste errors - [THRIFT-2565](https://issues.apache.org/jira/browse/THRIFT-2565) - autoconf fails to find mingw-g++ cross compiler on travis CI - [THRIFT-2555](https://issues.apache.org/jira/browse/THRIFT-2555) - excessive "unused field" comments - [THRIFT-2554](https://issues.apache.org/jira/browse/THRIFT-2554) - double initialization in generated Read() method - [THRIFT-2551](https://issues.apache.org/jira/browse/THRIFT-2551) - OutOfMemoryError "unable to create new native thread" kills serve thread - [THRIFT-2543](https://issues.apache.org/jira/browse/THRIFT-2543) - Generated enum type in haskell should be qualified - [THRIFT-2560](https://issues.apache.org/jira/browse/THRIFT-2560) - Thrift compiler generator tries to concat ints with strings using + - [THRIFT-2559](https://issues.apache.org/jira/browse/THRIFT-2559) - Centos 6.5 unable to "make" with Thrift 0.9.1 - [THRIFT-2526](https://issues.apache.org/jira/browse/THRIFT-2526) - Assignment operators and copy constructors in c++ don't copy the __isset struct - [THRIFT-2454](https://issues.apache.org/jira/browse/THRIFT-2454) - c_glib: There is no gethostbyname_r() in some OS. - [THRIFT-2451](https://issues.apache.org/jira/browse/THRIFT-2451) - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors - [THRIFT-2450](https://issues.apache.org/jira/browse/THRIFT-2450) - include HowToContribute in the src repo - [THRIFT-2448](https://issues.apache.org/jira/browse/THRIFT-2448) - thrift/test/test.sh has incorrect Node.js test path - [THRIFT-2460](https://issues.apache.org/jira/browse/THRIFT-2460) - unopened socket fd must be less than zero. - [THRIFT-2459](https://issues.apache.org/jira/browse/THRIFT-2459) - --version should not exit 1 - [THRIFT-2468](https://issues.apache.org/jira/browse/THRIFT-2468) - Timestamp handling - [THRIFT-2467](https://issues.apache.org/jira/browse/THRIFT-2467) - Unable to build contrib/fb303 on OSX 10.9.2 - [THRIFT-2466](https://issues.apache.org/jira/browse/THRIFT-2466) - Improper error handling for SSL/TLS connections that don't complete a handshake - [THRIFT-2463](https://issues.apache.org/jira/browse/THRIFT-2463) - test/py/RunClientServer.py fails sometimes - [THRIFT-2458](https://issues.apache.org/jira/browse/THRIFT-2458) - Generated golang server code for "oneway" methods is incorrect - [THRIFT-2456](https://issues.apache.org/jira/browse/THRIFT-2456) - THttpClient fails when using async support outside Silverlight - [THRIFT-2524](https://issues.apache.org/jira/browse/THRIFT-2524) - Visual Studio project is missing TThreadedServer files - [THRIFT-2523](https://issues.apache.org/jira/browse/THRIFT-2523) - Visual Studio project is missing OverlappedSubmissionThread files - [THRIFT-2520](https://issues.apache.org/jira/browse/THRIFT-2520) - cpp:cob_style generates incorrect .tcc file - [THRIFT-2508](https://issues.apache.org/jira/browse/THRIFT-2508) - Uncompileable C# code due to language keywords in IDL - [THRIFT-2506](https://issues.apache.org/jira/browse/THRIFT-2506) - Update TProtocolException error codes to be used consistently throughout the library - [THRIFT-2505](https://issues.apache.org/jira/browse/THRIFT-2505) - go: struct should always be a pointer to avoid copying of potentially size-unbounded structs - [THRIFT-2515](https://issues.apache.org/jira/browse/THRIFT-2515) - TLS Method error during make - [THRIFT-2503](https://issues.apache.org/jira/browse/THRIFT-2503) - C++: Fix name collision when a struct has a member named "val" - [THRIFT-2477](https://issues.apache.org/jira/browse/THRIFT-2477) - thrift --help text with misplaced comma - [THRIFT-2492](https://issues.apache.org/jira/browse/THRIFT-2492) - test/cpp does not compile on mac - [THRIFT-2500](https://issues.apache.org/jira/browse/THRIFT-2500) - sending random data crashes thrift(golang) service - [THRIFT-2475](https://issues.apache.org/jira/browse/THRIFT-2475) - c_glib: buffered_transport_write function return always TRUE. - [THRIFT-2495](https://issues.apache.org/jira/browse/THRIFT-2495) - JavaScript/Node string constants lack proper escaping - [THRIFT-2491](https://issues.apache.org/jira/browse/THRIFT-2491) - unable to import generated ThriftTest service - [THRIFT-2490](https://issues.apache.org/jira/browse/THRIFT-2490) - c_glib: if fail to read a exception from server, client may be occurred double free - [THRIFT-2470](https://issues.apache.org/jira/browse/THRIFT-2470) - THttpHandler swallows exceptions from processor - [THRIFT-2533](https://issues.apache.org/jira/browse/THRIFT-2533) - Boost version in requirements should be updated - [THRIFT-2532](https://issues.apache.org/jira/browse/THRIFT-2532) - Java version in installation requirements should be updated - [THRIFT-2529](https://issues.apache.org/jira/browse/THRIFT-2529) - TBufferedTransport split Tcp data bug in nodeJs - [THRIFT-2537](https://issues.apache.org/jira/browse/THRIFT-2537) - Path for "go get" does not work (pull request 115) - [THRIFT-2443](https://issues.apache.org/jira/browse/THRIFT-2443) - Node fails cross lang tests - [THRIFT-2437](https://issues.apache.org/jira/browse/THRIFT-2437) - Author fields in Python setup.py must be strings not lists. - [THRIFT-2435](https://issues.apache.org/jira/browse/THRIFT-2435) - Java compiler doesn't like struct member names that are identical to an existing enum or struct type - [THRIFT-2434](https://issues.apache.org/jira/browse/THRIFT-2434) - Missing namespace import for php TMultiplexedProcessor implementation - [THRIFT-2432](https://issues.apache.org/jira/browse/THRIFT-2432) - Flaky parallel build - [THRIFT-2430](https://issues.apache.org/jira/browse/THRIFT-2430) - Crash during TThreadPoolServer shutdown - [THRIFT-667](https://issues.apache.org/jira/browse/THRIFT-667) - Period should not be allowed in identifier names - [THRIFT-1212](https://issues.apache.org/jira/browse/THRIFT-1212) - Members capital case conflict - [THRIFT-2584](https://issues.apache.org/jira/browse/THRIFT-2584) - Error handler not listened on javascript client - [THRIFT-2294](https://issues.apache.org/jira/browse/THRIFT-2294) - Incorrect Makefile generation - [THRIFT-2601](https://issues.apache.org/jira/browse/THRIFT-2601) - Fix vagrant to work again for builds again - [THRIFT-2092](https://issues.apache.org/jira/browse/THRIFT-2092) - TNonblocking server should release handler as soon as connection closes - [THRIFT-2557](https://issues.apache.org/jira/browse/THRIFT-2557) - CS0542 member names cannot be the same as their enclosing type - [THRIFT-2605](https://issues.apache.org/jira/browse/THRIFT-2605) - TSocket warning on gcc 4.8.3 - [THRIFT-2607](https://issues.apache.org/jira/browse/THRIFT-2607) - ThreadManager.cpp warning on clang++ 3.4 - [THRIFT-1998](https://issues.apache.org/jira/browse/THRIFT-1998) - TCompactProtocol.tcc) - one more warning on Visual 2010 - [THRIFT-2610](https://issues.apache.org/jira/browse/THRIFT-2610) - MSVC warning in TSocket.cpp - [THRIFT-2614](https://issues.apache.org/jira/browse/THRIFT-2614) - TNonblockingServer.cpp warnings on MSVC - [THRIFT-2608](https://issues.apache.org/jira/browse/THRIFT-2608) - TNonblockingServer.cpp warnings on clang 3.4 - [THRIFT-2606](https://issues.apache.org/jira/browse/THRIFT-2606) - ThreadManager.h warning in clang++ 3.4 - [THRIFT-2609](https://issues.apache.org/jira/browse/THRIFT-2609) - TFileTransport.h unused field warning (clang 3.4) - [THRIFT-2416](https://issues.apache.org/jira/browse/THRIFT-2416) - Cannot use TCompactProtocol with MSVC - [THRIFT-1803](https://issues.apache.org/jira/browse/THRIFT-1803) - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes - [THRIFT-2385](https://issues.apache.org/jira/browse/THRIFT-2385) - Problem with gethostbyname2 during make check - [THRIFT-2262](https://issues.apache.org/jira/browse/THRIFT-2262) - thrift server 'MutateRow' operation gives no indication of success / failure - [THRIFT-2048](https://issues.apache.org/jira/browse/THRIFT-2048) - Prefer boolean context to nullptr_t conversion - [THRIFT-2528](https://issues.apache.org/jira/browse/THRIFT-2528) - Thrift Erlang Library: Multiple thrift applications in one bundle - [THRIFT-1999](https://issues.apache.org/jira/browse/THRIFT-1999) - warning on gcc 4.7 while compiling BoostMutex.cpp - [THRIFT-2104](https://issues.apache.org/jira/browse/THRIFT-2104) - Structs lose binary data when transferred from server to client in Java - [THRIFT-2184](https://issues.apache.org/jira/browse/THRIFT-2184) - undefined method rspec_verify for Thrift::MemoryBufferTransport - [THRIFT-2351](https://issues.apache.org/jira/browse/THRIFT-2351) - PHP TCompactProtocol has fails to decode messages - [THRIFT-2016](https://issues.apache.org/jira/browse/THRIFT-2016) - Resource Leak in thrift struct under compiler/cpp/src/parse/t_function.h - [THRIFT-2273](https://issues.apache.org/jira/browse/THRIFT-2273) - Please delete old releases from mirroring system - [THRIFT-2270](https://issues.apache.org/jira/browse/THRIFT-2270) - Faulty library version numbering at build or documentation - [THRIFT-2203](https://issues.apache.org/jira/browse/THRIFT-2203) - Tests keeping failing on Jenkins and Travis CI - [THRIFT-2399](https://issues.apache.org/jira/browse/THRIFT-2399) - thrift.el: recognize "//"-style comments in emacs thrift-mode - [THRIFT-2582](https://issues.apache.org/jira/browse/THRIFT-2582) - "FileTransport error" exception is raised when trying to use Java's TFileTransport - [THRIFT-1682](https://issues.apache.org/jira/browse/THRIFT-1682) - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe - [THRIFT-2357](https://issues.apache.org/jira/browse/THRIFT-2357) - recurse option has no effect when generating php - [THRIFT-2248](https://issues.apache.org/jira/browse/THRIFT-2248) - Go generator doesn't deal well with map keys of type binary - [THRIFT-2426](https://issues.apache.org/jira/browse/THRIFT-2426) - clarify IP rights and contributions from fbthrift - [THRIFT-2041](https://issues.apache.org/jira/browse/THRIFT-2041) - TNonblocking server compilation on windows (ARITHMETIC_RIGHT_SHIFT) - [THRIFT-2400](https://issues.apache.org/jira/browse/THRIFT-2400) - thrift.el: recognize "//"-style comments in emacs thrift-mode - [THRIFT-1717](https://issues.apache.org/jira/browse/THRIFT-1717) - Fix deb build in jenkins - [THRIFT-2266](https://issues.apache.org/jira/browse/THRIFT-2266) - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) - [THRIFT-1300](https://issues.apache.org/jira/browse/THRIFT-1300) - Test failures with parallel builds (make -j) - [THRIFT-2487](https://issues.apache.org/jira/browse/THRIFT-2487) - Tutorial requires two IDL files but only one is linked from the Thrift web site - [THRIFT-2329](https://issues.apache.org/jira/browse/THRIFT-2329) - missing release tags within git - [THRIFT-2306](https://issues.apache.org/jira/browse/THRIFT-2306) - concurent client calls with nodejs - [THRIFT-2222](https://issues.apache.org/jira/browse/THRIFT-2222) - ruby gem cannot be compiled on OS X mavericks - [THRIFT-2381](https://issues.apache.org/jira/browse/THRIFT-2381) - code which generated by thrift2/hbase.thrift compile error - [THRIFT-2390](https://issues.apache.org/jira/browse/THRIFT-2390) - no close event when connection lost - [THRIFT-2146](https://issues.apache.org/jira/browse/THRIFT-2146) - Unable to pass multiple "--gen" options to the thrift compiler - [THRIFT-2438](https://issues.apache.org/jira/browse/THRIFT-2438) - Unexpected readFieldEnd call causes JSON Parsing errors - [THRIFT-2498](https://issues.apache.org/jira/browse/THRIFT-2498) - Error message "Invalid method name" while trying to call HBase Thrift API - [THRIFT-841](https://issues.apache.org/jira/browse/THRIFT-841) - Build cruft - [THRIFT-2570](https://issues.apache.org/jira/browse/THRIFT-2570) - Wrong URL given in http://thrift.apache.org/developers - [THRIFT-2604](https://issues.apache.org/jira/browse/THRIFT-2604) - Fix debian packaging - [THRIFT-2618](https://issues.apache.org/jira/browse/THRIFT-2618) - Unignore /aclocal files required for build - [THRIFT-2562](https://issues.apache.org/jira/browse/THRIFT-2562) - ./configure create MakeFile in lib/d with errors - [THRIFT-2593](https://issues.apache.org/jira/browse/THRIFT-2593) - Unable to build thrift on ubuntu-12.04 (Precise) - [THRIFT-2461](https://issues.apache.org/jira/browse/THRIFT-2461) - Can't install thrift-0.8.0 on OS X 10.9.2 - [THRIFT-2602](https://issues.apache.org/jira/browse/THRIFT-2602) - Fix missing dist files - [THRIFT-2620](https://issues.apache.org/jira/browse/THRIFT-2620) - Fix python packaging - [THRIFT-2545](https://issues.apache.org/jira/browse/THRIFT-2545) - Test CPP fails to build (possibly typo) ## Documentation - [THRIFT-2155](https://issues.apache.org/jira/browse/THRIFT-2155) - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h - [THRIFT-1991](https://issues.apache.org/jira/browse/THRIFT-1991) - Add exceptions to examples - [THRIFT-2334](https://issues.apache.org/jira/browse/THRIFT-2334) - add a tutorial for node JS - [THRIFT-2392](https://issues.apache.org/jira/browse/THRIFT-2392) - Actionscript tutorial - [THRIFT-2383](https://issues.apache.org/jira/browse/THRIFT-2383) - contrib: sample for connecting Thrift with Rebus - [THRIFT-2382](https://issues.apache.org/jira/browse/THRIFT-2382) - contrib: sample for connecting Thrift with STOMP ### Improvement - [THRIFT-1457](https://issues.apache.org/jira/browse/THRIFT-1457) - Capacity of TframedTransport write buffer is never reset - [THRIFT-1135](https://issues.apache.org/jira/browse/THRIFT-1135) - Node.js tutorial - [THRIFT-1371](https://issues.apache.org/jira/browse/THRIFT-1371) - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris - [THRIFT-2142](https://issues.apache.org/jira/browse/THRIFT-2142) - Minor tweaks to thrift.el for better emacs package compatibility - [THRIFT-2268](https://issues.apache.org/jira/browse/THRIFT-2268) - Modify TSaslTransport to ignore TCP health checks from loadbalancers - [THRIFT-2264](https://issues.apache.org/jira/browse/THRIFT-2264) - GitHub page incorrectly states that Thrift is still incubating - [THRIFT-2263](https://issues.apache.org/jira/browse/THRIFT-2263) - Always generate good hashCode for Java - [THRIFT-2233](https://issues.apache.org/jira/browse/THRIFT-2233) - Java compiler should defensively copy its binary inputs - [THRIFT-2239](https://issues.apache.org/jira/browse/THRIFT-2239) - Address FindBugs errors - [THRIFT-2249](https://issues.apache.org/jira/browse/THRIFT-2249) - Add SMP Build option to thrift.spec (and three config defines) - [THRIFT-2254](https://issues.apache.org/jira/browse/THRIFT-2254) - Exceptions generated by Go compiler should implement error interface - [THRIFT-2260](https://issues.apache.org/jira/browse/THRIFT-2260) - Thrift imposes unneeded dependency on commons-lang3 - [THRIFT-2258](https://issues.apache.org/jira/browse/THRIFT-2258) - Add TLS v1.1/1.2 support to TSSLSocket.cpp - [THRIFT-2205](https://issues.apache.org/jira/browse/THRIFT-2205) - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes - [THRIFT-2204](https://issues.apache.org/jira/browse/THRIFT-2204) - SSL client for the cocoa client - [THRIFT-2172](https://issues.apache.org/jira/browse/THRIFT-2172) - Java compiler allocates optionals array for every struct with an optional field - [THRIFT-2185](https://issues.apache.org/jira/browse/THRIFT-2185) - use cabal instead of runhaskell in haskell library - [THRIFT-1926](https://issues.apache.org/jira/browse/THRIFT-1926) - PHP Constant Generation Refactoring - [THRIFT-2029](https://issues.apache.org/jira/browse/THRIFT-2029) - Port C++ tests to Windows - [THRIFT-2054](https://issues.apache.org/jira/browse/THRIFT-2054) - TSimpleFileTransport) - Java Lib has no straight forward TTransport based file transport - [THRIFT-2040](https://issues.apache.org/jira/browse/THRIFT-2040) - "uninitialized variable" warnings on MSVC/windows - [THRIFT-2034](https://issues.apache.org/jira/browse/THRIFT-2034) - Give developers' C++ code direct access to socket FDs on server side - [THRIFT-2095](https://issues.apache.org/jira/browse/THRIFT-2095) - Use print function for Python 3 compatibility - [THRIFT-1868](https://issues.apache.org/jira/browse/THRIFT-1868) - Make the TPC backlog configurable in the Java servers - [THRIFT-1813](https://issues.apache.org/jira/browse/THRIFT-1813) - Add @Generated annotation to generated classes - [THRIFT-1815](https://issues.apache.org/jira/browse/THRIFT-1815) - Code generators line buffer output - [THRIFT-2305](https://issues.apache.org/jira/browse/THRIFT-2305) - TFramedTransport empty constructor should probably be private - [THRIFT-2304](https://issues.apache.org/jira/browse/THRIFT-2304) - Move client assignments from construtor in method - [THRIFT-2309](https://issues.apache.org/jira/browse/THRIFT-2309) - Ruby (gem) & PHP RPM subpackages - [THRIFT-2318](https://issues.apache.org/jira/browse/THRIFT-2318) - perl: dependency Class::Accessor not checked - [THRIFT-2317](https://issues.apache.org/jira/browse/THRIFT-2317) - exclude tutorial from build - [THRIFT-2320](https://issues.apache.org/jira/browse/THRIFT-2320) - Program level doctext does not get attached by parser - [THRIFT-2349](https://issues.apache.org/jira/browse/THRIFT-2349) - Golang) - improve tutorial - [THRIFT-2348](https://issues.apache.org/jira/browse/THRIFT-2348) - PHP Generator: add array typehint to functions - [THRIFT-2344](https://issues.apache.org/jira/browse/THRIFT-2344) - configure.ac: compiler-only option - [THRIFT-2343](https://issues.apache.org/jira/browse/THRIFT-2343) - Golang) - Return a single error for all exceptions instead of multiple return values - [THRIFT-2341](https://issues.apache.org/jira/browse/THRIFT-2341) - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") - [THRIFT-2355](https://issues.apache.org/jira/browse/THRIFT-2355) - Add SSL and Web Socket Support to Node and JavaScript - [THRIFT-2350](https://issues.apache.org/jira/browse/THRIFT-2350) - Add async calls to normal JavaScript - [THRIFT-2330](https://issues.apache.org/jira/browse/THRIFT-2330) - Generate PHPDoc comments - [THRIFT-2332](https://issues.apache.org/jira/browse/THRIFT-2332) - RPMBUILD: run bootstrap (if needed) - [THRIFT-2391](https://issues.apache.org/jira/browse/THRIFT-2391) - simple socket transport for actionscript 3.0 - [THRIFT-2376](https://issues.apache.org/jira/browse/THRIFT-2376) - nodejs: allow Promise style calls for client and server - [THRIFT-2369](https://issues.apache.org/jira/browse/THRIFT-2369) - Add ssl support for nodejs implementation - [THRIFT-2401](https://issues.apache.org/jira/browse/THRIFT-2401) - Haskell tutorial compiles - [THRIFT-2417](https://issues.apache.org/jira/browse/THRIFT-2417) - C# Union classes are not partial - [THRIFT-2415](https://issues.apache.org/jira/browse/THRIFT-2415) - Named pipes server performance & message mode - [THRIFT-2404](https://issues.apache.org/jira/browse/THRIFT-2404) - emit warning on (typically inefficient) list - [THRIFT-2398](https://issues.apache.org/jira/browse/THRIFT-2398) - Improve Node Server Library - [THRIFT-2397](https://issues.apache.org/jira/browse/THRIFT-2397) - Add CORS and CSP support for JavaScript and Node.js libraries - [THRIFT-2407](https://issues.apache.org/jira/browse/THRIFT-2407) - use markdown (rename README => README.md) - [THRIFT-2300](https://issues.apache.org/jira/browse/THRIFT-2300) - D configure info output should follow same format as other languages - [THRIFT-2579](https://issues.apache.org/jira/browse/THRIFT-2579) - Windows CE support - [THRIFT-2574](https://issues.apache.org/jira/browse/THRIFT-2574) - Compiler option to generate namespace directories for Ruby - [THRIFT-2571](https://issues.apache.org/jira/browse/THRIFT-2571) - Simplify cross compilation using CMake - [THRIFT-2569](https://issues.apache.org/jira/browse/THRIFT-2569) - Introduce file to specify third party library locations on Windows - [THRIFT-2568](https://issues.apache.org/jira/browse/THRIFT-2568) - Implement own certificate handler - [THRIFT-2552](https://issues.apache.org/jira/browse/THRIFT-2552) - eliminate warning from configure.ac - [THRIFT-2549](https://issues.apache.org/jira/browse/THRIFT-2549) - Generate json tag for struct members. use go.tag annotation to override the default generated tag. - [THRIFT-2544](https://issues.apache.org/jira/browse/THRIFT-2544) - Add support for socket transport for c# library when using Windows Phone projects - [THRIFT-2453](https://issues.apache.org/jira/browse/THRIFT-2453) - haskell tutorial: fix up division by 0 example - [THRIFT-2449](https://issues.apache.org/jira/browse/THRIFT-2449) - Enhance typedef structure to distinguish between forwards and real typedefs - [THRIFT-2446](https://issues.apache.org/jira/browse/THRIFT-2446) - There is no way to handle server stream errors - [THRIFT-2455](https://issues.apache.org/jira/browse/THRIFT-2455) - Allow client certificates to be used with THttpClient - [THRIFT-2511](https://issues.apache.org/jira/browse/THRIFT-2511) - Node.js needs the compact protocol - [THRIFT-2493](https://issues.apache.org/jira/browse/THRIFT-2493) - Node.js lib needs HTTP client - [THRIFT-2502](https://issues.apache.org/jira/browse/THRIFT-2502) - Optimize go implementations of binary and compact protocols for speed - [THRIFT-2494](https://issues.apache.org/jira/browse/THRIFT-2494) - Add enum toString helper function in c_glib - [THRIFT-2471](https://issues.apache.org/jira/browse/THRIFT-2471) - Make cpp.ref annotation language agnostic - [THRIFT-2497](https://issues.apache.org/jira/browse/THRIFT-2497) - server and client for test/go, also several fixes and improvements - [THRIFT-2535](https://issues.apache.org/jira/browse/THRIFT-2535) - TJSONProtocol when serialized yields TField ids rather than names - [THRIFT-2220](https://issues.apache.org/jira/browse/THRIFT-2220) - Add a new struct structv? - [THRIFT-1352](https://issues.apache.org/jira/browse/THRIFT-1352) - Thrift server - [THRIFT-989](https://issues.apache.org/jira/browse/THRIFT-989) - Push boost m4 macros upstream - [THRIFT-1349](https://issues.apache.org/jira/browse/THRIFT-1349) - Remove unnecessary print outs - [THRIFT-2496](https://issues.apache.org/jira/browse/THRIFT-2496) - server and client for test/go, also several fixes and improvements - [THRIFT-1114](https://issues.apache.org/jira/browse/THRIFT-1114) - Maven publish shouldn't require passwords hardcoded in settings.xml - [THRIFT-2043](https://issues.apache.org/jira/browse/THRIFT-2043) - visual 2010 warnings) - unreachable code - [THRIFT-1683](https://issues.apache.org/jira/browse/THRIFT-1683) - Implement alternatives to Javascript Client side Transport protocol, just as NPAPI and WebSocket. - [THRIFT-1746](https://issues.apache.org/jira/browse/THRIFT-1746) - provide a SPDX file - [THRIFT-1772](https://issues.apache.org/jira/browse/THRIFT-1772) - Serialization does not check types of embedded structures. - [THRIFT-2387](https://issues.apache.org/jira/browse/THRIFT-2387) - nodejs: external imports should be centralized in index.js - [THRIFT-2037](https://issues.apache.org/jira/browse/THRIFT-2037) - More general macro THRIFT_UNUSED_VARIABLE ### New Feature - [THRIFT-1012](https://issues.apache.org/jira/browse/THRIFT-1012) - Transport for DataInput DataOutput interface - [THRIFT-2256](https://issues.apache.org/jira/browse/THRIFT-2256) - Using c++11/c++0x std library replace boost library - [THRIFT-2250](https://issues.apache.org/jira/browse/THRIFT-2250) - JSON and MemoryBuffer for JavaME - [THRIFT-2114](https://issues.apache.org/jira/browse/THRIFT-2114) - Python Service Remote SSL Option - [THRIFT-1719](https://issues.apache.org/jira/browse/THRIFT-1719) - SASL client support for Python - [THRIFT-1894](https://issues.apache.org/jira/browse/THRIFT-1894) - Thrift multi-threaded async Java Server using Java 7 AsynchronousChannelGroup - [THRIFT-1893](https://issues.apache.org/jira/browse/THRIFT-1893) - HTTP/JSON server/client for node js - [THRIFT-2347](https://issues.apache.org/jira/browse/THRIFT-2347) - C# TLS Transport based on THRIFT-181 - [THRIFT-2377](https://issues.apache.org/jira/browse/THRIFT-2377) - Allow addition of custom HTTP Headers to an HTTP Transport - [THRIFT-2408](https://issues.apache.org/jira/browse/THRIFT-2408) - Named Pipe Transport Option for C# - [THRIFT-2572](https://issues.apache.org/jira/browse/THRIFT-2572) - Add string/collection length limit checks (from C++) to java protocol readers - [THRIFT-2469](https://issues.apache.org/jira/browse/THRIFT-2469) - "java:fullcamel" option to automatically camel-case underscored attribute names - [THRIFT-795](https://issues.apache.org/jira/browse/THRIFT-795) - Importing service functions (simulation multiple inheritance) - [THRIFT-2164](https://issues.apache.org/jira/browse/THRIFT-2164) - Add a Get/Post Http Server to Node along with examples - [THRIFT-2255](https://issues.apache.org/jira/browse/THRIFT-2255) - add Parent Class for generated Struct class ### Question - [THRIFT-2539](https://issues.apache.org/jira/browse/THRIFT-2539) - Tsocket.cpp addrinfo ai_flags = AI_ADDRCONFIG - [THRIFT-2440](https://issues.apache.org/jira/browse/THRIFT-2440) - how to connect as3 to java by thrift , - [THRIFT-2379](https://issues.apache.org/jira/browse/THRIFT-2379) - Memmory leaking while using multithreading in C++ server. - [THRIFT-2277](https://issues.apache.org/jira/browse/THRIFT-2277) - Thrift: installing fb303 error - [THRIFT-2567](https://issues.apache.org/jira/browse/THRIFT-2567) - Csharp slow ? - [THRIFT-2573](https://issues.apache.org/jira/browse/THRIFT-2573) - thrift 0.9.2 release ### Sub-task - [THRIFT-981](https://issues.apache.org/jira/browse/THRIFT-981) - cocoa: add version Info to the library - [THRIFT-2132](https://issues.apache.org/jira/browse/THRIFT-2132) - Go: Support for Multiplexing Services on any Transport, Protocol and Server - [THRIFT-2299](https://issues.apache.org/jira/browse/THRIFT-2299) - TJsonProtocol implementation for Ruby does not allow for both possible slash (solidus) encodings - [THRIFT-2298](https://issues.apache.org/jira/browse/THRIFT-2298) - TJsonProtocol implementation for C# does not allow for both possible slash (solidus) encodings - [THRIFT-2297](https://issues.apache.org/jira/browse/THRIFT-2297) - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings - [THRIFT-2271](https://issues.apache.org/jira/browse/THRIFT-2271) - JavaScript: Support for Multiplexing Services - [THRIFT-2251](https://issues.apache.org/jira/browse/THRIFT-2251) - go test for compact protocol is not running - [THRIFT-2195](https://issues.apache.org/jira/browse/THRIFT-2195) - Delphi: Add event handlers for server and processing events - [THRIFT-2176](https://issues.apache.org/jira/browse/THRIFT-2176) - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID - [THRIFT-2175](https://issues.apache.org/jira/browse/THRIFT-2175) - Wrong field type set for binary - [THRIFT-2174](https://issues.apache.org/jira/browse/THRIFT-2174) - Deserializing JSON fails in specific cases - [THRIFT-2053](https://issues.apache.org/jira/browse/THRIFT-2053) - NodeJS: Support for Multiplexing Services - [THRIFT-1914](https://issues.apache.org/jira/browse/THRIFT-1914) - Python: Support for Multiplexing Services on any Transport, Protocol and Server - [THRIFT-1810](https://issues.apache.org/jira/browse/THRIFT-1810) - add ruby to test/test.sh - [THRIFT-2310](https://issues.apache.org/jira/browse/THRIFT-2310) - PHP: Client-side support for Multiplexing Services - [THRIFT-2346](https://issues.apache.org/jira/browse/THRIFT-2346) - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - [THRIFT-2345](https://issues.apache.org/jira/browse/THRIFT-2345) - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - [THRIFT-2338](https://issues.apache.org/jira/browse/THRIFT-2338) - First doctext wrongly interpreted as program doctext in some cases - [THRIFT-2325](https://issues.apache.org/jira/browse/THRIFT-2325) - SSL test certificates - [THRIFT-2358](https://issues.apache.org/jira/browse/THRIFT-2358) - C++: add compact protocol to cross language test suite - [THRIFT-2425](https://issues.apache.org/jira/browse/THRIFT-2425) - PHP: Server-side support for Multiplexing Services - [THRIFT-2421](https://issues.apache.org/jira/browse/THRIFT-2421) - Tree/Recursive struct support in thrift - [THRIFT-2290](https://issues.apache.org/jira/browse/THRIFT-2290) - Update Go tutorial to align with THRIFT-2232 - [THRIFT-2558](https://issues.apache.org/jira/browse/THRIFT-2558) - CSharp compiler generator tries to concat ints with strings using + - [THRIFT-2507](https://issues.apache.org/jira/browse/THRIFT-2507) - Additional LUA TProtocolException error code needed? - [THRIFT-2499](https://issues.apache.org/jira/browse/THRIFT-2499) - Compiler: allow annotations without "= value" - [THRIFT-2534](https://issues.apache.org/jira/browse/THRIFT-2534) - Cross language test results should recorded to a status.md or status.html file automatically - [THRIFT-66](https://issues.apache.org/jira/browse/THRIFT-66) - Java: Allow multiplexing multiple services over a single TCP connection - [THRIFT-1681](https://issues.apache.org/jira/browse/THRIFT-1681) - Add Lua Support - [THRIFT-1727](https://issues.apache.org/jira/browse/THRIFT-1727) - Ruby-1.9: data loss: "binary" fields are re-encoded - [THRIFT-1726](https://issues.apache.org/jira/browse/THRIFT-1726) - Ruby-1.9: "binary" fields are represented by string whose encoding is "UTF-8" - [THRIFT-988](https://issues.apache.org/jira/browse/THRIFT-988) - perl: add version Info to the library via configure - [THRIFT-334](https://issues.apache.org/jira/browse/THRIFT-334) - Compact Protocol for PHP - [THRIFT-2444](https://issues.apache.org/jira/browse/THRIFT-2444) - pull request 88: thrift: clean up enum value assignment ### Task - [THRIFT-2223](https://issues.apache.org/jira/browse/THRIFT-2223) - Spam links on wiki - [THRIFT-2566](https://issues.apache.org/jira/browse/THRIFT-2566) - Please create a DOAP file for your TLP - [THRIFT-2237](https://issues.apache.org/jira/browse/THRIFT-2237) - Update archive to contain all versions - [THRIFT-962](https://issues.apache.org/jira/browse/THRIFT-962) - Tutorial page on our website is really unhelpful ### Test - [THRIFT-2327](https://issues.apache.org/jira/browse/THRIFT-2327) - nodejs: nodejs test suite should be bundled with the library - [THRIFT-2445](https://issues.apache.org/jira/browse/THRIFT-2445) - THRIFT-2384 (code generation for go maps with binary keys) should be tested - [THRIFT-2501](https://issues.apache.org/jira/browse/THRIFT-2501) - C# The test parameters from the TestServer and TestClient are different from the http://thrift.apache.org/test/ ### Wish - [THRIFT-2190](https://issues.apache.org/jira/browse/THRIFT-2190) - Add the JavaScript thrift.js lib to the Bower registry - [THRIFT-2076](https://issues.apache.org/jira/browse/THRIFT-2076) - boost::optional instead of __isset ## 0.9.1 ### Bug - [THRIFT-1440](https://issues.apache.org/jira/browse/THRIFT-1440) - debian packaging: minor-ish policy problems - [THRIFT-1402](https://issues.apache.org/jira/browse/THRIFT-1402) - Generated Y_types.js does not require() X_types.js when an include in the IDL file was used - [THRIFT-1551](https://issues.apache.org/jira/browse/THRIFT-1551) - 2 thrift file define only struct (no service), one include another, the gen nodejs file didn't have "requires" at the top - [THRIFT-1264](https://issues.apache.org/jira/browse/THRIFT-1264) - TSocketClient is queried by run loop after deallocation in Cocoa - [THRIFT-1600](https://issues.apache.org/jira/browse/THRIFT-1600) - Thrift Go Compiler and Library out of date with Go 1 Release. - [THRIFT-1603](https://issues.apache.org/jira/browse/THRIFT-1603) - Thrift IDL allows for multiple exceptions, args or struct member names to be the same - [THRIFT-1062](https://issues.apache.org/jira/browse/THRIFT-1062) - Problems with python tutorials - [THRIFT-864](https://issues.apache.org/jira/browse/THRIFT-864) - default value fails if identifier is a struct - [THRIFT-930](https://issues.apache.org/jira/browse/THRIFT-930) - Ruby and Haskell bindings don't properly support DESTDIR (makes packaging painful) - [THRIFT-820](https://issues.apache.org/jira/browse/THRIFT-820) - The readLength attribute of TBinaryProtocol is used as an instance variable and is decremented on each call of checkReadLength - [THRIFT-1640](https://issues.apache.org/jira/browse/THRIFT-1640) - None of the tutorials linked on the website contain content - [THRIFT-1637](https://issues.apache.org/jira/browse/THRIFT-1637) - NPM registry does not include version 0.8 - [THRIFT-1648](https://issues.apache.org/jira/browse/THRIFT-1648) - NodeJS clients always receive 0 for 'double' values. - [THRIFT-1660](https://issues.apache.org/jira/browse/THRIFT-1660) - Python Thrift library can be installed with pip but not easy_install - [THRIFT-1657](https://issues.apache.org/jira/browse/THRIFT-1657) - Chrome browser sending OPTIONS method before POST in xmlHttpRequest - [THRIFT-2118](https://issues.apache.org/jira/browse/THRIFT-2118) - Certificate error handling still incorrect - [THRIFT-2137](https://issues.apache.org/jira/browse/THRIFT-2137) - Ruby test lib fails jenkins build #864 - [THRIFT-2136](https://issues.apache.org/jira/browse/THRIFT-2136) - Vagrant build not compiling java, ruby, php, go libs due to missing dependencies - [THRIFT-2135](https://issues.apache.org/jira/browse/THRIFT-2135) - GO lib leaves behind test files that are auto generated - [THRIFT-2134](https://issues.apache.org/jira/browse/THRIFT-2134) - mingw-cross-compile script failing with strip errors - [THRIFT-2133](https://issues.apache.org/jira/browse/THRIFT-2133) - java TestTBinaryProtocol.java test failing - [THRIFT-2126](https://issues.apache.org/jira/browse/THRIFT-2126) - lib/cpp/src/thrift/concurrency/STD* files missing from DIST - [THRIFT-2125](https://issues.apache.org/jira/browse/THRIFT-2125) - debian missing from DIST - [THRIFT-2124](https://issues.apache.org/jira/browse/THRIFT-2124) - .o, .so, .la, .deps, .libs, gen-* files left tutorials, test and lib/cpp when making DIST - [THRIFT-2123](https://issues.apache.org/jira/browse/THRIFT-2123) - GO lib missing files in DIST build - [THRIFT-2121](https://issues.apache.org/jira/browse/THRIFT-2121) - Compilation bug for Node.js - [THRIFT-2129](https://issues.apache.org/jira/browse/THRIFT-2129) - php ext missing from dist - [THRIFT-2128](https://issues.apache.org/jira/browse/THRIFT-2128) - lib GO tests fail with funct ends without a return statement - [THRIFT-2286](https://issues.apache.org/jira/browse/THRIFT-2286) - Failed to compile Thrift0.9.1 with boost1.55 by VS2010 if select Debug-mt&x64 mode. - [THRIFT-1973](https://issues.apache.org/jira/browse/THRIFT-1973) - TCompactProtocol in C# lib does not serialize and deserialize negative int32 and int64 number correctly - [THRIFT-1992](https://issues.apache.org/jira/browse/THRIFT-1992) - casts in TCompactProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc - [THRIFT-1930](https://issues.apache.org/jira/browse/THRIFT-1930) - C# generates unsigned byte for Thrift "byte" type - [THRIFT-1929](https://issues.apache.org/jira/browse/THRIFT-1929) - Update website to use Mirrors for downloads - [THRIFT-1928](https://issues.apache.org/jira/browse/THRIFT-1928) - Race may still exist in TFileTransport::flush() - [THRIFT-1934](https://issues.apache.org/jira/browse/THRIFT-1934) - Tabs in Example section on main page are not working - [THRIFT-1933](https://issues.apache.org/jira/browse/THRIFT-1933) - Delphi generator crashes when a typedef references another typedef from an included file - [THRIFT-1942](https://issues.apache.org/jira/browse/THRIFT-1942) - Binary accelerated cpp extension does not use Thrift namespaces for Exceptions - [THRIFT-1959](https://issues.apache.org/jira/browse/THRIFT-1959) - C#: Add Union TMemoryBuffer support - [THRIFT-1958](https://issues.apache.org/jira/browse/THRIFT-1958) - C#: Use static Object.Equals instead of .Equals() calls in equals - [THRIFT-1957](https://issues.apache.org/jira/browse/THRIFT-1957) - NodeJS TFramedTransport and TBufferedTransport read bytes as unsigned - [THRIFT-1955](https://issues.apache.org/jira/browse/THRIFT-1955) - Union Type writer generated in C# does not WriteStructBegin - [THRIFT-1952](https://issues.apache.org/jira/browse/THRIFT-1952) - Travis CI - [THRIFT-1949](https://issues.apache.org/jira/browse/THRIFT-1949) - WP7 build broken - [THRIFT-1943](https://issues.apache.org/jira/browse/THRIFT-1943) - docstrings for enum values are ignored - [THRIFT-2070](https://issues.apache.org/jira/browse/THRIFT-2070) - Improper `HexChar' and 'HexVal' implementation in TJSONProtocol.cs - [THRIFT-2017](https://issues.apache.org/jira/browse/THRIFT-2017) - Resource Leak in thrift struct under compiler/cpp/src/parse/t_program.h - [THRIFT-2032](https://issues.apache.org/jira/browse/THRIFT-2032) - C# client leaks sockets/handles - [THRIFT-1996](https://issues.apache.org/jira/browse/THRIFT-1996) - JavaME Constants generation is broken / inconsistent with regular Java generation - [THRIFT-2002](https://issues.apache.org/jira/browse/THRIFT-2002) - Haskell: Test use Data.Maybe instead of Maybe - [THRIFT-2051](https://issues.apache.org/jira/browse/THRIFT-2051) - Vagrant fails to build erlang - [THRIFT-2050](https://issues.apache.org/jira/browse/THRIFT-2050) - Vagrant C# lib compile fails with TException missing - [THRIFT-1978](https://issues.apache.org/jira/browse/THRIFT-1978) - Ruby: Thrift should allow for the SSL verify mode to be set - [THRIFT-1984](https://issues.apache.org/jira/browse/THRIFT-1984) - namespace collision in python bindings - [THRIFT-1988](https://issues.apache.org/jira/browse/THRIFT-1988) - When trying to build a debian package it fails as the file NEWS doesn't exist - [THRIFT-1975](https://issues.apache.org/jira/browse/THRIFT-1975) - TBinaryProtocol CheckLength can't be used for a client - [THRIFT-1995](https://issues.apache.org/jira/browse/THRIFT-1995) - '.' allowed at end of identifier generates non-compilable code - [THRIFT-2112](https://issues.apache.org/jira/browse/THRIFT-2112) - Error in Go generator when using typedefs in map keys - [THRIFT-2088](https://issues.apache.org/jira/browse/THRIFT-2088) - Typos in Thrift compiler help text - [THRIFT-2080](https://issues.apache.org/jira/browse/THRIFT-2080) - C# multiplex processor does not catch IOException - [THRIFT-2082](https://issues.apache.org/jira/browse/THRIFT-2082) - Executing "gmake clean" is broken - [THRIFT-2102](https://issues.apache.org/jira/browse/THRIFT-2102) - constants are not referencing to correct type when included from another thrift file - [THRIFT-2100](https://issues.apache.org/jira/browse/THRIFT-2100) - typedefs are not correctly referenced when including from other thrift files - [THRIFT-2066](https://issues.apache.org/jira/browse/THRIFT-2066) - 'make install' does not install two headers required for C++ bindings - [THRIFT-2065](https://issues.apache.org/jira/browse/THRIFT-2065) - Not valid constants filename in Java - [THRIFT-2047](https://issues.apache.org/jira/browse/THRIFT-2047) - Thrift.Protocol.TCompactProtocol, intToZigZag data lost (TCompactProtocol.cs) - [THRIFT-2036](https://issues.apache.org/jira/browse/THRIFT-2036) - Thrift gem warns about class variable access from top level - [THRIFT-2057](https://issues.apache.org/jira/browse/THRIFT-2057) - Vagrant fails on php tests - [THRIFT-2105](https://issues.apache.org/jira/browse/THRIFT-2105) - Generated code for default values of collections ignores t_field::T_REQUIRED - [THRIFT-2091](https://issues.apache.org/jira/browse/THRIFT-2091) - Unnecessary 'friend' declaration causes warning in TWinsockSingleton - [THRIFT-2090](https://issues.apache.org/jira/browse/THRIFT-2090) - Go generator, fix including of other thrift files - [THRIFT-2106](https://issues.apache.org/jira/browse/THRIFT-2106) - Fix support for namespaces in GO generator - [THRIFT-1783](https://issues.apache.org/jira/browse/THRIFT-1783) - C# doesn't handle required fields correctly - [THRIFT-1782](https://issues.apache.org/jira/browse/THRIFT-1782) - async only defined in silverlight - [THRIFT-1779](https://issues.apache.org/jira/browse/THRIFT-1779) - Missing process_XXXX method in generated TProcessor implementation for all 'oneway' service functions - [THRIFT-1692](https://issues.apache.org/jira/browse/THRIFT-1692) - SO_REUSEADDR allows for socket hijacking on Windows - [THRIFT-1720](https://issues.apache.org/jira/browse/THRIFT-1720) - JRuby times out on successful connection - [THRIFT-1713](https://issues.apache.org/jira/browse/THRIFT-1713) - Named and Anonymous Pipe transport (Delphi) - [THRIFT-1699](https://issues.apache.org/jira/browse/THRIFT-1699) - Native Union#read has extra read_field_end call - [THRIFT-1749](https://issues.apache.org/jira/browse/THRIFT-1749) - Python TSSLSocket error handling obscures actual error - [THRIFT-1748](https://issues.apache.org/jira/browse/THRIFT-1748) - Guard and RWGuard macros defined in global namespace - [THRIFT-1734](https://issues.apache.org/jira/browse/THRIFT-1734) - Front webpage is still advertising v0.8 as current release - [THRIFT-1729](https://issues.apache.org/jira/browse/THRIFT-1729) - C glib refactor left empty folders in svn - [THRIFT-1767](https://issues.apache.org/jira/browse/THRIFT-1767) - unions can't have required fields (Delphi) - [THRIFT-1765](https://issues.apache.org/jira/browse/THRIFT-1765) - Incorrect error message printed for null or negative keys - [THRIFT-1778](https://issues.apache.org/jira/browse/THRIFT-1778) - Configure requires manual intervention due to tar failure - [THRIFT-1777](https://issues.apache.org/jira/browse/THRIFT-1777) - TPipeServer is UNSTOPPABLE - [THRIFT-1753](https://issues.apache.org/jira/browse/THRIFT-1753) - Multiple C++ Windows, OSX, and iOS portability issues - [THRIFT-1756](https://issues.apache.org/jira/browse/THRIFT-1756) - 'make -j 8' fails with "unterminated #ifdef" error - [THRIFT-1773](https://issues.apache.org/jira/browse/THRIFT-1773) - Python library should run on python 2.4 - [THRIFT-1769](https://issues.apache.org/jira/browse/THRIFT-1769) - unions can't have required fields (C++) - [THRIFT-1768](https://issues.apache.org/jira/browse/THRIFT-1768) - unions can't have required fields (Compiler) - [THRIFT-1666](https://issues.apache.org/jira/browse/THRIFT-1666) - htonll usage in TBinaryProtocol.tcc generates warning with MSVC2010 - [THRIFT-1919](https://issues.apache.org/jira/browse/THRIFT-1919) - libthrift depends on httpcore-4.1.3 (directly) and httpcore-4.1.4 (transitively) - [THRIFT-1864](https://issues.apache.org/jira/browse/THRIFT-1864) - implement event handler for non-blocking server - [THRIFT-1859](https://issues.apache.org/jira/browse/THRIFT-1859) - Generated error c++ code with -out and include_prefix param - [THRIFT-1869](https://issues.apache.org/jira/browse/THRIFT-1869) - TThreadPoolServer (java) dies when threadpool is consumed - [THRIFT-1842](https://issues.apache.org/jira/browse/THRIFT-1842) - Memory leak with Pipes - [THRIFT-1838](https://issues.apache.org/jira/browse/THRIFT-1838) - Can't build compiler on OS X because of missing thrifty.h - [THRIFT-1846](https://issues.apache.org/jira/browse/THRIFT-1846) - Restore socket.h header to support builds with Android NDK - [THRIFT-1850](https://issues.apache.org/jira/browse/THRIFT-1850) - make check hangs on TSocket tests in TransportTest.cpp - [THRIFT-1873](https://issues.apache.org/jira/browse/THRIFT-1873) - Binary protocol factory ignores struct read/write flags - [THRIFT-1872](https://issues.apache.org/jira/browse/THRIFT-1872) - issues with TBufferedTransport buffer - [THRIFT-1904](https://issues.apache.org/jira/browse/THRIFT-1904) - Incorrect code is generated for typedefs which use included types - [THRIFT-1903](https://issues.apache.org/jira/browse/THRIFT-1903) - PHP namespaces cause binary protocols to not be used - [THRIFT-1895](https://issues.apache.org/jira/browse/THRIFT-1895) - Delphi: reserved variable name "result" not detected properly - [THRIFT-1881](https://issues.apache.org/jira/browse/THRIFT-1881) - TNonblockingServer does not release open connections or threads on shutdown - [THRIFT-1888](https://issues.apache.org/jira/browse/THRIFT-1888) - Java Thrift client can't connect to Python Thrift server on same host - [THRIFT-1831](https://issues.apache.org/jira/browse/THRIFT-1831) - Bug in list deserializer - [THRIFT-1824](https://issues.apache.org/jira/browse/THRIFT-1824) - many compile warning, becase Thread.h includes config.h - [THRIFT-1823](https://issues.apache.org/jira/browse/THRIFT-1823) - Missing parenthesis breaks "IS_..." macro in generated code - [THRIFT-1806](https://issues.apache.org/jira/browse/THRIFT-1806) - Python generation always truncates __init__.py files - [THRIFT-1795](https://issues.apache.org/jira/browse/THRIFT-1795) - Race condition in TThreadedServerPool java implementation - [THRIFT-1794](https://issues.apache.org/jira/browse/THRIFT-1794) - C# asyncctp broken - [THRIFT-1804](https://issues.apache.org/jira/browse/THRIFT-1804) - Binary+compact protocol single byte error in Ruby library (ARM architecture): caused by different char signedness - [THRIFT-1800](https://issues.apache.org/jira/browse/THRIFT-1800) - Documentation text not always escaped correctly when rendered to HTML - [THRIFT-1788](https://issues.apache.org/jira/browse/THRIFT-1788) - C#: Constants static constructor does not compile - [THRIFT-1816](https://issues.apache.org/jira/browse/THRIFT-1816) - Need "require" included thrift files in "xxx_types.js" - [THRIFT-1907](https://issues.apache.org/jira/browse/THRIFT-1907) - Compiling namespace and sub-namespace directives for unrecognized generators should only be a warning - [THRIFT-1913](https://issues.apache.org/jira/browse/THRIFT-1913) - skipping unknown fields in java unions - [THRIFT-2553](https://issues.apache.org/jira/browse/THRIFT-2553) - C++ linker error) - transport/TSocket - [THRIFT-274](https://issues.apache.org/jira/browse/THRIFT-274) - Towards a working release/versioning process ### Documentation - [THRIFT-1971](https://issues.apache.org/jira/browse/THRIFT-1971) - [Graphviz] Adds tutorial/general description documentation - [THRIFT-2001](https://issues.apache.org/jira/browse/THRIFT-2001) - http://thrift.apache.org/ Example "C++ Server" tab is broken ### Improvement - [THRIFT-1574](https://issues.apache.org/jira/browse/THRIFT-1574) - Apache project branding requirements: DOAP file [PATCH] - [THRIFT-1347](https://issues.apache.org/jira/browse/THRIFT-1347) - Unify the exceptions returned in generated Go code - [THRIFT-1353](https://issues.apache.org/jira/browse/THRIFT-1353) - Switch to performance branch, get rid of BinaryParser - [THRIFT-1629](https://issues.apache.org/jira/browse/THRIFT-1629) - Ruby 1.9 Compatibility during Thrift configure, make, install - [THRIFT-991](https://issues.apache.org/jira/browse/THRIFT-991) - Refactor Haskell code and generator - [THRIFT-990](https://issues.apache.org/jira/browse/THRIFT-990) - Sanify gettimeofday usage codebase-wide - [THRIFT-791](https://issues.apache.org/jira/browse/THRIFT-791) - Let C++ TSimpleServer be driven by an external main loop - [THRIFT-2117](https://issues.apache.org/jira/browse/THRIFT-2117) - Cocoa TBinaryProtocol strictWrite should be set to true by default - [THRIFT-2014](https://issues.apache.org/jira/browse/THRIFT-2014) - Change C++ lib includes to use style throughout - [THRIFT-1972](https://issues.apache.org/jira/browse/THRIFT-1972) - Add support for async processors - [THRIFT-1970](https://issues.apache.org/jira/browse/THRIFT-1970) - [Graphviz] Adds option to render exceptions relationships - [THRIFT-1966](https://issues.apache.org/jira/browse/THRIFT-1966) - Support different files for SSL certificates and keys - [THRIFT-1965](https://issues.apache.org/jira/browse/THRIFT-1965) - Adds Graphviz (graph description language) generator - [THRIFT-1956](https://issues.apache.org/jira/browse/THRIFT-1956) - Switch to Apache Commons Lang 3 - [THRIFT-1962](https://issues.apache.org/jira/browse/THRIFT-1962) - Multiplex processor should send any TApplicationException back to client - [THRIFT-1960](https://issues.apache.org/jira/browse/THRIFT-1960) - main() declares 22 unused gen bools - [THRIFT-1951](https://issues.apache.org/jira/browse/THRIFT-1951) - libthrift.jar has source files in it - [THRIFT-1997](https://issues.apache.org/jira/browse/THRIFT-1997) - Add accept backlog configuration method to TServerSocket - [THRIFT-2003](https://issues.apache.org/jira/browse/THRIFT-2003) - Deprecate senum - [THRIFT-2052](https://issues.apache.org/jira/browse/THRIFT-2052) - Vagrant machine image defaults to only 384MB of RAM - [THRIFT-1980](https://issues.apache.org/jira/browse/THRIFT-1980) - Modernize Go tooling, fix go client library. - [THRIFT-1977](https://issues.apache.org/jira/browse/THRIFT-1977) - C# compiler should generate constant files prefixed with thrift file name - [THRIFT-1985](https://issues.apache.org/jira/browse/THRIFT-1985) - add a Vagrantfile to build and test Apache Thrift fully reproducible - [THRIFT-1994](https://issues.apache.org/jira/browse/THRIFT-1994) - Deprecate slist - [THRIFT-1993](https://issues.apache.org/jira/browse/THRIFT-1993) - Factory to create instances from known (generated) interface types with Delphi - [THRIFT-2081](https://issues.apache.org/jira/browse/THRIFT-2081) - Specified timeout should be used in TSocket.Open() - [THRIFT-2084](https://issues.apache.org/jira/browse/THRIFT-2084) - Delphi: Ability to create entity Thrift-generated instances based on TypeInfo - [THRIFT-2083](https://issues.apache.org/jira/browse/THRIFT-2083) - Improve the go lib: buffered Transport, save memory allocation, handle concurrent request - [THRIFT-2109](https://issues.apache.org/jira/browse/THRIFT-2109) - Secure connections should be supported in Go - [THRIFT-2107](https://issues.apache.org/jira/browse/THRIFT-2107) - minor Go generator fixes - [THRIFT-1695](https://issues.apache.org/jira/browse/THRIFT-1695) - allow warning-free compilation in VS 2012 and GNU 4.6 - [THRIFT-1735](https://issues.apache.org/jira/browse/THRIFT-1735) - integrate tutorial into regular build - [THRIFT-1716](https://issues.apache.org/jira/browse/THRIFT-1716) - max allowed connections should be PIPE_UNLIMITED_INSTANCES - [THRIFT-1715](https://issues.apache.org/jira/browse/THRIFT-1715) - Allow excluding python parts when building contrib/fb303 - [THRIFT-1733](https://issues.apache.org/jira/browse/THRIFT-1733) - Fix RPM build issues on RHEL6/OL6 systems - [THRIFT-1728](https://issues.apache.org/jira/browse/THRIFT-1728) - Upgradation of httpcomponents - [THRIFT-1876](https://issues.apache.org/jira/browse/THRIFT-1876) - Use enum names instead of casted integers in assignments - [THRIFT-1874](https://issues.apache.org/jira/browse/THRIFT-1874) - timeout for the server-side end of a named pipe - [THRIFT-1897](https://issues.apache.org/jira/browse/THRIFT-1897) - Support validation of required fields - [THRIFT-1896](https://issues.apache.org/jira/browse/THRIFT-1896) - Add TBase protocol for Cocoa - [THRIFT-1880](https://issues.apache.org/jira/browse/THRIFT-1880) - Make named pipes server work asynchronously (overlapped) to allow for clean server stops - [THRIFT-1878](https://issues.apache.org/jira/browse/THRIFT-1878) - Add the possibility to send custom headers - [THRIFT-1882](https://issues.apache.org/jira/browse/THRIFT-1882) - Use single include - [THRIFT-1793](https://issues.apache.org/jira/browse/THRIFT-1793) - C#: Use static read instead of instance read - [THRIFT-1799](https://issues.apache.org/jira/browse/THRIFT-1799) - Option to generate HTML in "standalone mode" - [THRIFT-1815](https://issues.apache.org/jira/browse/THRIFT-1815) - Code generators line buffer output - [THRIFT-1890](https://issues.apache.org/jira/browse/THRIFT-1890) - C++: Make named pipes server work asynchronously - [THRIFT-474](https://issues.apache.org/jira/browse/THRIFT-474) - Generating Ruby on Rails friendly code ### New Feature - [THRIFT-801](https://issues.apache.org/jira/browse/THRIFT-801) - Provide an interactive shell (irb) when generating ruby bindings - [THRIFT-2292](https://issues.apache.org/jira/browse/THRIFT-2292) - Android Library Project - [THRIFT-2012](https://issues.apache.org/jira/browse/THRIFT-2012) - Modernizing Go - [THRIFT-1969](https://issues.apache.org/jira/browse/THRIFT-1969) - C#: Tests not properly linked from the solution - [THRIFT-1785](https://issues.apache.org/jira/browse/THRIFT-1785) - C#: Add TMemoryBuffer serializer/deserializer - [THRIFT-1780](https://issues.apache.org/jira/browse/THRIFT-1780) - Add option to generate nullable values - [THRIFT-1786](https://issues.apache.org/jira/browse/THRIFT-1786) - C# Union Typing - [THRIFT-591](https://issues.apache.org/jira/browse/THRIFT-591) - Make the C++ runtime library be compatible with Windows and Visual Studio - [THRIFT-514](https://issues.apache.org/jira/browse/THRIFT-514) - Add option to configure compiler output directory ### Question - [THRIFT-1764](https://issues.apache.org/jira/browse/THRIFT-1764) - how to get the context of client when on a rpc call in server side? - [THRIFT-1791](https://issues.apache.org/jira/browse/THRIFT-1791) - thrift's namespace directive when generating haskell code ### Sub-task - [THRIFT-1594](https://issues.apache.org/jira/browse/THRIFT-1594) - Java test clients should have a return codes that reflect whether it succeeds or not. - [THRIFT-1595](https://issues.apache.org/jira/browse/THRIFT-1595) - Java test server should follow the documented behavior as of THRIFT-1590 - [THRIFT-986](https://issues.apache.org/jira/browse/THRIFT-986) - st: add version Info to the library - [THRIFT-985](https://issues.apache.org/jira/browse/THRIFT-985) - php: add version Info to the library - [THRIFT-984](https://issues.apache.org/jira/browse/THRIFT-984) - ocaml: add version Info to the library - [THRIFT-1924](https://issues.apache.org/jira/browse/THRIFT-1924) - Delphi: Inconsistency in serialization of optional fields - [THRIFT-1922](https://issues.apache.org/jira/browse/THRIFT-1922) - C#: Inconsistency in serialization of optional fields - [THRIFT-1961](https://issues.apache.org/jira/browse/THRIFT-1961) - C# tests should be in lib/csharp/test/... - [THRIFT-1822](https://issues.apache.org/jira/browse/THRIFT-1822) - PHP unit test does not work - [THRIFT-1902](https://issues.apache.org/jira/browse/THRIFT-1902) - C++: Support for Multiplexing Services on any Transport, Protocol and Server - [THRIFT-1901](https://issues.apache.org/jira/browse/THRIFT-1901) - C#: Support for Multiplexing Services on any Transport, Protocol and Server - [THRIFT-1899](https://issues.apache.org/jira/browse/THRIFT-1899) - Delphi: Support for Multiplexing Services on any Transport, Protocol and Server - [THRIFT-563](https://issues.apache.org/jira/browse/THRIFT-563) - Support for Multiplexing Services on any Transport, Protocol and Server ## 0.9 ### Bug - [THRIFT-1438](https://issues.apache.org/jira/browse/THRIFT-1438) - lib/cpp/src/windows/config.h should read version from configure.ac rather than a #define - [THRIFT-1446](https://issues.apache.org/jira/browse/THRIFT-1446) - Compile error with Delphi 2009 in constant initializer - [THRIFT-1450](https://issues.apache.org/jira/browse/THRIFT-1450) - Problems building thrift 0.8.0 for Python and Ruby - [THRIFT-1449](https://issues.apache.org/jira/browse/THRIFT-1449) - Ruby client does not work on solaris (?) - [THRIFT-1447](https://issues.apache.org/jira/browse/THRIFT-1447) - NullpointerException in ProcessFunction.class :in "oneway" method - [THRIFT-1433](https://issues.apache.org/jira/browse/THRIFT-1433) - TServerSocket fix for MSVC - [THRIFT-1429](https://issues.apache.org/jira/browse/THRIFT-1429) - The nonblocking servers is supposed to use TransportFactory to read the data - [THRIFT-1427](https://issues.apache.org/jira/browse/THRIFT-1427) - PHP library uses non-multibyte safe functions with mbstring function overloading - [THRIFT-1421](https://issues.apache.org/jira/browse/THRIFT-1421) - Debian Packages can not be built - [THRIFT-1394](https://issues.apache.org/jira/browse/THRIFT-1394) - Treatment of optional fields is not consistent between C++ and Java - [THRIFT-1511](https://issues.apache.org/jira/browse/THRIFT-1511) - Server with oneway support ( JAVA ) - [THRIFT-1496](https://issues.apache.org/jira/browse/THRIFT-1496) - PHP compiler not namespacing enums - [THRIFT-1495](https://issues.apache.org/jira/browse/THRIFT-1495) - PHP TestClient fatals on missing class - [THRIFT-1508](https://issues.apache.org/jira/browse/THRIFT-1508) - TServerSocket does not allow for the user to specify the IP address to bind to - [THRIFT-1504](https://issues.apache.org/jira/browse/THRIFT-1504) - Cocoa Generator should use local file imports for base Thrift headers - [THRIFT-1512](https://issues.apache.org/jira/browse/THRIFT-1512) - Thrift socket support for Windows XP - [THRIFT-1502](https://issues.apache.org/jira/browse/THRIFT-1502) - TSimpleServer::serve(): Do not print out error message if server was stopped. - [THRIFT-1501](https://issues.apache.org/jira/browse/THRIFT-1501) - PHP old namespaces not generated for enums - [THRIFT-1483](https://issues.apache.org/jira/browse/THRIFT-1483) - java compiler does not generate type parameters for services in extended clauses - [THRIFT-1479](https://issues.apache.org/jira/browse/THRIFT-1479) - Compiled PHP process functions missing writeMessageEnd() - [THRIFT-1492](https://issues.apache.org/jira/browse/THRIFT-1492) - enabling c_glib render thrift unusable (even for C++ code) - [THRIFT-1491](https://issues.apache.org/jira/browse/THRIFT-1491) - Uninitialize processorFactory_ member in TServer.h - [THRIFT-1475](https://issues.apache.org/jira/browse/THRIFT-1475) - Incomplete records generation for Erlang - [THRIFT-1486](https://issues.apache.org/jira/browse/THRIFT-1486) - Javascript manual testserver not returning content types - [THRIFT-1488](https://issues.apache.org/jira/browse/THRIFT-1488) - src/concurrency/Thread.h:91:58: error: invalid conversion from 'pthread_t {aka _opaque_pthread_t*}' to 'apache::thrift::concurrency::Thread::id_t {aka long long unsigned int}' [-fpermissive] - [THRIFT-1490](https://issues.apache.org/jira/browse/THRIFT-1490) - Windows-specific header files) - fixes & tweaks - [THRIFT-1526](https://issues.apache.org/jira/browse/THRIFT-1526) - Union TupleSchemeFactory returns StandardSchemes - [THRIFT-1527](https://issues.apache.org/jira/browse/THRIFT-1527) - Generated implementation of tupleReadStruct in unions return null when the setfield is unrecognized - [THRIFT-1524](https://issues.apache.org/jira/browse/THRIFT-1524) - TNonBlockingServer does not compile in Visual Studio 2010 - [THRIFT-1529](https://issues.apache.org/jira/browse/THRIFT-1529) - TupleProtocol can unintentionally include an extra byte in bit vectors when number of optional fields is an integral of 8 - [THRIFT-1473](https://issues.apache.org/jira/browse/THRIFT-1473) - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations - [THRIFT-1456](https://issues.apache.org/jira/browse/THRIFT-1456) - System.Net.HttpWebRequest' does not contain a definition for 'Proxy' - [THRIFT-1468](https://issues.apache.org/jira/browse/THRIFT-1468) - Memory leak in TSaslServerTransport - [THRIFT-1461](https://issues.apache.org/jira/browse/THRIFT-1461) - Recent TNonblockingServer changes broke --enable-boostthreads=yes, Windows - [THRIFT-1460](https://issues.apache.org/jira/browse/THRIFT-1460) - why not add unicode strings support to python directly? - [THRIFT-1464](https://issues.apache.org/jira/browse/THRIFT-1464) - AbstractNonblockingServer.FrameBuffer TNonblockingTransport accessor changed from public to private - [THRIFT-1467](https://issues.apache.org/jira/browse/THRIFT-1467) - Possible AV with empty strings when using JSON protocol - [THRIFT-1523](https://issues.apache.org/jira/browse/THRIFT-1523) - clientTimeout not worked as expected in TServerSocket created by TSSLTransportFactory - [THRIFT-1537](https://issues.apache.org/jira/browse/THRIFT-1537) - TFramedTransport issues - [THRIFT-1519](https://issues.apache.org/jira/browse/THRIFT-1519) - Thirft Build Failure referencing rb_intern2 symbol - [THRIFT-1518](https://issues.apache.org/jira/browse/THRIFT-1518) - Generated C++ code only sends the first optional field in the write() function for a struct. - [THRIFT-1515](https://issues.apache.org/jira/browse/THRIFT-1515) - NameError: global name 'TApplicationException' is not defined - [THRIFT-1554](https://issues.apache.org/jira/browse/THRIFT-1554) - Inherited service methods are not resolved in derived service implementations - [THRIFT-1553](https://issues.apache.org/jira/browse/THRIFT-1553) - thrift nodejs service side can't read map structure, key as enum, value as Object - [THRIFT-1575](https://issues.apache.org/jira/browse/THRIFT-1575) - Typo in server/TThreadPoolServer.h - [THRIFT-1327](https://issues.apache.org/jira/browse/THRIFT-1327) - Fix Spec Suite under Ruby-1.8.7 (works for MRI Ruby-1.9.2) - [THRIFT-1326](https://issues.apache.org/jira/browse/THRIFT-1326) - on some platforms, #include is necessary to be included in Thrift.h - [THRIFT-1159](https://issues.apache.org/jira/browse/THRIFT-1159) - THttpClient->Flush() issue (connection thru proxy) - [THRIFT-1277](https://issues.apache.org/jira/browse/THRIFT-1277) - Node.js serializes false booleans as null - [THRIFT-1224](https://issues.apache.org/jira/browse/THRIFT-1224) - Cannot insert UTF-8 text - [THRIFT-1267](https://issues.apache.org/jira/browse/THRIFT-1267) - Node.js can't throw exceptions. - [THRIFT-1338](https://issues.apache.org/jira/browse/THRIFT-1338) - Do not use an unpatched autoconf 2.65 to generate release tarball - [THRIFT-1128](https://issues.apache.org/jira/browse/THRIFT-1128) - MAC OS X: thrift.h incompatibility with Thrift.h - [THRIFT-1631](https://issues.apache.org/jira/browse/THRIFT-1631) - Fix C++ server constructor typos - [THRIFT-1602](https://issues.apache.org/jira/browse/THRIFT-1602) - PHP C Extension is not Compatible with PHP 5.4 - [THRIFT-1610](https://issues.apache.org/jira/browse/THRIFT-1610) - IWebProxy not available on WP7 platform - [THRIFT-1606](https://issues.apache.org/jira/browse/THRIFT-1606) - Race condition in BoostThreadFactory.cpp - [THRIFT-1604](https://issues.apache.org/jira/browse/THRIFT-1604) - Python exception handeling for changes from PEP 3110 - [THRIFT-1607](https://issues.apache.org/jira/browse/THRIFT-1607) - Incorrect file modes for several source files - [THRIFT-1583](https://issues.apache.org/jira/browse/THRIFT-1583) - c_glib leaks memory - [THRIFT-1582](https://issues.apache.org/jira/browse/THRIFT-1582) - Bad includes of nested thrift files in c_glib - [THRIFT-1578](https://issues.apache.org/jira/browse/THRIFT-1578) - C_GLib generated code does not compile - [THRIFT-1597](https://issues.apache.org/jira/browse/THRIFT-1597) - TJSONProtocol.php is missing from Makefile.am - [THRIFT-1591](https://issues.apache.org/jira/browse/THRIFT-1591) - Enable TCP_NODELAY for ruby gem - [THRIFT-1624](https://issues.apache.org/jira/browse/THRIFT-1624) - Isset Generated differently on different platforms - [THRIFT-1622](https://issues.apache.org/jira/browse/THRIFT-1622) - Incorrect size returned on read - [THRIFT-1621](https://issues.apache.org/jira/browse/THRIFT-1621) - Memory leaks - [THRIFT-1612](https://issues.apache.org/jira/browse/THRIFT-1612) - Base64 encoding is broken - [THRIFT-1627](https://issues.apache.org/jira/browse/THRIFT-1627) - compiler built using compilers.vcxproj cannot be used to build some test .thrift files - [THRIFT-1571](https://issues.apache.org/jira/browse/THRIFT-1571) - Update Ruby HTTP transport for recent Ruby versions - [THRIFT-1023](https://issues.apache.org/jira/browse/THRIFT-1023) - Thrift encoding (UTF-8) issue with Ruby 1.9.2 - [THRIFT-1090](https://issues.apache.org/jira/browse/THRIFT-1090) - Document the generation of a file called "Constants.java" - [THRIFT-1082](https://issues.apache.org/jira/browse/THRIFT-1082) - Thrift::FramedTransport sometimes calls close() on an undefined value - [THRIFT-956](https://issues.apache.org/jira/browse/THRIFT-956) - Python module's version meta-data should be updated - [THRIFT-973](https://issues.apache.org/jira/browse/THRIFT-973) - Cocoa library won't compile using clang - [THRIFT-1632](https://issues.apache.org/jira/browse/THRIFT-1632) - ruby: data corruption in thrift_native implementation of MemoryBufferTransport - [THRIFT-1665](https://issues.apache.org/jira/browse/THRIFT-1665) - TBinaryProtocol: exceeded message length raises generic TException - [THRIFT-1664](https://issues.apache.org/jira/browse/THRIFT-1664) - Reference to non-existing variable in build script - [THRIFT-1663](https://issues.apache.org/jira/browse/THRIFT-1663) - Java Thrift server is not throwing exceptions - [THRIFT-1662](https://issues.apache.org/jira/browse/THRIFT-1662) - "removeObject:" should be "removeObserver:" in [-TSocketServer dealloc]? - [THRIFT-1643](https://issues.apache.org/jira/browse/THRIFT-1643) - Denial of Service attack in TBinaryProtocol.readString - [THRIFT-1674](https://issues.apache.org/jira/browse/THRIFT-1674) - Update Thrift D library to be compatible with 2.060 - [THRIFT-1673](https://issues.apache.org/jira/browse/THRIFT-1673) - Ruby compile flags for extension for multi arch builds (os x) - [THRIFT-1655](https://issues.apache.org/jira/browse/THRIFT-1655) - Configure still trying to use thrift_generators in output - [THRIFT-1654](https://issues.apache.org/jira/browse/THRIFT-1654) - c_glib thrift_socket_read() returns corrupted data - [THRIFT-1653](https://issues.apache.org/jira/browse/THRIFT-1653) - TThreadedSelectorServer leaks CLOSE_WAIT sockets - [THRIFT-1658](https://issues.apache.org/jira/browse/THRIFT-1658) - Java thrift server is not throwing TApplicationException - [THRIFT-1656](https://issues.apache.org/jira/browse/THRIFT-1656) - Setting proper headers in THttpServer.cpp so that "Cross-Origin Resource Sharing" on js client can work. - [THRIFT-1652](https://issues.apache.org/jira/browse/THRIFT-1652) - TSaslTransport does not log the error when kerberos auth fails - [THRIFT-2272](https://issues.apache.org/jira/browse/THRIFT-2272) - CLONE) - Denial of Service attack in TBinaryProtocol.readString - [THRIFT-2086](https://issues.apache.org/jira/browse/THRIFT-2086) - Invalid generated code for Node.JS when using namespaces - [THRIFT-1686](https://issues.apache.org/jira/browse/THRIFT-1686) - t_php_generator.cc uses "and" instead of "&&", and causes compiler errors with Visual Studio - [THRIFT-1693](https://issues.apache.org/jira/browse/THRIFT-1693) - libthrift has dependency on two different versions of httpcore - [THRIFT-1689](https://issues.apache.org/jira/browse/THRIFT-1689) - don't exit(-1) in TNonblockingServer - [THRIFT-1679](https://issues.apache.org/jira/browse/THRIFT-1679) - NodeJS: protocol readString() should treat string as utf8, not binary - [THRIFT-1721](https://issues.apache.org/jira/browse/THRIFT-1721) - Dist broken due to 0.8.0 to 0.9.0 changes - [THRIFT-1710](https://issues.apache.org/jira/browse/THRIFT-1710) - Minor issues in test case code - [THRIFT-1709](https://issues.apache.org/jira/browse/THRIFT-1709) - Warning "Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first" in TBinaryProtocol.cs at ReadInt64() - [THRIFT-1707](https://issues.apache.org/jira/browse/THRIFT-1707) - [ruby] Adjust server_spec.rb for RSpec 2.11.x and Ruby 1.9.3 - [THRIFT-1671](https://issues.apache.org/jira/browse/THRIFT-1671) - Cocoa code generator does not put keywords into generated method calls - [THRIFT-1670](https://issues.apache.org/jira/browse/THRIFT-1670) - Incompatibilities between different versions of a Thrift interface - [THRIFT-1669](https://issues.apache.org/jira/browse/THRIFT-1669) - NameError: global name 'TApplicationException' is not defined - [THRIFT-1668](https://issues.apache.org/jira/browse/THRIFT-1668) - Compile error in contrib/fb303, thrift/TDispatchProcessor.h: No such file or directory - [THRIFT-1845](https://issues.apache.org/jira/browse/THRIFT-1845) - Fix compiler warning caused by implicit string conversion with Xcode 4.6 - [THRIFT-304](https://issues.apache.org/jira/browse/THRIFT-304) - Building the Python library requires development headers - [THRIFT-369](https://issues.apache.org/jira/browse/THRIFT-369) - sets and maps break equality - [THRIFT-556](https://issues.apache.org/jira/browse/THRIFT-556) - Ruby compiler does not correctly referred to top-level modules when a submodule masks the top-level name - [THRIFT-481](https://issues.apache.org/jira/browse/THRIFT-481) - indentation of ruby classes is off by a few ### Improvement - [THRIFT-1498](https://issues.apache.org/jira/browse/THRIFT-1498) - Allow TThreadedPoolServer.Args to pass a ExecutorService - [THRIFT-1444](https://issues.apache.org/jira/browse/THRIFT-1444) - FunctionRunner) - add syntactic sugar to create shared_ptrs - [THRIFT-1443](https://issues.apache.org/jira/browse/THRIFT-1443) - define a TProcessor helper class to implement process() - [THRIFT-1441](https://issues.apache.org/jira/browse/THRIFT-1441) - Generate constructor with parameters for exception class to let it update message property automatically. - [THRIFT-1520](https://issues.apache.org/jira/browse/THRIFT-1520) - Embed version number in erlang .app file - [THRIFT-1480](https://issues.apache.org/jira/browse/THRIFT-1480) - python: remove tabs, adjust whitespace and address PEP8 warnings - [THRIFT-1485](https://issues.apache.org/jira/browse/THRIFT-1485) - Performance: pass large and/or refcounted arguments as "const" - [THRIFT-1484](https://issues.apache.org/jira/browse/THRIFT-1484) - Introduce phpunit test suite - [THRIFT-1532](https://issues.apache.org/jira/browse/THRIFT-1532) - The type specifications in the generated Erlang code should include "undefined" where it's used as a default value - [THRIFT-1534](https://issues.apache.org/jira/browse/THRIFT-1534) - Required fields in the Delphi code generator. - [THRIFT-1469](https://issues.apache.org/jira/browse/THRIFT-1469) - Java isset space optimization - [THRIFT-1465](https://issues.apache.org/jira/browse/THRIFT-1465) - Visibility of methods in generated java code - [THRIFT-1453](https://issues.apache.org/jira/browse/THRIFT-1453) - Don't change types of arguments when serializing with thrift php extension - [THRIFT-1452](https://issues.apache.org/jira/browse/THRIFT-1452) - generate a swap() method for all generated structs - [THRIFT-1451](https://issues.apache.org/jira/browse/THRIFT-1451) - FramedTransport: Prevent infinite loop when writing - [THRIFT-1521](https://issues.apache.org/jira/browse/THRIFT-1521) - Two patches for more Performance - [THRIFT-1555](https://issues.apache.org/jira/browse/THRIFT-1555) - Delphi version of the tutorial code - [THRIFT-1535](https://issues.apache.org/jira/browse/THRIFT-1535) - Why thrift don't use wrapped class for optional fields ? - [THRIFT-1204](https://issues.apache.org/jira/browse/THRIFT-1204) - Ruby autogenerated files should require 'thrift' gem - [THRIFT-1344](https://issues.apache.org/jira/browse/THRIFT-1344) - Using the httpc module directly rather than the deprecated http layer - [THRIFT-1343](https://issues.apache.org/jira/browse/THRIFT-1343) - no_auto_import min/2 to avoid compile warning - [THRIFT-1340](https://issues.apache.org/jira/browse/THRIFT-1340) - Add support of ARC to Objective-C - [THRIFT-1611](https://issues.apache.org/jira/browse/THRIFT-1611) - Improved code generation for typedefs - [THRIFT-1593](https://issues.apache.org/jira/browse/THRIFT-1593) - Pass on errors like "connection closed" to the handler module - [THRIFT-1615](https://issues.apache.org/jira/browse/THRIFT-1615) - PHP Namespace - [THRIFT-1567](https://issues.apache.org/jira/browse/THRIFT-1567) - Thrift/cpp: Allow alternate classes to be used for - [THRIFT-1072](https://issues.apache.org/jira/browse/THRIFT-1072) - Missing) - (id) initWithSharedProcessor in TSharedProcessorFactory.h - [THRIFT-1650](https://issues.apache.org/jira/browse/THRIFT-1650) - [ruby] Update clean items and svn:ignore entries for OS X artifacts - [THRIFT-1661](https://issues.apache.org/jira/browse/THRIFT-1661) - [PATCH] Add --with-qt4 configure option - [THRIFT-1675](https://issues.apache.org/jira/browse/THRIFT-1675) - Do we have any plan to support scala? - [THRIFT-1645](https://issues.apache.org/jira/browse/THRIFT-1645) - Replace Object#tee with more conventional Object#tap in specs - [THRIFT-1644](https://issues.apache.org/jira/browse/THRIFT-1644) - Upgrade RSpec to 2.10.x and refactor specs as needed - [THRIFT-1672](https://issues.apache.org/jira/browse/THRIFT-1672) - MonoTouch (and Mono for Android) compatibility - [THRIFT-1702](https://issues.apache.org/jira/browse/THRIFT-1702) - a thrift manual - [THRIFT-1694](https://issues.apache.org/jira/browse/THRIFT-1694) - Re-Enable serialization for WP7 Silverlight - [THRIFT-1691](https://issues.apache.org/jira/browse/THRIFT-1691) - Serializer/deserializer support for Delphi - [THRIFT-1688](https://issues.apache.org/jira/browse/THRIFT-1688) - Update IDL page markup - [THRIFT-1725](https://issues.apache.org/jira/browse/THRIFT-1725) - Tutorial web pages for Delphi and C# - [THRIFT-1714](https://issues.apache.org/jira/browse/THRIFT-1714) - [ruby] Explicitly add CWD to Ruby test_suites.rb - [THRIFT-317](https://issues.apache.org/jira/browse/THRIFT-317) - Issues with Java struct validation - [THRIFT-164](https://issues.apache.org/jira/browse/THRIFT-164) - Build web tutorial on Incubator web site - [THRIFT-541](https://issues.apache.org/jira/browse/THRIFT-541) - Cocoa code generator doesn't put keywords before all arguments. - [THRIFT-681](https://issues.apache.org/jira/browse/THRIFT-681) - The HTML generator does not handle JavaDoc style comments very well ### New Feature - [THRIFT-1500](https://issues.apache.org/jira/browse/THRIFT-1500) - D programming language support - [THRIFT-1510](https://issues.apache.org/jira/browse/THRIFT-1510) - There should be an implementation of the JsonProtocol for ruby - [THRIFT-1115](https://issues.apache.org/jira/browse/THRIFT-1115) - python TBase class for dynamic (de)serialization, and __slots__ option for memory savings - [THRIFT-1953](https://issues.apache.org/jira/browse/THRIFT-1953) - support for asp.net mvc 3 ### Question - [THRIFT-1235](https://issues.apache.org/jira/browse/THRIFT-1235) - How could I use THttpServerTransportFactory withTNonBlockingServer - [THRIFT-1368](https://issues.apache.org/jira/browse/THRIFT-1368) - TNonblockingServer usage - [THRIFT-1061](https://issues.apache.org/jira/browse/THRIFT-1061) - Read an invalid frame size of 0. Are you using TFramedTransport on the client side? - [THRIFT-491](https://issues.apache.org/jira/browse/THRIFT-491) - Ripping raw pthreads out of TFileTransport and associated test issues ### Sub-task - [THRIFT-1596](https://issues.apache.org/jira/browse/THRIFT-1596) - Delphi: Test clients should have a return codes that reflect whether they succeeded or not - [THRIFT-982](https://issues.apache.org/jira/browse/THRIFT-982) - javame: add version Info to the library - [THRIFT-1722](https://issues.apache.org/jira/browse/THRIFT-1722) - C# WP7 Assembly addition beaks mono build - [THRIFT-336](https://issues.apache.org/jira/browse/THRIFT-336) - Compact Protocol in C# ### Test - [THRIFT-1613](https://issues.apache.org/jira/browse/THRIFT-1613) - Add code back into empty source file ToStringTest.java - [THRIFT-1718](https://issues.apache.org/jira/browse/THRIFT-1718) - Incorrect check in TFileTransportTest ### Wish - [THRIFT-1463](https://issues.apache.org/jira/browse/THRIFT-1463) - Decouple Thrift IDL from generators - [THRIFT-1466](https://issues.apache.org/jira/browse/THRIFT-1466) - Proper Documentation for Thrift C Glib - [THRIFT-1539](https://issues.apache.org/jira/browse/THRIFT-1539) - Build and distribute the fb303 python libraries along with thrift - [THRIFT-1685](https://issues.apache.org/jira/browse/THRIFT-1685) - Please add "aereo.com" to "Powered by Apache Thrift" list in about page - [THRIFT-330](https://issues.apache.org/jira/browse/THRIFT-330) - TProcessor) - additional method to called when connection is broken ## 0.8 ### Bug - [THRIFT-1436](https://issues.apache.org/jira/browse/THRIFT-1436) - pip install thrift fails on Windows with "Unable to find vcvarsall.bat" - [THRIFT-1432](https://issues.apache.org/jira/browse/THRIFT-1432) - Javascript struct constants declared in the same file as their struct definition will cause an error - [THRIFT-1428](https://issues.apache.org/jira/browse/THRIFT-1428) - shared.thrft does not include namespace for php, so thrift compiler generate incorrect name - [THRIFT-1426](https://issues.apache.org/jira/browse/THRIFT-1426) - Dist package missing files for release 0.8 - [THRIFT-1425](https://issues.apache.org/jira/browse/THRIFT-1425) - The Node package is incompatible with latest node (0.6) & npm (1.0.27) - [THRIFT-1416](https://issues.apache.org/jira/browse/THRIFT-1416) - Python Unit test is broken on ci - [THRIFT-1419](https://issues.apache.org/jira/browse/THRIFT-1419) - AbstractNonBlockingServer does not catch errors when invoking the processor - [THRIFT-1424](https://issues.apache.org/jira/browse/THRIFT-1424) - Ruby specs fail when run with rake - [THRIFT-1420](https://issues.apache.org/jira/browse/THRIFT-1420) - Nonblocking and HsHa server should make sure to close all their socket connections when the selector exits - [THRIFT-1413](https://issues.apache.org/jira/browse/THRIFT-1413) - Generated code does not read MapEnd / ListEnd / SetEnd - [THRIFT-1409](https://issues.apache.org/jira/browse/THRIFT-1409) - Name conflict check does not work properly for exception object(Delphi). - [THRIFT-1408](https://issues.apache.org/jira/browse/THRIFT-1408) - Delphi Test Server: Exception test case fails due to naming conflict with e.message - [THRIFT-1407](https://issues.apache.org/jira/browse/THRIFT-1407) - Typo in Python socket server causes Thrift to fail when we enable a global socket timout - [THRIFT-1397](https://issues.apache.org/jira/browse/THRIFT-1397) - CI server fails during build due to unused parameters in delphi generator - [THRIFT-1404](https://issues.apache.org/jira/browse/THRIFT-1404) - Delphi compiler generates struct reader code with problem. - [THRIFT-1400](https://issues.apache.org/jira/browse/THRIFT-1400) - Ruby native extension aborts with __stack_chk_fail in OSX - [THRIFT-1399](https://issues.apache.org/jira/browse/THRIFT-1399) - One of the TServerImpl.Create CTORs lacks implementation - [THRIFT-1390](https://issues.apache.org/jira/browse/THRIFT-1390) - Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) - [THRIFT-1393](https://issues.apache.org/jira/browse/THRIFT-1393) - TTransportException's thrown from THttpClient contain superfluous slashes in the Exception message - [THRIFT-1392](https://issues.apache.org/jira/browse/THRIFT-1392) - Enabling both namespaces and autoloading in generated PHP code won't work. - [THRIFT-1406](https://issues.apache.org/jira/browse/THRIFT-1406) - Build error after applying THRIFT-1395 - [THRIFT-1405](https://issues.apache.org/jira/browse/THRIFT-1405) - Delphi compiler does not generates container serializer properly. - [THRIFT-1411](https://issues.apache.org/jira/browse/THRIFT-1411) - java generator does not provide type parameter for TBaseProcessor - [THRIFT-1473](https://issues.apache.org/jira/browse/THRIFT-1473) - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations - [THRIFT-1331](https://issues.apache.org/jira/browse/THRIFT-1331) - Ruby library deserializes an empty map to nil - [THRIFT-1330](https://issues.apache.org/jira/browse/THRIFT-1330) - PHP Namespaces no longer generated - [THRIFT-1328](https://issues.apache.org/jira/browse/THRIFT-1328) - TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range - [THRIFT-1322](https://issues.apache.org/jira/browse/THRIFT-1322) - OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch - [THRIFT-1143](https://issues.apache.org/jira/browse/THRIFT-1143) - Build doesn't detect correct architecture type on 64bit osx - [THRIFT-1205](https://issues.apache.org/jira/browse/THRIFT-1205) - port server unduly fragile with arbitrary input - [THRIFT-1279](https://issues.apache.org/jira/browse/THRIFT-1279) - type set is handled incorrectly when writing object - [THRIFT-1298](https://issues.apache.org/jira/browse/THRIFT-1298) - Standard scheme doesn't read or write metadata along with field values - [THRIFT-1265](https://issues.apache.org/jira/browse/THRIFT-1265) - C++ container deserialize - [THRIFT-1263](https://issues.apache.org/jira/browse/THRIFT-1263) - publish ruby client to rubygems - [THRIFT-1384](https://issues.apache.org/jira/browse/THRIFT-1384) - Java help menu missing newline near javame flag - [THRIFT-1382](https://issues.apache.org/jira/browse/THRIFT-1382) - Bundle install doesnot work because thrift crashes - [THRIFT-1381](https://issues.apache.org/jira/browse/THRIFT-1381) - Thrift C++ libs have incorrectly versioned names - [THRIFT-1350](https://issues.apache.org/jira/browse/THRIFT-1350) - Go library code does not build as of r60 (most recent release) - [THRIFT-1365](https://issues.apache.org/jira/browse/THRIFT-1365) - TupleProtocol#writeBitSet unintentionally writes a variable length byte array - [THRIFT-1359](https://issues.apache.org/jira/browse/THRIFT-1359) - --gen-cob cpp:cob_style does not compile anymore - [THRIFT-1319](https://issues.apache.org/jira/browse/THRIFT-1319) - Mismatch between how a union reads and writes a container - [THRIFT-1309](https://issues.apache.org/jira/browse/THRIFT-1309) - libfb303-0.7.0.jar missing in maven repository - [THRIFT-1238](https://issues.apache.org/jira/browse/THRIFT-1238) - Thrift JS client cannot read map of structures - [THRIFT-1254](https://issues.apache.org/jira/browse/THRIFT-1254) - Code can't be compiled against a regular JRE: Object.clone() override has a different return type - [THRIFT-1367](https://issues.apache.org/jira/browse/THRIFT-1367) - Mac OSX build fails with "no such file to load -- spec/rake/spectask" - [THRIFT-1355](https://issues.apache.org/jira/browse/THRIFT-1355) - Running make in lib/rb doesn't build the native extensions - [THRIFT-1370](https://issues.apache.org/jira/browse/THRIFT-1370) - Debian packaging should Build-Depend on libglib2.0-dev - [THRIFT-1342](https://issues.apache.org/jira/browse/THRIFT-1342) - Compilation problem on Windows of fastbinary.c - [THRIFT-1341](https://issues.apache.org/jira/browse/THRIFT-1341) - TProtocol.h endian detection wrong with boost - [THRIFT-1583](https://issues.apache.org/jira/browse/THRIFT-1583) - c_glib leaks memory - [THRIFT-1582](https://issues.apache.org/jira/browse/THRIFT-1582) - Bad includes of nested thrift files in c_glib - [THRIFT-1578](https://issues.apache.org/jira/browse/THRIFT-1578) - C_GLib generated code does not compile - [THRIFT-1027](https://issues.apache.org/jira/browse/THRIFT-1027) - 'make -j 16' fails with "unterminated #ifdef" error - [THRIFT-1121](https://issues.apache.org/jira/browse/THRIFT-1121) - Java server performance regression in 0.6 - [THRIFT-857](https://issues.apache.org/jira/browse/THRIFT-857) - tests run by "make install" fail if generators are disabled - [THRIFT-380](https://issues.apache.org/jira/browse/THRIFT-380) - Use setuptools for python build ### Dependency upgrade - [THRIFT-1257](https://issues.apache.org/jira/browse/THRIFT-1257) - thrift's dependency scope on javax.servlet:servlet-api should be 'provided' ### Improvement - [THRIFT-1445](https://issues.apache.org/jira/browse/THRIFT-1445) - minor C++ generator variable cleanup - [THRIFT-1435](https://issues.apache.org/jira/browse/THRIFT-1435) - make TException.Message property conformant to the usual expectations - [THRIFT-1431](https://issues.apache.org/jira/browse/THRIFT-1431) - Rename 'sys' module to 'util' - [THRIFT-1396](https://issues.apache.org/jira/browse/THRIFT-1396) - Dephi generator has dependacy on boost 1.42 later. - [THRIFT-1395](https://issues.apache.org/jira/browse/THRIFT-1395) - Patch to prevent warnings for integer types in some cases - [THRIFT-1275](https://issues.apache.org/jira/browse/THRIFT-1275) - thrift: always prefix namespaces with " ::" - [THRIFT-1274](https://issues.apache.org/jira/browse/THRIFT-1274) - thrift: fail compilation if an unexpected token is - [THRIFT-1271](https://issues.apache.org/jira/browse/THRIFT-1271) - thrift: fix missing namespace in generated local - [THRIFT-1270](https://issues.apache.org/jira/browse/THRIFT-1270) - thrift: add --allow-neg-keys argument to allow - [THRIFT-1345](https://issues.apache.org/jira/browse/THRIFT-1345) - Allow building without tests - [THRIFT-1286](https://issues.apache.org/jira/browse/THRIFT-1286) - Modernize the Thrift Ruby Library Dev Environment - [THRIFT-1284](https://issues.apache.org/jira/browse/THRIFT-1284) - thrift: fix processor inheritance - [THRIFT-1283](https://issues.apache.org/jira/browse/THRIFT-1283) - thrift: wrap t_cpp_generator::generate_process_function() to 80 - [THRIFT-1282](https://issues.apache.org/jira/browse/THRIFT-1282) - Upgrade httpclient to 4.1.2 (from 4.0.1) - [THRIFT-1281](https://issues.apache.org/jira/browse/THRIFT-1281) - add @generated to the docblock - [THRIFT-1280](https://issues.apache.org/jira/browse/THRIFT-1280) - Thrift: Improve Monitor exception-free interfaces - [THRIFT-1278](https://issues.apache.org/jira/browse/THRIFT-1278) - javadoc warnings) - compilation - [THRIFT-1227](https://issues.apache.org/jira/browse/THRIFT-1227) - Erlang implementation of thrift JSON protocol - [THRIFT-1295](https://issues.apache.org/jira/browse/THRIFT-1295) - Duplicate include in TSocket.cpp - [THRIFT-1294](https://issues.apache.org/jira/browse/THRIFT-1294) - thrift: fix log message typos in TSimpleServer - [THRIFT-1293](https://issues.apache.org/jira/browse/THRIFT-1293) - thrift: improve handling of exceptions thrown by - [THRIFT-1292](https://issues.apache.org/jira/browse/THRIFT-1292) - thrift: silence log spew from TThreadedServer - [THRIFT-1288](https://issues.apache.org/jira/browse/THRIFT-1288) - Allow typedefed exceptions in throws clauses - [THRIFT-1290](https://issues.apache.org/jira/browse/THRIFT-1290) - thrift: TNonblockingServer: clean up state in the - [THRIFT-1287](https://issues.apache.org/jira/browse/THRIFT-1287) - thrift: start refactoring some of the C++ processor - [THRIFT-1289](https://issues.apache.org/jira/browse/THRIFT-1289) - thrift: implement TNonblockingServer::stop() - [THRIFT-1305](https://issues.apache.org/jira/browse/THRIFT-1305) - thrift: make TConnection a private inner class of - [THRIFT-1304](https://issues.apache.org/jira/browse/THRIFT-1304) - TNonblockingServer: pass in the connection context to - [THRIFT-1302](https://issues.apache.org/jira/browse/THRIFT-1302) - thrift: raise an exception if send() times out in - [THRIFT-1301](https://issues.apache.org/jira/browse/THRIFT-1301) - thrift: consolidate common code in TNonblockingServer - [THRIFT-1377](https://issues.apache.org/jira/browse/THRIFT-1377) - abort PHP deserialization on unknown field type - [THRIFT-1379](https://issues.apache.org/jira/browse/THRIFT-1379) - fix uninitialized enum values in thrift C++ objects - [THRIFT-1376](https://issues.apache.org/jira/browse/THRIFT-1376) - Make port specification option in thrift remote - [THRIFT-1375](https://issues.apache.org/jira/browse/THRIFT-1375) - fixed a hex char conversion bug in TJSONProtocol - [THRIFT-1373](https://issues.apache.org/jira/browse/THRIFT-1373) - Fix user-defined exception generation in thrift (python) - [THRIFT-1361](https://issues.apache.org/jira/browse/THRIFT-1361) - Optional replacement of pthread by boost::thread - [THRIFT-1320](https://issues.apache.org/jira/browse/THRIFT-1320) - Consistency of configure generated config.h - [THRIFT-1317](https://issues.apache.org/jira/browse/THRIFT-1317) - Remove copy constructibility from - [THRIFT-1316](https://issues.apache.org/jira/browse/THRIFT-1316) - thrift: update server classes to accept - [THRIFT-1315](https://issues.apache.org/jira/browse/THRIFT-1315) - thrift: generate server interface factory classes - [THRIFT-1314](https://issues.apache.org/jira/browse/THRIFT-1314) - thrift: add TProcessorFactory - [THRIFT-1335](https://issues.apache.org/jira/browse/THRIFT-1335) - Add accept timeout to TServerSocket - [THRIFT-1334](https://issues.apache.org/jira/browse/THRIFT-1334) - Add more info to IllegalStateException - [THRIFT-1333](https://issues.apache.org/jira/browse/THRIFT-1333) - Make RWGuard not copyable - [THRIFT-1332](https://issues.apache.org/jira/browse/THRIFT-1332) - TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 - [THRIFT-1251](https://issues.apache.org/jira/browse/THRIFT-1251) - Generated java code should indicate which fields are required and which are optional - [THRIFT-1387](https://issues.apache.org/jira/browse/THRIFT-1387) - Build MSVC libraries with Boost Threads instead of Pthreads - [THRIFT-1339](https://issues.apache.org/jira/browse/THRIFT-1339) - Extend Tuple Protocol to TUnions - [THRIFT-1031](https://issues.apache.org/jira/browse/THRIFT-1031) - Patch to compile Thrift for vc++ 9.0 and 10.0 - [THRIFT-1130](https://issues.apache.org/jira/browse/THRIFT-1130) - Add the ability to specify symbolic default value for optional boolean - [THRIFT-1123](https://issues.apache.org/jira/browse/THRIFT-1123) - Patch to compile Thrift server and client for vc++ 9.0 and 10.0 - [THRIFT-386](https://issues.apache.org/jira/browse/THRIFT-386) - Make it possible to build the Python library without the extension ### New Feature - [THRIFT-1401](https://issues.apache.org/jira/browse/THRIFT-1401) - JSON-protocol for Delphi XE Libraries - [THRIFT-1167](https://issues.apache.org/jira/browse/THRIFT-1167) - Java nonblocking server with more than one thread for select and handling IO - [THRIFT-1366](https://issues.apache.org/jira/browse/THRIFT-1366) - Delphi generator, lirbrary and unit test. - [THRIFT-1354](https://issues.apache.org/jira/browse/THRIFT-1354) - Add rake task to build just the gem file - [THRIFT-769](https://issues.apache.org/jira/browse/THRIFT-769) - Pluggable Serializers ### Sub-task - [THRIFT-1415](https://issues.apache.org/jira/browse/THRIFT-1415) - delphi: add version Info to the library - [THRIFT-1391](https://issues.apache.org/jira/browse/THRIFT-1391) - Improved Delphi XE test cases ## 0.7 ### Bug - [THRIFT-1140](https://issues.apache.org/jira/browse/THRIFT-1140) - Framed Transport Client using C (Glib) Library hangs when connecting to Ruby Server - [THRIFT-1154](https://issues.apache.org/jira/browse/THRIFT-1154) - HttpClient does not specify the connection close parameter - [THRIFT-1153](https://issues.apache.org/jira/browse/THRIFT-1153) - HttpClient does not specify the connection close parameter - [THRIFT-1149](https://issues.apache.org/jira/browse/THRIFT-1149) - Nonblocking server fails when client connection is reset - [THRIFT-1146](https://issues.apache.org/jira/browse/THRIFT-1146) - Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable parameter in constructor - [THRIFT-1133](https://issues.apache.org/jira/browse/THRIFT-1133) - Java and JavaScript tutorial is broken since we have Java maven deployment - [THRIFT-1132](https://issues.apache.org/jira/browse/THRIFT-1132) - Deserialization error in TApplicationException C# - [THRIFT-1131](https://issues.apache.org/jira/browse/THRIFT-1131) - C# JSON Protocol is unable to decode escaped characters in string - [THRIFT-1208](https://issues.apache.org/jira/browse/THRIFT-1208) - python TCompactProtocol.py writeBool and readBool not follow the compact-proto-spec-2.txt spec for CONTAINER_WRITE, CONTAINER_READ - [THRIFT-1200](https://issues.apache.org/jira/browse/THRIFT-1200) - JS compiler generates code that clobbers existing namespaces - [THRIFT-1183](https://issues.apache.org/jira/browse/THRIFT-1183) - Pure-ruby CompactProtocol raises ArgumentError when deserializing under Ruby 1.9 - [THRIFT-1182](https://issues.apache.org/jira/browse/THRIFT-1182) - Native deserializer segfaults on incorrect list element type - [THRIFT-1181](https://issues.apache.org/jira/browse/THRIFT-1181) - AS3 compiler generates incorrect code for setting default values in constructor - [THRIFT-1234](https://issues.apache.org/jira/browse/THRIFT-1234) - thrift --help is missing doc on py:utf8strings - [THRIFT-1180](https://issues.apache.org/jira/browse/THRIFT-1180) - AS3 compiler generates uncompilable code for binary types. - [THRIFT-1194](https://issues.apache.org/jira/browse/THRIFT-1194) - Java lib does not install artifacts to local dir correctly - [THRIFT-1193](https://issues.apache.org/jira/browse/THRIFT-1193) - Potential infinite loop in nonblocking_server - [THRIFT-1192](https://issues.apache.org/jira/browse/THRIFT-1192) - Typo: TProtocol.h tests for HAVE_SYS_PARAM_H_ - [THRIFT-1190](https://issues.apache.org/jira/browse/THRIFT-1190) - readBufferBytesAllocated in TNonblockingServer.java should be AtomicLong to fix FD leakage and general server malfunction - [THRIFT-1187](https://issues.apache.org/jira/browse/THRIFT-1187) - nonblocking_server shutdown race under Ruby 1.9 - [THRIFT-1178](https://issues.apache.org/jira/browse/THRIFT-1178) - Java: TBase signature should be T extends TBase - [THRIFT-1164](https://issues.apache.org/jira/browse/THRIFT-1164) - Segmentation fault on NULL pointer in t_js_generator::generate_const - [THRIFT-1171](https://issues.apache.org/jira/browse/THRIFT-1171) - Perl write/readDouble assumes little-endian platform - [THRIFT-1222](https://issues.apache.org/jira/browse/THRIFT-1222) - Unhandled exception for TEvhttpServer request - [THRIFT-1220](https://issues.apache.org/jira/browse/THRIFT-1220) - TProcessor::process never returns false - [THRIFT-1285](https://issues.apache.org/jira/browse/THRIFT-1285) - Stable 0.7.0 Windows compiler exe available on the webside is not the good one - [THRIFT-1218](https://issues.apache.org/jira/browse/THRIFT-1218) - c_glib uses wrong name in pkg-config - [THRIFT-1215](https://issues.apache.org/jira/browse/THRIFT-1215) - Undefined property Thirft in lib/js/thrift.js - [THRIFT-1211](https://issues.apache.org/jira/browse/THRIFT-1211) - When using THttpClient, non 200 responses leave the connection open - [THRIFT-1228](https://issues.apache.org/jira/browse/THRIFT-1228) - The php accelerator module calls flush incorrectly - [THRIFT-1308](https://issues.apache.org/jira/browse/THRIFT-1308) - libfb303-0.7.0.jar missing in maven repository - [THRIFT-1255](https://issues.apache.org/jira/browse/THRIFT-1255) - Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) - [THRIFT-1253](https://issues.apache.org/jira/browse/THRIFT-1253) - Code generated for maps is not compiling - [THRIFT-1252](https://issues.apache.org/jira/browse/THRIFT-1252) - Segfault in Ruby deserializer - [THRIFT-1094](https://issues.apache.org/jira/browse/THRIFT-1094) - bug in TCompactProto python readMessageEnd method and updated test cases - [THRIFT-1093](https://issues.apache.org/jira/browse/THRIFT-1093) - several bugs in python TCompactProtocol - [THRIFT-1092](https://issues.apache.org/jira/browse/THRIFT-1092) - generated validate() method has wrong indentation - [THRIFT-1011](https://issues.apache.org/jira/browse/THRIFT-1011) - Error generating package imports when using classes from other packages - [THRIFT-1050](https://issues.apache.org/jira/browse/THRIFT-1050) - Declaring an argument named "manager" to a service method produces code that fails compile due to name conflicts with protected ivars in TAsyncClient - [THRIFT-1074](https://issues.apache.org/jira/browse/THRIFT-1074) - .keystore and .truststore are missing from the 0.6.0 distribution - [THRIFT-1067](https://issues.apache.org/jira/browse/THRIFT-1067) - Tons of bugs in php implementation - [THRIFT-1065](https://issues.apache.org/jira/browse/THRIFT-1065) - Unexpected exceptions not proper handled on JS - [THRIFT-1076](https://issues.apache.org/jira/browse/THRIFT-1076) - Erlang Thrift socket server has a bug that causes java thrift client of framed binary client to throw "out of sequence" exception - [THRIFT-1057](https://issues.apache.org/jira/browse/THRIFT-1057) - casts in TBinaryProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc - [THRIFT-1055](https://issues.apache.org/jira/browse/THRIFT-1055) - csharp TServerSocket and TSocket do not disable Nagle via Socket.NoDelay = true like cpp and java do - [THRIFT-1054](https://issues.apache.org/jira/browse/THRIFT-1054) - explicit call to PKG_PROG_PKG_CONFIG is missing and first use of PKG_CHECK_MODULES may not happen, causes mono detection to fail - [THRIFT-1117](https://issues.apache.org/jira/browse/THRIFT-1117) - JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment - [THRIFT-1111](https://issues.apache.org/jira/browse/THRIFT-1111) - The HTML generator does not distinguish between string and binary types - [THRIFT-1032](https://issues.apache.org/jira/browse/THRIFT-1032) - "make dist" fails due to c_glib problem - [THRIFT-1036](https://issues.apache.org/jira/browse/THRIFT-1036) - Auto-generated C++ code fails to compile with "-Werror -Wextra -Wall" g++ compiler flags - [THRIFT-1041](https://issues.apache.org/jira/browse/THRIFT-1041) - TDeserializer holds onto a reference of the array it reads after it is done deserializing - [THRIFT-1106](https://issues.apache.org/jira/browse/THRIFT-1106) - C++ code TAsyncProtocolProcessor.h & TAsyncBufferProcessor.h dont have virtual functions but no virtual destructor. Causes warnings on -Wall - [THRIFT-1105](https://issues.apache.org/jira/browse/THRIFT-1105) - OCaml generator does not prefix methods of included structs with their type - [THRIFT-1104](https://issues.apache.org/jira/browse/THRIFT-1104) - INSTALLDIRS should be included in configure script - [THRIFT-1102](https://issues.apache.org/jira/browse/THRIFT-1102) - typo in configure.ac: "==" operator in 'test' (instead of"'=") - [THRIFT-1101](https://issues.apache.org/jira/browse/THRIFT-1101) - bytebuffer length calculation in TBinaryProtocol writeBinary - [THRIFT-1098](https://issues.apache.org/jira/browse/THRIFT-1098) - Undefined properties in TBinaryProtocolFactory - [THRIFT-1081](https://issues.apache.org/jira/browse/THRIFT-1081) - PHP tests broken and somewhat incomplete - [THRIFT-1080](https://issues.apache.org/jira/browse/THRIFT-1080) - erlang test's 'make' fails on Mac OSX - [THRIFT-1078](https://issues.apache.org/jira/browse/THRIFT-1078) - ThriftTest.thrift generates invalid PHP library - [THRIFT-1120](https://issues.apache.org/jira/browse/THRIFT-1120) - proto.WriteListEnd being called in the wrong place - [THRIFT-1119](https://issues.apache.org/jira/browse/THRIFT-1119) - TJSONProtocol fails to UTF8 decode strings - [THRIFT-867](https://issues.apache.org/jira/browse/THRIFT-867) - PHP accelerator module's output transport is incompatible with TFramedTransport - [THRIFT-826](https://issues.apache.org/jira/browse/THRIFT-826) - PHP TSocket Write Timeout - [THRIFT-835](https://issues.apache.org/jira/browse/THRIFT-835) - Bad AS3 syntax in constructors that set default values - [THRIFT-788](https://issues.apache.org/jira/browse/THRIFT-788) - thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly - [THRIFT-125](https://issues.apache.org/jira/browse/THRIFT-125) - OCaml libraries don't compile with 32-bit ocaml - [THRIFT-342](https://issues.apache.org/jira/browse/THRIFT-342) - PHP: can't have sets of complex types - [THRIFT-731](https://issues.apache.org/jira/browse/THRIFT-731) - configure doesn't check for ant >= 1.7 - [THRIFT-690](https://issues.apache.org/jira/browse/THRIFT-690) - Update TApplicationException codes - [THRIFT-638](https://issues.apache.org/jira/browse/THRIFT-638) - BufferedTransport + C extensions block until recv timeout is reached on last fread call ### Dependency upgrade - [THRIFT-1177](https://issues.apache.org/jira/browse/THRIFT-1177) - Update thrift to reflect changes in Go's networking libraries ### Improvement - [THRIFT-1155](https://issues.apache.org/jira/browse/THRIFT-1155) - Remove log4j dependency from java client - [THRIFT-1151](https://issues.apache.org/jira/browse/THRIFT-1151) - Produce more informative runtime error in case of schema and data mismatch during serialization - [THRIFT-1207](https://issues.apache.org/jira/browse/THRIFT-1207) - Support DESTDIR on "make install" of ruby libs - [THRIFT-1199](https://issues.apache.org/jira/browse/THRIFT-1199) - Union structs should have generated methods to test whether a specific field is currently set - [THRIFT-1233](https://issues.apache.org/jira/browse/THRIFT-1233) - Remove unused include in generated C++ code - [THRIFT-1189](https://issues.apache.org/jira/browse/THRIFT-1189) - Ruby deserializer speed improvements - [THRIFT-1170](https://issues.apache.org/jira/browse/THRIFT-1170) - Thrift Generated Code and Java 5 - [THRIFT-1174](https://issues.apache.org/jira/browse/THRIFT-1174) - Publish as3 client implementation via Maven for use by flex-mojos users - [THRIFT-1225](https://issues.apache.org/jira/browse/THRIFT-1225) - TCompactProtocol for PHP - [THRIFT-1221](https://issues.apache.org/jira/browse/THRIFT-1221) - Remove SimpleCallback.h - [THRIFT-1217](https://issues.apache.org/jira/browse/THRIFT-1217) - Use evutil_socketpair instead of pipe (Windows port) - [THRIFT-1216](https://issues.apache.org/jira/browse/THRIFT-1216) - build Java Library behind a proxy - [THRIFT-1231](https://issues.apache.org/jira/browse/THRIFT-1231) - Remove bogus include - [THRIFT-1213](https://issues.apache.org/jira/browse/THRIFT-1213) - Membuffer should provide a way to get back the buffer - [THRIFT-1237](https://issues.apache.org/jira/browse/THRIFT-1237) - Java fb303 missing some methods - [THRIFT-1063](https://issues.apache.org/jira/browse/THRIFT-1063) - Fix Erlang Tutorial Files - [THRIFT-1053](https://issues.apache.org/jira/browse/THRIFT-1053) - Make remote client's IP address available for all socket related transports - [THRIFT-1109](https://issues.apache.org/jira/browse/THRIFT-1109) - Deploy fb303 along side libthrift to maven repo - [THRIFT-1107](https://issues.apache.org/jira/browse/THRIFT-1107) - improvement for compiler-generated python for 'None' object comparisons - [THRIFT-1069](https://issues.apache.org/jira/browse/THRIFT-1069) - Add command line option to prevent thrift from inserting gen-* directories - [THRIFT-1049](https://issues.apache.org/jira/browse/THRIFT-1049) - Allow for TServerSocket python library to bind to a specific host - [THRIFT-1126](https://issues.apache.org/jira/browse/THRIFT-1126) - Extending struct_info for erlang bindings - [THRIFT-1100](https://issues.apache.org/jira/browse/THRIFT-1100) - python TSSLSocket improvements, including certificate validation - [THRIFT-994](https://issues.apache.org/jira/browse/THRIFT-994) - Don't try to invoke phpize if we don't have it - [THRIFT-993](https://issues.apache.org/jira/browse/THRIFT-993) - Some improvements in C++ stubs for oneway operations - [THRIFT-997](https://issues.apache.org/jira/browse/THRIFT-997) - Using valueOf for base types in getFieldValue - [THRIFT-418](https://issues.apache.org/jira/browse/THRIFT-418) - Don't do runtime sorting of struct fields - [THRIFT-151](https://issues.apache.org/jira/browse/THRIFT-151) - TSSLServerSocket and TSSLSocket implementation - [THRIFT-27](https://issues.apache.org/jira/browse/THRIFT-27) - Generated erlang types don't contain default values for records - [THRIFT-113](https://issues.apache.org/jira/browse/THRIFT-113) - to-string methods should omit optional null fields from output - [THRIFT-363](https://issues.apache.org/jira/browse/THRIFT-363) - Maven Deploy - [THRIFT-447](https://issues.apache.org/jira/browse/THRIFT-447) - Make an abstract base Client class so we can generate less code - [THRIFT-627](https://issues.apache.org/jira/browse/THRIFT-627) - should c++ have setters for optional fields? ### New Feature - [THRIFT-1236](https://issues.apache.org/jira/browse/THRIFT-1236) - Erlang Reconnecting Thrift Client - [THRIFT-1021](https://issues.apache.org/jira/browse/THRIFT-1021) - Framed transport support for OCaml - [THRIFT-1068](https://issues.apache.org/jira/browse/THRIFT-1068) - Python SSL Socket Support - [THRIFT-1103](https://issues.apache.org/jira/browse/THRIFT-1103) - TZlibTransport for python, a zlib compressed transport - [THRIFT-1083](https://issues.apache.org/jira/browse/THRIFT-1083) - Preforking python process pool server - [THRIFT-999](https://issues.apache.org/jira/browse/THRIFT-999) - Add TForkingServer ### Sub-task - [THRIFT-1152](https://issues.apache.org/jira/browse/THRIFT-1152) - Attributes from private to protected - [THRIFT-1038](https://issues.apache.org/jira/browse/THRIFT-1038) - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable ### Task - [THRIFT-892](https://issues.apache.org/jira/browse/THRIFT-892) - Refactor erlang build system with rebar ### Wish - [THRIFT-625](https://issues.apache.org/jira/browse/THRIFT-625) - Add support for 'Go' ## 0.6.1 ### Bug - [THRIFT-1133](https://issues.apache.org/jira/browse/THRIFT-1133) - Java and JavaScript tutorial is broken since we have Java maven deployment - [THRIFT-1131](https://issues.apache.org/jira/browse/THRIFT-1131) - C# JSON Protocol is unable to decode escaped characters in string - [THRIFT-1074](https://issues.apache.org/jira/browse/THRIFT-1074) - .keystore and .truststore are missing from the 0.6.0 distribution ### Improvement - [THRIFT-1109](https://issues.apache.org/jira/browse/THRIFT-1109) - Deploy fb303 along side libthrift to maven repo - [THRIFT-363](https://issues.apache.org/jira/browse/THRIFT-363) - Maven Deploy ### Question - [THRIFT-1206](https://issues.apache.org/jira/browse/THRIFT-1206) - did the THRIFT 0.6.1 merge THRIFT-563 ? ### Sub-task - [THRIFT-1163](https://issues.apache.org/jira/browse/THRIFT-1163) - How can i use multi service in one program? ### Task - [THRIFT-1112](https://issues.apache.org/jira/browse/THRIFT-1112) - Apply THRIFT-363 to 0.6 branch - [THRIFT-1113](https://issues.apache.org/jira/browse/THRIFT-1113) - Apply THRIFT-1074 to 0.6 branch ## 0.6 ### Bug - [THRIFT-1020](https://issues.apache.org/jira/browse/THRIFT-1020) - OCaml compiler generates invalid OCaml - [THRIFT-1015](https://issues.apache.org/jira/browse/THRIFT-1015) - TUnion does not handle ByteBuffer in toString - [THRIFT-1013](https://issues.apache.org/jira/browse/THRIFT-1013) - generated java code may have name clashes with thrift library - [THRIFT-1009](https://issues.apache.org/jira/browse/THRIFT-1009) - TUnion does not correctly deep copy a ByteBuffer - [THRIFT-1032](https://issues.apache.org/jira/browse/THRIFT-1032) - "make dist" fails due to c_glib problem - [THRIFT-868](https://issues.apache.org/jira/browse/THRIFT-868) - Referencing constant values doesn't work with with typedef types - [THRIFT-971](https://issues.apache.org/jira/browse/THRIFT-971) - java module can't be compiled without ivy and network connection - [THRIFT-970](https://issues.apache.org/jira/browse/THRIFT-970) - Under heavy load, THttpClient may fail with "too many open files" - [THRIFT-969](https://issues.apache.org/jira/browse/THRIFT-969) - Java Tutorial broken, move CalculatorHandler to a separate file - [THRIFT-807](https://issues.apache.org/jira/browse/THRIFT-807) - JavaScript: Initialization of Base Types with 0 instead of null - [THRIFT-955](https://issues.apache.org/jira/browse/THRIFT-955) - Thrift compiler for Windows uses lowercase names and directories which is inconsistent with compiling on other platforms - [THRIFT-992](https://issues.apache.org/jira/browse/THRIFT-992) - Naming convention in C# constructor is not consistent with other fields causes compile errors - [THRIFT-1008](https://issues.apache.org/jira/browse/THRIFT-1008) - byte[] accessors throw NPE on unset field - [THRIFT-1006](https://issues.apache.org/jira/browse/THRIFT-1006) - Impossible to correctly qualify an enum constant in an external thrift file - [THRIFT-950](https://issues.apache.org/jira/browse/THRIFT-950) - Haskell bindings treat 'byte' as unsigned 8-bit int (Data.Word.Word8), java/cpp as signed (byte/int8_t). - [THRIFT-975](https://issues.apache.org/jira/browse/THRIFT-975) - lib/c_glib/README is missing => breaks make dist - [THRIFT-944](https://issues.apache.org/jira/browse/THRIFT-944) - Support all version-4s of base - [THRIFT-939](https://issues.apache.org/jira/browse/THRIFT-939) - optional binary fields throw NPE on default byte[] getters - [THRIFT-935](https://issues.apache.org/jira/browse/THRIFT-935) - PHP Extension aborts the build if php-config is not installed - [THRIFT-933](https://issues.apache.org/jira/browse/THRIFT-933) - Haskell's Thrift.cabal has warnings - [THRIFT-932](https://issues.apache.org/jira/browse/THRIFT-932) - Haskell tests need to be run through 'make check' (and probably 'cabal check') too - [THRIFT-904](https://issues.apache.org/jira/browse/THRIFT-904) - C# TSocket should disable nagle and linger - [THRIFT-941](https://issues.apache.org/jira/browse/THRIFT-941) - Make PHP C Extension use the defined Protocol writeMessageBegin function - [THRIFT-940](https://issues.apache.org/jira/browse/THRIFT-940) - 'make check' fails if boost is not in the std include and link paths - [THRIFT-924](https://issues.apache.org/jira/browse/THRIFT-924) - Fix generated php structure constants - [THRIFT-979](https://issues.apache.org/jira/browse/THRIFT-979) - ruby bindings used to work on jruby - [THRIFT-977](https://issues.apache.org/jira/browse/THRIFT-977) - Hex Conversion Bug in C++ TJSONProtocol - [THRIFT-347](https://issues.apache.org/jira/browse/THRIFT-347) - PHP TSocket Timeout Issues - [THRIFT-517](https://issues.apache.org/jira/browse/THRIFT-517) - TExceptions thrown by server result in cryptic error message on client) - Tried to read 4 bytes, but only got 0 bytes ### Improvement - [THRIFT-1024](https://issues.apache.org/jira/browse/THRIFT-1024) - Add Python Twisted example to the Tutorial - [THRIFT-958](https://issues.apache.org/jira/browse/THRIFT-958) - Change accessmodifer on trans_ field in the FrameBuffer class to public. - [THRIFT-957](https://issues.apache.org/jira/browse/THRIFT-957) - THsHaServer: Change access modifier of the invoker field. - [THRIFT-1002](https://issues.apache.org/jira/browse/THRIFT-1002) - CodeStyle: t_c_glib_generator.cc - [THRIFT-1005](https://issues.apache.org/jira/browse/THRIFT-1005) - Give unions byte[] signature methods to go along with their ByteBuffer counterparts - [THRIFT-951](https://issues.apache.org/jira/browse/THRIFT-951) - Add a new isServing() method to TServer - [THRIFT-943](https://issues.apache.org/jira/browse/THRIFT-943) - Silly readme typo fix. - [THRIFT-961](https://issues.apache.org/jira/browse/THRIFT-961) - JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler - [THRIFT-960](https://issues.apache.org/jira/browse/THRIFT-960) - add TestServer, TestNonblockingServer and TestClient again - [THRIFT-949](https://issues.apache.org/jira/browse/THRIFT-949) - Modify the TEnum interface so it defines a method similar to findByValue - [THRIFT-946](https://issues.apache.org/jira/browse/THRIFT-946) - Augment FieldValueMetaData so it differentiates 'string' and 'binary' fields. - [THRIFT-903](https://issues.apache.org/jira/browse/THRIFT-903) - custom ThreadFactory in THsHaServer - [THRIFT-913](https://issues.apache.org/jira/browse/THRIFT-913) - Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh - [THRIFT-926](https://issues.apache.org/jira/browse/THRIFT-926) - Miscellaneous C++ improvements - [THRIFT-929](https://issues.apache.org/jira/browse/THRIFT-929) - Improvements to the C++ test suite - [THRIFT-893](https://issues.apache.org/jira/browse/THRIFT-893) - add JavaScript to the tutorial examples - [THRIFT-1003](https://issues.apache.org/jira/browse/THRIFT-1003) - Polishing c_glib code - [THRIFT-71](https://issues.apache.org/jira/browse/THRIFT-71) - Debian packaging for thrift ### New Feature - [THRIFT-1033](https://issues.apache.org/jira/browse/THRIFT-1033) - Node.js language target - [THRIFT-947](https://issues.apache.org/jira/browse/THRIFT-947) - Provide a helper method to determine the TProtocol used to serialize some data. - [THRIFT-928](https://issues.apache.org/jira/browse/THRIFT-928) - Make more statistics available in C++ servers - [THRIFT-922](https://issues.apache.org/jira/browse/THRIFT-922) - Templatized [de]serialization code for C++ - [THRIFT-923](https://issues.apache.org/jira/browse/THRIFT-923) - Event-driven client and server support for C++ - [THRIFT-925](https://issues.apache.org/jira/browse/THRIFT-925) - Provide name<->value map for enums in C++ - [THRIFT-927](https://issues.apache.org/jira/browse/THRIFT-927) - Add option to modify the PHP include path - [THRIFT-377](https://issues.apache.org/jira/browse/THRIFT-377) - TFileTransport port in Java - [THRIFT-106](https://issues.apache.org/jira/browse/THRIFT-106) - TSSLServerSocket - [THRIFT-582](https://issues.apache.org/jira/browse/THRIFT-582) - C implementation of Thrift - [THRIFT-745](https://issues.apache.org/jira/browse/THRIFT-745) - Make it easier to instantiate servers ### Sub-task - [THRIFT-1038](https://issues.apache.org/jira/browse/THRIFT-1038) - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable ### Task - [THRIFT-862](https://issues.apache.org/jira/browse/THRIFT-862) - Async client issues / improvements ### Test - [THRIFT-581](https://issues.apache.org/jira/browse/THRIFT-581) - Add a testsuite for txThrift (Twisted) ## Incubating Versions Thrift 0.5.0) - Incubating -------------------------------------------------------------------------------- THRIFT-505 Build Make configure give a summary of the enabled components (David Reiss) THRIFT-506 Build Allow Thrift to be built without the C++ library (David Reiss) THRIFT-844 Build Build Requirements state autoconf 2.59+ is required, but 2.60+ is needed (Harlan Lieberman-Berg) THRIFT-850 Build Perl runtime requires Bit::Vector which may not be installed by default, but configure does not fail (Michael Lum) THRIFT-854 Build Provide configure option and make rules to build/install php extension (Anthony Molinaro) THRIFT-858 Build Have bootstrap.sh check for a suitable autoconf version before running (David Reiss) THRIFT-871 Build Thrift compiler for WIndows (binary distribution) (David Reiss) THRIFT-323 C# TJSONProtocol (Roger Meier) THRIFT-634 C# C# Compiler Generates Incorrect Code For Fields which begin with an uppercase letter (Jon S Akhtar) THRIFT-881 C# add csharp to the tutorial (Roger Meier) THRIFT-856 C++ Building cpp library fails on OS X with malloc and free not being declared in scope (James Clarke) THRIFT-865 C++ C++ compiler build depends on libfl even when flex/lex not detected (David Reiss) THRIFT-900 C++ Unix domain socket (Roger Meier) THRIFT-920 C++ C++ Test and Tutorial does not compile anymore due to the change within Enum handling (Roger Meier) THRIFT-567 C++ Can't immediately stop a TSimpleServer thread that is idle (Rush Manbert) THRIFT-756 C++ Exposing TSocket(int) constructor to public (Rajat Goel) THRIFT-798 C++ TNonblockingServer leaks resources when destroyed (David Reiss) THRIFT-812 C++, Python Demo of Thrift over ZeroMQ (David Reiss) THRIFT-629 Cocoa Unused Field In TSocketServer Appears To Break iPhone Build (Jon S Akhtar) THRIFT-838 Cocoa Generated Cocoa classes have useless @dynamic declarations (Kevin Ballard) THRIFT-805 Cocoa Don't generate process_XXXX methods for oneway methods (Brad Taylor) THRIFT-507 Compiler Remove the compiler's dependency on Boost (David Reiss) THRIFT-895 Compiler (General) Thrift compiler does not allow two different enumerations to have the same key name for one of the enum values (David Reiss) THRIFT-852 Compiler (General) Missing newline causes many compiler warnings (Anthony Molinaro) THRIFT-877 Compiler (General) smalltalk namespace doesn't work (Bruce Lowekamp) THRIFT-897 Compiler (General) Don't allow unqualified constant access to enum values (Bryan Duxbury) THRIFT-9 Compiler (General) Add a default namespace declaration for all languages (David Reiss) THRIFT-599 Erlang Don't use unnecessary processes in the Erlang transports and clients (David Reiss) THRIFT-646 Erlang Erlang library is missing install target (David Reiss) THRIFT-698 Erlang Generated module list should contain atoms, not strings (Anthony Molinaro) THRIFT-866 Erlang term() in spec definitions seems to not work in erlang R12 (Anthony Molinaro) THRIFT-886 Erlang Dialyzer warning (Anthony Molinaro) THRIFT-785 Erlang Framed transport server problems (Anthony Molinaro) THRIFT-884 HTML HTML Generator: add Key attribute to the Data Types Tables (Roger Meier) THRIFT-652 Haskell Generated field name for strut is not capitalized correctly (Christian Lavoie) THRIFT-743 Haskell compile error with GHC 6.12.1 (Christian Lavoie) THRIFT-901 Haskell Allow the bindings to compile without -fglasgow-exts and with -Wall -Werror (Christian Lavoie) THRIFT-905 Haskell Make haskell thrift bindings use automake to compile and install (Christian Lavoie) THRIFT-906 Haskell Improve type mappings (Christian Lavoie) THRIFT-914 Haskell Make haskell bindings 'easily' compilable (Christian Lavoie) THRIFT-918 Haskell Make haskell tests run again (Christian Lavoie) THRIFT-919 Haskell Update Haskell bindings README (Christian Lavoie) THRIFT-787 Haskell Enums are not read correctly (Christian Lavoie) THRIFT-250 Java ExecutorService as a constructor parameter for TServer (Ed Ceaser) THRIFT-693 Java Thrift compiler generated java code that throws compiler warnings about deprecated methods. (Bryan Duxbury) THRIFT-843 Java TNonblockingSocket connects without a timeout (Bryan Duxbury) THRIFT-845 Java async client does not respect timeout (Ning Liang) THRIFT-870 Java Java constants don't get Javadoc comments (Bryan Duxbury) THRIFT-873 Java Java tests fail due to Too many open files (Todd Lipcon) THRIFT-876 Java Add SASL support (Aaron T. Myers) THRIFT-879 Java Remove @Override from TUnion.clear (Dave Engberg) THRIFT-882 Java deep copy of binary fields does not copy ByteBuffer characteristics (arrayOffset, position) (Bryan Duxbury) THRIFT-888 Java async client should also have nonblocking connect (Eric Jensen) THRIFT-890 Java Java tutorial doesn't work (Todd Lipcon) THRIFT-894 Java Make default accessors for binary fields return byte[]; provide new accessors to get ByteBuffer version (Bryan Duxbury) THRIFT-896 Java TNonblockingSocket.isOpen() returns true even after close() (Eric Jensen) THRIFT-907 Java libfb303 doesn't compile in 0.4.0 (Todd Lipcon) THRIFT-912 Java Improvements and bug fixes to SASL implementation (Todd Lipcon) THRIFT-917 Java THsHaServer should not accept an ExecutorService without catching RejectedExecutionException (Ed Ceaser) THRIFT-931 Java Use log4j for Java tests (Todd Lipcon) THRIFT-880 JavaME JavaME code generator and runtime library (Dave Engberg) THRIFT-846 JavaScript JavaScript Test Framwork: extended Testcases (Roger Meier) THRIFT-885 JavaScript Url encoded strings never get decoded? How do we fix this? (T Jake Luciani) THRIFT-911 JavaScript (JavaScript compiler) Const structs, maps, sets, and lists generate a trailing comma (T Jake Luciani) THRIFT-860 OCaml copy method and reset method (Lev Walkin) THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) THRIFT-851 PHP php extension fails to compile on centos 5.x (Todd Lipcon) THRIFT-840 Perl Perl protocol handler could be more robust against unrecognised types (Conrad Hughes) THRIFT-758 Perl incorrect deference in exception handling (Yann Kerherve) THRIFT-257 Python Support validation of required fields (Esteve Fernandez) THRIFT-335 Python Compact Protocol for Python (David Reiss) THRIFT-596 Python Make Python's TBufferedTransport use a configurable input buffer (David Reiss) THRIFT-597 Python Python THttpServer performance improvements (David Reiss) THRIFT-598 Python Allow Python's threading servers to use daemon threads (David Reiss) THRIFT-666 Python Allow the handler to override HTTP responses in THttpServer (David Reiss) THRIFT-673 Python Generated Python code has whitespace issues (Ian Eure) THRIFT-721 Python THttpClient ignores url parameters (Thomas Kho) THRIFT-824 Python TApplicationException.__str__() refers to class constants as globals (Peter Schuller) THRIFT-855 Python Include optimized compiled python objects in install (Anthony Molinaro) THRIFT-859 Python Allow py:twisted to be generated in different namespace than py (Bruce Lowekamp) THRIFT-869 Python TSocket.py on Mac (and FreeBSD) doesn't handle ECONNRESET from recv() (Steven Knight) THRIFT-875 Python Include python setup.cfg in dist (Anthony Molinaro) THRIFT-610 Ruby binary_protocol.rb segfaults [line 86] (Unassigned) THRIFT-899 Ruby Ruby read timeouts can sometimes be 2x what they should be (Ryan King) THRIFT-909 Ruby allow block argument to struct constructor (Michael Stockton) THRIFT-456 Test Suite Bad IP address string in test/cpp/src/main.cpp (Rush Manbert) Thrift 0.4.0) - Incubating -------------------------------------------------------------------------------- THRIFT-650 Build Make Check fails on Centos/OSX with 0.2.0 tarball (Anthony Molinaro) THRIFT-770 Build Get 'make dist' to work without first compiling source code (Anthony Molinaro) THRIFT-160 C# Created THttpTransport for the C# library based on WebHttpRequest (Michael Greene) THRIFT-834 C# THttpClient resends contents of message after transport errors (Anatoly Fayngelerin) THRIFT-247 C++ THttpServer Transport (Unassigned) THRIFT-676 C++ Change C++ code generator so that generated classes can be wrapped with SWIG (Unassigned) THRIFT-570 Compiler Thrift compiler does not error when duplicate method names are present (Bruce Simpson) THRIFT-808 Compiler Segfault when constant declaration references a struct field that doesn't exist (Bryan Duxbury) THRIFT-646 Erlang Erlang library is missing install target (Anthony Molinaro) THRIFT-544 General multiple enums with the same key generate invalid code (Ben Taitelbaum) THRIFT-434 General ruby compiler should warn when a reserved word is used (Michael Stockton) THRIFT-799 General Files missing proper Apache license header (Bryan Duxbury) THRIFT-832 HTML HTML generator shows unspecified struct fields as 'required' (Bryan Duxbury) THRIFT-226 Java Collections with binary keys or values break equals() (Bryan Duxbury) THRIFT-484 Java Ability to use a slice of a buffer instead of a direct byte[] for binary fields (Bryan Duxbury) THRIFT-714 Java maxWorkerThreads parameter to THsHaServer has no effect (Bryan Duxbury) THRIFT-751 Java Add clear() method to TBase (Bryan Duxbury) THRIFT-765 Java Improved string encoding and decoding performance (Bryan Duxbury) THRIFT-768 Java Async client for Java (Bryan Duxbury) THRIFT-774 Java TDeserializer should provide a partialDeserialize method for primitive types (Piotr Kozikowski) THRIFT-783 Java .equals java method is broken on structs containing binary-type fields (Unassigned) THRIFT-804 Java CompareTo is broken for unions set to map, set, or list (Bryan Duxbury) THRIFT-814 Java Include a TServlet in the standard Thrift distribution (Mathias Herberts) THRIFT-818 Java Async client doesn't send method args (Bryan Duxbury) THRIFT-830 Java Switch binary field implementation from byte[] to ByteBuffer (Bryan Duxbury) THRIFT-831 Java FramedTransport implementation that reuses its buffers (Bryan Duxbury) THRIFT-833 Java build.xml in lib/java is missing a classpathref attribute for the javadoc task (Bryan Duxbury) THRIFT-836 Java Race condition causes CancelledKeyException in TAsyncClientManager (Bryan Duxbury) THRIFT-842 Java Upgrade to current version of commons-lang (2.5 instead of 2.4) and/or change dependency in ivy.xml to not be exact (Bryan Duxbury) THRIFT-815 JavaScript Deserialization of lists is critically broken. (T Jake Luciani) THRIFT-827 OCaml OCaml generator to take default values into account (Lev Walkin) THRIFT-647 PHP PHP library is missing install target (Anthony Molinaro) THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) THRIFT-718 PHP Thrift PHP library includes closing tags and extraneous whitespace (Nicholas Telford) THRIFT-778 PHP PHP socket listening server (Nick Jones) THRIFT-780 PHP PHP extension sometimes causes an abort with two exceptions at the same time (David Reiss) THRIFT-837 PHP PHP accelerator bug for writes > 8k (Thomas Kho) THRIFT-782 Perl Perl code for writing containers doesn't count length of write*Begin or write*End (Conrad Hughes) THRIFT-395 Python Python library + compiler does not support unicode strings (Unassigned) THRIFT-133 Ruby 'namespace ruby' should error out, or be an alias to 'namespace rb' (Bryan Duxbury) THRIFT-664 Ruby Ruby extension fails to build with Ruby 1.9.1 (Rajesh Malepati) THRIFT-699 Ruby Excise unused "native protocol method table" stuff from thrift_native (Bryan Duxbury) THRIFT-767 Ruby ruby compiler does not keep comments for enum values (Bryan Duxbury) THRIFT-811 Ruby http_client_transport.rb: allow custom http headers (Tony Kamenick) THRIFT-459 Ruby Ruby installation always tries to write to /Library/Ruby/site (Matthieu Imbert) Thrift 0.1.0) - Incubating (not released) -------------------------------------------------------------------------------- Compatibility Breaking Changes: C++: - It's quite possible that regenerating code and rebuilding will be required. Make sure your headers match your libs! Java: Python: Ruby: - Generated files now have underscored names [THRIFT-421] - The library has been rearranged to be more Ruby-like [THRIFT-276] Erlang: - Generated code will have to be regenerated, and the new code will have to be deployed atomically with the new library code [THRIFT-136] New Features and Bug Fixes: C++: - Support for TCompactProtocol [THRIFT-333] Java: - Support for TCompactProtocol [THRIFT-110] Python: - Support for Twisted [THRIFT-148] Ruby: - Support for TCompactProtocol [THRIFT-332] thrift-0.19.0/compiler/0000755000000000000000000000000014472652642014725 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/0000755000000000000000000000000014472652643015510 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/tests/0000777000000000000000000000000014370300523016636 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/tests/netcore/0000777000000000000000000000000014303740367020307 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc0000644000000000000000000001445114303740367027613 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include "../catch/catch.hpp" #include #include using std::vector; TEST_CASE("t_netstd_generator::netstd_type_usings() without option wcf should return valid namespaces", "[helpers]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "union", "union" } }; string option_string = ""; string expected_namespaces = "using System;\n" "using System.Collections;\n" "using System.Collections.Generic;\n" "using System.Text;\n" "using System.IO;\n" "using System.Threading;\n" "using System.Threading.Tasks;\n" "using Thrift;\n" "using Thrift.Collections;\n" + endl; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); REQUIRE_FALSE(gen->is_wcf_enabled()); REQUIRE(gen->netstd_type_usings() == expected_namespaces); delete gen; delete program; } TEST_CASE("t_netstd_generator::netstd_type_usings() with option wcf should return valid namespaces", "[helpers]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; string expected_namespaces_wcf = "using System;\n" "using System.Collections;\n" "using System.Collections.Generic;\n" "using System.Text;\n" "using System.IO;\n" "using System.Threading;\n" "using System.Threading.Tasks;\n" "using Thrift;\n" "using Thrift.Collections;\n" "using System.ServiceModel;\n" "using System.Runtime.Serialization;\n" + endl; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); REQUIRE(gen->is_wcf_enabled()); REQUIRE(gen->netstd_type_usings() == expected_namespaces_wcf); delete gen; delete program; } TEST_CASE("t_netstd_generator should contains latest C# keywords to normalize with @", "[helpers]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; vector current_keywords = { { "abstract" }, { "as" }, { "base" }, { "bool" }, { "break" }, { "byte" }, { "case" }, { "catch" }, { "char" }, { "checked" }, { "class" }, { "const" }, { "continue" }, { "decimal" }, { "default" }, { "delegate" }, { "do" }, { "double" }, { "else" }, { "enum" }, { "event" }, { "explicit" }, { "extern" }, { "false" }, { "finally" }, { "fixed" }, { "float" }, { "for" }, { "foreach" }, { "goto" }, { "if" }, { "implicit" }, { "in" }, { "int" }, { "interface" }, { "internal" }, { "is" }, { "lock" }, { "long" }, { "namespace" }, { "new" }, { "null" }, { "object" }, { "operator" }, { "out" }, { "override" }, { "params" }, { "private" }, { "protected" }, { "public" }, { "readonly" }, { "ref" }, { "return" }, { "sbyte" }, { "sealed" }, { "short" }, { "sizeof" }, { "stackalloc" }, { "static" }, { "string" }, { "struct" }, { "switch" }, { "this" }, { "throw" }, { "true" }, { "try" }, { "typeof" }, { "uint" }, { "ulong" }, { "unchecked" }, { "unsafe" }, { "ushort" }, { "using" }, { "void" }, { "volatile" }, { "while" }, // Contextual Keywords { "add" }, { "alias" }, { "ascending" }, { "async" }, { "await" }, { "descending" }, { "dynamic" }, { "from" }, { "get" }, { "global" }, { "group" }, { "into" }, { "join" }, { "let" }, { "orderby" }, { "partial" }, { "remove" }, { "select" }, { "set" }, { "value" }, { "var" }, { "when" }, { "where" }, { "yield" } }; string missed_keywords = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); map generators_keywords = gen->get_keywords_list(); for (vector::iterator it = current_keywords.begin(); it != current_keywords.end(); ++it) { if (generators_keywords.find(*it) == generators_keywords.end()) { missed_keywords = missed_keywords + *it + ","; } } REQUIRE(missed_keywords == ""); delete gen; delete program; } thrift-0.19.0/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc0000644000000000000000000002522314303740367030312 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include "../catch/catch.hpp" #include #include #include "t_netstd_generator_functional_tests_helpers.h" TEST_CASE( "t_netstd_generator should generate valid enum", "[functional]" ) { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); std::pair pair = TestDataGenerator::get_test_enum_data(program); string expected_result = pair.first; t_enum* test_enum = pair.second; string file_path = test_enum->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_enum(out, test_enum)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete test_enum; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid void", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); std::pair pair = TestDataGenerator::get_test_void_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_THROWS(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid string with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_string_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid bool with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_bool_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid sbyte (i8) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i8_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid short (i16) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i16_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid integer (i32) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i32_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid long (i64) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i64_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } TEST_CASE("t_netstd_generator should generate valid double with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_double_const_data(gen); string expected_result = pair.first; t_const* const_ = pair.second; vector consts_; consts_.push_back(const_); string file_path = const_->get_name() + ".cs"; ofstream out; out.open(file_path.c_str()); REQUIRE_NOTHROW(gen->generate_consts(out, consts_)); out.close(); std::ifstream ifs(file_path); string actual_result((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); std::remove(file_path.c_str()); REQUIRE(expected_result == actual_result); delete const_; delete gen; delete program; } thrift-0.19.0/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h0000644000000000000000000000326414303740367031677 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include class TestDataGenerator { public: static const string DEFAULT_FILE_HEADER; static std::pair get_test_enum_data(t_program* program); static std::pair get_test_void_const_data(t_netstd_generator* gen); static std::pair get_test_string_const_data(t_netstd_generator* gen); static std::pair get_test_bool_const_data(t_netstd_generator* gen); static std::pair get_test_i8_const_data(t_netstd_generator* gen); static std::pair get_test_i16_const_data(t_netstd_generator* gen); static std::pair get_test_i32_const_data(t_netstd_generator* gen); static std::pair get_test_i64_const_data(t_netstd_generator* gen); static std::pair get_test_double_const_data(t_netstd_generator* gen); }; thrift-0.19.0/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc0000644000000000000000000001733514303740367032041 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include #include "thrift/common.h" #include #include "t_netstd_generator_functional_tests_helpers.h" const string TestDataGenerator::DEFAULT_FILE_HEADER = "/**" "\n" " * Autogenerated by Thrift Compiler ()" "\n" " *" "\n" " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING" "\n" " * @generated" "\n" " */"; std::pair TestDataGenerator::get_test_enum_data(t_program* program) { string expected_result = DEFAULT_FILE_HEADER + "\n" "\n" "/// \n" "/// TestDoc\n" "/// \n" "public enum TestName\n" "{\n" " None = 0,\n" " First = 1,\n" " Second = 2,\n" "}\n"; t_enum* enum_ = new t_enum(program); enum_->set_name("TestName"); enum_->set_doc("TestDoc"); enum_->append(new t_enum_value("None", 0)); enum_->append(new t_enum_value("First", 1)); enum_->append(new t_enum_value("Second", 2)); return std::pair(expected_result, enum_); } std::pair TestDataGenerator::get_test_void_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER; t_type* type_ = new t_base_type("void", t_base_type::TYPE_VOID); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_string("VoidValue"); t_const* const_ = new t_const(type_, "void", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_string_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const string @string = \"StringValue\";\n" "}\n"; t_type* type_ = new t_base_type("string", t_base_type::TYPE_STRING); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_string("StringValue"); t_const* const_ = new t_const(type_, "string", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_bool_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const bool @bool = true;\n" "}\n"; t_type* type_ = new t_base_type("bool", t_base_type::TYPE_BOOL); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_integer(1); t_const* const_ = new t_const(type_, "bool", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_i8_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const sbyte @sbyte = 127;\n" "}\n"; t_type* type_ = new t_base_type("I8", t_base_type::TYPE_I8); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_integer(127); t_const* const_ = new t_const(type_, "sbyte", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_i16_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const short @short = 32767;\n" "}\n"; t_type* type_ = new t_base_type("i16", t_base_type::TYPE_I16); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_integer(32767); t_const* const_ = new t_const(type_, "short", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_i32_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const int @int = 2147483647;\n" "}\n"; t_type* type_ = new t_base_type("i32", t_base_type::TYPE_I32); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_integer(2147483647); t_const* const_ = new t_const(type_, "int", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_i64_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const long @long = 9223372036854775807;\n" "}\n"; t_type* type_ = new t_base_type("i64", t_base_type::TYPE_I64); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_integer(9223372036854775807); t_const* const_ = new t_const(type_, "long", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } std::pair TestDataGenerator::get_test_double_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" " /// \n" " public const double @double = 9.22337e+18;\n" "}\n"; t_type* type_ = new t_base_type("double", t_base_type::TYPE_DOUBLE); type_->set_doc("TestDoc"); t_const_value* const_value_ = new t_const_value(); const_value_->set_double(9223372036854775807.1); t_const* const_ = new t_const(type_, "double", const_value_); const_->set_doc("TestDoc"); return std::pair(expected_result, const_); } thrift-0.19.0/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc0000644000000000000000000000515414303740367031200 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include "../catch/catch.hpp" #include #include TEST_CASE( "t_netstd_generator should throw error with unknown options", "[initialization]" ) { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "keys", "keys" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = nullptr; REQUIRE_THROWS(gen = new t_netstd_generator(program, parsed_options, option_string)); delete gen; delete program; } TEST_CASE("t_netstd_generator should create valid instance with valid options", "[initialization]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" }, { "nullable", "nullable"} }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = nullptr; REQUIRE_NOTHROW(gen = new t_netstd_generator(program, parsed_options, option_string)); REQUIRE(gen != nullptr); REQUIRE(gen->is_wcf_enabled()); REQUIRE(gen->is_nullable_enabled()); REQUIRE_FALSE(gen->is_hashcode_enabled()); REQUIRE_FALSE(gen->is_serialize_enabled()); REQUIRE_FALSE(gen->is_union_enabled()); delete gen; delete program; } TEST_CASE("t_netstd_generator should pass init succesfully", "[initialization]") { string path = "CassandraTest.thrift"; string name = "netstd"; map parsed_options = { { "wcf", "wcf" },{ "nullable", "nullable" } }; string option_string = ""; t_program* program = new t_program(path, name); t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); REQUIRE_NOTHROW(gen->init_generator()); delete gen; delete program; } thrift-0.19.0/compiler/cpp/tests/CMakeLists.txt0000644000000000000000000001634414370300523021402 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # cmake_minimum_required(VERSION 2.8.12) project(thrift_compiler_tests) set(THRIFT_COMPILER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/.. ) # don't generate ZERO_CHECK set(CMAKE_SUPPRESS_REGENERATION true) # version.h now handled via veralign.sh #configure_file(${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) if(MSVC) # The winflexbison generator outputs some macros that conflict with the Visual Studio 2010 copy of stdint.h # This might be fixed in later versions of Visual Studio, but an easy solution is to include stdint.h first if(HAVE_STDINT_H) add_definitions(-D__STDC_LIMIT_MACROS) add_definitions(/FI"stdint.h") endif(HAVE_STDINT_H) endif() find_package(FLEX REQUIRED) find_package(BISON REQUIRED) # create directory for thrifty and thriftl file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/) # Create flex and bison files and build the lib parse static library BISON_TARGET(thrifty ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/thrifty.yy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc) FLEX_TARGET(thriftl ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/thriftl.ll ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc) ADD_FLEX_BISON_DEPENDENCY(thriftl thrifty) set(parse_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh ) add_library(parse STATIC ${parse_SOURCES}) # Thrift compiler tests set(thrift_compiler_tests ) # you can add some files manually there set(thrift_compiler_tests_manual_SOURCES # tests file to avoid main in every test file ${CMAKE_CURRENT_SOURCE_DIR}/tests_main.cc ) # set variable for tests sources - will be filled later set(thrift_compiler_tests_SOURCES ) set(thrift_compiler_SOURCES ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/logging.cc # we use logging instead of main to avoid breaking compillation (2 main v) ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/audit/t_audit.cpp ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/common.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/t_generator.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/validator_parser.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/validator_parser.h ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/parse/t_typedef.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/parse/parse.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/version.h ) # This macro adds an option THRIFT_COMPILER_${NAME} # that allows enabling or disabling certain languages macro(THRIFT_ADD_COMPILER name description initial) string(TOUPPER "THRIFT_COMPILER_${name}" enabler) set(src "${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/t_${name}_generator.cc") option(${enabler} ${description} ${initial}) if(${enabler}) list(APPEND thrift_compiler_SOURCES ${src}) file(GLOB thrift_compiler_tests_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.c*" "${CMAKE_CURRENT_SOURCE_DIR}/${name}/*.thrift" ) endif() endmacro() # This macro adds an option THRIFT_VALIDATOR_COMPILER_${NAME} # that allows enabling or disabling certain languages macro(THRIFT_ADD_VALIDATOR_COMPILER name description initial) string(TOUPPER "THRIFT_VALIDATOR_COMPILER_${name}" enabler) set(src "${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/${name}_validator_generator.cc") list(APPEND "${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/${name}_validator_generator.h") option(${enabler} ${description} ${initial}) if(${enabler}) list(APPEND thrift-compiler_SOURCES ${src}) endif() endmacro() # The following compiler with unit tests can be enabled or disabled THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" OFF) THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" OFF) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" OFF) THRIFT_ADD_COMPILER(d "Enable compiler for D" OFF) THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" OFF) THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" OFF) THRIFT_ADD_COMPILER(erl "Enable compiler for Erlang" OFF) THRIFT_ADD_COMPILER(go "Enable compiler for Go" OFF) THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" OFF) THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" OFF) THRIFT_ADD_COMPILER(html "Enable compiler for HTML Documentation" OFF) THRIFT_ADD_COMPILER(java "Enable compiler for Java" OFF) THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" OFF) THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" OFF) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" OFF) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" OFF) THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON) THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" OFF) THRIFT_ADD_COMPILER(php "Enable compiler for PHP" OFF) THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" OFF) THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" OFF) THRIFT_ADD_COMPILER(rs "Enable compiler for Rust" OFF) THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" OFF) THRIFT_ADD_COMPILER(swift "Enable compiler for Swift" OFF) THRIFT_ADD_COMPILER(xml "Enable compiler for XML" OFF) THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" OFF) # The following compiler can be enabled or disabled by enabling or disabling certain languages THRIFT_ADD_VALIDATOR_COMPILER(go "Enable validator compiler for Go" ON) # Thrift is looking for include files in the src directory # we also add the current binary directory for generated files include_directories(${CMAKE_CURRENT_BINARY_DIR} ${THRIFT_COMPILER_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR}/catch) add_library(thrift_compiler ${thrift_compiler_SOURCES}) #link parse lib to thrift_compiler lib target_link_libraries(thrift_compiler parse) # add tests executable add_executable(thrift_compiler_tests ${thrift_compiler_tests_manual_SOURCES} ${thrift_compiler_tests_SOURCES}) # if generates for Visual Studio set thrift_compiler_tests as default project if(MSVC) set_property(TARGET thrift_compiler_tests PROPERTY VS_STARTUP_PROJECT thrift_compiler_tests) endif() set_target_properties(thrift_compiler_tests PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin/) set_target_properties(thrift_compiler_tests PROPERTIES OUTPUT_NAME thrift_compiler_tests) target_link_libraries(thrift_compiler_tests thrift_compiler) enable_testing() add_test(NAME ThriftTests COMMAND thrift_compiler_tests) thrift-0.19.0/compiler/cpp/tests/README.md0000644000000000000000000000616114370300523020115 0ustar00rootroot00000000000000# Build and run compiler tests using CMake - [Build and run compiler tests using CMake](#build-and-run-compiler-tests-using-cmake) - [General information](#general-information) - [How to add your tests](#how-to-add-your-tests) - [Build and run tests on Unix-like systems](#build-and-run-tests-on-unix-like-systems) - [Prerequisites:](#prerequisites) - [Build and run test with CMake](#build-and-run-test-with-cmake) - [Build and run tests on Windows](#build-and-run-tests-on-windows) - [Prerequisites:](#prerequisites-1) - [Generation of VS project with CMake, build and run on Windows](#generation-of-vs-project-with-cmake-build-and-run-on-windows) ## General information Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netstd** implementation) At current moment these tests use free Catch library (https://github.com/catchorg/Catch2/tree/Catch1.x) for easy test creation and usage. Decision to use it was because of simplicity, easy usage, one header file to use, stable community and growing interest (https://cpp.libhunt.com/project/googletest-google/vs/catch?rel=cmp-cmp) Also, maybe, later it will be migrated to Catch2 (https://github.com/philsquared/Catch) - depends on need to support legacy compilers (c++98) ## How to add your tests - Open **CMakeLists.txt** - Set call of `THRIFT_ADD_COMPILER` for your language to `ON` ``` cmake THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) ``` - Create folder with name specified in list of languages in **CMakeLists.txt** - Create tests in folder for your language (with extensions like *.c* - cc, cpp, etc) - Don't forget to add include of catch.hpp in your test file ``` C #include "../catch/catch.hpp" ``` - If you need - add files manually to **thrift_compiler_tests_manual_SOURCES** in **CMakeLists.txt** similar to ``` cmake # you can add some files manually there set(thrift_compiler_tests_manual_SOURCES # tests file to avoid main in every test file ${CMAKE_CURRENT_SOURCE_DIR}/tests_main.cc ) ``` - Run **cmake** with arguments for your environment and compiler - Enjoy ## Build and run tests on Unix-like systems ### Prerequisites: - Install CMake - - Install winflexbison - ### Build and run test with CMake - Run commands in command line in current directory: ``` mkdir cmake-vs && cd cmake-vs cmake .. cmake --build . ctest -C Debug -V ``` ## Build and run tests on Windows ### Prerequisites: - Install CMake - - Install winflexbison - - Install VS2017 Community Edition - (ensure that you installed workload "Desktop Development with C++" for VS2017) ### Generation of VS project with CMake, build and run on Windows - Run commands in command line in current directory (ensure that VS installed): ``` mkdir cmake-vs cd cmake-vs cmake .. cmake --build . ctest -C Debug -V ``` thrift-0.19.0/compiler/cpp/tests/tests_main.cc0000644000000000000000000000152414303740367021323 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #define CATCH_CONFIG_MAIN #include "catch/catch.hpp" thrift-0.19.0/compiler/cpp/tests/ocaml/0000755000000000000000000000000014370300523017725 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/tests/ocaml/t_ocaml_generator_tests.cc0000644000000000000000000001011114370300523025134 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #include #include #include "../catch/catch.hpp" #include using defs_t = std::list; /** This subclass is meant to allow accessing the Thrift generated OCaml outputs and keep the tests stable across Thrift versions (as much as possible), but otherwise is identical to the standard OCaml generator. */ class t_test_ocaml_generator : public t_ocaml_generator { public: t_test_ocaml_generator(t_program* program) : t_ocaml_generator(program, {}, "") {} /** Override and turn off comment generation which contains a version number to make tests version-independent. */ std::string ocaml_autogen_comment() override { return ""; } // Allow inspecting the generated code. string types() { return f_types_.str(); } string consts() { return f_consts_.str(); } string service() { return f_service_.str(); } string types_i() { return f_types_i_.str(); } string service_i() { return f_service_i_.str(); } }; /** Helper to add a list of definitions to a Thrift 'program' (i.e. representation of the IDL) and generate the OCaml outputs. */ void gen_program(t_generator& gen, t_program& program, defs_t defs) { for (auto def : defs) { if (def->is_typedef()) program.add_typedef(static_cast(def)); else if (def->is_enum()) program.add_enum(static_cast(def)); else if (def->is_struct()) program.add_struct(static_cast(def)); else if (def->is_xception()) program.add_xception(static_cast(def)); else if (def->is_service()) program.add_service(static_cast(def)); } gen.generate_program(); } TEST_CASE( "t_ocaml_generator - typedefs", "[functional]" ) { t_program program("Typedefs.thrift", "Typedefs"); t_base_type ty_string("string", t_base_type::TYPE_STRING); t_typedef tydef_decimal(&program, &ty_string, "Decimal"); t_test_ocaml_generator gen(&program); gen_program(gen, program, defs_t { &tydef_decimal }); #include "snapshot_typedefs.cc" REQUIRE( snapshot == gen.types() ); } TEST_CASE( "t_ocaml_generator - handle exception from different module", "[functional]" ) { t_program errors_thrift("Errors.thrift", "Errors"); t_struct server_error(&errors_thrift, "ServerError"); server_error.set_xception(true); t_test_ocaml_generator errors_gen(&errors_thrift); gen_program(errors_gen, errors_thrift, defs_t { &server_error }); { #include "snapshot_exception_types_i.cc" REQUIRE( snapshot == errors_gen.types_i() ); } t_program service_thrift("Service.thrift", "Service"); t_service service(&service_thrift); service.set_name("Service"); t_base_type ret_type("void", t_base_type::TYPE_VOID); t_struct args(&service_thrift, "ping_args"); t_struct throws(&service_thrift, "ping_throws"); t_field ex_server_error(&server_error, "serverError", 1); throws.append(&ex_server_error); t_function ping(&ret_type, "ping", &args, &throws); service.add_function(&ping); t_test_ocaml_generator service_gen(&service_thrift); gen_program(service_gen, service_thrift, defs_t { &service }); { #include "snapshot_service_handle_ex.cc" REQUIRE( snapshot == service_gen.service() ); } } thrift-0.19.0/compiler/cpp/tests/ocaml/snapshot_typedefs.cc0000644000000000000000000000154214370300523024000 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. const char* snapshot(R"""( open Thrift type decimal = string )"""); thrift-0.19.0/compiler/cpp/tests/ocaml/README.md0000644000000000000000000000107114370300523021203 0ustar00rootroot00000000000000## Testing approach 1. Programmatically construct parsed instances of Thrift IDLs using internal types 2. Generate the OCaml output using the OCaml generator 3. Capture the generated output in `ostringstream` 4. Query and compare the outputs in the strings to stored snapshots in the `snapshot_*.cc` files Run tests in `../tests` directory: # Only on changing build definition: cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/bison -DCMAKE_CXX_STANDARD=11 . # On each iteration: rm -rf gen-ocaml; cmake --build . && ctest --output-on-failure thrift-0.19.0/compiler/cpp/tests/ocaml/snapshot_service_handle_ex.cc0000644000000000000000000001203014370300523025616 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. const char* snapshot(R"""( open Thrift open Service_types (* HELPER FUNCTIONS AND STRUCTURES *) class ping_args = object (self) method copy = let _new = Oo.copy self in _new method write (oprot : Protocol.t) = oprot#writeStructBegin "ping_args"; oprot#writeFieldStop; oprot#writeStructEnd end let rec read_ping_args (iprot : Protocol.t) = let _str2 = new ping_args in ignore(iprot#readStructBegin); (try while true do let (_,_t3,_id4) = iprot#readFieldBegin in if _t3 = Protocol.T_STOP then raise Break else (); (match _id4 with | _ -> iprot#skip _t3); iprot#readFieldEnd; done; () with Break -> ()); iprot#readStructEnd; _str2 class ping_result = object (self) val mutable _serverError : Errors_types.serverError option = None method get_serverError = _serverError method grab_serverError = match _serverError with None->raise (Field_empty "ping_result.serverError") | Some _x5 -> _x5 method set_serverError _x5 = _serverError <- Some _x5 method unset_serverError = _serverError <- None method reset_serverError = _serverError <- None method copy = let _new = Oo.copy self in if _serverError <> None then _new#set_serverError self#grab_serverError#copy; _new method write (oprot : Protocol.t) = oprot#writeStructBegin "ping_result"; (match _serverError with None -> () | Some _v -> oprot#writeFieldBegin("serverError",Protocol.T_STRUCT,1); _v#write(oprot); oprot#writeFieldEnd ); oprot#writeFieldStop; oprot#writeStructEnd end let rec read_ping_result (iprot : Protocol.t) = let _str8 = new ping_result in ignore(iprot#readStructBegin); (try while true do let (_,_t9,_id10) = iprot#readFieldBegin in if _t9 = Protocol.T_STOP then raise Break else (); (match _id10 with | 1 -> (if _t9 = Protocol.T_STRUCT then _str8#set_serverError (Errors_types.read_serverError iprot) else iprot#skip _t9) | _ -> iprot#skip _t9); iprot#readFieldEnd; done; () with Break -> ()); iprot#readStructEnd; _str8 class virtual iface = object (self) method virtual ping : unit end class client (iprot : Protocol.t) (oprot : Protocol.t) = object (self) val mutable seqid = 0 method ping = self#send_ping; self#recv_ping method private send_ping = oprot#writeMessageBegin ("ping", Protocol.CALL, seqid); let args = new ping_args in args#write oprot; oprot#writeMessageEnd; oprot#getTransport#flush method private recv_ping = let (fname, mtype, rseqid) = iprot#readMessageBegin in (if mtype = Protocol.EXCEPTION then let x = Application_Exn.read iprot in (iprot#readMessageEnd; raise (Application_Exn.E x)) else ()); let result = read_ping_result iprot in iprot#readMessageEnd; (match result#get_serverError with None -> () | Some _v -> raise (Errors_types.ServerError _v)); () end class processor (handler : iface) = object (self) inherit Processor.t val processMap = Hashtbl.create 1 method process iprot oprot = let (name, typ, seqid) = iprot#readMessageBegin in if Hashtbl.mem processMap name then (Hashtbl.find processMap name) (seqid, iprot, oprot) else ( iprot#skip(Protocol.T_STRUCT); iprot#readMessageEnd; let x = Application_Exn.create Application_Exn.UNKNOWN_METHOD ("Unknown function "^name) in oprot#writeMessageBegin(name, Protocol.EXCEPTION, seqid); x#write oprot; oprot#writeMessageEnd; oprot#getTransport#flush ); true method private process_ping (seqid, iprot, oprot) = let _ = read_ping_args iprot in iprot#readMessageEnd; let result = new ping_result in (try (handler#ping); with | Errors_types.ServerError serverError -> result#set_serverError serverError ); oprot#writeMessageBegin ("ping", Protocol.REPLY, seqid); result#write oprot; oprot#writeMessageEnd; oprot#getTransport#flush initializer Hashtbl.add processMap "ping" self#process_ping; end )"""); thrift-0.19.0/compiler/cpp/tests/ocaml/snapshot_exception_types_i.cc0000644000000000000000000000177414370300523025716 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. const char* snapshot(R"""( open Thrift class serverError : object ('a) method copy : 'a method write : Protocol.t -> unit end exception ServerError of serverError val read_serverError : Protocol.t -> serverError )"""); thrift-0.19.0/compiler/cpp/tests/catch/0000777000000000000000000000000014303740367017732 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/tests/catch/catch.hpp0000644000000000000000000146177414303740367021545 0ustar00rootroot00000000000000/* * Catch v1.9.4 * Generated: 2017-05-16 13:51:55.506519 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #define TWOBLUECUBES_CATCH_HPP_INCLUDED #ifdef __clang__ # pragma clang system_header #elif defined __GNUC__ # pragma GCC system_header #endif // #included from: internal/catch_suppress_warnings.h #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(push) # pragma warning(disable: 161 1682) # else // __ICC # pragma clang diagnostic ignored "-Wglobal-constructors" # pragma clang diagnostic ignored "-Wvariadic-macros" # pragma clang diagnostic ignored "-Wc99-extensions" # pragma clang diagnostic ignored "-Wunused-variable" # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" # pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" # pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wparentheses" # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL #endif #ifdef CATCH_IMPL # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN # endif #endif // #included from: internal/catch_notimplemented_exception.h #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED // #included from: catch_common.h #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED // #included from: catch_compiler_capabilities.h #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED // Detect a number of compiler features - mostly C++11/14 conformance - by compiler // The following features are defined: // // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? // CATCH_CONFIG_CPP11_OVERRIDE : is override supported? // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) // CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? // CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too // **************** // In general each macro has a _NO_ form // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 #ifdef __cplusplus # if __cplusplus >= 201103L # define CATCH_CPP11_OR_GREATER # endif # if __cplusplus >= 201402L # define CATCH_CPP14_OR_GREATER # endif #endif #ifdef __clang__ # if __has_feature(cxx_nullptr) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif # if __has_feature(cxx_noexcept) # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif # if defined(CATCH_CPP11_OR_GREATER) # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ _Pragma( "clang diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic push" ) \ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "clang diagnostic pop" ) # endif #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals #if defined(__CYGWIN__) || defined(__QNX__) # if !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS # endif #endif //////////////////////////////////////////////////////////////////////////////// // Cygwin #ifdef __CYGWIN__ // Required for some versions of Cygwin to declare gettimeofday // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin # define _BSD_SOURCE #endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Borland #ifdef __BORLANDC__ #endif // __BORLANDC__ //////////////////////////////////////////////////////////////////////////////// // EDG #ifdef __EDG_VERSION__ #endif // __EDG_VERSION__ //////////////////////////////////////////////////////////////////////////////// // Digital Mars #ifdef __DMC__ #endif // __DMC__ //////////////////////////////////////////////////////////////////////////////// // GCC #ifdef __GNUC__ # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif // - otherwise more recent versions define __cplusplus >= 201103L // and will get picked up below #endif // __GNUC__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH #if (_MSC_VER >= 1600) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE #define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS #endif #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // Use variadic macros if the compiler supports them #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ ( defined __GNUC__ && __GNUC__ >= 3 ) || \ ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS #endif // Use __COUNTER__ if the compiler supports it #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ ( defined __clang__ && __clang_major__ >= 3 ) #define CATCH_INTERNAL_CONFIG_COUNTER #endif //////////////////////////////////////////////////////////////////////////////// // C++ language feature support // catch all support for C++11 #if defined(CATCH_CPP11_OR_GREATER) # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM # endif # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE # endif # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) # define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE # endif # if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) # define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS # endif #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_NULLPTR #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_NOEXCEPT #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_GENERATED_METHODS #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_IS_ENUM #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_TUPLE #endif #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) # define CATCH_CONFIG_VARIADIC_MACROS #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_LONG_LONG #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_OVERRIDE #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_UNIQUE_PTR #endif // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for // analytics) because, at time of writing, __COUNTER__ is not properly handled by it. // This does not affect compilation #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) # define CATCH_CONFIG_COUNTER #endif #if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_SHUFFLE #endif # if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_TYPE_TRAITS # endif #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) # define CATCH_CONFIG_WINDOWS_SEH #endif // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. #if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) # define CATCH_CONFIG_POSIX_SIGNALS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) # define CATCH_NOEXCEPT noexcept # define CATCH_NOEXCEPT_IS(x) noexcept(x) #else # define CATCH_NOEXCEPT throw() # define CATCH_NOEXCEPT_IS(x) #endif // nullptr support #ifdef CATCH_CONFIG_CPP11_NULLPTR # define CATCH_NULL nullptr #else # define CATCH_NULL NULL #endif // override support #ifdef CATCH_CONFIG_CPP11_OVERRIDE # define CATCH_OVERRIDE override #else # define CATCH_OVERRIDE #endif // unique_ptr support #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR # define CATCH_AUTO_PTR( T ) std::unique_ptr #else # define CATCH_AUTO_PTR( T ) std::auto_ptr #endif #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) #ifdef CATCH_CONFIG_COUNTER # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) #else # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) #endif #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) #include #include namespace Catch { struct IConfig; struct CaseSensitive { enum Choice { Yes, No }; }; class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; NonCopyable( NonCopyable && ) = delete; NonCopyable& operator = ( NonCopyable const& ) = delete; NonCopyable& operator = ( NonCopyable && ) = delete; #else NonCopyable( NonCopyable const& info ); NonCopyable& operator = ( NonCopyable const& ); #endif protected: NonCopyable() {} virtual ~NonCopyable(); }; class SafeBool { public: typedef void (SafeBool::*type)() const; static type makeSafe( bool value ) { return value ? &SafeBool::trueValue : 0; } private: void trueValue() const {} }; template inline void deleteAll( ContainerT& container ) { typename ContainerT::const_iterator it = container.begin(); typename ContainerT::const_iterator itEnd = container.end(); for(; it != itEnd; ++it ) delete *it; } template inline void deleteAllValues( AssociativeContainerT& container ) { typename AssociativeContainerT::const_iterator it = container.begin(); typename AssociativeContainerT::const_iterator itEnd = container.end(); for(; it != itEnd; ++it ) delete it->second; } bool startsWith( std::string const& s, std::string const& prefix ); bool startsWith( std::string const& s, char prefix ); bool endsWith( std::string const& s, std::string const& suffix ); bool endsWith( std::string const& s, char suffix ); bool contains( std::string const& s, std::string const& infix ); void toLowerInPlace( std::string& s ); std::string toLower( std::string const& s ); std::string trim( std::string const& str ); bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); struct pluralise { pluralise( std::size_t count, std::string const& label ); friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); std::size_t m_count; std::string m_label; }; struct SourceLineInfo { SourceLineInfo(); SourceLineInfo( char const* _file, std::size_t _line ); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SourceLineInfo(SourceLineInfo const& other) = default; SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default; # endif bool empty() const; bool operator == ( SourceLineInfo const& other ) const; bool operator < ( SourceLineInfo const& other ) const; char const* file; std::size_t line; }; std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); // This is just here to avoid compiler warnings with macro constants and boolean literals inline bool isTrue( bool value ){ return value; } inline bool alwaysTrue() { return true; } inline bool alwaysFalse() { return false; } void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); void seedRng( IConfig const& config ); unsigned int rngSeed(); // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as // >> stuff +StreamEndStop struct StreamEndStop { std::string operator+() { return std::string(); } }; template T const& operator + ( T const& value, StreamEndStop ) { return value; } } #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); namespace Catch { class NotImplementedException : public std::exception { public: NotImplementedException( SourceLineInfo const& lineInfo ); NotImplementedException( NotImplementedException const& ) {} virtual ~NotImplementedException() CATCH_NOEXCEPT {} virtual const char* what() const CATCH_NOEXCEPT; private: std::string m_what; SourceLineInfo m_lineInfo; }; } // end namespace Catch /////////////////////////////////////////////////////////////////////////////// #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) // #included from: internal/catch_context.h #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED // #included from: catch_interfaces_generators.h #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED #include namespace Catch { struct IGeneratorInfo { virtual ~IGeneratorInfo(); virtual bool moveNext() = 0; virtual std::size_t getCurrentIndex() const = 0; }; struct IGeneratorsForTest { virtual ~IGeneratorsForTest(); virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; virtual bool moveNext() = 0; }; IGeneratorsForTest* createGeneratorsForTest(); } // end namespace Catch // #included from: catch_ptr.hpp #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif namespace Catch { // An intrusive reference counting smart pointer. // T must implement addRef() and release() methods // typically implementing the IShared interface template class Ptr { public: Ptr() : m_p( CATCH_NULL ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); } Ptr( Ptr const& other ) : m_p( other.m_p ){ if( m_p ) m_p->addRef(); } ~Ptr(){ if( m_p ) m_p->release(); } void reset() { if( m_p ) m_p->release(); m_p = CATCH_NULL; } Ptr& operator = ( T* p ){ Ptr temp( p ); swap( temp ); return *this; } Ptr& operator = ( Ptr const& other ){ Ptr temp( other ); swap( temp ); return *this; } void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } bool operator !() const { return m_p == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } private: T* m_p; }; struct IShared : NonCopyable { virtual ~IShared(); virtual void addRef() const = 0; virtual void release() const = 0; }; template struct SharedImpl : T { SharedImpl() : m_rc( 0 ){} virtual void addRef() const { ++m_rc; } virtual void release() const { if( --m_rc == 0 ) delete this; } mutable unsigned int m_rc; }; } // end namespace Catch #ifdef __clang__ #pragma clang diagnostic pop #endif namespace Catch { class TestCase; class Stream; struct IResultCapture; struct IRunner; struct IGeneratorsForTest; struct IConfig; struct IContext { virtual ~IContext(); virtual IResultCapture* getResultCapture() = 0; virtual IRunner* getRunner() = 0; virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; virtual bool advanceGeneratorsForCurrentTest() = 0; virtual Ptr getConfig() const = 0; }; struct IMutableContext : IContext { virtual ~IMutableContext(); virtual void setResultCapture( IResultCapture* resultCapture ) = 0; virtual void setRunner( IRunner* runner ) = 0; virtual void setConfig( Ptr const& config ) = 0; }; IContext& getCurrentContext(); IMutableContext& getCurrentMutableContext(); void cleanUpContext(); Stream createStream( std::string const& streamName ); } // #included from: internal/catch_test_registry.hpp #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED // #included from: catch_interfaces_testcase.h #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED #include namespace Catch { class TestSpec; struct ITestCase : IShared { virtual void invoke () const = 0; protected: virtual ~ITestCase(); }; class TestCase; struct IConfig; struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector const& getAllTests() const = 0; virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); } namespace Catch { template class MethodTestCase : public SharedImpl { public: MethodTestCase( void (C::*method)() ) : m_method( method ) {} virtual void invoke() const { C obj; (obj.*m_method)(); } private: virtual ~MethodTestCase() {} void (C::*m_method)(); }; typedef void(*TestFunction)(); struct NameAndDesc { NameAndDesc( const char* _name = "", const char* _description= "" ) : name( _name ), description( _description ) {} const char* name; const char* description; }; void registerTestCase ( ITestCase* testCase, char const* className, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ); struct AutoReg { AutoReg ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ); template AutoReg ( void (C::*method)(), char const* className, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ) { registerTestCase ( new MethodTestCase( method ), className, nameAndDesc, lineInfo ); } ~AutoReg(); private: AutoReg( AutoReg const& ); void operator= ( AutoReg const& ); }; void registerTestCaseFunction ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ); } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ static void TestName(); \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestName : ClassName{ \ void test(); \ }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ static void TestName(); \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ static void TestName() #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ namespace{ \ struct TestCaseName : ClassName{ \ void test(); \ }; \ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ } \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ void TestCaseName::test() #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \ CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS #endif // #included from: internal/catch_capture.hpp #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED // #included from: catch_result_builder.h #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED // #included from: catch_result_type.h #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED namespace Catch { // ResultWas::OfType enum struct ResultWas { enum OfType { Unknown = -1, Ok = 0, Info = 1, Warning = 2, FailureBit = 0x10, ExpressionFailed = FailureBit | 1, ExplicitFailure = FailureBit | 2, Exception = 0x100 | FailureBit, ThrewException = Exception | 1, DidntThrowException = Exception | 2, FatalErrorCondition = 0x200 | FailureBit }; }; inline bool isOk( ResultWas::OfType resultType ) { return ( resultType & ResultWas::FailureBit ) == 0; } inline bool isJustInfo( int flags ) { return flags == ResultWas::Info; } // ResultDisposition::Flags enum struct ResultDisposition { enum Flags { Normal = 0x01, ContinueOnFailure = 0x02, // Failures fail test, but execution continues FalseTest = 0x04, // Prefix expression with ! SuppressFail = 0x08 // Failures are reported but do not fail the test }; }; inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { return static_cast( static_cast( lhs ) | static_cast( rhs ) ); } inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } } // end namespace Catch // #included from: catch_assertionresult.h #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED #include namespace Catch { struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; struct DecomposedExpression { virtual ~DecomposedExpression() {} virtual bool isBinaryExpression() const { return false; } virtual void reconstructExpression( std::string& dest ) const = 0; // Only simple binary comparisons can be decomposed. // If more complex check is required then wrap sub-expressions in parentheses. template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); private: DecomposedExpression& operator = (DecomposedExpression const&); }; struct AssertionInfo { AssertionInfo() {} AssertionInfo( std::string const& _macroName, SourceLineInfo const& _lineInfo, std::string const& _capturedExpression, ResultDisposition::Flags _resultDisposition ); std::string macroName; SourceLineInfo lineInfo; std::string capturedExpression; ResultDisposition::Flags resultDisposition; }; struct AssertionResultData { AssertionResultData() : decomposedExpression( CATCH_NULL ) , resultType( ResultWas::Unknown ) , negated( false ) , parenthesized( false ) {} void negate( bool parenthesize ) { negated = !negated; parenthesized = parenthesize; if( resultType == ResultWas::Ok ) resultType = ResultWas::ExpressionFailed; else if( resultType == ResultWas::ExpressionFailed ) resultType = ResultWas::Ok; } std::string const& reconstructExpression() const { if( decomposedExpression != CATCH_NULL ) { decomposedExpression->reconstructExpression( reconstructedExpression ); if( parenthesized ) { reconstructedExpression.insert( 0, 1, '(' ); reconstructedExpression.append( 1, ')' ); } if( negated ) { reconstructedExpression.insert( 0, 1, '!' ); } decomposedExpression = CATCH_NULL; } return reconstructedExpression; } mutable DecomposedExpression const* decomposedExpression; mutable std::string reconstructedExpression; std::string message; ResultWas::OfType resultType; bool negated; bool parenthesized; }; class AssertionResult { public: AssertionResult(); AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); ~AssertionResult(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionResult( AssertionResult const& ) = default; AssertionResult( AssertionResult && ) = default; AssertionResult& operator = ( AssertionResult const& ) = default; AssertionResult& operator = ( AssertionResult && ) = default; # endif bool isOk() const; bool succeeded() const; ResultWas::OfType getResultType() const; bool hasExpression() const; bool hasMessage() const; std::string getExpression() const; std::string getExpressionInMacro() const; bool hasExpandedExpression() const; std::string getExpandedExpression() const; std::string getMessage() const; SourceLineInfo getSourceInfo() const; std::string getTestMacroName() const; void discardDecomposedExpression() const; void expandDecomposedExpression() const; protected: AssertionInfo m_info; AssertionResultData m_resultData; }; } // end namespace Catch // #included from: catch_matchers.hpp #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED namespace Catch { namespace Matchers { namespace Impl { template struct MatchAllOf; template struct MatchAnyOf; template struct MatchNotOf; class MatcherUntypedBase { public: std::string toString() const { if( m_cachedToString.empty() ) m_cachedToString = describe(); return m_cachedToString; } protected: virtual ~MatcherUntypedBase(); virtual std::string describe() const = 0; mutable std::string m_cachedToString; private: MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); }; template struct MatcherMethod { virtual bool match( ObjectT const& arg ) const = 0; }; template struct MatcherMethod { virtual bool match( PtrT* arg ) const = 0; }; template struct MatcherBase : MatcherUntypedBase, MatcherMethod { MatchAllOf operator && ( MatcherBase const& other ) const; MatchAnyOf operator || ( MatcherBase const& other ) const; MatchNotOf operator ! () const; }; template struct MatchAllOf : MatcherBase { virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if (!m_matchers[i]->match(arg)) return false; } return true; } virtual std::string describe() const CATCH_OVERRIDE { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if( i != 0 ) description += " and "; description += m_matchers[i]->toString(); } description += " )"; return description; } MatchAllOf& operator && ( MatcherBase const& other ) { m_matchers.push_back( &other ); return *this; } std::vector const*> m_matchers; }; template struct MatchAnyOf : MatcherBase { virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if (m_matchers[i]->match(arg)) return true; } return false; } virtual std::string describe() const CATCH_OVERRIDE { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; for( std::size_t i = 0; i < m_matchers.size(); ++i ) { if( i != 0 ) description += " or "; description += m_matchers[i]->toString(); } description += " )"; return description; } MatchAnyOf& operator || ( MatcherBase const& other ) { m_matchers.push_back( &other ); return *this; } std::vector const*> m_matchers; }; template struct MatchNotOf : MatcherBase { MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { return !m_underlyingMatcher.match( arg ); } virtual std::string describe() const CATCH_OVERRIDE { return "not " + m_underlyingMatcher.toString(); } MatcherBase const& m_underlyingMatcher; }; template MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { return MatchAllOf() && *this && other; } template MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { return MatchAnyOf() || *this || other; } template MatchNotOf MatcherBase::operator ! () const { return MatchNotOf( *this ); } } // namespace Impl // The following functions create the actual matcher objects. // This allows the types to be inferred // - deprecated: prefer ||, && and ! template inline Impl::MatchNotOf Not( Impl::MatcherBase const& underlyingMatcher ) { return Impl::MatchNotOf( underlyingMatcher ); } template inline Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { return Impl::MatchAllOf() && m1 && m2; } template inline Impl::MatchAllOf AllOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { return Impl::MatchAllOf() && m1 && m2 && m3; } template inline Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2 ) { return Impl::MatchAnyOf() || m1 || m2; } template inline Impl::MatchAnyOf AnyOf( Impl::MatcherBase const& m1, Impl::MatcherBase const& m2, Impl::MatcherBase const& m3 ) { return Impl::MatchAnyOf() || m1 || m2 || m3; } } // namespace Matchers using namespace Matchers; using Matchers::Impl::MatcherBase; } // namespace Catch namespace Catch { struct TestFailureException{}; template class ExpressionLhs; struct CopyableStream { CopyableStream() {} CopyableStream( CopyableStream const& other ) { oss << other.oss.str(); } CopyableStream& operator=( CopyableStream const& other ) { oss.str(std::string()); oss << other.oss.str(); return *this; } std::ostringstream oss; }; class ResultBuilder : public DecomposedExpression { public: ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg = "" ); ~ResultBuilder(); template ExpressionLhs operator <= ( T const& operand ); ExpressionLhs operator <= ( bool value ); template ResultBuilder& operator << ( T const& value ) { m_stream.oss << value; return *this; } ResultBuilder& setResultType( ResultWas::OfType result ); ResultBuilder& setResultType( bool result ); void endExpression( DecomposedExpression const& expr ); virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; AssertionResult build() const; AssertionResult build( DecomposedExpression const& expr ) const; void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); void captureExpectedException( std::string const& expectedMessage ); void captureExpectedException( Matchers::Impl::MatcherBase const& matcher ); void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; bool allowThrows() const; template void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); void setExceptionGuard(); void unsetExceptionGuard(); private: AssertionInfo m_assertionInfo; AssertionResultData m_data; CopyableStream m_stream; bool m_shouldDebugBreak; bool m_shouldThrow; bool m_guardException; }; } // namespace Catch // Include after due to circular dependency: // #included from: catch_expression_lhs.hpp #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED // #included from: catch_evaluate.hpp #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4389) // '==' : signed/unsigned mismatch #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) #endif #include namespace Catch { namespace Internal { enum Operator { IsEqualTo, IsNotEqualTo, IsLessThan, IsGreaterThan, IsLessThanOrEqualTo, IsGreaterThanOrEqualTo }; template struct OperatorTraits { static const char* getName(){ return "*error*"; } }; template<> struct OperatorTraits { static const char* getName(){ return "=="; } }; template<> struct OperatorTraits { static const char* getName(){ return "!="; } }; template<> struct OperatorTraits { static const char* getName(){ return "<"; } }; template<> struct OperatorTraits { static const char* getName(){ return ">"; } }; template<> struct OperatorTraits { static const char* getName(){ return "<="; } }; template<> struct OperatorTraits{ static const char* getName(){ return ">="; } }; template inline T& opCast(T const& t) { return const_cast(t); } // nullptr_t support based on pull request #154 from Konstantin Baumann #ifdef CATCH_CONFIG_CPP11_NULLPTR inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } #endif // CATCH_CONFIG_CPP11_NULLPTR // So the compare overloads can be operator agnostic we convey the operator as a template // enum, which is used to specialise an Evaluator for doing the comparison. template class Evaluator{}; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs) { return bool( opCast( lhs ) == opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) != opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) < opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) > opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) >= opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { return bool( opCast( lhs ) <= opCast( rhs ) ); } }; template bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { return Evaluator::evaluate( lhs, rhs ); } // This level of indirection allows us to specialise for integer types // to avoid signed/ unsigned warnings // "base" overload template bool compare( T1 const& lhs, T2 const& rhs ) { return Evaluator::evaluate( lhs, rhs ); } // unsigned X to int template bool compare( unsigned int lhs, int rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); } template bool compare( unsigned long lhs, int rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); } template bool compare( unsigned char lhs, int rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); } // unsigned X to long template bool compare( unsigned int lhs, long rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); } template bool compare( unsigned long lhs, long rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); } template bool compare( unsigned char lhs, long rhs ) { return applyEvaluator( lhs, static_cast( rhs ) ); } // int to unsigned X template bool compare( int lhs, unsigned int rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( int lhs, unsigned long rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( int lhs, unsigned char rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } // long to unsigned X template bool compare( long lhs, unsigned int rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( long lhs, unsigned long rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( long lhs, unsigned char rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } // pointer to long (when comparing against NULL) template bool compare( long lhs, T* rhs ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); } template bool compare( T* lhs, long rhs ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } // pointer to int (when comparing against NULL) template bool compare( int lhs, T* rhs ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); } template bool compare( T* lhs, int rhs ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } #ifdef CATCH_CONFIG_CPP11_LONG_LONG // long long to unsigned X template bool compare( long long lhs, unsigned int rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( long long lhs, unsigned long rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( long long lhs, unsigned long long rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( long long lhs, unsigned char rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } // unsigned long long to X template bool compare( unsigned long long lhs, int rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( unsigned long long lhs, long rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( unsigned long long lhs, long long rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } template bool compare( unsigned long long lhs, char rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } // pointer to long long (when comparing against NULL) template bool compare( long long lhs, T* rhs ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); } template bool compare( T* lhs, long long rhs ) { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } #endif // CATCH_CONFIG_CPP11_LONG_LONG #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { return Evaluator::evaluate( nullptr, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { return Evaluator::evaluate( lhs, nullptr ); } #endif // CATCH_CONFIG_CPP11_NULLPTR } // end of namespace Internal } // end of namespace Catch #ifdef _MSC_VER #pragma warning(pop) #endif // #included from: catch_tostring.h #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED #include #include #include #include #include #ifdef __OBJC__ // #included from: catch_objc_arc.hpp #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED #import #ifdef __has_feature #define CATCH_ARC_ENABLED __has_feature(objc_arc) #else #define CATCH_ARC_ENABLED 0 #endif void arcSafeRelease( NSObject* obj ); id performOptionalSelector( id obj, SEL sel ); #if !CATCH_ARC_ENABLED inline void arcSafeRelease( NSObject* obj ) { [obj release]; } inline id performOptionalSelector( id obj, SEL sel ) { if( [obj respondsToSelector: sel] ) return [obj performSelector: sel]; return nil; } #define CATCH_UNSAFE_UNRETAINED #define CATCH_ARC_STRONG #else inline void arcSafeRelease( NSObject* ){} inline id performOptionalSelector( id obj, SEL sel ) { #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" #endif if( [obj respondsToSelector: sel] ) return [obj performSelector: sel]; #ifdef __clang__ #pragma clang diagnostic pop #endif return nil; } #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained #define CATCH_ARC_STRONG __strong #endif #endif #ifdef CATCH_CONFIG_CPP11_TUPLE #include #endif #ifdef CATCH_CONFIG_CPP11_IS_ENUM #include #endif namespace Catch { // Why we're here. template std::string toString( T const& value ); // Built in overloads std::string toString( std::string const& value ); std::string toString( std::wstring const& value ); std::string toString( const char* const value ); std::string toString( char* const value ); std::string toString( const wchar_t* const value ); std::string toString( wchar_t* const value ); std::string toString( int value ); std::string toString( unsigned long value ); std::string toString( unsigned int value ); std::string toString( const double value ); std::string toString( const float value ); std::string toString( bool value ); std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); #ifdef CATCH_CONFIG_CPP11_LONG_LONG std::string toString( long long value ); std::string toString( unsigned long long value ); #endif #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); #endif #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ); std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ); std::string toString( NSObject* const& nsObject ); #endif namespace Detail { extern const std::string unprintableString; #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) struct BorgType { template BorgType( T const& ); }; struct TrueType { char sizer[1]; }; struct FalseType { char sizer[2]; }; TrueType& testStreamable( std::ostream& ); FalseType testStreamable( FalseType ); FalseType operator<<( std::ostream const&, BorgType const& ); template struct IsStreamInsertable { static std::ostream &s; static T const&t; enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; }; #else template class IsStreamInsertable { template static auto test(int) -> decltype( std::declval() << std::declval(), std::true_type() ); template static auto test(...) -> std::false_type; public: static const bool value = decltype(test(0))::value; }; #endif #if defined(CATCH_CONFIG_CPP11_IS_ENUM) template::value > struct EnumStringMaker { static std::string convert( T const& ) { return unprintableString; } }; template struct EnumStringMaker { static std::string convert( T const& v ) { return ::Catch::toString( static_cast::type>(v) ); } }; #endif template struct StringMakerBase { #if defined(CATCH_CONFIG_CPP11_IS_ENUM) template static std::string convert( T const& v ) { return EnumStringMaker::convert( v ); } #else template static std::string convert( T const& ) { return unprintableString; } #endif }; template<> struct StringMakerBase { template static std::string convert( T const& _value ) { std::ostringstream oss; oss << _value; return oss.str(); } }; std::string rawMemoryToString( const void *object, std::size_t size ); template inline std::string rawMemoryToString( const T& object ) { return rawMemoryToString( &object, sizeof(object) ); } } // end namespace Detail template struct StringMaker : Detail::StringMakerBase::value> {}; template struct StringMaker { template static std::string convert( U* p ) { if( !p ) return "NULL"; else return Detail::rawMemoryToString( p ); } }; template struct StringMaker { static std::string convert( R C::* p ) { if( !p ) return "NULL"; else return Detail::rawMemoryToString( p ); } }; namespace Detail { template std::string rangeToString( InputIterator first, InputIterator last ); } //template //struct StringMaker > { // static std::string convert( std::vector const& v ) { // return Detail::rangeToString( v.begin(), v.end() ); // } //}; template std::string toString( std::vector const& v ) { return Detail::rangeToString( v.begin(), v.end() ); } #ifdef CATCH_CONFIG_CPP11_TUPLE // toString for tuples namespace TupleDetail { template< typename Tuple, std::size_t N = 0, bool = (N < std::tuple_size::value) > struct ElementPrinter { static void print( const Tuple& tuple, std::ostream& os ) { os << ( N ? ", " : " " ) << Catch::toString(std::get(tuple)); ElementPrinter::print(tuple,os); } }; template< typename Tuple, std::size_t N > struct ElementPrinter { static void print( const Tuple&, std::ostream& ) {} }; } template struct StringMaker> { static std::string convert( const std::tuple& tuple ) { std::ostringstream os; os << '{'; TupleDetail::ElementPrinter>::print( tuple, os ); os << " }"; return os.str(); } }; #endif // CATCH_CONFIG_CPP11_TUPLE namespace Detail { template std::string makeString( T const& value ) { return StringMaker::convert( value ); } } // end namespace Detail /// \brief converts any type to a string /// /// The default template forwards on to ostringstream - except when an /// ostringstream overload does not exist - in which case it attempts to detect /// that and writes {?}. /// Overload (not specialise) this template for custom typs that you don't want /// to provide an ostream overload for. template std::string toString( T const& value ) { return StringMaker::convert( value ); } namespace Detail { template std::string rangeToString( InputIterator first, InputIterator last ) { std::ostringstream oss; oss << "{ "; if( first != last ) { oss << Catch::toString( *first ); for( ++first ; first != last ; ++first ) oss << ", " << Catch::toString( *first ); } oss << " }"; return oss.str(); } } } // end namespace Catch namespace Catch { template class BinaryExpression; template class MatchExpression; // Wraps the LHS of an expression and overloads comparison operators // for also capturing those and RHS (if any) template class ExpressionLhs : public DecomposedExpression { public: ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} ExpressionLhs& operator = ( const ExpressionLhs& ); template BinaryExpression operator == ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator != ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator < ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator > ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator <= ( RhsT const& rhs ) { return captureExpression( rhs ); } template BinaryExpression operator >= ( RhsT const& rhs ) { return captureExpression( rhs ); } BinaryExpression operator == ( bool rhs ) { return captureExpression( rhs ); } BinaryExpression operator != ( bool rhs ) { return captureExpression( rhs ); } void endExpression() { m_truthy = m_lhs ? true : false; m_rb .setResultType( m_truthy ) .endExpression( *this ); } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { dest = Catch::toString( m_truthy ); } private: template BinaryExpression captureExpression( RhsT& rhs ) const { return BinaryExpression( m_rb, m_lhs, rhs ); } template BinaryExpression captureExpression( bool rhs ) const { return BinaryExpression( m_rb, m_lhs, rhs ); } private: ResultBuilder& m_rb; T m_lhs; bool m_truthy; }; template class BinaryExpression : public DecomposedExpression { public: BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} BinaryExpression& operator = ( BinaryExpression& ); void endExpression() const { m_rb .setResultType( Internal::compare( m_lhs, m_rhs ) ) .endExpression( *this ); } virtual bool isBinaryExpression() const CATCH_OVERRIDE { return true; } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { std::string lhs = Catch::toString( m_lhs ); std::string rhs = Catch::toString( m_rhs ); char delim = lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos ? ' ' : '\n'; dest.reserve( 7 + lhs.size() + rhs.size() ); // 2 for spaces around operator // 2 for operator // 2 for parentheses (conditionally added later) // 1 for negation (conditionally added later) dest = lhs; dest += delim; dest += Internal::OperatorTraits::getName(); dest += delim; dest += rhs; } private: ResultBuilder& m_rb; LhsT m_lhs; RhsT m_rhs; }; template class MatchExpression : public DecomposedExpression { public: MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} virtual bool isBinaryExpression() const CATCH_OVERRIDE { return true; } virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { std::string matcherAsString = m_matcher.toString(); dest = Catch::toString( m_arg ); dest += ' '; if( matcherAsString == Detail::unprintableString ) dest += m_matcherString; else dest += matcherAsString; } private: ArgT m_arg; MatcherT m_matcher; char const* m_matcherString; }; } // end namespace Catch namespace Catch { template inline ExpressionLhs ResultBuilder::operator <= ( T const& operand ) { return ExpressionLhs( *this, operand ); } inline ExpressionLhs ResultBuilder::operator <= ( bool value ) { return ExpressionLhs( *this, value ); } template inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ) { MatchExpression expr( arg, matcher, matcherString ); setResultType( matcher.match( arg ) ); endExpression( expr ); } } // namespace Catch // #included from: catch_message.h #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED #include namespace Catch { struct MessageInfo { MessageInfo( std::string const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type ); std::string macroName; SourceLineInfo lineInfo; ResultWas::OfType type; std::string message; unsigned int sequence; bool operator == ( MessageInfo const& other ) const { return sequence == other.sequence; } bool operator < ( MessageInfo const& other ) const { return sequence < other.sequence; } private: static unsigned int globalCount; }; struct MessageBuilder { MessageBuilder( std::string const& macroName, SourceLineInfo const& lineInfo, ResultWas::OfType type ) : m_info( macroName, lineInfo, type ) {} template MessageBuilder& operator << ( T const& value ) { m_stream << value; return *this; } MessageInfo m_info; std::ostringstream m_stream; }; class ScopedMessage { public: ScopedMessage( MessageBuilder const& builder ); ScopedMessage( ScopedMessage const& other ); ~ScopedMessage(); MessageInfo m_info; }; } // end namespace Catch // #included from: catch_interfaces_capture.h #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED #include namespace Catch { class TestCase; class AssertionResult; struct AssertionInfo; struct SectionInfo; struct SectionEndInfo; struct MessageInfo; class ScopedMessageBuilder; struct Counts; struct IResultCapture { virtual ~IResultCapture(); virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; virtual std::string getCurrentTestName() const = 0; virtual const AssertionResult* getLastResult() const = 0; virtual void exceptionEarlyReported() = 0; virtual void handleFatalErrorCondition( std::string const& message ) = 0; }; IResultCapture& getResultCapture(); } // #included from: catch_debugger.h #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED // #included from: catch_platform.h #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) # define CATCH_PLATFORM_MAC #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) # define CATCH_PLATFORM_IPHONE #elif defined(linux) || defined(__linux) || defined(__linux__) # define CATCH_PLATFORM_LINUX #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) # define CATCH_PLATFORM_WINDOWS # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) # define CATCH_DEFINES_NOMINMAX # endif # if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) # define CATCH_DEFINES_WIN32_LEAN_AND_MEAN # endif #endif #include namespace Catch{ bool isDebuggerActive(); void writeToDebugConsole( std::string const& text ); } #ifdef CATCH_PLATFORM_MAC // The following code snippet based on: // http://cocoawithlove.com/2008/03/break-into-debugger.html #if defined(__ppc64__) || defined(__ppc__) #define CATCH_TRAP() \ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ : : : "memory","r0","r3","r4" ) #else #define CATCH_TRAP() __asm__("int $3\n" : : ) #endif #elif defined(CATCH_PLATFORM_LINUX) // If we can use inline assembler, do it because this allows us to break // directly at the location of the failing check instead of breaking inside // raise() called from it, i.e. one stack frame below. #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) #define CATCH_TRAP() asm volatile ("int $3") #else // Fall back to the generic way. #include #define CATCH_TRAP() raise(SIGTRAP) #endif #elif defined(_MSC_VER) #define CATCH_TRAP() __debugbreak() #elif defined(__MINGW32__) extern "C" __declspec(dllimport) void __stdcall DebugBreak(); #define CATCH_TRAP() DebugBreak() #endif #ifdef CATCH_TRAP #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } #else #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); #endif // #included from: catch_interfaces_runner.h #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED namespace Catch { class TestCase; struct IRunner { virtual ~IRunner(); virtual bool aborting() const = 0; }; } #if defined(CATCH_CONFIG_FAST_COMPILE) /////////////////////////////////////////////////////////////////////////////// // We can speedup compilation significantly by breaking into debugger lower in // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER // macro in each assertion #define INTERNAL_CATCH_REACT( resultBuilder ) \ resultBuilder.react(); /////////////////////////////////////////////////////////////////////////////// // Another way to speed-up compilation is to omit local try-catch for REQUIRE* // macros. // This can potentially cause false negative, if the test code catches // the exception before it propagates back up to the runner. #define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ __catchResult.setExceptionGuard(); \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ ( __catchResult <= expr ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ __catchResult.unsetExceptionGuard(); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ __catchResult.setExceptionGuard(); \ __catchResult.captureMatch( arg, matcher, #matcher ); \ __catchResult.unsetExceptionGuard(); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) #else /////////////////////////////////////////////////////////////////////////////// // In the event of a failure works out if the debugger needs to be invoked // and/or an exception thrown and takes appropriate action. // This needs to be done as a macro so the debugger will stop in the user // source code rather than in Catch library code #define INTERNAL_CATCH_REACT( resultBuilder ) \ if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ resultBuilder.react(); #endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ ( __catchResult <= expr ).endExpression(); \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::isTrue( false && static_cast( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( Catch::getResultCapture().getLastResult()->succeeded() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ if( !Catch::getResultCapture().getLastResult()->succeeded() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ try { \ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ __catchResult.captureExpectedException( matcher ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ if( __catchResult.allowThrows() ) \ try { \ static_cast(expr); \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( exceptionType ) { \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ } \ catch( ... ) { \ __catchResult.useActiveException( resultDisposition ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// #ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ __catchResult.captureResult( messageType ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) #else #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ __catchResult << log + ::Catch::StreamEndStop(); \ __catchResult.captureResult( messageType ); \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) #endif /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ try { \ __catchResult.captureMatch( arg, matcher, #matcher ); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ } while( Catch::alwaysFalse() ) // #included from: internal/catch_section.h #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED // #included from: catch_section_info.h #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED // #included from: catch_totals.hpp #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED #include namespace Catch { struct Counts { Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} Counts operator - ( Counts const& other ) const { Counts diff; diff.passed = passed - other.passed; diff.failed = failed - other.failed; diff.failedButOk = failedButOk - other.failedButOk; return diff; } Counts& operator += ( Counts const& other ) { passed += other.passed; failed += other.failed; failedButOk += other.failedButOk; return *this; } std::size_t total() const { return passed + failed + failedButOk; } bool allPassed() const { return failed == 0 && failedButOk == 0; } bool allOk() const { return failed == 0; } std::size_t passed; std::size_t failed; std::size_t failedButOk; }; struct Totals { Totals operator - ( Totals const& other ) const { Totals diff; diff.assertions = assertions - other.assertions; diff.testCases = testCases - other.testCases; return diff; } Totals delta( Totals const& prevTotals ) const { Totals diff = *this - prevTotals; if( diff.assertions.failed > 0 ) ++diff.testCases.failed; else if( diff.assertions.failedButOk > 0 ) ++diff.testCases.failedButOk; else ++diff.testCases.passed; return diff; } Totals& operator += ( Totals const& other ) { assertions += other.assertions; testCases += other.testCases; return *this; } Counts assertions; Counts testCases; }; } #include namespace Catch { struct SectionInfo { SectionInfo ( SourceLineInfo const& _lineInfo, std::string const& _name, std::string const& _description = std::string() ); std::string name; std::string description; SourceLineInfo lineInfo; }; struct SectionEndInfo { SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) {} SectionInfo sectionInfo; Counts prevAssertions; double durationInSeconds; }; } // end namespace Catch // #included from: catch_timer.h #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED #ifdef _MSC_VER namespace Catch { typedef unsigned long long UInt64; } #else #include namespace Catch { typedef uint64_t UInt64; } #endif namespace Catch { class Timer { public: Timer() : m_ticks( 0 ) {} void start(); unsigned int getElapsedMicroseconds() const; unsigned int getElapsedMilliseconds() const; double getElapsedSeconds() const; private: UInt64 m_ticks; }; } // namespace Catch #include namespace Catch { class Section : NonCopyable { public: Section( SectionInfo const& info ); ~Section(); // This indicates whether the section should be executed or not operator bool() const; private: SectionInfo m_info; std::string m_name; Counts m_assertions; bool m_sectionIncluded; Timer m_timer; }; } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS #define INTERNAL_CATCH_SECTION( ... ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) #else #define INTERNAL_CATCH_SECTION( name, desc ) \ if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) #endif // #included from: internal/catch_generators.hpp #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED #include #include #include namespace Catch { template struct IGenerator { virtual ~IGenerator() {} virtual T getValue( std::size_t index ) const = 0; virtual std::size_t size () const = 0; }; template class BetweenGenerator : public IGenerator { public: BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} virtual T getValue( std::size_t index ) const { return m_from+static_cast( index ); } virtual std::size_t size() const { return static_cast( 1+m_to-m_from ); } private: T m_from; T m_to; }; template class ValuesGenerator : public IGenerator { public: ValuesGenerator(){} void add( T value ) { m_values.push_back( value ); } virtual T getValue( std::size_t index ) const { return m_values[index]; } virtual std::size_t size() const { return m_values.size(); } private: std::vector m_values; }; template class CompositeGenerator { public: CompositeGenerator() : m_totalSize( 0 ) {} // *** Move semantics, similar to auto_ptr *** CompositeGenerator( CompositeGenerator& other ) : m_fileInfo( other.m_fileInfo ), m_totalSize( 0 ) { move( other ); } CompositeGenerator& setFileInfo( const char* fileInfo ) { m_fileInfo = fileInfo; return *this; } ~CompositeGenerator() { deleteAll( m_composed ); } operator T () const { size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); typename std::vector*>::const_iterator it = m_composed.begin(); typename std::vector*>::const_iterator itEnd = m_composed.end(); for( size_t index = 0; it != itEnd; ++it ) { const IGenerator* generator = *it; if( overallIndex >= index && overallIndex < index + generator->size() ) { return generator->getValue( overallIndex-index ); } index += generator->size(); } CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so } void add( const IGenerator* generator ) { m_totalSize += generator->size(); m_composed.push_back( generator ); } CompositeGenerator& then( CompositeGenerator& other ) { move( other ); return *this; } CompositeGenerator& then( T value ) { ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( value ); add( valuesGen ); return *this; } private: void move( CompositeGenerator& other ) { m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); m_totalSize += other.m_totalSize; other.m_composed.clear(); } std::vector*> m_composed; std::string m_fileInfo; size_t m_totalSize; }; namespace Generators { template CompositeGenerator between( T from, T to ) { CompositeGenerator generators; generators.add( new BetweenGenerator( from, to ) ); return generators; } template CompositeGenerator values( T val1, T val2 ) { CompositeGenerator generators; ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( val1 ); valuesGen->add( val2 ); generators.add( valuesGen ); return generators; } template CompositeGenerator values( T val1, T val2, T val3 ){ CompositeGenerator generators; ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( val1 ); valuesGen->add( val2 ); valuesGen->add( val3 ); generators.add( valuesGen ); return generators; } template CompositeGenerator values( T val1, T val2, T val3, T val4 ) { CompositeGenerator generators; ValuesGenerator* valuesGen = new ValuesGenerator(); valuesGen->add( val1 ); valuesGen->add( val2 ); valuesGen->add( val3 ); valuesGen->add( val4 ); generators.add( valuesGen ); return generators; } } // end namespace Generators using namespace Generators; } // end namespace Catch #define INTERNAL_CATCH_LINESTR2( line ) #line #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) // #included from: internal/catch_interfaces_exception.h #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include #include // #included from: catch_interfaces_registry_hub.h #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #include namespace Catch { class TestCase; struct ITestCaseRegistry; struct IExceptionTranslatorRegistry; struct IExceptionTranslator; struct IReporterRegistry; struct IReporterFactory; struct ITagAliasRegistry; struct IRegistryHub { virtual ~IRegistryHub(); virtual IReporterRegistry const& getReporterRegistry() const = 0; virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; }; struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; }; IRegistryHub& getRegistryHub(); IMutableRegistryHub& getMutableRegistryHub(); void cleanUp(); std::string translateActiveException(); } namespace Catch { typedef std::string(*exceptionTranslateFunction)(); struct IExceptionTranslator; typedef std::vector ExceptionTranslators; struct IExceptionTranslator { virtual ~IExceptionTranslator(); virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { virtual ~IExceptionTranslatorRegistry(); virtual std::string translateActiveException() const = 0; }; class ExceptionTranslatorRegistrar { template class ExceptionTranslator : public IExceptionTranslator { public: ExceptionTranslator( std::string(*translateFunction)( T& ) ) : m_translateFunction( translateFunction ) {} virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { if( it == itEnd ) throw; else return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); } } protected: std::string(*m_translateFunction)( T& ); }; public: template ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { getMutableRegistryHub().registerTranslator ( new ExceptionTranslator( translateFunction ) ); } }; } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ static std::string translatorName( signature ); \ namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ static std::string translatorName( signature ) #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // #included from: internal/catch_approx.hpp #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED #include #include #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) #include #endif namespace Catch { namespace Detail { class Approx { public: explicit Approx ( double value ) : m_epsilon( std::numeric_limits::epsilon()*100 ), m_margin( 0.0 ), m_scale( 1.0 ), m_value( value ) {} Approx( Approx const& other ) : m_epsilon( other.m_epsilon ), m_margin( other.m_margin ), m_scale( other.m_scale ), m_value( other.m_value ) {} static Approx custom() { return Approx( 0 ); } #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) template ::value>::type> Approx operator()( T value ) { Approx approx( static_cast(value) ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); approx.scale( m_scale ); return approx; } template ::value>::type> explicit Approx( T value ): Approx(static_cast(value)) {} template ::value>::type> friend bool operator == ( const T& lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula auto lhs_v = double(lhs); bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); if (relativeOK) { return true; } return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; } template ::value>::type> friend bool operator == ( Approx const& lhs, const T& rhs ) { return operator==( rhs, lhs ); } template ::value>::type> friend bool operator != ( T lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } template ::value>::type> friend bool operator != ( Approx const& lhs, T rhs ) { return !operator==( rhs, lhs ); } template ::value>::type> friend bool operator <= ( T lhs, Approx const& rhs ) { return double(lhs) < rhs.m_value || lhs == rhs; } template ::value>::type> friend bool operator <= ( Approx const& lhs, T rhs ) { return lhs.m_value < double(rhs) || lhs == rhs; } template ::value>::type> friend bool operator >= ( T lhs, Approx const& rhs ) { return double(lhs) > rhs.m_value || lhs == rhs; } template ::value>::type> friend bool operator >= ( Approx const& lhs, T rhs ) { return lhs.m_value > double(rhs) || lhs == rhs; } template ::value>::type> Approx& epsilon( T newEpsilon ) { m_epsilon = double(newEpsilon); return *this; } template ::value>::type> Approx& margin( T newMargin ) { m_margin = double(newMargin); return *this; } template ::value>::type> Approx& scale( T newScale ) { m_scale = double(newScale); return *this; } #else Approx operator()( double value ) { Approx approx( value ); approx.epsilon( m_epsilon ); approx.margin( m_margin ); approx.scale( m_scale ); return approx; } friend bool operator == ( double lhs, Approx const& rhs ) { // Thanks to Richard Harris for his help refining this formula bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); if (relativeOK) { return true; } return std::fabs(lhs - rhs.m_value) < rhs.m_margin; } friend bool operator == ( Approx const& lhs, double rhs ) { return operator==( rhs, lhs ); } friend bool operator != ( double lhs, Approx const& rhs ) { return !operator==( lhs, rhs ); } friend bool operator != ( Approx const& lhs, double rhs ) { return !operator==( rhs, lhs ); } friend bool operator <= ( double lhs, Approx const& rhs ) { return lhs < rhs.m_value || lhs == rhs; } friend bool operator <= ( Approx const& lhs, double rhs ) { return lhs.m_value < rhs || lhs == rhs; } friend bool operator >= ( double lhs, Approx const& rhs ) { return lhs > rhs.m_value || lhs == rhs; } friend bool operator >= ( Approx const& lhs, double rhs ) { return lhs.m_value > rhs || lhs == rhs; } Approx& epsilon( double newEpsilon ) { m_epsilon = newEpsilon; return *this; } Approx& margin( double newMargin ) { m_margin = newMargin; return *this; } Approx& scale( double newScale ) { m_scale = newScale; return *this; } #endif std::string toString() const { std::ostringstream oss; oss << "Approx( " << Catch::toString( m_value ) << " )"; return oss.str(); } private: double m_epsilon; double m_margin; double m_scale; double m_value; }; } template<> inline std::string toString( Detail::Approx const& value ) { return value.toString(); } } // end namespace Catch // #included from: internal/catch_matchers_string.h #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED namespace Catch { namespace Matchers { namespace StdString { struct CasedString { CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); std::string adjustString( std::string const& str ) const; std::string caseSensitivitySuffix() const; CaseSensitive::Choice m_caseSensitivity; std::string m_str; }; struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); virtual std::string describe() const CATCH_OVERRIDE; CasedString m_comparator; std::string m_operation; }; struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); virtual bool match( std::string const& source ) const CATCH_OVERRIDE; }; } // namespace StdString // The following functions create the actual matcher objects. // This allows the types to be inferred StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); } // namespace Matchers } // namespace Catch // #included from: internal/catch_matchers_vector.h #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED namespace Catch { namespace Matchers { namespace Vector { template struct ContainsElementMatcher : MatcherBase, T> { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} bool match(std::vector const &v) const CATCH_OVERRIDE { return std::find(v.begin(), v.end(), m_comparator) != v.end(); } virtual std::string describe() const CATCH_OVERRIDE { return "Contains: " + Catch::toString( m_comparator ); } T const& m_comparator; }; template struct ContainsMatcher : MatcherBase, std::vector > { ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} bool match(std::vector const &v) const CATCH_OVERRIDE { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; for (size_t i = 0; i < m_comparator.size(); ++i) if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) return false; return true; } virtual std::string describe() const CATCH_OVERRIDE { return "Contains: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; }; template struct EqualsMatcher : MatcherBase, std::vector > { EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} bool match(std::vector const &v) const CATCH_OVERRIDE { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc // - then just call that directly if (m_comparator.size() != v.size()) return false; for (size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != v[i]) return false; return true; } virtual std::string describe() const CATCH_OVERRIDE { return "Equals: " + Catch::toString( m_comparator ); } std::vector const& m_comparator; }; } // namespace Vector // The following functions create the actual matcher objects. // This allows the types to be inferred template Vector::ContainsMatcher Contains( std::vector const& comparator ) { return Vector::ContainsMatcher( comparator ); } template Vector::ContainsElementMatcher VectorContains( T const& comparator ) { return Vector::ContainsElementMatcher( comparator ); } template Vector::EqualsMatcher Equals( std::vector const& comparator ) { return Vector::EqualsMatcher( comparator ); } } // namespace Matchers } // namespace Catch // #included from: internal/catch_interfaces_tag_alias_registry.h #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED // #included from: catch_tag_alias.h #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED #include namespace Catch { struct TagAlias { TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} std::string tag; SourceLineInfo lineInfo; }; struct RegistrarForTagAliases { RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); }; } // end namespace Catch #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } // #included from: catch_option.hpp #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED namespace Catch { // An optional type template class Option { public: Option() : nullableValue( CATCH_NULL ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) {} ~Option() { reset(); } Option& operator= ( Option const& _other ) { if( &_other != this ) { reset(); if( _other ) nullableValue = new( storage ) T( *_other ); } return *this; } Option& operator = ( T const& _value ) { reset(); nullableValue = new( storage ) T( _value ); return *this; } void reset() { if( nullableValue ) nullableValue->~T(); nullableValue = CATCH_NULL; } T& operator*() { return *nullableValue; } T const& operator*() const { return *nullableValue; } T* operator->() { return nullableValue; } const T* operator->() const { return nullableValue; } T valueOr( T const& defaultValue ) const { return nullableValue ? *nullableValue : defaultValue; } bool some() const { return nullableValue != CATCH_NULL; } bool none() const { return nullableValue == CATCH_NULL; } bool operator !() const { return nullableValue == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } private: T *nullableValue; union { char storage[sizeof(T)]; // These are here to force alignment for the storage long double dummy1; void (*dummy2)(); long double dummy3; #ifdef CATCH_CONFIG_CPP11_LONG_LONG long long dummy4; #endif }; }; } // end namespace Catch namespace Catch { struct ITagAliasRegistry { virtual ~ITagAliasRegistry(); virtual Option find( std::string const& alias ) const = 0; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; static ITagAliasRegistry const& get(); }; } // end namespace Catch // These files are included here so the single_include script doesn't put them // in the conditionally compiled sections // #included from: internal/catch_test_case_info.h #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED #include #include #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif namespace Catch { struct ITestCase; struct TestCaseInfo { enum SpecialProperties{ None = 0, IsHidden = 1 << 1, ShouldFail = 1 << 2, MayFail = 1 << 3, Throws = 1 << 4, NonPortable = 1 << 5 }; TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, std::set const& _tags, SourceLineInfo const& _lineInfo ); TestCaseInfo( TestCaseInfo const& other ); friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); bool isHidden() const; bool throws() const; bool okToFail() const; bool expectedToFail() const; std::string name; std::string className; std::string description; std::set tags; std::set lcaseTags; std::string tagsAsString; SourceLineInfo lineInfo; SpecialProperties properties; }; class TestCase : public TestCaseInfo { public: TestCase( ITestCase* testCase, TestCaseInfo const& info ); TestCase( TestCase const& other ); TestCase withName( std::string const& _newName ) const; void invoke() const; TestCaseInfo const& getTestCaseInfo() const; void swap( TestCase& other ); bool operator == ( TestCase const& other ) const; bool operator < ( TestCase const& other ) const; TestCase& operator = ( TestCase const& other ); private: Ptr test; }; TestCase makeTestCase( ITestCase* testCase, std::string const& className, std::string const& name, std::string const& description, SourceLineInfo const& lineInfo ); } #ifdef __clang__ #pragma clang diagnostic pop #endif #ifdef __OBJC__ // #included from: internal/catch_objc.hpp #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED #import #include // NB. Any general catch headers included here must be included // in catch.hpp first to make sure they are included by the single // header for non obj-usage /////////////////////////////////////////////////////////////////////////////// // This protocol is really only here for (self) documenting purposes, since // all its methods are optional. @protocol OcFixture @optional -(void) setUp; -(void) tearDown; @end namespace Catch { class OcMethod : public SharedImpl { public: OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} virtual void invoke() const { id obj = [[m_cls alloc] init]; performOptionalSelector( obj, @selector(setUp) ); performOptionalSelector( obj, m_sel ); performOptionalSelector( obj, @selector(tearDown) ); arcSafeRelease( obj ); } private: virtual ~OcMethod() {} Class m_cls; SEL m_sel; }; namespace Detail{ inline std::string getAnnotation( Class cls, std::string const& annotationName, std::string const& testCaseName ) { NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; SEL sel = NSSelectorFromString( selStr ); arcSafeRelease( selStr ); id value = performOptionalSelector( cls, sel ); if( value ) return [(NSString*)value UTF8String]; return ""; } } inline size_t registerTestMethods() { size_t noTestMethods = 0; int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); for( int c = 0; c < noClasses; c++ ) { Class cls = classes[c]; { u_int count; Method* methods = class_copyMethodList( cls, &count ); for( u_int m = 0; m < count ; m++ ) { SEL selector = method_getName(methods[m]); std::string methodName = sel_getName(selector); if( startsWith( methodName, "Catch_TestCase_" ) ) { std::string testCaseName = methodName.substr( 15 ); std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); const char* className = class_getName( cls ); getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); noTestMethods++; } } free(methods); } } return noTestMethods; } namespace Matchers { namespace Impl { namespace NSStringMatchers { struct StringHolder : MatcherBase{ StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} StringHolder() { arcSafeRelease( m_substr ); } virtual bool match( NSString* arg ) const CATCH_OVERRIDE { return false; } NSString* m_substr; }; struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const CATCH_OVERRIDE { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } virtual std::string describe() const CATCH_OVERRIDE { return "equals string: " + Catch::toString( m_substr ); } }; struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } virtual std::string describe() const CATCH_OVERRIDE { return "contains string: " + Catch::toString( m_substr ); } }; struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } virtual std::string describe() const CATCH_OVERRIDE { return "starts with: " + Catch::toString( m_substr ); } }; struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} virtual bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } virtual std::string describe() const CATCH_OVERRIDE { return "ends with: " + Catch::toString( m_substr ); } }; } // namespace NSStringMatchers } // namespace Impl inline Impl::NSStringMatchers::Equals Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } inline Impl::NSStringMatchers::Contains Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } inline Impl::NSStringMatchers::StartsWith StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } inline Impl::NSStringMatchers::EndsWith EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } } // namespace Matchers using namespace Matchers; } // namespace Catch /////////////////////////////////////////////////////////////////////////////// #define OC_TEST_CASE( name, desc )\ +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ {\ return @ name; \ }\ +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ { \ return @ desc; \ } \ -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) #endif #ifdef CATCH_IMPL // !TBD: Move the leak detector code into a separate header #ifdef CATCH_CONFIG_WINDOWS_CRTDBG #include class LeakDetector { public: LeakDetector() { int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); flag |= _CRTDBG_LEAK_CHECK_DF; flag |= _CRTDBG_ALLOC_MEM_DF; _CrtSetDbgFlag(flag); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); // Change this to leaking allocation's number to break there _CrtSetBreakAlloc(-1); } }; #else class LeakDetector {}; #endif LeakDetector leakDetector; // #included from: internal/catch_impl.hpp #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED // Collect all the implementation files together here // These are the equivalent of what would usually be cpp files #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-vtables" #endif // #included from: ../catch_session.hpp #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED // #included from: internal/catch_commandline.hpp #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED // #included from: catch_config.hpp #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED // #included from: catch_test_spec_parser.hpp #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif // #included from: catch_test_spec.hpp #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wpadded" #endif // #included from: catch_wildcard_pattern.hpp #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED #include namespace Catch { class WildcardPattern { enum WildcardPosition { NoWildcard = 0, WildcardAtStart = 1, WildcardAtEnd = 2, WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd }; public: WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_wildcard( NoWildcard ), m_pattern( adjustCase( pattern ) ) { if( startsWith( m_pattern, '*' ) ) { m_pattern = m_pattern.substr( 1 ); m_wildcard = WildcardAtStart; } if( endsWith( m_pattern, '*' ) ) { m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); } } virtual ~WildcardPattern(); virtual bool matches( std::string const& str ) const { switch( m_wildcard ) { case NoWildcard: return m_pattern == adjustCase( str ); case WildcardAtStart: return endsWith( adjustCase( str ), m_pattern ); case WildcardAtEnd: return startsWith( adjustCase( str ), m_pattern ); case WildcardAtBothEnds: return contains( adjustCase( str ), m_pattern ); } #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" #endif throw std::logic_error( "Unknown enum" ); #ifdef __clang__ #pragma clang diagnostic pop #endif } private: std::string adjustCase( std::string const& str ) const { return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } CaseSensitive::Choice m_caseSensitivity; WildcardPosition m_wildcard; std::string m_pattern; }; } #include #include namespace Catch { class TestSpec { struct Pattern : SharedImpl<> { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { public: NamePattern( std::string const& name ) : m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: WildcardPattern m_wildcardPattern; }; class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} virtual ~TagPattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); } private: std::string m_tag; }; class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} virtual ~ExcludedPattern(); virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } private: Ptr m_underlyingPattern; }; struct Filter { std::vector > m_patterns; bool matches( TestCaseInfo const& testCase ) const { // All patterns in a filter must match for the filter to be a match for( std::vector >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { if( !(*it)->matches( testCase ) ) return false; } return true; } }; public: bool hasFilters() const { return !m_filters.empty(); } bool matches( TestCaseInfo const& testCase ) const { // A TestSpec matches if any filter matches for( std::vector::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) if( it->matches( testCase ) ) return true; return false; } private: std::vector m_filters; friend class TestSpecParser; }; } #ifdef __clang__ #pragma clang diagnostic pop #endif namespace Catch { class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; Mode m_mode; bool m_exclusion; std::size_t m_start, m_pos; std::string m_arg; std::vector m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; ITagAliasRegistry const* m_tagAliases; public: TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} TestSpecParser& parse( std::string const& arg ) { m_mode = None; m_exclusion = false; m_start = std::string::npos; m_arg = m_tagAliases->expandAliases( arg ); m_escapeChars.clear(); for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) visitChar( m_arg[m_pos] ); if( m_mode == Name ) addPattern(); return *this; } TestSpec testSpec() { addFilter(); return m_testSpec; } private: void visitChar( char c ) { if( m_mode == None ) { switch( c ) { case ' ': return; case '~': m_exclusion = true; return; case '[': return startNewMode( Tag, ++m_pos ); case '"': return startNewMode( QuotedName, ++m_pos ); case '\\': return escape(); default: startNewMode( Name, m_pos ); break; } } if( m_mode == Name ) { if( c == ',' ) { addPattern(); addFilter(); } else if( c == '[' ) { if( subString() == "exclude:" ) m_exclusion = true; else addPattern(); startNewMode( Tag, ++m_pos ); } else if( c == '\\' ) escape(); } else if( m_mode == EscapedName ) m_mode = Name; else if( m_mode == QuotedName && c == '"' ) addPattern(); else if( m_mode == Tag && c == ']' ) addPattern(); } void startNewMode( Mode mode, std::size_t start ) { m_mode = mode; m_start = start; } void escape() { if( m_mode == None ) m_start = m_pos; m_mode = EscapedName; m_escapeChars.push_back( m_pos ); } std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } template void addPattern() { std::string token = subString(); for( size_t i = 0; i < m_escapeChars.size(); ++i ) token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); m_escapeChars.clear(); if( startsWith( token, "exclude:" ) ) { m_exclusion = true; token = token.substr( 8 ); } if( !token.empty() ) { Ptr pattern = new T( token ); if( m_exclusion ) pattern = new TestSpec::ExcludedPattern( pattern ); m_currentFilter.m_patterns.push_back( pattern ); } m_exclusion = false; m_mode = None; } void addFilter() { if( !m_currentFilter.m_patterns.empty() ) { m_testSpec.m_filters.push_back( m_currentFilter ); m_currentFilter = TestSpec::Filter(); } } }; inline TestSpec parseTestSpec( std::string const& arg ) { return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); } } // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop #endif // #included from: catch_interfaces_config.h #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED #include #include #include namespace Catch { struct Verbosity { enum Level { NoOutput = 0, Quiet, Normal }; }; struct WarnAbout { enum What { Nothing = 0x00, NoAssertions = 0x01 }; }; struct ShowDurations { enum OrNot { DefaultForReporter, Always, Never }; }; struct RunTests { enum InWhatOrder { InDeclarationOrder, InLexicographicalOrder, InRandomOrder }; }; struct UseColour { enum YesOrNo { Auto, Yes, No }; }; class TestSpec; struct IConfig : IShared { virtual ~IConfig(); virtual bool allowThrows() const = 0; virtual std::ostream& stream() const = 0; virtual std::string name() const = 0; virtual bool includeSuccessfulResults() const = 0; virtual bool shouldDebugBreak() const = 0; virtual bool warnAboutMissingAssertions() const = 0; virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; virtual ShowDurations::OrNot showDurations() const = 0; virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; virtual UseColour::YesOrNo useColour() const = 0; virtual std::vector const& getSectionsToRun() const = 0; }; } // #included from: catch_stream.h #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED // #included from: catch_streambuf.h #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED #include namespace Catch { class StreamBufBase : public std::streambuf { public: virtual ~StreamBufBase() CATCH_NOEXCEPT; }; } #include #include #include #include namespace Catch { std::ostream& cout(); std::ostream& cerr(); struct IStream { virtual ~IStream() CATCH_NOEXCEPT; virtual std::ostream& stream() const = 0; }; class FileStream : public IStream { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); virtual ~FileStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; class CoutStream : public IStream { mutable std::ostream m_os; public: CoutStream(); virtual ~CoutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; class DebugOutStream : public IStream { CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); virtual ~DebugOutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; } #include #include #include #include #ifndef CATCH_CONFIG_CONSOLE_WIDTH #define CATCH_CONFIG_CONSOLE_WIDTH 80 #endif namespace Catch { struct ConfigData { ConfigData() : listTests( false ), listTags( false ), listReporters( false ), listTestNamesOnly( false ), showSuccessfulTests( false ), shouldDebugBreak( false ), noThrow( false ), showHelp( false ), showInvisibles( false ), filenamesAsTags( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), warnings( WarnAbout::Nothing ), showDurations( ShowDurations::DefaultForReporter ), runOrder( RunTests::InDeclarationOrder ), useColour( UseColour::Auto ) {} bool listTests; bool listTags; bool listReporters; bool listTestNamesOnly; bool showSuccessfulTests; bool shouldDebugBreak; bool noThrow; bool showHelp; bool showInvisibles; bool filenamesAsTags; int abortAfter; unsigned int rngSeed; Verbosity::Level verbosity; WarnAbout::What warnings; ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; UseColour::YesOrNo useColour; std::string outputFilename; std::string name; std::string processName; std::vector reporterNames; std::vector testsOrTags; std::vector sectionsToRun; }; class Config : public SharedImpl { private: Config( Config const& other ); Config& operator = ( Config const& other ); virtual void dummy(); public: Config() {} Config( ConfigData const& data ) : m_data( data ), m_stream( openStream() ) { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) parser.parse( data.testsOrTags[i] ); m_testSpec = parser.testSpec(); } } virtual ~Config() {} std::string const& getFilename() const { return m_data.outputFilename ; } bool listTests() const { return m_data.listTests; } bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } bool listTags() const { return m_data.listTags; } bool listReporters() const { return m_data.listReporters; } std::string getProcessName() const { return m_data.processName; } std::vector const& getReporterNames() const { return m_data.reporterNames; } std::vector const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } bool showHelp() const { return m_data.showHelp; } // IConfig interface virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } private: IStream const* openStream() { if( m_data.outputFilename.empty() ) return new CoutStream(); else if( m_data.outputFilename[0] == '%' ) { if( m_data.outputFilename == "%debug" ) return new DebugOutStream(); else throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); } else return new FileStream( m_data.outputFilename ); } ConfigData m_data; CATCH_AUTO_PTR( IStream const ) m_stream; TestSpec m_testSpec; }; } // end namespace Catch // #included from: catch_clara.h #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED // Use Catch's value for console width (store Clara's off to the side, if present) #ifdef CLARA_CONFIG_CONSOLE_WIDTH #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH #undef CLARA_CONFIG_CONSOLE_WIDTH #endif #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH // Declare Clara inside the Catch namespace #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { // #included from: ../external/clara.h // Version 0.0.2.4 // Only use header guard if we are not using an outer namespace #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) #ifndef STITCH_CLARA_OPEN_NAMESPACE #define TWOBLUECUBES_CLARA_H_INCLUDED #define STITCH_CLARA_OPEN_NAMESPACE #define STITCH_CLARA_CLOSE_NAMESPACE #else #define STITCH_CLARA_CLOSE_NAMESPACE } #endif #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE // ----------- #included from tbc_text_format.h ----------- // Only use header guard if we are not using an outer namespace #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE #define TBC_TEXT_FORMAT_H_INCLUDED #endif #include #include #include #include #include // Use optional outer namespace #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { #endif namespace Tbc { #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; #else const unsigned int consoleWidth = 80; #endif struct TextAttributes { TextAttributes() : initialIndent( std::string::npos ), indent( 0 ), width( consoleWidth-1 ), tabChar( '\t' ) {} TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } std::size_t initialIndent; // indent of first line, or npos std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos std::size_t width; // maximum width of text, including indent. Longer text will wrap char tabChar; // If this char is seen the indent is changed to current pos }; class Text { public: Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) : attr( _attr ) { std::string wrappableChars = " [({.,/|\\-"; std::size_t indent = _attr.initialIndent != std::string::npos ? _attr.initialIndent : _attr.indent; std::string remainder = _str; while( !remainder.empty() ) { if( lines.size() >= 1000 ) { lines.push_back( "... message truncated due to excessive size" ); return; } std::size_t tabPos = std::string::npos; std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); std::size_t pos = remainder.find_first_of( '\n' ); if( pos <= width ) { width = pos; } pos = remainder.find_last_of( _attr.tabChar, width ); if( pos != std::string::npos ) { tabPos = pos; if( remainder[width] == '\n' ) width--; remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); } if( width == remainder.size() ) { spliceLine( indent, remainder, width ); } else if( remainder[width] == '\n' ) { spliceLine( indent, remainder, width ); if( width <= 1 || remainder.size() != 1 ) remainder = remainder.substr( 1 ); indent = _attr.indent; } else { pos = remainder.find_last_of( wrappableChars, width ); if( pos != std::string::npos && pos > 0 ) { spliceLine( indent, remainder, pos ); if( remainder[0] == ' ' ) remainder = remainder.substr( 1 ); } else { spliceLine( indent, remainder, width-1 ); lines.back() += "-"; } if( lines.size() == 1 ) indent = _attr.indent; if( tabPos != std::string::npos ) indent += tabPos; } } } void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); _remainder = _remainder.substr( _pos ); } typedef std::vector::const_iterator const_iterator; const_iterator begin() const { return lines.begin(); } const_iterator end() const { return lines.end(); } std::string const& last() const { return lines.back(); } std::size_t size() const { return lines.size(); } std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } std::string toString() const { std::ostringstream oss; oss << *this; return oss.str(); } inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); it != itEnd; ++it ) { if( it != _text.begin() ) _stream << "\n"; _stream << *it; } return _stream; } private: std::string str; TextAttributes attr; std::vector lines; }; } // end namespace Tbc #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE } // end outer namespace #endif #endif // TBC_TEXT_FORMAT_H_INCLUDED // ----------- end of #include from tbc_text_format.h ----------- // ........... back in clara.h #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE // ----------- #included from clara_compilers.h ----------- #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED // Detect a number of compiler features - mostly C++11/14 conformance - by compiler // The following features are defined: // // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods // CLARA_CONFIG_CPP11_OVERRIDE : is override supported? // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? // In general each macro has a _NO_ form // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they // can be combined, en-mass, with the _NO_ forms later. // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 #ifdef __clang__ #if __has_feature(cxx_nullptr) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #endif #if __has_feature(cxx_noexcept) #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #endif #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // GCC #ifdef __GNUC__ #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #endif // - otherwise more recent versions define __cplusplus >= 201103L // and will get picked up below #endif // __GNUC__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #ifdef _MSC_VER #if (_MSC_VER >= 1600) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #endif #endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // C++ language feature support // catch all support for C++11 #if defined(__cplusplus) && __cplusplus >= 201103L #define CLARA_CPP11_OR_GREATER #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR #endif #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT #endif #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS #endif #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE #endif #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_NULLPTR #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_NOEXCEPT #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_GENERATED_METHODS #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_OVERRIDE #endif #if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) #define CLARA_CONFIG_CPP11_UNIQUE_PTR #endif // noexcept support: #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) #define CLARA_NOEXCEPT noexcept # define CLARA_NOEXCEPT_IS(x) noexcept(x) #else #define CLARA_NOEXCEPT throw() # define CLARA_NOEXCEPT_IS(x) #endif // nullptr support #ifdef CLARA_CONFIG_CPP11_NULLPTR #define CLARA_NULL nullptr #else #define CLARA_NULL NULL #endif // override support #ifdef CLARA_CONFIG_CPP11_OVERRIDE #define CLARA_OVERRIDE override #else #define CLARA_OVERRIDE #endif // unique_ptr support #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR # define CLARA_AUTO_PTR( T ) std::unique_ptr #else # define CLARA_AUTO_PTR( T ) std::auto_ptr #endif #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED // ----------- end of #include from clara_compilers.h ----------- // ........... back in clara.h #include #include #include #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) #define CLARA_PLATFORM_WINDOWS #endif // Use optional outer namespace #ifdef STITCH_CLARA_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE #endif namespace Clara { struct UnpositionalTag {}; extern UnpositionalTag _; #ifdef CLARA_CONFIG_MAIN UnpositionalTag _; #endif namespace Detail { #ifdef CLARA_CONSOLE_WIDTH const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; #else const unsigned int consoleWidth = 80; #endif using namespace Tbc; inline bool startsWith( std::string const& str, std::string const& prefix ) { return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; } template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct RemoveConstRef{ typedef T type; }; template struct IsBool { static const bool value = false; }; template<> struct IsBool { static const bool value = true; }; template void convertInto( std::string const& _source, T& _dest ) { std::stringstream ss; ss << _source; ss >> _dest; if( ss.fail() ) throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); } inline void convertInto( std::string const& _source, std::string& _dest ) { _dest = _source; } char toLowerCh(char c) { return static_cast( std::tolower( c ) ); } inline void convertInto( std::string const& _source, bool& _dest ) { std::string sourceLC = _source; std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) _dest = true; else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) _dest = false; else throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); } template struct IArgFunction { virtual ~IArgFunction() {} #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS IArgFunction() = default; IArgFunction( IArgFunction const& ) = default; #endif virtual void set( ConfigT& config, std::string const& value ) const = 0; virtual bool takesArg() const = 0; virtual IArgFunction* clone() const = 0; }; template class BoundArgFunction { public: BoundArgFunction() : functionObj( CLARA_NULL ) {} BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} BoundArgFunction& operator = ( BoundArgFunction const& other ) { IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; delete functionObj; functionObj = newFunctionObj; return *this; } ~BoundArgFunction() { delete functionObj; } void set( ConfigT& config, std::string const& value ) const { functionObj->set( config, value ); } bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { return functionObj != CLARA_NULL; } private: IArgFunction* functionObj; }; template struct NullBinder : IArgFunction{ virtual void set( C&, std::string const& ) const {} virtual bool takesArg() const { return true; } virtual IArgFunction* clone() const { return new NullBinder( *this ); } }; template struct BoundDataMember : IArgFunction{ BoundDataMember( M C::* _member ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { convertInto( stringValue, p.*member ); } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } M C::* member; }; template struct BoundUnaryMethod : IArgFunction{ BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { typename RemoveConstRef::type value; convertInto( stringValue, value ); (p.*member)( value ); } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } void (C::*member)( M ); }; template struct BoundNullaryMethod : IArgFunction{ BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} virtual void set( C& p, std::string const& stringValue ) const { bool value; convertInto( stringValue, value ); if( value ) (p.*member)(); } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } void (C::*member)(); }; template struct BoundUnaryFunction : IArgFunction{ BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} virtual void set( C& obj, std::string const& stringValue ) const { bool value; convertInto( stringValue, value ); if( value ) function( obj ); } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } void (*function)( C& ); }; template struct BoundBinaryFunction : IArgFunction{ BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} virtual void set( C& obj, std::string const& stringValue ) const { typename RemoveConstRef::type value; convertInto( stringValue, value ); function( obj, value ); } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } void (*function)( C&, T ); }; } // namespace Detail inline std::vector argsToVector( int argc, char const* const* const argv ) { std::vector args( static_cast( argc ) ); for( std::size_t i = 0; i < static_cast( argc ); ++i ) args[i] = argv[i]; return args; } class Parser { enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; Mode mode; std::size_t from; bool inQuotes; public: struct Token { enum Type { Positional, ShortOpt, LongOpt }; Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} Type type; std::string data; }; Parser() : mode( None ), from( 0 ), inQuotes( false ){} void parseIntoTokens( std::vector const& args, std::vector& tokens ) { const std::string doubleDash = "--"; for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) parseIntoTokens( args[i], tokens); } void parseIntoTokens( std::string const& arg, std::vector& tokens ) { for( std::size_t i = 0; i < arg.size(); ++i ) { char c = arg[i]; if( c == '"' ) inQuotes = !inQuotes; mode = handleMode( i, c, arg, tokens ); } mode = handleMode( arg.size(), '\0', arg, tokens ); } Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { switch( mode ) { case None: return handleNone( i, c ); case MaybeShortOpt: return handleMaybeShortOpt( i, c ); case ShortOpt: case LongOpt: case SlashOpt: return handleOpt( i, c, arg, tokens ); case Positional: return handlePositional( i, c, arg, tokens ); default: throw std::logic_error( "Unknown mode" ); } } Mode handleNone( std::size_t i, char c ) { if( inQuotes ) { from = i; return Positional; } switch( c ) { case '-': return MaybeShortOpt; #ifdef CLARA_PLATFORM_WINDOWS case '/': from = i+1; return SlashOpt; #endif default: from = i; return Positional; } } Mode handleMaybeShortOpt( std::size_t i, char c ) { switch( c ) { case '-': from = i+1; return LongOpt; default: from = i; return ShortOpt; } } Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) return mode; std::string optName = arg.substr( from, i-from ); if( mode == ShortOpt ) for( std::size_t j = 0; j < optName.size(); ++j ) tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); else if( mode == SlashOpt && optName.size() == 1 ) tokens.push_back( Token( Token::ShortOpt, optName ) ); else tokens.push_back( Token( Token::LongOpt, optName ) ); return None; } Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) return mode; std::string data = arg.substr( from, i-from ); tokens.push_back( Token( Token::Positional, data ) ); return None; } }; template struct CommonArgProperties { CommonArgProperties() {} CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} Detail::BoundArgFunction boundField; std::string description; std::string detail; std::string placeholder; // Only value if boundField takes an arg bool takesArg() const { return !placeholder.empty(); } void validate() const { if( !boundField.isSet() ) throw std::logic_error( "option not bound" ); } }; struct OptionArgProperties { std::vector shortNames; std::string longName; bool hasShortName( std::string const& shortName ) const { return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); } bool hasLongName( std::string const& _longName ) const { return _longName == longName; } }; struct PositionalArgProperties { PositionalArgProperties() : position( -1 ) {} int position; // -1 means non-positional (floating) bool isFixedPositional() const { return position != -1; } }; template class CommandLine { struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { Arg() {} Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} using CommonArgProperties::placeholder; // !TBD std::string dbgName() const { if( !longName.empty() ) return "--" + longName; if( !shortNames.empty() ) return "-" + shortNames[0]; return "positional args"; } std::string commands() const { std::ostringstream oss; bool first = true; std::vector::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); for(; it != itEnd; ++it ) { if( first ) first = false; else oss << ", "; oss << "-" << *it; } if( !longName.empty() ) { if( !first ) oss << ", "; oss << "--" << longName; } if( !placeholder.empty() ) oss << " <" << placeholder << ">"; return oss.str(); } }; typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; friend void addOptName( Arg& arg, std::string const& optName ) { if( optName.empty() ) return; if( Detail::startsWith( optName, "--" ) ) { if( !arg.longName.empty() ) throw std::logic_error( "Only one long opt may be specified. '" + arg.longName + "' already specified, now attempting to add '" + optName + "'" ); arg.longName = optName.substr( 2 ); } else if( Detail::startsWith( optName, "-" ) ) arg.shortNames.push_back( optName.substr( 1 ) ); else throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); } friend void setPositionalArg( Arg& arg, int position ) { arg.position = position; } class ArgBuilder { public: ArgBuilder( Arg* arg ) : m_arg( arg ) {} // Bind a non-boolean data member (requires placeholder string) template void bind( M C::* field, std::string const& placeholder ) { m_arg->boundField = new Detail::BoundDataMember( field ); m_arg->placeholder = placeholder; } // Bind a boolean data member (no placeholder required) template void bind( bool C::* field ) { m_arg->boundField = new Detail::BoundDataMember( field ); } // Bind a method taking a single, non-boolean argument (requires a placeholder string) template void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); m_arg->placeholder = placeholder; } // Bind a method taking a single, boolean argument (no placeholder string required) template void bind( void (C::* unaryMethod)( bool ) ) { m_arg->boundField = new Detail::BoundUnaryMethod( unaryMethod ); } // Bind a method that takes no arguments (will be called if opt is present) template void bind( void (C::* nullaryMethod)() ) { m_arg->boundField = new Detail::BoundNullaryMethod( nullaryMethod ); } // Bind a free function taking a single argument - the object to operate on (no placeholder string required) template void bind( void (* unaryFunction)( C& ) ) { m_arg->boundField = new Detail::BoundUnaryFunction( unaryFunction ); } // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) template void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { m_arg->boundField = new Detail::BoundBinaryFunction( binaryFunction ); m_arg->placeholder = placeholder; } ArgBuilder& describe( std::string const& description ) { m_arg->description = description; return *this; } ArgBuilder& detail( std::string const& detail ) { m_arg->detail = detail; return *this; } protected: Arg* m_arg; }; class OptBuilder : public ArgBuilder { public: OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder& operator[]( std::string const& optName ) { addOptName( *ArgBuilder::m_arg, optName ); return *this; } }; public: CommandLine() : m_boundProcessName( new Detail::NullBinder() ), m_highestSpecifiedArgPosition( 0 ), m_throwOnUnrecognisedTokens( false ) {} CommandLine( CommandLine const& other ) : m_boundProcessName( other.m_boundProcessName ), m_options ( other.m_options ), m_positionalArgs( other.m_positionalArgs ), m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) { if( other.m_floatingArg.get() ) m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); } CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { m_throwOnUnrecognisedTokens = shouldThrow; return *this; } OptBuilder operator[]( std::string const& optName ) { m_options.push_back( Arg() ); addOptName( m_options.back(), optName ); OptBuilder builder( &m_options.back() ); return builder; } ArgBuilder operator[]( int position ) { m_positionalArgs.insert( std::make_pair( position, Arg() ) ); if( position > m_highestSpecifiedArgPosition ) m_highestSpecifiedArgPosition = position; setPositionalArg( m_positionalArgs[position], position ); ArgBuilder builder( &m_positionalArgs[position] ); return builder; } // Invoke this with the _ instance ArgBuilder operator[]( UnpositionalTag ) { if( m_floatingArg.get() ) throw std::logic_error( "Only one unpositional argument can be added" ); m_floatingArg.reset( new Arg() ); ArgBuilder builder( m_floatingArg.get() ); return builder; } template void bindProcessName( M C::* field ) { m_boundProcessName = new Detail::BoundDataMember( field ); } template void bindProcessName( void (C::*_unaryMethod)( M ) ) { m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); } void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { typename std::vector::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; std::size_t maxWidth = 0; for( it = itBegin; it != itEnd; ++it ) maxWidth = (std::max)( maxWidth, it->commands().size() ); for( it = itBegin; it != itEnd; ++it ) { Detail::Text usage( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); Detail::Text desc( it->description, Detail::TextAttributes() .setWidth( width - maxWidth - 3 ) ); for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { std::string usageCol = i < usage.size() ? usage[i] : ""; os << usageCol; if( i < desc.size() && !desc[i].empty() ) os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) << desc[i]; os << "\n"; } } } std::string optUsage() const { std::ostringstream oss; optUsage( oss ); return oss.str(); } void argSynopsis( std::ostream& os ) const { for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { if( i > 1 ) os << " "; typename std::map::const_iterator it = m_positionalArgs.find( i ); if( it != m_positionalArgs.end() ) os << "<" << it->second.placeholder << ">"; else if( m_floatingArg.get() ) os << "<" << m_floatingArg->placeholder << ">"; else throw std::logic_error( "non consecutive positional arguments with no floating args" ); } // !TBD No indication of mandatory args if( m_floatingArg.get() ) { if( m_highestSpecifiedArgPosition > 1 ) os << " "; os << "[<" << m_floatingArg->placeholder << "> ...]"; } } std::string argSynopsis() const { std::ostringstream oss; argSynopsis( oss ); return oss.str(); } void usage( std::ostream& os, std::string const& procName ) const { validate(); os << "usage:\n " << procName << " "; argSynopsis( os ); if( !m_options.empty() ) { os << " [options]\n\nwhere options are: \n"; optUsage( os, 2 ); } os << "\n"; } std::string usage( std::string const& procName ) const { std::ostringstream oss; usage( oss, procName ); return oss.str(); } ConfigT parse( std::vector const& args ) const { ConfigT config; parseInto( args, config ); return config; } std::vector parseInto( std::vector const& args, ConfigT& config ) const { std::string processName = args.empty() ? std::string() : args[0]; std::size_t lastSlash = processName.find_last_of( "/\\" ); if( lastSlash != std::string::npos ) processName = processName.substr( lastSlash+1 ); m_boundProcessName.set( config, processName ); std::vector tokens; Parser parser; parser.parseIntoTokens( args, tokens ); return populate( tokens, config ); } std::vector populate( std::vector const& tokens, ConfigT& config ) const { validate(); std::vector unusedTokens = populateOptions( tokens, config ); unusedTokens = populateFixedArgs( unusedTokens, config ); unusedTokens = populateFloatingArgs( unusedTokens, config ); return unusedTokens; } std::vector populateOptions( std::vector const& tokens, ConfigT& config ) const { std::vector unusedTokens; std::vector errors; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); for(; it != itEnd; ++it ) { Arg const& arg = *it; try { if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { if( arg.takesArg() ) { if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) errors.push_back( "Expected argument to option: " + token.data ); else arg.boundField.set( config, tokens[++i].data ); } else { arg.boundField.set( config, "true" ); } break; } } catch( std::exception& ex ) { errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); } } if( it == itEnd ) { if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) unusedTokens.push_back( token ); else if( errors.empty() && m_throwOnUnrecognisedTokens ) errors.push_back( "unrecognised option: " + token.data ); } } if( !errors.empty() ) { std::ostringstream oss; for( std::vector::const_iterator it = errors.begin(), itEnd = errors.end(); it != itEnd; ++it ) { if( it != errors.begin() ) oss << "\n"; oss << *it; } throw std::runtime_error( oss.str() ); } return unusedTokens; } std::vector populateFixedArgs( std::vector const& tokens, ConfigT& config ) const { std::vector unusedTokens; int position = 1; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; typename std::map::const_iterator it = m_positionalArgs.find( position ); if( it != m_positionalArgs.end() ) it->second.boundField.set( config, token.data ); else unusedTokens.push_back( token ); if( token.type == Parser::Token::Positional ) position++; } return unusedTokens; } std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { if( !m_floatingArg.get() ) return tokens; std::vector unusedTokens; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; if( token.type == Parser::Token::Positional ) m_floatingArg->boundField.set( config, token.data ); else unusedTokens.push_back( token ); } return unusedTokens; } void validate() const { if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) throw std::logic_error( "No options or arguments specified" ); for( typename std::vector::const_iterator it = m_options.begin(), itEnd = m_options.end(); it != itEnd; ++it ) it->validate(); } private: Detail::BoundArgFunction m_boundProcessName; std::vector m_options; std::map m_positionalArgs; ArgAutoPtr m_floatingArg; int m_highestSpecifiedArgPosition; bool m_throwOnUnrecognisedTokens; }; } // end namespace Clara STITCH_CLARA_CLOSE_NAMESPACE #undef STITCH_CLARA_OPEN_NAMESPACE #undef STITCH_CLARA_CLOSE_NAMESPACE #endif // TWOBLUECUBES_CLARA_H_INCLUDED #undef STITCH_CLARA_OPEN_NAMESPACE // Restore Clara's value for console width, if present #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #endif #include #include namespace Catch { inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } inline void abortAfterX( ConfigData& config, int x ) { if( x < 1 ) throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); config.abortAfter = x; } inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } inline void addWarning( ConfigData& config, std::string const& _warning ) { if( _warning == "NoAssertions" ) config.warnings = static_cast( config.warnings | WarnAbout::NoAssertions ); else throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); } inline void setOrder( ConfigData& config, std::string const& order ) { if( startsWith( "declared", order ) ) config.runOrder = RunTests::InDeclarationOrder; else if( startsWith( "lexical", order ) ) config.runOrder = RunTests::InLexicographicalOrder; else if( startsWith( "random", order ) ) config.runOrder = RunTests::InRandomOrder; else throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); } inline void setRngSeed( ConfigData& config, std::string const& seed ) { if( seed == "time" ) { config.rngSeed = static_cast( std::time(0) ); } else { std::stringstream ss; ss << seed; ss >> config.rngSeed; if( ss.fail() ) throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); } } inline void setVerbosity( ConfigData& config, int level ) { // !TBD: accept strings? config.verbosity = static_cast( level ); } inline void setShowDurations( ConfigData& config, bool _showDurations ) { config.showDurations = _showDurations ? ShowDurations::Always : ShowDurations::Never; } inline void setUseColour( ConfigData& config, std::string const& value ) { std::string mode = toLower( value ); if( mode == "yes" ) config.useColour = UseColour::Yes; else if( mode == "no" ) config.useColour = UseColour::No; else if( mode == "auto" ) config.useColour = UseColour::Auto; else throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); } inline void forceColour( ConfigData& config ) { config.useColour = UseColour::Yes; } inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { std::ifstream f( _filename.c_str() ); if( !f.is_open() ) throw std::domain_error( "Unable to load input file: " + _filename ); std::string line; while( std::getline( f, line ) ) { line = trim(line); if( !line.empty() && !startsWith( line, '#' ) ) { if( !startsWith( line, '"' ) ) line = '"' + line + '"'; addTestOrTags( config, line + ',' ); } } } inline Clara::CommandLine makeCommandLineParser() { using namespace Clara; CommandLine cli; cli.bindProcessName( &ConfigData::processName ); cli["-?"]["-h"]["--help"] .describe( "display usage information" ) .bind( &ConfigData::showHelp ); cli["-l"]["--list-tests"] .describe( "list all/matching test cases" ) .bind( &ConfigData::listTests ); cli["-t"]["--list-tags"] .describe( "list all/matching tags" ) .bind( &ConfigData::listTags ); cli["-s"]["--success"] .describe( "include successful tests in output" ) .bind( &ConfigData::showSuccessfulTests ); cli["-b"]["--break"] .describe( "break into debugger on failure" ) .bind( &ConfigData::shouldDebugBreak ); cli["-e"]["--nothrow"] .describe( "skip exception tests" ) .bind( &ConfigData::noThrow ); cli["-i"]["--invisibles"] .describe( "show invisibles (tabs, newlines)" ) .bind( &ConfigData::showInvisibles ); cli["-o"]["--out"] .describe( "output filename" ) .bind( &ConfigData::outputFilename, "filename" ); cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) .describe( "reporter to use (defaults to console)" ) .bind( &addReporterName, "name" ); cli["-n"]["--name"] .describe( "suite name" ) .bind( &ConfigData::name, "name" ); cli["-a"]["--abort"] .describe( "abort at first failure" ) .bind( &abortAfterFirst ); cli["-x"]["--abortx"] .describe( "abort after x failures" ) .bind( &abortAfterX, "no. failures" ); cli["-w"]["--warn"] .describe( "enable warnings" ) .bind( &addWarning, "warning name" ); // - needs updating if reinstated // cli.into( &setVerbosity ) // .describe( "level of verbosity (0=no output)" ) // .shortOpt( "v") // .longOpt( "verbosity" ) // .placeholder( "level" ); cli[_] .describe( "which test or tests to use" ) .bind( &addTestOrTags, "test name, pattern or tags" ); cli["-d"]["--durations"] .describe( "show test durations" ) .bind( &setShowDurations, "yes|no" ); cli["-f"]["--input-file"] .describe( "load test names to run from a file" ) .bind( &loadTestNamesFromFile, "filename" ); cli["-#"]["--filenames-as-tags"] .describe( "adds a tag for the filename" ) .bind( &ConfigData::filenamesAsTags ); cli["-c"]["--section"] .describe( "specify section to run" ) .bind( &addSectionToRun, "section name" ); // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) .bind( &ConfigData::listTestNamesOnly ); cli["--list-reporters"] .describe( "list all reporters" ) .bind( &ConfigData::listReporters ); cli["--order"] .describe( "test case order (defaults to decl)" ) .bind( &setOrder, "decl|lex|rand" ); cli["--rng-seed"] .describe( "set a specific seed for random numbers" ) .bind( &setRngSeed, "'time'|number" ); cli["--force-colour"] .describe( "force colourised output (deprecated)" ) .bind( &forceColour ); cli["--use-colour"] .describe( "should output be colourised" ) .bind( &setUseColour, "yes|no" ); return cli; } } // end namespace Catch // #included from: internal/catch_list.hpp #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED // #included from: catch_text.h #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch // #included from: ../external/tbc_text_format.h // Only use header guard if we are not using an outer namespace #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED # endif # else # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED # endif #endif #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED #include #include #include // Use optional outer namespace #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { #endif namespace Tbc { #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; #else const unsigned int consoleWidth = 80; #endif struct TextAttributes { TextAttributes() : initialIndent( std::string::npos ), indent( 0 ), width( consoleWidth-1 ) {} TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } std::size_t initialIndent; // indent of first line, or npos std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos std::size_t width; // maximum width of text, including indent. Longer text will wrap }; class Text { public: Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) : attr( _attr ) { const std::string wrappableBeforeChars = "[({<\t"; const std::string wrappableAfterChars = "])}>-,./|\\"; const std::string wrappableInsteadOfChars = " \n\r"; std::string indent = _attr.initialIndent != std::string::npos ? std::string( _attr.initialIndent, ' ' ) : std::string( _attr.indent, ' ' ); typedef std::string::const_iterator iterator; iterator it = _str.begin(); const iterator strEnd = _str.end(); while( it != strEnd ) { if( lines.size() >= 1000 ) { lines.push_back( "... message truncated due to excessive size" ); return; } std::string suffix; std::size_t width = (std::min)( static_cast( strEnd-it ), _attr.width-static_cast( indent.size() ) ); iterator itEnd = it+width; iterator itNext = _str.end(); iterator itNewLine = std::find( it, itEnd, '\n' ); if( itNewLine != itEnd ) itEnd = itNewLine; if( itEnd != strEnd ) { bool foundWrapPoint = false; iterator findIt = itEnd; do { if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { itEnd = findIt+1; itNext = findIt+1; foundWrapPoint = true; } else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { itEnd = findIt; itNext = findIt; foundWrapPoint = true; } else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { itNext = findIt+1; itEnd = findIt; foundWrapPoint = true; } if( findIt == it ) break; else --findIt; } while( !foundWrapPoint ); if( !foundWrapPoint ) { // No good wrap char, so we'll break mid word and add a hyphen --itEnd; itNext = itEnd; suffix = "-"; } else { while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) --itEnd; } } lines.push_back( indent + std::string( it, itEnd ) + suffix ); if( indent.size() != _attr.indent ) indent = std::string( _attr.indent, ' ' ); it = itNext; } } typedef std::vector::const_iterator const_iterator; const_iterator begin() const { return lines.begin(); } const_iterator end() const { return lines.end(); } std::string const& last() const { return lines.back(); } std::size_t size() const { return lines.size(); } std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } std::string toString() const { std::ostringstream oss; oss << *this; return oss.str(); } inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); it != itEnd; ++it ) { if( it != _text.begin() ) _stream << "\n"; _stream << *it; } return _stream; } private: std::string str; TextAttributes attr; std::vector lines; }; } // end namespace Tbc #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE } // end outer namespace #endif #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace Catch { using Tbc::Text; using Tbc::TextAttributes; } // #included from: catch_console_colour.hpp #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED namespace Catch { struct Colour { enum Code { None = 0, White, Red, Green, Blue, Cyan, Yellow, Grey, Bright = 0x10, BrightRed = Bright | Red, BrightGreen = Bright | Green, LightGrey = Bright | Grey, BrightWhite = Bright | White, // By intention FileName = LightGrey, Warning = Yellow, ResultError = BrightRed, ResultSuccess = BrightGreen, ResultExpectedFailure = Warning, Error = BrightRed, Success = Green, OriginalExpression = Cyan, ReconstructedExpression = Yellow, SecondaryText = LightGrey, Headers = White }; // Use constructed object for RAII guard Colour( Code _colourCode ); Colour( Colour const& other ); ~Colour(); // Use static method for one-shot changes static void use( Code _colourCode ); private: bool m_moved; }; inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } } // end namespace Catch // #included from: catch_interfaces_reporter.h #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED #include #include #include namespace Catch { struct ReporterConfig { explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } Ptr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; Ptr m_fullConfig; }; struct ReporterPreferences { ReporterPreferences() : shouldRedirectStdOut( false ) {} bool shouldRedirectStdOut; }; template struct LazyStat : Option { LazyStat() : used( false ) {} LazyStat& operator=( T const& _value ) { Option::operator=( _value ); used = false; return *this; } void reset() { Option::reset(); used = false; } bool used; }; struct TestRunInfo { TestRunInfo( std::string const& _name ) : name( _name ) {} std::string name; }; struct GroupInfo { GroupInfo( std::string const& _name, std::size_t _groupIndex, std::size_t _groupsCount ) : name( _name ), groupIndex( _groupIndex ), groupsCounts( _groupsCount ) {} std::string name; std::size_t groupIndex; std::size_t groupsCounts; }; struct AssertionStats { AssertionStats( AssertionResult const& _assertionResult, std::vector const& _infoMessages, Totals const& _totals ) : assertionResult( _assertionResult ), infoMessages( _infoMessages ), totals( _totals ) { if( assertionResult.hasMessage() ) { // Copy message into messages list. // !TBD This should have been done earlier, somewhere MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); builder << assertionResult.getMessage(); builder.m_info.message = builder.m_stream.str(); infoMessages.push_back( builder.m_info ); } } virtual ~AssertionStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats && ) = default; # endif AssertionResult assertionResult; std::vector infoMessages; Totals totals; }; struct SectionStats { SectionStats( SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds, bool _missingAssertions ) : sectionInfo( _sectionInfo ), assertions( _assertions ), durationInSeconds( _durationInSeconds ), missingAssertions( _missingAssertions ) {} virtual ~SectionStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS SectionStats( SectionStats const& ) = default; SectionStats( SectionStats && ) = default; SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats && ) = default; # endif SectionInfo sectionInfo; Counts assertions; double durationInSeconds; bool missingAssertions; }; struct TestCaseStats { TestCaseStats( TestCaseInfo const& _testInfo, Totals const& _totals, std::string const& _stdOut, std::string const& _stdErr, bool _aborting ) : testInfo( _testInfo ), totals( _totals ), stdOut( _stdOut ), stdErr( _stdErr ), aborting( _aborting ) {} virtual ~TestCaseStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats && ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats && ) = default; # endif TestCaseInfo testInfo; Totals totals; std::string stdOut; std::string stdErr; bool aborting; }; struct TestGroupStats { TestGroupStats( GroupInfo const& _groupInfo, Totals const& _totals, bool _aborting ) : groupInfo( _groupInfo ), totals( _totals ), aborting( _aborting ) {} TestGroupStats( GroupInfo const& _groupInfo ) : groupInfo( _groupInfo ), aborting( false ) {} virtual ~TestGroupStats(); # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats && ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats && ) = default; # endif GroupInfo groupInfo; Totals totals; bool aborting; }; struct TestRunStats { TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting ) : runInfo( _runInfo ), totals( _totals ), aborting( _aborting ) {} virtual ~TestRunStats(); # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS TestRunStats( TestRunStats const& _other ) : runInfo( _other.runInfo ), totals( _other.totals ), aborting( _other.aborting ) {} # else TestRunStats( TestRunStats const& ) = default; TestRunStats( TestRunStats && ) = default; TestRunStats& operator = ( TestRunStats const& ) = default; TestRunStats& operator = ( TestRunStats && ) = default; # endif TestRunInfo runInfo; Totals totals; bool aborting; }; class MultipleReporters; struct IStreamingReporter : IShared { virtual ~IStreamingReporter(); // Implementing class must also provide the following static method: // static std::string getDescription(); virtual ReporterPreferences getPreferences() const = 0; virtual void noMatchingTestCases( std::string const& spec ) = 0; virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0; virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } }; struct IReporterFactory : IShared { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; struct IReporterRegistry { typedef std::map > FactoryMap; typedef std::vector > Listeners; virtual ~IReporterRegistry(); virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); } #include #include namespace Catch { inline std::size_t listTests( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) Catch::cout() << "Matching test cases:\n"; else { Catch::cout() << "All available test cases:\n"; testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } std::size_t matchedTests = 0; TextAttributes nameAttr, tagsAttr; nameAttr.setInitialIndent( 2 ).setIndent( 4 ); tagsAttr.setIndent( 6 ); std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { matchedTests++; TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); Colour::Code colour = testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None; Colour colourGuard( colour ); Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; if( !testCaseInfo.tags.empty() ) Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; } if( !config.testSpec().hasFilters() ) Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; else Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; return matchedTests; } inline std::size_t listTestsNamesOnly( Config const& config ) { TestSpec testSpec = config.testSpec(); if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { matchedTests++; TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); if( startsWith( testCaseInfo.name, '#' ) ) Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl; else Catch::cout() << testCaseInfo.name << std::endl; } return matchedTests; } struct TagInfo { TagInfo() : count ( 0 ) {} void add( std::string const& spelling ) { ++count; spellings.insert( spelling ); } std::string all() const { std::string out; for( std::set::const_iterator it = spellings.begin(), itEnd = spellings.end(); it != itEnd; ++it ) out += "[" + *it + "]"; return out; } std::set spellings; std::size_t count; }; inline std::size_t listTags( Config const& config ) { TestSpec testSpec = config.testSpec(); if( config.testSpec().hasFilters() ) Catch::cout() << "Tags for matching test cases:\n"; else { Catch::cout() << "All available tags:\n"; testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); } std::map tagCounts; std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { for( std::set::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), tagItEnd = it->getTestCaseInfo().tags.end(); tagIt != tagItEnd; ++tagIt ) { std::string tagName = *tagIt; std::string lcaseTagName = toLower( tagName ); std::map::iterator countIt = tagCounts.find( lcaseTagName ); if( countIt == tagCounts.end() ) countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; countIt->second.add( tagName ); } } for( std::map::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end(); countIt != countItEnd; ++countIt ) { std::ostringstream oss; oss << " " << std::setw(2) << countIt->second.count << " "; Text wrapper( countIt->second.all(), TextAttributes() .setInitialIndent( 0 ) .setIndent( oss.str().size() ) .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); Catch::cout() << oss.str() << wrapper << '\n'; } Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; return tagCounts.size(); } inline std::size_t listReporters( Config const& /*config*/ ) { Catch::cout() << "Available reporters:\n"; IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; std::size_t maxNameLen = 0; for(it = itBegin; it != itEnd; ++it ) maxNameLen = (std::max)( maxNameLen, it->first.size() ); for(it = itBegin; it != itEnd; ++it ) { Text wrapper( it->second->getDescription(), TextAttributes() .setInitialIndent( 0 ) .setIndent( 7+maxNameLen ) .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); Catch::cout() << " " << it->first << ':' << std::string( maxNameLen - it->first.size() + 2, ' ' ) << wrapper << '\n'; } Catch::cout() << std::endl; return factories.size(); } inline Option list( Config const& config ) { Option listedCount; if( config.listTests() ) listedCount = listedCount.valueOr(0) + listTests( config ); if( config.listTestNamesOnly() ) listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); if( config.listTags() ) listedCount = listedCount.valueOr(0) + listTags( config ); if( config.listReporters() ) listedCount = listedCount.valueOr(0) + listReporters( config ); return listedCount; } } // end namespace Catch // #included from: internal/catch_run_context.hpp #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED // #included from: catch_test_case_tracker.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #include #include #include #include #include CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS namespace Catch { namespace TestCaseTracking { struct NameAndLocation { std::string name; SourceLineInfo location; NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) : name( _name ), location( _location ) {} }; struct ITracker : SharedImpl<> { virtual ~ITracker(); // static queries virtual NameAndLocation const& nameAndLocation() const = 0; // dynamic queries virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete virtual bool hasChildren() const = 0; virtual ITracker& parent() = 0; // actions virtual void close() = 0; // Successfully complete virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; virtual void addChild( Ptr const& child ) = 0; virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; virtual void openChild() = 0; // Debug/ checking virtual bool isSectionTracker() const = 0; virtual bool isIndexTracker() const = 0; }; class TrackerContext { enum RunState { NotStarted, Executing, CompletedCycle }; Ptr m_rootTracker; ITracker* m_currentTracker; RunState m_runState; public: static TrackerContext& instance() { static TrackerContext s_instance; return s_instance; } TrackerContext() : m_currentTracker( CATCH_NULL ), m_runState( NotStarted ) {} ITracker& startRun(); void endRun() { m_rootTracker.reset(); m_currentTracker = CATCH_NULL; m_runState = NotStarted; } void startCycle() { m_currentTracker = m_rootTracker.get(); m_runState = Executing; } void completeCycle() { m_runState = CompletedCycle; } bool completedCycle() const { return m_runState == CompletedCycle; } ITracker& currentTracker() { return *m_currentTracker; } void setCurrentTracker( ITracker* tracker ) { m_currentTracker = tracker; } }; class TrackerBase : public ITracker { protected: enum CycleState { NotStarted, Executing, ExecutingChildren, NeedsAnotherRun, CompletedSuccessfully, Failed }; class TrackerHasName { NameAndLocation m_nameAndLocation; public: TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} bool operator ()( Ptr const& tracker ) { return tracker->nameAndLocation().name == m_nameAndLocation.name && tracker->nameAndLocation().location == m_nameAndLocation.location; } }; typedef std::vector > Children; NameAndLocation m_nameAndLocation; TrackerContext& m_ctx; ITracker* m_parent; Children m_children; CycleState m_runState; public: TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) : m_nameAndLocation( nameAndLocation ), m_ctx( ctx ), m_parent( parent ), m_runState( NotStarted ) {} virtual ~TrackerBase(); virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { return m_nameAndLocation; } virtual bool isComplete() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully || m_runState == Failed; } virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully; } virtual bool isOpen() const CATCH_OVERRIDE { return m_runState != NotStarted && !isComplete(); } virtual bool hasChildren() const CATCH_OVERRIDE { return !m_children.empty(); } virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { m_children.push_back( child ); } virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); return( it != m_children.end() ) ? it->get() : CATCH_NULL; } virtual ITracker& parent() CATCH_OVERRIDE { assert( m_parent ); // Should always be non-null except for root return *m_parent; } virtual void openChild() CATCH_OVERRIDE { if( m_runState != ExecutingChildren ) { m_runState = ExecutingChildren; if( m_parent ) m_parent->openChild(); } } virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } void open() { m_runState = Executing; moveToThis(); if( m_parent ) m_parent->openChild(); } virtual void close() CATCH_OVERRIDE { // Close any still open children (e.g. generators) while( &m_ctx.currentTracker() != this ) m_ctx.currentTracker().close(); switch( m_runState ) { case NotStarted: case CompletedSuccessfully: case Failed: throw std::logic_error( "Illogical state" ); case NeedsAnotherRun: break;; case Executing: m_runState = CompletedSuccessfully; break; case ExecutingChildren: if( m_children.empty() || m_children.back()->isComplete() ) m_runState = CompletedSuccessfully; break; default: throw std::logic_error( "Unexpected state" ); } moveToParent(); m_ctx.completeCycle(); } virtual void fail() CATCH_OVERRIDE { m_runState = Failed; if( m_parent ) m_parent->markAsNeedingAnotherRun(); moveToParent(); m_ctx.completeCycle(); } virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { m_runState = NeedsAnotherRun; } private: void moveToParent() { assert( m_parent ); m_ctx.setCurrentTracker( m_parent ); } void moveToThis() { m_ctx.setCurrentTracker( this ); } }; class SectionTracker : public TrackerBase { std::vector m_filters; public: SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) : TrackerBase( nameAndLocation, ctx, parent ) { if( parent ) { while( !parent->isSectionTracker() ) parent = &parent->parent(); SectionTracker& parentSection = static_cast( *parent ); addNextFilters( parentSection.m_filters ); } } virtual ~SectionTracker(); virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { SectionTracker* section = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isSectionTracker() ); section = static_cast( childTracker ); } else { section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); currentTracker.addChild( section ); } if( !ctx.completedCycle() ) section->tryOpen(); return *section; } void tryOpen() { if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) open(); } void addInitialFilters( std::vector const& filters ) { if( !filters.empty() ) { m_filters.push_back(""); // Root - should never be consulted m_filters.push_back(""); // Test Case - not a section filter m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); } } void addNextFilters( std::vector const& filters ) { if( filters.size() > 1 ) m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); } }; class IndexTracker : public TrackerBase { int m_size; int m_index; public: IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) : TrackerBase( nameAndLocation, ctx, parent ), m_size( size ), m_index( -1 ) {} virtual ~IndexTracker(); virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { IndexTracker* tracker = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { assert( childTracker ); assert( childTracker->isIndexTracker() ); tracker = static_cast( childTracker ); } else { tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); currentTracker.addChild( tracker ); } if( !ctx.completedCycle() && !tracker->isComplete() ) { if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) tracker->moveNext(); tracker->open(); } return *tracker; } int index() const { return m_index; } void moveNext() { m_index++; m_children.clear(); } virtual void close() CATCH_OVERRIDE { TrackerBase::close(); if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) m_runState = Executing; } }; inline ITracker& TrackerContext::startRun() { m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); m_currentTracker = CATCH_NULL; m_runState = Executing; return *m_rootTracker; } } // namespace TestCaseTracking using TestCaseTracking::ITracker; using TestCaseTracking::TrackerContext; using TestCaseTracking::SectionTracker; using TestCaseTracking::IndexTracker; } // namespace Catch CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS // #included from: catch_fatal_condition.hpp #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED namespace Catch { // Report the error condition inline void reportFatal( std::string const& message ) { IContext& context = Catch::getCurrentContext(); IResultCapture* resultCapture = context.getResultCapture(); resultCapture->handleFatalErrorCondition( message ); } } // namespace Catch #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// // #included from: catch_windows_h_proxy.h #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED #ifdef CATCH_DEFINES_NOMINMAX # define NOMINMAX #endif #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #ifdef __AFXDLL #include #else #include #endif #ifdef CATCH_DEFINES_NOMINMAX # undef NOMINMAX #endif #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN # undef WIN32_LEAN_AND_MEAN #endif # if !defined ( CATCH_CONFIG_WINDOWS_SEH ) namespace Catch { struct FatalConditionHandler { void reset() {} }; } # else // CATCH_CONFIG_WINDOWS_SEH is defined namespace Catch { struct SignalDefs { DWORD id; const char* name; }; extern SignalDefs signalDefs[]; // There is no 1-1 mapping between signals and windows exceptions. // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. SignalDefs signalDefs[] = { { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, }; struct FatalConditionHandler { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { reportFatal(signalDefs[i].name); } } // If its not an exception we care about, pass it along. // This stops us from eating debugger breaks etc. return EXCEPTION_CONTINUE_SEARCH; } FatalConditionHandler() { isSet = true; // 32k seems enough for Catch to handle stack overflow, // but the value was found experimentally, so there is no strong guarantee guaranteeSize = 32 * 1024; exceptionHandlerHandle = CATCH_NULL; // Register as first handler in current chain exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); // Pass in guarantee size to be filled SetThreadStackGuarantee(&guaranteeSize); } static void reset() { if (isSet) { // Unregister handler and restore the old guarantee RemoveVectoredExceptionHandler(exceptionHandlerHandle); SetThreadStackGuarantee(&guaranteeSize); exceptionHandlerHandle = CATCH_NULL; isSet = false; } } ~FatalConditionHandler() { reset(); } private: static bool isSet; static ULONG guaranteeSize; static PVOID exceptionHandlerHandle; }; bool FatalConditionHandler::isSet = false; ULONG FatalConditionHandler::guaranteeSize = 0; PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; } // namespace Catch # endif // CATCH_CONFIG_WINDOWS_SEH #else // Not Windows - assumed to be POSIX compatible ////////////////////////// # if !defined(CATCH_CONFIG_POSIX_SIGNALS) namespace Catch { struct FatalConditionHandler { void reset() {} }; } # else // CATCH_CONFIG_POSIX_SIGNALS is defined #include namespace Catch { struct SignalDefs { int id; const char* name; }; extern SignalDefs signalDefs[]; SignalDefs signalDefs[] = { { SIGINT, "SIGINT - Terminal interrupt signal" }, { SIGILL, "SIGILL - Illegal instruction signal" }, { SIGFPE, "SIGFPE - Floating point error signal" }, { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, { SIGTERM, "SIGTERM - Termination request signal" }, { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } }; struct FatalConditionHandler { static bool isSet; static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; static stack_t oldSigStack; static char altStackMem[SIGSTKSZ]; static void handleSignal( int sig ) { std::string name = ""; for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { SignalDefs &def = signalDefs[i]; if (sig == def.id) { name = def.name; break; } } reset(); reportFatal(name); raise( sig ); } FatalConditionHandler() { isSet = true; stack_t sigStack; sigStack.ss_sp = altStackMem; sigStack.ss_size = SIGSTKSZ; sigStack.ss_flags = 0; sigaltstack(&sigStack, &oldSigStack); struct sigaction sa = { 0 }; sa.sa_handler = handleSignal; sa.sa_flags = SA_ONSTACK; for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); } } ~FatalConditionHandler() { reset(); } static void reset() { if( isSet ) { // Set signals back to previous values -- hopefully nobody overwrote them in the meantime for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); } // Return the old stack sigaltstack(&oldSigStack, CATCH_NULL); isSet = false; } } }; bool FatalConditionHandler::isSet = false; struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; stack_t FatalConditionHandler::oldSigStack = {}; char FatalConditionHandler::altStackMem[SIGSTKSZ] = {}; } // namespace Catch # endif // CATCH_CONFIG_POSIX_SIGNALS #endif // not Windows #include #include namespace Catch { class StreamRedirect { public: StreamRedirect( std::ostream& stream, std::string& targetString ) : m_stream( stream ), m_prevBuf( stream.rdbuf() ), m_targetString( targetString ) { stream.rdbuf( m_oss.rdbuf() ); } ~StreamRedirect() { m_targetString += m_oss.str(); m_stream.rdbuf( m_prevBuf ); } private: std::ostream& m_stream; std::streambuf* m_prevBuf; std::ostringstream m_oss; std::string& m_targetString; }; /////////////////////////////////////////////////////////////////////////// class RunContext : public IResultCapture, public IRunner { RunContext( RunContext const& ); void operator =( RunContext const& ); public: explicit RunContext( Ptr const& _config, Ptr const& reporter ) : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), m_activeTestCase( CATCH_NULL ), m_config( _config ), m_reporter( reporter ), m_shouldReportUnexpected ( true ) { m_context.setRunner( this ); m_context.setConfig( m_config ); m_context.setResultCapture( this ); m_reporter->testRunStarting( m_runInfo ); } virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); } void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); } Totals runTest( TestCase const& testCase ) { Totals prevTotals = m_totals; std::string redirectedCout; std::string redirectedCerr; TestCaseInfo testInfo = testCase.getTestCaseInfo(); m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; do { ITracker& rootTracker = m_trackerContext.startRun(); assert( rootTracker.isSectionTracker() ); static_cast( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); do { m_trackerContext.startCycle(); m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); runCurrentTest( redirectedCout, redirectedCerr ); } while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } // !TBD: deprecated - this will be replaced by indexed trackers while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { deltaTotals.assertions.failed++; deltaTotals.testCases.passed--; deltaTotals.testCases.failed++; } m_totals.testCases += deltaTotals.testCases; m_reporter->testCaseEnded( TestCaseStats( testInfo, deltaTotals, redirectedCout, redirectedCerr, aborting() ) ); m_activeTestCase = CATCH_NULL; m_testCaseTracker = CATCH_NULL; return deltaTotals; } Ptr config() const { return m_config; } private: // IResultCapture virtual void assertionEnded( AssertionResult const& result ) { if( result.getResultType() == ResultWas::Ok ) { m_totals.assertions.passed++; } else if( !result.isOk() ) { m_totals.assertions.failed++; } // We have no use for the return value (whether messages should be cleared), because messages were made scoped // and should be let to clear themselves out. static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); // Reset working state m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); m_lastResult = result; } virtual bool sectionStarted ( SectionInfo const& sectionInfo, Counts& assertions ) { ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); if( !sectionTracker.isOpen() ) return false; m_activeSections.push_back( §ionTracker ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; m_reporter->sectionStarting( sectionInfo ); assertions = m_totals.assertions; return true; } bool testForMissingAssertions( Counts& assertions ) { if( assertions.total() != 0 ) return false; if( !m_config->warnAboutMissingAssertions() ) return false; if( m_trackerContext.currentTracker().hasChildren() ) return false; m_totals.assertions.failed++; assertions.failed++; return true; } virtual void sectionEnded( SectionEndInfo const& endInfo ) { Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); if( !m_activeSections.empty() ) { m_activeSections.back()->close(); m_activeSections.pop_back(); } m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { if( m_unfinishedSections.empty() ) m_activeSections.back()->fail(); else m_activeSections.back()->close(); m_activeSections.pop_back(); m_unfinishedSections.push_back( endInfo ); } virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } virtual void popScopedMessage( MessageInfo const& message ) { m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); } virtual std::string getCurrentTestName() const { return m_activeTestCase ? m_activeTestCase->getTestCaseInfo().name : std::string(); } virtual const AssertionResult* getLastResult() const { return &m_lastResult; } virtual void exceptionEarlyReported() { m_shouldReportUnexpected = false; } virtual void handleFatalErrorCondition( std::string const& message ) { // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. AssertionResultData tempResult; tempResult.resultType = ResultWas::FatalErrorCondition; tempResult.message = message; AssertionResult result(m_lastAssertionInfo, tempResult); getResultCapture().assertionEnded(result); handleUnfinishedSections(); // Recreate section for test case (as we will lose the one that was in scope) TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); Counts assertions; assertions.failed = 1; SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); m_reporter->sectionEnded( testCaseSectionStats ); TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); Totals deltaTotals; deltaTotals.testCases.failed = 1; m_reporter->testCaseEnded( TestCaseStats( testInfo, deltaTotals, std::string(), std::string(), false ) ); m_totals.testCases.failed++; testGroupEnded( std::string(), m_totals, 1, 1 ); m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); } public: // !TBD We need to do this another way! bool aborting() const { return m_totals.assertions.failed == static_cast( m_config->abortAfter() ); } private: void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); m_reporter->sectionStarting( testCaseSection ); Counts prevAssertions = m_totals.assertions; double duration = 0; m_shouldReportUnexpected = true; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); seedRng( *m_config ); Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { StreamRedirect coutRedir( Catch::cout(), redirectedCout ); StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); invokeActiveTestCase(); } else { invokeActiveTestCase(); } duration = timer.getElapsedSeconds(); } catch( TestFailureException& ) { // This just means the test was aborted due to failure } catch(...) { // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions // are reported without translation at the point of origin. if (m_shouldReportUnexpected) { makeUnexpectedResultBuilder().useActiveException(); } } m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); Counts assertions = m_totals.assertions - prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); if( testCaseInfo.okToFail() ) { std::swap( assertions.failedButOk, assertions.failed ); m_totals.assertions.failed -= assertions.failedButOk; m_totals.assertions.failedButOk += assertions.failedButOk; } SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); m_reporter->sectionEnded( testCaseSectionStats ); } void invokeActiveTestCase() { FatalConditionHandler fatalConditionHandler; // Handle signals m_activeTestCase->invoke(); fatalConditionHandler.reset(); } private: ResultBuilder makeUnexpectedResultBuilder() const { return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), m_lastAssertionInfo.lineInfo, m_lastAssertionInfo.capturedExpression.c_str(), m_lastAssertionInfo.resultDisposition ); } void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it ) sectionEnded( *it ); m_unfinishedSections.clear(); } TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; ITracker* m_testCaseTracker; ITracker* m_currentSectionTracker; AssertionResult m_lastResult; Ptr m_config; Totals m_totals; Ptr m_reporter; std::vector m_messages; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; std::vector m_activeSections; TrackerContext m_trackerContext; bool m_shouldReportUnexpected; }; IResultCapture& getResultCapture() { if( IResultCapture* capture = getCurrentContext().getResultCapture() ) return *capture; else throw std::logic_error( "No result capture instance" ); } } // end namespace Catch // #included from: internal/catch_version.h #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED namespace Catch { // Versioning information struct Version { Version( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, char const * const _branchName, unsigned int _buildNumber ); unsigned int const majorVersion; unsigned int const minorVersion; unsigned int const patchNumber; // buildNumber is only used if branchName is not null char const * const branchName; unsigned int const buildNumber; friend std::ostream& operator << ( std::ostream& os, Version const& version ); private: void operator=( Version const& ); }; inline Version libraryVersion(); } #include #include #include namespace Catch { Ptr createReporter( std::string const& reporterName, Ptr const& config ) { Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); if( !reporter ) { std::ostringstream oss; oss << "No reporter registered with name: '" << reporterName << "'"; throw std::domain_error( oss.str() ); } return reporter; } Ptr makeReporter( Ptr const& config ) { std::vector reporters = config->getReporterNames(); if( reporters.empty() ) reporters.push_back( "console" ); Ptr reporter; for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); it != itEnd; ++it ) reporter = addReporter( reporter, createReporter( *it, config ) ); return reporter; } Ptr addListeners( Ptr const& config, Ptr reporters ) { IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); it != itEnd; ++it ) reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); return reporters; } Totals runTests( Ptr const& config ) { Ptr iconfig = config.get(); Ptr reporter = makeReporter( config ); reporter = addListeners( iconfig, reporter ); RunContext context( iconfig, reporter ); Totals totals; context.testGroupStarting( config->name(), 1, 1 ); TestSpec testSpec = config->testSpec(); if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); it != itEnd; ++it ) { if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) totals += context.runTest( *it ); else reporter->skipTest( *it ); } context.testGroupEnded( iconfig->name(), totals, 1, 1 ); return totals; } void applyFilenamesAsTags( IConfig const& config ) { std::vector const& tests = getAllTestCasesSorted( config ); for(std::size_t i = 0; i < tests.size(); ++i ) { TestCase& test = const_cast( tests[i] ); std::set tags = test.tags; std::string filename = test.lineInfo.file; std::string::size_type lastSlash = filename.find_last_of( "\\/" ); if( lastSlash != std::string::npos ) filename = filename.substr( lastSlash+1 ); std::string::size_type lastDot = filename.find_last_of( "." ); if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); tags.insert( "#" + filename ); setTags( test, tags ); } } class Session : NonCopyable { static bool alreadyInstantiated; public: struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; Session() : m_cli( makeCommandLineParser() ) { if( alreadyInstantiated ) { std::string msg = "Only one instance of Catch::Session can ever be used"; Catch::cerr() << msg << std::endl; throw std::logic_error( msg ); } alreadyInstantiated = true; } ~Session() { Catch::cleanUp(); } void showHelp( std::string const& processName ) { Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; m_cli.usage( Catch::cout(), processName ); Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); if( m_configData.showHelp ) showHelp( m_configData.processName ); m_config.reset(); } catch( std::exception& ex ) { { Colour colourGuard( Colour::Red ); Catch::cerr() << "\nError(s) in input:\n" << Text( ex.what(), TextAttributes().setIndent(2) ) << "\n\n"; } m_cli.usage( Catch::cout(), m_configData.processName ); return (std::numeric_limits::max)(); } return 0; } void useConfigData( ConfigData const& _configData ) { m_configData = _configData; m_config.reset(); } int run( int argc, char const* const* const argv ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); return returnCode; } #if defined(WIN32) && defined(UNICODE) int run( int argc, wchar_t const* const* const argv ) { char **utf8Argv = new char *[ argc ]; for ( int i = 0; i < argc; ++i ) { int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); utf8Argv[ i ] = new char[ bufSize ]; WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); } int returnCode = applyCommandLine( argc, utf8Argv ); if( returnCode == 0 ) returnCode = run(); for ( int i = 0; i < argc; ++i ) delete [] utf8Argv[ i ]; delete [] utf8Argv; return returnCode; } #endif int run() { if( m_configData.showHelp ) return 0; try { config(); // Force config to be constructed seedRng( *m_config ); if( m_configData.filenamesAsTags ) applyFilenamesAsTags( *m_config ); // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); return static_cast( runTests( m_config ).assertions.failed ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; return (std::numeric_limits::max)(); } } Clara::CommandLine const& cli() const { return m_cli; } std::vector const& unusedTokens() const { return m_unusedTokens; } ConfigData& configData() { return m_configData; } Config& config() { if( !m_config ) m_config = new Config( m_configData ); return *m_config; } private: Clara::CommandLine m_cli; std::vector m_unusedTokens; ConfigData m_configData; Ptr m_config; }; bool Session::alreadyInstantiated = false; } // end namespace Catch // #included from: catch_registry_hub.hpp #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED // #included from: catch_test_case_registry_impl.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED #include #include #include #include namespace Catch { struct RandomNumberGenerator { typedef std::ptrdiff_t result_type; result_type operator()( result_type n ) const { return std::rand() % n; } #ifdef CATCH_CONFIG_CPP11_SHUFFLE static constexpr result_type min() { return 0; } static constexpr result_type max() { return 1000000; } result_type operator()() const { return std::rand() % max(); } #endif template static void shuffle( V& vector ) { RandomNumberGenerator rng; #ifdef CATCH_CONFIG_CPP11_SHUFFLE std::shuffle( vector.begin(), vector.end(), rng ); #else std::random_shuffle( vector.begin(), vector.end(), rng ); #endif } }; inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { std::vector sorted = unsortedTestCases; switch( config.runOrder() ) { case RunTests::InLexicographicalOrder: std::sort( sorted.begin(), sorted.end() ); break; case RunTests::InRandomOrder: { seedRng( config ); RandomNumberGenerator::shuffle( sorted ); } break; case RunTests::InDeclarationOrder: // already in declaration order break; } return sorted; } bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); } void enforceNoDuplicateTestCases( std::vector const& functions ) { std::set seenFunctions; for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); it != itEnd; ++it ) { std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); if( !prev.second ) { std::ostringstream ss; ss << Colour( Colour::Red ) << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; throw std::runtime_error(ss.str()); } } } std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; filtered.reserve( testCases.size() ); for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); it != itEnd; ++it ) if( matchTest( *it, testSpec, config ) ) filtered.push_back( *it ); return filtered; } std::vector const& getAllTestCasesSorted( IConfig const& config ) { return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); } class TestRegistry : public ITestCaseRegistry { public: TestRegistry() : m_currentSortOrder( RunTests::InDeclarationOrder ), m_unnamedCount( 0 ) {} virtual ~TestRegistry(); virtual void registerTest( TestCase const& testCase ) { std::string name = testCase.getTestCaseInfo().name; if( name.empty() ) { std::ostringstream oss; oss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( oss.str() ) ); } m_functions.push_back( testCase ); } virtual std::vector const& getAllTests() const { return m_functions; } virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { if( m_sortedFunctions.empty() ) enforceNoDuplicateTestCases( m_functions ); if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { m_sortedFunctions = sortTests( config, m_functions ); m_currentSortOrder = config.runOrder(); } return m_sortedFunctions; } private: std::vector m_functions; mutable RunTests::InWhatOrder m_currentSortOrder; mutable std::vector m_sortedFunctions; size_t m_unnamedCount; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; /////////////////////////////////////////////////////////////////////////// class FreeFunctionTestCase : public SharedImpl { public: FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} virtual void invoke() const { m_fun(); } private: virtual ~FreeFunctionTestCase(); TestFunction m_fun; }; inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { std::string className = classOrQualifiedMethodName; if( startsWith( className, '&' ) ) { std::size_t lastColons = className.rfind( "::" ); std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); if( penultimateColons == std::string::npos ) penultimateColons = 1; className = className.substr( penultimateColons, lastColons-penultimateColons ); } return className; } void registerTestCase ( ITestCase* testCase, char const* classOrQualifiedMethodName, NameAndDesc const& nameAndDesc, SourceLineInfo const& lineInfo ) { getMutableRegistryHub().registerTest ( makeTestCase ( testCase, extractClassName( classOrQualifiedMethodName ), nameAndDesc.name, nameAndDesc.description, lineInfo ) ); } void registerTestCaseFunction ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ) { registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); } /////////////////////////////////////////////////////////////////////////// AutoReg::AutoReg ( TestFunction function, SourceLineInfo const& lineInfo, NameAndDesc const& nameAndDesc ) { registerTestCaseFunction( function, lineInfo, nameAndDesc ); } AutoReg::~AutoReg() {} } // end namespace Catch // #included from: catch_reporter_registry.hpp #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED #include namespace Catch { class ReporterRegistry : public IReporterRegistry { public: virtual ~ReporterRegistry() CATCH_OVERRIDE {} virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } void registerReporter( std::string const& name, Ptr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } void registerListener( Ptr const& factory ) { m_listeners.push_back( factory ); } virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { return m_factories; } virtual Listeners const& getListeners() const CATCH_OVERRIDE { return m_listeners; } private: FactoryMap m_factories; Listeners m_listeners; }; } // #included from: catch_exception_translator_registry.hpp #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED #ifdef __OBJC__ #import "Foundation/Foundation.h" #endif namespace Catch { class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { public: ~ExceptionTranslatorRegistry() { deleteAll( m_translators ); } virtual void registerTranslator( const IExceptionTranslator* translator ) { m_translators.push_back( translator ); } virtual std::string translateActiveException() const { try { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else return tryTranslators(); #endif } catch( TestFailureException& ) { throw; } catch( std::exception& ex ) { return ex.what(); } catch( std::string& msg ) { return msg; } catch( const char* msg ) { return msg; } catch(...) { return "Unknown exception"; } } std::string tryTranslators() const { if( m_translators.empty() ) throw; else return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: std::vector m_translators; }; } // #included from: catch_tag_alias_registry.h #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED #include namespace Catch { class TagAliasRegistry : public ITagAliasRegistry { public: virtual ~TagAliasRegistry(); virtual Option find( std::string const& alias ) const; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); private: std::map m_registry; }; } // end namespace Catch namespace Catch { namespace { class RegistryHub : public IRegistryHub, public IMutableRegistryHub { RegistryHub( RegistryHub const& ); void operator=( RegistryHub const& ); public: // IRegistryHub RegistryHub() { } virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { return m_reporterRegistry; } virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { return m_testCaseRegistry; } virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { return m_tagAliasRegistry; } public: // IMutableRegistryHub virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerReporter( name, factory ); } virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerListener( factory ); } virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { m_testCaseRegistry.registerTest( testInfo ); } virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { m_tagAliasRegistry.add( alias, tag, lineInfo ); } private: TestRegistry m_testCaseRegistry; ReporterRegistry m_reporterRegistry; ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; TagAliasRegistry m_tagAliasRegistry; }; // Single, global, instance inline RegistryHub*& getTheRegistryHub() { static RegistryHub* theRegistryHub = CATCH_NULL; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; } } IRegistryHub& getRegistryHub() { return *getTheRegistryHub(); } IMutableRegistryHub& getMutableRegistryHub() { return *getTheRegistryHub(); } void cleanUp() { delete getTheRegistryHub(); getTheRegistryHub() = CATCH_NULL; cleanUpContext(); } std::string translateActiveException() { return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); } } // end namespace Catch // #included from: catch_notimplemented_exception.hpp #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED #include namespace Catch { NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) : m_lineInfo( lineInfo ) { std::ostringstream oss; oss << lineInfo << ": function "; oss << "not implemented"; m_what = oss.str(); } const char* NotImplementedException::what() const CATCH_NOEXCEPT { return m_what.c_str(); } } // end namespace Catch // #included from: catch_context_impl.hpp #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED // #included from: catch_stream.hpp #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED #include #include #include namespace Catch { template class StreamBufImpl : public StreamBufBase { char data[bufferSize]; WriterF m_writer; public: StreamBufImpl() { setp( data, data + sizeof(data) ); } ~StreamBufImpl() CATCH_NOEXCEPT { sync(); } private: int overflow( int c ) { sync(); if( c != EOF ) { if( pbase() == epptr() ) m_writer( std::string( 1, static_cast( c ) ) ); else sputc( static_cast( c ) ); } return 0; } int sync() { if( pbase() != pptr() ) { m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); setp( pbase(), epptr() ); } return 0; } }; /////////////////////////////////////////////////////////////////////////// FileStream::FileStream( std::string const& filename ) { m_ofs.open( filename.c_str() ); if( m_ofs.fail() ) { std::ostringstream oss; oss << "Unable to open file: '" << filename << '\''; throw std::domain_error( oss.str() ); } } std::ostream& FileStream::stream() const { return m_ofs; } struct OutputDebugWriter { void operator()( std::string const&str ) { writeToDebugConsole( str ); } }; DebugOutStream::DebugOutStream() : m_streamBuf( new StreamBufImpl() ), m_os( m_streamBuf.get() ) {} std::ostream& DebugOutStream::stream() const { return m_os; } // Store the streambuf from cout up-front because // cout may get redirected when running tests CoutStream::CoutStream() : m_os( Catch::cout().rdbuf() ) {} std::ostream& CoutStream::stream() const { return m_os; } #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions std::ostream& cout() { return std::cout; } std::ostream& cerr() { return std::cerr; } #endif } namespace Catch { class Context : public IMutableContext { Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} Context( Context const& ); void operator=( Context const& ); public: virtual ~Context() { deleteAllValues( m_generatorsByTestName ); } public: // IContext virtual IResultCapture* getResultCapture() { return m_resultCapture; } virtual IRunner* getRunner() { return m_runner; } virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { return getGeneratorsForCurrentTest() .getGeneratorInfo( fileInfo, totalSize ) .getCurrentIndex(); } virtual bool advanceGeneratorsForCurrentTest() { IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); return generators && generators->moveNext(); } virtual Ptr getConfig() const { return m_config; } public: // IMutableContext virtual void setResultCapture( IResultCapture* resultCapture ) { m_resultCapture = resultCapture; } virtual void setRunner( IRunner* runner ) { m_runner = runner; } virtual void setConfig( Ptr const& config ) { m_config = config; } friend IMutableContext& getCurrentMutableContext(); private: IGeneratorsForTest* findGeneratorsForCurrentTest() { std::string testName = getResultCapture()->getCurrentTestName(); std::map::const_iterator it = m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second : CATCH_NULL; } IGeneratorsForTest& getGeneratorsForCurrentTest() { IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); if( !generators ) { std::string testName = getResultCapture()->getCurrentTestName(); generators = createGeneratorsForTest(); m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); } return *generators; } private: Ptr m_config; IRunner* m_runner; IResultCapture* m_resultCapture; std::map m_generatorsByTestName; }; namespace { Context* currentContext = CATCH_NULL; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) currentContext = new Context(); return *currentContext; } IContext& getCurrentContext() { return getCurrentMutableContext(); } void cleanUpContext() { delete currentContext; currentContext = CATCH_NULL; } } // #included from: catch_console_colour_impl.hpp #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED // #included from: catch_errno_guard.hpp #define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED #include namespace Catch { class ErrnoGuard { public: ErrnoGuard():m_oldErrno(errno){} ~ErrnoGuard() { errno = m_oldErrno; } private: int m_oldErrno; }; } namespace Catch { namespace { struct IColourImpl { virtual ~IColourImpl() {} virtual void use( Colour::Code _colourCode ) = 0; }; struct NoColourImpl : IColourImpl { void use( Colour::Code ) {} static IColourImpl* instance() { static NoColourImpl s_instance; return &s_instance; } }; } // anon namespace } // namespace Catch #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) # ifdef CATCH_PLATFORM_WINDOWS # define CATCH_CONFIG_COLOUR_WINDOWS # else # define CATCH_CONFIG_COLOUR_ANSI # endif #endif #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// namespace Catch { namespace { class Win32ColourImpl : public IColourImpl { public: Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Red: return setTextAttribute( FOREGROUND_RED ); case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); case Colour::Grey: return setTextAttribute( 0 ); case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Bright: throw std::logic_error( "not a colour" ); } } private: void setTextAttribute( WORD _textAttribute ) { SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); } HANDLE stdoutHandle; WORD originalForegroundAttributes; WORD originalBackgroundAttributes; }; IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; Ptr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) colourMode = !isDebuggerActive() ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance(); } } // end anon namespace } // end namespace Catch #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// #include namespace Catch { namespace { // use POSIX/ ANSI console terminal codes // Thanks to Adam Strzelecki for original contribution // (http://github.com/nanoant) // https://github.com/philsquared/Catch/pull/131 class PosixColourImpl : public IColourImpl { public: virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { case Colour::None: case Colour::White: return setColour( "[0m" ); case Colour::Red: return setColour( "[0;31m" ); case Colour::Green: return setColour( "[0;32m" ); case Colour::Blue: return setColour( "[0;34m" ); case Colour::Cyan: return setColour( "[0;36m" ); case Colour::Yellow: return setColour( "[0;33m" ); case Colour::Grey: return setColour( "[1;30m" ); case Colour::LightGrey: return setColour( "[0;37m" ); case Colour::BrightRed: return setColour( "[1;31m" ); case Colour::BrightGreen: return setColour( "[1;32m" ); case Colour::BrightWhite: return setColour( "[1;37m" ); case Colour::Bright: throw std::logic_error( "not a colour" ); } } static IColourImpl* instance() { static PosixColourImpl s_instance; return &s_instance; } private: void setColour( const char* _escapeCode ) { Catch::cout() << '\033' << _escapeCode; } }; IColourImpl* platformColourInstance() { ErrnoGuard guard; Ptr config = getCurrentContext().getConfig(); UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto; if( colourMode == UseColour::Auto ) colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) ? UseColour::Yes : UseColour::No; return colourMode == UseColour::Yes ? PosixColourImpl::instance() : NoColourImpl::instance(); } } // end anon namespace } // end namespace Catch #else // not Windows or ANSI /////////////////////////////////////////////// namespace Catch { static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } } // end namespace Catch #endif // Windows/ ANSI/ None namespace Catch { Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast( _other ).m_moved = true; } Colour::~Colour(){ if( !m_moved ) use( None ); } void Colour::use( Code _colourCode ) { static IColourImpl* impl = platformColourInstance(); impl->use( _colourCode ); } } // end namespace Catch // #included from: catch_generators_impl.hpp #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED #include #include #include namespace Catch { struct GeneratorInfo : IGeneratorInfo { GeneratorInfo( std::size_t size ) : m_size( size ), m_currentIndex( 0 ) {} bool moveNext() { if( ++m_currentIndex == m_size ) { m_currentIndex = 0; return false; } return true; } std::size_t getCurrentIndex() const { return m_currentIndex; } std::size_t m_size; std::size_t m_currentIndex; }; /////////////////////////////////////////////////////////////////////////// class GeneratorsForTest : public IGeneratorsForTest { public: ~GeneratorsForTest() { deleteAll( m_generatorsInOrder ); } IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { std::map::const_iterator it = m_generatorsByName.find( fileInfo ); if( it == m_generatorsByName.end() ) { IGeneratorInfo* info = new GeneratorInfo( size ); m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); m_generatorsInOrder.push_back( info ); return *info; } return *it->second; } bool moveNext() { std::vector::const_iterator it = m_generatorsInOrder.begin(); std::vector::const_iterator itEnd = m_generatorsInOrder.end(); for(; it != itEnd; ++it ) { if( (*it)->moveNext() ) return true; } return false; } private: std::map m_generatorsByName; std::vector m_generatorsInOrder; }; IGeneratorsForTest* createGeneratorsForTest() { return new GeneratorsForTest(); } } // end namespace Catch // #included from: catch_assertionresult.hpp #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED namespace Catch { AssertionInfo::AssertionInfo( std::string const& _macroName, SourceLineInfo const& _lineInfo, std::string const& _capturedExpression, ResultDisposition::Flags _resultDisposition ) : macroName( _macroName ), lineInfo( _lineInfo ), capturedExpression( _capturedExpression ), resultDisposition( _resultDisposition ) {} AssertionResult::AssertionResult() {} AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) : m_info( info ), m_resultData( data ) {} AssertionResult::~AssertionResult() {} // Result was a success bool AssertionResult::succeeded() const { return Catch::isOk( m_resultData.resultType ); } // Result was a success, or failure is suppressed bool AssertionResult::isOk() const { return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); } ResultWas::OfType AssertionResult::getResultType() const { return m_resultData.resultType; } bool AssertionResult::hasExpression() const { return !m_info.capturedExpression.empty(); } bool AssertionResult::hasMessage() const { return !m_resultData.message.empty(); } std::string AssertionResult::getExpression() const { if( isFalseTest( m_info.resultDisposition ) ) return '!' + m_info.capturedExpression; else return m_info.capturedExpression; } std::string AssertionResult::getExpressionInMacro() const { if( m_info.macroName.empty() ) return m_info.capturedExpression; else return m_info.macroName + "( " + m_info.capturedExpression + " )"; } bool AssertionResult::hasExpandedExpression() const { return hasExpression() && getExpandedExpression() != getExpression(); } std::string AssertionResult::getExpandedExpression() const { return m_resultData.reconstructExpression(); } std::string AssertionResult::getMessage() const { return m_resultData.message; } SourceLineInfo AssertionResult::getSourceInfo() const { return m_info.lineInfo; } std::string AssertionResult::getTestMacroName() const { return m_info.macroName; } void AssertionResult::discardDecomposedExpression() const { m_resultData.decomposedExpression = CATCH_NULL; } void AssertionResult::expandDecomposedExpression() const { m_resultData.reconstructExpression(); } } // end namespace Catch // #included from: catch_test_case_info.hpp #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED #include namespace Catch { inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { if( startsWith( tag, '.' ) || tag == "hide" || tag == "!hide" ) return TestCaseInfo::IsHidden; else if( tag == "!throws" ) return TestCaseInfo::Throws; else if( tag == "!shouldfail" ) return TestCaseInfo::ShouldFail; else if( tag == "!mayfail" ) return TestCaseInfo::MayFail; else if( tag == "!nonportable" ) return TestCaseInfo::NonPortable; else return TestCaseInfo::None; } inline bool isReservedTag( std::string const& tag ) { return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); } inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { if( isReservedTag( tag ) ) { std::ostringstream ss; ss << Colour(Colour::Red) << "Tag name [" << tag << "] not allowed.\n" << "Tag names starting with non alpha-numeric characters are reserved\n" << Colour(Colour::FileName) << _lineInfo << '\n'; throw std::runtime_error(ss.str()); } } TestCase makeTestCase( ITestCase* _testCase, std::string const& _className, std::string const& _name, std::string const& _descOrTags, SourceLineInfo const& _lineInfo ) { bool isHidden( startsWith( _name, "./" ) ); // Legacy support // Parse out tags std::set tags; std::string desc, tag; bool inTag = false; for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { char c = _descOrTags[i]; if( !inTag ) { if( c == '[' ) inTag = true; else desc += c; } else { if( c == ']' ) { TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); if( prop == TestCaseInfo::IsHidden ) isHidden = true; else if( prop == TestCaseInfo::None ) enforceNotReservedTag( tag, _lineInfo ); tags.insert( tag ); tag.clear(); inTag = false; } else tag += c; } } if( isHidden ) { tags.insert( "hide" ); tags.insert( "." ); } TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); return TestCase( _testCase, info ); } void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) { testCaseInfo.tags = tags; testCaseInfo.lcaseTags.clear(); std::ostringstream oss; for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { oss << '[' << *it << ']'; std::string lcaseTag = toLower( *it ); testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); testCaseInfo.lcaseTags.insert( lcaseTag ); } testCaseInfo.tagsAsString = oss.str(); } TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, std::set const& _tags, SourceLineInfo const& _lineInfo ) : name( _name ), className( _className ), description( _description ), lineInfo( _lineInfo ), properties( None ) { setTags( *this, _tags ); } TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) : name( other.name ), className( other.className ), description( other.description ), tags( other.tags ), lcaseTags( other.lcaseTags ), tagsAsString( other.tagsAsString ), lineInfo( other.lineInfo ), properties( other.properties ) {} bool TestCaseInfo::isHidden() const { return ( properties & IsHidden ) != 0; } bool TestCaseInfo::throws() const { return ( properties & Throws ) != 0; } bool TestCaseInfo::okToFail() const { return ( properties & (ShouldFail | MayFail ) ) != 0; } bool TestCaseInfo::expectedToFail() const { return ( properties & (ShouldFail ) ) != 0; } TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} TestCase::TestCase( TestCase const& other ) : TestCaseInfo( other ), test( other.test ) {} TestCase TestCase::withName( std::string const& _newName ) const { TestCase other( *this ); other.name = _newName; return other; } void TestCase::swap( TestCase& other ) { test.swap( other.test ); name.swap( other.name ); className.swap( other.className ); description.swap( other.description ); tags.swap( other.tags ); lcaseTags.swap( other.lcaseTags ); tagsAsString.swap( other.tagsAsString ); std::swap( TestCaseInfo::properties, static_cast( other ).properties ); std::swap( lineInfo, other.lineInfo ); } void TestCase::invoke() const { test->invoke(); } bool TestCase::operator == ( TestCase const& other ) const { return test.get() == other.test.get() && name == other.name && className == other.className; } bool TestCase::operator < ( TestCase const& other ) const { return name < other.name; } TestCase& TestCase::operator = ( TestCase const& other ) { TestCase temp( other ); swap( temp ); return *this; } TestCaseInfo const& TestCase::getTestCaseInfo() const { return *this; } } // end namespace Catch // #included from: catch_version.hpp #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED namespace Catch { Version::Version ( unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber, char const * const _branchName, unsigned int _buildNumber ) : majorVersion( _majorVersion ), minorVersion( _minorVersion ), patchNumber( _patchNumber ), branchName( _branchName ), buildNumber( _buildNumber ) {} std::ostream& operator << ( std::ostream& os, Version const& version ) { os << version.majorVersion << '.' << version.minorVersion << '.' << version.patchNumber; // branchName is never null -> 0th char is \0 if it is empty if (version.branchName[0]) { os << '-' << version.branchName << '.' << version.buildNumber; } return os; } inline Version libraryVersion() { static Version version( 1, 9, 4, "", 0 ); return version; } } // #included from: catch_message.hpp #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED namespace Catch { MessageInfo::MessageInfo( std::string const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type ) : macroName( _macroName ), lineInfo( _lineInfo ), type( _type ), sequence( ++globalCount ) {} // This may need protecting if threading support is added unsigned int MessageInfo::globalCount = 0; //////////////////////////////////////////////////////////////////////////// ScopedMessage::ScopedMessage( MessageBuilder const& builder ) : m_info( builder.m_info ) { m_info.message = builder.m_stream.str(); getResultCapture().pushScopedMessage( m_info ); } ScopedMessage::ScopedMessage( ScopedMessage const& other ) : m_info( other.m_info ) {} ScopedMessage::~ScopedMessage() { if ( !std::uncaught_exception() ){ getResultCapture().popScopedMessage(m_info); } } } // end namespace Catch // #included from: catch_legacy_reporter_adapter.hpp #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED // #included from: catch_legacy_reporter_adapter.h #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED namespace Catch { // Deprecated struct IReporter : IShared { virtual ~IReporter(); virtual bool shouldRedirectStdout() const = 0; virtual void StartTesting() = 0; virtual void EndTesting( Totals const& totals ) = 0; virtual void StartGroup( std::string const& groupName ) = 0; virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; virtual void Aborted() = 0; virtual void Result( AssertionResult const& result ) = 0; }; class LegacyReporterAdapter : public SharedImpl { public: LegacyReporterAdapter( Ptr const& legacyReporter ); virtual ~LegacyReporterAdapter(); virtual ReporterPreferences getPreferences() const; virtual void noMatchingTestCases( std::string const& ); virtual void testRunStarting( TestRunInfo const& ); virtual void testGroupStarting( GroupInfo const& groupInfo ); virtual void testCaseStarting( TestCaseInfo const& testInfo ); virtual void sectionStarting( SectionInfo const& sectionInfo ); virtual void assertionStarting( AssertionInfo const& ); virtual bool assertionEnded( AssertionStats const& assertionStats ); virtual void sectionEnded( SectionStats const& sectionStats ); virtual void testCaseEnded( TestCaseStats const& testCaseStats ); virtual void testGroupEnded( TestGroupStats const& testGroupStats ); virtual void testRunEnded( TestRunStats const& testRunStats ); virtual void skipTest( TestCaseInfo const& ); private: Ptr m_legacyReporter; }; } namespace Catch { LegacyReporterAdapter::LegacyReporterAdapter( Ptr const& legacyReporter ) : m_legacyReporter( legacyReporter ) {} LegacyReporterAdapter::~LegacyReporterAdapter() {} ReporterPreferences LegacyReporterAdapter::getPreferences() const { ReporterPreferences prefs; prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); return prefs; } void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { m_legacyReporter->StartTesting(); } void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { m_legacyReporter->StartGroup( groupInfo.name ); } void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { m_legacyReporter->StartTestCase( testInfo ); } void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); } void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { // Not on legacy interface } bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); it != itEnd; ++it ) { if( it->type == ResultWas::Info ) { ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); rb << it->message; rb.setResultType( ResultWas::Info ); AssertionResult result = rb.build(); m_legacyReporter->Result( result ); } } } m_legacyReporter->Result( assertionStats.assertionResult ); return true; } void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { if( sectionStats.missingAssertions ) m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); } void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { m_legacyReporter->EndTestCase ( testCaseStats.testInfo, testCaseStats.totals, testCaseStats.stdOut, testCaseStats.stdErr ); } void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { if( testGroupStats.aborting ) m_legacyReporter->Aborted(); m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); } void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { m_legacyReporter->EndTesting( testRunStats.totals ); } void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { } } // #included from: catch_timer.hpp #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wc++11-long-long" #endif #ifdef CATCH_PLATFORM_WINDOWS #else #include #endif namespace Catch { namespace { #ifdef CATCH_PLATFORM_WINDOWS UInt64 getCurrentTicks() { static UInt64 hz=0, hzo=0; if (!hz) { QueryPerformanceFrequency( reinterpret_cast( &hz ) ); QueryPerformanceCounter( reinterpret_cast( &hzo ) ); } UInt64 t; QueryPerformanceCounter( reinterpret_cast( &t ) ); return ((t-hzo)*1000000)/hz; } #else UInt64 getCurrentTicks() { timeval t; gettimeofday(&t,CATCH_NULL); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif } void Timer::start() { m_ticks = getCurrentTicks(); } unsigned int Timer::getElapsedMicroseconds() const { return static_cast(getCurrentTicks() - m_ticks); } unsigned int Timer::getElapsedMilliseconds() const { return static_cast(getElapsedMicroseconds()/1000); } double Timer::getElapsedSeconds() const { return getElapsedMicroseconds()/1000000.0; } } // namespace Catch #ifdef __clang__ #pragma clang diagnostic pop #endif // #included from: catch_common.hpp #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED #include #include namespace Catch { bool startsWith( std::string const& s, std::string const& prefix ) { return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); } bool startsWith( std::string const& s, char prefix ) { return !s.empty() && s[0] == prefix; } bool endsWith( std::string const& s, std::string const& suffix ) { return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); } bool endsWith( std::string const& s, char suffix ) { return !s.empty() && s[s.size()-1] == suffix; } bool contains( std::string const& s, std::string const& infix ) { return s.find( infix ) != std::string::npos; } char toLowerCh(char c) { return static_cast( std::tolower( c ) ); } void toLowerInPlace( std::string& s ) { std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); } std::string toLower( std::string const& s ) { std::string lc = s; toLowerInPlace( lc ); return lc; } std::string trim( std::string const& str ) { static char const* whitespaceChars = "\n\r\t "; std::string::size_type start = str.find_first_not_of( whitespaceChars ); std::string::size_type end = str.find_last_not_of( whitespaceChars ); return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); } bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { bool replaced = false; std::size_t i = str.find( replaceThis ); while( i != std::string::npos ) { replaced = true; str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); if( i < str.size()-withThis.size() ) i = str.find( replaceThis, i+withThis.size() ); else i = std::string::npos; } return replaced; } pluralise::pluralise( std::size_t count, std::string const& label ) : m_count( count ), m_label( label ) {} std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { os << pluraliser.m_count << ' ' << pluraliser.m_label; if( pluraliser.m_count != 1 ) os << 's'; return os; } SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) : file( _file ), line( _line ) {} bool SourceLineInfo::empty() const { return file[0] == '\0'; } bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); } bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); } void seedRng( IConfig const& config ) { if( config.rngSeed() != 0 ) std::srand( config.rngSeed() ); } unsigned int rngSeed() { return getCurrentContext().getConfig()->rngSeed(); } std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << '(' << info.line << ')'; #else os << info.file << ':' << info.line; #endif return os; } void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { std::ostringstream oss; oss << locationInfo << ": Internal Catch error: '" << message << '\''; if( alwaysTrue() ) throw std::logic_error( oss.str() ); } } // #included from: catch_section.hpp #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED namespace Catch { SectionInfo::SectionInfo ( SourceLineInfo const& _lineInfo, std::string const& _name, std::string const& _description ) : name( _name ), description( _description ), lineInfo( _lineInfo ) {} Section::Section( SectionInfo const& info ) : m_info( info ), m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) { m_timer.start(); } Section::~Section() { if( m_sectionIncluded ) { SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); if( std::uncaught_exception() ) getResultCapture().sectionEndedEarly( endInfo ); else getResultCapture().sectionEnded( endInfo ); } } // This indicates whether the section should be executed or not Section::operator bool() const { return m_sectionIncluded; } } // end namespace Catch // #included from: catch_debugger.hpp #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED #ifdef CATCH_PLATFORM_MAC #include #include #include #include #include namespace Catch{ // The following function is taken directly from the following technical note: // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html // Returns true if the current process is being debugged (either // running under the debugger or has a debugger attached post facto). bool isDebuggerActive(){ int mib[4]; struct kinfo_proc info; size_t size; // Initialize the flags so that, if sysctl fails for some bizarre // reason, we get a predictable result. info.kp_proc.p_flag = 0; // Initialize mib, which tells sysctl the info we want, in this case // we're looking for information about a specific process ID. mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = getpid(); // Call sysctl. size = sizeof(info); if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } // We're being debugged if the P_TRACED flag is set. return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); } } // namespace Catch #elif defined(CATCH_PLATFORM_LINUX) #include #include namespace Catch{ // The standard POSIX way of detecting a debugger is to attempt to // ptrace() the process, but this needs to be done from a child and not // this process itself to still allow attaching to this process later // if wanted, so is rather heavy. Under Linux we have the PID of the // "debugger" (which doesn't need to be gdb, of course, it could also // be strace, for example) in /proc/$PID/status, so just get it from // there instead. bool isDebuggerActive(){ // Libstdc++ has a bug, where std::ifstream sets errno to 0 // This way our users can properly assert over errno values ErrnoGuard guard; std::ifstream in("/proc/self/status"); for( std::string line; std::getline(in, line); ) { static const int PREFIX_LEN = 11; if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { // We're traced if the PID is not 0 and no other PID starts // with 0 digit, so it's enough to check for just a single // character. return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; } } return false; } } // namespace Catch #elif defined(_MSC_VER) extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); namespace Catch { bool isDebuggerActive() { return IsDebuggerPresent() != 0; } } #elif defined(__MINGW32__) extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); namespace Catch { bool isDebuggerActive() { return IsDebuggerPresent() != 0; } } #else namespace Catch { inline bool isDebuggerActive() { return false; } } #endif // Platform #ifdef CATCH_PLATFORM_WINDOWS namespace Catch { void writeToDebugConsole( std::string const& text ) { ::OutputDebugStringA( text.c_str() ); } } #else namespace Catch { void writeToDebugConsole( std::string const& text ) { // !TBD: Need a version for Mac/ XCode and other IDEs Catch::cout() << text; } } #endif // Platform // #included from: catch_tostring.hpp #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED namespace Catch { namespace Detail { const std::string unprintableString = "{?}"; namespace { const int hexThreshold = 255; struct Endianness { enum Arch { Big, Little }; static Arch which() { union _{ int asInt; char asChar[sizeof (int)]; } u; u.asInt = 1; return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; } }; } std::string rawMemoryToString( const void *object, std::size_t size ) { // Reverse order for little endian architectures int i = 0, end = static_cast( size ), inc = 1; if( Endianness::which() == Endianness::Little ) { i = end-1; end = inc = -1; } unsigned char const *bytes = static_cast(object); std::ostringstream os; os << "0x" << std::setfill('0') << std::hex; for( ; i != end; i += inc ) os << std::setw(2) << static_cast(bytes[i]); return os.str(); } } std::string toString( std::string const& value ) { std::string s = value; if( getCurrentContext().getConfig()->showInvisibles() ) { for(size_t i = 0; i < s.size(); ++i ) { std::string subs; switch( s[i] ) { case '\n': subs = "\\n"; break; case '\t': subs = "\\t"; break; default: break; } if( !subs.empty() ) { s = s.substr( 0, i ) + subs + s.substr( i+1 ); ++i; } } } return '"' + s + '"'; } std::string toString( std::wstring const& value ) { std::string s; s.reserve( value.size() ); for(size_t i = 0; i < value.size(); ++i ) s += value[i] <= 0xff ? static_cast( value[i] ) : '?'; return Catch::toString( s ); } std::string toString( const char* const value ) { return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); } std::string toString( char* const value ) { return Catch::toString( static_cast( value ) ); } std::string toString( const wchar_t* const value ) { return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); } std::string toString( wchar_t* const value ) { return Catch::toString( static_cast( value ) ); } std::string toString( int value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } std::string toString( unsigned long value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } std::string toString( unsigned int value ) { return Catch::toString( static_cast( value ) ); } template std::string fpToString( T value, int precision ) { std::ostringstream oss; oss << std::setprecision( precision ) << std::fixed << value; std::string d = oss.str(); std::size_t i = d.find_last_not_of( '0' ); if( i != std::string::npos && i != d.size()-1 ) { if( d[i] == '.' ) i++; d = d.substr( 0, i+1 ); } return d; } std::string toString( const double value ) { return fpToString( value, 10 ); } std::string toString( const float value ) { return fpToString( value, 5 ) + 'f'; } std::string toString( bool value ) { return value ? "true" : "false"; } std::string toString( char value ) { if ( value == '\r' ) return "'\\r'"; if ( value == '\f' ) return "'\\f'"; if ( value == '\n' ) return "'\\n'"; if ( value == '\t' ) return "'\\t'"; if ( '\0' <= value && value < ' ' ) return toString( static_cast( value ) ); char chstr[] = "' '"; chstr[1] = value; return chstr; } std::string toString( signed char value ) { return toString( static_cast( value ) ); } std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } #ifdef CATCH_CONFIG_CPP11_LONG_LONG std::string toString( long long value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } std::string toString( unsigned long long value ) { std::ostringstream oss; oss << value; if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ')'; return oss.str(); } #endif #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; } #endif #ifdef __OBJC__ std::string toString( NSString const * const& nsstring ) { if( !nsstring ) return "nil"; return "@" + toString([nsstring UTF8String]); } std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) { if( !nsstring ) return "nil"; return "@" + toString([nsstring UTF8String]); } std::string toString( NSObject* const& nsObject ) { return toString( [nsObject description] ); } #endif } // end namespace Catch // #included from: catch_result_builder.hpp #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED namespace Catch { std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { return secondArg.empty() || secondArg == "\"\"" ? capturedExpression : capturedExpression + ", " + secondArg; } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, ResultDisposition::Flags resultDisposition, char const* secondArg ) : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), m_shouldDebugBreak( false ), m_shouldThrow( false ), m_guardException( false ) {} ResultBuilder::~ResultBuilder() { #if defined(CATCH_CONFIG_FAST_COMPILE) if ( m_guardException ) { m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; captureResult( ResultWas::ThrewException ); getCurrentContext().getResultCapture()->exceptionEarlyReported(); } #endif } ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { m_data.resultType = result; return *this; } ResultBuilder& ResultBuilder::setResultType( bool result ) { m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; return *this; } void ResultBuilder::endExpression( DecomposedExpression const& expr ) { AssertionResult result = build( expr ); handleResult( result ); } void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { m_assertionInfo.resultDisposition = resultDisposition; m_stream.oss << Catch::translateActiveException(); captureResult( ResultWas::ThrewException ); } void ResultBuilder::captureResult( ResultWas::OfType resultType ) { setResultType( resultType ); captureExpression(); } void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { if( expectedMessage.empty() ) captureExpectedException( Matchers::Impl::MatchAllOf() ); else captureExpectedException( Matchers::Equals( expectedMessage ) ); } void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase const& matcher ) { assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; data.reconstructedExpression = m_assertionInfo.capturedExpression; std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; data.reconstructedExpression = actualMessage; } AssertionResult result( m_assertionInfo, data ); handleResult( result ); } void ResultBuilder::captureExpression() { AssertionResult result = build(); handleResult( result ); } void ResultBuilder::handleResult( AssertionResult const& result ) { getResultCapture().assertionEnded( result ); if( !result.isOk() ) { if( getCurrentContext().getConfig()->shouldDebugBreak() ) m_shouldDebugBreak = true; if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) m_shouldThrow = true; } } void ResultBuilder::react() { #if defined(CATCH_CONFIG_FAST_COMPILE) if (m_shouldDebugBreak) { /////////////////////////////////////////////////////////////////// // To inspect the state during test, you need to go one level up the callstack // To go back to the test and change execution, jump over the throw statement /////////////////////////////////////////////////////////////////// CATCH_BREAK_INTO_DEBUGGER(); } #endif if( m_shouldThrow ) throw Catch::TestFailureException(); } bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } AssertionResult ResultBuilder::build() const { return build( *this ); } // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, // a temporary DecomposedExpression, which in turn holds references to // operands, possibly temporary as well. // It should immediately be passed to handleResult; if the expression // needs to be reported, its string expansion must be composed before // the temporaries are destroyed. AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const { assert( m_data.resultType != ResultWas::Unknown ); AssertionResultData data = m_data; // Flip bool results if FalseTest flag is set if( isFalseTest( m_assertionInfo.resultDisposition ) ) { data.negate( expr.isBinaryExpression() ); } data.message = m_stream.oss.str(); data.decomposedExpression = &expr; // for lazy reconstruction return AssertionResult( m_assertionInfo, data ); } void ResultBuilder::reconstructExpression( std::string& dest ) const { dest = m_assertionInfo.capturedExpression; } void ResultBuilder::setExceptionGuard() { m_guardException = true; } void ResultBuilder::unsetExceptionGuard() { m_guardException = false; } } // end namespace Catch // #included from: catch_tag_alias_registry.hpp #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED namespace Catch { TagAliasRegistry::~TagAliasRegistry() {} Option TagAliasRegistry::find( std::string const& alias ) const { std::map::const_iterator it = m_registry.find( alias ); if( it != m_registry.end() ) return it->second; else return Option(); } std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { std::string expandedTestSpec = unexpandedTestSpec; for( std::map::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); it != itEnd; ++it ) { std::size_t pos = expandedTestSpec.find( it->first ); if( pos != std::string::npos ) { expandedTestSpec = expandedTestSpec.substr( 0, pos ) + it->second.tag + expandedTestSpec.substr( pos + it->first.size() ); } } return expandedTestSpec; } void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { std::ostringstream oss; oss << Colour( Colour::Red ) << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << Colour( Colour::FileName ) << lineInfo << '\n'; throw std::domain_error( oss.str().c_str() ); } if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { std::ostringstream oss; oss << Colour( Colour::Red ) << "error: tag alias, \"" << alias << "\" already registered.\n" << "\tFirst seen at " << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' << Colour( Colour::Red ) << "\tRedefined at " << Colour( Colour::FileName) << lineInfo << '\n'; throw std::domain_error( oss.str().c_str() ); } } ITagAliasRegistry::~ITagAliasRegistry() {} ITagAliasRegistry const& ITagAliasRegistry::get() { return getRegistryHub().getTagAliasRegistry(); } RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); } } // end namespace Catch // #included from: catch_matchers_string.hpp namespace Catch { namespace Matchers { namespace StdString { CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_str( adjustString( str ) ) {} std::string CasedString::adjustString( std::string const& str ) const { return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } std::string CasedString::caseSensitivitySuffix() const { return m_caseSensitivity == CaseSensitive::No ? " (case insensitive)" : std::string(); } StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) : m_comparator( comparator ), m_operation( operation ) { } std::string StringMatcherBase::describe() const { std::string description; description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + m_comparator.caseSensitivitySuffix().size()); description += m_operation; description += ": \""; description += m_comparator.m_str; description += "\""; description += m_comparator.caseSensitivitySuffix(); return description; } EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} bool EqualsMatcher::match( std::string const& source ) const { return m_comparator.adjustString( source ) == m_comparator.m_str; } ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} bool ContainsMatcher::match( std::string const& source ) const { return contains( m_comparator.adjustString( source ), m_comparator.m_str ); } StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} bool StartsWithMatcher::match( std::string const& source ) const { return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); } EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} bool EndsWithMatcher::match( std::string const& source ) const { return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); } } // namespace StdString StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); } StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); } StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); } StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); } } // namespace Matchers } // namespace Catch // #included from: ../reporters/catch_reporter_multi.hpp #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED namespace Catch { class MultipleReporters : public SharedImpl { typedef std::vector > Reporters; Reporters m_reporters; public: void add( Ptr const& reporter ) { m_reporters.push_back( reporter ); } public: // IStreamingReporter virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporters[0]->getPreferences(); } virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->noMatchingTestCases( spec ); } virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testRunStarting( testRunInfo ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testGroupStarting( groupInfo ); } virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testCaseStarting( testInfo ); } virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->sectionStarting( sectionInfo ); } virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->assertionStarting( assertionInfo ); } // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { bool clearBuffer = false; for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) clearBuffer |= (*it)->assertionEnded( assertionStats ); return clearBuffer; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->sectionEnded( sectionStats ); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testCaseEnded( testCaseStats ); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testGroupEnded( testGroupStats ); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->testRunEnded( testRunStats ); } virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; ++it ) (*it)->skipTest( testInfo ); } virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { return this; } }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { Ptr resultingReporter; if( existingReporter ) { MultipleReporters* multi = existingReporter->tryAsMulti(); if( !multi ) { multi = new MultipleReporters; resultingReporter = Ptr( multi ); if( existingReporter ) multi->add( existingReporter ); } else resultingReporter = existingReporter; multi->add( additionalReporter ); } else resultingReporter = additionalReporter; return resultingReporter; } } // end namespace Catch // #included from: ../reporters/catch_reporter_xml.hpp #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED // #included from: catch_reporter_bases.hpp #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #include #include #include #include namespace Catch { namespace { // Because formatting using c++ streams is stateful, drop down to C is required // Alternatively we could use stringstream, but its performance is... not good. std::string getFormattedDuration( double duration ) { // Max exponent + 1 is required to represent the whole part // + 1 for decimal point // + 3 for the 3 decimal places // + 1 for null terminator const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; char buffer[maxDoubleSize]; // Save previous errno, to prevent sprintf from overwriting it ErrnoGuard guard; #ifdef _MSC_VER sprintf_s(buffer, "%.3f", duration); #else sprintf(buffer, "%.3f", duration); #endif return std::string(buffer); } } struct StreamingReporterBase : SharedImpl { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; } virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporterPrefs; } virtual ~StreamingReporterBase() CATCH_OVERRIDE; virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { currentTestRunInfo = _testRunInfo; } virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { currentGroupInfo = _groupInfo; } virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { currentTestCaseInfo = _testInfo; } virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_sectionStack.push_back( _sectionInfo ); } virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { m_sectionStack.pop_back(); } virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); } virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { currentGroupInfo.reset(); } virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } Ptr m_config; std::ostream& stream; LazyStat currentTestRunInfo; LazyStat currentGroupInfo; LazyStat currentTestCaseInfo; std::vector m_sectionStack; ReporterPreferences m_reporterPrefs; }; struct CumulativeReporterBase : SharedImpl { template struct Node : SharedImpl<> { explicit Node( T const& _value ) : value( _value ) {} virtual ~Node() {} typedef std::vector > ChildNodes; T value; ChildNodes children; }; struct SectionNode : SharedImpl<> { explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} virtual ~SectionNode(); bool operator == ( SectionNode const& other ) const { return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; } bool operator == ( Ptr const& other ) const { return operator==( *other ); } SectionStats stats; typedef std::vector > ChildSections; typedef std::vector Assertions; ChildSections childSections; Assertions assertions; std::string stdOut; std::string stdErr; }; struct BySectionInfo { BySectionInfo( SectionInfo const& other ) : m_other( other ) {} BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} bool operator() ( Ptr const& node ) const { return node->stats.sectionInfo.lineInfo == m_other.lineInfo; } private: void operator=( BySectionInfo const& ); SectionInfo const& m_other; }; typedef Node TestCaseNode; typedef Node TestGroupNode; typedef Node TestRunNode; CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) { m_reporterPrefs.shouldRedirectStdOut = false; } ~CumulativeReporterBase(); virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporterPrefs; } virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { if( !m_rootSection ) m_rootSection = new SectionNode( incompleteStats ); node = m_rootSection; } else { SectionNode& parentNode = *m_sectionStack.back(); SectionNode::ChildSections::const_iterator it = std::find_if( parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo( sectionInfo ) ); if( it == parentNode.childSections.end() ) { node = new SectionNode( incompleteStats ); parentNode.childSections.push_back( node ); } else node = *it; } m_sectionStack.push_back( node ); m_deepestSection = node; } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& sectionNode = *m_sectionStack.back(); sectionNode.assertions.push_back( assertionStats ); // AssertionResult holds a pointer to a temporary DecomposedExpression, // which getExpandedExpression() calls to build the expression string. // Our section stack copy of the assertionResult will likely outlive the // temporary, so it must be expanded or discarded now to avoid calling // a destroyed object later. prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); return true; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); m_testCases.push_back( node ); m_rootSection.reset(); assert( m_deepestSection ); m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); testRunEndedCumulative(); } virtual void testRunEndedCumulative() = 0; virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} virtual void prepareExpandedExpression( AssertionResult& result ) const { if( result.isOk() ) result.discardDecomposedExpression(); else result.expandDecomposedExpression(); } Ptr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; std::vector > m_testCases; std::vector > m_testGroups; std::vector > m_testRuns; Ptr m_rootSection; Ptr m_deepestSection; std::vector > m_sectionStack; ReporterPreferences m_reporterPrefs; }; template char const* getLineOfChars() { static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; if( !*line ) { std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; } return line; } struct TestEventListenerBase : StreamingReporterBase { TestEventListenerBase( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { return false; } }; } // end namespace Catch // #included from: ../internal/catch_reporter_registrars.hpp #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED namespace Catch { template class LegacyReporterRegistrar { class ReporterFactory : public IReporterFactory { virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new LegacyReporterAdapter( new T( config ) ); } virtual std::string getDescription() const { return T::getDescription(); } }; public: LegacyReporterRegistrar( std::string const& name ) { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; template class ReporterRegistrar { class ReporterFactory : public SharedImpl { // *** Please Note ***: // - If you end up here looking at a compiler error because it's trying to register // your custom reporter class be aware that the native reporter interface has changed // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. // However please consider updating to the new interface as the old one is now // deprecated and will probably be removed quite soon! // Please contact me via github if you have any questions at all about this. // In fact, ideally, please contact me anyway to let me know you've hit this - as I have // no idea who is actually using custom reporters at all (possibly no-one!). // The new interface is designed to minimise exposure to interface changes in the future. virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); } virtual std::string getDescription() const { return T::getDescription(); } }; public: ReporterRegistrar( std::string const& name ) { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; template class ListenerRegistrar { class ListenerFactory : public SharedImpl { virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); } virtual std::string getDescription() const { return std::string(); } }; public: ListenerRegistrar() { getMutableRegistryHub().registerListener( new ListenerFactory() ); } }; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } // Deprecated - use the form without INTERNAL_ #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } #define CATCH_REGISTER_LISTENER( listenerType ) \ namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } // #included from: ../internal/catch_xmlwriter.hpp #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #include #include #include #include namespace Catch { class XmlEncode { public: enum ForWhat { ForTextNodes, ForAttributes }; XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) : m_str( str ), m_forWhat( forWhat ) {} void encodeTo( std::ostream& os ) const { // Apostrophe escaping not necessary if we always use " to write attributes // (see: http://www.w3.org/TR/xml/#syntax) for( std::size_t i = 0; i < m_str.size(); ++ i ) { char c = m_str[i]; switch( c ) { case '<': os << "<"; break; case '&': os << "&"; break; case '>': // See: http://www.w3.org/TR/xml/#syntax if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) os << ">"; else os << c; break; case '\"': if( m_forWhat == ForAttributes ) os << """; else os << c; break; default: // Escape control chars - based on contribution by @espenalb in PR #465 and // by @mrpi PR #588 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast( c ); } else os << c; } } } friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { xmlEncode.encodeTo( os ); return os; } private: std::string m_str; ForWhat m_forWhat; }; class XmlWriter { public: class ScopedElement { public: ScopedElement( XmlWriter* writer ) : m_writer( writer ) {} ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ other.m_writer = CATCH_NULL; } ~ScopedElement() { if( m_writer ) m_writer->endElement(); } ScopedElement& writeText( std::string const& text, bool indent = true ) { m_writer->writeText( text, indent ); return *this; } template ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { m_writer->writeAttribute( name, attribute ); return *this; } private: mutable XmlWriter* m_writer; }; XmlWriter() : m_tagIsOpen( false ), m_needsNewline( false ), m_os( Catch::cout() ) { writeDeclaration(); } XmlWriter( std::ostream& os ) : m_tagIsOpen( false ), m_needsNewline( false ), m_os( os ) { writeDeclaration(); } ~XmlWriter() { while( !m_tags.empty() ) endElement(); } XmlWriter& startElement( std::string const& name ) { ensureTagClosed(); newlineIfNecessary(); m_os << m_indent << '<' << name; m_tags.push_back( name ); m_indent += " "; m_tagIsOpen = true; return *this; } ScopedElement scopedElement( std::string const& name ) { ScopedElement scoped( this ); startElement( name ); return scoped; } XmlWriter& endElement() { newlineIfNecessary(); m_indent = m_indent.substr( 0, m_indent.size()-2 ); if( m_tagIsOpen ) { m_os << "/>"; m_tagIsOpen = false; } else { m_os << m_indent << ""; } m_os << std::endl; m_tags.pop_back(); return *this; } XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { if( !name.empty() && !attribute.empty() ) m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; return *this; } XmlWriter& writeAttribute( std::string const& name, bool attribute ) { m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; return *this; } template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { std::ostringstream oss; oss << attribute; return writeAttribute( name, oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { if( !text.empty() ){ bool tagWasOpen = m_tagIsOpen; ensureTagClosed(); if( tagWasOpen && indent ) m_os << m_indent; m_os << XmlEncode( text ); m_needsNewline = true; } return *this; } XmlWriter& writeComment( std::string const& text ) { ensureTagClosed(); m_os << m_indent << ""; m_needsNewline = true; return *this; } void writeStylesheetRef( std::string const& url ) { m_os << "\n"; } XmlWriter& writeBlankLine() { ensureTagClosed(); m_os << '\n'; return *this; } void ensureTagClosed() { if( m_tagIsOpen ) { m_os << ">" << std::endl; m_tagIsOpen = false; } } private: XmlWriter( XmlWriter const& ); void operator=( XmlWriter const& ); void writeDeclaration() { m_os << "\n"; } void newlineIfNecessary() { if( m_needsNewline ) { m_os << std::endl; m_needsNewline = false; } } bool m_tagIsOpen; bool m_needsNewline; std::vector m_tags; std::string m_indent; std::ostream& m_os; }; } // #included from: catch_reenable_warnings.h #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(pop) # else # pragma clang diagnostic pop # endif #elif defined __GNUC__ # pragma GCC diagnostic pop #endif namespace Catch { class XmlReporter : public StreamingReporterBase { public: XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_xml(_config.stream()), m_sectionDepth( 0 ) { m_reporterPrefs.shouldRedirectStdOut = true; } virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as an XML document"; } virtual std::string getStylesheetRef() const { return std::string(); } void writeSourceInfo( SourceLineInfo const& sourceInfo ) { m_xml .writeAttribute( "filename", sourceInfo.file ) .writeAttribute( "line", sourceInfo.line ); } public: // StreamingReporterBase virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { StreamingReporterBase::noMatchingTestCases( s ); } virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); std::string stylesheetRef = getStylesheetRef(); if( !stylesheetRef.empty() ) m_xml.writeStylesheetRef( stylesheetRef ); m_xml.startElement( "Catch" ); if( !m_config->name().empty() ) m_xml.writeAttribute( "name", m_config->name() ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ) .writeAttribute( "name", trim( testInfo.name ) ) .writeAttribute( "description", testInfo.description ) .writeAttribute( "tags", testInfo.tagsAsString ); writeSourceInfo( testInfo.lineInfo ); if ( m_config->showDurations() == ShowDurations::Always ) m_testCaseTimer.start(); m_xml.ensureTagClosed(); } virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) .writeAttribute( "name", trim( sectionInfo.name ) ) .writeAttribute( "description", sectionInfo.description ); writeSourceInfo( sectionInfo.lineInfo ); m_xml.ensureTagClosed(); } } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); if( includeResults ) { // Print any info messages in tags. for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); it != itEnd; ++it ) { if( it->type == ResultWas::Info ) { m_xml.scopedElement( "Info" ) .writeText( it->message ); } else if ( it->type == ResultWas::Warning ) { m_xml.scopedElement( "Warning" ) .writeText( it->message ); } } } // Drop out if result was successful but we're not printing them. if( !includeResults && result.getResultType() != ResultWas::Warning ) return true; // Print the expression if there is one. if( result.hasExpression() ) { m_xml.startElement( "Expression" ) .writeAttribute( "success", result.succeeded() ) .writeAttribute( "type", result.getTestMacroName() ); writeSourceInfo( result.getSourceInfo() ); m_xml.scopedElement( "Original" ) .writeText( result.getExpression() ); m_xml.scopedElement( "Expanded" ) .writeText( result.getExpandedExpression() ); } // And... Print a result applicable to each result type. switch( result.getResultType() ) { case ResultWas::ThrewException: m_xml.startElement( "Exception" ); writeSourceInfo( result.getSourceInfo() ); m_xml.writeText( result.getMessage() ); m_xml.endElement(); break; case ResultWas::FatalErrorCondition: m_xml.startElement( "FatalErrorCondition" ); writeSourceInfo( result.getSourceInfo() ); m_xml.writeText( result.getMessage() ); m_xml.endElement(); break; case ResultWas::Info: m_xml.scopedElement( "Info" ) .writeText( result.getMessage() ); break; case ResultWas::Warning: // Warning will already have been written break; case ResultWas::ExplicitFailure: m_xml.startElement( "Failure" ); writeSourceInfo( result.getSourceInfo() ); m_xml.writeText( result.getMessage() ); m_xml.endElement(); break; default: break; } if( result.hasExpression() ) m_xml.endElement(); return true; } virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); e.writeAttribute( "successes", sectionStats.assertions.passed ); e.writeAttribute( "failures", sectionStats.assertions.failed ); e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); if ( m_config->showDurations() == ShowDurations::Always ) e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); m_xml.endElement(); } } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); if ( m_config->showDurations() == ShowDurations::Always ) e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); if( !testCaseStats.stdOut.empty() ) m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); if( !testCaseStats.stdErr.empty() ) m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); m_xml.endElement(); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); m_xml.endElement(); } virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) .writeAttribute( "failures", testRunStats.totals.assertions.failed ) .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); m_xml.endElement(); } private: Timer m_testCaseTimer; XmlWriter m_xml; int m_sectionDepth; }; INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) } // end namespace Catch // #included from: ../reporters/catch_reporter_junit.hpp #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED #include namespace Catch { namespace { std::string getCurrentTimestamp() { // Beware, this is not reentrant because of backward compatibility issues // Also, UTC only, again because of backward compatibility (%z is C++11) time_t rawtime; std::time(&rawtime); const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); #ifdef _MSC_VER std::tm timeInfo = {}; gmtime_s(&timeInfo, &rawtime); #else std::tm* timeInfo; timeInfo = std::gmtime(&rawtime); #endif char timeStamp[timeStampSize]; const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; #ifdef _MSC_VER std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); #else std::strftime(timeStamp, timeStampSize, fmt, timeInfo); #endif return std::string(timeStamp); } } class JunitReporter : public CumulativeReporterBase { public: JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ), m_okToFail( false ) { m_reporterPrefs.shouldRedirectStdOut = true; } virtual ~JunitReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); unexpectedExceptions = 0; CumulativeReporterBase::testGroupStarting( groupInfo ); } virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { m_okToFail = testCaseInfo.okToFail(); } virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } virtual void testRunEndedCumulative() CATCH_OVERRIDE { xml.endElement(); } void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); TestGroupStats const& stats = groupNode.value; xml.writeAttribute( "name", stats.groupInfo.name ); xml.writeAttribute( "errors", unexpectedExceptions ); xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); xml.writeAttribute( "tests", stats.totals.assertions.total() ); xml.writeAttribute( "hostname", "tbd" ); // !TBD if( m_config->showDurations() == ShowDurations::Never ) xml.writeAttribute( "time", "" ); else xml.writeAttribute( "time", suiteTime ); xml.writeAttribute( "timestamp", getCurrentTimestamp() ); // Write test cases for( TestGroupNode::ChildNodes::const_iterator it = groupNode.children.begin(), itEnd = groupNode.children.end(); it != itEnd; ++it ) writeTestCase( **it ); xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); } void writeTestCase( TestCaseNode const& testCaseNode ) { TestCaseStats const& stats = testCaseNode.value; // All test cases have exactly one section - which represents the // test case itself. That section may have 0-n nested sections assert( testCaseNode.children.size() == 1 ); SectionNode const& rootSection = *testCaseNode.children.front(); std::string className = stats.testInfo.className; if( className.empty() ) { if( rootSection.childSections.empty() ) className = "global"; } writeSection( className, "", rootSection ); } void writeSection( std::string const& className, std::string const& rootName, SectionNode const& sectionNode ) { std::string name = trim( sectionNode.stats.sectionInfo.name ); if( !rootName.empty() ) name = rootName + '/' + name; if( !sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty() ) { XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); if( className.empty() ) { xml.writeAttribute( "classname", name ); xml.writeAttribute( "name", "root" ); } else { xml.writeAttribute( "classname", className ); xml.writeAttribute( "name", name ); } xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); writeAssertions( sectionNode ); if( !sectionNode.stdOut.empty() ) xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); if( !sectionNode.stdErr.empty() ) xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); } for( SectionNode::ChildSections::const_iterator it = sectionNode.childSections.begin(), itEnd = sectionNode.childSections.end(); it != itEnd; ++it ) if( className.empty() ) writeSection( name, "", **it ); else writeSection( className, name, **it ); } void writeAssertions( SectionNode const& sectionNode ) { for( SectionNode::Assertions::const_iterator it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); it != itEnd; ++it ) writeAssertion( *it ); } void writeAssertion( AssertionStats const& stats ) { AssertionResult const& result = stats.assertionResult; if( !result.isOk() ) { std::string elementName; switch( result.getResultType() ) { case ResultWas::ThrewException: case ResultWas::FatalErrorCondition: elementName = "error"; break; case ResultWas::ExplicitFailure: elementName = "failure"; break; case ResultWas::ExpressionFailed: elementName = "failure"; break; case ResultWas::DidntThrowException: elementName = "failure"; break; // We should never see these here: case ResultWas::Info: case ResultWas::Warning: case ResultWas::Ok: case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: elementName = "internalError"; break; } XmlWriter::ScopedElement e = xml.scopedElement( elementName ); xml.writeAttribute( "message", result.getExpandedExpression() ); xml.writeAttribute( "type", result.getTestMacroName() ); std::ostringstream oss; if( !result.getMessage().empty() ) oss << result.getMessage() << '\n'; for( std::vector::const_iterator it = stats.infoMessages.begin(), itEnd = stats.infoMessages.end(); it != itEnd; ++it ) if( it->type == ResultWas::Info ) oss << it->message << '\n'; oss << "at " << result.getSourceInfo(); xml.writeText( oss.str(), false ); } } XmlWriter xml; Timer suiteTimer; std::ostringstream stdOutForSuite; std::ostringstream stdErrForSuite; unsigned int unexpectedExceptions; bool m_okToFail; }; INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch // #included from: ../reporters/catch_reporter_console.hpp #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED #include #include namespace Catch { struct ConsoleReporter : StreamingReporterBase { ConsoleReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_headerPrinted( false ) {} virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << '\'' << std::endl; } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); // Drop out if result was successful but we're not printing them. if( !includeResults && result.getResultType() != ResultWas::Warning ) return false; lazyPrint(); AssertionPrinter printer( stream, _assertionStats, includeResults ); printer.print(); stream << std::endl; return true; } virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); if( m_sectionStack.size() > 1 ) stream << "\nNo assertions in section"; else stream << "\nNo assertions in test case"; stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; } if( m_config->showDurations() == ShowDurations::Always ) { stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } if( m_headerPrinted ) { m_headerPrinted = false; } StreamingReporterBase::sectionEnded( _sectionStats ); } virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; printTotals( _testGroupStats.totals ); stream << '\n' << std::endl; } StreamingReporterBase::testGroupEnded( _testGroupStats ); } virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; StreamingReporterBase::testRunEnded( _testRunStats ); } private: class AssertionPrinter { void operator= ( AssertionPrinter const& ); public: AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ), stats( _stats ), result( _stats.assertionResult ), colour( Colour::None ), message( result.getMessage() ), messages( _stats.infoMessages ), printInfoMessages( _printInfoMessages ) { switch( result.getResultType() ) { case ResultWas::Ok: colour = Colour::Success; passOrFail = "PASSED"; //if( result.hasMessage() ) if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; if( _stats.infoMessages.size() > 1 ) messageLabel = "with messages"; break; case ResultWas::ExpressionFailed: if( result.isOk() ) { colour = Colour::Success; passOrFail = "FAILED - but was ok"; } else { colour = Colour::Error; passOrFail = "FAILED"; } if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; if( _stats.infoMessages.size() > 1 ) messageLabel = "with messages"; break; case ResultWas::ThrewException: colour = Colour::Error; passOrFail = "FAILED"; messageLabel = "due to unexpected exception with "; if (_stats.infoMessages.size() == 1) messageLabel += "message"; if (_stats.infoMessages.size() > 1) messageLabel += "messages"; break; case ResultWas::FatalErrorCondition: colour = Colour::Error; passOrFail = "FAILED"; messageLabel = "due to a fatal error condition"; break; case ResultWas::DidntThrowException: colour = Colour::Error; passOrFail = "FAILED"; messageLabel = "because no exception was thrown where one was expected"; break; case ResultWas::Info: messageLabel = "info"; break; case ResultWas::Warning: messageLabel = "warning"; break; case ResultWas::ExplicitFailure: passOrFail = "FAILED"; colour = Colour::Error; if( _stats.infoMessages.size() == 1 ) messageLabel = "explicitly with message"; if( _stats.infoMessages.size() > 1 ) messageLabel = "explicitly with messages"; break; // These cases are here to prevent compiler warnings case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: passOrFail = "** internal error **"; colour = Colour::Error; break; } } void print() const { printSourceInfo(); if( stats.totals.assertions.total() > 0 ) { if( result.isOk() ) stream << '\n'; printResultType(); printOriginalExpression(); printReconstructedExpression(); } else { stream << '\n'; } printMessage(); } private: void printResultType() const { if( !passOrFail.empty() ) { Colour colourGuard( colour ); stream << passOrFail << ":\n"; } } void printOriginalExpression() const { if( result.hasExpression() ) { Colour colourGuard( Colour::OriginalExpression ); stream << " "; stream << result.getExpressionInMacro(); stream << '\n'; } } void printReconstructedExpression() const { if( result.hasExpandedExpression() ) { stream << "with expansion:\n"; Colour colourGuard( Colour::ReconstructedExpression ); stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; } } void printMessage() const { if( !messageLabel.empty() ) stream << messageLabel << ':' << '\n'; for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); it != itEnd; ++it ) { // If this assertion is a warning ignore any INFO messages if( printInfoMessages || it->type != ResultWas::Info ) stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; } } void printSourceInfo() const { Colour colourGuard( Colour::FileName ); stream << result.getSourceInfo() << ": "; } std::ostream& stream; AssertionStats const& stats; AssertionResult const& result; Colour::Code colour; std::string passOrFail; std::string messageLabel; std::string message; std::vector messages; bool printInfoMessages; }; void lazyPrint() { if( !currentTestRunInfo.used ) lazyPrintRunInfo(); if( !currentGroupInfo.used ) lazyPrintGroupInfo(); if( !m_headerPrinted ) { printTestCaseAndSectionHeader(); m_headerPrinted = true; } } void lazyPrintRunInfo() { stream << '\n' << getLineOfChars<'~'>() << '\n'; Colour colour( Colour::SecondaryText ); stream << currentTestRunInfo->name << " is a Catch v" << libraryVersion() << " host application.\n" << "Run with -? for options\n\n"; if( m_config->rngSeed() != 0 ) stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; currentTestRunInfo.used = true; } void lazyPrintGroupInfo() { if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { printClosedHeader( "Group: " + currentGroupInfo->name ); currentGroupInfo.used = true; } } void printTestCaseAndSectionHeader() { assert( !m_sectionStack.empty() ); printOpenHeader( currentTestCaseInfo->name ); if( m_sectionStack.size() > 1 ) { Colour colourGuard( Colour::Headers ); std::vector::const_iterator it = m_sectionStack.begin()+1, // Skip first section (test case) itEnd = m_sectionStack.end(); for( ; it != itEnd; ++it ) printHeaderString( it->name, 2 ); } SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; if( !lineInfo.empty() ){ stream << getLineOfChars<'-'>() << '\n'; Colour colourGuard( Colour::FileName ); stream << lineInfo << '\n'; } stream << getLineOfChars<'.'>() << '\n' << std::endl; } void printClosedHeader( std::string const& _name ) { printOpenHeader( _name ); stream << getLineOfChars<'.'>() << '\n'; } void printOpenHeader( std::string const& _name ) { stream << getLineOfChars<'-'>() << '\n'; { Colour colourGuard( Colour::Headers ); printHeaderString( _name ); } } // if string has a : in first line will set indent to follow it on // subsequent lines void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { std::size_t i = _string.find( ": " ); if( i != std::string::npos ) i+=2; else i = 0; stream << Text( _string, TextAttributes() .setIndent( indent+i) .setInitialIndent( indent ) ) << '\n'; } struct SummaryColumn { SummaryColumn( std::string const& _label, Colour::Code _colour ) : label( _label ), colour( _colour ) {} SummaryColumn addRow( std::size_t count ) { std::ostringstream oss; oss << count; std::string row = oss.str(); for( std::vector::iterator it = rows.begin(); it != rows.end(); ++it ) { while( it->size() < row.size() ) *it = ' ' + *it; while( it->size() > row.size() ) row = ' ' + row; } rows.push_back( row ); return *this; } std::string label; Colour::Code colour; std::vector rows; }; void printTotals( Totals const& totals ) { if( totals.testCases.total() == 0 ) { stream << Colour( Colour::Warning ) << "No tests ran\n"; } else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { stream << Colour( Colour::ResultSuccess ) << "All tests passed"; stream << " (" << pluralise( totals.assertions.passed, "assertion" ) << " in " << pluralise( totals.testCases.passed, "test case" ) << ')' << '\n'; } else { std::vector columns; columns.push_back( SummaryColumn( "", Colour::None ) .addRow( totals.testCases.total() ) .addRow( totals.assertions.total() ) ); columns.push_back( SummaryColumn( "passed", Colour::Success ) .addRow( totals.testCases.passed ) .addRow( totals.assertions.passed ) ); columns.push_back( SummaryColumn( "failed", Colour::ResultError ) .addRow( totals.testCases.failed ) .addRow( totals.assertions.failed ) ); columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) .addRow( totals.testCases.failedButOk ) .addRow( totals.assertions.failedButOk ) ); printSummaryRow( "test cases", columns, 0 ); printSummaryRow( "assertions", columns, 1 ); } } void printSummaryRow( std::string const& label, std::vector const& cols, std::size_t row ) { for( std::vector::const_iterator it = cols.begin(); it != cols.end(); ++it ) { std::string value = it->rows[row]; if( it->label.empty() ) { stream << label << ": "; if( value != "0" ) stream << value; else stream << Colour( Colour::Warning ) << "- none -"; } else if( value != "0" ) { stream << Colour( Colour::LightGrey ) << " | "; stream << Colour( it->colour ) << value << ' ' << it->label; } } stream << '\n'; } static std::size_t makeRatio( std::size_t number, std::size_t total ) { std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; return ( ratio == 0 && number > 0 ) ? 1 : ratio; } static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { if( i > j && i > k ) return i; else if( j > k ) return j; else return k; } void printTotalsDivider( Totals const& totals ) { if( totals.testCases.total() > 0 ) { std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) findMax( failedRatio, failedButOkRatio, passedRatio )++; while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) findMax( failedRatio, failedButOkRatio, passedRatio )--; stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); if( totals.testCases.allPassed() ) stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); else stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); } else { stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); } stream << '\n'; } void printSummaryDivider() { stream << getLineOfChars<'-'>() << '\n'; } private: bool m_headerPrinted; }; INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) } // end namespace Catch // #included from: ../reporters/catch_reporter_compact.hpp #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED namespace Catch { struct CompactReporter : StreamingReporterBase { CompactReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} virtual ~CompactReporter(); static std::string getDescription() { return "Reports test results on a single line, suitable for IDEs"; } virtual ReporterPreferences getPreferences() const { ReporterPreferences prefs; prefs.shouldRedirectStdOut = false; return prefs; } virtual void noMatchingTestCases( std::string const& spec ) { stream << "No test cases matched '" << spec << '\'' << std::endl; } virtual void assertionStarting( AssertionInfo const& ) {} virtual bool assertionEnded( AssertionStats const& _assertionStats ) { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; // Drop out if result was successful and we're not printing those if( !m_config->includeSuccessfulResults() && result.isOk() ) { if( result.getResultType() != ResultWas::Warning ) return false; printInfoMessages = false; } AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); printer.print(); stream << std::endl; return true; } virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { if (m_config->showDurations() == ShowDurations::Always) { stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; } } virtual void testRunEnded( TestRunStats const& _testRunStats ) { printTotals( _testRunStats.totals ); stream << '\n' << std::endl; StreamingReporterBase::testRunEnded( _testRunStats ); } private: class AssertionPrinter { void operator= ( AssertionPrinter const& ); public: AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) : stream( _stream ) , stats( _stats ) , result( _stats.assertionResult ) , messages( _stats.infoMessages ) , itMessage( _stats.infoMessages.begin() ) , printInfoMessages( _printInfoMessages ) {} void print() { printSourceInfo(); itMessage = messages.begin(); switch( result.getResultType() ) { case ResultWas::Ok: printResultType( Colour::ResultSuccess, passedString() ); printOriginalExpression(); printReconstructedExpression(); if ( ! result.hasExpression() ) printRemainingMessages( Colour::None ); else printRemainingMessages(); break; case ResultWas::ExpressionFailed: if( result.isOk() ) printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); else printResultType( Colour::Error, failedString() ); printOriginalExpression(); printReconstructedExpression(); printRemainingMessages(); break; case ResultWas::ThrewException: printResultType( Colour::Error, failedString() ); printIssue( "unexpected exception with message:" ); printMessage(); printExpressionWas(); printRemainingMessages(); break; case ResultWas::FatalErrorCondition: printResultType( Colour::Error, failedString() ); printIssue( "fatal error condition with message:" ); printMessage(); printExpressionWas(); printRemainingMessages(); break; case ResultWas::DidntThrowException: printResultType( Colour::Error, failedString() ); printIssue( "expected exception, got none" ); printExpressionWas(); printRemainingMessages(); break; case ResultWas::Info: printResultType( Colour::None, "info" ); printMessage(); printRemainingMessages(); break; case ResultWas::Warning: printResultType( Colour::None, "warning" ); printMessage(); printRemainingMessages(); break; case ResultWas::ExplicitFailure: printResultType( Colour::Error, failedString() ); printIssue( "explicitly" ); printRemainingMessages( Colour::None ); break; // These cases are here to prevent compiler warnings case ResultWas::Unknown: case ResultWas::FailureBit: case ResultWas::Exception: printResultType( Colour::Error, "** internal error **" ); break; } } private: // Colour::LightGrey static Colour::Code dimColour() { return Colour::FileName; } #ifdef CATCH_PLATFORM_MAC static const char* failedString() { return "FAILED"; } static const char* passedString() { return "PASSED"; } #else static const char* failedString() { return "failed"; } static const char* passedString() { return "passed"; } #endif void printSourceInfo() const { Colour colourGuard( Colour::FileName ); stream << result.getSourceInfo() << ':'; } void printResultType( Colour::Code colour, std::string const& passOrFail ) const { if( !passOrFail.empty() ) { { Colour colourGuard( colour ); stream << ' ' << passOrFail; } stream << ':'; } } void printIssue( std::string const& issue ) const { stream << ' ' << issue; } void printExpressionWas() { if( result.hasExpression() ) { stream << ';'; { Colour colour( dimColour() ); stream << " expression was:"; } printOriginalExpression(); } } void printOriginalExpression() const { if( result.hasExpression() ) { stream << ' ' << result.getExpression(); } } void printReconstructedExpression() const { if( result.hasExpandedExpression() ) { { Colour colour( dimColour() ); stream << " for: "; } stream << result.getExpandedExpression(); } } void printMessage() { if ( itMessage != messages.end() ) { stream << " '" << itMessage->message << '\''; ++itMessage; } } void printRemainingMessages( Colour::Code colour = dimColour() ) { if ( itMessage == messages.end() ) return; // using messages.end() directly yields compilation error: std::vector::const_iterator itEnd = messages.end(); const std::size_t N = static_cast( std::distance( itMessage, itEnd ) ); { Colour colourGuard( colour ); stream << " with " << pluralise( N, "message" ) << ':'; } for(; itMessage != itEnd; ) { // If this assertion is a warning ignore any INFO messages if( printInfoMessages || itMessage->type != ResultWas::Info ) { stream << " '" << itMessage->message << '\''; if ( ++itMessage != itEnd ) { Colour colourGuard( dimColour() ); stream << " and"; } } } } private: std::ostream& stream; AssertionStats const& stats; AssertionResult const& result; std::vector messages; std::vector::const_iterator itMessage; bool printInfoMessages; }; // Colour, message variants: // - white: No tests ran. // - red: Failed [both/all] N test cases, failed [both/all] M assertions. // - white: Passed [both/all] N test cases (no assertions). // - red: Failed N tests cases, failed M assertions. // - green: Passed [both/all] N tests cases with M assertions. std::string bothOrAll( std::size_t count ) const { return count == 1 ? std::string() : count == 2 ? "both " : "all " ; } void printTotals( const Totals& totals ) const { if( totals.testCases.total() == 0 ) { stream << "No tests ran."; } else if( totals.testCases.failed == totals.testCases.total() ) { Colour colour( Colour::ResultError ); const std::string qualify_assertions_failed = totals.assertions.failed == totals.assertions.total() ? bothOrAll( totals.assertions.failed ) : std::string(); stream << "Failed " << bothOrAll( totals.testCases.failed ) << pluralise( totals.testCases.failed, "test case" ) << ", " "failed " << qualify_assertions_failed << pluralise( totals.assertions.failed, "assertion" ) << '.'; } else if( totals.assertions.total() == 0 ) { stream << "Passed " << bothOrAll( totals.testCases.total() ) << pluralise( totals.testCases.total(), "test case" ) << " (no assertions)."; } else if( totals.assertions.failed ) { Colour colour( Colour::ResultError ); stream << "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; } else { Colour colour( Colour::ResultSuccess ); stream << "Passed " << bothOrAll( totals.testCases.passed ) << pluralise( totals.testCases.passed, "test case" ) << " with " << pluralise( totals.assertions.passed, "assertion" ) << '.'; } } }; INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) } // end namespace Catch namespace Catch { // These are all here to avoid warnings about not having any out of line // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} IStream::~IStream() CATCH_NOEXCEPT {} FileStream::~FileStream() CATCH_NOEXCEPT {} CoutStream::~CoutStream() CATCH_NOEXCEPT {} DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} ITestCase::~ITestCase() {} ITestCaseRegistry::~ITestCaseRegistry() {} IRegistryHub::~IRegistryHub() {} IMutableRegistryHub::~IMutableRegistryHub() {} IExceptionTranslator::~IExceptionTranslator() {} IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} IReporter::~IReporter() {} IReporterFactory::~IReporterFactory() {} IReporterRegistry::~IReporterRegistry() {} IStreamingReporter::~IStreamingReporter() {} AssertionStats::~AssertionStats() {} SectionStats::~SectionStats() {} TestCaseStats::~TestCaseStats() {} TestGroupStats::~TestGroupStats() {} TestRunStats::~TestRunStats() {} CumulativeReporterBase::SectionNode::~SectionNode() {} CumulativeReporterBase::~CumulativeReporterBase() {} StreamingReporterBase::~StreamingReporterBase() {} ConsoleReporter::~ConsoleReporter() {} CompactReporter::~CompactReporter() {} IRunner::~IRunner() {} IMutableContext::~IMutableContext() {} IConfig::~IConfig() {} XmlReporter::~XmlReporter() {} JunitReporter::~JunitReporter() {} TestRegistry::~TestRegistry() {} FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} TestSpec::ExcludedPattern::~ExcludedPattern() {} Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} void Config::dummy() {} namespace TestCaseTracking { ITracker::~ITracker() {} TrackerBase::~TrackerBase() {} SectionTracker::~SectionTracker() {} IndexTracker::~IndexTracker() {} } } #ifdef __clang__ #pragma clang diagnostic pop #endif #endif #ifdef CATCH_CONFIG_MAIN // #included from: internal/catch_default_main.hpp #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED #ifndef __OBJC__ #if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) // Standard C/C++ Win32 Unicode wmain entry point extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { #else // Standard C/C++ main entry point int main (int argc, char * argv[]) { #endif int result = Catch::Session().run( argc, argv ); return ( result < 0xff ? result : 0xff ); } #else // __OBJC__ // Objective-C entry point int main (int argc, char * const argv[]) { #if !CATCH_ARC_ENABLED NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; #endif Catch::registerTestMethods(); int result = Catch::Session().run( argc, (char* const*)argv ); #if !CATCH_ARC_ENABLED [pool drain]; #endif return ( result < 0xff ? result : 0xff ); } #endif // __OBJC__ #endif #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED # undef CLARA_CONFIG_MAIN #endif ////// // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ #ifdef CATCH_CONFIG_PREFIX_ALL #if defined(CATCH_CONFIG_FAST_COMPILE) #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #else #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #endif #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #else #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #endif #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) #ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #else #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) #endif #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else #if defined(CATCH_CONFIG_FAST_COMPILE) #define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #else #define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) #endif #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) #define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #if defined(CATCH_CONFIG_FAST_COMPILE) #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #else #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) #endif #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) #ifdef CATCH_CONFIG_VARIADIC_MACROS #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #else #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) #endif #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) #endif #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) // "BDD-style" convenience wrappers #ifdef CATCH_CONFIG_VARIADIC_MACROS #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) #else #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED thrift-0.19.0/compiler/cpp/compiler.sln0000644000000000000000000000153614303740367020037 0ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compiler", "compiler.vcxproj", "{89975A1A-F799-4556-98B8-64E30AB39A90}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {89975A1A-F799-4556-98B8-64E30AB39A90}.Debug|Win32.ActiveCfg = Debug|Win32 {89975A1A-F799-4556-98B8-64E30AB39A90}.Debug|Win32.Build.0 = Debug|Win32 {89975A1A-F799-4556-98B8-64E30AB39A90}.Release|Win32.ActiveCfg = Release|Win32 {89975A1A-F799-4556-98B8-64E30AB39A90}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal thrift-0.19.0/compiler/cpp/Makefile.am0000644000000000000000000001243214370300523017526 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. AUTOMAKE_OPTIONS = subdir-objects nostdinc SUBDIRS = src . if WITH_TESTS SUBDIRS += test endif bin_PROGRAMS = thrift thrift_OBJDIR = obj thrift_SOURCES = src/thrift/audit/t_audit.cpp \ src/thrift/audit/t_audit.h \ src/thrift/common.cc \ src/thrift/common.h \ src/thrift/generate/t_generator.cc \ src/thrift/generate/t_generator.h \ src/thrift/generate/t_generator_registry.h \ src/thrift/generate/t_html_generator.h \ src/thrift/generate/t_oop_generator.h \ src/thrift/globals.h \ src/thrift/logging.h \ src/thrift/main.cc \ src/thrift/main.h \ src/thrift/version.h \ src/thrift/parse/parse.cc \ src/thrift/parse/t_base_type.h \ src/thrift/parse/t_const.h \ src/thrift/parse/t_const_value.h \ src/thrift/parse/t_container.h \ src/thrift/parse/t_doc.h \ src/thrift/parse/t_enum.h \ src/thrift/parse/t_enum_value.h \ src/thrift/parse/t_field.h \ src/thrift/parse/t_function.h \ src/thrift/parse/t_list.h \ src/thrift/parse/t_map.h \ src/thrift/parse/t_program.h \ src/thrift/parse/t_scope.h \ src/thrift/parse/t_service.h \ src/thrift/parse/t_set.h \ src/thrift/parse/t_struct.h \ src/thrift/parse/t_type.h \ src/thrift/parse/t_typedef.cc \ src/thrift/parse/t_typedef.h \ src/thrift/platform.h # Specific client generator source thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \ src/thrift/generate/t_cl_generator.cc \ src/thrift/generate/t_cpp_generator.cc \ src/thrift/generate/t_d_generator.cc \ src/thrift/generate/t_dart_generator.cc \ src/thrift/generate/t_delphi_generator.cc \ src/thrift/generate/t_erl_generator.cc \ src/thrift/generate/t_go_generator.cc \ src/thrift/generate/t_go_generator.h \ src/thrift/generate/t_gv_generator.cc \ src/thrift/generate/t_haxe_generator.cc \ src/thrift/generate/t_html_generator.cc \ src/thrift/generate/t_markdown_generator.cc \ src/thrift/generate/t_java_generator.cc \ src/thrift/generate/t_javame_generator.cc \ src/thrift/generate/t_js_generator.cc \ src/thrift/generate/t_json_generator.cc \ src/thrift/generate/t_kotlin_generator.cc \ src/thrift/generate/t_lua_generator.cc \ src/thrift/generate/t_netstd_generator.cc \ src/thrift/generate/t_netstd_generator.h \ src/thrift/generate/t_ocaml_generator.cc \ src/thrift/generate/t_perl_generator.cc \ src/thrift/generate/t_php_generator.cc \ src/thrift/generate/t_py_generator.cc \ src/thrift/generate/t_rb_generator.cc \ src/thrift/generate/t_rs_generator.cc \ src/thrift/generate/t_st_generator.cc \ src/thrift/generate/t_swift_generator.cc \ src/thrift/generate/t_xml_generator.cc \ src/thrift/generate/t_xsd_generator.cc \ src/thrift/generate/validator_parser.cc \ src/thrift/generate/validator_parser.h \ src/thrift/generate/go_validator_generator.cc \ src/thrift/generate/go_validator_generator.h thrift_CPPFLAGS = -I$(srcdir)/src thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror thrift_LDADD = @LEXLIB@ src/thrift/libparse.a WINDOWS_DIST = \ compiler.sln \ compiler.vcxproj \ compiler.vcxproj.filters EXTRA_DIST = \ coding_standards.md \ README.md \ CMakeLists.txt \ test \ tests \ $(WINDOWS_DIST) #clean-local: # $(RM) version.h -- do not delete, we need it src/thrift/main.cc: src/thrift/version.h style-local: $(CPPSTYLE_CMD) thrift-0.19.0/compiler/cpp/CMakeLists.txt0000644000000000000000000001433414370300523020235 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # cmake_minimum_required(VERSION 3.3) project("thrift-compiler" VERSION ${PACKAGE_VERSION}) # version.h now handled via veralign.sh #configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) find_package(FLEX REQUIRED) find_package(BISON REQUIRED) # create directory for thrifty and thriftl file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/) # Create flex and bison files and build the lib parse static library BISON_TARGET(thrifty ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/thrifty.yy ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc) FLEX_TARGET(thriftl ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/thriftl.ll ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc) ADD_FLEX_BISON_DEPENDENCY(thriftl thrifty) set(parse_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.cc ${CMAKE_CURRENT_BINARY_DIR}/thrift/thriftl.cc ${CMAKE_CURRENT_BINARY_DIR}/thrift/thrifty.hh ) add_library(parse STATIC ${parse_SOURCES}) # Create the thrift compiler set(compiler_core src/thrift/common.cc src/thrift/generate/t_generator.cc src/thrift/generate/validator_parser.cc src/thrift/generate/validator_parser.h src/thrift/parse/t_typedef.cc src/thrift/parse/parse.cc src/thrift/version.h ) set(thrift-compiler_SOURCES src/thrift/main.cc src/thrift/audit/t_audit.cpp ) set(thrift_compiler_LANGS ) # This macro adds an option THRIFT_COMPILER_${NAME} # that allows enabling or disabling certain languages macro(THRIFT_ADD_COMPILER name description initial) string(TOUPPER "THRIFT_COMPILER_${name}" enabler) set(src "src/thrift/generate/t_${name}_generator.cc") option(${enabler} ${description} ${initial}) if(${enabler}) list(APPEND thrift-compiler_SOURCES ${src}) list(APPEND thrift_compiler_LANGS ${name}) endif() endmacro() # This macro adds an option THRIFT_VALIDATOR_COMPILER_${NAME} # that allows enabling or disabling certain languages' validator macro(THRIFT_ADD_VALIDATOR_COMPILER name description initial) string(TOUPPER "THRIFT_COMPILER_${name}" enabler) set(src "src/thrift/generate/${name}_validator_generator.cc") list(APPEND "src/thrift/generate/${name}_validator_generator.h") option(${enabler} ${description} ${initial}) if(${enabler}) list(APPEND thrift-compiler_SOURCES ${src}) endif() endmacro() # The following compiler can be enabled or disabled THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" ON) THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" ON) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" ON) THRIFT_ADD_COMPILER(d "Enable compiler for D" ON) THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" ON) THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" ON) THRIFT_ADD_COMPILER(erl "Enable compiler for Erlang" ON) THRIFT_ADD_COMPILER(go "Enable compiler for Go" ON) THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" ON) THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" ON) THRIFT_ADD_COMPILER(html "Enable compiler for HTML Documentation" ON) THRIFT_ADD_COMPILER(markdown "Enable compiler for Markdown Documentation" ON) THRIFT_ADD_COMPILER(java "Enable compiler for Java" ON) THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" ON) THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" ON) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" ON) THRIFT_ADD_COMPILER(kotlin "Enable compiler for Kotlin" ON) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" ON) THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON) THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" ON) THRIFT_ADD_COMPILER(php "Enable compiler for PHP" ON) THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" ON) THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" ON) THRIFT_ADD_COMPILER(rs "Enable compiler for Rust" ON) THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" ON) THRIFT_ADD_COMPILER(swift "Enable compiler for Cocoa Swift" ON) THRIFT_ADD_COMPILER(xml "Enable compiler for XML" ON) THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" ON) # The following compiler can be enabled or disabled by enabling or disabling certain languages THRIFT_ADD_VALIDATOR_COMPILER(go "Enable validator compiler for Go" ON) # Thrift is looking for include files in the src directory # we also add the current binary directory for generated files include_directories(${CMAKE_CURRENT_BINARY_DIR} src) list(APPEND thrift-compiler_SOURCES ${compiler_core}) add_executable(thrift-compiler ${thrift-compiler_SOURCES}) set_target_properties(thrift-compiler PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin/) set_target_properties(thrift-compiler PROPERTIES OUTPUT_NAME thrift) target_link_libraries(thrift-compiler parse) add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/thrift${CMAKE_EXECUTABLE_SUFFIX}" DEPENDS thrift-compiler COMMAND ${CMAKE_COMMAND} -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/" COMMENT "Copying the thrift compiler to the source tree for use by downstream targets") add_custom_target(copy-thrift-compiler DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/thrift${CMAKE_EXECUTABLE_SUFFIX}") install(TARGETS thrift-compiler DESTINATION bin) if(BUILD_TESTING) add_subdirectory(test) endif() thrift-0.19.0/compiler/cpp/src/0000755000000000000000000000000014472652644016300 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/src/thrift/0000755000000000000000000000000014472652644017600 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/src/thrift/thrifty.hh0000644000000000000000000001125214472652644021613 0ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 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 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, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef YY_YY_THRIFT_THRIFTY_HH_INCLUDED # define YY_YY_THRIFT_THRIFTY_HH_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* "%code requires" blocks. */ #line 1 "thrift/thrifty.yy" /* yacc.c:1909 */ #include "thrift/parse/t_program.h" #line 48 "thrift/thrifty.hh" /* yacc.c:1909 */ /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { tok_identifier = 258, tok_literal = 259, tok_doctext = 260, tok_int_constant = 261, tok_dub_constant = 262, tok_include = 263, tok_namespace = 264, tok_cpp_include = 265, tok_cpp_type = 266, tok_xsd_all = 267, tok_xsd_optional = 268, tok_xsd_nillable = 269, tok_xsd_attrs = 270, tok_void = 271, tok_bool = 272, tok_string = 273, tok_binary = 274, tok_uuid = 275, tok_byte = 276, tok_i8 = 277, tok_i16 = 278, tok_i32 = 279, tok_i64 = 280, tok_double = 281, tok_map = 282, tok_list = 283, tok_set = 284, tok_oneway = 285, tok_async = 286, tok_typedef = 287, tok_struct = 288, tok_xception = 289, tok_throws = 290, tok_extends = 291, tok_service = 292, tok_enum = 293, tok_const = 294, tok_required = 295, tok_optional = 296, tok_union = 297, tok_reference = 298 }; #endif /* Tokens. */ #define tok_identifier 258 #define tok_literal 259 #define tok_doctext 260 #define tok_int_constant 261 #define tok_dub_constant 262 #define tok_include 263 #define tok_namespace 264 #define tok_cpp_include 265 #define tok_cpp_type 266 #define tok_xsd_all 267 #define tok_xsd_optional 268 #define tok_xsd_nillable 269 #define tok_xsd_attrs 270 #define tok_void 271 #define tok_bool 272 #define tok_string 273 #define tok_binary 274 #define tok_uuid 275 #define tok_byte 276 #define tok_i8 277 #define tok_i16 278 #define tok_i32 279 #define tok_i64 280 #define tok_double 281 #define tok_map 282 #define tok_list 283 #define tok_set 284 #define tok_oneway 285 #define tok_async 286 #define tok_typedef 287 #define tok_struct 288 #define tok_xception 289 #define tok_throws 290 #define tok_extends 291 #define tok_service 292 #define tok_enum 293 #define tok_const 294 #define tok_required 295 #define tok_optional 296 #define tok_union 297 #define tok_reference 298 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { #line 82 "thrift/thrifty.yy" /* yacc.c:1909 */ char* id; int64_t iconst; double dconst; bool tbool; t_doc* tdoc; t_type* ttype; t_base_type* tbase; t_typedef* ttypedef; t_enum* tenum; t_enum_value* tenumv; t_const* tconst; t_const_value* tconstv; t_struct* tstruct; t_service* tservice; t_function* tfunction; t_field* tfield; char* dtext; char* keyword; t_field::e_req ereq; t_annotation* tannot; t_field_id tfieldid; #line 170 "thrift/thrifty.hh" /* yacc.c:1909 */ }; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; int yyparse (void); #endif /* !YY_YY_THRIFT_THRIFTY_HH_INCLUDED */ thrift-0.19.0/compiler/cpp/src/thrift/parse/0000755000000000000000000000000014472652642020710 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/src/thrift/parse/t_typedef.h0000644000000000000000000000406614303740367023045 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_TYPEDEF_H #define T_TYPEDEF_H #include #include "thrift/parse/t_type.h" /** * A typedef is a mapping from a symbolic name to another type. In dymanically * typed languages (i.e. php/python) the code generator can actually usually * ignore typedefs and just use the underlying type directly, though in C++ * the symbolic naming can be quite useful for code clarity. * */ class t_typedef : public t_type { public: t_typedef(t_program* program, t_type* type, const std::string& symbolic) : t_type(program, symbolic), type_(type), symbolic_(symbolic), forward_(false) {} /** * This constructor is used to refer to a type that is lazily * resolved at a later time, like for forward declarations or * recursive types. */ t_typedef(t_program* program, const std::string& symbolic, bool forward) : t_type(program, symbolic), type_(nullptr), symbolic_(symbolic), forward_(forward) {} ~t_typedef() override = default; t_type* get_type(); const t_type* get_type() const; const std::string& get_symbolic() const { return symbolic_; } bool is_forward_typedef() const { return forward_; } bool is_typedef() const override { return true; } private: t_type* type_; std::string symbolic_; bool forward_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_const_value.h0000644000000000000000000001634214370300523023715 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_CONST_VALUE_H #define T_CONST_VALUE_H #include "thrift/parse/t_enum.h" #include #include #include #include /** * A const value is something parsed that could be a map, set, list, struct * or whatever. * */ class t_const_value { public: /** * Comparator to sort fields in ascending order by key. * Make this a functor instead of a function to help GCC inline it. */ struct value_compare { public: bool operator()(t_const_value const* const& left, t_const_value const* const& right) const { return *left < *right; } }; enum t_const_value_type { CV_INTEGER, CV_DOUBLE, CV_STRING, CV_MAP, CV_LIST, CV_IDENTIFIER, CV_UNKNOWN }; t_const_value() : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)nullptr), valType_(CV_UNKNOWN) {} t_const_value(int64_t val) : doubleVal_(0.0f), enum_((t_enum*)nullptr), valType_(CV_UNKNOWN) { set_integer(val); } t_const_value(std::string val) : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)nullptr), valType_(CV_UNKNOWN) { set_string(val); } void set_string(std::string val) { valType_ = CV_STRING; stringVal_ = val; } std::string get_string() const { return stringVal_; } void set_integer(int64_t val) { valType_ = CV_INTEGER; intVal_ = val; } int64_t get_integer() const { if (valType_ == CV_IDENTIFIER) { if (enum_ == nullptr) { throw "have identifier \"" + get_identifier() + "\", but unset enum on line!"; } std::string identifier = get_identifier(); std::string::size_type dot = identifier.rfind('.'); if (dot != std::string::npos) { identifier = identifier.substr(dot + 1); } t_enum_value* val = enum_->get_constant_by_name(identifier); if (val == nullptr) { throw "Unable to find enum value \"" + identifier + "\" in enum \"" + enum_->get_name() + "\""; } return val->get_value(); } else { return intVal_; } } void set_uuid(std::string val) { validate_uuid(val); valType_ = CV_STRING; stringVal_ = val; } std::string get_uuid() const { std::string tmp = stringVal_; validate_uuid(tmp); return tmp; } void set_double(double val) { valType_ = CV_DOUBLE; doubleVal_ = val; } double get_double() const { return doubleVal_; } void set_map() { valType_ = CV_MAP; } void add_map(t_const_value* key, t_const_value* val) { mapVal_[key] = val; } const std::map& get_map() const { return mapVal_; } void set_list() { valType_ = CV_LIST; } void add_list(t_const_value* val) { listVal_.push_back(val); } const std::vector& get_list() const { return listVal_; } void set_identifier(std::string val) { valType_ = CV_IDENTIFIER; identifierVal_ = val; } std::string get_identifier() const { return identifierVal_; } std::string get_identifier_name() const { std::string ret = get_identifier(); size_t s = ret.find('.'); if (s == std::string::npos) { throw "error: identifier " + ret + " is unqualified!"; } ret = ret.substr(s + 1); s = ret.find('.'); if (s != std::string::npos) { ret = ret.substr(s + 1); } return ret; } std::string get_identifier_with_parent() const { std::string ret = get_identifier(); size_t s = ret.find('.'); if (s == std::string::npos) { throw "error: identifier " + ret + " is unqualified!"; } size_t s2 = ret.find('.', s + 1); if (s2 != std::string::npos) { ret = ret.substr(s + 1); } return ret; } void set_enum(t_enum* tenum) { enum_ = tenum; } t_const_value_type get_type() const { if (valType_ == CV_UNKNOWN) { throw std::string("unknown t_const_value"); } return valType_; } /** * Comparator to sort map fields in ascending order by key and then value. * This is used for map comparison in lexicographic order. */ struct map_entry_compare { private: typedef std::pair ConstPair; public: bool operator()(ConstPair left, ConstPair right) const { if (*(left.first) < *(right.first)) { return true; } else { if (*(right.first) < *(left.first)) { return false; } else { return *(left.second) < *(right.second); } } } }; bool operator < (const t_const_value& that) const { ::t_const_value::t_const_value_type t1 = get_type(); ::t_const_value::t_const_value_type t2 = that.get_type(); if (t1 != t2) return t1 < t2; switch (t1) { case ::t_const_value::CV_INTEGER: return intVal_ < that.intVal_; case ::t_const_value::CV_DOUBLE: return doubleVal_ < that.doubleVal_; case ::t_const_value::CV_STRING: return stringVal_ < that.stringVal_; case ::t_const_value::CV_IDENTIFIER: return identifierVal_ < that.identifierVal_; case ::t_const_value::CV_MAP: return std::lexicographical_compare( mapVal_.begin(), mapVal_.end(), that.mapVal_.begin(), that.mapVal_.end(), map_entry_compare()); case ::t_const_value::CV_LIST: return std::lexicographical_compare( listVal_.begin(), listVal_.end(), that.listVal_.begin(), that.listVal_.end(), value_compare()); case ::t_const_value::CV_UNKNOWN: default: throw "unknown value type"; } } private: std::map mapVal_; std::vector listVal_; std::string stringVal_; int64_t intVal_; double doubleVal_; std::string identifierVal_; t_enum* enum_; t_const_value_type valType_; void validate_uuid(std::string & uuid) const { const std::string HEXCHARS = std::string("0123456789ABCDEFabcdef"); // we also allow for usual "Windows GUID" format "{01234567-9012-4567-9012-456789012345}" if ((uuid.length() == 38) && ('{' == uuid[0]) && ('}' == uuid[37])) { uuid = uuid.substr(1, 36); } // canonical format "01234567-9012-4567-9012-456789012345" expected bool valid = (uuid.length() == 36); for (size_t i = 0; valid && (i < uuid.length()); ++i) { switch(i) { case 8: case 13: case 18: case 23: if(uuid[i] != '-') { valid = false; } break; default: if(HEXCHARS.find(uuid[i]) == std::string::npos) { valid = false; } break; } } if( ! valid) { throw "invalid uuid " + uuid; } } }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_base_type.h0000644000000000000000000000472714370300523023352 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_BASE_TYPE_H #define T_BASE_TYPE_H #include #include "thrift/parse/t_type.h" /** * A thrift base type, which must be one of the defined enumerated types inside * this definition. * */ class t_base_type : public t_type { public: /** * Enumeration of thrift base types */ enum t_base { TYPE_VOID, TYPE_STRING, TYPE_UUID, TYPE_BOOL, TYPE_I8, TYPE_I16, TYPE_I32, TYPE_I64, TYPE_DOUBLE }; t_base_type(std::string name, t_base base) : t_type(name), base_(base), binary_(false) {} t_base get_base() const { return base_; } bool is_void() const override { return base_ == TYPE_VOID; } bool is_string() const override { return base_ == TYPE_STRING; } bool is_bool() const override { return base_ == TYPE_BOOL; } bool is_uuid() const override { return base_ == TYPE_UUID; } void set_binary(bool val) { binary_ = val; } bool is_binary() const override { return binary_ && (base_ == TYPE_STRING); } bool is_base_type() const override { return true; } static std::string t_base_name(t_base tbase) { switch (tbase) { case TYPE_VOID: return "void"; break; case TYPE_STRING: return "string"; break; case TYPE_UUID: return "uuid"; break; case TYPE_BOOL: return "bool"; break; case TYPE_I8: return "i8"; break; case TYPE_I16: return "i16"; break; case TYPE_I32: return "i32"; break; case TYPE_I64: return "i64"; break; case TYPE_DOUBLE: return "double"; break; default: return "(unknown)"; break; } } private: t_base base_; bool binary_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_doc.h0000644000000000000000000000271514303740367022151 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_DOC_H #define T_DOC_H #include "thrift/globals.h" #include "thrift/logging.h" /** * Documentation stubs * */ class t_doc { public: t_doc() : has_doc_(false) {} virtual ~t_doc() = default; void set_doc(const std::string& doc) { doc_ = doc; has_doc_ = true; if ((g_program_doctext_lineno == g_doctext_lineno) && (g_program_doctext_status == STILL_CANDIDATE)) { g_program_doctext_status = ALREADY_PROCESSED; pdebug("%s", "program doctext set to ALREADY_PROCESSED"); } } const std::string& get_doc() const { return doc_; } bool has_doc() { return has_doc_; } private: std::string doc_; bool has_doc_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_scope.h0000644000000000000000000002004714370300523022501 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_SCOPE_H #define T_SCOPE_H #include #include #include #include "thrift/parse/t_type.h" #include "thrift/parse/t_typedef.h" #include "thrift/parse/t_service.h" #include "thrift/parse/t_const.h" #include "thrift/parse/t_const_value.h" #include "thrift/parse/t_base_type.h" #include "thrift/parse/t_map.h" #include "thrift/parse/t_list.h" #include "thrift/parse/t_set.h" /** * This represents a variable scope used for looking up predefined types and * services. Typically, a scope is associated with a t_program. Scopes are not * used to determine code generation, but rather to resolve identifiers at * parse time. * */ class t_scope { public: t_scope() = default; void add_type(std::string name, t_type* type) { types_[name] = type; } t_type* get_type(std::string name) { return types_[name]; } const t_type* get_type(std::string name) const { const auto it = types_.find(name); if (types_.end() != it) { return it->second; } return nullptr; } void add_service(std::string name, t_service* service) { services_[name] = service; } t_service* get_service(std::string name) { return services_[name]; } const t_service* get_service(std::string name) const { const auto it = services_.find(name); if (services_.end() != it) { return it->second; } return nullptr; } void add_constant(std::string name, t_const* constant) { if (constants_.find(name) != constants_.end()) { throw "Enum " + name + " is already defined!"; } else { constants_[name] = constant; } } t_const* get_constant(std::string name) { return constants_[name]; } const t_const* get_constant(std::string name) const { const auto it = constants_.find(name); if (constants_.end() != it) { return it->second; } return nullptr; } void print() { std::map::iterator iter; for (iter = types_.begin(); iter != types_.end(); ++iter) { printf("%s => %s\n", iter->first.c_str(), iter->second->get_name().c_str()); } } void resolve_all_consts() { std::map::iterator iter; for (iter = constants_.begin(); iter != constants_.end(); ++iter) { t_const_value* cval = iter->second->get_value(); t_type* ttype = iter->second->get_type(); resolve_const_value(cval, ttype); } } void resolve_const_value(t_const_value* const_val, t_type* ttype) { while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } if (ttype->is_map()) { const std::map& map = const_val->get_map(); std::map::const_iterator v_iter; for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type()); resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type()); } } else if (ttype->is_list()) { const std::vector& val = const_val->get_list(); std::vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { resolve_const_value((*v_iter), ((t_list*)ttype)->get_elem_type()); } } else if (ttype->is_set()) { const std::vector& val = const_val->get_list(); std::vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { resolve_const_value((*v_iter), ((t_set*)ttype)->get_elem_type()); } } else if (ttype->is_struct()) { auto* tstruct = (t_struct*)ttype; const std::map& map = const_val->get_map(); std::map::const_iterator v_iter; for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { t_field* field = tstruct->get_field_by_name(v_iter->first->get_string()); if (field == nullptr) { throw "No field named \"" + v_iter->first->get_string() + "\" was found in struct of type \"" + tstruct->get_name() + "\""; } resolve_const_value(v_iter->second, field->get_type()); } } else if (const_val->get_type() == t_const_value::CV_IDENTIFIER) { if (ttype->is_enum()) { const_val->set_enum((t_enum*)ttype); } else { t_const* constant = get_constant(const_val->get_identifier()); if (constant == nullptr) { throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!"; } // Resolve typedefs to the underlying type t_type* const_type = constant->get_type()->get_true_type(); if (const_type->is_base_type()) { switch (((t_base_type*)const_type)->get_base()) { case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: const_val->set_integer(constant->get_value()->get_integer()); break; case t_base_type::TYPE_STRING: const_val->set_string(constant->get_value()->get_string()); break; case t_base_type::TYPE_UUID: const_val->set_uuid(constant->get_value()->get_uuid()); break; case t_base_type::TYPE_DOUBLE: const_val->set_double(constant->get_value()->get_double()); break; case t_base_type::TYPE_VOID: throw "Constants cannot be of type VOID"; } } else if (const_type->is_map()) { const std::map& map = constant->get_value()->get_map(); std::map::const_iterator v_iter; const_val->set_map(); for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { const_val->add_map(v_iter->first, v_iter->second); } } else if (const_type->is_list()) { const std::vector& val = constant->get_value()->get_list(); std::vector::const_iterator v_iter; const_val->set_list(); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { const_val->add_list(*v_iter); } } } } else if (ttype->is_enum()) { // enum constant with non-identifier value. set the enum and find the // value's name. auto* tenum = (t_enum*)ttype; t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer()); if (enum_value == nullptr) { std::ostringstream valstm; valstm << const_val->get_integer(); throw "Couldn't find a named value in enum " + tenum->get_name() + " for value " + valstm.str(); } const_val->set_identifier(tenum->get_name() + "." + enum_value->get_name()); const_val->set_enum(tenum); } } private: // Map of names to types std::map types_; // Map of names to constants std::map constants_; // Map of names to services std::map services_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_list.h0000644000000000000000000000227714303740367022362 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_LIST_H #define T_LIST_H #include "thrift/parse/t_container.h" /** * A list is a lightweight container type that just wraps another data type. * */ class t_list : public t_container { public: t_list(t_type* elem_type) : elem_type_(elem_type) {} t_type* get_elem_type() const { return elem_type_; } bool is_list() const override { return true; } private: t_type* elem_type_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_field.h0000644000000000000000000000714014370300523022452 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_FIELD_H #define T_FIELD_H #include #include #include #include "thrift/parse/t_doc.h" #include "thrift/parse/t_type.h" // Forward declare for xsd_attrs class t_struct; /** * Class to represent a field in a thrift structure. A field has a data type, * a symbolic name, and a numeric identifier. * */ class t_field : public t_doc { public: t_field(t_type* type, std::string name) : type_(type), name_(name), key_(0), req_(T_OPT_IN_REQ_OUT), value_(nullptr), xsd_optional_(false), xsd_nillable_(false), xsd_attrs_(nullptr), reference_(false) {} t_field(t_type* type, std::string name, int32_t key) : type_(type), name_(name), key_(key), req_(T_OPT_IN_REQ_OUT), value_(nullptr), xsd_optional_(false), xsd_nillable_(false), xsd_attrs_(nullptr), reference_(false) {} ~t_field() override = default; t_type* get_type() { return type_; } const t_type* get_type() const { return type_; } const std::string& get_name() const { return name_; } int32_t get_key() const { return key_; } enum e_req { T_REQUIRED, T_OPTIONAL, T_OPT_IN_REQ_OUT }; void set_req(e_req req) { req_ = req; } e_req get_req() const { return req_; } void set_value(t_const_value* value) { value_ = value; } t_const_value* get_value() { return value_; } const t_const_value* get_value() const { return value_; } void set_xsd_optional(bool xsd_optional) { xsd_optional_ = xsd_optional; } bool get_xsd_optional() const { return xsd_optional_; } void set_xsd_nillable(bool xsd_nillable) { xsd_nillable_ = xsd_nillable; } bool get_xsd_nillable() const { return xsd_nillable_; } void set_xsd_attrs(t_struct* xsd_attrs) { xsd_attrs_ = xsd_attrs; } t_struct* get_xsd_attrs() { return xsd_attrs_; } const t_struct* get_xsd_attrs() const { return xsd_attrs_; } /** * Comparator to sort fields in ascending order by key. * Make this a functor instead of a function to help GCC inline it. * The arguments are (const) references to const pointers to const t_fields. */ struct key_compare { bool operator()(t_field const* const& a, t_field const* const& b) { return a->get_key() < b->get_key(); } }; std::map> annotations_; bool get_reference() const { return reference_; } void set_reference(bool reference) { reference_ = reference; } private: t_type* type_; std::string name_; int32_t key_; e_req req_; t_const_value* value_; bool xsd_optional_; bool xsd_nillable_; t_struct* xsd_attrs_; bool reference_; }; /** * A simple struct for the parser to use to store a field ID, and whether or * not it was specified by the user or automatically chosen. */ struct t_field_id { int32_t value; bool auto_assigned; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_function.h0000644000000000000000000000533414370300523023217 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_FUNCTION_H #define T_FUNCTION_H #include "thrift/parse/t_doc.h" #include "thrift/parse/t_struct.h" #include "thrift/parse/t_type.h" #include /** * Representation of a function. Key parts are return type, function name, * optional modifiers, and an argument list, which is implemented as a thrift * struct. * */ class t_function : public t_doc { public: t_function(t_type* returntype, std::string name, t_struct* arglist, bool oneway = false) : returntype_(returntype), name_(name), arglist_(arglist), xceptions_(new t_struct(nullptr)), own_xceptions_(true), oneway_(oneway) { xceptions_->set_method_xcepts(true); if (oneway_ && (!returntype_->is_void())) { pwarning(1, "Oneway methods should return void.\n"); } } t_function(t_type* returntype, std::string name, t_struct* arglist, t_struct* xceptions, bool oneway = false) : returntype_(returntype), name_(name), arglist_(arglist), xceptions_(xceptions), own_xceptions_(false), oneway_(oneway) { xceptions_->set_method_xcepts(true); if (oneway_ && !xceptions_->get_members().empty()) { throw std::string("Oneway methods can't throw exceptions."); } if (oneway_ && (!returntype_->is_void())) { pwarning(1, "Oneway methods should return void.\n"); } } ~t_function() override { if (own_xceptions_) delete xceptions_; } t_type* get_returntype() const { return returntype_; } const std::string& get_name() const { return name_; } t_struct* get_arglist() const { return arglist_; } t_struct* get_xceptions() const { return xceptions_; } bool is_oneway() const { return oneway_; } std::map> annotations_; private: t_type* returntype_; std::string name_; t_struct* arglist_; t_struct* xceptions_; bool own_xceptions_; bool oneway_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_program.h0000644000000000000000000003332014370300523023035 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_PROGRAM_H #define T_PROGRAM_H #include #include #include // For program_name() #include "thrift/main.h" #include "thrift/parse/t_doc.h" #include "thrift/parse/t_scope.h" #include "thrift/parse/t_base_type.h" #include "thrift/parse/t_typedef.h" #include "thrift/parse/t_enum.h" #include "thrift/parse/t_const.h" #include "thrift/parse/t_struct.h" #include "thrift/parse/t_service.h" #include "thrift/parse/t_list.h" #include "thrift/parse/t_map.h" #include "thrift/parse/t_set.h" #include "thrift/generate/t_generator_registry.h" //#include "thrift/parse/t_doc.h" /** * Top level class representing an entire thrift program. A program consists * fundamentally of the following: * * Typedefs * Enumerations * Constants * Structs * Exceptions * Services * * The program module also contains the definitions of the base types. * */ class t_program : public t_doc { public: t_program(std::string path, std::string name) : path_(path), name_(name), out_path_("./"), out_path_is_absolute_(false), scope_(new t_scope), recursive_(false) {} t_program(std::string path) : path_(path), out_path_("./"), out_path_is_absolute_(false), recursive_(false) { name_ = program_name(path); scope_ = new t_scope(); } ~t_program() override { if (scope_) { delete scope_; scope_ = nullptr; } } // Path accessor const std::string& get_path() const { return path_; } // Output path accessor const std::string& get_out_path() const { return out_path_; } // Create gen-* dir accessor bool is_out_path_absolute() const { return out_path_is_absolute_; } // Name accessor const std::string& get_name() const { return name_; } // Namespace const std::string& get_namespace() const { return namespace_; } // Include prefix accessor const std::string& get_include_prefix() const { return include_prefix_; } // Accessors for program elements const std::vector& get_typedefs() const { return typedefs_; } const std::vector& get_enums() const { return enums_; } const std::vector& get_consts() const { return consts_; } const std::vector& get_structs() const { return structs_; } const std::vector& get_xceptions() const { return xceptions_; } const std::vector& get_objects() const { return objects_; } const std::vector& get_services() const { return services_; } const std::map& get_namespaces() const { return namespaces_; } // Program elements void add_typedef(t_typedef* td) { typedefs_.push_back(td); } void add_enum(t_enum* te) { enums_.push_back(te); } void add_const(t_const* tc) { consts_.push_back(tc); } void add_struct(t_struct* ts) { objects_.push_back(ts); structs_.push_back(ts); } void add_xception(t_struct* tx) { objects_.push_back(tx); xceptions_.push_back(tx); } void add_service(t_service* ts) { ts->validate_unique_members(); services_.push_back(ts); } // Programs to include std::vector& get_includes() { return includes_; } const std::vector& get_includes() const { return includes_; } void set_out_path(std::string out_path, bool out_path_is_absolute) { out_path_ = out_path; out_path_is_absolute_ = out_path_is_absolute; // Ensure that it ends with a trailing '/' (or '\' for windows machines) char c = out_path_.at(out_path_.size() - 1); if (!(c == '/' || c == '\\')) { out_path_.push_back('/'); } } // Typename collision detection /** * Search for typename collisions * @param t the type to test for collisions * @return true if a certain collision was found, otherwise false */ bool is_unique_typename(const t_type* t) const { int occurrences = program_typename_count(this, t); for (auto it = includes_.cbegin(); it != includes_.cend(); ++it) { occurrences += program_typename_count(*it, t); } return 0 == occurrences; } /** * Search all type collections for duplicate typenames * @param prog the program to search * @param t the type to test for collisions * @return the number of certain typename collisions */ int program_typename_count(const t_program* prog, const t_type* t) const { int occurrences = 0; occurrences += collection_typename_count(prog, prog->typedefs_, t); occurrences += collection_typename_count(prog, prog->enums_, t); occurrences += collection_typename_count(prog, prog->objects_, t); occurrences += collection_typename_count(prog, prog->services_, t); return occurrences; } /** * Search a type collection for duplicate typenames * @param prog the program to search * @param type_collection the type collection to search * @param t the type to test for collisions * @return the number of certain typename collisions */ template int collection_typename_count(const t_program* prog, const T type_collection, const t_type* t) const { int occurrences = 0; for (auto it = type_collection.cbegin(); it != type_collection.cend(); ++it) if (t != *it && 0 == t->get_name().compare((*it)->get_name()) && is_common_namespace(prog, t)) ++occurrences; return occurrences; } /** * Determine whether identical typenames will collide based on namespaces. * * Because we do not know which languages the user will generate code for, * collisions within programs (IDL files) having namespace declarations can be * difficult to determine. Only guaranteed collisions return true (cause an error). * Possible collisions involving explicit namespace declarations produce a warning. * Other possible collisions go unreported. * @param prog the program containing the preexisting typename * @param t the type containing the typename match * @return true if a collision within namespaces is found, otherwise false */ bool is_common_namespace(const t_program* prog, const t_type* t) const { // Case 1: Typenames are in the same program [collision] if (prog == t->get_program()) { pwarning(1, "Duplicate typename %s found in %s", t->get_name().c_str(), t->get_program()->get_name().c_str()); return true; } // Case 2: Both programs have identical namespace scope/name declarations [collision] bool match = true; for (auto it = prog->namespaces_.cbegin(); it != prog->namespaces_.cend(); ++it) { if (0 == it->second.compare(t->get_program()->get_namespace(it->first))) { pwarning(1, "Duplicate typename %s found in %s,%s,%s and %s,%s,%s [file,scope,ns]", t->get_name().c_str(), t->get_program()->get_name().c_str(), it->first.c_str(), it->second.c_str(), prog->get_name().c_str(), it->first.c_str(), it->second.c_str()); } else { match = false; } } for (auto it = t->get_program()->namespaces_.cbegin(); it != t->get_program()->namespaces_.cend(); ++it) { if (0 == it->second.compare(prog->get_namespace(it->first))) { pwarning(1, "Duplicate typename %s found in %s,%s,%s and %s,%s,%s [file,scope,ns]", t->get_name().c_str(), t->get_program()->get_name().c_str(), it->first.c_str(), it->second.c_str(), prog->get_name().c_str(), it->first.c_str(), it->second.c_str()); } else { match = false; } } if (0 == prog->namespaces_.size() && 0 == t->get_program()->namespaces_.size()) { pwarning(1, "Duplicate typename %s found in %s and %s", t->get_name().c_str(), t->get_program()->get_name().c_str(), prog->get_name().c_str()); } return match; } // Scoping and namespacing void set_namespace(std::string name) { namespace_ = name; } // Scope accessor t_scope* scope() { return scope_; } const t_scope* scope() const { return scope_; } // Includes void add_include(t_program* program) { includes_.push_back(program); } void add_include(std::string path, std::string include_site) { t_program* program = new t_program(path); // include prefix for this program is the site at which it was included // (minus the filename) std::string include_prefix; std::string::size_type last_slash = std::string::npos; if ((last_slash = include_site.rfind("/")) != std::string::npos) { include_prefix = include_site.substr(0, last_slash); } program->set_include_prefix(include_prefix); includes_.push_back(program); } void set_include_prefix(std::string include_prefix) { include_prefix_ = include_prefix; // this is intended to be a directory; add a trailing slash if necessary std::string::size_type len = include_prefix_.size(); if (len > 0 && include_prefix_[len - 1] != '/') { include_prefix_ += '/'; } } // Language neutral namespace / packaging void set_namespace(std::string language, std::string name_space) { if (language != "*") { size_t sub_index = language.find('.'); std::string base_language = language.substr(0, sub_index); if (base_language == "smalltalk") { pwarning(1, "Namespace 'smalltalk' is deprecated. Use 'st' instead"); base_language = "st"; } t_generator_registry::gen_map_t my_copy = t_generator_registry::get_generator_map(); t_generator_registry::gen_map_t::iterator it; it = my_copy.find(base_language); if (it == my_copy.end()) { std::string warning = "No generator named '" + base_language + "' could be found!"; pwarning(1, warning.c_str()); } else { if (sub_index != std::string::npos) { std::string sub_namespace = language.substr(sub_index + 1); if (!it->second->is_valid_namespace(sub_namespace)) { std::string warning = base_language + " generator does not accept '" + sub_namespace + "' as sub-namespace!"; pwarning(1, warning.c_str()); } } } } namespaces_[language] = name_space; } std::string get_namespace(std::string language) const { std::map::const_iterator iter; if ((iter = namespaces_.find(language)) != namespaces_.end() || (iter = namespaces_.find("*")) != namespaces_.end()) { return iter->second; } return std::string(); } const std::map& get_all_namespaces() const { return namespaces_; } void set_namespace_annotations(std::string language, std::map> annotations) { namespace_annotations_[language] = annotations; } const std::map>& get_namespace_annotations(const std::string& language) const { auto it = namespace_annotations_.find(language); if (namespace_annotations_.end() != it) { return it->second; } static const std::map> emptyMap; return emptyMap; } std::map>& get_namespace_annotations(const std::string& language) { return namespace_annotations_[language]; } // Language specific namespace / packaging void add_cpp_include(std::string path) { cpp_includes_.push_back(path); } const std::vector& get_cpp_includes() const { return cpp_includes_; } void add_c_include(std::string path) { c_includes_.push_back(path); } const std::vector& get_c_includes() const { return c_includes_; } void set_recursive(const bool recursive) { recursive_ = recursive; } bool get_recursive() const { return recursive_; } private: // File path std::string path_; // Name std::string name_; // Output directory std::string out_path_; // Output directory is absolute location for generated source (no gen-*) bool out_path_is_absolute_; // Namespace std::string namespace_; // Included programs std::vector includes_; // Include prefix for this program, if any std::string include_prefix_; // Identifier lookup scope t_scope* scope_; // Components to generate code for std::vector typedefs_; std::vector enums_; std::vector consts_; std::vector objects_; std::vector structs_; std::vector xceptions_; std::vector services_; // Dynamic namespaces std::map namespaces_; // Annotations for dynamic namespaces std::map>> namespace_annotations_; // C++ extra includes std::vector cpp_includes_; // C extra includes std::vector c_includes_; // Recursive code generation bool recursive_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_enum.h0000644000000000000000000000666614303740367022361 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_ENUM_H #define T_ENUM_H #include #include "thrift/parse/t_enum_value.h" #include "thrift/parse/t_type.h" /** * An enumerated type. A list of constant objects with a name for the type. * */ class t_enum : public t_type { public: t_enum(t_program* program) : t_type(program) {} void set_name(const std::string& name) override { name_ = name; } void append(t_enum_value* constant) { constants_.push_back(constant); } const std::vector& get_constants() const { return constants_; } t_enum_value* get_constant_by_name(const std::string& name) const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { if ((*c_iter)->get_name() == name) { return *c_iter; } } return nullptr; } t_enum_value* get_constant_by_value(int64_t value) const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { if ((*c_iter)->get_value() == value) { return *c_iter; } } return nullptr; } t_enum_value* get_min_value() const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; t_enum_value* min_value; if (enum_values.size() == 0) { min_value = nullptr; } else { int min_value_value; min_value = enum_values.front(); min_value_value = min_value->get_value(); for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { if ((*c_iter)->get_value() < min_value_value) { min_value = (*c_iter); min_value_value = min_value->get_value(); } } } return min_value; } t_enum_value* get_max_value() const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; t_enum_value* max_value; if (enum_values.size() == 0) { max_value = nullptr; } else { int max_value_value; max_value = enum_values.back(); max_value_value = max_value->get_value(); for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { if ((*c_iter)->get_value() > max_value_value) { max_value = (*c_iter); max_value_value = max_value->get_value(); } } } return max_value; } bool is_enum() const override { return true; } private: std::vector constants_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_enum_value.h0000644000000000000000000000270514370300523023531 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_ENUM_VALUE_H #define T_ENUM_VALUE_H #include "thrift/parse/t_doc.h" #include #include /** * A constant. These are used inside of enum definitions. Constants are just * symbol identifiers that may or may not have an explicit value associated * with them. * */ class t_enum_value : public t_doc { public: t_enum_value(std::string name, int value) : name_(name), value_(value) {} ~t_enum_value() override = default; const std::string& get_name() const { return name_; } int get_value() const { return value_; } std::map> annotations_; private: std::string name_; int value_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_service.h0000644000000000000000000000600014303740367023033 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_SERVICE_H #define T_SERVICE_H #include "thrift/parse/t_function.h" #include class t_program; /** * A service consists of a set of functions. * */ class t_service : public t_type { public: t_service(t_program* program) : t_type(program), extends_(nullptr) {} bool is_service() const override { return true; } void set_extends(t_service* extends) { extends_ = extends; } void add_function(t_function* func) { if (get_function_by_name(func->get_name()) != NULL) { throw "Function " + func->get_name() + " is already defined"; } functions_.push_back(func); } void validate_unique_members() { std::vector::const_iterator iter; for (iter = functions_.begin(); iter != functions_.end(); ++iter) { // throw exception when there is a conflict of names with super class if (extends_ != NULL) { if (extends_->get_function_by_name((*iter)->get_name()) != NULL) { throw "Function " + (*iter)->get_name() + " is already defined in service " + name_; } } } } t_function* get_function_by_name(std::string func_name) { if (extends_ != NULL) { t_function* func = NULL; if ((func = extends_->get_function_by_name(func_name)) != NULL) { return func; } } std::vector::const_iterator iter; for (iter = functions_.begin(); iter != functions_.end(); ++iter) { if ((*iter)->get_name() == func_name) { return *iter; } } return NULL; } const t_function* get_function_by_name(std::string func_name) const { if (extends_ != NULL) { t_function* func = NULL; if ((func = extends_->get_function_by_name(func_name)) != NULL) { return func; } } std::vector::const_iterator iter; for (iter = functions_.begin(); iter != functions_.end(); ++iter) { if ((*iter)->get_name() == func_name) { return *iter; } } return NULL; } const std::vector& get_functions() const { return functions_; } t_service* get_extends() { return extends_; } const t_service* get_extends() const { return extends_; } private: std::vector functions_; t_service* extends_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_container.h0000644000000000000000000000251614303740367023365 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_CONTAINER_H #define T_CONTAINER_H #include "thrift/parse/t_type.h" class t_container : public t_type { public: t_container() : cpp_name_(), has_cpp_name_(false) {} ~t_container() override = default; void set_cpp_name(std::string cpp_name) { cpp_name_ = cpp_name; has_cpp_name_ = true; } bool has_cpp_name() const { return has_cpp_name_; } std::string get_cpp_name() const { return cpp_name_; } bool is_container() const override { return true; } private: std::string cpp_name_; bool has_cpp_name_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_type.h0000644000000000000000000000642714370300523022357 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_TYPE_H #define T_TYPE_H #include "thrift/parse/t_doc.h" #include #include #include #include class t_program; /** * Generic representation of a thrift type. These objects are used by the * parser module to build up a tree of object that are all explicitly typed. * The generic t_type class exports a variety of useful methods that are * used by the code generator to branch based upon different handling for the * various types. * */ class t_type : public t_doc { public: ~t_type() override = default; virtual void set_name(const std::string& name) { name_ = name; } virtual const std::string& get_name() const { return name_; } virtual bool is_void() const { return false; } virtual bool is_base_type() const { return false; } virtual bool is_string() const { return false; } virtual bool is_uuid() const { return false; } virtual bool is_binary() const { return false; } virtual bool is_bool() const { return false; } virtual bool is_typedef() const { return false; } virtual bool is_enum() const { return false; } virtual bool is_struct() const { return false; } virtual bool is_xception() const { return false; } virtual bool is_container() const { return false; } virtual bool is_list() const { return false; } virtual bool is_set() const { return false; } virtual bool is_map() const { return false; } virtual bool is_service() const { return false; } t_program* get_program() { return program_; } const t_program* get_program() const { return program_; } t_type* get_true_type(); const t_type* get_true_type() const; // This function will break (maybe badly) unless 0 <= num <= 16. static char nybble_to_xdigit(int num) { if (num < 10) { return '0' + num; } else { return 'A' + num - 10; } } static std::string byte_to_hex(uint8_t byte) { std::string rv; rv += nybble_to_xdigit(byte >> 4); rv += nybble_to_xdigit(byte & 0x0f); return rv; } std::map> annotations_; protected: t_type() : program_(nullptr) { ; } t_type(t_program* program) : program_(program) { ; } t_type(t_program* program, std::string name) : program_(program), name_(name) { ; } t_type(std::string name) : program_(nullptr), name_(name) { ; } t_program* program_; std::string name_; }; /** * Placeholder struct for returning the key and value of an annotation * during parsing. */ struct t_annotation { std::string key; std::string val; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_const.h0000644000000000000000000000303514303740367022526 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_CONST_H #define T_CONST_H #include "thrift/parse/t_type.h" #include "thrift/parse/t_const_value.h" /** * A const is a constant value defined across languages that has a type and * a value. The trick here is that the declared type might not match the type * of the value object, since that is not determined until after parsing the * whole thing out. * */ class t_const : public t_doc { public: t_const(t_type* type, std::string name, t_const_value* value) : type_(type), name_(name), value_(value) {} t_type* get_type() const { return type_; } std::string get_name() const { return name_; } t_const_value* get_value() const { return value_; } private: t_type* type_; std::string name_; t_const_value* value_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_struct.h0000644000000000000000000001451614370300523022720 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_STRUCT_H #define T_STRUCT_H #include #include #include #include #include "thrift/parse/t_type.h" #include "thrift/parse/t_field.h" // Forward declare that puppy class t_program; /** * A struct is a container for a set of member fields that has a name. Structs * are also used to implement exception types. * */ class t_struct : public t_type { public: typedef std::vector members_type; t_struct(t_program* program) : t_type(program), is_xception_(false), is_union_(false), is_method_xcepts_(false), union_validated_(false), xcepts_validated_(false), members_with_value_(0), xsd_all_(false) {} t_struct(t_program* program, const std::string& name) : t_type(program, name), is_xception_(false), is_union_(false), is_method_xcepts_(false), union_validated_(false), xcepts_validated_(false), members_with_value_(0), xsd_all_(false) {} void set_name(const std::string& name) override { name_ = name; union_validated_= false; validate_members(); } void set_xception(bool is_xception) { is_xception_ = is_xception; } void set_method_xcepts(bool is_method_xcepts) { is_method_xcepts_ = is_method_xcepts; xcepts_validated_ = false; validate_members(); } void set_union(bool is_union) { is_union_ = is_union; union_validated_= false; validate_members(); } void set_xsd_all(bool xsd_all) { xsd_all_ = xsd_all; } bool get_xsd_all() const { return xsd_all_; } bool append(t_field* elem) { typedef members_type::iterator iter_type; std::pair bounds = std::equal_range(members_in_id_order_.begin(), members_in_id_order_.end(), elem, t_field::key_compare()); if (bounds.first != bounds.second) { return false; } // returns false when there is a conflict of field names if (get_field_by_name(elem->get_name()) != nullptr) { return false; } members_.push_back(elem); members_in_id_order_.insert(bounds.second, elem); if (needs_validation()) { validate_members(); } else { validate_member_field(elem); } return true; } const members_type& get_members() const { return members_; } const members_type& get_sorted_members() const { return members_in_id_order_; } bool is_struct() const override { return !is_xception_; } bool is_xception() const override { return is_xception_; } bool is_union() const { return is_union_; } t_field* get_field_by_name(std::string field_name) { return const_cast(const_cast(*this).get_field_by_name(field_name)); } const t_field* get_field_by_name(std::string field_name) const { members_type::const_iterator m_iter; for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { if ((*m_iter)->get_name() == field_name) { return *m_iter; } } return nullptr; } private: members_type members_; members_type members_in_id_order_; bool is_xception_; // struct is an IDL exception bool is_union_; // struct is an IDL union bool is_method_xcepts_; // struct holds the exceptions declared at a service method bool union_validated_; bool xcepts_validated_; int members_with_value_; bool xsd_all_; void validate_member_field(t_field* field) { validate_union_member(field); validate_method_exception_field(field); } void validate_union_member(t_field* field) { if (is_union_ && (!name_.empty())) { union_validated_ = true; // 1) unions can't have required fields // 2) union members are implicitly optional, otherwise bugs like THRIFT-3650 wait to happen if (field->get_req() != t_field::T_OPTIONAL) { // no warning on default requiredness, but do warn on anything else that is explicitly asked for if(field->get_req() != t_field::T_OPT_IN_REQ_OUT) { pwarning(1, "Union %s field %s: union members must be optional, ignoring specified requiredness.\n", name_.c_str(), field->get_name().c_str()); } field->set_req(t_field::T_OPTIONAL); } // unions may have up to one member defaulted, but not more if (field->get_value() != nullptr) { if (1 < ++members_with_value_) { throw "Error: Field " + field->get_name() + " provides another default value for union " + name_; } } } } void validate_method_exception_field(t_field* field) { if (is_method_xcepts_) { xcepts_validated_ = true; // THRIFT-5669: "required" makes no sense at "throws" clauses if (field->get_req() == t_field::T_REQUIRED) { field->set_req(t_field::T_OPT_IN_REQ_OUT); pwarning(1, "Exception field %s: \"required\" is illegal here, ignoring.\n", field->get_name().c_str()); } } } bool needs_validation() { if (is_method_xcepts_) { return !xcepts_validated_; } if (is_union_) { return !union_validated_; } return false; } void validate_members() { if (needs_validation()) { members_type::const_iterator m_iter; for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { validate_member_field(*m_iter); } } } }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/t_set.h0000644000000000000000000000236114303740367022174 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_SET_H #define T_SET_H #include "thrift/parse/t_container.h" /** * A set is a lightweight container type that just wraps another data type. * */ class t_set : public t_container { public: t_set(t_type* elem_type) : elem_type_(elem_type) {} const t_type* get_elem_type() const { return elem_type_; } t_type* get_elem_type() { return elem_type_; } bool is_set() const override { return true; } private: t_type* elem_type_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/parse/parse.cc0000644000000000000000000000224414303740367022326 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "thrift/parse/t_type.h" #include "thrift/parse/t_typedef.h" #include "thrift/main.h" t_type* t_type::get_true_type() { return const_cast(const_cast(this)->get_true_type()); } const t_type* t_type::get_true_type() const { const t_type* type = this; while (type->is_typedef()) { type = ((t_typedef*)type)->get_type(); } return type; } thrift-0.19.0/compiler/cpp/src/thrift/parse/t_typedef.cc0000644000000000000000000000242214303740367023175 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include "thrift/parse/t_typedef.h" #include "thrift/parse/t_program.h" t_type* t_typedef::get_type() { return const_cast(const_cast(this)->get_type()); } const t_type* t_typedef::get_type() const { if (type_ == nullptr) { const t_type* type = get_program()->scope()->get_type(symbolic_); if (type == nullptr) { printf("Type \"%s\" not defined\n", symbolic_.c_str()); exit(1); } return type; } return type_; } thrift-0.19.0/compiler/cpp/src/thrift/parse/t_map.h0000644000000000000000000000245514303740367022162 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_MAP_H #define T_MAP_H #include "thrift/parse/t_container.h" /** * A map is a lightweight container type that just wraps another two data * types. * */ class t_map : public t_container { public: t_map(t_type* key_type, t_type* val_type) : key_type_(key_type), val_type_(val_type) {} t_type* get_key_type() const { return key_type_; } t_type* get_val_type() const { return val_type_; } bool is_map() const override { return true; } private: t_type* key_type_; t_type* val_type_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/common.cc0000644000000000000000000000426614370300523021366 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "thrift/common.h" #include "thrift/parse/t_base_type.h" t_type* g_type_void; t_type* g_type_string; t_type* g_type_binary; t_type* g_type_uuid; t_type* g_type_bool; t_type* g_type_i8; t_type* g_type_i16; t_type* g_type_i32; t_type* g_type_i64; t_type* g_type_double; void initGlobals() { g_type_void = new t_base_type("void", t_base_type::TYPE_VOID); g_type_string = new t_base_type("string", t_base_type::TYPE_STRING); g_type_binary = new t_base_type("string", t_base_type::TYPE_STRING); ((t_base_type*)g_type_binary)->set_binary(true); g_type_uuid = new t_base_type("string", t_base_type::TYPE_UUID); g_type_bool = new t_base_type("bool", t_base_type::TYPE_BOOL); g_type_i8 = new t_base_type("i8", t_base_type::TYPE_I8); g_type_i16 = new t_base_type("i16", t_base_type::TYPE_I16); g_type_i32 = new t_base_type("i32", t_base_type::TYPE_I32); g_type_i64 = new t_base_type("i64", t_base_type::TYPE_I64); g_type_double = new t_base_type("double", t_base_type::TYPE_DOUBLE); } void clearGlobals() { delete g_type_void; delete g_type_string; delete g_type_binary; delete g_type_uuid; delete g_type_bool; delete g_type_i8; delete g_type_i16; delete g_type_i32; delete g_type_i64; delete g_type_double; } /** * The location of the last parsed doctext comment. */ int g_doctext_lineno; int g_program_doctext_lineno = 0; PROGDOCTEXT_STATUS g_program_doctext_status = INVALID; thrift-0.19.0/compiler/cpp/src/thrift/audit/0000755000000000000000000000000014472652642020704 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/src/thrift/audit/t_audit.h0000644000000000000000000000126214303740367022502 0ustar00rootroot00000000000000#ifndef T_AUDIT_H #define T_AUDIT_H void compare_namespace(t_program* newProgram, t_program* oldProgram); void compare_enums(const std::vector& newEnumList, const std::vector& oldEnumList); bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault); void compare_structs(const std::vector& newStructList, const std::vector& oldStructList); void compare_services(const std::vector& newServices, const std::vector& oldServices); void compare_consts(const std::vector& newConst, const std::vector& oldConst); #endif thrift-0.19.0/compiler/cpp/src/thrift/audit/t_audit.cpp0000644000000000000000000004161714303740367023045 0ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include #include #include // Careful: must include globals first for extern definitions #include "thrift/globals.h" #include "thrift/parse/t_program.h" #include "thrift/parse/t_scope.h" #include "thrift/parse/t_const.h" #include "thrift/parse/t_field.h" #include "thrift/version.h" #include "thrift/audit/t_audit.h" extern int g_warn; extern std::string g_curpath; extern bool g_return_failure; void thrift_audit_warning(int level, const char* fmt, ...) { if (g_warn < level) { return; } va_list args; printf("[Thrift Audit Warning:%s] ", g_curpath.c_str()); va_start(args, fmt); vprintf(fmt, args); va_end(args); printf("\n"); } void thrift_audit_failure(const char* fmt, ...) { va_list args; fprintf(stderr, "[Thrift Audit Failure:%s] ", g_curpath.c_str()); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); g_return_failure = true; } void compare_namespace(t_program* newProgram, t_program* oldProgram) { const std::map& newNamespaceMap = newProgram->get_all_namespaces(); const std::map& oldNamespaceMap = oldProgram->get_all_namespaces(); for(const auto & oldNamespaceMapIt : oldNamespaceMap) { auto newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt.first); if(newNamespaceMapIt == newNamespaceMap.end()) { thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt.first).c_str()); } else if((newNamespaceMapIt->second) != oldNamespaceMapIt.second) { thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt.second).c_str()); } } } void compare_enum_values(t_enum* newEnum,t_enum* oldEnum) { const std::vector& oldEnumValues = oldEnum->get_constants(); for(auto oldEnumValue : oldEnumValues) { int enumValue = oldEnumValue->get_value(); t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue); if(newEnumValue != nullptr) { std::string enumName = oldEnumValue->get_name(); if(enumName != newEnumValue->get_name()) { thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str()); } } else { thrift_audit_failure("Enum value %d missing in %s\n", enumValue, oldEnum->get_name().c_str()); } } } void compare_enums(const std::vector& newEnumList, const std::vector& oldEnumList) { std::map newEnumMap; std::vector::const_iterator newEnumIt; for(newEnumIt = newEnumList.begin(); newEnumIt != newEnumList.end(); newEnumIt++) { newEnumMap[(*newEnumIt)->get_name()] = *newEnumIt; } std::vector::const_iterator oldEnumIt; for(oldEnumIt = oldEnumList.begin(); oldEnumIt != oldEnumList.end(); oldEnumIt++) { std::map::iterator newEnumMapIt; newEnumMapIt = newEnumMap.find((*oldEnumIt)->get_name()); if(newEnumMapIt == newEnumMap.end()) { thrift_audit_warning(1, "Enum %s not found in new thrift file\n",(*oldEnumIt)->get_name().c_str()); } else { compare_enum_values(newEnumMapIt->second, *oldEnumIt); } } } //This function returns 'true' if the two arguements are of same types. //Returns false if they are of different type bool compare_type(t_type* newType, t_type* oldType) { //Comparing names of two types will work when the newType and oldType are basic types or structs or enums. //However, when they are containers, get_name() returns empty for which we have to compare the type of //their elements as well. if((newType->get_name()).empty() && (oldType->get_name()).empty()) { if(newType->is_list() && oldType->is_list()) { t_type* newElementType = ((t_list*)newType)->get_elem_type(); t_type* oldElementType = ((t_list*)oldType)->get_elem_type(); return compare_type(newElementType, oldElementType); } else if(newType->is_map() && oldType->is_map()) { t_type* newKeyType = ((t_map*)newType)->get_key_type(); t_type* oldKeyType = ((t_map*)oldType)->get_key_type(); t_type* newValType = ((t_map*)newType)->get_val_type(); t_type* oldValType = ((t_map*)oldType)->get_val_type(); return (compare_type(newKeyType, oldKeyType) && compare_type(newValType, oldValType)); } else if(newType->is_set() && oldType->is_set()) { t_type* newElementType = ((t_set*)newType)->get_elem_type(); t_type* oldElementType = ((t_set*)oldType)->get_elem_type(); return compare_type(newElementType, oldElementType); } else { return false; } } else if(newType->get_name() == oldType->get_name()) { return true; } else { return false; } } bool compare_pair(std::pair newMapPair, std::pair oldMapPair) { return compare_defaults(newMapPair.first, oldMapPair.first) && compare_defaults(newMapPair.second, oldMapPair.second); } // This function returns 'true' if the default values are same. Returns false if they are different. bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault) { if(newStructDefault == nullptr && oldStructDefault == nullptr) return true; else if(newStructDefault == nullptr && oldStructDefault != nullptr) return false; else if (newStructDefault != nullptr && oldStructDefault == nullptr) return false; if(newStructDefault->get_type() != oldStructDefault->get_type()) { return false; } switch(newStructDefault->get_type()) { case t_const_value::CV_INTEGER: return (newStructDefault->get_integer() == oldStructDefault->get_integer()); case t_const_value::CV_DOUBLE: return (newStructDefault->get_double() == oldStructDefault->get_double()); case t_const_value::CV_STRING: return (newStructDefault->get_string() == oldStructDefault->get_string()); case t_const_value::CV_LIST: { const std::vector& oldDefaultList = oldStructDefault->get_list(); const std::vector& newDefaultList = newStructDefault->get_list(); bool defaultValuesCompare = (oldDefaultList.size() == newDefaultList.size()); return defaultValuesCompare && std::equal(newDefaultList.begin(), newDefaultList.end(), oldDefaultList.begin(), compare_defaults); } case t_const_value::CV_MAP: { const std::map newMap = newStructDefault->get_map(); const std::map oldMap = oldStructDefault->get_map(); bool defaultValuesCompare = (oldMap.size() == newMap.size()); return defaultValuesCompare && std::equal(newMap.begin(), newMap.end(), oldMap.begin(), compare_pair); } case t_const_value::CV_IDENTIFIER: return (newStructDefault->get_identifier() == oldStructDefault->get_identifier()); default: return false; } } void compare_struct_field(t_field* newField, t_field* oldField, std::string oldStructName) { t_type* newFieldType = newField->get_type(); t_type* oldFieldType = oldField->get_type(); if(!compare_type(newFieldType, oldFieldType)) { thrift_audit_failure("Struct Field Type Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str()); } // A Struct member can be optional if it is mentioned explicitly, or if it is assigned with default values. bool newStructFieldOptional = (newField->get_req() != t_field::T_REQUIRED); bool oldStructFieldOptional = (oldField->get_req() != t_field::T_REQUIRED); if(newStructFieldOptional != oldStructFieldOptional) { thrift_audit_failure("Struct Field Requiredness Changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str()); } if(newStructFieldOptional || oldStructFieldOptional) { if(!compare_defaults(newField->get_value(), oldField->get_value())) { thrift_audit_warning(1, "Default value changed for Id = %d in %s \n", newField->get_key(), oldStructName.c_str()); } } std::string fieldName = newField->get_name(); if(fieldName != oldField->get_name()) { thrift_audit_warning(1, "Struct field name changed for Id = %d in %s\n", newField->get_key(), oldStructName.c_str()); } } void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std::string& oldStructName = std::string()) { std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName; const std::vector& oldStructMembersInIdOrder = oldStruct->get_sorted_members(); const std::vector& newStructMembersInIdOrder = newStruct->get_sorted_members(); auto oldStructMemberIt = oldStructMembersInIdOrder.begin(); auto newStructMemberIt = newStructMembersInIdOrder.begin(); // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member // lists together. while(!(oldStructMemberIt == oldStructMembersInIdOrder.end() && newStructMemberIt == newStructMembersInIdOrder.end())) { if(newStructMemberIt == newStructMembersInIdOrder.end() && oldStructMemberIt != oldStructMembersInIdOrder.end()) { // A field ID has been removed from the end. thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str()); oldStructMemberIt++; } else if(newStructMemberIt != newStructMembersInIdOrder.end() && oldStructMemberIt == oldStructMembersInIdOrder.end()) { //New field ID has been added to the end. if((*newStructMemberIt)->get_req() == t_field::T_REQUIRED) { thrift_audit_failure("Required Struct Field Added for Id = %d in %s \n", (*newStructMemberIt)->get_key(), structName.c_str()); } newStructMemberIt++; } else if((*newStructMemberIt)->get_key() == (*oldStructMemberIt)->get_key()) { //Field ID found in both structs. Compare field types, default values. compare_struct_field(*newStructMemberIt, *oldStructMemberIt, structName); newStructMemberIt++; oldStructMemberIt++; } else if((*newStructMemberIt)->get_key() < (*oldStructMemberIt)->get_key()) { //New Field Id is inserted in between //Adding fields to struct is fine, but adding them in the middle is suspicious. Error!! thrift_audit_failure("Struct field is added in the middle with Id = %d in %s\n", (*newStructMemberIt)->get_key(), structName.c_str()); newStructMemberIt++; } else if((*newStructMemberIt)->get_key() > (*oldStructMemberIt)->get_key()) { //A field is deleted in newStruct. thrift_audit_failure("Struct Field removed for Id = %d in %s \n", (*oldStructMemberIt)->get_key(), structName.c_str()); oldStructMemberIt++; } } } void compare_structs(const std::vector& newStructList, const std::vector& oldStructList) { std::map newStructMap; std::vector::const_iterator newStructListIt; for(newStructListIt = newStructList.begin(); newStructListIt != newStructList.end(); newStructListIt++) { newStructMap[(*newStructListIt)->get_name()] = *newStructListIt; } std::vector::const_iterator oldStructListIt; for(oldStructListIt = oldStructList.begin(); oldStructListIt != oldStructList.end(); oldStructListIt++) { std::map::iterator newStructMapIt; newStructMapIt = newStructMap.find((*oldStructListIt)->get_name()); if(newStructMapIt == newStructMap.end()) { thrift_audit_failure("Struct %s not found in new thrift file\n", (*oldStructListIt)->get_name().c_str()); } else { compare_single_struct(newStructMapIt->second, *oldStructListIt); } } } void compare_single_function(t_function* newFunction, t_function* oldFunction) { t_type* newFunctionReturnType = newFunction->get_returntype(); if(newFunction->is_oneway() != oldFunction->is_oneway()) { thrift_audit_failure("Oneway attribute changed for function %s\n",oldFunction->get_name().c_str()); } if(!compare_type(newFunctionReturnType, oldFunction->get_returntype())) { thrift_audit_failure("Return type changed for function %s\n",oldFunction->get_name().c_str()); } //Compare function arguments. compare_single_struct(newFunction->get_arglist(), oldFunction->get_arglist()); std::string exceptionName = oldFunction->get_name(); exceptionName += "_exception"; compare_single_struct(newFunction->get_xceptions(), oldFunction->get_xceptions(), exceptionName); } void compare_functions(const std::vector& newFunctionList, const std::vector& oldFunctionList) { std::map newFunctionMap; std::map::iterator newFunctionMapIt; for(auto newFunctionIt : newFunctionList) { newFunctionMap[newFunctionIt->get_name()] = newFunctionIt; } for(auto oldFunctionIt : oldFunctionList) { newFunctionMapIt = newFunctionMap.find(oldFunctionIt->get_name()); if(newFunctionMapIt == newFunctionMap.end()) { thrift_audit_failure("New Thrift File has missing function %s\n",oldFunctionIt->get_name().c_str()); continue; } else { //Function is found in both thrift files. Compare return type and argument list compare_single_function(newFunctionMapIt->second, oldFunctionIt); } } } void compare_services(const std::vector& newServices, const std::vector& oldServices) { std::vector::const_iterator oldServiceIt; std::map newServiceMap; for(auto newService : newServices) { newServiceMap[newService->get_name()] = newService; } for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++) { const std::string oldServiceName = (*oldServiceIt)->get_name(); auto newServiceMapIt = newServiceMap.find(oldServiceName); if(newServiceMapIt == newServiceMap.end()) { thrift_audit_failure("New Thrift file is missing a service %s\n", oldServiceName.c_str()); } else { t_service* oldServiceExtends = (*oldServiceIt)->get_extends(); t_service* newServiceExtends = (newServiceMapIt->second)->get_extends(); if(oldServiceExtends == nullptr) { // It is fine to add extends. So if service in older thrift did not have any extends, we are fine. // DO Nothing } else if(oldServiceExtends != nullptr && newServiceExtends == nullptr) { thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str()); } else { std::string oldExtendsName = oldServiceExtends->get_name(); std::string newExtendsName = newServiceExtends->get_name(); if( newExtendsName != oldExtendsName) { thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str()); } } compare_functions((newServiceMapIt->second)->get_functions(), (*oldServiceIt)->get_functions()); } } } void compare_consts(const std::vector& newConst, const std::vector& oldConst) { std::vector::const_iterator newConstIt; std::vector::const_iterator oldConstIt; std::map newConstMap; for(newConstIt = newConst.begin(); newConstIt != newConst.end(); newConstIt++) { newConstMap[(*newConstIt)->get_name()] = *newConstIt; } std::map::const_iterator newConstMapIt; for(oldConstIt = oldConst.begin(); oldConstIt != oldConst.end(); oldConstIt++) { newConstMapIt = newConstMap.find((*oldConstIt)->get_name()); if(newConstMapIt == newConstMap.end()) { thrift_audit_warning(1, "Constants Missing %s \n", ((*oldConstIt)->get_name()).c_str()); } else if(!compare_type((newConstMapIt->second)->get_type(), (*oldConstIt)->get_type())) { thrift_audit_warning(1, "Constant %s is of different type \n", ((*oldConstIt)->get_name()).c_str()); } else if(!compare_defaults((newConstMapIt->second)->get_value(), (*oldConstIt)->get_value())) { thrift_audit_warning(1, "Constant %s has different value\n", ((*oldConstIt)->get_name()).c_str()); } } } thrift-0.19.0/compiler/cpp/src/thrift/version.h0000644000000000000000000000175014454461475021441 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_VERSION_H_ #define _THRIFT_VERSION_H_ 1 #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #define THRIFT_VERSION "0.19.0" #endif // _THRIFT_VERSION_H_ thrift-0.19.0/compiler/cpp/src/thrift/generate/0000755000000000000000000000000014472652643021371 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/src/thrift/generate/t_haxe_generator.cc0000644000000000000000000031473314452237057025225 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * Haxe code generator. * */ class t_haxe_generator : public t_oop_generator { public: t_haxe_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; rtti_ = false; buildmacro_ = ""; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("callbacks") == 0) { printf("Hint: The 'callbacks' option is no longer necessary.\n"); } else if( iter->first.compare("rtti") == 0) { rtti_ = true; } else if( iter->first.compare("buildmacro") == 0) { buildmacro_ = (iter->second); } else { throw "unknown option haxe:" + iter->first; } } out_dir_base_ = "gen-haxe"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(std::vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value); void render_const_value(std::ostream& out, t_type* type, t_const_value* value); void render_struct_initializer(std::ostream& out, t_struct* type, t_const_value* value); void render_map_initializer(std::ostream& out, t_map* type, t_const_value* value); void render_list_initializer(std::ostream& out, t_list* type, t_const_value* value); void render_set_initializer(std::ostream& out, t_set* type, t_const_value* value); // helper std::string render_const_value_str( t_type* type, t_const_value* value); /** * Service-level generation functions */ void generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result = false); void generate_haxe_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool is_result = false); // removed -- equality,compare_to void generate_haxe_struct_reader(std::ostream& out, t_struct* tstruct); void generate_haxe_validator(std::ostream& out, t_struct* tstruct); void generate_haxe_struct_result_writer(std::ostream& out, t_struct* tstruct); void generate_haxe_struct_writer(std::ostream& out, t_struct* tstruct); void generate_haxe_struct_tostring(std::ostream& out, t_struct* tstruct, bool is_override); void generate_haxe_meta_data_map(std::ostream& out, t_struct* tstruct); void generate_field_value_meta_data(std::ostream& out, t_type* type); std::string get_haxe_type_string(t_type* type); void generate_reflection_setters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name); void generate_reflection_getters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name); void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct); void generate_generic_isset_method(std::ostream& out, t_struct* tstruct); void generate_property_getters_setters(std::ostream& out, t_struct* tstruct); void generate_function_helpers(t_function* tfunction); std::string get_cap_name(std::string name); std::string generate_isset_check(t_field* field); std::string generate_isset_check(std::string field); void generate_isset_set(ostream& out, t_field* field); // removed std::string isset_field_id(t_field* field); void generate_service_interface(t_service* tservice, bool combined); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); void generate_service_method_signature(t_function* tfunction, bool is_interface, bool combined); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter, std::string map); void generate_haxe_doc(std::ostream& out, t_doc* tdoc); void generate_haxe_doc(std::ostream& out, t_function* tdoc); void generate_rtti_decoration(std::ostream& out); void generate_macro_decoration(std::ostream& out); /** * Helper rendering functions */ std::string haxe_package(); std::string haxe_type_imports(); std::string haxe_thrift_imports(); std::string haxe_thrift_gen_imports(t_struct* tstruct, string& imports); std::string haxe_thrift_gen_imports(t_service* tservice); std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false); std::string base_type_name(t_base_type* tbase, bool in_container = false); std::string declare_field(t_field* tfield, bool init = false); std::string render_default_value_for_type(t_type* type, bool allow_null); std::string function_signature_combined(t_function* tfunction); std::string function_signature_normal(t_function* tfunction); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string get_enum_class_name(t_type* type) override; string generate_service_method_onsuccess(t_function* tfunction, bool as_type, bool omit_name); void generate_service_method_signature_combined(t_function* tfunction, bool is_interface); void generate_service_method_signature_normal(t_function* tfunction, bool is_interface); void generate_deprecation_attribute(ostream& out, t_function* func, bool as_comment); string make_haxe_string_literal( string const& value); bool type_can_be_null(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string()) { return true; } if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: // case t_base_type::TYPE_I64: - Int64 is not really nullable, even though it behaved that // way before Haxe 3.2.0 return true; default: return false; } } return false; } std::string constant_name(std::string name); std::string make_package_name(std::string value); private: bool rtti_; string buildmacro_; /** * File streams */ std::string package_name_; ofstream_with_content_based_conditional_update f_service_; std::string package_dir_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_haxe_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); package_name_ = make_package_name( program_->get_namespace("haxe")); string dir = package_name_; string subdir = get_out_dir(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } if (dir.size() > 0) { subdir = subdir + "/" + dir; MKDIR(subdir.c_str()); } package_dir_ = subdir; } // Haxe package names start with lowercase letters std::string t_haxe_generator::make_package_name(std::string value) { std::string retval(value); if (retval.length() > 0) { retval[0] = tolower(retval[0]); size_t index = retval.find('.'); while (index != std::string::npos) { if (++index < retval.length()) { retval[index] = tolower(retval[index]); } index = retval.find('.', index); } } return retval; } /** * Packages the generated file * * @return String of the package, i.e. "package org.apache.thriftdemo;" */ string t_haxe_generator::haxe_package() { if (!package_name_.empty()) { return string("package ") + package_name_; } return "package"; } /** * Prints standard haxe imports * * @return List of imports for haxe types that are used in here */ string t_haxe_generator::haxe_type_imports() { return string() + "import org.apache.thrift.helper.*;\n" + "import haxe.io.Bytes;\n" + "import haxe.ds.IntMap;\n" + "import haxe.ds.StringMap;\n" + "import haxe.ds.ObjectMap;\n" + "import org.apache.thrift.helper.ObjectSet;\n" + "\n" + "#if flash\n" + "import flash.errors.ArgumentError;\n" + "#end\n" + "\n"; } /** * Prints standard haxe imports * * @return List of imports necessary for thrift */ string t_haxe_generator::haxe_thrift_imports() { return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n" + "import org.apache.thrift.protocol.*;\n" + "\n"; } /** * Prints imports needed for a given type * * @return List of imports necessary for a given t_struct */ string t_haxe_generator::haxe_thrift_gen_imports(t_struct* tstruct, string& imports) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; // For each type check if it is from a different namespace for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_program* program = (*m_iter)->get_type()->get_program(); if (program != nullptr && program != program_) { string package = make_package_name( program->get_namespace("haxe")); if (!package.empty()) { if (imports.find(package + "." + (*m_iter)->get_type()->get_name()) == string::npos) { imports.append("import " + package + "." + (*m_iter)->get_type()->get_name() + ";\n"); } } } } return imports; } /** * Prints imports needed for a given type * * @return List of imports necessary for a given t_service */ string t_haxe_generator::haxe_thrift_gen_imports(t_service* tservice) { string imports; const vector& functions = tservice->get_functions(); vector::const_iterator f_iter; // For each type check if it is from a different namespace for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_program* program = (*f_iter)->get_returntype()->get_program(); if (program != nullptr && program != program_) { string package = make_package_name( program->get_namespace("haxe")); if (!package.empty()) { if (imports.find(package + "." + (*f_iter)->get_returntype()->get_name()) == string::npos) { imports.append("import " + package + "." + (*f_iter)->get_returntype()->get_name()+ ";\n"); } } } haxe_thrift_gen_imports((*f_iter)->get_arglist(), imports); haxe_thrift_gen_imports((*f_iter)->get_xceptions(), imports); } return imports; } /** * Nothing in haxe */ void t_haxe_generator::close_generator() { } /** * Generates a typedef. This is not done in haxe, since it does * not support arbitrary name replacements, and it'd be a wacky waste * of overhead to make wrapper classes. * * @param ttypedef The type definition */ void t_haxe_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Enums are a class with a set of static constants. * * @param tenum The enumeration */ void t_haxe_generator::generate_enum(t_enum* tenum) { // Make output file string f_enum_name = package_dir_ + "/" + get_cap_name(tenum->get_name()) + ".hx"; ofstream_with_content_based_conditional_update f_enum; f_enum.open(f_enum_name.c_str()); // Comment and package it f_enum << autogen_comment() << haxe_package() << ";" << endl << endl; // Add haxe imports f_enum << string() + "import org.apache.thrift.helper.*;" << endl << endl; generate_rtti_decoration(f_enum); generate_macro_decoration(f_enum); indent(f_enum) << "class " << get_cap_name(tenum->get_name()) << " "; scope_up(f_enum); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); indent(f_enum) << "public static inline var " << (*c_iter)->get_name() << " : Int = " << value << ";" << endl; } // Create a static Set with all valid values for this enum f_enum << endl; indent(f_enum) << "public static var VALID_VALUES = { new IntSet( ["; indent_up(); bool firstValue = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { // populate set f_enum << (firstValue ? "" : ", ") << (*c_iter)->get_name(); firstValue = false; } indent_down(); f_enum << "]); };" << endl; indent(f_enum) << "public static var VALUES_TO_NAMES = { ["; indent_up(); firstValue = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { f_enum << (firstValue ? "" : ",") << endl; indent(f_enum) << (*c_iter)->get_name() << " => \"" << (*c_iter)->get_name() << "\""; firstValue = false; } f_enum << endl; indent_down(); indent(f_enum) << "]; };" << endl; scope_down(f_enum); // end class f_enum.close(); } /** * Generates a class that holds all the constants. */ void t_haxe_generator::generate_consts(std::vector consts) { if (consts.empty()) { return; } string f_consts_name = package_dir_ + "/" + get_cap_name(program_name_) + "Constants.hx"; ofstream_with_content_based_conditional_update f_consts; f_consts.open(f_consts_name.c_str()); // Print header f_consts << autogen_comment() << haxe_package() << ";" << endl << endl; f_consts << endl; f_consts << haxe_type_imports(); generate_rtti_decoration(f_consts); generate_macro_decoration(f_consts); indent(f_consts) << "class " << get_cap_name(program_name_) << "Constants {" << endl << endl; indent_up(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { print_const_value(f_consts, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value()); } indent_down(); indent(f_consts) << "}" << endl; f_consts.close(); } void t_haxe_generator::print_const_value(std::ostream& out, string name, t_type* type, t_const_value* value) { type = get_true_type(type); bool complex = type->is_struct() || type->is_xception() || type->is_map() || type->is_list() || type->is_set(); indent(out); out << "public static "; if (!complex) { out << "inline "; } out << "var " << name; if (complex) { out << " (default,null)"; } out << " : " << get_cap_name(type_name(type)) << " = "; render_const_value(out, type, value); out << ";" << endl << endl; } std::string t_haxe_generator::render_const_value_str( t_type* type, t_const_value* value) { std::ostringstream render; render_const_value(render, type, value); return render.str(); } void t_haxe_generator::render_const_value(std::ostream& out, t_type* type, t_const_value* value) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_UUID: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: out << "(byte)" << value->get_integer(); break; case t_base_type::TYPE_I16: out << "(short)" << value->get_integer(); break; case t_base_type::TYPE_I32: out << value->get_integer(); break; case t_base_type::TYPE_I64: out << value->get_integer() << "L"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << "(double)" << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { render_struct_initializer(out, (t_struct*)type, value); } else if (type->is_map()) { render_map_initializer(out, (t_map*)type, value); } else if (type->is_list()) { render_list_initializer(out, (t_list*)type, value); } else if (type->is_set()) { render_set_initializer(out, (t_set*)type, value); } else { throw "compiler error: no const of type " + type->get_name(); } } void t_haxe_generator::render_struct_initializer(std::ostream& out, t_struct* type, t_const_value* value) { out << "(function() : " << get_cap_name(type_name(type)) << " {" << endl; indent_up(); indent(out) << "var tmp = new " << get_cap_name(type_name(type)) << "();" << endl; const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& values = value->get_map(); map::const_iterator v_iter; for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); break; } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } indent(out) << "tmp." << v_iter->first->get_string() << " = "; render_const_value(out, field_type, v_iter->second); out << ";" << endl; } indent(out) << "return tmp;" << endl; indent_down(); indent(out) << "})()"; // no endl } void t_haxe_generator::render_map_initializer(std::ostream& out, t_map* type, t_const_value* value) { out << "(function() : " << get_cap_name(type_name(type)) << " {" << endl; indent_up(); indent(out) << "var tmp = new " << get_cap_name(type_name(type)) << "();" << endl; t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); const map& values = value->get_map(); map::const_iterator v_iter; for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) { indent(out) << "tmp.set("; render_const_value(out, key_type, v_iter->first); out << ", "; render_const_value(out, val_type, v_iter->second); out << ");" << endl; } indent(out) << "return tmp;" << endl; indent_down(); indent(out) << "})()"; // no endl } void t_haxe_generator::render_list_initializer(std::ostream& out, t_list* type, t_const_value* value) { out << "(function() : " << get_cap_name(type_name(type)) << " {" << endl; indent_up(); indent(out) << "var tmp = new " << get_cap_name(type_name(type)) << "();" << endl; t_type* elm_type = type->get_elem_type(); const vector& values = value->get_list(); vector::const_iterator v_iter; for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) { indent(out) << "tmp.add("; render_const_value(out, elm_type, *v_iter); out << ");" << endl; } indent(out) << "return tmp;" << endl; indent_down(); indent(out) << "})()"; // no endl } void t_haxe_generator::render_set_initializer(std::ostream& out, t_set* type, t_const_value* value) { out << "(function() : " << get_cap_name(type_name(type)) << " {" << endl; indent_up(); indent(out) << "var tmp = new " << get_cap_name(type_name(type)) << "();" << endl; t_type* elm_type = type->get_elem_type(); const vector& values = value->get_list(); vector::const_iterator v_iter; for (v_iter = values.begin(); v_iter != values.end(); ++v_iter) { indent(out) << "tmp.add("; render_const_value(out, elm_type, *v_iter); out << ");" << endl; } indent(out) << "return tmp;" << endl; indent_down(); indent(out) << "})()"; // no endl } /** * Generates a struct definition for a thrift data type. This is a class * with data members, read(), write(), and an inner Isset class. * * @param tstruct The struct definition */ void t_haxe_generator::generate_struct(t_struct* tstruct) { generate_haxe_struct(tstruct, false); } /** * Exceptions are structs, but they inherit from Exception * * @param tstruct The struct definition */ void t_haxe_generator::generate_xception(t_struct* txception) { generate_haxe_struct(txception, true); } /** * Haxe struct definition. * * @param tstruct The struct definition */ void t_haxe_generator::generate_haxe_struct(t_struct* tstruct, bool is_exception, bool is_result) { // Make output file string f_struct_name = package_dir_ + "/" + get_cap_name(tstruct->get_name()) + ".hx"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << haxe_package() << ";" << endl; f_struct << endl; string imports; f_struct << haxe_type_imports() << haxe_thrift_imports() << haxe_thrift_gen_imports(tstruct, imports) << endl; generate_haxe_struct_definition(f_struct, tstruct, is_exception, is_result); f_struct.close(); } /** * haxe struct definition. This has various parameters, as it could be * generated standalone or inside another class as a helper. If it * is a helper than it is a static class. * * @param tstruct The struct definition * @param is_exception Is this an exception? * @param in_class If inside a class, needs to be static class * @param is_result If this is a result it needs a different writer */ void t_haxe_generator::generate_haxe_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool is_result) { generate_haxe_doc(out, tstruct); string clsname = get_cap_name(tstruct->get_name()); generate_rtti_decoration(out); generate_macro_decoration(out); indent(out) << "class " << clsname << " "; if (is_exception) { out << "extends TException "; } out << "implements TBase {" << endl << endl; indent_up(); indent(out) << "static var STRUCT_DESC = { new TStruct(\"" << tstruct->get_name() << "\"); };" << endl; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "static var " << constant_name((*m_iter)->get_name()) << "_FIELD_DESC = { new TField(\"" << (*m_iter)->get_name() << "\", " << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << "); };" << endl; } out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_haxe_doc(out, *m_iter); // indent(out) << "private var _" << (*m_iter)->get_name() + " : " + // type_name((*m_iter)->get_type()) << ";" << endl; indent(out) << "@:isVar" << endl; indent(out) << "public var " << (*m_iter)->get_name() + "(get,set) : " + get_cap_name(type_name((*m_iter)->get_type())) << ";" << endl; } out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "inline static var " << upcase_string((*m_iter)->get_name()) << "_FIELD_ID : Int = " << (*m_iter)->get_key() << ";" << endl; } out << endl; // Inner Isset class if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!type_can_be_null((*m_iter)->get_type())) { indent(out) << "private var __isset_" << (*m_iter)->get_name() << " : Bool = false;" << endl; } } } out << endl; // Static initializer to populate global class to struct metadata map if (false) { // TODO: reactivate when needed generate_haxe_meta_data_map(out, tstruct); indent(out) << "{" << endl; indent_up(); indent(out) << "FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ", metaDataMap);" << endl; indent_down(); indent(out) << "}" << endl; indent(out) << "}" << endl; } // Default constructor indent(out) << "public function new() {" << endl; indent_up(); if (is_exception) { indent(out) << "super();" << endl; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_value() != nullptr) { indent(out) << "this." << (*m_iter)->get_name() << " = "; render_const_value( out, (*m_iter)->get_type(), (*m_iter)->get_value()); out << ";" << endl; } } indent_down(); indent(out) << "}" << endl << endl; generate_property_getters_setters(out, tstruct); generate_generic_field_getters_setters(out, tstruct); generate_generic_isset_method(out, tstruct); generate_haxe_struct_reader(out, tstruct); if (is_result) { generate_haxe_struct_result_writer(out, tstruct); } else { generate_haxe_struct_writer(out, tstruct); } generate_haxe_struct_tostring(out, tstruct, is_exception); generate_haxe_validator(out, tstruct); scope_down(out); out << endl; } /** * Generates a function to read all the fields of the struct. * * @param tstruct The struct definition */ void t_haxe_generator::generate_haxe_struct_reader(ostream& out, t_struct* tstruct) { out << indent() << "public function read( iprot : TProtocol) : Void {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent(out) << "iprot.IncrementRecursionDepth();" << endl; indent(out) << "try" << endl; scope_up(out); // Declare stack tmp variables and read struct header out << indent() << "var field : TField;" << endl << indent() << "iprot.readStructBegin();" << endl; // Loop over reading in fields indent(out) << "while (true)" << endl; scope_up(out); // Read beginning field marker indent(out) << "field = iprot.readFieldBegin();" << endl; // Check for field STOP marker and break indent(out) << "if (field.type == TType.STOP) { " << endl; indent_up(); indent(out) << "break;" << endl; indent_down(); indent(out) << "}" << endl; // Switch statement on the field we are reading indent(out) << "switch (field.id)" << endl; scope_up(out); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << upcase_string((*f_iter)->get_name()) << "_FIELD_ID:" << endl; indent_up(); indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, "this."); generate_isset_set(out, *f_iter); indent_down(); out << indent() << "} else { " << endl << indent() << " TProtocolUtil.skip(iprot, field.type);" << endl << indent() << "}" << endl; indent_down(); } // In the default case we skip the field out << indent() << "default:" << endl << indent() << " TProtocolUtil.skip(iprot, field.type);" << endl; scope_down(out); // Read field end marker indent(out) << "iprot.readFieldEnd();" << endl; scope_down(out); out << indent() << "iprot.readStructEnd();" << endl << endl; indent(out) << "iprot.DecrementRecursionDepth();" << endl; scope_down(out); indent(out) << "catch(e:Dynamic)" << endl; scope_up(out); indent(out) << "iprot.DecrementRecursionDepth();" << endl; indent(out) << "throw e;" << endl; scope_down(out); // check for required fields of primitive type // (which can be checked here but not in the general validate method) out << endl << indent() << "// check for required fields of primitive type, which can't be " "checked in the validate method" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) { out << indent() << "if (!__isset_" << (*f_iter)->get_name() << ") {" << endl << indent() << " throw new TProtocolException(TProtocolException.UNKNOWN, \"Required field '" << (*f_iter)->get_name() << "' was not found in serialized data! Struct: \" + toString());" << endl << indent() << "}" << endl; } } // performs various checks (e.g. check that all required fields are set) indent(out) << "validate();" << endl; indent_down(); out << indent() << "}" << endl << endl; } // generates haxe method to perform various checks // (e.g. check that all required fields are set) void t_haxe_generator::generate_haxe_validator(ostream& out, t_struct* tstruct) { indent(out) << "public function validate() : Void {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; out << indent() << "// check for required fields" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { if (type_can_be_null((*f_iter)->get_type())) { indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl; indent(out) << " throw new TProtocolException(TProtocolException.UNKNOWN, \"Required field '" << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl; indent(out) << "}" << endl; } else { indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name() << "' because it's a primitive." << endl; } } } // check that fields of type enum have valid values out << indent() << "// check that fields of type enum have valid values" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); t_type* type = field->get_type(); // if field is an enum, check that its value is valid if (type->is_enum()) { indent(out) << "if (" << generate_isset_check(field) << " && !" << get_cap_name(get_enum_class_name(type)) << ".VALID_VALUES.contains(" << field->get_name() << ")){" << endl; indent_up(); indent(out) << "throw new TProtocolException(TProtocolException.UNKNOWN, \"The field '" << field->get_name() << "' has been assigned the invalid value \" + " << field->get_name() << ");" << endl; indent_down(); indent(out) << "}" << endl; } } indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a function to write all the fields of the struct * * @param tstruct The struct definition */ void t_haxe_generator::generate_haxe_struct_writer(ostream& out, t_struct* tstruct) { out << indent() << "public function write(oprot:TProtocol) : Void {" << endl; indent_up(); string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; // performs various checks (e.g. check that all required fields are set) indent(out) << "validate();" << endl; indent(out) << "oprot.IncrementRecursionDepth();" << endl; indent(out) << "try" << endl; scope_up(out); indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (could_be_unset) { indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); } bool null_allowed = type_can_be_null((*f_iter)->get_type()); if (null_allowed) { out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl; indent_up(); } indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; if (null_allowed) { indent_down(); indent(out) << "}" << endl; } if (could_be_unset) { indent_down(); indent(out) << "}" << endl; } } indent(out) << "oprot.writeFieldStop();" << endl; indent(out) << "oprot.writeStructEnd();" << endl; indent(out) << "oprot.DecrementRecursionDepth();" << endl; scope_down(out); indent(out) << "catch(e:Dynamic)" << endl; scope_up(out); indent(out) << "oprot.DecrementRecursionDepth();" << endl; indent(out) << "throw e;" << endl; scope_down(out); indent_down(); out << indent() << "}" << endl << endl; } /** * Generates a function to write all the fields of the struct, * which is a function result. These fields are only written * if they are set in the Isset array, and only one of them * can be set at a time. * * @param tstruct The struct definition */ void t_haxe_generator::generate_haxe_struct_result_writer(ostream& out, t_struct* tstruct) { out << indent() << "public function write(oprot:TProtocol) : Void {" << endl; indent_up(); string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent(out) << "oprot.IncrementRecursionDepth();" << endl; indent(out) << "try" << endl; scope_up(out); indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; out << endl << indent() << "if "; } else { out << " else if "; } out << "(this." << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; indent_down(); indent(out) << "}"; } indent(out) << endl; indent(out) << "oprot.writeFieldStop();" << endl; indent(out) << "oprot.writeStructEnd();" << endl; indent(out) << "oprot.DecrementRecursionDepth();" << endl; scope_down(out); indent(out) << "catch(e:Dynamic)" << endl; scope_up(out); indent(out) << "oprot.DecrementRecursionDepth();" << endl; indent(out) << "throw e;" << endl; scope_down(out); indent_down(); out << indent() << "}" << endl << endl; } void t_haxe_generator::generate_reflection_getters(ostringstream& out, t_type* type, string field_name, string cap_name) { (void)type; (void)cap_name; indent(out) << "case " << upcase_string(field_name) << "_FIELD_ID:" << endl; indent_up(); indent(out) << "return this." << field_name << ";" << endl; indent_down(); } void t_haxe_generator::generate_reflection_setters(ostringstream& out, t_type* type, string field_name, string cap_name) { (void)type; (void)cap_name; indent(out) << "case " << upcase_string(field_name) << "_FIELD_ID:" << endl; indent_up(); indent(out) << "if (value == null) {" << endl; indent(out) << " unset" << get_cap_name(field_name) << "();" << endl; indent(out) << "} else {" << endl; indent(out) << " this." << field_name << " = value;" << endl; indent(out) << "}" << endl << endl; indent_down(); } void t_haxe_generator::generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct) { std::ostringstream getter_stream; std::ostringstream setter_stream; // build up the bodies of both the getter and setter at once const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); indent_up(); generate_reflection_setters(setter_stream, type, field_name, cap_name); generate_reflection_getters(getter_stream, type, field_name, cap_name); indent_down(); } // create the setter indent(out) << "public function setFieldValue(fieldID : Int, value : Dynamic) : Void {" << endl; indent_up(); if (fields.size() > 0) { indent(out) << "switch (fieldID) {" << endl; out << setter_stream.str(); indent(out) << "default:" << endl; indent(out) << " throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; indent(out) << "}" << endl; } else { indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; } indent_down(); indent(out) << "}" << endl << endl; // create the getter indent(out) << "public function getFieldValue(fieldID : Int) : Dynamic {" << endl; indent_up(); if (fields.size() > 0) { indent(out) << "switch (fieldID) {" << endl; out << getter_stream.str(); indent(out) << "default:" << endl; indent(out) << " throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; indent(out) << "}" << endl; } else { indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; } indent_down(); indent(out) << "}" << endl << endl; } // Creates a generic isSet method that takes the field number as argument void t_haxe_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // create the isSet method indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a " "value) and false otherwise" << endl; indent(out) << "public function isSet(fieldID : Int) : Bool {" << endl; indent_up(); if (fields.size() > 0) { indent(out) << "switch (fieldID) {" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; indent(out) << "case " << upcase_string(field->get_name()) << "_FIELD_ID:" << endl; indent_up(); indent(out) << "return " << generate_isset_check(field) << ";" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; indent(out) << "}" << endl; } else { indent(out) << "throw new ArgumentError(\"Field \" + fieldID + \" doesn't exist!\");" << endl; } indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a set of property setters/getters for the given struct. * * @param tstruct The struct definition */ void t_haxe_generator::generate_property_getters_setters(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); // Simple getter generate_haxe_doc(out, field); indent(out) << "public function get_" << field_name << "() : " << get_cap_name(type_name(type)) << " {" << endl; indent_up(); indent(out) << "return this." << field_name << ";" << endl; indent_down(); indent(out) << "}" << endl << endl; // Simple setter generate_haxe_doc(out, field); indent(out) << "public function set_" << field_name << "(" << field_name << ":" << get_cap_name(type_name(type)) << ") : " << get_cap_name(type_name(type)) << " {" << endl; indent_up(); indent(out) << "this." << field_name << " = " << field_name << ";" << endl; generate_isset_set(out, field); indent(out) << "return this." << field_name << ";" << endl; indent_down(); indent(out) << "}" << endl << endl; // Unsetter indent(out) << "public function unset" << cap_name << "() : Void {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "this." << field_name << " = null;" << endl; } else { indent(out) << "this.__isset_" << field_name << " = false;" << endl; } indent_down(); indent(out) << "}" << endl << endl; // isSet method indent(out) << "// Returns true if field " << field_name << " is set (has been assigned a value) and false otherwise" << endl; indent(out) << "public function is" << get_cap_name("set") << cap_name << "() : Bool {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "return this." << field_name << " != null;" << endl; } else { indent(out) << "return this.__isset_" << field_name << ";" << endl; } indent_down(); indent(out) << "}" << endl << endl; } } /** * Generates a toString() method for the given struct * * @param tstruct The struct definition */ void t_haxe_generator::generate_haxe_struct_tostring(ostream& out, t_struct* tstruct, bool is_override) { out << indent() << "public "; if( is_override) { out << "override "; } out << "function toString() : String {" << endl; indent_up(); out << indent() << "var ret : String = \"" << tstruct->get_name() << "(\";" << endl; out << indent() << "var first : Bool = true;" << endl << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (could_be_unset) { indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); } t_field* field = (*f_iter); if (!first) { indent(out) << "if (!first) ret += \", \";" << endl; } indent(out) << "ret += \"" << (*f_iter)->get_name() << ":\";" << endl; bool can_be_null = type_can_be_null(field->get_type()); if (can_be_null) { indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl; indent(out) << " ret += \"null\";" << endl; indent(out) << "} else {" << endl; indent_up(); } if (field->get_type()->is_binary()) { indent(out) << " ret += \"BINARY\";" << endl; } else if (field->get_type()->is_enum()) { indent(out) << "var " << field->get_name() << "_name : String = " << get_cap_name(get_enum_class_name(field->get_type())) << ".VALUES_TO_NAMES[this." << (*f_iter)->get_name() << "];" << endl; indent(out) << "if (" << field->get_name() << "_name != null) {" << endl; indent(out) << " ret += " << field->get_name() << "_name;" << endl; indent(out) << " ret += \" (\";" << endl; indent(out) << "}" << endl; indent(out) << "ret += this." << field->get_name() << ";" << endl; indent(out) << "if (" << field->get_name() << "_name != null) {" << endl; indent(out) << " ret += \")\";" << endl; indent(out) << "}" << endl; } else { indent(out) << "ret += this." << (*f_iter)->get_name() << ";" << endl; } if (can_be_null) { indent_down(); indent(out) << "}" << endl; } indent(out) << "first = false;" << endl; if (could_be_unset) { indent_down(); indent(out) << "}" << endl; } first = false; } out << indent() << "ret += \")\";" << endl << indent() << "return ret;" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a static map with meta data to store information such as fieldID to * fieldName mapping * * @param tstruct The struct definition */ void t_haxe_generator::generate_haxe_meta_data_map(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Static Map with fieldID -> FieldMetaData mappings indent(out) << "inline static var metaDataMap : IntMap = new IntMap();" << endl; if (fields.size() > 0) { // Populate map scope_up(out); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; std::string field_name = field->get_name(); indent(out) << "metaDataMap[" << upcase_string(field_name) << "_FIELD_ID] = new FieldMetaData(\"" << field_name << "\", "; // Set field requirement type (required, optional, etc.) if (field->get_req() == t_field::T_REQUIRED) { out << "TFieldRequirementType.REQUIRED, "; } else if (field->get_req() == t_field::T_OPTIONAL) { out << "TFieldRequirementType.OPTIONAL, "; } else { out << "TFieldRequirementType.DEFAULT, "; } // Create value meta data generate_field_value_meta_data(out, field->get_type()); out << ");" << endl; } scope_down(out); } } /** * Returns a string with the haxe representation of the given thrift type * (e.g. for the type struct it returns "TType.STRUCT") */ std::string t_haxe_generator::get_haxe_type_string(t_type* type) { if (type->is_list()) { return "TType.LIST"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_typedef()) { return get_haxe_type_string(((t_typedef*)type)->get_type()); } else if (type->is_base_type()) { switch (((t_base_type*)type)->get_base()) { case t_base_type::TYPE_VOID: return "TType.VOID_"; break; case t_base_type::TYPE_STRING: return "TType.STRING"; break; case t_base_type::TYPE_UUID: return "TType.UUID"; break; case t_base_type::TYPE_BOOL: return "TType.BOOL"; break; case t_base_type::TYPE_I8: return "TType.BYTE"; break; case t_base_type::TYPE_I16: return "TType.I16"; break; case t_base_type::TYPE_I32: return "TType.I32"; break; case t_base_type::TYPE_I64: return "TType.I64"; break; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; break; default: throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_haxe_generator::get_haxe_type_string!"); break; // This should never happen! } } else { throw std::runtime_error( "Unknown thrift type \"" + type->get_name() + "\" passed to t_haxe_generator::get_haxe_type_string!"); // This should never happen! } } void t_haxe_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) { out << endl; indent_up(); indent_up(); if (type->is_struct()) { indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type); } else if (type->is_container()) { if (type->is_list()) { indent(out) << "new ListMetaData(TType.LIST, "; t_type* elem_type = ((t_list*)type)->get_elem_type(); generate_field_value_meta_data(out, elem_type); } else if (type->is_set()) { indent(out) << "new SetMetaData(TType.SET, "; t_type* elem_type = ((t_list*)type)->get_elem_type(); generate_field_value_meta_data(out, elem_type); } else { // map indent(out) << "new MapMetaData(TType.MAP, "; t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); generate_field_value_meta_data(out, key_type); out << ", "; generate_field_value_meta_data(out, val_type); } } else { indent(out) << "new FieldValueMetaData(" << get_haxe_type_string(type); } out << ")"; indent_down(); indent_down(); } /** * Generates a thrift service. In C++, this comprises an entirely separate * header and source file. The header file defines the methods and includes * the data types defined in the main header file, and the implementation * file contains implementations of the basic printer and default interfaces. * * @param tservice The service definition */ void t_haxe_generator::generate_service(t_service* tservice) { // Make service interface file with only "normal" calls string f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "_service.hx"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << haxe_package() << ";" << endl; f_service_ << endl << haxe_type_imports() << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice); if (tservice->get_extends() != nullptr) { t_type* parent = tservice->get_extends(); string parent_namespace = make_package_name( parent->get_program()->get_namespace("haxe")); if (!parent_namespace.empty() && parent_namespace != package_name_) { f_service_ << "import " << type_name(parent) << "_service;" << endl; } } f_service_ << endl; generate_service_interface(tservice,false); f_service_.close(); // Client interface file with dual suppport ("normal" and "callback" style) f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + ".hx"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << haxe_package() << ";" << endl; f_service_ << endl << haxe_type_imports() << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice); if (tservice->get_extends() != nullptr) { t_type* parent = tservice->get_extends(); string parent_namespace = make_package_name( parent->get_program()->get_namespace("haxe")); if (!parent_namespace.empty() && parent_namespace != package_name_) { f_service_ << "import " << type_name(parent) << ";" << endl; } } f_service_ << endl; generate_service_interface(tservice,true); f_service_.close(); // Now make the implementation/client file f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "Impl.hx"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << haxe_package() << ";" << endl << endl << haxe_type_imports() << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice) << endl; if (tservice->get_extends() != nullptr) { t_type* parent = tservice->get_extends(); string parent_namespace = make_package_name( parent->get_program()->get_namespace("haxe")); if (!parent_namespace.empty() && parent_namespace != package_name_) { f_service_ << "import " << type_name(parent) << "Impl;" << endl; } } f_service_ << endl; generate_service_client(tservice); f_service_.close(); // Now make the helper class files generate_service_helpers(tservice); // Now make the processor/server file f_service_name = package_dir_ + "/" + get_cap_name(service_name_) + "Processor.hx"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << haxe_package() << ";" << endl << endl << haxe_type_imports() << haxe_thrift_imports() << haxe_thrift_gen_imports(tservice) << endl; if (!package_name_.empty()) { f_service_ << "import " << package_name_ << ".*;" << endl; f_service_ << "import " << package_name_ << "." << get_cap_name(service_name_).c_str() << "Impl;" << endl; f_service_ << endl; } generate_service_server(tservice); f_service_.close(); } /** * Generates the code snippet for the onSuccess callbacks * * @param tfunction The service function to generate code for. */ string t_haxe_generator::generate_service_method_onsuccess(t_function* tfunction, bool as_type, bool omit_name) { if (tfunction->is_oneway()) { return ""; } string name = ""; if (!omit_name) { name = "onSuccess"; if (as_type) { name += " : "; } } if (tfunction->get_returntype()->is_void()) { if (as_type) { return name + "Void->Void = null"; } else { return name + "() : Void"; } } if (as_type) { return name + type_name(tfunction->get_returntype()) + "->Void = null"; } else { return name + "( retval : " + type_name(tfunction->get_returntype()) + ")"; } } /** * Generates a service method header * * @param tfunction The service function to generate code for. */ void t_haxe_generator::generate_service_method_signature(t_function* tfunction, bool is_interface, bool combined) { if( combined) { generate_service_method_signature_combined(tfunction, is_interface); } else { generate_service_method_signature_normal(tfunction, is_interface); } } /** * Generates a service method header in "normal" style * * @param tfunction The service function to generate code for. */ void t_haxe_generator::generate_service_method_signature_normal(t_function* tfunction, bool is_interface) { if (is_interface) { generate_deprecation_attribute(f_service_, tfunction, true); indent(f_service_) << function_signature_normal(tfunction) << ";" << endl << endl; } else { indent(f_service_) << "public " << function_signature_normal(tfunction) << " {" << endl; } } /** * Generates a service method header in "callback" style * * @param tfunction The service function to generate code for. */ void t_haxe_generator::generate_service_method_signature_combined(t_function* tfunction, bool is_interface) { if (!tfunction->is_oneway()) { std::string on_success_impl = generate_service_method_onsuccess(tfunction, false, false); indent(f_service_) << "// function onError(Dynamic) : Void;" << endl; indent(f_service_) << "// function " << on_success_impl.c_str() << ";" << endl; } if (is_interface) { generate_deprecation_attribute(f_service_, tfunction, false); indent(f_service_) << function_signature_combined(tfunction) << ";" << endl << endl; } else { indent(f_service_) << "public " << function_signature_combined(tfunction) << " {" << endl; } } string t_haxe_generator::make_haxe_string_literal( string const& value) { if (value.length() == 0) { return ""; } std::stringstream result; result << "\""; for (signed char const c: value) { if( (c >= 0) && (c < 32)) { // convert ctrl chars, but leave UTF-8 alone int width = std::min( (int)sizeof(c), 6); result << "\\u{" << std::hex << std::setw(width) << std::setfill('0') << (int)c << '}'; } else if ((c == '\\') || (c == '"')) { result << "\\" << c; } else { result << c; // anything else "as is" } } result << "\""; return result.str(); } void t_haxe_generator::generate_deprecation_attribute(ostream& out, t_function* func, bool as_comment) { auto iter = func->annotations_.find("deprecated"); if( func->annotations_.end() != iter) { if( as_comment) { out << indent() << "// DEPRECATED"; } else { out << indent() << "@:deprecated"; } // empty annotation values end up with "1" somewhere, ignore these as well if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) { string text = make_haxe_string_literal(iter->second.back()); if( as_comment) { out << ": " << text; } else { out << "(" << text << ")"; } } out << endl; } } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_haxe_generator::generate_service_interface(t_service* tservice, bool combined) { string cbk_postfix = combined ? "" : "_service"; string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends_iface = " extends " + tservice->get_extends()->get_name() + cbk_postfix; } vector functions = tservice->get_functions(); vector::iterator f_iter; generate_haxe_doc(f_service_, tservice); generate_rtti_decoration(f_service_); generate_macro_decoration(f_service_); f_service_ << indent() << "interface " << get_cap_name(service_name_) << cbk_postfix << extends_iface << " {" << endl << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_haxe_doc(f_service_, *f_iter); generate_service_method_signature(*f_iter, true, combined); } indent_down(); f_service_ << indent() << "}" << endl << endl; } /** * Generates structs for all the service args and return types * * @param tservice The service */ void t_haxe_generator::generate_service_helpers(t_service* tservice) { f_service_ << endl << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_haxe_struct(ts, false); generate_function_helpers(*f_iter); } } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_haxe_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = get_cap_name(tservice->get_extends()->get_name()); extends_client = " extends " + extends + "Impl"; } generate_rtti_decoration(f_service_); // build macro is inherited from interface indent(f_service_) << "class " << get_cap_name(service_name_) << "Impl" << extends_client << " implements " << get_cap_name(service_name_) << " {" << endl << endl; indent_up(); indent(f_service_) << "public function new( iprot : TProtocol, oprot : TProtocol = null)" << endl; scope_up(f_service_); if (extends.empty()) { f_service_ << indent() << "iprot_ = iprot;" << endl; f_service_ << indent() << "if (oprot == null) {" << endl; indent_up(); f_service_ << indent() << "oprot_ = iprot;" << endl; indent_down(); f_service_ << indent() << "} else {" << endl; indent_up(); f_service_ << indent() << "oprot_ = oprot;" << endl; indent_down(); f_service_ << indent() << "}" << endl; } else { f_service_ << indent() << "super(iprot, oprot);" << endl; } scope_down(f_service_); f_service_ << endl; if (extends.empty()) { f_service_ << indent() << "private var iprot_ : TProtocol;" << endl << indent() << "private var oprot_ : TProtocol;" << endl << indent() << "private var seqid_ : Int;" << endl << endl; indent(f_service_) << "public function getInputProtocol() : TProtocol" << endl; scope_up(f_service_); indent(f_service_) << "return this.iprot_;" << endl; scope_down(f_service_); f_service_ << endl; indent(f_service_) << "public function getOutputProtocol() : TProtocol" << endl; scope_up(f_service_); indent(f_service_) << "return this.oprot_;" << endl; scope_down(f_service_); f_service_ << endl; } // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); // Open function generate_service_method_signature(*f_iter, false, true); indent_up(); // Get the struct of function call params t_struct* arg_struct = (*f_iter)->get_arglist(); string argsname = get_cap_name((*f_iter)->get_name() + "_args"); vector::const_iterator fld_iter; const vector& fields = arg_struct->get_members(); // Serialize the request string args = tmp("args"); string calltype = (*f_iter)->is_oneway() ? "ONEWAY" : "CALL"; f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", TMessageType." << calltype << ", seqid_));" << endl << indent() << "var " << args << " : " << argsname << " = new " << argsname << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << indent() << args << "." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl; } f_service_ << indent() << args << ".write(oprot_);" << endl << indent() << "oprot_.writeMessageEnd();" << endl; string retval = tmp("retval"); if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) { f_service_ << indent() << "var " << retval << " : " << type_name((*f_iter)->get_returntype()) << " = " << render_default_value_for_type((*f_iter)->get_returntype(),true) << ";" << endl; } if ((*f_iter)->is_oneway()) { f_service_ << indent() << "oprot_.getTransport().flush();" << endl; } else { indent(f_service_) << "oprot_.getTransport().flush(function(error:Dynamic) : Void {" << endl; indent_up(); indent(f_service_) << "try {" << endl; indent_up(); string appex = tmp("appex"); indent(f_service_) << "var " << appex << " : TApplicationException;" << endl; string resultname = get_cap_name((*f_iter)->get_name() + "_result"); indent(f_service_) << "if (error != null) {" << endl; indent_up(); indent(f_service_) << "if (onError == null)" << endl; indent_up(); indent(f_service_) << "throw error;" << endl; indent_down(); indent(f_service_) << "onError(error);" << endl; indent(f_service_) << "return;" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; string msg = tmp("msg"); indent(f_service_) << "var " << msg << " : TMessage = iprot_.readMessageBegin();" << endl; indent(f_service_) << "if (" << msg << ".type == TMessageType.EXCEPTION) {" << endl; indent_up(); indent(f_service_) << appex << " = TApplicationException.read(iprot_);" << endl; indent(f_service_) << "iprot_.readMessageEnd();" << endl; indent(f_service_) << "if (onError == null)" << endl; indent_up(); indent(f_service_) << "throw " << appex << ";" << endl; indent_down(); indent(f_service_) << "onError(" << appex << ");" << endl; indent(f_service_) << "return;" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; string result = tmp("result"); indent(f_service_) << "var " << result << " : " << resultname << " = new " << resultname << "();" << endl; indent(f_service_) << "" << result << ".read(iprot_);" << endl; indent(f_service_) << "iprot_.readMessageEnd();" << endl; // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "if (" << result << "." << generate_isset_check("success") << ") {" << endl; indent_up(); indent(f_service_) << "if (onSuccess != null)" << endl; indent_up(); indent(f_service_) << "onSuccess(" << result << ".success);" << endl; indent_down(); indent(f_service_) << retval << " = " << result << ".success;" << endl; indent(f_service_) << "return;" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { indent(f_service_) << "if (" << result << "." << (*x_iter)->get_name() << " != null) {" << endl; indent_up(); indent(f_service_) << "if (onError == null)" << endl; indent_up(); indent(f_service_) << "throw " << result << "." << (*x_iter)->get_name() << ";" << endl; indent_down(); indent(f_service_) << "onError(" << result << "." << (*x_iter)->get_name() << ");" << endl; indent(f_service_) << "return;" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; } // If you get here it's an exception, unless a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "if (onSuccess != null)" << endl; indent_up(); indent(f_service_) << "onSuccess();" << endl; indent_down(); indent(f_service_) << "return;" << endl; } else { indent(f_service_) << appex << " = new TApplicationException(" << "TApplicationException.MISSING_RESULT," << "\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; indent(f_service_) << "if (onError == null)" << endl; indent_up(); indent(f_service_) << "throw " << appex << ";" << endl; indent_down(); indent(f_service_) << "onError(" << appex << ");" << endl; indent(f_service_) << "return;" << endl; } indent_down(); indent(f_service_) << endl; indent(f_service_) << "} catch( e : TException) {" << endl; indent_up(); indent(f_service_) << "if (onError == null)" << endl; indent_up(); indent(f_service_) << "throw e;" << endl; indent_down(); indent(f_service_) << "onError(e);" << endl; indent(f_service_) << "return;" << endl; indent_down(); indent(f_service_) << "}" << endl; indent_down(); indent(f_service_) << "});" << endl << endl; } if (!((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void())) { f_service_ << indent() << "return " << retval << ";" << endl; } // Close function scope_down(f_service_); f_service_ << endl; } indent_down(); indent(f_service_) << "}" << endl; } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_haxe_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; // Extends stuff string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = get_cap_name(type_name(tservice->get_extends())); extends_processor = " extends " + extends + "Processor"; } // Generate the header portion generate_rtti_decoration(f_service_); generate_macro_decoration(f_service_); indent(f_service_) << "class " << get_cap_name(service_name_) << "Processor" << extends_processor << " implements TProcessor {" << endl << endl; indent_up(); f_service_ << indent() << "private var " << get_cap_name(service_name_) << "_iface_ : " << get_cap_name(service_name_) << "_service;" << endl; if (extends.empty()) { f_service_ << indent() << "private var PROCESS_MAP = new StringMap< Int->TProtocol->TProtocol->Void >();" << endl; } f_service_ << endl; indent(f_service_) << "public function new( iface : " << get_cap_name(service_name_) << "_service)" << endl; scope_up(f_service_); if (!extends.empty()) { f_service_ << indent() << "super(iface);" << endl; } f_service_ << indent() << get_cap_name(service_name_) << "_iface_ = iface;" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << indent() << "PROCESS_MAP.set(\"" << (*f_iter)->get_name() << "\", " << (*f_iter)->get_name() << "());" << endl; } scope_down(f_service_); f_service_ << endl; // Generate the server implementation string override = ""; if (tservice->get_extends() != nullptr) { override = "override "; } indent(f_service_) << override << "public function process( iprot : TProtocol, oprot : TProtocol) : Bool" << endl; scope_up(f_service_); f_service_ << indent() << "var msg : TMessage = iprot.readMessageBegin();" << endl; // TODO(mcslee): validate message, was the seqid etc. legit? f_service_ << indent() << "var fn = PROCESS_MAP.get(msg.name);" << endl << indent() << "if (fn == null) {" << endl << indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl << indent() << " iprot.readMessageEnd();" << endl << indent() << " var appex = new TApplicationException(TApplicationException.UNKNOWN_METHOD, " << "\"Invalid method name: '\"+msg.name+\"'\");" << endl << indent() << " oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl << indent() << " appex.write(oprot);" << endl << indent() << " oprot.writeMessageEnd();" << endl << indent() << " oprot.getTransport().flush();" << endl << indent() << " return true;" << endl << indent() << "}" << endl << indent() << "fn( msg.seqid, iprot, oprot);" << endl ; f_service_ << indent() << "return true;" << endl; scope_down(f_service_); f_service_ << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } indent_down(); indent(f_service_) << "}" << endl << endl; } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_haxe_generator::generate_function_helpers(t_function* tfunction) { if (tfunction->is_oneway()) { return; } string resultname = get_cap_name(tfunction->get_name() + "_result"); t_struct result(program_, resultname); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_haxe_struct(&result, false, true); } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_haxe_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; // Open class indent(f_service_) << "private function " << tfunction->get_name() << "() : Int->TProtocol->TProtocol->Void {" << endl; indent_up(); // Open function indent(f_service_) << "return function( seqid : Int, iprot : TProtocol, oprot : TProtocol) : Void" << endl; scope_up(f_service_); string argsname = get_cap_name(tfunction->get_name() + "_args"); string resultname = get_cap_name(tfunction->get_name() + "_result"); f_service_ << indent() << "var args : " << argsname << " = new " << argsname << "();" << endl << indent() << "args.read(iprot);" << endl << indent() << "iprot.readMessageEnd();" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { f_service_ << indent() << "var result : " << resultname << " = new " << resultname << "();" << endl; } // Try block for any function to catch (defined or undefined) exceptions f_service_ << indent() << "try {" << endl; indent_up(); // normal function():result style // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); if (!(tfunction->is_oneway() || tfunction->get_returntype()->is_void())) { f_service_ << "result.success = "; } f_service_ << get_cap_name(service_name_) << "_iface_." << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << ");" << endl; indent_down(); f_service_ << indent() << "}"; if (!tfunction->is_oneway()) { // catch exceptions defined in the IDL for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << " catch (" << (*x_iter)->get_name() << ":" << get_cap_name(type_name((*x_iter)->get_type(), false, false)) << ") {" << endl; if (!tfunction->is_oneway()) { indent_up(); f_service_ << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl; indent_down(); f_service_ << indent() << "}"; } else { f_service_ << "}"; } } } // always catch all exceptions to prevent from service denial string appex = tmp("appex"); f_service_ << " catch (th : Dynamic) {" << endl; indent_up(); indent(f_service_) << "trace(\"Internal error processing " << tfunction->get_name() << "\", th);" << endl; if (!tfunction->is_oneway()) { indent(f_service_) << "var appex = new TApplicationException(TApplicationException.INTERNAL_ERROR, " "\"Internal error processing " << tfunction->get_name() << "\");" << endl; indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl; indent(f_service_) << "appex.write(oprot);" << endl; indent(f_service_) << "oprot.writeMessageEnd();" << endl; indent(f_service_) << "oprot.getTransport().flush();" << endl; } indent(f_service_) << "return;" << endl; indent_down(); f_service_ << indent() << "}" << endl; // Shortcut out here for oneway functions if (tfunction->is_oneway()) { f_service_ << indent() << "return;" << endl; scope_down(f_service_); // Close class indent_down(); f_service_ << indent() << "}" << endl << endl; return; } f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();" << endl << indent() << "oprot.getTransport().flush();" << endl; // Close function scope_down(f_service_); f_service_ << endl; // Close class indent_down(); f_service_ << indent() << "}" << endl << endl; } /** * Deserializes a field of any type. * * @param tfield The field * @param prefix The variable name or container for this field */ void t_haxe_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + tfield->get_name(); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << name << " = iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "readBinary();"; } else { out << "readString();"; } break; case t_base_type::TYPE_UUID: out << "readUuid();"; break; case t_base_type::TYPE_BOOL: out << "readBool();"; break; case t_base_type::TYPE_I8: out << "readByte();"; break; case t_base_type::TYPE_I16: out << "readI16();"; break; case t_base_type::TYPE_I32: out << "readI32();"; break; case t_base_type::TYPE_I64: out << "readI64();"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble();"; break; default: throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "readI32();"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); } } /** * Generates an unserializer for a struct, invokes read() */ void t_haxe_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { out << indent() << prefix << " = new " << get_cap_name(type_name(tstruct)) << "();" << endl << indent() << prefix << ".read(iprot);" << endl; } /** * Deserializes a container by reading its size and then iterating */ void t_haxe_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); string obj; if (ttype->is_map()) { obj = tmp("_map"); } else if (ttype->is_set()) { obj = tmp("_set"); } else if (ttype->is_list()) { obj = tmp("_list"); } // Declare variables, read header if (ttype->is_map()) { indent(out) << "var " << obj << " = iprot.readMapBegin();" << endl; } else if (ttype->is_set()) { indent(out) << "var " << obj << " = iprot.readSetBegin();" << endl; } else if (ttype->is_list()) { indent(out) << "var " << obj << " = iprot.readListBegin();" << endl; } indent(out) << prefix << " = new " << type_name(ttype, false, true) // size the collection correctly << "(" << ");" << endl; // For loop iterates over elements string i = tmp("_i"); indent(out) << "for( " << i << " in 0 ... " << obj << ".size)" << endl; scope_up(out); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } scope_down(out); // Read container end if (ttype->is_map()) { indent(out) << "iprot.readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "iprot.readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "iprot.readListEnd();" << endl; } scope_down(out); } /** * Generates code to deserialize a map */ void t_haxe_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey) << endl; indent(out) << declare_field(&fval) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << prefix << ".set( " << key << ", " << val << ");" << endl; } /** * Deserializes a set element */ void t_haxe_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".add(" << elem << ");" << endl; } /** * Deserializes a list element */ void t_haxe_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".add(" << elem << ");" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_haxe_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name()); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + tfield->get_name()); } else if (type->is_base_type() || type->is_enum()) { string name = prefix + tfield->get_name(); indent(out) << "oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "writeBinary(" << name << ");"; } else { out << "writeString(" << name << ");"; } break; case t_base_type::TYPE_UUID: out << "writeUuid(" << name << ");"; break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ");"; break; default: throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32(" << name << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type_name(type).c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_haxe_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; out << indent() << prefix << ".write(oprot);" << endl; } /** * Serializes a container by writing its size then the elements. * * @param ttype The type of container * @param prefix String prefix for fields */ void t_haxe_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { if (ttype->is_map()) { string iter = tmp("_key"); string counter = tmp("_sizeCounter"); indent(out) << "var " << counter << " : Int = 0;" << endl; indent(out) << "for( " << iter << " in " << prefix << ") {" << endl; indent(out) << " " << counter << +"++;" << endl; indent(out) << "}" << endl; indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << counter << "));" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix << ".size));" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListBegin(new TList(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));" << endl; } string iter = tmp("elem"); if (ttype->is_map()) { indent(out) << "for( " << iter << " in " << prefix << ".keys())" << endl; } else if (ttype->is_set()) { indent(out) << "for( " << iter << " in " << prefix << ".toArray())" << endl; } else if (ttype->is_list()) { indent(out) << "for( " << iter << " in " << prefix << ")" << endl; } scope_up(out); if (ttype->is_map()) { generate_serialize_map_element(out, (t_map*)ttype, iter, prefix); } else if (ttype->is_set()) { generate_serialize_set_element(out, (t_set*)ttype, iter); } else if (ttype->is_list()) { generate_serialize_list_element(out, (t_list*)ttype, iter); } scope_down(out); if (ttype->is_map()) { indent(out) << "oprot.writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListEnd();" << endl; } } /** * Serializes the members of a map. */ void t_haxe_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map) { t_field kfield(tmap->get_key_type(), iter); generate_serialize_field(out, &kfield, ""); t_field vfield(tmap->get_val_type(), map + ".get(" + iter + ")"); generate_serialize_field(out, &vfield, ""); } /** * Serializes the members of a set. */ void t_haxe_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Serializes the members of a list. */ void t_haxe_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Returns a haxe type name * * @param ttype The type * @param container Is the type going inside a container? * @return haxe type name, i.e. HashMap */ string t_haxe_generator::type_name(t_type* ttype, bool in_container, bool in_init) { (void)in_init; // typedefs are just resolved to their real type ttype = get_true_type(ttype); string prefix; if (ttype->is_base_type()) { return base_type_name((t_base_type*)ttype, in_container); } if (ttype->is_enum()) { return "Int"; } if (ttype->is_map()) { t_type* tkey = get_true_type(((t_map*)ttype)->get_key_type()); t_type* tval = get_true_type(((t_map*)ttype)->get_val_type()); if (tkey->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)tkey)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (!(tkey->is_binary())) { return "StringMap< " + type_name(tval) + ">"; } break; // default to ObjectMap<> case t_base_type::TYPE_UUID: return "StringMap< " + type_name(tval) + ">"; // uuids are stored as strings case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: return "IntMap< " + type_name(tval) + ">"; case t_base_type::TYPE_I64: return "Int64Map< " + type_name(tval) + ">"; default: break; // default to ObjectMap<> } } if (tkey->is_enum()) { return "IntMap< " + type_name(tval) + ">"; } return "ObjectMap< " + type_name(tkey) + ", " + type_name(tval) + ">"; } if (ttype->is_set()) { t_type* tkey = get_true_type(((t_set*)ttype)->get_elem_type()); if (tkey->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)tkey)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (!(tkey->is_binary())) { return "StringSet"; } break; // default to ObjectSet case t_base_type::TYPE_UUID: return "StringSet"; // uuids are stored as strings case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: return "IntSet"; case t_base_type::TYPE_I64: return "Int64Set"; default: break; // default to ObjectSet } } if (tkey->is_enum()) { return "IntSet"; } return "ObjectSet< " + type_name(tkey) + ">"; } if (ttype->is_list()) { t_type* telm = ((t_list*)ttype)->get_elem_type(); return "List< " + type_name(telm) + ">"; } // Check for namespacing t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { string package = make_package_name( program->get_namespace("haxe")); if (!package.empty()) { return package + "." + ttype->get_name(); } } return ttype->get_name(); } /** * Returns the haxe type that corresponds to the thrift type. * * @param tbase The base type * @param container Is it going in a haxe container? */ string t_haxe_generator::base_type_name(t_base_type* type, bool in_container) { (void)in_container; t_base_type::t_base tbase = type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "Void"; case t_base_type::TYPE_STRING: if (type->is_binary()) { return "haxe.io.Bytes"; } else { return "String"; } case t_base_type::TYPE_UUID: return "String"; case t_base_type::TYPE_BOOL: return "Bool"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: return "haxe.Int32"; case t_base_type::TYPE_I64: return "haxe.Int64"; case t_base_type::TYPE_DOUBLE: return "Float"; default: throw "compiler error: no Haxe name for base type " + t_base_type::t_base_name(tbase); } } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type */ string t_haxe_generator::declare_field(t_field* tfield, bool init) { string result = "var " + tfield->get_name() + " : " + type_name(tfield->get_type()); if (init) { t_type* ttype = get_true_type(tfield->get_type()); if (ttype->is_base_type() && tfield->get_value() != nullptr) { result += " = " + render_const_value_str( ttype, tfield->get_value()); } else { result += " = " + render_default_value_for_type( ttype, false); } } return result + ";"; } string t_haxe_generator::render_default_value_for_type( t_type* type, bool allow_null) { t_type* ttype = get_true_type(type); if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "null"; case t_base_type::TYPE_UUID: return "uuid.Uuid.NIL"; case t_base_type::TYPE_BOOL: return "false"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "0"; case t_base_type::TYPE_DOUBLE: return "0.0"; default: throw "unhandled type"; } } else if (ttype->is_enum()) { return "0"; } else if (ttype->is_container()) { return allow_null ? "null" : "new " + type_name(ttype, false, true) + "()"; } else { return allow_null ? "null" : "new " + type_name(ttype, false, true) + "()"; } } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_haxe_generator::function_signature_combined(t_function* tfunction) { std::string on_error_success = "onError : Dynamic->Void = null, " + generate_service_method_onsuccess(tfunction, true, false); std::string arguments = argument_list(tfunction->get_arglist()); if (!tfunction->is_oneway()) { if (arguments != "") { arguments += ", "; } arguments += on_error_success; //"onError : Function, onSuccess : Function"; } std::string resulttype; if (tfunction->is_oneway() || tfunction->get_returntype()->is_void()) { resulttype = "Void"; } else { resulttype = type_name(tfunction->get_returntype()); } std::string result = "function " + tfunction->get_name() + "(" + arguments + ") : "+resulttype; return result; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_haxe_generator::function_signature_normal(t_function* tfunction) { std::string arguments = argument_list(tfunction->get_arglist()); std::string resulttype; if (tfunction->is_oneway() || tfunction->get_returntype()->is_void()) { resulttype = "Void"; } else { resulttype = type_name(tfunction->get_returntype()); } std::string result = "function " + tfunction->get_name() + "(" + arguments + ") : " + resulttype; return result; } /** * Renders a comma separated field list, with type names */ string t_haxe_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += (*f_iter)->get_name() + " : " + type_name((*f_iter)->get_type()); } return result; } /** * Converts the parse type to a C++ enum string for the given type. */ string t_haxe_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.STRING"; case t_base_type::TYPE_UUID: return "TType.UUID"; case t_base_type::TYPE_BOOL: return "TType.BOOL"; case t_base_type::TYPE_I8: return "TType.BYTE"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; default: break; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_list()) { return "TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Haxe class names must start with uppercase letter, but Haxe namespaces must not. */ std::string t_haxe_generator::get_cap_name(std::string name) { if (name.length() == 0) { return name; } // test.for.Generic< data.Type, or.the.Like> and handle it recursively size_t generic_first = name.find('<'); size_t generic_last = name.rfind('>'); if ((generic_first != std::string::npos) && (generic_last != std::string::npos)) { string outer_type = name.substr(0, generic_first); string inner_types = name.substr(generic_first + 1, generic_last - generic_first - 1); string new_inner = ""; size_t comma_start = 0; while (comma_start < inner_types.length()) { size_t comma_pos = comma_start; int nested = 0; while (comma_pos < inner_types.length()) { bool found = false; switch (inner_types[comma_pos]) { case '<': ++nested; break; case '>': --nested; break; case ',': found = (nested == 0); break; } if (found) { break; } ++comma_pos; } if (new_inner.length() > 0) { new_inner += ","; } string inner = inner_types.substr(comma_start, comma_pos - comma_start); new_inner += get_cap_name(inner); comma_start = ++comma_pos; } return get_cap_name(outer_type) + "<" + new_inner + ">"; } // package name size_t index = name.find_first_not_of(" \n\r\t"); if (index < name.length()) { name[index] = tolower(name[index]); index = name.find('.'); while (index != std::string::npos) { if (++index < name.length()) { name[index] = tolower(name[index]); } index = name.find('.', index); } } // class name index = name.rfind('.'); if (index != std::string::npos) { ++index; } else { index = name.find_first_not_of(" \n\r\t"); } if (index < name.length()) { name[index] = toupper(name[index]); } return name; } string t_haxe_generator::constant_name(string name) { string constant_name; bool is_first = true; bool was_previous_char_upper = false; for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { constant_name += '_'; } constant_name += toupper(character); is_first = false; was_previous_char_upper = is_upper; } return constant_name; } /** * Enables RTTI for a class or interface */ void t_haxe_generator::generate_rtti_decoration(ostream& out) { if (rtti_) { out << "@:rtti" << endl; } } /** * Adds build macros to a class or interface */ void t_haxe_generator::generate_macro_decoration(ostream& out) { if (!buildmacro_.empty()) { out << "#if ! macro" << endl; out << "@:build( " << buildmacro_ << ")" << endl; // current class/interface out << "@:autoBuild( " << buildmacro_ << ")" << endl; // inherited classes/interfaces out << "#end" << endl; } } /** * Emits a haxeDoc comment if the provided object has a doc in Thrift */ void t_haxe_generator::generate_haxe_doc(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_docstring_comment(out, "/**\n", " * ", tdoc->get_doc(), " */\n"); } } /** * Emits a haxeDoc comment if the provided function object has a doc in Thrift */ void t_haxe_generator::generate_haxe_doc(ostream& out, t_function* tfunction) { if (tfunction->has_doc()) { stringstream ss; ss << tfunction->get_doc(); const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ss << "\n@param " << p->get_name(); if (p->has_doc()) { ss << " " << p->get_doc(); } } generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n"); } } std::string t_haxe_generator::generate_isset_check(t_field* field) { return generate_isset_check(field->get_name()); } std::string t_haxe_generator::generate_isset_check(std::string field_name) { return "is" + get_cap_name("set") + get_cap_name(field_name) + "()"; } void t_haxe_generator::generate_isset_set(ostream& out, t_field* field) { if (!type_can_be_null(field->get_type())) { indent(out) << "this.__isset_" << field->get_name() << " = true;" << endl; } } std::string t_haxe_generator::get_enum_class_name(t_type* type) { string package = ""; t_program* program = type->get_program(); if (program != nullptr /*&& program != program_*/) { package = make_package_name( program->get_namespace("haxe")) + "."; } return package + type->get_name(); } std::string t_haxe_generator::display_name() const { return "Haxe"; } THRIFT_REGISTER_GENERATOR( haxe, "Haxe", " rtti Enable @:rtti for generated classes and interfaces\n" " buildmacro=my.macros.Class.method(args)\n" " Add @:build macro calls to generated classes and interfaces\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_java_generator.cc0000644000000000000000000066000214452237057025212 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "thrift/generate/t_oop_generator.h" #include "thrift/platform.h" using std::map; using std::ostream; using std::ostringstream; using std::setfill; using std::set; using std::setw; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes static const string thrift_option_class = "org.apache.thrift.Option"; static const string jdk_option_class = "java.util.Optional"; /** * Java code generator. * */ class t_java_generator : public t_oop_generator { public: t_java_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; bean_style_ = false; android_style_ = false; private_members_ = false; nocamel_style_ = false; fullcamel_style_ = false; android_legacy_ = false; sorted_containers_ = false; java5_ = false; reuse_objects_ = false; use_option_type_ = false; generate_future_iface_ = false; use_jdk8_option_type_ = false; undated_generated_annotations_ = false; suppress_generated_annotations_ = false; rethrow_unhandled_exceptions_ = false; unsafe_binaries_ = false; annotations_as_metadata_ = false; jakarta_annotations_ = false; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if (iter->first.compare("beans") == 0) { bean_style_ = true; } else if (iter->first.compare("android") == 0) { android_style_ = true; } else if (iter->first.compare("private_members") == 0 || iter->first.compare("private-members") == 0) { // keep both private_members and private-members (legacy) for backwards compatibility private_members_ = true; } else if (iter->first.compare("nocamel") == 0) { nocamel_style_ = true; } else if (iter->first.compare("fullcamel") == 0) { fullcamel_style_ = true; } else if (iter->first.compare("android_legacy") == 0) { android_legacy_ = true; } else if (iter->first.compare("sorted_containers") == 0) { sorted_containers_ = true; } else if (iter->first.compare("java5") == 0) { java5_ = true; } else if (iter->first.compare("future_iface") == 0) { generate_future_iface_ = true; } else if (iter->first.compare("reuse_objects") == 0 || iter->first.compare("reuse-objects") == 0) { // keep both reuse_objects and reuse-objects (legacy) for backwards compatibility reuse_objects_ = true; } else if (iter->first.compare("option_type") == 0) { use_option_type_ = true; if (iter->second.compare("jdk8") == 0) { use_jdk8_option_type_ = true; } else if (iter->second.compare("thrift") == 0 || iter->second.compare("") == 0) { use_jdk8_option_type_ = false; } else { throw "option_type must be 'jdk8' or 'thrift'"; } } else if (iter->first.compare("rethrow_unhandled_exceptions") == 0) { rethrow_unhandled_exceptions_ = true; } else if (iter->first.compare("generated_annotations") == 0) { if (iter->second.compare("undated") == 0) { undated_generated_annotations_ = true; } else if (iter->second.compare("suppress") == 0) { suppress_generated_annotations_ = true; } else { throw "unknown option java:" + iter->first + "=" + iter->second; } } else if (iter->first.compare("unsafe_binaries") == 0) { unsafe_binaries_ = true; } else if (iter->first.compare("annotations_as_metadata") == 0) { annotations_as_metadata_ = true; } else if (iter->first.compare("jakarta_annotations") == 0) { jakarta_annotations_ = true; } else { throw "unknown option java:" + iter->first; } } if (java5_) { android_legacy_ = true; } out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java"); } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(std::vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_struct(t_struct* tstruct) override; void generate_union(t_struct* tunion); void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval = false); std::string render_const_value(std::ostream& out, t_type* type, t_const_value* value); /** * Service-level generation functions */ void generate_java_struct(t_struct* tstruct, bool is_exception); void generate_java_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false); void generate_java_struct_parcelable(std::ostream& out, t_struct* tstruct); void generate_java_struct_equality(std::ostream& out, t_struct* tstruct); void generate_java_struct_compare_to(std::ostream& out, t_struct* tstruct); void generate_java_struct_reader(std::ostream& out, t_struct* tstruct); void generate_java_validator(std::ostream& out, t_struct* tstruct); void generate_java_struct_result_writer(std::ostream& out, t_struct* tstruct); void generate_java_struct_writer(std::ostream& out, t_struct* tstruct); void generate_java_struct_tostring(std::ostream& out, t_struct* tstruct); void generate_java_struct_clear(std::ostream& out, t_struct* tstruct); void generate_java_struct_write_object(std::ostream& out, t_struct* tstruct); void generate_java_struct_read_object(std::ostream& out, t_struct* tstruct); void generate_java_meta_data_map(std::ostream& out, t_struct* tstruct); void generate_field_value_meta_data(std::ostream& out, t_type* type); void generate_metadata_for_field_annotations(std::ostream& out, t_field* field); std::string get_java_type_string(t_type* type); void generate_java_struct_field_by_id(ostream& out, t_struct* tstruct); void generate_reflection_setters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name); void generate_reflection_getters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name); void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct); void generate_generic_isset_method(std::ostream& out, t_struct* tstruct); void generate_java_bean_boilerplate(std::ostream& out, t_struct* tstruct); void generate_function_helpers(t_function* tfunction); std::string as_camel_case(std::string name, bool ucfirst = true); std::string get_rpc_method_name(std::string name); std::string get_cap_name(std::string name); std::string generate_isset_check(t_field* field); std::string generate_isset_check(std::string field); void generate_isset_set(ostream& out, t_field* field, std::string prefix); std::string isset_field_id(t_field* field); void generate_service_interface(t_service* tservice); void generate_service_async_interface(t_service* tservice); void generate_service_future_interface(t_service* tservice); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_async_client(t_service* tservice); void generate_service_future_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_service_async_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); void generate_process_async_function(t_service* tservice, t_function* tfunction); void generate_java_union(t_struct* tstruct); void generate_union_constructor(ostream& out, t_struct* tstruct); void generate_union_getters_and_setters(ostream& out, t_struct* tstruct); void generate_union_is_set_methods(ostream& out, t_struct* tstruct); void generate_union_abstract_methods(ostream& out, t_struct* tstruct); void generate_check_type(ostream& out, t_struct* tstruct); void generate_standard_scheme_read_value(ostream& out, t_struct* tstruct); void generate_standard_scheme_write_value(ostream& out, t_struct* tstruct); void generate_tuple_scheme_read_value(ostream& out, t_struct* tstruct); void generate_tuple_scheme_write_value(ostream& out, t_struct* tstruct); void generate_get_field_desc(ostream& out, t_struct* tstruct); void generate_get_struct_desc(ostream& out, t_struct* tstruct); void generate_get_field_name(ostream& out, t_struct* tstruct); void generate_union_comparisons(ostream& out, t_struct* tstruct); void generate_union_hashcode(ostream& out, t_struct* tstruct); void generate_scheme_map(ostream& out, t_struct* tstruct); void generate_standard_writer(ostream& out, t_struct* tstruct, bool is_result); void generate_standard_reader(ostream& out, t_struct* tstruct); void generate_java_struct_standard_scheme(ostream& out, t_struct* tstruct, bool is_result); void generate_java_struct_tuple_scheme(ostream& out, t_struct* tstruct); void generate_java_struct_tuple_reader(ostream& out, t_struct* tstruct); void generate_java_struct_tuple_writer(ostream& out, t_struct* tstruct); void generate_java_scheme_lookup(ostream& out); void generate_javax_generated_annotation(ostream& out); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", bool has_metadata = true); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = "", bool has_metadata = true); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = "", std::string obj = "", bool has_metadata = true); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = "", std::string obj = "", bool has_metadata = true); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = "", std::string obj = "", bool has_metadata = true); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", std::string postfix = "", bool has_metadata = true); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = "", bool has_metadata = true); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter, std::string map, bool has_metadata = true); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter, bool has_metadata = true); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter, bool has_metadata = true); void generate_deep_copy_container(std::ostream& out, std::string source_name_p1, std::string source_name_p2, std::string result_name, t_type* type); void generate_deep_copy_non_container(std::ostream& out, std::string source_name, std::string dest_name, t_type* type); enum isset_type { ISSET_NONE, ISSET_PRIMITIVE, ISSET_BITSET }; isset_type needs_isset(t_struct* tstruct, std::string* outPrimitiveType = nullptr); /** * Helper rendering functions */ std::string java_package(); std::string java_suppressions(); std::string java_nullable_annotation(); std::string java_override_annotation(); std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false, bool skip_generic = false, bool force_namespace = false); std::string base_type_name(t_base_type* tbase, bool in_container = false); std::string declare_field(t_field* tfield, bool init = false, bool comment = false); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string function_signature_async(t_function* tfunction, bool use_base_method = false, std::string prefix = ""); std::string function_signature_future(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct, bool include_types = true); std::string async_function_call_arglist(t_function* tfunc, bool use_base_method = true, bool include_types = true); std::string async_argument_list(t_function* tfunct, t_struct* tstruct, t_type* ttype, bool include_types = false); std::string type_to_enum(t_type* ttype); void generate_struct_desc(ostream& out, t_struct* tstruct); void generate_field_descs(ostream& out, t_struct* tstruct); void generate_field_name_constants(ostream& out, t_struct* tstruct); std::string make_valid_java_filename(std::string const& fromName); std::string make_valid_java_identifier(std::string const& fromName); string normalize_name(string name); bool type_can_be_null(t_type* ttype) { ttype = get_true_type(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string() || ttype->is_uuid() || ttype->is_enum(); } bool is_deprecated(const std::map>& annotations) { return annotations.find("deprecated") != annotations.end(); } bool is_deprecated(const std::map& annotations) { return annotations.find("deprecated") != annotations.end(); } bool is_enum_set(t_type* ttype) { if (!sorted_containers_) { ttype = get_true_type(ttype); if (ttype->is_set()) { t_set* tset = (t_set*)ttype; t_type* elem_type = get_true_type(tset->get_elem_type()); return elem_type->is_enum(); } } return false; } bool is_enum_map(t_type* ttype) { if (!sorted_containers_) { ttype = get_true_type(ttype); if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; t_type* key_type = get_true_type(tmap->get_key_type()); return key_type->is_enum(); } } return false; } std::string inner_enum_type_name(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; t_type* key_type = get_true_type(tmap->get_key_type()); return type_name(key_type, true) + ".class"; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; t_type* elem_type = get_true_type(tset->get_elem_type()); return type_name(elem_type, true) + ".class"; } return ""; } std::string constant_name(std::string name); private: /** * File streams */ std::string package_name_; ofstream_with_content_based_conditional_update f_service_; std::string package_dir_; // keywords (according to Oracle docs) // true, false, and null might seem like keywords, but they are actually literals; // you cannot use them as identifiers in your programs. const std::string JAVA_KEYWORDS[53] = { "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "try", "void", "volatile", "while", "true", "false", "null" }; std::set java_keywords = std::set(JAVA_KEYWORDS, JAVA_KEYWORDS + sizeof(JAVA_KEYWORDS) / sizeof(JAVA_KEYWORDS[0])); bool bean_style_; bool android_style_; bool private_members_; bool nocamel_style_; bool fullcamel_style_; bool android_legacy_; bool java5_; bool sorted_containers_; bool reuse_objects_; bool generate_future_iface_; bool use_option_type_; bool use_jdk8_option_type_; bool undated_generated_annotations_; bool suppress_generated_annotations_; bool rethrow_unhandled_exceptions_; bool unsafe_binaries_; bool annotations_as_metadata_; bool jakarta_annotations_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_java_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); package_name_ = program_->get_namespace("java"); string dir = package_name_; string subdir = get_out_dir(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } if (dir.size() > 0) { subdir = subdir + "/" + dir; MKDIR(subdir.c_str()); } package_dir_ = subdir; } /** * Packages the generated file * * @return String of the package, i.e. "package org.apache.thriftdemo;" */ string t_java_generator::java_package() { if (!package_name_.empty()) { return string("package ") + package_name_ + ";\n\n"; } return ""; } string t_java_generator::java_suppressions() { return "@SuppressWarnings({\"cast\", \"rawtypes\", \"serial\", \"unchecked\", \"unused\"})" + endl; } string t_java_generator::java_nullable_annotation() { return "@org.apache.thrift.annotation.Nullable"; } string t_java_generator::java_override_annotation() { return "@Override"; } string t_java_generator::normalize_name(string name) { string tmp(name); //transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(tolower)); // un-conflict keywords by prefixing with "$" if (java_keywords.find(tmp) != java_keywords.end()) { return "$" + name; } // no changes necessary return name; } /** * Nothing in Java */ void t_java_generator::close_generator() {} /** * Generates a typedef. This is not done in Java, since it does * not support arbitrary name replacements, and it'd be a wacky waste * of overhead to make wrapper classes. * * @param ttypedef The type definition */ void t_java_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Enums are a class with a set of static constants. * * @param tenum The enumeration */ void t_java_generator::generate_enum(t_enum* tenum) { bool is_deprecated = this->is_deprecated(tenum->annotations_); // Make output file string f_enum_name = package_dir_ + "/" + make_valid_java_filename(tenum->get_name()) + ".java"; ofstream_with_content_based_conditional_update f_enum; f_enum.open(f_enum_name.c_str()); // Comment and package it f_enum << autogen_comment() << java_package() << endl; generate_java_doc(f_enum, tenum); if (!suppress_generated_annotations_) { generate_javax_generated_annotation(f_enum); } if (is_deprecated) { indent(f_enum) << "@Deprecated" << endl; } indent(f_enum) << "public enum " << tenum->get_name() << " implements org.apache.thrift.TEnum "; scope_up(f_enum); vector constants = tenum->get_constants(); vector::iterator c_iter; bool first = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); if (first) { first = false; } else { f_enum << "," << endl; } generate_java_doc(f_enum, *c_iter); if (this->is_deprecated((*c_iter)->annotations_)) { indent(f_enum) << "@Deprecated" << endl; } indent(f_enum) << (*c_iter)->get_name() << "(" << value << ")"; } f_enum << ";" << endl << endl; // Field for thriftCode indent(f_enum) << "private final int value;" << endl << endl; indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl; indent(f_enum) << " this.value = value;" << endl; indent(f_enum) << "}" << endl << endl; indent(f_enum) << "/**" << endl; indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL." << endl; indent(f_enum) << " */" << endl; indent(f_enum) << java_override_annotation() << endl; indent(f_enum) << "public int getValue() {" << endl; indent(f_enum) << " return value;" << endl; indent(f_enum) << "}" << endl << endl; indent(f_enum) << "/**" << endl; indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL." << endl; indent(f_enum) << " * @return null if the value is not found." << endl; indent(f_enum) << " */" << endl; indent(f_enum) << java_nullable_annotation() << endl; indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl; indent_up(); indent(f_enum) << "switch (value) {" << endl; indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); indent(f_enum) << "case " << value << ":" << endl; indent(f_enum) << " return " << (*c_iter)->get_name() << ";" << endl; } indent(f_enum) << "default:" << endl; indent(f_enum) << " return null;" << endl; indent_down(); indent(f_enum) << "}" << endl; indent_down(); indent(f_enum) << "}" << endl; scope_down(f_enum); f_enum.close(); } /** * Generates a class that holds all the constants. */ void t_java_generator::generate_consts(std::vector consts) { if (consts.empty()) { return; } string f_consts_name = package_dir_ + '/' + make_valid_java_filename(program_name_) + "Constants.java"; ofstream_with_content_based_conditional_update f_consts; f_consts.open(f_consts_name.c_str()); // Print header f_consts << autogen_comment() << java_package() << java_suppressions(); f_consts << "public class " << make_valid_java_identifier(program_name_) << "Constants {" << endl << endl; indent_up(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { generate_java_doc(f_consts, (*c_iter)); print_const_value(f_consts, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false); } indent_down(); indent(f_consts) << "}" << endl; f_consts.close(); } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ void t_java_generator::print_const_value(std::ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) { type = get_true_type(type); indent(out); if (!defval) { out << (in_static ? "" : "public static final ") << type_name(type) << " "; } if (type->is_base_type()) { string v2 = render_const_value(out, type, value); out << name << " = " << v2 << ";" << endl << endl; } else if (type->is_enum()) { out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl; } else if (type->is_struct() || type->is_xception()) { const vector& unsorted_fields = ((t_struct*)type)->get_members(); vector fields = unsorted_fields; std::sort(fields.begin(), fields.end(), t_field::key_compare()); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; out << name << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); } for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string val = render_const_value(out, field_type, v_iter->second); indent(out) << name << "."; std::string cap_name = get_cap_name(v_iter->first->get_string()); out << "set" << cap_name << "(" << val << ");" << endl; } if (!in_static) { indent_down(); indent(out) << "}" << endl; } out << endl; } else if (type->is_map()) { std::string constructor_args; if (is_enum_map(type)) { constructor_args = inner_enum_type_name(type); } out << name << " = new " << type_name(type, false, true) << "(" << constructor_args << ");" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); } t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, ktype, v_iter->first); string val = render_const_value(out, vtype, v_iter->second); indent(out) << name << ".put(" << key << ", " << val << ");" << endl; } if (!in_static) { indent_down(); indent(out) << "}" << endl; } out << endl; } else if (type->is_list() || type->is_set()) { if (is_enum_set(type)) { out << name << " = " << type_name(type, false, true, true) << ".noneOf(" << inner_enum_type_name(type) << ");" << endl; } else { out << name << " = new " << type_name(type, false, true) << "();" << endl; } if (!in_static) { indent(out) << "static {" << endl; indent_up(); } t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(out, etype, *v_iter); indent(out) << name << ".add(" << val << ");" << endl; } if (!in_static) { indent_down(); indent(out) << "}" << endl; } out << endl; } else { throw "compiler error: no const of type " + type->get_name(); } } string t_java_generator::render_const_value(ostream& out, t_type* type, t_const_value* value) { type = get_true_type(type); std::ostringstream render; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (((t_base_type*)type)->is_binary()) { render << "java.nio.ByteBuffer.wrap(\"" << get_escaped_string(value) << "\".getBytes())"; } else { render << '"' << get_escaped_string(value) << '"'; } break; case t_base_type::TYPE_UUID: render << "java.util.UUID.fromString(\"" << get_escaped_string(value) << "\")"; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: render << "(byte)" << value->get_integer(); break; case t_base_type::TYPE_I16: render << "(short)" << value->get_integer(); break; case t_base_type::TYPE_I32: render << value->get_integer(); break; case t_base_type::TYPE_I64: render << value->get_integer() << "L"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << value->get_integer() << "d"; } else { render << emit_double_as_string(value->get_double()); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { std::string namespace_prefix = type->get_program()->get_namespace("java"); if (namespace_prefix.length() > 0) { namespace_prefix += "."; } render << namespace_prefix << value->get_identifier_with_parent(); } else { string t = tmp("tmp"); print_const_value(out, t, type, value, true); render << t; } return render.str(); } /** * Generates a struct definition for a thrift data type. This will be a org.apache.thrift.TBase * implementor. * * @param tstruct The struct definition */ void t_java_generator::generate_struct(t_struct* tstruct) { if (tstruct->is_union()) { generate_java_union(tstruct); } else { generate_java_struct(tstruct, false); } } /** * Exceptions are structs, but they inherit from Exception * * @param tstruct The struct definition */ void t_java_generator::generate_xception(t_struct* txception) { generate_java_struct(txception, true); } /** * Java struct definition. * * @param tstruct The struct definition */ void t_java_generator::generate_java_struct(t_struct* tstruct, bool is_exception) { // Make output file string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name()) + ".java"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << java_package(); generate_java_struct_definition(f_struct, tstruct, is_exception); f_struct.close(); } /** * Java union definition. * * @param tstruct The struct definition */ void t_java_generator::generate_java_union(t_struct* tstruct) { // Make output file string f_struct_name = package_dir_ + "/" + make_valid_java_filename(tstruct->get_name()) + ".java"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << java_package(); generate_java_doc(f_struct, tstruct); f_struct << java_suppressions(); bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); bool is_deprecated = this->is_deprecated(tstruct->annotations_); if (!suppress_generated_annotations_) { generate_javax_generated_annotation(f_struct); } if (is_deprecated) { indent(f_struct) << "@Deprecated" << endl; } indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << make_valid_java_identifier(tstruct->get_name()) << " extends org.apache.thrift.TUnion<" << make_valid_java_identifier(tstruct->get_name()) << ", " << make_valid_java_identifier(tstruct->get_name()) << "._Fields> "; scope_up(f_struct); generate_struct_desc(f_struct, tstruct); generate_field_descs(f_struct, tstruct); f_struct << endl; generate_field_name_constants(f_struct, tstruct); f_struct << endl; generate_java_meta_data_map(f_struct, tstruct); generate_union_constructor(f_struct, tstruct); f_struct << endl; generate_union_abstract_methods(f_struct, tstruct); f_struct << endl; generate_java_struct_field_by_id(f_struct, tstruct); f_struct << endl; generate_union_getters_and_setters(f_struct, tstruct); f_struct << endl; generate_union_is_set_methods(f_struct, tstruct); f_struct << endl; generate_union_comparisons(f_struct, tstruct); f_struct << endl; generate_union_hashcode(f_struct, tstruct); f_struct << endl; generate_java_struct_write_object(f_struct, tstruct); f_struct << endl; generate_java_struct_read_object(f_struct, tstruct); f_struct << endl; scope_down(f_struct); f_struct.close(); } void t_java_generator::generate_union_constructor(ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; indent(out) << "public " << type_name(tstruct) << "() {" << endl; indent_up(); bool default_value = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* type = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr) { indent(out) << "super(_Fields." << constant_name((*m_iter)->get_name()) << ", " << render_const_value(out, type, (*m_iter)->get_value()) << ");" << endl; default_value = true; break; } } if (default_value == false) { indent(out) << "super();" << endl; } indent_down(); indent(out) << "}" << endl << endl; indent(out) << "public " << type_name(tstruct) << "(_Fields setField, java.lang.Object value) {" << endl; indent(out) << " super(setField, value);" << endl; indent(out) << "}" << endl << endl; indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {" << endl; indent(out) << " super(other);" << endl; indent(out) << "}" << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public " << make_valid_java_identifier(tstruct->get_name()) << " deepCopy() {" << endl; indent(out) << " return new " << tstruct->get_name() << "(this);" << endl; indent(out) << "}" << endl << endl; // generate "constructors" for each field for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* type = (*m_iter)->get_type(); indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "(" << type_name(type) << " value) {" << endl; indent(out) << " " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl; indent(out) << " x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl; indent(out) << " return x;" << endl; indent(out) << "}" << endl << endl; if (type->is_binary()) { indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "(byte[] value) {" << endl; indent(out) << " " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl; indent(out) << " x.set" << get_cap_name((*m_iter)->get_name()); if (unsafe_binaries_) { indent(out) << "(java.nio.ByteBuffer.wrap(value));" << endl; } else { indent(out) << "(java.nio.ByteBuffer.wrap(value.clone()));" << endl; } indent(out) << " return x;" << endl; indent(out) << "}" << endl << endl; } } } void t_java_generator::generate_union_getters_and_setters(ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (first) { first = false; } else { out << endl; } t_field* field = (*m_iter); t_type* type = field->get_type(); std::string cap_name = get_cap_name(field->get_name()); bool is_deprecated = this->is_deprecated(field->annotations_); generate_java_doc(out, field); if (type->is_binary()) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public byte[] get" << cap_name << "() {" << endl; indent(out) << " set" << cap_name << "(org.apache.thrift.TBaseHelper.rightSize(buffer" << get_cap_name("for") << cap_name << "()));" << endl; indent(out) << " java.nio.ByteBuffer b = buffer" << get_cap_name("for") << cap_name << "();" << endl; indent(out) << " return b == null ? null : b.array();" << endl; indent(out) << "}" << endl; out << endl; indent(out) << "public java.nio.ByteBuffer buffer" << get_cap_name("for") << get_cap_name(field->get_name()) << "() {" << endl; indent(out) << " if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {" << endl; if (unsafe_binaries_) { indent(out) << " return (java.nio.ByteBuffer)getFieldValue();" << endl; } else { indent(out) << " return " "org.apache.thrift.TBaseHelper.copyBinary((java.nio.ByteBuffer)getFieldValue());" << endl; } indent(out) << " } else {" << endl; indent(out) << " throw new java.lang.RuntimeException(\"Cannot get field '" << field->get_name() << "' because union is currently set to \" + getFieldDesc(getSetField()).name);" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; } else { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public " << type_name(field->get_type()) << " get" << get_cap_name(field->get_name()) << "() {" << endl; indent(out) << " if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {" << endl; indent(out) << " return (" << type_name(field->get_type(), true) << ")getFieldValue();" << endl; indent(out) << " } else {" << endl; indent(out) << " throw new java.lang.RuntimeException(\"Cannot get field '" << field->get_name() << "' because union is currently set to \" + getFieldDesc(getSetField()).name);" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; } out << endl; generate_java_doc(out, field); if (type->is_binary()) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public void set" << get_cap_name(field->get_name()) << "(byte[] value) {" << endl; indent(out) << " set" << get_cap_name(field->get_name()); if (unsafe_binaries_) { indent(out) << "(java.nio.ByteBuffer.wrap(value));" << endl; } else { indent(out) << "(java.nio.ByteBuffer.wrap(value.clone()));" << endl; } indent(out) << "}" << endl; out << endl; } if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public void set" << get_cap_name(field->get_name()) << "(" << type_name(field->get_type()) << " value) {" << endl; indent(out) << " setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl; if (type_can_be_null(field->get_type())) { indent(out) << " value_ = java.util.Objects.requireNonNull(value,\"" << "_Fields." << constant_name(field->get_name()) << "\");" << endl; } else { indent(out) << " value_ = value;" << endl; } indent(out) << "}" << endl; } } void t_java_generator::generate_union_is_set_methods(ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (first) { first = false; } else { out << endl; } std::string field_name = (*m_iter)->get_name(); indent(out) << "public boolean is" << get_cap_name("set") << get_cap_name(field_name) << "() {" << endl; indent_up(); indent(out) << "return setField_ == _Fields." << constant_name(field_name) << ";" << endl; indent_down(); indent(out) << "}" << endl << endl; } } void t_java_generator::generate_union_abstract_methods(ostream& out, t_struct* tstruct) { generate_check_type(out, tstruct); out << endl; generate_standard_scheme_read_value(out, tstruct); out << endl; generate_standard_scheme_write_value(out, tstruct); out << endl; generate_tuple_scheme_read_value(out, tstruct); out << endl; generate_tuple_scheme_write_value(out, tstruct); out << endl; generate_get_field_desc(out, tstruct); out << endl; generate_get_struct_desc(out, tstruct); out << endl; indent(out) << java_override_annotation() << endl; indent(out) << "protected _Fields enumForId(short id) {" << endl; indent(out) << " return _Fields.findByThriftIdOrThrow(id);" << endl; indent(out) << "}" << endl; } void t_java_generator::generate_check_type(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "protected void checkType(_Fields setField, java.lang.Object value) throws " "java.lang.ClassCastException {" << endl; indent_up(); indent(out) << "switch (setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent(out) << " if (value instanceof " << type_name(field->get_type(), true, false, true) << ") {" << endl; indent(out) << " break;" << endl; indent(out) << " }" << endl; indent(out) << " throw new java.lang.ClassCastException(\"Was expecting value of type " << type_name(field->get_type(), true, false) << " for field '" << field->get_name() << "', but got \" + value.getClass().getSimpleName());" << endl; // do the real check here } indent(out) << "default:" << endl; indent(out) << " throw new java.lang.IllegalArgumentException(\"Unknown field id \" + setField);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_standard_scheme_read_value(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "protected java.lang.Object standardSchemeReadValue(org.apache.thrift.protocol.TProtocol " "iprot, org.apache.thrift.protocol.TField field) throws " "org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl; indent(out) << "if (setField != null) {" << endl; indent_up(); indent(out) << "switch (setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {" << endl; indent_up(); indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";" << endl; generate_deserialize_field(out, field, ""); indent(out) << "return " << field->get_name() << ";" << endl; indent_down(); indent(out) << "} else {" << endl; indent(out) << " org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl; indent(out) << " return null;" << endl; indent(out) << "}" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new java.lang.IllegalStateException(\"setField wasn't null, but didn't match any " "of the case statements!\");" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "org.apache.thrift.protocol.TProtocolUtil.skip(iprot, field.type);" << endl; indent(out) << "return null;" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_standard_scheme_write_value(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "protected void standardSchemeWriteValue(org.apache.thrift.protocol.TProtocol " "oprot) throws org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "switch (setField_) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = (" << type_name(field->get_type(), true, false) << ")value_;" << endl; generate_serialize_field(out, field); indent(out) << "return;" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new java.lang.IllegalStateException(\"Cannot write union with unknown field \" + " "setField_);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_tuple_scheme_read_value(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "protected java.lang.Object tupleSchemeReadValue(org.apache.thrift.protocol.TProtocol " "iprot, short fieldID) throws org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "_Fields setField = _Fields.findByThriftId(fieldID);" << endl; indent(out) << "if (setField != null) {" << endl; indent_up(); indent(out) << "switch (setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";" << endl; generate_deserialize_field(out, field, ""); indent(out) << "return " << field->get_name() << ";" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new java.lang.IllegalStateException(\"setField wasn't null, but didn't match any " "of the case statements!\");" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "throw new org.apache.thrift.protocol.TProtocolException(\"Couldn't find a field " "with field id \" + fieldID);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_tuple_scheme_write_value(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "protected void tupleSchemeWriteValue(org.apache.thrift.protocol.TProtocol oprot) " "throws org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "switch (setField_) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = (" << type_name(field->get_type(), true, false) << ")value_;" << endl; generate_serialize_field(out, field); indent(out) << "return;" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new java.lang.IllegalStateException(\"Cannot write union with unknown field \" + " "setField_);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_get_field_desc(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "protected org.apache.thrift.protocol.TField getFieldDesc(_Fields setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; indent(out) << "switch (setField) {" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent(out) << " return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl; } indent(out) << "default:" << endl; indent(out) << " throw new java.lang.IllegalArgumentException(\"Unknown field id \" + setField);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_get_struct_desc(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << java_override_annotation() << endl; indent(out) << "protected org.apache.thrift.protocol.TStruct getStructDesc() {" << endl; indent(out) << " return STRUCT_DESC;" << endl; indent(out) << "}" << endl; } void t_java_generator::generate_union_comparisons(ostream& out, t_struct* tstruct) { // equality indent(out) << "public boolean equals(java.lang.Object other) {" << endl; indent(out) << " if (other instanceof " << make_valid_java_identifier(tstruct->get_name()) << ") {" << endl; indent(out) << " return equals((" << make_valid_java_identifier(tstruct->get_name()) << ")other);" << endl; indent(out) << " } else {" << endl; indent(out) << " return false;" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; out << endl; indent(out) << "public boolean equals(" << make_valid_java_identifier(tstruct->get_name()) << " other) {" << endl; indent(out) << " return other != null && getSetField() == other.getSetField() && " "getFieldValue().equals(other.getFieldValue());" << endl; indent(out) << "}" << endl; out << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl; indent(out) << " int lastComparison = org.apache.thrift.TBaseHelper.compareTo(getSetField(), " "other.getSetField());" << endl; indent(out) << " if (lastComparison == 0) {" << endl; indent(out) << " return org.apache.thrift.TBaseHelper.compareTo(getFieldValue(), " "other.getFieldValue());" << endl; indent(out) << " }" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << "}" << endl; out << endl; } void t_java_generator::generate_union_hashcode(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << java_override_annotation() << endl; indent(out) << "public int hashCode() {" << endl; indent(out) << " java.util.List list = new java.util.ArrayList();" << endl; indent(out) << " list.add(this.getClass().getName());" << endl; indent(out) << " org.apache.thrift.TFieldIdEnum setField = getSetField();" << endl; indent(out) << " if (setField != null) {" << endl; indent(out) << " list.add(setField.getThriftFieldId());" << endl; indent(out) << " java.lang.Object value = getFieldValue();" << endl; indent(out) << " if (value instanceof org.apache.thrift.TEnum) {" << endl; indent(out) << " list.add(((org.apache.thrift.TEnum)getFieldValue()).getValue());" << endl; indent(out) << " } else {" << endl; indent(out) << " list.add(value);" << endl; indent(out) << " }" << endl; indent(out) << " }" << endl; indent(out) << " return list.hashCode();" << endl; indent(out) << "}"; } /** * Java struct definition. This has various parameters, as it could be * generated standalone or inside another class as a helper. If it * is a helper than it is a static class. * * @param tstruct The struct definition * @param is_exception Is this an exception? * @param in_class If inside a class, needs to be static class * @param is_result If this is a result it needs a different writer */ void t_java_generator::generate_java_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result) { generate_java_doc(out, tstruct); indent(out) << java_suppressions(); bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); bool is_deprecated = this->is_deprecated(tstruct->annotations_); if (!in_class && !suppress_generated_annotations_) { generate_javax_generated_annotation(out); } if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class " << make_valid_java_identifier(tstruct->get_name()) << " "; if (is_exception) { out << "extends org.apache.thrift.TException "; } out << "implements org.apache.thrift.TBase<" << make_valid_java_identifier(tstruct->get_name()) << ", " << make_valid_java_identifier(tstruct->get_name()) << "._Fields>, java.io.Serializable, Cloneable, Comparable<" << make_valid_java_identifier(tstruct->get_name()) << ">"; if (android_style_) { out << ", android.os.Parcelable"; } out << " "; scope_up(out); generate_struct_desc(out, tstruct); // Members are public for -java, private for -javabean const vector& members = tstruct->get_members(); vector::const_iterator m_iter; out << endl; generate_field_descs(out, tstruct); out << endl; generate_scheme_map(out, tstruct); out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (bean_style_ || private_members_) { indent(out) << "private "; } else { generate_java_doc(out, *m_iter); indent(out) << "public "; } out << declare_field(*m_iter, false, true) << endl; } out << endl; if (android_style_) { generate_java_struct_parcelable(out, tstruct); } generate_field_name_constants(out, tstruct); // isset data if (members.size() > 0) { out << endl; indent(out) << "// isset id assignments" << endl; int i = 0; int optionals = 0; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() == t_field::T_OPTIONAL) { optionals++; } if (!type_can_be_null((*m_iter)->get_type())) { indent(out) << "private static final int " << isset_field_id(*m_iter) << " = " << i << ";" << endl; i++; } } std::string primitiveType; switch (needs_isset(tstruct, &primitiveType)) { case ISSET_NONE: break; case ISSET_PRIMITIVE: indent(out) << "private " << primitiveType << " __isset_bitfield = 0;" << endl; break; case ISSET_BITSET: indent(out) << "private java.util.BitSet __isset_bit_vector = new java.util.BitSet(" << i << ");" << endl; break; } if (optionals > 0) { std::string output_string = "private static final _Fields optionals[] = {"; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() == t_field::T_OPTIONAL) { output_string = output_string + "_Fields." + constant_name((*m_iter)->get_name()) + ","; } } indent(out) << output_string.substr(0, output_string.length() - 1) << "};" << endl; } } generate_java_meta_data_map(out, tstruct); bool all_optional_members = true; // Default constructor indent(out) << "public " << make_valid_java_identifier(tstruct->get_name()) << "() {" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr) { print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); } if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { all_optional_members = false; } } indent_down(); indent(out) << "}" << endl << endl; if (!members.empty() && !all_optional_members) { // Full constructor for all fields indent(out) << "public " << make_valid_java_identifier(tstruct->get_name()) << "(" << endl; indent_up(); bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { if (!first) { out << "," << endl; } first = false; indent(out) << type_name((*m_iter)->get_type()) << " " << make_valid_java_identifier((*m_iter)->get_name()); } } out << ")" << endl; indent_down(); indent(out) << "{" << endl; indent_up(); indent(out) << "this();" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { t_type* type = get_true_type((*m_iter)->get_type()); if (type->is_binary()) { if (unsafe_binaries_) { indent(out) << "this." << make_valid_java_identifier((*m_iter)->get_name()) << " = " << make_valid_java_identifier((*m_iter)->get_name()) << ";" << endl; } else { indent(out) << "this." << make_valid_java_identifier((*m_iter)->get_name()) << " = org.apache.thrift.TBaseHelper.copyBinary(" << make_valid_java_identifier((*m_iter)->get_name()) << ");" << endl; } } else { indent(out) << "this." << make_valid_java_identifier((*m_iter)->get_name()) << " = " << make_valid_java_identifier((*m_iter)->get_name()) << ";" << endl; } generate_isset_set(out, (*m_iter), ""); } } indent_down(); indent(out) << "}" << endl << endl; } // copy constructor indent(out) << "/**" << endl; indent(out) << " * Performs a deep copy on other." << endl; indent(out) << " */" << endl; indent(out) << "public " << make_valid_java_identifier(tstruct->get_name()) << "(" << make_valid_java_identifier(tstruct->get_name()) << " other) {" << endl; indent_up(); switch (needs_isset(tstruct)) { case ISSET_NONE: break; case ISSET_PRIMITIVE: indent(out) << "__isset_bitfield = other.__isset_bitfield;" << endl; break; case ISSET_BITSET: indent(out) << "__isset_bit_vector.clear();" << endl; indent(out) << "__isset_bit_vector.or(other.__isset_bit_vector);" << endl; break; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); std::string field_name = field->get_name(); t_type* type = field->get_type()->get_true_type(); bool can_be_null = type_can_be_null(type); if (can_be_null) { indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl; indent_up(); } if (type->is_container()) { generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type); indent(out) << "this." << make_valid_java_identifier(field_name) << " = __this__" << field_name << ";" << endl; } else { indent(out) << "this." << make_valid_java_identifier(field_name) << " = "; generate_deep_copy_non_container(out, "other." + make_valid_java_identifier(field_name), field_name, type); out << ";" << endl; } if (can_be_null) { indent_down(); indent(out) << "}" << endl; } } indent_down(); indent(out) << "}" << endl << endl; // clone method, so that you can deep copy an object when you don't know its class. indent(out) << java_override_annotation() << endl; indent(out) << "public " << make_valid_java_identifier(tstruct->get_name()) << " deepCopy() {" << endl; indent(out) << " return new " << make_valid_java_identifier(tstruct->get_name()) << "(this);" << endl; indent(out) << "}" << endl << endl; generate_java_struct_clear(out, tstruct); generate_java_bean_boilerplate(out, tstruct); generate_generic_field_getters_setters(out, tstruct); generate_generic_isset_method(out, tstruct); generate_java_struct_equality(out, tstruct); generate_java_struct_compare_to(out, tstruct); generate_java_struct_field_by_id(out, tstruct); generate_java_struct_reader(out, tstruct); if (is_result) { generate_java_struct_result_writer(out, tstruct); } else { generate_java_struct_writer(out, tstruct); } generate_java_struct_tostring(out, tstruct); generate_java_validator(out, tstruct); generate_java_struct_write_object(out, tstruct); generate_java_struct_read_object(out, tstruct); generate_java_struct_standard_scheme(out, tstruct, is_result); generate_java_struct_tuple_scheme(out, tstruct); generate_java_scheme_lookup(out); scope_down(out); out << endl; } /** * generates parcelable interface implementation */ void t_java_generator::generate_java_struct_parcelable(ostream& out, t_struct* tstruct) { string tname = tstruct->get_name(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; out << indent() << java_override_annotation() << endl << indent() << "public void writeToParcel(android.os.Parcel out, int flags) {" << endl; indent_up(); string bitsetPrimitiveType = ""; switch (needs_isset(tstruct, &bitsetPrimitiveType)) { case ISSET_NONE: break; case ISSET_PRIMITIVE: indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl; if (bitsetPrimitiveType == "byte") { indent(out) << "out.writeByte(__isset_bitfield);" << endl; } else if (bitsetPrimitiveType == "short") { indent(out) << "out.writeInt(new Short(__isset_bitfield).intValue());" << endl; } else if (bitsetPrimitiveType == "int") { indent(out) << "out.writeInt(__isset_bitfield);" << endl; } else if (bitsetPrimitiveType == "long") { indent(out) << "out.writeLong(__isset_bitfield);" << endl; } out << endl; break; case ISSET_BITSET: indent(out) << "//BitSet" << endl; indent(out) << "out.writeSerializable(__isset_bit_vector);" << endl; out << endl; break; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); string name = (*m_iter)->get_name(); if (t->is_struct()) { indent(out) << "out.writeParcelable(" << name << ", flags);" << endl; } else if (type_name(t) == "float") { indent(out) << "out.writeFloat(" << name << ");" << endl; } else if (t->is_enum()) { indent(out) << "out.writeInt(" << name << " != null ? " << name << ".getValue() : -1);" << endl; } else if (t->is_list()) { if (((t_list*)t)->get_elem_type()->get_true_type()->is_struct()) { indent(out) << "out.writeTypedList(" << name << ");" << endl; } else { indent(out) << "out.writeList(" << name << ");" << endl; } } else if (t->is_map()) { indent(out) << "out.writeMap(" << name << ");" << endl; } else if (t->is_base_type()) { if (t->is_binary()) { indent(out) << "out.writeInt(" << name << "!=null ? 1 : 0);" << endl; indent(out) << "if(" << name << " != null) { " << endl; indent_up(); indent(out) << "out.writeByteArray(" << name << ".array(), " << name << ".position() + " << name << ".arrayOffset(), " << name << ".limit() - " << name << ".position() );" << endl; scope_down(out); } else { switch (((t_base_type*)t)->get_base()) { case t_base_type::TYPE_I16: indent(out) << "out.writeInt(new Short(" << name << ").intValue());" << endl; break; case t_base_type::TYPE_UUID: indent(out) << "out.writeUuid(" << name << ");" << endl; break; case t_base_type::TYPE_I32: indent(out) << "out.writeInt(" << name << ");" << endl; break; case t_base_type::TYPE_I64: indent(out) << "out.writeLong(" << name << ");" << endl; break; case t_base_type::TYPE_BOOL: indent(out) << "out.writeInt(" << name << " ? 1 : 0);" << endl; break; case t_base_type::TYPE_I8: indent(out) << "out.writeByte(" << name << ");" << endl; break; case t_base_type::TYPE_DOUBLE: indent(out) << "out.writeDouble(" << name << ");" << endl; break; case t_base_type::TYPE_STRING: indent(out) << "out.writeString(" << name << ");" << endl; break; case t_base_type::TYPE_VOID: break; default: throw "compiler error: unhandled type"; } } } } scope_down(out); out << endl; out << indent() << java_override_annotation() << endl << indent() << "public int describeContents() {" << endl; indent_up(); out << indent() << "return 0;" << endl; scope_down(out); out << endl; indent(out) << "public " << tname << "(android.os.Parcel in) {" << endl; indent_up(); // read in the required bitfield switch (needs_isset(tstruct, &bitsetPrimitiveType)) { case ISSET_NONE: break; case ISSET_PRIMITIVE: indent(out) << "//primitive bitfield of type: " << bitsetPrimitiveType << endl; if (bitsetPrimitiveType == "byte") { indent(out) << "__isset_bitfield = in.readByte();" << endl; } else if (bitsetPrimitiveType == "short") { indent(out) << "__isset_bitfield = (short) in.readInt();" << endl; } else if (bitsetPrimitiveType == "int") { indent(out) << "__isset_bitfield = in.readInt();" << endl; } else if (bitsetPrimitiveType == "long") { indent(out) << "__isset_bitfield = in.readLong();" << endl; } out << endl; break; case ISSET_BITSET: indent(out) << "//BitSet" << endl; indent(out) << "__isset_bit_vector = (java.util.BitSet) in.readSerializable();" << endl; out << endl; break; } // read all the fields for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); string name = (*m_iter)->get_name(); string prefix = "this." + name; if (t->is_struct()) { indent(out) << prefix << "= in.readParcelable(" << tname << ".class.getClassLoader());" << endl; } else if (t->is_enum()) { indent(out) << prefix << " = " << type_name(t) << ".findByValue(in.readInt());" << endl; } else if (t->is_list()) { t_list* list = (t_list*)t; indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl; if (list->get_elem_type()->get_true_type()->is_struct()) { indent(out) << "in.readTypedList(" << prefix << ", " << type_name(list->get_elem_type()) << ".CREATOR);" << endl; } else { indent(out) << "in.readList(" << prefix << ", " << tname << ".class.getClassLoader());" << endl; } } else if (t->is_map()) { indent(out) << prefix << " = new " << type_name(t, false, true) << "();" << endl; indent(out) << " in.readMap(" << prefix << ", " << tname << ".class.getClassLoader());" << endl; } else if (type_name(t) == "float") { indent(out) << prefix << " = in.readFloat();" << endl; } else if (t->is_base_type()) { t_base_type* bt = (t_base_type*)t; if (bt->is_binary()) { indent(out) << "if(in.readInt()==1) {" << endl; indent_up(); indent(out) << prefix << " = java.nio.ByteBuffer.wrap(in.createByteArray());" << endl; scope_down(out); } else { switch (bt->get_base()) { case t_base_type::TYPE_I8: indent(out) << prefix << " = in.readByte();" << endl; break; case t_base_type::TYPE_I16: indent(out) << prefix << " = (short) in.readInt();" << endl; break; case t_base_type::TYPE_I32: indent(out) << prefix << " = in.readInt();" << endl; break; case t_base_type::TYPE_I64: indent(out) << prefix << " = in.readLong();" << endl; break; case t_base_type::TYPE_UUID: indent(out) << prefix << " = in.readUuid();" << endl; break; case t_base_type::TYPE_BOOL: indent(out) << prefix << " = (in.readInt()==1);" << endl; break; case t_base_type::TYPE_DOUBLE: indent(out) << prefix << " = in.readDouble();" << endl; break; case t_base_type::TYPE_STRING: indent(out) << prefix << "= in.readString();" << endl; break; case t_base_type::TYPE_VOID: break; default: throw "compiler error: unhandled type"; } } } } scope_down(out); out << endl; indent(out) << "public static final android.os.Parcelable.Creator<" << tname << "> CREATOR = new android.os.Parcelable.Creator<" << tname << ">() {" << endl; indent_up(); indent(out) << java_override_annotation() << endl << indent() << "public " << tname << "[] newArray(int size) {" << endl; indent_up(); indent(out) << "return new " << tname << "[size];" << endl; scope_down(out); out << endl; indent(out) << java_override_annotation() << endl << indent() << "public " << tname << " createFromParcel(android.os.Parcel in) {" << endl; indent_up(); indent(out) << "return new " << tname << "(in);" << endl; scope_down(out); indent_down(); indent(out) << "};" << endl; out << endl; } /** * Generates equals methods and a hashCode method for a structure. * * @param tstruct The struct definition */ void t_java_generator::generate_java_struct_equality(ostream& out, t_struct* tstruct) { out << indent() << java_override_annotation() << endl << indent() << "public boolean equals(java.lang.Object that) {" << endl; indent_up(); out << indent() << "if (that instanceof " << make_valid_java_identifier(tstruct->get_name()) << ")" << endl << indent() << " return this.equals((" << make_valid_java_identifier(tstruct->get_name()) << ")that);" << endl << indent() << "return false;" << endl; scope_down(out); out << endl; out << indent() << "public boolean equals(" << make_valid_java_identifier(tstruct->get_name()) << " that) {" << endl; indent_up(); out << indent() << "if (that == null)" << endl << indent() << " return false;" << endl << indent() << "if (this == that)" << endl << indent() << " return true;" << endl; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << endl; t_type* t = get_true_type((*m_iter)->get_type()); // Most existing Thrift code does not use isset or optional/required, // so we treat "default" fields as required. bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; bool can_be_null = type_can_be_null(t); string name = (*m_iter)->get_name(); string this_present = "true"; string that_present = "true"; string unequal; if (is_optional || can_be_null) { this_present += " && this." + generate_isset_check(*m_iter); that_present += " && that." + generate_isset_check(*m_iter); } out << indent() << "boolean this_present_" << name << " = " << this_present << ";" << endl << indent() << "boolean that_present_" << name << " = " << that_present << ";" << endl << indent() << "if (" << "this_present_" << name << " || that_present_" << name << ") {" << endl; indent_up(); out << indent() << "if (!(" << "this_present_" << name << " && that_present_" << name << "))" << endl << indent() << " return false;" << endl; if (t->is_binary()) { unequal = "!this." + make_valid_java_identifier(name) + ".equals(that." + make_valid_java_identifier(name) + ")"; } else if (can_be_null) { unequal = "!this." + make_valid_java_identifier(name) + ".equals(that." + make_valid_java_identifier(name) + ")"; } else { unequal = "this." + make_valid_java_identifier(name) + " != that." + make_valid_java_identifier(name); } out << indent() << "if (" << unequal << ")" << endl << indent() << " return false;" << endl; scope_down(out); } out << endl; indent(out) << "return true;" << endl; scope_down(out); out << endl; const int MUL = 8191; // HashCode multiplier const int B_YES = 131071; const int B_NO = 524287; out << indent() << java_override_annotation() << endl << indent() << "public int hashCode() {" << endl; indent_up(); indent(out) << "int hashCode = 1;" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << endl; t_type* t = get_true_type((*m_iter)->get_type()); bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; bool can_be_null = type_can_be_null(t); string name = make_valid_java_identifier((*m_iter)->get_name()); if (is_optional || can_be_null) { indent(out) << "hashCode = hashCode * " << MUL << " + ((" << generate_isset_check(*m_iter) << ") ? " << B_YES << " : " << B_NO << ");" << endl; } if (is_optional || can_be_null) { indent(out) << "if (" + generate_isset_check(*m_iter) + ")" << endl; indent_up(); } if (t->is_enum()) { indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".getValue();" << endl; } else if (t->is_base_type()) { switch (((t_base_type*)t)->get_base()) { case t_base_type::TYPE_STRING: case t_base_type::TYPE_UUID: indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".hashCode();" << endl; break; case t_base_type::TYPE_BOOL: indent(out) << "hashCode = hashCode * " << MUL << " + ((" << name << ") ? " << B_YES << " : " << B_NO << ");" << endl; break; case t_base_type::TYPE_I8: indent(out) << "hashCode = hashCode * " << MUL << " + (int) (" << name << ");" << endl; break; case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ";" << endl; break; case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: indent(out) << "hashCode = hashCode * " << MUL << " + org.apache.thrift.TBaseHelper.hashCode(" << name << ");" << endl; break; case t_base_type::TYPE_VOID: throw std::logic_error("compiler error: a struct field cannot be void"); default: throw std::logic_error("compiler error: the following base type has no hashcode generator: " + t_base_type::t_base_name(((t_base_type*)t)->get_base())); } } else { indent(out) << "hashCode = hashCode * " << MUL << " + " << name << ".hashCode();" << endl; } if (is_optional || can_be_null) { indent_down(); } } out << endl; indent(out) << "return hashCode;" << endl; indent_down(); indent(out) << "}" << endl << endl; } void t_java_generator::generate_java_struct_compare_to(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl; indent_up(); indent(out) << "if (!getClass().equals(other.getClass())) {" << endl; indent(out) << " return getClass().getName().compareTo(other.getClass().getName());" << endl; indent(out) << "}" << endl; out << endl; indent(out) << "int lastComparison = 0;" << endl; out << endl; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = *m_iter; indent(out) << "lastComparison = java.lang.Boolean.compare(" << generate_isset_check(field) << ", other." << generate_isset_check(field) << ");" << endl; indent(out) << "if (lastComparison != 0) {" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << "}" << endl; indent(out) << "if (" << generate_isset_check(field) << ") {" << endl; indent(out) << " lastComparison = org.apache.thrift.TBaseHelper.compareTo(this." << make_valid_java_identifier(field->get_name()) << ", other." << make_valid_java_identifier(field->get_name()) << ");" << endl; indent(out) << " if (lastComparison != 0) {" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; } indent(out) << "return 0;" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a function to read all the fields of the struct. * * @param tstruct The struct definition */ void t_java_generator::generate_java_struct_reader(ostream& out, t_struct* /*tstruct*/) { indent(out) << java_override_annotation() << endl; indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot) throws " "org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "scheme(iprot).read(iprot, this);" << endl; indent_down(); indent(out) << "}" << endl << endl; } // generates java method to perform various checks // (e.g. check that all required fields are set) void t_java_generator::generate_java_validator(ostream& out, t_struct* tstruct) { indent(out) << "public void validate() throws org.apache.thrift.TException {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; out << indent() << "// check for required fields" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { if (bean_style_) { out << indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl << indent() << " throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' is unset! Struct:\" + toString());" << endl << indent() << "}" << endl << endl; } else { if (type_can_be_null((*f_iter)->get_type())) { indent(out) << "if (" << (*f_iter)->get_name() << " == null) {" << endl; indent(out) << " throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not present! Struct: \" + toString());" << endl; indent(out) << "}" << endl; } else { indent(out) << "// alas, we cannot check '" << (*f_iter)->get_name() << "' because it's a primitive and you chose the non-beans generator." << endl; } } } } out << indent() << "// check for sub-struct validity" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_type* type = get_true_type((*f_iter)->get_type()); if (type->is_struct() && !((t_struct*)type)->is_union()) { out << indent() << "if (" << make_valid_java_identifier((*f_iter)->get_name()) << " != null) {" << endl; out << indent() << " " << make_valid_java_identifier((*f_iter)->get_name()) << ".validate();" << endl; out << indent() << "}" << endl; } } indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a function to write all the fields of the struct * * @param tstruct The struct definition */ void t_java_generator::generate_java_struct_writer(ostream& out, t_struct* /*tstruct*/) { indent(out) << java_override_annotation() << endl; indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws " "org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "scheme(oprot).write(oprot, this);" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a function to write all the fields of the struct, * which is a function result. These fields are only written * if they are set in the Isset array, and only one of them * can be set at a time. * * @param tstruct The struct definition */ void t_java_generator::generate_java_struct_result_writer(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot) throws " "org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "scheme(oprot).write(oprot, this);" << endl; indent_down(); indent(out) << " }" << endl << endl; } void t_java_generator::generate_java_struct_field_by_id(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << java_nullable_annotation() << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public _Fields fieldForId(int fieldId) {" << endl; indent(out) << " return _Fields.findByThriftId(fieldId);" << endl; indent(out) << "}" << endl << endl; } void t_java_generator::generate_reflection_getters(ostringstream& out, t_type* type, string field_name, string cap_name) { indent(out) << "case " << constant_name(field_name) << ":" << endl; indent_up(); indent(out) << "return " << (type->is_bool() ? "is" : "get") << cap_name << "();" << endl << endl; indent_down(); } void t_java_generator::generate_reflection_setters(ostringstream& out, t_type* type, string field_name, string cap_name) { const bool is_binary = type->is_binary(); indent(out) << "case " << constant_name(field_name) << ":" << endl; indent_up(); indent(out) << "if (value == null) {" << endl; indent(out) << " unset" << get_cap_name(field_name) << "();" << endl; indent(out) << "} else {" << endl; if (is_binary) { indent_up(); indent(out) << "if (value instanceof byte[]) {" << endl; indent(out) << " set" << cap_name << "((byte[])value);" << endl; indent(out) << "} else {" << endl; } indent(out) << " set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl; if (is_binary) { indent(out) << "}" << endl; indent_down(); } indent(out) << "}" << endl; indent(out) << "break;" << endl << endl; indent_down(); } void t_java_generator::generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct) { std::ostringstream getter_stream; std::ostringstream setter_stream; // build up the bodies of both the getter and setter at once const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); indent_up(); generate_reflection_setters(setter_stream, type, field_name, cap_name); generate_reflection_getters(getter_stream, type, field_name, cap_name); indent_down(); } // create the setter indent(out) << java_override_annotation() << endl; indent(out) << "public void setFieldValue(_Fields field, " << java_nullable_annotation() << " java.lang.Object value) {" << endl; indent(out) << " switch (field) {" << endl; out << setter_stream.str(); indent(out) << " }" << endl; indent(out) << "}" << endl << endl; // create the getter indent(out) << java_nullable_annotation() << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public java.lang.Object getFieldValue(_Fields field) {" << endl; indent_up(); indent(out) << "switch (field) {" << endl; out << getter_stream.str(); indent(out) << "}" << endl; indent(out) << "throw new java.lang.IllegalStateException();" << endl; indent_down(); indent(out) << "}" << endl << endl; } // Creates a generic isSet method that takes the field number as argument void t_java_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // create the isSet method indent(out) << "/** Returns true if field corresponding to fieldID is set (has been assigned a " "value) and false otherwise */" << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public boolean isSet(_Fields field) {" << endl; indent_up(); indent(out) << "if (field == null) {" << endl; indent(out) << " throw new java.lang.IllegalArgumentException();" << endl; indent(out) << "}" << endl << endl; indent(out) << "switch (field) {" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << "return " << generate_isset_check(field) << ";" << endl; indent_down(); } indent(out) << "}" << endl; indent(out) << "throw new java.lang.IllegalStateException();" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a set of Java Bean boilerplate functions (setters, getters, etc.) * for the given struct. * * @param tstruct The struct definition */ void t_java_generator::generate_java_bean_boilerplate(ostream& out, t_struct* tstruct) { isset_type issetType = needs_isset(tstruct); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); bool optional = use_option_type_ && field->get_req() == t_field::T_OPTIONAL; bool is_deprecated = this->is_deprecated(field->annotations_); if (type->is_container()) { // Method to return the size of the collection if (optional) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } if (use_jdk8_option_type_) { indent(out) << "public " << jdk_option_class << " get" << cap_name; } else { indent(out) << "public " << thrift_option_class << " get" << cap_name; } out << get_cap_name("size() {") << endl; indent_up(); indent(out) << "if (this." << field_name << " == null) {" << endl; indent_up(); if (use_jdk8_option_type_) { indent(out) << "return " << jdk_option_class << ".empty();" << endl; } else { indent(out) << "return " << thrift_option_class << ".none();" << endl; } indent_down(); indent(out) << "} else {" << endl; indent_up(); if (use_jdk8_option_type_) { indent(out) << "return " << jdk_option_class << ".of(this."; } else { indent(out) << "return " << thrift_option_class << ".some(this."; } out << field_name << ".size());" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl << endl; } else { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public int get" << cap_name; out << get_cap_name("size() {") << endl; indent_up(); indent(out) << "return (this." << field_name << " == null) ? 0 : " << "this." << field_name << ".size();" << endl; indent_down(); indent(out) << "}" << endl << endl; } } if (type->is_set() || type->is_list()) { t_type* element_type; if (type->is_set()) { element_type = ((t_set*)type)->get_elem_type(); } else { element_type = ((t_list*)type)->get_elem_type(); } // Iterator getter for sets and lists if (optional) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } if (use_jdk8_option_type_) { indent(out) << "public " << jdk_option_class << "<"; } else { indent(out) << "public " << thrift_option_class << "<"; } out << "java.util.Iterator<" << type_name(element_type, true, false) << ">> get" << cap_name; out << get_cap_name("iterator() {") << endl; indent_up(); indent(out) << "if (this." << field_name << " == null) {" << endl; indent_up(); if (use_jdk8_option_type_) { indent(out) << "return " << jdk_option_class << ".empty();" << endl; } else { indent(out) << "return " << thrift_option_class << ".none();" << endl; } indent_down(); indent(out) << "} else {" << endl; indent_up(); if (use_jdk8_option_type_) { indent(out) << "return " << jdk_option_class << ".of(this."; } else { indent(out) << "return " << thrift_option_class << ".some(this."; } out << field_name << ".iterator());" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl << endl; } else { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << java_nullable_annotation() << endl; indent(out) << "public java.util.Iterator<" << type_name(element_type, true, false) << "> get" << cap_name; out << get_cap_name("iterator() {") << endl; indent_up(); indent(out) << "return (this." << field_name << " == null) ? null : " << "this." << field_name << ".iterator();" << endl; indent_down(); indent(out) << "}" << endl << endl; } // Add to set or list, create if the set/list is null if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public void add" << get_cap_name("to"); out << cap_name << "(" << type_name(element_type) << " elem) {" << endl; indent_up(); indent(out) << "if (this." << field_name << " == null) {" << endl; indent_up(); indent(out) << "this." << field_name; if (is_enum_set(type)) { out << " = " << type_name(type, false, true, true) << ".noneOf(" << inner_enum_type_name(type) << ");" << endl; } else { out << " = new " << type_name(type, false, true) << "();" << endl; } indent_down(); indent(out) << "}" << endl; indent(out) << "this." << field_name << ".add(elem);" << endl; indent_down(); indent(out) << "}" << endl << endl; } else if (type->is_map()) { // Put to map t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public void put" << get_cap_name("to"); out << cap_name << "(" << type_name(key_type) << " key, " << type_name(val_type) << " val) {" << endl; indent_up(); indent(out) << "if (this." << field_name << " == null) {" << endl; indent_up(); std::string constructor_args; if (is_enum_map(type)) { constructor_args = inner_enum_type_name(type); } indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "(" << constructor_args << ");" << endl; indent_down(); indent(out) << "}" << endl; indent(out) << "this." << field_name << ".put(key, val);" << endl; indent_down(); indent(out) << "}" << endl << endl; } // Simple getter generate_java_doc(out, field); if (type->is_binary()) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public byte[] get" << cap_name << "() {" << endl; indent(out) << " set" << cap_name << "(org.apache.thrift.TBaseHelper.rightSize(" << field_name << "));" << endl; indent(out) << " return " << field_name << " == null ? null : " << field_name << ".array();" << endl; indent(out) << "}" << endl << endl; indent(out) << "public java.nio.ByteBuffer buffer" << get_cap_name("for") << cap_name << "() {" << endl; if (unsafe_binaries_) { indent(out) << " return " << field_name << ";" << endl; } else { indent(out) << " return org.apache.thrift.TBaseHelper.copyBinary(" << field_name << ");" << endl; } indent(out) << "}" << endl << endl; } else { if (optional) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } if (use_jdk8_option_type_) { indent(out) << "public " << jdk_option_class << "<" << type_name(type, true) << ">"; } else { indent(out) << "public " << thrift_option_class << "<" << type_name(type, true) << ">"; } if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) { out << " is"; } else { out << " get"; } out << cap_name << "() {" << endl; indent_up(); indent(out) << "if (this.isSet" << cap_name << "()) {" << endl; indent_up(); if (use_jdk8_option_type_) { indent(out) << "return " << jdk_option_class << ".of(this."; } else { indent(out) << "return " << thrift_option_class << ".some(this."; } out << field_name << ");" << endl; indent_down(); indent(out) << "} else {" << endl; indent_up(); if (use_jdk8_option_type_) { indent(out) << "return " << jdk_option_class << ".empty();" << endl; } else { indent(out) << "return " << thrift_option_class << ".none();" << endl; } indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl << endl; } else { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } if (type_can_be_null(type)) { indent(out) << java_nullable_annotation() << endl; } indent(out) << "public " << type_name(type); if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) { out << " is"; } else { out << " get"; } out << cap_name << "() {" << endl; indent_up(); indent(out) << "return this." << make_valid_java_identifier(field_name) << ";" << endl; indent_down(); indent(out) << "}" << endl << endl; } } // Simple setter generate_java_doc(out, field); if (type->is_binary()) { if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public "; if (bean_style_) { out << "void"; } else { out << type_name(tstruct); } out << " set" << cap_name << "(byte[] " << make_valid_java_identifier(field_name) << ") {" << endl; indent(out) << " this." << make_valid_java_identifier(field_name) << " = " << make_valid_java_identifier(field_name) << " == null ? (java.nio.ByteBuffer)null"; if (unsafe_binaries_) { indent(out) << " : java.nio.ByteBuffer.wrap(" << make_valid_java_identifier(field_name) << ");" << endl; } else { indent(out) << " : java.nio.ByteBuffer.wrap(" << make_valid_java_identifier(field_name) << ".clone());" << endl; } if (!bean_style_) { indent(out) << " return this;" << endl; } indent(out) << "}" << endl << endl; } if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public "; if (bean_style_) { out << "void"; } else { out << type_name(tstruct); } out << " set" << cap_name << "(" << (type_can_be_null(type) ? (java_nullable_annotation() + " ") : "") << type_name(type) << " " << make_valid_java_identifier(field_name) << ") {" << endl; indent_up(); indent(out) << "this." << make_valid_java_identifier(field_name) << " = "; if (type->is_binary() && !unsafe_binaries_) { out << "org.apache.thrift.TBaseHelper.copyBinary(" << make_valid_java_identifier(field_name) << ")"; } else { out << make_valid_java_identifier(field_name); } out << ";" << endl; generate_isset_set(out, field, ""); if (!bean_style_) { indent(out) << "return this;" << endl; } indent_down(); indent(out) << "}" << endl << endl; // Unsetter if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public void unset" << cap_name << "() {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "this." << make_valid_java_identifier(field_name) << " = null;" << endl; } else if (issetType == ISSET_PRIMITIVE) { indent(out) << "__isset_bitfield = org.apache.thrift.EncodingUtils.clearBit(__isset_bitfield, " << isset_field_id(field) << ");" << endl; } else { indent(out) << "__isset_bit_vector.clear(" << isset_field_id(field) << ");" << endl; } indent_down(); indent(out) << "}" << endl << endl; // isSet method indent(out) << "/** Returns true if field " << field_name << " is set (has been assigned a value) and false otherwise */" << endl; if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public boolean is" << get_cap_name("set") << cap_name << "() {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "return this." << make_valid_java_identifier(field_name) << " != null;" << endl; } else if (issetType == ISSET_PRIMITIVE) { indent(out) << "return org.apache.thrift.EncodingUtils.testBit(__isset_bitfield, " << isset_field_id(field) << ");" << endl; } else { indent(out) << "return __isset_bit_vector.get(" << isset_field_id(field) << ");" << endl; } indent_down(); indent(out) << "}" << endl << endl; if (is_deprecated) { indent(out) << "@Deprecated" << endl; } indent(out) << "public void set" << cap_name << get_cap_name("isSet") << "(boolean value) {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "if (!value) {" << endl; indent(out) << " this." << make_valid_java_identifier(field_name) << " = null;" << endl; indent(out) << "}" << endl; } else if (issetType == ISSET_PRIMITIVE) { indent(out) << "__isset_bitfield = org.apache.thrift.EncodingUtils.setBit(__isset_bitfield, " << isset_field_id(field) << ", value);" << endl; } else { indent(out) << "__isset_bit_vector.set(" << isset_field_id(field) << ", value);" << endl; } indent_down(); indent(out) << "}" << endl << endl; } } /** * Generates a toString() method for the given struct * * @param tstruct The struct definition */ void t_java_generator::generate_java_struct_tostring(ostream& out, t_struct* tstruct) { out << indent() << java_override_annotation() << endl << indent() << "public java.lang.String toString() {" << endl; indent_up(); out << indent() << "java.lang.StringBuilder sb = new java.lang.StringBuilder(\"" << tstruct->get_name() << "(\");" << endl; out << indent() << "boolean first = true;" << endl << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (could_be_unset) { indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); } t_field* field = (*f_iter); if (!first) { indent(out) << "if (!first) sb.append(\", \");" << endl; } indent(out) << "sb.append(\"" << (*f_iter)->get_name() << ":\");" << endl; bool can_be_null = type_can_be_null(field->get_type()); if (can_be_null) { indent(out) << "if (this." << make_valid_java_identifier((*f_iter)->get_name()) << " == null) {" << endl; indent(out) << " sb.append(\"null\");" << endl; indent(out) << "} else {" << endl; indent_up(); } if (get_true_type(field->get_type())->is_binary()) { indent(out) << "org.apache.thrift.TBaseHelper.toString(this." << make_valid_java_identifier(field->get_name()) << ", sb);" << endl; } else if ((field->get_type()->is_set()) && (get_true_type(((t_set*)field->get_type())->get_elem_type())->is_binary())) { indent(out) << "org.apache.thrift.TBaseHelper.toString(this." << make_valid_java_identifier(field->get_name()) << ", sb);" << endl; } else if ((field->get_type()->is_list()) && (get_true_type(((t_list*)field->get_type())->get_elem_type())->is_binary())) { indent(out) << "org.apache.thrift.TBaseHelper.toString(this." << make_valid_java_identifier(field->get_name()) << ", sb);" << endl; } else { indent(out) << "sb.append(this." << make_valid_java_identifier((*f_iter)->get_name()) << ");" << endl; } if (can_be_null) { indent_down(); indent(out) << "}" << endl; } indent(out) << "first = false;" << endl; if (could_be_unset) { indent_down(); indent(out) << "}" << endl; } first = false; } out << indent() << "sb.append(\")\");" << endl << indent() << "return sb.toString();" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a static map with meta data to store information such as fieldID to * fieldName mapping * * @param tstruct The struct definition */ void t_java_generator::generate_java_meta_data_map(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Static Map with fieldID -> org.apache.thrift.meta_data.FieldMetaData mappings indent(out) << "public static final java.util.Map<_Fields, " "org.apache.thrift.meta_data.FieldMetaData> metaDataMap;" << endl; indent(out) << "static {" << endl; indent_up(); indent(out) << "java.util.Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new " "java.util.EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);" << endl; // Populate map for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; std::string field_name = field->get_name(); indent(out) << "tmpMap.put(_Fields." << constant_name(field_name) << ", new org.apache.thrift.meta_data.FieldMetaData(\"" << field_name << "\", "; // Set field requirement type (required, optional, etc.) if (field->get_req() == t_field::T_REQUIRED) { out << "org.apache.thrift.TFieldRequirementType.REQUIRED, "; } else if (field->get_req() == t_field::T_OPTIONAL) { out << "org.apache.thrift.TFieldRequirementType.OPTIONAL, "; } else { out << "org.apache.thrift.TFieldRequirementType.DEFAULT, "; } // Create value meta data generate_field_value_meta_data(out, field->get_type()); // Include the annotation into metadata when asked if (annotations_as_metadata_) { generate_metadata_for_field_annotations(out, field); } out << "));" << endl; } indent(out) << "metaDataMap = java.util.Collections.unmodifiableMap(tmpMap);" << endl; indent(out) << "org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(" << type_name(tstruct) << ".class, metaDataMap);" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Returns a string with the java representation of the given thrift type * (e.g. for the type struct it returns "org.apache.thrift.protocol.TType.STRUCT") */ std::string t_java_generator::get_java_type_string(t_type* type) { if (type->is_list()) { return "org.apache.thrift.protocol.TType.LIST"; } else if (type->is_map()) { return "org.apache.thrift.protocol.TType.MAP"; } else if (type->is_set()) { return "org.apache.thrift.protocol.TType.SET"; } else if (type->is_struct() || type->is_xception()) { return "org.apache.thrift.protocol.TType.STRUCT"; } else if (type->is_enum()) { return "org.apache.thrift.protocol.TType.ENUM"; } else if (type->is_typedef()) { return get_java_type_string(((t_typedef*)type)->get_type()); } else if (type->is_base_type()) { switch (((t_base_type*)type)->get_base()) { case t_base_type::TYPE_VOID: return "org.apache.thrift.protocol.TType.VOID"; break; case t_base_type::TYPE_STRING: return "org.apache.thrift.protocol.TType.STRING"; break; case t_base_type::TYPE_UUID: return "org.apache.thrift.protocol.TType.UUID"; break; case t_base_type::TYPE_BOOL: return "org.apache.thrift.protocol.TType.BOOL"; break; case t_base_type::TYPE_I8: return "org.apache.thrift.protocol.TType.BYTE"; break; case t_base_type::TYPE_I16: return "org.apache.thrift.protocol.TType.I16"; break; case t_base_type::TYPE_I32: return "org.apache.thrift.protocol.TType.I32"; break; case t_base_type::TYPE_I64: return "org.apache.thrift.protocol.TType.I64"; break; case t_base_type::TYPE_DOUBLE: return "org.apache.thrift.protocol.TType.DOUBLE"; break; default: throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_java_generator::get_java_type_string!"); return "Unknown thrift type \"" + type->get_name() + "\" passed to t_java_generator::get_java_type_string!"; break; // This should never happen! } } else { throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_java_generator::get_java_type_string!"); // This should never happen! } } void t_java_generator::generate_metadata_for_field_annotations(std::ostream& out, t_field* field) { if (field->annotations_.size() == 0) { return; } out << ", " << endl; indent_up(); indent_up(); indent(out) << "java.util.stream.Stream.>builder()" << endl; indent_up(); indent_up(); for (auto& annotation : field->annotations_) { indent(out) << ".add(new java.util.AbstractMap.SimpleImmutableEntry<>(\"" + annotation.first + "\", \"" + annotation.second.back() + "\"))" << endl; } indent(out) << ".build().collect(java.util.stream.Collectors.toMap(java.util.Map.Entry::getKey, " "java.util.Map.Entry::getValue))"; indent_down(); indent_down(); indent_down(); indent_down(); } void t_java_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) { t_type* ttype = get_true_type(type); out << endl; indent_up(); indent_up(); if (ttype->is_struct() || ttype->is_xception()) { indent(out) << "new " "org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType." "STRUCT, " << type_name(ttype) << ".class"; } else if (ttype->is_container()) { if (ttype->is_list()) { indent(out) << "new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST, "; t_type* elem_type = ((t_list*)ttype)->get_elem_type(); generate_field_value_meta_data(out, elem_type); } else if (ttype->is_set()) { indent(out) << "new org.apache.thrift.meta_data.SetMetaData(org.apache.thrift.protocol.TType.SET, "; t_type* elem_type = ((t_set*)ttype)->get_elem_type(); generate_field_value_meta_data(out, elem_type); } else { // map indent(out) << "new org.apache.thrift.meta_data.MapMetaData(org.apache.thrift.protocol.TType.MAP, "; t_type* key_type = ((t_map*)ttype)->get_key_type(); t_type* val_type = ((t_map*)ttype)->get_val_type(); generate_field_value_meta_data(out, key_type); out << ", "; generate_field_value_meta_data(out, val_type); } } else if (ttype->is_enum()) { indent(out) << "new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, " << type_name(ttype) << ".class"; } else { indent(out) << "new org.apache.thrift.meta_data.FieldValueMetaData(" << get_java_type_string(ttype); if (ttype->is_binary()) { indent(out) << ", true"; } else if (type->is_typedef()) { indent(out) << ", \"" << ((t_typedef*)type)->get_symbolic() << "\""; } } out << ")"; indent_down(); indent_down(); } /** * Generates a thrift service. In C++, this comprises an entirely separate * header and source file. The header file defines the methods and includes * the data types defined in the main header file, and the implementation * file contains implementations of the basic printer and default interfaces. * * @param tservice The service definition */ void t_java_generator::generate_service(t_service* tservice) { // Make output file string f_service_name = package_dir_ + "/" + make_valid_java_filename(service_name_) + ".java"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << java_package(); if (!suppress_generated_annotations_) { generate_javax_generated_annotation(f_service_); } f_service_ << java_suppressions(); f_service_ << "public class " << make_valid_java_identifier(service_name_) << " {" << endl << endl; indent_up(); // Generate the three main parts of the service generate_service_interface(tservice); generate_service_async_interface(tservice); if (generate_future_iface_) { generate_service_future_interface(tservice); } generate_service_client(tservice); generate_service_async_client(tservice); if (generate_future_iface_) { generate_service_future_client(tservice); } generate_service_server(tservice); generate_service_async_server(tservice); generate_service_helpers(tservice); indent_down(); f_service_ << "}" << endl; f_service_.close(); } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_java_generator::generate_service_interface(t_service* tservice) { string extends = ""; string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_iface = " extends " + extends + ".Iface"; } generate_java_doc(f_service_, tservice); f_service_ << indent() << "public interface Iface" << extends_iface << " {" << endl << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_service_, *f_iter); indent(f_service_) << "public " << function_signature(*f_iter) << ";" << endl << endl; } indent_down(); f_service_ << indent() << "}" << endl << endl; } void t_java_generator::generate_service_async_interface(t_service* tservice) { string extends = ""; string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_iface = " extends " + extends + ".AsyncIface"; } f_service_ << indent() << "public interface AsyncIface" << extends_iface << " {" << endl << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent(f_service_) << "public " << function_signature_async(*f_iter, true) << " throws org.apache.thrift.TException;" << endl << endl; } indent_down(); f_service_ << indent() << "}" << endl << endl; } void t_java_generator::generate_service_future_interface(t_service* tservice) { string extends = ""; string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_iface = " extends " + extends + " .FutureIface"; } f_service_ << indent() << "public interface FutureIface" << extends_iface << " {" << endl << endl; indent_up(); for (auto tfunc : tservice->get_functions()) { indent(f_service_) << "public " << function_signature_future(tfunc) << " throws org.apache.thrift.TException;" << endl << endl; } scope_down(f_service_); f_service_ << endl << endl; } /** * Generates structs for all the service args and return types * * @param tservice The service */ void t_java_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_java_struct_definition(f_service_, ts, false, true); generate_function_helpers(*f_iter); } } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_java_generator::generate_service_client(t_service* tservice) { string extends_client = "org.apache.thrift.TServiceClient"; if (tservice->get_extends() != nullptr) { extends_client = type_name(tservice->get_extends()) + ".Client"; } indent(f_service_) << "public static class Client extends " << extends_client << " implements Iface {" << endl; indent_up(); indent(f_service_) << "public static class Factory implements org.apache.thrift.TServiceClientFactory {" << endl; indent_up(); indent(f_service_) << "public Factory() {}" << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public Client getClient(org.apache.thrift.protocol.TProtocol prot) {" << endl; indent_up(); indent(f_service_) << "return new Client(prot);" << endl; indent_down(); indent(f_service_) << "}" << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public Client getClient(org.apache.thrift.protocol.TProtocol iprot, " "org.apache.thrift.protocol.TProtocol oprot) {" << endl; indent_up(); indent(f_service_) << "return new Client(iprot, oprot);" << endl; indent_down(); indent(f_service_) << "}" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; indent(f_service_) << "public Client(org.apache.thrift.protocol.TProtocol prot)" << endl; scope_up(f_service_); indent(f_service_) << "super(prot, prot);" << endl; scope_down(f_service_); f_service_ << endl; indent(f_service_) << "public Client(org.apache.thrift.protocol.TProtocol iprot, " "org.apache.thrift.protocol.TProtocol oprot) {" << endl; indent(f_service_) << " super(iprot, oprot);" << endl; indent(f_service_) << "}" << endl << endl; // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); string sep = "_"; string javaname = funname; if (fullcamel_style_) { sep = ""; javaname = as_camel_case(funname); } // Open function indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public " << function_signature(*f_iter) << endl; scope_up(f_service_); indent(f_service_) << "send" << sep << javaname << "("; // Get the struct of function call params t_struct* arg_struct = (*f_iter)->get_arglist(); // Declare the function arguments const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << make_valid_java_identifier((*fld_iter)->get_name()); } f_service_ << ");" << endl; if (!(*f_iter)->is_oneway()) { f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << "return "; } f_service_ << "recv" << sep << javaname << "();" << endl; } scope_down(f_service_); f_service_ << endl; t_function send_function(g_type_void, string("send") + sep + javaname, (*f_iter)->get_arglist()); string argsname = (*f_iter)->get_name() + "_args"; // Open function indent(f_service_) << "public " << function_signature(&send_function) << endl; scope_up(f_service_); // Serialize the request indent(f_service_) << argsname << " args = new " << argsname << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { indent(f_service_) << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << make_valid_java_identifier((*fld_iter)->get_name()) << ");" << endl; } const string sendBaseName = (*f_iter)->is_oneway() ? "sendBaseOneway" : "sendBase"; indent(f_service_) << sendBaseName << "(\"" << funname << "\", args);" << endl; scope_down(f_service_); f_service_ << endl; if (!(*f_iter)->is_oneway()) { string resultname = (*f_iter)->get_name() + "_result"; t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv") + sep + javaname, &noargs, (*f_iter)->get_xceptions()); // Open function indent(f_service_) << "public " << function_signature(&recv_function) << endl; scope_up(f_service_); f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl << indent() << "receiveBase(result, \"" << funname << "\");" << endl; // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl << indent() << " return result.success;" << endl << indent() << "}" << endl; } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "if (result." << make_valid_java_identifier((*x_iter)->get_name()) << " != null) {" << endl << indent() << " throw result." << make_valid_java_identifier((*x_iter)->get_name()) << ";" << endl << indent() << "}" << endl; } // If you get here it's an exception, unless a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "return;" << endl; } else { f_service_ << indent() << "throw new " "org.apache.thrift.TApplicationException(org.apache.thrift." "TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } // Close function scope_down(f_service_); f_service_ << endl; } } indent_down(); indent(f_service_) << "}" << endl; } void t_java_generator::generate_service_future_client(t_service* tservice) { string extends_client = ""; if (tservice->get_extends() != nullptr) { extends_client = "extends " + type_name(tservice->get_extends()) + ".FutureClient "; } static string adapter_class = "org.apache.thrift.async.AsyncMethodFutureAdapter"; indent(f_service_) << "public static class FutureClient " << extends_client << "implements FutureIface {" << endl; indent_up(); indent(f_service_) << "public FutureClient(AsyncIface delegate) {" << endl; indent_up(); indent(f_service_) << "this.delegate = delegate;" << endl; scope_down(f_service_); indent(f_service_) << "private final AsyncIface delegate;" << endl; for (auto tfunc : tservice->get_functions()) { string funname = tfunc->get_name(); string sep = "_"; string javaname = funname; if (fullcamel_style_) { sep = ""; javaname = as_camel_case(javaname); } auto ret_type_name = type_name(tfunc->get_returntype(), /*in_container=*/true); t_struct* arg_struct = tfunc->get_arglist(); string funclassname = funname + "_call"; auto fields = arg_struct->get_members(); string args_name = funname + "_args"; string result_name = funname + "_result"; indent(f_service_) << "@Override" << endl; indent(f_service_) << "public " << function_signature_future(tfunc) << " throws org.apache.thrift.TException {" << endl; indent_up(); auto adapter = tmp("asyncMethodFutureAdapter"); indent(f_service_) << adapter_class << "<" << ret_type_name << "> " << adapter << " = " << adapter_class << ".<" << ret_type_name << ">create();" << endl; bool empty_args = tfunc->get_arglist()->get_members().empty(); indent(f_service_) << "delegate." << get_rpc_method_name(funname) << "(" << argument_list(tfunc->get_arglist(), false) << (empty_args ? "" : ", ") << adapter << ");" << endl; indent(f_service_) << "return " << adapter << ".getFuture();" << endl; scope_down(f_service_); f_service_ << endl; } scope_down(f_service_); f_service_ << endl; } void t_java_generator::generate_service_async_client(t_service* tservice) { string extends_client = "org.apache.thrift.async.TAsyncClient"; if (tservice->get_extends() != nullptr) { extends_client = type_name(tservice->get_extends()) + ".AsyncClient"; } indent(f_service_) << "public static class AsyncClient extends " << extends_client << " implements AsyncIface {" << endl; indent_up(); // Factory method indent(f_service_) << "public static class Factory implements " "org.apache.thrift.async.TAsyncClientFactory {" << endl; indent(f_service_) << " private org.apache.thrift.async.TAsyncClientManager clientManager;" << endl; indent(f_service_) << " private org.apache.thrift.protocol.TProtocolFactory protocolFactory;" << endl; indent(f_service_) << " public Factory(org.apache.thrift.async.TAsyncClientManager " "clientManager, org.apache.thrift.protocol.TProtocolFactory " "protocolFactory) {" << endl; indent(f_service_) << " this.clientManager = clientManager;" << endl; indent(f_service_) << " this.protocolFactory = protocolFactory;" << endl; indent(f_service_) << " }" << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << " public AsyncClient " "getAsyncClient(org.apache.thrift.transport.TNonblockingTransport " "transport) {" << endl; indent(f_service_) << " return new AsyncClient(protocolFactory, clientManager, transport);" << endl; indent(f_service_) << " }" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << "public AsyncClient(org.apache.thrift.protocol.TProtocolFactory " "protocolFactory, org.apache.thrift.async.TAsyncClientManager " "clientManager, org.apache.thrift.transport.TNonblockingTransport " "transport) {" << endl; indent(f_service_) << " super(protocolFactory, clientManager, transport);" << endl; indent(f_service_) << "}" << endl << endl; // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); string sep = "_"; string javaname = funname; if (fullcamel_style_) { sep = ""; javaname = as_camel_case(javaname); } t_type* ret_type = (*f_iter)->get_returntype(); t_struct* arg_struct = (*f_iter)->get_arglist(); string funclassname = funname + "_call"; const vector& fields = arg_struct->get_members(); const std::vector& xceptions = (*f_iter)->get_xceptions()->get_members(); vector::const_iterator fld_iter; string args_name = (*f_iter)->get_name() + "_args"; string result_name = (*f_iter)->get_name() + "_result"; // Main method body indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public " << function_signature_async(*f_iter, false) << " throws org.apache.thrift.TException {" << endl; indent(f_service_) << " checkReady();" << endl; indent(f_service_) << " " << funclassname << " method_call = new " + funclassname + "(" << async_argument_list(*f_iter, arg_struct, ret_type) << ", this, ___protocolFactory, ___transport);" << endl; indent(f_service_) << " this.___currentMethod = method_call;" << endl; indent(f_service_) << " ___manager.call(method_call);" << endl; indent(f_service_) << "}" << endl; f_service_ << endl; // TAsyncMethod object for this function call indent(f_service_) << "public static class " + funclassname + " extends org.apache.thrift.async.TAsyncMethodCall<" + type_name((*f_iter)->get_returntype(), true) + "> {" << endl; indent_up(); // Member variables for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { indent(f_service_) << "private " + type_name((*fld_iter)->get_type()) + " " + make_valid_java_identifier((*fld_iter)->get_name()) + ";" << endl; } // NOTE since we use a new Client instance to deserialize, let's keep seqid to 0 for now // indent(f_service_) << "private int seqid;" << endl << endl; // Constructor indent(f_service_) << "public " + funclassname + "(" + async_argument_list(*f_iter, arg_struct, ret_type, true) << ", org.apache.thrift.async.TAsyncClient client, " "org.apache.thrift.protocol.TProtocolFactory protocolFactory, " "org.apache.thrift.transport.TNonblockingTransport transport) throws " "org.apache.thrift.TException {" << endl; indent(f_service_) << " super(client, protocolFactory, transport, resultHandler, " << ((*f_iter)->is_oneway() ? "true" : "false") << ");" << endl; // Assign member variables for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { indent(f_service_) << " this." + make_valid_java_identifier((*fld_iter)->get_name()) + " = " + make_valid_java_identifier((*fld_iter)->get_name()) + ";" << endl; } indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public void write_args(org.apache.thrift.protocol.TProtocol prot) " "throws org.apache.thrift.TException {" << endl; indent_up(); // Serialize request // NOTE we are leaving seqid as 0, for now (see above) f_service_ << indent() << "prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage(\"" << funname << "\", org.apache.thrift.protocol." << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL") << ", 0));" << endl << indent() << args_name << " args = new " << args_name << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << indent() << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << make_valid_java_identifier((*fld_iter)->get_name()) << ");" << endl; } f_service_ << indent() << "args.write(prot);" << endl << indent() << "prot.writeMessageEnd();" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; // Return method indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public " + type_name(ret_type, true) + " getResult() throws "; vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << type_name((*x_iter)->get_type(), false, false) + ", "; } f_service_ << "org.apache.thrift.TException {" << endl; indent_up(); f_service_ << indent() << "if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {" << endl << indent() << " throw new java.lang.IllegalStateException(\"Method call not finished!\");" << endl << indent() << "}" << endl << indent() << "org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new " "org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());" << endl << indent() << "org.apache.thrift.protocol.TProtocol prot = " "client.getProtocolFactory().getProtocol(memoryTransport);" << endl; indent(f_service_); if (ret_type->is_void()) { // NB: Includes oneways which always return void. if (!(*f_iter)->is_oneway()) { f_service_ << "(new Client(prot)).recv" + sep + javaname + "();" << endl; indent(f_service_); } f_service_ << "return null;" << endl; } else { f_service_ << "return (new Client(prot)).recv" + sep + javaname + "();" << endl; } // Close function indent_down(); indent(f_service_) << "}" << endl; // Close class indent_down(); indent(f_service_) << "}" << endl << endl; } // Close AsyncClient scope_down(f_service_); f_service_ << endl; } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_java_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; // Extends stuff string extends = ""; string extends_processor = ""; if (tservice->get_extends() == nullptr) { extends_processor = "org.apache.thrift.TBaseProcessor"; } else { extends = type_name(tservice->get_extends()); extends_processor = extends + ".Processor"; } // Generate the header portion indent(f_service_) << "public static class Processor extends " << extends_processor << " implements org.apache.thrift.TProcessor {" << endl; indent_up(); indent(f_service_) << "private static final org.slf4j.Logger _LOGGER = " "org.slf4j.LoggerFactory.getLogger(Processor.class.getName());" << endl; indent(f_service_) << "public Processor(I iface) {" << endl; indent(f_service_) << " super(iface, getProcessMap(new java.util.HashMap>()));" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << "protected Processor(I iface, java.util.Map> " "processMap) {" << endl; indent(f_service_) << " super(iface, getProcessMap(processMap));" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << "private static java.util.Map> " "getProcessMap(java.util.Map> processMap) {" << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent(f_service_) << "processMap.put(\"" << (*f_iter)->get_name() << "\", new " << make_valid_java_identifier((*f_iter)->get_name()) << "());" << endl; } indent(f_service_) << "return processMap;" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } indent_down(); indent(f_service_) << "}" << endl << endl; } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_java_generator::generate_service_async_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; // Extends stuff string extends = ""; string extends_processor = ""; if (tservice->get_extends() == nullptr) { extends_processor = "org.apache.thrift.TBaseAsyncProcessor"; } else { extends = type_name(tservice->get_extends()); extends_processor = extends + ".AsyncProcessor"; } // Generate the header portion indent(f_service_) << "public static class AsyncProcessor extends " << extends_processor << " {" << endl; indent_up(); indent(f_service_) << "private static final org.slf4j.Logger _LOGGER = " "org.slf4j.LoggerFactory.getLogger(AsyncProcessor.class.getName());" << endl; indent(f_service_) << "public AsyncProcessor(I iface) {" << endl; indent(f_service_) << " super(iface, getProcessMap(new java.util.HashMap>()));" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << "protected AsyncProcessor(I iface, java.util.Map> processMap) {" << endl; indent(f_service_) << " super(iface, getProcessMap(processMap));" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << "private static java.util.Map> getProcessMap(java.util.Map> processMap) {" << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent(f_service_) << "processMap.put(\"" << (*f_iter)->get_name() << "\", new " << make_valid_java_identifier((*f_iter)->get_name()) << "());" << endl; } indent(f_service_) << "return processMap;" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_async_function(tservice, *f_iter); } indent_down(); indent(f_service_) << "}" << endl << endl; } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_java_generator::generate_function_helpers(t_function* tfunction) { if (tfunction->is_oneway()) { return; } t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_java_struct_definition(f_service_, &result, false, true, true); } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_java_generator::generate_process_async_function(t_service* tservice, t_function* tfunction) { string argsname = tfunction->get_name() + "_args"; string resultname = tfunction->get_name() + "_result"; if (tfunction->is_oneway()) { resultname = "org.apache.thrift.TBase"; } string resulttype = type_name(tfunction->get_returntype(), true); (void)tservice; // Open class indent(f_service_) << "public static class " << make_valid_java_identifier(tfunction->get_name()) << " extends org.apache.thrift.AsyncProcessFunction {" << endl; indent_up(); indent(f_service_) << "public " << make_valid_java_identifier(tfunction->get_name()) << "() {" << endl; indent(f_service_) << " super(\"" << tfunction->get_name() << "\");" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public " << argsname << " getEmptyArgsInstance() {" << endl; indent(f_service_) << " return new " << argsname << "();" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public org.apache.thrift.async.AsyncMethodCallback<" << resulttype << "> getResultHandler(final " "org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer fb, " "final int seqid) {" << endl; indent_up(); indent(f_service_) << "final org.apache.thrift.AsyncProcessFunction fcall = this;" << endl; indent(f_service_) << "return new org.apache.thrift.async.AsyncMethodCallback<" << resulttype << ">() { " << endl; indent_up(); indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public void onComplete(" << resulttype << " o) {" << endl; indent_up(); if (!tfunction->is_oneway()) { indent(f_service_) << resultname << " result = new " << resultname << "();" << endl; if (!tfunction->get_returntype()->is_void()) { indent(f_service_) << "result.success = o;" << endl; // Set isset on success field if (!type_can_be_null(tfunction->get_returntype())) { indent(f_service_) << "result.set" << get_cap_name("success") << get_cap_name("isSet") << "(true);" << endl; } } indent(f_service_) << "try {" << endl; indent(f_service_) << " fcall.sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);" << endl; indent(f_service_) << "} catch (org.apache.thrift.transport.TTransportException e) {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"TTransportException writing to internal frame buffer\", e);" << endl << indent() << "fb.close();" << endl; indent_down(); indent(f_service_) << "} catch (java.lang.Exception e) {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"Exception writing to internal frame buffer\", e);" << endl << indent() << "onError(e);" << endl; indent_down(); indent(f_service_) << "}" << endl; } indent_down(); indent(f_service_) << "}" << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public void onError(java.lang.Exception e) {" << endl; indent_up(); if (tfunction->is_oneway()) { indent(f_service_) << "if (e instanceof org.apache.thrift.transport.TTransportException) {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"TTransportException inside handler\", e);" << endl << indent() << "fb.close();" << endl; indent_down(); indent(f_service_) << "} else {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"Exception inside oneway handler\", e);" << endl; indent_down(); indent(f_service_) << "}" << endl; } else { indent(f_service_) << "byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;" << endl; indent(f_service_) << "org.apache.thrift.TSerializable msg;" << endl; indent(f_service_) << resultname << " result = new " << resultname << "();" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; if (xceptions.size() > 0) { for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { if (x_iter == xceptions.begin()) f_service_ << indent(); string type = type_name((*x_iter)->get_type(), false, false); string name = (*x_iter)->get_name(); f_service_ << "if (e instanceof " << type << ") {" << endl; indent_up(); f_service_ << indent() << "result." << make_valid_java_identifier(name) << " = (" << type << ") e;" << endl << indent() << "result.set" << get_cap_name(name) << get_cap_name("isSet") << "(true);" << endl << indent() << "msg = result;" << endl; indent_down(); indent(f_service_) << "} else "; } } else { indent(f_service_); } f_service_ << "if (e instanceof org.apache.thrift.transport.TTransportException) {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"TTransportException inside handler\", e);" << endl << indent() << "fb.close();" << endl << indent() << "return;" << endl; indent_down(); indent(f_service_) << "} else if (e instanceof org.apache.thrift.TApplicationException) {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"TApplicationException inside handler\", e);" << endl << indent() << "msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;" << endl << indent() << "msg = (org.apache.thrift.TApplicationException)e;" << endl; indent_down(); indent(f_service_) << "} else {" << endl; indent_up(); f_service_ << indent() << "_LOGGER.error(\"Exception inside handler\", e);" << endl << indent() << "msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;" << endl << indent() << "msg = new " "org.apache.thrift.TApplicationException(org.apache.thrift." "TApplicationException.INTERNAL_ERROR, e.getMessage());" << endl; indent_down(); f_service_ << indent() << "}" << endl << indent() << "try {" << endl << indent() << " fcall.sendResponse(fb,msg,msgType,seqid);" << endl << indent() << "} catch (java.lang.Exception ex) {" << endl << indent() << " _LOGGER.error(\"Exception writing to internal frame buffer\", ex);" << endl << indent() << " fb.close();" << endl << indent() << "}" << endl; } indent_down(); indent(f_service_) << "}" << endl; indent_down(); indent(f_service_) << "};" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "protected boolean isOneway() {" << endl; indent(f_service_) << " return " << ((tfunction->is_oneway()) ? "true" : "false") << ";" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public void start(I iface, " << argsname << " args, org.apache.thrift.async.AsyncMethodCallback<" << resulttype << "> resultHandler) throws org.apache.thrift.TException {" << endl; indent_up(); // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); f_service_ << "iface." << get_rpc_method_name(tfunction->get_name()) << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << make_valid_java_identifier((*f_iter)->get_name()); } if (!first) f_service_ << ","; f_service_ << "resultHandler"; f_service_ << ");" << endl; indent_down(); indent(f_service_) << "}"; // Close function f_service_ << endl; // Close class indent_down(); f_service_ << indent() << "}" << endl << endl; } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_java_generator::generate_process_function(t_service* tservice, t_function* tfunction) { string argsname = tfunction->get_name() + "_args"; string resultname = tfunction->get_name() + "_result"; if (tfunction->is_oneway()) { resultname = "org.apache.thrift.TBase"; } (void)tservice; // Open class indent(f_service_) << "public static class " << make_valid_java_identifier(tfunction->get_name()) << " extends org.apache.thrift.ProcessFunction {" << endl; indent_up(); indent(f_service_) << "public " << make_valid_java_identifier(tfunction->get_name()) << "() {" << endl; indent(f_service_) << " super(\"" << tfunction->get_name() << "\");" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public " << argsname << " getEmptyArgsInstance() {" << endl; indent(f_service_) << " return new " << argsname << "();" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "protected boolean isOneway() {" << endl; indent(f_service_) << " return " << ((tfunction->is_oneway()) ? "true" : "false") << ";" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "protected boolean rethrowUnhandledExceptions() {" << endl; indent(f_service_) << " return " << ((rethrow_unhandled_exceptions_) ? "true" : "false") << ";" << endl; indent(f_service_) << "}" << endl << endl; indent(f_service_) << java_override_annotation() << endl; indent(f_service_) << "public " << resultname << " getResult(I iface, " << argsname << " args) throws org.apache.thrift.TException {" << endl; indent_up(); if (!tfunction->is_oneway()) { indent(f_service_) << resultname << " result = new " << resultname << "();" << endl; } t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Try block for a function with exceptions if (xceptions.size() > 0) { f_service_ << indent() << "try {" << endl; indent_up(); } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "result.success = "; } f_service_ << "iface." << get_rpc_method_name(tfunction->get_name()) << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << make_valid_java_identifier((*f_iter)->get_name()); } f_service_ << ");" << endl; // Set isset on success field if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void() && !type_can_be_null(tfunction->get_returntype())) { indent(f_service_) << "result.set" << get_cap_name("success") << get_cap_name("isSet") << "(true);" << endl; } if (!tfunction->is_oneway() && xceptions.size() > 0) { indent_down(); f_service_ << indent() << "}"; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << " catch (" << type_name((*x_iter)->get_type(), false, false) << " " << make_valid_java_identifier((*x_iter)->get_name()) << ") {" << endl; if (!tfunction->is_oneway()) { indent_up(); f_service_ << indent() << "result." << make_valid_java_identifier((*x_iter)->get_name()) << " = " << make_valid_java_identifier((*x_iter)->get_name()) << ";" << endl; indent_down(); f_service_ << indent() << "}"; } else { f_service_ << "}"; } } f_service_ << endl; } if (tfunction->is_oneway()) { indent(f_service_) << "return null;" << endl; } else { indent(f_service_) << "return result;" << endl; } indent_down(); indent(f_service_) << "}"; // Close function f_service_ << endl; // Close class indent_down(); f_service_ << indent() << "}" << endl << endl; } /** * Deserializes a field of any type. * * @param tfield The field * @param prefix The variable name or container for this field */ void t_java_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool has_metadata) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + make_valid_java_identifier(tfield->get_name()); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name, has_metadata); } else if (type->is_base_type()) { indent(out) << name << " = iprot."; t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "readBinary();"; } else { out << "readString();"; } break; case t_base_type::TYPE_BOOL: out << "readBool();"; break; case t_base_type::TYPE_I8: out << "readByte();"; break; case t_base_type::TYPE_I16: out << "readI16();"; break; case t_base_type::TYPE_I32: out << "readI32();"; break; case t_base_type::TYPE_I64: out << "readI64();"; break; case t_base_type::TYPE_UUID: out << "readUuid();"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble();"; break; default: throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase); } out << endl; } else if (type->is_enum()) { indent(out) << name << " = " << type_name(tfield->get_type(), true, false, false, true) + ".findByValue(iprot.readI32());" << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); } } /** * Generates an unserializer for a struct, invokes read() */ void t_java_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { if (reuse_objects_) { indent(out) << "if (" << prefix << " == null) {" << endl; indent_up(); } indent(out) << prefix << " = new " << type_name(tstruct) << "();" << endl; if (reuse_objects_) { indent_down(); indent(out) << "}" << endl; } indent(out) << prefix << ".read(iprot);" << endl; } /** * Deserializes a container by reading its size and then iterating */ void t_java_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix, bool has_metadata) { scope_up(out); string obj; if (ttype->is_map()) { obj = tmp("_map"); } else if (ttype->is_set()) { obj = tmp("_set"); } else if (ttype->is_list()) { obj = tmp("_list"); } if (has_metadata) { // Declare variables, read header if (ttype->is_map()) { indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = iprot.readMapBegin();" << endl; } else if (ttype->is_set()) { indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = iprot.readSetBegin();" << endl; } else if (ttype->is_list()) { indent(out) << "org.apache.thrift.protocol.TList " << obj << " = iprot.readListBegin();" << endl; } } else { // Declare variables, read header if (ttype->is_map()) { indent(out) << "org.apache.thrift.protocol.TMap " << obj << " = iprot.readMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << "); " << endl; } else if (ttype->is_set()) { indent(out) << "org.apache.thrift.protocol.TSet " << obj << " = iprot.readSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ");" << endl; } else if (ttype->is_list()) { indent(out) << "org.apache.thrift.protocol.TList " << obj << " = iprot.readListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ");" << endl; } } if (reuse_objects_) { indent(out) << "if (" << prefix << " == null) {" << endl; indent_up(); } if (is_enum_set(ttype)) { out << indent() << prefix << " = " << type_name(ttype, false, true, true) << ".noneOf"; } else { out << indent() << prefix << " = new " << type_name(ttype, false, true); } // construct the collection correctly i.e. with appropriate size/type if (is_enum_set(ttype) || is_enum_map(ttype)) { out << "(" << inner_enum_type_name(ttype) << ");" << endl; } else if (sorted_containers_ && (ttype->is_map() || ttype->is_set())) { // TreeSet and TreeMap don't have any constructor which takes a capacity as an argument out << "();" << endl; } else { out << "(" << (ttype->is_list() ? "" : "2*") << obj << ".size" << ");" << endl; } if (reuse_objects_) { indent_down(); indent(out) << "}" << endl; } if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix, obj, has_metadata); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix, obj, has_metadata); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix, obj, has_metadata); } scope_down(out); if (has_metadata) { // Read container end if (ttype->is_map()) { indent(out) << "iprot.readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "iprot.readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "iprot.readListEnd();" << endl; } } scope_down(out); } /** * Generates code to deserialize a map */ void t_java_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix, string obj, bool has_metadata) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey, reuse_objects_, false) << endl; indent(out) << declare_field(&fval, reuse_objects_, false) << endl; // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".size" << "; " << "++" << i << ")" << endl; scope_up(out); generate_deserialize_field(out, &fkey, "", has_metadata); generate_deserialize_field(out, &fval, "", has_metadata); if (get_true_type(fkey.get_type())->is_enum()) { indent(out) << "if (" << key << " != null)" << endl; scope_up(out); } indent(out) << prefix << ".put(" << key << ", " << val << ");" << endl; if (get_true_type(fkey.get_type())->is_enum()) { scope_down(out); } if (reuse_objects_ && !get_true_type(fkey.get_type())->is_base_type()) { indent(out) << key << " = null;" << endl; } if (reuse_objects_ && !get_true_type(fval.get_type())->is_base_type()) { indent(out) << val << " = null;" << endl; } } /** * Deserializes a set element */ void t_java_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix, string obj, bool has_metadata) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << declare_field(&felem, reuse_objects_, false) << endl; // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".size" << "; " << "++" << i << ")" << endl; scope_up(out); generate_deserialize_field(out, &felem, "", has_metadata); if (get_true_type(felem.get_type())->is_enum()) { indent(out) << "if (" << elem << " != null)" << endl; scope_up(out); } indent(out) << prefix << ".add(" << elem << ");" << endl; if (get_true_type(felem.get_type())->is_enum()) { scope_down(out); } if (reuse_objects_ && !get_true_type(felem.get_type())->is_base_type()) { indent(out) << elem << " = null;" << endl; } } /** * Deserializes a list element */ void t_java_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix, string obj, bool has_metadata) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << declare_field(&felem, reuse_objects_, false) << endl; // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".size" << "; " << "++" << i << ")" << endl; scope_up(out); generate_deserialize_field(out, &felem, "", has_metadata); if (get_true_type(felem.get_type())->is_enum()) { indent(out) << "if (" << elem << " != null)" << endl; scope_up(out); } indent(out) << prefix << ".add(" << elem << ");" << endl; if (get_true_type(felem.get_type())->is_enum()) { scope_down(out); } if (reuse_objects_ && !get_true_type(felem.get_type())->is_base_type()) { indent(out) << elem << " = null;" << endl; } } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_java_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, string postfix, bool has_metadata) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name() + postfix; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + make_valid_java_identifier(tfield->get_name()) + postfix); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + make_valid_java_identifier(tfield->get_name()) + postfix, has_metadata); } else if (type->is_enum()) { indent(out) << "oprot.writeI32(" << prefix + make_valid_java_identifier(tfield->get_name()) + postfix << ".getValue());" << endl; } else if (type->is_base_type()) { string name = prefix + make_valid_java_identifier(tfield->get_name()) + postfix; indent(out) << "oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "writeBinary(" << name << ");"; } else { out << "writeString(" << name << ");"; } break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ");"; break; case t_base_type::TYPE_UUID: out << "writeUuid(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ");"; break; default: throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32(struct." << name << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), postfix.c_str(), type_name(type).c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_java_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; out << indent() << prefix << ".write(oprot);" << endl; } /** * Serializes a container by writing its size then the elements. * * @param ttype The type of container * @param prefix String prefix for fields */ void t_java_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix, bool has_metadata) { scope_up(out); if (has_metadata) { if (ttype->is_map()) { indent(out) << "oprot.writeMapBegin(new org.apache.thrift.protocol.TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix << ".size()));" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetBegin(new org.apache.thrift.protocol.TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix << ".size()));" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListBegin(new org.apache.thrift.protocol.TList(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".size()));" << endl; } } else { indent(out) << "oprot.writeI32(" << prefix << ".size());" << endl; } string iter = tmp("_iter"); if (ttype->is_map()) { indent(out) << "for (java.util.Map.Entry<" << type_name(((t_map*)ttype)->get_key_type(), true, false) << ", " << type_name(((t_map*)ttype)->get_val_type(), true, false) << "> " << iter << " : " << prefix << ".entrySet())"; } else if (ttype->is_set()) { indent(out) << "for (" << type_name(((t_set*)ttype)->get_elem_type()) << " " << iter << " : " << prefix << ")"; } else if (ttype->is_list()) { indent(out) << "for (" << type_name(((t_list*)ttype)->get_elem_type()) << " " << iter << " : " << prefix << ")"; } out << endl; scope_up(out); if (ttype->is_map()) { generate_serialize_map_element(out, (t_map*)ttype, iter, prefix, has_metadata); } else if (ttype->is_set()) { generate_serialize_set_element(out, (t_set*)ttype, iter, has_metadata); } else if (ttype->is_list()) { generate_serialize_list_element(out, (t_list*)ttype, iter, has_metadata); } scope_down(out); if (has_metadata) { if (ttype->is_map()) { indent(out) << "oprot.writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListEnd();" << endl; } } scope_down(out); } /** * Serializes the members of a map. */ void t_java_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map, bool has_metadata) { (void)map; t_field kfield(tmap->get_key_type(), iter); generate_serialize_field(out, &kfield, "", ".getKey()", has_metadata); t_field vfield(tmap->get_val_type(), iter); generate_serialize_field(out, &vfield, "", ".getValue()", has_metadata); } /** * Serializes the members of a set. */ void t_java_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter, bool has_metadata) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, "", "", has_metadata); } /** * Serializes the members of a list. */ void t_java_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter, bool has_metadata) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, "", "", has_metadata); } /** * Returns a Java type name * * @param ttype The type * @param container Is the type going inside a container? * @return Java type name, i.e. java.util.HashMap */ string t_java_generator::type_name(t_type* ttype, bool in_container, bool in_init, bool skip_generic, bool force_namespace) { // In Java typedefs are just resolved to their real type ttype = get_true_type(ttype); string prefix; if (ttype->is_base_type()) { return base_type_name((t_base_type*)ttype, in_container); } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; if (in_init) { if (is_enum_map(tmap)) { prefix = "java.util.EnumMap"; } else if (sorted_containers_) { prefix = "java.util.TreeMap"; } else { prefix = "java.util.HashMap"; } } else { prefix = "java.util.Map"; } return prefix + (skip_generic ? "" : "<" + type_name(tmap->get_key_type(), true) + "," + type_name(tmap->get_val_type(), true) + ">"); } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; if (in_init) { if (is_enum_set(tset)) { prefix = "java.util.EnumSet"; } else if (sorted_containers_) { prefix = "java.util.TreeSet"; } else { prefix = "java.util.HashSet"; } } else { prefix = "java.util.Set"; } return prefix + (skip_generic ? "" : "<" + type_name(tset->get_elem_type(), true) + ">"); } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; if (in_init) { prefix = "java.util.ArrayList"; } else { prefix = "java.util.List"; } return prefix + (skip_generic ? "" : "<" + type_name(tlist->get_elem_type(), true) + ">"); } // Check for namespacing t_program* program = ttype->get_program(); if ((program != nullptr) && ((program != program_) || force_namespace)) { string package = program->get_namespace("java"); if (!package.empty()) { return package + "." + make_valid_java_identifier(ttype->get_name()); } } return make_valid_java_identifier(ttype->get_name()); } /** * Returns the Java type that corresponds to the thrift type. * * @param tbase The base type * @param container Is it going in a Java container? */ string t_java_generator::base_type_name(t_base_type* type, bool in_container) { t_base_type::t_base tbase = type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return (in_container ? "Void" : "void"); case t_base_type::TYPE_STRING: if (type->is_binary()) { return "java.nio.ByteBuffer"; } else { return "java.lang.String"; } case t_base_type::TYPE_UUID: return "java.util.UUID"; case t_base_type::TYPE_BOOL: return (in_container ? "java.lang.Boolean" : "boolean"); case t_base_type::TYPE_I8: return (in_container ? "java.lang.Byte" : "byte"); case t_base_type::TYPE_I16: return (in_container ? "java.lang.Short" : "short"); case t_base_type::TYPE_I32: return (in_container ? "java.lang.Integer" : "int"); case t_base_type::TYPE_I64: return (in_container ? "java.lang.Long" : "long"); case t_base_type::TYPE_DOUBLE: return (in_container ? "java.lang.Double" : "double"); default: throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase); } } /** * Declares a field, which may include initialization as necessary. * * @param tfield The field * @param init Whether to initialize the field */ string t_java_generator::declare_field(t_field* tfield, bool init, bool comment) { // TODO(mcslee): do we ever need to initialize the field? string result = ""; t_type* ttype = get_true_type(tfield->get_type()); if (type_can_be_null(ttype)) { result += java_nullable_annotation() + " "; } result += type_name(tfield->get_type()) + " " + make_valid_java_identifier(tfield->get_name()); if (init) { if (ttype->is_base_type() && tfield->get_value() != nullptr) { std::ofstream dummy; result += " = " + render_const_value(dummy, ttype, tfield->get_value()); } else if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: case t_base_type::TYPE_UUID: result += " = null"; break; case t_base_type::TYPE_BOOL: result += " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = (double)0"; break; default: throw "compiler error: unhandled type"; } } else if (ttype->is_enum()) { result += " = null"; } else if (ttype->is_container()) { result += " = new " + type_name(ttype, false, true) + "()"; } else { result += " = new " + type_name(ttype, false, true) + "()"; ; } } result += ";"; if (comment) { result += " // "; if (tfield->get_req() == t_field::T_OPTIONAL) { result += "optional"; } else { result += "required"; } } return result; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_java_generator::function_signature(t_function* tfunction, string prefix) { t_type* ttype = tfunction->get_returntype(); std::string fn_name = get_rpc_method_name(tfunction->get_name()); std::string result = type_name(ttype) + " " + prefix + fn_name + "(" + argument_list(tfunction->get_arglist()) + ") throws "; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { result += type_name((*x_iter)->get_type(), false, false) + ", "; } result += "org.apache.thrift.TException"; return result; } /** * Renders a function signature of the form 'void name(args, resultHandler)' * * @params tfunction Function definition * @return String of rendered function definition */ string t_java_generator::function_signature_async(t_function* tfunction, bool use_base_method, string prefix) { std::string arglist = async_function_call_arglist(tfunction, use_base_method, true); std::string ret_type = ""; if (use_base_method) { ret_type += "AsyncClient."; } ret_type += tfunction->get_name() + "_call"; std::string fn_name = get_rpc_method_name(tfunction->get_name()); std::string result = prefix + "void " + fn_name + "(" + arglist + ")"; return result; } /** * Renders a function signature of the form 'CompletableFuture name(args)' * * @params tfunction Function definition * @return String of rendered function definition */ string t_java_generator::function_signature_future(t_function* tfunction, string prefix) { t_type* ttype = tfunction->get_returntype(); std::string fn_name = get_rpc_method_name(tfunction->get_name()); return "java.util.concurrent.CompletableFuture<" + type_name(ttype, /*in_container=*/true) + "> " + prefix + fn_name + "(" + argument_list(tfunction->get_arglist()) + ")"; } string t_java_generator::async_function_call_arglist(t_function* tfunc, bool use_base_method, bool include_types) { (void)use_base_method; std::string arglist = ""; if (tfunc->get_arglist()->get_members().size() > 0) { arglist = argument_list(tfunc->get_arglist(), include_types) + ", "; } if (include_types) { arglist += "org.apache.thrift.async.AsyncMethodCallback<"; arglist += type_name(tfunc->get_returntype(), true) + "> "; } arglist += "resultHandler"; return arglist; } /** * Renders a comma separated field list, with type names */ string t_java_generator::argument_list(t_struct* tstruct, bool include_types) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } if (include_types) { result += type_name((*f_iter)->get_type()) + " "; } result += make_valid_java_identifier((*f_iter)->get_name()); } return result; } string t_java_generator::async_argument_list(t_function* tfunct, t_struct* tstruct, t_type* ttype, bool include_types) { (void)tfunct; (void)ttype; string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } if (include_types) { result += type_name((*f_iter)->get_type()) + " "; } result += make_valid_java_identifier((*f_iter)->get_name()); } if (!first) { result += ", "; } if (include_types) { result += "org.apache.thrift.async.AsyncMethodCallback<"; result += type_name(tfunct->get_returntype(), true) + "> "; } result += "resultHandler"; return result; } /** * Converts the parse type to a Java enum string for the given type. */ string t_java_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "org.apache.thrift.protocol.TType.STRING"; case t_base_type::TYPE_BOOL: return "org.apache.thrift.protocol.TType.BOOL"; case t_base_type::TYPE_I8: return "org.apache.thrift.protocol.TType.BYTE"; case t_base_type::TYPE_I16: return "org.apache.thrift.protocol.TType.I16"; case t_base_type::TYPE_I32: return "org.apache.thrift.protocol.TType.I32"; case t_base_type::TYPE_I64: return "org.apache.thrift.protocol.TType.I64"; case t_base_type::TYPE_UUID: return "org.apache.thrift.protocol.TType.UUID"; case t_base_type::TYPE_DOUBLE: return "org.apache.thrift.protocol.TType.DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "org.apache.thrift.protocol.TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "org.apache.thrift.protocol.TType.STRUCT"; } else if (type->is_map()) { return "org.apache.thrift.protocol.TType.MAP"; } else if (type->is_set()) { return "org.apache.thrift.protocol.TType.SET"; } else if (type->is_list()) { return "org.apache.thrift.protocol.TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Takes a name and produes a valid Java source file name from it * * @param fromName The name which shall become a valid Java source file name * @return The produced identifier */ std::string t_java_generator::make_valid_java_filename(std::string const& fromName) { // if any further rules apply to source file names in Java, modify as necessary return make_valid_java_identifier(fromName); } /** * Takes a name and produes a valid Java identifier from it * * @param fromName The name which shall become a valid Java identifier * @return The produced identifier */ std::string t_java_generator::make_valid_java_identifier(std::string const& fromName) { std::string str = fromName; if (str.empty()) { return str; } // tests rely on this assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); // if the first letter is a number, we add an additional underscore in front of it char c = str.at(0); if (('0' <= c) && (c <= '9')) { str = "_" + str; } // following chars: letter, number or underscore for (size_t i = 0; i < str.size(); ++i) { c = str.at(i); if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9')) && ('_' != c)) { str.replace(i, 1, "_"); } } return normalize_name(str); } std::string t_java_generator::as_camel_case(std::string name, bool ucfirst) { std::string new_name; size_t i = 0; for (i = 0; i < name.size(); i++) { if (name[i] != '_') break; } if (ucfirst) { new_name += toupper(name[i++]); } else { new_name += tolower(name[i++]); } for (; i < name.size(); i++) { if (name[i] == '_') { if (i < name.size() - 1) { i++; new_name += toupper(name[i]); } } else { new_name += name[i]; } } return new_name; } std::string t_java_generator::get_rpc_method_name(std::string name) { if (fullcamel_style_) { return make_valid_java_identifier(as_camel_case(name, false)); } else { return make_valid_java_identifier(name); } } /** * Applies the correct style to a string based on the value of nocamel_style_ * and/or fullcamel_style_ */ std::string t_java_generator::get_cap_name(std::string name) { if (nocamel_style_) { return "_" + name; } else if (fullcamel_style_) { return as_camel_case(name); } else { name[0] = toupper(name[0]); return name; } } string t_java_generator::constant_name(string name) { string constant_name; bool is_first = true; bool was_previous_char_upper = false; for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { constant_name += '_'; } constant_name += toupper(character); is_first = false; was_previous_char_upper = is_upper; } return constant_name; } void t_java_generator::generate_deep_copy_container(ostream& out, std::string source_name_p1, std::string source_name_p2, std::string result_name, t_type* type) { t_container* container = (t_container*)type; std::string source_name; if (source_name_p2 == "") source_name = source_name_p1; else source_name = source_name_p1 + "." + source_name_p2; bool copy_construct_container; if (container->is_map()) { t_map* tmap = (t_map*)container; copy_construct_container = tmap->get_key_type()->is_base_type() && tmap->get_val_type()->is_base_type(); } else { t_type* elem_type = container->is_list() ? ((t_list*)container)->get_elem_type() : ((t_set*)container)->get_elem_type(); copy_construct_container = elem_type->is_base_type(); } if (copy_construct_container) { // deep copy of base types can be done much more efficiently than iterating over all the // elements manually indent(out) << type_name(type, true, false) << " " << result_name << " = new " << type_name(container, false, true) << "(" << source_name << ");" << endl; return; } std::string constructor_args; if (is_enum_set(container) || is_enum_map(container)) { constructor_args = inner_enum_type_name(container); } else if (!(sorted_containers_ && (container->is_map() || container->is_set()))) { // unsorted containers accept a capacity value constructor_args = source_name + ".size()"; } if (is_enum_set(container)) { indent(out) << type_name(type, true, false) << " " << result_name << " = " << type_name(container, false, true, true) << ".noneOf(" << constructor_args << ");" << endl; } else { indent(out) << type_name(type, true, false) << " " << result_name << " = new " << type_name(container, false, true) << "(" << constructor_args << ");" << endl; } std::string iterator_element_name = source_name_p1 + "_element"; std::string result_element_name = result_name + "_copy"; if (container->is_map()) { t_type* key_type = ((t_map*)container)->get_key_type(); t_type* val_type = ((t_map*)container)->get_val_type(); indent(out) << "for (java.util.Map.Entry<" << type_name(key_type, true, false) << ", " << type_name(val_type, true, false) << "> " << iterator_element_name << " : " << source_name << ".entrySet()) {" << endl; indent_up(); out << endl; indent(out) << type_name(key_type, true, false) << " " << iterator_element_name << "_key = " << iterator_element_name << ".getKey();" << endl; indent(out) << type_name(val_type, true, false) << " " << iterator_element_name << "_value = " << iterator_element_name << ".getValue();" << endl; out << endl; if (key_type->is_container()) { generate_deep_copy_container(out, iterator_element_name + "_key", "", result_element_name + "_key", key_type); } else { indent(out) << type_name(key_type, true, false) << " " << result_element_name << "_key = "; generate_deep_copy_non_container(out, iterator_element_name + "_key", result_element_name + "_key", key_type); out << ";" << endl; } out << endl; if (val_type->is_container()) { generate_deep_copy_container(out, iterator_element_name + "_value", "", result_element_name + "_value", val_type); } else { indent(out) << type_name(val_type, true, false) << " " << result_element_name << "_value = "; generate_deep_copy_non_container(out, iterator_element_name + "_value", result_element_name + "_value", val_type); out << ";" << endl; } out << endl; indent(out) << result_name << ".put(" << result_element_name << "_key, " << result_element_name << "_value);" << endl; indent_down(); indent(out) << "}" << endl; } else { t_type* elem_type; if (container->is_set()) { elem_type = ((t_set*)container)->get_elem_type(); } else { elem_type = ((t_list*)container)->get_elem_type(); } indent(out) << "for (" << type_name(elem_type, true, false) << " " << iterator_element_name << " : " << source_name << ") {" << endl; indent_up(); if (elem_type->is_container()) { // recursive deep copy generate_deep_copy_container(out, iterator_element_name, "", result_element_name, elem_type); indent(out) << result_name << ".add(" << result_element_name << ");" << endl; } else { // iterative copy if (elem_type->is_binary()) { indent(out) << "java.nio.ByteBuffer temp_binary_element = "; generate_deep_copy_non_container(out, iterator_element_name, "temp_binary_element", elem_type); out << ";" << endl; indent(out) << result_name << ".add(temp_binary_element);" << endl; } else { indent(out) << result_name << ".add("; generate_deep_copy_non_container(out, iterator_element_name, result_name, elem_type); out << ");" << endl; } } indent_down(); indent(out) << "}" << endl; } } void t_java_generator::generate_deep_copy_non_container(ostream& out, std::string source_name, std::string dest_name, t_type* type) { (void)dest_name; type = get_true_type(type); if (type->is_base_type() || type->is_enum() || type->is_typedef()) { if (type->is_binary()) { out << "org.apache.thrift.TBaseHelper.copyBinary(" << source_name << ")"; } else { // everything else can be copied directly out << source_name; } } else { out << "new " << type_name(type, true, true) << "(" << source_name << ")"; } } std::string t_java_generator::generate_isset_check(t_field* field) { return generate_isset_check(field->get_name()); } std::string t_java_generator::isset_field_id(t_field* field) { return "__" + upcase_string(field->get_name() + "_isset_id"); } std::string t_java_generator::generate_isset_check(std::string field_name) { return "is" + get_cap_name("set") + get_cap_name(field_name) + "()"; } void t_java_generator::generate_isset_set(ostream& out, t_field* field, string prefix) { if (!type_can_be_null(field->get_type())) { indent(out) << prefix << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(true);" << endl; } } void t_java_generator::generate_struct_desc(ostream& out, t_struct* tstruct) { indent(out) << "private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new " "org.apache.thrift.protocol.TStruct(\"" << tstruct->get_name() << "\");" << endl; } void t_java_generator::generate_field_descs(ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "private static final org.apache.thrift.protocol.TField " << constant_name((*m_iter)->get_name()) << "_FIELD_DESC = new org.apache.thrift.protocol.TField(\"" << (*m_iter)->get_name() << "\", " << type_to_enum((*m_iter)->get_type()) << ", " << "(short)" << (*m_iter)->get_key() << ");" << endl; } } void t_java_generator::generate_scheme_map(ostream& out, t_struct* tstruct) { indent(out) << "private static final org.apache.thrift.scheme.SchemeFactory " "STANDARD_SCHEME_FACTORY = new " << tstruct->get_name() << "StandardSchemeFactory();" << endl; indent(out) << "private static final org.apache.thrift.scheme.SchemeFactory TUPLE_SCHEME_FACTORY = new " << tstruct->get_name() << "TupleSchemeFactory();" << endl; } void t_java_generator::generate_field_name_constants(ostream& out, t_struct* tstruct) { indent(out) << "/** The set of fields this struct contains, along with convenience methods for " "finding and manipulating them. */" << endl; indent(out) << "public enum _Fields implements org.apache.thrift.TFieldIdEnum {" << endl; indent_up(); bool first = true; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!first) { out << "," << endl; } first = false; generate_java_doc(out, *m_iter); indent(out) << constant_name((*m_iter)->get_name()) << "((short)" << (*m_iter)->get_key() << ", \"" << (*m_iter)->get_name() << "\")"; } out << ";" << endl << endl; indent(out) << "private static final java.util.Map byName = new " "java.util.HashMap();" << endl; out << endl; indent(out) << "static {" << endl; indent(out) << " for (_Fields field : java.util.EnumSet.allOf(_Fields.class)) {" << endl; indent(out) << " byName.put(field.getFieldName(), field);" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl << endl; indent(out) << "/**" << endl; indent(out) << " * Find the _Fields constant that matches fieldId, or null if its not found." << endl; indent(out) << " */" << endl; indent(out) << java_nullable_annotation() << endl; indent(out) << "public static _Fields findByThriftId(int fieldId) {" << endl; indent_up(); indent(out) << "switch(fieldId) {" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "case " << (*m_iter)->get_key() << ": // " << constant_name((*m_iter)->get_name()) << endl; indent(out) << " return " << constant_name((*m_iter)->get_name()) << ";" << endl; } indent(out) << "default:" << endl; indent(out) << " return null;" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl << endl; indent(out) << "/**" << endl; indent(out) << " * Find the _Fields constant that matches fieldId, throwing an exception" << endl; indent(out) << " * if it is not found." << endl; indent(out) << " */" << endl; indent(out) << "public static _Fields findByThriftIdOrThrow(int fieldId) {" << endl; indent(out) << " _Fields fields = findByThriftId(fieldId);" << endl; indent(out) << " if (fields == null) throw new java.lang.IllegalArgumentException(\"Field \" + " "fieldId + " "\" doesn't exist!\");" << endl; indent(out) << " return fields;" << endl; indent(out) << "}" << endl << endl; indent(out) << "/**" << endl; indent(out) << " * Find the _Fields constant that matches name, or null if its not found." << endl; indent(out) << " */" << endl; indent(out) << java_nullable_annotation() << endl; indent(out) << "public static _Fields findByName(java.lang.String name) {" << endl; indent(out) << " return byName.get(name);" << endl; indent(out) << "}" << endl << endl; indent(out) << "private final short _thriftId;" << endl; indent(out) << "private final java.lang.String _fieldName;" << endl << endl; indent(out) << "_Fields(short thriftId, java.lang.String fieldName) {" << endl; indent(out) << " _thriftId = thriftId;" << endl; indent(out) << " _fieldName = fieldName;" << endl; indent(out) << "}" << endl << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public short getThriftFieldId() {" << endl; indent(out) << " return _thriftId;" << endl; indent(out) << "}" << endl << endl; indent(out) << java_override_annotation() << endl; indent(out) << "public java.lang.String getFieldName() {" << endl; indent(out) << " return _fieldName;" << endl; indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } t_java_generator::isset_type t_java_generator::needs_isset(t_struct* tstruct, std::string* outPrimitiveType) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; int count = 0; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!type_can_be_null(get_true_type((*m_iter)->get_type()))) { count++; } } if (count == 0) { return ISSET_NONE; } else if (count <= 64) { if (outPrimitiveType != nullptr) { if (count <= 8) *outPrimitiveType = "byte"; else if (count <= 16) *outPrimitiveType = "short"; else if (count <= 32) *outPrimitiveType = "int"; else if (count <= 64) *outPrimitiveType = "long"; } return ISSET_PRIMITIVE; } else { return ISSET_BITSET; } } void t_java_generator::generate_java_struct_clear(std::ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "public void clear() {" << endl; indent_up(); for (auto field : tstruct->get_members()) { t_type* t = get_true_type(field->get_type()); if (field->get_value() != nullptr) { print_const_value(out, "this." + make_valid_java_identifier(field->get_name()), t, field->get_value(), true, true); continue; } if (type_can_be_null(t)) { if (reuse_objects_ && (t->is_container() || t->is_struct())) { indent(out) << "if (this." << make_valid_java_identifier(field->get_name()) << " != null) {" << endl; indent_up(); indent(out) << "this." << make_valid_java_identifier(field->get_name()) << ".clear();" << endl; indent_down(); indent(out) << "}" << endl; } else { indent(out) << "this." << make_valid_java_identifier(field->get_name()) << " = null;" << endl; } continue; } // must be a base type // means it also needs to be explicitly unset indent(out) << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(false);" << endl; t_base_type* base_type = (t_base_type*)t; switch (base_type->get_base()) { case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: indent(out) << "this." << make_valid_java_identifier(field->get_name()) << " = 0;" << endl; break; case t_base_type::TYPE_DOUBLE: indent(out) << "this." << make_valid_java_identifier(field->get_name()) << " = 0.0;" << endl; break; case t_base_type::TYPE_BOOL: indent(out) << "this." << make_valid_java_identifier(field->get_name()) << " = false;" << endl; break; default: throw "unsupported type: " + base_type->get_name() + " for field " + field->get_name(); } } indent_down(); indent(out) << "}" << endl << endl; } // generates java method to serialize (in the Java sense) the object void t_java_generator::generate_java_struct_write_object(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << "private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {" << endl; indent(out) << " try {" << endl; indent(out) << " write(new org.apache.thrift.protocol.TCompactProtocol(new " "org.apache.thrift.transport.TIOStreamTransport(out)));" << endl; indent(out) << " } catch (org.apache.thrift.TException te) {" << endl; indent(out) << " throw new java.io.IOException(te" << (android_legacy_ ? ".getMessage()" : "") << ");" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl << endl; } // generates java method to serialize (in the Java sense) the object void t_java_generator::generate_java_struct_read_object(ostream& out, t_struct* tstruct) { indent(out) << "private void readObject(java.io.ObjectInputStream in) throws " "java.io.IOException, java.lang.ClassNotFoundException {" << endl; indent(out) << " try {" << endl; if (!tstruct->is_union()) { switch (needs_isset(tstruct)) { case ISSET_NONE: break; case ISSET_PRIMITIVE: indent(out) << " // it doesn't seem like you should have to do this, but java " "serialization is wacky, and doesn't call the default constructor." << endl; indent(out) << " __isset_bitfield = 0;" << endl; break; case ISSET_BITSET: indent(out) << " // it doesn't seem like you should have to do this, but java " "serialization is wacky, and doesn't call the default constructor." << endl; indent(out) << " __isset_bit_vector = new java.util.BitSet(1);" << endl; break; } } indent(out) << " read(new org.apache.thrift.protocol.TCompactProtocol(new " "org.apache.thrift.transport.TIOStreamTransport(in)));" << endl; indent(out) << " } catch (org.apache.thrift.TException te) {" << endl; indent(out) << " throw new java.io.IOException(te" << (android_legacy_ ? ".getMessage()" : "") << ");" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl << endl; } void t_java_generator::generate_standard_reader(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "public void read(org.apache.thrift.protocol.TProtocol iprot, " << make_valid_java_identifier(tstruct->get_name()) << " struct) throws org.apache.thrift.TException {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Declare stack tmp variables and read struct header out << indent() << "org.apache.thrift.protocol.TField schemeField;" << endl << indent() << "iprot.readStructBegin();" << endl; // Loop over reading in fields indent(out) << "while (true)" << endl; scope_up(out); // Read beginning field marker indent(out) << "schemeField = iprot.readFieldBegin();" << endl; // Check for field STOP marker and break indent(out) << "if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { " << endl; indent_up(); indent(out) << "break;" << endl; indent_down(); indent(out) << "}" << endl; // Switch statement on the field we are reading indent(out) << "switch (schemeField.id) {" << endl; indent_up(); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << (*f_iter)->get_key() << ": // " << constant_name((*f_iter)->get_name()) << endl; indent_up(); indent(out) << "if (schemeField.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, "struct.", true); indent(out) << "struct." << "set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl; indent_down(); out << indent() << "} else { " << endl << indent() << " org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);" << endl << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);" << endl; indent_down(); indent(out) << "}" << endl; // Read field end marker indent(out) << "iprot.readFieldEnd();" << endl; indent_down(); indent(out) << "}" << endl; out << indent() << "iprot.readStructEnd();" << endl; // in non-beans style, check for required fields of primitive type // (which can be checked here but not in the general validate method) if (!bean_style_) { out << endl << indent() << "// check for required fields of primitive type, which can't be " "checked in the validate method" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) { out << indent() << "if (!struct." << generate_isset_check(*f_iter) << ") {" << endl << indent() << " throw new org.apache.thrift.protocol.TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not found in serialized data! Struct: \" + toString());" << endl << indent() << "}" << endl; } } } // performs various checks (e.g. check that all required fields are set) indent(out) << "struct.validate();" << endl; indent_down(); out << indent() << "}" << endl; } void t_java_generator::generate_standard_writer(ostream& out, t_struct* tstruct, bool is_result) { indent_up(); indent(out) << java_override_annotation() << endl; indent(out) << "public void write(org.apache.thrift.protocol.TProtocol oprot, " << make_valid_java_identifier(tstruct->get_name()) << " struct) throws org.apache.thrift.TException {" << endl; indent_up(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; // performs various checks (e.g. check that all required fields are set) indent(out) << "struct.validate();" << endl << endl; indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool null_allowed = type_can_be_null((*f_iter)->get_type()); if (null_allowed) { out << indent() << "if (struct." << make_valid_java_identifier((*f_iter)->get_name()) << " != null) {" << endl; indent_up(); } bool optional = ((*f_iter)->get_req() == t_field::T_OPTIONAL) || (is_result && !null_allowed); if (optional) { indent(out) << "if (" << "struct." << generate_isset_check((*f_iter)) << ") {" << endl; indent_up(); } indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "struct.", "", true); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; if (optional) { indent_down(); indent(out) << "}" << endl; } if (null_allowed) { indent_down(); indent(out) << "}" << endl; } } // Write the struct map out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();" << endl; indent_down(); out << indent() << "}" << endl << endl; indent_down(); } void t_java_generator::generate_java_struct_standard_scheme(ostream& out, t_struct* tstruct, bool is_result) { indent(out) << "private static class " << tstruct->get_name() << "StandardSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {" << endl; indent_up(); indent(out) << java_override_annotation() << endl; indent(out) << "public " << tstruct->get_name() << "StandardScheme getScheme() {" << endl; indent_up(); indent(out) << "return new " << tstruct->get_name() << "StandardScheme();" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl << endl; out << indent() << "private static class " << tstruct->get_name() << "StandardScheme extends org.apache.thrift.scheme.StandardScheme<" << make_valid_java_identifier(tstruct->get_name()) << "> {" << endl << endl; indent_up(); generate_standard_reader(out, tstruct); indent_down(); out << endl; generate_standard_writer(out, tstruct, is_result); out << indent() << "}" << endl << endl; } void t_java_generator::generate_java_struct_tuple_reader(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "public void read(org.apache.thrift.protocol.TProtocol prot, " << make_valid_java_identifier(tstruct->get_name()) << " struct) throws org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "org.apache.thrift.protocol.TTupleProtocol iprot = " "(org.apache.thrift.protocol.TTupleProtocol) prot;" << endl; int optional_count = 0; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) { optional_count++; } if ((*f_iter)->get_req() == t_field::T_REQUIRED) { generate_deserialize_field(out, (*f_iter), "struct.", false); indent(out) << "struct.set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl; } } if (optional_count > 0) { indent(out) << "java.util.BitSet incoming = iprot.readBitSet(" << optional_count << ");" << endl; int i = 0; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) { indent(out) << "if (incoming.get(" << i << ")) {" << endl; indent_up(); generate_deserialize_field(out, (*f_iter), "struct.", false); indent(out) << "struct.set" << get_cap_name((*f_iter)->get_name()) << get_cap_name("isSet") << "(true);" << endl; indent_down(); indent(out) << "}" << endl; i++; } } } indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_java_struct_tuple_writer(ostream& out, t_struct* tstruct) { indent(out) << java_override_annotation() << endl; indent(out) << "public void write(org.apache.thrift.protocol.TProtocol prot, " << make_valid_java_identifier(tstruct->get_name()) << " struct) throws org.apache.thrift.TException {" << endl; indent_up(); indent(out) << "org.apache.thrift.protocol.TTupleProtocol oprot = " "(org.apache.thrift.protocol.TTupleProtocol) prot;" << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool has_optional = false; int optional_count = 0; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) { optional_count++; has_optional = true; } if ((*f_iter)->get_req() == t_field::T_REQUIRED) { generate_serialize_field(out, (*f_iter), "struct.", "", false); } } if (has_optional) { indent(out) << "java.util.BitSet optionals = new java.util.BitSet();" << endl; int i = 0; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) { indent(out) << "if (struct." << generate_isset_check((*f_iter)) << ") {" << endl; indent_up(); indent(out) << "optionals.set(" << i << ");" << endl; indent_down(); indent(out) << "}" << endl; i++; } } indent(out) << "oprot.writeBitSet(optionals, " << optional_count << ");" << endl; int j = 0; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) { indent(out) << "if (struct." << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); generate_serialize_field(out, (*f_iter), "struct.", "", false); indent_down(); indent(out) << "}" << endl; j++; } } } indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_java_struct_tuple_scheme(ostream& out, t_struct* tstruct) { indent(out) << "private static class " << tstruct->get_name() << "TupleSchemeFactory implements org.apache.thrift.scheme.SchemeFactory {" << endl; indent_up(); indent(out) << java_override_annotation() << endl; indent(out) << "public " << tstruct->get_name() << "TupleScheme getScheme() {" << endl; indent_up(); indent(out) << "return new " << tstruct->get_name() << "TupleScheme();" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl << endl; out << indent() << "private static class " << tstruct->get_name() << "TupleScheme extends org.apache.thrift.scheme.TupleScheme<" << make_valid_java_identifier(tstruct->get_name()) << "> {" << endl << endl; indent_up(); generate_java_struct_tuple_writer(out, tstruct); out << endl; generate_java_struct_tuple_reader(out, tstruct); indent_down(); out << indent() << "}" << endl << endl; } void t_java_generator::generate_java_scheme_lookup(ostream& out) { indent(out) << "private static S scheme(" << "org.apache.thrift.protocol.TProtocol proto) {" << endl; indent_up(); indent(out) << "return (org.apache.thrift.scheme.StandardScheme.class.equals(proto.getScheme()) " << "? STANDARD_SCHEME_FACTORY " << ": TUPLE_SCHEME_FACTORY" << ").getScheme();" << endl; indent_down(); indent(out) << "}" << endl; } void t_java_generator::generate_javax_generated_annotation(ostream& out) { time_t seconds = time(nullptr); struct tm* now = localtime(&seconds); if (jakarta_annotations_) { indent(out) << "@jakarta.annotation.Generated(value = \"" << autogen_summary() << "\""; } else { indent(out) << "@javax.annotation.Generated(value = \"" << autogen_summary() << "\""; } if (undated_generated_annotations_) { out << ")" << endl; } else { indent(out) << ", date = \"" << (now->tm_year + 1900) << "-" << setfill('0') << setw(2) << (now->tm_mon + 1) << "-" << setfill('0') << setw(2) << now->tm_mday << "\")" << endl; } } std::string t_java_generator::display_name() const { return "Java"; } THRIFT_REGISTER_GENERATOR( java, "Java", " beans: Members will be private, and setter methods will return void.\n" " private_members: Members will be private, but setter methods will return 'this' like usual.\n" " private-members: Same as 'private_members' (deprecated).\n" " nocamel: Do not use CamelCase field accessors with beans.\n" " fullcamel: Convert underscored_accessor_or_service_names to camelCase.\n" " android: Generated structures are Parcelable.\n" " android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and above).\n" " option_type=[thrift|jdk8]:\n" " thrift: wrap optional fields in thrift Option type.\n" " jdk8: Wrap optional fields in JDK8+ Option type.\n" " If the Option type is not specified, 'thrift' is used.\n" " rethrow_unhandled_exceptions:\n" " Enable rethrow of unhandled exceptions and let them propagate further. (Default behavior is to catch and log it.)\n" " java5: Generate Java 1.5 compliant code (includes android_legacy flag).\n" " future_iface: Generate CompletableFuture based iface based on async client.\n" " reuse_objects: Data objects will not be allocated, but existing instances will be used (read and write).\n" " reuse-objects: Same as 'reuse_objects' (deprecated).\n" " sorted_containers:\n" " Use TreeSet/TreeMap instead of HashSet/HashMap as a implementation of set/map.\n" " generated_annotations=[undated|suppress]:\n" " undated: suppress the date at @Generated annotations\n" " suppress: suppress @Generated annotations entirely\n" " unsafe_binaries: Do not copy ByteBuffers in constructors, getters, and setters.\n" " jakarta_annotations: generate jakarta annotations (javax by default)\n" " annotations_as_metadata:\n" " Include Thrift field annotations as metadata in the generated code.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_cl_generator.cc0000644000000000000000000004234714370300523024661 0ustar00rootroot00000000000000/* * Copyright (c) 2008- Patrick Collison * Copyright (c) 2006- Facebook * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "t_oop_generator.h" using namespace std; /** * Common Lisp code generator. * * @author Patrick Collison */ class t_cl_generator : public t_oop_generator { public: t_cl_generator( t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { no_asd = false; system_prefix = "thrift-gen-"; std::map::const_iterator iter; for(iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if(iter->first.compare("no_asd") == 0) { no_asd = true; } else if (iter->first.compare("sys_pref") == 0) { system_prefix = iter->second; } else { throw "unknown option cl:" + iter->first; } } out_dir_base_ = "gen-cl"; copy_options_ = option_string; } void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_typedef (t_typedef* ttypedef) override; void generate_enum (t_enum* tenum) override; void generate_const (t_const* tconst) override; void generate_struct (t_struct* tstruct) override; void generate_xception (t_struct* txception) override; void generate_service (t_service* tservice) override; void generate_cl_struct (std::ostream& out, t_struct* tstruct, bool is_exception); void generate_cl_struct_internal (std::ostream& out, t_struct* tstruct, bool is_exception); void generate_exception_sig(std::ostream& out, t_function* f); std::string render_const_value(t_type* type, t_const_value* value); std::string cl_autogen_comment(); void asdf_def(std::ostream &out); void package_def(std::ostream &out); void package_in(std::ostream &out); std::string generated_package(); std::string prefix(std::string name); std::string package_of(t_program* program); std::string package(); std::string render_includes(); std::string type_name(t_type* ttype); std::string typespec (t_type *t); std::string function_signature(t_function* tfunction); std::string argument_list(t_struct* tstruct); std::string cl_docstring(std::string raw); private: int temporary_var; /** * Isolate the variable definitions, as they can require structure definitions */ ofstream_with_content_based_conditional_update f_asd_; ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_vars_; std::string copy_options_; bool no_asd; std::string system_prefix; }; void t_cl_generator::init_generator() { MKDIR(get_out_dir().c_str()); string program_dir = get_out_dir() + "/" + program_name_; MKDIR(program_dir.c_str()); temporary_var = 0; string f_types_name = program_dir + "/" + program_name_ + "-types.lisp"; string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp"; f_types_.open(f_types_name); f_types_ << cl_autogen_comment() << endl; f_vars_.open(f_vars_name); f_vars_ << cl_autogen_comment() << endl; package_def(f_types_); package_in(f_types_); package_in(f_vars_); if (!no_asd) { string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd"; f_asd_.open(f_asd_name); f_asd_ << cl_autogen_comment() << endl; asdf_def(f_asd_); } } /** * Renders all the imports necessary for including another Thrift program */ string t_cl_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; result += ":depends-on (:thrift"; for (auto include : includes) { result += " :" + system_prefix + underscore(include->get_name()); } result += ")\n"; return result; } string t_cl_generator::package_of(t_program* program) { string prefix = program->get_namespace("cl"); return prefix.empty() ? "thrift-generated" : prefix; } string t_cl_generator::package() { return package_of(program_); } string t_cl_generator::prefix(string symbol) { return "\"" + symbol + "\""; } string t_cl_generator::cl_autogen_comment() { return std::string(";;; ") + "Autogenerated by Thrift\n" + ";;; DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + ";;; options string: " + copy_options_ + "\n"; } string t_cl_generator::cl_docstring(string raw) { replace(raw.begin(), raw.end(), '"', '\''); return raw; } void t_cl_generator::close_generator() { f_asd_.close(); f_types_.close(); f_vars_.close(); } string t_cl_generator::generated_package() { return program_->get_namespace("cpp"); } void t_cl_generator::asdf_def(std::ostream &out) { out << "(asdf:defsystem #:" << system_prefix << program_name_ << endl; indent_up(); out << indent() << render_includes() << indent() << ":serial t" << endl << indent() << ":components (" << "(:file \"" << program_name_ << "-types\") " << "(:file \"" << program_name_ << "-vars\")))" << endl; indent_down(); } /*** * Generate a package definition. Add use references equivalent to the idl file's include statements. */ void t_cl_generator::package_def(std::ostream &out) { const vector& includes = program_->get_includes(); out << "(thrift:def-package :" << package(); if ( includes.size() > 0 ) { out << " :use ("; for (auto include : includes) { out << " :" << include->get_name(); } out << ")"; } out << ")" << endl << endl; } void t_cl_generator::package_in(std::ostream &out) { out << "(cl:in-package :" << package() << ")" << endl << endl; } /** * Generates a typedef. This is not done in Common Lisp, types are all implicit. * * @param ttypedef The type definition */ void t_cl_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } void t_cl_generator::generate_enum(t_enum* tenum) { f_types_ << "(thrift:def-enum " << prefix(tenum->get_name()) << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; int value = -1; indent_up(); f_types_ << indent() << "("; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { value = (*c_iter)->get_value(); if(c_iter != constants.begin()) f_types_ << endl << indent() << " "; f_types_ << "(\"" << (*c_iter)->get_name() << "\" . " << value << ")"; } indent_down(); f_types_ << "))" << endl << endl; } /** * Generate a constant value */ void t_cl_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); f_vars_ << "(thrift:def-constant " << prefix(name) << " " << render_const_value(type, value) << ")" << endl << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_cl_generator::render_const_value(t_type* type, t_const_value* value) { type = get_true_type(type); std::ostringstream out; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << "\"" << value->get_string() << "\""; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "t" : "nil"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << (type->is_struct() ? "(make-instance '" : "(make-exception '") << lowercase(type->get_name()) << " " << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } out << indent() << ":" << v_iter->first->get_string() << " " << render_const_value(field_type, v_iter->second) << endl; } out << indent() << ")"; indent_down(); } else if (type->is_map()) { // emit an hash form with both keys and values to be evaluated t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); out << "(thrift:map "; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << endl << indent() << "(cl:cons " << render_const_value(ktype, v_iter->first) << " " << render_const_value(vtype, v_iter->second) << ")"; } indent_down(); out << indent() << ")"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } if (type->is_set()) { out << "(thrift:set" << endl; } else { out << "(thrift:list" << endl; } indent_up(); indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << render_const_value(etype, *v_iter) << endl; } out << indent() << ")"; indent_down(); indent_down(); } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out.str(); } void t_cl_generator::generate_struct(t_struct* tstruct) { generate_cl_struct(f_types_, tstruct, false); } void t_cl_generator::generate_xception(t_struct* txception) { generate_cl_struct(f_types_, txception, true); } void t_cl_generator::generate_cl_struct_internal(std::ostream& out, t_struct* tstruct, bool is_exception) { (void)is_exception; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; out << "("; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_const_value* value = (*m_iter)->get_value(); t_type* type = (*m_iter)->get_type(); if (m_iter != members.begin()) { out << endl << indent() << " "; } out << "(" << prefix((*m_iter)->get_name()) << " " << ( (nullptr != value) ? render_const_value(type, value) : "nil" ) << " :id " << (*m_iter)->get_key(); if ( type->is_base_type() && "string" == typespec(type) ) if ( ((t_base_type*)type)->is_binary() ) out << " :type binary"; else out << " :type string"; else out << " :type " << typespec(type); if ( (*m_iter)->get_req() == t_field::T_OPTIONAL ) { out << " :optional t"; } if ( (*m_iter)->has_doc()) { out << " :documentation \"" << cl_docstring((*m_iter)->get_doc()) << "\""; } out <<")"; } out << ")"; } void t_cl_generator::generate_cl_struct(std::ostream& out, t_struct* tstruct, bool is_exception = false) { std::string name = type_name(tstruct); out << (is_exception ? "(thrift:def-exception " : "(thrift:def-struct ") << prefix(name) << endl; indent_up(); if ( tstruct->has_doc() ) { out << indent() ; out << "\"" << cl_docstring(tstruct->get_doc()) << "\"" << endl; } out << indent() ; generate_cl_struct_internal(out, tstruct, is_exception); indent_down(); out << ")" << endl << endl; } void t_cl_generator::generate_exception_sig(std::ostream& out, t_function* f) { generate_cl_struct_internal(out, f->get_xceptions(), true); } void t_cl_generator::generate_service(t_service* tservice) { string extends_client; vector functions = tservice->get_functions(); vector::iterator f_iter; if (tservice->get_extends() != nullptr) { extends_client = type_name(tservice->get_extends()); } extends_client = extends_client.empty() ? "nil" : prefix(extends_client); f_types_ << "(thrift:def-service " << prefix(service_name_) << " " << extends_client; indent_up(); if ( tservice->has_doc()) { f_types_ << endl << indent() << "(:documentation \"" << cl_docstring(tservice->get_doc()) << "\")"; } for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_function* function = *f_iter; string fname = function->get_name(); string signature = function_signature(function); t_struct* exceptions = function->get_xceptions(); const vector& xmembers = exceptions->get_members(); f_types_ << endl << indent() << "(:method " << prefix(fname); f_types_ << " (" << signature << " " << typespec((*f_iter)->get_returntype()) << ")"; if (xmembers.size() > 0) { f_types_ << endl << indent() << " :exceptions " ; generate_exception_sig(f_types_, function); } if ( (*f_iter)->is_oneway() ) { f_types_ << endl << indent() << " :oneway t"; } if ( (*f_iter)->has_doc() ) { f_types_ << endl << indent() << " :documentation \"" << cl_docstring((*f_iter)->get_doc()) << "\""; } f_types_ << ")"; } f_types_ << ")" << endl << endl; indent_down(); } string t_cl_generator::typespec(t_type *t) { t = get_true_type(t); if (t -> is_binary()){ return "binary"; } else if (t->is_base_type()) { return type_name(t); } else if (t->is_map()) { t_map *m = (t_map*) t; return "(thrift:map " + typespec(m->get_key_type()) + " " + typespec(m->get_val_type()) + ")"; } else if (t->is_struct() || t->is_xception()) { return "(struct " + prefix(type_name(t)) + ")"; } else if (t->is_list()) { return "(thrift:list " + typespec(((t_list*) t)->get_elem_type()) + ")"; } else if (t->is_set()) { return "(thrift:set " + typespec(((t_set*) t)->get_elem_type()) + ")"; } else if (t->is_enum()) { return "(enum \"" + ((t_enum*) t)->get_name() + "\")"; } else { throw "Sorry, I don't know how to generate this: " + type_name(t); } } string t_cl_generator::function_signature(t_function* tfunction) { return argument_list(tfunction->get_arglist()); } string t_cl_generator::argument_list(t_struct* tstruct) { stringstream res; res << "("; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { res << " "; } res << "(" + prefix((*f_iter)->get_name()) << " " << typespec((*f_iter)->get_type()) << " " << (*f_iter)->get_key() << ")"; } res << ")"; return res.str(); } string t_cl_generator::type_name(t_type* ttype) { string prefix = ""; t_program* program = ttype->get_program(); if (program != nullptr && program != program_) prefix = package_of(program) == package() ? "" : package_of(program) + ":"; string name = ttype->get_name(); if (ttype->is_struct() || ttype->is_xception()) name = lowercase(ttype->get_name()); return prefix + name; } std::string t_cl_generator::display_name() const { return "Common Lisp"; } THRIFT_REGISTER_GENERATOR( cl, "Common Lisp", " no_asd: Do not define ASDF systems for each generated Thrift program.\n" " sys_pref= The prefix to give ASDF system names. Default: thrift-gen-\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_st_generator.cc0000644000000000000000000010033714370300523024703 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ofstream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * Smalltalk code generator. * */ class t_st_generator : public t_oop_generator { public: t_st_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; temporary_var = 0; std::map::const_iterator iter; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option st:" + iter->first; } out_dir_base_ = "gen-st"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void generate_class_side_definition(); void generate_force_consts(); std::string render_const_value(t_type* type, t_const_value* value); /** * Struct generation code */ void generate_st_struct(std::ostream& out, t_struct* tstruct, bool is_exception); void generate_accessors(std::ostream& out, t_struct* tstruct); /** * Service-level generation functions */ void generate_service_client(t_service* tservice); void generate_send_method(t_function* tfunction); void generate_recv_method(t_function* tfunction); std::string map_reader(t_map* tmap); std::string list_reader(t_list* tlist); std::string set_reader(t_set* tset); std::string struct_reader(t_struct* tstruct, std::string clsName); std::string map_writer(t_map* tmap, std::string name); std::string list_writer(t_list* tlist, std::string name); std::string set_writer(t_set* tset, std::string name); std::string struct_writer(t_struct* tstruct, std::string fname); std::string write_val(t_type* t, std::string fname); std::string read_val(t_type* t); /** * Helper rendering functions */ std::string st_autogen_comment(); void st_class_def(std::ostream& out, std::string name); void st_method(std::ostream& out, std::string cls, std::string name); void st_method(std::ostream& out, std::string cls, std::string name, std::string category); void st_close_method(std::ostream& out); void st_class_method(std::ostream& out, std::string cls, std::string name); void st_class_method(std::ostream& out, std::string cls, std::string name, std::string category); void st_setter(std::ostream& out, std::string cls, std::string name, std::string type); void st_getter(std::ostream& out, std::string cls, std::string name); void st_accessors(std::ostream& out, std::string cls, std::string name, std::string type); std::string class_name(); static bool is_valid_namespace(const std::string& sub_namespace); std::string client_class_name(); std::string prefix(std::string name); std::string declare_field(t_field* tfield); std::string type_name(t_type* ttype); std::string function_signature(t_function* tfunction); std::string argument_list(t_struct* tstruct); std::string function_types_comment(t_function* fn); std::string type_to_enum(t_type* ttype); std::string a_type(t_type* type); bool is_vowel(char c); std::string temp_name(); std::string generated_category(); private: /** * File streams */ int temporary_var; ofstream_with_content_based_conditional_update f_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_st_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); temporary_var = 0; // Make output file string f_name = get_out_dir() + "/" + program_name_ + ".st"; f_.open(f_name.c_str()); // Print header f_ << st_autogen_comment() << endl; st_class_def(f_, program_name_); generate_class_side_definition(); // Generate enums vector enums = program_->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { generate_enum(*en_iter); } } string t_st_generator::class_name() { return capitalize(program_name_); } bool t_st_generator::is_valid_namespace(const std::string& sub_namespace) { return sub_namespace == "prefix" || sub_namespace == "category"; } string t_st_generator::prefix(string class_name) { string prefix = program_->get_namespace("smalltalk.prefix"); string name = capitalize(class_name); name = prefix.empty() ? name : (prefix + name); return name; } string t_st_generator::client_class_name() { return capitalize(service_name_) + "Client"; } /** * Autogen'd comment */ string t_st_generator::st_autogen_comment() { return std::string("'") + "Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "\n" + "DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "'!\n"; } void t_st_generator::generate_force_consts() { f_ << prefix(class_name()) << " enums keysAndValuesDo: [:k :v | " << prefix(class_name()) << " enums at: k put: v value].!" << endl; f_ << prefix(class_name()) << " constants keysAndValuesDo: [:k :v | " << prefix(class_name()) << " constants at: k put: v value].!" << endl; } void t_st_generator::close_generator() { generate_force_consts(); f_.close(); } string t_st_generator::generated_category() { string cat = program_->get_namespace("smalltalk.category"); // For compatibility with the Thrift grammar, the category must // be punctuated by dots. Replaces them with dashes here. for (char & iter : cat) { if (iter == '.') { iter = '-'; } } return cat.size() ? cat : "Generated-" + class_name(); } /** * Generates a typedef. This is not done in Smalltalk, types are all implicit. * * @param ttypedef The type definition */ void t_st_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } void t_st_generator::st_class_def(std::ostream& out, string name) { out << "Object subclass: #" << prefix(name) << endl; indent_up(); out << indent() << "instanceVariableNames: ''" << endl << indent() << "classVariableNames: ''" << endl << indent() << "poolDictionaries: ''" << endl << indent() << "category: '" << generated_category() << "'!" << endl << endl; } void t_st_generator::st_method(std::ostream& out, string cls, string name) { st_method(out, cls, name, "as yet uncategorized"); } void t_st_generator::st_class_method(std::ostream& out, string cls, string name) { st_method(out, cls + " class", name); } void t_st_generator::st_class_method(std::ostream& out, string cls, string name, string category) { st_method(out, cls, name, category); } void t_st_generator::st_method(std::ostream& out, string cls, string name, string category) { char timestr[50]; time_t rawtime; struct tm* tinfo; time(&rawtime); tinfo = localtime(&rawtime); strftime(timestr, 50, "%m/%d/%Y %H:%M", tinfo); out << "!" << prefix(cls) << " methodsFor: '" + category + "' stamp: 'thrift " << timestr << "'!\n" << name << endl; indent_up(); out << indent(); } void t_st_generator::st_close_method(std::ostream& out) { out << "! !" << endl << endl; indent_down(); } void t_st_generator::st_setter(std::ostream& out, string cls, string name, string type = "anObject") { st_method(out, cls, name + ": " + type); out << name << " := " + type; st_close_method(out); } void t_st_generator::st_getter(std::ostream& out, string cls, string name) { st_method(out, cls, name + ""); out << "^ " << name; st_close_method(out); } void t_st_generator::st_accessors(std::ostream& out, string cls, string name, string type = "anObject") { st_setter(out, cls, name, type); st_getter(out, cls, name); } void t_st_generator::generate_class_side_definition() { f_ << prefix(class_name()) << " class" << endl << "\tinstanceVariableNames: 'constants enums'!" << endl << endl; st_accessors(f_, class_name() + " class", "enums"); st_accessors(f_, class_name() + " class", "constants"); f_ << prefix(class_name()) << " enums: Dictionary new!" << endl; f_ << prefix(class_name()) << " constants: Dictionary new!" << endl; f_ << endl; } /** * Generates code for an enumerated type. Done using a class to scope * the values. * * @param tenum The enumeration */ void t_st_generator::generate_enum(t_enum* tenum) { string cls_name = program_name_ + capitalize(tenum->get_name()); f_ << prefix(class_name()) << " enums at: '" << tenum->get_name() << "' put: [" << "(Dictionary new " << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); f_ << "\tat: '" << (*c_iter)->get_name() << "' put: " << value << ";" << endl; } f_ << "\tyourself)]!" << endl << endl; } /** * Generate a constant value */ void t_st_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); f_ << prefix(class_name()) << " constants at: '" << name << "' put: [" << render_const_value(type, value) << "]!" << endl << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_st_generator::render_const_value(t_type* type, t_const_value* value) { type = get_true_type(type); std::ostringstream out; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << "(" << capitalize(type->get_name()) << " new " << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } out << indent() << v_iter->first->get_string() << ": " << render_const_value(field_type, v_iter->second) << ";" << endl; } out << indent() << "yourself)"; indent_down(); } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); out << "(Dictionary new" << endl; indent_up(); indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << indent(); out << "at: " << render_const_value(ktype, v_iter->first); out << " put: "; out << render_const_value(vtype, v_iter->second); out << ";" << endl; } out << indent() << indent() << "yourself)"; indent_down(); indent_down(); } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } if (type->is_set()) { out << "(Set new" << endl; } else { out << "(OrderedCollection new" << endl; } indent_up(); indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << indent(); out << "add: " << render_const_value(etype, *v_iter); out << ";" << endl; } out << indent() << indent() << "yourself)"; indent_down(); indent_down(); } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out.str(); } /** * Generates a Smalltalk struct */ void t_st_generator::generate_struct(t_struct* tstruct) { generate_st_struct(f_, tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_st_generator::generate_xception(t_struct* txception) { generate_st_struct(f_, txception, true); } /** * Generates a smalltalk class to represent a struct */ void t_st_generator::generate_st_struct(std::ostream& out, t_struct* tstruct, bool is_exception = false) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; if (is_exception) out << "Error"; else out << "Object"; out << " subclass: #" << prefix(type_name(tstruct)) << endl << "\tinstanceVariableNames: '"; if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (m_iter != members.begin()) out << " "; out << camelcase((*m_iter)->get_name()); } } out << "'\n" << "\tclassVariableNames: ''\n" << "\tpoolDictionaries: ''\n" << "\tcategory: '" << generated_category() << "'!\n\n"; generate_accessors(out, tstruct); } bool t_st_generator::is_vowel(char c) { switch (tolower(c)) { case 'a': case 'e': case 'i': case 'o': case 'u': return true; } return false; } string t_st_generator::a_type(t_type* type) { string prefix; if (is_vowel(type_name(type)[0])) prefix = "an"; else prefix = "a"; return prefix + capitalize(type_name(type)); } void t_st_generator::generate_accessors(std::ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; string type; string prefix; if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { st_accessors(out, capitalize(type_name(tstruct)), camelcase((*m_iter)->get_name()), a_type((*m_iter)->get_type())); } out << endl; } } /** * Generates a thrift service. * * @param tservice The service definition */ void t_st_generator::generate_service(t_service* tservice) { generate_service_client(tservice); // generate_service_server(tservice); } string t_st_generator::temp_name() { std::ostringstream out; out << "temp" << temporary_var++; return out.str(); } string t_st_generator::map_writer(t_map* tmap, string fname) { std::ostringstream out; string key = temp_name(); string val = temp_name(); out << "[oprot writeMapBegin: (TMap new keyType: " << type_to_enum(tmap->get_key_type()) << "; valueType: " << type_to_enum(tmap->get_val_type()) << "; size: " << fname << " size)." << endl; indent_up(); out << indent() << fname << " keysAndValuesDo: [:" << key << " :" << val << " |" << endl; indent_up(); out << indent() << write_val(tmap->get_key_type(), key) << "." << endl << indent() << write_val(tmap->get_val_type(), val); indent_down(); out << "]." << endl << indent() << "oprot writeMapEnd] value"; indent_down(); return out.str(); } string t_st_generator::map_reader(t_map* tmap) { std::ostringstream out; string desc = temp_name(); string val = temp_name(); out << "[|" << desc << " " << val << "| " << endl; indent_up(); out << indent() << desc << " := iprot readMapBegin." << endl << indent() << val << " := Dictionary new." << endl << indent() << desc << " size timesRepeat: [" << endl; indent_up(); out << indent() << val << " at: " << read_val(tmap->get_key_type()) << " put: " << read_val(tmap->get_val_type()); indent_down(); out << "]." << endl << indent() << "iprot readMapEnd." << endl << indent() << val << "] value"; indent_down(); return out.str(); } string t_st_generator::list_writer(t_list* tlist, string fname) { std::ostringstream out; string val = temp_name(); out << "[oprot writeListBegin: (TList new elemType: " << type_to_enum(tlist->get_elem_type()) << "; size: " << fname << " size)." << endl; indent_up(); out << indent() << fname << " do: [:" << val << "|" << endl; indent_up(); out << indent() << write_val(tlist->get_elem_type(), val) << endl; indent_down(); out << "]." << endl << indent() << "oprot writeListEnd] value"; indent_down(); return out.str(); } string t_st_generator::list_reader(t_list* tlist) { std::ostringstream out; string desc = temp_name(); string val = temp_name(); out << "[|" << desc << " " << val << "| " << desc << " := iprot readListBegin." << endl; indent_up(); out << indent() << val << " := OrderedCollection new." << endl << indent() << desc << " size timesRepeat: [" << endl; indent_up(); out << indent() << val << " add: " << read_val(tlist->get_elem_type()); indent_down(); out << "]." << endl << indent() << "iprot readListEnd." << endl << indent() << val << "] value"; indent_down(); return out.str(); } string t_st_generator::set_writer(t_set* tset, string fname) { std::ostringstream out; string val = temp_name(); out << "[oprot writeSetBegin: (TSet new elemType: " << type_to_enum(tset->get_elem_type()) << "; size: " << fname << " size)." << endl; indent_up(); out << indent() << fname << " do: [:" << val << "|" << endl; indent_up(); out << indent() << write_val(tset->get_elem_type(), val) << endl; indent_down(); out << "]." << endl << indent() << "oprot writeSetEnd] value"; indent_down(); return out.str(); } string t_st_generator::set_reader(t_set* tset) { std::ostringstream out; string desc = temp_name(); string val = temp_name(); out << "[|" << desc << " " << val << "| " << desc << " := iprot readSetBegin." << endl; indent_up(); out << indent() << val << " := Set new." << endl << indent() << desc << " size timesRepeat: [" << endl; indent_up(); out << indent() << val << " add: " << read_val(tset->get_elem_type()); indent_down(); out << "]." << endl << indent() << "iprot readSetEnd." << endl << indent() << val << "] value"; indent_down(); return out.str(); } string t_st_generator::struct_writer(t_struct* tstruct, string sname) { std::ostringstream out; const vector& fields = tstruct->get_sorted_members(); vector::const_iterator fld_iter; out << "[oprot writeStructBegin: " << "(TStruct new name: '" + tstruct->get_name() + "')." << endl; indent_up(); for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { bool optional = (*fld_iter)->get_req() == t_field::T_OPTIONAL; string fname = camelcase((*fld_iter)->get_name()); string accessor = sname + " " + camelcase(fname); if (optional) { out << indent() << accessor << " ifNotNil: [" << endl; indent_up(); } out << indent() << "oprot writeFieldBegin: (TField new name: '" << fname << "'; type: " << type_to_enum((*fld_iter)->get_type()) << "; id: " << (*fld_iter)->get_key() << ")." << endl; out << indent() << write_val((*fld_iter)->get_type(), accessor) << "." << endl << indent() << "oprot writeFieldEnd"; if (optional) { out << "]"; indent_down(); } out << "." << endl; } out << indent() << "oprot writeFieldStop; writeStructEnd] value"; indent_down(); return out.str(); } string t_st_generator::struct_reader(t_struct* tstruct, string clsName = "") { std::ostringstream out; const vector& fields = tstruct->get_members(); vector::const_iterator fld_iter; string val = temp_name(); string desc = temp_name(); string found = temp_name(); if (clsName.size() == 0) { clsName = tstruct->get_name(); } out << "[|" << desc << " " << val << "|" << endl; indent_up(); // This is nasty, but without it we'll break things by prefixing TResult. string name = ((capitalize(clsName) == "TResult") ? capitalize(clsName) : prefix(clsName)); out << indent() << val << " := " << name << " new." << endl; out << indent() << "iprot readStructBegin." << endl << indent() << "[" << desc << " := iprot readFieldBegin." << endl << indent() << desc << " type = TType stop] whileFalse: [|" << found << "|" << endl; indent_up(); for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { out << indent() << desc << " id = " << (*fld_iter)->get_key() << " ifTrue: [" << endl; indent_up(); out << indent() << found << " := true." << endl << indent() << val << " " << camelcase((*fld_iter)->get_name()) << ": " << read_val((*fld_iter)->get_type()); indent_down(); out << "]." << endl; } out << indent() << found << " ifNil: [iprot skip: " << desc << " type]]." << endl; indent_down(); out << indent() << "oprot readStructEnd." << endl << indent() << val << "] value"; indent_down(); return out.str(); } string t_st_generator::write_val(t_type* t, string fname) { t = get_true_type(t); if (t->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)t)->get_base(); switch (tbase) { case t_base_type::TYPE_DOUBLE: return "iprot writeDouble: " + fname + " asFloat"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "iprot write" + capitalize(type_name(t)) + ": " + fname + " asInteger"; default: return "iprot write" + capitalize(type_name(t)) + ": " + fname; } } else if (t->is_map()) { return map_writer((t_map*)t, fname); } else if (t->is_struct() || t->is_xception()) { return struct_writer((t_struct*)t, fname); } else if (t->is_list()) { return list_writer((t_list*)t, fname); } else if (t->is_set()) { return set_writer((t_set*)t, fname); } else if (t->is_enum()) { return "iprot writeI32: " + fname; } else { throw "Sorry, I don't know how to write this: " + type_name(t); } } string t_st_generator::read_val(t_type* t) { t = get_true_type(t); if (t->is_base_type()) { return "iprot read" + capitalize(type_name(t)); } else if (t->is_map()) { return map_reader((t_map*)t); } else if (t->is_struct() || t->is_xception()) { return struct_reader((t_struct*)t); } else if (t->is_list()) { return list_reader((t_list*)t); } else if (t->is_set()) { return set_reader((t_set*)t); } else if (t->is_enum()) { return "iprot readI32"; } else { throw "Sorry, I don't know how to read this: " + type_name(t); } } void t_st_generator::generate_send_method(t_function* function) { string funname = function->get_name(); string signature = function_signature(function); t_struct* arg_struct = function->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; st_method(f_, client_class_name(), "send" + capitalize(signature)); f_ << "oprot writeMessageBegin:" << endl; indent_up(); f_ << indent() << "(TCallMessage new" << endl; indent_up(); f_ << indent() << "name: '" << funname << "'; " << endl << indent() << "seqid: self nextSeqid)." << endl; indent_down(); indent_down(); f_ << indent() << "oprot writeStructBegin: " << "(TStruct new name: '" + capitalize(camelcase(funname)) + "_args')." << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { string fname = camelcase((*fld_iter)->get_name()); f_ << indent() << "oprot writeFieldBegin: (TField new name: '" << fname << "'; type: " << type_to_enum((*fld_iter)->get_type()) << "; id: " << (*fld_iter)->get_key() << ")." << endl; f_ << indent() << write_val((*fld_iter)->get_type(), fname) << "." << endl << indent() << "oprot writeFieldEnd." << endl; } f_ << indent() << "oprot writeFieldStop; writeStructEnd; writeMessageEnd." << endl; f_ << indent() << "oprot transport flush"; st_close_method(f_); } // We only support receiving TResult structures (so this won't work on the server side) void t_st_generator::generate_recv_method(t_function* function) { string funname = camelcase(function->get_name()); string signature = function_signature(function); t_struct result(program_, "TResult"); t_field success(function->get_returntype(), "success", 0); result.append(&success); t_struct* xs = function->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { // duplicate the field, but call it "exception"... we don't need a dynamic name t_field* exception = new t_field((*f_iter)->get_type(), "exception", (*f_iter)->get_key()); result.append(exception); } st_method(f_, client_class_name(), "recv" + capitalize(funname)); f_ << "| f msg res | " << endl << indent() << "msg := oprot readMessageBegin." << endl << indent() << "self validateRemoteMessage: msg." << endl << indent() << "res := " << struct_reader(&result) << "." << endl << indent() << "oprot readMessageEnd." << endl << indent() << "oprot transport flush." << endl << indent() << "res exception ifNotNil: [res exception signal]." << endl << indent() << "^ res"; st_close_method(f_); } string t_st_generator::function_types_comment(t_function* fn) { std::ostringstream out; const vector& fields = fn->get_arglist()->get_members(); vector::const_iterator f_iter; out << "\""; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << camelcase((*f_iter)->get_name()) << ": " << type_name((*f_iter)->get_type()); if ((f_iter + 1) != fields.end()) { out << ", "; } } out << "\""; return out.str(); } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_st_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = "TClient"; vector functions = tservice->get_functions(); vector::iterator f_iter; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_client = extends + "Client"; } f_ << extends_client << " subclass: #" << prefix(client_class_name()) << endl << "\tinstanceVariableNames: ''\n" << "\tclassVariableNames: ''\n" << "\tpoolDictionaries: ''\n" << "\tcategory: '" << generated_category() << "'!\n\n"; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = camelcase((*f_iter)->get_name()); string signature = function_signature(*f_iter); st_method(f_, client_class_name(), signature); f_ << function_types_comment(*f_iter) << endl << indent() << "self send" << capitalize(signature) << "." << endl; if (!(*f_iter)->is_oneway()) { f_ << indent() << "^ self recv" << capitalize(funname) << " success " << endl; } st_close_method(f_); generate_send_method(*f_iter); if (!(*f_iter)->is_oneway()) { generate_recv_method(*f_iter); } } } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_st_generator::function_signature(t_function* tfunction) { return camelcase(tfunction->get_name()) + capitalize(argument_list(tfunction->get_arglist())); } /** * Renders a field list */ string t_st_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += " "; } string name = camelcase((*f_iter)->get_name()); result += name + ": " + name; } return result; } string t_st_generator::type_name(t_type* ttype) { string prefix = ""; t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { if (!ttype->is_service()) { prefix = program->get_name() + "_types."; } } string name = ttype->get_name(); if (ttype->is_struct() || ttype->is_xception()) { name = capitalize(ttype->get_name()); } return prefix + name; } /* Convert t_type to Smalltalk type code */ string t_st_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType string"; case t_base_type::TYPE_BOOL: return "TType bool"; case t_base_type::TYPE_I8: return "TType byte"; case t_base_type::TYPE_I16: return "TType i16"; case t_base_type::TYPE_I32: return "TType i32"; case t_base_type::TYPE_I64: return "TType i64"; case t_base_type::TYPE_DOUBLE: return "TType double"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "TType i32"; } else if (type->is_struct() || type->is_xception()) { return "TType struct"; } else if (type->is_map()) { return "TType map"; } else if (type->is_set()) { return "TType set"; } else if (type->is_list()) { return "TType list"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_st_generator::display_name() const { return "Smalltalk"; } THRIFT_REGISTER_GENERATOR(st, "Smalltalk", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_markdown_generator.cc0000644000000000000000000010056614370300523026103 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostringstream; using std::pair; using std::string; using std::stringstream; using std::vector; static const char endl = '\n'; // avoid ostream << std::endl flushes /** * MARKDOWN code generator * * mostly copy/pasting/tweaking from t_html_generator's work. */ class t_markdown_generator : public t_generator { enum input_type { INPUT_UNKNOWN, INPUT_UTF8, INPUT_PLAIN }; public: t_markdown_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; unsafe_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("noescape") == 0) { unsafe_ = true; } else if( iter->first.compare("suffix") == 0 && !iter->second.empty()) { extension_ = "." + iter->second; } else { throw "unknown option markdown:" + iter->first; } } out_dir_base_ = "gen-markdown"; input_type_ = INPUT_UNKNOWN; escape_.clear(); escape_['&'] = "&"; escape_['<'] = "<"; escape_['>'] = ">"; escape_['"'] = """; escape_['\''] = "'"; init_allowed__markup(); } std::string display_name() const override; void generate_program() override; void generate_program_toc(); void generate_program_toc_row(t_program* tprog); void generate_program_toc_rows(t_program* tprog, std::vector& finished); void generate_index(); std::string escape_html(std::string const& str); std::string escape_html_tags(std::string const& str); std::string make_file_link(std::string name); std::string make_file_name(std::string name); bool is_utf8_sequence(std::string const& str, size_t firstpos); void detect_input_encoding(std::string const& str, size_t firstpos); void init_allowed__markup(); /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_service(t_service* tservice) override; void generate_xception(t_struct* txception) override; void print_doc(t_doc* tdoc); int print_type(t_type* ttype); void print_const_value(t_type* type, t_const_value* tvalue); void print_fn_args_doc(t_function* tfunction); std::string str_to_id(const std::string& s); private: ofstream_with_content_based_conditional_update f_out_; std::string current_file_; input_type input_type_; std::map allowed_markup; bool unsafe_; std::string extension_; }; /** * string to markdown-id link reference */ std::string t_markdown_generator::str_to_id(const std::string& s) { std::string id; for(auto chr=s.begin();chr<=s.end(); ++chr) { if(*chr == '.' || *chr == 0) continue; id += tolower(*chr); } return id; } /** * Emits the Table of Contents links at the top of the module's page */ void t_markdown_generator::generate_program_toc() { f_out_ << "| Module | Services & Functions | Data types | Constants |" << endl << "| --- | --- | --- | --- |" << endl; generate_program_toc_row(program_); f_out_ << endl; } /** * Recurses through from the provided program and generates a ToC row * for each discovered program exactly once by maintaining the list of * completed rows in 'finished' */ void t_markdown_generator::generate_program_toc_rows(t_program* tprog, std::vector& finished) { for (auto & iter : finished) { if (tprog->get_path() == iter->get_path()) { return; } } finished.push_back(tprog); generate_program_toc_row(tprog); vector includes = tprog->get_includes(); for (auto & include : includes) { generate_program_toc_rows(include, finished); } } /** * Emits the Table of Contents links at the top of the module's page */ void t_markdown_generator::generate_program_toc_row(t_program* tprog) { // "| Module | Services | Data types | Constants | vector> filling; string fname = make_file_name(tprog->get_name()); filling.emplace_back(); auto fill = &filling.back(); (*fill)[0] = tprog->get_name(); if (!tprog->get_services().empty()) { vector services = tprog->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { if(sv_iter != services.begin()) { filling.emplace_back(); fill = &filling.back(); } string name = get_service_name(*sv_iter); (*fill)[1] = "[" + name + "](" + make_file_link(fname) + "#service-" + str_to_id(name) + ")"; vector functions = (*sv_iter)->get_functions(); vector::iterator fn_iter; for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) { string fn_name = (*fn_iter)->get_name(); filling.emplace_back(); fill = &filling.back(); (*fill)[1] = " [ • " + fn_name + "](" + make_file_link(fname) + "#function-" + str_to_id(name + fn_name) + ")"; } } } // Data Types Column auto it_fill = filling.begin(); if (!tprog->get_enums().empty()) { vector enums = tprog->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { if(it_fill == filling.end()) { filling.emplace_back(); fill = &filling.back(); it_fill = filling.end(); } else { fill = &*it_fill; ++it_fill; } string name = (*en_iter)->get_name(); (*fill)[2] = "[" + name + "](" + make_file_link(fname) + "#enumeration-" + str_to_id(name) + ")"; } } if (!tprog->get_typedefs().empty()) { vector typedefs = tprog->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { if(it_fill == filling.end()) { filling.emplace_back(); fill = &filling.back(); it_fill = filling.end(); } else { fill = &*it_fill; ++it_fill; } string name = (*td_iter)->get_symbolic(); (*fill)[2] = "[" + name + "](" + make_file_link(fname) + "#typedef-" + str_to_id(name) + ")"; } } if (!tprog->get_objects().empty()) { vector objects = tprog->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { if(it_fill == filling.end()) { filling.emplace_back(); fill = &filling.back(); it_fill = filling.end(); } else { fill = &*it_fill; ++it_fill; } string name = (*o_iter)->get_name(); (*fill)[2] = "[" + name + "](" + make_file_link(fname); if ((*o_iter)->is_xception()) { (*fill)[2] += "#exception-"; } else if ((*o_iter)->is_struct() && (*o_iter)->is_union()) { (*fill)[2] += "#union-"; } else { (*fill)[2] += "#struct-"; } (*fill)[2] += str_to_id(name) + ")"; } } // Constants Column it_fill = filling.begin(); if (!tprog->get_consts().empty()) { map const_markdown; vector consts = tprog->get_consts(); vector::iterator con_iter; for (con_iter = consts.begin(); con_iter != consts.end(); ++con_iter) { if(it_fill == filling.end()) { filling.emplace_back(); fill = &filling.back(); it_fill = filling.end(); } else { fill = &*it_fill; ++it_fill; } string name = (*con_iter)->get_name(); (*fill)[3] = "[" + name + "](" + make_file_link(fname) + "#constant-" + str_to_id(name) + ")"; } } for(auto& fill : filling) { for(auto& c : fill) f_out_ << '|' << c; f_out_ << '|' << endl; } f_out_ << endl; } /** * Prepares for file generation by opening up the necessary file output * stream. */ void t_markdown_generator::generate_program() { // Make output directory MKDIR(get_out_dir().c_str()); string pname = program_->get_name(); current_file_ = make_file_name(pname); string fname = get_out_dir() + current_file_; f_out_.open(fname.c_str()); f_out_ << "# Thrift module: " << pname << endl << endl; print_doc(program_); f_out_ << endl << endl; generate_program_toc(); if (!program_->get_consts().empty()) { f_out_ << "***" << endl << "## Constants" << endl << endl; vector consts = program_->get_consts(); f_out_ << "|Constant|Type|Value||" << endl << "|---|---|---|---|" << endl; generate_consts(consts); f_out_ << endl; } if (!program_->get_enums().empty()) { f_out_ << "***" << endl << "## Enumerations" << endl << endl; // Generate enums vector enums = program_->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { generate_enum(*en_iter); } } if (!program_->get_typedefs().empty()) { f_out_ << "***" << endl << "## Type declarations" << endl << endl; // Generate typedefs vector typedefs = program_->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { generate_typedef(*td_iter); } } if (!program_->get_objects().empty()) { f_out_ << "***" << endl << "## Data structures" << endl << endl; // Generate structs and exceptions in declared order vector objects = program_->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { if ((*o_iter)->is_xception()) { generate_xception(*o_iter); } else { generate_struct(*o_iter); } } } if (!program_->get_services().empty()) { f_out_ << "***" << endl << "## Services" << endl << endl; // Generate services vector services = program_->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { service_name_ = get_service_name(*sv_iter); generate_service(*sv_iter); } } f_out_ << endl; f_out_.close(); generate_index(); } /** * Emits the index(.ext) file for the recursive set of Thrift programs */ void t_markdown_generator::generate_index() { current_file_ = make_file_name("index"); string index_fname = get_out_dir() + current_file_; f_out_.open(index_fname.c_str()); f_out_ << "# Thrift declarations" << endl; f_out_ << "| Module | Services & Functions | Data types | Constants |" << endl << "| --- | --- | --- | --- |" << endl; vector programs; generate_program_toc_rows(program_, programs); f_out_ << endl; f_out_.close(); } /** * Returns the target file for a link * The returned string is empty, whenever filename refers to the current file. */ std::string t_markdown_generator::make_file_link(std::string filename) { return (current_file_.compare(filename) != 0) ? filename : ""; } /** * Returns the target file for a link * The returned string is empty, whenever filename refers to the current file. */ std::string t_markdown_generator::make_file_name(std::string filename) { return extension_.empty() ? filename : (filename + extension_); } /** * If the provided documentable object has documentation attached, this * will emit it to the output stream in HTML format. */ void t_markdown_generator::print_doc(t_doc* tdoc) { if (tdoc->has_doc()) { if (unsafe_) { f_out_ << tdoc->get_doc(); } else { f_out_ << escape_html(tdoc->get_doc()); } } } bool t_markdown_generator::is_utf8_sequence(std::string const& str, size_t firstpos) { // leading char determines the length of the sequence unsigned char c = str.at(firstpos); int count = 0; if ((c & 0xE0) == 0xC0) { count = 1; } else if ((c & 0xF0) == 0xE0) { count = 2; } else if ((c & 0xF8) == 0xF0) { count = 3; } else if ((c & 0xFC) == 0xF8) { count = 4; } else if ((c & 0xFE) == 0xFC) { count = 5; } else { // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 leading byte", c, int(c)); return false; // no UTF-8 } // following chars size_t pos = firstpos + 1; while ((pos < str.length()) && (0 < count)) { c = str.at(pos); if ((c & 0xC0) != 0x80) { // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 following byte", c, int(c)); return false; // no UTF-8 } --count; ++pos; } // true if the sequence is complete return (0 == count); } void t_markdown_generator::detect_input_encoding(std::string const& str, size_t firstpos) { if (is_utf8_sequence(str, firstpos)) { pdebug("Input seems to be already UTF-8 encoded"); input_type_ = INPUT_UTF8; return; } // fallback pwarning(1, "Input is not UTF-8, treating as plain ANSI"); input_type_ = INPUT_PLAIN; } void t_markdown_generator::init_allowed__markup() { allowed_markup.clear(); // standalone tags allowed_markup["br"] = 1; allowed_markup["br/"] = 1; allowed_markup["img"] = 1; // paired tags allowed_markup["b"] = 1; allowed_markup["/b"] = 1; allowed_markup["u"] = 1; allowed_markup["/u"] = 1; allowed_markup["i"] = 1; allowed_markup["/i"] = 1; allowed_markup["s"] = 1; allowed_markup["/s"] = 1; allowed_markup["big"] = 1; allowed_markup["/big"] = 1; allowed_markup["small"] = 1; allowed_markup["/small"] = 1; allowed_markup["sup"] = 1; allowed_markup["/sup"] = 1; allowed_markup["sub"] = 1; allowed_markup["/sub"] = 1; allowed_markup["pre"] = 1; allowed_markup["/pre"] = 1; allowed_markup["tt"] = 1; allowed_markup["/tt"] = 1; allowed_markup["ul"] = 1; allowed_markup["/ul"] = 1; allowed_markup["ol"] = 1; allowed_markup["/ol"] = 1; allowed_markup["li"] = 1; allowed_markup["/li"] = 1; allowed_markup["a"] = 1; allowed_markup["/a"] = 1; allowed_markup["p"] = 1; allowed_markup["/p"] = 1; allowed_markup["code"] = 1; allowed_markup["/code"] = 1; allowed_markup["dl"] = 1; allowed_markup["/dl"] = 1; allowed_markup["dt"] = 1; allowed_markup["/dt"] = 1; allowed_markup["dd"] = 1; allowed_markup["/dd"] = 1; allowed_markup["h1"] = 1; allowed_markup["/h1"] = 1; allowed_markup["h2"] = 1; allowed_markup["/h2"] = 1; allowed_markup["h3"] = 1; allowed_markup["/h3"] = 1; allowed_markup["h4"] = 1; allowed_markup["/h4"] = 1; allowed_markup["h5"] = 1; allowed_markup["/h5"] = 1; allowed_markup["h6"] = 1; allowed_markup["/h6"] = 1; } std::string t_markdown_generator::escape_html_tags(std::string const& str) { std::ostringstream result; unsigned char c = '?'; size_t lastpos; size_t firstpos = 0; while (firstpos < str.length()) { // look for non-ASCII char lastpos = firstpos; while (lastpos < str.length()) { c = str.at(lastpos); if (('<' == c) || ('>' == c)) { break; } ++lastpos; } // copy what we got so far if (lastpos > firstpos) { result << str.substr(firstpos, lastpos - firstpos); firstpos = lastpos; } // reached the end? if (firstpos >= str.length()) { break; } // tag end without corresponding begin ++firstpos; if ('>' == c) { result << ">"; continue; } // extract the tag std::ostringstream tagstream; while (firstpos < str.length()) { c = str.at(firstpos); ++firstpos; if ('<' == c) { tagstream << "<"; // nested begin? } else if ('>' == c) { break; } else { tagstream << c; // not very efficient, but tags should be quite short } } // we allow for several markup in docstrings, all else will become escaped string tag_content = tagstream.str(); string tag_key = tag_content; size_t first_white = tag_key.find_first_of(" \t\f\v\n\r"); if (first_white != string::npos) { tag_key.erase(first_white); } for (char & i : tag_key) { i = tolower(i); } if (allowed_markup.find(tag_key) != allowed_markup.end()) { result << "<" << tag_content << ">"; } else { result << "<" << tagstream.str() << ">"; pverbose("illegal markup <%s> in doc-comment\n", tag_key.c_str()); } } return result.str(); } std::string t_markdown_generator::escape_html(std::string const& str) { // the generated HTML header says it is UTF-8 encoded // if UTF-8 input has been detected before, we don't need to change anything //if (input_type_ == INPUT_UTF8) { // return escape_html_tags(str); //} // convert unsafe chars to their &#; equivalent std::ostringstream result; unsigned char c = '?'; unsigned int ic = 0; size_t lastpos; size_t firstpos = 0; while (firstpos < str.length()) { // look for non-ASCII char lastpos = firstpos; while (lastpos < str.length()) { c = str.at(lastpos); ic = c; if ((32 > ic) || (127 < ic)) { break; } ++lastpos; } // copy what we got so far if (lastpos > firstpos) { result << str.substr(firstpos, lastpos - firstpos); firstpos = lastpos; } // reached the end? if (firstpos >= str.length()) { break; } // some control code? if (ic <= 31) { switch (c) { case '\r': case '\n': case '\t': result << ' '; break; default: // silently consume all other ctrl chars break; } ++firstpos; continue; } // reached the end? if (firstpos >= str.length()) { break; } // try to detect input encoding if (input_type_ == INPUT_UNKNOWN) { detect_input_encoding(str, firstpos); if (input_type_ == INPUT_UTF8) { lastpos = str.length(); result << str.substr(firstpos, lastpos - firstpos); break; } } // convert the character to something useful based on the detected encoding switch (input_type_) { case INPUT_PLAIN: result << "&#" << ic << ";"; ++firstpos; break; default: throw "Unexpected or unrecognized input encoding"; } } return escape_html_tags(result.str()); } /** * Prints out the provided type in Markdown */ int t_markdown_generator::print_type(t_type* ttype) { std::string::size_type len = 0; if (ttype->is_container()) { if (ttype->is_list()) { f_out_ << "list<"; len = 6 + print_type(((t_list*)ttype)->get_elem_type()); f_out_ << ">"; } else if (ttype->is_set()) { f_out_ << "set<"; len = 5 + print_type(((t_set*)ttype)->get_elem_type()); f_out_ << ">"; } else if (ttype->is_map()) { f_out_ << "map<"; len = 5 + print_type(((t_map*)ttype)->get_key_type()); f_out_ << ", "; len += print_type(((t_map*)ttype)->get_val_type()); f_out_ << ">"; } } else if (ttype->is_base_type()) { f_out_ << "```" << (ttype->is_binary() ? "binary" : ttype->get_name()) << "```"; len = ttype->get_name().size(); } else { string prog_name = ttype->get_program()->get_name(); string type_name = ttype->get_name(); f_out_ << "[```" << type_name << "```](" << make_file_link(make_file_name(prog_name)) << "#"; if (ttype->is_typedef()) { f_out_ << "typedef-"; } else if (ttype->is_xception()) { f_out_ << "exception-"; } else if (ttype->is_struct()) { if(((t_struct*)ttype)->is_union()) f_out_ << "union-"; else f_out_ << "struct-"; } else if (ttype->is_enum()) { f_out_ << "enumeration-"; } else if (ttype->is_service()) { f_out_ << "service-"; } len = type_name.size(); if (ttype->get_program() != program_) { f_out_ << str_to_id(prog_name); len += prog_name.size() + 1; } f_out_ << str_to_id(type_name) << ')'; } return (int)len; } /** * Prints out an Markdown representation of the provided constant value */ void t_markdown_generator::print_const_value(t_type* type, t_const_value* tvalue) { // if tvalue is an identifier, the constant content is already shown elsewhere if (tvalue->get_type() == t_const_value::CV_IDENTIFIER) { string fname = make_file_name(program_->get_name()); string name = escape_html(tvalue->get_identifier()); f_out_ << "[```" << name << "```](" + make_file_link(fname) + "#constant-" + str_to_id(name) + ")"; return; } t_type* truetype = type; while (truetype->is_typedef()) { truetype = ((t_typedef*)truetype)->get_type(); } bool first = true; if (truetype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base(); f_out_ << "```"; switch (tbase) { case t_base_type::TYPE_STRING: f_out_ << escape_html(get_escaped_string(tvalue)); break; case t_base_type::TYPE_BOOL: f_out_ << ((tvalue->get_integer() != 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_I16: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_I32: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_I64: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (tvalue->get_type() == t_const_value::CV_INTEGER) { f_out_ << tvalue->get_integer(); } else { f_out_ << tvalue->get_double(); } break; default: f_out_ << "UNKNOWN BASE TYPE"; break; } f_out_ << "```"; } else if (truetype->is_enum()) { f_out_ << escape_html(truetype->get_name()) << "." << escape_html(tvalue->get_identifier_name()); } else if (truetype->is_struct() || truetype->is_xception()) { f_out_ << "{ "; const vector& fields = ((t_struct*)truetype)->get_members(); vector::const_iterator f_iter; const map& val = tvalue->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + truetype->get_name() + " has no field " + v_iter->first->get_string(); } if (!first) { f_out_ << ", "; } first = false; f_out_ << escape_html(v_iter->first->get_string()) << " = "; print_const_value(field_type, v_iter->second); } f_out_ << " }"; } else if (truetype->is_map()) { f_out_ << "{ "; map map_elems = tvalue->get_map(); map::iterator map_iter; for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_map*)truetype)->get_key_type(), map_iter->first); f_out_ << " = "; print_const_value(((t_map*)truetype)->get_val_type(), map_iter->second); } f_out_ << " }"; } else if (truetype->is_list()) { f_out_ << "{ "; vector list_elems = tvalue->get_list(); ; vector::iterator list_iter; for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_list*)truetype)->get_elem_type(), *list_iter); } f_out_ << " }"; } else if (truetype->is_set()) { f_out_ << "{ "; vector list_elems = tvalue->get_list(); ; vector::iterator list_iter; for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_set*)truetype)->get_elem_type(), *list_iter); } f_out_ << " }"; } else { f_out_ << "UNKNOWN TYPE"; } } /** * Prints out documentation for arguments/exceptions of a function, if any documentation has been * supplied. */ void t_markdown_generator::print_fn_args_doc(t_function* tfunction) { bool has_docs = false; vector args = tfunction->get_arglist()->get_members(); vector::iterator arg_iter = args.begin(); if (arg_iter != args.end()) { for (; arg_iter != args.end(); arg_iter++) { if ((*arg_iter)->has_doc() && !(*arg_iter)->get_doc().empty()) { has_docs = true; break; } } if (has_docs) { arg_iter = args.begin(); f_out_ << endl << "* parameters:" << endl; for (int n = 1; arg_iter != args.end(); ++arg_iter, ++n ) { f_out_ << n << ". " << (*arg_iter)->get_name(); f_out_ << " - " << escape_html((*arg_iter)->get_doc()); f_out_ << endl; } f_out_ << endl; } } if(!has_docs) f_out_ << endl; has_docs = false; vector excepts = tfunction->get_xceptions()->get_members(); vector::iterator ex_iter = excepts.begin(); if (ex_iter != excepts.end()) { for (; ex_iter != excepts.end(); ++ex_iter) { if ((*ex_iter)->has_doc() && !(*ex_iter)->get_doc().empty()) { has_docs = true; break; } } if (has_docs) { ex_iter = excepts.begin(); f_out_ << "* exceptions:" << endl; for (; ex_iter != excepts.end(); ex_iter++) { f_out_ << " * " << (*ex_iter)->get_type()->get_name(); f_out_ << " - "; f_out_ << escape_html((*ex_iter)->get_doc()); f_out_ << endl; } f_out_ << endl; } } } /** * Generates a typedef. * * @param ttypedef The type definition */ void t_markdown_generator::generate_typedef(t_typedef* ttypedef) { string name = ttypedef->get_name(); f_out_ << "### Typedef: " << name << endl; print_doc(ttypedef); f_out_ << endl << endl; f_out_ << "_Base type_: **"; print_type(ttypedef->get_type()); f_out_ << "**" << endl << endl; f_out_ << endl; } /** * Generates code for an enumerated type. * * @param tenum The enumeration */ void t_markdown_generator::generate_enum(t_enum* tenum) { string name = tenum->get_name(); f_out_ << "### Enumeration: " << name << endl; print_doc(tenum); f_out_ << endl << endl << "|Name|Value|Description|" << endl << "|---|---|---|" << endl; vector values = tenum->get_constants(); vector::iterator val_iter; for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) { f_out_ << "|```"; f_out_ << (*val_iter)->get_name(); f_out_ << "```|```"; f_out_ << (*val_iter)->get_value(); f_out_ << "```|"; print_doc((*val_iter)); f_out_ << "|" << endl; } f_out_ << endl; } /** * Generates a constant value */ void t_markdown_generator::generate_const(t_const* tconst) { // |Constant|Type|Value|HAS_DOC| string name = tconst->get_name(); f_out_ << "| ```" << name << "``` | "; print_type(tconst->get_type()); f_out_ << "| ```"; print_const_value(tconst->get_type(), tconst->get_value()); f_out_ << "``` |"; if (tconst->has_doc()) { print_doc(tconst); } f_out_ << '|' << endl; } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_markdown_generator::generate_struct(t_struct* tstruct) { string name = tstruct->get_name(); f_out_ << "### "; if (tstruct->is_xception()) { f_out_ << "Exception: "; } else if (tstruct->is_union()) { f_out_ << "Union: "; } else { f_out_ << "Struct: "; } f_out_ << name << endl; print_doc(tstruct); f_out_ << endl << endl; vector members = tstruct->get_members(); vector::iterator mem_iter = members.begin(); f_out_ << "| Key | Field | Type | Description | Requiredness " "| Default value |" << endl << "| --- | --- | --- | --- | --- | --- |" << endl; for (; mem_iter != members.end(); mem_iter++) { f_out_ << '|' << (*mem_iter)->get_key(); f_out_ << '|' << (*mem_iter)->get_name(); f_out_ << '|'; print_type((*mem_iter)->get_type()); f_out_ << '|' << escape_html((*mem_iter)->get_doc()) << '|'; if ((*mem_iter)->get_req() == t_field::T_OPTIONAL) { f_out_ << "optional"; } else if ((*mem_iter)->get_req() == t_field::T_REQUIRED) { f_out_ << "required"; } else { f_out_ << "default"; } f_out_ << '|'; t_const_value* default_val = (*mem_iter)->get_value(); if (default_val != nullptr) { f_out_ << "```"; print_const_value((*mem_iter)->get_type(), default_val); f_out_ << "```"; } f_out_ << '|' << endl; } f_out_ << endl; } /** * Exceptions are special structs * * @param tstruct The struct definition */ void t_markdown_generator::generate_xception(t_struct* txception) { generate_struct(txception); } /** * Generates the Markdown block for a Thrift service. * * @param tservice The service definition */ void t_markdown_generator::generate_service(t_service* tservice) { f_out_ << "### Service: " << service_name_ << endl; if (tservice->get_extends()) { f_out_ << "**extends ** _"; print_type(tservice->get_extends()); f_out_ << "_" << endl; } print_doc(tservice); f_out_ << endl; vector functions = tservice->get_functions(); vector::iterator fn_iter = functions.begin(); for (; fn_iter != functions.end(); fn_iter++) { string fn_name = (*fn_iter)->get_name(); f_out_ << "#### Function: " << service_name_ << "." << fn_name << endl; print_doc(*fn_iter); f_out_ << endl << endl; print_type((*fn_iter)->get_returntype()); bool first = true; f_out_ << endl << " _" << fn_name << "_("; vector args = (*fn_iter)->get_arglist()->get_members(); vector::iterator arg_iter = args.begin(); for (; arg_iter != args.end(); arg_iter++) { if (!first) { f_out_ << "," << endl; } first = false; print_type((*arg_iter)->get_type()); f_out_ << " " << (*arg_iter)->get_name(); if ((*arg_iter)->get_value() != nullptr) { f_out_ << " = "; print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value()); } } f_out_ << ")" << endl; first = true; vector excepts = (*fn_iter)->get_xceptions()->get_members(); vector::iterator ex_iter = excepts.begin(); if (ex_iter != excepts.end()) { f_out_ << "> throws "; for (; ex_iter != excepts.end(); ex_iter++) { if (!first) { f_out_ << ", "; } first = false; print_type((*ex_iter)->get_type()); } f_out_ << endl; } print_fn_args_doc(*fn_iter); f_out_ << endl; } } std::string t_markdown_generator::display_name() const { return "Markdown"; } THRIFT_REGISTER_GENERATOR( markdown, "Markdown", " suffix: Create files/links with/out 'md|html' default None\n" " noescape: Do not escape with html-entities in doc text.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_dart_generator.cc0000644000000000000000000023701614370300523025214 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes static const string endl2 = "\n\n"; /** * Use the current Thrift version for static libraries. When releasing, update * the version in these files. * - lib/dart/pubspec.yaml * - test/dart/test_client/pubspec.yaml * - tutorial/dart/client/pubspec.yaml * - tutorial/dart/console_client/pubspec.yaml * - tutorial/dart/server/pubspec.yaml * See https://thrift.apache.org/docs/committers/HowToVersion */ static const string dart_thrift_version = THRIFT_VERSION; /* forward declarations */ string initial_caps_to_underscores(string name); /** * Dart code generator * */ class t_dart_generator : public t_oop_generator { public: t_dart_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; library_name_ = ""; library_prefix_ = ""; package_prefix_ = ""; pubspec_lib_ = ""; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("library_name") == 0) { library_name_ = (iter->second); } else if( iter->first.compare("library_prefix") == 0) { library_prefix_ = (iter->second) + "."; package_prefix_ = replace_all(library_prefix_, ".", "/"); } else if( iter->first.compare("pubspec_lib") == 0) { pubspec_lib_ = (iter->second); } else { throw "unknown option dart:" + iter->first; } } out_dir_base_ = "gen-dart"; } void scope_up(std::ostream& out, std::string prefix=" ") { out << prefix << "{" << endl; indent_up(); } void scope_down(std::ostream& out, std::string postfix=endl) { indent_down(); indent(out) << "}" << postfix; } string replace_all(string contents, string search, string repl) { string str(contents); size_t slen = search.length(); size_t rlen = repl.length(); size_t incr = (rlen > 0) ? rlen : 1; if (slen > 0) { size_t found = str.find(search); while ((found != string::npos) && (found < str.length())) { str.replace(found, slen, repl); found = str.find(search, found + incr); } } return str; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void export_class_to_library(string file_name, string class_name); void generate_dart_library(); void generate_dart_pubspec(); void generate_consts(std::vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval = false); std::string render_const_value(ostream& out, std::string name, t_type* type, t_const_value* value); /** * Service-level generation functions */ void generate_dart_struct(t_struct* tstruct, bool is_exception); void generate_dart_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool is_result = false, string export_file_name = ""); void generate_dart_struct_reader(std::ostream& out, t_struct* tstruct); void generate_dart_validator(std::ostream& out, t_struct* tstruct); void generate_dart_struct_result_writer(std::ostream& out, t_struct* tstruct); void generate_dart_struct_writer(std::ostream& out, t_struct* tstruct); void generate_dart_struct_tostring(std::ostream& out, t_struct* tstruct); std::string get_dart_type_string(t_type* type); void generate_generic_field_getters(std::ostream& out, t_struct* tstruct); void generate_generic_field_setters(std::ostream& out, t_struct* tstruct); void generate_generic_isset_method(std::ostream& out, t_struct* tstruct); void generate_dart_bean_boilerplate(std::ostream& out, t_struct* tstruct); void generate_function_helpers(t_function* tfunction); std::string init_value(t_field* tfield); std::string get_cap_name(std::string name); std::string get_member_name(std::string name); std::string get_args_class_name(std::string name); std::string get_result_class_name(std::string name); std::string get_file_name(std::string name); std::string get_constants_class_name(std::string name); std::string generate_isset_check(t_field* field); std::string generate_isset_check(std::string field); void generate_isset_set(ostream& out, t_field* field); void generate_service_interface(t_service* tservice); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter, std::string map); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_dart_doc(std::ostream& out, t_doc* tdoc); void generate_dart_doc(std::ostream& out, t_function* tdoc); /** * Helper rendering functions */ std::string find_library_name(t_program* program); std::string dart_library(string file_name); std::string service_imports(); std::string dart_thrift_imports(); std::string type_name(t_type* ttype); std::string base_type_name(t_base_type* tbase); std::string declare_field(t_field* tfield, bool init = false); std::string function_signature(t_function* tfunction); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string get_ttype_class_name(t_type* ttype); bool type_can_be_null(t_type* ttype) { ttype = get_true_type(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string(); } vector split(const string& s, char delim) { vector elems; stringstream ss(s); string item; while (getline(ss, item, delim)) { elems.push_back(item); } return elems; } std::string constant_name(std::string name); private: ofstream_with_content_based_conditional_update f_service_; std::string library_name_; std::string library_prefix_; std::string package_prefix_; std::string pubspec_lib_; std::string base_dir_; std::string src_dir_; std::string library_exports_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_dart_generator::init_generator() { MKDIR(get_out_dir().c_str()); if (library_name_.empty()) { library_name_ = find_library_name(program_); } string subdir = get_out_dir() + "/" + library_name_; MKDIR(subdir.c_str()); base_dir_ = subdir; if (library_prefix_.empty()) { subdir += "/lib"; MKDIR(subdir.c_str()); subdir += "/src"; MKDIR(subdir.c_str()); src_dir_ = subdir; } else { src_dir_ = base_dir_; } } string t_dart_generator::find_library_name(t_program* program) { string name = program->get_namespace("dart"); if (name.empty()) { name = program->get_name(); } name = replace_all(name, ".", "_"); name = replace_all(name, "-", "_"); return name; } /** * The Dart library * * @return String of the library, e.g. "library myservice;" */ string t_dart_generator::dart_library(string file_name) { string out = "library " + library_prefix_ + library_name_; if (!file_name.empty()) { if (library_prefix_.empty()) { out += ".src." + file_name; } else { out += "." + file_name; } } return out + ";\n"; } /** * Prints imports for services * * @return List of imports for services */ string t_dart_generator::service_imports() { return "import 'dart:async';" + endl; } /** * Prints standard dart imports * * @return List of imports necessary for thrift */ string t_dart_generator::dart_thrift_imports() { string imports = "import 'dart:typed_data' show Uint8List;" + endl + "import 'package:thrift/thrift.dart';" + endl; // add import for this library if (package_prefix_.empty()) { imports += "import 'package:" + library_name_ + "/" + library_name_ + ".dart';" + endl; } else { imports += "import 'package:" + package_prefix_ + library_name_ + ".dart';" + endl; } // add imports for included thrift files const vector& includes = program_->get_includes(); for (auto include : includes) { string include_name = find_library_name(include); string named_import = "t_" + include_name; if (package_prefix_.empty()) { imports += "import 'package:" + include_name + "/" + include_name + ".dart' as " + named_import + ";" + endl; } else { imports += "import 'package:" + package_prefix_ + include_name + ".dart' as " + named_import + ";" + endl; } } return imports; } /** * Not used */ void t_dart_generator::close_generator() { generate_dart_library(); if (library_prefix_.empty()) { generate_dart_pubspec(); } } void t_dart_generator::generate_dart_library() { string f_library_name; if (library_prefix_.empty()) { f_library_name = base_dir_ + "/lib/" + library_name_ + ".dart"; } else { f_library_name = get_out_dir() + "/" + library_name_ + ".dart"; } ofstream_with_content_based_conditional_update f_library; f_library.open(f_library_name.c_str()); f_library << autogen_comment() << endl; f_library << "library " << library_prefix_ << library_name_ << ";" << endl2; f_library << library_exports_; f_library.close(); } void t_dart_generator::export_class_to_library(string file_name, string class_name) { string subdir; if (library_prefix_.empty()) { subdir = "src"; } else { subdir = library_name_; } library_exports_ += "export '" + subdir + "/" + file_name + ".dart' show " + class_name + ";" + endl; } void t_dart_generator::generate_dart_pubspec() { string f_pubspec_name = base_dir_ + "/pubspec.yaml"; ofstream_with_content_based_conditional_update f_pubspec; f_pubspec.open(f_pubspec_name.c_str()); indent(f_pubspec) << "name: " << library_name_ << endl; indent(f_pubspec) << "version: 0.0.1" << endl; indent(f_pubspec) << "description: Autogenerated by Thrift Compiler" << endl; f_pubspec << endl; indent(f_pubspec) << "environment:" << endl; indent_up(); indent(f_pubspec) << "sdk: '>=1.24.3 <3.0.0'" << endl; indent_down(); f_pubspec << endl; indent(f_pubspec) << "dependencies:" << endl; indent_up(); if (pubspec_lib_.empty()) { // default to relative path within working directory, which works for tests indent(f_pubspec) << "thrift: # ^" << dart_thrift_version << endl; indent_up(); indent(f_pubspec) << "path: ../../../../lib/dart" << endl; indent_down(); } else { const vector lines = split(pubspec_lib_, '|'); for (const auto & line : lines) { indent(f_pubspec) << line << endl; } } // add included thrift files as dependencies const vector& includes = program_->get_includes(); for (auto include : includes) { string include_name = find_library_name(include); indent(f_pubspec) << include_name << ":" << endl; indent_up(); indent(f_pubspec) << "path: ../" << include_name << endl; indent_down(); } indent_down(); f_pubspec << endl; f_pubspec.close(); } /** * Not used * * @param ttypedef The type definition */ void t_dart_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Enums are a class with a set of static constants. * * @param tenum The enumeration */ void t_dart_generator::generate_enum(t_enum* tenum) { // Make output file string file_name = get_file_name(tenum->get_name()); string f_enum_name = src_dir_ + "/" + file_name + ".dart"; ofstream_with_content_based_conditional_update f_enum; f_enum.open(f_enum_name.c_str()); // Comment and add library f_enum << autogen_comment() << dart_library(file_name) << endl; string class_name = tenum->get_name(); export_class_to_library(file_name, class_name); f_enum << "class " << class_name; scope_up(f_enum); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); indent(f_enum) << "static const int " << (*c_iter)->get_name() << " = " << value << ";" << endl; } // Create a static Set with all valid values for this enum f_enum << endl; indent(f_enum) << "static final Set VALID_VALUES = new Set.from([" << endl; indent_up(); bool firstValue = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { // populate set indent(f_enum) << (firstValue ? "" : ", "); f_enum << (*c_iter)->get_name() << endl; firstValue = false; } indent_down(); indent(f_enum) << "]);" << endl; indent(f_enum) << "static final Map VALUES_TO_NAMES = {" << endl; indent_up(); firstValue = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { indent(f_enum) << (firstValue ? "" : ", "); f_enum << (*c_iter)->get_name() << ": '" << (*c_iter)->get_name() << "'" << endl; firstValue = false; } indent_down(); indent(f_enum) << "};" << endl; scope_down(f_enum); // end class f_enum.close(); } /** * Generates a class that holds all the constants. */ void t_dart_generator::generate_consts(std::vector consts) { if (consts.empty()) { return; } string class_name = get_constants_class_name(program_name_); string file_name = get_file_name(class_name); string f_consts_name = src_dir_ + "/" + file_name + ".dart"; ofstream_with_content_based_conditional_update f_consts; f_consts.open(f_consts_name.c_str()); // Print header f_consts << autogen_comment() << dart_library(file_name) << endl; f_consts << dart_thrift_imports() << endl; export_class_to_library(file_name, class_name); indent(f_consts) << "class " << class_name; scope_up(f_consts); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { print_const_value(f_consts, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false); f_consts << endl; } scope_down(f_consts); f_consts.close(); } void t_dart_generator::print_const_value(std::ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) { type = get_true_type(type); indent(out); if (!defval) { out << (in_static ? "var " : "static final "); } if (type->is_base_type()) { if (!defval) { out << type_name(type) << " "; } string v2 = render_const_value(out, name, type, value); out << name; out << " = " << v2 << ";" << endl << endl; } else if (type->is_enum()) { if (!defval) { out << type_name(type) << " "; } out << name; out << " = " << value->get_integer() << ";" << endl << endl; } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; out << type_name(type) << " " << name << " = new " << type_name(type) << "()"; indent_up(); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string val = render_const_value(out, name, field_type, v_iter->second); out << endl; indent(out) << ".." << v_iter->first->get_string() << " = " << val; } indent_down(); out << ";" << endl; } else if (type->is_map()) { if (!defval) { out << type_name(type) << " "; } out << name << " ="; scope_up(out); t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); indent(out) << key << ": " << val << "," << endl; } scope_down(out, ";" + endl); out << endl; } else if (type->is_list() || type->is_set()) { if (!defval) { out << type_name(type) << " "; } out << name << " = "; t_type* etype; if (type->is_list()) { out << "[" << endl; etype = ((t_list*)type)->get_elem_type(); } else { out << "new " << type_name(type) << ".from([" << endl; etype = ((t_set*)type)->get_elem_type(); } const vector& val = value->get_list(); vector::const_iterator v_iter; indent_up(); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(out, name, etype, *v_iter); indent(out) << val << "," << endl; } indent_down(); if (type->is_list()) { indent(out) << "];" << endl; } else { indent(out) << "]);" << endl; } } else { throw "compiler error: no const of type " + type->get_name(); } } string t_dart_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value) { (void)name; type = get_true_type(type); std::ostringstream render; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: render << "'" << get_escaped_string(value) << "'"; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: render << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << value->get_integer(); } else { render << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { render << value->get_integer(); } else { string t = tmp("tmp"); print_const_value(out, t, type, value, true); out << endl; render << t; } return render.str(); } /** * Generates a struct definition for a thrift data type. This is a class * with data members, read(), write(), and an inner Isset class. * * @param tstruct The struct definition */ void t_dart_generator::generate_struct(t_struct* tstruct) { generate_dart_struct(tstruct, false); } /** * Exceptions are structs, but they inherit from Exception * * @param tstruct The struct definition */ void t_dart_generator::generate_xception(t_struct* txception) { generate_dart_struct(txception, true); } /** * Dart struct definition. * * @param tstruct The struct definition */ void t_dart_generator::generate_dart_struct(t_struct* tstruct, bool is_exception) { string file_name = get_file_name(tstruct->get_name()); string f_struct_name = src_dir_ + "/" + file_name + ".dart"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << dart_library(file_name) << endl; string imports; f_struct << dart_thrift_imports() << endl; generate_dart_struct_definition(f_struct, tstruct, is_exception, false, file_name); f_struct.close(); } /** * Dart struct definition. This has various parameters, as it could be * generated standalone or inside another class as a helper. If it * is a helper than it is a static class. * * @param tstruct The struct definition * @param is_exception Is this an exception? * @param in_class If inside a class, needs to be static class * @param is_result If this is a result it needs a different writer */ void t_dart_generator::generate_dart_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool is_result, string export_file_name) { generate_dart_doc(out, tstruct); string class_name = tstruct->get_name(); if (!export_file_name.empty()) { export_class_to_library(export_file_name, class_name); } indent(out) << "class " << class_name << " "; out << "implements TBase"; if (is_exception) { out << ", Exception "; } scope_up(out); indent(out) << "static final TStruct _STRUCT_DESC = new TStruct(\"" << class_name << "\");" << endl; // Members are public for -dart, private for -dartbean const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "static final TField _" << constant_name((*m_iter)->get_name()) << "_FIELD_DESC = new TField(\"" << (*m_iter)->get_name() << "\", " << type_to_enum((*m_iter)->get_type()) << ", " << (*m_iter)->get_key() << ");" << endl; } out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_dart_doc(out, *m_iter); indent(out) << type_name((*m_iter)->get_type()) + " _" << get_member_name((*m_iter)->get_name()) << init_value(*m_iter) << ";" << endl; indent(out) << "static const int " << upcase_string((*m_iter)->get_name()) << " = " << (*m_iter)->get_key() << ";" << endl; } out << endl; // Inner Isset class if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!type_can_be_null((*m_iter)->get_type())) { string field_name = get_member_name((*m_iter)->get_name()); indent(out) << "bool __isset_" << field_name << " = false;" << endl; } } } out << endl; // Default constructor indent(out) << tstruct->get_name() << "()"; scope_up(out); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr) { print_const_value(out, "this." + get_member_name((*m_iter)->get_name()), t, (*m_iter)->get_value(), true, true); } } scope_down(out); out << endl; generate_dart_bean_boilerplate(out, tstruct); generate_generic_field_getters(out, tstruct); generate_generic_field_setters(out, tstruct); generate_generic_isset_method(out, tstruct); generate_dart_struct_reader(out, tstruct); if (is_result) { generate_dart_struct_result_writer(out, tstruct); } else { generate_dart_struct_writer(out, tstruct); } generate_dart_struct_tostring(out, tstruct); generate_dart_validator(out, tstruct); scope_down(out); out << endl; } /** * Generates a function to read all the fields of the struct. * * @param tstruct The struct definition */ void t_dart_generator::generate_dart_struct_reader(ostream& out, t_struct* tstruct) { indent(out) << "read(TProtocol iprot)"; scope_up(out); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Declare stack tmp variables and read struct header indent(out) << "TField field;" << endl; indent(out) << "iprot.readStructBegin();" << endl; // Loop over reading in fields indent(out) << "while (true)"; scope_up(out); // Read beginning field marker indent(out) << "field = iprot.readFieldBegin();" << endl; // Check for field STOP marker and break indent(out) << "if (field.type == TType.STOP)"; scope_up(out); indent(out) << "break;" << endl; scope_down(out); // Switch statement on the field we are reading indent(out) << "switch (field.id)"; scope_up(out); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << upcase_string((*f_iter)->get_name()) << ":" << endl; indent_up(); indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ")"; scope_up(out); generate_deserialize_field(out, *f_iter, "this."); generate_isset_set(out, *f_iter); scope_down(out, " else"); scope_up(out); indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl; scope_down(out); indent(out) << "break;" << endl; indent_down(); } // In the default case we skip the field indent(out) << "default:" << endl; indent_up(); indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl; indent(out) << "break;" << endl; indent_down(); scope_down(out); // Read field end marker indent(out) << "iprot.readFieldEnd();" << endl; scope_down(out); indent(out) << "iprot.readStructEnd();" << endl2; // in non-beans style, check for required fields of primitive type // (which can be checked here but not in the general validate method) indent(out) << "// check for required fields of primitive type, which can't be " "checked in the validate method" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED && !type_can_be_null((*f_iter)->get_type())) { string field_name = get_member_name((*f_iter)->get_name()); indent(out) << "if (!__isset_" << field_name << ")"; scope_up(out); indent(out) << " throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '" << field_name << "' was not found in serialized data! Struct: \" + toString());" << endl; scope_down(out, endl2); } } // performs various checks (e.g. check that all required fields are set) indent(out) << "validate();" << endl; scope_down(out, endl2); } // generates dart method to perform various checks // (e.g. check that all required fields are set) void t_dart_generator::generate_dart_validator(ostream& out, t_struct* tstruct) { indent(out) << "validate()"; scope_up(out); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent(out) << "// check for required fields" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { string field_name = get_member_name((*f_iter)->get_name()); if (type_can_be_null((*f_iter)->get_type())) { indent(out) << "if (" << field_name << " == null)"; scope_up(out); indent(out) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"Required field '" << field_name << "' was not present! Struct: \" + toString());" << endl; scope_down(out); } else { indent(out) << "// alas, we cannot check '" << field_name << "' because it's a primitive and you chose the non-beans generator." << endl; } } } // check that fields of type enum have valid values indent(out) << "// check that fields of type enum have valid values" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); t_type* type = field->get_type(); // if field is an enum, check that its value is valid if (type->is_enum()) { string field_name = get_member_name(field->get_name()); indent(out) << "if (" << generate_isset_check(field) << " && !" << get_ttype_class_name(type) << ".VALID_VALUES.contains(" << field_name << "))"; scope_up(out); indent(out) << "throw new TProtocolError(TProtocolErrorType.UNKNOWN, \"The field '" << field_name << "' has been assigned the invalid value " << "$" << field_name << "\");" << endl; scope_down(out); } } scope_down(out, endl2); } /** * Generates a function to write all the fields of the struct * * @param tstruct The struct definition */ void t_dart_generator::generate_dart_struct_writer(ostream& out, t_struct* tstruct) { out << indent() << "write(TProtocol oprot)"; scope_up(out); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; // performs various checks (e.g. check that all required fields are set) indent(out) << "validate();" << endl2; indent(out) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string field_name = get_member_name((*f_iter)->get_name()); bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (could_be_unset) { indent(out) << "if (" << generate_isset_check(*f_iter) << ")"; scope_up(out); } bool null_allowed = type_can_be_null((*f_iter)->get_type()); if (null_allowed) { indent(out) << "if (this." << field_name << " != null)"; scope_up(out); } indent(out) << "oprot.writeFieldBegin(_" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; if (null_allowed) { scope_down(out); } if (could_be_unset) { scope_down(out); } } // Write the struct map indent(out) << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();" << endl; scope_down(out, endl2); } /** * Generates a function to write all the fields of the struct, * which is a function result. These fields are only written * if they are set in the Isset array, and only one of them * can be set at a time. * * @param tstruct The struct definition */ void t_dart_generator::generate_dart_struct_result_writer(ostream& out, t_struct* tstruct) { indent(out) << "write(TProtocol oprot)"; scope_up(out); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent(out) << "oprot.writeStructBegin(_STRUCT_DESC);" << endl2; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; indent(out) << "if "; } else { out << " else if "; } out << "(this." << generate_isset_check(*f_iter) << ")"; scope_up(out); indent(out) << "oprot.writeFieldBegin(_" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; scope_down(out, ""); } out << endl; // Write the struct map indent(out) << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();" << endl; scope_down(out, endl2); } void t_dart_generator::generate_generic_field_getters(std::ostream& out, t_struct* tstruct) { // create the getter indent(out) << "getFieldValue(int fieldID)"; scope_up(out); indent(out) << "switch (fieldID)"; scope_up(out); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; std::string field_name = get_member_name(field->get_name()); indent(out) << "case " << upcase_string(field_name) << ":" << endl; indent_up(); indent(out) << "return this." << field_name << ";" << endl; indent_down(); } indent(out) << "default:" << endl; indent_up(); indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl; indent_down(); scope_down(out); // switch scope_down(out, endl2); // method } void t_dart_generator::generate_generic_field_setters(std::ostream& out, t_struct* tstruct) { // create the setter indent(out) << "setFieldValue(int fieldID, Object value)"; scope_up(out); indent(out) << "switch (fieldID)"; scope_up(out); // build up the bodies of both the getter and setter at once const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; std::string field_name = get_member_name(field->get_name()); indent(out) << "case " << upcase_string(field_name) << ":" << endl; indent_up(); indent(out) << "if (value == null)"; scope_up(out); indent(out) << "unset" << get_cap_name(field_name) << "();" << endl; scope_down(out, " else"); scope_up(out); indent(out) << "this." << field_name << " = value;" << endl; scope_down(out); indent(out) << "break;" << endl; indent_down(); out << endl; } indent(out) << "default:" << endl; indent_up(); indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl; indent_down(); scope_down(out); // switch scope_down(out, endl2); // method } // Creates a generic isSet method that takes the field number as argument void t_dart_generator::generate_generic_isset_method(std::ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // create the isSet method indent(out) << "// Returns true if field corresponding to fieldID is set (has been assigned a " "value) and false otherwise" << endl; indent(out) << "bool isSet(int fieldID)"; scope_up(out); indent(out) << "switch (fieldID)"; scope_up(out); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; indent(out) << "case " << upcase_string(field->get_name()) << ":" << endl; indent_up(); indent(out) << "return " << generate_isset_check(field) << ";" << endl; indent_down(); } indent(out) << "default:" << endl; indent_up(); indent(out) << "throw new ArgumentError(\"Field $fieldID doesn't exist!\");" << endl; indent_down(); scope_down(out); // switch scope_down(out, endl2); // method } /** * Generates a set of Dart Bean boilerplate functions (setters, getters, etc.) * for the given struct. * * @param tstruct The struct definition */ void t_dart_generator::generate_dart_bean_boilerplate(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = get_member_name(field->get_name()); std::string cap_name = get_cap_name(field_name); indent(out) << "// " << field_name << endl; // Simple getter generate_dart_doc(out, field); indent(out) << type_name(type) << " get " << field_name << " => this._" << field_name << ";" << endl2; // Simple setter generate_dart_doc(out, field); indent(out) << "set " << field_name << "(" << type_name(type) << " " << field_name << ")"; scope_up(out); indent(out) << "this._" << field_name << " = " << field_name << ";" << endl; generate_isset_set(out, field); scope_down(out, endl2); // isSet method indent(out) << "bool is" << get_cap_name("set") << cap_name << "()"; if (type_can_be_null(type)) { out << " => this." << field_name << " != null;" << endl2; } else { out << " => this.__isset_" << field_name << ";" << endl2; } // Unsetter indent(out) << "unset" << cap_name << "()"; scope_up(out); if (type_can_be_null(type)) { indent(out) << "this." << field_name << " = null;" << endl; } else { indent(out) << "this.__isset_" << field_name << " = false;" << endl; } scope_down(out, endl2); } } /** * Generates a toString() method for the given struct * * @param tstruct The struct definition */ void t_dart_generator::generate_dart_struct_tostring(ostream& out, t_struct* tstruct) { indent(out) << "String toString()"; scope_up(out); indent(out) << "StringBuffer ret = new StringBuffer(\"" << tstruct->get_name() << "(\");" << endl2; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (could_be_unset) { indent(out) << "if (" << generate_isset_check(*f_iter) << ")"; scope_up(out); } t_field* field = (*f_iter); std::string field_name = get_member_name(field->get_name()); if (!first) { indent(out) << "ret.write(\", \");" << endl; } indent(out) << "ret.write(\"" << field_name << ":\");" << endl; bool can_be_null = type_can_be_null(field->get_type()); if (can_be_null) { indent(out) << "if (this." << field_name << " == null)"; scope_up(out); indent(out) << "ret.write(\"null\");" << endl; scope_down(out, " else"); scope_up(out); } if (field->get_type()->is_binary()) { indent(out) << "ret.write(\"BINARY\");" << endl; } else if (field->get_type()->is_enum()) { indent(out) << "String " << field_name << "_name = " << get_ttype_class_name(field->get_type()) << ".VALUES_TO_NAMES[this." << field_name << "];" << endl; indent(out) << "if (" << field_name << "_name != null)"; scope_up(out); indent(out) << "ret.write(" << field_name << "_name);" << endl; indent(out) << "ret.write(\" (\");" << endl; scope_down(out); indent(out) << "ret.write(this." << field_name << ");" << endl; indent(out) << "if (" << field_name << "_name != null)"; scope_up(out); indent(out) << "ret.write(\")\");" << endl; scope_down(out); } else { indent(out) << "ret.write(this." << field_name << ");" << endl; } if (can_be_null) { scope_down(out); } if (could_be_unset) { scope_down(out); } out << endl; first = false; } indent(out) << "ret.write(\")\");" << endl2; indent(out) << "return ret.toString();" << endl; scope_down(out, endl2); } /** * Returns a string with the dart representation of the given thrift type * (e.g. for the type struct it returns "TType.STRUCT") */ std::string t_dart_generator::get_dart_type_string(t_type* type) { if (type->is_list()) { return "TType.LIST"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_typedef()) { return get_dart_type_string(((t_typedef*)type)->get_type()); } else if (type->is_base_type()) { switch (((t_base_type*)type)->get_base()) { case t_base_type::TYPE_VOID: return "TType.VOID"; break; case t_base_type::TYPE_STRING: return "TType.STRING"; break; case t_base_type::TYPE_BOOL: return "TType.BOOL"; break; case t_base_type::TYPE_I8: return "TType.BYTE"; break; case t_base_type::TYPE_I16: return "TType.I16"; break; case t_base_type::TYPE_I32: return "TType.I32"; break; case t_base_type::TYPE_I64: return "TType.I64"; break; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; break; default: throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_dart_generator::get_dart_type_string!"); break; // This should never happen! } } else { throw std::runtime_error( "Unknown thrift type \"" + type->get_name() + "\" passed to t_dart_generator::get_dart_type_string!"); // This should never happen! } } void t_dart_generator::generate_service(t_service* tservice) { string file_name = get_file_name(service_name_); string f_service_name = src_dir_ + "/" + file_name + ".dart"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << dart_library(file_name) << endl; f_service_ << service_imports() << dart_thrift_imports() << endl; f_service_ << endl; generate_service_interface(tservice); generate_service_client(tservice); generate_service_server(tservice); generate_service_helpers(tservice); f_service_.close(); } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_dart_generator::generate_service_interface(t_service* tservice) { string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends_iface = " extends " + get_ttype_class_name(tservice->get_extends()); } generate_dart_doc(f_service_, tservice); string class_name = service_name_; export_class_to_library(get_file_name(service_name_), class_name); indent(f_service_) << "abstract class " << class_name << extends_iface; scope_up(f_service_); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << endl; generate_dart_doc(f_service_, *f_iter); indent(f_service_) << function_signature(*f_iter) << ";" << endl; } scope_down(f_service_, endl2); } /** * Generates structs for all the service args and return types * * @param tservice The service */ void t_dart_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_dart_struct_definition(f_service_, ts, false, false); generate_function_helpers(*f_iter); } } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_dart_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = get_ttype_class_name(tservice->get_extends()); extends_client = " extends " + extends + "Client"; } string class_name = service_name_ + "Client"; export_class_to_library(get_file_name(service_name_), class_name); indent(f_service_) << "class " << class_name << extends_client << " implements " << service_name_; scope_up(f_service_); f_service_ << endl; indent(f_service_) << class_name << "(TProtocol iprot, [TProtocol oprot = null])"; if (!extends.empty()) { indent_up(); f_service_ << endl; indent(f_service_) << ": super(iprot, oprot);" << endl; indent_down(); } else { scope_up(f_service_); indent(f_service_) << "_iprot = iprot;" << endl; indent(f_service_) << "_oprot = (oprot == null) ? iprot : oprot;" << endl; scope_down(f_service_); } f_service_ << endl; if (extends.empty()) { indent(f_service_) << "TProtocol _iprot;" << endl2; indent(f_service_) << "TProtocol get iprot => _iprot;" << endl2; indent(f_service_) << "TProtocol _oprot;" << endl2; indent(f_service_) << "TProtocol get oprot => _oprot;" << endl2; indent(f_service_) << "int _seqid = 0;" << endl2; indent(f_service_) << "int get seqid => _seqid;" << endl2; indent(f_service_) << "int nextSeqid() => ++_seqid;" << endl2; } // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { // Open function indent(f_service_) << function_signature(*f_iter) << " async"; scope_up(f_service_); // Get the struct of function call params t_struct* arg_struct = (*f_iter)->get_arglist(); string argsname = get_args_class_name((*f_iter)->get_name()); vector::const_iterator fld_iter; const vector& fields = arg_struct->get_members(); // Serialize the request indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << (*f_iter)->get_name() << "\", " << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL") << ", nextSeqid()));" << endl; indent(f_service_) << argsname << " args = new " << argsname << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { string arg_field_name = get_member_name((*fld_iter)->get_name()); indent(f_service_) << "args." << arg_field_name << " = " << arg_field_name << ";" << endl; } indent(f_service_) << "args.write(oprot);" << endl; indent(f_service_) << "oprot.writeMessageEnd();" << endl2; indent(f_service_) << "await oprot.transport.flush();" << endl2; if (!(*f_iter)->is_oneway()) { indent(f_service_) << "TMessage msg = iprot.readMessageBegin();" << endl; indent(f_service_) << "if (msg.type == TMessageType.EXCEPTION)"; scope_up(f_service_); indent(f_service_) << "TApplicationError error = TApplicationError.read(iprot);" << endl; indent(f_service_) << "iprot.readMessageEnd();" << endl; indent(f_service_) << "throw error;" << endl; scope_down(f_service_, endl2); string result_class = get_result_class_name((*f_iter)->get_name()); indent(f_service_) << result_class << " result = new " << result_class << "();" << endl; indent(f_service_) << "result.read(iprot);" << endl; indent(f_service_) << "iprot.readMessageEnd();" << endl; // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "if (result." << generate_isset_check("success") << ")"; scope_up(f_service_); indent(f_service_) << "return result.success;" << endl; scope_down(f_service_, endl2); } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { string result_field_name = get_member_name((*x_iter)->get_name()); indent(f_service_) << "if (result." << result_field_name << " != null)"; scope_up(f_service_); indent(f_service_) << "throw result." << result_field_name << ";" << endl; scope_down(f_service_); } // If you get here it's an exception, unless a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "return;" << endl; } else { indent(f_service_) << "throw new TApplicationError(TApplicationErrorType.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } } scope_down(f_service_, endl2); } scope_down(f_service_, endl2); } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_dart_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; // typedef indent(f_service_) << "typedef void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" << endl2; // Extends stuff string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = get_ttype_class_name(tservice->get_extends()); extends_processor = " extends " + extends + "Processor"; } // Generate the header portion string class_name = service_name_ + "Processor"; export_class_to_library(get_file_name(service_name_), class_name); indent(f_service_) << "class " << class_name << extends_processor << " implements TProcessor"; scope_up(f_service_); indent(f_service_) << class_name << "(" << service_name_ << " iface)"; if (!extends.empty()) { indent_up(); f_service_ << endl; indent(f_service_) << ": super(iface)"; indent_down(); } scope_up(f_service_); if (extends.empty()) { indent(f_service_) << "iface_ = iface;" << endl; } for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent(f_service_) << "PROCESS_MAP[\"" << (*f_iter)->get_name() << "\"] = " << get_member_name((*f_iter)->get_name()) << ";" << endl; } scope_down(f_service_, endl2); indent(f_service_) << service_name_ << " iface_;" << endl; if (extends.empty()) { indent(f_service_) << "final Map PROCESS_MAP = {};" << endl; } f_service_ << endl; // Generate the server implementation indent(f_service_) << "bool process(TProtocol iprot, TProtocol oprot)"; scope_up(f_service_); indent(f_service_) << "TMessage msg = iprot.readMessageBegin();" << endl; indent(f_service_) << "ProcessFunction fn = PROCESS_MAP[msg.name];" << endl; indent(f_service_) << "if (fn == null)"; scope_up(f_service_); indent(f_service_) << "TProtocolUtil.skip(iprot, TType.STRUCT);" << endl; indent(f_service_) << "iprot.readMessageEnd();" << endl; indent(f_service_) << "TApplicationError x = new TApplicationError(TApplicationErrorType.UNKNOWN_METHOD, " "\"Invalid method name: '\"+msg.name+\"'\");" << endl; indent(f_service_) << "oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl; indent(f_service_) << "x.write(oprot);" << endl; indent(f_service_) << "oprot.writeMessageEnd();" << endl; indent(f_service_) << "oprot.transport.flush();" << endl; indent(f_service_) << "return true;" << endl; scope_down(f_service_); indent(f_service_) << "fn(msg.seqid, iprot, oprot);" << endl; indent(f_service_) << "return true;" << endl; scope_down(f_service_, endl2); // process function // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } scope_down(f_service_, endl2); // class } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_dart_generator::generate_function_helpers(t_function* tfunction) { if (tfunction->is_oneway()) { return; } t_struct result(program_, get_result_class_name(tfunction->get_name())); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_dart_struct_definition(f_service_, &result, false, true); } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_dart_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; bool await_result = (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()); indent(f_service_) << get_member_name(tfunction->get_name()) << "(int seqid, TProtocol iprot, TProtocol oprot)"; if (await_result) { f_service_ << " async"; } scope_up(f_service_); string argsname = get_args_class_name(tfunction->get_name()); string resultname = get_result_class_name(tfunction->get_name()); indent(f_service_) << argsname << " args = new " << argsname << "();" << endl; indent(f_service_) << "args.read(iprot);" << endl; indent(f_service_) << "iprot.readMessageEnd();" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; if (!tfunction->is_oneway()) { indent(f_service_) << resultname << " result = new " << resultname << "();" << endl; } if (!tfunction->is_oneway() && xceptions.size() > 0) { indent(f_service_) << "try"; scope_up(f_service_); } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); if (await_result) { f_service_ << "result.success = await "; } f_service_ << "iface_." << get_member_name(tfunction->get_name()) << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << get_member_name((*f_iter)->get_name()); } f_service_ << ");" << endl; if (!tfunction->is_oneway() && xceptions.size() > 0) { for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { string result_field_name = get_member_name((*x_iter)->get_name()); scope_down(f_service_, ""); f_service_ << " on " << type_name((*x_iter)->get_type()) << " catch(" << result_field_name << ")"; scope_up(f_service_); if (!tfunction->is_oneway()) { indent(f_service_) << "result." << result_field_name << " = " << result_field_name << ";" << endl; } } scope_down(f_service_, " "); f_service_ << "catch (th)"; scope_up(f_service_); indent(f_service_) << "// Internal error" << endl; indent(f_service_) << "TApplicationError x = new " "TApplicationError(TApplicationErrorType.INTERNAL_ERROR, \"Internal error processing " << tfunction->get_name() << "\");" << endl; indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl; indent(f_service_) << "x.write(oprot);" << endl; indent(f_service_) << "oprot.writeMessageEnd();" << endl; indent(f_service_) << "oprot.transport.flush();" << endl; indent(f_service_) << "return;" << endl; scope_down(f_service_); } if (tfunction->is_oneway()) { indent(f_service_) << "return;" << endl; } else { indent(f_service_) << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid));" << endl; indent(f_service_) << "result.write(oprot);" << endl; indent(f_service_) << "oprot.writeMessageEnd();" << endl; indent(f_service_) << "oprot.transport.flush();" << endl; } scope_down(f_service_, endl2); } /** * Deserializes a field of any type. * * @param tfield The field * @param prefix The variable name or container for this field */ void t_dart_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); string field_name = get_member_name(tfield->get_name()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + field_name; } string name = prefix + field_name; if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << name << " = iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "readBinary();"; } else { out << "readString();"; } break; case t_base_type::TYPE_BOOL: out << "readBool();"; break; case t_base_type::TYPE_I8: out << "readByte();"; break; case t_base_type::TYPE_I16: out << "readI16();"; break; case t_base_type::TYPE_I32: out << "readI32();"; break; case t_base_type::TYPE_I64: out << "readI64();"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble();"; break; default: throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "readI32();"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", field_name.c_str(), type_name(type).c_str()); } } /** * Generates an unserializer for a struct, invokes read() */ void t_dart_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { indent(out) << prefix << " = new " << type_name(tstruct) << "();" << endl; indent(out) << prefix << ".read(iprot);" << endl; } /** * Deserializes a container by reading its size and then iterating */ void t_dart_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { indent(out); scope_up(out, ""); string obj; if (ttype->is_map()) { obj = tmp("_map"); } else if (ttype->is_set()) { obj = tmp("_set"); } else if (ttype->is_list()) { obj = tmp("_list"); } // Declare variables, read header if (ttype->is_map()) { indent(out) << "TMap " << obj << " = iprot.readMapBegin();" << endl; } else if (ttype->is_set()) { indent(out) << "TSet " << obj << " = iprot.readSetBegin();" << endl; } else if (ttype->is_list()) { indent(out) << "TList " << obj << " = iprot.readListBegin();" << endl; } indent(out) << prefix << " = new " << type_name(ttype) << "();" << endl; // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".length" << "; " << "++" << i << ")"; scope_up(out); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } scope_down(out); // Read container end if (ttype->is_map()) { indent(out) << "iprot.readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "iprot.readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "iprot.readListEnd();" << endl; } scope_down(out); } /** * Generates code to deserialize a map */ void t_dart_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey) << endl; indent(out) << declare_field(&fval) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << prefix << "[" << key << "] = " << val << ";" << endl; } /** * Deserializes a set element */ void t_dart_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".add(" << elem << ");" << endl; } /** * Deserializes a list element */ void t_dart_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".add(" << elem << ");" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_dart_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); string field_name = get_member_name(tfield->get_name()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + field_name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + field_name); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + field_name); } else if (type->is_base_type() || type->is_enum()) { string name = prefix + field_name; indent(out) << "oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "writeBinary(" << name << ");"; } else { out << "writeString(" << name << ");"; } break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ");"; break; default: throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32(" << name << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), field_name.c_str(), type_name(type).c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_dart_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << prefix << ".write(oprot);" << endl; } /** * Serializes a container by writing its size then the elements. * * @param ttype The type of container * @param prefix String prefix for fields */ void t_dart_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { indent(out); scope_up(out, ""); if (ttype->is_map()) { string iter = tmp("_key"); indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix << ".length));" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix << ".length));" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListBegin(new TList(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length));" << endl; } string iter = tmp("elem"); if (ttype->is_map()) { indent(out) << "for (var " << iter << " in " << prefix << ".keys)"; } else if (ttype->is_set() || ttype->is_list()) { indent(out) << "for (var " << iter << " in " << prefix << ")"; } scope_up(out); if (ttype->is_map()) { generate_serialize_map_element(out, (t_map*)ttype, iter, prefix); } else if (ttype->is_set()) { generate_serialize_set_element(out, (t_set*)ttype, iter); } else if (ttype->is_list()) { generate_serialize_list_element(out, (t_list*)ttype, iter); } scope_down(out); if (ttype->is_map()) { indent(out) << "oprot.writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListEnd();" << endl; } scope_down(out); } /** * Serializes the members of a map. */ void t_dart_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map) { t_field kfield(tmap->get_key_type(), iter); generate_serialize_field(out, &kfield, ""); t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); generate_serialize_field(out, &vfield, ""); } /** * Serializes the members of a set. */ void t_dart_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Serializes the members of a list. */ void t_dart_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Returns a Dart type name * * @param ttype The type * @return Dart type name, i.e. Map */ string t_dart_generator::type_name(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_base_type()) { return base_type_name((t_base_type*)ttype); } else if (ttype->is_enum()) { return "int"; } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; return "Map<" + type_name(tmap->get_key_type()) + ", " + type_name(tmap->get_val_type()) + ">"; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; return "Set<" + type_name(tset->get_elem_type()) + ">"; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; return "List<" + type_name(tlist->get_elem_type()) + ">"; } return get_ttype_class_name(ttype); } /** * Returns the Dart type that corresponds to the thrift type. * * @param tbase The base type */ string t_dart_generator::base_type_name(t_base_type* type) { t_base_type::t_base tbase = type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: if (type->is_binary()) { return "Uint8List"; } else { return "String"; } case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "int"; case t_base_type::TYPE_DOUBLE: return "double"; default: throw "compiler error: no Dart name for base type " + t_base_type::t_base_name(tbase); } } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type */ string t_dart_generator::declare_field(t_field* tfield, bool init) { string field_name = get_member_name(tfield->get_name()); string result = type_name(tfield->get_type()) + " " + field_name; if (init) { t_type* ttype = get_true_type(tfield->get_type()); if (ttype->is_base_type() && tfield->get_value() != nullptr) { std:: ofstream dummy; result += " = " + render_const_value(dummy, field_name, ttype, tfield->get_value()); } else if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: result += " = null"; break; case t_base_type::TYPE_BOOL: result += " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = 0.0"; break; default: throw "compiler error: unhandled type"; } } else if (ttype->is_enum()) { result += " = 0"; } else if (ttype->is_container()) { result += " = new " + type_name(ttype) + "()"; } else { result += " = new " + type_name(ttype) + "()"; ; } } return result + ";"; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_dart_generator::function_signature(t_function* tfunction) { std::string arguments = argument_list(tfunction->get_arglist()); std::string returntype; if (tfunction->get_returntype()->is_void()) { returntype = "Future"; } else { returntype = "Future<" + type_name(tfunction->get_returntype()) + ">"; } std::string result = returntype + " " + get_member_name(tfunction->get_name()) + "(" + arguments + ")"; return result; } /** * Renders a comma separated field list, with type names */ string t_dart_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } string field_name = get_member_name((*f_iter)->get_name()); result += type_name((*f_iter)->get_type()) + " " + field_name; } return result; } /** * Converts the parse type to a C++ enum string for the given type. */ string t_dart_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.STRING"; case t_base_type::TYPE_BOOL: return "TType.BOOL"; case t_base_type::TYPE_I8: return "TType.BYTE"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; default: break; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_list()) { return "TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_dart_generator::init_value(t_field* field) { // Do not initialize optional fields if (field->get_req() == t_field::T_OPTIONAL) { return ""; } t_type* ttype = field->get_type(); // Get the actual type for a typedef if (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } // Only consider base types for default initialization if (!ttype->is_base_type()) { return ""; } t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); // Initialize bools, ints, and doubles with sane defaults string result; switch (tbase) { case t_base_type::TYPE_BOOL: result = " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result = " = 0"; break; case t_base_type::TYPE_DOUBLE: result = " = 0.0"; break; case t_base_type::TYPE_VOID: case t_base_type::TYPE_STRING: result = ""; break; default: throw "compiler error: unhandled type"; } return result; } std::string t_dart_generator::get_cap_name(std::string name) { name[0] = toupper(name[0]); return name; } std::string t_dart_generator::get_member_name(std::string name) { name[0] = tolower(name[0]); return name; } std::string t_dart_generator::get_args_class_name(std::string name) { return name + "_args"; } std::string t_dart_generator::get_result_class_name(std::string name) { return name + "_result"; } std::string t_dart_generator::get_file_name(std::string name) { // e.g. change APIForFileIO to api_for_file_io string ret; const char* tmp = name.c_str(); bool is_prev_lc = true; bool is_current_lc = tmp[0] == tolower(tmp[0]); bool is_next_lc = false; for (unsigned int i = 0; i < name.length(); i++) { char lc = tolower(tmp[i]); if (i == name.length() - 1) { is_next_lc = false; } else { is_next_lc = (tmp[i+1] == tolower(tmp[i+1])); } if (i != 0 && !is_current_lc && (is_prev_lc || is_next_lc)) { ret += "_"; } ret += lc; is_prev_lc = is_current_lc; is_current_lc = is_next_lc; } return ret; } std::string t_dart_generator::get_constants_class_name(std::string name) { // e.g. change my_great_model to MyGreatModelConstants string ret; const char* tmp = name.c_str(); bool is_prev_underscore = true; for (unsigned int i = 0; i < name.length(); i++) { if (tmp[i] == '_') { is_prev_underscore = true; } else { if (is_prev_underscore) { ret += toupper(tmp[i]); } else { ret += tmp[i]; } is_prev_underscore = false; } } return ret + "Constants"; } string t_dart_generator::constant_name(string name) { string constant_name; bool is_first = true; bool was_previous_char_upper = false; for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { constant_name += '_'; } constant_name += toupper(character); is_first = false; was_previous_char_upper = is_upper; } return constant_name; } /** * Emits a doc comment if the provided object has a doc in Thrift */ void t_dart_generator::generate_dart_doc(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_docstring_comment(out, "", "/// ", tdoc->get_doc(), ""); } } /** * Emits a doc comment if the provided function object has a doc in Thrift */ void t_dart_generator::generate_dart_doc(ostream& out, t_function* tfunction) { if (tfunction->has_doc()) { stringstream ss; ss << tfunction->get_doc(); const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; string field_name = get_member_name(p->get_name()); ss << "\n@param " << field_name; if (p->has_doc()) { ss << " " << p->get_doc(); } } generate_docstring_comment(out, "", "/// ", ss.str(), ""); } } std::string t_dart_generator::generate_isset_check(t_field* field) { string field_name = get_member_name(field->get_name()); return generate_isset_check(field_name); } std::string t_dart_generator::generate_isset_check(std::string field_name) { return "is" + get_cap_name("set") + get_cap_name(field_name) + "()"; } void t_dart_generator::generate_isset_set(ostream& out, t_field* field) { if (!type_can_be_null(field->get_type())) { string field_name = get_member_name(field->get_name()); indent(out) << "this.__isset_" << field_name << " = true;" << endl; } } std::string t_dart_generator::get_ttype_class_name(t_type* ttype) { if (program_ == ttype->get_program()) { return ttype->get_name(); } else { string named_import = "t_" + find_library_name(ttype->get_program()); return named_import + "." + ttype->get_name(); } } std::string t_dart_generator::display_name() const { return "Dart"; } THRIFT_REGISTER_GENERATOR( dart, "Dart", " library_name: Optional override for library name.\n" " library_prefix: Generate code that can be used within an existing library.\n" " Use a dot-separated string, e.g. \"my_parent_lib.src.gen\"\n" " pubspec_lib: Optional override for thrift lib dependency in pubspec.yaml,\n" " e.g. \"thrift: 0.x.x\". Use a pipe delimiter to separate lines,\n" " e.g. \"thrift:| git:| url: git@foo.com\"\n" ) thrift-0.19.0/compiler/cpp/src/thrift/generate/t_html_generator.cc0000644000000000000000000010573714370300523025232 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_generator.h" #include "thrift/generate/t_html_generator.h" using std::map; using std::ofstream; using std::ostringstream; using std::pair; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes enum input_type { INPUT_UNKNOWN, INPUT_UTF8, INPUT_PLAIN }; /** * HTML code generator * * mostly copy/pasting/tweaking from mcslee's work. */ class t_html_generator : public t_generator { public: t_html_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; standalone_ = false; unsafe_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("standalone") == 0) { standalone_ = true; } else if( iter->first.compare("noescape") == 0) { unsafe_ = true; } else { throw "unknown option html:" + iter->first; } } out_dir_base_ = "gen-html"; input_type_ = INPUT_UNKNOWN; escape_.clear(); escape_['&'] = "&"; escape_['<'] = "<"; escape_['>'] = ">"; escape_['"'] = """; escape_['\''] = "'"; init_allowed__markup(); } std::string display_name() const override; void generate_program() override; void generate_program_toc(); void generate_program_toc_row(t_program* tprog); void generate_program_toc_rows(t_program* tprog, std::vector& finished); void generate_index(); std::string escape_html(std::string const& str); std::string escape_html_tags(std::string const& str); void generate_css(); void generate_css_content(std::ostream& f_target); void generate_style_tag(); std::string make_file_link(std::string name); bool is_utf8_sequence(std::string const& str, size_t firstpos); void detect_input_encoding(std::string const& str, size_t firstpos); void init_allowed__markup(); /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_service(t_service* tservice) override; void generate_xception(t_struct* txception) override; void print_doc(t_doc* tdoc); int print_type(t_type* ttype); void print_const_value(t_type* type, t_const_value* tvalue); void print_fn_args_doc(t_function* tfunction); private: ofstream_with_content_based_conditional_update f_out_; std::string current_file_; input_type input_type_; std::map allowed_markup; bool standalone_; bool unsafe_; }; /** * Emits the Table of Contents links at the top of the module's page */ void t_html_generator::generate_program_toc() { f_out_ << "" << "" << endl; generate_program_toc_row(program_); f_out_ << "
ModuleServicesData typesConstants
" << endl; } /** * Recurses through from the provided program and generates a ToC row * for each discovered program exactly once by maintaining the list of * completed rows in 'finished' */ void t_html_generator::generate_program_toc_rows(t_program* tprog, std::vector& finished) { for (auto & iter : finished) { if (tprog->get_path() == iter->get_path()) { return; } } finished.push_back(tprog); generate_program_toc_row(tprog); vector includes = tprog->get_includes(); for (auto & include : includes) { generate_program_toc_rows(include, finished); } } /** * Emits the Table of Contents links at the top of the module's page */ void t_html_generator::generate_program_toc_row(t_program* tprog) { string fname = tprog->get_name() + ".html"; f_out_ << "" << endl << "" << tprog->get_name() << ""; if (!tprog->get_services().empty()) { vector services = tprog->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { string name = get_service_name(*sv_iter); f_out_ << "
" << name << "
" << endl; f_out_ << "
    " << endl; map fn_html; vector functions = (*sv_iter)->get_functions(); vector::iterator fn_iter; for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) { string fn_name = (*fn_iter)->get_name(); string html = "
  • " + fn_name + "
  • "; fn_html.insert(pair(fn_name, html)); } for (auto & html_iter : fn_html) { f_out_ << html_iter.second << endl; } f_out_ << "
" << endl; } } f_out_ << "" << endl << ""; map data_types; if (!tprog->get_enums().empty()) { vector enums = tprog->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { string name = (*en_iter)->get_name(); // f_out_ << "" << name // << "
" << endl; string html = "" + name + ""; data_types.insert(pair(name, html)); } } if (!tprog->get_typedefs().empty()) { vector typedefs = tprog->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { string name = (*td_iter)->get_symbolic(); // f_out_ << "" << name // << "
" << endl; string html = "" + name + ""; data_types.insert(pair(name, html)); } } if (!tprog->get_objects().empty()) { vector objects = tprog->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { string name = (*o_iter)->get_name(); // f_out_ << "" << name //<< "
" << endl; string html = "" + name + ""; data_types.insert(pair(name, html)); } } for (auto & data_type : data_types) { f_out_ << data_type.second << "
" << endl; } f_out_ << "" << endl << ""; if (!tprog->get_consts().empty()) { map const_html; vector consts = tprog->get_consts(); vector::iterator con_iter; for (con_iter = consts.begin(); con_iter != consts.end(); ++con_iter) { string name = (*con_iter)->get_name(); string html = "" + name + ""; const_html.insert(pair(name, html)); } for (auto & con_iter : const_html) { f_out_ << con_iter.second << "
" << endl; } } f_out_ << "" << endl << ""; } /** * Prepares for file generation by opening up the necessary file output * stream. */ void t_html_generator::generate_program() { // Make output directory MKDIR(get_out_dir().c_str()); current_file_ = program_->get_name() + ".html"; string fname = get_out_dir() + current_file_; f_out_.open(fname.c_str()); f_out_ << "" << endl; f_out_ << "" << endl; f_out_ << "" << endl; f_out_ << "" << endl; generate_style_tag(); f_out_ << "Thrift module: " << program_->get_name() << "" << endl << "
" << endl << "

Thrift module: " << program_->get_name() << "

" << endl; print_doc(program_); generate_program_toc(); if (!program_->get_consts().empty()) { f_out_ << "

Constants

" << endl; vector consts = program_->get_consts(); f_out_ << ""; f_out_ << "" << endl; generate_consts(consts); f_out_ << "
ConstantTypeValue
"; } if (!program_->get_enums().empty()) { f_out_ << "

Enumerations

" << endl; // Generate enums vector enums = program_->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { generate_enum(*en_iter); } } if (!program_->get_typedefs().empty()) { f_out_ << "

Type declarations

" << endl; // Generate typedefs vector typedefs = program_->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { generate_typedef(*td_iter); } } if (!program_->get_objects().empty()) { f_out_ << "

Data structures

" << endl; // Generate structs and exceptions in declared order vector objects = program_->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { if ((*o_iter)->is_xception()) { generate_xception(*o_iter); } else { generate_struct(*o_iter); } } } if (!program_->get_services().empty()) { f_out_ << "

Services

" << endl; // Generate services vector services = program_->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { service_name_ = get_service_name(*sv_iter); generate_service(*sv_iter); } } f_out_ << "
" << endl; f_out_.close(); generate_index(); generate_css(); } /** * Emits the index.html file for the recursive set of Thrift programs */ void t_html_generator::generate_index() { current_file_ = "index.html"; string index_fname = get_out_dir() + current_file_; f_out_.open(index_fname.c_str()); f_out_ << "" << endl << "" << endl; generate_style_tag(); f_out_ << "All Thrift declarations" << endl << "
" << endl << "

All Thrift declarations

" << endl; f_out_ << "" << "" << endl; vector programs; generate_program_toc_rows(program_, programs); f_out_ << "
ModuleServicesData typesConstants
" << endl; f_out_ << "
" << endl; f_out_.close(); } void t_html_generator::generate_css() { if (!standalone_) { current_file_ = "style.css"; string css_fname = get_out_dir() + current_file_; f_out_.open(css_fname.c_str()); generate_css_content(f_out_); f_out_.close(); } } void t_html_generator::generate_css_content(std::ostream& f_target) { f_target << BOOTSTRAP_CSS() << endl; f_target << "/* Auto-generated CSS for generated Thrift docs */" << endl; f_target << "h3, h4 { margin-bottom: 6px; }" << endl; f_target << "div.definition { border: 1px solid #CCC; margin-bottom: 10px; padding: 10px; }" << endl; f_target << "div.extends { margin: -0.5em 0 1em 5em }" << endl; f_target << "td { vertical-align: top; }" << endl; f_target << "table { empty-cells: show; }" << endl; f_target << "code { line-height: 20px; }" << endl; f_target << ".table-bordered th, .table-bordered td { border-bottom: 1px solid #DDDDDD; }" << endl; } /** * Generates the CSS tag. * Depending on "standalone", either a CSS file link (default), or the entire CSS is embedded * inline. */ void t_html_generator::generate_style_tag() { if (!standalone_) { f_out_ << "" << endl; } else { f_out_ << "" << endl; } } /** * Returns the target file for a link * The returned string is empty, whenever filename refers to the current file. */ std::string t_html_generator::make_file_link(std::string filename) { return (current_file_.compare(filename) != 0) ? filename : ""; } /** * If the provided documentable object has documentation attached, this * will emit it to the output stream in HTML format. */ void t_html_generator::print_doc(t_doc* tdoc) { if (tdoc->has_doc()) { if (unsafe_) { f_out_ << tdoc->get_doc() << "
"; } else { f_out_ << "
" << escape_html(tdoc->get_doc()) << "

"; } } } bool t_html_generator::is_utf8_sequence(std::string const& str, size_t firstpos) { // leading char determines the length of the sequence unsigned char c = str.at(firstpos); int count = 0; if ((c & 0xE0) == 0xC0) { count = 1; } else if ((c & 0xF0) == 0xE0) { count = 2; } else if ((c & 0xF8) == 0xF0) { count = 3; } else if ((c & 0xFC) == 0xF8) { count = 4; } else if ((c & 0xFE) == 0xFC) { count = 5; } else { // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 leading byte", c, int(c)); return false; // no UTF-8 } // following chars size_t pos = firstpos + 1; while ((pos < str.length()) && (0 < count)) { c = str.at(pos); if ((c & 0xC0) != 0x80) { // pdebug("UTF-8 test: char '%c' (%d) is not a valid UTF-8 following byte", c, int(c)); return false; // no UTF-8 } --count; ++pos; } // true if the sequence is complete return (0 == count); } void t_html_generator::detect_input_encoding(std::string const& str, size_t firstpos) { if (is_utf8_sequence(str, firstpos)) { pdebug("Input seems to be already UTF-8 encoded"); input_type_ = INPUT_UTF8; return; } // fallback pwarning(1, "Input is not UTF-8, treating as plain ANSI"); input_type_ = INPUT_PLAIN; } void t_html_generator::init_allowed__markup() { allowed_markup.clear(); // standalone tags allowed_markup["br"] = 1; allowed_markup["br/"] = 1; allowed_markup["img"] = 1; // paired tags allowed_markup["b"] = 1; allowed_markup["/b"] = 1; allowed_markup["u"] = 1; allowed_markup["/u"] = 1; allowed_markup["i"] = 1; allowed_markup["/i"] = 1; allowed_markup["s"] = 1; allowed_markup["/s"] = 1; allowed_markup["big"] = 1; allowed_markup["/big"] = 1; allowed_markup["small"] = 1; allowed_markup["/small"] = 1; allowed_markup["sup"] = 1; allowed_markup["/sup"] = 1; allowed_markup["sub"] = 1; allowed_markup["/sub"] = 1; allowed_markup["pre"] = 1; allowed_markup["/pre"] = 1; allowed_markup["tt"] = 1; allowed_markup["/tt"] = 1; allowed_markup["ul"] = 1; allowed_markup["/ul"] = 1; allowed_markup["ol"] = 1; allowed_markup["/ol"] = 1; allowed_markup["li"] = 1; allowed_markup["/li"] = 1; allowed_markup["a"] = 1; allowed_markup["/a"] = 1; allowed_markup["p"] = 1; allowed_markup["/p"] = 1; allowed_markup["code"] = 1; allowed_markup["/code"] = 1; allowed_markup["dl"] = 1; allowed_markup["/dl"] = 1; allowed_markup["dt"] = 1; allowed_markup["/dt"] = 1; allowed_markup["dd"] = 1; allowed_markup["/dd"] = 1; allowed_markup["h1"] = 1; allowed_markup["/h1"] = 1; allowed_markup["h2"] = 1; allowed_markup["/h2"] = 1; allowed_markup["h3"] = 1; allowed_markup["/h3"] = 1; allowed_markup["h4"] = 1; allowed_markup["/h4"] = 1; allowed_markup["h5"] = 1; allowed_markup["/h5"] = 1; allowed_markup["h6"] = 1; allowed_markup["/h6"] = 1; } std::string t_html_generator::escape_html_tags(std::string const& str) { std::ostringstream result; unsigned char c = '?'; size_t lastpos; size_t firstpos = 0; while (firstpos < str.length()) { // look for non-ASCII char lastpos = firstpos; while (lastpos < str.length()) { c = str.at(lastpos); if (('<' == c) || ('>' == c)) { break; } ++lastpos; } // copy what we got so far if (lastpos > firstpos) { result << str.substr(firstpos, lastpos - firstpos); firstpos = lastpos; } // reached the end? if (firstpos >= str.length()) { break; } // tag end without corresponding begin ++firstpos; if ('>' == c) { result << ">"; continue; } // extract the tag std::ostringstream tagstream; while (firstpos < str.length()) { c = str.at(firstpos); ++firstpos; if ('<' == c) { tagstream << "<"; // nested begin? } else if ('>' == c) { break; } else { tagstream << c; // not very efficient, but tags should be quite short } } // we allow for several markup in docstrings, all else will become escaped string tag_content = tagstream.str(); string tag_key = tag_content; size_t first_white = tag_key.find_first_of(" \t\f\v\n\r"); if (first_white != string::npos) { tag_key.erase(first_white); } for (char & i : tag_key) { i = tolower(i); } if (allowed_markup.find(tag_key) != allowed_markup.end()) { result << "<" << tag_content << ">"; } else { result << "<" << tagstream.str() << ">"; pverbose("illegal markup <%s> in doc-comment\n", tag_key.c_str()); } } return result.str(); } std::string t_html_generator::escape_html(std::string const& str) { // the generated HTML header says it is UTF-8 encoded // if UTF-8 input has been detected before, we don't need to change anything if (input_type_ == INPUT_UTF8) { return escape_html_tags(str); } // convert unsafe chars to their &#; equivalent std::ostringstream result; unsigned char c = '?'; unsigned int ic = 0; size_t lastpos; size_t firstpos = 0; while (firstpos < str.length()) { // look for non-ASCII char lastpos = firstpos; while (lastpos < str.length()) { c = str.at(lastpos); ic = c; if ((32 > ic) || (127 < ic)) { break; } ++lastpos; } // copy what we got so far if (lastpos > firstpos) { result << str.substr(firstpos, lastpos - firstpos); firstpos = lastpos; } // reached the end? if (firstpos >= str.length()) { break; } // some control code? if (ic <= 31) { switch (c) { case '\r': case '\n': case '\t': result << c; break; default: // silently consume all other ctrl chars break; } ++firstpos; continue; } // reached the end? if (firstpos >= str.length()) { break; } // try to detect input encoding if (input_type_ == INPUT_UNKNOWN) { detect_input_encoding(str, firstpos); if (input_type_ == INPUT_UTF8) { lastpos = str.length(); result << str.substr(firstpos, lastpos - firstpos); break; } } // convert the character to something useful based on the detected encoding switch (input_type_) { case INPUT_PLAIN: result << "&#" << ic << ";"; ++firstpos; break; default: throw "Unexpected or unrecognized input encoding"; } } return escape_html_tags(result.str()); } /** * Prints out the provided type in HTML */ int t_html_generator::print_type(t_type* ttype) { std::string::size_type len = 0; f_out_ << ""; if (ttype->is_container()) { if (ttype->is_list()) { f_out_ << "list<"; len = 6 + print_type(((t_list*)ttype)->get_elem_type()); f_out_ << ">"; } else if (ttype->is_set()) { f_out_ << "set<"; len = 5 + print_type(((t_set*)ttype)->get_elem_type()); f_out_ << ">"; } else if (ttype->is_map()) { f_out_ << "map<"; len = 5 + print_type(((t_map*)ttype)->get_key_type()); f_out_ << ", "; len += print_type(((t_map*)ttype)->get_val_type()); f_out_ << ">"; } } else if (ttype->is_base_type()) { f_out_ << (ttype->is_binary() ? "binary" : ttype->get_name()); len = ttype->get_name().size(); } else { string prog_name = ttype->get_program()->get_name(); string type_name = ttype->get_name(); f_out_ << "
is_typedef()) { f_out_ << "Typedef_"; } else if (ttype->is_struct() || ttype->is_xception()) { f_out_ << "Struct_"; } else if (ttype->is_enum()) { f_out_ << "Enum_"; } else if (ttype->is_service()) { f_out_ << "Svc_"; } f_out_ << type_name << "\">"; len = type_name.size(); if (ttype->get_program() != program_) { f_out_ << prog_name << "."; len += prog_name.size() + 1; } f_out_ << type_name << ""; } f_out_ << ""; return (int)len; } /** * Prints out an HTML representation of the provided constant value */ void t_html_generator::print_const_value(t_type* type, t_const_value* tvalue) { // if tvalue is an identifier, the constant content is already shown elsewhere if (tvalue->get_type() == t_const_value::CV_IDENTIFIER) { string fname = program_->get_name() + ".html"; string name = escape_html(tvalue->get_identifier()); f_out_ << "" + name + ""; return; } t_type* truetype = type; while (truetype->is_typedef()) { truetype = ((t_typedef*)truetype)->get_type(); } bool first = true; if (truetype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: f_out_ << '"' << escape_html(get_escaped_string(tvalue)) << '"'; break; case t_base_type::TYPE_BOOL: f_out_ << ((tvalue->get_integer() != 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_I16: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_I32: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_I64: f_out_ << tvalue->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (tvalue->get_type() == t_const_value::CV_INTEGER) { f_out_ << tvalue->get_integer(); } else { f_out_ << tvalue->get_double(); } break; default: f_out_ << "UNKNOWN BASE TYPE"; break; } } else if (truetype->is_enum()) { f_out_ << escape_html(truetype->get_name()) << "." << escape_html(tvalue->get_identifier_name()); } else if (truetype->is_struct() || truetype->is_xception()) { f_out_ << "{ "; const vector& fields = ((t_struct*)truetype)->get_members(); vector::const_iterator f_iter; const map& val = tvalue->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + truetype->get_name() + " has no field " + v_iter->first->get_string(); } if (!first) { f_out_ << ", "; } first = false; f_out_ << escape_html(v_iter->first->get_string()) << " = "; print_const_value(field_type, v_iter->second); } f_out_ << " }"; } else if (truetype->is_map()) { f_out_ << "{ "; map map_elems = tvalue->get_map(); map::iterator map_iter; for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_map*)truetype)->get_key_type(), map_iter->first); f_out_ << " = "; print_const_value(((t_map*)truetype)->get_val_type(), map_iter->second); } f_out_ << " }"; } else if (truetype->is_list()) { f_out_ << "{ "; vector list_elems = tvalue->get_list(); ; vector::iterator list_iter; for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_list*)truetype)->get_elem_type(), *list_iter); } f_out_ << " }"; } else if (truetype->is_set()) { f_out_ << "{ "; vector list_elems = tvalue->get_list(); ; vector::iterator list_iter; for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_set*)truetype)->get_elem_type(), *list_iter); } f_out_ << " }"; } else { f_out_ << "UNKNOWN TYPE"; } } /** * Prints out documentation for arguments/exceptions of a function, if any documentation has been * supplied. */ void t_html_generator::print_fn_args_doc(t_function* tfunction) { bool has_docs = false; vector args = tfunction->get_arglist()->get_members(); vector::iterator arg_iter = args.begin(); if (arg_iter != args.end()) { for (; arg_iter != args.end(); arg_iter++) { if ((*arg_iter)->has_doc() && !(*arg_iter)->get_doc().empty()) has_docs = true; } if (has_docs) { arg_iter = args.begin(); f_out_ << "

get_name() << "\">Parameters

" << endl; f_out_ << ""; f_out_ << ""; for (; arg_iter != args.end(); arg_iter++) { f_out_ << "" << endl; } f_out_ << "
NameDescription
" << (*arg_iter)->get_name(); f_out_ << ""; f_out_ << escape_html((*arg_iter)->get_doc()); f_out_ << "
"; } } has_docs = false; vector excepts = tfunction->get_xceptions()->get_members(); vector::iterator ex_iter = excepts.begin(); if (ex_iter != excepts.end()) { for (; ex_iter != excepts.end(); ex_iter++) { if ((*ex_iter)->has_doc() && !(*ex_iter)->get_doc().empty()) has_docs = true; } if (has_docs) { ex_iter = excepts.begin(); f_out_ << "

get_name() << "\">Exceptions

" << endl; f_out_ << ""; f_out_ << ""; for (; ex_iter != excepts.end(); ex_iter++) { f_out_ << "" << endl; } f_out_ << "
TypeDescription
" << (*ex_iter)->get_type()->get_name(); f_out_ << ""; f_out_ << escape_html((*ex_iter)->get_doc()); f_out_ << "
"; } } } /** * Generates a typedef. * * @param ttypedef The type definition */ void t_html_generator::generate_typedef(t_typedef* ttypedef) { string name = ttypedef->get_name(); f_out_ << "
"; f_out_ << "

Typedef: " << name << "

" << endl; f_out_ << "

Base type: "; print_type(ttypedef->get_type()); f_out_ << "

" << endl; print_doc(ttypedef); f_out_ << "
" << endl; } /** * Generates code for an enumerated type. * * @param tenum The enumeration */ void t_html_generator::generate_enum(t_enum* tenum) { string name = tenum->get_name(); f_out_ << "
"; f_out_ << "

Enumeration: " << name << "

" << endl; print_doc(tenum); vector values = tenum->get_constants(); vector::iterator val_iter; f_out_ << "
" << endl; for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) { f_out_ << "" << endl; } f_out_ << "
"; f_out_ << (*val_iter)->get_name(); f_out_ << ""; f_out_ << (*val_iter)->get_value(); f_out_ << "" << endl; print_doc((*val_iter)); f_out_ << "
" << endl; } /** * Generates a constant value */ void t_html_generator::generate_const(t_const* tconst) { string name = tconst->get_name(); f_out_ << "" << name << ""; print_type(tconst->get_type()); f_out_ << ""; print_const_value(tconst->get_type(), tconst->get_value()); f_out_ << ""; if (tconst->has_doc()) { f_out_ << "
"; print_doc(tconst); f_out_ << "
"; } } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_html_generator::generate_struct(t_struct* tstruct) { string name = tstruct->get_name(); f_out_ << "
"; f_out_ << "

"; if (tstruct->is_xception()) { f_out_ << "Exception: "; } else if (tstruct->is_union()) { f_out_ << "Union: "; } else { f_out_ << "Struct: "; } f_out_ << name << "

" << endl; vector members = tstruct->get_members(); vector::iterator mem_iter = members.begin(); f_out_ << ""; f_out_ << "" << endl; for (; mem_iter != members.end(); mem_iter++) { f_out_ << "" << endl; } f_out_ << "
KeyFieldTypeDescriptionRequirednessDefault value
" << (*mem_iter)->get_key() << ""; f_out_ << (*mem_iter)->get_name(); f_out_ << ""; print_type((*mem_iter)->get_type()); f_out_ << ""; f_out_ << escape_html((*mem_iter)->get_doc()); f_out_ << ""; if ((*mem_iter)->get_req() == t_field::T_OPTIONAL) { f_out_ << "optional"; } else if ((*mem_iter)->get_req() == t_field::T_REQUIRED) { f_out_ << "required"; } else { f_out_ << "default"; } f_out_ << ""; t_const_value* default_val = (*mem_iter)->get_value(); if (default_val != nullptr) { f_out_ << ""; print_const_value((*mem_iter)->get_type(), default_val); f_out_ << ""; } f_out_ << "

"; print_doc(tstruct); f_out_ << "
"; } /** * Exceptions are special structs * * @param tstruct The struct definition */ void t_html_generator::generate_xception(t_struct* txception) { generate_struct(txception); } /** * Generates the HTML block for a Thrift service. * * @param tservice The service definition */ void t_html_generator::generate_service(t_service* tservice) { f_out_ << "

Service: " << service_name_ << "

" << endl; if (tservice->get_extends()) { f_out_ << "
extends "; print_type(tservice->get_extends()); f_out_ << "
\n"; } print_doc(tservice); vector functions = tservice->get_functions(); vector::iterator fn_iter = functions.begin(); for (; fn_iter != functions.end(); fn_iter++) { string fn_name = (*fn_iter)->get_name(); f_out_ << "
"; f_out_ << "

Function: " << service_name_ << "." << fn_name << "

" << endl; f_out_ << "
";
    std::string::size_type offset = print_type((*fn_iter)->get_returntype());
    bool first = true;
    f_out_ << " " << fn_name << "(";
    offset += fn_name.size() + 2;
    vector args = (*fn_iter)->get_arglist()->get_members();
    vector::iterator arg_iter = args.begin();
    for (; arg_iter != args.end(); arg_iter++) {
      if (!first) {
        f_out_ << "," << endl;
        for (std::string::size_type i = 0; i < offset; ++i) {
          f_out_ << " ";
        }
      }
      first = false;
      print_type((*arg_iter)->get_type());
      f_out_ << " " << (*arg_iter)->get_name();
      if ((*arg_iter)->get_value() != nullptr) {
        f_out_ << " = ";
        print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value());
      }
    }
    f_out_ << ")" << endl;
    first = true;
    vector excepts = (*fn_iter)->get_xceptions()->get_members();
    vector::iterator ex_iter = excepts.begin();
    if (ex_iter != excepts.end()) {
      f_out_ << "    throws ";
      for (; ex_iter != excepts.end(); ex_iter++) {
        if (!first) {
          f_out_ << ", ";
        }
        first = false;
        print_type((*ex_iter)->get_type());
      }
      f_out_ << endl;
    }
    f_out_ << "
"; print_doc(*fn_iter); print_fn_args_doc(*fn_iter); f_out_ << "
"; } } std::string t_html_generator::display_name() const { return "HTML"; } THRIFT_REGISTER_GENERATOR( html, "HTML", " standalone: Self-contained mode, includes all CSS in the HTML files.\n" " Generates no style.css file, but HTML files will be larger.\n" " noescape: Do not escape html in doc text.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_rb_generator.cc0000644000000000000000000012336214370300523024663 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ofstream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * A subclass of std::ofstream that includes indenting functionality. */ class t_rb_ofstream : public std::ofstream { private: int indent_; public: t_rb_ofstream() : std::ofstream(), indent_(0) {} explicit t_rb_ofstream(const char* filename, ios_base::openmode mode = ios_base::out, int indent = 0) : std::ofstream(filename, mode), indent_(indent) {} t_rb_ofstream& indent() { for (int i = 0; i < indent_; ++i) { *this << " "; } return *this; } void indent_up() { indent_++; } void indent_down() { indent_--; } }; /** * Ruby code generator. * */ class t_rb_generator : public t_oop_generator { public: t_rb_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; require_rubygems_ = false; namespaced_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("rubygems") == 0) { require_rubygems_ = true; } else if( iter->first.compare("namespaced") == 0) { namespaced_ = true; } else { throw "unknown option ruby:" + iter->first; } } out_dir_base_ = "gen-rb"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_forward_declaration(t_struct* tstruct) override; void generate_union(t_struct* tunion); void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; t_rb_ofstream& render_const_value(t_rb_ofstream& out, t_type* type, t_const_value* value); /** * Struct generation code */ void generate_rb_struct_declaration(t_rb_ofstream& out, t_struct* tstruct, bool is_exception); void generate_rb_struct(t_rb_ofstream& out, t_struct* tstruct, bool is_exception); void generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct); void generate_rb_union(t_rb_ofstream& out, t_struct* tstruct, bool is_exception); void generate_rb_union_validator(t_rb_ofstream& out, t_struct* tstruct); void generate_rb_function_helpers(t_function* tfunction); void generate_rb_simple_constructor(t_rb_ofstream& out, t_struct* tstruct); void generate_rb_simple_exception_constructor(t_rb_ofstream& out, t_struct* tstruct); void generate_field_constants(t_rb_ofstream& out, t_struct* tstruct); void generate_field_constructors(t_rb_ofstream& out, t_struct* tstruct); void generate_field_defns(t_rb_ofstream& out, t_struct* tstruct); void generate_field_data(t_rb_ofstream& out, t_type* field_type, const std::string& field_name, t_const_value* field_value, bool optional); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); /** * Serialization constructs */ void generate_deserialize_field(t_rb_ofstream& out, t_field* tfield, std::string prefix = "", bool inclass = false); void generate_deserialize_struct(t_rb_ofstream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(t_rb_ofstream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(t_rb_ofstream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(t_rb_ofstream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(t_rb_ofstream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(t_rb_ofstream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(t_rb_ofstream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(t_rb_ofstream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(t_rb_ofstream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(t_rb_ofstream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(t_rb_ofstream& out, t_list* tlist, std::string iter); void generate_rdoc(t_rb_ofstream& out, t_doc* tdoc); /** * Helper rendering functions */ std::string rb_autogen_comment(); std::string render_require_thrift(); std::string render_includes(); std::string declare_field(t_field* tfield); std::string type_name(const t_type* ttype); std::string full_type_name(const t_type* ttype); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string rb_namespace_to_path_prefix(std::string rb_namespace); std::vector ruby_modules(const t_program* p) { std::string ns = p->get_namespace("rb"); std::vector modules; if (ns.empty()) { return modules; } std::string::iterator pos = ns.begin(); while (true) { std::string::iterator delim = std::find(pos, ns.end(), '.'); modules.push_back(capitalize(std::string(pos, delim))); pos = delim; if (pos == ns.end()) { break; } ++pos; } return modules; } void begin_namespace(t_rb_ofstream&, std::vector); void end_namespace(t_rb_ofstream&, std::vector); private: /** * File streams */ t_rb_ofstream f_types_; t_rb_ofstream f_consts_; t_rb_ofstream f_service_; std::string namespace_dir_; std::string require_prefix_; /** If true, add a "require 'rubygems'" line to the top of each gen-rb file. */ bool require_rubygems_; /** If true, generate files in idiomatic namespaced directories. */ bool namespaced_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_rb_generator::init_generator() { string subdir = get_out_dir(); // Make output directory MKDIR(subdir.c_str()); if (namespaced_) { require_prefix_ = rb_namespace_to_path_prefix(program_->get_namespace("rb")); string dir = require_prefix_; string::size_type loc; while ((loc = dir.find("/")) != string::npos) { subdir = subdir + dir.substr(0, loc) + "/"; MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } } namespace_dir_ = subdir; // Make output file string f_types_name = namespace_dir_ + underscore(program_name_) + "_types.rb"; f_types_.open(f_types_name.c_str()); string f_consts_name = namespace_dir_ + underscore(program_name_) + "_constants.rb"; f_consts_.open(f_consts_name.c_str()); // Print header f_types_ << rb_autogen_comment() << endl << render_require_thrift() << render_includes() << endl; begin_namespace(f_types_, ruby_modules(program_)); f_consts_ << rb_autogen_comment() << endl << render_require_thrift() << "require '" << require_prefix_ << underscore(program_name_) << "_types'" << endl << endl; begin_namespace(f_consts_, ruby_modules(program_)); } /** * Renders the require of thrift itself, and possibly of the rubygems dependency. */ string t_rb_generator::render_require_thrift() { if (require_rubygems_) { return "require 'rubygems'\nrequire 'thrift'\n"; } else { return "require 'thrift'\n"; } } /** * Renders all the imports necessary for including another Thrift program */ string t_rb_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; for (auto include : includes) { if (namespaced_) { t_program* included = include; std::string included_require_prefix = rb_namespace_to_path_prefix(included->get_namespace("rb")); std::string included_name = included->get_name(); result += "require '" + included_require_prefix + underscore(included_name) + "_types'\n"; } else { result += "require '" + underscore(include->get_name()) + "_types'\n"; } } if (includes.size() > 0) { result += "\n"; } return result; } /** * Autogen'd comment */ string t_rb_generator::rb_autogen_comment() { return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n"; } /** * Closes the type files */ void t_rb_generator::close_generator() { // Close types file end_namespace(f_types_, ruby_modules(program_)); end_namespace(f_consts_, ruby_modules(program_)); f_types_.close(); f_consts_.close(); } /** * Generates a typedef. This is not done in Ruby, types are all implicit. * * @param ttypedef The type definition */ void t_rb_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Generates code for an enumerated type. Done using a class to scope * the values. * * @param tenum The enumeration */ void t_rb_generator::generate_enum(t_enum* tenum) { f_types_.indent() << "module " << capitalize(tenum->get_name()) << endl; f_types_.indent_up(); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); // Ruby class constants have to be capitalized... omg i am so on the fence // about languages strictly enforcing capitalization why can't we just all // agree and play nice. string name = capitalize((*c_iter)->get_name()); generate_rdoc(f_types_, *c_iter); f_types_.indent() << name << " = " << value << endl; } // Create a hash mapping values back to their names (as strings) since ruby has no native enum // type f_types_.indent() << "VALUE_MAP = {"; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { // Populate the hash int value = (*c_iter)->get_value(); if (c_iter != constants.begin()) f_types_ << ", "; f_types_ << value << " => \"" << capitalize((*c_iter)->get_name()) << "\""; } f_types_ << "}" << endl; // Create a set with valid values for this enum f_types_.indent() << "VALID_VALUES = Set.new(["; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { // Populate the set if (c_iter != constants.begin()) f_types_ << ", "; f_types_ << capitalize((*c_iter)->get_name()); } f_types_ << "]).freeze" << endl; f_types_.indent_down(); f_types_.indent() << "end" << endl << endl; } /** * Generate a constant value */ void t_rb_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); name[0] = toupper(name[0]); f_consts_.indent() << name << " = "; render_const_value(f_consts_, type, value) << endl << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ t_rb_ofstream& t_rb_generator::render_const_value(t_rb_ofstream& out, t_type* type, t_const_value* value) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << "%q\"" << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out.indent() << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << full_type_name(type) << ".new({" << endl; out.indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } out.indent(); render_const_value(out, g_type_string, v_iter->first) << " => "; render_const_value(out, field_type, v_iter->second) << "," << endl; } out.indent_down(); out.indent() << "})"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); out << "{" << endl; out.indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out.indent(); render_const_value(out, ktype, v_iter->first) << " => "; render_const_value(out, vtype, v_iter->second) << "," << endl; } out.indent_down(); out.indent() << "}"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } if (type->is_set()) { out << "Set.new([" << endl; } else { out << "[" << endl; } out.indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out.indent(); render_const_value(out, etype, *v_iter) << "," << endl; } out.indent_down(); if (type->is_set()) { out.indent() << "])"; } else { out.indent() << "]"; } } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out; } /** * Generates a ruby struct */ void t_rb_generator::generate_struct(t_struct* tstruct) { if (tstruct->is_union()) { generate_rb_union(f_types_, tstruct, false); } else { generate_rb_struct(f_types_, tstruct, false); } } /** * Generates the "forward declarations" for ruby structs. * These are simply a declaration of each class with proper inheritance. * The rest of the struct is still generated in generate_struct as has * always been the case. These declarations allow thrift to generate valid * ruby in cases where thrift structs rely on recursive definitions. */ void t_rb_generator::generate_forward_declaration(t_struct* tstruct) { generate_rb_struct_declaration(f_types_, tstruct, tstruct->is_xception()); } void t_rb_generator::generate_rb_struct_declaration(t_rb_ofstream& out, t_struct* tstruct, bool is_exception) { out.indent() << "class " << type_name(tstruct); if (tstruct->is_union()) { out << " < ::Thrift::Union"; } if (is_exception) { out << " < ::Thrift::Exception"; } out << "; end" << endl << endl; } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_rb_generator::generate_xception(t_struct* txception) { generate_rb_struct(f_types_, txception, true); } /** * Generates a ruby struct */ void t_rb_generator::generate_rb_struct(t_rb_ofstream& out, t_struct* tstruct, bool is_exception = false) { generate_rdoc(out, tstruct); out.indent() << "class " << type_name(tstruct); if (is_exception) { out << " < ::Thrift::Exception"; } out << endl; out.indent_up(); out.indent() << "include ::Thrift::Struct, ::Thrift::Struct_Union" << endl; if (is_exception) { generate_rb_simple_exception_constructor(out, tstruct); } generate_field_constants(out, tstruct); generate_field_defns(out, tstruct); generate_rb_struct_required_validator(out, tstruct); out.indent() << "::Thrift::Struct.generate_accessors self" << endl; out.indent_down(); out.indent() << "end" << endl << endl; } /** * Generates a ruby union */ void t_rb_generator::generate_rb_union(t_rb_ofstream& out, t_struct* tstruct, bool is_exception = false) { (void)is_exception; generate_rdoc(out, tstruct); out.indent() << "class " << type_name(tstruct) << " < ::Thrift::Union" << endl; out.indent_up(); out.indent() << "include ::Thrift::Struct_Union" << endl; generate_field_constructors(out, tstruct); generate_field_constants(out, tstruct); generate_field_defns(out, tstruct); generate_rb_union_validator(out, tstruct); out.indent() << "::Thrift::Union.generate_accessors self" << endl; out.indent_down(); out.indent() << "end" << endl << endl; } void t_rb_generator::generate_field_constructors(t_rb_ofstream& out, t_struct* tstruct) { out.indent() << "class << self" << endl; out.indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (f_iter != fields.begin()) { out << endl; } std::string field_name = (*f_iter)->get_name(); out.indent() << "def " << field_name << "(val)" << endl; out.indent() << " " << tstruct->get_name() << ".new(:" << field_name << ", val)" << endl; out.indent() << "end" << endl; } out.indent_down(); out.indent() << "end" << endl; out << endl; } void t_rb_generator::generate_rb_simple_exception_constructor(t_rb_ofstream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); if (members.size() == 1) { vector::const_iterator m_iter = members.begin(); if ((*m_iter)->get_type()->is_string()) { string name = (*m_iter)->get_name(); out.indent() << "def initialize(message=nil)" << endl; out.indent_up(); out.indent() << "super()" << endl; out.indent() << "self." << name << " = message" << endl; out.indent_down(); out.indent() << "end" << endl << endl; if (name != "message") { out.indent() << "def message; " << name << " end" << endl << endl; } } } } void t_rb_generator::generate_field_constants(t_rb_ofstream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { std::string field_name = (*f_iter)->get_name(); std::string cap_field_name = upcase_string(field_name); out.indent() << cap_field_name << " = " << (*f_iter)->get_key() << endl; } out << endl; } void t_rb_generator::generate_field_defns(t_rb_ofstream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; out.indent() << "FIELDS = {" << endl; out.indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (f_iter != fields.begin()) { out << "," << endl; } // generate the field docstrings within the FIELDS constant. no real better place... generate_rdoc(out, *f_iter); out.indent() << upcase_string((*f_iter)->get_name()) << " => "; generate_field_data(out, (*f_iter)->get_type(), (*f_iter)->get_name(), (*f_iter)->get_value(), (*f_iter)->get_req() == t_field::T_OPTIONAL); } out.indent_down(); out << endl; out.indent() << "}" << endl << endl; out.indent() << "def struct_fields; FIELDS; end" << endl << endl; } void t_rb_generator::generate_field_data(t_rb_ofstream& out, t_type* field_type, const std::string& field_name = "", t_const_value* field_value = nullptr, bool optional = false) { field_type = get_true_type(field_type); // Begin this field's defn out << "{:type => " << type_to_enum(field_type); if (!field_name.empty()) { out << ", :name => '" << field_name << "'"; } if (field_value != nullptr) { out << ", :default => "; render_const_value(out, field_type, field_value); } if (!field_type->is_base_type()) { if (field_type->is_struct() || field_type->is_xception()) { out << ", :class => " << full_type_name((t_struct*)field_type); } else if (field_type->is_list()) { out << ", :element => "; generate_field_data(out, ((t_list*)field_type)->get_elem_type()); } else if (field_type->is_map()) { out << ", :key => "; generate_field_data(out, ((t_map*)field_type)->get_key_type()); out << ", :value => "; generate_field_data(out, ((t_map*)field_type)->get_val_type()); } else if (field_type->is_set()) { out << ", :element => "; generate_field_data(out, ((t_set*)field_type)->get_elem_type()); } } else { if (((t_base_type*)field_type)->is_binary()) { out << ", :binary => true"; } } if (optional) { out << ", :optional => true"; } if (field_type->is_enum()) { out << ", :enum_class => " << full_type_name(field_type); } // End of this field's defn out << "}"; } void t_rb_generator::begin_namespace(t_rb_ofstream& out, vector modules) { for (auto & module : modules) { out.indent() << "module " << module << endl; out.indent_up(); } } void t_rb_generator::end_namespace(t_rb_ofstream& out, vector modules) { for (vector::reverse_iterator m_iter = modules.rbegin(); m_iter != modules.rend(); ++m_iter) { out.indent_down(); out.indent() << "end" << endl; } } /** * Generates a thrift service. * * @param tservice The service definition */ void t_rb_generator::generate_service(t_service* tservice) { string f_service_name = namespace_dir_ + underscore(service_name_) + ".rb"; f_service_.open(f_service_name.c_str()); f_service_ << rb_autogen_comment() << endl << render_require_thrift(); if (tservice->get_extends() != nullptr) { if (namespaced_) { f_service_ << "require '" << rb_namespace_to_path_prefix( tservice->get_extends()->get_program()->get_namespace("rb")) << underscore(tservice->get_extends()->get_name()) << "'" << endl; } else { f_service_ << "require '" << require_prefix_ << underscore(tservice->get_extends()->get_name()) << "'" << endl; } } f_service_ << "require '" << require_prefix_ << underscore(program_name_) << "_types'" << endl << endl; begin_namespace(f_service_, ruby_modules(tservice->get_program())); f_service_.indent() << "module " << capitalize(tservice->get_name()) << endl; f_service_.indent_up(); // Generate the three main parts of the service (well, two for now in PHP) generate_service_client(tservice); generate_service_server(tservice); generate_service_helpers(tservice); f_service_.indent_down(); f_service_.indent() << "end" << endl << endl; end_namespace(f_service_, ruby_modules(tservice->get_program())); // Close service file f_service_.close(); } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_rb_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; f_service_.indent() << "# HELPER FUNCTIONS AND STRUCTURES" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_rb_struct(f_service_, ts); generate_rb_function_helpers(*f_iter); } } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_rb_generator::generate_rb_function_helpers(t_function* tfunction) { t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_rb_struct(f_service_, &result); } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_rb_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = full_type_name(tservice->get_extends()); extends_client = " < " + extends + "::Client "; } f_service_.indent() << "class Client" << extends_client << endl; f_service_.indent_up(); f_service_.indent() << "include ::Thrift::Client" << endl << endl; // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); // Open function f_service_.indent() << "def " << function_signature(*f_iter) << endl; f_service_.indent_up(); f_service_.indent() << "send_" << funname << "("; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << (*fld_iter)->get_name(); } f_service_ << ")" << endl; if (!(*f_iter)->is_oneway()) { f_service_.indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << "return "; } f_service_ << "recv_" << funname << "()" << endl; } f_service_.indent_down(); f_service_.indent() << "end" << endl; f_service_ << endl; f_service_.indent() << "def send_" << function_signature(*f_iter) << endl; f_service_.indent_up(); std::string argsname = capitalize((*f_iter)->get_name() + "_args"); std::string messageSendProc = (*f_iter)->is_oneway() ? "send_oneway_message" : "send_message"; f_service_.indent() << messageSendProc << "('" << funname << "', " << argsname; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << ", :" << (*fld_iter)->get_name() << " => " << (*fld_iter)->get_name(); } f_service_ << ")" << endl; f_service_.indent_down(); f_service_.indent() << "end" << endl; if (!(*f_iter)->is_oneway()) { std::string resultname = capitalize((*f_iter)->get_name() + "_result"); t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); // Open function f_service_ << endl; f_service_.indent() << "def " << function_signature(&recv_function) << endl; f_service_.indent_up(); f_service_.indent() << "fname, mtype, rseqid = receive_message_begin()" << endl; f_service_.indent() << "handle_exception(mtype)" << endl; f_service_.indent() << "if reply_seqid(rseqid)==false" << endl; f_service_.indent() << " raise \"seqid reply faild\"" << endl; f_service_.indent() << "end" << endl; f_service_.indent() << "result = receive_message(" << resultname << ")" << endl; // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_.indent() << "return result.success unless result.success.nil?" << endl; } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_.indent() << "raise result." << (*x_iter)->get_name() << " unless result." << (*x_iter)->get_name() << ".nil?" << endl; } // Careful, only return _result if not a void function if ((*f_iter)->get_returntype()->is_void()) { f_service_.indent() << "return" << endl; } else { f_service_.indent() << "raise " "::Thrift::ApplicationException.new(::Thrift::ApplicationException::" "MISSING_RESULT, '" << (*f_iter)->get_name() << " failed: unknown result')" << endl; } // Close function f_service_.indent_down(); f_service_.indent() << "end" << endl << endl; } } f_service_.indent_down(); f_service_.indent() << "end" << endl << endl; } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_rb_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = full_type_name(tservice->get_extends()); extends_processor = " < " + extends + "::Processor "; } // Generate the header portion f_service_.indent() << "class Processor" << extends_processor << endl; f_service_.indent_up(); f_service_.indent() << "include ::Thrift::Processor" << endl << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } f_service_.indent_down(); f_service_.indent() << "end" << endl << endl; } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_rb_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; // Open function f_service_.indent() << "def process_" << tfunction->get_name() << "(seqid, iprot, oprot)" << endl; f_service_.indent_up(); string argsname = capitalize(tfunction->get_name()) + "_args"; string resultname = capitalize(tfunction->get_name()) + "_result"; f_service_.indent() << "args = read_args(iprot, " << argsname << ")" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { f_service_.indent() << "result = " << resultname << ".new()" << endl; } // Try block for a function with exceptions if (xceptions.size() > 0) { f_service_.indent() << "begin" << endl; f_service_.indent_up(); } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_.indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "result.success = "; } f_service_ << "@handler." << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << ")" << endl; if (!tfunction->is_oneway() && xceptions.size() > 0) { f_service_.indent_down(); for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_.indent() << "rescue " << full_type_name((*x_iter)->get_type()) << " => " << (*x_iter)->get_name() << endl; if (!tfunction->is_oneway()) { f_service_.indent_up(); f_service_.indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << endl; f_service_.indent_down(); } } f_service_.indent() << "end" << endl; } // Shortcut out here for oneway functions if (tfunction->is_oneway()) { f_service_.indent() << "return" << endl; f_service_.indent_down(); f_service_.indent() << "end" << endl << endl; return; } f_service_.indent() << "write_result(result, oprot, '" << tfunction->get_name() << "', seqid)" << endl; // Close function f_service_.indent_down(); f_service_.indent() << "end" << endl << endl; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_rb_generator::function_signature(t_function* tfunction, string prefix) { // TODO(mcslee): Nitpicky, no ',' if argument_list is empty return prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")"; } /** * Renders a field list */ string t_rb_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += (*f_iter)->get_name(); } return result; } string t_rb_generator::type_name(const t_type* ttype) { string prefix = ""; string name = ttype->get_name(); if (ttype->is_struct() || ttype->is_xception() || ttype->is_enum()) { name = capitalize(ttype->get_name()); } return prefix + name; } string t_rb_generator::full_type_name(const t_type* ttype) { string prefix = "::"; vector modules = ruby_modules(ttype->get_program()); for (auto & module : modules) { prefix += module + "::"; } return prefix + type_name(ttype); } /** * Converts the parse type to a Ruby tyoe */ string t_rb_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "::Thrift::Types::STRING"; case t_base_type::TYPE_BOOL: return "::Thrift::Types::BOOL"; case t_base_type::TYPE_I8: return "::Thrift::Types::BYTE"; case t_base_type::TYPE_I16: return "::Thrift::Types::I16"; case t_base_type::TYPE_I32: return "::Thrift::Types::I32"; case t_base_type::TYPE_I64: return "::Thrift::Types::I64"; case t_base_type::TYPE_DOUBLE: return "::Thrift::Types::DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "::Thrift::Types::I32"; } else if (type->is_struct() || type->is_xception()) { return "::Thrift::Types::STRUCT"; } else if (type->is_map()) { return "::Thrift::Types::MAP"; } else if (type->is_set()) { return "::Thrift::Types::SET"; } else if (type->is_list()) { return "::Thrift::Types::LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } string t_rb_generator::rb_namespace_to_path_prefix(string rb_namespace) { string namespaces_left = rb_namespace; string::size_type loc; string path_prefix = ""; while ((loc = namespaces_left.find(".")) != string::npos) { path_prefix = path_prefix + underscore(namespaces_left.substr(0, loc)) + "/"; namespaces_left = namespaces_left.substr(loc + 1); } if (namespaces_left.size() > 0) { path_prefix = path_prefix + underscore(namespaces_left) + "/"; } return path_prefix; } void t_rb_generator::generate_rdoc(t_rb_ofstream& out, t_doc* tdoc) { if (tdoc->has_doc()) { out.indent(); generate_docstring_comment(out, "", "# ", tdoc->get_doc(), ""); } } void t_rb_generator::generate_rb_struct_required_validator(t_rb_ofstream& out, t_struct* tstruct) { out.indent() << "def validate" << endl; out.indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); if (field->get_req() == t_field::T_REQUIRED) { out.indent() << "raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, " "'Required field " << field->get_name() << " is unset!')"; if (field->get_type()->is_bool()) { out << " if @" << field->get_name() << ".nil?"; } else { out << " unless @" << field->get_name(); } out << endl; } } // if field is an enum, check that its value is valid for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); if (field->get_type()->is_enum()) { out.indent() << "unless @" << field->get_name() << ".nil? || " << full_type_name(field->get_type()) << "::VALID_VALUES.include?(@" << field->get_name() << ")" << endl; out.indent_up(); out.indent() << "raise ::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, " "'Invalid value of field " << field->get_name() << "!')" << endl; out.indent_down(); out.indent() << "end" << endl; } } out.indent_down(); out.indent() << "end" << endl << endl; } void t_rb_generator::generate_rb_union_validator(t_rb_ofstream& out, t_struct* tstruct) { out.indent() << "def validate" << endl; out.indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; out.indent() << "raise(StandardError, 'Union fields are not set.') if get_set_field.nil? || get_value.nil?" << endl; // if field is an enum, check that its value is valid for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { const t_field* field = (*f_iter); if (field->get_type()->is_enum()) { out.indent() << "if get_set_field == :" << field->get_name() << endl; out.indent() << " raise " "::Thrift::ProtocolException.new(::Thrift::ProtocolException::UNKNOWN, " "'Invalid value of field " << field->get_name() << "!') unless " << full_type_name(field->get_type()) << "::VALID_VALUES.include?(get_value)" << endl; out.indent() << "end" << endl; } } out.indent_down(); out.indent() << "end" << endl << endl; } std::string t_rb_generator::display_name() const { return "Ruby"; } THRIFT_REGISTER_GENERATOR( rb, "Ruby", " rubygems: Add a \"require 'rubygems'\" line to the top of each generated file.\n" " namespaced: Generate files in idiomatic namespaced directories.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_d_generator.cc0000644000000000000000000006625514370300523024512 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ofstream; using std::ostream; using std::ostringstream; using std::set; using std::string; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * D code generator. * * generate_*() functions are called by the base class to emit code for the * given entity, print_*() functions write a piece of code to the passed * stream, and render_*() return a string containing the D representation of * the passed entity. */ class t_d_generator : public t_oop_generator { public: t_d_generator(t_program* program, const std::map& parsed_options, const string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option d:" + iter->first; } out_dir_base_ = "gen-d"; } std::string display_name() const override; protected: // D reserved words are suffixed with an underscore static string suffix_if_reserved(const string& name) { const bool isIn = std::binary_search(std::begin(d_reserved_words), std::end(d_reserved_words), name); string ret = isIn ? name + "_" : name; return ret; } void init_generator() override { // Make output directory MKDIR(get_out_dir().c_str()); string dir = program_->get_namespace("d"); string subdir = get_out_dir(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } if (!dir.empty()) { subdir = subdir + "/" + dir; MKDIR(subdir.c_str()); } package_dir_ = subdir + "/"; // Make output file string f_types_name = package_dir_ + program_name_ + "_types.d"; f_types_.open(f_types_name.c_str()); // Print header f_types_ << autogen_comment() << "module " << render_package(*program_) << program_name_ << "_types;" << endl << endl; print_default_imports(f_types_); // Include type modules from other imported programs. const vector& includes = program_->get_includes(); for (auto include : includes) { f_types_ << "public import " << render_package(*include) << include->get_name() << "_types;" << endl; } if (!includes.empty()) f_types_ << endl; } void close_generator() override { // Close output file f_types_.close(); } void generate_consts(std::vector consts) override { if (!consts.empty()) { string f_consts_name = package_dir_ + program_name_ + "_constants.d"; ofstream_with_content_based_conditional_update f_consts; f_consts.open(f_consts_name.c_str()); f_consts << autogen_comment() << "module " << render_package(*program_) << program_name_ << "_constants;" << endl << endl; print_default_imports(f_consts); f_consts << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl << endl; vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { this->emit_doc(*c_iter, f_consts); string name = suffix_if_reserved((*c_iter)->get_name()); t_type* type = (*c_iter)->get_type(); indent(f_consts) << "immutable(" << render_type_name(type) << ") " << name << ";" << endl; } f_consts << endl << "shared static this() {" << endl; indent_up(); bool first = true; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { if (first) { first = false; } else { f_consts << endl; } t_type* type = (*c_iter)->get_type(); indent(f_consts) << suffix_if_reserved((*c_iter)->get_name()) << " = "; if (!is_immutable_type(type)) { f_consts << "cast(immutable(" << render_type_name(type) << ")) "; } f_consts << render_const_value(type, (*c_iter)->get_value()) << ";" << endl; } indent_down(); indent(f_consts) << "}" << endl; } } void generate_typedef(t_typedef* ttypedef) override { this->emit_doc(ttypedef, f_types_); f_types_ << indent() << "alias " << render_type_name(ttypedef->get_type()) << " " << ttypedef->get_symbolic() << ";" << endl << endl; } void generate_enum(t_enum* tenum) override { vector constants = tenum->get_constants(); this->emit_doc(tenum, f_types_); string enum_name = suffix_if_reserved(tenum->get_name()); f_types_ << indent() << "enum " << enum_name << " {" << endl; indent_up(); vector::const_iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { this->emit_doc(*c_iter, f_types_); indent(f_types_) << suffix_if_reserved((*c_iter)->get_name()); f_types_ << " = " << (*c_iter)->get_value() << ","; } f_types_ << endl; indent_down(); indent(f_types_) << "}" << endl; f_types_ << endl; } void generate_struct(t_struct* tstruct) override { print_struct_definition(f_types_, tstruct, false); } void generate_xception(t_struct* txception) override { print_struct_definition(f_types_, txception, true); } void generate_service(t_service* tservice) override { string svc_name = suffix_if_reserved(tservice->get_name()); // Service implementation file includes string f_servicename = package_dir_ + svc_name + ".d"; ofstream_with_content_based_conditional_update f_service; f_service.open(f_servicename.c_str()); f_service << autogen_comment() << "module " << suffix_if_reserved(render_package(*program_)) << svc_name << ";" << endl << endl; print_default_imports(f_service); f_service << "import " << suffix_if_reserved(render_package(*get_program())) << program_name_ << "_types;" << endl; t_service* extends_service = tservice->get_extends(); if (extends_service != nullptr) { f_service << "import " << suffix_if_reserved(render_package(*(extends_service->get_program()))) << suffix_if_reserved(extends_service->get_name()) << ";" << endl; } f_service << endl; string extends = ""; if (tservice->get_extends() != nullptr) { extends = " : " + suffix_if_reserved(render_type_name(tservice->get_extends())); } this->emit_doc(tservice, f_service); f_service << indent() << "interface " << svc_name << extends << " {" << endl; indent_up(); // Collect all the exception types service methods can throw so we can // emit the necessary aliases later. set exception_types; // Print the method signatures. vector functions = tservice->get_functions(); vector::iterator fn_iter; for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) { this->emit_doc(*fn_iter, f_service); f_service << indent(); print_function_signature(f_service, *fn_iter); f_service << ";" << endl; const vector& exceptions = (*fn_iter)->get_xceptions()->get_members(); vector::const_iterator ex_iter; for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) { exception_types.insert((*ex_iter)->get_type()); } } // Alias the exception types into the current scope. if (!exception_types.empty()) f_service << endl; set::const_iterator et_iter; for (et_iter = exception_types.begin(); et_iter != exception_types.end(); ++et_iter) { indent(f_service) << "alias " << render_package(*(*et_iter)->get_program()) << (*et_iter)->get_program()->get_name() << "_types" << "." << (*et_iter)->get_name() << " " << (*et_iter)->get_name() << ";" << endl; } // Write the method metadata. ostringstream meta; indent_up(); bool first = true; for (fn_iter = functions.begin(); fn_iter != functions.end(); ++fn_iter) { if ((*fn_iter)->get_arglist()->get_members().empty() && (*fn_iter)->get_xceptions()->get_members().empty() && !(*fn_iter)->is_oneway()) { continue; } if (first) { first = false; } else { meta << ","; } meta << endl << indent() << "TMethodMeta(`" << suffix_if_reserved((*fn_iter)->get_name()) << "`, " << endl; indent_up(); indent(meta) << "["; bool first = true; const vector& params = (*fn_iter)->get_arglist()->get_members(); vector::const_iterator p_iter; for (p_iter = params.begin(); p_iter != params.end(); ++p_iter) { if (first) { first = false; } else { meta << ", "; } meta << "TParamMeta(`" << suffix_if_reserved((*p_iter)->get_name()) << "`, " << (*p_iter)->get_key(); t_const_value* cv = (*p_iter)->get_value(); if (cv != nullptr) { meta << ", q{" << render_const_value((*p_iter)->get_type(), cv) << "}"; } meta << ")"; } meta << "]"; if (!(*fn_iter)->get_xceptions()->get_members().empty() || (*fn_iter)->is_oneway()) { meta << "," << endl << indent() << "["; bool first = true; const vector& exceptions = (*fn_iter)->get_xceptions()->get_members(); vector::const_iterator ex_iter; for (ex_iter = exceptions.begin(); ex_iter != exceptions.end(); ++ex_iter) { if (first) { first = false; } else { meta << ", "; } meta << "TExceptionMeta(`" << suffix_if_reserved((*ex_iter)->get_name()) << "`, " << (*ex_iter)->get_key() << ", `" << (*ex_iter)->get_type()->get_name() << "`)"; } meta << "]"; } if ((*fn_iter)->is_oneway()) { meta << "," << endl << indent() << "TMethodType.ONEWAY"; } indent_down(); meta << endl << indent() << ")"; } indent_down(); string meta_str(meta.str()); if (!meta_str.empty()) { f_service << endl << indent() << "enum methodMeta = [" << meta_str << endl << indent() << "];" << endl; } indent_down(); indent(f_service) << "}" << endl; // Server skeleton generation. string f_skeletonname = package_dir_ + svc_name + "_server.skeleton.d"; ofstream_with_content_based_conditional_update f_skeleton; f_skeleton.open(f_skeletonname.c_str()); print_server_skeleton(f_skeleton, tservice); f_skeleton.close(); } void emit_doc(t_doc *doc, std::ostream& out) { if (!doc->has_doc()) { return; } indent(out) << "/**" << std::endl; indent_up(); // No endl -- comments reliably have a newline at the end. // This is true even for stuff like: // /** method infos */ void foo(/** huh?*/ 1: i64 stuff) indent(out) << doc->get_doc(); indent_down(); indent(out) << "*/" << std::endl; } private: /** * Writes a server skeleton for the passed service to out. */ void print_server_skeleton(ostream& out, t_service* tservice) { string svc_name = suffix_if_reserved(tservice->get_name()); out << "/*" << endl << " * This auto-generated skeleton file illustrates how to build a server. If you" << endl << " * intend to customize it, you should edit a copy with another file name to " << endl << " * avoid overwriting it when running the generator again." << endl << " */" << endl << "module " << render_package(*tservice->get_program()) << svc_name << "_server;" << endl << endl << "import std.stdio;" << endl << "import thrift.codegen.processor;" << endl << "import thrift.protocol.binary;" << endl << "import thrift.server.simple;" << endl << "import thrift.server.transport.socket;" << endl << "import thrift.transport.buffered;" << endl << "import thrift.util.hashset;" << endl << endl << "import " << render_package(*tservice->get_program()) << svc_name << ";" << endl << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl << endl << endl << "class " << svc_name << "Handler : " << svc_name << " {" << endl; indent_up(); out << indent() << "this() {" << endl << indent() << " // Your initialization goes here." << endl << indent() << "}" << endl << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { out << indent(); print_function_signature(out, *f_iter); out << " {" << endl; indent_up(); out << indent() << "// Your implementation goes here." << endl << indent() << "writeln(\"" << suffix_if_reserved((*f_iter)->get_name()) << " called\");" << endl; t_type* rt = (*f_iter)->get_returntype(); if (!rt->is_void()) { indent(out) << "return typeof(return).init;" << endl; } indent_down(); out << indent() << "}" << endl << endl; } indent_down(); out << "}" << endl << endl; out << indent() << "void main() {" << endl; indent_up(); out << indent() << "auto protocolFactory = new TBinaryProtocolFactory!();" << endl << indent() << "auto processor = new TServiceProcessor!" << svc_name << "(new " << svc_name << "Handler);" << endl << indent() << "auto serverTransport = new TServerSocket(9090);" << endl << indent() << "auto transportFactory = new TBufferedTransportFactory;" << endl << indent() << "auto server = new TSimpleServer(" << endl << indent() << " processor, serverTransport, transportFactory, protocolFactory);" << endl << indent() << "server.serve();" << endl; indent_down(); out << "}" << endl; } /** * Writes the definition of a struct or an exception type to out. */ void print_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) { const vector& members = tstruct->get_members(); if (is_exception) { indent(out) << "class " << suffix_if_reserved(tstruct->get_name()) << " : TException {" << endl; } else { indent(out) << "struct " << suffix_if_reserved(tstruct->get_name()) << " {" << endl; } indent_up(); // Declare all fields. vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << render_type_name((*m_iter)->get_type()) << " " << suffix_if_reserved((*m_iter)->get_name()) << ";" << endl; } if (!members.empty()) indent(out) << endl; indent(out) << "mixin TStructHelpers!("; if (!members.empty()) { // If there are any fields, construct the TFieldMeta array to pass to // TStructHelpers. We can't just pass an empty array if not because [] // doesn't pass the TFieldMeta[] constraint. out << "["; indent_up(); bool first = true; vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (first) { first = false; } else { out << ","; } out << endl; indent(out) << "TFieldMeta(`" << suffix_if_reserved((*m_iter)->get_name()) << "`, " << (*m_iter)->get_key(); t_const_value* cv = (*m_iter)->get_value(); t_field::e_req req = (*m_iter)->get_req(); out << ", " << render_req(req); if (cv != nullptr) { out << ", q{" << render_const_value((*m_iter)->get_type(), cv) << "}"; } out << ")"; } indent_down(); out << endl << indent() << "]"; } out << ");" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Prints the D function signature (including return type) for the given * method. */ void print_function_signature(ostream& out, t_function* fn) { out << render_type_name(fn->get_returntype()) << " " << suffix_if_reserved(fn->get_name()) << "("; const vector& fields = fn->get_arglist()->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { out << ", "; } out << render_type_name((*f_iter)->get_type(), true) << " " << suffix_if_reserved((*f_iter)->get_name()); } out << ")"; } /** * Returns the D representation of value. The result is guaranteed to be a * single expression; for complex types, immediately called delegate * literals are used to achieve this. */ string render_const_value(t_type* type, t_const_value* value) { // Resolve any typedefs. type = get_true_type(type); ostringstream out; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: out << "cast(" << render_type_name(type) << ")" << value->get_integer(); break; case t_base_type::TYPE_I32: out << value->get_integer(); break; case t_base_type::TYPE_I64: out << value->get_integer() << "L"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "Compiler error: No const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "cast(" << render_type_name(type) << ")" << value->get_integer(); } else { out << "{" << endl; indent_up(); indent(out) << render_type_name(type) << " v;" << endl; if (type->is_struct() || type->is_xception()) { indent(out) << "v = " << (type->is_xception() ? "new " : "") << render_type_name(type) << "();" << endl; const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "Type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string val = render_const_value(field_type, v_iter->second); indent(out) << "v.set!`" << v_iter->first->get_string() << "`(" << val << ");" << endl; } } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(ktype, v_iter->first); string val = render_const_value(vtype, v_iter->second); indent(out) << "v["; if (!is_immutable_type(ktype)) { out << "cast(immutable(" << render_type_name(ktype) << "))"; } out << key << "] = " << val << ";" << endl; } } else if (type->is_list()) { t_type* etype = ((t_list*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(etype, *v_iter); indent(out) << "v ~= " << val << ";" << endl; } } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(etype, *v_iter); indent(out) << "v ~= " << val << ";" << endl; } } else { throw "Compiler error: Invalid type in render_const_value: " + type->get_name(); } indent(out) << "return v;" << endl; indent_down(); indent(out) << "}()"; } return out.str(); } /** * Returns the D package to which modules for program are written (with a * trailing dot, if not empty). */ string render_package(const t_program& program) const { string package = program.get_namespace("d"); if (package.size() == 0) return ""; return package + "."; } /** * Returns the name of the D repesentation of ttype. * * If isArg is true, a const reference to the type will be returned for * structs. */ string render_type_name(const t_type* ttype, bool isArg = false) const { if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: return "string"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "byte"; case t_base_type::TYPE_I16: return "short"; case t_base_type::TYPE_I32: return "int"; case t_base_type::TYPE_I64: return "long"; case t_base_type::TYPE_DOUBLE: return "double"; default: throw "Compiler error: No D type name for base type " + t_base_type::t_base_name(tbase); } } if (ttype->is_container()) { t_container* tcontainer = (t_container*)ttype; if (tcontainer->has_cpp_name()) { return tcontainer->get_cpp_name(); } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; t_type* ktype = tmap->get_key_type(); string name = render_type_name(tmap->get_val_type()) + "["; if (!is_immutable_type(ktype)) { name += "immutable("; } name += render_type_name(ktype); if (!is_immutable_type(ktype)) { name += ")"; } name += "]"; return name; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; return "HashSet!(" + render_type_name(tset->get_elem_type()) + ")"; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; return render_type_name(tlist->get_elem_type()) + "[]"; } } if (ttype->is_struct() && isArg) { return "ref const(" + ttype->get_name() + ")"; } else { return ttype->get_name(); } } /** * Returns the D TReq enum member corresponding to req. */ string render_req(t_field::e_req req) const { switch (req) { case t_field::T_OPT_IN_REQ_OUT: return "TReq.OPT_IN_REQ_OUT"; case t_field::T_OPTIONAL: return "TReq.OPTIONAL"; case t_field::T_REQUIRED: return "TReq.REQUIRED"; default: { std::stringstream ss; ss << "Compiler error: Invalid requirement level " << req; throw ss.str(); } } } /** * Writes the default list of imports (which are written to every generated * module) to f. */ void print_default_imports(ostream& out) { indent(out) << "import thrift.base;" << endl << "import thrift.codegen.base;" << endl << "import thrift.util.hashset;" << endl << endl; } /** * Returns whether type is »intrinsically immutable«, in the sense that * a value of that type is implicitly castable to immutable(type), and it is * allowed for AA keys without an immutable() qualifier. */ bool is_immutable_type(t_type* type) const { t_type* ttype = get_true_type(type); return ttype->is_base_type() || ttype->is_enum(); } /* * File streams, stored here to avoid passing them as parameters to every * function. */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_header_; string package_dir_; protected: static vector d_reserved_words; }; vector t_d_generator::d_reserved_words = { // The keywords are extracted from https://dlang.org/spec/lex.html // and sorted for use with std::binary_search "__FILE_FULL_PATH__", "__FILE__", "__FUNCTION__", "__LINE__", "__MODULE__", "__PRETTY_FUNCTION__", "__gshared", "__parameters", "__traits", "__vector", "abstract", "alias", "align", "asm", "assert", "auto", "body", "bool", "break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat", "char", "class", "const", "continue", "creal", "dchar", "debug", "default", "delegate", "delete", "deprecated", "do", "double", "else", "enum", "export", "extern", "false", "final", "finally", "float", "for", "foreach", "foreach_reverse", "function", "goto", "idouble", "if", "ifloat", "immutable", "import", "in", "inout", "int", "interface", "invariant", "ireal", "is", "lazy", "long", "macro ", "mixin", "module", "new", "nothrow", "null", "out", "override", "package", "pragma", "private", "protected", "public", "pure", "real", "ref", "return", "scope", "shared", "short", "static", "struct", "super", "switch", "synchronized", "template", "this", "throw", "true", "try", "typeid", "typeof", "ubyte", "ucent", "uint", "ulong", "union", "unittest", "ushort", "version", "void", "wchar", "while", "with" }; std::string t_d_generator::display_name() const { return "D"; } THRIFT_REGISTER_GENERATOR(d, "D", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_javame_generator.cc0000644000000000000000000034407014370300523025524 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * Java code generator. * */ class t_javame_generator : public t_oop_generator { public: t_javame_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)parsed_options; (void)option_string; std::map::const_iterator iter; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option javame:" + iter->first; } out_dir_base_ = "gen-javame"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(std::vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_struct(t_struct* tstruct) override; void generate_union(t_struct* tunion); void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value, bool in_static, bool defval = false); std::string render_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value); /** * Service-level generation functions */ void generate_java_struct(t_struct* tstruct, bool is_exception); void generate_java_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false); void generate_java_struct_equality(std::ostream& out, t_struct* tstruct); void generate_java_struct_compare_to(std::ostream& out, t_struct* tstruct); void generate_java_struct_reader(std::ostream& out, t_struct* tstruct); void generate_java_validator(std::ostream& out, t_struct* tstruct); void generate_java_struct_result_writer(std::ostream& out, t_struct* tstruct); void generate_java_struct_writer(std::ostream& out, t_struct* tstruct); void generate_java_struct_tostring(std::ostream& out, t_struct* tstruct); void generate_java_struct_clear(std::ostream& out, t_struct* tstruct); void generate_field_value_meta_data(std::ostream& out, t_type* type); std::string get_java_type_string(t_type* type); void generate_reflection_setters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name); void generate_reflection_getters(std::ostringstream& out, t_type* type, std::string field_name, std::string cap_name); void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct); void generate_java_bean_boilerplate(std::ostream& out, t_struct* tstruct); void generate_function_helpers(t_function* tfunction); std::string get_cap_name(std::string name); std::string generate_isset_check(t_field* field); std::string generate_isset_check(std::string field); void generate_isset_set(ostream& out, t_field* field); std::string isset_field_id(t_field* field); void generate_primitive_service_interface(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); void generate_java_union(t_struct* tstruct); void generate_union_constructor(ostream& out, t_struct* tstruct); void generate_union_getters_and_setters(ostream& out, t_struct* tstruct); void generate_union_abstract_methods(ostream& out, t_struct* tstruct); void generate_check_type(ostream& out, t_struct* tstruct); void generate_read_value(ostream& out, t_struct* tstruct); void generate_write_value(ostream& out, t_struct* tstruct); void generate_get_field_desc(ostream& out, t_struct* tstruct); void generate_get_struct_desc(ostream& out, t_struct* tstruct); void generate_get_field_name(ostream& out, t_struct* tstruct); void generate_union_comparisons(ostream& out, t_struct* tstruct); void generate_union_hashcode(ostream& out, t_struct* tstruct); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter, std::string map); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_java_doc(std::ostream& out, t_field* field) override; void generate_java_doc(std::ostream& out, t_doc* tdoc) override; void generate_java_doc(std::ostream& out, t_function* tdoc) override; void generate_java_docstring_comment(std::ostream& out, string contents) override; void generate_deep_copy_container(std::ostream& out, std::string source_name_p1, std::string source_name_p2, std::string result_name, t_type* type); void generate_deep_copy_non_container(std::ostream& out, std::string source_name, std::string dest_name, t_type* type); bool has_bit_vector(t_struct* tstruct); /** * Helper rendering functions */ std::string java_package(); std::string java_type_imports(); std::string java_thrift_imports(); std::string type_name(t_type* ttype, bool in_container = false, bool in_init = false, bool skip_generic = false); std::string base_type_name(t_base_type* tbase, bool in_container = false); std::string declare_field(t_field* tfield, bool init = false); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct, bool include_types = true); std::string type_to_enum(t_type* ttype); std::string get_enum_class_name(t_type* type) override; void generate_struct_desc(ostream& out, t_struct* tstruct); void generate_field_descs(ostream& out, t_struct* tstruct); std::string box_type(t_type* type, string value); bool type_can_be_null(t_type* ttype) { ttype = get_true_type(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string() || ttype->is_enum(); } std::string constant_name(std::string name); private: /** * File streams */ std::string package_name_; ofstream_with_content_based_conditional_update f_service_; std::string package_dir_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_javame_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); package_name_ = program_->get_namespace("java"); string dir = package_name_; string subdir = get_out_dir(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } if (dir.size() > 0) { subdir = subdir + "/" + dir; MKDIR(subdir.c_str()); } package_dir_ = subdir; } /** * Packages the generated file * * @return String of the package, i.e. "package org.apache.thriftdemo;" */ string t_javame_generator::java_package() { if (!package_name_.empty()) { return string("package ") + package_name_ + ";\n\n"; } return ""; } /** * Prints standard java imports * * @return List of imports for Java types that are used in here */ string t_javame_generator::java_type_imports() { return string() + "import java.util.Hashtable;\n" + "import java.util.Vector;\n" + "import java.util.Enumeration;\n\n"; } /** * Prints standard java imports * * @return List of imports necessary for thrift */ string t_javame_generator::java_thrift_imports() { return string() + "import org.apache.thrift.*;\n" + "import org.apache.thrift.meta_data.*;\n" + "import org.apache.thrift.transport.*;\n" + "import org.apache.thrift.protocol.*;\n\n"; } /** * Nothing in Java */ void t_javame_generator::close_generator() { } /** * Generates a typedef. This is not done in Java, since it does * not support arbitrary name replacements, and it'd be a wacky waste * of overhead to make wrapper classes. * * @param ttypedef The type definition */ void t_javame_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Enums are a class with a set of static constants. * * @param tenum The enumeration */ void t_javame_generator::generate_enum(t_enum* tenum) { // Make output file string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".java"; ofstream_with_content_based_conditional_update f_enum; f_enum.open(f_enum_name.c_str()); // Comment and package it f_enum << autogen_comment() << java_package(); generate_java_doc(f_enum, tenum); indent(f_enum) << "public class " << tenum->get_name() << " implements org.apache.thrift.TEnum "; scope_up(f_enum); f_enum << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); generate_java_doc(f_enum, *c_iter); indent(f_enum) << "public static final " << tenum->get_name() << " " << (*c_iter)->get_name() << " = new " << tenum->get_name() << "(" << value << ");" << endl; } f_enum << endl; // Field for thriftCode indent(f_enum) << "private final int value;" << endl << endl; indent(f_enum) << "private " << tenum->get_name() << "(int value) {" << endl; indent(f_enum) << " this.value = value;" << endl; indent(f_enum) << "}" << endl << endl; indent(f_enum) << "/**" << endl; indent(f_enum) << " * Get the integer value of this enum value, as defined in the Thrift IDL." << endl; indent(f_enum) << " */" << endl; indent(f_enum) << "public int getValue() {" << endl; indent(f_enum) << " return value;" << endl; indent(f_enum) << "}" << endl << endl; indent(f_enum) << "/**" << endl; indent(f_enum) << " * Find a the enum type by its integer value, as defined in the Thrift IDL." << endl; indent(f_enum) << " * @return null if the value is not found." << endl; indent(f_enum) << " */" << endl; indent(f_enum) << "public static " + tenum->get_name() + " findByValue(int value) { " << endl; indent_up(); indent(f_enum) << "switch (value) {" << endl; indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); indent(f_enum) << "case " << value << ":" << endl; indent(f_enum) << " return " << (*c_iter)->get_name() << ";" << endl; } indent(f_enum) << "default:" << endl; indent(f_enum) << " return null;" << endl; indent_down(); indent(f_enum) << "}" << endl; indent_down(); indent(f_enum) << "}" << endl; scope_down(f_enum); f_enum.close(); } /** * Generates a class that holds all the constants. */ void t_javame_generator::generate_consts(std::vector consts) { if (consts.empty()) { return; } string f_consts_name = package_dir_ + "/" + program_name_ + "Constants.java"; ofstream_with_content_based_conditional_update f_consts; f_consts.open(f_consts_name.c_str()); // Print header f_consts << autogen_comment() << java_package() << java_type_imports(); f_consts << "public class " << program_name_ << "Constants {" << endl << endl; indent_up(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { print_const_value(f_consts, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false); } indent_down(); indent(f_consts) << "}" << endl; f_consts.close(); } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ void t_javame_generator::print_const_value(std::ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval) { type = get_true_type(type); indent(out); if (!defval) { out << (in_static ? "" : "public static final ") << type_name(type) << " "; } if (type->is_base_type()) { string v2 = render_const_value(out, name, type, value); out << name << " = " << v2 << ";" << endl << endl; } else if (type->is_enum()) { out << name << " = " << render_const_value(out, name, type, value) << ";" << endl << endl; } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; out << name << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); } for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string val = render_const_value(out, name, field_type, v_iter->second); indent(out) << name << "."; std::string cap_name = get_cap_name(v_iter->first->get_string()); out << "set" << cap_name << "(" << val << ");" << endl; } if (!in_static) { indent_down(); indent(out) << "}" << endl; } out << endl; } else if (type->is_map()) { out << name << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); } t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); indent(out) << name << ".put(" << box_type(ktype, key) << ", " << box_type(vtype, val) << ");" << endl; } if (!in_static) { indent_down(); indent(out) << "}" << endl; } out << endl; } else if (type->is_list() || type->is_set()) { out << name << " = new " << type_name(type, false, true) << "();" << endl; if (!in_static) { indent(out) << "static {" << endl; indent_up(); } t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(out, name, etype, *v_iter); if (type->is_list()) { indent(out) << name << ".addElement(" << box_type(etype, val) << ");" << endl; } else { indent(out) << name << ".put(" << box_type(etype, val) << ", " << box_type(etype, val) << ");" << endl; } } if (!in_static) { indent_down(); indent(out) << "}" << endl; } out << endl; } else { throw "compiler error: no const of type " + type->get_name(); } } string t_javame_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value) { (void)name; type = get_true_type(type); std::ostringstream render; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: render << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: render << "(byte)" << value->get_integer(); break; case t_base_type::TYPE_I16: render << "(short)" << value->get_integer(); break; case t_base_type::TYPE_I32: render << value->get_integer(); break; case t_base_type::TYPE_I64: render << value->get_integer() << "L"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << "(double)" << value->get_integer(); } else { render << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { render << type_name(type, false, false) << "." << value->get_identifier(); } else { string t = tmp("tmp"); print_const_value(out, t, type, value, true); render << t; } return render.str(); } string t_javame_generator::box_type(t_type* type, string value) { if (type->is_base_type()) { switch (((t_base_type*)type)->get_base()) { case t_base_type::TYPE_BOOL: return "new Boolean(" + value + ")"; case t_base_type::TYPE_I8: return "new Byte(" + value + ")"; case t_base_type::TYPE_I16: return "new Short(" + value + ")"; case t_base_type::TYPE_I32: return "new Integer(" + value + ")"; case t_base_type::TYPE_I64: return "new Long(" + value + ")"; case t_base_type::TYPE_DOUBLE: return "new Double(" + value + ")"; default: break; } } return value; } /** * Generates a struct definition for a thrift data type. This will be a TBase * implementor. * * @param tstruct The struct definition */ void t_javame_generator::generate_struct(t_struct* tstruct) { if (tstruct->is_union()) { generate_java_union(tstruct); } else { generate_java_struct(tstruct, false); } } /** * Exceptions are structs, but they inherit from Exception * * @param tstruct The struct definition */ void t_javame_generator::generate_xception(t_struct* txception) { generate_java_struct(txception, true); } /** * Java struct definition. * * @param tstruct The struct definition */ void t_javame_generator::generate_java_struct(t_struct* tstruct, bool is_exception) { // Make output file string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports(); generate_java_struct_definition(f_struct, tstruct, is_exception); f_struct.close(); } /** * Java union definition. * * @param tstruct The struct definition */ void t_javame_generator::generate_java_union(t_struct* tstruct) { // Make output file string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".java"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports(); generate_java_doc(f_struct, tstruct); bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); indent(f_struct) << "public " << (is_final ? "final " : "") << "class " << tstruct->get_name() << " extends TUnion "; scope_up(f_struct); generate_struct_desc(f_struct, tstruct); generate_field_descs(f_struct, tstruct); f_struct << endl; generate_union_constructor(f_struct, tstruct); f_struct << endl; generate_union_abstract_methods(f_struct, tstruct); f_struct << endl; generate_union_getters_and_setters(f_struct, tstruct); f_struct << endl; generate_union_comparisons(f_struct, tstruct); f_struct << endl; generate_union_hashcode(f_struct, tstruct); f_struct << endl; scope_down(f_struct); f_struct.close(); } void t_javame_generator::generate_union_constructor(ostream& out, t_struct* tstruct) { indent(out) << "public " << type_name(tstruct) << "() {" << endl; indent(out) << " super();" << endl; indent(out) << "}" << endl << endl; indent(out) << "public " << type_name(tstruct) << "(_Fields setField, Object value) {" << endl; indent(out) << " super(setField, value);" << endl; indent(out) << "}" << endl << endl; indent(out) << "public " << type_name(tstruct) << "(" << type_name(tstruct) << " other) {" << endl; indent(out) << " super(other);" << endl; indent(out) << "}" << endl; indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl; indent(out) << " return new " << tstruct->get_name() << "(this);" << endl; indent(out) << "}" << endl << endl; // generate "constructors" for each field const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "public static " << type_name(tstruct) << " " << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type()) << " value) {" << endl; indent(out) << " " << type_name(tstruct) << " x = new " << type_name(tstruct) << "();" << endl; indent(out) << " x.set" << get_cap_name((*m_iter)->get_name()) << "(value);" << endl; indent(out) << " return x;" << endl; indent(out) << "}" << endl << endl; } } void t_javame_generator::generate_union_getters_and_setters(ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (first) { first = false; } else { out << endl; } t_field* field = (*m_iter); generate_java_doc(out, field); indent(out) << "public " << type_name(field->get_type()) << " get" << get_cap_name(field->get_name()) << "() {" << endl; indent(out) << " if (getSetField() == _Fields." << constant_name(field->get_name()) << ") {" << endl; indent(out) << " return (" << type_name(field->get_type(), true) << ")getFieldValue();" << endl; indent(out) << " } else {" << endl; indent(out) << " throw new RuntimeException(\"Cannot get field '" << field->get_name() << "' because union is currently set to \" + getFieldDesc(getSetField()).name);" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; out << endl; generate_java_doc(out, field); indent(out) << "public void set" << get_cap_name(field->get_name()) << "(" << type_name(field->get_type()) << " value) {" << endl; if (type_can_be_null(field->get_type())) { indent(out) << " if (value == null) throw new NullPointerException();" << endl; } indent(out) << " setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl; indent(out) << " value_ = value;" << endl; indent(out) << "}" << endl; } } void t_javame_generator::generate_union_abstract_methods(ostream& out, t_struct* tstruct) { generate_check_type(out, tstruct); out << endl; generate_read_value(out, tstruct); out << endl; generate_write_value(out, tstruct); out << endl; generate_get_field_desc(out, tstruct); out << endl; generate_get_struct_desc(out, tstruct); out << endl; } void t_javame_generator::generate_check_type(ostream& out, t_struct* tstruct) { indent(out) << "protected void checkType(_Fields setField, Object value) throws ClassCastException {" << endl; indent_up(); indent(out) << "switch (setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent(out) << " if (value instanceof " << type_name(field->get_type(), true, false, true) << ") {" << endl; indent(out) << " break;" << endl; indent(out) << " }" << endl; indent(out) << " throw new ClassCastException(\"Was expecting value of type " << type_name(field->get_type(), true, false) << " for field '" << field->get_name() << "', but got \" + value.getClass().getSimpleName());" << endl; // do the real check here } indent(out) << "default:" << endl; indent(out) << " throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_javame_generator::generate_read_value(ostream& out, t_struct* tstruct) { indent(out) << "protected Object readValue(TProtocol iprot, TField field) throws TException {" << endl; indent_up(); indent(out) << "_Fields setField = _Fields.findByThriftId(field.id);" << endl; indent(out) << "if (setField != null) {" << endl; indent_up(); indent(out) << "switch (setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << "if (field.type == " << constant_name(field->get_name()) << "_FIELD_DESC.type) {" << endl; indent_up(); indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << ";" << endl; generate_deserialize_field(out, field, ""); indent(out) << "return " << field->get_name() << ";" << endl; indent_down(); indent(out) << "} else {" << endl; indent(out) << " TProtocolUtil.skip(iprot, field.type);" << endl; indent(out) << " return null;" << endl; indent(out) << "}" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new IllegalStateException(\"setField wasn't null, but didn't match any " "of the case statements!\");" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "TProtocolUtil.skip(iprot, field.type);" << endl; indent(out) << "return null;" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_javame_generator::generate_write_value(ostream& out, t_struct* tstruct) { indent(out) << "protected void writeValue(TProtocol oprot) throws TException {" << endl; indent_up(); indent(out) << "switch (setField_) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent_up(); indent(out) << type_name(field->get_type(), true, false) << " " << field->get_name() << " = (" << type_name(field->get_type(), true, false) << ")value_;" << endl; generate_serialize_field(out, field, ""); indent(out) << "return;" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " throw new IllegalStateException(\"Cannot write union with unknown field \" + " "setField_);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_javame_generator::generate_get_field_desc(ostream& out, t_struct* tstruct) { indent(out) << "protected TField getFieldDesc(_Fields setField) {" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; indent(out) << "switch (setField) {" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); indent(out) << "case " << constant_name(field->get_name()) << ":" << endl; indent(out) << " return " << constant_name(field->get_name()) << "_FIELD_DESC;" << endl; } indent(out) << "default:" << endl; indent(out) << " throw new IllegalArgumentException(\"Unknown field id \" + setField);" << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}" << endl; } void t_javame_generator::generate_get_struct_desc(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << "protected TStruct getStructDesc() {" << endl; indent(out) << " return STRUCT_DESC;" << endl; indent(out) << "}" << endl; } void t_javame_generator::generate_union_comparisons(ostream& out, t_struct* tstruct) { // equality indent(out) << "public boolean equals(Object other) {" << endl; indent(out) << " if (other instanceof " << tstruct->get_name() << ") {" << endl; indent(out) << " return equals((" << tstruct->get_name() << ")other);" << endl; indent(out) << " } else {" << endl; indent(out) << " return false;" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; out << endl; indent(out) << "public boolean equals(" << tstruct->get_name() << " other) {" << endl; indent(out) << " return other != null && getSetField() == other.getSetField() && " "getFieldValue().equals(other.getFieldValue());" << endl; indent(out) << "}" << endl; out << endl; indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl; indent(out) << " int lastComparison = TBaseHelper.compareTo(getSetField(), other.getSetField());" << endl; indent(out) << " if (lastComparison == 0) {" << endl; indent(out) << " return TBaseHelper.compareTo(getFieldValue(), other.getFieldValue());" << endl; indent(out) << " }" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << "}" << endl; out << endl; } void t_javame_generator::generate_union_hashcode(ostream& out, t_struct* tstruct) { (void)tstruct; indent(out) << "/**" << endl; indent(out) << " * If you'd like this to perform more respectably, use the hashcode generator option." << endl; indent(out) << " */" << endl; indent(out) << "public int hashCode() {" << endl; indent(out) << " return 0;" << endl; indent(out) << "}" << endl; } /** * Java struct definition. This has various parameters, as it could be * generated standalone or inside another class as a helper. If it * is a helper than it is a static class. * * @param tstruct The struct definition * @param is_exception Is this an exception? * @param in_class If inside a class, needs to be static class * @param is_result If this is a result it needs a different writer */ void t_javame_generator::generate_java_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result) { generate_java_doc(out, tstruct); bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); indent(out) << "public " << (is_final ? "final " : "") << (in_class ? "static " : "") << "class " << tstruct->get_name() << " "; if (is_exception) { out << "extends Exception "; } out << "implements TBase "; scope_up(out); generate_struct_desc(out, tstruct); // Members are public for -java, private for -javabean const vector& members = tstruct->get_members(); vector::const_iterator m_iter; out << endl; generate_field_descs(out, tstruct); out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "private "; out << declare_field(*m_iter, false) << endl; } // isset data if (members.size() > 0) { out << endl; indent(out) << "// isset id assignments" << endl; int i = 0; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!type_can_be_null((*m_iter)->get_type())) { indent(out) << "private static final int " << isset_field_id(*m_iter) << " = " << i << ";" << endl; i++; } } if (i > 0) { indent(out) << "private boolean[] __isset_vector = new boolean[" << i << "];" << endl; } out << endl; } bool all_optional_members = true; // Default constructor indent(out) << "public " << tstruct->get_name() << "() {" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr) { print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); } if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { all_optional_members = false; } } indent_down(); indent(out) << "}" << endl << endl; if (!members.empty() && !all_optional_members) { // Full constructor for all fields indent(out) << "public " << tstruct->get_name() << "(" << endl; indent_up(); bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { if (!first) { out << "," << endl; } first = false; indent(out) << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name(); } } out << ")" << endl; indent_down(); indent(out) << "{" << endl; indent_up(); indent(out) << "this();" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { indent(out) << "this." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << ";" << endl; generate_isset_set(out, (*m_iter)); } } indent_down(); indent(out) << "}" << endl << endl; } // copy constructor indent(out) << "/**" << endl; indent(out) << " * Performs a deep copy on other." << endl; indent(out) << " */" << endl; indent(out) << "public " << tstruct->get_name() << "(" << tstruct->get_name() << " other) {" << endl; indent_up(); if (has_bit_vector(tstruct)) { indent(out) << "System.arraycopy(other.__isset_vector, 0, __isset_vector, 0, " "other.__isset_vector.length);" << endl; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = (*m_iter); std::string field_name = field->get_name(); t_type* type = field->get_type(); bool can_be_null = type_can_be_null(type); if (can_be_null) { indent(out) << "if (other." << generate_isset_check(field) << ") {" << endl; indent_up(); } if (type->is_container()) { generate_deep_copy_container(out, "other", field_name, "__this__" + field_name, type); indent(out) << "this." << field_name << " = __this__" << field_name << ";" << endl; } else { indent(out) << "this." << field_name << " = "; generate_deep_copy_non_container(out, "other." + field_name, field_name, type); out << ";" << endl; } if (can_be_null) { indent_down(); indent(out) << "}" << endl; } } indent_down(); indent(out) << "}" << endl << endl; // clone method, so that you can deep copy an object when you don't know its class. indent(out) << "public " << tstruct->get_name() << " deepCopy() {" << endl; indent(out) << " return new " << tstruct->get_name() << "(this);" << endl; indent(out) << "}" << endl << endl; generate_java_struct_clear(out, tstruct); generate_java_bean_boilerplate(out, tstruct); generate_generic_field_getters_setters(out, tstruct); generate_java_struct_equality(out, tstruct); generate_java_struct_compare_to(out, tstruct); generate_java_struct_reader(out, tstruct); if (is_result) { generate_java_struct_result_writer(out, tstruct); } else { generate_java_struct_writer(out, tstruct); } generate_java_struct_tostring(out, tstruct); generate_java_validator(out, tstruct); scope_down(out); out << endl; } /** * Generates equals methods and a hashCode method for a structure. * * @param tstruct The struct definition */ void t_javame_generator::generate_java_struct_equality(ostream& out, t_struct* tstruct) { out << indent() << "public boolean equals(Object that) {" << endl; indent_up(); out << indent() << "if (that == null)" << endl << indent() << " return false;" << endl << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent() << " return this.equals((" << tstruct->get_name() << ")that);" << endl << indent() << "return false;" << endl; scope_down(out); out << endl; out << indent() << "public boolean equals(" << tstruct->get_name() << " that) {" << endl; indent_up(); out << indent() << "if (that == null)" << endl << indent() << " return false;" << endl << indent() << "if (this == that)" << endl << indent() << " return true;" << endl; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << endl; t_type* t = get_true_type((*m_iter)->get_type()); // Most existing Thrift code does not use isset or optional/required, // so we treat "default" fields as required. bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; bool can_be_null = type_can_be_null(t); string name = (*m_iter)->get_name(); string this_present = "true"; string that_present = "true"; string unequal; if (is_optional || can_be_null) { this_present += " && this." + generate_isset_check(*m_iter); that_present += " && that." + generate_isset_check(*m_iter); } out << indent() << "boolean this_present_" << name << " = " << this_present << ";" << endl << indent() << "boolean that_present_" << name << " = " << that_present << ";" << endl << indent() << "if (" << "this_present_" << name << " || that_present_" << name << ") {" << endl; indent_up(); out << indent() << "if (!(" << "this_present_" << name << " && that_present_" << name << "))" << endl << indent() << " return false;" << endl; if (t->is_binary()) { unequal = "TBaseHelper.compareTo(this." + name + ", that." + name + ") != 0"; } else if (can_be_null) { unequal = "!this." + name + ".equals(that." + name + ")"; } else { unequal = "this." + name + " != that." + name; } out << indent() << "if (" << unequal << ")" << endl << indent() << " return false;" << endl; scope_down(out); } out << endl; indent(out) << "return true;" << endl; scope_down(out); out << endl; out << indent() << "public int hashCode() {" << endl; indent_up(); indent(out) << "return 0;" << endl; indent_down(); indent(out) << "}" << endl << endl; } void t_javame_generator::generate_java_struct_compare_to(ostream& out, t_struct* tstruct) { indent(out) << "public int compareTo(Object otherObject) {" << endl; // indent(out) << "public int compareTo(" << type_name(tstruct) << " other) {" << endl; indent_up(); indent(out) << "if (!getClass().equals(otherObject.getClass())) {" << endl; indent(out) << " return getClass().getName().compareTo(otherObject.getClass().getName());" << endl; indent(out) << "}" << endl; out << endl; indent(out) << type_name(tstruct) << " other = (" << type_name(tstruct) << ")otherObject;"; indent(out) << "int lastComparison = 0;" << endl; out << endl; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = *m_iter; indent(out) << "lastComparison = TBaseHelper.compareTo(" << generate_isset_check(field) << ", other." << generate_isset_check(field) << ");" << endl; indent(out) << "if (lastComparison != 0) {" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << "}" << endl; indent(out) << "if (" << generate_isset_check(field) << ") {" << endl; if (field->get_type()->is_struct() || field->get_type()->is_xception()) { indent(out) << " lastComparison = this." << field->get_name() << ".compareTo(other." << field->get_name() << ");" << endl; } else { indent(out) << " lastComparison = TBaseHelper.compareTo(this." << field->get_name() << ", other." << field->get_name() << ");" << endl; } indent(out) << " if (lastComparison != 0) {" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << " }" << endl; indent(out) << "}" << endl; } indent(out) << "return 0;" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a function to read all the fields of the struct. * * @param tstruct The struct definition */ void t_javame_generator::generate_java_struct_reader(ostream& out, t_struct* tstruct) { out << indent() << "public void read(TProtocol iprot) throws TException {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Declare stack tmp variables and read struct header out << indent() << "TField field;" << endl << indent() << "iprot.readStructBegin();" << endl; // Loop over reading in fields indent(out) << "while (true)" << endl; scope_up(out); // Read beginning field marker indent(out) << "field = iprot.readFieldBegin();" << endl; // Check for field STOP marker and break indent(out) << "if (field.type == TType.STOP) { " << endl; indent_up(); indent(out) << "break;" << endl; indent_down(); indent(out) << "}" << endl; // Switch statement on the field we are reading indent(out) << "switch (field.id) {" << endl; indent_up(); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << (*f_iter)->get_key() << ": // " << constant_name((*f_iter)->get_name()) << endl; indent_up(); indent(out) << "if (field.type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, "this."); generate_isset_set(out, *f_iter); indent_down(); out << indent() << "} else { " << endl << indent() << " TProtocolUtil.skip(iprot, field.type);" << endl << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } indent(out) << "default:" << endl; indent(out) << " TProtocolUtil.skip(iprot, field.type);" << endl; indent_down(); indent(out) << "}" << endl; // Read field end marker indent(out) << "iprot.readFieldEnd();" << endl; indent_down(); indent(out) << "}" << endl; out << indent() << "iprot.readStructEnd();" << endl; // performs various checks (e.g. check that all required fields are set) indent(out) << "validate();" << endl; indent_down(); out << indent() << "}" << endl << endl; } // generates java method to perform various checks // (e.g. check that all required fields are set) void t_javame_generator::generate_java_validator(ostream& out, t_struct* tstruct) { indent(out) << "public void validate() throws TException {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; out << indent() << "// check for required fields" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { out << indent() << "if (!" << generate_isset_check(*f_iter) << ") {" << endl << indent() << " throw new TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' is unset! Struct:\" + toString());" << endl << indent() << "}" << endl << endl; } } indent_down(); indent(out) << "}" << endl << endl; } /** * Generates a function to write all the fields of the struct * * @param tstruct The struct definition */ void t_javame_generator::generate_java_struct_writer(ostream& out, t_struct* tstruct) { out << indent() << "public void write(TProtocol oprot) throws TException {" << endl; indent_up(); string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; // performs various checks (e.g. check that all required fields are set) indent(out) << "validate();" << endl << endl; indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool null_allowed = type_can_be_null((*f_iter)->get_type()); if (null_allowed) { out << indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl; indent_up(); } bool optional = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (optional) { indent(out) << "if (" << generate_isset_check((*f_iter)) << ") {" << endl; indent_up(); } indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; if (optional) { indent_down(); indent(out) << "}" << endl; } if (null_allowed) { indent_down(); indent(out) << "}" << endl; } } // Write the struct map out << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();" << endl; indent_down(); out << indent() << "}" << endl << endl; } /** * Generates a function to write all the fields of the struct, * which is a function result. These fields are only written * if they are set in the Isset array, and only one of them * can be set at a time. * * @param tstruct The struct definition */ void t_javame_generator::generate_java_struct_result_writer(ostream& out, t_struct* tstruct) { out << indent() << "public void write(TProtocol oprot) throws TException {" << endl; indent_up(); string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent(out) << "oprot.writeStructBegin(STRUCT_DESC);" << endl; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; out << endl << indent() << "if "; } else { out << " else if "; } out << "(this." << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); indent(out) << "oprot.writeFieldBegin(" << constant_name((*f_iter)->get_name()) << "_FIELD_DESC);" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); // Write field closer indent(out) << "oprot.writeFieldEnd();" << endl; indent_down(); indent(out) << "}"; } // Write the struct map out << endl << indent() << "oprot.writeFieldStop();" << endl << indent() << "oprot.writeStructEnd();" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_javame_generator::generate_reflection_getters(ostringstream& out, t_type* type, string field_name, string cap_name) { indent(out) << "case " << constant_name(field_name) << ":" << endl; indent_up(); if (type->is_base_type() && !type->is_string()) { t_base_type* base_type = (t_base_type*)type; indent(out) << "return new " << type_name(type, true, false) << "(" << (base_type->is_bool() ? "is" : "get") << cap_name << "());" << endl << endl; } else { indent(out) << "return get" << cap_name << "();" << endl << endl; } indent_down(); } void t_javame_generator::generate_reflection_setters(ostringstream& out, t_type* type, string field_name, string cap_name) { indent(out) << "case " << constant_name(field_name) << ":" << endl; indent_up(); indent(out) << "if (value == null) {" << endl; indent(out) << " unset" << get_cap_name(field_name) << "();" << endl; indent(out) << "} else {" << endl; indent(out) << " set" << cap_name << "((" << type_name(type, true, false) << ")value);" << endl; indent(out) << "}" << endl; indent(out) << "break;" << endl << endl; indent_down(); } void t_javame_generator::generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct) { (void)out; std::ostringstream getter_stream; std::ostringstream setter_stream; // build up the bodies of both the getter and setter at once const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); indent_up(); generate_reflection_setters(setter_stream, type, field_name, cap_name); generate_reflection_getters(getter_stream, type, field_name, cap_name); indent_down(); } } /** * Generates a set of Java Bean boilerplate functions (setters, getters, etc.) * for the given struct. * * @param tstruct The struct definition */ void t_javame_generator::generate_java_bean_boilerplate(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; t_type* type = get_true_type(field->get_type()); std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); if (type->is_container()) { // Method to return the size of the collection indent(out) << "public int get" << cap_name; out << get_cap_name("size() {") << endl; indent_up(); indent(out) << "return (this." << field_name << " == null) ? 0 : " << "this." << field_name << ".size();" << endl; indent_down(); indent(out) << "}" << endl << endl; } if (type->is_set() || type->is_list()) { t_type* element_type; if (type->is_set()) { element_type = ((t_set*)type)->get_elem_type(); } else { element_type = ((t_list*)type)->get_elem_type(); } // Iterator getter for sets and lists indent(out) << "public Enumeration get" << cap_name; out << get_cap_name("Enumeration() {") << endl; indent_up(); indent(out) << "return (this." << field_name << " == null) ? null : " << "this." << field_name << ".elements();" << endl; indent_down(); indent(out) << "}" << endl << endl; // Add to set or list, create if the set/list is null indent(out); out << "public void add" << get_cap_name("to"); out << cap_name << "(" << type_name(element_type) << " elem) {" << endl; indent_up(); indent(out) << "if (this." << field_name << " == null) {" << endl; indent_up(); indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();" << endl; indent_down(); indent(out) << "}" << endl; if (type->is_set()) { indent(out) << "this." << field_name << ".put(" << box_type(element_type, "elem") << ", " << box_type(element_type, "elem") << ");" << endl; } else { indent(out) << "this." << field_name << ".addElement(" << box_type(element_type, "elem") << ");" << endl; } indent_down(); indent(out) << "}" << endl << endl; } else if (type->is_map()) { // Put to map t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); indent(out); out << "public void putTo" << cap_name << "(" << type_name(key_type, true) << " key, " << type_name(val_type, true) << " val) {" << endl; indent_up(); indent(out) << "if (this." << field_name << " == null) {" << endl; indent_up(); indent(out) << "this." << field_name << " = new " << type_name(type, false, true) << "();" << endl; indent_down(); indent(out) << "}" << endl; indent(out) << "this." << field_name << ".put(key, val);" << endl; indent_down(); indent(out) << "}" << endl << endl; } // Simple getter generate_java_doc(out, field); indent(out) << "public " << type_name(type); if (type->is_base_type() && ((t_base_type*)type)->get_base() == t_base_type::TYPE_BOOL) { out << " is"; } else { out << " get"; } out << cap_name << "() {" << endl; indent_up(); indent(out) << "return this." << field_name << ";" << endl; indent_down(); indent(out) << "}" << endl << endl; // Simple setter generate_java_doc(out, field); indent(out) << "public "; out << "void"; out << " set" << cap_name << "(" << type_name(type) << " " << field_name << ") {" << endl; indent_up(); indent(out) << "this." << field_name << " = " << field_name << ";" << endl; generate_isset_set(out, field); indent_down(); indent(out) << "}" << endl << endl; // Unsetter indent(out) << "public void unset" << cap_name << "() {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "this." << field_name << " = null;" << endl; } else { indent(out) << "__isset_vector[" << isset_field_id(field) << "] = false;" << endl; } indent_down(); indent(out) << "}" << endl << endl; // isSet method indent(out) << "/** Returns true if field " << field_name << " is set (has been assigned a value) and false otherwise */" << endl; indent(out) << "public boolean is" << get_cap_name("set") << cap_name << "() {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "return this." << field_name << " != null;" << endl; } else { indent(out) << "return __isset_vector[" << isset_field_id(field) << "];" << endl; } indent_down(); indent(out) << "}" << endl << endl; indent(out) << "public void set" << cap_name << get_cap_name("isSet") << "(boolean value) {" << endl; indent_up(); if (type_can_be_null(type)) { indent(out) << "if (!value) {" << endl; indent(out) << " this." << field_name << " = null;" << endl; indent(out) << "}" << endl; } else { indent(out) << "__isset_vector[" << isset_field_id(field) << "] = value;" << endl; } indent_down(); indent(out) << "}" << endl << endl; } } /** * Generates a toString() method for the given struct * * @param tstruct The struct definition */ void t_javame_generator::generate_java_struct_tostring(ostream& out, t_struct* tstruct) { out << indent() << "public String toString() {" << endl; indent_up(); out << indent() << "StringBuffer sb = new StringBuffer(\"" << tstruct->get_name() << "(\");" << endl; out << indent() << "boolean first = true;" << endl << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool could_be_unset = (*f_iter)->get_req() == t_field::T_OPTIONAL; if (could_be_unset) { indent(out) << "if (" << generate_isset_check(*f_iter) << ") {" << endl; indent_up(); } t_field* field = (*f_iter); if (!first) { indent(out) << "if (!first) sb.append(\", \");" << endl; } indent(out) << "sb.append(\"" << (*f_iter)->get_name() << ":\");" << endl; bool can_be_null = type_can_be_null(field->get_type()); if (can_be_null) { indent(out) << "if (this." << (*f_iter)->get_name() << " == null) {" << endl; indent(out) << " sb.append(\"null\");" << endl; indent(out) << "} else {" << endl; indent_up(); } if (field->get_type()->is_binary()) { indent(out) << "TBaseHelper.toString(this." << field->get_name() << ", sb);" << endl; } else { indent(out) << "sb.append(this." << (*f_iter)->get_name() << ");" << endl; } if (can_be_null) { indent_down(); indent(out) << "}" << endl; } indent(out) << "first = false;" << endl; if (could_be_unset) { indent_down(); indent(out) << "}" << endl; } first = false; } out << indent() << "sb.append(\")\");" << endl << indent() << "return sb.toString();" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Returns a string with the java representation of the given thrift type * (e.g. for the type struct it returns "TType.STRUCT") */ std::string t_javame_generator::get_java_type_string(t_type* type) { if (type->is_list()) { return "TType.LIST"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_enum()) { return "TType.ENUM"; } else if (type->is_typedef()) { return get_java_type_string(((t_typedef*)type)->get_type()); } else if (type->is_base_type()) { switch (((t_base_type*)type)->get_base()) { case t_base_type::TYPE_VOID: return "TType.VOID"; break; case t_base_type::TYPE_STRING: return "TType.STRING"; break; case t_base_type::TYPE_BOOL: return "TType.BOOL"; break; case t_base_type::TYPE_I8: return "TType.BYTE"; break; case t_base_type::TYPE_I16: return "TType.I16"; break; case t_base_type::TYPE_I32: return "TType.I32"; break; case t_base_type::TYPE_I64: return "TType.I64"; break; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; break; default: throw std::runtime_error("Unknown thrift type \"" + type->get_name() + "\" passed to t_javame_generator::get_java_type_string!"); break; // This should never happen! } } else { throw std::runtime_error( "Unknown thrift type \"" + type->get_name() + "\" passed to t_javame_generator::get_java_type_string!"); // This should never happen! } } void t_javame_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) { out << endl; indent_up(); indent_up(); if (type->is_struct() || type->is_xception()) { indent(out) << "new StructMetaData(TType.STRUCT, " << type_name(type) << ".class"; } else if (type->is_container()) { if (type->is_list()) { indent(out) << "new ListMetaData(TType.LIST, "; t_type* elem_type = ((t_list*)type)->get_elem_type(); generate_field_value_meta_data(out, elem_type); } else if (type->is_set()) { indent(out) << "new SetMetaData(TType.SET, "; t_type* elem_type = ((t_list*)type)->get_elem_type(); generate_field_value_meta_data(out, elem_type); } else { // map indent(out) << "new MapMetaData(TType.MAP, "; t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); generate_field_value_meta_data(out, key_type); out << ", "; generate_field_value_meta_data(out, val_type); } } else if (type->is_enum()) { indent(out) << "new EnumMetaData(TType.ENUM, " << type_name(type) << ".class"; } else { indent(out) << "new FieldValueMetaData(" << get_java_type_string(type); if (type->is_typedef()) { indent(out) << ", \"" << ((t_typedef*)type)->get_symbolic() << "\""; } } out << ")"; indent_down(); indent_down(); } /** * Generates a thrift service. In C++, this comprises an entirely separate * header and source file. The header file defines the methods and includes * the data types defined in the main header file, and the implementation * file contains implementations of the basic printer and default interfaces. * * @param tservice The service definition */ void t_javame_generator::generate_service(t_service* tservice) { // Make output file string f_service_name = package_dir_ + "/" + service_name_ + ".java"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports(); f_service_ << "public class " << service_name_ << " {" << endl << endl; indent_up(); // Generate the three main parts of the service generate_service_interface(tservice); generate_service_client(tservice); generate_service_server(tservice); generate_service_helpers(tservice); indent_down(); f_service_ << "}" << endl; f_service_.close(); } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_javame_generator::generate_primitive_service_interface(t_service* tservice) { f_service_ << indent() << "public interface Iface extends " << service_name_ << "Iface { }" << endl << endl; string f_interface_name = package_dir_ + "/" + service_name_ + "Iface.java"; ofstream_with_content_based_conditional_update f_iface; f_iface.open(f_interface_name.c_str()); string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends_iface = " extends " + type_name(tservice->get_extends()) + "Iface"; } f_iface << autogen_comment() << java_package() << java_type_imports() << java_thrift_imports(); generate_java_doc(f_iface, tservice); f_iface << "public interface " << service_name_ << "Iface" << extends_iface << " {" << endl << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_iface, *f_iter); f_iface << " public " << function_signature(*f_iter) << ";" << endl << endl; } f_iface << "}" << endl << endl; } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_javame_generator::generate_service_interface(t_service* tservice) { string extends = ""; string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_iface = " extends " + extends + ".Iface"; } generate_java_doc(f_service_, tservice); f_service_ << indent() << "public interface Iface" << extends_iface << " {" << endl << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_service_, *f_iter); indent(f_service_) << "public " << function_signature(*f_iter) << ";" << endl << endl; } indent_down(); f_service_ << indent() << "}" << endl << endl; } /** * Generates structs for all the service args and return types * * @param tservice The service */ void t_javame_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_java_struct_definition(f_service_, ts, false, true); generate_function_helpers(*f_iter); } } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_javame_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_client = " extends " + extends + ".Client"; } indent(f_service_) << "public static class Client" << extends_client << " implements TServiceClient, Iface {" << endl; indent_up(); indent(f_service_) << "public Client(TProtocol prot)" << endl; scope_up(f_service_); indent(f_service_) << "this(prot, prot);" << endl; scope_down(f_service_); f_service_ << endl; indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)" << endl; scope_up(f_service_); if (extends.empty()) { f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl; } else { f_service_ << indent() << "super(iprot, oprot);" << endl; } scope_down(f_service_); f_service_ << endl; if (extends.empty()) { f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent() << "protected TProtocol oprot_;" << endl << endl << indent() << "protected int seqid_;" << endl << endl; indent(f_service_) << "public TProtocol getInputProtocol()" << endl; scope_up(f_service_); indent(f_service_) << "return this.iprot_;" << endl; scope_down(f_service_); f_service_ << endl; indent(f_service_) << "public TProtocol getOutputProtocol()" << endl; scope_up(f_service_); indent(f_service_) << "return this.oprot_;" << endl; scope_down(f_service_); f_service_ << endl; } // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); // Open function indent(f_service_) << "public " << function_signature(*f_iter) << endl; scope_up(f_service_); indent(f_service_) << "send_" << funname << "("; // Get the struct of function call params t_struct* arg_struct = (*f_iter)->get_arglist(); // Declare the function arguments const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << (*fld_iter)->get_name(); } f_service_ << ");" << endl; if (!(*f_iter)->is_oneway()) { f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << "return "; } f_service_ << "recv_" << funname << "();" << endl; } scope_down(f_service_); f_service_ << endl; t_function send_function(g_type_void, string("send_") + (*f_iter)->get_name(), (*f_iter)->get_arglist()); string argsname = (*f_iter)->get_name() + "_args"; // Open function indent(f_service_) << "public " << function_signature(&send_function) << endl; scope_up(f_service_); // Serialize the request f_service_ << indent() << "oprot_.writeMessageBegin(new TMessage(\"" << funname << "\", " << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL") << ", ++seqid_));" << endl << indent() << argsname << " args = new " << argsname << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << indent() << "args.set" << get_cap_name((*fld_iter)->get_name()) << "(" << (*fld_iter)->get_name() << ");" << endl; } f_service_ << indent() << "args.write(oprot_);" << endl << indent() << "oprot_.writeMessageEnd();" << endl << indent() << "oprot_.getTransport().flush();" << endl; scope_down(f_service_); f_service_ << endl; if (!(*f_iter)->is_oneway()) { string resultname = (*f_iter)->get_name() + "_result"; t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs, (*f_iter)->get_xceptions()); // Open function indent(f_service_) << "public " << function_signature(&recv_function) << endl; scope_up(f_service_); f_service_ << indent() << "TMessage msg = iprot_.readMessageBegin();" << endl << indent() << "if (msg.type == TMessageType.EXCEPTION) {" << endl << indent() << " TApplicationException x = TApplicationException.read(iprot_);" << endl << indent() << " iprot_.readMessageEnd();" << endl << indent() << " throw x;" << endl << indent() << "}" << endl << indent() << "if (msg.seqid != seqid_) {" << endl << indent() << " throw new TApplicationException(TApplicationException.BAD_SEQUENCE_ID, \"" << (*f_iter)->get_name() << " failed: out of sequence response\");" << endl << indent() << "}" << endl << indent() << resultname << " result = new " << resultname << "();" << endl << indent() << "result.read(iprot_);" << endl << indent() << "iprot_.readMessageEnd();" << endl; // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << indent() << "if (result." << generate_isset_check("success") << ") {" << endl << indent() << " return result.success;" << endl << indent() << "}" << endl; } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "if (result." << (*x_iter)->get_name() << " != null) {" << endl << indent() << " throw result." << (*x_iter)->get_name() << ";" << endl << indent() << "}" << endl; } // If you get here it's an exception, unless a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "return;" << endl; } else { f_service_ << indent() << "throw new TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } // Close function scope_down(f_service_); f_service_ << endl; } } indent_down(); indent(f_service_) << "}" << endl; } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_javame_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; // Extends stuff string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_processor = " extends " + extends + ".Processor"; } // Generate the header portion indent(f_service_) << "public static class Processor" << extends_processor << " implements TProcessor {" << endl; indent_up(); indent(f_service_) << "public Processor(Iface iface)" << endl; scope_up(f_service_); if (!extends.empty()) { f_service_ << indent() << "super(iface);" << endl; } f_service_ << indent() << "iface_ = iface;" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << indent() << "processMap_.put(\"" << (*f_iter)->get_name() << "\", new " << (*f_iter)->get_name() << "());" << endl; } scope_down(f_service_); f_service_ << endl; if (extends.empty()) { f_service_ << indent() << "protected static interface ProcessFunction {" << endl << indent() << " public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException;" << endl << indent() << "}" << endl << endl; } f_service_ << indent() << "private Iface iface_;" << endl; if (extends.empty()) { f_service_ << indent() << "protected final Hashtable processMap_ = new Hashtable();" << endl; } f_service_ << endl; // Generate the server implementation indent(f_service_) << "public boolean process(TProtocol iprot, TProtocol oprot) throws TException" << endl; scope_up(f_service_); f_service_ << indent() << "TMessage msg = iprot.readMessageBegin();" << endl; // TODO(mcslee): validate message, was the seqid etc. legit? f_service_ << indent() << "ProcessFunction fn = (ProcessFunction)processMap_.get(msg.name);" << endl << indent() << "if (fn == null) {" << endl << indent() << " TProtocolUtil.skip(iprot, TType.STRUCT);" << endl << indent() << " iprot.readMessageEnd();" << endl << indent() << " TApplicationException x = new " "TApplicationException(TApplicationException.UNKNOWN_METHOD, \"Invalid method name: " "'\"+msg.name+\"'\");" << endl << indent() << " oprot.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid));" << endl << indent() << " x.write(oprot);" << endl << indent() << " oprot.writeMessageEnd();" << endl << indent() << " oprot.getTransport().flush();" << endl << indent() << " return true;" << endl << indent() << "}" << endl << indent() << "fn.process(msg.seqid, iprot, oprot);" << endl; f_service_ << indent() << "return true;" << endl; scope_down(f_service_); f_service_ << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } indent_down(); indent(f_service_) << "}" << endl << endl; } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_javame_generator::generate_function_helpers(t_function* tfunction) { if (tfunction->is_oneway()) { return; } t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_java_struct_definition(f_service_, &result, false, true, true); } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_javame_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; // Open class indent(f_service_) << "private class " << tfunction->get_name() << " implements ProcessFunction {" << endl; indent_up(); // Open function indent(f_service_) << "public void process(int seqid, TProtocol iprot, TProtocol oprot) throws TException" << endl; scope_up(f_service_); string argsname = tfunction->get_name() + "_args"; string resultname = tfunction->get_name() + "_result"; f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl << indent() << "try {" << endl; indent_up(); f_service_ << indent() << "args.read(iprot);" << endl; indent_down(); f_service_ << indent() << "} catch (TProtocolException e) {" << endl; indent_up(); f_service_ << indent() << "iprot.readMessageEnd();" << endl << indent() << "TApplicationException x = new " "TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage());" << endl << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl << indent() << "x.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();" << endl << indent() << "oprot.getTransport().flush();" << endl << indent() << "return;" << endl; indent_down(); f_service_ << indent() << "}" << endl; f_service_ << indent() << "iprot.readMessageEnd();" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl; } // Try block for a function with exceptions if (xceptions.size() > 0) { f_service_ << indent() << "try {" << endl; indent_up(); } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "result.success = "; } f_service_ << "iface_." << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << ");" << endl; // Set isset on success field if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void() && !type_can_be_null(tfunction->get_returntype())) { f_service_ << indent() << "result.set" << get_cap_name("success") << get_cap_name("isSet") << "(true);" << endl; } if (!tfunction->is_oneway() && xceptions.size() > 0) { indent_down(); f_service_ << indent() << "}"; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << " catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ") {" << endl; if (!tfunction->is_oneway()) { indent_up(); f_service_ << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl; indent_down(); f_service_ << indent() << "}"; } else { f_service_ << "}"; } } f_service_ << " catch (Throwable th) {" << endl; indent_up(); f_service_ << indent() << "TApplicationException x = new " "TApplicationException(TApplicationException.INTERNAL_ERROR, " "\"Internal error processing " << tfunction->get_name() << "\");" << endl << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.EXCEPTION, seqid));" << endl << indent() << "x.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();" << endl << indent() << "oprot.getTransport().flush();" << endl << indent() << "return;" << endl; indent_down(); f_service_ << indent() << "}" << endl; } // Shortcut out here for oneway functions if (tfunction->is_oneway()) { f_service_ << indent() << "return;" << endl; scope_down(f_service_); // Close class indent_down(); f_service_ << indent() << "}" << endl << endl; return; } f_service_ << indent() << "oprot.writeMessageBegin(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid));" << endl << indent() << "result.write(oprot);" << endl << indent() << "oprot.writeMessageEnd();" << endl << indent() << "oprot.getTransport().flush();" << endl; // Close function scope_down(f_service_); f_service_ << endl; // Close class indent_down(); f_service_ << indent() << "}" << endl << endl; } /** * Deserializes a field of any type. * * @param tfield The field * @param prefix The variable name or container for this field */ void t_javame_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + tfield->get_name(); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type()) { indent(out) << name << " = iprot."; t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (!type->is_binary()) { out << "readString();"; } else { out << "readBinary();"; } break; case t_base_type::TYPE_BOOL: out << "readBool();"; break; case t_base_type::TYPE_I8: out << "readByte();"; break; case t_base_type::TYPE_I16: out << "readI16();"; break; case t_base_type::TYPE_I32: out << "readI32();"; break; case t_base_type::TYPE_I64: out << "readI64();"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble();"; break; default: throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase); } out << endl; } else if (type->is_enum()) { indent(out) << name << " = " << type_name(tfield->get_type(), true, false) + ".findByValue(iprot.readI32());" << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); } } /** * Generates an unserializer for a struct, invokes read() */ void t_javame_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent() << prefix << ".read(iprot);" << endl; } /** * Deserializes a container by reading its size and then iterating */ void t_javame_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); string obj; if (ttype->is_map()) { obj = tmp("_map"); } else if (ttype->is_set()) { obj = tmp("_set"); } else if (ttype->is_list()) { obj = tmp("_list"); } // Declare variables, read header if (ttype->is_map()) { indent(out) << "TMap " << obj << " = iprot.readMapBegin();" << endl; } else if (ttype->is_set()) { indent(out) << "TSet " << obj << " = iprot.readSetBegin();" << endl; } else if (ttype->is_list()) { indent(out) << "TList " << obj << " = iprot.readListBegin();" << endl; } indent(out) << prefix << " = new " << type_name(ttype, false, true) // size the collection correctly << "(" << (ttype->is_list() ? "" : "2*") << obj << ".size" << ");" << endl; // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (int " << i << " = 0; " << i << " < " << obj << ".size" << "; " << "++" << i << ")" << endl; scope_up(out); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } scope_down(out); // Read container end if (ttype->is_map()) { indent(out) << "iprot.readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "iprot.readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "iprot.readListEnd();" << endl; } scope_down(out); } /** * Generates code to deserialize a map */ void t_javame_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey) << endl; indent(out) << declare_field(&fval) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << prefix << ".put(" << box_type(tmap->get_key_type(), key) << ", " << box_type(tmap->get_val_type(), val) << ");" << endl; } /** * Deserializes a set element */ void t_javame_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".put(" << box_type(tset->get_elem_type(), elem) << ", " << box_type(tset->get_elem_type(), elem) << ");" << endl; } /** * Deserializes a list element */ void t_javame_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".addElement(" << box_type(tlist->get_elem_type(), elem) << ");" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_javame_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name()); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + tfield->get_name()); } else if (type->is_enum()) { indent(out) << "oprot.writeI32(" << prefix + tfield->get_name() << ".getValue());" << endl; } else if (type->is_base_type()) { string name = prefix + tfield->get_name(); indent(out) << "oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "writeBinary(" << name << ");"; } else { out << "writeString(" << name << ");"; } break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ");"; break; default: throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32(" << name << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type_name(type).c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_javame_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; out << indent() << prefix << ".write(oprot);" << endl; } /** * Serializes a container by writing its size then the elements. * * @param ttype The type of container * @param prefix String prefix for fields */ void t_javame_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); if (ttype->is_map()) { indent(out) << "oprot.writeMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix << ".size()));" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix << ".size()));" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListBegin(new TList(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".size()));" << endl; } string iter = tmp("_iter"); if (ttype->is_map()) { string enumer = iter + "_enum"; string key_type = type_name(((t_map*)ttype)->get_key_type(), true, false); indent(out) << "for (Enumeration " << enumer << " = " << prefix << ".keys(); " << enumer << ".hasMoreElements(); ) "; scope_up(out); indent(out) << key_type << " " << iter << " = (" << key_type << ")" << enumer << ".nextElement();" << endl; } else if (ttype->is_set()) { string enumer = iter + "_enum"; string ele_type = type_name(((t_list*)ttype)->get_elem_type(), true); indent(out) << "for (Enumeration " << enumer << " = " << prefix << ".keys(); " << enumer << ".hasMoreElements(); ) "; scope_up(out); indent(out) << ele_type << " " << iter << " = (" << ele_type << ")" << enumer << ".nextElement();" << endl; } else if (ttype->is_list()) { string enumer = iter + "_enum"; indent(out) << "for (Enumeration " << enumer << " = " << prefix << ".elements(); " << enumer << ".hasMoreElements(); ) "; scope_up(out); string ele_type = type_name(((t_list*)ttype)->get_elem_type(), true); indent(out) << ele_type << " " << iter << " = (" << ele_type << ")" << enumer << ".nextElement();" << endl; } if (ttype->is_map()) { generate_serialize_map_element(out, (t_map*)ttype, iter, prefix); } else if (ttype->is_set()) { generate_serialize_set_element(out, (t_set*)ttype, iter); } else if (ttype->is_list()) { generate_serialize_list_element(out, (t_list*)ttype, iter); } scope_down(out); if (ttype->is_map()) { indent(out) << "oprot.writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListEnd();" << endl; } scope_down(out); } /** * Serializes the members of a map. */ void t_javame_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map) { t_field kfield(tmap->get_key_type(), iter); generate_serialize_field(out, &kfield, ""); string val_type = type_name(tmap->get_val_type(), true, false); t_field vfield(tmap->get_val_type(), "((" + val_type + ")" + map + ".get(" + iter + "))"); generate_serialize_field(out, &vfield, ""); } /** * Serializes the members of a set. */ void t_javame_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Serializes the members of a list. */ void t_javame_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Returns a Java type name * * @param ttype The type * @param container Is the type going inside a container? * @return Java type name, i.e. Vector */ string t_javame_generator::type_name(t_type* ttype, bool in_container, bool in_init, bool skip_generic) { (void)in_init; (void)skip_generic; // In Java typedefs are just resolved to their real type ttype = get_true_type(ttype); string prefix; if (ttype->is_base_type()) { return base_type_name((t_base_type*)ttype, in_container); } else if (ttype->is_map()) { return "Hashtable"; } else if (ttype->is_set()) { return "Hashtable"; } else if (ttype->is_list()) { return "Vector"; } // Check for namespacing t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { string package = program->get_namespace("java"); if (!package.empty()) { return package + "." + ttype->get_name(); } } return ttype->get_name(); } /** * Returns the C++ type that corresponds to the thrift type. * * @param tbase The base type * @param container Is it going in a Java container? */ string t_javame_generator::base_type_name(t_base_type* type, bool in_container) { t_base_type::t_base tbase = type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: if (!type->is_binary()) { return "String"; } else { return "byte[]"; } case t_base_type::TYPE_BOOL: return (in_container ? "Boolean" : "boolean"); case t_base_type::TYPE_I8: return (in_container ? "Byte" : "byte"); case t_base_type::TYPE_I16: return (in_container ? "Short" : "short"); case t_base_type::TYPE_I32: return (in_container ? "Integer" : "int"); case t_base_type::TYPE_I64: return (in_container ? "Long" : "long"); case t_base_type::TYPE_DOUBLE: return (in_container ? "Double" : "double"); default: throw "compiler error: no Java name for base type " + t_base_type::t_base_name(tbase); } } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type */ string t_javame_generator::declare_field(t_field* tfield, bool init) { // TODO(mcslee): do we ever need to initialize the field? string result = type_name(tfield->get_type()) + " " + tfield->get_name(); if (init) { t_type* ttype = get_true_type(tfield->get_type()); if (ttype->is_base_type() && tfield->get_value() != nullptr) { std::ofstream dummy; result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value()); } else if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: result += " = null"; break; case t_base_type::TYPE_BOOL: result += " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = (double)0"; break; default: throw "compiler error: unhandled type"; } } else if (ttype->is_enum()) { result += " = 0"; } else if (ttype->is_container()) { result += " = new " + type_name(ttype, false, true) + "()"; } else { result += " = new " + type_name(ttype, false, true) + "()"; ; } } return result + ";"; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_javame_generator::function_signature(t_function* tfunction, string prefix) { t_type* ttype = tfunction->get_returntype(); std::string result = type_name(ttype) + " " + prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ") throws "; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { result += type_name((*x_iter)->get_type(), false, false) + ", "; } result += "TException"; return result; } /** * Renders a comma separated field list, with type names */ string t_javame_generator::argument_list(t_struct* tstruct, bool include_types) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } if (include_types) { result += type_name((*f_iter)->get_type()) + " "; } result += (*f_iter)->get_name(); } return result; } /** * Converts the parse type to a C++ enum string for the given type. */ string t_javame_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.STRING"; case t_base_type::TYPE_BOOL: return "TType.BOOL"; case t_base_type::TYPE_I8: return "TType.BYTE"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_list()) { return "TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Applies the correct style to a string based on the value of nocamel_style_ */ std::string t_javame_generator::get_cap_name(std::string name) { name[0] = toupper(name[0]); return name; } string t_javame_generator::constant_name(string name) { string constant_name; bool is_first = true; bool was_previous_char_upper = false; for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { constant_name += '_'; } constant_name += toupper(character); is_first = false; was_previous_char_upper = is_upper; } return constant_name; } void t_javame_generator::generate_java_docstring_comment(ostream& out, string contents) { generate_docstring_comment(out, "/**\n", " * ", contents, " */\n"); } void t_javame_generator::generate_java_doc(ostream& out, t_field* field) { if (field->get_type()->is_enum()) { string combined_message = field->get_doc() + "\n@see " + get_enum_class_name(field->get_type()); generate_java_docstring_comment(out, combined_message); } else { generate_java_doc(out, (t_doc*)field); } } /** * Emits a JavaDoc comment if the provided object has a doc in Thrift */ void t_javame_generator::generate_java_doc(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_java_docstring_comment(out, tdoc->get_doc()); } } /** * Emits a JavaDoc comment if the provided function object has a doc in Thrift */ void t_javame_generator::generate_java_doc(ostream& out, t_function* tfunction) { if (tfunction->has_doc()) { stringstream ss; ss << tfunction->get_doc(); const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ss << "\n@param " << p->get_name(); if (p->has_doc()) { ss << " " << p->get_doc(); } } generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n"); } } void t_javame_generator::generate_deep_copy_container(ostream& out, std::string source_name_p1, std::string source_name_p2, std::string result_name, t_type* type) { t_container* container = (t_container*)type; std::string source_name; if (source_name_p2 == "") source_name = source_name_p1; else source_name = source_name_p1 + "." + source_name_p2; indent(out) << type_name(type, true, false) << " " << result_name << " = new " << type_name(container, false, true) << "();" << endl; std::string iterator_element_name = source_name_p1 + "_element"; std::string enumeration_name = source_name_p1 + "_enum"; std::string result_element_name = result_name + "_copy"; if (container->is_map()) { t_type* key_type = ((t_map*)container)->get_key_type(); t_type* val_type = ((t_map*)container)->get_val_type(); indent(out) << "for (Enumeration " << enumeration_name << " = " << source_name << ".keys(); " << enumeration_name << ".hasMoreElements(); ) {" << endl; indent_up(); out << endl; indent(out) << type_name(key_type, true, false) << " " << iterator_element_name << "_key = (" << type_name(key_type, true, false) << ")" << enumeration_name << ".nextElement();" << endl; indent(out) << type_name(val_type, true, false) << " " << iterator_element_name << "_value = (" << type_name(val_type, true, false) << ")" << source_name << ".get(" << iterator_element_name << "_key);" << endl; out << endl; if (key_type->is_container()) { generate_deep_copy_container(out, iterator_element_name + "_key", "", result_element_name + "_key", key_type); } else { indent(out) << type_name(key_type, true, false) << " " << result_element_name << "_key = "; generate_deep_copy_non_container(out, iterator_element_name + "_key", result_element_name + "_key", key_type); out << ";" << endl; } out << endl; if (val_type->is_container()) { generate_deep_copy_container(out, iterator_element_name + "_value", "", result_element_name + "_value", val_type); } else { indent(out) << type_name(val_type, true, false) << " " << result_element_name << "_value = "; generate_deep_copy_non_container(out, iterator_element_name + "_value", result_element_name + "_value", val_type); out << ";" << endl; } out << endl; indent(out) << result_name << ".put(" << result_element_name << "_key, " << result_element_name << "_value);" << endl; indent_down(); indent(out) << "}" << endl; } else { t_type* elem_type; if (container->is_set()) { elem_type = ((t_set*)container)->get_elem_type(); } else { elem_type = ((t_list*)container)->get_elem_type(); } indent(out) << "for (Enumeration " << enumeration_name << " = " << source_name << ".elements(); " << enumeration_name << ".hasMoreElements(); ) {" << endl; indent_up(); indent(out) << type_name(elem_type, true, false) << " " << iterator_element_name << " = (" << type_name(elem_type, true, false) << ")" << enumeration_name << ".nextElement();" << endl; if (elem_type->is_container()) { // recursive deep copy generate_deep_copy_container(out, iterator_element_name, "", result_element_name, elem_type); if (elem_type->is_list()) { indent(out) << result_name << ".addElement(" << result_element_name << ");" << endl; } else { indent(out) << result_name << ".put(" << result_element_name << ", " << result_element_name << ");" << endl; } } else { // iterative copy if (elem_type->is_binary()) { indent(out) << type_name(elem_type, true, false) << " temp_binary_element = "; generate_deep_copy_non_container(out, iterator_element_name, "temp_binary_element", elem_type); out << ";" << endl; if (elem_type->is_list()) { indent(out) << result_name << ".addElement(temp_binary_element);" << endl; } else { indent(out) << result_name << ".put(temp_binary_element, temp_binary_element);" << endl; } } else { indent(out) << result_name << ".addElement("; generate_deep_copy_non_container(out, iterator_element_name, result_name, elem_type); out << ");" << endl; } } indent_down(); indent(out) << "}" << endl; } } void t_javame_generator::generate_deep_copy_non_container(ostream& out, std::string source_name, std::string dest_name, t_type* type) { if (type->is_base_type() || type->is_enum() || type->is_typedef()) { // binary fields need to be copied with System.arraycopy if (type->is_binary()) { out << "new byte[" << source_name << ".length];" << endl; indent(out) << "System.arraycopy(" << source_name << ", 0, " << dest_name << ", 0, " << source_name << ".length)"; } // everything else can be copied directly else out << source_name; } else { out << "new " << type_name(type, true, true) << "(" << source_name << ")"; } } std::string t_javame_generator::generate_isset_check(t_field* field) { return generate_isset_check(field->get_name()); } std::string t_javame_generator::isset_field_id(t_field* field) { return "__" + upcase_string(field->get_name() + "_isset_id"); } std::string t_javame_generator::generate_isset_check(std::string field_name) { return "is" + get_cap_name("set") + get_cap_name(field_name) + "()"; } void t_javame_generator::generate_isset_set(ostream& out, t_field* field) { if (!type_can_be_null(field->get_type())) { indent(out) << "set" << get_cap_name(field->get_name()) << get_cap_name("isSet") << "(true);" << endl; } } std::string t_javame_generator::get_enum_class_name(t_type* type) { string package = ""; t_program* program = type->get_program(); if (program != nullptr && program != program_) { package = program->get_namespace("java") + "."; } return package + type->get_name(); } void t_javame_generator::generate_struct_desc(ostream& out, t_struct* tstruct) { indent(out) << "private static final TStruct STRUCT_DESC = new TStruct(\"" << tstruct->get_name() << "\");" << endl; } void t_javame_generator::generate_field_descs(ostream& out, t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "private static final TField " << constant_name((*m_iter)->get_name()) << "_FIELD_DESC = new TField(\"" << (*m_iter)->get_name() << "\", " << type_to_enum((*m_iter)->get_type()) << ", " << "(short)" << (*m_iter)->get_key() << ");" << endl; } } bool t_javame_generator::has_bit_vector(t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!type_can_be_null(get_true_type((*m_iter)->get_type()))) { return true; } } return false; } void t_javame_generator::generate_java_struct_clear(std::ostream& out, t_struct* tstruct) { indent(out) << "public void clear() {" << endl; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr) { print_const_value(out, "this." + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); } else { if (type_can_be_null(t)) { indent(out) << "this." << (*m_iter)->get_name() << " = null;" << endl; } else { // must be a base type // means it also needs to be explicitly unset indent(out) << "set" << get_cap_name((*m_iter)->get_name()) << get_cap_name("isSet") << "(false);" << endl; switch (((t_base_type*)t)->get_base()) { case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: indent(out) << "this." << (*m_iter)->get_name() << " = 0;" << endl; break; case t_base_type::TYPE_DOUBLE: indent(out) << "this." << (*m_iter)->get_name() << " = 0.0;" << endl; break; case t_base_type::TYPE_BOOL: indent(out) << "this." << (*m_iter)->get_name() << " = false;" << endl; break; default: // prevent gcc compiler warning break; } } } } indent_down(); indent(out) << "}" << endl << endl; } std::string t_javame_generator::display_name() const { return "Java ME"; } THRIFT_REGISTER_GENERATOR(javame, "Java ME", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_generator_registry.h0000644000000000000000000001030614303740367025775 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_GENERATOR_REGISTRY_H #define T_GENERATOR_REGISTRY_H class t_generator; /** * A factory for producing generator classes of a particular language. * * This class is also responsible for: * - Registering itself with the generator registry. * - Providing documentation for the generators it produces. */ class t_generator_factory { public: t_generator_factory(const std::string& short_name, const std::string& long_name, const std::string& documentation); virtual ~t_generator_factory() = default; virtual t_generator* get_generator( // The program to generate. t_program* program, // Note: parsed_options will not exist beyond the call to get_generator. const std::map& parsed_options, // Note: option_string might not exist beyond the call to get_generator. const std::string& option_string) = 0; virtual bool is_valid_namespace(const std::string& sub_namespace) = 0; std::string get_short_name() { return short_name_; } std::string get_long_name() { return long_name_; } std::string get_documentation() { return documentation_; } private: std::string short_name_; std::string long_name_; std::string documentation_; }; template class t_generator_factory_impl : public t_generator_factory { public: t_generator_factory_impl(const std::string& short_name, const std::string& long_name, const std::string& documentation) : t_generator_factory(short_name, long_name, documentation) {} t_generator* get_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) override { return new generator(program, parsed_options, option_string); } bool is_valid_namespace(const std::string& sub_namespace) override { return generator::is_valid_namespace(sub_namespace); } }; class t_generator_registry { public: static void register_generator(t_generator_factory* factory); static t_generator* get_generator(t_program* program, const std::string& options); static t_generator* get_generator(t_program* program, const std::string& laugnage, const std::map& parsed_options, const std::string& options); typedef std::map gen_map_t; static gen_map_t& get_generator_map(); private: t_generator_registry(); t_generator_registry(const t_generator_registry&); }; #define THRIFT_REGISTER_GENERATOR(language, long_name, doc) \ class t_##language##_generator_factory_impl \ : public t_generator_factory_impl { \ public: \ t_##language##_generator_factory_impl() \ : t_generator_factory_impl(#language, long_name, doc) {} \ }; \ static t_##language##_generator_factory_impl _registerer; #endif thrift-0.19.0/compiler/cpp/src/thrift/generate/t_oop_generator.h0000644000000000000000000000665214452237057024735 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_OOP_GENERATOR_H #define T_OOP_GENERATOR_H #include #include #include "thrift/common.h" #include "thrift/generate/t_generator.h" #include /** * Class with utility methods shared across common object oriented languages. * Specifically, most of this stuff is for C++/Java. * */ class t_oop_generator : public t_generator { public: t_oop_generator(t_program* program) : t_generator(program) {} /** * Scoping, using curly braces! */ void scope_up(std::ostream& out) { indent(out) << "{" << std::endl; indent_up(); } void scope_down(std::ostream& out) { indent_down(); indent(out) << "}" << std::endl; } std::string upcase_string(std::string original) { std::transform(original.begin(), original.end(), original.begin(), (int (*)(int))toupper); return original; } virtual std::string get_enum_class_name(t_type* type) { std::string package = ""; t_program* program = type->get_program(); if (program != nullptr && program != program_) { package = program->get_namespace("java") + "."; } return package + type->get_name(); } virtual void generate_java_docstring_comment(std::ostream& out, std::string contents) { generate_docstring_comment(out, "/**\n", " * ", contents, " */\n"); } virtual void generate_java_doc(std::ostream& out, t_field* field) { if (get_true_type(field->get_type())->is_enum()) { std::string combined_message = field->get_doc() + "\n@see " + get_enum_class_name(field->get_type()); generate_java_docstring_comment(out, combined_message); } else { generate_java_doc(out, (t_doc*)field); } } /** * Emits a JavaDoc comment if the provided object has a doc in Thrift */ virtual void generate_java_doc(std::ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_java_docstring_comment(out, tdoc->get_doc()); } } /** * Emits a JavaDoc comment if the provided function object has a doc in Thrift */ virtual void generate_java_doc(std::ostream& out, t_function* tfunction) { if (tfunction->has_doc()) { std::stringstream ss; ss << tfunction->get_doc(); const std::vector& fields = tfunction->get_arglist()->get_members(); std::vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ss << "\n@param " << p->get_name(); if (p->has_doc()) { ss << " " << p->get_doc(); } } generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n"); } } }; #endif thrift-0.19.0/compiler/cpp/src/thrift/generate/t_gv_generator.cc0000644000000000000000000002522014370300523024666 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostringstream; using std::pair; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * Graphviz code generator */ class t_gv_generator : public t_generator { public: t_gv_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; exception_arrows = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("exceptions") == 0) { exception_arrows = true; } else { throw "unknown option gv:" + iter->first; } } out_dir_base_ = "gen-gv"; } /** * Init and end of generator */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_service(t_service* tservice) override; protected: /** * Helpers */ void print_type(t_type* ttype, string struct_field_ref); void print_const_value(t_type* type, t_const_value* tvalue); private: ofstream_with_content_based_conditional_update f_out_; std::list edges; bool exception_arrows; }; /** * Init generator: * - Adds some escaping for the Graphviz domain. * - Create output directory and open file for writting. * - Write the file header. */ void t_gv_generator::init_generator() { escape_['{'] = "\\{"; escape_['}'] = "\\}"; // Make output directory MKDIR(get_out_dir().c_str()); string fname = get_out_dir() + program_->get_name() + ".gv"; f_out_.open(fname.c_str()); f_out_ << "digraph \"" << escape_string(program_name_) << "\" {" << endl; f_out_ << "node [style=filled, shape=record];" << endl; f_out_ << "edge [arrowsize=0.5];" << endl; f_out_ << "rankdir=LR" << endl; } /** * Closes generator: * - Print accumulated nodes connections. * - Print footnote. * - Closes file. */ void t_gv_generator::close_generator() { // Print edges std::list::iterator iter = edges.begin(); for (; iter != edges.end(); iter++) { f_out_ << (*iter) << endl; } // Print graph end } and close file f_out_ << "}" << endl; f_out_.close(); } void t_gv_generator::generate_typedef(t_typedef* ttypedef) { string name = ttypedef->get_name(); f_out_ << "node [fillcolor=azure];" << endl; f_out_ << name << " [label=\""; f_out_ << escape_string(name); f_out_ << " :: "; print_type(ttypedef->get_type(), name); f_out_ << "\"];" << endl; } void t_gv_generator::generate_enum(t_enum* tenum) { string name = tenum->get_name(); f_out_ << "node [fillcolor=white];" << endl; f_out_ << name << " [label=\"enum " << escape_string(name); vector values = tenum->get_constants(); vector::iterator val_iter; for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) { f_out_ << '|' << (*val_iter)->get_name(); f_out_ << " = "; f_out_ << (*val_iter)->get_value(); } f_out_ << "\"];" << endl; } void t_gv_generator::generate_const(t_const* tconst) { string name = tconst->get_name(); f_out_ << "node [fillcolor=aliceblue];" << endl; f_out_ << "const_" << name << " [label=\""; f_out_ << escape_string(name); f_out_ << " = "; print_const_value(tconst->get_type(), tconst->get_value()); f_out_ << " :: "; print_type(tconst->get_type(), "const_" + name); f_out_ << "\"];" << endl; } void t_gv_generator::generate_struct(t_struct* tstruct) { string name = tstruct->get_name(); if (tstruct->is_xception()) { f_out_ << "node [fillcolor=lightpink];" << endl; f_out_ << name << " [label=\""; f_out_ << "exception " << escape_string(name); } else if (tstruct->is_union()) { f_out_ << "node [fillcolor=lightcyan];" << endl; f_out_ << name << " [label=\""; f_out_ << "union " << escape_string(name); } else { f_out_ << "node [fillcolor=beige];" << endl; f_out_ << name << " [label=\""; f_out_ << "struct " << escape_string(name); } vector members = tstruct->get_members(); vector::iterator mem_iter = members.begin(); for (; mem_iter != members.end(); mem_iter++) { string field_name = (*mem_iter)->get_name(); // print port (anchor reference) f_out_ << "|'; // field name :: field type f_out_ << (*mem_iter)->get_name(); f_out_ << " :: "; print_type((*mem_iter)->get_type(), name + ":field_" + field_name); } f_out_ << "\"];" << endl; } void t_gv_generator::print_type(t_type* ttype, string struct_field_ref) { if (ttype->is_container()) { if (ttype->is_list()) { f_out_ << "list\\<"; print_type(((t_list*)ttype)->get_elem_type(), struct_field_ref); f_out_ << "\\>"; } else if (ttype->is_set()) { f_out_ << "set\\<"; print_type(((t_set*)ttype)->get_elem_type(), struct_field_ref); f_out_ << "\\>"; } else if (ttype->is_map()) { f_out_ << "map\\<"; print_type(((t_map*)ttype)->get_key_type(), struct_field_ref); f_out_ << ", "; print_type(((t_map*)ttype)->get_val_type(), struct_field_ref); f_out_ << "\\>"; } } else if (ttype->is_base_type()) { f_out_ << (ttype->is_binary() ? "binary" : ttype->get_name()); } else { f_out_ << ttype->get_name(); edges.push_back(struct_field_ref + " -> " + ttype->get_name()); } } /** * Prints out an string representation of the provided constant value */ void t_gv_generator::print_const_value(t_type* type, t_const_value* tvalue) { bool first = true; switch (tvalue->get_type()) { case t_const_value::CV_INTEGER: f_out_ << tvalue->get_integer(); break; case t_const_value::CV_DOUBLE: f_out_ << tvalue->get_double(); break; case t_const_value::CV_STRING: f_out_ << "\\\"" << get_escaped_string(tvalue) << "\\\""; break; case t_const_value::CV_MAP: { f_out_ << "\\{ "; map map_elems = tvalue->get_map(); map::iterator map_iter; for (map_iter = map_elems.begin(); map_iter != map_elems.end(); map_iter++) { if (!first) { f_out_ << ", "; } first = false; print_const_value(((t_map*)type)->get_key_type(), map_iter->first); f_out_ << " = "; print_const_value(((t_map*)type)->get_val_type(), map_iter->second); } f_out_ << " \\}"; } break; case t_const_value::CV_LIST: { f_out_ << "\\{ "; vector list_elems = tvalue->get_list(); ; vector::iterator list_iter; for (list_iter = list_elems.begin(); list_iter != list_elems.end(); list_iter++) { if (!first) { f_out_ << ", "; } first = false; if (type->is_list()) { print_const_value(((t_list*)type)->get_elem_type(), *list_iter); } else { print_const_value(((t_set*)type)->get_elem_type(), *list_iter); } } f_out_ << " \\}"; } break; case t_const_value::CV_IDENTIFIER: f_out_ << escape_string(type->get_name()) << "." << escape_string(tvalue->get_identifier_name()); break; default: f_out_ << "UNKNOWN"; break; } } void t_gv_generator::generate_service(t_service* tservice) { string service_name = get_service_name(tservice); f_out_ << "subgraph cluster_" << service_name << " {" << endl; f_out_ << "node [fillcolor=bisque];" << endl; f_out_ << "style=dashed;" << endl; f_out_ << "label = \"" << escape_string(service_name) << " service\";" << endl; // TODO: service extends vector functions = tservice->get_functions(); vector::iterator fn_iter = functions.begin(); for (; fn_iter != functions.end(); fn_iter++) { string fn_name = (*fn_iter)->get_name(); f_out_ << "function_" << service_name << fn_name; f_out_ << "[label=\"function " << escape_string(fn_name); f_out_ << " :: "; print_type((*fn_iter)->get_returntype(), "function_" + service_name + fn_name + ":return_type"); vector args = (*fn_iter)->get_arglist()->get_members(); vector::iterator arg_iter = args.begin(); for (; arg_iter != args.end(); arg_iter++) { f_out_ << "|get_name() << ">"; f_out_ << (*arg_iter)->get_name(); if ((*arg_iter)->get_value() != nullptr) { f_out_ << " = "; print_const_value((*arg_iter)->get_type(), (*arg_iter)->get_value()); } f_out_ << " :: "; print_type((*arg_iter)->get_type(), "function_" + service_name + fn_name + ":param_" + (*arg_iter)->get_name()); } // end of node f_out_ << "\"];" << endl; // Exception edges if (exception_arrows) { vector excepts = (*fn_iter)->get_xceptions()->get_members(); vector::iterator ex_iter = excepts.begin(); for (; ex_iter != excepts.end(); ex_iter++) { edges.push_back("function_" + service_name + fn_name + " -> " + (*ex_iter)->get_type()->get_name() + " [color=red]"); } } } f_out_ << " }" << endl; } std::string t_gv_generator::display_name() const { return "Graphviz"; } THRIFT_REGISTER_GENERATOR( gv, "Graphviz", " exceptions: Whether to draw arrows from functions to exception.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/validator_parser.h0000644000000000000000000001671114370300523025071 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_VALIDATOR_GENERATOR_H #define T_VALIDATOR_GENERATOR_H #include "thrift/generate/t_generator.h" #include #include #include #include #include class validation_value { public: struct validation_function { public: std::string name; std::vector arguments; }; enum validation_value_type { VV_INTEGER, VV_DOUBLE, VV_BOOL, VV_ENUM, VV_STRING, VV_FUNCTION, VV_FIELD_REFERENCE, VV_UNKNOWN }; validation_value() : val_type(VV_UNKNOWN) {} validation_value(const int64_t val) : int_val(val), val_type(VV_INTEGER) {} validation_value(const double val) : double_val(val), val_type(VV_DOUBLE) {} validation_value(const bool val) : bool_val(val), val_type(VV_BOOL) {} validation_value(t_enum_value* val) : enum_val(val), val_type(VV_ENUM) {} validation_value(const std::string val) : string_val(val), val_type(VV_STRING) {} validation_value(validation_function* val) : function_val(val), val_type(VV_FUNCTION) {} validation_value(t_field* val) : field_reference_val(val), val_type(VV_FIELD_REFERENCE) {} void set_int(const int64_t val) { int_val = val; val_type = VV_INTEGER; } int64_t get_int() const { return int_val; }; void set_double(const double val) { double_val = val; val_type = VV_DOUBLE; } double get_double() { return double_val; }; void set_bool(const bool val) { bool_val = val; val_type = VV_BOOL; } bool get_bool() const { return bool_val; }; void set_enum(t_enum_value* val) { enum_val = val; val_type = VV_ENUM; } t_enum_value* get_enum() const { return enum_val; }; void set_string(const std::string val) { string_val = val; val_type = VV_STRING; } std::string get_string() const { return string_val; }; void set_function(validation_function* val) { function_val = val; val_type = VV_FUNCTION; } validation_function* get_function() { return function_val; }; void set_field_reference(t_field* val) { field_reference_val = val; val_type = VV_FIELD_REFERENCE; } t_field* get_field_reference() const { return field_reference_val; }; bool is_field_reference() const { return val_type == VV_FIELD_REFERENCE; }; bool is_validation_function() const { return val_type == VV_FUNCTION; }; validation_value_type get_type() const { return val_type; }; private: int64_t int_val = 0; double double_val = 0.0; bool bool_val = false; t_enum_value* enum_val = nullptr; std::string string_val; validation_function* function_val = nullptr; t_field* field_reference_val = nullptr; validation_value_type val_type; }; class validation_rule { public: validation_rule(){}; validation_rule(std::string name) : name(name){}; validation_rule(std::string name, validation_rule* inner) : name(name), inner(inner){}; std::string get_name() { return name; }; void append_value(validation_value* value) { values.push_back(value); } const std::vector& get_values() { return values; }; validation_rule* get_inner() { return inner; }; private: std::string name; std::vector values; validation_rule* inner = nullptr; }; class validation_parser { public: validation_parser() {} validation_parser(t_struct* reference) : reference(reference) {} std::vector parse_field( t_type* type, std::map>& annotations); void set_reference(t_struct* reference) { this->reference = reference; }; private: std::vector parse_bool_field( t_type* type, std::map>& annotations); std::vector parse_enum_field( t_type* type, std::map>& annotations); std::vector parse_double_field( t_type* type, std::map>& annotations); std::vector parse_integer_field( t_type* type, std::map>& annotations); std::vector parse_string_field( t_type* type, std::map>& annotations); std::vector parse_set_field( t_type* type, std::map>& annotations); std::vector parse_list_field( t_type* type, std::map>& annotations); std::vector parse_map_field( t_type* type, std::map>& annotations); std::vector parse_struct_field( t_type* type, std::map>& annotations); std::vector parse_xception_field( t_type* type, std::map>& annotations); std::vector parse_union_field( t_type* type, std::map>& annotations); bool is_reference_field(std::string value); bool is_validation_function(std::string value); void add_bool_rule(std::vector& rules, std::string key, std::map>& annotations); void add_double_rule(std::vector& rules, std::string key, std::map>& annotations); void add_double_list_rule(std::vector& rules, std::string key, std::map>& annotations); void add_integer_rule(std::vector& rules, std::string key, std::map>& annotations); void add_integer_list_rule(std::vector& rules, std::string key, std::map>& annotations); void add_string_rule(std::vector& rules, std::string key, std::map>& annotations); void add_enum_list_rule(std::vector& rules, t_enum* enum_, std::string key, std::map>& annotations); t_field* get_referenced_field(std::string annotation_value); validation_value::validation_function* get_validation_function(std::string annotation_value); t_struct* reference = nullptr; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/generate/t_lua_generator.cc0000644000000000000000000011711314370300523025036 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::ostream; using std::string; using std::vector; using std::map; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * LUA code generator. * */ class t_lua_generator : public t_oop_generator { public: t_lua_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; gen_requires_ = true; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("omit_requires") == 0) { gen_requires_ = false; } else { throw "unknown option lua:" + iter->first; } } out_dir_base_ = "gen-lua"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); private: /** * True iff we should generate lua require statements. */ bool gen_requires_; /** * Struct-level generation functions */ void generate_lua_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false); void generate_lua_struct_reader(std::ostream& out, t_struct* tstruct); void generate_lua_struct_writer(std::ostream& out, t_struct* tstruct); /** * Service-level generation functions */ void generate_service_client(std::ostream& out, t_service* tservice); void generate_service_interface(std::ostream& out, t_service* tservice); void generate_service_processor(std::ostream& out, t_service* tservice); void generate_process_function(std::ostream& out, t_service* tservice, t_function* tfunction); void generate_service_helpers(ostream& out, t_service* tservice); void generate_function_helpers(ostream& out, t_function* tfunction); /** * Deserialization (Read) */ void generate_deserialize_field(std::ostream& out, t_field* tfield, bool local, std::string prefix = ""); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, bool local, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, bool local, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); /** * Serialization (Write) */ void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); /** * Helper rendering functions */ std::string lua_includes(); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct, std::string prefix = ""); std::string type_to_enum(t_type* ttype); static std::string get_namespace(const t_program* program); std::string autogen_comment() override { return std::string("--\n") + "-- Autogenerated by Thrift\n" + "--\n" + "-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "-- @" "generated\n" + "--\n"; } /** * File streams */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_consts_; ofstream_with_content_based_conditional_update f_service_; }; /** * Init and close methods */ void t_lua_generator::init_generator() { // Make output directory string outdir = get_out_dir(); MKDIR(outdir.c_str()); // Make output files string cur_namespace = get_namespace(program_); string f_consts_name = outdir + cur_namespace + "constants.lua"; f_consts_.open(f_consts_name.c_str()); string f_types_name = outdir + cur_namespace + "ttypes.lua"; f_types_.open(f_types_name.c_str()); // Add headers f_consts_ << autogen_comment() << lua_includes(); f_types_ << autogen_comment() << lua_includes(); if (gen_requires_) { f_types_ << endl << "require '" << cur_namespace << "constants'"; } } void t_lua_generator::close_generator() { // Close types file f_types_.close(); f_consts_.close(); } /** * Generate a typedef (essentially a constant) */ void t_lua_generator::generate_typedef(t_typedef* ttypedef) { if (ttypedef->get_type()->get_name().empty()) { return; } f_types_ << endl << endl << indent() << ttypedef->get_symbolic() << " = " << ttypedef->get_type()->get_name(); } /** * Generates code for an enumerated type (table) */ void t_lua_generator::generate_enum(t_enum* tenum) { f_types_ << endl << endl << tenum->get_name() << " = {" << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end();) { int32_t value = (*c_iter)->get_value(); f_types_ << " " << (*c_iter)->get_name() << " = " << value; ++c_iter; if (c_iter != constants.end()) { f_types_ << ","; } f_types_ << endl; } f_types_ << "}"; } /** * Generate a constant (non-local) value */ void t_lua_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); f_consts_ << endl << endl << name << " = "; f_consts_ << render_const_value(type, value); } /** * Prints the value of a constant with the given type. */ string t_lua_generator::render_const_value(t_type* type, t_const_value* value) { std::ostringstream out; type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << "'" << value->get_string() << "'"; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: out << value->get_integer(); break; case t_base_type::TYPE_I64: out << "lualongnumber.new('" << value->get_integer() << "')"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << type->get_name() << " = {" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } indent(out); out << render_const_value(g_type_string, v_iter->first); out << " = "; out << render_const_value(field_type, v_iter->second); ++v_iter; if (v_iter != val.end()) { out << ","; } } out << "}"; indent_down(); } else if (type->is_map()) { out << type->get_name() << "{" << endl; indent_up(); t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { indent(out) << "[" << render_const_value(ktype, v_iter->first) << "] = " << render_const_value(vtype, v_iter->second); ++v_iter; if (v_iter != val.end()) { out << ","; } out << endl; } indent_down(); indent(out) << "}"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } out << type->get_name() << " = {" << endl; const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { indent(out); out << "[" << render_const_value(etype, *v_iter) << "]"; if (type->is_set()) { out << " = true"; } else { out << " = false"; } ++v_iter; if (v_iter != val.end()) { out << "," << endl; } } out << "}"; } return out.str(); } /** * Generate a thrift struct */ void t_lua_generator::generate_struct(t_struct* tstruct) { generate_lua_struct_definition(f_types_, tstruct, false); } /** * Generate a thrift exception */ void t_lua_generator::generate_xception(t_struct* txception) { generate_lua_struct_definition(f_types_, txception, true); } /** * Generate a thrift struct or exception (lua table) */ void t_lua_generator::generate_lua_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) { vector::const_iterator m_iter; const vector& members = tstruct->get_members(); indent(out) << endl << endl << tstruct->get_name(); if (is_exception) { out << " = TException:new{" << endl << indent() << " __type = '" << tstruct->get_name() << "'"; if (members.size() > 0) { out << ","; } out << endl; } else { out << " = __TObject:new{" << endl; } indent_up(); for (m_iter = members.begin(); m_iter != members.end();) { indent(out); out << (*m_iter)->get_name(); ++m_iter; if (m_iter != members.end()) { out << "," << endl; } } indent_down(); indent(out); out << endl << "}"; generate_lua_struct_reader(out, tstruct); generate_lua_struct_writer(out, tstruct); } /** * Generate a struct/exception reader */ void t_lua_generator::generate_lua_struct_reader(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // function indent(out) << endl << endl << "function " << tstruct->get_name() << ":read(iprot)" << endl; indent_up(); indent(out) << "iprot:readStructBegin()" << endl; // while: Read in fields indent(out) << "while true do" << endl; indent_up(); // if: Check what to read indent(out) << "local fname, ftype, fid = iprot:readFieldBegin()" << endl; indent(out) << "if ftype == TType.STOP then" << endl; indent_up(); indent(out) << "break" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent_down(); indent(out) << "elseif fid == " << (*f_iter)->get_key() << " then" << endl; indent_up(); indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << " then" << endl; indent_up(); // Read field contents generate_deserialize_field(out, *f_iter, false, "self."); indent_down(); indent(out) << "else" << endl; indent(out) << " iprot:skip(ftype)" << endl; indent(out) << "end" << endl; } // end if indent_down(); indent(out) << "else" << endl; indent(out) << " iprot:skip(ftype)" << endl; indent(out) << "end" << endl; indent(out) << "iprot:readFieldEnd()" << endl; // end while indent_down(); indent(out) << "end" << endl; indent(out) << "iprot:readStructEnd()" << endl; // end function indent_down(); indent(out); out << "end"; } /** * Generate a struct/exception writer */ void t_lua_generator::generate_lua_struct_writer(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // function indent(out) << endl << endl << "function " << tstruct->get_name() << ":write(oprot)" << endl; indent_up(); indent(out) << "oprot:writeStructBegin('" << tstruct->get_name() << "')" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { // To check element of self whether nil or not. // avoid the value(false) of BOOL is lost. indent(out) << "if self." << (*f_iter)->get_name() << " ~= nil then" << endl; indent_up(); indent(out) << "oprot:writeFieldBegin('" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ")" << endl; // Write field contents generate_serialize_field(out, *f_iter, "self."); indent(out) << "oprot:writeFieldEnd()" << endl; indent_down(); indent(out) << "end" << endl; } indent(out) << "oprot:writeFieldStop()" << endl; indent(out) << "oprot:writeStructEnd()" << endl; // end function indent_down(); indent(out); out << "end"; } /** * Generate a thrift service */ void t_lua_generator::generate_service(t_service* tservice) { // Get output directory string outdir = get_out_dir(); // Open the file for writing string cur_ns = get_namespace(program_); string f_service_name = outdir + cur_ns + tservice->get_name() + ".lua"; f_service_.open(f_service_name.c_str()); // Headers f_service_ << autogen_comment() << lua_includes(); if (gen_requires_) { f_service_ << endl << "require '" << cur_ns << "ttypes'" << endl; if (tservice->get_extends() != nullptr) { f_service_ << "require '" << get_namespace(tservice->get_extends()->get_program()) << tservice->get_extends()->get_name() << "'" << endl; } } f_service_ << endl; generate_service_client(f_service_, tservice); generate_service_interface(f_service_, tservice); generate_service_processor(f_service_, tservice); generate_service_helpers(f_service_, tservice); // Close the file f_service_.close(); } void t_lua_generator::generate_service_interface(ostream& out, t_service* tservice) { string classname = tservice->get_name() + "Iface"; t_service* extends_s = tservice->get_extends(); // Interface object definition out << classname << " = "; if (extends_s) { out << extends_s->get_name() << "Iface:new{" << endl; } else { out << "__TObject:new{" << endl; } out << " __type = '" << classname << "'" << endl << "}" << endl << endl; } void t_lua_generator::generate_service_client(ostream& out, t_service* tservice) { string classname = tservice->get_name() + "Client"; t_service* extends_s = tservice->get_extends(); // Client object definition out << classname << " = __TObject.new("; if (extends_s != nullptr) { out << extends_s->get_name() << "Client"; } else { out << "__TClient"; } out << ", {" << endl << " __type = '" << classname << "'" << endl << "})" << endl; // Send/Recv functions vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string sig = function_signature(*f_iter); string funcname = (*f_iter)->get_name(); // Wrapper function indent(out) << endl << "function " << classname << ":" << sig << endl; indent_up(); indent(out) << "self:send_" << sig << endl << indent(); if (!(*f_iter)->is_oneway()) { if (!(*f_iter)->get_returntype()->is_void()) { out << "return "; } out << "self:recv_" << sig << endl; } indent_down(); indent(out) << "end" << endl; // Send function indent(out) << endl << "function " << classname << ":send_" << sig << endl; indent_up(); indent(out) << "self.oprot:writeMessageBegin('" << funcname << "', " << ((*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL") << ", self._seqid)" << endl; indent(out) << "local args = " << funcname << "_args:new{}" << endl; // Set the args const vector& args = (*f_iter)->get_arglist()->get_members(); vector::const_iterator fld_iter; for (fld_iter = args.begin(); fld_iter != args.end(); ++fld_iter) { std::string argname = (*fld_iter)->get_name(); if ((*fld_iter)->get_value() != nullptr) { // Insert default value for nil arguments t_type* type = get_true_type((*fld_iter)->get_type()); indent(out) << "if " << argname << " ~= nil then" << endl; indent_up(); indent(out) << "args." << argname << " = " << argname << endl; indent_down(); indent(out) << "else" << endl; indent_up(); indent(out) << "args." << argname << " = " << render_const_value(type, (*fld_iter)->get_value()) << endl; indent_down(); indent(out) << "end" << endl; } else { indent(out) << "args." << argname << " = " << argname << endl; } } indent(out) << "args:write(self.oprot)" << endl; indent(out) << "self.oprot:writeMessageEnd()" << endl; indent(out) << "self.oprot.trans:flush()" << endl; indent_down(); indent(out) << "end" << endl; // Recv function if (!(*f_iter)->is_oneway()) { indent(out) << endl << "function " << classname << ":recv_" << sig << endl; indent_up(); out << indent() << "local fname, mtype, rseqid = self.iprot:" << "readMessageBegin()" << endl << indent() << "if mtype == TMessageType.EXCEPTION then" << endl << indent() << " local x = TApplicationException:new{}" << endl << indent() << " x:read(self.iprot)" << endl << indent() << " self.iprot:readMessageEnd()" << endl << indent() << " error(x)" << endl << indent() << "end" << endl << indent() << "local result = " << funcname << "_result:new{}" << endl << indent() << "result:read(self.iprot)" << endl << indent() << "self.iprot:readMessageEnd()" << endl; // Return the result if it's not a void function if (!(*f_iter)->get_returntype()->is_void()) { out << indent() << "if result.success ~= nil then" << endl << indent() << " return result.success" << endl; // Throw custom exceptions const std::vector& xf = (*f_iter)->get_xceptions()->get_members(); vector::const_iterator x_iter; for (x_iter = xf.begin(); x_iter != xf.end(); ++x_iter) { out << indent() << "elseif result." << (*x_iter)->get_name() << " then" << endl << indent() << " error(result." << (*x_iter)->get_name() << ")" << endl; } out << indent() << "end" << endl << indent() << "error(TApplicationException:new{errorCode = " << "TApplicationException.MISSING_RESULT})" << endl; } indent_down(); indent(out) << "end" << endl; } } } void t_lua_generator::generate_service_processor(ostream& out, t_service* tservice) { string classname = tservice->get_name() + "Processor"; t_service* extends_s = tservice->get_extends(); // Define processor table out << endl << classname << " = __TObject.new("; if (extends_s != nullptr) { out << extends_s->get_name() << "Processor" << endl; } else { out << "__TProcessor" << endl; } out << ", {" << endl << " __type = '" << classname << "'" << endl << "})" << endl; // Process function indent(out) << endl << "function " << classname << ":process(iprot, oprot, server_ctx)" << endl; indent_up(); indent(out) << "local name, mtype, seqid = iprot:readMessageBegin()" << endl; indent(out) << "local func_name = 'process_' .. name" << endl; indent(out) << "if not self[func_name] or ttype(self[func_name]) ~= 'function' then" << endl; indent_up(); indent(out) << "if oprot ~= nil then"; indent_up(); out << endl << indent() << "iprot:skip(TType.STRUCT)" << endl << indent() << "iprot:readMessageEnd()" << endl << indent() << "x = TApplicationException:new{" << endl << indent() << " errorCode = TApplicationException.UNKNOWN_METHOD" << endl << indent() << "}" << endl << indent() << "oprot:writeMessageBegin(name, TMessageType.EXCEPTION, " << "seqid)" << endl << indent() << "x:write(oprot)" << endl << indent() << "oprot:writeMessageEnd()" << endl << indent() << "oprot.trans:flush()" << endl; indent_down(); out << indent() << "end" << endl << indent() << "return false, 'Unknown function '..name" << endl; indent_down(); indent(out) << "else" << endl << indent() << " return self[func_name](self, seqid, iprot, oprot, server_ctx)" << endl << indent() << "end" << endl; indent_down(); indent(out) << "end" << endl; // Generate the process subfunctions vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(out, tservice, *f_iter); } } void t_lua_generator::generate_process_function(ostream& out, t_service* tservice, t_function* tfunction) { string classname = tservice->get_name() + "Processor"; string argsname = tfunction->get_name() + "_args"; string resultname = tfunction->get_name() + "_result"; string fn_name = tfunction->get_name(); indent(out) << endl << "function " << classname << ":process_" << fn_name << "(seqid, iprot, oprot, server_ctx)" << endl; indent_up(); // Read the request out << indent() << "local args = " << argsname << ":new{}" << endl << indent() << "local reply_type = TMessageType.REPLY" << endl << indent() << "args:read(iprot)" << endl << indent() << "iprot:readMessageEnd()" << endl; if (!tfunction->is_oneway()) { out << indent() << "local result = " << resultname << ":new{}" << endl; } out << indent() << "local status, res = pcall(self.handler." << fn_name << ", self.handler"; // Print arguments t_struct* args = tfunction->get_arglist(); if (args->get_members().size() > 0) { out << ", " << argument_list(args, "args."); } out << ")" << endl; if (!tfunction->is_oneway()) { // Check for errors out << indent() << "if not status then" << endl << indent() << " reply_type = TMessageType.EXCEPTION" << endl << indent() << " result = TApplicationException:new{message = res}" << endl; // Handle custom exceptions const std::vector& xf = tfunction->get_xceptions()->get_members(); if (xf.size() > 0) { vector::const_iterator x_iter; for (x_iter = xf.begin(); x_iter != xf.end(); ++x_iter) { out << indent() << "elseif ttype(res) == '" << (*x_iter)->get_type()->get_name() << "' then" << endl << indent() << " result." << (*x_iter)->get_name() << " = res" << endl; } } // Set the result and write the reply out << indent() << "else" << endl << indent() << " result.success = res" << endl << indent() << "end" << endl << indent() << "oprot:writeMessageBegin('" << fn_name << "', reply_type, " << "seqid)" << endl << indent() << "result:write(oprot)" << endl << indent() << "oprot:writeMessageEnd()" << endl << indent() << "oprot.trans:flush()" << endl; } out << indent() << "return status, res" << endl; indent_down(); indent(out) << "end" << endl; } // Service helpers void t_lua_generator::generate_service_helpers(ostream& out, t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; out << endl << "-- HELPER FUNCTIONS AND STRUCTURES"; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_lua_struct_definition(out, ts, false); generate_function_helpers(out, *f_iter); } } void t_lua_generator::generate_function_helpers(ostream& out, t_function* tfunction) { if (!tfunction->is_oneway()) { t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_lua_struct_definition(out, &result, false); } } /** * Deserialize (Read) */ void t_lua_generator::generate_deserialize_field(ostream& out, t_field* tfield, bool local, string prefix) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + tfield->get_name(); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, local, name); } else if (type->is_container()) { generate_deserialize_container(out, type, local, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << (local ? "local " : "") << name << " = iprot:"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "readString()"; break; case t_base_type::TYPE_BOOL: out << "readBool()"; break; case t_base_type::TYPE_I8: out << "readByte()"; break; case t_base_type::TYPE_I16: out << "readI16()"; break; case t_base_type::TYPE_I32: out << "readI32()"; break; case t_base_type::TYPE_I64: out << "readI64()"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble()"; break; default: throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "readI32()"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); } } void t_lua_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, bool local, string prefix) { indent(out) << (local ? "local " : "") << prefix << " = " << tstruct->get_name() << ":new{}" << endl << indent() << prefix << ":read(iprot)" << endl; } void t_lua_generator::generate_deserialize_container(ostream& out, t_type* ttype, bool local, string prefix) { string size = tmp("_size"); string ktype = tmp("_ktype"); string vtype = tmp("_vtype"); string etype = tmp("_etype"); t_field fsize(g_type_i32, size); t_field fktype(g_type_i8, ktype); t_field fvtype(g_type_i8, vtype); t_field fetype(g_type_i8, etype); // Declare variables, read header indent(out) << (local ? "local " : "") << prefix << " = {}" << endl; if (ttype->is_map()) { indent(out) << "local " << ktype << ", " << vtype << ", " << size << " = iprot:readMapBegin() " << endl; } else if (ttype->is_set()) { indent(out) << "local " << etype << ", " << size << " = iprot:readSetBegin()" << endl; } else if (ttype->is_list()) { indent(out) << "local " << etype << ", " << size << " = iprot:readListBegin()" << endl; } // Deserialize indent(out) << "for _i=1," << size << " do" << endl; indent_up(); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } indent_down(); indent(out) << "end" << endl; // Read container end if (ttype->is_map()) { indent(out) << "iprot:readMapEnd()" << endl; } else if (ttype->is_set()) { indent(out) << "iprot:readSetEnd()" << endl; } else if (ttype->is_list()) { indent(out) << "iprot:readListEnd()" << endl; } } void t_lua_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { // A map is represented by a table indexable by any lua type string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); generate_deserialize_field(out, &fkey, true); generate_deserialize_field(out, &fval, true); indent(out) << prefix << "[" << key << "] = " << val << endl; } void t_lua_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { // A set is represented by a table indexed by the value string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); generate_deserialize_field(out, &felem, true); indent(out) << prefix << "[" << elem << "] = " << elem << endl; } void t_lua_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { // A list is represented by a table indexed by integer values // LUA natively provides all of the functions required to maintain a list string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); generate_deserialize_field(out, &felem, true); indent(out) << "table.insert(" << prefix << ", " << elem << ")" << endl; } /** * Serialize (Write) */ void t_lua_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); string name = prefix + tfield->get_name(); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_serialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << "oprot:"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "writeString(" << name << ")"; break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ")"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ")"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ")"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ")"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ")"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ")"; break; default: throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32(" << name << ")"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n", name.c_str(), type->get_name().c_str()); } } void t_lua_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << prefix << ":write(oprot)" << endl; } void t_lua_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { // Begin writing if (ttype->is_map()) { indent(out) << "oprot:writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "ttable_size(" << prefix << "))" << endl; } else if (ttype->is_set()) { indent(out) << "oprot:writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << "ttable_size(" << prefix << "))" << endl; } else if (ttype->is_list()) { indent(out) << "oprot:writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << "#" << prefix << ")" << endl; } // Serialize if (ttype->is_map()) { string kiter = tmp("kiter"); string viter = tmp("viter"); indent(out) << "for " << kiter << "," << viter << " in pairs(" << prefix << ") do" << endl; indent_up(); generate_serialize_map_element(out, (t_map*)ttype, kiter, viter); indent_down(); indent(out) << "end" << endl; } else if (ttype->is_set()) { string iter = tmp("iter"); indent(out) << "for " << iter << ",_ in pairs(" << prefix << ") do" << endl; indent_up(); generate_serialize_set_element(out, (t_set*)ttype, iter); indent_down(); indent(out) << "end" << endl; } else if (ttype->is_list()) { string iter = tmp("iter"); indent(out) << "for _," << iter << " in ipairs(" << prefix << ") do" << endl; indent_up(); generate_serialize_list_element(out, (t_list*)ttype, iter); indent_down(); indent(out) << "end" << endl; } // Finish writing if (ttype->is_map()) { indent(out) << "oprot:writeMapEnd()" << endl; } else if (ttype->is_set()) { indent(out) << "oprot:writeSetEnd()" << endl; } else if (ttype->is_list()) { indent(out) << "oprot:writeListEnd()" << endl; } } void t_lua_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), kiter); generate_serialize_field(out, &kfield, ""); t_field vfield(tmap->get_val_type(), viter); generate_serialize_field(out, &vfield, ""); } void t_lua_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } void t_lua_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Helper rendering functions */ string t_lua_generator::lua_includes() { if (gen_requires_) { return "\n\nrequire 'Thrift'"; } else { return ""; } } string t_lua_generator::get_namespace(const t_program* program) { std::string real_module = program->get_namespace("lua"); if (real_module.empty()) { return program->get_name() + "_"; } return real_module + "_"; } string t_lua_generator::function_signature(t_function* tfunction, string prefix) { (void)prefix; std::string ret = tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")"; return ret; } string t_lua_generator::argument_list(t_struct* tstruct, string prefix) { const vector& fields = tstruct->get_members(); vector::const_iterator fld_iter; std::string ret = ""; for (fld_iter = fields.begin(); fld_iter != fields.end();) { ret += prefix + (*fld_iter)->get_name(); ++fld_iter; if (fld_iter != fields.end()) { ret += ", "; } } return ret; } string t_lua_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.STRING"; case t_base_type::TYPE_BOOL: return "TType.BOOL"; case t_base_type::TYPE_I8: return "TType.BYTE"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_list()) { return "TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_lua_generator::display_name() const { return "Lua"; } THRIFT_REGISTER_GENERATOR( lua, "Lua", " omit_requires: Suppress generation of require 'somefile'.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/validator_parser.cc0000644000000000000000000004720414370300523025230 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This file is programmatically sanitized for style: * astyle --style=1tbs -f -p -H -j -U t_validator_parser.cc * * The output of astyle should not be taken unquestioningly, but it is a good * guide for ensuring uniformity and readability. */ #include #include #include #include #include #include #include "thrift/generate/t_generator.h" #include "thrift/generate/validator_parser.h" #include "thrift/platform.h" #include "thrift/version.h" #include #include #include #include #include #include const char* list_delimiter = "[], "; std::vector validation_parser::parse_field( t_type* type, std::map>& annotations) { std::vector empty_rules; if (type->is_typedef()) { type = type->get_true_type(); } if (type->is_enum()) { return parse_enum_field(type, annotations); } else if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_UUID: case t_base_type::TYPE_VOID: return empty_rules; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return parse_integer_field(type, annotations); case t_base_type::TYPE_DOUBLE: return parse_double_field(type, annotations); case t_base_type::TYPE_STRING: return parse_string_field(type, annotations); case t_base_type::TYPE_BOOL: return parse_bool_field(type, annotations); } } else if (type->is_list()) { return parse_list_field(type, annotations); } else if (type->is_set()) { return parse_set_field(type, annotations); } else if (type->is_map()) { return parse_map_field(type, annotations); } else if (type->is_struct()) { if (((t_struct*)type)->is_union()) { return parse_union_field(type, annotations); } return parse_struct_field(type, annotations); } else if (type->is_xception()) { return parse_xception_field(type, annotations); } throw "validator error: unsupported type: " + type->get_name(); } std::vector validation_parser::parse_bool_field( t_type* type, std::map>& annotations) { (void)type; std::vector rules; add_bool_rule(rules, "vt.const", annotations); return rules; } std::vector validation_parser::parse_enum_field( t_type* type, std::map>& annotations) { std::vector rules; add_bool_rule(rules, "vt.defined_only", annotations); add_enum_list_rule(rules, (t_enum*)type, "vt.in", annotations); add_enum_list_rule(rules, (t_enum*)type, "vt.not_in", annotations); return rules; } std::vector validation_parser::parse_double_field( t_type* type, std::map>& annotations) { (void)type; std::vector rules; add_double_rule(rules, "vt.lt", annotations); add_double_rule(rules, "vt.le", annotations); add_double_rule(rules, "vt.gt", annotations); add_double_rule(rules, "vt.ge", annotations); add_double_list_rule(rules, "vt.in", annotations); add_double_list_rule(rules, "vt.not_in", annotations); return rules; } std::vector validation_parser::parse_integer_field( t_type* type, std::map>& annotations) { (void)type; std::vector rules; add_integer_rule(rules, "vt.lt", annotations); add_integer_rule(rules, "vt.le", annotations); add_integer_rule(rules, "vt.gt", annotations); add_integer_rule(rules, "vt.ge", annotations); add_integer_list_rule(rules, "vt.in", annotations); add_integer_list_rule(rules, "vt.not_in", annotations); return rules; } std::vector validation_parser::parse_string_field( t_type* type, std::map>& annotations) { (void)type; std::vector rules; add_string_rule(rules, "vt.const", annotations); add_integer_rule(rules, "vt.min_size", annotations); add_integer_rule(rules, "vt.max_size", annotations); add_string_rule(rules, "vt.pattern", annotations); add_string_rule(rules, "vt.prefix", annotations); add_string_rule(rules, "vt.suffix", annotations); add_string_rule(rules, "vt.contains", annotations); add_string_rule(rules, "vt.not_contains", annotations); return rules; } std::vector validation_parser::parse_set_field( t_type* type, std::map>& annotations) { (void)type; return parse_list_field(type, annotations); } std::vector validation_parser::parse_list_field( t_type* type, std::map>& annotations) { (void)type; std::vector rules; add_integer_rule(rules, "vt.min_size", annotations); add_integer_rule(rules, "vt.max_size", annotations); std::string elem_prefix("vt.elem"); std::map> elem_annotations; for (auto it = annotations.begin(); it != annotations.end(); it++) { if (it->first.compare(0, elem_prefix.size(), elem_prefix) == 0) { std::string elem_key = "vt" + it->first.substr(elem_prefix.size()); elem_annotations[elem_key] = it->second; } } std::vector elem_rules; if (type->is_list()) { elem_rules = parse_field(((t_list*)type)->get_elem_type(), elem_annotations); } else if (type->is_set()) { elem_rules = parse_field(((t_set*)type)->get_elem_type(), elem_annotations); } for (auto it = elem_rules.begin(); it != elem_rules.end(); it++) { validation_rule* rule = new validation_rule(elem_prefix, *it); rules.push_back(rule); } return rules; } std::vector validation_parser::parse_map_field( t_type* type, std::map>& annotations) { std::vector rules; add_integer_rule(rules, "vt.min_size", annotations); add_integer_rule(rules, "vt.max_size", annotations); std::string key_prefix("vt.key"); std::map> key_annotations; for (auto it = annotations.begin(); it != annotations.end(); it++) { if (it->first.compare(0, key_prefix.size(), key_prefix) == 0) { std::string key_key = "vt" + it->first.substr(key_prefix.size()); key_annotations[key_key] = it->second; } } std::vector key_rules; key_rules = parse_field(((t_map*)type)->get_key_type(), key_annotations); for (auto it = key_rules.begin(); it != key_rules.end(); it++) { validation_rule* rule = new validation_rule(key_prefix, *it); rules.push_back(rule); } std::string value_prefix("vt.value"); std::map> value_annotations; for (auto it = annotations.begin(); it != annotations.end(); it++) { if (it->first.compare(0, value_prefix.size(), value_prefix) == 0) { std::string value_key = "vt" + it->first.substr(value_prefix.size()); value_annotations[value_key] = it->second; } } std::vector value_rules; value_rules = parse_field(((t_map*)type)->get_val_type(), value_annotations); for (auto it = value_rules.begin(); it != value_rules.end(); it++) { validation_rule* rule = new validation_rule(value_prefix, *it); rules.push_back(rule); } return rules; } std::vector validation_parser::parse_struct_field( t_type* type, std::map>& annotations) { (void)type; std::vector rules; add_bool_rule(rules, "vt.skip", annotations); return rules; } std::vector validation_parser::parse_xception_field( t_type* type, std::map>& annotations) { return parse_struct_field(type, annotations); } std::vector validation_parser::parse_union_field( t_type* type, std::map>& annotations) { return parse_struct_field(type, annotations); } bool validation_parser::is_reference_field(std::string value) { if (value[0] != '$') { return false; } value.erase(value.begin()); t_field* field = this->reference->get_field_by_name(value); return field != nullptr; } bool validation_parser::is_validation_function(std::string value) { if (value[0] != '@') { return false; } return true; } void validation_parser::add_bool_rule( std::vector& rules, std::string key, std::map>& annotations) { auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { validation_rule* rule = new validation_rule(key); validation_value* value; if (is_reference_field(annotation_value)) { t_field* field = get_referenced_field(annotation_value); value = new validation_value(field); } else { bool constant; std::istringstream(it->second.back()) >> std::boolalpha >> constant; value = new validation_value(constant); } rule->append_value(value); rules.push_back(rule); } } } void validation_parser::add_double_rule( std::vector& rules, std::string key, std::map>& annotations) { auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { if (annotation_value.size() == 0) { continue; } validation_rule* rule = new validation_rule(key); validation_value* value; if (is_validation_function(annotation_value)) { validation_value::validation_function* function = get_validation_function(annotation_value); value = new validation_value(function); } else if (is_reference_field(annotation_value)) { t_field* field = get_referenced_field(annotation_value); value = new validation_value(field); } else { double constant = std::stod(annotation_value); value = new validation_value(constant); } rule->append_value(value); rules.push_back(rule); } } } void validation_parser::add_enum_list_rule( std::vector& rules, t_enum* enum_, std::string key, std::map>& annotations) { auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { if (annotation_value.size() == 0) { continue; } validation_rule* rule = new validation_rule(key); if (annotation_value[0] == '[') { validation_value* value; char* str = strdup(annotation_value.c_str()); char* pch = strtok(str, list_delimiter); std::string val; while (pch != NULL) { std::string temp(pch); if (is_validation_function(temp)) { validation_value::validation_function* function = get_validation_function(temp); value = new validation_value(function); } else if (is_reference_field(temp)) { t_field* field = get_referenced_field(temp); value = new validation_value(field); } else if (std::stringstream(temp) >> val) { std::string::size_type dot = val.rfind('.'); if (dot != std::string::npos) { val = val.substr(dot + 1); } t_enum_value* enum_val = enum_->get_constant_by_name(val); value = new validation_value(enum_val); } else { delete rule; throw "validator error: validation double list parse failed: " + temp; } rule->append_value(value); pch = strtok(NULL, list_delimiter); } } else { validation_value* value; std::string val = annotation_value; std::string::size_type dot = val.rfind('.'); if (dot != std::string::npos) { val = val.substr(dot + 1); } t_enum_value* enum_val = enum_->get_constant_by_name(val); value = new validation_value(enum_val); rule->append_value(value); } rules.push_back(rule); } } } void validation_parser::add_double_list_rule( std::vector& rules, std::string key, std::map>& annotations) { std::map> double_rules; auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { if (annotation_value.size() == 0) { continue; } if (annotation_value[0] == '[') { validation_rule* rule = new validation_rule(key); validation_value* value; char* str = strdup(annotation_value.c_str()); char* pch = strtok(str, list_delimiter); double val; while (pch != NULL) { std::string temp(pch); if (is_validation_function(temp)) { validation_value::validation_function* function = get_validation_function(temp); value = new validation_value(function); } else if (is_reference_field(temp)) { t_field* field = get_referenced_field(temp); value = new validation_value(field); } else if (std::stringstream(temp) >> val) { value = new validation_value(val); } else { delete rule; throw "validator error: validation double list parse failed: " + temp; } rule->append_value(value); pch = strtok(NULL, list_delimiter); } rules.push_back(rule); } else { double_rules[key].push_back(annotation_value); } } } if (double_rules[key].size() > 0) { add_double_rule(rules, key, double_rules); } } void validation_parser::add_integer_rule( std::vector& rules, std::string key, std::map>& annotations) { auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { if (annotation_value.size() == 0) { continue; } validation_rule* rule = new validation_rule(key); validation_value* value; if (is_reference_field(annotation_value)) { t_field* field = get_referenced_field(annotation_value); value = new validation_value(field); } else if (is_validation_function(annotation_value)) { validation_value::validation_function* function = get_validation_function(annotation_value); value = new validation_value(function); } else { int64_t constant = std::stoll(annotation_value); value = new validation_value(constant); } rule->append_value(value); rules.push_back(rule); } } } void validation_parser::add_integer_list_rule( std::vector& rules, std::string key, std::map>& annotations) { std::map> integer_rules; auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { if (annotation_value.size() == 0) { continue; } if (annotation_value[0] == '[') { validation_rule* rule = new validation_rule(key); validation_value* value; char* str = strdup(annotation_value.c_str()); char* pch = strtok(str, list_delimiter); int64_t val; while (pch != NULL) { std::string temp(pch); if (is_validation_function(temp)) { validation_value::validation_function* function = get_validation_function(temp); value = new validation_value(function); } else if (is_reference_field(temp)) { t_field* field = get_referenced_field(temp); value = new validation_value(field); } else if (std::stringstream(temp) >> val) { value = new validation_value(val); } else { delete rule; throw "validator error: validation integer list parse failed: " + temp; } rule->append_value(value); pch = strtok(NULL, list_delimiter); } rules.push_back(rule); } else { integer_rules[key].push_back(annotation_value); } } } if (integer_rules[key].size() > 0) { add_integer_rule(rules, key, integer_rules); } } void validation_parser::add_string_rule( std::vector& rules, std::string key, std::map>& annotations) { auto it = annotations.find(key); if (it != annotations.end() && !it->second.empty()) { for (auto& annotation_value : it->second) { validation_rule* rule = new validation_rule(key); validation_value* value; if (is_reference_field(annotation_value)) { t_field* field = get_referenced_field(annotation_value); value = new validation_value(field); } else { value = new validation_value(annotation_value); } rule->append_value(value); rules.push_back(rule); } } } t_field* validation_parser::get_referenced_field(std::string annotation_value) { annotation_value.erase(annotation_value.begin()); return reference->get_field_by_name(annotation_value); } validation_value::validation_function* validation_parser::get_validation_function( std::string annotation_value) { std::string value = annotation_value; value.erase(value.begin()); validation_value::validation_function* function = new validation_value::validation_function; size_t name_end = value.find_first_of('('); if (name_end >= value.size()) { delete function; throw "validator error: validation function parse failed: " + annotation_value; } function->name = value.substr(0, name_end); value.erase(0, name_end + 1); // name( if (function->name == "len") { size_t argument_end = value.find_first_of(')'); if (argument_end >= value.size()) { delete function; throw "validator error: validation function parse failed: " + annotation_value; } std::string argument = value.substr(0, argument_end); if (argument.size() > 0 && argument[0] == '$') { t_field* field = get_referenced_field(argument); validation_value* value = new validation_value(field); function->arguments.push_back(value); } else { delete function; throw "validator error: validation function parse failed, unrecognized argument: " + annotation_value; } } else { delete function; throw "validator error: validation function parse failed, function not supported: " + annotation_value; } return function; } thrift-0.19.0/compiler/cpp/src/thrift/generate/t_generator.cc0000644000000000000000000002112014370300523024165 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "thrift/generate/t_generator.h" using namespace std; /** * Top level program generation function. Calls the generator subclass methods * for preparing file streams etc. then iterates over all the parts of the * program to perform the correct actions. * * @param program The thrift program to compile into C++ source */ void t_generator::generate_program() { // Initialize the generator init_generator(); // Generate enums vector enums = program_->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { generate_enum(*en_iter); } // Generate typedefs vector typedefs = program_->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { generate_typedef(*td_iter); } // Generate structs, exceptions, and unions in declared order vector objects = program_->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { generate_forward_declaration(*o_iter); } for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { if ((*o_iter)->is_xception()) { generate_xception(*o_iter); } else { generate_struct(*o_iter); } } // Generate constants vector consts = program_->get_consts(); generate_consts(consts); // Generate services vector services = program_->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { service_name_ = get_service_name(*sv_iter); generate_service(*sv_iter); } // Close the generator close_generator(); } std::set t_generator::lang_keywords_for_validation() const { // Nothing by default. It makes no sense to restrict the whole world to use non-PHP keywords only. // Override on a per-generator(!) basis if you cannot live without it, e.g. that particular language has no // mechanism or way to deal with it properly, so we absolutely need to fail on it as the last possible resort. return {}; } void t_generator::validate_input() const { validate(program_->get_enums()); validate(program_->get_typedefs()); validate(program_->get_objects()); validate(program_->get_consts()); validate(program_->get_services()); } template void t_generator::validate(const vector& list) const{ typename vector::const_iterator it; for(it=list.begin(); it != list.end(); ++it) { validate(*it); } } void t_generator::validate(t_function const* f) const { validate_id(f->get_name()); validate(f->get_arglist()); validate(f->get_xceptions()); } void t_generator::validate(t_service const* s) const { validate_id(s->get_name()); validate(s->get_functions()); } void t_generator::validate(t_enum const* en) const { validate_id(en->get_name()); validate(en->get_constants()); } void t_generator::validate(t_struct const* s) const { validate_id(s->get_name()); validate(s->get_members()); } void t_generator::validate(t_enum_value const* en_val) const { validate_id(en_val->get_name()); } void t_generator::validate(t_typedef const* td) const { validate_id(td->get_name()); } void t_generator::validate(t_const const* c) const { validate_id(c->get_name()); } void t_generator::validate(t_field const* f) const { validate_id(f->get_name()); } void t_generator::validate_id(const string& id) const { if (keywords_.find(id) != keywords_.end()) { // What the message really means is "we did not get it done yet" failure("Cannot use reserved language keyword \"%s\" with target language %s", id.c_str(), display_name().c_str()); } } string t_generator::escape_string(const string& in) const { string result = ""; for (string::const_iterator it = in.begin(); it < in.end(); it++) { std::map::const_iterator res = escape_.find(*it); if (res != escape_.end()) { result.append(res->second); } else { result.push_back(*it); } } return result; } void t_generator::generate_consts(vector consts) { vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { generate_const(*c_iter); } } void t_generator::generate_docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end) { if (!comment_start.empty()) indent(out) << comment_start; stringstream docs(contents, ios_base::in); while (!(docs.eof() || docs.fail())) { char line[1024]; docs.getline(line, 1024); if (strlen(line) > 0) { indent(out) << line_prefix << line << std::endl; } else if (line_prefix.empty()){ out << std::endl; } else if(!docs.eof()) { indent(out) << line_prefix << std::endl; } } if (!comment_end.empty()) indent(out) << comment_end; } void t_generator_registry::register_generator(t_generator_factory* factory) { gen_map_t& the_map = get_generator_map(); if (the_map.find(factory->get_short_name()) != the_map.end()) { failure("Duplicate generators for language \"%s\"!\n", factory->get_short_name().c_str()); } the_map[factory->get_short_name()] = factory; } void t_generator::parse_options(const string& options, string& language, map& parsed_options) { string::size_type colon = options.find(':'); language = options.substr(0, colon); if (colon != string::npos) { string::size_type pos = colon + 1; while (pos != string::npos && pos < options.size()) { string::size_type next_pos = options.find(',', pos); string option = options.substr(pos, next_pos - pos); pos = ((next_pos == string::npos) ? next_pos : next_pos + 1); string::size_type separator = option.find('='); string key, value; if (separator == string::npos) { key = option; value = ""; } else { key = option.substr(0, separator); value = option.substr(separator + 1); } parsed_options[key] = value; } } } t_generator* t_generator_registry::get_generator(t_program* program, const string& language, const map& parsed_options, const std::string& options) { gen_map_t& the_map = get_generator_map(); gen_map_t::iterator iter = the_map.find(language); if ((language == "csharp") || (language == "netcore")) { failure("The '%s' target is no longer available. Use 'netstd' instead.", language.c_str()); } if (iter == the_map.end()) { return nullptr; } return iter->second->get_generator(program, parsed_options, options); } t_generator* t_generator_registry::get_generator(t_program* program, const string& options) { string language; map parsed_options; t_generator::parse_options(options, language, parsed_options); return get_generator(program, language, parsed_options, options); } t_generator_registry::gen_map_t& t_generator_registry::get_generator_map() { // http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12 static gen_map_t* the_map = new gen_map_t(); return *the_map; } t_generator_factory::t_generator_factory(const std::string& short_name, const std::string& long_name, const std::string& documentation) : short_name_(short_name), long_name_(long_name), documentation_(documentation) { t_generator_registry::register_generator(this); } thrift-0.19.0/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc0000644000000000000000000017021314370300523025350 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_oop_generator.h" using std::ios; using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * OCaml code generator. * */ class t_ocaml_generator : public t_oop_generator { public: t_ocaml_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option ocaml:" + iter->first; } out_dir_base_ = "gen-ocaml"; } ~t_ocaml_generator() override; void init_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_program() override; void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); bool struct_member_persistent(t_field* tmember); bool struct_member_omitable(t_field* tmember); bool struct_member_default_cheaply_comparable(t_field* tmember); std::string struct_member_copy_of(t_type* type, string what); /** * Struct generation code */ void generate_ocaml_struct(t_struct* tstruct, bool is_exception); void generate_ocaml_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false); void generate_ocaml_struct_member(std::ostream& out, string tname, t_field* tmember); void generate_ocaml_struct_sig(std::ostream& out, t_struct* tstruct, bool is_exception); void generate_ocaml_struct_reader(std::ostream& out, t_struct* tstruct); void generate_ocaml_struct_writer(std::ostream& out, t_struct* tstruct); void generate_ocaml_function_helpers(t_function* tfunction); void generate_ocaml_method_copy(std::ostream& out, const vector& members); void generate_ocaml_member_copy(std::ostream& out, t_field* member); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct); void generate_deserialize_container(std::ostream& out, t_type* ttype); void generate_deserialize_set_element(std::ostream& out, t_set* tset); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_deserialize_type(std::ostream& out, t_type* type); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string name = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); /** * Helper rendering functions */ /** Need to disable codegen comment for unit tests to be version-agnostic */ virtual std::string ocaml_autogen_comment(); std::string ocaml_imports(); std::string type_name(t_type* ttype); std::string exception_ctor(t_type* ttype); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string function_type(t_function* tfunc, bool method = false, bool options = false); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string render_ocaml_type(t_type* type); // Need access to output file streams for testing. protected: /** * File streams */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_consts_; ofstream_with_content_based_conditional_update f_service_; ofstream_with_content_based_conditional_update f_types_i_; ofstream_with_content_based_conditional_update f_service_i_; }; /* * This is necessary because we want typedefs to appear later, * after all the types have been declared. */ void t_ocaml_generator::generate_program() { // Initialize the generator init_generator(); // Generate enums vector enums = program_->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { generate_enum(*en_iter); } // Generate structs vector structs = program_->get_structs(); vector::iterator st_iter; for (st_iter = structs.begin(); st_iter != structs.end(); ++st_iter) { generate_struct(*st_iter); } // Generate xceptions vector xceptions = program_->get_xceptions(); vector::iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { generate_xception(*x_iter); } // Generate typedefs vector typedefs = program_->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { generate_typedef(*td_iter); } // Generate services vector services = program_->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { service_name_ = get_service_name(*sv_iter); generate_service(*sv_iter); } // Generate constants vector consts = program_->get_consts(); generate_consts(consts); } /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_ocaml_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); // Make output file string f_types_name = get_out_dir() + program_name_ + "_types.ml"; f_types_.open(f_types_name.c_str()); string f_types_i_name = get_out_dir() + program_name_ + "_types.mli"; f_types_i_.open(f_types_i_name.c_str()); string f_consts_name = get_out_dir() + program_name_ + "_consts.ml"; f_consts_.open(f_consts_name.c_str()); // Print header f_types_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl; f_types_i_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl; f_consts_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl << "open " << capitalize(program_name_) << "_types" << endl; } /** * Autogen'd comment */ string t_ocaml_generator::ocaml_autogen_comment() { return std::string("(*\n") + " Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "\n" + " DO NOT EDIT UNLESS YOU ARE SURE YOU KNOW WHAT YOU ARE DOING\n" + "*)\n"; } /** * Prints standard thrift imports */ string t_ocaml_generator::ocaml_imports() { return "open Thrift"; } t_ocaml_generator::~t_ocaml_generator() { f_consts_.close(); f_types_.close(); f_types_i_.close(); f_service_.close(); f_service_i_.close(); } /** * Generates a typedef. Ez. * * @param ttypedef The type definition */ void t_ocaml_generator::generate_typedef(t_typedef* ttypedef) { f_types_ << indent() << "type " << decapitalize(ttypedef->get_symbolic()) << " = " << render_ocaml_type(ttypedef->get_type()) << endl << endl; f_types_i_ << indent() << "type " << decapitalize(ttypedef->get_symbolic()) << " = " << render_ocaml_type(ttypedef->get_type()) << endl << endl; } /** * Generates code for an enumerated type. * the values. * * @param tenum The enumeration */ void t_ocaml_generator::generate_enum(t_enum* tenum) { indent(f_types_) << "module " << capitalize(tenum->get_name()) << " = " << endl << "struct" << endl; indent(f_types_i_) << "module " << capitalize(tenum->get_name()) << " : " << endl << "sig" << endl; indent_up(); indent(f_types_) << "type t = " << endl; indent(f_types_i_) << "type t = " << endl; indent_up(); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { string name = capitalize((*c_iter)->get_name()); indent(f_types_) << "| " << name << endl; indent(f_types_i_) << "| " << name << endl; } indent_down(); indent(f_types_) << "let to_i = function" << endl; indent(f_types_i_) << "val to_i : t -> Int32.t" << endl; indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); string name = capitalize((*c_iter)->get_name()); indent(f_types_) << "| " << name << " -> " << value << "l" << endl; } indent_down(); indent(f_types_) << "let of_i = function" << endl; indent(f_types_i_) << "val of_i : Int32.t -> t" << endl; indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); string name = capitalize((*c_iter)->get_name()); indent(f_types_) << "| " << value << "l -> " << name << endl; } indent(f_types_) << "| _ -> raise Thrift_error" << endl; indent_down(); indent_down(); indent(f_types_) << "end" << endl; indent(f_types_i_) << "end" << endl; } /** * Generate a constant value */ void t_ocaml_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = decapitalize(tconst->get_name()); t_const_value* value = tconst->get_value(); indent(f_consts_) << "let " << name << " = " << render_const_value(type, value) << endl << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_ocaml_generator::render_const_value(t_type* type, t_const_value* value) { type = get_true_type(type); std::ostringstream out; // OCaml requires all floating point numbers contain a decimal point out.setf(ios::showpoint); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: out << value->get_integer(); break; case t_base_type::TYPE_I32: out << value->get_integer() << "l"; break; case t_base_type::TYPE_I64: out << value->get_integer() << "L"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer() << ".0"; } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { t_enum* tenum = (t_enum*)type; vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int val = (*c_iter)->get_value(); if (val == value->get_integer()) { indent(out) << capitalize(tenum->get_name()) << "." << capitalize((*c_iter)->get_name()); break; } } } else if (type->is_struct() || type->is_xception()) { string cname = type_name(type); string ct = tmp("_c"); out << endl; indent_up(); indent(out) << "(let " << ct << " = new " << cname << " in" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string fname = v_iter->first->get_string(); out << indent(); out << ct << "#set_" << fname << " "; out << render_const_value(field_type, v_iter->second); out << ";" << endl; } indent(out) << ct << ")"; indent_down(); indent_down(); } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; string hm = tmp("_hm"); out << endl; indent_up(); indent(out) << "(let " << hm << " = Hashtbl.create " << val.size() << " in" << endl; indent_up(); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(ktype, v_iter->first); string val = render_const_value(vtype, v_iter->second); indent(out) << "Hashtbl.add " << hm << " " << key << " " << val << ";" << endl; } indent(out) << hm << ")"; indent_down(); indent_down(); } else if (type->is_list()) { t_type* etype; etype = ((t_list*)type)->get_elem_type(); out << "[" << endl; indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent(); out << render_const_value(etype, *v_iter); out << ";" << endl; } indent_down(); indent(out) << "]"; } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; string hm = tmp("_hm"); indent(out) << "(let " << hm << " = Hashtbl.create " << val.size() << " in" << endl; indent_up(); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(etype, *v_iter); indent(out) << "Hashtbl.add " << hm << " " << val << " true;" << endl; } indent(out) << hm << ")" << endl; indent_down(); out << endl; } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out.str(); } /** * Generates a "struct" */ void t_ocaml_generator::generate_struct(t_struct* tstruct) { generate_ocaml_struct(tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct, but also has an exception declaration. * * @param txception The struct definition */ void t_ocaml_generator::generate_xception(t_struct* txception) { generate_ocaml_struct(txception, true); } /** * Generates an OCaml struct */ void t_ocaml_generator::generate_ocaml_struct(t_struct* tstruct, bool is_exception) { generate_ocaml_struct_definition(f_types_, tstruct, is_exception); generate_ocaml_struct_sig(f_types_i_, tstruct, is_exception); } void t_ocaml_generator::generate_ocaml_method_copy(ostream& out, const vector& members) { vector::const_iterator m_iter; /* Create a copy of the current object */ indent(out) << "method copy =" << endl; indent_up(); indent_up(); indent(out) << "let _new = Oo.copy self in" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) generate_ocaml_member_copy(out, *m_iter); indent_down(); indent(out) << "_new" << endl; indent_down(); } string t_ocaml_generator::struct_member_copy_of(t_type* type, string what) { if (type->is_struct() || type->is_xception()) { return what + string("#copy"); } if (type->is_map()) { string copy_of_k = struct_member_copy_of(((t_map*)type)->get_key_type(), "k"); string copy_of_v = struct_member_copy_of(((t_map*)type)->get_val_type(), "v"); if (copy_of_k == "k" && copy_of_v == "v") { return string("(Hashtbl.copy ") + what + string(")"); } else { return string( "((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v " "-> Hashtbl.add nh ") + copy_of_k + string(" ") + copy_of_v + string(") oh; nh) ") + what + ")"; } } if (type->is_set()) { string copy_of = struct_member_copy_of(((t_set*)type)->get_elem_type(), "k"); if (copy_of == "k") { return string("(Hashtbl.copy ") + what + string(")"); } else { return string( "((fun oh -> let nh = Hashtbl.create (Hashtbl.length oh) in Hashtbl.iter (fun k v " "-> Hashtbl.add nh ") + copy_of + string(" true") + string(") oh; nh) ") + what + ")"; } } if (type->is_list()) { string copy_of = struct_member_copy_of(((t_list*)type)->get_elem_type(), "x"); if (copy_of != "x") { return string("(List.map (fun x -> ") + copy_of + string(") ") + what + string(")"); } else { return what; } } return what; } void t_ocaml_generator::generate_ocaml_member_copy(ostream& out, t_field* tmember) { string mname = decapitalize(tmember->get_name()); t_type* type = get_true_type(tmember->get_type()); string grab_field = string("self#grab_") + mname; string copy_of = struct_member_copy_of(type, grab_field); if (copy_of != grab_field) { indent(out); if (!struct_member_persistent(tmember)) { out << "if _" << mname << " <> None then" << endl; indent(out) << " "; } out << "_new#set_" << mname << " " << copy_of << ";" << endl; } } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_ocaml_generator::generate_ocaml_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; string tname = type_name(tstruct); indent(out) << "class " << tname << " =" << endl; indent(out) << "object (self)" << endl; indent_up(); if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_ocaml_struct_member(out, tname, (*m_iter)); out << endl; } } generate_ocaml_method_copy(out, members); generate_ocaml_struct_writer(out, tstruct); indent_down(); indent(out) << "end" << endl; if (is_exception) { indent(out) << "exception " << capitalize(tname) << " of " << tname << endl; } generate_ocaml_struct_reader(out, tstruct); } /** * Generates a structure member for a thrift data type. * * @param tname Name of the parent structure for the member * @param tmember Member definition */ void t_ocaml_generator::generate_ocaml_struct_member(ostream& out, string tname, t_field* tmember) { string x = tmp("_x"); string mname = decapitalize(tmember->get_name()); indent(out) << "val mutable _" << mname << " : " << render_ocaml_type(tmember->get_type()); t_const_value* val = tmember->get_value(); if (val) { if (struct_member_persistent(tmember)) out << " = " << render_const_value(tmember->get_type(), tmember->get_value()) << endl; else out << " option = Some " << render_const_value(tmember->get_type(), tmember->get_value()) << endl; } else { // assert(!struct_member_persistent(tmember)) out << " option = None" << endl; } if (struct_member_persistent(tmember)) { indent(out) << "method get_" << mname << " = Some _" << mname << endl; indent(out) << "method grab_" << mname << " = _" << mname << endl; indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- " << x << endl; } else { indent(out) << "method get_" << mname << " = _" << mname << endl; indent(out) << "method grab_" << mname << " = match _" << mname << " with None->raise (Field_empty \"" << tname << "." << mname << "\") | Some " << x << " -> " << x << endl; indent(out) << "method set_" << mname << " " << x << " = _" << mname << " <- Some " << x << endl; indent(out) << "method unset_" << mname << " = _" << mname << " <- None" << endl; } indent(out) << "method reset_" << mname << " = _" << mname << " <- "; if (val) { if (struct_member_persistent(tmember)) out << render_const_value(tmember->get_type(), tmember->get_value()) << endl; else out << "Some " << render_const_value(tmember->get_type(), tmember->get_value()) << endl; } else { out << "None" << endl; } } /** * Check whether a member of the structure can not have undefined value * * @param tmember Member definition */ bool t_ocaml_generator::struct_member_persistent(t_field* tmember) { t_const_value* val = tmember->get_value(); return (val ? true : false); } /** * Check whether a member of the structure can be skipped during encoding * * @param tmember Member definition */ bool t_ocaml_generator::struct_member_omitable(t_field* tmember) { return (tmember->get_req() != t_field::T_REQUIRED); } /** * Figure out whether a member of the structure has * a cheaply comparable default value. * * @param tmember Member definition */ bool t_ocaml_generator::struct_member_default_cheaply_comparable(t_field* tmember) { t_type* type = get_true_type(tmember->get_type()); t_const_value* val = tmember->get_value(); if (!val) { return false; } else if (type->is_base_type()) { // Base types are generally cheaply compared for structural equivalence. switch (((t_base_type*)type)->get_base()) { case t_base_type::TYPE_DOUBLE: if (val->get_double() == 0.0) return true; else return false; default: return true; } } else if (type->is_list()) { // Empty lists are cheaply compared for structural equivalence. // Is empty list? if (val->get_list().size() == 0) return true; else return false; } else { return false; } } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_ocaml_generator::generate_ocaml_struct_sig(ostream& out, t_struct* tstruct, bool is_exception) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; string tname = type_name(tstruct); indent(out) << "class " << tname << " :" << endl; indent(out) << "object ('a)" << endl; indent_up(); string x = tmp("_x"); if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string mname = decapitalize((*m_iter)->get_name()); string type = render_ocaml_type((*m_iter)->get_type()); indent(out) << "method get_" << mname << " : " << type << " option" << endl; indent(out) << "method grab_" << mname << " : " << type << endl; indent(out) << "method set_" << mname << " : " << type << " -> unit" << endl; if (!struct_member_persistent(*m_iter)) indent(out) << "method unset_" << mname << " : unit" << endl; indent(out) << "method reset_" << mname << " : unit" << endl; } } indent(out) << "method copy : 'a" << endl; indent(out) << "method write : Protocol.t -> unit" << endl; indent_down(); indent(out) << "end" << endl; if (is_exception) { indent(out) << "exception " << capitalize(tname) << " of " << tname << endl; } indent(out) << "val read_" << tname << " : Protocol.t -> " << tname << endl; } /** * Generates the read method for a struct */ void t_ocaml_generator::generate_ocaml_struct_reader(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; string sname = type_name(tstruct); string str = tmp("_str"); string t = tmp("_t"); string id = tmp("_id"); indent(out) << "let rec read_" << sname << " (iprot : Protocol.t) =" << endl; indent_up(); indent(out) << "let " << str << " = new " << sname << " in" << endl; indent_up(); indent(out) << "ignore(iprot#readStructBegin);" << endl; // Loop over reading in fields indent(out) << "(try while true do" << endl; indent_up(); indent_up(); // Read beginning field marker indent(out) << "let (_," << t << "," << id << ") = iprot#readFieldBegin in" << endl; // Check for field STOP marker and break indent(out) << "if " << t << " = Protocol.T_STOP then" << endl; indent_up(); indent(out) << "raise Break" << endl; indent_down(); indent(out) << "else ();" << endl; indent(out) << "(match " << id << " with " << endl; indent_up(); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "| " << (*f_iter)->get_key() << " -> ("; out << "if " << t << " = " << type_to_enum((*f_iter)->get_type()) << " then" << endl; indent_up(); indent_up(); generate_deserialize_field(out, *f_iter, str); indent_down(); out << indent() << "else" << endl << indent() << " iprot#skip " << t << ")" << endl; indent_down(); } // In the default case we skip the field out << indent() << "| _ -> " << "iprot#skip " << t << ");" << endl; indent_down(); // Read field end marker indent(out) << "iprot#readFieldEnd;" << endl; indent_down(); indent(out) << "done; ()" << endl; indent_down(); indent(out) << "with Break -> ());" << endl; indent(out) << "iprot#readStructEnd;" << endl; indent(out) << str << endl << endl; indent_down(); indent_down(); } void t_ocaml_generator::generate_ocaml_struct_writer(ostream& out, t_struct* tstruct) { string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; string str = tmp("_str"); string f = tmp("_f"); indent(out) << "method write (oprot : Protocol.t) =" << endl; indent_up(); indent(out) << "oprot#writeStructBegin \"" << name << "\";" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* tmember = (*f_iter); string mname = "_" + decapitalize(tmember->get_name()); string _v; if (struct_member_persistent(tmember)) { if (struct_member_omitable(tmember) && struct_member_default_cheaply_comparable(tmember)) { _v = "_v"; // Avoid redundant encoding of members having default values. indent(out) << "(match " << mname << " with " << render_const_value(tmember->get_type(), tmember->get_value()) << " -> () | " << _v << " -> " << endl; } else { _v = mname; indent(out) << "(" << endl; } } else { indent(out) << "(match " << mname << " with "; if (struct_member_omitable(tmember)) { out << "None -> ()"; if (struct_member_default_cheaply_comparable(tmember)) { // Avoid redundant encoding of members having default values. out << " | Some " << render_const_value(tmember->get_type(), tmember->get_value()) << " -> ()"; } out << " | Some _v -> " << endl; } else { out << endl; indent(out) << "| None -> raise (Field_empty \"" << type_name(tstruct) << "." << mname << "\")" << endl; indent(out) << "| Some _v -> " << endl; } _v = "_v"; } indent_up(); // Write field header indent(out) << "oprot#writeFieldBegin(\"" << tmember->get_name() << "\"," << type_to_enum(tmember->get_type()) << "," << tmember->get_key() << ");" << endl; // Write field contents generate_serialize_field(out, tmember, _v); // Write field closer indent(out) << "oprot#writeFieldEnd" << endl; indent_down(); indent(out) << ");" << endl; } // Write the struct map out << indent() << "oprot#writeFieldStop;" << endl << indent() << "oprot#writeStructEnd" << endl; indent_down(); } /** * Generates a thrift service. * * @param tservice The service definition */ void t_ocaml_generator::generate_service(t_service* tservice) { string f_service_name = get_out_dir() + capitalize(service_name_) + ".ml"; f_service_.open(f_service_name.c_str()); string f_service_i_name = get_out_dir() + capitalize(service_name_) + ".mli"; f_service_i_.open(f_service_i_name.c_str()); f_service_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl; f_service_i_ << ocaml_autogen_comment() << endl << ocaml_imports() << endl; /* if (tservice->get_extends() != nullptr) { f_service_ << "open " << capitalize(tservice->get_extends()->get_name()) << endl; f_service_i_ << "open " << capitalize(tservice->get_extends()->get_name()) << endl; } */ f_service_ << "open " << capitalize(program_name_) << "_types" << endl << endl; f_service_i_ << "open " << capitalize(program_name_) << "_types" << endl << endl; // Generate the three main parts of the service generate_service_helpers(tservice); generate_service_interface(tservice); generate_service_client(tservice); generate_service_server(tservice); } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_ocaml_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; indent(f_service_) << "(* HELPER FUNCTIONS AND STRUCTURES *)" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_ocaml_struct_definition(f_service_, ts, false); generate_ocaml_function_helpers(*f_iter); } } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_ocaml_generator::generate_ocaml_function_helpers(t_function* tfunction) { t_struct result(program_, decapitalize(tfunction->get_name()) + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_ocaml_struct_definition(f_service_, &result, false); } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_ocaml_generator::generate_service_interface(t_service* tservice) { f_service_ << indent() << "class virtual iface =" << endl << "object (self)" << endl; f_service_i_ << indent() << "class virtual iface :" << endl << "object" << endl; indent_up(); if (tservice->get_extends() != nullptr) { string extends = type_name(tservice->get_extends()); indent(f_service_) << "inherit " << extends << ".iface" << endl; indent(f_service_i_) << "inherit " << extends << ".iface" << endl; } vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string ft = function_type(*f_iter, true, true); f_service_ << indent() << "method virtual " << decapitalize((*f_iter)->get_name()) << " : " << ft << endl; f_service_i_ << indent() << "method virtual " << decapitalize((*f_iter)->get_name()) << " : " << ft << endl; } indent_down(); indent(f_service_) << "end" << endl << endl; indent(f_service_i_) << "end" << endl << endl; } /** * Generates a service client definition. Note that in OCaml, the client doesn't implement iface. *This is because * The client does not (and should not have to) deal with arguments being None. * * @param tservice The service to generate a server for. */ void t_ocaml_generator::generate_service_client(t_service* tservice) { string extends = ""; indent(f_service_) << "class client (iprot : Protocol.t) (oprot : Protocol.t) =" << endl << "object (self)" << endl; indent(f_service_i_) << "class client : Protocol.t -> Protocol.t -> " << endl << "object" << endl; indent_up(); if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); indent(f_service_) << "inherit " << extends << ".client iprot oprot as super" << endl; indent(f_service_i_) << "inherit " << extends << ".client" << endl; } indent(f_service_) << "val mutable seqid = 0" << endl; // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); // Open function indent(f_service_) << "method " << function_signature(*f_iter) << " = " << endl; indent(f_service_i_) << "method " << decapitalize((*f_iter)->get_name()) << " : " << function_type(*f_iter, true, false) << endl; indent_up(); indent(f_service_) << "self#send_" << funname; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << " " << decapitalize((*fld_iter)->get_name()); } f_service_ << ";" << endl; if (!(*f_iter)->is_oneway()) { f_service_ << indent(); f_service_ << "self#recv_" << funname << endl; } indent_down(); indent(f_service_) << "method private send_" << function_signature(*f_iter) << " = " << endl; indent_up(); std::string argsname = decapitalize((*f_iter)->get_name() + "_args"); // Serialize the request header f_service_ << indent() << "oprot#writeMessageBegin (\"" << (*f_iter)->get_name() << "\", " << ((*f_iter)->is_oneway() ? "Protocol.ONEWAY" : "Protocol.CALL") << ", seqid);" << endl; f_service_ << indent() << "let args = new " << argsname << " in" << endl; indent_up(); for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << indent() << "args#set_" << (*fld_iter)->get_name() << " " << (*fld_iter)->get_name() << ";" << endl; } // Write to the stream f_service_ << indent() << "args#write oprot;" << endl << indent() << "oprot#writeMessageEnd;" << endl << indent() << "oprot#getTransport#flush" << endl; indent_down(); indent_down(); if (!(*f_iter)->is_oneway()) { std::string resultname = decapitalize((*f_iter)->get_name() + "_result"); t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); // Open function f_service_ << indent() << "method private " << function_signature(&recv_function) << " =" << endl; indent_up(); // TODO(mcslee): Validate message reply here, seq ids etc. f_service_ << indent() << "let (fname, mtype, rseqid) = iprot#readMessageBegin in" << endl; indent_up(); f_service_ << indent() << "(if mtype = Protocol.EXCEPTION then" << endl << indent() << " let x = Application_Exn.read iprot in" << endl; indent_up(); f_service_ << indent() << " (iprot#readMessageEnd;" << indent() << " raise (Application_Exn.E x))" << endl; indent_down(); f_service_ << indent() << "else ());" << endl; string res = "_"; t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); if (!(*f_iter)->get_returntype()->is_void() || xceptions.size() > 0) { res = "result"; } f_service_ << indent() << "let " << res << " = read_" << resultname << " iprot in" << endl; indent_up(); f_service_ << indent() << "iprot#readMessageEnd;" << endl; // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << indent() << "match result#get_success with Some v -> v | None -> (" << endl; indent_up(); } vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "(match result#get_" << (*x_iter)->get_name() << " with None -> () | Some _v ->" << endl; indent(f_service_) << " raise (" << capitalize(exception_ctor((*x_iter)->get_type())) << " _v));" << endl; } // Careful, only return _result if not a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "()" << endl; } else { f_service_ << indent() << "raise (Application_Exn.E (Application_Exn.create Application_Exn.MISSING_RESULT \"" << (*f_iter)->get_name() << " failed: unknown result\")))" << endl; indent_down(); } // Close function indent_down(); indent_down(); indent_down(); } } indent_down(); indent(f_service_) << "end" << endl << endl; indent(f_service_i_) << "end" << endl << endl; } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_ocaml_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; // Generate the header portion indent(f_service_) << "class processor (handler : iface) =" << endl << indent() << "object (self)" << endl; indent(f_service_i_) << "class processor : iface ->" << endl << indent() << "object" << endl; indent_up(); f_service_ << indent() << "inherit Processor.t" << endl << endl; f_service_i_ << indent() << "inherit Processor.t" << endl << endl; string extends = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); indent(f_service_) << "inherit " + extends + ".processor (handler :> " + extends + ".iface)" << endl; indent(f_service_i_) << "inherit " + extends + ".processor" << endl; } if (extends.empty()) { indent(f_service_) << "val processMap = Hashtbl.create " << functions.size() << endl; } indent(f_service_i_) << "val processMap : (string, int * Protocol.t * Protocol.t -> unit) Hashtbl.t" << endl; // Generate the server implementation indent(f_service_) << "method process iprot oprot =" << endl; indent(f_service_i_) << "method process : Protocol.t -> Protocol.t -> bool" << endl; indent_up(); f_service_ << indent() << "let (name, typ, seqid) = iprot#readMessageBegin in" << endl; indent_up(); // TODO(mcslee): validate message // HOT: dictionary function lookup f_service_ << indent() << "if Hashtbl.mem processMap name then" << endl << indent() << " (Hashtbl.find processMap name) (seqid, iprot, oprot)" << endl << indent() << "else (" << endl << indent() << " iprot#skip(Protocol.T_STRUCT);" << endl << indent() << " iprot#readMessageEnd;" << endl << indent() << " let x = Application_Exn.create Application_Exn.UNKNOWN_METHOD (\"Unknown " "function \"^name) in" << endl << indent() << " oprot#writeMessageBegin(name, Protocol.EXCEPTION, seqid);" << endl << indent() << " x#write oprot;" << endl << indent() << " oprot#writeMessageEnd;" << endl << indent() << " oprot#getTransport#flush" << endl << indent() << ");" << endl; // Read end of args field, the T_STOP, and the struct close f_service_ << indent() << "true" << endl; indent_down(); indent_down(); // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } indent(f_service_) << "initializer" << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << indent() << "Hashtbl.add processMap \"" << (*f_iter)->get_name() << "\" self#process_" << (*f_iter)->get_name() << ";" << endl; } indent_down(); indent_down(); indent(f_service_) << "end" << endl << endl; indent(f_service_i_) << "end" << endl << endl; } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_ocaml_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; // Open function indent(f_service_) << "method private process_" << tfunction->get_name() << " (seqid, iprot, oprot) =" << endl; indent_up(); string argsname = decapitalize(tfunction->get_name()) + "_args"; string resultname = decapitalize(tfunction->get_name()) + "_result"; // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; string args = "args"; if (fields.size() == 0) { args = "_"; } f_service_ << indent() << "let " << args << " = read_" << argsname << " iprot in" << endl; indent_up(); f_service_ << indent() << "iprot#readMessageEnd;" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { f_service_ << indent() << "let result = new " << resultname << " in" << endl; indent_up(); } // Try block for a function with exceptions if (xceptions.size() > 0) { f_service_ << indent() << "(try" << endl; indent_up(); } f_service_ << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "result#set_success "; } f_service_ << "(handler#" << tfunction->get_name(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { f_service_ << " args#get_" << (*f_iter)->get_name(); } f_service_ << ");" << endl; if (xceptions.size() > 0) { indent_down(); indent(f_service_) << "with" << endl; indent_up(); for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "| " << capitalize(exception_ctor((*x_iter)->get_type())) << " " << (*x_iter)->get_name() << " -> " << endl; indent_up(); indent_up(); if (!tfunction->is_oneway()) { f_service_ << indent() << "result#set_" << (*x_iter)->get_name() << " " << (*x_iter)->get_name() << endl; } else { indent(f_service_) << "()"; } indent_down(); indent_down(); } indent_down(); f_service_ << indent() << ");" << endl; } // Shortcut out here for oneway functions if (tfunction->is_oneway()) { f_service_ << indent() << "()" << endl; indent_down(); indent_down(); return; } f_service_ << indent() << "oprot#writeMessageBegin (\"" << tfunction->get_name() << "\", Protocol.REPLY, seqid);" << endl << indent() << "result#write oprot;" << endl << indent() << "oprot#writeMessageEnd;" << endl << indent() << "oprot#getTransport#flush" << endl; // Close function indent_down(); indent_down(); indent_down(); } /** * Deserializes a field of any type. */ void t_ocaml_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = tfield->get_type(); string name = decapitalize(tfield->get_name()); indent(out) << prefix << "#set_" << name << " "; generate_deserialize_type(out, type); out << endl; } /** * Deserializes a field of any type. */ void t_ocaml_generator::generate_deserialize_type(ostream& out, t_type* type) { type = get_true_type(type); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE"; } if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type); } else if (type->is_container()) { generate_deserialize_container(out, type); } else if (type->is_base_type()) { out << "iprot#"; t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct"; break; case t_base_type::TYPE_STRING: out << "readString"; break; case t_base_type::TYPE_BOOL: out << "readBool"; break; case t_base_type::TYPE_I8: out << "readByte"; break; case t_base_type::TYPE_I16: out << "readI16"; break; case t_base_type::TYPE_I32: out << "readI32"; break; case t_base_type::TYPE_I64: out << "readI64"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble"; break; default: throw "compiler error: no ocaml name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { string ename = capitalize(type->get_name()); out << "(" << ename << ".of_i iprot#readI32)"; } else { printf("DO NOT KNOW HOW TO DESERIALIZE TYPE '%s'\n", type->get_name().c_str()); } } /** * Generates an unserializer for a struct, calling read() */ void t_ocaml_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct) { string prefix = ""; t_program* program = tstruct->get_program(); if (program != nullptr && program != program_) { prefix = capitalize(program->get_name()) + "_types."; } string name = decapitalize(tstruct->get_name()); out << "(" << prefix << "read_" << name << " iprot)"; } /** * Serialize a container by writing out the header followed by * data and then a footer. */ void t_ocaml_generator::generate_deserialize_container(ostream& out, t_type* ttype) { string size = tmp("_size"); string ktype = tmp("_ktype"); string vtype = tmp("_vtype"); string etype = tmp("_etype"); string con = tmp("_con"); t_field fsize(g_type_i32, size); t_field fktype(g_type_i8, ktype); t_field fvtype(g_type_i8, vtype); t_field fetype(g_type_i8, etype); out << endl; indent_up(); // Declare variables, read header if (ttype->is_map()) { indent(out) << "(let (" << ktype << "," << vtype << "," << size << ") = iprot#readMapBegin in" << endl; indent(out) << "let " << con << " = Hashtbl.create " << size << " in" << endl; indent_up(); indent(out) << "for i = 1 to " << size << " do" << endl; indent_up(); indent(out) << "let _k = "; generate_deserialize_type(out, ((t_map*)ttype)->get_key_type()); out << " in" << endl; indent(out) << "let _v = "; generate_deserialize_type(out, ((t_map*)ttype)->get_val_type()); out << " in" << endl; indent_up(); indent(out) << "Hashtbl.add " << con << " _k _v" << endl; indent_down(); indent_down(); indent(out) << "done; iprot#readMapEnd; " << con << ")"; indent_down(); } else if (ttype->is_set()) { indent(out) << "(let (" << etype << "," << size << ") = iprot#readSetBegin in" << endl; indent(out) << "let " << con << " = Hashtbl.create " << size << " in" << endl; indent_up(); indent(out) << "for i = 1 to " << size << " do" << endl; indent_up(); indent(out) << "Hashtbl.add " << con << " "; generate_deserialize_type(out, ((t_set*)ttype)->get_elem_type()); out << " true" << endl; indent_down(); indent(out) << "done; iprot#readSetEnd; " << con << ")"; indent_down(); } else if (ttype->is_list()) { indent(out) << "(let (" << etype << "," << size << ") = iprot#readListBegin in" << endl; indent_up(); indent(out) << "let " << con << " = (Array.to_list (Array.init " << size << " (fun _ -> "; generate_deserialize_type(out, ((t_list*)ttype)->get_elem_type()); out << "))) in" << endl; indent_up(); indent(out) << "iprot#readListEnd; " << con << ")"; indent_down(); indent_down(); } indent_down(); } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_ocaml_generator::generate_serialize_field(ostream& out, t_field* tfield, string name) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + tfield->get_name(); } if (name.length() == 0) { name = decapitalize(tfield->get_name()); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_serialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << "oprot#"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "writeString(" << name << ")"; break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ")"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ")"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ")"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ")"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ")"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ")"; break; default: throw "compiler error: no ocaml name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { string ename = capitalize(type->get_name()); out << "writeI32(" << ename << ".to_i " << name << ")"; } } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); } out << ";" << endl; } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_ocaml_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << prefix << "#write(oprot)"; } void t_ocaml_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { if (ttype->is_map()) { indent(out) << "oprot#writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ","; out << type_to_enum(((t_map*)ttype)->get_val_type()) << ","; out << "Hashtbl.length " << prefix << ");" << endl; } else if (ttype->is_set()) { indent(out) << "oprot#writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ","; out << "Hashtbl.length " << prefix << ");" << endl; } else if (ttype->is_list()) { indent(out) << "oprot#writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ","; out << "List.length " << prefix << ");" << endl; } if (ttype->is_map()) { string kiter = tmp("_kiter"); string viter = tmp("_viter"); indent(out) << "Hashtbl.iter (fun " << kiter << " -> fun " << viter << " -> " << endl; indent_up(); generate_serialize_map_element(out, (t_map*)ttype, kiter, viter); indent_down(); indent(out) << ") " << prefix << ";" << endl; } else if (ttype->is_set()) { string iter = tmp("_iter"); indent(out) << "Hashtbl.iter (fun " << iter << " -> fun _ -> "; indent_up(); generate_serialize_set_element(out, (t_set*)ttype, iter); indent_down(); indent(out) << ") " << prefix << ";" << endl; } else if (ttype->is_list()) { string iter = tmp("_iter"); indent(out) << "List.iter (fun " << iter << " -> "; indent_up(); generate_serialize_list_element(out, (t_list*)ttype, iter); indent_down(); indent(out) << ") " << prefix << ";" << endl; } if (ttype->is_map()) { indent(out) << "oprot#writeMapEnd"; } else if (ttype->is_set()) { indent(out) << "oprot#writeSetEnd"; } else if (ttype->is_list()) { indent(out) << "oprot#writeListEnd"; } } /** * Serializes the members of a map. * */ void t_ocaml_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), kiter); generate_serialize_field(out, &kfield); t_field vfield(tmap->get_val_type(), viter); generate_serialize_field(out, &vfield); } /** * Serializes the members of a set. */ void t_ocaml_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield); } /** * Serializes the members of a list. */ void t_ocaml_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield); } /** * Renders a function signature of the form 'name args' * * @param tfunction Function definition * @return String of rendered function definition */ string t_ocaml_generator::function_signature(t_function* tfunction, string prefix) { return prefix + decapitalize(tfunction->get_name()) + " " + argument_list(tfunction->get_arglist()); } string t_ocaml_generator::function_type(t_function* tfunc, bool method, bool options) { string result = ""; const vector& fields = tfunc->get_arglist()->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result += render_ocaml_type((*f_iter)->get_type()); if (options) result += " option"; result += " -> "; } if (fields.empty() && !method) { result += "unit -> "; } result += render_ocaml_type(tfunc->get_returntype()); return result; } /** * Renders a field list */ string t_ocaml_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += " "; } result += (*f_iter)->get_name(); } return result; } string t_ocaml_generator::type_name(t_type* ttype) { string prefix = ""; t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { if (!ttype->is_service()) { prefix = capitalize(program->get_name()) + "_types."; } } string name = ttype->get_name(); if (ttype->is_service()) { name = capitalize(name); } else { name = decapitalize(name); } return prefix + name; } string t_ocaml_generator::exception_ctor(t_type* ttype) { string prefix = ""; t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { if (!ttype->is_service()) { prefix = capitalize(program->get_name()) + "_types."; } } return prefix + capitalize(ttype->get_name()); } /** * Converts the parse type to a Protocol.t_type enum */ string t_ocaml_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "Protocol.T_VOID"; case t_base_type::TYPE_STRING: return "Protocol.T_STRING"; case t_base_type::TYPE_BOOL: return "Protocol.T_BOOL"; case t_base_type::TYPE_I8: return "Protocol.T_BYTE"; case t_base_type::TYPE_I16: return "Protocol.T_I16"; case t_base_type::TYPE_I32: return "Protocol.T_I32"; case t_base_type::TYPE_I64: return "Protocol.T_I64"; case t_base_type::TYPE_DOUBLE: return "Protocol.T_DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "Protocol.T_I32"; } else if (type->is_struct() || type->is_xception()) { return "Protocol.T_STRUCT"; } else if (type->is_map()) { return "Protocol.T_MAP"; } else if (type->is_set()) { return "Protocol.T_SET"; } else if (type->is_list()) { return "Protocol.T_LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Converts the parse type to an ocaml type */ string t_ocaml_generator::render_ocaml_type(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "unit"; case t_base_type::TYPE_STRING: return "string"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "int"; case t_base_type::TYPE_I16: return "int"; case t_base_type::TYPE_I32: return "Int32.t"; case t_base_type::TYPE_I64: return "Int64.t"; case t_base_type::TYPE_DOUBLE: return "float"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return capitalize(((t_enum*)type)->get_name()) + ".t"; } else if (type->is_struct() || type->is_xception()) { return type_name((t_struct*)type); } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); return "(" + render_ocaml_type(ktype) + "," + render_ocaml_type(vtype) + ") Hashtbl.t"; } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); return "(" + render_ocaml_type(etype) + ",bool) Hashtbl.t"; } else if (type->is_list()) { t_type* etype = ((t_list*)type)->get_elem_type(); return render_ocaml_type(etype) + " list"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_ocaml_generator::display_name() const { return "OCaml"; } THRIFT_REGISTER_GENERATOR(ocaml, "OCaml", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/go_validator_generator.cc0000644000000000000000000010152714370300523026406 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This file is programmatically sanitized for style: * astyle --style=1tbs -f -p -H -j -U go_validator_generator.cc * * The output of astyle should not be taken unquestioningly, but it is a good * guide for ensuring uniformity and readability. */ #include #include #include #include #include #include #include "thrift/generate/go_validator_generator.h" #include "thrift/generate/validator_parser.h" #include "thrift/platform.h" #include "thrift/version.h" #include #include #include #include #include #include std::string go_validator_generator::get_field_reference_name(t_field* field) { t_type* type(field->get_type()); std::string tgt; t_const_value* def_value; go_generator->get_publicized_name_and_def_value(field, &tgt, &def_value); tgt = "p." + tgt; if (go_generator->is_pointer_field(field) && (type->is_base_type() || type->is_enum() || type->is_container())) { tgt = "*" + tgt; } return tgt; } void go_validator_generator::generate_struct_validator(std::ostream& out, t_struct* tstruct) { std::vector members = tstruct->get_members(); validation_parser parser(tstruct); for (auto it = members.begin(); it != members.end(); it++) { t_field* field(*it); const std::vector& rules = parser.parse_field(field->get_type(), field->annotations_); if (rules.size() == 0) { continue; } bool opt = field->get_req() == t_field::T_OPTIONAL; t_type* type = field->get_type(); std::string tgt = get_field_reference_name(field); std::string field_symbol = tstruct->get_name() + "." + field->get_name(); generate_field_validator(out, generator_context{field_symbol, "", tgt, opt, type, rules}); } } void go_validator_generator::generate_field_validator(std::ostream& out, const generator_context& context) { t_type* type = context.type; if (type->is_typedef()) { type = type->get_true_type(); } if (type->is_enum()) { if (context.tgt[0] == '*') { out << indent() << "if " << context.tgt.substr(1) << " != nil {" << endl; indent_up(); } generate_enum_field_validator(out, context); if (context.tgt[0] == '*') { indent_down(); out << indent() << "}" << endl; } return; } else if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); if (context.tgt[0] == '*') { out << indent() << "if " << context.tgt.substr(1) << " != nil {" << endl; indent_up(); } switch (tbase) { case t_base_type::TYPE_UUID: case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: generate_integer_field_validator(out, context); break; case t_base_type::TYPE_DOUBLE: generate_double_field_validator(out, context); break; case t_base_type::TYPE_STRING: generate_string_field_validator(out, context); break; case t_base_type::TYPE_BOOL: generate_bool_field_validator(out, context); break; } if (context.tgt[0] == '*') { indent_down(); out << indent() << "}" << endl; } return; } else if (type->is_list()) { return generate_list_field_validator(out, context); } else if (type->is_set()) { return generate_set_field_validator(out, context); } else if (type->is_map()) { return generate_map_field_validator(out, context); } else if (type->is_struct() || type->is_xception()) { return generate_struct_field_validator(out, context); } throw "validator error: unsupported type: " + type->get_name(); } void go_validator_generator::generate_enum_field_validator(std::ostream& out, const generator_context& context) { for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); if (values.size() == 0) { continue; } std::string key = (*it)->get_name(); if (key == "vt.in") { if (values.size() > 1) { std::string exist = GenID("_exist"); out << indent() << "var " << exist << " bool" << endl; std::string src = GenID("_src"); out << indent() << src << " := []int64{"; for (auto it = values.begin(); it != values.end(); it++) { if (it != values.begin()) { out << ", "; } out << "int64("; if ((*it)->is_field_reference()) { out << get_field_reference_name((*it)->get_field_reference()); } else { out << (*it)->get_enum()->get_value(); } out << ")"; } out << "}" << endl; out << indent() << "for _, src := range " << src << " {" << endl; indent_up(); out << indent() << "if int64(" << context.tgt << ") == src {" << endl; indent_up(); out << indent() << exist << " = true" << endl; out << indent() << "break" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "if " << exist << " == false {" << endl; } else { out << indent() << "if int64(" << context.tgt << ") != int64("; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else { out << values[0]->get_enum()->get_value(); } out << ") {" << endl; } indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.in\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule vt.in check failed\")" << endl; indent_down(); out << indent() << "}" << endl; if (values.size() > 1) { indent_down(); out << indent() << "}" << endl; } } else if (key == "vt.not_in") { if (values.size() > 1) { std::string src = GenID("_src"); out << indent() << src << " := []int64{"; for (auto it = values.begin(); it != values.end(); it++) { if (it != values.begin()) { out << ", "; } out << "int64("; if ((*it)->is_field_reference()) { out << get_field_reference_name((*it)->get_field_reference()); } else { out << (*it)->get_enum()->get_value(); } out << ")"; } out << "}" << endl; out << indent() << "for _, src := range " << src << " {" << endl; indent_up(); out << indent() << "if int64(" << context.tgt << ") == src {" << endl; } else { out << indent() << "if int64(" << context.tgt << ") == "; out << "int64("; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else { out << values[0]->get_enum()->get_value(); } out << ") {" << endl; } indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.not_in\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule vt.not_in check failed\")" << endl; indent_down(); out << indent() << "}" << endl; if (values.size() > 1) { indent_down(); out << indent() << "}" << endl; } } else if (key == "vt.defined_only") { if (values[0]->get_bool()) { out << indent() << "if (" << context.tgt << ").String() == \"\" "; } else { continue; } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } } } void go_validator_generator::generate_bool_field_validator(std::ostream& out, const generator_context& context) { for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); if (values.size() == 0) { continue; } std::string key = (*it)->get_name(); if (key == "vt.const") { out << indent() << "if " << context.tgt << " != "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else { if (values[0]->get_bool()) { out << "true"; } else { out << "false"; } } } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } } void go_validator_generator::generate_double_field_validator(std::ostream& out, const generator_context& context) { for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); if (values.size() == 0) { continue; } std::map signs{{"vt.lt", ">="}, {"vt.le", ">"}, {"vt.gt", "<="}, {"vt.ge", "<"}}; std::string key = (*it)->get_name(); auto key_it = signs.find(key); if (key_it != signs.end()) { out << indent() << "if " << context.tgt << " " << key_it->second << " "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else { out << values[0]->get_double(); } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; continue; } else if (key == "vt.in") { if (values.size() > 1) { std::string exist = GenID("_exist"); out << indent() << "var " << exist << " bool" << endl; std::string src = GenID("_src"); out << indent() << src << " := []float64{"; for (auto it = values.begin(); it != values.end(); it++) { if (it != values.begin()) { out << ", "; } if ((*it)->is_field_reference()) { out << get_field_reference_name((*it)->get_field_reference()); } else { out << (*it)->get_double(); } } out << "}" << endl; out << indent() << "for _, src := range " << src << " {" << endl; indent_up(); out << indent() << "if " << context.tgt << " == src {" << endl; indent_up(); out << indent() << exist << " = true" << endl; out << indent() << "break" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "if " << exist << " == false {" << endl; } else { out << indent() << "if " << context.tgt << " != "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else { out << values[0]->get_double(); } out << "{" << endl; } indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.in\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule vt.in check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } else if (key == "vt.not_in") { if (values.size() > 1) { std::string src = GenID("_src"); out << indent() << src << " := []float64{"; for (auto it = values.begin(); it != values.end(); it++) { if (it != values.begin()) { out << ", "; } if ((*it)->is_field_reference()) { out << get_field_reference_name((*it)->get_field_reference()); } else { out << (*it)->get_double(); } } out << "}" << endl; out << indent() << "for _, src := range " << src << " {" << endl; indent_up(); out << indent() << "if " << context.tgt << " == src {" << endl; } else { out << indent() << "if " << context.tgt << " == "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else { out << values[0]->get_double(); } out << "{" << endl; } indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.not_in\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule vt.not_in check failed\")" << endl; indent_down(); out << indent() << "}" << endl; if (values.size() > 1) { indent_down(); out << indent() << "}" << endl; } } } } void go_validator_generator::generate_integer_field_validator(std::ostream& out, const generator_context& context) { auto generate_current_type = [](std::ostream& out, t_type* type) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_I8: out << "int8"; break; case t_base_type::TYPE_I16: out << "int16"; break; case t_base_type::TYPE_I32: out << "int32"; break; case t_base_type::TYPE_I64: out << "int64"; break; default: throw "validator error: unsupported integer type: " + type->get_name(); } }; for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); if (values.size() == 0) { continue; } std::map signs{{"vt.lt", ">="}, {"vt.le", ">"}, {"vt.gt", "<="}, {"vt.ge", "<"}}; std::string key = (*it)->get_name(); auto key_it = signs.find(key); if (key_it != signs.end()) { out << indent() << "if " << context.tgt << " " << key_it->second << " "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else if (values[0]->is_validation_function()) { generate_current_type(out, context.type); out << "("; validation_value::validation_function* func = values[0]->get_function(); if (func->name == "len") { out << "len("; if (func->arguments[0]->is_field_reference()) { out << get_field_reference_name(func->arguments[0]->get_field_reference()); } out << ")"; } out << ")"; } else { out << values[0]->get_int(); } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } else if (key == "vt.in") { if (values.size() > 1) { std::string exist = GenID("_exist"); out << indent() << "var " << exist << " bool" << endl; std::string src = GenID("_src"); out << indent() << src << " := []"; generate_current_type(out, context.type); out << "{"; for (auto it = values.begin(); it != values.end(); it++) { if (it != values.begin()) { out << ", "; } if ((*it)->is_field_reference()) { out << get_field_reference_name((*it)->get_field_reference()); } else if ((*it)->is_validation_function()) { generate_current_type(out, context.type); out << "("; validation_value::validation_function* func = (*it)->get_function(); if (func->name == "len") { out << "len("; if (func->arguments[0]->is_field_reference()) { out << get_field_reference_name(func->arguments[0]->get_field_reference()); } out << ")"; } out << ")"; } else { out << (*it)->get_int(); } } out << "}" << endl; out << indent() << "for _, src := range " << src << " {" << endl; indent_up(); out << indent() << "if " << context.tgt << " == src {" << endl; indent_up(); out << indent() << exist << " = true" << endl; out << indent() << "break" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "if " << exist << " == false {" << endl; } else { out << indent() << "if " << context.tgt << " != "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else if (values[0]->is_validation_function()) { generate_current_type(out, context.type); out << "("; validation_value::validation_function* func = values[0]->get_function(); if (func->name == "len") { out << "len("; if (func->arguments[0]->is_field_reference()) { out << get_field_reference_name(func->arguments[0]->get_field_reference()); } out << ")"; } out << ")"; } else { out << values[0]->get_int(); } out << "{" << endl; } indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.in\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule vt.in check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } else if (key == "vt.not_in") { if (values.size() > 1) { std::string src = GenID("_src"); out << indent() << src << " := []"; t_base_type::t_base tbase = ((t_base_type*)context.type)->get_base(); switch (tbase) { case t_base_type::TYPE_I8: out << "int8"; break; case t_base_type::TYPE_I16: out << "int16"; break; case t_base_type::TYPE_I32: out << "int32"; break; case t_base_type::TYPE_I64: out << "int64"; break; default: throw "validator error: unsupported integer type: " + context.type->get_name(); } out << "{"; for (auto it = values.begin(); it != values.end(); it++) { if (it != values.begin()) { out << ", "; } if ((*it)->is_field_reference()) { out << get_field_reference_name((*it)->get_field_reference()); } else if ((*it)->is_validation_function()) { generate_current_type(out, context.type); out << "("; validation_value::validation_function* func = (*it)->get_function(); if (func->name == "len") { out << "len("; if (func->arguments[0]->is_field_reference()) { out << get_field_reference_name(func->arguments[0]->get_field_reference()); } out << ")"; } out << ")"; } else { out << (*it)->get_int(); } } out << "}" << endl; out << indent() << "for _, src := range " << src << " {" << endl; indent_up(); out << indent() << "if " << context.tgt << " == src {" << endl; } else { out << indent() << "if " << context.tgt << " == "; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else if (values[0]->is_validation_function()) { generate_current_type(out, context.type); out << "("; validation_value::validation_function* func = values[0]->get_function(); if (func->name == "len") { out << "len("; if (func->arguments[0]->is_field_reference()) { out << get_field_reference_name(func->arguments[0]->get_field_reference()); } out << ")"; } out << ")"; } else { out << values[0]->get_int(); } out << "{" << endl; } indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"vt.not_in\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule vt.not_in check failed\")" << endl; indent_down(); out << indent() << "}" << endl; if (values.size() > 1) { indent_down(); out << indent() << "}" << endl; } } } } void go_validator_generator::generate_string_field_validator(std::ostream& out, const generator_context& context) { std::string target = context.tgt; t_type* type = context.type; if (type->is_typedef()) { type = type->get_true_type(); } if (type->is_binary()) { target = GenID("_tgt"); out << indent() << target << " := " << "string(" << context.tgt << ")" << endl; } for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); if (values.size() == 0) { continue; } std::string key = (*it)->get_name(); if (key == "vt.const") { out << indent() << "if " << target << " != "; if (values[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << "\"" << values[0]->get_string() << "\""; } } else if (key == "vt.min_size" || key == "vt.max_size") { out << indent() << "if len(" << target << ") "; if (key == "vt.min_size") { out << "<"; } else { out << ">"; } out << " int("; if (values[0]->is_field_reference()) { out << get_field_reference_name(values[0]->get_field_reference()); } else if (values[0]->is_validation_function()) { validation_value::validation_function* func = values[0]->get_function(); if (func->name == "len") { out << "len("; if (func->arguments[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } out << ")"; } } else { out << values[0]->get_int(); } out << ")"; } else if (key == "vt.pattern") { out << indent() << "if ok, _ := regexp.MatchString(" << target << ","; if (values[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << "\"" << values[0]->get_string() << "\""; } out << "); ok "; } else if (key == "vt.prefix") { out << indent() << "if !strings.HasPrefix(" << target << ","; if (values[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << "\"" << values[0]->get_string() << "\""; } out << ")"; } else if (key == "vt.suffix") { out << indent() << "if !strings.HasSuffix(" << target << ","; if (values[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << "\"" << values[0]->get_string() << "\""; } out << ")"; } else if (key == "vt.contains") { out << indent() << "if !strings.Contains(" << target << ","; if (values[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << "\"" << values[0]->get_string() << "\""; } out << ")"; } else if (key == "vt.not_contains") { out << indent() << "if strings.Contains(" << target << ","; if (values[0]->is_field_reference()) { out << "string("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << "\"" << values[0]->get_string() << "\""; } out << ")"; } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } } void go_validator_generator::generate_set_field_validator(std::ostream& out, const generator_context& context) { return generate_list_field_validator(out, context); } void go_validator_generator::generate_list_field_validator(std::ostream& out, const generator_context& context) { for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); std::string key = (*it)->get_name(); if (key == "vt.min_size" || key == "vt.max_size") { out << indent() << "if len(" << context.tgt << ")"; if (key == "vt.min_size") { out << " < "; } else { out << " > "; } if (values[0]->is_field_reference()) { out << "int("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << values[0]->get_int(); } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } else if (key == "vt.elem") { out << indent() << "for i := 0; i < len(" << context.tgt << ");i++ {" << endl; indent_up(); std::string src = GenID("_elem"); out << indent() << src << " := " << context.tgt << "[i]" << endl; t_type* elem_type; if (context.type->is_list()) { elem_type = ((t_list*)context.type)->get_elem_type(); } else { elem_type = ((t_set*)context.type)->get_elem_type(); } generator_context ctx{context.field_symbol + ".elem", "", src, false, elem_type, std::vector{(*it)->get_inner()}}; generate_field_validator(out, ctx); indent_down(); out << indent() << "}" << endl; } } } void go_validator_generator::generate_map_field_validator(std::ostream& out, const generator_context& context) { for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); std::string key = (*it)->get_name(); if (key == "vt.min_size" || key == "vt.max_size") { out << indent() << "if len(" << context.tgt << ")"; if (key == "vt.min_size") { out << " < "; } else { out << " > "; } if (values[0]->is_field_reference()) { out << "int("; out << get_field_reference_name(values[0]->get_field_reference()); out << ")"; } else { out << values[0]->get_int(); } out << "{" << endl; indent_up(); out << indent() << "return thrift.NewValidationException(thrift.VALIDATION_FAILED, \"" + key + "\", \"" << context.field_symbol << "\", \"" << context.field_symbol << " not valid, rule " << key << " check failed\")" << endl; indent_down(); out << indent() << "}" << endl; } else if (key == "vt.key") { std::string src = GenID("_key"); out << indent() << "for " << src << " := range " << context.tgt << " {" << endl; indent_up(); generator_context ctx{context.field_symbol + ".key", "", src, false, ((t_map*)context.type)->get_key_type(), std::vector{(*it)->get_inner()}}; generate_field_validator(out, ctx); indent_down(); out << indent() << "}" << endl; } else if (key == "vt.value") { std::string src = GenID("_value"); out << indent() << "for _, " << src << " := range " << context.tgt << " {" << endl; indent_up(); generator_context ctx{context.field_symbol + ".value", "", src, false, ((t_map*)context.type)->get_val_type(), std::vector{(*it)->get_inner()}}; generate_field_validator(out, ctx); indent_down(); out << indent() << "}" << endl; } } } void go_validator_generator::generate_struct_field_validator(std::ostream& out, const generator_context& context) { bool generate_valid = true; validation_rule* last_valid_rule = nullptr; for (auto it = context.rules.begin(); it != context.rules.end(); it++) { const std::vector& values = (*it)->get_values(); if (values.size() == 0) { continue; } std::string key = (*it)->get_name(); if (key == "vt.skip") { if (values[0]->is_field_reference() || !values[0]->get_bool()) { generate_valid = true; } else if (values[0]->get_bool()) { generate_valid = false; } last_valid_rule = *it; } } if (generate_valid) { if (last_valid_rule == nullptr) { out << indent() << "if err := " << context.tgt << ".Validate(); err != nil {" << endl; indent_up(); out << indent() << "return err" << endl; indent_down(); out << indent() << "}" << endl; } else { const std::vector& values = last_valid_rule->get_values(); if (!values[0]->get_bool()) { out << indent() << "if err := " << context.tgt << ".Validate(); err != nil {" << endl; indent_up(); out << indent() << "return err" << endl; indent_down(); out << indent() << "}" << endl; } else if (values[0]->is_field_reference()) { out << indent() << "if !"; out << get_field_reference_name(values[0]->get_field_reference()); out << "{" << endl; indent_up(); out << indent() << "if err := " << context.tgt << ".Validate(); err != nil {" << endl; indent_up(); out << indent() << "return err" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; } } } } thrift-0.19.0/compiler/cpp/src/thrift/generate/go_validator_generator.h0000644000000000000000000000541014370300523026242 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_GO_VALIDATOR_GENERATOR_H #define T_GO_VALIDATOR_GENERATOR_H #include "thrift/generate/t_generator.h" #include "thrift/generate/t_go_generator.h" #include "thrift/generate/validator_parser.h" #include #include #include #include #include class go_validator_generator { public: go_validator_generator(t_go_generator* gg) : go_generator(gg){}; void generate_struct_validator(std::ostream& out, t_struct* tstruct); struct generator_context { std::string field_symbol; std::string src; std::string tgt; bool opt; t_type* type; std::vector rules; }; private: void generate_field_validator(std::ostream& out, const generator_context& context); void generate_enum_field_validator(std::ostream& out, const generator_context& context); void generate_bool_field_validator(std::ostream& out, const generator_context& context); void generate_integer_field_validator(std::ostream& out, const generator_context& context); void generate_double_field_validator(std::ostream& out, const generator_context& context); void generate_string_field_validator(std::ostream& out, const generator_context& context); void generate_list_field_validator(std::ostream& out, const generator_context& context); void generate_set_field_validator(std::ostream& out, const generator_context& context); void generate_map_field_validator(std::ostream& out, const generator_context& context); void generate_struct_field_validator(std::ostream& out, const generator_context& context); void indent_up() { go_generator->indent_up(); } void indent_down() { go_generator->indent_down(); } std::string indent() { return go_generator->indent(); } //std::string get_field_name(t_field* field); -- no impl? std::string get_field_reference_name(t_field* field); std::string GenID(std::string id) { return id + std::to_string(tmp_[id]++); }; t_go_generator* go_generator; std::map tmp_; }; #endif thrift-0.19.0/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc0000644000000000000000000057666014370300523025514 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /* forward declarations */ string initial_caps_to_underscores(string name); string underscores_to_initial_caps(string name); string to_upper_case(string name); string to_lower_case(string name); /** * C code generator, using glib for C typing. */ class t_c_glib_generator : public t_oop_generator { public: /* constructor */ t_c_glib_generator(t_program* program, const map& parsed_options, const string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; /* set the output directory */ this->out_dir_base_ = "gen-c_glib"; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option c_glib:" + iter->first; } /* set the namespace */ this->nspace = program_->get_namespace("c_glib"); if (this->nspace.empty()) { this->nspace = ""; this->nspace_u = ""; this->nspace_uc = ""; this->nspace_lc = ""; } else { /* replace dots with underscores */ char* tmp = strdup(this->nspace.c_str()); for (unsigned int i = 0; i < strlen(tmp); i++) { if (tmp[i] == '.') { tmp[i] = '_'; } } this->nspace = string(tmp, strlen(tmp)); free(tmp); /* clean up the namespace for C. * An input of 'namespace foo' should result in: * - nspace = foo - for thrift objects and typedefs * - nspace_u = Foo - for internal GObject prefixes * - nspace_uc = FOO_ - for macro prefixes * - nspace_lc = foo_ - for filename and method prefixes * The underscores are there since uc and lc strings are used as file and * variable prefixes. */ this->nspace_u = initial_caps_to_underscores(this->nspace); this->nspace_uc = to_upper_case(this->nspace_u) + "_"; this->nspace_lc = to_lower_case(this->nspace_u) + "_"; } } /* initialization and destruction */ void init_generator() override; void close_generator() override; std::string display_name() const override; /* generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_consts(vector consts) override; void generate_struct(t_struct* tstruct) override; void generate_service(t_service* tservice) override; void generate_xception(t_struct* tstruct) override; private: /* file streams */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_types_impl_; ofstream_with_content_based_conditional_update f_header_; ofstream_with_content_based_conditional_update f_service_; /* namespace variables */ string nspace; string nspace_u; string nspace_uc; string nspace_lc; /* helper functions */ bool is_complex_type(t_type* ttype); bool is_numeric(t_type* ttype); string type_name(t_type* ttype, bool in_typedef = false, bool is_const = false); string property_type_name(t_type* ttype, bool in_typedef = false, bool is_const = false); string base_type_name(t_type* type); string type_to_enum(t_type* type); string constant_literal(t_type* type, t_const_value* value); string constant_value(string name, t_type* type, t_const_value* value); string constant_value_with_storage(string name, t_type* type, t_const_value* value); string function_signature(t_function* tfunction); string argument_list(t_struct* tstruct); string xception_list(t_struct* tstruct); string declare_field(t_field* tfield, bool init = false, bool pointer = false, bool constant = false, bool reference = false); void declare_local_variable(ostream& out, t_type* ttype, string& base_name, bool for_hash_table); void declore_local_variable_for_write(ostream& out, t_type* ttype, string& base_name); /* generation functions */ void generate_const_initializer(string name, t_type* type, t_const_value* value, bool top_level = false); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_handler(t_service* tservice); void generate_service_processor(t_service* tservice); void generate_service_server(t_service* tservice); void generate_object(t_struct* tstruct); void generate_struct_writer(ostream& out, t_struct* tstruct, string this_name, string this_get = "", bool is_function = true); void generate_struct_reader(ostream& out, t_struct* tstruct, string this_name, string this_get = "", bool is_function = true); void generate_serialize_field(ostream& out, t_field* tfield, string prefix, string suffix, int error_ret); void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret); void generate_serialize_container(ostream& out, t_type* ttype, string prefix, int error_ret); void generate_serialize_map_element(ostream& out, t_map* tmap, string key, string value, int error_ret); void generate_serialize_set_element(ostream& out, t_set* tset, string element, int error_ret); void generate_serialize_list_element(ostream& out, t_list* tlist, string list, string index, int error_ret); void generate_deserialize_field(ostream& out, t_field* tfield, string prefix, string suffix, int error_ret, bool allocate = true); void generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret, bool allocate = true); void generate_deserialize_container(ostream& out, t_type* ttype, string prefix, int error_ret); void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix, int error_ret); void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix, int error_ret); void generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix, string index, int error_ret); string generate_new_hash_from_type(t_type* key, t_type* value); string generate_new_array_from_type(t_type* ttype); string generate_free_func_from_type(t_type* ttype); string generate_hash_func_from_type(t_type* ttype); string generate_cmp_func_from_type(t_type* ttype); }; /** * Prepare for file generation by opening up the necessary file * output streams. */ void t_c_glib_generator::init_generator() { /* create output directory */ MKDIR(get_out_dir().c_str()); string program_name_u = initial_caps_to_underscores(program_name_); string program_name_uc = to_upper_case(program_name_u); string program_name_lc = to_lower_case(program_name_u); /* create output files */ string f_types_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.h"; f_types_.open(f_types_name.c_str()); string f_types_impl_name = get_out_dir() + this->nspace_lc + program_name_lc + "_types.c"; f_types_impl_.open(f_types_impl_name.c_str()); /* add thrift boilerplate headers */ f_types_ << autogen_comment(); f_types_impl_ << autogen_comment(); /* include inclusion guard */ f_types_ << "#ifndef " << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << "#define " << this->nspace_uc << program_name_uc << "_TYPES_H" << endl << endl; /* include base types */ f_types_ << "/* base includes */" << endl << "#include " << endl << "#include " << endl << "#include " << endl; /* include other thrift includes */ const vector& includes = program_->get_includes(); if (!includes.empty()) { f_types_ << "/* other thrift includes */" << endl; for (auto include : includes) { const std::string& include_nspace = include->get_namespace("c_glib"); std::string include_nspace_prefix = include_nspace.empty() ? "" : initial_caps_to_underscores(include_nspace) + "_"; f_types_ << "#include \"" << include_nspace_prefix << initial_caps_to_underscores(include->get_name()) << "_types.h\"" << endl; } f_types_ << endl; } /* include custom headers */ const vector& c_includes = program_->get_c_includes(); f_types_ << "/* custom thrift includes */" << endl; for (const auto & c_include : c_includes) { if (c_include[0] == '<') { f_types_ << "#include " << c_include << endl; } else { f_types_ << "#include \"" << c_include << "\"" << endl; } } f_types_ << endl; /* include math.h (for "INFINITY") in the implementation file, in case we encounter a struct with a member of type double */ f_types_impl_ << endl << "#include " << endl; // include the types file f_types_impl_ << endl << "#include \"" << this->nspace_lc << program_name_u << "_types.h\"" << endl << "#include " << endl << endl; f_types_ << "/* begin types */" << endl << endl; } /** * Finish up generation and close all file streams. */ void t_c_glib_generator::close_generator() { string program_name_uc = to_upper_case(initial_caps_to_underscores(program_name_)); /* end the header inclusion guard */ f_types_ << "#endif /* " << this->nspace_uc << program_name_uc << "_TYPES_H */" << endl; /* close output file */ f_types_.close(); f_types_impl_.close(); } /** * Generates a Thrift typedef in C code. For example: * * Thrift: * typedef map SomeMap * * C: * typedef GHashTable * ThriftSomeMap; */ void t_c_glib_generator::generate_typedef(t_typedef* ttypedef) { f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << this->nspace << ttypedef->get_symbolic() << ";" << endl << endl; } /** * Generates a C enumeration. For example: * * Thrift: * enum MyEnum { * ONE = 1, * TWO * } * * C: * enum _ThriftMyEnum { * THRIFT_MY_ENUM_ONE = 1, * THRIFT_MY_ENUM_TWO * }; * typedef enum _ThriftMyEnum ThriftMyEnum; */ void t_c_glib_generator::generate_enum(t_enum* tenum) { string name = tenum->get_name(); string name_uc = to_upper_case(initial_caps_to_underscores(name)); f_types_ << indent() << "enum _" << this->nspace << name << " {" << endl; indent_up(); vector constants = tenum->get_constants(); vector::iterator c_iter; bool first = true; /* output each of the enumeration elements */ for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { if (first) { first = false; } else { f_types_ << "," << endl; } f_types_ << indent() << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name(); f_types_ << " = " << (*c_iter)->get_value(); } indent_down(); f_types_ << endl << "};" << endl << "typedef enum _" << this->nspace << name << " " << this->nspace << name << ";" << endl << endl; f_types_ << "/* return the name of the constant */" << endl; f_types_ << "const char *" << endl; f_types_ << "toString_" << name << "(int value); " << endl << endl; ; f_types_impl_ << "/* return the name of the constant */" << endl; f_types_impl_ << "const char *" << endl; f_types_impl_ << "toString_" << name << "(int value) " << endl; f_types_impl_ << "{" << endl; f_types_impl_ << " static __thread char buf[16] = {0};" << endl; f_types_impl_ << " switch(value) {" << endl; std::set done; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); // Skipping duplicate value if (done.find(value) == done.end()) { done.insert(value); f_types_impl_ << " case " << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name() << ":" << "return \"" << this->nspace_uc << name_uc << "_" << (*c_iter)->get_name() << "\";" << endl; } } f_types_impl_ << " default: g_snprintf(buf, 16, \"%d\", value); return buf;" << endl; f_types_impl_ << " }" << endl; f_types_impl_ << "}" << endl << endl; } /** * Generates Thrift constants in C code. */ void t_c_glib_generator::generate_consts(vector consts) { f_types_ << "/* constants */" << endl; f_types_impl_ << "/* constants */" << endl; vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { string name = (*c_iter)->get_name(); string name_uc = to_upper_case(name); string name_lc = to_lower_case(name); t_type* type = (*c_iter)->get_type(); t_const_value* value = (*c_iter)->get_value(); if (is_complex_type(type)) { f_types_ << type_name(type) << indent() << this->nspace_lc << name_lc << "_constant();" << endl; } f_types_ << indent() << "#define " << this->nspace_uc << name_uc << " " << constant_value(name_lc, type, value) << endl; generate_const_initializer(name_lc, type, value, true); } f_types_ << endl; f_types_impl_ << endl; } /** * Generate Thrift structs in C code, as GObjects. Example: * * Thrift: * struct Bonk * { * 1: string message, * 2: i32 type * } * * C GObject instance header: * struct _ThriftBonk * { * GObject parent; * * gchar * message; * gint32 type; * }; * typedef struct _ThriftBonk ThriftBonk * // ... additional GObject boilerplate ... */ void t_c_glib_generator::generate_struct(t_struct* tstruct) { f_types_ << "/* struct " << tstruct->get_name() << " */" << endl; generate_object(tstruct); } /** * Generate C code to represent Thrift services. Creates a new GObject * which can be used to access the service. */ void t_c_glib_generator::generate_service(t_service* tservice) { string svcname_u = initial_caps_to_underscores(tservice->get_name()); string svcname_uc = this->nspace_uc + to_upper_case(svcname_u); string filename = this->nspace_lc + to_lower_case(svcname_u); // make output files string f_header_name = get_out_dir() + filename + ".h"; f_header_.open(f_header_name.c_str()); string program_name_u = initial_caps_to_underscores(program_name_); string program_name_lc = to_lower_case(program_name_u); // add header file boilerplate f_header_ << autogen_comment(); // add an inclusion guard f_header_ << "#ifndef " << svcname_uc << "_H" << endl << "#define " << svcname_uc << "_H" << endl << endl; // add standard includes f_header_ << "#include " << endl << endl; f_header_ << "#include \"" << this->nspace_lc << program_name_lc << "_types.h\"" << endl; // if we are inheriting from another service, include its header t_service* extends_service = tservice->get_extends(); if (extends_service != nullptr) { f_header_ << "#include \"" << this->nspace_lc << to_lower_case(initial_caps_to_underscores(extends_service->get_name())) << ".h\"" << endl; } f_header_ << endl; // create the service implementation string f_service_name = get_out_dir() + filename + ".c"; f_service_.open(f_service_name.c_str()); // add the boilerplace header f_service_ << autogen_comment(); // include the headers f_service_ << "#include " << endl << "#include " << endl << "#include " << endl << "#include \"" << filename << ".h\"" << endl << endl; // generate the service-helper classes generate_service_helpers(tservice); // generate the client objects generate_service_client(tservice); // generate the server objects generate_service_server(tservice); // end the header inclusion guard f_header_ << "#endif /* " << svcname_uc << "_H */" << endl; // close the files f_service_.close(); f_header_.close(); } /** * */ void t_c_glib_generator::generate_xception(t_struct* tstruct) { string name = tstruct->get_name(); string name_u = initial_caps_to_underscores(name); string name_lc = to_lower_case(name_u); string name_uc = to_upper_case(name_u); generate_object(tstruct); f_types_ << "/* exception */" << endl << "typedef enum" << endl << "{" << endl; indent_up(); f_types_ << indent() << this->nspace_uc << name_uc << "_ERROR_CODE" << endl; indent_down(); f_types_ << "} " << this->nspace << name << "Error;" << endl << endl << "GQuark " << this->nspace_lc << name_lc << "_error_quark (void);" << endl << "#define " << this->nspace_uc << name_uc << "_ERROR (" << this->nspace_lc << name_lc << "_error_quark())" << endl << endl << endl; f_types_impl_ << "/* define the GError domain for exceptions */" << endl << "#define " << this->nspace_uc << name_uc << "_ERROR_DOMAIN \"" << this->nspace_lc << name_lc << "_error_quark\"" << endl << "GQuark" << endl << this->nspace_lc << name_lc << "_error_quark (void)" << endl << "{" << endl << " return g_quark_from_static_string (" << this->nspace_uc << name_uc << "_ERROR_DOMAIN);" << endl << "}" << endl << endl; } /******************** * HELPER FUNCTIONS * ********************/ /** * Returns true if ttype is not a primitive. */ bool t_c_glib_generator::is_complex_type(t_type* ttype) { ttype = get_true_type(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception(); } bool t_c_glib_generator::is_numeric(t_type* ttype) { return ttype->is_enum() || (ttype->is_base_type() && !ttype->is_string()); } /** * Maps a Thrift t_type to a C type. */ string t_c_glib_generator::type_name(t_type* ttype, bool in_typedef, bool is_const) { if (ttype->is_base_type()) { string bname = base_type_name(ttype); if (is_const) { return "const " + bname; } else { return bname; } } if (ttype->is_container()) { string cname; t_container* tcontainer = (t_container*)ttype; if (tcontainer->has_cpp_name()) { cname = tcontainer->get_cpp_name(); } else if (ttype->is_map()) { cname = "GHashTable"; } else if (ttype->is_set()) { // since a set requires unique elements, use a GHashTable, and // populate the keys and values with the same data, using keys for // the actual writes and reads. // TODO: discuss whether or not to implement TSet, THashSet or GHashSet cname = "GHashTable"; } else if (ttype->is_list()) { t_type* etype = get_true_type(((t_list*)ttype)->get_elem_type()); if (etype->is_void()) { throw std::runtime_error("compiler error: list element type cannot be void"); } // TODO: investigate other implementations besides GPtrArray cname = is_numeric(etype) ? "GArray" : "GPtrArray"; } /* Omit the dereference operator if we are aliasing this type within a typedef, to allow the type to be used more naturally in client code; otherwise, include it */ if (!in_typedef) { cname += " *"; } if (is_const) { return "const " + cname; } else { return cname; } } // check for a namespace t_program* tprogram = ttype->get_program(); string pname = (tprogram ? tprogram->get_namespace("c_glib") : "") + ttype->get_name(); if (is_complex_type(ttype)) { pname += " *"; } if (is_const) { return "const " + pname; } else { return pname; } } /** * Maps a Thrift primitive to the type needed to hold its value when used as an * object property. * * This method is needed because all integer properties of width less than 64 * bits map to the same type, gint, as opposed to their width-specific type * (gint8, gint16 or gint32). */ string t_c_glib_generator::property_type_name(t_type* ttype, bool in_typedef, bool is_const) { string result; if (ttype->is_base_type()) { switch (((t_base_type*)ttype)->get_base()) { case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: if (is_const) { result = "const gint"; } else { result = "gint"; } break; default: result = type_name(ttype, in_typedef, is_const); } } else { result = type_name(ttype, in_typedef, is_const); } return result; } /** * Maps a Thrift primitive to a C primitive. */ string t_c_glib_generator::base_type_name(t_type* type) { if (type->is_enum()) { return type_name(type); } if (!type->is_base_type()) { throw std::invalid_argument("Only base types are suppported."); } t_base_type* base_type = reinterpret_cast(type); t_base_type::t_base tbase = base_type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: if (base_type->is_binary()) { return "GByteArray *"; } else { return "gchar *"; } case t_base_type::TYPE_BOOL: return "gboolean"; case t_base_type::TYPE_I8: return "gint8"; case t_base_type::TYPE_I16: return "gint16"; case t_base_type::TYPE_I32: return "gint32"; case t_base_type::TYPE_I64: return "gint64"; case t_base_type::TYPE_DOUBLE: return "gdouble"; default: throw std::logic_error("compiler error: no C base type name for base type " + t_base_type::t_base_name(tbase)); } } /** * Returns a member of the ThriftType C enumeration in thrift_protocol.h * for a Thrift type. */ string t_c_glib_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "T_STRING"; case t_base_type::TYPE_BOOL: return "T_BOOL"; case t_base_type::TYPE_I8: return "T_BYTE"; case t_base_type::TYPE_I16: return "T_I16"; case t_base_type::TYPE_I32: return "T_I32"; case t_base_type::TYPE_I64: return "T_I64"; case t_base_type::TYPE_DOUBLE: return "T_DOUBLE"; default: break; } } else if (type->is_enum()) { return "T_I32"; } else if (type->is_struct()) { return "T_STRUCT"; } else if (type->is_xception()) { return "T_STRUCT"; } else if (type->is_map()) { return "T_MAP"; } else if (type->is_set()) { return "T_SET"; } else if (type->is_list()) { return "T_LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Returns a Thrift constant formatted as a literal for inclusion in C code. */ string t_c_glib_generator::constant_literal(t_type* type, t_const_value* value) { ostringstream render; if (type->is_base_type()) { /* primitives */ t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: render << "\"" + value->get_string() + "\""; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() != 0) ? "TRUE" : "FALSE"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: render << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: render << value->get_double(); break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else { t_const_value::t_const_value_type value_type = value->get_type(); switch (value_type) { case t_const_value::CV_IDENTIFIER: render << value->get_integer(); break; case t_const_value::CV_LIST: render << "{ "; { t_type* elem_type = ((t_list*)type)->get_elem_type(); const vector& list = value->get_list(); vector::const_iterator list_iter; if (list.size() > 0) { list_iter = list.begin(); render << constant_literal(elem_type, *list_iter); while (++list_iter != list.end()) { render << ", " << constant_literal(elem_type, *list_iter); } } } render << " }"; break; case t_const_value::CV_MAP: default: render << "NULL /* not supported */"; } } return render.str(); } /** * Returns C code that represents a Thrift constant. */ string t_c_glib_generator::constant_value(string name, t_type* type, t_const_value* value) { ostringstream render; if (type->is_base_type()) { /* primitives */ t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: render << "g_strdup (\"" + value->get_string() + "\")"; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() != 0) ? 1 : 0); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: render << value->get_integer(); break; case t_base_type::TYPE_I64: render << "G_GINT64_CONSTANT (" << value->get_integer() << ")"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << value->get_integer(); } else { render << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { render << "(" << type_name(type) << ")" << value->get_integer(); } else if (is_complex_type(type)) { render << "(" << this->nspace_lc << to_lower_case(name) << "_constant())"; } else { render << "NULL /* not supported */"; } return render.str(); } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_c_glib_generator::function_signature(t_function* tfunction) { t_type* ttype = tfunction->get_returntype(); t_struct* arglist = tfunction->get_arglist(); t_struct* xlist = tfunction->get_xceptions(); string fname = initial_caps_to_underscores(tfunction->get_name()); bool has_return = !ttype->is_void(); bool has_args = arglist->get_members().size() == 0; bool has_xceptions = xlist->get_members().size() == 0; return "gboolean " + this->nspace_lc + fname + " (" + this->nspace + service_name_ + "If * iface" + (has_return ? ", " + type_name(ttype) + "* _return" : "") + (has_args ? "" : (", " + argument_list(arglist))) + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError ** error)"; } /** * Renders a field list * * @param tstruct The struct definition * @return Comma sepearated list of all field names in that struct */ string t_c_glib_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += type_name((*f_iter)->get_type(), false, true) + " " + (*f_iter)->get_name(); } return result; } /** * Renders mutable exception lists * * @param tstruct The struct definition * @return Comma sepearated list of all field names in that struct */ string t_c_glib_generator::xception_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += type_name((*f_iter)->get_type(), false, false) + "* " + (*f_iter)->get_name(); } return result; } /** * Declares a field, including any necessary initialization. */ string t_c_glib_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant, bool reference) { string result = ""; if (constant) { result += "const "; } result += type_name(tfield->get_type()); if (pointer) { result += "*"; } if (reference) { result += "*"; } result += " " + tfield->get_name(); if (init) { t_type* type = get_true_type(tfield->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = (gdouble) 0"; break; case t_base_type::TYPE_STRING: result += " = NULL"; break; default: throw "compiler error: no C intializer for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { result += " = (" + type_name(type) + ") 0"; } else if (type->is_struct() || type->is_container()) { result += " = NULL"; } } if (!reference) { result += ";"; } return result; } string t_c_glib_generator::constant_value_with_storage(string fname, t_type* etype, t_const_value* value) { ostringstream render; if (is_numeric(etype)) { render << " " << type_name(etype) << " *" << fname << " = " << "g_new (" << base_type_name(etype) << ", 1);" << endl << " *" << fname << " = " << constant_value(fname, (t_type*)etype, value) << ";" << endl; } else { render << " " << type_name(etype) << " " << fname << " = " << constant_value(fname, (t_type*)etype, value) << ";" << endl; } return render.str(); } /** * Generates C code that initializes complex constants. */ void t_c_glib_generator::generate_const_initializer(string name, t_type* type, t_const_value* value, bool top_level) { string name_u = initial_caps_to_underscores(name); string name_lc = to_lower_case(name_u); string type_u = initial_caps_to_underscores(type->get_name()); string type_uc = to_upper_case(type_u); string maybe_static = top_level ? "" : "static "; if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; ostringstream initializers; // initialize any constants that may be referenced by this initializer for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; string field_name = ""; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); field_name = (*f_iter)->get_name(); break; } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } field_name = tmp(field_name); generate_const_initializer(name + "_constant_" + field_name, field_type, v_iter->second); initializers << " constant->" << v_iter->first->get_string() << " = " << constant_value(name + "_constant_" + field_name, field_type, v_iter->second) << ";" << endl << " constant->__isset_" << v_iter->first->get_string() << " = TRUE;" << endl; } // implement the initializer f_types_impl_ << maybe_static << this->nspace << type->get_name() << " *" << endl << this->nspace_lc << name_lc << "_constant (void)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << "static " << this->nspace << type->get_name() << " *constant = NULL;" << endl << indent() << "if (constant == NULL)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << "constant = g_object_new (" << this->nspace_uc << "TYPE_" << type_uc << ", NULL);" << endl << initializers.str(); scope_down(f_types_impl_); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; string field_name = ""; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); field_name = (*f_iter)->get_name(); break; } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } field_name = tmp(field_name); } f_types_impl_ << indent() << "return constant;" << endl; scope_down(f_types_impl_); f_types_impl_ << endl; } else if (type->is_list()) { string list_type = "GPtrArray *"; string free_func = generate_free_func_from_type(reinterpret_cast(type)->get_elem_type()); string list_initializer = "g_ptr_array_new_with_free_func (" + free_func + ");"; string list_appender = "g_ptr_array_add"; bool list_variable = false; t_type* etype = ((t_list*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; ostringstream initializers; ostringstream appenders; list_initializer = generate_new_array_from_type(etype); if (etype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)etype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot determine array type"; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: list_type = "GArray *"; list_appender = "g_array_append_val"; list_variable = true; break; case t_base_type::TYPE_STRING: break; default: throw "compiler error: no array info for type"; } } else if (etype->is_enum()) { list_type = "GArray *"; list_appender = "g_array_append_val"; list_variable = true; } for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string fname = tmp(name); generate_const_initializer(fname, etype, (*v_iter)); if (list_variable) { initializers << " " << type_name(etype) << " " << fname << " = " << constant_value(fname, (t_type*)etype, (*v_iter)) << ";" << endl; appenders << " " << list_appender << "(constant, " << fname << ");" << endl; } else { appenders << " " << list_appender << "(constant, " << constant_value(fname, (t_type*)etype, (*v_iter)) << ");" << endl; } } f_types_impl_ << maybe_static << list_type << endl << this->nspace_lc << name_lc << "_constant (void)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << "static " << list_type << " constant = NULL;" << endl << indent() << "if (constant == NULL)" << endl; scope_up(f_types_impl_); if (!initializers.str().empty()) { f_types_impl_ << initializers.str() << endl; } f_types_impl_ << indent() << "constant = " << list_initializer << endl << appenders.str(); scope_down(f_types_impl_); f_types_impl_ << indent() << "return constant;" << endl; scope_down(f_types_impl_); f_types_impl_ << endl; } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; ostringstream initializers; ostringstream appenders; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string fname = tmp(name); string ptr = is_numeric(etype) ? "*" : ""; generate_const_initializer(fname, etype, (*v_iter)); initializers << constant_value_with_storage(fname, (t_type*)etype, *v_iter); appenders << " g_hash_table_insert (constant, " << fname << ", 0);" << endl; } f_types_impl_ << maybe_static << "GHashTable *" << endl << this->nspace_lc << name_lc << "_constant (void)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl << indent() << "if (constant == NULL)" << endl; scope_up(f_types_impl_); f_types_impl_ << initializers.str() << endl << indent() << "constant = " << generate_new_hash_from_type(etype, nullptr) << endl << appenders.str(); scope_down(f_types_impl_); f_types_impl_ << indent() << "return constant;" << endl; scope_down(f_types_impl_); f_types_impl_ << endl; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; ostringstream initializers; ostringstream appenders; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string fname = tmp(name); string kname = fname + "key"; string vname = fname + "val"; generate_const_initializer(kname, ktype, v_iter->first); generate_const_initializer(vname, vtype, v_iter->second); initializers << constant_value_with_storage(kname, (t_type*)ktype, v_iter->first); initializers << constant_value_with_storage(vname, (t_type*)vtype, v_iter->second); appenders << " g_hash_table_insert (constant, " << kname << ", " << vname << ");" << endl; } f_types_impl_ << maybe_static << "GHashTable *" << endl << this->nspace_lc << name_lc << "_constant (void)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << "static GHashTable *constant = NULL;" << endl << indent() << "if (constant == NULL)" << endl; scope_up(f_types_impl_); f_types_impl_ << initializers.str() << endl << indent() << "constant = " << generate_new_hash_from_type(ktype, vtype) << endl << appenders.str(); scope_down(f_types_impl_); f_types_impl_ << indent() << "return constant;" << endl; scope_down(f_types_impl_); f_types_impl_ << endl; } } /** * Generates helper classes for a service, consisting of a ThriftStruct subclass * for the arguments to and the result from each method. * * @param tservice The service for which to generate helper classes */ void t_c_glib_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator function_iter; // Iterate through the service's methods for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string function_name = (*function_iter)->get_name(); t_struct* arg_list = (*function_iter)->get_arglist(); string arg_list_name_orig = arg_list->get_name(); // Generate the arguments class arg_list->set_name(tservice->get_name() + underscores_to_initial_caps(function_name) + "Args"); generate_struct(arg_list); arg_list->set_name(arg_list_name_orig); // Generate the result class if (!(*function_iter)->is_oneway()) { t_struct result(program_, tservice->get_name() + underscores_to_initial_caps(function_name) + "Result"); t_field success((*function_iter)->get_returntype(), "success", 0); success.set_req(t_field::T_OPTIONAL); if (!(*function_iter)->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = (*function_iter)->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator field_iter; for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) { (*field_iter)->set_req(t_field::T_OPTIONAL); result.append(*field_iter); } generate_struct(&result); } } } /** * Generates C code that represents a Thrift service client. */ void t_c_glib_generator::generate_service_client(t_service* tservice) { /* get some C friendly service names */ string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_)); string service_name_uc = to_upper_case(service_name_lc); string parent_service_name; string parent_service_name_lc; string parent_service_name_uc; string parent_class_name = "GObject"; string parent_type_name = "G_TYPE_OBJECT"; // The service this service extends, or nullptr if it extends no // service t_service* extends_service = tservice->get_extends(); if (extends_service) { // The name of the parent service parent_service_name = extends_service->get_name(); parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name)); parent_service_name_uc = to_upper_case(parent_service_name_lc); // The names of the client class' parent class and type parent_class_name = this->nspace + parent_service_name + "Client"; parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_CLIENT"; } // The base service (the topmost in the "extends" hierarchy), on // whose client class the "input_protocol" and "output_protocol" // properties are defined t_service* base_service = tservice; while (base_service->get_extends()) { base_service = base_service->get_extends(); } string base_service_name = base_service->get_name(); string base_service_name_lc = to_lower_case(initial_caps_to_underscores(base_service_name)); string base_service_name_uc = to_upper_case(base_service_name_lc); // Generate the client interface dummy object in the header. f_header_ << "/* " << service_name_ << " service interface */" << endl << "typedef struct _" << this->nspace << service_name_ << "If " << this->nspace << service_name_ << "If; " << " /* dummy object */" << endl << endl; // Generate the client interface object in the header. f_header_ << "struct _" << this->nspace << service_name_ << "IfInterface" << endl << "{" << endl << " GTypeInterface parent;" << endl << endl; /* write out the functions for this interface */ indent_up(); vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { /* make the function name C friendly */ string funname = initial_caps_to_underscores((*f_iter)->get_name()); t_type* ttype = (*f_iter)->get_returntype(); t_struct* arglist = (*f_iter)->get_arglist(); t_struct* xlist = (*f_iter)->get_xceptions(); bool has_return = !ttype->is_void(); bool has_args = arglist->get_members().size() == 0; bool has_xceptions = xlist->get_members().size() == 0; string params = "(" + this->nspace + service_name_ + "If *iface" + (has_return ? ", " + type_name(ttype) + "* _return" : "") + (has_args ? "" : (", " + argument_list(arglist))) + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)"; indent(f_header_) << "gboolean (*" << funname << ") " << params << ";" << endl; } indent_down(); f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "IfInterface " << this->nspace << service_name_ << "IfInterface;" << endl << endl; // generate all the interface boilerplate f_header_ << "GType " << this->nspace_lc << service_name_lc << "_if_get_type (void);" << endl << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF " << "(" << this->nspace_lc << service_name_lc << "_if_get_type())" << endl << "#define " << this->nspace_uc << service_name_uc << "_IF(obj) " << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF, " << this->nspace << service_name_ << "If))" << endl << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_IF(obj) " << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF))" << endl << "#define " << this->nspace_uc << service_name_uc << "_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), " << this->nspace_uc << "TYPE_" << service_name_uc << "_IF, " << this->nspace << service_name_ << "IfInterface))" << endl << endl; // write out all the interface function prototypes for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { /* make the function name C friendly */ string funname = initial_caps_to_underscores((*f_iter)->get_name()); t_type* ttype = (*f_iter)->get_returntype(); t_struct* arglist = (*f_iter)->get_arglist(); t_struct* xlist = (*f_iter)->get_xceptions(); bool has_return = !ttype->is_void(); bool has_args = arglist->get_members().size() == 0; bool has_xceptions = xlist->get_members().size() == 0; string params = "(" + this->nspace + service_name_ + "If *iface" + (has_return ? ", " + type_name(ttype) + "* _return" : "") + (has_args ? "" : (", " + argument_list(arglist))) + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)"; f_header_ << "gboolean " << this->nspace_lc << service_name_lc << "_if_" << funname << " " << params << ";" << endl; } f_header_ << endl; // Generate the client object instance definition in the header. f_header_ << "/* " << service_name_ << " service client */" << endl << "struct _" << this->nspace << service_name_ << "Client" << endl << "{" << endl << " " << parent_class_name << " parent;" << endl; if (!extends_service) { // Define "input_protocol" and "output_protocol" properties only // for base services; child service-client classes will inherit // these f_header_ << endl << " ThriftProtocol *input_protocol;" << endl << " ThriftProtocol *output_protocol;" << endl; } f_header_ << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "Client " << this->nspace << service_name_ << "Client;" << endl << endl; // Generate the class definition in the header. f_header_ << "struct _" << this->nspace << service_name_ << "ClientClass" << endl << "{" << endl << " " << parent_class_name << "Class parent;" << endl << "};" << endl << "typedef struct _" << this->nspace << service_name_ << "ClientClass " << this->nspace << service_name_ << "ClientClass;" << endl << endl; // Create all the GObject boilerplate f_header_ << "GType " << this->nspace_lc << service_name_lc << "_client_get_type (void);" << endl << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT " << "(" << this->nspace_lc << service_name_lc << "_client_get_type())" << endl << "#define " << this->nspace_uc << service_name_uc << "_CLIENT(obj) " << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "Client))" << endl << "#define " << this->nspace_uc << service_name_uc << "_CLIENT_CLASS(c) " << "(G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" << endl << "#define " << this->nspace_uc << service_name_uc << "_IS_CLIENT(obj) " << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT))" << endl << "#define " << this->nspace_uc << service_name_uc << "_IS_CLIENT_CLASS(c) " << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT))" << endl << "#define " << this->nspace_uc << service_name_uc << "_CLIENT_GET_CLASS(obj) " << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_CLIENT, " << this->nspace << service_name_ << "ClientClass))" << endl << endl; /* write out the function prototypes */ for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { /* make the function name C friendly */ string funname = to_lower_case(initial_caps_to_underscores((*f_iter)->get_name())); t_function service_function((*f_iter)->get_returntype(), service_name_lc + string("_client_") + funname, (*f_iter)->get_arglist(), (*f_iter)->get_xceptions()); indent(f_header_) << function_signature(&service_function) << ";" << endl; t_function send_function(g_type_void, service_name_lc + string("_client_send_") + funname, (*f_iter)->get_arglist()); indent(f_header_) << function_signature(&send_function) << ";" << endl; // implement recv if not a oneway service if (!(*f_iter)->is_oneway()) { t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), service_name_lc + string("_client_recv_") + funname, &noargs, (*f_iter)->get_xceptions()); indent(f_header_) << function_signature(&recv_function) << ";" << endl; } } /* write out the get/set function prototypes */ f_header_ << "void " + service_name_lc + "_client_set_property (GObject *object, guint " "property_id, const GValue *value, GParamSpec *pspec);" << endl; f_header_ << "void " + service_name_lc + "_client_get_property (GObject *object, guint " "property_id, GValue *value, GParamSpec *pspec);" << endl; f_header_ << endl; // end of header code // Generate interface method implementations for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { /* make the function name C friendly */ string funname = initial_caps_to_underscores((*f_iter)->get_name()); t_type* ttype = (*f_iter)->get_returntype(); t_struct* arglist = (*f_iter)->get_arglist(); t_struct* xlist = (*f_iter)->get_xceptions(); bool has_return = !ttype->is_void(); bool has_args = arglist->get_members().size() == 0; bool has_xceptions = xlist->get_members().size() == 0; string params = "(" + this->nspace + service_name_ + "If *iface" + (has_return ? ", " + type_name(ttype) + "* _return" : "") + (has_args ? "" : (", " + argument_list(arglist))) + (has_xceptions ? "" : (", " + xception_list(xlist))) + ", GError **error)"; string params_without_type = string("iface, ") + (has_return ? "_return, " : ""); const vector& fields = arglist->get_members(); vector::const_iterator f_iter_field; for (f_iter_field = fields.begin(); f_iter_field != fields.end(); ++f_iter_field) { params_without_type += (*f_iter_field)->get_name(); params_without_type += ", "; } const vector& xceptions = xlist->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { params_without_type += (*x_iter)->get_name(); params_without_type += ", "; } f_service_ << "gboolean" << endl << this->nspace_lc << service_name_lc << "_if_" << funname << " " << params << endl << "{" << endl << " return " << this->nspace_uc << service_name_uc << "_IF_GET_INTERFACE (iface)->" << funname << " (" << params_without_type << "error);" << endl << "}" << endl << endl; } // Generate interface boilerplate f_service_ << "GType" << endl << this->nspace_lc << service_name_lc << "_if_get_type (void)" << endl << "{" << endl << " static GType type = 0;" << endl << " if (type == 0)" << endl << " {" << endl << " static const GTypeInfo type_info =" << endl << " {" << endl << " sizeof (" << this->nspace << service_name_ << "IfInterface)," << endl << " NULL, /* base_init */" << endl << " NULL, /* base_finalize */" << endl << " NULL, /* class_init */" << endl << " NULL, /* class_finalize */" << endl << " NULL, /* class_data */" << endl << " 0, /* instance_size */" << endl << " 0, /* n_preallocs */" << endl << " NULL, /* instance_init */" << endl << " NULL /* value_table */" << endl << " };" << endl << " type = g_type_register_static (G_TYPE_INTERFACE," << endl << " \"" << this->nspace << service_name_ << "If\"," << endl << " &type_info, 0);" << endl << " }" << endl << " return type;" << endl << "}" << endl << endl; // Generate client boilerplate f_service_ << "static void " << endl << this->nspace_lc << service_name_lc << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);" << endl << endl << "G_DEFINE_TYPE_WITH_CODE (" << this->nspace << service_name_ << "Client, " << this->nspace_lc << service_name_lc << "_client," << endl << " " << parent_type_name << ", " << endl << " G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_" << service_name_uc << "_IF," << endl << " " << this->nspace_lc << service_name_lc << "_if_interface_init))" << endl << endl; // Generate property-related code only for base services---child // service-client classes have only properties inherited from their // parent class if (!extends_service) { // Generate client properties f_service_ << "enum _" << this->nspace << service_name_ << "ClientProperties" << endl << "{" << endl << " PROP_0," << endl << " PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL," << endl << " PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL" << endl << "};" << endl << endl; // generate property setter f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_set_property (" << "GObject *object, guint property_id, const GValue *value, " << "GParamSpec *pspec)" << endl << "{" << endl << " " << this->nspace << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc << "_CLIENT (object);" << endl << endl << " THRIFT_UNUSED_VAR (pspec);" << endl << endl << " switch (property_id)" << endl << " {" << endl << " case PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl << " client->input_protocol = g_value_get_object (value);" << endl << " break;" << endl << " case PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL:" << endl << " client->output_protocol = g_value_get_object (value);" << endl << " break;" << endl << " }" << endl << "}" << endl << endl; // generate property getter f_service_ << "void" << endl << this->nspace_lc << service_name_lc << "_client_get_property (" << "GObject *object, guint property_id, GValue *value, " << "GParamSpec *pspec)" << endl << "{" << endl << " " << this->nspace << service_name_ << "Client *client = " << this->nspace_uc << service_name_uc << "_CLIENT (object);" << endl << endl << " THRIFT_UNUSED_VAR (pspec);" << endl << endl << " switch (property_id)" << endl << " {" << endl << " case PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL:" << endl << " g_value_set_object (value, client->input_protocol);" << endl << " break;" << endl << " case PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL:" << endl << " g_value_set_object (value, client->output_protocol);" << endl << " break;" << endl << " }" << endl << "}" << endl << endl; } // Generate client method implementations for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string name = (*f_iter)->get_name(); string funname = initial_caps_to_underscores(name); // Get the struct of function call params and exceptions t_struct* arg_struct = (*f_iter)->get_arglist(); // Function for sending t_function send_function(g_type_void, service_name_lc + string("_client_send_") + funname, (*f_iter)->get_arglist()); // Open the send function indent(f_service_) << function_signature(&send_function) << endl; scope_up(f_service_); string reqType = (*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL"; // Serialize the request f_service_ << indent() << "gint32 cseqid = 0;" << endl << indent() << "ThriftProtocol * protocol = " << this->nspace_uc << base_service_name_uc << "_CLIENT (iface)->output_protocol;" << endl << endl << indent() << "if (thrift_protocol_write_message_begin (protocol, \"" << name << "\", " << reqType << ", cseqid, error) < 0)" << endl << indent() << " return FALSE;" << endl << endl; generate_struct_writer(f_service_, arg_struct, "", "", false); f_service_ << indent() << "if (thrift_protocol_write_message_end (protocol, error) < 0)" << endl << indent() << " return FALSE;" << endl << indent() << "if (!thrift_transport_flush (protocol->transport, error))" << endl << indent() << " return FALSE;" << endl << indent() << "if (!thrift_transport_write_end (protocol->transport, error))" << endl << indent() << " return FALSE;" << endl << endl << indent() << "return TRUE;" << endl; scope_down(f_service_); f_service_ << endl; // Generate recv function only if not an async function if (!(*f_iter)->is_oneway()) { t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), service_name_lc + string("_client_recv_") + funname, &noargs, (*f_iter)->get_xceptions()); // Open function indent(f_service_) << function_signature(&recv_function) << endl; scope_up(f_service_); f_service_ << indent() << "gint32 rseqid;" << endl << indent() << "gchar * fname = NULL;" << endl << indent() << "ThriftMessageType mtype;" << endl << indent() << "ThriftProtocol * protocol = " << this->nspace_uc << base_service_name_uc << "_CLIENT (iface)->input_protocol;" << endl << indent() << "ThriftApplicationException *xception;" << endl << endl << indent() << "if (thrift_protocol_read_message_begin " "(protocol, &fname, &mtype, &rseqid, error) < 0) {" << endl; indent_up(); f_service_ << indent() << "if (fname) g_free (fname);" << endl << indent() << "return FALSE;" << endl; indent_down(); f_service_ << indent() << "}" << endl << endl << indent() << "if (mtype == T_EXCEPTION) {" << endl; indent_up(); f_service_ << indent() << "if (fname) g_free (fname);" << endl << indent() << "xception = g_object_new " "(THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);" << endl << indent() << "thrift_struct_read (THRIFT_STRUCT (xception), " "protocol, NULL);" << endl << indent() << "thrift_protocol_read_message_end " "(protocol, NULL);" << endl << indent() << "thrift_transport_read_end " "(protocol->transport, NULL);" << endl << indent() << "g_set_error (error, " "THRIFT_APPLICATION_EXCEPTION_ERROR,xception->type, " "\"application error: %s\", xception->message);" << endl << indent() << "g_object_unref (xception);" << endl << indent() << "return FALSE;" << endl; indent_down(); f_service_ << indent() << "} else if (mtype != T_REPLY) {" << endl; indent_up(); f_service_ << indent() << "if (fname) g_free (fname);" << endl << indent() << "thrift_protocol_skip (protocol, T_STRUCT, " "NULL);" << endl << indent() << "thrift_protocol_read_message_end (protocol, " "NULL);" << endl << indent() << "thrift_transport_read_end (" "protocol->transport, NULL);" << endl << indent() << "g_set_error (error, " "THRIFT_APPLICATION_EXCEPTION_ERROR, " "THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE, " "\"invalid message type %d, expected T_REPLY\", mtype);" << endl << indent() << "return FALSE;" << endl; indent_down(); f_service_ << indent() << "} else if (strncmp (fname, \"" << name << "\", " << name.length() << ") != 0) {" << endl; indent_up(); f_service_ << indent() << "thrift_protocol_skip (protocol, T_STRUCT, " "NULL);" << endl << indent() << "thrift_protocol_read_message_end (protocol," "error);" << endl << indent() << "thrift_transport_read_end (" "protocol->transport, error);" << endl << indent() << "g_set_error (error, " "THRIFT_APPLICATION_EXCEPTION_ERROR, " "THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME, " "\"wrong method name %s, expected " << name << "\", fname);" << endl << indent() << "if (fname) g_free (fname);" << endl << indent() << "return FALSE;" << endl; indent_down(); f_service_ << indent() << "}" << endl << indent() << "if (fname) g_free (fname);" << endl << endl; t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; { t_struct result(program_, tservice->get_name() + "_" + (*f_iter)->get_name() + "_result"); t_field success((*f_iter)->get_returntype(), "*_return", 0); if (!(*f_iter)->get_returntype()->is_void()) { result.append(&success); } // add readers for exceptions, dereferencing the pointer. for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) { t_field* xception = new t_field((*x_iter)->get_type(), "*" + (*x_iter)->get_name(), (*x_iter)->get_key()); result.append(xception); } generate_struct_reader(f_service_, &result, "", "", false); } f_service_ << indent() << "if (thrift_protocol_read_message_end (protocol, error) < 0)" << endl << indent() << " return FALSE;" << endl << endl << indent() << "if (!thrift_transport_read_end (protocol->transport, error))" << endl << indent() << " return FALSE;" << endl << endl; // copy over any throw exceptions and return failure for (x_iter = xceptions.begin(); x_iter != xceptions.end(); x_iter++) { f_service_ << indent() << "if (*" << (*x_iter)->get_name() << " != NULL)" << endl << indent() << "{" << endl << indent() << " g_set_error (error, " << this->nspace_uc << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name())) << "_ERROR, " << this->nspace_uc << to_upper_case(initial_caps_to_underscores((*x_iter)->get_type()->get_name())) << "_ERROR_CODE, \"" << (*x_iter)->get_type()->get_name() << "\");" << endl << indent() << " return FALSE;" << endl << indent() << "}" << endl; } // Close function indent(f_service_) << "return TRUE;" << endl; scope_down(f_service_); f_service_ << endl; } // Open function t_function service_function((*f_iter)->get_returntype(), service_name_lc + string("_client_") + funname, (*f_iter)->get_arglist(), (*f_iter)->get_xceptions()); indent(f_service_) << function_signature(&service_function) << endl; scope_up(f_service_); // wrap each function f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_send_" << funname << " (iface"; // Declare the function arguments const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << ", " << (*fld_iter)->get_name(); } f_service_ << ", error))" << endl << indent() << " return FALSE;" << endl; // if not oneway, implement recv if (!(*f_iter)->is_oneway()) { string ret = (*f_iter)->get_returntype()->is_void() ? "" : "_return, "; const vector& xceptions = (*f_iter)->get_xceptions()->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { ret += (*x_iter)->get_name(); ret += ", "; } f_service_ << indent() << "if (!" << this->nspace_lc << service_name_lc << "_client_recv_" << funname << " (iface, " << ret << "error))" << endl << indent() << " return FALSE;" << endl; } // return TRUE which means all functions were called OK indent(f_service_) << "return TRUE;" << endl; scope_down(f_service_); f_service_ << endl; } // create the interface initializer f_service_ << "static void" << endl << this->nspace_lc << service_name_lc << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)" << endl; scope_up(f_service_); if (functions.size() > 0) { for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { /* make the function name C friendly */ string funname = initial_caps_to_underscores((*f_iter)->get_name()); f_service_ << indent() << "iface->" << funname << " = " << this->nspace_lc << service_name_lc << "_client_" << funname << ";" << endl; } } else { f_service_ << indent() << "THRIFT_UNUSED_VAR (iface);" << endl; } scope_down(f_service_); f_service_ << endl; // create the client instance initializer f_service_ << "static void" << endl << this->nspace_lc << service_name_lc << "_client_init (" << this->nspace << service_name_ << "Client *client)" << endl; scope_up(f_service_); if (!extends_service) { f_service_ << indent() << "client->input_protocol = NULL;" << endl << indent() << "client->output_protocol = NULL;" << endl; } else { f_service_ << indent() << "THRIFT_UNUSED_VAR (client);" << endl; } scope_down(f_service_); f_service_ << endl; // create the client class initializer f_service_ << "static void" << endl << this->nspace_lc << service_name_lc << "_client_class_init (" << this->nspace << service_name_ << "ClientClass *cls)" << endl << "{" << endl; if (!extends_service) { f_service_ << " GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl << " GParamSpec *param_spec;" << endl << endl << " gobject_class->set_property = " << this->nspace_lc << service_name_lc << "_client_set_property;" << endl << " gobject_class->get_property = " << this->nspace_lc << service_name_lc << "_client_get_property;" << endl << endl << " param_spec = g_param_spec_object (\"input_protocol\"," << endl << " \"input protocol (construct)\"," << endl << " \"Set the client input protocol\"," << endl << " THRIFT_TYPE_PROTOCOL," << endl << " G_PARAM_READWRITE);" << endl << " g_object_class_install_property (gobject_class," << endl << " PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_INPUT_PROTOCOL, param_spec);" << endl << endl << " param_spec = g_param_spec_object (\"output_protocol\"," << endl << " \"output protocol (construct)\"," << endl << " \"Set the client output protocol\"," << endl << " THRIFT_TYPE_PROTOCOL," << endl << " G_PARAM_READWRITE);" << endl << " g_object_class_install_property (gobject_class," << endl << " PROP_" << this->nspace_uc << service_name_uc << "_CLIENT_OUTPUT_PROTOCOL, param_spec);" << endl; } else { f_service_ << " THRIFT_UNUSED_VAR (cls);" << endl; } f_service_ << "}" << endl << endl; } /** * Generates C code that represents a Thrift service handler. * * @param tservice The service for which to generate a handler. */ void t_c_glib_generator::generate_service_handler(t_service* tservice) { vector functions = tservice->get_functions(); vector::const_iterator function_iter; string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_)); string service_name_uc = to_upper_case(service_name_lc); string service_handler_name = service_name_ + "Handler"; string class_name = this->nspace + service_handler_name; string class_name_lc = this->nspace_lc + initial_caps_to_underscores(service_handler_name); string class_name_uc = to_upper_case(class_name_lc); string parent_class_name; string parent_type_name; string args_indent; // The service this service extends, or nullptr if it extends no service t_service* extends_service = tservice->get_extends(); // Determine the name of our parent service (if any) and the handler class' // parent class name and type if (extends_service) { string parent_service_name = extends_service->get_name(); string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name)); string parent_service_name_uc = to_upper_case(parent_service_name_lc); parent_class_name = this->nspace + parent_service_name + "Handler"; parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_HANDLER"; } else { parent_class_name = "GObject"; parent_type_name = "G_TYPE_OBJECT"; } // Generate the handler class' definition in the header file // Generate the handler instance definition f_header_ << "/* " << service_name_ << " handler (abstract base class) */" << endl << "struct _" << class_name << endl << "{" << endl; indent_up(); f_header_ << indent() << parent_class_name << " parent;" << endl; indent_down(); f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl << endl; // Generate the handler class definition, including its class members // (methods) f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl; indent_up(); f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl; for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string method_name = initial_caps_to_underscores((*function_iter)->get_name()); t_type* return_type = (*function_iter)->get_returntype(); t_struct* arg_list = (*function_iter)->get_arglist(); t_struct* x_list = (*function_iter)->get_xceptions(); bool has_return = !return_type->is_void(); bool has_args = arg_list->get_members().size() == 0; bool has_xceptions = x_list->get_members().size() == 0; string params = "(" + this->nspace + service_name_ + "If *iface" + (has_return ? ", " + type_name(return_type) + "* _return" : "") + (has_args ? "" : (", " + argument_list(arg_list))) + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)"; indent(f_header_) << "gboolean (*" << method_name << ") " << params << ";" << endl; } indent_down(); f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name << "Class;" << endl << endl; // Generate the remaining header boilerplate f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER " << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc << "(obj) " << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER, " << class_name << "))" << endl << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER(obj) " << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER))" << endl << "#define " << class_name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER_CLASS(c) " << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER))" << endl << "#define " << this->nspace_uc << service_name_uc << "_HANDLER_GET_CLASS(obj) " << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_HANDLER, " << class_name << "Class))" << endl << endl; // Generate the handler class' method definitions for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string method_name = initial_caps_to_underscores((*function_iter)->get_name()); t_type* return_type = (*function_iter)->get_returntype(); t_struct* arg_list = (*function_iter)->get_arglist(); t_struct* x_list = (*function_iter)->get_xceptions(); bool has_return = !return_type->is_void(); bool has_args = arg_list->get_members().size() == 0; bool has_xceptions = x_list->get_members().size() == 0; string params = "(" + this->nspace + service_name_ + "If *iface" + (has_return ? ", " + type_name(return_type) + "* _return" : "") + (has_args ? "" : (", " + argument_list(arg_list))) + (has_xceptions ? "" : (", " + xception_list(x_list))) + ", GError **error)"; f_header_ << "gboolean " << class_name_lc << "_" << method_name << " " << params << ";" << endl; } f_header_ << endl; // Generate the handler's implementation in the implementation file // Generate the implementation boilerplate f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface);" << endl << endl; args_indent = string(25, ' '); f_service_ << "G_DEFINE_TYPE_WITH_CODE (" << class_name << ", " << endl << args_indent << class_name_lc << "," << endl << args_indent << parent_type_name << "," << endl << args_indent << "G_IMPLEMENT_INTERFACE (" << this->nspace_uc << "TYPE_" << service_name_uc << "_IF," << endl; args_indent += string(23, ' '); f_service_ << args_indent << class_name_lc << "_" << service_name_lc << "_if_interface_init))" << endl << endl; // Generate the handler method implementations for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string function_name = (*function_iter)->get_name(); string method_name = initial_caps_to_underscores(function_name); t_type* return_type = (*function_iter)->get_returntype(); t_struct* arg_list = (*function_iter)->get_arglist(); t_struct* x_list = (*function_iter)->get_xceptions(); const vector& args = arg_list->get_members(); const vector& xceptions = x_list->get_members(); vector::const_iterator field_iter; t_function implementing_function(return_type, service_name_lc + "_handler_" + method_name, arg_list, x_list, (*function_iter)->is_oneway()); indent(f_service_) << function_signature(&implementing_function) << endl; scope_up(f_service_); f_service_ << indent() << "g_return_val_if_fail (" << this->nspace_uc << "IS_" << service_name_uc << "_HANDLER (iface), FALSE);" << endl << endl << indent() << "return " << class_name_uc << "_GET_CLASS (iface)" << "->" << method_name << " (iface, "; if (!return_type->is_void()) { f_service_ << "_return, "; } for (field_iter = args.begin(); field_iter != args.end(); ++field_iter) { f_service_ << (*field_iter)->get_name() << ", "; } for (field_iter = xceptions.begin(); field_iter != xceptions.end(); ++field_iter) { f_service_ << (*field_iter)->get_name() << ", "; } f_service_ << "error);" << endl; scope_down(f_service_); f_service_ << endl; } // Generate the handler interface initializer f_service_ << "static void" << endl << class_name_lc << "_" << service_name_lc << "_if_interface_init (" << this->nspace << service_name_ << "IfInterface *iface)" << endl; scope_up(f_service_); if (functions.size() > 0) { for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string method_name = initial_caps_to_underscores((*function_iter)->get_name()); f_service_ << indent() << "iface->" << method_name << " = " << class_name_lc << "_" << method_name << ";" << endl; } } else { f_service_ << "THRIFT_UNUSED_VAR (iface);" << endl; } scope_down(f_service_); f_service_ << endl; // Generate the handler instance initializer f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)" << endl; scope_up(f_service_); f_service_ << indent() << "THRIFT_UNUSED_VAR (self);" << endl; scope_down(f_service_); f_service_ << endl; // Generate the handler class initializer f_service_ << "static void" << endl << class_name_lc << "_class_init (" << class_name << "Class *cls)" << endl; scope_up(f_service_); if (functions.size() > 0) { for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string function_name = (*function_iter)->get_name(); string method_name = initial_caps_to_underscores(function_name); // All methods are pure virtual and must be implemented by subclasses f_service_ << indent() << "cls->" << method_name << " = NULL;" << endl; } } else { f_service_ << indent() << "THRIFT_UNUSED_VAR (cls);" << endl; } scope_down(f_service_); f_service_ << endl; } /** * Generates C code that represents a Thrift service processor. * * @param tservice The service for which to generate a processor */ void t_c_glib_generator::generate_service_processor(t_service* tservice) { vector functions = tservice->get_functions(); vector::const_iterator function_iter; string service_name_lc = to_lower_case(initial_caps_to_underscores(service_name_)); string service_name_uc = to_upper_case(service_name_lc); string service_processor_name = service_name_ + "Processor"; string class_name = this->nspace + service_processor_name; string class_name_lc = this->nspace_lc + initial_caps_to_underscores(service_processor_name); string class_name_uc = to_upper_case(class_name_lc); string parent_class_name; string parent_type_name; string handler_class_name = this->nspace + service_name_ + "Handler"; string handler_class_name_lc = initial_caps_to_underscores(handler_class_name); string process_function_type_name = class_name + "ProcessFunction"; string process_function_def_type_name = class_name_lc + "_process_function_def"; string function_name; string args_indent; // The service this service extends, or nullptr if it extends no service t_service* extends_service = tservice->get_extends(); // Determine the name of our parent service (if any) and the // processor class' parent class name and type if (extends_service) { string parent_service_name = extends_service->get_name(); string parent_service_name_lc = to_lower_case(initial_caps_to_underscores(parent_service_name)); string parent_service_name_uc = to_upper_case(parent_service_name_lc); parent_class_name = this->nspace + parent_service_name + "Processor"; parent_type_name = this->nspace_uc + "TYPE_" + parent_service_name_uc + "_PROCESSOR"; } else { parent_class_name = "ThriftDispatchProcessor"; parent_type_name = "THRIFT_TYPE_DISPATCH_PROCESSOR"; } // Generate the processor class' definition in the header file // Generate the processor instance definition f_header_ << "/* " << service_name_ << " processor */" << endl << "struct _" << class_name << endl << "{" << endl; indent_up(); f_header_ << indent() << parent_class_name << " parent;" << endl << endl << indent() << "/* protected */" << endl << indent() << this->nspace + service_name_ + "Handler *handler;" << endl << indent() << "GHashTable *process_map;" << endl; indent_down(); f_header_ << "};" << endl << "typedef struct _" << class_name << " " << class_name << ";" << endl << endl; // Generate the processor class definition f_header_ << "struct _" << class_name << "Class" << endl << "{" << endl; indent_up(); f_header_ << indent() << parent_class_name << "Class parent;" << endl << endl << indent() << "/* protected */" << endl << indent() << "gboolean (*dispatch_call) (ThriftDispatchProcessor *processor," << endl; args_indent = indent() + string(27, ' '); f_header_ << args_indent << "ThriftProtocol *in," << endl << args_indent << "ThriftProtocol *out," << endl << args_indent << "gchar *fname," << endl << args_indent << "gint32 seqid," << endl << args_indent << "GError **error);" << endl; indent_down(); f_header_ << "};" << endl << "typedef struct _" << class_name << "Class " << class_name << "Class;" << endl << endl; // Generate the remaining header boilerplate f_header_ << "GType " << class_name_lc << "_get_type (void);" << endl << "#define " << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR " << "(" << class_name_lc << "_get_type())" << endl << "#define " << class_name_uc << "(obj) " << "(G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR, " << class_name << "))" << endl << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_PROCESSOR(obj) " << "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR))" << endl << "#define " << class_name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR, " << class_name << "Class))" << endl << "#define " << this->nspace_uc << "IS_" << service_name_uc << "_PROCESSOR_CLASS(c) " << "(G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR))" << endl << "#define " << this->nspace_uc << service_name_uc << "_PROCESSOR_GET_CLASS(obj) " << "(G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" << service_name_uc << "_PROCESSOR, " << class_name << "Class))" << endl << endl; // Generate the processor's implementation in the implementation file // Generate the processor's properties enum f_service_ << "enum _" << class_name << "Properties" << endl << "{" << endl; indent_up(); f_service_ << indent() << "PROP_" << class_name_uc << "_0," << endl << indent() << "PROP_" << class_name_uc << "_HANDLER" << endl; indent_down(); f_service_ << "};" << endl << endl; // Generate the implementation boilerplate args_indent = string(15, ' '); f_service_ << "G_DEFINE_TYPE (" << class_name << "," << endl << args_indent << class_name_lc << "," << endl << args_indent << parent_type_name << ")" << endl << endl; // Generate the processor's processing-function type args_indent = string(process_function_type_name.length() + 23, ' '); f_service_ << "typedef gboolean (* " << process_function_type_name << ") (" << class_name << " *, " << endl << args_indent << "gint32," << endl << args_indent << "ThriftProtocol *," << endl << args_indent << "ThriftProtocol *," << endl << args_indent << "GError **);" << endl << endl; // Generate the processor's processing-function-definition type f_service_ << "typedef struct" << endl << "{" << endl; indent_up(); f_service_ << indent() << "gchar *name;" << endl << indent() << process_function_type_name << " function;" << endl; indent_down(); f_service_ << "} " << process_function_def_type_name << ";" << endl << endl; // Generate forward declarations of the processor's processing functions so we // can refer to them in the processing-function-definition struct below and // keep all of the processor's declarations in one place for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { function_name = class_name_lc + "_process_" + initial_caps_to_underscores((*function_iter)->get_name()); args_indent = string(function_name.length() + 2, ' '); f_service_ << "static gboolean" << endl << function_name << " (" << class_name << " *," << endl << args_indent << "gint32," << endl << args_indent << "ThriftProtocol *," << endl << args_indent << "ThriftProtocol *," << endl << args_indent << "GError **);" << endl; } f_service_ << endl; // Generate the processor's processing-function definitions, if the service // defines any methods if (functions.size() > 0) { f_service_ << indent() << "static " << process_function_def_type_name << endl << indent() << class_name_lc << "_process_function_defs[" << functions.size() << "] = {" << endl; indent_up(); for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string service_function_name = (*function_iter)->get_name(); string process_function_name = class_name_lc + "_process_" + initial_caps_to_underscores(service_function_name); f_service_ << indent() << "{" << endl; indent_up(); f_service_ << indent() << "\"" << service_function_name << "\"," << endl << indent() << process_function_name << endl; indent_down(); f_service_ << indent() << "}" << (function_iter == --functions.end() ? "" : ",") << endl; } indent_down(); f_service_ << indent() << "};" << endl << endl; } // Generate the processor's processing functions for (function_iter = functions.begin(); function_iter != functions.end(); ++function_iter) { string service_function_name = (*function_iter)->get_name(); string service_function_name_ic = underscores_to_initial_caps(service_function_name); string service_function_name_lc = initial_caps_to_underscores(service_function_name); string service_function_name_uc = to_upper_case(service_function_name_lc); t_type* return_type = (*function_iter)->get_returntype(); bool has_return_value = !return_type->is_void(); t_struct* arg_list = (*function_iter)->get_arglist(); const vector& args = arg_list->get_members(); vector::const_iterator arg_iter; const vector& xceptions = (*function_iter)->get_xceptions()->get_members(); vector::const_iterator xception_iter; string args_class_name = this->nspace + service_name_ + service_function_name_ic + "Args"; string args_class_type = this->nspace_uc + "TYPE_" + service_name_uc + "_" + service_function_name_uc + "_ARGS"; string result_class_name = this->nspace + service_name_ + service_function_name_ic + "Result"; string result_class_type = this->nspace_uc + "TYPE_" + service_name_uc + "_" + service_function_name_uc + "_RESULT"; string handler_function_name = handler_class_name_lc + "_" + service_function_name_lc; function_name = class_name_lc + "_process_" + initial_caps_to_underscores(service_function_name); args_indent = string(function_name.length() + 2, ' '); f_service_ << "static gboolean" << endl << function_name << " (" << class_name << " *self," << endl << args_indent << "gint32 sequence_id," << endl << args_indent << "ThriftProtocol *input_protocol," << endl << args_indent << "ThriftProtocol *output_protocol," << endl << args_indent << "GError **error)" << endl; scope_up(f_service_); f_service_ << indent() << "gboolean result = TRUE;" << endl << indent() << "ThriftTransport * transport;" << endl << indent() << "ThriftApplicationException *xception;" << endl << indent() << args_class_name + " * args =" << endl; indent_up(); f_service_ << indent() << "g_object_new (" << args_class_type << ", NULL);" << endl << endl; indent_down(); if ((*function_iter)->is_oneway()) { f_service_ << indent() << "THRIFT_UNUSED_VAR (sequence_id);" << endl << indent() << "THRIFT_UNUSED_VAR (output_protocol);" << endl << endl; } f_service_ << indent() << "g_object_get (input_protocol, \"transport\", " << "&transport, NULL);" << endl << endl; // Read the method's arguments from the caller f_service_ << indent() << "if ((thrift_struct_read (THRIFT_STRUCT (args), " << "input_protocol, error) != -1) &&" << endl << indent() << " (thrift_protocol_read_message_end (input_protocol, " << "error) != -1) &&" << endl << indent() << " (thrift_transport_read_end (transport, error) != FALSE))" << endl; scope_up(f_service_); for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { f_service_ << indent() << property_type_name((*arg_iter)->get_type()) << " " << (*arg_iter)->get_name() << ";" << endl; } for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) { f_service_ << indent() << type_name((*xception_iter)->get_type()) << " " << initial_caps_to_underscores((*xception_iter)->get_name()) << " = NULL;" << endl; } if (has_return_value) { f_service_ << indent() << property_type_name(return_type) << " return_value;" << endl; } if (!(*function_iter)->is_oneway()) { f_service_ << indent() << result_class_name << " * result_struct;" << endl; } f_service_ << endl; if (args.size() > 0) { f_service_ << indent() << "g_object_get (args," << endl; args_indent = indent() + string(14, ' '); for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { string arg_name = (*arg_iter)->get_name(); f_service_ << args_indent << "\"" << arg_name << "\", &" << arg_name << "," << endl; } f_service_ << args_indent << "NULL);" << endl << endl; } if (!(*function_iter)->is_oneway()) { f_service_ << indent() << "g_object_unref (transport);" << endl << indent() << "g_object_get (output_protocol, \"transport\", " << "&transport, NULL);" << endl << endl << indent() << "result_struct = g_object_new (" << result_class_type << ", NULL);" << endl; if (has_return_value) { f_service_ << indent() << "g_object_get (result_struct, " "\"success\", &return_value, NULL);" << endl; } f_service_ << endl; } // Pass the arguments to the corresponding method in the handler f_service_ << indent() << "if (" << handler_function_name << " (" << this->nspace_uc << service_name_uc << "_IF (self->handler)," << endl; args_indent = indent() + string(handler_function_name.length() + 6, ' '); if (has_return_value) { string return_type_name = type_name(return_type); f_service_ << args_indent; // Cast return_value if it was declared as a type other than the return // value's actual type---this is true for integer values 32 bits or fewer // in width, for which GLib requires a plain gint type be used when // storing or retrieving as an object property if (return_type_name != property_type_name(return_type)) { if (return_type_name[return_type_name.length() - 1] != '*') { return_type_name += ' '; } return_type_name += '*'; f_service_ << "(" << return_type_name << ")"; } f_service_ << "&return_value," << endl; } for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { f_service_ << args_indent << (*arg_iter)->get_name() << "," << endl; } for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) { f_service_ << args_indent << "&" << initial_caps_to_underscores((*xception_iter)->get_name()) << "," << endl; } f_service_ << args_indent << "error) == TRUE)" << endl; scope_up(f_service_); // The handler reported success; return the result, if any, to the caller if (!(*function_iter)->is_oneway()) { if (has_return_value) { f_service_ << indent() << "g_object_set (result_struct, \"success\", "; if (type_name(return_type) != property_type_name(return_type)) { // Roundtrip cast to fix the position of sign bit. f_service_ << "(" << property_type_name(return_type) << ")" << "(" << type_name(return_type) << ")"; } f_service_ << "return_value, " << "NULL);" << endl; f_service_ << endl; } f_service_ << indent() << "result =" << endl; indent_up(); f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl; args_indent = indent() + string(39, ' '); f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent << "T_REPLY," << endl << args_indent << "sequence_id," << endl << args_indent << "error) != -1) &&" << endl << indent() << " (thrift_struct_write (THRIFT_STRUCT (result_struct)," << endl; args_indent = indent() + string(23, ' '); f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));" << endl; indent_down(); } scope_down(f_service_); f_service_ << indent() << "else" << endl; scope_up(f_service_); // The handler reported failure; check to see if an application-defined // exception was raised and if so, return it to the caller f_service_ << indent(); if (xceptions.size() > 0) { for (xception_iter = xceptions.begin(); xception_iter != xceptions.end(); ++xception_iter) { f_service_ << "if (" << initial_caps_to_underscores((*xception_iter)->get_name()) << " != NULL)" << endl; scope_up(f_service_); f_service_ << indent() << "g_object_set (result_struct," << endl; args_indent = indent() + string(14, ' '); f_service_ << args_indent << "\"" << (*xception_iter)->get_name() << "\", " << (*xception_iter)->get_name() << "," << endl << args_indent << "NULL);" << endl << endl; f_service_ << indent() << "g_object_unref ("<< (*xception_iter)->get_name() <<");"<< endl; f_service_ << indent() << "result =" << endl; indent_up(); f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl; args_indent = indent() + string(39, ' '); f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent << "T_REPLY," << endl << args_indent << "sequence_id," << endl << args_indent << "error) != -1) &&" << endl << indent() << " (thrift_struct_write (THRIFT_STRUCT (result_struct)," << endl; args_indent = indent() + string(23, ' '); f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));" << endl; indent_down(); scope_down(f_service_); f_service_ << indent() << "else" << endl; } scope_up(f_service_); f_service_ << indent(); } // If the handler reported failure but raised no application-defined // exception, return a Thrift application exception with the information // returned via GLib's own error-reporting mechanism f_service_ << "if (*error == NULL)" << endl; indent_up(); f_service_ << indent() << "g_warning (\"" << service_name_ << "." << (*function_iter)->get_name() << " implementation returned FALSE \"" << endl << indent() << string(11, ' ') << "\"but did not set an error\");" << endl << endl; indent_down(); f_service_ << indent() << "xception =" << endl; indent_up(); f_service_ << indent() << "g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION," << endl; args_indent = indent() + string(14, ' '); f_service_ << args_indent << "\"type\", *error != NULL ? (*error)->code :" << endl << args_indent << string(11, ' ') << "THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN," << endl << args_indent << "\"message\", *error != NULL ? (*error)->message : NULL," << endl << args_indent << "NULL);" << endl; indent_down(); f_service_ << indent() << "g_clear_error (error);" << endl << endl << indent() << "result =" << endl; indent_up(); f_service_ << indent() << "((thrift_protocol_write_message_begin (output_protocol," << endl; args_indent = indent() + string(39, ' '); f_service_ << args_indent << "\"" << service_function_name << "\"," << endl << args_indent << "T_EXCEPTION," << endl << args_indent << "sequence_id," << endl << args_indent << "error) != -1) &&" << endl << indent() << " (thrift_struct_write (THRIFT_STRUCT (xception)," << endl; args_indent = indent() + string(23, ' '); f_service_ << args_indent << "output_protocol," << endl << args_indent << "error) != -1));" << endl; indent_down(); f_service_ << endl << indent() << "g_object_unref (xception);" << endl; if (xceptions.size() > 0) { scope_down(f_service_); } scope_down(f_service_); f_service_ << endl; // Dellocate or unref retrieved argument values as necessary for (arg_iter = args.begin(); arg_iter != args.end(); ++arg_iter) { string arg_name = (*arg_iter)->get_name(); t_type* arg_type = get_true_type((*arg_iter)->get_type()); if (arg_type->is_base_type()) { t_base_type* base_type = ((t_base_type*)arg_type); if (base_type->get_base() == t_base_type::TYPE_STRING) { f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl; indent_up(); if (base_type->is_binary()) { f_service_ << indent() << "g_byte_array_unref (" << arg_name << ");" << endl; } else { f_service_ << indent() << "g_free (" << arg_name << ");" << endl; } indent_down(); } } else if (arg_type->is_container()) { f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl; indent_up(); if (arg_type->is_list()) { t_type* elem_type = ((t_list*)arg_type)->get_elem_type(); f_service_ << indent(); if (is_numeric(elem_type)) { f_service_ << "g_array_unref"; } else { f_service_ << "g_ptr_array_unref"; } f_service_ << " (" << arg_name << ");" << endl; } else if (arg_type->is_map() || arg_type->is_set()) { f_service_ << indent() << "g_hash_table_unref (" << arg_name << ");" << endl; } indent_down(); } else if (arg_type->is_struct()) { f_service_ << indent() << "if (" << arg_name << " != NULL)" << endl; indent_up(); f_service_ << indent() << "g_object_unref (" << arg_name << ");" << endl; indent_down(); } } if (!(*function_iter)->is_oneway()) { if (has_return_value) { // Deallocate (or unref) return_value return_type = get_true_type(return_type); if (return_type->is_base_type()) { t_base_type* base_type = ((t_base_type*)return_type); if (base_type->get_base() == t_base_type::TYPE_STRING) { f_service_ << indent() << "if (return_value != NULL)" << endl; indent_up(); if (base_type->is_binary()) { f_service_ << indent() << "g_byte_array_unref (return_value);" << endl; } else { f_service_ << indent() << "g_free (return_value);" << endl; } indent_down(); } } else if (return_type->is_container()) { f_service_ << indent() << "if (return_value != NULL)" << endl; indent_up(); if (return_type->is_list()) { t_type* elem_type = ((t_list*)return_type)->get_elem_type(); f_service_ << indent(); if (is_numeric(elem_type)) { f_service_ << "g_array_unref"; } else { f_service_ << "g_ptr_array_unref"; } f_service_ << " (return_value);" << endl; } else if (return_type->is_map() || return_type->is_set()) { f_service_ << indent() << "g_hash_table_unref (return_value);" << endl; } indent_down(); } else if (return_type->is_struct()) { f_service_ << indent() << "if (return_value != NULL)" << endl; indent_up(); f_service_ << indent() << "g_object_unref (return_value);" << endl; indent_down(); } } f_service_ << indent() << "g_object_unref (result_struct);" << endl << endl << indent() << "if (result == TRUE)" << endl; indent_up(); f_service_ << indent() << "result =" << endl; indent_up(); f_service_ << indent() << "((thrift_protocol_write_message_end " << "(output_protocol, error) != -1) &&" << endl << indent() << " (thrift_transport_write_end (transport, error) " << "!= FALSE) &&" << endl << indent() << " (thrift_transport_flush (transport, error) " << "!= FALSE));" << endl; indent_down(); indent_down(); } scope_down(f_service_); f_service_ << indent() << "else" << endl; indent_up(); f_service_ << indent() << "result = FALSE;" << endl; indent_down(); f_service_ << endl << indent() << "g_object_unref (transport);" << endl << indent() << "g_object_unref (args);" << endl << endl << indent() << "return result;" << endl; scope_down(f_service_); f_service_ << endl; } // Generate the processor's dispatch_call implementation function_name = class_name_lc + "_dispatch_call"; args_indent = indent() + string(function_name.length() + 2, ' '); f_service_ << "static gboolean" << endl << function_name << " (ThriftDispatchProcessor *dispatch_processor," << endl << args_indent << "ThriftProtocol *input_protocol," << endl << args_indent << "ThriftProtocol *output_protocol," << endl << args_indent << "gchar *method_name," << endl << args_indent << "gint32 sequence_id," << endl << args_indent << "GError **error)" << endl; scope_up(f_service_); f_service_ << indent() << class_name_lc << "_process_function_def *" << "process_function_def;" << endl; f_service_ << indent() << "gboolean dispatch_result = FALSE;" << endl << endl << indent() << class_name << " *self = " << class_name_uc << " (dispatch_processor);" << endl; f_service_ << indent() << parent_class_name << "Class " "*parent_class =" << endl; indent_up(); f_service_ << indent() << "g_type_class_peek_parent (" << class_name_uc << "_GET_CLASS (self));" << endl; indent_down(); f_service_ << endl << indent() << "process_function_def = " << "g_hash_table_lookup (self->process_map, method_name);" << endl << indent() << "if (process_function_def != NULL)" << endl; scope_up(f_service_); args_indent = indent() + string(53, ' '); f_service_ << indent() << "g_free (method_name);" << endl << indent() << "dispatch_result = " << "(*process_function_def->function) (self," << endl << args_indent << "sequence_id," << endl << args_indent << "input_protocol," << endl << args_indent << "output_protocol," << endl << args_indent << "error);" << endl; scope_down(f_service_); f_service_ << indent() << "else" << endl; scope_up(f_service_); // Method name not recognized; chain up to our parent processor---note the // top-most implementation of this method, in ThriftDispatchProcessor itself, // will return an application exception to the caller if no class in the // hierarchy recognizes the method name f_service_ << indent() << "dispatch_result = parent_class->dispatch_call " "(dispatch_processor," << endl; args_indent = indent() + string(47, ' '); f_service_ << args_indent << "input_protocol," << endl << args_indent << "output_protocol," << endl << args_indent << "method_name," << endl << args_indent << "sequence_id," << endl << args_indent << "error);" << endl; scope_down(f_service_); f_service_ << endl << indent() << "return dispatch_result;" << endl; scope_down(f_service_); f_service_ << endl; // Generate the processor's property setter function_name = class_name_lc + "_set_property"; args_indent = string(function_name.length() + 2, ' '); f_service_ << "static void" << endl << function_name << " (GObject *object," << endl << args_indent << "guint property_id," << endl << args_indent << "const GValue *value," << endl << args_indent << "GParamSpec *pspec)" << endl; scope_up(f_service_); f_service_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl << endl << indent() << "switch (property_id)" << endl; scope_up(f_service_); f_service_ << indent() << "case PROP_" << class_name_uc << "_HANDLER:" << endl; indent_up(); f_service_ << indent() << "if (self->handler != NULL)" << endl; indent_up(); f_service_ << indent() << "g_object_unref (self->handler);" << endl; indent_down(); f_service_ << indent() << "self->handler = g_value_get_object (value);" << endl << indent() << "g_object_ref (self->handler);" << endl; if (extends_service) { // Chain up to set the handler in every superclass as well f_service_ << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)->" << endl; indent_up(); f_service_ << indent() << "set_property (object, property_id, value, pspec);" << endl; indent_down(); } f_service_ << indent() << "break;" << endl; indent_down(); f_service_ << indent() << "default:" << endl; indent_up(); f_service_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" << endl << indent() << "break;" << endl; indent_down(); scope_down(f_service_); scope_down(f_service_); f_service_ << endl; // Generate processor's property getter function_name = class_name_lc + "_get_property"; args_indent = string(function_name.length() + 2, ' '); f_service_ << "static void" << endl << function_name << " (GObject *object," << endl << args_indent << "guint property_id," << endl << args_indent << "GValue *value," << endl << args_indent << "GParamSpec *pspec)" << endl; scope_up(f_service_); f_service_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl << endl << indent() << "switch (property_id)" << endl; scope_up(f_service_); f_service_ << indent() << "case PROP_" << class_name_uc << "_HANDLER:" << endl; indent_up(); f_service_ << indent() << "g_value_set_object (value, self->handler);" << endl << indent() << "break;" << endl; indent_down(); f_service_ << indent() << "default:" << endl; indent_up(); f_service_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" << endl << indent() << "break;" << endl; indent_down(); scope_down(f_service_); scope_down(f_service_); f_service_ << endl; // Generator the processor's dispose function f_service_ << "static void" << endl << class_name_lc << "_dispose (GObject *gobject)" << endl; scope_up(f_service_); f_service_ << indent() << class_name << " *self = " << class_name_uc << " (gobject);" << endl << endl << indent() << "if (self->handler != NULL)" << endl; scope_up(f_service_); f_service_ << indent() << "g_object_unref (self->handler);" << endl << indent() << "self->handler = NULL;" << endl; scope_down(f_service_); f_service_ << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)" "->dispose (gobject);" << endl; scope_down(f_service_); f_service_ << endl; // Generate processor finalize function f_service_ << "static void" << endl << class_name_lc << "_finalize (GObject *gobject)" << endl; scope_up(f_service_); f_service_ << indent() << this->nspace << service_name_ << "Processor *self = " << this->nspace_uc << service_name_uc << "_PROCESSOR (gobject);" << endl << endl << indent() << "thrift_safe_hash_table_destroy (self->process_map);" << endl << endl << indent() << "G_OBJECT_CLASS (" << class_name_lc << "_parent_class)" "->finalize (gobject);" << endl; scope_down(f_service_); f_service_ << endl; // Generate processor instance initializer f_service_ << "static void" << endl << class_name_lc << "_init (" << class_name << " *self)" << endl; scope_up(f_service_); if (functions.size() > 0) { f_service_ << indent() << "guint index;" << endl << endl; } f_service_ << indent() << "self->handler = NULL;" << endl << indent() << "self->process_map = " "g_hash_table_new (g_str_hash, g_str_equal);" << endl; if (functions.size() > 0) { args_indent = string(21, ' '); f_service_ << endl << indent() << "for (index = 0; index < " << functions.size() << "; index += 1)" << endl; indent_up(); f_service_ << indent() << "g_hash_table_insert (self->process_map," << endl << indent() << args_indent << class_name_lc << "_process_function_defs[index].name," << endl << indent() << args_indent << "&" << class_name_lc << "_process_function_defs[index]" << ");" << endl; indent_down(); } scope_down(f_service_); f_service_ << endl; // Generate processor class initializer f_service_ << "static void" << endl << class_name_lc << "_class_init (" << class_name << "Class *cls)" << endl; scope_up(f_service_); f_service_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl << indent() << "ThriftDispatchProcessorClass *dispatch_processor_class =" << endl; indent_up(); f_service_ << indent() << "THRIFT_DISPATCH_PROCESSOR_CLASS (cls);" << endl; indent_down(); f_service_ << indent() << "GParamSpec *param_spec;" << endl << endl << indent() << "gobject_class->dispose = " << class_name_lc << "_dispose;" << endl << indent() << "gobject_class->finalize = " << class_name_lc << "_finalize;" << endl << indent() << "gobject_class->set_property = " << class_name_lc << "_set_property;" << endl << indent() << "gobject_class->get_property = " << class_name_lc << "_get_property;" << endl << endl << indent() << "dispatch_processor_class->dispatch_call = " << class_name_lc << "_dispatch_call;" << endl << indent() << "cls->dispatch_call = " << class_name_lc << "_dispatch_call;" << endl << endl << indent() << "param_spec = g_param_spec_object (\"handler\"," << endl; args_indent = indent() + string(34, ' '); f_service_ << args_indent << "\"Service handler implementation\"," << endl << args_indent << "\"The service handler implementation \"" << endl << args_indent << "\"to which method calls are dispatched.\"," << endl << args_indent << this->nspace_uc + "TYPE_" + service_name_uc + "_HANDLER," << endl << args_indent << "G_PARAM_READWRITE);" << endl; f_service_ << indent() << "g_object_class_install_property (gobject_class," << endl; args_indent = indent() + string(33, ' '); f_service_ << args_indent << "PROP_" << class_name_uc << "_HANDLER," << endl << args_indent << "param_spec);" << endl; scope_down(f_service_); } /** * Generates C code that represents a Thrift service server. */ void t_c_glib_generator::generate_service_server(t_service* tservice) { (void)tservice; // Generate the service's handler class generate_service_handler(tservice); // Generate the service's processor class generate_service_processor(tservice); } /** * Generates C code to represent a THrift structure as a GObject. */ void t_c_glib_generator::generate_object(t_struct* tstruct) { string name = tstruct->get_name(); string name_u = initial_caps_to_underscores(name); string name_uc = to_upper_case(name_u); string class_name = this->nspace + name; string class_name_lc = this->nspace_lc + initial_caps_to_underscores(name); string class_name_uc = to_upper_case(class_name_lc); string function_name; string args_indent; // write the instance definition f_types_ << "struct _" << this->nspace << name << endl << "{ " << endl << " ThriftStruct parent; " << endl << endl << " /* public */" << endl; // for each field, add a member variable vector::const_iterator m_iter; const vector& members = tstruct->get_members(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); f_types_ << " " << type_name(t) << " " << (*m_iter)->get_name() << ";" << endl; if ((*m_iter)->get_req() != t_field::T_REQUIRED) { f_types_ << " gboolean __isset_" << (*m_iter)->get_name() << ";" << endl; } } // close the structure definition and create a typedef f_types_ << "};" << endl << "typedef struct _" << this->nspace << name << " " << this->nspace << name << ";" << endl << endl; // write the class definition f_types_ << "struct _" << this->nspace << name << "Class" << endl << "{" << endl << " ThriftStructClass parent;" << endl << "};" << endl << "typedef struct _" << this->nspace << name << "Class " << this->nspace << name << "Class;" << endl << endl; // write the standard GObject boilerplate f_types_ << "GType " << this->nspace_lc << name_u << "_get_type (void);" << endl << "#define " << this->nspace_uc << "TYPE_" << name_uc << " (" << this->nspace_lc << name_u << "_get_type())" << endl << "#define " << this->nspace_uc << name_uc << "(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), " << this->nspace_uc << "TYPE_" << name_uc << ", " << this->nspace << name << "))" << endl << "#define " << this->nspace_uc << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), " << this->nspace_uc << "_TYPE_" << name_uc << ", " << this->nspace << name << "Class))" << endl << "#define " << this->nspace_uc << "IS_" << name_uc << "(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), " << this->nspace_uc << "TYPE_" << name_uc << "))" << endl << "#define " << this->nspace_uc << "IS_" << name_uc << "_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), " << this->nspace_uc << "TYPE_" << name_uc << "))" << endl << "#define " << this->nspace_uc << name_uc << "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), " << this->nspace_uc << "TYPE_" << name_uc << ", " << this->nspace << name << "Class))" << endl << endl; // start writing the object implementation .c file // generate properties enum if (members.size() > 0) { f_types_impl_ << "enum _" << class_name << "Properties" << endl << "{" << endl; indent_up(); f_types_impl_ << indent() << "PROP_" << class_name_uc << "_0"; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string member_name_uc = to_upper_case(to_lower_case(initial_caps_to_underscores((*m_iter)->get_name()))); f_types_impl_ << "," << endl << indent() << "PROP_" << class_name_uc << "_" << member_name_uc; } f_types_impl_ << endl; indent_down(); f_types_impl_ << "};" << endl << endl; } // generate struct I/O methods string this_get = this->nspace + name + " * this_object = " + this->nspace_uc + name_uc + "(object);"; generate_struct_reader(f_types_impl_, tstruct, "this_object->", this_get); generate_struct_writer(f_types_impl_, tstruct, "this_object->", this_get); // generate property setter and getter if (members.size() > 0) { // generate property setter function_name = class_name_lc + "_set_property"; args_indent = string(function_name.length() + 2, ' '); f_types_impl_ << "static void" << endl << function_name << " (GObject *object," << endl << args_indent << "guint property_id," << endl << args_indent << "const GValue *value," << endl << args_indent << "GParamSpec *pspec)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl << endl << indent() << "switch (property_id)" << endl; scope_up(f_types_impl_); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* member = (*m_iter); string member_name = member->get_name(); string member_name_uc = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name))); t_type* member_type = get_true_type(member->get_type()); string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc; f_types_impl_ << indent() << "case " << property_identifier + ":" << endl; indent_up(); if (member_type->is_base_type()) { t_base_type* base_type = ((t_base_type*)member_type); string assign_function_name; if (base_type->get_base() == t_base_type::TYPE_STRING) { string release_function_name; f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl; indent_up(); if (base_type->is_binary()) { release_function_name = "g_byte_array_unref"; assign_function_name = "g_value_dup_boxed"; } else { release_function_name = "g_free"; assign_function_name = "g_value_dup_string"; } f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");" << endl; indent_down(); } else { switch (base_type->get_base()) { case t_base_type::TYPE_BOOL: assign_function_name = "g_value_get_boolean"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: assign_function_name = "g_value_get_int"; break; case t_base_type::TYPE_I64: assign_function_name = "g_value_get_int64"; break; case t_base_type::TYPE_DOUBLE: assign_function_name = "g_value_get_double"; break; default: throw "compiler error: " "unrecognized base type \"" + base_type->get_name() + "\" " "for struct member \"" + member_name + "\""; break; } } f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name << " (value);" << endl; } else if (member_type->is_enum()) { f_types_impl_ << indent() << "self->" << member_name << " = g_value_get_int (value);" << endl; } else if (member_type->is_container()) { string release_function_name; string assign_function_name; if (member_type->is_list()) { t_type* elem_type = ((t_list*)member_type)->get_elem_type(); // Lists of base types other than strings are represented as GArrays; // all others as GPtrArrays if (is_numeric(elem_type)) { release_function_name = "g_array_unref"; } else { release_function_name = "g_ptr_array_unref"; } assign_function_name = "g_value_dup_boxed"; } else if (member_type->is_set() || member_type->is_map()) { release_function_name = "g_hash_table_unref"; assign_function_name = "g_value_dup_boxed"; } f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl; indent_up(); f_types_impl_ << indent() << release_function_name << " (self->" << member_name << ");" << endl; indent_down(); f_types_impl_ << indent() << "self->" << member_name << " = " << assign_function_name << " (value);" << endl; } else if (member_type->is_struct() || member_type->is_xception()) { f_types_impl_ << indent() << "if (self->" << member_name << " != NULL)" << endl; indent_up(); f_types_impl_ << indent() << "g_object_unref (self->" << member_name << ");" << endl; indent_down(); f_types_impl_ << indent() << "self->" << member_name << " = g_value_dup_object (value);" << endl; } if (member->get_req() != t_field::T_REQUIRED) { f_types_impl_ << indent() << "self->__isset_" << member_name << " = TRUE;" << endl; } f_types_impl_ << indent() << "break;" << endl << endl; indent_down(); } f_types_impl_ << indent() << "default:" << endl; indent_up(); f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" << endl << indent() << "break;" << endl; indent_down(); scope_down(f_types_impl_); scope_down(f_types_impl_); f_types_impl_ << endl; // generate property getter function_name = class_name_lc + "_get_property"; args_indent = string(function_name.length() + 2, ' '); f_types_impl_ << "static void" << endl << function_name << " (GObject *object," << endl << args_indent << "guint property_id," << endl << args_indent << "GValue *value," << endl << args_indent << "GParamSpec *pspec)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << class_name << " *self = " << class_name_uc << " (object);" << endl << endl << indent() << "switch (property_id)" << endl; scope_up(f_types_impl_); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* member = (*m_iter); string member_name = (*m_iter)->get_name(); string member_name_uc = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name))); t_type* member_type = get_true_type(member->get_type()); string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc; string setter_function_name; if (member_type->is_base_type()) { t_base_type* base_type = ((t_base_type*)member_type); switch (base_type->get_base()) { case t_base_type::TYPE_BOOL: setter_function_name = "g_value_set_boolean"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: setter_function_name = "g_value_set_int"; break; case t_base_type::TYPE_I64: setter_function_name = "g_value_set_int64"; break; case t_base_type::TYPE_DOUBLE: setter_function_name = "g_value_set_double"; break; case t_base_type::TYPE_STRING: if (base_type->is_binary()) { setter_function_name = "g_value_set_boxed"; } else { setter_function_name = "g_value_set_string"; } break; default: throw "compiler error: " "unrecognized base type \"" + base_type->get_name() + "\" " "for struct member \"" + member_name + "\""; break; } } else if (member_type->is_enum()) { setter_function_name = "g_value_set_int"; } else if (member_type->is_struct() || member_type->is_xception()) { setter_function_name = "g_value_set_object"; } else if (member_type->is_container()) { setter_function_name = "g_value_set_boxed"; } else { throw "compiler error: " "unrecognized type for struct member \"" + member_name + "\""; } f_types_impl_ << indent() << "case " << property_identifier + ":" << endl; indent_up(); f_types_impl_ << indent() << setter_function_name << " (value, self->" << member_name << ");" << endl << indent() << "break;" << endl << endl; indent_down(); } f_types_impl_ << indent() << "default:" << endl; indent_up(); f_types_impl_ << indent() << "G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);" << endl << indent() << "break;" << endl; indent_down(); scope_down(f_types_impl_); scope_down(f_types_impl_); f_types_impl_ << endl; } // generate the instance init function f_types_impl_ << "static void " << endl << this->nspace_lc << name_u << "_instance_init (" << this->nspace << name << " * object)" << endl << "{" << endl; indent_up(); // generate default-value structures for container-type members bool constant_declaration_output = false; bool string_list_constant_output = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* member = *m_iter; t_const_value* member_value = member->get_value(); if (member_value != nullptr) { string member_name = member->get_name(); t_type* member_type = get_true_type(member->get_type()); if (member_type->is_list()) { const vector& list = member_value->get_list(); t_type* elem_type = ((t_list*)member_type)->get_elem_type(); // Generate an array with the list literal indent(f_types_impl_) << "static " << type_name(elem_type, false, true) << " __default_" << member_name << "[" << list.size() << "] = " << endl; indent_up(); f_types_impl_ << indent() << constant_literal(member_type, member_value) << ";" << endl; indent_down(); constant_declaration_output = true; // If we are generating values for a pointer array (i.e. a list of // strings), set a flag so we know to also declare an index variable to // use in pre-populating the array if (elem_type->is_string()) { string_list_constant_output = true; } } // TODO: Handle container types other than list } } if (constant_declaration_output) { if (string_list_constant_output) { indent(f_types_impl_) << "unsigned int list_index;" << endl; } f_types_impl_ << endl; } // satisfy compilers with -Wall turned on indent(f_types_impl_) << "/* satisfy -Wall */" << endl << indent() << "THRIFT_UNUSED_VAR (object);" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* member_type = (*m_iter)->get_type(); t_type* t = get_true_type(member_type); if (t->is_base_type()) { string dval = " = "; if (t->is_enum()) { dval += "(" + type_name(t) + ")"; } t_const_value* cv = (*m_iter)->get_value(); if (cv != nullptr) { dval += constant_value("", t, cv); } else { dval += t->is_string() ? "NULL" : "0"; } indent(f_types_impl_) << "object->" << (*m_iter)->get_name() << dval << ";" << endl; } else if (t->is_struct()) { string name = (*m_iter)->get_name(); t_program* type_program = member_type->get_program(); string type_nspace = type_program ? type_program->get_namespace("c_glib") : ""; string type_nspace_prefix = type_nspace.empty() ? "" : initial_caps_to_underscores(type_nspace) + "_"; string type_name_uc = to_upper_case(initial_caps_to_underscores(member_type->get_name())); indent(f_types_impl_) << "object->" << name << " = g_object_new (" << to_upper_case(type_nspace_prefix) << "TYPE_" << type_name_uc << ", NULL);" << endl; } else if (t->is_xception()) { string name = (*m_iter)->get_name(); indent(f_types_impl_) << "object->" << name << " = NULL;" << endl; } else if (t->is_container()) { string name = (*m_iter)->get_name(); string init_function; t_type* etype = nullptr; if (t->is_map()) { t_type* key = ((t_map*)t)->get_key_type(); t_type* value = ((t_map*)t)->get_val_type(); init_function = generate_new_hash_from_type(key, value); } else if (t->is_set()) { etype = ((t_set*)t)->get_elem_type(); init_function = generate_new_hash_from_type(etype, nullptr); } else if (t->is_list()) { etype = ((t_list*)t)->get_elem_type(); init_function = generate_new_array_from_type(etype); } indent(f_types_impl_) << "object->" << name << " = " << init_function << endl; // Pre-populate the container with the specified default values, if any if ((*m_iter)->get_value()) { t_const_value* member_value = (*m_iter)->get_value(); if (t->is_list()) { const vector& list = member_value->get_list(); if (is_numeric(etype)) { indent(f_types_impl_) << "g_array_append_vals (object->" << name << ", &__default_" << name << ", " << list.size() << ");" << endl; } else { indent(f_types_impl_) << "for (list_index = 0; list_index < " << list.size() << "; " << "list_index += 1)" << endl; indent_up(); indent(f_types_impl_) << "g_ptr_array_add (object->" << name << "," << endl << indent() << string(17, ' ') << "g_strdup (__default_" << name << "[list_index]));" << endl; indent_down(); } } // TODO: Handle container types other than list } } /* if not required, initialize the __isset variable */ if ((*m_iter)->get_req() != t_field::T_REQUIRED) { indent(f_types_impl_) << "object->__isset_" << (*m_iter)->get_name() << " = FALSE;" << endl; } } indent_down(); f_types_impl_ << "}" << endl << endl; /* create the destructor */ f_types_impl_ << "static void " << endl << this->nspace_lc << name_u << "_finalize (GObject *object)" << endl << "{" << endl; indent_up(); f_types_impl_ << indent() << this->nspace << name << " *tobject = " << this->nspace_uc << name_uc << " (object);" << endl << endl; f_types_impl_ << indent() << "/* satisfy -Wall in case we don't use tobject */" << endl << indent() << "THRIFT_UNUSED_VAR (tobject);" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if (t->is_container()) { string name = (*m_iter)->get_name(); if (t->is_map() || t->is_set()) { f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; f_types_impl_ << indent() << "{" << endl; indent_up(); f_types_impl_ << indent() << "g_hash_table_destroy (tobject->" << name << ");" << endl; f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; indent_down(); f_types_impl_ << indent() << "}" << endl; } else if (t->is_list()) { t_type* etype = ((t_list*)t)->get_elem_type(); string destructor_function = "g_ptr_array_unref"; if (etype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)etype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot determine array type"; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: destructor_function = "g_array_unref"; break; case t_base_type::TYPE_STRING: break; default: throw "compiler error: no array info for type"; } } else if (etype->is_enum()) { destructor_function = "g_array_unref"; } f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; f_types_impl_ << indent() << "{" << endl; indent_up(); f_types_impl_ << indent() << destructor_function << " (tobject->" << name << ");" << endl; f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; indent_down(); f_types_impl_ << indent() << "}" << endl; } } else if (t->is_struct() || t->is_xception()) { string name = (*m_iter)->get_name(); // TODO: g_clear_object needs glib >= 2.28 // f_types_impl_ << indent() << "g_clear_object (&(tobject->" << name << "));" << endl; // does g_object_unref the trick? f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; f_types_impl_ << indent() << "{" << endl; indent_up(); f_types_impl_ << indent() << "g_object_unref(tobject->" << name << ");" << endl; f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; indent_down(); f_types_impl_ << indent() << "}" << endl; } else if (t->is_string()) { string name = (*m_iter)->get_name(); f_types_impl_ << indent() << "if (tobject->" << name << " != NULL)" << endl; f_types_impl_ << indent() << "{" << endl; indent_up(); f_types_impl_ << indent() << generate_free_func_from_type(t) << "(tobject->" << name << ");" << endl; f_types_impl_ << indent() << "tobject->" << name << " = NULL;" << endl; indent_down(); f_types_impl_ << indent() << "}" << endl; } } indent_down(); f_types_impl_ << "}" << endl << endl; // generate the class init function f_types_impl_ << "static void" << endl << class_name_lc << "_class_init (" << class_name << "Class * cls)" << endl; scope_up(f_types_impl_); f_types_impl_ << indent() << "GObjectClass *gobject_class = G_OBJECT_CLASS (cls);" << endl << indent() << "ThriftStructClass *struct_class = " << "THRIFT_STRUCT_CLASS (cls);" << endl << endl << indent() << "struct_class->read = " << class_name_lc << "_read;" << endl << indent() << "struct_class->write = " << class_name_lc << "_write;" << endl << endl << indent() << "gobject_class->finalize = " << class_name_lc << "_finalize;" << endl; if (members.size() > 0) { f_types_impl_ << indent() << "gobject_class->get_property = " << class_name_lc << "_get_property;" << endl << indent() << "gobject_class->set_property = " << class_name_lc << "_set_property;" << endl; // install a property for each member for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* member = (*m_iter); string member_name = member->get_name(); string member_name_uc = to_upper_case(to_lower_case(initial_caps_to_underscores(member_name))); t_type* member_type = get_true_type(member->get_type()); t_const_value* member_value = member->get_value(); string property_identifier = "PROP_" + class_name_uc + "_" + member_name_uc; f_types_impl_ << endl << indent() << "g_object_class_install_property" << endl; indent_up(); args_indent = indent() + ' '; f_types_impl_ << indent() << "(gobject_class," << endl << args_indent << property_identifier << "," << endl << args_indent; if (member_type->is_base_type()) { t_base_type::t_base base_type = ((t_base_type*)member_type)->get_base(); if (base_type == t_base_type::TYPE_STRING) { if (((t_base_type*)member_type)->is_binary()) { args_indent += string(20, ' '); f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << "G_TYPE_BYTE_ARRAY," << endl << args_indent << "G_PARAM_READWRITE));" << endl; } else { args_indent += string(21, ' '); f_types_impl_ << "g_param_spec_string (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << ((member_value != NULL) ? "\"" + member_value->get_string() + "\"" : "NULL") << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; } } else if (base_type == t_base_type::TYPE_BOOL) { args_indent += string(22, ' '); f_types_impl_ << "g_param_spec_boolean (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << (((member_value != NULL) && (member_value->get_integer() != 0)) ? "TRUE" : "FALSE") << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; } else if ((base_type == t_base_type::TYPE_I8) || (base_type == t_base_type::TYPE_I16) || (base_type == t_base_type::TYPE_I32) || (base_type == t_base_type::TYPE_I64) || (base_type == t_base_type::TYPE_DOUBLE)) { string param_spec_function_name = "g_param_spec_int"; string min_value; string max_value; ostringstream default_value; switch (base_type) { case t_base_type::TYPE_I8: min_value = "G_MININT8"; max_value = "G_MAXINT8"; break; case t_base_type::TYPE_I16: min_value = "G_MININT16"; max_value = "G_MAXINT16"; break; case t_base_type::TYPE_I32: min_value = "G_MININT32"; max_value = "G_MAXINT32"; break; case t_base_type::TYPE_I64: param_spec_function_name = "g_param_spec_int64"; min_value = "G_MININT64"; max_value = "G_MAXINT64"; break; case t_base_type::TYPE_DOUBLE: param_spec_function_name = "g_param_spec_double"; min_value = "-INFINITY"; max_value = "INFINITY"; break; default: throw "compiler error: " "unrecognized base type \"" + member_type->get_name() + "\" " "for struct member \"" + member_name + "\""; break; } if (member_value != nullptr) { default_value << (base_type == t_base_type::TYPE_DOUBLE ? member_value->get_double() : member_value->get_integer()); } else { default_value << "0"; } args_indent += string(param_spec_function_name.length() + 2, ' '); f_types_impl_ << param_spec_function_name << " (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << min_value << "," << endl << args_indent << max_value << "," << endl << args_indent << default_value.str() << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; } indent_down(); } else if (member_type->is_enum()) { t_enum_value* enum_min_value = ((t_enum*)member_type)->get_min_value(); t_enum_value* enum_max_value = ((t_enum*)member_type)->get_max_value(); int min_value = (enum_min_value != nullptr) ? enum_min_value->get_value() : 0; int max_value = (enum_max_value != nullptr) ? enum_max_value->get_value() : 0; args_indent += string(18, ' '); f_types_impl_ << "g_param_spec_int (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << min_value << "," << endl << args_indent << max_value << "," << endl << args_indent << min_value << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; indent_down(); } else if (member_type->is_struct() || member_type->is_xception()) { t_program* type_program = member_type->get_program(); string type_nspace = type_program ? type_program->get_namespace("c_glib") : ""; string type_nspace_prefix = type_nspace.empty() ? "" : initial_caps_to_underscores(type_nspace) + "_"; string param_type = to_upper_case(type_nspace_prefix) + "TYPE_" + to_upper_case(initial_caps_to_underscores(member_type->get_name())); args_indent += string(20, ' '); f_types_impl_ << "g_param_spec_object (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << param_type << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; indent_down(); } else if (member_type->is_list()) { t_type* elem_type = ((t_list*)member_type)->get_elem_type(); string param_type; if (elem_type->is_base_type() && !elem_type->is_string()) { param_type = "G_TYPE_ARRAY"; } else { param_type = "G_TYPE_PTR_ARRAY"; } args_indent += string(20, ' '); f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << param_type << "," << endl << args_indent << "G_PARAM_READWRITE));" << endl; indent_down(); } else if (member_type->is_set() || member_type->is_map()) { args_indent += string(20, ' '); f_types_impl_ << "g_param_spec_boxed (\"" << member_name << "\"," << endl << args_indent << "NULL," << endl << args_indent << "NULL," << endl << args_indent << "G_TYPE_HASH_TABLE," << endl << args_indent << "G_PARAM_READWRITE));" << endl; indent_down(); } } } scope_down(f_types_impl_); f_types_impl_ << endl; f_types_impl_ << "GType" << endl << this->nspace_lc << name_u << "_get_type (void)" << endl << "{" << endl << " static GType type = 0;" << endl << endl << " if (type == 0) " << endl << " {" << endl << " static const GTypeInfo type_info = " << endl << " {" << endl << " sizeof (" << this->nspace << name << "Class)," << endl << " NULL, /* base_init */" << endl << " NULL, /* base_finalize */" << endl << " (GClassInitFunc) " << this->nspace_lc << name_u << "_class_init," << endl << " NULL, /* class_finalize */" << endl << " NULL, /* class_data */" << endl << " sizeof (" << this->nspace << name << ")," << endl << " 0, /* n_preallocs */" << endl << " (GInstanceInitFunc) " << this->nspace_lc << name_u << "_instance_init," << endl << " NULL, /* value_table */" << endl << " };" << endl << endl << " type = g_type_register_static (THRIFT_TYPE_STRUCT, " << endl << " \"" << this->nspace << name << "Type\"," << endl << " &type_info, 0);" << endl << " }" << endl << endl << " return type;" << endl << "}" << endl << endl; } /** * Generates functions to write Thrift structures to a stream. */ void t_c_glib_generator::generate_struct_writer(ostream& out, t_struct* tstruct, string this_name, string this_get, bool is_function) { string name = tstruct->get_name(); string name_u = initial_caps_to_underscores(name); string name_uc = to_upper_case(name_u); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; int error_ret = 0; if (is_function) { error_ret = -1; indent(out) << "static gint32" << endl << this->nspace_lc << name_u << "_write (ThriftStruct *object, ThriftProtocol *protocol, GError **error)" << endl; } indent(out) << "{" << endl; indent_up(); out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << endl; indent(out) << this_get << endl; // satisfy -Wall in the case of an empty struct if (!this_get.empty()) { indent(out) << "THRIFT_UNUSED_VAR (this_object);" << endl; } out << indent() << "if ((ret = thrift_protocol_write_struct_begin (protocol, \"" << name << "\", error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_OPTIONAL) { indent(out) << "if (this_object->__isset_" << (*f_iter)->get_name() << " == TRUE) {" << endl; indent_up(); } out << indent() << "if ((ret = thrift_protocol_write_field_begin (protocol, " << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ", error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl; generate_serialize_field(out, *f_iter, this_name, "", error_ret); out << indent() << "if ((ret = thrift_protocol_write_field_end (protocol, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl; if ((*f_iter)->get_req() == t_field::T_OPTIONAL) { indent_down(); indent(out) << "}" << endl; } } // write the struct map out << indent() << "if ((ret = thrift_protocol_write_field_stop (protocol, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << indent() << "if ((ret = thrift_protocol_write_struct_end (protocol, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << endl; if (is_function) { indent(out) << "return xfer;" << endl; } indent_down(); indent(out) << "}" << endl << endl; } /** * Generates code to read Thrift structures from a stream. */ void t_c_glib_generator::generate_struct_reader(ostream& out, t_struct* tstruct, string this_name, string this_get, bool is_function) { string name = tstruct->get_name(); string name_u = initial_caps_to_underscores(name); string name_uc = to_upper_case(name_u); int error_ret = 0; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; if (is_function) { error_ret = -1; indent(out) << "/* reads a " << name_u << " object */" << endl << "static gint32" << endl << this->nspace_lc << name_u << "_read (ThriftStruct *object, ThriftProtocol *protocol, GError **error)" << endl; } indent(out) << "{" << endl; indent_up(); // declare stack temp variables out << indent() << "gint32 ret;" << endl << indent() << "gint32 xfer = 0;" << endl << indent() << "gchar *name = NULL;" << endl << indent() << "ThriftType ftype;" << endl << indent() << "gint16 fid;" << endl << indent() << "guint32 len = 0;" << endl << indent() << "gpointer data = NULL;" << endl << indent() << this_get << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { indent(out) << "gboolean isset_" << (*f_iter)->get_name() << " = FALSE;" << endl; } } out << endl; // satisfy -Wall in case we don't use some variables out << indent() << "/* satisfy -Wall in case these aren't used */" << endl << indent() << "THRIFT_UNUSED_VAR (len);" << endl << indent() << "THRIFT_UNUSED_VAR (data);" << endl; if (!this_get.empty()) { out << indent() << "THRIFT_UNUSED_VAR (this_object);" << endl; } out << endl; // read the beginning of the structure marker out << indent() << "/* read the struct begin marker */" << endl << indent() << "if ((ret = thrift_protocol_read_struct_begin (protocol, &name, error)) < 0)" << endl << indent() << "{" << endl << indent() << " if (name) g_free (name);" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "}" << endl << indent() << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << indent() << "name = NULL;" << endl << endl; // read the struct fields out << indent() << "/* read the struct fields */" << endl << indent() << "while (1)" << endl; scope_up(out); // read beginning field marker out << indent() << "/* read the beginning of a field */" << endl << indent() << "if ((ret = thrift_protocol_read_field_begin (protocol, &name, &ftype, &fid, error)) < 0)" << endl << indent() << "{" << endl << indent() << " if (name) g_free (name);" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "}" << endl << indent() << "xfer += ret;" << endl << indent() << "if (name) g_free (name);" << endl << indent() << "name = NULL;" << endl << endl; // check for field STOP marker out << indent() << "/* break if we get a STOP field */" << endl << indent() << "if (ftype == T_STOP)" << endl << indent() << "{" << endl << indent() << " break;" << endl << indent() << "}" << endl << endl; // switch depending on the field type indent(out) << "switch (fid)" << endl; // start switch scope_up(out); // generate deserialization code for known types for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ")" << endl; indent(out) << "{" << endl; indent_up(); // generate deserialize field generate_deserialize_field(out, *f_iter, this_name, "", error_ret, false); indent_down(); out << indent() << "} else {" << endl << indent() << " if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << " xfer += ret;" << endl << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } // create the default case out << indent() << "default:" << endl << indent() << " if ((ret = thrift_protocol_skip (protocol, ftype, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << " xfer += ret;" << endl << indent() << " break;" << endl; // end switch scope_down(out); // read field end marker out << indent() << "if ((ret = thrift_protocol_read_field_end (protocol, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl; // end while loop scope_down(out); out << endl; // read the end of the structure out << indent() << "if ((ret = thrift_protocol_read_struct_end (protocol, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << endl; // if a required field is missing, throw an error for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { out << indent() << "if (!isset_" << (*f_iter)->get_name() << ")" << endl << indent() << "{" << endl << indent() << " g_set_error (error, THRIFT_PROTOCOL_ERROR," << endl << indent() << " THRIFT_PROTOCOL_ERROR_INVALID_DATA," << endl << indent() << " \"missing field\");" << endl << indent() << " return -1;" << endl << indent() << "}" << endl << endl; } } if (is_function) { indent(out) << "return xfer;" << endl; } // end the function/structure indent_down(); indent(out) << "}" << endl << endl; } void t_c_glib_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, string suffix, int error_ret) { t_type* type = get_true_type(tfield->get_type()); string name = prefix + tfield->get_name() + suffix; if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, name, error_ret); } else if (type->is_container()) { generate_serialize_container(out, type, name, error_ret); } else if (type->is_base_type() || type->is_enum()) { indent(out) << "if ((ret = thrift_protocol_write_"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_BOOL: out << "bool (protocol, " << name; break; case t_base_type::TYPE_I8: out << "byte (protocol, " << name; break; case t_base_type::TYPE_I16: out << "i16 (protocol, " << name; break; case t_base_type::TYPE_I32: out << "i32 (protocol, " << name; break; case t_base_type::TYPE_I64: out << "i64 (protocol, " << name; break; case t_base_type::TYPE_DOUBLE: out << "double (protocol, " << name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "binary (protocol, " << name << " ? ((GByteArray *) " << name << ")->data : NULL, " << name << " ? ((GByteArray *) " << name << ")->len : 0"; } else { out << "string (protocol, " << name; } break; default: throw "compiler error: no C writer for base type " + t_base_type::t_base_name(tbase) + name; } } else { out << "i32 (protocol, (gint32) " << name; } out << ", error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << endl; } else { throw std::logic_error("DO NOT KNOW HOW TO SERIALIZE FIELD '" + name + "' TYPE '" + type_name(type)); } } void t_c_glib_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret) { (void)tstruct; out << indent() << "if ((ret = thrift_struct_write (THRIFT_STRUCT (" << prefix << "), protocol, error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << endl; } void t_c_glib_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix, int error_ret) { scope_up(out); if (ttype->is_map()) { t_type* tkey = ((t_map*)ttype)->get_key_type(); t_type* tval = ((t_map*)ttype)->get_val_type(); string tkey_name = type_name(tkey); string tval_name = type_name(tval); string tkey_ptr; string tval_ptr; string keyname = tmp("key"); string valname = tmp("val"); declore_local_variable_for_write(out, tkey, keyname); declore_local_variable_for_write(out, tval, valname); /* If either the key or value type is a typedef, find its underlying type so we can correctly determine how to generate a pointer to it */ tkey = get_true_type(tkey); tval = get_true_type(tval); tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*"; tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*"; /* * Some ugliness here. To maximize backwards compatibility, we * avoid using GHashTableIter and instead get a GList of all keys, * then copy it into a array on the stack, and free it. * This is because we may exit early before we get a chance to free the * GList. */ out << indent() << "GList *key_list = NULL, *iter = NULL;" << endl << indent() << tkey_name << tkey_ptr << "* keys;" << endl << indent() << "int i = 0, key_count;" << endl << endl << indent() << "if ((ret = thrift_protocol_write_map_begin (protocol, " << type_to_enum(tkey) << ", " << type_to_enum(tval) << ", " << prefix << " ? " << "(gint32) g_hash_table_size ((GHashTable *) " << prefix << ") : 0" << ", error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << indent() << "if (" << prefix << ")" << endl << indent() << " g_hash_table_foreach ((GHashTable *) " << prefix << ", thrift_hash_table_get_keys, &key_list);" << endl << indent() << "key_count = g_list_length (key_list);" << endl << indent() << "keys = g_newa (" << tkey_name << tkey_ptr << ", key_count);" << endl << indent() << "for (iter = g_list_first (key_list); iter; " "iter = iter->next)" << endl; indent_up(); out << indent() << "keys[i++] = (" << tkey_name << tkey_ptr << ") iter->data;" << endl; indent_down(); out << indent() << "g_list_free (key_list);" << endl << endl << indent() << "for (i = 0; i < key_count; ++i)" << endl; scope_up(out); out << indent() << keyname << " = keys[i];" << endl << indent() << valname << " = (" << tval_name << tval_ptr << ") g_hash_table_lookup (((GHashTable *) " << prefix << "), (gpointer) " << keyname << ");" << endl << endl; generate_serialize_map_element(out, (t_map*)ttype, tkey_ptr + " " + keyname, tval_ptr + " " + valname, error_ret); scope_down(out); out << indent() << "if ((ret = thrift_protocol_write_map_end (protocol, " "error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl; } else if (ttype->is_set()) { t_type* telem = ((t_set*)ttype)->get_elem_type(); string telem_name = type_name(telem); string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*"; out << indent() << "GList *key_list = NULL, *iter = NULL;" << endl << indent() << telem_name << telem_ptr << "* keys;" << endl << indent() << "int i = 0, key_count;" << endl << indent() << telem_name << telem_ptr << " elem;" << endl << indent() << "gpointer value;" << endl << indent() << "THRIFT_UNUSED_VAR (value);" << endl << endl << indent() << "if ((ret = thrift_protocol_write_set_begin (protocol, " << type_to_enum(telem) << ", " << prefix << " ? " << "(gint32) g_hash_table_size ((GHashTable *) " << prefix << ") : 0" << ", error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << indent() << "if (" << prefix << ")" << endl << indent() << " g_hash_table_foreach ((GHashTable *) " << prefix << ", thrift_hash_table_get_keys, &key_list);" << endl << indent() << "key_count = g_list_length (key_list);" << endl << indent() << "keys = g_newa (" << telem_name << telem_ptr << ", key_count);" << endl << indent() << "for (iter = g_list_first (key_list); iter; " "iter = iter->next)" << endl; indent_up(); out << indent() << "keys[i++] = (" << telem_name << telem_ptr << ") iter->data;" << endl; indent_down(); out << indent() << "g_list_free (key_list);" << endl << endl << indent() << "for (i = 0; i < key_count; ++i)" << endl; scope_up(out); out << indent() << "elem = keys[i];" << endl << indent() << "value = (gpointer) g_hash_table_lookup " "(((GHashTable *) " << prefix << "), (gpointer) elem);" << endl << endl; generate_serialize_set_element(out, (t_set*)ttype, telem_ptr + "elem", error_ret); scope_down(out); out << indent() << "if ((ret = thrift_protocol_write_set_end (protocol, " "error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl; } else if (ttype->is_list()) { string length = "(" + prefix + " ? " + prefix + "->len : 0)"; string i = tmp("i"); out << indent() << "guint " << i << ";" << endl << endl << indent() << "if ((ret = thrift_protocol_write_list_begin (protocol, " << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", (gint32) " << length << ", error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << indent() << "for (" << i << " = 0; " << i << " < " << length << "; " << i << "++)" << endl; scope_up(out); generate_serialize_list_element(out, (t_list*)ttype, prefix, i, error_ret); scope_down(out); out << indent() << "if ((ret = thrift_protocol_write_list_end (protocol, " "error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl; } scope_down(out); } void t_c_glib_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string key, string value, int error_ret) { t_field kfield(tmap->get_key_type(), key); generate_serialize_field(out, &kfield, "", "", error_ret); t_field vfield(tmap->get_val_type(), value); generate_serialize_field(out, &vfield, "", "", error_ret); } void t_c_glib_generator::generate_serialize_set_element(ostream& out, t_set* tset, string element, int error_ret) { t_field efield(tset->get_elem_type(), element); generate_serialize_field(out, &efield, "", "", error_ret); } void t_c_glib_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string list, string index, int error_ret) { t_type* ttype = get_true_type(tlist->get_elem_type()); // cast to non-const string cast = ""; string name = "g_ptr_array_index ((GPtrArray *) " + list + ", " + index + ")"; if (ttype->is_void()) { throw std::runtime_error("compiler error: list element type cannot be void"); } else if (is_numeric(ttype)) { name = "g_array_index (" + list + ", " + base_type_name(ttype) + ", " + index + ")"; } else if (ttype->is_string()) { cast = "(gchar*)"; } else if (ttype->is_map() || ttype->is_set()) { cast = "(GHashTable*)"; } else if (ttype->is_list()) { t_type* etype = ((t_list*)ttype)->get_elem_type(); if (etype->is_void()) { throw std::runtime_error("compiler error: list element type cannot be void"); } cast = is_numeric(etype) ? "(GArray*)" : "(GPtrArray*)"; } t_field efield(ttype, "(" + cast + name + ")"); generate_serialize_field(out, &efield, "", "", error_ret); } /* deserializes a field of any type. */ void t_c_glib_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, string suffix, int error_ret, bool allocate) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw std::runtime_error("CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name()); } string name = prefix + tfield->get_name() + suffix; if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name, error_ret, allocate); } else if (type->is_container()) { generate_deserialize_container(out, type, name, error_ret); } else if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); if (tbase == t_base_type::TYPE_STRING) { indent(out) << "if (" << name << " != NULL)" << endl << indent() << "{" << endl; indent_up(); indent(out) << "g_free(" << name << ");" << endl << indent() << name << " = NULL;" << endl; indent_down(); indent(out) << "}" << endl << endl; } indent(out) << "if ((ret = thrift_protocol_read_"; switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "binary (protocol, &data, &len"; } else { out << "string (protocol, &" << name; } break; case t_base_type::TYPE_BOOL: out << "bool (protocol, &" << name; break; case t_base_type::TYPE_I8: out << "byte (protocol, &" << name; break; case t_base_type::TYPE_I16: out << "i16 (protocol, &" << name; break; case t_base_type::TYPE_I32: out << "i32 (protocol, &" << name; break; case t_base_type::TYPE_I64: out << "i64 (protocol, &" << name; break; case t_base_type::TYPE_DOUBLE: out << "double (protocol, &" << name; break; default: throw "compiler error: no C reader for base type " + t_base_type::t_base_name(tbase) + name; } out << ", error)) < 0)" << endl; out << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl; // load the byte array with the data if (tbase == t_base_type::TYPE_STRING && type->is_binary()) { indent(out) << name << " = g_byte_array_new();" << endl; indent(out) << "g_byte_array_append (" << name << ", (guint8 *) data, (guint) len);" << endl; indent(out) << "g_free (data);" << endl; } } else if (type->is_enum()) { string t = tmp("ecast"); out << indent() << "gint32 " << t << ";" << endl << indent() << "if ((ret = thrift_protocol_read_i32 (protocol, &" << t << ", error)) < 0)" << endl << indent() << " return " << error_ret << ";" << endl << indent() << "xfer += ret;" << endl << indent() << name << " = (" << type_name(type) << ")" << t << ";" << endl; } else { throw std::logic_error("DO NOT KNOW HOW TO SERIALIZE FIELD '" + tfield->get_name() + "' TYPE '" + type_name(type)); } // if the type is not required and this is a thrift struct (no prefix), // set the isset variable. if the type is required, then set the // local variable indicating the value was set, so that we can do // validation later. if (prefix != "" && tfield->get_req() != t_field::T_REQUIRED) { indent(out) << prefix << "__isset_" << tfield->get_name() << suffix << " = TRUE;" << endl; } else if (prefix != "" && tfield->get_req() == t_field::T_REQUIRED) { indent(out) << "isset_" << tfield->get_name() << " = TRUE;" << endl; } } void t_c_glib_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix, int error_ret, bool allocate) { string name_uc = to_upper_case(initial_caps_to_underscores(tstruct->get_name())); if (tstruct->is_xception()) { out << indent() << "/* This struct is an exception */" << endl; allocate = true; } if (allocate) { out << indent() << "if ( " << prefix << " != NULL)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "g_object_unref (" << prefix << ");" << endl; indent_down(); out << indent() << "}" << endl << indent() << prefix << " = g_object_new (" << this->nspace_uc << "TYPE_" << name_uc << ", NULL);" << endl; } out << indent() << "if ((ret = thrift_struct_read (THRIFT_STRUCT (" << prefix << "), protocol, error)) < 0)" << endl << indent() << "{" << endl; indent_up(); if (allocate) { indent(out) << "g_object_unref (" << prefix << ");" << endl; if (tstruct->is_xception()) { indent(out) << prefix << " = NULL;" << endl; } } out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "}" << endl << indent() << "xfer += ret;" << endl; } void t_c_glib_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix, int error_ret) { scope_up(out); if (ttype->is_map()) { out << indent() << "guint32 size;" << endl << indent() << "guint32 i;" << endl << indent() << "ThriftType key_type;" << endl << indent() << "ThriftType value_type;" << endl << endl << indent() << "/* read the map begin marker */" << endl << indent() << "if ((ret = thrift_protocol_read_map_begin (protocol, " "&key_type, &value_type, &size, error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << endl; // iterate over map elements out << indent() << "/* iterate through each of the map's fields */" << endl << indent() << "for (i = 0; i < size; i++)" << endl; scope_up(out); generate_deserialize_map_element(out, (t_map*)ttype, prefix, error_ret); scope_down(out); out << endl; // read map end out << indent() << "/* read the map end marker */" << endl << indent() << "if ((ret = thrift_protocol_read_map_end (protocol, " "error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl; } else if (ttype->is_set()) { out << indent() << "guint32 size;" << endl << indent() << "guint32 i;" << endl << indent() << "ThriftType element_type;" << endl << endl << indent() << "if ((ret = thrift_protocol_read_set_begin (protocol, " "&element_type, &size, error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << endl; // iterate over the elements out << indent() << "/* iterate through the set elements */" << endl << indent() << "for (i = 0; i < size; ++i)" << endl; scope_up(out); generate_deserialize_set_element(out, (t_set*)ttype, prefix, error_ret); scope_down(out); // read set end out << indent() << "if ((ret = thrift_protocol_read_set_end (protocol, " "error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << endl; } else if (ttype->is_list()) { out << indent() << "guint32 size;" << endl << indent() << "guint32 i;" << endl << indent() << "ThriftType element_type;" << endl << endl << indent() << "if ((ret = thrift_protocol_read_list_begin (protocol, " "&element_type,&size, error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl << endl; // iterate over the elements out << indent() << "/* iterate through list elements */" << endl << indent() << "for (i = 0; i < size; i++)" << endl; scope_up(out); generate_deserialize_list_element(out, (t_list*)ttype, prefix, "i", error_ret); scope_down(out); // read list end out << indent() << "if ((ret = thrift_protocol_read_list_end (protocol, " "error)) < 0)" << endl; indent_up(); out << indent() << "return " << error_ret << ";" << endl; indent_down(); out << indent() << "xfer += ret;" << endl; } scope_down(out); } void t_c_glib_generator::declare_local_variable(ostream& out, t_type* ttype, string& name, bool for_hash_table) { string tname = type_name(ttype); /* If the given type is a typedef, find its underlying type so we can correctly determine how to generate a pointer to it */ ttype = get_true_type(ttype); string ptr = !is_numeric(ttype) ? "" : "*"; if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; out << indent() << tname << ptr << " " << name << " = " << generate_new_hash_from_type(tmap->get_key_type(), tmap->get_val_type()) << endl; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; out << indent() << tname << ptr << " " << name << " = " << generate_new_array_from_type(tlist->get_elem_type()) << endl; } else if (for_hash_table && ttype->is_enum()) { out << indent() << tname << " " << name << ";" << endl; } else { out << indent() << tname << ptr << " " << name << (ptr != "" ? " = g_new (" + tname + ", 1)" : " = NULL") << ";" << endl; } } void t_c_glib_generator::declore_local_variable_for_write(ostream& out, t_type* ttype, string& name) { string tname = type_name(ttype); ttype = get_true_type(ttype); string ptr = ttype->is_string() || !ttype->is_base_type() ? " " : "* "; string init_val = ttype->is_enum() ? "" : " = NULL"; out << indent() << tname << ptr << name << init_val << ";" << endl; } void t_c_glib_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix, int error_ret) { t_type* tkey = tmap->get_key_type(); t_type* tval = tmap->get_val_type(); string keyname = tmp("key"); string valname = tmp("val"); declare_local_variable(out, tkey, keyname, true); declare_local_variable(out, tval, valname, true); /* If either the key or value type is a typedef, find its underlying type so we can correctly determine how to generate a pointer to it */ tkey = get_true_type(tkey); tval = get_true_type(tval); string tkey_ptr = tkey->is_string() || !tkey->is_base_type() ? "" : "*"; string tval_ptr = tval->is_string() || !tval->is_base_type() ? "" : "*"; // deserialize the fields of the map element t_field fkey(tkey, tkey_ptr + keyname); generate_deserialize_field(out, &fkey, "", "", error_ret); t_field fval(tval, tval_ptr + valname); generate_deserialize_field(out, &fval, "", "", error_ret); indent(out) << "if (" << prefix << " && " << keyname << ")" << endl; indent_up(); indent(out) << "g_hash_table_insert ((GHashTable *)" << prefix << ", (gpointer) " << keyname << ", (gpointer) " << valname << ");" << endl; indent_down(); } void t_c_glib_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix, int error_ret) { t_type* telem = tset->get_elem_type(); string elem = tmp("_elem"); string telem_ptr = telem->is_string() || !telem->is_base_type() ? "" : "*"; declare_local_variable(out, telem, elem, true); t_field felem(telem, telem_ptr + elem); generate_deserialize_field(out, &felem, "", "", error_ret); indent(out) << "if (" << prefix << " && " << elem << ")" << endl; indent_up(); indent(out) << "g_hash_table_insert ((GHashTable *) " << prefix << ", (gpointer) " << elem << ", (gpointer) " << elem << ");" << endl; indent_down(); } void t_c_glib_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix, string index, int error_ret) { (void)index; t_type* ttype = get_true_type(tlist->get_elem_type()); string elem = tmp("_elem"); string telem_ptr = !is_numeric(ttype) ? "" : "*"; declare_local_variable(out, ttype, elem, false); t_field felem(ttype, telem_ptr + elem); generate_deserialize_field(out, &felem, "", "", error_ret); if (ttype->is_void()) { throw std::runtime_error("compiler error: list element type cannot be void"); } else if (is_numeric(ttype)) { indent(out) << "g_array_append_vals (" << prefix << ", " << elem << ", 1);" << endl; indent(out) << "g_free (" << elem << ");" << endl; } else { indent(out) << "g_ptr_array_add (" << prefix << ", " << elem << ");" << endl; } } string t_c_glib_generator::generate_free_func_from_type(t_type* ttype) { if (ttype == nullptr) return "NULL"; if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot determine hash type"; break; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: return "g_free"; case t_base_type::TYPE_STRING: if (((t_base_type*)ttype)->is_binary()) { return "thrift_string_free"; } return "g_free"; default: throw "compiler error: no hash table info for type"; } } else if (ttype->is_enum()) { return "NULL"; } else if (ttype->is_map() || ttype->is_set()) { return "(GDestroyNotify) thrift_safe_hash_table_destroy"; } else if (ttype->is_struct()) { return "g_object_unref"; } else if (ttype->is_list()) { t_type* etype = ((t_list*)ttype)->get_elem_type(); if (etype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)etype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot determine array type"; break; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: return "(GDestroyNotify) g_array_unref"; case t_base_type::TYPE_STRING: return "(GDestroyNotify) g_ptr_array_unref"; default: throw "compiler error: no array info for type"; } } else if (etype->is_container() || etype->is_struct()) { return "(GDestroyNotify) g_ptr_array_unref"; ; } else if (etype->is_enum()) { return "(GDestroyNotify) g_array_unref"; } printf("Type not expected inside the array: %s\n", etype->get_name().c_str()); throw "Type not expected inside array"; } else if (ttype->is_typedef()) { return generate_free_func_from_type(((t_typedef*)ttype)->get_type()); } printf("Type not expected: %s\n", ttype->get_name().c_str()); throw "Type not expected"; } string t_c_glib_generator::generate_hash_func_from_type(t_type* ttype) { if (ttype == nullptr) return "NULL"; if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot determine hash type"; break; case t_base_type::TYPE_BOOL: return "thrift_boolean_hash"; case t_base_type::TYPE_I8: return "thrift_int8_hash"; case t_base_type::TYPE_I16: return "thrift_int16_hash"; case t_base_type::TYPE_I32: return "g_int_hash"; case t_base_type::TYPE_I64: return "g_int64_hash"; case t_base_type::TYPE_DOUBLE: return "g_double_hash"; case t_base_type::TYPE_STRING: return "g_str_hash"; default: throw "compiler error: no hash table info for type"; } } else if (ttype->is_enum()) { return "g_direct_hash"; } else if (ttype->is_container() || ttype->is_struct()) { return "g_direct_hash"; } else if (ttype->is_typedef()) { return generate_hash_func_from_type(((t_typedef*)ttype)->get_type()); } printf("Type not expected: %s\n", ttype->get_name().c_str()); throw "Type not expected"; } string t_c_glib_generator::generate_cmp_func_from_type(t_type* ttype) { if (ttype == nullptr) return "NULL"; if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot determine hash type"; break; case t_base_type::TYPE_BOOL: return "thrift_boolean_equal"; case t_base_type::TYPE_I8: return "thrift_int8_equal"; case t_base_type::TYPE_I16: return "thrift_int16_equal"; case t_base_type::TYPE_I32: return "g_int_equal"; case t_base_type::TYPE_I64: return "g_int64_equal"; case t_base_type::TYPE_DOUBLE: return "g_double_equal"; case t_base_type::TYPE_STRING: return "g_str_equal"; default: throw "compiler error: no hash table info for type"; } } else if (ttype->is_enum()) { return "g_direct_equal"; } else if (ttype->is_container() || ttype->is_struct()) { return "g_direct_equal"; } else if (ttype->is_typedef()) { return generate_cmp_func_from_type(((t_typedef*)ttype)->get_type()); } printf("Type not expected: %s\n", ttype->get_name().c_str()); throw "Type not expected"; } string t_c_glib_generator::generate_new_hash_from_type(t_type* key, t_type* value) { string hash_func = generate_hash_func_from_type(key); string cmp_func = generate_cmp_func_from_type(key); string key_free_func = generate_free_func_from_type(key); string value_free_func = generate_free_func_from_type(value); return "g_hash_table_new_full (" + hash_func + ", " + cmp_func + ", " + key_free_func + ", " + value_free_func + ");"; } string t_c_glib_generator::generate_new_array_from_type(t_type* ttype) { if (ttype->is_void()) { throw std::runtime_error("compiler error: cannot determine array type"); } else if (is_numeric(ttype)) { return "g_array_new (0, 1, sizeof (" + base_type_name(ttype) + "));"; } else { string free_func = generate_free_func_from_type(ttype); return "g_ptr_array_new_with_free_func (" + free_func + ");"; } } /*************************************** * UTILITY FUNCTIONS * ***************************************/ /** * Upper case a string. */ string to_upper_case(string name) { string s(name); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; } /** * Lower case a string. */ string to_lower_case(string name) { string s(name); std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } /** * Makes a string friendly to C code standards by lowercasing and adding * underscores, with the exception of the first character. For example: * * Input: "ZomgCamelCase" * Output: "zomg_camel_case" */ string initial_caps_to_underscores(string name) { string ret; const char* tmp = name.c_str(); int pos = 0; /* the first character isn't underscored if uppercase, just lowercased */ ret += tolower(tmp[pos]); pos++; for (unsigned int i = pos; i < name.length(); i++) { char lc = tolower(tmp[i]); if (lc != tmp[i]) { ret += '_'; } ret += lc; } return ret; } /** * Performs the reverse operation of initial_caps_to_underscores: The first * character of the string is made uppercase, along with each character that * follows an underscore (which is removed). Useful for converting Thrift * service-method names into GObject-style class names. * * Input: "zomg_camel_case" * Output: "ZomgCamelCase" */ string underscores_to_initial_caps(string name) { string ret; const char* tmp = name.c_str(); bool uppercase_next = true; for (unsigned int i = 0; i < name.length(); i++) { char c = tmp[i]; if (c == '_') { uppercase_next = true; } else { if (uppercase_next) { ret += toupper(c); uppercase_next = false; } else { ret += c; } } } return ret; } /* register this generator with the main program */ std::string t_c_glib_generator::display_name() const { return "C, using GLib"; } THRIFT_REGISTER_GENERATOR(c_glib, "C, using GLib", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_go_generator.h0000644000000000000000000003056614452237057024546 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_GO_GENERATOR_H #define T_GO_GENERATOR_H #include #include #include #include #include #include #include "thrift/generate/t_generator.h" #include "thrift/platform.h" #include "thrift/version.h" #include #include #include #include #include #include using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes const string DEFAULT_THRIFT_IMPORT = "github.com/apache/thrift/lib/go/thrift"; static std::string package_flag; /** * Go code generator. */ class t_go_generator : public t_generator { public: t_go_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; gen_thrift_import_ = DEFAULT_THRIFT_IMPORT; gen_package_prefix_ = ""; package_flag = ""; read_write_private_ = false; ignore_initialisms_ = false; skip_remote_ = false; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if (iter->first.compare("package_prefix") == 0) { gen_package_prefix_ = (iter->second); } else if (iter->first.compare("thrift_import") == 0) { gen_thrift_import_ = (iter->second); } else if (iter->first.compare("package") == 0) { package_flag = (iter->second); } else if (iter->first.compare("read_write_private") == 0) { read_write_private_ = true; } else if (iter->first.compare("ignore_initialisms") == 0) { ignore_initialisms_ = true; } else if( iter->first.compare("skip_remote") == 0) { skip_remote_ = true; } else { throw "unknown option go:" + iter->first; } } out_dir_base_ = "gen-go"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value, const string& name, bool opt = false); /** * Struct generation code */ void generate_go_struct(t_struct* tstruct, bool is_exception); void generate_go_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool is_result = false, bool is_args = false); void generate_go_struct_initializer(std::ostream& out, t_struct* tstruct, bool is_args_or_result = false); void generate_isset_helpers(std::ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false); void generate_countsetfields_helper(std::ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false); void generate_go_struct_reader(std::ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false); void generate_go_struct_writer(std::ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result = false, bool uses_countsetfields = false); void generate_go_struct_equals(std::ostream& out, t_struct* tstruct, const string& tstruct_name); void generate_go_function_helpers(t_function* tfunction); void get_publicized_name_and_def_value(t_field* tfield, string* OUT_pub_name, t_const_value** OUT_def_value) const; /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_remote(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, bool declare, std::string prefix = "", bool inclass = false, bool coerceData = false, bool inkey = false, bool in_container = false); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, bool is_pointer_field, bool declare, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, bool pointer_field, bool declare, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, bool declare, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, bool declare, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, bool declare, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", bool inkey = false); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, bool pointer_field, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_go_equals(std::ostream& out, t_type* ttype, string tgt, string src); void generate_go_equals_struct(std::ostream& out, t_type* ttype, string tgt, string src); void generate_go_equals_container(std::ostream& out, t_type* ttype, string tgt, string src); void generate_go_docstring(std::ostream& out, t_struct* tstruct); void generate_go_docstring(std::ostream& out, t_function* tfunction); void generate_go_docstring(std::ostream& out, t_doc* tdoc, t_struct* tstruct, const char* subheader); void generate_go_docstring(std::ostream& out, t_doc* tdoc); void parse_go_tags(map* tags, const string in); /** * Helper rendering functions */ std::string go_autogen_comment(); std::string go_package(); std::string go_imports_begin(bool consts); std::string go_imports_end(); std::string render_includes(bool consts); std::string render_included_programs(string& unused_protection); std::string render_program_import(const t_program* program, string& unused_protection); std::string render_system_packages(std::vector& system_packages); std::string render_import_protection(); std::string render_fastbinary_includes(); std::string declare_argument(t_field* tfield); std::string render_field_initial_value(t_field* tfield, const string& name, bool optional_field); std::string type_name(t_type* ttype); std::string module_name(t_type* ttype); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string function_signature_if(t_function* tfunction, std::string prefix = "", bool addError = false); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string type_to_go_type(t_type* ttype); std::string type_to_go_type_with_opt(t_type* ttype, bool optional_field); std::string type_to_go_key_type(t_type* ttype); std::string type_to_spec_args(t_type* ttype); void indent_up() { t_generator::indent_up(); } void indent_down() { t_generator::indent_down(); } std::string indent() { return t_generator::indent(); } std::ostream& indent(std::ostream& os) { return t_generator::indent(os); } static std::string get_real_go_module(const t_program* program) { if (!package_flag.empty()) { return package_flag; } std::string real_module = program->get_namespace("go"); if (!real_module.empty()) { return real_module; } return lowercase(program->get_name()); } static bool is_pointer_field(t_field* tfield, bool in_container = false); private: std::string gen_package_prefix_; std::string gen_thrift_import_; bool read_write_private_; bool ignore_initialisms_; bool skip_remote_; /** * File streams */ ofstream_with_content_based_conditional_update f_types_; std::string f_types_name_; ofstream_with_content_based_conditional_update f_consts_; std::string f_consts_name_; std::stringstream f_const_values_; std::string package_name_; std::string package_dir_; std::unordered_map package_identifiers_; std::set package_identifiers_set_; std::string read_method_name_; std::string write_method_name_; std::string equals_method_name_; std::set commonInitialisms; std::string camelcase(const std::string& value) const; void fix_common_initialism(std::string& value, int i) const; std::string publicize(const std::string& value, bool is_args_or_result = false) const; std::string publicize(const std::string& value, bool is_args_or_result, const std::string& service_name) const; std::string privatize(const std::string& value) const; std::string new_prefix(const std::string& value) const; static std::string variable_name_to_go_name(const std::string& value); static bool omit_initialization(t_field* tfield); }; #endif thrift-0.19.0/compiler/cpp/src/thrift/generate/t_js_generator.cc0000644000000000000000000031452714452237057024715 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::unordered_map; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes static const string episode_file_name = "thrift.js.episode"; // largest consecutive integer representable by a double (2 ^ 53 - 1) static const int64_t max_safe_integer = 0x1fffffffffffff; // smallest consecutive number representable by a double (-2 ^ 53 + 1) static const int64_t min_safe_integer = -max_safe_integer; #include "thrift/generate/t_oop_generator.h" /** * JS code generator. */ class t_js_generator : public t_oop_generator { public: t_js_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; gen_node_ = false; gen_jquery_ = false; gen_ts_ = false; gen_es6_ = false; gen_episode_file_ = false; bool with_ns_ = false; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("node") == 0) { gen_node_ = true; } else if( iter->first.compare("jquery") == 0) { gen_jquery_ = true; } else if( iter->first.compare("ts") == 0) { gen_ts_ = true; } else if( iter->first.compare("with_ns") == 0) { with_ns_ = true; } else if( iter->first.compare("es6") == 0) { gen_es6_ = true; } else if( iter->first.compare("imports") == 0) { parse_imports(program, iter->second); } else if (iter->first.compare("thrift_package_output_directory") == 0) { parse_thrift_package_output_directory(iter->second); } else { throw std::invalid_argument("unknown option js:" + iter->first); } } if (gen_es6_ && gen_jquery_) { throw std::invalid_argument("invalid switch: [-gen js:es6,jquery] options not compatible"); } if (gen_node_ && gen_jquery_) { throw std::invalid_argument("invalid switch: [-gen js:node,jquery] options not compatible, try: [-gen js:node -gen " "js:jquery]"); } if (!gen_node_ && with_ns_) { throw std::invalid_argument("invalid switch: [-gen js:with_ns] is only valid when using node.js"); } // Depending on the processing flags, we will update these to be ES6 compatible js_const_type_ = "var "; js_let_type_ = "var "; js_var_type_ = "var "; if (gen_es6_) { js_const_type_ = "const "; js_let_type_ = "let "; } if (gen_node_) { out_dir_base_ = "gen-nodejs"; no_ns_ = !with_ns_; } else { out_dir_base_ = "gen-js"; no_ns_ = false; } escape_['\''] = "\\'"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_recv_throw(std::string var); std::string render_recv_return(std::string var); std::string render_const_value(t_type* type, t_const_value* value); /** * Structs! */ void generate_js_struct(t_struct* tstruct, bool is_exception); void generate_js_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool is_exported = true); void generate_js_struct_reader(std::ostream& out, t_struct* tstruct); void generate_js_struct_writer(std::ostream& out, t_struct* tstruct); void generate_js_function_helpers(t_function* tfunction); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_rest(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_processor(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", bool inclass = false); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); /** * Helper rendering functions */ std::string js_includes(); std::string ts_includes(); std::string ts_service_includes(); std::string render_includes(); std::string render_ts_includes(); std::string get_import_path(t_program* program); std::string declare_field(t_field* tfield, bool init = false, bool obj = false); std::string function_signature(t_function* tfunction, std::string prefix = "", bool include_callback = false); std::string argument_list(t_struct* tstruct, bool include_callback = false); std::string type_to_enum(t_type* ttype); std::string make_valid_nodeJs_identifier(std::string const& name); std::string next_identifier_name(std::vector const& fields, std::string const& base_name); bool find_field(std::vector const& fields, std::string const& name); /** * Helper parser functions */ void parse_imports(t_program* program, const std::string& imports_string); void parse_thrift_package_output_directory(const std::string& thrift_package_output_directory); std::string autogen_comment() override { return std::string("//\n") + "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "//\n"; } t_type* get_contained_type(t_type* t); std::vector js_namespace_pieces(t_program* p) { std::string ns = p->get_namespace("js"); std::string::size_type loc; std::vector pieces; if (no_ns_) { return pieces; } if (ns.size() > 0) { while ((loc = ns.find(".")) != std::string::npos) { pieces.push_back(ns.substr(0, loc)); ns = ns.substr(loc + 1); } } if (ns.size() > 0) { pieces.push_back(ns); } return pieces; } std::string js_type_namespace(t_program* p) { if (gen_node_) { if (p != nullptr && p != program_) { return make_valid_nodeJs_identifier(p->get_name()) + "_ttypes."; } return "ttypes."; } return js_namespace(p); } std::string js_export_namespace(t_program* p) { if (gen_node_) { return "exports."; } return js_namespace(p); } bool has_js_namespace(t_program* p) { if (no_ns_) { return false; } std::string ns = p->get_namespace("js"); return (ns.size() > 0); } std::string js_namespace(t_program* p) { if (no_ns_) { return ""; } std::string ns = p->get_namespace("js"); if (ns.size() > 0) { ns += "."; } return ns; } /** * TypeScript Definition File helper functions */ string ts_function_signature(t_function* tfunction, bool include_callback); string ts_get_type(t_type* type); /** * Special indentation for TypeScript Definitions because of the module. * Returns the normal indentation + " " if a module was defined. * @return string */ string ts_indent() { return indent() + (!ts_module_.empty() ? " " : ""); } /** * Returns "declare " if no module was defined. * @return string */ string ts_declare() { return (ts_module_.empty() ? (gen_node_ ? "declare " : "export declare ") : ""); } /** * Returns "?" if the given field is optional or has a default value. * @param t_field The field to check * @return string */ string ts_get_req(t_field* field) {return (field->get_req() == t_field::T_OPTIONAL || field->get_value() != nullptr ? "?" : ""); } /** * Returns the documentation, if the provided documentable object has one. * @param t_doc The object to get the documentation from * @return string The documentation */ string ts_print_doc(t_doc* tdoc) { string result = endl; if (tdoc->has_doc()) { std::stringstream doc(tdoc->get_doc()); string item; result += ts_indent() + "/**" + endl; while (std::getline(doc, item)) { result += ts_indent() + " * " + item + endl; } result += ts_indent() + " */" + endl; } return result; } private: /** * True if we should generate NodeJS-friendly RPC services. */ bool gen_node_; /** * True if we should generate services that use jQuery ajax (async/sync). */ bool gen_jquery_; /** * True if we should generate a TypeScript Definition File for each service. */ bool gen_ts_; /** * True if we should generate ES6 code, i.e. with Promises */ bool gen_es6_; /** * True if we will generate an episode file. */ bool gen_episode_file_; /** * The name of the defined module(s), for TypeScript Definition Files. */ string ts_module_; /** * True if we should not generate namespace objects for node. */ bool no_ns_; /** * The node modules to use when importing the previously generated files. */ vector imports; /** * Cache for imported modules. */ unordered_map module_name_2_import_path; /** * Cache for TypeScript includes to generated import name. */ unordered_map include_2_import_name; /** * The prefix to use when generating the episode file. */ string thrift_package_output_directory_; /** * The variable decorator for "const" variables. Will default to "var" if in an incompatible language. */ string js_const_type_; /** * The variable decorator for "let" variables. Will default to "var" if in an incompatible language. */ string js_let_type_; /** * The default variable decorator. Supports all javascript languages, but is not scoped to functions or closures. */ string js_var_type_; /** * File streams */ ofstream_with_content_based_conditional_update f_episode_; ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_service_; ofstream_with_content_based_conditional_update f_types_ts_; ofstream_with_content_based_conditional_update f_service_ts_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_js_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); const auto outdir = get_out_dir(); // Make output file(s) if (gen_episode_file_) { const auto f_episode_file_path = outdir + episode_file_name; f_episode_.open(f_episode_file_path); } const auto f_types_name = outdir + program_->get_name() + "_types.js"; f_types_.open(f_types_name.c_str()); if (gen_episode_file_) { const auto types_module = program_->get_name() + "_types"; f_episode_ << types_module << ":" << thrift_package_output_directory_ << "/" << types_module << endl; } if (gen_ts_) { const auto f_types_ts_name = outdir + program_->get_name() + "_types.d.ts"; f_types_ts_.open(f_types_ts_name.c_str()); } // Print header f_types_ << autogen_comment(); if ((gen_node_ || gen_es6_) && no_ns_) { f_types_ << "\"use strict\";" << endl << endl; } f_types_ << js_includes() << endl << render_includes() << endl; if (gen_ts_) { f_types_ts_ << autogen_comment() << ts_includes() << endl << render_ts_includes() << endl; } if (gen_node_) { f_types_ << js_const_type_ << "ttypes = module.exports = {};" << endl; } string pns; // setup the namespace // TODO should the namespace just be in the directory structure for node? vector ns_pieces = js_namespace_pieces(program_); if (ns_pieces.size() > 0) { for (size_t i = 0; i < ns_pieces.size(); ++i) { pns += ((i == 0) ? "" : ".") + ns_pieces[i]; f_types_ << "if (typeof " << pns << " === 'undefined') {" << endl; f_types_ << " " << pns << " = {};" << endl; f_types_ << "}" << endl; f_types_ << "" << "if (typeof module !== 'undefined' && module.exports) {" << endl; f_types_ << " module.exports." << pns << " = " << pns << ";" << endl << "}" << endl; } if (gen_ts_) { ts_module_ = pns; f_types_ts_ << "declare module " << ts_module_ << " {"; } } } /** * Prints standard js imports */ string t_js_generator::js_includes() { if (gen_node_) { string result = js_const_type_ + "thrift = require('thrift');\n" + js_const_type_ + "Thrift = thrift.Thrift;\n"; if (!gen_es6_) { result += js_const_type_ + "Q = thrift.Q;\n"; } result += js_const_type_ + "Int64 = require('node-int64');\n"; return result; } string result = "if (typeof Int64 === 'undefined' && typeof require === 'function') {\n " + js_const_type_ + "Int64 = require('node-int64');\n}\n"; return result; } /** * Prints standard ts imports */ string t_js_generator::ts_includes() { if (gen_node_) { return string( "import thrift = require('thrift');\n" "import Thrift = thrift.Thrift;\n" "import Q = thrift.Q;\n" "import Int64 = require('node-int64');"); } return string("import Int64 = require('node-int64');"); } /** * Prints service ts imports */ string t_js_generator::ts_service_includes() { if (gen_node_) { return string( "import thrift = require('thrift');\n" "import Thrift = thrift.Thrift;\n" "import Q = thrift.Q;\n" "import Int64 = require('node-int64');"); } return string("import Int64 = require('node-int64');"); } /** * Renders all the imports necessary for including another Thrift program */ string t_js_generator::render_includes() { string result = ""; if (gen_node_) { const vector& includes = program_->get_includes(); for (auto include : includes) { result += js_const_type_ + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('" + get_import_path(include) + "');\n"; } if (includes.size() > 0) { result += "\n"; } } return result; } /** * Renders all the imports necessary for including another Thrift program */ string t_js_generator::render_ts_includes() { string result; if (!gen_node_) { return result; } const vector& includes = program_->get_includes(); for (auto include : includes) { string include_name = make_valid_nodeJs_identifier(include->get_name()) + "_ttypes"; include_2_import_name.insert({include, include_name}); result += "import " + include_name + " = require('" + get_import_path(include) + "');\n"; } if (includes.size() > 0) { result += "\n"; } return result; } string t_js_generator::get_import_path(t_program* program) { const string import_file_name(program->get_name() + "_types"); if (program->get_recursive()) { return "./" + import_file_name; } const string import_file_name_with_extension = import_file_name + ".js"; auto module_name_and_import_path_iterator = module_name_2_import_path.find(import_file_name); if (module_name_and_import_path_iterator != module_name_2_import_path.end()) { return module_name_and_import_path_iterator->second; } return "./" + import_file_name; } /** * Close up (or down) some filez. */ void t_js_generator::close_generator() { // Close types file(s) f_types_.close(); if (gen_ts_) { if (!ts_module_.empty()) { f_types_ts_ << "}"; } f_types_ts_.close(); } if (gen_episode_file_){ f_episode_.close(); } } /** * Generates a typedef. This is not done in JS, types are all implicit. * * @param ttypedef The type definition */ void t_js_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Generates code for an enumerated type. Since define is expensive to lookup * in JS, we use a global array for this. * * @param tenum The enumeration */ void t_js_generator::generate_enum(t_enum* tenum) { f_types_ << js_type_namespace(tenum->get_program()) << tenum->get_name() << " = {" << endl; if (gen_ts_) { f_types_ts_ << ts_print_doc(tenum) << ts_indent() << ts_declare() << "enum " << tenum->get_name() << " {" << endl; } indent_up(); vector const& constants = tenum->get_constants(); vector::const_iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); if (gen_ts_) { f_types_ts_ << ts_indent() << (*c_iter)->get_name() << " = " << value << "," << endl; // add 'value: key' in addition to 'key: value' for TypeScript enums f_types_ << indent() << "'" << value << "' : '" << (*c_iter)->get_name() << "'," << endl; } f_types_ << indent() << "'" << (*c_iter)->get_name() << "' : " << value; if (c_iter != constants.end() - 1) { f_types_ << ","; } f_types_ << endl; } indent_down(); f_types_ << "};" << endl; if (gen_ts_) { f_types_ts_ << ts_indent() << "}" << endl; } } /** * Generate a constant value */ void t_js_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); f_types_ << js_type_namespace(program_) << name << " = "; f_types_ << render_const_value(type, value) << ";" << endl; if (gen_ts_) { f_types_ts_ << ts_print_doc(tconst) << ts_indent() << ts_declare() << js_const_type_ << name << ": " << ts_get_type(type) << ";" << endl; } } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { std::ostringstream out; type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << "'" << get_escaped_string(value) << "'"; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: out << value->get_integer(); break; case t_base_type::TYPE_I64: { int64_t const& integer_value = value->get_integer(); if (integer_value <= max_safe_integer && integer_value >= min_safe_integer) { out << "new Int64(" << integer_value << ")"; } else { out << "new Int64('" << std::hex << integer_value << std::dec << "')"; } } break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << emit_double_as_string(value->get_double()); } break; default: throw std::runtime_error("compiler error: no const of base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { out << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << "new " << js_type_namespace(type->get_program()) << type->get_name() << "({"; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw std::runtime_error("type error: " + type->get_name() + " has no field " + v_iter->first->get_string()); } if (v_iter != val.begin()) out << ","; out << endl << indent() << render_const_value(g_type_string, v_iter->first); out << " : "; out << render_const_value(field_type, v_iter->second); } indent_down(); out << endl << indent() << "})"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); out << "{" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter != val.begin()) out << "," << endl; if (ktype->is_base_type() && ((t_base_type*)get_true_type(ktype))->get_base() == t_base_type::TYPE_I64){ out << indent() << "\"" << v_iter->first->get_integer() << "\""; } else { out << indent() << render_const_value(ktype, v_iter->first); } out << " : "; out << render_const_value(vtype, v_iter->second); } indent_down(); out << endl << indent() << "}"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } out << "["; const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter != val.begin()) out << ","; out << render_const_value(etype, *v_iter); } out << "]"; } return out.str(); } /** * Make a struct */ void t_js_generator::generate_struct(t_struct* tstruct) { generate_js_struct(tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_js_generator::generate_xception(t_struct* txception) { generate_js_struct(txception, true); } /** * Structs can be normal or exceptions. */ void t_js_generator::generate_js_struct(t_struct* tstruct, bool is_exception) { generate_js_struct_definition(f_types_, tstruct, is_exception); } /** * Return type of contained elements for a container type. For maps * this is type of value (keys are always strings in js) */ t_type* t_js_generator::get_contained_type(t_type* t) { t_type* etype; if (t->is_list()) { etype = ((t_list*)t)->get_elem_type(); } else if (t->is_set()) { etype = ((t_set*)t)->get_elem_type(); } else { etype = ((t_map*)t)->get_val_type(); } return etype; } /** * Generates a struct definition for a thrift data type. This is nothing in JS * where the objects are all just associative arrays (unless of course we * decide to start using objects for them...) * * @param tstruct The struct definition */ void t_js_generator::generate_js_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool is_exported) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; if (gen_node_) { string prefix = has_js_namespace(tstruct->get_program()) ? js_namespace(tstruct->get_program()) : js_const_type_; out << prefix << tstruct->get_name() << (is_exported ? " = module.exports." + tstruct->get_name() : ""); if (gen_ts_) { f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class " << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "") << " {" << endl; } } else { out << js_namespace(tstruct->get_program()) << tstruct->get_name(); if (gen_ts_) { f_types_ts_ << ts_print_doc(tstruct) << ts_indent() << ts_declare() << "class " << tstruct->get_name() << (is_exception ? " extends Thrift.TException" : "") << " {" << endl; } } if (gen_es6_) { if (gen_node_ && is_exception) { out << " = class extends Thrift.TException {" << endl; } else { out << " = class {" << endl; } indent_up(); indent(out) << "constructor(args) {" << endl; } else { out << " = function(args) {" << endl; } indent_up(); // Call super() method on inherited Error class if (gen_node_ && is_exception) { if (gen_es6_) { indent(out) << "super(args);" << endl; } else { indent(out) << "Thrift.TException.call(this, \"" << js_namespace(tstruct->get_program()) << tstruct->get_name() << "\");" << endl; } out << indent() << "this.name = \"" << js_namespace(tstruct->get_program()) << tstruct->get_name() << "\";" << endl; } // members with arguments for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string dval = declare_field(*m_iter, false, true); t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr && !(t->is_struct() || t->is_xception())) { dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value()); out << indent() << "this." << (*m_iter)->get_name() << " = " << dval << ";" << endl; } else { out << indent() << dval << ";" << endl; } if (gen_ts_) { string ts_access = gen_node_ ? "public " : ""; string member_name = (*m_iter)->get_name(); // Special case. Exceptions derive from Error, and error has a non optional message field. // Ignore the optional flag in this case, otherwise we will generate a incompatible field // in the eyes of typescript. string optional_flag = is_exception && member_name == "message" ? "" : ts_get_req(*m_iter); f_types_ts_ << ts_indent() << ts_access << member_name << optional_flag << ": " << ts_get_type((*m_iter)->get_type()) << ";" << endl; } } // Generate constructor from array if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr && (t->is_struct() || t->is_xception())) { indent(out) << "this." << (*m_iter)->get_name() << " = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl; } } // Early returns for exceptions for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if (t->is_xception()) { out << indent() << "if (args instanceof " << js_type_namespace(t->get_program()) << t->get_name() << ") {" << endl << indent() << indent() << "this." << (*m_iter)->get_name() << " = args;" << endl << indent() << indent() << "return;" << endl << indent() << "}" << endl; } } indent(out) << "if (args) {" << endl; indent_up(); if (gen_ts_) { f_types_ts_ << endl << ts_indent() << "constructor(args?: { "; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); indent(out) << "if (args." << (*m_iter)->get_name() << " !== undefined && args." << (*m_iter)->get_name() << " !== null) {" << endl; indent_up(); indent(out) << "this." << (*m_iter)->get_name(); if (t->is_struct()) { out << (" = new " + js_type_namespace(t->get_program()) + t->get_name() + "(args."+(*m_iter)->get_name() +");"); out << endl; } else if (t->is_container()) { t_type* etype = get_contained_type(t); string copyFunc = t->is_map() ? "Thrift.copyMap" : "Thrift.copyList"; string type_list = ""; while (etype->is_container()) { if (type_list.length() > 0) { type_list += ", "; } type_list += etype->is_map() ? "Thrift.copyMap" : "Thrift.copyList"; etype = get_contained_type(etype); } if (etype->is_struct()) { if (type_list.length() > 0) { type_list += ", "; } type_list += js_type_namespace(etype->get_program()) + etype->get_name(); } else { if (type_list.length() > 0) { type_list += ", "; } type_list += "null"; } out << (" = " + copyFunc + "(args." + (*m_iter)->get_name() + ", [" + type_list + "]);"); out << endl; } else { out << " = args." << (*m_iter)->get_name() << ";" << endl; } indent_down(); if (!(*m_iter)->get_req()) { indent(out) << "} else {" << endl; indent(out) << " throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.UNKNOWN, " "'Required field " << (*m_iter)->get_name() << " is unset!');" << endl; } indent(out) << "}" << endl; if (gen_ts_) { f_types_ts_ << (*m_iter)->get_name() << ts_get_req(*m_iter) << ": " << ts_get_type((*m_iter)->get_type()) << "; "; } } indent_down(); out << indent() << "}" << endl; if (gen_ts_) { f_types_ts_ << "});" << endl; } } // Done with constructor indent_down(); if (gen_es6_) { indent(out) << "}" << endl << endl; } else { indent(out) << "};" << endl; } if (gen_ts_) { f_types_ts_ << ts_indent() << "}" << endl; } if (!gen_es6_) { if (is_exception) { out << "Thrift.inherits(" << js_namespace(tstruct->get_program()) << tstruct->get_name() << ", Thrift.TException);" << endl; out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.name = '" << tstruct->get_name() << "';" << endl; } else { // init prototype manually if we aren't using es6 out << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype = {};" << endl; } } generate_js_struct_reader(out, tstruct); generate_js_struct_writer(out, tstruct); // Close out the class definition if (gen_es6_) { indent_down(); indent(out) << "};" << endl; } } /** * Generates the read() method for a struct */ void t_js_generator::generate_js_struct_reader(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; if (gen_es6_) { indent(out) << "read (input) {" << endl; } else { indent(out) << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.read = function(input) {" << endl; } indent_up(); indent(out) << "input.readStructBegin();" << endl; // Loop over reading in fields indent(out) << "while (true) {" << endl; indent_up(); indent(out) << js_const_type_ << "ret = input.readFieldBegin();" << endl; indent(out) << js_const_type_ << "ftype = ret.ftype;" << endl; if (!fields.empty()) { indent(out) << js_const_type_ << "fid = ret.fid;" << endl; } // Check for field STOP marker and break indent(out) << "if (ftype == Thrift.Type.STOP) {" << endl; indent_up(); indent(out) << "break;" << endl; indent_down(); indent(out) << "}" << endl; if (!fields.empty()) { // Switch statement on the field we are reading indent(out) << "switch (fid) {" << endl; indent_up(); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, "this."); indent_down(); indent(out) << "} else {" << endl; indent(out) << " input.skip(ftype);" << endl; out << indent() << "}" << endl << indent() << "break;" << endl; } if (fields.size() == 1) { // pseudo case to make jslint happy indent(out) << "case 0:" << endl; indent(out) << " input.skip(ftype);" << endl; indent(out) << " break;" << endl; } // In the default case we skip the field indent(out) << "default:" << endl; indent(out) << " input.skip(ftype);" << endl; scope_down(out); } else { indent(out) << "input.skip(ftype);" << endl; } indent(out) << "input.readFieldEnd();" << endl; scope_down(out); indent(out) << "input.readStructEnd();" << endl; indent(out) << "return;" << endl; indent_down(); if (gen_es6_) { indent(out) << "}" << endl << endl; } else { indent(out) << "};" << endl << endl; } } /** * Generates the write() method for a struct */ void t_js_generator::generate_js_struct_writer(ostream& out, t_struct* tstruct) { string name = tstruct->get_name(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; if (gen_es6_) { indent(out) << "write (output) {" << endl; } else { indent(out) << js_namespace(tstruct->get_program()) << tstruct->get_name() << ".prototype.write = function(output) {" << endl; } indent_up(); indent(out) << "output.writeStructBegin('" << name << "');" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << indent() << "if (this." << (*f_iter)->get_name() << " !== null && this." << (*f_iter)->get_name() << " !== undefined) {" << endl; indent_up(); indent(out) << "output.writeFieldBegin(" << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ");" << endl; // Write field contents generate_serialize_field(out, *f_iter, "this."); indent(out) << "output.writeFieldEnd();" << endl; indent_down(); indent(out) << "}" << endl; } out << indent() << "output.writeFieldStop();" << endl << indent() << "output.writeStructEnd();" << endl; out << indent() << "return;" << endl; indent_down(); if (gen_es6_) { out << indent() << "}" << endl << endl; } else { out << indent() << "};" << endl << endl; } } /** * Generates a thrift service. * * @param tservice The service definition */ void t_js_generator::generate_service(t_service* tservice) { string f_service_name = get_out_dir() + service_name_ + ".js"; f_service_.open(f_service_name.c_str()); if (gen_episode_file_) { f_episode_ << service_name_ << ":" << thrift_package_output_directory_ << "/" << service_name_ << endl; } if (gen_ts_) { string f_service_ts_name = get_out_dir() + service_name_ + ".d.ts"; f_service_ts_.open(f_service_ts_name.c_str()); } f_service_ << autogen_comment(); if ((gen_node_ || gen_es6_) && no_ns_) { f_service_ << "\"use strict\";" << endl << endl; } f_service_ << js_includes() << endl << render_includes() << endl; if (gen_ts_) { if (tservice->get_extends() != nullptr) { f_service_ts_ << "/// get_extends()->get_name() << ".d.ts\" />" << endl; } f_service_ts_ << autogen_comment() << endl << ts_includes() << endl << render_ts_includes() << endl; if (gen_node_) { f_service_ts_ << "import ttypes = require('./" + program_->get_name() + "_types');" << endl; // Generate type aliases // enum vector const& enums = program_->get_enums(); vector::const_iterator e_iter; for (e_iter = enums.begin(); e_iter != enums.end(); ++e_iter) { f_service_ts_ << "import " << (*e_iter)->get_name() << " = ttypes." << js_namespace(program_) << (*e_iter)->get_name() << endl; } // const vector const& consts = program_->get_consts(); vector::const_iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { f_service_ts_ << "import " << (*c_iter)->get_name() << " = ttypes." << js_namespace(program_) << (*c_iter)->get_name() << endl; } // exception vector const& exceptions = program_->get_xceptions(); vector::const_iterator x_iter; for (x_iter = exceptions.begin(); x_iter != exceptions.end(); ++x_iter) { f_service_ts_ << "import " << (*x_iter)->get_name() << " = ttypes." << js_namespace(program_) << (*x_iter)->get_name() << endl; } // structs vector const& structs = program_->get_structs(); vector::const_iterator s_iter; for (s_iter = structs.begin(); s_iter != structs.end(); ++s_iter) { f_service_ts_ << "import " << (*s_iter)->get_name() << " = ttypes." << js_namespace(program_) << (*s_iter)->get_name() << endl; } } else { f_service_ts_ << "import { " << program_->get_name() << " } from \"./" << program_->get_name() << "_types\";" << endl << endl; } if (!ts_module_.empty()) { if (gen_node_) { f_service_ts_ << "declare module " << ts_module_ << " {"; } else { f_service_ts_ << "declare module \"./" << program_->get_name() << "_types\" {" << endl; indent_up(); f_service_ts_ << ts_indent() << "module " << program_->get_name() << " {" << endl; indent_up(); } } } if (gen_node_) { if (tservice->get_extends() != nullptr) { f_service_ << js_const_type_ << tservice->get_extends()->get_name() << " = require('./" << tservice->get_extends()->get_name() << "');" << endl << js_const_type_ << tservice->get_extends()->get_name() << "Client = " << tservice->get_extends()->get_name() << ".Client;" << endl << js_const_type_ << tservice->get_extends()->get_name() << "Processor = " << tservice->get_extends()->get_name() << ".Processor;" << endl; f_service_ts_ << "import " << tservice->get_extends()->get_name() << " = require('./" << tservice->get_extends()->get_name() << "');" << endl; } f_service_ << js_const_type_ << "ttypes = require('./" + program_->get_name() + "_types');" << endl; } generate_service_helpers(tservice); generate_service_interface(tservice); generate_service_client(tservice); if (gen_node_) { generate_service_processor(tservice); } f_service_.close(); if (gen_ts_) { if (!ts_module_.empty()) { if (gen_node_) { f_service_ts_ << "}" << endl; } else { indent_down(); f_service_ts_ << ts_indent() << "}" << endl; f_service_ts_ << "}" << endl; } } f_service_ts_.close(); } } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_js_generator::generate_service_processor(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; if (gen_node_) { string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : js_const_type_; f_service_ << prefix << service_name_ << "Processor = " << "exports.Processor"; if (gen_ts_) { f_service_ts_ << endl << "declare class Processor "; if (tservice->get_extends() != nullptr) { f_service_ts_ << "extends " << tservice->get_extends()->get_name() << ".Processor "; } f_service_ts_ << "{" << endl; indent_up(); if(tservice->get_extends() == nullptr) { f_service_ts_ << ts_indent() << "private _handler: object;" << endl << endl; } f_service_ts_ << ts_indent() << "constructor(handler: object);" << endl; f_service_ts_ << ts_indent() << "process(input: thrift.TProtocol, output: thrift.TProtocol): void;" << endl; indent_down(); } } else { f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Processor = " << "exports.Processor"; } bool is_subclass_service = tservice->get_extends() != nullptr; // ES6 Constructor if (gen_es6_) { if (is_subclass_service) { f_service_ << " = class " << service_name_ << "Processor extends " << tservice->get_extends()->get_name() << "Processor {" << endl; } else { f_service_ << " = class " << service_name_ << "Processor {" << endl; } indent_up(); indent(f_service_) << "constructor(handler) {" << endl; } else { f_service_ << " = function(handler) {" << endl; } indent_up(); if (gen_es6_ && is_subclass_service) { indent(f_service_) << "super(handler);" << endl; } indent(f_service_) << "this._handler = handler;" << endl; indent_down(); // Done with constructor if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; } // ES5 service inheritance if (!gen_es6_ && is_subclass_service) { indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program()) << service_name_ << "Processor, " << tservice->get_extends()->get_name() << "Processor);" << endl; } // Generate the server implementation if (gen_es6_) { indent(f_service_) << "process (input, output) {" << endl; } else { indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Processor.prototype.process = function(input, output) {" << endl; } indent_up(); indent(f_service_) << js_const_type_ << "r = input.readMessageBegin();" << endl << indent() << "if (this['process_' + r.fname]) {" << endl << indent() << " return this['process_' + r.fname].call(this, r.rseqid, input, output);" << endl << indent() << "} else {" << endl << indent() << " input.skip(Thrift.Type.STRUCT);" << endl << indent() << " input.readMessageEnd();" << endl << indent() << " " << js_const_type_ << "x = new " "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN_METHOD, " "'Unknown function ' + r.fname);" << endl << indent() << " output.writeMessageBegin(r.fname, Thrift.MessageType.EXCEPTION, r.rseqid);" << endl << indent() << " x.write(output);" << endl << indent() << " output.writeMessageEnd();" << endl << indent() << " output.flush();" << endl << indent() << "}" << endl; indent_down(); if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; } // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } // Close off the processor class definition if (gen_es6_) { indent_down(); indent(f_service_) << "};" << endl; } if (gen_node_ && gen_ts_) { f_service_ts_ << "}" << endl; } } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_js_generator::generate_process_function(t_service* tservice, t_function* tfunction) { if (gen_es6_) { indent(f_service_) << "process_" + tfunction->get_name() + " (seqid, input, output) {" << endl; } else { indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Processor.prototype.process_" + tfunction->get_name() + " = function(seqid, input, output) {" << endl; } if (gen_ts_) { indent_up(); f_service_ts_ << ts_indent() << "process_" << tfunction->get_name() << "(seqid: number, input: thrift.TProtocol, output: thrift.TProtocol): void;" << endl; indent_down(); } indent_up(); string argsname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name() + "_args"; string resultname = js_namespace(program_) + service_name_ + "_" + tfunction->get_name() + "_result"; indent(f_service_) << js_const_type_ << "args = new " << argsname << "();" << endl << indent() << "args.read(input);" << endl << indent() << "input.readMessageEnd();" << endl; // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; // Shortcut out here for oneway functions if (tfunction->is_oneway()) { indent(f_service_) << "this._handler." << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << ");" << endl; indent_down(); if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; } return; } // Promise style invocation indent(f_service_) << "if (this._handler." << tfunction->get_name() << ".length === " << fields.size() << ") {" << endl; indent_up(); if (gen_es6_) { indent(f_service_) << "new Promise((resolve) => resolve(this._handler." << tfunction->get_name() << ".bind(this._handler)(" << endl; } else { string maybeComma = (fields.size() > 0 ? "," : ""); indent(f_service_) << "Q.fcall(this._handler." << tfunction->get_name() << ".bind(this._handler)" << maybeComma << endl; } indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string maybeComma = (f_iter != fields.end() - 1 ? "," : ""); indent(f_service_) << "args." << (*f_iter)->get_name() << maybeComma << endl; } indent_down(); if (gen_es6_) { indent(f_service_) << "))).then(result => {" << endl; } else { indent(f_service_) << ").then(function(result) {" << endl; } indent_up(); f_service_ << indent() << js_const_type_ << "result_obj = new " << resultname << "({success: result});" << endl << indent() << "output.writeMessageBegin(\"" << tfunction->get_name() << "\", Thrift.MessageType.REPLY, seqid);" << endl << indent() << "result_obj.write(output);" << endl << indent() << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl; indent_down(); if (gen_es6_) { indent(f_service_) << "}).catch(err => {" << endl; } else { indent(f_service_) << "}).catch(function (err) {" << endl; } indent_up(); indent(f_service_) << js_let_type_ << "result;" << endl; bool has_exception = false; t_struct* exceptions = tfunction->get_xceptions(); if (exceptions) { const vector& members = exceptions->get_members(); for (auto member : members) { t_type* t = get_true_type(member->get_type()); if (t->is_xception()) { if (!has_exception) { has_exception = true; indent(f_service_) << "if (err instanceof " << js_type_namespace(t->get_program()) << t->get_name(); } else { f_service_ << " || err instanceof " << js_type_namespace(t->get_program()) << t->get_name(); } } } } if (has_exception) { f_service_ << ") {" << endl; indent_up(); f_service_ << indent() << "result = new " << resultname << "(err);" << endl << indent() << "output.writeMessageBegin(\"" << tfunction->get_name() << "\", Thrift.MessageType.REPLY, seqid);" << endl; indent_down(); indent(f_service_) << "} else {" << endl; indent_up(); } f_service_ << indent() << "result = new " "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN," " err.message);" << endl << indent() << "output.writeMessageBegin(\"" << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << endl; if (has_exception) { indent_down(); indent(f_service_) << "}" << endl; } f_service_ << indent() << "result.write(output);" << endl << indent() << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl; indent_down(); indent(f_service_) << "});" << endl; indent_down(); // End promise style invocation // Callback style invocation indent(f_service_) << "} else {" << endl; indent_up(); indent(f_service_) << "this._handler." << tfunction->get_name() << "("; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { f_service_ << "args." << (*f_iter)->get_name() << ", "; } if (gen_es6_) { f_service_ << "(err, result) => {" << endl; } else { f_service_ << "function (err, result) {" << endl; } indent_up(); indent(f_service_) << js_let_type_ << "result_obj;" << endl; indent(f_service_) << "if ((err === null || typeof err === 'undefined')"; if (has_exception) { const vector& members = exceptions->get_members(); for (auto member : members) { t_type* t = get_true_type(member->get_type()); if (t->is_xception()) { f_service_ << " || err instanceof " << js_type_namespace(t->get_program()) << t->get_name(); } } } f_service_ << ") {" << endl; indent_up(); f_service_ << indent() << "result_obj = new " << resultname << "((err !== null || typeof err === 'undefined') ? err : {success: result});" << endl << indent() << "output.writeMessageBegin(\"" << tfunction->get_name() << "\", Thrift.MessageType.REPLY, seqid);" << endl; indent_down(); indent(f_service_) << "} else {" << endl; indent_up(); f_service_ << indent() << "result_obj = new " "Thrift.TApplicationException(Thrift.TApplicationExceptionType.UNKNOWN," " err.message);" << endl << indent() << "output.writeMessageBegin(\"" << tfunction->get_name() << "\", Thrift.MessageType.EXCEPTION, seqid);" << endl; indent_down(); f_service_ << indent() << "}" << endl << indent() << "result_obj.write(output);" << endl << indent() << "output.writeMessageEnd();" << endl << indent() << "output.flush();" << endl; indent_down(); indent(f_service_) << "});" << endl; indent_down(); indent(f_service_) << "}" << endl; // End callback style invocation indent_down(); if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; } } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_js_generator::generate_service_helpers(t_service* tservice) { // Do not generate TS definitions for helper functions bool gen_ts_tmp = gen_ts_; gen_ts_ = false; vector functions = tservice->get_functions(); vector::iterator f_iter; f_service_ << "//HELPER FUNCTIONS AND STRUCTURES" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); string name = ts->get_name(); ts->set_name(service_name_ + "_" + name); generate_js_struct_definition(f_service_, ts, false, false); generate_js_function_helpers(*f_iter); ts->set_name(name); } gen_ts_ = gen_ts_tmp; } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_js_generator::generate_js_function_helpers(t_function* tfunction) { t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_js_struct_definition(f_service_, &result, false, false); } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_js_generator::generate_service_interface(t_service* tservice) { (void)tservice; } /** * Generates a REST interface */ void t_js_generator::generate_service_rest(t_service* tservice) { (void)tservice; } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_js_generator::generate_service_client(t_service* tservice) { bool is_subclass_service = tservice->get_extends() != nullptr; if (gen_node_) { string prefix = has_js_namespace(tservice->get_program()) ? js_namespace(tservice->get_program()) : js_const_type_; f_service_ << prefix << service_name_ << "Client = " << "exports.Client"; if (gen_ts_) { f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class " << "Client "; if (tservice->get_extends() != nullptr) { f_service_ts_ << "extends " << tservice->get_extends()->get_name() << ".Client "; } f_service_ts_ << "{" << endl; } } else { f_service_ << js_namespace(tservice->get_program()) << service_name_ << "Client"; if (gen_ts_) { f_service_ts_ << ts_print_doc(tservice) << ts_indent() << ts_declare() << "class " << service_name_ << "Client "; if (is_subclass_service) { f_service_ts_ << "extends " << tservice->get_extends()->get_name() << "Client "; } f_service_ts_ << "{" << endl; } } // ES6 Constructor if (gen_es6_) { if (is_subclass_service) { f_service_ << " = class " << service_name_ << "Client extends " << js_namespace(tservice->get_extends()->get_program()) << tservice->get_extends()->get_name() << "Client {" << endl; } else { f_service_ << " = class " << service_name_ << "Client {" << endl; } indent_up(); if (gen_node_) { indent(f_service_) << "constructor(output, pClass) {" << endl; } else { indent(f_service_) << "constructor(input, output) {" << endl; } } else { if (gen_node_) { f_service_ << " = function(output, pClass) {" << endl; } else { f_service_ << " = function(input, output) {" << endl; } } indent_up(); if (gen_node_) { if (gen_es6_ && is_subclass_service) { indent(f_service_) << "super(output, pClass);" << endl; } indent(f_service_) << "this.output = output;" << endl; indent(f_service_) << "this.pClass = pClass;" << endl; indent(f_service_) << "this._seqid = 0;" << endl; indent(f_service_) << "this._reqs = {};" << endl; if (gen_ts_) { if(!is_subclass_service) { f_service_ts_ << ts_indent() << "private output: thrift.TTransport;" << endl << ts_indent() << "private pClass: thrift.TProtocol;" << endl << ts_indent() << "private _seqid: number;" << endl << endl; } f_service_ts_ << ts_indent() << "constructor(output: thrift.TTransport, pClass: { new(trans: thrift.TTransport): thrift.TProtocol });" << endl; } } else { indent(f_service_) << "this.input = input;" << endl; indent(f_service_) << "this.output = (!output) ? input : output;" << endl; indent(f_service_) << "this.seqid = 0;" << endl; if (gen_ts_) { f_service_ts_ << ts_indent() << "input: Thrift.TJSONProtocol;" << endl << ts_indent() << "output: Thrift.TJSONProtocol;" << endl << ts_indent() << "seqid: number;" << endl << endl << ts_indent() << "constructor(input: Thrift.TJSONProtocol, output?: Thrift.TJSONProtocol);" << endl; } } indent_down(); if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; if (is_subclass_service) { indent(f_service_) << "Thrift.inherits(" << js_namespace(tservice->get_program()) << service_name_ << "Client, " << js_namespace(tservice->get_extends()->get_program()) << tservice->get_extends()->get_name() << "Client);" << endl; } else { // init prototype indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype = {};" << endl; } } // utils for multiplexed services if (gen_node_) { if (gen_es6_) { indent(f_service_) << "seqid () { return this._seqid; }" << endl; indent(f_service_) << "new_seqid () { return this._seqid += 1; }" << endl; } else { indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.seqid = function() { return this._seqid; };" << endl << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.new_seqid = function() { return this._seqid += 1; };" << endl; } } // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); string arglist = argument_list(arg_struct); // Open function f_service_ << endl; if (gen_es6_) { indent(f_service_) << funname << " (" << arglist << ") {" << endl; } else { indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype." << function_signature(*f_iter, "", !gen_es6_) << " {" << endl; } indent_up(); if (gen_ts_) { // function definition without callback f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, false) << endl; if (!gen_es6_) { // overload with callback f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true) << endl; } else { // overload with callback f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true) << endl; } } if (gen_es6_ && gen_node_) { indent(f_service_) << "this._seqid = this.new_seqid();" << endl; indent(f_service_) << js_const_type_ << "self = this;" << endl << indent() << "return new Promise((resolve, reject) => {" << endl; indent_up(); indent(f_service_) << "self._reqs[self.seqid()] = (error, result) => {" << endl; indent_up(); indent(f_service_) << "return error ? reject(error) : resolve(result);" << endl; indent_down(); indent(f_service_) << "};" << endl; indent(f_service_) << "self.send_" << funname << "(" << arglist << ");" << endl; indent_down(); indent(f_service_) << "});" << endl; } else if (gen_node_) { // Node.js output ./gen-nodejs f_service_ << indent() << "this._seqid = this.new_seqid();" << endl << indent() << "if (callback === undefined) {" << endl; indent_up(); f_service_ << indent() << js_const_type_ << "_defer = Q.defer();" << endl << indent() << "this._reqs[this.seqid()] = function(error, result) {" << endl; indent_up(); indent(f_service_) << "if (error) {" << endl; indent_up(); indent(f_service_) << "_defer.reject(error);" << endl; indent_down(); indent(f_service_) << "} else {" << endl; indent_up(); indent(f_service_) << "_defer.resolve(result);" << endl; indent_down(); indent(f_service_) << "}" << endl; indent_down(); indent(f_service_) << "};" << endl; f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");" << endl << indent() << "return _defer.promise;" << endl; indent_down(); indent(f_service_) << "} else {" << endl; indent_up(); f_service_ << indent() << "this._reqs[this.seqid()] = callback;" << endl << indent() << "this.send_" << funname << "(" << arglist << ");" << endl; indent_down(); indent(f_service_) << "}" << endl; } else if (gen_es6_) { f_service_ << indent() << js_const_type_ << "self = this;" << endl << indent() << "return new Promise((resolve, reject) => {" << endl; indent_up(); f_service_ << indent() << "self.send_" << funname << "(" << arglist << (arglist.empty() ? "" : ", ") << "(error, result) => {" << endl; indent_up(); indent(f_service_) << "return error ? reject(error) : resolve(result);" << endl; indent_down(); f_service_ << indent() << "});" << endl; indent_down(); f_service_ << indent() << "});" << endl; } else if (gen_jquery_) { // jQuery output ./gen-js f_service_ << indent() << "if (callback === undefined) {" << endl; indent_up(); f_service_ << indent() << "this.send_" << funname << "(" << arglist << ");" << endl; if (!(*f_iter)->is_oneway()) { f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << "return "; } f_service_ << "this.recv_" << funname << "();" << endl; } indent_down(); f_service_ << indent() << "} else {" << endl; indent_up(); f_service_ << indent() << js_const_type_ << "postData = this.send_" << funname << "(" << arglist << (arglist.empty() ? "" : ", ") << "true);" << endl; f_service_ << indent() << "return this.output.getTransport()" << endl; indent_up(); f_service_ << indent() << ".jqRequest(this, postData, arguments, this.recv_" << funname << ");" << endl; indent_down(); indent_down(); f_service_ << indent() << "}" << endl; } else { // Standard JavaScript ./gen-js f_service_ << indent() << "this.send_" << funname << "(" << arglist << (arglist.empty() ? "" : ", ") << "callback); " << endl; if (!(*f_iter)->is_oneway()) { f_service_ << indent() << "if (!callback) {" << endl; f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << " return "; } f_service_ << "this.recv_" << funname << "();" << endl; f_service_ << indent() << "}" << endl; } } indent_down(); if (gen_es6_) { indent(f_service_) << "}" << endl << endl; } else { indent(f_service_) << "};" << endl << endl; } // Send function if (gen_es6_) { if (gen_node_) { indent(f_service_) << "send_" << funname << " (" << arglist << ") {" << endl; } else { // ES6 js still uses callbacks here. Should refactor this to promise style later.. indent(f_service_) << "send_" << funname << " (" << argument_list(arg_struct, true) << ") {" << endl; } } else { indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.send_" << function_signature(*f_iter, "", !gen_node_) << " {" << endl; } indent_up(); std::string outputVar; if (gen_node_) { f_service_ << indent() << js_const_type_ << "output = new this.pClass(this.output);" << endl; outputVar = "output"; } else { outputVar = "this.output"; } std::string argsname = js_namespace(program_) + service_name_ + "_" + (*f_iter)->get_name() + "_args"; std::string messageType = (*f_iter)->is_oneway() ? "Thrift.MessageType.ONEWAY" : "Thrift.MessageType.CALL"; // Build args if (fields.size() > 0){ // It is possible that a method argument is named "params", we need to ensure the locally // generated identifier "params" is uniquely named std::string params_identifier = this->next_identifier_name(fields, "params"); f_service_ << indent() << js_const_type_ << params_identifier << " = {" << endl; indent_up(); for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { indent(f_service_) << (*fld_iter)->get_name() << ": " << (*fld_iter)->get_name(); if (fld_iter != fields.end()-1) { f_service_ << "," << endl; } else { f_service_ << endl; } } indent_down(); indent(f_service_) << "};" << endl; // NOTE: "args" is a reserved keyword, so no need to generate a unique identifier indent(f_service_) << js_const_type_ << "args = new " << argsname << "(" << params_identifier << ");" << endl; } else { indent(f_service_) << js_const_type_ << "args = new " << argsname << "();" << endl; } // Serialize the request header within try/catch indent(f_service_) << "try {" << endl; indent_up(); if (gen_node_) { f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name() << "', " << messageType << ", this.seqid());" << endl; } else { f_service_ << indent() << outputVar << ".writeMessageBegin('" << (*f_iter)->get_name() << "', " << messageType << ", this.seqid);" << endl; } // Write to the stream f_service_ << indent() << "args.write(" << outputVar << ");" << endl << indent() << outputVar << ".writeMessageEnd();" << endl; if (gen_node_) { if((*f_iter)->is_oneway()) { f_service_ << indent() << "this.output.flush();" << endl; f_service_ << indent() << js_const_type_ << "callback = this._reqs[this.seqid()] || function() {};" << endl; f_service_ << indent() << "delete this._reqs[this.seqid()];" << endl; f_service_ << indent() << "callback(null);" << endl; } else { f_service_ << indent() << "return this.output.flush();" << endl; } } else { if (gen_jquery_) { f_service_ << indent() << "return this.output.getTransport().flush(callback);" << endl; } else if (gen_es6_) { f_service_ << indent() << js_const_type_ << "self = this;" << endl; if((*f_iter)->is_oneway()) { f_service_ << indent() << "this.output.getTransport().flush(true, null);" << endl; f_service_ << indent() << "callback();" << endl; } else { f_service_ << indent() << "this.output.getTransport().flush(true, () => {" << endl; indent_up(); f_service_ << indent() << js_let_type_ << "error = null, result = null;" << endl; f_service_ << indent() << "try {" << endl; f_service_ << indent() << " result = self.recv_" << funname << "();" << endl; f_service_ << indent() << "} catch (e) {" << endl; f_service_ << indent() << " error = e;" << endl; f_service_ << indent() << "}" << endl; f_service_ << indent() << "callback(error, result);" << endl; indent_down(); f_service_ << indent() << "});" << endl; } } else { f_service_ << indent() << "if (callback) {" << endl; indent_up(); if((*f_iter)->is_oneway()) { f_service_ << indent() << "this.output.getTransport().flush(true, null);" << endl; f_service_ << indent() << "callback();" << endl; } else { f_service_ << indent() << js_const_type_ << "self = this;" << endl; f_service_ << indent() << "this.output.getTransport().flush(true, function() {" << endl; indent_up(); f_service_ << indent() << js_let_type_ << "result = null;" << endl; f_service_ << indent() << "try {" << endl; f_service_ << indent() << " result = self.recv_" << funname << "();" << endl; f_service_ << indent() << "} catch (e) {" << endl; f_service_ << indent() << " result = e;" << endl; f_service_ << indent() << "}" << endl; f_service_ << indent() << "callback(result);" << endl; indent_down(); f_service_ << indent() << "});" << endl; } indent_down(); f_service_ << indent() << "} else {" << endl; f_service_ << indent() << " return this.output.getTransport().flush();" << endl; f_service_ << indent() << "}" << endl; } } indent_down(); f_service_ << indent() << "}" << endl; // Reset the transport and delete registered callback if there was a serialization error f_service_ << indent() << "catch (e) {" << endl; indent_up(); if (gen_node_) { f_service_ << indent() << "delete this._reqs[this.seqid()];" << endl; f_service_ << indent() << "if (typeof " << outputVar << ".reset === 'function') {" << endl; f_service_ << indent() << " " << outputVar << ".reset();" << endl; f_service_ << indent() << "}" << endl; } else { f_service_ << indent() << "if (typeof " << outputVar << ".getTransport().reset === 'function') {" << endl; f_service_ << indent() << " " << outputVar << ".getTransport().reset();" << endl; f_service_ << indent() << "}" << endl; } f_service_ << indent() << "throw e;" << endl; indent_down(); f_service_ << indent() << "}" << endl; indent_down(); // Close send function if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; } // Receive function if (!(*f_iter)->is_oneway()) { std::string resultname = js_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_result"; f_service_ << endl; // Open receive function if (gen_node_) { if (gen_es6_) { indent(f_service_) << "recv_" << (*f_iter)->get_name() << " (input, mtype, rseqid) {" << endl; } else { indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype.recv_" << (*f_iter)->get_name() << " = function(input,mtype,rseqid) {" << endl; } } else { if (gen_es6_) { indent(f_service_) << "recv_" << (*f_iter)->get_name() << " () {" << endl; } else { t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); indent(f_service_) << js_namespace(tservice->get_program()) << service_name_ << "Client.prototype." << function_signature(&recv_function) << " {" << endl; } } indent_up(); std::string inputVar; if (gen_node_) { inputVar = "input"; } else { inputVar = "this.input"; } if (gen_node_) { f_service_ << indent() << js_const_type_ << "callback = this._reqs[rseqid] || function() {};" << endl << indent() << "delete this._reqs[rseqid];" << endl; } else { f_service_ << indent() << js_const_type_ << "ret = this.input.readMessageBegin();" << endl << indent() << js_const_type_ << "mtype = ret.mtype;" << endl; } f_service_ << indent() << "if (mtype == Thrift.MessageType.EXCEPTION) {" << endl; indent_up(); f_service_ << indent() << js_const_type_ << "x = new Thrift.TApplicationException();" << endl << indent() << "x.read(" << inputVar << ");" << endl << indent() << inputVar << ".readMessageEnd();" << endl << indent() << render_recv_throw("x") << endl; scope_down(f_service_); f_service_ << indent() << js_const_type_ << "result = new " << resultname << "();" << endl << indent() << "result.read(" << inputVar << ");" << endl; f_service_ << indent() << inputVar << ".readMessageEnd();" << endl << endl; t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "if (null !== result." << (*x_iter)->get_name() << ") {" << endl << indent() << " " << render_recv_throw("result." + (*x_iter)->get_name()) << endl << indent() << "}" << endl; } // Careful, only return result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << indent() << "if (null !== result.success) {" << endl << indent() << " " << render_recv_return("result.success") << endl << indent() << "}" << endl; f_service_ << indent() << render_recv_throw("'" + (*f_iter)->get_name() + " failed: unknown result'") << endl; } else { if (gen_node_) { indent(f_service_) << "callback(null);" << endl; } else { indent(f_service_) << "return;" << endl; } } // Close receive function indent_down(); if (gen_es6_) { indent(f_service_) << "}" << endl; } else { indent(f_service_) << "};" << endl; } } } // Finish class definitions if (gen_ts_) { f_service_ts_ << ts_indent() << "}" << endl; } if (gen_es6_) { indent_down(); f_service_ << "};" << endl; } } std::string t_js_generator::render_recv_throw(std::string var) { if (gen_node_) { return "return callback(" + var + ");"; } else { return "throw " + var + ";"; } } std::string t_js_generator::render_recv_return(std::string var) { if (gen_node_) { return "return callback(null, " + var + ");"; } else { return "return " + var + ";"; } } /** * Deserializes a field of any type. */ void t_js_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool inclass) { (void)inclass; t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw std::runtime_error("CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name()); } string name = prefix + tfield->get_name(); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << name << " = input."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw std::runtime_error("compiler error: cannot serialize void field in a struct: " + name); break; case t_base_type::TYPE_STRING: out << (type->is_binary() ? "readBinary()" : "readString()"); break; case t_base_type::TYPE_BOOL: out << "readBool()"; break; case t_base_type::TYPE_I8: out << "readByte()"; break; case t_base_type::TYPE_I16: out << "readI16()"; break; case t_base_type::TYPE_I32: out << "readI32()"; break; case t_base_type::TYPE_I64: out << "readI64()"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble()"; break; default: throw std::runtime_error("compiler error: no JS name for base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { out << "readI32()"; } if (!gen_node_) { out << ".value"; } out << ";" << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Generates an unserializer for a variable. This makes two key assumptions, * first that there is a const char* variable named data that points to the * buffer for deserialization, and that there is a variable protocol which * is a reference to a TProtocol serialization object. */ void t_js_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { out << indent() << prefix << " = new " << js_type_namespace(tstruct->get_program()) << tstruct->get_name() << "();" << endl << indent() << prefix << ".read(input);" << endl; } void t_js_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { string size = tmp("_size"); string rtmp3 = tmp("_rtmp3"); t_field fsize(g_type_i32, size); // Declare variables, read header if (ttype->is_map()) { out << indent() << prefix << " = {};" << endl; out << indent() << js_const_type_ << rtmp3 << " = input.readMapBegin();" << endl; out << indent() << js_const_type_ << size << " = " << rtmp3 << ".size || 0;" << endl; } else if (ttype->is_set()) { out << indent() << prefix << " = [];" << endl << indent() << js_const_type_ << rtmp3 << " = input.readSetBegin();" << endl << indent() << js_const_type_ << size << " = " << rtmp3 << ".size || 0;" << endl; } else if (ttype->is_list()) { out << indent() << prefix << " = [];" << endl << indent() << js_const_type_ << rtmp3 << " = input.readListBegin();" << endl << indent() << js_const_type_ << size << " = " << rtmp3 << ".size || 0;" << endl; } // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (" << js_let_type_ << i << " = 0; " << i << " < " << size << "; ++" << i << ") {" << endl; indent_up(); if (ttype->is_map()) { if (!gen_node_) { out << indent() << "if (" << i << " > 0 ) {" << endl << indent() << " if (input.rstack.length > input.rpos[input.rpos.length -1] + 1) {" << endl << indent() << " input.rstack.pop();" << endl << indent() << " }" << endl << indent() << "}" << endl; } generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } scope_down(out); // Read container end if (ttype->is_map()) { indent(out) << "input.readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "input.readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "input.readListEnd();" << endl; } } /** * Generates code to deserialize a map */ void t_js_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("key"); string val = tmp("val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey, false, false) << ";" << endl; indent(out) << declare_field(&fval, false, false) << ";" << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << prefix << "[" << key << "] = " << val << ";" << endl; } void t_js_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << js_let_type_ << elem << " = null;" << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".push(" << elem << ");" << endl; } void t_js_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << js_let_type_ << elem << " = null;" << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".push(" << elem << ");" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_js_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw std::runtime_error("CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name()); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name()); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + tfield->get_name()); } else if (type->is_base_type() || type->is_enum()) { string name = tfield->get_name(); // Hack for when prefix is defined (always a hash ref) if (!prefix.empty()) name = prefix + tfield->get_name(); indent(out) << "output."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw std::runtime_error("compiler error: cannot serialize void field in a struct: " + name); break; case t_base_type::TYPE_STRING: out << (type->is_binary() ? "writeBinary(" : "writeString(") << name << ")"; break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ")"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ")"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ")"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ")"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ")"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ")"; break; default: throw std::runtime_error("compiler error: no JS name for base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { out << "writeI32(" << name << ")"; } out << ";" << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_js_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << prefix << ".write(output);" << endl; } /** * Writes out a container */ void t_js_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { if (ttype->is_map()) { indent(out) << "output.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "Thrift.objectLength(" << prefix << "));" << endl; } else if (ttype->is_set()) { indent(out) << "output.writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix << ".length);" << endl; } else if (ttype->is_list()) { indent(out) << "output.writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".length);" << endl; } if (ttype->is_map()) { string kiter = tmp("kiter"); string viter = tmp("viter"); indent(out) << "for (" << js_let_type_ << kiter << " in " << prefix << ") {" << endl; indent_up(); indent(out) << "if (" << prefix << ".hasOwnProperty(" << kiter << ")) {" << endl; indent_up(); indent(out) << js_let_type_ << viter << " = " << prefix << "[" << kiter << "];" << endl; generate_serialize_map_element(out, (t_map*)ttype, kiter, viter); scope_down(out); scope_down(out); } else if (ttype->is_set()) { string iter = tmp("iter"); indent(out) << "for (" << js_let_type_ << iter << " in " << prefix << ") {" << endl; indent_up(); indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << ")) {" << endl; indent_up(); indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl; generate_serialize_set_element(out, (t_set*)ttype, iter); scope_down(out); scope_down(out); } else if (ttype->is_list()) { string iter = tmp("iter"); indent(out) << "for (" << js_let_type_ << iter << " in " << prefix << ") {" << endl; indent_up(); indent(out) << "if (" << prefix << ".hasOwnProperty(" << iter << ")) {" << endl; indent_up(); indent(out) << iter << " = " << prefix << "[" << iter << "];" << endl; generate_serialize_list_element(out, (t_list*)ttype, iter); scope_down(out); scope_down(out); } if (ttype->is_map()) { indent(out) << "output.writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "output.writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "output.writeListEnd();" << endl; } } /** * Serializes the members of a map. * */ void t_js_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), kiter); generate_serialize_field(out, &kfield); t_field vfield(tmap->get_val_type(), viter); generate_serialize_field(out, &vfield); } /** * Serializes the members of a set. */ void t_js_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield); } /** * Serializes the members of a list. */ void t_js_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield); } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type */ string t_js_generator::declare_field(t_field* tfield, bool init, bool obj) { string result = "this." + tfield->get_name(); if (!obj) { result = js_let_type_ + tfield->get_name(); } if (init) { t_type* type = get_true_type(tfield->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_STRING: case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: result += " = null"; break; default: throw std::runtime_error("compiler error: no JS initializer for base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { result += " = null"; } else if (type->is_map()) { result += " = null"; } else if (type->is_container()) { result += " = null"; } else if (type->is_struct() || type->is_xception()) { if (obj) { result += " = new " + js_type_namespace(type->get_program()) + type->get_name() + "()"; } else { result += " = null"; } } } else { result += " = null"; } return result; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_js_generator::function_signature(t_function* tfunction, string prefix, bool include_callback) { string str; str = prefix + tfunction->get_name() + " = function("; str += argument_list(tfunction->get_arglist(), include_callback); str += ")"; return str; } /** * Renders a field list */ string t_js_generator::argument_list(t_struct* tstruct, bool include_callback) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += (*f_iter)->get_name(); } if (include_callback) { if (!fields.empty()) { result += ", "; } result += "callback"; } return result; } /** * Converts the parse type to a C++ enum string for the given type. */ string t_js_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw std::runtime_error("NO T_VOID CONSTRUCT"); case t_base_type::TYPE_STRING: return "Thrift.Type.STRING"; case t_base_type::TYPE_BOOL: return "Thrift.Type.BOOL"; case t_base_type::TYPE_I8: return "Thrift.Type.BYTE"; case t_base_type::TYPE_I16: return "Thrift.Type.I16"; case t_base_type::TYPE_I32: return "Thrift.Type.I32"; case t_base_type::TYPE_I64: return "Thrift.Type.I64"; case t_base_type::TYPE_DOUBLE: return "Thrift.Type.DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "Thrift.Type.I32"; } else if (type->is_struct() || type->is_xception()) { return "Thrift.Type.STRUCT"; } else if (type->is_map()) { return "Thrift.Type.MAP"; } else if (type->is_set()) { return "Thrift.Type.SET"; } else if (type->is_list()) { return "Thrift.Type.LIST"; } throw std::runtime_error("INVALID TYPE IN type_to_enum: " + type->get_name()); } /** * Converts a t_type to a TypeScript type (string). * @param t_type Type to convert to TypeScript * @return String TypeScript type */ string t_js_generator::ts_get_type(t_type* type) { std::string ts_type; type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: ts_type = type->is_binary() ? "Buffer" : "string"; break; case t_base_type::TYPE_BOOL: ts_type = "boolean"; break; case t_base_type::TYPE_I8: ts_type = "any"; break; case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_DOUBLE: ts_type = "number"; break; case t_base_type::TYPE_I64: ts_type = "Int64"; break; case t_base_type::TYPE_VOID: ts_type = "void"; break; default: throw "compiler error: unhandled type"; } } else if (type->is_enum() || type->is_struct() || type->is_xception()) { std::string type_name; if (type->get_program()) { type_name = js_namespace(type->get_program()); // If the type is not defined within the current program, we need to prefix it with the same name as // the generated "import" statement for the types containing program if(type->get_program() != program_) { auto prefix = include_2_import_name.find(type->get_program()); if(prefix != include_2_import_name.end()) { type_name.append(prefix->second); type_name.append("."); } } } type_name.append(type->get_name()); ts_type = type_name; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } ts_type = ts_get_type(etype) + "[]"; } else if (type->is_map()) { string ktype = ts_get_type(((t_map*)type)->get_key_type()); string vtype = ts_get_type(((t_map*)type)->get_val_type()); if (ktype == "number" || ktype == "string" ) { ts_type = "{ [k: " + ktype + "]: " + vtype + "; }"; } else if ((((t_map*)type)->get_key_type())->is_enum()) { // Not yet supported (enum map): https://github.com/Microsoft/TypeScript/pull/2652 //ts_type = "{ [k: " + ktype + "]: " + vtype + "; }"; ts_type = "{ [k: number /*" + ktype + "*/]: " + vtype + "; }"; } else { ts_type = "any"; } } return ts_type; } /** * Renders a TypeScript function signature of the form 'name(args: types): type;' * * @param t_function Function definition * @param bool in-/exclude the callback argument * @return String of rendered function definition */ std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback) { string str; const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator f_iter; str = tfunction->get_name() + "("; bool has_written_optional = false; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { // Ensure that non optional parameters do not follow optional parameters // E.g. public foo(a: string, b?: string; c: string) is invalid, c must be optional, or b non-optional string original_optional = ts_get_req(*f_iter); string optional = has_written_optional ? "?" : original_optional; has_written_optional = has_written_optional || optional.size() > 0; str += (*f_iter)->get_name() + optional + ": " + ts_get_type((*f_iter)->get_type()); if (f_iter + 1 != fields.end() || (include_callback && fields.size() > 0)) { str += ", "; } } if (include_callback) { if (gen_node_) { t_struct* exceptions = tfunction->get_xceptions(); string exception_types; if (exceptions) { const vector& members = exceptions->get_members(); for (vector::const_iterator it = members.begin(); it != members.end(); ++it) { t_type* t = get_true_type((*it)->get_type()); if (it == members.begin()) { exception_types = js_type_namespace(t->get_program()) + t->get_name(); } else { exception_types += " | " + js_type_namespace(t->get_program()) + t->get_name(); } } } if (exception_types == "") { str += "callback?: (error: void, response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; } else { str += "callback?: (error: " + exception_types + ", response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; } } else { str += "callback?: (data: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; } if (gen_jquery_) { str += "JQueryPromise<" + ts_get_type(tfunction->get_returntype()) +">;"; } else { str += "void;"; } } else { if (gen_es6_) { str += "): Promise<" + ts_get_type(tfunction->get_returntype()) + ">;"; } else { str += "): " + ts_get_type(tfunction->get_returntype()) + ";"; } } return str; } /** * Takes a name and produces a valid NodeJS identifier from it * * @param name The name which shall become a valid NodeJS identifier * @return The modified name with the updated identifier */ std::string t_js_generator::make_valid_nodeJs_identifier(std::string const& name) { std::string str = name; if (str.empty()) { return str; } // tests rely on this assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); // if the first letter is a number, we add an additional underscore in front of it char c = str.at(0); if (('0' <= c) && (c <= '9')) { str = "_" + str; } // following chars: letter, number or underscore for (size_t i = 0; i < str.size(); ++i) { c = str.at(i); if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9')) && ('_' != c) && ('$' != c)) { str.replace(i, 1, "_"); } } return str; } void t_js_generator::parse_imports(t_program* program, const std::string& imports_string) { if (program->get_recursive()) { throw std::invalid_argument("[-gen js:imports=] option is not usable in recursive code generation mode"); } std::stringstream sstream(imports_string); std::string import; while (std::getline(sstream, import, ':')) { imports.emplace_back(import); } if (imports.empty()) { throw std::invalid_argument("invalid usage: [-gen js:imports=] requires at least one path " "(multiple paths are separated by ':')"); } for (auto& import : imports) { // Strip trailing '/' if (!import.empty() && import[import.size() - 1] == '/') { import = import.substr(0, import.size() - 1); } if (import.empty()) { throw std::invalid_argument("empty paths are not allowed in imports"); } std::ifstream episode_file; string line; const auto episode_file_path = import + "/" + episode_file_name; episode_file.open(episode_file_path); if (!episode_file) { throw std::runtime_error("failed to open the file '" + episode_file_path + "'"); } while (std::getline(episode_file, line)) { const auto separator_position = line.find(':'); if (separator_position == string::npos) { // could not find the separator in the line throw std::runtime_error("the episode file '" + episode_file_path + "' is malformed, the line '" + line + "' does not have a key:value separator ':'"); } const auto module_name = line.substr(0, separator_position); const auto import_path = line.substr(separator_position + 1); if (module_name.empty()) { throw std::runtime_error("the episode file '" + episode_file_path + "' is malformed, the module name is empty"); } if (import_path.empty()) { throw std::runtime_error("the episode file '" + episode_file_path + "' is malformed, the import path is empty"); } const auto module_import_path = import.substr(import.find_last_of('/') + 1) + "/" + import_path; const auto result = module_name_2_import_path.emplace(module_name, module_import_path); if (!result.second) { throw std::runtime_error("multiple providers of import path found for " + module_name + "\n\t" + module_import_path + "\n\t" + result.first->second); } } } } void t_js_generator::parse_thrift_package_output_directory(const std::string& thrift_package_output_directory) { thrift_package_output_directory_ = thrift_package_output_directory; // Strip trailing '/' if (!thrift_package_output_directory_.empty() && thrift_package_output_directory_[thrift_package_output_directory_.size() - 1] == '/') { thrift_package_output_directory_ = thrift_package_output_directory_.substr(0, thrift_package_output_directory_.size() - 1); } // Check that the thrift_package_output_directory is not empty after stripping if (thrift_package_output_directory_.empty()) { throw std::invalid_argument("the thrift_package_output_directory argument must not be empty"); } else { gen_episode_file_ = true; } } /** * Checks is the specified field name is contained in the specified field vector */ bool t_js_generator::find_field(const std::vector& fields, const std::string& name) { vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == name) { return true; } } return false; } /** * Given a vector of fields, generate a valid identifier name that does not conflict with avaliable field names */ std::string t_js_generator::next_identifier_name(const std::vector& fields, const std::string& base_name) { // Search through fields until a match is not found, if a match is found prepend "_" to the identifier name std::string current_name = this->make_valid_nodeJs_identifier(base_name); while(this->find_field(fields, current_name)) { current_name = this->make_valid_nodeJs_identifier("_" + current_name); } return current_name; } std::string t_js_generator::display_name() const { return "Javascript"; } THRIFT_REGISTER_GENERATOR(js, "Javascript", " jquery: Generate jQuery compatible code.\n" " node: Generate node.js compatible code.\n" " ts: Generate TypeScript definition files.\n" " with_ns: Create global namespace objects when using node.js\n" " es6: Create ES6 code with Promises\n" " thrift_package_output_directory=:\n" " Generate episode file and use the as prefix\n" " imports=:\n" " ':' separated list of paths of modules that has episode files in their root\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_netstd_generator.cc0000644000000000000000000040053714452237057025577 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" #include "thrift/generate/t_netstd_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; //TODO: check for indentation //TODO: Do we need seqId_ in generation? t_netstd_generator::t_netstd_generator(t_program* program, const map& parsed_options, const string& option_string) : t_oop_generator(program) { (void)option_string; use_net6_features = false; suppress_deepcopy = false; add_async_postfix = false; use_pascal_case_properties = false; union_ = false; serialize_ = false; wcf_ = false; wcf_namespace_.clear(); map::const_iterator iter; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if (iter->first.compare("union") == 0) { union_ = true; } else if (iter->first.compare("serial") == 0) { serialize_ = true; wcf_namespace_ = iter->second; // since there can be only one namespace } else if (iter->first.compare("wcf") == 0) { wcf_ = true; wcf_namespace_ = iter->second; } else if (iter->first.compare("pascal") == 0) { use_pascal_case_properties = true; } else if (iter->first.compare("no_deepcopy") == 0) { suppress_deepcopy = true; } else if (iter->first.compare("net6") == 0) { use_net6_features = true; } else if (iter->first.compare("async_postfix") == 0) { add_async_postfix = true; } else { throw "unknown option netstd:" + iter->first; } } out_dir_base_ = "gen-netstd"; } static bool field_has_default(t_field* tfield) { return tfield->get_value() != nullptr; } static bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; } static t_type* resolve_typedef(t_type* ttype) { while (ttype->is_typedef()) { ttype = static_cast(ttype)->get_type(); } return ttype; } static bool type_can_be_null(t_type* ttype) { ttype = resolve_typedef(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string(); } bool t_netstd_generator::is_wcf_enabled() const { return wcf_; } bool t_netstd_generator::is_serialize_enabled() const { return serialize_; } bool t_netstd_generator::is_union_enabled() const { return union_; } void t_netstd_generator::init_generator() { MKDIR(get_out_dir().c_str()); namespace_name_ = program_->get_namespace("netstd"); string dir = namespace_name_; string subdir = get_out_dir().c_str(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } if (dir.size() > 0) { subdir = subdir + "/" + dir; MKDIR(subdir.c_str()); } namespace_dir_ = subdir; while (!member_mapping_scopes.empty()) { cleanup_member_name_mapping(member_mapping_scopes.back().scope_member); } pverbose(".NET Standard options:\n"); pverbose("- union ........... %s\n", (is_union_enabled() ? "ON" : "off")); pverbose("- serialize ....... %s\n", (is_serialize_enabled() ? "ON" : "off")); pverbose("- wcf ............. %s\n", (is_wcf_enabled() ? "ON" : "off")); pverbose("- pascal .......... %s\n", (use_pascal_case_properties ? "ON" : "off")); pverbose("- net6 ............ %s\n", (use_net6_features ? "ON" : "off")); pverbose("- no_deepcopy ..... %s\n", (suppress_deepcopy ? "ON" : "off")); pverbose("- async_postfix ... %s\n", (add_async_postfix ? "ON" : "off")); } string t_netstd_generator::normalize_name(string name, bool is_arg_name) { string tmp(name); transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(tolower)); // check for reserved argument names if( is_arg_name && (CANCELLATION_TOKEN_NAME == name)) { name += "_"; } // un-conflict keywords by prefixing with "@" if (netstd_keywords.find(tmp) != netstd_keywords.end()) { return "@" + name; } // prevent CS8981 "The type name only contains lower-cased ascii characters" if( name.find_first_not_of("abcdefghijklmnopqrstuvwxyz") == std::string::npos) { return "@" + name; } // no changes necessary return name; } void t_netstd_generator::reset_indent() { while( indent_count() > 0) { indent_down(); } } void t_netstd_generator::pragmas_and_directives(ostream& out) { if( use_net6_features) { out << "#nullable enable // requires C# 8.0" << endl; } // this one must be first out << "#pragma warning disable IDE0079 // remove unnecessary pragmas" << endl; out << "#pragma warning disable IDE0017 // object init can be simplified" << endl << "#pragma warning disable IDE0028 // collection init can be simplified" << endl << "#pragma warning disable IDE1006 // parts of the code use IDL spelling" << endl << "#pragma warning disable CA1822 // empty " << DEEP_COPY_METHOD_NAME << "() methods still non-static" << endl; if( ! use_net6_features) { out << "#pragma warning disable IDE0083 // pattern matching \"that is not SomeType\" requires net5.0 but we still support earlier versions" << endl; } out << endl; } void t_netstd_generator::start_netstd_namespace(ostream& out) { if (!namespace_name_.empty()) { out << "namespace " << namespace_name_ << endl; scope_up(out); } } void t_netstd_generator::end_netstd_namespace(ostream& out) { if (!namespace_name_.empty()) { scope_down(out); } } string t_netstd_generator::netstd_type_usings() const { string namespaces = "using System;\n" "using System.Collections;\n" "using System.Collections.Generic;\n" "using System.Text;\n" "using System.IO;\n" "using System.Linq;\n" "using System.Threading;\n" "using System.Threading.Tasks;\n" "using Microsoft.Extensions.Logging;\n" "using Thrift;\n" "using Thrift.Collections;\n"; if (is_wcf_enabled()) { namespaces += "using System.ServiceModel;\n"; namespaces += "using System.Runtime.Serialization;\n"; } return namespaces; } string t_netstd_generator::netstd_thrift_usings() const { string namespaces = "using Thrift.Protocol;\n" "using Thrift.Protocol.Entities;\n" "using Thrift.Protocol.Utilities;\n" "using Thrift.Transport;\n" "using Thrift.Transport.Client;\n" "using Thrift.Transport.Server;\n" "using Thrift.Processor;\n"; return namespaces; } void t_netstd_generator::close_generator() { // right at the end, after everything else generate_extensions_file(); } void t_netstd_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } void t_netstd_generator::generate_enum(t_enum* tenum) { int ic = indent_count(); string f_enum_name = namespace_dir_ + "/" + tenum->get_name() + ".cs"; ofstream_with_content_based_conditional_update f_enum; f_enum.open(f_enum_name.c_str()); generate_enum(f_enum, tenum); f_enum.close(); indent_validate(ic, "generate_enum"); } void t_netstd_generator::generate_enum(ostream& out, t_enum* tenum) { reset_indent(); out << autogen_comment() << endl; pragmas_and_directives(out); start_netstd_namespace(out); generate_netstd_doc(out, tenum); out << indent() << "public enum " << type_name(tenum,false) << endl; scope_up(out); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { generate_netstd_doc(out, *c_iter); int value = (*c_iter)->get_value(); out << indent() << normalize_name((*c_iter)->get_name()) << " = " << value << "," << endl; } scope_down(out); end_netstd_namespace(out); } void t_netstd_generator::generate_consts(vector consts) { if (consts.empty()) { return; } string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs"; ofstream_with_content_based_conditional_update f_consts; f_consts.open(f_consts_name.c_str()); generate_consts(f_consts, consts); f_consts.close(); } void t_netstd_generator::generate_consts(ostream& out, vector consts) { if (consts.empty()) { return; } reset_indent(); out << autogen_comment() << netstd_type_usings() << endl << endl; pragmas_and_directives(out); start_netstd_namespace(out); out << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Constants" << endl; scope_up(out); vector::iterator c_iter; bool need_static_constructor = false; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { generate_netstd_doc(out, *c_iter); if (print_const_value(out, normalize_name((*c_iter)->get_name()), (*c_iter)->get_type(), (*c_iter)->get_value(), false)) { need_static_constructor = true; } } if (need_static_constructor) { print_const_constructor(out, consts); } scope_down(out); end_netstd_namespace(out); } void t_netstd_generator::print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value) { if (type->is_struct() || type->is_xception()) { const vector& fields = static_cast(type)->get_members(); const map& val = value->get_map(); vector::const_iterator f_iter; map::const_iterator v_iter; collect_extensions_types(static_cast(type)); prepare_member_name_mapping(static_cast(type)); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_field* field = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field = *f_iter; } } if (field == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } t_type* field_type = field->get_type(); string val = render_const_value(out, name, field_type, v_iter->second); out << indent() << name << "." << prop_name(field) << " = " << val << ";" << endl; } cleanup_member_name_mapping(static_cast(type)); } else if (type->is_map()) { t_type* ktype = static_cast(type)->get_key_type(); t_type* vtype = static_cast(type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string val = render_const_value(out, name, vtype, v_iter->second); out << indent() << name << "[" << key << "]" << " = " << val << ";" << endl; } } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = static_cast(type)->get_elem_type(); } else { etype = static_cast(type)->get_elem_type(); } const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(out, name, etype, *v_iter); out << indent() << name << ".Add(" << val << ");" << endl; } } } void t_netstd_generator::print_const_constructor(ostream& out, vector consts) { out << indent() << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()" << endl; scope_up(out); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { string name = (*c_iter)->get_name(); t_type* type = (*c_iter)->get_type(); t_const_value* value = (*c_iter)->get_value(); print_const_def_value(out, name, type, value); } scope_down(out); } bool t_netstd_generator::print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval, bool needtype) { out << indent(); bool need_static_construction = !in_static; type = resolve_typedef( type); if (!defval || needtype) { out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ") << type_name(type) << " "; } if (type->is_base_type()) { string v2 = render_const_value(out, name, type, value); out << name << " = " << v2 << ";" << endl; need_static_construction = false; } else if (type->is_enum()) { out << name << " = " << type_name(type) << "." << value->get_identifier_name() << ";" << endl; need_static_construction = false; } else if (type->is_struct() || type->is_xception()) { out << name << " = new " << type_name(type) << "();" << endl; } else if (type->is_map()) { out << name << " = new " << type_name(type) << "();" << endl; } else if (type->is_list() || type->is_set()) { out << name << " = new " << type_name(type) << "();" << endl; } if (defval && !type->is_base_type() && !type->is_enum()) { print_const_def_value(out, name, type, value); } return need_static_construction; } string t_netstd_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value) { (void)name; ostringstream render; if (type->is_base_type()) { t_base_type::t_base tbase = static_cast(type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (type->is_binary()) { render << "System.Text.Encoding.UTF8.GetBytes(\"" << get_escaped_string(value) << "\")"; } else { render << '"' << get_escaped_string(value) << '"'; } break; case t_base_type::TYPE_UUID: render << "new System.Guid(\"" << get_escaped_string(value) << "\")"; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: render << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << value->get_integer(); } else { render << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { render << type_name(type) << "." << value->get_identifier_name(); } else { string t = normalize_name(tmp("tmp")); print_const_value(out, t, type, value, true, true, true); render << t; } return render.str(); } void t_netstd_generator::collect_extensions_types(t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; // make private members with public Properties for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { collect_extensions_types((*m_iter)->get_type()); } } void t_netstd_generator::collect_extensions_types(t_type* ttype) { ttype = resolve_typedef( ttype); string key = type_name(ttype); if (ttype->is_struct() || ttype->is_xception()) { if( checked_extension_types.find(key) == checked_extension_types.end()) { checked_extension_types[key] = ttype; // prevent recursion t_struct* tstruct = static_cast(ttype); collect_extensions_types(tstruct); } return; } if (ttype->is_container()) { if( collected_extension_types.find(key) == collected_extension_types.end()) { collected_extension_types[key] = ttype; // prevent recursion if( ttype->is_map()) { t_map* tmap = static_cast(ttype); collect_extensions_types(tmap->get_key_type()); collect_extensions_types(tmap->get_val_type()); } else if (ttype->is_set()) { t_set* tset = static_cast(ttype); collect_extensions_types(tset->get_elem_type()); } else if (ttype->is_list()) { t_list* tlist = static_cast(ttype); collect_extensions_types(tlist->get_elem_type()); } else { throw "compiler error: unhandled container type " + ttype->get_name(); } } return; } } void t_netstd_generator::generate_extensions_file() { if (collected_extension_types.empty()) { return; } string f_exts_name = namespace_dir_ + '/' + program_name_ + ".Extensions.cs"; ofstream_with_content_based_conditional_update f_exts; f_exts.open(f_exts_name.c_str()); generate_extensions(f_exts, collected_extension_types); f_exts.close(); } void t_netstd_generator::generate_extensions(ostream& out, map types) { if (types.empty()) { return; } reset_indent(); out << autogen_comment() << netstd_type_usings() << "using Thrift.Protocol;" << endl << endl << endl; pragmas_and_directives(out); start_netstd_namespace(out); out << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Extensions" << endl; scope_up(out); bool needs_typecast = false; std::map::const_iterator iter; for( iter = types.begin(); iter != types.end(); ++iter) { out << indent() << "public static bool Equals(this " << iter->first << " instance, object that)" << endl; scope_up(out); if( use_net6_features) { out << indent() << "if (that is not " << iter->first << " other) return false;" << endl; } else { out << indent() << "if (!(that is " << iter->first << " other)) return false;" << endl; } out << indent() << "if (ReferenceEquals(instance, other)) return true;" << endl; out << endl; out << indent() << "return TCollections.Equals(instance, other);" << endl; scope_down(out); out << endl << endl; out << indent() << "public static int GetHashCode(this " << iter->first << " instance)" << endl; scope_up(out); out << indent() << "return TCollections.GetHashCode(instance);" << endl; scope_down(out); out << endl << endl; if(! suppress_deepcopy) { out << indent() << "public static " << iter->first << nullable_field_suffix(iter->second) << " " << DEEP_COPY_METHOD_NAME << "(this " << iter->first << nullable_field_suffix(iter->second) << " source)" << endl; scope_up(out); out << indent() << "if (source == null)" << endl; indent_up(); out << indent() << "return null;" << endl << endl; indent_down(); string suffix(""); string tmp_instance = tmp("tmp"); out << indent() << "var " << tmp_instance << " = new " << iter->first << "(source.Count);" << endl; if( iter->second->is_map()) { t_map* tmap = static_cast(iter->second); string copy_key = get_deep_copy_method_call(tmap->get_key_type(), true, needs_typecast, suffix); string copy_val = get_deep_copy_method_call(tmap->get_val_type(), true, needs_typecast, suffix); bool null_key = type_can_be_null(tmap->get_key_type()); bool null_val = type_can_be_null(tmap->get_val_type()); out << indent() << "foreach (var pair in source)" << endl; indent_up(); if( use_net6_features) { out << indent() << tmp_instance << ".Add(pair.Key" << copy_key; out << ", pair.Value" << copy_val; } else { out << indent() << tmp_instance << ".Add("; if( null_key) { out << "(pair.Key != null) ? pair.Key" << copy_key << " : null"; } else { out << "pair.Key" << copy_key; } out << ", "; if( null_val) { out << "(pair.Value != null) ? pair.Value" << copy_val << " : null"; } else { out << "pair.Value" << copy_val; } } out << ");" << endl; indent_down(); } else if( iter->second->is_set() || iter->second->is_list()) { string copy_elm; bool null_elm = false; if (iter->second->is_set()) { t_set* tset = static_cast(iter->second); copy_elm = get_deep_copy_method_call(tset->get_elem_type(), true, needs_typecast, suffix); null_elm = type_can_be_null(tset->get_elem_type()); } else // list { t_list* tlist = static_cast(iter->second); copy_elm = get_deep_copy_method_call(tlist->get_elem_type(), true, needs_typecast, suffix); null_elm = type_can_be_null(tlist->get_elem_type()); } out << indent() << "foreach (var elem in source)" << endl; indent_up(); if( use_net6_features) { out << indent() << tmp_instance << ".Add(elem" << copy_elm; } else { out << indent() << tmp_instance << ".Add("; if( null_elm) { out << "(elem != null) ? elem" << copy_elm << " : null"; } else { out << "elem" << copy_elm; } } out << ");" << endl; indent_down(); } out << indent() << "return " << tmp_instance << ";" << endl; scope_down(out); out << endl << endl; } } scope_down(out); end_netstd_namespace(out); } void t_netstd_generator::generate_struct(t_struct* tstruct) { collect_extensions_types(tstruct); if (is_union_enabled() && tstruct->is_union()) { generate_netstd_union(tstruct); } else { generate_netstd_struct(tstruct, false); } } void t_netstd_generator::generate_xception(t_struct* txception) { generate_netstd_struct(txception, true); } void t_netstd_generator::generate_netstd_struct(t_struct* tstruct, bool is_exception) { int ic = indent_count(); string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); reset_indent(); f_struct << autogen_comment() << netstd_type_usings() << netstd_thrift_usings() << endl << endl; pragmas_and_directives(f_struct); generate_netstd_struct_definition(f_struct, tstruct, is_exception); f_struct.close(); indent_validate(ic, "generate_netstd_struct"); } void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result) { if (!in_class) { start_netstd_namespace(out); } out << endl; generate_netstd_doc(out, tstruct); collect_extensions_types(tstruct); prepare_member_name_mapping(tstruct); if ((is_serialize_enabled() || is_wcf_enabled()) && !is_exception) { out << indent() << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; } bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end(); string sharp_struct_name = type_name(tstruct, false); out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : "; if (is_exception) { out << "TException, "; } out << "TBase" << endl << indent() << "{" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; // make private members with public Properties for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { // if the field is required, then we use auto-properties if (!field_is_required((*m_iter))) { out << indent() << "private " << declare_field(*m_iter, false, true, "_") << endl; } } out << endl; bool has_non_required_fields = false; bool has_required_fields = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_netstd_doc(out, *m_iter); generate_property(out, *m_iter, true, true); bool is_required = field_is_required((*m_iter)); if (is_required) { has_required_fields = true; } else { has_non_required_fields = true; } } bool generate_isset = has_non_required_fields; if (generate_isset) { out << endl; if (is_serialize_enabled() || is_wcf_enabled()) { out << indent() << "[DataMember(Order = 1)]" << endl; } out << indent() << "public Isset __isset;" << endl; if (is_serialize_enabled() || is_wcf_enabled()) { out << indent() << "[DataContract]" << endl; } out << indent() << "public struct Isset" << endl << indent() << "{" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { bool is_required = field_is_required((*m_iter)); // if it is required, don't need Isset for that variable // if it is not required, if it has a default value, we need to generate Isset if (!is_required) { if (is_serialize_enabled() || is_wcf_enabled()) { out << indent() << "[DataMember]" << endl; } out << indent() << "public bool " << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << endl; } } indent_down(); out << indent() << "}" << endl << endl; if (generate_isset && (is_serialize_enabled() || is_wcf_enabled())) { out << indent() << "#region XmlSerializer support" << endl << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { bool is_required = field_is_required(*m_iter); // if it is required, don't need Isset for that variable // if it is not required, if it has a default value, we need to generate Isset if (!is_required) { out << indent() << "public bool ShouldSerialize" << prop_name(*m_iter) << "()" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return __isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << endl; indent_down(); out << indent() << "}" << endl << endl; } } out << indent() << "#endregion XmlSerializer support" << endl << endl; } } // We always want a default, no argument constructor for Reading out << indent() << "public " << sharp_struct_name << "()" << endl << indent() << "{" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); t = resolve_typedef(t); if ((*m_iter)->get_value() != nullptr) { if (field_is_required((*m_iter))) { print_const_value(out, "this." + normalize_name(prop_name(*m_iter)), t, (*m_iter)->get_value(), true, true); } else { print_const_value(out, "this._" + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); // Optionals with defaults are marked set out << indent() << "this.__isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << " = true;" << endl; } } } indent_down(); out << indent() << "}" << endl << endl; // if we have required fields, we add that CTOR too if (has_required_fields) { out << indent() << "public " << sharp_struct_name << "("; bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (field_is_required(*m_iter)) { if (first) { first = false; } else { out << ", "; } out << type_name((*m_iter)->get_type()) << nullable_field_suffix(*m_iter) << " " << normalize_name((*m_iter)->get_name()); } } out << ") : this()" << endl << indent() << "{" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (field_is_required(*m_iter)) { out << indent() << "this." << prop_name(*m_iter) << " = " << normalize_name((*m_iter)->get_name()) << ";" << endl; } } indent_down(); out << indent() << "}" << endl << endl; } // DeepCopy() generate_netstd_deepcopy_method(out, tstruct, sharp_struct_name); generate_netstd_struct_reader(out, tstruct); if (is_result) { generate_netstd_struct_result_writer(out, tstruct); } else { generate_netstd_struct_writer(out, tstruct); } generate_netstd_struct_equals(out, tstruct); generate_netstd_struct_hashcode(out, tstruct); generate_netstd_struct_tostring(out, tstruct); indent_down(); out << indent() << "}" << endl << endl; // generate a corresponding WCF fault to wrap the exception if ((is_serialize_enabled() || is_wcf_enabled()) && is_exception) { generate_netstd_wcffault(out, tstruct); } cleanup_member_name_mapping(tstruct); if (!in_class) { end_netstd_namespace(out); } } void t_netstd_generator::generate_netstd_wcffault(ostream& out, t_struct* tstruct) { out << endl; out << indent() << "[DataContract]" << endl; bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end(); out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << type_name(tstruct,false) << "Fault" << endl << indent() << "{" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; // make private members with public Properties for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { // if the field is required, then we use auto-properties if (!field_is_required((*m_iter))) { out << indent() << "private " << declare_field(*m_iter, false, true, "_") << endl; } } out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_property(out, *m_iter, true, false); } indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_deepcopy_method(ostream& out, t_struct* tstruct, std::string sharp_struct_name) { if( suppress_deepcopy) { return; // feature disabled } const vector& members = tstruct->get_members(); vector::const_iterator m_iter; out << indent() << "public " << sharp_struct_name << " " << DEEP_COPY_METHOD_NAME << "()" << endl; out << indent() << "{" << endl; indent_up(); // return directly if there are only required fields string tmp_instance = tmp("tmp"); out << indent() << "var " << tmp_instance << " = new " << sharp_struct_name << "();" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { bool needs_typecast = false; string suffix(""); t_type* ttype = (*m_iter)->get_type(); string copy_op = get_deep_copy_method_call(ttype, true, needs_typecast, suffix); bool is_required = field_is_required(*m_iter); generate_null_check_begin( out, *m_iter); out << indent() << tmp_instance << "." << prop_name(*m_iter) << " = "; if( needs_typecast) { out << "(" << type_name(ttype) << ")"; } out << "this." << prop_name(*m_iter) << copy_op << ";" << endl; generate_null_check_end( out, *m_iter); if( !is_required) { out << indent() << tmp_instance << ".__isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << " = this.__isset." << get_isset_name(normalize_name((*m_iter)->get_name())) << ";" << endl; } } out << indent() << "return " << tmp_instance << ";" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_struct_reader(ostream& out, t_struct* tstruct) { out << indent() << "public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "iprot.IncrementRecursionDepth();" << endl << indent() << "try" << endl << indent() << "{" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Required variables aren't in __isset, so we need tmp vars to check them for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (field_is_required(*f_iter)) { out << indent() << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; } } out << indent() << "TField field;" << endl << indent() << "await iprot.ReadStructBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "while (true)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "field = await iprot.ReadFieldBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "if (field.Type == TType.Stop)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "break;" << endl; indent_down(); out << indent() << "}" << endl << endl << indent() << "switch (field.ID)" << endl << indent() << "{" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool is_required = field_is_required(*f_iter); out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); out << indent() << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ")" << endl << indent() << "{" << endl; indent_up(); generate_deserialize_field(out, *f_iter); if (is_required) { out << indent() << "isset_" << (*f_iter)->get_name() << " = true;" << endl; } indent_down(); out << indent() << "}" << endl << indent() << "else" << endl << indent() << "{" << endl; indent_up(); out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, " << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } out << indent() << "default: " << endl; indent_up(); out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "break;" << endl; indent_down(); indent_down(); out << indent() << "}" << endl << endl << indent() << "await iprot.ReadFieldEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << endl << indent() << "await iprot.ReadStructEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (field_is_required((*f_iter))) { out << indent() << "if (!isset_" << (*f_iter)->get_name() << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; indent_down(); out << indent() << "}" << endl; } } indent_down(); out << indent() << "}" << endl; out << indent() << "finally" << endl << indent() << "{" << endl; indent_up(); out << indent() << "iprot.DecrementRecursionDepth();" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_null_check_begin(ostream& out, t_field* tfield) { bool is_required = field_is_required(tfield); bool null_allowed = type_can_be_null(tfield->get_type()); if( null_allowed || (!is_required)) { bool first = true; out << indent() << "if("; if( null_allowed) { out << "(" << prop_name(tfield) << " != null)"; first = false; } if( !is_required) { if( !first) { out << " && "; } out << "__isset." << get_isset_name(normalize_name(tfield->get_name())); } out << ")" << endl << indent() << "{" << endl; indent_up(); } } void t_netstd_generator::generate_null_check_end(ostream& out, t_field* tfield) { bool is_required = field_is_required(tfield); bool null_allowed = type_can_be_null(tfield->get_type()); if( null_allowed || (!is_required)) { indent_down(); out << indent() << "}" << endl; } } void t_netstd_generator::generate_netstd_struct_writer(ostream& out, t_struct* tstruct) { out << indent() << "public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "oprot.IncrementRecursionDepth();" << endl << indent() << "try" << endl << indent() << "{" << endl; indent_up(); string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; string tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = new TStruct(\"" << name << "\");" << endl << indent() << "await oprot.WriteStructBeginAsync(" << tmpvar << ", " << CANCELLATION_TOKEN_NAME << ");" << endl; if (fields.size() > 0) { tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = new TField();" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { generate_null_check_begin( out, *f_iter); out << indent() << tmpvar << ".Name = \"" << (*f_iter)->get_name() << "\";" << endl << indent() << tmpvar << ".Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl << indent() << tmpvar << ".ID = " << (*f_iter)->get_key() << ";" << endl << indent() << "await oprot.WriteFieldBeginAsync(" << tmpvar << ", " << CANCELLATION_TOKEN_NAME << ");" << endl; generate_serialize_field(out, *f_iter); out << indent() << "await oprot.WriteFieldEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; generate_null_check_end(out, *f_iter); } } out << indent() << "await oprot.WriteFieldStopAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.WriteStructEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << indent() << "finally" << endl << indent() << "{" << endl; indent_up(); out << indent() << "oprot.DecrementRecursionDepth();" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_struct_result_writer(ostream& out, t_struct* tstruct) { out << indent() << "public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "oprot.IncrementRecursionDepth();" << endl << indent() << "try" << endl << indent() << "{" << endl; indent_up(); string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; string tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = new TStruct(\"" << name << "\");" << endl << indent() << "await oprot.WriteStructBeginAsync(" << tmpvar << ", " << CANCELLATION_TOKEN_NAME << ");" << endl; if (fields.size() > 0) { tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = new TField();" << endl; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; out << endl << indent() << "if"; } else { out << indent() << "else if"; } out << "(this.__isset." << get_isset_name(normalize_name((*f_iter)->get_name())) << ")" << endl << indent() << "{" << endl; indent_up(); bool null_allowed = type_can_be_null((*f_iter)->get_type()); if (null_allowed) { out << indent() << "if (" << prop_name(*f_iter) << " != null)" << endl << indent() << "{" << endl; indent_up(); } out << indent() << tmpvar << ".Name = \"" << prop_name(*f_iter) << "\";" << endl << indent() << tmpvar << ".Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl << indent() << tmpvar << ".ID = " << (*f_iter)->get_key() << ";" << endl << indent() << "await oprot.WriteFieldBeginAsync(" << tmpvar << ", " << CANCELLATION_TOKEN_NAME << ");" << endl; generate_serialize_field(out, *f_iter); out << indent() << "await oprot.WriteFieldEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; if (null_allowed) { indent_down(); out << indent() << "}" << endl; } indent_down(); out << indent() << "}" << endl; } } out << indent() << "await oprot.WriteFieldStopAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.WriteStructEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << indent() << "finally" << endl << indent() << "{" << endl; indent_up(); out << indent() << "oprot.DecrementRecursionDepth();" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_struct_tostring(ostream& out, t_struct* tstruct) { string tmpvar = tmp("tmp"); out << indent() << "public override string ToString()" << endl << indent() << "{" << endl; indent_up(); out << indent() << "var " << tmpvar << " = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool useFirstFlag = false; string tmp_count = tmp("tmp"); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (!field_is_required((*f_iter))) { out << indent() << "int " << tmp_count.c_str() << " = 0;" << endl; useFirstFlag = true; } break; } bool had_required = false; // set to true after first required field has been processed for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool is_required = field_is_required(*f_iter); generate_null_check_begin(out, *f_iter); if (useFirstFlag && (!had_required)) { out << indent() << "if(0 < " << tmp_count.c_str() << (is_required ? "" : "++") << ") { " << tmpvar << ".Append(\", \"); }" << endl; out << indent() << tmpvar << ".Append(\"" << prop_name(*f_iter) << ": \");" << endl; } else { out << indent() << tmpvar << ".Append(\", " << prop_name(*f_iter) << ": \");" << endl; } out << indent() << prop_name(*f_iter) << ".ToString(" << tmpvar << ");" << endl; generate_null_check_end(out, *f_iter); if (is_required) { had_required = true; // now __count must be > 0, so we don't need to check it anymore } } out << indent() << tmpvar << ".Append(')');" << endl << indent() << "return " << tmpvar << ".ToString();" << endl; indent_down(); out << indent() << "}" << endl; } void t_netstd_generator::generate_netstd_union(t_struct* tunion) { int ic = indent_count(); string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs"; ofstream_with_content_based_conditional_update f_union; f_union.open(f_union_name.c_str()); reset_indent(); f_union << autogen_comment() << netstd_type_usings() << netstd_thrift_usings() << endl << endl; pragmas_and_directives(f_union); generate_netstd_union_definition(f_union, tunion); f_union.close(); indent_validate(ic, "generate_netstd_union."); } void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct* tunion) { // Let's define the class first start_netstd_namespace(out); out << indent() << "public abstract partial class " << normalize_name(tunion->get_name()) << " : TUnionBase" << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "public abstract global::System.Threading.Tasks.Task WriteAsync(TProtocol tProtocol, CancellationToken " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "public readonly int Isset;" << endl << indent() << "public abstract object" << nullable_suffix() <<" Data { get; }" << endl << indent() << "protected " << normalize_name(tunion->get_name()) << "(int isset)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "Isset = isset;" << endl; indent_down(); out << indent() << "}" << endl << endl; const vector& fields = tunion->get_members(); vector::const_iterator f_iter; out << indent() << "public override bool Equals(object" << nullable_suffix() << " that)" << endl; scope_up(out); if( use_net6_features) { out << indent() << "if (that is not " << tunion->get_name() << " other) return false;" << endl; } else { out << indent() << "if (!(that is " << tunion->get_name() << " other)) return false;" << endl; } out << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; out << endl; out << indent() << "if(this.Isset != other.Isset) return false;" << endl; out << endl; if(use_net6_features) { out << indent() << "return Isset switch" << endl; scope_up(out); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool needs_typecast = false; string suffix(""); get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix); out << indent() << (*f_iter)->get_key() << " => Equals(As_" << (*f_iter)->get_name() << ", other.As_" << (*f_iter)->get_name() << ")," << endl; } out << indent() << "_ => true," << endl; indent_down(); out << indent() << "};" << endl; } else { out << indent() << "switch (Isset)" << endl; scope_up(out); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool needs_typecast = false; string suffix(""); get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix); out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); out << indent() << "return Equals(As_" << (*f_iter)->get_name() << ", other.As_" << (*f_iter)->get_name() << ");" << endl; indent_down(); } out << indent() << "default:" << endl; indent_up(); out << indent() << "return true;" << endl; indent_down(); scope_down(out); } scope_down(out); out << endl; out << indent() << "public override int GetHashCode()" << endl; out << indent() << "{" << endl; indent_up(); if(use_net6_features) { out << indent() << "return Isset switch" << endl; out << indent() << "{" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string null_coalesce(is_nullable_type((*f_iter)->get_type()) ? "?" : ""); out << indent() << (*f_iter)->get_key() << " => As_" << (*f_iter)->get_name() << null_coalesce << ".GetHashCode()"; if( null_coalesce.size() > 0) { out << " ?? 0"; } out << "," << endl; } out << indent() << "_ => (new ___undefined()).GetHashCode()" << endl; indent_down(); out << indent() << "};" << endl; } else { out << indent() << "switch (Isset)" << endl; out << indent() << "{" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string null_coalesce(is_nullable_type((*f_iter)->get_type()) ? "?" : ""); out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); out << indent() << "return As_" << (*f_iter)->get_name() << null_coalesce << ".GetHashCode()"; if( null_coalesce.size() > 0) { out << " ?? 0"; } out << ";" << endl; indent_down(); } out << indent() << "default:" << endl; indent_up(); out << indent() << "return (new ___undefined()).GetHashCode();" << endl; indent_down(); indent_down(); out << indent() << "}" << endl; } indent_down(); out << indent() << "}" << endl << endl; if( ! suppress_deepcopy) { out << indent() << "public " << tunion->get_name() << " " << DEEP_COPY_METHOD_NAME << "()" << endl; out << indent() << "{" << endl; indent_up(); if(use_net6_features) { out << indent() << "return Isset switch" << endl; out << indent() << "{" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool needs_typecast = false; string suffix(""); string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix); out << indent() << (*f_iter)->get_key() << " => new " << (*f_iter)->get_name() << "(As_" << (*f_iter)->get_name() << suffix << copy_op << ")," << endl; } out << indent() << "_ => new ___undefined()" << endl; indent_down(); out << indent() << "};" << endl; } else { out << indent() << "switch (Isset)" << endl; out << indent() << "{" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool needs_typecast = false; string suffix(""); string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), false, needs_typecast, suffix); out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); out << indent() << "return new " << (*f_iter)->get_name() << "(As_" << (*f_iter)->get_name() << suffix << copy_op << ");" << endl; indent_down(); } out << indent() << "default:" << endl; indent_up(); out << indent() << "return new ___undefined();" << endl; indent_down(); indent_down(); out << indent() << "}" << endl; } indent_down(); out << indent() << "}" << endl << endl; } out << indent() << "public class ___undefined : " << tunion->get_name() << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "public override object" << nullable_suffix() <<" Data { get { return null; } }" << endl << indent() << "public ___undefined() : base(0) {}" << endl << endl; if( ! suppress_deepcopy) { out << indent() << "public new ___undefined " << DEEP_COPY_METHOD_NAME << "()" << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "return new ___undefined();" << endl; indent_down(); out << indent() << "}" << endl << endl; } t_struct undefined_struct(program_,"___undefined"); generate_netstd_struct_equals(out, &undefined_struct); generate_netstd_struct_hashcode(out, &undefined_struct); out << indent() << "public override global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist an union type which is not set.\");" << endl; indent_down(); out << indent() << "}" << endl << endl; indent_down(); out << indent() << "}" << endl << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { generate_netstd_union_class(out, tunion, (*f_iter)); } generate_netstd_union_reader(out, tunion); indent_down(); out << indent() << "}" << endl << endl; end_netstd_namespace(out); } void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tunion, t_field* tfield) { out << indent() << "public " << type_name(tfield->get_type()) << nullable_field_suffix(tfield) << " As_" << tfield->get_name() << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "get" << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "return (" << tfield->get_key() << " == Isset) && (Data != null)" << " ? (" << type_name(tfield->get_type()) << nullable_field_suffix(tfield) << ")Data" << " : default" << (use_net6_features ? "" : ("(" + type_name(tfield->get_type()) + ")")) << ";" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "public class " << normalize_name(tfield->get_name()) << " : " << normalize_name(tunion->get_name()) << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "private readonly " << type_name(tfield->get_type()) << " _data;" << endl << indent() << "public override object" << nullable_suffix() <<" Data { get { return _data; } }" << endl << indent() << "public " << normalize_name(tfield->get_name()) << "(" << type_name(tfield->get_type()) << " data) : base("<< tfield->get_key() <<")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "this._data = data;" << endl; indent_down(); out << indent() << "}" << endl; if( ! suppress_deepcopy) { out << indent() << "public new " << normalize_name(tfield->get_name()) << " " << DEEP_COPY_METHOD_NAME << "()" << endl; out << indent() << "{" << endl; indent_up(); bool needs_typecast = false; string suffix(""); string copy_op = get_deep_copy_method_call(tfield->get_type(), true, needs_typecast, suffix); out << indent() << "return new " << normalize_name(tfield->get_name()) << "(_data" << copy_op << ");" << endl; indent_down(); out << indent() << "}" << endl << endl; } out << indent() << "public override bool Equals(object" << nullable_suffix() << " that)" << endl; out << indent() << "{" << endl; indent_up(); if(use_net6_features) { out << indent() << "if (that is not " << tunion->get_name() << " other) return false;" << endl; } else { out << indent() << "if (!(that is " << tunion->get_name() << " other)) return false;" << endl; } out << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; out << endl; out << indent() << "return Equals( _data, other.As_" << tfield->get_name() << ");" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "public override int GetHashCode()" << endl; out << indent() << "{" << endl; indent_up(); out << indent() << "return _data.GetHashCode();" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "public override async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ") {" << endl; indent_up(); out << indent() << "oprot.IncrementRecursionDepth();" << endl << indent() << "try" << endl << indent() << "{" << endl; indent_up(); out << indent() << "var struc = new TStruct(\"" << tunion->get_name() << "\");" << endl << indent() << "await oprot.WriteStructBeginAsync(struc, " << CANCELLATION_TOKEN_NAME << ");" << endl; out << indent() << "var field = new TField();" << endl << indent() << "field.Name = \"" << tfield->get_name() << "\";" << endl << indent() << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl << indent() << "field.ID = " << tfield->get_key() << ";" << endl << indent() << "await oprot.WriteFieldBeginAsync(field, " << CANCELLATION_TOKEN_NAME << ");" << endl; generate_serialize_field(out, tfield, "_data", true, false); out << indent() << "await oprot.WriteFieldEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.WriteFieldStopAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.WriteStructEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << indent() << "finally" << endl << indent() << "{" << endl; indent_up(); out << indent() << "oprot.DecrementRecursionDepth();" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_struct_equals(ostream& out, t_struct* tstruct) { out << indent() << "public override bool Equals(object" << nullable_suffix() << " that)" << endl << indent() << "{" << endl; indent_up(); if(use_net6_features) { out << indent() << "if (that is not " << type_name(tstruct,false) << " other) return false;" << endl; } else { out << indent() << "if (!(that is " << type_name(tstruct,false) << " other)) return false;" << endl; } out << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; out << indent() << "return "; indent_up(); } else { out << endl; out << indent() << "&& "; } if (!field_is_required((*f_iter))) { out << "((__isset." << get_isset_name(normalize_name((*f_iter)->get_name())) << " == other.__isset." << get_isset_name(normalize_name((*f_iter)->get_name())) << ") && ((!__isset." << get_isset_name(normalize_name((*f_iter)->get_name())) << ") || ("; } t_type* ttype = (*f_iter)->get_type(); if (ttype->is_container() || ttype->is_binary()) { out << "TCollections.Equals("; } else { out << "global::System.Object.Equals("; } out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")"; if (!field_is_required((*f_iter))) { out << ")))"; } } if (first) { out << indent() << "return true;" << endl; } else { out << ";" << endl; indent_down(); } indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_struct_hashcode(ostream& out, t_struct* tstruct) { out << indent() << "public override int GetHashCode() {" << endl; indent_up(); out << indent() << "int hashcode = 157;" << endl; out << indent() << "unchecked {" << endl; indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_type* ttype = (*f_iter)->get_type(); generate_null_check_begin(out, *f_iter); out << indent() << "hashcode = (hashcode * 397) + "; if (ttype->is_container()) { out << "TCollections.GetHashCode(" << prop_name((*f_iter)) << ")"; } else { out << prop_name(*f_iter) << ".GetHashCode()"; } out << ";" << endl; generate_null_check_end(out, *f_iter); } indent_down(); out << indent() << "}" << endl; out << indent() << "return hashcode;" << endl; indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_service(t_service* tservice) { int ic = indent_count(); string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs"; ofstream_with_content_based_conditional_update f_service; f_service.open(f_service_name.c_str()); reset_indent(); f_service << autogen_comment() << netstd_type_usings() << netstd_thrift_usings() << endl << endl; pragmas_and_directives(f_service); start_netstd_namespace(f_service); f_service << indent() << "public partial class " << normalize_name(service_name_) << endl << indent() << "{" << endl; indent_up(); generate_service_interface(f_service, tservice); generate_service_client(f_service, tservice); generate_service_server(f_service, tservice); generate_service_helpers(f_service, tservice); indent_down(); f_service << indent() << "}" << endl; end_netstd_namespace(f_service); f_service.close(); indent_validate(ic, "generate_service."); } void t_netstd_generator::generate_service_interface(ostream& out, t_service* tservice) { string extends = ""; string extends_iface = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_iface = " : " + extends + ".IAsync"; } //out << endl << endl; generate_netstd_doc(out, tservice); if (is_wcf_enabled()) { out << indent() << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; } prepare_member_name_mapping(tservice); out << indent() << "public interface IAsync" << extends_iface << endl << indent() << "{" << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_netstd_doc(out, *f_iter); // if we're using WCF, add the corresponding attributes if (is_wcf_enabled()) { out << indent() << "[OperationContract]" << endl; const vector& xceptions = (*f_iter)->get_xceptions()->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << indent() << "[FaultContract(typeof(" + type_name((*x_iter)->get_type()) + "Fault))]" << endl; } } generate_deprecation_attribute(out, *f_iter); out << indent() << function_signature_async(*f_iter) << ";" << endl << endl; } indent_down(); out << indent() << "}" << endl << endl; cleanup_member_name_mapping(tservice); } void t_netstd_generator::generate_deprecation_attribute(ostream& out, t_function* func) { auto iter = func->annotations_.find("deprecated"); if( func->annotations_.end() != iter) { out << indent() << "[Obsolete"; // empty annotation values end up with "1" somewhere, ignore these as well if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) { out << "(" << make_csharp_string_literal(iter->second.back()) << ")"; } out << "]" << endl; } } void t_netstd_generator::generate_service_helpers(ostream& out, t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; prepare_member_name_mapping(tservice); out << indent() << "public class InternalStructs" << endl; out << indent() << "{" << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); collect_extensions_types(ts); generate_netstd_struct_definition(out, ts, false, true); generate_function_helpers(out, *f_iter); } indent_down(); out << indent() << "}" << endl << endl; cleanup_member_name_mapping(tservice); } void t_netstd_generator::generate_service_client(ostream& out, t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_client = extends + ".Client, "; } else { extends_client = "TBaseClient, IDisposable, "; } out << endl; generate_netstd_doc(out, tservice); prepare_member_name_mapping(tservice); out << indent() << "public class Client : " << extends_client << "IAsync" << endl << indent() << "{" << endl; indent_up(); out << indent() << "public Client(TProtocol protocol) : this(protocol, protocol)" << endl << indent() << "{" << endl << indent() << "}" << endl << endl << indent() << "public Client(TProtocol inputProtocol, TProtocol outputProtocol) : base(inputProtocol, outputProtocol)" << endl << indent() << "{" << endl << indent() << "}" << endl << endl; vector functions = tservice->get_functions(); vector::const_iterator functions_iterator; for (functions_iterator = functions.begin(); functions_iterator != functions.end(); ++functions_iterator) { string raw_func_name = (*functions_iterator)->get_name(); string function_name = raw_func_name + (add_async_postfix ? "Async" : ""); // async generate_deprecation_attribute(out, *functions_iterator); out << indent() << "public async " << function_signature_async(*functions_iterator, "") << endl << indent() << "{" << endl; indent_up(); out << indent() << "await send_" << function_name << "("; string call_args = argument_list((*functions_iterator)->get_arglist(),false); if(! call_args.empty()) { out << call_args << ", "; } out << CANCELLATION_TOKEN_NAME << ");" << endl; if(! (*functions_iterator)->is_oneway()) { out << indent() << ((*functions_iterator)->get_returntype()->is_void() ? "" : "return ") << "await recv_" << function_name << "(" << CANCELLATION_TOKEN_NAME << ");" << endl; } indent_down(); out << indent() << "}" << endl << endl; // async send generate_deprecation_attribute(out, *functions_iterator); out << indent() << "public async " << function_signature_async(*functions_iterator, "send_", MODE_NO_RETURN) << endl << indent() << "{" << endl; indent_up(); string tmpvar = tmp("tmp"); string argsname = (*functions_iterator)->get_name() + "_args"; out << indent() << "await OutputProtocol.WriteMessageBeginAsync(new TMessage(\"" << raw_func_name << "\", TMessageType." << ((*functions_iterator)->is_oneway() ? "Oneway" : "Call") << ", SeqId), " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << endl << indent() << "var " << tmpvar << " = new InternalStructs." << argsname << "() {" << endl; indent_up(); t_struct* arg_struct = (*functions_iterator)->get_arglist(); collect_extensions_types(arg_struct); prepare_member_name_mapping(arg_struct); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { out << indent() << prop_name(*fld_iter) << " = " << normalize_name((*fld_iter)->get_name(),true) << "," << endl; } indent_down(); out << indent() << "};" << endl; out << indent() << endl << indent() << "await " << tmpvar << ".WriteAsync(OutputProtocol, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await OutputProtocol.WriteMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await OutputProtocol.Transport.FlushAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << endl; if (!(*functions_iterator)->is_oneway()) { // async recv generate_deprecation_attribute(out, *functions_iterator); out << indent() << "public async " << function_signature_async(*functions_iterator, "recv_", MODE_NO_ARGS) << endl << indent() << "{" << endl; indent_up(); string resultname = (*functions_iterator)->get_name() + "_result"; t_struct noargs(program_); t_struct* xs = (*functions_iterator)->get_xceptions(); collect_extensions_types(xs); prepare_member_name_mapping(xs, xs->get_members(), resultname); tmpvar = tmp("tmp"); out << indent() << endl << indent() << "var " << tmpvar << " = await InputProtocol.ReadMessageBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "if (" << tmpvar << ".Type == TMessageType.Exception)" << endl << indent() << "{" << endl; indent_up(); tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = await TApplicationException.ReadAsync(InputProtocol, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await InputProtocol.ReadMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "throw " << tmpvar << ";" << endl; indent_down(); tmpvar = tmp("tmp"); out << indent() << "}" << endl << endl << indent() << "var " << tmpvar << " = new InternalStructs." << resultname << "();" << endl << indent() << "await " << tmpvar << ".ReadAsync(InputProtocol, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await InputProtocol.ReadMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; if (!(*functions_iterator)->get_returntype()->is_void()) { out << indent() << "if (" << tmpvar << ".__isset.success)" << endl << indent() << "{" << endl; indent_up(); string nullable_value = nullable_value_access((*functions_iterator)->get_returntype()); out << indent() << "return " << tmpvar << ".Success" << nullable_value << ";" << endl; indent_down(); out << indent() << "}" << endl; } const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << indent() << "if (" << tmpvar << ".__isset." << get_isset_name(normalize_name((*x_iter)->get_name())) << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "throw " << tmpvar << "." << prop_name(*x_iter) << nullable_value_access((*x_iter)->get_type()) << ";" << endl; indent_down(); out << indent() << "}" << endl; } if (!(*functions_iterator)->get_returntype()->is_void()) { out << indent() << "throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, \"" << function_name << " failed: unknown result\");" << endl; } cleanup_member_name_mapping(xs); indent_down(); out << indent() << "}" << endl << endl; } cleanup_member_name_mapping(arg_struct); } indent_down(); out << indent() << "}" << endl << endl; cleanup_member_name_mapping(tservice); } void t_netstd_generator::generate_service_server(ostream& out, t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_processor = extends + ".AsyncProcessor, "; } prepare_member_name_mapping(tservice); out << indent() << "public class AsyncProcessor : " << extends_processor << "ITAsyncProcessor" << endl << indent() << "{" << endl; indent_up(); out << indent() << "private readonly IAsync _iAsync;" << endl << indent() << "private readonly ILogger" << nullable_suffix() << " _logger;" << endl << endl << indent() << "public AsyncProcessor(IAsync iAsync, ILogger" << nullable_suffix() << " logger = default)"; if (!extends.empty()) { out << " : base(iAsync)"; } out << endl << indent() << "{" << endl; indent_up(); out << indent() << "_iAsync = iAsync ?? throw new ArgumentNullException(nameof(iAsync));" << endl; out << indent() << "_logger = logger;" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string raw_func_name = (*f_iter)->get_name(); out << indent() << "processMap_[\"" << raw_func_name << "\"] = " << raw_func_name << "_ProcessAsync;" << endl; } indent_down(); out << indent() << "}" << endl << endl; if (extends.empty()) { out << indent() << "protected delegate global::System.Threading.Tasks.Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ");" << endl; } if (extends.empty()) { out << indent() << "protected Dictionary processMap_ = new" << (use_net6_features ? "" : " Dictionary") // Simplify new expression (IDE0090) << "();" << endl; } out << endl; if (extends.empty()) { out << indent() << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return await ProcessAsync(iprot, oprot, CancellationToken.None);" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl; } else { out << indent() << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return await ProcessAsync(iprot, oprot, CancellationToken.None);" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl; } out << indent() << "{" << endl; indent_up(); out << indent() << "try" << endl << indent() << "{" << endl; indent_up(); out << indent() << "var msg = await iprot.ReadMessageBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << endl << indent() << "processMap_.TryGetValue(msg.Name, out var fn);" << endl << endl << indent() << "if (fn == null)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "await TProtocolUtil.SkipAsync(iprot, TType.Struct, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await iprot.ReadMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "var x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + msg.Name + \"'\");" << endl << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID), " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await x.WriteAsync(oprot, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.WriteMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.Transport.FlushAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "return true;" << endl; indent_down(); out << indent() << "}" << endl << endl << indent() << "await fn(msg.SeqID, iprot, oprot, " << CANCELLATION_TOKEN_NAME << ");" << endl << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "catch (IOException)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return false;" << endl; indent_down(); out << indent() << "}" << endl << endl << indent() << "return true;" << endl; indent_down(); out << indent() << "}" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function_async(out, tservice, *f_iter); } indent_down(); out << indent() << "}" << endl << endl; cleanup_member_name_mapping(tservice); } void t_netstd_generator::generate_function_helpers(ostream& out, t_function* tfunction) { if (tfunction->is_oneway()) { return; } t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } collect_extensions_types(&result); generate_netstd_struct_definition(out, &result, false, true, true); } void t_netstd_generator::generate_process_function_async(ostream& out, t_service* tservice, t_function* tfunction) { (void)tservice; out << indent() << "public async global::System.Threading.Tasks.Task " << tfunction->get_name() << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl << indent() << "{" << endl; indent_up(); string argsname = tfunction->get_name() + "_args"; string resultname = tfunction->get_name() + "_result"; string args = tmp("tmp"); out << indent() << "var " << args << " = new InternalStructs." << argsname << "();" << endl << indent() << "await " << args << ".ReadAsync(iprot, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await iprot.ReadMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; string tmpResult = tmp("tmp"); if (!tfunction->is_oneway()) { out << indent() << "var " << tmpResult << " = new InternalStructs." << resultname << "();" << endl; } out << indent() << "try" << endl << indent() << "{" << endl; indent_up(); t_struct* xs = tfunction->get_xceptions(); const vector& xceptions = xs->get_members(); if (xceptions.size() > 0) { out << indent() << "try" << endl << indent() << "{" << endl; indent_up(); } t_struct* arg_struct = tfunction->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; bool is_deprecated = (tfunction->annotations_.end() != tfunction->annotations_.find("deprecated")); if( is_deprecated) { out << indent() << "#pragma warning disable CS0618,CS0612" << endl; } out << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { out << tmpResult << ".Success = "; } out << "await _iAsync." << func_name(normalize_name(tfunction->get_name()) + (add_async_postfix ? "Async" : "")) << "("; bool first = true; collect_extensions_types(arg_struct); prepare_member_name_mapping(arg_struct); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { out << ", "; } out << args << "." << prop_name(*f_iter); } cleanup_member_name_mapping(arg_struct); if (!first) { out << ", "; } out << "" << CANCELLATION_TOKEN_NAME << ");" << endl; if( is_deprecated) { out << indent() << "#pragma warning restore CS0618,CS0612" << endl; } vector::const_iterator x_iter; collect_extensions_types(xs); prepare_member_name_mapping(xs, xs->get_members(), resultname); if (xceptions.size() > 0) { indent_down(); out << indent() << "}" << endl; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { string tmpex = tmp("tmp"); out << indent() << "catch (" << type_name((*x_iter)->get_type()) << " " << tmpex << ")" << endl << indent() << "{" << endl; if (!tfunction->is_oneway()) { indent_up(); out << indent() << tmpResult << "." << prop_name(*x_iter) << " = " << tmpex << ";" << endl; indent_down(); } out << indent() << "}" << endl; } } if (!tfunction->is_oneway()) { out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.Reply, seqid), " << CANCELLATION_TOKEN_NAME << "); " << endl << indent() << "await " << tmpResult << ".WriteAsync(oprot, " << CANCELLATION_TOKEN_NAME << ");" << endl; } indent_down(); cleanup_member_name_mapping(xs); string tmpex = tmp("tmp"); out << indent() << "}" << endl << indent() << "catch (TTransportException)" << endl << indent() << "{" << endl << indent() << " throw;" << endl << indent() << "}" << endl << indent() << "catch (Exception " << tmpex << ")" << endl << indent() << "{" << endl; indent_up(); string tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = $\"Error occurred in {GetType().FullName}: {" << tmpex << ".Message}\";" << endl; out << indent() << "if(_logger != null)" << endl; indent_up(); out << indent() << "_logger.LogError(\"{Exception}, {Message}\", " << tmpex << ", " << tmpvar << ");" << endl; indent_down(); out << indent() << "else" << endl; indent_up(); out << indent() << "Console.Error.WriteLine(" << tmpvar << ");" << endl; indent_down(); if (tfunction->is_oneway()) { indent_down(); out << indent() << "}" << endl; } else { tmpvar = tmp("tmp"); out << indent() << "var " << tmpvar << " = new TApplicationException(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" << endl << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << tfunction->get_name() << "\", TMessageType.Exception, seqid), " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await " << tmpvar << ".WriteAsync(oprot, " << CANCELLATION_TOKEN_NAME << ");" << endl; indent_down(); out << indent() << "}" << endl << indent() << "await oprot.WriteMessageEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << "await oprot.Transport.FlushAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } indent_down(); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_netstd_union_reader(ostream& out, t_struct* tunion) { // Thanks to THRIFT-1768, we don't need to check for required fields in the union const vector& fields = tunion->get_members(); vector::const_iterator f_iter; out << indent() << "public static async Task<" << tunion->get_name() << "> ReadAsync(TProtocol iprot, CancellationToken " << CANCELLATION_TOKEN_NAME << ")" << endl; scope_up(out); out << indent() << "iprot.IncrementRecursionDepth();" << endl; out << indent() << "try" << endl; scope_up(out); string tmpRetval = tmp("tmp"); out << indent() << tunion->get_name() << " " << tmpRetval << ";" << endl; out << indent() << "await iprot.ReadStructBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; out << indent() << "TField field = await iprot.ReadFieldBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; // we cannot have the first field be a stop -- we must have a single field defined out << indent() << "if (field.Type == TType.Stop)" << endl; scope_up(out); out << indent() << "await iprot.ReadFieldEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; out << indent() << "" << tmpRetval << " = new ___undefined();" << endl; scope_down(out); out << indent() << "else" << endl; scope_up(out); out << indent() << "switch (field.ID)" << endl; scope_up(out); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); out << indent() << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); string tmpvar = tmp("tmp"); out << indent() << type_name((*f_iter)->get_type()) << " " << tmpvar << ";" << endl; generate_deserialize_field(out, (*f_iter), tmpvar, true); out << indent() << tmpRetval << " = new " << (*f_iter)->get_name() << "(" << tmpvar << ");" << endl; indent_down(); out << indent() << "} else { " << endl << indent() << " await TProtocolUtil.SkipAsync(iprot, field.Type, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << " " << tmpRetval << " = new ___undefined();" << endl << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } out << indent() << "default: " << endl; indent_up(); out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, " << CANCELLATION_TOKEN_NAME << ");" << endl << indent() << tmpRetval << " = new ___undefined();" << endl; out << indent() << "break;" << endl; indent_down(); scope_down(out); out << indent() << "await iprot.ReadFieldEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; out << indent() << "if ((await iprot.ReadFieldBeginAsync(" << CANCELLATION_TOKEN_NAME << ")).Type != TType.Stop)" << endl; scope_up(out); out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; scope_down(out); // end of else for TStop scope_down(out); out << indent() << "await iprot.ReadStructEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; out << indent() << "return " << tmpRetval << ";" << endl; indent_down(); scope_down(out); out << indent() << "finally" << endl; scope_up(out); out << indent() << "iprot.DecrementRecursionDepth();" << endl; scope_down(out); out << indent() << "}" << endl << endl; } void t_netstd_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless) { t_type* type = tfield->get_type(); type = resolve_typedef( type); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + (is_propertyless ? "" : prop_name(tfield)); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, static_cast(type), name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { out << indent() << name << " = "; if (type->is_enum()) { out << "(" << type_name(type) << ")"; } out << "await iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = static_cast(type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "ReadBinaryAsync(" << CANCELLATION_TOKEN_NAME << ");"; } else { out << "ReadStringAsync(" << CANCELLATION_TOKEN_NAME << ");"; } break; case t_base_type::TYPE_UUID: out << "ReadUuidAsync(" << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_BOOL: out << "ReadBoolAsync(" << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I8: out << "ReadByteAsync(" << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I16: out << "ReadI16Async(" << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I32: out << "ReadI32Async(" << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I64: out << "ReadI64Async(" << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_DOUBLE: out << "ReadDoubleAsync(" << CANCELLATION_TOKEN_NAME << ");"; break; default: throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "ReadI32Async(" << CANCELLATION_TOKEN_NAME << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); } } void t_netstd_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { if (is_union_enabled() && tstruct->is_union()) { out << indent() << prefix << " = await " << type_name(tstruct) << ".ReadAsync(iprot, " << CANCELLATION_TOKEN_NAME << ");" << endl; } else { out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent() << "await " << prefix << ".ReadAsync(iprot, " << CANCELLATION_TOKEN_NAME << ");" << endl; } } void t_netstd_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { out << indent() << "{" << endl; indent_up(); string obj; if (ttype->is_map()) { obj = tmp("_map"); } else if (ttype->is_set()) { obj = tmp("_set"); } else if (ttype->is_list()) { obj = tmp("_list"); } if (ttype->is_map()) { out << indent() << "var " << obj << " = await iprot.ReadMapBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_set()) { out << indent() << "var " << obj << " = await iprot.ReadSetBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_list()) { out << indent() << "var " << obj << " = await iprot.ReadListBeginAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } out << indent() << prefix << " = new " << type_name(ttype) << "(" << obj << ".Count);" << endl; string i = tmp("_i"); out << indent() << "for(int " << i << " = 0; " << i << " < " << obj << ".Count; ++" << i << ")" << endl << indent() << "{" << endl; indent_up(); if (ttype->is_map()) { generate_deserialize_map_element(out, static_cast(ttype), prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, static_cast(ttype), prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, static_cast(ttype), prefix); } indent_down(); out << indent() << "}" << endl; if (ttype->is_map()) { out << indent() << "await iprot.ReadMapEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_set()) { out << indent() << "await iprot.ReadSetEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_list()) { out << indent() << "await iprot.ReadListEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } indent_down(); out << indent() << "}" << endl; } void t_netstd_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); out << indent() << declare_field(&fkey, false, false) << endl; out << indent() << declare_field(&fval, false, false) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); out << indent() << prefix << "[" << key << "] = " << val << ";" << endl; } void t_netstd_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); out << indent() << declare_field(&felem, false, false) << endl; generate_deserialize_field(out, &felem); out << indent() << prefix << ".Add(" << elem << ");" << endl; } void t_netstd_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); out << indent() << declare_field(&felem, false, false) << endl; generate_deserialize_field(out, &felem); out << indent() << prefix << ".Add(" << elem << ");" << endl; } void t_netstd_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless, bool allow_nullable) { t_type* type = tfield->get_type(); type = resolve_typedef( type); string name = prefix + (is_propertyless ? "" : prop_name(tfield)); string nullable_name = name + (allow_nullable ? nullable_value_access(type) : ""); if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, static_cast(type), name); } else if (type->is_container()) { generate_serialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { out << indent() << "await oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = static_cast(type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "WriteBinaryAsync("; } else { out << "WriteStringAsync("; } out << name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_UUID: out << "WriteUuidAsync(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_BOOL: out << "WriteBoolAsync(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I8: out << "WriteByteAsync(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I16: out << "WriteI16Async(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I32: out << "WriteI32Async(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_I64: out << "WriteI64Async(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; case t_base_type::TYPE_DOUBLE: out << "WriteDoubleAsync(" << nullable_name << ", " << CANCELLATION_TOKEN_NAME << ");"; break; default: throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "WriteI32Async((int)" << name << ", " << CANCELLATION_TOKEN_NAME << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type_name(type).c_str()); } } void t_netstd_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; out << indent() << "await " << prefix << ".WriteAsync(oprot, " << CANCELLATION_TOKEN_NAME << ");" << endl; } void t_netstd_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { if (ttype->is_map()) { out << indent() << "await oprot.WriteMapBeginAsync(new TMap(" << type_to_enum(static_cast(ttype)->get_key_type()) << ", " << type_to_enum(static_cast(ttype)->get_val_type()) << ", " << prefix << ".Count), " << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_set()) { out << indent() << "await oprot.WriteSetBeginAsync(new TSet(" << type_to_enum(static_cast(ttype)->get_elem_type()) << ", " << prefix << ".Count), " << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_list()) { out << indent() << "await oprot.WriteListBeginAsync(new TList(" << type_to_enum(static_cast(ttype)->get_elem_type()) << ", " << prefix << ".Count), " << CANCELLATION_TOKEN_NAME << ");" << endl; } string iter = tmp("_iter"); if (ttype->is_map()) { out << indent() << "foreach (" << type_name(static_cast(ttype)->get_key_type()) << " " << iter << " in " << prefix << ".Keys)"; } else if (ttype->is_set()) { out << indent() << "foreach (" << type_name(static_cast(ttype)->get_elem_type()) << " " << iter << " in " << prefix << ")"; } else if (ttype->is_list()) { out << indent() << "foreach (" << type_name(static_cast(ttype)->get_elem_type()) << " " << iter << " in " << prefix << ")"; } out << endl; out << indent() << "{" << endl; indent_up(); if (ttype->is_map()) { generate_serialize_map_element(out, static_cast(ttype), iter, prefix); } else if (ttype->is_set()) { generate_serialize_set_element(out, static_cast(ttype), iter); } else if (ttype->is_list()) { generate_serialize_list_element(out, static_cast(ttype), iter); } indent_down(); out << indent() << "}" << endl; if (ttype->is_map()) { out << indent() << "await oprot.WriteMapEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_set()) { out << indent() << "await oprot.WriteSetEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } else if (ttype->is_list()) { out << indent() << "await oprot.WriteListEndAsync(" << CANCELLATION_TOKEN_NAME << ");" << endl; } } void t_netstd_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map) { t_field kfield(tmap->get_key_type(), iter); generate_serialize_field(out, &kfield, "", false, false); t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); generate_serialize_field(out, &vfield, "", false, false); } void t_netstd_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, "", false, false); } void t_netstd_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, "", false, false); } void t_netstd_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset) { generate_netstd_property(out, tfield, isPublic, generateIsset, "_"); } void t_netstd_generator::generate_netstd_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset, string fieldPrefix) { if ((is_serialize_enabled() || is_wcf_enabled()) && isPublic) { out << indent() << "[DataMember(Order = 0)]" << endl; } out << indent() << (isPublic ? "public " : "private ") << type_name(tfield->get_type()) << nullable_field_suffix(tfield) << " " << prop_name(tfield) ; bool is_required = field_is_required(tfield); if (is_required) { out << " { get; set; }"; if( use_net6_features && (!force_member_nullable(tfield))) { out << initialize_field(tfield) << ";"; } out << endl; } else { out << endl << indent() << "{" << endl; indent_up(); out << indent() << "get" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return " << fieldPrefix + tfield->get_name() << ";" << endl; indent_down(); out << indent() << "}" << endl << indent() << "set" << endl << indent() << "{" << endl; indent_up(); if (generateIsset) { out << indent() << "__isset." << get_isset_name(normalize_name(tfield->get_name())) << " = true;" << endl; } out << indent() << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; } out << endl; } string t_netstd_generator::make_csharp_string_literal( string const& value) { if (value.length() == 0) { return ""; } std::stringstream result; result << "\""; for (signed char const c: value) { if( (c >= 0) && (c < 32)) { // convert ctrl chars, but leave UTF-8 alone int width = std::max( (int)sizeof(c), 4); result << "\\x" << std::hex << std::setw(width) << std::setfill('0') << (int)c; } else if ((c == '\\') || (c == '"')) { result << "\\" << c; } else { result << c; // anything else "as is" } } result << "\""; return result.str(); } string t_netstd_generator::make_valid_csharp_identifier(string const& fromName) { string str = fromName; if (str.empty()) { return str; } // tests rely on this assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); // if the first letter is a number, we add an additional underscore in front of it char c = str.at(0); if (('0' <= c) && (c <= '9')) { str = "_" + str; } // following chars: letter, number or underscore for (size_t i = 0; i < str.size(); ++i) { c = str.at(i); if (('A' > c || c > 'Z') && ('a' > c || c > 'z') && ('0' > c || c > '9') && '_' != c) { str.replace(i, 1, "_"); } } return str; } void t_netstd_generator::cleanup_member_name_mapping(void* scope) { if (member_mapping_scopes.empty()) { throw "internal error: cleanup_member_name_mapping() no scope active"; } member_mapping_scope& active = member_mapping_scopes.back(); if (active.scope_member != scope) { throw "internal error: cleanup_member_name_mapping() called for wrong struct"; } member_mapping_scopes.pop_back(); } string t_netstd_generator::get_mapped_member_name(string name) { if (!member_mapping_scopes.empty()) { member_mapping_scope& active = member_mapping_scopes.back(); map::iterator iter = active.mapping_table.find(name); if (active.mapping_table.end() != iter) { return iter->second; } } pverbose("no mapping for member %s\n", name.c_str()); return name; } void t_netstd_generator::prepare_member_name_mapping(t_service* tservice) { prepare_member_name_mapping(tservice, tservice->get_functions(), tservice->get_name()); } void t_netstd_generator::prepare_member_name_mapping(t_struct* tstruct) { prepare_member_name_mapping(tstruct, tstruct->get_members(), tstruct->get_name()); } void t_netstd_generator::prepare_member_name_mapping(t_struct* scope, const vector& members, const string& structname) { // begin new scope member_mapping_scopes.emplace_back(); member_mapping_scope& active = member_mapping_scopes.back(); active.scope_member = scope; // current C# generator policy: // - prop names are always rendered with an Uppercase first letter // - struct names are used as given std::set used_member_names; vector::const_iterator iter; // prevent name conflicts with struct (CS0542 error + THRIFT-2942) used_member_names.insert(structname); used_member_names.insert("Isset"); used_member_names.insert("Read"); used_member_names.insert("Write"); for (iter = members.begin(); iter != members.end(); ++iter) { string oldname = (*iter)->get_name(); string newname = prop_name(*iter, true); while (true) { // new name conflicts with another member if (used_member_names.find(newname) != used_member_names.end()) { pverbose("struct %s: member %s conflicts with another member\n", structname.c_str(), newname.c_str()); newname += '_'; continue; } // add always, this helps us to detect edge cases like // different spellings ("foo" and "Foo") within the same struct pverbose("struct %s: member mapping %s => %s\n", structname.c_str(), oldname.c_str(), newname.c_str()); active.mapping_table[oldname] = newname; used_member_names.insert(newname); break; } } } void t_netstd_generator::prepare_member_name_mapping(t_service* scope, const vector& members, const string& structname) { // begin new scope member_mapping_scopes.emplace_back(); member_mapping_scope& active = member_mapping_scopes.back(); active.scope_member = scope; // current C# generator policy: // - prop names are always rendered with an Uppercase first letter // - struct names are used as given std::set used_member_names; vector::const_iterator iter; // prevent name conflicts with service/intf used_member_names.insert(structname); used_member_names.insert("Client"); used_member_names.insert("IAsync"); used_member_names.insert("AsyncProcessor"); used_member_names.insert("InternalStructs"); for (iter = members.begin(); iter != members.end(); ++iter) { string oldname = (*iter)->get_name(); string newname = func_name(*iter, true); while (true) { // new name conflicts with another method if (used_member_names.find(newname) != used_member_names.end()) { pverbose("service %s: method %s conflicts with another method\n", structname.c_str(), newname.c_str()); newname += '_'; continue; } // add always, this helps us to detect edge cases like // different spellings ("foo" and "Foo") within the same service pverbose("service %s: method mapping %s => %s\n", structname.c_str(), oldname.c_str(), newname.c_str()); active.mapping_table[oldname] = newname; used_member_names.insert(newname); break; } } } string t_netstd_generator::convert_to_pascal_case(const string& str) { string out; bool must_capitalize = true; bool first_character = true; for (auto it = str.begin(); it != str.end(); ++it) { if (std::isalnum(*it)) { if (must_capitalize) { out.append(1, (char)::toupper(*it)); must_capitalize = false; } else { out.append(1, *it); } } else { if (first_character) //this is a private variable and should not be PascalCased return str; must_capitalize = true; } first_character = false; } return out; } string t_netstd_generator::get_isset_name(const string& str) { return ("Isset" != str) ? str : str + "_"; } string t_netstd_generator::prop_name(t_field* tfield, bool suppress_mapping) { string name(tfield->get_name()); if (suppress_mapping) { name[0] = toupper(name[0]); if (use_pascal_case_properties) name = t_netstd_generator::convert_to_pascal_case(name); } else { name = get_mapped_member_name(name); } return name; } string t_netstd_generator::func_name(t_function* tfunc, bool suppress_mapping) { return func_name(tfunc->get_name(), suppress_mapping); } string t_netstd_generator::func_name(std::string fname, bool suppress_mapping) { if (suppress_mapping) { return fname; } return get_mapped_member_name(fname); } bool t_netstd_generator::is_nullable_type(t_type* ttype) { ttype = resolve_typedef(ttype); if (ttype->is_enum()) { return false; } if (ttype->is_base_type()) { t_base_type::t_base tbase = static_cast(ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: return true; // both binary and string default: return false; } } return true; } string t_netstd_generator::nullable_suffix() { if(use_net6_features) { return "?"; } else { return ""; } } string t_netstd_generator::nullable_field_suffix(t_field* tfield) { if(field_is_required(tfield) && (!force_member_nullable(tfield))) return ""; else return nullable_field_suffix(tfield->get_type()); } string t_netstd_generator::nullable_field_suffix(t_type* ttype) { if( ! use_net6_features) { return ""; } ttype = resolve_typedef(ttype); if (ttype->is_enum()) { return ""; } if (ttype->is_base_type()) { t_base_type::t_base tbase = static_cast(ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: return nullable_suffix(); default: return ""; } } return nullable_suffix(); } string t_netstd_generator::nullable_value_access(t_type* ttype) { if( ! use_net6_features) return ""; ttype = resolve_typedef(ttype); // this code uses the null-forgiving operator and therefore assumes that the variable // has been properly checked against an isset guard or null if (ttype->is_base_type()) { t_base_type::t_base tbase = static_cast(ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: return "!"; default: return ""; } } if (ttype->is_container() || ttype->is_struct() || ttype->is_xception()) { return "!"; } return ""; } bool t_netstd_generator::force_member_nullable(t_field* tfield) { // IMPORTANT: // If tfield is a struct that contains a required field of the same type (directly or indirectly), // auto-initializing such a member field would immediately produce an OOM, or at least unexpectedly // allocate potentially large amounts of memory -> ALWAYS leave containers and struct members nullable t_type* ttype = resolve_typedef(tfield->get_type()); return ttype->is_struct() || ttype->is_container(); } string t_netstd_generator::type_name(t_type* ttype, bool with_namespace) { ttype = resolve_typedef(ttype); if (ttype->is_base_type()) { return base_type_name(static_cast(ttype)); } if (ttype->is_map()) { t_map* tmap = static_cast(ttype); return "Dictionary<" + type_name(tmap->get_key_type()) + ", " + type_name(tmap->get_val_type()) + ">"; } if (ttype->is_set()) { t_set* tset = static_cast(ttype); return "HashSet<" + type_name(tset->get_elem_type()) + ">"; } if (ttype->is_list()) { t_list* tlist = static_cast(ttype); return "List<" + type_name(tlist->get_elem_type()) + ">"; } string the_name = normalize_name(ttype->get_name()); if(with_namespace) { t_program* program = ttype->get_program(); if (program != nullptr)// && program != program_) { string ns = program->get_namespace("netstd"); if (!ns.empty()) { return "global::" + ns + "." + the_name; } } } return the_name; } string t_netstd_generator::base_type_name(t_base_type* tbase) { switch (tbase->get_base()) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: if (tbase->is_binary()) { return "byte[]"; } else { return "string"; } case t_base_type::TYPE_UUID: return "global::System.Guid"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "sbyte"; case t_base_type::TYPE_I16: return "short"; case t_base_type::TYPE_I32: return "int"; case t_base_type::TYPE_I64: return "long"; case t_base_type::TYPE_DOUBLE: return "double"; default: throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase->get_base()); } } string t_netstd_generator::get_deep_copy_method_call(t_type* ttype, bool is_not_null, bool& needs_typecast, string& suffix) { ttype = resolve_typedef(ttype); // if is_not_null is set, then the surrounding code already explicitly tests against != null string null_check(""); suffix = ""; needs_typecast = false; if (ttype->is_base_type()) { t_base_type::t_base tbase = static_cast(ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (ttype->is_binary()) { suffix = nullable_suffix(); if( use_net6_features) { null_check = is_not_null ? "!" : " ?? Array.Empty()"; } return ".ToArray()" + null_check; } else { if( use_net6_features) { null_check = is_not_null ? "!" : " ?? string.Empty"; } return null_check; // simple assignment will do, strings are immutable in C# } break; default: return ""; // simple assignment will do } } else if (ttype->is_enum()) { return ""; // simple assignment will do } else if (is_union_enabled() && ttype->is_struct() && static_cast(ttype)->is_union()) { needs_typecast = (! ttype->is_container()); suffix = nullable_suffix(); if( use_net6_features) { null_check = is_not_null ? "!" : " ?? new "+ttype->get_name() +".___undefined()"; } return "." + DEEP_COPY_METHOD_NAME + "()" + null_check; } else { needs_typecast = (! ttype->is_container()); suffix = nullable_suffix(); if( use_net6_features) { null_check = is_not_null ? "!" : " ?? new()"; } return "." + DEEP_COPY_METHOD_NAME + "()" + null_check; } throw "UNEXPECTED TYPE IN get_deep_copy_method_call: " + ttype->get_name(); } string t_netstd_generator::declare_field(t_field* tfield, bool init, bool allow_nullable, string prefix) { string result = type_name(tfield->get_type()) + (allow_nullable ? nullable_field_suffix(tfield) : "") + " " + prefix + tfield->get_name() ; if (init) { result += initialize_field(tfield); } return result + ";"; } string t_netstd_generator::initialize_field(t_field* tfield) { t_type* ttype = tfield->get_type(); ttype = resolve_typedef(ttype); if (ttype->is_base_type() && field_has_default(tfield)) { std::ofstream dummy; return " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value()); } else if (force_member_nullable(tfield)) { return ""; // see force_member_nullable() why this is necessary } else if (ttype->is_base_type()) { t_base_type::t_base tbase = static_cast(ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: if(use_net6_features && field_is_required(tfield)) { if (ttype->is_binary()) { return " = Array.Empty()"; } else { return " = string.Empty"; } } else { return " = null"; } break; case t_base_type::TYPE_UUID: return " = System.Guid.Empty"; break; case t_base_type::TYPE_BOOL: return " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return " = 0"; break; case t_base_type::TYPE_DOUBLE: return " = 0.0"; break; } } else if (ttype->is_enum()) { return " = default"; } else if (ttype->is_container()) { if(use_net6_features) { return " = new()"; } else { return " = new " + type_name(ttype) + "()"; } } else if (ttype->is_struct()) { t_struct* tstruct = static_cast(ttype); if(use_net6_features) { if(tstruct->is_union()) { return " = new " + type_name(ttype) + ".___undefined()"; } else { return " = new()"; } } else { return " = new " + type_name(ttype) + "()"; } } throw "UNEXPECTED TYPE IN initialize_field: " + ttype->get_name(); } string t_netstd_generator::function_signature(t_function* tfunction, string prefix) { t_type* ttype = tfunction->get_returntype(); return type_name(ttype) + " " + func_name(normalize_name(prefix + tfunction->get_name())) + "(" + argument_list(tfunction->get_arglist()) + ")"; } string t_netstd_generator::function_signature_async(t_function* tfunction, string prefix, int mode) { t_type* ttype = tfunction->get_returntype(); string task = "global::System.Threading.Tasks.Task"; if ((!ttype->is_void()) && ((mode & MODE_NO_RETURN) == 0)) { task += "<" + type_name(ttype) + ">"; } string result = task + " " + func_name(normalize_name(prefix + tfunction->get_name()) + (add_async_postfix ? "Async" : "")) + "("; if((mode & MODE_NO_ARGS) == 0) { string args = argument_list(tfunction->get_arglist()); result += args; if (!args.empty()) { result += ", "; } } result += "CancellationToken " + CANCELLATION_TOKEN_NAME + " = default)"; return result; } string t_netstd_generator::argument_list(t_struct* tstruct, bool with_types) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } if( with_types) { result += type_name((*f_iter)->get_type()) + nullable_field_suffix(*f_iter) + " "; } result += normalize_name((*f_iter)->get_name(),true); } return result; } string t_netstd_generator::type_to_enum(t_type* type) { type = resolve_typedef( type); if (type->is_base_type()) { t_base_type::t_base tbase = static_cast(type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.String"; case t_base_type::TYPE_UUID: return "TType.Uuid"; case t_base_type::TYPE_BOOL: return "TType.Bool"; case t_base_type::TYPE_I8: return "TType.Byte"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.Double"; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.Struct"; } else if (type->is_map()) { return "TType.Map"; } else if (type->is_set()) { return "TType.Set"; } else if (type->is_list()) { return "TType.List"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } void t_netstd_generator::generate_netstd_docstring_comment(ostream& out, string contents) { docstring_comment(out, "/// " + endl, "/// ", contents, "/// " + endl); } void t_netstd_generator::generate_netstd_doc(ostream& out, t_field* field) { if (field->get_type()->is_enum()) { string combined_message = field->get_doc() + endl + "get_type()) + "\"/>"; generate_netstd_docstring_comment(out, combined_message); } else { generate_netstd_doc(out, static_cast(field)); } } void t_netstd_generator::generate_netstd_doc(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_netstd_docstring_comment(out, tdoc->get_doc()); } } void t_netstd_generator::generate_netstd_doc(ostream& out, t_function* tfunction) { if (tfunction->has_doc()) { stringstream ps; const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ps << endl << "get_name() << "\">"; if (p->has_doc()) { string str = p->get_doc(); str.erase(remove(str.begin(), str.end(), '\n'), str.end()); ps << str; } ps << ""; } docstring_comment(out, "", "/// ", "" + endl + tfunction->get_doc() + "" + ps.str(), ""); } } void t_netstd_generator::docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end) { if (comment_start != "") { out << indent() << comment_start; } stringstream docs(contents, std::ios_base::in); while (!(docs.eof() || docs.fail())) { char line[1024]; docs.getline(line, 1024); // Just prnt a newline when the line & prefix are empty. if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) { out << endl; } else if (strlen(line) > 0 || !docs.eof()) { // skip the empty last line out << indent() << line_prefix << line << endl; } } if (comment_end != "") { out << indent() << comment_end; } } string t_netstd_generator::get_enum_class_name(t_type* type) { string package = ""; t_program* program = type->get_program(); if (program != nullptr) // && program != program_) { package = program->get_namespace("netstd") + "."; } return "global::" + package + type->get_name(); } std::string t_netstd_generator::display_name() const { return "C#"; } THRIFT_REGISTER_GENERATOR( netstd, "C#", " wcf: Adds bindings for WCF to generated classes.\n" " serial: Add serialization support to generated classes.\n" " union: Use new union typing, which includes a static read function for union types.\n" " pascal: Generate Pascal Case property names according to Microsoft naming convention.\n" " net6: Enable features that require net6 and C# 8 or higher.\n" " no_deepcopy: Suppress generation of " + DEEP_COPY_METHOD_NAME + "() method.\n" " async_postfix: Append \"Async\" to all service methods (maintains compatibility with existing code).\n" ) thrift-0.19.0/compiler/cpp/src/thrift/generate/t_xml_generator.cc0000644000000000000000000004760014370300523025060 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; using std::stack; using std::set; static const string endl = "\n"; static const string quot = "\""; static const string default_ns_prefix = "http://thrift.apache.org/xml/ns/"; /** * This generator creates an XML model of the parsed IDL tree, and is designed * to make it easy to use this file as the input for other template engines, * such as XSLT. To this end, the generated XML is slightly more verbose than * you might expect... for example, references to "id" types (such as structs, * unions, etc) always specify the name of the IDL document, even if the type * is defined in the same document as the reference. */ class t_xml_generator : public t_generator { public: t_xml_generator( t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; should_merge_includes_ = false; should_use_default_ns_ = true; should_use_namespaces_ = true; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("merge") == 0) { should_merge_includes_ = true; } else if( iter->first.compare("no_default_ns") == 0) { should_use_default_ns_ = false; } else if( iter->first.compare("no_namespaces") == 0) { should_use_namespaces_ = false; } else { throw "unknown option xml:" + iter->first; } } out_dir_base_ = "gen-xml"; } ~t_xml_generator() override = default; void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_program() override; void iterate_program(t_program* program); void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_function(t_function* tfunc); void generate_field(t_field* field); void generate_service(t_service* tservice) override; void generate_struct(t_struct* tstruct) override; void generate_annotations(std::map> annotations); private: bool should_merge_includes_; bool should_use_default_ns_; bool should_use_namespaces_; ofstream_with_content_based_conditional_update f_xml_; std::set programs_; std::stack elements_; bool top_element_is_empty; bool top_element_is_open; string target_namespace(t_program* program); void write_element_start(const string name); void close_top_element(); void write_element_end(); void write_attribute(string key, string val); void write_int_attribute(string key, int val); string escape_xml_string(const string& input); void write_xml_comment(string msg); void write_type(t_type* ttype); void write_doc(t_doc* tdoc); template string number_to_string(T t) { std::ostringstream out; out.imbue(std::locale::classic()); out.precision(std::numeric_limits::digits10); out << t; return out.str(); } template void write_number(T n) { f_xml_ << number_to_string(n); } template void write_element_number(string name, T n) { write_element_string(name, number_to_string(n)); } string get_type_name(t_type* ttype); void generate_constant(t_const* con); void write_element_string(string name, string value); void write_value(t_type* tvalue); void write_const_value(t_const_value* value); virtual std::string xml_autogen_comment() { return std::string("\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"; } }; void t_xml_generator::init_generator() { MKDIR(get_out_dir().c_str()); string f_xml_name = get_out_dir() + program_->get_name() + ".xml"; f_xml_.open(f_xml_name.c_str()); top_element_is_open = false; } string t_xml_generator::target_namespace(t_program* program) { std::map map; std::map::iterator iter; std::map> annotations; std::map>::iterator annotations_iter; annotations = program->get_namespace_annotations("xml"); if ((annotations_iter = annotations.find("targetNamespace")) != annotations.end()) { if (!annotations_iter->second.empty()) { return annotations_iter->second.back(); } } map = program->get_namespaces(); if ((iter = map.find("xml")) != map.end()) { return default_ns_prefix + iter->second; } annotations = program->get_namespace_annotations("*"); if ((annotations_iter = annotations.find("xml.targetNamespace")) != annotations.end()) { if (!annotations_iter->second.empty()) { return annotations_iter->second.back(); } } map = program->get_namespaces(); if ((iter = map.find("*")) != map.end()) { return default_ns_prefix + iter->second; } return default_ns_prefix + program->get_name(); } void t_xml_generator::write_xml_comment(string msg) { close_top_element(); // TODO: indent any EOLs that may occur with msg // TODO: proper msg escaping needed? f_xml_ << indent() << "" << endl; top_element_is_empty = false; } void t_xml_generator::close_top_element() { if( top_element_is_open) { top_element_is_open = false; if (elements_.size() > 0 && top_element_is_empty) { f_xml_ << ">" << endl; } } } void t_xml_generator::write_element_start(string name) { if (should_use_namespaces_ && !should_use_default_ns_) { name = "idl:" + name; } close_top_element(); f_xml_ << indent() << "<" << name; elements_.push(name); top_element_is_empty = true; top_element_is_open = true; indent_up(); } void t_xml_generator::write_element_end() { indent_down(); if (top_element_is_empty && top_element_is_open) { f_xml_ << " />" << endl; } else { f_xml_ << indent() << "" << endl; } top_element_is_empty = false; elements_.pop(); } void t_xml_generator::write_attribute(string key, string val) { f_xml_ << " " << key << "=\"" << escape_xml_string(val) << "\""; } void t_xml_generator::write_int_attribute(string key, int val) { write_attribute(key, number_to_string(val)); } void t_xml_generator::write_element_string(string name, string val) { if (should_use_namespaces_ && !should_use_default_ns_) { name = "idl:" + name; } close_top_element(); top_element_is_empty = false; f_xml_ << indent() << "<" << name << ">" << escape_xml_string(val) << "" << endl; } string t_xml_generator::escape_xml_string(const string& input) { std::ostringstream ss; for (char iter : input) { switch (iter) { case '&': ss << "&"; break; case '"': ss << """; break; case '\'': ss << "'"; break; case '<': ss << "<"; break; case '>': ss << ">"; break; default: ss << iter; break; } } return ss.str(); } void t_xml_generator::close_generator() { f_xml_.close(); } void t_xml_generator::generate_program() { init_generator(); write_element_start("idl"); if (should_use_namespaces_) { if (should_use_default_ns_) { write_attribute("xmlns", "http://thrift.apache.org/xml/idl"); } write_attribute("xmlns:idl", "http://thrift.apache.org/xml/idl"); } write_xml_comment( xml_autogen_comment()); iterate_program(program_); write_element_end(); close_generator(); } void t_xml_generator::iterate_program(t_program* program) { write_element_start("document"); write_attribute("name", program->get_name()); if (should_use_namespaces_) { const string targetNamespace = target_namespace(program); write_attribute("targetNamespace", targetNamespace); write_attribute("xmlns:" + program->get_name(), targetNamespace); } write_doc(program); const vector includes = program->get_includes(); vector::const_iterator inc_it; for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) { write_element_start("include"); write_attribute("name", (*inc_it)->get_name()); write_element_end(); } const map& namespaces = program->get_namespaces(); map::const_iterator ns_it; for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) { write_element_start("namespace"); write_attribute("name", ns_it->first); write_attribute("value", ns_it->second); generate_annotations(program->get_namespace_annotations(ns_it->first)); write_element_end(); } // TODO: can constants have annotations? vector consts = program->get_consts(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { generate_constant(*c_iter); } vector typedefs = program->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { generate_typedef(*td_iter); } vector enums = program->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { generate_enum(*en_iter); } vector objects = program->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { if ((*o_iter)->is_xception()) { generate_xception(*o_iter); } else { generate_struct(*o_iter); } } vector services = program->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { generate_service(*sv_iter); } write_element_end(); if (should_merge_includes_) { programs_.insert(program->get_name()); const vector programs = program->get_includes(); vector::const_iterator prog_it; for (prog_it = programs.begin(); prog_it != programs.end(); ++prog_it) { if (!programs_.count((*prog_it)->get_name())) { iterate_program(*prog_it); } } } } void t_xml_generator::generate_typedef(t_typedef* ttypedef) { write_element_start("typedef"); write_attribute("name", ttypedef->get_name()); write_doc(ttypedef); write_type(ttypedef->get_true_type()); generate_annotations(ttypedef->annotations_); write_element_end(); return; } void t_xml_generator::write_type(t_type* ttype) { const string type = get_type_name(ttype); write_attribute("type", type); if (type == "id") { write_attribute("type-module", ttype->get_program()->get_name()); write_attribute("type-id", ttype->get_name()); } else if (type == "list") { t_type* etype = ((t_list*)ttype)->get_elem_type(); write_element_start("elemType"); write_type(etype); write_element_end(); } else if (type == "set") { t_type* etype = ((t_set*)ttype)->get_elem_type(); write_element_start("elemType"); write_type(etype); write_element_end(); } else if (type == "map") { t_type* ktype = ((t_map*)ttype)->get_key_type(); write_element_start("keyType"); write_type(ktype); write_element_end(); t_type* vtype = ((t_map*)ttype)->get_val_type(); write_element_start("valueType"); write_type(vtype); write_element_end(); } } void t_xml_generator::write_doc(t_doc* tdoc) { if (tdoc->has_doc()) { string doc = tdoc->get_doc(); // for some reason there always seems to be a trailing newline on doc // comments; loop below naively tries to strip off trailing cr/lf int n = 0; for (string::reverse_iterator i = doc.rbegin(); i != doc.rend(); i++,n++) { if (*i != '\n' || *i == '\r') { if (n > 0) { doc.erase(doc.length() - n); } break; } } write_attribute("doc", doc); } } void t_xml_generator::generate_annotations( std::map> annotations) { std::map>::iterator iter; for (iter = annotations.begin(); iter != annotations.end(); ++iter) { for (auto& annotations_value : iter->second) { write_element_start("annotation"); write_attribute("key", iter->first); write_attribute("value", annotations_value); write_element_end(); } } } void t_xml_generator::generate_constant(t_const* con) { write_element_start("const"); write_attribute("name", con->get_name()); write_doc(con); write_type(con->get_type()); write_const_value(con->get_value()); write_element_end(); } void t_xml_generator::write_const_value(t_const_value* value) { switch (value->get_type()) { case t_const_value::CV_IDENTIFIER: case t_const_value::CV_INTEGER: write_element_number("int", value->get_integer()); break; case t_const_value::CV_DOUBLE: write_element_number("double", value->get_double()); break; case t_const_value::CV_STRING: write_element_string("string", value->get_string()); break; case t_const_value::CV_LIST: { write_element_start("list"); std::vector list = value->get_list(); std::vector::iterator lit; for (lit = list.begin(); lit != list.end(); ++lit) { write_element_start("entry"); write_const_value(*lit); write_element_end(); } write_element_end(); break; } case t_const_value::CV_MAP: { write_element_start("map"); std::map map = value->get_map(); std::map::iterator mit; for (mit = map.begin(); mit != map.end(); ++mit) { write_element_start("entry"); write_element_start("key"); write_const_value(mit->first); write_element_end(); write_element_start("value"); write_const_value(mit->second); write_element_end(); write_element_end(); } write_element_end(); break; } default: indent_up(); f_xml_ << indent() << "" << endl; indent_down(); break; } } void t_xml_generator::generate_enum(t_enum* tenum) { write_element_start("enum"); write_attribute("name", tenum->get_name()); write_doc(tenum); vector values = tenum->get_constants(); vector::iterator val_iter; for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) { t_enum_value* val = (*val_iter); write_element_start("member"); write_attribute("name", val->get_name()); write_int_attribute("value", val->get_value()); write_doc(val); generate_annotations(val->annotations_); write_element_end(); } generate_annotations(tenum->annotations_); write_element_end(); } void t_xml_generator::generate_struct(t_struct* tstruct) { string tagname = "struct"; if (tstruct->is_union()) { tagname = "union"; } else if (tstruct->is_xception()) { tagname = "exception"; } write_element_start(tagname); write_attribute("name", tstruct->get_name()); write_doc(tstruct); vector members = tstruct->get_members(); vector::iterator mem_iter; for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) { write_element_start("field"); generate_field(*mem_iter); write_element_end(); } generate_annotations(tstruct->annotations_); write_element_end(); } void t_xml_generator::generate_field(t_field* field) { write_attribute("name", field->get_name()); write_int_attribute("field-id", field->get_key()); write_doc(field); string requiredness; switch (field->get_req()) { case t_field::T_REQUIRED: requiredness = "required"; break; case t_field::T_OPTIONAL: requiredness = "optional"; break; default: requiredness = ""; break; } if (requiredness != "") { write_attribute("required", requiredness); } write_type(field->get_type()); if (field->get_value()) { write_element_start("default"); write_const_value(field->get_value()); write_element_end(); } generate_annotations(field->annotations_); } void t_xml_generator::generate_service(t_service* tservice) { write_element_start("service"); write_attribute("name", tservice->get_name()); if (should_use_namespaces_) { string prog_ns = target_namespace(tservice->get_program()); if (*prog_ns.rbegin() != '/') { prog_ns.push_back('/'); } const string tns = prog_ns + tservice->get_name(); write_attribute("targetNamespace", tns); write_attribute("xmlns:tns", tns); } if (tservice->get_extends()) { const t_service* extends = tservice->get_extends(); write_attribute("parent-module", extends->get_program()->get_name()); write_attribute("parent-id", extends->get_name()); } write_doc(tservice); vector functions = tservice->get_functions(); vector::iterator fn_iter = functions.begin(); for (; fn_iter != functions.end(); fn_iter++) { generate_function(*fn_iter); } generate_annotations(tservice->annotations_); write_element_end(); } void t_xml_generator::generate_function(t_function* tfunc) { write_element_start("method"); write_attribute("name", tfunc->get_name()); if (tfunc->is_oneway()) { write_attribute("oneway", "true"); } write_doc(tfunc); write_element_start("returns"); write_type(tfunc->get_returntype()); write_element_end(); vector members = tfunc->get_arglist()->get_members(); vector::iterator mem_iter = members.begin(); for (; mem_iter != members.end(); mem_iter++) { write_element_start("arg"); generate_field(*mem_iter); write_element_end(); } vector excepts = tfunc->get_xceptions()->get_members(); vector::iterator ex_iter = excepts.begin(); for (; ex_iter != excepts.end(); ex_iter++) { write_element_start("throws"); generate_field(*ex_iter); write_element_end(); } generate_annotations(tfunc->annotations_); write_element_end(); } string t_xml_generator::get_type_name(t_type* ttype) { if (ttype->is_list()) { return "list"; } if (ttype->is_set()) { return "set"; } if (ttype->is_map()) { return "map"; } if ((ttype->is_enum() )|| (ttype->is_struct() )|| (ttype->is_typedef() )|| (ttype->is_xception())){ return "id"; } if (ttype->is_base_type()) { t_base_type* tbasetype = (t_base_type*)ttype; if (tbasetype->is_binary() ) { return "binary"; } return t_base_type::t_base_name(tbasetype->get_base()); } return "(unknown)"; } std::string t_xml_generator::display_name() const { return "XML"; } THRIFT_REGISTER_GENERATOR( xml, "XML", " merge: Generate output with included files merged\n" " no_default_ns: Omit default xmlns and add idl: prefix to all elements\n" " no_namespaces: Do not add namespace definitions to the XML model\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_perl_generator.cc0000644000000000000000000015706214370300523025226 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * PERL code generator. * */ class t_perl_generator : public t_oop_generator { public: t_perl_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program), f_types_use_includes_emitted_(false) { (void)option_string; std::map::const_iterator iter; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option perl:" + iter->first; } out_dir_base_ = "gen-perl"; escape_['$'] = "\\$"; escape_['@'] = "\\@"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); /** * Structs! */ void generate_perl_struct(t_struct* tstruct, bool is_exception); void generate_perl_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false); void generate_perl_struct_reader(std::ostream& out, t_struct* tstruct); void generate_perl_struct_writer(std::ostream& out, t_struct* tstruct); void generate_perl_function_helpers(t_function* tfunction); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_rest(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_processor(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); void generate_use_includes(std::ostream& os, bool& done, t_type *type, bool selfish); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", bool inclass = false); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); /** * Helper rendering functions */ std::string perl_includes(); std::string declare_field(t_field* tfield, bool init = false, bool obj = false); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string autogen_comment() override { return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n"; } void perl_namespace_dirs(t_program* p, std::list& dirs) { std::string ns = p->get_namespace("perl"); std::string::size_type loc; if (ns.size() > 0) { while ((loc = ns.find(".")) != std::string::npos) { dirs.push_back(ns.substr(0, loc)); ns = ns.substr(loc + 1); } } if (ns.size() > 0) { dirs.push_back(ns); } } std::string perl_namespace(t_program* p) { std::string ns = p->get_namespace("perl"); std::string result = ""; std::string::size_type loc; if (ns.size() > 0) { while ((loc = ns.find(".")) != std::string::npos) { result += ns.substr(0, loc); result += "::"; ns = ns.substr(loc + 1); } if (ns.size() > 0) { result += ns + "::"; } } return result; } std::string get_namespace_out_dir() { std::string outdir = get_out_dir(); std::list dirs; perl_namespace_dirs(program_, dirs); std::list::iterator it; for (it = dirs.begin(); it != dirs.end(); it++) { outdir += *it + "/"; } return outdir; } private: /** * File streams */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_consts_; ofstream_with_content_based_conditional_update f_helpers_; ofstream_with_content_based_conditional_update f_service_; bool f_types_use_includes_emitted_; }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_perl_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); string outdir = get_out_dir(); std::list dirs; perl_namespace_dirs(program_, dirs); std::list::iterator it; for (it = dirs.begin(); it != dirs.end(); it++) { outdir += *it + "/"; MKDIR(outdir.c_str()); } // Make output file string f_types_name = outdir + "Types.pm"; f_types_.open(f_types_name.c_str()); string f_consts_name = outdir + "Constants.pm"; f_consts_.open(f_consts_name.c_str()); // Print header f_types_ << autogen_comment() << perl_includes(); // Print header f_consts_ << autogen_comment() << "package " << perl_namespace(program_) << "Constants;" << endl << perl_includes() << endl; } /** * Prints standard java imports */ string t_perl_generator::perl_includes() { string inc; inc = "use 5.10.0;\n"; inc += "use strict;\n"; inc += "use warnings;\n"; inc += "use Thrift::Exception;\n"; inc += "use Thrift::MessageType;\n"; inc += "use Thrift::Type;\n\n"; return inc; } /** * Close up (or down) some filez. */ void t_perl_generator::close_generator() { // Close types file f_types_ << "1;" << endl; f_types_.close(); f_consts_ << "1;" << endl; f_consts_.close(); } /** * Generates a typedef. This is not done in PERL, types are all implicit. * * @param ttypedef The type definition */ void t_perl_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Generates code for an enumerated type. Since define is expensive to lookup * in PERL, we use a global array for this. * * @param tenum The enumeration */ void t_perl_generator::generate_enum(t_enum* tenum) { f_types_ << "package " << perl_namespace(program_) << tenum->get_name() << ";" << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); f_types_ << "use constant " << (*c_iter)->get_name() << " => " << value << ";" << endl; } } /** * Generate a constant value */ void t_perl_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); f_consts_ << "use constant " << name << " => "; f_consts_ << render_const_value(type, value); f_consts_ << ";" << endl << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_perl_generator::render_const_value(t_type* type, t_const_value* value) { std::ostringstream out; type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "1" : "0"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << perl_namespace(type->get_program()) << type->get_name() << "->new({" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } indent(out) << render_const_value(g_type_string, v_iter->first); out << " => "; out << render_const_value(field_type, v_iter->second); out << ","; out << endl; } indent_down(); indent(out) << "})"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); out << "{" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { indent(out) << render_const_value(ktype, v_iter->first); out << " => "; out << render_const_value(vtype, v_iter->second); out << "," << endl; } indent_down(); indent(out) << "}"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } out << "[" << endl; indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { indent(out) << render_const_value(etype, *v_iter); if (type->is_set()) { out << " => 1"; } out << "," << endl; } indent_down(); indent(out) << "]"; } return out.str(); } /** * Make a struct */ void t_perl_generator::generate_struct(t_struct* tstruct) { generate_perl_struct(tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_perl_generator::generate_xception(t_struct* txception) { generate_perl_struct(txception, true); } /** * Structs can be normal or exceptions. */ void t_perl_generator::generate_perl_struct(t_struct* tstruct, bool is_exception) { generate_use_includes(f_types_, f_types_use_includes_emitted_, tstruct, false); generate_perl_struct_definition(f_types_, tstruct, is_exception); } /** * Generates a struct definition for a thrift data type. This is nothing in PERL * where the objects are all just associative arrays (unless of course we * decide to start using objects for them...) * * @param tstruct The struct definition */ void t_perl_generator::generate_perl_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; out << "package " << perl_namespace(tstruct->get_program()) << tstruct->get_name() << ";\n"; if (is_exception) { out << "use base qw(Thrift::TException);\n"; } // Create simple acessor methods out << "use base qw(Class::Accessor);\n"; if (members.size() > 0) { out << perl_namespace(tstruct->get_program()) << tstruct->get_name() << "->mk_accessors( qw( "; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if (!t->is_xception()) { out << (*m_iter)->get_name() << " "; } } out << ") );\n"; } out << endl; // new() indent_up(); out << "sub new {" << endl << indent() << "my $classname = shift;" << endl << indent() << "my $self = {};" << endl << indent() << "my $vals = shift || {};" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string dval = "undef"; t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr && !(t->is_struct() || t->is_xception())) { dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value()); } out << indent() << "$self->{" << (*m_iter)->get_name() << "} = " << dval << ";" << endl; } // Generate constructor from array if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr && (t->is_struct() || t->is_xception())) { indent(out) << "$self->{" << (*m_iter)->get_name() << "} = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl; } } out << indent() << "if (UNIVERSAL::isa($vals,'HASH')) {" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << indent() << "if (defined $vals->{" << (*m_iter)->get_name() << "}) {" << endl << indent() << " $self->{" << (*m_iter)->get_name() << "} = $vals->{" << (*m_iter)->get_name() << "};" << endl << indent() << "}" << endl; } indent_down(); out << indent() << "}" << endl; } out << indent() << "return bless ($self, $classname);" << endl; indent_down(); out << "}\n\n"; out << "sub getName {" << endl << indent() << " return '" << tstruct->get_name() << "';" << endl << indent() << "}" << endl << endl; generate_perl_struct_reader(out, tstruct); generate_perl_struct_writer(out, tstruct); } /** * Generates the read() method for a struct */ void t_perl_generator::generate_perl_struct_reader(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; out << "sub read {" << endl; indent_up(); out << indent() << "my ($self, $input) = @_;" << endl << indent() << "my $xfer = 0;" << endl << indent() << "my $fname;" << endl << indent() << "my $ftype = 0;" << endl << indent() << "my $fid = 0;" << endl; indent(out) << "$xfer += $input->readStructBegin(\\$fname);" << endl; // Loop over reading in fields indent(out) << "while (1)" << endl; scope_up(out); indent(out) << "$xfer += $input->readFieldBegin(\\$fname, \\$ftype, \\$fid);" << endl; // Check for field STOP marker and break indent(out) << "if ($ftype == Thrift::TType::STOP) {" << endl; indent_up(); indent(out) << "last;" << endl; indent_down(); indent(out) << "}" << endl; // Switch statement on the field we are reading indent(out) << "SWITCH: for($fid)" << endl; scope_up(out); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "/^" << (*f_iter)->get_key() << "$/ && do{"; indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, "self->"); indent_down(); indent(out) << "} else {" << endl; indent(out) << " $xfer += $input->skip($ftype);" << endl; out << indent() << "}" << endl << indent() << "last; };" << endl; } // In the default case we skip the field indent(out) << " $xfer += $input->skip($ftype);" << endl; scope_down(out); indent(out) << "$xfer += $input->readFieldEnd();" << endl; scope_down(out); indent(out) << "$xfer += $input->readStructEnd();" << endl; indent(out) << "return $xfer;" << endl; indent_down(); out << indent() << "}" << endl << endl; } /** * Generates the write() method for a struct */ void t_perl_generator::generate_perl_struct_writer(ostream& out, t_struct* tstruct) { string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; out << "sub write {" << endl; indent_up(); indent(out) << "my ($self, $output) = @_;" << endl; indent(out) << "my $xfer = 0;" << endl; indent(out) << "$xfer += $output->writeStructBegin('" << name << "');" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << indent() << "if (defined $self->{" << (*f_iter)->get_name() << "}) {" << endl; indent_up(); indent(out) << "$xfer += $output->writeFieldBegin(" << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ");" << endl; // Write field contents generate_serialize_field(out, *f_iter, "self->"); indent(out) << "$xfer += $output->writeFieldEnd();" << endl; indent_down(); indent(out) << "}" << endl; } out << indent() << "$xfer += $output->writeFieldStop();" << endl << indent() << "$xfer += $output->writeStructEnd();" << endl; out << indent() << "return $xfer;" << endl; indent_down(); out << indent() << "}" << endl << endl; } /** * Generates use clauses for included entities * * @param os The output stream * @param done A flag reference to debounce the action * @param type The type being processed * @param selfish Flag to indicate if the current namespace types should be "use"d as well. */ void t_perl_generator::generate_use_includes(std::ostream& os, bool& done, t_type *type, bool selfish) { t_program *current = type->get_program(); if (current && !done) { std::vector& currInc = current->get_includes(); std::vector::size_type numInc = currInc.size(); if (selfish) { os << "use " << perl_namespace(current) << "Types;" << endl; } for (std::vector::size_type i = 0; i < numInc; ++i) { t_program* incProgram = currInc.at(i); os << "use " << perl_namespace(incProgram) << "Types;" << endl; } os << endl; done = true; } } /** * Generates a thrift service. * * @param tservice The service definition */ void t_perl_generator::generate_service(t_service* tservice) { string f_service_name = get_namespace_out_dir() + service_name_ + ".pm"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment() << perl_includes(); bool done = false; generate_use_includes(f_service_, done, tservice, true); t_service* extends_s = tservice->get_extends(); if (extends_s != nullptr) { f_service_ << "use " << perl_namespace(extends_s->get_program()) << extends_s->get_name() << ";" << endl; } f_service_ << endl; // Generate the three main parts of the service (well, two for now in PERL) generate_service_helpers(tservice); generate_service_interface(tservice); generate_service_rest(tservice); generate_service_client(tservice); generate_service_processor(tservice); // Close service file f_service_ << "1;" << endl; f_service_.close(); } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_perl_generator::generate_service_processor(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; t_service* extends_s = tservice->get_extends(); if (extends_s != nullptr) { extends = perl_namespace(extends_s->get_program()) + extends_s->get_name(); extends_processor = "use base qw(" + extends + "Processor);"; } indent_up(); // Generate the header portion f_service_ << "package " << perl_namespace(program_) << service_name_ << "Processor;" << endl << endl << "use strict;" << endl << extends_processor << endl << endl; if (extends.empty()) { f_service_ << "sub new {" << endl; indent_up(); f_service_ << indent() << "my ($classname, $handler) = @_;" << endl << indent() << "my $self = {};" << endl; f_service_ << indent() << "$self->{handler} = $handler;" << endl; f_service_ << indent() << "return bless ($self, $classname);" << endl; indent_down(); f_service_ << "}" << endl << endl; } // Generate the server implementation f_service_ << "sub process {" << endl; indent_up(); f_service_ << indent() << "my ($self, $input, $output) = @_;" << endl; f_service_ << indent() << "my $rseqid = 0;" << endl << indent() << "my $fname = undef;" << endl << indent() << "my $mtype = 0;" << endl << endl; f_service_ << indent() << "$input->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);" << endl; // HOT: check for method implementation f_service_ << indent() << "my $methodname = 'process_'.$fname;" << endl << indent() << "if (!$self->can($methodname)) {" << endl; indent_up(); f_service_ << indent() << "$input->skip(Thrift::TType::STRUCT);" << endl << indent() << "$input->readMessageEnd();" << endl << indent() << "my $x = Thrift::TApplicationException->new('Function '.$fname.' not implemented.', " "Thrift::TApplicationException::UNKNOWN_METHOD);" << endl << indent() << "$output->writeMessageBegin($fname, Thrift::TMessageType::EXCEPTION, $rseqid);" << endl << indent() << "$x->write($output);" << endl << indent() << "$output->writeMessageEnd();" << endl << indent() << "$output->getTransport()->flush();" << endl << indent() << "return;" << endl; indent_down(); f_service_ << indent() << "}" << endl << indent() << "$self->$methodname($rseqid, $input, $output);" << endl << indent() << "return 1;" << endl; indent_down(); f_service_ << "}" << endl << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_perl_generator::generate_process_function(t_service* tservice, t_function* tfunction) { // Open function f_service_ << "sub process_" << tfunction->get_name() << " {" << endl; indent_up(); f_service_ << indent() << "my ($self, $seqid, $input, $output) = @_;" << endl; string argsname = perl_namespace(tservice->get_program()) + service_name_ + "_" + tfunction->get_name() + "_args"; string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_" + tfunction->get_name() + "_result"; f_service_ << indent() << "my $args = " << argsname << "->new();" << endl << indent() << "$args->read($input);" << endl; f_service_ << indent() << "$input->readMessageEnd();" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { f_service_ << indent() << "my $result = " << resultname << "->new();" << endl; } // Try block for a function with exceptions if (xceptions.size() > 0) { f_service_ << indent() << "eval {" << endl; indent_up(); } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "$result->{success} = "; } f_service_ << "$self->{handler}->" << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "$args->" << (*f_iter)->get_name(); } f_service_ << ");" << endl; if (!tfunction->is_oneway() && xceptions.size() > 0) { indent_down(); for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "}; if( UNIVERSAL::isa($@,'" << perl_namespace((*x_iter)->get_type()->get_program()) << (*x_iter)->get_type()->get_name() << "') ){ " << endl; indent_up(); f_service_ << indent() << "$result->{" << (*x_iter)->get_name() << "} = $@;" << endl; f_service_ << indent() << "$@ = undef;" << endl; indent_down(); f_service_ << indent(); } f_service_ << "}" << endl; // catch-all for unexpected exceptions (THRIFT-3191) f_service_ << indent() << "if ($@) {" << endl; indent_up(); f_service_ << indent() << "$@ =~ s/^\\s+|\\s+$//g;" << endl << indent() << "my $err = Thrift::TApplicationException->new(\"Unexpected Exception: \" . $@, Thrift::TApplicationException::INTERNAL_ERROR);" << endl << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', Thrift::TMessageType::EXCEPTION, $seqid);" << endl << indent() << "$err->write($output);" << endl << indent() << "$output->writeMessageEnd();" << endl << indent() << "$output->getTransport()->flush();" << endl << indent() << "$@ = undef;" << endl << indent() << "return;" << endl; indent_down(); f_service_ << indent() << "}" << endl; } // Shortcut out here for oneway functions if (tfunction->is_oneway()) { f_service_ << indent() << "return;" << endl; indent_down(); f_service_ << "}" << endl; return; } // Serialize the reply f_service_ << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', Thrift::TMessageType::REPLY, $seqid);" << endl << indent() << "$result->write($output);" << endl << indent() << "$output->writeMessageEnd();" << endl << indent() << "$output->getTransport()->flush();" << endl; // Close function indent_down(); f_service_ << "}" << endl << endl; } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_perl_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; f_service_ << "# HELPER FUNCTIONS AND STRUCTURES" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); string name = ts->get_name(); ts->set_name(service_name_ + "_" + name); generate_perl_struct_definition(f_service_, ts, false); generate_perl_function_helpers(*f_iter); ts->set_name(name); } } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_perl_generator::generate_perl_function_helpers(t_function* tfunction) { t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_perl_struct_definition(f_service_, &result, false); } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_perl_generator::generate_service_interface(t_service* tservice) { string extends_if = ""; t_service* extends_s = tservice->get_extends(); if (extends_s != nullptr) { extends_if = "use base qw(" + perl_namespace(extends_s->get_program()) + extends_s->get_name() + "If);"; } f_service_ << "package " << perl_namespace(program_) << service_name_ << "If;" << endl << endl << "use strict;" << endl << extends_if << endl << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << "sub " << function_signature(*f_iter) << endl << " die 'implement interface';\n}" << endl << endl; } indent_down(); } /** * Generates a REST interface */ void t_perl_generator::generate_service_rest(t_service* tservice) { string extends = ""; string extends_if = ""; t_service* extends_s = tservice->get_extends(); if (extends_s != nullptr) { extends = extends_s->get_name(); extends_if = "use base qw(" + perl_namespace(extends_s->get_program()) + extends_s->get_name() + "Rest);"; } f_service_ << "package " << perl_namespace(program_) << service_name_ << "Rest;" << endl << endl << "use strict;" << endl << extends_if << endl << endl; if (extends.empty()) { f_service_ << "sub new {" << endl; indent_up(); f_service_ << indent() << "my ($classname, $impl) = @_;" << endl << indent() << "my $self ={ impl => $impl };" << endl << endl << indent() << "return bless($self,$classname);" << endl; indent_down(); f_service_ << "}" << endl << endl; } vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << "sub " << (*f_iter)->get_name() << "{" << endl; indent_up(); f_service_ << indent() << "my ($self, $request) = @_;" << endl << endl; const vector& args = (*f_iter)->get_arglist()->get_members(); vector::const_iterator a_iter; for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) { //t_type* atype = get_true_type((*a_iter)->get_type()); string req = "$request->{'" + (*a_iter)->get_name() + "'}"; f_service_ << indent() << "my $" << (*a_iter)->get_name() << " = (" << req << ") ? " << req << " : undef;" << endl; /* slist no longer supported if (atype->is_string() && ((t_base_type*)atype)->is_string_list()) { f_service_ << indent() << "my @" << (*a_iter)->get_name() << " = split(/,/, $" << (*a_iter)->get_name() << ");" << endl << indent() << "$" << (*a_iter)->get_name() << " = \\@" << (*a_iter)->get_name() << endl; } */ } f_service_ << indent() << "return $self->{impl}->" << (*f_iter)->get_name() << "(" << argument_list((*f_iter)->get_arglist()) << ");" << endl; indent_down(); indent(f_service_) << "}" << endl << endl; } } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_perl_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = ""; t_service* extends_s = tservice->get_extends(); if (extends_s != nullptr) { extends = perl_namespace(extends_s->get_program()) + extends_s->get_name(); extends_client = "use base qw(" + extends + "Client);"; } f_service_ << "package " << perl_namespace(program_) << service_name_ << "Client;" << endl << endl << extends_client << endl << "use base qw(" << perl_namespace(program_) << service_name_ << "If);" << endl; // Constructor function f_service_ << "sub new {" << endl; indent_up(); f_service_ << indent() << "my ($classname, $input, $output) = @_;" << endl << indent() << "my $self = {};" << endl; if (!extends.empty()) { f_service_ << indent() << "$self = $classname->SUPER::new($input, $output);" << endl; } else { f_service_ << indent() << "$self->{input} = $input;" << endl << indent() << "$self->{output} = defined $output ? $output : $input;" << endl << indent() << "$self->{seqid} = 0;" << endl; } f_service_ << indent() << "return bless($self,$classname);" << endl; indent_down(); f_service_ << "}" << endl << endl; // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); // Open function f_service_ << "sub " << function_signature(*f_iter) << endl; indent_up(); indent(f_service_) << indent() << "$self->send_" << funname << "("; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "$" << (*fld_iter)->get_name(); } f_service_ << ");" << endl; if (!(*f_iter)->is_oneway()) { f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << "return "; } f_service_ << "$self->recv_" << funname << "();" << endl; } indent_down(); f_service_ << "}" << endl << endl; f_service_ << "sub send_" << function_signature(*f_iter) << endl; indent_up(); std::string argsname = perl_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_args"; // Serialize the request header f_service_ << indent() << "$self->{output}->writeMessageBegin('" << (*f_iter)->get_name() << "', " << ((*f_iter)->is_oneway() ? "Thrift::TMessageType::ONEWAY" : "Thrift::TMessageType::CALL") << ", $self->{seqid});" << endl; f_service_ << indent() << "my $args = " << argsname << "->new();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << indent() << "$args->{" << (*fld_iter)->get_name() << "} = $" << (*fld_iter)->get_name() << ";" << endl; } // Write to the stream f_service_ << indent() << "$args->write($self->{output});" << endl << indent() << "$self->{output}->writeMessageEnd();" << endl << indent() << "$self->{output}->getTransport()->flush();" << endl; indent_down(); f_service_ << "}" << endl; if (!(*f_iter)->is_oneway()) { std::string resultname = perl_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_result"; t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); // Open function f_service_ << endl << "sub " << function_signature(&recv_function) << endl; indent_up(); f_service_ << indent() << "my $rseqid = 0;" << endl << indent() << "my $fname;" << endl << indent() << "my $mtype = 0;" << endl << endl; f_service_ << indent() << "$self->{input}->readMessageBegin(\\$fname, \\$mtype, \\$rseqid);" << endl << indent() << "if ($mtype == Thrift::TMessageType::EXCEPTION) {" << endl << indent() << " my $x = Thrift::TApplicationException->new();" << endl << indent() << " $x->read($self->{input});" << endl << indent() << " $self->{input}->readMessageEnd();" << endl << indent() << " die $x;" << endl << indent() << "}" << endl; f_service_ << indent() << "my $result = " << resultname << "->new();" << endl << indent() << "$result->read($self->{input});" << endl; f_service_ << indent() << "$self->{input}->readMessageEnd();" << endl << endl; // Careful, only return result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << indent() << "if (defined $result->{success} ) {" << endl << indent() << " return $result->{success};" << endl << indent() << "}" << endl; } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_ << indent() << "if (defined $result->{" << (*x_iter)->get_name() << "}) {" << endl << indent() << " die $result->{" << (*x_iter)->get_name() << "};" << endl << indent() << "}" << endl; } // Careful, only return _result if not a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_) << "return;" << endl; } else { f_service_ << indent() << "die \"" << (*f_iter)->get_name() << " failed: unknown result\";" << endl; } // Close function indent_down(); f_service_ << "}" << endl; } } } /** * Deserializes a field of any type. */ void t_perl_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool inclass) { (void)inclass; t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = tfield->get_name(); // Hack for when prefix is defined (always a hash ref) if (!prefix.empty()) { name = prefix + "{" + tfield->get_name() + "}"; } if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << "$xfer += $input->"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "readString(\\$" << name << ");"; break; case t_base_type::TYPE_BOOL: out << "readBool(\\$" << name << ");"; break; case t_base_type::TYPE_I8: out << "readByte(\\$" << name << ");"; break; case t_base_type::TYPE_I16: out << "readI16(\\$" << name << ");"; break; case t_base_type::TYPE_I32: out << "readI32(\\$" << name << ");"; break; case t_base_type::TYPE_I64: out << "readI64(\\$" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble(\\$" << name << ");"; break; default: throw "compiler error: no PERL name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "readI32(\\$" << name << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Generates an unserializer for a variable. This makes two key assumptions, * first that there is a const char* variable named data that points to the * buffer for deserialization, and that there is a variable protocol which * is a reference to a TProtocol serialization object. */ void t_perl_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { out << indent() << "$" << prefix << " = " << perl_namespace(tstruct->get_program()) << tstruct->get_name() << "->new();" << endl << indent() << "$xfer += $" << prefix << "->read($input);" << endl; } void t_perl_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); string size = tmp("_size"); string ktype = tmp("_ktype"); string vtype = tmp("_vtype"); string etype = tmp("_etype"); t_field fsize(g_type_i32, size); t_field fktype(g_type_i8, ktype); t_field fvtype(g_type_i8, vtype); t_field fetype(g_type_i8, etype); out << indent() << "my $" << size << " = 0;" << endl; // Declare variables, read header if (ttype->is_map()) { out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << ktype << " = 0;" << endl << indent() << "my $" << vtype << " = 0;" << endl; out << indent() << "$xfer += $input->readMapBegin(" << "\\$" << ktype << ", \\$" << vtype << ", \\$" << size << ");" << endl; } else if (ttype->is_set()) { out << indent() << "$" << prefix << " = {};" << endl << indent() << "my $" << etype << " = 0;" << endl << indent() << "$xfer += $input->readSetBegin(" << "\\$" << etype << ", \\$" << size << ");" << endl; } else if (ttype->is_list()) { out << indent() << "$" << prefix << " = [];" << endl << indent() << "my $" << etype << " = 0;" << endl << indent() << "$xfer += $input->readListBegin(" << "\\$" << etype << ", \\$" << size << ");" << endl; } // For loop iterates over elements string i = tmp("_i"); indent(out) << "for (my $" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ")" << endl; scope_up(out); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } scope_down(out); // Read container end if (ttype->is_map()) { indent(out) << "$xfer += $input->readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "$xfer += $input->readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "$xfer += $input->readListEnd();" << endl; } scope_down(out); } /** * Generates code to deserialize a map */ void t_perl_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("key"); string val = tmp("val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey, true, true) << endl; indent(out) << declare_field(&fval, true, true) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << "$" << prefix << "->{$" << key << "} = $" << val << ";" << endl; } void t_perl_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << "my $" << elem << " = undef;" << endl; generate_deserialize_field(out, &felem); indent(out) << "$" << prefix << "->{$" << elem << "} = 1;" << endl; } void t_perl_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << "my $" << elem << " = undef;" << endl; generate_deserialize_field(out, &felem); indent(out) << "push(@{$" << prefix << "},$" << elem << ");" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_perl_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + "{" + tfield->get_name() + "}"); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + "{" + tfield->get_name() + "}"); } else if (type->is_base_type() || type->is_enum()) { string name = tfield->get_name(); // Hack for when prefix is defined (always a hash ref) if (!prefix.empty()) name = prefix + "{" + tfield->get_name() + "}"; indent(out) << "$xfer += $output->"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "writeString($" << name << ");"; break; case t_base_type::TYPE_BOOL: out << "writeBool($" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte($" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16($" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32($" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64($" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble($" << name << ");"; break; default: throw "compiler error: no PERL name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32($" << name << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_perl_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << "$xfer += $" << prefix << "->write($output);" << endl; } /** * Writes out a container */ void t_perl_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); if (ttype->is_map()) { indent(out) << "$xfer += $output->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "scalar(keys %{$" << prefix << "}));" << endl; } else if (ttype->is_set()) { indent(out) << "$xfer += $output->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << "scalar(@{$" << prefix << "}));" << endl; } else if (ttype->is_list()) { indent(out) << "$xfer += $output->writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << "scalar(@{$" << prefix << "}));" << endl; } scope_up(out); if (ttype->is_map()) { string kiter = tmp("kiter"); string viter = tmp("viter"); indent(out) << "while( my ($" << kiter << ",$" << viter << ") = each %{$" << prefix << "}) " << endl; scope_up(out); generate_serialize_map_element(out, (t_map*)ttype, kiter, viter); scope_down(out); } else if (ttype->is_set()) { string iter = tmp("iter"); indent(out) << "foreach my $" << iter << " (@{$" << prefix << "})" << endl; scope_up(out); generate_serialize_set_element(out, (t_set*)ttype, iter); scope_down(out); } else if (ttype->is_list()) { string iter = tmp("iter"); indent(out) << "foreach my $" << iter << " (@{$" << prefix << "}) " << endl; scope_up(out); generate_serialize_list_element(out, (t_list*)ttype, iter); scope_down(out); } scope_down(out); if (ttype->is_map()) { indent(out) << "$xfer += $output->writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "$xfer += $output->writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "$xfer += $output->writeListEnd();" << endl; } scope_down(out); } /** * Serializes the members of a map. * */ void t_perl_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), kiter); generate_serialize_field(out, &kfield); t_field vfield(tmap->get_val_type(), viter); generate_serialize_field(out, &vfield); } /** * Serializes the members of a set. */ void t_perl_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield); } /** * Serializes the members of a list. */ void t_perl_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield); } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type */ string t_perl_generator::declare_field(t_field* tfield, bool init, bool obj) { string result = "my $" + tfield->get_name(); if (init) { t_type* type = get_true_type(tfield->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_STRING: result += " = ''"; break; case t_base_type::TYPE_BOOL: result += " = 0"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = 0.0"; break; default: throw "compiler error: no PERL initializer for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { result += " = 0"; } else if (type->is_container()) { result += " = []"; } else if (type->is_struct() || type->is_xception()) { if (obj) { result += " = " + perl_namespace(type->get_program()) + type->get_name() + "->new()"; } else { result += " = undef"; } } } return result + ";"; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_perl_generator::function_signature(t_function* tfunction, string prefix) { string str; str = prefix + tfunction->get_name() + "{\n"; str += " my $self = shift;\n"; // Need to create perl function arg inputs const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { str += " my $" + (*f_iter)->get_name() + " = shift;\n"; } return str; } /** * Renders a field list */ string t_perl_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += "$" + (*f_iter)->get_name(); } return result; } /** * Converts the parse type to a C++ enum string for the given type. */ string t_perl_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "Thrift::TType::STRING"; case t_base_type::TYPE_BOOL: return "Thrift::TType::BOOL"; case t_base_type::TYPE_I8: return "Thrift::TType::BYTE"; case t_base_type::TYPE_I16: return "Thrift::TType::I16"; case t_base_type::TYPE_I32: return "Thrift::TType::I32"; case t_base_type::TYPE_I64: return "Thrift::TType::I64"; case t_base_type::TYPE_DOUBLE: return "Thrift::TType::DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "Thrift::TType::I32"; } else if (type->is_struct() || type->is_xception()) { return "Thrift::TType::STRUCT"; } else if (type->is_map()) { return "Thrift::TType::MAP"; } else if (type->is_set()) { return "Thrift::TType::SET"; } else if (type->is_list()) { return "Thrift::TType::LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_perl_generator::display_name() const { return "Perl"; } THRIFT_REGISTER_GENERATOR(perl, "Perl", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_cpp_generator.cc0000644000000000000000000055325014370300523025045 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ofstream; using std::ostream; using std::string; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * C++ code generator. This is legitimacy incarnate. * */ class t_cpp_generator : public t_oop_generator { public: t_cpp_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; gen_pure_enums_ = false; use_include_prefix_ = false; gen_cob_style_ = false; gen_no_client_completion_ = false; gen_no_default_operators_ = false; gen_templates_ = false; gen_templates_only_ = false; gen_moveable_ = false; gen_no_ostream_operators_ = false; gen_no_skeleton_ = false; has_members_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("pure_enums") == 0) { gen_pure_enums_ = true; } else if( iter->first.compare("include_prefix") == 0) { use_include_prefix_ = true; } else if( iter->first.compare("cob_style") == 0) { gen_cob_style_ = true; } else if( iter->first.compare("no_client_completion") == 0) { gen_no_client_completion_ = true; } else if( iter->first.compare("no_default_operators") == 0) { gen_no_default_operators_ = true; } else if( iter->first.compare("templates") == 0) { gen_templates_ = true; gen_templates_only_ = (iter->second == "only"); } else if( iter->first.compare("moveable_types") == 0) { gen_moveable_ = true; } else if ( iter->first.compare("no_ostream_operators") == 0) { gen_no_ostream_operators_ = true; } else if ( iter->first.compare("no_skeleton") == 0) { gen_no_skeleton_ = true; } else { throw "unknown option cpp:" + iter->first; } } out_dir_base_ = "gen-cpp"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(std::vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum); void generate_enum_ostream_operator(std::ostream& out, t_enum* tenum); void generate_enum_to_string_helper_function_decl(std::ostream& out, t_enum* tenum); void generate_enum_to_string_helper_function(std::ostream& out, t_enum* tenum); void generate_forward_declaration(t_struct* tstruct) override; void generate_struct(t_struct* tstruct) override { generate_cpp_struct(tstruct, false); } void generate_xception(t_struct* txception) override { generate_cpp_struct(txception, true); } void generate_cpp_struct(t_struct* tstruct, bool is_exception); void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value); std::string render_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value); void generate_struct_declaration(std::ostream& out, t_struct* tstruct, bool is_exception = false, bool pointers = false, bool read = true, bool write = true, bool swap = false, bool is_user_struct = false); void generate_struct_definition(std::ostream& out, std::ostream& force_cpp_out, t_struct* tstruct, bool setters = true, bool is_user_struct = false); void generate_copy_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); void generate_move_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); void generate_constructor_helper(std::ostream& out, t_struct* tstruct, bool is_excpetion, bool is_move); void generate_assignment_operator(std::ostream& out, t_struct* tstruct); void generate_move_assignment_operator(std::ostream& out, t_struct* tstruct); void generate_assignment_helper(std::ostream& out, t_struct* tstruct, bool is_move); void generate_struct_reader(std::ostream& out, t_struct* tstruct, bool pointers = false); void generate_struct_writer(std::ostream& out, t_struct* tstruct, bool pointers = false); void generate_struct_result_writer(std::ostream& out, t_struct* tstruct, bool pointers = false); void generate_struct_swap(std::ostream& out, t_struct* tstruct); void generate_struct_print_method(std::ostream& out, t_struct* tstruct); void generate_exception_what_method(std::ostream& out, t_struct* tstruct); /** * Service-level generation functions */ void generate_service_interface(t_service* tservice, string style); void generate_service_interface_factory(t_service* tservice, string style); void generate_service_null(t_service* tservice, string style); void generate_service_multiface(t_service* tservice); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice, string style); void generate_service_processor(t_service* tservice, string style); void generate_service_skeleton(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction, string style, bool specialized = false); void generate_function_helpers(t_service* tservice, t_function* tfunction); void generate_service_async_skeleton(t_service* tservice); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", std::string suffix = ""); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "", bool pointer = false); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix, bool push_back, std::string index); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", std::string suffix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = "", bool pointer = false); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string iter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_function_call(ostream& out, t_function* tfunction, string target, string iface, string arg_prefix); /* * Helper rendering functions */ std::string namespace_prefix(std::string ns); std::string namespace_open(std::string ns); std::string namespace_close(std::string ns); std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false); std::string base_type_name(t_base_type::t_base tbase); std::string declare_field(t_field* tfield, bool init = false, bool pointer = false, bool constant = false, bool reference = false); std::string function_signature(t_function* tfunction, std::string style, std::string prefix = "", bool name_params = true); std::string cob_function_signature(t_function* tfunction, std::string prefix = "", bool name_params = true); std::string argument_list(t_struct* tstruct, bool name_params = true, bool start_comma = false); std::string type_to_enum(t_type* ttype); void generate_enum_constant_list(std::ostream& f, const vector& constants, const char* prefix, const char* suffix, bool include_values); void generate_struct_ostream_operator_decl(std::ostream& f, t_struct* tstruct); void generate_struct_ostream_operator(std::ostream& f, t_struct* tstruct); void generate_struct_print_method_decl(std::ostream& f, t_struct* tstruct); void generate_exception_what_method_decl(std::ostream& f, t_struct* tstruct, bool external = false); bool is_reference(t_field* tfield) { return tfield->get_reference(); } bool is_complex_type(t_type* ttype) { ttype = get_true_type(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || (ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING)); } void set_use_include_prefix(bool use_include_prefix) { use_include_prefix_ = use_include_prefix; } /** * The compiler option "no_thrift_ostream_impl" can be used to prevent * the compiler from emitting implementations for operator <<. In this * case the consuming application must provide any needed to build. * * To disable this on a per structure bases, one can alternatively set * the annotation "cpp.customostream" to prevent thrift from emitting an * operator << (std::ostream&). * * See AnnotationTest for validation of this annotation feature. */ bool has_custom_ostream(t_type* ttype) const { return (gen_no_ostream_operators_) || (ttype->annotations_.find("cpp.customostream") != ttype->annotations_.end()); } /** * Determine if all fields of t_struct's storage do not throw * Move/Copy Constructors and Assignments applicable for 'noexcept' * Move defaults to 'noexcept' */ bool is_struct_storage_not_throwing(t_struct* tstruct) const; private: /** * Returns the include prefix to use for a file generated by program, or the * empty string if no include prefix should be used. */ std::string get_include_prefix(const t_program& program) const; /** * Returns the legal program name to use for a file generated by program, if the * program name contains dots then replace it with underscores, otherwise return the * original program name. */ std::string get_legal_program_name(std::string program_name); /** * True if we should generate pure enums for Thrift enums, instead of wrapper classes. */ bool gen_pure_enums_; /** * True if we should generate templatized reader/writer methods. */ bool gen_templates_; /** * True iff we should generate process function pointers for only templatized * reader/writer methods. */ bool gen_templates_only_; /** * True if we should generate move constructors & assignment operators. */ bool gen_moveable_; /** * True if we should generate ostream definitions */ bool gen_no_ostream_operators_; /** * True iff we should use a path prefix in our #include statements for other * thrift-generated header files. */ bool use_include_prefix_; /** * True if we should generate "Continuation OBject"-style classes as well. */ bool gen_cob_style_; /** * True if we should omit calls to completion__() in CobClient class. */ bool gen_no_client_completion_; /** * True if we should omit generating the default opeartors ==, != and <. */ bool gen_no_default_operators_; /** * True if we should generate skeleton. */ bool gen_no_skeleton_; /** * True if thrift has member(s) */ bool has_members_; /** * Strings for namespace, computed once up front then used directly */ std::string ns_open_; std::string ns_close_; /** * File streams, stored here to avoid passing them as parameters to every * function. */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_types_impl_; ofstream_with_content_based_conditional_update f_types_tcc_; ofstream_with_content_based_conditional_update f_header_; ofstream_with_content_based_conditional_update f_service_; ofstream_with_content_based_conditional_update f_service_tcc_; // The ProcessorGenerator is used to generate parts of the code, // so it needs access to many of our protected members and methods. // // TODO: The code really should be cleaned up so that helper methods for // writing to the output files are separate from the generator classes // themselves. friend class ProcessorGenerator; }; /** * Prepares for file generation by opening up the necessary file output * streams. */ void t_cpp_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); program_name_ = get_legal_program_name(program_name_); // Make output file string f_types_name = get_out_dir() + program_name_ + "_types.h"; f_types_.open(f_types_name); string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp"; f_types_impl_.open(f_types_impl_name.c_str()); if (gen_templates_) { // If we don't open the stream, it appears to just discard data, // which is fine. string f_types_tcc_name = get_out_dir() + program_name_ + "_types.tcc"; f_types_tcc_.open(f_types_tcc_name.c_str()); } // Print header f_types_ << autogen_comment(); f_types_impl_ << autogen_comment(); f_types_tcc_ << autogen_comment(); // Start ifndef f_types_ << "#ifndef " << program_name_ << "_TYPES_H" << endl << "#define " << program_name_ << "_TYPES_H" << endl << endl; f_types_tcc_ << "#ifndef " << program_name_ << "_TYPES_TCC" << endl << "#define " << program_name_ << "_TYPES_TCC" << endl << endl; // Include base types f_types_ << "#include " << endl << endl << "#include " << endl << "#include " << endl << "#include " << endl << "#include " << endl << "#include " << endl << endl; // Include C++xx compatibility header f_types_ << "#include " << endl; f_types_ << "#include " << endl; // Include other Thrift includes const vector& includes = program_->get_includes(); for (auto include : includes) { f_types_ << "#include \"" << get_include_prefix(*include) << include->get_name() << "_types.h\"" << endl; // XXX(simpkins): If gen_templates_ is enabled, we currently assume all // included files were also generated with templates enabled. f_types_tcc_ << "#include \"" << get_include_prefix(*include) << include->get_name() << "_types.tcc\"" << endl; } f_types_ << endl; // Include custom headers const vector& cpp_includes = program_->get_cpp_includes(); for (const auto & cpp_include : cpp_includes) { if (cpp_include[0] == '<') { f_types_ << "#include " << cpp_include << endl; } else { f_types_ << "#include \"" << cpp_include << "\"" << endl; } } f_types_ << endl; // Include the types file f_types_impl_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\"" << endl << endl; f_types_tcc_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\"" << endl << endl; // The swap() code needs for std::swap() f_types_impl_ << "#include " << endl; // for operator<< f_types_impl_ << "#include " << endl << endl; f_types_impl_ << "#include " << endl << endl; // Open namespace ns_open_ = namespace_open(program_->get_namespace("cpp")); ns_close_ = namespace_close(program_->get_namespace("cpp")); f_types_ << ns_open_ << endl << endl; f_types_impl_ << ns_open_ << endl << endl; f_types_tcc_ << ns_open_ << endl << endl; } /** * Closes the output files. */ void t_cpp_generator::close_generator() { // Close namespace f_types_ << ns_close_ << endl << endl; f_types_impl_ << ns_close_ << endl; f_types_tcc_ << ns_close_ << endl << endl; // Include the types.tcc file from the types header file, // so clients don't have to explicitly include the tcc file. // TODO(simpkins): Make this a separate option. if (gen_templates_) { f_types_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.tcc\"" << endl << endl; } // Close ifndef f_types_ << "#endif" << endl; f_types_tcc_ << "#endif" << endl; // Close output file f_types_.close(); f_types_impl_.close(); f_types_tcc_.close(); string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp"; if (!has_members_) { remove(f_types_impl_name.c_str()); } } /** * Generates a typedef. This is just a simple 1-liner in C++ * * @param ttypedef The type definition */ void t_cpp_generator::generate_typedef(t_typedef* ttypedef) { generate_java_doc(f_types_, ttypedef); f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << ttypedef->get_symbolic() << ";" << endl << endl; } void t_cpp_generator::generate_enum_constant_list(std::ostream& f, const vector& constants, const char* prefix, const char* suffix, bool include_values) { f << " {" << endl; indent_up(); vector::const_iterator c_iter; bool first = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { if (first) { first = false; } else { f << "," << endl; } generate_java_doc(f, *c_iter); indent(f) << prefix << (*c_iter)->get_name() << suffix; if (include_values) { f << " = " << (*c_iter)->get_value(); } } f << endl; indent_down(); indent(f) << "};" << endl; } /** * Generates code for an enumerated type. In C++, this is essentially the same * as the thrift definition itself, using the enum keyword in C++. * * @param tenum The enumeration */ void t_cpp_generator::generate_enum(t_enum* tenum) { vector constants = tenum->get_constants(); std::string enum_name = tenum->get_name(); if (!gen_pure_enums_) { enum_name = "type"; generate_java_doc(f_types_, tenum); f_types_ << indent() << "struct " << tenum->get_name() << " {" << endl; indent_up(); } f_types_ << indent() << "enum " << enum_name; generate_enum_constant_list(f_types_, constants, "", "", true); if (!gen_pure_enums_) { indent_down(); f_types_ << "};" << endl; } f_types_ << endl; /** Generate a character array of enum names for debugging purposes. */ std::string prefix = ""; if (!gen_pure_enums_) { prefix = tenum->get_name() + "::"; } f_types_impl_ << indent() << "int _k" << tenum->get_name() << "Values[] ="; generate_enum_constant_list(f_types_impl_, constants, prefix.c_str(), "", false); f_types_impl_ << indent() << "const char* _k" << tenum->get_name() << "Names[] ="; generate_enum_constant_list(f_types_impl_, constants, "\"", "\"", false); f_types_ << indent() << "extern const std::map _" << tenum->get_name() << "_VALUES_TO_NAMES;" << endl << endl; f_types_impl_ << indent() << "const std::map _" << tenum->get_name() << "_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(" << constants.size() << ", _k" << tenum->get_name() << "Values" << ", _k" << tenum->get_name() << "Names), " << "::apache::thrift::TEnumIterator(-1, nullptr, nullptr));" << endl << endl; generate_enum_ostream_operator_decl(f_types_, tenum); generate_enum_ostream_operator(f_types_impl_, tenum); generate_enum_to_string_helper_function_decl(f_types_, tenum); generate_enum_to_string_helper_function(f_types_impl_, tenum); has_members_ = true; } void t_cpp_generator::generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum) { out << "std::ostream& operator<<(std::ostream& out, const "; if (gen_pure_enums_) { out << tenum->get_name(); } else { out << tenum->get_name() << "::type&"; } out << " val);" << endl; out << endl; } void t_cpp_generator::generate_enum_ostream_operator(std::ostream& out, t_enum* tenum) { // If we've been told the consuming application will provide an ostream // operator definition then we only make a declaration: if (!has_custom_ostream(tenum)) { out << "std::ostream& operator<<(std::ostream& out, const "; if (gen_pure_enums_) { out << tenum->get_name(); } else { out << tenum->get_name() << "::type&"; } out << " val) "; scope_up(out); out << indent() << "std::map::const_iterator it = _" << tenum->get_name() << "_VALUES_TO_NAMES.find(val);" << endl; out << indent() << "if (it != _" << tenum->get_name() << "_VALUES_TO_NAMES.end()) {" << endl; indent_up(); out << indent() << "out << it->second;" << endl; indent_down(); out << indent() << "} else {" << endl; indent_up(); out << indent() << "out << static_cast(val);" << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "return out;" << endl; scope_down(out); out << endl; } } void t_cpp_generator::generate_enum_to_string_helper_function_decl(std::ostream& out, t_enum* tenum) { out << "std::string to_string(const "; if (gen_pure_enums_) { out << tenum->get_name(); } else { out << tenum->get_name() << "::type&"; } out << " val);" << endl; out << endl; } void t_cpp_generator::generate_enum_to_string_helper_function(std::ostream& out, t_enum* tenum) { if (!has_custom_ostream(tenum)) { out << "std::string to_string(const "; if (gen_pure_enums_) { out << tenum->get_name(); } else { out << tenum->get_name() << "::type&"; } out << " val) " ; scope_up(out); out << indent() << "std::map::const_iterator it = _" << tenum->get_name() << "_VALUES_TO_NAMES.find(val);" << endl; out << indent() << "if (it != _" << tenum->get_name() << "_VALUES_TO_NAMES.end()) {" << endl; indent_up(); out << indent() << "return std::string(it->second);" << endl; indent_down(); out << indent() << "} else {" << endl; indent_up(); out << indent() << "return std::to_string(static_cast(val));" << endl; indent_down(); out << indent() << "}" << endl; scope_down(out); out << endl; } } /** * Generates a class that holds all the constants. */ void t_cpp_generator::generate_consts(std::vector consts) { string f_consts_name = get_out_dir() + program_name_ + "_constants.h"; ofstream_with_content_based_conditional_update f_consts; if (consts.size() > 0) { f_consts.open(f_consts_name); string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp"; ofstream_with_content_based_conditional_update f_consts_impl; f_consts_impl.open(f_consts_impl_name); // Print header f_consts << autogen_comment(); f_consts_impl << autogen_comment(); // Start ifndef f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_ << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl; f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_constants.h\"" << endl << endl << ns_open_ << endl << endl; f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << " " << program_name_ << "Constants();" << endl << endl; indent_up(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { string name = (*c_iter)->get_name(); t_type* type = (*c_iter)->get_type(); f_consts << indent() << type_name(type) << " " << name << ";" << endl; } indent_down(); f_consts << "};" << endl; f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;" << endl << endl << program_name_ << "Constants::" << program_name_ << "Constants() {" << endl; indent_up(); for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { print_const_value(f_consts_impl, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value()); } indent_down(); indent(f_consts_impl) << "}" << endl; f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_ << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl; f_consts.close(); f_consts_impl << endl << ns_close_ << endl << endl; f_consts_impl.close(); } } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ void t_cpp_generator::print_const_value(ostream& out, string name, t_type* type, t_const_value* value) { type = get_true_type(type); if (type->is_base_type()) { string v2 = render_const_value(out, name, type, value); indent(out) << name << " = " << v2 << ";" << endl << endl; } else if (type->is_enum()) { indent(out) << name << " = static_cast<" << type_name(type) << '>' << '(' << value->get_integer() << ");" << endl << endl; } else if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; bool is_nonrequired_field = false; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; is_nonrequired_field = false; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); is_nonrequired_field = (*f_iter)->get_req() != t_field::T_REQUIRED; } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string item_val = render_const_value(out, name, field_type, v_iter->second); indent(out) << name << "." << v_iter->first->get_string() << " = " << item_val << ";" << endl; if (is_nonrequired_field) { indent(out) << name << ".__isset." << v_iter->first->get_string() << " = true;" << endl; } } out << endl; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(out, name, ktype, v_iter->first); string item_val = render_const_value(out, name, vtype, v_iter->second); indent(out) << name << ".insert(std::make_pair(" << key << ", " << item_val << "));" << endl; } out << endl; } else if (type->is_list()) { t_type* etype = ((t_list*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string item_val = render_const_value(out, name, etype, *v_iter); indent(out) << name << ".push_back(" << item_val << ");" << endl; } out << endl; } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string item_val = render_const_value(out, name, etype, *v_iter); indent(out) << name << ".insert(" << item_val << ");" << endl; } out << endl; } else { throw "INVALID TYPE IN print_const_value: " + type->get_name(); } } /** * */ string t_cpp_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value) { (void)name; std::ostringstream render; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: render << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: render << value->get_integer(); break; case t_base_type::TYPE_I64: render << value->get_integer() << "LL"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << "static_cast(" << value->get_integer() << ")"; } else { render << emit_double_as_string(value->get_double()); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { render << "static_cast<" << type_name(type) << '>' << '(' << value->get_integer() << ')'; } else { string t = tmp("tmp"); indent(out) << type_name(type) << " " << t << ";" << endl; print_const_value(out, t, type, value); render << t; } return render.str(); } void t_cpp_generator::generate_forward_declaration(t_struct* tstruct) { // Forward declare struct def f_types_ << indent() << "class " << tstruct->get_name() << ";" << endl << endl; } /** * Generates a struct definition for a thrift data type. This is a class * with data members and a read/write() function, plus a mirroring isset * inner class. * * @param tstruct The struct definition */ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) { generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true); generate_struct_definition(f_types_impl_, f_types_impl_, tstruct, true, true); std::ostream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_); generate_struct_reader(out, tstruct); generate_struct_writer(out, tstruct); generate_struct_swap(f_types_impl_, tstruct); generate_copy_constructor(f_types_impl_, tstruct, is_exception); if (gen_moveable_) { generate_move_constructor(f_types_impl_, tstruct, is_exception); } generate_assignment_operator(f_types_impl_, tstruct); if (gen_moveable_) { generate_move_assignment_operator(f_types_impl_, tstruct); } if (!has_custom_ostream(tstruct)) { generate_struct_print_method(f_types_impl_, tstruct); } if (is_exception) { generate_exception_what_method(f_types_impl_, tstruct); } has_members_ = true; } void t_cpp_generator::generate_copy_constructor(ostream& out, t_struct* tstruct, bool is_exception) { generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/false); } void t_cpp_generator::generate_move_constructor(ostream& out, t_struct* tstruct, bool is_exception) { generate_constructor_helper(out, tstruct, is_exception, /*is_move=*/true); } namespace { // Helper to convert a variable to rvalue, if move is enabled std::string maybeMove(std::string const& other, bool move) { if (move) { return "std::move(" + other + ")"; } return other; } } void t_cpp_generator::generate_constructor_helper(ostream& out, t_struct* tstruct, bool is_exception, bool is_move) { std::string tmp_name = tmp("other"); indent(out) << tstruct->get_name() << "::" << tstruct->get_name(); if (is_move) { out << "(" << tstruct->get_name() << "&& "; } else { out << "(const " << tstruct->get_name() << "& "; } out << tmp_name << ") "; if(is_move || is_struct_storage_not_throwing(tstruct)) out << "noexcept "; if (is_exception) out << ": TException() "; out << "{" << endl; indent_up(); const vector& members = tstruct->get_members(); // eliminate compiler unused warning if (members.empty()) indent(out) << "(void) " << tmp_name << ";" << endl; vector::const_iterator f_iter; bool has_nonrequired_fields = false; for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) { if ((*f_iter)->get_req() != t_field::T_REQUIRED) has_nonrequired_fields = true; indent(out) << (*f_iter)->get_name() << " = " << maybeMove( tmp_name + "." + (*f_iter)->get_name(), is_move && is_complex_type((*f_iter)->get_type())) << ";" << endl; } if (has_nonrequired_fields) { indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", false) << ";" << endl; } indent_down(); indent(out) << "}" << endl; } void t_cpp_generator::generate_assignment_operator(ostream& out, t_struct* tstruct) { generate_assignment_helper(out, tstruct, /*is_move=*/false); } void t_cpp_generator::generate_move_assignment_operator(ostream& out, t_struct* tstruct) { generate_assignment_helper(out, tstruct, /*is_move=*/true); } void t_cpp_generator::generate_assignment_helper(ostream& out, t_struct* tstruct, bool is_move) { std::string tmp_name = tmp("other"); indent(out) << tstruct->get_name() << "& " << tstruct->get_name() << "::operator=("; if (is_move) { out << tstruct->get_name() << "&& "; } else { out << "const " << tstruct->get_name() << "& "; } out << tmp_name << ") "; if(is_move || is_struct_storage_not_throwing(tstruct)) out << "noexcept "; out << "{" << endl; indent_up(); const vector& members = tstruct->get_members(); // eliminate compiler unused warning if (members.empty()) indent(out) << "(void) " << tmp_name << ";" << endl; vector::const_iterator f_iter; bool has_nonrequired_fields = false; for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) { if ((*f_iter)->get_req() != t_field::T_REQUIRED) has_nonrequired_fields = true; indent(out) << (*f_iter)->get_name() << " = " << maybeMove( tmp_name + "." + (*f_iter)->get_name(), is_move && is_complex_type((*f_iter)->get_type())) << ";" << endl; } if (has_nonrequired_fields) { indent(out) << "__isset = " << maybeMove(tmp_name + ".__isset", false) << ";" << endl; } indent(out) << "return *this;" << endl; indent_down(); indent(out) << "}" << endl; } /** * Writes the struct declaration into the header file * * @param out Output stream * @param tstruct The struct */ void t_cpp_generator::generate_struct_declaration(ostream& out, t_struct* tstruct, bool is_exception, bool pointers, bool read, bool write, bool swap, bool is_user_struct) { string extends = ""; if (is_exception) { extends = " : public ::apache::thrift::TException"; } else { if (is_user_struct && !gen_templates_) { extends = " : public virtual ::apache::thrift::TBase"; } } // Get members vector::const_iterator m_iter; const vector& members = tstruct->get_members(); // Write the isset structure declaration outside the class. This makes // the generated code amenable to processing by SWIG. // We only declare the struct if it gets used in the class. // Isset struct has boolean fields, but only for non-required fields. bool has_nonrequired_fields = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) has_nonrequired_fields = true; } if (has_nonrequired_fields && (!pointers || read)) { out << indent() << "typedef struct _" << tstruct->get_name() << "__isset {" << endl; indent_up(); indent(out) << "_" << tstruct->get_name() << "__isset() "; bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() == t_field::T_REQUIRED) { continue; } string isSet = ((*m_iter)->get_value() != nullptr) ? "true" : "false"; if (first) { first = false; out << ": " << (*m_iter)->get_name() << "(" << isSet << ")"; } else { out << ", " << (*m_iter)->get_name() << "(" << isSet << ")"; } } out << " {}" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { indent(out) << "bool " << (*m_iter)->get_name() << " :1;" << endl; } } indent_down(); indent(out) << "} _" << tstruct->get_name() << "__isset;" << endl; } out << endl; generate_java_doc(out, tstruct); // Open struct def out << indent() << "class " << tstruct->get_name() << extends << " {" << endl << indent() << " public:" << endl << endl; indent_up(); if (!pointers) { bool ok_noexcept = is_struct_storage_not_throwing(tstruct); // Copy constructor indent(out) << tstruct->get_name() << "(const " << tstruct->get_name() << "&)" << (ok_noexcept? " noexcept" : "") << ';' << endl; // Move constructor if (gen_moveable_) { indent(out) << tstruct->get_name() << "(" << tstruct->get_name() << "&&) noexcept;" << endl; } // Assignment Operator indent(out) << tstruct->get_name() << "& operator=(const " << tstruct->get_name() << "&)" << (ok_noexcept? " noexcept" : "") << ';' << endl; // Move assignment operator if (gen_moveable_) { indent(out) << tstruct->get_name() << "& operator=(" << tstruct->get_name() << "&&) noexcept;" << endl; } bool has_default_value = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if (is_reference(*m_iter) || t->is_string()) { t_const_value* cv = (*m_iter)->get_value(); if (cv != nullptr) { has_default_value = true; break; } } } // Default constructor std::string clsname_ctor = tstruct->get_name() + "()"; indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept"); bool init_ctor = false; std::string args_indent( indent().size() + clsname_ctor.size() + (has_default_value ? 3 : -1), ' '); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) { string dval; t_const_value* cv = (*m_iter)->get_value(); if (cv != nullptr) { dval += render_const_value(out, (*m_iter)->get_name(), t, cv); } else if (t->is_enum()) { dval += "static_cast<" + type_name(t) + ">(0)"; } else { dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0"; } if (!init_ctor) { init_ctor = true; if(has_default_value) { out << " : "; } else { out << '\n' << args_indent << ": "; args_indent.append(" "); } } else { out << ",\n" << args_indent; } out << (*m_iter)->get_name() << "(" << dval << ")"; } } out << " {" << endl; indent_up(); // TODO(dreiss): When everything else in Thrift is perfect, // do more of these in the initializer list. for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if (!t->is_base_type() && !t->is_enum() && !is_reference(*m_iter)) { t_const_value* cv = (*m_iter)->get_value(); if (cv != nullptr) { print_const_value(out, (*m_iter)->get_name(), t, cv); } } } scope_down(out); } if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { out << endl << indent() << "virtual ~" << tstruct->get_name() << "() noexcept;" << endl; } // Declare all fields for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_java_doc(out, *m_iter); indent(out) << declare_field(*m_iter, false, (pointers && !(*m_iter)->get_type()->is_xception()), !read) << endl; } // Add the __isset data member if we need it, using the definition from above if (has_nonrequired_fields && (!pointers || read)) { out << endl << indent() << "_" << tstruct->get_name() << "__isset __isset;" << endl; } // Create a setter function for each field for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (pointers) { continue; } if (is_reference((*m_iter))) { out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::std::shared_ptr<" << type_name((*m_iter)->get_type(), false, false) << ">"; out << " val);" << endl; } else { out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true); out << " val);" << endl; } } out << endl; if (!pointers) { // Should we generate default operators? if (!gen_no_default_operators_) { // Generate an equality testing operator. Make it inline since the compiler // will do a better job than we would when deciding whether to inline it. out << indent() << "bool operator == (const " << tstruct->get_name() << " & " << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl; scope_up(out); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { // Most existing Thrift code does not use isset or optional/required, // so we treat "default" fields as required. if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl << indent() << " return false;" << endl; } else { out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset." << (*m_iter)->get_name() << ")" << endl << indent() << " return false;" << endl << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !(" << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl << indent() << " return false;" << endl; } } indent(out) << "return true;" << endl; scope_down(out); out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {" << endl << indent() << " return !(*this == rhs);" << endl << indent() << "}" << endl << endl; // Generate the declaration of a less-than operator. This must be // implemented by the application developer if they wish to use it. (They // will get a link error if they try to use it without an implementation.) out << indent() << "bool operator < (const " << tstruct->get_name() << " & ) const;" << endl << endl; } } if (read) { if (gen_templates_) { out << indent() << "template " << endl << indent() << "uint32_t read(Protocol_* iprot);" << endl; } else { out << indent() << "uint32_t read(" << "::apache::thrift::protocol::TProtocol* iprot)"; if(!is_exception && !extends.empty()) out << " override"; out << ';' << endl; } } if (write) { if (gen_templates_) { out << indent() << "template " << endl << indent() << "uint32_t write(Protocol_* oprot) const;" << endl; } else { out << indent() << "uint32_t write(" << "::apache::thrift::protocol::TProtocol* oprot) const"; if(!is_exception && !extends.empty()) out << " override"; out << ';' << endl; } } out << endl; if (is_user_struct && !has_custom_ostream(tstruct)) { out << indent() << "virtual "; generate_struct_print_method_decl(out, nullptr); out << ";" << endl; } // std::exception::what() if (is_exception) { out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << endl; out << indent(); generate_exception_what_method_decl(out, tstruct, false); out << ";" << endl; } indent_down(); indent(out) << "};" << endl << endl; if (swap) { // Generate a namespace-scope swap() function if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { out << indent() << "void swap(" << tstruct->get_name() << " &a1, " << tstruct->get_name() << " &a2);" << endl << endl; } else { out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() << " &b);" << endl << endl; } } if (is_user_struct) { generate_struct_ostream_operator_decl(out, tstruct); } } void t_cpp_generator::generate_struct_definition(ostream& out, ostream& force_cpp_out, t_struct* tstruct, bool setters, bool is_user_struct) { // Get members vector::const_iterator m_iter; const vector& members = tstruct->get_members(); // Destructor if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name() << "() noexcept {" << endl; indent_up(); indent_down(); force_cpp_out << indent() << "}" << endl << endl; } // Create a setter function for each field if (setters) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (is_reference((*m_iter))) { out << endl << indent() << "void " << tstruct->get_name() << "::__set_" << (*m_iter)->get_name() << "(::std::shared_ptr<" << type_name((*m_iter)->get_type(), false, false) << ">"; out << " val) {" << endl; } else { out << endl << indent() << "void " << tstruct->get_name() << "::__set_" << (*m_iter)->get_name() << "(" << type_name((*m_iter)->get_type(), false, true); out << " val) {" << endl; } indent_up(); out << indent() << "this->" << (*m_iter)->get_name() << " = val;" << endl; indent_down(); // assume all fields are required except optional fields. // for optional fields change __isset.name to true bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; if (is_optional) { out << indent() << indent() << "__isset." << (*m_iter)->get_name() << " = true;" << endl; } out << indent() << "}" << endl; } } if (is_user_struct) { generate_struct_ostream_operator(out, tstruct); } out << endl; } /** * Makes a helper function to gen a struct reader. * * @param out Stream to write to * @param tstruct The struct */ void t_cpp_generator::generate_struct_reader(ostream& out, t_struct* tstruct, bool pointers) { if (gen_templates_) { out << indent() << "template " << endl << indent() << "uint32_t " << tstruct->get_name() << "::read(Protocol_* iprot) {" << endl; } else { indent(out) << "uint32_t " << tstruct->get_name() << "::read(::apache::thrift::protocol::TProtocol* iprot) {" << endl; } indent_up(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; // Declare stack tmp variables out << endl << indent() << "::apache::thrift::protocol::TInputRecursionTracker tracker(*iprot);" << endl << indent() << "uint32_t xfer = 0;" << endl << indent() << "std::string fname;" << endl << indent() << "::apache::thrift::protocol::TType ftype;" << endl << indent() << "int16_t fid;" << endl << endl << indent() << "xfer += iprot->readStructBegin(fname);" << endl << endl << indent() << "using ::apache::thrift::protocol::TProtocolException;" << endl << endl; // Required variables aren't in __isset, so we need tmp vars to check them. for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; } out << endl; // Loop over reading in fields indent(out) << "while (true)" << endl; scope_up(out); // Read beginning field marker indent(out) << "xfer += iprot->readFieldBegin(fname, ftype, fid);" << endl; // Check for field STOP marker out << indent() << "if (ftype == ::apache::thrift::protocol::T_STOP) {" << endl << indent() << " break;" << endl << indent() << "}" << endl; if (fields.empty()) { out << indent() << "xfer += iprot->skip(ftype);" << endl; } else { // Switch statement on the field we are reading indent(out) << "switch (fid)" << endl; scope_up(out); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); indent(out) << "if (ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); const char* isset_prefix = ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset." : "isset_"; #if 0 // This code throws an exception if the same field is encountered twice. // We've decided to leave it out for performance reasons. // TODO(dreiss): Generate this code and "if" it out to make it easier // for people recompiling thrift to include it. out << indent() << "if (" << isset_prefix << (*f_iter)->get_name() << ")" << endl << indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; #endif if (pointers && !(*f_iter)->get_type()->is_xception()) { generate_deserialize_field(out, *f_iter, "(*(this->", "))"); } else { generate_deserialize_field(out, *f_iter, "this->"); } out << indent() << isset_prefix << (*f_iter)->get_name() << " = true;" << endl; indent_down(); out << indent() << "} else {" << endl << indent() << " xfer += iprot->skip(ftype);" << endl << // TODO(dreiss): Make this an option when thrift structs // have a common base class. // indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } // In the default case we skip the field out << indent() << "default:" << endl << indent() << " xfer += iprot->skip(ftype);" << endl << indent() << " break;" << endl; scope_down(out); } //!fields.empty() // Read field end marker indent(out) << "xfer += iprot->readFieldEnd();" << endl; scope_down(out); out << endl << indent() << "xfer += iprot->readStructEnd();" << endl; // Throw if any required fields are missing. // We do this after reading the struct end so that // there might possibly be a chance of continuing. out << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) out << indent() << "if (!isset_" << (*f_iter)->get_name() << ')' << endl << indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; } indent(out) << "return xfer;" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates the write function. * * @param out Stream to write to * @param tstruct The struct */ void t_cpp_generator::generate_struct_writer(ostream& out, t_struct* tstruct, bool pointers) { string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; if (gen_templates_) { out << indent() << "template " << endl << indent() << "uint32_t " << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl; } else { indent(out) << "uint32_t " << tstruct->get_name() << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl; } indent_up(); out << indent() << "uint32_t xfer = 0;" << endl; indent(out) << "::apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot);" << endl; indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool check_if_set = (*f_iter)->get_req() == t_field::T_OPTIONAL || (*f_iter)->get_type()->is_xception(); if (check_if_set) { out << endl << indent() << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl; indent_up(); } else { out << endl; } // Write field header out << indent() << "xfer += oprot->writeFieldBegin(" << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ");" << endl; // Write field contents if (pointers && !(*f_iter)->get_type()->is_xception()) { generate_serialize_field(out, *f_iter, "(*(this->", "))"); } else { generate_serialize_field(out, *f_iter, "this->"); } // Write field closer indent(out) << "xfer += oprot->writeFieldEnd();" << endl; if (check_if_set) { indent_down(); indent(out) << '}'; } } out << endl; // Write the struct map out << indent() << "xfer += oprot->writeFieldStop();" << endl << indent() << "xfer += oprot->writeStructEnd();" << endl << indent() << "return xfer;" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Struct writer for result of a function, which can have only one of its * fields set and does a conditional if else look up into the __isset field * of the struct. * * @param out Output stream * @param tstruct The result struct */ void t_cpp_generator::generate_struct_result_writer(ostream& out, t_struct* tstruct, bool pointers) { string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; if (gen_templates_) { out << indent() << "template " << endl << indent() << "uint32_t " << tstruct->get_name() << "::write(Protocol_* oprot) const {" << endl; } else { indent(out) << "uint32_t " << tstruct->get_name() << "::write(::apache::thrift::protocol::TProtocol* oprot) const {" << endl; } indent_up(); out << endl << indent() << "uint32_t xfer = 0;" << endl << endl; indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; out << endl << indent() << "if "; } else { out << " else if "; } out << "(this->__isset." << (*f_iter)->get_name() << ") {" << endl; indent_up(); // Write field header out << indent() << "xfer += oprot->writeFieldBegin(" << "\"" << (*f_iter)->get_name() << "\", " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ");" << endl; // Write field contents if (pointers) { generate_serialize_field(out, *f_iter, "(*(this->", "))"); } else { generate_serialize_field(out, *f_iter, "this->"); } // Write field closer indent(out) << "xfer += oprot->writeFieldEnd();" << endl; indent_down(); indent(out) << "}"; } // Write the struct map out << endl << indent() << "xfer += oprot->writeFieldStop();" << endl << indent() << "xfer += oprot->writeStructEnd();" << endl << indent() << "return xfer;" << endl; indent_down(); indent(out) << "}" << endl << endl; } /** * Generates the swap function. * * @param out Stream to write to * @param tstruct The struct */ void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) { if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { out << indent() << "void swap(" << tstruct->get_name() << " &a1, " << tstruct->get_name() << " &a2) {" << endl; } else { out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() << " &b) {" << endl; } indent_up(); // Let argument-dependent name lookup find the correct swap() function to // use based on the argument types. If none is found in the arguments' // namespaces, fall back to ::std::swap(). out << indent() << "using ::std::swap;" << endl; bool has_nonrequired_fields = false; const vector& fields = tstruct->get_members(); for (auto tfield : fields) { if (tfield->get_req() != t_field::T_REQUIRED) { has_nonrequired_fields = true; } if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { out << indent() << "swap(a1." << tfield->get_name() << ", a2." << tfield->get_name() << ");" << endl; } else { out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");" << endl; } } if (has_nonrequired_fields) { if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { out << indent() << "swap(a1.__isset, a2.__isset);" << endl; } else { out << indent() << "swap(a.__isset, b.__isset);" << endl; } } // handle empty structs if (fields.size() == 0) { if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { out << indent() << "(void) a1;" << endl; out << indent() << "(void) a2;" << endl; } else { out << indent() << "(void) a;" << endl; out << indent() << "(void) b;" << endl; } } scope_down(out); out << endl; } void t_cpp_generator::generate_struct_ostream_operator_decl(std::ostream& out, t_struct* tstruct) { out << "std::ostream& operator<<(std::ostream& out, const " << tstruct->get_name() << "& obj);" << endl; out << endl; } void t_cpp_generator::generate_struct_ostream_operator(std::ostream& out, t_struct* tstruct) { if (!has_custom_ostream(tstruct)) { // thrift defines this behavior out << "std::ostream& operator<<(std::ostream& out, const " << tstruct->get_name() << "& obj)" << endl; scope_up(out); out << indent() << "obj.printTo(out);" << endl << indent() << "return out;" << endl; scope_down(out); out << endl; } } void t_cpp_generator::generate_struct_print_method_decl(std::ostream& out, t_struct* tstruct) { out << "void "; if (tstruct) { out << tstruct->get_name() << "::"; } out << "printTo(std::ostream& out) const"; } void t_cpp_generator::generate_exception_what_method_decl(std::ostream& out, t_struct* tstruct, bool external) { out << "const char* "; if (external) { out << tstruct->get_name() << "::"; } out << "what() const noexcept"; if(!external) out << " override"; } namespace struct_ostream_operator_generator { void generate_required_field_value(std::ostream& out, const t_field* field) { out << " << to_string(" << field->get_name() << ")"; } void generate_optional_field_value(std::ostream& out, const t_field* field) { out << "; (__isset." << field->get_name() << " ? (out"; generate_required_field_value(out, field); out << ") : (out << \"\"))"; } void generate_field_value(std::ostream& out, const t_field* field) { if (field->get_req() == t_field::T_OPTIONAL) generate_optional_field_value(out, field); else generate_required_field_value(out, field); } void generate_field_name(std::ostream& out, const t_field* field) { out << "\"" << field->get_name() << "=\""; } void generate_field(std::ostream& out, const t_field* field) { generate_field_name(out, field); generate_field_value(out, field); } void generate_fields(std::ostream& out, const vector& fields, const std::string& indent) { const vector::const_iterator beg = fields.begin(); const vector::const_iterator end = fields.end(); for (vector::const_iterator it = beg; it != end; ++it) { out << indent << "out << "; if (it != beg) { out << "\", \" << "; } generate_field(out, *it); out << ";" << endl; } } } /** * Generates operator<< */ void t_cpp_generator::generate_struct_print_method(std::ostream& out, t_struct* tstruct) { out << indent(); generate_struct_print_method_decl(out, tstruct); out << " {" << endl; indent_up(); out << indent() << "using ::apache::thrift::to_string;" << endl; out << indent() << "out << \"" << tstruct->get_name() << "(\";" << endl; struct_ostream_operator_generator::generate_fields(out, tstruct->get_members(), indent()); out << indent() << "out << \")\";" << endl; indent_down(); out << "}" << endl << endl; } /** * Generates what() method for exceptions */ void t_cpp_generator::generate_exception_what_method(std::ostream& out, t_struct* tstruct) { out << indent(); generate_exception_what_method_decl(out, tstruct, true); out << " {" << endl; indent_up(); out << indent() << "try {" << endl; indent_up(); out << indent() << "std::stringstream ss;" << endl; out << indent() << "ss << \"TException - service has thrown: \" << *this;" << endl; out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << endl; out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << endl; indent_down(); out << indent() << "} catch (const std::exception&) {" << endl; indent_up(); out << indent() << "return \"TException - service has thrown: " << tstruct->get_name() << "\";" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << "}" << endl << endl; } /** * Generates a thrift service. In C++, this comprises an entirely separate * header and source file. The header file defines the methods and includes * the data types defined in the main header file, and the implementation * file contains implementations of the basic printer and default interfaces. * * @param tservice The service definition */ void t_cpp_generator::generate_service(t_service* tservice) { string svcname = tservice->get_name(); // Make output files string f_header_name = get_out_dir() + svcname + ".h"; f_header_.open(f_header_name.c_str()); // Print header file includes f_header_ << autogen_comment(); f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl << endl; if (gen_cob_style_) { f_header_ << "#include " << endl // TMemoryBuffer << "#include " << endl << "namespace apache { namespace thrift { namespace async {" << endl << "class TAsyncChannel;" << endl << "}}}" << endl; } f_header_ << "#include " << endl; if (gen_cob_style_) { f_header_ << "#include " << endl; } f_header_ << "#include " << endl; f_header_ << "#include " << endl; f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\"" << endl; t_service* extends_service = tservice->get_extends(); if (extends_service != nullptr) { f_header_ << "#include \"" << get_include_prefix(*(extends_service->get_program())) << extends_service->get_name() << ".h\"" << endl; } f_header_ << endl << ns_open_ << endl << endl; f_header_ << "#ifdef _MSC_VER\n" " #pragma warning( push )\n" " #pragma warning (disable : 4250 ) //inheriting methods via dominance \n" "#endif\n\n"; // Service implementation file includes string f_service_name = get_out_dir() + svcname + ".cpp"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment(); f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl; if (gen_cob_style_) { f_service_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl; } if (gen_templates_) { f_service_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" << endl; string f_service_tcc_name = get_out_dir() + svcname + ".tcc"; f_service_tcc_.open(f_service_tcc_name.c_str()); f_service_tcc_ << autogen_comment(); f_service_tcc_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl; f_service_tcc_ << "#ifndef " << svcname << "_TCC" << endl << "#define " << svcname << "_TCC" << endl << endl; if (gen_cob_style_) { f_service_tcc_ << "#include \"thrift/async/TAsyncChannel.h\"" << endl; } } f_service_ << endl << ns_open_ << endl << endl; f_service_tcc_ << endl << ns_open_ << endl << endl; // Generate all the components generate_service_interface(tservice, ""); generate_service_interface_factory(tservice, ""); generate_service_null(tservice, ""); generate_service_helpers(tservice); generate_service_client(tservice, ""); generate_service_processor(tservice, ""); generate_service_multiface(tservice); generate_service_client(tservice, "Concurrent"); // Generate skeleton if (!gen_no_skeleton_) { generate_service_skeleton(tservice); } // Generate all the cob components if (gen_cob_style_) { generate_service_interface(tservice, "CobCl"); generate_service_interface(tservice, "CobSv"); generate_service_interface_factory(tservice, "CobSv"); generate_service_null(tservice, "CobSv"); generate_service_client(tservice, "Cob"); generate_service_processor(tservice, "Cob"); if (!gen_no_skeleton_) { generate_service_async_skeleton(tservice); } } f_header_ << "#ifdef _MSC_VER\n" " #pragma warning( pop )\n" "#endif\n\n"; // Close the namespace f_service_ << ns_close_ << endl << endl; f_service_tcc_ << ns_close_ << endl << endl; f_header_ << ns_close_ << endl << endl; // TODO(simpkins): Make this a separate option if (gen_templates_) { f_header_ << "#include \"" << get_include_prefix(*get_program()) << svcname << ".tcc\"" << endl << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.tcc\"" << endl << endl; } f_header_ << "#endif" << endl; f_service_tcc_ << "#endif" << endl; // Close the files f_service_tcc_.close(); f_service_.close(); f_header_.close(); } /** * Generates helper functions for a service. Basically, this generates types * for all the arguments and results to functions. * * @param tservice The service to generate a header definition for */ void t_cpp_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); string name_orig = ts->get_name(); // TODO(dreiss): Why is this stuff not in generate_function_helpers? ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_args"); generate_struct_declaration(f_header_, ts, false); generate_struct_definition(out, f_service_, ts, false); generate_struct_reader(out, ts); generate_struct_writer(out, ts); ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs"); generate_struct_declaration(f_header_, ts, false, true, false, true); generate_struct_definition(out, f_service_, ts, false); generate_struct_writer(out, ts, true); ts->set_name(name_orig); generate_function_helpers(tservice, *f_iter); } } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_cpp_generator::generate_service_interface(t_service* tservice, string style) { string service_if_name = service_name_ + style + "If"; if (style == "CobCl") { // Forward declare the client. string client_name = service_name_ + "CobClient"; if (gen_templates_) { client_name += "T"; service_if_name += "T"; indent(f_header_) << "template " << endl; } indent(f_header_) << "class " << client_name << ";" << endl << endl; } string extends = ""; if (tservice->get_extends() != nullptr) { extends = " : virtual public " + type_name(tservice->get_extends()) + style + "If"; if (style == "CobCl" && gen_templates_) { // TODO(simpkins): If gen_templates_ is enabled, we currently assume all // parent services were also generated with templates enabled. extends += "T"; } } if (style == "CobCl" && gen_templates_) { f_header_ << "template " << endl; } generate_java_doc(f_header_, tservice); f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { if ((*f_iter)->has_doc()) f_header_ << endl; generate_java_doc(f_header_, *f_iter); f_header_ << indent() << "virtual " << function_signature(*f_iter, style) << " = 0;" << endl; } indent_down(); f_header_ << "};" << endl << endl; if (style == "CobCl" && gen_templates_) { // generate a backwards-compatible typedef for clients that do not // know about the new template-style code f_header_ << "typedef " << service_if_name << "< ::apache::thrift::protocol::TProtocol> " << service_name_ << style << "If;" << endl << endl; } } /** * Generates a service interface factory. * * @param tservice The service to generate an interface factory for. */ void t_cpp_generator::generate_service_interface_factory(t_service* tservice, string style) { string service_if_name = service_name_ + style + "If"; // Figure out the name of the upper-most parent class. // Getting everything to work out properly with inheritance is annoying. // Here's what we're doing for now: // // - All handlers implement getHandler(), but subclasses use covariant return // types to return their specific service interface class type. We have to // use raw pointers because of this; shared_ptr<> can't be used for // covariant return types. // // - Since we're not using shared_ptr<>, we also provide a releaseHandler() // function that must be called to release a pointer to a handler obtained // via getHandler(). // // releaseHandler() always accepts a pointer to the upper-most parent class // type. This is necessary since the parent versions of releaseHandler() // may accept any of the parent types, not just the most specific subclass // type. Implementations can use dynamic_cast to cast the pointer to the // subclass type if desired. t_service* base_service = tservice; while (base_service->get_extends() != nullptr) { base_service = base_service->get_extends(); } string base_if_name = type_name(base_service) + style + "If"; // Generate the abstract factory class string factory_name = service_if_name + "Factory"; string extends; if (tservice->get_extends() != nullptr) { extends = " : virtual public " + type_name(tservice->get_extends()) + style + "IfFactory"; } f_header_ << "class " << factory_name << extends << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << "typedef " << service_if_name << " Handler;" << endl << endl << indent() << "virtual ~" << factory_name << "() {}" << endl << endl << indent() << "virtual " << service_if_name << "* getHandler(" << "const ::apache::thrift::TConnectionInfo& connInfo)" << (extends.empty() ? "" : " override") << " = 0;" << endl << indent() << "virtual void releaseHandler(" << base_if_name << "* /* handler */)" << (extends.empty() ? "" : " override") << " = 0;" << endl << indent(); indent_down(); f_header_ << "};" << endl << endl; // Generate the singleton factory class string singleton_factory_name = service_if_name + "SingletonFactory"; f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << singleton_factory_name << "(const ::std::shared_ptr<" << service_if_name << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~" << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual " << service_if_name << "* getHandler(" << "const ::apache::thrift::TConnectionInfo&) override {" << endl << indent() << " return iface_.get();" << endl << indent() << "}" << endl << indent() << "virtual void releaseHandler(" << base_if_name << "* /* handler */) override {}" << endl; f_header_ << endl << " protected:" << endl << indent() << "::std::shared_ptr<" << service_if_name << "> iface_;" << endl; indent_down(); f_header_ << "};" << endl << endl; } /** * Generates a null implementation of the service. * * @param tservice The service to generate a header definition for */ void t_cpp_generator::generate_service_null(t_service* tservice, string style) { string extends = ""; if (tservice->get_extends() != nullptr) { extends = " , virtual public " + type_name(tservice->get_extends()) + style + "Null"; } f_header_ << "class " << service_name_ << style << "Null : virtual public " << service_name_ << style << "If" << extends << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << "virtual ~" << service_name_ << style << "Null() {}" << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_header_ << indent() << function_signature(*f_iter, style, "", false) << " override {" << endl; indent_up(); t_type* returntype = (*f_iter)->get_returntype(); t_field returnfield(returntype, "_return"); if (style == "") { if (returntype->is_void() || is_complex_type(returntype)) { f_header_ << indent() << "return;" << endl; } else { f_header_ << indent() << declare_field(&returnfield, true) << endl << indent() << "return _return;" << endl; } } else if (style == "CobSv") { if (returntype->is_void()) { f_header_ << indent() << "return cob();" << endl; } else { t_field returnfield(returntype, "_return"); f_header_ << indent() << declare_field(&returnfield, true) << endl << indent() << "return cob(_return);" << endl; } } else { throw "UNKNOWN STYLE"; } indent_down(); f_header_ << indent() << "}" << endl; } indent_down(); f_header_ << "};" << endl << endl; } void t_cpp_generator::generate_function_call(ostream& out, t_function* tfunction, string target, string iface, string arg_prefix) { bool first = true; t_type* ret_type = get_true_type(tfunction->get_returntype()); out << indent(); if (!tfunction->is_oneway() && !ret_type->is_void()) { if (is_complex_type(ret_type)) { first = false; out << iface << "->" << tfunction->get_name() << "(" << target; } else { out << target << " = " << iface << "->" << tfunction->get_name() << "("; } } else { out << iface << "->" << tfunction->get_name() << "("; } const std::vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { out << ", "; } out << arg_prefix << (*f_iter)->get_name(); } out << ");" << endl; } void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) { string svcname = tservice->get_name(); // Service implementation file includes string f_skeleton_name = get_out_dir() + svcname + "_async_server.skeleton.cpp"; string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp")); ofstream_with_content_based_conditional_update f_skeleton; f_skeleton.open(f_skeleton_name.c_str()); f_skeleton << "// This autogenerated skeleton file illustrates one way to adapt a synchronous" << endl << "// interface into an asynchronous interface. You should copy it to another" << endl << "// filename to avoid overwriting it and rewrite as asynchronous any functions" << endl << "// that would otherwise introduce unwanted latency." << endl << endl << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl << "#include " << endl << "#include " << endl << "#include " << endl << "#include " << endl << "#include " << endl << endl << "using namespace ::apache::thrift;" << endl << "using namespace ::apache::thrift::protocol;" << endl << "using namespace ::apache::thrift::transport;" << endl << "using namespace ::apache::thrift::async;" << endl << endl; // the following code would not compile: // using namespace ; // using namespace ::; if ((!ns.empty()) && (ns.compare(" ::") != 0)) { f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl; } f_skeleton << "class " << svcname << "Handler : virtual public " << svcname << "If {" << endl << " public:" << endl; indent_up(); f_skeleton << indent() << svcname << "Handler() {" << endl << indent() << " // Your initialization goes here" << endl << indent() << "}" << endl << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_skeleton, *f_iter); f_skeleton << indent() << function_signature(*f_iter, "") << " {" << endl << indent() << " // Your implementation goes here" << endl << indent() << " printf(\"" << (*f_iter)->get_name() << "\\n\");" << endl << indent() << "}" << endl << endl; } indent_down(); f_skeleton << "};" << endl << endl; f_skeleton << "class " << svcname << "AsyncHandler : " << "public " << svcname << "CobSvIf {" << endl << " public:" << endl; indent_up(); f_skeleton << indent() << svcname << "AsyncHandler() {" << endl << indent() << " syncHandler_ = std::unique_ptr<" << svcname << "Handler>(new " << svcname << "Handler);" << endl << indent() << " // Your initialization goes here" << endl << indent() << "}" << endl; f_skeleton << indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_skeleton << endl << indent() << function_signature(*f_iter, "CobSv", "", true) << " {" << endl; indent_up(); t_type* returntype = (*f_iter)->get_returntype(); t_field returnfield(returntype, "_return"); string target = returntype->is_void() ? "" : "_return"; if (!returntype->is_void()) { f_skeleton << indent() << declare_field(&returnfield, true) << endl; } generate_function_call(f_skeleton, *f_iter, target, "syncHandler_", ""); f_skeleton << indent() << "return cob(" << target << ");" << endl; scope_down(f_skeleton); } f_skeleton << endl << " protected:" << endl << indent() << "std::unique_ptr<" << svcname << "Handler> syncHandler_;" << endl; indent_down(); f_skeleton << "};" << endl << endl; f_skeleton << indent() << "int main(int argc, char **argv) {" << endl; indent_up(); f_skeleton << indent() << "int port = 9090;" << endl << indent() << "::std::shared_ptr<" << svcname << "AsyncHandler> handler(new " << svcname << "AsyncHandler());" << endl << indent() << "::std::shared_ptr<" << svcname << "AsyncProcessor> processor(new " << svcname << "AsyncProcessor(handler));" << endl << indent() << "::std::shared_ptr protocolFactory(new TBinaryProtocolFactory());" << endl << indent() << "::std::shared_ptr protocolProcessor(new TAsyncProtocolProcessor(processor, protocolFactory));" << endl << endl << indent() << "TEvhttpServer server(protocolProcessor, port);" << endl << indent() << "server.serve();" << endl << indent() << "return 0;" << endl; indent_down(); f_skeleton << "}" << endl << endl; } /** * Generates a multiface, which is a single server that just takes a set * of objects implementing the interface and calls them all, returning the * value of the last one to be called. * * @param tservice The service to generate a multiserver for. */ void t_cpp_generator::generate_service_multiface(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_multiface = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_multiface = ", public " + extends + "Multiface"; } string list_type = string("std::vector >"; // Generate the header portion f_header_ << "class " << service_name_ << "Multiface : " << "virtual public " << service_name_ << "If" << extends_multiface << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << service_name_ << "Multiface(" << list_type << "& ifaces) : ifaces_(ifaces) {" << endl; if (!extends.empty()) { f_header_ << indent() << " std::vector >::iterator iter;" << endl << indent() << " for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {" << endl << indent() << " " << extends << "Multiface::add(*iter);" << endl << indent() << " }" << endl; } f_header_ << indent() << "}" << endl << indent() << "virtual ~" << service_name_ << "Multiface() {}" << endl; indent_down(); // Protected data members f_header_ << " protected:" << endl; indent_up(); f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_ << "Multiface() {}" << endl << indent() << "void add(::std::shared_ptr<" << service_name_ << "If> iface) {" << endl; if (!extends.empty()) { f_header_ << indent() << " " << extends << "Multiface::add(iface);" << endl; } f_header_ << indent() << " ifaces_.push_back(iface);" << endl << indent() << "}" << endl; indent_down(); f_header_ << indent() << " public:" << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_header_, *f_iter); t_struct* arglist = (*f_iter)->get_arglist(); const vector& args = arglist->get_members(); vector::const_iterator a_iter; string call = string("ifaces_[i]->") + (*f_iter)->get_name() + "("; bool first = true; if (is_complex_type((*f_iter)->get_returntype())) { call += "_return"; first = false; } for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) { if (first) { first = false; } else { call += ", "; } call += (*a_iter)->get_name(); } call += ")"; f_header_ << indent() << function_signature(*f_iter, "") << " override {" << endl; indent_up(); f_header_ << indent() << "size_t sz = ifaces_.size();" << endl << indent() << "size_t i = 0;" << endl << indent() << "for (; i < (sz - 1); ++i) {" << endl; indent_up(); f_header_ << indent() << call << ";" << endl; indent_down(); f_header_ << indent() << "}" << endl; if (!(*f_iter)->get_returntype()->is_void()) { if (is_complex_type((*f_iter)->get_returntype())) { f_header_ << indent() << call << ";" << endl << indent() << "return;" << endl; } else { f_header_ << indent() << "return " << call << ";" << endl; } } else { f_header_ << indent() << call << ";" << endl; } indent_down(); f_header_ << indent() << "}" << endl << endl; } indent_down(); f_header_ << indent() << "};" << endl << endl; } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_cpp_generator::generate_service_client(t_service* tservice, string style) { string ifstyle; if (style == "Cob") { ifstyle = "CobCl"; } std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); string template_header, template_suffix, short_suffix, protocol_type, _this; string const prot_factory_type = "::apache::thrift::protocol::TProtocolFactory"; if (gen_templates_) { template_header = "template \n"; short_suffix = "T"; template_suffix = "T"; protocol_type = "Protocol_"; _this = "this->"; } else { protocol_type = "::apache::thrift::protocol::TProtocol"; } string prot_ptr = "std::shared_ptr< " + protocol_type + ">"; string client_suffix = "Client" + template_suffix; string if_suffix = "If"; if (style == "Cob") { if_suffix += template_suffix; } string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { // TODO(simpkins): If gen_templates_ is enabled, we currently assume all // parent services were also generated with templates enabled. extends = type_name(tservice->get_extends()); extends_client = ", public " + extends + style + client_suffix; } // Generate the header portion if (style == "Concurrent") { f_header_ << "// The \'concurrent\' client is a thread safe client that correctly handles\n" "// out of order responses. It is slower than the regular client, so should\n" "// only be used when you need to share a connection among multiple threads\n"; } f_header_ << template_header << "class " << service_name_ << style << "Client" << short_suffix << " : " << "virtual public " << service_name_ << ifstyle << if_suffix << extends_client << " {" << endl << " public:" << endl; indent_up(); if (style != "Cob") { f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr << " prot"; if (style == "Concurrent") { f_header_ << ", std::shared_ptr< ::apache::thrift::async::TConcurrentClientSyncInfo> sync"; } f_header_ << ") "; if (extends.empty()) { if (style == "Concurrent") { f_header_ << ": sync_(sync)" << endl; } f_header_ << "{" << endl; f_header_ << indent() << " setProtocol" << short_suffix << "(prot);" << endl << indent() << "}" << endl; } else { f_header_ << ":" << endl; f_header_ << indent() << " " << extends << style << client_suffix << "(prot, prot"; if (style == "Concurrent") { f_header_ << ", sync"; } f_header_ << ") {}" << endl; } f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr << " iprot, " << prot_ptr << " oprot"; if (style == "Concurrent") { f_header_ << ", std::shared_ptr< ::apache::thrift::async::TConcurrentClientSyncInfo> sync"; } f_header_ << ") "; if (extends.empty()) { if (style == "Concurrent") { f_header_ << ": sync_(sync)" << endl; } f_header_ << "{" << endl; f_header_ << indent() << " setProtocol" << short_suffix << "(iprot,oprot);" << endl << indent() << "}" << endl; } else { f_header_ << ":" << indent() << " " << extends << style << client_suffix << "(iprot, oprot"; if (style == "Concurrent") { f_header_ << ", sync"; } f_header_ << ") {}" << endl; } // create the setProtocol methods if (extends.empty()) { f_header_ << " private:" << endl; // 1: one parameter f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " prot) {" << endl; f_header_ << indent() << "setProtocol" << short_suffix << "(prot,prot);" << endl; f_header_ << indent() << "}" << endl; // 2: two parameter f_header_ << indent() << "void setProtocol" << short_suffix << "(" << prot_ptr << " iprot, " << prot_ptr << " oprot) {" << endl; f_header_ << indent() << " piprot_=iprot;" << endl << indent() << " poprot_=oprot;" << endl << indent() << " iprot_ = iprot.get();" << endl << indent() << " oprot_ = oprot.get();" << endl; f_header_ << indent() << "}" << endl; f_header_ << " public:" << endl; } // Generate getters for the protocols. // Note that these are not currently templated for simplicity. // TODO(simpkins): should they be templated? f_header_ << indent() << "std::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {" << endl << indent() << " return " << _this << "piprot_;" << endl << indent() << "}" << endl; f_header_ << indent() << "std::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {" << endl << indent() << " return " << _this << "poprot_;" << endl << indent() << "}" << endl; } else /* if (style == "Cob") */ { f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << "std::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, " << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl; if (extends.empty()) { f_header_ << indent() << " channel_(channel)," << endl << indent() << " itrans_(new ::apache::thrift::transport::TMemoryBuffer())," << endl << indent() << " otrans_(new ::apache::thrift::transport::TMemoryBuffer())," << endl; if (gen_templates_) { // TProtocolFactory classes return generic TProtocol pointers. // We have to dynamic cast to the Protocol_ type we are expecting. f_header_ << indent() << " piprot_(::std::dynamic_pointer_cast(" << "protocolFactory->getProtocol(itrans_)))," << endl << indent() << " poprot_(::std::dynamic_pointer_cast(" << "protocolFactory->getProtocol(otrans_))) {" << endl; // Throw a TException if either dynamic cast failed. f_header_ << indent() << " if (!piprot_ || !poprot_) {" << endl << indent() << " throw ::apache::thrift::TException(\"" << "TProtocolFactory returned unexpected protocol type in " << service_name_ << style << "Client" << short_suffix << " constructor\");" << endl << indent() << " }" << endl; } else { f_header_ << indent() << " piprot_(protocolFactory->getProtocol(itrans_))," << endl << indent() << " poprot_(protocolFactory->getProtocol(otrans_)) {" << endl; } f_header_ << indent() << " iprot_ = piprot_.get();" << endl << indent() << " oprot_ = poprot_.get();" << endl << indent() << "}" << endl; } else { f_header_ << indent() << " " << extends << style << client_suffix << "(channel, protocolFactory) {}" << endl; } } if (style == "Cob") { generate_java_doc(f_header_, tservice); f_header_ << indent() << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl << indent() << " return " << _this << "channel_;" << endl << indent() << "}" << endl; if (!gen_no_client_completion_) { f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl; } } vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_header_, *f_iter); indent(f_header_) << function_signature(*f_iter, ifstyle) << " override;" << endl; // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style. if (style == "Concurrent" && !(*f_iter)->is_oneway()) { // concurrent clients need to move the seqid from the send function to the // recv function. Oneway methods don't have a recv function, so we don't need to // move the seqid for them. Attempting to do so would result in a seqid leak. t_function send_function(g_type_i32, /*returning seqid*/ string("send_") + (*f_iter)->get_name(), (*f_iter)->get_arglist()); indent(f_header_) << function_signature(&send_function, "") << ";" << endl; } else { t_function send_function(g_type_void, string("send_") + (*f_iter)->get_name(), (*f_iter)->get_arglist()); indent(f_header_) << function_signature(&send_function, "") << ";" << endl; } if (!(*f_iter)->is_oneway()) { if (style == "Concurrent") { t_field seqIdArg(g_type_i32, "seqid"); t_struct seqIdArgStruct(program_); seqIdArgStruct.append(&seqIdArg); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &seqIdArgStruct); indent(f_header_) << function_signature(&recv_function, "") << ";" << endl; } else { t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); indent(f_header_) << function_signature(&recv_function, "") << ";" << endl; } } } indent_down(); if (extends.empty()) { f_header_ << " protected:" << endl; indent_up(); if (style == "Cob") { f_header_ << indent() << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl << indent() << "::std::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl << indent() << "::std::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;" << endl; } f_header_ << indent() << prot_ptr << " piprot_;" << endl << indent() << prot_ptr << " poprot_;" << endl << indent() << protocol_type << "* iprot_;" << endl << indent() << protocol_type << "* oprot_;" << endl; if (style == "Concurrent") { f_header_ << indent() << "std::shared_ptr< ::apache::thrift::async::TConcurrentClientSyncInfo> sync_;"< " << service_name_ << style << "Client;" << endl << endl; } string scope = service_name_ + style + client_suffix + "::"; // Generate client method implementations for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string seqIdCapture; string seqIdUse; string seqIdCommaUse; if (style == "Concurrent" && !(*f_iter)->is_oneway()) { seqIdCapture = "int32_t seqid = "; seqIdUse = "seqid"; seqIdCommaUse = ", seqid"; } string funname = (*f_iter)->get_name(); // Open function if (gen_templates_) { indent(out) << template_header; } indent(out) << function_signature(*f_iter, ifstyle, scope) << endl; scope_up(out); indent(out) << seqIdCapture << "send_" << funname << "("; // Get the struct of function call params t_struct* arg_struct = (*f_iter)->get_arglist(); // Declare the function arguments const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { out << ", "; } out << (*fld_iter)->get_name(); } out << ");" << endl; if (style != "Cob") { if (!(*f_iter)->is_oneway()) { out << indent(); if (!(*f_iter)->get_returntype()->is_void()) { if (is_complex_type((*f_iter)->get_returntype())) { out << "recv_" << funname << "(_return" << seqIdCommaUse << ");" << endl; } else { out << "return recv_" << funname << "(" << seqIdUse << ");" << endl; } } else { out << "recv_" << funname << "(" << seqIdUse << ");" << endl; } } } else { if (!(*f_iter)->is_oneway()) { out << indent() << _this << "channel_->sendAndRecvMessage(" << "::std::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());" << endl; } else { out << indent() << _this << "channel_->sendMessage(" << "::std::bind(cob, this), " << _this << "otrans_.get());" << endl; } } scope_down(out); out << endl; // if (style != "Cob") // TODO(dreiss): Libify the client and don't generate this for cob-style if (true) { t_type* send_func_return_type = g_type_void; if (style == "Concurrent" && !(*f_iter)->is_oneway()) { send_func_return_type = g_type_i32; } // Function for sending t_function send_function(send_func_return_type, string("send_") + (*f_iter)->get_name(), (*f_iter)->get_arglist()); // Open the send function if (gen_templates_) { indent(out) << template_header; } indent(out) << function_signature(&send_function, "", scope) << endl; scope_up(out); // Function arguments and results string argsname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs"; string resultname = tservice->get_name() + "_" + (*f_iter)->get_name() + "_presult"; string cseqidVal = "0"; if (style == "Concurrent") { if (!(*f_iter)->is_oneway()) { cseqidVal = "this->sync_->generateSeqId()"; } } // Serialize the request out << indent() << "int32_t cseqid = " << cseqidVal << ";" << endl; if(style == "Concurrent") { out << indent() << "::apache::thrift::async::TConcurrentSendSentry sentry(this->sync_.get());" << endl; } if (style == "Cob") { out << indent() << _this << "otrans_->resetBuffer();" << endl; } out << indent() << _this << "oprot_->writeMessageBegin(\"" << (*f_iter)->get_name() << "\", ::apache::thrift::protocol::" << ((*f_iter)->is_oneway() ? "T_ONEWAY" : "T_CALL") << ", cseqid);" << endl << endl << indent() << argsname << " args;" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { out << indent() << "args." << (*fld_iter)->get_name() << " = &" << (*fld_iter)->get_name() << ";" << endl; } out << indent() << "args.write(" << _this << "oprot_);" << endl << endl << indent() << _this << "oprot_->writeMessageEnd();" << endl << indent() << _this << "oprot_->getTransport()->writeEnd();" << endl << indent() << _this << "oprot_->getTransport()->flush();" << endl; if (style == "Concurrent") { out << endl << indent() << "sentry.commit();" << endl; if (!(*f_iter)->is_oneway()) { out << indent() << "return cseqid;" << endl; } } scope_down(out); out << endl; // Generate recv function only if not an oneway function if (!(*f_iter)->is_oneway()) { t_struct noargs(program_); t_field seqIdArg(g_type_i32, "seqid"); t_struct seqIdArgStruct(program_); seqIdArgStruct.append(&seqIdArg); t_struct* recv_function_args = &noargs; if (style == "Concurrent") { recv_function_args = &seqIdArgStruct; } t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), recv_function_args); // Open the recv function if (gen_templates_) { indent(out) << template_header; } indent(out) << function_signature(&recv_function, "", scope) << endl; scope_up(out); out << endl << indent() << "int32_t rseqid = 0;" << endl << indent() << "std::string fname;" << endl << indent() << "::apache::thrift::protocol::TMessageType mtype;" << endl; if(style == "Concurrent") { out << endl << indent() << "// the read mutex gets dropped and reacquired as part of waitForWork()" << endl << indent() << "// The destructor of this sentry wakes up other clients" << endl << indent() << "::apache::thrift::async::TConcurrentRecvSentry sentry(this->sync_.get(), seqid);" << endl; } if (style == "Cob" && !gen_no_client_completion_) { out << indent() << "bool completed = false;" << endl << endl << indent() << "try {"; indent_up(); } out << endl; if (style == "Concurrent") { out << indent() << "while(true) {" << endl << indent() << " if(!this->sync_->getPending(fname, mtype, rseqid)) {" << endl; indent_up(); indent_up(); } out << indent() << _this << "iprot_->readMessageBegin(fname, mtype, rseqid);" << endl; if (style == "Concurrent") { scope_down(out); out << indent() << "if(seqid == rseqid) {" << endl; indent_up(); } out << indent() << "if (mtype == ::apache::thrift::protocol::T_EXCEPTION) {" << endl << indent() << " ::apache::thrift::TApplicationException x;" << endl << indent() << " x.read(" << _this << "iprot_);" << endl << indent() << " " << _this << "iprot_->readMessageEnd();" << endl << indent() << " " << _this << "iprot_->getTransport()->readEnd();" << endl; if (style == "Cob" && !gen_no_client_completion_) { out << indent() << " completed = true;" << endl << indent() << " completed__(true);" << endl; } if (style == "Concurrent") { out << indent() << " sentry.commit();" << endl; } out << indent() << " throw x;" << endl << indent() << "}" << endl << indent() << "if (mtype != ::apache::thrift::protocol::T_REPLY) {" << endl << indent() << " " << _this << "iprot_->skip(" << "::apache::thrift::protocol::T_STRUCT);" << endl << indent() << " " << _this << "iprot_->readMessageEnd();" << endl << indent() << " " << _this << "iprot_->getTransport()->readEnd();" << endl; if (style == "Cob" && !gen_no_client_completion_) { out << indent() << " completed = true;" << endl << indent() << " completed__(false);" << endl; } out << indent() << "}" << endl << indent() << "if (fname.compare(\"" << (*f_iter)->get_name() << "\") != 0) {" << endl << indent() << " " << _this << "iprot_->skip(" << "::apache::thrift::protocol::T_STRUCT);" << endl << indent() << " " << _this << "iprot_->readMessageEnd();" << endl << indent() << " " << _this << "iprot_->getTransport()->readEnd();" << endl; if (style == "Cob" && !gen_no_client_completion_) { out << indent() << " completed = true;" << endl << indent() << " completed__(false);" << endl; } if (style == "Concurrent") { out << endl << indent() << " // in a bad state, don't commit" << endl << indent() << " using ::apache::thrift::protocol::TProtocolException;" << endl << indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; } out << indent() << "}" << endl; if (!(*f_iter)->get_returntype()->is_void() && !is_complex_type((*f_iter)->get_returntype())) { t_field returnfield((*f_iter)->get_returntype(), "_return"); out << indent() << declare_field(&returnfield) << endl; } out << indent() << resultname << " result;" << endl; if (!(*f_iter)->get_returntype()->is_void()) { out << indent() << "result.success = &_return;" << endl; } out << indent() << "result.read(" << _this << "iprot_);" << endl << indent() << _this << "iprot_->readMessageEnd();" << endl << indent() << _this << "iprot_->getTransport()->readEnd();" << endl << endl; // Careful, only look for _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { if (is_complex_type((*f_iter)->get_returntype())) { out << indent() << "if (result.__isset.success) {" << endl; out << indent() << " // _return pointer has now been filled" << endl; if (style == "Cob" && !gen_no_client_completion_) { out << indent() << " completed = true;" << endl << indent() << " completed__(true);" << endl; } if (style == "Concurrent") { out << indent() << " sentry.commit();" << endl; } out << indent() << " return;" << endl << indent() << "}" << endl; } else { out << indent() << "if (result.__isset.success) {" << endl; if (style == "Cob" && !gen_no_client_completion_) { out << indent() << " completed = true;" << endl << indent() << " completed__(true);" << endl; } if (style == "Concurrent") { out << indent() << " sentry.commit();" << endl; } out << indent() << " return _return;" << endl << indent() << "}" << endl; } } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << indent() << "if (result.__isset." << (*x_iter)->get_name() << ") {" << endl; if (style == "Cob" && !gen_no_client_completion_) { out << indent() << " completed = true;" << endl << indent() << " completed__(true);" << endl; } if (style == "Concurrent") { out << indent() << " sentry.commit();" << endl; } out << indent() << " throw result." << (*x_iter)->get_name() << ";" << endl << indent() << "}" << endl; } // We only get here if we are a void function if ((*f_iter)->get_returntype()->is_void()) { if (style == "Cob" && !gen_no_client_completion_) { out << indent() << "completed = true;" << endl << indent() << "completed__(true);" << endl; } if (style == "Concurrent") { out << indent() << "sentry.commit();" << endl; } indent(out) << "return;" << endl; } else { if (style == "Cob" && !gen_no_client_completion_) { out << indent() << "completed = true;" << endl << indent() << "completed__(true);" << endl; } if (style == "Concurrent") { out << indent() << "// in a bad state, don't commit" << endl; } out << indent() << "throw " "::apache::thrift::TApplicationException(::apache::thrift::" "TApplicationException::MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } if (style == "Concurrent") { indent_down(); indent_down(); out << indent() << " }" << endl << indent() << " // seqid != rseqid" << endl << indent() << " this->sync_->updatePending(fname, mtype, rseqid);" << endl << endl << indent() << " // this will temporarily unlock the readMutex, and let other clients get work done" << endl << indent() << " this->sync_->waitForWork(seqid);" << endl << indent() << "} // end while(true)" << endl; } if (style == "Cob" && !gen_no_client_completion_) { indent_down(); out << indent() << "} catch (...) {" << endl << indent() << " if (!completed) {" << endl << indent() << " completed__(false);" << endl << indent() << " }" << endl << indent() << " throw;" << endl << indent() << "}" << endl; } // Close function scope_down(out); out << endl; } } } } class ProcessorGenerator { public: ProcessorGenerator(t_cpp_generator* generator, t_service* service, const string& style); void run() { generate_class_definition(); // Generate the dispatchCall() function generate_dispatch_call(false); if (generator_->gen_templates_) { generate_dispatch_call(true); } // Generate all of the process subfunctions generate_process_functions(); generate_factory(); } void generate_class_definition(); void generate_dispatch_call(bool template_protocol); void generate_process_functions(); void generate_factory(); protected: std::string type_name(t_type* ttype, bool in_typedef = false, bool arg = false) { return generator_->type_name(ttype, in_typedef, arg); } std::string indent() { return generator_->indent(); } std::ostream& indent(std::ostream& os) { return generator_->indent(os); } void indent_up() { generator_->indent_up(); } void indent_down() { generator_->indent_down(); } t_cpp_generator* generator_; t_service* service_; std::ostream& f_header_; std::ostream& f_out_; string service_name_; string style_; string pstyle_; string class_name_; string if_name_; string factory_class_name_; string finish_cob_; string finish_cob_decl_; string ret_type_; string call_context_; string cob_arg_; string call_context_arg_; string call_context_decl_; string template_header_; string template_suffix_; string typename_str_; string class_suffix_; string extends_; }; ProcessorGenerator::ProcessorGenerator(t_cpp_generator* generator, t_service* service, const string& style) : generator_(generator), service_(service), f_header_(generator->f_header_), f_out_(generator->gen_templates_ ? generator->f_service_tcc_ : generator->f_service_), service_name_(generator->service_name_), style_(style) { if (style_ == "Cob") { pstyle_ = "Async"; class_name_ = service_name_ + pstyle_ + "Processor"; if_name_ = service_name_ + "CobSvIf"; finish_cob_ = "::std::function cob, "; finish_cob_decl_ = "::std::function, "; cob_arg_ = "cob, "; ret_type_ = "void "; } else { class_name_ = service_name_ + "Processor"; if_name_ = service_name_ + "If"; ret_type_ = "bool "; // TODO(edhall) callContext should eventually be added to TAsyncProcessor call_context_ = ", void* callContext"; call_context_arg_ = ", callContext"; call_context_decl_ = ", void*"; } factory_class_name_ = class_name_ + "Factory"; if (generator->gen_templates_) { template_header_ = "template \n"; template_suffix_ = ""; typename_str_ = "typename "; class_name_ += "T"; factory_class_name_ += "T"; } if (service_->get_extends() != nullptr) { extends_ = type_name(service_->get_extends()) + pstyle_ + "Processor"; if (generator_->gen_templates_) { // TODO(simpkins): If gen_templates_ is enabled, we currently assume all // parent services were also generated with templates enabled. extends_ += "T"; } } } void ProcessorGenerator::generate_class_definition() { // Generate the dispatch methods vector functions = service_->get_functions(); vector::iterator f_iter; string parent_class; if (service_->get_extends() != nullptr) { parent_class = extends_; } else { if (style_ == "Cob") { parent_class = "::apache::thrift::async::TAsyncDispatchProcessor"; } else { parent_class = "::apache::thrift::TDispatchProcessor"; } if (generator_->gen_templates_) { parent_class += "T"; } } // Generate the header portion f_header_ << template_header_ << "class " << class_name_ << " : public " << parent_class << " {" << endl; // Protected data members f_header_ << " protected:" << endl; indent_up(); f_header_ << indent() << "::std::shared_ptr<" << if_name_ << "> iface_;" << endl; f_header_ << indent() << "virtual " << ret_type_ << "dispatchCall(" << finish_cob_ << "::apache::thrift::protocol::TProtocol* iprot, " << "::apache::thrift::protocol::TProtocol* oprot, " << "const std::string& fname, int32_t seqid" << call_context_ << ") override;" << endl; if (generator_->gen_templates_) { f_header_ << indent() << "virtual " << ret_type_ << "dispatchCallTemplated(" << finish_cob_ << "Protocol_* iprot, Protocol_* oprot, " << "const std::string& fname, int32_t seqid" << call_context_ << ");" << endl; } indent_down(); // Process function declarations f_header_ << " private:" << endl; indent_up(); // Declare processMap_ f_header_ << indent() << "typedef void (" << class_name_ << "::*" << "ProcessFunction)(" << finish_cob_decl_ << "int32_t, " << "::apache::thrift::protocol::TProtocol*, " << "::apache::thrift::protocol::TProtocol*" << call_context_decl_ << ");" << endl; if (generator_->gen_templates_) { f_header_ << indent() << "typedef void (" << class_name_ << "::*" << "SpecializedProcessFunction)(" << finish_cob_decl_ << "int32_t, " << "Protocol_*, Protocol_*" << call_context_decl_ << ");" << endl << indent() << "struct ProcessFunctions {" << endl << indent() << " ProcessFunction generic;" << endl << indent() << " SpecializedProcessFunction specialized;" << endl << indent() << " ProcessFunctions(ProcessFunction g, " << "SpecializedProcessFunction s) :" << endl << indent() << " generic(g)," << endl << indent() << " specialized(s) {}" << endl << indent() << " ProcessFunctions() : generic(nullptr), specialized(nullptr) " << "{}" << endl << indent() << "};" << endl << indent() << "typedef std::map " << "ProcessMap;" << endl; } else { f_header_ << indent() << "typedef std::map " << "ProcessMap;" << endl; } f_header_ << indent() << "ProcessMap processMap_;" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent(f_header_) << "void process_" << (*f_iter)->get_name() << "(" << finish_cob_ << "int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, " "::apache::thrift::protocol::TProtocol* oprot" << call_context_ << ");" << endl; if (generator_->gen_templates_) { indent(f_header_) << "void process_" << (*f_iter)->get_name() << "(" << finish_cob_ << "int32_t seqid, Protocol_* iprot, Protocol_* oprot" << call_context_ << ");" << endl; } if (style_ == "Cob") { // XXX Factor this out, even if it is a pain. string ret_arg = ((*f_iter)->get_returntype()->is_void() ? "" : ", const " + type_name((*f_iter)->get_returntype()) + "& _return"); f_header_ << indent() << "void return_" << (*f_iter)->get_name() << "(::std::function cob, int32_t seqid, " << "::apache::thrift::protocol::TProtocol* oprot, " << "void* ctx" << ret_arg << ");" << endl; if (generator_->gen_templates_) { f_header_ << indent() << "void return_" << (*f_iter)->get_name() << "(::std::function cob, int32_t seqid, " << "Protocol_* oprot, void* ctx" << ret_arg << ");" << endl; } // XXX Don't declare throw if it doesn't exist f_header_ << indent() << "void throw_" << (*f_iter)->get_name() << "(::std::function cob, int32_t seqid, " << "::apache::thrift::protocol::TProtocol* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw);" << endl; if (generator_->gen_templates_) { f_header_ << indent() << "void throw_" << (*f_iter)->get_name() << "(::std::function cob, int32_t seqid, " << "Protocol_* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw);" << endl; } } } f_header_ << " public:" << endl << indent() << class_name_ << "(::std::shared_ptr<" << if_name_ << "> iface) :" << endl; if (!extends_.empty()) { f_header_ << indent() << " " << extends_ << "(iface)," << endl; } f_header_ << indent() << " iface_(iface) {" << endl; indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_header_ << indent() << "processMap_[\"" << (*f_iter)->get_name() << "\"] = "; if (generator_->gen_templates_) { f_header_ << "ProcessFunctions(" << endl; if (generator_->gen_templates_only_) { indent(f_header_) << " nullptr," << endl; } else { indent(f_header_) << " &" << class_name_ << "::process_" << (*f_iter)->get_name() << "," << endl; } indent(f_header_) << " &" << class_name_ << "::process_" << (*f_iter)->get_name() << ")"; } else { f_header_ << "&" << class_name_ << "::process_" << (*f_iter)->get_name(); } f_header_ << ";" << endl; } indent_down(); f_header_ << indent() << "}" << endl << endl << indent() << "virtual ~" << class_name_ << "() {}" << endl; indent_down(); f_header_ << "};" << endl << endl; if (generator_->gen_templates_) { // Generate a backwards compatible typedef, for callers who don't know // about the new template-style code. // // We can't use TProtocol as the template parameter, since ProcessorT // provides overloaded versions of most methods, one of which accepts // TProtocol pointers, and one which accepts Protocol_ pointers. This // results in a compile error if instantiated with Protocol_ == TProtocol. // Therefore, we define TDummyProtocol solely so we can use it as the // template parameter here. f_header_ << "typedef " << class_name_ << "< ::apache::thrift::protocol::TDummyProtocol > " << service_name_ << pstyle_ << "Processor;" << endl << endl; } } void ProcessorGenerator::generate_dispatch_call(bool template_protocol) { string protocol = "::apache::thrift::protocol::TProtocol"; string function_suffix; if (template_protocol) { protocol = "Protocol_"; // We call the generic version dispatchCall(), and the specialized // version dispatchCallTemplated(). We can't call them both // dispatchCall(), since this will cause the compiler to issue a warning if // a service that doesn't use templates inherits from a service that does // use templates: the compiler complains that the subclass only implements // the generic version of dispatchCall(), and hides the templated version. // Using different names for the two functions prevents this. function_suffix = "Templated"; } f_out_ << template_header_ << ret_type_ << class_name_ << template_suffix_ << "::dispatchCall" << function_suffix << "(" << finish_cob_ << protocol << "* iprot, " << protocol << "* oprot, " << "const std::string& fname, int32_t seqid" << call_context_ << ") {" << endl; indent_up(); // HOT: member function pointer map f_out_ << indent() << typename_str_ << "ProcessMap::iterator pfn;" << endl << indent() << "pfn = processMap_.find(fname);" << endl << indent() << "if (pfn == processMap_.end()) {" << endl; if (extends_.empty()) { f_out_ << indent() << " iprot->skip(::apache::thrift::protocol::T_STRUCT);" << endl << indent() << " iprot->readMessageEnd();" << endl << indent() << " iprot->getTransport()->readEnd();" << endl << indent() << " ::apache::thrift::TApplicationException " "x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, \"Invalid method name: " "'\"+fname+\"'\");" << endl << indent() << " oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent() << " x.write(oprot);" << endl << indent() << " oprot->writeMessageEnd();" << endl << indent() << " oprot->getTransport()->writeEnd();" << endl << indent() << " oprot->getTransport()->flush();" << endl << indent() << (style_ == "Cob" ? " return cob(true);" : " return true;") << endl; } else { f_out_ << indent() << " return " << extends_ << "::dispatchCall(" << (style_ == "Cob" ? "cob, " : "") << "iprot, oprot, fname, seqid" << call_context_arg_ << ");" << endl; } f_out_ << indent() << "}" << endl; if (template_protocol) { f_out_ << indent() << "(this->*(pfn->second.specialized))"; } else { if (generator_->gen_templates_only_) { // TODO: This is a null pointer, so nothing good will come from calling // it. Throw an exception instead. f_out_ << indent() << "(this->*(pfn->second.generic))"; } else if (generator_->gen_templates_) { f_out_ << indent() << "(this->*(pfn->second.generic))"; } else { f_out_ << indent() << "(this->*(pfn->second))"; } } f_out_ << "(" << cob_arg_ << "seqid, iprot, oprot" << call_context_arg_ << ");" << endl; // TODO(dreiss): return pfn ret? if (style_ == "Cob") { f_out_ << indent() << "return;" << endl; } else { f_out_ << indent() << "return true;" << endl; } indent_down(); f_out_ << "}" << endl << endl; } void ProcessorGenerator::generate_process_functions() { vector functions = service_->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { if (generator_->gen_templates_) { generator_->generate_process_function(service_, *f_iter, style_, false); generator_->generate_process_function(service_, *f_iter, style_, true); } else { generator_->generate_process_function(service_, *f_iter, style_, false); } } } void ProcessorGenerator::generate_factory() { string if_factory_name = if_name_ + "Factory"; // Generate the factory class definition f_header_ << template_header_ << "class " << factory_class_name_ << " : public ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessorFactory" : "TProcessorFactory") << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << factory_class_name_ << "(const ::std::shared_ptr< " << if_factory_name << " >& handlerFactory) noexcept :" << endl << indent() << " handlerFactory_(handlerFactory) {}" << endl << endl << indent() << "::std::shared_ptr< ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " << "getProcessor(const ::apache::thrift::TConnectionInfo& connInfo) override;" << endl; f_header_ << endl << " protected:" << endl << indent() << "::std::shared_ptr< " << if_factory_name << " > handlerFactory_;" << endl; indent_down(); f_header_ << "};" << endl << endl; // If we are generating templates, output a typedef for the plain // factory name. if (generator_->gen_templates_) { f_header_ << "typedef " << factory_class_name_ << "< ::apache::thrift::protocol::TDummyProtocol > " << service_name_ << pstyle_ << "ProcessorFactory;" << endl << endl; } // Generate the getProcessor() method f_out_ << template_header_ << indent() << "::std::shared_ptr< ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " << factory_class_name_ << template_suffix_ << "::getProcessor(" << "const ::apache::thrift::TConnectionInfo& connInfo) {" << endl; indent_up(); f_out_ << indent() << "::apache::thrift::ReleaseHandler< " << if_factory_name << " > cleanup(handlerFactory_);" << endl << indent() << "::std::shared_ptr< " << if_name_ << " > handler(" << "handlerFactory_->getHandler(connInfo), cleanup);" << endl << indent() << "::std::shared_ptr< ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " << "processor(new " << class_name_ << template_suffix_ << "(handler));" << endl << indent() << "return processor;" << endl; indent_down(); f_out_ << indent() << "}" << endl << endl; } /** * Generates a service processor definition. * * @param tservice The service to generate a processor for. */ void t_cpp_generator::generate_service_processor(t_service* tservice, string style) { ProcessorGenerator generator(this, tservice, style); generator.run(); } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_cpp_generator::generate_function_helpers(t_service* tservice, t_function* tfunction) { if (tfunction->is_oneway()) { return; } std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); t_struct result(program_, tservice->get_name() + "_" + tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_struct_declaration(f_header_, &result, false); generate_struct_definition(out, f_service_, &result, false); generate_struct_reader(out, &result); generate_struct_result_writer(out, &result); result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult"); generate_struct_declaration(f_header_, &result, false, true, true, gen_cob_style_); generate_struct_definition(out, f_service_, &result, false); generate_struct_reader(out, &result, true); if (gen_cob_style_) { generate_struct_writer(out, &result, true); } } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_cpp_generator::generate_process_function(t_service* tservice, t_function* tfunction, string style, bool specialized) { t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; string service_func_name = "\"" + tservice->get_name() + "." + tfunction->get_name() + "\""; std::ostream& out = (gen_templates_ ? f_service_tcc_ : f_service_); string prot_type = (specialized ? "Protocol_" : "::apache::thrift::protocol::TProtocol"); string class_suffix; if (gen_templates_) { class_suffix = "T"; } // I tried to do this as one function. I really did. But it was too hard. if (style != "Cob") { // Open function if (gen_templates_) { out << indent() << "template " << endl; } const bool unnamed_oprot_seqid = tfunction->is_oneway() && !(gen_templates_ && !specialized); out << "void " << tservice->get_name() << "Processor" << class_suffix << "::" << "process_" << tfunction->get_name() << "(" << "int32_t" << (unnamed_oprot_seqid ? ", " : " seqid, ") << prot_type << "* iprot, " << prot_type << "*" << (unnamed_oprot_seqid ? ", " : " oprot, ") << "void* callContext)" << endl; scope_up(out); string argsname = tservice->get_name() + "_" + tfunction->get_name() + "_args"; string resultname = tservice->get_name() + "_" + tfunction->get_name() + "_result"; if (tfunction->is_oneway() && !unnamed_oprot_seqid) { out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl; } out << indent() << "void* ctx = nullptr;" << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " ctx = this->eventHandler_->getContext(" << service_func_name << ", callContext);" << endl << indent() << "}" << endl << indent() << "::apache::thrift::TProcessorContextFreer freer(" << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->preRead(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << endl << indent() << argsname << " args;" << endl << indent() << "args.read(iprot);" << endl << indent() << "iprot->readMessageEnd();" << endl << indent() << "uint32_t bytes = iprot->getTransport()->readEnd();" << endl << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->postRead(ctx, " << service_func_name << ", bytes);" << endl << indent() << "}" << endl << endl; // Declare result if (!tfunction->is_oneway()) { out << indent() << resultname << " result;" << endl; } // Try block for functions with exceptions out << indent() << "try {" << endl; indent_up(); // Generate the function call bool first = true; out << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { if (is_complex_type(tfunction->get_returntype())) { first = false; out << "iface_->" << tfunction->get_name() << "(result.success"; } else { out << "result.success = iface_->" << tfunction->get_name() << "("; } } else { out << "iface_->" << tfunction->get_name() << "("; } for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { out << ", "; } out << "args." << (*f_iter)->get_name(); } out << ");" << endl; // Set isset on success field if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { out << indent() << "result.__isset.success = true;" << endl; } indent_down(); out << indent() << "}"; if (!tfunction->is_oneway()) { for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << " catch (" << type_name((*x_iter)->get_type()) << " &" << (*x_iter)->get_name() << ") {" << endl; if (!tfunction->is_oneway()) { indent_up(); out << indent() << "result." << (*x_iter)->get_name() << " = std::move(" << (*x_iter)->get_name() << ");" << endl << indent() << "result.__isset." << (*x_iter)->get_name() << " = true;" << endl; indent_down(); out << indent() << "}"; } else { out << "}"; } } } if (!tfunction->is_oneway()) { out << " catch (const std::exception& e) {" << endl; } else { out << " catch (const std::exception&) {" << endl; } indent_up(); out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl; if (!tfunction->is_oneway()) { out << endl << indent() << "::apache::thrift::TApplicationException x(e.what());" << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent() << "x.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl << indent() << "oprot->getTransport()->writeEnd();" << endl << indent() << "oprot->getTransport()->flush();" << endl; } out << indent() << "return;" << endl; indent_down(); out << indent() << "}" << endl << endl; // Shortcut out here for oneway functions if (tfunction->is_oneway()) { out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->asyncComplete(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << endl << indent() << "return;" << endl; indent_down(); out << "}" << endl << endl; return; } // Serialize the result into a struct out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl << indent() << "bytes = oprot->getTransport()->writeEnd();" << endl << indent() << "oprot->getTransport()->flush();" << endl << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl << indent() << "}" << endl; // Close function scope_down(out); out << endl; } // Cob style. else { // Processor entry point. // TODO(edhall) update for callContext when TEventServer is ready if (gen_templates_) { out << indent() << "template " << endl; } out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::process_" << tfunction->get_name() << "(::std::function cob, int32_t seqid, " << prot_type << "* iprot, " << prot_type << "* oprot)" << endl; scope_up(out); // TODO(simpkins): we could try to consoldate this // with the non-cob code above if (gen_templates_ && !specialized) { // If these are instances of Protocol_, instead of any old TProtocol, // use the specialized process function instead. out << indent() << "Protocol_* _iprot = dynamic_cast(iprot);" << endl << indent() << "Protocol_* _oprot = dynamic_cast(oprot);" << endl << indent() << "if (_iprot && _oprot) {" << endl << indent() << " return process_" << tfunction->get_name() << "(cob, seqid, _iprot, _oprot);" << endl << indent() << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, iprot, _iprot);" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl; } if (tfunction->is_oneway()) { out << indent() << "(void) seqid;" << endl << indent() << "(void) oprot;" << endl; } out << indent() << tservice->get_name() + "_" + tfunction->get_name() << "_args args;" << endl << indent() << "void* ctx = nullptr;" << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " ctx = this->eventHandler_->getContext(" << service_func_name << ", nullptr);" << endl << indent() << "}" << endl << indent() << "::apache::thrift::TProcessorContextFreer freer(" << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl << indent() << "try {" << endl; indent_up(); out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->preRead(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << indent() << "args.read(iprot);" << endl << indent() << "iprot->readMessageEnd();" << endl << indent() << "uint32_t bytes = iprot->getTransport()->readEnd();" << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->postRead(ctx, " << service_func_name << ", bytes);" << endl << indent() << "}" << endl; scope_down(out); // TODO(dreiss): Handle TExceptions? Expose to server? out << indent() << "catch (const std::exception&) {" << endl << indent() << " if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl << indent() << " }" << endl << indent() << " return cob(false);" << endl << indent() << "}" << endl; if (tfunction->is_oneway()) { out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->asyncComplete(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl; } // TODO(dreiss): Figure out a strategy for exceptions in async handlers. out << indent() << "freer.unregister();" << endl; if (tfunction->is_oneway()) { // No return. Just hand off our cob. // TODO(dreiss): Call the cob immediately? out << indent() << "iface_->" << tfunction->get_name() << "(" << "::std::bind(cob, true)" << endl; indent_up(); indent_up(); } else { string ret_arg, ret_placeholder; if (!tfunction->get_returntype()->is_void()) { ret_arg = ", const " + type_name(tfunction->get_returntype()) + "& _return"; ret_placeholder = ", ::std::placeholders::_1"; } // When gen_templates_ is true, the return_ and throw_ functions are // overloaded. We have to declare pointers to them so that the compiler // can resolve the correct overloaded version. out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix << "::*return_fn)(::std::function " << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg << ") =" << endl; out << indent() << " &" << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_" << tfunction->get_name() << ";" << endl; if (!xceptions.empty()) { out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix << "::*throw_fn)(::std::function " << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw) =" << endl; out << indent() << " &" << tservice->get_name() << "AsyncProcessor" << class_suffix << "::throw_" << tfunction->get_name() << ";" << endl; } out << indent() << "iface_->" << tfunction->get_name() << "(" << endl; indent_up(); indent_up(); out << indent() << "::std::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder << ")"; if (!xceptions.empty()) { out << ',' << endl << indent() << "::std::bind(throw_fn, this, cob, seqid, oprot, " << "ctx, ::std::placeholders::_1)"; } } // XXX Whitespace cleanup. for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << ',' << endl << indent() << "args." << (*f_iter)->get_name(); } out << ");" << endl; indent_down(); indent_down(); scope_down(out); out << endl; // Normal return. if (!tfunction->is_oneway()) { string ret_arg_decl, ret_arg_name; if (!tfunction->get_returntype()->is_void()) { ret_arg_decl = ", const " + type_name(tfunction->get_returntype()) + "& _return"; ret_arg_name = ", _return"; } if (gen_templates_) { out << indent() << "template " << endl; } out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_" << tfunction->get_name() << "(::std::function cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg_decl << ')' << endl; scope_up(out); if (gen_templates_ && !specialized) { // If oprot is a Protocol_ instance, // use the specialized return function instead. out << indent() << "Protocol_* _oprot = dynamic_cast(oprot);" << endl << indent() << "if (_oprot) {" << endl << indent() << " return return_" << tfunction->get_name() << "(cob, seqid, _oprot, ctx" << ret_arg_name << ");" << endl << indent() << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl; } out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_presult result;" << endl; if (!tfunction->get_returntype()->is_void()) { // The const_cast here is unfortunate, but it would be a pain to avoid, // and we only do a write with this struct, which is const-safe. out << indent() << "result.success = const_cast<" << type_name(tfunction->get_returntype()) << "*>(&_return);" << endl << indent() << "result.__isset.success = true;" << endl; } // Serialize the result into a struct out << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " ctx = this->eventHandler_->getContext(" << service_func_name << ", nullptr);" << endl << indent() << "}" << endl << indent() << "::apache::thrift::TProcessorContextFreer freer(" << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl << indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" << endl << indent() << "oprot->getTransport()->flush();" << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl << indent() << "}" << endl << indent() << "return cob(true);" << endl; scope_down(out); out << endl; } // Exception return. if (!tfunction->is_oneway() && !xceptions.empty()) { if (gen_templates_) { out << indent() << "template " << endl; } out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::throw_" << tfunction->get_name() << "(::std::function cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw)" << endl; scope_up(out); if (gen_templates_ && !specialized) { // If oprot is a Protocol_ instance, // use the specialized throw function instead. out << indent() << "Protocol_* _oprot = dynamic_cast(oprot);" << endl << indent() << "if (_oprot) {" << endl << indent() << " return throw_" << tfunction->get_name() << "(cob, seqid, _oprot, ctx, _throw);" << endl << indent() << "}" << endl << indent() << "T_GENERIC_PROTOCOL(this, oprot, _oprot);" << endl << endl; } // Get the event handler context out << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " ctx = this->eventHandler_->getContext(" << service_func_name << ", nullptr);" << endl << indent() << "}" << endl << indent() << "::apache::thrift::TProcessorContextFreer freer(" << "this->eventHandler_.get(), ctx, " << service_func_name << ");" << endl << endl; // Throw the TDelayedException, and catch the result out << indent() << tservice->get_name() << "_" << tfunction->get_name() << "_result result;" << endl << endl << indent() << "try {" << endl; indent_up(); out << indent() << "_throw->throw_it();" << endl << indent() << "return cob(false);" << endl; // Is this possible? TBD. indent_down(); out << indent() << '}'; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << " catch (" << type_name((*x_iter)->get_type()) << " &" << (*x_iter)->get_name() << ") {" << endl; indent_up(); out << indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl << indent() << "result.__isset." << (*x_iter)->get_name() << " = true;" << endl; scope_down(out); } // Handle the case where an undeclared exception is thrown out << " catch (std::exception& e) {" << endl; indent_up(); out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->handlerError(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << endl << indent() << "::apache::thrift::TApplicationException x(e.what());" << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", ::apache::thrift::protocol::T_EXCEPTION, seqid);" << endl << indent() << "x.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl << indent() << "oprot->getTransport()->writeEnd();" << endl << indent() << "oprot->getTransport()->flush();" << endl << // We pass true to the cob here, since we did successfully write a // response, even though it is an exception response. // It looks like the argument is currently ignored, anyway. indent() << "return cob(true);" << endl; scope_down(out); // Serialize the result into a struct out << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->preWrite(ctx, " << service_func_name << ");" << endl << indent() << "}" << endl << endl << indent() << "oprot->writeMessageBegin(\"" << tfunction->get_name() << "\", ::apache::thrift::protocol::T_REPLY, seqid);" << endl << indent() << "result.write(oprot);" << endl << indent() << "oprot->writeMessageEnd();" << endl << indent() << "uint32_t bytes = oprot->getTransport()->writeEnd();" << endl << indent() << "oprot->getTransport()->flush();" << endl << indent() << "if (this->eventHandler_.get() != nullptr) {" << endl << indent() << " this->eventHandler_->postWrite(ctx, " << service_func_name << ", bytes);" << endl << indent() << "}" << endl << indent() << "return cob(true);" << endl; scope_down(out); out << endl; } // for each function } // cob style } /** * Generates a skeleton file of a server * * @param tservice The service to generate a server for. */ void t_cpp_generator::generate_service_skeleton(t_service* tservice) { string svcname = tservice->get_name(); // Service implementation file includes string f_skeleton_name = get_out_dir() + svcname + "_server.skeleton.cpp"; string ns = namespace_prefix(tservice->get_program()->get_namespace("cpp")); ofstream_with_content_based_conditional_update f_skeleton; f_skeleton.open(f_skeleton_name.c_str()); f_skeleton << "// This autogenerated skeleton file illustrates how to build a server." << endl << "// You should copy it to another filename to avoid overwriting it." << endl << endl << "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl << "#include " << endl << "#include " << endl << "#include " << endl << "#include " << endl << endl << "using namespace ::apache::thrift;" << endl << "using namespace ::apache::thrift::protocol;" << endl << "using namespace ::apache::thrift::transport;" << endl << "using namespace ::apache::thrift::server;" << endl << endl; // the following code would not compile: // using namespace ; // using namespace ::; if ((!ns.empty()) && (ns.compare(" ::") != 0)) { f_skeleton << "using namespace " << string(ns, 0, ns.size() - 2) << ";" << endl << endl; } f_skeleton << "class " << svcname << "Handler : virtual public " << svcname << "If {" << endl << " public:" << endl; indent_up(); f_skeleton << indent() << svcname << "Handler() {" << endl << indent() << " // Your initialization goes here" << endl << indent() << "}" << endl << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_java_doc(f_skeleton, *f_iter); f_skeleton << indent() << function_signature(*f_iter, "") << " {" << endl << indent() << " // Your implementation goes here" << endl << indent() << " printf(\"" << (*f_iter)->get_name() << "\\n\");" << endl << indent() << "}" << endl << endl; } indent_down(); f_skeleton << "};" << endl << endl; f_skeleton << indent() << "int main(int argc, char **argv) {" << endl; indent_up(); f_skeleton << indent() << "int port = 9090;" << endl << indent() << "::std::shared_ptr<" << svcname << "Handler> handler(new " << svcname << "Handler());" << endl << indent() << "::std::shared_ptr processor(new " << svcname << "Processor(handler));" << endl << indent() << "::std::shared_ptr serverTransport(new TServerSocket(port));" << endl << indent() << "::std::shared_ptr transportFactory(new TBufferedTransportFactory());" << endl << indent() << "::std::shared_ptr protocolFactory(new TBinaryProtocolFactory());" << endl << endl << indent() << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);" << endl << indent() << "server.serve();" << endl << indent() << "return 0;" << endl; indent_down(); f_skeleton << "}" << endl << endl; // Close the files f_skeleton.close(); } /** * Deserializes a field of any type. */ void t_cpp_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, string suffix) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + tfield->get_name() + suffix; if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name, is_reference(tfield)); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type()) { indent(out) << "xfer += iprot->"; t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "readBinary(" << name << ");"; } else { out << "readString(" << name << ");"; } break; case t_base_type::TYPE_BOOL: out << "readBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "readByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "readI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "readI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "readI64(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble(" << name << ");"; break; default: throw "compiler error: no C++ reader for base type " + t_base_type::t_base_name(tbase) + name; } out << endl; } else if (type->is_enum()) { string t = tmp("ecast"); out << indent() << "int32_t " << t << ";" << endl << indent() << "xfer += iprot->readI32(" << t << ");" << endl << indent() << name << " = static_cast<" << type_name(type) << ">(" << t << ");" << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); } } /** * Generates an unserializer for a variable. This makes two key assumptions, * first that there is a const char* variable named data that points to the * buffer for deserialization, and that there is a variable protocol which * is a reference to a TProtocol serialization object. */ void t_cpp_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix, bool pointer) { if (pointer) { indent(out) << "if (!" << prefix << ") { " << endl; indent(out) << " " << prefix << " = ::std::shared_ptr<" << type_name(tstruct) << ">(new " << type_name(tstruct) << ");" << endl; indent(out) << "}" << endl; indent(out) << "xfer += " << prefix << "->read(iprot);" << endl; indent(out) << "bool wasSet = false;" << endl; const vector& members = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = members.begin(); f_iter != members.end(); ++f_iter) { indent(out) << "if (" << prefix << "->__isset." << (*f_iter)->get_name() << ") { wasSet = true; }" << endl; } indent(out) << "if (!wasSet) { " << prefix << ".reset(); }" << endl; } else { indent(out) << "xfer += " << prefix << ".read(iprot);" << endl; } } void t_cpp_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); string size = tmp("_size"); string ktype = tmp("_ktype"); string vtype = tmp("_vtype"); string etype = tmp("_etype"); t_container* tcontainer = (t_container*)ttype; bool use_push = tcontainer->has_cpp_name(); indent(out) << prefix << ".clear();" << endl << indent() << "uint32_t " << size << ";" << endl; // Declare variables, read header if (ttype->is_map()) { out << indent() << "::apache::thrift::protocol::TType " << ktype << ";" << endl << indent() << "::apache::thrift::protocol::TType " << vtype << ";" << endl << indent() << "xfer += iprot->readMapBegin(" << ktype << ", " << vtype << ", " << size << ");" << endl; } else if (ttype->is_set()) { out << indent() << "::apache::thrift::protocol::TType " << etype << ";" << endl << indent() << "xfer += iprot->readSetBegin(" << etype << ", " << size << ");" << endl; } else if (ttype->is_list()) { out << indent() << "::apache::thrift::protocol::TType " << etype << ";" << endl << indent() << "xfer += iprot->readListBegin(" << etype << ", " << size << ");" << endl; if (!use_push) { indent(out) << prefix << ".resize(" << size << ");" << endl; } } // For loop iterates over elements string i = tmp("_i"); out << indent() << "uint32_t " << i << ";" << endl << indent() << "for (" << i << " = 0; " << i << " < " << size << "; ++" << i << ")" << endl; scope_up(out); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix, use_push, i); } scope_down(out); // Read container end if (ttype->is_map()) { indent(out) << "xfer += iprot->readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "xfer += iprot->readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "xfer += iprot->readListEnd();" << endl; } scope_down(out); } /** * Generates code to deserialize a map */ void t_cpp_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); out << indent() << declare_field(&fkey) << endl; generate_deserialize_field(out, &fkey); indent(out) << declare_field(&fval, false, false, false, true) << " = " << prefix << "[" << key << "];" << endl; generate_deserialize_field(out, &fval); } void t_cpp_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".insert(" << elem << ");" << endl; } void t_cpp_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix, bool use_push, string index) { if (use_push) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << declare_field(&felem) << endl; generate_deserialize_field(out, &felem); indent(out) << prefix << ".push_back(" << elem << ");" << endl; } else { t_field felem(tlist->get_elem_type(), prefix + "[" + index + "]"); generate_deserialize_field(out, &felem); } } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_cpp_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, string suffix) { t_type* type = get_true_type(tfield->get_type()); string name = prefix + tfield->get_name() + suffix; // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, name, is_reference(tfield)); } else if (type->is_container()) { generate_serialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << "xfer += oprot->"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "writeBinary(" << name << ");"; } else { out << "writeString(" << name << ");"; } break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ");"; break; default: throw "compiler error: no C++ writer for base type " + t_base_type::t_base_name(tbase) + name; } } else if (type->is_enum()) { out << "writeI32(static_cast(" << name << "));"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n", name.c_str(), type_name(type).c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_cpp_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, bool pointer) { if (pointer) { indent(out) << "if (" << prefix << ") {" << endl; indent(out) << " xfer += " << prefix << "->write(oprot); " << endl; indent(out) << "} else {" << "oprot->writeStructBegin(\"" << tstruct->get_name() << "\"); " << endl; indent(out) << " oprot->writeStructEnd();" << endl; indent(out) << " oprot->writeFieldStop();" << endl; indent(out) << "}" << endl; } else { indent(out) << "xfer += " << prefix << ".write(oprot);" << endl; } } void t_cpp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { scope_up(out); if (ttype->is_map()) { indent(out) << "xfer += oprot->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "static_cast(" << prefix << ".size()));" << endl; } else if (ttype->is_set()) { indent(out) << "xfer += oprot->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << "static_cast(" << prefix << ".size()));" << endl; } else if (ttype->is_list()) { indent(out) << "xfer += oprot->writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << "static_cast(" << prefix << ".size()));" << endl; } string iter = tmp("_iter"); out << indent() << type_name(ttype) << "::const_iterator " << iter << ";" << endl << indent() << "for (" << iter << " = " << prefix << ".begin(); " << iter << " != " << prefix << ".end(); ++" << iter << ")" << endl; scope_up(out); if (ttype->is_map()) { generate_serialize_map_element(out, (t_map*)ttype, iter); } else if (ttype->is_set()) { generate_serialize_set_element(out, (t_set*)ttype, iter); } else if (ttype->is_list()) { generate_serialize_list_element(out, (t_list*)ttype, iter); } scope_down(out); if (ttype->is_map()) { indent(out) << "xfer += oprot->writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "xfer += oprot->writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "xfer += oprot->writeListEnd();" << endl; } scope_down(out); } /** * Serializes the members of a map. * */ void t_cpp_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter) { t_field kfield(tmap->get_key_type(), iter + "->first"); generate_serialize_field(out, &kfield, ""); t_field vfield(tmap->get_val_type(), iter + "->second"); generate_serialize_field(out, &vfield, ""); } /** * Serializes the members of a set. */ void t_cpp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), "(*" + iter + ")"); generate_serialize_field(out, &efield, ""); } /** * Serializes the members of a list. */ void t_cpp_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), "(*" + iter + ")"); generate_serialize_field(out, &efield, ""); } /** * Makes a :: prefix for a namespace * * @param ns The namespace, w/ periods in it * @return Namespaces */ string t_cpp_generator::namespace_prefix(string ns) { // Always start with "::", to avoid possible name collisions with // other names in one of the current namespaces. // // We also need a leading space, in case the name is used inside of a // template parameter. "MyTemplate<::foo::Bar>" is not valid C++, // since "<:" is an alternative token for "[". string result = " ::"; if (ns.size() == 0) { return result; } string::size_type loc; while ((loc = ns.find(".")) != string::npos) { result += ns.substr(0, loc); result += "::"; ns = ns.substr(loc + 1); } if (ns.size() > 0) { result += ns + "::"; } return result; } /** * Opens namespace. * * @param ns The namespace, w/ periods in it * @return Namespaces */ string t_cpp_generator::namespace_open(string ns) { if (ns.size() == 0) { return ""; } string result = ""; string separator = ""; string::size_type loc; while ((loc = ns.find(".")) != string::npos) { result += separator; result += "namespace "; result += ns.substr(0, loc); result += " {"; separator = " "; ns = ns.substr(loc + 1); } if (ns.size() > 0) { result += separator + "namespace " + ns + " {"; } return result; } /** * Closes namespace. * * @param ns The namespace, w/ periods in it * @return Namespaces */ string t_cpp_generator::namespace_close(string ns) { if (ns.size() == 0) { return ""; } string result = "}"; string::size_type loc; while ((loc = ns.find(".")) != string::npos) { result += "}"; ns = ns.substr(loc + 1); } result += " // namespace"; return result; } /** * Returns a C++ type name * * @param ttype The type * @return String of the type name, i.e. std::set */ string t_cpp_generator::type_name(t_type* ttype, bool in_typedef, bool arg) { if (ttype->is_base_type()) { string bname = base_type_name(((t_base_type*)ttype)->get_base()); std::map>::iterator it = ttype->annotations_.find("cpp.type"); if (it != ttype->annotations_.end() && !it->second.empty()) { bname = it->second.back(); } if (!arg) { return bname; } if (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING) { return "const " + bname + "&"; } else { return "const " + bname; } } // Check for a custom overloaded C++ name if (ttype->is_container()) { string cname; t_container* tcontainer = (t_container*)ttype; if (tcontainer->has_cpp_name()) { cname = tcontainer->get_cpp_name(); } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; cname = "std::map<" + type_name(tmap->get_key_type(), in_typedef) + ", " + type_name(tmap->get_val_type(), in_typedef) + "> "; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; cname = "std::set<" + type_name(tset->get_elem_type(), in_typedef) + "> "; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; cname = "std::vector<" + type_name(tlist->get_elem_type(), in_typedef) + "> "; } if (arg) { return "const " + cname + "&"; } else { return cname; } } string class_prefix; if (in_typedef && (ttype->is_struct() || ttype->is_xception())) { class_prefix = "class "; } // Check if it needs to be namespaced string pname; t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { pname = class_prefix + namespace_prefix(program->get_namespace("cpp")) + ttype->get_name(); } else { pname = class_prefix + ttype->get_name(); } if (ttype->is_enum() && !gen_pure_enums_) { pname += "::type"; } if (arg) { if (is_complex_type(ttype)) { return "const " + pname + "&"; } else { return "const " + pname; } } else { return pname; } } /** * Returns the C++ type that corresponds to the thrift type. * * @param tbase The base type * @return Explicit C++ type, i.e. "int32_t" */ string t_cpp_generator::base_type_name(t_base_type::t_base tbase) { switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: return "std::string"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "int8_t"; case t_base_type::TYPE_I16: return "int16_t"; case t_base_type::TYPE_I32: return "int32_t"; case t_base_type::TYPE_I64: return "int64_t"; case t_base_type::TYPE_DOUBLE: return "double"; default: throw "compiler error: no C++ base type name for base type " + t_base_type::t_base_name(tbase); } } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type * @return Field declaration, i.e. int x = 0; */ string t_cpp_generator::declare_field(t_field* tfield, bool init, bool pointer, bool constant, bool reference) { // TODO(mcslee): do we ever need to initialize the field? string result = ""; if (constant) { result += "const "; } result += type_name(tfield->get_type()); if (is_reference(tfield)) { result = "::std::shared_ptr<" + result + ">"; } if (pointer) { result += "*"; } if (reference) { result += "&"; } result += " " + tfield->get_name(); if (init) { t_type* type = get_true_type(tfield->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: case t_base_type::TYPE_STRING: break; case t_base_type::TYPE_BOOL: result += " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = 0.0"; break; default: throw "compiler error: no C++ initializer for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { result += " = static_cast<" + type_name(type) + ">(0)"; } } if (!reference) { result += ";"; } return result; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_cpp_generator::function_signature(t_function* tfunction, string style, string prefix, bool name_params) { t_type* ttype = tfunction->get_returntype(); t_struct* arglist = tfunction->get_arglist(); bool has_xceptions = !tfunction->get_xceptions()->get_members().empty(); if (style == "") { if (is_complex_type(ttype)) { return "void " + prefix + tfunction->get_name() + "(" + type_name(ttype) + (name_params ? "& _return" : "& /* _return */") + argument_list(arglist, name_params, true) + ")"; } else { return type_name(ttype) + " " + prefix + tfunction->get_name() + "(" + argument_list(arglist, name_params) + ")"; } } else if (style.substr(0, 3) == "Cob") { string cob_type; string exn_cob; if (style == "CobCl") { cob_type = "(" + service_name_ + "CobClient"; if (gen_templates_) { cob_type += "T"; } cob_type += "* client)"; } else if (style == "CobSv") { cob_type = (ttype->is_void() ? "()" : ("(" + type_name(ttype) + " const& _return)")); if (has_xceptions) { exn_cob = ", ::std::function /* exn_cob */"; } } else { throw "UNKNOWN STYLE"; } return "void " + prefix + tfunction->get_name() + "(::std::function cob" + exn_cob + argument_list(arglist, name_params, true) + ")"; } else { throw "UNKNOWN STYLE"; } } /** * Renders a field list * * @param tstruct The struct definition * @return Comma sepearated list of all field names in that struct */ string t_cpp_generator::argument_list(t_struct* tstruct, bool name_params, bool start_comma) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = !start_comma; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += type_name((*f_iter)->get_type(), false, true) + " " + (name_params ? (*f_iter)->get_name() : "/* " + (*f_iter)->get_name() + " */"); } return result; } /** * Converts the parse type to a C++ enum string for the given type. * * @param type Thrift Type * @return String of C++ code to definition of that type constant */ string t_cpp_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "::apache::thrift::protocol::T_STRING"; case t_base_type::TYPE_BOOL: return "::apache::thrift::protocol::T_BOOL"; case t_base_type::TYPE_I8: return "::apache::thrift::protocol::T_BYTE"; case t_base_type::TYPE_I16: return "::apache::thrift::protocol::T_I16"; case t_base_type::TYPE_I32: return "::apache::thrift::protocol::T_I32"; case t_base_type::TYPE_I64: return "::apache::thrift::protocol::T_I64"; case t_base_type::TYPE_DOUBLE: return "::apache::thrift::protocol::T_DOUBLE"; default: break; } } else if (type->is_enum()) { return "::apache::thrift::protocol::T_I32"; } else if (type->is_struct()) { return "::apache::thrift::protocol::T_STRUCT"; } else if (type->is_xception()) { return "::apache::thrift::protocol::T_STRUCT"; } else if (type->is_map()) { return "::apache::thrift::protocol::T_MAP"; } else if (type->is_set()) { return "::apache::thrift::protocol::T_SET"; } else if (type->is_list()) { return "::apache::thrift::protocol::T_LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } bool t_cpp_generator::is_struct_storage_not_throwing(t_struct* tstruct) const { vector members = tstruct->get_members(); for(size_t i=0; i < members.size(); ++i) { t_type* type = get_true_type(members[i]->get_type()); if(type->is_enum()) continue; if(type->is_xception()) return false; if(type->is_base_type()) switch(((t_base_type*)type)->get_base()) { case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: continue; case t_base_type::TYPE_VOID: case t_base_type::TYPE_STRING: default: return false; } if(type->is_struct()) { const vector& more = ((t_struct*)type)->get_members(); for(auto it = more.begin(); it < more.end(); ++it) { if(std::find(members.begin(), members.end(), *it) == members.end()) members.push_back(*it); } continue; } return false; // rest-as-throwing(require-alloc) } return true; } string t_cpp_generator::get_include_prefix(const t_program& program) const { string include_prefix = program.get_include_prefix(); if (!use_include_prefix_ || (include_prefix.size() > 0 && include_prefix[0] == '/')) { // if flag is turned off or this is absolute path, return empty prefix return ""; } string::size_type last_slash = string::npos; if ((last_slash = include_prefix.rfind("/")) != string::npos) { return include_prefix.substr(0, last_slash) + (get_program()->is_out_path_absolute() ? "/" : "/" + out_dir_base_ + "/"); } return ""; } string t_cpp_generator::get_legal_program_name(std::string program_name) { std::size_t found = 0; while(true) { found = program_name.find('.'); if(found != string::npos) { program_name = program_name.replace(found, 1, "_"); } else { break; } } return program_name; } std::string t_cpp_generator::display_name() const { return "C++"; } THRIFT_REGISTER_GENERATOR( cpp, "C++", " cob_style: Generate \"Continuation OBject\"-style classes.\n" " no_client_completion:\n" " Omit calls to completion__() in CobClient class.\n" " no_default_operators:\n" " Omits generation of default operators ==, != and <\n" " templates: Generate templatized reader/writer methods.\n" " pure_enums: Generate pure enums instead of wrapper classes.\n" " include_prefix: Use full include paths in generated files.\n" " moveable_types: Generate move constructors and assignment operators.\n" " no_ostream_operators:\n" " Omit generation of ostream definitions.\n" " no_skeleton: Omits generation of skeleton.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_kotlin_generator.cc0000644000000000000000000022121314370300523025552 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "thrift/generate/t_oop_generator.h" #include "thrift/platform.h" using std::map; using std::ostream; using std::ostringstream; using std::set; using std::setfill; using std::setw; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes static const string KOTLIN_RESERVED_WORDS[] = { "as", "as?", "break", "class", "continue", "do", "else", "false", "for", "fun", "if", "in", "!in", "interface", "is", "!is", "null", "object", "package", "return", "super", "this", "throw", "true", "try", "typealias", "typeof", "val", "var", "when", "while", "by", "catch", "constructor", "delegate", "dynamic", "field", "file", "finally", "get", "import", "init", "param", "property", "receiver", "set", "setparam", "value", "where", }; const set KOTLIN_RESERVED_WORDS_SET(KOTLIN_RESERVED_WORDS, KOTLIN_RESERVED_WORDS + sizeof(KOTLIN_RESERVED_WORDS) / sizeof(KOTLIN_RESERVED_WORDS[0])); /** * Kotlin code generator. */ class t_kotlin_generator : public t_oop_generator { public: t_kotlin_generator(t_program* program, const std::map& /*parsed_options*/, const std::string& /*option_string*/) : t_oop_generator(program) {} /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(std::vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_struct(t_struct* tstruct) override; // void generate_union(t_struct* tunion); void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; private: std::string package_name_; std::string package_dir_; ofstream_with_content_based_conditional_update f_types_; std::string kotlin_package(); std::string warning_surpressions(); std::string constant_name(std::string name); std::string type_to_enum(t_type* type); std::string inner_enum_type_name(t_type* ttype); bool is_enum_set(t_type* ttype); bool is_enum_map(t_type* ttype); std::string type_name(t_type* ttype, bool in_init = false, bool skip_generic = false, bool force_namespace = false); std::string base_type_name(t_base_type* tbase); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string base_type_write_expression(t_base_type* tbase, std::string it = "it"); std::string base_type_read_expression(t_base_type* tbase); bool is_reserved(const string& name); string kotlin_safe_name(const string& name); void generate_kdoc_comment(std::ostream& out, t_doc* tdoc); void generate_kotlin_struct(t_struct* tstruct, bool is_exception); void generate_service_interface(t_service* tservice); void generate_service_client(t_service* tservice); void generate_client_call(std::ostream& out, t_service* tservice, t_function* tfunc); void generate_service_processor(t_service* tservice); void generate_service_process_function(ostream& out, t_service* tservice, t_function* tfunc); void generate_service_args_helpers(t_service* tservice); void generate_service_result_helpers(t_service* tservice); void generate_union_definition(std::ostream& out, t_struct* tunion, std::string additional_interface = ""); void generate_union_standard_scheme(std::ostream& out, t_struct* tunion); void generate_union_tuple_scheme(std::ostream& out, t_struct* tunion); void generate_union_standard_scheme_read(std::ostream& out, t_struct* tunion); void generate_union_standard_scheme_write(std::ostream& out, t_struct* tunion); void generate_union_methods_definitions(std::ostream& out, t_struct* tunion); void generate_union_method_check_type(std::ostream& out, t_struct* tunion); void generate_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, std::string additional_interface = ""); void generate_struct_field_name_constants(std::ostream& out, t_struct* tstruct); void generate_struct_companion_object(std::ostream& out, t_struct* tstruct); void generate_field_value_meta_data(std::ostream& out, t_type* ttype); void generate_metadata_for_field_annotations(std::ostream& out, t_field* tfield); void generate_struct_standard_scheme(std::ostream& out, t_struct* tstruct); void generate_struct_standard_scheme_read(std::ostream& out, t_struct* tstruct); void generate_struct_standard_scheme_write(std::ostream& out, t_struct* tstruct); void generate_struct_method_deep_copy(std::ostream& out, t_struct* tstruct); void generate_struct_method_compare_to(std::ostream& out, t_struct* tstruct); void generate_struct_method_field_for_id(std::ostream& out, t_struct* tstruct); void generate_struct_method_set_field_value(std::ostream& out, t_struct* tstruct); void generate_struct_method_get_field_value(std::ostream& out, t_struct* tstruct); void generate_struct_method_is_set(std::ostream& out, t_struct* tstruct); void generate_struct_method_clear(std::ostream& out, t_struct* tstruct); void generate_struct_method_validate(std::ostream& out, t_struct* tstruct); void generate_struct_method_read(std::ostream& out, t_struct* tstruct); void generate_struct_method_write(std::ostream& out, t_struct* tstruct); void generate_serialize_value(ostream& out, t_type* ttype, std::string it = "it"); void generate_serialize_field(ostream& out, t_field* tfield); void generate_serialize_container(ostream& out, t_type* ttype, std::string it = "it"); void generate_deserialize_value(ostream& out, t_type* ttype); void generate_deserialize_field(ostream& out, t_field* tfield, string prefix); void generate_deserialize_container(ostream& out, t_type* ttype); void generate_kotlin_union(t_struct* tstruct); }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_kotlin_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); package_name_ = program_->get_namespace("java"); string dir = package_name_; string subdir = get_out_dir(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); MKDIR(subdir.c_str()); dir = dir.substr(loc + 1); } if (dir.size() > 0) { subdir = subdir + "/" + dir; MKDIR(subdir.c_str()); } package_dir_ = subdir; string f_types_name = package_dir_ + "/" + program_->get_name() + "Constants.kt"; f_types_.open(f_types_name); f_types_ << autogen_comment() << kotlin_package(); } /** * Nothing in Kotlin generator */ void t_kotlin_generator::close_generator() { f_types_ << endl; f_types_.close(); } /** * Generates a typedef. This is not done in Java, since it does * not support arbitrary name replacements, and it'd be a wacky waste * of overhead to make wrapper classes. * * @param ttypedef The type definition */ void t_kotlin_generator::generate_typedef(t_typedef* ttypedef) { f_types_ << "typealias " << ttypedef->get_symbolic() << " = " << type_name(ttypedef->get_type(), true) << endl; } void t_kotlin_generator::generate_enum(t_enum* tenum) { // Make output file string f_enum_name = package_dir_ + "/" + (tenum->get_name()) + ".kt"; ofstream_with_content_based_conditional_update f_enum; f_enum.open(f_enum_name.c_str()); f_enum << autogen_comment() << kotlin_package(); indent(f_enum) << "enum class " << kotlin_safe_name(tenum->get_name()) << "(private val value: kotlin.Int) : org.apache.thrift.TEnum {"; indent_up(); indent(f_enum); auto first = true; auto enum_values = tenum->get_constants(); for (auto& enum_value : enum_values) { f_enum << (first ? "" : ",") << endl; first = false; indent(f_enum) << enum_value->get_name() << "(" << enum_value->get_value() << ")"; } if (first) { indent(f_enum); } f_enum << ";" << endl << endl; indent(f_enum) << "override fun getValue() = value" << endl << endl; { indent(f_enum) << "companion object {" << endl; indent_up(); { indent(f_enum) << "@kotlin.jvm.JvmStatic" << endl; indent(f_enum) << "fun findByValue(i: kotlin.Int): " << kotlin_safe_name(tenum->get_name()) << "? {" << endl; indent_up(); { indent(f_enum) << "return when (i) {" << endl; indent_up(); { auto enum_values = tenum->get_constants(); for (auto& enum_value : enum_values) { indent(f_enum) << enum_value->get_value() << " -> " << enum_value->get_name() << endl; } indent(f_enum) << "else -> null" << endl; } scope_down(f_enum); } scope_down(f_enum); } scope_down(f_enum); } scope_down(f_enum); f_enum.close(); } void t_kotlin_generator::generate_consts(std::vector consts) { for (auto const_value : consts) { auto const_type = const_value->get_type(); if (const_type->is_base_type()) { f_types_ << "const "; } f_types_ << "val " << kotlin_safe_name(const_value->get_name()) << ": " << type_name(const_type) << " = "; auto value = const_value->get_value(); if (const_type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)const_type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: f_types_ << "\"" << value->get_string() << "\""; break; case t_base_type::TYPE_BOOL: f_types_ << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: f_types_ << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { f_types_ << value->get_integer() << "."; } else { f_types_ << emit_double_as_string(value->get_double()); } break; default: f_types_ << value->get_integer(); break; } } else if (const_type->is_enum()) { auto namespace_prefix = const_type->get_program()->get_namespace("java"); if (namespace_prefix.length() > 0) { namespace_prefix += "."; } f_types_ << namespace_prefix + value->get_identifier_with_parent(); } else { // TODO } f_types_ << endl; } } string t_kotlin_generator::base_type_name(t_base_type* type) { t_base_type::t_base tbase = type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "kotlin.Unit"; case t_base_type::TYPE_STRING: if (type->is_binary()) { return "kotlin.ByteArray"; } else { return "kotlin.String"; } case t_base_type::TYPE_BOOL: return "kotlin.Boolean"; case t_base_type::TYPE_I8: return "kotlin.Byte"; case t_base_type::TYPE_I16: return "kotlin.Short"; case t_base_type::TYPE_I32: return "kotlin.Int"; case t_base_type::TYPE_I64: return "kotlin.Long"; case t_base_type::TYPE_UUID: return "java.util.UUID"; case t_base_type::TYPE_DOUBLE: return "kotlin.Double"; default: throw "compiler error: no Kotlin name for base type " + t_base_type::t_base_name(tbase); } } string t_kotlin_generator::type_name(t_type* ttype, bool in_init, bool skip_generic, bool force_namespace) { ttype = get_true_type(ttype); string prefix; if (ttype->is_base_type()) { return base_type_name((t_base_type*)ttype); } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; if (in_init) { prefix = "kotlin.collections.Map"; } else { prefix = "kotlin.collections.Map"; } return prefix + (skip_generic ? "" : "<" + type_name(tmap->get_key_type(), true) + ", " + type_name(tmap->get_val_type(), true) + ">"); } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; if (in_init) { prefix = "kotlin.collections.Set"; } else { prefix = "kotlin.collections.Set"; } return prefix + (skip_generic ? "" : "<" + type_name(tset->get_elem_type(), true) + ">"); } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; if (in_init) { prefix = "kotlin.collections.List"; } else { prefix = "kotlin.collections.List"; } return prefix + (skip_generic ? "" : "<" + type_name(tlist->get_elem_type(), true) + ">"); } // Check for namespacing t_program* program = ttype->get_program(); if ((program != nullptr) && ((program != program_) || force_namespace)) { string package = program->get_namespace("java"); if (!package.empty()) { return package + "." + kotlin_safe_name(ttype->get_name()); } } return kotlin_safe_name(ttype->get_name()); } /** * Generates a struct definition for a thrift data type. This will be a org.apache.thrift.TBase * implementor. * * @param tstruct The struct definition */ void t_kotlin_generator::generate_struct(t_struct* tstruct) { if (tstruct->is_union()) { generate_kotlin_union(tstruct); } else { generate_kotlin_struct(tstruct, false); } } void t_kotlin_generator::generate_kotlin_union(t_struct* tunion) { string f_union_name = package_dir_ + "/" + (tunion->get_name()) + ".kt"; ofstream_with_content_based_conditional_update f_union; f_union.open(f_union_name.c_str()); f_union << autogen_comment() << warning_surpressions() << kotlin_package(); generate_union_definition(f_union, tunion); f_union.close(); } void t_kotlin_generator::generate_kotlin_struct(t_struct* tstruct, bool is_exception) { string f_struct_name = package_dir_ + "/" + (tstruct->get_name()) + ".kt"; ofstream_with_content_based_conditional_update f_struct; f_struct.open(f_struct_name.c_str()); f_struct << autogen_comment() << warning_surpressions() << kotlin_package(); generate_struct_definition(f_struct, tstruct, is_exception); f_struct.close(); } void t_kotlin_generator::generate_struct_field_name_constants(std::ostream& out, t_struct* tstruct) { indent(out) << "enum class _Fields(private val thriftFieldId: kotlin.Short, private val " "fieldName: kotlin.String) : org.apache.thrift.TFieldIdEnum {" << endl; indent_up(); { // fields { bool first = true; for (auto& field : tstruct->get_members()) { if (!first) { out << "," << endl; } first = false; indent(out) << constant_name(field->get_name()) << "(" << field->get_key() << ", \"" << field->get_name() << "\")"; } if (first) { indent(out); } out << ";" << endl << endl; } // methods indent(out) << "override fun getThriftFieldId() = thriftFieldId" << endl << endl; indent(out) << "override fun getFieldName() = fieldName" << endl << endl; // companion object indent(out) << "companion object {" << endl; indent_up(); { indent(out) << "@kotlin.jvm.JvmStatic" << endl; indent(out) << "fun findByValue(value: kotlin.Int): _Fields? {" << endl; indent_up(); { indent(out) << "return when (value) {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { indent(out) << field->get_key() << " -> " << constant_name(field->get_name()) << endl; } indent(out) << "else -> null" << endl; } scope_down(out); } scope_down(out); } out << endl; { indent(out) << "@kotlin.jvm.JvmStatic" << endl; indent(out) << "fun findByName(name: kotlin.String): _Fields? {" << endl; indent_up(); { indent(out) << "return when (name) {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { indent(out) << "\"" << field->get_name() << "\"" << " -> " << constant_name(field->get_name()) << endl; } indent(out) << "else -> null" << endl; } scope_down(out); } scope_down(out); } scope_down(out); } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_companion_object(std::ostream& out, t_struct* tstruct) { indent(out) << "companion object {" << endl; indent_up(); { indent(out) << "private val STRUCT_DESC: org.apache.thrift.protocol.TStruct = " "org.apache.thrift.protocol.TStruct(\"" << tstruct->get_name() << "\")" << endl; { for (auto& field : tstruct->get_members()) { // field desc indent(out) << "private val " << constant_name(field->get_name()) << "_FIELD_DESC: org.apache.thrift.protocol.TField = " "org.apache.thrift.protocol.TField(\"" << field->get_name() << "\", " << type_to_enum(field->get_type()) << ", " << field->get_key() << ")" << endl; // field metadata indent(out) << "private val " << constant_name(field->get_name()) << "_FIELD_META_DATA: org.apache.thrift.meta_data.FieldMetaData = " "org.apache.thrift.meta_data.FieldMetaData(" << endl; indent_up(); { indent(out) << '"' << field->get_name() << '"' << ',' << endl; indent(out) << "org.apache.thrift.TFieldRequirementType."; if (field->get_req() == t_field::T_REQUIRED) { out << "REQUIRED"; } else if (field->get_req() == t_field::T_OPTIONAL) { out << "OPTIONAL"; } else { out << "DEFAULT"; } out << ',' << endl; generate_field_value_meta_data(indent(out), field->get_type()); out << ',' << endl; generate_metadata_for_field_annotations(indent(out), field); } out << ")" << endl; indent_down(); } } // all fields in a map indent(out) << "private val metadata: Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> = mapOf(" << endl; indent_up(); for (auto& field : tstruct->get_members()) { indent(out) << "_Fields." << constant_name(field->get_name()) << " to " << constant_name(field->get_name()) << "_FIELD_META_DATA," << endl; } indent_down(); indent(out) << ")" << endl; indent(out) << "init {" << endl; indent_up(); indent(out) << "org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(" << tstruct->get_name() << "::class.java, metadata)" << endl; scope_down(out); } scope_down(out); out << endl; } void t_kotlin_generator::generate_metadata_for_field_annotations(std::ostream& out, t_field* field) { if (field->annotations_.size() == 0) { out << "emptyMap()"; } else { out << "mapOf(" << endl; indent_up(); for (auto& annotation : field->annotations_) { indent(out) << "\"" + annotation.first + "\" to \"" + annotation.second.back() + "\"," << endl; } indent_down(); indent(out) << ")"; } } void t_kotlin_generator::generate_field_value_meta_data(std::ostream& out, t_type* type) { static const string ttype_class = "org.apache.thrift.protocol.TType."; static const string meta_package = "org.apache.thrift.meta_data."; out << meta_package; if (type->is_struct() || type->is_xception()) { out << "StructMetaData(" << ttype_class << "STRUCT, " << type_name(type) << "::class.java"; } else if (type->is_container()) { if (type->is_list()) { out << "ListMetaData(" << ttype_class << "LIST," << endl; indent_up(); t_type* elem_type = ((t_list*)type)->get_elem_type(); generate_field_value_meta_data(indent(out), elem_type); indent_down(); } else if (type->is_set()) { out << "SetMetaData(" << ttype_class << "SET," << endl; indent_up(); t_type* elem_type = ((t_set*)type)->get_elem_type(); generate_field_value_meta_data(indent(out), elem_type); indent_down(); } else { out << "MapMetaData(" << ttype_class << "MAP," << endl; indent_up(); t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); generate_field_value_meta_data(indent(out), key_type); out << "," << endl; generate_field_value_meta_data(indent(out), val_type); indent_down(); } } else if (type->is_enum()) { out << "EnumMetaData(" << ttype_class << "ENUM, " << type_name(type) << "::class.java"; } else { out << "FieldValueMetaData(" << type_to_enum(type); if (type->is_typedef()) { out << ", \"" << ((t_typedef*)type)->get_symbolic() << "\""; } else if (type->is_binary()) { out << ", true"; } } out << ")"; } void t_kotlin_generator::generate_struct_method_deep_copy(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun deepCopy(): " << tstruct->get_name() << " {" << endl; indent_up(); { indent(out) << "return " << tstruct->get_name() << " (" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { indent(out) << kotlin_safe_name(field->get_name()) << "," << endl; } } indent_down(); indent(out) << ")" << endl; } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_compare_to(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun compareTo(other: " << tstruct->get_name() << "?): kotlin.Int {" << endl; indent_up(); { indent(out) << "val comparator = compareBy<" << tstruct->get_name() << "> { it::class.java.name }" << endl; indent_up(); for (auto& field : tstruct->get_members()) { indent(out) << ".thenBy"; auto field_type = field->get_type(); if (field_type->is_list() || field_type->is_set() || field_type->is_map() || field_type->is_binary()) { out << "(org.apache.thrift.TBaseHelper::compareTo)"; } out << " { it." << kotlin_safe_name(field->get_name()) << " } " << endl; } indent_down(); indent(out) << "return nullsFirst(comparator).compare(this, other)" << endl; } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_field_for_id(std::ostream& out, t_struct* /*tstruct*/) { indent(out) << "override fun fieldForId(fieldId: kotlin.Int): _Fields {" << endl; indent_up(); { indent(out) << "return _Fields.findByValue(fieldId) ?: throw " "kotlin.IllegalArgumentException(\"invalid fieldId $fieldId\")" << endl; } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_is_set(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun isSet(field: _Fields): kotlin.Boolean {" << endl; indent_up(); { indent(out) << "return when (field) {" << endl; indent_up(); { auto members = tstruct->get_members(); if (members.size() > 0) { for (auto& field : members) { indent(out) << "_Fields." << constant_name(field->get_name()) << " -> "; if (field->get_req() == t_field::T_REQUIRED) { out << "this._" << field->get_name() << " != null"; } else { out << "this." << kotlin_safe_name(field->get_name()) << " != null"; } out << endl; } } else { indent(out) << "else -> false" << endl; } } scope_down(out); } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_clear(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun clear(): kotlin.Unit {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { auto is_required = field->get_req() == t_field::T_REQUIRED; indent(out) << (is_required ? "_" + field->get_name() : kotlin_safe_name(field->get_name())) << " = null" << endl; } } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_validate(std::ostream& out, t_struct* tstruct) { indent(out) << "@kotlin.jvm.Throws(org.apache.thrift.TException::class)" << endl; indent(out) << "fun validate(): kotlin.Unit {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { bool is_required = field->get_req() == t_field::T_REQUIRED; if (is_required) { indent(out) << "if (_" << field->get_name() << " == null) {" << endl; indent_up(); { indent(out) << "throw org.apache.thrift.TException(\"Required field `" << field->get_name() << "' is null, " "struct is: $this\")" << endl; } scope_down(out); } } } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_set_field_value(std::ostream& out, t_struct* tstruct) { indent(out) << "@Suppress(\"UNCHECKED_CAST\")" << endl; indent(out) << "override fun setFieldValue(field: _Fields, value: kotlin.Any?): kotlin.Unit {" << endl; indent_up(); { const vector& members = tstruct->get_members(); if (members.size() > 0) { indent(out) << "when (field) {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { auto is_required = field->get_req() == t_field::T_REQUIRED; indent(out) << "_Fields." << constant_name(field->get_name()) << " -> this." << (is_required ? "_" + field->get_name() : kotlin_safe_name(field->get_name())) << " = value as " << type_name(field->get_type()) << "?" << endl; } } scope_down(out); } else { indent(out) << "return" << endl; } } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_get_field_value(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun getFieldValue(field: _Fields): kotlin.Any? {" << endl; indent_up(); { auto members = tstruct->get_members(); if (members.size() > 0) { indent(out) << "return when (field) {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { indent(out) << "_Fields." << constant_name(field->get_name()) << " -> this." << kotlin_safe_name(field->get_name()) << endl; } } scope_down(out); } else { indent(out) << "return null" << endl; } } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_read(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun read(iproto: org.apache.thrift.protocol.TProtocol): kotlin.Unit {" << endl; indent_up(); { indent(out) << "require(org.apache.thrift.scheme.StandardScheme::class.java == iproto.scheme) { " "\"only standard scheme is " "supported for now\" }" << endl; indent(out) << tstruct->get_name() << "StandardScheme.read(iproto, this)" << endl; } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_method_write(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun write(oproto: org.apache.thrift.protocol.TProtocol): kotlin.Unit {" << endl; indent_up(); { indent(out) << "require(org.apache.thrift.scheme.StandardScheme::class.java == oproto.scheme) { " "\"only standard scheme is " "supported for now\" }" << endl; indent(out) << tstruct->get_name() << "StandardScheme.write(oproto, this)" << endl; } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_standard_scheme_read(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun read(iproto: org.apache.thrift.protocol.TProtocol, struct: " << tstruct->get_name() << ") {" << endl; indent_up(); { indent(out) << "iproto.apply {" << endl; indent_up(); { indent(out) << "readStruct {" << endl; indent_up(); { indent(out) << "var stopped = false" << endl; indent(out) << "while (!stopped) {" << endl; indent_up(); { indent(out) << "stopped = readField {" << endl; indent_up(); { indent(out) << "val skipNext = { " "org.apache.thrift.protocol.TProtocolUtil.skip(iproto, it.type) }" << endl; indent(out) << "when (it.id.toInt()) {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { indent(out) << field->get_key() << " -> {" << endl; indent_up(); { indent(out) << "if (it.type == " << type_to_enum(field->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, field, "struct."); indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "skipNext()" << endl; indent_down(); indent(out) << "}" << endl; } scope_down(out); } indent(out) << "else -> skipNext()" << endl; } scope_down(out); } scope_down(out); } scope_down(out); indent(out) << "struct.validate()" << endl; } scope_down(out); } scope_down(out); } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_standard_scheme_write(std::ostream& out, t_struct* tstruct) { indent(out) << "override fun write(oproto: org.apache.thrift.protocol.TProtocol, struct: " << tstruct->get_name() << ") {" << endl; indent_up(); { indent(out) << "struct.validate()" << endl; indent(out) << "oproto.apply {" << endl; indent_up(); { indent(out) << "writeStruct(STRUCT_DESC) {" << endl; indent_up(); { for (auto& field : tstruct->get_members()) { auto is_required = field->get_req() == t_field::T_REQUIRED; indent(out) << "struct." << kotlin_safe_name(field->get_name()) << (is_required ? "" : "?") << ".let { " << kotlin_safe_name(field->get_name()) << " ->" << endl; indent_up(); { indent(out) << "writeField(" << constant_name(field->get_name()) << "_FIELD_DESC) {" << endl; indent_up(); generate_serialize_field(out, field); scope_down(out); } scope_down(out); } } indent(out) << "writeFieldStop()" << endl; scope_down(out); } scope_down(out); } scope_down(out); out << endl; } void t_kotlin_generator::generate_struct_standard_scheme(std::ostream& out, t_struct* tstruct) { indent(out) << "private object " << tstruct->get_name() << "StandardScheme : org.apache.thrift.scheme.StandardScheme<" << tstruct->get_name() << ">() {" << endl; indent_up(); generate_struct_standard_scheme_read(out, tstruct); generate_struct_standard_scheme_write(out, tstruct); scope_down(out); out << endl; } void t_kotlin_generator::generate_union_tuple_scheme(std::ostream& out, t_struct* /*tunion*/) { indent(out) << "override fun tupleSchemeReadValue(iproto: org.apache.thrift.protocol.TProtocol, " "fieldID: kotlin.Short) = throw kotlin.UnsupportedOperationException(\"only " "standard scheme is supported for now\")" << endl; indent(out) << "override fun tupleSchemeWriteValue(oproto: org.apache.thrift.protocol.TProtocol) = " "throw kotlin.UnsupportedOperationException(\"only standard scheme is supported for " "now\")" << endl; } void t_kotlin_generator::generate_union_standard_scheme(std::ostream& out, t_struct* tunion) { generate_union_standard_scheme_read(out, tunion); generate_union_standard_scheme_write(out, tunion); } void t_kotlin_generator::generate_union_standard_scheme_read(std::ostream& out, t_struct* tunion) { indent(out) << "override fun standardSchemeReadValue(iproto: org.apache.thrift.protocol.TProtocol, " "field: org.apache.thrift.protocol.TField): Any? =" << endl; indent_up(); indent(out) << "when (_Fields.findByValue(field.id.toInt())) {" << endl; indent_up(); for (auto& member : tunion->get_members()) { auto expect_type = type_name(member->get_type()); indent(out) << "_Fields." << constant_name(member->get_name()) << " -> {" << endl; indent_up(); { indent(out) << "if (field.type == " << constant_name(member->get_name()) << "_FIELD_DESC.type) {" << endl; indent_up(); indent(out) << "iproto.run {" << endl; indent_up(); indent(out); generate_deserialize_value(out, member->get_type()); out << endl; scope_down(out); indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "org.apache.thrift.protocol.TProtocolUtil.skip(iproto, field.type)" << endl; indent(out) << "null" << endl; scope_down(out); } scope_down(out); } indent(out) << "null -> {" << endl; indent_up(); indent(out) << "org.apache.thrift.protocol.TProtocolUtil.skip(iproto, field.type)" << endl; indent(out) << "null" << endl; scope_down(out); scope_down(out); indent_down(); } void t_kotlin_generator::generate_union_standard_scheme_write(std::ostream& out, t_struct* tunion) { indent(out) << "@Suppress(\"UNCHECKED_CAST\")" << endl; indent(out) << "override fun standardSchemeWriteValue(oproto: org.apache.thrift.protocol.TProtocol) {" << endl; indent_up(); indent(out) << "when (setField_) {" << endl; indent_up(); for (auto& member : tunion->get_members()) { indent(out) << "_Fields." << constant_name(member->get_name()) << " -> {" << endl; indent_up(); { indent(out) << "val it = value_ as " << type_name(member->get_type()) << endl; indent(out) << "oproto.apply {" << endl; indent_up(); { indent(out); generate_serialize_value(out, member->get_type()); out << endl; } scope_down(out); } scope_down(out); } indent(out) << "null -> throw kotlin.IllegalStateException(\"Cannot write union with unknown " "field $setField_\")" << endl; scope_down(out); scope_down(out); } void t_kotlin_generator::generate_union_methods_definitions(std::ostream& out, t_struct* tunion) { { // this is a hack to reuse code t_struct union_fields(program_, tunion->get_name()); t_enum enum_type(program_); enum_type.set_name("setField_"); t_field set_field(&enum_type, "setField_", 0); t_base_type value_type("value_", t_base_type::TYPE_STRING); value_type.set_binary(true); t_field value(&value_type, "value_", 1); union_fields.append(&set_field); union_fields.append(&value); generate_struct_method_compare_to(out, &union_fields); } auto union_class_name = kotlin_safe_name(tunion->get_name()); { indent(out) << "override fun deepCopy() = " << union_class_name << "(this)" << endl; } { indent(out) << "override fun enumForId(id: kotlin.Short) = fieldForId(id.toInt())" << endl; } { indent(out) << "override fun getStructDesc() = STRUCT_DESC" << endl; } { indent(out) << "override fun getFieldDesc(setField: _Fields) = when (setField) {" << endl; indent_up(); for (auto& member : tunion->get_members()) { indent(out) << "_Fields." << constant_name(member->get_name()) << " -> " << constant_name(member->get_name()) << "_FIELD_DESC" << endl; } scope_down(out); } } void t_kotlin_generator::generate_union_method_check_type(std::ostream& out, t_struct* tunion) { indent(out) << "@Suppress(\"UNCHECKED_CAST\")" << endl; indent(out) << "override fun checkType(setField: _Fields, value: kotlin.Any?) {" << endl; indent_up(); indent(out) << "when (setField) {" << endl; indent_up(); for (auto& member : tunion->get_members()) { auto expect_type = type_name(member->get_type()); indent(out) << "_Fields." << constant_name(member->get_name()) << " -> value as? " << expect_type << " ?: throw kotlin.ClassCastException(\"Was expecting value of type `" << expect_type << "' for field `" << member->get_name() << "', but got ${value?.javaClass}\")" << endl; } scope_down(out); scope_down(out); } void t_kotlin_generator::generate_union_definition(std::ostream& out, t_struct* tunion, string /*additional interface*/) { auto union_class_name = kotlin_safe_name(tunion->get_name()); indent(out) << "class " << union_class_name << " : org.apache.thrift.TUnion<" << union_class_name << ", " << union_class_name << "._Fields> {" << endl; indent_up(); indent(out) << "constructor(setField: _Fields, value: kotlin.Any) : super(setField, value)" << endl; indent(out) << "constructor(other: " << union_class_name << ") : super(other)" << endl; indent(out) << "constructor() : super()" << endl; generate_struct_field_name_constants(out, tunion); generate_struct_companion_object(out, tunion); generate_struct_method_field_for_id(out, tunion); generate_union_methods_definitions(out, tunion); generate_union_method_check_type(out, tunion); generate_union_standard_scheme(out, tunion); generate_union_tuple_scheme(out, tunion); indent_down(); indent(out) << "}" << endl; } void t_kotlin_generator::generate_struct_definition(std::ostream& out, t_struct* tstruct, bool is_exception, string additional_interface) { generate_kdoc_comment(out, tstruct); auto members = tstruct->get_members(); if (members.size() > 0) { indent(out) << "data class "; } else { indent(out) << "class "; } out << kotlin_safe_name(tstruct->get_name()) << "("; indent_up(); auto sep = ""; for (auto field : members) { out << sep << endl; sep = ","; generate_kdoc_comment(out, field); auto is_required = field->get_req() == t_field::T_REQUIRED; if (is_required) { indent(out) << "private var _" << field->get_name(); } else if (is_exception && field->get_name() == "message") { // special handling for exception when field name is message - needs override if (!field->get_type()->is_string()) { throw "type error: for `message' field in an exception struct, it must be a string"; } indent(out) << "override var message"; } else { indent(out) << "var " << kotlin_safe_name(field->get_name()); } out << ": " << type_name(field->get_type()) << "? = null"; } indent_down(); out << endl; indent(out) << ") : "; if (is_exception) { out << "org.apache.thrift.TException(), "; } if (additional_interface != "") { additional_interface = ", " + additional_interface; } out << "org.apache.thrift.TBase<" << tstruct->get_name() << ", " << tstruct->get_name() << "._Fields>" << additional_interface << " {" << endl; indent_up(); for (auto field : members) { if (field->get_req() == t_field::T_REQUIRED) { indent(out); // special handling for exception when field name is message - needs override if (is_exception && field->get_name() == "message") { out << "override "; } out << "val " << kotlin_safe_name(field->get_name()) << ": " << type_name(field->get_type()) << " get() = _" + kotlin_safe_name(field->get_name()) << "!!" << endl; } } generate_struct_field_name_constants(out, tstruct); generate_struct_companion_object(out, tstruct); generate_struct_standard_scheme(out, tstruct); generate_struct_method_compare_to(out, tstruct); generate_struct_method_field_for_id(out, tstruct); generate_struct_method_get_field_value(out, tstruct); generate_struct_method_set_field_value(out, tstruct); generate_struct_method_is_set(out, tstruct); generate_struct_method_deep_copy(out, tstruct); generate_struct_method_clear(out, tstruct); generate_struct_method_validate(out, tstruct); generate_struct_method_read(out, tstruct); generate_struct_method_write(out, tstruct); indent_down(); indent(out) << "}" << endl; } string t_kotlin_generator::base_type_write_expression(t_base_type* tbase, string it) { switch (tbase->get_base()) { case t_base_type::TYPE_VOID: throw "compiler error: no void in base types"; case t_base_type::TYPE_STRING: if (tbase->is_binary()) { return "writeBinary(java.nio.ByteBuffer.wrap(" + it + "))"; } else { return "writeString(" + it + ")"; } case t_base_type::TYPE_BOOL: return "writeBool(" + it + ")"; case t_base_type::TYPE_I8: return "writeByte(" + it + ")"; case t_base_type::TYPE_I16: return "writeI16(" + it + ")"; case t_base_type::TYPE_I32: return "writeI32(" + it + ")"; case t_base_type::TYPE_I64: return "writeI64(" + it + ")"; case t_base_type::TYPE_UUID: return "writeUuid(" + it + ")"; case t_base_type::TYPE_DOUBLE: return "writeDouble(" + it + ")"; default: throw "compiler error: no Kotlin name for base type " + t_base_type::t_base_name(tbase->get_base()); } } string t_kotlin_generator::base_type_read_expression(t_base_type* tbase) { switch (tbase->get_base()) { case t_base_type::TYPE_VOID: throw "compiler error: no void in base types"; case t_base_type::TYPE_STRING: if (tbase->is_binary()) { return "org.apache.thrift.TBaseHelper.byteBufferToByteArray(readBinary())"; } else { return "readString()"; } case t_base_type::TYPE_BOOL: return "readBool()"; case t_base_type::TYPE_I8: return "readByte()"; case t_base_type::TYPE_I16: return "readI16()"; case t_base_type::TYPE_I32: return "readI32()"; case t_base_type::TYPE_I64: return "readI64()"; case t_base_type::TYPE_UUID: return "readUuid()"; case t_base_type::TYPE_DOUBLE: return "readDouble()"; default: throw "compiler error: no Kotlin name for base type " + t_base_type::t_base_name(tbase->get_base()); } } void t_kotlin_generator::generate_serialize_value(ostream& out, t_type* type, string it) { t_type* ttype = get_true_type(type); if (ttype->is_struct() || ttype->is_xception()) { out << it << ".write(this)"; } else if (ttype->is_container()) { generate_serialize_container(out, ttype, it); } else if (ttype->is_base_type()) { out << base_type_write_expression((t_base_type*)ttype, it); } else if (ttype->is_enum()) { out << "writeI32(" << it << ".value)"; } else { printf("cannot deserialize type '%s'\n", type_name(ttype).c_str()); } } void t_kotlin_generator::generate_deserialize_value(ostream& out, t_type* type) { t_type* ttype = get_true_type(type); if (ttype->is_struct() || ttype->is_xception()) { out << type_name(ttype) << "().apply { read(iproto) }"; } else if (ttype->is_container()) { generate_deserialize_container(out, ttype); } else if (ttype->is_base_type()) { out << base_type_read_expression((t_base_type*)ttype); } else if (ttype->is_enum()) { out << "requireNotNull(" << type_name(ttype, false, false, true) + ".findByValue(readI32()))"; } else { printf("cannot deserialize type '%s'\n", type_name(ttype).c_str()); } } /** * Serializes a field of any type. * * @param tfield The field */ void t_kotlin_generator::generate_serialize_field(ostream& out, t_field* tfield) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + tfield->get_name(); } indent(out); generate_serialize_value(out, type, kotlin_safe_name(tfield->get_name())); out << endl; } /** * Deserializes a field of any type. * * @param tfield The field * @param prefix The variable name or container for this field */ void t_kotlin_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } auto is_required = tfield->get_req() == t_field::T_REQUIRED; string name = prefix + (is_required ? "_" + tfield->get_name() : kotlin_safe_name(tfield->get_name())); indent(out) << name << " = "; generate_deserialize_value(out, type); out << endl; } /** * Serializes a container by writing its size and then iterating */ void t_kotlin_generator::generate_serialize_container(ostream& out, t_type* ttype, string it) { if (ttype->is_map()) { out << "writeMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << it << ") { (key, value) ->" << endl; indent_up(); { generate_serialize_value(indent(out), ((t_map*)ttype)->get_key_type(), "key"); out << endl; generate_serialize_value(indent(out), ((t_map*)ttype)->get_val_type(), "value"); out << endl; indent_down(); } indent(out) << "}"; } else if (ttype->is_set()) { out << "writeSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << it << ") {" << endl; indent_up(); { generate_serialize_value(indent(out), ((t_set*)ttype)->get_elem_type()); out << endl; indent_down(); } indent(out) << "}"; } else if (ttype->is_list()) { out << "writeList(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << it << ") {" << endl; { indent_up(); generate_serialize_value(indent(out), ((t_list*)ttype)->get_elem_type()); out << endl; indent_down(); } indent(out) << "}"; } else { throw "not a container type: " + ttype->get_name(); } } /** * Deserializes a container by reading its size and then iterating */ void t_kotlin_generator::generate_deserialize_container(ostream& out, t_type* ttype) { if (ttype->is_map()) { out << "readMap { tmap ->" << endl; indent_up(); indent(out) << "kotlin.collections.List(tmap.size) {" << endl; indent_up(); indent(out); generate_deserialize_value(out, ((t_map*)ttype)->get_key_type()); out << " to "; generate_deserialize_value(out, ((t_map*)ttype)->get_val_type()); out << endl; indent_down(); indent(out) << "}.associate { it }" << endl; indent_down(); indent(out) << "}"; } else if (ttype->is_set()) { out << "readSet { tset ->" << endl; indent_up(); indent(out) << "kotlin.collections.List(tset.size) {" << endl; indent_up(); indent(out); generate_deserialize_value(out, ((t_set*)ttype)->get_elem_type()); out << endl; indent_down(); indent(out) << "}.toSet()" << endl; indent_down(); indent(out) << "}"; } else if (ttype->is_list()) { out << "readList { tlist ->" << endl; indent_up(); indent(out) << "kotlin.collections.List(tlist.size) {" << endl; indent_up(); indent(out); generate_deserialize_value(out, ((t_list*)ttype)->get_elem_type()); out << endl; indent_down(); indent(out) << "}" << endl; indent_down(); indent(out) << "}"; } else { throw "not a container type: " + ttype->get_name(); } } string t_kotlin_generator::function_signature(t_function* tfunction, string prefix) { auto result = "suspend fun " + prefix + tfunction->get_name() + "("; auto arguments = tfunction->get_arglist(); bool first = true; for (t_field* tfield : arguments->get_members()) { if (first) { first = false; } else { result += ", "; } result += tfield->get_name() + ": " + type_name(tfield->get_type()); } result += "): "; result += type_name(tfunction->get_returntype()); return result; } void t_kotlin_generator::generate_service_interface(t_service* tservice) { string f_service_name = package_dir_ + "/" + tservice->get_name() + ".kt"; ofstream_with_content_based_conditional_update out; out.open(f_service_name.c_str()); out << autogen_comment() << kotlin_package(); out << "interface " << tservice->get_name() << " {" << endl; indent_up(); for (auto tfunc : tservice->get_functions()) { generate_kdoc_comment(out, tfunc); indent(out) << function_signature(tfunc) << endl; } scope_down(out); out << endl << endl; out.close(); } void t_kotlin_generator::generate_service_client(t_service* tservice) { string f_service_name = package_dir_ + "/" + tservice->get_name() + "Client.kt"; ofstream_with_content_based_conditional_update out; out.open(f_service_name.c_str()); out << autogen_comment() << warning_surpressions() << kotlin_package(); generate_docstring_comment(out, "/**\n", " * ", "client implementation for [" + tservice->get_name() + "]", " */\n"); indent(out) << "class " << tservice->get_name() << "Client(" << endl; indent_up(); indent(out) << "protocolFactory: org.apache.thrift.protocol.TProtocolFactory," << endl; indent(out) << "clientManager: org.apache.thrift.async.TAsyncClientManager," << endl; indent(out) << "transport: org.apache.thrift.transport.TNonblockingTransport" << endl; indent_down(); out << "): org.apache.thrift.async.TAsyncClient(protocolFactory, clientManager, transport), " << tservice->get_name() << " {" << endl << endl; indent_up(); { indent(out) << "private val seqId = java.util.concurrent.atomic.AtomicInteger()" << endl << endl; for (auto tfunc : tservice->get_functions()) { indent(out) << "override " << function_signature(tfunc) << " {" << endl; indent_up(); { string args_name = tservice->get_name() + "FunctionArgs." + tfunc->get_name() + "_args"; indent(out) << "val args = " << args_name << "("; auto first = true; for (auto tfield : tfunc->get_arglist()->get_members()) { if (!first) { out << ", "; } first = false; out << tfield->get_name(); } out << ")" << endl; indent(out) << "return transformCallback {" << endl; indent_up(); { indent(out) << "checkReady()" << endl; indent(out) << "___currentMethod = ProcessCall." << tfunc->get_name() << "Call(args, seqId.getAndIncrement(), this, ___protocolFactory, ___transport, it)" << endl; indent(out) << "___manager.call(___currentMethod)" << endl; } scope_down(out); } scope_down(out); } indent(out) << "private suspend fun " "org.apache.thrift.async.TAsyncClient.transformCallback(action: " "(org.apache.thrift.async.AsyncMethodCallback) -> Unit): R {" << endl; indent_up(); indent(out) << "val deferred = kotlinx.coroutines.CompletableDeferred()" << endl; indent(out) << "val callback = object : org.apache.thrift.async.AsyncMethodCallback {" << endl; indent_up(); indent(out) << "override fun onComplete(response: R) { deferred.complete(response) }" << endl; indent(out) << "override fun onError(exception: java.lang.Exception) { " "deferred.completeExceptionally(exception) }" << endl; scope_down(out); indent(out) << "action(callback)" << endl; indent(out) << "return deferred.await()" << endl; scope_down(out); indent(out) << "sealed interface ProcessCall {" << endl; indent_up(); for (auto tfunc : tservice->get_functions()) { generate_client_call(out, tservice, tfunc); } scope_down(out); } scope_down(out); out << endl << endl; out.close(); } void t_kotlin_generator::generate_client_call(std::ostream& out, t_service* tservice, t_function* tfunc) { string funname = tfunc->get_name(); string funclassname = funname + "Call"; string rtype = type_name(tfunc->get_returntype(), true); indent(out) << "class " + funclassname + "(" << endl; indent_up(); string args_name = tservice->get_name() + "FunctionArgs." + tfunc->get_name() + "_args"; indent(out) << "val args: " << args_name << "," << endl; indent(out) << "val seqId: kotlin.Int," << endl; indent(out) << "client: org.apache.thrift.async.TAsyncClient," << endl; indent(out) << "protocolFactory: org.apache.thrift.protocol.TProtocolFactory," << endl; indent(out) << "transport: org.apache.thrift.transport.TNonblockingTransport," << endl; indent(out) << "resultHandler: org.apache.thrift.async.AsyncMethodCallback<" << rtype << ">," << endl; indent_down(); indent(out) << ") : org.apache.thrift.async.TAsyncMethodCall<" << rtype << ">(client, protocolFactory, transport, resultHandler, " << (tfunc->is_oneway() ? "true" : "false") << "), ProcessCall {" << endl; indent_up(); indent(out) << "override fun write_args(protocol: org.apache.thrift.protocol.TProtocol) {" << endl; indent_up(); indent(out) << "val marker = org.apache.thrift.protocol.TMessage(\"" << tfunc->get_name() << "\", org.apache.thrift.protocol.TMessageType.CALL, seqId)" << endl; indent(out) << "protocol.writeMessage(marker) { args.write(protocol) }" << endl; scope_down(out); indent(out) << "override fun getResult(): " << rtype << " {" << endl; indent_up(); indent(out) << "check(state == org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) { " "\"Method call not finished!\" }" << endl; indent(out) << "val memoryTransport = " "org.apache.thrift.transport.TMemoryInputTransport(frameBuffer.array())" << endl; indent(out) << "val protocol = client.protocolFactory.getProtocol(memoryTransport)" << endl; if (tfunc->is_oneway()) { indent(out) << "// one way function, nothing to read" << endl; } else { indent(out) << "return protocol.readMessage {" << endl; indent_up(); { indent(out) << "if (it.type == org.apache.thrift.protocol.TMessageType.EXCEPTION) {" << endl; indent_up(); indent(out) << "val ex = org.apache.thrift.TApplicationException().apply { read(protocol) }" << endl; indent(out) << "throw ex" << endl; scope_down(out); indent(out) << "if (it.seqid != seqId) {" << endl; indent_up(); indent(out) << "throw org.apache.thrift.TApplicationException(" << endl; indent_up(); indent(out) << "org.apache.thrift.TApplicationException.BAD_SEQUENCE_ID," << endl; indent(out) << "\"" << funname << " failed: out of sequence response: expected $seqId but got ${it.seqid}\"" << endl; indent_down(); indent(out) << ")" << endl; scope_down(out); string result_name = tservice->get_name() + "FunctionResult." + tfunc->get_name() + "_result"; indent(out) << "val result = " << result_name << "().apply { read(protocol) }" << endl; for (auto xception : tfunc->get_xceptions()->get_members()) { indent(out) << "result." << xception->get_name() << "?.let { throw it }" << endl; } if (!tfunc->get_returntype()->is_void()) { indent(out) << "result.success ?: throw " "org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException." "MISSING_RESULT, \"returnString failed: unknown result\")" << endl; } } scope_down(out); } scope_down(out); scope_down(out); } void t_kotlin_generator::generate_service_processor(t_service* tservice) { string f_service_name = package_dir_ + "/" + tservice->get_name() + "Processor.kt"; ofstream_with_content_based_conditional_update out; out.open(f_service_name.c_str()); out << autogen_comment() << warning_surpressions() << kotlin_package(); auto service_imports = {"import kotlinx.coroutines.future.future"}; for (auto service_import : service_imports) { out << service_import << endl; } out << endl; generate_docstring_comment(out, "/**\n", " * ", "server implementation for [" + tservice->get_name() + "]", " */\n"); indent(out) << "class " << tservice->get_name() << "Processor(" << endl; indent_up(); indent(out) << "handler: " << tservice->get_name() << "," << endl; indent(out) << "private val scope: kotlinx.coroutines.CoroutineScope," << endl; indent(out) << "private val processMap: kotlin.collections.Mapget_name() << ", out org.apache.thrift.TBase<*, " "*>, out kotlin.Any>> = mapOf(" << endl; indent_up(); { for (auto tfunc : tservice->get_functions()) { indent(out) << '"' << tfunc->get_name() << '"' << " to ProcessFunction." << tfunc->get_name() << "(scope)," << endl; } } indent_down(); indent(out) << ")" << endl; indent_down(); out << "): org.apache.thrift.TBaseAsyncProcessor<" << tservice->get_name() << ">(handler, processMap) {" << endl; indent_up(); indent(out) << "companion object {" << endl; indent_up(); indent(out) << "internal val logger: org.slf4j.Logger = " "org.slf4j.LoggerFactory.getLogger(" << tservice->get_name() << "Processor::class.java)" << endl; scope_down(out); indent(out) << "sealed interface ProcessFunction {" << endl; indent_up(); { for (auto tfunc : tservice->get_functions()) { generate_service_process_function(out, tservice, tfunc); } } scope_down(out); scope_down(out); out << endl << endl; out.close(); } void t_kotlin_generator::generate_service_process_function(ostream& out, t_service* tservice, t_function* tfunc) { string args_name = tservice->get_name() + "FunctionArgs." + tfunc->get_name() + "_args"; string rtype = type_name(tfunc->get_returntype(), true); indent(out) << "class " << tfunc->get_name() << "get_name() << ">(private val scope: kotlinx.coroutines.CoroutineScope) : " "org.apache.thrift.AsyncProcessFunction(\"" << tfunc->get_name() << "\"), ProcessFunction {" << endl; indent_up(); { indent(out) << "override fun isOneway() = " << (tfunc->is_oneway() ? "true" : "false") << endl; indent(out) << "override fun getEmptyArgsInstance() = " << args_name << "()" << endl; indent(out) << "override fun start(iface: I, args: " << args_name << ", resultHandler: org.apache.thrift.async.AsyncMethodCallback<" << rtype << ">) {" << endl; indent_up(); indent(out) << "scope.future {" << endl; indent_up(); indent(out) << "iface." << tfunc->get_name() << "("; { auto arguments = tfunc->get_arglist(); bool first = true; for (t_field* tfield : arguments->get_members()) { if (first) { first = false; } else { out << ", "; } out << "args." << tfield->get_name() << "!!"; } } out << ")" << endl; indent_down(); indent(out) << "}.whenComplete { r, t ->" << endl; { indent_up(); indent(out) << "if (t != null) {" << endl; indent_up(); indent(out) << "resultHandler.onError(t as java.lang.Exception)" << endl; indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "resultHandler.onComplete(r)" << endl; } scope_down(out); scope_down(out); scope_down(out); indent(out) << "override fun getResultHandler(fb: " "org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer, seqid: " "Int) =" << endl; indent_up(); { indent(out) << "object : org.apache.thrift.async.AsyncMethodCallback<" << rtype << ">{" << endl; indent_up(); { indent(out) << "override fun onComplete(response: " << rtype << ") {" << endl; indent_up(); if (tfunc->is_oneway()) { indent(out) << "// one way function, no result handling" << endl; } else { string result_name = tservice->get_name() + "FunctionResult." + tfunc->get_name() + "_result"; indent(out) << "val result = " << result_name << "()" << endl; if (!tfunc->get_returntype()->is_void()) { indent(out) << "result.success = response" << endl; } indent(out) << "try {" << endl; indent_up(); indent(out) << "sendResponse(fb, result, org.apache.thrift.protocol.TMessageType.REPLY, seqid)" << endl; indent_down(); indent(out) << "} catch (e: org.apache.thrift.transport.TTransportException) {" << endl; indent_up(); indent(out) << "logger.error(\"TTransportException writing to internal frame buffer\", e)" << endl; indent(out) << "fb.close()" << endl; indent_down(); indent(out) << "} catch (e: Exception) {" << endl; indent_up(); indent(out) << "logger.error(\"Exception writing to internal frame buffer\", e)" << endl; indent(out) << "onError(e)" << endl; scope_down(out); } scope_down(out); } { indent(out) << "override fun onError(exception: kotlin.Exception) {" << endl; indent_up(); if (tfunc->is_oneway()) { indent(out) << "if (exception is org.apache.thrift.transport.TTransportException) {" << endl; indent_up(); indent(out) << "logger.error(\"TTransportException inside handler\", exception)" << endl; indent(out) << "fb.close()" << endl; indent_down(); indent(out) << "} else {" << endl; indent_up(); indent(out) << "logger.error(\"Exception inside oneway handler\", exception)" << endl; scope_down(out); } else { indent(out) << "val (msgType, msg) = when (exception) {" << endl; indent_up(); auto xceptions = tfunc->get_xceptions()->get_members(); for (auto xception : xceptions) { indent(out) << "is " << type_name(xception->get_type()) << " -> {" << endl; indent_up(); string result_name = tservice->get_name() + "FunctionResult." + tfunc->get_name() + "_result"; indent(out) << "val result = " << result_name << "()" << endl; indent(out) << "result." << xception->get_name() << " = exception" << endl; indent(out) << "org.apache.thrift.protocol.TMessageType.REPLY to result" << endl; scope_down(out); } indent(out) << "is org.apache.thrift.transport.TTransportException -> {" << endl; indent_up(); indent(out) << "logger.error(\"TTransportException inside handler\", exception)" << endl; indent(out) << "fb.close()" << endl; indent(out) << "return" << endl; scope_down(out); indent(out) << "is org.apache.thrift.TApplicationException -> {" << endl; indent_up(); indent(out) << "logger.error(\"TApplicationException inside handler\", exception)" << endl; indent(out) << "org.apache.thrift.protocol.TMessageType.EXCEPTION to exception" << endl; scope_down(out); indent(out) << "else -> {" << endl; indent_up(); indent(out) << "logger.error(\"Exception inside handler\", exception)" << endl; indent(out) << "org.apache.thrift.protocol.TMessageType.EXCEPTION to " "org.apache.thrift.TApplicationException(org.apache.thrift." "TApplicationException.INTERNAL_ERROR, exception.message)" << endl; scope_down(out); scope_down(out); indent(out) << "try {" << endl; indent_up(); indent(out) << "sendResponse(fb, msg, msgType, seqid)" << endl; indent_down(); indent(out) << "} catch (ex: java.lang.Exception) {" << endl; indent_up(); indent(out) << "logger.error(\"Exception writing to internal frame buffer\", ex)" << endl; indent(out) << "fb.close()" << endl; scope_down(out); } scope_down(out); } scope_down(out); } indent_down(); } scope_down(out); } void t_kotlin_generator::generate_service_result_helpers(t_service* tservice) { string f_service_result_name = package_dir_ + "/" + tservice->get_name() + "FunctionResult.kt"; ofstream_with_content_based_conditional_update out; out.open(f_service_result_name.c_str()); out << autogen_comment() << warning_surpressions() << kotlin_package(); generate_docstring_comment(out, "/**\n", " * ", "function result for [" + tservice->get_name() + "]", " */\n"); indent(out) << "sealed interface " << tservice->get_name() << "FunctionResult {" << endl; indent_up(); for (auto func : tservice->get_functions()) { if (func->is_oneway()) { continue; } t_struct result(program_, func->get_name() + "_result"); t_field success(func->get_returntype(), "success", 0); if (!func->get_returntype()->is_void()) { result.append(&success); } for (auto& member : func->get_xceptions()->get_members()) { result.append(member); } generate_struct_definition(out, &result, false, tservice->get_name() + "FunctionResult"); } scope_down(out); out.close(); } void t_kotlin_generator::generate_service_args_helpers(t_service* tservice) { string f_service_args_name = package_dir_ + "/" + tservice->get_name() + "FunctionArgs.kt"; ofstream_with_content_based_conditional_update out; out.open(f_service_args_name.c_str()); out << autogen_comment() << warning_surpressions() << kotlin_package(); generate_docstring_comment(out, "/**\n", " * ", "function arguments for [" + tservice->get_name() + "]", " */\n"); indent(out) << "sealed interface " << tservice->get_name() << "FunctionArgs {" << endl; indent_up(); for (auto func : tservice->get_functions()) { t_struct* ts = func->get_arglist(); generate_struct_definition(out, ts, false, tservice->get_name() + "FunctionArgs"); out << endl; } scope_down(out); out.close(); } void t_kotlin_generator::generate_service(t_service* tservice) { generate_service_interface(tservice); generate_service_client(tservice); generate_service_processor(tservice); generate_service_args_helpers(tservice); generate_service_result_helpers(tservice); } void t_kotlin_generator::generate_xception(t_struct* txception) { generate_kotlin_struct(txception, true); } /** * Converts the parse type to a Java enum string for the given type. */ string t_kotlin_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "org.apache.thrift.protocol.TType.STRING"; case t_base_type::TYPE_BOOL: return "org.apache.thrift.protocol.TType.BOOL"; case t_base_type::TYPE_I8: return "org.apache.thrift.protocol.TType.BYTE"; case t_base_type::TYPE_I16: return "org.apache.thrift.protocol.TType.I16"; case t_base_type::TYPE_I32: return "org.apache.thrift.protocol.TType.I32"; case t_base_type::TYPE_I64: return "org.apache.thrift.protocol.TType.I64"; case t_base_type::TYPE_UUID: return "org.apache.thrift.protocol.TType.UUID"; case t_base_type::TYPE_DOUBLE: return "org.apache.thrift.protocol.TType.DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "org.apache.thrift.protocol.TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "org.apache.thrift.protocol.TType.STRUCT"; } else if (type->is_map()) { return "org.apache.thrift.protocol.TType.MAP"; } else if (type->is_set()) { return "org.apache.thrift.protocol.TType.SET"; } else if (type->is_list()) { return "org.apache.thrift.protocol.TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } string t_kotlin_generator::inner_enum_type_name(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; t_type* key_type = get_true_type(tmap->get_key_type()); return type_name(key_type, true) + ".class"; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; t_type* elem_type = get_true_type(tset->get_elem_type()); return type_name(elem_type, true) + ".class"; } return ""; } bool t_kotlin_generator::is_enum_set(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_set()) { t_set* tset = (t_set*)ttype; t_type* elem_type = get_true_type(tset->get_elem_type()); return elem_type->is_enum(); } return false; } bool t_kotlin_generator::is_enum_map(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; t_type* key_type = get_true_type(tmap->get_key_type()); return key_type->is_enum(); } return false; } /** * Packages the generated file * * @return String of the package, i.e. "package org.apache.thriftdemo" */ string t_kotlin_generator::kotlin_package() { if (!package_name_.empty()) { return string("package ") + package_name_ + endl + endl; } return ""; } string t_kotlin_generator::warning_surpressions() { return "@file:Suppress(\"ClassName\", \"PropertyName\", \"RedundantUnitReturnType\", " "\"NestedLambdaShadowedImplicitParameter\", " "\"RemoveRedundantQualifierName\")" + endl; } string t_kotlin_generator::constant_name(string name) { string constant_name; bool is_first = true; bool was_previous_char_upper = false; for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { constant_name += '_'; } constant_name += toupper(character); is_first = false; was_previous_char_upper = is_upper; } return constant_name; } bool t_kotlin_generator::is_reserved(const string& name) { return KOTLIN_RESERVED_WORDS_SET.find(name) != KOTLIN_RESERVED_WORDS_SET.end(); } string t_kotlin_generator::kotlin_safe_name(const string& name) { if (is_reserved(name)) { return "`" + name + "`"; } else { return name; } } void t_kotlin_generator::generate_kdoc_comment(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_docstring_comment(out, "/**\n", " * ", tdoc->get_doc(), " */\n"); } } std::string t_kotlin_generator::display_name() const { return "Kotlin"; } THRIFT_REGISTER_GENERATOR(kotlin, "Kotlin", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_generator.h0000644000000000000000000003221214370300523024033 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_GENERATOR_H #define T_GENERATOR_H #define MSC_2015_VER 1900 #include #include #include #include #include #include #include #include "thrift/common.h" #include "thrift/logging.h" #include "thrift/version.h" #include "thrift/generate/t_generator_registry.h" #include "thrift/parse/t_program.h" /** * Base class for a thrift code generator. This class defines the basic * routines for code generation and contains the top level method that * dispatches code generation across various components. * */ class t_generator { public: t_generator(t_program* program) { update_keywords_for_validation(); tmp_ = 0; indent_ = 0; program_ = program; program_name_ = get_program_name(program); escape_['\n'] = "\\n"; escape_['\r'] = "\\r"; escape_['\t'] = "\\t"; escape_['"'] = "\\\""; escape_['\\'] = "\\\\"; } virtual ~t_generator() {} /** * Framework generator method that iterates over all the parts of a program * and performs general actions. This is implemented by the base class and * should not normally be overwritten in the subclasses. */ virtual void generate_program(); const t_program* get_program() const { return program_; } void generate_docstring_comment(std::ostream& out, const std::string& comment_start, const std::string& line_prefix, const std::string& contents, const std::string& comment_end); static void parse_options(const std::string& options, std::string& language, std::map& parsed_options); /** * check whether sub-namespace declaraction is used by generator. * e.g. allow * namespace py.twisted bar * to specify namespace to use when -gen py:twisted is specified. * Will be called with subnamespace, i.e. is_valid_namespace("twisted") * will be called for the above example. */ static bool is_valid_namespace(const std::string& sub_namespace) { (void)sub_namespace; return false; } /** * Escape string to use one in generated sources. */ virtual std::string escape_string(const std::string& in) const; std::string get_escaped_string(t_const_value* constval) { return escape_string(constval->get_string()); } /** * Check if all identifiers are valid for the target language * See update_keywords_for_validation() */ virtual void validate_input() const; /** * Must override. Should be equivalent to the "long name" parameter at THRIFT_REGISTER_GENERATOR. * TODO: essentially duplicates, so we should find a way to get rid of one */ virtual std::string display_name() const = 0; protected: virtual std::set lang_keywords_for_validation() const; /** * Call this from constructor if you implement lang_keywords_for_validation() */ void update_keywords_for_validation() { keywords_ = lang_keywords_for_validation(); } /** * A list of reserved words that cannot be used as identifiers. */ std::set keywords_; virtual void validate_id(const std::string& id) const; virtual void validate(t_enum const* en) const; virtual void validate(t_enum_value const* en_val) const; virtual void validate(t_typedef const* td) const; virtual void validate(t_const const* c) const; virtual void validate(t_service const* s) const; virtual void validate(t_struct const* c) const; virtual void validate(t_field const* f) const; virtual void validate(t_function const* f) const; template void validate(const std::vector& list) const; /** * Optional methods that may be implemented by subclasses to take necessary * steps at the beginning or end of code generation. */ virtual void init_generator() {} virtual void close_generator() {} virtual void generate_consts(std::vector consts); /** * Pure virtual methods implemented by the generator subclasses. */ virtual void generate_typedef(t_typedef* ttypedef) = 0; virtual void generate_enum(t_enum* tenum) = 0; virtual void generate_const(t_const* tconst) { (void)tconst; } virtual void generate_struct(t_struct* tstruct) = 0; virtual void generate_service(t_service* tservice) = 0; virtual void generate_forward_declaration(t_struct*) {} virtual void generate_xception(t_struct* txception) { // By default exceptions are the same as structs generate_struct(txception); } /** * Method to get the program name, may be overridden */ virtual std::string get_program_name(t_program* tprogram) { return tprogram->get_name(); } /** * Method to get the service name, may be overridden */ virtual std::string get_service_name(t_service* tservice) { return tservice->get_name(); } /** * Get the current output directory */ virtual std::string get_out_dir() const { if (program_->is_out_path_absolute()) { return program_->get_out_path() + "/"; } return program_->get_out_path() + out_dir_base_ + "/"; } /** * Creates a unique temporary variable name, which is just "name" with a * number appended to it (i.e. name35) */ std::string tmp(std::string name) { std::ostringstream out; out << name << tmp_++; return out.str(); } /** * Generates a comment about this code being autogenerated, using C++ style * comments, which are also fair game in Java / PHP, yay! * * @return C-style comment mentioning that this file is autogenerated. */ virtual std::string autogen_comment() { return std::string("/**\n") + " * " + autogen_summary() + "\n" + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + " * @generated\n" + " */\n"; } virtual std::string autogen_summary() { return std::string("Autogenerated by Thrift Compiler (") + THRIFT_VERSION + ")"; } /** * Indentation level modifiers */ void indent_up() { ++indent_; } void indent_down() { --indent_; } /** * Indentation validation helper */ int indent_count() { return indent_; } void indent_validate( int expected, const char * func_name) { if (indent_ != expected) { pverbose("Wrong indent count in %s: difference = %i \n", func_name, (expected - indent_)); } } /** * Indentation print function */ std::string indent() { std::string ind = ""; int i; for (i = 0; i < indent_; ++i) { ind += indent_str(); } return ind; } /** * Indentation utility wrapper */ std::ostream& indent(std::ostream& os) { return os << indent(); } /** * Capitalization helpers */ std::string capitalize(std::string in) { in[0] = toupper(in[0]); return in; } std::string decapitalize(std::string in) { in[0] = tolower(in[0]); return in; } static std::string lowercase(std::string in) { for (size_t i = 0; i < in.size(); ++i) { in[i] = tolower(in[i]); } return in; } static std::string uppercase(std::string in) { for (size_t i = 0; i < in.size(); ++i) { in[i] = toupper(in[i]); } return in; } /** * Transforms a camel case string to an equivalent one separated by underscores * e.g. aMultiWord -> a_multi_word * someName -> some_name * CamelCase -> camel_case * name -> name * Name -> name */ std::string underscore(std::string in) { in[0] = tolower(in[0]); for (size_t i = 1; i < in.size(); ++i) { if (isupper(in[i])) { in[i] = tolower(in[i]); in.insert(i, "_"); } } return in; } /** * Transforms a string with words separated by underscores to a camel case equivalent * e.g. a_multi_word -> aMultiWord * some_name -> someName * name -> name */ std::string camelcase(std::string in) { std::ostringstream out; bool underscore = false; for (size_t i = 0; i < in.size(); i++) { if (in[i] == '_') { underscore = true; continue; } if (underscore) { out << (char)toupper(in[i]); underscore = false; continue; } out << in[i]; } return out.str(); } const std::string emit_double_as_string(const double value) { std::stringstream double_output_stream; // sets the maximum precision: http://en.cppreference.com/w/cpp/io/manip/setprecision // sets the output format to fixed: http://en.cppreference.com/w/cpp/io/manip/fixed (not in scientific notation) double_output_stream << std::setprecision(std::numeric_limits::digits10 + 1); #ifdef _MSC_VER // strtod is broken in MSVC compilers older than 2015, so std::fixed fails to format a double literal. // more details: https://blogs.msdn.microsoft.com/vcblog/2014/06/18/ // c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/ // and // http://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/ #if _MSC_VER >= MSC_2015_VER double_output_stream << std::fixed; #endif #else double_output_stream << std::fixed; #endif double_output_stream << value; return double_output_stream.str(); } public: /** * Get the true type behind a series of typedefs. */ static const t_type* get_true_type(const t_type* type) { return type->get_true_type(); } static t_type* get_true_type(t_type* type) { return type->get_true_type(); } protected: /** * The program being generated */ t_program* program_; /** * Quick accessor for formatted program name that is currently being * generated. */ std::string program_name_; /** * Quick accessor for formatted service name that is currently being * generated. */ std::string service_name_; /** * Output type-specifc directory name ("gen-*") */ std::string out_dir_base_; /** * Map of characters to escape in string literals. */ std::map escape_; virtual std::string indent_str() const { return " "; } private: /** * Current code indentation level */ int indent_; /** * Temporary variable counter, for making unique variable names */ int tmp_; }; template > class template_ofstream_with_content_based_conditional_update : public std::ostringstream { public: template_ofstream_with_content_based_conditional_update(): contents_written(false) {} template_ofstream_with_content_based_conditional_update(std::string const& output_file_path_) : output_file_path(output_file_path_), contents_written(false) {} ~template_ofstream_with_content_based_conditional_update() { if (!contents_written) { close(); } } void open(std::string const& output_file_path_) { output_file_path = output_file_path_; clear_buf(); contents_written = false; } void close() { if (contents_written || output_file_path == "") return; if (!is_readable(output_file_path)) { dump(); return; } std::ifstream old_file; old_file.exceptions(old_file.exceptions() | std::ifstream::badbit | std::ifstream::failbit); old_file.open(output_file_path.c_str(), std::ios::in); if (old_file) { std::ostringstream oss; oss << old_file.rdbuf(); std::string const old_file_contents(oss.str()); old_file.close(); if (old_file_contents != str()) { dump(); } } } protected: void dump() { std::ofstream out_file; out_file.exceptions(out_file.exceptions() | std::ofstream::badbit | std::ofstream::failbit); try { out_file.open(output_file_path.c_str(), std::ios::out); } catch (const std::ios_base::failure& e) { ::failure("failed to write the output to the file '%s', details: '%s'", output_file_path.c_str(), e.what()); } out_file << str(); out_file.close(); clear_buf(); contents_written = true; } void clear_buf() { str(std::string()); } static bool is_readable(std::string const& file_name) { return static_cast(std::ifstream(file_name.c_str())); } private: std::string output_file_path; bool contents_written; }; typedef template_ofstream_with_content_based_conditional_update ofstream_with_content_based_conditional_update; #endif thrift-0.19.0/compiler/cpp/src/thrift/generate/t_json_generator.cc0000644000000000000000000005414114370300523025227 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; using std::stack; static const string endl = "\n"; static const string quot = "\""; static const bool NO_INDENT = false; static const bool FORCE_STRING = true; class t_json_generator : public t_generator { public: t_json_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; should_merge_includes_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("merge") == 0) { should_merge_includes_ = true; } else { throw "unknown option json:" + iter->first; } } out_dir_base_ = "gen-json"; } ~t_json_generator() override = default; /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_program() override; void generate_function(t_function* tfunc); void generate_field(t_field* field); void generate_service(t_service* tservice) override; void generate_struct(t_struct* tstruct) override; private: bool should_merge_includes_; ofstream_with_content_based_conditional_update f_json_; std::stack comma_needed_; template string number_to_string(T t) { std::ostringstream out; out.imbue(std::locale::classic()); out.precision(std::numeric_limits::digits10); out << t; return out.str(); } template void write_number(T n) { f_json_ << number_to_string(n); } string get_type_name(t_type* ttype); string get_qualified_name(t_type* ttype); void start_object(bool should_indent = true); void start_array(); void end_object(); void end_array(); void write_comma_if_needed(); void indicate_comma_needed(); string escape_json_string(const string& input); string json_str(const string& str); void merge_includes(t_program*); void generate_constant(t_const* con); void write_type_spec_entry(const char* name, t_type* ttype); void write_type_spec_object(const char* name, t_type* ttype); void write_type_spec(t_type* ttype); void write_string(const string& value); void write_value(t_type* tvalue); void write_const_value(t_const_value* value, bool force_string = false); void write_key_and(string key); void write_key_and_string(string key, string val); void write_key_and_integer(string key, int val); void write_key_and_bool(string key, bool val); }; void t_json_generator::init_generator() { MKDIR(get_out_dir().c_str()); string f_json_name = get_out_dir() + program_->get_name() + ".json"; f_json_.open(f_json_name.c_str()); // Merge all included programs into this one so we can output one big file. if (should_merge_includes_) { merge_includes(program_); } } string t_json_generator::escape_json_string(const string& input) { std::ostringstream ss; for (char iter : input) { switch (iter) { case '\\': ss << "\\\\"; break; case '"': ss << "\\\""; break; case '/': ss << "\\/"; break; case '\b': ss << "\\b"; break; case '\f': ss << "\\f"; break; case '\n': ss << "\\n"; break; case '\r': ss << "\\r"; break; case '\t': ss << "\\t"; break; default: ss << iter; break; } } return ss.str(); } void t_json_generator::start_object(bool should_indent) { f_json_ << (should_indent ? indent() : "") << "{" << endl; indent_up(); comma_needed_.push(false); } void t_json_generator::start_array() { f_json_ << "[" << endl; indent_up(); comma_needed_.push(false); } void t_json_generator::write_comma_if_needed() { if (comma_needed_.top()) { f_json_ << "," << endl; } } void t_json_generator::indicate_comma_needed() { comma_needed_.pop(); comma_needed_.push(true); } void t_json_generator::write_key_and(string key) { write_comma_if_needed(); indent(f_json_) << json_str(key) << ": "; indicate_comma_needed(); } void t_json_generator::write_key_and_integer(string key, int val) { write_comma_if_needed(); indent(f_json_) << json_str(key) << ": " << number_to_string(val); indicate_comma_needed(); } void t_json_generator::write_key_and_string(string key, string val) { write_comma_if_needed(); indent(f_json_) << json_str(key) << ": " << json_str(val); indicate_comma_needed(); } void t_json_generator::write_key_and_bool(string key, bool val) { write_comma_if_needed(); indent(f_json_) << json_str(key) << ": " << (val ? "true" : "false"); indicate_comma_needed(); } void t_json_generator::end_object() { indent_down(); f_json_ << endl << indent() << "}"; comma_needed_.pop(); } void t_json_generator::end_array() { indent_down(); if (comma_needed_.top()) { f_json_ << endl; } indent(f_json_) << "]"; comma_needed_.pop(); } void t_json_generator::write_type_spec_object(const char* name, t_type* ttype) { ttype = ttype->get_true_type(); if (ttype->is_struct() || ttype->is_xception() || ttype->is_container() || ttype->is_enum()) { write_key_and(name); start_object(NO_INDENT); write_key_and("typeId"); write_type_spec(ttype); end_object(); } } void t_json_generator::write_type_spec_entry(const char* name, t_type* ttype) { write_key_and(name); write_type_spec(ttype); } void t_json_generator::write_type_spec(t_type* ttype) { ttype = ttype->get_true_type(); write_string(get_type_name(ttype)); if (ttype->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : ttype->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } if (ttype->is_struct() || ttype->is_xception() || ttype->is_enum()) { write_key_and_string("class", get_qualified_name(ttype)); } else if (ttype->is_map()) { t_type* ktype = ((t_map*)ttype)->get_key_type(); t_type* vtype = ((t_map*)ttype)->get_val_type(); write_key_and_string("keyTypeId", get_type_name(ktype)); write_key_and_string("valueTypeId", get_type_name(vtype)); write_type_spec_object("keyType", ktype); write_type_spec_object("valueType", vtype); } else if (ttype->is_list()) { t_type* etype = ((t_list*)ttype)->get_elem_type(); write_key_and_string("elemTypeId", get_type_name(etype)); write_type_spec_object("elemType", etype); } else if (ttype->is_set()) { t_type* etype = ((t_set*)ttype)->get_elem_type(); write_key_and_string("elemTypeId", get_type_name(etype)); write_type_spec_object("elemType", etype); } } void t_json_generator::close_generator() { f_json_ << endl; f_json_.close(); } void t_json_generator::merge_includes(t_program* program) { vector includes = program->get_includes(); vector::iterator inc_iter; for (inc_iter = includes.begin(); inc_iter != includes.end(); ++inc_iter) { t_program* include = *inc_iter; // recurse in case we get crazy merge_includes(include); // merge enums vector enums = include->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { program->add_enum(*en_iter); } // merge typedefs vector typedefs = include->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { program->add_typedef(*td_iter); } // merge structs vector objects = include->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { program->add_struct(*o_iter); } // merge constants vector consts = include->get_consts(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { program->add_const(*c_iter); } // merge services vector services = include->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { program->add_service(*sv_iter); } } } void t_json_generator::generate_program() { init_generator(); start_object(); write_key_and_string("name", program_->get_name()); if (program_->has_doc()) { write_key_and_string("doc", program_->get_doc()); } // When merging includes, the "namespaces" and "includes" sections // become ambiguous, so just skip them. if (!should_merge_includes_) { // Generate namespaces write_key_and("namespaces"); start_object(NO_INDENT); const map& namespaces = program_->get_namespaces(); map::const_iterator ns_it; for (ns_it = namespaces.begin(); ns_it != namespaces.end(); ++ns_it) { write_key_and_string(ns_it->first, ns_it->second); indicate_comma_needed(); } end_object(); // Generate includes write_key_and("includes"); start_array(); const vector includes = program_->get_includes(); vector::const_iterator inc_it; for (inc_it = includes.begin(); inc_it != includes.end(); ++inc_it) { write_comma_if_needed(); f_json_ << indent(); write_string((*inc_it)->get_name()); indicate_comma_needed(); } end_array(); } // Generate enums write_key_and("enums"); start_array(); vector enums = program_->get_enums(); vector::iterator en_iter; for (en_iter = enums.begin(); en_iter != enums.end(); ++en_iter) { write_comma_if_needed(); generate_enum(*en_iter); indicate_comma_needed(); } end_array(); // Generate typedefs write_key_and("typedefs"); start_array(); vector typedefs = program_->get_typedefs(); vector::iterator td_iter; for (td_iter = typedefs.begin(); td_iter != typedefs.end(); ++td_iter) { write_comma_if_needed(); generate_typedef(*td_iter); indicate_comma_needed(); } end_array(); // Generate structs, exceptions, and unions in declared order write_key_and("structs"); start_array(); vector objects = program_->get_objects(); vector::iterator o_iter; for (o_iter = objects.begin(); o_iter != objects.end(); ++o_iter) { write_comma_if_needed(); if ((*o_iter)->is_xception()) { generate_xception(*o_iter); } else { generate_struct(*o_iter); } indicate_comma_needed(); } end_array(); // Generate constants write_key_and("constants"); start_array(); vector consts = program_->get_consts(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { write_comma_if_needed(); generate_constant(*c_iter); indicate_comma_needed(); } end_array(); // Generate services write_key_and("services"); start_array(); vector services = program_->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { write_comma_if_needed(); generate_service(*sv_iter); indicate_comma_needed(); } end_array(); end_object(); // Close the generator close_generator(); } void t_json_generator::generate_typedef(t_typedef* ttypedef) { start_object(); write_key_and_string("name", get_qualified_name(ttypedef)); write_key_and_string("typeId", get_type_name(ttypedef->get_true_type())); write_type_spec_object("type", ttypedef->get_true_type()); if (ttypedef->has_doc()) { write_key_and_string("doc", ttypedef->get_doc()); } if (ttypedef->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : ttypedef->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } end_object(); } void t_json_generator::write_string(const string& value) { f_json_ << quot << escape_json_string(value) << quot; } void t_json_generator::write_const_value(t_const_value* value, bool should_force_string) { switch (value->get_type()) { case t_const_value::CV_IDENTIFIER: case t_const_value::CV_INTEGER: if (should_force_string) { write_string(number_to_string(value->get_integer())); } else { write_number(value->get_integer()); } break; case t_const_value::CV_DOUBLE: if (should_force_string) { write_string(number_to_string(value->get_double())); } else { write_number(value->get_double()); } break; case t_const_value::CV_STRING: write_string(value->get_string()); break; case t_const_value::CV_LIST: { start_array(); std::vector list = value->get_list(); std::vector::iterator lit; for (lit = list.begin(); lit != list.end(); ++lit) { write_comma_if_needed(); f_json_ << indent(); write_const_value(*lit); indicate_comma_needed(); } end_array(); break; } case t_const_value::CV_MAP: { start_object(NO_INDENT); std::map map = value->get_map(); std::map::iterator mit; for (mit = map.begin(); mit != map.end(); ++mit) { write_comma_if_needed(); f_json_ << indent(); // JSON objects only allow string keys write_const_value(mit->first, FORCE_STRING); f_json_ << ": "; write_const_value(mit->second); indicate_comma_needed(); } end_object(); break; } default: f_json_ << "null"; break; } } string t_json_generator::json_str(const string& str) { return quot + escape_json_string(str) + quot; } void t_json_generator::generate_constant(t_const* con) { start_object(); write_key_and_string("name", con->get_name()); write_key_and_string("typeId", get_type_name(con->get_type())); write_type_spec_object("type", con->get_type()); if (con->has_doc()) { write_key_and_string("doc", con->get_doc()); } write_key_and("value"); write_const_value(con->get_value()); end_object(); } void t_json_generator::generate_enum(t_enum* tenum) { start_object(); write_key_and_string("name", tenum->get_name()); if (tenum->has_doc()) { write_key_and_string("doc", tenum->get_doc()); } if (tenum->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : tenum->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } write_key_and("members"); start_array(); vector values = tenum->get_constants(); vector::iterator val_iter; for (val_iter = values.begin(); val_iter != values.end(); ++val_iter) { write_comma_if_needed(); t_enum_value* val = (*val_iter); start_object(); write_key_and_string("name", val->get_name()); write_key_and_integer("value", val->get_value()); if (val->has_doc()) { write_key_and_string("doc", val->get_doc()); } end_object(); indicate_comma_needed(); } end_array(); end_object(); } void t_json_generator::generate_struct(t_struct* tstruct) { start_object(); write_key_and_string("name", tstruct->get_name()); if (tstruct->has_doc()) { write_key_and_string("doc", tstruct->get_doc()); } if (tstruct->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : tstruct->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } write_key_and_bool("isException", tstruct->is_xception()); write_key_and_bool("isUnion", tstruct->is_union()); write_key_and("fields"); start_array(); vector members = tstruct->get_members(); vector::iterator mem_iter; for (mem_iter = members.begin(); mem_iter != members.end(); mem_iter++) { write_comma_if_needed(); generate_field(*mem_iter); indicate_comma_needed(); } end_array(); end_object(); } void t_json_generator::generate_service(t_service* tservice) { start_object(); write_key_and_string("name", get_qualified_name(tservice)); if (tservice->get_extends()) { write_key_and_string("extends", get_qualified_name(tservice->get_extends())); } if (tservice->has_doc()) { write_key_and_string("doc", tservice->get_doc()); } if (tservice->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : tservice->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } write_key_and("functions"); start_array(); vector functions = tservice->get_functions(); vector::iterator fn_iter = functions.begin(); for (; fn_iter != functions.end(); fn_iter++) { write_comma_if_needed(); generate_function(*fn_iter); indicate_comma_needed(); } end_array(); end_object(); } void t_json_generator::generate_function(t_function* tfunc) { start_object(); write_key_and_string("name", tfunc->get_name()); write_key_and_string("returnTypeId", get_type_name(tfunc->get_returntype())); write_type_spec_object("returnType", tfunc->get_returntype()); write_key_and_bool("oneway", tfunc->is_oneway()); if (tfunc->has_doc()) { write_key_and_string("doc", tfunc->get_doc()); } if (tfunc->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : tfunc->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } write_key_and("arguments"); start_array(); vector members = tfunc->get_arglist()->get_members(); vector::iterator mem_iter = members.begin(); for (; mem_iter != members.end(); mem_iter++) { write_comma_if_needed(); generate_field(*mem_iter); indicate_comma_needed(); } end_array(); write_key_and("exceptions"); start_array(); vector excepts = tfunc->get_xceptions()->get_members(); vector::iterator ex_iter = excepts.begin(); for (; ex_iter != excepts.end(); ex_iter++) { write_comma_if_needed(); generate_field(*ex_iter); indicate_comma_needed(); } end_array(); end_object(); } void t_json_generator::generate_field(t_field* field) { start_object(); write_key_and_integer("key", field->get_key()); write_key_and_string("name", field->get_name()); write_key_and_string("typeId", get_type_name(field->get_type())); write_type_spec_object("type", field->get_type()); if (field->has_doc()) { write_key_and_string("doc", field->get_doc()); } if (field->annotations_.size() > 0) { write_key_and("annotations"); start_object(); for (auto & annotation : field->annotations_) { for (auto& annotation_value : annotation.second) { write_key_and_string(annotation.first, annotation_value); } } end_object(); } write_key_and("required"); switch (field->get_req()) { case t_field::T_REQUIRED: write_string("required"); break; case t_field::T_OPT_IN_REQ_OUT: write_string("req_out"); break; default: write_string("optional"); break; } if (field->get_value()) { write_key_and("default"); write_const_value(field->get_value()); } end_object(); } string t_json_generator::get_type_name(t_type* ttype) { ttype = ttype->get_true_type(); if (ttype->is_list()) { return "list"; } if (ttype->is_set()) { return "set"; } if (ttype->is_map()) { return "map"; } if (ttype->is_enum()) { return "enum"; } if (ttype->is_struct()) { return ((t_struct*)ttype)->is_union() ? "union" : "struct"; } if (ttype->is_xception()) { return "exception"; } if (ttype->is_base_type()) { t_base_type* tbasetype = (t_base_type*)ttype; return tbasetype->is_binary() ? "binary" : t_base_type::t_base_name(tbasetype->get_base()); } return "(unknown)"; } string t_json_generator::get_qualified_name(t_type* ttype) { if (should_merge_includes_ || ttype->get_program() == program_) { return ttype->get_name(); } return ttype->get_program()->get_name() + "." + ttype->get_name(); } std::string t_json_generator::display_name() const { return "JSON"; } THRIFT_REGISTER_GENERATOR(json, "JSON", " merge: Generate output with included files merged\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_go_generator.cc0000644000000000000000000044633514472647462024720 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This file is programmatically sanitized for style: * astyle --style=1tbs -f -p -H -j -U t_go_generator.cc * * The output of astyle should not be taken unquestioningly, but it is a good * guide for ensuring uniformity and readability. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_generator.h" #include "thrift/generate/t_go_generator.h" #include "thrift/generate/go_validator_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; /** * A helper for automatically formatting the emitted Go code from the Thrift * IDL per the Go style guide. * * Returns: * - true, if the formatting process succeeded. * - false, if the formatting process failed, which means the basic output was * still generated. */ bool format_go_output(const string& file_path); // returns true if field initialization can be omitted since it has corresponding go type zero value // or default value is not set bool t_go_generator::omit_initialization(t_field* tfield) { t_const_value* value = tfield->get_value(); if (!value) { return true; } t_type* type = tfield->get_type()->get_true_type(); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw ""; case t_base_type::TYPE_STRING: if (type->is_binary()) { //[]byte are always inline return false; } // strings are pointers if has no default return value->get_string().empty(); case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return value->get_integer() == 0; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { return value->get_integer() == 0; } else { return value->get_double() == 0.; } case t_base_type::TYPE_UUID: // it's hard to detect all zero uuid here, so just always inline it. return false; default: throw "compiler error: unhandled type"; } } return false; } // Returns true if the type need a reference if used as optional without default static bool type_need_reference(t_type* type) { type = type->get_true_type(); if (type->is_map() || type->is_set() || type->is_list() || type->is_struct() || type->is_xception() || type->is_binary()) { return false; } return true; } // returns false if field could not use comparison to default value as !IsSet* bool t_go_generator::is_pointer_field(t_field* tfield, bool in_container_value) { (void)in_container_value; if (tfield->annotations_.count("cpp.ref") != 0) { return true; } t_type* type = tfield->get_type()->get_true_type(); // Structs in containers are pointers if (type->is_struct() || type->is_xception()) { return true; } if (!(tfield->get_req() == t_field::T_OPTIONAL)) { return false; } bool has_default = tfield->get_value(); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw ""; case t_base_type::TYPE_STRING: if (type->is_binary()) { //[]byte are always inline return false; } // strings are pointers if has no default return !has_default; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: case t_base_type::TYPE_UUID: return !has_default; default: break; } } else if (type->is_enum()) { return !has_default; } else if (type->is_struct() || type->is_xception()) { return true; } else if (type->is_map()) { return has_default; } else if (type->is_set()) { return has_default; } else if (type->is_list()) { return has_default; } else if (type->is_typedef()) { return has_default; } throw "INVALID TYPE IN type_to_go_type: " + type->get_name(); } std::string t_go_generator::camelcase(const std::string& value) const { std::string value2(value); std::setlocale(LC_ALL, "C"); // set locale to classic // Fix common initialism in first word fix_common_initialism(value2, 0); // as long as we are changing things, let's change _ followed by lowercase to // capital and fix common initialisms for (std::string::size_type i = 1; i < value2.size() - 1; ++i) { if (value2[i] == '_') { if (islower(value2[i + 1])) { value2.replace(i, 2, 1, toupper(value2[i + 1])); } if (i > static_cast(std::numeric_limits().max())) { throw "integer overflow in t_go_generator::camelcase, value = " + value; } fix_common_initialism(value2, static_cast(i)); } } return value2; } // Checks to see if the word starting at i in value contains a common initialism // and if so replaces it with the upper case version of the word. void t_go_generator::fix_common_initialism(std::string& value, int i) const { if (!ignore_initialisms_) { size_t wordLen = value.find('_', i); if (wordLen != std::string::npos) { wordLen -= i; } std::string word = value.substr(i, wordLen); std::transform(word.begin(), word.end(), word.begin(), ::toupper); if (commonInitialisms.find(word) != commonInitialisms.end()) { value.replace(i, word.length(), word); } } } std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result, const std::string& service_name) const { if (value.size() <= 0) { return value; } std::string value2(value), prefix; string::size_type dot_pos = value.rfind('.'); if (dot_pos != string::npos) { prefix = value.substr(0, dot_pos + 1) + prefix; value2 = value.substr(dot_pos + 1); } if (!isupper(value2[0])) { value2[0] = toupper(value2[0]); } value2 = camelcase(value2); // final length before further checks, the string may become longer size_t len_before = value2.length(); // IDL identifiers may start with "New" which interferes with the CTOR pattern // Adding an extra underscore to all those identifiers solves this if ((len_before >= 3) && (value2.substr(0, 3) == "New")) { value2 += '_'; } // IDL identifiers may end with "Args"/"Result" which interferes with the implicit service // function structs // Adding another extra underscore to all those identifiers solves this // Suppress this check for the actual helper struct names if (!is_args_or_result) { bool ends_with_args = (len_before >= 4) && (value2.substr(len_before - 4, 4) == "Args"); bool ends_with_rslt = (len_before >= 6) && (value2.substr(len_before - 6, 6) == "Result"); if (ends_with_args || ends_with_rslt) { value2 += '_'; } } // Avoid naming collisions with other services if (is_args_or_result) { prefix += publicize(service_name); } return prefix + value2; } std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result) const { return publicize(value, is_args_or_result, service_name_); } std::string t_go_generator::new_prefix(const std::string& value) const { if (value.size() <= 0) { return value; } string::size_type dot_pos = value.rfind('.'); if (dot_pos != string::npos) { return value.substr(0, dot_pos + 1) + "New" + publicize(value.substr(dot_pos + 1)); } return "New" + publicize(value); } std::string t_go_generator::privatize(const std::string& value) const { if (value.size() <= 0) { return value; } std::string value2(value); if (!islower(value2[0])) { value2[0] = tolower(value2[0]); } value2 = camelcase(value2); return value2; } std::string t_go_generator::variable_name_to_go_name(const std::string& value) { if (value.size() <= 0) { return value; } std::string value2(value); std::transform(value2.begin(), value2.end(), value2.begin(), ::tolower); switch (value[0]) { case 'b': case 'B': if (value2 != "break") { return value; } break; case 'c': case 'C': if (value2 != "case" && value2 != "chan" && value2 != "const" && value2 != "continue") { return value; } break; case 'd': case 'D': if (value2 != "default" && value2 != "defer") { return value; } break; case 'e': case 'E': if (value2 != "else" && value2 != "error") { return value; } break; case 'f': case 'F': if (value2 != "fallthrough" && value2 != "for" && value2 != "func") { return value; } break; case 'g': case 'G': if (value2 != "go" && value2 != "goto") { return value; } break; case 'i': case 'I': if (value2 != "if" && value2 != "import" && value2 != "interface") { return value; } break; case 'm': case 'M': if (value2 != "map") { return value; } break; case 'p': case 'P': if (value2 != "package") { return value; } break; case 'r': case 'R': if (value2 != "range" && value2 != "return") { return value; } break; case 's': case 'S': if (value2 != "select" && value2 != "struct" && value2 != "switch") { return value; } break; case 't': case 'T': if (value2 != "type") { return value; } break; case 'v': case 'V': if (value2 != "var") { return value; } break; default: return value; } return value2 + "_a1"; } /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_go_generator::init_generator() { // Make output directory string module = get_real_go_module(program_); string target = module; package_dir_ = get_out_dir(); // This set is taken from https://github.com/golang/lint/blob/master/lint.go#L692 commonInitialisms.insert("API"); commonInitialisms.insert("ASCII"); commonInitialisms.insert("CPU"); commonInitialisms.insert("CSS"); commonInitialisms.insert("DNS"); commonInitialisms.insert("EOF"); commonInitialisms.insert("GUID"); commonInitialisms.insert("HTML"); commonInitialisms.insert("HTTP"); commonInitialisms.insert("HTTPS"); commonInitialisms.insert("ID"); commonInitialisms.insert("IP"); commonInitialisms.insert("JSON"); commonInitialisms.insert("LHS"); commonInitialisms.insert("QPS"); commonInitialisms.insert("RAM"); commonInitialisms.insert("RHS"); commonInitialisms.insert("RPC"); commonInitialisms.insert("SLA"); commonInitialisms.insert("SMTP"); commonInitialisms.insert("SSH"); commonInitialisms.insert("TCP"); commonInitialisms.insert("TLS"); commonInitialisms.insert("TTL"); commonInitialisms.insert("UDP"); commonInitialisms.insert("UI"); commonInitialisms.insert("UID"); commonInitialisms.insert("UUID"); commonInitialisms.insert("URI"); commonInitialisms.insert("URL"); commonInitialisms.insert("UTF8"); commonInitialisms.insert("VM"); commonInitialisms.insert("XML"); commonInitialisms.insert("XSRF"); commonInitialisms.insert("XSS"); // names of read and write methods if (read_write_private_) { read_method_name_ = "read"; write_method_name_ = "write"; } else { read_method_name_ = "Read"; write_method_name_ = "Write"; } equals_method_name_ = "Equals"; while (true) { // TODO: Do better error checking here. MKDIR(package_dir_.c_str()); if (module.empty()) { break; } string::size_type pos = module.find('.'); if (pos == string::npos) { package_dir_ += "/"; package_dir_ += module; package_name_ = module; module.clear(); } else { package_dir_ += "/"; package_dir_ += module.substr(0, pos); module.erase(0, pos + 1); } } string::size_type loc; while ((loc = target.find(".")) != string::npos) { target.replace(loc, 1, 1, '/'); } // Make output files f_types_name_ = package_dir_ + "/" + program_name_ + ".go"; f_types_.open(f_types_name_); f_consts_name_ = package_dir_ + "/" + program_name_ + "-consts.go"; f_consts_.open(f_consts_name_); // Print header f_types_ << go_autogen_comment() << go_package() << render_includes(false); f_consts_ << go_autogen_comment() << go_package() << render_includes(true); f_const_values_ << endl << "func init() {" << endl; // Create file for the GoUnusedProtection__ variable string f_unused_prot_name_ = package_dir_ + "/" + "GoUnusedProtection__.go"; ofstream_with_content_based_conditional_update f_unused_prot_; f_unused_prot_.open(f_unused_prot_name_.c_str()); f_unused_prot_ << go_autogen_comment() << go_package() << render_import_protection(); f_unused_prot_.close(); } string t_go_generator::render_included_programs(string& unused_prot) { const vector& includes = program_->get_includes(); string result = ""; string local_namespace = get_real_go_module(program_); std::set included; for (auto include : includes) { std::string includeModule = get_real_go_module(include); if (!local_namespace.empty() && local_namespace == includeModule) { continue; } if (!included.insert(includeModule).second) { continue; } result += render_program_import(include, unused_prot); } return result; } string t_go_generator::render_program_import(const t_program* program, string& unused_protection) { string result = ""; string go_module = get_real_go_module(program); string go_path = go_module; size_t found = 0; for (size_t j = 0; j < go_module.size(); j++) { // Import statement uses slashes ('/') in namespace if (go_module[j] == '.') { go_path[j] = '/'; found = j + 1; } } auto it = package_identifiers_.find(go_module); auto last_component = go_module.substr(found); if (it == package_identifiers_.end()) { auto value = last_component; // This final path component has already been used, let's construct a more unique alias if (package_identifiers_set_.find(value) != package_identifiers_set_.end()) { // TODO: This would produce more readable code if it appended trailing go_module // path components to generate a more readable name unique identifier (e.g. use // packageacommon as the alias for packagea/common instead of common=). But just // appending an integer is much simpler code value = tmp(value); } package_identifiers_set_.insert(value); it = package_identifiers_.emplace(go_module, std::move(value)).first; } auto const& package_identifier = it->second; result += "\t"; // if the package_identifier is different than final path component we need an alias if (last_component.compare(package_identifier) != 0) { result += package_identifier + " "; } string s; for (auto const& e : package_identifiers_set_) { s += e; s += ','; } s.pop_back(); result += "\"" + gen_package_prefix_ + go_path + "\"\n"; unused_protection += "var _ = " + package_identifier + ".GoUnusedProtection__\n"; return result; } /** * Render import lines for the system packages. * * The arg system_packages supports the following two options for import auto * rename in case duplications happens: * * 1. The full import path without double quotation marks, with part after the * last "/" as the import identifier. e.g.: * - "context" (context) * - "database/sql/driver" (driver) * 2. A rename import with double quotation marks around the full import path, * with the part before the first space as the import identifier. e.g.: * - "thrift \"github.com/apache/thrift/lib/go/thrift\"" (thrift) * * If a system package's package name is different from the last part of its * full import path, please always rename import it for dedup to work correctly, * e.g. "package \"github.com/org/go-package\"". * * @param system_packages */ string t_go_generator::render_system_packages(std::vector& system_packages) { string result = ""; for (vector::iterator iter = system_packages.begin(); iter != system_packages.end(); ++iter) { string package = *iter; string identifier = package; auto space_pos = package.find(" "); if (space_pos != string::npos) { // This is a rename import line, no need to wrap double quotation marks. result += "\t"+ package +"\n"; // The part before the first space is the import identifier. identifier = package.substr(0, space_pos); } else { result += "\t\""+ package +"\"\n"; // The part after the last / is the import identifier. auto slash_pos = package.rfind("/"); if (slash_pos != string::npos) { identifier = package.substr(slash_pos+1); } } // Reserve these package names in case the collide with imported Thrift packages package_identifiers_set_.insert(identifier); package_identifiers_.emplace(package, identifier); } return result; } /** * Renders all the imports necessary for including another Thrift program. * If consts include the additional imports. */ string t_go_generator::render_includes(bool consts) { const vector& includes = program_->get_includes(); string result = ""; string unused_prot = ""; result += go_imports_begin(consts); result += render_included_programs(unused_prot); if (includes.size() > 0) { result += "\n"; } return result + go_imports_end() + unused_prot; } string t_go_generator::render_import_protection() { return string("var GoUnusedProtection__ int;\n\n"); } /** * Renders all the imports necessary to use the accelerated TBinaryProtocol */ string t_go_generator::render_fastbinary_includes() { return ""; } /** * Autogen'd comment. The different text is necessary due to * https://github.com/golang/go/issues/13560#issuecomment-288457920 */ string t_go_generator::go_autogen_comment() { return std::string() + "// Code generated by Thrift Compiler (" + THRIFT_VERSION + "). DO NOT EDIT.\n\n"; } /** * Prints standard thrift package */ string t_go_generator::go_package() { return string("package ") + package_name_ + "\n\n"; } /** * Render the beginning of the import statement. * If consts include the additional imports. */ string t_go_generator::go_imports_begin(bool consts) { std::vector system_packages; system_packages.push_back("bytes"); system_packages.push_back("context"); // If not writing constants, and there are enums, need extra imports. if (!consts && get_program()->get_enums().size() > 0) { system_packages.push_back("database/sql/driver"); } system_packages.push_back("errors"); system_packages.push_back("fmt"); system_packages.push_back("time"); // For the thrift import, always do rename import to make sure it's called thrift. system_packages.push_back("thrift \"" + gen_thrift_import_ + "\""); // validator import system_packages.push_back("strings"); system_packages.push_back("regexp"); return "import (\n" + render_system_packages(system_packages); } /** * End the import statement, include undscore-assignments * * These "_ =" prevent the go compiler complaining about unused imports. * This will have to do in lieu of more intelligent import statement construction */ string t_go_generator::go_imports_end() { string import_end = string( ")\n\n" "// (needed to ensure safety because of naive import list construction.)\n" "var _ = thrift.ZERO\n" "var _ = fmt.Printf\n" "var _ = errors.New\n" "var _ = context.Background\n" "var _ = time.Now\n" "var _ = bytes.Equal\n" "// (needed by validator.)\n" "var _ = strings.Contains\n" "var _ = regexp.MatchString\n\n"); return import_end; } /** * Closes the type files */ void t_go_generator::close_generator() { f_const_values_ << "}" << endl << endl; f_consts_ << f_const_values_.str(); // Close types and constants files f_consts_.close(); f_types_.close(); format_go_output(f_types_name_); format_go_output(f_consts_name_); } /** * Generates a typedef. * * @param ttypedef The type definition */ void t_go_generator::generate_typedef(t_typedef* ttypedef) { generate_go_docstring(f_types_, ttypedef); string new_type_name(publicize(ttypedef->get_symbolic())); string base_type(type_to_go_type(ttypedef->get_type())); if (base_type == new_type_name) { return; } f_types_ << "type " << new_type_name << " " << base_type << endl << endl; // Generate a convenience function that converts an instance of a type // (which may be a constant) into a pointer to an instance of a type. f_types_ << "func " << new_type_name << "Ptr(v " << new_type_name << ") *" << new_type_name << " { return &v }" << endl << endl; } /** * Generates code for an enumerated type. Done using a class to scope * the values. * * @param tenum The enumeration */ void t_go_generator::generate_enum(t_enum* tenum) { std::ostringstream to_string_mapping, from_string_mapping; std::string tenum_name(publicize(tenum->get_name())); generate_go_docstring(f_types_, tenum); f_types_ << "type " << tenum_name << " int64" << endl << "const (" << endl; to_string_mapping << indent() << "func (p " << tenum_name << ") String() string {" << endl; to_string_mapping << indent() << " switch p {" << endl; from_string_mapping << indent() << "func " << tenum_name << "FromString(s string) (" << tenum_name << ", error) {" << endl; from_string_mapping << indent() << " switch s {" << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; int value = -1; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { value = (*c_iter)->get_value(); string iter_std_name(escape_string((*c_iter)->get_name())); string iter_name((*c_iter)->get_name()); f_types_ << indent() << " " << tenum_name << "_" << iter_name << ' ' << tenum_name << " = " << value << endl; // Dictionaries to/from string names of enums to_string_mapping << indent() << " case " << tenum_name << "_" << iter_name << ": return \"" << iter_std_name << "\"" << endl; if (iter_std_name != escape_string(iter_name)) { from_string_mapping << indent() << " case \"" << iter_std_name << "\", \"" << escape_string(iter_name) << "\": return " << tenum_name << "_" << iter_name << ", nil " << endl; } else { from_string_mapping << indent() << " case \"" << iter_std_name << "\": return " << tenum_name << "_" << iter_name << ", nil " << endl; } } to_string_mapping << indent() << " }" << endl; to_string_mapping << indent() << " return \"\"" << endl; to_string_mapping << indent() << "}" << endl; from_string_mapping << indent() << " }" << endl; from_string_mapping << indent() << " return " << tenum_name << "(0)," << " fmt.Errorf(\"not a valid " << tenum_name << " string\")" << endl; from_string_mapping << indent() << "}" << endl; f_types_ << ")" << endl << endl << to_string_mapping.str() << endl << from_string_mapping.str() << endl << endl; // Generate a convenience function that converts an instance of an enum // (which may be a constant) into a pointer to an instance of that enum // type. f_types_ << "func " << tenum_name << "Ptr(v " << tenum_name << ") *" << tenum_name << " { return &v }" << endl << endl; // Generate MarshalText f_types_ << "func (p " << tenum_name << ") MarshalText() ([]byte, error) {" << endl; f_types_ << "return []byte(p.String()), nil" << endl; f_types_ << "}" << endl << endl; // Generate UnmarshalText f_types_ << "func (p *" << tenum_name << ") UnmarshalText(text []byte) error {" << endl; f_types_ << "q, err := " << tenum_name << "FromString(string(text))" << endl; f_types_ << "if (err != nil) {" << endl << "return err" << endl << "}" << endl; f_types_ << "*p = q" << endl; f_types_ << "return nil" << endl; f_types_ << "}" << endl << endl; // Generate Scan for sql.Scanner interface f_types_ << "func (p *" << tenum_name << ") Scan(value interface{}) error {" <get_type(); string name = publicize(tconst->get_name()); t_const_value* value = tconst->get_value(); if (type->is_enum() || (type->is_base_type() && ((t_base_type*)type)->get_base() != t_base_type::TYPE_UUID)) { indent(f_consts_) << "const " << name << " = " << render_const_value(type, value, name) << endl; } else { f_const_values_ << indent() << name << " = " << render_const_value(type, value, name) << endl << endl; f_consts_ << indent() << "var " << name << " " << type_to_go_type(type) << endl; } } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_go_generator::render_const_value(t_type* type, t_const_value* value, const string& name, bool opt) { string typedef_opt_ptr; string typedef_opt; if (type->is_typedef()) { typedef_opt = publicize(type_name(type)); typedef_opt_ptr = typedef_opt + "Ptr"; } type = get_true_type(type); std::ostringstream out; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); if (opt) { switch (tbase) { case t_base_type::TYPE_BOOL: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.BoolPtr"; } out << "("; out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.Int8Ptr"; } out << "("; out << value->get_integer(); break; case t_base_type::TYPE_I16: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.Int16Ptr"; } out << "("; out << value->get_integer(); break; case t_base_type::TYPE_I32: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.Int32Ptr"; } out << "("; out << value->get_integer(); break; case t_base_type::TYPE_I64: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.Int64Ptr"; } out << "("; out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.Float64Ptr"; } out << "("; if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; case t_base_type::TYPE_STRING: if (typedef_opt_ptr != "") { out << typedef_opt_ptr; } else { out << "thrift.StringPtr"; } out << "("; out << '"' + get_escaped_string(value) + '"'; break; case t_base_type::TYPE_UUID: if (typedef_opt_ptr != "") { out << typedef_opt_ptr << "(" << typedef_opt; } else { out << "thrift.TuuidPtr"; } out << "("; out << "thrift.Must(thrift.ParseTuuid(\"" + get_escaped_string(value) + "\"))"; if (typedef_opt_ptr != "") { out << ")"; } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } out << ")"; } else { switch (tbase) { case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "[]byte(\"" << get_escaped_string(value) << "\")"; } else { out << '"' << get_escaped_string(value) << '"'; } break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: if (opt) { out << "&(&struct{x int}{"; } out << value->get_integer(); if (opt) { out << "}).x"; } break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; case t_base_type::TYPE_UUID: if (typedef_opt != "") { out << typedef_opt << "("; } out << "thrift.Must(thrift.ParseTuuid(\"" + get_escaped_string(value) + "\"))"; if (typedef_opt != "") { out << ")"; } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } } else if (type->is_enum()) { if (opt) { if (typedef_opt_ptr != "") { out << typedef_opt_ptr << "("; } else { out << type_name(type) << "Ptr("; } } out << value->get_integer(); if (opt) { out << ")"; } } else if (type->is_struct() || type->is_xception()) { out << "&" << publicize(type_name(type)) << "{"; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; bool is_optional = false; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); is_optional = is_pointer_field(*f_iter); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } out << endl << indent() << publicize(v_iter->first->get_string()) << ": " << render_const_value(field_type, v_iter->second, name, is_optional) << "," << endl; } indent_down(); out << "}"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); out << "map[" << type_to_go_key_type(ktype) << "]" << type_to_go_type(vtype) << "{" << endl; indent_up(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << render_const_value(ktype, v_iter->first, name) << ": " << render_const_value(vtype, v_iter->second, name) << "," << endl; } indent_down(); out << indent() << "}"; } else if (type->is_list()) { t_type* etype = ((t_list*)type)->get_elem_type(); const vector& val = value->get_list(); out << "[]" << type_to_go_type(etype) << "{" << endl; indent_up(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << render_const_value(etype, *v_iter, name) << ", "; } indent_down(); out << indent() << "}"; } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); const vector& val = value->get_list(); out << "[]" << type_to_go_type(etype) << "{" << endl; indent_up(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent() << render_const_value(etype, *v_iter, name) << ", "; } indent_down(); out << indent() << "}"; } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out.str(); } /** * Generates a go struct */ void t_go_generator::generate_struct(t_struct* tstruct) { generate_go_struct(tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_go_generator::generate_xception(t_struct* txception) { generate_go_struct(txception, true); } /** * Generates a go struct */ void t_go_generator::generate_go_struct(t_struct* tstruct, bool is_exception) { generate_go_struct_definition(f_types_, tstruct, is_exception); // generate Validate function std::string tstruct_name(publicize(tstruct->get_name(), false)); f_types_ << "func (p *" << tstruct_name << ") Validate() error {" << endl; indent_up(); go_validator_generator(this).generate_struct_validator(f_types_, tstruct); f_types_ << indent() << "return nil" << endl; indent_down(); f_types_ << "}" << endl; } void t_go_generator::get_publicized_name_and_def_value(t_field* tfield, string* OUT_pub_name, t_const_value** OUT_def_value) const { const string base_field_name = tfield->get_name(); const string escaped_field_name = escape_string(base_field_name); *OUT_pub_name = publicize(escaped_field_name); *OUT_def_value = tfield->get_value(); } void t_go_generator::generate_go_struct_initializer(ostream& out, t_struct* tstruct, bool is_args_or_result) { out << publicize(type_name(tstruct), is_args_or_result) << "{"; const vector& members = tstruct->get_members(); for (auto member : members) { bool pointer_field = is_pointer_field(member); string publicized_name; t_const_value* def_value; get_publicized_name_and_def_value(member, &publicized_name, &def_value); if (!pointer_field && def_value != nullptr && !omit_initialization(member)) { out << endl << indent() << publicized_name << ": " << render_field_initial_value(member, member->get_name(), pointer_field) << "," << endl; } } out << "}" << endl; } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_go_generator::generate_go_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool is_result, bool is_args) { const vector& members = tstruct->get_members(); const vector& sorted_members = tstruct->get_sorted_members(); vector::const_iterator m_iter; std::string tstruct_name(publicize(tstruct->get_name(), is_args || is_result)); generate_go_docstring(out, tstruct); out << indent() << "type " << tstruct_name << " struct {" << endl; /* Here we generate the structure specification for the fastbinary codec. These specifications have the following structure: thrift_spec -> tuple of item_spec item_spec -> nil | (tag, type_enum, name, spec_args, default) tag -> integer type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ... name -> string_literal default -> nil # Handled by __init__ spec_args -> nil # For simple types | (type_enum, spec_args) # Value type for list/set | (type_enum, spec_args, type_enum, spec_args) # Key and value for map | (class_name, spec_args_ptr) # For struct/exception class_name -> identifier # Basically a pointer to the class spec_args_ptr -> expression # just class_name.spec_args TODO(dreiss): Consider making this work for structs with negative tags. */ // TODO(dreiss): Look into generating an empty tuple instead of nil // for structures with no members. // TODO(dreiss): Test encoding of structs where some inner structs // don't have thrift_spec. indent_up(); int num_setable = 0; if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) { int sorted_keys_pos = 0; for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) { // Set field to optional if field is union, this is so we can get a // pointer to the field. if (tstruct->is_union()) (*m_iter)->set_req(t_field::T_OPTIONAL); if (sorted_keys_pos != (*m_iter)->get_key()) { int first_unused = (std::max)(1, sorted_keys_pos++); while (sorted_keys_pos != (*m_iter)->get_key()) { ++sorted_keys_pos; } int last_unused = sorted_keys_pos - 1; if (first_unused < last_unused) { indent(out) << "// unused fields # " << first_unused << " to " << last_unused << endl; } else if (first_unused == last_unused) { indent(out) << "// unused field # " << first_unused << endl; } } t_type* fieldType = (*m_iter)->get_type(); string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter)); maptags; tags["db"]=escape_string((*m_iter)->get_name()); // Only add the `omitempty` tag if this field is optional and has no default value. // Otherwise a proper value like `false` for a bool field will be ommitted from // the JSON output since Go Marshal won't output `zero values`. bool has_default = (*m_iter)->get_value(); bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; if (is_optional && !has_default) { tags["json"]=escape_string((*m_iter)->get_name())+",omitempty"; } else { tags["json"]=escape_string((*m_iter)->get_name()); } // Check for user defined tags and them if there are any. User defined tags // can override the above db and json tags. std::map>::iterator it = (*m_iter)->annotations_.find("go.tag"); if (it != (*m_iter)->annotations_.end()) { parse_go_tags(&tags, it->second.back()); } string gotag; for (auto it = tags.begin(); it != tags.end(); ++it) { gotag += it->first + ":\"" + it->second + "\" "; } // Trailing whitespace gotag.resize(gotag.size()-1); indent(out) << publicize((*m_iter)->get_name()) << " " << goType << " `thrift:\"" << escape_string((*m_iter)->get_name()) << "," << sorted_keys_pos; if ((*m_iter)->get_req() == t_field::T_REQUIRED) { out << ",required"; } out << "\" " << gotag << "`" << endl; sorted_keys_pos++; } } else { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { // This fills in default values, as opposed to nulls out << indent() << publicize((*m_iter)->get_name()) << " " << type_to_go_type((*m_iter)->get_type()) << endl; } } indent_down(); out << indent() << "}" << endl << endl; out << indent() << "func New" << tstruct_name << "() *" << tstruct_name << " {" << endl; out << indent() << " return &"; generate_go_struct_initializer(out, tstruct, is_result || is_args); out << indent() << "}" << endl << endl; // Default values for optional fields for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string publicized_name; t_const_value* def_value; get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value); t_type* fieldType = (*m_iter)->get_type(); string goType = type_to_go_type_with_opt(fieldType, false); string def_var_name = tstruct_name + "_" + publicized_name + "_DEFAULT"; if ((*m_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*m_iter)) { out << indent() << "var " << def_var_name << " " << goType; if (def_value != nullptr) { out << " = " << render_const_value(fieldType, def_value, (*m_iter)->get_name()); } out << endl; } // num_setable is used for deciding if Count* methods will be generated for union fields. // This applies to all nullable fields including slices (used for set, list and binary) and maps, not just pointers. t_type* type = fieldType->get_true_type(); if (is_pointer_field(*m_iter)|| type->is_map() || type->is_set() || type->is_list() || type->is_binary()) { num_setable += 1; } if (is_pointer_field(*m_iter)) { string goOptType = type_to_go_type_with_opt(fieldType, true); string maybepointer = goOptType != goType ? "*" : ""; out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() " << goType << " {" << endl; out << indent() << " if !p.IsSet" << publicized_name << "() {" << endl; out << indent() << " return " << def_var_name << endl; out << indent() << " }" << endl; out << indent() << "return " << maybepointer << "p." << publicized_name << endl; out << indent() << "}" << endl; } else { out << endl; out << indent() << "func (p *" << tstruct_name << ") Get" << publicized_name << "() " << goType << " {" << endl; out << indent() << " return p." << publicized_name << endl; out << indent() << "}" << endl; } } if (tstruct->is_union() && num_setable > 0) { generate_countsetfields_helper(out, tstruct, tstruct_name, is_result); } generate_isset_helpers(out, tstruct, tstruct_name, is_result); generate_go_struct_reader(out, tstruct, tstruct_name, is_result); generate_go_struct_writer(out, tstruct, tstruct_name, is_result, num_setable > 0); if (!is_result && !is_args) { generate_go_struct_equals(out, tstruct, tstruct_name); } out << indent() << "func (p *" << tstruct_name << ") String() string {" << endl; out << indent() << " if p == nil {" << endl; out << indent() << " return \"\"" << endl; out << indent() << " }" << endl; out << indent() << " return fmt.Sprintf(\"" << escape_string(tstruct_name) << "(%+v)\", *p)" << endl; out << indent() << "}" << endl << endl; if (is_exception) { out << indent() << "func (p *" << tstruct_name << ") Error() string {" << endl; indent_up(); out << indent() << "return p.String()" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "func (" << tstruct_name << ") TExceptionType() thrift.TExceptionType {" << endl; indent_up(); out << indent() << "return thrift.TExceptionTypeCompiled" << endl; indent_down(); out << indent() << "}" << endl << endl; out << indent() << "var _ thrift.TException = (*" << tstruct_name << ")(nil)" << endl << endl; } } /** * Generates the IsSet helper methods for a struct */ void t_go_generator::generate_isset_helpers(ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result) { (void)is_result; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; const string escaped_tstruct_name(escape_string(tstruct->get_name())); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { const string field_name(publicize(escape_string((*f_iter)->get_name()))); if ((*f_iter)->get_req() == t_field::T_OPTIONAL || is_pointer_field(*f_iter)) { out << indent() << "func (p *" << tstruct_name << ") IsSet" << field_name << "() bool {" << endl; indent_up(); t_type* ttype = (*f_iter)->get_type()->get_true_type(); bool is_byteslice = ttype->is_binary(); bool compare_to_nil_only = ttype->is_set() || ttype->is_list() || ttype->is_map() || (is_byteslice && !(*f_iter)->get_value()); if (is_pointer_field(*f_iter) || compare_to_nil_only) { out << indent() << "return p." << field_name << " != nil" << endl; } else { string def_var_name = tstruct_name + "_" + field_name + "_DEFAULT"; if (is_byteslice) { out << indent() << "return !bytes.Equal(p." << field_name << ", " << def_var_name << ")" << endl; } else { out << indent() << "return p." << field_name << " != " << def_var_name << endl; } } indent_down(); out << indent() << "}" << endl << endl; } } } /** * Generates the CountSetFields helper method for a struct */ void t_go_generator::generate_countsetfields_helper(ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result) { (void)is_result; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; const string escaped_tstruct_name(escape_string(tstruct->get_name())); out << indent() << "func (p *" << tstruct_name << ") CountSetFields" << tstruct_name << "() int {" << endl; indent_up(); out << indent() << "count := 0" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) continue; t_type* type = (*f_iter)->get_type()->get_true_type(); if (!(is_pointer_field(*f_iter) || type->is_map() || type->is_set() || type->is_list() || type->is_binary())) continue; const string field_name(publicize(escape_string((*f_iter)->get_name()))); out << indent() << "if (p.IsSet" << field_name << "()) {" << endl; indent_up(); out << indent() << "count++" << endl; indent_down(); out << indent() << "}" << endl; } out << indent() << "return count" << endl << endl; indent_down(); out << indent() << "}" << endl << endl; } /** * Generates the read method for a struct */ void t_go_generator::generate_go_struct_reader(ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result) { (void)is_result; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; string escaped_tstruct_name(escape_string(tstruct->get_name())); out << indent() << "func (p *" << tstruct_name << ") " << read_method_name_ << "(ctx context.Context, iprot thrift.TProtocol) error {" << endl; indent_up(); out << indent() << "if _, err := iprot.ReadStructBegin(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(\"%T read error: \", p), err)" << endl; out << indent() << "}" << endl << endl; // Required variables does not have IsSet functions, so we need tmp vars to check them. for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { const string field_name(publicize(escape_string((*f_iter)->get_name()))); indent(out) << "var isset" << field_name << " bool = false;" << endl; } } out << endl; // Loop over reading in fields indent(out) << "for {" << endl; indent_up(); // Read beginning field marker out << indent() << "_, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx)" << endl; out << indent() << "if err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(" "\"%T field %d read error: \", p, fieldId), err)" << endl; out << indent() << "}" << endl; // Check for field STOP marker and break out << indent() << "if fieldTypeId == thrift.STOP { break; }" << endl; string thriftFieldTypeId; // Generate deserialization code for known cases int32_t field_id = -1; // Switch statement on the field we are reading, false if no fields present bool have_switch = !fields.empty(); if (have_switch) { indent(out) << "switch fieldId {" << endl; } // All the fields we know for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { field_id = (*f_iter)->get_key(); // if negative id, ensure we generate a valid method name string field_method_prefix("ReadField"); int32_t field_method_suffix = field_id; if (field_method_suffix < 0) { field_method_prefix += "_"; field_method_suffix *= -1; } out << indent() << "case " << field_id << ":" << endl; indent_up(); thriftFieldTypeId = type_to_enum((*f_iter)->get_type()); if (thriftFieldTypeId == "thrift.BINARY") { thriftFieldTypeId = "thrift.STRING"; } out << indent() << "if fieldTypeId == " << thriftFieldTypeId << " {" << endl; out << indent() << " if err := p." << field_method_prefix << field_method_suffix << "(ctx, iprot); err != nil {" << endl; out << indent() << " return err" << endl; out << indent() << " }" << endl; // Mark required field as read if ((*f_iter)->get_req() == t_field::T_REQUIRED) { const string field_name(publicize(escape_string((*f_iter)->get_name()))); out << indent() << " isset" << field_name << " = true" << endl; } out << indent() << "} else {" << endl; out << indent() << " if err := iprot.Skip(ctx, fieldTypeId); err != nil {" << endl; out << indent() << " return err" << endl; out << indent() << " }" << endl; out << indent() << "}" << endl; indent_down(); } // Begin switch default case if (have_switch) { out << indent() << "default:" << endl; indent_up(); } // Skip unknown fields in either case out << indent() << "if err := iprot.Skip(ctx, fieldTypeId); err != nil {" << endl; out << indent() << " return err" << endl; out << indent() << "}" << endl; // End switch default case if (have_switch) { indent_down(); out << indent() << "}" << endl; } // Read field end marker out << indent() << "if err := iprot.ReadFieldEnd(ctx); err != nil {" << endl; out << indent() << " return err" << endl; out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "if err := iprot.ReadStructEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(" "\"%T read struct end error: \", p), err)" << endl; out << indent() << "}" << endl; // Return error if any required fields are missing. for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { const string field_name(publicize(escape_string((*f_iter)->get_name()))); out << indent() << "if !isset" << field_name << "{" << endl; out << indent() << " return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, " "fmt.Errorf(\"Required field " << field_name << " is not set\"));" << endl; out << indent() << "}" << endl; } } out << indent() << "return nil" << endl; indent_down(); out << indent() << "}" << endl << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string field_type_name(publicize((*f_iter)->get_type()->get_name())); string field_name(publicize((*f_iter)->get_name())); string field_method_prefix("ReadField"); int32_t field_id = (*f_iter)->get_key(); int32_t field_method_suffix = field_id; if (field_method_suffix < 0) { field_method_prefix += "_"; field_method_suffix *= -1; } out << indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_method_suffix << "(ctx context.Context, iprot thrift.TProtocol) error {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, false, "p."); indent_down(); out << indent() << " return nil" << endl; out << indent() << "}" << endl << endl; } } void t_go_generator::generate_go_struct_writer(ostream& out, t_struct* tstruct, const string& tstruct_name, bool is_result, bool uses_countsetfields) { (void)is_result; string name(tstruct->get_name()); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent(out) << "func (p *" << tstruct_name << ") " << write_method_name_ << "(ctx context.Context, oprot thrift.TProtocol) error {" << endl; indent_up(); if (tstruct->is_union() && uses_countsetfields) { std::string tstruct_name(publicize(tstruct->get_name())); out << indent() << "if c := p.CountSetFields" << tstruct_name << "(); c != 1 {" << endl << indent() << " return fmt.Errorf(\"%T write union: exactly one field must be set (%d set)\", p, c)" << endl << indent() << "}" << endl; } out << indent() << "if err := oprot.WriteStructBegin(ctx, \"" << name << "\"); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(" "\"%T write struct begin error: \", p), err) }" << endl; string field_name; string escape_field_name; // t_const_value* field_default_value; t_field::e_req field_required; int32_t field_id = -1; out << indent() << "if p != nil {" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string field_method_prefix("writeField"); field_name = (*f_iter)->get_name(); escape_field_name = escape_string(field_name); field_id = (*f_iter)->get_key(); int32_t field_method_suffix = field_id; if (field_method_suffix < 0) { field_method_prefix += "_"; field_method_suffix *= -1; } out << indent() << "if err := p." << field_method_prefix << field_method_suffix << "(ctx, oprot); err != nil { return err }" << endl; } indent_down(); out << indent() << "}" << endl; // Write the struct map out << indent() << "if err := oprot.WriteFieldStop(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"write field stop error: \", err) }" << endl; out << indent() << "if err := oprot.WriteStructEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"write struct stop error: \", err) }" << endl; out << indent() << "return nil" << endl; indent_down(); out << indent() << "}" << endl << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string field_method_prefix("writeField"); field_id = (*f_iter)->get_key(); field_name = (*f_iter)->get_name(); escape_field_name = escape_string(field_name); // field_default_value = (*f_iter)->get_value(); field_required = (*f_iter)->get_req(); int32_t field_method_suffix = field_id; if (field_method_suffix < 0) { field_method_prefix += "_"; field_method_suffix *= -1; } out << indent() << "func (p *" << tstruct_name << ") " << field_method_prefix << field_method_suffix << "(ctx context.Context, oprot thrift.TProtocol) (err error) {" << endl; indent_up(); if (field_required == t_field::T_OPTIONAL) { out << indent() << "if p.IsSet" << publicize(field_name) << "() {" << endl; indent_up(); } out << indent() << "if err := oprot.WriteFieldBegin(ctx, \"" << escape_field_name << "\", " << type_to_enum((*f_iter)->get_type()) << ", " << field_id << "); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(\"%T write field begin error " << field_id << ":" << escape_field_name << ": \", p), err) }" << endl; // Write field contents generate_serialize_field(out, *f_iter, "p."); // Write field closer out << indent() << "if err := oprot.WriteFieldEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(\"%T write field end error " << field_id << ":" << escape_field_name << ": \", p), err) }" << endl; if (field_required == t_field::T_OPTIONAL) { indent_down(); out << indent() << "}" << endl; } indent_down(); out << indent() << " return err" << endl; out << indent() << "}" << endl << endl; } } void t_go_generator::generate_go_struct_equals(ostream& out, t_struct* tstruct, const string& tstruct_name) { string name(tstruct->get_name()); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent(out) << "func (p *" << tstruct_name << ") " << equals_method_name_ << "(other *" << tstruct_name << ") bool {" << endl; indent_up(); string field_name; string publicize_field_name; out << indent() << "if p == other {" << endl; indent_up(); out << indent() << "return true" << endl; indent_down(); out << indent() << "} else if p == nil || other == nil {" << endl; indent_up(); out << indent() << "return false" << endl; indent_down(); out << indent() << "}" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { field_name = (*f_iter)->get_name(); t_type* field_type = (*f_iter)->get_type(); publicize_field_name = publicize(field_name); string goType = type_to_go_type_with_opt(field_type, is_pointer_field(*f_iter)); string tgt = "p." + publicize_field_name; string src = "other." + publicize_field_name; t_type* ttype = field_type->get_true_type(); // Compare field contents if (is_pointer_field(*f_iter) && (ttype->is_base_type() || ttype->is_enum() || ttype->is_container())) { string tgtv = "(*" + tgt + ")"; string srcv = "(*" + src + ")"; out << indent() << "if " << tgt << " != " << src << " {" << endl; indent_up(); out << indent() << "if " << tgt << " == nil || " << src << " == nil {" << endl; indent_up(); out << indent() << "return false" << endl; indent_down(); out << indent() << "}" << endl; generate_go_equals(out, field_type, tgtv, srcv); indent_down(); out << indent() << "}" << endl; } else { generate_go_equals(out, field_type, tgt, src); } } out << indent() << "return true" << endl; indent_down(); out << indent() << "}" << endl << endl; } /** * Generates a thrift service. * * @param tservice The service definition */ void t_go_generator::generate_service(t_service* tservice) { string test_suffix("_test"); string filename = lowercase(service_name_); string f_service_name; generate_service_interface(tservice); generate_service_client(tservice); generate_service_server(tservice); generate_service_helpers(tservice); if(!skip_remote_) { generate_service_remote(tservice); } f_types_ << endl; } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_go_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; f_types_ << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_go_struct_definition(f_types_, ts, false, false, true); generate_go_function_helpers(*f_iter); } } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_go_generator::generate_go_function_helpers(t_function* tfunction) { if (!tfunction->is_oneway()) { t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); success.set_req(t_field::T_OPTIONAL); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* f = *f_iter; f->set_req(t_field::T_OPTIONAL); result.append(f); } generate_go_struct_definition(f_types_, &result, false, true); } } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_go_generator::generate_service_interface(t_service* tservice) { string extends = ""; string extends_if = ""; string serviceName(publicize(tservice->get_name())); string interfaceName = serviceName; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); size_t index = extends.rfind("."); if (index != string::npos) { extends_if = "\n" + indent() + " " + extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "\n"; } else { extends_if = "\n" + indent() + publicize(extends) + "\n"; } } f_types_ << indent() << "type " << interfaceName << " interface {" << extends_if; indent_up(); generate_go_docstring(f_types_, tservice); vector functions = tservice->get_functions(); if (!functions.empty()) { f_types_ << endl; vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_go_docstring(f_types_, (*f_iter)); f_types_ << indent() << function_signature_if(*f_iter, "", true) << endl; } } indent_down(); f_types_ << indent() << "}" << endl << endl; } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_go_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_field = ""; string extends_client = ""; string extends_client_new = ""; string serviceName(publicize(tservice->get_name())); if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); size_t index = extends.rfind("."); if (index != string::npos) { extends_client = extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "Client"; extends_client_new = extends.substr(0, index + 1) + "New" + publicize(extends.substr(index + 1)) + "Client"; } else { extends_client = publicize(extends) + "Client"; extends_client_new = "New" + extends_client; } } extends_field = extends_client.substr(extends_client.find(".") + 1); generate_go_docstring(f_types_, tservice); f_types_ << indent() << "type " << serviceName << "Client struct {" << endl; indent_up(); if (!extends_client.empty()) { f_types_ << indent() << "*" << extends_client << endl; } else { f_types_ << indent() << "c thrift.TClient" << endl; f_types_ << indent() << "meta thrift.ResponseMeta" << endl; } indent_down(); f_types_ << indent() << "}" << endl << endl; // Legacy constructor function f_types_ << indent() << "func New" << serviceName << "ClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *" << serviceName << "Client {" << endl; indent_up(); f_types_ << indent() << "return &" << serviceName << "Client"; if (!extends.empty()) { f_types_ << "{" << extends_field << ": " << extends_client_new << "Factory(t, f)}"; } else { indent_up(); f_types_ << "{" << endl; f_types_ << indent() << "c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t))," << endl; indent_down(); f_types_ << indent() << "}" << endl; } indent_down(); f_types_ << indent() << "}" << endl << endl; // Legacy constructor function with custom input & output protocols f_types_ << indent() << "func New" << serviceName << "ClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *" << serviceName << "Client {" << endl; indent_up(); f_types_ << indent() << "return &" << serviceName << "Client"; if (!extends.empty()) { f_types_ << "{" << extends_field << ": " << extends_client_new << "Protocol(t, iprot, oprot)}" << endl; } else { indent_up(); f_types_ << "{" << endl; f_types_ << indent() << "c: thrift.NewTStandardClient(iprot, oprot)," << endl; indent_down(); f_types_ << indent() << "}" << endl; } indent_down(); f_types_ << indent() << "}" << endl << endl; // Constructor function f_types_ << indent() << "func New" << serviceName << "Client(c thrift.TClient) *" << serviceName << "Client {" << endl; indent_up(); f_types_ << indent() << "return &" << serviceName << "Client{" << endl; indent_up(); if (!extends.empty()) { f_types_ << indent() << extends_field << ": " << extends_client_new << "(c)," << endl; } else { f_types_ << indent() << "c: c," << endl; } indent_down(); f_types_ << indent() << "}" << endl; indent_down(); f_types_ << indent() << "}" << endl << endl; if (extends.empty()) { f_types_ << indent() << "func (p *" << serviceName << "Client) Client_() thrift.TClient {" << endl; indent_up(); f_types_ << indent() << "return p.c" << endl; indent_down(); f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << serviceName << "Client) LastResponseMeta_() thrift.ResponseMeta {" << endl; indent_up(); f_types_ << indent() << "return p.meta" << endl; indent_down(); f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << serviceName << "Client) SetLastResponseMeta_(meta thrift.ResponseMeta) {" << endl; indent_up(); f_types_ << indent() << "p.meta = meta" << endl; indent_down(); f_types_ << indent() << "}" << endl << endl; } // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = publicize((*f_iter)->get_name()); // Open function generate_go_docstring(f_types_, (*f_iter)); f_types_ << indent() << "func (p *" << serviceName << "Client) " << function_signature_if(*f_iter, "", true) << " {" << endl; indent_up(); std::string method = (*f_iter)->get_name(); std::string argsType = publicize(method + "_args", true); std::string argsName = tmp("_args"); f_types_ << indent() << "var " << argsName << " " << argsType << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_types_ << indent() << argsName << "." << publicize((*fld_iter)->get_name()) << " = " << variable_name_to_go_name((*fld_iter)->get_name()) << endl; } if (!(*f_iter)->is_oneway()) { std::string metaName = tmp("_meta"); std::string resultName = tmp("_result"); std::string resultType = publicize(method + "_result", true); f_types_ << indent() << "var " << resultName << " " << resultType << endl; f_types_ << indent() << "var " << metaName << " thrift.ResponseMeta" << endl; f_types_ << indent() << metaName << ", _err = p.Client_().Call(ctx, \"" << method << "\", &" << argsName << ", &" << resultName << ")" << endl; f_types_ << indent() << "p.SetLastResponseMeta_(" << metaName << ")" << endl; f_types_ << indent() << "if _err != nil {" << endl; indent_up(); f_types_ << indent() << "return" << endl; indent_down(); f_types_ << indent() << "}" << endl; t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; if (!xceptions.empty()) { f_types_ << indent() << "switch {" << endl; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { const std::string pubname = publicize((*x_iter)->get_name()); const std::string field = resultName + "." + pubname; f_types_ << indent() << "case " << field << "!= nil:" << endl; indent_up(); if (!(*f_iter)->get_returntype()->is_void()) { f_types_ << indent() << "return _r, " << field << endl; } else { f_types_ << indent() << "return "<< field << endl; } indent_down(); } f_types_ << indent() << "}" << endl << endl; } if ((*f_iter)->get_returntype()->is_struct()) { // Check if the result is nil, which likely means we have a new // exception added but unknown to the client yet // (e.g. client hasn't updated the thrift file). // Sadly this check can only be reliable done when the return type is a // struct in go. std::string retName = tmp("_ret"); f_types_ << indent() << "if " << retName << " := " << resultName << ".GetSuccess(); " << retName << " != nil {" << endl; indent_up(); f_types_ << indent() << "return " << retName << ", nil" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "return nil, " << "thrift.NewTApplicationException(thrift.MISSING_RESULT, \"" << method << " failed: unknown result\")" << endl; } else if (!(*f_iter)->get_returntype()->is_void()) { f_types_ << indent() << "return " << resultName << ".GetSuccess(), nil" << endl; } else { f_types_ << indent() << "return nil" << endl; } } else { // Since we don't have response meta for oneway calls, overwrite it with // an empty one to avoid users getting the meta from last call and // mistaken it as from the oneway call. f_types_ << indent() << "p.SetLastResponseMeta_(thrift.ResponseMeta{})" << endl; // TODO: would be nice to not to duplicate the call generation f_types_ << indent() << "if _, err := p.Client_().Call(ctx, \"" << method << "\", &" << argsName << ", nil); err != nil {" << endl; indent_up(); f_types_ << indent() << "return err" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "return nil" << endl; } indent_down(); f_types_ << "}" << endl << endl; } } /** * Generates a command line tool for making remote requests * * @param tservice The service to generate a remote for. */ void t_go_generator::generate_service_remote(t_service* tservice) { vector functions; std::unordered_map func_to_service; // collect all functions including inherited functions t_service* parent = tservice; while (parent != nullptr) { vector p_functions = parent->get_functions(); functions.insert(functions.end(), p_functions.begin(), p_functions.end()); // We need to maintain a map of functions names to the name of their parent. // This is because functions may come from a parent service, and if we need // to create the arguments struct (e.g. `NewParentServiceNameFuncNameArgs()`) // we need to make sure to specify the correct service name. for (vector::iterator f_iter = p_functions.begin(); f_iter != p_functions.end(); ++f_iter) { auto it = func_to_service.find((*f_iter)->get_name()); if (it == func_to_service.end()) { func_to_service.emplace((*f_iter)->get_name(), parent->get_name()); } } parent = parent->get_extends(); } // This file is not useful if there are no functions; don't generate it if (functions.size() == 0) { return; } string f_remote_dir = package_dir_ + "/" + underscore(service_name_) + "-remote"; MKDIR(f_remote_dir.c_str()); vector::iterator f_iter; string f_remote_name = f_remote_dir + "/" + underscore(service_name_) + "-remote.go"; ofstream_with_content_based_conditional_update f_remote; f_remote.open(f_remote_name.c_str()); string unused_protection; std::vector system_packages; system_packages.push_back("context"); system_packages.push_back("flag"); system_packages.push_back("fmt"); system_packages.push_back("math"); system_packages.push_back("net"); system_packages.push_back("net/url"); system_packages.push_back("os"); system_packages.push_back("strconv"); system_packages.push_back("strings"); // For the thrift import, always do rename import to make sure it's called thrift. system_packages.push_back("thrift \"" + gen_thrift_import_ + "\""); f_remote << go_autogen_comment(); f_remote << indent() << "package main" << endl << endl; f_remote << indent() << "import (" << endl; f_remote << render_system_packages(system_packages); f_remote << indent() << render_included_programs(unused_protection); f_remote << render_program_import(program_, unused_protection); f_remote << indent() << ")" << endl; f_remote << indent() << endl; f_remote << indent() << unused_protection; // filled in render_included_programs() f_remote << indent() << endl; f_remote << indent() << "func Usage() {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Usage of \", os.Args[0], \" " "[-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:\")" << endl; f_remote << indent() << " flag.PrintDefaults()" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"\\nFunctions:\")" << endl; string package_name_aliased = package_identifiers_[get_real_go_module(program_)]; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_remote << " fmt.Fprintln(os.Stderr, \" " << (*f_iter)->get_returntype()->get_name() << " " << (*f_iter)->get_name() << "("; t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); std::vector::size_type num_args = args.size(); bool first = true; for (std::vector::size_type i = 0; i < num_args; ++i) { if (first) { first = false; } else { f_remote << ", "; } f_remote << args[i]->get_type()->get_name() << " " << args[i]->get_name(); } f_remote << ")\")" << endl; } f_remote << indent() << " fmt.Fprintln(os.Stderr)" << endl; f_remote << indent() << " os.Exit(0)" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << endl; f_remote << indent() << "type httpHeaders map[string]string" << endl; f_remote << indent() << endl; f_remote << indent() << "func (h httpHeaders) String() string {" << endl; f_remote << indent() << " var m map[string]string = h" << endl; f_remote << indent() << " return fmt.Sprintf(\"%s\", m)" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << endl; f_remote << indent() << "func (h httpHeaders) Set(value string) error {" << endl; f_remote << indent() << " parts := strings.Split(value, \": \")" << endl; f_remote << indent() << " if len(parts) != 2 {" << endl; f_remote << indent() << " return fmt.Errorf(\"header should be of format 'Key: Value'\")" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " h[parts[0]] = parts[1]" << endl; f_remote << indent() << " return nil" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << endl; f_remote << indent() << "func main() {" << endl; indent_up(); f_remote << indent() << "flag.Usage = Usage" << endl; f_remote << indent() << "var host string" << endl; f_remote << indent() << "var port int" << endl; f_remote << indent() << "var protocol string" << endl; f_remote << indent() << "var urlString string" << endl; f_remote << indent() << "var framed bool" << endl; f_remote << indent() << "var useHttp bool" << endl; f_remote << indent() << "headers := make(httpHeaders)" << endl; f_remote << indent() << "var parsedUrl *url.URL" << endl; f_remote << indent() << "var trans thrift.TTransport" << endl; f_remote << indent() << "_ = strconv.Atoi" << endl; f_remote << indent() << "_ = math.Abs" << endl; f_remote << indent() << "flag.Usage = Usage" << endl; f_remote << indent() << "flag.StringVar(&host, \"h\", \"localhost\", \"Specify host and port\")" << endl; f_remote << indent() << "flag.IntVar(&port, \"p\", 9090, \"Specify port\")" << endl; f_remote << indent() << "flag.StringVar(&protocol, \"P\", \"binary\", \"" "Specify the protocol (binary, compact, simplejson, json)\")" << endl; f_remote << indent() << "flag.StringVar(&urlString, \"u\", \"\", \"Specify the url\")" << endl; f_remote << indent() << "flag.BoolVar(&framed, \"framed\", false, \"Use framed transport\")" << endl; f_remote << indent() << "flag.BoolVar(&useHttp, \"http\", false, \"Use http\")" << endl; f_remote << indent() << "flag.Var(headers, \"H\", \"Headers to set on the http(s) request (e.g. -H \\\"Key: Value\\\")\")" << endl; f_remote << indent() << "flag.Parse()" << endl; f_remote << indent() << endl; f_remote << indent() << "if len(urlString) > 0 {" << endl; f_remote << indent() << " var err error" << endl; f_remote << indent() << " parsedUrl, err = url.Parse(urlString)" << endl; f_remote << indent() << " if err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl; f_remote << indent() << " flag.Usage()" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " host = parsedUrl.Host" << endl; f_remote << indent() << " useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == \"http\" || parsedUrl.Scheme == \"https\"" << endl; f_remote << indent() << "} else if useHttp {" << endl; f_remote << indent() << " _, err := url.Parse(fmt.Sprint(\"http://\", host, \":\", port))" << endl; f_remote << indent() << " if err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Error parsing URL: \", err)" << endl; f_remote << indent() << " flag.Usage()" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << endl; f_remote << indent() << "cmd := flag.Arg(0)" << endl; f_remote << indent() << "var err error" << endl; f_remote << indent() << "var cfg *thrift.TConfiguration = nil" << endl; f_remote << indent() << "if useHttp {" << endl; f_remote << indent() << " trans, err = thrift.NewTHttpClient(parsedUrl.String())" << endl; f_remote << indent() << " if len(headers) > 0 {" << endl; f_remote << indent() << " httptrans := trans.(*thrift.THttpClient)" << endl; f_remote << indent() << " for key, value := range headers {" << endl; f_remote << indent() << " httptrans.SetHeader(key, value)" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << "} else {" << endl; f_remote << indent() << " portStr := fmt.Sprint(port)" << endl; f_remote << indent() << " if strings.Contains(host, \":\") {" << endl; f_remote << indent() << " host, portStr, err = net.SplitHostPort(host)" << endl; f_remote << indent() << " if err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"error with host:\", err)" << endl; f_remote << indent() << " os.Exit(1)" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " trans = thrift.NewTSocketConf(net.JoinHostPort(host, portStr), cfg)" << endl; f_remote << indent() << " if err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"error resolving address:\", err)" << endl; f_remote << indent() << " os.Exit(1)" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << " if framed {" << endl; f_remote << indent() << " trans = thrift.NewTFramedTransportConf(trans, cfg)" << endl; f_remote << indent() << " }" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "if err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Error creating transport\", err)" << endl; f_remote << indent() << " os.Exit(1)" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "defer trans.Close()" << endl; f_remote << indent() << "var protocolFactory thrift.TProtocolFactory" << endl; f_remote << indent() << "switch protocol {" << endl; f_remote << indent() << "case \"compact\":" << endl; f_remote << indent() << " protocolFactory = thrift.NewTCompactProtocolFactoryConf(cfg)" << endl; f_remote << indent() << " break" << endl; f_remote << indent() << "case \"simplejson\":" << endl; f_remote << indent() << " protocolFactory = thrift.NewTSimpleJSONProtocolFactoryConf(cfg)" << endl; f_remote << indent() << " break" << endl; f_remote << indent() << "case \"json\":" << endl; f_remote << indent() << " protocolFactory = thrift.NewTJSONProtocolFactory()" << endl; f_remote << indent() << " break" << endl; f_remote << indent() << "case \"binary\", \"\":" << endl; f_remote << indent() << " protocolFactory = thrift.NewTBinaryProtocolFactoryConf(cfg)" << endl; f_remote << indent() << " break" << endl; f_remote << indent() << "default:" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Invalid protocol specified: \", protocol)" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " os.Exit(1)" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "iprot := protocolFactory.GetProtocol(trans)" << endl; f_remote << indent() << "oprot := protocolFactory.GetProtocol(trans)" << endl; f_remote << indent() << "client := " << package_name_aliased << ".New" << publicize(service_name_) << "Client(thrift.NewTStandardClient(iprot, oprot))" << endl; f_remote << indent() << "if err := trans.Open(); err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Error opening socket to \", " "host, \":\", port, \" \", err)" << endl; f_remote << indent() << " os.Exit(1)" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << endl; f_remote << indent() << "switch cmd {" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); std::vector::size_type num_args = args.size(); string funcName((*f_iter)->get_name()); string pubName(publicize(funcName)); string argumentsName(publicize(funcName + "_args", true, func_to_service[funcName])); f_remote << indent() << "case \"" << escape_string(funcName) << "\":" << endl; indent_up(); f_remote << indent() << "if flag.NArg() - 1 != " << num_args << " {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"" << escape_string(pubName) << " requires " << num_args << " args\")" << endl; f_remote << indent() << " flag.Usage()" << endl; f_remote << indent() << "}" << endl; for (std::vector::size_type i = 0; i < num_args; ++i) { std::vector::size_type flagArg = i + 1; t_type* the_type(args[i]->get_type()); t_type* the_type2(get_true_type(the_type)); if (the_type2->is_enum()) { f_remote << indent() << "tmp" << i << ", err := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl; f_remote << indent() << "if err != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "argvalue" << i << " := " << package_name_aliased << "." << publicize(the_type->get_name()) << "(tmp" << i << ")" << endl; } else if (the_type2->is_base_type()) { t_base_type::t_base e = ((t_base_type*)the_type2)->get_base(); string err(tmp("err")); switch (e) { case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_STRING: if (the_type2->is_binary()) { f_remote << indent() << "argvalue" << i << " := []byte(flag.Arg(" << flagArg << "))" << endl; } else { f_remote << indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ")" << endl; } break; case t_base_type::TYPE_BOOL: f_remote << indent() << "argvalue" << i << " := flag.Arg(" << flagArg << ") == \"true\"" << endl; break; case t_base_type::TYPE_I8: f_remote << indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl; f_remote << indent() << "if " << err << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "argvalue" << i << " := int8(tmp" << i << ")" << endl; break; case t_base_type::TYPE_I16: f_remote << indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl; f_remote << indent() << "if " << err << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "argvalue" << i << " := int16(tmp" << i << ")" << endl; break; case t_base_type::TYPE_I32: f_remote << indent() << "tmp" << i << ", " << err << " := (strconv.Atoi(flag.Arg(" << flagArg << ")))" << endl; f_remote << indent() << "if " << err << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "argvalue" << i << " := int32(tmp" << i << ")" << endl; break; case t_base_type::TYPE_I64: f_remote << indent() << "argvalue" << i << ", " << err << " := (strconv.ParseInt(flag.Arg(" << flagArg << "), 10, 64))" << endl; f_remote << indent() << "if " << err << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; break; case t_base_type::TYPE_DOUBLE: f_remote << indent() << "argvalue" << i << ", " << err << " := (strconv.ParseFloat(flag.Arg(" << flagArg << "), 64))" << endl; f_remote << indent() << "if " << err << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; break; case t_base_type::TYPE_UUID: f_remote << indent() << "argvalue" << i << ", " << err << " := (thrift.ParseTuuid(flag.Arg(" << flagArg << ")))" << endl; f_remote << indent() << "if " << err << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; break; default: throw("Invalid base type in generate_service_remote"); } // f_remote << publicize(args[i]->get_name()) << "(strconv.Atoi(flag.Arg(" << flagArg << // ")))"; } else if (the_type2->is_struct()) { string arg(tmp("arg")); string mbTrans(tmp("mbTrans")); string err1(tmp("err")); string factory(tmp("factory")); string jsProt(tmp("jsProt")); string err2(tmp("err")); std::string tstruct_name(publicize(the_type->get_name())); std::string tstruct_module( module_name(the_type)); if(tstruct_module.empty()) { tstruct_module = package_name_aliased; } f_remote << indent() << arg << " := flag.Arg(" << flagArg << ")" << endl; f_remote << indent() << mbTrans << " := thrift.NewTMemoryBufferLen(len(" << arg << "))" << endl; f_remote << indent() << "defer " << mbTrans << ".Close()" << endl; f_remote << indent() << "_, " << err1 << " := " << mbTrans << ".WriteString(" << arg << ")" << endl; f_remote << indent() << "if " << err1 << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl; f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl; f_remote << indent() << "argvalue" << i << " := " << tstruct_module << ".New" << tstruct_name << "()" << endl; f_remote << indent() << err2 << " := argvalue" << i << "." << read_method_name_ << "(context.Background(), " << jsProt << ")" << endl; f_remote << indent() << "if " << err2 << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; } else if (the_type2->is_container() || the_type2->is_xception()) { string arg(tmp("arg")); string mbTrans(tmp("mbTrans")); string err1(tmp("err")); string factory(tmp("factory")); string jsProt(tmp("jsProt")); string err2(tmp("err")); std::string argName(publicize(args[i]->get_name())); f_remote << indent() << arg << " := flag.Arg(" << flagArg << ")" << endl; f_remote << indent() << mbTrans << " := thrift.NewTMemoryBufferLen(len(" << arg << "))" << endl; f_remote << indent() << "defer " << mbTrans << ".Close()" << endl; f_remote << indent() << "_, " << err1 << " := " << mbTrans << ".WriteString(" << arg << ")" << endl; f_remote << indent() << "if " << err1 << " != nil { " << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl; f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl; f_remote << indent() << "containerStruct" << i << " := " << package_name_aliased << ".New" << argumentsName << "()" << endl; f_remote << indent() << err2 << " := containerStruct" << i << ".ReadField" << (i + 1) << "(context.Background(), " << jsProt << ")" << endl; f_remote << indent() << "if " << err2 << " != nil {" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; f_remote << indent() << "argvalue" << i << " := containerStruct" << i << "." << argName << endl; } else { throw("Invalid argument type in generate_service_remote"); } if (the_type->is_typedef()) { std::string typedef_module(module_name(the_type)); if(typedef_module.empty()) { typedef_module = package_name_aliased; } f_remote << indent() << "value" << i << " := " << typedef_module << "." << publicize(the_type->get_name()) << "(argvalue" << i << ")" << endl; } else { f_remote << indent() << "value" << i << " := argvalue" << i << endl; } } f_remote << indent() << "fmt.Print(client." << pubName << "("; bool argFirst = true; f_remote << "context.Background()"; for (std::vector::size_type i = 0; i < num_args; ++i) { if (argFirst) { argFirst = false; f_remote << ", "; } else { f_remote << ", "; } if (args[i]->get_type()->is_enum()) { f_remote << "value" << i; } else if (args[i]->get_type()->is_base_type()) { t_base_type::t_base e = ((t_base_type*)(args[i]->get_type()))->get_base(); switch (e) { case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_STRING: case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: case t_base_type::TYPE_UUID: f_remote << "value" << i; break; default: throw("Invalid base type in generate_service_remote"); } // f_remote << publicize(args[i]->get_name()) << "(strconv.Atoi(flag.Arg(" << flagArg << // ")))"; } else { f_remote << "value" << i; } } f_remote << "))" << endl; f_remote << indent() << "fmt.Print(\"\\n\")" << endl; f_remote << indent() << "break" << endl; indent_down(); } f_remote << indent() << "case \"\":" << endl; f_remote << indent() << " Usage()" << endl; f_remote << indent() << " break" << endl; f_remote << indent() << "default:" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Invalid function \", cmd)" << endl; f_remote << indent() << "}" << endl; indent_down(); f_remote << indent() << "}" << endl; // Close service file f_remote.close(); format_go_output(f_remote_name); #ifndef _MSC_VER // Make file executable, love that bitwise OR action chmod(f_remote_name.c_str(), S_IRUSR | S_IWUSR | S_IXUSR #ifndef _WIN32 | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH #endif ); #endif } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_go_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; string extends_processor_new = ""; string serviceName(publicize(tservice->get_name())); if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); size_t index = extends.rfind("."); if (index != string::npos) { extends_processor = extends.substr(0, index + 1) + publicize(extends.substr(index + 1)) + "Processor"; extends_processor_new = extends.substr(0, index + 1) + "New" + publicize(extends.substr(index + 1)) + "Processor"; } else { extends_processor = publicize(extends) + "Processor"; extends_processor_new = "New" + extends_processor; } } string pServiceName(privatize(tservice->get_name())); // Generate the header portion string self(tmp("self")); if (extends_processor.empty()) { f_types_ << indent() << "type " << serviceName << "Processor struct {" << endl; f_types_ << indent() << " processorMap map[string]thrift.TProcessorFunction" << endl; f_types_ << indent() << " handler " << serviceName << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << serviceName << "Processor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {" << endl; f_types_ << indent() << " p.processorMap[key] = processor" << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << serviceName << "Processor) GetProcessorFunction(key string) " "(processor thrift.TProcessorFunction, ok bool) {" << endl; f_types_ << indent() << " processor, ok = p.processorMap[key]" << endl; f_types_ << indent() << " return processor, ok" << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << serviceName << "Processor) ProcessorMap() map[string]thrift.TProcessorFunction {" << endl; f_types_ << indent() << " return p.processorMap" << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func New" << serviceName << "Processor(handler " << serviceName << ") *" << serviceName << "Processor {" << endl << endl; f_types_ << indent() << " " << self << " := &" << serviceName << "Processor{handler:handler, processorMap:make(map[string]thrift.TProcessorFunction)}" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string escapedFuncName(escape_string((*f_iter)->get_name())); f_types_ << indent() << " " << self << ".processorMap[\"" << escapedFuncName << "\"] = &" << pServiceName << "Processor" << publicize((*f_iter)->get_name()) << "{handler:handler}" << endl; } string x(tmp("x")); f_types_ << indent() << "return " << self << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << serviceName << "Processor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err " "thrift.TException) {" << endl; f_types_ << indent() << " name, _, seqId, err2 := iprot.ReadMessageBegin(ctx)" << endl; f_types_ << indent() << " if err2 != nil { return false, thrift.WrapTException(err2) }" << endl; f_types_ << indent() << " if processor, ok := p.GetProcessorFunction(name); ok {" << endl; f_types_ << indent() << " return processor.Process(ctx, seqId, iprot, oprot)" << endl; f_types_ << indent() << " }" << endl; f_types_ << indent() << " iprot.Skip(ctx, thrift.STRUCT)" << endl; f_types_ << indent() << " iprot.ReadMessageEnd(ctx)" << endl; f_types_ << indent() << " " << x << " := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, \"Unknown function " "\" + name)" << endl; f_types_ << indent() << " oprot.WriteMessageBegin(ctx, name, thrift.EXCEPTION, seqId)" << endl; f_types_ << indent() << " " << x << ".Write(ctx, oprot)" << endl; f_types_ << indent() << " oprot.WriteMessageEnd(ctx)" << endl; f_types_ << indent() << " oprot.Flush(ctx)" << endl; f_types_ << indent() << " return false, " << x << endl; f_types_ << indent() << "" << endl; f_types_ << indent() << "}" << endl << endl; } else { f_types_ << indent() << "type " << serviceName << "Processor struct {" << endl; f_types_ << indent() << " *" << extends_processor << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func New" << serviceName << "Processor(handler " << serviceName << ") *" << serviceName << "Processor {" << endl; f_types_ << indent() << " " << self << " := &" << serviceName << "Processor{" << extends_processor_new << "(handler)}" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string escapedFuncName(escape_string((*f_iter)->get_name())); f_types_ << indent() << " " << self << ".AddToProcessorMap(\"" << escapedFuncName << "\", &" << pServiceName << "Processor" << publicize((*f_iter)->get_name()) << "{handler:handler})" << endl; } f_types_ << indent() << " return " << self << endl; f_types_ << indent() << "}" << endl << endl; } // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } f_types_ << endl; } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_go_generator::generate_process_function(t_service* tservice, t_function* tfunction) { // Open function string processorName = privatize(tservice->get_name()) + "Processor" + publicize(tfunction->get_name()); string argsname = publicize(tfunction->get_name() + "_args", true); string resultname = publicize(tfunction->get_name() + "_result", true); // t_struct* xs = tfunction->get_xceptions(); // const std::vector& xceptions = xs->get_members(); f_types_ << indent() << "type " << processorName << " struct {" << endl; f_types_ << indent() << " handler " << publicize(tservice->get_name()) << endl; f_types_ << indent() << "}" << endl << endl; f_types_ << indent() << "func (p *" << processorName << ") Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err " "thrift.TException) {" << endl; indent_up(); string write_err; if (!tfunction->is_oneway()) { write_err = tmp("_write_err"); f_types_ << indent() << "var " << write_err << " error" << endl; } f_types_ << indent() << "args := " << argsname << "{}" << endl; f_types_ << indent() << "if err2 := args." << read_method_name_ << "(ctx, iprot); err2 != nil {" << endl; indent_up(); f_types_ << indent() << "iprot.ReadMessageEnd(ctx)" << endl; if (!tfunction->is_oneway()) { f_types_ << indent() << "x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err2.Error())" << endl; f_types_ << indent() << "oprot.WriteMessageBegin(ctx, \"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId)" << endl; f_types_ << indent() << "x.Write(ctx, oprot)" << endl; f_types_ << indent() << "oprot.WriteMessageEnd(ctx)" << endl; f_types_ << indent() << "oprot.Flush(ctx)" << endl; } f_types_ << indent() << "return false, thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "iprot.ReadMessageEnd(ctx)" << endl << endl; // Even though we never create the goroutine in oneway handlers, // always have (nop) tickerCancel defined makes the writing part of code // generating easier and less error-prone. f_types_ << indent() << "tickerCancel := func() {}" << endl; // Only create the goroutine for non-oneways. if (!tfunction->is_oneway()) { f_types_ << indent() << "// Start a goroutine to do server side connectivity check." << endl; f_types_ << indent() << "if thrift.ServerConnectivityCheckInterval > 0 {" << endl; indent_up(); f_types_ << indent() << "var cancel context.CancelCauseFunc" << endl; f_types_ << indent() << "ctx, cancel = context.WithCancelCause(ctx)" << endl; f_types_ << indent() << "defer cancel(nil)" << endl; f_types_ << indent() << "var tickerCtx context.Context" << endl; f_types_ << indent() << "tickerCtx, tickerCancel = context.WithCancel(context.Background())" << endl; f_types_ << indent() << "defer tickerCancel()" << endl; f_types_ << indent() << "go func(ctx context.Context, cancel context.CancelCauseFunc) {" << endl; indent_up(); f_types_ << indent() << "ticker := time.NewTicker(thrift.ServerConnectivityCheckInterval)" << endl; f_types_ << indent() << "defer ticker.Stop()" << endl; f_types_ << indent() << "for {" << endl; indent_up(); f_types_ << indent() << "select {" << endl; f_types_ << indent() << "case <-ctx.Done():" << endl; indent_up(); f_types_ << indent() << "return" << endl; indent_down(); f_types_ << indent() << "case <-ticker.C:" << endl; indent_up(); f_types_ << indent() << "if !iprot.Transport().IsOpen() {" << endl; indent_up(); f_types_ << indent() << "cancel(thrift.ErrAbandonRequest)" << endl; f_types_ << indent() << "return" << endl; indent_down(); f_types_ << indent() << "}" << endl; indent_down(); f_types_ << indent() << "}" << endl; indent_down(); f_types_ << indent() << "}" << endl; indent_down(); f_types_ << indent() << "}(tickerCtx, cancel)" << endl; indent_down(); f_types_ << indent() << "}" << endl << endl; } else { // Make sure we don't get the defined but unused compiling error. f_types_ << indent() << "_ = tickerCancel" << endl << endl; } if (!tfunction->is_oneway()) { f_types_ << indent() << "result := " << resultname << "{}" << endl; } bool need_reference = type_need_reference(tfunction->get_returntype()); f_types_ << indent() << "if "; if (!tfunction->is_oneway()) { if (!tfunction->get_returntype()->is_void()) { f_types_ << "retval, "; } } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_types_ << "err2 := p.handler." << publicize(tfunction->get_name()) << "("; bool first = true; f_types_ << "ctx"; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; f_types_ << ", "; } else { f_types_ << ", "; } f_types_ << "args." << publicize((*f_iter)->get_name()); } f_types_ << "); err2 != nil {" << endl; indent_up(); f_types_ << indent() << "tickerCancel()" << endl; f_types_ << indent() << "err = thrift.WrapTException(err2)" << endl; t_struct* exceptions = tfunction->get_xceptions(); const vector& x_fields = exceptions->get_members(); if (!x_fields.empty()) { f_types_ << indent() << "switch v := err2.(type) {" << endl; vector::const_iterator xf_iter; for (xf_iter = x_fields.begin(); xf_iter != x_fields.end(); ++xf_iter) { f_types_ << indent() << "case " << type_to_go_type(((*xf_iter)->get_type())) << ":" << endl; indent_up(); f_types_ << indent() << "result." << publicize((*xf_iter)->get_name()) << " = v" << endl; indent_down(); } f_types_ << indent() << "default:" << endl; indent_up(); } if (!tfunction->is_oneway()) { // Avoid writing the error to the wire if it's ErrAbandonRequest f_types_ << indent() << "if errors.Is(err2, thrift.ErrAbandonRequest) {" << endl; indent_up(); f_types_ << indent() << "return false, thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if errors.Is(err2, context.Canceled) {" << endl; indent_up(); f_types_ << indent() << "if err := context.Cause(ctx); errors.Is(err, thrift.ErrAbandonRequest) {" << endl; indent_up(); f_types_ << indent() << "return false, thrift.WrapTException(err)" << endl; indent_down(); f_types_ << indent() << "}" << endl; indent_down(); f_types_ << indent() << "}" << endl; string exc(tmp("_exc")); f_types_ << indent() << exc << " := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, " "\"Internal error processing " << escape_string(tfunction->get_name()) << ": \" + err2.Error())" << endl; f_types_ << indent() << "if err2 := oprot.WriteMessageBegin(ctx, \"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId); err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 := " << exc << ".Write(ctx, oprot); " << write_err << " == nil && err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 := oprot.WriteMessageEnd(ctx); " << write_err << " == nil && err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 := oprot.Flush(ctx); " << write_err << " == nil && err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if " << write_err << " != nil {" << endl; indent_up(); f_types_ << indent() << "return false, thrift.WrapTException(" << write_err << ")" << endl; indent_down(); f_types_ << indent() << "}" << endl; // return success=true as long as writing to the wire was successful. f_types_ << indent() << "return true, err" << endl; } if (!x_fields.empty()) { indent_down(); f_types_ << indent() << "}" << endl; // closes switch } indent_down(); f_types_ << indent() << "}"; // closes err2 != nil if (!tfunction->is_oneway()) { if (!tfunction->get_returntype()->is_void()) { f_types_ << " else {" << endl; // make sure we set Success retval only on success indent_up(); f_types_ << indent() << "result.Success = "; if (need_reference) { f_types_ << "&"; } f_types_ << "retval" << endl; indent_down(); f_types_ << indent() << "}" << endl; } else { f_types_ << endl; } f_types_ << indent() << "tickerCancel()" << endl; f_types_ << indent() << "if err2 := oprot.WriteMessageBegin(ctx, \"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqId); err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 := result." << write_method_name_ << "(ctx, oprot); " << write_err << " == nil && err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 := oprot.WriteMessageEnd(ctx); " << write_err << " == nil && err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 := oprot.Flush(ctx); " << write_err << " == nil && err2 != nil {" << endl; indent_up(); f_types_ << indent() << write_err << " = thrift.WrapTException(err2)" << endl; indent_down(); f_types_ << indent() << "}" << endl; f_types_ << indent() << "if " << write_err << " != nil {" << endl; indent_up(); f_types_ << indent() << "return false, thrift.WrapTException(" << write_err << ")" << endl; indent_down(); f_types_ << indent() << "}" << endl; // return success=true as long as writing to the wire was successful. f_types_ << indent() << "return true, err" << endl; } else { f_types_ << endl; f_types_ << indent() << "tickerCancel()" << endl; f_types_ << indent() << "return true, err" << endl; } indent_down(); f_types_ << indent() << "}" << endl << endl; } /** * Deserializes a field of any type. */ void t_go_generator::generate_deserialize_field(ostream& out, t_field* tfield, bool declare, string prefix, bool inclass, bool coerceData, bool inkey, bool in_container_value) { (void)inclass; (void)coerceData; t_type* orig_type = tfield->get_type(); t_type* type = get_true_type(orig_type); string name(prefix + publicize(tfield->get_name())); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + name; } if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, is_pointer_field(tfield, in_container_value), declare, name); } else if (type->is_container()) { generate_deserialize_container(out, orig_type, is_pointer_field(tfield), declare, name); } else if (type->is_base_type() || type->is_enum()) { if (declare) { string type_name = inkey ? type_to_go_key_type(tfield->get_type()) : type_to_go_type(tfield->get_type()); out << "var " << tfield->get_name() << " " << type_name << endl; } indent(out) << "if v, err := iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary() && !inkey) { out << "ReadBinary(ctx)"; } else { out << "ReadString(ctx)"; } break; case t_base_type::TYPE_BOOL: out << "ReadBool(ctx)"; break; case t_base_type::TYPE_I8: out << "ReadByte(ctx)"; break; case t_base_type::TYPE_I16: out << "ReadI16(ctx)"; break; case t_base_type::TYPE_I32: out << "ReadI32(ctx)"; break; case t_base_type::TYPE_I64: out << "ReadI64(ctx)"; break; case t_base_type::TYPE_DOUBLE: out << "ReadDouble(ctx)"; break; case t_base_type::TYPE_UUID: out << "ReadUUID(ctx)"; break; default: throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "ReadI32(ctx)"; } out << "; err != nil {" << endl; out << indent() << "return thrift.PrependError(\"error reading field " << tfield->get_key() << ": \", err)" << endl; out << "} else {" << endl; string wrap; if (type->is_enum() || orig_type->is_typedef()) { wrap = publicize(type_name(orig_type)); } else if (((t_base_type*)type)->get_base() == t_base_type::TYPE_I8) { wrap = "int8"; } string maybe_address = (is_pointer_field(tfield) ? "&" : ""); if (wrap == "") { indent(out) << name << " = " << maybe_address << "v" << endl; } else { indent(out) << "temp := " << wrap << "(v)" << endl; indent(out) << name << " = " << maybe_address << "temp" << endl; } out << "}" << endl; } else { throw "INVALID TYPE IN generate_deserialize_field '" + type->get_name() + "' for field '" + tfield->get_name() + "'"; } } /** * Generates an unserializer for a struct, calling read() */ void t_go_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, bool pointer_field, bool declare, string prefix) { string eq(declare ? " := " : " = "); out << indent() << prefix << eq << (pointer_field ? "&" : ""); generate_go_struct_initializer(out, tstruct); out << indent() << "if err := " << prefix << "." << read_method_name_ << "(ctx, iprot); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(\"%T error reading struct: \", " << prefix << "), err)" << endl; out << indent() << "}" << endl; } /** * Serialize a container by writing out the header followed by * data and then a footer. */ void t_go_generator::generate_deserialize_container(ostream& out, t_type* orig_type, bool pointer_field, bool declare, string prefix) { t_type* ttype = get_true_type(orig_type); string eq(" = "); if (declare) { eq = " := "; } // Declare variables, read header if (ttype->is_map()) { out << indent() << "_, _, size, err := iprot.ReadMapBegin(ctx)" << endl; out << indent() << "if err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error reading map begin: \", err)" << endl; out << indent() << "}" << endl; out << indent() << "tMap := make(" << type_to_go_type(orig_type) << ", size)" << endl; out << indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tMap" << endl; } else if (ttype->is_set()) { out << indent() << "_, size, err := iprot.ReadSetBegin(ctx)" << endl; out << indent() << "if err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error reading set begin: \", err)" << endl; out << indent() << "}" << endl; out << indent() << "tSet := make(" << type_to_go_type(orig_type) << ", 0, size)" << endl; out << indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tSet" << endl; } else if (ttype->is_list()) { out << indent() << "_, size, err := iprot.ReadListBegin(ctx)" << endl; out << indent() << "if err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error reading list begin: \", err)" << endl; out << indent() << "}" << endl; out << indent() << "tSlice := make(" << type_to_go_type(orig_type) << ", 0, size)" << endl; out << indent() << prefix << eq << " " << (pointer_field ? "&" : "") << "tSlice" << endl; } else { throw "INVALID TYPE IN generate_deserialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'"; } // For loop iterates over elements out << indent() << "for i := 0; i < size; i ++ {" << endl; indent_up(); if (pointer_field) { prefix = "(*" + prefix + ")"; } if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, declare, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, declare, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, declare, prefix); } indent_down(); out << indent() << "}" << endl; // Read container end if (ttype->is_map()) { out << indent() << "if err := iprot.ReadMapEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error reading map end: \", err)" << endl; out << indent() << "}" << endl; } else if (ttype->is_set()) { out << indent() << "if err := iprot.ReadSetEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error reading set end: \", err)" << endl; out << indent() << "}" << endl; } else if (ttype->is_list()) { out << indent() << "if err := iprot.ReadListEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error reading list end: \", err)" << endl; out << indent() << "}" << endl; } } /** * Generates code to deserialize a map */ void t_go_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, bool declare, string prefix) { (void)declare; string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); fkey.set_req(t_field::T_OPT_IN_REQ_OUT); fval.set_req(t_field::T_OPT_IN_REQ_OUT); generate_deserialize_field(out, &fkey, true, "", false, false, true); generate_deserialize_field(out, &fval, true, "", false, false, false, true); indent(out) << prefix << "[" << key << "] = " << val << endl; } /** * Write a set element */ void t_go_generator::generate_deserialize_set_element(ostream& out, t_set* tset, bool declare, string prefix) { (void)declare; string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); felem.set_req(t_field::T_OPT_IN_REQ_OUT); generate_deserialize_field(out, &felem, true, "", false, false, false, true); indent(out) << prefix << " = append(" << prefix << ", " << elem << ")" << endl; } /** * Write a list element */ void t_go_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, bool declare, string prefix) { (void)declare; string elem = tmp("_elem"); t_field felem(((t_list*)tlist)->get_elem_type(), elem); felem.set_req(t_field::T_OPT_IN_REQ_OUT); generate_deserialize_field(out, &felem, true, "", false, false, false, true); indent(out) << prefix << " = append(" << prefix << ", " << elem << ")" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_go_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, bool inkey) { t_type* type = get_true_type(tfield->get_type()); string name(prefix + publicize(tfield->get_name())); // Do nothing for void types if (type->is_void()) { throw "compiler error: cannot generate serialize for void type: " + name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_serialize_container(out, type, is_pointer_field(tfield), name); } else if (type->is_base_type() || type->is_enum()) { indent(out) << "if err := oprot."; if (is_pointer_field(tfield)) { name = "*" + name; } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary() && !inkey) { out << "WriteBinary(ctx, " << name << ")"; } else { out << "WriteString(ctx, string(" << name << "))"; } break; case t_base_type::TYPE_BOOL: out << "WriteBool(ctx, bool(" << name << "))"; break; case t_base_type::TYPE_I8: out << "WriteByte(ctx, int8(" << name << "))"; break; case t_base_type::TYPE_I16: out << "WriteI16(ctx, int16(" << name << "))"; break; case t_base_type::TYPE_I32: out << "WriteI32(ctx, int32(" << name << "))"; break; case t_base_type::TYPE_I64: out << "WriteI64(ctx, int64(" << name << "))"; break; case t_base_type::TYPE_DOUBLE: out << "WriteDouble(ctx, float64(" << name << "))"; break; case t_base_type::TYPE_UUID: out << "WriteUUID(ctx, thrift.Tuuid(" << name << "))"; break; default: throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "WriteI32(ctx, int32(" << name << "))"; } out << "; err != nil {" << endl; out << indent() << "return thrift.PrependError(fmt.Sprintf(\"%T." << escape_string(tfield->get_name()) << " (" << tfield->get_key() << ") field write error: \", p), err) }" << endl; } else { throw "compiler error: Invalid type in generate_serialize_field '" + type->get_name() + "' for field '" + name + "'"; } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_go_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; out << indent() << "if err := " << prefix << "." << write_method_name_ << "(ctx, oprot); err != nil {" << endl; out << indent() << " return thrift.PrependError(fmt.Sprintf(\"%T error writing struct: \", " << prefix << "), err)" << endl; out << indent() << "}" << endl; } void t_go_generator::generate_serialize_container(ostream& out, t_type* ttype, bool pointer_field, string prefix) { if (pointer_field) { prefix = "*" + prefix; } if (ttype->is_map()) { out << indent() << "if err := oprot.WriteMapBegin(ctx, " << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "len(" << prefix << ")); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error writing map begin: \", err)" << endl; out << indent() << "}" << endl; } else if (ttype->is_set()) { out << indent() << "if err := oprot.WriteSetBegin(ctx, " << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << "len(" << prefix << ")); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error writing set begin: \", err)" << endl; out << indent() << "}" << endl; } else if (ttype->is_list()) { out << indent() << "if err := oprot.WriteListBegin(ctx, " << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << "len(" << prefix << ")); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error writing list begin: \", err)" << endl; out << indent() << "}" << endl; } else { throw "compiler error: Invalid type in generate_serialize_container '" + ttype->get_name() + "' for prefix '" + prefix + "'"; } if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; out << indent() << "for k, v := range " << prefix << " {" << endl; indent_up(); generate_serialize_map_element(out, tmap, "k", "v"); indent_down(); indent(out) << "}" << endl; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; out << indent() << "for i := 0; iget_elem_type()); out << indent() << "if func(tgt, src " << goType << ") bool {" << endl; indent_up(); generate_go_equals(out, tset->get_elem_type(), "tgt", "src"); out << indent() << "return true" << endl; indent_down(); out << indent() << "}(" << wrapped_prefix << "[i], " << wrapped_prefix << "[j]) {" << endl; indent_up(); out << indent() << "return thrift.PrependError(\"\", fmt.Errorf(\"%T error writing set field: slice is not " "unique\", " << wrapped_prefix << "))" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl; out << indent() << "for _, v := range " << prefix << " {" << endl; indent_up(); generate_serialize_set_element(out, tset, "v"); indent_down(); indent(out) << "}" << endl; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; out << indent() << "for _, v := range " << prefix << " {" << endl; indent_up(); generate_serialize_list_element(out, tlist, "v"); indent_down(); indent(out) << "}" << endl; } if (ttype->is_map()) { out << indent() << "if err := oprot.WriteMapEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error writing map end: \", err)" << endl; out << indent() << "}" << endl; } else if (ttype->is_set()) { out << indent() << "if err := oprot.WriteSetEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error writing set end: \", err)" << endl; out << indent() << "}" << endl; } else if (ttype->is_list()) { out << indent() << "if err := oprot.WriteListEnd(ctx); err != nil {" << endl; out << indent() << " return thrift.PrependError(\"error writing list end: \", err)" << endl; out << indent() << "}" << endl; } } /** * Serializes the members of a map. * */ void t_go_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), ""); t_field vfield(tmap->get_val_type(), ""); kfield.set_req(t_field::T_OPT_IN_REQ_OUT); vfield.set_req(t_field::T_OPT_IN_REQ_OUT); generate_serialize_field(out, &kfield, kiter, true); generate_serialize_field(out, &vfield, viter); } /** * Serializes the members of a set. */ void t_go_generator::generate_serialize_set_element(ostream& out, t_set* tset, string prefix) { t_field efield(tset->get_elem_type(), ""); efield.set_req(t_field::T_OPT_IN_REQ_OUT); generate_serialize_field(out, &efield, prefix); } /** * Serializes the members of a list. */ void t_go_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string prefix) { t_field efield(tlist->get_elem_type(), ""); efield.set_req(t_field::T_OPT_IN_REQ_OUT); generate_serialize_field(out, &efield, prefix); } /** * Compares any type */ void t_go_generator::generate_go_equals(ostream& out, t_type* ori_type, string tgt, string src) { t_type* ttype = get_true_type(ori_type); // Do nothing for void types if (ttype->is_void()) { throw "compiler error: cannot generate equals for void type: " + tgt; } if (ttype->is_struct() || ttype->is_xception()) { generate_go_equals_struct(out, ttype, tgt, src); } else if (ttype->is_container()) { generate_go_equals_container(out, ttype, tgt, src); } else if (ttype->is_base_type() || ttype->is_enum()) { out << indent() << "if "; if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot equals void: " + tgt; break; case t_base_type::TYPE_STRING: if (ttype->is_binary()) { out << "bytes.Compare(" << tgt << ", " << src << ") != 0"; } else { out << tgt << " != " << src; } break; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: case t_base_type::TYPE_UUID: out << tgt << " != " << src; break; default: throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); } } else if (ttype->is_enum()) { out << tgt << " != " << src; } out << " { return false }" << endl; } else { throw "compiler error: Invalid type in generate_go_equals '" + ttype->get_name() + "' for '" + tgt + "'"; } } /** * Compares the members of a struct */ void t_go_generator::generate_go_equals_struct(ostream& out, t_type* ttype, string tgt, string src) { (void)ttype; out << indent() << "if !" << tgt << "." << equals_method_name_ << "(" << src << ") { return false }" << endl; } /** * Compares any container type */ void t_go_generator::generate_go_equals_container(ostream& out, t_type* ttype, string tgt, string src) { out << indent() << "if len(" << tgt << ") != len(" << src << ") { return false }" << endl; if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; out << indent() << "for k, _tgt := range " << tgt << " {" << endl; indent_up(); string element_source = tmp("_src"); out << indent() << element_source << " := " << src << "[k]" << endl; generate_go_equals(out, tmap->get_val_type(), "_tgt", element_source); indent_down(); indent(out) << "}" << endl; } else if (ttype->is_list() || ttype->is_set()) { t_type* elem; if (ttype->is_list()) { t_list* temp = (t_list*)ttype; elem = temp->get_elem_type(); } else { t_set* temp = (t_set*)ttype; elem = temp->get_elem_type(); } out << indent() << "for i, _tgt := range " << tgt << " {" << endl; indent_up(); string element_source = tmp("_src"); out << indent() << element_source << " := " << src << "[i]" << endl; generate_go_equals(out, elem, "_tgt", element_source); indent_down(); indent(out) << "}" << endl; } else { throw "INVALID TYPE IN generate_go_equals_container '" + ttype->get_name(); } } /** * Generates the docstring for a given struct. */ void t_go_generator::generate_go_docstring(ostream& out, t_struct* tstruct) { generate_go_docstring(out, tstruct, tstruct, "Attributes"); } /** * Generates the docstring for a given function. */ void t_go_generator::generate_go_docstring(ostream& out, t_function* tfunction) { generate_go_docstring(out, tfunction, tfunction->get_arglist(), "Parameters"); } /** * Generates the docstring for a struct or function. */ void t_go_generator::generate_go_docstring(ostream& out, t_doc* tdoc, t_struct* tstruct, const char* subheader) { bool has_doc = false; stringstream ss; if (tdoc->has_doc()) { has_doc = true; ss << tdoc->get_doc(); } const vector& fields = tstruct->get_members(); if (fields.size() > 0) { if (has_doc) { ss << endl; } has_doc = true; ss << subheader << ":\n"; vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ss << " - " << publicize(p->get_name()); if (p->has_doc()) { ss << ": " << p->get_doc(); } else { ss << endl; } } } if (has_doc) { generate_docstring_comment(out, "", "// ", ss.str(), ""); } } /** * Generates the docstring for a generic object. */ void t_go_generator::generate_go_docstring(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_docstring_comment(out, "", "//", tdoc->get_doc(), ""); } } /** * Declares an argument, which may include initialization as necessary. * * @param tfield The field */ string t_go_generator::declare_argument(t_field* tfield) { std::ostringstream result; result << publicize(tfield->get_name()) << "="; if (tfield->get_value() != nullptr) { result << "thrift_spec[" << tfield->get_key() << "][4]"; } else { result << "nil"; } return result.str(); } /** * Renders a struct field initial value. * * @param tfield The field, which must have `tfield->get_value() != nullptr` */ string t_go_generator::render_field_initial_value(t_field* tfield, const string& name, bool optional_field) { t_type* type = get_true_type(tfield->get_type()); if (optional_field) { // The caller will make a second pass for optional fields, // assigning the result of render_const_value to "*field_name". It // is maddening that Go syntax does not allow for a type-agnostic // way to initialize a pointer to a const value, but so it goes. // The alternative would be to write type specific functions that // convert from const values to pointer types, but given the lack // of overloading it would be messy. return "new(" + type_to_go_type(tfield->get_type()) + ")"; } else { return render_const_value(type, tfield->get_value(), name); } } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_go_generator::function_signature(t_function* tfunction, string prefix) { // TODO(mcslee): Nitpicky, no ',' if argument_list is empty return publicize(prefix + tfunction->get_name()) + "(" + argument_list(tfunction->get_arglist()) + ")"; } /** * Renders an interface function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_go_generator::function_signature_if(t_function* tfunction, string prefix, bool addError) { string signature = publicize(prefix + tfunction->get_name()) + "("; signature += "ctx context.Context"; if (!tfunction->get_arglist()->get_members().empty()) { signature += ", " + argument_list(tfunction->get_arglist()); } signature += ") ("; t_type* ret = tfunction->get_returntype(); t_struct* exceptions = tfunction->get_xceptions(); string errs = argument_list(exceptions); if (!ret->is_void()) { signature += "_r " + type_to_go_type(ret); if (addError || errs.size() == 0) { signature += ", "; } } if (addError) { signature += "_err error"; } signature += ")"; return signature; } /** * Renders a field list */ string t_go_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += variable_name_to_go_name((*f_iter)->get_name()) + " " + type_to_go_type((*f_iter)->get_type()); } return result; } string t_go_generator::type_name(t_type* ttype) { string module( module_name(ttype)); if( ! module.empty()) { return module + "." + ttype->get_name(); } return ttype->get_name(); } string t_go_generator::module_name(t_type* ttype) { t_program* program = ttype->get_program(); if (program != nullptr && program != program_) { if (program->get_namespace("go").empty() || program_->get_namespace("go").empty() || program->get_namespace("go") != program_->get_namespace("go")) { string module(get_real_go_module(program)); return package_identifiers_[module]; } } return ""; } /** * Converts the parse type to a go tyoe */ string t_go_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: /* this is wrong, binary is still a string type internally if (type->is_binary()) { return "thrift.BINARY"; } */ return "thrift.STRING"; case t_base_type::TYPE_BOOL: return "thrift.BOOL"; case t_base_type::TYPE_I8: return "thrift.BYTE"; case t_base_type::TYPE_I16: return "thrift.I16"; case t_base_type::TYPE_I32: return "thrift.I32"; case t_base_type::TYPE_I64: return "thrift.I64"; case t_base_type::TYPE_DOUBLE: return "thrift.DOUBLE"; case t_base_type::TYPE_UUID: return "thrift.UUID"; default: break; } } else if (type->is_enum()) { return "thrift.I32"; } else if (type->is_struct() || type->is_xception()) { return "thrift.STRUCT"; } else if (type->is_map()) { return "thrift.MAP"; } else if (type->is_set()) { return "thrift.SET"; } else if (type->is_list()) { return "thrift.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Converts the parse type to a go map type, will throw an exception if it will * not produce a valid go map type. */ string t_go_generator::type_to_go_key_type(t_type* type) { t_type* resolved_type = type; while (resolved_type->is_typedef()) { resolved_type = ((t_typedef*)resolved_type)->get_type()->get_true_type(); } if (resolved_type->is_map() || resolved_type->is_list() || resolved_type->is_set()) { throw "Cannot produce a valid type for a Go map key: " + type_to_go_type(type) + " - aborting."; } if (resolved_type->is_binary()) return "string"; return type_to_go_type(type); } /** * Converts the parse type to a go type */ string t_go_generator::type_to_go_type(t_type* type) { return type_to_go_type_with_opt(type, false); } /** * Converts the parse type to a go type, taking into account whether the field * associated with the type is T_OPTIONAL. */ string t_go_generator::type_to_go_type_with_opt(t_type* type, bool optional_field) { string maybe_pointer(optional_field ? "*" : ""); if (type->is_typedef() && ((t_typedef*)type)->is_forward_typedef()) { type = ((t_typedef*)type)->get_true_type(); } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw ""; case t_base_type::TYPE_STRING: if (type->is_binary()) { return maybe_pointer + "[]byte"; } return maybe_pointer + "string"; case t_base_type::TYPE_BOOL: return maybe_pointer + "bool"; case t_base_type::TYPE_I8: return maybe_pointer + "int8"; case t_base_type::TYPE_I16: return maybe_pointer + "int16"; case t_base_type::TYPE_I32: return maybe_pointer + "int32"; case t_base_type::TYPE_I64: return maybe_pointer + "int64"; case t_base_type::TYPE_DOUBLE: return maybe_pointer + "float64"; case t_base_type::TYPE_UUID: return maybe_pointer + "thrift.Tuuid"; default: break; } } else if (type->is_enum()) { return maybe_pointer + publicize(type_name(type)); } else if (type->is_struct() || type->is_xception()) { return "*" + publicize(type_name(type)); } else if (type->is_map()) { t_map* t = (t_map*)type; string keyType = type_to_go_key_type(t->get_key_type()); string valueType = type_to_go_type(t->get_val_type()); return maybe_pointer + string("map[") + keyType + "]" + valueType; } else if (type->is_set()) { t_set* t = (t_set*)type; string elemType = type_to_go_type(t->get_elem_type()); return maybe_pointer + string("[]") + elemType; } else if (type->is_list()) { t_list* t = (t_list*)type; string elemType = type_to_go_type(t->get_elem_type()); return maybe_pointer + string("[]") + elemType; } else if (type->is_typedef()) { return maybe_pointer + publicize(type_name(type)); } throw "INVALID TYPE IN type_to_go_type: " + type->get_name(); } /** See the comment inside generate_go_struct_definition for what this is. */ string t_go_generator::type_to_spec_args(t_type* ttype) { while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } if (ttype->is_base_type() || ttype->is_enum()) { return "nil"; } else if (ttype->is_struct() || ttype->is_xception()) { return "(" + type_name(ttype) + ", " + type_name(ttype) + ".thrift_spec)"; } else if (ttype->is_map()) { return "(" + type_to_enum(((t_map*)ttype)->get_key_type()) + "," + type_to_spec_args(((t_map*)ttype)->get_key_type()) + "," + type_to_enum(((t_map*)ttype)->get_val_type()) + "," + type_to_spec_args(((t_map*)ttype)->get_val_type()) + ")"; } else if (ttype->is_set()) { return "(" + type_to_enum(((t_set*)ttype)->get_elem_type()) + "," + type_to_spec_args(((t_set*)ttype)->get_elem_type()) + ")"; } else if (ttype->is_list()) { return "(" + type_to_enum(((t_list*)ttype)->get_elem_type()) + "," + type_to_spec_args(((t_list*)ttype)->get_elem_type()) + ")"; } throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name(); } // parses a string of struct tags into key/value pairs and writes them to the given map void t_go_generator::parse_go_tags(map* tags, const string in) { string key; string value; size_t mode=0; // 0/1/2 for key/value/whitespace size_t index=0; for (auto it=in.begin(); it #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes #define NSGLOBAL (nsglobal_.size() ? nsglobal_ : "") #define NSGLOBAL_A ("\\" + NSGLOBAL) #define NSGLOBAL_B (NSGLOBAL + "\\") #define NSGLOBAL_AB ("\\" + NSGLOBAL + "\\") /** * PHP code generator. * */ class t_php_generator : public t_oop_generator { public: t_php_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; std::map::const_iterator iter; binary_inline_ = false; rest_ = false; phps_ = false; oop_ = false; validate_ = false; json_serializable_ = false; getters_setters_ = false; nsglobal_ = ""; // by default global namespace is empty classmap_ = false; for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if (iter->first.compare("inlined") == 0) { binary_inline_ = true; } else if (iter->first.compare("rest") == 0) { rest_ = true; } else if (iter->first.compare("server") == 0) { phps_ = true; } else if (iter->first.compare("oop") == 0) { oop_ = true; } else if (iter->first.compare("validate") == 0) { validate_ = true; } else if (iter->first.compare("json") == 0) { json_serializable_ = true; } else if (iter->first.compare("nsglobal") == 0) { nsglobal_ = iter->second; } else if (iter->first.compare("classmap") == 0) { classmap_ = true; } else if (iter->first.compare("psr4") == 0) { if(classmap_){ throw "psr4 and classmap are mutually exclusive."; } else { pwarning(0, "psr4 is default option! needn't add psr4 option!\n"); } } else if (iter->first.compare("getters_setters") == 0) { getters_setters_ = true; } else { throw "unknown option php:" + iter->first; } } if (oop_ && binary_inline_) { throw "oop and inlined are mutually exclusive."; } update_keywords_for_validation(); out_dir_base_ = (binary_inline_ ? "gen-phpi" : "gen-php"); escape_['$'] = "\\$"; } std::string indent_str() const override { return " "; } static bool is_valid_namespace(const std::string& sub_namespace); /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_consts(vector consts) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); std::set lang_keywords_for_validation() const override; /** * Structs! */ void generate_php_struct(t_struct* tstruct, bool is_exception); void generate_php_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool is_result = false); void generate_php_struct_reader(std::ostream& out, t_struct* tstruct, bool is_result); void generate_php_struct_writer(std::ostream& out, t_struct* tstruct, bool is_result); void generate_php_function_helpers(t_service* tservice, t_function* tfunction); void generate_php_struct_required_validator(ostream& out, t_struct* tstruct, std::string method_name, bool write_mode); void generate_php_struct_read_validator(ostream& out, t_struct* tstruct); void generate_php_struct_write_validator(ostream& out, t_struct* tstruct); void generate_php_struct_json_serialize(ostream& out, t_struct* tstruct, bool is_result); bool needs_php_write_validator(t_struct* tstruct, bool is_result); bool needs_php_read_validator(t_struct* tstruct, bool is_result); int get_php_num_required_fields(const vector& fields, bool write_mode); void generate_php_type_spec(std::ostream& out, t_type* t); void generate_php_struct_spec(std::ostream& out, t_struct* tstruct); void generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct); void generate_reflection_setters(ostringstream& out, string field_name, string cap_name); void generate_reflection_getters(ostringstream& out, string field_name, string cap_name); std::string get_cap_name(std::string name); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_rest(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_processor(t_service* tservice); void generate_process_function(std::ostream& out, t_service* tservice, t_function* tfunction); void generate_service_header(t_service* tservice, std::ostream& file); void generate_program_header(std::ostream& file); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = "", bool inclass = false); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_php_doc(std::ostream& out, t_doc* tdoc); void generate_php_doc(std::ostream& out, t_field* tfield); void generate_php_doc(std::ostream& out, t_function* tfunction); void generate_php_docstring_comment(std::ostream& out, string contents); /** * Helper rendering functions */ std::string php_includes(); std::string declare_field(t_field* tfield, bool init = false, bool obj = false); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct, bool addTypeHints = true); std::string type_to_cast(t_type* ttype); std::string type_to_enum(t_type* ttype); std::string type_to_phpdoc(t_type* ttype); bool php_is_scalar(t_type *ttype) { ttype = ttype->get_true_type(); if(ttype->is_base_type()) { return true; } else if(ttype->is_enum()) { return true; } else { return false; } } std::string php_namespace_base(const t_program* p) { std::string ns = p->get_namespace("php"); const char* delimiter = "\\"; size_t position = ns.find('.'); while (position != string::npos) { ns.replace(position, 1, delimiter); position = ns.find('.', position + 1); } return ns; } // general use namespace prefixing: \my\namespace\ or my_namespace_ string php_namespace(const t_program* p) { string ns = php_namespace_base(p); return (nsglobal_.size() ? NSGLOBAL_AB : NSGLOBAL_B) + (ns.size() ? (ns + "\\") : ""); } // return the namespace of a file: // global\ns\sub\ns or global\ns or sub\ns string php_namespace_suffix(const t_program* p) { string ns = php_namespace_base(p); return NSGLOBAL + (ns.size() && NSGLOBAL.size() ? "\\" : "") + ns; } // add a directory to already existing namespace string php_namespace_directory(string directory, bool end = true) { (void)directory; if (end) { return ";"; } else { return ""; } } // writing an autload identifier into globa;ls: my\namespace\ or my_namespace_ string php_namespace_autoload(const t_program* p) { std::string ns = php_namespace_base(p); return (nsglobal_.size() ? NSGLOBAL_B : NSGLOBAL) + (ns.size() ? (ns + "\\") : ""); } // declaring a type: typename or my_namespace_typename string php_namespace_declaration(t_type* t) { return t->get_name(); } std::string php_path(t_program* p) { std::string ns = p->get_namespace("php.path"); if (ns.empty()) { return p->get_name(); } // Transform the java-style namespace into a path. for (char & n : ns) { if (n == '.') { n = '/'; } } return ns + '/'; } /** * Transform class_method into ClassMethod * * @param str * @return stirng */ string classify(string str) { string classe = ""; vector x = split(str, '_'); for (const auto & i : x) { classe = classe + capitalize(i); } return classe; } /** * Split method * @param s * @param delim * @param elems * @return */ vector& split(const string& s, char delim, vector& elems) { stringstream ss(s); string item; while (getline(ss, item, delim)) { elems.push_back(item); } return elems; } vector split(const string& s, char delim) { vector elems; return split(s, delim, elems); } /** * Capitalize method * @param str * @return */ string capitalize(string str) { string::iterator it(str.begin()); if (it != str.end()) str[0] = toupper((unsigned char)str[0]); // while(++it != str.end()) // { // *it = tolower((unsigned char)*it); // } return str; } private: /** * File streams */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_service_; std::string package_dir_; /** * Generate protocol-independent template? Or Binary inline code? */ bool binary_inline_; /** * Generate a REST handler class */ bool rest_; /** * Generate stubs for a PHP server */ bool phps_; /** * Whether to use OOP base class TBase */ bool oop_; /** * Whether to generate old-style PHP file to use classmap autoloading */ bool classmap_; /** * Whether to generate validator code */ bool validate_; /** * Whether to generate JsonSerializable classes */ bool json_serializable_; /** * Global namespace for PHP 5.3 */ std::string nsglobal_; /** * Whether to generate getters and setters */ bool getters_setters_; }; std::set t_php_generator::lang_keywords_for_validation() const { std::string keywords[] = { "BEGIN", "END", "__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__", "__LINE__", "__METHOD__", "__NAMESPACE__", "abstract", "alias", "and", "args", "as", "assert", "begin", "break", "case", "catch", "class", "clone", "continue", "declare", "def", "default", "del", "delete", "do", "dynamic", "elif", "else", "elseif", "elsif", "end", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "ensure", "except", "exec", "finally", "float", "for", "foreach", "from", "function", "global", "goto", "if", "implements", "import", "in", "inline", "instanceof", "interface", "is", "lambda", "module", "native", "new", "next", "nil", "not", "or", "package", "pass", "public", "print", "private", "protected", "raise", "redo", "rescue", "retry", "register", "return", "self", "sizeof", "static", "super", "switch", "synchronized", "then", "this", "throw", "transient", "try", "undef", "unless", "unsigned", "until", "use", "var", "virtual", "volatile", "when", "while", "with", "xor", "yield" }; return std::set(keywords, keywords + sizeof(keywords)/sizeof(keywords[0]) ); } bool t_php_generator::is_valid_namespace(const std::string& sub_namespace) { return sub_namespace == "path"; } /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_php_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); // Create Real directory Namespaces vector NSx = split(php_namespace_suffix(get_program()), '\\'); package_dir_ = get_out_dir(); for (const auto & i : NSx) { package_dir_ = package_dir_ + "/" + i + "/"; MKDIR(package_dir_.c_str()); } // Prepare output file for all the types in classmap mode if (classmap_) { // Make output file string f_types_name = package_dir_ + "Types.php"; f_types_.open(f_types_name.c_str()); generate_program_header(f_types_); } } /** * Prints standard php includes */ string t_php_generator::php_includes() { string includes = "use Thrift\\Base\\TBase;\n" "use Thrift\\Type\\TType;\n" "use Thrift\\Type\\TMessageType;\n" "use Thrift\\Exception\\TException;\n" "use Thrift\\Exception\\TProtocolException;\n" "use Thrift\\Protocol\\TProtocol;\n" "use Thrift\\Protocol\\TBinaryProtocolAccelerated;\n" "use Thrift\\Exception\\TApplicationException;\n"; if (json_serializable_) { includes += "use JsonSerializable;\n" "use stdClass;\n"; } return includes; } /** * Close up (or down) some filez. */ void t_php_generator::close_generator() { if (classmap_) { // Close types file f_types_.close(); } } /** * Generates a typedef. This is not done in PHP, types are all implicit. * * @param ttypedef The type definition */ void t_php_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Generates service header contains namespace suffix and includes inside file specified */ void t_php_generator::generate_service_header(t_service* tservice, std::ostream& file) { file << "get_program()).empty()) { file << "namespace " << php_namespace_suffix(tservice->get_program()) << ";" << endl << endl; } file << autogen_comment() << php_includes(); file << endl; } /** * Generates program header contains namespace suffix and includes inside file specified */ void t_php_generator::generate_program_header(std::ostream& file) { file << "get_name() + ".php"; f_enum.open(f_enum_name.c_str()); generate_program_header(f_enum); } vector constants = tenum->get_constants(); vector::iterator c_iter; // We're also doing it this way to see how it performs. It's more legible // code but you can't do things like an 'extract' on it, which is a bit of // a downer. generate_php_doc(f_enum, tenum); f_enum << "final class " << tenum->get_name() << endl << "{" << endl; indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); generate_php_doc(f_enum, *c_iter); indent(f_enum) << "const " << (*c_iter)->get_name() << " = " << value << ";" << endl << endl; } indent(f_enum) << "static public $__names = array(" << endl; indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); indent(f_enum) << value << " => '" << (*c_iter)->get_name() << "'," << endl; } indent_down(); indent(f_enum) << ");" << endl; indent_down(); f_enum << "}" << endl << endl; if (!classmap_) { f_enum.close(); } } /** * Generate constant class * * Override the one from t_generator */ void t_php_generator::generate_consts(vector consts) { vector::iterator c_iter; // Create class only if needed if (consts.size() > 0) { ofstream_with_content_based_conditional_update& f_consts = f_types_; if (!classmap_) { string f_consts_name = package_dir_ + "Constant.php"; f_consts.open(f_consts_name.c_str()); generate_program_header(f_consts); } f_consts << "final class Constant extends \\Thrift\\Type\\TConstant"<< endl << "{" << endl; indent_up(); // Create static property for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { string name = (*c_iter)->get_name(); indent(f_consts) << "static protected $" << name << ";" << endl; } // Create init function for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { string name = (*c_iter)->get_name(); f_consts << endl; f_consts << indent() << "protected static function init_" << name << "()" <get_type(), (*c_iter)->get_value()); f_consts << ";" << endl; indent_down(); indent(f_consts) << "}" << endl; } indent_down(); f_consts << "}" << endl; if (!classmap_) { f_consts.close(); } } } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_php_generator::render_const_value(t_type* type, t_const_value* value) { std::ostringstream out; type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << "new " << php_namespace(type->get_program()) << type->get_name() << "(array(" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } out << indent(); out << render_const_value(g_type_string, v_iter->first); out << " => "; out << render_const_value(field_type, v_iter->second); out << "," << endl; } indent_down(); indent(out) << "))"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); out << "array(" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent(); out << render_const_value(ktype, v_iter->first); out << " => "; out << render_const_value(vtype, v_iter->second); out << "," << endl; } indent_down(); indent(out) << ")"; } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } out << "array(" << endl; indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { out << indent(); out << render_const_value(etype, *v_iter); if (type->is_set()) { out << " => true"; } out << "," << endl; } indent_down(); indent(out) << ")"; } return out.str(); } /** * Make a struct */ void t_php_generator::generate_struct(t_struct* tstruct) { generate_php_struct(tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_php_generator::generate_xception(t_struct* txception) { generate_php_struct(txception, true); } /** * Structs can be normal or exceptions. */ void t_php_generator::generate_php_struct(t_struct* tstruct, bool is_exception) { ofstream_with_content_based_conditional_update& f_struct = f_types_; if (!classmap_) { string f_struct_name = package_dir_ + tstruct->get_name() + ".php"; f_struct.open(f_struct_name.c_str()); generate_program_header(f_struct); } generate_php_struct_definition(f_struct, tstruct, is_exception); if (!classmap_) { f_struct.close(); } } void t_php_generator::generate_php_type_spec(ostream& out, t_type* t) { t = get_true_type(t); indent(out) << "'type' => " << type_to_enum(t) << "," << endl; if (t->is_base_type()) { // Noop, type is all we need } else if (t->is_struct() || t->is_xception() || t->is_enum()) { indent(out) << "'class' => '" << php_namespace(t->get_program()) << t->get_name() << "'," << endl; } else if (t->is_map()) { t_type* ktype = get_true_type(((t_map*)t)->get_key_type()); t_type* vtype = get_true_type(((t_map*)t)->get_val_type()); indent(out) << "'ktype' => " << type_to_enum(ktype) << "," << endl; indent(out) << "'vtype' => " << type_to_enum(vtype) << "," << endl; indent(out) << "'key' => array(" << endl; indent_up(); generate_php_type_spec(out, ktype); indent_down(); indent(out) << ")," << endl; indent(out) << "'val' => array(" << endl; indent_up(); generate_php_type_spec(out, vtype); indent(out) << ")," << endl; indent_down(); } else if (t->is_list() || t->is_set()) { t_type* etype; if (t->is_list()) { etype = get_true_type(((t_list*)t)->get_elem_type()); } else { etype = get_true_type(((t_set*)t)->get_elem_type()); } indent(out) << "'etype' => " << type_to_enum(etype) << "," << endl; indent(out) << "'elem' => array(" << endl; indent_up(); generate_php_type_spec(out, etype); indent(out) << ")," << endl; indent_down(); } else { throw "compiler error: no type for php struct spec field"; } } /** * Generates the struct specification structure, which fully qualifies enough * type information to generalize serialization routines. */ void t_php_generator::generate_php_struct_spec(ostream& out, t_struct* tstruct) { indent(out) << "static public $_TSPEC = array(" << endl; indent_up(); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); indent(out) << (*m_iter)->get_key() << " => array(" << endl; indent_up(); out << indent() << "'var' => '" << (*m_iter)->get_name() << "'," << endl; out << indent() << "'isRequired' => " << ((*m_iter)->get_req() == t_field::T_REQUIRED ? "true" : "false") << "," << endl; generate_php_type_spec(out, t); indent_down(); indent(out) << ")," << endl; } indent_down(); indent(out) << ");" << endl << endl; } /** * Generates necessary accessors and mutators for the fields */ void t_php_generator::generate_generic_field_getters_setters(std::ostream& out, t_struct* tstruct) { std::ostringstream getter_stream; std::ostringstream setter_stream; // build up the bodies of both the getter and setter at once const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = *f_iter; std::string field_name = field->get_name(); std::string cap_name = get_cap_name(field_name); indent_up(); generate_reflection_setters(setter_stream, field_name, cap_name); generate_reflection_getters(getter_stream, field_name, cap_name); indent_down(); } indent(out) << endl; out << getter_stream.str(); out << setter_stream.str(); indent(out) << endl; } /** * Generates a getter for the generated private fields */ void t_php_generator::generate_reflection_getters(ostringstream& out, string field_name, string cap_name) { out << indent() << "public function " << "get" << cap_name << "()" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return $this->" << field_name << ";" << endl; indent_down(); out << indent() << "}" << endl; out << endl; } /** * Generates a setter for the generated private fields */ void t_php_generator::generate_reflection_setters(ostringstream& out, string field_name, string cap_name) { out << indent() << "public function set" << cap_name << "(" << "$" << field_name << ")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "$this->" << field_name << " = $" << field_name << ";" << endl; indent_down(); out << indent() << "}" << endl; out << endl; } /** * Gets the first-letter capitalized name for the field * * @param std::string name of the field */ std::string t_php_generator::get_cap_name(std::string name) { name[0] = toupper(name[0]); return name; } /** * Generates a struct definition for a thrift data type. This is nothing in PHP * where the objects are all just associative arrays (unless of course we * decide to start using objects for them...) * * @param tstruct The struct definition */ void t_php_generator::generate_php_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool is_result) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; generate_php_doc(out, tstruct); out << "class " << php_namespace_declaration(tstruct); if (is_exception) { out << " extends " << "TException"; } else if (oop_) { out << " extends " << "TBase"; } if (json_serializable_) { out << " implements JsonSerializable"; } out << endl << "{" << endl; indent_up(); out << indent() << "static public $isValidate = " << (validate_ ? "true" : "false") << ";" << endl << endl; generate_php_struct_spec(out, tstruct); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string dval = "null"; t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr && !(t->is_struct() || t->is_xception())) { dval = render_const_value((*m_iter)->get_type(), (*m_iter)->get_value()); } generate_php_doc(out, *m_iter); string access = (getters_setters_) ? "private" : "public"; indent(out) << access << " $" << (*m_iter)->get_name() << " = " << dval << ";" << endl; } out << endl; // Generate constructor from array string param = (members.size() > 0) ? "$vals = null" : ""; out << indent() << "public function __construct(" << param << ")"<< endl << indent() << "{" << endl; indent_up(); if (members.size() > 0) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = get_true_type((*m_iter)->get_type()); if ((*m_iter)->get_value() != nullptr && (t->is_struct() || t->is_xception())) { indent(out) << "$this->" << (*m_iter)->get_name() << " = " << render_const_value(t, (*m_iter)->get_value()) << ";" << endl; } } out << indent() << "if (is_array($vals)) {" << endl; indent_up(); if (oop_) { out << indent() << "parent::__construct(self::$_TSPEC, $vals);" << endl; } else { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << indent() << "if (isset($vals['" << (*m_iter)->get_name() << "'])) {" << endl; indent_up(); out << indent() << "$this->" << (*m_iter)->get_name() << " = $vals['" << (*m_iter)->get_name() << "'];" << endl; indent_down(); out << indent() << "}" << endl; } } indent_down(); out << indent() << "}" << endl; } scope_down(out); out << endl; out << indent() << "public function getName()" << endl << indent() << "{" << endl; indent_up(); out << indent() << "return '" << tstruct->get_name() << "';" << endl; indent_down(); out << indent() << "}" << endl << endl; out << endl; if (getters_setters_) { generate_generic_field_getters_setters(out, tstruct); } generate_php_struct_reader(out, tstruct, is_result); out << endl; generate_php_struct_writer(out, tstruct, is_result); if (needs_php_read_validator(tstruct, is_result)) { out << endl; generate_php_struct_read_validator(out, tstruct); } if (needs_php_write_validator(tstruct, is_result)) { out << endl; generate_php_struct_write_validator(out, tstruct); } if (json_serializable_) { out << endl; generate_php_struct_json_serialize(out, tstruct, is_result); } indent_down(); out << indent() << "}" << endl; } /** * Generates the read() method for a struct */ void t_php_generator::generate_php_struct_reader(ostream& out, t_struct* tstruct, bool is_result) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent(out) << "public function read($input)" << endl; scope_up(out); if (oop_) { if (needs_php_read_validator(tstruct, is_result)) { indent(out) << "$tmp = $this->_read('" << tstruct->get_name() << "', self::$_TSPEC, $input);" << endl; indent(out) << "$this->_validateForRead();" << endl; indent(out) << "return $tmp;" << endl; } else { indent(out) << "return $this->_read('" << tstruct->get_name() << "', self::$_TSPEC, $input);" << endl; } scope_down(out); out << endl; return; } out << indent() << "$xfer = 0;" << endl << indent() << "$fname = null;" << endl << indent() << "$ftype = 0;" << endl << indent() << "$fid = 0;" << endl; // Declare stack tmp variables if (!binary_inline_) { indent(out) << "$xfer += $input->readStructBegin($fname);" << endl; } // Loop over reading in fields indent(out) << "while (true) {" << endl; indent_up(); // Read beginning field marker if (binary_inline_) { t_field fftype(g_type_i8, "ftype"); t_field ffid(g_type_i16, "fid"); generate_deserialize_field(out, &fftype); out << indent() << "if ($ftype == " << "TType::STOP) {" << endl << indent() << " break;" << endl << indent() << "}" << endl; generate_deserialize_field(out, &ffid); } else { indent(out) << "$xfer += $input->readFieldBegin($fname, $ftype, $fid);" << endl; // Check for field STOP marker and break indent(out) << "if ($ftype == " << "TType::STOP) {" << endl; indent_up(); indent(out) << "break;" << endl; indent_down(); indent(out) << "}" << endl; } // Switch statement on the field we are reading indent(out) << "switch ($fid) {" << endl; indent_up(); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; indent_up(); indent(out) << "if ($ftype == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; indent_up(); generate_deserialize_field(out, *f_iter, "this->"); indent_down(); out << indent() << "} else {" << endl; indent_up(); if (binary_inline_) { indent(out) << "$xfer += TProtocol::skipBinary($input, $ftype);" << endl; } else { indent(out) << "$xfer += $input->skip($ftype);" << endl; } indent_down(); out << indent() << "}" << endl << indent() << "break;" << endl; indent_down(); } // In the default case we skip the field indent(out) << "default:" << endl; indent_up(); if (binary_inline_) { indent(out) << "$xfer += " << "TProtocol::skipBinary($input, $ftype);" << endl; } else { indent(out) << "$xfer += $input->skip($ftype);" << endl; } indent(out) << "break;" << endl; indent_down(); scope_down(out); if (!binary_inline_) { // Read field end marker indent(out) << "$xfer += $input->readFieldEnd();" << endl; } scope_down(out); if (!binary_inline_) { indent(out) << "$xfer += $input->readStructEnd();" << endl; } if (needs_php_read_validator(tstruct, is_result)) { indent(out) << "$this->_validateForRead();" << endl; } indent(out) << "return $xfer;" << endl; indent_down(); out << indent() << "}" << endl; } /** * Generates the write() method for a struct */ void t_php_generator::generate_php_struct_writer(ostream& out, t_struct* tstruct, bool is_result) { string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; if (binary_inline_) { indent(out) << "public function write(&$output)" << endl; } else { indent(out) << "public function write($output)" << endl; } indent(out) << "{" << endl; indent_up(); if (needs_php_write_validator(tstruct, is_result)) { indent(out) << "$this->_validateForWrite();" << endl; } if (oop_) { indent(out) << "return $this->_write('" << tstruct->get_name() << "', self::$_TSPEC, $output);" << endl; scope_down(out); out << endl; return; } indent(out) << "$xfer = 0;" << endl; if (!binary_inline_) { indent(out) << "$xfer += $output->writeStructBegin('" << name << "');" << endl; } for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << indent() << "if ($this->" << (*f_iter)->get_name() << " !== null) {" << endl; indent_up(); t_type* type = get_true_type((*f_iter)->get_type()); string expect; if (type->is_container()) { expect = "array"; } else if (type->is_struct()) { expect = "object"; } if (!expect.empty()) { out << indent() << "if (!is_" << expect << "($this->" << (*f_iter)->get_name() << ")) {" << endl; indent_up(); out << indent() << "throw new " << "TProtocolException('Bad type in structure.', " << "TProtocolException::INVALID_DATA);" << endl; scope_down(out); } // Write field header if (binary_inline_) { out << indent() << "$output .= pack('c', " << type_to_enum((*f_iter)->get_type()) << ");" << endl << indent() << "$output .= pack('n', " << (*f_iter)->get_key() << ");" << endl; } else { indent(out) << "$xfer += $output->writeFieldBegin(" << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ");" << endl; } // Write field contents generate_serialize_field(out, *f_iter, "this->"); // Write field closer if (!binary_inline_) { indent(out) << "$xfer += $output->writeFieldEnd();" << endl; } indent_down(); indent(out) << "}" << endl; } if (binary_inline_) { out << indent() << "$output .= pack('c', " << "TType::STOP);" << endl; } else { out << indent() << "$xfer += $output->writeFieldStop();" << endl << indent() << "$xfer += $output->writeStructEnd();" << endl; } out << indent() << "return $xfer;" << endl; indent_down(); out << indent() << "}" << endl; } void t_php_generator::generate_php_struct_read_validator(ostream& out, t_struct* tstruct) { generate_php_struct_required_validator(out, tstruct, "_validateForRead", false); } void t_php_generator::generate_php_struct_write_validator(ostream& out, t_struct* tstruct) { generate_php_struct_required_validator(out, tstruct, "_validateForWrite", true); } void t_php_generator::generate_php_struct_required_validator(ostream& out, t_struct* tstruct, std::string method_name, bool write_mode) { indent(out) << "private function " << method_name << "() {" << endl; indent_up(); const vector& fields = tstruct->get_members(); if (fields.size() > 0) { vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); if (field->get_req() == t_field::T_REQUIRED || (field->get_req() == t_field::T_OPT_IN_REQ_OUT && write_mode)) { indent(out) << "if ($this->" << field->get_name() << " === null) {" << endl; indent_up(); indent(out) << "throw new TProtocolException('Required field " << tstruct->get_name() << "." << field->get_name() << " is unset!');" << endl; indent_down(); indent(out) << "}" << endl; } } } indent_down(); indent(out) << "}" << endl; } void t_php_generator::generate_php_struct_json_serialize(ostream& out, t_struct* tstruct, bool is_result) { indent(out) << "public function jsonSerialize() {" << endl; indent_up(); if (needs_php_write_validator(tstruct, is_result)) { indent(out) << "$this->_validateForWrite();" << endl; } indent(out) << "$json = new stdClass;" << endl; const vector& fields = tstruct->get_members(); if (fields.size() > 0) { vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); t_type* type = field->get_type(); const string& name = field->get_name(); if (type->is_map()) { t_type* key_type = ((t_map*)type)->get_key_type(); if (!(key_type->is_base_type() || key_type->is_enum())) { // JSON object keys must be strings. PHP's json_encode() // function will convert any scalar key to strings, but // we skip thrift maps with non-scalar keys. continue; } } indent(out) << "if ($this->" << name << " !== null) {" << endl; indent_up(); indent(out) << "$json->" << name << " = "; if (type->is_map()) { out << "(object)"; } else { out << type_to_cast(type); } out << "$this->" << name << ";" << endl; indent_down(); indent(out) << "}" << endl; } } indent(out) << "return $json;" << endl; indent_down(); indent(out) << "}" << endl; } int t_php_generator::get_php_num_required_fields(const vector& fields, bool write_mode) { int num_req = 0; if (fields.size() > 0) { vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED || ((*f_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT && write_mode)) { ++num_req; } } } return num_req; } bool t_php_generator::needs_php_write_validator(t_struct* tstruct, bool is_result) { return (validate_ && !is_result && !tstruct->is_union() && get_php_num_required_fields(tstruct->get_members(), true) > 0); } bool t_php_generator::needs_php_read_validator(t_struct* tstruct, bool is_result) { return (validate_ && !is_result && (get_php_num_required_fields(tstruct->get_members(), false) > 0)); } /** * Generates a thrift service. * * @param tservice The service definition */ void t_php_generator::generate_service(t_service* tservice) { if(classmap_) { string f_service_name = package_dir_ + service_name_ + ".php"; f_service_.open(f_service_name.c_str()); generate_service_header(tservice, f_service_); } // Generate the three main parts of the service (well, two for now in PHP) generate_service_interface(tservice); if (rest_) { generate_service_rest(tservice); } generate_service_client(tservice); generate_service_helpers(tservice); if (phps_) { generate_service_processor(tservice); } if(classmap_) { // Close service file f_service_ << endl; f_service_.close(); } } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_php_generator::generate_service_processor(t_service* tservice) { ofstream_with_content_based_conditional_update& f_service_processor = f_service_; if (!classmap_) { string f_service_processor_name = package_dir_ + service_name_ + "Processor.php"; f_service_processor.open(f_service_processor_name.c_str()); generate_service_header(tservice, f_service_processor); } // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = tservice->get_extends()->get_name(); extends_processor = " extends " + php_namespace(tservice->get_extends()->get_program()) + extends + "Processor"; } // Generate the header portion f_service_processor << "class " << service_name_ << "Processor" << extends_processor << endl << "{" << endl; indent_up(); if (extends.empty()) { f_service_processor << indent() << "protected $handler_ = null;" << endl; } f_service_processor << indent() << "public function __construct($handler)"<< endl << indent() << "{" << endl; indent_up(); if (extends.empty()) { f_service_processor << indent() << "$this->handler_ = $handler;" << endl; } else { f_service_processor << indent() << "parent::__construct($handler);" << endl; } indent_down(); f_service_processor << indent() << "}" << endl << endl; // Generate the server implementation f_service_processor << indent() << "public function process($input, $output)" << endl << indent() << "{" << endl; indent_up(); f_service_processor << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl << indent() << "$mtype = 0;" << endl << endl; if (binary_inline_) { t_field ffname(g_type_string, "fname"); t_field fmtype(g_type_i8, "mtype"); t_field fseqid(g_type_i32, "rseqid"); generate_deserialize_field(f_service_processor, &ffname, "", true); generate_deserialize_field(f_service_processor, &fmtype, "", true); generate_deserialize_field(f_service_processor, &fseqid, "", true); } else { f_service_processor << indent() << "$input->readMessageBegin($fname, $mtype, $rseqid);" << endl; } // HOT: check for method implementation f_service_processor << indent() << "$methodname = 'process_'.$fname;" << endl << indent() << "if (!method_exists($this, $methodname)) {" << endl; indent_up(); if (binary_inline_) { f_service_processor << indent() << "throw new \\Exception('Function '.$fname.' not implemented.');" << endl; } else { f_service_processor << indent() << " $input->skip(" << "TType::STRUCT);" << endl << indent() << " $input->readMessageEnd();" << endl << indent() << " $x = new " << "TApplicationException('Function '.$fname.' not implemented.', " << "TApplicationException::UNKNOWN_METHOD);" << endl << indent() << " $output->writeMessageBegin($fname, " << "TMessageType::EXCEPTION, $rseqid);" << endl << indent() << " $x->write($output);" << endl << indent() << " $output->writeMessageEnd();" << endl << indent() << " $output->getTransport()->flush();" << endl << indent() << " return;" << endl; } indent_down(); f_service_processor << indent() << "}" << endl << indent() << "$this->$methodname($rseqid, $input, $output);" << endl << indent() << "return true;" << endl; indent_down(); f_service_processor << indent() << "}" << endl << endl; // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(f_service_processor, tservice, *f_iter); } indent_down(); f_service_processor << "}" << endl; if (!classmap_) { f_service_processor.close(); } } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_php_generator::generate_process_function(std::ostream& out, t_service* tservice, t_function* tfunction) { // Open function out << indent() << "protected function process_" << tfunction->get_name() << "($seqid, $input, $output)" << endl << indent() << "{" << endl; indent_up(); string argsname = php_namespace(tservice->get_program()) + service_name_ + "_" + tfunction->get_name() + "_args"; string resultname = php_namespace(tservice->get_program()) + service_name_ + "_" + tfunction->get_name() + "_result"; out << indent() << "$bin_accel = ($input instanceof " << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_read_binary_after_message_begin');" << endl; out << indent() << "if ($bin_accel) {" << endl; indent_up(); out << indent() << "$args = thrift_protocol_read_binary_after_message_begin(" <isStrictRead()" <read($input);" << endl; indent_down(); out << indent() << "}" << endl; if (!binary_inline_) { out << indent() << "$input->readMessageEnd();" << endl; } t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { out << indent() << "$result = new " << resultname << "();" << endl; } // Try block for a function with exceptions if (xceptions.size() > 0) { out << indent() << "try {" << endl; indent_up(); } // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; out << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { out << "$result->success = "; } out << "$this->handler_->" << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { out << ", "; } out << "$args->" << (*f_iter)->get_name(); } out << ");" << endl; if (!tfunction->is_oneway() && xceptions.size() > 0) { indent_down(); for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << indent() << "} catch (" << php_namespace(get_true_type((*x_iter)->get_type())->get_program()) << (*x_iter)->get_type()->get_name() << " $" << (*x_iter)->get_name() << ") {" << endl; if (!tfunction->is_oneway()) { indent_up(); out << indent() << "$result->" << (*x_iter)->get_name() << " = $" << (*x_iter)->get_name() << ";" << endl; indent_down(); out << indent(); } } out << "}" << endl; } // Shortcut out here for oneway functions if (tfunction->is_oneway()) { out << indent() << "return;" << endl; indent_down(); out << indent() << "}" << endl; return; } out << indent() << "$bin_accel = ($output instanceof " << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');" << endl; out << indent() << "if ($bin_accel) {" << endl; indent_up(); out << indent() << "thrift_protocol_write_binary(" << endl; indent_up(); out << indent() << "$output,"<get_name()<< "'," <isStrictWrite()"<get_name() << "'));" << endl << indent() << "$buff .= '" << tfunction->get_name() << "';" << endl << indent() << "$buff .= pack('N', $seqid);" << endl << indent() << "$result->write($buff);" << endl << indent() << "$output->write($buff);" << endl << indent() << "$output->flush();" << endl; } else { out << indent() << "$output->writeMessageBegin('" << tfunction->get_name() << "', " << "TMessageType::REPLY, $seqid);" << endl << indent() << "$result->write($output);" << endl << indent() << "$output->writeMessageEnd();" << endl << indent() << "$output->getTransport()->flush();" << endl; } scope_down(out); // Close function indent_down(); out << indent() << "}" << endl; } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_php_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; ofstream_with_content_based_conditional_update& f_struct_definition = f_service_; if (classmap_) { f_struct_definition << "// HELPER FUNCTIONS AND STRUCTURES" << endl << endl; } for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); string name = ts->get_name(); ts->set_name(service_name_ + "_" + name); if (!classmap_) { string f_struct_definition_name = package_dir_ + service_name_ + "_" + name + ".php"; f_struct_definition.open(f_struct_definition_name.c_str()); generate_service_header(tservice, f_struct_definition); } generate_php_struct_definition(f_struct_definition, ts); if (!classmap_) { f_struct_definition.close(); } generate_php_function_helpers(tservice, *f_iter); ts->set_name(name); } } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_php_generator::generate_php_function_helpers(t_service* tservice, t_function* tfunction) { if (!tfunction->is_oneway()) { t_struct result(program_, service_name_ + "_" + tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } ofstream_with_content_based_conditional_update& f_struct_helper = f_service_; if (!classmap_) { string f_struct_helper_name = package_dir_ + result.get_name() + ".php"; f_struct_helper.open(f_struct_helper_name.c_str()); generate_service_header(tservice, f_struct_helper); } generate_php_struct_definition(f_struct_helper, &result, false, true); if (!classmap_) { f_struct_helper.close(); } } } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_php_generator::generate_service_interface(t_service* tservice) { ofstream_with_content_based_conditional_update& f_service_interface = f_service_; if (!classmap_) { string f_service_interface_name = package_dir_ + service_name_ + "If.php"; f_service_interface.open(f_service_interface_name.c_str()); generate_service_header(tservice, f_service_interface); } string extends = ""; string extends_if = ""; if (tservice->get_extends() != nullptr) { extends = " extends " + php_namespace(tservice->get_extends()->get_program()) + tservice->get_extends()->get_name(); extends_if = " extends " + php_namespace(tservice->get_extends()->get_program()) + tservice->get_extends()->get_name() + "If"; } generate_php_doc(f_service_interface, tservice); f_service_interface << "interface " << php_namespace_declaration(tservice) << "If" << extends_if << endl << "{" << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_php_doc(f_service_interface, *f_iter); indent(f_service_interface) << "public function " << function_signature(*f_iter) << ";" << endl; } indent_down(); f_service_interface << "}" << endl; // Close service interface file if (!classmap_) { f_service_interface.close(); } } /** * Generates a REST interface */ void t_php_generator::generate_service_rest(t_service* tservice) { ofstream_with_content_based_conditional_update& f_service_rest = f_service_; if (!classmap_) { string f_service_rest_name = package_dir_ + service_name_ + "Rest.php"; f_service_rest.open(f_service_rest_name.c_str()); generate_service_header(tservice, f_service_rest); } string extends = ""; string extends_if = ""; if (tservice->get_extends() != nullptr) { extends = " extends " + php_namespace(tservice->get_extends()->get_program()) + tservice->get_extends()->get_name(); extends_if = " extends " + php_namespace(tservice->get_extends()->get_program()) + tservice->get_extends()->get_name() + "Rest"; } f_service_rest << "class " << service_name_ << "Rest" << extends_if << endl << "{" << endl; indent_up(); if (extends.empty()) { f_service_rest << indent() << "protected $impl_;" << endl << endl; } f_service_rest << indent() << "public function __construct($impl) {" << endl << indent() << " $this->impl_ = $impl;" << endl << indent() << "}" << endl << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent(f_service_rest) << "public function " << (*f_iter)->get_name() << "($request) {" << endl; indent_up(); const vector& args = (*f_iter)->get_arglist()->get_members(); vector::const_iterator a_iter; for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) { t_type* atype = get_true_type((*a_iter)->get_type()); string cast = type_to_cast(atype); string req = "$request['" + (*a_iter)->get_name() + "']"; if (atype->is_bool()) { f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = " << cast << "(!empty(" << req << ") && (" << req << " !== 'false'));" << endl; } else { f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = isset(" << req << ") ? " << cast << req << " : null;" << endl; } /* slist no longer supported if (atype->is_string() && ((t_base_type*)atype)->is_string_list()) { f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = explode(',', $" << (*a_iter)->get_name() << ");" << endl; } else */ if (atype->is_map() || atype->is_list()) { f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = json_decode($" << (*a_iter)->get_name() << ", true);" << endl; } else if (atype->is_set()) { f_service_rest << indent() << "$" << (*a_iter)->get_name() << " = array_fill_keys(json_decode($" << (*a_iter)->get_name() << ", true), 1);" << endl; } else if (atype->is_struct() || atype->is_xception()) { f_service_rest << indent() << "if ($" << (*a_iter)->get_name() << " !== null) {" << endl << indent() << " $" << (*a_iter)->get_name() << " = new " << php_namespace(atype->get_program()) << atype->get_name() << "(json_decode($" << (*a_iter)->get_name() << ", true));" << endl << indent() << "}" << endl; } } f_service_rest << indent() << "return $this->impl_->" << (*f_iter)->get_name() << "(" << argument_list((*f_iter)->get_arglist(), false) << ");" << endl; indent_down(); indent(f_service_rest) << "}" << endl << endl; } indent_down(); f_service_rest << "}" << endl << endl; // Close service rest file f_service_rest << endl; if (!classmap_) { f_service_rest.close(); } } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_php_generator::generate_service_client(t_service* tservice) { ofstream_with_content_based_conditional_update& f_service_client = f_service_; if (!classmap_) { string f_service_client_name = package_dir_ + service_name_ + "Client.php"; f_service_client.open(f_service_client_name.c_str()); generate_service_header(tservice, f_service_client); } string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = tservice->get_extends()->get_name(); extends_client = " extends " + php_namespace(tservice->get_extends()->get_program()) + extends + "Client"; } f_service_client << "class " << php_namespace_declaration(tservice) << "Client" << extends_client << " implements " << php_namespace(tservice->get_program()) << service_name_ << "If" << endl <<"{"<< endl; indent_up(); // Private members if (extends.empty()) { f_service_client << indent() << "protected $input_ = null;" << endl << indent() << "protected $output_ = null;" << endl << endl; f_service_client << indent() << "protected $seqid_ = 0;" << endl << endl; } // Constructor function f_service_client << indent() << "public function __construct($input, $output = null)" << endl << indent() << "{" << endl; indent_up(); if (!extends.empty()) { f_service_client << indent() << "parent::__construct($input, $output);" << endl; } else { f_service_client << indent() << "$this->input_ = $input;" << endl << indent() << "$this->output_ = $output ? $output : $input;" << endl; } indent_down(); f_service_client << indent() << "}" << endl << endl; // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); f_service_client << endl; // Open function indent(f_service_client) << "public function " << function_signature(*f_iter) << endl; scope_up(f_service_client); indent(f_service_client) << "$this->send_" << funname << "("; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { f_service_client << ", "; } f_service_client << "$" << (*fld_iter)->get_name(); } f_service_client << ");" << endl; if (!(*f_iter)->is_oneway()) { f_service_client << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_client << "return "; } f_service_client << "$this->recv_" << funname << "();" << endl; } scope_down(f_service_client); f_service_client << endl; indent(f_service_client) << "public function send_" << function_signature(*f_iter) << endl; scope_up(f_service_client); std::string argsname = php_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_args"; f_service_client << indent() << "$args = new " << argsname << "();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_client << indent() << "$args->" << (*fld_iter)->get_name() << " = $" << (*fld_iter)->get_name() << ";" << endl; } f_service_client << indent() << "$bin_accel = ($this->output_ instanceof " << "TBinaryProtocolAccelerated) && function_exists('thrift_protocol_write_binary');" << endl; f_service_client << indent() << "if ($bin_accel) {" << endl; indent_up(); string messageType = (*f_iter)->is_oneway() ? "TMessageType::ONEWAY" : "TMessageType::CALL"; f_service_client << indent() << "thrift_protocol_write_binary(" << endl; indent_up(); f_service_client << indent() << "$this->output_," << endl << indent() << "'" << (*f_iter)->get_name() << "'," << endl << indent() << messageType << "," << endl << indent() << "$args," << endl << indent() << "$this->seqid_," << endl << indent() << "$this->output_->isStrictWrite()" << endl; indent_down(); f_service_client << indent() << ");" << endl; indent_down(); f_service_client << indent() << "} else {" << endl; indent_up(); // Serialize the request header if (binary_inline_) { f_service_client << indent() << "$buff = pack('N', (0x80010000 | " << messageType << "));" << endl << indent() << "$buff .= pack('N', strlen('" << funname << "'));" << endl << indent() << "$buff .= '" << funname << "';" << endl << indent() << "$buff .= pack('N', $this->seqid_);" << endl; } else { f_service_client << indent() << "$this->output_->writeMessageBegin('" << (*f_iter)->get_name() << "', " << messageType << ", $this->seqid_);" << endl; } // Write to the stream if (binary_inline_) { f_service_client << indent() << "$args->write($buff);" << endl << indent() << "$this->output_->write($buff);" << endl << indent() << "$this->output_->flush();" << endl; } else { f_service_client << indent() << "$args->write($this->output_);" << endl << indent() << "$this->output_->writeMessageEnd();" << endl << indent() << "$this->output_->getTransport()->flush();" << endl; } scope_down(f_service_client); scope_down(f_service_client); if (!(*f_iter)->is_oneway()) { std::string resultname = php_namespace(tservice->get_program()) + service_name_ + "_" + (*f_iter)->get_name() + "_result"; t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); // Open function f_service_client << endl << indent() << "public function " << function_signature(&recv_function) << endl; scope_up(f_service_client); f_service_client << indent() << "$bin_accel = ($this->input_ instanceof " << "TBinaryProtocolAccelerated)" << " && function_exists('thrift_protocol_read_binary');" << endl; f_service_client << indent() << "if ($bin_accel) {" << endl; indent_up(); f_service_client << indent() << "$result = thrift_protocol_read_binary(" << endl; indent_up(); f_service_client << indent() << "$this->input_," << endl << indent() << "'" << resultname << "'," << endl << indent() << "$this->input_->isStrictRead()" << endl; indent_down(); f_service_client << indent() << ");" << endl; indent_down(); f_service_client << indent() << "} else {" << endl; indent_up(); f_service_client << indent() << "$rseqid = 0;" << endl << indent() << "$fname = null;" << endl << indent() << "$mtype = 0;" << endl << endl; if (binary_inline_) { t_field ffname(g_type_string, "fname"); t_field fseqid(g_type_i32, "rseqid"); f_service_client << indent() << "$ver = unpack('N', $this->input_->readAll(4));" << endl << indent() << "$ver = $ver[1];" << endl << indent() << "$mtype = $ver & 0xff;" << endl << indent() << "$ver = $ver & 0xffff0000;" << endl << indent() << "if ($ver != 0x80010000) throw new " << "TProtocolException('Bad version identifier: '.$ver, " << "TProtocolException::BAD_VERSION);" << endl; generate_deserialize_field(f_service_client, &ffname, "", true); generate_deserialize_field(f_service_client, &fseqid, "", true); } else { f_service_client << indent() << "$this->input_->readMessageBegin($fname, $mtype, $rseqid);" << endl << indent() << "if ($mtype == TMessageType::EXCEPTION) {" << endl; indent_up(); f_service_client << indent() << "$x = new TApplicationException();" << endl << indent() << "$x->read($this->input_);" << endl << indent() << "$this->input_->readMessageEnd();" << endl << indent() << "throw $x;" << endl; indent_down(); f_service_client << indent() << "}" << endl; } f_service_client << indent() << "$result = new " << resultname << "();" << endl << indent() << "$result->read($this->input_);" << endl; if (!binary_inline_) { f_service_client << indent() << "$this->input_->readMessageEnd();" << endl; } scope_down(f_service_client); // Careful, only return result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_client << indent() << "if ($result->success !== null) {" << endl; indent_up(); f_service_client << indent() << "return $result->success;" << endl; indent_down(); f_service_client << indent() << "}" << endl; } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { f_service_client << indent() << "if ($result->" << (*x_iter)->get_name() << " !== null) {" << endl; indent_up(); f_service_client << indent() << "throw $result->" << (*x_iter)->get_name() << ";" << endl; indent_down(); f_service_client << indent() << "}" << endl; } // Careful, only return _result if not a void function if ((*f_iter)->get_returntype()->is_void()) { indent(f_service_client) << "return;" << endl; } else { f_service_client << indent() << "throw new \\Exception(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl; } // Close function scope_down(f_service_client); } } indent_down(); f_service_client << "}" << endl; // Close service client file if (!classmap_) { f_service_client.close(); } } /** * Deserializes a field of any type. */ void t_php_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool inclass) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + tfield->get_name(); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else { if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type() || type->is_enum()) { if (binary_inline_) { std::string itrans = (inclass ? "$this->input_" : "$input"); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << indent() << "$len = unpack('N', " << itrans << "->readAll(4));" << endl << indent() << "$len = $len[1];" << endl << indent() << "if ($len > 0x7fffffff) {" << endl << indent() << " $len = 0 - (($len - 1) ^ 0xffffffff);" << endl << indent() << "}" << endl << indent() << "$" << name << " = " << itrans << "->readAll($len);" << endl; break; case t_base_type::TYPE_BOOL: out << indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));" << endl << indent() << "$" << name << " = (bool)$" << name << "[1];" << endl; break; case t_base_type::TYPE_I8: out << indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));" << endl << indent() << "$" << name << " = $" << name << "[1];" << endl; break; case t_base_type::TYPE_I16: out << indent() << "$val = unpack('n', " << itrans << "->readAll(2));" << endl << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fff) {" << endl << indent() << " $val = 0 - (($val - 1) ^ 0xffff);" << endl << indent() << "}" << endl << indent() << "$" << name << " = $val;" << endl; break; case t_base_type::TYPE_I32: out << indent() << "$val = unpack('N', " << itrans << "->readAll(4));" << endl << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fffffff) {" << endl << indent() << " $val = 0 - (($val - 1) ^ 0xffffffff);" << endl << indent() << "}" << endl << indent() << "$" << name << " = $val;" << endl; break; case t_base_type::TYPE_I64: out << indent() << "$arr = unpack('N2', " << itrans << "->readAll(8));" << endl << indent() << "if ($arr[1] & 0x80000000) {" << endl << indent() << " $arr[1] = $arr[1] ^ 0xFFFFFFFF;" << endl << indent() << " $arr[2] = $arr[2] ^ 0xFFFFFFFF;" << endl << indent() << " $" << name << " = 0 - $arr[1]*4294967296 - $arr[2] - 1;" << endl << indent() << "} else {" << endl << indent() << " $" << name << " = $arr[1]*4294967296 + $arr[2];" << endl << indent() << "}" << endl; break; case t_base_type::TYPE_DOUBLE: out << indent() << "$arr = unpack('d', strrev(" << itrans << "->readAll(8)));" << endl << indent() << "$" << name << " = $arr[1];" << endl; break; default: throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase) + tfield->get_name(); } } else if (type->is_enum()) { out << indent() << "$val = unpack('N', " << itrans << "->readAll(4));" << endl << indent() << "$val = $val[1];" << endl << indent() << "if ($val > 0x7fffffff) {" << endl << indent() << " $val = 0 - (($val - 1) ^ 0xffffffff);" << endl << indent() << "}" << endl << indent() << "$" << name << " = $val;" << endl; } } else { indent(out) << "$xfer += $input->"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "readString($" << name << ");"; break; case t_base_type::TYPE_BOOL: out << "readBool($" << name << ");"; break; case t_base_type::TYPE_I8: out << "readByte($" << name << ");"; break; case t_base_type::TYPE_I16: out << "readI16($" << name << ");"; break; case t_base_type::TYPE_I32: out << "readI32($" << name << ");"; break; case t_base_type::TYPE_I64: out << "readI64($" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble($" << name << ");"; break; default: throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "readI32($" << name << ");"; } out << endl; } } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); } } } /** * Generates an unserializer for a variable. This makes two key assumptions, * first that there is a const char* variable named data that points to the * buffer for deserialization, and that there is a variable protocol which * is a reference to a TProtocol serialization object. */ void t_php_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { out << indent() << "$" << prefix << " = new " << php_namespace(tstruct->get_program()) << tstruct->get_name() << "();" << endl << indent() << "$xfer += $" << prefix << "->read($input);" << endl; } void t_php_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { string size = tmp("_size"); string ktype = tmp("_ktype"); string vtype = tmp("_vtype"); string etype = tmp("_etype"); t_field fsize(g_type_i32, size); t_field fktype(g_type_i8, ktype); t_field fvtype(g_type_i8, vtype); t_field fetype(g_type_i8, etype); out << indent() << "$" << prefix << " = array();" << endl << indent() << "$" << size << " = 0;" << endl; // Declare variables, read header if (ttype->is_map()) { out << indent() << "$" << ktype << " = 0;" << endl << indent() << "$" << vtype << " = 0;" << endl; if (binary_inline_) { generate_deserialize_field(out, &fktype); generate_deserialize_field(out, &fvtype); generate_deserialize_field(out, &fsize); } else { out << indent() << "$xfer += $input->readMapBegin(" << "$" << ktype << ", $" << vtype << ", $" << size << ");" << endl; } } else if (ttype->is_set()) { if (binary_inline_) { generate_deserialize_field(out, &fetype); generate_deserialize_field(out, &fsize); } else { out << indent() << "$" << etype << " = 0;" << endl << indent() << "$xfer += $input->readSetBegin(" << "$" << etype << ", $" << size << ");" << endl; } } else if (ttype->is_list()) { if (binary_inline_) { generate_deserialize_field(out, &fetype); generate_deserialize_field(out, &fsize); } else { out << indent() << "$" << etype << " = 0;" << endl << indent() << "$xfer += $input->readListBegin(" << "$" << etype << ", $" << size << ");" << endl; } } // For loop iterates over elements string i = tmp("_i"); indent(out) << "for ($" << i << " = 0; $" << i << " < $" << size << "; ++$" << i << ") {" << endl; indent_up(); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } scope_down(out); if (!binary_inline_) { // Read container end if (ttype->is_map()) { indent(out) << "$xfer += $input->readMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "$xfer += $input->readSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "$xfer += $input->readListEnd();" << endl; } } } /** * Generates code to deserialize a map */ void t_php_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("key"); string val = tmp("val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); indent(out) << declare_field(&fkey, true, true) << endl; indent(out) << declare_field(&fval, true, true) << endl; generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << "$" << prefix << "[$" << key << "] = $" << val << ";" << endl; } void t_php_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("elem"); t_field felem(tset->get_elem_type(), elem); indent(out) << "$" << elem << " = null;" << endl; generate_deserialize_field(out, &felem); t_type* elem_type = tset->get_elem_type(); if(php_is_scalar(elem_type)) { indent(out) << "$" << prefix << "[$" << elem << "] = true;" << endl; } else { indent(out) << "$" << prefix << "[] = $" << elem << ";" << endl; } } void t_php_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("elem"); t_field felem(tlist->get_elem_type(), elem); indent(out) << "$" << elem << " = null;" << endl; generate_deserialize_field(out, &felem); indent(out) << "$" << prefix << " []= $" << elem << ";" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_php_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name()); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + tfield->get_name()); } else if (type->is_base_type() || type->is_enum()) { string name = prefix + tfield->get_name(); if (binary_inline_) { if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << indent() << "$output .= pack('N', strlen($" << name << "));" << endl << indent() << "$output .= $" << name << ";" << endl; break; case t_base_type::TYPE_BOOL: out << indent() << "$output .= pack('c', $" << name << " ? 1 : 0);" << endl; break; case t_base_type::TYPE_I8: out << indent() << "$output .= pack('c', $" << name << ");" << endl; break; case t_base_type::TYPE_I16: out << indent() << "$output .= pack('n', $" << name << ");" << endl; break; case t_base_type::TYPE_I32: out << indent() << "$output .= pack('N', $" << name << ");" << endl; break; case t_base_type::TYPE_I64: out << indent() << "$output .= pack('N2', $" << name << " >> 32, $" << name << " & 0xFFFFFFFF);" << endl; break; case t_base_type::TYPE_DOUBLE: out << indent() << "$output .= strrev(pack('d', $" << name << "));" << endl; break; default: throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << indent() << "$output .= pack('N', $" << name << ");" << endl; } } else { indent(out) << "$xfer += $output->"; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: out << "writeString($" << name << ");"; break; case t_base_type::TYPE_BOOL: out << "writeBool($" << name << ");"; break; case t_base_type::TYPE_I8: out << "writeByte($" << name << ");"; break; case t_base_type::TYPE_I16: out << "writeI16($" << name << ");"; break; case t_base_type::TYPE_I32: out << "writeI32($" << name << ");"; break; case t_base_type::TYPE_I64: out << "writeI64($" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble($" << name << ");"; break; default: throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "writeI32($" << name << ");"; } out << endl; } } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_php_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << "$xfer += $" << prefix << "->write($output);" << endl; } /** * Writes out a container */ void t_php_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { if (ttype->is_map()) { if (binary_inline_) { out << indent() << "$output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_key_type()) << ");" << endl << indent() << "$output .= pack('c', " << type_to_enum(((t_map*)ttype)->get_val_type()) << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));" << endl; } else { indent(out) << "$output->writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "count($" << prefix << "));" << endl; } } else if (ttype->is_set()) { if (binary_inline_) { out << indent() << "$output .= pack('c', " << type_to_enum(((t_set*)ttype)->get_elem_type()) << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));" << endl; } else { indent(out) << "$output->writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << "count($" << prefix << "));" << endl; } } else if (ttype->is_list()) { if (binary_inline_) { out << indent() << "$output .= pack('c', " << type_to_enum(((t_list*)ttype)->get_elem_type()) << ");" << endl << indent() << "$output .= strrev(pack('l', count($" << prefix << ")));" << endl; } else { indent(out) << "$output->writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << "count($" << prefix << "));" << endl; } } if (ttype->is_map()) { string kiter = tmp("kiter"); string viter = tmp("viter"); indent(out) << "foreach ($" << prefix << " as " << "$" << kiter << " => $" << viter << ") {" << endl; indent_up(); generate_serialize_map_element(out, (t_map*)ttype, kiter, viter); scope_down(out); } else if (ttype->is_set()) { string iter = tmp("iter"); string iter_val = tmp("iter"); indent(out) << "foreach ($" << prefix << " as $" << iter << " => $" << iter_val << ") {" << endl; indent_up(); t_type* elem_type = ((t_set*)ttype)->get_elem_type(); if(php_is_scalar(elem_type)) { generate_serialize_set_element(out, (t_set*)ttype, iter); } else { generate_serialize_set_element(out, (t_set*)ttype, iter_val); } scope_down(out); } else if (ttype->is_list()) { string iter = tmp("iter"); indent(out) << "foreach ($" << prefix << " as $" << iter << ") {" << endl; indent_up(); generate_serialize_list_element(out, (t_list*)ttype, iter); scope_down(out); } if (!binary_inline_) { if (ttype->is_map()) { indent(out) << "$output->writeMapEnd();" << endl; } else if (ttype->is_set()) { indent(out) << "$output->writeSetEnd();" << endl; } else if (ttype->is_list()) { indent(out) << "$output->writeListEnd();" << endl; } } } /** * Serializes the members of a map. * */ void t_php_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), kiter); generate_serialize_field(out, &kfield, ""); t_field vfield(tmap->get_val_type(), viter); generate_serialize_field(out, &vfield, ""); } /** * Serializes the members of a set. */ void t_php_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Serializes the members of a list. */ void t_php_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Emits a PHPDoc comment for the given contents */ void t_php_generator::generate_php_docstring_comment(ostream& out, string contents) { generate_docstring_comment(out, "/**\n", " * ", contents, " */\n"); } /** * Emits a PHPDoc comment if the provided object has a doc in Thrift */ void t_php_generator::generate_php_doc(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_php_docstring_comment(out, tdoc->get_doc()); } } /** * Emits a PHPDoc comment for a field */ void t_php_generator::generate_php_doc(ostream& out, t_field* field) { stringstream ss; // prepend free-style doc if available if (field->has_doc()) { ss << field->get_doc() << endl; } // append @var tag t_type* type = get_true_type(field->get_type()); ss << "@var " << type_to_phpdoc(type) << endl; generate_php_docstring_comment(out, ss.str()); } /** * Emits a PHPDoc comment for a function */ void t_php_generator::generate_php_doc(ostream& out, t_function* function) { stringstream ss; if (function->has_doc()) { ss << function->get_doc() << endl; } // generate parameter types doc const vector& args = function->get_arglist()->get_members(); vector::const_iterator a_iter; for (a_iter = args.begin(); a_iter != args.end(); ++a_iter) { t_field* arg = *a_iter; ss << "@param " << type_to_phpdoc(arg->get_type()) << " $" << arg->get_name(); if (arg->has_doc()) { ss << " " << arg->get_doc(); } ss << endl; } // generate return type doc t_type* ret_type = function->get_returntype(); if (!ret_type->is_void() || ret_type->has_doc()) { ss << "@return " << type_to_phpdoc(ret_type); if (ret_type->has_doc()) { ss << " " << ret_type->get_doc(); } ss << endl; } // generate exceptions doc const vector& excs = function->get_xceptions()->get_members(); vector::const_iterator e_iter; for (e_iter = excs.begin(); e_iter != excs.end(); ++e_iter) { t_field* exc = *e_iter; ss << "@throws " << type_to_phpdoc(exc->get_type()); if (exc->has_doc()) { ss << " " << exc->get_doc(); } ss << endl; } generate_docstring_comment(out, "/**\n", " * ", ss.str(), " */\n"); } /** * Declares a field, which may include initialization as necessary. * * @param ttype The type */ string t_php_generator::declare_field(t_field* tfield, bool init, bool obj) { string result = "$" + tfield->get_name(); if (init) { t_type* type = get_true_type(tfield->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: break; case t_base_type::TYPE_STRING: result += " = ''"; break; case t_base_type::TYPE_BOOL: result += " = false"; break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: result += " = 0"; break; case t_base_type::TYPE_DOUBLE: result += " = 0.0"; break; default: throw "compiler error: no PHP initializer for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { result += " = 0"; } else if (type->is_container()) { result += " = array()"; } else if (type->is_struct() || type->is_xception()) { if (obj) { result += " = new " + php_namespace(type->get_program()) + type->get_name() + "()"; } else { result += " = null"; } } } return result + ";"; } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_php_generator::function_signature(t_function* tfunction, string prefix) { return prefix + tfunction->get_name() + "(" + argument_list(tfunction->get_arglist()) + ")"; } /** * Renders a field list */ string t_php_generator::argument_list(t_struct* tstruct, bool addTypeHints) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } t_type* type = (*f_iter)->get_type(); // Set type name if (addTypeHints) { if (type->is_struct()) { string className = php_namespace(type->get_program()) + php_namespace_directory("Definition", false) + classify(type->get_name()); result += className + " "; } else if (type->is_container()) { result += "array "; } } result += "$" + (*f_iter)->get_name(); } return result; } /** * Gets a typecast string for a particular type. */ string t_php_generator::type_to_cast(t_type* type) { if (type->is_base_type()) { t_base_type* btype = (t_base_type*)type; switch (btype->get_base()) { case t_base_type::TYPE_BOOL: return "(bool)"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "(int)"; case t_base_type::TYPE_DOUBLE: return "(double)"; case t_base_type::TYPE_STRING: return "(string)"; default: return ""; } } else if (type->is_enum()) { return "(int)"; } return ""; } /** * Converts the parse type to a C++ enum string for the given type. */ string t_php_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType::STRING"; case t_base_type::TYPE_BOOL: return "TType::BOOL"; case t_base_type::TYPE_I8: return "TType::BYTE"; case t_base_type::TYPE_I16: return "TType::I16"; case t_base_type::TYPE_I32: return "TType::I32"; case t_base_type::TYPE_I64: return "TType::I64"; case t_base_type::TYPE_DOUBLE: return "TType::DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "TType::I32"; } else if (type->is_struct() || type->is_xception()) { return "TType::STRUCT"; } else if (type->is_map()) { return "TType::MAP"; } else if (type->is_set()) { return "TType::SET"; } else if (type->is_list()) { return "TType::LST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Converts the parse type to a PHPDoc string for the given type. */ string t_php_generator::type_to_phpdoc(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: return "string"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "int"; case t_base_type::TYPE_I16: return "int"; case t_base_type::TYPE_I32: return "int"; case t_base_type::TYPE_I64: return "int"; case t_base_type::TYPE_DOUBLE: return "double"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "int"; } else if (type->is_struct() || type->is_xception()) { return php_namespace(type->get_program()) + type->get_name(); } else if (type->is_map()) { return "array"; } else if (type->is_set()) { t_set* tset = static_cast(type); t_type* t_elem = tset->get_elem_type(); if (t_elem->is_container()) { return "(" + type_to_phpdoc(t_elem) + ")[]"; } else { return type_to_phpdoc(t_elem) + "[]"; } } else if (type->is_list()) { t_list* tlist = static_cast(type); t_type* t_elem = tlist->get_elem_type(); if (t_elem->is_container()) { return "(" + type_to_phpdoc(t_elem) + ")[]"; } else { return type_to_phpdoc(t_elem) + "[]"; } } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_php_generator::display_name() const { return "PHP"; } THRIFT_REGISTER_GENERATOR( php, "PHP", " inlined: Generate PHP inlined files\n" " server: Generate PHP server stubs\n" " oop: Generate PHP with object oriented subclasses\n" " classmap: Generate old-style PHP files (use classmap autoloading)\n" " rest: Generate PHP REST processors\n" " nsglobal=NAME: Set global namespace\n" " validate: Generate PHP validator methods\n" " json: Generate JsonSerializable classes (requires PHP >= 5.4)\n" " getters_setters: Generate Getters and Setters for struct variables\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_xsd_generator.cc0000644000000000000000000002772114370300523025060 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include "thrift/version.h" #include "thrift/platform.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * XSD generator, creates an XSD for the base types etc. * */ class t_xsd_generator : public t_generator { public: t_xsd_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; /* no options yet */ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { throw "unknown option xsd:" + iter->first; } out_dir_base_ = "gen-xsd"; } ~t_xsd_generator() override = default; /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override { (void)tenum; } void generate_service(t_service* tservice) override; void generate_struct(t_struct* tstruct) override; private: void generate_element(std::ostream& out, std::string name, t_type* ttype, t_struct* attrs = nullptr, bool optional = false, bool nillable = false, bool list_element = false); std::string ns(std::string in, std::string ns) { return ns + ":" + in; } std::string xsd(std::string in) { return ns(in, "xsd"); } std::string type_name(t_type* ttype); std::string base_type_name(t_base_type::t_base tbase); virtual std::string xml_autogen_comment() { return std::string("\n"; } /** * Output xsd/php file */ ofstream_with_content_based_conditional_update f_xsd_; ofstream_with_content_based_conditional_update f_php_; /** * Output string stream */ std::ostringstream s_xsd_types_; }; void t_xsd_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); // Make output file string f_php_name = get_out_dir() + program_->get_name() + "_xsd.php"; f_php_.open(f_php_name.c_str()); f_php_ << "" << endl; f_php_.close(); } void t_xsd_generator::generate_typedef(t_typedef* ttypedef) { indent(s_xsd_types_) << "get_name() << "\">" << endl; indent_up(); indent(s_xsd_types_) << "get_type()) << "\" />" << endl; indent_down(); indent(s_xsd_types_) << "" << endl << endl; } void t_xsd_generator::generate_struct(t_struct* tstruct) { vector::const_iterator m_iter; const vector& members = tstruct->get_members(); bool xsd_all = tstruct->get_xsd_all(); indent(s_xsd_types_) << "get_name() << "\">" << endl; indent_up(); if (xsd_all) { indent(s_xsd_types_) << "" << endl; } else { indent(s_xsd_types_) << "" << endl; } indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_element(s_xsd_types_, (*m_iter)->get_name(), (*m_iter)->get_type(), (*m_iter)->get_xsd_attrs(), (*m_iter)->get_xsd_optional() || xsd_all, (*m_iter)->get_xsd_nillable()); } indent_down(); if (xsd_all) { indent(s_xsd_types_) << "" << endl; } else { indent(s_xsd_types_) << "" << endl; } indent_down(); indent(s_xsd_types_) << "" << endl << endl; } void t_xsd_generator::generate_element(ostream& out, string name, t_type* ttype, t_struct* attrs, bool optional, bool nillable, bool list_element) { string sminOccurs = (optional || list_element) ? " minOccurs=\"0\"" : ""; string smaxOccurs = list_element ? " maxOccurs=\"unbounded\"" : ""; string soptional = sminOccurs + smaxOccurs; string snillable = nillable ? " nillable=\"true\"" : ""; if (ttype->is_void() || ttype->is_list()) { indent(out) << "" << endl; indent_up(); if (attrs == nullptr && ttype->is_void()) { indent(out) << "" << endl; } else { indent(out) << "" << endl; indent_up(); if (ttype->is_list()) { indent(out) << "" << endl; indent_up(); string subname; t_type* subtype = ((t_list*)ttype)->get_elem_type(); if (subtype->is_base_type() || subtype->is_container()) { subname = name + "_elt"; } else { subname = type_name(subtype); } f_php_ << "$GLOBALS['" << program_->get_name() << "_xsd_elt_" << name << "'] = '" << subname << "';" << endl; generate_element(out, subname, subtype, nullptr, false, false, true); indent_down(); indent(out) << "" << endl; indent(out) << "" << endl; } if (attrs != nullptr) { const vector& members = attrs->get_members(); vector::const_iterator a_iter; for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) { indent(out) << "get_name() << "\" type=\"" << type_name((*a_iter)->get_type()) << "\" />" << endl; } } indent_down(); indent(out) << "" << endl; } indent_down(); indent(out) << "" << endl; } else { if (attrs == nullptr) { indent(out) << "" << endl; } else { // Wow, all this work for a SIMPLE TYPE with attributes?!?!?! indent(out) << "" << endl; indent_up(); indent(out) << "" << endl; indent_up(); indent(out) << "" << endl; indent_up(); indent(out) << "" << endl; indent_up(); const vector& members = attrs->get_members(); vector::const_iterator a_iter; for (a_iter = members.begin(); a_iter != members.end(); ++a_iter) { indent(out) << "get_name() << "\" type=\"" << type_name((*a_iter)->get_type()) << "\" />" << endl; } indent_down(); indent(out) << "" << endl; indent_down(); indent(out) << "" << endl; indent_down(); indent(out) << "" << endl; indent_down(); indent(out) << "" << endl; } } } void t_xsd_generator::generate_service(t_service* tservice) { // Make output file string f_xsd_name = get_out_dir() + tservice->get_name() + ".xsd"; f_xsd_.open(f_xsd_name.c_str()); string ns = program_->get_namespace("xsd"); const std::map> annot = program_->get_namespace_annotations("xsd"); const std::map>::const_iterator uri = annot.find("uri"); if (uri != annot.end() && !uri->second.empty()) { ns = uri->second.back(); } if (ns.size() > 0) { ns = " targetNamespace=\"" + ns + "\" xmlns=\"" + ns + "\" " + "elementFormDefault=\"qualified\""; } // Print the XSD header f_xsd_ << "" << endl << "" << endl << xml_autogen_comment() << endl; // Print out the type definitions indent(f_xsd_) << s_xsd_types_.str(); // Keep a list of all the possible exceptions that might get thrown map all_xceptions; // List the elements that you might actually get vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string elemname = (*f_iter)->get_name() + "_response"; t_type* returntype = (*f_iter)->get_returntype(); generate_element(f_xsd_, elemname, returntype); f_xsd_ << endl; t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { all_xceptions[(*x_iter)->get_name()] = (t_struct*)((*x_iter)->get_type()); } } map::iterator ax_iter; for (ax_iter = all_xceptions.begin(); ax_iter != all_xceptions.end(); ++ax_iter) { generate_element(f_xsd_, ax_iter->first, ax_iter->second); } // Close the XSD document f_xsd_ << endl << "" << endl; f_xsd_.close(); } string t_xsd_generator::type_name(t_type* ttype) { if (ttype->is_typedef()) { return ttype->get_name(); } if (ttype->is_base_type()) { return xsd(base_type_name(((t_base_type*)ttype)->get_base())); } if (ttype->is_enum()) { return xsd("int"); } if (ttype->is_struct() || ttype->is_xception()) { return ttype->get_name(); } return "container"; } /** * Returns the XSD type that corresponds to the thrift type. * * @param tbase The base type * @return Explicit XSD type, i.e. xsd:string */ string t_xsd_generator::base_type_name(t_base_type::t_base tbase) { switch (tbase) { case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: return "string"; case t_base_type::TYPE_BOOL: return "boolean"; case t_base_type::TYPE_I8: return "byte"; case t_base_type::TYPE_I16: return "short"; case t_base_type::TYPE_I32: return "int"; case t_base_type::TYPE_I64: return "long"; case t_base_type::TYPE_DOUBLE: return "decimal"; default: throw "compiler error: no XSD base type name for base type " + t_base_type::t_base_name(tbase); } } std::string t_xsd_generator::display_name() const { return "XSD"; } THRIFT_REGISTER_GENERATOR(xsd, "XSD", "") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_html_generator.h0000644000000000000000000005720514303740367025102 0ustar00rootroot00000000000000#define BOOTSTRAP_CSS() \ "/*!\n" \ " * Bootstrap v2.0.3\n" \ " *\n" \ " * Copyright 2012 Twitter, Inc\n" \ " * Licensed under the Apache License v2.0\n" \ " * http://www.apache.org/licenses/LICENSE-2.0\n" \ " *\n" \ " * Designed and built with all the love in the world @twitter by @mdo and @fat.\n" \ " */\n" \ ".clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:\"\";}\n" \ ".clearfix:after{clear:both;}\n" \ ".hide-text{font:0/0 " \ "a;color:transparent;text-shadow:none;background-color:transparent;border:0;}\n" \ ".input-block-level{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-" \ "moz-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;}\n" \ "article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}\n" \ "audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}\n" \ "audio:not([controls]){display:none;}\n" \ "html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}\n" \ "a:focus{outline:thin dotted #333;outline:5px auto " \ "-webkit-focus-ring-color;outline-offset:-2px;}\n" \ "a:hover,a:active{outline:0;}\n" \ "sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}\n" \ "sup{top:-0.5em;}\n" \ "sub{bottom:-0.25em;}\n" \ "img{max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}\n" \ "button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}\n" \ "button,input{*overflow:visible;line-height:normal;}\n" \ "button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}\n" \ "button,input[type=\"button\"],input[type=\"reset\"],input[type=\"submit\"]{cursor:pointer;-" \ "webkit-appearance:button;}\n" \ "input[type=\"search\"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:" \ "content-box;-webkit-appearance:textfield;}\n" \ "input[type=\"search\"]::-webkit-search-decoration,input[type=\"search\"]::-webkit-search-" \ "cancel-button{-webkit-appearance:none;}\n" \ "textarea{overflow:auto;vertical-align:top;}\n" \ "body{margin:0;font-family:\"Helvetica " \ "Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#333333;background-" \ "color:#ffffff;}\n" \ "a{color:#0088cc;text-decoration:none;}\n" \ "a:hover{color:#005580;text-decoration:underline;}\n" \ ".row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:\"\";}\n" \ ".row:after{clear:both;}\n" \ "[class*=\"span\"]{float:left;margin-left:20px;}\n" \ ".container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}\n" \ ".span12{width:940px;}\n" \ ".span11{width:860px;}\n" \ ".span10{width:780px;}\n" \ ".span9{width:700px;}\n" \ ".span8{width:620px;}\n" \ ".span7{width:540px;}\n" \ ".span6{width:460px;}\n" \ ".span5{width:380px;}\n" \ ".span4{width:300px;}\n" \ ".span3{width:220px;}\n" \ ".span2{width:140px;}\n" \ ".span1{width:60px;}\n" \ ".offset12{margin-left:980px;}\n" \ ".offset11{margin-left:900px;}\n" \ ".offset10{margin-left:820px;}\n" \ ".offset9{margin-left:740px;}\n" \ ".offset8{margin-left:660px;}\n" \ ".offset7{margin-left:580px;}\n" \ ".offset6{margin-left:500px;}\n" \ ".offset5{margin-left:420px;}\n" \ ".offset4{margin-left:340px;}\n" \ ".offset3{margin-left:260px;}\n" \ ".offset2{margin-left:180px;}\n" \ ".offset1{margin-left:100px;}\n" \ ".row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:\"\";}" \ "\n" \ ".row-fluid:after{clear:both;}\n" \ ".row-fluid " \ "[class*=\"span\"]{display:block;width:100%;min-height:28px;-webkit-box-sizing:border-box;-moz-" \ "box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:" \ "2.127659574%;*margin-left:2.0744680846382977%;}\n" \ ".row-fluid [class*=\"span\"]:first-child{margin-left:0;}\n" \ ".row-fluid .span12{width:99.99999998999999%;*width:99.94680850063828%;}\n" \ ".row-fluid .span11{width:91.489361693%;*width:91.4361702036383%;}\n" \ ".row-fluid .span10{width:82.97872339599999%;*width:82.92553190663828%;}\n" \ ".row-fluid .span9{width:74.468085099%;*width:74.4148936096383%;}\n" \ ".row-fluid .span8{width:65.95744680199999%;*width:65.90425531263828%;}\n" \ ".row-fluid .span7{width:57.446808505%;*width:57.3936170156383%;}\n" \ ".row-fluid .span6{width:48.93617020799999%;*width:48.88297871863829%;}\n" \ ".row-fluid .span5{width:40.425531911%;*width:40.3723404216383%;}\n" \ ".row-fluid .span4{width:31.914893614%;*width:31.8617021246383%;}\n" \ ".row-fluid .span3{width:23.404255317%;*width:23.3510638276383%;}\n" \ ".row-fluid .span2{width:14.89361702%;*width:14.8404255306383%;}\n" \ ".row-fluid .span1{width:6.382978723%;*width:6.329787233638298%;}\n" \ ".container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{" \ "display:table;content:\"\";}\n" \ ".container:after{clear:both;}\n" \ ".container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,." \ "container-fluid:after{display:table;content:\"\";}\n" \ ".container-fluid:after{clear:both;}\n" \ "p{margin:0 0 9px;font-family:\"Helvetica " \ "Neue\",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p " \ "small{font-size:11px;color:#999999;}\n" \ ".lead{margin-bottom:18px;font-size:20px;font-weight:200;line-height:27px;}\n" \ "h1,h2,h3,h4,h5,h6{margin:0;font-family:inherit;font-weight:bold;color:inherit;text-rendering:" \ "optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 " \ "small{font-weight:normal;color:#999999;}\n" \ "h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}\n" \ "h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}\n" \ "h3{font-size:18px;line-height:27px;}h3 small{font-size:14px;}\n" \ "h4,h5,h6{line-height:18px;}\n" \ "h4{font-size:14px;}h4 small{font-size:12px;}\n" \ "h5{font-size:12px;}\n" \ "h6{font-size:11px;color:#999999;text-transform:uppercase;}\n" \ ".page-header{padding-bottom:17px;margin:18px 0;border-bottom:1px solid #eeeeee;}\n" \ ".page-header h1{line-height:1;}\n" \ "ul,ol{padding:0;margin:0 0 9px 25px;}\n" \ "ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}\n" \ "ul{list-style:disc;}\n" \ "ol{list-style:decimal;}\n" \ "li{line-height:18px;}\n" \ "ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}\n" \ "dl{margin-bottom:18px;}\n" \ "dt,dd{line-height:18px;}\n" \ "dt{font-weight:bold;line-height:17px;}\n" \ "dd{margin-left:9px;}\n" \ ".dl-horizontal " \ "dt{float:left;width:120px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;" \ "white-space:nowrap;}\n" \ ".dl-horizontal dd{margin-left:130px;}\n" \ "hr{margin:18px 0;border:0;border-top:1px solid #eeeeee;border-bottom:1px solid #ffffff;}\n" \ "strong{font-weight:bold;}\n" \ "em{font-style:italic;}\n" \ ".muted{color:#999999;}\n" \ "abbr[title]{cursor:help;border-bottom:1px dotted #ddd;}\n" \ "abbr.initialism{font-size:90%;text-transform:uppercase;}\n" \ "blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote " \ "p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}\n" \ "blockquote small{display:block;line-height:18px;color:#999999;}blockquote " \ "small:before{content:'\\2014 \\00A0';}\n" \ "blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid " \ "#eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right " \ "small{text-align:right;}\n" \ "q:before,q:after,blockquote:before,blockquote:after{content:\"\";}\n" \ "address{display:block;margin-bottom:18px;font-style:normal;line-height:18px;}\n" \ "small{font-size:100%;}\n" \ "cite{font-style:normal;}\n" \ "code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,\"Courier " \ "New\",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;" \ "border-radius:3px;}\n" \ "code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}\n" \ "pre{display:block;padding:8.5px;margin:0 0 " \ "9px;font-size:12.025px;line-height:18px;word-break:break-all;word-wrap:break-word;white-space:" \ "pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid " \ "rgba(0, 0, 0, " \ "0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{" \ "margin-bottom:18px;}\n" \ "pre code{padding:0;color:inherit;background-color:transparent;border:0;}\n" \ ".pre-scrollable{max-height:340px;overflow-y:scroll;}\n" \ ".label,.badge{font-size:10.998px;font-weight:bold;line-height:14px;color:#ffffff;vertical-" \ "align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, " \ "0.25);background-color:#999999;}\n" \ ".label{padding:1px 4px " \ "2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}\n" \ ".badge{padding:1px 9px " \ "2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}\n" \ "a.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}\n" \ ".label-important,.badge-important{background-color:#b94a48;}\n" \ ".label-important[href],.badge-important[href]{background-color:#953b39;}\n" \ ".label-warning,.badge-warning{background-color:#f89406;}\n" \ ".label-warning[href],.badge-warning[href]{background-color:#c67605;}\n" \ ".label-success,.badge-success{background-color:#468847;}\n" \ ".label-success[href],.badge-success[href]{background-color:#356635;}\n" \ ".label-info,.badge-info{background-color:#3a87ad;}\n" \ ".label-info[href],.badge-info[href]{background-color:#2d6987;}\n" \ ".label-inverse,.badge-inverse{background-color:#333333;}\n" \ ".label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a;}\n" \ "table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}" \ "\n" \ ".table{width:100%;margin-bottom:18px;}.table th,.table " \ "td{padding:8px;line-height:18px;text-align:left;vertical-align:top;border-top:1px solid " \ "#dddddd;}\n" \ ".table th{font-weight:bold;}\n" \ ".table thead th{vertical-align:bottom;}\n" \ ".table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table " \ "colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table " \ "thead:first-child tr:first-child th,.table thead:first-child tr:first-child " \ "td{border-top:0;}\n" \ ".table tbody+tbody{border-top:2px solid #dddddd;}\n" \ ".table-condensed th,.table-condensed td{padding:4px 5px;}\n" \ ".table-bordered{border:1px solid " \ "#dddddd;border-collapse:separate;*border-collapse:collapsed;border-left:0;-webkit-border-" \ "radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered " \ "td{border-left:1px solid #dddddd;}\n" \ ".table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child " \ "th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead " \ "tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered " \ "colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child " \ "th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child " \ "tr:first-child td{border-top:0;}\n" \ ".table-bordered thead:first-child tr:first-child th:first-child,.table-bordered " \ "tbody:first-child tr:first-child " \ "td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-" \ "radius-topleft:4px;}\n" \ ".table-bordered thead:first-child tr:first-child th:last-child,.table-bordered " \ "tbody:first-child tr:first-child " \ "td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-" \ "radius-topright:4px;}\n" \ ".table-bordered thead:last-child tr:last-child th:first-child,.table-bordered " \ "tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 " \ "4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 " \ "4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-" \ "bottomleft:4px;}\n" \ ".table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child " \ "tr:last-child " \ "td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-" \ "border-radius-bottomright:4px;}\n" \ ".table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) " \ "th{background-color:#f9f9f9;}\n" \ ".table tbody tr:hover td,.table tbody tr:hover th{background-color:#f5f5f5;}\n" \ "table .span1{float:none;width:44px;margin-left:0;}\n" \ "table .span2{float:none;width:124px;margin-left:0;}\n" \ "table .span3{float:none;width:204px;margin-left:0;}\n" \ "table .span4{float:none;width:284px;margin-left:0;}\n" \ "table .span5{float:none;width:364px;margin-left:0;}\n" \ "table .span6{float:none;width:444px;margin-left:0;}\n" \ "table .span7{float:none;width:524px;margin-left:0;}\n" \ "table .span8{float:none;width:604px;margin-left:0;}\n" \ "table .span9{float:none;width:684px;margin-left:0;}\n" \ "table .span10{float:none;width:764px;margin-left:0;}\n" \ "table .span11{float:none;width:844px;margin-left:0;}\n" \ "table .span12{float:none;width:924px;margin-left:0;}\n" \ "table .span13{float:none;width:1004px;margin-left:0;}\n" \ "table .span14{float:none;width:1084px;margin-left:0;}\n" \ "table .span15{float:none;width:1164px;margin-left:0;}\n" \ "table .span16{float:none;width:1244px;margin-left:0;}\n" \ "table .span17{float:none;width:1324px;margin-left:0;}\n" \ "table .span18{float:none;width:1404px;margin-left:0;}\n" \ "table .span19{float:none;width:1484px;margin-left:0;}\n" \ "table .span20{float:none;width:1564px;margin-left:0;}\n" \ "table .span21{float:none;width:1644px;margin-left:0;}\n" \ "table .span22{float:none;width:1724px;margin-left:0;}\n" \ "table .span23{float:none;width:1804px;margin-left:0;}\n" \ "table .span24{float:none;width:1884px;margin-left:0;}" thrift-0.19.0/compiler/cpp/src/thrift/generate/t_erl_generator.cc0000644000000000000000000011760214370300523025042 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const std::string endl = "\n"; // avoid ostream << std::endl flushes /** * Erlang code generator. * */ class t_erl_generator : public t_generator { public: t_erl_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator(program) { (void)option_string; std::map::const_iterator iter; legacy_names_ = false; delimiter_ = "."; app_prefix_ = ""; maps_ = false; export_lines_first_ = true; export_types_lines_first_ = true; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("legacynames") == 0) { legacy_names_ = true; } else if( iter->first.compare("maps") == 0) { maps_ = true; } else if( iter->first.compare("delimiter") == 0) { delimiter_ = iter->second; } else if( iter->first.compare("app_prefix") == 0) { app_prefix_ = iter->second; } else { throw "unknown option erl:" + iter->first; } } out_dir_base_ = "gen-erl"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void generate_member_type(std::ostream& out, t_type* type); void generate_member_value(std::ostream& out, t_type* type, t_const_value* value); std::string render_member_type(t_field* field); std::string render_member_value(t_field* field); std::string render_member_requiredness(t_field* field); // std::string render_default_value(t_type* type); std::string render_default_value(t_field* field); std::string render_const_value(t_type* type, t_const_value* value); std::string render_type_term(t_type* ttype, bool expand_structs, bool extended_info = false); /** * Struct generation code */ void generate_erl_struct(t_struct* tstruct, bool is_exception); void generate_erl_struct_definition(std::ostream& out, t_struct* tstruct); void generate_erl_struct_member(std::ostream& out, t_field* tmember); void generate_erl_struct_info(std::ostream& out, t_struct* tstruct); void generate_erl_extended_struct_info(std::ostream& out, t_struct* tstruct); void generate_erl_function_helpers(t_function* tfunction); void generate_type_metadata(std::string function_name, vector names); void generate_enum_info(t_enum* tenum); void generate_enum_metadata(); void generate_const_function(t_const* tconst, ostringstream& exports, ostringstream& functions); void generate_const_functions(); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_metadata(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_function_info(t_service* tservice, t_function* tfunction); /** * Helper rendering functions */ std::string erl_autogen_comment(); std::string erl_imports(); std::string render_includes(); std::string type_name(t_type* ttype); std::string render_const_list_values(t_type* type, t_const_value* value); std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string type_module(t_type* ttype); std::string make_safe_for_module_name(std::string in) { if (legacy_names_) { return decapitalize(app_prefix_ + in); } else { return underscore(app_prefix_) + underscore(in); } } std::string atomify(std::string in) { if (legacy_names_) { return "'" + decapitalize(in) + "'"; } else { return "'" + in + "'"; } } std::string constify(std::string in) { if (legacy_names_) { return capitalize(in); } else { return uppercase(in); } } static std::string comment(string in); private: bool has_default_value(t_field*); /* if true retain pre 0.9.2 naming scheme for functions, atoms and consts */ bool legacy_names_; /* if true use maps instead of dicts in generated code */ bool maps_; /* delimiter between namespace and record name */ std::string delimiter_; /* used to avoid module name clashes for different applications */ std::string app_prefix_; /** * add function to export list */ void export_function(t_function* tfunction, std::string prefix = ""); void export_string(std::string name, int num); void export_types_string(std::string name, int num); /** * write out headers and footers for hrl files */ void hrl_header(std::ostream& out, std::string name); void hrl_footer(std::ostream& out, std::string name); /** * stuff to spit out at the top of generated files */ bool export_lines_first_; std::ostringstream export_lines_; bool export_types_lines_first_; std::ostringstream export_types_lines_; /** * File streams */ std::ostringstream f_info_; std::ostringstream f_info_ext_; ofstream_with_content_based_conditional_update f_types_file_; ofstream_with_content_based_conditional_update f_types_hrl_file_; ofstream_with_content_based_conditional_update f_consts_file_; ofstream_with_content_based_conditional_update f_consts_hrl_file_; std::ostringstream f_service_; ofstream_with_content_based_conditional_update f_service_file_; ofstream_with_content_based_conditional_update f_service_hrl_; /** * Metadata containers */ std::vector v_struct_names_; std::vector v_enum_names_; std::vector v_exception_names_; std::vector v_enums_; std::vector v_consts_; }; /** * UI for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_erl_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); // setup export lines export_lines_first_ = true; export_types_lines_first_ = true; string program_module_name = make_safe_for_module_name(program_name_); // types files string f_types_name = get_out_dir() + program_module_name + "_types.erl"; string f_types_hrl_name = get_out_dir() + program_module_name + "_types.hrl"; f_types_file_.open(f_types_name.c_str()); f_types_hrl_file_.open(f_types_hrl_name.c_str()); hrl_header(f_types_hrl_file_, program_module_name + "_types"); f_types_file_ << erl_autogen_comment() << endl << "-module(" << program_module_name << "_types)." << endl << erl_imports() << endl; f_types_file_ << "-include(\"" << program_module_name << "_types.hrl\")." << endl << endl; f_types_hrl_file_ << render_includes() << endl; // consts files string f_consts_name = get_out_dir() + program_module_name + "_constants.erl"; string f_consts_hrl_name = get_out_dir() + program_module_name + "_constants.hrl"; f_consts_file_.open(f_consts_name.c_str()); f_consts_hrl_file_.open(f_consts_hrl_name.c_str()); f_consts_file_ << erl_autogen_comment() << endl << "-module(" << program_module_name << "_constants)." << endl << erl_imports() << endl << "-include(\"" << program_module_name << "_types.hrl\")." << endl << endl; f_consts_hrl_file_ << erl_autogen_comment() << endl << erl_imports() << endl << "-include(\"" << program_module_name << "_types.hrl\")." << endl << endl; } /** * Boilerplate at beginning and end of header files */ void t_erl_generator::hrl_header(ostream& out, string name) { out << erl_autogen_comment() << endl << "-ifndef(_" << name << "_included)." << endl << "-define(_" << name << "_included, yeah)." << endl; } void t_erl_generator::hrl_footer(ostream& out, string name) { (void)name; out << "-endif." << endl; } /** * Renders all the imports necessary for including another Thrift program */ string t_erl_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; for (auto include : includes) { result += "-include(\"" + make_safe_for_module_name(include->get_name()) + "_types.hrl\").\n"; } if (includes.size() > 0) { result += "\n"; } return result; } /** * Autogen'd comment */ string t_erl_generator::erl_autogen_comment() { return std::string("%%\n") + "%% Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "%%\n" + "%% DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "%%\n"; } /** * Comment out text */ string t_erl_generator::comment(string in) { size_t pos = 0; in.insert(pos, "%% "); while ((pos = in.find_first_of('\n', pos)) != string::npos) { in.insert(++pos, "%% "); } return in; } /** * Prints standard thrift imports */ string t_erl_generator::erl_imports() { return ""; } /** * Closes the type files */ void t_erl_generator::close_generator() { export_types_string("struct_info", 1); export_types_string("struct_info_ext", 1); export_types_string("enum_info", 1); export_types_string("enum_names", 0); export_types_string("struct_names", 0); export_types_string("exception_names", 0); f_types_file_ << "-export([" << export_types_lines_.str() << "])." << endl << endl; f_types_file_ << f_info_.str(); f_types_file_ << "struct_info(_) -> erlang:error(function_clause)." << endl << endl; f_types_file_ << f_info_ext_.str(); f_types_file_ << "struct_info_ext(_) -> erlang:error(function_clause)." << endl << endl; generate_const_functions(); generate_type_metadata("struct_names", v_struct_names_); generate_enum_metadata(); generate_type_metadata("enum_names", v_enum_names_); generate_type_metadata("exception_names", v_exception_names_); hrl_footer(f_types_hrl_file_, string("BOGUS")); f_types_file_.close(); f_types_hrl_file_.close(); f_consts_file_.close(); f_consts_hrl_file_.close(); } const std::string emit_double_as_string(const double value) { std::stringstream double_output_stream; // sets the maximum precision: http://en.cppreference.com/w/cpp/io/manip/setprecision // sets the output format to fixed: http://en.cppreference.com/w/cpp/io/manip/fixed (not in scientific notation) double_output_stream << std::setprecision(std::numeric_limits::digits10 + 1); #ifdef _MSC_VER // strtod is broken in MSVC compilers older than 2015, so std::fixed fails to format a double literal. // more details: https://blogs.msdn.microsoft.com/vcblog/2014/06/18/ // c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/ // and // http://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/ #if _MSC_VER >= MSC_2015_VER double_output_stream << std::fixed; #else // note that if this function is called from the erlang generator and the MSVC compiler is older than 2015, // the double literal must be output in the scientific format. There can be some cases where the // mantissa of the output does not have fractionals, which is illegal in Erlang. // example => 10000000000000000.0 being output as 1e+16 double_output_stream << std::scientific; #endif #else double_output_stream << std::fixed; #endif double_output_stream << value; return double_output_stream.str(); } void t_erl_generator::generate_type_metadata(std::string function_name, vector names) { size_t num_structs = names.size(); indent(f_types_file_) << function_name << "() ->\n"; indent_up(); indent(f_types_file_) << "["; for(size_t i=0; i < num_structs; i++) { f_types_file_ << names.at(i); if (i < num_structs - 1) { f_types_file_ << ", "; } } f_types_file_ << "].\n\n"; indent_down(); } /** * Generates a typedef. no op * * @param ttypedef The type definition */ void t_erl_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } void t_erl_generator::generate_const_function(t_const* tconst, ostringstream& exports, ostringstream& functions) { t_type* type = get_true_type(tconst->get_type()); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); string const_fun_name = lowercase(name); // Emit const function export. if (exports.tellp() > 0) { exports << ", "; } exports << const_fun_name << "/1, " << const_fun_name << "/2"; // Emit const function definition. map::const_iterator i, end = value->get_map().end(); // The one-argument form throws an error if the key does not exist in the map. for (i = value->get_map().begin(); i != end;) { functions << const_fun_name << "(" << render_const_value(ktype, i->first) << ") -> " << render_const_value(vtype, i->second); ++i; functions << (i != end ? ";\n" : ".\n\n"); } // The two-argument form returns a default value if the key does not exist in the map. for (i = value->get_map().begin(); i != end; ++i) { functions << const_fun_name << "(" << render_const_value(ktype, i->first) << ", _) -> " << render_const_value(vtype, i->second) << ";\n"; } functions << const_fun_name << "(_, Default) -> Default.\n\n"; } else if (type->is_list()) { string const_fun_name = lowercase(name); if (exports.tellp() > 0) { exports << ", "; } exports << const_fun_name << "/1, " << const_fun_name << "/2"; size_t list_size = value->get_list().size(); string rendered_list = render_const_list_values(type, value); functions << const_fun_name << "(N) when N >= 1, N =< " << list_size << " ->\n" << indent_str() << "element(N, {" << rendered_list << "}).\n"; functions << const_fun_name << "(N, _) when N >= 1, N =< " << list_size << " ->\n" << indent_str() << "element(N, {" << rendered_list << "});\n" << const_fun_name << "(_, Default) -> Default.\n\n"; indent_down(); } } void t_erl_generator::generate_const_functions() { ostringstream exports; ostringstream functions; vector::iterator c_iter; for (c_iter = v_consts_.begin(); c_iter != v_consts_.end(); ++c_iter) { generate_const_function(*c_iter, exports, functions); } if (exports.tellp() > 0) { f_consts_file_ << "-export([" << exports.str() << "]).\n\n" << functions.str(); } } /** * Generates code for an enumerated type. Done using a class to scope * the values. * * @param tenum The enumeration */ void t_erl_generator::generate_enum(t_enum* tenum) { vector constants = tenum->get_constants(); vector::iterator c_iter; v_enums_.push_back(tenum); v_enum_names_.push_back(atomify(tenum->get_name())); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); string name = (*c_iter)->get_name(); indent(f_types_hrl_file_) << "-define(" << constify(make_safe_for_module_name(program_name_)) << "_" << constify(tenum->get_name()) << "_" << constify(name) << ", " << value << ")." << endl; } f_types_hrl_file_ << endl; } void t_erl_generator::generate_enum_info(t_enum* tenum){ vector constants = tenum->get_constants(); size_t num_constants = constants.size(); indent(f_types_file_) << "enum_info(" << atomify(tenum->get_name()) << ") ->\n"; indent_up(); indent(f_types_file_) << "[\n"; for(size_t i=0; i < num_constants; i++) { indent_up(); t_enum_value* value = constants.at(i); indent(f_types_file_) << "{" << atomify(value->get_name()) << ", " << value->get_value() << "}"; if (i < num_constants - 1) { f_types_file_ << ",\n"; } indent_down(); } f_types_file_ << "\n"; indent(f_types_file_) << "];\n\n"; indent_down(); } void t_erl_generator::generate_enum_metadata() { size_t enum_count = v_enums_.size(); for(size_t i=0; i < enum_count; i++) { t_enum* tenum = v_enums_.at(i); generate_enum_info(tenum); } indent(f_types_file_) << "enum_info(_) -> erlang:error(function_clause).\n\n"; } /** * Generate a constant value */ void t_erl_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); // Save the tconst so that function can be emitted in generate_const_functions(). v_consts_.push_back(tconst); f_consts_hrl_file_ << "-define(" << constify(make_safe_for_module_name(program_name_)) << "_" << constify(name) << ", " << render_const_value(type, value) << ")." << endl << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_erl_generator::render_const_value(t_type* type, t_const_value* value) { type = get_true_type(type); std::ostringstream out; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << "float(" << value->get_integer() << ")"; } else { out << emit_double_as_string(value->get_double()); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { indent(out) << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { out << "#" << type_name(type) << "{"; const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; bool first = true; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } if (first) { first = false; } else { out << ","; } out << v_iter->first->get_string(); out << " = "; out << render_const_value(field_type, v_iter->second); } indent_down(); indent(out) << "}"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); if (maps_) { out << "maps:from_list(["; } else { out << "dict:from_list(["; } map::const_iterator i, end = value->get_map().end(); for (i = value->get_map().begin(); i != end;) { out << "{" << render_const_value(ktype, i->first) << "," << render_const_value(vtype, i->second) << "}"; if (++i != end) { out << ","; } } out << "])"; } else if (type->is_set()) { t_type* etype = ((t_set*)type)->get_elem_type(); out << "sets:from_list(["; vector::const_iterator i, end = value->get_list().end(); for (i = value->get_list().begin(); i != end;) { out << render_const_value(etype, *i); if (++i != end) { out << ","; } } out << "])"; } else if (type->is_list()) { out << "[" << render_const_list_values(type, value) << "]"; } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out.str(); } string t_erl_generator::render_const_list_values(t_type* type, t_const_value* value) { std::ostringstream out; t_type* etype = ((t_list*)type)->get_elem_type(); bool first = true; const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (first) { first = false; } else { out << ","; } out << render_const_value(etype, *v_iter); } return out.str(); } string t_erl_generator::render_default_value(t_field* field) { t_type* type = field->get_type(); if (type->is_struct() || type->is_xception()) { return "#" + type_name(type) + "{}"; } else if (type->is_map()) { if (maps_) { return "#{}"; } else { return "dict:new()"; } } else if (type->is_set()) { return "sets:new()"; } else if (type->is_list()) { return "[]"; } else { return "undefined"; } } string t_erl_generator::render_member_type(t_field* field) { t_type* type = get_true_type(field->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: return "string() | binary()"; case t_base_type::TYPE_BOOL: return "boolean()"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "integer()"; case t_base_type::TYPE_DOUBLE: return "float()"; default: throw "compiler error: unsupported base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { return "integer()"; } else if (type->is_struct() || type->is_xception()) { return type_name(type) + "()"; } else if (type->is_map()) { if (maps_) { return "map()"; } else { return "dict:dict()"; } } else if (type->is_set()) { return "sets:set()"; } else if (type->is_list()) { return "list()"; } else { throw "compiler error: unsupported type " + type->get_name(); } } string t_erl_generator::render_member_requiredness(t_field* field) { switch (field->get_req()) { case t_field::T_REQUIRED: return "required"; case t_field::T_OPTIONAL: return "optional"; default: return "undefined"; } } /** * Generates a struct */ void t_erl_generator::generate_struct(t_struct* tstruct) { v_struct_names_.push_back(type_name(tstruct)); generate_erl_struct(tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_erl_generator::generate_xception(t_struct* txception) { v_exception_names_.push_back(type_name(txception)); generate_erl_struct(txception, true); } /** * Generates a struct */ void t_erl_generator::generate_erl_struct(t_struct* tstruct, bool is_exception) { (void)is_exception; generate_erl_struct_definition(f_types_hrl_file_, tstruct); generate_erl_struct_info(f_info_, tstruct); generate_erl_extended_struct_info(f_info_ext_, tstruct); } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_erl_generator::generate_erl_struct_definition(ostream& out, t_struct* tstruct) { indent(out) << "%% struct " << type_name(tstruct) << endl << endl; std::stringstream buf; buf << indent() << "-record(" << type_name(tstruct) << ", {"; string field_indent(buf.str().size(), ' '); const vector& members = tstruct->get_members(); for (vector::const_iterator m_iter = members.begin(); m_iter != members.end();) { generate_erl_struct_member(buf, *m_iter); if (++m_iter != members.end()) { buf << "," << endl << field_indent; } } buf << "})."; out << buf.str() << endl; out << "-type " + type_name(tstruct) << "() :: #" + type_name(tstruct) + "{}." << endl << endl; } /** * Generates the record field definition */ void t_erl_generator::generate_erl_struct_member(ostream& out, t_field* tmember) { out << atomify(tmember->get_name()); if (has_default_value(tmember)) out << " = " << render_member_value(tmember); out << " :: " << render_member_type(tmember); if (tmember->get_req() != t_field::T_REQUIRED) out << " | 'undefined'"; } bool t_erl_generator::has_default_value(t_field* field) { t_type* type = field->get_type(); if (!field->get_value()) { if (field->get_req() == t_field::T_REQUIRED) { if (type->is_struct() || type->is_xception() || type->is_map() || type->is_set() || type->is_list()) { return true; } else { return false; } } else { return false; } } else { return true; } } string t_erl_generator::render_member_value(t_field* field) { if (!field->get_value()) { return render_default_value(field); } else { return render_const_value(field->get_type(), field->get_value()); } } /** * Generates the read method for a struct */ void t_erl_generator::generate_erl_struct_info(ostream& out, t_struct* tstruct) { indent(out) << "struct_info(" << type_name(tstruct) << ") ->" << endl; indent_up(); out << indent() << render_type_term(tstruct, true) << ";" << endl; indent_down(); out << endl; } void t_erl_generator::generate_erl_extended_struct_info(ostream& out, t_struct* tstruct) { indent(out) << "struct_info_ext(" << type_name(tstruct) << ") ->" << endl; indent_up(); out << indent() << render_type_term(tstruct, true, true) << ";" << endl; indent_down(); out << endl; } /** * Generates a thrift service. * * @param tservice The service definition */ void t_erl_generator::generate_service(t_service* tservice) { service_name_ = make_safe_for_module_name(service_name_); string f_service_hrl_name = get_out_dir() + service_name_ + "_thrift.hrl"; string f_service_name = get_out_dir() + service_name_ + "_thrift.erl"; f_service_file_.open(f_service_name.c_str()); f_service_hrl_.open(f_service_hrl_name.c_str()); // Reset service text aggregating stream streams f_service_.str(""); export_lines_.str(""); export_lines_first_ = true; hrl_header(f_service_hrl_, service_name_); if (tservice->get_extends() != nullptr) { f_service_hrl_ << "-include(\"" << make_safe_for_module_name(tservice->get_extends()->get_name()) << "_thrift.hrl\"). % inherit " << endl; } f_service_hrl_ << "-include(\"" << make_safe_for_module_name(program_name_) << "_types.hrl\")." << endl << endl; // Generate the three main parts of the service (well, two for now in PHP) generate_service_helpers(tservice); // cpiro: New Erlang Order generate_service_interface(tservice); generate_service_metadata(tservice); // indent_down(); f_service_file_ << erl_autogen_comment() << endl << "-module(" << service_name_ << "_thrift)." << endl << "-behaviour(thrift_service)." << endl << endl << erl_imports() << endl; f_service_file_ << "-include(\"" << make_safe_for_module_name(tservice->get_name()) << "_thrift.hrl\")." << endl << endl; f_service_file_ << "-export([" << export_lines_.str() << "])." << endl << endl; f_service_file_ << f_service_.str(); hrl_footer(f_service_hrl_, f_service_name); // Close service file f_service_file_.close(); f_service_hrl_.close(); } void t_erl_generator::generate_service_metadata(t_service* tservice) { export_string("function_names", 0); vector functions = tservice->get_functions(); size_t num_functions = functions.size(); indent(f_service_) << "function_names() -> " << endl; indent_up(); indent(f_service_) << "["; for (size_t i=0; i < num_functions; i++) { t_function* current = functions.at(i); f_service_ << atomify(current->get_name()); if (i < num_functions - 1) { f_service_ << ", "; } } f_service_ << "].\n\n"; indent_down(); } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_erl_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; // indent(f_service_) << // "% HELPER FUNCTIONS AND STRUCTURES" << endl << endl; export_string("struct_info", 1); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_erl_function_helpers(*f_iter); } f_service_ << "struct_info(_) -> erlang:error(function_clause)." << endl; } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_erl_generator::generate_erl_function_helpers(t_function* tfunction) { (void)tfunction; } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_erl_generator::generate_service_interface(t_service* tservice) { export_string("function_info", 2); vector functions = tservice->get_functions(); vector::iterator f_iter; f_service_ << "%%% interface" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << indent() << "% " << function_signature(*f_iter) << endl; generate_function_info(tservice, *f_iter); } // Inheritance - pass unknown functions to base class if (tservice->get_extends() != nullptr) { indent(f_service_) << "function_info(Function, InfoType) ->" << endl; indent_up(); indent(f_service_) << make_safe_for_module_name(tservice->get_extends()->get_name()) << "_thrift:function_info(Function, InfoType)." << endl; indent_down(); } else { // return function_clause error for non-existent functions indent(f_service_) << "function_info(_Func, _Info) -> erlang:error(function_clause)." << endl; } indent(f_service_) << endl; } /** * Generates a function_info(FunctionName, params_type) and * function_info(FunctionName, reply_type) */ void t_erl_generator::generate_function_info(t_service* tservice, t_function* tfunction) { (void)tservice; string name_atom = atomify(tfunction->get_name()); t_struct* xs = tfunction->get_xceptions(); t_struct* arg_struct = tfunction->get_arglist(); // function_info(Function, params_type): indent(f_service_) << "function_info(" << name_atom << ", params_type) ->" << endl; indent_up(); indent(f_service_) << render_type_term(arg_struct, true) << ";" << endl; indent_down(); // function_info(Function, reply_type): indent(f_service_) << "function_info(" << name_atom << ", reply_type) ->" << endl; indent_up(); if (!tfunction->get_returntype()->is_void()) indent(f_service_) << render_type_term(tfunction->get_returntype(), false) << ";" << endl; else if (tfunction->is_oneway()) indent(f_service_) << "oneway_void;" << endl; else indent(f_service_) << "{struct, []}" << ";" << endl; indent_down(); // function_info(Function, exceptions): indent(f_service_) << "function_info(" << name_atom << ", exceptions) ->" << endl; indent_up(); indent(f_service_) << render_type_term(xs, true) << ";" << endl; indent_down(); } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_erl_generator::function_signature(t_function* tfunction, string prefix) { return prefix + tfunction->get_name() + "(This" + capitalize(argument_list(tfunction->get_arglist())) + ")"; } /** * Add a function to the exports list */ void t_erl_generator::export_string(string name, int num) { if (export_lines_first_) { export_lines_first_ = false; } else { export_lines_ << ", "; } export_lines_ << name << "/" << num; } void t_erl_generator::export_types_string(string name, int num) { if (export_types_lines_first_) { export_types_lines_first_ = false; } else { export_types_lines_ << ", "; } export_types_lines_ << name << "/" << num; } void t_erl_generator::export_function(t_function* tfunction, string prefix) { t_struct::members_type::size_type num = tfunction->get_arglist()->get_members().size(); if (num > static_cast(std::numeric_limits().max())) { throw "integer overflow in t_erl_generator::export_function, name " + tfunction->get_name(); } export_string(prefix + tfunction->get_name(), 1 // This + static_cast(num)); } /** * Renders a field list */ string t_erl_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; result += ", "; // initial comma to compensate for initial This } else { result += ", "; } result += capitalize((*f_iter)->get_name()); } return result; } string t_erl_generator::type_name(t_type* ttype) { string prefix = ttype->get_program()->get_namespace("erl"); size_t prefix_length = prefix.length(); if (prefix_length > 0 && prefix[prefix_length - 1] != '_') { size_t delimiter_length = delimiter_.length(); if (delimiter_length > 0 && delimiter_length < prefix_length) { bool not_match = prefix.compare(prefix_length - delimiter_length, prefix_length, delimiter_) != 0; if (not_match) { prefix += delimiter_; } } } string name = ttype->get_name(); return atomify(prefix + name); } /** * Converts the parse type to a Erlang "type" (macro for int constants) */ string t_erl_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "?tType_STRING"; case t_base_type::TYPE_BOOL: return "?tType_BOOL"; case t_base_type::TYPE_I8: return "?tType_I8"; case t_base_type::TYPE_I16: return "?tType_I16"; case t_base_type::TYPE_I32: return "?tType_I32"; case t_base_type::TYPE_I64: return "?tType_I64"; case t_base_type::TYPE_DOUBLE: return "?tType_DOUBLE"; default: break; } } else if (type->is_enum()) { return "?tType_I32"; } else if (type->is_struct() || type->is_xception()) { return "?tType_STRUCT"; } else if (type->is_map()) { return "?tType_MAP"; } else if (type->is_set()) { return "?tType_SET"; } else if (type->is_list()) { return "?tType_LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** * Generate an Erlang term which represents a thrift type */ std::string t_erl_generator::render_type_term(t_type* type, bool expand_structs, bool extended_info) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "string"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "byte"; case t_base_type::TYPE_I16: return "i16"; case t_base_type::TYPE_I32: return "i32"; case t_base_type::TYPE_I64: return "i64"; case t_base_type::TYPE_DOUBLE: return "double"; default: break; } } else if (type->is_enum()) { return "i32"; } else if (type->is_struct() || type->is_xception()) { if (expand_structs) { std::stringstream buf; buf << "{struct, ["; string field_indent(buf.str().size(), ' '); t_struct::members_type const& fields = static_cast(type)->get_members(); t_struct::members_type::const_iterator i, end = fields.end(); for (i = fields.begin(); i != end;) { t_struct::members_type::value_type member = *i; int32_t key = member->get_key(); string type = render_type_term(member->get_type(), false, false); // recursive call if (!extended_info) { // Convert to format: {struct, [{Fid, Type}|...]} buf << "{" << key << ", " << type << "}"; } else { // Convert to format: {struct, [{Fid, Req, Type, Name, Def}|...]} string name = member->get_name(); string value = render_member_value(member); string requiredness = render_member_requiredness(member); buf << "{" << key << ", " << requiredness << ", " << type << ", " << atomify(name) << ", " << value << "}"; } if (++i != end) { buf << "," << endl << field_indent; } } buf << "]}" << endl; return buf.str(); } else { return "{struct, {" + atomify(type_module(type)) + ", " + type_name(type) + "}}"; } } else if (type->is_map()) { // {map, KeyType, ValType} t_type* key_type = ((t_map*)type)->get_key_type(); t_type* val_type = ((t_map*)type)->get_val_type(); return "{map, " + render_type_term(key_type, false) + ", " + render_type_term(val_type, false) + "}"; } else if (type->is_set()) { t_type* elem_type = ((t_set*)type)->get_elem_type(); return "{set, " + render_type_term(elem_type, false) + "}"; } else if (type->is_list()) { t_type* elem_type = ((t_list*)type)->get_elem_type(); return "{list, " + render_type_term(elem_type, false) + "}"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_erl_generator::type_module(t_type* ttype) { return make_safe_for_module_name(ttype->get_program()->get_name()) + "_types"; } std::string t_erl_generator::display_name() const { return "Erlang"; } THRIFT_REGISTER_GENERATOR( erl, "Erlang", " legacynames: Output files retain naming conventions of Thrift 0.9.1 and earlier.\n" " delimiter= Delimiter between namespace prefix and record name. Default is '.'.\n" " app_prefix= Application prefix for generated Erlang files.\n" " maps: Generate maps instead of dicts.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_netstd_generator.h0000644000000000000000000002566414370300523025431 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::set; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes static const string DEEP_COPY_METHOD_NAME = "DeepCopy"; static const string CANCELLATION_TOKEN_NAME = "cancellationToken"; class t_netstd_generator : public t_oop_generator { struct member_mapping_scope { public: member_mapping_scope() : scope_member(0) { } void* scope_member; map mapping_table; }; public: t_netstd_generator(t_program* program, const map& parsed_options, const string& option_string); bool is_wcf_enabled() const; bool is_hashcode_enabled() const; bool is_serialize_enabled() const; bool is_union_enabled() const; // overrides void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(vector consts) override; void generate_consts(ostream& out, vector consts); void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_enum(ostream& out, t_enum* tenum); void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; // additional files void generate_extensions_file(); void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); void generate_netstd_property(ostream& out, t_field* tfield, bool isPublic, bool includeIsset = true, string fieldPrefix = ""); bool print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval = false, bool needtype = false); string render_const_value(ostream& out, string name, t_type* type, t_const_value* value); void print_const_constructor(ostream& out, vector consts); void print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value); void generate_netstd_struct(t_struct* tstruct, bool is_exception); void generate_netstd_union(t_struct* tunion); void generate_netstd_struct_definition(ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false); void generate_netstd_union_definition(ostream& out, t_struct* tunion); void generate_netstd_union_class(ostream& out, t_struct* tunion, t_field* tfield); void generate_netstd_wcffault(ostream& out, t_struct* tstruct); void generate_netstd_deepcopy_method(ostream& out, t_struct* tstruct, std::string sharp_struct_name); void generate_netstd_struct_reader(ostream& out, t_struct* tstruct); void generate_netstd_struct_result_writer(ostream& out, t_struct* tstruct); void generate_netstd_struct_writer(ostream& out, t_struct* tstruct); void generate_netstd_struct_tostring(ostream& out, t_struct* tstruct); void generate_netstd_struct_equals(ostream& out, t_struct* tstruct); void generate_netstd_struct_hashcode(ostream& out, t_struct* tstruct); void generate_netstd_union_reader(ostream& out, t_struct* tunion); void generate_function_helpers(ostream& out, t_function* tfunction); void generate_service_interface(ostream& out, t_service* tservice); void generate_deprecation_attribute(ostream& out, t_function* func); void generate_service_helpers(ostream& out, t_service* tservice); void generate_service_client(ostream& out, t_service* tservice); void generate_service_server(ostream& out, t_service* tservice); void generate_process_function_async(ostream& out, t_service* tservice, t_function* function); void generate_deserialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_propertyless = false); void generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix = ""); void generate_deserialize_container(ostream& out, t_type* ttype, string prefix = ""); void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix = ""); void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix = ""); void generate_deserialize_list_element(ostream& out, t_list* list, string prefix = ""); void generate_serialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_propertyless = false, bool allow_nullable = true); void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix = ""); void generate_serialize_container(ostream& out, t_type* ttype, string prefix = ""); void generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map); void generate_serialize_set_element(ostream& out, t_set* tmap, string iter); void generate_serialize_list_element(ostream& out, t_list* tlist, string iter); void generate_netstd_doc(ostream& out, t_field* field); void generate_netstd_doc(ostream& out, t_doc* tdoc); void generate_netstd_doc(ostream& out, t_function* tdoc); void generate_netstd_docstring_comment(ostream& out, string contents); void docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end); void start_netstd_namespace(ostream& out); void end_netstd_namespace(ostream& out); string netstd_type_usings() const; string netstd_thrift_usings() const; static const int MODE_FULL_DECL = 0x00; static const int MODE_NO_RETURN = 0x01; static const int MODE_NO_ARGS = 0x02; string type_name(t_type* ttype, bool with_namespace = true); string base_type_name(t_base_type* tbase); string declare_field(t_field* tfield, bool init = false, bool allow_nullable = true, string prefix = ""); string function_signature_async(t_function* tfunction, string prefix = "", int mode = MODE_FULL_DECL); string function_signature(t_function* tfunction, string prefix = ""); string argument_list(t_struct* tstruct, bool with_types = true); string type_to_enum(t_type* ttype); string prop_name(t_field* tfield, bool suppress_mapping = false); string func_name(t_function* tfunc, bool suppress_mapping = false); string func_name(std::string fname, bool suppress_mapping = false); string convert_to_pascal_case(const string& str); string get_enum_class_name(t_type* type) override; protected: std::string autogen_comment() override { string comment = "/**\n"; if( ! use_net6_features) { comment += " * \n"; } comment += " * " + autogen_summary() + "\n"; comment += " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"; if( ! use_net6_features) { comment += " * \n"; } comment += " */\n"; return comment; } private: string namespace_name_; string namespace_dir_; bool union_; bool hashcode_; bool serialize_; bool wcf_; bool use_pascal_case_properties; bool suppress_deepcopy; bool use_net6_features; bool add_async_postfix; const std::string CSHARP_KEYWORDS[101] = { // C# keywords "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while", // C# contextual keywords "add", "alias", "ascending", "async", "await", "descending", "dynamic", "from", "get", "global", "group", "into", "join", "let", "orderby", "partial", "remove", "select", "set", "value", "var", "when", "where", "yield" }; string wcf_namespace_; std::set netstd_keywords = std::set(CSHARP_KEYWORDS, CSHARP_KEYWORDS + sizeof(CSHARP_KEYWORDS) / sizeof(CSHARP_KEYWORDS[0])); vector member_mapping_scopes; map collected_extension_types; map checked_extension_types; string normalize_name(string name, bool is_arg_name = false); string make_valid_csharp_identifier(string const& fromName); string make_csharp_string_literal( string const& value); void prepare_member_name_mapping(t_service* tservice); void prepare_member_name_mapping(t_struct* tstruct); void prepare_member_name_mapping(t_struct* scope, const vector& members, const string& structname); void prepare_member_name_mapping(t_service* scope, const vector& members, const string& structname); void cleanup_member_name_mapping(void* scope); string get_mapped_member_name(string oldname); string get_isset_name(const string& str); string get_deep_copy_method_call(t_type* ttype, bool is_not_null, bool& needs_typecast, string& suffix); void collect_extensions_types(t_struct* tstruct); void collect_extensions_types(t_type* ttype); void generate_extensions(ostream& out, map types); void reset_indent(); void generate_null_check_begin(ostream& out, t_field* tfield); void generate_null_check_end(ostream& out, t_field* tfield); string initialize_field(t_field* tfield); void pragmas_and_directives(ostream& out); bool is_nullable_type(t_type* ttype); bool force_member_nullable(t_field* tfield); // see there string nullable_suffix(); // unconditionally string nullable_field_suffix(t_field* tfield); // depends on field type string nullable_field_suffix(t_type* ttype); // depends on field type string nullable_value_access(t_type* ttype); // depends on field type }; thrift-0.19.0/compiler/cpp/src/thrift/generate/t_delphi_generator.cc0000644000000000000000000045653214370300523025535 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" #ifdef _WIN32 #include #include #include #include #endif using std::map; using std::set; using std::ofstream; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes class t_delphi_generator : public t_oop_generator { public: t_delphi_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_oop_generator(program) { (void)option_string; indent_impl_ = 0; has_forward = false; has_enum = false; has_const = false; std::map::const_iterator iter; ansistr_binary_ = false; register_types_ = false; constprefix_ = false; old_names_ = false; events_ = false; xmldoc_ = false; async_ = false; com_types_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("ansistr_binary") == 0) { ansistr_binary_ = true; } else if( iter->first.compare("register_types") == 0) { register_types_ = true; } else if( iter->first.compare("old_names") == 0) { old_names_ = true; } else if( iter->first.compare("constprefix") == 0) { constprefix_ = true; } else if( iter->first.compare("events") == 0) { events_ = true; } else if( iter->first.compare("xmldoc") == 0) { xmldoc_ = true; } else if( iter->first.compare("async") == 0) { async_ = true; } else if( iter->first.compare("com_types") == 0) { com_types_ = true; } else { throw "unknown option delphi:" + iter->first; } } if(com_types_ && ansistr_binary_) { throw "com_types and ansistr_binary are mutually exclusive"; } out_dir_base_ = "gen-delphi"; escape_.clear(); escape_['\''] = "''"; } void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(std::vector consts) override; void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_forward_declaration(t_struct* tstruct) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception); void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic); void generate_delphi_property(ostream& out, bool struct_is_exception, t_field* tfield, bool isPublic, std::string fieldPrefix = ""); void generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception); void generate_delphi_property_reader_definition(ostream& out, t_field* tfield, bool is_xception_class); void generate_delphi_property_writer_definition(ostream& out, t_field* tfield, bool is_xception_class); void generate_delphi_property_reader_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class); void generate_delphi_property_writer_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factory_name); void generate_delphi_clear_union_value(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factory_name); void generate_delphi_isset_reader_writer_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception); void generate_delphi_struct_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory); void generate_delphi_struct_result_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory); void generate_delphi_struct_tostring_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory); void add_delphi_uses_list(string unitname); void generate_delphi_struct_reader_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory); void generate_delphi_create_exception_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception); bool const_needs_var(t_type* type); void print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value); void print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value); void print_const_value(std::ostream& vars, std::ostream& out, std::string name, t_type* type, t_const_value* value); void initialize_field(std::ostream& vars, std::ostream& out, std::string name, t_type* type, t_const_value* value); void finalize_field(std::ostream& out, std::string name, t_type* type, t_const_value* value, std::string cls_nm = ""); std::string render_const_value(std::ostream& local_vars, std::ostream& out, std::string name, t_type* type, t_const_value* value); void print_const_def_value(std::ostream& vars, std::ostream& out, std::string name, t_type* type, t_const_value* value, std::string cls_nm = ""); std::string make_constants_classname(); void generate_delphi_struct(t_struct* tstruct, bool is_exception); void generate_delphi_struct_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result = false, bool is_x_factory = false); void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct); void generate_delphi_struct_type_factory(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result = false, bool is_x_factory = false); void generate_delphi_struct_type_factory_registration(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result = false, bool is_x_factory = false); void generate_delphi_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false, bool is_x_factory = false); void generate_delphi_struct_reader(std::ostream& out, t_struct* tstruct); void generate_delphi_struct_result_writer(std::ostream& out, t_struct* tstruct); void generate_delphi_struct_writer(std::ostream& out, t_struct* tstruct); void generate_delphi_struct_tostring(std::ostream& out, t_struct* tstruct); void generate_function_helpers(t_function* tfunction); void generate_service_interface(t_service* tservice); void generate_service_interface(t_service* tservice, bool for_async); void generate_guid(std::ostream& out); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* function); void generate_deserialize_field(std::ostream& out, bool is_xception, t_field* tfield, std::string prefix, std::ostream& local_vars); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string name, std::string prefix); void generate_deserialize_container(ostream& out, bool is_xception, t_type* ttype, string name, std::ostream& local_vars); void generate_deserialize_set_element(std::ostream& out, bool is_xception, t_set* tset, std::string prefix, std::ostream& local_vars); void generate_deserialize_map_element(std::ostream& out, bool is_xception, t_map* tmap, std::string prefix, std::ostream& local_vars); void generate_deserialize_list_element(std::ostream& out, bool is_xception, t_list* list, std::string prefix, std::ostream& local_vars); void generate_serialize_field(std::ostream& out, bool is_xception, t_field* tfield, std::string prefix, std::ostream& local_vars); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix, std::ostream& local_vars); void generate_serialize_container(std::ostream& out, bool is_xception, t_type* ttype, std::string prefix, std::ostream& local_vars); void generate_serialize_map_element(std::ostream& out, bool is_xception, t_map* tmap, std::string iter, std::string map, std::ostream& local_vars); void generate_serialize_set_element(std::ostream& out, bool is_xception, t_set* tmap, std::string iter, std::ostream& local_vars); void generate_serialize_list_element(std::ostream& out, bool is_xception, t_list* tlist, std::string iter, std::ostream& local_vars); void delphi_type_usings(std::ostream& out); std::string delphi_thrift_usings(); std::string type_name(t_type* ttype, bool b_cls = false, bool b_no_postfix = false, bool b_exception_factory = false, bool b_full_exception_factory = false); std::string normalize_clsnm(std::string name, std::string prefix, bool b_no_check_keyword = false); std::string make_valid_delphi_identifier(std::string const& fromName); std::string make_pascal_string_literal( std::string value); std::string input_arg_prefix(t_type* ttype); std::string base_type_name(t_base_type* tbase); std::string declare_field(t_field* tfield, bool init = false, std::string prefix = "", bool is_xception_class = false); std::string function_signature(t_function* tfunction, bool for_async, std::string full_cls = "", bool is_xception = false); std::string argument_list(t_struct* tstruct); std::string constructor_argument_list(t_struct* tstruct, std::string current_indent); std::string type_to_enum(t_type* ttype); std::string prop_name(t_field* tfield, bool is_xception = false, std::string prefix = ""); std::string prop_name(std::string name, bool is_xception = false, std::string prefix = ""); std::string constructor_param_name(string name); void write_enum(std::string line); void write_forward_decr(std::string line); void write_const(std::string line); void write_struct(std::string line); void write_service(std::string line); std::string autogen_comment() override { return std::string("(**\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + " *)\n"; } string replace_all(string contents, string search, string replace); string xml_encode(string contents); string xmldoc_encode(string contents); string xmlattrib_encode(string contents); void generate_delphi_doc(std::ostream& out, t_field* field); void generate_delphi_doc(std::ostream& out, t_doc* tdoc); void generate_delphi_doc(std::ostream& out, t_function* tdoc); void generate_delphi_docstring_comment(std::ostream& out, string contents); bool type_can_be_null(t_type* ttype) { while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } return ttype->is_container() || ttype->is_struct() || ttype->is_xception(); } private: std::string namespace_name_; std::ostringstream s_forward_decr; std::ostringstream s_enum; std::ostringstream s_const; std::ostringstream s_struct; std::ostringstream s_service; std::ostringstream s_const_impl; std::ostringstream s_struct_impl; std::ostringstream s_service_impl; std::ostringstream s_type_factory_registration; std::ostringstream s_type_factory_funcs; bool has_forward; bool has_enum; bool has_const; std::string namespace_dir_; std::set types_known; std::list typedefs_pending; std::vector uses_list; std::string empty_value(t_type* type); const std::string DELPHI_KEYWORDS[81] = { // keywords "and", "array", "as", "asm", "at", "automated", "begin", "case", "class", "const", "constructor", "destructor", "dispinterface", "div", "do", "downto", "else", "end", "except", "exports", "file", "finalization", "finally", "for", "function", "goto", "if", "implementation", "in", "inherited", "initialization", "inline", "interface", "is", "label", "library", "mod", "nil", "not", "object", "of", "on", "or", "out", "packed", "private", "procedure", "program", "property", "protected", "public", "published", "raise", "record", "repeat", "resourcestring", "set", "shl", "shr", "string", "then", "threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while", "with", "xor", // predefined types (lowercase!) "ansistring", "boolean", "double", "int64", "integer", "shortint", "smallint", "string", "unicodestring" }; // reserved variables and types (lowercase!) const std::string DELPHI_RESERVED_NAMES[8] = { "result", "system", "sysutils", "tbytes", "tclass", "thrift", "tinterfacedobject", "tobject" }; // reserved method names (lowercase!) const std::string DELPHI_RESERVED_METHOD[31] = { "afterconstruction", "beforedestruction", "classinfo", "classname", "classnameis", "classparent", "classtype", "cleanupinstance", "create", "defaulthandler", "destroy", "dispatch", "equals", "fieldaddress", "free", "freeinstance", "gethashcode", "getinterface", "getinterfaceentry", "getinterfacetable", "inheritsfrom", "initinstance", "instancesize", "methodaddress", "methodname", "newinstance", "read", "safecallexception", "tostring", "unitname", "write" }; // reserved exception class method names (lowercase!) const std::string DELPHI_RESERVED_METHOD_EXCEPTION[23] = { "setinnerexception", "setstackinfo", "getstacktrace", "raisingexception", "createfmt", "createres", "createresfmt", "createhelp", "createfmthelp", "createreshelp", "createresfmthelp", "getbaseexception", "baseexception", "helpcontext", "innerexception", "message", "stacktrace", "stackinfo", "getexceptionstackinfoproc", "getstackinfostringproc", "cleanupstackinfoproc", "raiseouterexception", "throwouterexception" }; // TODO: put all into one map, value=flags tells what it is std::set delphi_keywords = std::set(DELPHI_KEYWORDS, DELPHI_KEYWORDS + sizeof(DELPHI_KEYWORDS) / sizeof(DELPHI_KEYWORDS[0])); std::set delphi_reserved_names = std::set(DELPHI_RESERVED_NAMES, DELPHI_RESERVED_NAMES + sizeof(DELPHI_RESERVED_NAMES) / sizeof(DELPHI_RESERVED_NAMES[0])); std::set delphi_reserved_method = std::set(DELPHI_RESERVED_METHOD, DELPHI_RESERVED_METHOD + sizeof(DELPHI_RESERVED_METHOD) / sizeof(DELPHI_RESERVED_METHOD[0])); std::set delphi_reserved_method_exception = std::set(DELPHI_RESERVED_METHOD_EXCEPTION, DELPHI_RESERVED_METHOD_EXCEPTION + sizeof(DELPHI_RESERVED_METHOD_EXCEPTION) / sizeof(DELPHI_RESERVED_METHOD_EXCEPTION[0])); bool find_keyword(std::set& keywords, std::string name); std::string normalize_name(std::string name, bool b_method = false, bool b_exception_method = false, bool b_force_underscore = false); bool is_fully_defined_type(t_type* ttype); void add_defined_type(t_type* ttype); void init_known_types_list(); bool is_void(t_type* type); int indent_impl_; bool ansistr_binary_; bool register_types_; bool constprefix_; bool old_names_; bool events_; bool xmldoc_; bool async_; bool com_types_; void indent_up_impl() { ++indent_impl_; }; void indent_down_impl() { --indent_impl_; }; std::string indent_impl() { std::string ind = ""; int i; for (i = 0; i < indent_impl_; ++i) { ind += " "; } return ind; }; std::ostream& indent_impl(std::ostream& os) { return os << indent_impl(); }; }; string t_delphi_generator::replace_all(string contents, string search, string repl) { string str(contents); size_t slen = search.length(); size_t rlen = repl.length(); size_t incr = (rlen > 0) ? rlen : 1; if (slen > 0) { size_t found = str.find(search); while ((found != string::npos) && (found < str.length())) { str.replace(found, slen, repl); found = str.find(search, found + incr); } } return str; } // XML encoding string t_delphi_generator::xml_encode(string contents) { string str(contents); // escape the escape str = replace_all(str, "&", "&"); // other standard XML entities str = replace_all(str, "<", "<"); str = replace_all(str, ">", ">"); return str; } // XML attribute encoding string t_delphi_generator::xmlattrib_encode(string contents) { string str(xml_encode(contents)); // our attribs are enclosed in " str = replace_all(str, "\"", "\\\""); return str; } // XML encoding for doc comments string t_delphi_generator::xmldoc_encode(string contents) { string str(xml_encode(contents)); // XMLDoc specific: convert linebreaks into graphs str = replace_all(str, "\r\n", "\r"); str = replace_all(str, "\n", "\r"); str = replace_all(str, "\r", "\n"); return str; } void t_delphi_generator::generate_delphi_docstring_comment(ostream& out, string contents) { if (xmldoc_) { generate_docstring_comment(out, "{$REGION 'XMLDoc'}/// \n", "/// ", "" + contents + "", "/// \n{$ENDREGION}\n"); } } void t_delphi_generator::generate_delphi_doc(ostream& out, t_field* field) { if (xmldoc_) { if (field->get_type()->is_enum()) { string combined_message = xmldoc_encode(field->get_doc()) + "\nget_type())) + "\"/>"; generate_delphi_docstring_comment(out, combined_message); } else { generate_delphi_doc(out, (t_doc*)field); } } } void t_delphi_generator::generate_delphi_doc(ostream& out, t_doc* tdoc) { if (tdoc->has_doc() && xmldoc_) { generate_delphi_docstring_comment(out, xmldoc_encode(tdoc->get_doc())); } } void t_delphi_generator::generate_delphi_doc(ostream& out, t_function* tfunction) { if (tfunction->has_doc() && xmldoc_) { stringstream ps; const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ps << "\nget_name()) << "\">"; if (p->has_doc()) { std::string str = p->get_doc(); str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); // remove the newlines that appear from the parser ps << xmldoc_encode(str); } ps << ""; } generate_docstring_comment(out, "{$REGION 'XMLDoc'}", "/// ", "" + xmldoc_encode(tfunction->get_doc()) + "" + ps.str(), "{$ENDREGION}\n"); } } bool t_delphi_generator::find_keyword(std::set& keywords, std::string name) { std::string::size_type len = name.length(); if (len <= 0) { return false; } std::string::size_type nlast = name.find_last_of('_'); if (nlast >= 1) { if (nlast == (len - 1)) { string new_name(name, 0, nlast); return find_keyword(keywords, new_name); } } return (keywords.find(name) != keywords.end()); } std::string t_delphi_generator::normalize_name(std::string name, bool b_method, bool b_exception_method, bool b_force_underscore) { string tmp(name); std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(std::tolower)); bool b_reserved = false; bool b_keyword = false; if (find_keyword(delphi_keywords, tmp)) { b_keyword = true; } else if (find_keyword(delphi_reserved_names, tmp)) { b_reserved = true; } else if (b_method && find_keyword(delphi_reserved_method, tmp)) { b_reserved = true; } else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) { b_reserved = true; } // neither reserved nor keyword? if (!(b_reserved || b_keyword)) { return name; } // apply the rule: old style '_' postfix or more modern '&' prefix? // underscore always on non-keywords or when explicitly asked via arg if( (!b_keyword) || old_names_ || b_force_underscore) { return name + "_"; } else { return "&" + name; } } void t_delphi_generator::add_delphi_uses_list(string unitname) { vector::const_iterator s_iter; bool found = false; for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) { if ((*s_iter) == unitname) { found = true; break; } } if (!found) { uses_list.push_back(unitname); } } void t_delphi_generator::init_generator() { indent_impl_ = 0; namespace_name_ = program_->get_namespace("delphi"); has_forward = false; has_enum = false; has_const = false; add_delphi_uses_list("Classes"); add_delphi_uses_list("SysUtils"); add_delphi_uses_list("Generics.Collections"); if(async_) { add_delphi_uses_list("System.Threading"); } add_delphi_uses_list("Thrift"); add_delphi_uses_list("Thrift.Utils"); add_delphi_uses_list("Thrift.Collections"); add_delphi_uses_list("Thrift.Protocol"); add_delphi_uses_list("Thrift.Transport"); if (register_types_) { add_delphi_uses_list("Thrift.TypeRegistry"); } init_known_types_list(); string unitname, nsname; const vector& includes = program_->get_includes(); for (auto include : includes) { unitname = include->get_name(); nsname = include->get_namespace("delphi"); if ("" != nsname) { unitname = normalize_name(nsname,false,false,true/*force underscore*/); } add_delphi_uses_list(unitname); } MKDIR(get_out_dir().c_str()); } void t_delphi_generator::close_generator() { std::string unitname = program_name_; if ("" != namespace_name_) { unitname = namespace_name_; } for (int i = 0; i < (int)unitname.size(); i++) { if (unitname[i] == ' ') { unitname.replace(i, 1, "_"); } } unitname = normalize_name(unitname,false,false,true/*force underscore*/); std::string f_name = get_out_dir() + "/" + unitname + ".pas"; ofstream_with_content_based_conditional_update f_all; f_all.open(f_name); f_all << autogen_comment() << endl; generate_delphi_doc(f_all, program_); f_all << "unit " << unitname << ";" << endl << endl; f_all << "{$WARN SYMBOL_DEPRECATED OFF}" << endl << endl; if(com_types_) { f_all << "{$MINENUMSIZE 4}" << endl << endl; } f_all << "interface" << endl << endl; f_all << "uses" << endl; indent_up(); vector::const_iterator s_iter; for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) { if (s_iter != uses_list.begin()) { f_all << ","; f_all << endl; } indent(f_all) << *s_iter; } f_all << ";" << endl << endl; indent_down(); string tmp_unit(unitname); for (int i = 0; i < (int)tmp_unit.size(); i++) { if (tmp_unit[i] == '.') { tmp_unit.replace(i, 1, "_"); } } f_all << "const" << endl; indent_up(); indent(f_all) << "c" << tmp_unit << "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_ConstPrefix = " << (constprefix_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_Events = " << (events_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc = " << (xmldoc_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_Async = " << (async_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_COM_types = " << (com_types_ ? "True" : "False") << ";" << endl; indent(f_all) << "c" << tmp_unit << "_Option_Old_Names = " << (old_names_ ? "True" : "False") << ";" << endl; indent_down(); f_all << endl; f_all << "type" << endl; if (has_forward) { f_all << s_forward_decr.str() << endl; } if (has_enum) { indent(f_all) << endl; indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl; f_all << s_enum.str(); indent(f_all) << "{$SCOPEDENUMS OFF}" << endl << endl; } f_all << s_struct.str(); f_all << s_service.str(); f_all << s_const.str(); f_all << "implementation" << endl << endl; f_all << s_struct_impl.str(); f_all << s_service_impl.str(); f_all << s_const_impl.str(); if (register_types_) { f_all << endl; f_all << "// Type factory methods and registration" << endl; f_all << s_type_factory_funcs.str(); f_all << "procedure RegisterTypeFactories;" << endl; f_all << "begin" << endl; f_all << s_type_factory_registration.str(); f_all << "end;" << endl; } f_all << endl; string constants_class = make_constants_classname(); f_all << "initialization" << endl; if (has_const) { f_all << "{$IF CompilerVersion < 21.0} // D2010" << endl; f_all << " " << constants_class.c_str() << "_Initialize;" << endl; f_all << "{$IFEND}" << endl; } if (register_types_) { f_all << " RegisterTypeFactories;" << endl; } f_all << endl; f_all << "finalization" << endl; if (has_const) { f_all << "{$IF CompilerVersion < 21.0} // D2010" << endl; f_all << " " << constants_class.c_str() << "_Finalize;" << endl; f_all << "{$IFEND}" << endl; } f_all << endl << endl; f_all << "end." << endl; f_all.close(); if (!typedefs_pending.empty()) { pwarning(0, "%d typedefs with unresolved type references left:\n", typedefs_pending.size()); for (std::list::iterator iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) { pwarning(0, "- %s\n", (*iter)->get_symbolic().c_str()); } } } void t_delphi_generator::delphi_type_usings(ostream& out) { indent_up(); indent(out) << "Classes, SysUtils, Generics.Collections, Thrift.Collections, Thrift.Protocol," << endl; indent(out) << "Thrift.Transport;" << endl << endl; indent_down(); } void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) { // Forward declare struct def has_forward = true; pdebug("forward declaration of %s\n", type_name(tstruct).c_str()); string what = tstruct->is_xception() ? "class" : "interface"; indent_up(); indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";" << endl; indent_down(); add_defined_type(tstruct); } void t_delphi_generator::generate_typedef(t_typedef* ttypedef) { t_type* type = ttypedef->get_type(); // write now or save for later? if (!is_fully_defined_type(type)) { pverbose("typedef %s: unresolved dependencies found\n", type_name(ttypedef).c_str()); typedefs_pending.push_back(ttypedef); return; } indent_up(); generate_delphi_doc(s_struct, ttypedef); indent(s_struct) << type_name(ttypedef) << " = "; // commented out: the benefit is not big enough to risk breaking existing code // bool container = type->is_list() || type->is_map() || type->is_set(); // if( ! container) // s_struct << "type "; //the "type A = type B" syntax leads to E2574 with generics s_struct << type_name(ttypedef->get_type()) << ";" << endl << endl; indent_down(); add_defined_type(ttypedef); } bool t_delphi_generator::is_fully_defined_type(t_type* ttype) { if ((nullptr != ttype->get_program()) && (ttype->get_program() != program_)) { t_scope* scope = ttype->get_program()->scope(); if (nullptr != scope->get_type(ttype->get_name())) { // printf("type %s found in included scope %s\n", ttype->get_name().c_str(), // ttype->get_program()->get_name().c_str()); return true; } } if (ttype->is_typedef()) { return (types_known.find(type_name(ttype)) != types_known.end()); } if (ttype->is_base_type()) { return (types_known.find(base_type_name((t_base_type*)ttype)) != types_known.end()); } else if (ttype->is_enum()) { return true; // enums are written first, before all other types } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; return is_fully_defined_type(tmap->get_key_type()) && is_fully_defined_type(tmap->get_val_type()); } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; return is_fully_defined_type(tset->get_elem_type()); } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; return is_fully_defined_type(tlist->get_elem_type()); } return (types_known.find(type_name(ttype)) != types_known.end()); } void t_delphi_generator::add_defined_type(t_type* ttype) { // mark as known type types_known.insert(type_name(ttype)); // check all pending typedefs std::list::iterator iter; bool more = true; while (more && (!typedefs_pending.empty())) { more = false; for (iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) { t_typedef* ttypedef = (*iter); if (is_fully_defined_type(ttypedef->get_type())) { pverbose("typedef %s: all pending references are now resolved\n", type_name(ttypedef).c_str()); typedefs_pending.erase(iter); generate_typedef(ttypedef); more = true; break; } } } } void t_delphi_generator::init_known_types_list() { // known base types types_known.insert( type_name(g_type_string)); types_known.insert( type_name(g_type_binary)); types_known.insert( type_name(g_type_uuid)); types_known.insert( type_name(g_type_bool)); types_known.insert( type_name(g_type_i8)); types_known.insert( type_name(g_type_i16)); types_known.insert( type_name(g_type_i32)); types_known.insert( type_name(g_type_i64)); types_known.insert( type_name(g_type_double)); } void t_delphi_generator::generate_enum(t_enum* tenum) { has_enum = true; indent_up(); generate_delphi_doc(s_enum, tenum); indent(s_enum) << type_name(tenum, true, true) << " = " << "(" << endl; indent_up(); vector constants = tenum->get_constants(); if (constants.empty()) { indent(s_enum) << "dummy = 0 // empty enums are not allowed"; } else { vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); if (c_iter != constants.begin()) { s_enum << ","; s_enum << endl; } generate_delphi_doc(s_enum, *c_iter); indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value; } } s_enum << endl; indent_down(); indent(s_enum) << ");" << endl << endl; indent_down(); } std::string t_delphi_generator::make_pascal_string_literal(std::string value) { std::stringstream result; if (value.length() == 0) { return ""; } result << "'"; for (signed char const c: value) { if( (c >= 0) && (c < 32)) { // convert ctrl chars, but leave UTF-8 alone result << "#" << (int)c; } else if (c == '\'') { result << "''"; // duplicate any single quotes we find } else { result << c; // anything else "as is" } } result << "'"; return result.str(); } std::string t_delphi_generator::make_valid_delphi_identifier(std::string const& fromName) { std::string str = fromName; if (str.empty()) { return str; } // tests rely on this assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); // if the first letter is a number, we add an additional underscore in front of it char c = str.at(0); if (('0' <= c) && (c <= '9')) { str = "_" + str; } // following chars: letter, number or underscore for (size_t i = 0; i < str.size(); ++i) { c = str.at(i); if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9')) && ('_' != c)) { str.replace(i, 1, "_"); } } return str; } std::string t_delphi_generator::make_constants_classname() { if (constprefix_) { return make_valid_delphi_identifier("T" + program_name_ + "Constants"); } else { return "TConstants"; // compatibility } } void t_delphi_generator::generate_consts(std::vector consts) { if (consts.empty()) { return; } has_const = true; string constants_class = make_constants_classname(); indent_up(); indent(s_const) << constants_class.c_str() << " = class" << endl; indent(s_const) << "private" << endl; indent_up(); vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { if (const_needs_var((*c_iter)->get_type())) { print_private_field(s_const, normalize_name((*c_iter)->get_name()), (*c_iter)->get_type(), (*c_iter)->get_value()); } } indent_down(); indent(s_const) << "public" << endl; indent_up(); for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { generate_delphi_doc(s_const, *c_iter); print_const_prop(s_const, normalize_name((*c_iter)->get_name()), (*c_iter)->get_type(), (*c_iter)->get_value()); } indent(s_const) << "{$IF CompilerVersion >= 21.0}" << endl; indent(s_const) << "class constructor Create;" << endl; indent(s_const) << "class destructor Destroy;" << endl; indent(s_const) << "{$IFEND}" << endl; indent_down(); indent(s_const) << "end;" << endl << endl; indent_down(); std::ostringstream vars, code; indent_up_impl(); for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { initialize_field(vars, code, prop_name((*c_iter)->get_name(), false, "F"), (*c_iter)->get_type(), (*c_iter)->get_value()); } indent_down_impl(); indent_impl(s_const_impl) << "{$IF CompilerVersion >= 21.0}" << endl; indent_impl(s_const_impl) << "class constructor " << constants_class.c_str() << ".Create;" << endl; if (!vars.str().empty()) { indent_impl(s_const_impl) << "var" << endl; s_const_impl << vars.str(); } indent_impl(s_const_impl) << "begin" << endl; if (!code.str().empty()) { s_const_impl << code.str(); } indent_impl(s_const_impl) << "end;" << endl << endl; indent_impl(s_const_impl) << "class destructor " << constants_class.c_str() << ".Destroy;" << endl; indent_impl(s_const_impl) << "begin" << endl; indent_up_impl(); for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { if (const_needs_var((*c_iter)->get_type())) { finalize_field(s_const_impl, normalize_name((*c_iter)->get_name()), (*c_iter)->get_type(), (*c_iter)->get_value()); } } indent_impl(s_const_impl) << "inherited;" << endl; indent_down_impl(); indent_impl(s_const_impl) << "end;" << endl; indent_impl(s_const_impl) << "{$ELSE}" << endl; vars.str(""); code.str(""); indent_up_impl(); for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { if (const_needs_var((*c_iter)->get_type())) { initialize_field(vars, code, constants_class + "." + prop_name((*c_iter)->get_name(), false, "F"), (*c_iter)->get_type(), (*c_iter)->get_value()); } } indent_down_impl(); indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Initialize;" << endl; if (!vars.str().empty()) { indent_impl(s_const_impl) << "var" << endl; s_const_impl << vars.str(); } indent_impl(s_const_impl) << "begin" << endl; if (!code.str().empty()) { s_const_impl << code.str(); } indent_impl(s_const_impl) << "end;" << endl << endl; indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Finalize;" << endl; indent_impl(s_const_impl) << "begin" << endl; indent_up_impl(); for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { finalize_field(s_const_impl, normalize_name((*c_iter)->get_name()), (*c_iter)->get_type(), (*c_iter)->get_value(), constants_class); } indent_down_impl(); indent_impl(s_const_impl) << "end;" << endl; indent_impl(s_const_impl) << "{$IFEND}" << endl << endl; } void t_delphi_generator::print_const_def_value(std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value, string cls_nm) { string cls_prefix; if (cls_nm == "") { cls_prefix = ""; } else { cls_prefix = cls_nm + "."; } if (type->is_struct() || type->is_xception()) { const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } string val = render_const_value(vars, out, name, field_type, v_iter->second); indent_impl(out) << cls_prefix << normalize_name(name) << "." << prop_name(v_iter->first->get_string(), type->is_xception()) << " := " << val << ";" << endl; } } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string key = render_const_value(vars, out, name, ktype, v_iter->first); string val = render_const_value(vars, out, name, vtype, v_iter->second); indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]" << " := " << val << ";" << endl; } } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { string val = render_const_value(vars, out, name, etype, *v_iter); indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << endl; } } } void t_delphi_generator::print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value) { (void)value; indent(out) << "class var F" << name << ": " << type_name(type) << ";" << endl; } bool t_delphi_generator::const_needs_var(t_type* type) { t_type* truetype = type; while (truetype->is_typedef()) { truetype = ((t_typedef*)truetype)->get_type(); } return (!truetype->is_base_type()); } void t_delphi_generator::print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value) { (void)value; if (const_needs_var(type)) { indent(out) << "class property " << name << ": " << type_name(type) << " read F" << name << ";" << endl; } else { std::ostringstream vars; // dummy string v2 = render_const_value(vars, out, name, type, value); indent(out) << "const " << name << " = " << v2 << ";" << endl; } } void t_delphi_generator::print_const_value(std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value) { t_type* truetype = type; while (truetype->is_typedef()) { truetype = ((t_typedef*)truetype)->get_type(); } if (truetype->is_base_type()) { // already done // string v2 = render_const_value( vars, out, name, type, value); // indent_impl(out) << name << " := " << v2 << ";" << endl; } else if (truetype->is_enum()) { indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name() << ";" << endl; } else { string typname; typname = type_name(truetype, true, false, type->is_xception(), type->is_xception()); indent_impl(out) << name << " := " << typname << ".Create;" << endl; print_const_def_value(vars, out, name, truetype, value); } } void t_delphi_generator::initialize_field(std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value) { print_const_value(vars, out, name, type, value); } void t_delphi_generator::finalize_field(std::ostream& out, string name, t_type* type, t_const_value* value, string cls_nm) { (void)out; (void)name; (void)type; (void)value; (void)cls_nm; } string t_delphi_generator::render_const_value(ostream& vars, ostream& out, string name, t_type* type, t_const_value* value) { (void)name; t_type* truetype = type; while (truetype->is_typedef()) { truetype = ((t_typedef*)truetype)->get_type(); } std::ostringstream render; if (truetype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: render << "'" << get_escaped_string(value) << "'"; break; case t_base_type::TYPE_UUID: render << "['{" << value->get_uuid() << "}']"; break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "True" : "False"); break; case t_base_type::TYPE_I8: render << "ShortInt( " << value->get_integer() << ")"; break; case t_base_type::TYPE_I16: render << "SmallInt( " << value->get_integer() << ")"; break; case t_base_type::TYPE_I32: render << "LongInt( " << value->get_integer() << ")"; break; case t_base_type::TYPE_I64: render << "Int64( " << value->get_integer() << ")"; break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { render << value->get_integer() << ".0"; // make it a double constant by adding ".0" } else { render << value->get_double(); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (truetype->is_enum()) { render << type_name(type, false) << "." << value->get_identifier_name(); } else { string t = tmp("tmp"); vars << " " << t << " : " << type_name(type) << ";" << endl; print_const_value(vars, out, t, type, value); render << t; } return render.str(); } void t_delphi_generator::generate_struct(t_struct* tstruct) { generate_delphi_struct(tstruct, false); } void t_delphi_generator::generate_xception(t_struct* txception) { generate_delphi_struct(txception, true); } void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) { indent_up(); generate_delphi_struct_definition(s_struct, tstruct, is_exception); indent_down(); add_defined_type(tstruct); generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception); if (register_types_) { generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception); generate_delphi_struct_type_factory_registration(s_type_factory_registration, "", tstruct, is_exception); } } void t_delphi_generator::generate_delphi_struct_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result, bool is_x_factory) { if (is_exception && (!is_x_factory)) { generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true); } string cls_nm; string exception_factory_name; if (is_exception) { exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; } if (is_exception) { cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true); } else { cls_nm = type_name(tstruct, true, false); } std::ostringstream vars, code; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; indent_up_impl(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); while (t->is_typedef()) { t = ((t_typedef*)t)->get_type(); } if ((*m_iter)->get_value() != nullptr) { initialize_field(vars, code, prop_name((*m_iter)->get_name(), is_exception, ""), t, (*m_iter)->get_value()); if ((*m_iter)->get_req() != t_field::T_REQUIRED) { indent_impl(code) << prop_name((*m_iter), is_exception, "F__isset_") << " := True;" << endl; } } } indent_down_impl(); indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." << "Create;" << endl; if (!vars.str().empty()) { out << "var" << endl; out << vars.str(); } indent_impl(out) << "begin" << endl; indent_up_impl(); if (is_exception && (!is_x_factory)) { indent_impl(out) << "inherited Create('');" << endl; } else { indent_impl(out) << "inherited;" << endl; } if (!code.str().empty()) { out << code.str(); } indent_down_impl(); indent_impl(out) << "end;" << endl << endl; if ((members.size() > 0) && is_exception && (!is_x_factory)) { indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "Create;" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { string propname = prop_name((*m_iter)->get_name(), is_exception); string param_name = constructor_param_name((*m_iter)->get_name()); indent_impl(out) << propname << " := " << param_name << ";" << endl; } indent_impl(out) << "UpdateMessageProperty;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } indent_impl(out) << "destructor " << cls_prefix << cls_nm << "." << "Destroy;" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); while (t->is_typedef()) { t = ((t_typedef*)t)->get_type(); } finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value()); } indent_impl(out) << "inherited;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; if (is_exception && (!is_x_factory)) { indent_impl(out) << "function " << cls_prefix << cls_nm << "." << exception_factory_name << ": I" << exception_factory_name << ";" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "if F" << exception_factory_name << " = nil" << endl; indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << endl << endl; indent_impl(out) << "result := F" << exception_factory_name << ";" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "if GetInterface(IID, Obj)" << endl; indent_impl(out) << "then result := S_OK" << endl; indent_impl(out) << "else result := E_NOINTERFACE;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "result := -1; // not refcounted" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "result := -1; // not refcounted" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } if (tstruct->is_union()) { indent_impl(out) << "procedure " << cls_prefix << cls_nm << "." << "ClearUnionValues;" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); while (t->is_typedef()) { t = ((t_typedef*)t)->get_type(); } generate_delphi_clear_union_value(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception, tstruct->is_union(), is_x_factory, exception_factory_name); } indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); while (t->is_typedef()) { t = ((t_typedef*)t)->get_type(); } generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception); generate_delphi_property_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception, tstruct->is_union(), is_x_factory, exception_factory_name); if ((*m_iter)->get_req() != t_field::T_REQUIRED) { generate_delphi_isset_reader_writer_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception); } } generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); if (is_result) { generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); } else { generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); } generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); if (is_exception && is_x_factory) { generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception); } } void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) { string struct_intf_name = type_name(tstruct); out << "Create_"; out << struct_intf_name; out << "_Impl"; } void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result, bool is_x_factory) { (void)cls_prefix; if (is_exception) return; if (is_result) return; if (is_x_factory) return; string struct_intf_name = type_name(tstruct); string cls_nm = type_name(tstruct, true, false); out << "function "; print_delphi_struct_type_factory_func(out, tstruct); out << ": "; out << struct_intf_name; out << ";" << endl; out << "begin" << endl; indent_up(); indent(out) << "Result := " << cls_nm << ".Create;" << endl; indent_down(); out << "end;" << endl << endl; } void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result, bool is_x_factory) { (void)cls_prefix; if (is_exception) return; if (is_result) return; if (is_x_factory) return; string struct_intf_name = type_name(tstruct); indent(out) << " TypeRegistry.RegisterTypeFactory<" << struct_intf_name << ">("; print_delphi_struct_type_factory_func(out, tstruct); out << ");"; out << endl; } void t_delphi_generator::generate_delphi_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result, bool is_x_factory) { bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); string struct_intf_name; string struct_name; string isset_name; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; if (is_exception) { struct_intf_name = type_name(tstruct, false, false, true); } else { struct_intf_name = type_name(tstruct); } if (is_exception) { struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory); } else { struct_name = type_name(tstruct, true); } if ((!is_exception) || is_x_factory) { generate_delphi_doc(out, tstruct); indent(out) << struct_intf_name << " = interface(IBase)" << endl; indent_up(); generate_guid(out); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_delphi_property_reader_definition(out, *m_iter, is_exception); generate_delphi_property_writer_definition(out, *m_iter, is_exception); } if (is_x_factory) { out << endl; indent(out) << "// Create Exception Object" << endl; indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl; } if (members.size() > 0) { out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_property(out, *m_iter, true, is_exception); } } if (members.size() > 0) { out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { generate_delphi_isset_reader_writer_definition(out, *m_iter, is_exception); } } } if (members.size() > 0) { out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { isset_name = prop_name(*m_iter, is_exception, "__isset_"); indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" << endl; } } } indent_down(); indent(out) << "end;" << endl << endl; } generate_delphi_doc(out, tstruct); indent(out) << struct_name << " = "; if (is_final) { out << "sealed "; } out << "class("; if (is_exception && (!is_x_factory)) { out << "TException, IInterface, IBase, ISupportsToString"; } else { out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name; } out << ")" << endl; if (is_exception && (!is_x_factory)) { indent(out) << "public" << endl; indent_up(); indent(out) << "type" << endl; indent_up(); generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true); indent_down(); indent_down(); } indent(out) << "private" << endl; indent_up(); if (is_exception && (!is_x_factory)) { indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << endl << endl; } for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << declare_field(*m_iter, false, "F", is_exception) << endl; } if (members.size() > 0) { indent(out) << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { isset_name = prop_name(*m_iter, is_exception, "F__isset_"); indent(out) << isset_name << ": System.Boolean;" << endl; } } } indent(out) << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_delphi_property_reader_definition(out, *m_iter, is_exception); generate_delphi_property_writer_definition(out, *m_iter, is_exception); } if (tstruct->is_union()) { out << endl; indent(out) << "// Clear values(for union's property setter)" << endl; indent(out) << "procedure ClearUnionValues;" << endl; } if (members.size() > 0) { out << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { isset_name = prop_name(*m_iter, is_exception, "__isset_"); indent(out) << "function Get" << isset_name << ": System.Boolean;" << endl; indent(out) << "procedure Set" << isset_name << "( const value : System.Boolean);" << endl; } } } if (is_exception && (!is_x_factory)) { out << endl; indent_down(); indent(out) << "strict protected" << endl; indent_up(); indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << endl; indent(out) << "function _AddRef: Integer; stdcall;" << endl; indent(out) << "function _Release: Integer; stdcall;" << endl; out << endl; } indent_down(); indent(out) << "public" << endl; indent_up(); if ((members.size() > 0) && is_exception && (!is_x_factory)) { indent(out) << "constructor Create; overload;" << endl; indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent()) << "); overload;" << endl; } else { indent(out) << "constructor Create;" << endl; } indent(out) << "destructor Destroy; override;" << endl; out << endl; indent(out) << "function ToString: string; override;" << endl; if (is_exception && (!is_x_factory)) { out << endl; indent(out) << "// Exception Factory" << endl; indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << endl; } out << endl; indent(out) << "// IBase" << endl; indent(out) << "procedure Read( const iprot: IProtocol);" << endl; indent(out) << "procedure Write( const oprot: IProtocol);" << endl; if (is_exception && is_x_factory) { out << endl; indent(out) << "// Create Exception Object" << endl; indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl; } if (members.size() > 0) { out << endl; indent(out) << "// Properties" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_property(out, *m_iter, true, is_exception); } } if (members.size() > 0) { out << endl; indent(out) << "// isset" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if ((*m_iter)->get_req() != t_field::T_REQUIRED) { isset_name = prop_name(*m_iter, is_exception, "__isset_"); indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << " write Set" << isset_name << ";" << endl; } } } indent_down(); indent(out) << "end;" << endl << endl; } void t_delphi_generator::generate_service(t_service* tservice) { indent_up(); generate_delphi_doc(s_service, tservice); indent(s_service) << normalize_clsnm(service_name_, "T") << " = class" << endl; indent(s_service) << "public" << endl; indent_up(); indent(s_service) << "type" << endl; generate_service_interface(tservice); generate_service_client(tservice); generate_service_server(tservice); generate_service_helpers(tservice); indent_down(); indent_down(); indent(s_service) << "end;" << endl; indent(s_service) << endl; indent_down(); } void t_delphi_generator::generate_service_interface(t_service* tservice) { generate_service_interface(tservice,false); if(async_) { generate_service_interface(tservice,true); } } void t_delphi_generator::generate_service_interface(t_service* tservice, bool for_async) { string extends = ""; string extends_iface = ""; string iface_name = for_async ? "IAsync" : "Iface"; indent_up(); generate_delphi_doc(s_service, tservice); if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends(), true, true); extends_iface = extends + "." + iface_name; generate_delphi_doc(s_service, tservice); indent(s_service) << iface_name << " = interface(" << extends_iface << ")" << endl; } else { indent(s_service) << iface_name << " = interface" << endl; } indent_up(); generate_guid(s_service); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_delphi_doc(s_service, *f_iter); indent(s_service) << function_signature(*f_iter, for_async) << endl; } indent_down(); indent(s_service) << "end;" << endl << endl; indent_down(); } void t_delphi_generator::generate_guid(std::ostream& out) { #ifdef _WIN32 // TODO: add support for non-windows platforms if needed GUID guid; if (SUCCEEDED(CoCreateGuid(&guid))) { OLECHAR guid_chars[40]{}; if (StringFromGUID2(guid, &guid_chars[0], sizeof(guid_chars) / sizeof(guid_chars[0])) > 0) { std::wstring guid_wstr(guid_chars); std::wstring_convert> convert; std::string guid_str = convert.to_bytes(guid_wstr); indent(out) << "['" << guid_str << "']" << endl; } } #else (void)out; // prevent unused warning on other platforms #endif } void t_delphi_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_delphi_struct_definition(s_service, ts, false, true); generate_delphi_struct_impl(s_service_impl, normalize_clsnm(service_name_, "T") + ".", ts, false); generate_function_helpers(*f_iter); } } void t_delphi_generator::generate_service_client(t_service* tservice) { indent_up(); string extends = ""; string extends_client = "TInterfacedObject"; string implements = async_ ? "Iface, IAsync" : "Iface"; generate_delphi_doc(s_service, tservice); if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends(), true, true); extends_client = extends + ".TClient"; } indent(s_service) << "TClient = class( " << extends_client << ", " << implements << ")" << endl; indent(s_service) << "public" << endl; indent_up(); indent(s_service) << "constructor Create( prot: IProtocol); overload;" << endl; indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T") << ".TClient.Create( prot: IProtocol);" << endl; indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "Create( prot, prot );" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; indent(s_service) << "constructor Create( const iprot: IProtocol; const oprot: IProtocol); overload;" << endl; indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T") << ".TClient.Create( const iprot: IProtocol; const oprot: IProtocol);" << endl; indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "inherited Create;" << endl; indent_impl(s_service_impl) << "iprot_ := iprot;" << endl; indent_impl(s_service_impl) << "oprot_ := oprot;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; indent_down(); if (extends.empty()) { indent(s_service) << "protected" << endl; indent_up(); indent(s_service) << "iprot_: IProtocol;" << endl; indent(s_service) << "oprot_: IProtocol;" << endl; indent(s_service) << "seqid_: System.Integer;" << endl; indent_down(); indent(s_service) << "public" << endl; indent_up(); indent(s_service) << "property InputProtocol: IProtocol read iprot_;" << endl; indent(s_service) << "property OutputProtocol: IProtocol read oprot_;" << endl; indent_down(); } vector functions = tservice->get_functions(); vector::const_iterator f_iter; indent(s_service) << "protected" << endl; indent_up(); indent(s_service) << "// Iface" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); generate_delphi_doc(s_service, *f_iter); indent(s_service) << function_signature(*f_iter, false) << endl; } if( async_) { indent(s_service) << endl; indent(s_service) << "// IAsync" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); generate_delphi_doc(s_service, *f_iter); indent(s_service) << function_signature(*f_iter, true) << endl; } } indent_down(); indent(s_service) << "public" << endl; indent_up(); string full_cls = normalize_clsnm(service_name_, "T") + ".TClient"; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string funname = (*f_iter)->get_name(); vector::const_iterator fld_iter; t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); // one for sync only, two for async+sync int mode = async_ ? 1 : 0; while( mode >= 0) { bool for_async = (mode != 0); mode--; indent_impl(s_service_impl) << function_signature(*f_iter, for_async, full_cls) << endl; indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); t_type* ttype = (*f_iter)->get_returntype(); if( for_async) { if (is_void(ttype)) { // Delphi forces us to specify a type with IFuture, so we use Integer=0 for void methods indent_impl(s_service_impl) << "result := TTask.Future(function: System.Integer" << endl; } else { string rettype = type_name(ttype, false, true, false, true); indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << endl; } indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); } indent_impl(s_service_impl) << "send_" << funname << "("; bool first = true; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { s_service_impl << ", "; } s_service_impl << normalize_name((*fld_iter)->get_name()); } s_service_impl << ");" << endl; if (!(*f_iter)->is_oneway()) { s_service_impl << indent_impl(); if (!(*f_iter)->get_returntype()->is_void()) { s_service_impl << "Result := "; } s_service_impl << "recv_" << funname << "();" << endl; } if( for_async) { if (is_void(ttype)) { indent_impl(s_service_impl) << "Result := 0;" << endl; // no IFuture in Delphi } indent_down_impl(); indent_impl(s_service_impl) << "end);" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; } t_function send_function(g_type_void, string("send_") + (*f_iter)->get_name(), (*f_iter)->get_arglist()); string argsname = (*f_iter)->get_name() + "_args"; string args_clsnm = normalize_clsnm(argsname, "T"); string args_intfnm = normalize_clsnm(argsname, "I"); string argsvar = tmp("_args"); string msgvar = tmp("_msg"); indent(s_service) << function_signature(&send_function, false) << endl; indent_impl(s_service_impl) << function_signature(&send_function, false, full_cls) << endl; indent_impl(s_service_impl) << "var" << endl; indent_up_impl(); indent_impl(s_service_impl) << argsvar << " : " << args_intfnm << ";" << endl; indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.TThriftMessage;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "seqid_ := seqid_ + 1;" << endl; indent_impl(s_service_impl) << "Thrift.Protocol.Init( " << msgvar << ", '" << funname << "', " << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call") << ", seqid_);" << endl; indent_impl(s_service_impl) << "oprot_.WriteMessageBegin( " << msgvar << " );" << endl; indent_impl(s_service_impl) << argsvar << " := " << args_clsnm << "Impl.Create();" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter) << " := " << normalize_name((*fld_iter)->get_name()) << ";" << endl; } indent_impl(s_service_impl) << argsvar << ".Write(oprot_);" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter) << " := " << empty_value((*fld_iter)->get_type()) << ";" << endl; } indent_impl(s_service_impl) << "oprot_.WriteMessageEnd();" << endl; indent_impl(s_service_impl) << "oprot_.Transport.Flush();" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; if (!(*f_iter)->is_oneway()) { string org_resultname = (*f_iter)->get_name() + "_result"; string result_clsnm = normalize_clsnm(org_resultname, "T"); string result_intfnm = normalize_clsnm(org_resultname, "I"); t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs, (*f_iter)->get_xceptions()); t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); string exceptvar = tmp("_ex"); string appexvar = tmp("_ax"); string retvar = tmp("_ret"); indent(s_service) << function_signature(&recv_function, false) << endl; indent_impl(s_service_impl) << function_signature(&recv_function, false, full_cls) << endl; indent_impl(s_service_impl) << "var" << endl; indent_up_impl(); indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.TThriftMessage;" << endl; if (xceptions.size() > 0) { indent_impl(s_service_impl) << exceptvar << " : Exception;" << endl; } indent_impl(s_service_impl) << appexvar << " : TApplicationException;" << endl; indent_impl(s_service_impl) << retvar << " : " << result_intfnm << ";" << endl; indent_down_impl(); indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << msgvar << " := iprot_.ReadMessageBegin();" << endl; indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << appexvar << " := TApplicationException.Read(iprot_);" << endl; indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl; indent_impl(s_service_impl) << "raise " << appexvar << ";" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; indent_impl(s_service_impl) << retvar << " := " << result_clsnm << "Impl.Create();" << endl; indent_impl(s_service_impl) << retvar << ".Read(iprot_);" << endl; indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl; if (!(*f_iter)->get_returntype()->is_void()) { indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "Result := " << retvar << ".Success;" << endl; t_type* type = (*f_iter)->get_returntype(); if (type->is_struct() || type->is_xception() || type->is_map() || type->is_list() || type->is_set()) { indent_impl(s_service_impl) << retvar << ".Success := nil;" << endl; } indent_impl(s_service_impl) << "Exit;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; } vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { indent_impl(s_service_impl) << "if (" << retvar << "." << prop_name(*x_iter, false, "__isset_") << ") then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter) << ".CreateException;" << endl; indent_impl(s_service_impl) << "raise " << exceptvar << ";" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; } if (!(*f_iter)->get_returntype()->is_void()) { indent_impl(s_service_impl) << "raise TApplicationExceptionMissingResult.Create('" << (*f_iter)->get_name() << " failed: unknown result');" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; } } indent_down(); indent(s_service) << "end;" << endl << endl; } void t_delphi_generator::generate_service_server(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl"; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends(), true, true); extends_processor = extends + ".TProcessorImpl"; indent(s_service) << "TProcessorImpl = class(" << extends_processor << ", IProcessor)" << endl; } else { indent(s_service) << "TProcessorImpl = class( TInterfacedObject, IProcessor)" << endl; } indent(s_service) << "public" << endl; indent_up(); indent(s_service) << "constructor Create( iface_: Iface );" << endl; indent(s_service) << "destructor Destroy; override;" << endl; indent_down(); indent_impl(s_service_impl) << "constructor " << full_cls << ".Create( iface_: Iface );" << endl; indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); if (tservice->get_extends() != nullptr) { indent_impl(s_service_impl) << "inherited Create( iface_);" << endl; } else { indent_impl(s_service_impl) << "inherited Create;" << endl; } indent_impl(s_service_impl) << "Self.iface_ := iface_;" << endl; if (tservice->get_extends() != nullptr) { indent_impl(s_service_impl) << "ASSERT( processMap_ <> nil); // inherited" << endl; } else { indent_impl(s_service_impl) << "processMap_ := TThriftDictionaryImpl.Create;" << endl; } for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { indent_impl(s_service_impl) << "processMap_.AddOrSetValue( '" << (*f_iter)->get_name() << "', " << (*f_iter)->get_name() << "_Process);" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; indent_impl(s_service_impl) << "destructor " << full_cls << ".Destroy;" << endl; indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "inherited;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; indent(s_service) << "private" << endl; indent_up(); indent(s_service) << "iface_: Iface;" << endl; indent_down(); if (tservice->get_extends() == nullptr) { indent(s_service) << "protected" << endl; indent_up(); indent(s_service) << "type" << endl; indent_up(); indent(s_service) << "TProcessFunction = reference to procedure( seqid: System.Integer; const iprot: " "IProtocol; const oprot: IProtocol" << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl; indent_down(); indent_down(); indent(s_service) << "protected" << endl; indent_up(); indent(s_service) << "processMap_: IThriftDictionary;" << endl; indent_down(); } indent(s_service) << "public" << endl; indent_up(); if (extends.empty()) { indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const " "events : IProcessorEvents): System.Boolean;" << endl; } else { indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const " "events : IProcessorEvents): System.Boolean; reintroduce;" << endl; } indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; " "const oprot: IProtocol; const events " ": IProcessorEvents): System.Boolean;" << endl; ; indent_impl(s_service_impl) << "var" << endl; indent_up_impl(); indent_impl(s_service_impl) << "msg : Thrift.Protocol.TThriftMessage;" << endl; indent_impl(s_service_impl) << "fn : TProcessFunction;" << endl; indent_impl(s_service_impl) << "x : TApplicationException;" << endl; if (events_) { indent_impl(s_service_impl) << "context : IRequestEvents;" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "try" << endl; indent_up_impl(); indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl; indent_impl(s_service_impl) << "fn := nil;" << endl; indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl; indent_impl(s_service_impl) << "or not Assigned(fn) then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl; indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl; indent_impl(s_service_impl) << "x := " "TApplicationExceptionUnknownMethod.Create(" "'Invalid method name: ''' + msg.Name + '''');" << endl; indent_impl(s_service_impl) << "Thrift.Protocol.Init( msg, msg.Name, TMessageType.Exception, msg.SeqID);" << endl; indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl; indent_impl(s_service_impl) << "x.Write(oprot);" << endl; indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl; indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl; indent_impl(s_service_impl) << "Result := True;" << endl; indent_impl(s_service_impl) << "Exit;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; if (events_) { indent_impl(s_service_impl) << "if events <> nil" << endl; indent_impl(s_service_impl) << "then context := events.CreateRequestContext(msg.Name)" << endl; indent_impl(s_service_impl) << "else context := nil;" << endl; indent_impl(s_service_impl) << "try" << endl; indent_up_impl(); indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot, context);" << endl; indent_down_impl(); indent_impl(s_service_impl) << "finally" << endl; indent_up_impl(); indent_impl(s_service_impl) << "if context <> nil then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "context.CleanupContext;" << endl; indent_impl(s_service_impl) << "context := nil;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; } else { indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot);" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "except" << endl; indent_up_impl(); indent_impl(s_service_impl) << "on TTransportExceptionTimedOut do begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "Result := True;" << endl; indent_impl(s_service_impl) << "Exit;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; indent_impl(s_service_impl) << "else begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "Result := False;" << endl; indent_impl(s_service_impl) << "Exit;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; indent_impl(s_service_impl) << "Result := True;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_process_function(tservice, *f_iter); } indent_down(); indent(s_service) << "end;" << endl << endl; } void t_delphi_generator::generate_function_helpers(t_function* tfunction) { if (tfunction->is_oneway()) { return; } t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "Success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_delphi_struct_definition(s_service, &result, false, true, true); generate_delphi_struct_impl(s_service_impl, normalize_clsnm(service_name_, "T") + ".", &result, false); } void t_delphi_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; string funcname = tfunction->get_name(); string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl"; string org_argsname = funcname + "_args"; string args_clsnm = normalize_clsnm(org_argsname, "T"); string args_intfnm = normalize_clsnm(org_argsname, "I"); string org_resultname = funcname + "_result"; string result_clsnm = normalize_clsnm(org_resultname, "T"); string result_intfnm = normalize_clsnm(org_resultname, "I"); indent(s_service) << "procedure " << funcname << "_Process( seqid: System.Integer; const iprot: IProtocol; const oprot: IProtocol" << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl; if (tfunction->is_oneway()) { indent_impl(s_service_impl) << "// one way processor" << endl; } else { indent_impl(s_service_impl) << "// both way processor" << endl; } indent_impl(s_service_impl) << "procedure " << full_cls << "." << funcname << "_Process( seqid: System.Integer; const iprot: IProtocol; const oprot: IProtocol" << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl; indent_impl(s_service_impl) << "var" << endl; indent_up_impl(); indent_impl(s_service_impl) << "args: " << args_intfnm << ";" << endl; if (!tfunction->is_oneway()) { indent_impl(s_service_impl) << "msg: Thrift.Protocol.TThriftMessage;" << endl; indent_impl(s_service_impl) << "ret: " << result_intfnm << ";" << endl; indent_impl(s_service_impl) << "appx : TApplicationException;" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); if (!tfunction->is_oneway()) { indent_impl(s_service_impl) << "ret := " << result_clsnm << "Impl.Create;" << endl; } indent_impl(s_service_impl) << "try" << endl; indent_up_impl(); if (events_) { indent_impl(s_service_impl) << "if events <> nil then events.PreRead;" << endl; } indent_impl(s_service_impl) << "args := " << args_clsnm << "Impl.Create;" << endl; indent_impl(s_service_impl) << "args.Read(iprot);" << endl; indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl; if (events_) { indent_impl(s_service_impl) << "if events <> nil then events.PostRead;" << endl; } t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; s_service_impl << indent_impl(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { s_service_impl << "ret.Success := "; } s_service_impl << "iface_." << normalize_name(tfunction->get_name(), true) << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { s_service_impl << ", "; } s_service_impl << "args." << prop_name(*f_iter); } s_service_impl << ");" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent_impl(s_service_impl) << "args." << prop_name(*f_iter) << " := " << empty_value((*f_iter)->get_type()) << ";" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "except" << endl; indent_up_impl(); for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { indent_impl(s_service_impl) << "on E: " << type_name((*x_iter)->get_type(), true, true) << " do begin" << endl; indent_up_impl(); if (!tfunction->is_oneway()) { string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true) + "Factory"; indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name << ";" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; } indent_impl(s_service_impl) << "on E: Exception do begin" << endl; indent_up_impl(); if(events_) { indent_impl(s_service_impl) << "if events <> nil then events.UnhandledError(E);" << endl; } if (!tfunction->is_oneway()) { indent_impl(s_service_impl) << "appx := TApplicationExceptionInternalError.Create(E.Message);" << endl; indent_impl(s_service_impl) << "try" << endl; indent_up_impl(); if(events_) { indent_impl(s_service_impl) << "if events <> nil then events.PreWrite;" << endl; } indent_impl(s_service_impl) << "Thrift.Protocol.Init( msg, '" << tfunction->get_name() << "', TMessageType.Exception, seqid);" << endl; indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl; indent_impl(s_service_impl) << "appx.Write(oprot);" << endl; indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl; indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl; if(events_) { indent_impl(s_service_impl) << "if events <> nil then events.PostWrite;" << endl; } indent_impl(s_service_impl) << "Exit;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "finally" << endl; indent_up_impl(); indent_impl(s_service_impl) << "appx.Free;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl; if (!tfunction->is_oneway()) { if (events_) { indent_impl(s_service_impl) << "if events <> nil then events.PreWrite;" << endl; } indent_impl(s_service_impl) << "Thrift.Protocol.Init( msg, '" << tfunction->get_name() << "', TMessageType.Reply, seqid); " << endl; indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg); " << endl; indent_impl(s_service_impl) << "ret.Write(oprot);" << endl; indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl; indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl; if (events_) { indent_impl(s_service_impl) << "if events <> nil then events.PostWrite;" << endl; } } else if (events_) { indent_impl(s_service_impl) << "if events <> nil then events.OnewayComplete;" << endl; } indent_down_impl(); indent_impl(s_service_impl) << "end;" << endl << endl; } void t_delphi_generator::generate_deserialize_field(ostream& out, bool is_xception, t_field* tfield, string prefix, ostream& local_vars) { t_type* type = tfield->get_type(); while (type->is_typedef()) { type = ((t_typedef*)type)->get_type(); } if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + prop_name(tfield, is_xception); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name, ""); } else if (type->is_container()) { generate_deserialize_container(out, is_xception, type, name, local_vars); } else if (type->is_base_type() || type->is_enum()) { indent_impl(out) << name << " := "; if (type->is_enum()) { out << type_name(type, false) << "("; } out << "iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { if (ansistr_binary_) { out << "ReadAnsiString();"; } else { out << (com_types_ ? "ReadBinaryCOM();" : "ReadBinary();"); } } else { out << "ReadString();"; } break; case t_base_type::TYPE_UUID: out << "ReadUuid();"; break; case t_base_type::TYPE_BOOL: out << "ReadBool();"; break; case t_base_type::TYPE_I8: out << "ReadByte();"; break; case t_base_type::TYPE_I16: out << "ReadI16();"; break; case t_base_type::TYPE_I32: out << "ReadI32();"; break; case t_base_type::TYPE_I64: out << "ReadI64();"; break; case t_base_type::TYPE_DOUBLE: out << "ReadDouble();"; break; default: throw "compiler error: no Delphi name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "ReadI32()"; out << ");"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); } } void t_delphi_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string name, string prefix) { string typ_name; if (tstruct->is_xception()) { typ_name = type_name(tstruct, true, false, true, true); } else { typ_name = type_name(tstruct, true, false); } indent_impl(out) << prefix << name << " := " << typ_name << ".Create;" << endl; indent_impl(out) << prefix << name << ".Read(iprot);" << endl; } void t_delphi_generator::generate_deserialize_container(ostream& out, bool is_xception, t_type* ttype, string name, std::ostream& local_vars) { string obj; string counter; string local_var; if (ttype->is_map()) { obj = tmp("_map"); } else if (ttype->is_set()) { obj = tmp("_set"); } else if (ttype->is_list()) { obj = tmp("_list"); } if (ttype->is_map()) { local_var = obj + ": TThriftMap;"; } else if (ttype->is_set()) { local_var = obj + ": TThriftSet;"; } else if (ttype->is_list()) { local_var = obj + ": TThriftList;"; } local_vars << " " << local_var << endl; counter = tmp("_i"); local_var = counter + ": System.Integer;"; local_vars << " " << local_var << endl; indent_impl(out) << name << " := " << type_name(ttype, true) << ".Create;" << endl; if (ttype->is_map()) { indent_impl(out) << obj << " := iprot.ReadMapBegin();" << endl; } else if (ttype->is_set()) { indent_impl(out) << obj << " := iprot.ReadSetBegin();" << endl; } else if (ttype->is_list()) { indent_impl(out) << obj << " := iprot.ReadListBegin();" << endl; } indent_impl(out) << "for " << counter << " := 0 to " << obj << ".Count - 1 do begin" << endl; indent_up_impl(); if (ttype->is_map()) { generate_deserialize_map_element(out, is_xception, (t_map*)ttype, name, local_vars); } else if (ttype->is_set()) { generate_deserialize_set_element(out, is_xception, (t_set*)ttype, name, local_vars); } else if (ttype->is_list()) { generate_deserialize_list_element(out, is_xception, (t_list*)ttype, name, local_vars); } indent_down_impl(); indent_impl(out) << "end;" << endl; if (ttype->is_map()) { indent_impl(out) << "iprot.ReadMapEnd();" << endl; } else if (ttype->is_set()) { indent_impl(out) << "iprot.ReadSetEnd();" << endl; } else if (ttype->is_list()) { indent_impl(out) << "iprot.ReadListEnd();" << endl; } } void t_delphi_generator::generate_deserialize_map_element(ostream& out, bool is_xception, t_map* tmap, string prefix, ostream& local_vars) { string key = tmp("_key"); string val = tmp("_val"); string local_var; t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); local_vars << " " << declare_field(&fkey) << endl; local_vars << " " << declare_field(&fval) << endl; generate_deserialize_field(out, is_xception, &fkey, "", local_vars); generate_deserialize_field(out, is_xception, &fval, "", local_vars); indent_impl(out) << prefix << ".AddOrSetValue( " << key << ", " << val << ");" << endl; } void t_delphi_generator::generate_deserialize_set_element(ostream& out, bool is_xception, t_set* tset, string prefix, ostream& local_vars) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); local_vars << " " << declare_field(&felem) << endl; generate_deserialize_field(out, is_xception, &felem, "", local_vars); indent_impl(out) << prefix << ".Add(" << elem << ");" << endl; } void t_delphi_generator::generate_deserialize_list_element(ostream& out, bool is_xception, t_list* tlist, string prefix, ostream& local_vars) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); local_vars << " " << declare_field(&felem) << endl; generate_deserialize_field(out, is_xception, &felem, "", local_vars); indent_impl(out) << prefix << ".Add(" << elem << ");" << endl; } void t_delphi_generator::generate_serialize_field(ostream& out, bool is_xception, t_field* tfield, string prefix, ostream& local_vars) { (void)local_vars; t_type* type = tfield->get_type(); while (type->is_typedef()) { type = ((t_typedef*)type)->get_type(); } string name = prefix + prop_name(tfield, is_xception); if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, name, local_vars); } else if (type->is_container()) { generate_serialize_container(out, is_xception, type, name, local_vars); } else if (type->is_base_type() || type->is_enum()) { indent_impl(out) << "oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { if (ansistr_binary_) { out << "WriteAnsiString("; } else { out << "WriteBinary("; } } else { out << "WriteString("; } out << name << ");"; break; case t_base_type::TYPE_UUID: out << "WriteUuid(" << name << ");"; break; case t_base_type::TYPE_BOOL: out << "WriteBool(" << name << ");"; break; case t_base_type::TYPE_I8: out << "WriteByte(" << name << ");"; break; case t_base_type::TYPE_I16: out << "WriteI16(" << name << ");"; break; case t_base_type::TYPE_I32: out << "WriteI32(" << name << ");"; break; case t_base_type::TYPE_I64: out << "WriteI64(" << name << ");"; break; case t_base_type::TYPE_DOUBLE: out << "WriteDouble(" << name << ");"; break; default: throw "compiler error: no Delphi name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << "WriteI32(System.Integer(" << name << "));"; } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type_name(type).c_str()); } } void t_delphi_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, ostream& local_vars) { (void)local_vars; (void)tstruct; out << indent_impl() << prefix << ".Write(oprot);" << endl; } void t_delphi_generator::generate_serialize_container(ostream& out, bool is_xception, t_type* ttype, string prefix, ostream& local_vars) { string obj; if (ttype->is_map()) { obj = tmp("map"); local_vars << " " << obj << " : TThriftMap;" << endl; indent_impl(out) << "Thrift.Protocol.Init( " << obj << ", " << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix << ".Count);" << endl; indent_impl(out) << "oprot.WriteMapBegin( " << obj << ");" << endl; } else if (ttype->is_set()) { obj = tmp("set_"); local_vars << " " << obj << " : TThriftSet;" << endl; indent_impl(out) << "Thrift.Protocol.Init( " << obj << ", " << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix << ".Count);" << endl; indent_impl(out) << "oprot.WriteSetBegin( " << obj << ");" << endl; } else if (ttype->is_list()) { obj = tmp("list_"); local_vars << " " << obj << " : TThriftList;" << endl; indent_impl(out) << "Thrift.Protocol.Init( " << obj << ", " << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".Count);" << endl; indent_impl(out) << "oprot.WriteListBegin( " << obj << ");" << endl; } string iter = tmp("_iter"); if (ttype->is_map()) { local_vars << " " << iter << ": " << type_name(((t_map*)ttype)->get_key_type()) << ";" << endl; indent_impl(out) << "for " << iter << " in " << prefix << ".Keys do begin" << endl; indent_up_impl(); } else if (ttype->is_set()) { local_vars << " " << iter << ": " << type_name(((t_set*)ttype)->get_elem_type()) << ";" << endl; indent_impl(out) << "for " << iter << " in " << prefix << " do begin" << endl; indent_up_impl(); } else if (ttype->is_list()) { local_vars << " " << iter << ": " << type_name(((t_list*)ttype)->get_elem_type()) << ";" << endl; indent_impl(out) << "for " << iter << " in " << prefix << " do begin" << endl; indent_up_impl(); } if (ttype->is_map()) { generate_serialize_map_element(out, is_xception, (t_map*)ttype, iter, prefix, local_vars); } else if (ttype->is_set()) { generate_serialize_set_element(out, is_xception, (t_set*)ttype, iter, local_vars); } else if (ttype->is_list()) { generate_serialize_list_element(out, is_xception, (t_list*)ttype, iter, local_vars); } indent_down_impl(); indent_impl(out) << "end;" << endl; if (ttype->is_map()) { indent_impl(out) << "oprot.WriteMapEnd();" << endl; } else if (ttype->is_set()) { indent_impl(out) << "oprot.WriteSetEnd();" << endl; } else if (ttype->is_list()) { indent_impl(out) << "oprot.WriteListEnd();" << endl; } } void t_delphi_generator::generate_serialize_map_element(ostream& out, bool is_xception, t_map* tmap, string iter, string map, ostream& local_vars) { t_field kfield(tmap->get_key_type(), iter); generate_serialize_field(out, is_xception, &kfield, "", local_vars); t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); generate_serialize_field(out, is_xception, &vfield, "", local_vars); } void t_delphi_generator::generate_serialize_set_element(ostream& out, bool is_xception, t_set* tset, string iter, ostream& local_vars) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, is_xception, &efield, "", local_vars); } void t_delphi_generator::generate_serialize_list_element(ostream& out, bool is_xception, t_list* tlist, string iter, ostream& local_vars) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, is_xception, &efield, "", local_vars); } void t_delphi_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception) { generate_delphi_property(out, is_xception, tfield, isPublic, "Get"); } void t_delphi_generator::generate_delphi_property(ostream& out, bool struct_is_xception, t_field* tfield, bool isPublic, std::string fieldPrefix) { (void)isPublic; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); generate_delphi_doc(out, tfield); indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": " << type_name(ftype, false, true, is_xception, true) << " read " << prop_name(tfield, struct_is_xception, fieldPrefix) << " write " << prop_name(tfield, struct_is_xception, "Set") << ";" << endl; } std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception, std::string prefix) { return prop_name(tfield->get_name(), is_xception, prefix); } std::string t_delphi_generator::prop_name(string name, bool is_xception, std::string prefix) { string ret = name; ret[0] = toupper(ret[0]); return normalize_name(prefix + ret, true, is_xception); } std::string t_delphi_generator::constructor_param_name(string name) { string ret = name; ret[0] = toupper(ret[0]); return normalize_name("a" + ret, false, false); } string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_no_check_keyword) { if (clsnm.size() > 0) { clsnm[0] = toupper(clsnm[0]); } if (b_no_check_keyword) { return prefix + clsnm; } else { return normalize_name(prefix + clsnm); } } string t_delphi_generator::type_name(t_type* ttype, bool b_cls, bool b_no_postfix, bool b_exception_factory, bool b_full_exception_factory) { if (ttype->is_typedef()) { t_typedef* tdef = (t_typedef*)ttype; if (tdef->is_forward_typedef()) { // forward types according to THRIFT-2421 if (tdef->get_type() != nullptr) { return type_name(tdef->get_type(), b_cls, b_no_postfix, b_exception_factory, b_full_exception_factory); } else { throw "unresolved forward declaration: " + tdef->get_symbolic(); } } else { return normalize_name("T" + tdef->get_symbolic()); } } string typ_nm; string s_factory; if (ttype->is_base_type()) { return base_type_name((t_base_type*)ttype); } else if (ttype->is_enum()) { b_cls = true; b_no_postfix = true; } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; if (b_cls) { typ_nm = "TThriftDictionaryImpl"; } else { typ_nm = "IThriftDictionary"; } return typ_nm + "<" + type_name(tmap->get_key_type()) + ", " + type_name(tmap->get_val_type()) + ">"; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; if (b_cls) { typ_nm = "TThriftHashSetImpl"; } else { typ_nm = "IThriftHashSet"; } return typ_nm + "<" + type_name(tset->get_elem_type()) + ">"; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; if (b_cls) { typ_nm = "TThriftListImpl"; } else { typ_nm = "IThriftList"; } return typ_nm + "<" + type_name(tlist->get_elem_type()) + ">"; } string type_prefix; if (b_cls) { type_prefix = "T"; } else { type_prefix = "I"; } string nm = normalize_clsnm(ttype->get_name(), type_prefix); if (b_exception_factory) { nm = nm + "Factory"; } if (b_cls) { if (!b_no_postfix) { nm = nm + "Impl"; } } if (b_exception_factory && b_full_exception_factory) { return type_name(ttype, true, true, false, false) + "." + nm; } return nm; } // returns "const " for some argument types string t_delphi_generator::input_arg_prefix(t_type* ttype) { // base types if (ttype->is_base_type()) { switch (((t_base_type*)ttype)->get_base()) { // these should be const'ed for optimal performamce case t_base_type::TYPE_STRING: // refcounted pointer case t_base_type::TYPE_UUID: // refcounted pointer case t_base_type::TYPE_I64: // larger than 32 bit case t_base_type::TYPE_DOUBLE: // larger than 32 bit return "const "; // all others don't need to be case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_BOOL: case t_base_type::TYPE_VOID: return ""; // we better always report any unknown types default: throw "compiler error: no input_arg_prefix() for base type " + t_base_type::t_base_name(((t_base_type*)ttype)->get_base()); } // enums } else if (ttype->is_enum()) { return ""; // usually <= 32 bit // containers } else if (ttype->is_map()) { return "const "; // refcounted pointer } else if (ttype->is_set()) { return "const "; // refcounted pointer } else if (ttype->is_list()) { return "const "; // refcounted pointer } // any other type, either TSomething or ISomething return "const "; // possibly refcounted pointer } string t_delphi_generator::base_type_name(t_base_type* tbase) { switch (tbase->get_base()) { case t_base_type::TYPE_VOID: // no "void" in Delphi language return ""; case t_base_type::TYPE_STRING: if (tbase->is_binary()) { if (ansistr_binary_) { return "System.AnsiString"; } else { return com_types_ ? "IThriftBytes" : "SysUtils.TBytes"; } } else { return com_types_ ? "System.WideString" : "System.string"; } case t_base_type::TYPE_UUID: return "System.TGuid"; case t_base_type::TYPE_BOOL: return "System.Boolean"; case t_base_type::TYPE_I8: return "System.ShortInt"; case t_base_type::TYPE_I16: return "System.SmallInt"; case t_base_type::TYPE_I32: return "System.Integer"; case t_base_type::TYPE_I64: return "System.Int64"; case t_base_type::TYPE_DOUBLE: return "System.Double"; default: throw "compiler error: no Delphi name for base type " + t_base_type::t_base_name(tbase->get_base()); } } string t_delphi_generator::declare_field(t_field* tfield, bool init, std::string prefix, bool is_xception_class) { (void)init; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); string result = prop_name(tfield, is_xception_class, prefix) + ": " + type_name(ftype, false, true, is_xception, true) + ";"; return result; } string t_delphi_generator::function_signature(t_function* tfunction, bool for_async, std::string full_cls, bool is_xception) { t_type* ttype = tfunction->get_returntype(); string prefix; if (full_cls == "") { prefix = ""; } else { prefix = full_cls + "."; } string signature = ""; if( for_async) { if (is_void(ttype)) { signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async(" + argument_list(tfunction->get_arglist()) + "): IFuture;"; // no IFuture in Delphi } else { signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async(" + argument_list(tfunction->get_arglist()) + "): IFuture<" + type_name(ttype, false, true, is_xception, true) + ">;"; } } else { if (is_void(ttype)) { signature = "procedure " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "(" + argument_list(tfunction->get_arglist()) + ");"; } else { signature = "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "(" + argument_list(tfunction->get_arglist()) + "): " + type_name(ttype, false, true, is_xception, true) + ";"; } } // deprecated method? only at intf decl! if( full_cls == "") { auto iter = tfunction->annotations_.find("deprecated"); if( tfunction->annotations_.end() != iter && !iter->second.empty()) { signature += " deprecated"; // empty annotation values end up with "1" somewhere, ignore these as well if ((iter->second.back().length() > 0) && (iter->second.back() != "1")) { signature += " " + make_pascal_string_literal(iter->second.back()); } signature += ";"; } } return signature; } string t_delphi_generator::argument_list(t_struct* tstruct) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; t_type* tt; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += "; "; } tt = (*f_iter)->get_type(); result += input_arg_prefix(tt); // const? result += normalize_name((*f_iter)->get_name()) + ": " + type_name(tt, false, true, tt->is_xception(), true); } return result; } string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string current_indent) { ostringstream result; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool first = true; t_type* tt; string line = ""; string newline_indent = current_indent + " "; bool firstline = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { line += ";"; } if (line.size() > 80) { if (firstline) { result << endl << newline_indent; firstline = false; } result << line << endl; line = newline_indent; } else if (line.size() > 0) { line += " "; } tt = (*f_iter)->get_type(); line += input_arg_prefix(tt); // const? line += constructor_param_name((*f_iter)->get_name()) + ": " + type_name(tt, false, true, tt->is_xception(), true); } if (line.size() > 0) { result << line; } string result_str; if (firstline) { result_str = " " + result.str(); } else { result_str = result.str(); } return result_str; } string t_delphi_generator::type_to_enum(t_type* type) { while (type->is_typedef()) { type = ((t_typedef*)type)->get_type(); } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.String_"; case t_base_type::TYPE_UUID: return "TType.Uuid"; case t_base_type::TYPE_BOOL: return "TType.Bool_"; case t_base_type::TYPE_I8: return "TType.Byte_"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.Double_"; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.Struct"; } else if (type->is_map()) { return "TType.Map"; } else if (type->is_set()) { return "TType.Set_"; } else if (type->is_list()) { return "TType.List"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } string t_delphi_generator::empty_value(t_type* type) { while (type->is_typedef()) { type = ((t_typedef*)type)->get_type(); } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "0"; case t_base_type::TYPE_STRING: if (type->is_binary()) { if (ansistr_binary_) { return "''"; } else { return "nil"; } } else { return "''"; } case t_base_type::TYPE_UUID: return "System.TGuid.Empty"; case t_base_type::TYPE_BOOL: return "False"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "0"; case t_base_type::TYPE_DOUBLE: return "0.0"; } } else if (type->is_enum()) { return "T" + type->get_name() + "(0)"; } else if (type->is_struct() || type->is_xception()) { return "nil"; } else if (type->is_map()) { return "nil"; } else if (type->is_set()) { return "nil"; } else if (type->is_list()) { return "nil"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out, t_field* tfield, bool is_xception_class) { t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); indent(out) << "procedure " << prop_name(tfield, is_xception_class, "Set") << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");" << endl; } void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out, t_field* tfield, bool is_xception_class) { t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); indent(out) << "function " << prop_name(tfield, is_xception_class, "Get") << ": " << type_name(ftype, false, true, is_xception, true) << ";" << endl; } void t_delphi_generator::generate_delphi_isset_reader_writer_definition(ostream& out, t_field* tfield, bool is_xception) { indent(out) << "function " << prop_name(tfield, is_xception,"Get__isset_") << ": System.Boolean;" << endl; indent(out) << "procedure " << prop_name(tfield, is_xception, "Set__isset_") << "( const value : System.Boolean);" << endl; } void t_delphi_generator::generate_delphi_clear_union_value(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factory_name) { (void)cls_prefix; (void)name; (void)type; (void)is_union; (void)is_xception_factory; (void)xception_factory_name; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); indent_impl(out) << "if " << prop_name(tfield, is_xception_class,"F__isset_") << " then begin" << endl; indent_up_impl(); indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := False;" << endl; indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := " << "Default( " << type_name(ftype, false, true, is_xception, true) << ");" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl; } void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factory_name) { (void)type; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); indent_impl(out) << "procedure " << cls_prefix << name << "." << prop_name(tfield, is_xception_class,"Set") << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); if (is_union) { indent_impl(out) << "ClearUnionValues;" << endl; } if (tfield->get_req() != t_field::T_REQUIRED) { indent_impl(out) << prop_name(tfield, is_xception_class,"F__isset_") << " := True;" << endl; } indent_impl(out) << prop_name(tfield, is_xception_class,fieldPrefix) << " := Value;" << endl; if (is_xception_class && (!is_xception_factory)) { indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class) << " := Value;" << endl; } indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class) { (void)type; t_type* ftype = tfield->get_type(); bool is_xception = ftype->is_xception(); indent_impl(out) << "function " << cls_prefix << name << "." << prop_name(tfield, is_xception_class,"Get") << ": " << type_name(ftype, false, true, is_xception, true) << ";" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "Result := " << prop_name(tfield, is_xception_class,fieldPrefix) << ";" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } void t_delphi_generator::generate_delphi_isset_reader_writer_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception) { (void)type; string isset_name = prop_name(tfield, is_xception, "__isset_"); indent_impl(out) << "function " << cls_prefix << name << "." << "Get" << isset_name << ": System.Boolean;" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; indent_impl(out) << "procedure " << cls_prefix << name << "." << "Set" << isset_name << "( const value: System.Boolean);" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << fieldPrefix << isset_name << " := value;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception) { (void)cls_prefix; string exception_cls_nm = type_name(tstruct, true, true); string cls_nm = type_name(tstruct, true, false, is_exception, is_exception); indent_impl(out) << "function " << cls_nm << ".CreateException: " << exception_cls_nm << ";" << endl; indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << endl; string factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; indent_impl(out) << "Result.F" << factory_name << " := Self;" << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; string propname; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { propname = prop_name(*f_iter, is_exception); if ((*f_iter)->get_req() != t_field::T_REQUIRED) { indent_impl(out) << "if " << prop_name(*f_iter, is_exception,"__isset_") << " then begin" << endl; indent_up_impl(); } indent_impl(out) << "Result." << propname << " := " << propname << ";" << endl; if ((*f_iter)->get_req() != t_field::T_REQUIRED) { indent_down_impl(); indent_impl(out) << "end;" << endl; } } indent_impl(out) << "Result.UpdateMessageProperty;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory) { ostringstream local_vars; ostringstream code_block; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent_impl(code_block) << "begin" << endl; indent_up_impl(); indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << endl; indent_impl(code_block) << "tracker := iprot.NextRecursionLevel;" << endl; // local bools for required fields for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { indent_impl(local_vars) << prop_name(*f_iter, is_exception,"_req_isset_") << " : System.Boolean;" << endl; indent_impl(code_block) << prop_name(*f_iter, is_exception,"_req_isset_") << " := FALSE;" << endl; } } indent_impl(code_block) << "struc := iprot.ReadStructBegin;" << endl; indent_impl(code_block) << "try" << endl; indent_up_impl(); indent_impl(code_block) << "while (true) do begin" << endl; indent_up_impl(); indent_impl(code_block) << "field_ := iprot.ReadFieldBegin();" << endl; indent_impl(code_block) << "if (field_.Type_ = TType.Stop) then Break;" << endl; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { code_block << endl; indent_impl(code_block) << "case field_.ID of" << endl; indent_up_impl(); } first = false; if (f_iter != fields.begin()) { code_block << endl; } indent_impl(code_block) << (*f_iter)->get_key() << ": begin" << endl; indent_up_impl(); indent_impl(code_block) << "if (field_.Type_ = " << type_to_enum((*f_iter)->get_type()) << ") then begin" << endl; indent_up_impl(); generate_deserialize_field(code_block, is_exception, *f_iter, "Self.", local_vars); // required field? if ((*f_iter)->get_req() == t_field::T_REQUIRED) { indent_impl(code_block) << prop_name(*f_iter, is_exception,"_req_isset_") << " := TRUE;" << endl; } indent_down_impl(); indent_impl(code_block) << "end else begin" << endl; indent_up_impl(); indent_impl(code_block) << "TProtocolUtil.Skip(iprot, field_.Type_);" << endl; indent_down_impl(); indent_impl(code_block) << "end;" << endl; indent_down_impl(); indent_impl(code_block) << "end;"; } if (!first) { code_block << endl; indent_down_impl(); indent_impl(code_block) << "else" << endl; indent_up_impl(); } indent_impl(code_block) << "TProtocolUtil.Skip(iprot, field_.Type_);" << endl; if (!first) { indent_down_impl(); indent_impl(code_block) << "end;" << endl; } indent_impl(code_block) << "iprot.ReadFieldEnd;" << endl; indent_down_impl(); indent_impl(code_block) << "end;" << endl; indent_down_impl(); indent_impl(code_block) << "finally" << endl; indent_up_impl(); indent_impl(code_block) << "iprot.ReadStructEnd;" << endl; indent_down_impl(); indent_impl(code_block) << "end;" << endl; // all required fields have been read? first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { if(first) { code_block << endl; first = false; } indent_impl(code_block) << "if not " << prop_name(*f_iter, is_exception,"_req_isset_") << endl; indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create(" << "'required field " << prop_name(*f_iter, is_exception) << " not set');" << endl; } } if( is_exception && (!is_x_factory)) { code_block << endl; indent_impl(code_block) << "UpdateMessageProperty;" << endl; } indent_down_impl(); indent_impl(code_block) << "end;" << endl << endl; string cls_nm; cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" << endl; indent_impl(out) << "var" << endl; indent_up_impl(); indent_impl(out) << "field_ : TThriftField;" << endl; indent_impl(out) << "struc : TThriftStruct;" << endl; indent_down_impl(); out << local_vars.str() << endl; out << code_block.str(); } void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory) { ostringstream local_vars; ostringstream code_block; string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent_impl(code_block) << "begin" << endl; indent_up_impl(); indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << endl; indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << endl; indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << endl; indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << endl; if (fields.size() > 0) { indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent_impl(code_block) << "if (" << prop_name(*f_iter, is_exception,"__isset_") << ") then" << endl; indent_impl(code_block) << "begin" << endl; indent_up_impl(); indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << endl; indent_impl(code_block) << "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";" << endl; indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << endl; indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << endl; generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars); indent_impl(code_block) << "oprot.WriteFieldEnd();" << endl; indent_down_impl(); } } indent_impl(code_block) << "oprot.WriteFieldStop();" << endl; indent_impl(code_block) << "oprot.WriteStructEnd();" << endl; indent_down_impl(); indent_impl(code_block) << "end;" << endl << endl; string cls_nm; cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << endl; indent_impl(out) << "var" << endl; indent_up_impl(); indent_impl(out) << "struc : TThriftStruct;" << endl; if (fields.size() > 0) { indent_impl(out) << "field_ : TThriftField;" << endl; } out << local_vars.str(); indent_down_impl(); out << code_block.str(); } void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory) { ostringstream local_vars; ostringstream code_block; string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent_impl(code_block) << "begin" << endl; indent_up_impl(); indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << endl; indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << endl; indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << endl; indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << endl; if (fields.size() > 0) { indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << endl; } for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { string fieldname = prop_name((*f_iter), is_exception); string isset_name = prop_name((*f_iter), is_exception, "__isset_"); bool null_allowed = type_can_be_null((*f_iter)->get_type()); bool is_required = ((*f_iter)->get_req() == t_field::T_REQUIRED); bool has_isset = (!is_required); if (is_required && null_allowed) { null_allowed = false; indent_impl(code_block) << "if (Self." << fieldname << " = nil)" << endl; indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create(" << "'required field " << fieldname << " not set');" << endl; } if (null_allowed) { indent_impl(code_block) << "if (Self." << fieldname << " <> nil)"; if (has_isset) { code_block << " and " << isset_name; } code_block << " then begin" << endl; indent_up_impl(); } else { if (has_isset) { indent_impl(code_block) << "if (" << isset_name << ") then begin" << endl; indent_up_impl(); } } indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << endl; indent_impl(code_block) << "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";" << endl; indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << endl; indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << endl; generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars); indent_impl(code_block) << "oprot.WriteFieldEnd();" << endl; if (null_allowed || has_isset) { indent_down_impl(); indent_impl(code_block) << "end;" << endl; } } indent_impl(code_block) << "oprot.WriteFieldStop();" << endl; indent_impl(code_block) << "oprot.WriteStructEnd();" << endl; indent_down_impl(); indent_impl(code_block) << "end;" << endl << endl; string cls_nm; cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << endl; indent_impl(out) << "var" << endl; indent_up_impl(); indent_impl(out) << "struc : TThriftStruct;" << endl; if (fields.size() > 0) { indent_impl(out) << "field_ : TThriftField;" << endl; } out << local_vars.str(); indent_down_impl(); out << code_block.str(); } void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; string cls_nm; if (is_exception) { cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true); } else { cls_nm = type_name(tstruct, true, false); } string tmp_sb = tmp("_sb"); string tmp_first = tmp("_first"); bool useFirstFlag = false; indent_impl(out) << "function " << cls_prefix << cls_nm << ".ToString: string;" << endl; indent_impl(out) << "var" << endl; indent_up_impl(); indent_impl(out) << tmp_sb << " : TThriftStringBuilder;" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool is_optional = ((*f_iter)->get_req() != t_field::T_REQUIRED); if (is_optional) { indent_impl(out) << tmp_first << " : System.Boolean;" << endl; useFirstFlag = true; } break; } indent_down_impl(); indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << tmp_sb << " := TThriftStringBuilder.Create('(');" << endl; indent_impl(out) << "try" << endl; indent_up_impl(); if (useFirstFlag) { indent_impl(out) << tmp_first << " := TRUE;" << endl; } bool had_required = false; // set to true after first required field has been processed for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool null_allowed = type_can_be_null((*f_iter)->get_type()); bool is_optional = ((*f_iter)->get_req() != t_field::T_REQUIRED); if (null_allowed) { indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " <> nil)"; if (is_optional) { out << " and " << prop_name(*f_iter, is_exception,"__isset_"); } out << " then begin" << endl; indent_up_impl(); } else { if (is_optional) { indent_impl(out) << "if (" << prop_name(*f_iter, is_exception, "__isset_") << ") then begin" << endl; indent_up_impl(); } } if (useFirstFlag && (!had_required)) { indent_impl(out) << "if not " << tmp_first << " then " << tmp_sb << ".Append(',');" << endl; if (is_optional) { indent_impl(out) << tmp_first << " := FALSE;" << endl; } indent_impl(out) << tmp_sb << ".Append('" << prop_name((*f_iter), is_exception) << ": ');" << endl; } else { indent_impl(out) << tmp_sb << ".Append(', " << prop_name((*f_iter), is_exception) << ": ');" << endl; } t_type* ttype = (*f_iter)->get_type(); while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } if (ttype->is_xception() || ttype->is_struct()) { indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " = nil) then " << tmp_sb << ".Append('') else " << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ".ToString());" << endl; } else if (ttype->is_enum()) { indent_impl(out) << tmp_sb << ".Append(EnumUtils<" << type_name(ttype, false, true, false, false) << ">.ToString( System.Ord( Self." << prop_name((*f_iter), is_exception) << ")));" << endl; } else if (ttype->is_uuid()) { indent_impl(out) << tmp_sb << ".Append( GUIDToString(Self." << prop_name((*f_iter), is_exception) << "));" << endl; } else { indent_impl(out) << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ");" << endl; } if (null_allowed || is_optional) { indent_down_impl(); indent_impl(out) << "end;" << endl; } if (!is_optional) { had_required = true; // now __first must be false, so we don't need to check it anymore } } indent_impl(out) << tmp_sb << ".Append(')');" << endl; indent_impl(out) << "Result := " << tmp_sb << ".ToString;" << endl; if (useFirstFlag) { indent_impl(out) << "if " << tmp_first << " then {prevent warning};" << endl; } indent_down_impl(); indent_impl(out) << "finally" << endl; indent_up_impl(); indent_impl(out) << tmp_sb << ".Free;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; } bool t_delphi_generator::is_void(t_type* type) { while (type->is_typedef()) { type = ((t_typedef*)type)->get_type(); } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); if (tbase == t_base_type::TYPE_VOID) { return true; } } return false; } std::string t_delphi_generator::display_name() const { return "Delphi"; } THRIFT_REGISTER_GENERATOR( delphi, "Delphi", " ansistr_binary: Use AnsiString for binary datatype (default is TBytes).\n" " register_types: Enable TypeRegistry, allows for creation of struct, union\n" " and container instances by interface or TypeInfo()\n" " constprefix: Name TConstants classes after IDL to reduce ambiguities\n" " events: Enable and use processing events in the generated code.\n" " xmldoc: Enable XMLDoc comments for Help Insight etc.\n" " async: Generate IAsync interface to use Parallel Programming Library (XE7+ only).\n" " com_types: Use COM-compatible data types (e.g. WideString).\n" " old_names: Compatibility: generate \"reserved\" identifiers with '_' postfix instead of '&' prefix.\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_swift_generator.cc0000644000000000000000000032425014370300523025413 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::set; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * Swift 3 code generator. * * Designed from the Swift/Cocoa code generator(s) */ class t_swift_generator : public t_oop_generator { public: t_swift_generator(t_program* program, const map& parsed_options, const string& option_string) : t_oop_generator(program) { update_keywords_for_validation(); (void)option_string; map::const_iterator iter; log_unexpected_ = false; async_clients_ = false; debug_descriptions_ = false; no_strict_ = false; namespaced_ = false; gen_cocoa_ = false; promise_kit_ = false; safe_enums_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("log_unexpected") == 0) { log_unexpected_ = true; } else if( iter->first.compare("async_clients") == 0) { async_clients_ = true; } else if( iter->first.compare("no_strict") == 0) { no_strict_ = true; } else if( iter->first.compare("debug_descriptions") == 0) { debug_descriptions_ = true; } else if( iter->first.compare("namespaced") == 0) { namespaced_ = true; } else if( iter->first.compare("cocoa") == 0) { gen_cocoa_ = true; } else if( iter->first.compare("safe_enums") == 0) { safe_enums_ = true; } else if( iter->first.compare("promise_kit") == 0) { if (gen_cocoa_ == false) { throw "PromiseKit only available with Swift 2.x, use `cocoa` option" + iter->first; } promise_kit_ = true; } else { throw "unknown option swift:" + iter->first; } } out_dir_base_ = "gen-swift"; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; void generate_consts(vector consts) override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; void render_const_value(ostream& out, t_type* type, t_const_value* value); void generate_swift_struct(ostream& out, t_struct* tstruct, bool is_private); void generate_swift_struct_init(ostream& out, t_struct* tstruct, bool all, bool is_private); void generate_swift_struct_implementation(ostream& out, t_struct* tstruct, bool is_result, bool is_private); void generate_swift_struct_hashable_extension(ostream& out, t_struct* tstruct, bool is_private); void generate_swift_struct_equatable_extension(ostream& out, t_struct* tstruct, bool is_private); void generate_swift_struct_thrift_extension(ostream& out, t_struct* tstruct, bool is_result, bool is_private); void generate_swift_struct_reader(ostream& out, t_struct* tstruct, bool is_private); void generate_swift_struct_printable_extension(ostream& out, t_struct* tstruct); void generate_swift_union_reader(ostream& out, t_struct* tstruct); string function_result_helper_struct_type(t_service *tservice, t_function* tfunction); string function_args_helper_struct_type(t_service* tservice, t_function* tfunction); void generate_function_helpers(t_service *tservice, t_function* tfunction); /** * Service-level generation functions */ void generate_swift_service_protocol(ostream& out, t_service* tservice); void generate_swift_service_protocol_async(ostream& out, t_service* tservice); void generate_swift_service_client(ostream& out, t_service* tservice); void generate_swift_service_client_async(ostream& out, t_service* tservice); void generate_swift_service_client_send_function_implementation(ostream& out, t_service* tservice, t_function* tfunction, bool needs_protocol); void generate_swift_service_client_send_function_invocation(ostream& out, t_function* tfunction); void generate_swift_service_client_send_async_function_invocation(ostream& out, t_function* tfunction); void generate_swift_service_client_recv_function_implementation(ostream& out, t_service* tservice, t_function* tfunction, bool needs_protocol); void generate_swift_service_client_implementation(ostream& out, t_service* tservice); void generate_swift_service_client_async_implementation(ostream& out, t_service* tservice); void generate_swift_service_server(ostream& out, t_service* tservice); void generate_swift_service_server_implementation(ostream& out, t_service* tservice); void generate_swift_service_helpers(t_service* tservice); /** * Helper rendering functions */ string swift_imports(); string swift_thrift_imports(); string type_name(t_type* ttype, bool is_optional=false, bool is_forced=false); string base_type_name(t_base_type* tbase); string declare_property(t_field* tfield, bool is_private); string function_signature(t_function* tfunction); string async_function_signature(t_function* tfunction); string argument_list(t_struct* tstruct, string protocol_name, bool is_internal); string type_to_enum(t_type* ttype, bool qualified=false); string maybe_escape_identifier(const string& identifier); void populate_reserved_words(); /** Swift 3 specific */ string enum_case_name(t_enum_value* tenum_case, bool declaration); string enum_const_name(string enum_identifier); void function_docstring(ostream& out, t_function* tfunction); void async_function_docstring(ostream& out, t_function* tfunction); void generate_docstring(ostream& out, string& doc); /** Swift 2/Cocoa carryover */ string promise_function_signature(t_function* tfunction); string function_name(t_function* tfunction); void generate_old_swift_struct_writer(ostream& out,t_struct* tstruct, bool is_private); void generate_old_swift_struct_result_writer(ostream& out, t_struct* tstruct); /** Swift 2/Cocoa backwards compatibility*/ void generate_old_enum(t_enum* tenum); void generate_old_swift_struct(ostream& out, t_struct* tstruct, bool is_private); void generate_old_swift_service_client_async_implementation(ostream& out, t_service* tservice); static std::string get_real_swift_module(const t_program* program) { std::string real_module = program->get_namespace("swift"); if (real_module.empty()) { return program->get_name(); } return real_module; } private: void block_open(ostream& out) { out << " {" << endl; indent_up(); } void block_close(ostream& out, bool end_line=true) { indent_down(); indent(out) << "}"; if (end_line) out << endl; } bool field_is_optional(t_field* tfield) { bool opt = tfield->get_req() == t_field::T_OPTIONAL; if (tfield->annotations_.find("swift.nullable") != tfield->annotations_.end() && tfield->get_req() != t_field::T_REQUIRED) { opt = true; } if (gen_cocoa_) { // Backwards compatibility, only if its actually "optional" opt = tfield->get_req() == t_field::T_OPTIONAL; } return opt; } bool struct_has_required_fields(t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!field_is_optional(*m_iter)) { return true; } } return false; } bool struct_has_optional_fields(t_struct* tstruct) { const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (field_is_optional(*m_iter)) { return true; } } return false; } string constants_declarations_; /** * File streams */ ofstream_with_content_based_conditional_update f_decl_; ofstream_with_content_based_conditional_update f_impl_; bool log_unexpected_; bool async_clients_; bool debug_descriptions_; bool no_strict_; bool namespaced_; bool safe_enums_; set swift_reserved_words_; /** Swift 2/Cocoa compatibility */ bool gen_cocoa_; bool promise_kit_; protected: std::set lang_keywords_for_validation() const override { return {}; } }; /** * Prepares for file generation by opening up the necessary file output * streams. */ void t_swift_generator::init_generator() { // Make output directory string module = get_real_swift_module(program_); string out_dir = get_out_dir(); string module_path = out_dir; string name = program_name_; if (namespaced_ && !module.empty()) { module_path = module_path + "/" + module; name = module; } MKDIR(module_path.c_str()); populate_reserved_words(); // we have a .swift declarations file... string f_decl_name = name + ".swift"; string f_decl_fullname = module_path + "/" + f_decl_name; f_decl_.open(f_decl_fullname.c_str()); f_decl_ << autogen_comment() << endl; f_decl_ << swift_imports() << swift_thrift_imports() << endl; // ...and a .swift implementation extensions file string f_impl_name = name + "+Exts.swift"; string f_impl_fullname = module_path + "/" + f_impl_name; f_impl_.open(f_impl_fullname.c_str()); f_impl_ << autogen_comment() << endl; f_impl_ << swift_imports() << swift_thrift_imports() << endl; } /** * Prints standard Cocoa imports * * @return List of imports for Cocoa libraries */ string t_swift_generator::swift_imports() { vector includes_list; includes_list.emplace_back("Foundation"); ostringstream includes; vector::const_iterator i_iter; for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) { includes << "import " << *i_iter << endl; } if (namespaced_) { const vector& program_includes = program_->get_includes(); for (auto program_include : program_includes) { includes << ("import " + get_real_swift_module(program_include)) << endl; } } includes << endl; return includes.str(); } /** * Prints Thrift runtime imports * * @return List of imports necessary for Thrift runtime */ string t_swift_generator::swift_thrift_imports() { vector includes_list; includes_list.emplace_back("Thrift"); if (gen_cocoa_ && promise_kit_) { includes_list.emplace_back("PromiseKit"); } ostringstream includes; vector::const_iterator i_iter; for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) { includes << "import " << *i_iter << endl; } includes << endl; return includes.str(); } /** * Finish up generation. */ void t_swift_generator::close_generator() { // stick our constants declarations at the end of the header file // since they refer to things we are defining. f_decl_ << constants_declarations_ << endl; } /** * Generates a typedef. This is just a simple 1-liner in Swift * * @param ttypedef The type definition */ void t_swift_generator::generate_typedef(t_typedef* ttypedef) { f_decl_ << indent() << "public typealias " << ttypedef->get_symbolic() << " = " << type_name(ttypedef->get_type()) << endl; f_decl_ << endl; } /** * Generates code for an enumerated type. In Swift, this is * essentially the same as the thrift definition itself, using * Swift syntax. Conforms to TEnum which * implementes read/write. * * @param tenum The enumeration */ void t_swift_generator::generate_enum(t_enum* tenum) { if (gen_cocoa_) { generate_old_enum(tenum); return; } f_decl_ << indent() << "public enum " << tenum->get_name() << " : TEnum"; block_open(f_decl_); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { f_decl_ << indent() << "case " << enum_case_name((*c_iter), true) << endl; } // unknown associated value case for safety and similar behavior to other languages if (safe_enums_) { f_decl_ << indent() << "case unknown(Int32)" << endl; } f_decl_ << endl; // TSerializable read(from:) f_decl_ << indent() << "public static func read(from proto: TProtocol) throws -> " << tenum->get_name(); block_open(f_decl_); f_decl_ << indent() << "let raw: Int32 = try proto.read()" << endl; f_decl_ << indent() << "let new = " << tenum->get_name() << "(rawValue: raw)" << endl; f_decl_ << indent() << "if let unwrapped = new {" << endl; indent_up(); f_decl_ << indent() << "return unwrapped" << endl; indent_down(); f_decl_ << indent() << "} else {" << endl; indent_up(); f_decl_ << indent() << "throw TProtocolError(error: .invalidData," << endl; f_decl_ << indent() << " message: \"Invalid enum value (\\(raw)) for \\(" << tenum->get_name() << ".self)\")" << endl; indent_down(); f_decl_ << indent() << "}" << endl; block_close(f_decl_); // empty init for TSerializable f_decl_ << endl; f_decl_ << indent() << "public init()"; block_open(f_decl_); f_decl_ << indent() << "self = ." << enum_case_name(constants.front(), false) << endl; block_close(f_decl_); f_decl_ << endl; // rawValue getter f_decl_ << indent() << "public var rawValue: Int32"; block_open(f_decl_); f_decl_ << indent() << "switch self {" << endl; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { f_decl_ << indent() << "case ." << enum_case_name((*c_iter), true) << ": return " << (*c_iter)->get_value() << endl; } if (safe_enums_) { f_decl_ << indent() << "case .unknown(let value): return value" << endl; } f_decl_ << indent() << "}" << endl; block_close(f_decl_); f_decl_ << endl; // convenience rawValue initalizer f_decl_ << indent() << "public init?(rawValue: Int32)"; block_open(f_decl_); f_decl_ << indent() << "switch rawValue {" << endl;; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { f_decl_ << indent() << "case " << (*c_iter)->get_value() << ": self = ." << enum_case_name((*c_iter), true) << endl; } if (!safe_enums_) { f_decl_ << indent() << "default: return nil" << endl; } else { f_decl_ << indent() << "default: self = .unknown(rawValue)" << endl; } f_decl_ << indent() << "}" << endl; block_close(f_decl_); block_close(f_decl_); f_decl_ << endl; } /** * Generates code for an enumerated type. This is for Swift 2.x/Cocoa * backwards compatibility * * @param tenum The enumeration */ void t_swift_generator::generate_old_enum(t_enum* tenum) { f_decl_ << indent() << "public enum " << tenum->get_name() << " : Int32"; block_open(f_decl_); vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { f_decl_ << indent() << "case " << (*c_iter)->get_name() << " = " << (*c_iter)->get_value() << endl; } f_decl_ << endl; f_decl_ << indent() << "public init() { self.init(rawValue: " << constants.front()->get_value() << ")! }" << endl; block_close(f_decl_); f_decl_ << endl; f_impl_ << indent() << "extension " << tenum->get_name() << " : TEnum"; block_open(f_impl_); f_impl_ << endl; f_impl_ << indent() << "public static func readValueFromProtocol(proto: TProtocol) throws -> " << tenum->get_name(); block_open(f_impl_); f_impl_ << indent() << "var raw = Int32()" << endl << indent() << "try proto.readI32(&raw)" << endl << indent() << "return " << tenum->get_name() << "(rawValue: raw)!" << endl; block_close(f_impl_); f_impl_ << endl; f_impl_ << indent() << "public static func writeValue(value: " << tenum->get_name() << ", toProtocol proto: TProtocol) throws"; block_open(f_impl_); f_impl_ << indent() << "try proto.writeI32(value.rawValue)" << endl; block_close(f_impl_); f_impl_ << endl; block_close(f_impl_); f_impl_ << endl; } string t_swift_generator::enum_case_name(t_enum_value* tenum_case, bool declaration) { string name = tenum_case->get_name(); // force to lowercase for Swift style, maybe escape if its a keyword std::transform(name.begin(), name.end(), name.begin(), ::tolower); if (declaration) { name = maybe_escape_identifier(name); } return name; } /** * Renders a constant enum value by transforming the value portion to lowercase * for Swift style. */ string t_swift_generator::enum_const_name(string enum_identifier) { string::iterator it; for (it = enum_identifier.begin(); it < enum_identifier.end(); ++it) { if ((*it) == '.') { break; } } std::transform(it, enum_identifier.end(), it, ::tolower); return enum_identifier; } /** * Generates public constants for all Thrift constants. * * @param consts Constants to generate */ void t_swift_generator::generate_consts(vector consts) { ostringstream const_interface; // Public constants for base types & strings vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { t_type* type = (*c_iter)->get_type(); const_interface << "public let " << capitalize((*c_iter)->get_name()) << " : " << type_name(type) << " = "; render_const_value(const_interface, type, (*c_iter)->get_value()); const_interface << endl << endl; } // this gets spit into the header file in ::close_generator constants_declarations_ = const_interface.str(); } /** * Generates a struct definition for a thrift data type. This is a struct * with public members. Optional types are used for optional properties to * allow them to be tested for availability. Separate inits are included for * required properties & all properties. * * Generates extensions to provide conformance to TStruct, TSerializable, * Hashable & Equatable * * @param tstruct The struct definition */ void t_swift_generator::generate_struct(t_struct* tstruct) { generate_swift_struct(f_decl_, tstruct, false); generate_swift_struct_implementation(f_impl_, tstruct, false, false); } /** * Exceptions are structs, but they conform to Error * * @param tstruct The struct definition */ void t_swift_generator::generate_xception(t_struct* txception) { generate_swift_struct(f_decl_, txception, false); generate_swift_struct_implementation(f_impl_, txception, false, false); } void t_swift_generator::generate_docstring(ostream& out, string& doc) { if (doc != "") { std::vector strings; std::string::size_type pos = 0; std::string::size_type prev = 0; while (((pos = doc.find("\n", prev)) != std::string::npos) || ((pos = doc.find("\r", prev)) != std::string::npos) || ((pos = doc.find("\r\n", prev)) != std::string::npos)) { strings.push_back(doc.substr(prev, pos - prev)); prev = pos + 1; } // To get the last substring (or only, if delimiter is not found) strings.push_back(doc.substr(prev)); vector::const_iterator d_iter; for (d_iter = strings.begin(); d_iter != strings.end(); ++d_iter) { if ((*d_iter) != "") { out << indent() << "/// " << (*d_iter) << endl; } } } } /** * Generate the interface for a struct. Only properties and * init methods are included. * * @param tstruct The struct definition * @param is_private * Is the struct public or private */ void t_swift_generator::generate_swift_struct(ostream& out, t_struct* tstruct, bool is_private) { if (gen_cocoa_) { generate_old_swift_struct(out, tstruct, is_private); return; } string doc = tstruct->get_doc(); generate_docstring(out, doc); // properties const vector& members = tstruct->get_members(); vector::const_iterator m_iter; if (tstruct->is_union()) { // special, unions out << indent() << "public enum " << tstruct->get_name(); block_open(out); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << endl; string doc = (*m_iter)->get_doc(); generate_docstring(out, doc); out << indent() << "case " << maybe_escape_identifier((*m_iter)->get_name()) << "(val: " << type_name((*m_iter)->get_type(), false) << ")" << endl; } } else { // Normal structs string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public"; out << indent() << visibility << " final class " << tstruct->get_name(); if (tstruct->is_xception()) { out << " : Swift.Error"; // Error seems to be a common exception name in thrift } block_open(out); vector sorted = members; sort(sorted.begin(), sorted.end(), [](t_field *a, t_field *b) { return (a->get_key() < b->get_key()); } ); for (m_iter = sorted.begin(); m_iter != sorted.end(); ++m_iter) { out << endl; // TODO: Defaults string doc = (*m_iter)->get_doc(); generate_docstring(out, doc); out << indent() << declare_property(*m_iter, is_private) << endl; } out << endl; out << endl; if (!struct_has_required_fields(tstruct)) { indent(out) << visibility << " init() { }" << endl; } if (struct_has_required_fields(tstruct)) { generate_swift_struct_init(out, tstruct, false, is_private); } if (struct_has_optional_fields(tstruct)) { generate_swift_struct_init(out, tstruct, true, is_private); } } block_close(out); out << endl; } /** * Legacy Swift2/Cocoa generator * * @param tstruct * @param is_private */ void t_swift_generator::generate_old_swift_struct(ostream& out, t_struct* tstruct, bool is_private) { string visibility = is_private ? "private" : "public"; out << indent() << visibility << " final class " << tstruct->get_name(); if (tstruct->is_xception()) { out << " : ErrorType"; } block_open(out); // properties const vector& members = tstruct->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << endl; out << indent() << declare_property(*m_iter, is_private) << endl; } out << endl; // init indent(out) << visibility << " init()"; block_open(out); block_close(out); out << endl; if (struct_has_required_fields(tstruct)) { generate_swift_struct_init(out, tstruct, false, is_private); } if (struct_has_optional_fields(tstruct)) { generate_swift_struct_init(out, tstruct, true, is_private); } block_close(out); out << endl; } /** * Generate struct init for properties * * @param tstruct The structure definition * @param all Generate init with all or just required properties * @param is_private * Is the initializer public or private */ void t_swift_generator::generate_swift_struct_init(ostream& out, t_struct* tstruct, bool all, bool is_private) { string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public"; indent(out) << visibility << " init("; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; bool first=true; for (m_iter = members.begin(); m_iter != members.end();) { if (all || !field_is_optional(*m_iter)) { if (first) { first = false; } else { out << ", "; } out << (*m_iter)->get_name() << ": " << maybe_escape_identifier(type_name((*m_iter)->get_type(), field_is_optional(*m_iter))); } ++m_iter; } out << ")"; block_open(out); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!gen_cocoa_) { bool should_set = all; should_set = should_set || !field_is_optional((*m_iter)); if (should_set) { out << indent() << "self." << maybe_escape_identifier((*m_iter)->get_name()) << " = " << maybe_escape_identifier((*m_iter)->get_name()) << endl; } } else { /** legacy Swift2/Cocoa */ if (all || (*m_iter)->get_req() == t_field::T_REQUIRED || (*m_iter)->get_req() == t_field::T_OPT_IN_REQ_OUT) { out << indent() << "self." << maybe_escape_identifier((*m_iter)->get_name()) << " = " << maybe_escape_identifier((*m_iter)->get_name()) << endl; } } } block_close(out); out << endl; } /** * Generate the hashable protocol implmentation * * @param tstruct The structure definition * @param is_private * Is the struct public or private */ void t_swift_generator::generate_swift_struct_hashable_extension(ostream& out, t_struct* tstruct, bool is_private) { string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public"; indent(out) << "extension " << tstruct->get_name() << " : Hashable"; block_open(out); out << endl; indent(out) << visibility << " func hash(into hasher: inout Hasher)"; block_open(out); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; if (!members.empty()) { if (!tstruct->is_union()) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* tfield = *m_iter; indent(out) << "hasher.combine(" << maybe_escape_identifier(tfield->get_name()) << ")" << endl; } } else { indent(out) << "switch self {" << endl; for (m_iter = members.begin(); m_iter != members.end(); m_iter++) { t_field *tfield = *m_iter; indent(out) << "case ." << tfield->get_name() << "(let val): hasher.combine(val)" << endl; } indent(out) << "}" << endl << endl; } } block_close(out); out << endl; block_close(out); out << endl; } /** * Generate the equatable protocol implementation * * @param tstruct The structure definition * @param is_private * Is the struct public or private */ void t_swift_generator::generate_swift_struct_equatable_extension(ostream& out, t_struct* tstruct, bool is_private) { string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public"; indent(out) << visibility << " func ==(lhs: " << type_name(tstruct) << ", rhs: " << type_name(tstruct) << ") -> Bool"; block_open(out); indent(out) << "return"; const vector& members = tstruct->get_members(); vector::const_iterator m_iter; if (members.size()) { if (!tstruct->is_union()) { out << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end();) { t_field* tfield = *m_iter; indent(out) << "(lhs." << maybe_escape_identifier(tfield->get_name()) << (gen_cocoa_ ? " ?" : " ") << "== rhs." << maybe_escape_identifier(tfield->get_name()) << ")"; // swift 2 ?== operator not in 3? if (++m_iter != members.end()) { out << " &&"; } out << endl; } indent_down(); } else { block_open(out); indent(out) << "switch (lhs, rhs) {" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* tfield = *m_iter; indent(out) << "case (." << tfield->get_name() << "(let lval), ." << tfield->get_name() << "(let rval)): return lval == rval" << endl; } indent(out) << "default: return false" << endl; indent(out) << "}" << endl; indent_down(); indent(out) << "}()" << endl; } } else { out << " true" << endl; } block_close(out); out << endl; } /** * Generate struct implementation. Produces extensions that * fulfill the requisite protocols to complete the value. * * @param tstruct The struct definition * @param is_result * If this is a result it needs a different writer * @param is_private * Is the struct public or private */ void t_swift_generator::generate_swift_struct_implementation(ostream& out, t_struct* tstruct, bool is_result, bool is_private) { generate_swift_struct_equatable_extension(out, tstruct, is_private); if (!is_private && !is_result && !gen_cocoa_) { // old compiler didn't use debug_descriptions, OR it with gen_cocoa_ so the flag doesn't matter w/ cocoa generate_swift_struct_printable_extension(out, tstruct); } generate_swift_struct_hashable_extension(out, tstruct, is_private); generate_swift_struct_thrift_extension(out, tstruct, is_result, is_private); out << endl << endl; } /** * Generate the TStruct protocol implementation. * * @param tstruct The structure definition * @param is_result * Is the struct a result value * @param is_private * Is the struct public or private */ void t_swift_generator::generate_swift_struct_thrift_extension(ostream& out, t_struct* tstruct, bool is_result, bool is_private) { indent(out) << "extension " << tstruct->get_name() << " : TStruct"; block_open(out); out << endl; if (!gen_cocoa_) { /** Swift 3, no writer we just write field ID's */ string access = (is_private) ? (gen_cocoa_ ? "private" : "fileprivate") : "public"; // generate fieldID's dictionary out << indent() << access << " static var fieldIds: [String: Int32]"; block_open(out); out << indent() << "return ["; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; bool wrote = false; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { wrote = true; out << "\"" << (*f_iter)->get_name() << "\": " << (*f_iter)->get_key() << ", "; } if (!wrote) { // pad a colon out << ":"; } out << "]" << endl; block_close(out); out << endl; out << indent() << access << " static var structName: String { return \"" << tstruct->get_name() << "\" }" << endl << endl; if (tstruct->is_union()) { generate_swift_union_reader(out, tstruct); } else { generate_swift_struct_reader(out, tstruct, is_private); } } else { /** Legacy Swift2/Cocoa */ generate_swift_struct_reader(out, tstruct, is_private); if (is_result) { generate_old_swift_struct_result_writer(out, tstruct); } else { generate_old_swift_struct_writer(out, tstruct, is_private); } } block_close(out); out << endl; } void t_swift_generator::generate_swift_union_reader(ostream& out, t_struct* tstruct) { indent(out) << "public static func read(from proto: TProtocol) throws -> " << tstruct->get_name(); block_open(out); indent(out) << "_ = try proto.readStructBegin()" << endl; indent(out) << "var ret: " << tstruct->get_name() << "?"; out << endl; indent(out) << "fields: while true"; block_open(out); out << endl; indent(out) << "let (_, fieldType, fieldID) = try proto.readFieldBegin()" << endl << endl; indent(out) << "switch (fieldID, fieldType)"; block_open(out); indent(out) << "case (_, .stop): break fields" << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):"; string padding = ""; t_type* type = get_true_type((*f_iter)->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: case t_base_type::TYPE_DOUBLE: case t_base_type::TYPE_UUID: padding = " "; break; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: padding = " "; break; case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: padding = " "; break; default: break; } } else if (type->is_enum() || type->is_set() || type->is_map()) { padding = " "; } else if (type->is_struct() || type->is_xception()) { padding = " "; } else if (type->is_list()) { padding = " "; } indent(out) << padding << "ret = " << tstruct->get_name() << "." << (*f_iter)->get_name() << "(val: " << "try " << type_name((*f_iter)->get_type(), false, false) << ".read(from: proto))" << endl; } indent(out) << "case let (_, unknownType): try proto.skip(type: unknownType)" << endl; block_close(out); indent(out) << "try proto.readFieldEnd()" << endl; block_close(out); out << endl; indent(out) << "try proto.readStructEnd()" << endl; indent(out) << "if let ret = ret"; block_open(out); indent(out) << "return ret" << endl; block_close(out); out << endl; indent(out) << "throw TProtocolError(error: .unknown, message: \"Missing required value for type: " << tstruct->get_name() << "\")"; block_close(out); out << endl; } /** * Generates a function to read a struct from * from a protocol. (TStruct compliance) * * @param tstruct The structure definition * @param is_private * Is the struct public or private */ void t_swift_generator::generate_swift_struct_reader(ostream& out, t_struct* tstruct, bool is_private) { if (!gen_cocoa_) { /** Swift 3 case */ string visibility = is_private ? "fileprivate" : "public"; indent(out) << visibility << " static func read(from proto: TProtocol) throws -> " << tstruct->get_name(); block_open(out); indent(out) << "_ = try proto.readStructBegin()" << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool optional = field_is_optional(*f_iter); indent(out) << "var " << maybe_escape_identifier((*f_iter)->get_name()) << ": " << type_name((*f_iter)->get_type(), optional, !optional) << endl; } out << endl; // Loop over reading in fields indent(out) << "fields: while true"; block_open(out); out << endl; indent(out) << "let (_, fieldType, fieldID) = try proto.readFieldBegin()" << endl << endl; indent(out) << "switch (fieldID, fieldType)"; block_open(out); indent(out) << "case (_, .stop): break fields" << endl; // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):"; string padding = ""; t_type* type = get_true_type((*f_iter)->get_type()); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: case t_base_type::TYPE_DOUBLE: case t_base_type::TYPE_UUID: padding = " "; break; case t_base_type::TYPE_BOOL: case t_base_type::TYPE_I8: padding = " "; break; case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: padding = " "; break; default: break; } } else if (type->is_enum() || type->is_set() || type->is_map()) { padding = " "; } else if (type->is_struct() || type->is_xception()) { padding = " "; } else if (type->is_list()) { padding = " "; } out << padding << maybe_escape_identifier((*f_iter)->get_name()) << " = try " << type_name((*f_iter)->get_type(), false, false) << ".read(from: proto)" << endl; } indent(out) << "case let (_, unknownType): try proto.skip(type: unknownType)" << endl; block_close(out); out << endl; // Read field end marker indent(out) << "try proto.readFieldEnd()" << endl; block_close(out); out << endl; indent(out) << "try proto.readStructEnd()" << endl; if (struct_has_required_fields(tstruct)) { // performs various checks (e.g. check that all required fields are set) indent(out) << "// Required fields" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (field_is_optional(*f_iter)) { continue; } indent(out) << "try proto.validateValue(" << maybe_escape_identifier((*f_iter)->get_name()) << ", " << "named: \"" << (*f_iter)->get_name() << "\")" << endl; } } out << endl; indent(out) << "return " << tstruct->get_name() << "("; for (f_iter = fields.begin(); f_iter != fields.end();) { out << (*f_iter)->get_name() << ": " << maybe_escape_identifier((*f_iter)->get_name()); if (++f_iter != fields.end()) { out << ", "; } } } else { /** Legacy Swif2/Cocoa case */ string visibility = is_private ? "private" : "public"; indent(out) << visibility << " static func readValueFromProtocol(__proto: TProtocol) throws -> " << tstruct->get_name(); block_open(out); out << endl; indent(out) << "try __proto.readStructBegin()" << endl << endl; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { bool optional = field_is_optional(*f_iter); indent(out) << "var " << maybe_escape_identifier((*f_iter)->get_name()) << " : " << type_name((*f_iter)->get_type(), optional, !optional) << endl; } out << endl; // Loop over reading in fields indent(out) << "fields: while true"; block_open(out); out << endl; indent(out) << "let (_, fieldType, fieldID) = try __proto.readFieldBegin()" << endl << endl; indent(out) << "switch (fieldID, fieldType)"; block_open(out); indent(out) << "case (_, .STOP):" << endl; indent_up(); indent(out) << "break fields" << endl << endl; indent_down(); // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):" << endl; indent_up(); indent(out) << maybe_escape_identifier((*f_iter)->get_name()) << " = try __proto.readValue() as " << type_name((*f_iter)->get_type()) << endl << endl; indent_down(); } indent(out) << "case let (_, unknownType):" << endl; indent_up(); indent(out) << "try __proto.skipType(unknownType)" << endl; indent_down(); block_close(out); out << endl; // Read field end marker indent(out) << "try __proto.readFieldEnd()" << endl; block_close(out); out << endl; indent(out) << "try __proto.readStructEnd()" << endl; out << endl; if (struct_has_required_fields(tstruct)) { // performs various checks (e.g. check that all required fields are set) indent(out) << "// Required fields" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (field_is_optional(*f_iter)) { continue; } indent(out) << "try __proto.validateValue(" << (*f_iter)->get_name() << ", " << "named: \"" << (*f_iter)->get_name() << "\")" << endl; } } out << endl; indent(out) << "return " << tstruct->get_name() << "("; for (f_iter = fields.begin(); f_iter != fields.end();) { out << (*f_iter)->get_name() << ": " << maybe_escape_identifier((*f_iter)->get_name()); if (++f_iter != fields.end()) { out << ", "; } } } out << ")" << endl; block_close(out); out << endl; } /** * Generates a function to write a struct to * a protocol. (TStruct compliance) ONLY FOR SWIFT2/COCOA * * @param tstruct The structure definition * @param is_private * Is the struct public or private */ void t_swift_generator::generate_old_swift_struct_writer(ostream& out, t_struct* tstruct, bool is_private) { string visibility = is_private ? "private" : "public"; indent(out) << visibility << " static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws"; block_open(out); out << endl; string name = tstruct->get_name(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent(out) << "try __proto.writeStructBeginWithName(\"" << name << "\")" << endl; out << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field *tfield = *f_iter; bool optional = field_is_optional(tfield); if (optional) { indent(out) << "if let " << maybe_escape_identifier(tfield->get_name()) << " = __value." << maybe_escape_identifier(tfield->get_name()); block_open(out); } indent(out) << "try __proto.writeFieldValue(" << (optional ? "" : "__value.") << maybe_escape_identifier(tfield->get_name()) << ", " << "name: \"" << tfield->get_name() << "\", " << "type: " << type_to_enum(tfield->get_type()) << ", " << "id: " << tfield->get_key() << ")" << endl; if (optional) { block_close(out); } out << endl; } indent(out) << "try __proto.writeFieldStop()" << endl << endl; indent(out) << "try __proto.writeStructEnd()" << endl; block_close(out); out << endl; } /** * Generates a function to read a struct from * from a protocol. (TStruct compliance) ONLY FOR SWIFT 2/COCOA * * This is specifically a function result. Only * the first available field is written. * * @param tstruct The structure definition */ void t_swift_generator::generate_old_swift_struct_result_writer(ostream& out, t_struct* tstruct) { indent(out) << "private static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws"; block_open(out); out << endl; string name = tstruct->get_name(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent(out) << "try __proto.writeStructBeginWithName(\"" << name << "\")" << endl; out << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field *tfield = *f_iter; indent(out) << "if let result = __value." << (*f_iter)->get_name(); block_open(out); indent(out) << "try __proto.writeFieldValue(result, " << "name: \"" << tfield->get_name() << "\", " << "type: " << type_to_enum(tfield->get_type()) << ", " << "id: " << tfield->get_key() << ")" << endl; block_close(out); } // Write the struct map indent(out) << "try __proto.writeFieldStop()" << endl << endl; indent(out) << "try __proto.writeStructEnd()" << endl; block_close(out); out << endl; } /** * Generates a description method for the given struct * * @param tstruct The struct definition */ void t_swift_generator::generate_swift_struct_printable_extension(ostream& out, t_struct* tstruct) { // Allow use of debugDescription so the app can add description via a cateogory/extension const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; indent(out) << "extension " << tstruct->get_name() << " : " << (debug_descriptions_ ? "CustomDebugStringConvertible" : "CustomStringConvertible"); block_open(out); out << endl; indent(out) << "public var description : String"; block_open(out); indent(out) << "var desc = \"" << tstruct->get_name(); if (!gen_cocoa_) { if (!tstruct->is_union()) { out << "(\"" << endl; for (f_iter = fields.begin(); f_iter != fields.end();) { indent(out) << "desc += \"" << (*f_iter)->get_name() << "=\\(String(describing: self." << maybe_escape_identifier((*f_iter)->get_name()) << "))"; if (++f_iter != fields.end()) { out << ", "; } out << "\"" << endl; } } else { out << ".\"" << endl; indent(out) << "switch self {" << endl; for (f_iter = fields.begin(); f_iter != fields.end();f_iter++) { indent(out) << "case ." << (*f_iter)->get_name() << "(let val): " << "desc += \"" << (*f_iter)->get_name() << "(val: \\(val))\"" << endl; } indent(out) << "}" << endl; } } else { out << "(\"" << endl; for (f_iter = fields.begin(); f_iter != fields.end();) { indent(out) << "desc += \"" << (*f_iter)->get_name() << "=\\(self." << maybe_escape_identifier((*f_iter)->get_name()) << ")"; if (++f_iter != fields.end()) { out << ", "; } out << "\"" << endl; } indent(out) << "desc += \")\"" << endl; } indent(out) << "return desc" << endl; block_close(out); out << endl; block_close(out); out << endl; } /** * Generates a thrift service. In Swift this consists of a * protocol definition and a client (with it's implementation * separated into exts file). * * @param tservice The service definition */ void t_swift_generator::generate_service(t_service* tservice) { generate_swift_service_protocol(f_decl_, tservice); generate_swift_service_client(f_decl_, tservice); if (async_clients_) { generate_swift_service_protocol_async(f_decl_, tservice); generate_swift_service_client_async(f_decl_, tservice); } generate_swift_service_server(f_decl_, tservice); generate_swift_service_helpers(tservice); generate_swift_service_client_implementation(f_impl_, tservice); if (async_clients_) { generate_swift_service_client_async_implementation(f_impl_, tservice); } generate_swift_service_server_implementation(f_impl_, tservice); } /** * Generates structs for all the service return types * * @param tservice The service */ void t_swift_generator::generate_swift_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); string qname = function_args_helper_struct_type(tservice, *f_iter); t_struct qname_ts = t_struct(ts->get_program(), qname); const vector& members = ts->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { qname_ts.append(*m_iter); } generate_swift_struct(f_impl_, &qname_ts, true); generate_swift_struct_implementation(f_impl_, &qname_ts, false, true); generate_function_helpers(tservice, *f_iter); } } string t_swift_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) { if (tfunction->is_oneway()) { return tservice->get_name() + "_" + tfunction->get_name(); } else { return tservice->get_name() + "_" + tfunction->get_name() + "_result"; } } string t_swift_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) { return tservice->get_name() + "_" + tfunction->get_name() + "_args"; } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_swift_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) { if (tfunction->is_oneway()) { return; } // create a result struct with a success field of the return type, // and a field for each type of exception thrown t_struct result(program_, function_result_helper_struct_type(tservice, tfunction)); if (!tfunction->get_returntype()->is_void()) { t_field* success = new t_field(tfunction->get_returntype(), "success", 0); success->set_req(t_field::T_OPTIONAL); result.append(success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field *x = *f_iter; t_field *ox = new t_field(x->get_type(), x->get_name(), x->get_key()); ox->set_req(t_field::T_OPTIONAL); result.append(ox); } // generate the result struct generate_swift_struct(f_impl_, &result, true); generate_swift_struct_implementation(f_impl_, &result, true, true); for (f_iter = result.get_members().begin(); f_iter != result.get_members().end(); ++f_iter) { delete *f_iter; } } /** * Generates a service protocol definition. * * @param tservice The service to generate a protocol definition for */ void t_swift_generator::generate_swift_service_protocol(ostream& out, t_service* tservice) { if (!gen_cocoa_) { string doc = tservice->get_doc(); generate_docstring(out, doc); indent(out) << "public protocol " << tservice->get_name(); t_service* parent = tservice->get_extends(); if (parent != nullptr) { out << " : " << parent->get_name(); } block_open(out); out << endl; vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { function_docstring(out, *f_iter); indent(out) << function_signature(*f_iter) << endl << endl; } } else { indent(out) << "public protocol " << tservice->get_name(); block_open(out); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { out << endl; indent(out) << function_signature(*f_iter) << " // exceptions: "; t_struct* xs = (*f_iter)->get_xceptions(); const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << type_name((*x_iter)->get_type()) + ", "; } out << endl; } } block_close(out); out << endl; } /** * Generates an asynchronous service protocol definition. * * @param tservice The service to generate a protocol definition for */ void t_swift_generator::generate_swift_service_protocol_async(ostream& out, t_service* tservice) { if (!gen_cocoa_) { string doc = tservice->get_doc(); generate_docstring(out, doc); } indent(out) << "public protocol " << tservice->get_name() << "Async"; block_open(out); if (!gen_cocoa_) { out << endl; } vector functions = tservice->get_functions(); vector::iterator f_iter; if (!gen_cocoa_) { for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { async_function_docstring(out, *f_iter); indent(out) << async_function_signature(*f_iter) << endl << endl; } } else { for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { out << endl; indent(out) << async_function_signature(*f_iter) << endl; if (promise_kit_) { indent(out) << promise_function_signature(*f_iter) << endl; } // out << endl; } } block_close(out); out << endl; } /** * Generates a service client interface definition. * * @param tservice The service to generate a client interface definition for */ void t_swift_generator::generate_swift_service_client(ostream& out, t_service* tservice) { if (!gen_cocoa_) { indent(out) << "open class " << tservice->get_name() << "Client";// : " // Inherit from ParentClient t_service* parent = tservice->get_extends(); out << " : " << ((parent == nullptr) ? "TClient" : parent->get_name() + "Client"); out << " /* , " << tservice->get_name() << " */"; block_open(out); out << endl; } else { // a indent(out) << "public class " << tservice->get_name() << "Client /* : " << tservice->get_name() << " */"; block_open(out); out << endl; indent(out) << "let __inProtocol : TProtocol" << endl << endl; indent(out) << "let __outProtocol : TProtocol" << endl << endl; indent(out) << "public init(inoutProtocol: TProtocol)"; block_open(out); indent(out) << "__inProtocol = inoutProtocol" << endl; indent(out) << "__outProtocol = inoutProtocol" << endl; block_close(out); out << endl; indent(out) << "public init(inProtocol: TProtocol, outProtocol: TProtocol)"; block_open(out); indent(out) << "__inProtocol = inProtocol" << endl; indent(out) << "__outProtocol = outProtocol" << endl; block_close(out); out << endl; } block_close(out); out << endl; } /** * Generates a service client interface definition. * * @param tservice The service to generate a client interface definition for */ void t_swift_generator::generate_swift_service_client_async(ostream& out, t_service* tservice) { if (!gen_cocoa_) { indent(out) << "open class " << tservice->get_name() << "AsyncClient";// : " // Inherit from ParentClient t_service* parent = tservice->get_extends(); out << " : " << ((parent == nullptr) ? "T" : parent->get_name()) + "AsyncClient"; out << " /* , " << tservice->get_name() << " */"; block_open(out); out << endl; } else { indent(out) << "public class " << tservice->get_name() << "AsyncClient /* : " << tservice->get_name() << " */"; block_open(out); out << endl; indent(out) << "let __protocolFactory : TProtocolFactory" << endl << endl; indent(out) << "let __transportFactory : TAsyncTransportFactory" << endl << endl; indent(out) << "public init(protocolFactory: TProtocolFactory, transportFactory: TAsyncTransportFactory)"; block_open(out); indent(out) << "__protocolFactory = protocolFactory" << endl; indent(out) << "__transportFactory = transportFactory" << endl; block_close(out); out << endl; } block_close(out); out << endl; } /** * Generates a service server interface definition. In other words, * the TProcess implementation for the service definition. * * @param tservice The service to generate a client interface definition for */ void t_swift_generator::generate_swift_service_server(ostream& out, t_service* tservice) { if (!gen_cocoa_) { indent(out) << "open class " << tservice->get_name() << "Processor /* " << tservice->get_name() << " */"; block_open(out); out << endl; out << indent() << "typealias ProcessorHandlerDictionary = " << "[String: (Int32, TProtocol, TProtocol, " << tservice->get_name() << ") throws -> Void]" << endl << endl << indent() << "public var service: " << tservice->get_name() << endl << endl << indent() << "public required init(service: " << tservice->get_name() << ")"; } else { indent(out) << "public class " << tservice->get_name() << "Processor : NSObject /* " << tservice->get_name() << " */"; block_open(out); out << endl; out << indent() << "typealias ProcessorHandlerDictionary = " << "[String: (Int, TProtocol, TProtocol, " << tservice->get_name() << ") throws -> Void]" << endl << endl << indent() << "let service : " << tservice->get_name() << endl << endl << indent() << "public init(service: " << tservice->get_name() << ")"; } block_open(out); indent(out) << "self.service = service" << endl; block_close(out); out << endl; block_close(out); out << endl; } /** * Generates a function that will send the arguments * for a service function via a protocol. * * @param tservice The service to generate * @param tfunction The function to generate * @param needs_protocol * Wether the first parameter must be a protocol or if * the protocol is to be assumed */ void t_swift_generator::generate_swift_service_client_send_function_implementation(ostream& out, t_service *tservice, t_function* tfunction, bool needs_protocol) { string funname = tfunction->get_name(); t_function send_function(g_type_bool, "send_" + tfunction->get_name(), tfunction->get_arglist()); string argsname = function_args_helper_struct_type(tservice, tfunction); t_struct* arg_struct = tfunction->get_arglist(); string proto = needs_protocol ? (gen_cocoa_ ? "__outProtocol" : "on outProtocol") : ""; // Open function indent(out) << "private func " << send_function.get_name() << "(" << argument_list(tfunction->get_arglist(), proto, true) << ") throws"; block_open(out); if (!gen_cocoa_) { // Serialize the request indent(out) << "try outProtocol.writeMessageBegin(name: \"" << funname << "\", " << "type: " << (tfunction->is_oneway() ? ".oneway" : ".call") << ", " << "sequenceID: 0)" << endl; indent(out) << "let args = " << argsname << "("; // write out function parameters const vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end();) { t_field *tfield = (*f_iter); out << tfield->get_name() << ": " << tfield->get_name(); if (++f_iter != fields.end()) { out << ", "; } } out << ")" << endl; indent(out) << "try args.write(to: outProtocol)" << endl; indent(out) << "try outProtocol.writeMessageEnd()" << endl; } else { out << endl; // Serialize the request indent(out) << "try __outProtocol.writeMessageBeginWithName(\"" << funname << "\", " << "type: " << (tfunction->is_oneway() ? ".ONEWAY" : ".CALL") << ", " << "sequenceID: 0)" << endl; out << endl; indent(out) << "let __args = " << argsname << "("; // write out function parameters const vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end();) { t_field *tfield = (*f_iter); out << tfield->get_name() << ": " << tfield->get_name(); if (++f_iter != fields.end()) { out << ", "; } } out << ")" << endl; indent(out) << "try " << argsname << ".writeValue(__args, toProtocol: __outProtocol)" << endl << endl; indent(out) << "try __outProtocol.writeMessageEnd()" << endl; } block_close(out); out << endl; } /** * Generates a function that will recv the result for a * service function via a protocol. * * @param tservice The service to generate * @param tfunction The function to generate * @param needs_protocol * Wether the first parameter must be a protocol or if * the protocol is to be assumed */ void t_swift_generator::generate_swift_service_client_recv_function_implementation(ostream& out, t_service* tservice, t_function* tfunction, bool needs_protocol) { // Open function indent(out) << "private func recv_" << tfunction->get_name() << "("; if (!gen_cocoa_) { if (needs_protocol) { out << "on inProtocol: TProtocol"; } out << ") throws"; if (!tfunction->get_returntype()->is_void()) { out << " -> " << type_name(tfunction->get_returntype()); } block_open(out); // check for an exception indent(out) << "try inProtocol.readResultMessageBegin() " << endl; string resultname = function_result_helper_struct_type(tservice, tfunction); indent(out); if (!tfunction->get_returntype()->is_void() || !tfunction->get_xceptions()->get_members().empty()) { out << "let result = "; } else { out << "_ = "; } string return_type_name = type_name(tfunction->get_returntype()); out << "try " << resultname << ".read(from: inProtocol)" << endl; indent(out) << "try inProtocol.readMessageEnd()" << endl << endl; // Careful, only return _result if not a void function if (!tfunction->get_returntype()->is_void()) { indent(out) << "if let success = result.success"; block_open(out); indent(out) << "return success" << endl; block_close(out); } t_struct* xs = tfunction->get_xceptions(); const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { indent(out) << "if let " << (*x_iter)->get_name() << " = result." << (*x_iter)->get_name(); block_open(out); indent(out) << "throw " << (*x_iter)->get_name() << endl; block_close(out); } // If you get here it's an exception, unless a void function if (!tfunction->get_returntype()->is_void()) { indent(out) << "throw TApplicationError(error: .missingResult(methodName: \"" << tfunction->get_name() << "\"))" << endl; } } else { if (needs_protocol) { out << "__inProtocol: TProtocol"; } out << ") throws"; if (!tfunction->get_returntype()->is_void()) { out << " -> " << type_name(tfunction->get_returntype()); } block_open(out); // check for an exception out << endl; indent(out) << "try __inProtocol.readResultMessageBegin() " << endl << endl; string resultname = function_result_helper_struct_type(tservice, tfunction); indent(out); if (!tfunction->get_returntype()->is_void() || !tfunction->get_xceptions()->get_members().empty()) { out << "let __result = "; } out << "try " << resultname << ".readValueFromProtocol(__inProtocol)" << endl << endl; indent(out) << "try __inProtocol.readMessageEnd()" << endl << endl; // Careful, only return _result if not a void function if (!tfunction->get_returntype()->is_void()) { indent(out) << "if let __success = __result.success"; block_open(out); indent(out) << "return __success" << endl; block_close(out); } t_struct* xs = tfunction->get_xceptions(); const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { indent(out) << "if let " << (*x_iter)->get_name() << " = __result." << (*x_iter)->get_name(); block_open(out); indent(out) << "throw " << (*x_iter)->get_name() << endl; block_close(out); } // If you get here it's an exception, unless a void function if (!tfunction->get_returntype()->is_void()) { indent(out) << "throw NSError(" << endl; indent_up(); indent(out) << "domain: TApplicationErrorDomain, " << endl; indent(out) << "code: Int(TApplicationError.MissingResult.rawValue)," << endl; indent(out) << "userInfo: [TApplicationErrorMethodKey: \"" << tfunction->get_name() << "\"])" << endl; indent_down(); } } // Close function block_close(out); out << endl; } /** * Generates an invocation of a given the send function for the * service function. * * @param tfunction The service to generate an implementation for */ void t_swift_generator::generate_swift_service_client_send_function_invocation(ostream& out, t_function* tfunction) { indent(out) << "try send_" << tfunction->get_name() << "("; t_struct* arg_struct = tfunction->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end();) { out << (*f_iter)->get_name() << ": " << (*f_iter)->get_name(); if (++f_iter != fields.end()) { out << ", "; } } out << ")" << endl; } /** * Generates an invocation of a given the send function for the * service function. This is for asynchronous protocols. * * @param tfunction The service to generate an implementation for */ void t_swift_generator::generate_swift_service_client_send_async_function_invocation(ostream& out, t_function* tfunction) { t_struct* arg_struct = tfunction->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; if (!gen_cocoa_) { indent(out) << "try send_" << tfunction->get_name() << "(on: proto"; } else { indent(out) << "try send_" << tfunction->get_name() << "(__protocol"; // } for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { out << ", " << (*f_iter)->get_name() << ": " << (*f_iter)->get_name(); } out << ")" << endl; } /** * Generates a service client protocol implementation via extension. * * @param tservice The service to generate an implementation for */ void t_swift_generator::generate_swift_service_client_implementation(ostream& out, t_service* tservice) { string name = tservice->get_name() + "Client"; indent(out) << "extension " << name << " : " << tservice->get_name(); block_open(out); out << endl; // generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_swift_service_client_send_function_implementation(out, tservice, *f_iter, false); if (!(*f_iter)->is_oneway()) { generate_swift_service_client_recv_function_implementation(out, tservice, *f_iter, false); } // Open function indent(out) << "public " << function_signature(*f_iter); block_open(out); if (gen_cocoa_) { out << endl; } generate_swift_service_client_send_function_invocation(out, *f_iter); if (!gen_cocoa_) { indent(out) << "try outProtocol.transport.flush()" << endl; } else { out << endl; indent(out) << "try __outProtocol.transport().flush()" << endl << endl; } if (!(*f_iter)->is_oneway()) { if ((*f_iter)->get_returntype()->is_void()) { indent(out) << "try recv_" << (*f_iter)->get_name() << "()" << endl; } else { indent(out) << "return try recv_" << (*f_iter)->get_name() << "()" << endl; } } block_close(out); out << endl; } block_close(out); out << endl; } /** * Generates a service asynchronous client protocol implementation via extension. * * @param tservice The service to generate an implementation for */ void t_swift_generator::generate_swift_service_client_async_implementation(ostream& out, t_service* tservice) { if (gen_cocoa_) { generate_old_swift_service_client_async_implementation(out, tservice); return; } string name = tservice->get_name() + "AsyncClient"; string protocol_name = tservice->get_name() + "Async"; indent(out) << "extension " << name << " : " << protocol_name; block_open(out); out << endl; // generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_swift_service_client_send_function_implementation(out, tservice, *f_iter, true); if (!(*f_iter)->is_oneway()) { generate_swift_service_client_recv_function_implementation(out, tservice, *f_iter, true); } indent(out) << "public " << async_function_signature(*f_iter); block_open(out); out << endl; out << indent() << "let transport = factory.newTransport()" << endl << indent() << "let proto = Protocol(on: transport)" << endl << endl; out << indent() << "do"; block_open(out); generate_swift_service_client_send_async_function_invocation(out, *f_iter); indent_down(); out << indent() << "} catch let error {" << endl; indent_up(); out << indent() << "completion(.error(error))" << endl; block_close(out); out << endl; bool ret_is_void = (*f_iter)->get_returntype()->is_void(); bool is_oneway = (*f_iter)->is_oneway(); string error_completion_call = "completion(.error(error))"; indent(out) << "transport.flush"; block_open(out); out << indent() << "(trans, error) in" << endl << endl; out << indent() << "if let error = error"; block_open(out); out << indent() << error_completion_call << endl; block_close(out); if (!is_oneway) { out << indent() << "do"; block_open(out); indent(out); if (!ret_is_void) { out << "let result = "; } out << "try self.recv_" << (*f_iter)->get_name() << "(on: proto)" << endl; out << indent() << (ret_is_void ? "completion(.success(Void()))" : "completion(.success(result))") << endl; indent_down(); out << indent() << "} catch let error {" << endl; indent_up(); out << indent() << error_completion_call << endl; block_close(out); } else { out << indent() << "completion(.success(Void()))" << endl; } block_close(out); block_close(out); } block_close(out); out << endl; } void t_swift_generator::generate_old_swift_service_client_async_implementation(ostream& out, t_service* tservice) { string name = tservice->get_name() + "AsyncClient"; string protocol_name = tservice->get_name() + "Async"; indent(out) << "extension " << name << " : " << protocol_name; block_open(out); out << endl; // generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { generate_swift_service_client_send_function_implementation(out, tservice, *f_iter, true); if (!(*f_iter)->is_oneway()) { generate_swift_service_client_recv_function_implementation(out, tservice, *f_iter, true); } indent(out) << "public " << async_function_signature(*f_iter); block_open(out); out << endl; out << indent() << "let __transport = __transportFactory.newTransport()" << endl << indent() << "let __protocol = __protocolFactory.newProtocolOnTransport(__transport)" << endl << endl; generate_swift_service_client_send_async_function_invocation(out, *f_iter); out << endl; indent(out) << "__transport.flushWithCompletion("; if ((*f_iter)->is_oneway()) { out << "success, failure: failure)" << endl; } else { block_open(out); indent(out) << "do"; block_open(out); indent(out); if (!(*f_iter)->get_returntype()->is_void()) { out << "let result = "; } out << "try self.recv_" << (*f_iter)->get_name() << "(__protocol)" << endl; out << indent() << "success("; if (!(*f_iter)->get_returntype()->is_void()) { out << "result"; } out << ")" << endl; block_close(out); indent(out) << "catch let error"; block_open(out); indent(out) << "failure(error as NSError)" << endl; block_close(out); block_close(out); indent(out) << ", failure: failure)" << endl; } block_close(out); out << endl; // Promise function if (promise_kit_) { indent(out) << "public " << promise_function_signature(*f_iter); block_open(out); out << indent() << "let (__promise, __fulfill, __reject) = Promise<" << type_name((*f_iter)->get_returntype()) << ">.pendingPromise()" << endl << endl << indent() << "let __transport = __transportFactory.newTransport()" << endl << indent() << "let __protocol = __protocolFactory.newProtocolOnTransport(__transport)" << endl << endl; generate_swift_service_client_send_async_function_invocation(out, *f_iter); out << endl; indent(out) << "__transport.flushWithCompletion("; if ((*f_iter)->is_oneway()) { out << "{ __fulfill() }, failure: { __reject($0) })" << endl; } else { block_open(out); indent(out) << "do"; block_open(out); indent(out); if (!(*f_iter)->get_returntype()->is_void()) { out << "let result = "; } out << "try self.recv_" << (*f_iter)->get_name() << "(__protocol)" << endl; out << indent() << "__fulfill("; if (!(*f_iter)->get_returntype()->is_void()) { out << "result"; } out << ")" << endl; block_close(out); indent(out) << "catch let error"; block_open(out); indent(out) << "__reject(error)" << endl; block_close(out); block_close(out); indent(out) << ", failure: { error in " << endl; indent_up(); indent(out) << "__reject(error)" << endl; indent_down(); indent(out) << "})" << endl; } indent(out) << "return __promise" << endl; block_close(out); out << endl; } } block_close(out); out << endl; } /** * Generates a service server implementation. * * Implemented by generating a block for each service function that * handles the processing of that function. The blocks are stored in * a map and looked up via function/message name. * * @param tservice The service to generate an implementation for */ void t_swift_generator::generate_swift_service_server_implementation(ostream& out, t_service* tservice) { string name = tservice->get_name() + "Processor"; indent(out) << "extension " << name << " : TProcessor"; block_open(out); out << endl; indent(out) << "static let processorHandlers" << (gen_cocoa_ ? " " : "") << ": ProcessorHandlerDictionary ="; block_open(out); out << endl; out << indent() << "var processorHandlers = ProcessorHandlerDictionary()" << endl << endl; // generate method map for routing incoming calls vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_function* tfunction = *f_iter; string args_type = function_args_helper_struct_type(tservice, *f_iter); out << indent() << "processorHandlers[\"" << tfunction->get_name() << "\"] = { sequenceID, inProtocol, outProtocol, handler in" << endl << endl; indent_up(); if (!gen_cocoa_) { out << indent() << "let args = try " << args_type << ".read(from: inProtocol)" << endl << endl << indent() << "try inProtocol.readMessageEnd()" << endl << endl; } else { out << indent() << "let args = try " << args_type << ".readValueFromProtocol(inProtocol)" << endl << endl << indent() << "try inProtocol.readMessageEnd()" << endl << endl; } if (!tfunction->is_oneway() ) { string result_type = function_result_helper_struct_type(tservice, tfunction); indent(out) << "var result = " << result_type << "()" << endl; indent(out) << "do"; block_open(out); indent(out); if (!tfunction->get_returntype()->is_void()) { out << "result.success = "; } out << "try handler." << (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name()) << "("; t_struct* arg_struct = tfunction->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end();) { string fieldName = (*f_iter)->get_name(); if (!gen_cocoa_ || f_iter != fields.begin()) { out << fieldName << ": "; } out << "args." << fieldName; if (++f_iter != fields.end()) { out << ", "; } } out << ")" << endl; block_close(out); t_struct* xs = tfunction->get_xceptions(); const vector& xfields = xs->get_members(); vector::const_iterator x_iter; if (!gen_cocoa_) { for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) { indent(out) << "catch let error as "; t_program* program = (*x_iter)->get_type()->get_program(); if ((*x_iter)->get_type()->get_name() == "Error" && namespaced_ && program != program_) { out << get_real_swift_module(program) << "."; } out << (*x_iter)->get_type()->get_name(); out << " { result." << (*x_iter)->get_name() << " = error }" << endl; } indent(out) << "catch let error { throw error }" << endl; out << endl; if (!tfunction->is_oneway()) { out << indent() << "try outProtocol.writeMessageBegin(name: \"" << tfunction->get_name() << "\", type: .reply, sequenceID: sequenceID)" << endl << indent() << "try result.write(to: outProtocol)" << endl << indent() << "try outProtocol.writeMessageEnd()" << endl << indent() << "try outProtocol.transport.flush()" << endl; } } else { for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) { indent(out) << "catch let error as " << (*x_iter)->get_type()->get_name(); block_open(out); indent(out) << "result." << (*x_iter)->get_name() << " = error" << endl; block_close(out); } indent(out) << "catch let error"; block_open(out); out << indent() << "throw error" << endl; block_close(out); out << endl; if (!tfunction->is_oneway()) { out << indent() << "try outProtocol.writeMessageBeginWithName(\"" << tfunction->get_name() << "\", type: .REPLY, sequenceID: sequenceID)" << endl << indent() << "try " << result_type << ".writeValue(result, toProtocol: outProtocol)" << endl << indent() << "try outProtocol.writeMessageEnd()" << endl; } } } block_close(out); } indent(out) << "return processorHandlers" << endl; block_close(out,false); out << "()" << endl; out << endl; if (!gen_cocoa_) { indent(out) << "public func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws"; } else { indent(out) << "public func processOnInputProtocol(inProtocol: TProtocol, outputProtocol outProtocol: TProtocol) throws"; } block_open(out); out << endl; out << indent() << "let (messageName, _, sequenceID) = try inProtocol.readMessageBegin()" << endl << endl << indent() << "if let processorHandler = " << name << ".processorHandlers[messageName]"; block_open(out); out << indent() << "do"; block_open(out); out << indent() << "try processorHandler(sequenceID, inProtocol, outProtocol, service)" << endl; block_close(out); if (!gen_cocoa_) { out << indent() << "catch let error as TApplicationError"; block_open(out); out << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: error)" << endl << indent() << "try outProtocol.transport.flush()" << endl; block_close(out); block_close(out); out << indent() << "else"; block_open(out); out << indent() << "try inProtocol.skip(type: .struct)" << endl << indent() << "try inProtocol.readMessageEnd()" << endl << indent() << "let ex = TApplicationError(error: .unknownMethod(methodName: messageName))" << endl << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: ex)" << endl << indent() << "try outProtocol.transport.flush()" << endl; } else { out << indent() << "catch let error as NSError"; block_open(out); out << indent() << "try outProtocol.writeExceptionForMessageName(messageName, sequenceID: sequenceID, ex: error)" << endl; block_close(out); block_close(out); out << indent() << "else"; block_open(out); out << indent() << "try inProtocol.skipType(.STRUCT)" << endl << indent() << "try inProtocol.readMessageEnd()" << endl << indent() << "try outProtocol.writeExceptionForMessageName(messageName," << endl; indent_up(); out << indent() << "sequenceID: sequenceID," << endl << indent() << "ex: NSError(" << endl; indent_up(); out << indent() << "domain: TApplicationErrorDomain, " << endl << indent() << "code: Int(TApplicationError.UnknownMethod.rawValue), " << endl << indent() << "userInfo: [TApplicationErrorMethodKey: messageName]))" << endl; indent_down(); indent_down(); } block_close(out); block_close(out); block_close(out); out << endl; } /** * Returns an Swift name * * @param ttype The type * @param class_ref Do we want a Class reference istead of a type reference? * @return Swift type name, i.e. Dictionary */ string t_swift_generator::type_name(t_type* ttype, bool is_optional, bool is_forced) { string result = ""; if (ttype->is_base_type()) { result += base_type_name((t_base_type*)ttype); } else if (ttype->is_map()) { t_map *map = (t_map *)ttype; result += "TMap<" + type_name(map->get_key_type()) + ", " + type_name(map->get_val_type()) + ">"; } else if (ttype->is_set()) { t_set *set = (t_set *)ttype; result += "TSet<" + type_name(set->get_elem_type()) + ">"; } else if (ttype->is_list()) { t_list *list = (t_list *)ttype; result += "TList<" + type_name(list->get_elem_type()) + ">"; } else { t_program* program = ttype->get_program(); if (namespaced_ && program != program_) { result += get_real_swift_module(program) + "."; } result += ttype->get_name(); } if (is_optional) { result += "?"; } if (is_forced) { result += "!"; } return result; } /** * Returns the Swift type that corresponds to the thrift type. * * @param tbase The base type */ string t_swift_generator::base_type_name(t_base_type* type) { t_base_type::t_base tbase = type->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: return "Void"; case t_base_type::TYPE_STRING: if (type->is_binary()) { return gen_cocoa_ ? "TBinary" : "Data"; } else { return "String"; } case t_base_type::TYPE_BOOL: return "Bool"; case t_base_type::TYPE_I8: return "Int8"; case t_base_type::TYPE_I16: return "Int16"; case t_base_type::TYPE_I32: return "Int32"; case t_base_type::TYPE_I64: return "Int64"; case t_base_type::TYPE_DOUBLE: return "Double"; case t_base_type::TYPE_UUID: return "UUID"; default: throw "compiler error: no Swift name for base type " + t_base_type::t_base_name(tbase); } } /** * Renders full constant value (as would be seen after an '=') * */ void t_swift_generator::render_const_value(ostream& out, t_type* type, t_const_value* value) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: out << "\"" << get_escaped_string(value) << "\""; break; case t_base_type::TYPE_BOOL: out << ((value->get_integer() > 0) ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << type_name(type) << "(" << value->get_integer() << ")"; break; case t_base_type::TYPE_DOUBLE: out << type_name(type) << "("; if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); } else { out << value->get_double(); } out << ")"; break; case t_base_type::TYPE_UUID: out << "UUID(uuidString: \"" << get_escaped_string(value) << "\")"; break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << (gen_cocoa_ ? value->get_identifier() : enum_const_name(value->get_identifier())); // Swift2/Cocoa compatibility } else if (type->is_struct() || type->is_xception()) { out << type_name(type) << "("; const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (f_iter = fields.begin(); f_iter != fields.end();) { t_field* tfield = *f_iter; t_const_value* value = nullptr; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (tfield->get_name() == v_iter->first->get_string()) { value = v_iter->second; } } if (value) { out << tfield->get_name() << ": "; render_const_value(out, tfield->get_type(), value); } else if (!field_is_optional(tfield)) { throw "constant error: required field " + type->get_name() + "." + tfield->get_name() + " has no value"; } if (++f_iter != fields.end()) { out << ", "; } } out << ")"; } else if (type->is_map()) { out << "["; t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { render_const_value(out, ktype, v_iter->first); out << ": "; render_const_value(out, vtype, v_iter->second); if (++v_iter != val.end()) { out << ", "; } } out << "]"; } else if (type->is_list()) { out << "["; t_type* etype = ((t_list*)type)->get_elem_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { render_const_value(out, etype, v_iter->first); if (++v_iter != val.end()) { out << ", "; } } out << "]"; } else if (type->is_set()) { out << "["; t_type* etype = ((t_set*)type)->get_elem_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end();) { render_const_value(out, etype, v_iter->first); if (++v_iter != val.end()) { out << ", "; } } out << "]"; } else { throw "compiler error: no const of type " + type->get_name(); } } /** * Declares an Swift property. * * @param tfield The field to declare a property for */ string t_swift_generator::declare_property(t_field* tfield, bool is_private) { string visibility = is_private ? (gen_cocoa_ ? "private" : "fileprivate") : "public"; ostringstream render; render << visibility << " var " << maybe_escape_identifier(tfield->get_name()); if (field_is_optional(tfield)) { render << (gen_cocoa_ ? " " : "") << ": " << type_name(tfield->get_type(), true); } else { if (!gen_cocoa_) { render << ": " << type_name(tfield->get_type(), false); } else { // Swift2/Cocoa backward compat, Bad, default init render << " = " << type_name(tfield->get_type(), false) << "()"; } } return render.str(); } /** * Renders a function signature * * @param tfunction Function definition * @return String of rendered function definition */ string t_swift_generator::function_signature(t_function* tfunction) { string result = "func " + (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name()); result += "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws"; /// argsreview t_type* ttype = tfunction->get_returntype(); if (!ttype->is_void()) { result += " -> " + type_name(ttype); } return result; } /** * Renders a function docstring * * @param tfunction Function definition * @return String of rendered function definition */ void t_swift_generator::function_docstring(ostream& out, t_function* tfunction) { // Generate docstring with following format: // /// // /// // /// - Parameters: // /// - : // /// - Returns: (Thrift has no docstring on return val) // /// - Throws: // Description string doc = tfunction->get_doc(); generate_docstring(out, doc); indent(out) << "///" << endl; // Parameters const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator f_iter; if (!fields.empty()) { indent(out) << "/// - Parameters:" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "/// - " << (*f_iter)->get_name() << ": "; string doc = (*f_iter)->get_doc(); if (!doc.empty() && doc[doc.length()-1] == '\n') { doc.erase(doc.length()-1); } out << doc << endl; } } // Returns t_type* ttype = tfunction->get_returntype(); if (!ttype->is_void()) { indent(out) << "/// - Returns: " << type_name(ttype) << endl; } // Throws indent(out) << "/// - Throws: "; t_struct* xs = tfunction->get_xceptions(); const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << type_name((*x_iter)->get_type()); if (*x_iter != xceptions.back()) { out << ", "; } } out << endl; } /** * Renders a function docstring * * @param tfunction Function definition * @return String of rendered function definition */ void t_swift_generator::async_function_docstring(ostream& out, t_function* tfunction) { // Generate docstring with following format: // /// // /// // /// - Parameters: // /// - : // /// - callback: // Description string doc = tfunction->get_doc(); generate_docstring(out, doc); indent(out) << "///" << endl; // Parameters const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator f_iter; if (!fields.empty()) { indent(out) << "/// - Parameters:" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << "/// - " << (*f_iter)->get_name() << ": "; string doc = (*f_iter)->get_doc(); if (!doc.empty() && doc[doc.length()-1] == '\n') { doc.erase(doc.length()-1); } out << doc << endl; } } // completion indent(out) << "/// - completion: Result<" << type_name(tfunction->get_returntype()) << ", Error> wrapping return and following Exceptions: "; t_struct* xs = tfunction->get_xceptions(); const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { out << type_name((*x_iter)->get_type()); if (*x_iter != xceptions.back()) { out << ", "; } } out << endl; } /** * Renders a function signature that returns asynchronously via blocks. * * @param tfunction Function definition * @return String of rendered function definition */ string t_swift_generator::async_function_signature(t_function* tfunction) { t_type* ttype = tfunction->get_returntype(); t_struct* targlist = tfunction->get_arglist(); string result = "func " + (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name()); if (!gen_cocoa_) { string response_string = "(Result<"; response_string += (ttype->is_void()) ? "Void" : type_name(ttype); response_string += ", Error>) -> Void"; result += "(" + argument_list(tfunction->get_arglist(), "", false) + (targlist->get_members().size() ? ", " : "") + "completion: @escaping " + response_string + ")"; } else { string response_param = "(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ") -> Void"; result += "(" + argument_list(tfunction->get_arglist(), "", false) + (targlist->get_members().size() ? ", " : "") + "success: " + response_param + ", " + "failure: (NSError) -> Void) throws"; } return result; } /** * Renders a function signature that returns asynchronously via promises. * ONLY FOR Swift2/Cocoa BACKWARDS COMPATIBILITY * * @param tfunction Function definition * @return String of rendered function definition */ string t_swift_generator::promise_function_signature(t_function* tfunction) { return "func " + function_name(tfunction) + "(" + argument_list(tfunction->get_arglist(), "", false) + ") throws " + "-> Promise<" + type_name(tfunction->get_returntype()) + ">"; } /** * Renders a verbose function name suitable for a Swift method. ONLY FOR Swift2/Cocoa BACKWARDS COMPATIBILITY */ string t_swift_generator::function_name(t_function* tfunction) { string name = tfunction->get_name(); if (!tfunction->get_arglist()->get_members().empty()) { string first_arg = tfunction->get_arglist()->get_members().front()->get_name(); if (name.size() < first_arg.size() || lowercase(name.substr(name.size()-first_arg.size())) != lowercase(first_arg)) { name += "With" + capitalize(tfunction->get_arglist()->get_members()[0]->get_name()); } } return name; } /** * Renders a Swift method argument list */ string t_swift_generator::argument_list(t_struct* tstruct, string protocol_name, bool is_internal) { string result = ""; bool include_protocol = !protocol_name.empty(); const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; if (include_protocol) { result += protocol_name + ": TProtocol"; if (!fields.empty()) { result += ", "; } } else if (!fields.empty() && is_internal && gen_cocoa_) { // Force first argument to be named, Swift2/Cocoa backwards compat result += fields.front()->get_name() + " "; } for (f_iter = fields.begin(); f_iter != fields.end();) { t_field* arg = *f_iter; if (!gen_cocoa_) { // optional args not usually permitted for some reason, even though dynamic langs handle it // use annotation "swift.nullable" to achieve result += arg->get_name() + ": " + type_name(arg->get_type(), field_is_optional(arg)); } else { result += arg->get_name() + ": " + type_name(arg->get_type()); } if (++f_iter != fields.end()) { result += ", "; } } return result; } /** * https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html * */ void t_swift_generator::populate_reserved_words() { if (!gen_cocoa_) { swift_reserved_words_.insert("__COLUMN__"); swift_reserved_words_.insert("__FILE__"); swift_reserved_words_.insert("__FUNCTION__"); swift_reserved_words_.insert("__LINE__"); swift_reserved_words_.insert("Any"); swift_reserved_words_.insert("as"); swift_reserved_words_.insert("associatedtype"); swift_reserved_words_.insert("associativity"); swift_reserved_words_.insert("break"); swift_reserved_words_.insert("case"); swift_reserved_words_.insert("catch"); swift_reserved_words_.insert("class"); swift_reserved_words_.insert("continue"); swift_reserved_words_.insert("convenience"); swift_reserved_words_.insert("default"); swift_reserved_words_.insert("defer"); swift_reserved_words_.insert("deinit"); swift_reserved_words_.insert("didSet"); swift_reserved_words_.insert("do"); swift_reserved_words_.insert("dynamic"); swift_reserved_words_.insert("dynamicType"); swift_reserved_words_.insert("else"); swift_reserved_words_.insert("enum"); swift_reserved_words_.insert("extension"); swift_reserved_words_.insert("fallthrough"); swift_reserved_words_.insert("false"); swift_reserved_words_.insert("fileprivate"); swift_reserved_words_.insert("final"); swift_reserved_words_.insert("for"); swift_reserved_words_.insert("func"); swift_reserved_words_.insert("get"); swift_reserved_words_.insert("guard"); swift_reserved_words_.insert("if"); swift_reserved_words_.insert("import"); swift_reserved_words_.insert("in"); swift_reserved_words_.insert("indirect"); swift_reserved_words_.insert("infix"); swift_reserved_words_.insert("init"); swift_reserved_words_.insert("inout"); swift_reserved_words_.insert("internal"); swift_reserved_words_.insert("is"); swift_reserved_words_.insert("lazy"); swift_reserved_words_.insert("left"); swift_reserved_words_.insert("let"); swift_reserved_words_.insert("mutating"); swift_reserved_words_.insert("nil"); swift_reserved_words_.insert("none"); swift_reserved_words_.insert("nonmutating"); swift_reserved_words_.insert("open"); swift_reserved_words_.insert("operator"); swift_reserved_words_.insert("optional"); swift_reserved_words_.insert("override"); swift_reserved_words_.insert("postfix"); swift_reserved_words_.insert("precedence"); swift_reserved_words_.insert("prefix"); swift_reserved_words_.insert("private"); swift_reserved_words_.insert("protocol"); swift_reserved_words_.insert("Protocol"); swift_reserved_words_.insert("public"); swift_reserved_words_.insert("repeat"); swift_reserved_words_.insert("required"); swift_reserved_words_.insert("rethrows"); swift_reserved_words_.insert("return"); swift_reserved_words_.insert("right"); swift_reserved_words_.insert("self"); swift_reserved_words_.insert("Self"); swift_reserved_words_.insert("set"); swift_reserved_words_.insert("static"); swift_reserved_words_.insert("struct"); swift_reserved_words_.insert("subscript"); swift_reserved_words_.insert("super"); swift_reserved_words_.insert("switch"); swift_reserved_words_.insert("throw"); swift_reserved_words_.insert("throws"); swift_reserved_words_.insert("true"); swift_reserved_words_.insert("try"); swift_reserved_words_.insert("Type"); swift_reserved_words_.insert("typealias"); swift_reserved_words_.insert("unowned"); swift_reserved_words_.insert("var"); swift_reserved_words_.insert("weak"); swift_reserved_words_.insert("where"); swift_reserved_words_.insert("while"); swift_reserved_words_.insert("willSet"); } else { swift_reserved_words_.insert("Self"); swift_reserved_words_.insert("associatedtype"); swift_reserved_words_.insert("defer"); swift_reserved_words_.insert("deinit"); swift_reserved_words_.insert("dynamicType"); swift_reserved_words_.insert("enum"); swift_reserved_words_.insert("extension"); swift_reserved_words_.insert("fallthrough"); swift_reserved_words_.insert("false"); swift_reserved_words_.insert("func"); swift_reserved_words_.insert("guard"); swift_reserved_words_.insert("init"); swift_reserved_words_.insert("inout"); swift_reserved_words_.insert("internal"); swift_reserved_words_.insert("let"); swift_reserved_words_.insert("operator"); swift_reserved_words_.insert("protocol"); swift_reserved_words_.insert("repeat"); swift_reserved_words_.insert("rethrows"); swift_reserved_words_.insert("struct"); swift_reserved_words_.insert("subscript"); swift_reserved_words_.insert("throws"); swift_reserved_words_.insert("true"); swift_reserved_words_.insert("typealias"); swift_reserved_words_.insert("where"); } } string t_swift_generator::maybe_escape_identifier(const string& identifier) { if (swift_reserved_words_.find(identifier) != swift_reserved_words_.end()) { return "`" + identifier + "`"; } return identifier; } /** * Converts the parse type to a Swift TType enumeration. */ string t_swift_generator::type_to_enum(t_type* type, bool qualified) { type = get_true_type(type); string result = qualified ? "TType." : "."; if (!gen_cocoa_) { if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return result + "string"; case t_base_type::TYPE_BOOL: return result + "bool"; case t_base_type::TYPE_I8: return result + "i8"; case t_base_type::TYPE_I16: return result + "i16"; case t_base_type::TYPE_I32: return result + "i32"; case t_base_type::TYPE_I64: return result + "i64"; case t_base_type::TYPE_DOUBLE: return result + "double"; case t_base_type::TYPE_UUID: return result + "uuid"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return result + "i32"; } else if (type->is_struct() || type->is_xception()) { return result + "struct"; } else if (type->is_map()) { return result + "map"; } else if (type->is_set()) { return result + "set"; } else if (type->is_list()) { return result + "list"; } } else { if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return result + "STRING"; case t_base_type::TYPE_BOOL: return result + "BOOL"; case t_base_type::TYPE_I8: return result + "BYTE"; case t_base_type::TYPE_I16: return result + "I16"; case t_base_type::TYPE_I32: return result + "I32"; case t_base_type::TYPE_I64: return result + "I64"; case t_base_type::TYPE_DOUBLE: return result + "DOUBLE"; case t_base_type::TYPE_UUID: return result + "UUID"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return result + "I32"; } else if (type->is_struct() || type->is_xception()) { return result + "STRUCT"; } else if (type->is_map()) { return result + "MAP"; } else if (type->is_set()) { return result + "SET"; } else if (type->is_list()) { return result + "LIST"; } } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } std::string t_swift_generator::display_name() const { return "Swift 3.0"; } THRIFT_REGISTER_GENERATOR( swift, "Swift 3.0", " log_unexpected: Log every time an unexpected field ID or type is encountered.\n" " debug_descriptions:\n" " Allow use of debugDescription so the app can add description via a cateogory/extension\n" " async_clients: Generate clients which invoke asynchronously via block syntax.\n" " namespaced: Generate source in Module scoped output directories for Swift Namespacing.\n" " cocoa: Generate Swift 2.x code compatible with the Thrift/Cocoa library\n" " promise_kit: Generate clients which invoke asynchronously via promises (only use with cocoa flag)\n" " safe_enums: Generate enum types with an unknown case to handle unspecified values rather than throw a serialization error\n") thrift-0.19.0/compiler/cpp/src/thrift/generate/t_rs_generator.cc0000644000000000000000000036024514370300523024707 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include "thrift/platform.h" #include "thrift/generate/t_generator.h" using std::map; using std::ofstream; using std::ostringstream; using std::pair; using std::set; using std::string; using std::vector; static const string endl("\n"); // avoid ostream << std::endl flushes static const string SERVICE_RESULT_VARIABLE("result_value"); static const string RESULT_STRUCT_SUFFIX("Result"); static const string RUST_RESERVED_WORDS[] = { "abstract", "alignof", "as", "become", "box", "break", "const", "continue", "crate", "do", "else", "enum", "extern", "false", "final", "fn", "for", "if", "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "offsetof", "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", "self", "sizeof", "static", "struct", "super", "trait", "true", "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield" }; const set RUST_RESERVED_WORDS_SET( RUST_RESERVED_WORDS, RUST_RESERVED_WORDS + sizeof(RUST_RESERVED_WORDS)/sizeof(RUST_RESERVED_WORDS[0]) ); static const string SYNC_CLIENT_GENERIC_BOUND_VARS(""); static const string SYNC_CLIENT_GENERIC_BOUNDS("where IP: TInputProtocol, OP: TOutputProtocol"); // FIXME: extract common TMessageIdentifier function // FIXME: have to_rust_type deal with Option class t_rs_generator : public t_generator { public: t_rs_generator( t_program* program, const std::map&, const std::string& ) : t_generator(program) { gen_dir_ = get_out_dir(); } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; private: // struct type // T_REGULAR: user-defined struct in the IDL // T_ARGS: struct used to hold all service-call parameters // T_RESULT: struct used to hold all service-call returns and exceptions // T_EXCEPTION: user-defined exception in the IDL enum e_struct_type { T_REGULAR, T_ARGS, T_RESULT, T_EXCEPTION }; // Directory to which generated code is written. string gen_dir_; // File to which generated code is written. ofstream_with_content_based_conditional_update f_gen_; // Write the common compiler attributes and module includes to the top of the auto-generated file. void render_attributes_and_includes(); // Create the closure of Rust modules referenced by this service. void compute_service_referenced_modules(t_service *tservice, set> &referenced_modules); // Write the rust representation of an enum. void render_enum_definition(t_enum* tenum, const string& enum_name); // Write the impl blocks associated with the traits necessary to convert an enum to/from an i32. void render_enum_conversion(t_enum* tenum, const string& enum_name); // Write the impl block associated with the rust representation of an enum. This includes methods // to write the enum to a protocol, read it from a protocol, etc. void render_enum_impl(t_enum* tenum, const string& enum_name); // Write a simple rust const value (ie. `pub const FOO: foo...`). void render_const_value(const string& name, t_type* ttype, t_const_value* tvalue); // Write a constant list, set, map or struct. These constants require allocation and cannot be defined // using a 'pub const'. As a result, I create a holder struct with a single `const_value` method that // returns the initialized instance. void render_const_value_holder(const string& name, t_type* ttype, t_const_value* tvalue); // Write the actual const value - the right side of a const definition. void render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned = true, bool is_inline = true); // Write a const struct (returned from `const_value` method). void render_const_struct(t_type* ttype, t_const_value* tvalue); // Write a const list (returned from `const_value` method). void render_const_list(t_type* ttype, t_const_value* tvalue); // Write a const set (returned from `const_value` method). void render_const_set(t_type* ttype, t_const_value* tvalue); // Write a const map (returned from `const_value` method). void render_const_map(t_type* ttype, t_const_value* tvalue); // Write the rust representation of a thrift struct to the generated file. Set `struct_type` to `T_ARGS` // if rendering the struct used to pack arguments for a service call. When `struct_type` is `T_ARGS` the // struct and its members have module visibility, and all fields are required. When `struct_type` is // anything else the struct and its members have public visibility and fields have the visibility set // in their definition. void render_struct(const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type); // Write the comment block preceding a type definition (and implementation). void render_type_comment(const string& struct_name); // Write the rust representation of a thrift struct. Supports argument structs, result structs, // user-defined structs and exception structs. The exact struct type to be generated is controlled // by the `struct_type` parameter, which (among other things) modifies the visibility of the // written struct and members, controls which trait implementations are generated. void render_struct_definition( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ); // Writes the impl block associated with the rust representation of a struct. At minimum this // contains the methods to read from a protocol and write to a protocol. Additional methods may // be generated depending on `struct_type`. void render_struct_impl( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ); // Generate a `fn new(...)` for a struct with name `struct_name` and type `t_struct`. The auto-generated // code may include generic type parameters to make the constructor more ergonomic. `struct_type` controls // the visibility of the generated constructor. void render_struct_constructor( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ); // Write the `ok_or` method added to all Thrift service call result structs. You can use this method // to convert a struct into a `Result` and use it in a `try!` or combinator chain. void render_result_struct_to_result_method(t_struct* tstruct); // Write the implementations for the `Error` and `Debug` traits. These traits are necessary for a // user-defined exception to be properly handled as Rust errors. void render_exception_struct_error_trait_impls(const string& struct_name, t_struct* tstruct); // Write the function that serializes a struct to its wire representation. If `struct_type` is `T_ARGS` // then all fields are considered "required", if not, the default optionality is used. void render_struct_sync_write(t_struct *tstruct, t_rs_generator::e_struct_type struct_type); // Helper function that serializes a single struct field to its wire representation. Unpacks the // variable (since it may be optional) and serializes according to the optionality rules required by `req`. // Variables in auto-generated code are passed by reference. Since this function may be called in // contexts where the variable is *already* a reference you can set `field_var_is_ref` to `true` to avoid // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. void render_struct_field_sync_write( const string &field_var, bool field_var_is_ref, t_field *tfield, t_field::e_req req); // Write the rust function that serializes a single type (i.e. a i32 etc.) to its wire representation. // Variables in auto-generated code are passed by reference. Since this function may be called in // contexts where the variable is *already* a reference you can set `type_var_is_ref` to `true` to avoid // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. void render_type_sync_write(const string &type_var, bool type_var_is_ref, t_type *ttype); // Write a list to the output protocol. `list_variable` is the variable containing the list // that will be written to the output protocol. // Variables in auto-generated code are passed by reference. Since this function may be called in // contexts where the variable is *already* a reference you can set `list_var_is_ref` to `true` to avoid // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. void render_list_sync_write(const string &list_var, bool list_var_is_ref, t_list *tlist); // Write a set to the output protocol. `set_variable` is the variable containing the set that will // be written to the output protocol. // Variables in auto-generated code are passed by reference. Since this function may be called in // contexts where the variable is *already* a reference you can set `set_var_is_ref` to `true` to avoid // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. void render_set_sync_write(const string &set_var, bool set_var_is_ref, t_set *tset); // Write a map to the output protocol. `map_variable` is the variable containing the map that will // be written to the output protocol. // Variables in auto-generated code are passed by reference. Since this function may be called in // contexts where the variable is *already* a reference you can set `map_var_is_ref` to `true` to avoid // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. void render_map_sync_write(const string &map_var, bool map_var_is_ref, t_map *tset); // Return `true` if we need to dereference ths type when writing an element from a container. // Iterations on rust containers are performed as follows: `for v in &values { ... }` // where `v` has type `&RUST_TYPE` All defined functions take primitives by value, so, if the // rendered code is calling such a function it has to dereference `v`. bool needs_deref_on_container_write(t_type* ttype); // Return the variable (including all dereferences) required to write values from a rust container // to the output protocol. For example, if you were iterating through a container and using the temp // variable `v` to represent each element, then `ttype` is the type stored in the container and // `base_var` is "v". The return value is the actual string you will have to use to properly reference // the temp variable for writing to the output protocol. string string_container_write_variable(t_type* ttype, const string& base_var); // Write the code to read bytes from the wire into the given `t_struct`. `struct_name` is the // actual Rust name of the `t_struct`. If `struct_type` is `T_ARGS` then all struct fields are // necessary. Otherwise, the field's default optionality is used. void render_struct_sync_read(const string &struct_name, t_struct *tstruct, t_rs_generator::e_struct_type struct_type); // Write the rust function that deserializes a single type (i.e. i32 etc.) from its wire representation. // Set `is_boxed` to `true` if the resulting value should be wrapped in a `Box::new(...)`. void render_type_sync_read(const string &type_var, t_type *ttype, bool is_boxed = false); // Read the wire representation of a list and convert it to its corresponding rust implementation. // The deserialized list is stored in `list_variable`. void render_list_sync_read(t_list *tlist, const string &list_variable); // Read the wire representation of a set and convert it to its corresponding rust implementation. // The deserialized set is stored in `set_variable`. void render_set_sync_read(t_set *tset, const string &set_variable); // Read the wire representation of a map and convert it to its corresponding rust implementation. // The deserialized map is stored in `map_variable`. void render_map_sync_read(t_map *tmap, const string &map_variable); // Return a temporary variable used to store values when deserializing nested containers. string struct_field_read_temp_variable(t_field* tfield); // Top-level function that calls the various render functions necessary to write the rust representation // of a thrift union (i.e. an enum). void render_union(t_struct* tstruct); // Write the enum corresponding to the Thrift union. void render_union_definition(const string& union_name, t_struct* tstruct); // Write the enum impl (with read/write functions) for the Thrift union. void render_union_impl(const string& union_name, t_struct* tstruct); // Write the `ENUM::write_to_out_protocol` function. void render_union_sync_write(const string &union_name, t_struct *tstruct); // Write the `ENUM::read_from_in_protocol` function. void render_union_sync_read(const string &union_name, t_struct *tstruct); // Top-level function that calls the various render functions necessary to write the rust representation // of a Thrift client. void render_sync_client(t_service* tservice); // Write the trait with the service-call methods for `tservice`. void render_sync_client_trait(t_service *tservice); // Write the trait to be implemented by the client impl if end users can use it to make service calls. void render_sync_client_marker_trait(t_service *tservice); // Write the code to create the Thrift service sync client struct and its matching 'impl' block. void render_sync_client_definition_and_impl(const string& client_impl_name); // Write the code to create the `SyncClient::new` functions as well as any other functions // callers would like to use on the Thrift service sync client. void render_sync_client_lifecycle_functions(const string& client_struct); // Write the code to create the impl block for the `TThriftClient` trait. Since generated // Rust Thrift clients perform all their operations using methods defined in this trait, we // have to implement it for the client structs. void render_sync_client_tthriftclient_impl(const string &client_impl_name); // Write the marker traits for any service(s) being extended, including the one for the current // service itself (i.e. `tservice`) void render_sync_client_marker_trait_impls(t_service *tservice, const string &impl_struct_name); // Generate a list of all the traits this Thrift client struct extends. string sync_client_marker_traits_for_extension(t_service *tservice); // Top-level function that writes the code to make the Thrift service calls. void render_sync_client_process_impl(t_service* tservice); // Write the actual function that calls out to the remote service and processes its response. void render_sync_send_recv_wrapper(t_function* tfunc); // Write the `send` functionality for a Thrift service call represented by a `t_service->t_function`. void render_sync_send(t_function* tfunc); // Write the `recv` functionality for a Thrift service call represented by a `t_service->t_function`. // This method is only rendered if the function is *not* oneway. void render_sync_recv(t_function* tfunc); void render_sync_processor(t_service *tservice); void render_sync_handler_trait(t_service *tservice); void render_sync_processor_definition_and_impl(t_service *tservice); void render_sync_process_delegation_functions(t_service *tservice); void render_sync_process_function(t_function *tfunc, const string &handler_type); void render_process_match_statements(t_service* tservice); void render_sync_handler_succeeded(t_function *tfunc); void render_sync_handler_failed(t_function *tfunc); void render_sync_handler_failed_user_exception_branch(t_function *tfunc); void render_sync_handler_failed_application_exception_branch(t_function *tfunc, const string &app_err_var); void render_sync_handler_failed_default_exception_branch(t_function *tfunc); void render_sync_handler_send_exception_response(t_function *tfunc, const string &err_var); void render_service_call_structs(t_service* tservice); void render_service_call_args_struct(t_function* tfunc); void render_service_call_result_value_struct(t_function* tfunc); string handler_successful_return_struct(t_function* tfunc); // Writes the result of `render_thrift_error_struct` wrapped in an `Err(thrift::Error(...))`. void render_thrift_error( const string& error_kind, const string& error_struct, const string& sub_error_kind, const string& error_message ); // Write a thrift::Error variant struct. Error structs take the form: // ``` // pub struct error_struct { // kind: sub_error_kind, // message: error_message, // } // ``` // A concrete example is: // ``` // pub struct ApplicationError { // kind: ApplicationErrorKind::Unknown, // message: "This is some error message", // } // ``` void render_thrift_error_struct( const string& error_struct, const string& sub_error_kind, const string& error_message ); // Return a string containing all the unpacked service call args given a service call function // `t_function`. Prepends the args with either `&mut self` or `&self` and includes the arg types // in the returned string, for example: // `fn foo(&mut self, field_0: String)`. string rust_sync_service_call_declaration(t_function* tfunc, bool self_is_mutable); // Return a string containing all the unpacked service call args given a service call function // `t_function`. Only includes the arg names, each of which is prefixed with the optional prefix // `field_prefix`, for example: `self.field_0`. string rust_sync_service_call_invocation(t_function* tfunc, const string& field_prefix = ""); // Return a string containing all fields in the struct `tstruct` for use in a function declaration. // Each field is followed by its type, for example: `field_0: String`. string struct_to_declaration(t_struct* tstruct, t_rs_generator::e_struct_type struct_type); // Return a string containing all fields in the struct `tstruct` for use in a function call, // for example: `field_0: String`. string struct_to_invocation(t_struct* tstruct, const string& field_prefix = ""); // Write the documentation for a struct, service-call or other documentation-annotated element. void render_rustdoc(t_doc* tdoc); // Return `true` if the true type of `ttype` is a thrift double, `false` otherwise. bool is_double(t_type* ttype); // Return a string representing the rust type given a `t_type`. string to_rust_type(t_type* ttype); // Return a string representing the `const` rust type given a `t_type` string to_rust_const_type(t_type* ttype); // Return a string representing the rift `protocol::TType` given a `t_type`. string to_rust_field_type_enum(t_type* ttype); // Return the default value to be used when initializing a struct field which has `OPT_IN_REQ_OUT` // optionality. string opt_in_req_out_value(t_type* ttype); // Return `true` if we can write a const of the form `pub const FOO: ...`. bool can_generate_simple_const(t_type* ttype); // Return `true` if we cannot write a standard Rust constant (because the type needs some allocation). bool can_generate_const_holder(t_type* ttype); // Return `true` if this type is a void, and should be represented by the rust `()` type. bool is_void(t_type* ttype); t_field::e_req actual_field_req(t_field* tfield, t_rs_generator::e_struct_type struct_type); // Return `true` if this `t_field::e_req` is either `t_field::T_OPTIONAL` or `t_field::T_OPT_IN_REQ_OUT` // and needs to be wrapped by an `Option`, `false` otherwise. bool is_optional(t_field::e_req req); // Return `true` if the service call has arguments, `false` otherwise. bool has_args(t_function* tfunc); // Return `true` if a service call has non-`()` arguments, `false` otherwise. bool has_non_void_args(t_function* tfunc); // Return `pub ` (notice trailing whitespace!) if the struct should be public, `` (empty string) otherwise. string visibility_qualifier(t_rs_generator::e_struct_type struct_type); // Returns the namespace prefix for a given Thrift service. If the type is defined in the presently-computed // Thrift program, then an empty string is returned. string rust_namespace(t_service* tservice); // Returns the namespace prefix for a given Thrift type. If the type is defined in the presently-computed // Thrift program, then an empty string is returned. string rust_namespace(t_type* ttype); // Returns the camel-cased name for a Rust struct type. Handles the case where `tstruct->get_name()` is // a reserved word. string rust_struct_name(t_struct* tstruct); // Returns the snake-cased name for a Rust field or local variable. Handles the case where // `tfield->get_name()` is a reserved word. string rust_field_name(t_field* tstruct); // Returns the camel-cased name for a Rust union type. Handles the case where `tstruct->get_name()` is // a reserved word. string rust_union_field_name(t_field* tstruct); // Converts any variable name into a 'safe' variant that does not clash with any Rust reserved keywords. string rust_safe_name(const string& name); // Return `true` if the name is a reserved Rust keyword, `false` otherwise. bool is_reserved(const string& name); // Return the name of the function that users will invoke to make outgoing service calls. string service_call_client_function_name(t_function* tfunc); // Return the name of the function that users will have to implement to handle incoming service calls. string service_call_handler_function_name(t_function* tfunc); // Return the name of the struct used to pack the arguments for the thrift service call. string service_call_args_struct_name(t_function* tfunc); // Return the name of the struct used to pack the return value // and user-defined exceptions for the thrift service call. string service_call_result_struct_name(t_function* tfunc); string rust_sync_client_marker_trait_name(t_service* tservice); // Return the trait name for the sync service client given a `t_service`. string rust_sync_client_trait_name(t_service* tservice); // Return the name for the sync service client struct given a `t_service`. string rust_sync_client_impl_name(t_service* tservice); // Return the trait name that users will have to implement for the server half of a Thrift service. string rust_sync_handler_trait_name(t_service* tservice); // Return the struct name for the server half of a Thrift service. string rust_sync_processor_name(t_service* tservice); // Return the struct name for the struct that contains all the service-call implementations for // the server half of a Thrift service. string rust_sync_processor_impl_name(t_service *tservice); // Return the variant name for an enum variant string rust_enum_variant_name(const string& name); // Properly uppercase names for use in Rust. string rust_upper_case(const string& name); // Snake-case field, parameter and function names and make them Rust friendly. string rust_snake_case(const string& name); // Camel-case type/variant names and make them Rust friendly. string rust_camel_case(const string& name); // Replace all instances of `search_string` with `replace_string` in `target`. void string_replace(string& target, const string& search_string, const string& replace_string); // Adjust field identifier to correctly handle unspecified field identifiers // THRIFT-4953 string rust_safe_field_id(int32_t id); }; void t_rs_generator::init_generator() { // make output directory for this thrift program MKDIR(gen_dir_.c_str()); // create the file into which we're going to write the generated code string f_gen_name = gen_dir_ + "/" + rust_snake_case(get_program()->get_name()) + ".rs"; f_gen_.open(f_gen_name.c_str()); // header comment f_gen_ << "// " << autogen_summary() << endl; f_gen_ << "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING" << endl; f_gen_ << endl; render_attributes_and_includes(); } void t_rs_generator::render_attributes_and_includes() { // turn off some compiler/clippy warnings // code may not be used f_gen_ << "#![allow(dead_code)]" << endl; // code always includes BTreeMap/BTreeSet/OrderedFloat f_gen_ << "#![allow(unused_imports)]" << endl; // code might not include imports from crates f_gen_ << "#![allow(unused_extern_crates)]" << endl; // constructors take *all* struct parameters, which can trigger the "too many arguments" warning // some auto-gen'd types can be deeply nested. clippy recommends factoring them out which is hard to autogen // some methods may start with "is_" // FIXME: re-enable the 'vec_box' lint see: [THRIFT-5364](https://issues.apache.org/jira/browse/THRIFT-5364) // This can happen because we automatically generate a Vec> when the type is a typedef // and it's a forward typedef. This (typedef + forward typedef) can happen in two situations: // 1. When the type is recursive // 2. When you define types out of order f_gen_ << "#![allow(clippy::too_many_arguments, clippy::type_complexity, clippy::vec_box, clippy::wrong_self_convention)]" << endl; // prevent rustfmt from running against this file // lines are too long, code is (thankfully!) not visual-indented, etc. // can't use #[rustfmt::skip] see: https://github.com/rust-lang/rust/issues/54726 f_gen_ << "#![cfg_attr(rustfmt, rustfmt_skip)]" << endl; f_gen_ << endl; // add standard includes f_gen_ << "use std::cell::RefCell;" << endl; f_gen_ << "use std::collections::{BTreeMap, BTreeSet};" << endl; f_gen_ << "use std::convert::{From, TryFrom};" << endl; f_gen_ << "use std::default::Default;" << endl; f_gen_ << "use std::error::Error;" << endl; f_gen_ << "use std::fmt;" << endl; f_gen_ << "use std::fmt::{Display, Formatter};" << endl; f_gen_ << "use std::rc::Rc;" << endl; f_gen_ << endl; f_gen_ << "use thrift::OrderedFloat;" << endl; f_gen_ << "use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, ProtocolErrorKind, TThriftClient};" << endl; f_gen_ << "use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSerializable, TSetIdentifier, TStructIdentifier, TType};" << endl; f_gen_ << "use thrift::protocol::field_id;" << endl; f_gen_ << "use thrift::protocol::verify_expected_message_type;" << endl; f_gen_ << "use thrift::protocol::verify_expected_sequence_number;" << endl; f_gen_ << "use thrift::protocol::verify_expected_service_call;" << endl; f_gen_ << "use thrift::protocol::verify_required_field_exists;" << endl; f_gen_ << "use thrift::server::TProcessor;" << endl; f_gen_ << endl; // add all the program includes // NOTE: this is more involved than you would expect because of service extension // Basically, I have to find the closure of all the services and include their modules at the top-level set> referenced_modules; // set // first, start by adding explicit thrift includes const vector includes = get_program()->get_includes(); vector::const_iterator includes_iter; for(includes_iter = includes.begin(); includes_iter != includes.end(); ++includes_iter) { referenced_modules.insert(std::make_pair((*includes_iter)->get_name(), (*includes_iter)->get_namespace("rs"))); } // next, recursively iterate through all the services and add the names of any programs they reference const vector services = get_program()->get_services(); vector::const_iterator service_iter; for (service_iter = services.begin(); service_iter != services.end(); ++service_iter) { compute_service_referenced_modules(*service_iter, referenced_modules); } // finally, write all the "pub use..." declarations if (!referenced_modules.empty()) { set>::iterator module_iter; for (module_iter = referenced_modules.begin(); module_iter != referenced_modules.end(); ++module_iter) { string module_name((*module_iter).first); string module_namespace((*module_iter).second); string_replace(module_namespace, ".", "::"); if (module_namespace.empty()) { f_gen_ << "use crate::" << rust_snake_case(module_name) << ";" << endl; } else { f_gen_ << "use crate::" << module_namespace << "::" << rust_snake_case(module_name) << ";" << endl; } } f_gen_ << endl; } } void t_rs_generator::compute_service_referenced_modules( t_service *tservice, set> &referenced_modules ) { t_service* extends = tservice->get_extends(); if (extends) { if (extends->get_program() != get_program()) { referenced_modules.insert(std::make_pair(extends->get_program()->get_name(), extends->get_program()->get_namespace("rs"))); } compute_service_referenced_modules(extends, referenced_modules); } } void t_rs_generator::close_generator() { f_gen_.close(); } //----------------------------------------------------------------------------- // // Consts // // NOTE: consider using macros to generate constants // //----------------------------------------------------------------------------- // This is worse than it should be because constants // aren't (sensibly) limited to scalar types void t_rs_generator::generate_const(t_const* tconst) { string name = tconst->get_name(); t_type* ttype = tconst->get_type(); t_const_value* tvalue = tconst->get_value(); if (can_generate_simple_const(ttype)) { render_const_value(name, ttype, tvalue); } else if (can_generate_const_holder(ttype)) { render_const_value_holder(name, ttype, tvalue); } else { throw "cannot generate const for " + name; } } void t_rs_generator::render_const_value(const string& name, t_type* ttype, t_const_value* tvalue) { if (!can_generate_simple_const(ttype)) { throw "cannot generate simple rust constant for " + ttype->get_name(); } f_gen_ << "pub const " << rust_upper_case(name) << ": " << to_rust_const_type(ttype) << " = "; render_const_value(ttype, tvalue, false); f_gen_ << ";" << endl; f_gen_ << endl; } void t_rs_generator::render_const_value_holder(const string& name, t_type* ttype, t_const_value* tvalue) { if (!can_generate_const_holder(ttype)) { throw "cannot generate constant holder for " + ttype->get_name(); } string holder_name("Const" + rust_camel_case(name)); f_gen_ << indent() << "pub struct " << holder_name << ";" << endl; f_gen_ << indent() << "impl " << holder_name << " {" << endl; indent_up(); f_gen_ << indent() << "pub fn const_value() -> " << to_rust_type(ttype) << " {" << endl; indent_up(); render_const_value(ttype, tvalue, true, false); indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned, bool is_inline) { if (!is_inline) { f_gen_ << indent(); } if (ttype->is_base_type()) { t_base_type* tbase_type = (t_base_type*)ttype; switch (tbase_type->get_base()) { case t_base_type::TYPE_STRING: if (tbase_type->is_binary()) { if (is_owned) { f_gen_ << "\"" << tvalue->get_string() << "\""<< ".to_owned().into_bytes()"; } else { f_gen_ << "b\"" << tvalue->get_string() << "\""; } } else { f_gen_ << "\"" << tvalue->get_string() << "\""; if (is_owned) { f_gen_ << ".to_owned()"; } } break; case t_base_type::TYPE_BOOL: f_gen_ << (tvalue->get_integer() ? "true" : "false"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: f_gen_ << tvalue->get_integer(); break; case t_base_type::TYPE_DOUBLE: f_gen_ << "OrderedFloat::from(" << tvalue->get_double() << "_f64)"; break; default: throw "cannot generate const value for " + t_base_type::t_base_name(tbase_type->get_base()); } } else if (ttype->is_typedef()) { render_const_value(get_true_type(ttype), tvalue, is_owned, true); } else if (ttype->is_enum()) { f_gen_ << "{" << endl; indent_up(); f_gen_ << indent() << to_rust_type(ttype) << "::try_from(" << tvalue->get_integer() << ").expect(\"expecting valid const value\")" << endl; indent_down(); f_gen_ << indent() << "}"; } else if (ttype->is_struct() || ttype->is_xception()) { render_const_struct(ttype, tvalue); } else if (ttype->is_container()) { // all of them use vec! or from(), extra block is no longer needed if (ttype->is_list()) { render_const_list(ttype, tvalue); } else if (ttype->is_set()) { render_const_set(ttype, tvalue); } else if (ttype->is_map()) { render_const_map(ttype, tvalue); } else { throw "cannot generate const container value for " + ttype->get_name(); } } else { throw "cannot generate const value for " + ttype->get_name(); } if (!is_inline) { f_gen_ << endl; } } void t_rs_generator::render_const_struct(t_type* ttype, t_const_value*) { if (((t_struct*)ttype)->is_union()) { f_gen_ << "{" << endl; indent_up(); f_gen_ << indent() << "unimplemented!()" << endl; indent_down(); f_gen_ << indent() << "}"; } else { f_gen_ << "{" << endl; indent_up(); f_gen_ << indent() << "unimplemented!()" << endl; indent_down(); f_gen_ << indent() << "}"; } } void t_rs_generator::render_const_list(t_type* ttype, t_const_value* tvalue) { t_type* elem_type = ((t_list*)ttype)->get_elem_type(); f_gen_ << "vec![" << endl; indent_up(); const vector& elems = tvalue->get_list(); vector::const_iterator elem_iter; for(elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { f_gen_ << indent(); t_const_value* elem_value = (*elem_iter); render_const_value(elem_type, elem_value); f_gen_ << "," << endl; } indent_down(); f_gen_ << indent() << "]"; } void t_rs_generator::render_const_set(t_type* ttype, t_const_value* tvalue) { t_type* elem_type = ((t_set*)ttype)->get_elem_type(); f_gen_ << "BTreeSet::from([" << endl; indent_up(); const vector& elems = tvalue->get_list(); vector::const_iterator elem_iter; for(elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { f_gen_ << indent(); t_const_value* elem_value = (*elem_iter); render_const_value(elem_type, elem_value); f_gen_ << "," << endl; } indent_down(); f_gen_ << indent() << "])"; } void t_rs_generator::render_const_map(t_type* ttype, t_const_value* tvalue) { t_type* key_type = ((t_map*)ttype)->get_key_type(); t_type* val_type = ((t_map*)ttype)->get_val_type(); f_gen_ << "BTreeMap::from([" << endl; indent_up(); const map& elems = tvalue->get_map(); map::const_iterator elem_iter; for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { t_const_value* key_value = elem_iter->first; t_const_value* val_value = elem_iter->second; f_gen_ << indent() << "(" << endl; indent_up(); f_gen_ << indent(); render_const_value(key_type, key_value); f_gen_ << "," << endl; f_gen_ << indent(); render_const_value(val_type, val_value); f_gen_ << "," << endl; indent_down(); f_gen_ << indent() << ")," << endl; } indent_down(); f_gen_ << indent() << "])"; } //----------------------------------------------------------------------------- // // Typedefs // //----------------------------------------------------------------------------- void t_rs_generator::generate_typedef(t_typedef* ttypedef) { std::string actual_type = to_rust_type(ttypedef->get_type()); f_gen_ << "pub type " << rust_safe_name(ttypedef->get_symbolic()) << " = " << actual_type << ";" << endl; f_gen_ << endl; } //----------------------------------------------------------------------------- // // Enums // //----------------------------------------------------------------------------- void t_rs_generator::generate_enum(t_enum* tenum) { string enum_name(rust_camel_case(tenum->get_name())); render_enum_definition(tenum, enum_name); render_enum_impl(tenum, enum_name); render_enum_conversion(tenum, enum_name); } void t_rs_generator::render_enum_definition(t_enum* tenum, const string& enum_name) { render_rustdoc((t_doc*) tenum); f_gen_ << "#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]" << endl; f_gen_ << "pub struct " << enum_name << "(pub i32);" << endl; f_gen_ << endl; } void t_rs_generator::render_enum_impl(t_enum* tenum, const string& enum_name) { f_gen_ << "impl " << enum_name << " {" << endl; indent_up(); vector constants = tenum->get_constants(); // associated constants for each IDL-defined enum variant { vector::iterator constants_iter; for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { t_enum_value* val = (*constants_iter); render_rustdoc((t_doc*) val); f_gen_ << indent() << "pub const " << rust_enum_variant_name(val->get_name()) << ": " << enum_name << " = " << enum_name << "(" << val->get_value() << ")" << ";" << endl; } } // array containing all IDL-defined enum variants { f_gen_ << indent() << "pub const ENUM_VALUES: &'static [Self] = &[" << endl; indent_up(); vector::iterator constants_iter; for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { t_enum_value* val = (*constants_iter); f_gen_ << indent() << "Self::" << rust_enum_variant_name(val->get_name()) << "," << endl; } indent_down(); f_gen_ << indent() << "];" << endl; } indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; f_gen_ << "impl TSerializable for " << enum_name << " {" << endl; indent_up(); f_gen_ << indent() << "#[allow(clippy::trivially_copy_pass_by_ref)]" << endl; f_gen_ << indent() << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" << endl; indent_up(); f_gen_ << indent() << "o_prot.write_i32(self.0)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" << enum_name << "> {" << endl; indent_up(); f_gen_ << indent() << "let enum_value = i_prot.read_i32()?;" << endl; f_gen_ << indent() << "Ok(" << enum_name << "::from(enum_value)" << ")" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_enum_conversion(t_enum* tenum, const string& enum_name) { // From trait: i32 -> ENUM_TYPE f_gen_ << "impl From for " << enum_name << " {" << endl; indent_up(); f_gen_ << indent() << "fn from(i: i32) -> Self {" << endl; indent_up(); f_gen_ << indent() << "match i {" << endl; indent_up(); vector constants = tenum->get_constants(); vector::iterator constants_iter; for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { t_enum_value* val = (*constants_iter); f_gen_ << indent() << val->get_value() << " => " << enum_name << "::" << rust_enum_variant_name(val->get_name()) << "," << endl; } f_gen_ << indent() << "_ => " << enum_name << "(i)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; // From trait: &i32 -> ENUM_TYPE f_gen_ << "impl From<&i32> for " << enum_name << " {" << endl; indent_up(); f_gen_ << indent() << "fn from(i: &i32) -> Self {" << endl; indent_up(); f_gen_ << indent() << enum_name << "::from(*i)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; // From trait: ENUM_TYPE -> int f_gen_ << "impl From<" << enum_name << "> for i32 {" << endl; indent_up(); f_gen_ << indent() << "fn from(e: " << enum_name << ") -> i32 {" << endl; indent_up(); f_gen_ << indent() << "e.0" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; // From trait: &ENUM_TYPE -> int f_gen_ << "impl From<&" << enum_name << "> for i32 {" << endl; indent_up(); f_gen_ << indent() << "fn from(e: &" << enum_name << ") -> i32 {" << endl; indent_up(); f_gen_ << indent() << "e.0" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } //----------------------------------------------------------------------------- // // Structs, Unions and Exceptions // //----------------------------------------------------------------------------- void t_rs_generator::generate_xception(t_struct* txception) { render_struct(rust_struct_name(txception), txception, t_rs_generator::T_EXCEPTION); } void t_rs_generator::generate_struct(t_struct* tstruct) { if (tstruct->is_union()) { render_union(tstruct); } else if (tstruct->is_struct()) { render_struct(rust_struct_name(tstruct), tstruct, t_rs_generator::T_REGULAR); } else { throw "cannot generate struct for exception"; } } void t_rs_generator::render_struct( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ) { render_type_comment(struct_name); render_struct_definition(struct_name, tstruct, struct_type); render_struct_impl(struct_name, tstruct, struct_type); if (struct_type == t_rs_generator::T_EXCEPTION) { render_exception_struct_error_trait_impls(struct_name, tstruct); } } void t_rs_generator::render_struct_definition( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ) { render_rustdoc((t_doc*) tstruct); const vector members = tstruct->get_sorted_members(); vector::const_iterator members_iter; bool need_default = struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION; for (members_iter = members.begin(); need_default && members_iter != members.end(); ++members_iter) { t_field* member = *members_iter; if (!is_optional(member->get_req())) { need_default = false; } } f_gen_ << "#[derive(Clone, Debug" << (need_default ? ", Default" : "") << ", Eq, Hash, Ord, PartialEq, PartialOrd)]" << endl; f_gen_ << visibility_qualifier(struct_type) << "struct " << struct_name << " {" << endl; // render the members if (!members.empty()) { indent_up(); for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string rust_type = to_rust_type(member->get_type()); rust_type = is_optional(member_req) ? "Option<" + rust_type + ">" : rust_type; render_rustdoc((t_doc*) member); f_gen_ << indent() << visibility_qualifier(struct_type) << rust_field_name(member) << ": " << rust_type << "," << endl; } indent_down(); } f_gen_ << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_exception_struct_error_trait_impls(const string& struct_name, t_struct* tstruct) { // error::Error trait f_gen_ << "impl Error for " << struct_name << " {}" << endl; f_gen_ << endl; // convert::From trait f_gen_ << "impl From<" << struct_name << "> for thrift::Error {" << endl; indent_up(); f_gen_ << indent() << "fn from(e: " << struct_name << ") -> Self {" << endl; indent_up(); f_gen_ << indent() << "thrift::Error::User(Box::new(e))" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; // fmt::Display trait f_gen_ << "impl Display for " << struct_name << " {" << endl; indent_up(); f_gen_ << indent() << "fn fmt(&self, f: &mut Formatter) -> fmt::Result {" << endl; indent_up(); f_gen_ << indent() << "write!(f, " << "\"remote service threw " << tstruct->get_name() << "\"" // use *original* name << ")" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_struct_impl( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ) { f_gen_ << "impl " << struct_name << " {" << endl; indent_up(); if (struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION) { render_struct_constructor(struct_name, tstruct, struct_type); } if (struct_type == t_rs_generator::T_RESULT) { render_result_struct_to_result_method(tstruct); } if (struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION) { indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; f_gen_ << "impl TSerializable for " << struct_name << " {" << endl; indent_up(); } render_struct_sync_read(struct_name, tstruct, struct_type); render_struct_sync_write(tstruct, struct_type); indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_struct_constructor( const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type ) { const vector& members = tstruct->get_sorted_members(); vector::const_iterator members_iter; // build the convenience type parameters that allows us to pass unwrapped values to a constructor and // have them automatically converted into Option bool first_arg = true; ostringstream generic_type_parameters; ostringstream generic_type_qualifiers; for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); if (is_optional(member_req)) { if (first_arg) { first_arg = false; } else { generic_type_parameters << ", "; generic_type_qualifiers << ", "; } generic_type_parameters << "F" << rust_safe_field_id(member->get_key()); generic_type_qualifiers << "F" << rust_safe_field_id(member->get_key()) << ": Intoget_type()) << ">>"; } } string type_parameter_string = generic_type_parameters.str(); if (type_parameter_string.length() != 0) { type_parameter_string = "<" + type_parameter_string + ">"; } string type_qualifier_string = generic_type_qualifiers.str(); if (type_qualifier_string.length() != 0) { type_qualifier_string = "where " + type_qualifier_string + " "; } // now build the actual constructor arg list // when we're building this list we have to use the type parameters in place of the actual type names // if necessary ostringstream args; first_arg = true; for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string member_name(rust_field_name(member)); if (first_arg) { first_arg = false; } else { args << ", "; } if (is_optional(member_req)) { args << member_name << ": " << "F" << rust_safe_field_id(member->get_key()); } else { args << member_name << ": " << to_rust_type(member->get_type()); } } string arg_string = args.str(); string visibility(visibility_qualifier(struct_type)); f_gen_ << indent() << visibility << "fn new" << type_parameter_string << "(" << arg_string << ") -> " << struct_name << " " << type_qualifier_string << "{" << endl; indent_up(); if (members.empty()) { f_gen_ << indent() << struct_name << " {}" << endl; } else { f_gen_ << indent() << struct_name << " {" << endl; indent_up(); for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string member_name(rust_field_name(member)); if (is_optional(member_req)) { f_gen_ << indent() << member_name << ": " << member_name << ".into()," << endl; } else { f_gen_ << indent() << member_name << "," << endl; } } indent_down(); f_gen_ << indent() << "}" << endl; } indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { // we don't use the rust struct name in this method, just the service call name string service_call_name = tstruct->get_name(); // check that we actually have a result size_t index = service_call_name.find(RESULT_STRUCT_SUFFIX, 0); if (index == std::string::npos) { throw "result struct " + service_call_name + " missing result suffix"; } else { service_call_name.replace(index, 6, ""); } const vector& members = tstruct->get_sorted_members(); vector::const_iterator members_iter; // find out what the call's expected return type was string rust_return_type = "()"; for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); if (member->get_name() == SERVICE_RESULT_VARIABLE) { // don't have to check safe name here rust_return_type = to_rust_type(member->get_type()); break; } } // NOTE: ideally I would generate the branches and render them separately // I tried this however, and the resulting code was harder to understand // maintaining a rendered branch count (while a little ugly) got me the // rendering I wanted with code that was reasonably understandable f_gen_ << indent() << "fn ok_or(self) -> thrift::Result<" << rust_return_type << "> {" << endl; indent_up(); int rendered_branch_count = 0; // render the exception branches for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* tfield = (*members_iter); if (tfield->get_name() != SERVICE_RESULT_VARIABLE) { // don't have to check safe name here string field_name("self." + rust_field_name(tfield)); string branch_statement = rendered_branch_count == 0 ? "if" : "} else if"; f_gen_ << indent() << branch_statement << " " << field_name << ".is_some() {" << endl; indent_up(); f_gen_ << indent() << "Err(thrift::Error::User(Box::new(" << field_name << ".unwrap())))" << endl; indent_down(); rendered_branch_count++; } } // render the return value branches if (rust_return_type == "()") { if (rendered_branch_count == 0) { // we have the unit return and this service call has no user-defined // exceptions. this means that we've a trivial return (happens with oneways) f_gen_ << indent() << "Ok(())" << endl; } else { // we have the unit return, but there are user-defined exceptions // if we've gotten this far then we have the default return (i.e. call successful) f_gen_ << indent() << "} else {" << endl; indent_up(); f_gen_ << indent() << "Ok(())" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } } else { string branch_statement = rendered_branch_count == 0 ? "if" : "} else if"; f_gen_ << indent() << branch_statement << " self." << SERVICE_RESULT_VARIABLE << ".is_some() {" << endl; indent_up(); f_gen_ << indent() << "Ok(self." << SERVICE_RESULT_VARIABLE << ".unwrap())" << endl; indent_down(); f_gen_ << indent() << "} else {" << endl; indent_up(); // if we haven't found a valid return value *or* a user exception // then we're in trouble; return a default error render_thrift_error( "Application", "ApplicationError", "ApplicationErrorKind::MissingResult", "\"no result received for " + service_call_name + "\"" ); indent_down(); f_gen_ << indent() << "}" << endl; } indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_union(t_struct* tstruct) { string union_name(rust_struct_name(tstruct)); render_type_comment(union_name); render_union_definition(union_name, tstruct); render_union_impl(union_name, tstruct); } void t_rs_generator::render_union_definition(const string& union_name, t_struct* tstruct) { const vector& members = tstruct->get_sorted_members(); if (members.empty()) { throw "cannot generate rust enum with 0 members"; // may be valid thrift, but it's invalid rust } f_gen_ << "#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]" << endl; f_gen_ << "pub enum " << union_name << " {" << endl; indent_up(); vector::const_iterator member_iter; for(member_iter = members.begin(); member_iter != members.end(); ++member_iter) { t_field* tfield = (*member_iter); f_gen_ << indent() << rust_union_field_name(tfield) << "(" << to_rust_type(tfield->get_type()) << ")," << endl; } indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_union_impl(const string& union_name, t_struct* tstruct) { f_gen_ << "impl TSerializable for " << union_name << " {" << endl; indent_up(); render_union_sync_read(union_name, tstruct); render_union_sync_write(union_name, tstruct); indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } //----------------------------------------------------------------------------- // // Sync Struct Write // //----------------------------------------------------------------------------- void t_rs_generator::render_struct_sync_write( t_struct *tstruct, t_rs_generator::e_struct_type struct_type ) { f_gen_ << indent() << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" << endl; indent_up(); // write struct header to output protocol // note: use the *original* struct name here f_gen_ << indent() << "let struct_ident = TStructIdentifier::new(\"" + tstruct->get_name() + "\");" << endl; f_gen_ << indent() << "o_prot.write_struct_begin(&struct_ident)?;" << endl; // write struct members to output protocol vector members = tstruct->get_sorted_members(); if (!members.empty()) { vector::iterator members_iter; for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string member_var("self." + rust_field_name(member)); render_struct_field_sync_write(member_var, false, member, member_req); } } // write struct footer to output protocol f_gen_ << indent() << "o_prot.write_field_stop()?;" << endl; f_gen_ << indent() << "o_prot.write_struct_end()" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_union_sync_write(const string &union_name, t_struct *tstruct) { f_gen_ << indent() << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" << endl; indent_up(); // write struct header to output protocol // note: use the *original* struct name here f_gen_ << indent() << "let struct_ident = TStructIdentifier::new(\"" + tstruct->get_name() + "\");" << endl; f_gen_ << indent() << "o_prot.write_struct_begin(&struct_ident)?;" << endl; // write the enum field to the output protocol vector members = tstruct->get_sorted_members(); if (!members.empty()) { f_gen_ << indent() << "match *self {" << endl; indent_up(); vector::iterator members_iter; for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = t_field::T_REQUIRED; t_type* ttype = member->get_type(); if (ttype->is_typedef()) { // get the actual type of typedef ttype = ((t_typedef*)ttype)->get_type(); } string match_var((ttype->is_base_type() && !ttype->is_string()) ? "f" : "ref f"); f_gen_ << indent() << union_name << "::" << rust_union_field_name(member) << "(" << match_var << ") => {" << endl; indent_up(); render_struct_field_sync_write("f", true, member, member_req); indent_down(); f_gen_ << indent() << "}," << endl; } indent_down(); f_gen_ << indent() << "}" << endl; } // write struct footer to output protocol f_gen_ << indent() << "o_prot.write_field_stop()?;" << endl; f_gen_ << indent() << "o_prot.write_struct_end()" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_struct_field_sync_write( const string &field_var, bool field_var_is_ref, t_field *tfield, t_field::e_req req ) { t_type* field_type = tfield->get_type(); t_type* actual_type = get_true_type(field_type); ostringstream field_stream; field_stream << "TFieldIdentifier::new(" << "\"" << tfield->get_name() << "\"" << ", " // note: use *original* name << to_rust_field_type_enum(field_type) << ", " << tfield->get_key() << ")"; string field_ident_string = field_stream.str(); if (is_optional(req)) { string let_var((actual_type->is_base_type() && !actual_type->is_string()) ? "fld_var" : "ref fld_var"); f_gen_ << indent() << "if let Some(" << let_var << ") = " << field_var << " {" << endl; indent_up(); f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl; render_type_sync_write("fld_var", true, field_type); f_gen_ << indent() << "o_prot.write_field_end()?" << endl; indent_down(); /* FIXME: rethink how I deal with OPT_IN_REQ_OUT if (req == t_field::T_OPT_IN_REQ_OUT) { f_gen_ << indent() << "let field_ident = " << field_ident_string << ";" << endl; f_gen_ << indent() << "o_prot.write_field_begin(&field_ident)?;" << endl; f_gen_ << indent() << "o_prot.write_field_end()?;" << endl; }*/ f_gen_ << indent() << "}" << endl; } else { f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl; render_type_sync_write(field_var, field_var_is_ref, tfield->get_type()); f_gen_ << indent() << "o_prot.write_field_end()?;" << endl; } } void t_rs_generator::render_type_sync_write(const string &type_var, bool type_var_is_ref, t_type *ttype) { if (ttype->is_base_type()) { t_base_type* tbase_type = (t_base_type*)ttype; switch (tbase_type->get_base()) { case t_base_type::TYPE_VOID: throw "cannot write field of type TYPE_VOID to output protocol"; case t_base_type::TYPE_STRING: { string ref(type_var_is_ref ? "" : "&"); if (tbase_type->is_binary()) { f_gen_ << indent() << "o_prot.write_bytes(" + ref + type_var + ")?;" << endl; } else { f_gen_ << indent() << "o_prot.write_string(" + ref + type_var + ")?;" << endl; } return; } case t_base_type::TYPE_BOOL: f_gen_ << indent() << "o_prot.write_bool(" + type_var + ")?;" << endl; return; case t_base_type::TYPE_I8: f_gen_ << indent() << "o_prot.write_i8(" + type_var + ")?;" << endl; return; case t_base_type::TYPE_I16: f_gen_ << indent() << "o_prot.write_i16(" + type_var + ")?;" << endl; return; case t_base_type::TYPE_I32: f_gen_ << indent() << "o_prot.write_i32(" + type_var + ")?;" << endl; return; case t_base_type::TYPE_I64: f_gen_ << indent() << "o_prot.write_i64(" + type_var + ")?;" << endl; return; case t_base_type::TYPE_DOUBLE: f_gen_ << indent() << "o_prot.write_double(" + type_var + ".into())?;" << endl; return; default: throw "compiler error: unhandled type"; } } else if (ttype->is_typedef()) { t_typedef* ttypedef = (t_typedef*) ttype; render_type_sync_write(type_var, type_var_is_ref, ttypedef->get_type()); return; } else if (ttype->is_enum() || ttype->is_struct() || ttype->is_xception()) { f_gen_ << indent() << type_var + ".write_to_out_protocol(o_prot)?;" << endl; return; } else if (ttype->is_map()) { render_map_sync_write(type_var, type_var_is_ref, (t_map *) ttype); return; } else if (ttype->is_set()) { render_set_sync_write(type_var, type_var_is_ref, (t_set *) ttype); return; } else if (ttype->is_list()) { render_list_sync_write(type_var, type_var_is_ref, (t_list *) ttype); return; } throw "cannot write unsupported type " + ttype->get_name(); } void t_rs_generator::render_list_sync_write(const string &list_var, bool list_var_is_ref, t_list *tlist) { t_type* elem_type = tlist->get_elem_type(); f_gen_ << indent() << "o_prot.write_list_begin(" << "&TListIdentifier::new(" << to_rust_field_type_enum(elem_type) << ", " << list_var << ".len() as i32" << ")" << ")?;" << endl; string ref(list_var_is_ref ? "" : "&"); f_gen_ << indent() << "for e in " << ref << list_var << " {" << endl; indent_up(); render_type_sync_write(string_container_write_variable(elem_type, "e"), true, elem_type); indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "o_prot.write_list_end()?;" << endl; } void t_rs_generator::render_set_sync_write(const string &set_var, bool set_var_is_ref, t_set *tset) { t_type* elem_type = tset->get_elem_type(); f_gen_ << indent() << "o_prot.write_set_begin(" << "&TSetIdentifier::new(" << to_rust_field_type_enum(elem_type) << ", " << set_var << ".len() as i32" << ")" << ")?;" << endl; string ref(set_var_is_ref ? "" : "&"); f_gen_ << indent() << "for e in " << ref << set_var << " {" << endl; indent_up(); render_type_sync_write(string_container_write_variable(elem_type, "e"), true, elem_type); indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "o_prot.write_set_end()?;" << endl; } void t_rs_generator::render_map_sync_write(const string &map_var, bool map_var_is_ref, t_map *tmap) { t_type* key_type = tmap->get_key_type(); t_type* val_type = tmap->get_val_type(); f_gen_ << indent() << "o_prot.write_map_begin(" << "&TMapIdentifier::new(" << to_rust_field_type_enum(key_type) << ", " << to_rust_field_type_enum(val_type) << ", " << map_var << ".len() as i32)" << ")?;" << endl; string ref(map_var_is_ref ? "" : "&"); f_gen_ << indent() << "for (k, v) in " << ref << map_var << " {" << endl; indent_up(); render_type_sync_write(string_container_write_variable(key_type, "k"), true, key_type); render_type_sync_write(string_container_write_variable(val_type, "v"), true, val_type); indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "o_prot.write_map_end()?;" << endl; } string t_rs_generator::string_container_write_variable(t_type* ttype, const string& base_var) { bool type_needs_deref = needs_deref_on_container_write(ttype); bool type_is_double = is_double(ttype); string write_variable; if (type_is_double && type_needs_deref) { write_variable = "(*" + base_var + ")"; } else if (type_needs_deref) { write_variable = "*" + base_var; } else { write_variable = base_var; } return write_variable; } bool t_rs_generator::needs_deref_on_container_write(t_type* ttype) { ttype = get_true_type(ttype); return ttype->is_base_type() && !ttype->is_string(); } //----------------------------------------------------------------------------- // // Sync Struct Read // //----------------------------------------------------------------------------- void t_rs_generator::render_struct_sync_read( const string &struct_name, t_struct *tstruct, t_rs_generator::e_struct_type struct_type ) { f_gen_ << indent() << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" << struct_name << "> {" << endl; indent_up(); f_gen_ << indent() << "i_prot.read_struct_begin()?;" << endl; // create temporary variables: one for each field in the struct const vector members = tstruct->get_sorted_members(); vector::const_iterator members_iter; for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); f_gen_ << indent() << "let mut " << struct_field_read_temp_variable(member) << ": Option<" << to_rust_type(member->get_type()) << "> = "; if (member_req == t_field::T_OPT_IN_REQ_OUT) { f_gen_ << opt_in_req_out_value(member->get_type()) << ";"; } else { f_gen_ << "None;"; } f_gen_ << endl; } // now loop through the fields we've received f_gen_ << indent() << "loop {" << endl; // start loop indent_up(); // break out if you've found the Stop field f_gen_ << indent() << "let field_ident = i_prot.read_field_begin()?;" << endl; f_gen_ << indent() << "if field_ident.field_type == TType::Stop {" << endl; indent_up(); f_gen_ << indent() << "break;" << endl; indent_down(); f_gen_ << indent() << "}" << endl; // now read all the fields found // avoid clippy::match_single_binding if (members.empty()) { f_gen_ << indent() << "i_prot.skip(field_ident.field_type)?;" << endl; } else { f_gen_ << indent() << "let field_id = field_id(&field_ident)?;" << endl; f_gen_ << indent() << "match field_id {" << endl; // start match indent_up(); for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* tfield = (*members_iter); f_gen_ << indent() << rust_safe_field_id(tfield->get_key()) << " => {" << endl; indent_up(); render_type_sync_read("val", tfield->get_type()); f_gen_ << indent() << struct_field_read_temp_variable(tfield) << " = Some(val);" << endl; indent_down(); f_gen_ << indent() << "}," << endl; } // default case (skip fields) f_gen_ << indent() << "_ => {" << endl; indent_up(); f_gen_ << indent() << "i_prot.skip(field_ident.field_type)?;" << endl; indent_down(); f_gen_ << indent() << "}," << endl; indent_down(); f_gen_ << indent() << "};" << endl; // finish match } f_gen_ << indent() << "i_prot.read_field_end()?;" << endl; indent_down(); f_gen_ << indent() << "}" << endl; // finish loop f_gen_ << indent() << "i_prot.read_struct_end()?;" << endl; // read message footer from the wire // verify that all required fields exist for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* tfield = (*members_iter); t_field::e_req req = actual_field_req(tfield, struct_type); if (!is_optional(req)) { f_gen_ << indent() << "verify_required_field_exists(" << "\"" << struct_name << "." << rust_field_name(tfield) << "\"" << ", " << "&" << struct_field_read_temp_variable(tfield) << ")?;" << endl; } } // construct the struct if (members.size() == 0) { f_gen_ << indent() << "let ret = " << struct_name << " {};" << endl; } else { f_gen_ << indent() << "let ret = " << struct_name << " {" << endl; indent_up(); for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* tfield = (*members_iter); t_field::e_req req = actual_field_req(tfield, struct_type); string field_name(rust_field_name(tfield)); string field_key = struct_field_read_temp_variable(tfield); if (is_optional(req)) { f_gen_ << indent() << field_name << ": " << field_key << "," << endl; } else { f_gen_ << indent() << field_name << ": " << field_key << ".expect(\"auto-generated code should have checked for presence of required fields\")" << "," << endl; } } indent_down(); f_gen_ << indent() << "};" << endl; } // return the constructed value f_gen_ << indent() << "Ok(ret)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_union_sync_read(const string &union_name, t_struct *tstruct) { f_gen_ << indent() << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" << union_name << "> {" << endl; indent_up(); // create temporary variables to hold the // completed union as well as a count of fields read f_gen_ << indent() << "let mut ret: Option<" << union_name << "> = None;" << endl; f_gen_ << indent() << "let mut received_field_count = 0;" << endl; // read the struct preamble f_gen_ << indent() << "i_prot.read_struct_begin()?;" << endl; // now loop through the fields we've received f_gen_ << indent() << "loop {" << endl; // start loop indent_up(); // break out if you've found the Stop field f_gen_ << indent() << "let field_ident = i_prot.read_field_begin()?;" << endl; f_gen_ << indent() << "if field_ident.field_type == TType::Stop {" << endl; indent_up(); f_gen_ << indent() << "break;" << endl; indent_down(); f_gen_ << indent() << "}" << endl; // now read all the fields found f_gen_ << indent() << "let field_id = field_id(&field_ident)?;" << endl; f_gen_ << indent() << "match field_id {" << endl; // start match indent_up(); const vector members = tstruct->get_sorted_members(); vector::const_iterator members_iter; for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); f_gen_ << indent() << rust_safe_field_id(member->get_key()) << " => {" << endl; indent_up(); render_type_sync_read("val", member->get_type()); f_gen_ << indent() << "if ret.is_none() {" << endl; indent_up(); f_gen_ << indent() << "ret = Some(" << union_name << "::" << rust_union_field_name(member) << "(val));" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "received_field_count += 1;" << endl; indent_down(); f_gen_ << indent() << "}," << endl; } // default case (skip fields) f_gen_ << indent() << "_ => {" << endl; indent_up(); f_gen_ << indent() << "i_prot.skip(field_ident.field_type)?;" << endl; f_gen_ << indent() << "received_field_count += 1;" << endl; indent_down(); f_gen_ << indent() << "}," << endl; indent_down(); f_gen_ << indent() << "};" << endl; // finish match f_gen_ << indent() << "i_prot.read_field_end()?;" << endl; indent_down(); f_gen_ << indent() << "}" << endl; // finish loop f_gen_ << indent() << "i_prot.read_struct_end()?;" << endl; // finish reading message from wire // return the value or an error f_gen_ << indent() << "if received_field_count == 0 {" << endl; indent_up(); render_thrift_error( "Protocol", "ProtocolError", "ProtocolErrorKind::InvalidData", "\"received empty union from remote " + union_name + "\"" ); indent_down(); f_gen_ << indent() << "} else if received_field_count > 1 {" << endl; indent_up(); render_thrift_error( "Protocol", "ProtocolError", "ProtocolErrorKind::InvalidData", "\"received multiple fields for union from remote " + union_name + "\"" ); indent_down(); f_gen_ << indent() << "} else {" << endl; indent_up(); f_gen_ << indent() << "Ok(ret.expect(\"return value should have been constructed\"))" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } // Construct the rust representation of all supported types from the wire. void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype, bool is_boxed) { if (ttype->is_base_type()) { t_base_type* tbase_type = (t_base_type*)ttype; switch (tbase_type->get_base()) { case t_base_type::TYPE_VOID: throw "cannot read field of type TYPE_VOID from input protocol"; case t_base_type::TYPE_STRING: if (tbase_type->is_binary()) { f_gen_ << indent() << "let " << type_var << " = i_prot.read_bytes()?;" << endl; } else { f_gen_ << indent() << "let " << type_var << " = i_prot.read_string()?;" << endl; } return; case t_base_type::TYPE_BOOL: f_gen_ << indent() << "let " << type_var << " = i_prot.read_bool()?;" << endl; return; case t_base_type::TYPE_I8: f_gen_ << indent() << "let " << type_var << " = i_prot.read_i8()?;" << endl; return; case t_base_type::TYPE_I16: f_gen_ << indent() << "let " << type_var << " = i_prot.read_i16()?;" << endl; return; case t_base_type::TYPE_I32: f_gen_ << indent() << "let " << type_var << " = i_prot.read_i32()?;" << endl; return; case t_base_type::TYPE_I64: f_gen_ << indent() << "let " << type_var << " = i_prot.read_i64()?;" << endl; return; case t_base_type::TYPE_DOUBLE: f_gen_ << indent() << "let " << type_var << " = OrderedFloat::from(i_prot.read_double()?);" << endl; return; default: throw "compiler error: unhandled type"; } } else if (ttype->is_typedef()) { // FIXME: not a fan of separate `is_boxed` parameter // This is problematic because it's an optional parameter, and only comes // into play once. The core issue is that I lose an important piece of type // information (whether the type is a fwd ref) by unwrapping the typedef'd // type and making the recursive call using it. I can't modify or wrap the // generated string after the fact because it's written directly into the file, // so I have to pass this parameter along. Going with this approach because it // seems like the lowest-cost option to easily support recursive types. t_typedef* ttypedef = (t_typedef*)ttype; render_type_sync_read(type_var, ttypedef->get_type(), ttypedef->is_forward_typedef()); return; } else if (ttype->is_enum() || ttype->is_struct() || ttype->is_xception()) { string read_call(to_rust_type(ttype) + "::read_from_in_protocol(i_prot)?"); read_call = is_boxed ? "Box::new(" + read_call + ")" : read_call; f_gen_ << indent() << "let " << type_var << " = " << read_call << ";" << endl; return; } else if (ttype->is_map()) { render_map_sync_read((t_map *) ttype, type_var); return; } else if (ttype->is_set()) { render_set_sync_read((t_set *) ttype, type_var); return; } else if (ttype->is_list()) { render_list_sync_read((t_list *) ttype, type_var); return; } throw "cannot read unsupported type " + ttype->get_name(); } // Construct the rust representation of a list from the wire. void t_rs_generator::render_list_sync_read(t_list *tlist, const string &list_var) { t_type* elem_type = tlist->get_elem_type(); f_gen_ << indent() << "let list_ident = i_prot.read_list_begin()?;" << endl; f_gen_ << indent() << "let mut " << list_var << ": " << to_rust_type((t_type*) tlist) << " = Vec::with_capacity(list_ident.size as usize);" << endl; f_gen_ << indent() << "for _ in 0..list_ident.size {" << endl; indent_up(); string list_elem_var = tmp("list_elem_"); render_type_sync_read(list_elem_var, elem_type); f_gen_ << indent() << list_var << ".push(" << list_elem_var << ");" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "i_prot.read_list_end()?;" << endl; } // Construct the rust representation of a set from the wire. void t_rs_generator::render_set_sync_read(t_set *tset, const string &set_var) { t_type* elem_type = tset->get_elem_type(); f_gen_ << indent() << "let set_ident = i_prot.read_set_begin()?;" << endl; f_gen_ << indent() << "let mut " << set_var << ": " << to_rust_type((t_type*) tset) << " = BTreeSet::new();" << endl; f_gen_ << indent() << "for _ in 0..set_ident.size {" << endl; indent_up(); string set_elem_var = tmp("set_elem_"); render_type_sync_read(set_elem_var, elem_type); f_gen_ << indent() << set_var << ".insert(" << set_elem_var << ");" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "i_prot.read_set_end()?;" << endl; } // Construct the rust representation of a map from the wire. void t_rs_generator::render_map_sync_read(t_map *tmap, const string &map_var) { t_type* key_type = tmap->get_key_type(); t_type* val_type = tmap->get_val_type(); f_gen_ << indent() << "let map_ident = i_prot.read_map_begin()?;" << endl; f_gen_ << indent() << "let mut " << map_var << ": " << to_rust_type((t_type*) tmap) << " = BTreeMap::new();" << endl; f_gen_ << indent() << "for _ in 0..map_ident.size {" << endl; indent_up(); string key_elem_var = tmp("map_key_"); render_type_sync_read(key_elem_var, key_type); string val_elem_var = tmp("map_val_"); render_type_sync_read(val_elem_var, val_type); f_gen_ << indent() << map_var << ".insert(" << key_elem_var << ", " << val_elem_var << ");" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "i_prot.read_map_end()?;" << endl; } string t_rs_generator::struct_field_read_temp_variable(t_field* tfield) { std::ostringstream foss; foss << "f_" << rust_safe_field_id(tfield->get_key()); return foss.str(); } //----------------------------------------------------------------------------- // // Sync Client // //----------------------------------------------------------------------------- void t_rs_generator::generate_service(t_service* tservice) { render_sync_client(tservice); render_sync_processor(tservice); render_service_call_structs(tservice); } void t_rs_generator::render_service_call_structs(t_service* tservice) { const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; // thrift args for service calls are packed // into a struct that's transmitted over the wire, so // generate structs for those too // // thrift returns are *also* packed into a struct // that's passed over the wire, so, generate the struct // for that too. Note that this result struct *also* // contains the exceptions as well for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); render_service_call_args_struct(tfunc); if (!tfunc->is_oneway()) { render_service_call_result_value_struct(tfunc); } } } void t_rs_generator::render_sync_client(t_service* tservice) { string client_impl_name(rust_sync_client_impl_name(tservice)); render_type_comment(tservice->get_name() + " service client"); // note: use *original* name render_sync_client_trait(tservice); render_sync_client_marker_trait(tservice); render_sync_client_definition_and_impl(client_impl_name); render_sync_client_tthriftclient_impl(client_impl_name); render_sync_client_marker_trait_impls(tservice, client_impl_name); f_gen_ << endl; render_sync_client_process_impl(tservice); } void t_rs_generator::render_sync_client_trait(t_service *tservice) { string extension = ""; if (tservice->get_extends()) { t_service* extends = tservice->get_extends(); extension = " : " + rust_namespace(extends) + rust_sync_client_trait_name(extends); } render_rustdoc((t_doc*) tservice); f_gen_ << "pub trait " << rust_sync_client_trait_name(tservice) << extension << " {" << endl; indent_up(); const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); string func_name = service_call_client_function_name(tfunc); string func_args = rust_sync_service_call_declaration(tfunc, true); string func_return = to_rust_type(tfunc->get_returntype()); render_rustdoc((t_doc*) tfunc); f_gen_ << indent() << "fn " << func_name << func_args << " -> thrift::Result<" << func_return << ">;" << endl; } indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_sync_client_marker_trait(t_service *tservice) { f_gen_ << indent() << "pub trait " << rust_sync_client_marker_trait_name(tservice) << " {}" << endl; f_gen_ << endl; } void t_rs_generator::render_sync_client_marker_trait_impls(t_service *tservice, const string &impl_struct_name) { f_gen_ << indent() << "impl " << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << rust_namespace(tservice) << rust_sync_client_marker_trait_name(tservice) << " for " << impl_struct_name << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS << " {}" << endl; t_service* extends = tservice->get_extends(); if (extends) { render_sync_client_marker_trait_impls(extends, impl_struct_name); } } void t_rs_generator::render_sync_client_definition_and_impl(const string& client_impl_name) { // render the definition for the client struct f_gen_ << "pub struct " << client_impl_name << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS << " {" << endl; indent_up(); f_gen_ << indent() << "_i_prot: IP," << endl; f_gen_ << indent() << "_o_prot: OP," << endl; f_gen_ << indent() << "_sequence_number: i32," << endl; indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; // render the struct implementation // this includes the new() function as well as the helper send/recv methods for each service call f_gen_ << "impl " << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << client_impl_name << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS << " {" << endl; indent_up(); render_sync_client_lifecycle_functions(client_impl_name); indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_sync_client_lifecycle_functions(const string& client_struct) { f_gen_ << indent() << "pub fn new(input_protocol: IP, output_protocol: OP) -> " << client_struct << SYNC_CLIENT_GENERIC_BOUND_VARS << " {" << endl; indent_up(); f_gen_ << indent() << client_struct << " { _i_prot: input_protocol, _o_prot: output_protocol, _sequence_number: 0 }" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_sync_client_tthriftclient_impl(const string &client_impl_name) { f_gen_ << indent() << "impl " << SYNC_CLIENT_GENERIC_BOUND_VARS << " TThriftClient for " << client_impl_name << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS << " {" << endl; indent_up(); f_gen_ << indent() << "fn i_prot_mut(&mut self) -> &mut dyn TInputProtocol { &mut self._i_prot }" << endl; f_gen_ << indent() << "fn o_prot_mut(&mut self) -> &mut dyn TOutputProtocol { &mut self._o_prot }" << endl; f_gen_ << indent() << "fn sequence_number(&self) -> i32 { self._sequence_number }" << endl; f_gen_ << indent() << "fn increment_sequence_number(&mut self) -> i32 { self._sequence_number += 1; self._sequence_number }" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_sync_client_process_impl(t_service* tservice) { string marker_extension = "" + sync_client_marker_traits_for_extension(tservice); f_gen_ << "impl " << rust_sync_client_trait_name(tservice) << " for C {" << endl; indent_up(); const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* func = (*func_iter); render_sync_send_recv_wrapper(func); } indent_down(); f_gen_ << "}" << endl; f_gen_ << endl; } string t_rs_generator::sync_client_marker_traits_for_extension(t_service *tservice) { string marker_extension; t_service* extends = tservice->get_extends(); if (extends) { marker_extension = " + " + rust_namespace(extends) + rust_sync_client_marker_trait_name(extends); marker_extension = marker_extension + sync_client_marker_traits_for_extension(extends); } return marker_extension; } void t_rs_generator::render_sync_send_recv_wrapper(t_function* tfunc) { string func_name = service_call_client_function_name(tfunc); string func_decl_args = rust_sync_service_call_declaration(tfunc, true); string func_call_args = rust_sync_service_call_invocation(tfunc); string func_return = to_rust_type(tfunc->get_returntype()); f_gen_ << indent() << "fn " << func_name << func_decl_args << " -> thrift::Result<" << func_return << "> {" << endl; indent_up(); f_gen_ << indent() << "(" << endl; indent_up(); render_sync_send(tfunc); indent_down(); f_gen_ << indent() << ")?;" << endl; if (tfunc->is_oneway()) { f_gen_ << indent() << "Ok(())" << endl; } else { render_sync_recv(tfunc); } indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_sync_send(t_function* tfunc) { f_gen_ << indent() << "{" << endl; indent_up(); // increment the sequence number and generate the call header string message_type = tfunc->is_oneway() ? "TMessageType::OneWay" : "TMessageType::Call"; f_gen_ << indent() << "self.increment_sequence_number();" << endl; f_gen_ << indent() << "let message_ident = " << "TMessageIdentifier::new(\"" << tfunc->get_name() << "\", " // note: use *original* name << message_type << ", " << "self.sequence_number());" << endl; // pack the arguments into the containing struct that we'll write out over the wire // note that this struct is generated even if we have 0 args ostringstream struct_definition; vector members = tfunc->get_arglist()->get_sorted_members(); vector::iterator members_iter; for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); string member_name(rust_field_name(member)); struct_definition << member_name << ", "; } string struct_fields = struct_definition.str(); if (struct_fields.size() > 0) { struct_fields = struct_fields.substr(0, struct_fields.size() - 2); // strip trailing comma } f_gen_ << indent() << "let call_args = " << service_call_args_struct_name(tfunc) << " { " << struct_fields << " };" << endl; // write everything over the wire f_gen_ << indent() << "self.o_prot_mut().write_message_begin(&message_ident)?;" << endl; f_gen_ << indent() << "call_args.write_to_out_protocol(self.o_prot_mut())?;" << endl; // written even if we have 0 args f_gen_ << indent() << "self.o_prot_mut().write_message_end()?;" << endl; f_gen_ << indent() << "self.o_prot_mut().flush()" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_sync_recv(t_function* tfunc) { f_gen_ << indent() << "{" << endl; indent_up(); f_gen_ << indent() << "let message_ident = self.i_prot_mut().read_message_begin()?;" << endl; f_gen_ << indent() << "verify_expected_sequence_number(self.sequence_number(), message_ident.sequence_number)?;" << endl; f_gen_ << indent() << "verify_expected_service_call(\"" << tfunc->get_name() <<"\", &message_ident.name)?;" << endl; // note: use *original* name // FIXME: replace with a "try" block f_gen_ << indent() << "if message_ident.message_type == TMessageType::Exception {" << endl; indent_up(); f_gen_ << indent() << "let remote_error = thrift::Error::read_application_error_from_in_protocol(self.i_prot_mut())?;" << endl; f_gen_ << indent() << "self.i_prot_mut().read_message_end()?;" << endl; f_gen_ << indent() << "return Err(thrift::Error::Application(remote_error))" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "verify_expected_message_type(TMessageType::Reply, message_ident.message_type)?;" << endl; f_gen_ << indent() << "let result = " << service_call_result_struct_name(tfunc) << "::read_from_in_protocol(self.i_prot_mut())?;" << endl; f_gen_ << indent() << "self.i_prot_mut().read_message_end()?;" << endl; f_gen_ << indent() << "result.ok_or()" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } string t_rs_generator::rust_sync_service_call_declaration(t_function* tfunc, bool self_is_mutable) { ostringstream func_args; if (self_is_mutable) { func_args << "(&mut self"; } else { func_args << "(&self"; } if (has_args(tfunc)) { func_args << ", "; // put comma after "self" func_args << struct_to_declaration(tfunc->get_arglist(), T_ARGS); } func_args << ")"; return func_args.str(); } string t_rs_generator::rust_sync_service_call_invocation(t_function* tfunc, const string& field_prefix) { ostringstream func_args; func_args << "("; if (has_args(tfunc)) { func_args << struct_to_invocation(tfunc->get_arglist(), field_prefix); } func_args << ")"; return func_args.str(); } string t_rs_generator::struct_to_declaration(t_struct* tstruct, t_rs_generator::e_struct_type struct_type) { ostringstream args; bool first_arg = true; std::vector fields = tstruct->get_sorted_members(); std::vector::iterator field_iter; for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) { t_field* tfield = (*field_iter); t_field::e_req field_req = actual_field_req(tfield, struct_type); string rust_type = to_rust_type(tfield->get_type()); rust_type = is_optional(field_req) ? "Option<" + rust_type + ">" : rust_type; if (first_arg) { first_arg = false; } else { args << ", "; } args << rust_field_name(tfield) << ": " << rust_type; } return args.str(); } string t_rs_generator::struct_to_invocation(t_struct* tstruct, const string& field_prefix) { ostringstream args; bool first_arg = true; std::vector fields = tstruct->get_sorted_members(); std::vector::iterator field_iter; for (field_iter = fields.begin(); field_iter != fields.end(); ++field_iter) { t_field* tfield = (*field_iter); if (first_arg) { first_arg = false; } else { args << ", "; } args << field_prefix << rust_field_name(tfield); } return args.str(); } void t_rs_generator::render_service_call_args_struct(t_function* tfunc) { string args_struct_name(service_call_args_struct_name(tfunc)); render_struct(args_struct_name, tfunc->get_arglist(), t_rs_generator::T_ARGS); } void t_rs_generator::render_service_call_result_value_struct(t_function* tfunc) { string result_struct_name = service_call_result_struct_name(tfunc); t_struct result(program_, result_struct_name); t_field return_value(tfunc->get_returntype(), SERVICE_RESULT_VARIABLE, 0); return_value.set_req(t_field::T_OPTIONAL); if (!tfunc->get_returntype()->is_void()) { result.append(&return_value); } t_struct* exceptions = tfunc->get_xceptions(); const vector& exception_types = exceptions->get_members(); vector::const_iterator exception_iter; for(exception_iter = exception_types.begin(); exception_iter != exception_types.end(); ++exception_iter) { t_field* exception_type = *exception_iter; exception_type->set_req(t_field::T_OPTIONAL); result.append(exception_type); } render_struct(result_struct_name, &result, t_rs_generator::T_RESULT); } //----------------------------------------------------------------------------- // // Sync Processor // //----------------------------------------------------------------------------- void t_rs_generator::render_sync_processor(t_service *tservice) { render_type_comment(tservice->get_name() + " service processor"); // note: use *original* name render_sync_handler_trait(tservice); render_sync_processor_definition_and_impl(tservice); } void t_rs_generator::render_sync_handler_trait(t_service *tservice) { string extension = ""; if (tservice->get_extends() != nullptr) { t_service* extends = tservice->get_extends(); extension = " : " + rust_namespace(extends) + rust_sync_handler_trait_name(extends); } const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; render_rustdoc((t_doc*) tservice); f_gen_ << "pub trait " << rust_sync_handler_trait_name(tservice) << extension << " {" << endl; indent_up(); for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); string func_name = service_call_handler_function_name(tfunc); string func_args = rust_sync_service_call_declaration(tfunc, false); string func_return = to_rust_type(tfunc->get_returntype()); render_rustdoc((t_doc*) tfunc); f_gen_ << indent() << "fn " << func_name << func_args << " -> thrift::Result<" << func_return << ">;" << endl; } indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_sync_processor_definition_and_impl(t_service *tservice) { string service_processor_name = rust_sync_processor_name(tservice); string handler_trait_name = rust_sync_handler_trait_name(tservice); // struct f_gen_ << indent() << "pub struct " << service_processor_name << " {" << endl; indent_up(); f_gen_ << indent() << "handler: H," << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; // delegating impl f_gen_ << indent() << "impl " << service_processor_name << " {" << endl; indent_up(); f_gen_ << indent() << "pub fn new(handler: H) -> " << service_processor_name << " {" << endl; indent_up(); f_gen_ << indent() << service_processor_name << " {" << endl; indent_up(); f_gen_ << indent() << "handler," << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << indent() << "}" << endl; render_sync_process_delegation_functions(tservice); indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; // actual impl string service_actual_processor_name = rust_sync_processor_impl_name(tservice); f_gen_ << indent() << "pub struct " << service_actual_processor_name << ";" << endl; f_gen_ << endl; f_gen_ << indent() << "impl " << service_actual_processor_name << " {" << endl; indent_up(); vector functions = tservice->get_functions(); vector::iterator func_iter; for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); render_sync_process_function(tfunc, handler_trait_name); } indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; // processor impl f_gen_ << indent() << "impl TProcessor for " << service_processor_name << " {" << endl; indent_up(); f_gen_ << indent() << "fn process(&self, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" << endl; indent_up(); f_gen_ << indent() << "let message_ident = i_prot.read_message_begin()?;" << endl; f_gen_ << indent() << "let res = match &*message_ident.name {" << endl; // [sigh] explicit deref coercion indent_up(); render_process_match_statements(tservice); f_gen_ << indent() << "method => {" << endl; indent_up(); render_thrift_error( "Application", "ApplicationError", "ApplicationErrorKind::UnknownMethod", "format!(\"unknown method {}\", method)" ); indent_down(); f_gen_ << indent() << "}," << endl; indent_down(); f_gen_ << indent() << "};" << endl; f_gen_ << indent() << "thrift::server::handle_process_result(&message_ident, res, o_prot)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; } void t_rs_generator::render_sync_process_delegation_functions(t_service *tservice) { string actual_processor(rust_namespace(tservice) + rust_sync_processor_impl_name(tservice)); vector functions = tservice->get_functions(); vector::iterator func_iter; for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); string function_name("process_" + rust_snake_case(tfunc->get_name())); f_gen_ << indent() << "fn " << function_name << "(&self, " << "incoming_sequence_number: i32, " << "i_prot: &mut dyn TInputProtocol, " << "o_prot: &mut dyn TOutputProtocol) " << "-> thrift::Result<()> {" << endl; indent_up(); f_gen_ << indent() << actual_processor << "::" << function_name << "(" << "&self.handler, " << "incoming_sequence_number, " << "i_prot, " << "o_prot" << ")" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } t_service* extends = tservice->get_extends(); if (extends) { render_sync_process_delegation_functions(extends); } } void t_rs_generator::render_process_match_statements(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator func_iter; for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); f_gen_ << indent() << "\"" << tfunc->get_name() << "\"" << " => {" << endl; // note: use *original* name indent_up(); f_gen_ << indent() << "self.process_" << rust_snake_case(tfunc->get_name()) << "(message_ident.sequence_number, i_prot, o_prot)" << endl; indent_down(); f_gen_ << indent() << "}," << endl; } t_service* extends = tservice->get_extends(); if (extends) { render_process_match_statements(extends); } } void t_rs_generator::render_sync_process_function(t_function *tfunc, const string &handler_type) { string sequence_number_param("incoming_sequence_number"); string output_protocol_param("o_prot"); if (tfunc->is_oneway()) { sequence_number_param = "_"; output_protocol_param = "_"; } f_gen_ << indent() << "pub fn process_" << rust_snake_case(tfunc->get_name()) << "" << "(handler: &H, " << sequence_number_param << ": i32, " << "i_prot: &mut dyn TInputProtocol, " << output_protocol_param << ": &mut dyn TOutputProtocol) " << "-> thrift::Result<()> {" << endl; indent_up(); // *always* read arguments from the input protocol f_gen_ << indent() << "let " << (has_non_void_args(tfunc) ? "args" : "_") << " = " << service_call_args_struct_name(tfunc) << "::read_from_in_protocol(i_prot)?;" << endl; f_gen_ << indent() << "match handler." << service_call_handler_function_name(tfunc) << rust_sync_service_call_invocation(tfunc, "args.") << " {" << endl; // start match indent_up(); // handler succeeded string handler_return_variable = tfunc->is_oneway() || tfunc->get_returntype()->is_void() ? "_" : "handler_return"; f_gen_ << indent() << "Ok(" << handler_return_variable << ") => {" << endl; indent_up(); render_sync_handler_succeeded(tfunc); indent_down(); f_gen_ << indent() << "}," << endl; // handler failed f_gen_ << indent() << "Err(e) => {" << endl; indent_up(); render_sync_handler_failed(tfunc); indent_down(); f_gen_ << indent() << "}," << endl; indent_down(); f_gen_ << indent() << "}" << endl; // end match indent_down(); f_gen_ << indent() << "}" << endl; // end function } void t_rs_generator::render_sync_handler_succeeded(t_function *tfunc) { if (tfunc->is_oneway()) { f_gen_ << indent() << "Ok(())" << endl; } else { f_gen_ << indent() << "let message_ident = TMessageIdentifier::new(" << "\"" << tfunc->get_name() << "\", " // note: use *original* name << "TMessageType::Reply, " << "incoming_sequence_number);" << endl; f_gen_ << indent() << "o_prot.write_message_begin(&message_ident)?;" << endl; f_gen_ << indent() << "let ret = " << handler_successful_return_struct(tfunc) <<";" << endl; f_gen_ << indent() << "ret.write_to_out_protocol(o_prot)?;" << endl; f_gen_ << indent() << "o_prot.write_message_end()?;" << endl; f_gen_ << indent() << "o_prot.flush()" << endl; } } void t_rs_generator::render_sync_handler_failed(t_function *tfunc) { string err_var("e"); f_gen_ << indent() << "match " << err_var << " {" << endl; indent_up(); // if there are any user-defined exceptions for this service call handle them first if (tfunc->get_xceptions() != nullptr && tfunc->get_xceptions()->get_sorted_members().size() > 0) { string user_err_var("usr_err"); f_gen_ << indent() << "thrift::Error::User(" << user_err_var << ") => {" << endl; indent_up(); render_sync_handler_failed_user_exception_branch(tfunc); indent_down(); f_gen_ << indent() << "}," << endl; } // application error string app_err_var("app_err"); f_gen_ << indent() << "thrift::Error::Application(" << app_err_var << ") => {" << endl; indent_up(); render_sync_handler_failed_application_exception_branch(tfunc, app_err_var); indent_down(); f_gen_ << indent() << "}," << endl; // default case f_gen_ << indent() << "_ => {" << endl; indent_up(); render_sync_handler_failed_default_exception_branch(tfunc); indent_down(); f_gen_ << indent() << "}," << endl; indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function *tfunc) { if (tfunc->get_xceptions() == nullptr || tfunc->get_xceptions()->get_sorted_members().empty()) { throw "cannot render user exception branches if no user exceptions defined"; } const vector txceptions = tfunc->get_xceptions()->get_sorted_members(); vector::const_iterator xception_iter; int branches_rendered = 0; // run through all user-defined exceptions for (xception_iter = txceptions.begin(); xception_iter != txceptions.end(); ++xception_iter) { t_field* xception_field = (*xception_iter); string if_statement(branches_rendered == 0 ? "if usr_err" : "} else if usr_err"); string exception_type(to_rust_type(xception_field->get_type())); f_gen_ << indent() << if_statement << ".downcast_ref::<" << exception_type << ">().is_some() {" << endl; indent_up(); f_gen_ << indent() << "let err = usr_err.downcast::<" << exception_type << ">().expect(\"downcast already checked\");" << endl; // render the members of the return struct ostringstream members; bool has_result_variable = !(tfunc->is_oneway() || tfunc->get_returntype()->is_void()); if (has_result_variable) { members << SERVICE_RESULT_VARIABLE << ": None, "; } vector::const_iterator xception_members_iter; for(xception_members_iter = txceptions.begin(); xception_members_iter != txceptions.end(); ++xception_members_iter) { t_field* member = (*xception_members_iter); string member_name(rust_field_name(member)); if (member == xception_field) { members << member_name << ": Some(*err), "; } else { members << member_name << ": None, "; } } string member_string = members.str(); member_string.replace(member_string.size() - 2, 2, " "); // trim trailing comma // now write out the return struct f_gen_ << indent() << "let ret_err = " << service_call_result_struct_name(tfunc) << "{ " << member_string << "};" << endl; f_gen_ << indent() << "let message_ident = " << "TMessageIdentifier::new(" << "\"" << tfunc->get_name() << "\", " // note: use *original* name << "TMessageType::Reply, " << "incoming_sequence_number);" << endl; f_gen_ << indent() << "o_prot.write_message_begin(&message_ident)?;" << endl; f_gen_ << indent() << "ret_err.write_to_out_protocol(o_prot)?;" << endl; f_gen_ << indent() << "o_prot.write_message_end()?;" << endl; f_gen_ << indent() << "o_prot.flush()" << endl; indent_down(); branches_rendered++; } // the catch all, if somehow it was a user exception that we don't support f_gen_ << indent() << "} else {" << endl; indent_up(); // FIXME: same as default block below f_gen_ << indent() << "let ret_err = {" << endl; indent_up(); render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "usr_err.to_string()"); indent_down(); f_gen_ << indent() << "};" << endl; render_sync_handler_send_exception_response(tfunc, "ret_err"); indent_down(); f_gen_ << indent() << "}" << endl; } void t_rs_generator::render_sync_handler_failed_application_exception_branch( t_function *tfunc, const string &app_err_var ) { if (tfunc->is_oneway()) { f_gen_ << indent() << "Err(thrift::Error::Application(" << app_err_var << "))" << endl; } else { render_sync_handler_send_exception_response(tfunc, app_err_var); } } void t_rs_generator::render_sync_handler_failed_default_exception_branch(t_function *tfunc) { f_gen_ << indent() << "let ret_err = {" << endl; indent_up(); render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "e.to_string()"); indent_down(); f_gen_ << indent() << "};" << endl; if (tfunc->is_oneway()) { f_gen_ << indent() << "Err(thrift::Error::Application(ret_err))" << endl; } else { render_sync_handler_send_exception_response(tfunc, "ret_err"); } } void t_rs_generator::render_sync_handler_send_exception_response(t_function *tfunc, const string &err_var) { f_gen_ << indent() << "let message_ident = TMessageIdentifier::new(" << "\"" << tfunc->get_name() << "\", " // note: use *original* name << "TMessageType::Exception, " << "incoming_sequence_number);" << endl; f_gen_ << indent() << "o_prot.write_message_begin(&message_ident)?;" << endl; f_gen_ << indent() << "thrift::Error::write_application_error_to_out_protocol(&" << err_var << ", o_prot)?;" << endl; f_gen_ << indent() << "o_prot.write_message_end()?;" << endl; f_gen_ << indent() << "o_prot.flush()" << endl; } string t_rs_generator::handler_successful_return_struct(t_function* tfunc) { int member_count = 0; ostringstream return_struct; return_struct << service_call_result_struct_name(tfunc) << " { "; // actual return if (!tfunc->get_returntype()->is_void()) { return_struct << "result_value: Some(handler_return)"; member_count++; } // any user-defined exceptions if (tfunc->get_xceptions() != nullptr) { t_struct* txceptions = tfunc->get_xceptions(); const vector members = txceptions->get_sorted_members(); vector::const_iterator members_iter; for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* xception_field = (*members_iter); if (member_count > 0) { return_struct << ", "; } return_struct << rust_field_name(xception_field) << ": None"; member_count++; } } return_struct << " }"; return return_struct.str(); } //----------------------------------------------------------------------------- // // Utility // //----------------------------------------------------------------------------- void t_rs_generator::render_type_comment(const string& type_name) { f_gen_ << "//" << endl; f_gen_ << "// " << type_name << endl; f_gen_ << "//" << endl; f_gen_ << endl; } // NOTE: do *not* put in an extra newline after doc is generated. // This is because rust docs have to abut the line they're documenting. void t_rs_generator::render_rustdoc(t_doc* tdoc) { if (!tdoc->has_doc()) { return; } generate_docstring_comment(f_gen_, "", "/// ", tdoc->get_doc(), ""); } void t_rs_generator::render_thrift_error( const string& error_kind, const string& error_struct, const string& sub_error_kind, const string& error_message ) { f_gen_ << indent() << "Err(" << endl; indent_up(); f_gen_ << indent() << "thrift::Error::" << error_kind << "(" << endl; indent_up(); render_thrift_error_struct(error_struct, sub_error_kind, error_message); indent_down(); f_gen_ << indent() << ")" << endl; indent_down(); f_gen_ << indent() << ")" << endl; } void t_rs_generator::render_thrift_error_struct( const string& error_struct, const string& sub_error_kind, const string& error_message ) { f_gen_ << indent() << error_struct << "::new(" << endl; indent_up(); f_gen_ << indent() << sub_error_kind << "," << endl; f_gen_ << indent() << error_message << endl; indent_down(); f_gen_ << indent() << ")" << endl; } bool t_rs_generator::is_double(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); if (tbase == t_base_type::TYPE_DOUBLE) { return true; } } return false; } string t_rs_generator::to_rust_type(t_type* ttype) { // ttype = get_true_type(ttype); <-- recurses through as many typedef layers as necessary if (ttype->is_base_type()) { t_base_type* tbase_type = ((t_base_type*)ttype); switch (tbase_type->get_base()) { case t_base_type::TYPE_VOID: return "()"; case t_base_type::TYPE_STRING: if (tbase_type->is_binary()) { return "Vec"; } else { return "String"; } case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: return "i8"; case t_base_type::TYPE_I16: return "i16"; case t_base_type::TYPE_I32: return "i32"; case t_base_type::TYPE_I64: return "i64"; case t_base_type::TYPE_DOUBLE: return "OrderedFloat"; default: throw "compiler error: unhandled type"; } } else if (ttype->is_typedef()) { t_typedef* ttypedef = (t_typedef*)ttype; string rust_type = rust_namespace(ttype) + ttypedef->get_symbolic(); rust_type = ttypedef->is_forward_typedef() ? "Box<" + rust_type + ">" : rust_type; return rust_type; } else if (ttype->is_enum()) { return rust_namespace(ttype) + rust_camel_case(ttype->get_name()); } else if (ttype->is_struct() || ttype->is_xception()) { return rust_namespace(ttype) + rust_camel_case(ttype->get_name()); } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; return "BTreeMap<" + to_rust_type(tmap->get_key_type()) + ", " + to_rust_type(tmap->get_val_type()) + ">"; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; return "BTreeSet<" + to_rust_type(tset->get_elem_type()) + ">"; } else if (ttype->is_list()) { t_list* tlist = (t_list*)ttype; return "Vec<" + to_rust_type(tlist->get_elem_type()) + ">"; } throw "cannot find rust type for " + ttype->get_name(); } string t_rs_generator::to_rust_const_type(t_type* ttype) { if (ttype->is_base_type()) { t_base_type* tbase_type = ((t_base_type*)ttype); if (tbase_type->get_base() == t_base_type::TYPE_STRING) { if (tbase_type->is_binary()) { return "&[u8]"; } else { return "&str"; } } } return to_rust_type(ttype); } string t_rs_generator::to_rust_field_type_enum(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "will not generate protocol::TType for TYPE_VOID"; case t_base_type::TYPE_STRING: // both strings and binary are actually encoded as TType::String return "TType::String"; case t_base_type::TYPE_BOOL: return "TType::Bool"; case t_base_type::TYPE_I8: return "TType::I08"; case t_base_type::TYPE_I16: return "TType::I16"; case t_base_type::TYPE_I32: return "TType::I32"; case t_base_type::TYPE_I64: return "TType::I64"; case t_base_type::TYPE_DOUBLE: return "TType::Double"; default: throw "compiler error: unhandled type"; } } else if (ttype->is_enum()) { return "TType::I32"; } else if (ttype->is_struct() || ttype->is_xception()) { return "TType::Struct"; } else if (ttype->is_map()) { return "TType::Map"; } else if (ttype->is_set()) { return "TType::Set"; } else if (ttype->is_list()) { return "TType::List"; } throw "cannot find TType for " + ttype->get_name(); } string t_rs_generator::opt_in_req_out_value(t_type* ttype) { ttype = get_true_type(ttype); if (ttype->is_base_type()) { t_base_type* tbase_type = ((t_base_type*)ttype); switch (tbase_type->get_base()) { case t_base_type::TYPE_VOID: throw "cannot generate OPT_IN_REQ_OUT value for void"; case t_base_type::TYPE_STRING: if (tbase_type->is_binary()) { return "Some(Vec::new())"; } else { return "Some(\"\".to_owned())"; } case t_base_type::TYPE_BOOL: return "Some(false)"; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: return "Some(0)"; case t_base_type::TYPE_DOUBLE: return "Some(OrderedFloat::from(0.0))"; default: throw "compiler error: unhandled type"; } } else if (ttype->is_enum() || ttype->is_struct() || ttype->is_xception()) { return "None"; } else if (ttype->is_list()) { return "Some(Vec::new())"; } else if (ttype->is_set()) { return "Some(BTreeSet::new())"; } else if (ttype->is_map()) { return "Some(BTreeMap::new())"; } throw "cannot generate opt-in-req-out value for type " + ttype->get_name(); } bool t_rs_generator::can_generate_simple_const(t_type* ttype) { t_type* actual_type = get_true_type(ttype); if (actual_type->is_base_type()) { t_base_type* tbase_type = (t_base_type*)actual_type; return !(tbase_type->get_base() == t_base_type::TYPE_DOUBLE); } else { return false; } } bool t_rs_generator::can_generate_const_holder(t_type* ttype) { t_type* actual_type = get_true_type(ttype); return !can_generate_simple_const(actual_type) && !actual_type->is_service(); } bool t_rs_generator::is_void(t_type* ttype) { return ttype->is_base_type() && ((t_base_type*)ttype)->get_base() == t_base_type::TYPE_VOID; } bool t_rs_generator::is_optional(t_field::e_req req) { return req == t_field::T_OPTIONAL || req == t_field::T_OPT_IN_REQ_OUT; } t_field::e_req t_rs_generator::actual_field_req(t_field* tfield, t_rs_generator::e_struct_type struct_type) { return struct_type == t_rs_generator::T_ARGS ? t_field::T_REQUIRED : tfield->get_req(); } bool t_rs_generator::has_args(t_function* tfunc) { return tfunc->get_arglist() != nullptr && !tfunc->get_arglist()->get_sorted_members().empty(); } bool t_rs_generator::has_non_void_args(t_function* tfunc) { bool has_non_void_args = false; const vector args = tfunc->get_arglist()->get_sorted_members(); vector::const_iterator args_iter; for (args_iter = args.begin(); args_iter != args.end(); ++args_iter) { t_field* tfield = (*args_iter); if (!tfield->get_type()->is_void()) { has_non_void_args = true; break; } } return has_non_void_args; } string t_rs_generator::visibility_qualifier(t_rs_generator::e_struct_type struct_type) { switch(struct_type) { case t_rs_generator::T_ARGS: case t_rs_generator::T_RESULT: return ""; default: return "pub "; } } string t_rs_generator::rust_namespace(t_service* tservice) { if (tservice->get_program()->get_name() != get_program()->get_name()) { return rust_snake_case(tservice->get_program()->get_name()) + "::"; } else { return ""; } } string t_rs_generator::rust_namespace(t_type* ttype) { if (ttype->get_program()->get_name() != get_program()->get_name()) { return rust_snake_case(ttype->get_program()->get_name()) + "::"; } else { return ""; } } bool t_rs_generator::is_reserved(const string& name) { return RUST_RESERVED_WORDS_SET.find(name) != RUST_RESERVED_WORDS_SET.end(); } string t_rs_generator::rust_struct_name(t_struct* tstruct) { string base_struct_name(rust_camel_case(tstruct->get_name())); return rust_safe_name(base_struct_name); } string t_rs_generator::rust_field_name(t_field* tfield) { string base_field_name(rust_snake_case(tfield->get_name())); return rust_safe_name(base_field_name); } string t_rs_generator::rust_union_field_name(t_field* tfield) { string base_field_name(rust_camel_case(tfield->get_name())); return rust_safe_name(base_field_name); } string t_rs_generator::rust_safe_name(const string& name) { if (is_reserved(name)) { return name + "_"; } else { return name; } } string t_rs_generator::service_call_client_function_name(t_function* tfunc) { return rust_snake_case(tfunc->get_name()); } string t_rs_generator::service_call_handler_function_name(t_function* tfunc) { return "handle_" + rust_snake_case(tfunc->get_name()); } string t_rs_generator::service_call_args_struct_name(t_function* tfunc) { // Thrift automatically appends `Args` to the arglist name. No need to do it here. return rust_camel_case(service_name_) + rust_camel_case(tfunc->get_arglist()->get_name()); } string t_rs_generator::service_call_result_struct_name(t_function* tfunc) { return rust_camel_case(service_name_) + rust_camel_case(tfunc->get_name()) + RESULT_STRUCT_SUFFIX; } string t_rs_generator::rust_sync_client_marker_trait_name(t_service* tservice) { return "T" + rust_camel_case(tservice->get_name()) + "SyncClientMarker"; } string t_rs_generator::rust_sync_client_trait_name(t_service* tservice) { return "T" + rust_camel_case(tservice->get_name()) + "SyncClient"; } string t_rs_generator::rust_sync_client_impl_name(t_service* tservice) { return rust_camel_case(tservice->get_name()) + "SyncClient"; } string t_rs_generator::rust_sync_handler_trait_name(t_service* tservice) { return rust_camel_case(tservice->get_name()) + "SyncHandler"; } string t_rs_generator::rust_sync_processor_name(t_service* tservice) { return rust_camel_case(tservice->get_name()) + "SyncProcessor"; } string t_rs_generator::rust_sync_processor_impl_name(t_service *tservice) { return "T" + rust_camel_case(tservice->get_name()) + "ProcessFunctions"; } string t_rs_generator::rust_enum_variant_name(const string &name) { bool all_uppercase = true; for (char i : name) { if (isalpha(i) && islower(i)) { all_uppercase = false; break; } } if (all_uppercase) { return name; } else { string modified_name(uppercase(underscore(name))); string_replace(modified_name, "__", "_"); return modified_name; } } string t_rs_generator::rust_upper_case(const string& name) { bool all_uppercase = true; for (char i : name) { if (isalpha(i) && islower(i)) { all_uppercase = false; break; } } if (all_uppercase) { return name; } else { string str(uppercase(underscore(name))); string_replace(str, "__", "_"); return str; } } string t_rs_generator::rust_snake_case(const string& name) { string str(decapitalize(underscore(name))); string_replace(str, "__", "_"); return str; } string t_rs_generator::rust_camel_case(const string& name) { string str(capitalize(camelcase(name))); string_replace(str, "_", ""); return str; } string t_rs_generator::rust_safe_field_id(int32_t id) { string id_str = std::to_string(abs(id)); if (id >= 0) { return id_str; } else { string str("neg"); str += id_str; return str; } } void t_rs_generator::string_replace(string& target, const string& search_string, const string& replace_string) { if (target.empty()) { return; } size_t match_len = search_string.length(); size_t replace_len = replace_string.length(); size_t search_idx = 0; size_t match_idx; while ((match_idx = target.find(search_string, search_idx)) != string::npos) { target.replace(match_idx, match_len, replace_string); search_idx = match_idx + replace_len; } } std::string t_rs_generator::display_name() const { return "Rust"; } THRIFT_REGISTER_GENERATOR( rs, "Rust", "\n") // no Rust-generator-specific options thrift-0.19.0/compiler/cpp/src/thrift/generate/t_py_generator.cc0000644000000000000000000031422514452237057024724 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include "thrift/platform.h" #include "thrift/version.h" #include "thrift/generate/t_generator.h" using std::map; using std::ostream; using std::ostringstream; using std::string; using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes /** * Python code generator. * */ class t_py_generator : public t_generator { public: t_py_generator(t_program* program, const std::map& parsed_options, const std::string& option_string) : t_generator (program) { update_keywords_for_validation(); std::map::const_iterator iter; gen_newstyle_ = true; gen_utf8strings_ = true; gen_dynbase_ = false; gen_slots_ = false; gen_tornado_ = false; gen_zope_interface_ = false; gen_twisted_ = false; gen_dynamic_ = false; gen_enum_ = false; coding_ = ""; gen_dynbaseclass_ = ""; gen_dynbaseclass_exc_ = ""; gen_dynbaseclass_frozen_exc_ = ""; gen_dynbaseclass_frozen_ = ""; import_dynbase_ = ""; package_prefix_ = ""; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("enum") == 0) { gen_enum_ = true; } else if( iter->first.compare("new_style") == 0) { pwarning(0, "new_style is enabled by default, so the option will be removed in the near future.\n"); } else if( iter->first.compare("old_style") == 0) { gen_newstyle_ = false; pwarning(0, "old_style is deprecated and may be removed in the future.\n"); } else if( iter->first.compare("utf8strings") == 0) { pwarning(0, "utf8strings is enabled by default, so the option will be removed in the near future.\n"); } else if( iter->first.compare("no_utf8strings") == 0) { gen_utf8strings_ = false; } else if( iter->first.compare("slots") == 0) { gen_slots_ = true; } else if( iter->first.compare("package_prefix") == 0) { package_prefix_ = iter->second; } else if( iter->first.compare("dynamic") == 0) { gen_dynamic_ = true; gen_newstyle_ = false; // dynamic is newstyle if( gen_dynbaseclass_.empty()) { gen_dynbaseclass_ = "TBase"; } if( gen_dynbaseclass_frozen_.empty()) { gen_dynbaseclass_frozen_ = "TFrozenBase"; } if( gen_dynbaseclass_exc_.empty()) { gen_dynbaseclass_exc_ = "TExceptionBase"; } if( gen_dynbaseclass_frozen_exc_.empty()) { gen_dynbaseclass_frozen_exc_ = "TFrozenExceptionBase"; } if( import_dynbase_.empty()) { import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TFrozenExceptionBase, TTransport\n"; } } else if( iter->first.compare("dynbase") == 0) { gen_dynbase_ = true; gen_dynbaseclass_ = (iter->second); } else if( iter->first.compare("dynfrozen") == 0) { gen_dynbaseclass_frozen_ = (iter->second); } else if( iter->first.compare("dynexc") == 0) { gen_dynbaseclass_exc_ = (iter->second); } else if( iter->first.compare("dynfrozenexc") == 0) { gen_dynbaseclass_frozen_exc_ = (iter->second); } else if( iter->first.compare("dynimport") == 0) { gen_dynbase_ = true; import_dynbase_ = (iter->second); } else if( iter->first.compare("zope.interface") == 0) { gen_zope_interface_ = true; } else if( iter->first.compare("twisted") == 0) { gen_twisted_ = true; gen_zope_interface_ = true; } else if( iter->first.compare("tornado") == 0) { gen_tornado_ = true; } else if( iter->first.compare("coding") == 0) { coding_ = iter->second; } else { throw "unknown option py:" + iter->first; } } if (gen_twisted_ && gen_tornado_) { throw "at most one of 'twisted' and 'tornado' are allowed"; } copy_options_ = option_string; if (gen_twisted_) { out_dir_base_ = "gen-py.twisted"; } else if (gen_tornado_) { out_dir_base_ = "gen-py.tornado"; } else { out_dir_base_ = "gen-py"; } } std::string indent_str() const override { return " "; } /** * Init and close methods */ void init_generator() override; void close_generator() override; std::string display_name() const override; /** * Program-level generation functions */ void generate_typedef(t_typedef* ttypedef) override; void generate_enum(t_enum* tenum) override; void generate_const(t_const* tconst) override; void generate_struct(t_struct* tstruct) override; void generate_forward_declaration(t_struct* tstruct) override; void generate_xception(t_struct* txception) override; void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); /** * Struct generation code */ void generate_py_struct(t_struct* tstruct, bool is_exception); void generate_py_thrift_spec(std::ostream& out, t_struct* tstruct, bool is_exception); void generate_py_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception = false); void generate_py_struct_reader(std::ostream& out, t_struct* tstruct); void generate_py_struct_writer(std::ostream& out, t_struct* tstruct); void generate_py_struct_required_validator(std::ostream& out, t_struct* tstruct); void generate_py_function_helpers(t_function* tfunction); /** * Service-level generation functions */ void generate_service_helpers(t_service* tservice); void generate_service_interface(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_remote(t_service* tservice); void generate_service_server(t_service* tservice); void generate_process_function(t_service* tservice, t_function* tfunction); /** * Serialization constructs */ void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); void generate_deserialize_list_element(std::ostream& out, t_list* tlist, std::string prefix = ""); void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); void generate_serialize_map_element(std::ostream& out, t_map* tmap, std::string kiter, std::string viter); void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); void generate_python_docstring(std::ostream& out, t_struct* tstruct); void generate_python_docstring(std::ostream& out, t_function* tfunction); void generate_python_docstring(std::ostream& out, t_doc* tdoc, t_struct* tstruct, const char* subheader); void generate_python_docstring(std::ostream& out, t_doc* tdoc); /** * Helper rendering functions */ std::string py_autogen_comment(); std::string py_imports(); std::string render_includes(); std::string declare_argument(t_field* tfield); std::string render_field_default_value(t_field* tfield); std::string type_name(t_type* ttype); std::string function_signature(t_function* tfunction, bool interface = false); std::string argument_list(t_struct* tstruct, std::vector* pre = nullptr, std::vector* post = nullptr); std::string type_to_enum(t_type* ttype); std::string type_to_spec_args(t_type* ttype); static bool is_valid_namespace(const std::string& sub_namespace) { return sub_namespace == "twisted"; } static std::string get_real_py_module(const t_program* program, bool gen_twisted, std::string package_dir="") { if (gen_twisted) { std::string twisted_module = program->get_namespace("py.twisted"); if (!twisted_module.empty()) { return twisted_module; } } std::string real_module = program->get_namespace("py"); if (real_module.empty()) { return program->get_name(); } return package_dir + real_module; } static bool is_immutable(t_type* ttype) { std::map>::iterator it = ttype->annotations_.find("python.immutable"); if (it == ttype->annotations_.end()) { // Exceptions are immutable by default. return ttype->is_xception(); } else if (!it->second.empty() && it->second.back() == "false") { return false; } else { return true; } } private: /** * True if we should generate new-style classes. */ bool gen_newstyle_; bool gen_enum_; /** * True if we should generate dynamic style classes. */ bool gen_dynamic_; bool gen_dynbase_; std::string gen_dynbaseclass_; std::string gen_dynbaseclass_frozen_; std::string gen_dynbaseclass_exc_; std::string gen_dynbaseclass_frozen_exc_; std::string import_dynbase_; bool gen_slots_; std::string copy_options_; /** * True if we should generate code for use with zope.interface. */ bool gen_zope_interface_; /** * True if we should generate Twisted-friendly RPC services. */ bool gen_twisted_; /** * True if we should generate code for use with Tornado */ bool gen_tornado_; /** * True if strings should be encoded using utf-8. */ bool gen_utf8strings_; /** * specify generated file encoding * eg. # -*- coding: utf-8 -*- */ string coding_; string package_prefix_; /** * File streams */ ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_consts_; ofstream_with_content_based_conditional_update f_service_; std::string package_dir_; std::string module_; protected: std::set lang_keywords_for_validation() const override { std::string keywords[] = { "False", "None", "True", "and", "as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "print", "raise", "return", "try", "while", "with", "yield" }; return std::set(keywords, keywords + sizeof(keywords)/sizeof(keywords[0]) ); } }; /** * Prepares for file generation by opening up the necessary file output * streams. * * @param tprogram The program to generate */ void t_py_generator::init_generator() { // Make output directory string module = get_real_py_module(program_, gen_twisted_); package_dir_ = get_out_dir(); module_ = module; while (true) { // TODO: Do better error checking here. MKDIR(package_dir_.c_str()); std::ofstream init_py((package_dir_ + "/__init__.py").c_str(), std::ios_base::app); init_py.close(); if (module.empty()) { break; } string::size_type pos = module.find('.'); if (pos == string::npos) { package_dir_ += "/"; package_dir_ += module; module.clear(); } else { package_dir_ += "/"; package_dir_ += module.substr(0, pos); module.erase(0, pos + 1); } } // Make output file string f_types_name = package_dir_ + "/" + "ttypes.py"; f_types_.open(f_types_name.c_str()); string f_consts_name = package_dir_ + "/" + "constants.py"; f_consts_.open(f_consts_name.c_str()); string f_init_name = package_dir_ + "/__init__.py"; ofstream_with_content_based_conditional_update f_init; f_init.open(f_init_name.c_str()); f_init << "__all__ = ['ttypes', 'constants'"; vector services = program_->get_services(); vector::iterator sv_iter; for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) { f_init << ", '" << (*sv_iter)->get_name() << "'"; } f_init << "]" << endl; f_init.close(); // Print header f_types_ << py_autogen_comment() << endl << py_imports() << endl << render_includes() << endl << "from thrift.transport import TTransport" << endl << import_dynbase_; f_types_ << "all_structs = []" << endl; f_consts_ << py_autogen_comment() << endl << py_imports() << endl << "from .ttypes import *" << endl; } /** * Renders all the imports necessary for including another Thrift program */ string t_py_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; for (auto include : includes) { result += "import " + get_real_py_module(include, gen_twisted_, package_prefix_) + ".ttypes\n"; } return result; } /** * Autogen'd comment */ string t_py_generator::py_autogen_comment() { string coding; if (!coding_.empty()) { coding = "# -*- coding: " + coding_ + " -*-\n"; } return coding + std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n" + "# options string: " + copy_options_ + "\n" + "#\n"; } /** * Prints standard thrift imports */ string t_py_generator::py_imports() { ostringstream ss; ss << "from thrift.Thrift import TType, TMessageType, TFrozenDict, TException, " "TApplicationException" << endl << "from thrift.protocol.TProtocol import TProtocolException" << endl << "from thrift.TRecursive import fix_spec" << endl; if (gen_enum_) { ss << "from enum import IntEnum" << endl; } if (gen_utf8strings_) { ss << endl << "import sys"; } return ss.str(); } /** * Closes the type files */ void t_py_generator::close_generator() { // Fix thrift_spec definitions for recursive structs. f_types_ << "fix_spec(all_structs)" << endl; f_types_ << "del all_structs" << endl; // Close types file f_types_.close(); f_consts_.close(); } /** * Generates a typedef. This is not done in Python, types are all implicit. * * @param ttypedef The type definition */ void t_py_generator::generate_typedef(t_typedef* ttypedef) { (void)ttypedef; } /** * Generates code for an enumerated type. Done using a class to scope * the values. * * @param tenum The enumeration */ void t_py_generator::generate_enum(t_enum* tenum) { std::ostringstream to_string_mapping, from_string_mapping; std::string base_class; if (gen_enum_) { base_class = "IntEnum"; } else if (gen_newstyle_) { base_class = "object"; } else if (gen_dynamic_) { base_class = gen_dynbaseclass_; } f_types_ << endl << endl << "class " << tenum->get_name() << (base_class.empty() ? "" : "(" + base_class + ")") << ":" << endl; indent_up(); generate_python_docstring(f_types_, tenum); to_string_mapping << indent() << "_VALUES_TO_NAMES = {" << endl; from_string_mapping << indent() << "_NAMES_TO_VALUES = {" << endl; vector constants = tenum->get_constants(); vector::iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); indent(f_types_) << (*c_iter)->get_name() << " = " << value << endl; // Dictionaries to/from string names of enums to_string_mapping << indent() << indent() << value << ": \"" << escape_string((*c_iter)->get_name()) << "\"," << endl; from_string_mapping << indent() << indent() << '"' << escape_string((*c_iter)->get_name()) << "\": " << value << ',' << endl; } to_string_mapping << indent() << "}" << endl; from_string_mapping << indent() << "}" << endl; indent_down(); f_types_ << endl; if (!gen_enum_) { f_types_ << to_string_mapping.str() << endl << from_string_mapping.str(); } } /** * Generate a constant value */ void t_py_generator::generate_const(t_const* tconst) { t_type* type = tconst->get_type(); string name = tconst->get_name(); t_const_value* value = tconst->get_value(); indent(f_consts_) << name << " = " << render_const_value(type, value); f_consts_ << endl; } /** * Prints the value of a constant with the given type. Note that type checking * is NOT performed in this function as it is always run beforehand using the * validate_types method in main.cc */ string t_py_generator::render_const_value(t_type* type, t_const_value* value) { type = get_true_type(type); std::ostringstream out; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (((t_base_type*)type)->is_binary()) { out << 'b'; } out << '"' << get_escaped_string(value) << '"'; break; case t_base_type::TYPE_BOOL: out << (value->get_integer() > 0 ? "True" : "False"); break; case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: case t_base_type::TYPE_I64: out << value->get_integer(); break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << "float(" << value->get_integer() << ")"; } else { out << emit_double_as_string(value->get_double()); } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { out << indent(); int64_t int_val = value->get_integer(); if (gen_enum_) { t_enum_value* enum_val = ((t_enum*)type)->get_constant_by_value(int_val); out << type_name(type) << "." << enum_val->get_name(); } else { out << int_val; } } else if (type->is_struct() || type->is_xception()) { out << type_name(type) << "(**{" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } indent(out) << render_const_value(g_type_string, v_iter->first) << ": " << render_const_value(field_type, v_iter->second) << "," << endl; } indent_down(); indent(out) << "})"; } else if (type->is_map()) { t_type* ktype = ((t_map*)type)->get_key_type(); t_type* vtype = ((t_map*)type)->get_val_type(); if (is_immutable(type)) { out << "TFrozenDict("; } out << "{" << endl; indent_up(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { indent(out) << render_const_value(ktype, v_iter->first) << ": " << render_const_value(vtype, v_iter->second) << "," << endl; } indent_down(); indent(out) << "}"; if (is_immutable(type)) { out << ")"; } } else if (type->is_list() || type->is_set()) { t_type* etype; if (type->is_list()) { etype = ((t_list*)type)->get_elem_type(); } else { etype = ((t_set*)type)->get_elem_type(); } if (type->is_set()) { if (is_immutable(type)) { out << "frozen"; } out << "set("; } if (is_immutable(type) || type->is_set()) { out << "(" << endl; } else { out << "[" << endl; } indent_up(); const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { indent(out) << render_const_value(etype, *v_iter) << "," << endl; } indent_down(); if (is_immutable(type) || type->is_set()) { indent(out) << ")"; } else { indent(out) << "]"; } if (type->is_set()) { out << ")"; } } else { throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name(); } return out.str(); } /** * Generates the "forward declarations" for python structs. * These are actually full class definitions so that calls to generate_struct * can add the thrift_spec field. This is needed so that all thrift_spec * definitions are grouped at the end of the file to enable co-recursive structs. */ void t_py_generator::generate_forward_declaration(t_struct* tstruct) { generate_py_struct(tstruct, tstruct->is_xception()); } /** * Generates a python struct */ void t_py_generator::generate_struct(t_struct* tstruct) { generate_py_thrift_spec(f_types_, tstruct, false); } /** * Generates a struct definition for a thrift exception. Basically the same * as a struct but extends the Exception class. * * @param txception The struct definition */ void t_py_generator::generate_xception(t_struct* txception) { generate_py_thrift_spec(f_types_, txception, true); } /** * Generates a python struct */ void t_py_generator::generate_py_struct(t_struct* tstruct, bool is_exception) { generate_py_struct_definition(f_types_, tstruct, is_exception); } /** * Generate the thrift_spec for a struct * For example, * all_structs.append(Recursive) * Recursive.thrift_spec = ( * None, # 0 * (1, TType.LIST, 'Children', (TType.STRUCT, (Recursive, None), False), None, ), # 1 * ) */ void t_py_generator::generate_py_thrift_spec(ostream& out, t_struct* tstruct, bool /*is_exception*/) { const vector& sorted_members = tstruct->get_sorted_members(); vector::const_iterator m_iter; // Add struct definition to list so thrift_spec can be fixed for recursive structures. indent(out) << "all_structs.append(" << tstruct->get_name() << ")" << endl; if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) { indent(out) << tstruct->get_name() << ".thrift_spec = (" << endl; indent_up(); int sorted_keys_pos = 0; for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) { for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) { indent(out) << "None, # " << sorted_keys_pos << endl; } indent(out) << "(" << (*m_iter)->get_key() << ", " << type_to_enum((*m_iter)->get_type()) << ", " << "'" << (*m_iter)->get_name() << "'" << ", " << type_to_spec_args((*m_iter)->get_type()) << ", " << render_field_default_value(*m_iter) << ", " << ")," << " # " << sorted_keys_pos << endl; sorted_keys_pos++; } indent_down(); indent(out) << ")" << endl; } else { indent(out) << tstruct->get_name() << ".thrift_spec = ()" << endl; } } /** * Generates a struct definition for a thrift data type. * * @param tstruct The struct definition */ void t_py_generator::generate_py_struct_definition(ostream& out, t_struct* tstruct, bool is_exception) { const vector& members = tstruct->get_members(); const vector& sorted_members = tstruct->get_sorted_members(); vector::const_iterator m_iter; out << endl << endl << "class " << tstruct->get_name(); if (is_exception) { if (gen_dynamic_) { if (is_immutable(tstruct)) { out << "(" << gen_dynbaseclass_frozen_exc_ << ")"; } else { out << "(" << gen_dynbaseclass_exc_ << ")"; } } else { out << "(TException)"; } } else if (gen_dynamic_) { if (is_immutable(tstruct)) { out << "(" << gen_dynbaseclass_frozen_ << ")"; } else { out << "(" << gen_dynbaseclass_ << ")"; } } else if (gen_newstyle_) { out << "(object)"; } out << ":" << endl; indent_up(); generate_python_docstring(out, tstruct); out << endl; /* Here we generate the structure specification for the fastbinary codec. These specifications have the following structure: thrift_spec -> tuple of item_spec item_spec -> None | (tag, type_enum, name, spec_args, default) tag -> integer type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ... name -> string_literal default -> None # Handled by __init__ spec_args -> None # For simple types | (type_enum, spec_args) # Value type for list/set | (type_enum, spec_args, type_enum, spec_args) # Key and value for map | (class_name, spec_args_ptr) # For struct/exception class_name -> identifier # Basically a pointer to the class spec_args_ptr -> expression # just class_name.spec_args TODO(dreiss): Consider making this work for structs with negative tags. */ if (gen_slots_) { indent(out) << "__slots__ = (" << endl; indent_up(); for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) { indent(out) << "'" << (*m_iter)->get_name() << "'," << endl; } indent_down(); indent(out) << ")" << endl << endl; } // TODO(dreiss): Look into generating an empty tuple instead of None // for structures with no members. // TODO(dreiss): Test encoding of structs where some inner structs // don't have thrift_spec. if (members.size() > 0) { out << endl; out << indent() << "def __init__(self,"; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << " " << declare_argument(*m_iter) << ","; } out << "):" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { // Initialize fields t_type* type = (*m_iter)->get_type(); if (!type->is_base_type() && !type->is_enum() && (*m_iter)->get_value() != nullptr) { indent(out) << "if " << (*m_iter)->get_name() << " is " << "self.thrift_spec[" << (*m_iter)->get_key() << "][4]:" << endl; indent_up(); indent(out) << (*m_iter)->get_name() << " = " << render_field_default_value(*m_iter) << endl; indent_down(); } if (is_immutable(tstruct)) { if (gen_enum_ && type->is_enum()) { indent(out) << "super(" << tstruct->get_name() << ", self).__setattr__('" << (*m_iter)->get_name() << "', " << (*m_iter)->get_name() << " if hasattr(" << (*m_iter)->get_name() << ", 'value') else " << type_name(type) << ".__members__.get(" << (*m_iter)->get_name() << "))" << endl; } else if (gen_newstyle_ || gen_dynamic_) { indent(out) << "super(" << tstruct->get_name() << ", self).__setattr__('" << (*m_iter)->get_name() << "', " << (*m_iter)->get_name() << ")" << endl; } else { indent(out) << "self.__dict__['" << (*m_iter)->get_name() << "'] = " << (*m_iter)->get_name() << endl; } } else { indent(out) << "self." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << endl; } } indent_down(); } if (is_immutable(tstruct)) { out << endl; out << indent() << "def __setattr__(self, *args):" << endl; indent_up(); // Not user-provided fields should be editable so that the Python Standard Library can edit // internal fields of std library base classes. For example, in Python 3.11 ContextManager // edits the `__traceback__` field on Exceptions. Allowing this to work with `__slots__` is // trivial because we know which fields are user-provided, without slots we need to build a // way to know which fields are user-provided. if (gen_slots_ && !gen_dynamic_) { out << indent() << "if args[0] not in self.__slots__:" << endl; indent_up(); out << indent() << "super().__setattr__(*args)" << endl << indent() << "return" << endl; indent_down(); } out << indent() << "raise TypeError(\"can't modify immutable instance\")" << endl; indent_down(); out << endl; out << indent() << "def __delattr__(self, *args):" << endl; indent_up(); // Not user-provided fields should be editable so that the Python Standard Library can edit // internal fields of std library base classes. For example, in Python 3.11 ContextManager // edits the `__traceback__` field on Exceptions. Allowing this to work with `__slots__` is // trivial because we know which fields are user-provided, without slots we need to build a // way to know which fields are user-provided. if (gen_slots_ && !gen_dynamic_) { out << indent() << "if args[0] not in self.__slots__:" << endl; indent_up(); out << indent() << "super().__delattr__(*args)" << endl << indent() << "return" << endl; indent_down(); } out << indent() << "raise TypeError(\"can't modify immutable instance\")" << endl; indent_down(); out << endl; // Hash all of the members in order, and also hash in the class // to avoid collisions for stuff like single-field structures. out << indent() << "def __hash__(self):" << endl << indent() << indent_str() << "return hash(self.__class__) ^ hash(("; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { out << "self." << (*m_iter)->get_name() << ", "; } out << "))" << endl; } else if (gen_enum_) { bool has_enum = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* type = (*m_iter)->get_type(); if (type->is_enum()) { has_enum = true; break; } } if (has_enum) { out << endl; indent(out) << "def __setattr__(self, name, value):" << endl; indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* type = (*m_iter)->get_type(); if (type->is_enum()) { out << indent() << "if name == \"" << (*m_iter)->get_name() << "\":" << endl << indent() << indent_str() << "super().__setattr__(name, value if hasattr(value, 'value') else " << type_name(type) << ".__members__.get(value))" << endl << indent() << indent_str() << "return" << endl; } } indent(out) << "super().__setattr__(name, value)" << endl << endl; indent_down(); } } if (!gen_dynamic_) { out << endl; generate_py_struct_reader(out, tstruct); generate_py_struct_writer(out, tstruct); } // For exceptions only, generate a __str__ method. This is // because when raised exceptions are printed to the console, __repr__ // isn't used. See python bug #5882 if (is_exception) { out << endl; out << indent() << "def __str__(self):" << endl << indent() << indent_str() << "return repr(self)" << endl; } if (!gen_slots_) { out << endl; // Printing utilities so that on the command line thrift // structs look pretty like dictionaries indent(out) << "def __repr__(self):" << endl; indent_up(); out << indent() << "L = ['%s=%r' % (key, value)" << endl << indent() << " for key, value in self.__dict__.items()]" << endl << indent() << "return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl << endl; indent_down(); // Equality and inequality methods that compare by value out << indent() << "def __eq__(self, other):" << endl; indent_up(); out << indent() << "return isinstance(other, self.__class__) and " "self.__dict__ == other.__dict__" << endl; indent_down(); out << endl; out << indent() << "def __ne__(self, other):" << endl; indent_up(); out << indent() << "return not (self == other)" << endl; indent_down(); } else if (!gen_dynamic_) { out << endl; // no base class available to implement __eq__ and __repr__ and __ne__ for us // so we must provide one that uses __slots__ indent(out) << "def __repr__(self):" << endl; indent_up(); out << indent() << "L = ['%s=%r' % (key, getattr(self, key))" << endl << indent() << " for key in self.__slots__]" << endl << indent() << "return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl << endl; indent_down(); // Equality method that compares each attribute by value and type, walking __slots__ out << indent() << "def __eq__(self, other):" << endl; indent_up(); out << indent() << "if not isinstance(other, self.__class__):" << endl << indent() << indent_str() << "return False" << endl << indent() << "for attr in self.__slots__:" << endl << indent() << indent_str() << "my_val = getattr(self, attr)" << endl << indent() << indent_str() << "other_val = getattr(other, attr)" << endl << indent() << indent_str() << "if my_val != other_val:" << endl << indent() << indent_str() << indent_str() << "return False" << endl << indent() << "return True" << endl << endl; indent_down(); out << indent() << "def __ne__(self, other):" << endl << indent() << indent_str() << "return not (self == other)" << endl; } indent_down(); } /** * Generates the read method for a struct */ void t_py_generator::generate_py_struct_reader(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; if (is_immutable(tstruct)) { out << indent() << "@classmethod" << endl << indent() << "def read(cls, iprot):" << endl; } else { indent(out) << "def read(self, iprot):" << endl; } indent_up(); const char* id = is_immutable(tstruct) ? "cls" : "self"; indent(out) << "if iprot._fast_decode is not None " "and isinstance(iprot.trans, TTransport.CReadableTransport) " "and " << id << ".thrift_spec is not None:" << endl; indent_up(); if (is_immutable(tstruct)) { indent(out) << "return iprot._fast_decode(None, iprot, [cls, cls.thrift_spec])" << endl; } else { indent(out) << "iprot._fast_decode(self, iprot, [self.__class__, self.thrift_spec])" << endl; indent(out) << "return" << endl; } indent_down(); indent(out) << "iprot.readStructBegin()" << endl; if (is_immutable(tstruct)) { for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* tfield = *f_iter; std::ostringstream result; result << tfield->get_name() << " = "; if (tfield->get_value() != nullptr) { result << render_field_default_value(tfield); } else { result << "None"; } indent(out) << result.str() << endl; } } // Loop over reading in fields indent(out) << "while True:" << endl; indent_up(); // Read beginning field marker indent(out) << "(fname, ftype, fid) = iprot.readFieldBegin()" << endl; // Check for field STOP marker and break indent(out) << "if ftype == TType.STOP:" << endl; indent_up(); indent(out) << "break" << endl; indent_down(); // Switch statement on the field we are reading bool first = true; // Generate deserialization code for known cases for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; out << indent() << "if "; } else { out << indent() << "elif "; } out << "fid == " << (*f_iter)->get_key() << ":" << endl; indent_up(); indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << ":" << endl; indent_up(); if (is_immutable(tstruct)) { generate_deserialize_field(out, *f_iter); } else { generate_deserialize_field(out, *f_iter, "self."); } indent_down(); out << indent() << "else:" << endl << indent() << indent_str() << "iprot.skip(ftype)" << endl; indent_down(); } // In the default case we skip the field out << indent() << "else:" << endl << indent() << indent_str() << "iprot.skip(ftype)" << endl; // Read field end marker indent(out) << "iprot.readFieldEnd()" << endl; indent_down(); indent(out) << "iprot.readStructEnd()" << endl; if (is_immutable(tstruct)) { indent(out) << "return cls(" << endl; indent_up(); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { indent(out) << (*f_iter)->get_name() << "=" << (*f_iter)->get_name() << "," << endl; } indent_down(); indent(out) << ")" << endl; } indent_down(); out << endl; } void t_py_generator::generate_py_struct_writer(ostream& out, t_struct* tstruct) { string name = tstruct->get_name(); const vector& fields = tstruct->get_sorted_members(); vector::const_iterator f_iter; indent(out) << "def write(self, oprot):" << endl; indent_up(); indent(out) << "if oprot._fast_encode is not None and self.thrift_spec is not None:" << endl; indent_up(); indent(out) << "oprot.trans.write(oprot._fast_encode(self, [self.__class__, self.thrift_spec]))" << endl; indent(out) << "return" << endl; indent_down(); indent(out) << "oprot.writeStructBegin('" << name << "')" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { // Write field header indent(out) << "if self." << (*f_iter)->get_name() << " is not None:" << endl; indent_up(); indent(out) << "oprot.writeFieldBegin(" << "'" << (*f_iter)->get_name() << "', " << type_to_enum((*f_iter)->get_type()) << ", " << (*f_iter)->get_key() << ")" << endl; // Write field contents generate_serialize_field(out, *f_iter, "self."); // Write field closer indent(out) << "oprot.writeFieldEnd()" << endl; indent_down(); } // Write the struct map out << indent() << "oprot.writeFieldStop()" << endl << indent() << "oprot.writeStructEnd()" << endl; out << endl; indent_down(); generate_py_struct_required_validator(out, tstruct); } void t_py_generator::generate_py_struct_required_validator(ostream& out, t_struct* tstruct) { indent(out) << "def validate(self):" << endl; indent_up(); const vector& fields = tstruct->get_members(); if (fields.size() > 0) { vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_field* field = (*f_iter); if (field->get_req() == t_field::T_REQUIRED) { indent(out) << "if self." << field->get_name() << " is None:" << endl; indent(out) << indent_str() << "raise TProtocolException(message='Required field " << field->get_name() << " is unset!')" << endl; } } } indent(out) << "return" << endl; indent_down(); } /** * Generates a thrift service. * * @param tservice The service definition */ void t_py_generator::generate_service(t_service* tservice) { string f_service_name = package_dir_ + "/" + service_name_ + ".py"; f_service_.open(f_service_name.c_str()); f_service_ << py_autogen_comment() << endl << py_imports() << endl; if (tservice->get_extends() != nullptr) { f_service_ << "import " << get_real_py_module(tservice->get_extends()->get_program(), gen_twisted_, package_prefix_) << "." << tservice->get_extends()->get_name() << endl; } f_service_ << "import logging" << endl << "from .ttypes import *" << endl << "from thrift.Thrift import TProcessor" << endl << "from thrift.transport import TTransport" << endl << import_dynbase_; if (gen_zope_interface_) { f_service_ << "from zope.interface import Interface, implementer" << endl; } if (gen_twisted_) { f_service_ << "from twisted.internet import defer" << endl << "from thrift.transport import TTwisted" << endl; } else if (gen_tornado_) { f_service_ << "from tornado import gen" << endl; f_service_ << "from tornado import concurrent" << endl; } f_service_ << "all_structs = []" << endl; // Generate the three main parts of the service generate_service_interface(tservice); generate_service_client(tservice); generate_service_server(tservice); generate_service_helpers(tservice); generate_service_remote(tservice); // Close service file f_service_ << "fix_spec(all_structs)" << endl << "del all_structs" << endl; f_service_.close(); } /** * Generates helper functions for a service. * * @param tservice The service to generate a header definition for */ void t_py_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; f_service_ << endl << "# HELPER FUNCTIONS AND STRUCTURES" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); generate_py_struct_definition(f_service_, ts, false); generate_py_thrift_spec(f_service_, ts, false); generate_py_function_helpers(*f_iter); } } /** * Generates a struct and helpers for a function. * * @param tfunction The function */ void t_py_generator::generate_py_function_helpers(t_function* tfunction) { if (!tfunction->is_oneway()) { t_struct result(program_, tfunction->get_name() + "_result"); t_field success(tfunction->get_returntype(), "success", 0); if (!tfunction->get_returntype()->is_void()) { result.append(&success); } t_struct* xs = tfunction->get_xceptions(); const vector& fields = xs->get_members(); vector::const_iterator f_iter; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { result.append(*f_iter); } generate_py_struct_definition(f_service_, &result, false); generate_py_thrift_spec(f_service_, &result, false); } } /** * Generates a service interface definition. * * @param tservice The service to generate a header definition for */ void t_py_generator::generate_service_interface(t_service* tservice) { string extends = ""; string extends_if = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_if = "(" + extends + ".Iface)"; } else { if (gen_zope_interface_) { extends_if = "(Interface)"; } else if (gen_newstyle_ || gen_dynamic_ || gen_tornado_) { extends_if = "(object)"; } } f_service_ << endl << endl << "class Iface" << extends_if << ":" << endl; indent_up(); generate_python_docstring(f_service_, tservice); vector functions = tservice->get_functions(); if (functions.empty()) { f_service_ << indent() << "pass" << endl; } else { vector::iterator f_iter; bool first = true; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << endl; } f_service_ << indent() << "def " << function_signature(*f_iter, true) << ":" << endl; indent_up(); generate_python_docstring(f_service_, (*f_iter)); f_service_ << indent() << "pass" << endl; indent_down(); } } indent_down(); } /** * Generates a service client definition. * * @param tservice The service to generate a server for. */ void t_py_generator::generate_service_client(t_service* tservice) { string extends = ""; string extends_client = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); if (gen_zope_interface_) { extends_client = "(" + extends + ".Client)"; } else { extends_client = extends + ".Client, "; } } else { if (gen_zope_interface_ && (gen_newstyle_ || gen_dynamic_)) { extends_client = "(object)"; } } f_service_ << endl << endl; if (gen_zope_interface_) { f_service_ << "@implementer(Iface)" << endl << "class Client" << extends_client << ":" << endl << endl; } else { f_service_ << "class Client(" << extends_client << "Iface):" << endl; } indent_up(); generate_python_docstring(f_service_, tservice); // Constructor function if (gen_twisted_) { f_service_ << indent() << "def __init__(self, transport, oprot_factory):" << endl; } else if (gen_tornado_) { f_service_ << indent() << "def __init__(self, transport, iprot_factory, oprot_factory=None):" << endl; } else { f_service_ << indent() << "def __init__(self, iprot, oprot=None):" << endl; } indent_up(); if (extends.empty()) { if (gen_twisted_) { f_service_ << indent() << "self._transport = transport" << endl << indent() << "self._oprot_factory = oprot_factory" << endl << indent() << "self._seqid = 0" << endl << indent() << "self._reqs = {}" << endl; } else if (gen_tornado_) { f_service_ << indent() << "self._transport = transport" << endl << indent() << "self._iprot_factory = iprot_factory" << endl << indent() << "self._oprot_factory = (oprot_factory if oprot_factory is not None" << endl << indent() << " else iprot_factory)" << endl << indent() << "self._seqid = 0" << endl << indent() << "self._reqs = {}" << endl << indent() << "self._transport.io_loop.spawn_callback(self._start_receiving)" << endl; } else { f_service_ << indent() << "self._iprot = self._oprot = iprot" << endl << indent() << "if oprot is not None:" << endl << indent() << indent_str() << "self._oprot = oprot" << endl << indent() << "self._seqid = 0" << endl; } } else { if (gen_twisted_) { f_service_ << indent() << extends << ".Client.__init__(self, transport, oprot_factory)" << endl; } else if (gen_tornado_) { f_service_ << indent() << extends << ".Client.__init__(self, transport, iprot_factory, oprot_factory)" << endl; } else { f_service_ << indent() << extends << ".Client.__init__(self, iprot, oprot)" << endl; } } indent_down(); if (gen_tornado_ && extends.empty()) { f_service_ << endl << indent() << "@gen.engine" << endl << indent() << "def _start_receiving(self):" << endl; indent_up(); indent(f_service_) << "while True:" << endl; indent_up(); f_service_ << indent() << "try:" << endl << indent() << indent_str() << "frame = yield self._transport.readFrame()" << endl << indent() << "except TTransport.TTransportException as e:" << endl << indent() << indent_str() << "for future in self._reqs.values():" << endl << indent() << indent_str() << indent_str() << "future.set_exception(e)" << endl << indent() << indent_str() << "self._reqs = {}" << endl << indent() << indent_str() << "return" << endl << indent() << "tr = TTransport.TMemoryBuffer(frame)" << endl << indent() << "iprot = self._iprot_factory.getProtocol(tr)" << endl << indent() << "(fname, mtype, rseqid) = iprot.readMessageBegin()" << endl << indent() << "method = getattr(self, 'recv_' + fname)" << endl << indent() << "future = self._reqs.pop(rseqid, None)" << endl << indent() << "if not future:" << endl << indent() << indent_str() << "# future has already been discarded" << endl << indent() << indent_str() << "continue" << endl << indent() << "try:" << endl << indent() << indent_str() << "result = method(iprot, mtype, rseqid)" << endl << indent() << "except Exception as e:" << endl << indent() << indent_str() << "future.set_exception(e)" << endl << indent() << "else:" << endl << indent() << indent_str() << "future.set_result(result)" << endl; indent_down(); indent_down(); } // Generate client method implementations vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; string funname = (*f_iter)->get_name(); f_service_ << endl; // Open function indent(f_service_) << "def " << function_signature(*f_iter, false) << ":" << endl; indent_up(); generate_python_docstring(f_service_, (*f_iter)); if (gen_twisted_) { indent(f_service_) << "seqid = self._seqid = self._seqid + 1" << endl; indent(f_service_) << "self._reqs[seqid] = defer.Deferred()" << endl << endl; indent(f_service_) << "d = defer.maybeDeferred(self.send_" << funname; } else if (gen_tornado_) { indent(f_service_) << "self._seqid += 1" << endl; if (!(*f_iter)->is_oneway()) { indent(f_service_) << "future = self._reqs[self._seqid] = concurrent.Future()" << endl; } indent(f_service_) << "self.send_" << funname << "("; } else { indent(f_service_) << "self.send_" << funname << "("; } bool first = true; if (gen_twisted_) { // we need a leading comma if there are args, since it's called as maybeDeferred(funcname, // arg) first = false; } for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << (*fld_iter)->get_name(); } f_service_ << ")" << endl; if (!(*f_iter)->is_oneway()) { if (gen_twisted_) { // nothing. See the next block. } else if (gen_tornado_) { indent(f_service_) << "return future" << endl; } else { f_service_ << indent(); if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << "return "; } f_service_ << "self.recv_" << funname << "()" << endl; } } indent_down(); if (gen_twisted_) { // This block injects the body of the send_<> method for twisted (and a cb/eb pair) indent_up(); indent(f_service_) << "d.addCallbacks(" << endl; indent_up(); f_service_ << indent() << "callback=self.cb_send_" << funname << "," << endl << indent() << "callbackArgs=(seqid,)," << endl << indent() << "errback=self.eb_send_" << funname << "," << endl << indent() << "errbackArgs=(seqid,))" << endl; indent_down(); indent(f_service_) << "return d" << endl; indent_down(); f_service_ << endl; indent(f_service_) << "def cb_send_" << funname << "(self, _, seqid):" << endl; indent_up(); if ((*f_iter)->is_oneway()) { // if one-way, fire the deferred & remove it from _reqs f_service_ << indent() << "d = self._reqs.pop(seqid)" << endl << indent() << "d.callback(None)" << endl << indent() << "return d" << endl; } else { f_service_ << indent() << "return self._reqs[seqid]" << endl; } indent_down(); f_service_ << endl; // add an errback to fail the request if the call to send_<> raised an exception indent(f_service_) << "def eb_send_" << funname << "(self, f, seqid):" << endl; indent_up(); f_service_ << indent() << "d = self._reqs.pop(seqid)" << endl << indent() << "d.errback(f)" << endl << indent() << "return d" << endl; indent_down(); } f_service_ << endl; indent(f_service_) << "def send_" << function_signature(*f_iter, false) << ":" << endl; indent_up(); std::string argsname = (*f_iter)->get_name() + "_args"; std::string messageType = (*f_iter)->is_oneway() ? "TMessageType.ONEWAY" : "TMessageType.CALL"; // Serialize the request header if (gen_twisted_ || gen_tornado_) { f_service_ << indent() << "oprot = self._oprot_factory.getProtocol(self._transport)" << endl << indent() << "oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', " << messageType << ", self._seqid)" << endl; } else { f_service_ << indent() << "self._oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', " << messageType << ", self._seqid)" << endl; } f_service_ << indent() << "args = " << argsname << "()" << endl; for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { f_service_ << indent() << "args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << endl; } // Write to the stream if (gen_twisted_ || gen_tornado_) { f_service_ << indent() << "args.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()" << endl << indent() << "oprot.trans.flush()" << endl; } else { f_service_ << indent() << "args.write(self._oprot)" << endl << indent() << "self._oprot.writeMessageEnd()" << endl << indent() << "self._oprot.trans.flush()" << endl; } indent_down(); if (!(*f_iter)->is_oneway()) { std::string resultname = (*f_iter)->get_name() + "_result"; // Open function f_service_ << endl; if (gen_twisted_ || gen_tornado_) { f_service_ << indent() << "def recv_" << (*f_iter)->get_name() << "(self, iprot, mtype, rseqid):" << endl; } else { t_struct noargs(program_); t_function recv_function((*f_iter)->get_returntype(), string("recv_") + (*f_iter)->get_name(), &noargs); f_service_ << indent() << "def " << function_signature(&recv_function) << ":" << endl; } indent_up(); // TODO(mcslee): Validate message reply here, seq ids etc. if (gen_twisted_) { f_service_ << indent() << "d = self._reqs.pop(rseqid)" << endl; } else if (gen_tornado_) { } else { f_service_ << indent() << "iprot = self._iprot" << endl << indent() << "(fname, mtype, rseqid) = iprot.readMessageBegin()" << endl; } f_service_ << indent() << "if mtype == TMessageType.EXCEPTION:" << endl << indent() << indent_str() << "x = TApplicationException()" << endl; if (gen_twisted_) { f_service_ << indent() << indent_str() << "x.read(iprot)" << endl << indent() << indent_str() << "iprot.readMessageEnd()" << endl << indent() << indent_str() << "return d.errback(x)" << endl << indent() << "result = " << resultname << "()" << endl << indent() << "result.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl; } else { f_service_ << indent() << indent_str() << "x.read(iprot)" << endl << indent() << indent_str() << "iprot.readMessageEnd()" << endl << indent() << indent_str() << "raise x" << endl << indent() << "result = " << resultname << "()" << endl << indent() << "result.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl; } // Careful, only return _result if not a void function if (!(*f_iter)->get_returntype()->is_void()) { f_service_ << indent() << "if result.success is not None:" << endl; if (gen_twisted_) { f_service_ << indent() << indent_str() << "return d.callback(result.success)" << endl; } else { f_service_ << indent() << indent_str() << "return result.success" << endl; } } t_struct* xs = (*f_iter)->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { const string& xname = (*x_iter)->get_name(); f_service_ << indent() << "if result." << xname << " is not None:" << endl; if (gen_twisted_) { f_service_ << indent() << indent_str() << "return d.errback(result." << xname << ")" << endl; } else { f_service_ << indent() << indent_str() << "raise result." << xname << "" << endl; } } // Careful, only return _result if not a void function if ((*f_iter)->get_returntype()->is_void()) { if (gen_twisted_) { f_service_ << indent() << "return d.callback(None)" << endl; } else { f_service_ << indent() << "return" << endl; } } else { if (gen_twisted_) { f_service_ << indent() << "return d.errback(TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\"))" << endl; } else { f_service_ << indent() << "raise TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\")" << endl; } } // Close function indent_down(); } } indent_down(); } /** * Generates a command line tool for making remote requests * * @param tservice The service to generate a remote for. */ void t_py_generator::generate_service_remote(t_service* tservice) { vector functions = tservice->get_functions(); // Get all function from parents t_service* parent = tservice->get_extends(); while (parent != nullptr) { vector p_functions = parent->get_functions(); functions.insert(functions.end(), p_functions.begin(), p_functions.end()); parent = parent->get_extends(); } vector::iterator f_iter; string f_remote_name = package_dir_ + "/" + service_name_ + "-remote"; ofstream_with_content_based_conditional_update f_remote; f_remote.open(f_remote_name.c_str()); f_remote << "#!/usr/bin/env python" << endl << py_autogen_comment() << endl << "import sys" << endl << "import pprint" << endl << "if sys.version_info[0] > 2:" << endl << indent_str() << "from urllib.parse import urlparse" << endl << "else:" << endl << indent_str() << "from urlparse import urlparse" << endl << "from thrift.transport import TTransport, TSocket, TSSLSocket, THttpClient" << endl << "from thrift.protocol.TBinaryProtocol import TBinaryProtocol" << endl << endl; f_remote << "from " << module_ << " import " << service_name_ << endl << "from " << module_ << ".ttypes import *" << endl << endl; f_remote << "if len(sys.argv) <= 1 or sys.argv[1] == '--help':" << endl << indent_str() << "print('')" << endl << indent_str() << "print('Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] [-s[sl]] [-novalidate] [-ca_certs certs] [-keyfile keyfile] [-certfile certfile] function [arg1 [arg2...]]')" << endl << indent_str() << "print('')" << endl << indent_str() << "print('Functions:')" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_remote << indent_str() << "print(' " << (*f_iter)->get_returntype()->get_name() << " " << (*f_iter)->get_name() << "("; t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); std::vector::size_type num_args = args.size(); bool first = true; for (std::vector::size_type i = 0; i < num_args; ++i) { if (first) { first = false; } else { f_remote << ", "; } f_remote << args[i]->get_type()->get_name() << " " << args[i]->get_name(); } f_remote << ")')" << endl; } f_remote << indent_str() << "print('')" << endl << indent_str() << "sys.exit(0)" << endl << endl; f_remote << "pp = pprint.PrettyPrinter(indent=2)" << endl << "host = 'localhost'" << endl << "port = 9090" << endl << "uri = ''" << endl << "framed = False" << endl << "ssl = False" << endl << "validate = True" << endl << "ca_certs = None" << endl << "keyfile = None" << endl << "certfile = None" << endl << "http = False" << endl << "argi = 1" << endl << endl << "if sys.argv[argi] == '-h':" << endl << indent_str() << "parts = sys.argv[argi + 1].split(':')" << endl << indent_str() << "host = parts[0]" << endl << indent_str() << "if len(parts) > 1:" << endl << indent_str() << indent_str() << "port = int(parts[1])" << endl << indent_str() << "argi += 2" << endl << endl << "if sys.argv[argi] == '-u':" << endl << indent_str() << "url = urlparse(sys.argv[argi + 1])" << endl << indent_str() << "parts = url[1].split(':')" << endl << indent_str() << "host = parts[0]" << endl << indent_str() << "if len(parts) > 1:" << endl << indent_str() << indent_str() << "port = int(parts[1])" << endl << indent_str() << "else:" << endl << indent_str() << indent_str() << "port = 80" << endl << indent_str() << "uri = url[2]" << endl << indent_str() << "if url[4]:" << endl << indent_str() << indent_str() << "uri += '?%s' % url[4]" << endl << indent_str() << "http = True" << endl << indent_str() << "argi += 2" << endl << endl << "if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':" << endl << indent_str() << "framed = True" << endl << indent_str() << "argi += 1" << endl << endl << "if sys.argv[argi] == '-s' or sys.argv[argi] == '-ssl':" << endl << indent_str() << "ssl = True" << endl << indent_str() << "argi += 1" << endl << endl << "if sys.argv[argi] == '-novalidate':" << endl << indent_str() << "validate = False" << endl << indent_str() << "argi += 1" << endl << endl << "if sys.argv[argi] == '-ca_certs':" << endl << indent_str() << "ca_certs = sys.argv[argi+1]" << endl << indent_str() << "argi += 2" << endl << endl << "if sys.argv[argi] == '-keyfile':" << endl << indent_str() << "keyfile = sys.argv[argi+1]" << endl << indent_str() << "argi += 2" << endl << endl << "if sys.argv[argi] == '-certfile':" << endl << indent_str() << "certfile = sys.argv[argi+1]" << endl << indent_str() << "argi += 2" << endl << endl << "cmd = sys.argv[argi]" << endl << "args = sys.argv[argi + 1:]" << endl << endl << "if http:" << endl << indent_str() << "transport = THttpClient.THttpClient(host, port, uri)" << endl << "else:" << endl << indent_str() << "if ssl:" << endl << indent_str() << indent_str() << "socket = TSSLSocket.TSSLSocket(host, port, " "validate=validate, ca_certs=ca_certs, keyfile=keyfile, certfile=certfile)" << endl << indent_str() << "else:" << endl << indent_str() << indent_str() << "socket = TSocket.TSocket(host, port)" << endl << indent_str() << "if framed:" << endl << indent_str() << indent_str() << "transport = TTransport.TFramedTransport(socket)" << endl << indent_str() << "else:" << endl << indent_str() << indent_str() << "transport = TTransport.TBufferedTransport(socket)" << endl << "protocol = TBinaryProtocol(transport)" << endl << "client = " << service_name_ << ".Client(protocol)" << endl << "transport.open()" << endl << endl; // Generate the dispatch methods bool first = true; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { if (first) { first = false; } else { f_remote << "el"; } t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); std::vector::size_type num_args = args.size(); f_remote << "if cmd == '" << (*f_iter)->get_name() << "':" << endl; indent_up(); f_remote << indent() << "if len(args) != " << num_args << ":" << endl << indent() << indent_str() << "print('" << (*f_iter)->get_name() << " requires " << num_args << " args')" << endl << indent() << indent_str() << "sys.exit(1)" << endl << indent() << "pp.pprint(client." << (*f_iter)->get_name() << "("; indent_down(); bool first_arg = true; for (std::vector::size_type i = 0; i < num_args; ++i) { if (first_arg) first_arg = false; else f_remote << " "; if (args[i]->get_type()->is_string()) { f_remote << "args[" << i << "],"; } else { f_remote << "eval(args[" << i << "]),"; } } f_remote << "))" << endl; f_remote << endl; } if (functions.size() > 0) { f_remote << "else:" << endl; f_remote << indent_str() << "print('Unrecognized method %s' % cmd)" << endl; f_remote << indent_str() << "sys.exit(1)" << endl; f_remote << endl; } f_remote << "transport.close()" << endl; // Close service file f_remote.close(); #ifndef _MSC_VER // Make file executable, love that bitwise OR action chmod(f_remote_name.c_str(), S_IRUSR | S_IWUSR | S_IXUSR #ifndef _WIN32 | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH #endif ); #endif // _MSC_VER } /** * Generates a service server definition. * * @param tservice The service to generate a server for. */ void t_py_generator::generate_service_server(t_service* tservice) { // Generate the dispatch methods vector functions = tservice->get_functions(); vector::iterator f_iter; string extends = ""; string extends_processor = ""; if (tservice->get_extends() != nullptr) { extends = type_name(tservice->get_extends()); extends_processor = extends + ".Processor, "; } f_service_ << endl << endl; // Generate the header portion if (gen_zope_interface_) { f_service_ << "@implementer(Iface)" << endl << "class Processor(" << extends_processor << "TProcessor):" << endl; } else { f_service_ << "class Processor(" << extends_processor << "Iface, TProcessor):" << endl; } indent_up(); indent(f_service_) << "def __init__(self, handler):" << endl; indent_up(); if (extends.empty()) { if (gen_zope_interface_) { f_service_ << indent() << "self._handler = Iface(handler)" << endl; } else { f_service_ << indent() << "self._handler = handler" << endl; } f_service_ << indent() << "self._processMap = {}" << endl; } else { if (gen_zope_interface_) { f_service_ << indent() << extends << ".Processor.__init__(self, Iface(handler))" << endl; } else { f_service_ << indent() << extends << ".Processor.__init__(self, handler)" << endl; } } for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << indent() << "self._processMap[\"" << (*f_iter)->get_name() << "\"] = Processor.process_" << (*f_iter)->get_name() << endl; } f_service_ << indent() << "self._on_message_begin = None" << endl; indent_down(); f_service_ << endl; f_service_ << indent() << "def on_message_begin(self, func):" << endl; indent_up(); f_service_ << indent() << "self._on_message_begin = func" << endl; indent_down(); f_service_ << endl; // Generate the server implementation f_service_ << indent() << "def process(self, iprot, oprot):" << endl; indent_up(); f_service_ << indent() << "(name, type, seqid) = iprot.readMessageBegin()" << endl; f_service_ << indent() << "if self._on_message_begin:" << endl; indent_up(); f_service_ << indent() << "self._on_message_begin(name, type, seqid)" << endl; indent_down(); // TODO(mcslee): validate message // HOT: dictionary function lookup f_service_ << indent() << "if name not in self._processMap:" << endl; indent_up(); f_service_ << indent() << "iprot.skip(TType.STRUCT)" << endl << indent() << "iprot.readMessageEnd()" << endl << indent() << "x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown " "function %s' % (name))" << endl << indent() << "oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)" << endl << indent() << "x.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()" << endl << indent() << "oprot.trans.flush()" << endl; if (gen_twisted_) { f_service_ << indent() << "return defer.succeed(None)" << endl; } else { f_service_ << indent() << "return" << endl; } indent_down(); f_service_ << indent() << "else:" << endl; if (gen_twisted_ || gen_tornado_) { f_service_ << indent() << indent_str() << "return self._processMap[name](self, seqid, iprot, oprot)" << endl; } else { f_service_ << indent() << indent_str() << "self._processMap[name](self, seqid, iprot, oprot)" << endl; // Read end of args field, the T_STOP, and the struct close f_service_ << indent() << "return True" << endl; } indent_down(); // Generate the process subfunctions for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_service_ << endl; generate_process_function(tservice, *f_iter); } indent_down(); } /** * Generates a process function definition. * * @param tfunction The function to write a dispatcher for */ void t_py_generator::generate_process_function(t_service* tservice, t_function* tfunction) { (void)tservice; // Open function if (gen_tornado_) { f_service_ << indent() << "@gen.coroutine" << endl << indent() << "def process_" << tfunction->get_name() << "(self, seqid, iprot, oprot):" << endl; } else { f_service_ << indent() << "def process_" << tfunction->get_name() << "(self, seqid, iprot, oprot):" << endl; } indent_up(); string argsname = tfunction->get_name() + "_args"; string resultname = tfunction->get_name() + "_result"; f_service_ << indent() << "args = " << argsname << "()" << endl << indent() << "args.read(iprot)" << endl << indent() << "iprot.readMessageEnd()" << endl; t_struct* xs = tfunction->get_xceptions(); const std::vector& xceptions = xs->get_members(); vector::const_iterator x_iter; // Declare result for non oneway function if (!tfunction->is_oneway()) { f_service_ << indent() << "result = " << resultname << "()" << endl; } if (gen_twisted_) { // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent() << "d = defer.maybeDeferred(self._handler." << tfunction->get_name() << ", "; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << ")" << endl; if (tfunction->is_oneway()) { f_service_ << indent() << "d.addErrback(self.handle_exception_" << tfunction->get_name() << ", seqid)" << endl; } else { f_service_ << indent() << "d.addCallback(self.write_results_success_" << tfunction->get_name() << ", result, seqid, oprot)" << endl << indent() << "d.addErrback(self.write_results_exception_" << tfunction->get_name() << ", result, seqid, oprot)" << endl; } f_service_ << indent() << "return d" << endl << endl; indent_down(); if (tfunction->is_oneway()) { indent(f_service_) << "def handle_exception_" << tfunction->get_name() << "(self, error, seqid):" << endl; } else { indent(f_service_) << "def write_results_success_" << tfunction->get_name() << "(self, success, result, seqid, oprot):" << endl; indent_up(); if (!tfunction->get_returntype()->is_void()) { f_service_ << indent() << "result.success = success" << endl; } f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid)" << endl << indent() << "result.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()" << endl << indent() << "oprot.trans.flush()" << endl << endl; indent_down(); indent(f_service_) << "def write_results_exception_" << tfunction->get_name() << "(self, error, result, seqid, oprot):" << endl; } indent_up(); if (!tfunction->is_oneway()) { f_service_ << indent() << "msg_type = TMessageType.REPLY" << endl; } f_service_ << indent() << "try:" << endl; // Kinda absurd f_service_ << indent() << indent_str() << "error.raiseException()" << endl; if (!tfunction->is_oneway()) { for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { const string& xname = (*x_iter)->get_name(); f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as " << xname << ":" << endl; indent_up(); f_service_ << indent() << "result." << xname << " = " << xname << endl; indent_down(); } } f_service_ << indent() << "except TTransport.TTransportException:" << endl << indent() << indent_str() << "raise" << endl; if (!tfunction->is_oneway()) { f_service_ << indent() << "except TApplicationException as ex:" << endl << indent() << indent_str() << "logging.exception('TApplication exception in handler')" << endl << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl << indent() << indent_str() << "result = ex" << endl << indent() << "except Exception:" << endl << indent() << indent_str() << "logging.exception('Unexpected exception in handler')" << endl << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl << indent() << indent_str() << "result = TApplicationException(TApplicationException.INTERNAL_ERROR, " "'Internal error')" << endl << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() << "\", msg_type, seqid)" << endl << indent() << "result.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()" << endl << indent() << "oprot.trans.flush()" << endl; } else { f_service_ << indent() << "except Exception:" << endl << indent() << indent_str() << "logging.exception('Exception in oneway handler')" << endl; } indent_down(); } else if (gen_tornado_) { // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; if (!tfunction->is_oneway()) { indent(f_service_) << "msg_type = TMessageType.REPLY" << endl; } f_service_ << indent() << "try:" << endl; indent_up(); f_service_ << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "result.success = "; } f_service_ << "yield gen.maybe_future(self._handler." << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << "))" << endl; indent_down(); if (!tfunction->is_oneway()) { for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { const string& xname = (*x_iter)->get_name(); f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as " << xname << ":" << endl << indent() << indent_str() << "result." << xname << " = " << xname << endl; } } f_service_ << indent() << "except TTransport.TTransportException:" << endl << indent() << indent_str() << "raise" << endl; if (!tfunction->is_oneway()) { f_service_ << indent() << "except TApplicationException as ex:" << endl << indent() << indent_str() << "logging.exception('TApplication exception in handler')" << endl << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl << indent() << indent_str() << "result = ex" << endl << indent() << "except Exception:" << endl << indent() << indent_str() << "logging.exception('Unexpected exception in handler')" << endl << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl << indent() << indent_str() << "result = TApplicationException(TApplicationException.INTERNAL_ERROR, " "'Internal error')" << endl; } else { f_service_ << indent() << "except Exception:" << endl << indent() << indent_str() << "logging.exception('Exception in oneway handler')" << endl; } if (!tfunction->is_oneway()) { f_service_ << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() << "\", msg_type, seqid)" << endl << indent() << "result.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()" << endl << indent() << "oprot.trans.flush()" << endl; } // Close function indent_down(); } else { // py // Try block for a function with exceptions // It also catches arbitrary exceptions raised by handler method to propagate them to the client f_service_ << indent() << "try:" << endl; indent_up(); // Generate the function call t_struct* arg_struct = tfunction->get_arglist(); const std::vector& fields = arg_struct->get_members(); vector::const_iterator f_iter; f_service_ << indent(); if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { f_service_ << "result.success = "; } f_service_ << "self._handler." << tfunction->get_name() << "("; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { f_service_ << ", "; } f_service_ << "args." << (*f_iter)->get_name(); } f_service_ << ")" << endl; if (!tfunction->is_oneway()) { f_service_ << indent() << "msg_type = TMessageType.REPLY" << endl; } indent_down(); f_service_ << indent() << "except TTransport.TTransportException:" << endl << indent() << indent_str() << "raise" << endl; if (!tfunction->is_oneway()) { for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { const string& xname = (*x_iter)->get_name(); f_service_ << indent() << "except " << type_name((*x_iter)->get_type()) << " as " << xname << ":" << endl; indent_up(); f_service_ << indent() << "msg_type = TMessageType.REPLY" << endl; f_service_ << indent() << "result." << xname << " = " << xname << endl; indent_down(); } f_service_ << indent() << "except TApplicationException as ex:" << endl << indent() << indent_str() << "logging.exception('TApplication exception in handler')" << endl << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl << indent() << indent_str() << "result = ex" << endl << indent() << "except Exception:" << endl << indent() << indent_str() << "logging.exception('Unexpected exception in handler')" << endl << indent() << indent_str() << "msg_type = TMessageType.EXCEPTION" << endl << indent() << indent_str() << "result = TApplicationException(TApplicationException.INTERNAL_ERROR, " "'Internal error')" << endl << indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() << "\", msg_type, seqid)" << endl << indent() << "result.write(oprot)" << endl << indent() << "oprot.writeMessageEnd()" << endl << indent() << "oprot.trans.flush()" << endl; } else { f_service_ << indent() << "except Exception:" << endl << indent() << indent_str() << "logging.exception('Exception in oneway handler')" << endl; } // Close function indent_down(); } } /** * Deserializes a field of any type. */ void t_py_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } string name = prefix + tfield->get_name(); if (type->is_struct() || type->is_xception()) { generate_deserialize_struct(out, (t_struct*)type, name); } else if (type->is_container()) { generate_deserialize_container(out, type, name); } else if (type->is_base_type()) { indent(out) << name << " = iprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "readBinary()"; } else if(!gen_utf8strings_) { out << "readString()"; } else { out << "readString().decode('utf-8', errors='replace') if sys.version_info[0] == 2 else iprot.readString()"; } break; case t_base_type::TYPE_BOOL: out << "readBool()"; break; case t_base_type::TYPE_I8: out << "readByte()"; break; case t_base_type::TYPE_I16: out << "readI16()"; break; case t_base_type::TYPE_I32: out << "readI32()"; break; case t_base_type::TYPE_I64: out << "readI64()"; break; case t_base_type::TYPE_DOUBLE: out << "readDouble()"; break; default: throw "compiler error: no Python name for base type " + t_base_type::t_base_name(tbase); } } out << endl; } else if (type->is_enum()) { if (gen_enum_) { indent(out) << name << " = " << type_name(type) << "(iprot.readI32())"; } else { indent(out) << name << " = iprot.readI32()"; } out << endl; } else { printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Generates an unserializer for a struct, calling read() */ void t_py_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) { if (is_immutable(tstruct)) { out << indent() << prefix << " = " << type_name(tstruct) << ".read(iprot)" << endl; } else { out << indent() << prefix << " = " << type_name(tstruct) << "()" << endl << indent() << prefix << ".read(iprot)" << endl; } } /** * Serialize a container by writing out the header followed by * data and then a footer. */ void t_py_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) { string size = tmp("_size"); string ktype = tmp("_ktype"); string vtype = tmp("_vtype"); string etype = tmp("_etype"); t_field fsize(g_type_i32, size); t_field fktype(g_type_i8, ktype); t_field fvtype(g_type_i8, vtype); t_field fetype(g_type_i8, etype); // Declare variables, read header if (ttype->is_map()) { out << indent() << prefix << " = {}" << endl << indent() << "(" << ktype << ", " << vtype << ", " << size << ") = iprot.readMapBegin()" << endl; } else if (ttype->is_set()) { out << indent() << prefix << " = set()" << endl << indent() << "(" << etype << ", " << size << ") = iprot.readSetBegin()" << endl; } else if (ttype->is_list()) { out << indent() << prefix << " = []" << endl << indent() << "(" << etype << ", " << size << ") = iprot.readListBegin()" << endl; } // For loop iterates over elements string i = tmp("_i"); indent(out) << "for " << i << " in range(" << size << "):" << endl; indent_up(); if (ttype->is_map()) { generate_deserialize_map_element(out, (t_map*)ttype, prefix); } else if (ttype->is_set()) { generate_deserialize_set_element(out, (t_set*)ttype, prefix); } else if (ttype->is_list()) { generate_deserialize_list_element(out, (t_list*)ttype, prefix); } indent_down(); // Read container end if (ttype->is_map()) { indent(out) << "iprot.readMapEnd()" << endl; if (is_immutable(ttype)) { indent(out) << prefix << " = TFrozenDict(" << prefix << ")" << endl; } } else if (ttype->is_set()) { indent(out) << "iprot.readSetEnd()" << endl; if (is_immutable(ttype)) { indent(out) << prefix << " = frozenset(" << prefix << ")" << endl; } } else if (ttype->is_list()) { if (is_immutable(ttype)) { indent(out) << prefix << " = tuple(" << prefix << ")" << endl; } indent(out) << "iprot.readListEnd()" << endl; } } /** * Generates code to deserialize a map */ void t_py_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) { string key = tmp("_key"); string val = tmp("_val"); t_field fkey(tmap->get_key_type(), key); t_field fval(tmap->get_val_type(), val); generate_deserialize_field(out, &fkey); generate_deserialize_field(out, &fval); indent(out) << prefix << "[" << key << "] = " << val << endl; } /** * Write a set element */ void t_py_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) { string elem = tmp("_elem"); t_field felem(tset->get_elem_type(), elem); generate_deserialize_field(out, &felem); indent(out) << prefix << ".add(" << elem << ")" << endl; } /** * Write a list element */ void t_py_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) { string elem = tmp("_elem"); t_field felem(tlist->get_elem_type(), elem); generate_deserialize_field(out, &felem); indent(out) << prefix << ".append(" << elem << ")" << endl; } /** * Serializes a field of any type. * * @param tfield The field to serialize * @param prefix Name to prepend to field name */ void t_py_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix) { t_type* type = get_true_type(tfield->get_type()); // Do nothing for void types if (type->is_void()) { throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); } if (type->is_struct() || type->is_xception()) { generate_serialize_struct(out, (t_struct*)type, prefix + tfield->get_name()); } else if (type->is_container()) { generate_serialize_container(out, type, prefix + tfield->get_name()); } else if (type->is_base_type() || type->is_enum()) { string name = prefix + tfield->get_name(); indent(out) << "oprot."; if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "compiler error: cannot serialize void field in a struct: " + name; break; case t_base_type::TYPE_STRING: if (type->is_binary()) { out << "writeBinary(" << name << ")"; } else if (!gen_utf8strings_) { out << "writeString(" << name << ")"; } else { out << "writeString(" << name << ".encode('utf-8') if sys.version_info[0] == 2 else " << name << ")"; } break; case t_base_type::TYPE_BOOL: out << "writeBool(" << name << ")"; break; case t_base_type::TYPE_I8: out << "writeByte(" << name << ")"; break; case t_base_type::TYPE_I16: out << "writeI16(" << name << ")"; break; case t_base_type::TYPE_I32: out << "writeI32(" << name << ")"; break; case t_base_type::TYPE_I64: out << "writeI64(" << name << ")"; break; case t_base_type::TYPE_DOUBLE: out << "writeDouble(" << name << ")"; break; default: throw "compiler error: no Python name for base type " + t_base_type::t_base_name(tbase); } } else if (type->is_enum()) { if (gen_enum_){ out << "writeI32(" << name << ".value)"; } else { out << "writeI32(" << name << ")"; } } out << endl; } else { printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type->get_name().c_str()); } } /** * Serializes all the members of a struct. * * @param tstruct The struct to serialize * @param prefix String prefix to attach to all fields */ void t_py_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) { (void)tstruct; indent(out) << prefix << ".write(oprot)" << endl; } void t_py_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { if (ttype->is_map()) { indent(out) << "oprot.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << "len(" << prefix << "))" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetBegin(" << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << "len(" << prefix << "))" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListBegin(" << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << "len(" << prefix << "))" << endl; } if (ttype->is_map()) { string kiter = tmp("kiter"); string viter = tmp("viter"); indent(out) << "for " << kiter << ", " << viter << " in " << prefix << ".items():" << endl; indent_up(); generate_serialize_map_element(out, (t_map*)ttype, kiter, viter); indent_down(); } else if (ttype->is_set()) { string iter = tmp("iter"); indent(out) << "for " << iter << " in " << prefix << ":" << endl; indent_up(); generate_serialize_set_element(out, (t_set*)ttype, iter); indent_down(); } else if (ttype->is_list()) { string iter = tmp("iter"); indent(out) << "for " << iter << " in " << prefix << ":" << endl; indent_up(); generate_serialize_list_element(out, (t_list*)ttype, iter); indent_down(); } if (ttype->is_map()) { indent(out) << "oprot.writeMapEnd()" << endl; } else if (ttype->is_set()) { indent(out) << "oprot.writeSetEnd()" << endl; } else if (ttype->is_list()) { indent(out) << "oprot.writeListEnd()" << endl; } } /** * Serializes the members of a map. * */ void t_py_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string kiter, string viter) { t_field kfield(tmap->get_key_type(), kiter); generate_serialize_field(out, &kfield, ""); t_field vfield(tmap->get_val_type(), viter); generate_serialize_field(out, &vfield, ""); } /** * Serializes the members of a set. */ void t_py_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { t_field efield(tset->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Serializes the members of a list. */ void t_py_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) { t_field efield(tlist->get_elem_type(), iter); generate_serialize_field(out, &efield, ""); } /** * Generates the docstring for a given struct. */ void t_py_generator::generate_python_docstring(ostream& out, t_struct* tstruct) { generate_python_docstring(out, tstruct, tstruct, "Attributes"); } /** * Generates the docstring for a given function. */ void t_py_generator::generate_python_docstring(ostream& out, t_function* tfunction) { generate_python_docstring(out, tfunction, tfunction->get_arglist(), "Parameters"); } /** * Generates the docstring for a struct or function. */ void t_py_generator::generate_python_docstring(ostream& out, t_doc* tdoc, t_struct* tstruct, const char* subheader) { bool has_doc = false; stringstream ss; if (tdoc->has_doc()) { has_doc = true; ss << tdoc->get_doc(); } const vector& fields = tstruct->get_members(); if (fields.size() > 0) { if (has_doc) { ss << endl; } has_doc = true; ss << subheader << ":\n"; vector::const_iterator p_iter; for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { t_field* p = *p_iter; ss << " - " << p->get_name(); if (p->has_doc()) { ss << ": " << p->get_doc(); } else { ss << endl; } } } if (has_doc) { generate_docstring_comment(out, "\"\"\"\n", "", ss.str(), "\"\"\"\n"); } } /** * Generates the docstring for a generic object. */ void t_py_generator::generate_python_docstring(ostream& out, t_doc* tdoc) { if (tdoc->has_doc()) { generate_docstring_comment(out, "\"\"\"\n", "", tdoc->get_doc(), "\"\"\"\n"); } } /** * Declares an argument, which may include initialization as necessary. * * @param tfield The field */ string t_py_generator::declare_argument(t_field* tfield) { std::ostringstream result; result << tfield->get_name() << "="; if (tfield->get_value() != nullptr) { result << render_field_default_value(tfield); } else { result << "None"; } return result.str(); } /** * Renders a field default value, returns None otherwise. * * @param tfield The field */ string t_py_generator::render_field_default_value(t_field* tfield) { t_type* type = get_true_type(tfield->get_type()); if (tfield->get_value() != nullptr) { return render_const_value(type, tfield->get_value()); } else { return "None"; } } /** * Renders a function signature of the form 'type name(args)' * * @param tfunction Function definition * @return String of rendered function definition */ string t_py_generator::function_signature(t_function* tfunction, bool interface) { vector pre; vector post; string signature = tfunction->get_name() + "("; if (!(gen_zope_interface_ && interface)) { pre.emplace_back("self"); } signature += argument_list(tfunction->get_arglist(), &pre, &post) + ")"; return signature; } /** * Renders a field list */ string t_py_generator::argument_list(t_struct* tstruct, vector* pre, vector* post) { string result = ""; const vector& fields = tstruct->get_members(); vector::const_iterator f_iter; vector::const_iterator s_iter; bool first = true; if (pre) { for (s_iter = pre->begin(); s_iter != pre->end(); ++s_iter) { if (first) { first = false; } else { result += ", "; } result += *s_iter; } } for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { first = false; } else { result += ", "; } result += (*f_iter)->get_name(); } if (post) { for (s_iter = post->begin(); s_iter != post->end(); ++s_iter) { if (first) { first = false; } else { result += ", "; } result += *s_iter; } } return result; } string t_py_generator::type_name(t_type* ttype) { while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } t_program* program = ttype->get_program(); if (ttype->is_service()) { return get_real_py_module(program, gen_twisted_, package_prefix_) + "." + ttype->get_name(); } if (program != nullptr && program != program_) { return get_real_py_module(program, gen_twisted_, package_prefix_) + ".ttypes." + ttype->get_name(); } return ttype->get_name(); } /** * Converts the parse type to a Python tyoe */ string t_py_generator::type_to_enum(t_type* type) { type = get_true_type(type); if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: throw "NO T_VOID CONSTRUCT"; case t_base_type::TYPE_STRING: return "TType.STRING"; case t_base_type::TYPE_BOOL: return "TType.BOOL"; case t_base_type::TYPE_I8: return "TType.BYTE"; case t_base_type::TYPE_I16: return "TType.I16"; case t_base_type::TYPE_I32: return "TType.I32"; case t_base_type::TYPE_I64: return "TType.I64"; case t_base_type::TYPE_DOUBLE: return "TType.DOUBLE"; default: throw "compiler error: unhandled type"; } } else if (type->is_enum()) { return "TType.I32"; } else if (type->is_struct() || type->is_xception()) { return "TType.STRUCT"; } else if (type->is_map()) { return "TType.MAP"; } else if (type->is_set()) { return "TType.SET"; } else if (type->is_list()) { return "TType.LIST"; } throw "INVALID TYPE IN type_to_enum: " + type->get_name(); } /** See the comment inside generate_py_struct_definition for what this is. */ string t_py_generator::type_to_spec_args(t_type* ttype) { while (ttype->is_typedef()) { ttype = ((t_typedef*)ttype)->get_type(); } if (ttype->is_binary()) { return "'BINARY'"; } else if (gen_utf8strings_ && ttype->is_base_type() && reinterpret_cast(ttype)->is_string()) { return "'UTF8'"; } else if (ttype->is_base_type() || ttype->is_enum()) { return "None"; } else if (ttype->is_struct() || ttype->is_xception()) { return "[" + type_name(ttype) + ", None]"; } else if (ttype->is_map()) { return "(" + type_to_enum(((t_map*)ttype)->get_key_type()) + ", " + type_to_spec_args(((t_map*)ttype)->get_key_type()) + ", " + type_to_enum(((t_map*)ttype)->get_val_type()) + ", " + type_to_spec_args(((t_map*)ttype)->get_val_type()) + ", " + (is_immutable(ttype) ? "True" : "False") + ")"; } else if (ttype->is_set()) { return "(" + type_to_enum(((t_set*)ttype)->get_elem_type()) + ", " + type_to_spec_args(((t_set*)ttype)->get_elem_type()) + ", " + (is_immutable(ttype) ? "True" : "False") + ")"; } else if (ttype->is_list()) { return "(" + type_to_enum(((t_list*)ttype)->get_elem_type()) + ", " + type_to_spec_args(((t_list*)ttype)->get_elem_type()) + ", " + (is_immutable(ttype) ? "True" : "False") + ")"; } throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name(); } std::string t_py_generator::display_name() const { return "Python"; } THRIFT_REGISTER_GENERATOR( py, "Python", " zope.interface: Generate code for use with zope.interface.\n" " twisted: Generate Twisted-friendly RPC services.\n" " tornado: Generate code for use with Tornado.\n" " no_utf8strings: Do not Encode/decode strings using utf8 in the generated code. Basically no effect for Python 3.\n" " coding=CODING: Add file encoding declare in generated file.\n" " slots: Generate code using slots for instance members.\n" " dynamic: Generate dynamic code, less code generated but slower.\n" " dynbase=CLS Derive generated classes from class CLS instead of TBase.\n" " dynfrozen=CLS Derive generated immutable classes from class CLS instead of TFrozenBase.\n" " dynexc=CLS Derive generated exceptions from CLS instead of TExceptionBase.\n" " dynfrozenexc=CLS Derive generated immutable exceptions from CLS instead of TFrozenExceptionBase.\n" " dynimport='from foo.bar import CLS'\n" " Add an import line to generated code to find the dynbase class.\n" " package_prefix='top.package.'\n" " Package prefix for generated files.\n" " old_style: Deprecated. Generate old-style classes.\n" " enum: Generates Python's IntEnum, connects thrift to python enums. Python 3.4 and higher.\n" ) thrift-0.19.0/compiler/cpp/src/thrift/thriftl.ll0000644000000000000000000002311214370300523021563 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Thrift scanner. * * Tokenizes a thrift definition file. */ %{ /* This is redundant with some of the flags in Makefile.am, but it works * when people override CXXFLAGS without being careful. The pragmas are * the 'right' way to do it, but don't work on old-enough GCC (in particular * the GCC that ship on Mac OS X 10.6.5, *counter* to what the GNU docs say) * * We should revert the Makefile.am changes once Apple ships a reasonable * GCC. */ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-label" #endif #ifdef _MSC_VER #pragma warning( push ) // warning C4102: 'find_rule' : unreferenced label #pragma warning( disable : 4102 ) // warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data #pragma warning( disable : 4267 ) // avoid isatty redefinition #define YY_NEVER_INTERACTIVE 1 #define YY_NO_UNISTD_H 1 #endif #include #include #include #include #ifdef _MSC_VER #include "thrift/windows/config.h" #endif #include "thrift/main.h" #include "thrift/common.h" #include "thrift/globals.h" #include "thrift/parse/t_program.h" /** * Must be included AFTER parse/t_program.h, but I can't remember why anymore * because I wrote this a while ago. */ #if defined(BISON_USE_PARSER_H_EXTENSION) #include "thrift/thrifty.h" #else #include "thrift/thrifty.hh" #endif void integer_overflow(const char* text) { yyerror("This integer is too big: \"%s\"\n", text); exit(1); } void unexpected_token(const char* text) { yyerror("Unexpected token in input: \"%s\"\n", text); exit(1); } void error_no_longer_supported(const char* text, const char* replace_with) { yyerror("\"%s\" is no longer supported, use \"%s\" instead. Line %d\n", text, replace_with, yylineno); exit(1); } %} /** * Provides the yylineno global, useful for debugging output */ %option lex-compat /** * Our inputs are all single files, so no need for yywrap */ %option noyywrap /** * We don't use it, and it fires up warnings at -Wall */ %option nounput /** * Helper definitions, comments, constants, and whatnot */ intconstant ([+-]?[0-9]+) hexconstant ([+-]?"0x"[0-9A-Fa-f]+) dubconstant ([+-]?[0-9]*(\.[0-9]+)?([eE][+-]?[0-9]+)?) identifier ([a-zA-Z_](\.[a-zA-Z_0-9]|[a-zA-Z_0-9])*) whitespace ([ \t\r\n]*) sillycomm ("/*""*"*"*/") multicm_begin ("/*") doctext_begin ("/**") comment ("//"[^\n]*) unixcomment ("#"[^\n]*) symbol ([:;\,\{\}\(\)\=<>\[\]]) literal_begin (['\"]) %% {whitespace} { /* do nothing */ } {sillycomm} { /* do nothing */ } {doctext_begin} { std::string parsed("/**"); int state = 0; // 0 = normal, 1 = "*" seen, "*/" seen while(state < 2) { int ch = yyinput(); parsed.push_back(ch); switch (ch) { case EOF: yyerror("Unexpected end of file in doc-comment at %d\n", yylineno); exit(1); case '*': state = 1; break; case '/': state = (state == 1) ? 2 : 0; break; default: state = 0; break; } } pdebug("doctext = \"%s\"\n",parsed.c_str()); /* This does not show up in the parse tree. */ /* Rather, the parser will grab it out of the global. */ if (g_parse_mode == PROGRAM) { clear_doctext(); g_doctext = strdup(parsed.c_str() + 3); assert(strlen(g_doctext) >= 2); g_doctext[strlen(g_doctext) - 2] = ' '; g_doctext[strlen(g_doctext) - 1] = '\0'; g_doctext = clean_up_doctext(g_doctext); g_doctext_lineno = yylineno; if( (g_program_doctext_candidate == nullptr) && (g_program_doctext_status == INVALID)){ g_program_doctext_candidate = strdup(g_doctext); g_program_doctext_lineno = g_doctext_lineno; g_program_doctext_status = STILL_CANDIDATE; pdebug("%s","program doctext set to STILL_CANDIDATE"); } } } {multicm_begin} { /* parsed, but thrown away */ std::string parsed("/*"); int state = 0; // 0 = normal, 1 = "*" seen, "*/" seen while(state < 2) { int ch = yyinput(); parsed.push_back(ch); switch (ch) { case EOF: yyerror("Unexpected end of file in multiline comment at %d\n", yylineno); exit(1); case '*': state = 1; break; case '/': state = (state == 1) ? 2 : 0; break; default: state = 0; break; } } pdebug("multi_comm = \"%s\"\n",parsed.c_str()); } {comment} { /* do nothing */ } {unixcomment} { /* do nothing */ } {symbol} { return yytext[0]; } "*" { return yytext[0]; } "false" { yylval.iconst=0; return tok_int_constant; } "true" { yylval.iconst=1; return tok_int_constant; } "namespace" { return tok_namespace; } "cpp_include" { return tok_cpp_include; } "cpp_type" { return tok_cpp_type; } "xsd_all" { return tok_xsd_all; } "xsd_optional" { return tok_xsd_optional; } "xsd_nillable" { return tok_xsd_nillable; } "xsd_attrs" { return tok_xsd_attrs; } "include" { return tok_include; } "void" { return tok_void; } "bool" { return tok_bool; } "byte" { emit_byte_type_warning(); return tok_byte; } "i8" { return tok_i8; } "i16" { return tok_i16; } "i32" { return tok_i32; } "i64" { return tok_i64; } "double" { return tok_double; } "string" { return tok_string; } "binary" { return tok_binary; } "uuid" { return tok_uuid; } "map" { return tok_map; } "list" { return tok_list; } "set" { return tok_set; } "oneway" { return tok_oneway; } "typedef" { return tok_typedef; } "struct" { return tok_struct; } "union" { return tok_union; } "exception" { return tok_xception; } "extends" { return tok_extends; } "throws" { return tok_throws; } "service" { return tok_service; } "enum" { return tok_enum; } "const" { return tok_const; } "required" { return tok_required; } "optional" { return tok_optional; } "async" { pwarning(0, "\"async\" is deprecated. It is called \"oneway\" now.\n"); return tok_async; } "&" { return tok_reference; } {intconstant} { errno = 0; yylval.iconst = strtoll(yytext, nullptr, 10); if (errno == ERANGE) { integer_overflow(yytext); } return tok_int_constant; } {hexconstant} { errno = 0; char sign = yytext[0]; int shift = sign == '0' ? 2 : 3; yylval.iconst = strtoll(yytext+shift, nullptr, 16); if (sign == '-') { yylval.iconst = -yylval.iconst; } if (errno == ERANGE) { integer_overflow(yytext); } return tok_int_constant; } {identifier} { yylval.id = strdup(yytext); return tok_identifier; } {dubconstant} { /* Deliberately placed after identifier, since "e10" is NOT a double literal (THRIFT-3477) */ yylval.dconst = atof(yytext); return tok_dub_constant; } {literal_begin} { char mark = yytext[0]; std::string result; for(;;) { int ch = yyinput(); switch (ch) { case EOF: yyerror("End of file while read string at %d\n", yylineno); exit(1); case '\n': yyerror("End of line while read string at %d\n", yylineno - 1); exit(1); case '\\': ch = yyinput(); switch (ch) { case 'r': result.push_back('\r'); continue; case 'n': result.push_back('\n'); continue; case 't': result.push_back('\t'); continue; case '"': result.push_back('"'); continue; case '\'': result.push_back('\''); continue; case '\\': result.push_back('\\'); continue; default: yyerror("Bad escape character\n"); return -1; } break; default: if (ch == mark) { yylval.id = strdup(result.c_str()); return tok_literal; } else { result.push_back(ch); } } } } . { unexpected_token(yytext); } %% #ifdef _MSC_VER #pragma warning( pop ) #endif /* vim: filetype=lex */ thrift-0.19.0/compiler/cpp/src/thrift/windows/0000755000000000000000000000000014472652644021272 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/src/thrift/windows/config.h0000644000000000000000000000264314303740367022706 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_CONFIG_H_ #define _THRIFT_WINDOWS_CONFIG_H_ 1 #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #ifndef _WIN32 #error "This is a Windows header only" #endif #include #include #include #define strtoll(begin_ptr, end_ptr, length) _strtoi64(begin_ptr, end_ptr, length) #ifndef PRIu64 #define PRIu64 "I64u" #endif #ifndef PRIi64 #define PRIi64 "I64i" #endif // squelch deprecation warnings #pragma warning(disable : 4996) // squelch bool conversion performance warning #pragma warning(disable : 4800) #include #endif // _THRIFT_WINDOWS_CONFIG_H_ thrift-0.19.0/compiler/cpp/src/thrift/thriftl.cc0000644000000000000000000020377714472652643021602 0ustar00rootroot00000000000000 #line 3 "thrift/thriftl.cc" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 4 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #ifndef SIZE_MAX #define SIZE_MAX (~(size_t)0) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ /* begin standard C++ headers. */ /* TODO: this is always defined, so inline it */ #define yyconst const #if defined(__GNUC__) && __GNUC__ >= 3 #define yynoreturn __attribute__((__noreturn__)) #else #define yynoreturn #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an * integer in range [0..255] for use as an array index. */ #define YY_SC_TO_UI(c) ((YY_CHAR) (c)) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires * access to the local variable yy_act. Since yyless() is a macro, it would break * existing scanners that call yyless() from OUTSIDE yylex. * One obvious solution it to make yy_act a global. I tried that, and saw * a 5% performance hit in a non-yylineno scanner, because yy_act is * normally declared as a register variable-- so it is not worth it. */ #define YY_LESS_LINENO(n) \ do { \ int yyl;\ for ( yyl = n; yyl < yyleng; ++yyl )\ if ( yytext[yyl] == '\n' )\ --yylineno;\ }while(0) #define YY_LINENO_REWIND_TO(dst) \ do {\ const char *p;\ for ( p = yy_cp-1; p >= (dst); --p)\ if ( *p == '\n' )\ --yylineno;\ }while(0) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ int yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = NULL; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart ( FILE *input_file ); void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size ); void yy_delete_buffer ( YY_BUFFER_STATE b ); void yy_flush_buffer ( YY_BUFFER_STATE b ); void yypush_buffer_state ( YY_BUFFER_STATE new_buffer ); void yypop_buffer_state ( void ); static void yyensure_buffer_stack ( void ); static void yy_load_buffer_state ( void ); static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size ); YY_BUFFER_STATE yy_scan_string ( const char *yy_str ); YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len ); void *yyalloc ( yy_size_t ); void *yyrealloc ( void *, yy_size_t ); void yyfree ( void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer( yyin, YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define yywrap() (/*CONSTCOND*/1) #define YY_SKIP_YYWRAP typedef flex_uint8_t YY_CHAR; FILE *yyin = NULL, *yyout = NULL; typedef int yy_state_type; #define YY_FLEX_LEX_COMPAT extern int yylineno; int yylineno = 1; extern char yytext[]; static yy_state_type yy_get_previous_state ( void ); static yy_state_type yy_try_NUL_trans ( yy_state_type current_state ); static int yy_get_next_buffer ( void ); static void yynoreturn yy_fatal_error ( const char* msg ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ if ( yyleng >= YYLMAX ) \ YY_FATAL_ERROR( "token too large, exceeds YYLMAX" ); \ yy_flex_strncpy( yytext, (yytext_ptr), yyleng + 1 ); \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 53 #define YY_END_OF_BUFFER 54 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static const flex_int16_t yy_accept[225] = { 0, 1, 1, 54, 52, 1, 1, 51, 6, 46, 7, 8, 50, 52, 52, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 1, 6, 0, 47, 47, 0, 50, 4, 5, 0, 0, 49, 0, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 22, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 3, 5, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 23, 24, 25, 49, 49, 30, 49, 49, 49, 49, 49, 32, 49, 49, 49, 49, 49, 49, 49, 49, 0, 2, 49, 49, 20, 21, 49, 49, 49, 41, 49, 49, 49, 49, 31, 49, 49, 49, 49, 49, 49, 49, 49, 10, 49, 49, 29, 19, 49, 45, 49, 42, 49, 49, 49, 49, 49, 9, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 36, 49, 49, 49, 28, 49, 49, 26, 49, 49, 49, 49, 33, 49, 49, 49, 27, 35, 39, 49, 49, 49, 49, 49, 49, 49, 49, 38, 18, 49, 49, 49, 40, 34, 14, 49, 49, 49, 49, 13, 49, 49, 44, 43, 49, 49, 49, 49, 37, 11, 17, 49, 49, 49, 49, 49, 12, 49, 49, 16, 15, 0 } ; static const YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 4, 5, 1, 1, 6, 4, 7, 7, 8, 9, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 17, 19, 17, 7, 7, 7, 7, 7, 1, 1, 20, 20, 20, 20, 21, 20, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 7, 1, 7, 1, 23, 1, 24, 25, 26, 27, 28, 29, 30, 31, 32, 22, 22, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 22, 7, 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static const YY_CHAR yy_meta[47] = { 0, 1, 1, 2, 1, 1, 1, 1, 1, 3, 4, 1, 5, 5, 5, 5, 5, 5, 5, 5, 6, 7, 8, 8, 6, 6, 6, 6, 7, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 } ; static const flex_int16_t yy_base[232] = { 0, 0, 0, 469, 470, 45, 47, 470, 0, 470, 470, 470, 41, 0, 44, 44, 423, 457, 81, 46, 56, 47, 49, 23, 50, 91, 71, 51, 53, 70, 54, 101, 77, 102, 103, 105, 68, 0, 0, 0, 421, 456, 93, 456, 0, 0, 453, 452, 452, 451, 107, 108, 110, 109, 112, 114, 115, 117, 122, 121, 118, 120, 57, 449, 123, 125, 130, 128, 142, 131, 145, 146, 150, 151, 154, 156, 148, 159, 163, 161, 449, 68, 0, 0, 164, 158, 165, 166, 167, 169, 176, 168, 187, 190, 171, 447, 446, 445, 193, 194, 444, 195, 196, 198, 174, 199, 443, 202, 200, 203, 204, 207, 210, 211, 218, 211, 470, 219, 214, 442, 441, 215, 217, 229, 440, 223, 236, 237, 238, 439, 241, 240, 242, 244, 245, 247, 249, 251, 438, 256, 253, 437, 436, 262, 435, 257, 425, 258, 259, 263, 260, 269, 422, 275, 274, 264, 277, 279, 280, 284, 282, 289, 294, 414, 297, 299, 290, 405, 298, 303, 402, 305, 306, 307, 309, 401, 310, 311, 315, 400, 399, 398, 316, 318, 322, 326, 331, 332, 334, 337, 396, 395, 338, 342, 339, 394, 393, 392, 340, 343, 345, 344, 391, 346, 350, 390, 389, 347, 358, 348, 361, 386, 385, 384, 360, 357, 370, 364, 359, 383, 379, 380, 381, 351, 470, 413, 418, 73, 422, 428, 433, 437 } ; static const flex_int16_t yy_def[232] = { 0, 224, 1, 224, 224, 224, 224, 224, 225, 224, 224, 224, 226, 227, 224, 226, 15, 228, 228, 228, 228, 228, 228, 18, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 224, 225, 227, 15, 15, 229, 227, 224, 230, 231, 228, 228, 229, 18, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 229, 224, 230, 231, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 224, 224, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 0, 224, 224, 224, 224, 224, 224, 224 } ; static const flex_int16_t yy_nxt[517] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 17, 18, 17, 17, 19, 20, 21, 22, 23, 24, 17, 17, 25, 26, 27, 28, 29, 17, 17, 30, 31, 32, 33, 34, 17, 35, 17, 36, 36, 36, 36, 38, 43, 39, 38, 44, 46, 46, 57, 46, 46, 46, 41, 46, 46, 41, 46, 46, 58, 41, 36, 36, 41, 97, 59, 66, 115, 67, 42, 116, 46, 46, 70, 54, 55, 56, 50, 46, 51, 45, 48, 46, 52, 49, 49, 49, 49, 49, 49, 49, 49, 46, 53, 65, 60, 68, 61, 69, 73, 62, 63, 46, 46, 46, 41, 46, 74, 46, 46, 46, 46, 41, 46, 75, 46, 46, 64, 46, 46, 71, 46, 46, 46, 46, 96, 46, 95, 76, 46, 78, 46, 46, 72, 85, 77, 79, 86, 88, 92, 98, 87, 89, 46, 84, 94, 46, 46, 90, 46, 91, 46, 46, 101, 93, 46, 99, 46, 100, 46, 46, 102, 46, 103, 46, 46, 46, 46, 46, 46, 46, 111, 46, 118, 104, 46, 105, 46, 106, 114, 107, 108, 112, 122, 110, 120, 113, 109, 46, 119, 117, 46, 123, 124, 46, 46, 46, 46, 121, 46, 46, 46, 127, 46, 46, 46, 125, 133, 46, 126, 115, 46, 46, 116, 130, 46, 46, 128, 46, 46, 46, 132, 138, 139, 46, 135, 129, 137, 141, 142, 46, 131, 143, 134, 140, 136, 144, 46, 46, 46, 147, 46, 46, 46, 145, 46, 46, 146, 46, 148, 46, 150, 46, 149, 46, 155, 152, 46, 46, 46, 46, 46, 151, 46, 46, 46, 160, 157, 158, 156, 46, 153, 154, 159, 162, 46, 46, 164, 46, 163, 46, 46, 170, 46, 168, 46, 161, 172, 165, 166, 46, 46, 171, 173, 167, 46, 169, 178, 46, 46, 46, 175, 174, 176, 46, 179, 46, 46, 46, 177, 46, 46, 46, 182, 180, 187, 46, 46, 186, 46, 181, 183, 185, 46, 192, 193, 191, 46, 189, 184, 194, 188, 46, 46, 195, 46, 196, 190, 46, 46, 46, 46, 197, 46, 46, 46, 46, 46, 46, 46, 199, 46, 46, 202, 198, 204, 201, 206, 46, 46, 46, 46, 46, 200, 203, 46, 205, 208, 209, 212, 207, 46, 211, 214, 221, 215, 217, 210, 213, 216, 46, 46, 46, 218, 46, 46, 46, 46, 220, 219, 46, 46, 46, 46, 46, 46, 46, 46, 222, 46, 46, 46, 46, 46, 223, 37, 46, 37, 37, 37, 37, 37, 37, 40, 40, 46, 40, 47, 47, 47, 47, 47, 80, 46, 80, 82, 46, 82, 82, 82, 82, 82, 82, 83, 83, 83, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 224, 46, 224, 224, 46, 224, 81, 48, 224, 46, 224, 224, 3, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224 } ; static const flex_int16_t yy_chk[517] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 6, 6, 12, 14, 12, 15, 14, 19, 21, 23, 22, 24, 27, 12, 28, 30, 15, 20, 62, 23, 12, 36, 36, 15, 62, 24, 27, 81, 28, 227, 81, 29, 26, 30, 21, 21, 22, 19, 32, 20, 15, 18, 18, 20, 18, 18, 18, 18, 18, 18, 18, 18, 25, 20, 26, 25, 29, 25, 29, 32, 25, 25, 31, 33, 34, 42, 35, 32, 50, 51, 53, 52, 42, 54, 32, 55, 56, 25, 57, 60, 31, 61, 59, 58, 64, 61, 65, 60, 33, 67, 34, 66, 69, 31, 51, 33, 35, 52, 54, 58, 64, 53, 55, 68, 50, 59, 70, 71, 56, 76, 57, 72, 73, 67, 58, 74, 65, 75, 66, 85, 77, 68, 79, 69, 78, 84, 86, 87, 88, 91, 89, 76, 94, 85, 70, 104, 71, 90, 71, 79, 72, 73, 77, 89, 75, 87, 78, 74, 92, 86, 84, 93, 90, 91, 98, 99, 101, 102, 88, 103, 105, 108, 94, 107, 109, 110, 92, 104, 111, 93, 115, 112, 113, 115, 101, 118, 121, 98, 122, 114, 117, 103, 109, 110, 125, 107, 99, 108, 112, 113, 123, 102, 114, 105, 111, 107, 117, 126, 127, 128, 122, 131, 130, 132, 118, 133, 134, 121, 135, 122, 136, 125, 137, 123, 140, 131, 127, 139, 145, 147, 148, 150, 126, 143, 149, 155, 136, 133, 134, 132, 151, 128, 130, 135, 139, 154, 153, 143, 156, 140, 157, 158, 149, 160, 147, 159, 137, 151, 143, 143, 161, 166, 150, 153, 145, 162, 148, 158, 164, 168, 165, 155, 154, 156, 169, 159, 171, 172, 173, 157, 174, 176, 177, 162, 160, 168, 178, 182, 166, 183, 161, 164, 165, 184, 174, 176, 173, 185, 171, 164, 177, 169, 186, 187, 178, 188, 182, 172, 189, 192, 194, 198, 183, 193, 199, 201, 200, 203, 207, 209, 185, 204, 223, 188, 184, 192, 187, 194, 215, 208, 218, 214, 210, 186, 189, 217, 193, 199, 200, 204, 198, 216, 203, 208, 218, 209, 214, 201, 207, 210, 220, 221, 222, 215, 219, 213, 212, 211, 217, 216, 206, 205, 202, 197, 196, 195, 191, 190, 220, 181, 180, 179, 175, 170, 221, 225, 167, 225, 225, 225, 225, 225, 225, 226, 226, 163, 226, 228, 228, 228, 228, 228, 229, 152, 229, 230, 146, 230, 230, 230, 230, 230, 230, 231, 231, 231, 144, 142, 141, 138, 129, 124, 120, 119, 106, 100, 97, 96, 95, 80, 63, 49, 48, 47, 46, 43, 41, 40, 17, 16, 3, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224, 224 } ; /* Table of booleans, true if rule could match eol. */ static const flex_int32_t yy_rule_can_match_eol[54] = { 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET #ifndef YYLMAX #define YYLMAX 8192 #endif char yytext[YYLMAX]; char *yytext_ptr; #line 1 "thrift/thriftl.ll" /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Thrift scanner. * * Tokenizes a thrift definition file. */ #line 27 "thrift/thriftl.ll" /* This is redundant with some of the flags in Makefile.am, but it works * when people override CXXFLAGS without being careful. The pragmas are * the 'right' way to do it, but don't work on old-enough GCC (in particular * the GCC that ship on Mac OS X 10.6.5, *counter* to what the GNU docs say) * * We should revert the Makefile.am changes once Apple ships a reasonable * GCC. */ #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wunused-function" #pragma GCC diagnostic ignored "-Wunused-label" #endif #ifdef _MSC_VER #pragma warning( push ) // warning C4102: 'find_rule' : unreferenced label #pragma warning( disable : 4102 ) // warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data #pragma warning( disable : 4267 ) // avoid isatty redefinition #define YY_NEVER_INTERACTIVE 1 #define YY_NO_UNISTD_H 1 #endif #include #include #include #include #ifdef _MSC_VER #include "thrift/windows/config.h" #endif #include "thrift/main.h" #include "thrift/common.h" #include "thrift/globals.h" #include "thrift/parse/t_program.h" /** * Must be included AFTER parse/t_program.h, but I can't remember why anymore * because I wrote this a while ago. */ #if defined(BISON_USE_PARSER_H_EXTENSION) #include "thrift/thrifty.h" #else #include "thrift/thrifty.hh" #endif void integer_overflow(const char* text) { yyerror("This integer is too big: \"%s\"\n", text); exit(1); } void unexpected_token(const char* text) { yyerror("Unexpected token in input: \"%s\"\n", text); exit(1); } void error_no_longer_supported(const char* text, const char* replace_with) { yyerror("\"%s\" is no longer supported, use \"%s\" instead. Line %d\n", text, replace_with, yylineno); exit(1); } #line 757 "thrift/thriftl.cc" /** * Provides the yylineno global, useful for debugging output */ /** * Our inputs are all single files, so no need for yywrap */ /** * We don't use it, and it fires up warnings at -Wall */ /** * Helper definitions, comments, constants, and whatnot */ #line 770 "thrift/thriftl.cc" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals ( void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy ( void ); int yyget_debug ( void ); void yyset_debug ( int debug_flag ); YY_EXTRA_TYPE yyget_extra ( void ); void yyset_extra ( YY_EXTRA_TYPE user_defined ); FILE *yyget_in ( void ); void yyset_in ( FILE * _in_str ); FILE *yyget_out ( void ); void yyset_out ( FILE * _out_str ); int yyget_leng ( void ); char *yyget_text ( void ); int yyget_lineno ( void ); void yyset_lineno ( int _line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap ( void ); #else extern int yywrap ( void ); #endif #endif #ifndef YY_NO_UNPUT #endif #ifndef yytext_ptr static void yy_flex_strncpy ( char *, const char *, int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen ( const char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput ( void ); #else static int input ( void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_load_buffer_state( ); } { #line 129 "thrift/thriftl.ll" #line 988 "thrift/thriftl.cc" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 225 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 470 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) { int yyl; for ( yyl = 0; yyl < yyleng; ++yyl ) if ( yytext[yyl] == '\n' ) yylineno++; ; } do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: /* rule 1 can match eol */ YY_RULE_SETUP #line 131 "thrift/thriftl.ll" { /* do nothing */ } YY_BREAK case 2: YY_RULE_SETUP #line 132 "thrift/thriftl.ll" { /* do nothing */ } YY_BREAK case 3: YY_RULE_SETUP #line 134 "thrift/thriftl.ll" { std::string parsed("/**"); int state = 0; // 0 = normal, 1 = "*" seen, "*/" seen while(state < 2) { int ch = yyinput(); parsed.push_back(ch); switch (ch) { case EOF: yyerror("Unexpected end of file in doc-comment at %d\n", yylineno); exit(1); case '*': state = 1; break; case '/': state = (state == 1) ? 2 : 0; break; default: state = 0; break; } } pdebug("doctext = \"%s\"\n",parsed.c_str()); /* This does not show up in the parse tree. */ /* Rather, the parser will grab it out of the global. */ if (g_parse_mode == PROGRAM) { clear_doctext(); g_doctext = strdup(parsed.c_str() + 3); assert(strlen(g_doctext) >= 2); g_doctext[strlen(g_doctext) - 2] = ' '; g_doctext[strlen(g_doctext) - 1] = '\0'; g_doctext = clean_up_doctext(g_doctext); g_doctext_lineno = yylineno; if( (g_program_doctext_candidate == nullptr) && (g_program_doctext_status == INVALID)){ g_program_doctext_candidate = strdup(g_doctext); g_program_doctext_lineno = g_doctext_lineno; g_program_doctext_status = STILL_CANDIDATE; pdebug("%s","program doctext set to STILL_CANDIDATE"); } } } YY_BREAK case 4: YY_RULE_SETUP #line 177 "thrift/thriftl.ll" { /* parsed, but thrown away */ std::string parsed("/*"); int state = 0; // 0 = normal, 1 = "*" seen, "*/" seen while(state < 2) { int ch = yyinput(); parsed.push_back(ch); switch (ch) { case EOF: yyerror("Unexpected end of file in multiline comment at %d\n", yylineno); exit(1); case '*': state = 1; break; case '/': state = (state == 1) ? 2 : 0; break; default: state = 0; break; } } pdebug("multi_comm = \"%s\"\n",parsed.c_str()); } YY_BREAK case 5: YY_RULE_SETUP #line 202 "thrift/thriftl.ll" { /* do nothing */ } YY_BREAK case 6: YY_RULE_SETUP #line 203 "thrift/thriftl.ll" { /* do nothing */ } YY_BREAK case 7: YY_RULE_SETUP #line 205 "thrift/thriftl.ll" { return yytext[0]; } YY_BREAK case 8: YY_RULE_SETUP #line 206 "thrift/thriftl.ll" { return yytext[0]; } YY_BREAK case 9: YY_RULE_SETUP #line 208 "thrift/thriftl.ll" { yylval.iconst=0; return tok_int_constant; } YY_BREAK case 10: YY_RULE_SETUP #line 209 "thrift/thriftl.ll" { yylval.iconst=1; return tok_int_constant; } YY_BREAK case 11: YY_RULE_SETUP #line 211 "thrift/thriftl.ll" { return tok_namespace; } YY_BREAK case 12: YY_RULE_SETUP #line 212 "thrift/thriftl.ll" { return tok_cpp_include; } YY_BREAK case 13: YY_RULE_SETUP #line 213 "thrift/thriftl.ll" { return tok_cpp_type; } YY_BREAK case 14: YY_RULE_SETUP #line 214 "thrift/thriftl.ll" { return tok_xsd_all; } YY_BREAK case 15: YY_RULE_SETUP #line 215 "thrift/thriftl.ll" { return tok_xsd_optional; } YY_BREAK case 16: YY_RULE_SETUP #line 216 "thrift/thriftl.ll" { return tok_xsd_nillable; } YY_BREAK case 17: YY_RULE_SETUP #line 217 "thrift/thriftl.ll" { return tok_xsd_attrs; } YY_BREAK case 18: YY_RULE_SETUP #line 218 "thrift/thriftl.ll" { return tok_include; } YY_BREAK case 19: YY_RULE_SETUP #line 219 "thrift/thriftl.ll" { return tok_void; } YY_BREAK case 20: YY_RULE_SETUP #line 220 "thrift/thriftl.ll" { return tok_bool; } YY_BREAK case 21: YY_RULE_SETUP #line 221 "thrift/thriftl.ll" { emit_byte_type_warning(); return tok_byte; } YY_BREAK case 22: YY_RULE_SETUP #line 222 "thrift/thriftl.ll" { return tok_i8; } YY_BREAK case 23: YY_RULE_SETUP #line 223 "thrift/thriftl.ll" { return tok_i16; } YY_BREAK case 24: YY_RULE_SETUP #line 224 "thrift/thriftl.ll" { return tok_i32; } YY_BREAK case 25: YY_RULE_SETUP #line 225 "thrift/thriftl.ll" { return tok_i64; } YY_BREAK case 26: YY_RULE_SETUP #line 226 "thrift/thriftl.ll" { return tok_double; } YY_BREAK case 27: YY_RULE_SETUP #line 227 "thrift/thriftl.ll" { return tok_string; } YY_BREAK case 28: YY_RULE_SETUP #line 228 "thrift/thriftl.ll" { return tok_binary; } YY_BREAK case 29: YY_RULE_SETUP #line 229 "thrift/thriftl.ll" { return tok_uuid; } YY_BREAK case 30: YY_RULE_SETUP #line 230 "thrift/thriftl.ll" { return tok_map; } YY_BREAK case 31: YY_RULE_SETUP #line 231 "thrift/thriftl.ll" { return tok_list; } YY_BREAK case 32: YY_RULE_SETUP #line 232 "thrift/thriftl.ll" { return tok_set; } YY_BREAK case 33: YY_RULE_SETUP #line 233 "thrift/thriftl.ll" { return tok_oneway; } YY_BREAK case 34: YY_RULE_SETUP #line 234 "thrift/thriftl.ll" { return tok_typedef; } YY_BREAK case 35: YY_RULE_SETUP #line 235 "thrift/thriftl.ll" { return tok_struct; } YY_BREAK case 36: YY_RULE_SETUP #line 236 "thrift/thriftl.ll" { return tok_union; } YY_BREAK case 37: YY_RULE_SETUP #line 237 "thrift/thriftl.ll" { return tok_xception; } YY_BREAK case 38: YY_RULE_SETUP #line 238 "thrift/thriftl.ll" { return tok_extends; } YY_BREAK case 39: YY_RULE_SETUP #line 239 "thrift/thriftl.ll" { return tok_throws; } YY_BREAK case 40: YY_RULE_SETUP #line 240 "thrift/thriftl.ll" { return tok_service; } YY_BREAK case 41: YY_RULE_SETUP #line 241 "thrift/thriftl.ll" { return tok_enum; } YY_BREAK case 42: YY_RULE_SETUP #line 242 "thrift/thriftl.ll" { return tok_const; } YY_BREAK case 43: YY_RULE_SETUP #line 243 "thrift/thriftl.ll" { return tok_required; } YY_BREAK case 44: YY_RULE_SETUP #line 244 "thrift/thriftl.ll" { return tok_optional; } YY_BREAK case 45: YY_RULE_SETUP #line 245 "thrift/thriftl.ll" { pwarning(0, "\"async\" is deprecated. It is called \"oneway\" now.\n"); return tok_async; } YY_BREAK case 46: YY_RULE_SETUP #line 249 "thrift/thriftl.ll" { return tok_reference; } YY_BREAK case 47: YY_RULE_SETUP #line 251 "thrift/thriftl.ll" { errno = 0; yylval.iconst = strtoll(yytext, nullptr, 10); if (errno == ERANGE) { integer_overflow(yytext); } return tok_int_constant; } YY_BREAK case 48: YY_RULE_SETUP #line 260 "thrift/thriftl.ll" { errno = 0; char sign = yytext[0]; int shift = sign == '0' ? 2 : 3; yylval.iconst = strtoll(yytext+shift, nullptr, 16); if (sign == '-') { yylval.iconst = -yylval.iconst; } if (errno == ERANGE) { integer_overflow(yytext); } return tok_int_constant; } YY_BREAK case 49: YY_RULE_SETUP #line 274 "thrift/thriftl.ll" { yylval.id = strdup(yytext); return tok_identifier; } YY_BREAK case 50: YY_RULE_SETUP #line 279 "thrift/thriftl.ll" { /* Deliberately placed after identifier, since "e10" is NOT a double literal (THRIFT-3477) */ yylval.dconst = atof(yytext); return tok_dub_constant; } YY_BREAK case 51: YY_RULE_SETUP #line 285 "thrift/thriftl.ll" { char mark = yytext[0]; std::string result; for(;;) { int ch = yyinput(); switch (ch) { case EOF: yyerror("End of file while read string at %d\n", yylineno); exit(1); case '\n': yyerror("End of line while read string at %d\n", yylineno - 1); exit(1); case '\\': ch = yyinput(); switch (ch) { case 'r': result.push_back('\r'); continue; case 'n': result.push_back('\n'); continue; case 't': result.push_back('\t'); continue; case '"': result.push_back('"'); continue; case '\'': result.push_back('\''); continue; case '\\': result.push_back('\\'); continue; default: yyerror("Bad escape character\n"); return -1; } break; default: if (ch == mark) { yylval.id = strdup(result.c_str()); return tok_literal; } else { result.push_back(ch); } } } } YY_BREAK case 52: YY_RULE_SETUP #line 336 "thrift/thriftl.ll" { unexpected_token(yytext); } YY_BREAK case 53: YY_RULE_SETUP #line 340 "thrift/thriftl.ll" ECHO; YY_BREAK #line 1464 "thrift/thriftl.cc" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1); for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc( (void *) b->yy_ch_buf, (yy_size_t) (b->yy_buf_size + 2) ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = NULL; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); /* "- 2" to take care of EOB's */ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { yy_state_type yy_current_state; char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 225 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 225 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; yy_is_jam = (yy_current_state == 224); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (int) ((yy_c_buf_p) - (yytext_ptr)); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return 0; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); if ( c == '\n' ) yylineno++; ; return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer( yyin, YY_BUF_SIZE ); } yy_init_buffer( YY_CURRENT_BUFFER, input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree( (void *) b->yy_ch_buf ); yyfree( (void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return NULL; b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = NULL; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (const char * yystr ) { return yy_scan_bytes( yystr, (int) strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = (yy_size_t) (_yybytes_len + 2); buf = (char *) yyalloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yynoreturn yy_fatal_error (const char* msg ) { fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param _line_number line number * */ void yyset_lineno (int _line_number ) { yylineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * _in_str ) { yyin = _in_str ; } void yyset_out (FILE * _out_str ) { yyout = _out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int _bdebug ) { yy_flex_debug = _bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ /* We do not touch yylineno unless the option is enabled. */ yylineno = 1; (yy_buffer_stack) = NULL; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = NULL; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = NULL; yyout = NULL; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer( YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, const char * s2, int n ) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (const char * s ) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return malloc(size); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return realloc(ptr, size); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 340 "thrift/thriftl.ll" #ifdef _MSC_VER #pragma warning( pop ) #endif /* vim: filetype=lex */ thrift-0.19.0/compiler/cpp/src/thrift/thrifty.cc0000644000000000000000000031420314472652644021603 0ustar00rootroot00000000000000/* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 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 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, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Copy the first part of user declarations. */ #line 4 "thrift/thrifty.yy" /* yacc.c:339 */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Thrift parser. * * This parser is used on a thrift definition file. * */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif #include #include #ifndef _MSC_VER #include #else #include #endif #include #ifdef _MSC_VER #include "thrift/windows/config.h" #endif #include "thrift/main.h" #include "thrift/common.h" #include "thrift/globals.h" #include "thrift/parse/t_program.h" #include "thrift/parse/t_scope.h" #ifdef _MSC_VER //warning C4065: switch statement contains 'default' but no 'case' labels #pragma warning(disable:4065) #endif /** * This global variable is used for automatic numbering of field indices etc. * when parsing the members of a struct. Field values are automatically * assigned starting from -1 and working their way down. */ int y_field_val = -1; /** * This global variable is used for automatic numbering of enum values. * y_enum_val is the last value assigned; the next auto-assigned value will be * y_enum_val+1, and then it continues working upwards. Explicitly specified * enum values reset y_enum_val to that value. */ int32_t y_enum_val = -1; int g_arglist = 0; const int struct_is_struct = 0; const int struct_is_union = 1; #line 140 "thrift/thrifty.cc" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULLPTR nullptr # else # define YY_NULLPTR 0 # endif # endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* In a future release of Bison, this section will be replaced by #include "y.tab.h". */ #ifndef YY_YY_THRIFT_THRIFTY_HH_INCLUDED # define YY_YY_THRIFT_THRIFTY_HH_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* "%code requires" blocks. */ #line 1 "thrift/thrifty.yy" /* yacc.c:355 */ #include "thrift/parse/t_program.h" #line 174 "thrift/thrifty.cc" /* yacc.c:355 */ /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { tok_identifier = 258, tok_literal = 259, tok_doctext = 260, tok_int_constant = 261, tok_dub_constant = 262, tok_include = 263, tok_namespace = 264, tok_cpp_include = 265, tok_cpp_type = 266, tok_xsd_all = 267, tok_xsd_optional = 268, tok_xsd_nillable = 269, tok_xsd_attrs = 270, tok_void = 271, tok_bool = 272, tok_string = 273, tok_binary = 274, tok_uuid = 275, tok_byte = 276, tok_i8 = 277, tok_i16 = 278, tok_i32 = 279, tok_i64 = 280, tok_double = 281, tok_map = 282, tok_list = 283, tok_set = 284, tok_oneway = 285, tok_async = 286, tok_typedef = 287, tok_struct = 288, tok_xception = 289, tok_throws = 290, tok_extends = 291, tok_service = 292, tok_enum = 293, tok_const = 294, tok_required = 295, tok_optional = 296, tok_union = 297, tok_reference = 298 }; #endif /* Tokens. */ #define tok_identifier 258 #define tok_literal 259 #define tok_doctext 260 #define tok_int_constant 261 #define tok_dub_constant 262 #define tok_include 263 #define tok_namespace 264 #define tok_cpp_include 265 #define tok_cpp_type 266 #define tok_xsd_all 267 #define tok_xsd_optional 268 #define tok_xsd_nillable 269 #define tok_xsd_attrs 270 #define tok_void 271 #define tok_bool 272 #define tok_string 273 #define tok_binary 274 #define tok_uuid 275 #define tok_byte 276 #define tok_i8 277 #define tok_i16 278 #define tok_i32 279 #define tok_i64 280 #define tok_double 281 #define tok_map 282 #define tok_list 283 #define tok_set 284 #define tok_oneway 285 #define tok_async 286 #define tok_typedef 287 #define tok_struct 288 #define tok_xception 289 #define tok_throws 290 #define tok_extends 291 #define tok_service 292 #define tok_enum 293 #define tok_const 294 #define tok_required 295 #define tok_optional 296 #define tok_union 297 #define tok_reference 298 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED union YYSTYPE { #line 82 "thrift/thrifty.yy" /* yacc.c:355 */ char* id; int64_t iconst; double dconst; bool tbool; t_doc* tdoc; t_type* ttype; t_base_type* tbase; t_typedef* ttypedef; t_enum* tenum; t_enum_value* tenumv; t_const* tconst; t_const_value* tconstv; t_struct* tstruct; t_service* tservice; t_function* tfunction; t_field* tfield; char* dtext; char* keyword; t_field::e_req ereq; t_annotation* tannot; t_field_id tfieldid; #line 296 "thrift/thrifty.cc" /* yacc.c:355 */ }; typedef union YYSTYPE YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; int yyparse (void); #endif /* !YY_YY_THRIFT_THRIFTY_HH_INCLUDED */ /* Copy the second part of user declarations. */ #line 313 "thrift/thrifty.cc" /* yacc.c:358 */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #else typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ # define YY_(Msgid) Msgid # endif #endif #ifndef YY_ATTRIBUTE # if (defined __GNUC__ \ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C # define YY_ATTRIBUTE(Spec) __attribute__(Spec) # else # define YY_ATTRIBUTE(Spec) /* empty */ # endif #endif #ifndef YY_ATTRIBUTE_PURE # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif #ifndef YY_ATTRIBUTE_UNUSED # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif #if !defined _Noreturn \ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) # if defined _MSC_VER && 1200 <= _MSC_VER # define _Noreturn __declspec (noreturn) # else # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) #else # define YYUSE(E) /* empty */ #endif #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 215 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 57 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 58 /* YYNRULES -- Number of rules. */ #define YYNRULES 143 /* YYNSTATES -- Number of states. */ #define YYNSTATES 224 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 298 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 53, 54, 44, 2, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 52, 46, 55, 49, 56, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 50, 2, 51, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 47, 2, 48, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 249, 249, 261, 272, 281, 286, 291, 295, 307, 315, 325, 338, 346, 351, 359, 374, 392, 399, 406, 413, 422, 424, 427, 430, 443, 471, 478, 485, 499, 514, 526, 545, 554, 560, 565, 571, 576, 583, 590, 597, 604, 611, 618, 625, 629, 635, 650, 655, 660, 665, 670, 675, 680, 685, 690, 704, 718, 723, 728, 741, 746, 753, 759, 774, 778, 783, 788, 798, 803, 813, 820, 854, 859, 864, 876, 881, 886, 891, 896, 901, 906, 911, 916, 921, 926, 931, 936, 941, 946, 951, 956, 961, 966, 971, 976, 981, 986, 991, 996, 1001, 1006, 1011, 1019, 1059, 1069, 1074, 1079, 1083, 1095, 1100, 1109, 1114, 1119, 1126, 1145, 1150, 1156, 1169, 1174, 1179, 1184, 1189, 1194, 1199, 1204, 1209, 1214, 1220, 1231, 1236, 1241, 1248, 1258, 1268, 1286, 1291, 1296, 1302, 1307, 1315, 1321, 1330, 1336 }; #endif #if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "tok_identifier", "tok_literal", "tok_doctext", "tok_int_constant", "tok_dub_constant", "tok_include", "tok_namespace", "tok_cpp_include", "tok_cpp_type", "tok_xsd_all", "tok_xsd_optional", "tok_xsd_nillable", "tok_xsd_attrs", "tok_void", "tok_bool", "tok_string", "tok_binary", "tok_uuid", "tok_byte", "tok_i8", "tok_i16", "tok_i32", "tok_i64", "tok_double", "tok_map", "tok_list", "tok_set", "tok_oneway", "tok_async", "tok_typedef", "tok_struct", "tok_xception", "tok_throws", "tok_extends", "tok_service", "tok_enum", "tok_const", "tok_required", "tok_optional", "tok_union", "tok_reference", "'*'", "','", "';'", "'{'", "'}'", "'='", "'['", "']'", "':'", "'('", "')'", "'<'", "'>'", "$accept", "Program", "CaptureDocText", "DestroyDocText", "HeaderList", "Header", "Include", "DefinitionList", "Definition", "TypeDefinition", "CommaOrSemicolonOptional", "Typedef", "Enum", "EnumDefList", "EnumDef", "EnumValue", "Const", "ConstValue", "ConstList", "ConstListContents", "ConstMap", "ConstMapContents", "StructHead", "Struct", "XsdAll", "XsdOptional", "XsdNillable", "XsdAttributes", "Xception", "Service", "FlagArgs", "UnflagArgs", "Extends", "FunctionList", "Function", "Oneway", "Throws", "FieldList", "Field", "FieldName", "FieldIdentifier", "FieldReference", "FieldRequiredness", "FieldValue", "FunctionType", "FieldType", "BaseType", "SimpleBaseType", "ContainerType", "SimpleContainerType", "MapType", "SetType", "ListType", "CppType", "TypeAnnotations", "TypeAnnotationList", "TypeAnnotation", "TypeAnnotationValue", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 42, 44, 59, 123, 125, 61, 91, 93, 58, 40, 41, 60, 62 }; # endif #define YYPACT_NINF -123 #define yypact_value_is_default(Yystate) \ (!!((Yystate) == (-123))) #define YYTABLE_NINF -59 #define yytable_value_is_error(Yytable_value) \ 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int16 yypact[] = { -123, 11, 6, -123, 28, 18, 17, 9, 22, -123, -123, 50, -123, 26, 29, -123, 186, -123, 36, 40, 44, 186, -123, -123, -123, -123, -123, -123, 48, -123, -123, -123, 1, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, 45, 45, 45, 52, -123, 1, -123, 1, -123, -123, -123, 10, 34, 25, 61, 53, -123, -123, 69, 20, 24, 31, 1, -123, -123, -123, 87, 46, -123, 42, -123, 47, 4, -123, 186, 186, 186, -4, 51, -123, -123, 54, 27, -123, 49, -123, -123, 55, 39, 57, -123, -123, -123, 1, 90, -123, -123, 1, 98, -123, -123, -123, -123, -123, -123, -123, -4, -123, -123, 58, 99, -4, 186, 45, -123, -123, 56, 5, 59, -123, 60, 1, 21, 16, -123, 1, -123, -123, 63, -123, -123, -123, -123, 186, 19, 62, -123, 105, -4, -123, 64, -123, -4, -123, -123, 72, -123, -123, 159, 1, -123, -123, 27, -123, -123, 118, -123, 102, -123, -123, -4, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, 71, 70, -123, 27, 111, -123, -123, -123, 116, 78, -123, 110, 129, 119, 1, 112, 1, -123, -4, -123, -4, 120, -123, 113, -123, -123, -123 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 6, 0, 13, 1, 0, 3, 0, 0, 0, 5, 7, 0, 11, 0, 0, 10, 0, 44, 0, 0, 0, 0, 45, 12, 15, 17, 18, 14, 0, 19, 20, 16, 138, 9, 114, 121, 118, 119, 120, 122, 123, 124, 125, 126, 127, 136, 136, 136, 0, 115, 138, 116, 138, 129, 130, 131, 0, 60, 0, 0, 48, 140, 8, 0, 0, 0, 0, 138, 117, 128, 70, 0, 0, 27, 0, 47, 0, 0, 135, 0, 0, 0, 23, 3, 59, 57, 3, 0, 70, 143, 137, 139, 0, 0, 0, 21, 22, 24, 138, 104, 69, 62, 138, 0, 26, 35, 34, 32, 33, 43, 40, 23, 36, 37, 3, 0, 23, 0, 136, 133, 55, 0, 109, 3, 25, 30, 138, 0, 0, 31, 138, 142, 141, 0, 134, 103, 107, 108, 0, 66, 0, 61, 0, 23, 41, 0, 38, 23, 46, 132, 106, 64, 65, 0, 138, 29, 28, 0, 39, 105, 0, 113, 0, 112, 56, 23, 72, 75, 73, 74, 76, 77, 84, 85, 86, 78, 79, 80, 81, 82, 83, 87, 88, 89, 90, 91, 92, 93, 95, 97, 96, 98, 99, 100, 101, 102, 94, 111, 0, 42, 0, 50, 70, 110, 49, 52, 3, 51, 54, 68, 0, 138, 0, 138, 70, 23, 70, 23, 3, 71, 3, 63, 53, 67 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -123, -123, -1, -123, -123, -123, -123, -123, -123, -123, -103, -123, -123, -123, -123, -123, -123, -122, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -85, -123, -123, -123, -123, -123, -123, -123, -20, -123, -123, -123, -123, -123, -123, -123, -37, -50, -123, -123, -123 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 1, 99, 4, 2, 9, 10, 5, 23, 24, 97, 25, 26, 86, 104, 126, 27, 111, 112, 128, 113, 127, 28, 29, 76, 205, 208, 211, 30, 31, 101, 140, 72, 123, 141, 153, 213, 83, 100, 197, 122, 160, 138, 201, 162, 48, 49, 50, 51, 52, 53, 54, 55, 64, 62, 77, 91, 116 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int16 yytable[] = { 68, 59, 69, 114, 11, 145, 147, 89, 129, 65, 66, 3, 13, 132, -4, -4, -4, 82, -2, 105, 106, 12, 107, 108, 105, 106, 15, 107, 108, 32, 105, 106, 33, 107, 108, 165, 6, 7, 8, 56, 156, 95, 96, 57, 158, 136, 137, 58, 120, 151, 152, 60, 124, 14, 61, 67, 63, 70, 90, 92, 93, 94, 199, 109, 74, 75, 110, 146, 109, 144, 71, 110, 73, 78, 109, 79, 143, 110, 203, 80, 148, 134, 16, 17, 18, 103, 81, 19, 20, 21, 84, 87, 22, 85, 88, 118, 121, 133, 115, 98, 117, 125, 102, 131, 164, 198, 130, -58, 135, 142, 154, 155, 219, 119, 221, 159, 157, 206, 150, 149, 200, 166, 139, 202, 204, 210, 167, 168, 169, 218, 207, 220, 209, 163, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 215, 34, 217, 212, 216, 214, 223, 222, 0, 0, 0, 0, 0, 0, 161, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47 }; static const yytype_int16 yycheck[] = { 50, 21, 52, 88, 5, 127, 128, 3, 111, 46, 47, 0, 3, 116, 8, 9, 10, 67, 0, 3, 4, 4, 6, 7, 3, 4, 4, 6, 7, 3, 3, 4, 3, 6, 7, 157, 8, 9, 10, 3, 143, 45, 46, 3, 147, 40, 41, 3, 98, 30, 31, 3, 102, 44, 53, 3, 11, 47, 54, 79, 80, 81, 165, 47, 3, 12, 50, 51, 47, 48, 36, 50, 47, 4, 47, 55, 126, 50, 200, 55, 130, 118, 32, 33, 34, 86, 55, 37, 38, 39, 3, 49, 42, 47, 47, 56, 6, 117, 49, 48, 45, 3, 48, 4, 154, 3, 48, 48, 52, 49, 48, 6, 215, 56, 217, 43, 52, 202, 138, 56, 49, 3, 123, 53, 13, 15, 8, 9, 10, 214, 14, 216, 54, 153, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 211, 3, 213, 35, 53, 47, 54, 48, -1, -1, -1, -1, -1, -1, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 58, 61, 0, 60, 64, 8, 9, 10, 62, 63, 59, 4, 3, 44, 4, 32, 33, 34, 37, 38, 39, 42, 65, 66, 68, 69, 73, 79, 80, 85, 86, 3, 3, 3, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 102, 103, 104, 105, 106, 107, 108, 109, 3, 3, 3, 102, 3, 53, 111, 11, 110, 110, 110, 3, 111, 111, 47, 36, 89, 47, 3, 12, 81, 112, 4, 55, 55, 55, 111, 94, 3, 47, 70, 49, 47, 3, 54, 113, 102, 102, 102, 45, 46, 67, 48, 59, 95, 87, 48, 59, 71, 3, 4, 6, 7, 47, 50, 74, 75, 77, 94, 49, 114, 45, 56, 56, 111, 6, 97, 90, 111, 3, 72, 78, 76, 67, 48, 4, 67, 102, 110, 52, 40, 41, 99, 59, 88, 91, 49, 111, 48, 74, 51, 74, 111, 56, 102, 30, 31, 92, 48, 6, 67, 52, 67, 43, 98, 16, 101, 102, 111, 74, 3, 8, 9, 10, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 96, 3, 67, 49, 100, 53, 74, 13, 82, 94, 14, 83, 54, 15, 84, 35, 93, 47, 111, 53, 111, 94, 67, 94, 67, 48, 54 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 57, 58, 59, 60, 61, 61, 62, 62, 62, 62, 63, 64, 64, 65, 65, 65, 66, 66, 66, 66, 67, 67, 67, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 74, 74, 74, 74, 75, 76, 76, 77, 78, 78, 79, 79, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 86, 87, 88, 89, 89, 90, 90, 91, 92, 92, 92, 93, 93, 94, 94, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 98, 98, 99, 99, 99, 100, 100, 101, 101, 102, 102, 102, 103, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 105, 106, 106, 106, 107, 108, 109, 110, 110, 111, 111, 112, 112, 113, 114, 114 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 2, 0, 0, 3, 0, 1, 4, 3, 2, 2, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 5, 6, 2, 0, 4, 3, 1, 6, 1, 1, 1, 1, 1, 1, 3, 3, 0, 3, 5, 0, 1, 1, 7, 1, 0, 1, 0, 1, 0, 4, 0, 6, 9, 0, 0, 2, 0, 2, 0, 10, 1, 1, 0, 4, 0, 2, 0, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 1, 0, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 7, 5, 6, 2, 0, 3, 0, 2, 0, 3, 2, 0 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (yylen); \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) /* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*----------------------------------------. | Print this symbol's value on YYOUTPUT. | `----------------------------------------*/ static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) { FILE *yyo = yyoutput; YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) { YYFPRINTF (yyoutput, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) { unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyssp, yyvsp, Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T yystrlen (const char *yystr) { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * yystpcpy (char *yydest, const char *yysrc) { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per "expected"). */ int yycount = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; break; } yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } } } } switch (yycount) { # define YYCASE_(N, S) \ case N: \ yyformat = S; \ break YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); # undef YYCASE_ } { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return 1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyformat += 2; } else { yyp++; yyformat++; } } return 0; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); YY_IGNORE_MAYBE_UNINITIALIZED_END } /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ int yyparse (void) { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: 'yyss': related to states. 'yyvs': related to semantic values. Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yyssp = yyss = yyssa; yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = yylex (); } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 250 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Program -> Headers DefinitionList"); if((g_program_doctext_candidate != nullptr) && (g_program_doctext_status != ALREADY_PROCESSED)) { g_program->set_doc(g_program_doctext_candidate); g_program_doctext_status = ALREADY_PROCESSED; } clear_doctext(); } #line 1577 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 3: #line 261 "thrift/thrifty.yy" /* yacc.c:1646 */ { if (g_parse_mode == PROGRAM) { (yyval.dtext) = g_doctext; g_doctext = nullptr; } else { (yyval.dtext) = nullptr; } } #line 1590 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 4: #line 272 "thrift/thrifty.yy" /* yacc.c:1646 */ { if (g_parse_mode == PROGRAM) { clear_doctext(); } } #line 1600 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 5: #line 282 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("HeaderList -> HeaderList Header"); } #line 1608 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 6: #line 286 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("HeaderList -> "); } #line 1616 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 7: #line 292 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Header -> Include"); } #line 1624 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 8: #line 296 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Header -> tok_namespace tok_identifier tok_identifier"); declare_valid_program_doctext(); if (g_parse_mode == PROGRAM) { g_program->set_namespace((yyvsp[-2].id), (yyvsp[-1].id)); } if ((yyvsp[0].ttype) != nullptr) { g_program->set_namespace_annotations((yyvsp[-2].id), (yyvsp[0].ttype)->annotations_); delete (yyvsp[0].ttype); } } #line 1640 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 9: #line 308 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Header -> tok_namespace * tok_identifier"); declare_valid_program_doctext(); if (g_parse_mode == PROGRAM) { g_program->set_namespace("*", (yyvsp[0].id)); } } #line 1652 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 10: #line 316 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Header -> tok_cpp_include tok_literal"); declare_valid_program_doctext(); if (g_parse_mode == PROGRAM) { g_program->add_cpp_include((yyvsp[0].id)); } } #line 1664 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 11: #line 326 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Include -> tok_include tok_literal"); declare_valid_program_doctext(); if (g_parse_mode == INCLUDES) { std::string path = include_file(std::string((yyvsp[0].id))); if (!path.empty()) { g_program->add_include(path, std::string((yyvsp[0].id))); } } } #line 1679 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 12: #line 339 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("DefinitionList -> DefinitionList Definition"); if ((yyvsp[-1].dtext) != nullptr && (yyvsp[0].tdoc) != nullptr) { (yyvsp[0].tdoc)->set_doc((yyvsp[-1].dtext)); } } #line 1690 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 13: #line 346 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("DefinitionList -> "); } #line 1698 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 14: #line 352 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Definition -> Const"); if (g_parse_mode == PROGRAM) { g_program->add_const((yyvsp[0].tconst)); } (yyval.tdoc) = (yyvsp[0].tconst); } #line 1710 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 15: #line 360 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Definition -> TypeDefinition"); if (g_parse_mode == PROGRAM) { g_scope->add_type((yyvsp[0].ttype)->get_name(), (yyvsp[0].ttype)); if (g_parent_scope != nullptr) { g_parent_scope->add_type(g_parent_prefix + (yyvsp[0].ttype)->get_name(), (yyvsp[0].ttype)); } if (! g_program->is_unique_typename((yyvsp[0].ttype))) { yyerror("Type \"%s\" is already defined.", (yyvsp[0].ttype)->get_name().c_str()); exit(1); } } (yyval.tdoc) = (yyvsp[0].ttype); } #line 1729 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 16: #line 375 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Definition -> Service"); if (g_parse_mode == PROGRAM) { g_scope->add_service((yyvsp[0].tservice)->get_name(), (yyvsp[0].tservice)); if (g_parent_scope != nullptr) { g_parent_scope->add_service(g_parent_prefix + (yyvsp[0].tservice)->get_name(), (yyvsp[0].tservice)); } g_program->add_service((yyvsp[0].tservice)); if (! g_program->is_unique_typename((yyvsp[0].tservice))) { yyerror("Type \"%s\" is already defined.", (yyvsp[0].tservice)->get_name().c_str()); exit(1); } } (yyval.tdoc) = (yyvsp[0].tservice); } #line 1749 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 17: #line 393 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeDefinition -> Typedef"); if (g_parse_mode == PROGRAM) { g_program->add_typedef((yyvsp[0].ttypedef)); } } #line 1760 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 18: #line 400 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeDefinition -> Enum"); if (g_parse_mode == PROGRAM) { g_program->add_enum((yyvsp[0].tenum)); } } #line 1771 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 19: #line 407 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeDefinition -> Struct"); if (g_parse_mode == PROGRAM) { g_program->add_struct((yyvsp[0].tstruct)); } } #line 1782 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 20: #line 414 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeDefinition -> Xception"); if (g_parse_mode == PROGRAM) { g_program->add_xception((yyvsp[0].tstruct)); } } #line 1793 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 21: #line 423 "thrift/thrifty.yy" /* yacc.c:1646 */ {} #line 1799 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 22: #line 425 "thrift/thrifty.yy" /* yacc.c:1646 */ {} #line 1805 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 23: #line 427 "thrift/thrifty.yy" /* yacc.c:1646 */ {} #line 1811 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 24: #line 431 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeDef -> tok_typedef FieldType tok_identifier"); validate_simple_identifier( (yyvsp[-2].id)); t_typedef *td = new t_typedef(g_program, (yyvsp[-3].ttype), (yyvsp[-2].id)); (yyval.ttypedef) = td; if ((yyvsp[-1].ttype) != nullptr) { (yyval.ttypedef)->annotations_ = (yyvsp[-1].ttype)->annotations_; delete (yyvsp[-1].ttype); } } #line 1826 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 25: #line 444 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Enum -> tok_enum tok_identifier { EnumDefList }"); (yyval.tenum) = (yyvsp[-2].tenum); validate_simple_identifier( (yyvsp[-4].id)); (yyval.tenum)->set_name((yyvsp[-4].id)); if ((yyvsp[0].ttype) != nullptr) { (yyval.tenum)->annotations_ = (yyvsp[0].ttype)->annotations_; delete (yyvsp[0].ttype); } // make constants for all the enum values if (g_parse_mode == PROGRAM) { const std::vector& enum_values = (yyval.tenum)->get_constants(); std::vector::const_iterator c_iter; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { std::string const_name = (yyval.tenum)->get_name() + "." + (*c_iter)->get_name(); t_const_value* const_val = new t_const_value((*c_iter)->get_value()); const_val->set_enum((yyval.tenum)); g_scope->add_constant(const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val)); if (g_parent_scope != nullptr) { g_parent_scope->add_constant(g_parent_prefix + const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val)); } } } } #line 1856 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 26: #line 472 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("EnumDefList -> EnumDefList EnumDef"); (yyval.tenum) = (yyvsp[-1].tenum); (yyval.tenum)->append((yyvsp[0].tenumv)); } #line 1866 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 27: #line 478 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("EnumDefList -> "); (yyval.tenum) = new t_enum(g_program); y_enum_val = -1; } #line 1876 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 28: #line 486 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("EnumDef -> EnumValue"); (yyval.tenumv) = (yyvsp[-2].tenumv); if ((yyvsp[-3].dtext) != nullptr) { (yyval.tenumv)->set_doc((yyvsp[-3].dtext)); } if ((yyvsp[-1].ttype) != nullptr) { (yyval.tenumv)->annotations_ = (yyvsp[-1].ttype)->annotations_; delete (yyvsp[-1].ttype); } } #line 1892 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 29: #line 500 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("EnumValue -> tok_identifier = tok_int_constant"); if ((yyvsp[0].iconst) < INT32_MIN || (yyvsp[0].iconst) > INT32_MAX) { // Note: this used to be just a warning. However, since thrift always // treats enums as i32 values, I'm changing it to a fatal error. // I doubt this will affect many people, but users who run into this // will have to update their thrift files to manually specify the // truncated i32 value that thrift has always been using anyway. failure("64-bit value supplied for enum %s will be truncated.", (yyvsp[-2].id)); } y_enum_val = static_cast((yyvsp[0].iconst)); (yyval.tenumv) = new t_enum_value((yyvsp[-2].id), y_enum_val); } #line 1910 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 30: #line 515 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("EnumValue -> tok_identifier"); validate_simple_identifier( (yyvsp[0].id)); if (y_enum_val == INT32_MAX) { failure("enum value overflow at enum %s", (yyvsp[0].id)); } ++y_enum_val; (yyval.tenumv) = new t_enum_value((yyvsp[0].id), y_enum_val); } #line 1924 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 31: #line 527 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Const -> tok_const FieldType tok_identifier = ConstValue"); if (g_parse_mode == PROGRAM) { validate_simple_identifier( (yyvsp[-3].id)); g_scope->resolve_const_value((yyvsp[-1].tconstv), (yyvsp[-4].ttype)); (yyval.tconst) = new t_const((yyvsp[-4].ttype), (yyvsp[-3].id), (yyvsp[-1].tconstv)); validate_const_type((yyval.tconst)); g_scope->add_constant((yyvsp[-3].id), (yyval.tconst)); if (g_parent_scope != nullptr) { g_parent_scope->add_constant(g_parent_prefix + (yyvsp[-3].id), (yyval.tconst)); } } else { (yyval.tconst) = nullptr; } } #line 1945 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 32: #line 546 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstValue => tok_int_constant"); (yyval.tconstv) = new t_const_value(); (yyval.tconstv)->set_integer((yyvsp[0].iconst)); if (!g_allow_64bit_consts && ((yyvsp[0].iconst) < INT32_MIN || (yyvsp[0].iconst) > INT32_MAX)) { pwarning(1, "64-bit constant \"%" PRIi64"\" may not work in all languages.\n", (yyvsp[0].iconst)); } } #line 1958 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 33: #line 555 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstValue => tok_dub_constant"); (yyval.tconstv) = new t_const_value(); (yyval.tconstv)->set_double((yyvsp[0].dconst)); } #line 1968 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 34: #line 561 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstValue => tok_literal"); (yyval.tconstv) = new t_const_value((yyvsp[0].id)); } #line 1977 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 35: #line 566 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstValue => tok_identifier"); (yyval.tconstv) = new t_const_value(); (yyval.tconstv)->set_identifier((yyvsp[0].id)); } #line 1987 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 36: #line 572 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstValue => ConstList"); (yyval.tconstv) = (yyvsp[0].tconstv); } #line 1996 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 37: #line 577 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstValue => ConstMap"); (yyval.tconstv) = (yyvsp[0].tconstv); } #line 2005 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 38: #line 584 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstList => [ ConstListContents ]"); (yyval.tconstv) = (yyvsp[-1].tconstv); } #line 2014 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 39: #line 591 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstListContents => ConstListContents ConstValue CommaOrSemicolonOptional"); (yyval.tconstv) = (yyvsp[-2].tconstv); (yyval.tconstv)->add_list((yyvsp[-1].tconstv)); } #line 2024 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 40: #line 597 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstListContents =>"); (yyval.tconstv) = new t_const_value(); (yyval.tconstv)->set_list(); } #line 2034 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 41: #line 605 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstMap => { ConstMapContents }"); (yyval.tconstv) = (yyvsp[-1].tconstv); } #line 2043 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 42: #line 612 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstMapContents => ConstMapContents ConstValue CommaOrSemicolonOptional"); (yyval.tconstv) = (yyvsp[-4].tconstv); (yyval.tconstv)->add_map((yyvsp[-3].tconstv), (yyvsp[-1].tconstv)); } #line 2053 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 43: #line 618 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ConstMapContents =>"); (yyval.tconstv) = new t_const_value(); (yyval.tconstv)->set_map(); } #line 2063 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 44: #line 626 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.iconst) = struct_is_struct; } #line 2071 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 45: #line 630 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.iconst) = struct_is_union; } #line 2079 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 46: #line 636 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Struct -> tok_struct tok_identifier { FieldList }"); validate_simple_identifier( (yyvsp[-5].id)); (yyvsp[-2].tstruct)->set_xsd_all((yyvsp[-4].tbool)); (yyvsp[-2].tstruct)->set_union((yyvsp[-6].iconst) == struct_is_union); (yyval.tstruct) = (yyvsp[-2].tstruct); (yyval.tstruct)->set_name((yyvsp[-5].id)); if ((yyvsp[0].ttype) != nullptr) { (yyval.tstruct)->annotations_ = (yyvsp[0].ttype)->annotations_; delete (yyvsp[0].ttype); } } #line 2096 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 47: #line 651 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = true; } #line 2104 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 48: #line 655 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = false; } #line 2112 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 49: #line 661 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = true; } #line 2120 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 50: #line 665 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = false; } #line 2128 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 51: #line 671 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = true; } #line 2136 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 52: #line 675 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = false; } #line 2144 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 53: #line 681 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tstruct) = (yyvsp[-1].tstruct); } #line 2152 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 54: #line 685 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tstruct) = nullptr; } #line 2160 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 55: #line 691 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Xception -> tok_xception tok_identifier { FieldList }"); validate_simple_identifier( (yyvsp[-4].id)); (yyvsp[-2].tstruct)->set_name((yyvsp[-4].id)); (yyvsp[-2].tstruct)->set_xception(true); (yyval.tstruct) = (yyvsp[-2].tstruct); if ((yyvsp[0].ttype) != nullptr) { (yyval.tstruct)->annotations_ = (yyvsp[0].ttype)->annotations_; delete (yyvsp[0].ttype); } } #line 2176 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 56: #line 705 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Service -> tok_service tok_identifier { FunctionList }"); validate_simple_identifier( (yyvsp[-7].id)); (yyval.tservice) = (yyvsp[-3].tservice); (yyval.tservice)->set_name((yyvsp[-7].id)); (yyval.tservice)->set_extends((yyvsp[-6].tservice)); if ((yyvsp[0].ttype) != nullptr) { (yyval.tservice)->annotations_ = (yyvsp[0].ttype)->annotations_; delete (yyvsp[0].ttype); } } #line 2192 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 57: #line 718 "thrift/thrifty.yy" /* yacc.c:1646 */ { g_arglist = 1; } #line 2200 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 58: #line 723 "thrift/thrifty.yy" /* yacc.c:1646 */ { g_arglist = 0; } #line 2208 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 59: #line 729 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Extends -> tok_extends tok_identifier"); (yyval.tservice) = nullptr; if (g_parse_mode == PROGRAM) { (yyval.tservice) = g_scope->get_service((yyvsp[0].id)); if ((yyval.tservice) == nullptr) { yyerror("Service \"%s\" has not been defined.", (yyvsp[0].id)); exit(1); } } } #line 2224 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 60: #line 741 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tservice) = nullptr; } #line 2232 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 61: #line 747 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FunctionList -> FunctionList Function"); (yyval.tservice) = (yyvsp[-1].tservice); (yyvsp[-1].tservice)->add_function((yyvsp[0].tfunction)); } #line 2242 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 62: #line 753 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FunctionList -> "); (yyval.tservice) = new t_service(g_program); } #line 2251 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 63: #line 760 "thrift/thrifty.yy" /* yacc.c:1646 */ { validate_simple_identifier( (yyvsp[-6].id)); (yyvsp[-4].tstruct)->set_name(std::string((yyvsp[-6].id)) + "_args"); (yyval.tfunction) = new t_function((yyvsp[-7].ttype), (yyvsp[-6].id), (yyvsp[-4].tstruct), (yyvsp[-2].tstruct), (yyvsp[-8].tbool)); if ((yyvsp[-9].dtext) != nullptr) { (yyval.tfunction)->set_doc((yyvsp[-9].dtext)); } if ((yyvsp[-1].ttype) != nullptr) { (yyval.tfunction)->annotations_ = (yyvsp[-1].ttype)->annotations_; delete (yyvsp[-1].ttype); } } #line 2268 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 64: #line 775 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = true; } #line 2276 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 65: #line 779 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = true; } #line 2284 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 66: #line 783 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = false; } #line 2292 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 67: #line 789 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("Throws -> tok_throws ( FieldList )"); (yyval.tstruct) = (yyvsp[-1].tstruct); if (g_parse_mode == PROGRAM && !validate_throws((yyval.tstruct))) { yyerror("Throws clause may not contain non-exception types"); exit(1); } } #line 2305 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 68: #line 798 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tstruct) = new t_struct(g_program); } #line 2313 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 69: #line 804 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldList -> FieldList , Field"); (yyval.tstruct) = (yyvsp[-1].tstruct); if (!((yyval.tstruct)->append((yyvsp[0].tfield)))) { yyerror("\"%d: %s\" - field identifier/name has already been used", (yyvsp[0].tfield)->get_key(), (yyvsp[0].tfield)->get_name().c_str()); exit(1); } } #line 2326 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 70: #line 813 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldList -> "); y_field_val = -1; (yyval.tstruct) = new t_struct(g_program); } #line 2336 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 71: #line 821 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("tok_int_constant : Field -> FieldType FieldName"); if ((yyvsp[-10].tfieldid).auto_assigned) { pwarning(1, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", (yyvsp[-6].id)); if (g_strict >= 192) { yyerror("Implicit field keys are deprecated and not allowed with -strict"); exit(1); } } validate_simple_identifier((yyvsp[-6].id)); (yyval.tfield) = new t_field((yyvsp[-8].ttype), (yyvsp[-6].id), (yyvsp[-10].tfieldid).value); (yyval.tfield)->set_reference((yyvsp[-7].tbool)); (yyval.tfield)->set_req((yyvsp[-9].ereq)); if ((yyvsp[-5].tconstv) != nullptr) { g_scope->resolve_const_value((yyvsp[-5].tconstv), (yyvsp[-8].ttype)); validate_field_value((yyval.tfield), (yyvsp[-5].tconstv)); (yyval.tfield)->set_value((yyvsp[-5].tconstv)); } (yyval.tfield)->set_xsd_optional((yyvsp[-4].tbool)); (yyval.tfield)->set_xsd_nillable((yyvsp[-3].tbool)); if ((yyvsp[-11].dtext) != nullptr) { (yyval.tfield)->set_doc((yyvsp[-11].dtext)); } if ((yyvsp[-2].tstruct) != nullptr) { (yyval.tfield)->set_xsd_attrs((yyvsp[-2].tstruct)); } if ((yyvsp[-1].ttype) != nullptr) { (yyval.tfield)->annotations_ = (yyvsp[-1].ttype)->annotations_; delete (yyvsp[-1].ttype); } } #line 2372 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 72: #line 855 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_identifier"); (yyval.id) = (yyvsp[0].id); } #line 2381 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 73: #line 860 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_namespace"); (yyval.id) = strdup("namespace"); } #line 2390 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 74: #line 865 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_cpp_include"); (yyval.id) = strdup("cpp_include"); } #line 2399 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 75: #line 877 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_include"); (yyval.id) = strdup("include"); } #line 2408 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 76: #line 882 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_void"); (yyval.id) = strdup("void"); } #line 2417 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 77: #line 887 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_bool"); (yyval.id) = strdup("bool"); } #line 2426 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 78: #line 892 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_byte"); (yyval.id) = strdup("byte"); } #line 2435 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 79: #line 897 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_i8"); (yyval.id) = strdup("i8"); } #line 2444 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 80: #line 902 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_i16"); (yyval.id) = strdup("i16"); } #line 2453 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 81: #line 907 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_i32"); (yyval.id) = strdup("i32"); } #line 2462 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 82: #line 912 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_i64"); (yyval.id) = strdup("i64"); } #line 2471 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 83: #line 917 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_double"); (yyval.id) = strdup("double"); } #line 2480 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 84: #line 922 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_string"); (yyval.id) = strdup("string"); } #line 2489 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 85: #line 927 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_binary"); (yyval.id) = strdup("binary"); } #line 2498 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 86: #line 932 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_uuid"); (yyval.id) = strdup("uuid"); } #line 2507 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 87: #line 937 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_map"); (yyval.id) = strdup("map"); } #line 2516 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 88: #line 942 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_list"); (yyval.id) = strdup("list"); } #line 2525 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 89: #line 947 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_set"); (yyval.id) = strdup("set"); } #line 2534 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 90: #line 952 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_oneway"); (yyval.id) = strdup("oneway"); } #line 2543 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 91: #line 957 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_async"); (yyval.id) = strdup("async"); } #line 2552 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 92: #line 962 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_typedef"); (yyval.id) = strdup("typedef"); } #line 2561 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 93: #line 967 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_struct"); (yyval.id) = strdup("struct"); } #line 2570 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 94: #line 972 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_union"); (yyval.id) = strdup("union"); } #line 2579 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 95: #line 977 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_xception"); (yyval.id) = strdup("exception"); } #line 2588 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 96: #line 982 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_extends"); (yyval.id) = strdup("extends"); } #line 2597 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 97: #line 987 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_throws"); (yyval.id) = strdup("throws"); } #line 2606 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 98: #line 992 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_service"); (yyval.id) = strdup("service"); } #line 2615 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 99: #line 997 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_enum"); (yyval.id) = strdup("enum"); } #line 2624 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 100: #line 1002 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_const"); (yyval.id) = strdup("const"); } #line 2633 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 101: #line 1007 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_required"); (yyval.id) = strdup("required"); } #line 2642 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 102: #line 1012 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldName -> tok_optional"); (yyval.id) = strdup("optional"); } #line 2651 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 103: #line 1020 "thrift/thrifty.yy" /* yacc.c:1646 */ { if ((yyvsp[-1].iconst) <= 0) { if (g_allow_neg_field_keys) { /* * g_allow_neg_field_keys exists to allow users to add explicitly * specified key values to old .thrift files without breaking * protocol compatibility. */ if ((yyvsp[-1].iconst) != y_field_val) { /* * warn if the user-specified negative value isn't what * thrift would have auto-assigned. */ pwarning(1, "Nonpositive field key (%" PRIi64") differs from what would be " "auto-assigned by thrift (%d).\n", (yyvsp[-1].iconst), y_field_val); } /* * Leave $1 as-is, and update y_field_val to be one less than $1. * The FieldList parsing will catch any duplicate key values. */ y_field_val = static_cast((yyvsp[-1].iconst) - 1); (yyval.tfieldid).value = static_cast((yyvsp[-1].iconst)); (yyval.tfieldid).auto_assigned = false; } else { pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n", (yyvsp[-1].iconst)); (yyval.tfieldid).value = y_field_val--; (yyval.tfieldid).auto_assigned = true; } } else { (yyval.tfieldid).value = static_cast((yyvsp[-1].iconst)); (yyval.tfieldid).auto_assigned = false; } if( (SHRT_MIN > (yyval.tfieldid).value) || ((yyval.tfieldid).value > SHRT_MAX)) { pwarning(1, "Field key (%d) exceeds allowed range (%d..%d).\n", (yyval.tfieldid).value, SHRT_MIN, SHRT_MAX); } } #line 2694 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 104: #line 1059 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tfieldid).value = y_field_val--; (yyval.tfieldid).auto_assigned = true; if( (SHRT_MIN > (yyval.tfieldid).value) || ((yyval.tfieldid).value > SHRT_MAX)) { pwarning(1, "Field key (%d) exceeds allowed range (%d..%d).\n", (yyval.tfieldid).value, SHRT_MIN, SHRT_MAX); } } #line 2707 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 105: #line 1070 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = true; } #line 2715 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 106: #line 1074 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tbool) = false; } #line 2723 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 107: #line 1080 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.ereq) = t_field::T_REQUIRED; } #line 2731 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 108: #line 1084 "thrift/thrifty.yy" /* yacc.c:1646 */ { if (g_arglist) { if (g_parse_mode == PROGRAM) { pwarning(1, "optional keyword is ignored in argument lists.\n"); } (yyval.ereq) = t_field::T_OPT_IN_REQ_OUT; } else { (yyval.ereq) = t_field::T_OPTIONAL; } } #line 2746 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 109: #line 1095 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.ereq) = t_field::T_OPT_IN_REQ_OUT; } #line 2754 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 110: #line 1101 "thrift/thrifty.yy" /* yacc.c:1646 */ { if (g_parse_mode == PROGRAM) { (yyval.tconstv) = (yyvsp[0].tconstv); } else { (yyval.tconstv) = nullptr; } } #line 2766 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 111: #line 1109 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.tconstv) = nullptr; } #line 2774 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 112: #line 1115 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FunctionType -> FieldType"); (yyval.ttype) = (yyvsp[0].ttype); } #line 2783 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 113: #line 1120 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FunctionType -> tok_void"); (yyval.ttype) = g_type_void; } #line 2792 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 114: #line 1127 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldType -> tok_identifier"); if (g_parse_mode == INCLUDES) { // Ignore identifiers in include mode (yyval.ttype) = nullptr; } else { // Lookup the identifier in the current scope (yyval.ttype) = g_scope->get_type((yyvsp[0].id)); if ((yyval.ttype) == nullptr) { /* * Either this type isn't yet declared, or it's never declared. Either way allow it and we'll figure it out during generation. */ (yyval.ttype) = new t_typedef(g_program, (yyvsp[0].id), true); } } } #line 2815 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 115: #line 1146 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldType -> BaseType"); (yyval.ttype) = (yyvsp[0].ttype); } #line 2824 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 116: #line 1151 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("FieldType -> ContainerType"); (yyval.ttype) = (yyvsp[0].ttype); } #line 2833 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 117: #line 1157 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> SimpleBaseType TypeAnnotations"); if ((yyvsp[0].ttype) != nullptr) { (yyval.ttype) = new t_base_type(*static_cast((yyvsp[-1].ttype))); (yyval.ttype)->annotations_ = (yyvsp[0].ttype)->annotations_; delete (yyvsp[0].ttype); } else { (yyval.ttype) = (yyvsp[-1].ttype); } } #line 2848 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 118: #line 1170 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_string"); (yyval.ttype) = g_type_string; } #line 2857 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 119: #line 1175 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_binary"); (yyval.ttype) = g_type_binary; } #line 2866 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 120: #line 1180 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_uuid"); (yyval.ttype) = g_type_uuid; } #line 2875 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 121: #line 1185 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_bool"); (yyval.ttype) = g_type_bool; } #line 2884 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 122: #line 1190 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_byte"); (yyval.ttype) = g_type_i8; // byte is signed in Thrift, just an alias for i8 } #line 2893 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 123: #line 1195 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_i8"); (yyval.ttype) = g_type_i8; } #line 2902 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 124: #line 1200 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_i16"); (yyval.ttype) = g_type_i16; } #line 2911 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 125: #line 1205 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_i32"); (yyval.ttype) = g_type_i32; } #line 2920 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 126: #line 1210 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_i64"); (yyval.ttype) = g_type_i64; } #line 2929 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 127: #line 1215 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("BaseType -> tok_double"); (yyval.ttype) = g_type_double; } #line 2938 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 128: #line 1221 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ContainerType -> SimpleContainerType TypeAnnotations"); (yyval.ttype) = (yyvsp[-1].ttype); if ((yyvsp[0].ttype) != nullptr) { (yyval.ttype)->annotations_ = (yyvsp[0].ttype)->annotations_; delete (yyvsp[0].ttype); } } #line 2951 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 129: #line 1232 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("SimpleContainerType -> MapType"); (yyval.ttype) = (yyvsp[0].ttype); } #line 2960 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 130: #line 1237 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("SimpleContainerType -> SetType"); (yyval.ttype) = (yyvsp[0].ttype); } #line 2969 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 131: #line 1242 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("SimpleContainerType -> ListType"); (yyval.ttype) = (yyvsp[0].ttype); } #line 2978 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 132: #line 1249 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("MapType -> tok_map "); (yyval.ttype) = new t_map((yyvsp[-3].ttype), (yyvsp[-1].ttype)); if ((yyvsp[-5].id) != nullptr) { ((t_container*)(yyval.ttype))->set_cpp_name(std::string((yyvsp[-5].id))); } } #line 2990 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 133: #line 1259 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("SetType -> tok_set"); (yyval.ttype) = new t_set((yyvsp[-1].ttype)); if ((yyvsp[-3].id) != nullptr) { ((t_container*)(yyval.ttype))->set_cpp_name(std::string((yyvsp[-3].id))); } } #line 3002 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 134: #line 1269 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("ListType -> tok_list"); check_for_list_of_bytes((yyvsp[-2].ttype)); (yyval.ttype) = new t_list((yyvsp[-2].ttype)); if ((yyvsp[-4].id) != nullptr) { ((t_container*)(yyval.ttype))->set_cpp_name(std::string((yyvsp[-4].id))); } if ((yyvsp[0].id) != nullptr) { ((t_container*)(yyval.ttype))->set_cpp_name(std::string((yyvsp[0].id))); pwarning(1, "The syntax 'list cpp_type \"c++ type\"' is deprecated. Use 'list cpp_type \"c++ type\" ' instead.\n"); } if (((yyvsp[-4].id) != nullptr) && ((yyvsp[0].id) != nullptr)) { pwarning(1, "Two cpp_types clauses at list<%>\n", (yyvsp[-4].id)); } } #line 3022 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 135: #line 1287 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.id) = (yyvsp[0].id); } #line 3030 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 136: #line 1291 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.id) = nullptr; } #line 3038 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 137: #line 1297 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeAnnotations -> ( TypeAnnotationList )"); (yyval.ttype) = (yyvsp[-1].ttype); } #line 3047 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 138: #line 1302 "thrift/thrifty.yy" /* yacc.c:1646 */ { (yyval.ttype) = nullptr; } #line 3055 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 139: #line 1308 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation"); (yyval.ttype) = (yyvsp[-1].ttype); (yyval.ttype)->annotations_[(yyvsp[0].tannot)->key].push_back((yyvsp[0].tannot)->val); delete (yyvsp[0].tannot); } #line 3066 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 140: #line 1315 "thrift/thrifty.yy" /* yacc.c:1646 */ { /* Just use a dummy structure to hold the annotations. */ (yyval.ttype) = new t_struct(g_program); } #line 3075 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 141: #line 1322 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeAnnotation -> TypeAnnotationValue"); (yyval.tannot) = new t_annotation; (yyval.tannot)->key = (yyvsp[-2].id); (yyval.tannot)->val = (yyvsp[-1].id); } #line 3086 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 142: #line 1331 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeAnnotationValue -> = tok_literal"); (yyval.id) = (yyvsp[0].id); } #line 3095 "thrift/thrifty.cc" /* yacc.c:1646 */ break; case 143: #line 1336 "thrift/thrifty.yy" /* yacc.c:1646 */ { pdebug("TypeAnnotationValue ->"); (yyval.id) = strdup("1"); } #line 3104 "thrift/thrifty.cc" /* yacc.c:1646 */ break; #line 3108 "thrift/thrifty.cc" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) { char const *yymsgp = YY_("syntax error"); int yysyntax_error_status; yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; yysyntax_error_status = 2; } else { yysyntax_error_status = YYSYNTAX_ERROR; yymsgp = yymsg; } } yyerror (yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } # undef YYSYNTAX_ERROR #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif return yyresult; } #line 1341 "thrift/thrifty.yy" /* yacc.c:1906 */ thrift-0.19.0/compiler/cpp/src/thrift/main.h0000644000000000000000000000542214303740367020671 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_MAIN_H #define T_MAIN_H #include #include #include "thrift/logging.h" #include "thrift/parse/t_const.h" #include "thrift/parse/t_field.h" /** * Defined in the flex library */ extern "C" { int yylex(void); } int yyparse(void); /** * Expected to be defined by Flex/Bison */ void yyerror(const char* fmt, ...); /** * Check simple identifier names */ void validate_simple_identifier(const char* identifier); /** * Check constant types */ void validate_const_type(t_const* c); /** * Check constant types */ void validate_field_value(t_field* field, t_const_value* cv); /** * Check members of a throws block */ bool validate_throws(t_struct* throws); /** * Converts a string filename into a thrift program name */ std::string program_name(std::string filename); /** * Gets the directory path of a filename */ std::string directory_name(std::string filename); /** * Get the absolute path for an include file */ std::string include_file(std::string filename); /** * Clears any previously stored doctext string. */ void clear_doctext(); /** * Cleans up text commonly found in doxygen-like comments */ char* clean_up_doctext(char* doctext); /** * We are sure the program doctext candidate is really the program doctext. */ void declare_valid_program_doctext(); /** * Emits a warning on list, binary type is typically a much better choice. */ void check_for_list_of_bytes(t_type* list_elem_type); /** * Emits a one-time warning on byte type, promoting the new i8 type instead */ void emit_byte_type_warning(); /** * Prints deprecation notice for old NS declarations that are no longer supported * If new_form is nullptr, old_form is assumed to be a language identifier, such as "cpp" * If new_form is not nullptr, both arguments are used exactly as given */ void error_unsupported_namespace_decl(const char* old_form, const char* new_form = nullptr); /** * Flex utilities */ extern int yylineno; extern char yytext[]; extern std::FILE* yyin; #endif thrift-0.19.0/compiler/cpp/src/thrift/globals.h0000644000000000000000000000745014303740367021373 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_GLOBALS_H #define T_GLOBALS_H #include #include #include #include #include /** * This module contains all the global variables (slap on the wrist) that are * shared throughout the program. The reason for this is to facilitate simple * interaction between the parser and the rest of the program. Before calling * yyparse(), the main.cc program will make necessary adjustments to these * global variables such that the parser does the right thing and puts entries * into the right containers, etc. * */ /** * Hooray for forward declaration of types! */ class t_program; class t_scope; class t_type; /** * Parsing mode, two passes up in this gin rummy! */ enum PARSE_MODE { INCLUDES = 1, PROGRAM = 2 }; /** * Strictness level */ extern int g_strict; /** * The master program parse tree. This is accessed from within the parser code * to build up the program elements. */ extern t_program* g_program; /** * The scope that we are currently parsing into */ extern t_scope* g_scope; /** * The parent scope to also load symbols into */ extern t_scope* g_parent_scope; /** * The prefix for the parent scope entries */ extern std::string g_parent_prefix; /** * The parsing pass that we are on. We do different things on each pass. */ extern PARSE_MODE g_parse_mode; /** * Global time string, used in formatting error messages etc. */ extern char* g_time_str; /** * The last parsed doctext comment. */ extern char* g_doctext; /** * The location of the last parsed doctext comment. */ extern int g_doctext_lineno; /** * Status of program level doctext candidate */ enum PROGDOCTEXT_STATUS { INVALID = 0, STILL_CANDIDATE = 1, // the text may or may not be the program doctext ALREADY_PROCESSED = 2, // doctext has been used and is no longer available ABSOLUTELY_SURE = 3, // this is the program doctext NO_PROGRAM_DOCTEXT = 4 // there is no program doctext }; /** * The program level doctext. Stored separately to make parsing easier. */ extern char* g_program_doctext_candidate; extern int g_program_doctext_lineno; extern PROGDOCTEXT_STATUS g_program_doctext_status; /** * Whether or not negative field keys are accepted. * * When a field does not have a user-specified key, thrift automatically * assigns a negative value. However, this is fragile since changes to the * file may unintentionally change the key numbering, resulting in a new * protocol that is not backwards compatible. * * When g_allow_neg_field_keys is enabled, users can explicitly specify * negative keys. This way they can write a .thrift file with explicitly * specified keys that is still backwards compatible with older .thrift files * that did not specify key values. */ extern int g_allow_neg_field_keys; /** * Whether or not 64-bit constants will generate a warning. * * Some languages don't support 64-bit constants, but many do, so we can * suppress this warning for projects that don't use any non-64-bit-safe * languages. */ extern int g_allow_64bit_consts; #endif thrift-0.19.0/compiler/cpp/src/thrift/common.h0000644000000000000000000000237114370300523021223 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_COMMON_H #define T_COMMON_H #include "thrift/parse/t_type.h" /** * Global types for the parser to be able to reference */ extern t_type* g_type_void; extern t_type* g_type_string; extern t_type* g_type_binary; extern t_type* g_type_uuid; extern t_type* g_type_bool; extern t_type* g_type_i8; extern t_type* g_type_i16; extern t_type* g_type_i32; extern t_type* g_type_i64; extern t_type* g_type_double; void initGlobals(); void clearGlobals(); #endif thrift-0.19.0/compiler/cpp/src/thrift/logging.cc0000644000000000000000000000341714303740367021533 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "thrift/logging.h" #include "thrift/globals.h" #include #include #include int g_debug = 0; int g_warn = 1; int g_verbose = 0; void pdebug(const char* fmt, ...) { if (g_debug == 0) { return; } va_list args; // printf("[PARSE:%d] ", yylineno); va_start(args, fmt); vprintf(fmt, args); va_end(args); printf("\n"); } void pverbose(const char* fmt, ...) { if (g_verbose == 0) { return; } va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); } void pwarning(int level, const char* fmt, ...) { if (g_warn < level) { return; } va_list args; // printf("[WARNING:%s:%d] ", g_curpath.c_str(), yylineno); va_start(args, fmt); vprintf(fmt, args); va_end(args); printf("\n"); } void failure(const char* fmt, ...) { va_list args; // fprintf(stderr, "[FAILURE:%s:%d] ", g_curpath.c_str(), yylineno); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); printf("\n"); exit(1); } thrift-0.19.0/compiler/cpp/src/thrift/thrifty.yy0000644000000000000000000007413414370300523021644 0ustar00rootroot00000000000000%code requires { #include "thrift/parse/t_program.h" } %{ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * Thrift parser. * * This parser is used on a thrift definition file. * */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS #endif #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS #endif #include #include #ifndef _MSC_VER #include #else #include #endif #include #ifdef _MSC_VER #include "thrift/windows/config.h" #endif #include "thrift/main.h" #include "thrift/common.h" #include "thrift/globals.h" #include "thrift/parse/t_program.h" #include "thrift/parse/t_scope.h" #ifdef _MSC_VER //warning C4065: switch statement contains 'default' but no 'case' labels #pragma warning(disable:4065) #endif /** * This global variable is used for automatic numbering of field indices etc. * when parsing the members of a struct. Field values are automatically * assigned starting from -1 and working their way down. */ int y_field_val = -1; /** * This global variable is used for automatic numbering of enum values. * y_enum_val is the last value assigned; the next auto-assigned value will be * y_enum_val+1, and then it continues working upwards. Explicitly specified * enum values reset y_enum_val to that value. */ int32_t y_enum_val = -1; int g_arglist = 0; const int struct_is_struct = 0; const int struct_is_union = 1; %} /** * This structure is used by the parser to hold the data types associated with * various parse nodes. */ %union { char* id; int64_t iconst; double dconst; bool tbool; t_doc* tdoc; t_type* ttype; t_base_type* tbase; t_typedef* ttypedef; t_enum* tenum; t_enum_value* tenumv; t_const* tconst; t_const_value* tconstv; t_struct* tstruct; t_service* tservice; t_function* tfunction; t_field* tfield; char* dtext; char* keyword; t_field::e_req ereq; t_annotation* tannot; t_field_id tfieldid; } /** * Strings identifier */ %token tok_identifier %token tok_literal %token tok_doctext /** * Constant values */ %token tok_int_constant %token tok_dub_constant /** * Header keywords */ %token tok_include %token tok_namespace %token tok_cpp_include %token tok_cpp_type %token tok_xsd_all %token tok_xsd_optional %token tok_xsd_nillable %token tok_xsd_attrs /** * Base datatype keywords */ %token tok_void %token tok_bool %token tok_string %token tok_binary %token tok_uuid %token tok_byte %token tok_i8 %token tok_i16 %token tok_i32 %token tok_i64 %token tok_double /** * Complex type keywords */ %token tok_map %token tok_list %token tok_set /** * Function modifiers */ %token tok_oneway %token tok_async /** * Thrift language keywords */ %token tok_typedef %token tok_struct %token tok_xception %token tok_throws %token tok_extends %token tok_service %token tok_enum %token tok_const %token tok_required %token tok_optional %token tok_union %token tok_reference /** * Grammar nodes */ %type BaseType %type SimpleBaseType %type ContainerType %type SimpleContainerType %type MapType %type SetType %type ListType %type Definition %type TypeDefinition %type Typedef %type TypeAnnotations %type TypeAnnotationList %type TypeAnnotation %type TypeAnnotationValue %type Field %type FieldIdentifier %type FieldName %type FieldRequiredness %type FieldType %type FieldValue %type FieldList %type FieldReference %type Enum %type EnumDefList %type EnumDef %type EnumValue %type Const %type ConstValue %type ConstList %type ConstListContents %type ConstMap %type ConstMapContents %type StructHead %type Struct %type Xception %type Service %type Function %type FunctionType %type FunctionList %type Throws %type Extends %type Oneway %type XsdAll %type XsdOptional %type XsdNillable %type XsdAttributes %type CppType %type CaptureDocText %% /** * Thrift Grammar Implementation. * * For the most part this source file works its way top down from what you * might expect to find in a typical .thrift file, i.e. type definitions and * namespaces up top followed by service definitions using those types. */ Program: HeaderList DefinitionList { pdebug("Program -> Headers DefinitionList"); if((g_program_doctext_candidate != nullptr) && (g_program_doctext_status != ALREADY_PROCESSED)) { g_program->set_doc(g_program_doctext_candidate); g_program_doctext_status = ALREADY_PROCESSED; } clear_doctext(); } CaptureDocText: { if (g_parse_mode == PROGRAM) { $$ = g_doctext; g_doctext = nullptr; } else { $$ = nullptr; } } /* TODO(dreiss): Try to DestroyDocText in all sorts or random places. */ DestroyDocText: { if (g_parse_mode == PROGRAM) { clear_doctext(); } } /* We have to DestroyDocText here, otherwise it catches the doctext on the first real element. */ HeaderList: HeaderList DestroyDocText Header { pdebug("HeaderList -> HeaderList Header"); } | { pdebug("HeaderList -> "); } Header: Include { pdebug("Header -> Include"); } | tok_namespace tok_identifier tok_identifier TypeAnnotations { pdebug("Header -> tok_namespace tok_identifier tok_identifier"); declare_valid_program_doctext(); if (g_parse_mode == PROGRAM) { g_program->set_namespace($2, $3); } if ($4 != nullptr) { g_program->set_namespace_annotations($2, $4->annotations_); delete $4; } } | tok_namespace '*' tok_identifier { pdebug("Header -> tok_namespace * tok_identifier"); declare_valid_program_doctext(); if (g_parse_mode == PROGRAM) { g_program->set_namespace("*", $3); } } | tok_cpp_include tok_literal { pdebug("Header -> tok_cpp_include tok_literal"); declare_valid_program_doctext(); if (g_parse_mode == PROGRAM) { g_program->add_cpp_include($2); } } Include: tok_include tok_literal { pdebug("Include -> tok_include tok_literal"); declare_valid_program_doctext(); if (g_parse_mode == INCLUDES) { std::string path = include_file(std::string($2)); if (!path.empty()) { g_program->add_include(path, std::string($2)); } } } DefinitionList: DefinitionList CaptureDocText Definition { pdebug("DefinitionList -> DefinitionList Definition"); if ($2 != nullptr && $3 != nullptr) { $3->set_doc($2); } } | { pdebug("DefinitionList -> "); } Definition: Const { pdebug("Definition -> Const"); if (g_parse_mode == PROGRAM) { g_program->add_const($1); } $$ = $1; } | TypeDefinition { pdebug("Definition -> TypeDefinition"); if (g_parse_mode == PROGRAM) { g_scope->add_type($1->get_name(), $1); if (g_parent_scope != nullptr) { g_parent_scope->add_type(g_parent_prefix + $1->get_name(), $1); } if (! g_program->is_unique_typename($1)) { yyerror("Type \"%s\" is already defined.", $1->get_name().c_str()); exit(1); } } $$ = $1; } | Service { pdebug("Definition -> Service"); if (g_parse_mode == PROGRAM) { g_scope->add_service($1->get_name(), $1); if (g_parent_scope != nullptr) { g_parent_scope->add_service(g_parent_prefix + $1->get_name(), $1); } g_program->add_service($1); if (! g_program->is_unique_typename($1)) { yyerror("Type \"%s\" is already defined.", $1->get_name().c_str()); exit(1); } } $$ = $1; } TypeDefinition: Typedef { pdebug("TypeDefinition -> Typedef"); if (g_parse_mode == PROGRAM) { g_program->add_typedef($1); } } | Enum { pdebug("TypeDefinition -> Enum"); if (g_parse_mode == PROGRAM) { g_program->add_enum($1); } } | Struct { pdebug("TypeDefinition -> Struct"); if (g_parse_mode == PROGRAM) { g_program->add_struct($1); } } | Xception { pdebug("TypeDefinition -> Xception"); if (g_parse_mode == PROGRAM) { g_program->add_xception($1); } } CommaOrSemicolonOptional: ',' {} | ';' {} | {} Typedef: tok_typedef FieldType tok_identifier TypeAnnotations CommaOrSemicolonOptional { pdebug("TypeDef -> tok_typedef FieldType tok_identifier"); validate_simple_identifier( $3); t_typedef *td = new t_typedef(g_program, $2, $3); $$ = td; if ($4 != nullptr) { $$->annotations_ = $4->annotations_; delete $4; } } Enum: tok_enum tok_identifier '{' EnumDefList '}' TypeAnnotations { pdebug("Enum -> tok_enum tok_identifier { EnumDefList }"); $$ = $4; validate_simple_identifier( $2); $$->set_name($2); if ($6 != nullptr) { $$->annotations_ = $6->annotations_; delete $6; } // make constants for all the enum values if (g_parse_mode == PROGRAM) { const std::vector& enum_values = $$->get_constants(); std::vector::const_iterator c_iter; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { std::string const_name = $$->get_name() + "." + (*c_iter)->get_name(); t_const_value* const_val = new t_const_value((*c_iter)->get_value()); const_val->set_enum($$); g_scope->add_constant(const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val)); if (g_parent_scope != nullptr) { g_parent_scope->add_constant(g_parent_prefix + const_name, new t_const(g_type_i32, (*c_iter)->get_name(), const_val)); } } } } EnumDefList: EnumDefList EnumDef { pdebug("EnumDefList -> EnumDefList EnumDef"); $$ = $1; $$->append($2); } | { pdebug("EnumDefList -> "); $$ = new t_enum(g_program); y_enum_val = -1; } EnumDef: CaptureDocText EnumValue TypeAnnotations CommaOrSemicolonOptional { pdebug("EnumDef -> EnumValue"); $$ = $2; if ($1 != nullptr) { $$->set_doc($1); } if ($3 != nullptr) { $$->annotations_ = $3->annotations_; delete $3; } } EnumValue: tok_identifier '=' tok_int_constant { pdebug("EnumValue -> tok_identifier = tok_int_constant"); if ($3 < INT32_MIN || $3 > INT32_MAX) { // Note: this used to be just a warning. However, since thrift always // treats enums as i32 values, I'm changing it to a fatal error. // I doubt this will affect many people, but users who run into this // will have to update their thrift files to manually specify the // truncated i32 value that thrift has always been using anyway. failure("64-bit value supplied for enum %s will be truncated.", $1); } y_enum_val = static_cast($3); $$ = new t_enum_value($1, y_enum_val); } | tok_identifier { pdebug("EnumValue -> tok_identifier"); validate_simple_identifier( $1); if (y_enum_val == INT32_MAX) { failure("enum value overflow at enum %s", $1); } ++y_enum_val; $$ = new t_enum_value($1, y_enum_val); } Const: tok_const FieldType tok_identifier '=' ConstValue CommaOrSemicolonOptional { pdebug("Const -> tok_const FieldType tok_identifier = ConstValue"); if (g_parse_mode == PROGRAM) { validate_simple_identifier( $3); g_scope->resolve_const_value($5, $2); $$ = new t_const($2, $3, $5); validate_const_type($$); g_scope->add_constant($3, $$); if (g_parent_scope != nullptr) { g_parent_scope->add_constant(g_parent_prefix + $3, $$); } } else { $$ = nullptr; } } ConstValue: tok_int_constant { pdebug("ConstValue => tok_int_constant"); $$ = new t_const_value(); $$->set_integer($1); if (!g_allow_64bit_consts && ($1 < INT32_MIN || $1 > INT32_MAX)) { pwarning(1, "64-bit constant \"%" PRIi64"\" may not work in all languages.\n", $1); } } | tok_dub_constant { pdebug("ConstValue => tok_dub_constant"); $$ = new t_const_value(); $$->set_double($1); } | tok_literal { pdebug("ConstValue => tok_literal"); $$ = new t_const_value($1); } | tok_identifier { pdebug("ConstValue => tok_identifier"); $$ = new t_const_value(); $$->set_identifier($1); } | ConstList { pdebug("ConstValue => ConstList"); $$ = $1; } | ConstMap { pdebug("ConstValue => ConstMap"); $$ = $1; } ConstList: '[' ConstListContents ']' { pdebug("ConstList => [ ConstListContents ]"); $$ = $2; } ConstListContents: ConstListContents ConstValue CommaOrSemicolonOptional { pdebug("ConstListContents => ConstListContents ConstValue CommaOrSemicolonOptional"); $$ = $1; $$->add_list($2); } | { pdebug("ConstListContents =>"); $$ = new t_const_value(); $$->set_list(); } ConstMap: '{' ConstMapContents '}' { pdebug("ConstMap => { ConstMapContents }"); $$ = $2; } ConstMapContents: ConstMapContents ConstValue ':' ConstValue CommaOrSemicolonOptional { pdebug("ConstMapContents => ConstMapContents ConstValue CommaOrSemicolonOptional"); $$ = $1; $$->add_map($2, $4); } | { pdebug("ConstMapContents =>"); $$ = new t_const_value(); $$->set_map(); } StructHead: tok_struct { $$ = struct_is_struct; } | tok_union { $$ = struct_is_union; } Struct: StructHead tok_identifier XsdAll '{' FieldList '}' TypeAnnotations { pdebug("Struct -> tok_struct tok_identifier { FieldList }"); validate_simple_identifier( $2); $5->set_xsd_all($3); $5->set_union($1 == struct_is_union); $$ = $5; $$->set_name($2); if ($7 != nullptr) { $$->annotations_ = $7->annotations_; delete $7; } } XsdAll: tok_xsd_all { $$ = true; } | { $$ = false; } XsdOptional: tok_xsd_optional { $$ = true; } | { $$ = false; } XsdNillable: tok_xsd_nillable { $$ = true; } | { $$ = false; } XsdAttributes: tok_xsd_attrs '{' FieldList '}' { $$ = $3; } | { $$ = nullptr; } Xception: tok_xception tok_identifier '{' FieldList '}' TypeAnnotations { pdebug("Xception -> tok_xception tok_identifier { FieldList }"); validate_simple_identifier( $2); $4->set_name($2); $4->set_xception(true); $$ = $4; if ($6 != nullptr) { $$->annotations_ = $6->annotations_; delete $6; } } Service: tok_service tok_identifier Extends '{' FlagArgs FunctionList UnflagArgs '}' TypeAnnotations { pdebug("Service -> tok_service tok_identifier { FunctionList }"); validate_simple_identifier( $2); $$ = $6; $$->set_name($2); $$->set_extends($3); if ($9 != nullptr) { $$->annotations_ = $9->annotations_; delete $9; } } FlagArgs: { g_arglist = 1; } UnflagArgs: { g_arglist = 0; } Extends: tok_extends tok_identifier { pdebug("Extends -> tok_extends tok_identifier"); $$ = nullptr; if (g_parse_mode == PROGRAM) { $$ = g_scope->get_service($2); if ($$ == nullptr) { yyerror("Service \"%s\" has not been defined.", $2); exit(1); } } } | { $$ = nullptr; } FunctionList: FunctionList Function { pdebug("FunctionList -> FunctionList Function"); $$ = $1; $1->add_function($2); } | { pdebug("FunctionList -> "); $$ = new t_service(g_program); } Function: CaptureDocText Oneway FunctionType tok_identifier '(' FieldList ')' Throws TypeAnnotations CommaOrSemicolonOptional { validate_simple_identifier( $4); $6->set_name(std::string($4) + "_args"); $$ = new t_function($3, $4, $6, $8, $2); if ($1 != nullptr) { $$->set_doc($1); } if ($9 != nullptr) { $$->annotations_ = $9->annotations_; delete $9; } } Oneway: tok_oneway { $$ = true; } | tok_async // deprecated { $$ = true; } | { $$ = false; } Throws: tok_throws '(' FieldList ')' { pdebug("Throws -> tok_throws ( FieldList )"); $$ = $3; if (g_parse_mode == PROGRAM && !validate_throws($$)) { yyerror("Throws clause may not contain non-exception types"); exit(1); } } | { $$ = new t_struct(g_program); } FieldList: FieldList Field { pdebug("FieldList -> FieldList , Field"); $$ = $1; if (!($$->append($2))) { yyerror("\"%d: %s\" - field identifier/name has already been used", $2->get_key(), $2->get_name().c_str()); exit(1); } } | { pdebug("FieldList -> "); y_field_val = -1; $$ = new t_struct(g_program); } Field: CaptureDocText FieldIdentifier FieldRequiredness FieldType FieldReference FieldName FieldValue XsdOptional XsdNillable XsdAttributes TypeAnnotations CommaOrSemicolonOptional { pdebug("tok_int_constant : Field -> FieldType FieldName"); if ($2.auto_assigned) { pwarning(1, "No field key specified for %s, resulting protocol may have conflicts or not be backwards compatible!\n", $6); if (g_strict >= 192) { yyerror("Implicit field keys are deprecated and not allowed with -strict"); exit(1); } } validate_simple_identifier($6); $$ = new t_field($4, $6, $2.value); $$->set_reference($5); $$->set_req($3); if ($7 != nullptr) { g_scope->resolve_const_value($7, $4); validate_field_value($$, $7); $$->set_value($7); } $$->set_xsd_optional($8); $$->set_xsd_nillable($9); if ($1 != nullptr) { $$->set_doc($1); } if ($10 != nullptr) { $$->set_xsd_attrs($10); } if ($11 != nullptr) { $$->annotations_ = $11->annotations_; delete $11; } } FieldName: // identifiers and everything that could be one if it would not be identified as a different token already and excluding the "xsd*" keywords to follow a FieldName tok_identifier { pdebug("FieldName -> tok_identifier"); $$ = $1; } | tok_namespace { pdebug("FieldName -> tok_namespace"); $$ = strdup("namespace"); } | tok_cpp_include { pdebug("FieldName -> tok_cpp_include"); $$ = strdup("cpp_include"); } /* see THRIFT-5627 "More consistent syntax for cpp_type" -> activate when this issue is resolved | tok_cpp_type { pdebug("FieldName -> tok_cpp_type"); $$ = $strdup("cpp_type"); } */ | tok_include { pdebug("FieldName -> tok_include"); $$ = strdup("include"); } | tok_void { pdebug("FieldName -> tok_void"); $$ = strdup("void"); } | tok_bool { pdebug("FieldName -> tok_bool"); $$ = strdup("bool"); } | tok_byte { pdebug("FieldName -> tok_byte"); $$ = strdup("byte"); } | tok_i8 { pdebug("FieldName -> tok_i8"); $$ = strdup("i8"); } | tok_i16 { pdebug("FieldName -> tok_i16"); $$ = strdup("i16"); } | tok_i32 { pdebug("FieldName -> tok_i32"); $$ = strdup("i32"); } | tok_i64 { pdebug("FieldName -> tok_i64"); $$ = strdup("i64"); } | tok_double { pdebug("FieldName -> tok_double"); $$ = strdup("double"); } | tok_string { pdebug("FieldName -> tok_string"); $$ = strdup("string"); } | tok_binary { pdebug("FieldName -> tok_binary"); $$ = strdup("binary"); } | tok_uuid { pdebug("FieldName -> tok_uuid"); $$ = strdup("uuid"); } | tok_map { pdebug("FieldName -> tok_map"); $$ = strdup("map"); } | tok_list { pdebug("FieldName -> tok_list"); $$ = strdup("list"); } | tok_set { pdebug("FieldName -> tok_set"); $$ = strdup("set"); } | tok_oneway { pdebug("FieldName -> tok_oneway"); $$ = strdup("oneway"); } | tok_async { pdebug("FieldName -> tok_async"); $$ = strdup("async"); } | tok_typedef { pdebug("FieldName -> tok_typedef"); $$ = strdup("typedef"); } | tok_struct { pdebug("FieldName -> tok_struct"); $$ = strdup("struct"); } | tok_union { pdebug("FieldName -> tok_union"); $$ = strdup("union"); } | tok_xception { pdebug("FieldName -> tok_xception"); $$ = strdup("exception"); } | tok_extends { pdebug("FieldName -> tok_extends"); $$ = strdup("extends"); } | tok_throws { pdebug("FieldName -> tok_throws"); $$ = strdup("throws"); } | tok_service { pdebug("FieldName -> tok_service"); $$ = strdup("service"); } | tok_enum { pdebug("FieldName -> tok_enum"); $$ = strdup("enum"); } | tok_const { pdebug("FieldName -> tok_const"); $$ = strdup("const"); } | tok_required { pdebug("FieldName -> tok_required"); $$ = strdup("required"); } | tok_optional { pdebug("FieldName -> tok_optional"); $$ = strdup("optional"); } FieldIdentifier: tok_int_constant ':' { if ($1 <= 0) { if (g_allow_neg_field_keys) { /* * g_allow_neg_field_keys exists to allow users to add explicitly * specified key values to old .thrift files without breaking * protocol compatibility. */ if ($1 != y_field_val) { /* * warn if the user-specified negative value isn't what * thrift would have auto-assigned. */ pwarning(1, "Nonpositive field key (%" PRIi64") differs from what would be " "auto-assigned by thrift (%d).\n", $1, y_field_val); } /* * Leave $1 as-is, and update y_field_val to be one less than $1. * The FieldList parsing will catch any duplicate key values. */ y_field_val = static_cast($1 - 1); $$.value = static_cast($1); $$.auto_assigned = false; } else { pwarning(1, "Nonpositive value (%d) not allowed as a field key.\n", $1); $$.value = y_field_val--; $$.auto_assigned = true; } } else { $$.value = static_cast($1); $$.auto_assigned = false; } if( (SHRT_MIN > $$.value) || ($$.value > SHRT_MAX)) { pwarning(1, "Field key (%d) exceeds allowed range (%d..%d).\n", $$.value, SHRT_MIN, SHRT_MAX); } } | { $$.value = y_field_val--; $$.auto_assigned = true; if( (SHRT_MIN > $$.value) || ($$.value > SHRT_MAX)) { pwarning(1, "Field key (%d) exceeds allowed range (%d..%d).\n", $$.value, SHRT_MIN, SHRT_MAX); } } FieldReference: tok_reference { $$ = true; } | { $$ = false; } FieldRequiredness: tok_required { $$ = t_field::T_REQUIRED; } | tok_optional { if (g_arglist) { if (g_parse_mode == PROGRAM) { pwarning(1, "optional keyword is ignored in argument lists.\n"); } $$ = t_field::T_OPT_IN_REQ_OUT; } else { $$ = t_field::T_OPTIONAL; } } | { $$ = t_field::T_OPT_IN_REQ_OUT; } FieldValue: '=' ConstValue { if (g_parse_mode == PROGRAM) { $$ = $2; } else { $$ = nullptr; } } | { $$ = nullptr; } FunctionType: FieldType { pdebug("FunctionType -> FieldType"); $$ = $1; } | tok_void { pdebug("FunctionType -> tok_void"); $$ = g_type_void; } FieldType: tok_identifier { pdebug("FieldType -> tok_identifier"); if (g_parse_mode == INCLUDES) { // Ignore identifiers in include mode $$ = nullptr; } else { // Lookup the identifier in the current scope $$ = g_scope->get_type($1); if ($$ == nullptr) { /* * Either this type isn't yet declared, or it's never declared. Either way allow it and we'll figure it out during generation. */ $$ = new t_typedef(g_program, $1, true); } } } | BaseType { pdebug("FieldType -> BaseType"); $$ = $1; } | ContainerType { pdebug("FieldType -> ContainerType"); $$ = $1; } BaseType: SimpleBaseType TypeAnnotations { pdebug("BaseType -> SimpleBaseType TypeAnnotations"); if ($2 != nullptr) { $$ = new t_base_type(*static_cast($1)); $$->annotations_ = $2->annotations_; delete $2; } else { $$ = $1; } } SimpleBaseType: tok_string { pdebug("BaseType -> tok_string"); $$ = g_type_string; } | tok_binary { pdebug("BaseType -> tok_binary"); $$ = g_type_binary; } | tok_uuid { pdebug("BaseType -> tok_uuid"); $$ = g_type_uuid; } | tok_bool { pdebug("BaseType -> tok_bool"); $$ = g_type_bool; } | tok_byte { pdebug("BaseType -> tok_byte"); $$ = g_type_i8; // byte is signed in Thrift, just an alias for i8 } | tok_i8 { pdebug("BaseType -> tok_i8"); $$ = g_type_i8; } | tok_i16 { pdebug("BaseType -> tok_i16"); $$ = g_type_i16; } | tok_i32 { pdebug("BaseType -> tok_i32"); $$ = g_type_i32; } | tok_i64 { pdebug("BaseType -> tok_i64"); $$ = g_type_i64; } | tok_double { pdebug("BaseType -> tok_double"); $$ = g_type_double; } ContainerType: SimpleContainerType TypeAnnotations { pdebug("ContainerType -> SimpleContainerType TypeAnnotations"); $$ = $1; if ($2 != nullptr) { $$->annotations_ = $2->annotations_; delete $2; } } SimpleContainerType: MapType { pdebug("SimpleContainerType -> MapType"); $$ = $1; } | SetType { pdebug("SimpleContainerType -> SetType"); $$ = $1; } | ListType { pdebug("SimpleContainerType -> ListType"); $$ = $1; } MapType: tok_map CppType '<' FieldType ',' FieldType '>' { pdebug("MapType -> tok_map "); $$ = new t_map($4, $6); if ($2 != nullptr) { ((t_container*)$$)->set_cpp_name(std::string($2)); } } SetType: tok_set CppType '<' FieldType '>' { pdebug("SetType -> tok_set"); $$ = new t_set($4); if ($2 != nullptr) { ((t_container*)$$)->set_cpp_name(std::string($2)); } } ListType: tok_list CppType '<' FieldType '>' CppType // the second CppType is for compatibility reasons = deprecated { pdebug("ListType -> tok_list"); check_for_list_of_bytes($4); $$ = new t_list($4); if ($2 != nullptr) { ((t_container*)$$)->set_cpp_name(std::string($2)); } if ($6 != nullptr) { ((t_container*)$$)->set_cpp_name(std::string($6)); pwarning(1, "The syntax 'list cpp_type \"c++ type\"' is deprecated. Use 'list cpp_type \"c++ type\" ' instead.\n"); } if (($2 != nullptr) && ($6 != nullptr)) { pwarning(1, "Two cpp_types clauses at list<%>\n", $2); } } CppType: tok_cpp_type tok_literal { $$ = $2; } | { $$ = nullptr; } TypeAnnotations: '(' TypeAnnotationList ')' { pdebug("TypeAnnotations -> ( TypeAnnotationList )"); $$ = $2; } | { $$ = nullptr; } TypeAnnotationList: TypeAnnotationList TypeAnnotation { pdebug("TypeAnnotationList -> TypeAnnotationList , TypeAnnotation"); $$ = $1; $$->annotations_[$2->key].push_back($2->val); delete $2; } | { /* Just use a dummy structure to hold the annotations. */ $$ = new t_struct(g_program); } TypeAnnotation: tok_identifier TypeAnnotationValue CommaOrSemicolonOptional { pdebug("TypeAnnotation -> TypeAnnotationValue"); $$ = new t_annotation; $$->key = $1; $$->val = $2; } TypeAnnotationValue: '=' tok_literal { pdebug("TypeAnnotationValue -> = tok_literal"); $$ = $2; } | { pdebug("TypeAnnotationValue ->"); $$ = strdup("1"); } %% thrift-0.19.0/compiler/cpp/src/thrift/platform.h0000644000000000000000000000277414303740367021600 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * define for mkdir,since the method signature * is different for the non-POSIX MinGW */ #ifdef _MSC_VER #include "thrift/windows/config.h" #endif #ifdef _WIN32 #include #include #else #include #include #endif #include // ignore EEXIST, throw on any other error #ifdef _WIN32 #define MKDIR(x) { int r = _mkdir(x); if (r == -1 && errno != EEXIST) { throw (std::string(x) + ": ") + strerror(errno); } } #else #define MKDIR(x) { int r = mkdir(x, S_IRWXU | S_IRWXG | S_IRWXO); if (r == -1 && errno != EEXIST) { throw (std::string(x) + ": ") + strerror(errno); } } #endif #ifdef PATH_MAX #define THRIFT_PATH_MAX PATH_MAX #else #define THRIFT_PATH_MAX MAX_PATH #endif thrift-0.19.0/compiler/cpp/src/thrift/main.cc0000644000000000000000000011426014370300523021016 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * thrift - a lightweight cross-language rpc/serialization tool * * This file contains the main compiler engine for Thrift, which invokes the * scanner/parser to build the thrift object tree. The interface generation * code for each language lives in a file by the language name under the * generate/ folder, and all parse structures live in parse/ * */ #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include /* for GetFullPathName */ #endif // Careful: must include globals first for extern definitions #include "thrift/common.h" #include "thrift/globals.h" #include "thrift/platform.h" #include "thrift/main.h" #include "thrift/parse/t_program.h" #include "thrift/parse/t_scope.h" #include "thrift/generate/t_generator.h" #include "thrift/audit/t_audit.h" #include "thrift/version.h" using namespace std; /** * Global program tree */ t_program* g_program; /** * Global scope */ t_scope* g_scope; /** * Parent scope to also parse types */ t_scope* g_parent_scope; /** * Prefix for putting types in parent scope */ string g_parent_prefix; /** * Parsing pass */ PARSE_MODE g_parse_mode; /** * Current directory of file being parsed */ string g_curdir; /** * Current file being parsed */ string g_curpath; /** * Search path for inclusions */ vector g_incl_searchpath; /** * Global debug state */ int g_debug = 0; /** * Strictness level */ int g_strict = 127; /** * Warning level */ int g_warn = 1; /** * Verbose output */ int g_verbose = 0; /** * Global time string */ char* g_time_str; /** * The last parsed doctext comment. */ char* g_doctext; /** * The First doctext comment */ char* g_program_doctext_candidate; /** * Whether or not negative field keys are accepted. */ int g_allow_neg_field_keys; /** * Whether or not 64-bit constants will generate a warning. */ int g_allow_64bit_consts = 0; /** * Flags to control code generation */ bool gen_recurse = false; /** * Flags to control thrift audit */ bool g_audit = false; /** * Flag to control return status */ bool g_return_failure = false; bool g_audit_fatal = true; bool g_generator_failure = false; /** * Win32 doesn't have realpath, so use fallback implementation in that case, * otherwise this just calls through to realpath */ char* saferealpath(const char* path, char* resolved_path) { #ifdef _WIN32 char buf[MAX_PATH]; char* basename; DWORD len = GetFullPathNameA(path, MAX_PATH, buf, &basename); if (len == 0 || len > MAX_PATH - 1) { strcpy(resolved_path, path); } else { strcpy(resolved_path, buf); } // Replace backslashes with forward slashes so the // rest of the code behaves correctly. size_t resolved_len = strlen(resolved_path); for (size_t i = 0; i < resolved_len; i++) { if (resolved_path[i] == '\\') { resolved_path[i] = '/'; } } return resolved_path; #else return realpath(path, resolved_path); #endif } bool check_is_directory(const char* dir_name) { #ifdef _WIN32 DWORD attributes = ::GetFileAttributesA(dir_name); if (attributes == INVALID_FILE_ATTRIBUTES) { fprintf(stderr, "Output directory %s is unusable: GetLastError() = %ld\n", dir_name, GetLastError()); return false; } if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY) { fprintf(stderr, "Output directory %s exists but is not a directory\n", dir_name); return false; } return true; #else struct stat sb; if (stat(dir_name, &sb) < 0) { fprintf(stderr, "Output directory %s is unusable: %s\n", dir_name, strerror(errno)); return false; } if (!S_ISDIR(sb.st_mode)) { fprintf(stderr, "Output directory %s exists but is not a directory\n", dir_name); return false; } return true; #endif } /** * Report an error to the user. This is called yyerror for historical * reasons (lex and yacc expect the error reporting routine to be called * this). Call this function to report any errors to the user. * yyerror takes printf style arguments. * * @param fmt C format string followed by additional arguments */ void yyerror(const char* fmt, ...) { va_list args; fprintf(stderr, "[ERROR:%s:%d] (last token was '%s')\n", g_curpath.c_str(), yylineno, yytext); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); fprintf(stderr, "\n"); } /** * Prints a debug message from the parser. * * @param fmt C format string followed by additional arguments */ void pdebug(const char* fmt, ...) { if (g_debug == 0) { return; } va_list args; printf("[PARSE:%d] ", yylineno); va_start(args, fmt); vprintf(fmt, args); va_end(args); printf("\n"); } /** * Prints a verbose output mode message * * @param fmt C format string followed by additional arguments */ void pverbose(const char* fmt, ...) { if (g_verbose == 0) { return; } va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); } /** * Prints a warning message * * @param fmt C format string followed by additional arguments */ void pwarning(int level, const char* fmt, ...) { if (g_warn < level) { return; } va_list args; printf("[WARNING:%s:%d] ", g_curpath.c_str(), yylineno); va_start(args, fmt); vprintf(fmt, args); va_end(args); printf("\n"); } /** * Prints a failure message and exits * * @param fmt C format string followed by additional arguments */ void failure(const char* fmt, ...) { va_list args; fprintf(stderr, "[FAILURE:%s:%d] ", g_curpath.c_str(), yylineno); va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); printf("\n"); exit(1); } /** * Converts a string filename into a thrift program name */ string program_name(string filename) { string::size_type slash = filename.rfind("/"); if (slash != string::npos) { filename = filename.substr(slash + 1); } string::size_type dot = filename.rfind("."); if (dot != string::npos) { filename = filename.substr(0, dot); } return filename; } /** * Gets the directory path of a filename */ string directory_name(string filename) { string::size_type slash = filename.rfind("/"); // No slash, just use the current directory if (slash == string::npos) { return "."; } return filename.substr(0, slash); } /** * Finds the appropriate file path for the given filename */ string include_file(string filename) { // Absolute path? Just try that if (filename[0] == '/') { // Realpath! char rp[THRIFT_PATH_MAX]; // cppcheck-suppress uninitvar if (saferealpath(filename.c_str(), rp) == nullptr) { pwarning(0, "Cannot open include file %s\n", filename.c_str()); return std::string(); } // Stat this file struct stat finfo; if (stat(rp, &finfo) == 0) { return rp; } } else { // relative path, start searching // new search path with current dir global vector sp = g_incl_searchpath; sp.insert(sp.begin(), g_curdir); // iterate through paths vector::iterator it; for (it = sp.begin(); it != sp.end(); it++) { string sfilename = *(it) + "/" + filename; // Realpath! char rp[THRIFT_PATH_MAX]; // cppcheck-suppress uninitvar if (saferealpath(sfilename.c_str(), rp) == nullptr) { continue; } // Stat this files struct stat finfo; if (stat(rp, &finfo) == 0) { return rp; } } } // Uh oh pwarning(0, "Could not find include file %s\n", filename.c_str()); return std::string(); } /** * Clears any previously stored doctext string. * Also prints a warning if we are discarding information. */ void clear_doctext() { if (g_doctext != nullptr) { pwarning(2, "Uncaptured doctext at on line %d.", g_doctext_lineno); } free(g_doctext); g_doctext = nullptr; } /** * Reset program doctext information after processing a file */ void reset_program_doctext_info() { if (g_program_doctext_candidate != nullptr) { free(g_program_doctext_candidate); g_program_doctext_candidate = nullptr; } g_program_doctext_lineno = 0; g_program_doctext_status = INVALID; pdebug("%s", "program doctext set to INVALID"); } /** * We are sure the program doctext candidate is really the program doctext. */ void declare_valid_program_doctext() { if ((g_program_doctext_candidate != nullptr) && (g_program_doctext_status == STILL_CANDIDATE)) { g_program_doctext_status = ABSOLUTELY_SURE; pdebug("%s", "program doctext set to ABSOLUTELY_SURE"); } else { g_program_doctext_status = NO_PROGRAM_DOCTEXT; pdebug("%s", "program doctext set to NO_PROGRAM_DOCTEXT"); } } /** * Cleans up text commonly found in doxygen-like comments * * Warning: if you mix tabs and spaces in a non-uniform way, * you will get what you deserve. */ char* clean_up_doctext(char* doctext) { // Convert to C++ string, and remove Windows's carriage returns. string docstring = doctext; docstring.erase(remove(docstring.begin(), docstring.end(), '\r'), docstring.end()); // Separate into lines. vector lines; string::size_type pos = string::npos; string::size_type last; while (true) { last = (pos == string::npos) ? 0 : pos + 1; pos = docstring.find('\n', last); if (pos == string::npos) { // First bit of cleaning. If the last line is only whitespace, drop it. string::size_type nonwhite = docstring.find_first_not_of(" \t", last); if (nonwhite != string::npos) { lines.push_back(docstring.substr(last)); } break; } lines.push_back(docstring.substr(last, pos - last)); } // A very profound docstring. if (lines.empty()) { return nullptr; } // Clear leading whitespace from the first line. pos = lines.front().find_first_not_of(" \t"); lines.front().erase(0, pos); // If every nonblank line after the first has the same number of spaces/tabs, // then a star, remove them. bool have_prefix = true; bool found_prefix = false; string::size_type prefix_len = 0; vector::iterator l_iter; for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) { if (l_iter->empty()) { continue; } pos = l_iter->find_first_not_of(" \t"); if (!found_prefix) { if (pos != string::npos) { if (l_iter->at(pos) == '*') { found_prefix = true; prefix_len = pos; } else { have_prefix = false; break; } } else { // Whitespace-only line. Truncate it. l_iter->clear(); } } else if (l_iter->size() > pos && l_iter->at(pos) == '*' && pos == prefix_len) { // Business as usual. } else if (pos == string::npos) { // Whitespace-only line. Let's truncate it for them. l_iter->clear(); } else { // The pattern has been broken. have_prefix = false; break; } } // If our prefix survived, delete it from every line. if (have_prefix) { // Get the star too. prefix_len++; for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) { l_iter->erase(0, prefix_len); } } // Now delete the minimum amount of leading whitespace from each line. prefix_len = string::npos; for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) { if (l_iter->empty()) { continue; } pos = l_iter->find_first_not_of(" \t"); if (pos != string::npos && (prefix_len == string::npos || pos < prefix_len)) { prefix_len = pos; } } // If our prefix survived, delete it from every line. if (prefix_len != string::npos) { for (l_iter = lines.begin() + 1; l_iter != lines.end(); ++l_iter) { l_iter->erase(0, prefix_len); } } // Remove trailing whitespace from every line. for (l_iter = lines.begin(); l_iter != lines.end(); ++l_iter) { pos = l_iter->find_last_not_of(" \t"); if (pos != string::npos && pos != l_iter->length() - 1) { l_iter->erase(pos + 1); } } // If the first line is empty, remove it. // Don't do this earlier because a lot of steps skip the first line. if (lines.front().empty()) { lines.erase(lines.begin()); } // Now rejoin the lines and copy them back into doctext. docstring.clear(); for (l_iter = lines.begin(); l_iter != lines.end(); ++l_iter) { docstring += *l_iter; docstring += '\n'; } // assert(docstring.length() <= strlen(doctext)); may happen, see THRIFT-1755 if (docstring.length() <= strlen(doctext)) { strcpy(doctext, docstring.c_str()); } else { free(doctext); // too short doctext = strdup(docstring.c_str()); } return doctext; } /** Set to true to debug docstring parsing */ static bool dump_docs = false; /** * Dumps docstrings to stdout * Only works for top-level definitions and the whole program doc * (i.e., not enum constants, struct fields, or functions. */ void dump_docstrings(t_program* program) { string progdoc = program->get_doc(); if (!progdoc.empty()) { printf("Whole program doc:\n%s\n", progdoc.c_str()); } const vector& typedefs = program->get_typedefs(); vector::const_iterator t_iter; for (t_iter = typedefs.begin(); t_iter != typedefs.end(); ++t_iter) { t_typedef* td = *t_iter; if (td->has_doc()) { printf("typedef %s:\n%s\n", td->get_name().c_str(), td->get_doc().c_str()); } } const vector& enums = program->get_enums(); vector::const_iterator e_iter; for (e_iter = enums.begin(); e_iter != enums.end(); ++e_iter) { t_enum* en = *e_iter; if (en->has_doc()) { printf("enum %s:\n%s\n", en->get_name().c_str(), en->get_doc().c_str()); } } const vector& consts = program->get_consts(); vector::const_iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { t_const* co = *c_iter; if (co->has_doc()) { printf("const %s:\n%s\n", co->get_name().c_str(), co->get_doc().c_str()); } } const vector& structs = program->get_structs(); vector::const_iterator s_iter; for (s_iter = structs.begin(); s_iter != structs.end(); ++s_iter) { t_struct* st = *s_iter; if (st->has_doc()) { printf("struct %s:\n%s\n", st->get_name().c_str(), st->get_doc().c_str()); } } const vector& xceptions = program->get_xceptions(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { t_struct* xn = *x_iter; if (xn->has_doc()) { printf("xception %s:\n%s\n", xn->get_name().c_str(), xn->get_doc().c_str()); } } const vector& services = program->get_services(); vector::const_iterator v_iter; for (v_iter = services.begin(); v_iter != services.end(); ++v_iter) { t_service* sv = *v_iter; if (sv->has_doc()) { printf("service %s:\n%s\n", sv->get_name().c_str(), sv->get_doc().c_str()); } } } /** * Emits a warning on list, binary type is typically a much better choice. */ void check_for_list_of_bytes(t_type* list_elem_type) { if ((g_parse_mode == PROGRAM) && (list_elem_type != nullptr) && list_elem_type->is_base_type()) { t_base_type* tbase = (t_base_type*)list_elem_type; if (tbase->get_base() == t_base_type::TYPE_I8) { pwarning(1, "Consider using the more efficient \"binary\" type instead of \"list\"."); } } } static bool g_byte_warning_emitted = false; /** * Emits a one-time warning on byte type, promoting the new i8 type instead */ void emit_byte_type_warning() { if (!g_byte_warning_emitted) { pwarning(1, "The \"byte\" type is a compatibility alias for \"i8\". Use \"i8\" to emphasize the " "signedness of this type.\n"); g_byte_warning_emitted = true; } } /** * Prints deprecation notice for old NS declarations that are no longer supported * If new_form is nullptr, old_form is assumed to be a language identifier, such as "cpp" * If new_form is not nullptr, both arguments are used exactly as given */ void error_unsupported_namespace_decl(const char* old_form, const char* new_form) { const char* remainder = ""; if( new_form == nullptr) { new_form = old_form; remainder = "_namespace"; } failure("Unsupported declaration '%s%s'. Use 'namespace %s' instead.", old_form, remainder, new_form); } /** * Prints the version number */ void version() { printf("Thrift version %s\n", THRIFT_VERSION); } /** * Display the usage message and then exit with an error code. */ void usage() { fprintf(stderr, "Usage: thrift [options] file\n\n"); fprintf(stderr, "Use thrift -help for a list of options\n"); exit(1); } /** * Diplays the help message and then exits with an error code. */ void help() { fprintf(stderr, "Usage: thrift [options] file\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, " -version Print the compiler version\n"); fprintf(stderr, " -o dir Set the output directory for gen-* packages\n"); fprintf(stderr, " (default: current directory)\n"); fprintf(stderr, " -out dir Set the ouput location for generated files.\n"); fprintf(stderr, " (no gen-* folder will be created)\n"); fprintf(stderr, " -I dir Add a directory to the list of directories\n"); fprintf(stderr, " searched for include directives\n"); fprintf(stderr, " -nowarn Suppress all compiler warnings (BAD!)\n"); fprintf(stderr, " -strict Strict compiler warnings on\n"); fprintf(stderr, " -v[erbose] Verbose mode\n"); fprintf(stderr, " -r[ecurse] Also generate included files\n"); fprintf(stderr, " -debug Parse debug trace to stdout\n"); fprintf(stderr, " --allow-neg-keys Allow negative field keys (Used to " "preserve protocol\n"); fprintf(stderr, " compatibility with older .thrift files)\n"); fprintf(stderr, " --allow-64bit-consts Do not print warnings about using 64-bit constants\n"); fprintf(stderr, " --gen STR Generate code with a dynamically-registered generator.\n"); fprintf(stderr, " STR has the form language[:key1=val1[,key2[,key3=val3]]].\n"); fprintf(stderr, " Keys and values are options passed to the generator.\n"); fprintf(stderr, " Many options will not require values.\n"); fprintf(stderr, "\n"); fprintf(stderr, "Options related to audit operation\n"); fprintf(stderr, " --audit OldFile Old Thrift file to be audited with 'file'\n"); fprintf(stderr, " -Iold dir Add a directory to the list of directories\n"); fprintf(stderr, " searched for include directives for old thrift file\n"); fprintf(stderr, " -Inew dir Add a directory to the list of directories\n"); fprintf(stderr, " searched for include directives for new thrift file\n"); fprintf(stderr, "\n"); fprintf(stderr, "Available generators (and options):\n"); t_generator_registry::gen_map_t gen_map = t_generator_registry::get_generator_map(); t_generator_registry::gen_map_t::iterator iter; for (iter = gen_map.begin(); iter != gen_map.end(); ++iter) { fprintf(stderr, " %s (%s):\n", iter->second->get_short_name().c_str(), iter->second->get_long_name().c_str()); fprintf(stderr, "%s", iter->second->get_documentation().c_str()); } exit(1); } /** * You know, when I started working on Thrift I really thought it wasn't going * to become a programming language because it was just a generator and it * wouldn't need runtime type information and all that jazz. But then we * decided to add constants, and all of a sudden that means runtime type * validation and inference, except the "runtime" is the code generator * runtime. */ void validate_const_rec(std::string name, t_type* type, t_const_value* value) { if (type->is_void()) { throw "type error: cannot declare a void const: " + name; } if (type->is_base_type()) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_STRING: if (value->get_type() != t_const_value::CV_STRING) { throw "type error: const \"" + name + "\" was declared as string"; } break; case t_base_type::TYPE_UUID: if (value->get_type() != t_const_value::CV_STRING) { throw "type error: const \"" + name + "\" was declared as uuid"; } value->set_uuid(value->get_uuid()); // validates constant break; case t_base_type::TYPE_BOOL: if (value->get_type() != t_const_value::CV_INTEGER) { throw "type error: const \"" + name + "\" was declared as bool"; } break; case t_base_type::TYPE_I8: if (value->get_type() != t_const_value::CV_INTEGER) { throw "type error: const \"" + name + "\" was declared as byte"; } break; case t_base_type::TYPE_I16: if (value->get_type() != t_const_value::CV_INTEGER) { throw "type error: const \"" + name + "\" was declared as i16"; } break; case t_base_type::TYPE_I32: if (value->get_type() != t_const_value::CV_INTEGER) { throw "type error: const \"" + name + "\" was declared as i32"; } break; case t_base_type::TYPE_I64: if (value->get_type() != t_const_value::CV_INTEGER) { throw "type error: const \"" + name + "\" was declared as i64"; } break; case t_base_type::TYPE_DOUBLE: if (value->get_type() != t_const_value::CV_INTEGER && value->get_type() != t_const_value::CV_DOUBLE) { throw "type error: const \"" + name + "\" was declared as double"; } break; default: throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase) + name; } } else if (type->is_enum()) { if (value->get_type() != t_const_value::CV_IDENTIFIER) { throw "type error: const \"" + name + "\" was declared as enum"; } // see if there's a dot in the identifier std::string name_portion = value->get_identifier_name(); const vector& enum_values = ((t_enum*)type)->get_constants(); vector::const_iterator c_iter; bool found = false; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { if ((*c_iter)->get_name() == name_portion) { found = true; break; } } if (!found) { throw "type error: const " + name + " was declared as type " + type->get_name() + " which is an enum, but " + value->get_identifier() + " is not a valid value for that enum"; } } else if (type->is_struct() || type->is_xception()) { if (value->get_type() != t_const_value::CV_MAP) { throw "type error: const \"" + name + "\" was declared as struct/xception"; } const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter->first->get_type() != t_const_value::CV_STRING) { throw "type error: " + name + " struct key must be string"; } t_type* field_type = nullptr; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_name() == v_iter->first->get_string()) { field_type = (*f_iter)->get_type(); } } if (field_type == nullptr) { throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); } validate_const_rec(name + "." + v_iter->first->get_string(), field_type, v_iter->second); } } else if (type->is_map()) { t_type* k_type = ((t_map*)type)->get_key_type(); t_type* v_type = ((t_map*)type)->get_val_type(); const map& val = value->get_map(); map::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { validate_const_rec(name + "", k_type, v_iter->first); validate_const_rec(name + "", v_type, v_iter->second); } } else if (type->is_list() || type->is_set()) { t_type* e_type; if (type->is_list()) { e_type = ((t_list*)type)->get_elem_type(); } else { e_type = ((t_set*)type)->get_elem_type(); } const vector& val = value->get_list(); vector::const_iterator v_iter; for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { validate_const_rec(name + "", e_type, *v_iter); } } } /** * Check simple identifier names * It's easier to do it this way instead of rewriting the whole grammar etc. */ void validate_simple_identifier(const char* identifier) { string name(identifier); if (name.find(".") != string::npos) { yyerror("Identifier %s can't have a dot.", identifier); exit(1); } } /** * Check the type of the parsed const information against its declared type */ void validate_const_type(t_const* c) { validate_const_rec(c->get_name(), c->get_type(), c->get_value()); } /** * Check the type of a default value assigned to a field. */ void validate_field_value(t_field* field, t_const_value* cv) { validate_const_rec(field->get_name(), field->get_type(), cv); } /** * Check that all the elements of a throws block are actually exceptions. */ bool validate_throws(t_struct* throws) { const vector& members = throws->get_members(); vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (!t_generator::get_true_type((*m_iter)->get_type())->is_xception()) { return false; } } return true; } /** * Skips UTF-8 BOM if there is one */ bool skip_utf8_bom(FILE* f) { // pretty straightforward, but works if (fgetc(f) == 0xEF) { if (fgetc(f) == 0xBB) { if (fgetc(f) == 0xBF) { return true; } } } rewind(f); return false; } /** * Parses a program */ void parse(t_program* program, t_program* parent_program) { // Get scope file path string path = program->get_path(); // Set current dir global, which is used in the include_file function g_curdir = directory_name(path); g_curpath = path; // Open the file // skip UTF-8 BOM if there is one yyin = fopen(path.c_str(), "r"); if (yyin == 0) { failure("Could not open input file: \"%s\"", path.c_str()); } if (skip_utf8_bom(yyin)) pverbose("Skipped UTF-8 BOM at %s\n", path.c_str()); // Create new scope and scan for includes pverbose("Scanning %s for includes\n", path.c_str()); g_parse_mode = INCLUDES; g_program = program; g_scope = program->scope(); try { yylineno = 1; if (yyparse() != 0) { failure("Parser error during include pass."); } } catch (string &x) { failure(x.c_str()); } fclose(yyin); // Recursively parse all the include programs vector& includes = program->get_includes(); vector::iterator iter; for (iter = includes.begin(); iter != includes.end(); ++iter) { parse(*iter, program); } // reset program doctext status before parsing a new file reset_program_doctext_info(); // Parse the program file g_parse_mode = PROGRAM; g_program = program; g_scope = program->scope(); g_parent_scope = (parent_program != nullptr) ? parent_program->scope() : nullptr; g_parent_prefix = program->get_name() + "."; g_curpath = path; // Open the file // skip UTF-8 BOM if there is one yyin = fopen(path.c_str(), "r"); if (yyin == 0) { failure("Could not open input file: \"%s\"", path.c_str()); } if (skip_utf8_bom(yyin)) pverbose("Skipped UTF-8 BOM at %s\n", path.c_str()); pverbose("Parsing %s for types\n", path.c_str()); yylineno = 1; try { if (yyparse() != 0) { failure("Parser error during types pass."); } } catch (string &x) { failure(x.c_str()); } fclose(yyin); } /** * Generate code */ void generate(t_program* program, const vector& generator_strings) { // Oooohh, recursive code generation, hot!! if (gen_recurse) { program->set_recursive(true); const vector& includes = program->get_includes(); for (auto include : includes) { // Propagate output path from parent to child programs include->set_out_path(program->get_out_path(), program->is_out_path_absolute()); generate(include, generator_strings); } } // Generate code! try { pverbose("Program: %s\n", program->get_path().c_str()); if (dump_docs) { dump_docstrings(program); } // make sure all symbolic constants are properly resolved program->scope()->resolve_all_consts(); vector::const_iterator iter; for (iter = generator_strings.begin(); iter != generator_strings.end(); ++iter) { t_generator* generator = t_generator_registry::get_generator(program, *iter); if (generator == nullptr) { pwarning(1, "Unable to get a generator for \"%s\".\n", iter->c_str()); g_generator_failure = true; } else if (generator) { generator->validate_input(); pverbose("Generating \"%s\"\n", iter->c_str()); generator->generate_program(); delete generator; } } } catch (string &s) { failure("Error: %s\n", s.c_str()); } catch (const char* exc) { failure("Error: %s\n", exc); } catch (const std::invalid_argument& invalid_argument_exception) { failure("Error: %s\n", invalid_argument_exception.what()); } } void audit(t_program* new_program, t_program* old_program, string new_thrift_include_path, string old_thrift_include_path) { vector temp_incl_searchpath = g_incl_searchpath; if (!old_thrift_include_path.empty()) { g_incl_searchpath.push_back(old_thrift_include_path); } parse(old_program, nullptr); g_incl_searchpath = temp_incl_searchpath; if (!new_thrift_include_path.empty()) { g_incl_searchpath.push_back(new_thrift_include_path); } parse(new_program, nullptr); compare_namespace(new_program, old_program); compare_services(new_program->get_services(), old_program->get_services()); compare_enums(new_program->get_enums(), old_program->get_enums()); compare_structs(new_program->get_structs(), old_program->get_structs()); compare_structs(new_program->get_xceptions(), old_program->get_xceptions()); compare_consts(new_program->get_consts(), old_program->get_consts()); } /** * Parse it up.. then spit it back out, in pretty much every language. Alright * not that many languages, but the cool ones that we care about. */ int main(int argc, char** argv) { int i; std::string out_path; bool out_path_is_absolute = false; // Setup time string time_t now = time(nullptr); g_time_str = ctime(&now); // Check for necessary arguments, you gotta have at least a filename and // an output language flag if (argc < 2) { usage(); } vector generator_strings; string old_thrift_include_path; string new_thrift_include_path; string old_input_file; // Set the current path to a dummy value to make warning messages clearer. g_curpath = "arguments"; // Hacky parameter handling... I didn't feel like using a library sorry! for (i = 1; i < argc - 1; i++) { char* arg; arg = strtok(argv[i], " "); while (arg != nullptr) { // Treat double dashes as single dashes if (arg[0] == '-' && arg[1] == '-') { ++arg; } if (strcmp(arg, "-help") == 0) { help(); } else if (strcmp(arg, "-version") == 0) { version(); exit(0); } else if (strcmp(arg, "-debug") == 0) { g_debug = 1; } else if (strcmp(arg, "-nowarn") == 0) { g_warn = 0; } else if (strcmp(arg, "-strict") == 0) { g_strict = 255; g_warn = 2; } else if (strcmp(arg, "-v") == 0 || strcmp(arg, "-verbose") == 0) { g_verbose = 1; } else if (strcmp(arg, "-r") == 0 || strcmp(arg, "-recurse") == 0) { gen_recurse = true; } else if (strcmp(arg, "-allow-neg-keys") == 0) { g_allow_neg_field_keys = true; } else if (strcmp(arg, "-allow-64bit-consts") == 0) { g_allow_64bit_consts = true; } else if (strcmp(arg, "-gen") == 0) { arg = argv[++i]; if (arg == nullptr) { fprintf(stderr, "Missing generator specification\n"); usage(); } generator_strings.emplace_back(arg); } else if (strcmp(arg, "-I") == 0) { // An argument of "-I\ asdf" is invalid and has unknown results arg = argv[++i]; if (arg == nullptr) { fprintf(stderr, "Missing Include directory\n"); usage(); } g_incl_searchpath.emplace_back(arg); } else if ((strcmp(arg, "-o") == 0) || (strcmp(arg, "-out") == 0)) { out_path_is_absolute = (strcmp(arg, "-out") == 0) ? true : false; arg = argv[++i]; if (arg == nullptr) { fprintf(stderr, "-o: missing output directory\n"); usage(); } out_path = arg; #ifdef _WIN32 // strip out trailing \ on Windows std::string::size_type last = out_path.length() - 1; if (out_path[last] == '\\') { out_path.erase(last); } #endif if (!check_is_directory(out_path.c_str())) return -1; } else if (strcmp(arg, "-audit") == 0) { g_audit = true; arg = argv[++i]; if (arg == nullptr) { fprintf(stderr, "Missing old thrift file name for audit operation\n"); usage(); } char old_thrift_file_rp[THRIFT_PATH_MAX]; // cppcheck-suppress uninitvar if (saferealpath(arg, old_thrift_file_rp) == nullptr) { failure("Could not open input file with realpath: %s", arg); } old_input_file = string(old_thrift_file_rp); } else if (strcmp(arg, "-audit-nofatal") == 0) { g_audit_fatal = false; } else if (strcmp(arg, "-Iold") == 0) { arg = argv[++i]; if (arg == nullptr) { fprintf(stderr, "Missing Include directory for old thrift file\n"); usage(); } old_thrift_include_path = string(arg); } else if (strcmp(arg, "-Inew") == 0) { arg = argv[++i]; if (arg == nullptr) { fprintf(stderr, "Missing Include directory for new thrift file\n"); usage(); } new_thrift_include_path = string(arg); } else { fprintf(stderr, "Unrecognized option: %s\n", arg); usage(); } // Tokenize more arg = strtok(nullptr, " "); } } // display help if ((strcmp(argv[argc - 1], "-help") == 0) || (strcmp(argv[argc - 1], "--help") == 0)) { help(); } // if you're asking for version, you have a right not to pass a file if ((strcmp(argv[argc - 1], "-version") == 0) || (strcmp(argv[argc - 1], "--version") == 0)) { version(); exit(0); } // Initialize global types initGlobals(); if (g_audit) { // Audit operation if (old_input_file.empty()) { fprintf(stderr, "Missing file name of old thrift file for audit\n"); usage(); } char new_thrift_file_rp[THRIFT_PATH_MAX]; if (argv[i] == nullptr) { fprintf(stderr, "Missing file name of new thrift file for audit\n"); usage(); } // cppcheck-suppress uninitvar if (saferealpath(argv[i], new_thrift_file_rp) == nullptr) { failure("Could not open input file with realpath: %s", argv[i]); } string new_input_file(new_thrift_file_rp); t_program new_program(new_input_file); t_program old_program(old_input_file); audit(&new_program, &old_program, new_thrift_include_path, old_thrift_include_path); } else { // Generate options // You gotta generate something! if (generator_strings.empty()) { fprintf(stderr, "No output language(s) specified\n"); usage(); } // Real-pathify it char rp[THRIFT_PATH_MAX]; if (argv[i] == nullptr) { fprintf(stderr, "Missing file name\n"); usage(); } // cppcheck-suppress uninitvar if (saferealpath(argv[i], rp) == nullptr) { failure("Could not open input file with realpath: %s", argv[i]); } string input_file(rp); // Instance of the global parse tree t_program* program = new t_program(input_file); if (out_path.size()) { program->set_out_path(out_path, out_path_is_absolute); } // Compute the cpp include prefix. // infer this from the filename passed in string input_filename = argv[i]; string include_prefix; string::size_type last_slash = string::npos; if ((last_slash = input_filename.rfind("/")) != string::npos) { include_prefix = input_filename.substr(0, last_slash); } program->set_include_prefix(include_prefix); // Parse it! parse(program, nullptr); // The current path is not really relevant when we are doing generation. // Reset the variable to make warning messages clearer. g_curpath = "generation"; // Reset yylineno for the heck of it. Use 1 instead of 0 because // That is what shows up during argument parsing. yylineno = 1; // Generate it! generate(program, generator_strings); delete program; } // Clean up. Who am I kidding... this program probably orphans heap memory // all over the place, but who cares because it is about to exit and it is // all referenced and used by this wacky parse tree up until now anyways. clearGlobals(); // Finished if (g_return_failure && g_audit_fatal) { exit(2); } if (g_generator_failure) { exit(3); } // Finished return 0; } thrift-0.19.0/compiler/cpp/src/thrift/logging.h0000644000000000000000000000230714303740367021372 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef T_LOGGING_H #define T_LOGGING_H extern int g_debug; extern int g_warn; extern int g_verbose; /** * Parse debugging output, used to print helpful info */ void pdebug(const char* fmt, ...); /** * Parser warning */ void pwarning(int level, const char* fmt, ...); /** * Print verbose output message */ void pverbose(const char* fmt, ...); /** * Failure! */ void failure(const char* fmt, ...); #endif thrift-0.19.0/compiler/cpp/src/Makefile.am0000644000000000000000000000261114303740367020325 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. AUTOMAKE_OPTIONS = subdir-objects nostdinc AM_YFLAGS = -d BUILT_SOURCES = thrift/thrifty.cc noinst_LIBRARIES = thrift/libparse.a thrift_libparse_a_CPPFLAGS = -I$(srcdir) thrift_libparse_a_CXXFLAGS = -Wall -Wno-sign-compare -Wno-unused thrift_libparse_a_SOURCES = thrift/thrifty.yy \ thrift/thriftl.ll clean-local: $(RM) thrift/thriftl.cc thrift/thrifty.cc thrift/thrifty.h thrift/thrifty.hh EXTRA_DIST = \ thrift/logging.cc \ thrift/windows/config.h thrift-0.19.0/compiler/cpp/src/Makefile.in0000644000000000000000000007537314472652514020360 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = compiler/cpp/src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = thrift_libparse_a_AR = $(AR) $(ARFLAGS) thrift_libparse_a_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_thrift_libparse_a_OBJECTS = \ thrift/thrift_libparse_a-thrifty.$(OBJEXT) \ thrift/thrift_libparse_a-thriftl.$(OBJEXT) thrift_libparse_a_OBJECTS = $(am_thrift_libparse_a_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS) AM_V_LEX = $(am__v_LEX_@AM_V@) am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) am__v_LEX_0 = @echo " LEX " $@; am__v_LEX_1 = YLWRAP = $(top_srcdir)/ylwrap am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ -e s/c++$$/h++/ -e s/c$$/h/ YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS) AM_V_YACC = $(am__v_YACC_@AM_V@) am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@) am__v_YACC_0 = @echo " YACC " $@; am__v_YACC_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(thrift_libparse_a_SOURCES) DIST_SOURCES = $(thrift_libparse_a_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/ylwrap thrift/thriftl.cc thrift/thrifty.cc \ thrift/thrifty.hh DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = subdir-objects nostdinc AM_YFLAGS = -d BUILT_SOURCES = thrift/thrifty.cc noinst_LIBRARIES = thrift/libparse.a thrift_libparse_a_CPPFLAGS = -I$(srcdir) thrift_libparse_a_CXXFLAGS = -Wall -Wno-sign-compare -Wno-unused thrift_libparse_a_SOURCES = thrift/thrifty.yy \ thrift/thriftl.ll EXTRA_DIST = \ thrift/logging.cc \ thrift/windows/config.h all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .cc .ll .lo .o .obj .yy $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign compiler/cpp/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign compiler/cpp/src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) thrift/thrifty.hh: thrift/thrifty.cc @if test ! -f $@; then rm -f thrift/thrifty.cc; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) thrift/thrifty.cc; else :; fi thrift/$(am__dirstamp): @$(MKDIR_P) thrift @: > thrift/$(am__dirstamp) thrift/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) thrift/$(DEPDIR) @: > thrift/$(DEPDIR)/$(am__dirstamp) thrift/thrift_libparse_a-thrifty.$(OBJEXT): thrift/$(am__dirstamp) \ thrift/$(DEPDIR)/$(am__dirstamp) thrift/thrift_libparse_a-thriftl.$(OBJEXT): thrift/$(am__dirstamp) \ thrift/$(DEPDIR)/$(am__dirstamp) thrift/libparse.a: $(thrift_libparse_a_OBJECTS) $(thrift_libparse_a_DEPENDENCIES) $(EXTRA_thrift_libparse_a_DEPENDENCIES) thrift/$(am__dirstamp) $(AM_V_at)-rm -f thrift/libparse.a $(AM_V_AR)$(thrift_libparse_a_AR) thrift/libparse.a $(thrift_libparse_a_OBJECTS) $(thrift_libparse_a_LIBADD) $(AM_V_at)$(RANLIB) thrift/libparse.a mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f thrift/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< thrift/thrift_libparse_a-thrifty.o: thrift/thrifty.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -MT thrift/thrift_libparse_a-thrifty.o -MD -MP -MF thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Tpo -c -o thrift/thrift_libparse_a-thrifty.o `test -f 'thrift/thrifty.cc' || echo '$(srcdir)/'`thrift/thrifty.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Tpo thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='thrift/thrifty.cc' object='thrift/thrift_libparse_a-thrifty.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -c -o thrift/thrift_libparse_a-thrifty.o `test -f 'thrift/thrifty.cc' || echo '$(srcdir)/'`thrift/thrifty.cc thrift/thrift_libparse_a-thrifty.obj: thrift/thrifty.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -MT thrift/thrift_libparse_a-thrifty.obj -MD -MP -MF thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Tpo -c -o thrift/thrift_libparse_a-thrifty.obj `if test -f 'thrift/thrifty.cc'; then $(CYGPATH_W) 'thrift/thrifty.cc'; else $(CYGPATH_W) '$(srcdir)/thrift/thrifty.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Tpo thrift/$(DEPDIR)/thrift_libparse_a-thrifty.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='thrift/thrifty.cc' object='thrift/thrift_libparse_a-thrifty.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -c -o thrift/thrift_libparse_a-thrifty.obj `if test -f 'thrift/thrifty.cc'; then $(CYGPATH_W) 'thrift/thrifty.cc'; else $(CYGPATH_W) '$(srcdir)/thrift/thrifty.cc'; fi` thrift/thrift_libparse_a-thriftl.o: thrift/thriftl.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -MT thrift/thrift_libparse_a-thriftl.o -MD -MP -MF thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Tpo -c -o thrift/thrift_libparse_a-thriftl.o `test -f 'thrift/thriftl.cc' || echo '$(srcdir)/'`thrift/thriftl.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Tpo thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='thrift/thriftl.cc' object='thrift/thrift_libparse_a-thriftl.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -c -o thrift/thrift_libparse_a-thriftl.o `test -f 'thrift/thriftl.cc' || echo '$(srcdir)/'`thrift/thriftl.cc thrift/thrift_libparse_a-thriftl.obj: thrift/thriftl.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -MT thrift/thrift_libparse_a-thriftl.obj -MD -MP -MF thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Tpo -c -o thrift/thrift_libparse_a-thriftl.obj `if test -f 'thrift/thriftl.cc'; then $(CYGPATH_W) 'thrift/thriftl.cc'; else $(CYGPATH_W) '$(srcdir)/thrift/thriftl.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Tpo thrift/$(DEPDIR)/thrift_libparse_a-thriftl.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='thrift/thriftl.cc' object='thrift/thrift_libparse_a-thriftl.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_libparse_a_CPPFLAGS) $(CPPFLAGS) $(thrift_libparse_a_CXXFLAGS) $(CXXFLAGS) -c -o thrift/thrift_libparse_a-thriftl.obj `if test -f 'thrift/thriftl.cc'; then $(CYGPATH_W) 'thrift/thriftl.cc'; else $(CYGPATH_W) '$(srcdir)/thrift/thriftl.cc'; fi` .ll.cc: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .yy.cc: $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LIBRARIES) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f thrift/$(DEPDIR)/$(am__dirstamp) -rm -f thrift/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -rm -f thrift/thriftl.cc -rm -f thrift/thrifty.cc -rm -f thrift/thrifty.hh -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-local \ clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf thrift/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf thrift/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-local clean-noinstLIBRARIES cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile clean-local: $(RM) thrift/thriftl.cc thrift/thrifty.cc thrift/thrifty.h thrift/thrifty.hh # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/compiler/cpp/README.md0000644000000000000000000001237214303740367016766 0ustar00rootroot00000000000000# Build Thrift IDL compiler using CMake - [Build Thrift IDL compiler using CMake](#build-thrift-idl-compiler-using-cmake) - [Build on Unix-like System](#build-on-unix-like-system) - [Prerequisites](#prerequisites) - [Build using CMake](#build-using-cmake) - [Build with Eclipse IDE](#build-with-eclipse-ide) - [Build with XCode IDE in MacOS](#build-with-xcode-ide-in-macos) - [Usage of other IDEs](#usage-of-other-ides) - [Build on Windows](#build-on-windows) - [Prerequisites](#prerequisites-1) - [Build using Git Bash](#build-using-git-bash) - [Using Visual Studio and Win flex-bison](#using-visual-studio-and-win-flex-bison) - [Cross compile using mingw32 and generate a Windows Installer with CPack](#cross-compile-using-mingw32-and-generate-a-windows-installer-with-cpack) - [Other cases](#other-cases) - [Building the Thrift IDL compiler in Windows without CMake](#building-the-thrift-idl-compiler-in-windows-without-cmake) - [Unit tests for compiler](#unit-tests-for-compiler) - [Using boost test](#using-boost-test) - [Using Catch C++ test library](#using-catch-c-test-library) - [Have a Happy free time and holidays](#have-a-happy-free-time-and-holidays) ## Build on Unix-like System ### Prerequisites - Install CMake - Install flex and bison ### Build using CMake - Go to **thrift\compiler\cpp** - Use the following steps to build using cmake: ``` mkdir cmake-build && cd cmake-build cmake .. make ``` #### Build with Eclipse IDE - Go to **thrift\compiler\cpp** - Use the following steps to build using cmake: ``` mkdir cmake-ec && cd cmake-ec cmake -G "Eclipse CDT4 - Unix Makefiles" .. make ``` Now open the folder cmake-ec using eclipse. #### Build with XCode IDE in MacOS - Install/update flex, bison and cmake with brew ``` brew install flex brew install bison brew install cmake ``` - Go to **thrift\compiler\cpp** - Run commands in command line: ``` mkdir cmake-build && cd cmake-build cmake -G "Xcode" .. cmake --build . ``` #### Usage of other IDEs Please check list of supported IDE ``` cmake --help ``` ## Build on Windows ### Prerequisites - Install CMake - https://cmake.org/download/ - In case if you want to build without Git Bash - install winflexbison - https://sourceforge.net/projects/winflexbison/ - In case if you want to build with Visual Studio - install Visual Studio - Better to use the latest stable Visual Studio Community Edition - https://www.visualstudio.com/vs/whatsnew/ (ensure that you installed workload "Desktop Development with C++" for VS2017) - Microsoft added some support for CMake and improving it in Visual Studio ### Build using Git Bash Git Bash provides flex and bison - Go to **thrift\compiler\cpp** - Use the following steps to build using cmake: ``` mkdir cmake-vs && cd cmake-vs cmake -DWITH_SHARED_LIB=off .. cmake --build . ``` ### Using Visual Studio and Win flex-bison - Generate a Visual Studio project for version of Visual Studio which you have (**cmake --help** can show list of supportable VS versions): - Run commands in command line: ``` mkdir cmake-vs cd cmake-vs cmake -G "Visual Studio 15 2017" .. ``` - Now open the folder cmake-vs using Visual Studio. ### Cross compile using mingw32 and generate a Windows Installer with CPack ``` mkdir cmake-mingw32 && cd cmake-mingw32 cmake -DCMAKE_TOOLCHAIN_FILE=../build/cmake/mingw32-toolchain.cmake -DBUILD_COMPILER=ON -DBUILD_LIBRARIES=OFF -DBUILD_TESTING=OFF .. cpack ``` # Other cases ## Building the Thrift IDL compiler in Windows without CMake If you don't want to use CMake you can use the already available Visual Studio 2010 solution. The Visual Studio project contains pre-build commands to generate the thriftl.cc, thrifty.cc and thrifty.hh files which are necessary to build the compiler. These depend on bison, flex and their dependencies to work properly. Download flex & bison as described above. Place these binaries somewhere in the path and rename win_flex.exe and win_bison.exe to flex.exe and bison.exe respectively. If this doesn't work on a system, try these manual pre-build steps. Open compiler.sln and remove the Pre-build commands under the project's: Properties -> Build Events -> Pre-Build Events. From a command prompt: ``` cd thrift/compiler/cpp flex -o src\thrift\thriftl.cc src\thrift\thriftl.ll ``` In the generated thriftl.cc, comment out #include Place a copy of bison.simple in thrift/compiler/cpp ``` bison -y -o "src/thrift/thrifty.cc" --defines src/thrift/thrifty.yy move src\thrift\thrifty.cc.hh src\thrift\thrifty.hh ``` Bison might generate the yacc header file "thrifty.cc.h" with just one h ".h" extension; in this case you'll have to rename to "thrifty.h". ``` move src\thrift\version.h.in src\thrift\version.h ``` Download inttypes.h from the interwebs and place it in an include path location (e.g. thrift/compiler/cpp/src). Build the compiler in Visual Studio. # Unit tests for compiler ## Using boost test - pls check **test** folder ## Using Catch C++ test library Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netstd** implementation) - pls check **tests** folder # Have a Happy free time and holidays thrift-0.19.0/compiler/cpp/coding_standards.md0000644000000000000000000000030214303740367021325 0ustar00rootroot00000000000000## Compiler Coding Standards * When making small change / bugfix - follow style as seen in nearby code. * When making major refactor and / or adding new feature - follow style for C++ librarythrift-0.19.0/compiler/cpp/test/0000777000000000000000000000000014472652603016467 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/test/Makefile.am0000644000000000000000000000206514303740367020520 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc AM_CPPFLAGS = -I$(top_srcdir)/compiler/cpp/src AM_CXXFLAGS = -Wall -Wextra -pedantic thrift-0.19.0/compiler/cpp/test/CMakeLists.txt0000644000000000000000000000340014370300523021204 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift") set(KEYWORD_LANGS php) # the whole ticket THRIFT-4655 is only about PHP so leave other languages alone LIST(REMOVE_ITEM KEYWORD_LANGS swift) # in Swift you can escape reserved words (and in other languages as well) foreach(LANG ${KEYWORD_LANGS}) foreach(SAMPLE ${KEYWORD_SAMPLES}) get_filename_component(FILENAME ${SAMPLE} NAME_WE) add_test(NAME "${LANG}_${FILENAME}" COMMAND thrift-compiler --gen ${LANG} ${SAMPLE}) set_tests_properties("${LANG}_${FILENAME}" PROPERTIES PASS_REGULAR_EXPRESSION "Cannot use reserved language keyword") endforeach() endforeach() find_package(PythonInterp QUIET) if(PYTHONINTERP_FOUND) add_test(NAME StalenessCheckTest COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler/staleness_check.py ${THRIFT_COMPILER}) else() message(WARNING "Skipping StalenessCheckTest as there is no python interpreter available.") endif() thrift-0.19.0/compiler/cpp/test/Makefile0000644000000000000000000004353514472652603020135 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # compiler/cpp/test/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = compiler/cpp/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/compiler/cpp/test abs_srcdir = /thrift/src/compiler/cpp/test abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../../ top_builddir = ../../.. top_srcdir = ../../.. AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc AM_CPPFLAGS = -I$(top_srcdir)/compiler/cpp/src AM_CXXFLAGS = -Wall -Wextra -pedantic all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign compiler/cpp/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign compiler/cpp/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/compiler/cpp/test/compiler/0000777000000000000000000000000014370300523020265 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/test/compiler/Single.thrift0000644000000000000000000000147614370300523022734 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const string foo = "bar" thrift-0.19.0/compiler/cpp/test/compiler/Including.thrift0000644000000000000000000000162114370300523023417 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ include "Included.thrift" const string s = "string" struct BStruct { 1: Included.a_struct one_of_each } thrift-0.19.0/compiler/cpp/test/compiler/Included.thrift0000644000000000000000000000225014370300523023231 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const string foo = "bar" struct a_struct { 1: bool im_true, 2: bool im_false, 3: i8 a_bite, 4: i16 integer16, 5: i32 integer32, 6: i64 integer64, 7: double double_precision, 8: string some_characters, 9: string zomg_unicode, 10: bool what_who, } service AService { i32 a_procedure(1: i32 arg) } thrift-0.19.0/compiler/cpp/test/compiler/staleness_check.py0000777000000000000000000001304114062750226024006 0ustar00rootroot00000000000000#!/usr/bin/env python3 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # from __future__ import print_function import os import shutil import subprocess import sys import tempfile import time import unittest class TestStalenessCheck(unittest.TestCase): CURRENT_DIR_PATH = os.path.dirname(os.path.realpath(__file__)) THRIFT_EXECUTABLE_PATH = None SINGLE_THRIFT_FILE_PATH = os.path.join(CURRENT_DIR_PATH, "Single.thrift") INCLUDING_THRIFT_FILE_PATH = os.path.join(CURRENT_DIR_PATH, "Including.thrift") INCLUDED_THRIFT_FILE_PATH = os.path.join(CURRENT_DIR_PATH, "Included.thrift") def test_staleness_check_of_single_thrift_file_without_changed_output(self): temp_dir = tempfile.mkdtemp(dir=TestStalenessCheck.CURRENT_DIR_PATH) command = [TestStalenessCheck.THRIFT_EXECUTABLE_PATH, "-gen", "cpp", "-o", temp_dir] command += [TestStalenessCheck.SINGLE_THRIFT_FILE_PATH] subprocess.call(command) used_file_path = os.path.join(temp_dir, "gen-cpp", "Single_constants.cpp") first_modification_time = os.path.getmtime(os.path.join(used_file_path)) time.sleep(1.0) subprocess.call(command) second_modification_time = os.path.getmtime(used_file_path) self.assertEqual(second_modification_time, first_modification_time) shutil.rmtree(temp_dir, ignore_errors=True) def test_staleness_check_of_single_thrift_file_with_changed_output(self): temp_dir = tempfile.mkdtemp(dir=TestStalenessCheck.CURRENT_DIR_PATH) command = [TestStalenessCheck.THRIFT_EXECUTABLE_PATH, "-gen", "cpp", "-o", temp_dir] command += [TestStalenessCheck.SINGLE_THRIFT_FILE_PATH] subprocess.call(command) used_file_path = os.path.join(temp_dir, "gen-cpp", "Single_constants.cpp") first_modification_time = os.path.getmtime(os.path.join(used_file_path)) used_file = open(used_file_path, "r") first_contents = used_file.read() used_file.close() used_file = open(used_file_path, "a") used_file.write("\n/* This is a comment */\n") used_file.close() time.sleep(1.0) subprocess.call(command) second_modification_time = os.path.getmtime(used_file_path) used_file = open(used_file_path, "r") second_contents = used_file.read() used_file.close() self.assertGreater(second_modification_time, first_modification_time) self.assertEqual(first_contents, second_contents) shutil.rmtree(temp_dir, ignore_errors=True) def test_staleness_check_of_included_file(self): temp_dir = tempfile.mkdtemp(dir=TestStalenessCheck.CURRENT_DIR_PATH) temp_included_file_path = os.path.join(temp_dir, "Included.thrift") temp_including_file_path = os.path.join(temp_dir, "Including.thrift") shutil.copy2(TestStalenessCheck.INCLUDED_THRIFT_FILE_PATH, temp_included_file_path) shutil.copy2(TestStalenessCheck.INCLUDING_THRIFT_FILE_PATH, temp_including_file_path) command = [TestStalenessCheck.THRIFT_EXECUTABLE_PATH, "-gen", "cpp", "-recurse", "-o", temp_dir] command += [temp_including_file_path] subprocess.call(command) included_constants_cpp_file_path = os.path.join(temp_dir, "gen-cpp", "Included_constants.cpp") including_constants_cpp_file_path = os.path.join(temp_dir, "gen-cpp", "Including_constants.cpp") included_constants_cpp_first_modification_time = os.path.getmtime(included_constants_cpp_file_path) including_constants_cpp_first_modification_time = os.path.getmtime(including_constants_cpp_file_path) temp_included_file = open(temp_included_file_path, "a") temp_included_file.write("\nconst i32 an_integer = 42\n") temp_included_file.close() time.sleep(1.0) subprocess.call(command) included_constants_cpp_second_modification_time = os.path.getmtime(included_constants_cpp_file_path) including_constants_cpp_second_modification_time = os.path.getmtime(including_constants_cpp_file_path) self.assertGreater( included_constants_cpp_second_modification_time, included_constants_cpp_first_modification_time) self.assertEqual( including_constants_cpp_first_modification_time, including_constants_cpp_second_modification_time) shutil.rmtree(temp_dir, ignore_errors=True) def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() suite.addTest(loader.loadTestsFromTestCase(TestStalenessCheck)) return suite if __name__ == "__main__": # The path of Thrift compiler is passed as an argument to the test script. # Remove it to not confuse the unit testing framework TestStalenessCheck.THRIFT_EXECUTABLE_PATH = sys.argv[-1] del sys.argv[-1] unittest.main(defaultTest="suite", testRunner=unittest.TextTestRunner(verbosity=2)) thrift-0.19.0/compiler/cpp/test/keyword-samples/0000777000000000000000000000000014370300523021601 5ustar00rootroot00000000000000thrift-0.19.0/compiler/cpp/test/keyword-samples/exception1_return.thrift0000644000000000000000000000152714370300523026502 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_010 exception return {} thrift-0.19.0/compiler/cpp/test/keyword-samples/typedef1_return.thrift0000644000000000000000000000152714370300523026144 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_004 typedef bool return thrift-0.19.0/compiler/cpp/test/keyword-samples/union2_return.thrift0000644000000000000000000000156614370300523025640 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_006 union union_name { 1: optional bool return=1 } thrift-0.19.0/compiler/cpp/test/keyword-samples/union1_return.thrift0000644000000000000000000000152414370300523025631 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_005 union return {} thrift-0.19.0/compiler/cpp/test/keyword-samples/struct1_return.thrift0000644000000000000000000000152414370300523026025 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_002 struct return {} thrift-0.19.0/compiler/cpp/test/keyword-samples/const1_return.thrift0000644000000000000000000000153214370300523025626 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_007 const bool return = 0 thrift-0.19.0/compiler/cpp/test/keyword-samples/service1_return.thrift0000644000000000000000000000152514370300523026142 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_012 service return {} thrift-0.19.0/compiler/cpp/test/keyword-samples/service4_return.thrift0000644000000000000000000000166314370300523026150 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_001 exception exception_name {} service service_name { void function_name() throws ( 1: exception_name return) } thrift-0.19.0/compiler/cpp/test/keyword-samples/service2_return.thrift0000644000000000000000000000160014370300523026135 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_013 service service_name { bool function_name(1: i32 return) } thrift-0.19.0/compiler/cpp/test/keyword-samples/enum2_return.thrift0000644000000000000000000000154014370300523025444 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_009 enum enum_name { return } thrift-0.19.0/compiler/cpp/test/keyword-samples/enum1_return.thrift0000644000000000000000000000152414370300523025445 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_008 enum return { } thrift-0.19.0/compiler/cpp/test/keyword-samples/service3_return.thrift0000644000000000000000000000155414370300523026146 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_014 service service_name { void return() } thrift-0.19.0/compiler/cpp/test/keyword-samples/exception2_return.thrift0000644000000000000000000000157014370300523026501 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_011 exception exception_name { 1: required i8 return } thrift-0.19.0/compiler/cpp/test/keyword-samples/struct2_return.thrift0000644000000000000000000000157014370300523026027 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace * keyword_test_003 struct struct_name { 1: required bool return = 1 } thrift-0.19.0/compiler/cpp/test/Makefile.in0000644000000000000000000004260414472652514020537 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = compiler/cpp/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc AM_CPPFLAGS = -I$(top_srcdir)/compiler/cpp/src AM_CXXFLAGS = -Wall -Wextra -pedantic all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign compiler/cpp/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign compiler/cpp/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/compiler/cpp/compiler.vcxproj.filters0000644000000000000000000001541114303740367022402 0ustar00rootroot00000000000000 generate generate generate generate parse parse parse parse parse parse parse parse parse parse parse parse parse parse parse parse parse parse windows windows {ae9d0a15-57ae-4f01-87a4-81f790249b83} {5df016bb-591b-420a-a535-4330d9187fbf} {b5c626af-afa5-433c-8e10-ee734533cb68} generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate generate parse parse generate generate thrift-0.19.0/compiler/cpp/Makefile.in0000644000000000000000000043273614472652514017571 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_TESTS_TRUE@am__append_1 = test bin_PROGRAMS = thrift$(EXEEXT) subdir = compiler/cpp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) am__dirstamp = $(am__leading_dot)dirstamp am_thrift_OBJECTS = src/thrift/audit/thrift-t_audit.$(OBJEXT) \ src/thrift/thrift-common.$(OBJEXT) \ src/thrift/generate/thrift-t_generator.$(OBJEXT) \ src/thrift/thrift-main.$(OBJEXT) \ src/thrift/parse/thrift-parse.$(OBJEXT) \ src/thrift/parse/thrift-t_typedef.$(OBJEXT) \ src/thrift/generate/thrift-t_c_glib_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_cl_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_cpp_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_d_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_dart_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_delphi_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_erl_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_go_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_gv_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_haxe_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_html_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_markdown_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_java_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_javame_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_js_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_json_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_kotlin_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_lua_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_netstd_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_ocaml_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_perl_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_php_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_py_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_rb_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_rs_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_st_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_swift_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_xml_generator.$(OBJEXT) \ src/thrift/generate/thrift-t_xsd_generator.$(OBJEXT) \ src/thrift/generate/thrift-validator_parser.$(OBJEXT) \ src/thrift/generate/thrift-go_validator_generator.$(OBJEXT) thrift_OBJECTS = $(am_thrift_OBJECTS) thrift_DEPENDENCIES = src/thrift/libparse.a AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = thrift_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(thrift_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(thrift_SOURCES) DIST_SOURCES = $(thrift_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = src . test am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = subdir-objects nostdinc SUBDIRS = src . $(am__append_1) thrift_OBJDIR = obj # Specific client generator source thrift_SOURCES = src/thrift/audit/t_audit.cpp \ src/thrift/audit/t_audit.h src/thrift/common.cc \ src/thrift/common.h src/thrift/generate/t_generator.cc \ src/thrift/generate/t_generator.h \ src/thrift/generate/t_generator_registry.h \ src/thrift/generate/t_html_generator.h \ src/thrift/generate/t_oop_generator.h src/thrift/globals.h \ src/thrift/logging.h src/thrift/main.cc src/thrift/main.h \ src/thrift/version.h src/thrift/parse/parse.cc \ src/thrift/parse/t_base_type.h src/thrift/parse/t_const.h \ src/thrift/parse/t_const_value.h \ src/thrift/parse/t_container.h src/thrift/parse/t_doc.h \ src/thrift/parse/t_enum.h src/thrift/parse/t_enum_value.h \ src/thrift/parse/t_field.h src/thrift/parse/t_function.h \ src/thrift/parse/t_list.h src/thrift/parse/t_map.h \ src/thrift/parse/t_program.h src/thrift/parse/t_scope.h \ src/thrift/parse/t_service.h src/thrift/parse/t_set.h \ src/thrift/parse/t_struct.h src/thrift/parse/t_type.h \ src/thrift/parse/t_typedef.cc src/thrift/parse/t_typedef.h \ src/thrift/platform.h \ src/thrift/generate/t_c_glib_generator.cc \ src/thrift/generate/t_cl_generator.cc \ src/thrift/generate/t_cpp_generator.cc \ src/thrift/generate/t_d_generator.cc \ src/thrift/generate/t_dart_generator.cc \ src/thrift/generate/t_delphi_generator.cc \ src/thrift/generate/t_erl_generator.cc \ src/thrift/generate/t_go_generator.cc \ src/thrift/generate/t_go_generator.h \ src/thrift/generate/t_gv_generator.cc \ src/thrift/generate/t_haxe_generator.cc \ src/thrift/generate/t_html_generator.cc \ src/thrift/generate/t_markdown_generator.cc \ src/thrift/generate/t_java_generator.cc \ src/thrift/generate/t_javame_generator.cc \ src/thrift/generate/t_js_generator.cc \ src/thrift/generate/t_json_generator.cc \ src/thrift/generate/t_kotlin_generator.cc \ src/thrift/generate/t_lua_generator.cc \ src/thrift/generate/t_netstd_generator.cc \ src/thrift/generate/t_netstd_generator.h \ src/thrift/generate/t_ocaml_generator.cc \ src/thrift/generate/t_perl_generator.cc \ src/thrift/generate/t_php_generator.cc \ src/thrift/generate/t_py_generator.cc \ src/thrift/generate/t_rb_generator.cc \ src/thrift/generate/t_rs_generator.cc \ src/thrift/generate/t_st_generator.cc \ src/thrift/generate/t_swift_generator.cc \ src/thrift/generate/t_xml_generator.cc \ src/thrift/generate/t_xsd_generator.cc \ src/thrift/generate/validator_parser.cc \ src/thrift/generate/validator_parser.h \ src/thrift/generate/go_validator_generator.cc \ src/thrift/generate/go_validator_generator.h thrift_CPPFLAGS = -I$(srcdir)/src thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror thrift_LDADD = @LEXLIB@ src/thrift/libparse.a WINDOWS_DIST = \ compiler.sln \ compiler.vcxproj \ compiler.vcxproj.filters EXTRA_DIST = \ coding_standards.md \ README.md \ CMakeLists.txt \ test \ tests \ $(WINDOWS_DIST) all: all-recursive .SUFFIXES: .SUFFIXES: .cc .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign compiler/cpp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign compiler/cpp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list src/thrift/audit/$(am__dirstamp): @$(MKDIR_P) src/thrift/audit @: > src/thrift/audit/$(am__dirstamp) src/thrift/audit/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/audit/$(DEPDIR) @: > src/thrift/audit/$(DEPDIR)/$(am__dirstamp) src/thrift/audit/thrift-t_audit.$(OBJEXT): \ src/thrift/audit/$(am__dirstamp) \ src/thrift/audit/$(DEPDIR)/$(am__dirstamp) src/thrift/$(am__dirstamp): @$(MKDIR_P) src/thrift @: > src/thrift/$(am__dirstamp) src/thrift/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/$(DEPDIR) @: > src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/thrift-common.$(OBJEXT): src/thrift/$(am__dirstamp) \ src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/$(am__dirstamp): @$(MKDIR_P) src/thrift/generate @: > src/thrift/generate/$(am__dirstamp) src/thrift/generate/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/generate/$(DEPDIR) @: > src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/thrift-main.$(OBJEXT): src/thrift/$(am__dirstamp) \ src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/parse/$(am__dirstamp): @$(MKDIR_P) src/thrift/parse @: > src/thrift/parse/$(am__dirstamp) src/thrift/parse/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/parse/$(DEPDIR) @: > src/thrift/parse/$(DEPDIR)/$(am__dirstamp) src/thrift/parse/thrift-parse.$(OBJEXT): \ src/thrift/parse/$(am__dirstamp) \ src/thrift/parse/$(DEPDIR)/$(am__dirstamp) src/thrift/parse/thrift-t_typedef.$(OBJEXT): \ src/thrift/parse/$(am__dirstamp) \ src/thrift/parse/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_c_glib_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_cl_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_cpp_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_d_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_dart_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_delphi_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_erl_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_go_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_gv_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_haxe_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_html_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_markdown_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_java_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_javame_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_js_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_json_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_kotlin_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_lua_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_netstd_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_ocaml_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_perl_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_php_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_py_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_rb_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_rs_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_st_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_swift_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_xml_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-t_xsd_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-validator_parser.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) src/thrift/generate/thrift-go_validator_generator.$(OBJEXT): \ src/thrift/generate/$(am__dirstamp) \ src/thrift/generate/$(DEPDIR)/$(am__dirstamp) thrift$(EXEEXT): $(thrift_OBJECTS) $(thrift_DEPENDENCIES) $(EXTRA_thrift_DEPENDENCIES) @rm -f thrift$(EXEEXT) $(AM_V_CXXLD)$(thrift_LINK) $(thrift_OBJECTS) $(thrift_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f src/thrift/*.$(OBJEXT) -rm -f src/thrift/audit/*.$(OBJEXT) -rm -f src/thrift/generate/*.$(OBJEXT) -rm -f src/thrift/parse/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/$(DEPDIR)/thrift-common.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/$(DEPDIR)/thrift-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/audit/$(DEPDIR)/thrift-t_audit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/parse/$(DEPDIR)/thrift-parse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Po@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cc.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cc.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< src/thrift/audit/thrift-t_audit.o: src/thrift/audit/t_audit.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/audit/thrift-t_audit.o -MD -MP -MF src/thrift/audit/$(DEPDIR)/thrift-t_audit.Tpo -c -o src/thrift/audit/thrift-t_audit.o `test -f 'src/thrift/audit/t_audit.cpp' || echo '$(srcdir)/'`src/thrift/audit/t_audit.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/audit/$(DEPDIR)/thrift-t_audit.Tpo src/thrift/audit/$(DEPDIR)/thrift-t_audit.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/audit/t_audit.cpp' object='src/thrift/audit/thrift-t_audit.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/audit/thrift-t_audit.o `test -f 'src/thrift/audit/t_audit.cpp' || echo '$(srcdir)/'`src/thrift/audit/t_audit.cpp src/thrift/audit/thrift-t_audit.obj: src/thrift/audit/t_audit.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/audit/thrift-t_audit.obj -MD -MP -MF src/thrift/audit/$(DEPDIR)/thrift-t_audit.Tpo -c -o src/thrift/audit/thrift-t_audit.obj `if test -f 'src/thrift/audit/t_audit.cpp'; then $(CYGPATH_W) 'src/thrift/audit/t_audit.cpp'; else $(CYGPATH_W) '$(srcdir)/src/thrift/audit/t_audit.cpp'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/audit/$(DEPDIR)/thrift-t_audit.Tpo src/thrift/audit/$(DEPDIR)/thrift-t_audit.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/audit/t_audit.cpp' object='src/thrift/audit/thrift-t_audit.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/audit/thrift-t_audit.obj `if test -f 'src/thrift/audit/t_audit.cpp'; then $(CYGPATH_W) 'src/thrift/audit/t_audit.cpp'; else $(CYGPATH_W) '$(srcdir)/src/thrift/audit/t_audit.cpp'; fi` src/thrift/thrift-common.o: src/thrift/common.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/thrift-common.o -MD -MP -MF src/thrift/$(DEPDIR)/thrift-common.Tpo -c -o src/thrift/thrift-common.o `test -f 'src/thrift/common.cc' || echo '$(srcdir)/'`src/thrift/common.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/$(DEPDIR)/thrift-common.Tpo src/thrift/$(DEPDIR)/thrift-common.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/common.cc' object='src/thrift/thrift-common.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/thrift-common.o `test -f 'src/thrift/common.cc' || echo '$(srcdir)/'`src/thrift/common.cc src/thrift/thrift-common.obj: src/thrift/common.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/thrift-common.obj -MD -MP -MF src/thrift/$(DEPDIR)/thrift-common.Tpo -c -o src/thrift/thrift-common.obj `if test -f 'src/thrift/common.cc'; then $(CYGPATH_W) 'src/thrift/common.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/common.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/$(DEPDIR)/thrift-common.Tpo src/thrift/$(DEPDIR)/thrift-common.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/common.cc' object='src/thrift/thrift-common.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/thrift-common.obj `if test -f 'src/thrift/common.cc'; then $(CYGPATH_W) 'src/thrift/common.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/common.cc'; fi` src/thrift/generate/thrift-t_generator.o: src/thrift/generate/t_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_generator.Tpo -c -o src/thrift/generate/thrift-t_generator.o `test -f 'src/thrift/generate/t_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_generator.cc' object='src/thrift/generate/thrift-t_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_generator.o `test -f 'src/thrift/generate/t_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_generator.cc src/thrift/generate/thrift-t_generator.obj: src/thrift/generate/t_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_generator.Tpo -c -o src/thrift/generate/thrift-t_generator.obj `if test -f 'src/thrift/generate/t_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_generator.cc' object='src/thrift/generate/thrift-t_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_generator.obj `if test -f 'src/thrift/generate/t_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_generator.cc'; fi` src/thrift/thrift-main.o: src/thrift/main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/thrift-main.o -MD -MP -MF src/thrift/$(DEPDIR)/thrift-main.Tpo -c -o src/thrift/thrift-main.o `test -f 'src/thrift/main.cc' || echo '$(srcdir)/'`src/thrift/main.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/$(DEPDIR)/thrift-main.Tpo src/thrift/$(DEPDIR)/thrift-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/main.cc' object='src/thrift/thrift-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/thrift-main.o `test -f 'src/thrift/main.cc' || echo '$(srcdir)/'`src/thrift/main.cc src/thrift/thrift-main.obj: src/thrift/main.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/thrift-main.obj -MD -MP -MF src/thrift/$(DEPDIR)/thrift-main.Tpo -c -o src/thrift/thrift-main.obj `if test -f 'src/thrift/main.cc'; then $(CYGPATH_W) 'src/thrift/main.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/main.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/$(DEPDIR)/thrift-main.Tpo src/thrift/$(DEPDIR)/thrift-main.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/main.cc' object='src/thrift/thrift-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/thrift-main.obj `if test -f 'src/thrift/main.cc'; then $(CYGPATH_W) 'src/thrift/main.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/main.cc'; fi` src/thrift/parse/thrift-parse.o: src/thrift/parse/parse.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/parse/thrift-parse.o -MD -MP -MF src/thrift/parse/$(DEPDIR)/thrift-parse.Tpo -c -o src/thrift/parse/thrift-parse.o `test -f 'src/thrift/parse/parse.cc' || echo '$(srcdir)/'`src/thrift/parse/parse.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/parse/$(DEPDIR)/thrift-parse.Tpo src/thrift/parse/$(DEPDIR)/thrift-parse.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/parse/parse.cc' object='src/thrift/parse/thrift-parse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/parse/thrift-parse.o `test -f 'src/thrift/parse/parse.cc' || echo '$(srcdir)/'`src/thrift/parse/parse.cc src/thrift/parse/thrift-parse.obj: src/thrift/parse/parse.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/parse/thrift-parse.obj -MD -MP -MF src/thrift/parse/$(DEPDIR)/thrift-parse.Tpo -c -o src/thrift/parse/thrift-parse.obj `if test -f 'src/thrift/parse/parse.cc'; then $(CYGPATH_W) 'src/thrift/parse/parse.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/parse/parse.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/parse/$(DEPDIR)/thrift-parse.Tpo src/thrift/parse/$(DEPDIR)/thrift-parse.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/parse/parse.cc' object='src/thrift/parse/thrift-parse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/parse/thrift-parse.obj `if test -f 'src/thrift/parse/parse.cc'; then $(CYGPATH_W) 'src/thrift/parse/parse.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/parse/parse.cc'; fi` src/thrift/parse/thrift-t_typedef.o: src/thrift/parse/t_typedef.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/parse/thrift-t_typedef.o -MD -MP -MF src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Tpo -c -o src/thrift/parse/thrift-t_typedef.o `test -f 'src/thrift/parse/t_typedef.cc' || echo '$(srcdir)/'`src/thrift/parse/t_typedef.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Tpo src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/parse/t_typedef.cc' object='src/thrift/parse/thrift-t_typedef.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/parse/thrift-t_typedef.o `test -f 'src/thrift/parse/t_typedef.cc' || echo '$(srcdir)/'`src/thrift/parse/t_typedef.cc src/thrift/parse/thrift-t_typedef.obj: src/thrift/parse/t_typedef.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/parse/thrift-t_typedef.obj -MD -MP -MF src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Tpo -c -o src/thrift/parse/thrift-t_typedef.obj `if test -f 'src/thrift/parse/t_typedef.cc'; then $(CYGPATH_W) 'src/thrift/parse/t_typedef.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/parse/t_typedef.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Tpo src/thrift/parse/$(DEPDIR)/thrift-t_typedef.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/parse/t_typedef.cc' object='src/thrift/parse/thrift-t_typedef.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/parse/thrift-t_typedef.obj `if test -f 'src/thrift/parse/t_typedef.cc'; then $(CYGPATH_W) 'src/thrift/parse/t_typedef.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/parse/t_typedef.cc'; fi` src/thrift/generate/thrift-t_c_glib_generator.o: src/thrift/generate/t_c_glib_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_c_glib_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Tpo -c -o src/thrift/generate/thrift-t_c_glib_generator.o `test -f 'src/thrift/generate/t_c_glib_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_c_glib_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_c_glib_generator.cc' object='src/thrift/generate/thrift-t_c_glib_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_c_glib_generator.o `test -f 'src/thrift/generate/t_c_glib_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_c_glib_generator.cc src/thrift/generate/thrift-t_c_glib_generator.obj: src/thrift/generate/t_c_glib_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_c_glib_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Tpo -c -o src/thrift/generate/thrift-t_c_glib_generator.obj `if test -f 'src/thrift/generate/t_c_glib_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_c_glib_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_c_glib_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_c_glib_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_c_glib_generator.cc' object='src/thrift/generate/thrift-t_c_glib_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_c_glib_generator.obj `if test -f 'src/thrift/generate/t_c_glib_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_c_glib_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_c_glib_generator.cc'; fi` src/thrift/generate/thrift-t_cl_generator.o: src/thrift/generate/t_cl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_cl_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Tpo -c -o src/thrift/generate/thrift-t_cl_generator.o `test -f 'src/thrift/generate/t_cl_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_cl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_cl_generator.cc' object='src/thrift/generate/thrift-t_cl_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_cl_generator.o `test -f 'src/thrift/generate/t_cl_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_cl_generator.cc src/thrift/generate/thrift-t_cl_generator.obj: src/thrift/generate/t_cl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_cl_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Tpo -c -o src/thrift/generate/thrift-t_cl_generator.obj `if test -f 'src/thrift/generate/t_cl_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_cl_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_cl_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_cl_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_cl_generator.cc' object='src/thrift/generate/thrift-t_cl_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_cl_generator.obj `if test -f 'src/thrift/generate/t_cl_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_cl_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_cl_generator.cc'; fi` src/thrift/generate/thrift-t_cpp_generator.o: src/thrift/generate/t_cpp_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_cpp_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Tpo -c -o src/thrift/generate/thrift-t_cpp_generator.o `test -f 'src/thrift/generate/t_cpp_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_cpp_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_cpp_generator.cc' object='src/thrift/generate/thrift-t_cpp_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_cpp_generator.o `test -f 'src/thrift/generate/t_cpp_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_cpp_generator.cc src/thrift/generate/thrift-t_cpp_generator.obj: src/thrift/generate/t_cpp_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_cpp_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Tpo -c -o src/thrift/generate/thrift-t_cpp_generator.obj `if test -f 'src/thrift/generate/t_cpp_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_cpp_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_cpp_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_cpp_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_cpp_generator.cc' object='src/thrift/generate/thrift-t_cpp_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_cpp_generator.obj `if test -f 'src/thrift/generate/t_cpp_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_cpp_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_cpp_generator.cc'; fi` src/thrift/generate/thrift-t_d_generator.o: src/thrift/generate/t_d_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_d_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Tpo -c -o src/thrift/generate/thrift-t_d_generator.o `test -f 'src/thrift/generate/t_d_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_d_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_d_generator.cc' object='src/thrift/generate/thrift-t_d_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_d_generator.o `test -f 'src/thrift/generate/t_d_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_d_generator.cc src/thrift/generate/thrift-t_d_generator.obj: src/thrift/generate/t_d_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_d_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Tpo -c -o src/thrift/generate/thrift-t_d_generator.obj `if test -f 'src/thrift/generate/t_d_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_d_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_d_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_d_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_d_generator.cc' object='src/thrift/generate/thrift-t_d_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_d_generator.obj `if test -f 'src/thrift/generate/t_d_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_d_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_d_generator.cc'; fi` src/thrift/generate/thrift-t_dart_generator.o: src/thrift/generate/t_dart_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_dart_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Tpo -c -o src/thrift/generate/thrift-t_dart_generator.o `test -f 'src/thrift/generate/t_dart_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_dart_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_dart_generator.cc' object='src/thrift/generate/thrift-t_dart_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_dart_generator.o `test -f 'src/thrift/generate/t_dart_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_dart_generator.cc src/thrift/generate/thrift-t_dart_generator.obj: src/thrift/generate/t_dart_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_dart_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Tpo -c -o src/thrift/generate/thrift-t_dart_generator.obj `if test -f 'src/thrift/generate/t_dart_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_dart_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_dart_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_dart_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_dart_generator.cc' object='src/thrift/generate/thrift-t_dart_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_dart_generator.obj `if test -f 'src/thrift/generate/t_dart_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_dart_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_dart_generator.cc'; fi` src/thrift/generate/thrift-t_delphi_generator.o: src/thrift/generate/t_delphi_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_delphi_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Tpo -c -o src/thrift/generate/thrift-t_delphi_generator.o `test -f 'src/thrift/generate/t_delphi_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_delphi_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_delphi_generator.cc' object='src/thrift/generate/thrift-t_delphi_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_delphi_generator.o `test -f 'src/thrift/generate/t_delphi_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_delphi_generator.cc src/thrift/generate/thrift-t_delphi_generator.obj: src/thrift/generate/t_delphi_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_delphi_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Tpo -c -o src/thrift/generate/thrift-t_delphi_generator.obj `if test -f 'src/thrift/generate/t_delphi_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_delphi_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_delphi_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_delphi_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_delphi_generator.cc' object='src/thrift/generate/thrift-t_delphi_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_delphi_generator.obj `if test -f 'src/thrift/generate/t_delphi_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_delphi_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_delphi_generator.cc'; fi` src/thrift/generate/thrift-t_erl_generator.o: src/thrift/generate/t_erl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_erl_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Tpo -c -o src/thrift/generate/thrift-t_erl_generator.o `test -f 'src/thrift/generate/t_erl_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_erl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_erl_generator.cc' object='src/thrift/generate/thrift-t_erl_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_erl_generator.o `test -f 'src/thrift/generate/t_erl_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_erl_generator.cc src/thrift/generate/thrift-t_erl_generator.obj: src/thrift/generate/t_erl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_erl_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Tpo -c -o src/thrift/generate/thrift-t_erl_generator.obj `if test -f 'src/thrift/generate/t_erl_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_erl_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_erl_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_erl_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_erl_generator.cc' object='src/thrift/generate/thrift-t_erl_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_erl_generator.obj `if test -f 'src/thrift/generate/t_erl_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_erl_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_erl_generator.cc'; fi` src/thrift/generate/thrift-t_go_generator.o: src/thrift/generate/t_go_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_go_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Tpo -c -o src/thrift/generate/thrift-t_go_generator.o `test -f 'src/thrift/generate/t_go_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_go_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_go_generator.cc' object='src/thrift/generate/thrift-t_go_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_go_generator.o `test -f 'src/thrift/generate/t_go_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_go_generator.cc src/thrift/generate/thrift-t_go_generator.obj: src/thrift/generate/t_go_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_go_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Tpo -c -o src/thrift/generate/thrift-t_go_generator.obj `if test -f 'src/thrift/generate/t_go_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_go_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_go_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_go_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_go_generator.cc' object='src/thrift/generate/thrift-t_go_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_go_generator.obj `if test -f 'src/thrift/generate/t_go_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_go_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_go_generator.cc'; fi` src/thrift/generate/thrift-t_gv_generator.o: src/thrift/generate/t_gv_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_gv_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Tpo -c -o src/thrift/generate/thrift-t_gv_generator.o `test -f 'src/thrift/generate/t_gv_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_gv_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_gv_generator.cc' object='src/thrift/generate/thrift-t_gv_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_gv_generator.o `test -f 'src/thrift/generate/t_gv_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_gv_generator.cc src/thrift/generate/thrift-t_gv_generator.obj: src/thrift/generate/t_gv_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_gv_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Tpo -c -o src/thrift/generate/thrift-t_gv_generator.obj `if test -f 'src/thrift/generate/t_gv_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_gv_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_gv_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_gv_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_gv_generator.cc' object='src/thrift/generate/thrift-t_gv_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_gv_generator.obj `if test -f 'src/thrift/generate/t_gv_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_gv_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_gv_generator.cc'; fi` src/thrift/generate/thrift-t_haxe_generator.o: src/thrift/generate/t_haxe_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_haxe_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Tpo -c -o src/thrift/generate/thrift-t_haxe_generator.o `test -f 'src/thrift/generate/t_haxe_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_haxe_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_haxe_generator.cc' object='src/thrift/generate/thrift-t_haxe_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_haxe_generator.o `test -f 'src/thrift/generate/t_haxe_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_haxe_generator.cc src/thrift/generate/thrift-t_haxe_generator.obj: src/thrift/generate/t_haxe_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_haxe_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Tpo -c -o src/thrift/generate/thrift-t_haxe_generator.obj `if test -f 'src/thrift/generate/t_haxe_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_haxe_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_haxe_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_haxe_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_haxe_generator.cc' object='src/thrift/generate/thrift-t_haxe_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_haxe_generator.obj `if test -f 'src/thrift/generate/t_haxe_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_haxe_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_haxe_generator.cc'; fi` src/thrift/generate/thrift-t_html_generator.o: src/thrift/generate/t_html_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_html_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Tpo -c -o src/thrift/generate/thrift-t_html_generator.o `test -f 'src/thrift/generate/t_html_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_html_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_html_generator.cc' object='src/thrift/generate/thrift-t_html_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_html_generator.o `test -f 'src/thrift/generate/t_html_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_html_generator.cc src/thrift/generate/thrift-t_html_generator.obj: src/thrift/generate/t_html_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_html_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Tpo -c -o src/thrift/generate/thrift-t_html_generator.obj `if test -f 'src/thrift/generate/t_html_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_html_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_html_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_html_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_html_generator.cc' object='src/thrift/generate/thrift-t_html_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_html_generator.obj `if test -f 'src/thrift/generate/t_html_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_html_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_html_generator.cc'; fi` src/thrift/generate/thrift-t_markdown_generator.o: src/thrift/generate/t_markdown_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_markdown_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Tpo -c -o src/thrift/generate/thrift-t_markdown_generator.o `test -f 'src/thrift/generate/t_markdown_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_markdown_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_markdown_generator.cc' object='src/thrift/generate/thrift-t_markdown_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_markdown_generator.o `test -f 'src/thrift/generate/t_markdown_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_markdown_generator.cc src/thrift/generate/thrift-t_markdown_generator.obj: src/thrift/generate/t_markdown_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_markdown_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Tpo -c -o src/thrift/generate/thrift-t_markdown_generator.obj `if test -f 'src/thrift/generate/t_markdown_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_markdown_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_markdown_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_markdown_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_markdown_generator.cc' object='src/thrift/generate/thrift-t_markdown_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_markdown_generator.obj `if test -f 'src/thrift/generate/t_markdown_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_markdown_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_markdown_generator.cc'; fi` src/thrift/generate/thrift-t_java_generator.o: src/thrift/generate/t_java_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_java_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Tpo -c -o src/thrift/generate/thrift-t_java_generator.o `test -f 'src/thrift/generate/t_java_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_java_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_java_generator.cc' object='src/thrift/generate/thrift-t_java_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_java_generator.o `test -f 'src/thrift/generate/t_java_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_java_generator.cc src/thrift/generate/thrift-t_java_generator.obj: src/thrift/generate/t_java_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_java_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Tpo -c -o src/thrift/generate/thrift-t_java_generator.obj `if test -f 'src/thrift/generate/t_java_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_java_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_java_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_java_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_java_generator.cc' object='src/thrift/generate/thrift-t_java_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_java_generator.obj `if test -f 'src/thrift/generate/t_java_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_java_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_java_generator.cc'; fi` src/thrift/generate/thrift-t_javame_generator.o: src/thrift/generate/t_javame_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_javame_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Tpo -c -o src/thrift/generate/thrift-t_javame_generator.o `test -f 'src/thrift/generate/t_javame_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_javame_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_javame_generator.cc' object='src/thrift/generate/thrift-t_javame_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_javame_generator.o `test -f 'src/thrift/generate/t_javame_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_javame_generator.cc src/thrift/generate/thrift-t_javame_generator.obj: src/thrift/generate/t_javame_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_javame_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Tpo -c -o src/thrift/generate/thrift-t_javame_generator.obj `if test -f 'src/thrift/generate/t_javame_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_javame_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_javame_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_javame_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_javame_generator.cc' object='src/thrift/generate/thrift-t_javame_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_javame_generator.obj `if test -f 'src/thrift/generate/t_javame_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_javame_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_javame_generator.cc'; fi` src/thrift/generate/thrift-t_js_generator.o: src/thrift/generate/t_js_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_js_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Tpo -c -o src/thrift/generate/thrift-t_js_generator.o `test -f 'src/thrift/generate/t_js_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_js_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_js_generator.cc' object='src/thrift/generate/thrift-t_js_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_js_generator.o `test -f 'src/thrift/generate/t_js_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_js_generator.cc src/thrift/generate/thrift-t_js_generator.obj: src/thrift/generate/t_js_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_js_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Tpo -c -o src/thrift/generate/thrift-t_js_generator.obj `if test -f 'src/thrift/generate/t_js_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_js_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_js_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_js_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_js_generator.cc' object='src/thrift/generate/thrift-t_js_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_js_generator.obj `if test -f 'src/thrift/generate/t_js_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_js_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_js_generator.cc'; fi` src/thrift/generate/thrift-t_json_generator.o: src/thrift/generate/t_json_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_json_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Tpo -c -o src/thrift/generate/thrift-t_json_generator.o `test -f 'src/thrift/generate/t_json_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_json_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_json_generator.cc' object='src/thrift/generate/thrift-t_json_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_json_generator.o `test -f 'src/thrift/generate/t_json_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_json_generator.cc src/thrift/generate/thrift-t_json_generator.obj: src/thrift/generate/t_json_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_json_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Tpo -c -o src/thrift/generate/thrift-t_json_generator.obj `if test -f 'src/thrift/generate/t_json_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_json_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_json_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_json_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_json_generator.cc' object='src/thrift/generate/thrift-t_json_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_json_generator.obj `if test -f 'src/thrift/generate/t_json_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_json_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_json_generator.cc'; fi` src/thrift/generate/thrift-t_kotlin_generator.o: src/thrift/generate/t_kotlin_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_kotlin_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Tpo -c -o src/thrift/generate/thrift-t_kotlin_generator.o `test -f 'src/thrift/generate/t_kotlin_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_kotlin_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_kotlin_generator.cc' object='src/thrift/generate/thrift-t_kotlin_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_kotlin_generator.o `test -f 'src/thrift/generate/t_kotlin_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_kotlin_generator.cc src/thrift/generate/thrift-t_kotlin_generator.obj: src/thrift/generate/t_kotlin_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_kotlin_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Tpo -c -o src/thrift/generate/thrift-t_kotlin_generator.obj `if test -f 'src/thrift/generate/t_kotlin_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_kotlin_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_kotlin_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_kotlin_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_kotlin_generator.cc' object='src/thrift/generate/thrift-t_kotlin_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_kotlin_generator.obj `if test -f 'src/thrift/generate/t_kotlin_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_kotlin_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_kotlin_generator.cc'; fi` src/thrift/generate/thrift-t_lua_generator.o: src/thrift/generate/t_lua_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_lua_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Tpo -c -o src/thrift/generate/thrift-t_lua_generator.o `test -f 'src/thrift/generate/t_lua_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_lua_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_lua_generator.cc' object='src/thrift/generate/thrift-t_lua_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_lua_generator.o `test -f 'src/thrift/generate/t_lua_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_lua_generator.cc src/thrift/generate/thrift-t_lua_generator.obj: src/thrift/generate/t_lua_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_lua_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Tpo -c -o src/thrift/generate/thrift-t_lua_generator.obj `if test -f 'src/thrift/generate/t_lua_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_lua_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_lua_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_lua_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_lua_generator.cc' object='src/thrift/generate/thrift-t_lua_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_lua_generator.obj `if test -f 'src/thrift/generate/t_lua_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_lua_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_lua_generator.cc'; fi` src/thrift/generate/thrift-t_netstd_generator.o: src/thrift/generate/t_netstd_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_netstd_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Tpo -c -o src/thrift/generate/thrift-t_netstd_generator.o `test -f 'src/thrift/generate/t_netstd_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_netstd_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_netstd_generator.cc' object='src/thrift/generate/thrift-t_netstd_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_netstd_generator.o `test -f 'src/thrift/generate/t_netstd_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_netstd_generator.cc src/thrift/generate/thrift-t_netstd_generator.obj: src/thrift/generate/t_netstd_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_netstd_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Tpo -c -o src/thrift/generate/thrift-t_netstd_generator.obj `if test -f 'src/thrift/generate/t_netstd_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_netstd_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_netstd_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_netstd_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_netstd_generator.cc' object='src/thrift/generate/thrift-t_netstd_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_netstd_generator.obj `if test -f 'src/thrift/generate/t_netstd_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_netstd_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_netstd_generator.cc'; fi` src/thrift/generate/thrift-t_ocaml_generator.o: src/thrift/generate/t_ocaml_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_ocaml_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Tpo -c -o src/thrift/generate/thrift-t_ocaml_generator.o `test -f 'src/thrift/generate/t_ocaml_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_ocaml_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_ocaml_generator.cc' object='src/thrift/generate/thrift-t_ocaml_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_ocaml_generator.o `test -f 'src/thrift/generate/t_ocaml_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_ocaml_generator.cc src/thrift/generate/thrift-t_ocaml_generator.obj: src/thrift/generate/t_ocaml_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_ocaml_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Tpo -c -o src/thrift/generate/thrift-t_ocaml_generator.obj `if test -f 'src/thrift/generate/t_ocaml_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_ocaml_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_ocaml_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_ocaml_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_ocaml_generator.cc' object='src/thrift/generate/thrift-t_ocaml_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_ocaml_generator.obj `if test -f 'src/thrift/generate/t_ocaml_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_ocaml_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_ocaml_generator.cc'; fi` src/thrift/generate/thrift-t_perl_generator.o: src/thrift/generate/t_perl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_perl_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Tpo -c -o src/thrift/generate/thrift-t_perl_generator.o `test -f 'src/thrift/generate/t_perl_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_perl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_perl_generator.cc' object='src/thrift/generate/thrift-t_perl_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_perl_generator.o `test -f 'src/thrift/generate/t_perl_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_perl_generator.cc src/thrift/generate/thrift-t_perl_generator.obj: src/thrift/generate/t_perl_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_perl_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Tpo -c -o src/thrift/generate/thrift-t_perl_generator.obj `if test -f 'src/thrift/generate/t_perl_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_perl_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_perl_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_perl_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_perl_generator.cc' object='src/thrift/generate/thrift-t_perl_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_perl_generator.obj `if test -f 'src/thrift/generate/t_perl_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_perl_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_perl_generator.cc'; fi` src/thrift/generate/thrift-t_php_generator.o: src/thrift/generate/t_php_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_php_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Tpo -c -o src/thrift/generate/thrift-t_php_generator.o `test -f 'src/thrift/generate/t_php_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_php_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_php_generator.cc' object='src/thrift/generate/thrift-t_php_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_php_generator.o `test -f 'src/thrift/generate/t_php_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_php_generator.cc src/thrift/generate/thrift-t_php_generator.obj: src/thrift/generate/t_php_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_php_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Tpo -c -o src/thrift/generate/thrift-t_php_generator.obj `if test -f 'src/thrift/generate/t_php_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_php_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_php_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_php_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_php_generator.cc' object='src/thrift/generate/thrift-t_php_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_php_generator.obj `if test -f 'src/thrift/generate/t_php_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_php_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_php_generator.cc'; fi` src/thrift/generate/thrift-t_py_generator.o: src/thrift/generate/t_py_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_py_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Tpo -c -o src/thrift/generate/thrift-t_py_generator.o `test -f 'src/thrift/generate/t_py_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_py_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_py_generator.cc' object='src/thrift/generate/thrift-t_py_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_py_generator.o `test -f 'src/thrift/generate/t_py_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_py_generator.cc src/thrift/generate/thrift-t_py_generator.obj: src/thrift/generate/t_py_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_py_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Tpo -c -o src/thrift/generate/thrift-t_py_generator.obj `if test -f 'src/thrift/generate/t_py_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_py_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_py_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_py_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_py_generator.cc' object='src/thrift/generate/thrift-t_py_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_py_generator.obj `if test -f 'src/thrift/generate/t_py_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_py_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_py_generator.cc'; fi` src/thrift/generate/thrift-t_rb_generator.o: src/thrift/generate/t_rb_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_rb_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Tpo -c -o src/thrift/generate/thrift-t_rb_generator.o `test -f 'src/thrift/generate/t_rb_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_rb_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_rb_generator.cc' object='src/thrift/generate/thrift-t_rb_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_rb_generator.o `test -f 'src/thrift/generate/t_rb_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_rb_generator.cc src/thrift/generate/thrift-t_rb_generator.obj: src/thrift/generate/t_rb_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_rb_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Tpo -c -o src/thrift/generate/thrift-t_rb_generator.obj `if test -f 'src/thrift/generate/t_rb_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_rb_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_rb_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_rb_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_rb_generator.cc' object='src/thrift/generate/thrift-t_rb_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_rb_generator.obj `if test -f 'src/thrift/generate/t_rb_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_rb_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_rb_generator.cc'; fi` src/thrift/generate/thrift-t_rs_generator.o: src/thrift/generate/t_rs_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_rs_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Tpo -c -o src/thrift/generate/thrift-t_rs_generator.o `test -f 'src/thrift/generate/t_rs_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_rs_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_rs_generator.cc' object='src/thrift/generate/thrift-t_rs_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_rs_generator.o `test -f 'src/thrift/generate/t_rs_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_rs_generator.cc src/thrift/generate/thrift-t_rs_generator.obj: src/thrift/generate/t_rs_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_rs_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Tpo -c -o src/thrift/generate/thrift-t_rs_generator.obj `if test -f 'src/thrift/generate/t_rs_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_rs_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_rs_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_rs_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_rs_generator.cc' object='src/thrift/generate/thrift-t_rs_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_rs_generator.obj `if test -f 'src/thrift/generate/t_rs_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_rs_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_rs_generator.cc'; fi` src/thrift/generate/thrift-t_st_generator.o: src/thrift/generate/t_st_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_st_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Tpo -c -o src/thrift/generate/thrift-t_st_generator.o `test -f 'src/thrift/generate/t_st_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_st_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_st_generator.cc' object='src/thrift/generate/thrift-t_st_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_st_generator.o `test -f 'src/thrift/generate/t_st_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_st_generator.cc src/thrift/generate/thrift-t_st_generator.obj: src/thrift/generate/t_st_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_st_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Tpo -c -o src/thrift/generate/thrift-t_st_generator.obj `if test -f 'src/thrift/generate/t_st_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_st_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_st_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_st_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_st_generator.cc' object='src/thrift/generate/thrift-t_st_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_st_generator.obj `if test -f 'src/thrift/generate/t_st_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_st_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_st_generator.cc'; fi` src/thrift/generate/thrift-t_swift_generator.o: src/thrift/generate/t_swift_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_swift_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Tpo -c -o src/thrift/generate/thrift-t_swift_generator.o `test -f 'src/thrift/generate/t_swift_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_swift_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_swift_generator.cc' object='src/thrift/generate/thrift-t_swift_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_swift_generator.o `test -f 'src/thrift/generate/t_swift_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_swift_generator.cc src/thrift/generate/thrift-t_swift_generator.obj: src/thrift/generate/t_swift_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_swift_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Tpo -c -o src/thrift/generate/thrift-t_swift_generator.obj `if test -f 'src/thrift/generate/t_swift_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_swift_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_swift_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_swift_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_swift_generator.cc' object='src/thrift/generate/thrift-t_swift_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_swift_generator.obj `if test -f 'src/thrift/generate/t_swift_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_swift_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_swift_generator.cc'; fi` src/thrift/generate/thrift-t_xml_generator.o: src/thrift/generate/t_xml_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_xml_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Tpo -c -o src/thrift/generate/thrift-t_xml_generator.o `test -f 'src/thrift/generate/t_xml_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_xml_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_xml_generator.cc' object='src/thrift/generate/thrift-t_xml_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_xml_generator.o `test -f 'src/thrift/generate/t_xml_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_xml_generator.cc src/thrift/generate/thrift-t_xml_generator.obj: src/thrift/generate/t_xml_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_xml_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Tpo -c -o src/thrift/generate/thrift-t_xml_generator.obj `if test -f 'src/thrift/generate/t_xml_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_xml_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_xml_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_xml_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_xml_generator.cc' object='src/thrift/generate/thrift-t_xml_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_xml_generator.obj `if test -f 'src/thrift/generate/t_xml_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_xml_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_xml_generator.cc'; fi` src/thrift/generate/thrift-t_xsd_generator.o: src/thrift/generate/t_xsd_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_xsd_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Tpo -c -o src/thrift/generate/thrift-t_xsd_generator.o `test -f 'src/thrift/generate/t_xsd_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_xsd_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_xsd_generator.cc' object='src/thrift/generate/thrift-t_xsd_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_xsd_generator.o `test -f 'src/thrift/generate/t_xsd_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/t_xsd_generator.cc src/thrift/generate/thrift-t_xsd_generator.obj: src/thrift/generate/t_xsd_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-t_xsd_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Tpo -c -o src/thrift/generate/thrift-t_xsd_generator.obj `if test -f 'src/thrift/generate/t_xsd_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_xsd_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_xsd_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-t_xsd_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/t_xsd_generator.cc' object='src/thrift/generate/thrift-t_xsd_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-t_xsd_generator.obj `if test -f 'src/thrift/generate/t_xsd_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/t_xsd_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/t_xsd_generator.cc'; fi` src/thrift/generate/thrift-validator_parser.o: src/thrift/generate/validator_parser.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-validator_parser.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Tpo -c -o src/thrift/generate/thrift-validator_parser.o `test -f 'src/thrift/generate/validator_parser.cc' || echo '$(srcdir)/'`src/thrift/generate/validator_parser.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Tpo src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/validator_parser.cc' object='src/thrift/generate/thrift-validator_parser.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-validator_parser.o `test -f 'src/thrift/generate/validator_parser.cc' || echo '$(srcdir)/'`src/thrift/generate/validator_parser.cc src/thrift/generate/thrift-validator_parser.obj: src/thrift/generate/validator_parser.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-validator_parser.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Tpo -c -o src/thrift/generate/thrift-validator_parser.obj `if test -f 'src/thrift/generate/validator_parser.cc'; then $(CYGPATH_W) 'src/thrift/generate/validator_parser.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/validator_parser.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Tpo src/thrift/generate/$(DEPDIR)/thrift-validator_parser.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/validator_parser.cc' object='src/thrift/generate/thrift-validator_parser.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-validator_parser.obj `if test -f 'src/thrift/generate/validator_parser.cc'; then $(CYGPATH_W) 'src/thrift/generate/validator_parser.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/validator_parser.cc'; fi` src/thrift/generate/thrift-go_validator_generator.o: src/thrift/generate/go_validator_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-go_validator_generator.o -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Tpo -c -o src/thrift/generate/thrift-go_validator_generator.o `test -f 'src/thrift/generate/go_validator_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/go_validator_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/go_validator_generator.cc' object='src/thrift/generate/thrift-go_validator_generator.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-go_validator_generator.o `test -f 'src/thrift/generate/go_validator_generator.cc' || echo '$(srcdir)/'`src/thrift/generate/go_validator_generator.cc src/thrift/generate/thrift-go_validator_generator.obj: src/thrift/generate/go_validator_generator.cc @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/generate/thrift-go_validator_generator.obj -MD -MP -MF src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Tpo -c -o src/thrift/generate/thrift-go_validator_generator.obj `if test -f 'src/thrift/generate/go_validator_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/go_validator_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/go_validator_generator.cc'; fi` @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Tpo src/thrift/generate/$(DEPDIR)/thrift-go_validator_generator.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/generate/go_validator_generator.cc' object='src/thrift/generate/thrift-go_validator_generator.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(thrift_CPPFLAGS) $(CPPFLAGS) $(thrift_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/generate/thrift-go_validator_generator.obj `if test -f 'src/thrift/generate/go_validator_generator.cc'; then $(CYGPATH_W) 'src/thrift/generate/go_validator_generator.cc'; else $(CYGPATH_W) '$(srcdir)/src/thrift/generate/go_validator_generator.cc'; fi` .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f src/thrift/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/$(am__dirstamp) -rm -f src/thrift/audit/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/audit/$(am__dirstamp) -rm -f src/thrift/generate/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/generate/$(am__dirstamp) -rm -f src/thrift/parse/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/parse/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -rf src/thrift/$(DEPDIR) src/thrift/audit/$(DEPDIR) src/thrift/generate/$(DEPDIR) src/thrift/parse/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf src/thrift/$(DEPDIR) src/thrift/audit/$(DEPDIR) src/thrift/generate/$(DEPDIR) src/thrift/parse/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: uninstall-binPROGRAMS .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-binPROGRAMS clean-generic clean-libtool \ cscopelist-am ctags ctags-am distclean distclean-compile \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile #clean-local: # $(RM) version.h -- do not delete, we need it src/thrift/main.cc: src/thrift/version.h style-local: $(CPPSTYLE_CMD) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/compiler/cpp/compiler.vcxproj0000644000000000000000000003234614370300523020727 0ustar00rootroot00000000000000 Debug Win32 Debug x64 Release Win32 Release x64 {89975A1A-F799-4556-98B8-64E30AB39A90} Win32Proj compiler Application true MultiByte Application true MultiByte Application false true MultiByte Application false true MultiByte true $(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath) thrift $(ExecutablePath);C:\Program Files (x86)\Git\bin true $(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath) thrift $(ExecutablePath);C:\Program Files (x86)\Git\bin false $(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath) thrift $(ExecutablePath);C:\Program Files (x86)\Git\bin false $(ProjectDir)\src\;$(ProjectDir)\src\windows\;$(IncludePath) thrift $(ExecutablePath);C:\Program Files (x86)\Git\bin Level3 Disabled WIN32;MINGW;YY_NO_UNISTD_H;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) thrift\windows\config.h CompileAsCpp MultiThreadedDebugDLL Console true flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll && bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy Level3 Disabled WIN32;MINGW;YY_NO_UNISTD_H;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) thrift\windows\config.h CompileAsCpp MultiThreadedDLL Console true flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll && bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy Level3 MaxSpeed true true WIN32;MINGW;YY_NO_UNISTD_H;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) thrift\windows\config.h CompileAsCpp MultiThreadedDLL Console true true true flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll && bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy Level3 MaxSpeed true true WIN32;MINGW;YY_NO_UNISTD_H;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) thrift\windows\config.h CompileAsCpp MultiThreadedDLL Console true true true flex -o "src\\thrift\\thriftl.cc" src/thrift/thriftl.ll && bison -y -o "src\\thrift\\thrifty.cc" --defines="src\\thrift\\thrifty.hh" src/thrift/thrifty.yy thrift-0.19.0/contrib/0000777000000000000000000000000014454461475014561 5ustar00rootroot00000000000000thrift-0.19.0/contrib/Vagrantfile0000644000000000000000000000764514303740367016747 0ustar00rootroot00000000000000# -*- mode: ruby -*- # vi: set ft=ruby : # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $build_and_test = < ### hello.js - Node Server var thrift = require('thrift'); var hello_svc = require('./gen-nodejs/hello_svc.js'); var hello_handler = { get_message: function(name, result) { var msg = "Hello " + name + "!"; result(null, msg); } } var hello_svc_opt = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, processor: hello_svc, handler: hello_handler }; var server_opt = { staticFilePath: ".", services: { "/hello": hello_svc_opt } } var server = Thrift.createWebServer(server_opt); var port = 9099; server.listen(port); console.log("Http/Thrift Server running on port: " + port); TypeScript ------------------------------------ TypeScript definition files can also be generated by running: thrift --gen js:ts file.thrift # Breaking Changes ## 0.13.0 1. 64-bit integer constants are now generatd using node-int64 e.g.: var x = new Int64("7fffffffffffffff"); thrift-0.19.0/lib/js/coding_standards.md0000644000000000000000000000010314303740367020112 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/js/test/0000777000000000000000000000000014472652604015256 5ustar00rootroot00000000000000thrift-0.19.0/lib/js/test/test-async.js0000644000000000000000000003061714303740367017706 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ /* * Fully Async JavaScript test suite for ThriftTest.thrift. * These tests are designed to exercise the WebSocket transport * (which is exclusively async). * * To compile client code for this test use: * $ thrift -gen js ThriftTest.thrift */ // all Languages in UTF-8 const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Bahasa Melayu, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; function checkRecursively(assert, map1, map2) { if (typeof map1 !== 'function' && typeof map2 !== 'function') { if (!map1 || typeof map1 !== 'object') { assert.equal(map1, map2); } else { for (let key in map1) { checkRecursively(assert, map1[key], map2[key]); } } } } QUnit.module('Base Types'); QUnit.test('Void', function(assert) { assert.expect(1); const done = assert.async(); client.testVoid(function(result) { assert.equal(result, undefined); done(); }); }); QUnit.test('String', function(assert) { assert.expect(3); const done = assert.async(3); client.testString('', function(result) { assert.equal(result, ''); done(); }); client.testString(stringTest, function(result) { assert.equal(result, stringTest); done(); }); const specialCharacters = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; client.testString(specialCharacters, function(result) { assert.equal(result, specialCharacters); done(); }); }); QUnit.test('Double', function(assert) { assert.expect(4); const done = assert.async(4); client.testDouble(0, function(result) { assert.equal(result, 0); done(); }); client.testDouble(-1, function(result) { assert.equal(result, -1); done(); }); client.testDouble(3.14, function(result) { assert.equal(result, 3.14); done(); }); client.testDouble(Math.pow(2, 60), function(result) { assert.equal(result, Math.pow(2, 60)); done(); }); }); // TODO: add testBinary() QUnit.test('Byte', function(assert) { assert.expect(2); const done = assert.async(2); client.testByte(0, function(result) { assert.equal(result, 0); done(); }); client.testByte(0x01, function(result) { assert.equal(result, 0x01); done(); }); }); QUnit.test('I32', function(assert) { assert.expect(3); const done = assert.async(3); client.testI32(0, function(result) { assert.equal(result, 0); done(); }); client.testI32(Math.pow(2, 30), function(result) { assert.equal(result, Math.pow(2, 30)); done(); }); client.testI32(-Math.pow(2, 30), function(result) { assert.equal(result, -Math.pow(2, 30)); done(); }); }); QUnit.test('I64', function(assert) { assert.expect(3); const done = assert.async(3); client.testI64(0, function(result) { assert.equal(result, 0); done(); }); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately client.testI64(Math.pow(2, 52), function(result) { assert.equal(result, Math.pow(2, 52)); done(); }); client.testI64(-Math.pow(2, 52), function(result) { assert.equal(result, -Math.pow(2, 52)); done(); }); }); QUnit.module('Structured Types'); QUnit.test('Struct', function(assert) { assert.expect(5); const done = assert.async(); const structTestInput = new ThriftTest.Xtruct(); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately structTestInput.i64_thing = Math.pow(2, 52); client.testStruct(structTestInput, function(result) { assert.equal(result.string_thing, structTestInput.string_thing); assert.equal(result.byte_thing, structTestInput.byte_thing); assert.equal(result.i32_thing, structTestInput.i32_thing); assert.equal(result.i64_thing, structTestInput.i64_thing); assert.equal(JSON.stringify(result), JSON.stringify(structTestInput)); done(); }); }); QUnit.test('Nest', function(assert) { assert.expect(7); const done = assert.async(); const xtrTestInput = new ThriftTest.Xtruct(); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately xtrTestInput.i64_thing = Math.pow(2, 52); const nestTestInput = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; nestTestInput.struct_thing = xtrTestInput; nestTestInput.i32_thing = Math.pow(2, 15); client.testNest(nestTestInput, function(result) { assert.equal(result.byte_thing, nestTestInput.byte_thing); assert.equal(result.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); assert.equal(result.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); assert.equal(result.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); assert.equal(result.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing); assert.equal(result.i32_thing, nestTestInput.i32_thing); assert.equal(JSON.stringify(result), JSON.stringify(nestTestInput)); done(); }); }); QUnit.test('Map', function(assert) { assert.expect(3); const done = assert.async(); const mapTestInput = {7: 77, 8: 88, 9: 99}; client.testMap(mapTestInput, function(result) { for (let key in result) { assert.equal(result[key], mapTestInput[key]); } done(); }); }); QUnit.test('StringMap', function(assert) { assert.expect(6); const done = assert.async(); const mapTestInput = { 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', 'longValue': stringTest, stringTest: 'long key' }; client.testStringMap(mapTestInput, function(result) { for (let key in result) { assert.equal(result[key], mapTestInput[key]); } done(); }); }); QUnit.test('Set', function(assert) { assert.expect(1); const done = assert.async(); const setTestInput = [1, 2, 3]; client.testSet(setTestInput, function(result) { assert.ok(result, setTestInput); done(); }); }); QUnit.test('List', function(assert) { assert.expect(1); const done = assert.async(); const listTestInput = [1, 2, 3]; client.testList(listTestInput, function(result) { assert.ok(result, listTestInput); done(); }); }); QUnit.test('Enum', function(assert) { assert.expect(1); const done = assert.async(); client.testEnum(ThriftTest.Numberz.ONE, function(result) { assert.equal(result, ThriftTest.Numberz.ONE); done(); }); }); QUnit.test('TypeDef', function(assert) { assert.expect(1); const done = assert.async(); client.testTypedef(69, function(result) { assert.equal(result, 69); done(); }); }); QUnit.module('deeper!'); QUnit.test('MapMap', function(assert) { assert.expect(16); const done = assert.async(); const mapMapTestExpectedResult = { '4': {'1': 1, '2': 2, '3': 3, '4': 4}, '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} }; client.testMapMap(1, function(result) { for (let key in result) { for (let key2 in result[key]) { assert.equal(result[key][key2], mapMapTestExpectedResult[key][key2]); } } checkRecursively(assert, result, mapMapTestExpectedResult); done(); }); }); QUnit.module('Exception'); QUnit.test('Xception', function(assert) { assert.expect(2); const done = assert.async(); client.testException('Xception', function(e) { assert.equal(e.errorCode, 1001); assert.equal(e.message, 'Xception'); done(); }); }); QUnit.test('no Exception', function(assert) { assert.expect(1); const done = assert.async(); client.testException('no Exception', function(e) { assert.ok(!e); done(); }); }); QUnit.module('Insanity'); QUnit.test('testInsanity', function(assert) { assert.expect(24); const done = assert.async(); const insanity = { '1': { '2': { 'userMap': { '5': 5, '8': 8 }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': 4 }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': 2 } ] }, '3': { 'userMap': { '5': 5, '8': 8 }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': 4 }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': 2 } ] } }, '2': { '6': { 'userMap': null, 'xtructs': null } } }; client.testInsanity(new ThriftTest.Insanity(), function(res) { assert.ok(res, JSON.stringify(res)); assert.ok(insanity, JSON.stringify(insanity)); checkRecursively(assert, res, insanity); done(); }); }); QUnit.module('Oneway'); QUnit.test('testOneway', function(assert) { assert.expect(1); const done = assert.async(); client.testOneway(1, function(result) { assert.equal(result, undefined); done(); }); }); thrift-0.19.0/lib/js/test/test-jq.js0000644000000000000000000001102714303740367017175 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ /* * JavaScript test suite for ThriftTest.thrift. These tests * will run only with jQuery (-gen js:jquery) Apache Thrift * interfaces. To create client code: * $ thrift -gen js:jquery ThriftTest.thrift * * See also: * ++ test.js for generic tests * ++ test-nojq.js for "-gen js" only tests */ ////////////////////////////////// //jQuery asynchronous tests jQuery.ajaxSetup({ timeout: 0 }); QUnit.module('jQ Async Manual'); QUnit.test('testI32', function(assert) { assert.expect(2); const done = assert.async(2); const transport = new Thrift.Transport(); const protocol = new Thrift.Protocol(transport); const client = new ThriftTest.ThriftTestClient(protocol); const jqxhr = jQuery.ajax({ url: '/service', data: client.send_testI32(Math.pow(-2, 31)), type: 'POST', cache: false, dataType: 'text', success: function(res) { transport.setRecvBuffer(res); assert.equal(client.recv_testI32(), Math.pow(-2, 31)); done(); }, error: function() { assert.ok(false); }, complete: function() { assert.ok(true); done(); } }); }); QUnit.test('testI64', function(assert) { assert.expect(2); const done = assert.async(2); const transport = new Thrift.Transport(); const protocol = new Thrift.Protocol(transport); const client = new ThriftTest.ThriftTestClient(protocol); jQuery.ajax({ url: '/service', //This is usually 2^61 but JS cannot represent anything over 2^52 accurately data: client.send_testI64(Math.pow(-2, 52)), type: 'POST', cache: false, dataType: 'text', success: function(res) { transport.setRecvBuffer(res); //This is usually 2^61 but JS cannot represent anything over 2^52 accurately assert.equal(client.recv_testI64(), Math.pow(-2, 52)); done(); }, error: function() { assert.ok(false); }, complete: function() { assert.ok(true); done(); } }); }); QUnit.module('jQ Async'); QUnit.test('I32', function(assert) { assert.expect(3); const done = assert.async(3); client.testI32(Math.pow(2, 30), function(result) { assert.equal(result, Math.pow(2, 30)); done(); }); const jqxhr = client.testI32(Math.pow(-2, 31), function(result) { assert.equal(result, Math.pow(-2, 31)); done(); }); jqxhr.success(function(result) { assert.equal(result, Math.pow(-2, 31)); done(); }); }); QUnit.test('I64', function(assert) { assert.expect(4); const done = assert.async(4); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately client.testI64(Math.pow(2, 52), function(result) { assert.equal(result, Math.pow(2, 52)); done(); }); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately client.testI64(Math.pow(-2, 52), function(result) { assert.equal(result, Math.pow(-2, 52)); done(); }) .error(function(xhr, status, e) { assert.ok(false, e.message); }) .success(function(result) { //This is usually 2^60 but JS cannot represent anything over 2^52 accurately assert.equal(result, Math.pow(-2, 52)); done(); }) .complete(function() { assert.ok(true); done(); }); }); QUnit.test('Xception', function(assert) { assert.expect(2); const done = assert.async(2); const dfd = client.testException('Xception', function(result) { assert.ok(false); done(); }) .error(function(xhr, status, e) { assert.equal(e.errorCode, 1001); assert.equal(e.message, 'Xception'); done(); $(document).ajaxError( function() { done(); } ); }); }); thrift-0.19.0/lib/js/test/phantomjs-qunit.js0000644000000000000000000000700214303740367020745 0ustar00rootroot00000000000000/*jshint evil:true*/ /* This file is only used by the test suite. * * Origin: https://github.com/ariya/phantomjs/blob/master/examples/run-qunit.js * License: https://github.com/ariya/phantomjs/blob/master/LICENSE.BSD * * Inclusion into Apache products is allowed according to http://www.apache.org/legal/3party.html */ var system = require('system'); /** * Wait until the test condition is true or a timeout occurs. Useful for waiting * on a server response or for a ui change (fadeIn, etc.) to occur. * * @param testFx javascript condition that evaluates to a boolean, * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or * as a callback function. * @param onReady what to do when testFx condition is fulfilled, * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or * as a callback function. * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used. */ function waitFor(testFx, onReady, timeOutMillis) { var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s start = new Date().getTime(), condition = false, interval = setInterval(function() { if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { // If not time-out yet and condition not yet fulfilled condition = (typeof(testFx) === 'string' ? eval(testFx) : testFx()); //< defensive code } else { if (!condition) { // If condition still not fulfilled (timeout but condition is 'false') console.log("'waitFor()' timeout"); phantom.exit(1); } else { // Condition fulfilled (timeout and/or condition is 'true') console.log("'waitFor()' finished in " + (new Date().getTime() - start) + 'ms.'); if (typeof(onReady) === 'string') { eval(onReady); } else { onReady(); //< Do what it's supposed to do once the condition is fulfilled } clearInterval(interval); //< Stop this interval } } }, 100); //< repeat check every 250ms } if (system.args.length === 1 || system.args.length > 3) { console.log('Usage: phantomjs phantomjs-qunit.js URL'); phantom.exit(1); } var page = new WebPage(); // Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") page.onConsoleMessage = function(msg) { console.log(msg); }; page.open(system.args[1], function(status) { if (status !== 'success') { console.log('Unable to access network'); phantom.exit(1); } else { waitFor(function() { return page.evaluate(function() { var el = document.getElementById('qunit-testresult'); if (el && el.innerText.match('completed')) { return true; } return false; }); }, function() { var failedNum = page.evaluate(function() { var el = document.getElementById('qunit-testresult'); console.log(el.innerText); try { return el.getElementsByClassName('failed')[0].innerHTML; } catch (e) { } return 10000; }); phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0); }); } }); thrift-0.19.0/lib/js/test/test-int64.html0000644000000000000000000000477114303740367020067 0ustar00rootroot00000000000000+ Int64 Constants in JS: Unit Test

Int64 Constants in JS: Unit Test

thrift-0.19.0/lib/js/test/test-deep-constructor.html0000644000000000000000000000455514303740367022423 0ustar00rootroot00000000000000 Thrift Javascript Bindings: Unit Test

Thrift Javascript Bindings: Deep Constructor Test (JsDeepConstructorTest.thrift)

Valid XHTML 1.0!

thrift-0.19.0/lib/js/test/Makefile.am0000644000000000000000000000174714303740367017314 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean check-local: all $(ANT) $(ANT_FLAGS) test thrift-0.19.0/lib/js/test/test-double-rendering.html0000644000000000000000000000502414303740367022340 0ustar00rootroot00000000000000+ Rendering Double Constants in JS: Unit Test

Rendering Double Constants in JS: Unit Test

thrift-0.19.0/lib/js/test/test.html0000644000000000000000000000536514303740367017125 0ustar00rootroot00000000000000 Thrift Javascript Bindings: Unit Test

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

thrift-0.19.0/lib/js/test/phantom-client.js0000644000000000000000000003270214303740367020533 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ (function() { 'use strict'; // Rudimentary test helper functions // TODO: Return error code based on kind of errors rather than throw var ok = function(t, msg) { if (!t) { console.log('*** FAILED ***'); throw new Error(msg); } }; var equal = function(a, b) { if (a !== b) { console.log('*** FAILED ***'); throw new Error(); } }; var test = function(name, f) { console.log('TEST : ' + name); f(); console.log('OK\n'); }; var parseArgs = function(args) { var skips = [ '--transport=http', '--protocol=json' ]; var opts = { port: '9090' // protocol: 'json', }; var keys = {}; for (var key in opts) { keys['--' + key + '='] = key; } for (var i in args) { var arg = args[i]; if (skips.indexOf(arg) != -1) { continue; } var hit = false; for (var k in keys) { if (arg.slice(0, k.length) === k) { opts[keys[k]] = arg.slice(k.length); hit = true; break; } } if (!hit) { throw new Error('Unknown argument: ' + arg); } } opts.port = parseInt(opts.port, 10); if (!opts.port || opts.port < 1 || opts.port > 65535) { throw new Error('Invalid port number'); } return opts; }; var execute = function() { console.log('### Apache Thrift Javascript standalone test client'); console.log('------------------------------------------------------------'); phantom.page.injectJs('src/thrift.js'); phantom.page.injectJs('test/gen-js/ThriftTest_types.js'); phantom.page.injectJs('test/gen-js/ThriftTest.js'); var system = require('system'); var opts = parseArgs(system.args.slice(1)); var port = opts.port; var transport = new Thrift.Transport('http://localhost:' + port + '/service'); var protocol = new Thrift.Protocol(transport); var client = new ThriftTest.ThriftTestClient(protocol); // TODO: Remove duplicate code with test.js. // all Languages in UTF-8 var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Bahasa Melayu, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; function checkRecursively(map1, map2) { if (typeof map1 !== 'function' && typeof map2 !== 'function') { if (!map1 || typeof map1 !== 'object') { equal(map1, map2); } else { for (var key in map1) { checkRecursively(map1[key], map2[key]); } } } } test('Void', function() { equal(client.testVoid(), undefined); }); test('Binary (String)', function() { var binary = ''; for (var v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } equal(client.testBinary(binary), binary); }); test('Binary (Uint8Array)', function() { var binary = ''; for (var v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } var arr = new Uint8Array(binary.length); for (var i = 0; i < binary.length; ++i) { arr[i] = binary[i].charCodeAt(); } equal(client.testBinary(arr), binary); }); test('String', function() { equal(client.testString(''), ''); equal(client.testString(stringTest), stringTest); var specialCharacters = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; equal(client.testString(specialCharacters), specialCharacters); }); test('Double', function() { equal(client.testDouble(0), 0); equal(client.testDouble(-1), -1); equal(client.testDouble(3.14), 3.14); equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60)); }); test('Bool', function() { equal(client.testBool(true), true); equal(client.testBool(false), false); }); test('I8', function() { equal(client.testByte(0), 0); equal(client.testByte(0x01), 0x01); }); test('I32', function() { equal(client.testI32(0), 0); equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30)); equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30)); }); test('I64', function() { equal(client.testI64(0), 0); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately equal(client.testI64(Math.pow(2, 52)), Math.pow(2, 52)); equal(client.testI64(-Math.pow(2, 52)), -Math.pow(2, 52)); }); test('Struct', function() { var structTestInput = new ThriftTest.Xtruct(); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately structTestInput.i64_thing = Math.pow(2, 52); var structTestOutput = client.testStruct(structTestInput); equal(structTestOutput.string_thing, structTestInput.string_thing); equal(structTestOutput.byte_thing, structTestInput.byte_thing); equal(structTestOutput.i32_thing, structTestInput.i32_thing); equal(structTestOutput.i64_thing, structTestInput.i64_thing); equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput)); }); test('Nest', function() { var xtrTestInput = new ThriftTest.Xtruct(); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately xtrTestInput.i64_thing = Math.pow(2, 52); var nestTestInput = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; nestTestInput.struct_thing = xtrTestInput; nestTestInput.i32_thing = Math.pow(2, 15); var nestTestOutput = client.testNest(nestTestInput); equal(nestTestOutput.byte_thing, nestTestInput.byte_thing); equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); equal(nestTestOutput.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing); equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput)); }); test('Map', function() { var mapTestInput = {7: 77, 8: 88, 9: 99}; var mapTestOutput = client.testMap(mapTestInput); for (var key in mapTestOutput) { equal(mapTestOutput[key], mapTestInput[key]); } }); test('StringMap', function() { var mapTestInput = { 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', 'longValue': stringTest, stringTest: 'long key' }; var mapTestOutput = client.testStringMap(mapTestInput); for (var key in mapTestOutput) { equal(mapTestOutput[key], mapTestInput[key]); } }); test('Set', function() { var setTestInput = [1, 2, 3]; ok(client.testSet(setTestInput), setTestInput); }); test('List', function() { var listTestInput = [1, 2, 3]; ok(client.testList(listTestInput), listTestInput); }); test('Enum', function() { equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE); }); test('TypeDef', function() { equal(client.testTypedef(69), 69); }); test('Skip', function() { var structTestInput = new ThriftTest.Xtruct(); var modifiedClient = new ThriftTest.ThriftTestClient(protocol); modifiedClient.recv_testStruct = function() { var input = modifiedClient.input; var xtruct3 = new ThriftTest.Xtruct3(); input.readMessageBegin(); input.readStructBegin(); // read Xtruct data with Xtruct3 input.readFieldBegin(); xtruct3.read(input); input.readFieldEnd(); // read Thrift.Type.STOP message input.readFieldBegin(); input.readFieldEnd(); input.readStructEnd(); input.readMessageEnd(); return xtruct3; }; structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); structTestInput.i64_thing = Math.pow(2, 52); var structTestOutput = modifiedClient.testStruct(structTestInput); equal(structTestOutput instanceof ThriftTest.Xtruct3, true); equal(structTestOutput.string_thing, structTestInput.string_thing); equal(structTestOutput.changed, null); equal(structTestOutput.i32_thing, structTestInput.i32_thing); equal(structTestOutput.i64_thing, structTestInput.i64_thing); }); test('MapMap', function() { var mapMapTestExpectedResult = { '4': {'1': 1, '2': 2, '3': 3, '4': 4}, '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} }; var mapMapTestOutput = client.testMapMap(1); for (var key in mapMapTestOutput) { for (var key2 in mapMapTestOutput[key]) { equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]); } } checkRecursively(mapMapTestOutput, mapMapTestExpectedResult); }); test('Xception', function() { try { client.testException('Xception'); ok(false); } catch (e) { equal(e.errorCode, 1001); equal(e.message, 'Xception'); } }); test('no Exception', function() { try { client.testException('no Exception'); } catch (e) { ok(false); } }); test('TException', function() { try { client.testException('TException'); ok(false); } catch (e) { ok(ok); } }); var crazy = { 'userMap': { '5': 5, '8': 8 }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': 4 }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': 2 }] }; test('Insanity', function() { var insanity = { '1': { '2': crazy, '3': crazy }, '2': { '6': { 'userMap': null, 'xtructs': null } } }; var res = client.testInsanity(new ThriftTest.Insanity(crazy)); ok(res, JSON.stringify(res)); ok(insanity, JSON.stringify(insanity)); checkRecursively(res, insanity); }); console.log('------------------------------------------------------------'); console.log('### All tests succeeded.'); return 0; }; try { var ret = execute(); phantom.exit(ret); } catch (err) { // Catch all and exit to avoid hang. console.error(err); phantom.exit(1); } })(); thrift-0.19.0/lib/js/test/jsTestDriver.conf0000644000000000000000000000063514303740367020552 0ustar00rootroot00000000000000server: http://localhost:9876 load: # Qunit adapter - build/js/lib/equiv.js - build/js/lib/QUnitAdapter.js # dependencies - build/js/lib/jquery.js - build/js/thrift.js - gen-js/DoubleConstantsTest_constants.js - gen-js/ThriftTest_types.js - gen-js/ThriftTest.js # the test suite - test.js # redirect to the Java based Thrift testserver proxy: - {matcher: "*", server: " http://localhost:8088"} thrift-0.19.0/lib/js/test/Makefile0000644000000000000000000004350114472652604016715 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # lib/js/test/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = lib/js/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/lib/js/test abs_srcdir = /thrift/src/lib/js/test abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../../ top_builddir = ../../.. top_srcdir = ../../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/js/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/js/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean check-local: all $(ANT) $(ANT_FLAGS) test # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/js/test/src/0000777000000000000000000000000014062750226016037 5ustar00rootroot00000000000000thrift-0.19.0/lib/js/test/src/test/0000777000000000000000000000000014303740367017021 5ustar00rootroot00000000000000thrift-0.19.0/lib/js/test/src/test/Httpd.java0000644000000000000000000003233514303740367020751 0ustar00rootroot00000000000000/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * . * */ package test; import java.io.File; import java.io.IOException; import java.io.InterruptedIOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.net.URLDecoder; import java.util.Locale; import org.apache.http.ConnectionClosedException; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpServerConnection; import org.apache.http.HttpStatus; import org.apache.http.MethodNotSupportedException; import org.apache.http.entity.ContentProducer; import org.apache.http.entity.EntityTemplate; import org.apache.http.entity.FileEntity; import org.apache.http.impl.DefaultHttpResponseFactory; import org.apache.http.impl.DefaultHttpServerConnection; import org.apache.http.impl.NoConnectionReuseStrategy; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpParams; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.BasicHttpProcessor; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpProcessor; import org.apache.http.protocol.HttpRequestHandler; import org.apache.http.protocol.HttpRequestHandlerRegistry; import org.apache.http.protocol.HttpService; import org.apache.http.util.EntityUtils; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TJSONProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TMemoryBuffer; import thrift.test.ThriftTest; import org.apache.thrift.server.ServerTestBase.TestHandler; import eu.medsea.mimeutil.detector.ExtensionMimeDetector; import eu.medsea.mimeutil.MimeUtil2; import eu.medsea.mimeutil.MimeType; import java.util.Collection; import java.util.Iterator; /** * Basic, yet fully functional and spec compliant, HTTP/1.1 file server. *

* Please note the purpose of this application is demonstrate the usage of * HttpCore APIs. It is NOT intended to demonstrate the most efficient way of * building an HTTP file server. * * */ public class Httpd { public static void main(String[] args) throws Exception { if (args.length < 1) { System.err.println("Please specify document root directory"); System.exit(1); } Thread t = new RequestListenerThread(8088, args[0]); t.setDaemon(false); t.start(); } static class HttpFileHandler implements HttpRequestHandler { private final String docRoot; public HttpFileHandler(final String docRoot) { super(); this.docRoot = docRoot; } public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException { String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH); if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) { throw new MethodNotSupportedException(method + " method not supported"); } String target = request.getRequestLine().getUri(); if (request instanceof HttpEntityEnclosingRequest && target.equals("/service")) { HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); byte[] entityContent = EntityUtils.toByteArray(entity); System.out.println("Incoming content: " + new String(entityContent)); final String output = this.thriftRequest(entityContent); System.out.println("Outgoing content: "+output); EntityTemplate body = new EntityTemplate(new ContentProducer() { public void writeTo(final OutputStream outstream) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); writer.write(output); writer.flush(); } }); body.setContentType("text/html; charset=UTF-8"); response.setEntity(body); } else { if(target.indexOf("?") != -1) { target = target.substring(1, target.indexOf("?")); } final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8")); if (!file.exists()) { response.setStatusCode(HttpStatus.SC_NOT_FOUND); EntityTemplate body = new EntityTemplate(new ContentProducer() { public void writeTo(final OutputStream outstream) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); writer.write("

"); writer.write("File "); writer.write(file.getPath()); writer.write(" not found"); writer.write("

"); writer.flush(); } }); body.setContentType("text/html; charset=UTF-8"); response.setEntity(body); System.out.println("File " + file.getPath() + " not found"); } else if (!file.canRead() || file.isDirectory()) { response.setStatusCode(HttpStatus.SC_FORBIDDEN); EntityTemplate body = new EntityTemplate(new ContentProducer() { public void writeTo(final OutputStream outstream) throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outstream, "UTF-8"); writer.write("

"); writer.write("Access denied"); writer.write("

"); writer.flush(); } }); body.setContentType("text/html; charset=UTF-8"); response.setEntity(body); System.out.println("Cannot read file " + file.getPath()); } else { String mimeType = "application/octet-stream"; MimeUtil2 mimeUtil = new MimeUtil2(); synchronized (this) { mimeUtil.registerMimeDetector(ExtensionMimeDetector.class.getName()); } Collection collection = mimeUtil.getMimeTypes(file); Iterator iterator = collection.iterator(); while(iterator.hasNext()) { MimeType mt = iterator.next(); mimeType = mt.getMediaType() + "/" + mt.getSubType(); break; } response.setStatusCode(HttpStatus.SC_OK); FileEntity body = new FileEntity(file, mimeType); response.addHeader("Content-Type", mimeType); response.setEntity(body); System.out.println("Serving file " + file.getPath()); } } } private String thriftRequest(byte[] input){ try{ //Input TMemoryBuffer inbuffer = new TMemoryBuffer(input.length); inbuffer.write(input); TProtocol inprotocol = new TJSONProtocol(inbuffer); //Output TMemoryBuffer outbuffer = new TMemoryBuffer(100); TProtocol outprotocol = new TJSONProtocol(outbuffer); TProcessor processor = new ThriftTest.Processor(new TestHandler()); processor.process(inprotocol, outprotocol); byte[] output = new byte[outbuffer.length()]; outbuffer.readAll(output, 0, output.length); return new String(output,"UTF-8"); }catch(Throwable t){ return "Error:"+t.getMessage(); } } } static class RequestListenerThread extends Thread { private final ServerSocket serversocket; private final HttpParams params; private final HttpService httpService; public RequestListenerThread(int port, final String docroot) throws IOException { this.serversocket = new ServerSocket(port); this.params = new BasicHttpParams(); this.params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 1000).setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false).setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1"); // Set up the HTTP protocol processor HttpProcessor httpproc = new BasicHttpProcessor(); // Set up request handlers HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry(); reqistry.register("*", new HttpFileHandler(docroot)); // Set up the HTTP service this.httpService = new HttpService(httpproc, new NoConnectionReuseStrategy(), new DefaultHttpResponseFactory()); this.httpService.setParams(this.params); this.httpService.setHandlerResolver(reqistry); } public void run() { System.out.println("Listening on port " + this.serversocket.getLocalPort()); System.out.println("Point your browser to http://localhost:8088/test/test.html"); while (!Thread.interrupted()) { try { // Set up HTTP connection Socket socket = this.serversocket.accept(); DefaultHttpServerConnection conn = new DefaultHttpServerConnection(); System.out.println("Incoming connection from " + socket.getInetAddress()); conn.bind(socket, this.params); // Start worker thread Thread t = new WorkerThread(this.httpService, conn); t.setDaemon(true); t.start(); } catch (InterruptedIOException ex) { break; } catch (IOException e) { System.err.println("I/O error initialising connection thread: " + e.getMessage()); break; } } } } static class WorkerThread extends Thread { private final HttpService httpservice; private final HttpServerConnection conn; public WorkerThread(final HttpService httpservice, final HttpServerConnection conn) { super(); this.httpservice = httpservice; this.conn = conn; } public void run() { System.out.println("New connection thread"); HttpContext context = new BasicHttpContext(null); try { while (!Thread.interrupted() && this.conn.isOpen()) { this.httpservice.handleRequest(this.conn, context); } } catch (ConnectionClosedException ex) { System.err.println("Client closed connection"); } catch (IOException ex) { System.err.println("I/O error: " + ex.getMessage()); } catch (HttpException ex) { System.err.println("Unrecoverable HTTP protocol violation: " + ex.getMessage()); } finally { try { this.conn.shutdown(); } catch (IOException ignore) { } } } } } thrift-0.19.0/lib/js/test/README.md0000644000000000000000000000532714303740367016535 0ustar00rootroot00000000000000Thrift Javascript Library ========================= This browser based Apache Thrift implementation supports RPC clients using the JSON protocol over Http[s] with XHR and WebSocket. License ------- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Test Servers ------------ drwxr-xr-x 2 randy randy 4096 Feb 8 15:44 sec -rw-r--r-- 1 randy randy 2183 Feb 9 04:01 server_http.js -rw-r--r-- 1 randy randy 2386 Feb 9 05:39 server_https.js server_http.js is a Node.js web server which support the standard Apache Thrift test suite (thrift/test/ThriftTest.thrift). The server supports Apache Thrift XHR and WebSocket clients. server_https.js is the same but uses SSL/TLS. The server key and cert are pulled from the thrift/test/keys folder. Both of these servers support WebSocket (the http: supports ws:, and the https: support wss:). To run the client test with the Java test server use: $ make check (requires the Apache Thrift Java branch and make check must have been run in thrift/lib/java previously). To run the client tests with the Node servers run the grunt build in the parent js directory (see README there). Test Clients ------------ -rw-r--r-- 1 randy randy 13558 Feb 9 07:18 test-async.js -rw-r--r-- 1 randy randy 5724 Feb 9 03:45 test_handler.js -rwxr-xr-x 1 randy randy 2719 Feb 9 06:04 test.html -rw-r--r-- 1 randy randy 4611 Feb 9 06:05 test-jq.js -rwxr-xr-x 1 randy randy 12153 Feb 9 06:04 test.js -rw-r--r-- 1 randy randy 2593 Feb 9 06:16 test-nojq.html -rw-r--r-- 1 randy randy 1450 Feb 9 06:14 test-nojq.js -rw-r--r-- 1 randy randy 2847 Feb 9 06:31 testws.html There are three html test driver files, all of which are QUnit based. test.html tests the Apache Thrift jQuery generated code (thrift -gen js:jquery). The test-nojq.html runs almost identical tests against normal JavaScript builds (thrift -gen js). Both of the previous tests use the XHR transport. The testws.html runs similar tests using the WebSocket transport. The test*.js files are loaded by the html drivers and contain the actual Apache Thrift tests. thrift-0.19.0/lib/js/test/test_handler.js0000644000000000000000000001332214303740367020262 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //This is the server side Node test handler for the standard // Apache Thrift test service. const es6Mode = process.argv.includes('--es6'); const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; const ttypes = require(`./${genFolder}/ThriftTest_types`); const TException = require('../../nodejs/lib/thrift').TException; const Int64 = require('node-int64'); exports.ThriftTestHandler = { testVoid: function(result) { console.log('testVoid()'); result(null); }, testString: function(thing, result) { console.log('testString(\'' + thing + '\')'); result(null, thing); }, testByte: function(thing, result) { console.log('testByte(' + thing + ')'); result(null, thing); }, testI32: function(thing, result) { console.log('testI32(' + thing + ')'); result(null, thing); }, testI64: function(thing, result) { console.log('testI64(' + thing + ')'); result(null, thing); }, testDouble: function(thing, result) { console.log('testDouble(' + thing + ')'); result(null, thing); }, testBinary: function(thing, result) { console.log('testBinary(\'' + thing + '\')'); result(null, thing); }, testStruct: function(thing, result) { console.log('testStruct('); console.log(thing); console.log(')'); result(null, thing); }, testNest: function(nest, result) { console.log('testNest('); console.log(nest); console.log(')'); result(null, nest); }, testMap: function(thing, result) { console.log('testMap('); console.log(thing); console.log(')'); result(null, thing); }, testStringMap: function(thing, result) { console.log('testStringMap('); console.log(thing); console.log(')'); result(null, thing); }, testSet: function(thing, result) { console.log('testSet('); console.log(thing); console.log(')'); result(null, thing); }, testList: function(thing, result) { console.log('testList('); console.log(thing); console.log(')'); result(null, thing); }, testEnum: function(thing, result) { console.log('testEnum(' + thing + ')'); result(null, thing); }, testTypedef: function(thing, result) { console.log('testTypedef(' + thing + ')'); result(null, thing); }, testMapMap: function(hello, result) { console.log('testMapMap(' + hello + ')'); const mapmap = []; const pos = []; const neg = []; for (let i = 1; i < 5; i++) { pos[i] = i; neg[-i] = -i; } mapmap[4] = pos; mapmap[-4] = neg; result(null, mapmap); }, testInsanity: function(argument, result) { console.log('testInsanity('); console.log(argument); console.log(')'); const hello = new ttypes.Xtruct(); hello.string_thing = 'Hello2'; hello.byte_thing = 2; hello.i32_thing = 2; hello.i64_thing = new Int64(2); const goodbye = new ttypes.Xtruct(); goodbye.string_thing = 'Goodbye4'; goodbye.byte_thing = 4; goodbye.i32_thing = 4; goodbye.i64_thing = new Int64(4); const crazy = new ttypes.Insanity(); crazy.userMap = []; crazy.userMap[ttypes.Numberz.EIGHT] = 8; crazy.userMap[ttypes.Numberz.FIVE] = 5; crazy.xtructs = [goodbye, hello]; const first_map = []; const second_map = []; first_map[ttypes.Numberz.TWO] = crazy; first_map[ttypes.Numberz.THREE] = crazy; const looney = new ttypes.Insanity(); second_map[ttypes.Numberz.SIX] = looney; const insane = []; insane[1] = first_map; insane[2] = second_map; console.log('insane result:'); console.log(insane); result(null, insane); }, testMulti: function(arg0, arg1, arg2, arg3, arg4, arg5, result) { console.log('testMulti()'); const hello = new ttypes.Xtruct(); hello.string_thing = 'Hello2'; hello.byte_thing = arg0; hello.i32_thing = arg1; hello.i64_thing = arg2; result(null, hello); }, testException: function(arg, result) { console.log('testException(' + arg + ')'); if (arg === 'Xception') { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = arg; result(x); } else if (arg === 'TException') { result(new TException(arg)); } else { result(null); } }, testMultiException: function(arg0, arg1, result) { console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); if (arg0 === ('Xception')) { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = 'This is an Xception'; result(x); } else if (arg0 === ('Xception2')) { const x2 = new ttypes.Xception2(); x2.errorCode = 2002; x2.struct_thing = new ttypes.Xtruct(); x2.struct_thing.string_thing = 'This is an Xception2'; result(x2); } const res = new ttypes.Xtruct(); res.string_thing = arg1; result(null, res); }, testOneway: function(sleepFor, result) { console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!'); } }; //ThriftTestSvcHandler thrift-0.19.0/lib/js/test/test-es6.js0000644000000000000000000003133514303740367017264 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ /* * Fully Async JavaScript test suite for ThriftTest.thrift. * These tests are designed to exercise the WebSocket transport * (which is exclusively async). * * To compile client code for this test use: * $ thrift -gen js:es6 ThriftTest.thrift */ // all Languages in UTF-8 const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Bahasa Melayu, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; function checkRecursively(assert, map1, map2) { if (typeof map1 !== 'function' && typeof map2 !== 'function') { if (!map1 || typeof map1 !== 'object') { assert.equal(map1, map2); } else { for (var key in map1) { checkRecursively(assert, map1[key], map2[key]); } } } } QUnit.module('Base Types'); QUnit.test('Void', function( assert ) { assert.expect(1); const done = assert.async(); client.testVoid().then(function(result) { assert.equal(result, undefined); done(); }); }); QUnit.test('String', function( assert ) { assert.expect(3); const done = assert.async(3); client.testString('').then(function(result) { assert.equal(result, ''); done(); }); client.testString(stringTest).then(function(result) { assert.equal(result, stringTest); done(); }); var specialCharacters = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; client.testString(specialCharacters).then(function(result) { assert.equal(result, specialCharacters); done(); }); }); QUnit.test('Double', function( assert ) { assert.expect(4); const done = assert.async(4); client.testDouble(0).then(function(result) { assert.equal(result, 0); done(); }); client.testDouble(-1).then(function(result) { assert.equal(result, -1); done(); }); client.testDouble(3.14).then(function(result) { assert.equal(result, 3.14); done(); }); client.testDouble(Math.pow(2, 60)).then(function(result) { assert.equal(result, Math.pow(2, 60)); done(); }); }); // TODO: add testBinary() QUnit.test('Byte', function( assert ) { assert.expect(2); const done = assert.async(2); client.testByte(0).then(function(result) { assert.equal(result, 0); done(); }); client.testByte(0x01).then(function(result) { assert.equal(result, 0x01); done(); }); }); QUnit.test('I32', function( assert ) { assert.expect(3); const done = assert.async(3); client.testI32(0).then(function(result) { assert.equal(result, 0); done(); }); client.testI32(Math.pow(2, 30)).then(function(result) { assert.equal(result, Math.pow(2, 30)); done(); }); client.testI32(-Math.pow(2, 30)).then(function(result) { assert.equal(result, -Math.pow(2, 30)); done(); }); }); QUnit.test('I64', function( assert ) { assert.expect(3); const done = assert.async(3); client.testI64(0).then(function(result) { assert.equal(result, 0); done(); }); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately client.testI64(Math.pow(2, 52)).then(function(result) { assert.equal(result, Math.pow(2, 52)); done(); }); client.testI64(-Math.pow(2, 52)).then(function(result) { assert.equal(result, -Math.pow(2, 52)); done(); }); }); QUnit.module('Structured Types'); QUnit.test('Struct', function( assert ) { assert.expect(5); const done = assert.async(); var structTestInput = new ThriftTest.Xtruct(); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately structTestInput.i64_thing = Math.pow(2, 52); client.testStruct(structTestInput).then(function(result) { assert.equal(result.string_thing, structTestInput.string_thing); assert.equal(result.byte_thing, structTestInput.byte_thing); assert.equal(result.i32_thing, structTestInput.i32_thing); assert.equal(result.i64_thing, structTestInput.i64_thing); assert.equal(JSON.stringify(result), JSON.stringify(structTestInput)); done(); }); }); QUnit.test('Nest', function( assert ) { assert.expect(7); const done = assert.async(); var xtrTestInput = new ThriftTest.Xtruct(); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); //This is usually 2^60 but JS cannot represent anything over 2^52 accurately xtrTestInput.i64_thing = Math.pow(2, 52); var nestTestInput = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; nestTestInput.struct_thing = xtrTestInput; nestTestInput.i32_thing = Math.pow(2, 15); client.testNest(nestTestInput).then(function(result) { assert.equal(result.byte_thing, nestTestInput.byte_thing); assert.equal(result.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); assert.equal(result.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); assert.equal(result.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); assert.equal(result.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing); assert.equal(result.i32_thing, nestTestInput.i32_thing); assert.equal(JSON.stringify(result), JSON.stringify(nestTestInput)); done(); }); }); QUnit.test('Map', function( assert ) { assert.expect(3); const done = assert.async(); var mapTestInput = {7: 77, 8: 88, 9: 99}; client.testMap(mapTestInput).then(function(result) { for (var key in result) { assert.equal(result[key], mapTestInput[key]); } done(); }); }); QUnit.test('StringMap', function( assert ) { assert.expect(6); const done = assert.async(); var mapTestInput = { 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', 'longValue': stringTest, stringTest: 'long key' }; client.testStringMap(mapTestInput).then(function(result) { for (var key in result) { assert.equal(result[key], mapTestInput[key]); } done(); }); }); QUnit.test('Set', function( assert ) { assert.expect(1); const done = assert.async(); var setTestInput = [1, 2, 3]; client.testSet(setTestInput).then(function(result) { assert.ok(result, setTestInput); done(); }); }); QUnit.test('List', function( assert ) { assert.expect(1); const done = assert.async(); var listTestInput = [1, 2, 3]; client.testList(listTestInput).then(function(result) { assert.ok(result, listTestInput); done(); }); }); QUnit.test('Enum', function( assert ) { assert.expect(1); const done = assert.async(); client.testEnum(ThriftTest.Numberz.ONE).then(function(result) { assert.equal(result, ThriftTest.Numberz.ONE); done(); }); }); QUnit.test('TypeDef', function( assert ) { assert.expect(1); const done = assert.async(); client.testTypedef(69).then(function(result) { assert.equal(result, 69); done(); }); }); QUnit.module('deeper!'); QUnit.test('MapMap', function( assert ) { assert.expect(16); const done = assert.async(); var mapMapTestExpectedResult = { '4': {'1': 1, '2': 2, '3': 3, '4': 4}, '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} }; client.testMapMap(1).then(function(result) { for (var key in result) { for (var key2 in result[key]) { assert.equal(result[key][key2], mapMapTestExpectedResult[key][key2]); } } checkRecursively(assert, result, mapMapTestExpectedResult); done(); }); }); QUnit.module('Exception'); QUnit.test('Xception', function( assert ) { assert.expect(2); const done = assert.async(); client.testException('Xception').then(function(res) { assert.ok(false); }).catch(function(e) { console.log(`Exception exception e`); console.log(e); console.log(JSON.stringify(e, null, 2)); assert.equal(e.errorCode, 1001); assert.equal(e.message, 'Xception'); done(); }); }); QUnit.test('no Exception', function( assert ) { assert.expect(1); const done = assert.async(); client.testException('no Exception').then(function(e) { assert.ok(!e); done(); }); }); QUnit.module('Insanity'); QUnit.test('testInsanity', function( assert ) { assert.expect(24); const done = assert.async(); var insanity = { '1': { '2': { 'userMap': { '5': 5, '8': 8 }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': 4 }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': 2 } ] }, '3': { 'userMap': { '5': 5, '8': 8 }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': 4 }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': 2 } ] } }, '2': { '6': { 'userMap': null, 'xtructs': null } } }; client.testInsanity(new ThriftTest.Insanity()).then(function(res) { assert.ok(res, JSON.stringify(res)); assert.ok(insanity, JSON.stringify(insanity)); checkRecursively(assert, res, insanity); done(); }); }); QUnit.module('Oneway'); QUnit.test('testOneway', function( assert ) { assert.expect(1); const done = assert.async(); client.testOneway(1).then(function(result) { assert.equal(result, undefined); done(); }); }); thrift-0.19.0/lib/js/test/test.js0000644000000000000000000003527214303740367016575 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ /* * JavaScript test suite for ThriftTest.thrift. These tests * will run against Normal (-gen js) and jQuery (-gen js:jquery) * Apache Thrift interfaces. * * Synchronous blocking calls should be identical in both * Normal and jQuery interfaces. All synchronous tests belong * here. * * Asynchronous success callbacks passed as the last parameter * of an RPC call should be identical in both Normal and jQuery * interfaces. Async success tests belong here. * * Asynchronous exception processing is different in Normal * and jQuery interfaces. Such tests belong in the test-nojq.js * or test-jq.js files respectively. jQuery specific XHR object * tests also belong in test-jq.js. Do not create any jQuery * dependencies in this file or in test-nojq.js * * To compile client code for this test use: * $ thrift -gen js ThriftTest.thrift * -- or -- * $ thrift -gen js:jquery ThriftTest.thrift * * See also: * ++ test-nojq.js for "-gen js" only tests * ++ test-jq.js for "-gen js:jquery" only tests */ const transport = new Thrift.Transport('/service'); const protocol = new Thrift.Protocol(transport); const client = new ThriftTest.ThriftTestClient(protocol); const int64_2_pow_60 = new Int64('1000000000000000'); const int64_minus_2_pow_60 = new Int64('f000000000000000'); // Work around for old API used by QUnitAdapter of jsTestDriver if (typeof QUnit.log == 'function') { // When using real QUnit (fron PhantomJS) log failures to console QUnit.log(function(details) { if (!details.result) { console.log('======== FAIL ========'); console.log('TestName: ' + details.name); if (details.message) console.log(details.message); console.log('Expected: ' + details.expected); console.log('Actual : ' + details.actual); console.log('======================'); } }); } // all Languages in UTF-8 const stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Bahasa Melayu, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; function checkRecursively(assert, map1, map2) { if (typeof map1 !== 'function' && typeof map2 !== 'function') { if (!map1 || typeof map1 !== 'object') { assert.equal(map1, map2); } else { for (let key in map1) { checkRecursively(assert, map1[key], map2[key]); } } } } QUnit.module('Base Types'); QUnit.test('Void', function(assert) { assert.equal(client.testVoid(), undefined); }); QUnit.test('Binary (String)', function(assert) { let binary = ''; for (let v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } assert.equal(client.testBinary(binary), binary); }); QUnit.test('Binary (Uint8Array)', function(assert) { let binary = ''; for (let v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } const arr = new Uint8Array(binary.length); for (let i = 0; i < binary.length; ++i) { arr[i] = binary[i].charCodeAt(); } assert.equal(client.testBinary(arr), binary); }); QUnit.test('String', function(assert) { assert.equal(client.testString(''), ''); assert.equal(client.testString(stringTest), stringTest); const specialCharacters = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; assert.equal(client.testString(specialCharacters), specialCharacters); }); QUnit.test('Double', function(assert) { assert.equal(client.testDouble(0), 0); assert.equal(client.testDouble(-1), -1); assert.equal(client.testDouble(3.14), 3.14); assert.equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60)); }); QUnit.test('Byte', function(assert) { assert.equal(client.testByte(0), 0); assert.equal(client.testByte(0x01), 0x01); }); QUnit.test('I32', function(assert) { assert.equal(client.testI32(0), 0); assert.equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30)); assert.equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30)); }); QUnit.test('I64', function(assert) { assert.equal(client.testI64(0), 0); let int64_2_pow_60_result = client.testI64(int64_2_pow_60); assert.ok(int64_2_pow_60.equals(int64_2_pow_60_result)); let int64_minus_2_pow_60_result = client.testI64(int64_minus_2_pow_60); assert.ok(int64_minus_2_pow_60.equals(int64_minus_2_pow_60_result)); }); QUnit.module('Structured Types'); QUnit.test('Struct', function(assert) { const structTestInput = new ThriftTest.Xtruct(); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); structTestInput.i64_thing = int64_2_pow_60; const structTestOutput = client.testStruct(structTestInput); assert.equal(structTestOutput.string_thing, structTestInput.string_thing); assert.equal(structTestOutput.byte_thing, structTestInput.byte_thing); assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing); assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing)); assert.equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput)); }); QUnit.test('Nest', function(assert) { const xtrTestInput = new ThriftTest.Xtruct(); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); xtrTestInput.i64_thing = int64_2_pow_60; const nestTestInput = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; nestTestInput.struct_thing = xtrTestInput; nestTestInput.i32_thing = Math.pow(2, 15); const nestTestOutput = client.testNest(nestTestInput); assert.equal(nestTestOutput.byte_thing, nestTestInput.byte_thing); assert.equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); assert.equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); assert.equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); assert.ok(nestTestOutput.struct_thing.i64_thing.equals(nestTestInput.struct_thing.i64_thing)); assert.equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); assert.equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput)); }); QUnit.test('Map', function(assert) { const mapTestInput = {7: 77, 8: 88, 9: 99}; const mapTestOutput = client.testMap(mapTestInput); for (let key in mapTestOutput) { assert.equal(mapTestOutput[key], mapTestInput[key]); } }); QUnit.test('StringMap', function(assert) { const mapTestInput = { 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', 'longValue': stringTest, stringTest: 'long key' }; const mapTestOutput = client.testStringMap(mapTestInput); for (let key in mapTestOutput) { assert.equal(mapTestOutput[key], mapTestInput[key]); } }); QUnit.test('Set', function(assert) { const setTestInput = [1, 2, 3]; assert.ok(client.testSet(setTestInput), setTestInput); }); QUnit.test('List', function(assert) { const listTestInput = [1, 2, 3]; assert.ok(client.testList(listTestInput), listTestInput); }); QUnit.test('Enum', function(assert) { assert.equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE); }); QUnit.test('TypeDef', function(assert) { assert.equal(client.testTypedef(69), 69); }); QUnit.test('Skip', function(assert) { const structTestInput = new ThriftTest.Xtruct(); const modifiedClient = new ThriftTest.ThriftTestClient(protocol); modifiedClient.recv_testStruct = function() { const input = modifiedClient.input; const xtruct3 = new ThriftTest.Xtruct3(); input.readMessageBegin(); input.readStructBegin(); // read Xtruct data with Xtruct3 input.readFieldBegin(); xtruct3.read(input); input.readFieldEnd(); // read Thrift.Type.STOP message input.readFieldBegin(); input.readFieldEnd(); input.readStructEnd(); input.readMessageEnd(); return xtruct3; }; structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); structTestInput.i64_thing = int64_2_pow_60; const structTestOutput = modifiedClient.testStruct(structTestInput); assert.equal(structTestOutput instanceof ThriftTest.Xtruct3, true); assert.equal(structTestOutput.string_thing, structTestInput.string_thing); assert.equal(structTestOutput.changed, null); assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing); assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing)); }); QUnit.module('deeper!'); QUnit.test('MapMap', function(assert) { const mapMapTestExpectedResult = { '4': {'1': 1, '2': 2, '3': 3, '4': 4}, '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} }; const mapMapTestOutput = client.testMapMap(1); for (let key in mapMapTestOutput) { for (let key2 in mapMapTestOutput[key]) { assert.equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]); } } checkRecursively(assert, mapMapTestOutput, mapMapTestExpectedResult); }); QUnit.module('Exception'); QUnit.test('Xception', function(assert) { assert.expect(2); const done = assert.async(); try { client.testException('Xception'); assert.ok(false); }catch (e) { assert.equal(e.errorCode, 1001); assert.equal(e.message, 'Xception'); done(); } }); QUnit.test('no Exception', function(assert) { assert.expect(1); try { client.testException('no Exception'); assert.ok(true); }catch (e) { assert.ok(false); } }); QUnit.test('TException', function(assert) { //ThriftTest does not list TException as a legal exception so it will // generate an exception on the server that does not propagate back to // the client. This test has been modified to equate to "no exception" assert.expect(1); try { client.testException('TException'); } catch (e) { //assert.ok(false); } assert.ok(true); }); QUnit.module('Insanity'); const crazy = { 'userMap': { '5': 5, '8': 8 }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': new Int64(4) }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': new Int64(2) }] }; QUnit.test('testInsanity', function(assert) { const insanity = { '1': { '2': crazy, '3': crazy }, '2': { '6': { 'userMap': null, 'xtructs': null } } }; const res = client.testInsanity(new ThriftTest.Insanity(crazy)); assert.ok(res, JSON.stringify(res)); assert.ok(insanity, JSON.stringify(insanity)); checkRecursively(assert, res, insanity); }); ////////////////////////////////// //Run same tests asynchronously QUnit.module('Async'); QUnit.test('Double', function(assert) { assert.expect(1); const done = assert.async(); client.testDouble(3.14159265, function(result) { assert.equal(result, 3.14159265); done(); }); }); QUnit.test('Byte', function(assert) { assert.expect(1); const done = assert.async(); client.testByte(0x01, function(result) { assert.equal(result, 0x01); done(); }); }); QUnit.test('I32', function(assert) { assert.expect(2); const done = assert.async(2); client.testI32(Math.pow(2, 30), function(result) { assert.equal(result, Math.pow(2, 30)); done(); }); client.testI32(Math.pow(-2, 31), function(result) { assert.equal(result, Math.pow(-2, 31)); done(); }); }); QUnit.test('I64', function(assert) { assert.expect(2); const done = assert.async(2); client.testI64(int64_2_pow_60, function(result) { assert.ok(int64_2_pow_60.equals(result)); done(); }); client.testI64(int64_minus_2_pow_60, function(result) { assert.ok(int64_minus_2_pow_60.equals(result)); done(); }); }); thrift-0.19.0/lib/js/test/server_http.js0000644000000000000000000000412414303740367020153 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This HTTP server is designed to serve the test.html browser // based JavaScript test page (which must be in the current directory). // This server also supplies the Thrift based test service, which depends // on the standard ThriftTest.thrift IDL service (which must be compiled // for Node and browser based JavaScript in ./gen-nodejs and ./gen-js // respectively). // // Using the command flag --es6, this server can be run using nodejs code built // for the es6 environment or for pre-es6 environment. // const thrift = require('../../nodejs/lib/thrift'); const es6Mode = process.argv.includes('--es6'); const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; const ThriftTestSvc = require(`./${genFolder}/ThriftTest.js`); const ThriftTestHandler = require('./test_handler').ThriftTestHandler; const ThriftTestSvcOpt = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, processor: ThriftTestSvc, handler: ThriftTestHandler }; const ThriftWebServerOptions = { files: __dirname, services: { '/service': ThriftTestSvcOpt } }; const server = thrift.createWebServer(ThriftWebServerOptions); const port = es6Mode ? 8088 : 8089; server.listen(port); console.log(`Serving files from: ${__dirname}`); console.log(`Http/Thrift Server (ES6 mode ${es6Mode}) running on port: ${port}`); thrift-0.19.0/lib/js/test/build.xml0000644000000000000000000002313714370300523017064 0ustar00rootroot00000000000000 Java Script Test based on Thrift Java Library You need libthrift*.jar and libthrift*test.jar located at ${thrift.java.dir}/build/libs Did you compile Thrift Java library and its test suite by "make check"? Thrift compiler is missing ! check if Xvfb is available: check if phantomjs is available: Running Unit Tests with headless browser! check if gjslint is available: thrift-0.19.0/lib/js/test/server_https.js0000644000000000000000000000447114303740367020343 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //This HTTP server is designed to server the test.html browser // based JavaScript test page (which must be in the current directory). // This server also supplies the Thrift based test service, which depends // on the standard ThriftTest.thrift IDL service (which must be compiled // for Node and browser based JavaScript in ./gen-nodejs and ./gen-js // respectively). The current directory must also include the browser // support libraries for test.html (jquery.js, qunit.js and qunit.css // in ./build/js/lib). const fs = require('fs'); const thrift = require('../../nodejs/lib/thrift'); const es6Mode = process.argv.includes('--es6'); const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; const ThriftTestSvc = require(`./${genFolder}/ThriftTest.js`); const ThriftTestHandler = require('./test_handler').ThriftTestHandler; //Setup the I/O stack options for the ThriftTest service const ThriftTestSvcOpt = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, processor: ThriftTestSvc, handler: ThriftTestHandler }; const ThriftWebServerOptions = { files: __dirname, tls: { key: fs.readFileSync('../../../test/keys/server.key'), cert: fs.readFileSync('../../../test/keys/server.crt') }, services: { '/service': ThriftTestSvcOpt } }; const server = thrift.createWebServer(ThriftWebServerOptions); const port = es6Mode ? 8090 : 8091; server.listen(port); console.log(`Serving files from: ${__dirname}`); console.log(`Http/Thrift Server (ES6 mode ${es6Mode}) running on port: ${port}`); thrift-0.19.0/lib/js/test/build.properties0000644000000000000000000000036414303740367020467 0ustar00rootroot00000000000000# Maven Ant tasks Jar details mvn.ant.task.version=2.1.3 mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar thrift-0.19.0/lib/js/test/test-int64.js0000644000000000000000000000722614303740367017535 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ // Work around for old API used by QUnitAdapter of jsTestDriver if (typeof QUnit.log == 'function') { // When using real QUnit (fron PhantomJS) log failures to console QUnit.log(function(details) { if (!details.result) { console.log('======== FAIL ========'); console.log('TestName: ' + details.name); if (details.message) console.log(details.message); console.log('Expected: ' + details.expected); console.log('Actual : ' + details.actual); console.log('======================'); } }); } QUnit.module('Int64'); QUnit.test('Int64', function(assert) { console.log('Int64 test -- starts'); const EXPECTED_SMALL_INT64_AS_NUMBER = 42; const EXPECTED_SMALL_INT64 = new Int64(42); const EXPECTED_MAX_JS_SAFE_INT64 = new Int64(Number.MAX_SAFE_INTEGER); const EXPECTED_MIN_JS_SAFE_INT64 = new Int64(Number.MIN_SAFE_INTEGER); const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64 = new Int64("0020000000000000"); // hex-encoded const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement const EXPECTED_MAX_SIGNED_INT64 = new Int64("7fffffffffffffff"); // hex-encoded const EXPECTED_MIN_SIGNED_INT64 = new Int64("8000000000000000"); // hex-encoded 2's complement const EXPECTED_INT64_LIST = [ EXPECTED_SMALL_INT64, EXPECTED_MAX_JS_SAFE_INT64, EXPECTED_MIN_JS_SAFE_INT64, EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, EXPECTED_MAX_SIGNED_INT64, EXPECTED_MIN_SIGNED_INT64 ]; assert.ok(EXPECTED_SMALL_INT64.equals(Int64Test.SMALL_INT64)); assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(Int64Test.MAX_JS_SAFE_INT64)); assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(Int64Test.MIN_JS_SAFE_INT64)); assert.ok( EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( Int64Test.MAX_JS_SAFE_PLUS_ONE_INT64 ) ); assert.ok( EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( Int64Test.MIN_JS_SAFE_MINUS_ONE_INT64 ) ); assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(Int64Test.MAX_SIGNED_INT64)); assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(Int64Test.MIN_SIGNED_INT64)); assert.equal( EXPECTED_SMALL_INT64_AS_NUMBER, Int64Test.SMALL_INT64.toNumber() ); assert.equal( Number.MAX_SAFE_INTEGER, Int64Test.MAX_JS_SAFE_INT64.toNumber() ); assert.equal( Number.MIN_SAFE_INTEGER, Int64Test.MIN_JS_SAFE_INT64.toNumber() ); for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(Int64Test.INT64_LIST[i])); } for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i){ let int64Object = EXPECTED_INT64_LIST[i]; assert.ok(Int64Test.INT64_2_INT64_MAP[JSONInt64.toDecimalString(int64Object)].equals(int64Object)); } console.log('Int64 test -- ends'); }); thrift-0.19.0/lib/js/test/test-nojq.html0000644000000000000000000000517714303740367020073 0ustar00rootroot00000000000000 Thrift Javascript Bindings: Unit Test

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

thrift-0.19.0/lib/js/test/test-es6.html0000644000000000000000000000606314303740367017614 0ustar00rootroot00000000000000 Thrift Javascript Bindings: Unit Test

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

thrift-0.19.0/lib/js/test/deep-constructor.test.js0000644000000000000000000001242314303740367022065 0ustar00rootroot00000000000000function serialize(data) { const transport = new Thrift.Transport('/service'); const protocol = new Thrift.Protocol(transport); protocol.writeMessageBegin('', 0, 0); data.write(protocol); protocol.writeMessageEnd(); return transport.send_buf; } function deserialize(serialized, type) { const transport = new Thrift.Transport('/service'); transport.setRecvBuffer(serialized); const protocol = new Thrift.Protocol(transport); protocol.readMessageBegin(); const data = new type(); data.read(protocol); protocol.readMessageEnd(); return data; } function createThriftObj() { return new Complex({ struct_field: new Simple({value: 'a'}), struct_list_field: [ new Simple({value: 'b'}), new Simple({value: 'c'}) ], struct_set_field: [ new Simple({value: 'd'}), new Simple({value: 'e'}) ], struct_map_field: { A: new Simple({value: 'f'}), B: new Simple({value: 'g'}) }, struct_nested_containers_field: [ [ { C: [ new Simple({value: 'h'}), new Simple({value: 'i'}) ] } ] ], struct_nested_containers_field2: { D: [ { DA: new Simple({value: 'j'}) }, { DB: new Simple({value: 'k'}) } ] }, list_of_list_field: [ ['one', 'two'], ['three', 'four'], ['five', 'six'] ] } ); } function createJsObj() { return { struct_field: {value: 'a'}, struct_list_field: [ {value: 'b'}, {value: 'c'} ], struct_set_field: [ {value: 'd'}, {value: 'e'} ], struct_map_field: { A: {value: 'f'}, B: {value: 'g'} }, struct_nested_containers_field: [ [ { C: [ {value: 'h'}, {value: 'i'} ] } ] ], struct_nested_containers_field2: { D: [ { DA: {value: 'j'} }, { DB: {value: 'k'} } ] }, list_of_list_field: [ ['one', 'two'], ['three', 'four'], ['five', 'six'] ] }; } function assertValues(obj, assert) { assert.equal(obj.struct_field.value, 'a'); assert.equal(obj.struct_list_field[0].value, 'b'); assert.equal(obj.struct_list_field[1].value, 'c'); assert.equal(obj.struct_set_field[0].value, 'd'); assert.equal(obj.struct_set_field[1].value, 'e'); assert.equal(obj.struct_map_field.A.value, 'f'); assert.equal(obj.struct_map_field.B.value, 'g'); assert.equal(obj.struct_nested_containers_field[0][0].C[0].value, 'h'); assert.equal(obj.struct_nested_containers_field[0][0].C[1].value, 'i'); assert.equal(obj.struct_nested_containers_field2.D[0].DA.value, 'j'); assert.equal(obj.struct_nested_containers_field2.D[1].DB.value, 'k'); assert.equal(obj.list_of_list_field[0][0], 'one'); assert.equal(obj.list_of_list_field[0][1], 'two'); assert.equal(obj.list_of_list_field[1][0], 'three'); assert.equal(obj.list_of_list_field[1][1], 'four'); assert.equal(obj.list_of_list_field[2][0], 'five'); assert.equal(obj.list_of_list_field[2][1], 'six'); } const cases = { 'Serialize/deserialize simple struct should return equal object': function(assert) { const tObj = new Simple({value: 'a'}); const received = deserialize(serialize(tObj), Simple); assert.ok(tObj !== received); assert.deepEqual(received, tObj); }, 'Serialize/deserialize should return equal object': function(assert) { const tObj = createThriftObj(); const received = deserialize(serialize(tObj), Complex); assert.ok(tObj !== received); assert.deepEqual(received, tObj); }, 'Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects': function(assert) { const tObj1 = createThriftObj(); const tObj2 = new Complex(createJsObj()); assertValues(tObj2, assert); assert.equal(serialize(tObj2), serialize(tObj1)); }, 'Modifications to args object should not affect constructed Thrift object': function(assert) { const args = createJsObj(); assertValues(args, assert); const tObj = new Complex(args); assertValues(tObj, assert); args.struct_field.value = 'ZZZ'; args.struct_list_field[0].value = 'ZZZ'; args.struct_list_field[1].value = 'ZZZ'; args.struct_set_field[0].value = 'ZZZ'; args.struct_set_field[1].value = 'ZZZ'; args.struct_map_field.A.value = 'ZZZ'; args.struct_map_field.B.value = 'ZZZ'; args.struct_nested_containers_field[0][0].C[0] = 'ZZZ'; args.struct_nested_containers_field[0][0].C[1] = 'ZZZ'; args.struct_nested_containers_field2.D[0].DA = 'ZZZ'; args.struct_nested_containers_field2.D[0].DB = 'ZZZ'; assertValues(tObj, assert); }, 'nulls are ok': function(assert) { const tObj = new Complex({ struct_field: null, struct_list_field: null, struct_set_field: null, struct_map_field: null, struct_nested_containers_field: null, struct_nested_containers_field2: null }); const received = deserialize(serialize(tObj), Complex); assert.ok(tObj !== received); assert.deepEqual(tObj, received); } }; Object.keys(cases).forEach(function(caseName) { QUnit.test(caseName, cases[caseName]); }); thrift-0.19.0/lib/js/test/test-double-rendering.js0000644000000000000000000001337114303740367022014 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ /* * JavaScript test suite for double constants inside * DoubleConstantsTest.thrift. These tests will run against Normal (-gen js) * Apache Thrift interfaces. * * To compile client code for this test use: * $ thrift -gen js DoubleConstantsTest.thrift */ // double assertion threshold const EPSILON = 0.0000001; // Work around for old API used by QUnitAdapter of jsTestDriver if (typeof QUnit.log == 'function') { // When using real QUnit (fron PhantomJS) log failures to console QUnit.log(function(details) { if (!details.result) { console.log('======== FAIL ========'); console.log('TestName: ' + details.name); if (details.message) console.log(details.message); console.log('Expected: ' + details.expected); console.log('Actual : ' + details.actual); console.log('======================'); } }); } QUnit.module('Double rendering'); QUnit.test('Double (rendering)', function(assert) { console.log('Double rendering test -- starts'); const EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1; const EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100; const EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807; const EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807; const EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359; const EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1; const EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1; const EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308; const EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43; const EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308; const EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43; assert.ok( Math.abs(EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT - DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT - DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT - DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT - DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS - DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE - DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE - DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE - DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE - DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE - DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST) <= EPSILON); assert.ok( Math.abs( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE - DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) <= EPSILON); assert.equal(typeof DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, 'number'); assert.equal(typeof DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, 'number'); const EXPECTED_DOUBLE_LIST = [1,-100,100,9223372036854775807,-9223372036854775807,3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308, 9223372036854775816.43,-9223372036854775816.43]; assert.equal(DOUBLE_LIST_TEST.length, EXPECTED_DOUBLE_LIST.length); for (let i = 0; i < EXPECTED_DOUBLE_LIST.length; ++i) { assert.ok(Math.abs(EXPECTED_DOUBLE_LIST[i] - DOUBLE_LIST_TEST[i]) <= EPSILON); } console.log('Double rendering test -- ends'); }); thrift-0.19.0/lib/js/test/Makefile.in0000644000000000000000000004257214472652516017333 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/js/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/js/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/js/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile export CLASSPATH # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean check-local: all $(ANT) $(ANT_FLAGS) test # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/js/test/test-nojq.js0000644000000000000000000000272114303740367017533 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ /* * JavaScript test suite for ThriftTest.thrift. These tests * will run only with normal "-gen js" Apache Thrift interfaces. * To create client code: * $ thrift -gen js ThriftTest.thrift * * See also: * ++ test.js for generic tests * ++ test-jq.js for "-gen js:jquery" only tests */ ////////////////////////////////// //Async exception tests QUnit.module('NojQ Async'); QUnit.test('Xception', function(assert) { assert.expect(2); const done = assert.async(); client.testException('Xception', function(result) { assert.equal(result.errorCode, 1001); assert.equal(result.message, 'Xception'); done(); }); }); thrift-0.19.0/lib/js/test/testws.html0000644000000000000000000000606014303740367017470 0ustar00rootroot00000000000000 Thrift Javascript Bindings: Unit Test

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

thrift-0.19.0/lib/js/Makefile.in0000644000000000000000000006057314472652516016355 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Make sure this doesn't fail if ant is not configured. # We call npm install twice to work around older npm issues # (note these issues may no longer be present, but it is ok) # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/js ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = test am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @HAVE_NPM_TRUE@SUBDIRS = test EXTRA_DIST = \ coding_standards.md \ Gruntfile.js \ package.json \ package-lock.json \ CMakeLists.txt \ README.md \ src \ test all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/js/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/js/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook @HAVE_NPM_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am check-local clean clean-generic clean-libtool \ clean-local cscopelist-am ctags ctags-am dist-hook distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile @HAVE_NPM_TRUE@prereq: @HAVE_NPM_TRUE@ $(NPM) install || $(NPM) install @HAVE_NPM_TRUE@ $(NPM) list @HAVE_NPM_TRUE@check-local: prereq all @HAVE_NPM_TRUE@ ./node_modules/.bin/grunt @HAVE_NPM_TRUE@doc: prereq @HAVE_NPM_TRUE@ ./node_modules/.bin/grunt jsdoc clean-local: $(RM) -r dist $(RM) -r doc $(RM) -r node_modules $(RM) -r test/build/ $(RM) -r test/gen-*/ dist-hook: $(RM) -r $(distdir)/dist/ $(RM) -r $(distdir)/doc/ $(RM) -r $(distdir)/node_modules/ $(RM) -r $(distdir)/test/build/ $(RM) -r $(distdir)/test/gen-*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/js/Gruntfile.js0000644000000000000000000002232414370300523016556 0ustar00rootroot00000000000000//To build dist/thrift.js, dist/thrift.min.js and doc/* //run grunt at the command line in this directory. //Prerequisites: // Node Setup - nodejs.org // Grunt Setup - npm install //reads the ./package.json and installs project dependencies // Run grunt - npx grunt // uses project-local installed version of grunt (from package.json) module.exports = function(grunt) { 'use strict'; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { separator: ';' }, dist: { src: ['src/**/*.js'], dest: 'dist/<%= pkg.name %>.js' } }, jsdoc : { dist : { src: ['src/*.js', './README.md'], options: { destination: 'doc' } } }, uglify: { options: { banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n' }, dist: { files: { 'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>'] } } }, shell: { InstallThriftJS: { command: 'cp src/thrift.js test/build/js/thrift.js' }, InstallThriftNodeJSDep: { command: 'cd ../.. && npm install' }, InstallTestLibs: { command: 'cd test && ant download_jslibs' }, ThriftGen: { command: [ '"../../compiler/cpp/thrift" -gen js --out test/gen-js ../../test/v0.16/ThriftTest.thrift', '"../../compiler/cpp/thrift" -gen js --out test/gen-js ../../test/JsDeepConstructorTest.thrift', '"../../compiler/cpp/thrift" -gen js:jquery --out test/gen-js-jquery ../../test/v0.16/ThriftTest.thrift', '"../../compiler/cpp/thrift" -gen js:node --out test/gen-nodejs ../../test/v0.16/ThriftTest.thrift', '"../../compiler/cpp/thrift" -gen js:es6 --out test/gen-js-es6 ../../test/v0.16/ThriftTest.thrift', '"../../compiler/cpp/thrift" -gen js:node,es6 --out ./test/gen-nodejs-es6 ../../test/v0.16/ThriftTest.thrift', ].join(' && ') }, ThriftGenJQ: { command: '../../compiler/cpp/thrift -gen js:jquery -gen js:node -o test ../../test/v0.16/ThriftTest.thrift' }, ThriftGenDeepConstructor: { command: '../../compiler/cpp/thrift -gen js -o test ../../test/JsDeepConstructorTest.thrift' }, ThriftBrowserifyNodeInt64: { command: [ './node_modules/browserify/bin/cmd.js ./node_modules/node-int64/Int64.js -s Int64 -o test/build/js/lib/Int64.js', './node_modules/browserify/bin/cmd.js ../nodejs/lib/thrift/int64_util.js -s Int64Util -o test/build/js/lib/Int64Util.js', './node_modules/browserify/bin/cmd.js ./node_modules/json-int64/index.js -s JSONInt64 -o test/build/js/lib/JSONInt64.js' ].join(' && ') }, ThriftGenInt64: { command: '../../compiler/cpp/thrift -gen js -o test ../../test/Int64Test.thrift' }, ThriftGenDoubleConstants: { command: '../../compiler/cpp/thrift -gen js -o test ../../test/DoubleConstantsTest.thrift' }, ThriftTestServer: { options: { async: true, execOptions: { cwd: "./test", env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} } }, command: "node server_http.js", }, ThriftTestServerES6: { options: { async: true, execOptions: { cwd: "./test", env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} } }, command: "node server_http.js --es6", }, ThriftTestServer_TLS: { options: { async: true, execOptions: { cwd: "./test", env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} } }, command: "node server_https.js", }, ThriftTestServerES6_TLS: { options: { async: true, execOptions: { cwd: "./test", env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} } }, command: "node server_https.js --es6", }, }, qunit: { ThriftJS: { options: { urls: [ 'http://localhost:8089/test-nojq.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], }, } }, ThriftJSJQ: { options: { urls: [ 'http://localhost:8089/test.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], }, } }, ThriftJS_DoubleRendering: { options: { urls: [ 'http://localhost:8089/test-double-rendering.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], ignoreHTTPSErrors: true, }, } }, ThriftJS_Int64: { options: { urls: [ 'http://localhost:8089/test-int64.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], ignoreHTTPSErrors: true, }, } }, ThriftWS: { options: { urls: [ 'http://localhost:8089/testws.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], }, } }, ThriftJS_TLS: { options: { urls: [ 'https://localhost:8091/test-nojq.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], ignoreHTTPSErrors: true, }, } }, ThriftJSJQ_TLS: { options: { urls: [ 'https://localhost:8091/test.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], ignoreHTTPSErrors: true, }, } }, ThriftWS_TLS: { options: { urls: [ 'https://localhost:8091/testws.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], ignoreHTTPSErrors: true, }, } }, ThriftDeepConstructor: { options: { urls: [ 'http://localhost:8089/test-deep-constructor.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], }, } }, ThriftWSES6: { options: { urls: [ 'http://localhost:8088/test-es6.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], }, } } }, jshint: { // The main Thrift library file. not es6 yet :( lib: { src: ['src/**/*.js'], }, // The test files use es6 test: { src: ['Gruntfile.js', 'test/*.js'], options: { esversion: 6, } }, gen_js_code: { src: ['test/gen-js/*.js', 'test/gen-js-jquery/*.js'], }, gen_es6_code: { src: ['test/gen-js-es6/*.js'], options: { esversion: 6, } }, gen_node_code: { src: ['test/gen-nodejs/*.js'], options: { node: true, } }, gen_node_es6_code: { src: ['test/gen-nodejs-es6/*.js'], options: { node: true, esversion: 6, } } }, }); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-jsdoc'); grunt.loadNpmTasks('grunt-shell-spawn'); grunt.registerTask('wait', 'Wait just one second for the server to start', function () { var done = this.async(); setTimeout(function() { done(true); }, 1000); }); grunt.registerTask('CreateDirectories', 'Creating required local directories', function () { grunt.file.mkdir('test/build/js/lib'); grunt.file.mkdir('test/gen-js'); grunt.file.mkdir('test/gen-js-jquery'); grunt.file.mkdir('test/gen-nodejs'); grunt.file.mkdir('test/gen-js-es6'); grunt.file.mkdir('test/gen-nodejs-es6'); }); grunt.registerTask('installAndGenerate', [ 'CreateDirectories', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', 'shell:ThriftGenDeepConstructor', 'shell:ThriftGenDoubleConstants', 'shell:InstallTestLibs', 'shell:ThriftBrowserifyNodeInt64', 'shell:ThriftGenInt64' ]); grunt.registerTask('test', [ 'installAndGenerate', 'jshint', 'shell:ThriftTestServer', 'shell:ThriftTestServer_TLS', 'shell:ThriftTestServerES6', 'shell:ThriftTestServerES6_TLS', 'wait', 'qunit:ThriftDeepConstructor', 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', 'qunit:ThriftJS_DoubleRendering', 'qunit:ThriftWS', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', 'qunit:ThriftWSES6', 'qunit:ThriftJS_Int64', 'shell:ThriftTestServer:kill', 'shell:ThriftTestServer_TLS:kill', 'shell:ThriftTestServerES6:kill', 'shell:ThriftTestServerES6_TLS:kill', ]); grunt.registerTask('default', ['test', 'concat', 'uglify', 'jsdoc']); }; thrift-0.19.0/lib/javame/0000777000000000000000000000000014303740367015123 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/0000777000000000000000000000000014062750226015707 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/0000777000000000000000000000000014062750226016476 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/apache/0000777000000000000000000000000014062750226017717 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/apache/thrift/0000777000000000000000000000000014303740367021222 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/apache/thrift/TBaseHelper.java0000644000000000000000000001336614303740367024230 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.util.Vector; import java.util.Hashtable; import java.util.Enumeration; public class TBaseHelper { public static int compareTo(boolean a, boolean b) { return (a == b) ? 0 : (a ? 1 : -1); } public static int compareTo(Boolean a, Boolean b) { return (a.booleanValue() == b.booleanValue()) ? 0 : (a.booleanValue() ? 1 : -1); } public static int compareTo(Boolean a, boolean b) { return (a.booleanValue() == b) ? 0 : (a.booleanValue() ? 1 : -1); } public static Boolean booleanValueOf(boolean b) { return (b ? Boolean.TRUE : Boolean.FALSE); } public static int compareTo(byte a, byte b) { if (a < b) { return -1; } else if (b < a) { return 1; } else { return 0; } } public static int compareTo(short a, short b) { if (a < b) { return -1; } else if (b < a) { return 1; } else { return 0; } } public static int compareTo(int a, int b) { if (a < b) { return -1; } else if (b < a) { return 1; } else { return 0; } } public static int compareTo(long a, long b) { if (a < b) { return -1; } else if (b < a) { return 1; } else { return 0; } } public static int compareTo(double a, double b) { if (a < b) { return -1; } else if (b < a) { return 1; } else { return 0; } } public static int compareTo(String a, String b) { return a.compareTo(b); } public static int compareTo(byte[] a, byte[] b) { int sizeCompare = compareTo(a.length, b.length); if (sizeCompare != 0) { return sizeCompare; } for (int i = 0; i < a.length; i++) { int byteCompare = compareTo(a, b); if (byteCompare != 0) { return byteCompare; } } return 0; } public static int compareTo(Object a, Object b) { if (a instanceof Vector) { return compareTo((Vector)a, (Vector)b); } if (a instanceof Hashtable) { return compareTo((Hashtable)a, (Hashtable)b); } else { return ((TBase)a).compareTo(b); } } public static int compareTo(Vector a, Vector b) { int lastComparison = compareTo(a.size(), b.size()); if (lastComparison != 0) { return lastComparison; } for (int i = 0; i < a.size(); i++) { Object oA = a.elementAt(i); Object oB = b.elementAt(i); lastComparison = compareTo(oA, oB); if (lastComparison != 0) { return lastComparison; } } return 0; } public static int compareTo(Hashtable a, Hashtable b) { int lastComparison = compareTo(a.size(), b.size()); if (lastComparison != 0) { return lastComparison; } Enumeration enumA = a.keys(); Enumeration enumB = b.keys(); while (lastComparison == 0 && enumA.hasMoreElements()) { Object keyA = enumA.nextElement(); Object keyB = enumB.nextElement(); lastComparison = compareTo(keyA, keyB); if (lastComparison == 0) { lastComparison = compareTo(a.get(keyA), b.get(keyB)); } } return lastComparison; } public static int compareTo(TEnum a, TEnum b) { return compareTo(a.getValue(), b.getValue()); } /* public static int compareTo(List a, List b) { int lastComparison = compareTo(a.size(), b.size()); if (lastComparison != 0) { return lastComparison; } for (int i = 0; i < a.size(); i++) { Object oA = a.get(i); Object oB = b.get(i); if (oA instanceof List) { lastComparison = compareTo((List) oA, (List) oB); } else { lastComparison = compareTo((Comparable) oA, (Comparable) oB); } if (lastComparison != 0) { return lastComparison; } } return 0; } */ public static void toString(byte[] bytes, StringBuffer sb) { toString(bytes, 0, bytes.length, sb); } public static void toString(byte[] buf, int arrayOffset, int origLimit, StringBuffer sb) { int limit = (origLimit - arrayOffset > 128) ? arrayOffset + 128 : origLimit; for (int i = arrayOffset; i < limit; i++) { if (i > arrayOffset) { sb.append(" "); } sb.append(paddedByteString(buf[i])); } if (origLimit != limit) { sb.append("..."); } } public static String paddedByteString(byte b) { int extended = (b | 0x100) & 0x1ff; return Integer.toHexString(extended).toUpperCase().substring(1); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TEnum.java0000644000000000000000000000156514303740367023120 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; public interface TEnum { public int getValue(); } thrift-0.19.0/lib/javame/src/org/apache/thrift/TByteArrayOutputStream.java0000644000000000000000000000225114303740367026504 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.ByteArrayOutputStream; /** * Class that allows access to the underlying buf without doing deep * copies on it. * */ public class TByteArrayOutputStream extends ByteArrayOutputStream { public TByteArrayOutputStream(int size) { super(size); } public byte[] get() { return buf; } public int len() { return count; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/0000777000000000000000000000000014303740367023063 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TProtocolException.java0000644000000000000000000000400014303740367027520 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TException; /** * Protocol exceptions. * */ public class TProtocolException extends TException { private static final long serialVersionUID = 1L; public static final int UNKNOWN = 0; public static final int INVALID_DATA = 1; public static final int NEGATIVE_SIZE = 2; public static final int SIZE_LIMIT = 3; public static final int BAD_VERSION = 4; public static final int NOT_IMPLEMENTED = 5; protected int type_ = UNKNOWN; public TProtocolException() { super(); } public TProtocolException(int type) { super(); type_ = type; } public TProtocolException(int type, String message) { super(message); type_ = type; } public TProtocolException(String message) { super(message); } public TProtocolException(int type, Throwable cause) { super(cause); type_ = type; } public TProtocolException(Throwable cause) { super(cause); } public TProtocolException(String message, Throwable cause) { super(message, cause); } public TProtocolException(int type, String message, Throwable cause) { super(message, cause); type_ = type; } public int getType() { return type_; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java0000644000000000000000000001061714303740367026512 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TException; /** * Utility class with static methods for interacting with protocol data * streams. * */ public class TProtocolUtil { /** * The maximum recursive depth the skip() function will traverse before * throwing a TException. */ private static int maxSkipDepth = Integer.MAX_VALUE; /** * Specifies the maximum recursive depth that the skip function will * traverse before throwing a TException. This is a global setting, so * any call to skip in this JVM will enforce this value. * * @param depth the maximum recursive depth. A value of 2 would allow * the skip function to skip a structure or collection with basic children, * but it would not permit skipping a struct that had a field containing * a child struct. A value of 1 would only allow skipping of simple * types and empty structs/collections. */ public static void setMaxSkipDepth(int depth) { maxSkipDepth = depth; } /** * Skips over the next data element from the provided input TProtocol object. * * @param prot the protocol object to read from * @param type the next value will be intepreted as this TType value. */ public static void skip(TProtocol prot, byte type) throws TException { skip(prot, type, maxSkipDepth); } /** * Skips over the next data element from the provided input TProtocol object. * * @param prot the protocol object to read from * @param type the next value will be intepreted as this TType value. * @param maxDepth this function will only skip complex objects to this * recursive depth, to prevent Java stack overflow. */ public static void skip(TProtocol prot, byte type, int maxDepth) throws TException { if (maxDepth <= 0) { throw new TException("Maximum skip depth exceeded"); } switch (type) { case TType.BOOL: { prot.readBool(); break; } case TType.BYTE: { prot.readByte(); break; } case TType.I16: { prot.readI16(); break; } case TType.I32: { prot.readI32(); break; } case TType.I64: { prot.readI64(); break; } case TType.DOUBLE: { prot.readDouble(); break; } case TType.STRING: { prot.readBinary(); break; } case TType.STRUCT: { prot.readStructBegin(); while (true) { TField field = prot.readFieldBegin(); if (field.type == TType.STOP) { break; } skip(prot, field.type, maxDepth - 1); prot.readFieldEnd(); } prot.readStructEnd(); break; } case TType.MAP: { TMap map = prot.readMapBegin(); for (int i = 0; i < map.size; i++) { skip(prot, map.keyType, maxDepth - 1); skip(prot, map.valueType, maxDepth - 1); } prot.readMapEnd(); break; } case TType.SET: { TSet set = prot.readSetBegin(); for (int i = 0; i < set.size; i++) { skip(prot, set.elemType, maxDepth - 1); } prot.readSetEnd(); break; } case TType.LIST: { TList list = prot.readListBegin(); for (int i = 0; i < list.size; i++) { skip(prot, list.elemType, maxDepth - 1); } prot.readListEnd(); break; } default: throw new TProtocolException(TProtocolException.INVALID_DATA, "Unrecognized type " + type); } } } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TType.java0000644000000000000000000000263514303740367024775 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Type constants in the Thrift protocol. * */ public final class TType { public static final byte STOP = 0; public static final byte VOID = 1; public static final byte BOOL = 2; public static final byte BYTE = 3; public static final byte DOUBLE = 4; public static final byte I16 = 6; public static final byte I32 = 8; public static final byte I64 = 10; public static final byte STRING = 11; public static final byte STRUCT = 12; public static final byte MAP = 13; public static final byte SET = 14; public static final byte LIST = 15; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TBase64Utils.java0000644000000000000000000001236014303740367026115 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Class for encoding and decoding Base64 data. * * This class is kept at package level because the interface does no input * validation and is therefore too low-level for generalized reuse. * * Note also that the encoding does not pad with equal signs , as discussed in * section 2.2 of the RFC (http://www.faqs.org/rfcs/rfc3548.html). Furthermore, * bad data encountered when decoding is neither rejected or ignored but simply * results in bad decoded data -- this is not in compliance with the RFC but is * done in the interest of performance. * */ class TBase64Utils { private static final String ENCODE_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * Encode len bytes of data in src at offset srcOff, storing the result into * dst at offset dstOff. len must be 1, 2, or 3. dst must have at least len+1 * bytes of space at dstOff. src and dst should not be the same object. This * method does no validation of the input values in the interest of * performance. * * @param src the source of bytes to encode * @param srcOff the offset into the source to read the unencoded bytes * @param len the number of bytes to encode (must be 1, 2, or 3). * @param dst the destination for the encoding * @param dstOff the offset into the destination to place the encoded bytes */ static final void encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) { dst[dstOff] = (byte)ENCODE_TABLE.charAt((src[srcOff] >> 2) & 0x3F); if (len == 3) { dst[dstOff + 1] = (byte)ENCODE_TABLE.charAt( ((src[srcOff] << 4) & 0x30) | ((src[srcOff+1] >> 4) & 0x0F)); dst[dstOff + 2] = (byte)ENCODE_TABLE.charAt( ((src[srcOff+1] << 2) & 0x3C) | ((src[srcOff+2] >> 6) & 0x03)); dst[dstOff + 3] = (byte)ENCODE_TABLE.charAt(src[srcOff+2] & 0x3F); } else if (len == 2) { dst[dstOff+1] = (byte)ENCODE_TABLE.charAt( ((src[srcOff] << 4) & 0x30) | ((src[srcOff+1] >> 4) & 0x0F)); dst[dstOff + 2] = (byte)ENCODE_TABLE.charAt((src[srcOff+1] << 2) & 0x3C); } else { // len == 1) { dst[dstOff + 1] = (byte)ENCODE_TABLE.charAt((src[srcOff] << 4) & 0x30); } } private static final byte[] DECODE_TABLE = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; /** * Decode len bytes of data in src at offset srcOff, storing the result into * dst at offset dstOff. len must be 2, 3, or 4. dst must have at least len-1 * bytes of space at dstOff. src and dst may be the same object as long as * dstoff <= srcOff. This method does no validation of the input values in * the interest of performance. * * @param src the source of bytes to decode * @param srcOff the offset into the source to read the encoded bytes * @param len the number of bytes to decode (must be 2, 3, or 4) * @param dst the destination for the decoding * @param dstOff the offset into the destination to place the decoded bytes */ static final void decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) { dst[dstOff] = (byte) ((DECODE_TABLE[src[srcOff] & 0x0FF] << 2) | (DECODE_TABLE[src[srcOff+1] & 0x0FF] >> 4)); if (len > 2) { dst[dstOff+1] = (byte) (((DECODE_TABLE[src[srcOff+1] & 0x0FF] << 4) & 0xF0) | (DECODE_TABLE[src[srcOff+2] & 0x0FF] >> 2)); if (len > 3) { dst[dstOff+2] = (byte) (((DECODE_TABLE[src[srcOff+2] & 0x0FF] << 6) & 0xC0) | DECODE_TABLE[src[srcOff+3] & 0x0FF]); } } } } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TMessage.java0000644000000000000000000000213214303740367025430 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates struct metadata. * */ public class TMessage { public TMessage() {} public TMessage(String n, byte t, int s) { name = n; type = t; seqid = s; } public String name = ""; public byte type; public int seqid; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TMap.java0000644000000000000000000000217114303740367024564 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates map metadata. * */ public class TMap { public TMap() {} public TMap(byte k, byte v, int s) { keyType = k; valueType = v; size = s; } public byte keyType = TType.STOP; public byte valueType = TType.STOP; public int size = 0; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TProtocol.java0000644000000000000000000001057314303740367025655 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; /** * Protocol interface definition. * */ public abstract class TProtocol { /** * Prevent direct instantiation */ private TProtocol() {} /** * Transport */ protected TTransport trans_; /** * Constructor */ protected TProtocol(TTransport trans) { trans_ = trans; } /** * Transport accessor */ public TTransport getTransport() { return trans_; } /** * Writing methods. */ public abstract void writeMessageBegin(TMessage message) throws TException; public abstract void writeMessageEnd() throws TException; public abstract void writeStructBegin(TStruct struct) throws TException; public abstract void writeStructEnd() throws TException; public abstract void writeFieldBegin(TField field) throws TException; public abstract void writeFieldEnd() throws TException; public abstract void writeFieldStop() throws TException; public abstract void writeMapBegin(TMap map) throws TException; public abstract void writeMapEnd() throws TException; public abstract void writeListBegin(TList list) throws TException; public abstract void writeListEnd() throws TException; public abstract void writeSetBegin(TSet set) throws TException; public abstract void writeSetEnd() throws TException; public abstract void writeBool(boolean b) throws TException; public void writeBool(Boolean b) throws TException { writeBool(b.booleanValue()); } public abstract void writeByte(byte b) throws TException; public void writeByte(Byte b) throws TException { writeByte(b.byteValue()); } public abstract void writeI16(short i16) throws TException; public void writeI16(Short i16) throws TException { writeI16(i16.shortValue()); } public abstract void writeI32(int i32) throws TException; public void writeI32(Integer i32) throws TException { writeI32(i32.intValue()); } public abstract void writeI64(long i64) throws TException; public void writeI64(Long i64) throws TException { writeI64(i64.longValue()); } public abstract void writeDouble(double dub) throws TException; public void writeDouble(Double d) throws TException { writeDouble(d.doubleValue()); } public abstract void writeString(String str) throws TException; public abstract void writeBinary(byte[] bin) throws TException; /** * Reading methods. */ public abstract TMessage readMessageBegin() throws TException; public abstract void readMessageEnd() throws TException; public abstract TStruct readStructBegin() throws TException; public abstract void readStructEnd() throws TException; public abstract TField readFieldBegin() throws TException; public abstract void readFieldEnd() throws TException; public abstract TMap readMapBegin() throws TException; public abstract void readMapEnd() throws TException; public abstract TList readListBegin() throws TException; public abstract void readListEnd() throws TException; public abstract TSet readSetBegin() throws TException; public abstract void readSetEnd() throws TException; public abstract boolean readBool() throws TException; public abstract byte readByte() throws TException; public abstract short readI16() throws TException; public abstract int readI32() throws TException; public abstract long readI64() throws TException; public abstract double readDouble() throws TException; public abstract String readString() throws TException; public abstract byte[] readBinary() throws TException; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TSet.java0000644000000000000000000000206414303740367024603 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates set metadata. * */ public class TSet { public TSet() {} public TSet(byte t, int s) { elemType = t; size = s; } public byte elemType = TType.STOP; public int size = 0; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TMessageType.java0000644000000000000000000000204114303740367026271 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Message type constants in the Thrift protocol. * */ public final class TMessageType { public static final byte CALL = 1; public static final byte REPLY = 2; public static final byte EXCEPTION = 3; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TProtocolFactory.java0000644000000000000000000000202714303740367027200 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.transport.TTransport; /** * Factory interface for constructing protocol instances. * */ public interface TProtocolFactory { public TProtocol getProtocol(TTransport trans); } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TList.java0000644000000000000000000000207014303740367024760 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates list metadata. * */ public class TList { public TList() {} public TList(byte t, int s) { elemType = t; size = s; } public byte elemType = TType.STOP; public int size = 0; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TField.java0000644000000000000000000000214714303740367025075 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates field metadata. * */ public class TField { public TField() {} public TField(String n, byte t, short i) { name = n; type = t; id = i; } public String name = ""; public byte type = TType.STOP; public short id = 0; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TJSONProtocol.java0000644000000000000000000006700514303740367026351 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Stack; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; /** * JSON protocol implementation for thrift. * This is a full-featured protocol supporting write and read. * Please see the C++ class header for a detailed description of the * protocol's wire format. */ public class TJSONProtocol extends TProtocol { /** * Factory for JSON protocol objects */ public static class Factory implements TProtocolFactory { public TProtocol getProtocol(TTransport trans) { return new TJSONProtocol(trans); } } private static final byte[] COMMA = new byte[] { ',' }; private static final byte[] COLON = new byte[] { ':' }; private static final byte[] LBRACE = new byte[] { '{' }; private static final byte[] RBRACE = new byte[] { '}' }; private static final byte[] LBRACKET = new byte[] { '[' }; private static final byte[] RBRACKET = new byte[] { ']' }; private static final byte[] QUOTE = new byte[] { '"' }; private static final byte[] BACKSLASH = new byte[] { '\\' }; private static final byte[] ZERO = new byte[] { '0' }; private static final byte[] ESCSEQ = new byte[] { '\\', 'u', '0', '0' }; private static final long VERSION = 1; private static final byte[] JSON_CHAR_TABLE = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, // 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 1, 1, '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 }; private static final String ESCAPE_CHARS = "\"\\/bfnrt"; private static final byte[] ESCAPE_CHAR_VALS = { '"', '\\', '/', '\b', '\f', '\n', '\r', '\t', }; private static final int DEF_STRING_SIZE = 16; private static final byte[] NAME_BOOL = new byte[] { 't', 'f' }; private static final byte[] NAME_BYTE = new byte[] { 'i', '8' }; private static final byte[] NAME_I16 = new byte[] { 'i', '1', '6' }; private static final byte[] NAME_I32 = new byte[] { 'i', '3', '2' }; private static final byte[] NAME_I64 = new byte[] { 'i', '6', '4' }; private static final byte[] NAME_DOUBLE = new byte[] { 'd', 'b', 'l' }; private static final byte[] NAME_STRUCT = new byte[] { 'r', 'e', 'c' }; private static final byte[] NAME_STRING = new byte[] { 's', 't', 'r' }; private static final byte[] NAME_MAP = new byte[] { 'm', 'a', 'p' }; private static final byte[] NAME_LIST = new byte[] { 'l', 's', 't' }; private static final byte[] NAME_SET = new byte[] { 's', 'e', 't' }; private static final TStruct ANONYMOUS_STRUCT = new TStruct(); private static final byte[] getTypeNameForTypeID(byte typeID) throws TException { switch (typeID) { case TType.BOOL: return NAME_BOOL; case TType.BYTE: return NAME_BYTE; case TType.I16: return NAME_I16; case TType.I32: return NAME_I32; case TType.I64: return NAME_I64; case TType.DOUBLE: return NAME_DOUBLE; case TType.STRING: return NAME_STRING; case TType.STRUCT: return NAME_STRUCT; case TType.MAP: return NAME_MAP; case TType.SET: return NAME_SET; case TType.LIST: return NAME_LIST; default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized type"); } } private static final byte getTypeIDForTypeName(byte[] name) throws TException { byte result = TType.STOP; if (name.length > 1) { switch (name[0]) { case 'd': result = TType.DOUBLE; break; case 'i': switch (name[1]) { case '8': result = TType.BYTE; break; case '1': result = TType.I16; break; case '3': result = TType.I32; break; case '6': result = TType.I64; break; } break; case 'l': result = TType.LIST; break; case 'm': result = TType.MAP; break; case 'r': result = TType.STRUCT; break; case 's': if (name[1] == 't') { result = TType.STRING; } else if (name[1] == 'e') { result = TType.SET; } break; case 't': result = TType.BOOL; break; } } if (result == TType.STOP) { throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized type"); } return result; } // Base class for tracking JSON contexts that may require inserting/reading // additional JSON syntax characters // This base context does nothing. protected class JSONBaseContext { /** * @throws TException */ protected void write() throws TException {} /** * @throws TException */ protected void read() throws TException {} protected boolean escapeNum() { return false; } } // Context for JSON lists. Will insert/read commas before each item except // for the first one protected class JSONListContext extends JSONBaseContext { private boolean first_ = true; protected void write() throws TException { if (first_) { first_ = false; } else { trans_.write(COMMA); } } protected void read() throws TException { if (first_) { first_ = false; } else { readJSONSyntaxChar(COMMA); } } } // Context for JSON records. Will insert/read colons before the value portion // of each record pair, and commas before each key except the first. In // addition, will indicate that numbers in the key position need to be // escaped in quotes (since JSON keys must be strings). protected class JSONPairContext extends JSONBaseContext { private boolean first_ = true; private boolean colon_ = true; protected void write() throws TException { if (first_) { first_ = false; colon_ = true; } else { trans_.write(colon_ ? COLON : COMMA); colon_ = !colon_; } } protected void read() throws TException { if (first_) { first_ = false; colon_ = true; } else { readJSONSyntaxChar(colon_ ? COLON : COMMA); colon_ = !colon_; } } protected boolean escapeNum() { return colon_; } } // Holds up to one byte from the transport protected class LookaheadReader { private boolean hasData_; private byte[] data_ = new byte[1]; // Return and consume the next byte to be read, either taking it from the // data buffer if present or getting it from the transport otherwise. protected byte read() throws TException { if (hasData_) { hasData_ = false; } else { trans_.readAll(data_, 0, 1); } return data_[0]; } // Return the next byte to be read without consuming, filling the data // buffer if it has not been filled already. protected byte peek() throws TException { if (!hasData_) { trans_.readAll(data_, 0, 1); } hasData_ = true; return data_[0]; } } // Stack of nested contexts of type JSONBaseContext that we may be in private Stack contextStack_ = new Stack(); // Current context that we are in private JSONBaseContext context_ = new JSONBaseContext(); // Reader that manages a 1-byte buffer private LookaheadReader reader_ = new LookaheadReader(); // Push a new JSON context onto the stack. private void pushContext(JSONBaseContext c) { contextStack_.push(context_); context_ = c; } // Pop the last JSON context off the stack private void popContext() { context_ = (JSONBaseContext)contextStack_.pop(); } /** * Constructor */ public TJSONProtocol(TTransport trans) { super(trans); } public void reset() { contextStack_.clear(); context_ = new JSONBaseContext(); reader_ = new LookaheadReader(); } // Temporary buffer used by several methods private byte[] tmpbuf_ = new byte[4]; // Read a byte that must match b[0]; otherwise an exception is thrown. // Marked protected to avoid synthetic accessor in JSONListContext.read // and JSONPairContext.read protected void readJSONSyntaxChar(byte[] b) throws TException { byte ch = reader_.read(); if (ch != b[0]) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Unexpected character:" + (char)ch); } } // Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its // corresponding hex value private static final byte hexVal(byte ch) throws TException { if ((ch >= '0') && (ch <= '9')) { return (byte)((char)ch - '0'); } else if ((ch >= 'a') && (ch <= 'f')) { return (byte)((char)ch - 'a' + 10); } else { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); } } // Convert a byte containing a hex value to its corresponding hex character private static final byte hexChar(byte val) { val &= 0x0F; if (val < 10) { return (byte)((char)val + '0'); } else { return (byte)((char)(val - 10) + 'a'); } } private static boolean isHighSurrogate(char c) { return c >= '\uD800' && c <= '\uDBFF'; } private static boolean isLowSurrogate(char c) { return c >= '\uDC00' && c <= '\uDFFF'; } private static byte[] toUTF8(int codepoint) { final int[] FIRST_BYTE_MASK = { 0, 0xc0, 0xe0, 0xf0 }; int length = 0; if (codepoint <= 0x7f) length = 1; else if (codepoint <= 0x7ff) length = 2; else if (codepoint <= 0xffff) length = 3; else if (codepoint <= 0x1fffff) length = 4; else throw new RuntimeException("Code point over U+1FFFFF is not supported"); byte[] bytes = new byte[length]; switch (length) { case 4: bytes[3] = (byte)((codepoint & 0x3f) | 0x80); codepoint >>= 6; case 3: bytes[2] = (byte)((codepoint & 0x3f) | 0x80); codepoint >>= 6; case 2: bytes[1] = (byte)((codepoint & 0x3f) | 0x80); codepoint >>= 6; case 1: bytes[0] = (byte)(codepoint | FIRST_BYTE_MASK[length - 1]); } return bytes; } private static byte[] toUTF8(int high, int low) { int codepoint = (1 << 16) + ((high & 0x3ff) << 10); codepoint += low & 0x3ff; return toUTF8(codepoint); } // Write the bytes in array buf as a JSON characters, escaping as needed private void writeJSONString(byte[] b) throws TException { context_.write(); trans_.write(QUOTE); int len = b.length; for (int i = 0; i < len; i++) { if ((b[i] & 0x00FF) >= 0x30) { if (b[i] == BACKSLASH[0]) { trans_.write(BACKSLASH); trans_.write(BACKSLASH); } else { trans_.write(b, i, 1); } } else { tmpbuf_[0] = JSON_CHAR_TABLE[b[i]]; if (tmpbuf_[0] == 1) { trans_.write(b, i, 1); } else if (tmpbuf_[0] > 1) { trans_.write(BACKSLASH); trans_.write(tmpbuf_, 0, 1); } else { trans_.write(ESCSEQ); tmpbuf_[0] = hexChar((byte)(b[i] >> 4)); tmpbuf_[1] = hexChar(b[i]); trans_.write(tmpbuf_, 0, 2); } } } trans_.write(QUOTE); } // Write out number as a JSON value. If the context dictates so, it will be // wrapped in quotes to output as a JSON string. private void writeJSONInteger(long num) throws TException { context_.write(); String str = Long.toString(num); boolean escapeNum = context_.escapeNum(); if (escapeNum) { trans_.write(QUOTE); } try { byte[] buf = str.getBytes("UTF-8"); trans_.write(buf); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } if (escapeNum) { trans_.write(QUOTE); } } // Write out a double as a JSON value. If it is NaN or infinity or if the // context dictates escaping, write out as JSON string. private void writeJSONDouble(double num) throws TException { context_.write(); String str = Double.toString(num); boolean special = false; switch (str.charAt(0)) { case 'N': // NaN case 'I': // Infinity special = true; break; case '-': if (str.charAt(1) == 'I') { // -Infinity special = true; } break; } boolean escapeNum = special || context_.escapeNum(); if (escapeNum) { trans_.write(QUOTE); } try { byte[] b = str.getBytes("UTF-8"); trans_.write(b, 0, b.length); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } if (escapeNum) { trans_.write(QUOTE); } } // Write out contents of byte array b as a JSON string with base-64 encoded // data private void writeJSONBase64(byte[] b, int offset, int length) throws TException { context_.write(); trans_.write(QUOTE); int len = length; int off = offset; while (len >= 3) { // Encode 3 bytes at a time TBase64Utils.encode(b, off, 3, tmpbuf_, 0); trans_.write(tmpbuf_, 0, 4); off += 3; len -= 3; } if (len > 0) { // Encode remainder TBase64Utils.encode(b, off, len, tmpbuf_, 0); trans_.write(tmpbuf_, 0, len + 1); } trans_.write(QUOTE); } private void writeJSONObjectStart() throws TException { context_.write(); trans_.write(LBRACE); pushContext(new JSONPairContext()); } private void writeJSONObjectEnd() throws TException { popContext(); trans_.write(RBRACE); } private void writeJSONArrayStart() throws TException { context_.write(); trans_.write(LBRACKET); pushContext(new JSONListContext()); } private void writeJSONArrayEnd() throws TException { popContext(); trans_.write(RBRACKET); } public void writeMessageBegin(TMessage message) throws TException { writeJSONArrayStart(); writeJSONInteger(VERSION); try { byte[] b = message.name.getBytes("UTF-8"); writeJSONString(b); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } writeJSONInteger(message.type); writeJSONInteger(message.seqid); } public void writeMessageEnd() throws TException { writeJSONArrayEnd(); } public void writeStructBegin(TStruct struct) throws TException { writeJSONObjectStart(); } public void writeStructEnd() throws TException { writeJSONObjectEnd(); } public void writeFieldBegin(TField field) throws TException { writeJSONInteger(field.id); writeJSONObjectStart(); writeJSONString(getTypeNameForTypeID(field.type)); } public void writeFieldEnd() throws TException { writeJSONObjectEnd(); } public void writeFieldStop() {} public void writeMapBegin(TMap map) throws TException { writeJSONArrayStart(); writeJSONString(getTypeNameForTypeID(map.keyType)); writeJSONString(getTypeNameForTypeID(map.valueType)); writeJSONInteger(map.size); writeJSONObjectStart(); } public void writeMapEnd() throws TException { writeJSONObjectEnd(); writeJSONArrayEnd(); } public void writeListBegin(TList list) throws TException { writeJSONArrayStart(); writeJSONString(getTypeNameForTypeID(list.elemType)); writeJSONInteger(list.size); } public void writeListEnd() throws TException { writeJSONArrayEnd(); } public void writeSetBegin(TSet set) throws TException { writeJSONArrayStart(); writeJSONString(getTypeNameForTypeID(set.elemType)); writeJSONInteger(set.size); } public void writeSetEnd() throws TException { writeJSONArrayEnd(); } public void writeBool(boolean b) throws TException { writeJSONInteger(b ? (long)1 : (long)0); } public void writeByte(byte b) throws TException { writeJSONInteger(b); } public void writeI16(short i16) throws TException { writeJSONInteger(i16); } public void writeI32(int i32) throws TException { writeJSONInteger(i32); } public void writeI64(long i64) throws TException { writeJSONInteger(i64); } public void writeDouble(double dub) throws TException { writeJSONDouble(dub); } public void writeString(String str) throws TException { try { byte[] b = str.getBytes("UTF-8"); writeJSONString(b); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } } public void writeBinary(byte[] bin) throws TException { writeJSONBase64(bin, 0, bin.length); } /** * Reading methods. */ // Read in a JSON string, unescaping as appropriate.. Skip reading from the // context if skipContext is true. private TByteArrayOutputStream readJSONString(boolean skipContext) throws TException { TByteArrayOutputStream arr = new TByteArrayOutputStream(DEF_STRING_SIZE); int highSurrogate = 0; if (!skipContext) { context_.read(); } readJSONSyntaxChar(QUOTE); while (true) { byte ch = reader_.read(); if (ch == QUOTE[0]) { break; } if (ch == ESCSEQ[0]) { ch = reader_.read(); if (ch == ESCSEQ[1]) { trans_.readAll(tmpbuf_, 0, 4); short cu = (short)( ((short)hexVal(tmpbuf_[0]) << 12) + ((short)hexVal(tmpbuf_[1]) << 8) + ((short)hexVal(tmpbuf_[2]) << 4) + (short)hexVal(tmpbuf_[3])); try { if (isHighSurrogate((char)cu)) { if (highSurrogate != 0) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); } highSurrogate = cu; } else if (isLowSurrogate((char)cu)) { if (highSurrogate == 0) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected high surrogate char"); } arr.write(toUTF8(highSurrogate, cu)); highSurrogate = 0; } else { arr.write(toUTF8(cu)); } continue; } catch (UnsupportedEncodingException ex) { throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "JVM does not support UTF-8"); } catch (IOException ex) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Invalid unicode sequence"); } } else { int off = ESCAPE_CHARS.indexOf(ch); if (off == -1) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); } ch = ESCAPE_CHAR_VALS[off]; } } arr.write(ch); } if (highSurrogate != 0) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); } return arr; } // Return true if the given byte could be a valid part of a JSON number. private boolean isJSONNumeric(byte b) { switch (b) { case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'E': case 'e': return true; } return false; } // Read in a sequence of characters that are all valid in JSON numbers. Does // not do a complete regex check to validate that this is actually a number. private String readJSONNumericChars() throws TException { StringBuffer strbuf = new StringBuffer(); while (true) { byte ch = reader_.peek(); if (!isJSONNumeric(ch)) { break; } strbuf.append((char)reader_.read()); } return strbuf.toString(); } // Read in a JSON number. If the context dictates, read in enclosing quotes. private long readJSONInteger() throws TException { context_.read(); if (context_.escapeNum()) { readJSONSyntaxChar(QUOTE); } String str = readJSONNumericChars(); if (context_.escapeNum()) { readJSONSyntaxChar(QUOTE); } try { return Long.valueOf(str).longValue(); } catch (NumberFormatException ex) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); } } // Read in a JSON double value. Throw if the value is not wrapped in quotes // when expected or if wrapped in quotes when not expected. private double readJSONDouble() throws TException { context_.read(); if (reader_.peek() == QUOTE[0]) { TByteArrayOutputStream arr = readJSONString(true); try { double dub = Double.valueOf(arr.toString("UTF-8")).doubleValue(); if (!context_.escapeNum() && !Double.isNaN(dub) && !Double.isInfinite(dub)) { // Throw exception -- we should not be in a string in this case throw new TProtocolException(TProtocolException.INVALID_DATA, "Numeric data unexpectedly quoted"); } return dub; } catch (UnsupportedEncodingException ex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } } else { if (context_.escapeNum()) { // This will throw - we should have had a quote if escapeNum == true readJSONSyntaxChar(QUOTE); } try { return Double.valueOf(readJSONNumericChars()).doubleValue(); } catch (NumberFormatException ex) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); } } } // Read in a JSON string containing base-64 encoded data and decode it. private byte[] readJSONBase64() throws TException { TByteArrayOutputStream arr = readJSONString(false); byte[] b = arr.get(); int len = arr.len(); int off = 0; int size = 0; // Ignore padding int bound = len >= 2 ? len - 2 : 0; for (int i = len - 1; i >= bound && b[i] == '='; --i) { --len; } while (len >= 4) { // Decode 4 bytes at a time TBase64Utils.decode(b, off, 4, b, size); // NB: decoded in place off += 4; len -= 4; size += 3; } // Don't decode if we hit the end or got a single leftover byte (invalid // base64 but legal for skip of regular string type) if (len > 1) { // Decode remainder TBase64Utils.decode(b, off, len, b, size); // NB: decoded in place size += len - 1; } // Sadly we must copy the byte[] (any way around this?) byte[] result = new byte[size]; System.arraycopy(b, 0, result, 0, size); return result; } private void readJSONObjectStart() throws TException { context_.read(); readJSONSyntaxChar(LBRACE); pushContext(new JSONPairContext()); } private void readJSONObjectEnd() throws TException { readJSONSyntaxChar(RBRACE); popContext(); } private void readJSONArrayStart() throws TException { context_.read(); readJSONSyntaxChar(LBRACKET); pushContext(new JSONListContext()); } private void readJSONArrayEnd() throws TException { readJSONSyntaxChar(RBRACKET); popContext(); } public TMessage readMessageBegin() throws TException { readJSONArrayStart(); if (readJSONInteger() != VERSION) { throw new TProtocolException(TProtocolException.BAD_VERSION, "Message contained bad version."); } String name; try { name = readJSONString(false).toString("UTF-8"); } catch (UnsupportedEncodingException ex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } byte type = (byte)readJSONInteger(); int seqid = (int)readJSONInteger(); return new TMessage(name, type, seqid); } public void readMessageEnd() throws TException { readJSONArrayEnd(); } public TStruct readStructBegin() throws TException { readJSONObjectStart(); return ANONYMOUS_STRUCT; } public void readStructEnd() throws TException { readJSONObjectEnd(); } public TField readFieldBegin() throws TException { byte ch = reader_.peek(); byte type; short id = 0; if (ch == RBRACE[0]) { type = TType.STOP; } else { id = (short)readJSONInteger(); readJSONObjectStart(); type = getTypeIDForTypeName(readJSONString(false).get()); } return new TField("", type, id); } public void readFieldEnd() throws TException { readJSONObjectEnd(); } public TMap readMapBegin() throws TException { readJSONArrayStart(); byte keyType = getTypeIDForTypeName(readJSONString(false).get()); byte valueType = getTypeIDForTypeName(readJSONString(false).get()); int size = (int)readJSONInteger(); readJSONObjectStart(); return new TMap(keyType, valueType, size); } public void readMapEnd() throws TException { readJSONObjectEnd(); readJSONArrayEnd(); } public TList readListBegin() throws TException { readJSONArrayStart(); byte elemType = getTypeIDForTypeName(readJSONString(false).get()); int size = (int)readJSONInteger(); return new TList(elemType, size); } public void readListEnd() throws TException { readJSONArrayEnd(); } public TSet readSetBegin() throws TException { readJSONArrayStart(); byte elemType = getTypeIDForTypeName(readJSONString(false).get()); int size = (int)readJSONInteger(); return new TSet(elemType, size); } public void readSetEnd() throws TException { readJSONArrayEnd(); } public boolean readBool() throws TException { return (readJSONInteger() == 0 ? false : true); } public byte readByte() throws TException { return (byte)readJSONInteger(); } public short readI16() throws TException { return (short)readJSONInteger(); } public int readI32() throws TException { return (int)readJSONInteger(); } public long readI64() throws TException { return readJSONInteger(); } public double readDouble() throws TException { return readJSONDouble(); } public String readString() throws TException { try { return readJSONString(false).toString("UTF-8"); } catch (UnsupportedEncodingException ex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } } public byte[] readBinary() throws TException { return readJSONBase64(); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TStruct.java0000644000000000000000000000200314303740367025325 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates struct metadata. * */ public class TStruct { public TStruct() {} public TStruct(String n) { name = n; } public String name = ""; } thrift-0.19.0/lib/javame/src/org/apache/thrift/protocol/TBinaryProtocol.java0000644000000000000000000002071014303740367027014 0ustar00rootroot00000000000000 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.io.UnsupportedEncodingException; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; /** * Binary protocol implementation for thrift. * */ public class TBinaryProtocol extends TProtocol { protected static final int VERSION_MASK = 0xffff0000; protected static final int VERSION_1 = 0x80010000; protected boolean strictRead_ = false; protected boolean strictWrite_ = true; /** * Factory */ public static class Factory implements TProtocolFactory { protected boolean strictRead_ = false; protected boolean strictWrite_ = true; public Factory() { this(false, true); } public Factory(boolean strictRead, boolean strictWrite) { strictRead_ = strictRead; strictWrite_ = strictWrite; } public TProtocol getProtocol(TTransport trans) { return new TBinaryProtocol(trans, strictRead_, strictWrite_); } } /** * Constructor */ public TBinaryProtocol(TTransport trans) { this(trans, false, true); } public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) { super(trans); strictRead_ = strictRead; strictWrite_ = strictWrite; } public void writeMessageBegin(TMessage message) throws TException { if (strictWrite_) { int version = VERSION_1 | message.type; writeI32(version); writeString(message.name); writeI32(message.seqid); } else { writeString(message.name); writeByte(message.type); writeI32(message.seqid); } } public void writeMessageEnd() {} public void writeStructBegin(TStruct struct) {} public void writeStructEnd() {} public void writeFieldBegin(TField field) throws TException { writeByte(field.type); writeI16(field.id); } public void writeFieldEnd() {} public void writeFieldStop() throws TException { writeByte(TType.STOP); } public void writeMapBegin(TMap map) throws TException { writeByte(map.keyType); writeByte(map.valueType); writeI32(map.size); } public void writeMapEnd() {} public void writeListBegin(TList list) throws TException { writeByte(list.elemType); writeI32(list.size); } public void writeListEnd() {} public void writeSetBegin(TSet set) throws TException { writeByte(set.elemType); writeI32(set.size); } public void writeSetEnd() {} public void writeBool(boolean b) throws TException { writeByte(b ? (byte)1 : (byte)0); } private byte [] bout = new byte[1]; public void writeByte(byte b) throws TException { bout[0] = b; trans_.write(bout, 0, 1); } private byte[] i16out = new byte[2]; public void writeI16(short i16) throws TException { i16out[0] = (byte)(0xff & (i16 >> 8)); i16out[1] = (byte)(0xff & (i16)); trans_.write(i16out, 0, 2); } private byte[] i32out = new byte[4]; public void writeI32(int i32) throws TException { i32out[0] = (byte)(0xff & (i32 >> 24)); i32out[1] = (byte)(0xff & (i32 >> 16)); i32out[2] = (byte)(0xff & (i32 >> 8)); i32out[3] = (byte)(0xff & (i32)); trans_.write(i32out, 0, 4); } private byte[] i64out = new byte[8]; public void writeI64(long i64) throws TException { i64out[0] = (byte)(0xff & (i64 >> 56)); i64out[1] = (byte)(0xff & (i64 >> 48)); i64out[2] = (byte)(0xff & (i64 >> 40)); i64out[3] = (byte)(0xff & (i64 >> 32)); i64out[4] = (byte)(0xff & (i64 >> 24)); i64out[5] = (byte)(0xff & (i64 >> 16)); i64out[6] = (byte)(0xff & (i64 >> 8)); i64out[7] = (byte)(0xff & (i64)); trans_.write(i64out, 0, 8); } public void writeDouble(double dub) throws TException { writeI64(Double.doubleToLongBits(dub)); } public void writeString(String str) throws TException { try { byte[] dat = str.getBytes("UTF-8"); writeI32(dat.length); trans_.write(dat, 0, dat.length); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } } public void writeBinary(byte[] bin) throws TException { writeI32(bin.length); trans_.write(bin, 0, bin.length); } /** * Reading methods. */ public TMessage readMessageBegin() throws TException { TMessage message = new TMessage(); int size = readI32(); if (size < 0) { int version = size & VERSION_MASK; if (version != VERSION_1) { throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in readMessageBegin"); } message.type = (byte)(size & 0x000000ff); message.name = readString(); message.seqid = readI32(); } else { if (strictRead_) { throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); } message.name = readStringBody(size); message.type = readByte(); message.seqid = readI32(); } return message; } public void readMessageEnd() {} public TStruct readStructBegin() { return new TStruct(); } public void readStructEnd() {} public TField readFieldBegin() throws TException { TField field = new TField(); field.type = readByte(); if (field.type != TType.STOP) { field.id = readI16(); } return field; } public void readFieldEnd() {} public TMap readMapBegin() throws TException { TMap map = new TMap(); map.keyType = readByte(); map.valueType = readByte(); map.size = readI32(); return map; } public void readMapEnd() {} public TList readListBegin() throws TException { TList list = new TList(); list.elemType = readByte(); list.size = readI32(); return list; } public void readListEnd() {} public TSet readSetBegin() throws TException { TSet set = new TSet(); set.elemType = readByte(); set.size = readI32(); return set; } public void readSetEnd() {} public boolean readBool() throws TException { return (readByte() == 1); } private byte[] bin = new byte[1]; public byte readByte() throws TException { readAll(bin, 0, 1); return bin[0]; } private byte[] i16rd = new byte[2]; public short readI16() throws TException { readAll(i16rd, 0, 2); return (short) (((i16rd[0] & 0xff) << 8) | ((i16rd[1] & 0xff))); } private byte[] i32rd = new byte[4]; public int readI32() throws TException { readAll(i32rd, 0, 4); return ((i32rd[0] & 0xff) << 24) | ((i32rd[1] & 0xff) << 16) | ((i32rd[2] & 0xff) << 8) | ((i32rd[3] & 0xff)); } private byte[] i64rd = new byte[8]; public long readI64() throws TException { readAll(i64rd, 0, 8); return ((long)(i64rd[0] & 0xff) << 56) | ((long)(i64rd[1] & 0xff) << 48) | ((long)(i64rd[2] & 0xff) << 40) | ((long)(i64rd[3] & 0xff) << 32) | ((long)(i64rd[4] & 0xff) << 24) | ((long)(i64rd[5] & 0xff) << 16) | ((long)(i64rd[6] & 0xff) << 8) | ((long)(i64rd[7] & 0xff)); } public double readDouble() throws TException { return Double.longBitsToDouble(readI64()); } public String readString() throws TException { int size = readI32(); return readStringBody(size); } public String readStringBody(int size) throws TException { try { byte[] buf = new byte[size]; trans_.readAll(buf, 0, size); return new String(buf, "UTF-8"); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT UTF-8"); } } public byte[] readBinary() throws TException { int size = readI32(); byte[] buf = new byte[size]; trans_.readAll(buf, 0, size); return buf; } private int readAll(byte[] buf, int off, int len) throws TException { return trans_.readAll(buf, off, len); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TSerializer.java0000644000000000000000000000636314303740367024326 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; /** * Generic utility for easily serializing objects into a byte array or Java * String. * */ public class TSerializer { /** * This is the byte array that data is actually serialized into */ private final ByteArrayOutputStream baos_ = new ByteArrayOutputStream(); /** * This transport wraps that byte array */ private final TIOStreamTransport transport_ = new TIOStreamTransport(baos_); /** * Internal protocol used for serializing objects. */ private TProtocol protocol_; /** * Create a new TSerializer that uses the TBinaryProtocol by default. */ public TSerializer() { this(new TBinaryProtocol.Factory()); } /** * Create a new TSerializer. It will use the TProtocol specified by the * factory that is passed in. * * @param protocolFactory Factory to create a protocol */ public TSerializer(TProtocolFactory protocolFactory) { protocol_ = protocolFactory.getProtocol(transport_); } /** * Serialize the Thrift object into a byte array. The process is simple, * just clear the byte array output, write the object into it, and grab the * raw bytes. * * @param base The object to serialize * @return Serialized object in byte[] format */ public byte[] serialize(TBase base) throws TException { baos_.reset(); base.write(protocol_); return baos_.toByteArray(); } /** * Serialize the Thrift object into a Java string, using a specified * character set for encoding. * * @param base The object to serialize * @param charset Valid JVM charset * @return Serialized object as a String */ public String toString(TBase base, String charset) throws TException { try { return new String(serialize(base), charset); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT ENCODING: " + charset); } } /** * Serialize the Thrift object into a Java string, using the default JVM * charset encoding. * * @param base The object to serialize * @return Serialized object as a String */ public String toString(TBase base) throws TException { return new String(serialize(base)); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TException.java0000644000000000000000000000232514303740367024145 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** * Generic exception class for Thrift. * */ public class TException extends Exception { private static final long serialVersionUID = 1L; public TException() { super(); } public TException(String message) { super(message); } public TException(Throwable cause) { super(cause.getMessage()); } public TException(String message, Throwable cause) { super(message); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TProcessor.java0000644000000000000000000000212314303740367024162 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TProtocol; /** * A processor is a generic object which operates upon an input stream and * writes to some output stream. * */ public interface TProcessor { public boolean process(TProtocol in, TProtocol out) throws TException; } thrift-0.19.0/lib/javame/src/org/apache/thrift/TServiceClient.java0000644000000000000000000000241414303740367024745 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TProtocol; /** * A TServiceClient is used to communicate with a TService implementation * across protocols and transports. */ public interface TServiceClient { /** * Get the TProtocol being used as the input (read) protocol. * @return */ public TProtocol getInputProtocol(); /** * Get the TProtocol being used as the output (write) protocol. * @return */ public TProtocol getOutputProtocol(); } thrift-0.19.0/lib/javame/src/org/apache/thrift/TDeserializer.java0000644000000000000000000000560014303740367024630 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; /** * Generic utility for easily deserializing objects from a byte array or Java * String. * */ public class TDeserializer { private final TProtocolFactory protocolFactory_; /** * Create a new TDeserializer that uses the TBinaryProtocol by default. */ public TDeserializer() { this(new TBinaryProtocol.Factory()); } /** * Create a new TDeserializer. It will use the TProtocol specified by the * factory that is passed in. * * @param protocolFactory Factory to create a protocol */ public TDeserializer(TProtocolFactory protocolFactory) { protocolFactory_ = protocolFactory; } /** * Deserialize the Thrift object from a byte array. * * @param base The object to read into * @param bytes The array to read from */ public void deserialize(TBase base, byte[] bytes) throws TException { base.read( protocolFactory_.getProtocol( new TIOStreamTransport( new ByteArrayInputStream(bytes)))); } /** * Deserialize the Thrift object from a Java string, using a specified * character set for decoding. * * @param base The object to read into * @param data The string to read from * @param charset Valid JVM charset */ public void deserialize(TBase base, String data, String charset) throws TException { try { deserialize(base, data.getBytes(charset)); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT ENCODING: " + charset); } } /** * Deerialize the Thrift object from a Java string, using the default JVM * charset encoding. * * @param base The object to read into * @param data The string to read from * @return Serialized object as a String */ public void toString(TBase base, String data) throws TException { deserialize(base, data.getBytes()); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TBase.java0000644000000000000000000000245614303740367023066 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TProtocol; /** * Generic base interface for generated Thrift objects. * */ public interface TBase { /** * Reads the TObject from the given input protocol. * * @param iprot Input protocol */ public void read(TProtocol iprot) throws TException; /** * Writes the objects out to the protocol * * @param oprot Output protocol */ public void write(TProtocol oprot) throws TException; public int compareTo(Object other); } thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/0000777000000000000000000000000014303740367023141 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/FieldMetaData.java0000644000000000000000000001053514303740367026430 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.TBase; import java.util.Hashtable; /** * This class is used to store meta data about thrift fields. Every field in a * a struct should have a corresponding instance of this class describing it. * * The meta data is registered by ALL Thrift struct classes via a static {...} * initializer block in the generated Thrift code. * * Since different threads could be initializing different Thrift classes, calls * to the public static methods of this class could be racy. * * All methods of this class should be made thread safe. */ public class FieldMetaData { public final String fieldName; public final byte requirementType; public final FieldValueMetaData valueMetaData; private static final Hashtable structMap; static { structMap = new Hashtable(); } public FieldMetaData(String name, byte req, FieldValueMetaData vMetaData){ this.fieldName = name; this.requirementType = req; this.valueMetaData = vMetaData; } public static void addStructMetaDataMap(Class sClass, Hashtable map){ synchronized (structMap) { structMap.put(sClass, map); } } /** * Returns a map with metadata (i.e. instances of FieldMetaData) that * describe the fields of the given class. * * @param sClass The TBase class for which the metadata map is requested. It is not * guaranteed that sClass will have been statically initialized before * this method is called. A racy call to * {@link FieldMetaData#addStructMetaDataMap(Class, Hashtable)} from a different * thread during static initialization of the Thrift class is possible. */ public static Hashtable getStructMetaDataMap(Class sClass) { // Note: Do not use synchronized on this method declaration - it leads to a deadlock. // Similarly, do not trigger sClass.newInstance() while holding a lock on structMap, // it will lead to the same deadlock. // See: https://issues.apache.org/jira/browse/THRIFT-5430 for details. boolean isThriftStructStaticallyInitialized = false; synchronized (structMap) { isThriftStructStaticallyInitialized = structMap.containsKey(sClass); } if (!isThriftStructStaticallyInitialized){ // Load class if it hasn't been loaded try{ sClass.newInstance(); } catch (InstantiationException e){ throw new RuntimeException("InstantiationException for TBase class: " + sClass.getName() + ", message: " + e.getMessage()); } catch (IllegalAccessException e){ throw new RuntimeException("IllegalAccessException for TBase class: " + sClass.getName() + ", message: " + e.getMessage()); } } synchronized (structMap) { return (Hashtable) structMap.get(sClass); } } } thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/SetMetaData.java0000644000000000000000000000352514303740367026141 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; public class SetMetaData extends FieldValueMetaData { public final FieldValueMetaData elemMetaData; public SetMetaData(byte type, FieldValueMetaData eMetaData){ super(type); this.elemMetaData = eMetaData; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/StructMetaData.java0000644000000000000000000000362214303740367026670 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.TBase; import org.apache.thrift.meta_data.FieldValueMetaData; public class StructMetaData extends FieldValueMetaData { public final Class structClass; public StructMetaData(byte type, Class sClass){ super(type); this.structClass = sClass; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/ListMetaData.java0000644000000000000000000000361714303740367026323 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.meta_data.FieldValueMetaData; public class ListMetaData extends FieldValueMetaData { public final FieldValueMetaData elemMetaData; public ListMetaData(byte type, FieldValueMetaData eMetaData){ super(type); this.elemMetaData = eMetaData; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/FieldValueMetaData.java0000644000000000000000000000410414303740367027420 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.protocol.TType; /** * FieldValueMetaData and collection of subclasses to store metadata about * the value(s) of a field */ public class FieldValueMetaData { public final byte type; public FieldValueMetaData(byte type){ this.type = type; } public boolean isStruct() { return type == TType.STRUCT; } public boolean isContainer() { return type == TType.LIST || type == TType.MAP || type == TType.SET; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/meta_data/MapMetaData.java0000644000000000000000000000377614303740367026133 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.meta_data.FieldValueMetaData; public class MapMetaData extends FieldValueMetaData { public final FieldValueMetaData keyMetaData; public final FieldValueMetaData valueMetaData; public MapMetaData(byte type, FieldValueMetaData kMetaData, FieldValueMetaData vMetaData){ super(type); this.keyMetaData = kMetaData; this.valueMetaData = vMetaData; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TApplicationException.java0000644000000000000000000000707614303740367026341 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TField; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolUtil; import org.apache.thrift.protocol.TStruct; import org.apache.thrift.protocol.TType; /** * Application level exception * */ public class TApplicationException extends TException { private static final long serialVersionUID = 1L; public static final int UNKNOWN = 0; public static final int UNKNOWN_METHOD = 1; public static final int INVALID_MESSAGE_TYPE = 2; public static final int WRONG_METHOD_NAME = 3; public static final int BAD_SEQUENCE_ID = 4; public static final int MISSING_RESULT = 5; public static final int INTERNAL_ERROR = 6; public static final int PROTOCOL_ERROR = 7; public static final int INVALID_TRANSFORM = 8; public static final int INVALID_PROTOCOL = 9; public static final int UNSUPPORTED_CLIENT_TYPE = 10; protected int type_ = UNKNOWN; public TApplicationException() { super(); } public TApplicationException(int type) { super(); type_ = type; } public TApplicationException(int type, String message) { super(message); type_ = type; } public TApplicationException(String message) { super(message); } public int getType() { return type_; } public static TApplicationException read(TProtocol iprot) throws TException { TField field; iprot.readStructBegin(); String message = null; int type = UNKNOWN; while (true) { field = iprot.readFieldBegin(); if (field.type == TType.STOP) { break; } switch (field.id) { case 1: if (field.type == TType.STRING) { message = iprot.readString(); } else { TProtocolUtil.skip(iprot, field.type); } break; case 2: if (field.type == TType.I32) { type = iprot.readI32(); } else { TProtocolUtil.skip(iprot, field.type); } break; default: TProtocolUtil.skip(iprot, field.type); break; } iprot.readFieldEnd(); } iprot.readStructEnd(); return new TApplicationException(type, message); } public void write(TProtocol oprot) throws TException { TStruct struct = new TStruct("TApplicationException"); TField field = new TField(); oprot.writeStructBegin(struct); if (getMessage() != null) { field.name = "message"; field.type = TType.STRING; field.id = 1; oprot.writeFieldBegin(field); oprot.writeString(getMessage()); oprot.writeFieldEnd(); } field.name = "type"; field.type = TType.I32; field.id = 2; oprot.writeFieldBegin(field); oprot.writeI32(type_); oprot.writeFieldEnd(); oprot.writeFieldStop(); oprot.writeStructEnd(); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/0000777000000000000000000000000014303740367023256 5ustar00rootroot00000000000000thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/TIOStreamTransport.java0000644000000000000000000001014314303740367027640 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * This is the most commonly used base transport. It takes an InputStream * and an OutputStream and uses those to perform all transport operations. * This allows for compatibility with all the nice constructs Java already * has to provide a variety of types of streams. * */ public class TIOStreamTransport extends TTransport { /** Underlying inputStream */ protected InputStream inputStream_ = null; /** Underlying outputStream */ protected OutputStream outputStream_ = null; /** * Subclasses can invoke the default constructor and then assign the input * streams in the open method. */ protected TIOStreamTransport() {} /** * Input stream constructor. * * @param is Input stream to read from */ public TIOStreamTransport(InputStream is) { inputStream_ = is; } /** * Output stream constructor. * * @param os Output stream to read from */ public TIOStreamTransport(OutputStream os) { outputStream_ = os; } /** * Two-way stream constructor. * * @param is Input stream to read from * @param os Output stream to read from */ public TIOStreamTransport(InputStream is, OutputStream os) { inputStream_ = is; outputStream_ = os; } /** * The streams must already be open at construction time, so this should * always return true. * * @return true */ public boolean isOpen() { return true; } /** * The streams must already be open. This method does nothing. */ public void open() throws TTransportException {} /** * Closes both the input and output streams. */ public void close() { if (inputStream_ != null) { try { inputStream_.close(); } catch (IOException iox) { } inputStream_ = null; } if (outputStream_ != null) { try { outputStream_.close(); } catch (IOException iox) { } outputStream_ = null; } } /** * Reads from the underlying input stream if not null. */ public int read(byte[] buf, int off, int len) throws TTransportException { if (inputStream_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "Cannot read from null inputStream"); } try { return inputStream_.read(buf, off, len); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } /** * Writes to the underlying output stream if not null. */ public void write(byte[] buf, int off, int len) throws TTransportException { if (outputStream_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "Cannot write to null outputStream"); } try { outputStream_.write(buf, off, len); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } /** * Flushes the underlying output stream if not null. */ public void flush() throws TTransportException { if (outputStream_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "Cannot flush null outputStream"); } try { outputStream_.flush(); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/TTransportException.java0000644000000000000000000000372614303740367030124 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TException; /** * Transport exceptions. * */ public class TTransportException extends TException { private static final long serialVersionUID = 1L; public static final int UNKNOWN = 0; public static final int NOT_OPEN = 1; public static final int ALREADY_OPEN = 2; public static final int TIMED_OUT = 3; public static final int END_OF_FILE = 4; protected int type_ = UNKNOWN; public TTransportException() { super(); } public TTransportException(int type) { super(); type_ = type; } public TTransportException(int type, String message) { super(message); type_ = type; } public TTransportException(String message) { super(message); } public TTransportException(int type, Throwable cause) { super(cause); type_ = type; } public TTransportException(Throwable cause) { super(cause); } public TTransportException(String message, Throwable cause) { super(message, cause); } public TTransportException(int type, String message, Throwable cause) { super(message, cause); type_ = type; } public int getType() { return type_; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/THttpClient.java0000644000000000000000000001110314303740367026313 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Hashtable; import javax.microedition.io.Connector; import javax.microedition.io.HttpConnection; /** * HTTP implementation of the TTransport interface. Used for working with a * Thrift web services implementation. * */ public class THttpClient extends TTransport { private String url_ = null; private final ByteArrayOutputStream requestBuffer_ = new ByteArrayOutputStream(); private InputStream inputStream_ = null; private HttpConnection connection = null; private int connectTimeout_ = 0; private int readTimeout_ = 0; private Hashtable customHeaders_ = null; public THttpClient(String url) throws TTransportException { url_ = url; } public void setConnectTimeout(int timeout) { connectTimeout_ = timeout; } public void setReadTimeout(int timeout) { readTimeout_ = timeout; } public void setCustomHeaders(Hashtable headers) { customHeaders_ = headers; } public void setCustomHeader(String key, String value) { if (customHeaders_ == null) { customHeaders_ = new Hashtable(); } customHeaders_.put(key, value); } public void open() {} public void close() { if (null != inputStream_) { try { inputStream_.close(); } catch (IOException ioe) { } inputStream_ = null; } if (connection != null) { try { connection.close(); } catch (IOException ioe) { } connection = null; } } public boolean isOpen() { return true; } public int read(byte[] buf, int off, int len) throws TTransportException { if (inputStream_ == null) { throw new TTransportException("Response buffer is empty, no request."); } try { int ret = inputStream_.read(buf, off, len); if (ret == -1) { throw new TTransportException("No more data available."); } return ret; } catch (IOException iox) { throw new TTransportException(iox); } } public void write(byte[] buf, int off, int len) { requestBuffer_.write(buf, off, len); } public void flush() throws TTransportException { // Extract request and reset buffer byte[] data = requestBuffer_.toByteArray(); requestBuffer_.reset(); try { // Create connection object connection = (HttpConnection)Connector.open(url_); // Make the request connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/x-thrift"); connection.setRequestProperty("Accept", "application/x-thrift"); connection.setRequestProperty("User-Agent", "JavaME/THttpClient"); connection.setRequestProperty("Connection", "Keep-Alive"); connection.setRequestProperty("Keep-Alive", "5000"); connection.setRequestProperty("Http-version", "HTTP/1.1"); connection.setRequestProperty("Cache-Control", "no-transform"); if (customHeaders_ != null) { for (Enumeration e = customHeaders_.keys() ; e.hasMoreElements() ;) { String key = (String)e.nextElement(); String value = (String)customHeaders_.get(key); connection.setRequestProperty(key, value); } } OutputStream os = connection.openOutputStream(); os.write(data); os.close(); int responseCode = connection.getResponseCode(); if (responseCode != HttpConnection.HTTP_OK) { throw new TTransportException("HTTP Response code: " + responseCode); } // Read the responses inputStream_ = connection.openInputStream(); } catch (IOException iox) { System.out.println(iox.toString()); throw new TTransportException(iox); } } } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/TTransport.java0000644000000000000000000000703514303740367026242 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; /** * Generic class that encapsulates the I/O layer. This is basically a thin * wrapper around the combined functionality of Java input/output streams. * */ public abstract class TTransport { /** * Queries whether the transport is open. * * @return True if the transport is open. */ public abstract boolean isOpen(); /** * Is there more data to be read? * * @return True if the remote side is still alive and feeding us */ public boolean peek() { return isOpen(); } /** * Opens the transport for reading/writing. * * @throws TTransportException if the transport could not be opened */ public abstract void open() throws TTransportException; /** * Closes the transport. */ public abstract void close(); /** * Reads up to len bytes into buffer buf, starting att offset off. * * @param buf Array to read into * @param off Index to start reading at * @param len Maximum number of bytes to read * @return The number of bytes actually read * @throws TTransportException if there was an error reading data */ public abstract int read(byte[] buf, int off, int len) throws TTransportException; /** * Guarantees that all of len bytes are actually read off the transport. * * @param buf Array to read into * @param off Index to start reading at * @param len Maximum number of bytes to read * @return The number of bytes actually read, which must be equal to len * @throws TTransportException if there was an error reading data */ public int readAll(byte[] buf, int off, int len) throws TTransportException { int got = 0; int ret = 0; while (got < len) { ret = read(buf, off+got, len-got); if (ret <= 0) { throw new TTransportException("Cannot read. Remote side has closed. Tried to read " + len + " bytes, but only got " + got + " bytes."); } got += ret; } return got; } /** * Writes the buffer to the output * * @param buf The output data buffer * @throws TTransportException if an error occurs writing data */ public void write(byte[] buf) throws TTransportException { write(buf, 0, buf.length); } /** * Writes up to len bytes from the buffer. * * @param buf The output data buffer * @param off The offset to start writing from * @param len The number of bytes to write * @throws TTransportException if there was an error writing data */ public abstract void write(byte[] buf, int off, int len) throws TTransportException; /** * Flush any pending data out of a transport buffer. * * @throws TTransportException if there was an error writing out data. */ public void flush() throws TTransportException {} } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/TMemoryBuffer.java0000644000000000000000000000520014303740367026640 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TByteArrayOutputStream; import java.io.UnsupportedEncodingException; /** * Memory buffer-based implementation of the TTransport interface. */ public class TMemoryBuffer extends TTransport { /** * Create a TMemoryBuffer with an initial buffer size of size. The * internal buffer will grow as necessary to accommodate the size of the data * being written to it. */ public TMemoryBuffer(int size) { arr_ = new TByteArrayOutputStream(size); } public boolean isOpen() { return true; } public void open() { /* Do nothing */ } public void close() { /* Do nothing */ } public int read(byte[] buf, int off, int len) { byte[] src = arr_.get(); int amtToRead = (len > arr_.len() - pos_ ? arr_.len() - pos_ : len); if (amtToRead > 0) { System.arraycopy(src, pos_, buf, off, amtToRead); pos_ += amtToRead; } return amtToRead; } public void write(byte[] buf, int off, int len) { arr_.write(buf, off, len); } /** * Output the contents of the memory buffer as a String, using the supplied * encoding * * @param enc the encoding to use * @return the contents of the memory buffer as a String */ public String toString(String enc) throws UnsupportedEncodingException { return arr_.toString(enc); } public String inspect() { String buf = ""; byte[] bytes = arr_.toByteArray(); for (int i = 0; i < bytes.length; i++) { buf += (pos_ == i ? "==>" : "") + Integer.toHexString(bytes[i] & 0xff) + " "; } return buf; } // The contents of the buffer private TByteArrayOutputStream arr_; // Position to read next byte from private int pos_; public int length() { return arr_.size(); } public byte[] getArray() { return arr_.get(); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/TFramedTransport.java0000644000000000000000000000615714303740367027365 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.ByteArrayInputStream; import org.apache.thrift.TByteArrayOutputStream; /** * Socket implementation of the TTransport interface. To be commented soon! * */ public class TFramedTransport extends TTransport { /** * Underlying transport */ private TTransport transport_ = null; /** * Buffer for output */ private final TByteArrayOutputStream writeBuffer_ = new TByteArrayOutputStream(1024); /** * Buffer for input */ private ByteArrayInputStream readBuffer_ = null; public static class Factory extends TTransportFactory { public Factory() { } public TTransport getTransport(TTransport base) { return new TFramedTransport(base); } } /** * Constructor wraps around another tranpsort */ public TFramedTransport(TTransport transport) { transport_ = transport; } public void open() throws TTransportException { transport_.open(); } public boolean isOpen() { return transport_.isOpen(); } public void close() { transport_.close(); } public int read(byte[] buf, int off, int len) throws TTransportException { if (readBuffer_ != null) { int got = readBuffer_.read(buf, off, len); if (got > 0) { return got; } } // Read another frame of data readFrame(); return readBuffer_.read(buf, off, len); } private void readFrame() throws TTransportException { byte[] i32rd = new byte[4]; transport_.readAll(i32rd, 0, 4); int size = ((i32rd[0] & 0xff) << 24) | ((i32rd[1] & 0xff) << 16) | ((i32rd[2] & 0xff) << 8) | ((i32rd[3] & 0xff)); byte[] buff = new byte[size]; transport_.readAll(buff, 0, size); readBuffer_ = new ByteArrayInputStream(buff); } public void write(byte[] buf, int off, int len) throws TTransportException { writeBuffer_.write(buf, off, len); } public void flush() throws TTransportException { byte[] buf = writeBuffer_.get(); int len = writeBuffer_.len(); writeBuffer_.reset(); byte[] i32out = new byte[4]; i32out[0] = (byte)(0xff & (len >> 24)); i32out[1] = (byte)(0xff & (len >> 16)); i32out[2] = (byte)(0xff & (len >> 8)); i32out[3] = (byte)(0xff & (len)); transport_.write(i32out, 0, 4); transport_.write(buf, 0, len); transport_.flush(); } } thrift-0.19.0/lib/javame/src/org/apache/thrift/transport/TTransportFactory.java0000644000000000000000000000251514303740367027570 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; /** * Factory class used to create wrapped instance of Transports. * This is used primarily in servers, which get Transports from * a ServerTransport and then may want to mutate them (i.e. create * a BufferedTransport from the underlying base transport) * */ public class TTransportFactory { /** * Return a wrapped instance of the base Transport. * * @param in The base transport * @returns Wrapped Transport */ public TTransport getTransport(TTransport trans) { return trans; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TProcessorFactory.java0000644000000000000000000000226014303740367025514 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.transport.TTransport; /** * The default processor factory just returns a singleton * instance. */ public class TProcessorFactory { private final TProcessor processor_; public TProcessorFactory(TProcessor processor) { processor_ = processor; } public TProcessor getProcessor(TTransport trans) { return processor_; } } thrift-0.19.0/lib/javame/src/org/apache/thrift/TFieldRequirementType.java0000644000000000000000000000346714303740367026325 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** * Requirement type constants. * */ public final class TFieldRequirementType { public static final byte REQUIRED = 1; public static final byte OPTIONAL = 2; public static final byte DEFAULT = 3; } thrift-0.19.0/lib/javame/coding_standards.md0000644000000000000000000000010314303740367020741 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/delphi/0000777000000000000000000000000014370300523015113 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/src/0000777000000000000000000000000014454461475015723 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/src/Thrift.Defines.inc0000644000000000000000000000267114303740367021225 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) // Good lists of Delphi version numbers // https://github.com/project-jedi/jedi/blob/master/jedi.inc // http://docwiki.embarcadero.com/RADStudio/Seattle/en/Compiler_Versions // start with most backwards compatible defaults {$DEFINE OLD_UNIT_NAMES} {$DEFINE OLD_SOCKETS} // TODO: add socket support for CompilerVersion >= 28.0 {$UNDEF HAVE_CLASS_CTOR} // enable features as they are available {$IF CompilerVersion >= 21.0} // Delphi 2010 {$DEFINE HAVE_CLASS_CTOR} {$IFEND} {$IF CompilerVersion >= 23.0} // Delphi XE2 {$UNDEF OLD_UNIT_NAMES} {$IFEND} {$IF CompilerVersion >= 28.0} // Delphi XE7 {$UNDEF OLD_SOCKETS} {$IFEND} // EOF thrift-0.19.0/lib/delphi/src/Thrift.Collections.pas0000644000000000000000000004776514452237057022157 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Collections; interface uses SysUtils, Generics.Collections, Generics.Defaults, Thrift.Utils; type {$IF CompilerVersion < 21.0} TArray = array of T; {$IFEND} IThriftContainer = interface( ISupportsToString) ['{E05C0F9D-A4F5-491D-AADA-C926B4BDB6E4}'] end; IThriftDictionary = interface(IThriftContainer) ['{25EDD506-F9D1-4008-A40F-5940364B7E46}'] function GetEnumerator: TEnumerator>; function GetKeys: TDictionary.TKeyCollection; function GetValues: TDictionary.TValueCollection; function GetItem(const Key: TKey): TValue; procedure SetItem(const Key: TKey; const Value: TValue); function GetCount: Integer; procedure Add(const Key: TKey; const Value: TValue); procedure Remove(const Key: TKey); {$IF CompilerVersion >= 21.0} function ExtractPair(const Key: TKey): TPair; {$IFEND} procedure Clear; procedure TrimExcess; function TryGetValue(const Key: TKey; out Value: TValue): Boolean; procedure AddOrSetValue(const Key: TKey; const Value: TValue); function ContainsKey(const Key: TKey): Boolean; function ContainsValue(const Value: TValue): Boolean; function ToArray: TArray>; property Items[const Key: TKey]: TValue read GetItem write SetItem; default; property Count: Integer read GetCount; property Keys: TDictionary.TKeyCollection read GetKeys; property Values: TDictionary.TValueCollection read GetValues; end; TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictionary, IThriftContainer, ISupportsToString) strict private FDictionary : TDictionary; strict protected function GetEnumerator: TEnumerator>; function GetKeys: TDictionary.TKeyCollection; function GetValues: TDictionary.TValueCollection; function GetItem(const Key: TKey): TValue; procedure SetItem(const Key: TKey; const Value: TValue); function GetCount: Integer; procedure Add(const Key: TKey; const Value: TValue); procedure Remove(const Key: TKey); {$IF CompilerVersion >= 21.0} function ExtractPair(const Key: TKey): TPair; {$IFEND} procedure Clear; procedure TrimExcess; function TryGetValue(const Key: TKey; out Value: TValue): Boolean; procedure AddOrSetValue(const Key: TKey; const Value: TValue); function ContainsKey(const Key: TKey): Boolean; function ContainsValue(const Value: TValue): Boolean; function ToArray: TArray>; property Items[const Key: TKey]: TValue read GetItem write SetItem; default; property Count: Integer read GetCount; property Keys: TDictionary.TKeyCollection read GetKeys; property Values: TDictionary.TValueCollection read GetValues; public constructor Create( const aCapacity: Integer = 0); overload; constructor Create( const aCapacity: Integer; const aComparer : IEqualityComparer); overload; destructor Destroy; override; function ToString : string; override; end; IThriftList = interface(IThriftContainer) ['{29BEEE31-9CB4-401B-AA04-5148A75F473B}'] function GetEnumerator: TEnumerator; function GetCapacity: Integer; procedure SetCapacity(Value: Integer); function GetCount: Integer; procedure SetCount(Value: Integer); function GetItem(Index: Integer): T; procedure SetItem(Index: Integer; const Value: T); function Add(const Value: T): Integer; procedure AddRange(const Values: array of T); overload; procedure AddRange(const Collection: IEnumerable); overload; procedure AddRange(Collection: TEnumerable); overload; procedure Insert(Index: Integer; const Value: T); procedure InsertRange(Index: Integer; const Values: array of T); overload; procedure InsertRange(Index: Integer; const Collection: IEnumerable); overload; procedure InsertRange(Index: Integer; const Collection: TEnumerable); overload; function Remove(const Value: T): Integer; procedure Delete(Index: Integer); procedure DeleteRange(AIndex, ACount: Integer); function Extract(const Value: T): T; {$IF CompilerVersion >= 21.0} procedure Exchange(Index1, Index2: Integer); procedure Move(CurIndex, NewIndex: Integer); function First: T; function Last: T; {$IFEND} procedure Clear; function Contains(const Value: T): Boolean; function IndexOf(const Value: T): Integer; function LastIndexOf(const Value: T): Integer; procedure Reverse; procedure Sort; overload; procedure Sort(const AComparer: IComparer); overload; function BinarySearch(const Item: T; out Index: Integer): Boolean; overload; function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer): Boolean; overload; procedure TrimExcess; function ToArray: TArray; property Capacity: Integer read GetCapacity write SetCapacity; property Count: Integer read GetCount write SetCount; property Items[Index: Integer]: T read GetItem write SetItem; default; end; TThriftListImpl = class( TInterfacedObject, IThriftList, IThriftContainer, ISupportsToString) strict private FList : TList; strict protected function GetEnumerator: TEnumerator; function GetCapacity: Integer; procedure SetCapacity(Value: Integer); function GetCount: Integer; procedure SetCount(Value: Integer); function GetItem(Index: Integer): T; procedure SetItem(Index: Integer; const Value: T); function Add(const Value: T): Integer; procedure AddRange(const Values: array of T); overload; procedure AddRange(const Collection: IEnumerable); overload; procedure AddRange(Collection: TEnumerable); overload; procedure Insert(Index: Integer; const Value: T); procedure InsertRange(Index: Integer; const Values: array of T); overload; procedure InsertRange(Index: Integer; const Collection: IEnumerable); overload; procedure InsertRange(Index: Integer; const Collection: TEnumerable); overload; function Remove(const Value: T): Integer; procedure Delete(Index: Integer); procedure DeleteRange(AIndex, ACount: Integer); function Extract(const Value: T): T; {$IF CompilerVersion >= 21.0} procedure Exchange(Index1, Index2: Integer); procedure Move(CurIndex, NewIndex: Integer); function First: T; function Last: T; {$IFEND} procedure Clear; function Contains(const Value: T): Boolean; function IndexOf(const Value: T): Integer; function LastIndexOf(const Value: T): Integer; procedure Reverse; procedure Sort; overload; procedure Sort(const AComparer: IComparer); overload; function BinarySearch(const Item: T; out Index: Integer): Boolean; overload; function BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer): Boolean; overload; procedure TrimExcess; function ToArray: TArray; property Capacity: Integer read GetCapacity write SetCapacity; property Count: Integer read GetCount write SetCount; property Items[Index: Integer]: T read GetItem write SetItem; default; public constructor Create( const aCapacity: Integer = 0); destructor Destroy; override; function ToString : string; override; end; IThriftHashSet = interface(IThriftContainer) ['{0923A3B5-D4D4-48A8-91AD-40238E2EAD66}'] function GetEnumerator: TEnumerator; function GetIsReadOnly: Boolean; function GetCount: Integer; property Count: Integer read GetCount; property IsReadOnly: Boolean read GetIsReadOnly; procedure Add( const item: TValue); procedure Clear; function Contains( const item: TValue): Boolean; procedure CopyTo(var A: TArray; arrayIndex: Integer); function Remove( const item: TValue ): Boolean; end; // compatibility IHashSet = interface( IThriftHashSet) ['{C3CF557F-21D9-4524-B899-D3145B0389BB}'] end deprecated 'use IThriftHashSet'; {$WARN SYMBOL_DEPRECATED OFF} TThriftHashSetImpl = class( TInterfacedObject, IHashSet, IThriftHashSet, IThriftContainer, ISupportsToString) {$WARN SYMBOL_DEPRECATED DEFAULT} strict private FDictionary : IThriftDictionary; FIsReadOnly: Boolean; strict protected function GetEnumerator: TEnumerator; function GetIsReadOnly: Boolean; function GetCount: Integer; property Count: Integer read GetCount; property IsReadOnly: Boolean read FIsReadOnly; procedure Add( const item: TValue); procedure Clear; function Contains( const item: TValue): Boolean; procedure CopyTo(var A: TArray; arrayIndex: Integer); function Remove( const item: TValue ): Boolean; public constructor Create( const aCapacity: Integer = 0); overload; constructor Create( const aCapacity: Integer; const aComparer : IEqualityComparer); overload; function ToString : string; override; end; // compatibility THashSetImpl = class( TThriftHashSetImpl) end deprecated 'use TThriftHashSetImpl'; implementation { TThriftHashSetImpl. } procedure TThriftHashSetImpl.Add( const item: TValue); begin if not FDictionary.ContainsKey(item) then begin FDictionary.Add( item, 0); end; end; procedure TThriftHashSetImpl.Clear; begin FDictionary.Clear; end; function TThriftHashSetImpl.Contains( const item: TValue): Boolean; begin Result := FDictionary.ContainsKey(item); end; procedure TThriftHashSetImpl.CopyTo(var A: TArray; arrayIndex: Integer); var i : Integer; Enumlator : TEnumerator; begin Enumlator := GetEnumerator; while Enumlator.MoveNext do begin A[arrayIndex] := Enumlator.Current; Inc(arrayIndex); end; end; constructor TThriftHashSetImpl.Create( const aCapacity: Integer); begin inherited Create; FDictionary := TThriftDictionaryImpl.Create( aCapacity); end; constructor TThriftHashSetImpl.Create( const aCapacity: Integer; const aComparer : IEqualityComparer); begin inherited Create; FDictionary := TThriftDictionaryImpl.Create( aCapacity, aComparer); end; function TThriftHashSetImpl.GetCount: Integer; begin Result := FDictionary.Count; end; function TThriftHashSetImpl.GetEnumerator: TEnumerator; begin Result := FDictionary.Keys.GetEnumerator; end; function TThriftHashSetImpl.GetIsReadOnly: Boolean; begin Result := FIsReadOnly; end; function TThriftHashSetImpl.Remove( const item: TValue): Boolean; begin Result := False; if FDictionary.ContainsKey( item ) then begin FDictionary.Remove( item ); Result := not FDictionary.ContainsKey( item ); end; end; function TThriftHashSetImpl.ToString : string; var elm : TValue; sb : TThriftStringBuilder; first : Boolean; begin sb := TThriftStringBuilder.Create('{'); try first := TRUE; for elm in FDictionary.Keys do begin if first then first := FALSE else sb.Append(', '); sb.Append( StringUtils.ToString(elm)); end; sb.Append('}'); Result := sb.ToString; finally sb.Free; end; end; { TThriftDictionaryImpl } procedure TThriftDictionaryImpl.Add(const Key: TKey; const Value: TValue); begin FDictionary.Add( Key, Value); end; procedure TThriftDictionaryImpl.AddOrSetValue(const Key: TKey; const Value: TValue); begin FDictionary.AddOrSetValue( Key, Value); end; procedure TThriftDictionaryImpl.Clear; begin FDictionary.Clear; end; function TThriftDictionaryImpl.ContainsKey( const Key: TKey): Boolean; begin Result := FDictionary.ContainsKey( Key ); end; function TThriftDictionaryImpl.ContainsValue( const Value: TValue): Boolean; begin Result := FDictionary.ContainsValue( Value ); end; constructor TThriftDictionaryImpl.Create(const aCapacity: Integer); begin inherited Create; FDictionary := TDictionary.Create( aCapacity); end; constructor TThriftDictionaryImpl.Create(const aCapacity: Integer; const aComparer : IEqualityComparer); begin inherited Create; FDictionary := TDictionary.Create( aCapacity, aComparer); end; destructor TThriftDictionaryImpl.Destroy; begin FDictionary.Free; inherited; end; {$IF CompilerVersion >= 21.0} function TThriftDictionaryImpl.ExtractPair( const Key: TKey): TPair; begin Result := FDictionary.ExtractPair( Key); end; {$IFEND} function TThriftDictionaryImpl.GetCount: Integer; begin Result := FDictionary.Count; end; function TThriftDictionaryImpl.GetEnumerator: TEnumerator>; begin Result := FDictionary.GetEnumerator; end; function TThriftDictionaryImpl.GetItem(const Key: TKey): TValue; begin Result := FDictionary.Items[Key]; end; function TThriftDictionaryImpl.GetKeys: TDictionary.TKeyCollection; begin Result := FDictionary.Keys; end; function TThriftDictionaryImpl.GetValues: TDictionary.TValueCollection; begin Result := FDictionary.Values; end; procedure TThriftDictionaryImpl.Remove(const Key: TKey); begin FDictionary.Remove( Key ); end; procedure TThriftDictionaryImpl.SetItem(const Key: TKey; const Value: TValue); begin FDictionary.AddOrSetValue( Key, Value); end; function TThriftDictionaryImpl.ToArray: TArray>; {$IF CompilerVersion < 22.0} var x : TPair; i : Integer; {$IFEND} begin {$IF CompilerVersion < 22.0} SetLength(Result, Count); i := 0; for x in FDictionaly do begin Result[i] := x; Inc( i ); end; {$ELSE} Result := FDictionary.ToArray; {$IFEND} end; function TThriftDictionaryImpl.ToString : string; var pair : TPair; sb : TThriftStringBuilder; first : Boolean; begin sb := TThriftStringBuilder.Create('{'); try first := TRUE; for pair in FDictionary do begin if first then first := FALSE else sb.Append(', '); sb.Append( '('); sb.Append( StringUtils.ToString(pair.Key)); sb.Append(' => '); sb.Append( StringUtils.ToString(pair.Value)); sb.Append(')'); end; sb.Append('}'); Result := sb.ToString; finally sb.Free; end; end; procedure TThriftDictionaryImpl.TrimExcess; begin FDictionary.TrimExcess; end; function TThriftDictionaryImpl.TryGetValue(const Key: TKey; out Value: TValue): Boolean; begin Result := FDictionary.TryGetValue( Key, Value); end; { TThriftListImpl } function TThriftListImpl.Add(const Value: T): Integer; begin Result := FList.Add( Value ); end; procedure TThriftListImpl.AddRange(Collection: TEnumerable); begin FList.AddRange( Collection ); end; procedure TThriftListImpl.AddRange(const Collection: IEnumerable); begin FList.AddRange( Collection ); end; procedure TThriftListImpl.AddRange(const Values: array of T); begin FList.AddRange( Values ); end; function TThriftListImpl.BinarySearch(const Item: T; out Index: Integer): Boolean; begin Result := FList.BinarySearch( Item, Index); end; function TThriftListImpl.BinarySearch(const Item: T; out Index: Integer; const AComparer: IComparer): Boolean; begin Result := FList.BinarySearch( Item, Index, AComparer); end; procedure TThriftListImpl.Clear; begin FList.Clear; end; function TThriftListImpl.Contains(const Value: T): Boolean; begin Result := FList.Contains( Value ); end; constructor TThriftListImpl.Create( const aCapacity: Integer); begin inherited Create; FList := TList.Create; if aCapacity > 0 then FList.Capacity := aCapacity; end; procedure TThriftListImpl.Delete(Index: Integer); begin FList.Delete( Index ) end; procedure TThriftListImpl.DeleteRange(AIndex, ACount: Integer); begin FList.DeleteRange( AIndex, ACount) end; destructor TThriftListImpl.Destroy; begin FList.Free; inherited; end; {$IF CompilerVersion >= 21.0} procedure TThriftListImpl.Exchange(Index1, Index2: Integer); begin FList.Exchange( Index1, Index2 ) end; {$IFEND} function TThriftListImpl.Extract(const Value: T): T; begin Result := FList.Extract( Value ) end; {$IF CompilerVersion >= 21.0} function TThriftListImpl.First: T; begin Result := FList.First; end; {$IFEND} function TThriftListImpl.GetCapacity: Integer; begin Result := FList.Capacity; end; function TThriftListImpl.GetCount: Integer; begin Result := FList.Count; end; function TThriftListImpl.GetEnumerator: TEnumerator; begin Result := FList.GetEnumerator; end; function TThriftListImpl.GetItem(Index: Integer): T; begin Result := FList[Index]; end; function TThriftListImpl.IndexOf(const Value: T): Integer; begin Result := FList.IndexOf( Value ); end; procedure TThriftListImpl.Insert(Index: Integer; const Value: T); begin FList.Insert( Index, Value); end; procedure TThriftListImpl.InsertRange(Index: Integer; const Collection: TEnumerable); begin FList.InsertRange( Index, Collection ); end; procedure TThriftListImpl.InsertRange(Index: Integer; const Values: array of T); begin FList.InsertRange( Index, Values); end; procedure TThriftListImpl.InsertRange(Index: Integer; const Collection: IEnumerable); begin FList.InsertRange( Index, Collection ); end; {$IF CompilerVersion >= 21.0} function TThriftListImpl.Last: T; begin Result := FList.Last; end; {$IFEND} function TThriftListImpl.LastIndexOf(const Value: T): Integer; begin Result := FList.LastIndexOf( Value ); end; {$IF CompilerVersion >= 21.0} procedure TThriftListImpl.Move(CurIndex, NewIndex: Integer); begin FList.Move( CurIndex, NewIndex); end; {$IFEND} function TThriftListImpl.Remove(const Value: T): Integer; begin Result := FList.Remove( Value ); end; procedure TThriftListImpl.Reverse; begin FList.Reverse; end; procedure TThriftListImpl.SetCapacity(Value: Integer); begin FList.Capacity := Value; end; procedure TThriftListImpl.SetCount(Value: Integer); begin FList.Count := Value; end; procedure TThriftListImpl.SetItem(Index: Integer; const Value: T); begin FList[Index] := Value; end; procedure TThriftListImpl.Sort; begin FList.Sort; end; procedure TThriftListImpl.Sort(const AComparer: IComparer); begin FList.Sort(AComparer); end; function TThriftListImpl.ToArray: TArray; {$IF CompilerVersion < 22.0} var x : T; i : Integer; {$IFEND} begin {$IF CompilerVersion < 22.0} SetLength(Result, Count); i := 0; for x in FList do begin Result[i] := x; Inc( i ); end; {$ELSE} Result := FList.ToArray; {$IFEND} end; function TThriftListImpl.ToString : string; var elm : T; sb : TThriftStringBuilder; first : Boolean; begin sb := TThriftStringBuilder.Create('{'); try first := TRUE; for elm in FList do begin if first then first := FALSE else sb.Append(', '); sb.Append( StringUtils.ToString(elm)); end; sb.Append('}'); Result := sb.ToString; finally sb.Free; end; end; procedure TThriftListImpl.TrimExcess; begin FList.TrimExcess; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Protocol.pas0000644000000000000000000012767614370300523021466 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) {$SCOPEDENUMS ON} unit Thrift.Protocol; interface uses Classes, SysUtils, Contnrs, Thrift.Exception, Thrift.Stream, Thrift.Utils, Thrift.Collections, Thrift.Configuration, Thrift.Transport; type TType = ( Stop = 0, Void = 1, Bool_ = 2, Byte_ = 3, Double_ = 4, I16 = 6, I32 = 8, I64 = 10, String_ = 11, Struct = 12, Map = 13, Set_ = 14, List = 15, Uuid = 16 ); TMessageType = ( Call = 1, Reply = 2, Exception = 3, Oneway = 4 ); const VALID_TTYPES = [ TType.Stop, TType.Void, TType.Bool_, TType.Byte_, TType.Double_, TType.I16, TType.I32, TType.I64, TType.String_, TType.Uuid, TType.Struct, TType.Map, TType.Set_, TType.List ]; VALID_MESSAGETYPES = [Low(TMessageType)..High(TMessageType)]; type IProtocol = interface; TThriftMessage = record Name: string; Type_: TMessageType; SeqID: Integer; end; TThriftStruct = record Name: string; end; TThriftField = record Name: string; Type_: TType; Id: SmallInt; end; TThriftList = record ElementType: TType; Count: Integer; end; TThriftMap = record KeyType: TType; ValueType: TType; Count: Integer; end; TThriftSet = record ElementType: TType; Count: Integer; end; IProtocolFactory = interface ['{7CD64A10-4E9F-4E99-93BF-708A31F4A67B}'] function GetProtocol( const trans: ITransport): IProtocol; end; TProtocolException = class abstract( TException) public type TExceptionType = ( UNKNOWN = 0, INVALID_DATA = 1, NEGATIVE_SIZE = 2, SIZE_LIMIT = 3, BAD_VERSION = 4, NOT_IMPLEMENTED = 5, DEPTH_LIMIT = 6 ); strict protected constructor HiddenCreate(const Msg: string); class function GetType: TExceptionType; virtual; abstract; public // purposefully hide inherited constructor class function Create(const Msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; class function Create: TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; class function Create( aType: TExceptionType): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; class function Create( aType: TExceptionType; const msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; property Type_: TExceptionType read GetType; end; // Needed to remove deprecation warning TProtocolExceptionSpecialized = class abstract (TProtocolException) public constructor Create(const Msg: string); end; TProtocolExceptionUnknown = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionInvalidData = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionNegativeSize = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionSizeLimit = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionBadVersion = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionNotImplemented = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionDepthLimit = class (TProtocolExceptionSpecialized) strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolUtil = class public class procedure Skip( prot: IProtocol; type_: TType); end; IProtocolRecursionTracker = interface ['{29CA033F-BB56-49B1-9EE3-31B1E82FC7A5}'] // no members yet end; TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRecursionTracker) strict protected FProtocol : IProtocol; public constructor Create( prot : IProtocol); destructor Destroy; override; end; IThriftBytes = interface; // forward IProtocol = interface ['{6067A28E-15BF-4C9D-9A6F-D991BB3DCB85}'] function GetTransport: ITransport; procedure WriteMessageBegin( const msg: TThriftMessage); procedure WriteMessageEnd; procedure WriteStructBegin( const struc: TThriftStruct); procedure WriteStructEnd; procedure WriteFieldBegin( const field: TThriftField); procedure WriteFieldEnd; procedure WriteFieldStop; procedure WriteMapBegin( const map: TThriftMap); procedure WriteMapEnd; procedure WriteListBegin( const list: TThriftList); procedure WriteListEnd(); procedure WriteSetBegin( const set_: TThriftSet ); procedure WriteSetEnd(); procedure WriteBool( b: Boolean); procedure WriteByte( b: ShortInt); procedure WriteI16( i16: SmallInt); procedure WriteI32( i32: Integer); procedure WriteI64( const i64: Int64); procedure WriteDouble( const d: Double); procedure WriteString( const s: string ); procedure WriteAnsiString( const s: AnsiString); procedure WriteBinary( const b: TBytes); overload; procedure WriteBinary( const b: IThriftBytes); overload; procedure WriteUuid( const uuid: TGuid); function ReadMessageBegin: TThriftMessage; procedure ReadMessageEnd(); function ReadStructBegin: TThriftStruct; procedure ReadStructEnd; function ReadFieldBegin: TThriftField; procedure ReadFieldEnd(); function ReadMapBegin: TThriftMap; procedure ReadMapEnd(); function ReadListBegin: TThriftList; procedure ReadListEnd(); function ReadSetBegin: TThriftSet; procedure ReadSetEnd(); function ReadBool: Boolean; function ReadByte: ShortInt; function ReadI16: SmallInt; function ReadI32: Integer; function ReadI64: Int64; function ReadDouble:Double; function ReadBinary: TBytes; // IMPORTANT: this is NOT safe across module boundaries function ReadBinaryCOM : IThriftBytes; function ReadUuid: TGuid; function ReadString: string; function ReadAnsiString: AnsiString; function NextRecursionLevel : IProtocolRecursionTracker; procedure IncrementRecursionDepth; procedure DecrementRecursionDepth; function GetMinSerializedSize( const aType : TType) : Integer; property Transport: ITransport read GetTransport; function Configuration : IThriftConfiguration; end; TProtocolImplClass = class of TProtocolImpl; TProtocolImpl = class abstract( TInterfacedObject, IProtocol) strict protected FTrans : ITransport; FRecursionLimit : Integer; FRecursionDepth : Integer; function NextRecursionLevel : IProtocolRecursionTracker; procedure IncrementRecursionDepth; procedure DecrementRecursionDepth; function GetMinSerializedSize( const aType : TType) : Integer; virtual; abstract; procedure CheckReadBytesAvailable( const value : TThriftList); overload; inline; procedure CheckReadBytesAvailable( const value : TThriftSet); overload; inline; procedure CheckReadBytesAvailable( const value : TThriftMap); overload; inline; procedure Reset; virtual; function GetTransport: ITransport; function Configuration : IThriftConfiguration; procedure WriteMessageBegin( const msg: TThriftMessage); virtual; abstract; procedure WriteMessageEnd; virtual; abstract; procedure WriteStructBegin( const struc: TThriftStruct); virtual; abstract; procedure WriteStructEnd; virtual; abstract; procedure WriteFieldBegin( const field: TThriftField); virtual; abstract; procedure WriteFieldEnd; virtual; abstract; procedure WriteFieldStop; virtual; abstract; procedure WriteMapBegin( const map: TThriftMap); virtual; abstract; procedure WriteMapEnd; virtual; abstract; procedure WriteListBegin( const list: TThriftList); virtual; abstract; procedure WriteListEnd(); virtual; abstract; procedure WriteSetBegin( const set_: TThriftSet ); virtual; abstract; procedure WriteSetEnd(); virtual; abstract; procedure WriteBool( b: Boolean); virtual; abstract; procedure WriteByte( b: ShortInt); virtual; abstract; procedure WriteI16( i16: SmallInt); virtual; abstract; procedure WriteI32( i32: Integer); virtual; abstract; procedure WriteI64( const i64: Int64); virtual; abstract; procedure WriteDouble( const d: Double); virtual; abstract; procedure WriteString( const s: string ); virtual; procedure WriteAnsiString( const s: AnsiString); virtual; procedure WriteBinary( const b: TBytes); overload; virtual; abstract; procedure WriteUuid( const b: TGuid); virtual; abstract; function ReadMessageBegin: TThriftMessage; virtual; abstract; procedure ReadMessageEnd(); virtual; abstract; function ReadStructBegin: TThriftStruct; virtual; abstract; procedure ReadStructEnd; virtual; abstract; function ReadFieldBegin: TThriftField; virtual; abstract; procedure ReadFieldEnd(); virtual; abstract; function ReadMapBegin: TThriftMap; virtual; abstract; procedure ReadMapEnd(); virtual; abstract; function ReadListBegin: TThriftList; virtual; abstract; procedure ReadListEnd(); virtual; abstract; function ReadSetBegin: TThriftSet; virtual; abstract; procedure ReadSetEnd(); virtual; abstract; function ReadBool: Boolean; virtual; abstract; function ReadByte: ShortInt; virtual; abstract; function ReadI16: SmallInt; virtual; abstract; function ReadI32: Integer; virtual; abstract; function ReadI64: Int64; virtual; abstract; function ReadDouble:Double; virtual; abstract; function ReadBinary: TBytes; virtual; abstract; function ReadUuid: TGuid; virtual; abstract; function ReadString: string; virtual; function ReadAnsiString: AnsiString; virtual; // provide generic implementation for all derived classes procedure WriteBinary( const bytes : IThriftBytes); overload; virtual; function ReadBinaryCOM : IThriftBytes; virtual; property Transport: ITransport read GetTransport; public constructor Create( const aTransport : ITransport); virtual; end; IBase = interface( ISupportsToString) ['{AFF6CECA-5200-4540-950E-9B89E0C1C00C}'] procedure Read( const prot: IProtocol); procedure Write( const prot: IProtocol); end; IThriftBytes = interface( ISupportsToString) ['{CDBEF7E8-BEF2-4A0A-983A-F334E3FF0016}'] function GetCount : Integer; procedure SetCount(const value : Integer); // WARNING: This returns a direct pointer to the underlying data structure function QueryRawDataPtr : Pointer; property Count : Integer read GetCount write SetCount; end; TThriftBytesImpl = class( TInterfacedObject, IThriftBytes, ISupportsToString) strict private FData : TBytes; strict protected function GetCount : Integer; procedure SetCount(const value : Integer); function QueryRawDataPtr : Pointer; public constructor Create; overload; constructor Create( const bytes : TBytes); overload; constructor Create( var bytes : TBytes; const aTakeOwnership : Boolean = FALSE); overload; function ToString : string; override; end; TBinaryProtocolImpl = class( TProtocolImpl ) strict protected const VERSION_MASK : Cardinal = $ffff0000; VERSION_1 : Cardinal = $80010000; strict protected FStrictRead : Boolean; FStrictWrite : Boolean; function GetMinSerializedSize( const aType : TType) : Integer; override; strict private function ReadAll( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer ): Integer; inline; function ReadStringBody( size: Integer): string; public type TFactory = class( TInterfacedObject, IProtocolFactory) strict protected FStrictRead : Boolean; FStrictWrite : Boolean; function GetProtocol( const trans: ITransport): IProtocol; public constructor Create( const aStrictRead : Boolean = FALSE; const aStrictWrite: Boolean = TRUE); reintroduce; end; constructor Create( const trans: ITransport); overload; override; constructor Create( const trans: ITransport; strictRead, strictWrite: Boolean); reintroduce; overload; procedure WriteMessageBegin( const msg: TThriftMessage); override; procedure WriteMessageEnd; override; procedure WriteStructBegin( const struc: TThriftStruct); override; procedure WriteStructEnd; override; procedure WriteFieldBegin( const field: TThriftField); override; procedure WriteFieldEnd; override; procedure WriteFieldStop; override; procedure WriteMapBegin( const map: TThriftMap); override; procedure WriteMapEnd; override; procedure WriteListBegin( const list: TThriftList); override; procedure WriteListEnd(); override; procedure WriteSetBegin( const set_: TThriftSet ); override; procedure WriteSetEnd(); override; procedure WriteBool( b: Boolean); override; procedure WriteByte( b: ShortInt); override; procedure WriteI16( i16: SmallInt); override; procedure WriteI32( i32: Integer); override; procedure WriteI64( const i64: Int64); override; procedure WriteDouble( const d: Double); override; procedure WriteBinary( const b: TBytes); override; procedure WriteUuid( const uuid: TGuid); override; function ReadMessageBegin: TThriftMessage; override; procedure ReadMessageEnd(); override; function ReadStructBegin: TThriftStruct; override; procedure ReadStructEnd; override; function ReadFieldBegin: TThriftField; override; procedure ReadFieldEnd(); override; function ReadMapBegin: TThriftMap; override; procedure ReadMapEnd(); override; function ReadListBegin: TThriftList; override; procedure ReadListEnd(); override; function ReadSetBegin: TThriftSet; override; procedure ReadSetEnd(); override; function ReadBool: Boolean; override; function ReadByte: ShortInt; override; function ReadI16: SmallInt; override; function ReadI32: Integer; override; function ReadI64: Int64; override; function ReadDouble:Double; override; function ReadBinary: TBytes; override; function ReadUuid: TGuid; override; end; { TProtocolDecorator forwards all requests to an enclosed TProtocol instance, providing a way to author concise concrete decorator subclasses. The decorator does not (and should not) modify the behaviour of the enclosed TProtocol See p.175 of Design Patterns (by Gamma et al.) } TProtocolDecorator = class( TProtocolImpl) strict private FWrappedProtocol : IProtocol; strict protected function GetMinSerializedSize( const aType : TType) : Integer; override; public // Encloses the specified protocol. // All operations will be forward to the given protocol. Must be non-null. constructor Create( const aProtocol : IProtocol); reintroduce; procedure WriteMessageBegin( const msg: TThriftMessage); override; procedure WriteMessageEnd; override; procedure WriteStructBegin( const struc: TThriftStruct); override; procedure WriteStructEnd; override; procedure WriteFieldBegin( const field: TThriftField); override; procedure WriteFieldEnd; override; procedure WriteFieldStop; override; procedure WriteMapBegin( const map: TThriftMap); override; procedure WriteMapEnd; override; procedure WriteListBegin( const list: TThriftList); override; procedure WriteListEnd(); override; procedure WriteSetBegin( const set_: TThriftSet ); override; procedure WriteSetEnd(); override; procedure WriteBool( b: Boolean); override; procedure WriteByte( b: ShortInt); override; procedure WriteI16( i16: SmallInt); override; procedure WriteI32( i32: Integer); override; procedure WriteI64( const i64: Int64); override; procedure WriteDouble( const d: Double); override; procedure WriteString( const s: string ); override; procedure WriteAnsiString( const s: AnsiString); override; procedure WriteBinary( const b: TBytes); override; procedure WriteUuid( const uuid: TGuid); override; function ReadMessageBegin: TThriftMessage; override; procedure ReadMessageEnd(); override; function ReadStructBegin: TThriftStruct; override; procedure ReadStructEnd; override; function ReadFieldBegin: TThriftField; override; procedure ReadFieldEnd(); override; function ReadMapBegin: TThriftMap; override; procedure ReadMapEnd(); override; function ReadListBegin: TThriftList; override; procedure ReadListEnd(); override; function ReadSetBegin: TThriftSet; override; procedure ReadSetEnd(); override; function ReadBool: Boolean; override; function ReadByte: ShortInt; override; function ReadI16: SmallInt; override; function ReadI32: Integer; override; function ReadI64: Int64; override; function ReadDouble:Double; override; function ReadBinary: TBytes; override; function ReadUuid: TGuid; override; function ReadString: string; override; function ReadAnsiString: AnsiString; override; end; type IRequestEvents = interface ['{F926A26A-5B00-4560-86FA-2CAE3BA73DAF}'] // Called before reading arguments. procedure PreRead; // Called between reading arguments and calling the handler. procedure PostRead; // Called between calling the handler and writing the response. procedure PreWrite; // Called after writing the response. procedure PostWrite; // Called when an oneway (async) function call completes successfully. procedure OnewayComplete; // Called if the handler throws an undeclared exception. procedure UnhandledError( const e : Exception); // Called when a client has finished request-handling to clean up procedure CleanupContext; end; IProcessorEvents = interface ['{A8661119-657C-447D-93C5-512E36162A45}'] // Called when a client is about to call the processor. procedure Processing( const transport : ITransport); // Called on any service function invocation function CreateRequestContext( const aFunctionName : string) : IRequestEvents; // Called when a client has finished request-handling to clean up procedure CleanupContext; end; IProcessor = interface ['{7BAE92A5-46DA-4F13-B6EA-0EABE233EE5F}'] function Process( const iprot :IProtocol; const oprot: IProtocol; const events : IProcessorEvents = nil): Boolean; end; procedure Init( var rec : TThriftMessage; const AName: string = ''; const AMessageType: TMessageType = Low(TMessageType); const ASeqID: Integer = 0); overload; inline; procedure Init( var rec : TThriftStruct; const AName: string = ''); overload; inline; procedure Init( var rec : TThriftField; const AName: string = ''; const AType: TType = Low(TType); const AID: SmallInt = 0); overload; inline; procedure Init( var rec : TThriftMap; const AKeyType: TType = Low(TType); const AValueType: TType = Low(TType); const ACount: Integer = 0); overload; inline; procedure Init( var rec : TThriftSet; const AElementType: TType = Low(TType); const ACount: Integer = 0); overload; inline; procedure Init( var rec : TThriftList; const AElementType: TType = Low(TType); const ACount: Integer = 0); overload; inline; implementation function ConvertInt64ToDouble( const n: Int64): Double; inline; begin ASSERT( SizeOf(n) = SizeOf(Result)); System.Move( n, Result, SizeOf(Result)); end; function ConvertDoubleToInt64( const d: Double): Int64; inline; begin ASSERT( SizeOf(d) = SizeOf(Result)); System.Move( d, Result, SizeOf(Result)); end; { TProtocolRecursionTrackerImpl } constructor TProtocolRecursionTrackerImpl.Create( prot : IProtocol); begin inherited Create; // storing the pointer *after* the (successful) increment is important here prot.IncrementRecursionDepth; FProtocol := prot; end; destructor TProtocolRecursionTrackerImpl.Destroy; begin try // we have to release the reference iff the pointer has been stored if FProtocol <> nil then begin FProtocol.DecrementRecursionDepth; FProtocol := nil; end; finally inherited Destroy; end; end; { TProtocolImpl } constructor TProtocolImpl.Create( const aTransport : ITransport); begin inherited Create; FTrans := aTransport; FRecursionLimit := aTransport.Configuration.RecursionLimit; FRecursionDepth := 0; end; function TProtocolImpl.NextRecursionLevel : IProtocolRecursionTracker; begin result := TProtocolRecursionTrackerImpl.Create(Self); end; procedure TProtocolImpl.IncrementRecursionDepth; begin if FRecursionDepth < FRecursionLimit then Inc(FRecursionDepth) else raise TProtocolExceptionDepthLimit.Create('Depth limit exceeded'); end; procedure TProtocolImpl.DecrementRecursionDepth; begin Dec(FRecursionDepth) end; function TProtocolImpl.GetTransport: ITransport; begin Result := FTrans; end; function TProtocolImpl.Configuration : IThriftConfiguration; begin Result := FTrans.Configuration; end; procedure TProtocolImpl.Reset; begin FTrans.ResetConsumedMessageSize; end; function TProtocolImpl.ReadAnsiString: AnsiString; var b : TBytes; len : Integer; begin Result := ''; b := ReadBinary; len := Length( b ); if len > 0 then begin SetLength( Result, len); System.Move( b[0], Pointer(Result)^, len ); end; end; function TProtocolImpl.ReadString: string; begin Result := TEncoding.UTF8.GetString( ReadBinary ); end; procedure TProtocolImpl.WriteAnsiString(const s: AnsiString); var b : TBytes; len : Integer; begin len := Length(s); SetLength( b, len); if len > 0 then begin System.Move( Pointer(s)^, b[0], len ); end; WriteBinary( b ); end; procedure TProtocolImpl.WriteString(const s: string); var b : TBytes; begin b := TEncoding.UTF8.GetBytes(s); WriteBinary( b ); end; procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftList); begin FTrans.CheckReadBytesAvailable( value.Count * GetMinSerializedSize(value.ElementType)); end; procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftSet); begin FTrans.CheckReadBytesAvailable( value.Count * GetMinSerializedSize(value.ElementType)); end; procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftMap); var nPairSize : Integer; begin nPairSize := GetMinSerializedSize(value.KeyType) + GetMinSerializedSize(value.ValueType); FTrans.CheckReadBytesAvailable( value.Count * nPairSize); end; procedure TProtocolImpl.WriteBinary( const bytes : IThriftBytes); var tmp : TBytes; begin SetLength( tmp, bytes.Count); if Length(tmp) > 0 then Move( bytes.QueryRawDataPtr^, tmp[0], Length(tmp)); WriteBinary( tmp); end; function TProtocolImpl.ReadBinaryCOM : IThriftBytes; var bytes : TBytes; begin bytes := ReadBinary; result := TThriftBytesImpl.Create(bytes,TRUE); end; { TThriftBytesImpl } constructor TThriftBytesImpl.Create; begin inherited Create; ASSERT( Length(FData) = 0); end; constructor TThriftBytesImpl.Create( const bytes : TBytes); begin FData := bytes; // copies the data end; constructor TThriftBytesImpl.Create( var bytes : TBytes; const aTakeOwnership : Boolean); procedure SwapPointer( var one, two); var pOne : Pointer absolute one; pTwo : Pointer absolute two; pTmp : Pointer; begin pTmp := pOne; pOne := pTwo; pTwo := pTmp; end; begin inherited Create; ASSERT( Length(FData) = 0); if aTakeOwnership then SwapPointer( FData, bytes) else FData := bytes; // copies the data end; function TThriftBytesImpl.ToString : string; var sb : TThriftStringBuilder; begin sb := TThriftStringBuilder.Create(); try sb.Append('Bin: '); sb.Append( FData); result := sb.ToString; finally sb.Free; end; end; function TThriftBytesImpl.GetCount : Integer; begin result := Length(FData); end; procedure TThriftBytesImpl.SetCount(const value : Integer); begin SetLength( FData, value); end; function TThriftBytesImpl.QueryRawDataPtr : Pointer; begin result := FData; end; { TProtocolUtil } class procedure TProtocolUtil.Skip( prot: IProtocol; type_: TType); var field : TThriftField; map : TThriftMap; set_ : TThriftSet; list : TThriftList; i : Integer; tracker : IProtocolRecursionTracker; begin tracker := prot.NextRecursionLevel; case type_ of // simple types TType.Bool_ : prot.ReadBool(); TType.Byte_ : prot.ReadByte(); TType.I16 : prot.ReadI16(); TType.I32 : prot.ReadI32(); TType.I64 : prot.ReadI64(); TType.Double_ : prot.ReadDouble(); TType.String_ : prot.ReadBinary();// Don't try to decode the string, just skip it. TType.Uuid : prot.ReadUuid(); // structured types TType.Struct : begin prot.ReadStructBegin(); while TRUE do begin field := prot.ReadFieldBegin(); if (field.Type_ = TType.Stop) then Break; Skip(prot, field.Type_); prot.ReadFieldEnd(); end; prot.ReadStructEnd(); end; TType.Map : begin map := prot.ReadMapBegin(); for i := 0 to map.Count-1 do begin Skip(prot, map.KeyType); Skip(prot, map.ValueType); end; prot.ReadMapEnd(); end; TType.Set_ : begin set_ := prot.ReadSetBegin(); for i := 0 to set_.Count-1 do Skip( prot, set_.ElementType); prot.ReadSetEnd(); end; TType.List : begin list := prot.ReadListBegin(); for i := 0 to list.Count-1 do Skip( prot, list.ElementType); prot.ReadListEnd(); end; else raise TProtocolExceptionInvalidData.Create('Unexpected type '+IntToStr(Ord(type_))); end; end; { TBinaryProtocolImpl } constructor TBinaryProtocolImpl.Create( const trans: ITransport); begin // call the real CTOR Self.Create( trans, FALSE, TRUE); end; constructor TBinaryProtocolImpl.Create( const trans: ITransport; strictRead, strictWrite: Boolean); begin inherited Create( trans); FStrictRead := strictRead; FStrictWrite := strictWrite; end; function TBinaryProtocolImpl.ReadAll( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer ): Integer; begin Result := FTrans.ReadAll( pBuf, buflen, off, len ); end; function TBinaryProtocolImpl.ReadBinary: TBytes; var size : Integer; buf : TBytes; begin size := ReadI32; FTrans.CheckReadBytesAvailable( size); SetLength( buf, size); FTrans.ReadAll( buf, 0, size); Result := buf; end; function TBinaryProtocolImpl.ReadUuid : TGuid; var network : TGuid; // in network order (Big Endian) begin ASSERT( SizeOf(result) = 16); FTrans.ReadAll( @network, SizeOf(network), 0, SizeOf(network)); result := GuidUtils.SwapByteOrder(network); end; function TBinaryProtocolImpl.ReadBool: Boolean; begin Result := (ReadByte = 1); end; function TBinaryProtocolImpl.ReadByte: ShortInt; begin ReadAll( @result, SizeOf(result), 0, 1); end; function TBinaryProtocolImpl.ReadDouble: Double; begin Result := ConvertInt64ToDouble( ReadI64 ) end; function TBinaryProtocolImpl.ReadFieldBegin: TThriftField; begin Init( result, '', TType( ReadByte), 0); if ( result.Type_ <> TType.Stop ) then begin result.Id := ReadI16; end; end; procedure TBinaryProtocolImpl.ReadFieldEnd; begin end; function TBinaryProtocolImpl.ReadI16: SmallInt; var i16in : packed array[0..1] of Byte; begin ReadAll( @i16in, Sizeof(i16in), 0, 2); Result := SmallInt(((i16in[0] and $FF) shl 8) or (i16in[1] and $FF)); end; function TBinaryProtocolImpl.ReadI32: Integer; var i32in : packed array[0..3] of Byte; begin ReadAll( @i32in, SizeOf(i32in), 0, 4); Result := Integer( ((i32in[0] and $FF) shl 24) or ((i32in[1] and $FF) shl 16) or ((i32in[2] and $FF) shl 8) or (i32in[3] and $FF)); end; function TBinaryProtocolImpl.ReadI64: Int64; var i64in : packed array[0..7] of Byte; begin ReadAll( @i64in, SizeOf(i64in), 0, 8); Result := (Int64( i64in[0] and $FF) shl 56) or (Int64( i64in[1] and $FF) shl 48) or (Int64( i64in[2] and $FF) shl 40) or (Int64( i64in[3] and $FF) shl 32) or (Int64( i64in[4] and $FF) shl 24) or (Int64( i64in[5] and $FF) shl 16) or (Int64( i64in[6] and $FF) shl 8) or (Int64( i64in[7] and $FF)); end; function TBinaryProtocolImpl.ReadListBegin: TThriftList; begin result.ElementType := TType(ReadByte); result.Count := ReadI32; CheckReadBytesAvailable(result); end; procedure TBinaryProtocolImpl.ReadListEnd; begin end; function TBinaryProtocolImpl.ReadMapBegin: TThriftMap; begin result.KeyType := TType(ReadByte); result.ValueType := TType(ReadByte); result.Count := ReadI32; CheckReadBytesAvailable(result); end; procedure TBinaryProtocolImpl.ReadMapEnd; begin end; function TBinaryProtocolImpl.ReadMessageBegin: TThriftMessage; var size : Integer; version : Integer; begin Reset; Init( result); size := ReadI32; if (size < 0) then begin version := size and Integer( VERSION_MASK); if ( version <> Integer( VERSION_1)) then begin raise TProtocolExceptionBadVersion.Create('Bad version in ReadMessageBegin: ' + IntToStr(version) ); end; result.Type_ := TMessageType( size and $000000ff); result.Name := ReadString; result.SeqID := ReadI32; Exit; end; try if FStrictRead then raise TProtocolExceptionBadVersion.Create('Missing version in readMessageBegin, old client?' ); result.Name := ReadStringBody( size ); result.Type_ := TMessageType( ReadByte ); result.SeqID := ReadI32; except if CharUtils.IsHtmlDoctype(size) then raise TProtocolExceptionInvalidData.Create('Remote end sends HTML instead of data') else raise; // something else end; end; procedure TBinaryProtocolImpl.ReadMessageEnd; begin inherited; end; function TBinaryProtocolImpl.ReadSetBegin: TThriftSet; begin result.ElementType := TType(ReadByte); result.Count := ReadI32; CheckReadBytesAvailable(result); end; procedure TBinaryProtocolImpl.ReadSetEnd; begin end; function TBinaryProtocolImpl.ReadStringBody( size: Integer): string; var buf : TBytes; begin FTrans.CheckReadBytesAvailable( size); SetLength( buf, size); FTrans.ReadAll( buf, 0, size ); Result := TEncoding.UTF8.GetString( buf); end; function TBinaryProtocolImpl.ReadStructBegin: TThriftStruct; begin Init( Result); end; procedure TBinaryProtocolImpl.ReadStructEnd; begin inherited; end; procedure TBinaryProtocolImpl.WriteBinary( const b: TBytes); var iLen : Integer; begin iLen := Length(b); WriteI32( iLen); if iLen > 0 then FTrans.Write(b, 0, iLen); end; procedure TBinaryProtocolImpl.WriteUuid( const uuid: TGuid); var network : TGuid; // in network order (Big Endian) begin ASSERT( SizeOf(uuid) = 16); network := GuidUtils.SwapByteOrder(uuid); Transport.Write( @network, 0, SizeOf(network)); end; procedure TBinaryProtocolImpl.WriteBool(b: Boolean); begin if b then begin WriteByte( 1 ); end else begin WriteByte( 0 ); end; end; procedure TBinaryProtocolImpl.WriteByte(b: ShortInt); begin FTrans.Write( @b, 0, 1); end; procedure TBinaryProtocolImpl.WriteDouble( const d: Double); begin WriteI64(ConvertDoubleToInt64(d)); end; procedure TBinaryProtocolImpl.WriteFieldBegin( const field: TThriftField); begin WriteByte(ShortInt(field.Type_)); WriteI16(field.ID); end; procedure TBinaryProtocolImpl.WriteFieldEnd; begin end; procedure TBinaryProtocolImpl.WriteFieldStop; begin WriteByte(ShortInt(TType.Stop)); end; procedure TBinaryProtocolImpl.WriteI16(i16: SmallInt); var i16out : packed array[0..1] of Byte; begin i16out[0] := Byte($FF and (i16 shr 8)); i16out[1] := Byte($FF and i16); FTrans.Write( @i16out, 0, 2); end; procedure TBinaryProtocolImpl.WriteI32(i32: Integer); var i32out : packed array[0..3] of Byte; begin i32out[0] := Byte($FF and (i32 shr 24)); i32out[1] := Byte($FF and (i32 shr 16)); i32out[2] := Byte($FF and (i32 shr 8)); i32out[3] := Byte($FF and i32); FTrans.Write( @i32out, 0, 4); end; procedure TBinaryProtocolImpl.WriteI64( const i64: Int64); var i64out : packed array[0..7] of Byte; begin i64out[0] := Byte($FF and (i64 shr 56)); i64out[1] := Byte($FF and (i64 shr 48)); i64out[2] := Byte($FF and (i64 shr 40)); i64out[3] := Byte($FF and (i64 shr 32)); i64out[4] := Byte($FF and (i64 shr 24)); i64out[5] := Byte($FF and (i64 shr 16)); i64out[6] := Byte($FF and (i64 shr 8)); i64out[7] := Byte($FF and i64); FTrans.Write( @i64out, 0, 8); end; procedure TBinaryProtocolImpl.WriteListBegin( const list: TThriftList); begin WriteByte(ShortInt(list.ElementType)); WriteI32(list.Count); end; procedure TBinaryProtocolImpl.WriteListEnd; begin end; procedure TBinaryProtocolImpl.WriteMapBegin( const map: TThriftMap); begin WriteByte(ShortInt(map.KeyType)); WriteByte(ShortInt(map.ValueType)); WriteI32(map.Count); end; procedure TBinaryProtocolImpl.WriteMapEnd; begin end; procedure TBinaryProtocolImpl.WriteMessageBegin( const msg: TThriftMessage); var version : Cardinal; begin Reset; if FStrictWrite then begin version := VERSION_1 or Cardinal( msg.Type_); WriteI32( Integer( version) ); WriteString( msg.Name); WriteI32( msg.SeqID); end else begin WriteString( msg.Name); WriteByte(ShortInt( msg.Type_)); WriteI32( msg.SeqID); end; end; procedure TBinaryProtocolImpl.WriteMessageEnd; begin end; procedure TBinaryProtocolImpl.WriteSetBegin( const set_: TThriftSet); begin WriteByte(ShortInt(set_.ElementType)); WriteI32(set_.Count); end; procedure TBinaryProtocolImpl.WriteSetEnd; begin end; procedure TBinaryProtocolImpl.WriteStructBegin( const struc: TThriftStruct); begin end; procedure TBinaryProtocolImpl.WriteStructEnd; begin end; function TBinaryProtocolImpl.GetMinSerializedSize( const aType : TType) : Integer; // Return the minimum number of bytes a type will consume on the wire begin case aType of TType.Stop: result := 0; TType.Void: result := 0; TType.Bool_: result := SizeOf(Byte); TType.Byte_: result := SizeOf(Byte); TType.Double_: result := SizeOf(Double); TType.I16: result := SizeOf(Int16); TType.I32: result := SizeOf(Int32); TType.I64: result := SizeOf(Int64); TType.String_: result := SizeOf(Int32); // string length TType.Struct: result := 0; // empty struct TType.Map: result := SizeOf(Int32); // element count TType.Set_: result := SizeOf(Int32); // element count TType.List: result := SizeOf(Int32); // element count TType.Uuid: result := SizeOf(TGuid); else raise TTransportExceptionBadArgs.Create('Unhandled type code'); end; end; { TProtocolException } constructor TProtocolException.HiddenCreate(const Msg: string); begin inherited Create(Msg); end; class function TProtocolException.Create(const Msg: string): TProtocolException; begin Result := TProtocolExceptionUnknown.Create(Msg); end; class function TProtocolException.Create: TProtocolException; begin Result := TProtocolExceptionUnknown.Create(''); end; class function TProtocolException.Create(aType: TExceptionType): TProtocolException; begin {$WARN SYMBOL_DEPRECATED OFF} Result := Create(aType, ''); {$WARN SYMBOL_DEPRECATED DEFAULT} end; class function TProtocolException.Create(aType: TExceptionType; const msg: string): TProtocolException; begin case aType of TExceptionType.INVALID_DATA: Result := TProtocolExceptionInvalidData.Create(msg); TExceptionType.NEGATIVE_SIZE: Result := TProtocolExceptionNegativeSize.Create(msg); TExceptionType.SIZE_LIMIT: Result := TProtocolExceptionSizeLimit.Create(msg); TExceptionType.BAD_VERSION: Result := TProtocolExceptionBadVersion.Create(msg); TExceptionType.NOT_IMPLEMENTED: Result := TProtocolExceptionNotImplemented.Create(msg); TExceptionType.DEPTH_LIMIT: Result := TProtocolExceptionDepthLimit.Create(msg); else ASSERT( TExceptionType.UNKNOWN = aType); Result := TProtocolExceptionUnknown.Create(msg); end; end; { TProtocolExceptionSpecialized } constructor TProtocolExceptionSpecialized.Create(const Msg: string); begin inherited HiddenCreate(Msg); end; { specialized TProtocolExceptions } class function TProtocolExceptionUnknown.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.UNKNOWN; end; class function TProtocolExceptionInvalidData.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.INVALID_DATA; end; class function TProtocolExceptionNegativeSize.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.NEGATIVE_SIZE; end; class function TProtocolExceptionSizeLimit.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.SIZE_LIMIT; end; class function TProtocolExceptionBadVersion.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.BAD_VERSION; end; class function TProtocolExceptionNotImplemented.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.NOT_IMPLEMENTED; end; class function TProtocolExceptionDepthLimit.GetType: TProtocolException.TExceptionType; begin result := TExceptionType.DEPTH_LIMIT; end; { TBinaryProtocolImpl.TFactory } constructor TBinaryProtocolImpl.TFactory.Create( const aStrictRead, aStrictWrite: Boolean); begin inherited Create; FStrictRead := AStrictRead; FStrictWrite := AStrictWrite; end; function TBinaryProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IProtocol; begin Result := TBinaryProtocolImpl.Create( trans, FStrictRead, FStrictWrite); end; { TProtocolDecorator } constructor TProtocolDecorator.Create( const aProtocol : IProtocol); begin ASSERT( aProtocol <> nil); inherited Create( aProtocol.Transport); FWrappedProtocol := aProtocol; end; procedure TProtocolDecorator.WriteMessageBegin( const msg: TThriftMessage); begin FWrappedProtocol.WriteMessageBegin( msg); end; procedure TProtocolDecorator.WriteMessageEnd; begin FWrappedProtocol.WriteMessageEnd; end; procedure TProtocolDecorator.WriteStructBegin( const struc: TThriftStruct); begin FWrappedProtocol.WriteStructBegin( struc); end; procedure TProtocolDecorator.WriteStructEnd; begin FWrappedProtocol.WriteStructEnd; end; procedure TProtocolDecorator.WriteFieldBegin( const field: TThriftField); begin FWrappedProtocol.WriteFieldBegin( field); end; procedure TProtocolDecorator.WriteFieldEnd; begin FWrappedProtocol.WriteFieldEnd; end; procedure TProtocolDecorator.WriteFieldStop; begin FWrappedProtocol.WriteFieldStop; end; procedure TProtocolDecorator.WriteMapBegin( const map: TThriftMap); begin FWrappedProtocol.WriteMapBegin( map); end; procedure TProtocolDecorator.WriteMapEnd; begin FWrappedProtocol.WriteMapEnd; end; procedure TProtocolDecorator.WriteListBegin( const list: TThriftList); begin FWrappedProtocol.WriteListBegin( list); end; procedure TProtocolDecorator.WriteListEnd(); begin FWrappedProtocol.WriteListEnd(); end; procedure TProtocolDecorator.WriteSetBegin( const set_: TThriftSet ); begin FWrappedProtocol.WriteSetBegin( set_); end; procedure TProtocolDecorator.WriteSetEnd(); begin FWrappedProtocol.WriteSetEnd(); end; procedure TProtocolDecorator.WriteBool( b: Boolean); begin FWrappedProtocol.WriteBool( b); end; procedure TProtocolDecorator.WriteByte( b: ShortInt); begin FWrappedProtocol.WriteByte( b); end; procedure TProtocolDecorator.WriteI16( i16: SmallInt); begin FWrappedProtocol.WriteI16( i16); end; procedure TProtocolDecorator.WriteI32( i32: Integer); begin FWrappedProtocol.WriteI32( i32); end; procedure TProtocolDecorator.WriteI64( const i64: Int64); begin FWrappedProtocol.WriteI64( i64); end; procedure TProtocolDecorator.WriteDouble( const d: Double); begin FWrappedProtocol.WriteDouble( d); end; procedure TProtocolDecorator.WriteString( const s: string ); begin FWrappedProtocol.WriteString( s); end; procedure TProtocolDecorator.WriteAnsiString( const s: AnsiString); begin FWrappedProtocol.WriteAnsiString( s); end; procedure TProtocolDecorator.WriteBinary( const b: TBytes); begin FWrappedProtocol.WriteBinary( b); end; procedure TProtocolDecorator.WriteUuid( const uuid: TGuid); begin FWrappedProtocol.WriteUuid( uuid); end; function TProtocolDecorator.ReadMessageBegin: TThriftMessage; begin result := FWrappedProtocol.ReadMessageBegin; end; procedure TProtocolDecorator.ReadMessageEnd(); begin FWrappedProtocol.ReadMessageEnd(); end; function TProtocolDecorator.ReadStructBegin: TThriftStruct; begin result := FWrappedProtocol.ReadStructBegin; end; procedure TProtocolDecorator.ReadStructEnd; begin FWrappedProtocol.ReadStructEnd; end; function TProtocolDecorator.ReadFieldBegin: TThriftField; begin result := FWrappedProtocol.ReadFieldBegin; end; procedure TProtocolDecorator.ReadFieldEnd(); begin FWrappedProtocol.ReadFieldEnd(); end; function TProtocolDecorator.ReadMapBegin: TThriftMap; begin result := FWrappedProtocol.ReadMapBegin; end; procedure TProtocolDecorator.ReadMapEnd(); begin FWrappedProtocol.ReadMapEnd(); end; function TProtocolDecorator.ReadListBegin: TThriftList; begin result := FWrappedProtocol.ReadListBegin; end; procedure TProtocolDecorator.ReadListEnd(); begin FWrappedProtocol.ReadListEnd(); end; function TProtocolDecorator.ReadSetBegin: TThriftSet; begin result := FWrappedProtocol.ReadSetBegin; end; procedure TProtocolDecorator.ReadSetEnd(); begin FWrappedProtocol.ReadSetEnd(); end; function TProtocolDecorator.ReadBool: Boolean; begin result := FWrappedProtocol.ReadBool; end; function TProtocolDecorator.ReadByte: ShortInt; begin result := FWrappedProtocol.ReadByte; end; function TProtocolDecorator.ReadI16: SmallInt; begin result := FWrappedProtocol.ReadI16; end; function TProtocolDecorator.ReadI32: Integer; begin result := FWrappedProtocol.ReadI32; end; function TProtocolDecorator.ReadI64: Int64; begin result := FWrappedProtocol.ReadI64; end; function TProtocolDecorator.ReadDouble:Double; begin result := FWrappedProtocol.ReadDouble; end; function TProtocolDecorator.ReadBinary: TBytes; begin result := FWrappedProtocol.ReadBinary; end; function TProtocolDecorator.ReadUuid: TGuid; begin result := FWrappedProtocol.ReadUuid; end; function TProtocolDecorator.ReadString: string; begin result := FWrappedProtocol.ReadString; end; function TProtocolDecorator.ReadAnsiString: AnsiString; begin result := FWrappedProtocol.ReadAnsiString; end; function TProtocolDecorator.GetMinSerializedSize( const aType : TType) : Integer; begin result := FWrappedProtocol.GetMinSerializedSize(aType); end; { Init helper functions } procedure Init( var rec : TThriftMessage; const AName: string; const AMessageType: TMessageType; const ASeqID: Integer); begin rec.Name := AName; rec.Type_ := AMessageType; rec.SeqID := ASeqID; end; procedure Init( var rec : TThriftStruct; const AName: string = ''); begin rec.Name := AName; end; procedure Init( var rec : TThriftField; const AName: string; const AType: TType; const AID: SmallInt); begin rec.Name := AName; rec.Type_ := AType; rec.Id := AId; end; procedure Init( var rec : TThriftMap; const AKeyType, AValueType: TType; const ACount: Integer); begin rec.ValueType := AValueType; rec.KeyType := AKeyType; rec.Count := ACount; end; procedure Init( var rec : TThriftSet; const AElementType: TType; const ACount: Integer); begin rec.Count := ACount; rec.ElementType := AElementType; end; procedure Init( var rec : TThriftList; const AElementType: TType; const ACount: Integer); begin rec.Count := ACount; rec.ElementType := AElementType; end; end. thrift-0.19.0/lib/delphi/src/Thrift.TypeRegistry.pas0000644000000000000000000000473314303740367022335 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.TypeRegistry; interface uses Generics.Collections, TypInfo, Thrift.Protocol; type TFactoryMethod = function:T; TypeRegistry = class strict private class var FTypeInfoToFactoryLookup : TDictionary; public class constructor Create; class destructor Destroy; class procedure RegisterTypeFactory(const aFactoryMethod: TFactoryMethod); class function Construct: F; class function ConstructFromTypeInfo(const aTypeInfo: PTypeInfo): IBase; end; implementation { TypeRegistration } class constructor TypeRegistry.Create; begin FTypeInfoToFactoryLookup := TDictionary.Create; end; class destructor TypeRegistry.Destroy; begin FTypeInfoToFactoryLookup.Free; end; class procedure TypeRegistry.RegisterTypeFactory(const aFactoryMethod: TFactoryMethod); var TypeInfo : Pointer; begin TypeInfo := System.TypeInfo(F); if (TypeInfo <> nil) and (PTypeInfo(TypeInfo).Kind = tkInterface) then FTypeInfoToFactoryLookup.AddOrSetValue(TypeInfo, @aFactoryMethod); end; class function TypeRegistry.Construct: F; var TypeInfo : PTypeInfo; Factory : Pointer; begin Result := default(F); TypeInfo := System.TypeInfo(F); if Assigned(TypeInfo) and (TypeInfo.Kind = tkInterface) then begin if FTypeInfoToFactoryLookup.TryGetValue(TypeInfo, Factory) then Result := TFactoryMethod(Factory)(); end; end; class function TypeRegistry.ConstructFromTypeInfo(const aTypeInfo: PTypeInfo): IBase; var Factory : Pointer; begin Result := nil; if FTypeInfoToFactoryLookup.TryGetValue(aTypeInfo, Factory) then Result := IBase(TFactoryMethod(Factory)()); end; end. thrift-0.19.0/lib/delphi/src/Thrift.WinHTTP.pas0000644000000000000000000015446414303740367021127 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.WinHTTP; {$I Thrift.Defines.inc} {$SCOPEDENUMS ON} // packing according to winhttp.h {$IFDEF Win64} {$ALIGN 8} {$ELSE} {$ALIGN 4} {$ENDIF} interface uses Windows, Classes, SysUtils, Math, Generics.Collections; type HINTERNET = type Pointer; INTERNET_PORT = type WORD; INTERNET_SCHEME = type Integer; LPLPCWSTR = ^LPCWSTR; LPURL_COMPONENTS = ^URL_COMPONENTS; URL_COMPONENTS = record dwStructSize : DWORD; // set to SizeOf(URL_COMPONENTS) lpszScheme : LPWSTR; // scheme name dwSchemeLength : DWORD; nScheme : INTERNET_SCHEME; // enumerated scheme type lpszHostName : LPWSTR; // host name dwHostNameLength : DWORD; nPort : INTERNET_PORT; // port number lpszUserName : LPWSTR; // user name dwUserNameLength : DWORD; lpszPassword : LPWSTR; // password dwPasswordLength : DWORD; lpszUrlPath : LPWSTR; // URL-path dwUrlPathLength : DWORD; lpszExtraInfo : LPWSTR; // extra information dwExtraInfoLength : DWORD; end; URL_COMPONENTSW = URL_COMPONENTS; LPURL_COMPONENTSW = LPURL_COMPONENTS; // When retrieving proxy data, an application must free the lpszProxy and // lpszProxyBypass strings contained in this structure (if they are non-NULL) // using the GlobalFree function. LPWINHTTP_PROXY_INFO = ^WINHTTP_PROXY_INFO; WINHTTP_PROXY_INFO = record dwAccessType : DWORD; // see WINHTTP_ACCESS_* types below lpszProxy : LPWSTR; // proxy server list lpszProxyBypass : LPWSTR; // proxy bypass list end; LPWINHTTP_PROXY_INFOW = ^WINHTTP_PROXY_INFOW; WINHTTP_PROXY_INFOW = WINHTTP_PROXY_INFO; WINHTTP_AUTOPROXY_OPTIONS = record dwFlags : DWORD; dwAutoDetectFlags : DWORD; lpszAutoConfigUrl : LPCWSTR; lpvReserved : LPVOID; dwReserved : DWORD; fAutoLogonIfChallenged : BOOL; end; WINHTTP_CURRENT_USER_IE_PROXY_CONFIG = record fAutoDetect : BOOL; lpszAutoConfigUrl : LPWSTR; lpszProxy : LPWSTR; lpszProxyBypass : LPWSTR; end; function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL; stdcall; function WinHttpOpen( const pszAgentW : LPCWSTR; const dwAccessType : DWORD; const pszProxyW : LPCWSTR; const pszProxyBypassW : LPCWSTR; const dwFlags : DWORD ) : HINTERNET; stdcall; function WinHttpConnect( const hSession : HINTERNET; const pswzServerName : LPCWSTR; const nServerPort : INTERNET_PORT; const dwReserved : DWORD ) : HINTERNET; stdcall; function WinHttpOpenRequest( const hConnect : HINTERNET; const pwszVerb, pwszObjectName, pwszVersion, pwszReferrer : LPCWSTR; const ppwszAcceptTypes : LPLPCWSTR; const dwFlags : DWORD ) : HINTERNET; stdcall; function WinHttpQueryOption( const hInternet : HINTERNET; const dwOption : DWORD; const pBuffer : Pointer; var dwBufferLength : DWORD) : BOOL; stdcall; function WinHttpSetOption( const hInternet : HINTERNET; const dwOption : DWORD; const pBuffer : Pointer; const dwBufferLength : DWORD) : BOOL; stdcall; function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET; const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32 ) : BOOL; stdcall; function WinHttpAddRequestHeaders( const hRequest : HINTERNET; const pwszHeaders : LPCWSTR; const dwHeadersLengthInChars : DWORD; const dwModifiers : DWORD ) : BOOL; stdcall; function WinHttpGetProxyForUrl( const hSession : HINTERNET; const lpcwszUrl : LPCWSTR; const options : WINHTTP_AUTOPROXY_OPTIONS; const info : WINHTTP_PROXY_INFO ) : BOOL; stdcall; function WinHttpGetIEProxyConfigForCurrentUser( var config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ) : BOOL; stdcall; function WinHttpSendRequest( const hRequest : HINTERNET; const lpszHeaders : LPCWSTR; const dwHeadersLength : DWORD; const lpOptional : Pointer; const dwOptionalLength : DWORD; const dwTotalLength : DWORD; const pContext : Pointer ) : BOOL; stdcall; function WinHttpWriteData( const hRequest : HINTERNET; const pBuf : Pointer; const dwBytesToWrite : DWORD; out dwBytesWritten : DWORD ) : BOOL; stdcall; function WinHttpReceiveResponse( const hRequest : HINTERNET; const lpReserved : Pointer) : BOOL; stdcall; function WinHttpQueryHeaders( const hRequest : HINTERNET; const dwInfoLevel : DWORD; const pwszName : LPCWSTR; const lpBuffer : Pointer; var dwBufferLength : DWORD; var dwIndex : DWORD ) : BOOL; stdcall; function WinHttpQueryDataAvailable( const hRequest : HINTERNET; var dwNumberOfBytesAvailable : DWORD ) : BOOL; stdcall; function WinHttpReadData( const hRequest : HINTERNET; const lpBuffer : Pointer; const dwBytesToRead : DWORD; out dwBytesRead : DWORD ) : BOOL; stdcall; function WinHttpCrackUrl( const pwszUrl : LPCWSTR; const dwUrlLength : DWORD; const dwFlags : DWORD; var urlComponents : URL_COMPONENTS ) : BOOL; stdcall; function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; const dwFlags : DWORD; const pwszUrl : LPCWSTR; var pdwUrlLength : DWORD ) : BOOL; stdcall; const // WinHttpOpen dwAccessType values WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0; WINHTTP_ACCESS_TYPE_NO_PROXY = 1; WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3; // flags for WinHttpOpen(): WINHTTP_FLAG_ASYNC = $10000000; // want async session, requires WinHttpSetStatusCallback() usage WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0; // ports INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443) // flags for WinHttpOpenRequest(): WINHTTP_FLAG_SECURE = $00800000; // use SSL if applicable (HTTPS) WINHTTP_FLAG_ESCAPE_PERCENT = $00000004; // if escaping enabled, escape percent as well WINHTTP_FLAG_NULL_CODEPAGE = $00000008; // assume all symbols are ASCII, use fast convertion WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100; // add "pragma: no-cache" request header WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE; WINHTTP_FLAG_ESCAPE_DISABLE = $00000040; // disable escaping WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query // flags for WinHttpSendRequest(): WINHTTP_NO_PROXY_NAME = nil; WINHTTP_NO_PROXY_BYPASS = nil; WINHTTP_NO_CLIENT_CERT_CONTEXT = nil; WINHTTP_NO_REFERER = nil; WINHTTP_DEFAULT_ACCEPT_TYPES = nil; WINHTTP_NO_ADDITIONAL_HEADERS = nil; WINHTTP_NO_REQUEST_DATA = nil; WINHTTP_HEADER_NAME_BY_INDEX = nil; WINHTTP_NO_OUTPUT_BUFFER = nil; WINHTTP_NO_HEADER_INDEX = nil; // WinHttpAddRequestHeaders() dwModifiers WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF; WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000; WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = $10000000; WINHTTP_ADDREQ_FLAG_ADD = $20000000; WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = $40000000; WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = $01000000; WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA; WINHTTP_ADDREQ_FLAG_REPLACE = $80000000; // URL functions ICU_NO_ENCODE = $20000000; // Don't convert unsafe characters to escape sequence ICU_DECODE = $10000000; // Convert %XX escape sequences to characters ICU_NO_META = $08000000; // Don't convert .. etc. meta path sequences ICU_ENCODE_SPACES_ONLY = $04000000; // Encode spaces only ICU_BROWSER_MODE = $02000000; // Special encode/decode rules for browser ICU_ENCODE_PERCENT = $00001000; // Encode any percent (ASCII25) ICU_ESCAPE = $80000000; // (un)escape URL characters ICU_ESCAPE_AUTHORITY = $00002000; // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host) ICU_REJECT_USERPWD = $00004000; // rejects usrls whick have username/pwd sections INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1); INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2); // options manifests for WinHttp{Query|Set}Option WINHTTP_OPTION_CALLBACK = 1; WINHTTP_OPTION_RESOLVE_TIMEOUT = 2; WINHTTP_OPTION_CONNECT_TIMEOUT = 3; WINHTTP_OPTION_CONNECT_RETRIES = 4; WINHTTP_OPTION_SEND_TIMEOUT = 5; WINHTTP_OPTION_RECEIVE_TIMEOUT = 6; WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7; WINHTTP_OPTION_HANDLE_TYPE = 9; WINHTTP_OPTION_READ_BUFFER_SIZE = 12; WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13; WINHTTP_OPTION_PARENT_HANDLE = 21; WINHTTP_OPTION_EXTENDED_ERROR = 24; WINHTTP_OPTION_SECURITY_FLAGS = 31; WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32; WINHTTP_OPTION_URL = 34; WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36; WINHTTP_OPTION_PROXY = 38; WINHTTP_OPTION_USER_AGENT = 41; WINHTTP_OPTION_CONTEXT_VALUE = 45; WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47; WINHTTP_OPTION_REQUEST_PRIORITY = 58; WINHTTP_OPTION_HTTP_VERSION = 59; WINHTTP_OPTION_DISABLE_FEATURE = 63; WINHTTP_OPTION_CODEPAGE = 68; WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73; WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74; WINHTTP_OPTION_AUTOLOGON_POLICY = 77; WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78; WINHTTP_OPTION_ENABLE_FEATURE = 79; WINHTTP_OPTION_WORKER_THREAD_COUNT = 80; WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81; WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82; WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83; WINHTTP_OPTION_SECURE_PROTOCOLS = 84; WINHTTP_OPTION_ENABLETRACING = 85; WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86; WINHTTP_OPTION_PASSPORT_RETURN_URL = 87; WINHTTP_OPTION_REDIRECT_POLICY = 88; WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89; WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90; WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91; WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92; WINHTTP_OPTION_CONNECTION_INFO = 93; WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94; WINHTTP_OPTION_SPN = 96; WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97; WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98; WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99; WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100; WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101; WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103; WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104; WINHTTP_OPTION_SERVER_SPN_USED = 106; WINHTTP_OPTION_PROXY_SPN_USED = 107; WINHTTP_OPTION_SERVER_CBT = 108; // options for newer WinHTTP versions WINHTTP_OPTION_DECOMPRESSION = 118; // WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK; //WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT; WINHTTP_OPTION_USERNAME = $1000; WINHTTP_OPTION_PASSWORD = $1001; WINHTTP_OPTION_PROXY_USERNAME = $1002; WINHTTP_OPTION_PROXY_PASSWORD = $1003; // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER WINHTTP_CONNS_PER_SERVER_UNLIMITED = $FFFFFFFF; // values for WINHTTP_OPTION_AUTOLOGON_POLICY WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0; WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1; WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2; WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM; // values for WINHTTP_OPTION_REDIRECT_POLICY WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0; WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1; WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2; WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS; WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP; WINHTTP_DISABLE_PASSPORT_AUTH = $00000000; WINHTTP_ENABLE_PASSPORT_AUTH = $10000000; WINHTTP_DISABLE_PASSPORT_KEYRING = $20000000; WINHTTP_ENABLE_PASSPORT_KEYRING = $40000000; // values for WINHTTP_OPTION_DISABLE_FEATURE WINHTTP_DISABLE_COOKIES = $00000001; WINHTTP_DISABLE_REDIRECTS = $00000002; WINHTTP_DISABLE_AUTHENTICATION = $00000004; WINHTTP_DISABLE_KEEP_ALIVE = $00000008; // values for WINHTTP_OPTION_ENABLE_FEATURE WINHTTP_ENABLE_SSL_REVOCATION = $00000001; WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = $00000002; // values for WINHTTP_OPTION_SPN WINHTTP_DISABLE_SPN_SERVER_PORT = $00000000; WINHTTP_ENABLE_SPN_SERVER_PORT = $00000001; WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT; // winhttp handle types WINHTTP_HANDLE_TYPE_SESSION = 1; WINHTTP_HANDLE_TYPE_CONNECT = 2; WINHTTP_HANDLE_TYPE_REQUEST = 3; // values for auth schemes WINHTTP_AUTH_SCHEME_BASIC = $00000001; WINHTTP_AUTH_SCHEME_NTLM = $00000002; WINHTTP_AUTH_SCHEME_PASSPORT = $00000004; WINHTTP_AUTH_SCHEME_DIGEST = $00000008; WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010; // WinHttp supported Authentication Targets WINHTTP_AUTH_TARGET_SERVER = $00000000; WINHTTP_AUTH_TARGET_PROXY = $00000001; // options for WINHTTP_OPTION_DECOMPRESSION WINHTTP_DECOMPRESSION_FLAG_GZIP = $00000001; WINHTTP_DECOMPRESSION_FLAG_DEFLATE = $00000002; WINHTTP_DECOMPRESSION_FLAG_ALL = WINHTTP_DECOMPRESSION_FLAG_GZIP or WINHTTP_DECOMPRESSION_FLAG_DEFLATE; // values for WINHTTP_OPTION_SECURITY_FLAGS // query only SECURITY_FLAG_SECURE = $00000001; // can query only SECURITY_FLAG_STRENGTH_WEAK = $10000000; SECURITY_FLAG_STRENGTH_MEDIUM = $40000000; SECURITY_FLAG_STRENGTH_STRONG = $20000000; // query flags WINHTTP_QUERY_MIME_VERSION = 0; WINHTTP_QUERY_CONTENT_TYPE = 1; WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2; WINHTTP_QUERY_CONTENT_ID = 3; WINHTTP_QUERY_CONTENT_DESCRIPTION = 4; WINHTTP_QUERY_CONTENT_LENGTH = 5; WINHTTP_QUERY_CONTENT_LANGUAGE = 6; WINHTTP_QUERY_ALLOW = 7; WINHTTP_QUERY_PUBLIC = 8; WINHTTP_QUERY_DATE = 9; WINHTTP_QUERY_EXPIRES = 10; WINHTTP_QUERY_LAST_MODIFIED = 11; WINHTTP_QUERY_MESSAGE_ID = 12; WINHTTP_QUERY_URI = 13; WINHTTP_QUERY_DERIVED_FROM = 14; WINHTTP_QUERY_COST = 15; WINHTTP_QUERY_LINK = 16; WINHTTP_QUERY_PRAGMA = 17; WINHTTP_QUERY_VERSION = 18; WINHTTP_QUERY_STATUS_CODE = 19; WINHTTP_QUERY_STATUS_TEXT = 20; WINHTTP_QUERY_RAW_HEADERS = 21; WINHTTP_QUERY_RAW_HEADERS_CRLF = 22; WINHTTP_QUERY_CONNECTION = 23; WINHTTP_QUERY_ACCEPT = 24; WINHTTP_QUERY_ACCEPT_CHARSET = 25; WINHTTP_QUERY_ACCEPT_ENCODING = 26; WINHTTP_QUERY_ACCEPT_LANGUAGE = 27; WINHTTP_QUERY_AUTHORIZATION = 28; WINHTTP_QUERY_CONTENT_ENCODING = 29; WINHTTP_QUERY_FORWARDED = 30; WINHTTP_QUERY_FROM = 31; WINHTTP_QUERY_IF_MODIFIED_SINCE = 32; WINHTTP_QUERY_LOCATION = 33; WINHTTP_QUERY_ORIG_URI = 34; WINHTTP_QUERY_REFERER = 35; WINHTTP_QUERY_RETRY_AFTER = 36; WINHTTP_QUERY_SERVER = 37; WINHTTP_QUERY_TITLE = 38; WINHTTP_QUERY_USER_AGENT = 39; WINHTTP_QUERY_WWW_AUTHENTICATE = 40; WINHTTP_QUERY_PROXY_AUTHENTICATE = 41; WINHTTP_QUERY_ACCEPT_RANGES = 42; WINHTTP_QUERY_SET_COOKIE = 43; WINHTTP_QUERY_COOKIE = 44; WINHTTP_QUERY_REQUEST_METHOD = 45; WINHTTP_QUERY_REFRESH = 46; WINHTTP_QUERY_CONTENT_DISPOSITION = 47; WINHTTP_QUERY_AGE = 48; WINHTTP_QUERY_CACHE_CONTROL = 49; WINHTTP_QUERY_CONTENT_BASE = 50; WINHTTP_QUERY_CONTENT_LOCATION = 51; WINHTTP_QUERY_CONTENT_MD5 = 52; WINHTTP_QUERY_CONTENT_RANGE = 53; WINHTTP_QUERY_ETAG = 54; WINHTTP_QUERY_HOST = 55; WINHTTP_QUERY_IF_MATCH = 56; WINHTTP_QUERY_IF_NONE_MATCH = 57; WINHTTP_QUERY_IF_RANGE = 58; WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59; WINHTTP_QUERY_MAX_FORWARDS = 60; WINHTTP_QUERY_PROXY_AUTHORIZATION = 61; WINHTTP_QUERY_RANGE = 62; WINHTTP_QUERY_TRANSFER_ENCODING = 63; WINHTTP_QUERY_UPGRADE = 64; WINHTTP_QUERY_VARY = 65; WINHTTP_QUERY_VIA = 66; WINHTTP_QUERY_WARNING = 67; WINHTTP_QUERY_EXPECT = 68; WINHTTP_QUERY_PROXY_CONNECTION = 69; WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70; WINHTTP_QUERY_PROXY_SUPPORT = 75; WINHTTP_QUERY_AUTHENTICATION_INFO = 76; WINHTTP_QUERY_PASSPORT_URLS = 77; WINHTTP_QUERY_PASSPORT_CONFIG = 78; WINHTTP_QUERY_MAX = 78; WINHTTP_QUERY_CUSTOM = 65535; WINHTTP_QUERY_FLAG_REQUEST_HEADERS = $80000000; WINHTTP_QUERY_FLAG_SYSTEMTIME = $40000000; WINHTTP_QUERY_FLAG_NUMBER = $20000000; // Secure connection error status flags WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001; WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002; WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = $00000004; WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = $00000008; WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = $00000010; WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = $00000020; WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = $00000040; WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = $80000000; WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = $00000008; WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = $00000020; WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = $00000080; WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200; WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800; // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher! WINHTTP_FLAG_SECURE_PROTOCOL_ALL = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; // AutoProxy WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001; WINHTTP_AUTOPROXY_CONFIG_URL = $00000002; WINHTTP_AUTOPROXY_HOST_KEEPCASE = $00000004; WINHTTP_AUTOPROXY_HOST_LOWERCASE = $00000008; WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000; WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000; // Flags for dwAutoDetectFlags WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001; WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002; const WINHTTP_ERROR_BASE = 12000; ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1; ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2; ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4; ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5; ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6; ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7; ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9; ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11; ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12; ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15; ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17; ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18; ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19; ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29; ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30; ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32; ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44; ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100; ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101; ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102; ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103; ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150; ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152; ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153; ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154; ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155; ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156; ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178; ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166; ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167; ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172; ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175; // Certificate security errors. Additional information is provided // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification. ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37; ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38; ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45; ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57; ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157; ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169; ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170; ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179; ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180; ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181; ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182; ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183; ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184; ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185; ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186; WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 186; const WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE or WINHTTP_FLAG_BYPASS_PROXY_CACHE or WINHTTP_FLAG_ESCAPE_DISABLE; type IWinHTTPSession = interface; IWinHTTPConnection = interface; IWinHTTPRequest = interface ['{FADA4B45-D447-4F07-8361-1AD6656E5E8C}'] function Handle : HINTERNET; function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; procedure TryAutoProxy( const aUrl : string); procedure EnableAutomaticContentDecompression( const aEnable : Boolean); function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; function FlushAndReceiveResponse : Boolean; function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; function QueryTotalResponseSize( out dwSize : DWORD) : Boolean; function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean; end; IWinHTTPConnection = interface ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}'] function Handle : HINTERNET; function Session : IWinHTTPSession; function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; end; IWinHTTPSession = interface ['{261ADCB7-5465-4407-8840-468C17F009F0}'] function Handle : HINTERNET; function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean; end; IWinHTTPUrl = interface ['{78BE977C-4171-4AF5-A250-FD2890205E63}'] // url parts getter function GetScheme : UnicodeString; function GetNumScheme : INTERNET_SCHEME; function GetHostName : UnicodeString; function GetPort : INTERNET_PORT; function GetUserName : UnicodeString; function GetPassword : UnicodeString; function GetUrlPath : UnicodeString; function GetExtraInfo : UnicodeString; // url parts setter procedure SetScheme( const value : UnicodeString); procedure SetHostName ( const value : UnicodeString); procedure SetPort( const value : INTERNET_PORT); procedure SetUserName( const value : UnicodeString); procedure SetPassword( const value : UnicodeString); procedure SetUrlPath( const value : UnicodeString); procedure SetExtraInfo( const value : UnicodeString); // url as a whole function BuildUrl : UnicodeString; procedure CrackUrl( const value : UnicodeString); // url parts property Scheme : UnicodeString read GetScheme write SetScheme; property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly property HostName : UnicodeString read GetHostName write SetHostName; property Port : INTERNET_PORT read GetPort write SetPort; property UserName : UnicodeString read GetUserName write SetUserName; property Password : UnicodeString read GetPassword write SetPassword; property UrlPath : UnicodeString read GetUrlPath write SetUrlPath; property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo; // url as a whole property CompleteURL : UnicodeString read BuildUrl write CrackUrl; end; type TWinHTTPHandleObjectImpl = class( TInterfacedObject) strict protected FHandle : HINTERNET; function Handle : HINTERNET; public constructor Create( const aHandle : HINTERNET); destructor Destroy; override; end; TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession) strict protected // IWinHTTPSession function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean; public constructor Create( const aAgent : UnicodeString; const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; const aProxy : UnicodeString = ''; const aProxyBypass : UnicodeString = ''; const aFlags : DWORD = 0); destructor Destroy; override; end; TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection) strict protected FSession : IWinHTTPSession; // IWinHTTPConnection function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; function Session : IWinHTTPSession; public constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT); destructor Destroy; override; end; TAcceptTypesArray = array of string; TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) strict protected FConnection : IWinHTTPConnection; // IWinHTTPRequest function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; procedure TryAutoProxy( const aUrl : string); procedure EnableAutomaticContentDecompression( const aEnable : Boolean); function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; function FlushAndReceiveResponse : Boolean; function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; function QueryTotalResponseSize( out dwSize : DWORD) : Boolean; function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean; public constructor Create( const aConnection : IWinHTTPConnection; const aVerb, aObjName : UnicodeString; const aVersion : UnicodeString = ''; const aReferrer : UnicodeString = ''; const aAcceptTypes : UnicodeString = '*/*'; const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS ); destructor Destroy; override; end; TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl) strict private FScheme : UnicodeString; FNumScheme : INTERNET_SCHEME; FHostName : UnicodeString; FPort : INTERNET_PORT; FUserName : UnicodeString; FPassword : UnicodeString; FUrlPath : UnicodeString; FExtraInfo : UnicodeString; strict protected // url parts getter function GetScheme : UnicodeString; function GetNumScheme : INTERNET_SCHEME; function GetHostName : UnicodeString; function GetPort : INTERNET_PORT; function GetUserName : UnicodeString; function GetPassword : UnicodeString; function GetUrlPath : UnicodeString; function GetExtraInfo : UnicodeString; // url parts setter procedure SetScheme( const value : UnicodeString); procedure SetHostName ( const value : UnicodeString); procedure SetPort( const value : INTERNET_PORT); procedure SetUserName( const value : UnicodeString); procedure SetPassword( const value : UnicodeString); procedure SetUrlPath( const value : UnicodeString); procedure SetExtraInfo( const value : UnicodeString); // url as a whole function BuildUrl : UnicodeString; procedure CrackUrl( const value : UnicodeString); public constructor Create( const aUri : UnicodeString); destructor Destroy; override; end; WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO procedure Initialize; procedure FreeAllocatedResources; end; WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG procedure Initialize; procedure FreeAllocatedResources; end; EWinHTTPException = class(Exception); { helper functions } function WinHttpSysErrorMessage( const error : Cardinal): string; procedure RaiseLastWinHttpError; implementation const WINHTTP_DLL = 'WinHTTP.dll'; function WinHttpCloseHandle; stdcall; external WINHTTP_DLL; function WinHttpOpen; stdcall; external WINHTTP_DLL; function WinHttpConnect; stdcall; external WINHTTP_DLL; function WinHttpOpenRequest; stdcall; external WINHTTP_DLL; function WinHttpSendRequest; stdcall; external WINHTTP_DLL; function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL; function WinHttpQueryOption; stdcall; external WINHTTP_DLL; function WinHttpSetOption; stdcall; external WINHTTP_DLL; function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL; function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL; function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL; function WinHttpWriteData; stdcall; external WINHTTP_DLL; function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL; function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL; function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL; function WinHttpReadData; stdcall; external WINHTTP_DLL; function WinHttpCrackUrl; stdcall; external WINHTTP_DLL; function WinHttpCreateUrl; stdcall; external WINHTTP_DLL; { helper functions } function WinHttpSysErrorMessage( const error : Cardinal): string; const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_IGNORE_INSERTS or FORMAT_MESSAGE_FROM_SYSTEM or FORMAT_MESSAGE_FROM_HMODULE; var pBuffer : PChar; nChars : Cardinal; begin if (error < WINHTTP_ERROR_BASE) or (error > WINHTTP_ERROR_LAST) then Exit( SysUtils.SysErrorMessage( error)); pBuffer := nil; try nChars := FormatMessage( FLAGS, Pointer( GetModuleHandle( WINHTTP_DLL)), error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language @pBuffer, 0, nil); SetString( result, pBuffer, nChars); finally LocalFree( NativeUInt( pBuffer)); end; end; procedure RaiseLastWinHttpError; var error : Cardinal; sMsg : string; begin error := Cardinal( GetLastError); if error <> NOERROR then begin sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error); raise EWinHTTPException.Create( sMsg); end; end; { misc. record helper } procedure GlobalFreeAndNil( var p : LPWSTR); begin if p <> nil then begin GlobalFree( HGLOBAL( p)); p := nil; end; end; procedure WINHTTP_PROXY_INFO_Helper.Initialize; begin FillChar( Self, SizeOf(Self), 0); end; procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources; // The caller must free the lpszProxy and lpszProxyBypass strings // if they are non-NULL. Use GlobalFree to free the strings. begin GlobalFreeAndNil( lpszProxy); GlobalFreeAndNil( lpszProxyBypass); Initialize; end; procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize; begin FillChar( Self, SizeOf(Self), 0); end; procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources; // The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings // if they are non-NULL. Use GlobalFree to free the strings. begin GlobalFreeAndNil( lpszProxy); GlobalFreeAndNil( lpszProxyBypass); GlobalFreeAndNil( lpszAutoConfigUrl); Initialize; end; { TWinHTTPHandleObjectImpl } constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET); begin inherited Create; FHandle := aHandle; if FHandle = nil then raise EWinHTTPException.Create('Invalid handle'); end; destructor TWinHTTPHandleObjectImpl.Destroy; begin try if Assigned(FHandle) then begin WinHttpCloseHandle(FHandle); FHandle := nil; end; finally inherited Destroy; end; end; function TWinHTTPHandleObjectImpl.Handle : HINTERNET; begin result := FHandle; end; { TWinHTTPSessionImpl } constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD; const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD); var handle : HINTERNET; begin handle := WinHttpOpen( PWideChar(aAgent), aAccessType, PWideChar(Pointer(aProxy)), // may be nil PWideChar(Pointer(aProxyBypass)), // may be nil aFlags); if handle = nil then RaiseLastWinHttpError; inherited Create( handle); end; destructor TWinHTTPSessionImpl.Destroy; begin inherited Destroy; // add code here end; function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection; begin result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort); end; function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; begin result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout); end; function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean; var dwSize : DWORD; begin dwSize := SizeOf(aFlagSet); result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize); end; { TWinHTTPConnectionImpl } constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT); var handle : HINTERNET; begin FSession := aSession; handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0); if handle = nil then RaiseLastWinHttpError; inherited Create( handle); end; destructor TWinHTTPConnectionImpl.Destroy; begin inherited Destroy; FSession := nil; end; function TWinHTTPConnectionImpl.Session : IWinHTTPSession; begin result := FSession; end; function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; var dwFlags : DWORD; begin dwFlags := WINHTTP_THRIFT_DEFAULTS; if secure then dwFlags := dwFlags or WINHTTP_FLAG_SECURE else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE; result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags); end; { TWinHTTPRequestImpl } constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection; const aVerb, aObjName, aVersion, aReferrer : UnicodeString; const aAcceptTypes : UnicodeString; const aFlags : DWORD ); var handle : HINTERNET; accept : array[0..1] of PWideChar; begin FConnection := aConnection; accept[0] := PWideChar(aAcceptTypes); accept[1] := nil; handle := WinHttpOpenRequest( FConnection.Handle, PWideChar(UpperCase(aVerb)), PWideChar(aObjName), PWideChar(aVersion), PWideChar(aReferrer), @accept, aFlags); if handle = nil then RaiseLastWinHttpError; inherited Create( handle); end; destructor TWinHTTPRequestImpl.Destroy; begin inherited Destroy; FConnection := nil; end; function TWinHTTPRequestImpl.Connection : IWinHTTPConnection; begin result := FConnection; end; function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; begin result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout); end; function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean; begin result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag); end; procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string); // From MSDN: // AutoProxy support is not fully integrated into the HTTP stack in WinHTTP. // Before sending a request, the application must call WinHttpGetProxyForUrl // to obtain the name of a proxy server and then call WinHttpSetOption using // WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request // handle created by WinHttpOpenRequest. // See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api var options : WINHTTP_AUTOPROXY_OPTIONS; proxy : WINHTTP_PROXY_INFO; ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG; dwSize : DWORD; begin // try AutoProxy via PAC first proxy.Initialize; try FillChar( options, SizeOf(options), 0); options.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT; options.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A; options.fAutoLogonIfChallenged := TRUE; if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin dwSize := SizeOf(proxy); WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize); Exit; end; finally proxy.FreeAllocatedResources; end; // Use IE settings as a fallback, useful in client (i.e. non-server) environments ieProxy.Initialize; try if WinHttpGetIEProxyConfigForCurrentUser( ieProxy) then begin // lpszAutoConfigUrl = "Use automatic proxy configuration" if ieProxy.lpszAutoConfigUrl <> nil then begin options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl; options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL; proxy.Initialize; try if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin dwSize := SizeOf(proxy); WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize); Exit; end; finally proxy.FreeAllocatedResources; end; end; // lpszProxy = "use a proxy server" if ieProxy.lpszProxy <> nil then begin proxy.Initialize; try proxy.dwAccessType := WINHTTP_ACCESS_TYPE_NAMED_PROXY; proxy.lpszProxy := ieProxy.lpszProxy; proxy.lpszProxyBypass := ieProxy.lpszProxyBypass; dwSize := SizeOf(proxy); WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize); Exit; finally proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies! end; end; end; finally ieProxy.FreeAllocatedResources; end; end; procedure TWinHTTPRequestImpl.EnableAutomaticContentDecompression( const aEnable : Boolean); // Enable automatic gzip,deflate decompression on systems that support this option // From the docs: WinHTTP will automatically set an appropriate Accept-Encoding header, // overriding any value supplied by the caller -> we don't have to do this // Available on Win 8.1 or higher var value : DWORD; begin if aEnable then value := WINHTTP_DECOMPRESSION_FLAG_ALL else value := 0; // ignore returned value, the option is not supported with older WinHTTP versions WinHttpSetOption( Handle, WINHTTP_OPTION_DECOMPRESSION, @value, SizeOf(DWORD)); end; function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean; begin result := WinHttpSendRequest( FHandle, WINHTTP_NO_ADDITIONAL_HEADERS, 0, pBuf, dwBytes, // number of bytes in pBuf dwBytes + dwExtra, // becomes the Content-Length nil); // context for async operations end; function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; begin if not WinHttpWriteData( FHandle, pBuf, dwBytes, result) then result := 0; end; function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean; begin result := WinHttpReceiveResponse( FHandle, nil); end; function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes; var dwAvailable, dwReceived : DWORD; begin if WinHttpQueryDataAvailable( FHandle, dwAvailable) then dwAvailable := Min( dwRead, dwAvailable) else dwAvailable := 0; SetLength( result, dwAvailable); if dwAvailable = 0 then Exit; if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived) then SetLength( result, dwReceived) else SetLength( result, 0); end; function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; var dwAvailable : DWORD; begin if WinHttpQueryDataAvailable( FHandle, dwAvailable) then dwAvailable := Min( dwRead, dwAvailable) else dwAvailable := 0; if (dwAvailable = 0) or not WinHttpReadData( FHandle, pBuf, dwAvailable, result) then result := 0; end; function TWinHTTPRequestImpl.QueryDataAvailable : DWORD; begin if not WinHttpQueryDataAvailable( FHandle, result) then result := 0; end; function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boolean; var dwBytes, dwError, dwIndex : DWORD; bytes : array[0..32-1] of Byte; begin dwBytes := SizeOf( result); dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); result := WinHttpQueryHeaders( FHandle, WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, @dwSize, dwBytes, dwIndex); if result then Exit; dwError := GetLastError; // Hack: WinHttpQueryHeaders() sometimes returns error 122 even if the buffer is large enough // According to the docs, WINHTTP_QUERY_FLAG_NUMBER always returns a 32 bit number (which it does!) // but for some strange reason since win 10 build 18636.815 passing a 4 bytes buffer is not enough anymore if dwError = ERROR_INSUFFICIENT_BUFFER then begin dwBytes := sizeof(bytes); FillChar( bytes[0], dwBytes, 0); result := WinHttpQueryHeaders( FHandle, WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, @bytes[0], dwBytes, dwIndex); if result then begin ASSERT( dwBytes = SizeOf(dwSize)); // result is still a DWORD Move( bytes[0], dwSize, SizeOf(dwSize)); // copy over result data Exit; end; end; // header may just not be there dwSize := MAXINT; // we don't know, just return something useful ASSERT( dwError = ERROR_WINHTTP_HEADER_NOT_FOUND); // anything else would be an real error end; function TWinHTTPRequestImpl.QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean; var dwBytes, dwError, dwIndex : DWORD; begin // HTTP status code dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); dwBytes := SizeOf(dwStatusCode); result := WinHttpQueryHeaders( FHandle, WINHTTP_QUERY_STATUS_CODE or WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, @dwStatusCode, dwBytes, dwIndex); if not result then begin dwStatusCode := 0; // no data dwError := GetLastError; if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error end; // HTTP status text dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); dwBytes := 0; result := WinHttpQueryHeaders( FHandle, WINHTTP_QUERY_STATUS_TEXT, WINHTTP_HEADER_NAME_BY_INDEX, WINHTTP_NO_OUTPUT_BUFFER, // we need to determine the size first dwBytes, // will receive the required buffer size dwIndex); if dwBytes > 0 then begin // allocate buffer and call again to get the value SetLength( sStatusText, dwBytes div SizeOf(Char)); dwBytes := Length(sStatusText) * SizeOf(Char); result := WinHttpQueryHeaders( FHandle, WINHTTP_QUERY_STATUS_TEXT, WINHTTP_HEADER_NAME_BY_INDEX, @sStatusText[1], dwBytes, dwIndex); end; if result then SetLength( sStatusText, StrLen(PChar(sStatusText))) // get rid of any terminating #0 chars else begin sStatusText := ''; // no data dwError := GetLastError; if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error end; // do we have at least something? result := (dwStatusCode <> 0) or (sStatusText <> ''); end; { TWinHTTPUrlImpl } constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString); begin inherited Create; CrackUrl( aUri) end; destructor TWinHTTPUrlImpl.Destroy; begin inherited Destroy; end; procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString); const FLAGS = 0; // no special operations, leave components as-is var components : URL_COMPONENTS; begin FillChar(components, SizeOf(components), 0); components.dwStructSize := SizeOf(components); if value <> '' then begin { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the length member is not zero, both the pointer and length members are returned. } components.dwSchemeLength := DWORD(-1); components.dwHostNameLength := DWORD(-1); components.dwUserNameLength := DWORD(-1); components.dwPasswordLength := DWORD(-1); components.dwUrlPathLength := DWORD(-1); components.dwExtraInfoLength := DWORD(-1); WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components); end; FNumScheme := components.nScheme; FPort := components.nPort; SetString( FScheme, components.lpszScheme, components.dwSchemeLength); SetString( FHostName, components.lpszHostName, components.dwHostNameLength); SetString( FUserName, components.lpszUserName, components.dwUserNameLength); SetString( FPassword, components.lpszPassword, components.dwPasswordLength); SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength); SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength); end; function TWinHTTPUrlImpl.BuildUrl : UnicodeString; const FLAGS = 0; // no special operations, leave components as-is var components : URL_COMPONENTS; dwChars : DWORD; begin FillChar(components, SizeOf(components), 0); components.dwStructSize := SizeOf(components); components.lpszScheme := PWideChar(FScheme); components.dwSchemeLength := Length(FScheme); components.lpszHostName := PWideChar(FHostName); components.dwHostNameLength := Length(FHostName); components.nPort := FPort; components.lpszUserName := PWideChar(FUserName); components.dwUserNameLength := Length(FUserName); components.lpszPassword := PWideChar(FPassword); components.dwPasswordLength := Length(FPassword); components.lpszUrlPath := PWideChar(FUrlPath); components.dwUrlPathLength := Length(FUrlPath); components.lpszExtraInfo := PWideChar(FExtraInfo); components.dwExtraInfoLength := Length(FExtraInfo); WinHttpCreateUrl( components, FLAGS, nil, dwChars); if dwChars = 0 then result := '' else begin SetLength( result, dwChars + 1); WinHttpCreateUrl( components, FLAGS, @result[1], dwChars); SetLength( result, dwChars); // cut off terminating #0 end; end; function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString; begin result := FExtraInfo; end; function TWinHTTPUrlImpl.GetHostName: UnicodeString; begin result := FHostName; end; function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME; begin result := FNumScheme; end; function TWinHTTPUrlImpl.GetPassword: UnicodeString; begin result := FPassword; end; function TWinHTTPUrlImpl.GetPort: INTERNET_PORT; begin result := FPort; end; function TWinHTTPUrlImpl.GetScheme: UnicodeString; begin result := FScheme; end; function TWinHTTPUrlImpl.GetUrlPath: UnicodeString; begin result := FUrlPath; end; function TWinHTTPUrlImpl.GetUserName: UnicodeString; begin result := FUserName; end; procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString); begin FExtraInfo := value; end; procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString); begin FHostName := value; end; procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString); begin FPassword := value; end; procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT); begin FPort := value; end; procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString); begin FScheme := value; end; procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString); begin FUrlPath := value; end; procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString); begin FUserName := value; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Stream.pas0000644000000000000000000002446314303740367021120 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Stream; {$I Thrift.Defines.inc} interface uses Classes, SysUtils, SysConst, RTLConsts, {$IFDEF OLD_UNIT_NAMES} ActiveX, {$ELSE} Winapi.ActiveX, {$ENDIF} Thrift.Utils; type IThriftStream = interface ['{3A61A8A6-3639-4B91-A260-EFCA23944F3A}'] procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; procedure Open; procedure Close; procedure Flush; function IsOpen: Boolean; function ToArray: TBytes; function Size : Int64; function Position : Int64; end; TThriftStreamImpl = class abstract( TInterfacedObject, IThriftStream) strict private procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload; strict protected // IThriftStream procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline; procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual; procedure Open; virtual; abstract; procedure Close; virtual; abstract; procedure Flush; virtual; abstract; function IsOpen: Boolean; virtual; abstract; function ToArray: TBytes; virtual; abstract; function Size : Int64; virtual; function Position : Int64; virtual; end; TThriftStreamAdapterDelphi = class( TThriftStreamImpl) strict private FStream : TStream; FOwnsStream : Boolean; strict protected // IThriftStream procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; function Size : Int64; override; function Position : Int64; override; public constructor Create( const aStream: TStream; aOwnsStream : Boolean); destructor Destroy; override; end; TThriftStreamAdapterCOM = class( TThriftStreamImpl) strict private FStream : IStream; strict protected // IThriftStream procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; function Size : Int64; override; function Position : Int64; override; public constructor Create( const aStream: IStream); end; TThriftMemoryStream = class(TMemoryStream) strict protected FInitialCapacity : NativeInt; public constructor Create( const aInitialCapacity : NativeInt = 4096); // reimplemented procedure Clear; // make it publicly visible property Capacity; end; implementation uses Thrift.Transport; { TThriftMemoryStream } constructor TThriftMemoryStream.Create( const aInitialCapacity : NativeInt); begin inherited Create; FInitialCapacity := aInitialCapacity; Clear; end; procedure TThriftMemoryStream.Clear; // reimplemented to keep initial capacity begin Position := 0; Size := 0; // primary goal: minimize costly reallocations (performance!) // secondary goal: prevent costly ressource over-allocations if (FInitialCapacity >= 1024*1024) // if we are talking about MB or ((Capacity div 2) > FInitialCapacity) // or the allocated buffer is really large or (Capacity < FInitialCapacity) // or we are actually below the limit then Capacity := FInitialCapacity; end; { TThriftStreamAdapterCOM } procedure TThriftStreamAdapterCOM.Close; begin FStream := nil; end; constructor TThriftStreamAdapterCOM.Create( const aStream: IStream); begin inherited Create; FStream := aStream; end; procedure TThriftStreamAdapterCOM.Flush; begin if IsOpen then begin if FStream <> nil then begin FStream.Commit( STGC_DEFAULT ); end; end; end; function TThriftStreamAdapterCOM.Size : Int64; var statstg: TStatStg; begin FillChar( statstg, SizeOf( statstg), 0); if IsOpen and Succeeded( FStream.Stat( statstg, STATFLAG_NONAME )) then result := statstg.cbSize else result := 0; end; function TThriftStreamAdapterCOM.Position : Int64; var newpos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND}; begin if SUCCEEDED( FStream.Seek( 0, STREAM_SEEK_CUR, newpos)) then result := Int64(newpos) else raise TTransportExceptionEndOfFile.Create('Seek() error'); end; function TThriftStreamAdapterCOM.IsOpen: Boolean; begin Result := FStream <> nil; end; procedure TThriftStreamAdapterCOM.Open; begin // nothing to do end; function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; var pTmp : PByte; begin inherited; if count >= buflen-offset then count := buflen-offset; Result := 0; if FStream <> nil then begin if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); FStream.Read( pTmp, count, @Result); end; end; end; function TThriftStreamAdapterCOM.ToArray: TBytes; var len : Int64; NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND}; cbRead : Integer; begin len := Self.Size; SetLength( Result, len ); if len > 0 then begin if Succeeded( FStream.Seek( 0, STREAM_SEEK_SET, NewPos) ) then begin FStream.Read( @Result[0], len, @cbRead); end; end; end; procedure TThriftStreamAdapterCOM.Write( const pBuf: Pointer; offset: Integer; count: Integer); var nWritten : Integer; pTmp : PByte; begin inherited; if IsOpen then begin if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); FStream.Write( pTmp, count, @nWritten); end; end; end; { TThriftStreamImpl } procedure TThriftStreamImpl.CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); begin if count > 0 then begin if (offset < 0) or ( offset >= buflen) then begin raise ERangeError.Create( SBitsIndexError ); end; if count > buflen then begin raise ERangeError.Create( SBitsIndexError ); end; end; end; function TThriftStreamImpl.Read(var buffer: TBytes; offset, count: Integer): Integer; begin if Length(buffer) > 0 then Result := Read( @buffer[0], Length(buffer), offset, count) else Result := 0; end; function TThriftStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; begin Result := 0; CheckSizeAndOffset( pBuf, buflen, offset, count ); end; procedure TThriftStreamImpl.Write(const buffer: TBytes; offset, count: Integer); begin if Length(buffer) > 0 then Write( @buffer[0], offset, count); end; procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer); begin CheckSizeAndOffset( pBuf, offset+count, offset, count); end; function TThriftStreamImpl.Size : Int64; begin ASSERT(FALSE); raise ENotImplemented.Create(ClassName+'.Size'); end; function TThriftStreamImpl.Position : Int64; begin ASSERT(FALSE); raise ENotImplemented.Create(ClassName+'.Position'); end; { TThriftStreamAdapterDelphi } constructor TThriftStreamAdapterDelphi.Create( const aStream: TStream; aOwnsStream: Boolean); begin inherited Create; FStream := aStream; FOwnsStream := aOwnsStream; end; destructor TThriftStreamAdapterDelphi.Destroy; begin if FOwnsStream then Close; inherited; end; procedure TThriftStreamAdapterDelphi.Close; begin FStream.Free; FStream := nil; FOwnsStream := False; end; procedure TThriftStreamAdapterDelphi.Flush; begin // nothing to do end; function TThriftStreamAdapterDelphi.Size : Int64; begin result := FStream.Size; end; function TThriftStreamAdapterDelphi.Position : Int64; begin result := FStream.Position; end; function TThriftStreamAdapterDelphi.IsOpen: Boolean; begin Result := FStream <> nil; end; procedure TThriftStreamAdapterDelphi.Open; begin // nothing to do end; function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer; var pTmp : PByte; begin inherited; if count >= buflen-offset then count := buflen-offset; if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); Result := FStream.Read( pTmp^, count) end else Result := 0; end; function TThriftStreamAdapterDelphi.ToArray: TBytes; var OrgPos : Integer; len : Integer; begin if FStream <> nil then len := FStream.Size else len := 0; SetLength( Result, len ); if len > 0 then begin OrgPos := FStream.Position; try FStream.Position := 0; FStream.ReadBuffer( Pointer(@Result[0])^, len ); finally FStream.Position := OrgPos; end; end end; procedure TThriftStreamAdapterDelphi.Write(const pBuf : Pointer; offset, count: Integer); var pTmp : PByte; begin inherited; if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); FStream.Write( pTmp^, count) end; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Exception.pas0000644000000000000000000000361214303740367021614 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) {$SCOPEDENUMS ON} unit Thrift.Exception; interface uses Classes, SysUtils; type // base class for all Thrift exceptions TException = class( SysUtils.Exception) strict private function GetMessageText : string; public function Message : string; // hide inherited property: allow read, but prevent accidental writes procedure UpdateMessageProperty; // update inherited message property with toString() end; implementation { TException } function TException.Message; // allow read (exception summary), but prevent accidental writes // read will return the exception summary begin result := Self.GetMessageText; end; procedure TException.UpdateMessageProperty; // Update the inherited Message property to better conform to standard behaviour. // Nice benefit: The IDE is now able to show the exception message again. begin inherited Message := Self.GetMessageText; end; function TException.GetMessageText : string; // produces a summary text begin result := Self.ToString; if (result <> '') and (result[1] = '(') then result := Copy(result,2,Length(result)-2); end; end. thrift-0.19.0/lib/delphi/src/Thrift.Protocol.Multiplex.pas0000644000000000000000000000666514303740367023454 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Protocol.Multiplex; interface uses Thrift.Protocol; { TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift client to communicate with a multiplexing Thrift server, by prepending the service name to the function name during function calls. NOTE: THIS IS NOT USED BY SERVERS. On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. This example uses a single socket transport to invoke two services: TSocket transport = new TSocket("localhost", 9090); transport.open(); TBinaryProtocol protocol = new TBinaryProtocol(transport); TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator"); Calculator.Client service = new Calculator.Client(mp); TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport"); WeatherReport.Client service2 = new WeatherReport.Client(mp2); System.out.println(service.add(2,2)); System.out.println(service2.getTemperature()); } type TMultiplexedProtocol = class( TProtocolDecorator) public const { Used to delimit the service name from the function name } SEPARATOR = ':'; strict private FServiceName : String; public { Wrap the specified protocol, allowing it to be used to communicate with a multiplexing server. The serviceName is required as it is prepended to the message header so that the multiplexing server can broker the function call to the proper service. Args: protocol ....... Your communication protocol of choice, e.g. TBinaryProtocol. serviceName .... The service name of the service communicating via this protocol. } constructor Create( const aProtocol : IProtocol; const aServiceName : string); { Prepends the service name to the function name, separated by SEPARATOR. Args: The original message. } procedure WriteMessageBegin( const msg: TThriftMessage); override; end; implementation constructor TMultiplexedProtocol.Create(const aProtocol: IProtocol; const aServiceName: string); begin ASSERT( aServiceName <> ''); inherited Create(aProtocol); FServiceName := aServiceName; end; procedure TMultiplexedProtocol.WriteMessageBegin( const msg: TThriftMessage); // Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR. var newMsg : TThriftMessage; begin case msg.Type_ of TMessageType.Call, TMessageType.Oneway : begin Init( newMsg, FServiceName + SEPARATOR + msg.Name, msg.Type_, msg.SeqID); inherited WriteMessageBegin( newMsg); end; else inherited WriteMessageBegin( msg); end; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Transport.pas0000644000000000000000000014327614370300523021653 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Transport; {$I Thrift.Defines.inc} {$SCOPEDENUMS ON} interface uses Classes, SysUtils, Math, Generics.Collections, {$IFDEF OLD_UNIT_NAMES} WinSock, Sockets, {$ELSE} Winapi.WinSock, {$IFDEF OLD_SOCKETS} Web.Win.Sockets, {$ELSE} Thrift.Socket, {$ENDIF} {$ENDIF} Thrift.Configuration, Thrift.Collections, Thrift.Exception, Thrift.Utils, Thrift.WinHTTP, Thrift.Stream; type IStreamTransport = interface; ITransport = interface ['{52F81383-F880-492F-8AA7-A66B85B93D6B}'] function GetIsOpen: Boolean; property IsOpen: Boolean read GetIsOpen; function Peek: Boolean; procedure Open; procedure Close; function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload; function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload; function ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; procedure Write( const buf: TBytes); overload; procedure Write( const buf: TBytes; off: Integer; len: Integer); overload; procedure Write( const pBuf : Pointer; off, len : Integer); overload; procedure Write( const pBuf : Pointer; len : Integer); overload; procedure Flush; function Configuration : IThriftConfiguration; function MaxMessageSize : Integer; procedure ResetConsumedMessageSize( const knownSize : Int64 = -1); procedure CheckReadBytesAvailable( const numBytes : Int64); procedure UpdateKnownMessageSize( const size : Int64); end; TTransportBase = class abstract( TInterfacedObject) strict protected function GetIsOpen: Boolean; virtual; abstract; property IsOpen: Boolean read GetIsOpen; function Peek: Boolean; virtual; procedure Open(); virtual; abstract; procedure Close(); virtual; abstract; function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline; function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual; abstract; function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline; function ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual; procedure Write( const buf: TBytes); overload; inline; procedure Write( const buf: TBytes; off: Integer; len: Integer); overload; inline; procedure Write( const pBuf : Pointer; len : Integer); overload; inline; procedure Write( const pBuf : Pointer; off, len : Integer); overload; virtual; abstract; procedure Flush; virtual; function Configuration : IThriftConfiguration; virtual; abstract; procedure UpdateKnownMessageSize( const size : Int64); virtual; abstract; end; // base class for all endpoint transports, e.g. sockets, pipes or HTTP TEndpointTransportBase = class abstract( TTransportBase, ITransport) strict private FRemainingMessageSize : Int64; FKnownMessageSize : Int64; FConfiguration : IThriftConfiguration; strict protected function Configuration : IThriftConfiguration; override; function MaxMessageSize : Integer; property RemainingMessageSize : Int64 read FRemainingMessageSize; property KnownMessageSize : Int64 read FKnownMessageSize; procedure ResetConsumedMessageSize( const newSize : Int64 = -1); procedure UpdateKnownMessageSize(const size : Int64); override; procedure CheckReadBytesAvailable(const numBytes : Int64); inline; procedure CountConsumedMessageBytes(const numBytes : Int64); inline; public constructor Create( const aConfig : IThriftConfiguration); reintroduce; end; // base class for all layered transports, e.g. framed TLayeredTransportBase = class abstract( TTransportBase, ITransport) strict private FTransport : T; strict protected property InnerTransport : T read FTransport; function GetUnderlyingTransport: ITransport; function Configuration : IThriftConfiguration; override; procedure UpdateKnownMessageSize( const size : Int64); override; function MaxMessageSize : Integer; inline; procedure ResetConsumedMessageSize( const knownSize : Int64 = -1); inline; procedure CheckReadBytesAvailable( const numBytes : Int64); virtual; public constructor Create( const aTransport: T); reintroduce; property UnderlyingTransport: ITransport read GetUnderlyingTransport; end; TTransportException = class abstract( TException) public type TExceptionType = ( Unknown, NotOpen, AlreadyOpen, TimedOut, EndOfFile, BadArgs, Interrupted, CorruptedData ); strict protected constructor HiddenCreate(const Msg: string); class function GetType: TExceptionType; virtual; abstract; public class function Create( aType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; class function Create( aType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; property Type_: TExceptionType read GetType; end; // Needed to remove deprecation warning TTransportExceptionSpecialized = class abstract (TTransportException) public constructor Create(const Msg: string); end; TTransportExceptionUnknown = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionNotOpen = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionTimedOut = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionBadArgs = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionInterrupted = class (TTransportExceptionSpecialized) strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionCorruptedData = class (TTransportExceptionSpecialized) protected class function GetType: TTransportException.TExceptionType; override; end; TSecureProtocol = ( SSL_2, SSL_3, TLS_1, // outdated, for compatibilty only TLS_1_1, TLS_1_2 // secure (as of today) ); TSecureProtocols = set of TSecureProtocol; IHTTPClient = interface( ITransport ) ['{7BF615DD-8680-4004-A5B2-88947BA3BA3D}'] procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; procedure SetConnectionTimeout(const Value: Integer); function GetConnectionTimeout: Integer; procedure SetSendTimeout(const Value: Integer); function GetSendTimeout: Integer; procedure SetReadTimeout(const Value: Integer); function GetReadTimeout: Integer; function GetCustomHeaders: IThriftDictionary; procedure SendRequest; function GetSecureProtocols : TSecureProtocols; procedure SetSecureProtocols( const value : TSecureProtocols); property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; property SecureProtocols : TSecureProtocols read GetSecureProtocols write SetSecureProtocols; end; IServerTransport = interface ['{FA01363F-6B40-482F-971E-4A085535EFC8}'] procedure Listen; procedure Close; function Accept( const fnAccepting: TProc): ITransport; function Configuration : IThriftConfiguration; end; TServerTransportImpl = class( TInterfacedObject, IServerTransport) strict private FConfig : IThriftConfiguration; strict protected function Configuration : IThriftConfiguration; procedure Listen; virtual; abstract; procedure Close; virtual; abstract; function Accept( const fnAccepting: TProc): ITransport; virtual; abstract; public constructor Create( const aConfig : IThriftConfiguration); end; ITransportFactory = interface ['{DD809446-000F-49E1-9BFF-E0D0DC76A9D7}'] function GetTransport( const aTransport: ITransport): ITransport; end; TTransportFactoryImpl = class ( TInterfacedObject, ITransportFactory) strict protected function GetTransport( const aTransport: ITransport): ITransport; virtual; end; TTcpSocketStreamImpl = class( TThriftStreamImpl) {$IFDEF OLD_SOCKETS} strict private type TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error); strict private FTcpClient : TCustomIpClient; FTimeout : Integer; function Select( ReadReady, WriteReady, ExceptFlag: PBoolean; TimeOut: Integer; var wsaError : Integer): Integer; function WaitForData( TimeOut : Integer; pBuf : Pointer; DesiredBytes: Integer; var wsaError, bytesReady : Integer): TWaitForData; {$ELSE} FTcpClient: TSocket; strict protected const SLEEP_TIME = 200; {$ENDIF} strict protected procedure Write( const pBuf : Pointer; offset, count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; public {$IFDEF OLD_SOCKETS} constructor Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer = DEFAULT_THRIFT_TIMEOUT); {$ELSE} constructor Create( const aTcpClient: TSocket; const aTimeout : Longword = DEFAULT_THRIFT_TIMEOUT); {$ENDIF} end; IStreamTransport = interface( ITransport ) ['{A8479B47-2A3E-4421-A9A0-D5A9EDCC634A}'] function GetInputStream: IThriftStream; function GetOutputStream: IThriftStream; property InputStream : IThriftStream read GetInputStream; property OutputStream : IThriftStream read GetOutputStream; end; TStreamTransportImpl = class( TEndpointTransportBase, IStreamTransport) strict protected FInputStream : IThriftStream; FOutputStream : IThriftStream; strict protected function GetIsOpen: Boolean; override; function GetInputStream: IThriftStream; function GetOutputStream: IThriftStream; strict protected procedure Open; override; procedure Close; override; procedure Flush; override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; public constructor Create( const aInputStream, aOutputStream : IThriftStream; const aConfig : IThriftConfiguration = nil); reintroduce; destructor Destroy; override; property InputStream : IThriftStream read GetInputStream; property OutputStream : IThriftStream read GetOutputStream; end; TBufferedStreamImpl = class( TThriftStreamImpl) strict private FStream : IThriftStream; FBufSize : Integer; FReadBuffer : TThriftMemoryStream; FWriteBuffer : TThriftMemoryStream; strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; function Size : Int64; override; function Position : Int64; override; public constructor Create( const aStream: IThriftStream; const aBufSize : Integer); destructor Destroy; override; end; TServerSocketImpl = class( TServerTransportImpl) strict private {$IFDEF OLD_SOCKETS} FServer : TTcpServer; FPort : Integer; FClientTimeout : Integer; {$ELSE} FServer: TServerSocket; {$ENDIF} FUseBufferedSocket : Boolean; FOwnsServer : Boolean; strict protected function Accept( const fnAccepting: TProc) : ITransport; override; public {$IFDEF OLD_SOCKETS} constructor Create( const aServer: TTcpServer; const aClientTimeout : Integer = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; constructor Create( const aPort: Integer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aConfig : IThriftConfiguration = nil); overload; {$ELSE} constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; constructor Create( const aPort: Integer; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aConfig : IThriftConfiguration = nil); overload; {$ENDIF} destructor Destroy; override; procedure Listen; override; procedure Close; override; end; TBufferedTransportImpl = class( TLayeredTransportBase) strict private FInputBuffer : IThriftStream; FOutputBuffer : IThriftStream; FBufSize : Integer; procedure InitBuffers; strict protected function GetIsOpen: Boolean; override; procedure Flush; override; public type TFactory = class( TTransportFactoryImpl ) public function GetTransport( const aTransport: ITransport): ITransport; override; end; constructor Create( const aTransport : IStreamTransport; const aBufSize: Integer = 1024); procedure Open(); override; procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure CheckReadBytesAvailable( const value : Int64); override; property IsOpen: Boolean read GetIsOpen; end; TSocketImpl = class(TStreamTransportImpl) strict private {$IFDEF OLD_SOCKETS} FClient : TCustomIpClient; {$ELSE} FClient: TSocket; {$ENDIF} FOwnsClient : Boolean; FHost : string; FPort : Integer; {$IFDEF OLD_SOCKETS} FTimeout : Integer; {$ELSE} FTimeout : Longword; {$ENDIF} procedure InitSocket; strict protected function GetIsOpen: Boolean; override; public {$IFDEF OLD_SOCKETS} constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; {$ELSE} constructor Create(const aClient: TSocket; const aOwnsClient: Boolean; const aConfig : IThriftConfiguration = nil); overload; constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; {$ENDIF} destructor Destroy; override; procedure Open; override; procedure Close; override; {$IFDEF OLD_SOCKETS} property TcpClient: TCustomIpClient read FClient; {$ELSE} property TcpClient: TSocket read FClient; {$ENDIF} property Host : string read FHost; property Port: Integer read FPort; end; TFramedTransportImpl = class( TLayeredTransportBase) strict protected type TFramedHeader = Int32; strict protected FWriteBuffer : TThriftMemoryStream; FReadBuffer : TThriftMemoryStream; procedure InitWriteBuffer; procedure ReadFrame; procedure Open(); override; function GetIsOpen: Boolean; override; procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure CheckReadBytesAvailable( const value : Int64); override; procedure Flush; override; public type TFactory = class( TTransportFactoryImpl ) public function GetTransport( const aTransport: ITransport): ITransport; override; end; constructor Create( const aTransport: ITransport); overload; destructor Destroy; override; end; const DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2]; implementation { TTransportBase } procedure TTransportBase.Flush; begin // nothing to do end; function TTransportBase.Peek: Boolean; begin Result := IsOpen; end; function TTransportBase.Read(var buf: TBytes; off: Integer; len: Integer): Integer; begin if Length(buf) > 0 then result := Read( @buf[0], Length(buf), off, len) else result := 0; end; function TTransportBase.ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; begin if Length(buf) > 0 then result := ReadAll( @buf[0], Length(buf), off, len) else result := 0; end; function TTransportBase.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; var ret : Integer; begin result := 0; while result < len do begin ret := Read( pBuf, buflen, off + result, len - result); if ret > 0 then Inc( result, ret) else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' ); end; end; procedure TTransportBase.Write( const buf: TBytes); begin if Length(buf) > 0 then Write( @buf[0], 0, Length(buf)); end; procedure TTransportBase.Write( const buf: TBytes; off: Integer; len: Integer); begin if Length(buf) > 0 then Write( @buf[0], off, len); end; procedure TTransportBase.Write( const pBuf : Pointer; len : Integer); begin Self.Write( pBuf, 0, len); end; { TEndpointTransportBase } constructor TEndpointTransportBase.Create( const aConfig : IThriftConfiguration); begin inherited Create; if aConfig <> nil then FConfiguration := aConfig else FConfiguration := TThriftConfigurationImpl.Create; ResetConsumedMessageSize; end; function TEndpointTransportBase.Configuration : IThriftConfiguration; begin result := FConfiguration; end; function TEndpointTransportBase.MaxMessageSize : Integer; begin ASSERT( Configuration <> nil); result := Configuration.MaxMessageSize; end; procedure TEndpointTransportBase.ResetConsumedMessageSize( const newSize : Int64); // Resets RemainingMessageSize to the configured maximum begin // full reset if newSize < 0 then begin FKnownMessageSize := MaxMessageSize; FRemainingMessageSize := MaxMessageSize; Exit; end; // update only: message size can shrink, but not grow ASSERT( KnownMessageSize <= MaxMessageSize); if newSize > KnownMessageSize then raise TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); FKnownMessageSize := newSize; FRemainingMessageSize := newSize; end; procedure TEndpointTransportBase.UpdateKnownMessageSize( const size : Int64); // Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). // Will throw if we already consumed too many bytes. var consumed : Int64; begin consumed := KnownMessageSize - RemainingMessageSize; ResetConsumedMessageSize(size); CountConsumedMessageBytes(consumed); end; procedure TEndpointTransportBase.CheckReadBytesAvailable( const numBytes : Int64); // Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data begin if (RemainingMessageSize < numBytes) or (numBytes < 0) then raise TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); end; procedure TEndpointTransportBase.CountConsumedMessageBytes( const numBytes : Int64); // Consumes numBytes from the RemainingMessageSize. begin if (RemainingMessageSize >= numBytes) and (numBytes >= 0) then Dec( FRemainingMessageSize, numBytes) else begin FRemainingMessageSize := 0; raise TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); end; end; { TLayeredTransportBase } constructor TLayeredTransportBase.Create( const aTransport: T); begin inherited Create; FTransport := aTransport; end; function TLayeredTransportBase.GetUnderlyingTransport: ITransport; begin result := InnerTransport; end; function TLayeredTransportBase.Configuration : IThriftConfiguration; begin result := InnerTransport.Configuration; end; procedure TLayeredTransportBase.UpdateKnownMessageSize( const size : Int64); begin InnerTransport.UpdateKnownMessageSize( size); end; function TLayeredTransportBase.MaxMessageSize : Integer; begin result := InnerTransport.MaxMessageSize; end; procedure TLayeredTransportBase.ResetConsumedMessageSize( const knownSize : Int64 = -1); begin InnerTransport.ResetConsumedMessageSize( knownSize); end; procedure TLayeredTransportBase.CheckReadBytesAvailable( const numBytes : Int64); begin InnerTransport.CheckReadBytesAvailable( numBytes); end; { TTransportException } constructor TTransportException.HiddenCreate(const Msg: string); begin inherited Create(Msg); end; class function TTransportException.Create(aType: TExceptionType): TTransportException; begin //no inherited; {$WARN SYMBOL_DEPRECATED OFF} Result := Create(aType, '') {$WARN SYMBOL_DEPRECATED DEFAULT} end; class function TTransportException.Create(aType: TExceptionType; const msg: string): TTransportException; begin case aType of TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg); TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg); TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg); TExceptionType.EndOfFile: Result := TTransportExceptionEndOfFile.Create(msg); TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg); TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg); else ASSERT( TExceptionType.Unknown = aType); Result := TTransportExceptionUnknown.Create(msg); end; end; class function TTransportException.Create(const msg: string): TTransportException; begin Result := TTransportExceptionUnknown.Create(Msg); end; { TTransportExceptionSpecialized } constructor TTransportExceptionSpecialized.Create(const Msg: string); begin inherited HiddenCreate(Msg); end; { specialized TTransportExceptions } class function TTransportExceptionUnknown.GetType: TTransportException.TExceptionType; begin result := TExceptionType.Unknown; end; class function TTransportExceptionNotOpen.GetType: TTransportException.TExceptionType; begin result := TExceptionType.NotOpen; end; class function TTransportExceptionAlreadyOpen.GetType: TTransportException.TExceptionType; begin result := TExceptionType.AlreadyOpen; end; class function TTransportExceptionTimedOut.GetType: TTransportException.TExceptionType; begin result := TExceptionType.TimedOut; end; class function TTransportExceptionEndOfFile.GetType: TTransportException.TExceptionType; begin result := TExceptionType.EndOfFile; end; class function TTransportExceptionBadArgs.GetType: TTransportException.TExceptionType; begin result := TExceptionType.BadArgs; end; class function TTransportExceptionInterrupted.GetType: TTransportException.TExceptionType; begin result := TExceptionType.Interrupted; end; class function TTransportExceptionCorruptedData.GetType: TTransportException.TExceptionType; begin result := TExceptionType.CorruptedData; end; { TTransportFactoryImpl } function TTransportFactoryImpl.GetTransport( const aTransport: ITransport): ITransport; begin Result := aTransport; end; { TServerTransportImpl } constructor TServerTransportImpl.Create( const aConfig : IThriftConfiguration); begin inherited Create; if aConfig <> nil then FConfig := aConfig else FConfig := TThriftConfigurationImpl.Create; end; function TServerTransportImpl.Configuration : IThriftConfiguration; begin result := FConfig; end; { TServerSocket } {$IFDEF OLD_SOCKETS} constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer; const aConfig : IThriftConfiguration); {$ELSE} constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword; const aConfig : IThriftConfiguration); {$ENDIF} begin inherited Create( aConfig); FServer := aServer; {$IFDEF OLD_SOCKETS} FClientTimeout := aClientTimeout; {$ELSE} FServer.RecvTimeout := aClientTimeout; FServer.SendTimeout := aClientTimeout; {$ENDIF} end; {$IFDEF OLD_SOCKETS} constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; aUseBufferedSockets: Boolean; const aConfig : IThriftConfiguration); {$ELSE} constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; aUseBufferedSockets: Boolean; const aConfig : IThriftConfiguration); {$ENDIF} begin inherited Create( aConfig); {$IFDEF OLD_SOCKETS} FPort := aPort; FClientTimeout := aClientTimeout; FOwnsServer := True; FServer := TTcpServer.Create( nil ); FServer.BlockMode := bmBlocking; {$IF CompilerVersion >= 21.0} FServer.LocalPort := AnsiString( IntToStr( FPort)); {$ELSE} FServer.LocalPort := IntToStr( FPort); {$IFEND} {$ELSE} FOwnsServer := True; FServer := TServerSocket.Create(aPort, aClientTimeout, aClientTimeout); {$ENDIF} FUseBufferedSocket := aUseBufferedSockets; end; destructor TServerSocketImpl.Destroy; begin if FOwnsServer then begin FServer.Free; FServer := nil; end; inherited; end; function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport; var {$IFDEF OLD_SOCKETS} client : TCustomIpClient; {$ELSE} client: TSocket; {$ENDIF} trans : IStreamTransport; begin if FServer = nil then begin raise TTransportExceptionNotOpen.Create('No underlying server socket.'); end; {$IFDEF OLD_SOCKETS} client := nil; try client := TCustomIpClient.Create(nil); if Assigned(fnAccepting) then fnAccepting(); if not FServer.Accept( client) then begin client.Free; Result := nil; Exit; end; if client = nil then begin Result := nil; Exit; end; trans := TSocketImpl.Create( client, TRUE, FClientTimeout, Configuration); client := nil; // trans owns it now if FUseBufferedSocket then result := TBufferedTransportImpl.Create( trans) else result := trans; except on E: Exception do begin client.Free; raise TTransportExceptionUnknown.Create(E.ToString); end; end; {$ELSE} if Assigned(fnAccepting) then fnAccepting(); client := FServer.Accept; try trans := TSocketImpl.Create(client, TRUE, Configuration); client := nil; if FUseBufferedSocket then Result := TBufferedTransportImpl.Create(trans) else Result := trans; except client.Free; raise; end; {$ENDIF} end; procedure TServerSocketImpl.Listen; begin if FServer <> nil then begin {$IFDEF OLD_SOCKETS} try FServer.Active := True; except on E: Exception do raise TTransportExceptionUnknown.Create('Could not accept on listening socket: ' + E.Message); end; {$ELSE} FServer.Listen; {$ENDIF} end; end; procedure TServerSocketImpl.Close; begin if FServer <> nil then {$IFDEF OLD_SOCKETS} try FServer.Active := False; except on E: Exception do raise TTransportExceptionUnknown.Create('Error on closing socket : ' + E.Message); end; {$ELSE} FServer.Close; {$ENDIF} end; { TSocket } {$IFDEF OLD_SOCKETS} constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer; const aConfig : IThriftConfiguration); {$ELSE} constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean; const aConfig : IThriftConfiguration); {$ENDIF} var stream : IThriftStream; begin FClient := aClient; FOwnsClient := aOwnsClient; {$IFDEF OLD_SOCKETS} FTimeout := aTimeout; {$ELSE} FTimeout := aClient.RecvTimeout; {$ENDIF} stream := TTcpSocketStreamImpl.Create( FClient, FTimeout); inherited Create( stream, stream, aConfig); end; {$IFDEF OLD_SOCKETS} constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer; const aConfig : IThriftConfiguration); {$ELSE} constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword; const aConfig : IThriftConfiguration); {$ENDIF} begin inherited Create(nil,nil, aConfig); FHost := aHost; FPort := aPort; FTimeout := aTimeout; InitSocket; end; destructor TSocketImpl.Destroy; begin if FOwnsClient then FreeAndNil( FClient); inherited; end; procedure TSocketImpl.Close; begin inherited Close; FInputStream := nil; FOutputStream := nil; if FOwnsClient then FreeAndNil( FClient) else FClient := nil; end; function TSocketImpl.GetIsOpen: Boolean; begin {$IFDEF OLD_SOCKETS} Result := (FClient <> nil) and FClient.Connected; {$ELSE} Result := (FClient <> nil) and FClient.IsOpen {$ENDIF} end; procedure TSocketImpl.InitSocket; var stream : IThriftStream; begin if FOwnsClient then FreeAndNil( FClient) else FClient := nil; {$IFDEF OLD_SOCKETS} FClient := TTcpClient.Create( nil); {$ELSE} FClient := TSocket.Create(FHost, FPort); {$ENDIF} FOwnsClient := True; stream := TTcpSocketStreamImpl.Create( FClient, FTimeout); FInputStream := stream; FOutputStream := stream; end; procedure TSocketImpl.Open; begin if IsOpen then begin raise TTransportExceptionAlreadyOpen.Create('Socket already connected'); end; if FHost = '' then begin raise TTransportExceptionNotOpen.Create('Cannot open null host'); end; if Port <= 0 then begin raise TTransportExceptionNotOpen.Create('Cannot open without port'); end; if FClient = nil then InitSocket; {$IFDEF OLD_SOCKETS} FClient.RemoteHost := TSocketHost( Host); FClient.RemotePort := TSocketPort( IntToStr( Port)); FClient.Connect; {$ELSE} FClient.Open; {$ENDIF} FInputStream := TTcpSocketStreamImpl.Create( FClient, FTimeout); FOutputStream := FInputStream; end; { TBufferedStream } procedure TBufferedStreamImpl.Close; begin Flush; FStream := nil; FReadBuffer.Free; FReadBuffer := nil; FWriteBuffer.Free; FWriteBuffer := nil; end; constructor TBufferedStreamImpl.Create( const aStream: IThriftStream; const aBufSize : Integer); begin inherited Create; FStream := aStream; FBufSize := aBufSize; FReadBuffer := TThriftMemoryStream.Create(FBufSize); FWriteBuffer := TThriftMemoryStream.Create(FBufSize); end; destructor TBufferedStreamImpl.Destroy; begin Close; inherited; end; procedure TBufferedStreamImpl.Flush; var buf : TBytes; len : Integer; begin if IsOpen then begin len := FWriteBuffer.Size; if len > 0 then begin SetLength( buf, len ); FWriteBuffer.Position := 0; FWriteBuffer.Read( Pointer(@buf[0])^, len ); FStream.Write( buf, 0, len ); end; FWriteBuffer.Clear; end; end; function TBufferedStreamImpl.IsOpen: Boolean; begin Result := (FWriteBuffer <> nil) and (FReadBuffer <> nil) and (FStream <> nil) and FStream.IsOpen; end; procedure TBufferedStreamImpl.Open; begin FStream.Open; end; function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; var nRead : Integer; tempbuf : TBytes; pTmp : PByte; begin inherited; Result := 0; if IsOpen then begin while count > 0 do begin if FReadBuffer.Position >= FReadBuffer.Size then begin FReadBuffer.Clear; SetLength( tempbuf, FBufSize); nRead := FStream.Read( tempbuf, 0, FBufSize ); if nRead = 0 then Break; // avoid infinite loop FReadBuffer.WriteBuffer( Pointer(@tempbuf[0])^, nRead ); FReadBuffer.Position := 0; end; if FReadBuffer.Position < FReadBuffer.Size then begin nRead := Min( FReadBuffer.Size - FReadBuffer.Position, count); pTmp := pBuf; Inc( pTmp, offset); Inc( Result, FReadBuffer.Read( pTmp^, nRead)); Dec( count, nRead); Inc( offset, nRead); end; end; end; end; function TBufferedStreamImpl.ToArray: TBytes; var len : Integer; begin if IsOpen then len := FReadBuffer.Size else len := 0; SetLength( Result, len); if len > 0 then begin FReadBuffer.Position := 0; FReadBuffer.Read( Pointer(@Result[0])^, len ); end; end; procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: Integer); var pTmp : PByte; begin inherited; if count > 0 then begin if IsOpen then begin pTmp := pBuf; Inc( pTmp, offset); FWriteBuffer.Write( pTmp^, count ); if FWriteBuffer.Size > FBufSize then begin Flush; end; end; end; end; function TBufferedStreamImpl.Size : Int64; begin result := FReadBuffer.Size; end; function TBufferedStreamImpl.Position : Int64; begin result := FReadBuffer.Position; end; { TStreamTransportImpl } constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream; const aConfig : IThriftConfiguration); begin inherited Create( aConfig); FInputStream := aInputStream; FOutputStream := aOutputStream; end; destructor TStreamTransportImpl.Destroy; begin FInputStream := nil; FOutputStream := nil; inherited; end; procedure TStreamTransportImpl.Close; begin FInputStream := nil; FOutputStream := nil; end; procedure TStreamTransportImpl.Flush; begin if FOutputStream = nil then begin raise TTransportExceptionNotOpen.Create('Cannot flush null outputstream' ); end; FOutputStream.Flush; end; function TStreamTransportImpl.GetInputStream: IThriftStream; begin Result := FInputStream; end; function TStreamTransportImpl.GetIsOpen: Boolean; begin Result := True; end; function TStreamTransportImpl.GetOutputStream: IThriftStream; begin Result := FOutputStream; end; procedure TStreamTransportImpl.Open; begin // nothing to do end; function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); Result := FInputStream.Read( pBuf,buflen, off, len ); CountConsumedMessageBytes( result); end; procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer); begin if FOutputStream = nil then raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' ); FOutputStream.Write( pBuf, off, len ); end; { TBufferedTransportImpl } constructor TBufferedTransportImpl.Create( const aTransport : IStreamTransport; const aBufSize: Integer); begin ASSERT( aTransport <> nil); inherited Create( aTransport); FBufSize := aBufSize; InitBuffers; end; procedure TBufferedTransportImpl.Close; begin InnerTransport.Close; FInputBuffer := nil; FOutputBuffer := nil; end; procedure TBufferedTransportImpl.Flush; begin if FOutputBuffer <> nil then begin FOutputBuffer.Flush; end; end; function TBufferedTransportImpl.GetIsOpen: Boolean; begin Result := InnerTransport.IsOpen; end; procedure TBufferedTransportImpl.InitBuffers; begin if InnerTransport.InputStream <> nil then begin FInputBuffer := TBufferedStreamImpl.Create( InnerTransport.InputStream, FBufSize ); end; if InnerTransport.OutputStream <> nil then begin FOutputBuffer := TBufferedStreamImpl.Create( InnerTransport.OutputStream, FBufSize ); end; end; procedure TBufferedTransportImpl.Open; begin InnerTransport.Open; InitBuffers; // we need to get the buffers to match FTransport substreams again end; function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputBuffer <> nil then Result := FInputBuffer.Read( pBuf,buflen, off, len ) else Result := 0; end; procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer); begin if FOutputBuffer <> nil then begin FOutputBuffer.Write( pBuf, off, len ); end; end; procedure TBufferedTransportImpl.CheckReadBytesAvailable( const value : Int64); var buffered, need : Int64; begin need := value; // buffered bytes buffered := FInputBuffer.Size - FInputBuffer.Position; if buffered < need then InnerTransport.CheckReadBytesAvailable( need - buffered); end; { TBufferedTransportImpl.TFactory } function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; begin Result := TFramedTransportImpl.Create( aTransport); end; { TFramedTransportImpl } constructor TFramedTransportImpl.Create( const aTransport: ITransport); begin ASSERT( aTransport <> nil); inherited Create( aTransport); InitWriteBuffer; end; destructor TFramedTransportImpl.Destroy; begin FWriteBuffer.Free; FWriteBuffer := nil; FReadBuffer.Free; FReadBuffer := nil; inherited; end; procedure TFramedTransportImpl.Close; begin InnerTransport.Close; end; procedure TFramedTransportImpl.Flush; var buf : TBytes; len : Integer; data_len : Int64; begin if not IsOpen then raise TTransportExceptionNotOpen.Create('not open'); len := FWriteBuffer.Size; SetLength( buf, len); if len > 0 then begin System.Move( FWriteBuffer.Memory^, buf[0], len ); end; data_len := len - SizeOf(TFramedHeader); if (0 > data_len) or (data_len > Configuration.MaxFrameSize) then raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: invalid frame size ('+IntToStr(data_len)+')') else UpdateKnownMessageSize( len); InitWriteBuffer; buf[0] := Byte($FF and (data_len shr 24)); buf[1] := Byte($FF and (data_len shr 16)); buf[2] := Byte($FF and (data_len shr 8)); buf[3] := Byte($FF and data_len); InnerTransport.Write( buf, 0, len ); InnerTransport.Flush; end; function TFramedTransportImpl.GetIsOpen: Boolean; begin Result := InnerTransport.IsOpen; end; procedure TFramedTransportImpl.InitWriteBuffer; const DUMMY_HEADER : TFramedHeader = 0; begin FreeAndNil( FWriteBuffer); FWriteBuffer := TThriftMemoryStream.Create(1024); FWriteBuffer.Write( DUMMY_HEADER, SizeOf(DUMMY_HEADER)); end; procedure TFramedTransportImpl.Open; begin InnerTransport.Open; end; function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; var pTmp : PByte; begin if len > (buflen-off) then len := buflen-off; pTmp := pBuf; Inc( pTmp, off); if (FReadBuffer <> nil) and (len > 0) then begin result := FReadBuffer.Read( pTmp^, len); if result > 0 then Exit; end; ReadFrame; if len > 0 then Result := FReadBuffer.Read( pTmp^, len) else Result := 0; end; procedure TFramedTransportImpl.ReadFrame; var i32rd : packed array[0..SizeOf(TFramedHeader)-1] of Byte; size : Integer; buff : TBytes; begin InnerTransport.ReadAll( @i32rd[0], SizeOf(i32rd), 0, SizeOf(i32rd)); size := ((i32rd[0] and $FF) shl 24) or ((i32rd[1] and $FF) shl 16) or ((i32rd[2] and $FF) shl 8) or (i32rd[3] and $FF); if size < 0 then begin Close(); raise TTransportExceptionCorruptedData.Create('Read a negative frame size ('+IntToStr(size)+')'); end; if Int64(size) > Int64(Configuration.MaxFrameSize) then begin Close(); if CharUtils.IsHtmlDoctype(size) then raise TTransportExceptionCorruptedData.Create('Remote end sends HTML instead of data') else raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(Configuration.MaxFrameSize)+')'); end; UpdateKnownMessageSize(size + SizeOf(size)); SetLength( buff, size ); InnerTransport.ReadAll( buff, 0, size ); FreeAndNil( FReadBuffer); FReadBuffer := TThriftMemoryStream.Create(1024); if Length(buff) > 0 then FReadBuffer.Write( Pointer(@buff[0])^, size ); FReadBuffer.Position := 0; end; procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer); var pTmp : PByte; begin if len > 0 then begin pTmp := pBuf; Inc( pTmp, off); FWriteBuffer.Write( pTmp^, len ); end; end; procedure TFramedTransportImpl.CheckReadBytesAvailable( const value : Int64); var buffered, need : Int64; begin need := value; // buffered bytes buffered := FReadBuffer.Size - FReadBuffer.Position; if buffered < need then InnerTransport.CheckReadBytesAvailable( need - buffered); end; { TFramedTransport.TFactory } function TFramedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; begin Result := TFramedTransportImpl.Create( aTransport); end; { TTcpSocketStreamImpl } procedure TTcpSocketStreamImpl.Close; begin FTcpClient.Close; end; {$IFDEF OLD_SOCKETS} constructor TTcpSocketStreamImpl.Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer); begin inherited Create; FTcpClient := aTcpClient; FTimeout := aTimeout; end; {$ELSE} constructor TTcpSocketStreamImpl.Create( const aTcpClient: TSocket; const aTimeout : Longword); begin inherited Create; FTcpClient := aTcpClient; if aTimeout = 0 then FTcpClient.RecvTimeout := SLEEP_TIME else FTcpClient.RecvTimeout := aTimeout; FTcpClient.SendTimeout := aTimeout; end; {$ENDIF} procedure TTcpSocketStreamImpl.Flush; begin // nothing to do end; function TTcpSocketStreamImpl.IsOpen: Boolean; begin {$IFDEF OLD_SOCKETS} Result := FTcpClient.Active; {$ELSE} Result := FTcpClient.IsOpen; {$ENDIF} end; procedure TTcpSocketStreamImpl.Open; begin FTcpClient.Open; end; {$IFDEF OLD_SOCKETS} function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolean; TimeOut: Integer; var wsaError : Integer): Integer; var ReadFds: TFDset; ReadFdsptr: PFDset; WriteFds: TFDset; WriteFdsptr: PFDset; ExceptFds: TFDset; ExceptFdsptr: PFDset; tv: timeval; Timeptr: PTimeval; socket : TSocket; begin if not FTcpClient.Active then begin wsaError := WSAEINVAL; Exit( SOCKET_ERROR); end; socket := FTcpClient.Handle; if Assigned(ReadReady) then begin ReadFdsptr := @ReadFds; FD_ZERO(ReadFds); FD_SET(socket, ReadFds); end else begin ReadFdsptr := nil; end; if Assigned(WriteReady) then begin WriteFdsptr := @WriteFds; FD_ZERO(WriteFds); FD_SET(socket, WriteFds); end else begin WriteFdsptr := nil; end; if Assigned(ExceptFlag) then begin ExceptFdsptr := @ExceptFds; FD_ZERO(ExceptFds); FD_SET(socket, ExceptFds); end else begin ExceptFdsptr := nil; end; if TimeOut >= 0 then begin tv.tv_sec := TimeOut div 1000; tv.tv_usec := 1000 * (TimeOut mod 1000); Timeptr := @tv; end else begin Timeptr := nil; // wait forever end; wsaError := 0; try {$IFDEF MSWINDOWS} {$IFDEF OLD_UNIT_NAMES} result := WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr); {$ELSE} result := Winapi.WinSock.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr); {$ENDIF} {$ENDIF} {$IFDEF LINUX} result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr); {$ENDIF} if result = SOCKET_ERROR then wsaError := WSAGetLastError; except result := SOCKET_ERROR; end; if Assigned(ReadReady) then ReadReady^ := FD_ISSET(socket, ReadFds); if Assigned(WriteReady) then WriteReady^ := FD_ISSET(socket, WriteFds); if Assigned(ExceptFlag) then ExceptFlag^ := FD_ISSET(socket, ExceptFds); end; {$ENDIF} {$IFDEF OLD_SOCKETS} function TTcpSocketStreamImpl.WaitForData( TimeOut : Integer; pBuf : Pointer; DesiredBytes : Integer; var wsaError, bytesReady : Integer): TWaitForData; var bCanRead, bError : Boolean; retval : Integer; const MSG_PEEK = {$IFDEF OLD_UNIT_NAMES} WinSock.MSG_PEEK {$ELSE} Winapi.WinSock.MSG_PEEK {$ENDIF}; begin bytesReady := 0; // The select function returns the total number of socket handles that are ready // and contained in the fd_set structures, zero if the time limit expired, // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, // WSAGetLastError can be used to retrieve a specific error code. retval := Self.Select( @bCanRead, nil, @bError, TimeOut, wsaError); if retval = SOCKET_ERROR then Exit( TWaitForData.wfd_Error); if (retval = 0) or not bCanRead then Exit( TWaitForData.wfd_Timeout); // recv() returns the number of bytes received, or -1 if an error occurred. // The return value will be 0 when the peer has performed an orderly shutdown. retval := recv( FTcpClient.Handle, pBuf^, DesiredBytes, MSG_PEEK); if retval <= 0 then Exit( TWaitForData.wfd_Error); // at least we have some data bytesReady := Min( retval, DesiredBytes); result := TWaitForData.wfd_HaveData; end; {$ENDIF} {$IFDEF OLD_SOCKETS} function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; // old sockets version var wfd : TWaitForData; wsaError, msecs : Integer; nBytes : Integer; pTmp : PByte; begin inherited; if FTimeout > 0 then msecs := FTimeout else msecs := DEFAULT_THRIFT_TIMEOUT; result := 0; pTmp := pBuf; Inc( pTmp, offset); while (count > 0) and (result = 0) do begin while TRUE do begin wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes); case wfd of TWaitForData.wfd_Error : Exit; TWaitForData.wfd_HaveData : Break; TWaitForData.wfd_Timeout : begin if (FTimeout = 0) then Exit else raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError))); end; else ASSERT( FALSE); end; end; // reduce the timeout once we got data if FTimeout > 0 then msecs := FTimeout div 10 else msecs := DEFAULT_THRIFT_TIMEOUT div 10; msecs := Max( msecs, 200); ASSERT( nBytes <= count); nBytes := FTcpClient.ReceiveBuf( pTmp^, nBytes); Inc( pTmp, nBytes); Dec( count, nBytes); Inc( result, nBytes); end; end; function TTcpSocketStreamImpl.ToArray: TBytes; // old sockets version var len : Integer; begin len := 0; if IsOpen then begin len := FTcpClient.BytesReceived; end; SetLength( Result, len ); if len > 0 then begin FTcpClient.ReceiveBuf( Pointer(@Result[0])^, len); end; end; procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer); // old sockets version var bCanWrite, bError : Boolean; retval, wsaError : Integer; pTmp : PByte; begin inherited; if not FTcpClient.Active then raise TTransportExceptionNotOpen.Create('not open'); // The select function returns the total number of socket handles that are ready // and contained in the fd_set structures, zero if the time limit expired, // or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, // WSAGetLastError can be used to retrieve a specific error code. retval := Self.Select( nil, @bCanWrite, @bError, FTimeOut, wsaError); if retval = SOCKET_ERROR then raise TTransportExceptionUnknown.Create(SysErrorMessage(Cardinal(wsaError))); if (retval = 0) then raise TTransportExceptionTimedOut.Create('timed out'); if bError or not bCanWrite then raise TTransportExceptionUnknown.Create('unknown error'); pTmp := pBuf; Inc( pTmp, offset); FTcpClient.SendBuf( pTmp^, count); end; {$ELSE} function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; // new sockets version var nBytes : Integer; pTmp : PByte; begin inherited; result := 0; pTmp := pBuf; Inc( pTmp, offset); while count > 0 do begin nBytes := FTcpClient.Read( pTmp^, count); if nBytes = 0 then Exit; Inc( pTmp, nBytes); Dec( count, nBytes); Inc( result, nBytes); end; end; function TTcpSocketStreamImpl.ToArray: TBytes; // new sockets version var len : Integer; begin len := 0; try if FTcpClient.Peek then repeat SetLength(Result, Length(Result) + 1024); len := FTcpClient.Read(Result[Length(Result) - 1024], 1024); until len < 1024; except on TTransportException do begin { don't allow default exceptions } end; else raise; end; if len > 0 then SetLength(Result, Length(Result) - 1024 + len); end; procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integer); // new sockets version var pTmp : PByte; begin inherited; if not FTcpClient.IsOpen then raise TTransportExceptionNotOpen.Create('not open'); pTmp := pBuf; Inc( pTmp, offset); FTcpClient.Write( pTmp^, count); end; {$ENDIF} end. thrift-0.19.0/lib/delphi/src/Thrift.pas0000644000000000000000000002703514454461475017673 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift; interface uses SysUtils, Thrift.Utils, Thrift.Exception, Thrift.Protocol; const Version = '0.19.0'; type TException = Thrift.Exception.TException; // compatibility alias TApplicationExceptionSpecializedClass = class of TApplicationExceptionSpecialized; TApplicationException = class( TException, IBase, ISupportsToString) public type {$SCOPEDENUMS ON} TExceptionType = ( Unknown, UnknownMethod, InvalidMessageType, WrongMethodName, BadSequenceID, MissingResult, InternalError, ProtocolError, InvalidTransform, InvalidProtocol, UnsupportedClientType ); {$SCOPEDENUMS OFF} strict private FExceptionType : TExceptionType; strict protected function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; strict protected constructor HiddenCreate(const Msg: string); class function GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; public // purposefully hide inherited constructor class function Create(const Msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; class function Create: TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; class function Create( AType: TExceptionType): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; class function Create( AType: TExceptionType; const msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; function Type_: TExceptionType; virtual; procedure IBase_Read( const iprot: IProtocol); procedure IBase.Read = IBase_Read; class function Read( const iprot: IProtocol): TApplicationException; procedure Write( const oprot: IProtocol ); end; // Needed to remove deprecation warning TApplicationExceptionSpecialized = class abstract (TApplicationException) strict protected class function GetType: TApplicationException.TExceptionType; virtual; abstract; public constructor Create(const Msg: string); function Type_: TApplicationException.TExceptionType; override; end; TApplicationExceptionUnknown = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionUnknownMethod = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInvalidMessageType = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionWrongMethodName = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionBadSequenceID = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionMissingResult = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInternalError = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionProtocolError = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInvalidTransform = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInvalidProtocol = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionUnsupportedClientType = class (TApplicationExceptionSpecialized) strict protected class function GetType: TApplicationException.TExceptionType; override; end; implementation { TApplicationException } constructor TApplicationException.HiddenCreate(const Msg: string); begin inherited Create(Msg); end; class function TApplicationException.Create(const Msg: string): TApplicationException; begin Result := TApplicationExceptionUnknown.Create(Msg); end; class function TApplicationException.Create: TApplicationException; begin Result := TApplicationExceptionUnknown.Create(''); end; class function TApplicationException.Create( AType: TExceptionType): TApplicationException; begin {$WARN SYMBOL_DEPRECATED OFF} Result := Create(AType, ''); {$WARN SYMBOL_DEPRECATED DEFAULT} end; class function TApplicationException.Create( AType: TExceptionType; const msg: string): TApplicationException; begin Result := GetSpecializedExceptionType(AType).Create(msg); end; function TApplicationException.QueryInterface(const IID: TGUID; out Obj): HResult; begin if GetInterface(IID, Obj) then result := S_OK else result := E_NOINTERFACE; end; function TApplicationException._AddRef: Integer; begin result := -1; // not refcounted end; function TApplicationException._Release: Integer; begin result := -1; // not refcounted end; function TApplicationException.Type_: TExceptionType; begin result := FExceptionType; end; class function TApplicationException.GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; begin case AType of TExceptionType.UnknownMethod: Result := TApplicationExceptionUnknownMethod; TExceptionType.InvalidMessageType: Result := TApplicationExceptionInvalidMessageType; TExceptionType.WrongMethodName: Result := TApplicationExceptionWrongMethodName; TExceptionType.BadSequenceID: Result := TApplicationExceptionBadSequenceID; TExceptionType.MissingResult: Result := TApplicationExceptionMissingResult; TExceptionType.InternalError: Result := TApplicationExceptionInternalError; TExceptionType.ProtocolError: Result := TApplicationExceptionProtocolError; TExceptionType.InvalidTransform: Result := TApplicationExceptionInvalidTransform; TExceptionType.InvalidProtocol: Result := TApplicationExceptionInvalidProtocol; TExceptionType.UnsupportedClientType: Result := TApplicationExceptionUnsupportedClientType; else ASSERT( TExceptionType.Unknown = aType); Result := TApplicationExceptionUnknown; end; end; procedure TApplicationException.IBase_Read( const iprot: IProtocol); var field : TThriftField; struc : TThriftStruct; begin struc := iprot.ReadStructBegin; while ( True ) do begin field := iprot.ReadFieldBegin; if ( field.Type_ = TType.Stop) then begin Break; end; case field.Id of 1 : begin if ( field.Type_ = TType.String_) then begin Exception(Self).Message := iprot.ReadString; end else begin TProtocolUtil.Skip( iprot, field.Type_ ); end; end; 2 : begin if ( field.Type_ = TType.I32) then begin FExceptionType := TExceptionType( iprot.ReadI32 ); end else begin TProtocolUtil.Skip( iprot, field.Type_ ); end; end else begin TProtocolUtil.Skip( iprot, field.Type_); end; end; iprot.ReadFieldEnd; end; iprot.ReadStructEnd; end; class function TApplicationException.Read( const iprot: IProtocol): TApplicationException; var instance : TApplicationException; base : IBase; begin instance := TApplicationException.CreateFmt('',[]); try if Supports( instance, IBase, base) then try base.Read(iprot); finally base := nil; // clear ref before free end; result := GetSpecializedExceptionType(instance.Type_).Create( Exception(instance).Message); finally instance.Free; end; end; procedure TApplicationException.Write( const oprot: IProtocol); var struc : TThriftStruct; field : TThriftField; begin Init(struc, 'TApplicationException'); Init(field); oprot.WriteStructBegin( struc ); if Message <> '' then begin field.Name := 'message'; field.Type_ := TType.String_; field.Id := 1; oprot.WriteFieldBegin( field ); oprot.WriteString( Message ); oprot.WriteFieldEnd; end; field.Name := 'type'; field.Type_ := TType.I32; field.Id := 2; oprot.WriteFieldBegin(field); oprot.WriteI32(Integer(Type_)); oprot.WriteFieldEnd(); oprot.WriteFieldStop(); oprot.WriteStructEnd(); end; { TApplicationExceptionSpecialized } constructor TApplicationExceptionSpecialized.Create(const Msg: string); begin inherited HiddenCreate(Msg); end; function TApplicationExceptionSpecialized.Type_: TApplicationException.TExceptionType; begin result := GetType; end; { specialized TApplicationExceptions } class function TApplicationExceptionUnknownMethod.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.UnknownMethod; end; class function TApplicationExceptionInvalidMessageType.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.InvalidMessageType; end; class function TApplicationExceptionWrongMethodName.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.WrongMethodName; end; class function TApplicationExceptionBadSequenceID.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.BadSequenceID; end; class function TApplicationExceptionMissingResult.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.MissingResult; end; class function TApplicationExceptionInternalError.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.InternalError; end; class function TApplicationExceptionProtocolError.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.ProtocolError; end; class function TApplicationExceptionInvalidTransform.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.InvalidTransform; end; class function TApplicationExceptionInvalidProtocol.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.InvalidProtocol; end; class function TApplicationExceptionUnsupportedClientType.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.UnsupportedClientType; end; class function TApplicationExceptionUnknown.GetType : TApplicationException.TExceptionType; begin result := TExceptionType.Unknown; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Socket.pas0000644000000000000000000014566614303740367021126 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Socket; {$I Thrift.Defines.inc} {$I-} // prevent annoying errors with default log delegate and no console interface {$IFNDEF OLD_SOCKETS} // not for OLD_SOCKETS uses Winapi.Windows, Winapi.Winsock2; const AI_PASSIVE = $00000001; // Socket address will be used in bind() call AI_CANONNAME = $00000002; // Return canonical name in first ai_canonname AI_NUMERICHOST = $00000004; // Nodename must be a numeric address string AI_NUMERICSERV = $00000008; // Servicename must be a numeric port number AI_ALL = $00000100; // Query both IP6 and IP4 with AI_V4MAPPED AI_ADDRCONFIG = $00000400; // Resolution only if global address configured AI_V4MAPPED = $00000800; // On v6 failure, query v4 and convert to V4MAPPED format AI_NON_AUTHORITATIVE = $00004000; // LUP_NON_AUTHORITATIVE AI_SECURE = $00008000; // LUP_SECURE AI_RETURN_PREFERRED_NAMES = $00010000; // LUP_RETURN_PREFERRED_NAMES AI_FQDN = $00020000; // Return the FQDN in ai_canonname AI_FILESERVER = $00040000; // Resolving fileserver name resolution type PAddrInfoA = ^TAddrInfoA; TAddrInfoA = record ai_flags: Integer; ai_family: Integer; ai_socktype: Integer; ai_protocol: Integer; ai_addrlen: NativeUInt; ai_canonname: PAnsiChar; ai_addr: PSockAddr; ai_next: PAddrInfoA; end; PAddrInfoW = ^TAddrInfoW; TAddrInfoW = record ai_flags: Integer; ai_family: Integer; ai_socktype: Integer; ai_protocol: Integer; ai_addrlen: NativeUInt; ai_canonname: PChar; ai_addr: PSockAddr; ai_next: PAddrInfoW; end; TAddressFamily = USHORT; TIn6Addr = record case Integer of 0: (_Byte: array[0..15] of UCHAR); 1: (_Word: array[0..7] of USHORT); end; TScopeId = record public Value: ULONG; strict private function GetBitField(Loc: Integer): Integer; inline; procedure SetBitField(Loc: Integer; const aValue: Integer); inline; public property Zone: Integer index $0028 read GetBitField write SetBitField; property Level: Integer index $2804 read GetBitField write SetBitField; end; TSockAddrIn6 = record sin6_family: TAddressFamily; sin6_port: USHORT; sin6_flowinfo: ULONG; sin6_addr: TIn6Addr; case Integer of 0: (sin6_scope_id: ULONG); 1: (sin6_scope_struct: TScopeId); end; PSockAddrIn6 = ^TSockAddrIn6; const NI_NOFQDN = $01; // Only return nodename portion for local hosts NI_NUMERICHOST = $02; // Return numeric form of the host's address NI_NAMEREQD = $04; // Error if the host's name not in DNS NI_NUMERICSERV = $08; // Return numeric form of the service (port #) NI_DGRAM = $10; // Service is a datagram service NI_MAXHOST = 1025; // Max size of a fully-qualified domain name NI_MAXSERV = 32; // Max size of a service name function getaddrinfo(pNodeName, pServiceName: PAnsiChar; const pHints: TAddrInfoA; var ppResult: PAddrInfoA): Integer; stdcall; function GetAddrInfoW(pNodeName, pServiceName: PWideChar; const pHints: TAddrInfoW; var ppResult: PAddrInfoW): Integer; stdcall; procedure freeaddrinfo(pAddrInfo: PAddrInfoA); stdcall; procedure FreeAddrInfoW(pAddrInfo: PAddrInfoW); stdcall; function getnameinfo(const pSockaddr: TSockAddr; SockaddrLength: Integer; pNodeBuffer: PAnsiChar; NodeBufferSize: DWORD; pServiceBuffer: PAnsiChar; ServiceBufferSize: DWORD; Flags: Integer): Integer; stdcall; function GetNameInfoW(const pSockaddr: TSockAddr; SockaddrLength: Integer; pNodeBuffer: PWideChar; NodeBufferSize: DWORD; pServiceBuffer: PWideChar; ServiceBufferSize: DWORD; Flags: Integer): Integer; stdcall; type TSmartPointerDestroyer = reference to procedure(Value: T); ISmartPointer = reference to function: T; TSmartPointer = class(TInterfacedObject, ISmartPointer) strict private FValue: T; FDestroyer: TSmartPointerDestroyer; public constructor Create(AValue: T; ADestroyer: TSmartPointerDestroyer); destructor Destroy; override; function Invoke: T; end; TBaseSocket = class abstract public type TLogDelegate = reference to procedure( const str: string); strict private FPort: Integer; FSocket: Winapi.Winsock2.TSocket; FSendTimeout, FRecvTimeout: Longword; FKeepAlive: Boolean; FLogDelegate: TLogDelegate; class constructor Create; class destructor Destroy; class procedure DefaultLogDelegate(const Str: string); strict protected type IGetAddrInfoWrapper = interface function Init: Integer; function GetRes: PAddrInfoW; property Res: PAddrInfoW read GetRes; end; TGetAddrInfoWrapper = class(TInterfacedObject, IGetAddrInfoWrapper) strict private FNode: string; FService: string; FHints, FRes: PAddrInfoW; public constructor Create(ANode, AService: string; AHints: PAddrInfoW); destructor Destroy; override; function Init: Integer; function GetRes: PAddrInfoW; property Res: PAddrInfoW read GetRes; end; strict protected procedure CommonInit; virtual; function CreateSocket(AAddress: string; APort: Integer): IGetAddrInfoWrapper; procedure SetRecvTimeout(ARecvTimeout: Longword); virtual; procedure SetSendTimeout(ASendTimeout: Longword); virtual; procedure SetKeepAlive(AKeepAlive: Boolean); virtual; procedure SetSocket(ASocket: Winapi.Winsock2.TSocket); property LogDelegate: TLogDelegate read FLogDelegate; public // // Constructs a new socket. Note that this does NOT actually connect the // socket. // constructor Create(ALogDelegate: TLogDelegate = nil); overload; constructor Create(APort: Integer; ALogDelegate: TLogDelegate = nil); overload; // // Destroys the socket object, closing it if necessary. // destructor Destroy; override; // // Shuts down communications on the socket // procedure Close; virtual; // The port that the socket is connected to property Port: Integer read FPort write FPort; // The receive timeout property RecvTimeout: Longword read FRecvTimeout write SetRecvTimeout; // The send timeout property SendTimeout: Longword read FSendTimeout write SetSendTimeout; // Set SO_KEEPALIVE property KeepAlive: Boolean read FKeepAlive write SetKeepAlive; // The underlying socket descriptor property Socket: Winapi.Winsock2.TSocket read FSocket write SetSocket; end; TSocket = class(TBaseSocket) strict private type TCachedPeerAddr = record case Integer of 0: (ipv4: TSockAddrIn); 1: (ipv6: TSockAddrIn6); end; strict private FHost: string; FPeerHost: string; FPeerAddress: string; FPeerPort: Integer; FInterruptListener: ISmartPointer; FConnTimeout: Longword; FLingerOn: Boolean; FLingerVal: Integer; FNoDelay: Boolean; FMaxRecvRetries: Longword; FCachedPeerAddr: TCachedPeerAddr; procedure InitPeerInfo; procedure OpenConnection(Res: TBaseSocket.IGetAddrInfoWrapper); procedure LocalOpen; procedure SetGenericTimeout(S: Winapi.Winsock2.TSocket; Timeout: Longword; OptName: Integer); function GetIsOpen: Boolean; procedure SetNoDelay(ANoDelay: Boolean); function GetSocketInfo: string; function GetPeerHost: string; function GetPeerAddress: string; function GetPeerPort: Integer; function GetOrigin: string; strict protected procedure CommonInit; override; procedure SetRecvTimeout(ARecvTimeout: Longword); override; procedure SetSendTimeout(ASendTimeout: Longword); override; procedure SetKeepAlive(AKeepAlive: Boolean); override; public // // Constructs a new socket. Note that this does NOT actually connect the // socket. // constructor Create(ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; // // Constructs a new socket. Note that this does NOT actually connect the // socket. // // @param host An IP address or hostname to connect to // @param port The port to connect on // constructor Create(AHost: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; // // Constructor to create socket from socket descriptor. // constructor Create(ASocket: Winapi.Winsock2.TSocket; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; // // Constructor to create socket from socket descriptor that // can be interrupted safely. // constructor Create(ASocket: Winapi.Winsock2.TSocket; AInterruptListener: ISmartPointer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; // // Creates and opens the socket // // @throws ETransportationException If the socket could not connect // procedure Open; // // Shuts down communications on the socket // procedure Close; override; // // Reads from the underlying socket. // \returns the number of bytes read or 0 indicates EOF // \throws TTransportException of types: // Interrupted means the socket was interrupted // out of a blocking call // NotOpen means the socket has been closed // TimedOut means the receive timeout expired // Unknown means something unexpected happened // function Read(var Buf; Len: Integer): Integer; // // Writes to the underlying socket. Loops until done or fail. // procedure Write(const Buf; Len: Integer); // // Writes to the underlying socket. Does single send() and returns result. // function WritePartial(const Buf; Len: Integer): Integer; // // Returns a cached copy of the peer address. // function GetCachedAddress(out Len: Integer): PSockAddr; // // Set a cache of the peer address (used when trivially available: e.g. // accept() or connect()). Only caches IPV4 and IPV6; unset for others. // procedure SetCachedAddress(const Addr: TSockAddr; Len: Integer); // // Controls whether the linger option is set on the socket. // // @param on Whether SO_LINGER is on // @param linger If linger is active, the number of seconds to linger for // procedure SetLinger(LingerOn: Boolean; LingerVal: Integer); // // Calls select() on the socket to see if there is more data available. // function Peek: Boolean; // Whether the socket is alive property IsOpen: Boolean read GetIsOpen; // The host that the socket is connected to property Host: string read FHost write FHost; // Whether to enable or disable Nagle's algorithm property NoDelay: Boolean read FNoDelay write SetNoDelay; // Connect timeout property ConnTimeout: Longword read FConnTimeout write FConnTimeout; // The max number of recv retries in the case of a WSAEWOULDBLOCK property MaxRecvRetries: Longword read FMaxRecvRetries write FMaxRecvRetries; // Socket information formatted as a string property SocketInfo: string read GetSocketInfo; // The DNS name of the host to which the socket is connected property PeerHost: string read GetPeerHost; // The address of the host to which the socket is connected property PeerAddress: string read GetPeerAddress; // The port of the host to which the socket is connected property PeerPort: Integer read GetPeerPort; // The origin the socket is connected to property Origin: string read GetOrigin; end; TServerSocketFunc = reference to procedure(sock: Winapi.Winsock2.TSocket); TServerSocket = class(TBaseSocket) strict private FAddress: string; FAcceptBacklog, FRetryLimit, FRetryDelay, FTcpSendBuffer, FTcpRecvBuffer: Integer; FAcceptTimeout: Longword; FListening, FInterruptableChildren: Boolean; FInterruptSockWriter, // is notified on Interrupt() FInterruptSockReader, // is used in select with FSocket for interruptability FChildInterruptSockWriter: Winapi.Winsock2.TSocket; // is notified on InterruptChildren() FChildInterruptSockReader: ISmartPointer; // if FnterruptableChildren this is shared with child TSockets FListenCallback, FAcceptCallback: TServerSocketFunc; function CreateSocketObj(Client: Winapi.Winsock2.TSocket): TSocket; procedure Notify(NotifySocket: Winapi.Winsock2.TSocket); procedure SetInterruptableChildren(AValue: Boolean); strict protected procedure CommonInit; override; public const DEFAULT_BACKLOG = 1024; public // // Constructor. // // @param port Port number to bind to // constructor Create(APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; // // Constructor. // // @param port Port number to bind to // @param sendTimeout Socket send timeout // @param recvTimeout Socket receive timeout // constructor Create(APort: Integer; ASendTimeout, ARecvTimeout: Longword; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; // // Constructor. // // @param address Address to bind to // @param port Port number to bind to // constructor Create(AAddress: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); overload; procedure Listen; function Accept: TSocket; procedure Interrupt; procedure InterruptChildren; procedure Close; override; property AcceptBacklog: Integer read FAcceptBacklog write FAcceptBacklog; property AcceptTimeout: Longword read FAcceptTimeout write FAcceptTimeout; property RetryLimit: Integer read FRetryLimit write FRetryLimit; property RetryDelay: Integer read FRetryDelay write FRetryDelay; property TcpSendBuffer: Integer read FTcpSendBuffer write FTcpSendBuffer; property TcpRecvBuffer: Integer read FTcpRecvBuffer write FTcpRecvBuffer; // When enabled (the default), new children TSockets will be constructed so // they can be interrupted by TServerTransport.InterruptChildren(). // This is more expensive in terms of system calls (poll + recv) however // ensures a connected client cannot interfere with TServer.Stop(). // // When disabled, TSocket children do not incur an additional poll() call. // Server-side reads are more efficient, however a client can interfere with // the server's ability to shutdown properly by staying connected. // // Must be called before listen(); mode cannot be switched after that. // \throws EPropertyError if listen() has been called property InterruptableChildren: Boolean read FInterruptableChildren write SetInterruptableChildren; // listenCallback gets called just before listen, and after all Thrift // setsockopt calls have been made. If you have custom setsockopt // things that need to happen on the listening socket, this is the place to do it. property ListenCallback: TServerSocketFunc read FListenCallback write FListenCallback; // acceptCallback gets called after each accept call, on the newly created socket. // It is called after all Thrift setsockopt calls have been made. If you have // custom setsockopt things that need to happen on the accepted // socket, this is the place to do it. property AcceptCallback: TServerSocketFunc read FAcceptCallback write FAcceptCallback; end; {$ENDIF} // not for OLD_SOCKETS implementation {$IFNDEF OLD_SOCKETS} // not for OLD_SOCKETS uses System.SysUtils, System.Math, System.DateUtils, Thrift.Transport; constructor TBaseSocket.TGetAddrInfoWrapper.Create(ANode, AService: string; AHints: PAddrInfoW); begin inherited Create; FNode := ANode; FService := AService; FHints := AHints; FRes := nil; end; destructor TBaseSocket.TGetAddrInfoWrapper.Destroy; begin if Assigned(FRes) then FreeAddrInfoW(FRes); inherited Destroy; end; function TBaseSocket.TGetAddrInfoWrapper.Init: Integer; begin if FRes = nil then Exit(GetAddrInfoW(@FNode[1], @FService[1], FHints^, FRes)); Result := 0; end; function TBaseSocket.TGetAddrInfoWrapper.GetRes: PAddrInfoW; begin Result := FRes; end; procedure DestroyerOfFineSockets(ssock: Winapi.Winsock2.TSocket); begin closesocket(ssock); end; function TScopeId.GetBitField(Loc: Integer): Integer; begin Result := (Value shr (Loc shr 8)) and ((1 shl (Loc and $FF)) - 1); end; procedure TScopeId.SetBitField(Loc: Integer; const aValue: Integer); begin Value := (Value and ULONG((not ((1 shl (Loc and $FF)) - 1)))) or ULONG(aValue shl (Loc shr 8)); end; function getaddrinfo; external 'ws2_32.dll' name 'getaddrinfo'; function GetAddrInfoW; external 'ws2_32.dll' name 'GetAddrInfoW'; procedure freeaddrinfo; external 'ws2_32.dll' name 'freeaddrinfo'; procedure FreeAddrInfoW; external 'ws2_32.dll' name 'FreeAddrInfoW'; function getnameinfo; external 'ws2_32.dll' name 'getnameinfo'; function GetNameInfoW; external 'ws2_32.dll' name 'GetNameInfoW'; constructor TSmartPointer.Create(AValue: T; ADestroyer: TSmartPointerDestroyer); begin inherited Create; FValue := AValue; FDestroyer := ADestroyer; end; destructor TSmartPointer.Destroy; begin if Assigned(FDestroyer) then FDestroyer(FValue); inherited Destroy; end; function TSmartPointer.Invoke: T; begin Result := FValue; end; class constructor TBaseSocket.Create; var Version: WORD; Data: WSAData; Error: Integer; begin Version := $0202; FillChar(Data, SizeOf(Data), 0); Error := WSAStartup(Version, Data); if Error <> 0 then raise Exception.Create('Failed to initialize Winsock.'); end; class destructor TBaseSocket.Destroy; begin WSACleanup; end; class procedure TBaseSocket.DefaultLogDelegate(const Str: string); var OutStr: string; begin OutStr := Format('Thrift: %s %s', [DateTimeToStr(Now, TFormatSettings.Create), Str]); try Writeln(OutStr); if IoResult <> 0 then OutputDebugString(PChar(OutStr)); except OutputDebugString(PChar(OutStr)); end; end; procedure TBaseSocket.CommonInit; begin FSocket := INVALID_SOCKET; FPort := 0; FSendTimeout := 0; FRecvTimeout := 0; FKeepAlive := False; FLogDelegate := DefaultLogDelegate; end; function TBaseSocket.CreateSocket(AAddress: string; APort: Integer): IGetAddrInfoWrapper; var Hints: TAddrInfoW; Res: PAddrInfoW; ThePort: array[0..5] of Char; Error: Integer; begin FillChar(Hints, SizeOf(Hints), 0); Hints.ai_family := PF_UNSPEC; Hints.ai_socktype := SOCK_STREAM; Hints.ai_flags := AI_PASSIVE; StrFmt(ThePort, '%d', [FPort]); Result := TGetAddrInfoWrapper.Create(AAddress, ThePort, @Hints); Error := Result.Init; if Error <> 0 then begin LogDelegate(Format('GetAddrInfoW %d: %s', [Error, SysErrorMessage(Error)])); Close; raise TTransportExceptionNotOpen.Create('Could not resolve host for server socket.'); end; // Pick the ipv6 address first since ipv4 addresses can be mapped // into ipv6 space. Res := Result.Res; while Assigned(Res) do begin if (Res^.ai_family = AF_INET6) or (not Assigned(Res^.ai_next)) then Break; Res := Res^.ai_next; end; FSocket := Winapi.Winsock2.socket(Res^.ai_family, Res^.ai_socktype, Res^.ai_protocol); if FSocket = INVALID_SOCKET then begin Error := WSAGetLastError; LogDelegate(Format('TBaseSocket.CreateSocket() socket() %s', [SysErrorMessage(Error)])); Close; raise TTransportExceptionNotOpen.Create(Format('socket(): %s', [SysErrorMessage(Error)])); end; end; procedure TBaseSocket.SetRecvTimeout(ARecvTimeout: Longword); begin FRecvTimeout := ARecvTimeout; end; procedure TBaseSocket.SetSendTimeout(ASendTimeout: Longword); begin FSendTimeout := ASendTimeout; end; procedure TBaseSocket.SetKeepAlive(AKeepAlive: Boolean); begin FKeepAlive := AKeepAlive; end; procedure TBaseSocket.SetSocket(ASocket: Winapi.Winsock2.TSocket); begin if FSocket <> INVALID_SOCKET then Close; FSocket := ASocket; end; constructor TBaseSocket.Create(ALogDelegate: TLogDelegate); begin inherited Create; CommonInit; if Assigned(ALogDelegate) then FLogDelegate := ALogDelegate; end; constructor TBaseSocket.Create(APort: Integer; ALogDelegate: TLogDelegate); begin inherited Create; CommonInit; FPort := APort; if Assigned(ALogDelegate) then FLogDelegate := ALogDelegate; end; destructor TBaseSocket.Destroy; begin Close; inherited Destroy; end; procedure TBaseSocket.Close; begin if FSocket <> INVALID_SOCKET then begin shutdown(FSocket, SD_BOTH); closesocket(FSocket); end; FSocket := INVALID_SOCKET; end; procedure TSocket.InitPeerInfo; begin FCachedPeerAddr.ipv4.sin_family := AF_UNSPEC; FPeerHost := ''; FPeerAddress := ''; FPeerPort := 0; end; procedure TSocket.CommonInit; begin inherited CommonInit; FHost := ''; FInterruptListener := nil; FConnTimeout := 0; FLingerOn := True; FLingerVal := 0; FNoDelay := True; FMaxRecvRetries := 5; InitPeerInfo; end; procedure TSocket.OpenConnection(Res: TBaseSocket.IGetAddrInfoWrapper); label Done; var ErrnoCopy: Integer; Ret, Ret2: Integer; Fds: TFdSet; TVal: TTimeVal; PTVal: PTimeVal; Val, Lon: Integer; One, Zero: Cardinal; begin if SendTimeout > 0 then SetSendTimeout(SendTimeout); if RecvTimeout > 0 then SetRecvTimeout(RecvTimeout); if KeepAlive then SetKeepAlive(KeepAlive); SetLinger(FLingerOn, FLingerVal); SetNoDelay(FNoDelay); // Set the socket to be non blocking for connect if a timeout exists Zero := 0; if FConnTimeout > 0 then begin One := 1; if ioctlsocket(Socket, Integer(FIONBIO), One) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TSocket.OpenConnection() ioctlsocket() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('ioctlsocket() failed: %s', [SysErrorMessage(ErrnoCopy)])); end; end else begin if ioctlsocket(Socket, Integer(FIONBIO), Zero) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TSocket.OpenConnection() ioctlsocket() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('ioctlsocket() failed: %s', [SysErrorMessage(ErrnoCopy)])); end; end; Ret := connect(Socket, Res.Res^.ai_addr^, Res.Res^.ai_addrlen); if Ret = 0 then goto Done; ErrnoCopy := WSAGetLastError; if (ErrnoCopy <> WSAEINPROGRESS) and (ErrnoCopy <> WSAEWOULDBLOCK) then begin LogDelegate(Format('TSocket.OpenConnection() connect() ', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('connect() failed: %s', [SysErrorMessage(ErrnoCopy)])); end; FD_ZERO(Fds); _FD_SET(Socket, Fds); if FConnTimeout > 0 then begin TVal.tv_sec := FConnTimeout div 1000; TVal.tv_usec := (FConnTimeout mod 1000) * 1000; PTVal := @TVal; end else PTVal := nil; Ret := select(1, nil, @Fds, nil, PTVal); if Ret > 0 then begin // Ensure the socket is connected and that there are no errors set Lon := SizeOf(Val); Ret2 := getsockopt(Socket, SOL_SOCKET, SO_ERROR, @Val, Lon); if Ret2 = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TSocket.OpenConnection() getsockopt() ', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('getsockopt(): %s', [SysErrorMessage(ErrnoCopy)])); end; // no errors on socket, go to town if Val = 0 then goto Done; LogDelegate(Format('TSocket.OpenConnection() error on socket (after select()) ', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('socket OpenConnection() error: %s', [SysErrorMessage(Val)])); end else if Ret = 0 then begin // socket timed out LogDelegate(Format('TSocket.OpenConnection() timed out ', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create('OpenConnection() timed out'); end else begin // error on select() ErrnoCopy := WSAGetLastError; LogDelegate(Format('TSocket.OpenConnection() select() ', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('select() failed: %s', [SysErrorMessage(ErrnoCopy)])); end; Done: // Set socket back to normal mode (blocking) ioctlsocket(Socket, Integer(FIONBIO), Zero); SetCachedAddress(Res.Res^.ai_addr^, Res.Res^.ai_addrlen); end; procedure TSocket.LocalOpen; var Res: TBaseSocket.IGetAddrInfoWrapper; begin if IsOpen then Exit; // Validate port number if (Port < 0) or (Port > $FFFF) then raise TTransportExceptionBadArgs.Create('Specified port is invalid'); Res := CreateSocket(Host, Port); OpenConnection(Res); end; procedure TSocket.SetGenericTimeout(S: Winapi.Winsock2.TSocket; Timeout: Longword; OptName: Integer); var Time: DWORD; begin if S = INVALID_SOCKET then Exit; Time := Timeout; if setsockopt(S, SOL_SOCKET, OptName, @Time, SizeOf(Time)) = SOCKET_ERROR then LogDelegate(Format('SetGenericTimeout() setsockopt() %s', [SysErrorMessage(WSAGetLastError)])); end; function TSocket.GetIsOpen: Boolean; begin Result := Socket <> INVALID_SOCKET; end; procedure TSocket.SetNoDelay(ANoDelay: Boolean); var V: Integer; begin FNoDelay := ANoDelay; if Socket = INVALID_SOCKET then Exit; V := IfThen(FNoDelay, 1, 0); if setsockopt(Socket, IPPROTO_TCP, TCP_NODELAY, @V, SizeOf(V)) = SOCKET_ERROR then LogDelegate(Format('TSocket.SetNoDelay() setsockopt() %s %s', [SocketInfo, SysErrorMessage(WSAGetLastError)])); end; function TSocket.GetSocketInfo: string; begin if (FHost = '') or (Port = 0) then Result := '' else Result := ''; end; function TSocket.GetPeerHost: string; var Addr: TSockAddrStorage; AddrPtr: PSockAddr; AddrLen: Integer; ClientHost: array[0..NI_MAXHOST-1] of Char; ClientService: array[0..NI_MAXSERV-1] of Char; begin if FPeerHost = '' then begin if Socket = INVALID_SOCKET then Exit(FPeerHost); AddrPtr := GetCachedAddress(AddrLen); if AddrPtr = nil then begin AddrLen := SizeOf(Addr); if getpeername(Socket, PSockAddr(@Addr)^, AddrLen) <> 0 then Exit(FPeerHost); AddrPtr := PSockAddr(@Addr); SetCachedAddress(AddrPtr^, AddrLen); end; GetNameInfoW(AddrPtr^, AddrLen, ClientHost, NI_MAXHOST, ClientService, NI_MAXSERV, 0); FPeerHost := ClientHost; end; Result := FPeerHost; end; function TSocket.GetPeerAddress: string; var Addr: TSockAddrStorage; AddrPtr: PSockAddr; AddrLen: Integer; ClientHost: array[0..NI_MAXHOST-1] of Char; ClientService: array[0..NI_MAXSERV-1] of Char; begin if FPeerAddress = '' then begin if Socket = INVALID_SOCKET then Exit(FPeerAddress); AddrPtr := GetCachedAddress(AddrLen); if AddrPtr = nil then begin AddrLen := SizeOf(Addr); if getpeername(Socket, PSockAddr(@Addr)^, AddrLen) <> 0 then Exit(FPeerHost); AddrPtr := PSockAddr(@Addr); SetCachedAddress(AddrPtr^, AddrLen); end; GetNameInfoW(AddrPtr^, AddrLen, ClientHost, NI_MAXHOST, ClientService, NI_MAXSERV, NI_NUMERICHOST or NI_NUMERICSERV); FPeerAddress := ClientHost; TryStrToInt(ClientService, FPeerPort); end; Result := FPeerAddress end; function TSocket.GetPeerPort: Integer; begin GetPeerAddress; Result := FPeerPort; end; function TSocket.GetOrigin: string; begin Result := GetPeerHost + ':' + GetPeerPort.ToString; end; procedure TSocket.SetRecvTimeout(ARecvTimeout: Longword); begin inherited SetRecvTimeout(ARecvTimeout); SetGenericTimeout(Socket, ARecvTimeout, SO_RCVTIMEO); end; procedure TSocket.SetSendTimeout(ASendTimeout: Longword); begin inherited SetSendTimeout(ASendTimeout); SetGenericTimeout(Socket, ASendTimeout, SO_SNDTIMEO); end; procedure TSocket.SetKeepAlive(AKeepAlive: Boolean); var Value: Integer; begin inherited SetKeepAlive(AKeepAlive); Value := IfThen(KeepAlive, 1, 0); if setsockopt(Socket, SOL_SOCKET, SO_KEEPALIVE, @Value, SizeOf(Value)) = SOCKET_ERROR then LogDelegate(Format('TSocket.SetKeepAlive() setsockopt() %s %s', [SocketInfo, SysErrorMessage(WSAGetLastError)])); end; constructor TSocket.Create(ALogDelegate: TBaseSocket.TLogDelegate = nil); begin // Not needed, but just a placeholder inherited Create(ALogDelegate); end; constructor TSocket.Create(AHost: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate); begin inherited Create(APort, ALogDelegate); FHost := AHost; end; constructor TSocket.Create(ASocket: Winapi.Winsock2.TSocket; ALogDelegate: TBaseSocket.TLogDelegate); begin inherited Create(ALogDelegate); Socket := ASocket; end; constructor TSocket.Create(ASocket: Winapi.Winsock2.TSocket; AInterruptListener: ISmartPointer; ALogDelegate: TBaseSocket.TLogDelegate); begin inherited Create(ALogDelegate); Socket := ASocket; FInterruptListener := AInterruptListener; end; procedure TSocket.Open; begin if IsOpen then Exit; LocalOpen; end; procedure TSocket.Close; begin inherited Close; InitPeerInfo; end; function TSocket.Read(var Buf; Len: Integer): Integer; label TryAgain; var Retries: Longword; EAgainThreshold, ReadElapsed: UInt64; Start: TDateTime; Got: Integer; Fds: TFdSet; ErrnoCopy: Integer; TVal: TTimeVal; PTVal: PTimeVal; Ret: Integer; begin if Socket = INVALID_SOCKET then raise TTransportExceptionNotOpen.Create('Called read on non-open socket'); Retries := 0; // THRIFT_EAGAIN can be signalled both when a timeout has occurred and when // the system is out of resources (an awesome undocumented feature). // The following is an approximation of the time interval under which // THRIFT_EAGAIN is taken to indicate an out of resources error. EAgainThreshold := 0; if RecvTimeout <> 0 then // if a readTimeout is specified along with a max number of recv retries, then // the threshold will ensure that the read timeout is not exceeded even in the // case of resource errors EAgainThreshold := RecvTimeout div IfThen(FMaxRecvRetries > 0, FMaxRecvRetries, 2); TryAgain: // Read from the socket if RecvTimeout > 0 then Start := Now else // if there is no read timeout we don't need the TOD to determine whether // an THRIFT_EAGAIN is due to a timeout or an out-of-resource condition. Start := 0; if Assigned(FInterruptListener) then begin FD_ZERO(Fds); _FD_SET(Socket, Fds); _FD_SET(FInterruptListener, Fds); if RecvTimeout > 0 then begin TVal.tv_sec := RecvTimeout div 1000; TVal.tv_usec := (RecvTimeout mod 1000) * 1000; PTVal := @TVal; end else PTVal := nil; Ret := select(2, @Fds, nil, nil, PTVal); ErrnoCopy := WSAGetLastError; if Ret < 0 then begin // error cases if (ErrnoCopy = WSAEINTR) and (Retries < FMaxRecvRetries) then begin Inc(Retries); goto TryAgain; end; LogDelegate(Format('TSocket.Read() select() %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)])); end else if Ret > 0 then begin // Check the interruptListener if FD_ISSET(FInterruptListener, Fds) then raise TTransportExceptionInterrupted.Create('Interrupted'); end else // Ret = 0 raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (timed out)'); // falling through means there is something to recv and it cannot block end; Got := recv(Socket, Buf, Len, 0); ErrnoCopy := WSAGetLastError; // Check for error on read if Got < 0 then begin if ErrnoCopy = WSAEWOULDBLOCK then begin // if no timeout we can assume that resource exhaustion has occurred. if RecvTimeout = 0 then raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (unavailable resources)'); // check if this is the lack of resources or timeout case ReadElapsed := MilliSecondsBetween(Now, Start); if (EAgainThreshold = 0) or (ReadElapsed < EAgainThreshold) then begin if Retries < FMaxRecvRetries then begin Inc(Retries); Sleep(1); goto TryAgain; end else raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (unavailable resources)'); end else // infer that timeout has been hit raise TTransportExceptionTimedOut.Create('WSAEWOULDBLOCK (timed out)'); end; // If interrupted, try again if (ErrnoCopy = WSAEINTR) and (Retries < FMaxRecvRetries) then begin Inc(Retries); goto TryAgain; end; if ErrnoCopy = WSAECONNRESET then Exit(0); // This ish isn't open if ErrnoCopy = WSAENOTCONN then raise TTransportExceptionNotOpen.Create('WSAENOTCONN'); // Timed out! if ErrnoCopy = WSAETIMEDOUT then raise TTransportExceptionNotOpen.Create('WSAETIMEDOUT'); // Now it's not a try again case, but a real probblez LogDelegate(Format('TSocket.Read() recv() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)])); // Some other error, whatevz raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)])); end; Result := Got; end; procedure TSocket.Write(const Buf; Len: Integer); var Sent, B: Integer; begin Sent := 0; while Sent < Len do begin B := WritePartial((PByte(@Buf) + Sent)^, Len - Sent); if B = 0 then // This should only happen if the timeout set with SO_SNDTIMEO expired. // Raise an exception. raise TTransportExceptionTimedOut.Create('send timeout expired'); Inc(Sent, B); end; end; function TSocket.WritePartial(const Buf; Len: Integer): Integer; var B: Integer; ErrnoCopy: Integer; begin if Socket = INVALID_SOCKET then raise TTransportExceptionNotOpen.Create('Called write on non-open socket'); B := send(Socket, Buf, Len, 0); if B < 0 then begin // Fail on a send error ErrnoCopy := WSAGetLastError; if ErrnoCopy = WSAEWOULDBLOCK then Exit(0); LogDelegate(Format('TSocket.WritePartial() send() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)])); if (ErrnoCopy = WSAECONNRESET) or (ErrnoCopy = WSAENOTCONN) then begin Close; raise TTransportExceptionNotOpen.Create(Format('write() send(): %s', [SysErrorMessage(ErrnoCopy)])); end; raise TTransportExceptionUnknown.Create(Format('write() send(): %s', [SysErrorMessage(ErrnoCopy)])); end; // Fail on blocked send if B = 0 then raise TTransportExceptionNotOpen.Create('Socket send returned 0.'); Result := B; end; function TSocket.GetCachedAddress(out Len: Integer): PSockAddr; begin case FCachedPeerAddr.ipv4.sin_family of AF_INET: begin Len := SizeOf(TSockAddrIn); Result := PSockAddr(@FCachedPeerAddr.ipv4); end; AF_INET6: begin Len := SizeOf(TSockAddrIn6); Result := PSockAddr(@FCachedPeerAddr.ipv6); end; else Len := 0; Result := nil; end; end; procedure TSocket.SetCachedAddress(const Addr: TSockAddr; Len: Integer); begin case Addr.sa_family of AF_INET: if Len = SizeOf(TSockAddrIn) then FCachedPeerAddr.ipv4 := PSockAddrIn(@Addr)^; AF_INET6: if Len = SizeOf(TSockAddrIn6) then FCachedPeerAddr.ipv6 := PSockAddrIn6(@Addr)^; end; FPeerAddress := ''; FPeerHost := ''; FPeerPort := 0; end; procedure TSocket.SetLinger(LingerOn: Boolean; LingerVal: Integer); var L: TLinger; begin FLingerOn := LingerOn; FLingerVal := LingerVal; if Socket = INVALID_SOCKET then Exit; L.l_onoff := IfThen(FLingerOn, 1, 0); L.l_linger := LingerVal; if setsockopt(Socket, SOL_SOCKET, SO_LINGER, @L, SizeOf(L)) = SOCKET_ERROR then LogDelegate(Format('TSocket.SetLinger() setsockopt() %s %s', [SocketInfo, SysErrorMessage(WSAGetLastError)])); end; function TSocket.Peek: Boolean; var Retries: Longword; Fds: TFdSet; TVal: TTimeVal; PTVal: PTimeVal; Ret: Integer; ErrnoCopy: Integer; Buf: Byte; begin if not IsOpen then Exit(False); if Assigned(FInterruptListener) then begin Retries := 0; while true do begin FD_ZERO(Fds); _FD_SET(Socket, Fds); _FD_SET(FInterruptListener, Fds); if RecvTimeout > 0 then begin TVal.tv_sec := RecvTimeout div 1000; TVal.tv_usec := (RecvTimeout mod 1000) * 1000; PTVal := @TVal; end else PTVal := nil; Ret := select(2, @Fds, nil, nil, PTVal); ErrnoCopy := WSAGetLastError; if Ret < 0 then begin // error cases if (ErrnoCopy = WSAEINTR) and (Retries < FMaxRecvRetries) then begin Inc(Retries); Continue; end; LogDelegate(Format('TSocket.Peek() select() %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)])); end else if Ret > 0 then begin // Check the interruptListener if FD_ISSET(FInterruptListener, Fds) then Exit(False); // There must be data or a disconnection, fall through to the PEEK Break; end else // timeout Exit(False); end; end; // Check to see if data is available or if the remote side closed Ret := recv(Socket, Buf, 1, MSG_PEEK); if Ret = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; if ErrnoCopy = WSAECONNRESET then begin Close; Exit(False); end; LogDelegate(Format('TSocket.Peek() recv() %s %s', [SocketInfo, SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionUnknown.Create(Format('recv(): %s', [SysErrorMessage(ErrnoCopy)])); end; Result := Ret > 0; end; function TServerSocket.CreateSocketObj(Client: Winapi.Winsock2.TSocket): TSocket; begin if FInterruptableChildren then Result := TSocket.Create(Client, FChildInterruptSockReader) else Result := TSocket.Create(Client); end; procedure TServerSocket.Notify(NotifySocket: Winapi.Winsock2.TSocket); var Byt: Byte; begin if NotifySocket <> INVALID_SOCKET then begin Byt := 0; if send(NotifySocket, Byt, SizeOf(Byt), 0) = SOCKET_ERROR then LogDelegate(Format('TServerSocket.Notify() send() %s', [SysErrorMessage(WSAGetLastError)])); end; end; procedure TServerSocket.SetInterruptableChildren(AValue: Boolean); begin if FListening then raise Exception.Create('InterruptableChildren cannot be set after listen()'); FInterruptableChildren := AValue; end; procedure TServerSocket.CommonInit; begin inherited CommonInit; FInterruptableChildren := True; FAcceptBacklog := DEFAULT_BACKLOG; FAcceptTimeout := 0; FRetryLimit := 0; FRetryDelay := 0; FTcpSendBuffer := 0; FTcpRecvBuffer := 0; FListening := False; FInterruptSockWriter := INVALID_SOCKET; FInterruptSockReader := INVALID_SOCKET; FChildInterruptSockWriter := INVALID_SOCKET; end; constructor TServerSocket.Create(APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate = nil); begin // Unnecessary, but here for documentation purposes inherited Create(APort, ALogDelegate); end; constructor TServerSocket.Create(APort: Integer; ASendTimeout, ARecvTimeout: Longword; ALogDelegate: TBaseSocket.TLogDelegate); begin inherited Create(APort, ALogDelegate); SendTimeout := ASendTimeout; RecvTimeout := ARecvTimeout; end; constructor TServerSocket.Create(AAddress: string; APort: Integer; ALogDelegate: TBaseSocket.TLogDelegate); begin inherited Create(APort, ALogDelegate); FAddress := AAddress; end; procedure TServerSocket.Listen; function CreateSocketPair(var Reader, Writer: Winapi.Winsock2.TSocket): Integer; label Error; type TSAUnion = record case Integer of 0: (inaddr: TSockAddrIn); 1: (addr: TSockAddr); end; var a: TSAUnion; listener: Winapi.Winsock2.TSocket; e: Integer; addrlen: Integer; flags: DWORD; reuse: Integer; begin addrlen := SizeOf(a.inaddr); flags := 0; reuse := 1; listener := Winapi.Winsock2.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if listener = INVALID_SOCKET then Exit(SOCKET_ERROR); FillChar(a, SizeOf(a), 0); a.inaddr.sin_family := AF_INET; a.inaddr.sin_addr.s_addr := htonl(INADDR_LOOPBACK); a.inaddr.sin_port := 0; Reader := INVALID_SOCKET; Writer := INVALID_SOCKET; // ignore errors coming out of this setsockopt. This is because // SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't // want to force socket pairs to be an admin. setsockopt(listener, SOL_SOCKET, Integer(SO_EXCLUSIVEADDRUSE), @reuse, SizeOf(reuse)); if bind(listener, a.addr, SizeOf(a.inaddr)) = SOCKET_ERROR then goto Error; if getsockname(listener, a.addr, addrlen) = SOCKET_ERROR then goto Error; if Winapi.Winsock2.listen(listener, 1) = SOCKET_ERROR then goto Error; Reader := WSASocket(AF_INET, SOCK_STREAM, 0, nil, 0, flags); if Reader = INVALID_SOCKET then goto Error; if connect(Reader, a.addr, SizeOf(a.inaddr)) = SOCKET_ERROR then goto Error; Writer := Winapi.Winsock2.accept(listener, nil, nil); if Writer = INVALID_SOCKET then goto Error; closesocket(listener); Exit(0); Error: e := WSAGetLastError; closesocket(listener); closesocket(Reader); closesocket(Writer); WSASetLastError(e); Result := SOCKET_ERROR; end; var TempIntReader, TempIntWriter: Winapi.Winsock2.TSocket; One: Cardinal; ErrnoCopy: Integer; Ling: TLinger; Retries: Integer; AddrInfo: IGetAddrInfoWrapper; SA: TSockAddrStorage; Len: Integer; begin // Create the socket pair used to interrupt if CreateSocketPair(TempIntReader, TempIntWriter) = SOCKET_ERROR then begin LogDelegate(Format('TServerSocket.Listen() CreateSocketPair() Interrupt %s', [SysErrorMessage(WSAGetLastError)])); FInterruptSockReader := INVALID_SOCKET; FInterruptSockWriter := INVALID_SOCKET; end else begin FInterruptSockReader := TempIntReader; FInterruptSockWriter := TempIntWriter; end; // Create the socket pair used to interrupt all clients if CreateSocketPair(TempIntReader, TempIntWriter) = SOCKET_ERROR then begin LogDelegate(Format('TServerSocket.Listen() CreateSocketPair() ChildInterrupt %s', [SysErrorMessage(WSAGetLastError)])); FChildInterruptSockReader := TSmartPointer.Create(INVALID_SOCKET, nil); FChildInterruptSockWriter := INVALID_SOCKET; end else begin FChildInterruptSockReader := TSmartPointer.Create(TempIntReader, DestroyerOfFineSockets); FChildInterruptSockWriter := TempIntWriter; end; if (Port < 0) or (Port > $FFFF) then raise TTransportExceptionBadArgs.Create('Specified port is invalid'); AddrInfo := CreateSocket(FAddress, Port); // Set SO_EXCLUSIVEADDRUSE to prevent 2MSL delay on accept One := 1; setsockopt(Socket, SOL_SOCKET, Integer(SO_EXCLUSIVEADDRUSE), @one, SizeOf(One)); // ignore errors coming out of this setsockopt on Windows. This is because // SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't // want to force servers to be an admin. // Set TCP buffer sizes if FTcpSendBuffer > 0 then begin if setsockopt(Socket, SOL_SOCKET, SO_SNDBUF, @FTcpSendBuffer, SizeOf(FTcpSendBuffer)) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_SNDBUF %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('Could not set SO_SNDBUF: %s', [SysErrorMessage(ErrnoCopy)])); end; end; if FTcpRecvBuffer > 0 then begin if setsockopt(Socket, SOL_SOCKET, SO_RCVBUF, @FTcpRecvBuffer, SizeOf(FTcpRecvBuffer)) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_RCVBUF %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('Could not set SO_RCVBUF: %s', [SysErrorMessage(ErrnoCopy)])); end; end; // Turn linger off, don't want to block on calls to close Ling.l_onoff := 0; Ling.l_linger := 0; if setsockopt(Socket, SOL_SOCKET, SO_LINGER, @Ling, SizeOf(Ling)) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Listen() setsockopt() SO_LINGER %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('Could not set SO_LINGER: %s', [SysErrorMessage(ErrnoCopy)])); end; // TCP Nodelay, speed over bandwidth if setsockopt(Socket, IPPROTO_TCP, TCP_NODELAY, @One, SizeOf(One)) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Listen() setsockopt() TCP_NODELAY %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('Could not set TCP_NODELAY: %s', [SysErrorMessage(ErrnoCopy)])); end; // Set NONBLOCK on the accept socket if ioctlsocket(Socket, Integer(FIONBIO), One) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Listen() ioctlsocket() FIONBIO %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('ioctlsocket() FIONBIO: %s', [SysErrorMessage(ErrnoCopy)])); end; // prepare the port information // we may want to try to bind more than once, since THRIFT_NO_SOCKET_CACHING doesn't // always seem to work. The client can configure the retry variables. Retries := 0; while True do begin if bind(Socket, AddrInfo.Res^.ai_addr^, AddrInfo.Res^.ai_addrlen) = 0 then Break; Inc(Retries); if Retries > FRetryLimit then Break; Sleep(FRetryDelay * 1000); end; // retrieve bind info if (Port = 0) and (Retries < FRetryLimit) then begin Len := SizeOf(SA); FillChar(SA, Len, 0); if getsockname(Socket, PSockAddr(@SA)^, Len) = SOCKET_ERROR then LogDelegate(Format('TServerSocket.Listen() getsockname() %s', [SysErrorMessage(WSAGetLastError)])) else begin if SA.ss_family = AF_INET6 then Port := ntohs(PSockAddrIn6(@SA)^.sin6_port) else Port := ntohs(PSockAddrIn(@SA)^.sin_port); end; end; // throw an error if we failed to bind properly if (Retries > FRetryLimit) then begin LogDelegate(Format('TServerSocket.Listen() BIND %d', [Port])); Close; raise TTransportExceptionNotOpen.Create(Format('Could not bind: %s', [SysErrorMessage(WSAGetLastError)])); end; if Assigned(FListenCallback) then FListenCallback(Socket); // Call listen if Winapi.Winsock2.listen(Socket, FAcceptBacklog) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Listen() listen() %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionNotOpen.Create(Format('Could not listen: %s', [SysErrorMessage(ErrnoCopy)])); end; // The socket is now listening! end; function TServerSocket.Accept: TSocket; var Fds: TFdSet; MaxEInters, NumEInters: Integer; TVal: TTimeVal; PTVal: PTimeVal; ErrnoCopy: Integer; Buf: Byte; ClientAddress: TSockAddrStorage; Size: Integer; ClientSocket: Winapi.Winsock2.TSocket; Zero: Cardinal; Client: TSocket; Ret: Integer; begin MaxEInters := 5; NumEInters := 0; while True do begin FD_ZERO(Fds); _FD_SET(Socket, Fds); _FD_SET(FInterruptSockReader, Fds); if FAcceptTimeout > 0 then begin TVal.tv_sec := FAcceptTimeout div 1000; TVal.tv_usec := (FAcceptTimeout mod 1000) * 1000; PTVal := @TVal; end else PTVal := nil; // TODO: if WSAEINTR is received, we'll restart the timeout. // To be accurate, we need to fix this in the future. Ret := select(2, @Fds, nil, nil, PTVal); if Ret < 0 then begin // error cases if (WSAGetLastError = WSAEINTR) and (NumEInters < MaxEInters) then begin // THRIFT_EINTR needs to be handled manually and we can tolerate // a certain number Inc(NumEInters); Continue; end; ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Accept() select() %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionUnknown.Create(Format('Unknown: %s', [SysErrorMessage(ErrnoCopy)])); end else if Ret > 0 then begin // Check for an interrupt signal if (FInterruptSockReader <> INVALID_SOCKET) and FD_ISSET(FInterruptSockReader, Fds) then begin if recv(FInterruptSockReader, Buf, SizeOf(Buf), 0) = SOCKET_ERROR then LogDelegate(Format('TServerSocket.Accept() recv() interrupt %s', [SysErrorMessage(WSAGetLastError)])); raise TTransportExceptionInterrupted.Create('interrupted'); end; // Check for the actual server socket being ready if FD_ISSET(Socket, Fds) then Break; end else begin LogDelegate('TServerSocket.Accept() select() 0'); raise TTransportExceptionUnknown.Create('unknown error'); end; end; Size := SizeOf(ClientAddress); ClientSocket := Winapi.Winsock2.accept(Socket, @ClientAddress, @Size); if ClientSocket = INVALID_SOCKET then begin ErrnoCopy := WSAGetLastError; LogDelegate(Format('TServerSocket.Accept() accept() %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionUnknown.Create(Format('accept(): %s', [SysErrorMessage(ErrnoCopy)])); end; // Make sure client socket is blocking Zero := 0; if ioctlsocket(ClientSocket, Integer(FIONBIO), Zero) = SOCKET_ERROR then begin ErrnoCopy := WSAGetLastError; closesocket(ClientSocket); LogDelegate(Format('TServerSocket.Accept() ioctlsocket() FIONBIO %s', [SysErrorMessage(ErrnoCopy)])); raise TTransportExceptionUnknown.Create(Format('ioctlsocket(): %s', [SysErrorMessage(ErrnoCopy)])); end; Client := CreateSocketObj(ClientSocket); if SendTimeout > 0 then Client.SendTimeout := SendTimeout; if RecvTimeout > 0 then Client.RecvTimeout := RecvTimeout; if KeepAlive then Client.KeepAlive := KeepAlive; Client.SetCachedAddress(PSockAddr(@ClientAddress)^, Size); if Assigned(FAcceptCallback) then FAcceptCallback(ClientSocket); Result := Client; end; procedure TServerSocket.Interrupt; begin Notify(FInterruptSockWriter); end; procedure TServerSocket.InterruptChildren; begin Notify(FChildInterruptSockWriter); end; procedure TServerSocket.Close; begin inherited Close; if FInterruptSockWriter <> INVALID_SOCKET then closesocket(FInterruptSockWriter); if FInterruptSockReader <> INVALID_SOCKET then closesocket(FInterruptSockReader); if FChildInterruptSockWriter <> INVALID_SOCKET then closesocket(FChildInterruptSockWriter); FChildInterruptSockReader := TSmartPointer.Create(INVALID_SOCKET, nil); FListening := False; end; {$ENDIF} // not for OLD_SOCKETS end. thrift-0.19.0/lib/delphi/src/Thrift.Processor.Multiplex.pas0000644000000000000000000001720714303740367023624 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Processor.Multiplex; interface uses SysUtils, Generics.Collections, Thrift, Thrift.Protocol, Thrift.Protocol.Multiplex; { TMultiplexedProcessor is a TProcessor allowing a single TServer to provide multiple services. To do so, you instantiate the processor and then register additional processors with it, as shown in the following example: TMultiplexedProcessor processor = new TMultiplexedProcessor(); processor.registerProcessor( "Calculator", new Calculator.Processor(new CalculatorHandler())); processor.registerProcessor( "WeatherReport", new WeatherReport.Processor(new WeatherReportHandler())); TServerTransport t = new TServerSocket(9090); TSimpleServer server = new TSimpleServer(processor, t); server.serve(); } type IMultiplexedProcessor = interface( IProcessor) ['{807F9D19-6CF4-4789-840E-93E87A12EB63}'] // Register a service with this TMultiplexedProcessor. This allows us // to broker requests to individual services by using the service name // to select them at request time. procedure RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean = FALSE); end; TMultiplexedProcessorImpl = class( TInterfacedObject, IMultiplexedProcessor, IProcessor) strict private type // Our goal was to work with any protocol. In order to do that, we needed // to allow them to call readMessageBegin() and get a TMessage in exactly // the standard format, without the service name prepended to TMessage.name. TStoredMessageProtocol = class( TProtocolDecorator) strict private FMessageBegin : TThriftMessage; public constructor Create( const protocol : IProtocol; const aMsgBegin : TThriftMessage); function ReadMessageBegin: TThriftMessage; override; end; strict private FServiceProcessorMap : TDictionary; FDefaultProcessor : IProcessor; procedure Error( const oprot : IProtocol; const msg : TThriftMessage; extype : TApplicationExceptionSpecializedClass; const etxt : string); public constructor Create; destructor Destroy; override; // Register a service with this TMultiplexedProcessorImpl. This allows us // to broker requests to individual services by using the service name // to select them at request time. procedure RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean = FALSE); { This implementation of process performs the following steps: - Read the beginning of the message. - Extract the service name from the message. - Using the service name to locate the appropriate processor. - Dispatch to the processor, with a decorated instance of TProtocol that allows readMessageBegin() to return the original TMessage. An exception is thrown if the message type is not CALL or ONEWAY or if the service is unknown (or not properly registered). } function Process( const iprot, oprot: IProtocol; const events : IProcessorEvents = nil): Boolean; end; implementation constructor TMultiplexedProcessorImpl.TStoredMessageProtocol.Create( const protocol : IProtocol; const aMsgBegin : TThriftMessage); begin inherited Create( protocol); FMessageBegin := aMsgBegin; end; constructor TMultiplexedProcessorImpl.Create; begin inherited Create; FServiceProcessorMap := TDictionary.Create; end; destructor TMultiplexedProcessorImpl.Destroy; begin try FreeAndNil( FServiceProcessorMap); finally inherited Destroy; end; end; function TMultiplexedProcessorImpl.TStoredMessageProtocol.ReadMessageBegin: TThriftMessage; begin Reset; result := FMessageBegin; end; procedure TMultiplexedProcessorImpl.RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean); begin FServiceProcessorMap.Add( serviceName, processor); if asDefault then begin if FDefaultProcessor = nil then FDefaultProcessor := processor else raise TApplicationExceptionInternalError.Create('Only one default service allowed'); end; end; procedure TMultiplexedProcessorImpl.Error( const oprot : IProtocol; const msg : TThriftMessage; extype : TApplicationExceptionSpecializedClass; const etxt : string); var appex : TApplicationException; newMsg : TThriftMessage; begin appex := extype.Create(etxt); try Init( newMsg, msg.Name, TMessageType.Exception, msg.SeqID); oprot.WriteMessageBegin(newMsg); appex.Write(oprot); oprot.WriteMessageEnd(); oprot.Transport.Flush(); finally appex.Free; end; end; function TMultiplexedProcessorImpl.Process(const iprot, oprot : IProtocol; const events : IProcessorEvents = nil): Boolean; var msg, newMsg : TThriftMessage; idx : Integer; sService : string; processor : IProcessor; protocol : IProtocol; const ERROR_INVALID_MSGTYPE = 'Message must be "call" or "oneway"'; ERROR_INCOMPATIBLE_PROT = 'No service name found in "%s". Client is expected to use TMultiplexProtocol.'; ERROR_UNKNOWN_SERVICE = 'Service "%s" is not registered with MultiplexedProcessor'; begin // Use the actual underlying protocol (e.g. TBinaryProtocol) to read the message header. // This pulls the message "off the wire", which we'll deal with at the end of this method. msg := iprot.readMessageBegin(); if not (msg.Type_ in [TMessageType.Call, TMessageType.Oneway]) then begin Error( oprot, msg, TApplicationExceptionInvalidMessageType, ERROR_INVALID_MSGTYPE); Exit( FALSE); end; // Extract the service name // use FDefaultProcessor as fallback if there is no separator idx := Pos( TMultiplexedProtocol.SEPARATOR, msg.Name); if idx > 0 then begin // Create a new TMessage, something that can be consumed by any TProtocol sService := Copy( msg.Name, 1, idx-1); if not FServiceProcessorMap.TryGetValue( sService, processor) then begin Error( oprot, msg, TApplicationExceptionInternalError, Format(ERROR_UNKNOWN_SERVICE,[sService])); Exit( FALSE); end; // Create a new TMessage, removing the service name Inc( idx, Length(TMultiplexedProtocol.SEPARATOR)); Init( newMsg, Copy( msg.Name, idx, MAXINT), msg.Type_, msg.SeqID); end else if FDefaultProcessor <> nil then begin processor := FDefaultProcessor; newMsg := msg; // no need to change end else begin Error( oprot, msg, TApplicationExceptionInvalidProtocol, Format(ERROR_INCOMPATIBLE_PROT,[msg.Name])); Exit( FALSE); end; // Dispatch processing to the stored processor protocol := TStoredMessageProtocol.Create( iprot, newMsg); result := processor.process( protocol, oprot, events); end; end. thrift-0.19.0/lib/delphi/src/Thrift.Configuration.pas0000644000000000000000000000635614303740367022475 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Configuration; interface uses SysUtils, Generics.Collections, Generics.Defaults; const DEFAULT_RECURSION_LIMIT = 64; DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; // 100 MB DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms type IThriftConfiguration = interface ['{ADD75449-1A67-4B78-9B75-502A1E338CFC}'] function GetRecursionLimit : Cardinal; procedure SetRecursionLimit( const value : Cardinal); function GetMaxFrameSize : Cardinal; procedure SetMaxFrameSize( const value : Cardinal); function GetMaxMessageSize : Cardinal; procedure SetMaxMessageSize( const value : Cardinal); property RecursionLimit : Cardinal read GetRecursionLimit write SetRecursionLimit; property MaxFrameSize : Cardinal read GetMaxFrameSize write SetMaxFrameSize; property MaxMessageSize : Cardinal read GetMaxMessageSize write SetMaxMessageSize; end; TThriftConfigurationImpl = class( TInterfacedObject, IThriftConfiguration) strict protected FRecursionLimit : Cardinal; FMaxFrameSize : Cardinal; FMaxMessageSize : Cardinal; // IThriftConfiguration function GetRecursionLimit : Cardinal; procedure SetRecursionLimit( const value : Cardinal); function GetMaxFrameSize : Cardinal; procedure SetMaxFrameSize( const value : Cardinal); function GetMaxMessageSize : Cardinal; procedure SetMaxMessageSize( const value : Cardinal); public constructor Create; end; implementation { TThriftConfigurationImpl } constructor TThriftConfigurationImpl.Create; begin inherited Create; FRecursionLimit := DEFAULT_RECURSION_LIMIT; FMaxFrameSize := DEFAULT_MAX_FRAME_SIZE; FMaxMessageSize := DEFAULT_MAX_MESSAGE_SIZE; end; function TThriftConfigurationImpl.GetRecursionLimit: Cardinal; begin result := FRecursionLimit; end; procedure TThriftConfigurationImpl.SetRecursionLimit(const value: Cardinal); begin FRecursionLimit := value; end; function TThriftConfigurationImpl.GetMaxFrameSize: Cardinal; begin result := FMaxFrameSize; end; procedure TThriftConfigurationImpl.SetMaxFrameSize(const value: Cardinal); begin FMaxFrameSize := value; end; function TThriftConfigurationImpl.GetMaxMessageSize: Cardinal; begin result := FMaxMessageSize; end; procedure TThriftConfigurationImpl.SetMaxMessageSize(const value: Cardinal); begin FMaxMessageSize := value; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Protocol.Compact.pas0000644000000000000000000010467714370300523023047 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) {$SCOPEDENUMS ON} unit Thrift.Protocol.Compact; interface uses Classes, SysUtils, Math, Generics.Collections, Thrift.Configuration, Thrift.Transport, Thrift.Protocol, Thrift.Utils; type ICompactProtocol = interface( IProtocol) ['{C01927EC-021A-45F7-93B1-23D6A5420EDD}'] end; // Compact protocol implementation for thrift. // Adapted from the C# version. TCompactProtocolImpl = class( TProtocolImpl, ICompactProtocol) public type TFactory = class( TInterfacedObject, IProtocolFactory) public function GetProtocol( const trans: ITransport): IProtocol; end; strict private const { TODO static TStruct ANONYMOUS_STRUCT = new TStruct(""); static TField TSTOP = new TField("", TType.Stop, (short)0); } PROTOCOL_ID = Byte( $82); VERSION = Byte( 1); VERSION_MASK = Byte( $1F); // 0001 1111 TYPE_MASK = Byte( $E0); // 1110 0000 TYPE_BITS = Byte( $07); // 0000 0111 TYPE_SHIFT_AMOUNT = Byte( 5); strict private type // All of the on-wire type codes. Types = ( STOP = $00, BOOLEAN_TRUE = $01, BOOLEAN_FALSE = $02, BYTE_ = $03, I16 = $04, I32 = $05, I64 = $06, DOUBLE_ = $07, BINARY = $08, LIST = $09, SET_ = $0A, MAP = $0B, STRUCT = $0C, UUID = $0D ); private type TEightBytesArray = packed array[0..7] of Byte; strict private const ttypeToCompactType : array[TType] of Types = ( Types.STOP, // Stop = 0, Types(-1), // Void = 1, Types.BOOLEAN_TRUE, // Bool_ = 2, Types.BYTE_, // Byte_ = 3, Types.DOUBLE_, // Double_ = 4, Types(-5), // unused Types.I16, // I16 = 6, Types(-7), // unused Types.I32, // I32 = 8, Types(-9), // unused Types.I64, // I64 = 10, Types.BINARY, // String_ = 11, Types.STRUCT, // Struct = 12, Types.MAP, // Map = 13, Types.SET_, // Set_ = 14, Types.LIST, // List = 15, Types.UUID // Uuid = 16 ); tcompactTypeToType : array[Types] of TType = ( TType.Stop, // STOP TType.Bool_, // BOOLEAN_TRUE TType.Bool_, // BOOLEAN_FALSE TType.Byte_, // BYTE_ TType.I16, // I16 TType.I32, // I32 TType.I64, // I64 TType.Double_, // DOUBLE_ TType.String_, // BINARY TType.List, // LIST TType.Set_, // SET_ TType.Map, // MAP TType.Struct, // STRUCT TType.Uuid // UUID ); strict private // Used to keep track of the last field for the current and previous structs, // so we can do the delta stuff. lastField_ : TStack; lastFieldId_ : Integer; // If we encounter a boolean field begin, save the TField here so it can // have the value incorporated. strict private booleanField_ : TThriftField; // If we Read a field header, and it's a boolean field, save the boolean // value here so that ReadBool can use it. strict private boolValue_ : ( unused, bool_true, bool_false); public constructor Create(const trans : ITransport); override; destructor Destroy; override; strict private procedure WriteByteDirect( const b : Byte); overload; // Writes a byte without any possibility of all that field header nonsense. procedure WriteByteDirect( const n : Integer); overload; // Write an i32 as a varint. Results in 1-5 bytes on the wire. // TODO: make a permanent buffer like WriteVarint64? procedure WriteVarint32( n : Cardinal); strict private // The workhorse of WriteFieldBegin. It has the option of doing a 'type override' // of the type header. This is used specifically in the boolean field case. procedure WriteFieldBeginInternal( const field : TThriftField; typeOverride : Byte); public procedure WriteMessageBegin( const msg: TThriftMessage); override; procedure WriteMessageEnd; override; procedure WriteStructBegin( const struc: TThriftStruct); override; procedure WriteStructEnd; override; procedure WriteFieldBegin( const field: TThriftField); override; procedure WriteFieldEnd; override; procedure WriteFieldStop; override; procedure WriteMapBegin( const map: TThriftMap); override; procedure WriteMapEnd; override; procedure WriteListBegin( const list: TThriftList); override; procedure WriteListEnd(); override; procedure WriteSetBegin( const set_: TThriftSet ); override; procedure WriteSetEnd(); override; procedure WriteBool( b: Boolean); override; procedure WriteByte( b: ShortInt); override; procedure WriteI16( i16: SmallInt); override; procedure WriteI32( i32: Integer); override; procedure WriteI64( const i64: Int64); override; procedure WriteDouble( const dub: Double); override; procedure WriteBinary( const b: TBytes); overload; override; procedure WriteUuid( const uuid: TGuid); override; private // unit visible stuff class function DoubleToInt64Bits( const db : Double) : Int64; class function Int64BitsToDouble( const i64 : Int64) : Double; // Abstract method for writing the start of lists and sets. List and sets on // the wire differ only by the type indicator. procedure WriteCollectionBegin( const elemType : TType; size : Integer); procedure WriteVarint64( n : UInt64); // Convert l into a zigzag long. This allows negative numbers to be // represented compactly as a varint. class function longToZigzag( const n : Int64) : UInt64; // Convert n into a zigzag int. This allows negative numbers to be // represented compactly as a varint. class function intToZigZag( const n : Integer) : Cardinal; //Convert a Int64 into little-endian bytes in buf starting at off and going until off+7. class procedure fixedLongToBytes( const n : Int64; var buf : TEightBytesArray); inline; strict protected function GetMinSerializedSize( const aType : TType) : Integer; override; procedure Reset; override; public function ReadMessageBegin: TThriftMessage; override; procedure ReadMessageEnd(); override; function ReadStructBegin: TThriftStruct; override; procedure ReadStructEnd; override; function ReadFieldBegin: TThriftField; override; procedure ReadFieldEnd(); override; function ReadMapBegin: TThriftMap; override; procedure ReadMapEnd(); override; function ReadListBegin: TThriftList; override; procedure ReadListEnd(); override; function ReadSetBegin: TThriftSet; override; procedure ReadSetEnd(); override; function ReadBool: Boolean; override; function ReadByte: ShortInt; override; function ReadI16: SmallInt; override; function ReadI32: Integer; override; function ReadI64: Int64; override; function ReadDouble:Double; override; function ReadBinary: TBytes; overload; override; function ReadUuid: TGuid; override; private // Internal Reading methods // Read an i32 from the wire as a varint. The MSB of each byte is set // if there is another byte to follow. This can Read up to 5 bytes. function ReadVarint32 : Cardinal; // Read an i64 from the wire as a proper varint. The MSB of each byte is set // if there is another byte to follow. This can Read up to 10 bytes. function ReadVarint64 : UInt64; // encoding helpers // Convert from zigzag Integer to Integer. class function zigzagToInt( const n : Cardinal ) : Integer; // Convert from zigzag Int64 to Int64. class function zigzagToLong( const n : UInt64) : Int64; // Note that it's important that the mask bytes are Int64 literals, // otherwise they'll default to ints, and when you shift an Integer left 56 bits, // you just get a messed up Integer. class function bytesToLong( const bytes : TEightBytesArray) : Int64; inline; // type testing and converting class function isBoolType( const b : byte) : Boolean; // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. class function getTType( const type_ : byte) : TType; // Given a TType value, find the appropriate TCompactProtocol.Types constant. class function getCompactType( const ttype : TType) : Byte; end; implementation //--- TCompactProtocolImpl.TFactory ---------------------------------------- function TCompactProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IProtocol; begin result := TCompactProtocolImpl.Create( trans); end; //--- TCompactProtocolImpl ------------------------------------------------- constructor TCompactProtocolImpl.Create( const trans : ITransport); begin inherited Create( trans); lastFieldId_ := 0; lastField_ := TStack.Create; Init( booleanField_, '', TType.Stop, 0); boolValue_ := unused; end; destructor TCompactProtocolImpl.Destroy; begin try FreeAndNil( lastField_); finally inherited Destroy; end; end; procedure TCompactProtocolImpl.Reset; begin inherited Reset; lastField_.Clear(); lastFieldId_ := 0; Init( booleanField_, '', TType.Stop, 0); boolValue_ := unused; end; // Writes a byte without any possibility of all that field header nonsense. // Used internally by other writing methods that know they need to Write a byte. procedure TCompactProtocolImpl.WriteByteDirect( const b : Byte); begin Transport.Write( @b, SizeOf(b)); end; // Writes a byte without any possibility of all that field header nonsense. procedure TCompactProtocolImpl.WriteByteDirect( const n : Integer); begin WriteByteDirect( Byte(n)); end; // Write an i32 as a varint. Results in 1-5 bytes on the wire. procedure TCompactProtocolImpl.WriteVarint32( n : Cardinal); var idx : Integer; i32buf : packed array[0..4] of Byte; begin idx := 0; while TRUE do begin ASSERT( idx < Length(i32buf)); // last part? if ((n and not $7F) = 0) then begin i32buf[idx] := Byte(n); Inc(idx); Break; end; i32buf[idx] := Byte((n and $7F) or $80); Inc(idx); n := n shr 7; end; Transport.Write( @i32buf[0], 0, idx); end; // Write a message header to the wire. Compact Protocol messages contain the // protocol version so we can migrate forwards in the future if need be. procedure TCompactProtocolImpl.WriteMessageBegin( const msg: TThriftMessage); var versionAndType : Byte; begin Reset; versionAndType := Byte( VERSION and VERSION_MASK) or Byte( (Cardinal(msg.Type_) shl TYPE_SHIFT_AMOUNT) and TYPE_MASK); WriteByteDirect( PROTOCOL_ID); WriteByteDirect( versionAndType); WriteVarint32( Cardinal(msg.SeqID)); WriteString( msg.Name); end; // Write a struct begin. This doesn't actually put anything on the wire. We use it as an // opportunity to put special placeholder markers on the field stack so we can get the // field id deltas correct. procedure TCompactProtocolImpl.WriteStructBegin( const struc: TThriftStruct); begin lastField_.Push(lastFieldId_); lastFieldId_ := 0; end; // Write a struct end. This doesn't actually put anything on the wire. We use this as an // opportunity to pop the last field from the current struct off of the field stack. procedure TCompactProtocolImpl.WriteStructEnd; begin lastFieldId_ := lastField_.Pop(); end; // Write a field header containing the field id and field type. If the difference between the // current field id and the last one is small (< 15), then the field id will be encoded in // the 4 MSB as a delta. Otherwise, the field id will follow the type header as a zigzag varint. procedure TCompactProtocolImpl.WriteFieldBegin( const field: TThriftField); begin case field.Type_ of TType.Bool_ : booleanField_ := field; // we want to possibly include the value, so we'll wait. else WriteFieldBeginInternal(field, $FF); end; end; // The workhorse of WriteFieldBegin. It has the option of doing a 'type override' // of the type header. This is used specifically in the boolean field case. procedure TCompactProtocolImpl.WriteFieldBeginInternal( const field : TThriftField; typeOverride : Byte); var typeToWrite : Byte; begin // if there's a type override, use that. if typeOverride = $FF then typeToWrite := getCompactType( field.Type_) else typeToWrite := typeOverride; // check if we can use delta encoding for the field id if (field.ID > lastFieldId_) and ((field.ID - lastFieldId_) <= 15) then begin // Write them together WriteByteDirect( ((field.ID - lastFieldId_) shl 4) or typeToWrite); end else begin // Write them separate WriteByteDirect( typeToWrite); WriteI16( field.ID); end; lastFieldId_ := field.ID; end; // Write the STOP symbol so we know there are no more fields in this struct. procedure TCompactProtocolImpl.WriteFieldStop; begin WriteByteDirect( Byte( Types.STOP)); end; // Write a map header. If the map is empty, omit the key and value type // headers, as we don't need any additional information to skip it. procedure TCompactProtocolImpl.WriteMapBegin( const map: TThriftMap); var key, val : Byte; begin if (map.Count = 0) then WriteByteDirect( 0) else begin WriteVarint32( Cardinal( map.Count)); key := getCompactType(map.KeyType); val := getCompactType(map.ValueType); WriteByteDirect( (key shl 4) or val); end; end; // Write a list header. procedure TCompactProtocolImpl.WriteListBegin( const list: TThriftList); begin WriteCollectionBegin( list.ElementType, list.Count); end; // Write a set header. procedure TCompactProtocolImpl.WriteSetBegin( const set_: TThriftSet ); begin WriteCollectionBegin( set_.ElementType, set_.Count); end; // Write a boolean value. Potentially, this could be a boolean field, in // which case the field header info isn't written yet. If so, decide what the // right type header is for the value and then Write the field header. // Otherwise, Write a single byte. procedure TCompactProtocolImpl.WriteBool( b: Boolean); var bt : Types; begin if b then bt := Types.BOOLEAN_TRUE else bt := Types.BOOLEAN_FALSE; if booleanField_.Type_ = TType.Bool_ then begin // we haven't written the field header yet WriteFieldBeginInternal( booleanField_, Byte(bt)); booleanField_.Type_ := TType.Stop; end else begin // we're not part of a field, so just Write the value. WriteByteDirect( Byte(bt)); end; end; // Write a byte. Nothing to see here! procedure TCompactProtocolImpl.WriteByte( b: ShortInt); begin WriteByteDirect( Byte(b)); end; // Write an I16 as a zigzag varint. procedure TCompactProtocolImpl.WriteI16( i16: SmallInt); begin WriteVarint32( intToZigZag( i16)); end; // Write an i32 as a zigzag varint. procedure TCompactProtocolImpl.WriteI32( i32: Integer); begin WriteVarint32( intToZigZag( i32)); end; // Write an i64 as a zigzag varint. procedure TCompactProtocolImpl.WriteI64( const i64: Int64); begin WriteVarint64( longToZigzag( i64)); end; class function TCompactProtocolImpl.DoubleToInt64Bits( const db : Double) : Int64; begin ASSERT( SizeOf(db) = SizeOf(result)); Move( db, result, SizeOf(result)); end; class function TCompactProtocolImpl.Int64BitsToDouble( const i64 : Int64) : Double; begin ASSERT( SizeOf(i64) = SizeOf(result)); Move( i64, result, SizeOf(result)); end; // Write a double to the wire as 8 bytes. procedure TCompactProtocolImpl.WriteDouble( const dub: Double); var data : TEightBytesArray; begin fixedLongToBytes( DoubleToInt64Bits(dub), data); Transport.Write( @data[0], 0, SizeOf(data)); end; // Write a byte array, using a varint for the size. procedure TCompactProtocolImpl.WriteBinary( const b: TBytes); begin WriteVarint32( Cardinal(Length(b))); Transport.Write( b); end; procedure TCompactProtocolImpl.WriteUuid( const uuid: TGuid); var network : TGuid; // in network order (Big Endian) begin ASSERT( SizeOf(uuid) = 16); network := GuidUtils.SwapByteOrder(uuid); Transport.Write( @network, 0, SizeOf(network)); end; procedure TCompactProtocolImpl.WriteMessageEnd; begin // nothing to do end; procedure TCompactProtocolImpl.WriteMapEnd; begin // nothing to do end; procedure TCompactProtocolImpl.WriteListEnd; begin // nothing to do end; procedure TCompactProtocolImpl.WriteSetEnd; begin // nothing to do end; procedure TCompactProtocolImpl.WriteFieldEnd; begin // nothing to do end; // Abstract method for writing the start of lists and sets. List and sets on // the wire differ only by the type indicator. procedure TCompactProtocolImpl.WriteCollectionBegin( const elemType : TType; size : Integer); begin if size <= 14 then WriteByteDirect( (size shl 4) or getCompactType(elemType)) else begin WriteByteDirect( $F0 or getCompactType(elemType)); WriteVarint32( Cardinal(size)); end; end; // Write an i64 as a varint. Results in 1-10 bytes on the wire. procedure TCompactProtocolImpl.WriteVarint64( n : UInt64); var idx : Integer; varint64out : packed array[0..9] of Byte; begin idx := 0; while TRUE do begin ASSERT( idx < Length(varint64out)); // last one? if (n and not UInt64($7F)) = 0 then begin varint64out[idx] := Byte(n); Inc(idx); Break; end; varint64out[idx] := Byte((n and $7F) or $80); Inc(idx); n := n shr 7; end; Transport.Write( @varint64out[0], 0, idx); end; // Convert l into a zigzag Int64. This allows negative numbers to be // represented compactly as a varint. class function TCompactProtocolImpl.longToZigzag( const n : Int64) : UInt64; begin // there is no arithmetic right shift in Delphi if n >= 0 then result := UInt64(n shl 1) else result := UInt64(n shl 1) xor $FFFFFFFFFFFFFFFF; end; // Convert n into a zigzag Integer. This allows negative numbers to be // represented compactly as a varint. class function TCompactProtocolImpl.intToZigZag( const n : Integer) : Cardinal; begin // there is no arithmetic right shift in Delphi if n >= 0 then result := Cardinal(n shl 1) else result := Cardinal(n shl 1) xor $FFFFFFFF; end; // Convert a Int64 into 8 little-endian bytes in buf class procedure TCompactProtocolImpl.fixedLongToBytes( const n : Int64; var buf : TEightBytesArray); begin ASSERT( Length(buf) >= 8); buf[0] := Byte( n and $FF); buf[1] := Byte((n shr 8) and $FF); buf[2] := Byte((n shr 16) and $FF); buf[3] := Byte((n shr 24) and $FF); buf[4] := Byte((n shr 32) and $FF); buf[5] := Byte((n shr 40) and $FF); buf[6] := Byte((n shr 48) and $FF); buf[7] := Byte((n shr 56) and $FF); end; // Read a message header. function TCompactProtocolImpl.ReadMessageBegin : TThriftMessage; var protocolId, versionAndType, version, type_ : Byte; seqid : Integer; msgNm : String; begin Reset; protocolId := Byte( ReadByte); if (protocolId <> PROTOCOL_ID) then raise TProtocolExceptionBadVersion.Create( 'Expected protocol id ' + IntToHex(PROTOCOL_ID,2) + ' but got ' + IntToHex(protocolId,2)); versionAndType := Byte( ReadByte); version := Byte( versionAndType and VERSION_MASK); if (version <> VERSION) then raise TProtocolExceptionBadVersion.Create( 'Expected version ' +IntToStr(VERSION) + ' but got ' + IntToStr(version)); type_ := Byte( (versionAndType shr TYPE_SHIFT_AMOUNT) and TYPE_BITS); seqid := Integer( ReadVarint32); msgNm := ReadString; Init( result, msgNm, TMessageType(type_), seqid); end; // Read a struct begin. There's nothing on the wire for this, but it is our // opportunity to push a new struct begin marker onto the field stack. function TCompactProtocolImpl.ReadStructBegin: TThriftStruct; begin lastField_.Push( lastFieldId_); lastFieldId_ := 0; Init( result); end; // Doesn't actually consume any wire data, just removes the last field for // this struct from the field stack. procedure TCompactProtocolImpl.ReadStructEnd; begin // consume the last field we Read off the wire. lastFieldId_ := lastField_.Pop(); end; // Read a field header off the wire. function TCompactProtocolImpl.ReadFieldBegin: TThriftField; var type_ : Byte; modifier : ShortInt; fieldId : SmallInt; begin type_ := Byte( ReadByte); // if it's a stop, then we can return immediately, as the struct is over. if type_ = Byte(Types.STOP) then begin Init( result, '', TType.Stop, 0); Exit; end; // mask off the 4 MSB of the type header. it could contain a field id delta. modifier := ShortInt( (type_ and $F0) shr 4); if (modifier = 0) then fieldId := ReadI16 // not a delta. look ahead for the zigzag varint field id. else fieldId := SmallInt( lastFieldId_ + modifier); // add the delta to the last Read field id. Init( result, '', getTType(Byte(type_ and $0F)), fieldId); // if this happens to be a boolean field, the value is encoded in the type // save the boolean value in a special instance variable. if isBoolType(type_) then begin if Byte(type_ and $0F) = Byte(Types.BOOLEAN_TRUE) then boolValue_ := bool_true else boolValue_ := bool_false; end; // push the new field onto the field stack so we can keep the deltas going. lastFieldId_ := result.ID; end; // Read a map header off the wire. If the size is zero, skip Reading the key // and value type. This means that 0-length maps will yield TMaps without the // "correct" types. function TCompactProtocolImpl.ReadMapBegin: TThriftMap; var size : Integer; keyAndValueType : Byte; key, val : TType; begin size := Integer( ReadVarint32); if size = 0 then keyAndValueType := 0 else keyAndValueType := Byte( ReadByte); key := getTType( Byte( keyAndValueType shr 4)); val := getTType( Byte( keyAndValueType and $F)); Init( result, key, val, size); ASSERT( (result.KeyType = key) and (result.ValueType = val)); CheckReadBytesAvailable(result); end; // Read a list header off the wire. If the list size is 0-14, the size will // be packed into the element type header. If it's a longer list, the 4 MSB // of the element type header will be $F, and a varint will follow with the // true size. function TCompactProtocolImpl.ReadListBegin: TThriftList; var size_and_type : Byte; size : Integer; type_ : TType; begin size_and_type := Byte( ReadByte); size := (size_and_type shr 4) and $0F; if (size = 15) then size := Integer( ReadVarint32); type_ := getTType( size_and_type); Init( result, type_, size); CheckReadBytesAvailable(result); end; // Read a set header off the wire. If the set size is 0-14, the size will // be packed into the element type header. If it's a longer set, the 4 MSB // of the element type header will be $F, and a varint will follow with the // true size. function TCompactProtocolImpl.ReadSetBegin: TThriftSet; var size_and_type : Byte; size : Integer; type_ : TType; begin size_and_type := Byte( ReadByte); size := (size_and_type shr 4) and $0F; if (size = 15) then size := Integer( ReadVarint32); type_ := getTType( size_and_type); Init( result, type_, size); CheckReadBytesAvailable(result); end; // Read a boolean off the wire. If this is a boolean field, the value should // already have been Read during ReadFieldBegin, so we'll just consume the // pre-stored value. Otherwise, Read a byte. function TCompactProtocolImpl.ReadBool: Boolean; begin if boolValue_ <> unused then begin result := (boolValue_ = bool_true); boolValue_ := unused; Exit; end; result := (Byte(ReadByte) = Byte(Types.BOOLEAN_TRUE)); end; // Read a single byte off the wire. Nothing interesting here. function TCompactProtocolImpl.ReadByte: ShortInt; begin Transport.ReadAll( @result, SizeOf(result), 0, 1); end; // Read an i16 from the wire as a zigzag varint. function TCompactProtocolImpl.ReadI16: SmallInt; begin result := SmallInt( zigzagToInt( ReadVarint32)); end; // Read an i32 from the wire as a zigzag varint. function TCompactProtocolImpl.ReadI32: Integer; begin result := zigzagToInt( ReadVarint32); end; // Read an i64 from the wire as a zigzag varint. function TCompactProtocolImpl.ReadI64: Int64; begin result := zigzagToLong( ReadVarint64); end; // No magic here - just Read a double off the wire. function TCompactProtocolImpl.ReadDouble : Double; var longBits : TEightBytesArray; begin ASSERT( SizeOf(longBits) = SizeOf(result)); Transport.ReadAll( @longBits[0], SizeOf(longBits), 0, SizeOf(longBits)); result := Int64BitsToDouble( bytesToLong( longBits)); end; // Read a byte[] from the wire. function TCompactProtocolImpl.ReadBinary: TBytes; var length : Integer; begin length := Integer( ReadVarint32); FTrans.CheckReadBytesAvailable(length); SetLength( result, length); if (length > 0) then Transport.ReadAll( result, 0, length); end; function TCompactProtocolImpl.ReadUuid: TGuid; var network : TGuid; // in network order (Big Endian) begin ASSERT( SizeOf(result) = 16); FTrans.ReadAll( @network, SizeOf(network), 0, SizeOf(network)); result := GuidUtils.SwapByteOrder(network); end; procedure TCompactProtocolImpl.ReadMessageEnd; begin // nothing to do end; procedure TCompactProtocolImpl.ReadFieldEnd; begin // nothing to do end; procedure TCompactProtocolImpl.ReadMapEnd; begin // nothing to do end; procedure TCompactProtocolImpl.ReadListEnd; begin // nothing to do end; procedure TCompactProtocolImpl.ReadSetEnd; begin // nothing to do end; // Read an i32 from the wire as a varint. The MSB of each byte is set // if there is another byte to follow. This can Read up to 5 bytes. function TCompactProtocolImpl.ReadVarint32 : Cardinal; var shift : Integer; b : Byte; begin result := 0; shift := 0; while TRUE do begin b := Byte( ReadByte); result := result or (Cardinal(b and $7F) shl shift); if ((b and $80) <> $80) then Break; Inc( shift, 7); end; end; // Read an i64 from the wire as a proper varint. The MSB of each byte is set // if there is another byte to follow. This can Read up to 10 bytes. function TCompactProtocolImpl.ReadVarint64 : UInt64; var shift : Integer; b : Byte; begin result := 0; shift := 0; while TRUE do begin b := Byte( ReadByte); result := result or (UInt64(b and $7F) shl shift); if ((b and $80) <> $80) then Break; Inc( shift, 7); end; end; // Convert from zigzag Integer to Integer. class function TCompactProtocolImpl.zigzagToInt( const n : Cardinal ) : Integer; begin result := Integer(n shr 1) xor (-Integer(n and 1)); end; // Convert from zigzag Int64 to Int64. class function TCompactProtocolImpl.zigzagToLong( const n : UInt64) : Int64; begin result := Int64(n shr 1) xor (-Int64(n and 1)); end; // Note that it's important that the mask bytes are Int64 literals, // otherwise they'll default to ints, and when you shift an Integer left 56 bits, // you just get a messed up Integer. class function TCompactProtocolImpl.bytesToLong( const bytes : TEightBytesArray) : Int64; begin ASSERT( Length(bytes) >= 8); result := (Int64(bytes[7] and $FF) shl 56) or (Int64(bytes[6] and $FF) shl 48) or (Int64(bytes[5] and $FF) shl 40) or (Int64(bytes[4] and $FF) shl 32) or (Int64(bytes[3] and $FF) shl 24) or (Int64(bytes[2] and $FF) shl 16) or (Int64(bytes[1] and $FF) shl 8) or (Int64(bytes[0] and $FF)); end; class function TCompactProtocolImpl.isBoolType( const b : byte) : Boolean; var lowerNibble : Byte; begin lowerNibble := b and $0f; result := (Types(lowerNibble) in [Types.BOOLEAN_TRUE, Types.BOOLEAN_FALSE]); end; // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. class function TCompactProtocolImpl.getTType( const type_ : byte) : TType; var tct : Types; begin tct := Types( type_ and $0F); if tct in [Low(Types)..High(Types)] then result := tcompactTypeToType[tct] else raise TProtocolExceptionInvalidData.Create('don''t know what type: '+IntToStr(Ord(tct))); end; // Given a TType value, find the appropriate TCompactProtocol.Types constant. class function TCompactProtocolImpl.getCompactType( const ttype : TType) : Byte; begin if ttype in VALID_TTYPES then result := Byte( ttypeToCompactType[ttype]) else raise TProtocolExceptionInvalidData.Create('don''t know what type: '+IntToStr(Ord(ttype))); end; function TCompactProtocolImpl.GetMinSerializedSize( const aType : TType) : Integer; // Return the minimum number of bytes a type will consume on the wire begin case aType of TType.Stop: result := 0; TType.Void: result := 0; TType.Bool_: result := SizeOf(Byte); TType.Byte_: result := SizeOf(Byte); TType.Double_: result := 8; // uses fixedLongToBytes() which always writes 8 bytes TType.I16: result := SizeOf(Byte); TType.I32: result := SizeOf(Byte); TType.I64: result := SizeOf(Byte); TType.String_: result := SizeOf(Byte); // string length TType.Struct: result := 0; // empty struct TType.Map: result := SizeOf(Byte); // element count TType.Set_: result := SizeOf(Byte); // element count TType.List: result := SizeOf(Byte); // element count TType.Uuid: result := SizeOf(TGuid); else raise TTransportExceptionBadArgs.Create('Unhandled type code'); end; end; //--- unit tests ------------------------------------------- {$IFDEF Debug} procedure TestDoubleToInt64Bits; procedure TestPair( const a : Double; const b : Int64); begin ASSERT( TCompactProtocolImpl.DoubleToInt64Bits(a) = b); ASSERT( TCompactProtocolImpl.Int64BitsToDouble(b) = a); end; begin TestPair( 1.0000000000000000E+000, Int64($3FF0000000000000)); TestPair( 1.5000000000000000E+001, Int64($402E000000000000)); TestPair( 2.5500000000000000E+002, Int64($406FE00000000000)); TestPair( 4.2949672950000000E+009, Int64($41EFFFFFFFE00000)); TestPair( 3.9062500000000000E-003, Int64($3F70000000000000)); TestPair( 2.3283064365386963E-010, Int64($3DF0000000000000)); TestPair( 1.2345678901230000E-300, Int64($01AA74FE1C1E7E45)); TestPair( 1.2345678901234500E-150, Int64($20D02A36586DB4BB)); TestPair( 1.2345678901234565E+000, Int64($3FF3C0CA428C59FA)); TestPair( 1.2345678901234567E+000, Int64($3FF3C0CA428C59FB)); TestPair( 1.2345678901234569E+000, Int64($3FF3C0CA428C59FC)); TestPair( 1.2345678901234569E+150, Int64($5F182344CD3CDF9F)); TestPair( 1.2345678901234569E+300, Int64($7E3D7EE8BCBBD352)); TestPair( -1.7976931348623157E+308, Int64($FFEFFFFFFFFFFFFF)); TestPair( 1.7976931348623157E+308, Int64($7FEFFFFFFFFFFFFF)); TestPair( 4.9406564584124654E-324, Int64($0000000000000001)); TestPair( 0.0000000000000000E+000, Int64($0000000000000000)); TestPair( 4.94065645841247E-324, Int64($0000000000000001)); TestPair( 3.2378592100206092E-319, Int64($000000000000FFFF)); TestPair( 1.3906711615669959E-309, Int64($0000FFFFFFFFFFFF)); TestPair( NegInfinity, Int64($FFF0000000000000)); TestPair( Infinity, Int64($7FF0000000000000)); // NaN is special ASSERT( TCompactProtocolImpl.DoubleToInt64Bits( NaN) = Int64($FFF8000000000000)); ASSERT( IsNan( TCompactProtocolImpl.Int64BitsToDouble( Int64($FFF8000000000000)))); end; {$ENDIF} {$IFDEF Debug} procedure TestZigZag; procedure Test32( const test : Integer); var zz : Cardinal; begin zz := TCompactProtocolImpl.intToZigZag(test); ASSERT( TCompactProtocolImpl.zigzagToInt(zz) = test, IntToStr(test)); end; procedure Test64( const test : Int64); var zz : UInt64; begin zz := TCompactProtocolImpl.longToZigzag(test); ASSERT( TCompactProtocolImpl.zigzagToLong(zz) = test, IntToStr(test)); end; var i : Integer; begin // protobuf testcases ASSERT( TCompactProtocolImpl.intToZigZag(0) = 0, 'pb #1 to ZigZag'); ASSERT( TCompactProtocolImpl.intToZigZag(-1) = 1, 'pb #2 to ZigZag'); ASSERT( TCompactProtocolImpl.intToZigZag(1) = 2, 'pb #3 to ZigZag'); ASSERT( TCompactProtocolImpl.intToZigZag(-2) = 3, 'pb #4 to ZigZag'); ASSERT( TCompactProtocolImpl.intToZigZag(+2147483647) = 4294967294, 'pb #5 to ZigZag'); ASSERT( TCompactProtocolImpl.intToZigZag(-2147483648) = 4294967295, 'pb #6 to ZigZag'); // protobuf testcases ASSERT( TCompactProtocolImpl.zigzagToInt(0) = 0, 'pb #1 from ZigZag'); ASSERT( TCompactProtocolImpl.zigzagToInt(1) = -1, 'pb #2 from ZigZag'); ASSERT( TCompactProtocolImpl.zigzagToInt(2) = 1, 'pb #3 from ZigZag'); ASSERT( TCompactProtocolImpl.zigzagToInt(3) = -2, 'pb #4 from ZigZag'); ASSERT( TCompactProtocolImpl.zigzagToInt(4294967294) = +2147483647, 'pb #5 from ZigZag'); ASSERT( TCompactProtocolImpl.zigzagToInt(4294967295) = -2147483648, 'pb #6 from ZigZag'); // back and forth 32 Test32( 0); for i := 0 to 30 do begin Test32( +(Integer(1) shl i)); Test32( -(Integer(1) shl i)); end; Test32( Integer($7FFFFFFF)); Test32( Integer($80000000)); // back and forth 64 Test64( 0); for i := 0 to 62 do begin Test64( +(Int64(1) shl i)); Test64( -(Int64(1) shl i)); end; Test64( Int64($7FFFFFFFFFFFFFFF)); Test64( Int64($8000000000000000)); end; {$ENDIF} {$IFDEF Debug} procedure TestLongBytes; procedure Test( const test : Int64); var buf : TCompactProtocolImpl.TEightBytesArray; begin TCompactProtocolImpl.fixedLongToBytes( test, buf); ASSERT( TCompactProtocolImpl.bytesToLong( buf) = test, IntToStr(test)); end; var i : Integer; begin Test( 0); for i := 0 to 62 do begin Test( +(Int64(1) shl i)); Test( -(Int64(1) shl i)); end; Test( Int64($7FFFFFFFFFFFFFFF)); Test( Int64($8000000000000000)); end; {$ENDIF} {$IFDEF Debug} procedure UnitTest; var w : WORD; const FPU_CW_DENORMALIZED = $0002; begin w := Get8087CW; try Set8087CW( w or FPU_CW_DENORMALIZED); TestDoubleToInt64Bits; TestZigZag; TestLongBytes; finally Set8087CW( w); end; end; {$ENDIF} initialization {$IFDEF Debug} UnitTest; {$ENDIF} end. thrift-0.19.0/lib/delphi/src/Thrift.Transport.WinHTTP.pas0000644000000000000000000002730114303740367023107 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Transport.WinHTTP; {$I Thrift.Defines.inc} {$SCOPEDENUMS ON} interface uses Classes, SysUtils, Math, Generics.Collections, Thrift.Collections, Thrift.Configuration, Thrift.Transport, Thrift.Exception, Thrift.Utils, Thrift.WinHTTP, Thrift.Stream; type TWinHTTPClientImpl = class( TEndpointTransportBase, IHTTPClient) strict private FUri : string; FInputStream : IThriftStream; FOutputMemoryStream : TThriftMemoryStream; FDnsResolveTimeout : Integer; FConnectionTimeout : Integer; FSendTimeout : Integer; FReadTimeout : Integer; FCustomHeaders : IThriftDictionary; FSecureProtocols : TSecureProtocols; function CreateRequest: IWinHTTPRequest; function SecureProtocolsAsWinHTTPFlags : Cardinal; strict private type TErrorInfo = ( SplitUrl, WinHTTPSession, WinHTTPConnection, WinHTTPRequest, RequestSetup, AutoProxy ); THTTPResponseStream = class( TThriftStreamImpl) strict private FRequest : IWinHTTPRequest; strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; public constructor Create( const aRequest : IWinHTTPRequest); destructor Destroy; override; end; strict protected function GetIsOpen: Boolean; override; procedure Open(); override; procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; procedure SetConnectionTimeout(const Value: Integer); function GetConnectionTimeout: Integer; procedure SetSendTimeout(const Value: Integer); function GetSendTimeout: Integer; procedure SetReadTimeout(const Value: Integer); function GetReadTimeout: Integer; function GetSecureProtocols : TSecureProtocols; procedure SetSecureProtocols( const value : TSecureProtocols); function GetCustomHeaders: IThriftDictionary; procedure SendRequest; property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; public constructor Create( const aUri: string; const aConfig : IThriftConfiguration = nil); destructor Destroy; override; end; implementation const WINHTTP_CONNECTION_TIMEOUT = 60 * 1000; WINHTTP_SENDRECV_TIMEOUT = 30 * 1000; { TWinHTTPClientImpl } constructor TWinHTTPClientImpl.Create( const aUri: string; const aConfig : IThriftConfiguration); begin inherited Create( aConfig); FUri := AUri; // defaults according to MSDN FDnsResolveTimeout := 0; // no timeout FConnectionTimeout := WINHTTP_CONNECTION_TIMEOUT; FSendTimeout := WINHTTP_SENDRECV_TIMEOUT; FReadTimeout := WINHTTP_SENDRECV_TIMEOUT; FSecureProtocols := DEFAULT_THRIFT_SECUREPROTOCOLS; FCustomHeaders := TThriftDictionaryImpl.Create; FOutputMemoryStream := TThriftMemoryStream.Create; end; destructor TWinHTTPClientImpl.Destroy; begin Close; FreeAndNil( FOutputMemoryStream); inherited; end; function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; var pair : TPair; session : IWinHTTPSession; connect : IWinHTTPConnection; url : IWinHTTPUrl; sPath : string; info : TErrorInfo; begin info := TErrorInfo.SplitUrl; try url := TWinHTTPUrlImpl.Create( FUri); info := TErrorInfo.WinHTTPSession; session := TWinHTTPSessionImpl.Create('ApacheThriftDelphi/WinHTTP'); session.EnableSecureProtocols( SecureProtocolsAsWinHTTPFlags); info := TErrorInfo.WinHTTPConnection; connect := session.Connect( url.HostName, url.Port); info := TErrorInfo.WinHTTPRequest; sPath := url.UrlPath + url.ExtraInfo; result := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, THRIFT_MIMETYPE); // setting a timeout value to 0 (zero) means "no timeout" for that setting info := TErrorInfo.RequestSetup; result.SetTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); // headers result.AddRequestHeader( 'Content-Type: '+THRIFT_MIMETYPE, WINHTTP_ADDREQ_FLAG_ADD); for pair in FCustomHeaders do begin Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD); end; // enable automatic gzip,deflate decompression result.EnableAutomaticContentDecompression(TRUE); // AutoProxy support info := TErrorInfo.AutoProxy; result.TryAutoProxy( FUri); except on e:TException do raise; on e:Exception do raise TTransportExceptionUnknown.Create( e.Message+' (at '+EnumUtils.ToString(Ord(info))+')'); end; end; function TWinHTTPClientImpl.SecureProtocolsAsWinHTTPFlags : Cardinal; const PROTOCOL_MAPPING : array[TSecureProtocol] of Cardinal = ( WINHTTP_FLAG_SECURE_PROTOCOL_SSL2, WINHTTP_FLAG_SECURE_PROTOCOL_SSL3, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 ); var prot : TSecureProtocol; protos : TSecureProtocols; begin result := 0; protos := GetSecureProtocols; for prot := Low(TSecureProtocol) to High(TSecureProtocol) do begin if prot in protos then result := result or PROTOCOL_MAPPING[prot]; end; end; function TWinHTTPClientImpl.GetDnsResolveTimeout: Integer; begin Result := FDnsResolveTimeout; end; procedure TWinHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer); begin FDnsResolveTimeout := Value; end; function TWinHTTPClientImpl.GetConnectionTimeout: Integer; begin Result := FConnectionTimeout; end; procedure TWinHTTPClientImpl.SetConnectionTimeout(const Value: Integer); begin FConnectionTimeout := Value; end; function TWinHTTPClientImpl.GetSendTimeout: Integer; begin Result := FSendTimeout; end; procedure TWinHTTPClientImpl.SetSendTimeout(const Value: Integer); begin FSendTimeout := Value; end; function TWinHTTPClientImpl.GetReadTimeout: Integer; begin Result := FReadTimeout; end; procedure TWinHTTPClientImpl.SetReadTimeout(const Value: Integer); begin FReadTimeout := Value; end; function TWinHTTPClientImpl.GetSecureProtocols : TSecureProtocols; begin Result := FSecureProtocols; end; procedure TWinHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols); begin FSecureProtocols := Value; end; function TWinHTTPClientImpl.GetCustomHeaders: IThriftDictionary; begin Result := FCustomHeaders; end; function TWinHTTPClientImpl.GetIsOpen: Boolean; begin Result := Assigned( FOutputMemoryStream); end; procedure TWinHTTPClientImpl.Open; begin FreeAndNil( FOutputMemoryStream); FOutputMemoryStream := TThriftMemoryStream.Create; end; procedure TWinHTTPClientImpl.Close; begin FInputStream := nil; FreeAndNil( FOutputMemoryStream); end; procedure TWinHTTPClientImpl.Flush; begin try SendRequest; finally FreeAndNil( FOutputMemoryStream); FOutputMemoryStream := TThriftMemoryStream.Create; ASSERT( FOutputMemoryStream <> nil); end; end; function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then begin raise TTransportExceptionNotOpen.Create('No request has been sent'); end; try Result := FInputStream.Read( pBuf, buflen, off, len); CountConsumedMessageBytes( result); except on E: Exception do raise TTransportExceptionUnknown.Create(E.Message); end; end; procedure TWinHTTPClientImpl.SendRequest; var http : IWinHTTPRequest; pData : PByte; len : Integer; error, dwSize : Cardinal; sMsg : string; begin http := CreateRequest; pData := FOutputMemoryStream.Memory; len := FOutputMemoryStream.Size; // send all data immediately, since we have it in memory if not http.SendRequest( pData, len, 0) then begin error := Cardinal( GetLastError); sMsg := 'WinHTTP send error '+IntToStr(Int64(error))+' '+WinHttpSysErrorMessage(error); raise TTransportExceptionUnknown.Create(sMsg); end; // end request and start receiving if not http.FlushAndReceiveResponse then begin error := Cardinal( GetLastError); sMsg := 'WinHTTP recv error '+IntToStr(Int64(error))+' '+WinHttpSysErrorMessage(error); if error = ERROR_WINHTTP_TIMEOUT then raise TTransportExceptionTimedOut.Create( sMsg) else raise TTransportExceptionInterrupted.Create( sMsg); end; // we're about to receive a new message, so reset everyting ResetConsumedMessageSize(-1); FInputStream := THTTPResponseStream.Create( http); if http.QueryTotalResponseSize( dwSize) // FALSE indicates "no info available" then UpdateKnownMessageSize( dwSize); end; procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); var pTmp : PByte; begin pTmp := pBuf; Inc(pTmp,off); FOutputMemoryStream.Write( pTmp^, len); end; { TWinHTTPClientImpl.THTTPResponseStream } constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest); begin inherited Create; FRequest := aRequest; end; destructor TWinHTTPClientImpl.THTTPResponseStream.Destroy; begin try Close; finally inherited Destroy; end; end; procedure TWinHTTPClientImpl.THTTPResponseStream.Close; begin FRequest := nil; end; procedure TWinHTTPClientImpl.THTTPResponseStream.Flush; begin raise ENotImplemented(ClassName+'.Flush'); end; function TWinHTTPClientImpl.THTTPResponseStream.IsOpen: Boolean; begin Result := FRequest <> nil; end; procedure TWinHTTPClientImpl.THTTPResponseStream.Open; begin // nothing to do end; procedure TWinHTTPClientImpl.THTTPResponseStream.Write(const pBuf : Pointer; offset, count: Integer); begin inherited; // check pointers raise ENotImplemented(ClassName+'.Write'); end; function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer; var pTmp : PByte; begin inherited; // check pointers if count >= buflen-offset then count := buflen-offset; if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); Result := FRequest.ReadData( pTmp, count); ASSERT( Result >= 0); end else Result := 0; end; function TWinHTTPClientImpl.THTTPResponseStream.ToArray: TBytes; begin raise ENotImplemented(ClassName+'.ToArray'); end; end. thrift-0.19.0/lib/delphi/src/Thrift.Serializer.pas0000644000000000000000000001430714303740367021772 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Serializer; {$I Thrift.Defines.inc} interface uses {$IFDEF OLD_UNIT_NAMES} Classes, Windows, SysUtils, {$ELSE} System.Classes, Winapi.Windows, System.SysUtils, {$ENDIF} Thrift.Configuration, Thrift.Protocol, Thrift.Transport, Thrift.Stream; type // Generic utility for easily serializing objects into a byte array or Stream. TSerializer = class strict private FStream : TThriftMemoryStream; FTransport : ITransport; FProtocol : IProtocol; public constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol const aTransFact : ITransportFactory = nil; const aConfig : IThriftConfiguration = nil); // DTOR destructor Destroy; override; // Serialize the Thrift object. function Serialize( const input : IBase) : TBytes; overload; procedure Serialize( const input : IBase; const aStm : TStream); overload; end; // Generic utility for easily deserializing objects from byte array or Stream. TDeserializer = class strict private FStream : TThriftMemoryStream; FTransport : ITransport; FProtocol : IProtocol; public constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol const aTransFact : ITransportFactory = nil; const aConfig : IThriftConfiguration = nil); // DTOR destructor Destroy; override; // Deserialize the Thrift object data. procedure Deserialize( const input : TBytes; const target : IBase); overload; procedure Deserialize( const input : TStream; const target : IBase); overload; end; implementation { TSerializer } constructor TSerializer.Create( const aProtFact : IProtocolFactory; const aTransFact : ITransportFactory; const aConfig : IThriftConfiguration); var adapter : IThriftStream; protfact : IProtocolFactory; begin inherited Create; FStream := TThriftMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); FTransport := TStreamTransportImpl.Create( nil, adapter, aConfig); if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport); if aProtFact <> nil then protfact := aProtFact else protfact := TBinaryProtocolImpl.TFactory.Create; FProtocol := protfact.GetProtocol( FTransport); if not FTransport.IsOpen then FTransport.Open; end; destructor TSerializer.Destroy; begin try FProtocol := nil; FTransport := nil; FreeAndNil( FStream); finally inherited Destroy; end; end; function TSerializer.Serialize( const input : IBase) : TBytes; // Serialize the Thrift object into a byte array. The process is simple, // just clear the byte array output, write the object into it, and grab the // raw bytes. var iBytes : Int64; begin try FStream.Size := 0; input.Write( FProtocol); FTransport.Flush; SetLength( result, FStream.Size); iBytes := Length(result); if iBytes > 0 then Move( FStream.Memory^, result[0], iBytes); finally FStream.Size := 0; // free any allocated memory end; end; procedure TSerializer.Serialize( const input : IBase; const aStm : TStream); // Serialize the Thrift object into a byte array. The process is simple, // just clear the byte array output, write the object into it, and grab the // raw bytes. const COPY_ENTIRE_STREAM = 0; begin try FStream.Size := 0; input.Write( FProtocol); FTransport.Flush; aStm.CopyFrom( FStream, COPY_ENTIRE_STREAM); finally FStream.Size := 0; // free any allocated memory end; end; { TDeserializer } constructor TDeserializer.Create( const aProtFact : IProtocolFactory; const aTransFact : ITransportFactory; const aConfig : IThriftConfiguration); var adapter : IThriftStream; protfact : IProtocolFactory; begin inherited Create; FStream := TThriftMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); FTransport := TStreamTransportImpl.Create( adapter, nil, aConfig); if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport); if aProtFact <> nil then protfact := aProtFact else protfact := TBinaryProtocolImpl.TFactory.Create; FProtocol := protfact.GetProtocol( FTransport); if not FTransport.IsOpen then FTransport.Open; end; destructor TDeserializer.Destroy; begin try FProtocol := nil; FTransport := nil; FreeAndNil( FStream); finally inherited Destroy; end; end; procedure TDeserializer.Deserialize( const input : TBytes; const target : IBase); // Deserialize the Thrift object data from the byte array. var iBytes : Int64; begin try iBytes := Length(input); FStream.Size := iBytes; if iBytes > 0 then Move( input[0], FStream.Memory^, iBytes); target.Read( FProtocol); finally FStream.Size := 0; // free any allocated memory end; end; procedure TDeserializer.Deserialize( const input : TStream; const target : IBase); // Deserialize the Thrift object data from the byte array. const COPY_ENTIRE_STREAM = 0; var before : Int64; begin try before := FStream.Position; FStream.CopyFrom( input, COPY_ENTIRE_STREAM); FStream.Position := before; target.Read( FProtocol); finally FStream.Size := 0; // free any allocated memory end; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Transport.Pipes.pas0000644000000000000000000010526214303740367022735 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Transport.Pipes; {$WARN SYMBOL_PLATFORM OFF} {$I Thrift.Defines.inc} interface uses {$IFDEF OLD_UNIT_NAMES} Windows, SysUtils, Math, AccCtrl, AclAPI, SyncObjs, {$ELSE} Winapi.Windows, System.SysUtils, System.Math, Winapi.AccCtrl, Winapi.AclAPI, System.SyncObjs, {$ENDIF} Thrift.Configuration, Thrift.Transport, Thrift.Utils, Thrift.Stream; const DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT = 10; // default: fail fast on open type //--- Pipe Streams --- TPipeStreamBase = class( TThriftStreamImpl) strict protected FPipe : THandle; FTimeout : DWORD; FOpenTimeOut : DWORD; // separate value to allow for fail-fast-on-open scenarios FOverlapped : Boolean; procedure Write( const pBuf : Pointer; offset, count : Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; //procedure Open; override; - see derived classes procedure Close; override; procedure Flush; override; function ReadDirect( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; function ReadOverlapped( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; procedure WriteDirect( const pBuf : Pointer; offset: Integer; count: Integer); overload; procedure WriteOverlapped( const pBuf : Pointer; offset: Integer; count: Integer); overload; function IsOpen: Boolean; override; function ToArray: TBytes; override; public constructor Create( aEnableOverlapped : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT ); reintroduce; overload; destructor Destroy; override; end; TNamedPipeStreamImpl = class sealed( TPipeStreamBase) strict private FPipeName : string; FShareMode : DWORD; FSecurityAttribs : PSecurityAttributes; strict protected procedure Open; override; public constructor Create( const aPipeName : string; const aEnableOverlapped : Boolean; const aShareMode: DWORD = 0; const aSecurityAttributes: PSecurityAttributes = nil; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT ); reintroduce; overload; end; THandlePipeStreamImpl = class sealed( TPipeStreamBase) strict private FSrcHandle : THandle; strict protected procedure Open; override; public constructor Create( const aPipeHandle : THandle; const aOwnsHandle, aEnableOverlapped : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT ); reintroduce; overload; destructor Destroy; override; end; //--- Pipe Transports --- IPipeTransport = interface( IStreamTransport) ['{5E05CC85-434F-428F-BFB2-856A168B5558}'] end; TPipeTransportBase = class( TStreamTransportImpl, IPipeTransport) strict protected // ITransport function GetIsOpen: Boolean; override; procedure Open; override; procedure Close; override; end; TNamedPipeTransportClientEndImpl = class( TPipeTransportBase) public // Named pipe constructors constructor Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD; const aConfig : IThriftConfiguration = nil ); reintroduce; overload; constructor Create( const aPipeName : string; const aShareMode: DWORD = 0; const aSecurityAttributes: PSecurityAttributes = nil; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT; const aConfig : IThriftConfiguration = nil ); reintroduce; overload; end; TNamedPipeTransportServerEndImpl = class( TNamedPipeTransportClientEndImpl) strict private FHandle : THandle; strict protected // ITransport procedure Close; override; public constructor Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil ); reintroduce; overload; end; TAnonymousPipeTransportImpl = class( TPipeTransportBase) public // Anonymous pipe constructor constructor Create( const aPipeRead, aPipeWrite : THandle; const aOwnsHandles : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil ); reintroduce; overload; end; //--- Server Transports --- IAnonymousPipeServerTransport = interface( IServerTransport) ['{7AEE6793-47B9-4E49-981A-C39E9108E9AD}'] // Server side anonymous pipe ends function ReadHandle : THandle; function WriteHandle : THandle; // Client side anonymous pipe ends function ClientAnonRead : THandle; function ClientAnonWrite : THandle; end; INamedPipeServerTransport = interface( IServerTransport) ['{9DF9EE48-D065-40AF-8F67-D33037D3D960}'] function Handle : THandle; end; TPipeServerTransportBase = class( TServerTransportImpl) strict protected FStopServer : TEvent; procedure InternalClose; virtual; abstract; function QueryStopServer : Boolean; public constructor Create( const aConfig : IThriftConfiguration); destructor Destroy; override; procedure Listen; override; procedure Close; override; end; TAnonymousPipeServerTransportImpl = class( TPipeServerTransportBase, IAnonymousPipeServerTransport) strict private FBufSize : DWORD; // Server side anonymous pipe handles FReadHandle, FWriteHandle : THandle; //Client side anonymous pipe handles FClientAnonRead, FClientAnonWrite : THandle; FTimeOut: DWORD; strict protected function Accept(const fnAccepting: TProc): ITransport; override; function CreateAnonPipe : Boolean; // IAnonymousPipeServerTransport function ReadHandle : THandle; function WriteHandle : THandle; function ClientAnonRead : THandle; function ClientAnonWrite : THandle; procedure InternalClose; override; public constructor Create( const aBufsize : Cardinal = 4096; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil ); reintroduce; overload; end; TNamedPipeFlag = ( OnlyLocalClients // sets PIPE_REJECT_REMOTE_CLIENTS ); TNamedPipeFlags = set of TNamedPipeFlag; TNamedPipeServerTransportImpl = class( TPipeServerTransportBase, INamedPipeServerTransport) strict private FPipeName : string; FMaxConns : DWORD; FBufSize : DWORD; FTimeout : DWORD; FHandle : THandle; FConnected : Boolean; FOnlyLocalClients : Boolean; strict protected function Accept(const fnAccepting: TProc): ITransport; override; function CreateNamedPipe : THandle; function CreateTransportInstance : ITransport; // INamedPipeServerTransport function Handle : THandle; procedure InternalClose; override; public constructor Create( const aPipename : string; const aBufsize : Cardinal = 4096; const aMaxConns : Cardinal = PIPE_UNLIMITED_INSTANCES; const aTimeOut : Cardinal = INFINITE; const aConfig : IThriftConfiguration = nil ); reintroduce; overload; deprecated 'use the other CTOR instead'; constructor Create( const aPipename : string; const aFlags : TNamedPipeFlags; const aConfig : IThriftConfiguration = nil; const aBufsize : Cardinal = 4096; const aMaxConns : Cardinal = PIPE_UNLIMITED_INSTANCES; const aTimeOut : Cardinal = INFINITE ); reintroduce; overload; end; implementation const // flags used but not declared in all Delphi versions, see MSDN PIPE_ACCEPT_REMOTE_CLIENTS = 0; // CreateNamedPipe() -> dwPipeMode = default PIPE_REJECT_REMOTE_CLIENTS = $00000008; // CreateNamedPipe() -> dwPipeMode // Windows platfoms only // https://github.com/dotnet/coreclr/pull/379/files // https://referencesource.microsoft.com/#System.Runtime.Remoting/channels/ipc/win32namedpipes.cs,46b96e3f3828f497,references // Citation from the first source: // > For mitigating local elevation of privilege attack through named pipes // > make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // > named pipe server can't impersonate a high privileged client security context {$IFDEF MSWINDOWS} PREVENT_PIPE_IMPERSONATION = SECURITY_SQOS_PRESENT or SECURITY_ANONYMOUS; {$ELSE} PREVENT_PIPE_IMPERSONATION = 0; // not available on Linux etc {$ENDIF} procedure ClosePipeHandle( var hPipe : THandle); begin if hPipe <> INVALID_HANDLE_VALUE then try CloseHandle( hPipe); finally hPipe := INVALID_HANDLE_VALUE; end; end; function DuplicatePipeHandle( const hSource : THandle) : THandle; begin if not DuplicateHandle( GetCurrentProcess, hSource, GetCurrentProcess, @result, 0, FALSE, DUPLICATE_SAME_ACCESS) then raise TTransportExceptionNotOpen.Create('DuplicateHandle: '+SysErrorMessage(GetLastError)); end; { TPipeStreamBase } constructor TPipeStreamBase.Create( aEnableOverlapped : Boolean; const aTimeOut, aOpenTimeOut : DWORD); begin inherited Create; FPipe := INVALID_HANDLE_VALUE; FTimeout := aTimeOut; FOpenTimeOut := aOpenTimeOut; FOverlapped := aEnableOverlapped; ASSERT( FTimeout > 0); // FOpenTimeout may be 0 end; destructor TPipeStreamBase.Destroy; begin try Close; finally inherited Destroy; end; end; procedure TPipeStreamBase.Close; begin ClosePipeHandle( FPipe); end; procedure TPipeStreamBase.Flush; begin FlushFileBuffers( FPipe); end; function TPipeStreamBase.IsOpen: Boolean; begin result := (FPipe <> INVALID_HANDLE_VALUE); end; procedure TPipeStreamBase.Write( const pBuf : Pointer; offset, count : Integer); begin if FOverlapped then WriteOverlapped( pBuf, offset, count) else WriteDirect( pBuf, offset, count); end; function TPipeStreamBase.Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; begin if FOverlapped then result := ReadOverlapped( pBuf, buflen, offset, count) else result := ReadDirect( pBuf, buflen, offset, count); end; procedure TPipeStreamBase.WriteDirect( const pBuf : Pointer; offset: Integer; count: Integer); var cbWritten, nBytes : DWORD; pData : PByte; begin if not IsOpen then raise TTransportExceptionNotOpen.Create('Called write on non-open pipe'); // if necessary, send the data in chunks // there's a system limit around 0x10000 bytes that we hit otherwise // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." nBytes := Min( 15*4096, count); // 16 would exceed the limit pData := pBuf; Inc( pData, offset); while nBytes > 0 do begin if not WriteFile( FPipe, pData^, nBytes, cbWritten, nil) then raise TTransportExceptionNotOpen.Create('Write to pipe failed'); Inc( pData, cbWritten); Dec( count, cbWritten); nBytes := Min( nBytes, count); end; end; procedure TPipeStreamBase.WriteOverlapped( const pBuf : Pointer; offset: Integer; count: Integer); var cbWritten, dwWait, dwError, nBytes : DWORD; overlapped : IOverlappedHelper; pData : PByte; begin if not IsOpen then raise TTransportExceptionNotOpen.Create('Called write on non-open pipe'); // if necessary, send the data in chunks // there's a system limit around 0x10000 bytes that we hit otherwise // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." nBytes := Min( 15*4096, count); // 16 would exceed the limit pData := pBuf; Inc( pData, offset); while nBytes > 0 do begin overlapped := TOverlappedHelperImpl.Create; if not WriteFile( FPipe, pData^, nBytes, cbWritten, overlapped.OverlappedPtr) then begin dwError := GetLastError; case dwError of ERROR_IO_PENDING : begin dwWait := overlapped.WaitFor(FTimeout); if (dwWait = WAIT_TIMEOUT) then begin CancelIo( FPipe); // prevents possible AV on invalid overlapped ptr raise TTransportExceptionTimedOut.Create('Pipe write timed out'); end; if (dwWait <> WAIT_OBJECT_0) or not GetOverlappedResult( FPipe, overlapped.Overlapped, cbWritten, TRUE) then raise TTransportExceptionUnknown.Create('Pipe write error'); end; else raise TTransportExceptionUnknown.Create(SysErrorMessage(dwError)); end; end; ASSERT( DWORD(nBytes) = cbWritten); Inc( pData, cbWritten); Dec( count, cbWritten); nBytes := Min( nBytes, count); end; end; function TPipeStreamBase.ReadDirect( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; var cbRead, dwErr, nRemaining : DWORD; bytes, retries : LongInt; bOk : Boolean; pData : PByte; const INTERVAL = 10; // ms begin if not IsOpen then raise TTransportExceptionNotOpen.Create('Called read on non-open pipe'); // MSDN: Handle can be a handle to a named pipe instance, // or it can be a handle to the read end of an anonymous pipe, // The handle must have GENERIC_READ access to the pipe. if FTimeOut <> INFINITE then begin retries := Max( 1, Round( 1.0 * FTimeOut / INTERVAL)); while TRUE do begin if not PeekNamedPipe( FPipe, nil, 0, nil, @bytes, nil) then begin dwErr := GetLastError; if (dwErr = ERROR_INVALID_HANDLE) or (dwErr = ERROR_BROKEN_PIPE) or (dwErr = ERROR_PIPE_NOT_CONNECTED) then begin result := 0; // other side closed the pipe Exit; end; end else if bytes > 0 then begin Break; // there are data end; Dec( retries); if retries > 0 then Sleep( INTERVAL) else raise TTransportExceptionTimedOut.Create('Pipe read timed out'); end; end; result := 0; nRemaining := count; pData := pBuf; Inc( pData, offset); while nRemaining > 0 do begin // read the data (or block INFINITE-ly) bOk := ReadFile( FPipe, pData^, nRemaining, cbRead, nil); if (not bOk) and (GetLastError() <> ERROR_MORE_DATA) then Break; // No more data, possibly because client disconnected. Dec( nRemaining, cbRead); Inc( pData, cbRead); Inc( result, cbRead); end; end; function TPipeStreamBase.ReadOverlapped( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; var cbRead, dwWait, dwError, nRemaining : DWORD; bOk : Boolean; overlapped : IOverlappedHelper; pData : PByte; begin if not IsOpen then raise TTransportExceptionNotOpen.Create('Called read on non-open pipe'); result := 0; nRemaining := count; pData := pBuf; Inc( pData, offset); while nRemaining > 0 do begin overlapped := TOverlappedHelperImpl.Create; // read the data bOk := ReadFile( FPipe, pData^, nRemaining, cbRead, overlapped.OverlappedPtr); if not bOk then begin dwError := GetLastError; case dwError of ERROR_IO_PENDING : begin dwWait := overlapped.WaitFor(FTimeout); if (dwWait = WAIT_TIMEOUT) then begin CancelIo( FPipe); // prevents possible AV on invalid overlapped ptr raise TTransportExceptionTimedOut.Create('Pipe read timed out'); end; if (dwWait <> WAIT_OBJECT_0) or not GetOverlappedResult( FPipe, overlapped.Overlapped, cbRead, TRUE) then raise TTransportExceptionUnknown.Create('Pipe read error'); end; else raise TTransportExceptionUnknown.Create(SysErrorMessage(dwError)); end; end; ASSERT( cbRead > 0); // see TTransportImpl.ReadAll() ASSERT( cbRead <= DWORD(nRemaining)); Dec( nRemaining, cbRead); Inc( pData, cbRead); Inc( result, cbRead); end; end; function TPipeStreamBase.ToArray: TBytes; var bytes : LongInt; begin SetLength( result, 0); bytes := 0; if IsOpen and PeekNamedPipe( FPipe, nil, 0, nil, @bytes, nil) and (bytes > 0) then begin SetLength( result, bytes); Read( result, 0, bytes); end; end; { TNamedPipeStreamImpl } constructor TNamedPipeStreamImpl.Create( const aPipeName : string; const aEnableOverlapped : Boolean; const aShareMode: DWORD; const aSecurityAttributes: PSecurityAttributes; const aTimeOut, aOpenTimeOut : DWORD); begin inherited Create( aEnableOverlapped, aTimeOut, aOpenTimeOut); FPipeName := aPipeName; FShareMode := aShareMode; FSecurityAttribs := aSecurityAttributes; if Copy(FPipeName,1,2) <> '\\' then FPipeName := '\\.\pipe\' + FPipeName; // assume localhost end; procedure TNamedPipeStreamImpl.Open; var hPipe : THandle; retries, timeout, dwErr, dwFlagsAndAttributes : DWORD; const INTERVAL = 10; // ms begin if IsOpen then Exit; retries := Max( 1, Round( 1.0 * FOpenTimeOut / INTERVAL)); timeout := FOpenTimeOut; // if the server hasn't gotten to the point where the pipe has been created, at least wait the timeout // According to MSDN, if no instances of the specified named pipe exist, the WaitNamedPipe function // returns IMMEDIATELY, regardless of the time-out value. // Always use INTERVAL, since WaitNamedPipe(0) defaults to some other value while not WaitNamedPipe( PChar(FPipeName), INTERVAL) do begin dwErr := GetLastError; if dwErr <> ERROR_FILE_NOT_FOUND then raise TTransportExceptionNotOpen.Create('Unable to open pipe, '+SysErrorMessage(dwErr)); if timeout <> INFINITE then begin if (retries > 0) then Dec(retries) else raise TTransportExceptionNotOpen.Create('Unable to open pipe, timed out'); end; Sleep(INTERVAL) end; dwFlagsAndAttributes := FILE_FLAG_OVERLAPPED or FILE_FLAG_WRITE_THROUGH // async+fast, please or PREVENT_PIPE_IMPERSONATION; // open that thingy hPipe := CreateFile( PChar( FPipeName), GENERIC_READ or GENERIC_WRITE, FShareMode, // sharing FSecurityAttribs, // security attributes OPEN_EXISTING, // opens existing pipe dwFlagsAndAttributes, // flags + attribs 0); // no template file if hPipe = INVALID_HANDLE_VALUE then raise TTransportExceptionNotOpen.Create('Unable to open pipe, '+SysErrorMessage(GetLastError)); // everything fine FPipe := hPipe; end; { THandlePipeStreamImpl } constructor THandlePipeStreamImpl.Create( const aPipeHandle : THandle; const aOwnsHandle, aEnableOverlapped : Boolean; const aTimeOut : DWORD); begin inherited Create( aEnableOverlapped, aTimeout, aTimeout); if aOwnsHandle then FSrcHandle := aPipeHandle else FSrcHandle := DuplicatePipeHandle( aPipeHandle); Open; end; destructor THandlePipeStreamImpl.Destroy; begin try ClosePipeHandle( FSrcHandle); finally inherited Destroy; end; end; procedure THandlePipeStreamImpl.Open; begin if not IsOpen then FPipe := DuplicatePipeHandle( FSrcHandle); end; { TPipeTransportBase } function TPipeTransportBase.GetIsOpen: Boolean; begin result := (FInputStream <> nil) and (FInputStream.IsOpen) and (FOutputStream <> nil) and (FOutputStream.IsOpen); end; procedure TPipeTransportBase.Open; begin FInputStream.Open; FOutputStream.Open; end; procedure TPipeTransportBase.Close; begin FInputStream.Close; FOutputStream.Close; end; { TNamedPipeTransportClientEndImpl } constructor TNamedPipeTransportClientEndImpl.Create( const aPipeName : string; const aShareMode: DWORD; const aSecurityAttributes: PSecurityAttributes; const aTimeOut, aOpenTimeOut : DWORD; const aConfig : IThriftConfiguration); // Named pipe constructor begin inherited Create( nil, nil, aConfig); FInputStream := TNamedPipeStreamImpl.Create( aPipeName, TRUE, aShareMode, aSecurityAttributes, aTimeOut, aOpenTimeOut); FOutputStream := FInputStream; // true for named pipes end; constructor TNamedPipeTransportClientEndImpl.Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD; const aConfig : IThriftConfiguration); // Named pipe constructor begin inherited Create( nil, nil, aConfig); FInputStream := THandlePipeStreamImpl.Create( aPipe, aOwnsHandle, TRUE, aTimeOut); FOutputStream := FInputStream; // true for named pipes end; { TNamedPipeTransportServerEndImpl } constructor TNamedPipeTransportServerEndImpl.Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD; const aConfig : IThriftConfiguration); // Named pipe constructor begin FHandle := DuplicatePipeHandle( aPipe); inherited Create( aPipe, aOwnsHandle, aTimeout, aConfig); end; procedure TNamedPipeTransportServerEndImpl.Close; begin FlushFileBuffers( FHandle); DisconnectNamedPipe( FHandle); // force client off the pipe ClosePipeHandle( FHandle); inherited Close; end; { TAnonymousPipeTransportImpl } constructor TAnonymousPipeTransportImpl.Create( const aPipeRead, aPipeWrite : THandle; const aOwnsHandles : Boolean; const aTimeOut : DWORD; const aConfig : IThriftConfiguration); // Anonymous pipe constructor begin inherited Create( nil, nil, aConfig); // overlapped is not supported with AnonPipes, see MSDN FInputStream := THandlePipeStreamImpl.Create( aPipeRead, aOwnsHandles, FALSE, aTimeout); FOutputStream := THandlePipeStreamImpl.Create( aPipeWrite, aOwnsHandles, FALSE, aTimeout); end; { TPipeServerTransportBase } constructor TPipeServerTransportBase.Create( const aConfig : IThriftConfiguration); begin inherited Create( aConfig); FStopServer := TEvent.Create(nil,TRUE,FALSE,''); // manual reset end; destructor TPipeServerTransportBase.Destroy; begin try FreeAndNil( FStopServer); finally inherited Destroy; end; end; function TPipeServerTransportBase.QueryStopServer : Boolean; begin result := (FStopServer = nil) or (FStopServer.WaitFor(0) <> wrTimeout); end; procedure TPipeServerTransportBase.Listen; begin FStopServer.ResetEvent; end; procedure TPipeServerTransportBase.Close; begin FStopServer.SetEvent; InternalClose; end; { TAnonymousPipeServerTransportImpl } constructor TAnonymousPipeServerTransportImpl.Create( const aBufsize : Cardinal; const aTimeOut : DWORD; const aConfig : IThriftConfiguration); // Anonymous pipe CTOR begin inherited Create(aConfig); FBufsize := aBufSize; FReadHandle := INVALID_HANDLE_VALUE; FWriteHandle := INVALID_HANDLE_VALUE; FClientAnonRead := INVALID_HANDLE_VALUE; FClientAnonWrite := INVALID_HANDLE_VALUE; FTimeOut := aTimeOut; // The anonymous pipe needs to be created first so that the server can // pass the handles on to the client before the serve (acceptImpl) // blocking call. if not CreateAnonPipe then raise TTransportExceptionNotOpen.Create(ClassName+'.Create() failed'); end; function TAnonymousPipeServerTransportImpl.Accept(const fnAccepting: TProc): ITransport; var buf : Byte; br : DWORD; begin if Assigned(fnAccepting) then fnAccepting(); // This 0-byte read serves merely as a blocking call. if not ReadFile( FReadHandle, buf, 0, br, nil) and (GetLastError() <> ERROR_MORE_DATA) then raise TTransportExceptionNotOpen.Create('TServerPipe unable to initiate pipe communication'); // create the transport impl result := TAnonymousPipeTransportImpl.Create( FReadHandle, FWriteHandle, FALSE, FTimeOut, Configuration); end; procedure TAnonymousPipeServerTransportImpl.InternalClose; begin ClosePipeHandle( FReadHandle); ClosePipeHandle( FWriteHandle); ClosePipeHandle( FClientAnonRead); ClosePipeHandle( FClientAnonWrite); end; function TAnonymousPipeServerTransportImpl.ReadHandle : THandle; begin result := FReadHandle; end; function TAnonymousPipeServerTransportImpl.WriteHandle : THandle; begin result := FWriteHandle; end; function TAnonymousPipeServerTransportImpl.ClientAnonRead : THandle; begin result := FClientAnonRead; end; function TAnonymousPipeServerTransportImpl.ClientAnonWrite : THandle; begin result := FClientAnonWrite; end; function TAnonymousPipeServerTransportImpl.CreateAnonPipe : Boolean; var sd : PSECURITY_DESCRIPTOR; sa : SECURITY_ATTRIBUTES; //TSecurityAttributes; hCAR, hPipeW, hCAW, hPipe : THandle; begin sd := PSECURITY_DESCRIPTOR( LocalAlloc( LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH)); try Win32Check( InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION)); Win32Check( SetSecurityDescriptorDacl( sd, TRUE, nil, FALSE)); sa.nLength := sizeof( sa); sa.lpSecurityDescriptor := sd; sa.bInheritHandle := TRUE; //allow passing handle to child Result := CreatePipe( hCAR, hPipeW, @sa, FBufSize); //create stdin pipe if not Result then begin //create stdin pipe raise TTransportExceptionNotOpen.Create('TServerPipe CreatePipe (anon) failed, '+SysErrorMessage(GetLastError)); Exit; end; Result := CreatePipe( hPipe, hCAW, @sa, FBufSize); //create stdout pipe if not Result then begin //create stdout pipe CloseHandle( hCAR); CloseHandle( hPipeW); raise TTransportExceptionNotOpen.Create('TServerPipe CreatePipe (anon) failed, '+SysErrorMessage(GetLastError)); Exit; end; FClientAnonRead := hCAR; FClientAnonWrite := hCAW; FReadHandle := hPipe; FWriteHandle := hPipeW; finally if sd <> nil then LocalFree( Cardinal(sd)); end; end; { TNamedPipeServerTransportImpl } constructor TNamedPipeServerTransportImpl.Create( const aPipename : string; const aFlags : TNamedPipeFlags; const aConfig : IThriftConfiguration; const aBufsize, aMaxConns, aTimeOut : Cardinal); // Named Pipe CTOR begin inherited Create( aConfig); FPipeName := aPipename; FBufsize := aBufSize; FMaxConns := Max( 1, Min( PIPE_UNLIMITED_INSTANCES, aMaxConns)); FHandle := INVALID_HANDLE_VALUE; FTimeout := aTimeOut; FConnected := FALSE; ASSERT( FTimeout > 0); FOnlyLocalClients := (TNamedPipeFlag.OnlyLocalClients in aFlags); if Copy(FPipeName,1,2) <> '\\' then FPipeName := '\\.\pipe\' + FPipeName; // assume localhost end; constructor TNamedPipeServerTransportImpl.Create( const aPipename : string; const aBufsize, aMaxConns, aTimeOut : Cardinal; const aConfig : IThriftConfiguration); // Named Pipe CTOR (deprecated) begin {$WARN SYMBOL_DEPRECATED OFF} // Delphi XE emits a false warning here Create( aPipeName, [], aConfig, aBufsize, aMaxConns, aTimeOut); {$WARN SYMBOL_DEPRECATED ON} end; function TNamedPipeServerTransportImpl.Accept(const fnAccepting: TProc): ITransport; var dwError, dwWait, dwDummy : DWORD; overlapped : IOverlappedHelper; handles : array[0..1] of THandle; begin overlapped := TOverlappedHelperImpl.Create; ASSERT( not FConnected); CreateNamedPipe; while not FConnected do begin if QueryStopServer then begin InternalClose; Abort; end; if Assigned(fnAccepting) then fnAccepting(); // Wait for the client to connect; if it succeeds, the // function returns a nonzero value. If the function returns // zero, GetLastError should return ERROR_PIPE_CONNECTED. if ConnectNamedPipe( Handle, overlapped.OverlappedPtr) then begin FConnected := TRUE; Break; end; // ConnectNamedPipe() returns FALSE for OverlappedIO, even if connected. // We have to check GetLastError() explicitly to find out dwError := GetLastError; case dwError of ERROR_PIPE_CONNECTED : begin FConnected := not QueryStopServer; // special case: pipe immediately connected end; ERROR_IO_PENDING : begin handles[0] := overlapped.WaitHandle; handles[1] := FStopServer.Handle; dwWait := WaitForMultipleObjects( 2, @handles, FALSE, FTimeout); FConnected := (dwWait = WAIT_OBJECT_0) and GetOverlappedResult( Handle, overlapped.Overlapped, dwDummy, TRUE) and not QueryStopServer; end; else InternalClose; raise TTransportExceptionNotOpen.Create('Client connection failed'); end; end; // create the transport impl result := CreateTransportInstance; end; function TNamedPipeServerTransportImpl.CreateTransportInstance : ITransport; // create the transport impl var hPipe : THandle; begin hPipe := THandle( InterlockedExchangePointer( Pointer(FHandle), Pointer(INVALID_HANDLE_VALUE))); try FConnected := FALSE; result := TNamedPipeTransportServerEndImpl.Create( hPipe, TRUE, FTimeout, Configuration); except ClosePipeHandle(hPipe); raise; end; end; procedure TNamedPipeServerTransportImpl.InternalClose; var hPipe : THandle; begin hPipe := THandle( InterlockedExchangePointer( Pointer(FHandle), Pointer(INVALID_HANDLE_VALUE))); if hPipe = INVALID_HANDLE_VALUE then Exit; try if FConnected then FlushFileBuffers( hPipe) else CancelIo( hPipe); DisconnectNamedPipe( hPipe); finally ClosePipeHandle( hPipe); FConnected := FALSE; end; end; function TNamedPipeServerTransportImpl.Handle : THandle; begin {$IFDEF WIN64} result := THandle( InterlockedExchangeAdd64( Int64(FHandle), 0)); {$ELSE} result := THandle( InterlockedExchangeAdd( Integer(FHandle), 0)); {$ENDIF} end; function TNamedPipeServerTransportImpl.CreateNamedPipe : THandle; var SIDAuthWorld : SID_IDENTIFIER_AUTHORITY ; everyone_sid : PSID; ea : EXPLICIT_ACCESS; acl : PACL; sd : PSECURITY_DESCRIPTOR; sa : SECURITY_ATTRIBUTES; dwPipeModeXtra : DWORD; const SECURITY_WORLD_SID_AUTHORITY : TSIDIdentifierAuthority = (Value : (0,0,0,0,0,1)); SECURITY_WORLD_RID = $00000000; begin sd := nil; everyone_sid := nil; try ASSERT( (FHandle = INVALID_HANDLE_VALUE) and not FConnected); // Windows - set security to allow non-elevated apps // to access pipes created by elevated apps. SIDAuthWorld := SECURITY_WORLD_SID_AUTHORITY; AllocateAndInitializeSid( SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, everyone_sid); ZeroMemory( @ea, SizeOf(ea)); ea.grfAccessPermissions := GENERIC_ALL; //SPECIFIC_RIGHTS_ALL or STANDARD_RIGHTS_ALL; ea.grfAccessMode := SET_ACCESS; ea.grfInheritance := NO_INHERITANCE; ea.Trustee.TrusteeForm := TRUSTEE_IS_SID; ea.Trustee.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP; ea.Trustee.ptstrName := PChar(everyone_sid); acl := nil; SetEntriesInAcl( 1, @ea, nil, acl); sd := PSECURITY_DESCRIPTOR( LocalAlloc( LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH)); Win32Check( InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION)); Win32Check( SetSecurityDescriptorDacl( sd, TRUE, acl, FALSE)); sa.nLength := SizeOf(sa); sa.lpSecurityDescriptor := sd; sa.bInheritHandle := FALSE; // any extra flags we want to add to dwPipeMode dwPipeModeXtra := 0; if FOnlyLocalClients then dwPipeModeXtra := dwPipeModeXtra or PIPE_REJECT_REMOTE_CLIENTS; // Create an instance of the named pipe {$IFDEF OLD_UNIT_NAMES} result := Windows.CreateNamedPipe( {$ELSE} result := Winapi.Windows.CreateNamedPipe( {$ENDIF} PChar( FPipeName), // pipe name PIPE_ACCESS_DUPLEX or FILE_FLAG_OVERLAPPED, // read/write access + async mode PIPE_TYPE_BYTE or PIPE_READMODE_BYTE or dwPipeModeXtra, // byte type pipe + byte read mode + extras FMaxConns, // max. instances FBufSize, // output buffer size FBufSize, // input buffer size FTimeout, // time-out, see MSDN @sa // default security attribute ); if( result <> INVALID_HANDLE_VALUE) then InterlockedExchangePointer( Pointer(FHandle), Pointer(result)) else raise TTransportExceptionNotOpen.Create('CreateNamedPipe() failed ' + IntToStr(GetLastError)); finally if sd <> nil then LocalFree( Cardinal( sd)); if acl <> nil then LocalFree( Cardinal( acl)); if everyone_sid <> nil then FreeSid(everyone_sid); end; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Protocol.JSON.pas0000644000000000000000000007752014370300523022226 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) {$SCOPEDENUMS ON} unit Thrift.Protocol.JSON; interface uses Character, Classes, SysUtils, Math, Generics.Collections, Thrift.Configuration, Thrift.Transport, Thrift.Protocol, Thrift.Stream, Thrift.Utils; type IJSONProtocol = interface( IProtocol) ['{F0DAFDBD-692A-4B71-9736-F5D485A2178F}'] // Read a byte that must match b; otherwise an exception is thrown. procedure ReadJSONSyntaxChar( b : Byte); end; // JSON protocol implementation for thrift. // This is a full-featured protocol supporting Write and Read. // Please see the C++ class header for a detailed description of the protocol's wire format. // Adapted from the C# version. TJSONProtocolImpl = class( TProtocolImpl, IJSONProtocol) public type TFactory = class( TInterfacedObject, IProtocolFactory) public function GetProtocol( const trans: ITransport): IProtocol; end; strict private class function GetTypeNameForTypeID(typeID : TType) : string; class function GetTypeIDForTypeName( const name : string) : TType; strict protected type // Base class for tracking JSON contexts that may require // inserting/Reading additional JSON syntax characters. // This base context does nothing. TJSONBaseContext = class strict protected FProto : Pointer; // weak IJSONProtocol; public constructor Create( const aProto : IJSONProtocol); procedure Write; virtual; procedure Read; virtual; function EscapeNumbers : Boolean; virtual; end; // Context for JSON lists. // Will insert/Read commas before each item except for the first one. TJSONListContext = class( TJSONBaseContext) strict private FFirst : Boolean; public constructor Create( const aProto : IJSONProtocol); procedure Write; override; procedure Read; override; end; // Context for JSON records. Will insert/Read colons before the value portion of each record // pair, and commas before each key except the first. In addition, will indicate that numbers // in the key position need to be escaped in quotes (since JSON keys must be strings). TJSONPairContext = class( TJSONBaseContext) strict private FFirst, FColon : Boolean; public constructor Create( const aProto : IJSONProtocol); procedure Write; override; procedure Read; override; function EscapeNumbers : Boolean; override; end; // Holds up to one byte from the transport TLookaheadReader = class strict protected FProto : Pointer; // weak IJSONProtocol; protected constructor Create( const aProto : IJSONProtocol); strict private FHasData : Boolean; FData : Byte; public // Return and consume the next byte to be Read, either taking it from the // data buffer if present or getting it from the transport otherwise. function Read : Byte; // Return the next byte to be Read without consuming, filling the data // buffer if it has not been filled alReady. function Peek : Byte; end; strict protected // Stack of nested contexts that we may be in FContextStack : TStack; // Current context that we are in FContext : TJSONBaseContext; // Reader that manages a 1-byte buffer FReader : TLookaheadReader; // Push/pop a new JSON context onto/from the stack. procedure ResetContextStack; procedure PushContext( const aCtx : TJSONBaseContext); procedure PopContext; strict protected function GetMinSerializedSize( const aType : TType) : Integer; override; procedure Reset; override; public // TJSONProtocolImpl Constructor constructor Create( const aTrans : ITransport); override; destructor Destroy; override; strict protected // IJSONProtocol // Read a byte that must match b; otherwise an exception is thrown. procedure ReadJSONSyntaxChar( b : Byte); strict private // Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its corresponding hex value class function HexVal( ch : Byte) : Byte; // Convert a byte containing a hex value to its corresponding hex character class function HexChar( val : Byte) : Byte; // Write the bytes in array buf as a JSON characters, escaping as needed procedure WriteJSONString( const b : TBytes); overload; procedure WriteJSONString( const str : string); overload; // Write out number as a JSON value. If the context dictates so, it will be // wrapped in quotes to output as a JSON string. procedure WriteJSONInteger( const num : Int64); // Write out a double as a JSON value. If it is NaN or infinity or if the // context dictates escaping, Write out as JSON string. procedure WriteJSONDouble( const num : Double); // Write out contents of byte array b as a JSON string with base-64 encoded data procedure WriteJSONBase64( const b : TBytes); procedure WriteJSONObjectStart; procedure WriteJSONObjectEnd; procedure WriteJSONArrayStart; procedure WriteJSONArrayEnd; public // IProtocol procedure WriteMessageBegin( const aMsg : TThriftMessage); override; procedure WriteMessageEnd; override; procedure WriteStructBegin( const struc: TThriftStruct); override; procedure WriteStructEnd; override; procedure WriteFieldBegin( const field: TThriftField); override; procedure WriteFieldEnd; override; procedure WriteFieldStop; override; procedure WriteMapBegin( const map: TThriftMap); override; procedure WriteMapEnd; override; procedure WriteListBegin( const list: TThriftList); override; procedure WriteListEnd(); override; procedure WriteSetBegin( const set_: TThriftSet ); override; procedure WriteSetEnd(); override; procedure WriteBool( b: Boolean); override; procedure WriteByte( b: ShortInt); override; procedure WriteI16( i16: SmallInt); override; procedure WriteI32( i32: Integer); override; procedure WriteI64( const i64: Int64); override; procedure WriteDouble( const d: Double); override; procedure WriteString( const s: string ); override; procedure WriteBinary( const b: TBytes); override; procedure WriteUuid( const uuid: TGuid); override; // function ReadMessageBegin: TThriftMessage; override; procedure ReadMessageEnd(); override; function ReadStructBegin: TThriftStruct; override; procedure ReadStructEnd; override; function ReadFieldBegin: TThriftField; override; procedure ReadFieldEnd(); override; function ReadMapBegin: TThriftMap; override; procedure ReadMapEnd(); override; function ReadListBegin: TThriftList; override; procedure ReadListEnd(); override; function ReadSetBegin: TThriftSet; override; procedure ReadSetEnd(); override; function ReadBool: Boolean; override; function ReadByte: ShortInt; override; function ReadI16: SmallInt; override; function ReadI32: Integer; override; function ReadI64: Int64; override; function ReadDouble:Double; override; function ReadString : string; override; function ReadBinary: TBytes; override; function ReadUuid: TGuid; override; strict private // Reading methods. // Read in a JSON string, unescaping as appropriate. // Skip Reading from the context if skipContext is true. function ReadJSONString( skipContext : Boolean) : TBytes; // Return true if the given byte could be a valid part of a JSON number. function IsJSONNumeric( b : Byte) : Boolean; // Read in a sequence of characters that are all valid in JSON numbers. Does // not do a complete regex check to validate that this is actually a number. function ReadJSONNumericChars : String; // Read in a JSON number. If the context dictates, Read in enclosing quotes. function ReadJSONInteger : Int64; // Read in a JSON double value. Throw if the value is not wrapped in quotes // when expected or if wrapped in quotes when not expected. function ReadJSONDouble : Double; // Read in a JSON string containing base-64 encoded data and decode it. function ReadJSONBase64 : TBytes; procedure ReadJSONObjectStart; procedure ReadJSONObjectEnd; procedure ReadJSONArrayStart; procedure ReadJSONArrayEnd; end; implementation var COMMA : TBytes; COLON : TBytes; LBRACE : TBytes; RBRACE : TBytes; LBRACKET : TBytes; RBRACKET : TBytes; QUOTE : TBytes; BACKSLASH : TBytes; ESCSEQ : TBytes; const VERSION = 1; JSON_CHAR_TABLE : array[0..$2F] of Byte = (0,0,0,0, 0,0,0,0, Byte('b'),Byte('t'),Byte('n'),0, Byte('f'),Byte('r'),0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,1,Byte('"'),1, 1,1,1,1, 1,1,1,1, 1,1,1,1); ESCAPE_CHARS = '"\/btnfr'; ESCAPE_CHAR_VALS = '"\/'#8#9#10#12#13; DEF_STRING_SIZE = 16; NAME_BOOL = 'tf'; NAME_BYTE = 'i8'; NAME_I16 = 'i16'; NAME_I32 = 'i32'; NAME_I64 = 'i64'; NAME_DOUBLE = 'dbl'; NAME_STRUCT = 'rec'; NAME_STRING = 'str'; NAME_MAP = 'map'; NAME_LIST = 'lst'; NAME_SET = 'set'; NAME_UUID = 'uid'; INVARIANT_CULTURE : TFormatSettings = ( ThousandSeparator: ','; DecimalSeparator: '.'); //--- TJSONProtocolImpl ---------------------- function TJSONProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IProtocol; begin result := TJSONProtocolImpl.Create( trans); end; class function TJSONProtocolImpl.GetTypeNameForTypeID(typeID : TType) : string; begin case typeID of TType.Bool_: result := NAME_BOOL; TType.Byte_: result := NAME_BYTE; TType.I16: result := NAME_I16; TType.I32: result := NAME_I32; TType.I64: result := NAME_I64; TType.Double_: result := NAME_DOUBLE; TType.String_: result := NAME_STRING; TType.Struct: result := NAME_STRUCT; TType.Map: result := NAME_MAP; TType.Set_: result := NAME_SET; TType.List: result := NAME_LIST; TType.Uuid: result := NAME_UUID; else raise TProtocolExceptionNotImplemented.Create('Unrecognized type ('+IntToStr(Ord(typeID))+')'); end; end; class function TJSONProtocolImpl.GetTypeIDForTypeName( const name : string) : TType; begin if name = NAME_BOOL then result := TType.Bool_ else if name = NAME_BYTE then result := TType.Byte_ else if name = NAME_I16 then result := TType.I16 else if name = NAME_I32 then result := TType.I32 else if name = NAME_I64 then result := TType.I64 else if name = NAME_DOUBLE then result := TType.Double_ else if name = NAME_STRUCT then result := TType.Struct else if name = NAME_STRING then result := TType.String_ else if name = NAME_MAP then result := TType.Map else if name = NAME_LIST then result := TType.List else if name = NAME_SET then result := TType.Set_ else if name = NAME_UUID then result := TType.Uuid else raise TProtocolExceptionNotImplemented.Create('Unrecognized type ('+name+')'); end; constructor TJSONProtocolImpl.TJSONBaseContext.Create( const aProto : IJSONProtocol); begin inherited Create; FProto := Pointer(aProto); end; procedure TJSONProtocolImpl.TJSONBaseContext.Write; begin // nothing end; procedure TJSONProtocolImpl.TJSONBaseContext.Read; begin // nothing end; function TJSONProtocolImpl.TJSONBaseContext.EscapeNumbers : Boolean; begin result := FALSE; end; constructor TJSONProtocolImpl.TJSONListContext.Create( const aProto : IJSONProtocol); begin inherited Create( aProto); FFirst := TRUE; end; procedure TJSONProtocolImpl.TJSONListContext.Write; begin if FFirst then FFirst := FALSE else IJSONProtocol(FProto).Transport.Write( COMMA); end; procedure TJSONProtocolImpl.TJSONListContext.Read; begin if FFirst then FFirst := FALSE else IJSONProtocol(FProto).ReadJSONSyntaxChar( COMMA[0]); end; constructor TJSONProtocolImpl.TJSONPairContext.Create( const aProto : IJSONProtocol); begin inherited Create( aProto); FFirst := TRUE; FColon := TRUE; end; procedure TJSONProtocolImpl.TJSONPairContext.Write; begin if FFirst then begin FFirst := FALSE; FColon := TRUE; end else begin if FColon then IJSONProtocol(FProto).Transport.Write( COLON) else IJSONProtocol(FProto).Transport.Write( COMMA); FColon := not FColon; end; end; procedure TJSONProtocolImpl.TJSONPairContext.Read; begin if FFirst then begin FFirst := FALSE; FColon := TRUE; end else begin if FColon then IJSONProtocol(FProto).ReadJSONSyntaxChar( COLON[0]) else IJSONProtocol(FProto).ReadJSONSyntaxChar( COMMA[0]); FColon := not FColon; end; end; function TJSONProtocolImpl.TJSONPairContext.EscapeNumbers : Boolean; begin result := FColon; end; constructor TJSONProtocolImpl.TLookaheadReader.Create( const aProto : IJSONProtocol); begin inherited Create; FProto := Pointer(aProto); FHasData := FALSE; end; function TJSONProtocolImpl.TLookaheadReader.Read : Byte; begin if FHasData then FHasData := FALSE else begin IJSONProtocol(FProto).Transport.ReadAll( @FData, SizeOf(FData), 0, 1); end; result := FData; end; function TJSONProtocolImpl.TLookaheadReader.Peek : Byte; begin if not FHasData then begin IJSONProtocol(FProto).Transport.ReadAll( @FData, SizeOf(FData), 0, 1); FHasData := TRUE; end; result := FData; end; constructor TJSONProtocolImpl.Create( const aTrans : ITransport); begin inherited Create( aTrans); // Stack of nested contexts that we may be in FContextStack := TStack.Create; FContext := TJSONBaseContext.Create( Self); FReader := TLookaheadReader.Create( Self); end; destructor TJSONProtocolImpl.Destroy; begin try ResetContextStack; // free any contents FreeAndNil( FReader); FreeAndNil( FContext); FreeAndNil( FContextStack); finally inherited Destroy; end; end; procedure TJSONProtocolImpl.Reset; begin inherited Reset; ResetContextStack; end; procedure TJSONProtocolImpl.ResetContextStack; begin while FContextStack.Count > 0 do PopContext; end; procedure TJSONProtocolImpl.PushContext( const aCtx : TJSONBaseContext); begin FContextStack.Push( FContext); FContext := aCtx; end; procedure TJSONProtocolImpl.PopContext; begin FreeAndNil(FContext); FContext := FContextStack.Pop; end; procedure TJSONProtocolImpl.ReadJSONSyntaxChar( b : Byte); var ch : Byte; begin ch := FReader.Read; if (ch <> b) then raise TProtocolExceptionInvalidData.Create('Unexpected character ('+Char(ch)+')'); end; class function TJSONProtocolImpl.HexVal( ch : Byte) : Byte; var i : Integer; begin i := StrToIntDef( '$0'+Char(ch), -1); if (0 <= i) and (i < $10) then result := i else raise TProtocolExceptionInvalidData.Create('Expected hex character ('+Char(ch)+')'); end; class function TJSONProtocolImpl.HexChar( val : Byte) : Byte; const HEXCHARS = '0123456789ABCDEF'; begin result := Byte( PChar(HEXCHARS)[val and $0F]); ASSERT( Pos( Char(result), HEXCHARS) > 0); end; procedure TJSONProtocolImpl.WriteJSONString( const str : string); begin WriteJSONString( SysUtils.TEncoding.UTF8.GetBytes( str)); end; procedure TJSONProtocolImpl.WriteJSONString( const b : TBytes); var i : Integer; tmp : TBytes; begin FContext.Write; Transport.Write( QUOTE); for i := 0 to Length(b)-1 do begin if (b[i] and $00FF) >= $30 then begin if (b[i] = BACKSLASH[0]) then begin Transport.Write( BACKSLASH); Transport.Write( BACKSLASH); end else begin Transport.Write( b, i, 1); end; end else begin SetLength( tmp, 2); tmp[0] := JSON_CHAR_TABLE[b[i]]; if (tmp[0] = 1) then begin Transport.Write( b, i, 1) end else if (tmp[0] > 1) then begin Transport.Write( BACKSLASH); Transport.Write( tmp, 0, 1); end else begin Transport.Write( ESCSEQ); tmp[0] := HexChar( b[i] div $10); tmp[1] := HexChar( b[i]); Transport.Write( tmp, 0, 2); end; end; end; Transport.Write( QUOTE); end; procedure TJSONProtocolImpl.WriteJSONInteger( const num : Int64); var str : String; escapeNum : Boolean; begin FContext.Write; str := IntToStr(num); escapeNum := FContext.EscapeNumbers; if escapeNum then Transport.Write( QUOTE); Transport.Write( SysUtils.TEncoding.UTF8.GetBytes( str)); if escapeNum then Transport.Write( QUOTE); end; procedure TJSONProtocolImpl.WriteJSONDouble( const num : Double); var str : string; special : Boolean; escapeNum : Boolean; begin FContext.Write; str := FloatToStr( num, INVARIANT_CULTURE); special := FALSE; case UpCase(str[1]) of 'N' : special := TRUE; // NaN 'I' : special := TRUE; // Infinity '-' : special := (UpCase(str[2]) = 'I'); // -Infinity end; escapeNum := special or FContext.EscapeNumbers; if escapeNum then Transport.Write( QUOTE); Transport.Write( SysUtils.TEncoding.UTF8.GetBytes( str)); if escapeNum then Transport.Write( QUOTE); end; procedure TJSONProtocolImpl.WriteJSONBase64( const b : TBytes); var len, off, cnt : Integer; tmpBuf : TBytes; begin FContext.Write; Transport.Write( QUOTE); len := Length(b); off := 0; SetLength( tmpBuf, 4); while len >= 3 do begin // Encode 3 bytes at a time Base64Utils.Encode( b, off, 3, tmpBuf, 0); Transport.Write( tmpBuf, 0, 4); Inc( off, 3); Dec( len, 3); end; // Encode remainder, if any if len > 0 then begin cnt := Base64Utils.Encode( b, off, len, tmpBuf, 0); Transport.Write( tmpBuf, 0, cnt); end; Transport.Write( QUOTE); end; procedure TJSONProtocolImpl.WriteJSONObjectStart; begin FContext.Write; Transport.Write( LBRACE); PushContext( TJSONPairContext.Create( Self)); end; procedure TJSONProtocolImpl.WriteJSONObjectEnd; begin PopContext; Transport.Write( RBRACE); end; procedure TJSONProtocolImpl.WriteJSONArrayStart; begin FContext.Write; Transport.Write( LBRACKET); PushContext( TJSONListContext.Create( Self)); end; procedure TJSONProtocolImpl.WriteJSONArrayEnd; begin PopContext; Transport.Write( RBRACKET); end; procedure TJSONProtocolImpl.WriteMessageBegin( const aMsg : TThriftMessage); begin Reset; ResetContextStack; // THRIFT-1473 WriteJSONArrayStart; WriteJSONInteger(VERSION); WriteJSONString( SysUtils.TEncoding.UTF8.GetBytes( aMsg.Name)); WriteJSONInteger( LongInt( aMsg.Type_)); WriteJSONInteger( aMsg.SeqID); end; procedure TJSONProtocolImpl.WriteMessageEnd; begin WriteJSONArrayEnd; end; procedure TJSONProtocolImpl.WriteStructBegin( const struc: TThriftStruct); begin WriteJSONObjectStart; end; procedure TJSONProtocolImpl.WriteStructEnd; begin WriteJSONObjectEnd; end; procedure TJSONProtocolImpl.WriteFieldBegin( const field : TThriftField); begin WriteJSONInteger(field.ID); WriteJSONObjectStart; WriteJSONString( GetTypeNameForTypeID(field.Type_)); end; procedure TJSONProtocolImpl.WriteFieldEnd; begin WriteJSONObjectEnd; end; procedure TJSONProtocolImpl.WriteFieldStop; begin // nothing to do end; procedure TJSONProtocolImpl.WriteMapBegin( const map: TThriftMap); begin WriteJSONArrayStart; WriteJSONString( GetTypeNameForTypeID( map.KeyType)); WriteJSONString( GetTypeNameForTypeID( map.ValueType)); WriteJSONInteger( map.Count); WriteJSONObjectStart; end; procedure TJSONProtocolImpl.WriteMapEnd; begin WriteJSONObjectEnd; WriteJSONArrayEnd; end; procedure TJSONProtocolImpl.WriteListBegin( const list: TThriftList); begin WriteJSONArrayStart; WriteJSONString( GetTypeNameForTypeID( list.ElementType)); WriteJSONInteger(list.Count); end; procedure TJSONProtocolImpl.WriteListEnd; begin WriteJSONArrayEnd; end; procedure TJSONProtocolImpl.WriteSetBegin( const set_: TThriftSet); begin WriteJSONArrayStart; WriteJSONString( GetTypeNameForTypeID( set_.ElementType)); WriteJSONInteger( set_.Count); end; procedure TJSONProtocolImpl.WriteSetEnd; begin WriteJSONArrayEnd; end; procedure TJSONProtocolImpl.WriteBool( b: Boolean); begin if b then WriteJSONInteger( 1) else WriteJSONInteger( 0); end; procedure TJSONProtocolImpl.WriteByte( b: ShortInt); begin WriteJSONInteger( b); end; procedure TJSONProtocolImpl.WriteI16( i16: SmallInt); begin WriteJSONInteger( i16); end; procedure TJSONProtocolImpl.WriteI32( i32: Integer); begin WriteJSONInteger( i32); end; procedure TJSONProtocolImpl.WriteI64( const i64: Int64); begin WriteJSONInteger(i64); end; procedure TJSONProtocolImpl.WriteDouble( const d: Double); begin WriteJSONDouble( d); end; procedure TJSONProtocolImpl.WriteString( const s: string ); begin WriteJSONString( SysUtils.TEncoding.UTF8.GetBytes( s)); end; procedure TJSONProtocolImpl.WriteBinary( const b: TBytes); begin WriteJSONBase64( b); end; procedure TJSONProtocolImpl.WriteUuid( const uuid: TGuid); begin WriteString( Copy( GuidToString(uuid), 2, 36)); // strip off the { braces } end; function TJSONProtocolImpl.ReadJSONString( skipContext : Boolean) : TBytes; var buffer : TThriftMemoryStream; ch : Byte; wch : Word; highSurogate: Char; surrogatePairs: Array[0..1] of Char; off : Integer; tmp : TBytes; begin highSurogate := #0; buffer := TThriftMemoryStream.Create; try if not skipContext then FContext.Read; ReadJSONSyntaxChar( QUOTE[0]); while TRUE do begin ch := FReader.Read; if (ch = QUOTE[0]) then Break; // check for escapes if (ch <> ESCSEQ[0]) then begin buffer.Write( ch, 1); Continue; end; // distuinguish between \uNNNN and \? ch := FReader.Read; if (ch <> ESCSEQ[1]) then begin off := Pos( Char(ch), ESCAPE_CHARS); if off < 1 then raise TProtocolExceptionInvalidData.Create('Expected control char'); ch := Byte( ESCAPE_CHAR_VALS[off]); buffer.Write( ch, 1); Continue; end; // it is \uXXXX SetLength( tmp, 4); Transport.ReadAll( tmp, 0, 4); wch := (HexVal(tmp[0]) shl 12) + (HexVal(tmp[1]) shl 8) + (HexVal(tmp[2]) shl 4) + HexVal(tmp[3]); // we need to make UTF8 bytes from it, to be decoded later if CharUtils.IsHighSurrogate(char(wch)) then begin if highSurogate <> #0 then raise TProtocolExceptionInvalidData.Create('Expected low surrogate char'); highSurogate := char(wch); end else if CharUtils.IsLowSurrogate(char(wch)) then begin if highSurogate = #0 then TProtocolExceptionInvalidData.Create('Expected high surrogate char'); surrogatePairs[0] := highSurogate; surrogatePairs[1] := char(wch); tmp := TEncoding.UTF8.GetBytes(surrogatePairs); buffer.Write( tmp[0], Length(tmp)); highSurogate := #0; end else begin tmp := SysUtils.TEncoding.UTF8.GetBytes(Char(wch)); buffer.Write( tmp[0], Length(tmp)); end; end; if highSurogate <> #0 then raise TProtocolExceptionInvalidData.Create('Expected low surrogate char'); SetLength( result, buffer.Size); if buffer.Size > 0 then Move( buffer.Memory^, result[0], Length(result)); finally buffer.Free; end; end; function TJSONProtocolImpl.IsJSONNumeric( b : Byte) : Boolean; const NUMCHARS = ['+','-','.','0','1','2','3','4','5','6','7','8','9','E','e']; begin result := CharInSet( Char(b), NUMCHARS); end; function TJSONProtocolImpl.ReadJSONNumericChars : string; var strbld : TThriftStringBuilder; ch : Byte; begin strbld := TThriftStringBuilder.Create; try while TRUE do begin ch := FReader.Peek; if IsJSONNumeric(ch) then strbld.Append( Char(FReader.Read)) else Break; end; result := strbld.ToString; finally strbld.Free; end; end; function TJSONProtocolImpl.ReadJSONInteger : Int64; var str : string; begin FContext.Read; if FContext.EscapeNumbers then ReadJSONSyntaxChar( QUOTE[0]); str := ReadJSONNumericChars; if FContext.EscapeNumbers then ReadJSONSyntaxChar( QUOTE[0]); try result := StrToInt64(str); except on e:Exception do begin raise TProtocolExceptionInvalidData.Create('Bad data encounted in numeric data ('+str+') ('+e.Message+')'); end; end; end; function TJSONProtocolImpl.ReadJSONDouble : Double; var dub : Double; str : string; begin FContext.Read; if FReader.Peek = QUOTE[0] then begin str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString( TRUE)); dub := StrToFloat( str, INVARIANT_CULTURE); if not FContext.EscapeNumbers() and not Math.IsNaN(dub) and not Math.IsInfinite(dub) then begin // Throw exception -- we should not be in a string in Self case raise TProtocolExceptionInvalidData.Create('Numeric data unexpectedly quoted'); end; result := dub; Exit; end; // will throw - we should have had a quote if escapeNum == true if FContext.EscapeNumbers then ReadJSONSyntaxChar( QUOTE[0]); try str := ReadJSONNumericChars; result := StrToFloat( str, INVARIANT_CULTURE); except on e:Exception do raise TProtocolExceptionInvalidData.Create('Bad data encounted in numeric data ('+str+') ('+e.Message+')'); end; end; function TJSONProtocolImpl.ReadJSONBase64 : TBytes; var b : TBytes; len, off, size : Integer; begin b := ReadJSONString(false); len := Length(b); off := 0; size := 0; // reduce len to ignore fill bytes Dec(len); while (len >= 0) and (b[len] = Byte('=')) do Dec(len); Inc(len); // read & decode full byte triplets = 4 source bytes while (len >= 4) do begin // Decode 4 bytes at a time Inc( size, Base64Utils.Decode( b, off, 4, b, size)); // decoded in place Inc( off, 4); Dec( len, 4); end; // Don't decode if we hit the end or got a single leftover byte (invalid // base64 but legal for skip of regular string type) if len > 1 then begin // Decode remainder Inc( size, Base64Utils.Decode( b, off, len, b, size)); // decoded in place end; // resize to final size and return the data SetLength( b, size); result := b; end; procedure TJSONProtocolImpl.ReadJSONObjectStart; begin FContext.Read; ReadJSONSyntaxChar( LBRACE[0]); PushContext( TJSONPairContext.Create( Self)); end; procedure TJSONProtocolImpl.ReadJSONObjectEnd; begin ReadJSONSyntaxChar( RBRACE[0]); PopContext; end; procedure TJSONProtocolImpl.ReadJSONArrayStart; begin FContext.Read; ReadJSONSyntaxChar( LBRACKET[0]); PushContext( TJSONListContext.Create( Self)); end; procedure TJSONProtocolImpl.ReadJSONArrayEnd; begin ReadJSONSyntaxChar( RBRACKET[0]); PopContext; end; function TJSONProtocolImpl.ReadMessageBegin: TThriftMessage; begin Reset; ResetContextStack; // THRIFT-1473 Init( result); ReadJSONArrayStart; if ReadJSONInteger <> VERSION then raise TProtocolExceptionBadVersion.Create('Message contained bad version.'); result.Name := SysUtils.TEncoding.UTF8.GetString( ReadJSONString( FALSE)); result.Type_ := TMessageType( ReadJSONInteger); result.SeqID := ReadJSONInteger; end; procedure TJSONProtocolImpl.ReadMessageEnd; begin ReadJSONArrayEnd; end; function TJSONProtocolImpl.ReadStructBegin : TThriftStruct ; begin ReadJSONObjectStart; Init( result); end; procedure TJSONProtocolImpl.ReadStructEnd; begin ReadJSONObjectEnd; end; function TJSONProtocolImpl.ReadFieldBegin : TThriftField; var ch : Byte; str : string; begin Init( result); ch := FReader.Peek; if ch = RBRACE[0] then result.Type_ := TType.Stop else begin result.ID := ReadJSONInteger; ReadJSONObjectStart; str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString( FALSE)); result.Type_ := GetTypeIDForTypeName( str); end; end; procedure TJSONProtocolImpl.ReadFieldEnd; begin ReadJSONObjectEnd; end; function TJSONProtocolImpl.ReadMapBegin : TThriftMap; var str : string; begin Init( result); ReadJSONArrayStart; str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString(FALSE)); result.KeyType := GetTypeIDForTypeName( str); str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString(FALSE)); result.ValueType := GetTypeIDForTypeName( str); result.Count := ReadJSONInteger; CheckReadBytesAvailable(result); ReadJSONObjectStart; end; procedure TJSONProtocolImpl.ReadMapEnd; begin ReadJSONObjectEnd; ReadJSONArrayEnd; end; function TJSONProtocolImpl.ReadListBegin : TThriftList; var str : string; begin Init( result); ReadJSONArrayStart; str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString(FALSE)); result.ElementType := GetTypeIDForTypeName( str); result.Count := ReadJSONInteger; CheckReadBytesAvailable(result); end; procedure TJSONProtocolImpl.ReadListEnd; begin ReadJSONArrayEnd; end; function TJSONProtocolImpl.ReadSetBegin : TThriftSet; var str : string; begin Init( result); ReadJSONArrayStart; str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString(FALSE)); result.ElementType := GetTypeIDForTypeName( str); result.Count := ReadJSONInteger; CheckReadBytesAvailable(result); end; procedure TJSONProtocolImpl.ReadSetEnd; begin ReadJSONArrayEnd; end; function TJSONProtocolImpl.ReadBool : Boolean; begin result := (ReadJSONInteger <> 0); end; function TJSONProtocolImpl.ReadByte : ShortInt; begin result := ReadJSONInteger; end; function TJSONProtocolImpl.ReadI16 : SmallInt; begin result := ReadJSONInteger; end; function TJSONProtocolImpl.ReadI32 : LongInt; begin result := ReadJSONInteger; end; function TJSONProtocolImpl.ReadI64 : Int64; begin result := ReadJSONInteger; end; function TJSONProtocolImpl.ReadDouble : Double; begin result := ReadJSONDouble; end; function TJSONProtocolImpl.ReadString : string; begin result := SysUtils.TEncoding.UTF8.GetString( ReadJSONString( FALSE)); end; function TJSONProtocolImpl.ReadBinary : TBytes; begin result := ReadJSONBase64; end; function TJSONProtocolImpl.ReadUuid: TGuid; begin result := StringToGUID( '{' + ReadString + '}'); end; function TJSONProtocolImpl.GetMinSerializedSize( const aType : TType) : Integer; // Return the minimum number of bytes a type will consume on the wire begin case aType of TType.Stop: result := 0; TType.Void: result := 0; TType.Bool_: result := 1; TType.Byte_: result := 1; TType.Double_: result := 1; TType.I16: result := 1; TType.I32: result := 1; TType.I64: result := 1; TType.String_: result := 2; // empty string TType.Struct: result := 2; // empty struct TType.Map: result := 2; // empty map TType.Set_: result := 2; // empty set TType.List: result := 2; // empty list TType.Uuid: result := 36; // "E236974D-F0B0-4E05-8F29-0B455D41B1A1" else raise TTransportExceptionBadArgs.Create('Unhandled type code'); end; end; //--- init code --- procedure InitBytes( var b : TBytes; aData : array of Byte); begin SetLength( b, Length(aData)); Move( aData, b[0], Length(b)); end; initialization InitBytes( COMMA, [Byte(',')]); InitBytes( COLON, [Byte(':')]); InitBytes( LBRACE, [Byte('{')]); InitBytes( RBRACE, [Byte('}')]); InitBytes( LBRACKET, [Byte('[')]); InitBytes( RBRACKET, [Byte(']')]); InitBytes( QUOTE, [Byte('"')]); InitBytes( BACKSLASH, [Byte('\')]); InitBytes( ESCSEQ, [Byte('\'),Byte('u'),Byte('0'),Byte('0')]); end. thrift-0.19.0/lib/delphi/src/Thrift.Utils.pas0000644000000000000000000003317014370300523020746 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Utils; interface {$I Thrift.Defines.inc} uses {$IFDEF OLD_UNIT_NAMES} Classes, Windows, SysUtils, Character, SyncObjs, TypInfo, Rtti; {$ELSE} System.Classes, Winapi.Windows, System.SysUtils, System.Character, System.SyncObjs, System.TypInfo, System.Rtti; {$ENDIF} type ISupportsToString = interface ['{AF71C350-E0CD-4E94-B77C-0310DC8227FF}'] function ToString : string; end; IOverlappedHelper = interface ['{A1832EFA-2E02-4884-8F09-F0A0277157FA}'] function Overlapped : TOverlapped; function OverlappedPtr : POverlapped; function WaitHandle : THandle; function WaitFor(dwTimeout: DWORD) : DWORD; end; TOverlappedHelperImpl = class( TInterfacedObject, IOverlappedHelper) strict protected FOverlapped : TOverlapped; FEvent : TEvent; // IOverlappedHelper function Overlapped : TOverlapped; function OverlappedPtr : POverlapped; function WaitHandle : THandle; function WaitFor(dwTimeout: DWORD) : DWORD; public constructor Create; destructor Destroy; override; end; TThriftStringBuilder = class( TStringBuilder) public function Append(const Value: TBytes): TStringBuilder; overload; function Append(const Value: ISupportsToString): TStringBuilder; overload; end; Base64Utils = class sealed public class function Encode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; static; class function Decode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; static; end; CharUtils = class sealed public class function IsHighSurrogate( const c : Char) : Boolean; static; inline; class function IsLowSurrogate( const c : Char) : Boolean; static; inline; class function IsHtmlDoctype( const fourBytes : Integer) : Boolean; static; end; IntegerUtils = class sealed strict private class procedure SwapBytes( var one, two : Byte); static; inline; class procedure Swap2( const pValue : Pointer); static; class procedure Swap4( const pValue : Pointer); static; class procedure Swap8( const pValue : Pointer); static; public class procedure SwapByteOrder( const pValue : Pointer; const size : Integer); overload; static; end; // problem: inheritance possible for class helpers ONLY but not with record helpers // workaround: use static class method instead of record helper :-( GuidUtils = class sealed public // new stuff class function SwapByteOrder( const aGuid : TGuid) : TGuid; static; {$IFDEF Debug} class procedure SelfTest; static; {$ENDIF} end; EnumUtils = class sealed public class function ToString(const value : Integer) : string; reintroduce; static; inline; end; StringUtils = class sealed public class function ToString(const value : T) : string; reintroduce; static; inline; end; const THRIFT_MIMETYPE = 'application/x-thrift'; {$IFDEF Win64} function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; {$ENDIF} implementation { TOverlappedHelperImpl } constructor TOverlappedHelperImpl.Create; begin inherited Create; FillChar( FOverlapped, SizeOf(FOverlapped), 0); FEvent := TEvent.Create( nil, TRUE, FALSE, ''); // always ManualReset, see MSDN FOverlapped.hEvent := FEvent.Handle; end; destructor TOverlappedHelperImpl.Destroy; begin try FOverlapped.hEvent := 0; FreeAndNil( FEvent); finally inherited Destroy; end; end; function TOverlappedHelperImpl.Overlapped : TOverlapped; begin result := FOverlapped; end; function TOverlappedHelperImpl.OverlappedPtr : POverlapped; begin result := @FOverlapped; end; function TOverlappedHelperImpl.WaitHandle : THandle; begin result := FOverlapped.hEvent; end; function TOverlappedHelperImpl.WaitFor( dwTimeout : DWORD) : DWORD; begin result := WaitForSingleObject( FOverlapped.hEvent, dwTimeout); end; { Base64Utils } class function Base64Utils.Encode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; const ENCODE_TABLE : PAnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; begin ASSERT( len in [1..3]); dst[dstOff] := Byte( ENCODE_TABLE[ (src[srcOff] shr 2) and $3F]); case len of 3 : begin Inc(dstOff); dst[dstOff] := Byte( ENCODE_TABLE[ ((src[srcOff] shl 4) and $30) or ((src[srcOff + 1] shr 4) and $0F)]); Inc(dstOff); dst[dstOff] := Byte( ENCODE_TABLE[ ((src[srcOff + 1] shl 2) and $3C) or ((src[srcOff + 2] shr 6) and $03)]); Inc(dstOff); dst[dstOff] := Byte( ENCODE_TABLE[ src[srcOff + 2] and $3F]); result := 4; end; 2 : begin Inc(dstOff); dst[dstOff] := Byte( ENCODE_TABLE[ ((src[srcOff] shl 4) and $30) or ((src[srcOff + 1] shr 4) and $0F)]); Inc(dstOff); dst[dstOff] := Byte( ENCODE_TABLE[ (src[srcOff + 1] shl 2) and $3C]); result := 3; end; 1 : begin Inc(dstOff); dst[dstOff] := Byte( ENCODE_TABLE[ (src[srcOff] shl 4) and $30]); result := 2; end; else ASSERT( FALSE); result := 0; // because invalid call end; end; class function Base64Utils.Decode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; const DECODE_TABLE : array[0..$FF] of Integer = ( -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 ); begin ASSERT( len in [1..4]); result := 1; dst[dstOff] := ((DECODE_TABLE[src[srcOff] and $0FF] shl 2) or (DECODE_TABLE[src[srcOff + 1] and $0FF] shr 4)); if (len > 2) then begin Inc( result); Inc( dstOff); dst[dstOff] := (((DECODE_TABLE[src[srcOff + 1] and $0FF] shl 4) and $F0) or (DECODE_TABLE[src[srcOff + 2] and $0FF] shr 2)); if (len > 3) then begin Inc( result); Inc( dstOff); dst[dstOff] := (((DECODE_TABLE[src[srcOff + 2] and $0FF] shl 6) and $C0) or DECODE_TABLE[src[srcOff + 3] and $0FF]); end; end; end; class function CharUtils.IsHighSurrogate( const c : Char) : Boolean; begin {$IF CompilerVersion < 25.0} {$IFDEF OLD_UNIT_NAMES} result := Character.IsHighSurrogate(c); {$ELSE} result := System.Character.IsHighSurrogate(c); {$ENDIF} {$ELSE} result := c.IsHighSurrogate(); {$IFEND} end; class function CharUtils.IsLowSurrogate( const c : Char) : Boolean; begin {$IF CompilerVersion < 25.0} {$IFDEF OLD_UNIT_NAMES} result := Character.IsLowSurrogate(c); {$ELSE} result := System.Character.IsLowSurrogate(c); {$ENDIF} {$ELSE} result := c.IsLowSurrogate(); {$IFEND} end; class function CharUtils.IsHtmlDoctype( const fourBytes : Integer) : Boolean; var pc : PAnsiChar; const HTML_BEGIN : PAnsiChar = 'OD!<'; // first 4 bytes of ' HTML_BEGIN[0] then Exit(FALSE); Inc( pc); if UpCase(pc^) <> HTML_BEGIN[1] then Exit(FALSE); Inc( pc); if UpCase(pc^) <> HTML_BEGIN[2] then Exit(FALSE); Inc( pc); result := (UpCase(pc^) = HTML_BEGIN[3]); end; { IntegerUtils } class procedure IntegerUtils.SwapBytes( var one, two : Byte); var tmp : Byte; begin tmp := one; one := two; two := tmp; end; class procedure IntegerUtils.Swap2( const pValue : Pointer); var pData : PByteArray absolute pValue; begin SwapBytes( pData^[0], pData^[1]); end; class procedure IntegerUtils.Swap4( const pValue : Pointer); var pData : PByteArray absolute pValue; begin SwapBytes( pData^[0], pData^[3]); SwapBytes( pData^[1], pData^[2]); end; class procedure IntegerUtils.Swap8( const pValue : Pointer); var pData : PByteArray absolute pValue; begin SwapBytes( pData^[0], pData^[7]); SwapBytes( pData^[1], pData^[6]); SwapBytes( pData^[2], pData^[5]); SwapBytes( pData^[3], pData^[4]); end; class procedure IntegerUtils.SwapByteOrder( const pValue : Pointer; const size : Integer); begin case size of 2 : Swap2( pValue); 4 : Swap4( pValue); 8 : Swap8( pValue); else raise EArgumentException.Create('Unexpected size'); end; end; { GuidUtils } class function GuidUtils.SwapByteOrder( const aGuid : TGuid) : TGuid; // convert to/from network byte order // - https://www.ietf.org/rfc/rfc4122.txt // - https://stackoverflow.com/questions/10850075/guid-uuid-compatibility-issue-between-net-and-linux // - https://lists.gnu.org/archive/html/bug-parted/2002-01/msg00099.html begin result := aGuid; IntegerUtils.SwapByteOrder( @result.D1, SizeOf(result.D1)); IntegerUtils.SwapByteOrder( @result.D2, SizeOf(result.D2)); IntegerUtils.SwapByteOrder( @result.D3, SizeOf(result.D3)); //result.D4 = array of byte -> implicitly correct end; {$IFDEF Debug} class procedure GuidUtils.SelfTest; var guid : TGuid; pBytes : PByteArray; i, expected : Integer; const TEST_GUID : TGuid = '{00112233-4455-6677-8899-aabbccddeeff}'; begin // host to network guid := TEST_GUID; guid := GuidUtils.SwapByteOrder(guid); // validate network order pBytes := @guid; for i := 0 to $F do begin expected := i * $11; ASSERT( pBytes^[i] = expected); end; // network to host and final validation guid := GuidUtils.SwapByteOrder(guid); ASSERT( IsEqualGuid( guid, TEST_GUID)); // prevent collisions with SysUtils.TGuidHelper guid := TGuid.NewGuid; end; {$ENDIF} {$IFDEF Win64} function InterlockedCompareExchange64( var Target : Int64; Exchange, Comparand : Int64) : Int64; inline; begin {$IFDEF OLD_UNIT_NAMES} result := Windows.InterlockedCompareExchange64( Target, Exchange, Comparand); {$ELSE} result := WinApi.Windows.InterlockedCompareExchange64( Target, Exchange, Comparand); {$ENDIF} end; function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; var old : Int64; begin repeat Old := Addend; until (InterlockedCompareExchange64( Addend, Old + Value, Old) = Old); result := Old; end; {$ENDIF} { EnumUtils } class function EnumUtils.ToString(const value : Integer) : string; var pType : PTypeInfo; begin pType := PTypeInfo(TypeInfo(T)); if Assigned(pType) and (pType^.Kind = tkEnumeration) {$IF CompilerVersion >= 23.0} // TODO: Range correct? What we know is that XE does not offer it, but Rio has it and (pType^.TypeData^.MaxValue >= value) and (pType^.TypeData^.MinValue <= value) {$ELSE} and FALSE // THRIFT-5048: pType^.TypeData^ member not supported -> prevent GetEnumName() from reading outside the legal range {$IFEND} then result := GetEnumName( PTypeInfo(pType), value) else result := IntToStr(Ord(value)); end; { StringUtils } class function StringUtils.ToString(const value : T) : string; type PInterface = ^IInterface; var pType : PTypeInfo; stos : ISupportsToString; pIntf : PInterface; // Workaround: Rio does not allow the direct typecast begin pType := PTypeInfo(TypeInfo(T)); if Assigned(pType) then begin case pType^.Kind of tkInterface : begin pIntf := PInterface(@value); if Supports( pIntf^, ISupportsToString, stos) then begin result := stos.toString; Exit; end; end; tkEnumeration : begin case SizeOf(value) of 1 : begin result := EnumUtils.ToString( PShortInt(@value)^); Exit; end; 2 : begin result := EnumUtils.ToString( PSmallInt(@value)^); Exit; end; 4 : begin result := EnumUtils.ToString( PLongInt(@value)^); Exit; end; else ASSERT(FALSE); // in theory, this should not happen end; end; end; end; result := TValue.From(value).ToString; end; { TThriftStringBuilder } function TThriftStringBuilder.Append(const Value: TBytes): TStringBuilder; begin Result := Append( string( RawByteString(Value)) ); end; function TThriftStringBuilder.Append( const Value: ISupportsToString): TStringBuilder; begin Result := Append( Value.ToString ); end; begin {$IFDEF Debug} GuidUtils.SelfTest; {$ENDIF} end. thrift-0.19.0/lib/delphi/src/Thrift.Server.pas0000644000000000000000000002173314303740367021130 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Server; {$I Thrift.Defines.inc} {$I-} // prevent annoying errors with default log delegate and no console interface uses {$IFDEF OLD_UNIT_NAMES} Windows, SysUtils, {$ELSE} Winapi.Windows, System.SysUtils, {$ENDIF} Thrift, Thrift.Protocol, Thrift.Transport, Thrift.Configuration; type IServerEvents = interface ['{9E2A99C5-EE85-40B2-9A52-2D1722B18176}'] // Called before the server begins. procedure PreServe; // Called when the server transport is ready to accept requests procedure PreAccept; // Called when a new client has connected and the server is about to being processing. function CreateProcessingContext( const input, output : IProtocol) : IProcessorEvents; end; IServer = interface ['{ADC46F2D-8199-4D1C-96D2-87FD54351723}'] procedure Serve; procedure Stop; function GetServerEvents : IServerEvents; procedure SetServerEvents( const value : IServerEvents); property ServerEvents : IServerEvents read GetServerEvents write SetServerEvents; end; TServerImpl = class abstract( TInterfacedObject, IServer ) public type TLogDelegate = reference to procedure( const str: string); strict protected FProcessor : IProcessor; FServerTransport : IServerTransport; FInputTransportFactory : ITransportFactory; FOutputTransportFactory : ITransportFactory; FInputProtocolFactory : IProtocolFactory; FOutputProtocolFactory : IProtocolFactory; FLogDelegate : TLogDelegate; FServerEvents : IServerEvents; FConfiguration : IThriftConfiguration; class procedure DefaultLogDelegate( const str: string); function GetServerEvents : IServerEvents; procedure SetServerEvents( const value : IServerEvents); procedure Serve; virtual; abstract; procedure Stop; virtual; abstract; public constructor Create( const aProcessor :IProcessor; const aServerTransport: IServerTransport; const aInputTransportFactory : ITransportFactory; const aOutputTransportFactory : ITransportFactory; const aInputProtocolFactory : IProtocolFactory; const aOutputProtocolFactory : IProtocolFactory; const aConfig : IThriftConfiguration; const aLogDelegate : TLogDelegate ); overload; constructor Create( const aProcessor: IProcessor; const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory = nil; const aProtocolFactory: IProtocolFactory = nil; const aConfig : IThriftConfiguration = nil; const aLogDel: TServerImpl.TLogDelegate = nil ); overload; end; TSimpleServer = class( TServerImpl) private FStop : Boolean; public procedure Serve; override; procedure Stop; override; end; implementation { TServerImpl } constructor TServerImpl.Create( const aProcessor: IProcessor; const aServerTransport: IServerTransport; const aInputTransportFactory, aOutputTransportFactory: ITransportFactory; const aInputProtocolFactory, aOutputProtocolFactory: IProtocolFactory; const aConfig : IThriftConfiguration; const aLogDelegate : TLogDelegate); begin inherited Create; FProcessor := aProcessor; FServerTransport := aServerTransport; if aConfig <> nil then FConfiguration := aConfig else FConfiguration := TThriftConfigurationImpl.Create; if aInputTransportFactory <> nil then FInputTransportFactory := aInputTransportFactory else FInputTransportFactory := TTransportFactoryImpl.Create; if aOutputTransportFactory <> nil then FOutputTransportFactory := aOutputTransportFactory else FOutputTransportFactory := TTransportFactoryImpl.Create; if aInputProtocolFactory <> nil then FInputProtocolFactory := aInputProtocolFactory else FInputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; if aOutputProtocolFactory <> nil then FOutputProtocolFactory := aOutputProtocolFactory else FOutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; if Assigned(aLogDelegate) then FLogDelegate := aLogDelegate else FLogDelegate := DefaultLogDelegate; end; constructor TServerImpl.Create( const aProcessor: IProcessor; const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory; const aProtocolFactory: IProtocolFactory; const aConfig : IThriftConfiguration; const aLogDel: TServerImpl.TLogDelegate); begin Create( aProcessor, aServerTransport, aTransportFactory, aTransportFactory, aProtocolFactory, aProtocolFactory, aConfig, aLogDel); end; class procedure TServerImpl.DefaultLogDelegate( const str: string); begin try Writeln( str); if IoResult <> 0 then OutputDebugString(PChar(str)); except OutputDebugString(PChar(str)); end; end; function TServerImpl.GetServerEvents : IServerEvents; begin result := FServerEvents; end; procedure TServerImpl.SetServerEvents( const value : IServerEvents); begin // if you need more than one, provide a specialized IServerEvents implementation FServerEvents := value; end; { TSimpleServer } procedure TSimpleServer.Serve; var client : ITransport; InputTransport : ITransport; OutputTransport : ITransport; InputProtocol : IProtocol; OutputProtocol : IProtocol; context : IProcessorEvents; begin try FServerTransport.Listen; except on E: Exception do begin FLogDelegate( E.ToString); end; end; if FServerEvents <> nil then FServerEvents.PreServe; client := nil; while (not FStop) do begin try // clean up any old instances before waiting for clients InputTransport := nil; OutputTransport := nil; InputProtocol := nil; OutputProtocol := nil; // close any old connections before before waiting for new clients if client <> nil then try try client.Close; finally client := nil; end; except // catch all, we can't do much about it at this point end; client := FServerTransport.Accept( procedure begin if FServerEvents <> nil then FServerEvents.PreAccept; end); if client = nil then begin if FStop then Abort // silent exception else raise TTransportExceptionUnknown.Create('ServerTransport.Accept() may not return NULL'); end; FLogDelegate( 'Client Connected!'); InputTransport := FInputTransportFactory.GetTransport( client ); OutputTransport := FOutputTransportFactory.GetTransport( client ); InputProtocol := FInputProtocolFactory.GetProtocol( InputTransport ); OutputProtocol := FOutputProtocolFactory.GetProtocol( OutputTransport ); if FServerEvents <> nil then context := FServerEvents.CreateProcessingContext( InputProtocol, OutputProtocol) else context := nil; while not FStop do begin if context <> nil then context.Processing( client); if not FProcessor.Process( InputProtocol, OutputProtocol, context) then Break; end; except on E: TTransportException do begin if FStop then FLogDelegate('TSimpleServer was shutting down, caught ' + E.ToString) else FLogDelegate( E.ToString); end; on E: Exception do begin FLogDelegate( E.ToString); end; end; if context <> nil then begin context.CleanupContext; context := nil; end; if InputTransport <> nil then begin InputTransport.Close; end; if OutputTransport <> nil then begin OutputTransport.Close; end; end; if FStop then begin try FServerTransport.Close; except on E: TTransportException do begin FLogDelegate('TServerTranport failed on close: ' + E.Message); end; end; FStop := False; end; end; procedure TSimpleServer.Stop; begin FStop := True; FServerTransport.Close; end; end. thrift-0.19.0/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas0000644000000000000000000001721714303740367023457 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Thrift.Transport.MsxmlHTTP; {$I Thrift.Defines.inc} {$SCOPEDENUMS ON} interface uses Classes, SysUtils, Math, Generics.Collections, {$IFDEF OLD_UNIT_NAMES} ActiveX, msxml, {$ELSE} Winapi.ActiveX, Winapi.msxml, {$ENDIF} Thrift.Collections, Thrift.Configuration, Thrift.Transport, Thrift.Exception, Thrift.Utils, Thrift.Stream; type TMsxmlHTTPClientImpl = class( TEndpointTransportBase, IHTTPClient) strict private FUri : string; FInputStream : IThriftStream; FOutputStream : IThriftStream; FDnsResolveTimeout : Integer; FConnectionTimeout : Integer; FSendTimeout : Integer; FReadTimeout : Integer; FCustomHeaders : IThriftDictionary; function CreateRequest: IXMLHTTPRequest; strict protected function GetIsOpen: Boolean; override; procedure Open(); override; procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; procedure SetConnectionTimeout(const Value: Integer); function GetConnectionTimeout: Integer; procedure SetSendTimeout(const Value: Integer); function GetSendTimeout: Integer; procedure SetReadTimeout(const Value: Integer); function GetReadTimeout: Integer; function GetSecureProtocols : TSecureProtocols; procedure SetSecureProtocols( const value : TSecureProtocols); function GetCustomHeaders: IThriftDictionary; procedure SendRequest; property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; public constructor Create( const aUri: string; const aConfig : IThriftConfiguration); reintroduce; destructor Destroy; override; end; implementation const XMLHTTP_CONNECTION_TIMEOUT = 60 * 1000; XMLHTTP_SENDRECV_TIMEOUT = 30 * 1000; { TMsxmlHTTPClientImpl } constructor TMsxmlHTTPClientImpl.Create( const aUri: string; const aConfig : IThriftConfiguration); begin inherited Create( aConfig); FUri := aUri; // defaults according to MSDN FDnsResolveTimeout := 0; // no timeout FConnectionTimeout := XMLHTTP_CONNECTION_TIMEOUT; FSendTimeout := XMLHTTP_SENDRECV_TIMEOUT; FReadTimeout := XMLHTTP_SENDRECV_TIMEOUT; FCustomHeaders := TThriftDictionaryImpl.Create; FOutputStream := TThriftStreamAdapterDelphi.Create( TThriftMemoryStream.Create, True); end; function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest; var pair : TPair; srvHttp : IServerXMLHTTPRequest; begin {$IF CompilerVersion >= 21.0} Result := CoServerXMLHTTP.Create; {$ELSE} Result := CoXMLHTTPRequest.Create; {$IFEND} // setting a timeout value to 0 (zero) means "no timeout" for that setting if Supports( result, IServerXMLHTTPRequest, srvHttp) then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); Result.open('POST', FUri, False, '', ''); Result.setRequestHeader( 'Content-Type', THRIFT_MIMETYPE); Result.setRequestHeader( 'Accept', THRIFT_MIMETYPE); Result.setRequestHeader( 'User-Agent', 'ApacheThriftDelphi/msxml'); for pair in FCustomHeaders do begin Result.setRequestHeader( pair.Key, pair.Value ); end; end; destructor TMsxmlHTTPClientImpl.Destroy; begin Close; inherited; end; function TMsxmlHTTPClientImpl.GetDnsResolveTimeout: Integer; begin Result := FDnsResolveTimeout; end; procedure TMsxmlHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer); begin FDnsResolveTimeout := Value; end; function TMsxmlHTTPClientImpl.GetConnectionTimeout: Integer; begin Result := FConnectionTimeout; end; procedure TMsxmlHTTPClientImpl.SetConnectionTimeout(const Value: Integer); begin FConnectionTimeout := Value; end; function TMsxmlHTTPClientImpl.GetSendTimeout: Integer; begin Result := FSendTimeout; end; procedure TMsxmlHTTPClientImpl.SetSendTimeout(const Value: Integer); begin FSendTimeout := Value; end; function TMsxmlHTTPClientImpl.GetReadTimeout: Integer; begin Result := FReadTimeout; end; procedure TMsxmlHTTPClientImpl.SetReadTimeout(const Value: Integer); begin FReadTimeout := Value; end; function TMsxmlHTTPClientImpl.GetSecureProtocols : TSecureProtocols; begin Result := []; end; procedure TMsxmlHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols); begin raise TTransportExceptionBadArgs.Create('SetSecureProtocols: Not supported with '+ClassName); end; function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary; begin Result := FCustomHeaders; end; function TMsxmlHTTPClientImpl.GetIsOpen: Boolean; begin Result := Assigned(FOutputStream); end; procedure TMsxmlHTTPClientImpl.Open; begin FOutputStream := TThriftStreamAdapterDelphi.Create( TThriftMemoryStream.Create, True); end; procedure TMsxmlHTTPClientImpl.Close; begin FInputStream := nil; FOutputStream := nil; end; procedure TMsxmlHTTPClientImpl.Flush; begin try SendRequest; finally FOutputStream := nil; FOutputStream := TThriftStreamAdapterDelphi.Create( TThriftMemoryStream.Create, True); ASSERT( FOutputStream <> nil); end; end; function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then begin raise TTransportExceptionNotOpen.Create('No request has been sent'); end; try Result := FInputStream.Read( pBuf, buflen, off, len); except on E: Exception do raise TTransportExceptionUnknown.Create(E.Message); end; end; procedure TMsxmlHTTPClientImpl.SendRequest; var xmlhttp : IXMLHTTPRequest; ms : TThriftMemoryStream; a : TBytes; len : Integer; begin xmlhttp := CreateRequest; ms := TThriftMemoryStream.Create; try a := FOutputStream.ToArray; len := Length(a); if len > 0 then begin ms.WriteBuffer( Pointer(@a[0])^, len); end; ms.Position := 0; xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference ))); FInputStream := nil; FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream); ResetConsumedMessageSize; UpdateKnownMessageSize( FInputStream.Size); finally ms.Free; end; end; procedure TMsxmlHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); begin if FOutputStream <> nil then FOutputStream.Write( pBuf, off, len) else raise TTransportExceptionNotOpen.Create('Transport closed'); end; end. thrift-0.19.0/lib/delphi/README.md0000644000000000000000000000177614303740367016413 0ustar00rootroot00000000000000Thrift Delphi Software Library License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Using Thrift with Delphi ==================== The Thrift Delphi Library requires at least Delphi 2010. Because the Library heavily relies on generics, using it with earlier versions (such as Delphi 7) will *not* work. thrift-0.19.0/lib/delphi/coding_standards.md0000644000000000000000000000010314303740367020743 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/delphi/test/0000777000000000000000000000000014370300523016072 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/server.dpr0000644000000000000000000000463714303740367020127 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program server; {$APPTYPE CONSOLE} uses SysUtils, TestServer in 'TestServer.pas', TestServerEvents in 'TestServerEvents.pas', Thrift.Test in 'gen-delphi\Thrift.Test.pas', Thrift in '..\src\Thrift.pas', Thrift.Exception in '..\src\Thrift.Exception.pas', Thrift.Transport in '..\src\Thrift.Transport.pas', Thrift.Socket in '..\src\Thrift.Socket.pas', Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas', Thrift.Protocol in '..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\src\Thrift.Protocol.Compact.pas', Thrift.Protocol.Multiplex in '..\src\Thrift.Protocol.Multiplex.pas', Thrift.Processor.Multiplex in '..\src\Thrift.Processor.Multiplex.pas', Thrift.Collections in '..\src\Thrift.Collections.pas', Thrift.Configuration in '..\src\Thrift.Configuration.pas', Thrift.Server in '..\src\Thrift.Server.pas', Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas', Thrift.Utils in '..\src\Thrift.Utils.pas', Thrift.WinHTTP in '..\src\Thrift.WinHTTP.pas', Thrift.Stream in '..\src\Thrift.Stream.pas'; var nParamCount : Integer; args : array of string; i : Integer; arg : string; begin try Writeln( 'Delphi TestServer '+Thrift.Version); nParamCount := ParamCount; SetLength( args, nParamCount); for i := 1 to nParamCount do begin arg := ParamStr( i ); args[i-1] := arg; end; TTestServer.Execute( args ); except on E: EAbort do begin ExitCode := $FF; end; on E: Exception do begin Writeln(E.ClassName, ': ', E.Message); ExitCode := $FF; end; end; end. thrift-0.19.0/lib/delphi/test/TestServer.pas0000644000000000000000000005415414370300523020712 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit TestServer; {$I ../src/Thrift.Defines.inc} {$WARN SYMBOL_PLATFORM OFF} {.$DEFINE RunEndless} // activate to interactively stress-test the server stop routines via Ctrl+C interface uses Windows, SysUtils, Generics.Collections, Thrift.Server, Thrift.Transport, Thrift.Transport.Pipes, Thrift.Protocol, Thrift.Protocol.JSON, Thrift.Protocol.Compact, Thrift.Collections, Thrift.Configuration, Thrift.Utils, Thrift.Test, Thrift, TestConstants, TestServerEvents, ConsoleHelper, Contnrs; type TTestServer = class public type ITestHandler = interface( TThriftTest.Iface ) procedure SetServer( const AServer : IServer ); procedure TestStop; end; TTestHandlerImpl = class( TInterfacedObject, ITestHandler ) strict private FServer : IServer; strict protected procedure testVoid(); function testBool(thing: Boolean): Boolean; function testString(const thing: string): string; function testByte(thing: ShortInt): ShortInt; function testI32(thing: Integer): Integer; function testI64(const thing: Int64): Int64; function testDouble(const thing: Double): Double; function testBinary(const thing: TBytes): TBytes; function testUuid(const thing: System.TGuid): System.TGuid; function testStruct(const thing: IXtruct): IXtruct; function testNest(const thing: IXtruct2): IXtruct2; function testMap(const thing: IThriftDictionary): IThriftDictionary; function testStringMap(const thing: IThriftDictionary): IThriftDictionary; function testSet(const thing: IThriftHashSet): IThriftHashSet; function testList(const thing: IThriftList): IThriftList; function testEnum(thing: TNumberz): TNumberz; function testTypedef(const thing: Int64): Int64; function testMapMap(hello: Integer): IThriftDictionary>; function testInsanity(const argument: IInsanity): IThriftDictionary>; function testMulti(arg0: ShortInt; arg1: Integer; const arg2: Int64; const arg3: IThriftDictionary; arg4: TNumberz; const arg5: Int64): IXtruct; procedure testException(const arg: string); function testMultiException(const arg0: string; const arg1: string): IXtruct; procedure testOneway(secondsToSleep: Integer); procedure TestStop; procedure SetServer( const AServer : IServer ); end; class procedure PrintCmdLineHelp; class procedure InvalidArgs; class function IsSwitch( const aArgument, aSwitch : string; out sValue : string) : Boolean; class procedure LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport); class procedure Execute( const arguments : array of string); end; implementation var g_Handler : TTestServer.ITestHandler = nil; function MyConsoleEventHandler( dwCtrlType : DWORD) : BOOL; stdcall; // Note that this Handler procedure is called from another thread var handler : TTestServer.ITestHandler; begin result := TRUE; try case dwCtrlType of CTRL_C_EVENT : Console.WriteLine( 'Ctrl+C pressed'); CTRL_BREAK_EVENT : Console.WriteLine( 'Ctrl+Break pressed'); CTRL_CLOSE_EVENT : Console.WriteLine( 'Received CloseTask signal'); CTRL_LOGOFF_EVENT : Console.WriteLine( 'Received LogOff signal'); CTRL_SHUTDOWN_EVENT : Console.WriteLine( 'Received Shutdown signal'); else Console.WriteLine( 'Received console event #'+IntToStr(Integer(dwCtrlType))); end; handler := g_Handler; if handler <> nil then handler.TestStop; except // catch all end; end; { TTestServer.TTestHandlerImpl } procedure TTestServer.TTestHandlerImpl.SetServer( const AServer: IServer); begin FServer := AServer; end; function TTestServer.TTestHandlerImpl.testByte(thing: ShortInt): ShortInt; begin Console.WriteLine('testByte("' + IntToStr( thing) + '")'); Result := thing; end; function TTestServer.TTestHandlerImpl.testDouble( const thing: Double): Double; begin Console.WriteLine('testDouble("' + FloatToStr( thing ) + '")'); Result := thing; end; function TTestServer.TTestHandlerImpl.testBinary(const thing: TBytes): TBytes; begin Console.WriteLine('testBinary('+IntToStr(Length(thing)) + ' bytes)'); Result := thing; end; function TTestServer.TTestHandlerImpl.testUuid(const thing: System.TGuid): System.TGuid; begin Console.WriteLine('testUuid('+GUIDToString(thing)+')'); Result := thing; end; function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz; begin Console.WriteLine('testEnum(' + EnumUtils.ToString(Ord(thing)) + ')'); Result := thing; end; procedure TTestServer.TTestHandlerImpl.testException(const arg: string); begin Console.WriteLine('testException(' + arg + ')'); if ( arg = 'Xception') then begin raise TXception.Create( 1001, arg); end; if (arg = 'TException') then begin raise TException.Create('TException'); end; // else do not throw anything end; function TTestServer.TTestHandlerImpl.testI32(thing: Integer): Integer; begin Console.WriteLine('testI32("' + IntToStr( thing) + '")'); Result := thing; end; function TTestServer.TTestHandlerImpl.testI64( const thing: Int64): Int64; begin Console.WriteLine('testI64("' + IntToStr( thing) + '")'); Result := thing; end; function TTestServer.TTestHandlerImpl.testInsanity( const argument: IInsanity): IThriftDictionary>; var looney : IInsanity; first_map : IThriftDictionary; second_map : IThriftDictionary; insane : IThriftDictionary>; begin Console.Write('testInsanity('); if argument <> nil then Console.Write(argument.ToString); Console.WriteLine(')'); (** * So you think you've got this all worked, out eh? * * Creates a the returned map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, * 2 => { 6 => , }, * } * @return map> - a map with the above values *) first_map := TThriftDictionaryImpl.Create; second_map := TThriftDictionaryImpl.Create; first_map.AddOrSetValue( TNumberz.TWO, argument); first_map.AddOrSetValue( TNumberz.THREE, argument); looney := TInsanityImpl.Create; second_map.AddOrSetValue( TNumberz.SIX, looney); insane := TThriftDictionaryImpl>.Create; insane.AddOrSetValue( 1, first_map); insane.AddOrSetValue( 2, second_map); Result := insane; end; function TTestServer.TTestHandlerImpl.testList( const thing: IThriftList): IThriftList; begin Console.Write('testList('); if thing <> nil then Console.Write(thing.ToString); Console.WriteLine(')'); Result := thing; end; function TTestServer.TTestHandlerImpl.testMap( const thing: IThriftDictionary): IThriftDictionary; begin Console.Write('testMap('); if thing <> nil then Console.Write(thing.ToString); Console.WriteLine(')'); Result := thing; end; function TTestServer.TTestHandlerImpl.TestMapMap( hello: Integer): IThriftDictionary>; var mapmap : IThriftDictionary>; pos : IThriftDictionary; neg : IThriftDictionary; i : Integer; begin Console.WriteLine('testMapMap(' + IntToStr( hello) + ')'); mapmap := TThriftDictionaryImpl>.Create; pos := TThriftDictionaryImpl.Create; neg := TThriftDictionaryImpl.Create; for i := 1 to 4 do begin pos.AddOrSetValue( i, i); neg.AddOrSetValue( -i, -i); end; mapmap.AddOrSetValue(4, pos); mapmap.AddOrSetValue( -4, neg); Result := mapmap; end; function TTestServer.TTestHandlerImpl.testMulti(arg0: ShortInt; arg1: Integer; const arg2: Int64; const arg3: IThriftDictionary; arg4: TNumberz; const arg5: Int64): IXtruct; var hello : IXtruct; begin Console.WriteLine('testMulti()'); hello := TXtructImpl.Create; hello.String_thing := 'Hello2'; hello.Byte_thing := arg0; hello.I32_thing := arg1; hello.I64_thing := arg2; Result := hello; end; function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: string): IXtruct; var x2 : TXception2; begin Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')'); if ( arg0 = 'Xception') then begin raise TXception.Create( 1001, 'This is an Xception'); // test the new rich CTOR end; if ( arg0 = 'Xception2') then begin x2 := TXception2.Create; // the old way still works too? x2.ErrorCode := 2002; x2.Struct_thing := TXtructImpl.Create; x2.Struct_thing.String_thing := 'This is an Xception2'; x2.UpdateMessageProperty; raise x2; end; Result := TXtructImpl.Create; Result.String_thing := arg1; end; function TTestServer.TTestHandlerImpl.testNest( const thing: IXtruct2): IXtruct2; begin Console.Write('testNest('); if thing <> nil then Console.Write(thing.ToString); Console.WriteLine(')'); Result := thing; end; procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer); begin Console.WriteLine('testOneway(' + IntToStr( secondsToSleep )+ '), sleeping...'); Sleep(secondsToSleep * 1000); Console.WriteLine('testOneway finished'); end; function TTestServer.TTestHandlerImpl.testSet( const thing: IThriftHashSet):IThriftHashSet; begin Console.Write('testSet('); if thing <> nil then Console.Write(thing.ToString); Console.WriteLine(')');; Result := thing; end; procedure TTestServer.TTestHandlerImpl.testStop; begin if FServer <> nil then begin FServer.Stop; end; end; function TTestServer.TTestHandlerImpl.testBool(thing: Boolean): Boolean; begin Console.WriteLine('testBool(' + BoolToStr(thing,true) + ')'); Result := thing; end; function TTestServer.TTestHandlerImpl.testString( const thing: string): string; begin Console.WriteLine('teststring("' + thing + '")'); Result := thing; end; function TTestServer.TTestHandlerImpl.testStringMap( const thing: IThriftDictionary): IThriftDictionary; begin Console.Write('testStringMap('); if thing <> nil then Console.Write(thing.ToString); Console.WriteLine(')'); Result := thing; end; function TTestServer.TTestHandlerImpl.testTypedef( const thing: Int64): Int64; begin Console.WriteLine('testTypedef(' + IntToStr( thing) + ')'); Result := thing; end; procedure TTestServer.TTestHandlerImpl.TestVoid; begin Console.WriteLine('testVoid()'); end; function TTestServer.TTestHandlerImpl.testStruct( const thing: IXtruct): IXtruct; begin Console.Write('testStruct('); if thing <> nil then Console.Write(thing.ToString); Console.WriteLine(')'); Result := thing; end; { TTestServer } class procedure TTestServer.PrintCmdLineHelp; const HELPTEXT = ' [options]'#10 + #10 + 'Allowed options:'#10 + ' -h | --help Produces this help message'#10 + ' --port=arg (9090) Port number to connect'#10 + ' --pipe=arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + ' --anon-pipes Windows Anonymous Pipes server, auto-starts client.exe'#10 + ' --server-type=arg (simple) Type of server (simple, thread-pool, threaded, nonblocking)'#10 + ' --transport=arg (sockets) Transport: buffered, framed, anonpipe'#10 + ' --protocol=arg (binary) Protocol: binary, compact, json'#10 + ' --ssl Encrypted Transport using SSL'#10 + ' --processor-events Enable processor-events'#10 + ' -n=num | --workers=num (4) Number of thread-pool server workers'#10 ; begin Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT); end; class procedure TTestServer.InvalidArgs; begin Console.WriteLine( 'Invalid args.'); Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + ' -h for more information'); Abort; end; class function TTestServer.IsSwitch( const aArgument, aSwitch : string; out sValue : string) : Boolean; begin sValue := ''; result := (Copy( aArgument, 1, Length(aSwitch)) = aSwitch); if result then begin if (Copy( aArgument, 1, Length(aSwitch)+1) = (aSwitch+'=')) then sValue := Copy( aArgument, Length(aSwitch)+2, MAXINT); end; end; class procedure TTestServer.LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport); //Launch child process and pass R/W anonymous pipe handles on cmd line. //This is a simple example and does not include elevation or other //advanced features. var pi : PROCESS_INFORMATION; si : STARTUPINFO; sArg, sHandles, sCmdLine : string; i : Integer; begin GetStartupInfo( si); //set startupinfo for the spawned process // preformat handles args sHandles := Format( '%d %d', [ Integer(transport.ClientAnonRead), Integer(transport.ClientAnonWrite)]); // pass all settings to client sCmdLine := app; for i := 1 to ParamCount do begin sArg := ParamStr(i); // add anonymous handles and quote strings where appropriate if sArg = '--anon-pipes' then sArg := sArg +' '+ sHandles else begin if Pos(' ',sArg) > 0 then sArg := '"'+sArg+'"'; end;; sCmdLine := sCmdLine +' '+ sArg; end; // spawn the child process Console.WriteLine('Starting client '+sCmdLine); Win32Check( CreateProcess( nil, PChar(sCmdLine), nil,nil,TRUE,0,nil,nil,si,pi)); CloseHandle( pi.hThread); CloseHandle( pi.hProcess); end; class procedure TTestServer.Execute( const arguments : array of string); var Port : Integer; ServerEvents : Boolean; sPipeName : string; testHandler : ITestHandler; testProcessor : IProcessor; ServerTrans : IServerTransport; ServerEngine : IServer; anonymouspipe : IAnonymousPipeServerTransport; namedpipe : INamedPipeServerTransport; TransportFactory : ITransportFactory; ProtocolFactory : IProtocolFactory; iArg, numWorker : Integer; sArg, sValue : string; protType : TKnownProtocol; servertype : TServerType; endpoint : TEndpointTransport; layered : TLayeredTransports; UseSSL : Boolean; // include where appropriate (TLayeredTransport?) config : IThriftConfiguration; const PIPEFLAGS = [ TNamedPipeFlag.OnlyLocalClients]; begin try ServerEvents := FALSE; protType := prot_Binary; servertype := srv_Simple; endpoint := trns_Sockets; layered := []; UseSSL := FALSE; Port := 9090; sPipeName := ''; numWorker := 4; iArg := 0; while iArg < Length(arguments) do begin sArg := arguments[iArg]; Inc(iArg); // Allowed options: if IsSwitch( sArg, '-h', sValue) or IsSwitch( sArg, '--help', sValue) then begin // -h | --help produce help message PrintCmdLineHelp; Exit; end else if IsSwitch( sArg, '--port', sValue) then begin // --port arg (=9090) Port number to listen Port := StrToIntDef( sValue, Port); end else if IsSwitch( sArg, '--anon-pipes', sValue) then begin endpoint := trns_AnonPipes; end else if IsSwitch( sArg, '--pipe', sValue) then begin // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) endpoint := trns_NamedPipes; sPipeName := sValue; // --pipe end else if IsSwitch( sArg, '--server-type', sValue) then begin // --server-type arg (=simple) type of server, // arg = "simple", "thread-pool", "threaded", or "nonblocking" if sValue = 'simple' then servertype := srv_Simple else if sValue = 'thread-pool' then servertype := srv_Threadpool else if sValue = 'threaded' then servertype := srv_Threaded else if sValue = 'nonblocking' then servertype := srv_Nonblocking else InvalidArgs; end else if IsSwitch( sArg, '--transport', sValue) then begin // --transport arg (=buffered) transport: buffered, framed, http if sValue = 'buffered' then Include( layered, trns_Buffered) else if sValue = 'framed' then Include( layered, trns_Framed) else if sValue = 'http' then endpoint := trns_MsxmlHttp else if sValue = 'winhttp' then endpoint := trns_WinHttp else if sValue = 'anonpipe' then endpoint := trns_AnonPipes else InvalidArgs; end else if IsSwitch( sArg, '--protocol', sValue) then begin // --protocol arg (=binary) protocol: binary, compact, json if sValue = 'binary' then protType := prot_Binary else if sValue = 'compact' then protType := prot_Compact else if sValue = 'json' then protType := prot_JSON else InvalidArgs; end else if IsSwitch( sArg, '--ssl', sValue) then begin // --ssl Encrypted Transport using SSL UseSSL := TRUE; end else if IsSwitch( sArg, '--processor-events', sValue) then begin // --processor-events processor-events ServerEvents := TRUE; end else if IsSwitch( sArg, '-n', sValue) or IsSwitch( sArg, '--workers', sValue) then begin // -n [ --workers ] arg (=4) Number of thread pools workers. // Only valid for thread-pool server type numWorker := StrToIntDef(sValue,4); end else begin InvalidArgs; end; end; Console.WriteLine('Server configuration: '); // create protocol factory, default to BinaryProtocol case protType of prot_Binary : ProtocolFactory := TBinaryProtocolImpl.TFactory.Create; prot_JSON : ProtocolFactory := TJSONProtocolImpl.TFactory.Create; prot_Compact : ProtocolFactory := TCompactProtocolImpl.TFactory.Create; else raise Exception.Create('Unhandled protocol'); end; ASSERT( ProtocolFactory <> nil); Console.WriteLine('- '+THRIFT_PROTOCOLS[protType]+' protocol'); config := nil; // TODO case endpoint of trns_Sockets : begin Console.WriteLine('- sockets (port '+IntToStr(port)+')'); if (trns_Buffered in layered) then Console.WriteLine('- buffered'); servertrans := TServerSocketImpl.Create( Port, DEFAULT_THRIFT_TIMEOUT, (trns_Buffered in layered)); end; trns_MsxmlHttp, trns_WinHttp : begin raise Exception.Create('HTTP server transport not implemented'); end; trns_NamedPipes : begin Console.WriteLine('- named pipe ('+sPipeName+')'); namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, PIPEFLAGS, config); servertrans := namedpipe; end; trns_AnonPipes : begin Console.WriteLine('- anonymous pipes'); anonymouspipe := TAnonymousPipeServerTransportImpl.Create; servertrans := anonymouspipe; end else raise Exception.Create('Unhandled endpoint transport'); end; ASSERT( servertrans <> nil); if UseSSL then begin raise Exception.Create('SSL not implemented'); end; if (trns_Framed in layered) then begin Console.WriteLine('- framed transport'); TransportFactory := TFramedTransportImpl.TFactory.Create; end else begin TransportFactory := TTransportFactoryImpl.Create; end; ASSERT( TransportFactory <> nil); testHandler := TTestHandlerImpl.Create; testProcessor := TThriftTest.TProcessorImpl.Create( testHandler ); case servertype of srv_Simple : begin ServerEngine := TSimpleServer.Create( testProcessor, ServerTrans, TransportFactory, ProtocolFactory); end; srv_Nonblocking : begin raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented'); end; srv_Threadpool, srv_Threaded: begin if numWorker > 1 then {use here}; raise Exception.Create(SERVER_TYPES[servertype]+' server not implemented'); end; else raise Exception.Create('Unhandled server type'); end; ASSERT( ServerEngine <> nil); testHandler.SetServer( ServerEngine); // test events? if ServerEvents then begin Console.WriteLine('- server events test enabled'); ServerEngine.ServerEvents := TServerEventsImpl.Create; end; // start the client now when we have the anon handles, but before the server starts if endpoint = trns_AnonPipes then LaunchAnonPipeChild( ExtractFilePath(ParamStr(0))+'client.exe', anonymouspipe); // install Ctrl+C handler before the server starts g_Handler := testHandler; SetConsoleCtrlHandler( @MyConsoleEventHandler, TRUE); Console.WriteLine(''); repeat Console.WriteLine('Starting the server ...'); serverEngine.Serve; until {$IFDEF RunEndless} FALSE {$ELSE} TRUE {$ENDIF}; testHandler.SetServer( nil); g_Handler := nil; except on E: EAbort do raise; on E: Exception do begin Console.WriteLine( E.Message + #10 + E.StackTrace ); end; end; Console.WriteLine( 'done.'); end; end. thrift-0.19.0/lib/delphi/test/Performance/0000777000000000000000000000000014370300523020333 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/Performance/DataFactory.pas0000644000000000000000000001637214370300523023246 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. unit DataFactory; interface uses SysUtils, Thrift.Collections, Thrift.Test; type TestDataFactory = class strict protected class function CreateSetField(const count : Integer) : IThriftHashSet< IInsanity>; static; class function CreateInsanity(const count : Integer) : IInsanity; static; class function CreateBytesArray(const count : Integer) : TBytes; static; class function CreateXtructs(const count : Integer) : IThriftList< IXtruct>; static; class function CreateXtruct(const count : Integer) : IXtruct; static; class function CreateListField(const count : Integer) : IThriftList< IThriftDictionary< IThriftHashSet< Integer>, IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>>; static; class function CreateUserMap(const count : Integer) : IThriftDictionary< TNumberz, Int64>; static; class function CreateListFieldData(const count : Integer) : IThriftDictionary< IThriftHashSet< Integer>, IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>; static; class function CreateIntHashSet(const count : Integer) : IThriftHashSet< Integer>; static; class function CreateListFieldDataDict(const count : Integer) : IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>; static; class function CreateListFieldDataDictValue(const count : Integer) : IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>; static; class function CreateListFieldDataDictValueList(const count : Integer) : IThriftList< IThriftDictionary< IInsanity, string>>; static; class function CreateListFieldDataDictValueListDict(const count : Integer) : IThriftDictionary< IInsanity, string>; static; public class function CreateCrazyNesting(const count : Integer = 10) : ICrazyNesting; static; end; implementation class function TestDataFactory.CreateCrazyNesting(const count : Integer = 10) : ICrazyNesting; begin if (count <= 0) then Exit(nil); result := TCrazyNestingImpl.Create; result.Binary_field := CreateBytesArray(count); result.List_field := CreateListField(count); result.Set_field := CreateSetField(count); result.String_field := Format('data level %d', [count]); end; class function TestDataFactory.CreateSetField(const count : Integer) : IThriftHashSet< IInsanity>; var i : Integer; begin result := TThriftHashSetImpl< IInsanity>.Create; for i := 0 to count-1 do begin result.Add(CreateInsanity(count)); end; end; class function TestDataFactory.CreateInsanity(const count : Integer) : IInsanity; begin result := TInsanityImpl.Create; result.UserMap := CreateUserMap(count); result.Xtructs := CreateXtructs(count); end; class function TestDataFactory.CreateXtructs(const count : Integer) : IThriftList< IXtruct>; var i : Integer; begin result := TThriftListImpl< IXtruct>.Create; for i := 0 to count-1 do begin result.Add(CreateXtruct(count)); end; end; class function TestDataFactory.CreateXtruct(const count : Integer) : IXtruct; begin result := TXtructImpl.Create; result.Byte_thing := SmallInt(count mod 128); result.I32_thing := count; result.I64_thing := count; result.String_thing := Format('data level %d', [count]); end; class function TestDataFactory.CreateUserMap(const count : Integer) : IThriftDictionary< TNumberz, Int64>; begin result := TThriftDictionaryImpl< TNumberz, Int64>.Create; result.Add(TNumberz.ONE, count); result.Add(TNumberz.TWO, count); result.Add(TNumberz.THREE, count); result.Add(TNumberz.FIVE, count); result.Add(TNumberz.SIX, count); result.Add(TNumberz.EIGHT, count); end; class function TestDataFactory.CreateListField(const count : Integer) : IThriftList< IThriftDictionary< IThriftHashSet< Integer>, IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>>; var i : Integer; begin result := TThriftListImpl< IThriftDictionary< IThriftHashSet< Integer>, IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>>.Create; for i := 0 to count-1 do begin result.Add(CreateListFieldData(count)); end; end; class function TestDataFactory.CreateListFieldData(const count : Integer) : IThriftDictionary< IThriftHashSet< Integer>, IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>; var i : Integer; begin result := TThriftDictionaryImpl< IThriftHashSet< Integer>, IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>.Create; for i := 0 to count-1 do begin result.Add( CreateIntHashSet(count), CreateListFieldDataDict(count)); end; end; class function TestDataFactory.CreateIntHashSet(const count : Integer) : IThriftHashSet< Integer>; var i : Integer; begin result := TThriftHashSetImpl< Integer>.Create; for i := 0 to count-1 do begin result.Add(i); end; end; class function TestDataFactory.CreateListFieldDataDict(const count : Integer) : IThriftDictionary< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>; var i : Integer; begin result := TThriftDictionaryImpl< Integer, IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>.Create; for i := 0 to count-1 do begin result.Add(i, CreateListFieldDataDictValue(count)); end; end; class function TestDataFactory.CreateListFieldDataDictValue(const count : Integer) : IThriftHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>; var i : Integer; begin result := TThriftHashSetImpl< IThriftList< IThriftDictionary< IInsanity, string>>>.Create; for i := 0 to count-1 do begin result.Add( CreateListFieldDataDictValueList(count)); end; end; class function TestDataFactory.CreateListFieldDataDictValueList(const count : Integer) : IThriftList< IThriftDictionary< IInsanity, string>>; var i : Integer; begin result := TThriftListImpl< IThriftDictionary< IInsanity, string>>.Create; for i := 0 to count-1 do begin result.Add(CreateListFieldDataDictValueListDict(count)); end; end; class function TestDataFactory.CreateListFieldDataDictValueListDict(const count : Integer) : IThriftDictionary< IInsanity, string>; begin result := TThriftDictionaryImpl< IInsanity, string>.Create; result.Add(CreateInsanity(count), Format('data level %d', [count])); end; class function TestDataFactory.CreateBytesArray(const count : Integer) : TBytes; var i : Integer; begin SetLength( result, count); for i := 0 to count-1 do begin result[i] := i mod $FF; end; end; end. thrift-0.19.0/lib/delphi/test/Performance/PerfTests.pas0000644000000000000000000001245214303740367022771 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. unit PerfTests; interface uses Windows, Classes, SysUtils, Thrift.Collections, Thrift.Configuration, Thrift.Test, Thrift.Protocol, Thrift.Protocol.JSON, Thrift.Protocol.Compact, Thrift.Transport, Thrift.Stream, ConsoleHelper, TestConstants, DataFactory; type TPerformanceTests = class strict private FTestdata : ICrazyNesting; FMemBuffer : TMemoryStream; FTransport : ITransport; FConfig : IThriftConfiguration; procedure ProtocolPeformanceTest; procedure RunTest( const ptyp : TKnownProtocol; const layered : TLayeredTransport); function GenericProtocolFactory(const ptyp : TKnownProtocol; const layered : TLayeredTransport; const forWrite : Boolean) : IProtocol; function GetProtocolTransportName(const ptyp : TKnownProtocol; const layered : TLayeredTransport) : string; public class function Execute : Integer; end; implementation // not available in all versions, so make sure we have this one imported function IsDebuggerPresent: BOOL; stdcall; external KERNEL32 name 'IsDebuggerPresent'; class function TPerformanceTests.Execute : Integer; var instance : TPerformanceTests; begin instance := TPerformanceTests.Create; instance.ProtocolPeformanceTest; // debug only if IsDebuggerPresent then begin Console.Write('Hit ENTER ...'); ReadLn; end; result := 0; end; procedure TPerformanceTests.ProtocolPeformanceTest; var layered : TLayeredTransport; begin Console.WriteLine('Setting up for ProtocolPeformanceTest ...'); FTestdata := TestDataFactory.CreateCrazyNesting(); for layered := Low(TLayeredTransport) to High(TLayeredTransport) do begin RunTest( TKnownProtocol.prot_Binary, layered); RunTest( TKnownProtocol.prot_Compact, layered); RunTest( TKnownProtocol.prot_JSON, layered); end; end; procedure TPerformanceTests.RunTest( const ptyp : TKnownProtocol; const layered : TLayeredTransport); var freq, start, stop : Int64; proto : IProtocol; restored : ICrazyNesting; begin QueryPerformanceFrequency( freq); FConfig := TThriftConfigurationImpl.Create; proto := GenericProtocolFactory( ptyp, layered, TRUE); QueryPerformanceCounter( start); FTestdata.Write(proto); FTransport.Flush; QueryPerformanceCounter( stop); Console.WriteLine( Format('RunTest(%s): write = %d msec', [ GetProtocolTransportName(ptyp,layered), Round(1000.0*(stop-start)/freq) ])); restored := TCrazyNestingImpl.Create; proto := GenericProtocolFactory( ptyp, layered, FALSE); QueryPerformanceCounter( start); restored.Read(proto); QueryPerformanceCounter( stop); Console.WriteLine( Format('RunTest(%s): read = %d msec', [ GetProtocolTransportName(ptyp,layered), Round(1000.0*(stop-start)/freq) ])); end; function TPerformanceTests.GenericProtocolFactory(const ptyp : TKnownProtocol; const layered : TLayeredTransport; const forWrite : Boolean) : IProtocol; var newBuf : TMemoryStream; stream : IThriftStream; trans : IStreamTransport; const COPY_ENTIRE_STREAM = 0; begin // read happens after write here, so let's take over the written bytes newBuf := TMemoryStream.Create; if not forWrite then newBuf.CopyFrom( FMemBuffer, COPY_ENTIRE_STREAM); FMemBuffer := newBuf; FMemBuffer.Position := 0; // layered transports anyone? stream := TThriftStreamAdapterDelphi.Create( newBuf, TRUE); if forWrite then trans := TStreamTransportImpl.Create( nil, stream, FConfig) else trans := TStreamTransportImpl.Create( stream, nil, FConfig); case layered of trns_Framed : FTransport := TFramedTransportImpl.Create( trans); trns_Buffered : FTransport := TBufferedTransportImpl.Create( trans); else FTransport := trans; end; if not FTransport.IsOpen then FTransport.Open; case ptyp of prot_Binary : result := TBinaryProtocolImpl.Create(trans); prot_Compact : result := TCompactProtocolImpl.Create(trans); prot_JSON : result := TJSONProtocolImpl.Create(trans); else ASSERT(FALSE); end; end; function TPerformanceTests.GetProtocolTransportName(const ptyp : TKnownProtocol; const layered : TLayeredTransport) : string; begin case layered of trns_Framed : result := ' + framed'; trns_Buffered : result := ' + buffered'; else result := ''; end; case ptyp of prot_Binary : result := 'binary' + result; prot_Compact : result := 'compact' + result; prot_JSON : result := 'JSON' + result; else ASSERT(FALSE); end; end; end. thrift-0.19.0/lib/delphi/test/client.dproj0000644000000000000000000001360714370300523020413 0ustar00rootroot00000000000000 {F262F488-F81C-4B6E-8694-518C54CBB8F3} client.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false bin\$(Config)\$(Platform) DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication client.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 --protocol=compact True 12 thrift-0.19.0/lib/delphi/test/TestConstants.pas0000644000000000000000000002235214303740367021425 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit TestConstants; interface uses SysUtils, Thrift.Protocol, Thrift.Protocol.Compact, Thrift.Protocol.JSON; type TKnownProtocol = ( prot_Binary, // default binary protocol prot_JSON, // JSON protocol prot_Compact ); TServerType = ( srv_Simple, srv_Nonblocking, srv_Threadpool, srv_Threaded ); TEndpointTransport = ( trns_Sockets, trns_MsxmlHttp, trns_WinHttp, trns_NamedPipes, trns_AnonPipes, trns_EvHttp // as listed on http://thrift.apache.org/test ); TLayeredTransport = ( trns_None, trns_Buffered, trns_Framed ); TLayeredTransports = set of TLayeredTransport; const PROTOCOL_CLASSES : array[TKnownProtocol] of TProtocolImplClass = ( TBinaryProtocolImpl, TJSONProtocolImpl, TCompactProtocolImpl ); const SERVER_TYPES : array[TServerType] of string = ('Simple', 'Nonblocking', 'Threadpool', 'Threaded'); THRIFT_PROTOCOLS : array[TKnownProtocol] of string = ('Binary', 'JSON', 'Compact'); LAYERED_TRANSPORTS : array[TLayeredTransport] of string = ('None', 'Buffered', 'Framed'); ENDPOINT_TRANSPORTS : array[TEndpointTransport] of string = ('Sockets', 'Http', 'WinHttp', 'Named Pipes','Anon Pipes', 'EvHttp'); HUGE_TEST_STRING = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. ' + 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ' + 'eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam ' + 'voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit ' + 'amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam ' + 'nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed ' + 'diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet ' + 'clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. '; function BytesToHex( const bytes : TBytes) : string; implementation function BytesToHex( const bytes : TBytes) : string; var i : Integer; begin result := ''; for i := Low(bytes) to High(bytes) do begin result := result + IntToHex(bytes[i],2); end; end; end. thrift-0.19.0/lib/delphi/test/codegen/0000777000000000000000000000000014370300523017476 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/codegen/README.md0000644000000000000000000000136614303740367020771 0ustar00rootroot00000000000000How to use the test case: ---------------------------------------------- - copy and the template batch file - open the batch file and adjust configuration as necessary - run the batch Configuration: ---------------------------------------------- SVNWORKDIR should point to the Thrift working copy root MY_THRIFT_FILES can be set to point to a folder with more thrift IDL files. If you don't have any such files, just leave the setting blank. BIN Local MSYS binary folder. Your THRIFT.EXE is installed here. MINGW_BIN Local MinGW bin folder. Contains DLL files required by THRIFT.EXE DCC Identifies the Delphi Command Line compiler (dcc32.exe) To be configuired only, if the default is not suitable. ---------------------------------------------- *EOF*thrift-0.19.0/lib/delphi/test/codegen/run-Pascal-Codegen-Tests.bat.tmpl0000644000000000000000000001467414370300523025620 0ustar00rootroot00000000000000REM /* REM * Licensed to the Apache Software Foundation (ASF) under one REM * or more contributor license agreements. See the NOTICE file REM * distributed with this work for additional information REM * regarding copyright ownership. The ASF licenses this file REM * to you under the Apache License, Version 2.0 (the REM * "License"); you may not use this file except in compliance REM * with the License. You may obtain a copy of the License at REM * REM * http://www.apache.org/licenses/LICENSE-2.0 REM * REM * Unless required by applicable law or agreed to in writing, REM * software distributed under the License is distributed on an REM * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY REM * KIND, either express or implied. See the License for the REM * specific language governing permissions and limitations REM * under the License. REM */ @echo off if ""=="%1" goto CONFIG goto HANDLEDIR REM ----------------------------------------------------- :CONFIG REM ----------------------------------------------------- rem * CONFIGURATION BEGIN rem * configuration settings, adjust as necessary to meet your system setup set SVNWORKDIR= set MY_THRIFT_FILES= set BIN=C:\MSys10\local\bin set MINGW_BIN=C:\MinGW\bin set DCC= set SUBDIR=gen-delphi rem * CONFIGURATION END REM ----------------------------------------------------- :START REM ----------------------------------------------------- rem * configured? if "%SVNWORKDIR%"=="" goto CONFIG_ERROR rem * try to find dcc32.exe echo Looking for dcc32.exe ... if not exist "%DCC%" set DCC=%ProgramFiles%\Embarcadero\RAD Studio\8.0\bin\dcc32.exe if not exist "%DCC%" set DCC=%ProgramFiles(x86)%\Embarcadero\RAD Studio\8.0\bin\dcc32.exe if not exist "%DCC%" goto CONFIG_ERROR echo Found %DCC% echo. rem * some helpers set PATH=%BIN%;%MINGW_BIN%;%PATH% set TARGET=%SVNWORKDIR%\..\thrift-testing set SOURCE=%SVNWORKDIR% set TESTAPP=TestProject set UNITSEARCH=%SOURCE%\lib\pas\src;%SOURCE%\lib\delphi\src set OUTDCU="%TARGET%\dcu" set LOGFILE=%TARGET%\%SUBDIR%\codegen.log rem * create and/or empty target dirs if not exist "%TARGET%" md "%TARGET%" if not exist "%TARGET%\%SUBDIR%" md "%TARGET%\%SUBDIR%" if not exist "%OUTDCU%" md "%OUTDCU%" if exist "%TARGET%\*.thrift" del "%TARGET%\*.thrift" /Q if exist "%TARGET%\%SUBDIR%\*.*" del "%TARGET%\%SUBDIR%\*.*" /Q if exist "%OUTDCU%\*.*" del "%OUTDCU%\*.*" /Q rem init logfile echo Errors > "%LOGFILE%" echo ---------------- >> "%LOGFILE%" rem * recurse through thrift WC and "my thrift files" folder rem * copies all .thrift files into thrift-testing call %0 %SOURCE% if not "%MY_THRIFT_FILES%"=="" call %0 %MY_THRIFT_FILES% rem * compile all thrift files, generate PAS and C++ code echo. echo Generating code, please wait ... cd "%TARGET%" for %%a in (*.thrift) do "%BIN%\thrift.exe" -v --gen delphi:register_types,constprefix,events,xmldoc "%%a" 2>> "%LOGFILE%" REM * for %%a in (*.thrift) do "%BIN%\thrift.exe" -v --gen cpp "%%a" >> NUL: cmd /c start notepad "%LOGFILE%" cd .. rem * check for special Delphi testcases being processed if not exist "%TARGET%\%SUBDIR%\ReservedKeywords.pas" goto TESTCASE_MISSING rem * generate a minimal DPR file that uses all generated pascal units cd "%TARGET%\%SUBDIR%\" if exist inherited.* ren inherited.* _inherited.* echo program %TESTAPP%; > %TESTAPP%.dpr echo {$APPTYPE CONSOLE} >> %TESTAPP%.dpr echo. >> %TESTAPP%.dpr echo uses >> %TESTAPP%.dpr for %%a in (*.pas) do echo %%~na, >> %TESTAPP%.dpr echo Windows, Classes, SysUtils; >> %TESTAPP%.dpr echo. >> %TESTAPP%.dpr echo begin >> %TESTAPP%.dpr echo Writeln('Successfully compiled!'); >> %TESTAPP%.dpr echo Writeln('List of units:'); >> %TESTAPP%.dpr for %%a in (*.pas) do echo Write('%%~na':30,'':10); >> %TESTAPP%.dpr echo Writeln; >> %TESTAPP%.dpr echo end. >> %TESTAPP%.dpr echo. >> %TESTAPP%.dpr cd ..\.. rem * try to compile the DPR rem * this should not throw any errors, warnings or hints "%DCC%" -B "%TARGET%\%SUBDIR%\%TESTAPP%" -U"%UNITSEARCH%" -I"%UNITSEARCH%" -N"%OUTDCU%" -E"%TARGET%\%SUBDIR%" dir "%TARGET%\%SUBDIR%\%TESTAPP%.exe" if not exist "%TARGET%\%SUBDIR%\%TESTAPP%.exe" goto CODEGEN_FAILED echo. echo ----------------------------------------------------------------- echo The compiled program is now executed. If it hangs or crashes, we echo have a serious problem with the generated code. Expected output echo is "Successfully compiled:" followed by a list of generated units. echo ----------------------------------------------------------------- "%TARGET%\%SUBDIR%\%TESTAPP%.exe" echo ----------------------------------------------------------------- echo. pause GOTO EOF REM ----------------------------------------------------- :DXE_NOT_FOUND REM ----------------------------------------------------- echo Delphi Compiler (dcc32.exe) not found. echo Please check the "DCC" setting in this batch. echo. cmd /c start notepad README.MD cmd /c start notepad %0 pause GOTO EOF REM ----------------------------------------------------- :CONFIG_ERROR REM ----------------------------------------------------- echo Missing, incomplete or wrong configuration settings! cmd /c start notepad README.MD cmd /c start notepad %0 pause GOTO EOF REM ----------------------------------------------------- :TESTCASE_MISSING REM ----------------------------------------------------- echo Missing an expected Delphi testcase! pause GOTO EOF REM ----------------------------------------------------- :CODEGEN_FAILED REM ----------------------------------------------------- echo Code generation FAILED! pause GOTO EOF REM ----------------------------------------------------- :HANDLEDIR REM ----------------------------------------------------- REM echo %1 for /D %%a in (%1\*) do call %0 %%a if exist "%1\*.thrift" copy /b "%1\*.thrift" "%TARGET%\*.*" GOTO EOF REM ----------------------------------------------------- :EOF REM ----------------------------------------------------- thrift-0.19.0/lib/delphi/test/TestClient.pas0000644000000000000000000015000314370300523020650 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit TestClient; {$I ../src/Thrift.Defines.inc} {.$DEFINE StressTest} // activate to stress-test the server with frequent connects/disconnects {.$DEFINE PerfTest} // activate the performance test {$DEFINE Exceptions} // activate the exceptions test (or disable while debugging) {$if CompilerVersion >= 28} {$DEFINE SupportsAsync} {$ifend} {$WARN SYMBOL_PLATFORM OFF} // Win32Check interface uses Classes, Windows, SysUtils, Math, ActiveX, ComObj, {$IFDEF SupportsAsync} System.Threading, {$ENDIF} DateUtils, Generics.Collections, TestConstants, ConsoleHelper, PerfTests, Thrift, Thrift.Protocol.Compact, Thrift.Protocol.JSON, Thrift.Protocol, Thrift.Transport.Pipes, Thrift.Transport.WinHTTP, Thrift.Transport.MsxmlHTTP, Thrift.Transport, Thrift.Stream, Thrift.Test, Thrift.WinHTTP, Thrift.Utils, Thrift.Configuration, Thrift.Collections; type TClientThread = class; TThreadConsole = class(TThriftConsole) strict private FThread : TClientThread; FLogThreadID : Boolean; public constructor Create( const aThread: TClientThread; const aLogThreadID : Boolean); procedure Write( const S: string); override; procedure WriteLine( const S: string); override; end; TTestSetup = record protType : TKnownProtocol; endpoint : TEndpointTransport; layered : TLayeredTransports; useSSL : Boolean; // include where appropriate (TLayeredTransport?) host : string; port : Integer; sPipeName : string; hAnonRead, hAnonWrite : THandle; end; TClientThread = class( TThread ) private type TTestGroup = ( test_Unknown, test_BaseTypes, test_Structs, test_Containers, test_Exceptions // new values here ); TTestGroups = set of TTestGroup; TTestSize = ( Empty, // Edge case: the zero-length empty binary Normal, // Fairly small array of usual size (256 bytes) ByteArrayTest, // THRIFT-4454 Large writes/reads may cause range check errors in debug mode PipeWriteLimit, // THRIFT-4372 Pipe write operations across a network are limited to 65,535 bytes per write. FifteenMB // quite a bit of data, but still below the default max frame size ); strict private FSetup : TTestSetup; FTransport : ITransport; FProtocol : IProtocol; FNumIterations : Integer; FThreadNo : Integer; FConsole : TThreadConsole; // test reporting, will be refactored out into separate class later FTestGroup : string; FCurrentTest : TTestGroup; FSuccesses : Integer; FErrors : TStringList; FFailed : TTestGroups; FExecuted : TTestGroups; procedure StartTestGroup( const aGroup : string; const aTest : TTestGroup); procedure Expect( aTestResult : Boolean; const aTestInfo : string); procedure ReportResults; function CalculateExitCode : Byte; procedure ClientTest; {$IFDEF SupportsAsync} procedure ClientAsyncTest; {$ENDIF} procedure InitializeProtocolTransportStack; procedure ShutdownProtocolTransportStack; function InitializeHttpTransport( const aTimeoutSetting : Integer; const aConfig : IThriftConfiguration = nil) : IHTTPClient; procedure JSONProtocolReadWriteTest; function PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes; {$IFDEF StressTest} procedure StressTest(const client : TThriftTest.Iface); {$ENDIF} {$IFDEF Win64} procedure UseInterlockedExchangeAdd64; {$ENDIF} strict protected procedure Execute; override; property Console : TThreadConsole read FConsole; public constructor Create( const aSetup : TTestSetup; const aNumIteration, aThreadNo: Integer; const aLogThreadID : Boolean); destructor Destroy; override; property ThreadNo : Integer read FThreadNo; end; TTestClient = class private class var FNumIterations : Integer; FNumThreads : Integer; class procedure PrintCmdLineHelp; class procedure InvalidArgs; public class function Execute( const arguments: array of string) : Byte; end; implementation const EXITCODE_SUCCESS = $00; // no errors bits set // EXITCODE_FAILBIT_BASETYPES = $01; EXITCODE_FAILBIT_STRUCTS = $02; EXITCODE_FAILBIT_CONTAINERS = $04; EXITCODE_FAILBIT_EXCEPTIONS = $08; MAP_FAILURES_TO_EXITCODE_BITS : array[TClientThread.TTestGroup] of Byte = ( EXITCODE_SUCCESS, // no bits here EXITCODE_FAILBIT_BASETYPES, EXITCODE_FAILBIT_STRUCTS, EXITCODE_FAILBIT_CONTAINERS, EXITCODE_FAILBIT_EXCEPTIONS ); function BoolToString( b : Boolean) : string; // overrides global BoolToString() begin if b then result := 'true' else result := 'false'; end; // not available in all versions, so make sure we have this one imported function IsDebuggerPresent: BOOL; stdcall; external KERNEL32 name 'IsDebuggerPresent'; { TTestClient } class procedure TTestClient.PrintCmdLineHelp; const HELPTEXT = ' [options]'#10 + #10 + 'Allowed options:'#10 + ' -h | --help Produces this help message'#10 + ' --host=arg (localhost) Host to connect'#10 + ' --port=arg (9090) Port number to connect'#10 + ' --pipe=arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + ' --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)'#10 + ' --transport=arg (sockets) Transport: buffered, framed, http, winhttp'#10 + ' --protocol=arg (binary) Protocol: binary, compact, json'#10 + ' --ssl Encrypted Transport using SSL'#10 + ' -n=num | --testloops=num (1) Number of Tests'#10 + ' -t=num | --threads=num (1) Number of Test threads'#10 + ' --performance Run the built-in performance test (no other arguments)'#10 ; begin Writeln( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT); end; class procedure TTestClient.InvalidArgs; begin Console.WriteLine( 'Invalid args.'); Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + ' -h for more information'); Abort; end; class function TTestClient.Execute(const arguments: array of string) : Byte; function IsSwitch( const aArgument, aSwitch : string; out sValue : string) : Boolean; begin sValue := ''; result := (Copy( aArgument, 1, Length(aSwitch)) = aSwitch); if result then begin if (Copy( aArgument, 1, Length(aSwitch)+1) = (aSwitch+'=')) then sValue := Copy( aArgument, Length(aSwitch)+2, MAXINT); end; end; var iArg : Integer; threadExitCode : Byte; sArg, sValue : string; threads : array of TThread; dtStart : TDateTime; test : Integer; thread : TThread; setup : TTestSetup; begin // init record with setup do begin protType := prot_Binary; endpoint := trns_Sockets; layered := []; useSSL := FALSE; host := 'localhost'; port := 9090; sPipeName := ''; hAnonRead := INVALID_HANDLE_VALUE; hAnonWrite := INVALID_HANDLE_VALUE; end; try iArg := 0; while iArg < Length(arguments) do begin sArg := arguments[iArg]; Inc(iArg); if IsSwitch( sArg, '-h', sValue) or IsSwitch( sArg, '--help', sValue) then begin // -h [ --help ] produce help message PrintCmdLineHelp; result := $FF; // all tests failed Exit; end else if IsSwitch( sArg, '--host', sValue) then begin // --host arg (=localhost) Host to connect setup.host := sValue; end else if IsSwitch( sArg, '--port', sValue) then begin // --port arg (=9090) Port number to connect setup.port := StrToIntDef(sValue,0); if setup.port <= 0 then InvalidArgs; end else if IsSwitch( sArg, '--domain-socket', sValue) then begin // --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port raise Exception.Create('domain-socket not supported'); end // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) else if IsSwitch( sArg, '--pipe', sValue) then begin // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) setup.endpoint := trns_NamedPipes; setup.sPipeName := sValue; Console.WriteLine('Using named pipe ('+setup.sPipeName+')'); end else if IsSwitch( sArg, '--anon-pipes', sValue) then begin // --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) setup.endpoint := trns_AnonPipes; setup.hAnonRead := THandle( StrToIntDef( arguments[iArg], Integer(INVALID_HANDLE_VALUE))); Inc(iArg); setup.hAnonWrite := THandle( StrToIntDef( arguments[iArg], Integer(INVALID_HANDLE_VALUE))); Inc(iArg); Console.WriteLine('Using anonymous pipes ('+IntToStr(Integer(setup.hAnonRead))+' and '+IntToStr(Integer(setup.hAnonWrite))+')'); end else if IsSwitch( sArg, '--transport', sValue) then begin // --transport arg (=sockets) Transport: buffered, framed, http, winhttp, evhttp if sValue = 'buffered' then Include( setup.layered, trns_Buffered) else if sValue = 'framed' then Include( setup.layered, trns_Framed) else if sValue = 'http' then setup.endpoint := trns_MsXmlHttp else if sValue = 'winhttp' then setup.endpoint := trns_WinHttp else if sValue = 'evhttp' then setup.endpoint := trns_EvHttp // recognized, but not supported else InvalidArgs; end else if IsSwitch( sArg, '--protocol', sValue) then begin // --protocol arg (=binary) Protocol: binary, compact, json if sValue = 'binary' then setup.protType := prot_Binary else if sValue = 'compact' then setup.protType := prot_Compact else if sValue = 'json' then setup.protType := prot_JSON else InvalidArgs; end else if IsSwitch( sArg, '--ssl', sValue) then begin // --ssl Encrypted Transport using SSL setup.useSSL := TRUE; end else if IsSwitch( sArg, '-n', sValue) or IsSwitch( sArg, '--testloops', sValue) then begin // -n [ --testloops ] arg (=1) Number of Tests FNumIterations := StrToIntDef( sValue, 0); if FNumIterations <= 0 then InvalidArgs; end else if IsSwitch( sArg, '-t', sValue) or IsSwitch( sArg, '--threads', sValue) then begin // -t [ --threads ] arg (=1) Number of Test threads FNumThreads := StrToIntDef( sValue, 0); if FNumThreads <= 0 then InvalidArgs; end else if IsSwitch( sArg, '--performance', sValue) then begin result := TPerformanceTests.Execute; Exit; end else begin InvalidArgs; end; end; // In the anonymous pipes mode the client is launched by the test server // -> behave nicely and allow for attaching a debugger to this process if (setup.endpoint = trns_AnonPipes) and not IsDebuggerPresent then MessageBox( 0, 'Attach Debugger and/or click OK to continue.', 'Thrift TestClient (Delphi)', MB_OK or MB_ICONEXCLAMATION); SetLength( threads, FNumThreads); dtStart := Now; // layered transports are not really meant to be stacked upon each other if (trns_Framed in setup.layered) then begin Console.WriteLine('Using framed transport'); end else if (trns_Buffered in setup.layered) then begin Console.WriteLine('Using buffered transport'); end; Console.WriteLine(THRIFT_PROTOCOLS[setup.protType]+' protocol'); if FNumThreads <> 1 then Console.WriteLine(IntToStr(FNumThreads)+' client threads'); if FNumIterations <> 1 then Console.WriteLine(IntToStr(FNumIterations)+' iterations'); for test := 0 to FNumThreads - 1 do begin thread := TClientThread.Create( setup, FNumIterations, test, FNumThreads<>1); threads[test] := thread; thread.Start; end; result := 0; for test := 0 to FNumThreads - 1 do begin threadExitCode := threads[test].WaitFor; result := result or threadExitCode; threads[test].Free; threads[test] := nil; end; Console.Write('Total time: ' + IntToStr( MilliSecondsBetween(Now, dtStart))); except on E: EAbort do raise; on E: Exception do begin Console.WriteLine( E.Message + #10 + E.StackTrace); raise; end; end; Console.WriteLine(''); Console.WriteLine('done!'); end; { TClientThread } procedure TClientThread.ClientTest; var client : TThriftTest.Iface; s : string; i8 : ShortInt; i32 : Integer; i64 : Int64; binOut,binIn : TBytes; guidIn, guidOut : TGuid; dub : Double; o : IXtruct; o2 : IXtruct2; i : IXtruct; i2 : IXtruct2; mapout : IThriftDictionary; mapin : IThriftDictionary; strmapout : IThriftDictionary; strmapin : IThriftDictionary; j : Integer; first : Boolean; key : Integer; strkey : string; listout : IThriftList; listin : IThriftList; setout : IThriftHashSet; setin : IThriftHashSet; ret : TNumberz; uid : Int64; mm : IThriftDictionary>; pos : IThriftDictionary; neg : IThriftDictionary; m2 : IThriftDictionary; k2 : Integer; insane : IInsanity; truck : IXtruct; whoa : IThriftDictionary>; key64 : Int64; val : IThriftDictionary; k2_2 : TNumberz; k3 : TNumberz; v2 : IInsanity; userMap : IThriftDictionary; xtructs : IThriftList; x : IXtruct; arg0 : ShortInt; arg1 : Integer; arg2 : Int64; arg3 : IThriftDictionary; arg4 : TNumberz; arg5 : Int64; {$IFDEF PerfTest} StartTick : Cardinal; k : Integer; {$ENDIF} hello, goodbye : IXtruct; crazy : IInsanity; looney : IInsanity; first_map : IThriftDictionary; second_map : IThriftDictionary; pair : TPair; testsize : TTestSize; begin client := TThriftTest.TClient.Create( FProtocol); FTransport.Open; {$IFDEF StressTest} StressTest( client); {$ENDIF StressTest} {$IFDEF Exceptions} // in-depth exception test // (1) do we get an exception at all? // (2) do we get the right exception? // (3) does the exception contain the expected data? StartTestGroup( 'testException', test_Exceptions); // case 1: exception type declared in IDL at the function call try client.testException('Xception'); Expect( FALSE, 'testException(''Xception''): must trow an exception'); except on e:TXception do begin Expect( e.ErrorCode = 1001, 'error code'); Expect( e.Message_ = 'Xception', 'error message'); Console.WriteLine( ' = ' + IntToStr(e.ErrorCode) + ', ' + e.Message_ ); end; on e:TTransportException do Expect( FALSE, 'Unexpected : "'+e.ToString+'"'); on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); end; // re-open connection if needed if not FTransport.IsOpen then FTransport.Open; // case 2: exception type NOT declared in IDL at the function call // this will close the connection try client.testException('TException'); Expect( FALSE, 'testException(''TException''): must trow an exception'); except on e:TTransportException do begin Console.WriteLine( e.ClassName+' = '+e.Message); // this is what we get end; on e:TApplicationException do begin Console.WriteLine( e.ClassName+' = '+e.Message); // this is what we get end; on e:TException do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); end; if FTransport.IsOpen then FTransport.Close; FTransport.Open; // re-open connection, server has already closed // case 3: no exception try client.testException('something'); Expect( TRUE, 'testException(''something''): must not trow an exception'); except on e:TTransportException do Expect( FALSE, 'Unexpected : "'+e.ToString+'"'); on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); end; {$ENDIF Exceptions} // re-open connection if needed if not FTransport.IsOpen then FTransport.Open; // simple things StartTestGroup( 'simple Thrift calls', test_BaseTypes); client.testVoid(); Expect( TRUE, 'testVoid()'); // success := no exception s := BoolToString( client.testBool(TRUE)); Expect( s = BoolToString(TRUE), 'testBool(TRUE) = '+s); s := BoolToString( client.testBool(FALSE)); Expect( s = BoolToString(FALSE), 'testBool(FALSE) = '+s); s := client.testString('Test'); Expect( s = 'Test', 'testString(''Test'') = "'+s+'"'); s := client.testString(''); // empty string Expect( s = '', 'testString('''') = "'+s+'"'); s := client.testString(HUGE_TEST_STRING); Expect( length(s) = length(HUGE_TEST_STRING), 'testString( length(HUGE_TEST_STRING) = '+IntToStr(Length(HUGE_TEST_STRING))+') ' +'=> length(result) = '+IntToStr(Length(s))); i8 := client.testByte(1); Expect( i8 = 1, 'testByte(1) = ' + IntToStr( i8 )); i32 := client.testI32(-1); Expect( i32 = -1, 'testI32(-1) = ' + IntToStr(i32)); Console.WriteLine('testI64(-34359738368)'); i64 := client.testI64(-34359738368); Expect( i64 = -34359738368, 'testI64(-34359738368) = ' + IntToStr( i64)); guidOut := StringToGUID('{00112233-4455-6677-8899-AABBCCDDEEFF}'); Console.WriteLine('testUuid('+GUIDToString(guidOut)+')'); try guidIn := client.testUuid(guidOut); Expect( IsEqualGUID(guidIn, guidOut), 'testUuid('+GUIDToString(guidOut)+') = '+GUIDToString(guidIn)); except on e:TApplicationException do Console.WriteLine('testUuid(): '+e.Message); on e:Exception do Expect( FALSE, 'testUuid(): Unexpected exception "'+e.ClassName+'": '+e.Message); end; // random binary small for testsize := Low(TTestSize) to High(TTestSize) do begin binOut := PrepareBinaryData( TRUE, testsize); Console.WriteLine('testBinary('+IntToStr(Length(binOut))+' bytes)'); try binIn := client.testBinary(binOut); Expect( Length(binOut) = Length(binIn), 'testBinary('+IntToStr(Length(binOut))+' bytes): '+IntToStr(Length(binIn))+' bytes received'); i32 := Min( Length(binOut), Length(binIn)); Expect( CompareMem( binOut, binIn, i32), 'testBinary('+IntToStr(Length(binOut))+' bytes): validating received data'); except on e:TApplicationException do Console.WriteLine('testBinary(): '+e.Message); on e:Exception do Expect( FALSE, 'testBinary(): Unexpected exception "'+e.ClassName+'": '+e.Message); end; end; Console.WriteLine('testDouble(5.325098235)'); dub := client.testDouble(5.325098235); Expect( abs(dub-5.325098235) < 1e-14, 'testDouble(5.325098235) = ' + FloatToStr( dub)); // structs StartTestGroup( 'testStruct', test_Structs); Console.WriteLine('testStruct({''Zero'', 1, -3, -5})'); o := TXtructImpl.Create; o.String_thing := 'Zero'; o.Byte_thing := 1; o.I32_thing := -3; o.I64_thing := -5; i := client.testStruct(o); Expect( i.String_thing = 'Zero', 'i.String_thing = "'+i.String_thing+'"'); Expect( i.Byte_thing = 1, 'i.Byte_thing = '+IntToStr(i.Byte_thing)); Expect( i.I32_thing = -3, 'i.I32_thing = '+IntToStr(i.I32_thing)); Expect( i.I64_thing = -5, 'i.I64_thing = '+IntToStr(i.I64_thing)); Expect( i.__isset_String_thing, 'i.__isset_String_thing = '+BoolToString(i.__isset_String_thing)); Expect( i.__isset_Byte_thing, 'i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing)); Expect( i.__isset_I32_thing, 'i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing)); Expect( i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing)); // nested structs StartTestGroup( 'testNest', test_Structs); Console.WriteLine('testNest({1, {''Zero'', 1, -3, -5}, 5})'); o2 := TXtruct2Impl.Create; o2.Byte_thing := 1; o2.Struct_thing := o; o2.I32_thing := 5; i2 := client.testNest(o2); i := i2.Struct_thing; Expect( i.String_thing = 'Zero', 'i.String_thing = "'+i.String_thing+'"'); Expect( i.Byte_thing = 1, 'i.Byte_thing = '+IntToStr(i.Byte_thing)); Expect( i.I32_thing = -3, 'i.I32_thing = '+IntToStr(i.I32_thing)); Expect( i.I64_thing = -5, 'i.I64_thing = '+IntToStr(i.I64_thing)); Expect( i2.Byte_thing = 1, 'i2.Byte_thing = '+IntToStr(i2.Byte_thing)); Expect( i2.I32_thing = 5, 'i2.I32_thing = '+IntToStr(i2.I32_thing)); Expect( i.__isset_String_thing, 'i.__isset_String_thing = '+BoolToString(i.__isset_String_thing)); Expect( i.__isset_Byte_thing, 'i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing)); Expect( i.__isset_I32_thing, 'i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing)); Expect( i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing)); Expect( i2.__isset_Byte_thing, 'i2.__isset_Byte_thing'); Expect( i2.__isset_I32_thing, 'i2.__isset_I32_thing'); // map: A map of strictly unique keys to values. // Translates to an STL map, Java HashMap, PHP associative array, Python/Ruby dictionary, etc. StartTestGroup( 'testMap', test_Containers); mapout := TThriftDictionaryImpl.Create; for j := 0 to 4 do begin mapout.AddOrSetValue( j, j - 10); end; Console.Write('testMap({'); first := True; for key in mapout.Keys do begin if first then first := False else Console.Write( ', ' ); Console.Write( IntToStr( key) + ' => ' + IntToStr( mapout[key])); end; Console.WriteLine('})'); mapin := client.testMap( mapout ); Expect( mapin.Count = mapout.Count, 'testMap: mapin.Count = mapout.Count'); for j := 0 to 4 do begin Expect( mapout.ContainsKey(j), 'testMap: mapout.ContainsKey('+IntToStr(j)+') = '+BoolToString(mapout.ContainsKey(j))); end; for key in mapin.Keys do begin Expect( mapin[key] = mapout[key], 'testMap: '+IntToStr(key) + ' => ' + IntToStr( mapin[key])); Expect( mapin[key] = key - 10, 'testMap: mapin['+IntToStr(key)+'] = '+IntToStr( mapin[key])); end; // map: A map of strictly unique keys to values. // Translates to an STL map, Java HashMap, PHP associative array, Python/Ruby dictionary, etc. StartTestGroup( 'testStringMap', test_Containers); strmapout := TThriftDictionaryImpl.Create; for j := 0 to 4 do begin strmapout.AddOrSetValue( IntToStr(j), IntToStr(j - 10)); end; Console.Write('testStringMap({'); first := True; for strkey in strmapout.Keys do begin if first then first := False else Console.Write( ', ' ); Console.Write( strkey + ' => ' + strmapout[strkey]); end; Console.WriteLine('})'); strmapin := client.testStringMap( strmapout ); Expect( strmapin.Count = strmapout.Count, 'testStringMap: strmapin.Count = strmapout.Count'); for j := 0 to 4 do begin Expect( strmapout.ContainsKey(IntToStr(j)), 'testStringMap: strmapout.ContainsKey('+IntToStr(j)+') = ' + BoolToString(strmapout.ContainsKey(IntToStr(j)))); end; for strkey in strmapin.Keys do begin Expect( strmapin[strkey] = strmapout[strkey], 'testStringMap: '+strkey + ' => ' + strmapin[strkey]); Expect( strmapin[strkey] = IntToStr( StrToInt(strkey) - 10), 'testStringMap: strmapin['+strkey+'] = '+strmapin[strkey]); end; // set: An unordered set of unique elements. // Translates to an STL set, Java HashSet, set in Python, etc. // Note: PHP does not support sets, so it is treated similar to a List StartTestGroup( 'testSet', test_Containers); setout := TThriftHashSetImpl.Create; for j := -2 to 2 do begin setout.Add( j ); end; Console.Write('testSet({'); first := True; for j in setout do begin if first then first := False else Console.Write(', '); Console.Write(IntToStr( j)); end; Console.WriteLine('})'); setin := client.testSet(setout); Expect( setin.Count = setout.Count, 'testSet: setin.Count = setout.Count'); Expect( setin.Count = 5, 'testSet: setin.Count = '+IntToStr(setin.Count)); for j := -2 to 2 do // unordered, we can't rely on the order => test for known elements only begin Expect( setin.Contains(j), 'testSet: setin.Contains('+IntToStr(j)+') => '+BoolToString(setin.Contains(j))); end; // list: An ordered list of elements. // Translates to an STL vector, Java ArrayList, native arrays in scripting languages, etc. StartTestGroup( 'testList', test_Containers); listout := TThriftListImpl.Create; listout.Add( +1); listout.Add( -2); listout.Add( +3); listout.Add( -4); listout.Add( 0); Console.Write('testList({'); first := True; for j in listout do begin if first then first := False else Console.Write(', '); Console.Write(IntToStr( j)); end; Console.WriteLine('})'); listin := client.testList(listout); Expect( listin.Count = listout.Count, 'testList: listin.Count = listout.Count'); Expect( listin.Count = 5, 'testList: listin.Count = '+IntToStr(listin.Count)); Expect( listin[0] = +1, 'listin[0] = '+IntToStr( listin[0])); Expect( listin[1] = -2, 'listin[1] = '+IntToStr( listin[1])); Expect( listin[2] = +3, 'listin[2] = '+IntToStr( listin[2])); Expect( listin[3] = -4, 'listin[3] = '+IntToStr( listin[3])); Expect( listin[4] = 0, 'listin[4] = '+IntToStr( listin[4])); // enums ret := client.testEnum(TNumberz.ONE); Expect( ret = TNumberz.ONE, 'testEnum(ONE) = '+IntToStr(Ord(ret))); ret := client.testEnum(TNumberz.TWO); Expect( ret = TNumberz.TWO, 'testEnum(TWO) = '+IntToStr(Ord(ret))); ret := client.testEnum(TNumberz.THREE); Expect( ret = TNumberz.THREE, 'testEnum(THREE) = '+IntToStr(Ord(ret))); ret := client.testEnum(TNumberz.FIVE); Expect( ret = TNumberz.FIVE, 'testEnum(FIVE) = '+IntToStr(Ord(ret))); ret := client.testEnum(TNumberz.EIGHT); Expect( ret = TNumberz.EIGHT, 'testEnum(EIGHT) = '+IntToStr(Ord(ret))); // typedef uid := client.testTypedef(309858235082523); Expect( uid = 309858235082523, 'testTypedef(309858235082523) = '+IntToStr(uid)); // maps of maps StartTestGroup( 'testMapMap(1)', test_Containers); mm := client.testMapMap(1); Console.Write(' = {'); for key in mm.Keys do begin Console.Write( IntToStr( key) + ' => {'); m2 := mm[key]; for k2 in m2.Keys do begin Console.Write( IntToStr( k2) + ' => ' + IntToStr( m2[k2]) + ', '); end; Console.Write('}, '); end; Console.WriteLine('}'); // verify result data Expect( mm.Count = 2, 'mm.Count = '+IntToStr(mm.Count)); pos := mm[4]; neg := mm[-4]; for j := 1 to 4 do begin Expect( pos[j] = j, 'pos[j] = '+IntToStr(pos[j])); Expect( neg[-j] = -j, 'neg[-j] = '+IntToStr(neg[-j])); end; // insanity StartTestGroup( 'testInsanity', test_Structs); insane := TInsanityImpl.Create; insane.UserMap := TThriftDictionaryImpl.Create; insane.UserMap.AddOrSetValue( TNumberz.FIVE, 5000); truck := TXtructImpl.Create; truck.String_thing := 'Truck'; truck.Byte_thing := -8; // byte is signed truck.I32_thing := 32; truck.I64_thing := 64; insane.Xtructs := TThriftListImpl.Create; insane.Xtructs.Add( truck ); whoa := client.testInsanity( insane ); Console.Write(' = {'); for key64 in whoa.Keys do begin val := whoa[key64]; Console.Write( IntToStr( key64) + ' => {'); for k2_2 in val.Keys do begin v2 := val[k2_2]; Console.Write( IntToStr( Integer( k2_2)) + ' => {'); userMap := v2.UserMap; Console.Write('{'); if userMap <> nil then begin for k3 in userMap.Keys do begin Console.Write( IntToStr( Integer( k3)) + ' => ' + IntToStr( userMap[k3]) + ', '); end; end else begin Console.Write('null'); end; Console.Write('}, '); xtructs := v2.Xtructs; Console.Write('{'); if xtructs <> nil then begin for x in xtructs do begin Console.Write('{"' + x.String_thing + '", ' + IntToStr( x.Byte_thing) + ', ' + IntToStr( x.I32_thing) + ', ' + IntToStr( x.I32_thing) + '}, '); end; end else begin Console.Write('null'); end; Console.Write('}'); Console.Write('}, '); end; Console.Write('}, '); end; Console.WriteLine('}'); (** * So you think you've got this all worked, out eh? * * Creates a the returned map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, * 2 => { 6 => , }, * } * @return map> - a map with the above values *) // verify result data Expect( whoa.Count = 2, 'whoa.Count = '+IntToStr(whoa.Count)); // first_map := whoa[1]; second_map := whoa[2]; Expect( first_map.Count = 2, 'first_map.Count = '+IntToStr(first_map.Count)); Expect( second_map.Count = 1, 'second_map.Count = '+IntToStr(second_map.Count)); // looney := second_map[TNumberz.SIX]; Expect( Assigned(looney), 'Assigned(looney) = '+BoolToString(Assigned(looney))); Expect( not looney.__isset_UserMap, 'looney.__isset_UserMap = '+BoolToString(looney.__isset_UserMap)); Expect( not looney.__isset_Xtructs, 'looney.__isset_Xtructs = '+BoolToString(looney.__isset_Xtructs)); // for ret in [TNumberz.TWO, TNumberz.THREE] do begin crazy := first_map[ret]; Console.WriteLine('first_map['+intToStr(Ord(ret))+']'); Expect( crazy.__isset_UserMap, 'crazy.__isset_UserMap = '+BoolToString(crazy.__isset_UserMap)); Expect( crazy.__isset_Xtructs, 'crazy.__isset_Xtructs = '+BoolToString(crazy.__isset_Xtructs)); Expect( crazy.UserMap.Count = insane.UserMap.Count, 'crazy.UserMap.Count = '+IntToStr(crazy.UserMap.Count)); for pair in insane.UserMap do begin Expect( crazy.UserMap[pair.Key] = pair.Value, 'crazy.UserMap['+IntToStr(Ord(pair.key))+'] = '+IntToStr(crazy.UserMap[pair.Key])); end; Expect( crazy.Xtructs.Count = insane.Xtructs.Count, 'crazy.Xtructs.Count = '+IntToStr(crazy.Xtructs.Count)); for arg0 := 0 to insane.Xtructs.Count-1 do begin hello := insane.Xtructs[arg0]; goodbye := crazy.Xtructs[arg0]; Expect( goodbye.String_thing = hello.String_thing, 'goodbye.String_thing = '+goodbye.String_thing); Expect( goodbye.Byte_thing = hello.Byte_thing, 'goodbye.Byte_thing = '+IntToStr(goodbye.Byte_thing)); Expect( goodbye.I32_thing = hello.I32_thing, 'goodbye.I32_thing = '+IntToStr(goodbye.I32_thing)); Expect( goodbye.I64_thing = hello.I64_thing, 'goodbye.I64_thing = '+IntToStr(goodbye.I64_thing)); end; end; // multi args StartTestGroup( 'testMulti', test_BaseTypes); arg0 := 1; arg1 := 2; arg2 := High(Int64); arg3 := TThriftDictionaryImpl.Create; arg3.AddOrSetValue( 1, 'one'); arg4 := TNumberz.FIVE; arg5 := 5000000; Console.WriteLine('Test Multi(' + IntToStr( arg0) + ',' + IntToStr( arg1) + ',' + IntToStr( arg2) + ',' + arg3.ToString + ',' + IntToStr( Integer( arg4)) + ',' + IntToStr( arg5) + ')'); i := client.testMulti( arg0, arg1, arg2, arg3, arg4, arg5); Expect( i.String_thing = 'Hello2', 'testMulti: i.String_thing = "'+i.String_thing+'"'); Expect( i.Byte_thing = arg0, 'testMulti: i.Byte_thing = '+IntToStr(i.Byte_thing)); Expect( i.I32_thing = arg1, 'testMulti: i.I32_thing = '+IntToStr(i.I32_thing)); Expect( i.I64_thing = arg2, 'testMulti: i.I64_thing = '+IntToStr(i.I64_thing)); Expect( i.__isset_String_thing, 'testMulti: i.__isset_String_thing = '+BoolToString(i.__isset_String_thing)); Expect( i.__isset_Byte_thing, 'testMulti: i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing)); Expect( i.__isset_I32_thing, 'testMulti: i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing)); Expect( i.__isset_I64_thing, 'testMulti: i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing)); // multi exception StartTestGroup( 'testMultiException(1)', test_Exceptions); try i := client.testMultiException( 'need more pizza', 'run out of beer'); Expect( i.String_thing = 'run out of beer', 'i.String_thing = "' +i.String_thing+ '"'); Expect( i.__isset_String_thing, 'i.__isset_String_thing = '+BoolToString(i.__isset_String_thing)); { this is not necessarily true, these fields are default-serialized Expect( not i.__isset_Byte_thing, 'i.__isset_Byte_thing = '+BoolToString(i.__isset_Byte_thing)); Expect( not i.__isset_I32_thing, 'i.__isset_I32_thing = '+BoolToString(i.__isset_I32_thing)); Expect( not i.__isset_I64_thing, 'i.__isset_I64_thing = '+BoolToString(i.__isset_I64_thing)); } except on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); end; StartTestGroup( 'testMultiException(Xception)', test_Exceptions); try i := client.testMultiException( 'Xception', 'second test'); Expect( FALSE, 'testMultiException(''Xception''): must trow an exception'); except on x:TXception do begin Expect( x.__isset_ErrorCode, 'x.__isset_ErrorCode = '+BoolToString(x.__isset_ErrorCode)); Expect( x.__isset_Message, 'x.__isset_Message = '+BoolToString(x.__isset_Message)); Expect( x.ErrorCode = 1001, 'x.ErrorCode = '+IntToStr(x.ErrorCode)); Expect( x.Message_ = 'This is an Xception', 'x.Message = "'+x.Message_+'"'); end; on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); end; StartTestGroup( 'testMultiException(Xception2)', test_Exceptions); try i := client.testMultiException( 'Xception2', 'third test'); Expect( FALSE, 'testMultiException(''Xception2''): must trow an exception'); except on x:TXception2 do begin Expect( x.__isset_ErrorCode, 'x.__isset_ErrorCode = '+BoolToString(x.__isset_ErrorCode)); Expect( x.__isset_Struct_thing, 'x.__isset_Struct_thing = '+BoolToString(x.__isset_Struct_thing)); Expect( x.ErrorCode = 2002, 'x.ErrorCode = '+IntToStr(x.ErrorCode)); Expect( x.Struct_thing.String_thing = 'This is an Xception2', 'x.Struct_thing.String_thing = "'+x.Struct_thing.String_thing+'"'); Expect( x.Struct_thing.__isset_String_thing, 'x.Struct_thing.__isset_String_thing = '+BoolToString(x.Struct_thing.__isset_String_thing)); { this is not necessarily true, these fields are default-serialized Expect( not x.Struct_thing.__isset_Byte_thing, 'x.Struct_thing.__isset_Byte_thing = '+BoolToString(x.Struct_thing.__isset_Byte_thing)); Expect( not x.Struct_thing.__isset_I32_thing, 'x.Struct_thing.__isset_I32_thing = '+BoolToString(x.Struct_thing.__isset_I32_thing)); Expect( not x.Struct_thing.__isset_I64_thing, 'x.Struct_thing.__isset_I64_thing = '+BoolToString(x.Struct_thing.__isset_I64_thing)); } end; on e:Exception do Expect( FALSE, 'Unexpected exception "'+e.ClassName+'": '+e.Message); end; // oneway functions StartTestGroup( 'Test Oneway(1)', test_Unknown); client.testOneway(1); Expect( TRUE, 'Test Oneway(1)'); // success := no exception // call time {$IFDEF PerfTest} StartTestGroup( 'Test Calltime()'); StartTick := GetTickCount; for k := 0 to 1000 - 1 do begin client.testVoid(); end; Console.WriteLine(' = ' + FloatToStr( (GetTickCount - StartTick) / 1000 ) + ' ms a testVoid() call' ); {$ENDIF PerfTest} // no more tests here StartTestGroup( '', test_Unknown); end; {$IFDEF SupportsAsync} procedure TClientThread.ClientAsyncTest; var client : TThriftTest.IAsync; s : string; i8 : ShortInt; begin StartTestGroup( 'Async Tests', test_Unknown); client := TThriftTest.TClient.Create( FProtocol); FTransport.Open; // oneway void functions client.testOnewayAsync(1).Wait; Expect( TRUE, 'Test Oneway(1)'); // success := no exception // normal functions s := client.testStringAsync(HUGE_TEST_STRING).Value; Expect( length(s) = length(HUGE_TEST_STRING), 'testString( length(HUGE_TEST_STRING) = '+IntToStr(Length(HUGE_TEST_STRING))+') ' +'=> length(result) = '+IntToStr(Length(s))); i8 := client.testByte(1).Value; Expect( i8 = 1, 'testByte(1) = ' + IntToStr( i8 )); end; {$ENDIF} {$IFDEF StressTest} procedure TClientThread.StressTest(const client : TThriftTest.Iface); begin while TRUE do begin try if not FTransport.IsOpen then FTransport.Open; // re-open connection, server has already closed try client.testString('Test'); Write('.'); finally if FTransport.IsOpen then FTransport.Close; end; except on e:Exception do Writeln(#10+e.message); end; end; end; {$ENDIF} function TClientThread.PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes; var i : Integer; begin case aSize of Empty : SetLength( result, 0); Normal : SetLength( result, $100); ByteArrayTest : SetLength( result, SizeOf(TByteArray) + 128); PipeWriteLimit : SetLength( result, 65535 + 128); FifteenMB : SetLength( result, 15 * 1024 * 1024); else raise EArgumentException.Create('aSize'); end; ASSERT( Low(result) = 0); if Length(result) = 0 then Exit; // linear distribution, unless random is requested if not aRandomDist then begin for i := Low(result) to High(result) do begin result[i] := i mod $100; end; Exit; end; // random distribution of all 256 values FillChar( result[0], Length(result) * SizeOf(result[0]), $0); for i := Low(result) to High(result) do begin result[i] := Byte( Random($100)); end; end; {$IFDEF Win64} procedure TClientThread.UseInterlockedExchangeAdd64; var a,b : Int64; begin a := 1; b := 2; Thrift.Utils.InterlockedExchangeAdd64( a,b); Expect( a = 3, 'InterlockedExchangeAdd64'); end; {$ENDIF} procedure TClientThread.JSONProtocolReadWriteTest; // Tests only then read/write procedures of the JSON protocol // All tests succeed, if we can read what we wrote before // Note that passing this test does not imply, that our JSON is really compatible to what // other clients or servers expect as the real JSON. This is beyond the scope of this test. var prot : IProtocol; stm : TStringStream; list : TThriftList; config : IThriftConfiguration; binary, binRead, emptyBinary : TBytes; i,iErr : Integer; const TEST_SHORT = ShortInt( $FE); TEST_SMALL = SmallInt( $FEDC); TEST_LONG = LongInt( $FEDCBA98); TEST_I64 = Int64( $FEDCBA9876543210); TEST_DOUBLE = -1.234e-56; DELTA_DOUBLE = TEST_DOUBLE * 1e-14; TEST_STRING = 'abc-'#$00E4#$00f6#$00fc; // german umlauts (en-us: "funny chars") // Test THRIFT-2336 and THRIFT-3404 with U+1D11E (G Clef symbol) and 'РуÑÑкое Ðазвание'; G_CLEF_AND_CYRILLIC_TEXT = #$1d11e' '#$0420#$0443#$0441#$0441#$043a#$043e#$0435' '#$041d#$0430#$0437#$0432#$0430#$043d#$0438#$0435; G_CLEF_AND_CYRILLIC_JSON = '"\ud834\udd1e \u0420\u0443\u0441\u0441\u043a\u043e\u0435 \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"'; // test both possible solidus encodings SOLIDUS_JSON_DATA = '"one/two\/three"'; SOLIDUS_EXCPECTED = 'one/two/three'; begin stm := TStringStream.Create; try StartTestGroup( 'JsonProtocolTest', test_Unknown); config := TThriftConfigurationImpl.Create; // prepare binary data binary := PrepareBinaryData( FALSE, Normal); SetLength( emptyBinary, 0); // empty binary data block // output setup prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( nil, TThriftStreamAdapterDelphi.Create( stm, FALSE), config)); // write Init( list, TType.String_, 9); prot.WriteListBegin( list); prot.WriteBool( TRUE); prot.WriteBool( FALSE); prot.WriteByte( TEST_SHORT); prot.WriteI16( TEST_SMALL); prot.WriteI32( TEST_LONG); prot.WriteI64( TEST_I64); prot.WriteDouble( TEST_DOUBLE); prot.WriteString( TEST_STRING); prot.WriteBinary( binary); prot.WriteString( ''); // empty string prot.WriteBinary( emptyBinary); // empty binary data block prot.WriteListEnd; // input setup Expect( stm.Position = stm.Size, 'Stream position/length after write'); stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); // read and compare list := prot.ReadListBegin; Expect( list.ElementType = TType.String_, 'list element type'); Expect( list.Count = 9, 'list element count'); Expect( prot.ReadBool, 'WriteBool/ReadBool: TRUE'); Expect( not prot.ReadBool, 'WriteBool/ReadBool: FALSE'); Expect( prot.ReadByte = TEST_SHORT, 'WriteByte/ReadByte'); Expect( prot.ReadI16 = TEST_SMALL, 'WriteI16/ReadI16'); Expect( prot.ReadI32 = TEST_LONG, 'WriteI32/ReadI32'); Expect( prot.ReadI64 = TEST_I64, 'WriteI64/ReadI64'); Expect( abs(prot.ReadDouble-TEST_DOUBLE) < abs(DELTA_DOUBLE), 'WriteDouble/ReadDouble'); Expect( prot.ReadString = TEST_STRING, 'WriteString/ReadString'); binRead := prot.ReadBinary; Expect( Length(prot.ReadString) = 0, 'WriteString/ReadString (empty string)'); Expect( Length(prot.ReadBinary) = 0, 'empty WriteBinary/ReadBinary (empty data block)'); prot.ReadListEnd; // test binary data Expect( Length(binary) = Length(binRead), 'Binary data length check'); iErr := -1; for i := Low(binary) to High(binary) do begin if binary[i] <> binRead[i] then begin iErr := i; Break; end; end; if iErr < 0 then Expect( TRUE, 'Binary data check ('+IntToStr(Length(binary))+' Bytes)') else Expect( FALSE, 'Binary data check at offset '+IntToStr(iErr)); Expect( stm.Position = stm.Size, 'Stream position after read'); // Solidus can be encoded in two ways. Make sure we can read both stm.Position := 0; stm.Size := 0; stm.WriteString(SOLIDUS_JSON_DATA); stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); Expect( prot.ReadString = SOLIDUS_EXCPECTED, 'Solidus encoding'); // Widechars should work too. Do they? // After writing, we ensure that we are able to read it back // We can't assume hex-encoding, since (nearly) any Unicode char is valid JSON stm.Position := 0; stm.Size := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( nil, TThriftStreamAdapterDelphi.Create( stm, FALSE), config)); prot.WriteString( G_CLEF_AND_CYRILLIC_TEXT); stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); Expect( prot.ReadString = G_CLEF_AND_CYRILLIC_TEXT, 'Writing JSON with chars > 8 bit'); // Widechars should work with hex-encoding too. Do they? stm.Position := 0; stm.Size := 0; stm.WriteString( G_CLEF_AND_CYRILLIC_JSON); stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); Expect( prot.ReadString = G_CLEF_AND_CYRILLIC_TEXT, 'Reading JSON with chars > 8 bit'); finally stm.Free; prot := nil; //-> Release StartTestGroup( '', test_Unknown); // no more tests here end; end; procedure TClientThread.StartTestGroup( const aGroup : string; const aTest : TTestGroup); begin FTestGroup := aGroup; FCurrentTest := aTest; Include( FExecuted, aTest); if FTestGroup <> '' then begin Console.WriteLine(''); Console.WriteLine( aGroup+' tests'); Console.WriteLine( StringOfChar('-',60)); end; end; procedure TClientThread.Expect( aTestResult : Boolean; const aTestInfo : string); begin if aTestResult then begin Inc(FSuccesses); Console.WriteLine( aTestInfo+': passed'); end else begin FErrors.Add( FTestGroup+': '+aTestInfo); Include( FFailed, FCurrentTest); Console.WriteLine( aTestInfo+': *** FAILED ***'); // We have a failed test! // -> issue DebugBreak ONLY if a debugger is attached, // -> unhandled DebugBreaks would cause Windows to terminate the app otherwise if IsDebuggerPresent then {$IFDEF CPUX64} DebugBreak {$ELSE} asm int 3 end {$ENDIF}; end; end; procedure TClientThread.ReportResults; var nTotal : Integer; sLine : string; begin // prevent us from stupid DIV/0 errors nTotal := FSuccesses + FErrors.Count; if nTotal = 0 then begin Console.WriteLine('No results logged'); Exit; end; Console.WriteLine(''); Console.WriteLine( StringOfChar('=',60)); Console.WriteLine( IntToStr(nTotal)+' tests performed'); Console.WriteLine( IntToStr(FSuccesses)+' tests succeeded ('+IntToStr(round(100*FSuccesses/nTotal))+'%)'); Console.WriteLine( IntToStr(FErrors.Count)+' tests failed ('+IntToStr(round(100*FErrors.Count/nTotal))+'%)'); Console.WriteLine( StringOfChar('=',60)); if FErrors.Count > 0 then begin Console.WriteLine('FAILED TESTS:'); for sLine in FErrors do Console.WriteLine('- '+sLine); Console.WriteLine( StringOfChar('=',60)); InterlockedIncrement( ExitCode); // return <> 0 on errors end; Console.WriteLine(''); end; function TClientThread.CalculateExitCode : Byte; var test : TTestGroup; begin result := EXITCODE_SUCCESS; for test := Low(TTestGroup) to High(TTestGroup) do begin if (test in FFailed) or not (test in FExecuted) then result := result or MAP_FAILURES_TO_EXITCODE_BITS[test]; end; end; constructor TClientThread.Create( const aSetup : TTestSetup; const aNumIteration, aThreadNo: Integer; const aLogThreadID : Boolean); begin FSetup := aSetup; FThreadNo := aThreadNo; FNumIterations := aNumIteration; FConsole := TThreadConsole.Create( Self, aLogThreadID); FCurrentTest := test_Unknown; // error list: keep correct order, allow for duplicates FErrors := TStringList.Create; FErrors.Sorted := FALSE; FErrors.Duplicates := dupAccept; inherited Create( TRUE); end; destructor TClientThread.Destroy; begin FreeAndNil( FConsole); FreeAndNil( FErrors); inherited; end; procedure TClientThread.Execute; var i : Integer; begin // perform all tests try {$IFDEF Win64} UseInterlockedExchangeAdd64; {$ENDIF} JSONProtocolReadWriteTest; // must be run in the context of the thread InitializeProtocolTransportStack; try for i := 0 to FNumIterations - 1 do begin ClientTest; {$IFDEF SupportsAsync} ClientAsyncTest; {$ENDIF} end; // report the outcome ReportResults; SetReturnValue( CalculateExitCode); finally ShutdownProtocolTransportStack; end; except on e:Exception do Expect( FALSE, 'unexpected exception: "'+e.message+'"'); end; end; function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer; const aConfig : IThriftConfiguration) : IHTTPClient; var sUrl : string; comps : URL_COMPONENTS; dwChars : DWORD; begin ASSERT( FSetup.endpoint in [trns_MsxmlHttp, trns_WinHttp]); if FSetup.useSSL then sUrl := 'https://' else sUrl := 'http://'; sUrl := sUrl + FSetup.host; // add the port number if necessary and at the right place FillChar( comps, SizeOf(comps), 0); comps.dwStructSize := SizeOf(comps); comps.dwSchemeLength := MAXINT; comps.dwHostNameLength := MAXINT; comps.dwUserNameLength := MAXINT; comps.dwPasswordLength := MAXINT; comps.dwUrlPathLength := MAXINT; comps.dwExtraInfoLength := MAXINT; Win32Check( WinHttpCrackUrl( PChar(sUrl), Length(sUrl), 0, comps)); case FSetup.port of 80 : if FSetup.useSSL then comps.nPort := FSetup.port; 443 : if not FSetup.useSSL then comps.nPort := FSetup.port; else if FSetup.port > 0 then comps.nPort := FSetup.port; end; dwChars := Length(sUrl) + 64; SetLength( sUrl, dwChars); Win32Check( WinHttpCreateUrl( comps, 0, @sUrl[1], dwChars)); SetLength( sUrl, dwChars); Console.WriteLine('Target URL: '+sUrl); case FSetup.endpoint of trns_MsxmlHttp : result := TMsxmlHTTPClientImpl.Create( sUrl, aConfig); trns_WinHttp : result := TWinHTTPClientImpl.Create( sUrl, aConfig); else raise Exception.Create(ENDPOINT_TRANSPORTS[FSetup.endpoint]+' unhandled case'); end; result.DnsResolveTimeout := aTimeoutSetting; result.ConnectionTimeout := aTimeoutSetting; result.SendTimeout := aTimeoutSetting; result.ReadTimeout := aTimeoutSetting; end; procedure TClientThread.InitializeProtocolTransportStack; var streamtrans : IStreamTransport; canSSL : Boolean; const DEBUG_TIMEOUT = 30 * 1000; RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT; PIPE_TIMEOUT = RELEASE_TIMEOUT; HTTP_TIMEOUTS = 10 * 1000; begin // needed for HTTP clients as they utilize the MSXML COM components OleCheck( CoInitialize( nil)); canSSL := FALSE; case FSetup.endpoint of trns_Sockets: begin Console.WriteLine('Using sockets ('+FSetup.host+' port '+IntToStr(FSetup.port)+')'); streamtrans := TSocketImpl.Create( FSetup.host, FSetup.port); FTransport := streamtrans; end; trns_MsxmlHttp, trns_WinHttp: begin Console.WriteLine('Using HTTPClient'); FTransport := InitializeHttpTransport( HTTP_TIMEOUTS); canSSL := TRUE; end; trns_EvHttp: begin raise Exception.Create(ENDPOINT_TRANSPORTS[FSetup.endpoint]+' transport not implemented'); end; trns_NamedPipes: begin streamtrans := TNamedPipeTransportClientEndImpl.Create( FSetup.sPipeName, 0, nil, PIPE_TIMEOUT, PIPE_TIMEOUT); FTransport := streamtrans; end; trns_AnonPipes: begin streamtrans := TAnonymousPipeTransportImpl.Create( FSetup.hAnonRead, FSetup.hAnonWrite, FALSE, PIPE_TIMEOUT); FTransport := streamtrans; end; else raise Exception.Create('Unhandled endpoint transport'); end; ASSERT( FTransport <> nil); // layered transports are not really meant to be stacked upon each other if (trns_Framed in FSetup.layered) then begin FTransport := TFramedTransportImpl.Create( FTransport); end else if (trns_Buffered in FSetup.layered) and (streamtrans <> nil) then begin FTransport := TBufferedTransportImpl.Create( streamtrans, 32); // small buffer to test read() end; if FSetup.useSSL and not canSSL then begin raise Exception.Create('SSL/TLS not implemented'); end; // create protocol instance, default to BinaryProtocol FProtocol := PROTOCOL_CLASSES[FSetup.protType].Create(FTransport); ASSERT( (FTransport <> nil) and (FProtocol <> nil)); end; procedure TClientThread.ShutdownProtocolTransportStack; begin try FProtocol := nil; if FTransport <> nil then begin FTransport.Close; FTransport := nil; end; finally CoUninitialize; end; end; { TThreadConsole } constructor TThreadConsole.Create( const aThread: TClientThread; const aLogThreadID : Boolean); begin inherited Create; FThread := AThread; FLogThreadID := aLogThreadID; end; procedure TThreadConsole.Write(const S: string); begin if FLogThreadID then ConsoleHelper.Console.Write( IntToStr(FThread.ThreadNo)+'> '+S) else ConsoleHelper.Console.Write( S); end; procedure TThreadConsole.WriteLine(const S: string); begin if FLogThreadID then ConsoleHelper.Console.WriteLine( IntToStr(FThread.ThreadNo)+'> '+S) else ConsoleHelper.Console.WriteLine( S); end; initialization TTestClient.FNumIterations := 1; TTestClient.FNumThreads := 1; end. thrift-0.19.0/lib/delphi/test/multiplexed/0000777000000000000000000000000014303740367020440 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Test.Common.pas0000644000000000000000000000170414303740367025273 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Multiplex.Test.Common; interface const NAME_BENCHMARKSERVICE = 'BenchmarkService'; NAME_AGGR = 'Aggr'; implementation // nix end. thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Test.Client.dproj0000644000000000000000000001453214303740367025617 0ustar00rootroot00000000000000 {59132A87-6294-4E25-AE9C-7CD17CD4400D} Multiplex.Test.Client.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication Multiplex.Test.Client.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 True 12 thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Test.Server.dproj0000644000000000000000000001472214303740367025650 0ustar00rootroot00000000000000 {42C6ED3D-36E2-47C5-99B2-02BDA574B9E5} Multiplex.Test.Server.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication Multiplex.Test.Server.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 True 12 thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas0000644000000000000000000001216614303740367025262 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Multiplex.Server.Main; {$WARN SYMBOL_PLATFORM OFF} {.$DEFINE RunEndless} // activate to interactively stress-test the server stop routines via Ctrl+C interface uses Windows, SysUtils, Generics.Collections, Thrift.Server, Thrift.Transport, Thrift.Transport.Pipes, Thrift.Protocol, Thrift.Protocol.Multiplex, Thrift.Processor.Multiplex, Thrift.Collections, Thrift.Configuration, Thrift.Utils, Thrift, Benchmark, // in gen-delphi folder Aggr, // in gen-delphi folder Multiplex.Test.Common, ConsoleHelper, Contnrs; type TTestServer = class public type ITestHandler = interface ['{CAE09AAB-80FB-48E9-B3A8-7F9B96F5419A}'] procedure SetServer( const AServer : IServer ); end; protected type TTestHandlerImpl = class( TInterfacedObject, ITestHandler) private FServer : IServer; protected // ITestHandler procedure SetServer( const AServer : IServer ); property Server : IServer read FServer write SetServer; end; TBenchmarkServiceImpl = class( TTestHandlerImpl, TBenchmarkService.Iface) protected // TBenchmarkService.Iface function fibonacci(n: ShortInt): Integer; end; TAggrImpl = class( TTestHandlerImpl, TAggr.Iface) protected FList : IThriftList; // TAggr.Iface procedure addValue(value: Integer); function getValues(): IThriftList; public constructor Create; destructor Destroy; override; end; public class procedure Execute( const args: array of string); end; implementation { TTestServer.TTestHandlerImpl } procedure TTestServer.TTestHandlerImpl.SetServer( const AServer: IServer); begin FServer := AServer; end; { TTestServer.TBenchmarkServiceImpl } function TTestServer.TBenchmarkServiceImpl.fibonacci(n: ShortInt): Integer; var prev, next : Integer; begin prev := 0; result := 1; while n > 0 do begin next := result + prev; prev := result; result := next; Dec(n); end; end; { TTestServer.TAggrImpl } constructor TTestServer.TAggrImpl.Create; begin inherited Create; FList := TThriftListImpl.Create; end; destructor TTestServer.TAggrImpl.Destroy; begin try FreeAndNil( FList); finally inherited Destroy; end; end; procedure TTestServer.TAggrImpl.addValue(value: Integer); begin FList.Add( value); end; function TTestServer.TAggrImpl.getValues(): IThriftList; begin result := FList; end; { TTestServer } class procedure TTestServer.Execute( const args: array of string); var TransportFactory : ITransportFactory; ProtocolFactory : IProtocolFactory; ServerTrans : IServerTransport; benchHandler : TBenchmarkService.Iface; aggrHandler : TAggr.Iface; benchProcessor : IProcessor; aggrProcessor : IProcessor; multiplex : IMultiplexedProcessor; ServerEngine : IServer; config : IThriftConfiguration; begin try config := TThriftConfigurationImpl.Create; // create protocol factory, default to BinaryProtocol ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( TRUE, TRUE); servertrans := TServerSocketImpl.Create( 9090, DEFAULT_THRIFT_TIMEOUT, FALSE, config); TransportFactory := TFramedTransportImpl.TFactory.Create; benchHandler := TBenchmarkServiceImpl.Create; benchProcessor := TBenchmarkService.TProcessorImpl.Create( benchHandler); aggrHandler := TAggrImpl.Create; aggrProcessor := TAggr.TProcessorImpl.Create( aggrHandler); multiplex := TMultiplexedProcessorImpl.Create; multiplex.RegisterProcessor( NAME_BENCHMARKSERVICE, benchProcessor); multiplex.RegisterProcessor( NAME_AGGR, aggrProcessor); ServerEngine := TSimpleServer.Create( multiplex, ServerTrans, TransportFactory, ProtocolFactory); (benchHandler as ITestHandler).SetServer( ServerEngine); (aggrHandler as ITestHandler).SetServer( ServerEngine); Console.WriteLine('Starting the server ...'); ServerEngine.serve(); (benchHandler as ITestHandler).SetServer( nil); (aggrHandler as ITestHandler).SetServer( nil); except on E: Exception do begin Console.Write( E.Message); end; end; Console.WriteLine( 'done.'); end; end. thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr0000644000000000000000000000437414303740367025271 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program Multiplex.Test.Client; {$APPTYPE CONSOLE} uses SysUtils, Multiplex.Client.Main in 'Multiplex.Client.Main.pas', Benchmark in 'gen-delphi\Benchmark.pas', Aggr in 'gen-delphi\Aggr.pas', Thrift in '..\..\src\Thrift.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Transport.Pipes in '..\..\src\Thrift.Transport.Pipes.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.Multiplex in '..\..\src\Thrift.Protocol.Multiplex.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas'; var nParamCount : Integer; args : array of string; i : Integer; arg : string; s : string; begin try Writeln( 'Multiplex TestClient '+Thrift.Version); nParamCount := ParamCount; SetLength( args, nParamCount); for i := 1 to nParamCount do begin arg := ParamStr( i ); args[i-1] := arg; end; TTestClient.Execute( args ); Readln; except on E: Exception do begin Writeln(E.ClassName, ': ', E.Message); ExitCode := $FFFF; end; end; end. thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr0000644000000000000000000000456214303740367025320 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program Multiplex.Test.Server; {$APPTYPE CONSOLE} uses SysUtils, Multiplex.Server.Main in 'Multiplex.Server.Main.pas', Benchmark in 'gen-delphi\Benchmark.pas', Aggr in 'gen-delphi\Aggr.pas', ConsoleHelper in '..\ConsoleHelper.pas', Thrift in '..\..\src\Thrift.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Transport.Pipes in '..\..\src\Thrift.Transport.Pipes.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.Multiplex in '..\..\src\Thrift.Protocol.Multiplex.pas', Thrift.Processor.Multiplex in '..\..\src\Thrift.Processor.Multiplex.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas'; var nParamCount : Integer; args : array of string; i : Integer; arg : string; s : string; begin try Writeln( 'Multiplex TestServer '+Thrift.Version); nParamCount := ParamCount; SetLength( args, nParamCount); for i := 1 to nParamCount do begin arg := ParamStr( i ); args[i-1] := arg; end; TTestServer.Execute( args ); Writeln('Press ENTER to close ... '); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. thrift-0.19.0/lib/delphi/test/multiplexed/Multiplex.Client.Main.pas0000644000000000000000000000625014303740367025227 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Multiplex.Client.Main; {.$DEFINE StressTest} // activate to stress-test the server with frequent connects/disconnects {.$DEFINE PerfTest} // activate to activate the performance test interface uses Windows, SysUtils, Classes, DateUtils, Generics.Collections, Thrift, Thrift.Protocol, Thrift.Protocol.Multiplex, Thrift.Transport.Pipes, Thrift.Transport, Thrift.Stream, Thrift.Collections, Thrift.Configuration, Benchmark, Aggr, Multiplex.Test.Common; type TTestClient = class protected FProtocol : IProtocol; procedure ParseArgs( const args: array of string); procedure Setup; procedure Run; public constructor Create( const args: array of string); class procedure Execute( const args: array of string); end; implementation type IServiceClient = interface ['{7745C1C2-AB20-43BA-B6F0-08BF92DE0BAC}'] procedure Test; end; //--- TTestClient ------------------------------------- class procedure TTestClient.Execute( const args: array of string); var client : TTestClient; begin client := TTestClient.Create(args); try client.Run; finally client.Free; end; end; constructor TTestClient.Create( const args: array of string); begin inherited Create; ParseArgs(args); Setup; end; procedure TTestClient.ParseArgs( const args: array of string); begin if Length(args) <> 0 then raise Exception.Create('No args accepted so far'); end; procedure TTestClient.Setup; var trans : ITransport; config : IThriftConfiguration; begin config := TThriftConfigurationImpl.Create; trans := TSocketImpl.Create( 'localhost', 9090, DEFAULT_THRIFT_TIMEOUT, config); trans := TFramedTransportImpl.Create( trans); trans.Open; FProtocol := TBinaryProtocolImpl.Create( trans, TRUE, TRUE); end; procedure TTestClient.Run; var bench : TBenchmarkService.Iface; aggr : TAggr.Iface; multiplex : IProtocol; i : Integer; begin try multiplex := TMultiplexedProtocol.Create( FProtocol, NAME_BENCHMARKSERVICE); bench := TBenchmarkService.TClient.Create( multiplex); multiplex := TMultiplexedProtocol.Create( FProtocol, NAME_AGGR); aggr := TAggr.TClient.Create( multiplex); for i := 1 to 10 do aggr.addValue( bench.fibonacci(i)); for i in aggr.getValues do Write(IntToStr(i)+' '); WriteLn; except on e:Exception do Writeln(#10+e.Message); end; end; end. thrift-0.19.0/lib/delphi/test/server.dproj0000644000000000000000000001341014370300523020433 0ustar00rootroot00000000000000 {07CEDA3D-0963-40FE-B3C2-0ED4E24DE067} server.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false bin\$(Config)\$(Platform) DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication server.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 --protocol=compact True 12 thrift-0.19.0/lib/delphi/test/maketest.sh0000777000000000000000000000155514062750226020263 0ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # ../../../compiler/cpp/thrift --gen delphi -o . ../../../test/ThriftTest.thrift thrift-0.19.0/lib/delphi/test/TestServerEvents.pas0000644000000000000000000001015114303740367022076 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit TestServerEvents; interface uses SysUtils, Thrift, Thrift.Protocol, Thrift.Transport, Thrift.Server, ConsoleHelper; type TRequestEventsImpl = class( TInterfacedObject, IRequestEvents) protected FStart : TDateTime; // IRequestProcessingEvents procedure PreRead; procedure PostRead; procedure PreWrite; procedure PostWrite; procedure OnewayComplete; procedure UnhandledError( const e : Exception); procedure CleanupContext; public constructor Create; end; TProcessorEventsImpl = class( TInterfacedObject, IProcessorEvents) protected FReqs : Integer; // IProcessorEvents procedure Processing( const transport : ITransport); function CreateRequestContext( const aFunctionName : string) : IRequestEvents; procedure CleanupContext; public constructor Create; end; TServerEventsImpl = class( TInterfacedObject, IServerEvents) protected // IServerEvents procedure PreServe; procedure PreAccept; function CreateProcessingContext( const input, output : IProtocol) : IProcessorEvents; end; implementation { TServerEventsImpl } procedure TServerEventsImpl.PreServe; begin Console.WriteLine('ServerEvents: Server starting to serve requests'); end; procedure TServerEventsImpl.PreAccept; begin Console.WriteLine('ServerEvents: Server transport is ready to accept incoming calls'); end; function TServerEventsImpl.CreateProcessingContext(const input, output: IProtocol): IProcessorEvents; begin result := TProcessorEventsImpl.Create; end; { TProcessorEventsImpl } constructor TProcessorEventsImpl.Create; begin inherited Create; FReqs := 0; Console.WriteLine('ProcessorEvents: Client connected, processing begins'); end; procedure TProcessorEventsImpl.Processing(const transport: ITransport); begin Console.WriteLine('ProcessorEvents: Processing of incoming request begins'); end; function TProcessorEventsImpl.CreateRequestContext( const aFunctionName: string): IRequestEvents; begin result := TRequestEventsImpl.Create; Inc( FReqs); end; procedure TProcessorEventsImpl.CleanupContext; begin Console.WriteLine( 'ProcessorEvents: completed after handling '+IntToStr(FReqs)+' requests.'); end; { TRequestEventsImpl } constructor TRequestEventsImpl.Create; begin inherited Create; FStart := Now; Console.WriteLine('RequestEvents: New request'); end; procedure TRequestEventsImpl.PreRead; begin Console.WriteLine('RequestEvents: Reading request message ...'); end; procedure TRequestEventsImpl.PostRead; begin Console.WriteLine('RequestEvents: Reading request message completed'); end; procedure TRequestEventsImpl.PreWrite; begin Console.WriteLine('RequestEvents: Writing response message ...'); end; procedure TRequestEventsImpl.PostWrite; begin Console.WriteLine('RequestEvents: Writing response message completed'); end; procedure TRequestEventsImpl.OnewayComplete; begin Console.WriteLine('RequestEvents: Oneway message processed'); end; procedure TRequestEventsImpl.UnhandledError(const e: Exception); begin Console.WriteLine('RequestEvents: Unhandled exception of type '+e.classname); end; procedure TRequestEventsImpl.CleanupContext; var millis : Double; begin millis := (Now - FStart) * (24*60*60*1000); Console.WriteLine( 'Request processing completed in '+IntToStr(Round(millis))+' ms'); end; end. thrift-0.19.0/lib/delphi/test/skip/0000777000000000000000000000000014370300523017040 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/skip/README.md0000644000000000000000000000054514303740367020331 0ustar00rootroot00000000000000These two projects belong together. Both programs simulate server and client for different versions of the same protocol. The intention of this test is to ensure fully working compatibility features of the Delphi Thrift implementation. The expected test result is, that no errors occur with both programs, regardless in which order they might be started. thrift-0.19.0/lib/delphi/test/skip/skiptest_version1.dproj0000644000000000000000000001422014303740367023601 0ustar00rootroot00000000000000 {894CD87B-337B-49F7-BC7D-2D9F65CE8FE0} skiptest_version1.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication skiptest_version1.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 True 12 thrift-0.19.0/lib/delphi/test/skip/skiptest_version2.dproj0000644000000000000000000001422014303740367023602 0ustar00rootroot00000000000000 {DBB2D6D8-0FC6-4329-8408-28B1452B33AD} skiptest_version2.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication skiptest_version2.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 True 12 thrift-0.19.0/lib/delphi/test/skip/skiptest_version2.dpr0000644000000000000000000001631614370300523023247 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program skiptest_version2; {$APPTYPE CONSOLE} uses Classes, Windows, SysUtils, Skiptest.Two in 'gen-delphi\Skiptest.Two.pas', Thrift in '..\..\src\Thrift.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas'; const REQUEST_EXT = '.request'; RESPONSE_EXT = '.response'; function CreatePing : IPing; var list : IThriftList; set_ : IThriftHashSet; begin result := TPingImpl.Create; result.Version1 := TConstants.SKIPTESTSERVICE_VERSION; result.EnumTest := TPingPongEnum.PingTwo; result.BoolVal := TRUE; result.ByteVal := 2; result.DbVal := 3; result.I16Val := 4; result.I32Val := 5; result.I64Val := 6; result.StrVal := 'seven'; result.StructVal := TPongImpl.Create; result.StructVal.Version1 := -1; result.StructVal.Version2 := -2; result.StructVal.EnumTest := TPingPongEnum.PongTwo; list := TThriftListImpl.Create; list.Add( result.StructVal); list.Add( result.StructVal); set_ := TThriftHashSetImpl.Create; set_.Add( 'one'); set_.Add( 'uno'); set_.Add( 'eins'); set_.Add( 'een'); result.MapVal := TThriftDictionaryImpl< IThriftList, IThriftHashSet>.Create; result.MapVal.Add( list, set_); end; type TDummyServer = class( TInterfacedObject, TSkipTestService.Iface) protected // TSkipTestService.Iface function PingPong(const ping: IPing; const pong: IPong): IPing; end; function TDummyServer.PingPong(const ping: IPing; const pong: IPong): IPing; // TSkipTestService.Iface begin Writeln('- performing request from version '+IntToStr(ping.Version1)+' client'); Writeln( ping.ToString); result := CreatePing; end; function CreateProtocol( protfact : IProtocolFactory; stm : TStream; aForInput : Boolean) : IProtocol; var adapt : IThriftStream; trans : ITransport; begin adapt := TThriftStreamAdapterDelphi.Create( stm, FALSE); if aForInput then trans := TStreamTransportImpl.Create( adapt, nil, TThriftConfigurationImpl.Create) else trans := TStreamTransportImpl.Create( nil, adapt, TThriftConfigurationImpl.Create); result := protfact.GetProtocol( trans); end; procedure CreateRequest( protfact : IProtocolFactory; fname : string); var stm : TFileStream; ping : IPing; proto : IProtocol; client : TSkipTestService.TClient; // we need access to send/recv_pingpong() cliRef : IUnknown; // holds the refcount begin Writeln('- creating new request'); stm := TFileStream.Create( fname+REQUEST_EXT+'.tmp', fmCreate); try ping := CreatePing; // save request data proto := CreateProtocol( protfact, stm, FALSE); client := TSkipTestService.TClient.Create( nil, proto); cliRef := client as IUnknown; client.send_PingPong( ping, ping.StructVal); finally client := nil; // not Free! cliRef := nil; stm.Free; if client = nil then {warning suppressed}; end; DeleteFile( fname+REQUEST_EXT); RenameFile( fname+REQUEST_EXT+'.tmp', fname+REQUEST_EXT); end; procedure ReadResponse( protfact : IProtocolFactory; fname : string); var stm : TFileStream; ping : IPing; proto : IProtocol; client : TSkipTestService.TClient; // we need access to send/recv_pingpong() cliRef : IUnknown; // holds the refcount begin Writeln('- reading response'); stm := TFileStream.Create( fname+RESPONSE_EXT, fmOpenRead); try // load request data proto := CreateProtocol( protfact, stm, TRUE); client := TSkipTestService.TClient.Create( proto, nil); cliRef := client as IUnknown; ping := client.recv_PingPong; finally client := nil; // not Free! cliRef := nil; stm.Free; if client = nil then {warning suppressed}; end; end; procedure ProcessFile( protfact : IProtocolFactory; fname : string); var stmIn, stmOut : TFileStream; protIn, protOut : IProtocol; server : IProcessor; begin Writeln('- processing request'); stmOut := nil; stmIn := TFileStream.Create( fname+REQUEST_EXT, fmOpenRead); try stmOut := TFileStream.Create( fname+RESPONSE_EXT+'.tmp', fmCreate); // process request and write response data protIn := CreateProtocol( protfact, stmIn, TRUE); protOut := CreateProtocol( protfact, stmOut, FALSE); server := TSkipTestService.TProcessorImpl.Create( TDummyServer.Create); server.Process( protIn, protOut); finally server := nil; // not Free! stmIn.Free; stmOut.Free; if server = nil then {warning suppressed}; end; DeleteFile( fname+RESPONSE_EXT); RenameFile( fname+RESPONSE_EXT+'.tmp', fname+RESPONSE_EXT); end; procedure Test( protfact : IProtocolFactory; fname : string); begin // try to read an existing request Writeln; Writeln('Reading data file '+fname); if FileExists( fname + REQUEST_EXT) then begin ProcessFile( protfact, fname); ReadResponse( protfact, fname); end; // create a new request and try to process Writeln; Writeln('Writing data file '+fname); CreateRequest( protfact, fname); ProcessFile( protfact, fname); ReadResponse( protfact, fname); end; const FILE_BINARY = 'pingpong.bin'; FILE_JSON = 'pingpong.json'; FILE_COMPACT = 'pingpong.compact'; begin try Writeln( 'Delphi SkipTest '+IntToStr(TConstants.SKIPTESTSERVICE_VERSION)+' using '+Thrift.Version); Writeln; Writeln('Binary protocol'); Test( TBinaryProtocolImpl.TFactory.Create, FILE_BINARY); Writeln; Writeln('JSON protocol'); Test( TJSONProtocolImpl.TFactory.Create, FILE_JSON); Writeln; Writeln('Compact protocol'); Test( TCompactProtocolImpl.TFactory.Create, FILE_COMPACT); Writeln; Writeln('Test completed without errors.'); Writeln; Write('Press ENTER to close ...'); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. thrift-0.19.0/lib/delphi/test/skip/skiptest_version1.dpr0000644000000000000000000001457214303740367023262 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program skiptest_version1; {$APPTYPE CONSOLE} uses Classes, Windows, SysUtils, Skiptest.One in 'gen-delphi\Skiptest.One.pas', Thrift in '..\..\src\Thrift.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas'; const REQUEST_EXT = '.request'; RESPONSE_EXT = '.response'; function CreatePing : IPing; begin result := TPingImpl.Create; result.Version1 := TConstants.SKIPTESTSERVICE_VERSION; result.EnumTest := TPingPongEnum.PingOne; end; type TDummyServer = class( TInterfacedObject, TSkipTestService.Iface) protected // TSkipTestService.Iface function PingPong(const ping: IPing): IPing; end; function TDummyServer.PingPong(const ping: IPing): IPing; // TSkipTestService.Iface begin Writeln('- performing request from version '+IntToStr(ping.Version1)+' client'); Writeln( ping.ToString); result := CreatePing; end; function CreateProtocol( protfact : IProtocolFactory; stm : TStream; aForInput : Boolean) : IProtocol; var adapt : IThriftStream; trans : ITransport; begin adapt := TThriftStreamAdapterDelphi.Create( stm, FALSE); if aForInput then trans := TStreamTransportImpl.Create( adapt, nil, TThriftConfigurationImpl.Create) else trans := TStreamTransportImpl.Create( nil, adapt, TThriftConfigurationImpl.Create); result := protfact.GetProtocol( trans); end; procedure CreateRequest( protfact : IProtocolFactory; fname : string); var stm : TFileStream; ping : IPing; proto : IProtocol; client : TSkipTestService.TClient; // we need access to send/recv_pingpong() cliRef : IUnknown; // holds the refcount begin Writeln('- creating new request'); stm := TFileStream.Create( fname+REQUEST_EXT+'.tmp', fmCreate); try ping := CreatePing; // save request data proto := CreateProtocol( protfact, stm, FALSE); client := TSkipTestService.TClient.Create( nil, proto); cliRef := client as IUnknown; client.send_PingPong( ping); finally client := nil; // not Free! cliRef := nil; stm.Free; if client = nil then {warning suppressed}; end; DeleteFile( fname+REQUEST_EXT); RenameFile( fname+REQUEST_EXT+'.tmp', fname+REQUEST_EXT); end; procedure ReadResponse( protfact : IProtocolFactory; fname : string); var stm : TFileStream; ping : IPing; proto : IProtocol; client : TSkipTestService.TClient; // we need access to send/recv_pingpong() cliRef : IUnknown; // holds the refcount begin Writeln('- reading response'); stm := TFileStream.Create( fname+RESPONSE_EXT, fmOpenRead); try // load request data proto := CreateProtocol( protfact, stm, TRUE); client := TSkipTestService.TClient.Create( proto, nil); cliRef := client as IUnknown; ping := client.recv_PingPong; finally client := nil; // not Free! cliRef := nil; stm.Free; if client = nil then {warning suppressed}; end; end; procedure ProcessFile( protfact : IProtocolFactory; fname : string); var stmIn, stmOut : TFileStream; protIn, protOut : IProtocol; server : IProcessor; begin Writeln('- processing request'); stmOut := nil; stmIn := TFileStream.Create( fname+REQUEST_EXT, fmOpenRead); try stmOut := TFileStream.Create( fname+RESPONSE_EXT+'.tmp', fmCreate); // process request and write response data protIn := CreateProtocol( protfact, stmIn, TRUE); protOut := CreateProtocol( protfact, stmOut, FALSE); server := TSkipTestService.TProcessorImpl.Create( TDummyServer.Create); server.Process( protIn, protOut); finally server := nil; // not Free! stmIn.Free; stmOut.Free; if server = nil then {warning suppressed}; end; DeleteFile( fname+RESPONSE_EXT); RenameFile( fname+RESPONSE_EXT+'.tmp', fname+RESPONSE_EXT); end; procedure Test( protfact : IProtocolFactory; fname : string); begin // try to read an existing request Writeln('Reading data file '+fname); if FileExists( fname + REQUEST_EXT) then begin ProcessFile( protfact, fname); ReadResponse( protfact, fname); end; // create a new request and try to process Writeln('Writing data file '+fname); CreateRequest( protfact, fname); ProcessFile( protfact, fname); ReadResponse( protfact, fname); end; const FILE_BINARY = 'pingpong.bin'; FILE_JSON = 'pingpong.json'; FILE_COMPACT = 'pingpong.compact'; begin try Writeln( 'Delphi SkipTest '+IntToStr(TConstants.SKIPTESTSERVICE_VERSION)+' using '+Thrift.Version); Writeln; Writeln('Binary protocol'); Test( TBinaryProtocolImpl.TFactory.Create, FILE_BINARY); Writeln; Writeln('JSON protocol'); Test( TJSONProtocolImpl.TFactory.Create, FILE_JSON); Writeln; Writeln('Compact protocol'); Test( TCompactProtocolImpl.TFactory.Create, FILE_COMPACT); Writeln; Writeln('Test completed without errors.'); Writeln; Write('Press ENTER to close ...'); Readln; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. thrift-0.19.0/lib/delphi/test/skip/idl/0000777000000000000000000000000014303740367017622 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/skip/idl/skiptest_version_2.thrift0000644000000000000000000000367414303740367024706 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // version 2 of the interface namespace * Skiptest.Two const i32 SKIPTESTSERVICE_VERSION = 2 enum PingPongEnum { PingOne = 0, PongOne = 1, PingTwo = 2, PongTwo = 3, } struct Pong { 1 : optional i32 version1 2 : optional i16 version2 100 : PingPongEnum EnumTest } struct Ping { 1 : optional i32 version1 10 : optional bool boolVal 11 : optional byte byteVal 12 : optional double dbVal 13 : optional i16 i16Val 14 : optional i32 i32Val 15 : optional i64 i64Val 16 : optional string strVal 17 : optional Pong structVal 18 : optional map< list< Pong>, set< string>> mapVal 100 : PingPongEnum EnumTest } exception PingFailed { 1 : optional i32 pingErrorCode } exception PongFailed { 222 : optional i32 pongErrorCode 10 : optional bool boolVal 11 : optional byte byteVal 12 : optional double dbVal 13 : optional i16 i16Val 14 : optional i32 i32Val 15 : optional i64 i64Val 16 : optional string strVal 17 : optional Pong structVal 18 : optional map< list< Pong>, set< string>> mapVal } service SkipTestService { Ping PingPong( 1: Ping ping, 3: Pong pong) throws (1: PingFailed pif, 444: PongFailed pof); } // EOF thrift-0.19.0/lib/delphi/test/skip/idl/skiptest_version_1.thrift0000644000000000000000000000224314303740367024674 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // version 1 of the interface namespace * Skiptest.One const i32 SKIPTESTSERVICE_VERSION = 1 enum PingPongEnum { PingOne = 0, PongOne = 1, } struct Ping { 1 : optional i32 version1 100 : PingPongEnum EnumTest } exception PongFailed { 222 : optional i32 pongErrorCode } service SkipTestService { Ping PingPong( 1: Ping ping) throws (444: PongFailed pof); } // EOFthrift-0.19.0/lib/delphi/test/keywords/0000777000000000000000000000000014303740367017753 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/keywords/ReservedKeywords.thrift0000644000000000000000000000570014303740367024502 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // make sure generated code does not produce name collisions with predefined keywords namespace delphi System include "ReservedIncluded.thrift" typedef i32 Cardinal typedef string message typedef list< map< Cardinal, message>> program struct unit { 1: Cardinal downto; 2: program procedure; } typedef set< unit> units exception exception1 { 1: program message; 2: unit array; } service constructor { unit Create(1: Cardinal asm; 2: message inherited) throws (1: exception1 label); units Destroy(); } const Cardinal downto = +1 const Cardinal published = -1 enum keywords { record = 1, repeat = 2, deprecated = 3 } struct Struct_lists { 1: list init; 2: list struc; 3: list field; 4: list field_; 5: list tracker; 6: list Self; } struct Struct_structs { 1: Struct_simple init; 2: Struct_simple struc; 3: Struct_simple field; 4: Struct_simple field_; 5: Struct_simple tracker; 6: Struct_simple Self; } struct Struct_simple { 1: bool init; 2: bool struc; 3: bool field; 4: bool field_; 5: bool tracker; 6: bool Self; } struct Struct_strings { 1: string init; 2: string struc; 3: string field; 4: string field_; 5: string tracker; 6: string Self; } struct Struct_binary { 1: binary init; 2: binary struc; 3: binary field; 4: binary field_; 5: binary tracker; 6: binary Self; } typedef i32 IProtocol typedef i32 ITransport typedef i32 IFace typedef i32 IAsync typedef i32 System typedef i32 SysUtils typedef i32 Generics typedef i32 Thrift struct Struct_Thrift_Names { 1: IProtocol IProtocol 2: ITransport ITransport 3: IFace IFace 4: IAsync IAsync 5: System System 6: SysUtils SysUtils 7: Generics Generics 8: Thrift Thrift } enum Thrift4554_Enum { Foo = 0, Bar = 1, Baz = 2, } struct Thrift4554_Struct { 1 : optional double MinValue 2 : optional double MaxValue 3 : optional bool Integer // causes issue 4 : optional Thrift4554_Enum Foo } service deprecate_included_outer extends ReservedIncluded.deprecate_included_inner { void FooBarBaz() } // EOF thrift-0.19.0/lib/delphi/test/keywords/ReservedKeywords.dproj0000644000000000000000000001257014303740367024323 0ustar00rootroot00000000000000 {F2E9B6FC-A931-4271-8E30-5A4E402481B4} ReservedKeywords.dpr 12.3 True Debug Win32 Console None DCC32 true true Base true true Base true bin\$(Config)\$(Platform) dcu\$(Project)\$(Config)\$(Platform) 00400000 gen-delphi;..\..\src;$(DCC_UnitSearchPath) WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias) false false false false false DEBUG;$(DCC_Define) false true false RELEASE;$(DCC_Define) 0 false MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 ReservedKeywords.dpr True 12 thrift-0.19.0/lib/delphi/test/keywords/ReservedIncluded.thrift0000644000000000000000000000237514303740367024427 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // make sure generated code does not produce name collisions with predefined keywords namespace delphi SysUtils const i32 integer = 42 service deprecate_included_inner { void Foo( ) ( deprecated = "This method has neither 'x' nor \"y\"" ) void Bar( ) ( deprecated = "Fails to deliver 中文 колбаÑа" ) void Baz( ) ( deprecated = "Need this to work with tabs (\t) or Umlauts (äöüÄÖÜß) too" ) void Deprecated() ( deprecated ) // no comment } // EOF thrift-0.19.0/lib/delphi/test/keywords/ReservedKeywords.dpr0000644000000000000000000000036714303740367023773 0ustar00rootroot00000000000000program ReservedKeywords; {$APPTYPE CONSOLE} uses SysUtils, System_, AnnotationTest; begin try { TODO -oUser -cConsole Main : Code hier einfügen } except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. thrift-0.19.0/lib/delphi/test/typeregistry/0000777000000000000000000000000014303740367020656 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/typeregistry/TestTypeRegistry.dpr0000644000000000000000000000372514303740367024702 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program TestTypeRegistry; {$APPTYPE CONSOLE} uses Classes, Windows, SysUtils, Generics.Collections, TypInfo, Thrift in '..\..\src\Thrift.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Test in 'gen-delphi\Thrift.Test.pas', DebugProtoTest in 'gen-delphi\DebugProtoTest.pas', Test.TypeRegistry, Test.EnumToString; begin try Test.TypeRegistry.RunTest; Test.EnumToString.RunTest; Writeln('Completed.'); except on e:Exception do Writeln(e.ClassName,': ',e.Message); end; end. thrift-0.19.0/lib/delphi/test/typeregistry/Test.EnumToString.pas0000644000000000000000000000506014303740367024674 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Test.EnumToString; interface uses Classes, SysUtils, Thrift.Utils, DebugProtoTest; procedure RunTest; implementation {$SCOPEDENUMS ON} type TIrregularEnum = ( // has gaps and/or does not start at zero FiveHundretOne = 501, FiveHundretTwo = 502, FiveHundretFive = 505 ); TRegularEnum = ( // starts at zero, no gaps, no duplicates One, Two, Three ); procedure IrregularEnumToString; // TIrregularEnum does not run from 0 to N, so we don't have RTTI for it // Search for "E2134: Type has no typeinfo" message to get the details // Unfortunately, this also means that StringUtils.ToString() does not work for enums w/o RTTI var value : Integer; sA,sB : string; begin for value := Pred(Ord(Low(TIrregularEnum))) to Succ(Ord(High(TIrregularEnum))) do begin sA := EnumUtils.ToString(Ord(value)); // much more reliable sB := StringUtils.ToString(TIrregularEnum(value)); // does not really work WriteLn( '- TIrregularEnum('+IntToStr(value)+'): EnumUtils => ',sA,', StringUtils => ', sB); end; end; procedure RegularEnumToString; // Regular enums have RTTI and work like a charm var value : Integer; sA,sB : string; begin for value := Pred(Ord(Low(TRegularEnum))) to Succ(Ord(High(TRegularEnum))) do begin sA := EnumUtils.ToString(Ord(value)); sB := StringUtils.ToString(TRegularEnum(value)); if sA = sB // both are expected to work with regular enums then WriteLn( '- TRegularEnum('+IntToStr(value)+'): ',sA,' = ', sB) else raise Exception.Create( 'Test failed: '+sA+' <> '+sB); end; end; procedure RunTest; begin Writeln('Testing enum utils ...'); RegularEnumToString; IrregularEnumToString; Writeln; end; end. thrift-0.19.0/lib/delphi/test/typeregistry/TestTypeRegistry.dproj0000644000000000000000000001444514303740367025234 0ustar00rootroot00000000000000 {D6B3910D-CD64-449F-B7A6-404D5DF1DAC5} TestTypeRegistry.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication TestTypeRegistry.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 True 12 thrift-0.19.0/lib/delphi/test/typeregistry/Test.TypeRegistry.pas0000644000000000000000000000425314303740367024753 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit Test.TypeRegistry; interface uses Classes, SysUtils, TypInfo, Thrift, Thrift.TypeRegistry, DebugProtoTest; procedure RunTest; implementation type Tester = class public class procedure Test; end; class procedure Tester.Test; var instance : T; name : string; begin instance := TypeRegistry.Construct; name := GetTypeName(TypeInfo(T)); if instance <> nil then Writeln( name, ' = ok') else begin Writeln( name, ' = failed'); raise Exception.Create( 'Test with '+name+' failed!'); end; end; procedure RunTest; begin Writeln('Testing type registry ...'); Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Tester.Test; Writeln; end; end. thrift-0.19.0/lib/delphi/test/ConsoleHelper.pas0000644000000000000000000000652514370300523021345 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit ConsoleHelper; interface uses Classes, SysUtils, SyncObjs; type TThriftConsole = class strict private FLock : TCriticalSection; strict protected procedure Lock; procedure UnLock; public constructor Create; destructor Destroy; override; procedure Write( const S: string); virtual; procedure WriteLine( const S: string); virtual; end; TGUIConsole = class( TThriftConsole ) strict private FLineBreak : Boolean; FMemo : TStrings; procedure InternalWrite( const S: string; bWriteLine: Boolean); public constructor Create( AMemo: TStrings); procedure Write( const S: string); override; procedure WriteLine( const S: string); override; end; function Console: TThriftConsole; procedure ChangeConsole( AConsole: TThriftConsole ); procedure RestoreConsoleToDefault; implementation var FDefaultConsole : TThriftConsole; FConsole : TThriftConsole; function Console: TThriftConsole; begin Result := FConsole; end; { TThriftConsole } constructor TThriftConsole.Create; begin inherited Create; FLock := TCriticalSection.Create; end; destructor TThriftConsole.Destroy; begin FreeAndNil( FLock); inherited Destroy; end; procedure TThriftConsole.Lock; begin FLock.Enter; end; procedure TThriftConsole.UnLock; begin FLock.Leave; end; procedure TThriftConsole.Write(const S: string); begin Lock; try System.Write( S ); finally Unlock; end; end; procedure TThriftConsole.WriteLine(const S: string); begin Lock; try System.Writeln( S ); finally Unlock; end; end; procedure ChangeConsole( AConsole: TThriftConsole ); begin FConsole := AConsole; end; procedure RestoreConsoleToDefault; begin FConsole := FDefaultConsole; end; { TGUIConsole } constructor TGUIConsole.Create( AMemo: TStrings); begin inherited Create; FMemo := AMemo; FLineBreak := True; end; procedure TGUIConsole.InternalWrite(const S: string; bWriteLine: Boolean); var idx : Integer; begin Lock; try if FLineBreak then begin FMemo.Add( S ) end else begin idx := FMemo.Count - 1; if idx < 0 then FMemo.Add( S ) else FMemo[idx] := FMemo[idx] + S; end; FLineBreak := bWriteLine; finally Unlock; end; end; procedure TGUIConsole.Write(const S: string); begin InternalWrite( S, False); end; procedure TGUIConsole.WriteLine(const S: string); begin InternalWrite( S, True); end; initialization FDefaultConsole := TThriftConsole.Create; FConsole := FDefaultConsole; finalization FDefaultConsole.Free; FDefaultConsole := nil; end. thrift-0.19.0/lib/delphi/test/client.dpr0000644000000000000000000000503614303740367020071 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program client; {$APPTYPE CONSOLE} uses SysUtils, DataFactory in 'Performance\DataFactory.pas', PerfTests in 'Performance\PerfTests.pas', TestClient in 'TestClient.pas', Thrift.Test in 'gen-delphi\Thrift.Test.pas', Thrift in '..\src\Thrift.pas', Thrift.Transport in '..\src\Thrift.Transport.pas', Thrift.Socket in '..\src\Thrift.Socket.pas', Thrift.Configuration in '..\src\Thrift.Configuration.pas', Thrift.Exception in '..\src\Thrift.Exception.pas', Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas', Thrift.Transport.WinHTTP in '..\src\Thrift.Transport.WinHTTP.pas', Thrift.Transport.MsxmlHTTP in '..\src\Thrift.Transport.MsxmlHTTP.pas', Thrift.Protocol in '..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\src\Thrift.Protocol.Compact.pas', Thrift.Protocol.Multiplex in '..\src\Thrift.Protocol.Multiplex.pas', Thrift.Collections in '..\src\Thrift.Collections.pas', Thrift.Server in '..\src\Thrift.Server.pas', Thrift.Stream in '..\src\Thrift.Stream.pas', Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas', Thrift.WinHTTP in '..\src\Thrift.WinHTTP.pas', Thrift.Utils in '..\src\Thrift.Utils.pas'; var nParamCount : Integer; args : array of string; i : Integer; arg : string; begin try Writeln( 'Delphi TestClient '+Thrift.Version); nParamCount := ParamCount; SetLength( args, nParamCount); for i := 1 to nParamCount do begin arg := ParamStr( i ); args[i-1] := arg; end; ExitCode := TTestClient.Execute( args); except on E: EAbort do begin ExitCode := $FF; end; on E: Exception do begin Writeln(E.ClassName, ': ', E.Message); ExitCode := $FF; end; end; end. thrift-0.19.0/lib/delphi/test/serializer/0000777000000000000000000000000014370300523020243 5ustar00rootroot00000000000000thrift-0.19.0/lib/delphi/test/serializer/SerializerData.dpr0000644000000000000000000000500614370300523023652 0ustar00rootroot00000000000000library SerializerData; (* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) uses Classes, Windows, SysUtils, Generics.Collections, Thrift in '..\..\src\Thrift.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', System_ in 'gen-delphi\System_.pas', SysUtils_ in 'gen-delphi\SysUtils_.pas', DebugProtoTest in 'gen-delphi\DebugProtoTest.pas', TestSerializer.Data in 'TestSerializer.Data.pas'; {$R *.res} function CreateOneOfEach : IOneOfEach; stdcall; begin result := Fixtures.CreateOneOfEach; end; function CreateNesting : INesting; stdcall; begin result := Fixtures.CreateNesting; end; function CreateHolyMoley : IHolyMoley; stdcall; begin result := Fixtures.CreateHolyMoley; end; function CreateCompactProtoTestStruct : ICompactProtoTestStruct; stdcall; begin result := Fixtures.CreateCompactProtoTestStruct; end; exports CreateOneOfEach, CreateNesting, CreateHolyMoley, CreateCompactProtoTestStruct; begin IsMultiThread := TRUE; ASSERT( cDebugProtoTest_Option_COM_types); ASSERT( cSystem__Option_COM_types); end. thrift-0.19.0/lib/delphi/test/serializer/SerializerData.dproj0000644000000000000000000001457314370300523024214 0ustar00rootroot00000000000000 {B523D1D7-2C9A-4B39-A6CF-69EF536D5079} SerializerData.dpr 12.3 True Debug Win32 Library None DCC32 true true Base true true Base true .\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;$(DCC_UnitAlias) bin\$(Config)\$(Platform) false true false false false DEBUG;$(DCC_Define) false true false RELEASE;$(DCC_Define) 0 false MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 SerializerData.dpr True 12 thrift-0.19.0/lib/delphi/test/serializer/SerializerData.res0000644000000000000000000026231014370300523023661 0ustar00rootroot00000000000000 ÿÿÿÿL ÿÿÿÿ‰PNG  IHDR\r¨fÿÿIDATxÚ콜eWq'\7¼;çîé鞥QJH€%Ç58`ƒ×ì·`/Æ?{ƒðÚüc/ø³ùð:/¶/6&JBÅ43šœSOçðúåxïùªêœsßëIÝ#FšOÝóú…N¥ý«Ê€«ëŠ\ùå>ôÓo¿þ ³™2LNMA¾T0l˜MÍÃøô Ø–\a€eûalbfç2ø» Âtùý†kžó™®áà Õ*´4%¡»³œZ™þ®SƒîŽ6hN&Àuk‰¡»¥šã!øú#Û>ü_é¾?¿Ü×äêzù˸ÜpuN¦>ÓÝžÜràØhöÈé1˜Ïäa>]Äçg`z6ç4%#k{:ZÖU ¥ L¢ìšP®T _.á' €  Ó†R© ¥JU='ðÿ¨P9Ý~¹>o(€*?„ð!Àá÷ C@8€ Ÿs˜¶É÷ÛŒLÍ웘™ÛßZ+—AS"­ÑlY¿²uÏÑÑzÛ­kÿúr_Ï«ëüëªx¬ï=ñÂ[ׯê¿}ÇþS™#GÇad|ʽñšU¿E:¦ææa6“"ZøB¾ ™\ Å TkT]—…ÙdY'Á6Ø‚[> ÕÆ']0H°ñ9òØð[zB}³áý—ž2L´þp¤U) Âjµ5|üNÒôyþnâçùða¡‚ú}ÐÒÜ„ŠÂ‘ º:Z`b6³kÇÞcßšŒÚ]mM°z¨®_»,¾ûÐé'ï½ëºÇ.÷µ³¯« à5\ŽžYµry÷Šm;…Cg¦atbÚ¹}˪ô´ßwldª86ž‚ÙtÚ-–+Ç!ç¤Fyô¡ÐhM“¬7ð_LFBÛ”] 6ø|Ba$KŽ’Ì7ÙB…`ãó´Üìæ³àWðåO`A/WpúfäËȳ¨B)|aÍqù3R@ôNõ;)!ú ö.èiTA¶eæ"¿Ý”ŒBog ÷v„NNï/ø“î6k°·V´Â­×­í>:zdÓÊÞC—û^½YÖUð*®Ïþï¯ûßuß½{žt^ÚʽûÖõÿ½¿»õ§v85üÌ$œœ˜ƒ¹ùLÅïó Ù¶© €ÕPêQÄ T® UGÁ&ËMVÝ‹GÑ‚£€ûÑ’û-f­nÅ7ò³å'q7ñõ&[~eéIŠMzÞæ²À+Ï@xÊ€<Ò8$ä(·ü~Á^„Å^ýNc¾PdåSÀ£VP®Õ P&ÏD@®gÅA¯Ä4-ðáqÑ[¨œLÛÀ°Á‡JÂÍW«ÕcmÍ1og v%aóºåÉ£#“ÿñÀÛÿø–ë×™›Vt[_ýö3g~ÿ7ßU¹Ü÷òº®*€K¼¶í9æ/jæÃOﱈ½é§ÞqëýûŸÎ91^Ä?¿­wO¦P‚\±ÅB*hm å „6ZçHÈAŒ­ÃÂÁ0þôC…ÞF!ò+«Ž•­¾‰å³lŽÉý¨H~[w`W]*iÙ0Ôï®CâR=¸j 7MïyÂHDÄaŒâ{Û´~(´a¨+úõïmýd¡T}é­·n$uäÞsÓ†«Ê஫ à¯öx*€ÞGŸÛ5[*®Y½bà×&g2-=ŒO¦|ùRÙ4P€Éª3¨†ßîyÀGÖÜ´î>²î(á ÇÕ>²ÞhíAÇæ,ÇRØH@]ê1¾O¿Ó/ôWxÎ=[zRø¼¿ÇÄc`0œtÃäÏ)—*üSxØ€z/aÒÑ—@¡Éê‚õ ý$EDËTaˆK> )|”«UÆ/Ê(øô H Qy”Q9’ ¯¡X,±‡Aï l·³­©ÚÞÚ- cßÁ“„vÞ~Óú<²3o½aÝ—/÷=~#­« à‡\÷õG»oÚ²êšÇŸ=”;x쌸ýÆÕŸ+WjûŸ®ŒOÍDªŽh"13MŠ×-vƒ}(Ì$üápbaZz?DÑ †P0 ~­Ér,@ÿcaÇÿ{Îa ÊeIÁ¤Ï¦÷™ „… ÄdáU†Ÿ–Ð{R<‘{‚L7Èì‹Ö»/J¥Áƒ`‘¾„À>ú^!5 ¿ÆUŠÇE€Ž„< rùt4 ¥$+ ö,”B"EeS,•!—/C¿·ˆÊ”}½š¼ 1ðôR½íÍù5Ã}~üÎSmÛ÷;[Ö÷ܼ6ºuÇ¡¿ú®»Ç.÷¸’×Uð ÖT*׳çÈióG_LöµþÊÆuƒ¿úü®“åã§Çq³»7:ŽcTªª¸Ñ«û|& y2x$„ÂŽ‚OBˆ‚a“ ÀšÜs ÍWwEÆßRÐy—¼L¿ù1$ÀÏ ‚ضÍàaô9>?y~/µÇnkT ¨@LC¨Ø¤Õ&av¥’0ÊÔ€Áa ¹ò‚€?WžÅü5|¥1žÇ×Tñ5e‚%ù½.‡R‘È4ƒ!ÁHtÓC‹…˜oOÛÒUDŽÄ âÆ›LÚá¾O2á|¶Å¨<‘}@§Õ€ñ>r7ï2ú6 ý‡+|)gr¶A=A@ B8‘I©•Ž$ЩIA &–ÑÊ~ààûlSfN˜ñ„Ta>_€yô 2ù*±óÙ< £Àd#ªAX9ÐE¯ÛÚÓ‘|bÓª‘îŽ/^îËòzXo€ÝõÊ×ÃϾ”¸}Ëú·ÿÛ÷·•ú{[þáÌèló³;ÂÈÔ,„0çc¿-™€Îæ8n(‹‹cØÊÓ¤T (£¼< y@‡¾€Á!_Èg¸ç–M¾ñəϮ_9øÜªå}™ŽÖØéWo—^Þõ†Uÿ÷»Ï„oظâ¿8yfíS/ì_V*9×̤‰RZ†hÈ‚þÎèíh…D8Ñ`lŸŒÓkйWCÁ':*Ř.×¹›º¤N}CãW„-„ž•ÇÏT™6^Ü—ªÆ<¿Am^WÝ™:ëOaìšÆ¹·L†Jå < é‘ÇašŠˆ#ÄËÊ)xü?Å`tb/qá ¯°yœ sŠFî‚‚ø åÙˆ†c6$ \hP®wž Ô€RРp¼‹æQ˜µ²•©BâgøœµTµ¤¥J–ñÂäÍxlfNOÎBºPbêv+zƒ!¿±óöë7œ\Þ×µÿévÿñ{ßuOárìãW{½¡ÀS/2â¡ÿŸ¿ó”qÃúåïÆÝúGGÏLv:6³©$›¢Ð‰|t·7CZw ‘Nå~V*.в‰fÍ­q>ÚÛsK4ž\«h»BJ¸ÄÔ%740¦ÿ%„—¤®<ºÎ¼†f½;Ï€‡j‹É A,/ãÀ¯uL~‘3h8aC65¤ÐsÒò‚/ÍuKlèXßðªé=’%©ÏÏð²%²Q'HÐW°tÖk¨#§e} XÐå ð€¸5<ŽÙtƧç`b.‹Ê ó´%ðj¨ú:[Ç«•âÇöûÊÏÞw›ÈK•;¯[}%£² ÖMtEƒ¡Íÿò§`å@Ç—·8Úrf"-ñ$0ÎoJ„`¸» :Û9]Ç%®†¬’«bH´Ô|NòÔéwªm7 ·ÀÚ,²¼]€çxÉ>ÕÇP¹C¹¥RP$8hzýú¤@h'؃Ĵ­;ü¨_à PÍ;5W?¶%° Eƒ0”ObœG$]©°4“Ñ;mð+£l‚ôv(¬¢k*Swbáguá÷Ü~±PïšÆu°ÒˆÂÐQ‚¬PURí•R»‚y…à Ø¬èÇ&fáÈÈÌ¡'Foqv> ímQ¸fõÀìÈØì{~ö¾Û!W*íB0~©öìå^o(ðضýï ØöŸþû÷·¢VÏ5UǠد…å@;¬èbbÜÓ2>¦tR¥ZÆ8°©T–›Rxˆ½ªr“À’ÚàÆâ—L›ÖÐ$x× ÀŸÚ²/L‘Jx‚¥­¿rà…ª ¯w=«o¨Š<$MT(»Rîn9Ë®[·ðôÞšPaá#®ü)‹}‚ ¯· ¨t§ú,…軪'ô”§cªÂ¡²g‰¸¾&gÿ~ÑãW½]<ʸ à ü|*ÒjN&¹7õO V¡`ÅKÇVðυ£gfàà‰ jΊJË¡ ¢-MýäÝ7AÙ©}äž›ÖýÃk²¡_ƒõ†QŸÿòƒ¿‹þp×þ“ËŠ¥"Æwe¼¹>¦€®_ÑÅz~NëÙKG¿Zq`|&csóP*¢»OÝmˆ“®\Ù:òÜOæ¦߀ÂUî°©Ù~:%(­©RaØÊÎ×›o:efhËZ·ÆW«PÅuR;&Ô[Ü]êDØuÆØª§€Å|†‹£tˆ7ø¨ Wä¨s¶!W(0>RSžQt…—âY¹§I=–;4ŽçêÖaÜÈ‘úP+8’šBåÿz¨¤ÿ»0s°ÖèI@r­<Ÿ-Û¯u´D¡§#‰ŠÀ§†—Æ`¥†žá †ûOÁáÓ“P,׸J3ÁƵý' ùÂ'>üË÷ýÓeÜî—l]ñ Ë}ò?Û?plì¾b¡´úôè$ºtôv¶Àʾ^îm‡Ö¦¬1ÇM||¢”N§ÒèòÍÃÆÙbEZMÕÊzáåÑ(µrÙ—€¢ eú´u7¼”ÀœUí ί²¨w–z¸uþ†¹ 5 ¡x–:QÊ2€.-;qÃPêäóÉïw…×1Èhô§/°¸@• ¿ëzœDjØAõwñ©©ÜzÿV¢j¾bY6­T\*]J˜!;‘sÐõöh<üOm?S(д«âÑ ZüN¸iÓ´Æ"2%¥8çgó%Øl c¼)(—ªà7•€˜Š ã%ëµeªÇžRˆEÂwáåŬÐb°N¶Þ¦ñ|.W¶©É>†xrÕ©§Y¦–D §6ãyPb]P—]rCN¡èÅ*,pMOSi¥c¸ yuy"’¿°È2¡.|ÚÍw=}r¦Ršì%ðßMv¡Éæ’àä²YV¸S„¯¤sœ‚­82ÍêÔª<…ˆÂ šiH<~ …‘Ô¹° î7–€Á¨»P?гï‹ÊÒpˆ„žU ’‚èn†Í«—Aœèߨx]ÚB2 Sù,<·ë=5 /‰6ÞŒ ù·m¦^?µõÅÝßÿ‹û?X|Dà’­+Jä‹Uß“Ûv›/¾tôí‰Dì_ž:,*èrV¡³= 7l†C½Ùâ“&'Ð/›/Âî#gPøGñµîcg*ð‹kë ’”òÒU@÷ò—«…D5÷0\Ù\³$d›îÎÖ§%;Ð % Äé*²¸ÔД=õ7îô=ÕH¤a¿7º»÷t+磻1„ y4å¶!篿ßÐ)ªí·U´â˜2Dqk¤ E˜ž!Jn–)¹S³)ŒµÓÜЃróÜ‚ÍMUkõ¬l!ŒºÀבc×âQ…faÒ5¨ÏE åº’¸E3ÂA…¿C‚A4,]Д qXC›¦Œ×ùøØ4{{Ÿ‚b…&‘7'žÄ³¼ÿ?÷[WÌÐÓ+B<òìKï@kð™­;_³ÿØn=Ý‹ÂÚ=pËuë ¿#Î1œaËÑÕsÓ)8tb ¶¢å?51Ã7”À2î½w¾Xç<ïÅZè…Ü(¼q„ІëæI±ÙÎ0P ú>RDq´öTeØÓÖË{Û¡»£ ‘ ¿×‡Ç£m´P©=‡CKë6T×]ü+*nê~©-0;ŽËm±HÞª4XƒXŒâ×$§A+!øÔ…—º×ÀY@§!¯UAJ‚DÐ)…hØò9ºV>Ê:Ðë‚!°lSÞX²«/….¶%±®‘på¼*yeŽºN¶ä Øì¹rÊbìÌ䙄 T33óÃF©Qæ!Ä XmUu Ji‰z&¡¿uÚ”w´ÐʺãÑ÷œ”,]#ºÆ„ÉPhvýšAذz•wL4ѵÄŸJÃ3/ì…]‡N3ÆáÃðÙö÷ÀöýÁ?|æ7¯ˆ®Ä¯kð§û-«§³å6t[?‹Vÿú#ÇÇe*éÆÍ«`Ëæa®$ ‰Üç4¨b|z¶m߇OŒÃÔ\–Šòÿºíõ)½VDèJ@ðRF¦G*1¼|¼¶ü26… aŽš@Ï`VÍQŠÑÔᎇV‚Ç<ÔŠùœ^Š*Õ(<üG§vÕŸ…¨7tÅyot=ÛÑS[³|n¼v%´·'fa³!˜šKÁó»à /‰©¹iŽßïû~Âï÷`ˆçTÝ‘ÿùÑ_._nYºÐzÝ*€O~ákf"¾> òÔè̽‡Ñò“…ZÖ 7]³ ®Ý°Ú[cP(9j¢­ §F'áùá ¾6‹.d( p¸K`¿†«ö‘šƒ§€«i°Šù&L.ð‘a‚Œu! QLÛZ›¡§³º»Z¡³½…+“Q?”Éu¬ÐÄÜš,È~ûÔ-˜Çt‘P;‘€'ÝúJj4y§@}õ‹`’õ®–ð'Æ£”ß'¥!¼><É£ bVZ*áN:’-(Ó›z@ˆú¯rÙ%ÃO0q¨‚çXòÜ©rßRÁŸe| _Ià%uÍ(Ññ“g@ˆ|~n‡fäï~Tž}ˆJ!à´¥ìªdÊK¨>¿¤xÔˆqJJÒ’Åàg:WÞÇiôèNNÁI¼¿Ó3tÅ‹ û † FC@£q‡…}4¹@óµcg-ø³ÇÂT‹ð9.½ŠÊ;+‡ºáÚÍCh€z0 ày W¶ar& ;w†­;±cá 0,ëï:Ûⶨ‰,—ªO~áÞ÷ºììúºTÿ³¯>Ÿ=ì³ÍO˵_ýòÞN¸ç¶-°z¸—ãÍ5îÄ#/£ÕÜwðì9xfÐM¤i£›É°™®D¥ål4 †j⡌ eš›c0ˆÉà`7´¶Å™ÈC,=å¸s-uÒezÔ \çÔ0~wr¨¥çÁ-YøC¸±}‚bù ·´ÕËTV—Kx´P@¤Ý\-üüg… €v€)´2S'á1ì$ßX²Ùê;žK]w£ñï๠ç™7÷¸þJé°WäÊ<%T„E|eQø ã AÊ€åf-!†œùâ¿£Ô‚-¦dB1MYÆìJtŸºÿq 2÷\4e GMÎ!L¥ópüÄ>zæÓYž I[Ús«ß{WÕ(>}‡åHQð’Àz.ƒÎ™¦›RH@ŸÕÔ…U+—Áµ×p¨ÉÓŸ-:6Á˜ÅwzF'瀎}óA¿õå/|â}ºÜ2vözÝ(€ñ©ÙV¼ÜŸûê·Ÿ*ž›ûÅùl1V«Ua¨¿î}ëͰj¸ÑåZ­ÂH5‘{vî:ÇŽŸá\2å¼} $‰¸×ŠbÑåµé††#ê‚ S]ÄÎ[½bººš9¥—@WŸ<”b©Êyn#dnÙÀs0I° 00¦·ð߀VÞ!„7“I±¼I|} ºJ¸å´^+“Pº*–÷RmO·îy8Žª´$0=ö 04ÀGÉ–àa½³y+…@¬pìuT°—׌×4‹blfZ´t$^"';<úœ:ûRfƒúüMOÏÃèØ =1ŠŠ  •´iœåÎ×)Ù® ÷4§£žð©·*WoQÏËð›Áš¤d¡exV/_›6 C,ágÝKçA¸÷Ð)xô©p•} *œm_øËO½ÿã—[Ö×ëBŒÍÌwÔÊ¥lßsâ£/¢ uj|–ÓL«Ñº¾cþk7­ä¯äSþy>•ýx÷ì?‰7£ÄÂ4}^:ÏU®] ¾”Ó¬f× ÅÜ38}VãÍF¡­ cüžX94±h@æÛ+UpÅ(É.c¡£Ï Š¹BÜl  …>@s/5Kv™g/àý§&'OObx0“³CÁ$Cy†ö^t¥{4èc]²0I¤X ’wa¸õªÃ`(\½jÖ®„V‘Z¸Õ˜Ü”5§¤´É%˪UøóXÀéy~Ñÿ¦PA 'að{ª¼-~>J ×óϽó3¼–ZšµGJN2<«gÊ>”Mq¹-ËwY1X  äk,•Ñ„?ÅþãÜ>ôxÇRãg‰~cA…1*;—m?ýQ˜÷…¡@±>MSJ¶$ ½½âM1ð?Ÿ“i* Ïh`»ßT<•šÍÀ¡#§àôé n^.£ò1l…©{¬Â¸³'$Ëû¿°ç€nÊbòyÖ8E _!åRf n^¿ 6®ä‰Q”—!¯* À᡼‡OœaEñóž}7~î·¿xÿ.;&pYÀl*gÛÿ§·î:òûÿú§Õœ¸*ôww½wm¨U‰TCSr)O<;—aåôÈ8ȹºéeÝyba~8×±?Ïjüœ:}„q]=]°rxcþ~®Ë…õÙ}*t …,>YïZ& "›[T™9Çx †RV»¦v"÷ 'A À$& Z–J‚½R•áBÕaŒÁ©•åóU©x6™ËP5[M–Þr}US“Æ^{ï@{>Šm( 9‘—ÀV&QÁ—ðY¿súÒ$/=/ÛRœzÃKÉé<»õ®>.!ý®$ÁJAò($(Ù>Hc80Fåê ¢ù JÜôè³â‰twu@GGz2uWg3È8Fg;˜2mù`÷ÊÁƒG`l|ZfbÀTÔf™½Yzh¨`Òwª"Š~h…¢ñ&Ò ½ '0Œ©àµ'æ$õ؃ÆêÇ·ÃI Sˆ“BÕ–!~I¸ÆW¿ø‡¸¬µ—U8®øô“Ïø­o>þ|loMmmIøÑ»o€«™eÆH9º÷ù\öï=Ê.1eñˆuŽ\{)vM iÐìšn[ÿ·¶„W§íÊìEtt´Âðò>H¢+ ‡»’n®é±U*k¢›™ XÅ"ŠF•óõ¤{ h<ÍujLÜG¥ßȪãw8(Èê+áwUJp£Tfá?•§QÙ¸¬p¤»-ÝÉ%½+ñ€†Ë#`áõðž7êE<ÜJ›(Ó¦݈Íc0@a«ßñ'õ °‹¼öˆ©_‹Â+|–×Hß:ÝÊ3ÊŠù A¿»àA:ÔÙPæÂ1T>N}&„ƒ!hNÄ¡£«‰³t£I¸A’\ÉlF›¯q&—…Ô|N=“S)ÞKܦazKcí,ô 4­x!YT3‘õ5䆭¸úº;`ÃÆ‰†ñI`°¢²=ü,ŒÍfÁ° ä·fMaþÖ?ýËÚXä²(€JµŒÞœñ¡m;Oþ·ï?½³ûà©Qv)©¨âžÛ¯ƒk× C((™aß§Ñí?zä$Œœgz+³íøÈ/ÍÑÃ7¤Å«£:‚®,Åh4E&‹@oZ›Î&hmjf€^ç¨÷i›i’ðQLŽÂYËeÀA%à'OT¥¡2®J§qM=¹ü$¸«,üÄêÄò+X`‹2þ$@éB|ðkªRPX@Š’KƒkŠTä*! cT}ñMÅþ“‡ÝÀûó6qÃnöäÁðB ¶˜¶¡BKÚ:rûQMºþä`ñ…ž½›‚á÷I´ŸÂ6R ô~CxíȤ!–XÞŽ9I)TQç!ÈùÃèÄ ŒB ¯š~p,?7?iŠ¡%Ö–fâL4Ô ‚  TÝ£f VðºÍͦa|rÆÇ¦™ F ²MDÕ ‘†ŠOy4&°T‰ËES”ìén‡Áe½Ð‚!ŒPÔî<î“Ý»Â÷ŸÚÅd&â@„¾}º~úÿûÃ÷ÿëåCXÚ™½:kçþSûxbך]óæ#Îõ·®ƒ7¯ã)=®”(½366…nÿÊGÅ+ˆ9/÷|'("\mõÄy²˜†zÃEbQèE7®µx(BÀy-ÇË¥3}ÝY7—CÁÅÍDÂJ¨>*Ÿ)Qq®,döˆËÜ|ᨸœ(¼TP‚Â-ÐÊ u œ|‘?‹¬½¨HA8(÷žiÆlõk°©|èü½¦ëü½tMÕ5hìt¤î³Ê݆—Ôù3†Êƒ*j­hC=Ï@¦%_z>T>öøAŠ‚~VìY€äÛ/P ºÔ$¢S‘+vRáz (ðŠÀ‘c¹RSkzŒÍH — ±‚wh²0ã7–‚+䵡‘ãè‚Ó#“Ér*‘ÀCyIŒÆù¬õ¨J—´Ïd¹7‘š¨¢««–uASSBzªxlTôÛw†'ŸÝ³sè˜Týù<ª«}ñÓ¿þÈåÃË¢>tÿ?\ßÙÖüð±ÑñµäêëlƒÛ®_ ·ßº‚÷1‘7H:•†'F`58•ÓšŠ.—€Eò‡8¬ÐúK¬ Û;2N*¥(ÜzKOWwÈÑy=oêæ¹Å(.¨Ašp®8ßÎÐÍÌd6P¨ Rx]~rGh©˜iJ²Ëô`*ð[~¿¢ ûX€M¥z؈T´¬pI"7ƒá…Å` 2á8þA=ò<ðûxrsszPiÓpô€›|(<Ä"èÂÇçC¬½y 5ÇÆ&`f6#«%AMvn¸&uþ§ëQÃ$CÃøé–VTPƒËú˜ød(ED’žzv<µ}/LÎÑjêú|6ôèOÿû¯¼øZËâkª¾ô/Zó¹ÜºùTù³SsÙ;óÕb ‰Úû¶ëÖÁ[oY‡î\Œé½tc³ÙœA—jj† ¬­ÉC–È Ùg±T¯«ë„[§öE.egg'4a¬ßÔg÷°ÆCúñŽžøƒëfÒW’e&ª®©œZ®2äʼ»æ.£ó5éÂç `ë¸ùà‰@åá’µ§çÉåGÅ@ô_Ð1¼+ë ÍÎU¤¢ÛçA]÷éɸ €N±°¥™^Eç4iÀRßé*¶ ¡òèšC@ ÀTVO7Q•Q^(K„äp}€?ˆÞ†u„øè‚ûØkà+hØR‘Ð9ó5ÀР&ÁU*k¦ã©âçd0HE[!h‚|0e:O¼V$D‰d’Bö´wpÑ¡ ^_UÛaãw»ìUæ¸Òpbb½Ê²º–êи°RR·RYtŸ™šJ Üé˜ÊXx^m­Ð¿¬bZÈM}2Ò>öÜKðôóû`>“ãTg,|ÿü»~Ÿ¹ïs¿÷˯0øš)€o<´Í˜œ›_9—É|lb*ÿžºaÈܼe-Üó–Mx¡ËUø+Ê0::Ó“)Õ1FUàÁBÄ)€¡rÚíS¹bã…oE²½½oŒÜŽ+ê…3”zse.Ÿ„Õ7ºï0ñN é3iG .án­Ê 8¹úF=…B‹x\úü71É'¼¨:нçz®§.MÊ›j†­ó¶È2tykƒ¸Èõ¹hg  à*l¡FÔ+#Lݳ ‘8Ã/¶TH"½á3™×¯±RV ÀX­ÂËK§’r·\9èÓ¨Èô'G_“÷E ŠB6Ö¹HB¨’†Š4 Bks3tu4Css‚…˜{ÂUê‰+å¡Rˆ¹é4Æã3G¯ŒÒ¾¬È¡Q Ô b‹o4:Ê•H·µ7AoO7wªâ~ŠF09‚GŸÚÏí8eÜ‘P<•/‡üöÙ¶qø3¿óK¯IÝÀk¦¾õðóm§'gÿäøôoLNeƒݲe5Ü{ǵÐ×Ó…’"‘ æžŸf2G•êê)¾ÕÌRHb‡.ÐXÊØlÝ#^Ãð<¨J$FáoA7­Y‘?Y‹Ïq¿`Ÿ™{(ð"3ÇBÍóå 9ïO2óÞx#÷díóŒØsxPʳàSvÀEŸ‘}Bô‹eÆX°MÖÝÞÃkn¡Ósõd×¹·ªÇXx-´"0/z].ôy M}êìá³^¯Ëçy¿|—«zýsÙ­!3-($Åéã°‚‰ð(\ðÉlƒ)óôL¿q@µkwP)HTB R‰vôÚ ‰AÍò£ò6Éîs³•þÞNhiOB(äçÞˆ2ä“•ᵂ´1HÁÌÔƒƒ¤ƒ ôu…8+K´C£B/݃˜÷‰©"µµ½:»Zñte8A¯èôØ<øƒ°m×Þ[Á€¿„þ*à³?ûGù…‰K'}9î×âK¶¾tÈ›˜ÿƒÝ‡Nÿæ‘‘‰VºžÝmMðÖ ÷ au9ƧÙŸKÁÔô ”PP,N+Rƒ›ªw›Fÿ½RºEV£5S£»cj´µ¶âÏ·ÒbÊ©S ²ô(ÄV¹H]6dšŽ€Bîm-m§¬À:NÑ•P¨QQ¤Ó` ° TN…ô9-¾d¢‹[•±.ïG,¸õë†NU5×ó‘WtåÎÙ·uïèÜMÝ8d¡bzXᢟ#šRIêa©^ÇoÛô˜ˆ„p¶€Yœ¨HW@¸):WKò \Ux$‰PU¾eü¬²„B ™D Ì5w@)‡ªú>J¶u4A_[WB Uë`ÊöhôÑY ˦§g!‹î¸æœU¸ørMð*Fn L×c RJKkÚ;¤Á!\‚2‡ŽÂ¿ïi8yf†•xs<:ƒ?þðóÿÕ?_Šlý°ë5QÏí:ô»Ïï>ñÛ/î9ÞI%•½Ý­pß][`óº!¼3ëèâ•ÑõŸŸ•õÞ¦pÁ×Öü:eÕ4Ì%Þ• ·’jöãQH65A4f¥BÄ#–ÇâøÓr*l¹Ýt­yNöÚ#W–òýª= >ÅîD9åð Nzÿq>Yüb‰>tmìÓU{¦:]šËŒ:Ý_¯Ñm÷âu€y^ÀŠQQ—/z[ ‰øg+£Þ'@wØQ0£Bë¦ÃÎ.¶ÑP„PcÄø5š†­[ àêû¡8<ŒÃ’=u¢žˆ”5 ·Þ§zÒµv ²2¸J™*ÑEsž‹5Ád[cíPÆð H8¾Ž ÇššâÐB×ÑÑ‚Þ@@–6kàTÀt~ÔÚ<ÎB&5/÷[£Ïe.¾Ñ˜ÂÍ@ ßé^X^(Àµ$x@ÔI©³»Rˆ½»@Ðf|kÏÁð퇟‡q4|„àù›¿ýÌo¾ÿUÈ‹ï”K»öyߎÝÇ?÷ô‹‡““3ó0ˆàntûo¿i-ßÔ §¶TèÌe €¥ûê·Ñë]^;u-œQþ?RŒùã‰ß®^#k SRxƒ,j#ŸáXSr£Szu»Ê½Èq>ÅóyŠé³Ô®½†ÔH õ¨ÀÈÍw* ôX@BM ®OÏ5 ëD¾Ço`1xµæ SW‹ÜJíL¸S:ŽÕo J« RŒ§Å]øñò¸'X*3³áµ ¿ÑÝY˜a(ËwéÞPÏ@Ó/€°U 2ôL¿csz!ÄÆs3©)Ð ¾6ŠA¶© 2ÉüÙ€ù$xTmØÙÙÂùy*4rUÿFíÁ†j$šãù¼7¨· „>ˆ¢Q¿w²ã¨ HÉ8× Ðó~ÕWñÙ‡áÁG·ÂÄlšØ£[Q}Üÿ÷Ÿý¯^\l[¼:ëÌd*ˆqÛ]GG&¾÷õ¶ÁèÄ tµ%áú«à]?~«ªx“±†7*;Ÿc¶ŸåÓE<Š–+Ô¬x¡àÎËrãiÙÎ[7<{Õàr‚"…ñÂGÐå§Í.¿Bðù]¤„¨c/ºêlùñw3^-Åů1ª[%Ę0RŠîëbŒOŸêû)ö‡B™sü¼É\YÌãªE#¹D4XYÝ' ¶Iêl…öp¥,Ìóˆû…Òzž· €qPOƒiœ¥¡­¸®®k Ñ: Üz£áû\C yíÕ½ñˆ’ð zJ÷ž¬¼cº²Í–í‡ú ú$§À†™lÄ% –º&ŽŠåÉšS(F Sð r‰(¤ãmjí…\S+T}²¥ÿÈÓìÇp``Y7ã>KÚjMÓfÄE…ôJäÅ9²SôùHäg ÁùþnÔ6 ½7ƒÇÎK%C¥DåÆŸçOCH¾ö'aÛ®ƒ4g€0–Ïþ±¿ùÿyÿ«%£:öK²NMo)•«/üõWIº‰Bsãæð ?u'†z!æ´Ë~—.³yŒÃrrrìYêB‹!3bŸ:2žvÙMWÌpÕKZ[B”f‰Ç¹‘#-Sh6¨+-}¿;7/uH¨òÞd­ÊߣB xÞÅã¹,ø»˜GW1›½·Tfâa†«Ów¯æm{ã-OAhò‘iI|€ ¾ˆnì“Y°í:°ë*òPMÎuä*HšFäÁLç2˜ì†R$Áµ ÜÐ_ß܇•+˜IÈÍW•2Ö 5š Ÿ¼¯%4HÌ%P ÔT%UZz—.a\d}‘¢uLÇÂŒù< ‡š¿ºP@ñßx¶í8Äá¯å³¦[›ãkMÓ˜ýãßz÷«²£^5ðåÿxrù|:lÏ‘“0“.pïþûîº6¬d–¡&ÅVQxJÅ¢JÃo©Åî£ÍAT¶›&—Ÿ[<[à ¹Y¥×¾[iy*Ü1©ÏpèF—ò ÒÉ|»`.9Yr¦áy­»ƒÖÞA—ߤã%t¿˜Sî¾dûQx`‚{N¼|u-¾ôÐ¡Š’˜\DJ€¬$Õ0yHyš j2߯  ¦*úBC‚ÖnÈ&Û!ÛÜå`ˆ'ýPøC ÜßÓ ýCílùÉC ïJ6^‘ä&R Ô¢­BYGMy6uë4¯®°á¿K8GPõ$5SžZÄv ˆï§p  žëÞC#ð½G·ÃÁ#§ ™AG[˱¦Xä-}ß¿*YWe—>úÌžUNŒ}iïá“wæKví~ôî-p÷­›Y³Q—Rô#“p\É{XÊгÞUø”tZU*FÒ¶‚A°0Öb^¸£ÊnA¦ïlîÌ<ÆíiÙ\“™†òs ±g¾h _ç¦ñõy‰ê»y)üÌÕç&Òc0ë™óWãÒ¾a×9!Œ©ê,É`+L¤"Â4”Õˆ¼—ïÏ  ”!Q³ñ.”ÂIHuôÃ|[?šš¡ê§"!‰¡Dbèîj†¡þ^†PªJö¦))O¼gh_RcVQ¬ªpõ|Öɨ󇗰Ç ÂpòÑSµ1ı¯U®i¨¡5{jÛ^xð‰m¢ñ–©Z¯Èh4èý:tX:uäêjXçB‰LdÊ2[`Qã}°XøÙ+pM™ò4x¾€ì©@YJR† kR(SËWCº½‹½®5Ú~è낾þNEƒ²J“9 Àý&Y¶©<÷lÍ‘¥Øç(ȼԙ…œkõòh¬`€S’ôWêq13—GžÚßr'ø6ô´·0ø3ŸþðÏ|ýR_÷KºSñ&Ÿ<3ý±ï<þÂ{ŸÚy€ÎþÎ6xÏO݃P,U¼U.u4H/¯äÐÖ³¾Q‘Tt??—Ë/)f4¹$ÕâvRš»Æ%›Dè¡Ü<¡÷Ôb$`Å=u©„Ðüý=Ï´]ªí'á§ØßÅçe™®£€'u šüq5îÅ낵 zOh†òL… B`–¡¤x² .“–=¸ ï×tßJ˜A%PÀp B±*³ §¯{;&B!6(5C6=5•'Ç_˜ì%G¦Ÿï¸—<´T žÕ¬TNOÛÄ ðËÄn¢†+GONÂW¾ñœ˜˜Æc êObQÿç¾ðñ_›º”×ý’*€b©ü¿zzï¿ýèv¡T€d2?ûŽàÚ5Cèæ˜<;ž’]+*|i¼hçƒZ=xW±Ý”[®l*iûeá«ZÙ¡¤šx³ÍB ~Bù…#•‘%¤Õw1LâI3çŸ@>@Ë_ËäÐíÏpáÁi=Eäqn"¯ÒPgÓ¯ú/o¯OCýߊ­ŠžÈ+`ú0a4k€pºßšêÍÍVj4Ë…\g ÒL ­…ùÎ^¨†âÜoóó>úzÚaå²^îDäšBµRSUªÍ5páZ×=çX—¬)”@“³}éí€h[F¥µçÀ1ø×ž‡ùl>;Óœ ÿQ,øÒ§>øó™KuÝ/Ù>ýæ#Ï‘Pøñgw»ãŽǠ£)7m^ o¿yDÃ~n¢( ÎÅ?û¯â›F¤0›–|*Ú`‚—EL!·Ýz3—ç¦ÅŠºxŽÆtSY.ÕäŸEáÇXß™O ÐãjèÉxØÂ€Ú )³2 tU•ÜùuW×ËYg+•Õ ’C@-ËdƒÛkP"o¬Åüª¿ +D>ó¡â¯„03°fzú¡o…j¬‰= *È |ÐÕN\Vˆ… ±¤:aHóæB™Ùxœ‹Ÿ˜Rg^ŸÕ©‰ÇÖÉŠÞ×¶% Cyv?<½ë0” eho‰ŸŒ'ÃÿóSü¹/]ªë|IvéwÛêËßîC£vøÔørÁ=Ôßïþ‘ µ)*cëšlËl(—NêZO=«Ûb‹É#ô?Wv•ᜲ79ו–…ÝFK`aÌn–iªNÕë‚GÚÜá’]ŒéÉÊ£«dý)Ö§ŸT$B…=”ÿweƒMݳÞT7SßUÉÕ“eÌW}€~-èÑ'ŸP< i‘½þ„¨„ª'àqBÄ%Pc»¨þ ¨DêÁûH¥ÈùDÌ·`8o†ÔÐz¨‚\ÜUã¢3::’°¬£"á 1¥ÆvLÓ#H)Gà<{xÑóòj…öH#ËUy0²-£€™T¾úÐ6812±HÐõû­ïþùÇß÷—ê:_’]ú…zÀjއžzaïñkόϺ[[à-[ÖÀ× aVc¶S^¨¼my´Qç à¹oêRœÝ¿âüS)—H:¢¦zñØgrI¦U+ƒÝ?_©*=!K€©ð“nlÊqQ1¸Ù þZ}rý)˜—…<\ à0}T ˆsHßCÏZ\þW².¦øÏ¶®:ä‚Î7‰!j±å“09äPOI2 ÜV PEå@ `5‚ñu7@¶£•@Hve¦0?«·­º;“ ùe³%å¦{ŒKj;fIö ³:Ý—a´ Ù†µNlk`qRñã5Ußá³}ðÌ®#ðø Qd!d[ûÐyç?~îC‡.Åu¿$;õãùõáB¾´gf.$ äúõCð¶[6@8([mß™@jᬫ¼ÔÐ[Tcec8 mu6–TÂõrM¿¯Äã±k’ÍåšàXr2mµ~…ØBТ;i¨¾t¤$ˆª[È2è ËóR°ðHX©*º©*C–/\µzºß¼Cæ±MÑp¬/ç.¼‰ADMörë¡¡|Âû«ãµrÍÕ•= ©Ú2 Jê4“¹F#@¥ÜÜ«·áMšé_ Ó+6B•€ë·Ù[$.X UgsO‚ßc¼!"2ÏCôd¿jInh–§7>¾q¿jö§.•2ÕÄ&=¤ÔðŠ¦¸ZÕ ªó2TÈkÅã·}&7Æ}𙽰}ï :ŸtÀo=ÐÑÑüûüÛï>ùÃ^÷Z|ûñú_8pê÷o­R ­ZÖ w^¿Vtò¼4Cñðèq™ú(ÔxJ£ñ¢5.e!l‹Z=ãzn“¡ª¬ªe‡IDEn¯Í‘Ÿg„}¨x’DéÅ8àzB{Õ[Ÿè£”Ï'& Ð“ j/„ô­—Ûp¹²g?o±†Ê¼WO¡žûE©+5lÓ5¼‘êB7"ÈuÖƒW…(êµöÆ‚môÆ_³r ï9ÃóÖcÉ€¬&ÿnûT3Sž³ F-jEVÒÃAa/…¢0³l5Ì®|k+*Ø®Å54“°£5 -É·©W%‘ª·„ü~ê+ ¹cµœ6¼ðœ Õb¤Þ\D3u‹:íý×-…ÈeüþB¾L“…Ù“MF‚pøä<¾ý ¡!#ÐÚ’üÒuë>ó®¹åôsݨÝõض½­™láÿyî¥ÃŸœIåQ «p×ká†õƒÜˆÁ2§Æ4Röhk´åç/IeN–h@Ô3Ë›Kãµñó³êû^‚š¡zÀñ ¹øQcGQkFݾ´¦>Çd·ŠÓxÛsœ?î| Ütމ=@é?"q;.É[wýSN^¢{¯ÆZ ¼vã¬TX–Í›ž[éšjú°ªztø²PŸèóæPKYçëåÏKõ*ä&°–¬)  [xË m)¥"3Ž#«:‹Ñ&Hõ­€Tÿ0›[Áð‡Yèhž@ V[s b±0˜^ñi½F…þ  '`Ê>–u·L¯jB(¡ê@Àû>‹v…â`üo(f—¢öR'ß*y2Y0åÇG8ýÜ߯Èi#ðzñÉcq½M&”Æ^œ¯è(7Ñ”E¼°b„dËÒQY4&ÏÓPM<&7©& † oêø a]HÈIKÒ¤ ÕÉØP^3 U‡'âð<GæTPQä›: ßÖ …ö.H÷,GO@zt\SתÖd”[ÃË¢B6Å+ÅC ÆŸ4ùØ^P¾^¢û6öH¸Ø"EVÂ0 •JC¹è27ÀÀÄL^Øwžžäqswݼž¸6¿þ‹?yÇß¾ÒëùC)€/þóƒïÙwdäÿäòvËÉú¯ìë’ qy\5@G{3#ª–âà/åj 5]@~Ÿ¼îªtÔ@á/ÂäZp£î&Ыø1£q´ôAQ›;tÚ2Ç_)r‹®*•û¢Ð©ÿ¬RÚçöQ?`:)U ꌄ¥©ž|µ–˜žÔu í0ÏÙ°òã,ÕªÌë Êfç­¥²4¥ófY‹…jR™TTdÉæÜš? B£Ê8–øT5†r4™¶.˜Ø| 8~?ÇßT`Fû0ˆŠ„æCÐä!M+£Ït„ì}@·¸ƒZ”ÇBr,šn„²`Þ¬àÞB,~/%ÅÝe*ðäDŠS˶j™vøô<²}/ï‰XÈ]­¿üÑüô—_éõ|Š็ÞùìŽCŸØºëئh$ ý]I¸~í4ÅÃP¢ÚztÃbÔ¡£‰Ý¾ ¨ÿ¢7™ÀCxC8¼£®*él¦¦f¡HEÔ®·fò…¢µ£ÅŒ£ÐÇÈ›rœ5ð"Æa‘?Êñg¡ÊÂ?Çÿ¦j>ÙÀÓá×»†£ÆZ™Ò 7$9ãåå{,“d–«òßzé²~VÍþÉ$T³ï„.ˆ1‚DW×¢D§ ¹´×PœS²©#‘P”È ¨:²Ð‡Òƒ(©±ÈõwC®¥\âÐg8ʸàŽÆ#¸—ë \äJ‹ x¨M÷&C=½Hã9œ_ʽT}jø9““s-”Ø{¡‰shü¶ï? 'ÇÑ;¨”`Ýòî—®Y=ð‡?v÷ÿöJ®ç+ÚYÂuþÓcÛößÿÍG_Ø0›ÊAÀM›‡¡‹rþ–à)¹Á@úºZ Æwt³¤kz±Ïuß@ZxÃòPƒñ‰9˜Me@6—A¥àúYh›¬*´dùñfÑ="b…#{ñ jÁ£ ý¬Í]››‘t`GZkÙ¬£±'Ÿö m½²¿–¾aÁC€‹„² jkÈϲÏg)(•`*Ôãª÷ï­‹õ=ÐᲿr$»!«ûˆ.LCMT§&íÛ¥>‚ô\µ 5šC0´Rk1$hG%BåkÉ©Çh‚wSbS×xƒdåþ R㮎Vw5÷Q¿ÎëÚ¾”“T¯§ï$Cwjt CØ®þšš‡§wƒl© I”¯·Þ´zÏM×~²§­ë/÷z¾"061ýÄ×ÚvÇž?ÀñQ/ZùkV-ãyïUꤋ›·%‡þ¾€dã=Ço)_`Ê«¥‹&øv⟘æQÐ5#€âf?ÆÇ~ôÝ;ì*´šÂ“8îXË=û <™—Ü}©¨¢/ ÎÜ*…"¨Àîu´½¬â›rO 4*f£¡šÔ:Ù}˜<€†qá’õ® iÅé]Å`RËÖ@¦*-àbxÀpŸÂh<ÛÏÆÐÐÒóIÕ1QóOÚ™CÐ"[ÀAC¡ ![Ò/e›Õ1Éw¢¡83ÿS­¿£†!Ì‹GNÃ) æ3E¸qã2¸÷ö ?ظjøÎ—{-_Ö®?:2eøm»õÙû¿ûÌ΃×OLg ýÚµ}ЋpÙo¹êB"‚eýíFê©=(r)  šÁgêî9xåˆ=‚"›Ë«¦‘’öI®»Ï….ô‘75 5týLª„öÓÄ^B…_7‚u½œuq,ÀëøÂYS( YV½¦€¦)×d9:w¨p½×\[äû‡!ß; ¥¦žs ƒyÚ¿4ðÕfLA™tÕªŽjJ ŽÄÑxHMVttY ÞÀwXl)Ï÷t)_‚㧦`.•† ßb/ …{{û¾S05ŸfÚý­›Wm¿óæõ?Z­:3ýÝ­/›‚²¤uld*ðû¾ôßxâûŸ Ó¯žöfذ¼[ZdCöX# 8´¼“G4éê‡zƒË%•7ù‚'lÁÔx4ÐAá€Ç¢ŠZ5BŸ¿ÅÒ\)æ§ûUã} b=Ðâ—H`ÌO-ȨÇ?ñį*€+w-P ã¿Õ ¬ó0„©˜š²)ãU9›A¶tàq"Pñ Û=©Õ› ØÕ+Û¶5d­åR Íj!ÉD5)+…ÁÁ~Ø?ò†¯@SÖ™·¯Ù«šœèÒ\?¬_7ÌY1y‹: {öÌ£ÎQ'¡„ÁâVdäq8pä gØ,E4;rjNŽÍñþïíL~ü®ëÞoÛö·¯_?”]Êõ\²ì:4²|ljö›ß|xÛšl®d%ãèæt7CwKLöÀ‹Ö‚ÖíªBˆË,  ¨ºb ¯½µëEð%4@ó¦ÚÆû8rì œT C%7é06 É6 YõŽUN|ÜbŒ¹48ãcà¤SàPÁºþT Hy_îñ¯6ÅÕue­‹–‹7à{ßT)S÷m­ ¦¨K,ôÄÀ#“8,ô b°bs'Lm~ ”zû Žs¡wF²÷dEí)] ÊÑ>» ôõvÁð`7Ä¢t:]5¾tA‹:TQ ßkÐ8™ßPY"ÔMÍeàÀáÓ03“Ûoñ¬Ã™Ù*€Y˜œOC$äw~æGn>МŒþäW_Êõ\’œ™L³©Ì;úÁÎö8ƒa“ Ë{Z¡·#ÁEdí]·›7¬B·§ƒu®®â 1*(t­¶«A’ü¹ž %ó·ªí4c.œD÷f÷þcLÇ5TÇ*¾¾'d¦¸É“zB¶œðB¹]¹UÌ«˜Ÿ<âû—ª<ˆ“ÛD¹Š”ñ&áØ¿Ù×þ†ŽÕ/WŽŒãÔnÜVrY͆l÷¤7\ Õd8Á€4Ϊïd _S¬H>.2ÀÁ k‡`²aä‹Ðà­HZ¸ËšCxu%Œ^Ê¡(¤`¨—&~ÊÈÈìÚ}€û Y‰X±g¦æàÄè †6¬^Ö[6 Ý‹„ºaãð¢ñÆÒÀÄÜÀ±‘‰þÍWþ/†ß„ /ƒIhID X“M8’1\Ý&hiŠB¹TT%0R!<·©±8¢±tV(‡Bê‘>9•†={OÂØø4øC>TPsg˰`yÄ›“˜¡~ïìiPÊ'õdÁMÏÊtßôWöQM¸ °ÇuTç1•¿J°yïóÒ°uÀ0 ‘VÌ)A4$Ò,Ü„:•mZ¿Ê­PijæP€Àr‡…j ¥ZCoP‰úçÑíëê„Më–£WƒjU{¼ ^¨¸%ByĦòX²er$žLlRõá\* Ïï8éL‘ÝšAfæs02–‚™Õ*¼ëÞ›ÿr »ýO®Y;xj±ë³$ 8r|ì×÷ý«¯}÷9ÓöÐÕœ„6Œmè‚РFc’MkúapY76ËdÊ£©ç¥—054 Æ”©>¡Š{T©„œCšyçžã°oß N-R˜V3ª@-؆®Ïš˜ Cø¨ªÁüÔ΋À>Ö1? "EdŸYžzا7‹ïªà¿YÖy')ƒ®À¬×¨ËÞ”ÄßËD5£›Ž®„b{äVC-Ù*«J s¢ *ŽT.fkZªcË ¢ríê~Ø´a9w®-È4̪r°N|MÓ 42v4Õ˜R‚{öŸâú*)¢›ÏóüZ­ ÷Þv­»qÍ²ßØ´jào»>K’„ÇŸÛûáG·íþüé1*:²`YW$Â9Ç3ÃÛo¿b± W6É9XåòŸ³1ÅÖÕ=t@æWMŽw,ËщìØ{Æ&fÑÛ°9}ƒjB¤h’>X™Po = Æ¬.17îÌ,¸ÔÓ=šðCS{hp„¬- Ö ¼-Bñë«À~-F’ME´?2€ûš†ÈÐ|nŠûÄÁ}XJ$ ½ñv( ¬dlŽKQ¨ô…7S,pù»SÓcìe;)…®¶8l^¿z»¡R«¨¿›êk5-Ílè(„^¼‡£É}›Êá±'w Í+H³‰†‘èÂD BWºÛÛáî›×ÿÖ=·løÂb×gQ ›ýµç÷ýÈWxzm8b&RWKBþTLì-Wð0Æšã4”ðžU½¥ÄÝ”%6 Uÿêõhêm¿?xv:6Ù¥¢ ú´£õ_‘ðCGØ„² qÑ8NÌ2ºÿ3ÓàLNs=-ƒ [`¦—¡¹õú„]‰AK;ý«ë _‹¦zµÐ{‚«1@*ê UÃø?׿2뮇JW7˜<Àࡳô=D‹ŸÏ乿¿¡&X× Ê`÷Ê^xËM@Såàýw5_A4Ài$ W9&W*Uxq÷!8~bJ•2§‹¨h¦R®ÂÍ¡<üìܸÿ–kVýiw[óß]ìô•€GÇþêÑ­»?ðض}†1îA,`לRs-ɼýŽk 9åT…WìãåE¨†äD™j^šj¥â) Ò¶“Ó)xrë^˜ž™çFT†¼œø}Nøh÷ç3E"˜\;7^9> $Öΰ®-¡‹óèü¶pƒâF{ȳè!—}í;{Qwì”d^™¡ TâÓq[u^!' N¡o"F*F®gÐ|SMgDÏ_ç‘ÑɨÅC0­ø_µ×r,¦¥i1ÆËm¶Ïõ@Ë<Ï»i”v§¨•ã)Ð ŸÉ)³œ¿ñü|8’jƒá˜gœ¦0àÀáÓâu:t•çb/ÀåtcÒ¨r,]:Sæ :–f SÉsÝR—¶Y±FZRN5¿«G‡j3B(ÁËonÃ~z­@ŽO Š&’ˆÐãݽL›0"±d΄¯Z0íÏÏw .¿}nÝ›ïî>|e Ëû<ð¬=V±¡ÈˆP gLÂMWÏU^­ÿnš¥’Š>I@C”{…º Õ)Åj'§Ï´ãé7 Wâ§”¸9\6­èøôè< ?Èd߇‡‹FC¢ãgðÐÎöV$[Éýçɽ¬ê“Š«×Ìhê)!RCÕ\òæ/¯ý:·gª@qWLiŠÒF5ªm˜+N<nôDÄV|Fa.¯2Z(7½‡ 7ÍÞX,½ª€¨ ÝuÃrTUˆœ½ÃP”Òµd]Hk¨Œi~|:…nñiè[7…Æ«)dÞ²ã€êyÐզƯ!O8/7€Ù“G½þ'w]½â|×àœ6°ïØ)·Ûí¼õñ6~Ðe4k ;™sÏ#˜8ïF®wqQ.®X4ó§C˜eÀ΀CÈ8ŒiLnèìcóöýذuŸLƒexcÒÏab|Љ[Fæ)uáS;¥ƒKïé@’9þ¬é×Ö‚$‹{êñ{÷·“‹—×åu®u>PÒl…æ³ ¬#˜"Û¨…äÒ« •–@/.REo×…Œsðt ö9)ÃpyçWù±ý½†es'aÁœ (滓×I鬚•RCIÓܘ /?Éö}ÇÈsރƦv8ÈCç0"KJ[s<žÀ„1•õŸ»uùÿˆÅ“ÏÑ÷ñþÇ8§u¬ß¾/7Çïyí‰Ug;ÕêÌae‡šiÎûg˜â ~×,™ŽÂ`@.ÎuälàÌe§ñœ¦RÜåAˆ{Õãù×6¡£;*¥¦ó.n Š?†Ä‰ãHÒÏ úþã¶Î—/J®%åÆ <ºMpœM;k’Y®…epTÕ ç¦Û‘**¢'£°:øA3Þ­;Žì$SQ‡)$è¡ÐফçãŠùSEEˆ)êr_ËÆo‡!·)&α&ÇZ²ŸgV¿£šâH7±§Îåù¹Sdžó‚þò[¯™wV‡àYÖ±cßQ-K”½¶~÷žgÚŠÙú>볆:\hÅöîA”¾"[·|,á¼ Ã,`joÔ€b¹g;0´1VTÀÿ‰Ûଫº ¹©ˆ702ÄÎp¯¬ß‰ƒtûäÞæ§„¨3uì\·|6Æ©¦0J»ª‡¬—À-Ë Â¼v<ŽçÖlÆé3pH®Ì®z©ß+) ¶ÝrÍÜ©>«iîÔq}嬗Ù^w$ŽÄïüýªM?êê NS µàd¡£ßÒyÓpå©29…E:lô‹Ÿ±ºâIçû¿î]xeíiœàÙœt™ã¨/¦û1©Ð-_Î…¢ùH67Q,Æ}þ<Ð#,³àaéºVbU@Ãf$ ¡5œ {±§À€zqÕ°ƒ …öó’àvs¦“áó$*þWæÂ9k‚‹¯„§´D’JæÞ䄟«7nÇæÝ‡Äí²yÜ.7®¿r.V,%Š>2û‚u5`3d°èp¬VÜJ›à: ÞÚ°›Ž«48ÕXs§P‘}>Gèþ[–5Çç~jÞ´ñ=ýÑw½±eϬT*µêÉ—¶”÷ÆâºËÁÙ©t÷\œÞàgîº3¦ÔJ²Íxƒµ´ð‡) )#©áÙ—×ãí-;‘ðK™%Lvn¡3 s0"׋"¿.È+ÈÀMF̦/ÑÒ“E»{e”—–ʈ Ö4ÍÐ.À%Z ½o½ñQŸÊµÎé Xä6® p—í9¹ÆMª² ü>è••(¼ëÓÈ™4Y˜·Ú‚9i^wô4ÞÚ²ÇO7Iˆ«^Ë@¨7Œå fâ¶–ÂÉ oÖ #í¿øâ†:É/Ðùîª;ˆGžX·ÛmqpØvJÒÑïw·¯˜ÛèÔµ›V,™¹£Ï1ú”â‰E{žÙ¸}ÏÄ“„T‚L ¹Ó /ägïþÆŒ¬&äRdÝ¢ñ^ô„­/¶g·GÇÞ}'ðÚº­8~²9>¯¤í¢däW–û±¤ª…Ò{ ×U3Ü9Æç)>FSŒV€8ýVóÞ²§ÄÈ@ K€ÄÔ†Z Ë7|óæ#çÊ«?êSÔÅ^A÷; ¸w@øš!”`Öêç4ÆEØ`y"1ýzÕŸÁ%KDr^f=(ErÞ³ðúÛÛñææø•<‡p$‚QUXqÅ\L›8Z”®M[M$[óBË4ƒwŽ?ß<þ 9Èq¥HÀôbn¡3] :fL‰‰c*¯X4ý>‡è̵ß›ùøêÍ;"̲#Ôs U7%V9ë8~B5V^±e%EÒšÈK×6ðÖL`t€NúÉçßÀ»;ê”P‚RAЀÌ.͇ßE.L*7¡O2–,+õJ654+Žý©l‘I¨h–v»9àìÄG³œ%¥Èÿü>N‹ ýÇ?’a8¬ó&-EkÞíùg“UGE7€ÍÙXw*¿ðe^·R:ót‡[¼\n$Êóù±e{V½þÂÑ„jð‘–á“ÿ0{ÆDÜqóÕ⪫ ‹70 NUÅ=ðz]hmiÅ«omÂþ'(NÉtä”LÊtÉïù=NÜvÝÂY+ÏØÙ÷YëÈÑÓÕGN6}þ—O¿ùîüÓ ãœfJJkÌsf—æ×/ä £á§øå“TS¯Þg¾Àe¶tØ4îùèã/bÿácðù½Vû#0µÐƒù%ÔÈ,6¥'à M†»”ÚOW7RÍH´µ©Œ©5ËÏ´z Ôhn…²}Qah¯Á Øð8ƒÏ™üþËk½Î¥(G†^|ÝxüœçñQ¯óM{ê3sjЫf8…­§ï{é~‹$’êþ7ˆä_½ÅŸ¸9cFÃéÍÁÞÐý7NžnÆëëßÅŽ½¤›Ö´ZÑ#´©­{ïü„hê·ÛYÀ‹Ÿ¿­¢¥“±Çh#Üà(ž_½1žŠ-š†:’<›@€ÙŸ¹ãÊ¿SSþëɵէÒÇÈ>஺£_«ohûÁã«7ÁAp›Qè†â„*99|á3w¡¬¬Ð’ú7Óþ®rÇ ¹òûöÇëo¾ƒB.—×)]’>2ø«*9Ès{ÓýÒäo!î–<Ð3ÕÜŠTG—jŒ¶À¤¢i2Ø´ú ¿Ïq^íbO â'?´ãüäíú=Ïä)â…ðy öbo õûßr‰Â€"’rfß!,ÀT(Àä öX”&ÁS;…7Ü€‚… áÕh9޼șž»iÛ{xî¥7D0G·Ct3ËÉ–®ºr!¦Œ'cÈÍ÷‘S“så;_W½‡MmøÕcÏ Ü‚Kw‹¬^’¥Ä4·äÈïºnOëúúÜ)µ?Ìz{™õèªÍÖÞÝý³­;÷Ëo"B—2㨨*Å=w߆ü\ŸRCÍÒóØÉZ3ÏâÞ\»»ÞÛîPr™Àÿ1ùAiVB iîÑB!iÄHu¶Á Ð0yªiXJîø.«ü_ÿ]våÁX€þ‹A xãMƒž¤d ó׻܀½T5À”D`ŒGvÑ&Ƥ TŠã ¤Èè ¯½¥+o„»¸H­JíÊâ{öÀ¯}Ú3¯L'Ež‹éL2 7\w\.%I>P¯5»—+h<-û±ÇŸFCC+GÇ 0u'z 9L'ÊËùóûn^’Þiú¼ÒëïÔÝ·jí¶G;:»ägw2 'S é=>/&NªÅׯ@Žß-Ý€™÷E-Öú'TJ˜xà¡Çp¦¡AQž™øKW%Ï|a\ÊÉÓHYã3¥’ )&þ´´·Ã GÓaÇÇ ÿò«ƒ–ücÀ^ yŸ¼gЀóà Ì´$—a%ç¸;0L!q\ÆÎ[ƒt?T|ê^¸KJÈ =)ȱÎ3§ñÒêµfŸÕ!ŽÑ•¡ŠŠ |îþ»ÈñªÉÒæû±)eĺÓ)¤¼×^{uû ·'ª€€(¡ù‘"C+ËÏǵ‹§~zåòY¿Ëþ[õ6Msùº­ûþþç¯^Á’Ü:½‹€5dìôÇË–/ÄìYSD¢˜ß„-hnZ¸Ø‰ŠûŸÂé†f<úØÓuwÃÅí”L r^w®"÷ß!®ÇD2à“i¾ÜôÓB‚}Ð÷z(Ø+ø‰›%I9˜kx€ê_‘ÙÖ­§]šó1¥ÔÛÙ¼‹QvÇpÕTÃWRž¶‡ËAny;wîÃó/¼¬Èðܬq+Ü`î½ûÔÔ”Ãét*MÁØ––!<‰“د­Y‹––¸Ün‚’Òý*@ž÷çn[ºæªE“¿ãtz×e‚Kzß}mÃ{ÿó7Ͼ…`Ðg* G""õh4*ç÷~ê“(,Ê•žd[¶HÈÀÜžnʳý¶nÞ† ë·Òköʼ6‚”x˜\äÃrrŸ¼.]2¨rD–]"ƒ7ÛÈð ¸Ì @=ËUº g¯Á^–p’r0†Ãú7±Á[¥@æÜKH@÷µgôX,Y(š3Œ2¥ô/Yƒ‚þöÔ©F<ôÐ#´SÇÒ‚¤ì]óÄáE‹çañbÖÕÌ•â}M¡·[ˆé_n«ø7¢þd|>¿ê1púrxÑŠãÞàÊ¿WZTô-þÓôËì=TÿÀ–]‡¿ôÒº÷“ã‚3νõ1IJ$ãqL ÷ÿK_þ"¹þqë5íø_%"XnÍ-mXõôó8q¢±DT’wB¯1A®¨.ÀO„RVù…ùÕÌ÷Oµ¶ pË/ba‹Viî¾ ý×`¯ÁÎ 4ÿãß¹ÄàÙ+v(ÀÞiÔ°¸dÌ ˆr9º ¾q‘7}6Êo¹Eh¹fR)ÿ¸È èêáÉ'ŸÃÑÃÇ‘ˆ%ÄEçûœ«]¥¥…¸çÞ;PQY‰(OÁ‚qÑ3Ë$Þ2qK¾ÓåÂ/~þ8,lCæpÃðä#Iáš1sRÍ/Íœüeû/e=óêæŸ®oþÊŽ}Ç…8àìm’ »L|`Îþì¹ÓñÉOÞ‰X4j{Æý7¤çùâíÀ GǯxÅ|„°ÃÀK'9µ 7.G@S5C˜¬ãÏl?Úý“m­B⩾f"j‰üd^ó¢ê¯Ã` eà5Ø ÀÕ¦o~cH–3ËV¶²¼^æÐcQkçOÐýK¦$£Ÿôxବ@áìù¨¸ï>¸|^ž8*û‡‘HïnÝ·ÞX‡. œR´š×ÈÓþÒ—?qãÇI~m@9³/Ë…íÆíòàO>ƒíÛvŠ2Óɤ$'’þR åuL®-GMEÁO?{ÛÕ!cÿñ¿=´ê'íí¡¯œllƒCOÂÑӨ꞉Š‹ ±tÙB\qåRkšŽì>E“¸0°¦@‚Àd×®ÝxôáßÂíô(QzÎO'9³0€[GV©Hx 5´‘©¿´û'XûŸµþÌ„ÿ÷éݸ ÙëÃ^\%(þæ·íxÌàêÀP^}¤íLᙊñGiƒJº°W£ %êÈÏCþœù¨ú“/ÀÈW°‘¤I47µ’‹þ[46*j°ðKP¨{ï}÷`ƬéBçU9¶‹Wß>7Ñ7¥zÃÛ±nÝ´ÐkyÜJV?å/',r¢¢$yy¾Ÿþï?»«/üìñÕ?zgÇ‘¿bƒ– C“Á‘ÀŒÀQ#GáÚ•×`ÚŒÉfºãÎæL=u»]himÇÛk×cÝ›kÅýᤠǩ£ˆÐqZn+«Ka¸ÒÏ/Œ§©¿‰®€(4v81¨k–Âïùk¸—àÃYœääà`-†2c04K]*FƯŒ^“îÀ0S„yD˜×#!@Íg¦ºïE ÆšzÅÇøÏÿø!Ž;!ZìÇ)åE/_¾K¯X†’’R„‹ž—=k+­ÀmJrñð¡ÃxùåÕ8|ð|nâL §ú~Þ”1ÿõW÷ßøU>†XH<Özöí߬^¿ç3y>¹ÝmТÝ2¬›fΜ;î¼…E…i­ÿ´Ü—|oÍA¿Àòù}8rè(^\õ"Ž>ª\)ÝD …£}~Œæ`AY.Å+kz˜çev…llÁQN$Õ´UËpÞõa‡eÿúïƒFbãgª+ª2%Ú{ q5BŒ=Þ„!›¥An}`ìx”Þx#Š.‡; ,¡ZæiÓr;]xðW¿Á®»Ø’¸çר©©Â-·ÝЉ“&³¹øyÙÓ´,92Èx1 ½½üáñ?`ë–­È¥ÏJÂy#¾„(,¸zî¤Gî¾~áçJŠ U&¯µ½ý/{qã×ÞØzp|¾—\†Ðñ¨'.®¼â Üÿ™ûÈûŽ¥³iÛ ЭJÀùW ƒÛwâÉÇŸ@o$,ôb[AnÐô¢Œ-ÌÃX¿#­­Æñ¿Æ­•Lý=Ó(ðë“»Å} ̧ÖsÌ}» ²>Là5Ø¡ÀP÷xñÆ#}/&b C’€qºW{’ ´19ðÕT#Ñ"TÞt¼Å0x7×ÕØ/f¾ñúÛxë·ÐÒÒ$³/$ä5ÕÜŒOß?,\€îP¶vGVÅ­Ï ÛGy€%³äøsð…Ùo½ñ&òƒ¹Ògcº¼Ðr+Ð1°tæØƒ·­˜ûÃÑ#*,Gݵïè¾W7¼7qK]=üÚaÛŽ ÷ŸŠUE®]qî¹÷“hïì´2¢Y'¥Y³þú51jYðEó¡oz{=žüýïáô{á0™J Œ ø°¸¦JK›Šª1Î"ü“” º:‘d‡¡qƒ»ÿÂÏÎÐ/ÀÙëÃ^ƒÙ¿0Ô½^’ë²AïskpŒ§ˆ' *$ົ»¬éS0ò¾/À[VA›iB5ùÈdlGŸÀ³O=ƒƒûö{nÄNÈ™s÷}ŸÂrÚp™ÛŸi ÎEF/@ƒЭ„ ªÇåàé?<…7^{ n‡“íDŠ< GÑ(:W'fM¨ÁU‹¦î_0cü$9âS¯nÙ°³îÄâ#§šà4zÉå>(YxNør‚¸âš¸zÅ5ÓέÔv³.ŠMèÇÊžÀä’u¯¿Õ«VÁOn‰.M&¦pCíHŒ+-E²·NKÉ„Ý&-Ò“@'Á@ñ• däxÊPC†›_l 7l/ ñ›ß’eÁ>=–F¿Œ c/€6I.öDU‡ Ì¬ øáª©Ä”¯ÿ¼£ª‘ŠÆ•}ˆ¤“‚zñð/ÂÖw¶ Ttvò¢¡®\¹W\}µxÌR ÈbÚŠäΑð¶ÇšJÅÈO!õ;ë߯Ú5¯£³­&‘ß쮘Œ„Ç1•E˜1iÔÆO^¿h‰üÝÏÿðê†#Ç›Ÿiꄞ¡÷d”˜¥TZ^«¯]‰ù‹ˆÈ`ÿAÙÉ‘s©«ðcÌ,lnlÆ[kÖ`ËÆðù”†y˜Ž¿¤¬·NƒšÂ|D­ãKé„ùÑ^òF:$À?ó OÃÒûÓÍËp¡u)€70 V.€‰ALj«/(™Dÿ‰ðä T ½äþ‡É`a/Íí†`οüü´¹%z£"«' ?²ÐÜ7~øï?Å«¯¬F~~¾ÚP)vç2áÌY³q@õ¨ˆ‹¬øù«[Ùv—Ýà%o{÷®xcõÔ?Na†GBjõTh¾\çûQUš¿ñ¿ÿÉí ¾÷Ëç6œiéZÜÖÖ#Ô‚žS%ËEQ;q"®¹ö:Lš2‘˜=”öH{®§–NA¦Go›VíT~—§úz}8xà ^_½êö •8)õO+jÊpóØ($ÔÜpŠýSj¸y)æxˆà§5IÈ4¬AI—à¼ëRÀ`R…™púó÷_’ó~?ë\D ™Ha,ݲÚ©Ãq®˜ÒÀêAIÚég~ÿûÈ›JF—0…ÜK #7àÁÃþ/<÷‚4ÿ8xÖ…I F×Öâêë®Ç”Ó„{Öp]Ë®äg +”-@É’{¼²³:¼ñÊ«dw¤Ç›jnÍD8ò)Ôúôy6þßÿþùí6$ mqo¨‘–“èi8*ùÅH4‚y âZ:¡òÊré @öÅ0TâÂFF³¨¢õ/mÕ~ÛÞÝŠ5/¿‚Ó§N )‚3Ÿ~BÊOŒ.Çõ£Êôº—™'<ù‡b&fþ10ÙÒn)þZ‚I¦þ±3~^û¹õ_¿‹È–Í—äܺú¡E¾) ž¡p•Ú„ÉÐE=8ÑÐ)ÿômΘ ‡Û#_0cÖOÀê×à©'žÂÉúSð¸ÜÆ'É#.,*ÆÊnÀ’åËD2ÜLWÚÐ'ÛŸaÿÙ`¤Cö¸Ï­!cëæÍðÒæÊ³`ùäTTCsyPSšÿÖ?ÿ·û®RðO¬í'–sÒ­ãô!tŸ9&3ô“_ÿ‰å„8‰gˆðF+*+íׇ” )–ž45'Ás_Yõ"^|þ$bIHÓ¾¡£Œb¥OÔVથÈõ{'ÃfÙ1¬òCèÇê?­Vï?b4 KSèãçþóŽÀk0Û˜‡"1èB° ‡A €Ïé›üo¢`ú,8óóà äŠp ß¼Ÿ ;·ïÆï~”Bâ-ðûs”æ@JIƒßtë­¸åöÛÐ%]¹¦ý¥t dƒé©AZzcæ4 ç xvÁ«/¿Œ—Èîr‚A‰YòJk?¢ ‡“G•þú}+¾©uu†'þÇ#/ý~߱ƎDšîAgóièB¸÷þOã†[n °RÿU/h@:Êök/Piÿ™RûÌÏÍÅoó0žöyú>)fú¤tL,*À㪰°¦”\/=® ˆw“ãŸP7@›jF2­÷\€‹­K ƒ0=¸á/þì’û@Vv ?0Õ?JÆ"ï¸'nZS„âRªÿù/!úlø*+á),!6Dž†uòäi<ô‹ñⳫK¤ìàtìNºçÙøïÿÜg….,6¦ÛŠ[fzØhöyȹI¯‚iUT"ð¥^À£?‚Ü‚ùóÜ¢2”ÔN¼ù˜P]‚/ßµ¼Y;^ßòÆCϬ]xèT³/ÖÙˆSû¶£7ÔÝp¢»£ŸÿÓ/á&A£Nô­Gö­MfÒ™¤„¸$2êÇÀc<‚5¯¾†ü‚<™”LX:¢·M‹éÅÂ4ä±' E»»¤Àìee"£O¡ñ2\x]JàÝŸ½€ÁZœ:ýV1.«Äe»âi ÃîN$) 0ÔH.3)-Â5·Ü†¢Ùs‘W;ÞÒ ©lñâ€Î®.üâG?Ç#¿þ- Ón}gW'®Yy-î#àÄ¡aX’död¬~ ?[BÌ(bZ6X—KîsøÕ/~B€yíÞœ j¦Î†¿ £ËŠðé[CÛ²ë`â™×¶9Nµuk½Mõ8¶}zzºDn˜kîŸûÒ±â†ë-ÈrõÓT3"¦ªïIÑ‚%[OÆÏÊ>Ü*ùøo‡µo¼‰ÜÜ€5o-…OÐîß¼˜T^J¡ADØ}’X ã×"Q€NÄÛÛ¡…c’LÔúi|Ü@`¸¯*º‘«Ihh‘‚Ô®j™^û¾ã9lÒ rÝ;)ò’ÒÞŽ@ eW_â9sQ0e|U5JÙš †ìÂçsâßÿ1¾÷ÏßC9Ç媎‡P(„ÅË–   °@Â[‡À¡YC„Ó'’ ÂíÒ¼aå ‚¹xýµ5øÍC¿†É¹;·Ï‡Ú¹‹‘_> ey9¸áŠiÐ^^·Ã|}Ó´†¢h;¼{×½N.LLê•~ŠËïÿÒpåŠkâžü챺6¶+’IHhÖ€þæ&Ÿª?…'÷8¶lÚLñˆŸvsM2§÷ϨÅç—ÍØÒ"b÷1ÞF"@$,ôßd;y#‘Ô„våêôÿ >.k8À`’‚ºžø½‰eZ$—³5&Õ¤ eì´û3$h÷çÄ sŠçÏ'˜ƒ¢9 9Š¼Þ˜h²/[”ãÆÏ~þ[ü¯ÿñ¿ æ+µ`æÆç3kÎlÜyïݨ; öt‹TgØfgÝ÷º½év÷¼òtä‚X¿vy¿AWG§kìNYv-Êj§ (àÆÒ¹ã =½æ]sý¶:tG’8¶m ÞYý4<LrÑË*Ëqÿ—¿€%W,COw(3ñY@VFRÁ˜™UÔd&Ú»›¶âé'žÄ¾º:øü~8 MCãsÅ\|~ù\”dï½0N8Ø{ ÝáNj1jnªúïùf»ç5œ`0Ï«\ 2+‹å–¡Ák Låöw“½p% j$eŠP‚~§`Ây(¥=8¦ òlUi(ò»ð뇟Äßþõ·‰$Dd‡Ù€¬ŸdéçÌ›ko¼5£GIðBK¤Ã5•ÄËÎ ¯×‡'{›Ö¯GŒb{]Ä) 7öÀ×উ#ŽÇd¤²t-qf•€p˜Â£+D9•ž›Þÿù8­á œäDà`­¡çVçQ¹žÌ@'y©]´‰rïWÐ¥»½ä,ƨ»îFþôÉHE’*¡HÇ ø<ØûÞü쇿ÀÓO>/ô]QÈ¢c±TøâeKp@49€³ÊávYV‰Ðï!8~«_~;ÞÝ&¹¸$y£gÍèYsQ\X€ªÂk–_sjFÔ+»àEÊ@F!æ7¶ê™ç°õMäE„%1,øÕÍËqý˜ BθtQ©ÖFº ÿ§Xú«»G}Ym˜Šo ÉPDf\\†l8­á ¼jþðÌ k(5{€ˆ²÷> BMÍ,_¸c>u fM'ˆ§—ã÷à½uøùO~‰WV½Jž²GÂnÀc1On fBP$KS€Ó!0â,{°„ÐÀìÂæ†F¬[»›7m‚D,Šê©³P3uŠ QSZLð«UæÉ†´¶¶áÌ=hØÿœ„¬HÂåˆ9óçI{a"‘¸è…Ò³&ñªÄ©—Ë…Ÿ{»vl"„ƒ'¡ÒóôƸf®U†nfHñl@»¡1–:0Ï4zÈ0“}ÝšÖrο> øø–Ïd{]‰$º)ˆ¤R’H0×%GÙ¢%{ÿgP4k&ýµÿ’ŒÜ‹#‡âá‡~‹'{~_Žº÷9¤ˆqþm2>õÙÏ J¯f%ö ÕOdMËè{>ª)XýoÆlwÚD·¿û.Þ\óœ.…ÖQÔLžŽªIS‘ÈEQ0ÚßþÛïÌöPz{zÐx¨ ëàt»%)·üê«0eú4á§ Q&å?:)%Þ¤“$ææÉ§phÿa@Ùd†.”Ÿ,™‚kF” Kz€”ˆz{``Ðy@Ü&GVà£.>—*?Nk¸À`–‡¨xè7þ®ÄÉH¤I$tòJ,ÂØOßâ³ÉËæÇŽ„‹ì‚z>õ‡çðóŸ=N ]äï¥p¼vÂ8Ü{ÿýˆÓF™€ƒŒ¡§ú“â¬6}CWß³ËÏÝ„uïíÁ[¯¯!p˳ò±“Q1a*<fx؆þìï~j&ùMÐÉ5Ùæã‡DZ˜w|öÆOš(ÝEÝ®TˆF "%p+â³ÇŽ¥q_ÈÈy×ÿÏùcqeU: \|‡LKáö£·[¡0]^µÑgÕa/ÀÅ×e¼eZ-ÀúE “¼€hÊPÀ ÂhÅ `ô=ŸFñtöÂêO5¥‘ÑêÅ /¼‚ŸüøŠû°³ú‘H£ÇÁ­wÞ.I@»öoåýÓ¶e×åmH#„lºäíí;€wÖ¯—ÉALʯ‰ÒÚÉðsÉ#Cûüßþ—éÐ݈„ºÐzâ º›NÃÉèA¿÷­›¬éì@ûÉ£ˆv´XÞILŸ9 £jG“»b+ºÀ’„„¦˜Ó/‹þÆéq‘ ò¦´'²7 . .×L¿3¥‹KsÑc8±Ô›Ò)Cdø}@‘‹l b†õqZ— ³†ØÀysôI©±àI3©`î\Tßqr§N§-bm\yôÐý½fÍ[øí#OÀKÞ±iªFî䫨©¦üJ ÅuËÀe×OYªÜšÚp ˜iª°f±p8ÙΆŽ9Š÷vý¬Q˜_=ú7™J°ðSSXBíè:s±î68uvÄ”©ÓP5¢z@í¦pòO—˜Ä„‹âþoo@cC£R&1•ëÎ"Šÿ41‹ üèI¦q3ÈH²Û±â®èv¢CO¿ÒY¢èƒu2k¨{ ºcäðÌ@ÉõkDP0{*o¿ Á)Ó„â®AÉŠ»z{"xóÍxüñgÈSöZd7ž†—@YE,Y$T`‡Å¬M[ WÊL é©”•'°àdýIìÛ['!·Ôûr [9žÜ"r&R 8öŽww¢·ñ4b¡8ȉÆM/“K9£x1Hw)[´EÍ"í0òlß¶ ÍMÍ’ø°uÕÂt¢7&€ùù„ÈèÙE±}6zIFzéߨ¥+d7õ—Í.Ϙ}žÓ¡¥C£þk(r.@fõ«V8óò³iÿçÿUW_V2Ͳ53?ól¿”D¢––fMñå’vœbþÎ(}YU€¸ˆš²ãçÍš‹Ò[îD€¯‹(üÈ Ë80€õë·à™gž‡‡gX¯$£/(,ÂÔéÓ$TvÕsÃݵvû½Ý„—MÌÊe/¾©á <,,[&ÙyƒyÈ)­;X@à•Ì@²§±–Äz: ‰» ¡fd5JKKɈݪ_ù‚ËÒ§wšöz‡ûêö¢­µ]< MÄ SíÆœ !¡F'çpføÍ¼ëSäþ€ˆ’!345XA: ­B·î„s€jBZ@ä\þP[— ³Î» vû©™u÷÷gÅdRe¦u=ë>š5û‚oβó9¨öt]4,â´³¶‹”‰A" ÆJ˜9…7Ýœ‰SaR<¯Æèi’g‹Ðó›7mË/¾"„9[Ù'I ’K†:jÌ(éë—hÚš ##b¿SÛèMdlÿahmnÁÉãÇÉ‹fª±wNÞ¢r¸¹ê\l0z{èhB2Ò­jò´———"¿°ðÀ±#GDÝÄávÊs‡ µºº n ›ÏuŸjòæõMèõííh>ÓÓéP99_.Šÿ5®:ðûøã$w;Eñ¿ «öÔ¢âsƒRS4Œ _RfëivIBæúñ£º„œ S<¯¹–¢¯A ákÁ$fð 8T?XžhD­ …†®‹8BÒÝBnÝ´K¤ý&d$ aoç½€Ôêל1° ç¢+—Œ?ïžA€;oœ“z«ôÛÿ¦_¹EW²èòíÀªCINVÓ}Ç 3{ÀMºËÎþ\Ɉ´ž°ÈÒŒœ¿ àT³)ↀÎXJª¬”b/€ ƒ{Òt䬸 î±¥­Ý~®´±°ßlÙô.\äeÛ®+Ͼàœ@aaá9U°²UÎMSÎ\Ÿ0m¦¡î*3ÉΓääÑ¿~±qí ßú©¼-ƒ#‚#•x›/:—&™týlÍÿ³×¹B]þ¶§»GˆE™“$£§ ð§zÓq„9þgÿŸPQhŽ˜<ã&V²Ox7`Tôº3Ì [¢([§”Çé€6È~>8²—Úë%DõÓ÷5°DËŒhb$Õ­ÐÅN7Ù!Jÿů¸¹W]?(çÙðÝoef8ò&ª0rr hùz÷qV½êf`4Ïq³o<3‘”¾þÒ/þÜ£ÆÊù7þçÿ!/0’>7EŒ6=™ i‡?ûüújV^xñ´ö:è–»Ÿ¶Pàa4ì‰v…•2U[²C…LçnÖîHÅÅ+0U=ž‰Óá½ê8ÇNŸí–Nav"ÇáCG°}Û ” ßGlw@@µlÞ¿qìÿñ@ž°ÌÛPy‹”Û¤ŸÀá±C€+¥q# w¢.MnÝé÷ÿYêBª“ãX„ÝÍ>1zƒa͉?1Û0E‹8$K™¢pk›I;°<3ø “+¨çä¢èVyÐÌꓤÕÉzè¶Öà]ÊoƒévÃ&7&Ÿ *£QÐçcÈ>ÀE_"¸ð*]ýÁϕ֙ü#Ò.­š>™Q=oþ£_ì¼+ë÷ ;9ÝýExªGøÌþOŸŸíR—‰ì›_U…²÷ûì]òâoðɒۖÝY ü|rÿɸµžR'[e`­ªHë¢þÛB¹ÿ세x¼¡1€¹'΀çÊë¡ S ãp¥íØ±ãØ»k7ÝB.±áÑÈ­æ”êÛ] 2aˆHƒ=múÚ7þåA³»7!C r †L/á:'»|’†a(Ì= }5,NÀMAiÆ/JwgçqLˆw!Áî'šÚe#q˜±ˆ€«ãIüB®kA.Å‚E0ss q £Ÿð1mirݪ V¬ßïfìÅÆÏ^À`¬>p‰Våû§A9NìÔq´=ùÐyží÷Yj™P ûÙg.Îþýþ9#;åËS~S'š µtʽÇ÷%ù2¸îÓ®˜ //ˆÜ¼…âzZcZ†Ìë¬)/`I°'ÌúÆ.ô†“(8PଦS.@wwÚÛ: ¢éZéùK’Û´CÙ'§£¬´yùA)¹V 5Fß/Œ”ºÜLD!€VQ$]Oƒ–Ý"k8@áÍŸ‚·vâ>N¢¥-þô’žû@—Ak9´’ÀM@t¿óP÷Ä•,xRî}CB†hy5RÕc‘5 É¢F©&pA\ª fF%6×,¾óX¤©©ÍÍÍç ìÕgV`ÏØî’ÒÌ—Ë!€ÏåÀÆ޶v£´0ˆ)£k =»æ]óííûqât+Æ–çcêˆB$’JÒƒ'NÔ£ÕjäQ/˜=’X¥Þ2îˆÝ®›ÊŠQ4䣪ºBÆ‚±è¡ðúéÕœ8€Ê“G‘ÓÓ _8·S%>8a·1ÊÛ"ÐkJ`V Ê wˆ¬á e_ük8ró?ðqzw¼ƒ®µ¯\ÒsÈâZ?sùS‡O³.Éê3@ÝÓm½œ»’ÝZ‰ØFÉøãUc¨dA‘5áÚ”€‚ÿË÷¼Ç*k¦-ˆ‰s¡œ>݈¶¶6EÙÐÎÙžf±9<áŽÂââŒ9BðL(r;tì=Õà ¨*+À¼©c ½²v‡ùúæ=8vº µôà”Q…p9±…“ÌTjhh„ÛíîóBfZ!»AW%+`¥Vè|=jŠÉqQ®ÍÓS¥' ôè>ä¶7S|bWà‘DŸ°øøBÅ`t¤sàøgÕã?k¸>À`¬öCôÈþýœßOÀ‹‡ÓHyúèh!¤Èƒ²¡‘GˆßBáj8©šñ™8Ä1~oítÄ+G"^R‰d _BÕ*ï”~\Ÿ†\¯ )öH+>wÎ;v¡P÷YU€³ÞGv>ÎfššØYyy1jÇÕŠâ°$Äé5wŸhÅ‘†.Œ Í~Éì±Ð¶ì<˜xêµÍŽÃ'[´±•%˜:ªŸEK¤c×ÕíGý‰SðxÜÖ\CGZ¦Ø:…ô¿i°š2LKʇ½‡ñãÇ¢º¦B¸&ƒ.·ù4JöíBÞ™cp³×àpÂðz¥$(Á»H‘˜”\„ôãqB/¥ÝŸÞ˜é÷Ÿàã´†+ fðR÷û)Ò}¦{÷xÐÕƒ$…·qòZx€¦bqö|»¦,@¬¼‰Ü"$ý¹ÂÈäÒ nªdxQÐ…â\/…ªêÆÉ—Û!»ÿ¡CG/*ÅÍ&j[ŒFX¸¦855•˜õú½‡OùÆW—aúØ ¼3°‚Ï®]{pøàŠß½ª¶ XÜvXhg×ÿS–H AÚ ~ÊÔI3fât¡8ÕÁ.”‡\ÿÂ=ï¢ààn8)bî¾áóKch§ÑÅ5ɵÒèK8øtqÅ„¤E0‚9p¤.ÀùÖ¥6~ºxçgàR¬K‰ˆK­¤ê¹§Za„z‘ Ç# ON •6©˜ÌÆà?Rý ­³®B¸´)º§S¿ÚÄ,ú²ƒ¼Üò?Jós¤w@ä¾éqσ£Çê±{÷~I†C»@g#7øØB³KÞÜþ‰`ÜØ1˜1kº5^Ì@yÓ;5à0½‡Ic*qÿM‹È›é OüÁ#/ü~Ǿ3FV”`&ÀÈÒá3³vùŽ{°ÿÀ!á%k}ZŸïùd ‹?ÝSÆÉX4"'2eòx:±¨dP ºB¤ü›¿k31¦Ç+mÃ,Ê”aƒùÓ ì>ÑóŽ¼ @a€Q„#9<Ê{]ØÄD º˜üÃ$ K±ìÌþÅ–ô ‘³ÛÞ̦v¤zˆӭǕèXJÕÿÛé^Nª×J‰è83ÿ„‹*$±m8݃OmŠ>¯#Jó r$Ä¥¿b‚ÎÞý‡±cû{äº+‚œœÇyH?v_ŠMb^5N¾'ã˜8qfΘ.öÇ'vª¥ ï>ƒcgÚ0el%¾tDzf± ¯ûµí=ËKŠò0kl¦Œª”ØÆE.÷Þºƒò•J%¬É?ý/›•P­ȪI¨“äl(Àd2þ©S'K~AÉ,«7³m#‚[Þ†“Ë!Í6ô¦é‹;´ú€hø}ŠPI¡ÀÅg• «5`°@çäÿˆKeÏ/îAšºòD™þkö’!µv!EaiŒþ–§qÐK ”Š‹B°–'Ž-ºáÂrÕQ åmÅóO•–äú1®º%ÉTR6O‡å@ïÚsï½·~Ÿ'›ÿ›uVýKÙm°º5DÇäIhÓ€…:…×u'šðÞ¡S¨olÃŒ U‡¿vß5ß”#|õÛ¿ÚŽ%»f¯Æ‚ÉãD•ÄIpøÈ rGö¡‹ÙJVr°/Xi§<7ðˆãÑ£ª1uÚdæÉ•Á!.7Ü[×óá 8»BðÒ1 f+¸=ªÉ‡/·Gcb°×`r% ²®‘å2Âüã´†# –û©Øöz_ÀLئ6W§uôX%ÁõˆhšÒ Øk&Ò}Ц¸æn\| z Ë ³ú.´´àP4™ÄتRL¦67è“’ïÿÜX¢×ØIÆðàQòÀ=™&¥,cÏ&ÙÙÙÀÕ1®äç1uÊ$ÔÖŽD*’MuDZë`=ºè5FW—¼õÿý·O]%Gýîƒ/l8}¦}1 L_‰—ÌVàvãÔ©ìܵ§OŸËéR/Ô§g7gg²þé%úœ‘Œ¡¢² 3fNCUu9’.~Üó]˜o½†TC# 8ÇíMO b°pØÀ*¬ôÚN U\ä©ÉúGrŽí†ànÀnéÿzPÜÿ¦ÿ©îÎýœíuö ó½IMU£N5Áà‰Õ=ÂÒÆÃmÀ=tsæŸÅ@"ФXxÌxuùqpÞõèÉ-„žŒ«¹©üä0Ê‚ic1­¶ZimªaÅI\#…vŸ¨?E!€;}çnsΨ¥{€˜ DPUEö6c ª«*¢óävã—6¼‡ÝGN A(/ØøÝoÜ»DŽð³Ç_ÛpäDÓâã§Ú0™ ë³7/B"¥tþ;Ú;°sÇ^8pnKÓOjðÂÃ'£dÑ Ñ<{rT¬?Î\€Y3g[2Ýæö>ˆî·ßFÏ¡ý¨‰¶ƒ_ÁÀ¥Ê…\5塊¦†d&ÊŠà˜2‚✤¸6F:©>XÇ0u † Öù^ŠæŸ³—bÞÙÍbro¥|b ^‹$¥þ¯ó¬J2ø87ÑÆ"C‹ßßÁ•­”*ñº IO.º Q?~¢9¹ä$å~·Ž^òn^>ÓÆÕžÄ¬™~Ü.ò¸ÉEß¹cš›[ÒÜ›ó/«ëÐ>W‹wÃì˜Ñ#0sö4”–•H>Àãðâ×/®Cݱ“¨,.@UIáÆ¿ùò­ žzuˆûŽ-Þ{ð$&Ž!¸u©(»Y·,Åöm»±mÛ{ä’¸Õ‹òœ>æ3qížLÖh`]µ¬ ¨ª,‘ä$C5k:-Co:JFªzëgêѶqÚvlǘÎ&¸t5#@úøy’0}9â)f6Ðñè{­(Ž Õ"]¦9ÜJ©Õú ÏêòºÜ ø¡¬ÁÚý9öo¦Ýÿæþžóµ5œlÏÀ´dÃ9ö76@ …$/£»7¡˜1 B–°qOÕò壽¨'k¦"é н®6GÓ*[»Éý~ÙLLª­B8šTÀ 'áõx°íÝ=ر}·(3'à¢+=LÜÓÈÎ"‘0¦M›„9sf  Ààò$ÙÕ¯ž^ƒ½‡ObJm ¦Ž¹ñS7-V°sÿ‰}¯®ß1qý¶ո禅(,("p’ÛïĦÍÛðÚê7Ùm@ÆÍÏ"ûhH÷9g2a‚!ôÆé³§bå W#F¶Î G¬ØÓÜ€®mÛнm ÊìWªU,YÅ\ujÐãFØýÒ ráSIÏ@x=R`æ tpõ—Fº Cú\/uìo/[;FÃÙša¦‰5bX]÷×7ˆ,3긧¯'ž’/žØŠKx*‚et߆…h¨¨ESñ$ÉØÖ½©dâLTWãÚE31ª¦ QÞÐäÕy,xŽØÙöí»àáp{7®ÊeXãFHÒIxõ5W`þ¢Ù䘧D²,ÔÛ‹ß>ó:êŸÂ‚ã°|Þ¤ýKçLž$/ÑÒúËÇV½ýµÕoï?aL n^1ãFWÃE€ßç•Ýÿ¥—^…ÛéVî¿Uw̦0ž‹[rtê_%N8žÜÿko¸ >‘Õ¢SfïìBüð!D·m‚{íëj:îöH%‘4Å Ô,oB' rV—Àôº‘ ú¥oá2ô]&0ó¯äÓ_ùÀ»ÿGÉûÙ;;lÌ~‘؜ï=ºï´¶.$Ï´JüϽþQú QÜâiÀIÙH 08,4'ÚrKqlätJ‘KÕ¶n·«“ñaÉìÉ´Éæ!žHYó9‡àÄ+/½†=»÷"à¿ø˜u¥¬g¾7ù. ãÆ›¯ÃìyÓî S`àÈÉF¼ðê&ì?zWÌ›xðæ«gÿp˜?Ûˆ%“Úožzó7/¼¹í3#«Ë°lÞd,™5N’nú™ôÖ[ÐÕVóÿ,¡ÂóëßÙMCzºIÉܰhé|ÔT—‹»Â‚F®”ÙÞ‚ø»ï üøïÅÿr’ûÏ“S¤3¥’tÕÄ*¦LPÒ½.h, –GîMaPå Ò|ʾĉË0ø‹ßURþÃÆÏ ðQ,žè£›ÆY`köÉæÅU/Nüi†ÑÞ#º€<øSÒý§È?JD1üS’6çWàà¨éˆ¸ÂzU*9†è¸î³·_iF‹îïÐÊ7ÐÔÜ… ëÞÁ‰ãõ™9XZz6Ó¬x“âb¯××.§ wœ„‰xwÆú-u8y¦W/šôÈ×Îû\UEYÆoÿùãk~´~Û¾¿bÎÿ¤±5¸ëšYð{U2®±©Yò'Ž7¨jß9ˆ@ýW¶`R’f iS'`Úô gÙTCH±¢ÛßEËÃߌÁëP“N%sÊzºjâø+-n™ãƒ^V³,Wy ©¬àDË$\†‹ñówÅõÈ™µè‡~¸ñç£Z6sE¹æÊêu‹X›Î#1/¥£©ÃõÐȈX¨†õ29‰×F!­Ýþk˜*Æçø?êõ£9¯j¦ÑÏ\5³Ü`ë5XõîÏﻣ*Ëã·õR|ïÞs{w@Wg·èY^lÙcòÌ4%X©fWV–`Þ¼¨ª*—f¥p4Šg^ߎ}‡N δQÿõõÏÞôU Ë>þÿ_½ø“ÖÎί'W§¼¸z×ry,¸ÉÔç^™b&'°âÈšJ,]:Oæ’)ú™y*H]Ÿ~ ¥-ðX˜Ì=ÓB⤠ÕF,ñ™=(¢¢Zy…®L gö—‰>k¨À`qþ?š¬ß•QθϺmDÖ®*d´–.$ö—ŸEäÃàò_­ä t3˜*~go"îö“Û_€¶¼+§rS6OŸžwн^RT€O^·%…¹dŒ‰ô¼Aöb×­ß‚úúåå꿃5[!ÝÊÚJ@ãÇ×bÒÄÑÈ'™í0‰âÁ§Ö¡¡µ •ÅyÈÏõýôÿÅ'ÿBŽaì™5›r¸¾é+[vB~NŸ¿}ŠórXÔ‹N4‰S'È Ø«”vµ¾õÈ €iñdV]¸¢Â<,_6_æ—ëê%ΊÕ×£mÝ[(=R'}\䱈.Ö ´ß : ê/àó()€£4fÐ ƒµ õ¼#k2Ìp‚¡ ƒeüü¼tK•ÎújFÙî¿z"¡à@½Lãeš-7¦w‘ñwpû/RJœKÕF!_Zh÷ïÊÍGcao_J—«>·“'ÖbÁ´1È øÅ+ñ±ëÖnDK[çÀåÀ­ÍvµÂTS…fÍš†‘#Êávq¾N§·Ð…Gž{ÎL[å?ýÜ]+úÀžÃ'ØúÞ‘/=ÿú6æqÝâ©QU ·SábKk¶nÝ#±¹êvR|çþÞÿù@r'§N‡‚Â|ñä·9~ïìBôPòÞXGo* ;JQ$9$HÙC+éxfA~:˃¤¢`ÏPà2NZørà-Nôå’Û?l?Ž÷Ùø?Š’_ÿewf—ÿìÙ¢ÿÇî9ËÒÑ®™\¨ öí?†˜Œ8¶IøJè⪥*là7ÌãŽËK P3¢ZÆ…sV_¼&Kt¶"ðèpvu@ã‰Dà˜‰€@ÀÉ2Gš•7`çÁ9^˜ñ’2Óàp€ÁRÕá5À<ÿü•·ŠÐ»ýÝ÷ãç%š€)•éï_Á樔ÇÒ¡̶.í"ãÅ®y˜Œª• ‹BõÌXw*ަ¢j¯œ€°Ï'8`U§R—ÑQšŸk—Í‚‡‡íÂJ>ò1ÈHOŸi™ÆV$¹D®k€6°»ÖžÛ¡Y6Æ65yÊxäýrün.ýí>~]aÜsÝ,›=þ{U•¥ßRg-2Âåk·îûûŸ=öê ¿ß¢@ gÔ¢0/(n747µ¡µ½]5GhöËÚYÓ‹cRn—Åì£Ç&…ví¤•ˆá;äúû{Þæ3pijçgãws iVÿ³5‰‰Hì*åŒ,ƒÎÒÇÜN'˜W€ÊÊ2²1·ä0Z»zðîÞchêì¦Í;‰ûo^ºæÊ¹“¾ãøÖý6Ç77í½ï…·¶>ÚÚ¢ØÛ‰+fM@Yqâɤ(¢ô’ ÑÜÚJïמʪ eÍ<ˆt¸iÍö«5^S1i%èÓÐüt£x@ †[vBW™àjZ¹‡å¾¥ä{ÍO{d¹„LŠ0¬¹Žadø¼SV›×û.é¹J*à®IȤAáöóâݾóÕg.‰ÂÏ»l‚Žfõä«¡²ô}{8Õ†ÙB\&þj"þ&W¾-C/}ï€rÕäwåàTÉ(´”!áôÈ|H¾C9ÈM&’ÈËÍ%zŠŠòÔœC‹ÆË·k,žÀ™úÓ²ÑêšaÿÀlÉVë–; × KJ‘K!<“鸜ÞL¶a÷aÄc ò|¸fÑ”OßtÕ¼ßÙÇèó*¿_µéÏÚºC?{ggˆ,˜Z‹Šâ|…VœåŒ&dˆ·/ª¡8oÖÿüg­æ¦óóà#/Ãåp*ÅcïÁ»g;‚mð1ÀXcýP’Éü JËÔBW zE ´2 ÜnåreË” ƒ€ Ž0jëöˆ¬¶“¼Áò8Îõúlü—²Áçý¬>3¬°Ò´&I™,ÿE±?Èõ§M/J7QŒ6=ýŠkÂü‹q±Þ–\äœÉ¯Â©²‘è æ!©«¹{Ì ` à©[¥ÅŘ9}ªè\VÂ\òZäQ°2pW{—5+»µ÷«O9žéöä—ÀÃå{«õ°‘B˜Í»ÈìÍ9ÓjŸëýóÏÞzíÏÓï=û€;ëN|­¾¡í¿²‘v^c«JPSVÛ)'Ç1|OG§484ÅC”{_»­â+{¸˜@w¸Tû$£nÜD°±ùû6"xæ\Lüar<2͌ƥ˜\Fd<à¢Å…0+ `äøàL*pH6Yih›?ïü¹WÜ0¨ÆÿQ.6ø®µ/é]Ÿ—mr²ñó¿zúÍïø<”äady!rÉͯŸ‡!ŠŽyDéšê"h¬Ps@ÓXMað²ÚXl/OG7sêL;Œ&úê Ë€ÞýC)ÑTRÔ˜ÿÏCe^Ý‹.z¼nôtœ*®¦û:%’áÊ0 Ù4ýþª«*QRV,“„4ÑÕ´F²”X¤W fO›ÐÀîZ¶—Ê£i.Ú}>ù™«gÝ‘N4t …˜X,‰Oß´àïGWÿzÚÄq§ÎûJ¯oÜ3ó‰W7ïˆs›"¹Þ£*ŠP’áBÛFBÜo~£¦=‡ï}€ôra•<žS®²©¬¤êD’Ü˜Šƒ»<²þÎVä*¿À]‚2 ª2 zéL¯äïäþŒ$U&³Ú˜ Å€Ýý‹á³«©Û9| ßZ†f3Gm¢Ž‚NÚ%Ž7!ÕÒ =—û)Dß•àÆŸz)òñ“äwœ†çÔ6œ@uo·d35ÚñšS4ל¬©®éé®NÙQ’O@1 /…~_†Ó}}q=?LF=²oÈÆø[IN*›}¸z0xšoW‰Óm0º{Á» t¦R¢ú“ çyúoÒö,éÞg—¿5Pˆú¢jôÐîË­¿V¶Jy¨t·–VÔ ¸¬œ 1‘.Q3‹iÁ'…°ªZºêI³”.²4Íò]¬{OŠAEWãÌéX-! :áu»1c|&Œ)[¼rÙÜ>üë³^å­Í»g%Sƪ?¼¼¥¼;ÖKò(¦/“ QGžÏ ¿S•å2;ÿ@pªË­Y3Ð;y>]hÎôsØÃñ“'ÑowÊë`ô™CÐ9«ÊoJ'äriWÙ¥]&ë¦èEù@AFAœRjš Aà Øàã§ŽÉn§¯¡RËÿ K’ΊZ÷ÓÍy"µ~¼©Ž$ÃQÉ#Eé&j#ÃíŽ&$ù²©ýì³Òßôzsp‚Œ¿-X€{©6AŽ_ƒ~ß,D^i%|þ —ËÄÐÕ“´+»œ"Áﴨ¦%‡Ïv6°=ÕPy0zѸA¶¾ ·&3ë¶­;Bî/‡ðÆ+g6(Ü´béœ>®ÚY¶±³îH 7¿ów«Öý¨³' ªüøÝjâ!\®×- XÂ(“¬bY®×E¹®|w$F'ž7Ë£àÿ¹âaT׿‡qwKïM3°—AÀípˆÇÀɧåjq| rD0Ô( ª.Â!ª 4Ô€wñ¤µ“'[ÄÀÙèùñª[ïý.Éúè»OSñµ*ë©j?®[É7Ó¢çÂ*K 3^Ùè÷Ö‹ègŠ H’<õ'§ !mfõÀ'n„’Ĺö”(ƶ57“= æÓèê[‰xº]ñXÈñæ2`‘p@yÒ![Qê3Ò•3ùš7Лõ§;þxùåÊpm0P®HÖªX•Xß²TÕa<[Àd6'IÍζÔäï»es,ݶeýœãY³ýýçö·ÌJ#Ͼt2><žEw[½í-Û($)…x-ñmVC4«|9l€;_¸ªæÉ7'[¢k¶ 5TŠü ¦Ñqñ$6ŸÝ/\kœ;a2QQ–BªÒ £þå~€t læ pÀaCG1µ¸——üñhŸô%Ýh­ðÖzm‹nà+‹éÜ”¿Vî˜ÖY¸†PqÛ2óÏ™ÍÃ"׿:4Ž*ÏÅ$ÃÄÈ¿œV,†5æàü s.ÅÙÖÂId£qÔUŸ¼.ï‘5§¿íìZ„Ö®ÅFââ=()áP·ŠT"†)€! Ñ<‚b… ¯¡Iw.•+ó7äWPxRÅd¡"Õ2Ö1žI0™ÅØt]ßzÓòb:ëùлdÛ.·—;÷K%c‘Gÿþ;»¶é võïhK"Ác»\Õ»ÓBÖ¿5”rƒ‹…+WØVl@÷P‹»RU  Þp½Á"ŒôãššÁæ‹kЮSX¼‡ ì€+1O€[-ÂɰAR)rÇ–vÃ'Ô gx¥«ruÍìjêv«ÙEüʰ o­7âræ)sWw­àWæ\ê)=ü;r•±)ŠýgQ+–¤âÅ®?Í6È6ª"hácãb"J®G ¡„¼¯k²Î’‘'Ï4ÅÒOµ)%D„£×aº’V:£qžƒé4.qÙ÷pX£§ÿÀºDpèâÔ]dIø³¤¤„EKÚ+ûç0Iñÿª¾öúǼeo¾Xy×ýwÝ–›¿g—UgÎõ‡#¡àÿþ»»þøÈ©ÁŒÖkM'°¸#-¬\¹/`îï\Å"¬³µüayAžn@‡08¶íÇŒª‘\=‡v"6Þ(il!W‚ÏtߎÎ|é× ÒßOdp„¾øÔ4$hWºQWÃtº—,ÇŠµ›Ùêê‘àâÈÓ›ÇC!iÕ ]M§¯òjb ç$¦,¹>õlͺ­óf*Ζ­q ‹$3!mP¹pq<‡iòf¶¬_\»ëÖ5_ºÿö›?órûvÅs_.ןü»o>uß÷žÙC TKK»ZdBU†ærN$šYKý²WôìhÖU«™¤cŽõ‰lAÃ%… T6ë#©£/Â:}í…Úƒ4x^€vû#ôÜ( |æõ¸6B¾Äòº2B†pXÜ>ÛÌQ×Z³®uËd_ßZoÔå¾üÇÊmfüçξ€z.*Y‰ýéÓ…*Š$q5‰§]oî^…þÍ‘ Bç¬0jP%Aå¬Û¾æ±bÍl¿ãn´d:D!˜Jç›ßÆÖ?¢€¿Z–%4à+ X%æ|6õd/9HÃóƳyò\³õŸ pàü0Åÿôï;6bãš¾¯Ü¿cË'¯¼¯WYƒCSÿÓ®C§ýkß{~#+ŽGXE®uK,F1+Š  ß»!Žsu~S œC,j`ôw“tS Å dJˆÄöu™AlÐmØûÒ‡÷`Qˆç©…EééÎGèõ"œ°U 8hb&òVlòlîhKÒ÷Y{V±Ø[À{)ËcéŒK¹J@˜}u=ÝñjÚ»¶•gíò€™|È•Q¦«2 O•. ÝWQoòR2rÄPŒ5,Œ»!tƒ¥ hzzF¦2»/÷àßz×½¸yÛíd•+ê4sKºTº,áÂd÷ŽìúAˆk>˜CÕ5—L´rä)ç+U8uG85òÕ*Î^ÁL‰Œ'y1?þÐíGïܶêÏzºº¾t¥]]Щâ…CŸ}|çÁ?¿02%eŒõ«¡;ÓB{£zì +€ƒp0¨¡—W§k"³šŽ«â÷R½*1L¹ÔЃHªëžVº8€ÄþX>t’bû„„FpÀá{a¨R"»÷6)«=‹—Ã|ëúµŒåoXoyoø¥c}Gw‡¾ÜPO{^h`2ÿL;•Eut Eç+Ït\5Îøsé•A]sO*0{‘ãæ>OÂŒ¼…™º%!ˆØé@Cú` dy?ðááö»îB<™”Ü•«[ÖYcd[“ Äb!¨ˆ`®ZáxÞïMeM}nËcùáYG’s,ÀÈÄ,Ž÷’'R¥°¼Ž½cÛÿµ¬¯ý?ݾucÿÕötA  xÒšÎæzz÷áïí;råz ëI¬îë’Ò[]$§!“H’ñˆ¶ê®Ö¢&º_8Ó©jÔ¢›R %-‰‚ YUQN0‚`1 œ:†â¾=HŒ •\,8ÊÙU&1 Ø %à›)ÀxÁNw¥nnI’·…Ó¸Ìe™‡m<І·4À YM¯’š›±i²újR K'ý4ï>+äKÂòScÀO™bôF,¿‹\¥&%¿ “whN>Kñóˆp²PÅ·&Š‚ (;ÜaªP…åZI ݺ ›ñÑ}‹¡QS³=åÖÑ–J¡%SPa¨k_ا5ÏÕ=‚–ð’Knl‚¼cIuÚJ¶Î]Ã±ó£¤ "X³¬ÛÖ-{O2ýþÝ·ßtÕÓº`¿÷ØÙá•cS3ßúÇo=½!›/Ú3i¬]Ú…%$L•ZC4-Ç:mé…Aa8U]Xzjæ-_H§³¥ý¯*Åe³¹2²Å"YpGx«&)äÐ8~ #O>†%õ"Úh“ÙÕ”û!¯AzlÕ2l[Ê ð`Qò\ìŽ6Xɸî§öššW>Ês£¥ýMDo­ë»”e×÷Æé•óeù<5G+™' „cš¯I8ÃS¨—*^§_–Î× YR.ù™{ÏOѹ™&Å0IÞçž™"ÍѲ–Ÿ;ý˜&¿^AO_>ùsŸÆšÍ7I"ΑöÆÓu‘ˆ…ÑJ†& JsP³#vŸVW4 bë_âyœ+WäeøuG§s8=0 nÚ‹Å£?p˱֖øï½}ËÙ…ìë‚À‘³Ã-$ÔïÿÞÓ/ýדg†ã욯&p˚ŊÕŠ•„K™dŠãÄnR.k° Rí”êûZ¹Ž±™Ad (# &»ZÙ)œ{ìqtœ=Œn·†P$* A¶øìD­ „qÉ ÞŠ@*!UñѬ:ëËk+ãCb¾¥nÜò€@Pe5ÁoÀÀfU"×S¶‚š[Œã!Wä±ÖÏ >‘“ò^Y¬=DÈgIøëš;ÀÒ#ïùNÌ”±o2ƒÓEœÍ—hæhž œŽTüÀ{ñáŸø˜Âª04ÖœoWƒ~Òi)û™±]¼ÂQkXi©B!2Ôx:_¤°¸„ K_GÎ ãÌà¸ÈL_Wºøî{núù`È~øîm7Í^ý^!YΡÓíəܹo?¶gɹQkIO6¯]ŒnŠ©9¾©2"ÅÙm-qD)ö©¹:Ï/ZL¿á‚v@?×V“O"<ÃSZ…„²/8…U. ÿä£h:‹Î“……‰Q‚Ì[ ªêW_eä8ÅmAéLÀ"%`u¦UU@ó:&7kjÍ&ðÔFç­TáY†%‹CÊš™CfõÆösK-¬bMâ}ù’û_¥8žÁ<®ù“gÍÿªIÃ9J°¥#KûÒT»& ÈUtjÄ[yzýwÜ…O}ææ¹z݃ïr2‘èI’FȪ¼Q“/cÁ$Õºz!¬ÃôGårYŠóà s§ÇÆfrd˜/ââø wwà¾[× t¶·¬¸{ûæSá¼¢óLš&Nnþ_~ùO~ôðñx‚„|qonY½H ‰JæµUmMµ(ÔNš<ÀB€tAÂÒ¢¬˜šžE‰n#¯lù}uú}¼áâìó;Ü÷úòt§"û“ Äñ:#ÿÛÍiCòÜýÀ;0“›£µg¯$JafkkZ®Ñ+ã馽 `”™ž\Ä*„›{ò ߇=áý'Σxeº¦›Ö-+|ü½w£R­}fÍÊEÅ…îé+R§Ç­p0رsïÑïü`ï‰Û†ÇrèÌ´àÖKÑ‘Ž“æ QläÒò…›€L“¼q¯þ–M¾s. Z‚7¨V˜âˆ”ÝXYFäIÚ1ûƒ'PÚù )]œˆä‘bŒ  wZˆùÃþžB†@:!^€ÃPá`Hu)ú„ÝKüùKo­²äD0ÔC7‘*¤^³ÓÏÕêi‘À°Ë_'+é–j2ÒK¾jçï6$a'q½Å™%R ÜIWtp0_Å@¥iŠØÛ0Íb\âËd2øàG?‚w¼ëATjU‰í=L? 8WÁx2O,¾ôÚMkòÕ>§vïmWy'Œ+àd8Çþâ²·=S¨bçá3æF½[V~ó¾Û6ýBµVŸ °àCúª<ÚÁቧ¾þÈη?¹û(ÚS),íåÌãbDBA¡AæOÄÐFZÐV…E…ì.¬ t㮎©„AXU\gfóÈç+Òˆ¤ò<–‚Zô^¥c‡1þè÷Pí?‡Étu›0$eëå¤d2r,$Œ°äJ’íëB­=I߇­²¥Ú œ2gá´§o­×o܆(jèô—$Ê™jšâþ‰4F§Q'ãÀç¥àpÆŸ;üj(ñ™4Ciõï Ý ßÏå-'…1QcN[eÚ¹á§An8 ü»Þûn¼û=ïEG[EžbÐÉcGqýI&lijè¦6ãcA…dWc¤Ž®afzù2{¿L…G¡/ý§pvd%z¼;“xøÎ­ëþÝO¾ïîc¯t?_•pkî‡éÐç¿ùÄ‹7MMN&pÇM«Ñ•‰ Y'3û(Înoå¾ç všïêW¥ÀÆØ æš3¹¬ùfФÊ*d;ª“Šß£\Báø ÌìzîÙcè¦÷çP€o OJájo™„5PH~Í¿‹ñ”áìLBõD"ª7ÁÑ®”66„“o­»V“UÚözj\EÉ]¨ÀáŸÉiT(æ¯»Ž”©³×ËPí%ä÷T™›’þ«Øx¤h 8—mWÍ×k¸5IFßqÏ]xà½aÑ¢>ñ:-M8béN½xœ„?’°S•$]’´õàSSºòRJ‰3<”·Ž©©,jN•^&,A“S3øÁ¡SÒô“N†ÑÖýÏ_øµOýò«ÙËW}œ°ïÄG°ïøïî>pææT,†Å=íØº~Ú’Q5L”6N‚­)©· SÊ?ü\¼³JÀ)º$Õàá’KRl§YÚjE÷FT•„–ã¾üÁ8ÿÄ#HOŒ"CRÌsØe˜Çÿ¤btsÂ\&”aP´¶]ãé­ä3´ªp™”(–ÿ€ëƒešé‘o­²¼ý÷(½ ,,Wœè< P†3‡C–¿:[@‘䈃aføa å>»ï3wãþÇék¨nc°¾ª¥:ó,R­©¶Ý¾¾^|âg>‰EËÓùV|Ã;È‚!—¿5–©¼ a†F!*ØrS\½cÖòøj˜ÉÍ¢X®«†¸`@’á{Oôc€1 tÞ—u§´µD¾ø¹óñ/¿š=}M§ùÿø‡ýégÿ®È Ú„{·mÄÊE"1uG1°vˆ&’Úè,è ÝÖ+9yWÍ_c<7`0}s¡TÄÔÌ´À9Ah„£¯rYLž8Š‘§ž@×Ô$Ò5NˆAv@…azHÐÕ%€ô,B E×Ú‘‚EÊÀ ‡äzd¤¦’¶f 0ÿv¾µ^¿Õ¤òV¨Ï&}1gÿLVøü\bIðòœð˹\³wPvŒG©Š½Ðy¦,Ýÿ³ ÎÕ§W.hzz)ù5iGgOÞûž‡°~Ã:iù­K§Ÿß’^«-ÓŠ$~ØD[¶&íä÷Spôæ ?ù4¸âÉáÏDï]bÐOvZ’~!!Àupfp í9AïD Û¶Xð“ðëŸüÊ«Ý××t~~ò¥OÓEþõ7ß+˜äÅ]lݸ ‹;ÛÈuiÈF‡9hO S ï›)ÛÌïPqùÁûÆ]À²þg.ŽŠ,½ëÎ<«óç~ñøo¯v¿_Ó½{aɩÜg¾ûÌKP¬Ar;nYƒ[Ö-ƒS« š5U†P[ÂÚ«¨Ó\x£9€u½]—/=Äæ&úéžø7Uzý,»G…¢‚oÚj °¶ÒµT+% þóW1»÷h ‰&%£Ë BÎ8°1Ð CVó ƒyÁî ,ž4Ä}Î ÅÏ«néNCfeuuS嘹Ç? ÀjÈ(ªk©ü|_ßo?Å›”¼#e¾Úð+¡^iÈø-îî+PXǧJtW¸FæX 25 ¼AR nGÙ@E+¨ƒ¶*禳èèìĽï¸ÛoÛŽh$Úóè­!ÞA2™¤_PX~üŠa~ÝØ÷³þ€ê<«j†ÁÈò9âDælq3Ù¼PÙñÜ®ƒ§†°óàiÞDɰ޽mõ煉ѿ|ßwN¼Úý~Íwî©Þ;‘Í?ýÇö€Š®^Þ‡7­ÂÊÞ ò¤ù‡‚aÒ’)Ä“1i„¥µeâƒÛös¢ù¯Òò’-ðm7F²Q2‚~¤ÖJ79ÁÌáýÝù ŠÇŽ!F!3xr ,ÂYWØ€ˆI þ€»#ÄÌ´ˆ€.ëx½æ W;wÍ*!´Õ2œóoö¥úá®=£bS ¸Ô×›öÊ ›e¨Lñ~–Üý‰T™Õ—Lb¥Ú@™é¼\ﯢ⨠)´õ­Šø[8Jã¼£0€ ÃÊÅæ¹zù\²êo»ómØqÇmtvÓ¨Õj:‘mé쾋X,Ž2lQÎ?Ù Kð©<`¦ÁD>šk–0X-H繄Ééia)âð“„Ï Nâ…ƒgq~hL\ÿ{oÛŒTÔzû‡ºû™×²×¯ùΜXf_ùë¯=rÏ™aéßß²z î¾e%"ÑÅ_U)Ã$qG„#A™’âèöGsÇmß•Ìo!6‰¸M¦£êÿqR[$m³£<"ŠG†Ó3ýgqá™gÛÿR…œÌc Ùa‰©‚Â%Àù>…äù‡ü¸x ’ ã1;R°[“„5Ÿ€+e!¯'’-Ÿhž{÷f]¯G`–c2ì† Cãúå?ÆÂ“Ð×Çs¨‘°r/J…3ù÷“(6ªòá\—Ñ,4;R‹¤í§ìòn"­(U»š­Á@ b¾ýÎ[qÇ;ÐÑÑ!É6;M·ž«“~ŠûÃÚB#²TõBŠ„sØŠx±÷Y£ð%;•Å,…5<þŠ SB™g÷ÄSDvzÚÓøøGxÖmÔ~ú¶+¯ÚñwÅëy­7ªTu"ÕjímϾtèO¿ÿܾÍC£ÙHO{Û7,ÁÖ +¤ÃŠ­>ƒqRé´¶¥5€£¹¡÷ܬÎw¡š®¿ë6-K{ÉÝÏ’ËVáé(U×å£& Ý 4uæ4.îÚ…Ñ—v£½\@ŠÝ}ŒànFž5 X’!'¡¨žxÔx0V”bôeµÄ„v\U´°un á¢y?ßü À±^k¸c_ þ6±ù´òHXx^_¾ˆjv–@µ|IÚoKLÊÁ½ú$˜òª ò‘Ra iYù9déGÂq …˜µâÆDx¹œ+õs\Fp˶͸íÎíè¡øßa0 e³5×%¡ %Õ"I?U®«kÖÞ«ï ¹«Ç—Ê1[ødäà ã}>~'¼¹”½ÿļxä,&HÙ%¢gyoç¾~àÞÏÅbÑVt¦*¯å^³Súü“xv÷á/ž<3²²X­cQOîØ(X¿Ä‘l•z©šÎê»×’æ]–aNòýh¾“< !GGšÓ×< ˜‰xs%~o`êÜŽ?ýÜSG‘šF˜Gšq)ÐÕ½Ü=P]„ª“ÒSÀΡ8ˆñ(¬¶$B餌o'c…º£“Rvýìå¿Yוúò¯¾,Ý{Ñç[Òv½°¥æeêÎ:ò5H8ù2¬éÊ3yú¾(¼x\¿/‘K^ªª~~G3K9:”s¬šä)ø½¦‚ \ˆf0K (³&õ,Az‹ ÓÍ“5¿é¦ xÛÛnCgO»!S}KV^ç˜p†Ë}-©$ÌIt< ûÕ—LfššïF{P,HäÄ ñÌ@ƽ̖ñýb`x ¡p¨Ñ YÚÛñ»¿ñóüöµ¸‡×ì¨>õÒQ«^­=¹sßé·ï=Út&-+áîm+Ädª0Ÿ–H$жö6BøS›è‘=Àt{ÏMž4Ût}ïªt"—÷êŒÈæQ(½^GæÅ©R»“g0B^Àìþ½RHÔ,IÊŠ‰E™`$"ˆA&dáæa#œ á·9æëNÁMFTw¢nA 4®Õnþp,K—G_å_+ŒM±u£i©›šžÓá¶‚AaÇûµ™YX³dõé^VÊUÁój‚o•?uEDÓ û•§ÉXþÉhC±6LDÓ˜% ^×<,…URñd7­ÁÖ­[Èò÷Ê 48ï«V1ÙLB'ýB¡ª÷»Í¾ü…ì„äº4®Eí¡zœùC§&'Q*)>AxS-ÕñÂá³Øò<òÅ b±Øùd<úÇ‹:Òõï~ñCד~MmU©\ùâ÷Ÿ=øKß~â¥p‘nP&•Àƒw¬Çúå}Ò†1c [ÝDKR¼•Ew¼ymåñè¡ê88ðûêól€­ÜCÚÔ*Å¥|,CUO|ÕÊ…­Š’ljöÂN?ñ8fîClvz3 s¤´â D„OÀ–Ð@‹˜dÄRù9”ü»Å°Z)$ Å`™¨$¨¬ÉH@-3SéUžE©íó} jò¨æpM0-wƒüƒ"xàS›)ÈØn±øŽr÷Yøy˜‡cȘi•ìÔè¾Ô­ÒmŽgP 19G@;ùDq?Çó›·lÀ=÷ÜABN,¾7¬C±X‡"!¤$ã’kSÆJÁ}¯ô*ÖVªaôZŒóÏçót= )3šöäÙüëîÃôx©dŒ™²¾T¯;¿òWŸÿô‚Z}t ®åq M[}fpì·¿óäÞŸÙ¹ç$BQ=m)¼ïí[±¤·“>dM™Áá÷îë‰BÐ,.º[ÊÄGóÏ•fš…&„I¤¸úÆ1VšCÛ­ëÄÿ> V>pSƒC8³s&^Ú…øø0"n™¾‚ÐÈp}eÀ­ÄÑã\ñ¸B J9IH7Én‰Kn€çpO‡ CXyÍz†Æ5 N×õæ—7Y©©X)[i.¡@óumBLÈ5ÿõÍ@5uéU|* â‘ ±ð;¨’*ô0W«hůŽÍÈÈ.ŒJ݈.sùé¬ðØ®ŒÑ0Ÿž;ÉÂ>AB?™Ì`*Ù‚*w|ºª»”ß·A¯£ÐnÓ¦uؾm º::PmTÄ“°u€k)‚›•>y~.÷iŒçö² Sƒ†4×Ö]~fpC¹ý\Zä.Ö()¤þ± |穽¸8‘—ϳnE7:2Éßû¥ŸzÏ®ÕÉòßãk¶F§³÷>ûûÏî<öãã“‚ÖÛ±e%î¹e-z2iéÆr\ÇCP™N=‚AlJãeÜ©&gš¹éjÄXÀŠÚ*®—J#&êé+f”’4}DToêâ .ìÞé=/¢12ˆD½,u~K·"5§³ E4¤{ Â6„&Psàæ!ž‘ÀÃQX¤RV è Ôk_®×I©>¹Oà|y‘yÒlþtþ+鿱tÙµI¦éqÀ§h}/繪ú ãU*;VjŽÆSHÖF`·dõ¹—¼G&í¬ó¸nfð%ÃQ#/¬…ÙçÙûæm¨ŸÎð¥YÞ„õ:ü¨šænPâQd€Â&'0°ï†_xõá3ˆ–ŠM¾wÝ(ÂïÌì¨ÐÙ âŒ2W ¸—€CAFõ¸§ƒÆÞ€xª„yé1Ð÷ÍN6O0®pcü xûcÜ]{A¯áh@57Ánòí©¶æ_ËäZšVÎn6]îW¾\«5³£&”mäê:<ì¢@Öbáz¥ŽJ©,£â*L à öðxt¼ñàj’W†ÉÖÈÊW"$üdõg’m¨Æ“¨ÛŒæä0#(ÌRy™ V¯[í[o’Œ~žî½éç7 Q§aו²tG'üÌç¶š'ÓÖ>©è¿14fš\ÒQm¬2e›óK\7{Îý*œ+ÛuèžÞ}ùZ ;wµ?ÕÕ™úÌg~⡯b«¯¸^·põïþåé•ÓÙÙ3‡Ï !K7uåòn<°c3nZÑ'ÐLèyR³•²dymÝ›íšô¯«ÜsýÍ 7?;—@Š-w<»mñh-¡ÜªF@ý]PO F„µ@gŸÛ‹/îBµÿXΰg@ÿ(<` 37NŠžà&#&јÕÊ`Í0ÀTÛuÓ„/ù6g‚ÑœyåîÏæËϾxÞßãp¹¾&Ûoá½ÐÅd -!È1¾[%§ûYŸÍ E·EB^¯ÖÅê×*5I²I9¯a)‹/#·4ôÕš²žc)+j7øõƒ¨'’¨¶“à·w£J®?ÿl…#¢xª ¥Pâá(º»Iø—õ‘X„YܚƇ¨¤œjWgcr¶ Üú£ôU%£óK&ä\ i%ÀŸÎŽžöã@]Ýûµ«z!CÀ[ÍlYÌ-pàd?¾ûÔ!\“<Àº‹G6­[úŽc럼޲y}Àž3ÁÁñ‰ääùsz`¬ƒaÀ}ø©»W.–Ö^®ÛóžÆ©aòJ2lÁ°‰¥d;iƒÐ/L°<’ïÃù=¨,.¯^r¯V.éDG{J•eêJ±ðûY(í…%EL]ÆÀþý˜Ø¿Õ‹°(LUÔT…Z®î$s!#Œ`Å@‘­B@‡\†¤›ÎIB“w`GC‚0“°É2Ÿ[¼JKcQüŽmõ×[6¯[.é[ìî¼86ñ[ýC“¿8<šs¬u×ö5xïÛ·ai_'Š%eõ¹@pôt?ÎŒ L‚³î¶žùn鸩g»ÍÿQ|©eð`ÊEãÊ—>m©V,í–÷æÎ?×U‡QþŽ~Ï Ál½J¹I Ÿ@ÿž½ÈÜðøPÈÒá¬jáPc›øï¶ò‚š‚œkœàÞþ!K+ òl¦%çÏÅåĸ†Ó¿n”„?ÅàHhb{VÐr}Ñ5ÀsÞ^®ØØ\Æ‹0Óu_n¹Í3 “Á6–ÍÆL±úRg—š3ùdÙ].ße Þá™Û àa_c«ßpå«ì6„ž«ê¨°ŽUzÃwß,ã‚8ŠJ’}LÖšjA½w9êÝ=@k'Å\) §B’°µê–PÆóêì"«¿bz»;J'DY;ìÒK§úD’C´1pqgûG0I×\§0%,ÝÍù½ëj‚äAÚ-Ï+R1]¦/_Ö…Õ«– A¦a)o€dÿúÌ~ìÚ‚>Ÿ›mIÄ­¥=_êîhý£ŸýÈÛǯ‡\^7ðÝeMO¯Ê~{t|ö§'²9`Þ½}#2FwW+ò…B$|Y²þÇOœÇ™þ‹Bç …½²¡8ô*e«;°^î†@ßxy‰å\KáH¸Ø[±´Ë—öQL¥¸ÐÇVÝ]2f<ÄdŒž9‡Ñ‘=u³ÃMOÂÎeɤ”´‹h©Cª0dʕ׭Å!Á‘Ø¢ÂF1X ~,teL`J €CèžN ëPP\±¬ Šlê`¾Ðç² »yÛã%½.§,_RÏjF¿²}z µ„Xœx£{––­¥ÍÞ :)kÒÒ¬ä áu„Yב¾|Ûš Ãɽó `’¥²ç†Ÿï¿)C·%¤Û`µuÁéêA½£SFÃsvŸïiaÃô©Ö4ÚÈ»ë[ÔMJ ±X˜”OE0 F™Ù¡€”‡ó’\šÀ™sØÎ*d­$¡‡š4^ŠèªË+ioнZn1_¹l6¬[†4ÅÿŒ2LÐýåpã±À {N T-çí€ûÅŽ¶L §-óõöÖ–ŸþØ}× Kz¥u]«Iÿ忘ɗ6å²Å?ž˜¾¯T©G˜:üÞqÿ[JQŒVª“ÀÄ;tô4Î’‹ÄS\"Šã.SX¸¥¹ŽÜä Fû01t…ÃÇQ=w Î̬FU:m¶‚–á‹ÓCI¥']qÇqhÀÃ0ŒRPžŠ8?Áµay[4†ÛÜ‘à`‘;ÁD)@ˆJ!09F[nytf.繚êe÷Mç \×P¸ëQi,ìuW d……½*Õá$[¹ ”«‚©ç¤µ°Å¯9Ò™)ã¬YØ]W%õ\““1Øy38Ö$lm …ØûïêºÁêZ «£‹â¡ÁÔ\,¨ u½Ú—––8Ú»;ѽ¨Gµé*î6Q@®«8õ‚´w¬xÆ'fpñÂNŸÄ,ÏÔ“¡ ' ½ŒP½û/‡ó»‰©“Ï\A°I£®Z¾7m\® 7ë<¾.,óýþ žÛuÙl!Šÿ™®ôß“¨‘˜ýÍŸ{ízÉäõ.'ËúìþÛm}­ž¼0šž"k±´·wݶ ÷ßµ &Ü„kfhtœÄ…‘IT*ŽÄÒV`^ñ•>œ«çè±O‚ÖÒÃyq²‡on$EG[ŠnÔ ,_Ô)Äüì}é…¥˜Z}V­–Q*0rð(&OGþB?j£ÀÌìQ xØ3ÏZ:Ž÷„R%º§@ ¶:˜ai6²…hKÁU<Ü´blAˆ, ý· ÛÊ ü<{!M»n‹vñ*(°_68ÒÎ…*»®Â¤K⪮by¶ò,äØZÇ÷$øbé™ù™㮼:'ú¸Î.VÞՉޫècô"Á¨wêšék¶XÜÊÊ¥=“ĆÕK±~í2¤˜ÔRXjñÜs`“{R]šÅÔøÆOžÅÌñ£¨ œFíÄ 8å"阚G_æè¦9õ¾4‘ Káªj,¡ O1‹%„:è¶NZY&Ä`—6ÃŽºŒå þ  š¬t¹Ðlýp^˧èÒȭ˵ïºró¹tç”ê’ß–[î΃RŠì¢3ÇbU3غ+´žþ†°ñ8Vsân³¬é4ÁMŽjúwÌXnVrÉVz#¸|BKVÂM·JÍ^)9“bg-YýÖ´µ·¢5B,©8û8ìàÏ[5tÙ{?=[ w§N]$ ' ÷…PÉÕÕ$Ûš{­j­=ÆæžéJ”‡Bu•Ÿ Š‡Ù‚‚XM–ËÆ•èënS÷†þ+•ëxþ¥ãxúùýÌ3 Ï.ðÿ~ééÇo”Þ@›Æ„;¿¼óÀÉ_ûî“ûûNœ¦î ·½ï¼o+nݲñXXn4×hǧòؽï(Žœ8b¹ŒH0¬â­,ל -\~é¸ü-ó-¡‡]±,)Ó0· =ß°v9–/ïÆ¢Þ6ÉS¨Ä´9ˆ®$v¸^Ë!;@Êiðr'O 86JÁÜ™i8<œ«VÀ I üIA€ e9×l¯ÂÇ¡‡ ÌX,Tèp¼pB¾³îHY2Žˆ»,³(ØC *bS±HzzNÓìº:<±ô앦`%'EêH‡š#V^2ù,Ü®J ²ð7´PUÙF:ªÆÍÊ,<†ÓÌ€Û*––©½Zõ9¦¤¦á²<ÏÁfFÝL'‚==P|Hµ#ØÑ-^€Å¡Ÿx JqÙ.JÏO¦hmM!Ñ’P4ôÝùi††êýfWüÂÐÎŒàÄé 2dƒ‰?x^„º— Ä%¶ÞxRëw¼ÀÒãÂÅC¢Ç¹ÄÅĈlÙ´‚ÎO‡âÀ¤gç+5ì9t>u€Îó·öò5¡?þß¾ôG¿ô÷7BÍç½a‹¬ïžÞuôW~bOË(m [ãnRïð6…à&)ÍY˜™ÉáÉÝqâÔ ¹œŒQõš.<jêåƒÖÐ b!­²’^¤×aB¶ºËxôùMkÐKžI†¼.ßA'¦ê\Æ©UÉ.¢BGÒK˜žšÄ +ƒS§P9wÕá ¨OŽ©7©‰WÉ}®6“†PÓ_çXb¯Í”=‚ šŠd5¤±‰=…XS׬†Zš¡X\=ÌDF©[9!¿Ð”VŽŽk­f3‘ciŤKŽ ±`ë.¸u­\ÅÂK -Ѐ¡Ú0l¶ŠÒ]p U q”YÃcùÐKïŽÊÔªCÃ( _„“›F}l É)RerÛ¡,²Ót#=oE*PšôIJ›1³¾eþÞwRÅN¡¸Ò%&Òñr®J€ZÚ3Poäz0^úq4V–ðEO§53ÚLÏÒÈERLÍa¯šáŽºvüa«ý´#1úÐÖØòhY¼N„”+¹ùhv4&xÅ!W!¯ЇlM"™L =¶(k×ò&çÚf‡Ìnp¤3L‚¶ûÅc8vz•z>ÿP¯—‹éç/µË¶ ýj<?Ρ]êf&Ãݱ =}¨–k¢ 8Øwô<¾ûØ.\S9&Æ †?aÿô¥?üÅÊ#uC¯¡±ÉvÒÌŸ=|ââï~å[/U­RìÄú½xÏ;nÃÖµK0]® y'ãñ§¦³xjç<¹ëцº&ñ%µ¬…¡·üKd=âGK: l#7sÓºe¸uëZôu¤P¬8"ìjJ­ÊX« :[:•»`AªÌÌ`òÌiÌœ9‡ú…CC¨Ž“(æEÙ‰µdL½&D¬Š®(‹¬” ,5ÕØ9¹ÍpD…@z~¡Ioš^¯œo?ßÁ÷ǺþfÓµ¨ždù"ûºÚÏõ½ŽÕ|A#ûB¹ÆŒIa™ÄÌø†÷Ftv#¶z’+Ö¤ìDDÁ¦5=ZõLYˆ‘Bˆ&#Q8ÈIX¥8Tl4T UJ0¹ÿ"Fxd,‹œÄ‘S2V«\Õ AhrK™ C YJùª0G9kÞnègÔ1[*‘Õߊ{nß,pó€Vžiºn&ôüÞS{pòìE IU?E/úð—ÿì³…ë+m—ÿ|7| OvWk_?xìâoì>pçÇ$Ž]Oõ®Û7á¶[V£VqÔ¦ƒ1>9‰öÃÓ»‰›Èr[fw¨6cNÖÁG_ÈF8&ìcwcw•_’nZ&IJÅXµ¬·nZC.^L\Of9ªËÓ%¤‚°ä°:•J¹*ù,JÙ¬Y–É ˜={¥‹ý¨æfàLN 4:JžCIðRv¤ë0Ý4ã øƒYölàºþì½±lše¦ Ò1ŒhfzAs†½÷™ý­¼ÀÊÇ ëÙëÜ9JC¼&ŠÍÁ¹®0¯Oá¡- ÜÂ$ªÄ/CrÃØç³2æ“}‰”|F;àJhÁ€¬`ÈÊ-ö¾xT› H¨Ú Ì|ƒg€ÔúYฑìØÉó"^ÄÙ £àê’Tí †ã:Ⱪ¢¥° ÐFÔÝ|j&7ŠË"±qûÖõ¸ûÖ›ÈKÌ¢P 'N÷r?Yþ'wÆ‘ÓçÅ«ÉÄ“˜Éý*½Ôÿùå/þêëŽò[й¿Ñ`ÖðøTG$þÓ¯|ã©Ò™ £Ÿš-µp|·fy/~ì·cÃêeR®á,+wôMggðÈ3pää€ÄU,ta®‘Kƒ¡7¶iÝ\šØÓS39¸ts5¼í­)Ü~Ó:¬\Öƒ^ºáë1IH‰1îœ}f[Kµ IÉÎVcÇ8ëÌns5?‹â…‹(^¼ˆÊlÕiR"T(dp¸'‚cZú·–#…Q))tÀ[¡¸òlÕmI>@áµ'òd`»Ži¡v/qxç…†›Q¾Ü&ý•tP6”ð5T@†£ðÜò‘˜Xù[ù– BíþpŠbüžÄV­D…ž[¼¦†ú{ÉÑØ ñîXðC<Êç3¡ 瀌rv\åÙ…™‹qôôèäÌ,. NHÉácg(æÏJù1ÀhK•jÕêÏñĪ[ÏòÐ{W^æ9¥@,Š̹½®¶46“gxÿÛnBg&- 0ˆ—uôX?Ïý8~nXðí­‰|È þÅŸüÖOÿΖµ9çþF_€Må¢]m©ò¿ÿ‹¯ýy¶XþÔØät+—Ö/êÆƒo߆kú‰FPo°›XGq¶Š]û“Ëwš¼ˆ¹Ý&èd-põØ®…¥{Ýfl&r³ª"8ªÅS—y,Gqtµ·Òõ,ÁM¢ôv¤e £¾XQ0ÜUEêä(Z¶îøsD˜œŠÎª“PU 3( £4Bž)žm˜ë?‡Ê)ò ÜbÑJƒÌ:G)7E/­,°2âºüè—£÷2?û½SacÅâèAÀ uß…%Ü[F©©Ì‘î.D÷"ÒÖ‰Hª ¡¶v´¬X`¦ – õl•+°t÷†@² /žrõí¢`ÙAÄs¥¢`뤥€ª„œU•M«ÌX©`2›ÇáS°ïàLÈt åÙÛz¬‘o[¾qs L «}2ÍeŠÅš'ñ~÷v·aÇ–5¸mË:¤!õ9èú¸,zúÜE|û±Ý8qL’¡=í­3©dü+¿÷Ë{U#¼_Ïõ†RfýΟ- Ù:“Íjt"c‹ÐF.÷‡¼·l\% ‡\->.…j‡O à™Ž¡Ÿ6<ãò£°BÍ›·ÐpM—IÕðáeÔðQÎæKüÏ“†#¤[¸§ [7­ÄŠEíJ€tß_c3Ú¶=¨‚m¼GÎZ3°¦šÏ“"( Á 3LƒE@½\$o€¹ñf(„˜B=_b<„ )ŠFaV¥¢ˆ%)„¨Ñïœ`ò}ó]3R7ø;ƒŽD³¿‚+zo[tqÁ#dÕ‚B %x`*}%ÉëI¶PìÞ‚ýLµˆågö#ÎîG2­°ÃQC¹:—ÁaÓÒm+"|QÒb¥Y¸,G“µX2rÌ! ¨ÎH[Õõ–r½DZÿðœ»8"¤%Þ/GÏ€¨éÁÞ NîðrDjTÞDˆã®*Š$UU¯Râ‘Ü ¾}Çf²þËÅÕwuâ‘QŸÃ·݉ñé¬à#:Û’¥ŽtË—)|ùÜïöc7<æŸ¿Þ à·¿øÏV$XÚ¿—/Õ?~ôܹÙ!,ï뼴ñ·oe­F±T~ö|¡ ðÒ¾“2@&è¹€—®ùÖ—'¾_*…`{3áàFÔÂG¿L&cXÔÓ!1àâžv¬XÒ‡t**¯Y'áVã¤u6_¿“cRSˆ$²¥` nKà @Cu×¹µ*ÊÓ“(£–%o€”B­G…gÇÑè÷u>ä¥ÊSÓ¨khë¥üÚ&aòX|ôG’Ä›dÒÉ Ç¢dÉS§'¤ú™……?L.}„;ÀÃ]ÚÉÚ·¦éCrø}IùYú $üQÿªZž®Ñ£©yDÑ:lõëêqWuèÙÅ«â LÐq¢CC“›Àðð$rÜpÄm׺M[³=h³¿Ž¶Þs•_³Ûáòá?#üzŒ"d~õk—bÇÖµX½¤‰DLJ¤sÅ ö5«@MzT—i÷W%,ó†~ ËÃûGÎ[5¨<<Ó)hæQ˜|cPxµeZ°ré"l½izºÒ’²uKñÈTÏï=]{ŽSH2&IÀµË{qóú•/6œÚo?û¹Oø ;3ê ­ÌzìùQLÿŸ?pbë±ÓÈë­ ¡â¦µËðö;¶¦íP¬¼AåæNNÍ ÿâ8;+ /N]¤ J\™Ú¶Î-Cu¤ë&^“ŠÉÌ«ûý8Ë·‹lɸ´Ìà%:œ rŸ9<Ȥ’hooÁºÎ®Ž )ÅQot,¬Óш9^¶FáÓôÄ ¯”“îQâJG •$ëUWž4ò ‰Äc"­Ð>ŒNƒ¨-ª«bm?ÛrP$¿Sm£Lƒîœ|†Q–Ÿ°)|¥“§Íý’ìtT‹18Š©bœ¬=fÆ'g1=3‹"¹ÖÌÁî7+O¡b·›7ižÏ¦¿™_®4–ÿQ*³ïSÐ;YAñ\ ºà®ŽVlX³kVô¢=“bgGHE8ü'åôôÎCØ{ø¬$!b¼ŽžwÛ–eûBÁÈo½óm›¿£eçjë‡Bð:waú›šüN¬>pbÙìl(Lñÿ-W ¿àÚÕ‹¥€z”´p¡\E?…ÇN]”2O^‘Z·I5æšú¸> s7Ƈ!ðZ=凫n©¥Ë\B„!]i6ZZbr€ÚÉšdÒ-hK§ÐÖ– kŽŠbjN=v=‹d•·~o·[ª ÑkÛek¯Fa± Èú(`{óU•€ˆ| 7í XšûÚ|N[c,òù z޾òÜ™œÉ’0Í 7[¥ÈÞA”+(ÉULJD¸úºòd5_Aø»3ÌÃü>\f\BÜúUK±´·î_•ªzf¹QÅ©óCx~÷1>vŽÂÍ*bÑHmëÆåxÛ-kN§["ÿaãêeÿxEäU­À«V­î™—ŽÝóg´×ëõ»&è°”ÈBl^·wïØ€«ûJÄ%`¡b¨ CS8rê\óCŠÆÊâ3žµˆÎLW:†Rº }Oâ¤J¥öžèÇ¡ãýèÄØLNʺ[×­ÀÖMËa‡ÂŸ¸ïÖuÿpíO÷õY?Ô €W¶\ø½o~ÿ¥Ô‰Sƒï-Vªë™Þ™;ÃV-iÇ–UK°ž<‚ÎŽ´¤øÆÉ]e|8ÀD#¹|ùrY“SB»ý–g5ýÖo~àe—«¶ â½ÿ›Wð[XóÚz®œ­¨´Øcptv_ò¡ç<>NRñ÷R;+ˆ¬¢4W+åhš1#p®_Ú/umT @Õ¾ŸÖR}÷êZ¸šÀ{ȃ<øgž­Ç^¤A†bå“#x`>`šy £…Œ¥‡ùÖõ©Ex{d*š€QžW^sS~ºÄ ¾˜é¾ÌÜC.|<Žî¶:ZãB¿È8&¡åüé û‰sÃØâ"Î]B•>ï²%]h‰Eo\¹è»|p[®%žüüu?ô×pýÐ+³þâo¿ó‰d2öûŽ_.îg©B‡ÞÁæ5Kpë¦UèiOË䞆ÎòrÙ™'MÍ”H«çU‰¬QW5u¯J`Ü÷&h! À둟£üùhýýÚó‘‰þ§–Ï_p<:*ãe4Ka>DÂ! ®<ì@ÊüY34ßè²RVlpRK•èt_A…YJTÝX¯7±Ä^k5_˴ͪ_kÃФ)œ¸ÉGúæå%L¢SâwÛòyTºQéjûï-“ÜÔ(AÏ„²¼¨ÖTími„C¡/ £þȳžÌaïñ³8|ú¢(ºx<ˆ8)ŒmV/*¿û?ê¡Jäq­Ö›FðzrçáŸ!«øgÿòýÏV25§*ý+äâm\»[Ö-G,h{ÜöŽfærY–ÜÖB±"n«jäi–Õ¡s}!ÂeѾç»M¾B§ií=8ŒN*Z²ëWþW4αkù,£îÐkN¡QŠÉòJ”º\g²zZàTíÞÇm7ÿ²ÝæµûsfðŠ£IR †BýÏ™óù=Eæ#BU7ÕŸÁšß6¡¹ðï©—;™ó/çƒ]Σ™û|Wç‚8|⪠SwE‚®„PþéÓ¥ªƒãg/à¹ý#³b0"AÛʹƧ?ôÕù×ïß±þo_¿S|}×›J<ûÒ±Þd,vË?=ü V.ïýʾ£gÛyÒP&Ó‚t:ŽŽLk—õÒWô›³§ÀK¦Ë6¶ŸçÔ•ÙÂ9u¯Œ¤ŒŽ¢Ž6ˆ:9œ¶IÄùž«¬½;ïLšªƒÂÓ¸qæ#º„ïøºFaèÇ}wÉr›°¿»¬„²üúáKsÄbN¼9 Ð|xÎëk´¢ù…_ä/W›÷× æûN _n°F9ZÆkÐtÇ®‡éÖ•WÌl>u ŠÒeè ¢0Jò&jð‹­ùc‘ˆÜ÷“ýÃ8¡‡„p¥bjª ‰ÁmëOžÿéŸøà}(ªûïÙ¾føõ:Ã×{½Ù€•ŠÇÂ_}økë–U?EèÏ Œö?7$‰?Æå÷vµbqg+V.ê¾?Ž¡«ÕŠ –€Ž¿¹‡ËW qT©€PÜf-\§¬Õ®V@×Þ]Uh0æ"×L ýŠVí•X»K—{…WYÈš¿²k™[0|yÉ}™×3jÃòÂC« )öœÇ]C€ÈËV‡š}|ߢš0U¸$WCr¯G§²878þ‘)²ú3˜¤°“Œç–÷u תµß>xjà«?ù·»…BµJ àÕnén½©€}õ;ÏÅwܼö=ynp#)†å¥JmëäT^r)2+wbÅ’šŒ…J̽ùu§iA\=ñb1lI×øªaÚqç8¯9¥Íœ›×k€æïà¾i·ÿ•¯9(K“Tß»šÆ]yQf·mzwéðÊVcÚ¸gÀÕèËTD\5˜…=õr¥¦sôâÌÅ1dg+D‹öÝ{ÛÆó«–ô}þ¥ãôÉÞ_¼Ñ[ôºmû›uMdóKŸèO95ð¶¾î¶ß|ôÙƒ¤Ì 3ùY9]m­XԙƢî´§ctÓC’­æU×së ÀTUÜ' Š…· Ö]3å˜a“¨šŸó÷7y/güM½ý¯lÍW– µ,OÐų²›%Zpé’¤£IOe²0‡p•šª•l ¤†wp¹•“zSäŒÏ`hl ã“Ó¢nZ“IDBÖ±wÝsKhptâO6¯]ú†•Ks]íé½=¯ë¶¿Ù×ß|ãñΫ–¾ÿï¿õTyݪ%¿svptýÀдŮ!»…mmŒÄKaIwÚ“q) 6LS‰&Ý%@q#³¼FcQ¡€6‰=e“€ÅKV鿟ï ÏA¾iÉk°|I/dš“ÄS¿µl_vÁU!ï;÷]p)²,x„† ¡«ÐÍCŒ³ÈÊË’à“«ŸE©R•Ç—.îtW,î=~ê̹ÿð‰Ý=rzàáŸýÈ»®Ë€Î¹~$€}ëÉÝŸ%×þ×Î]ï;waÔ’–° uogÝœ0l‰"‘ˆHíÜÖ.½ŒÍ"‹&/iɘ_> ÓWT:Ôx™Yuî¼Øøré¸Ë¡ë~¤×eøþÉ;&‰¢¸ù ¶”"Ë¥²Â!”k$Ìe8rõ O]á²f®PÁ´€Àò¥8?[( ×BwW¦±ri»biÏ©Œÿý#÷oÿ‹½×sýÈ)€¯~÷¹ðCwoûÃÁ¡Éw>öü(… ëó³LÌ„Å%I‚ßÝ‘pHk"Ž(#î‚j@‡Ìºa#‘LH3O<f¢0'™tK²@} “¯~Ú¬g»XX_ÁÆr½ ©FP*)ö¼0uKlƳHÉÊ;ÜRF6›C¡PD­ÚP)UöÔlµ¿F&Òs’sn(=04vïÆµËþë£/È9ٟηÃ@cäî·§¢ :Z“ˆØÊ›Ì´²¡™®Â‘Z[[dTUŠBˆ@H“U0µc¦ËûºÏŒõÿ‘ÜýË/Sæ3 Üi(ÉW ŠR|uH€''§xª®€“TžOý­mºéOyB1ó 0 ‡Á^ î±ôd%†Y/_Ü™ýèƒ;ÒÇÏŽüüÒ¾ögV.ïͶDC£7z®û¾ßè ¸‘ëñç¦ï¾}ãƒ_dWyù¢Î¿o{~ïI ŽN‘å*>¹û‰Hm©:3IÁ‡›ðTqŒOg.O𥠋 Ù³VdH!pÞ@¥Óh¶`n»ñ[«Ù2¬†‡:j4:©N¶ì3Ù¼¼äóyrõ+BZÓ³™7Pž«ùËå2FgrϤrV* áôë!e¾}Ór õZ§NõýÌ/üÄ;£Ïï=õÈwnÌÞèÏ#÷ý­¶î/í>prÉ©sÃ÷‘5ºãøùAœ»0&Þwè¥ZÈeä=žOÇJB…®”©¹ª|ÈÐY5Ñ&*¡A:ÝBÏ‹J[iŒgا’‚ѯë®n“mÂUßÜk> ɲš` ¶Ì<€ûîgó³ÒÂÏQ¤¯,Åî³$Ð¥²" aÀS¯4¿É7¸-À„¶ ⢠¾”/øÄØ>Àb|@ DŒÄ!jŒ•²®Œ’Ò¤m²æÚ%MÒ¤ub;¾¾¶ß÷å<Ï9ǯ³¥PF‹êGr'ΛÆöyÎyn¿ÿ‡kô¹3ñÇíÿnëÿ/Ú–YDÂä* Þ€œÐÔXLC!Ø]ðáPwtøÔd3Ú|<ŸMÂΧÆCô– ×pÐçƨU»C¯ÇþÒÓÙ`ü#öå`ø{Ý»ïäûe»[ÑÜÂ^<8v¤ç•™EéôùcîzÐ-ɪÓäønHZAó8*~…OÀÉb±æ;PM7«Sà"5Õ>ú3¥Ô!¸ðT€£±B”›YT¦†Ã'q‡3LÃØ°ê6s –å÷êóD¤dÜ2¹ùµ6›¿å#ÂbVàýß•6>VÎ»Ž˜Äƒad°‘H”„דdåÆ*½ŸÄªŠh·fD!™±úx}…M"fpœ;DwzHÞB_…Öé—lmª‹7ꦟúèƒý…~/me+:€[Ø‹ƒo:Ž ôv\™^’~ÿæÐRu¹ç¹†úÚ§Ï O‘…¥ .Z!±Ãx.=öÛé} þºœ6œÄƒSAnj轌þÉÔ{iÌj³ÙQRLµÑð‚:²R¨(¸HEEñ€Ð4Âèá0 ž ûÀðQÞ¯µ_dÈØ¸ÐsðÞ~+Y-¶›™É'ê îÖMžÈàe7ÑÅhêÚ ãRØ`U¸á=Îñ>NÖé & 30^ ù”,£ƒA"ÐàýVpílÆ$ ÿ§4¬ÇÓx¼‡Ó$÷hD'º r¨· /DÚ·:îo(§àÝB¿—¶²ÀmÚuª§9P×óöèLÝþöÆç®-¯bކ0T°ŽR·°øaÄÔIãO‡jÃxUVTT©,0ÂY}‚”`€zõpf@£,hB¯×í!®RÖ äq;1cyÓdUƒ/X†£ÃÄ 'ò˜†Ä„ArºYb¸Hb‹Õ¶ +F*‰… NGÁ¶Ztl2£ !„.ê(ÝÉã±8rô~ŠÆç°kkôHÍ:ýX0Nê\ –]BO%ÔÉ€ *€\ÔI›ÞD]…`ñ[‹ZfüÁ|ÑPÞ¶ Ý·K°´¦a·•qQj.l C]œCJÓIœ.Tä(òp%çàøG†€“Ë·,ûÁuÁyhEA ­Ú{vŸ3(§Â•3š6´»½…Üs¿cx|æäÕ…àÏyÀÛÝ0ª+<‹…~ol7+:€ÿÒNþöOþhÛfh<66yÍèÛýÝtÆhŸ˜O¯WÝiìd!6ŠÊf€VìàÕEa0PMfsð¼iˆ÷ ™‡W F°ˆ™¸ë>Çe.â¡È2çî®GD‚€xÂίÒS S¡|7†+*=}¨ø·(’¤ÛTyÂﯓšêË¥} åÓó+¿{íϾ}¨·CÞ×ѨüæÔ¹…¯?ý‰â¢¿KVtÿcûÑËØq¸¯ýÀù‹3‰‰«AóñÃÝÏ;íjçÂJ(¹Œ ^A06RÝ͆‡KÊaÅ$é4¸Ð§”£ÞŠjžÄËr,— sD– ° ˜_üù¢ „´Z”‰`pì†tð~|…AT9 Õ€ž}¤ =æ´+*¨ìúk}ôh_Nêk|NMKýñ­ÑMÍ©½¹šô÷ìr^ž¼6µ·­i¢Ð¯Ó½bEP`»^?^îvµŒÏ,&¡¯`êê™[Z1ú{;¾áq;ko¬†h˜À,;ðöC4t€ÙwHž¸LfzC|‚–'Þr„ƒkìÉÖÉà„¢|æ®pŽ?‹Ðkgƒp¹1P=’tüº‚ÉL¨¼¥. Ý‚5>rc-:ò±Ù“Õ^—Z_ç#­Í~ıµßWïŒF“³•Þ_ú5¸—­è¶¨-®¬}Ç_SÑ;>³™[&áxg߯.­‘àjT÷•»w×ï¨è„œ–ˆiwö4u -A†µŸÀ2žÎU‘ÿ½£°;d¤åbc‘ÄJ{Î&HŽ„™z‘,.¯­®¯Wù@«ÿ?A®ÿ?A¯ÿ?A¯ÿ>A®ÿ>A«ÿ=?©ÿIK¬ÿjj·ÿ¤ ÇÿÙÑÕÿëåàÿ÷óíÿÞÔÉÿïêæÿïêæÿïêæÿïêæÿïêæÿÒŸÿÐÁ´ý—zen¶¢“mʹªÿÛÐÆÿïêæÿïêæÿõðìÿÿüøÿæ×ËÿÿÿÿÿÞÚèÿtt¼ÿAD«ÿAC³ÿHKÃÿSZÐÿ_iÙÿhtÞÿlzàÿl{àÿjyÞÿcnÛÿYaÒÿLPÅÿBDµÿ?A«ÿMN«ÿˆƒ±ÿ¿´·ÿâÛÖÿõðéÿ̽±ÿïêæÿïêæÿïêæÿïêæÿÛÏÅÿȸ©û›j>ij§E¹§™õåÞÛÿïêæÿïêæÿòíéÿÔżÿõìèÿþûÿÿ™—ÏÿKL´ÿGI¿ÿQVÑÿfrÞÿw‡ãÿ~äÿ~äÿ}ãÿ}ãÿ}ãÿ}ãÿ}äÿ~ãÿ{äÿp~àÿZcÔÿFI¾ÿ>A¬ÿQP¥ÿŒ€™ÿ÷µÿöñðÿæÞÙÿïêæÿïêæÿïêæÿïêæÿåÞÚÿ¹§˜õ½©˜EØÎÄ®˜‡ßâÛØÿäÝ×ÿãÛÔÿãÛÔÿæÝ×ÿìäáÿáÛäÿnm¼ÿHJ¼ÿKOÎÿfrßÿz‹äÿ}äÿ}Žäÿ}äÿ}ãÿ}ãÿ}ãÿ}äÿ}ãÿ}äÿ~äÿ~äÿ}Žäÿ}äÿráÿU\ÒÿBDµÿEFªÿ„{¤ÿ¸¨¦ÿúóñÿìåáÿâÛÔÿãÛÕÿãÛÕÿäÜÖÿáÛ×ÿ«•‚ß­˜…º§—œÉ»³ÿíçáÿòíæÿòíæÿòíæÿåÝØÿÇ¿ÉÿYW¯ÿHJÃÿTZÙÿsƒâÿ}ãÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}Žäÿ}Žäÿ~äÿ}äÿ|ŽãÿdoÝÿIKÂÿ_bÊÿ—¿ÿ½¬ªÿõëçÿîæáÿòíæÿñíæÿòíçÿíçáÿʼ´ÿ¬•‚•Æ·ª-¸¢’úßÔÏÿîæáÿëâÞÿéàÛÿÜÑÌÿ¿´¸ÿTQ­ÿGIÆÿW^Ýÿx‰ãÿ}äÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}äÿ}ãÿjvàÿ\`Ùÿz|åÿ¤šÃÿ±  ÿíàÜÿäÚÕÿéàÛÿîåáÿñéäÿâ×Òÿ²œŒú§“ƒ&æÝÕ·£’²È·®ÿæÛ×ÿîäßÿèÞÚÿÜÐËÿĵ¯ÿd^«ÿHJÉÿU[ÝÿyŠãÿ}ãÿ~äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}ãÿ}ãÿo|æÿgjãÿ‚„èÿ€œÿ¦“”ÿìÝÕÿèÜ×ÿëáÜÿñçãÿêßÛÿÇ·®ÿ±Œ«ÒÌÃÓǽ+´‹úÙÊÄÿóèãÿöêæÿåÙÔÿŵ¬ÿ‡}¥ÿGJÆÿPUÜÿs‚ãÿ}äÿ}äÿ}åÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}äÿ}ãÿ}ãÿfoãÿdfÙÿ€€Öÿ’„ŒÿË»µÿãÒÊÿíáÝÿúîéÿóèãÿÖÇÀÿ¨úÇ»±+´Ÿ“¶ “ÿçØÔÿýïìÿ÷éåÿÕÅ¿ÿ«˜šÿOP¾ÿMQÙÿgtâÿ}ãÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}ãÿ}ãÿzŒäÿZ`ßÿacÏÿ‡ƒ¶ÿªžÿåÐÅÿç×ÑÿöéåÿôæãÿãÕÑÿ´žÿª”‚…×ÏÇ­–„ÞÁ« ÿðáÞÿÿðíÿñáÞÿÀ«žÿzp¥ÿKOÓÿU[àÿ{Œäÿ}äÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ•£éÿ¬·îÿ¬·îÿ¬·îÿ¬·îÿ¬·îÿ¨³íÿ ­ëÿŸèÿåÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}ãÿ}ãÿn{äÿPRÍÿZ\¹ÿš“ÿǶ«ÿäÎÂÿúëçÿÿðíÿñáÞÿƱ¦ÿ­–…ÞÕÏÉñ£3´Œÿ̺´ÿïÞÚÿòáÞÿÜÌÈÿ»©¥ÿUVÈÿNRÞÿiuâÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ ­ëÿñòüÿþþþÿþþþÿþþþÿùúýÿùúýÿþþþÿþþþÿðòüÿÀÈòÿ…•æÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ{ŒäÿSXÙÿCE³ÿyq˜ÿ¬›ÿáÎÃÿíÞÛÿÿðíÿöçäÿÔüÿµÿǸ«3´ {˼³ÿØÉÆÿöçäÿóäáÿÙÌÈÿ­¦ÈÿMQÚÿQWáÿx‰ãÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ°ºïÿþþþÿþþþÿþþþÿŽœèÿ}Žäÿ‰™çÿ¿Çòÿüüþÿþþþÿíðûÿ’ éÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}ãÿdoáÿEHÁÿVSŸÿ™„vÿÚÌÅÿàÒÏÿöçäÿíÞÛÿáÒÏÿ×È¿ÿ¬œ{±›‰¤à×ÒÿÛÌÉÿðáÞÿêÛØÿîåàÿŽÚÿQVàÿZbâÿ}ãÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}ŽäÿªµíÿþþþÿþþþÿþþþÿŽœèÿ}Žäÿ}Žäÿ}Žäÿ»Äñÿþþþÿþþþÿìîûÿƒ“æÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ~äÿ}ãÿs‚ãÿKNÑÿAC¨ÿ‹tmÿñ£ÿéßÛÿáÒÏÿÞÏÌÿÛÌÉÿéàÚÿ½§•¤¯˜‡ÆÆ¹·ÿÕÆÃÿäÕÒÿáÒÏÿäÙ×ÿjkÜÿV[áÿeqâÿ~äÿ}äÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}ŽäÿªµíÿþþþÿþþþÿþþþÿŽœèÿ}Žäÿ}Žäÿ}Žäÿ‚’åÿôöüÿþþþÿþþþÿ¸Áðÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ~äÿ}äÿz‹äÿQWÛÿ@B°ÿ‚sˆÿ³žÿÞÔÒÿÛÌÉÿØÉÆÿØÉÆÿË¿½ÿ¹£’Ò»¥–ü° žÿÏÀ½ÿáÒÏÿáÒÏÿʽÂÿgkçÿW\áÿn{ãÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}Žäÿ}ŽäÿªµíÿþþþÿþþþÿþþþÿŽœèÿ}Žäÿ}Žäÿ}Žäÿ}ŽäÿÐ×õÿþþþÿþþþÿæéúÿ~åÿ}Žäÿ}Žäÿ}Žäÿ}äÿ}Žäÿ}ŽäÿYaßÿCE¸ÿulœÿ¾©ÿ;¼ÿçØÕÿÞÏÌÿÞÏÌÿ¶¥¤ÿµ ‘ÿ®—ˆÿ½¨›ÿÒÃÀÿáÒÏÿáÒÏÿ¿¬¢ÿqwðÿV[áÿlzãÿ|äÿ|Žäÿ|Žäÿ|Žäÿ|Žäÿ~äÿ~äÿ~äÿ~äÿªµíÿþþþÿþþþÿþþþÿŽèÿ~äÿ}Žäÿ}Žäÿ}Žäÿ»Äñÿþþþÿþþþÿûûþÿ†–æÿ}äÿ~äÿ~äÿ~äÿ}äÿ}äÿ]eáÿEHÀÿlh¨ÿÖżÿŰ£ÿðáÞÿáÒÏÿêÛØÿ·¤£ÿ°™Šÿº¤“ÿŰ£ÿÞÏÌÿçØÕÿêÛØÿÁ¬¤ÿ~„öÿW[âÿRXáÿV^âÿYaâÿZbãÿZbãÿZbãÿ\câÿ`jãÿajãÿajâÿ—ìÿþþþÿþþþÿþþþÿv~æÿakãÿblãÿblãÿclãÿŸ¤íÿþþþÿþþþÿþþþÿ{ƒçÿiuãÿiuãÿiuãÿiuãÿlyãÿjwãÿRYáÿGIÄÿlj°ÿëßÚÿï¡ÿùêçÿçØÕÿùêçÿÁ®«ÿíœÿ̶¤ÿѼ¯ÿóäáÿêÛØÿðáÞÿ¼§Ÿÿ‚‡õÿW]âÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿŒŽëÿþþþÿþþþÿþþþÿeiåÿOSáÿOSáÿOSáÿOSáÿ”–íÿþþþÿþþþÿþþþÿnqæÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿNSáÿGIÆÿrs¹ÿÿûúÿ»§šÿÿðíÿêÛØÿÿöóÿ¾­ªÿůžÿй©ÿÝɼÿÿöóÿíÞÛÿöçäÿ¶¢™ÿ‡Œôÿ[`ãÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿŒŽëÿÿÿÿÿÿÿÿÿÿÿÿÿeiåÿOSáÿOSáÿOSáÿOSáÿ›îÿþþþÿþþþÿþþþÿknæÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿNSáÿGIÆÿ{|Àÿÿÿÿÿ±œÿÿöóÿíÞÛÿÿÿüÿµ¤¢ÿíœÿ¶Ÿ’üØÄ·ÿÿÿüÿòäÝÿíÞÙÿ²ž•ÿ–šôÿbgãÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿŒŽëÿÿÿÿÿÿÿÿÿÿÿÿÿeiåÿOSáÿOSáÿOSáÿOSáÿ´µòÿþþþÿþþþÿùùþÿZ^ãÿOSáÿOSáÿOSáÿOSáÿOSáÿOTáÿOSàÿGHÅÿ””Ëÿÿÿÿÿ°›ÿüíêÿáÒÏÿÿóðÿ¨˜—ÿÁ«šÿ½¦•ÆÓÀ³ÿÿÿþÿôêâÿÿþ÷ÿ¿¬ ÿžŸëÿotåÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿŒŽëÿÿÿÿÿÿÿÿÿÿÿÿÿeiåÿOSáÿOSáÿOSáÿPTâÿäåúÿþþþÿþþþÿÙÚøÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSàÿEHÁÿ·µÙÿöðêÿ¸¥™ÿÿþ÷ÿõêâÿÿÿÿÿ®£ ÿįò¿­žÿÿÿõÿõíäÿÿÿÿÿȶ§ÿ¦¤Øÿ…èÿQUáÿOSáÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿŒŽëÿÿÿÿÿÿÿÿÿÿÿÿÿeiåÿOSáÿOSáÿOSáÿ‡Šëÿþþþÿþþþÿþþþÿ“ìÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿMRÝÿHH½ÿßÛèÿÙÑÊÿÁ¯¡ÿÿÿúÿ÷ðçÿÿÿÿÿ­¢›ÿÁ«™¤Ì¸§{·¢‘ÿ÷ñçÿõðæÿÿÿÿÿá×Íÿ¦´ÿ–™ëÿZ_âÿOSáÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿŒìÿÿÿÿÿÿÿÿÿÿÿÿÿeiåÿOSáÿOSáÿy|èÿññüÿþþþÿþþþÿÈÉõÿQUâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿLP×ÿdcÅÿÿûöÿÁ³ªÿÜÒÈÿÿüòÿõðæÿÿÿÿÿ°ž‘ÿκ©{ØÇ¹3º£‘ÿÜÑÇÿóíæÿÿÿûÿÿüôÿ¸¥žÿ¨¨çÿsxåÿOTáÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿ[_ãÿÄÅõÿÿÿÿÿÿÿÿÿÿÿÿÿ¹ºóÿ²´òÿÔÕ÷ÿýýþÿþþþÿøøýÿ®¯ñÿTXâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿJNÐÿ™—Õÿøñëÿ´Ÿÿÿùðÿüöïÿöðéÿôéßÿ²™†ÿÜ˽3óêàÄ«˜Þɵ¤ÿôðéÿÿÿ÷ÿÿÿÿÿϹ¦ÿ±¨Äÿ—šêÿX\âÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿ’”ìÿÐÑ÷ÿÐÑ÷ÿÐÑ÷ÿÐÑ÷ÿÐÑ÷ÿÐÑ÷ÿËÍöÿ¹»óÿ—™íÿbeäÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿNRÞÿNPÈÿÏÈÚÿØÅ¸ÿÔ¾¬ÿÿÿÿÿ÷óëÿúöïÿÖ°ÿÅ­™ÞíãÚÕÀ°“À¦”ÿóíçÿü÷òÿÿÿÿÿöìãÿ¸¤¡ÿ±±èÿx|æÿPUáÿOTáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOTáÿLQØÿvr¿ÿØÈÁÿëšÿùïåÿÿúôÿóïéÿöðêÿ»¡ÿ똅ä×Í+¿¦”úÞÒÊÿøóïÿÿüøÿÿüøÿϽ´ÿ·¯Åÿ¨©ëÿbgãÿOTáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOTáÿOSáÿPTáÿPUàÿSUÍÿ¬Ÿ¬ÿÇ´©ÿÔøÿÿÿúÿõðìÿïêæÿßÒÊÿ³š‡úØÊ½+éÞÓűŸ²É¸¯ÿïéåÿ÷òïÿ÷òïÿïèãÿô°ÿÀ¾ãÿ™œêÿZ_âÿOSâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿNSáÿOTáÿTXáÿOSÛÿ‡¸ÿÁ±©ÿɹ±ÿìåàÿôïìÿîéæÿïéæÿ̼³ÿÁ¬œ²åÜÓÅ·ª-¼§—ûáÙÖÿñìêÿñìêÿñíêÿáÙÕÿÑÈÎÿÃÃíÿ’•éÿY^âÿOTáÿOSáÿOSáÿOSáÿNSáÿOSáÿOSáÿPTâÿPTâÿPTâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOTáÿVZáÿTYàÿvrÆÿ²¬ÿÒÆÁÿàÙÕÿîéçÿîéçÿîéçÿæßÛÿ¼§˜ûȸ«-­—„ŽÔÉÃÿìèæÿìèæÿìèçÿìèçÿèâáÿßÜèÿÇÈðÿ—šéÿ]câÿOTáÿOSáÿOSáÿOTâÿOTáÿOTáÿPTâÿPTâÿPTâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿPTáÿZ_âÿ^câÿomÏÿÁ²¯ÿâÜÚÿçâáÿìèçÿìèçÿìèæÿðìêÿàÖÐÿ­“~xÙÎŲœ‹ßòíæÿëæåÿêååÿêååÿêåäÿóîéÿìéïÿËÌðÿ¦¨ëÿmqäÿRWáÿOTáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿTXáÿchãÿhmäÿzxÎÿõ´ÿñëäÿóîêÿêæåÿêåäÿíèèÿñìëÿþùòÿ»¤Ò¯—‚ Ä´¦E¾«šõïéãÿïêæÿïêæÿïêæÿïêæÿêãÜÿòîíÿÔÓïÿ½¾îÿ’éÿbgãÿQVáÿNSàÿNSáÿOSáÿNSáÿOSáÿOSáÿOTáÿNTáÿOSáÿOSáÿOTáÿSWáÿbgãÿtyçÿuzäÿ”ŽÄÿÐþÿõïèÿêãÜÿïêæÿïêæÿòíéÿáÖÓÿûõïÿ˸§ô¤ˆr%¶¡’mɸ¨ÿãØÐÿïêæÿïêæÿïêæÿïêæÿÕÉÀÿôîçÿäáìÿÎÎïÿº»ïÿ—šêÿtxåÿ^câÿTYáÿPUáÿOSáÿOSáÿOSáÿQUàÿV[âÿ_dãÿptåÿ€…çÿ„‰èÿŽÖÿ¸¬»ÿåÜÒÿõðçÿÖÊÁÿïêæÿïêæÿïêæÿõðìÿîäÛÿׯ·û§‹uZøõô¿­ž™Ï¿°ýÚÎÄÿïêæÿïêæÿïêæÿïêæÿÝÈ»ÿâØÍÿóïêÿàÞëÿÍÍîÿÀÀïÿ±³ìÿ¡£êÿ’•éÿ‰èÿ‡‹èÿˆ‹éÿéÿ’•êÿ–™ìÿ–˜æÿœ™Ôÿ¸°ÄÿßÖÎÿöñçÿâØÍÿïêæÿïêæÿïêæÿïêæÿòíéÿã×ÌÿÛ̽ý£‡qn¸¥–ª’€‚ͼ¬þÝÒÆÿòíéÿïêæÿïêæÿïêæÿïêæÿïêæÿÜÑÃÿóîçÿêåèÿÛ×åÿËÉãÿÁ¿åÿ¹¸äÿµ³àÿ²°ßÿ±®Ûÿµ°ÔÿüÎÿÖÎÏÿìäÜÿôïæÿÝÒÄÿïêæÿïêæÿïêæÿïêæÿòíéÿõðìÿã×ÌÿÑÁ±ù¡‡qoŸ„pëáß¿«sÀ­žüàÖÏÿÓ½¬ÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿ̼²ÿÓÈÂÿß×ÔÿãÜÙÿâÛØÿâÛÖÿâÛ×ÿâÜØÿãÝÚÿߨÕÿÓÈÃÿÁ°¦ÿïêæÿïêæÿïêæÿïêæÿòíéÿõðìÿûöòÿàÖÏÿð¢ü£‹xdÇ´¤C¹¢Þξµÿ˺°ÿι¬ÿÙöÿòíéÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿòíéÿõðìÿ¿ªÿ˹°ÿѸÿ¶ŸÞƳ£CÒŹ¼¨—œÃ«šþǵ«ÿÓºÿÑÁ¹ÿõðìÿòíéÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿïêæÿòíéÿøóïÿͼ´ÿʸ­ÿ¶ŸŽþÀ«šœÎÀµÖËÀØÊ¿;±˜ƒ¥À¨—úƲ¦ÿÒûÿÜÏÊÿãØÔÿèßÜÿèàÝÿèßÜÿçßÜÿçßÜÿçßÜÿèßÜÿèßÜÿèàÝÿèßÜÿãØÕÿÙÌÇÿÒûÿƲ§ÿ· Žú±˜ƒ¥ÎÀ³;ÔÇ¿»©›ų¤+»¤’еœŠÝ¶ŸŽý¾©œÿ˺²ÿÖÉÂÿÞÒÍÿâØÓÿäÚÖÿäÚÖÿâ×ÓÿÞÒÍÿÖÈÃÿË»²ÿ¾ªÿ³œŒý´œ‰Ý¹¢ŠËº¬+»ª˜È·ª ǵ¦?²›‡t¶ Ž¶®•‚Ѹ¡ÿ¼¤’ÿº¡Žÿº¡Žÿ¼¤‘ÿÁª˜ÿ³š†Ñ°—ƒ©²›‡tʸª?ȸª ÿÿÿÿtQÿøÿtQÿàÿtQÿÀÿtQÿ€ÿtQþtQü?tQø?tQøtQðtQàtQàtQÀtQ€tQ€tQ€tQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQ€tQ€tQ€tQÀtQàtQàtQðtQøtQø?tQü?tQþÿtQÿ€ÿtQÿÀÿtQÿàÿtQÿøÿtQÿÿÿÿtQ¨ ÿÿÿÿ( @ Í»­½¦“k¼¥“µ³š†Ü´š†ÿ¯”ÿ¯”ÿ´š†ÿ´š†Ý¹ ¯Ã­›q˸©Í»­=¼¥”¯À©™úÙÈ»ÿðã×ÿÿ÷ìÿÿÿ÷ÿÿÿúÿÿÿúÿÿþóÿýôéÿìàÔÿÚÈ»ÿ¬œú¿¨–®Æ²¢7Ⱥ®³Ÿ¢¾¬ ÿÑúÿêàÖÿùïåÿùïåÿðæÜÿçÝÓÿêàÖÿðæÜÿóéßÿüòèÿÿûñÿÿþôÿýòèÿãÖÌÿÌ»¯ÿ½¨˜¢Ê»®¾ª›4Å´¥áÍÀ¸ÿ¼©œÿòíéÿþùõÿÙǹÿíàÕÿñèáÿíæáÿðéåÿóìèÿñéäÿôêãÿóæÛÿëÙËÿÿÿÿÿÿÿÿÿλ®ÿÙÌÃÿÈ·©á¸¥–4½¨—<ÔÆ·òÁ­œÿïêæÿïêæÿòíéÿåØÍÿÿüüÿÕÒìÿžžÑÿyz½ÿttºÿ{{¾ÿ˜—ËÿÌÊäÿÿÿÿÿÿÿÿÿÿúîÿÿÿÿÿÿÿÿÿÿÿþÿʶ¦ÿÏÀ²ò¡‡s4Á¯ 2Ú˾÷ʸªÿõðìÿïêæÿƵ§ÿàÛÝÿ‹ŠÁÿJL±ÿFJ¼ÿRYÉÿ\eÐÿ^hÒÿ[eÏÿRYÇÿEI¸ÿLN±ÿŒÆÿåÝãÿÿÿÿÿóâÕÿÿÿÿÿÿÿÿÿ̺­ÿͽ®ëŸ…nÙÌÂ̺®ÞèÞØÿõðìÿòíéÿÛÒÎÿ«¨ÌÿKL²ÿOTËÿjwÞÿz‹ãÿ~ãÿ}ãÿ}ãÿ}ãÿ~ãÿzŒãÿjvÜÿPUÇÿYZ¼ÿ¦œ¿ÿÿ÷öÿÿÿÿÿÿÿÿÿÿüøÿèÞØÿų¥ÞÅ´¤ÓÀ±¤úòìÿÿùóÿöðêÿâÚÕÿŒˆ¸ÿFH¾ÿakÜÿ{äÿ~åÿ~åÿ}äÿ}äÿ}äÿ}äÿ~äÿ~äÿ~äÿ{ãÿfpÝÿ]_Íÿ…µÿÜÏÍÿÿÿÿÿÿÿÿÿÿÿùÿîæáÿµŸžäÓÅ5âÐÅýÿüøÿ÷îêÿãØÒÿކ²ÿGJÆÿhtàÿ}äÿ~äÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ}äÿ}äÿ~åÿ}äÿ€’çÿz†ïÿfiÚÿŠ€ªÿȹ·ÿÿõðÿÿÿþÿðçãÿʹ®ý´¢“/ÛÆ¶°ïáÛÿ÷ëçÿã×Òÿ°¢°ÿJLÅÿclàÿ}äÿ}äÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ}äÿƒ•éÿtíÿln×ÿ—‰žÿÜÌÄÿõèäÿëßÛÿÚÌÆÿ¸¤”°éÞÕÚ³üêÜØÿäÖÓÿŲ©ÿda¼ÿU[Ýÿ|ãÿ}äÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ~åÿ}äÿ}ãÿ‘æÿfkåÿpo»ÿ£–‘ÿæÓÊÿêÝÙÿÞÐÌÿÁªšúÐÆ¼É´£iÞÊÁÿÞÏÌÿÕÆÃÿ£”¦ÿLP×ÿlyâÿ~äÿ~åÿ~åÿ~åÿ˜¥êÿìïûÿòôüÿñóüÿíïûÿèëúÿÐÖõÿŸ«ëÿ~åÿ~åÿ~åÿ}äÿ}äÿs€çÿ[]Ïÿ‚’ÿÙŹÿíÞÛÿçØÕÿÒ¿µÿÉ´¤iÖĵ«ãÕÑÿäÕÒÿÕÈÄÿŽÙÿRWàÿ{Œãÿ~äÿ~åÿ~åÿ~åÿ~åÿÉÐôÿÿÿÿÿÞãøÿ~åÿœèÿÜà÷ÿþþþÿ¿Çòÿ~åÿ~åÿ~åÿ}äÿ{ãÿRWÔÿog›ÿÒÁ´ÿèÚ×ÿíÞÛÿÝÎËÿ×ĵ«áÐÃ×íÞÛÿäÕÒÿÜÏÌÿqsåÿ]fâÿ}äÿ~äÿ~åÿ~åÿ~åÿ~åÿÆÎóÿÿÿÿÿÞãøÿ~åÿ~åÿˆ—çÿúûþÿþþþÿš§êÿ~åÿ~åÿ~äÿ~äÿ_gßÿZX°ÿɲ¢ÿëßÜÿíÞÛÿçØÕÿÛʾÜÔ½¬ÿÿöóÿðáÞÿȲ¥ÿhméÿdoâÿ}äÿ}äÿ~äÿ~äÿ~åÿ~åÿÆÎóÿÿÿÿÿÞãøÿ~åÿ~åÿ~åÿÜàøÿÿÿÿÿÈÐôÿ~åÿ~åÿ}äÿ~äÿfqáÿHJ¶ÿ¼ª¦ÿÕ¿°ÿöçäÿùêçÿÁª™ÿÖ¾­ÿÿÿÿÿÿðíÿй®ÿtyñÿV]áÿcnâÿeqãÿfqãÿgrãÿjvãÿjvãÿ¾ÃóÿÿÿÿÿÚÝøÿkwãÿkxãÿlxãÿÄÉôÿÿÿÿÿÚÞøÿn|ãÿsäÿp~ãÿrãÿ^gâÿBEºÿźÀÿÒ»­ÿüíêÿÿùöÿ¾¦•ÿÕ½¬ÿÿÿÿÿÿöóÿ̶«ÿ…öÿNSáÿOSáÿOSáÿPTâÿPTâÿPTâÿPTâÿ²´òÿÿÿÿÿÓÔ÷ÿPTâÿPTâÿPTâÿ¸ºóÿÿÿÿÿØÙøÿOSáÿVZâÿOSáÿOSáÿNSáÿCE¼ÿáÝæÿη©ÿÿðíÿÿùöÿ´›‹ÿȰ ÿÿÿÿÿÿÿüÿȲ§ÿ“—ûÿPTáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿ²´òÿÿÿÿÿÓÔ÷ÿPTâÿPTâÿPTâÿÈÉõÿÿÿÿÿÌÍöÿPTâÿPTâÿPTâÿPTâÿOSáÿHJ¾ÿóðòÿÁ«ÿÿöðÿÿöðÿ­•„ÿìšòÿÿÿÿÿÿÿÿÒ¾¯ÿž îÿTYâÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿ²´òÿÿÿÿÿÓÔ÷ÿPTâÿPTâÿVZãÿóóýÿÿÿÿÿ ¢ïÿPTâÿPTâÿPTâÿPTâÿOSàÿ\]ÄÿôïèÿÌ·¨ÿÿÿÿÿÿ÷ðÿ´‹ô»§—«ÿ÷íÿÿÿÿÿïçÝÿ£ŸÌÿgkäÿOSáÿPTâÿPTâÿPTâÿPTâÿPTâÿ²´òÿÿÿÿÿÓÔ÷ÿPTâÿRVâÿ¹»óÿÿÿÿÿæçúÿY]ãÿPTâÿPTâÿPTâÿPTâÿMRÜÿŽŒÔÿá×ÎÿñéàÿÿÿÿÿèßÖÿ­™‰«Í¸§iâÒÃÿÿÿÿÿÿÿùÿ¥•œÿŠŽèÿPUáÿOSáÿPTâÿPTâÿPTâÿilæÿååúÿÿÿÿÿòòüÿÊÌöÿëëûÿ÷÷ýÿ¾¿ôÿ`däÿPTâÿPTâÿPTâÿOSáÿOSáÿKOÔÿÇÃäÿÁ®žÿÿÿÿÿÿÿÿÿÄ´¦ÿ·¢iëàÕŬ˜üÿÿýÿÿûõÿǶ¨ÿ¬©ÙÿeiãÿOSáÿPTâÿPTâÿPTâÿY]ãÿknæÿknæÿknæÿknæÿeiåÿRVâÿPTâÿPTâÿPTâÿPTâÿOSáÿOSáÿOSàÿ``ÇÿÌ»µÿо°ÿÿÿÿÿÿûôÿ¯–‚ú˼°̶¦°îãÜÿûöòÿðêåÿ½°¶ÿŸ¡éÿUZâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿOTáÿPTáÿOSÛÿ’±ÿÀ®¤ÿíæáÿûöòÿßÔÎÿµŸŽ°Ôõ5ͽ²ýöñïÿúõóÿèàÜÿÌÇÞÿ’•êÿTXáÿOSáÿOSáÿOSáÿOSáÿOTáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿPTáÿUYáÿzÂÿʼ¶ÿß×ÓÿîéçÿðëèÿÅ´ªýÀ¯¡5òíêÿøôóÿû÷öÿóîíÿÙÙòÿ˜›êÿY]âÿOTáÿOTáÿOTáÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿPTâÿOSáÿSWáÿ_dâÿyvÌÿÖÌÈÿêåäÿìèçÿìèçÿêåáÿ©’€‹ÞÐÆϾ®Þñêæÿþùõÿþùõÿöïéÿçäôÿ´¶ðÿswåÿRWáÿOSáÿOSáÿOSáÿOSáÿOTáÿOSáÿOSáÿQUáÿ_dãÿquäÿ’ŒÉÿàÖÑÿëäÝÿìèçÿìèçÿìèçÿÀ®Ò¬• ı¢2ÕÅ·÷ÙËÂÿþùõÿøôóÿòîíÿîééÿÓÒîÿ®¯íÿ…ˆçÿjnäÿ\aãÿY]âÿ[_ãÿdhãÿswåÿƒ‡çÿ‘‘ÙÿÁ¸ÈÿìäÛÿÔÆ¼ÿòîíÿòîíÿйÿɸ©ë›i(¹¤“<ØÈ¹òѾ°ÿþùõÿõñðÿïëêÿìèçÿèãäÿÛØêÿÈÆæÿ¸·çÿ¯¯åÿ¬«ãÿ­«Ýÿ¸´ØÿÐÉÔÿìäÛÿ×ɺÿûöòÿÿüøÿÿÿûÿ˸ªÿÌ»«ç›€j4İ¢4˺¬áɸ­ÿøóïÿòíéÿïêæÿïêæÿìèçÿÍÀ¹ÿÔÉÃÿ×ÍÇÿ×ÍÇÿÔÊÄÿÍÀ¹ÿïëêÿøóïÿþùõÿÿÿûÿÿÿþÿÒÁ¶ÿÈ·©á ˆu,ÖÆ»Á¬›¢Å±¤ÿÉ·®ÿøóïÿøóïÿøóïÿøóïÿøóïÿøóïÿøóïÿøóïÿøóïÿûöòÿÿüøÿÿÿþÿØÆ½ÿκ­ÿÁ¬œ¢Í½°Ê·¨7º£‘®»¦˜úο¶ÿÝÑÌÿæÝÙÿëäâÿíçåÿíæåÿëäâÿæÝÙÿàÔÏÿÔŽÿį¡ú¼¦•®Â°Ÿ7Ų£º¥“q¶ŸŽ¯¸¢’Ü»¦˜ÿ¹£”ÿ¹£”ÿ»¦˜ÿ¸¢’ݲ›‰©º¤’q®ŸÿÀÿÿÿü?øðàÀÀ€€€€ÀÀàðøü?ÿÿÿÀÿˆ ÿÿÿÿ(0 µ -«“€…µžŒÎ»¥“ó½§•ÿº¤’ÿµŸŽó­–„Ê«“‰´ŸŽ-¹¥–-»§š»Í¼°þéÞÓÿþ÷íÿþöíÿÿùïÿÿùïÿÿùïÿøðæÿàÕÊÿÁ°¤þµ¡“·¸¥•-ïãß¼©šm̽²÷Ó¶ÿÿÿÿÿÿÿÿÿ÷ëáÿùðèÿÿ÷ñÿÿ÷ñÿÿõîÿòåÛÿÿüøÿõðìÿij§ÿ̽²÷¯ mäßÙøøõñ¡†Î½®ÿÿÿûÿÿÿÿÿúêÞÿðëùÿµ´åÿƒƒÌÿzzËÿ‚‚Ïÿ§§ßÿàÝöÿÿÿúÿåÖÉÿÿüøÿÿüøÿÒÀ²ÿ»§•{¿­ŸjàÔÊÿÿÿþÿÿÿÿÿñêõÿ““àÿflÛÿs~åÿzˆèÿ~Žëÿ{Šéÿt€ãÿhoÚÿqrÌÿƾÙÿÿÿúÿÿÿÿÿÿÿÿÿàÓÊþ´Ÿ^±¢-ÛÏÆ÷ÿùóÿÿÿúÿÕÏéÿjlÚÿtéÿ€‘çÿ}äÿ}äÿ}äÿ}äÿ}äÿƒ•êÿíÿlqßÿŸ˜Çÿÿÿÿÿÿÿÿÿÿÿÿÿ×ËÂ÷¬–‚*À­Ÿ¶èÝÙÿôêåÿɾÐÿceÛÿ~Œîÿ€’çÿ~äÿ~åÿ}Žåÿ~åÿ~åÿ}äÿ~åÿ€’çÿ‡˜ñÿzñÿ‘‡±ÿüîêÿÿÿÿÿñçâÿ¾«³Ç´¦/Ô·þîáÝÿÔÄÀÿdcÉÿp|çÿ€’çÿ}åÿ~åÿ~åÿ}äÿ~åÿ~åÿ~åÿ~åÿ}äÿ}äÿ„”ñÿtvãÿœ‘ÿýìåÿñäàÿÑ¿´þ¿­,Àªš…ßÍÇÿìÜØÿ¤˜½ÿU\Ýÿ}Žäÿ~äÿ~ŽåÿŒ›çÿÒØöÿÕÛöÿÑ×õÿËÒôÿ«¶îÿåÿ~åÿ}äÿ}äÿoxçÿmi§ÿͺ¯ÿãÓÏÿØÇÁÿßÏÄÇíÞÛÿæØÔÿ‚‚âÿhtâÿ~äÿ~åÿ}Žåÿ~åÿÖÛöÿþþþÿ†–æÿ‘ŸèÿíïûÿÚß÷ÿåÿ~åÿ}äÿ}ëÿTUÁÿı¦ÿáÒÏÿɸµÿàÐÅÇ̺²ðíÞÛÿØÉÆÿ\`Þÿt‚äÿ~äÿ~åÿ}äÿ~åÿÔÚöÿþþþÿ†–æÿ~åÿ±»ïÿÿÿÿÿ¦²íÿ~åÿ~äÿ…–íÿW\Õÿ¨˜¢ÿäÕÒÿêÛØÿÒÀ¸ôÁ¬£ÿÿóðÿØÉÆÿ`eäÿdoâÿkxãÿkxãÿn{ãÿo|äÿÏÔöÿÿÿÿÿy…åÿp}äÿŽ™éÿÿÿÿÿ¾Åòÿs‚äÿs‚äÿz‰éÿ[`Þÿ”²ÿçØÕÿðáÞÿ¸£šÿµ ˜ÿòâÜÿ̽ºÿjoæÿOSáÿOSáÿOSáÿOSáÿOSáÿÅÆõÿþþþÿZ^ãÿPTâÿswçÿþþþÿµ·òÿOSáÿOSáÿRVäÿTWÜÿ±¯ÏÿêÛØÿóäáÿ¥ˆÿ¬™’ðÿóìÿÀ±®ÿx|áÿOSáÿOSáÿOSáÿOSáÿOSáÿÅÆõÿþþþÿZ^ãÿOSâÿŽìÿþþþÿŸ¡ïÿPTáÿOSâÿOSáÿMPÔÿ¹¶ÉÿÛÌÉÿáÒÏÿ‹ƒô«šÇÿÿöÿÛÓËÿ‘ÐÿX]çÿOSáÿOSáÿOSáÿOSáÿÅÇõÿþþþÿZ^ãÿZ^ãÿÝÞùÿññüÿ`däÿPTâÿPTâÿOSáÿQSÍÿÍÅÃÿÝÖÍÿÿÿöÿ¡ƒÇ±›‰…æÜÑÿÿûóÿª®ÿuzíÿOSáÿOSáÿOSáÿcfåÿÙÚøÿçèûÿÃÄõÿÕÖøÿ¼½óÿhlæÿPTâÿPTâÿOSáÿOSàÿ{zÍÿº©œÿúõíÿãÙÎÿ§‘…ñ£/ǵ©þþúõÿ×ÊÄÿ®­ìÿW\äÿOSáÿOSáÿOSáÿOSáÿOSáÿOSáÿOSâÿPTáÿOSâÿOSâÿOSáÿOSáÿPTÙÿ¨›­ÿÑøÿøôïÿij¦þ¶¢‘,¼ªœ¶ðêçÿòíêÿÓËÔÿ•˜ìÿRVáÿOSáÿOSáÿOSáÿOSáÿOSáÿPTâÿPTâÿPTâÿPTâÿOSáÿSXáÿ…ÁÿÔÇÁÿõðíÿíçäÿ¸¦˜¶¶£’*ÙÏÇ÷úöõÿü÷öÿçåòÿ™œêÿW\âÿOSáÿOTáÿOSáÿOSáÿPTâÿPTâÿPTâÿPTáÿ]bâÿ…‚Ðÿ÷ïëÿÿÿÿÿûöõÿØÎÅôŸ…q ¾¬œjûðçÿÿûôÿÿýöÿÿùüÿ¿Àìÿ„çÿ\`âÿPUáÿOSáÿOTáÿUYâÿeiäÿz}âÿª¤Íÿðçßÿûîçÿ÷éâÿåÚÒþ­–ƒ]øõôÑ¿¯†ûëßÿÿÿÿÿÿÿÿÿÛ̾ÿâÝäÿÍÌêÿ°°çÿ ¡åÿžžãÿ¨§Þÿ½¹ÙÿàØÕÿÖÆ·ÿÿÿþÿÿÿÿÿÜÍÀý±›ˆwëáß½ª›mÜʾ÷ÿÿÿÿÿÿÿÿøóïÿòíéÿïêæÿïêæÿïêæÿïêæÿïêæÿøóïÿþùõÿÁª›ÿǵ¨÷¸¤”i¾«›-¼§˜·Å²§þÒüÿÚÎÉÿøóïÿøóïÿøóïÿõðìÿÕÈÃÿÒýÿȵªþį ·Á®Ÿ-¿ª™-¹£“‰¿«ÊÆ´¨óɸ¬ÿɸ¬ÿñ¥ó·¢”dzŒ‰·¢‘-þAøAàAÀAÀA€A€AAAAAAAAAAA€A€AÀAÀAàAøAþAh ÿÿÿÿ(  ¹¤”;¿«›ŸÐ¿°äÓ³ÿÓóÿͼ¬â½©š¡³Œ9İ¡ ÔÄ·¥Ð¾²ÿþùõÿþùõÿûöòÿþùõÿÿüøÿèÙÍÿâÐÄÿ×Ǻ¥Á®Ÿ ¾¬ ØÈºÉƯÿþùõÿ«§Ëÿ~€ÌÿjoÆÿquÉÿ™™ÔÿâÛæÿÿÿÿÿÒ»©ÿÒÀ±Ä¥‹tÔÆ»¥ôìåÿÕÌÔÿmpÌÿmzÜÿ}Žäÿ}äÿ}äÿ{‹åÿksÙÿ¦ŸÏÿÿÿÿÿôìåÿÐÀµ£¾«›9ÝÐÉþØÌÌÿabÇÿxˆãÿ~äÿ~åÿ~åÿ}äÿ}äÿ}äÿ†‘øÿ‡~§ÿôçâÿãÖÏþ¹¥•8­ ¡ÐÁ½ÿކÁÿn|âÿ}äÿ„”æÿÿÿÿÿÿÿÿÿÿÿÿÿ†–æÿ}äÿ‰›ðÿ„ëÿÚÊÈÿèÙÕÿÐÀ¸à;»ÿwzêÿ}Žäÿ~åÿ~åÿÿÿÿÿ®¹îÿ›¨ëÿÿÿÿÿ…•æÿ~äÿ€Œôÿ°¤¿ÿðáÞÿÖŽáݪÿØÉÆÿfmèÿqãÿr€äÿt‚äÿÿÿÿÿ¨±îÿtƒäÿÿÿÿÿ¤®íÿx‡äÿs€éÿˆ‚»ÿíÞÛÿÀ¬¦ÿǵ®ÿÒÃÀÿchäÿOSáÿPTâÿPTâÿÿÿÿÿ‘”ìÿPTâÿÿÿÿÿ‘“ìÿQUâÿRVäÿ–•ÓÿäÕÒÿ»¨¡ÿáÓÉàÏÀ½ÿuwÖÿOSáÿPTâÿPTâÿÿÿÿÿ‘”ìÿlpæÿÿÿÿÿfjåÿPTâÿOSàÿ¡ÄÿéàÙÿ̾´áË·¦¡ÿÿøÿ£›¼ÿUYâÿPTâÿX\ãÿÿÿÿÿÿÿÿÿÿÿÿÿorçÿPTâÿOSáÿRU×ÿ¼®­ÿþùòÿ¸£’ŸË·§9ùïéÿâÙØÿ”•äÿPUáÿOSáÿOSáÿPTâÿPTâÿPTâÿOSáÿQUáÿ“ÇÿèÞÙÿäÚÔÿ³ŸŽ9ðâ×£ÿù÷ÿëæéÿ ¢êÿY]âÿOSáÿOSáÿOSáÿPTáÿ\aâÿ›˜Ûÿôìéÿóíëÿ̽±šÐ½® èØËÉ×µÿÿÿþÿ×Óåÿ¤¥çÿ‡‰äÿ†‡áÿ£¢áÿÒÊÚÿÿÿÿÿι¬ÿν¯Á¡…o dz¥ ÖĶ¥Ó½¯ÿÿÿþÿøóïÿõðìÿõðìÿþùõÿÿÿÿÿÓ½¯ÿÊ·ª¥£‹x ¾¨—9ɵ©¡Î¾´âйÿйÿÐÀ¶áλ®¡¿ª™9ð¬AÀ¬A€¬A€¬A¬A¬A¬A¬A¬A¬A¬A¬A€¬A€¬AÀ¬Að¬AL0ÿÿMAINICON L00 ¨%  ¨ ˆ  hthrift-0.19.0/lib/delphi/test/serializer/TestSerializer.dpr0000644000000000000000000000402114370300523023714 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) program TestSerializer; {$APPTYPE CONSOLE} uses Classes, Windows, SysUtils, Generics.Collections, Thrift in '..\..\src\Thrift.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', System_ in 'gen-delphi\System_.pas', SysUtils_ in 'gen-delphi\SysUtils_.pas', DebugProtoTest in 'gen-delphi\DebugProtoTest.pas', TestSerializer.Tests in 'TestSerializer.Tests.pas'; var test : TTestSerializer; begin test := TTestSerializer.Create; try test.RunTests; finally test.Free; end; end. thrift-0.19.0/lib/delphi/test/serializer/TestSerializer.dproj0000644000000000000000000001470114370300523024253 0ustar00rootroot00000000000000 {9282EDD8-7C12-41B0-8172-61C6BFA6E238} TestSerializer.dpr True Debug Win32 Console None DCC32 12.3 true true Base true true Base true dcu\$(Project)\$(Config)\$(Platform) bin\$(Config)\$(Platform) false 00400000 WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias) false false false false false RELEASE;$(DCC_Define) 0 false DEBUG;$(DCC_Define) false true MainSource Cfg_2 Base Base Cfg_1 Base Delphi.Personality.12 VCLApplication TestSerializer.dpr False False 1 0 0 0 False False False False False 1031 1252 1.0.0.0 1.0.0.0 True 12 thrift-0.19.0/lib/delphi/test/serializer/TestSerializer.Tests.pas0000644000000000000000000003135414370300523025024 0ustar00rootroot00000000000000unit TestSerializer.Tests; (* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) interface uses Classes, Windows, SysUtils, Generics.Collections, Thrift, Thrift.Exception, Thrift.Socket, Thrift.Transport, Thrift.Protocol, Thrift.Protocol.JSON, Thrift.Protocol.Compact, Thrift.Collections, Thrift.Configuration, Thrift.Server, Thrift.Utils, Thrift.Serializer, Thrift.Stream, Thrift.WinHTTP, Thrift.TypeRegistry, System_, DebugProtoTest; {$TYPEINFO ON} type TFactoryPair = record prot : IProtocolFactory; trans : ITransportFactory; end; TTestSerializer = class //extends TestCase { private type TMethod = ( mt_Bytes, mt_Stream ); strict private FProtocols : TList< TFactoryPair>; procedure AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory); class function UserFriendlyName( const factory : TFactoryPair) : string; overload; class function UserFriendlyName( const method : TMethod) : string; overload; class function Serialize(const input : IBase; const factory : TFactoryPair) : TBytes; overload; class procedure Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream); overload; class procedure Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); overload; class procedure Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); overload; class procedure ValidateReadToEnd( const input : TBytes; const serial : TDeserializer); overload; class procedure ValidateReadToEnd( const input : TStream; const serial : TDeserializer); overload; class function LengthOf( const bytes : TBytes) : Integer; overload; inline; class function LengthOf( const bytes : IThriftBytes) : Integer; overload; inline; class function DataPtrOf( const bytes : TBytes) : Pointer; overload; inline; class function DataPtrOf( const bytes : IThriftBytes) : Pointer; overload; inline; procedure Test_Serializer_Deserializer; procedure Test_COM_Types; procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); public constructor Create; destructor Destroy; override; procedure RunTests; end; implementation const SERIALIZERDATA_DLL = 'SerializerData.dll'; function CreateOneOfEach : IOneOfEach; stdcall; external SERIALIZERDATA_DLL; function CreateNesting : INesting; stdcall; external SERIALIZERDATA_DLL; function CreateHolyMoley : IHolyMoley; stdcall; external SERIALIZERDATA_DLL; function CreateCompactProtoTestStruct : ICompactProtoTestStruct; stdcall; external SERIALIZERDATA_DLL; { TTestSerializer } constructor TTestSerializer.Create; begin inherited Create; FProtocols := TList< TFactoryPair>.Create; AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, nil); AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, nil); AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, nil); AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create); AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create); AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create); AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create); AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create); AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create); end; destructor TTestSerializer.Destroy; begin try FreeAndNil( FProtocols); finally inherited Destroy; end; end; procedure TTestSerializer.AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory); var rec : TFactoryPair; begin rec.prot := aProto; rec.trans := aTrans; FProtocols.Add( rec); end; class function TTestSerializer.LengthOf( const bytes : TBytes) : Integer; begin result := Length(bytes); end; class function TTestSerializer.LengthOf( const bytes : IThriftBytes) : Integer; begin if bytes <> nil then result := bytes.Count else result := 0; end; class function TTestSerializer.DataPtrOf( const bytes : TBytes) : Pointer; begin result := bytes; end; class function TTestSerializer.DataPtrOf( const bytes : IThriftBytes) : Pointer; begin if bytes <> nil then result := bytes.QueryRawDataPtr else result := nil; end; procedure TTestSerializer.Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); var tested, correct : IOneOfEach; bytes : TBytes; i : Integer; begin // write tested := CreateOneOfEach; case method of mt_Bytes: bytes := Serialize( tested, factory); mt_Stream: begin stream.Size := 0; Serialize( tested, factory, stream); end else ASSERT( FALSE); end; // init + read tested := TOneOfEachImpl.Create; case method of mt_Bytes: Deserialize( bytes, tested, factory); mt_Stream: begin stream.Position := 0; Deserialize( stream, tested, factory); end else ASSERT( FALSE); end; // check correct := CreateOneOfEach; ASSERT( tested.Im_true = correct.Im_true); ASSERT( tested.Im_false = correct.Im_false); ASSERT( tested.A_bite = correct.A_bite); ASSERT( tested.Integer16 = correct.Integer16); ASSERT( tested.Integer32 = correct.Integer32); ASSERT( tested.Integer64 = correct.Integer64); ASSERT( Abs( tested.Double_precision - correct.Double_precision) < 1E-12); ASSERT( tested.Some_characters = correct.Some_characters); ASSERT( tested.Zomg_unicode = correct.Zomg_unicode); ASSERT( tested.Rfc4122_uuid = correct.Rfc4122_uuid); ASSERT( tested.What_who = correct.What_who); ASSERT( LengthOf(tested.Base64) = LengthOf(correct.Base64)); ASSERT( CompareMem( DataPtrOf(tested.Base64), DataPtrOf(correct.Base64), LengthOf(correct.Base64))); ASSERT( tested.Byte_list.Count = correct.Byte_list.Count); for i := 0 to tested.Byte_list.Count-1 do ASSERT( tested.Byte_list[i] = correct.Byte_list[i]); ASSERT( tested.I16_list.Count = correct.I16_list.Count); for i := 0 to tested.I16_list.Count-1 do ASSERT( tested.I16_list[i] = correct.I16_list[i]); ASSERT( tested.I64_list.Count = correct.I64_list.Count); for i := 0 to tested.I64_list.Count-1 do ASSERT( tested.I64_list[i] = correct.I64_list[i]); end; procedure TTestSerializer.Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); var tested, correct : ICompactProtoTestStruct; bytes : TBytes; begin // write tested := CreateCompactProtoTestStruct; case method of mt_Bytes: bytes := Serialize( tested, factory); mt_Stream: begin stream.Size := 0; Serialize( tested, factory, stream); end else ASSERT( FALSE); end; // init + read correct := TCompactProtoTestStructImpl.Create; case method of mt_Bytes: Deserialize( bytes, tested, factory); mt_Stream: begin stream.Position := 0; Deserialize( stream, tested, factory); end else ASSERT( FALSE); end; // check correct := CreateCompactProtoTestStruct; ASSERT( correct.Field500 = tested.Field500); ASSERT( correct.Field5000 = tested.Field5000); ASSERT( correct.Field20000 = tested.Field20000); end; procedure TTestSerializer.Test_Serializer_Deserializer; var factory : TFactoryPair; stream : TFileStream; method : TMethod; begin stream := TFileStream.Create( 'TestSerializer.dat', fmCreate); try for method in [Low(TMethod)..High(TMethod)] do begin Writeln( UserFriendlyName(method)); for factory in FProtocols do begin Writeln('- '+UserFriendlyName(factory)); Test_OneOfEach( method, factory, stream); Test_CompactStruct( method, factory, stream); end; Writeln; end; finally stream.Free; end; end; class function TTestSerializer.UserFriendlyName( const factory : TFactoryPair) : string; begin result := Copy( (factory.prot as TObject).ClassName, 2, MAXINT); if factory.trans <> nil then result := Copy( (factory.trans as TObject).ClassName, 2, MAXINT) +' '+ result; result := StringReplace( result, 'Impl', '', [rfReplaceAll]); result := StringReplace( result, 'Transport.TFactory', '', [rfReplaceAll]); result := StringReplace( result, 'Protocol.TFactory', '', [rfReplaceAll]); end; class function TTestSerializer.UserFriendlyName( const method : TMethod) : string; const NAMES : array[TMethod] of string = ('TBytes','Stream'); begin result := NAMES[method]; end; procedure TTestSerializer.Test_COM_Types; var tested : IOneOfEach; begin {$IF cDebugProtoTest_Option_COM_types} ASSERT( SizeOf(TSomeEnum) = SizeOf(Int32)); // -> MINENUMSIZE 4 // try to set values that allocate memory tested := CreateOneOfEach; tested.Zomg_unicode := 'This is a test'; tested.Base64 := TThriftBytesImpl.Create( TEncoding.UTF8.GetBytes('abc')); {$IFEND} end; procedure TTestSerializer.RunTests; begin try Test_Serializer_Deserializer; Test_COM_Types; except on e:Exception do begin Writeln( e.ClassName+': '+ e.Message); Write('Hit ENTER to close ... '); Readln; end; end; end; class function TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair) : TBytes; var serial : TSerializer; config : IThriftConfiguration; begin config := TThriftConfigurationImpl.Create; //config.MaxMessageSize := 0; // we don't read anything here serial := TSerializer.Create( factory.prot, factory.trans, config); try result := serial.Serialize( input); finally serial.Free; end; end; class procedure TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream); var serial : TSerializer; config : IThriftConfiguration; begin config := TThriftConfigurationImpl.Create; //config.MaxMessageSize := 0; // we don't read anything here serial := TSerializer.Create( factory.prot, factory.trans, config); try serial.Serialize( input, aStream); finally serial.Free; end; end; class procedure TTestSerializer.Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); var serial : TDeserializer; config : IThriftConfiguration; begin config := TThriftConfigurationImpl.Create; config.MaxMessageSize := Length(input); serial := TDeserializer.Create( factory.prot, factory.trans, config); try serial.Deserialize( input, target); ValidateReadToEnd( input, serial); finally serial.Free; end; end; class procedure TTestSerializer.Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); var serial : TDeserializer; config : IThriftConfiguration; begin config := TThriftConfigurationImpl.Create; config.MaxMessageSize := input.Size; serial := TDeserializer.Create( factory.prot, factory.trans, config); try serial.Deserialize( input, target); ValidateReadToEnd( input, serial); finally serial.Free; end; end; class procedure TTestSerializer.ValidateReadToEnd( const input : TBytes; const serial : TDeserializer); // we should not have any more byte to read var dummy : IBase; begin try dummy := TOneOfEachImpl.Create; serial.Deserialize( input, dummy); raise EInOutError.Create('Expected exception not thrown?'); except on e:TTransportExceptionEndOfFile do {expected}; on e:Exception do raise; // unexpected end; end; class procedure TTestSerializer.ValidateReadToEnd( const input : TStream; const serial : TDeserializer); // we should not have any more byte to read var dummy : IBase; begin try input.Position := 0; dummy := TOneOfEachImpl.Create; serial.Deserialize( input, dummy); raise EInOutError.Create('Expected exception not thrown?'); except on e:TTransportExceptionEndOfFile do {expected}; on e:Exception do raise; // unexpected end; end; end. thrift-0.19.0/lib/delphi/test/serializer/TestSerializer.Data.pas0000644000000000000000000003555114370300523024576 0ustar00rootroot00000000000000(* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *) unit TestSerializer.Data; interface uses SysUtils, ActiveX, ComObj, Thrift.Protocol, Thrift.Collections, DebugProtoTest; type Fixtures = class public class function CreateOneOfEach : IOneOfEach; class function CreateNesting : INesting; class function CreateHolyMoley : IHolyMoley; class function CreateCompactProtoTestStruct : ICompactProtoTestStruct; // These byte arrays are serialized versions of the above structs. // They were serialized in binary protocol using thrift 0.6.x and are used to // test backwards compatibility with respect to the standard scheme. (* all data copied from JAVA version, to be used later public static final byte[] persistentBytesOneOfEach = new byte[] { $02, $00, $01, $01, $02, $00, $02, $00, $03, $00, $03, $D6, $06, $00, $04, $69, $78, $08, $00, $05, $01, $00, $00, $00, $0A, $00, $06, $00, $00, $00, $01, $65, $A0, $BC, $00, $04, $00, $07, $40, $09, $21, $FB, $54, $44, $2D, $18, $0B, $00, $08, $00, $00, $00, $0D, $4A, $53, $4F, $4E, $20, $54, $48, $49, $53, $21, $20, $22, $01, $0B, $00, $09, $00, $00, $00, $2E, $D3, $80, $E2, $85, $AE, $CE, $9D, $20, $D0, $9D, $CE, $BF, $E2, $85, $BF, $D0, $BE, $C9, $A1, $D0, $B3, $D0, $B0, $CF, $81, $E2, $84, $8E, $20, $CE, $91, $74, $74, $CE, $B1, $E2, $85, $BD, $CE, $BA, $EF, $BF, $BD, $E2, $80, $BC, $02, $00, $0A, $00, $0B, $00, $0B, $00, $00, $00, $06, $62, $61, $73, $65, $36, $34, $0F, $00, $0C, $03, $00, $00, $00, $03, $01, $02, $03, $0F, $00, $0D, $06, $00, $00, $00, $03, $00, $01, $00, $02, $00, $03, $0F, $00, $0E, $0A, $00, $00, $00, $03, $00, $00, $00, $00, $00, $00, $00, $01, $00, $00, $00, $00, $00, $00, $00, $02, $00, $00, $00, $00, $00, $00, $00, $03, $00 }; public static final byte[] persistentBytesNesting = new byte[] { $0C, $00, $01, $08, $00, $01, $00, $00, $7A, $69, $0B, $00, $02, $00, $00, $00, $13, $49, $20, $61, $6D, $20, $61, $20, $62, $6F, $6E, $6B, $2E, $2E, $2E, $20, $78, $6F, $72, $21, $00, $0C, $00, $02, $02, $00, $01, $01, $02, $00, $02, $00, $03, $00, $03, $D6, $06, $00, $04, $69, $78, $08, $00, $05, $01, $00, $00, $00, $0A, $00, $06, $00, $00, $00, $01, $65, $A0, $BC, $00, $04, $00, $07, $40, $09, $21, $FB, $54, $44, $2D, $18, $0B, $00, $08, $00, $00, $00, $0D, $4A, $53, $4F, $4E, $20, $54, $48, $49, $53, $21, $20, $22, $01, $0B, $00, $09, $00, $00, $00, $2E, $D3, $80, $E2, $85, $AE, $CE, $9D, $20, $D0, $9D, $CE, $BF, $E2, $85, $BF, $D0, $BE, $C9, $A1, $D0, $B3, $D0, $B0, $CF, $81, $E2, $84, $8E, $20, $CE, $91, $74, $74, $CE, $B1, $E2, $85, $BD, $CE, $BA, $EF, $BF, $BD, $E2, $80, $BC, $02, $00, $0A, $00, $0B, $00, $0B, $00, $00, $00, $06, $62, $61, $73, $65, $36, $34, $0F, $00, $0C, $03, $00, $00, $00, $03, $01, $02, $03, $0F, $00, $0D, $06, $00, $00, $00, $03, $00, $01, $00, $02, $00, $03, $0F, $00, $0E, $0A, $00, $00, $00, $03, $00, $00, $00, $00, $00, $00, $00, $01, $00, $00, $00, $00, $00, $00, $00, $02, $00, $00, $00, $00, $00, $00, $00, $03, $00, $00 }; public static final byte[] persistentBytesHolyMoley = new byte[] { $0F, $00, $01, $0C, $00, $00, $00, $02, $02, $00, $01, $01, $02, $00, $02, $00, $03, $00, $03, $23, $06, $00, $04, $69, $78, $08, $00, $05, $01, $00, $00, $00, $0A, $00, $06, $00, $00, $00, $01, $65, $A0, $BC, $00, $04, $00, $07, $40, $09, $21, $FB, $54, $44, $2D, $18, $0B, $00, $08, $00, $00, $00, $0D, $4A, $53, $4F, $4E, $20, $54, $48, $49, $53, $21, $20, $22, $01, $0B, $00, $09, $00, $00, $00, $2E, $D3, $80, $E2, $85, $AE, $CE, $9D, $20, $D0, $9D, $CE, $BF, $E2, $85, $BF, $D0, $BE, $C9, $A1, $D0, $B3, $D0, $B0, $CF, $81, $E2, $84, $8E, $20, $CE, $91, $74, $74, $CE, $B1, $E2, $85, $BD, $CE, $BA, $EF, $BF, $BD, $E2, $80, $BC, $02, $00, $0A, $00, $0B, $00, $0B, $00, $00, $00, $06, $62, $61, $73, $65, $36, $34, $0F, $00, $0C, $03, $00, $00, $00, $03, $01, $02, $03, $0F, $00, $0D, $06, $00, $00, $00, $03, $00, $01, $00, $02, $00, $03, $0F, $00, $0E, $0A, $00, $00, $00, $03, $00, $00, $00, $00, $00, $00, $00, $01, $00, $00, $00, $00, $00, $00, $00, $02, $00, $00, $00, $00, $00, $00, $00, $03, $00, $02, $00, $01, $01, $02, $00, $02, $00, $03, $00, $03, $D6, $06, $00, $04, $69, $78, $08, $00, $05, $01, $00, $00, $00, $0A, $00, $06, $00, $00, $00, $01, $65, $A0, $BC, $00, $04, $00, $07, $40, $09, $21, $FB, $54, $44, $2D, $18, $0B, $00, $08, $00, $00, $00, $0D, $4A, $53, $4F, $4E, $20, $54, $48, $49, $53, $21, $20, $22, $01, $0B, $00, $09, $00, $00, $00, $2E, $D3, $80, $E2, $85, $AE, $CE, $9D, $20, $D0, $9D, $CE, $BF, $E2, $85, $BF, $D0, $BE, $C9, $A1, $D0, $B3, $D0, $B0, $CF, $81, $E2, $84, $8E, $20, $CE, $91, $74, $74, $CE, $B1, $E2, $85, $BD, $CE, $BA, $EF, $BF, $BD, $E2, $80, $BC, $02, $00, $0A, $00, $0B, $00, $0B, $00, $00, $00, $06, $62, $61, $73, $65, $36, $34, $0F, $00, $0C, $03, $00, $00, $00, $03, $01, $02, $03, $0F, $00, $0D, $06, $00, $00, $00, $03, $00, $01, $00, $02, $00, $03, $0F, $00, $0E, $0A, $00, $00, $00, $03, $00, $00, $00, $00, $00, $00, $00, $01, $00, $00, $00, $00, $00, $00, $00, $02, $00, $00, $00, $00, $00, $00, $00, $03, $00, $0E, $00, $02, $0F, $00, $00, $00, $03, $0B, $00, $00, $00, $00, $0B, $00, $00, $00, $03, $00, $00, $00, $0F, $74, $68, $65, $6E, $20, $61, $20, $6F, $6E, $65, $2C, $20, $74, $77, $6F, $00, $00, $00, $06, $74, $68, $72, $65, $65, $21, $00, $00, $00, $06, $46, $4F, $55, $52, $21, $21, $0B, $00, $00, $00, $02, $00, $00, $00, $09, $61, $6E, $64, $20, $61, $20, $6F, $6E, $65, $00, $00, $00, $09, $61, $6E, $64, $20, $61, $20, $74, $77, $6F, $0D, $00, $03, $0B, $0F, $00, $00, $00, $03, $00, $00, $00, $03, $74, $77, $6F, $0C, $00, $00, $00, $02, $08, $00, $01, $00, $00, $00, $01, $0B, $00, $02, $00, $00, $00, $05, $57, $61, $69, $74, $2E, $00, $08, $00, $01, $00, $00, $00, $02, $0B, $00, $02, $00, $00, $00, $05, $57, $68, $61, $74, $3F, $00, $00, $00, $00, $05, $74, $68, $72, $65, $65, $0C, $00, $00, $00, $00, $00, $00, $00, $04, $7A, $65, $72, $6F, $0C, $00, $00, $00, $00, $00 }; *) private const kUnicodeBytes : packed array[0..43] of Byte = ( $d3, $80, $e2, $85, $ae, $ce, $9d, $20, $d0, $9d, $ce, $bf, $e2, $85, $bf, $d0, $be, $c9, $a1, $d0, $b3, $d0, $b0, $cf, $81, $e2, $84, $8e, $20, $ce, $91, $74, $74, $ce, $b1, $e2, $85, $bd, $ce, $ba, $83, $e2, $80, $bc); end; implementation class function Fixtures.CreateOneOfEach : IOneOfEach; var db : Double; us : Utf8String; begin result := TOneOfEachImpl.Create; result.setIm_true( TRUE); result.setIm_false( FALSE); result.setA_bite( ShortInt($D6)); result.setInteger16( 27000); result.setInteger32( 1 shl 24); result.setInteger64( Int64(6000) * Int64(1000) * Int64(1000)); db := Pi; result.setDouble_precision( db); result.setSome_characters( 'JSON THIS! \"\1'); // ?? SetLength( us, Length(kUnicodeBytes)); Move( kUnicodeBytes[0], us[1], Length(kUnicodeBytes)); // ?? SetString( us, PChar(@kUnicodeBytes[0]), Length(kUnicodeBytes)); // !! result.setZomg_unicode( UnicodeString( us)); result.Rfc4122_uuid := TGuid.Create('{00112233-4455-6677-8899-aabbccddeeff}'); {$IF cDebugProtoTest_Option_AnsiStr_Binary} result.SetBase64('base64'); {$ELSEIF cDebugProtoTest_Option_COM_Types} result.SetBase64( TThriftBytesImpl.Create( TEncoding.UTF8.GetBytes('base64'))); {$ELSE} result.SetBase64( TEncoding.UTF8.GetBytes('base64')); {$IFEND} // byte, i16, and i64 lists are populated by default constructor end; class function Fixtures.CreateNesting : INesting; var bonk : IBonk; begin bonk := TBonkImpl.Create; bonk.&Type := 31337; bonk.Message := 'I am a bonk... xor!'; result := TNestingImpl.Create; result.My_bonk := bonk; result.My_ooe := CreateOneOfEach; end; class function Fixtures.CreateHolyMoley : IHolyMoley; type TStringType = {$IF cDebugProtoTest_Option_COM_Types} WideString {$ELSE} String {$IFEND}; var big : IThriftList; stage1 : IThriftList; stage2 : IThriftList; b : IBonk; begin result := THolyMoleyImpl.Create; big := TThriftListImpl.Create; big.add( CreateOneOfEach); big.add( CreateNesting.my_ooe); result.Big := big; result.Big[0].setA_bite( $22); result.Big[0].setA_bite( $23); result.Contain := TThriftHashSetImpl< IThriftList>.Create; stage1 := TThriftListImpl.Create; stage1.add( 'and a one'); stage1.add( 'and a two'); result.Contain.add( stage1); stage1 := TThriftListImpl.Create; stage1.add( 'then a one, two'); stage1.add( 'three!'); stage1.add( 'FOUR!!'); result.Contain.add( stage1); stage1 := TThriftListImpl.Create; result.Contain.add( stage1); stage2 := TThriftListImpl.Create; result.Bonks := TThriftDictionaryImpl< TStringType, IThriftList< IBonk>>.Create; // one empty result.Bonks.Add( 'zero', stage2); // one with two stage2 := TThriftListImpl.Create; b := TBonkImpl.Create; b.&type := 1; b.message := 'Wait.'; stage2.Add( b); b := TBonkImpl.Create; b.&type := 2; b.message := 'What?'; stage2.Add( b); result.Bonks.Add( 'two', stage2); // one with three stage2 := TThriftListImpl.Create; b := TBonkImpl.Create; b.&type := 3; b.message := 'quoth'; stage2.Add( b); b := TBonkImpl.Create; b.&type := 4; b.message := 'the raven'; stage2.Add( b); b := TBonkImpl.Create; b.&type := 5; b.message := 'nevermore'; stage2.Add( b); result.bonks.Add( 'three', stage2); end; class function Fixtures.CreateCompactProtoTestStruct : ICompactProtoTestStruct; // superhuge compact proto test struct begin result := TCompactProtoTestStructImpl.Create; result.A_byte := DebugProtoTest.TConstants.COMPACT_TEST.A_byte; result.A_i16 := DebugProtoTest.TConstants.COMPACT_TEST.A_i16; result.A_i32 := DebugProtoTest.TConstants.COMPACT_TEST.A_i32; result.A_i64 := DebugProtoTest.TConstants.COMPACT_TEST.A_i64; result.A_double := DebugProtoTest.TConstants.COMPACT_TEST.A_double; result.A_string := DebugProtoTest.TConstants.COMPACT_TEST.A_string; result.A_binary := DebugProtoTest.TConstants.COMPACT_TEST.A_binary; result.True_field := DebugProtoTest.TConstants.COMPACT_TEST.True_field; result.False_field := DebugProtoTest.TConstants.COMPACT_TEST.False_field; result.Empty_struct_field := DebugProtoTest.TConstants.COMPACT_TEST.Empty_struct_field; result.Byte_list := DebugProtoTest.TConstants.COMPACT_TEST.Byte_list; result.I16_list := DebugProtoTest.TConstants.COMPACT_TEST.I16_list; result.I32_list := DebugProtoTest.TConstants.COMPACT_TEST.I32_list; result.I64_list := DebugProtoTest.TConstants.COMPACT_TEST.I64_list; result.Double_list := DebugProtoTest.TConstants.COMPACT_TEST.Double_list; result.String_list := DebugProtoTest.TConstants.COMPACT_TEST.String_list; result.Binary_list := DebugProtoTest.TConstants.COMPACT_TEST.Binary_list; result.Boolean_list := DebugProtoTest.TConstants.COMPACT_TEST.Boolean_list; result.Struct_list := DebugProtoTest.TConstants.COMPACT_TEST.Struct_list; result.Byte_set := DebugProtoTest.TConstants.COMPACT_TEST.Byte_set; result.I16_set := DebugProtoTest.TConstants.COMPACT_TEST.I16_set; result.I32_set := DebugProtoTest.TConstants.COMPACT_TEST.I32_set; result.I64_set := DebugProtoTest.TConstants.COMPACT_TEST.I64_set; result.Double_set := DebugProtoTest.TConstants.COMPACT_TEST.Double_set; result.String_set := DebugProtoTest.TConstants.COMPACT_TEST.String_set; result.String_set := DebugProtoTest.TConstants.COMPACT_TEST.String_set; result.String_set := DebugProtoTest.TConstants.COMPACT_TEST.String_set; result.Binary_set := DebugProtoTest.TConstants.COMPACT_TEST.Binary_set; result.Boolean_set := DebugProtoTest.TConstants.COMPACT_TEST.Boolean_set; result.Struct_set := DebugProtoTest.TConstants.COMPACT_TEST.Struct_set; result.Byte_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_byte_map; result.I16_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.I16_byte_map; result.I32_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.I32_byte_map; result.I64_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.I64_byte_map; result.Double_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.Double_byte_map; result.String_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.String_byte_map; result.Binary_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.Binary_byte_map; result.Boolean_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.Boolean_byte_map; result.Byte_i16_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_i16_map; result.Byte_i32_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_i32_map; result.Byte_i64_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_i64_map; result.Byte_double_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_double_map; result.Byte_string_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_string_map; result.Byte_binary_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_binary_map; result.Byte_boolean_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_boolean_map; result.List_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.List_byte_map; result.Set_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.Set_byte_map; result.Map_byte_map := DebugProtoTest.TConstants.COMPACT_TEST.Map_byte_map; result.Byte_map_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_map_map; result.Byte_set_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_set_map; result.Byte_list_map := DebugProtoTest.TConstants.COMPACT_TEST.Byte_list_map; result.Field500 := 500; result.Field5000 := 5000; result.Field20000 := 20000; {$IF cDebugProtoTest_Option_AnsiStr_Binary} result.A_binary := AnsiString( #0#1#2#3#4#5#6#7#8); {$ELSEIF cDebugProtoTest_Option_COM_Types} result.A_binary := TThriftBytesImpl.Create( TEncoding.UTF8.GetBytes( #0#1#2#3#4#5#6#7#8)); {$ELSE} result.A_binary := TEncoding.UTF8.GetBytes( #0#1#2#3#4#5#6#7#8); {$IFEND} end; end. thrift-0.19.0/lib/delphi/DelphiThrift.groupproj0000644000000000000000000001710314370300523021450 0ustar00rootroot00000000000000 {6BD327A5-7688-4263-B6A8-B15207CF4EC5} Default.Personality.12 thrift-0.19.0/lib/perl/0000755000000000000000000000000014472652660014623 5ustar00rootroot00000000000000thrift-0.19.0/lib/perl/Makefile.PL0000644000000000000000000000347314303740367016577 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use ExtUtils::MakeMaker; WriteMakefile( ABSTRACT => 'Apache Thrift is a software framework for scalable cross-language services development.', AUTHOR => 'Apache Thrift ', LICENSE => 'apache_2_0', MIN_PERL_VERSION => '5.010000', NAME => 'Thrift', NEEDS_LINKING => 0, PREREQ_PM => { 'Bit::Vector' => 0, 'Class::Accessor' => 0 }, # SIGN => 1, TEST_REQUIRES => { 'Test::Exception' => 0, }, VERSION_FROM => 'lib/Thrift.pm' ); # THRIFT-4691 package MY; # so that "SUPER" works right sub test { # Adds gen-perl and gen-perl2 to the test execution as include paths # Could not find anything in MakeMaker that would do this... my @result; for (@result = shift->SUPER::test(@_)) { s/\$\(TEST_FILES\)/-Igen-perl -Igen-perl2 \$(TEST_FILES)/ig; } @result; } thrift-0.19.0/lib/perl/Makefile.am0000644000000000000000000000601614370300523016643 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = t Makefile-perl.mk : Makefile.PL $(PERL) Makefile.PL MAKEFILE=Makefile-perl.mk INSTALLDIRS=$(INSTALLDIRS) INSTALL_BASE=$(PERL_PREFIX) all-local: Makefile-perl.mk $(MAKE) -f $< find blib -name 'Makefile*' -exec rm -f {} \; install-exec-local: Makefile-perl.mk $(MAKE) -f $< install DESTDIR=$(DESTDIR)/ clean-local: if test -f Makefile-perl.mk ; then \ $(MAKE) -f Makefile-perl.mk clean ; \ fi $(RM) Makefile-perl.mk.old $(RM) -r gen-perl gen-perl2 EXTRA_DIST = \ coding_standards.md \ build-cpan-dist.sh \ Makefile.PL \ MANIFEST.SKIP \ test.pl \ lib/Thrift.pm \ lib/Thrift.pm \ lib/Thrift/BinaryProtocol.pm \ lib/Thrift/BufferedTransport.pm \ lib/Thrift/Exception.pm \ lib/Thrift/FramedTransport.pm \ lib/Thrift/HttpClient.pm \ lib/Thrift/MemoryBuffer.pm \ lib/Thrift/MessageType.pm \ lib/Thrift/MultiplexedProcessor.pm \ lib/Thrift/MultiplexedProtocol.pm \ lib/Thrift/Protocol.pm \ lib/Thrift/ProtocolDecorator.pm \ lib/Thrift/Server.pm \ lib/Thrift/ServerSocket.pm \ lib/Thrift/Socket.pm \ lib/Thrift/SSLSocket.pm \ lib/Thrift/SSLServerSocket.pm \ lib/Thrift/UnixServerSocket.pm \ lib/Thrift/UnixSocket.pm \ lib/Thrift/Type.pm \ lib/Thrift/Transport.pm \ tools/FixupDist.pl \ README.md THRIFT = @top_builddir@/compiler/cpp/thrift THRIFT_IF = @top_srcdir@/test/v0.16/ThriftTest.thrift NAME_BENCHMARKSERVICE = @top_srcdir@/lib/rb/benchmark/Benchmark.thrift NAME_AGGR = @top_srcdir@/contrib/async-test/aggr.thrift THRIFTTEST_GEN = \ gen-perl/ThriftTest/Constants.pm \ gen-perl/ThriftTest/SecondService.pm \ gen-perl/ThriftTest/ThriftTest.pm \ gen-perl/ThriftTest/Types.pm BENCHMARK_GEN = \ gen-perl/BenchmarkService.pm \ gen-perl/Constants.pm \ gen-perl/Types.pm AGGR_GEN = \ gen-perl2/Aggr.pm \ gen-perl2/Constants.pm \ gen-perl2/Types.pm PERL_GEN = \ $(THRIFTTEST_GEN) \ $(BENCHMARK_GEN) \ $(AGGR_GEN) BUILT_SOURCES = $(PERL_GEN) check-local: $(PERL_GEN) $(PERL) -Iblib/lib -I@abs_srcdir@ -I@builddir@/gen-perl2 -I@builddir@/gen-perl \ @abs_srcdir@/test.pl @abs_srcdir@/t/*.t $(THRIFTTEST_GEN): $(THRIFT_IF) $(THRIFT) $(THRIFT) --gen perl $< $(BENCHMARK_GEN): $(NAME_BENCHMARKSERVICE) $(THRIFT) $(THRIFT) --gen perl $< $(AGGR_GEN): $(NAME_AGGR) $(THRIFT) $(MKDIR_P) gen-perl2 $(THRIFT) -out gen-perl2 --gen perl $< thrift-0.19.0/lib/perl/tools/0000755000000000000000000000000014472652660015763 5ustar00rootroot00000000000000thrift-0.19.0/lib/perl/tools/FixupDist.pl0000644000000000000000000000214414303740367020233 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # # This will fix up the distribution so that CPAN properly # indexes Thrift. # use 5.10.0; use strict; use warnings; use utf8; use Data::Dumper; use CPAN::Meta; my $meta = CPAN::Meta->load_file('META.json'); $meta->{'provides'} = { 'Thrift' => { 'file' => 'lib/Thrift.pm', 'version' => $meta->version() } }; $meta->save('META.json'); thrift-0.19.0/lib/perl/MANIFEST.SKIP0000644000000000000000000000026614303740367016520 0ustar00rootroot00000000000000blib/.*$ build-cpan-dist.sh FixupDist.pl MANIFEST.bak MANIFEST.SKIP MYMETA.json Makefile Makefile.am Makefile.in pm_to_blib t/Makefile t/Makefile.am t/Makefile.in tools/FixupDist.pl thrift-0.19.0/lib/perl/README.md0000644000000000000000000001050114303740367016072 0ustar00rootroot00000000000000Thrift Perl Software Library # Summary Apache Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages. A language-neutral IDL is used to generate functioning client libraries and server-side handling frameworks. # License Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. # For More Information See the [Apache Thrift Web Site](http://thrift.apache.org/) for more information. # Using Thrift with Perl Thrift requires Perl >= 5.10.0 Unexpected exceptions in a service handler are converted to TApplicationException with type INTERNAL ERROR and the string of the exception is delivered as the message. On the client side, exceptions are thrown with die, so be sure to wrap eval{} statments around any code that contains exceptions. Please see tutoral and test dirs for examples. The Perl ForkingServer ignores SIGCHLD allowing the forks to be reaped by the operating system naturally when they exit. This means one cannot use a custom SIGCHLD handler in the consuming perl implementation that calls serve(). It is acceptable to use a custom SIGCHLD handler within a thrift handler implementation as the ForkingServer resets the forked child process to use default signal handling. # Dependencies The following modules are not provided by Perl 5.10.0 but are required to use Thrift. ## Runtime * Bit::Vector * Class::Accessor ## Test This is only required when running tests: * Test::Exception ### HttpClient Transport These are only required if using Thrift::HttpClient: * HTTP::Request * IO::String * LWP::UserAgent ### SSL/TLS These are only required if using Thrift::SSLSocket or Thrift::SSLServerSocket: * IO::Socket::SSL # Breaking Changes ## 0.10.0 The socket classes were refactored in 0.10.0 so that there is one package per file. This means `use Socket;` no longer defines SSLSocket. You can use this technique to make your application run against 0.10.0 as well as earlier versions: `eval { require Thrift::SSLSocket; } or do { require Thrift::Socket; }` ## 0.11.0 * Namespaces of packages that were not scoped within Thrift have been fixed. ** TApplicationException is now Thrift::TApplicationException ** TException is now Thrift::TException ** TMessageType is now Thrift::TMessageType ** TProtocolException is now Thrift::TProtocolException ** TProtocolFactory is now Thrift::TProtocolFactory ** TTransportException is now Thrift::TTransportException ** TType is now Thrift::TType If you need a single version of your code to work with both older and newer thrift namespace changes, you can make the new, correct namespaces behave like the old ones in your files with this technique to create an alias, which will allow you code to run against either version of the perl runtime for thrift: `BEGIN {*TType:: = *Thrift::TType::}` * Packages found in Thrift.pm were moved into the Thrift/ directory in separate files: ** Thrift::TApplicationException is now in Thrift/Exception.pm ** Thrift::TException is now in Thrift/Exception.pm ** Thrift::TMessageType is now in Thrift/MessageType.pm ** Thrift::TType is now in Thrift/Type.pm If you need to modify your code to work against both older or newer thrift versions, you can deal with these changes in a backwards compatible way in your projects using eval: `eval { require Thrift::Exception; require Thrift::MessageType; require Thrift::Type; } or do { require Thrift; }` # Deprecations ## 0.11.0 Thrift::HttpClient setRecvTimeout() and setSendTimeout() are deprecated. Use setTimeout instead. thrift-0.19.0/lib/perl/coding_standards.md0000644000000000000000000000025214303740367020445 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md). Additional perl coding standards can be found in [perlstyle](http://perldoc.perl.org/perlstyle.html). thrift-0.19.0/lib/perl/build-cpan-dist.sh0000755000000000000000000000236314370300523020126 0ustar00rootroot00000000000000#!/bin/bash # # This script is intended to be used after tagging the repository and updating # the version files for a release. It will create a CPAN archive. Run this # from inside a docker image like ubuntu-focal. # set -e rm -f MANIFEST rm -rf Thrift-* # setup cpan without a prompt echo | cpan cpan install HTTP::Date Log::Log4perl cpan install CPAN cpan install CPAN::Meta ExtUtils::MakeMaker JSON::PP # cpan install Module::Signature perl Makefile.PL rm MYMETA.yml make manifest make dist # # We unpack the archive so we can add version metadata for CPAN # so that it properly indexes Thrift and remove unnecessary files. # echo '-----------------------------------------------------------' set -x DISTFILE=$(ls Thrift*.gz) NEWFILE=${DISTFILE/t-v/t-} if [[ "$DISTFILE" != "$NEWFILE" ]]; then mv $DISTFILE $NEWFILE DISTFILE="$NEWFILE" fi tar xzf $DISTFILE rm $DISTFILE DISTDIR=$(ls -d Thrift*) # cpan doesn't like "Thrift-v0.nn.0 as a directory name # needs to be Thrift-0.nn.0 NEWDIR=${DISTDIR/t-v/t-} if [[ "$DISTDIR" != "$NEWDIR" ]]; then mv $DISTDIR $NEWDIR DISTDIR="$NEWDIR" fi cd $DISTDIR cp -p ../Makefile.PL . cp -pr ../gen-perl . cp -pr ../gen-perl2 . perl ../tools/FixupDist.pl cd .. tar cvzf $DISTFILE $DISTDIR rm -r $DISTDIR thrift-0.19.0/lib/perl/test.pl0000644000000000000000000000152214303740367016132 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use strict; use warnings; use Test::Harness; runtests(@ARGV); thrift-0.19.0/lib/perl/t/0000755000000000000000000000000014472652660015066 5ustar00rootroot00000000000000thrift-0.19.0/lib/perl/t/Makefile.am0000644000000000000000000000150714303740367017120 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # EXTRA_DIST = memory_buffer.t processor.t multiplex.t thrift-0.19.0/lib/perl/t/memory_buffer.t0000644000000000000000000000311314303740367020105 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use Test::More tests => 7; use Test::Exception; use strict; use warnings; use Data::Dumper; use Thrift::BinaryProtocol; use Thrift::MemoryBuffer; use ThriftTest::Types; my $transport = Thrift::MemoryBuffer->new(); my $protocol = Thrift::BinaryProtocol->new($transport); throws_ok { $protocol->readByte } 'Thrift::TTransportException'; my $a = ThriftTest::Xtruct->new(); $a->i32_thing(10); $a->i64_thing(30); $a->string_thing('Hello, world!'); $a->write($protocol); my $b = ThriftTest::Xtruct->new(); $b->read($protocol); is($b->i32_thing, $a->i32_thing); is($b->i64_thing, $a->i64_thing); is($b->string_thing, $a->string_thing); $b->write($protocol); my $c = ThriftTest::Xtruct->new(); $c->read($protocol); is($c->i32_thing, $a->i32_thing); is($c->i64_thing, $a->i64_thing); is($c->string_thing, $a->string_thing); thrift-0.19.0/lib/perl/t/processor.t0000644000000000000000000000554014303740367017271 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use Test::More tests => 2; use strict; use warnings; use Thrift::BinaryProtocol; use Thrift::MemoryBuffer; use Thrift::MessageType; use ThriftTest::ThriftTest; use ThriftTest::Types; use Data::Dumper; my $buffer = Thrift::MemoryBuffer->new(1024); my $protocol = Thrift::BinaryProtocol->new($buffer); my $client = ThriftTest::ThriftTestClient->new($protocol); $buffer->open(); $client->send_testString("foo"); $client->{seqid}++; $client->send_testString("bar"); my $client_command_binary = $buffer->getBuffer; $buffer->resetBuffer; # Process by server my $server_output_binary; { my $protocol_factory = Thrift::BinaryProtocolFactory->new(); my $input_buffer = Thrift::MemoryBuffer->new(); $input_buffer->write($client_command_binary); my $input_protocol = $protocol_factory->getProtocol($input_buffer); my $output_buffer = Thrift::MemoryBuffer->new(); my $output_protocol = $protocol_factory->getProtocol($output_buffer); my $processor = ThriftTest::ThriftTestProcessor->new( My::ThriftTest->new() ); my $result = $processor->process($input_protocol, $output_protocol); print "process resulted in $result\n"; $result = $processor->process($input_protocol, $output_protocol); print "process resulted in $result\n"; $server_output_binary = $output_buffer->getBuffer(); } $buffer->write($server_output_binary); foreach my $val (("got foo","got bar")){ my ($function_name, $message_type, $sequence_id); $protocol->readMessageBegin(\$function_name, \$message_type, \$sequence_id); print " $function_name, $message_type, $sequence_id\n"; if ($message_type == Thrift::TMessageType::EXCEPTION) { die; } my $result = ThriftTest::ThriftTest_testString_result->new(); $result->read($protocol); $protocol->readMessageEnd(); is($result->success(),$val); } package My::ThriftTest; use strict; use warnings; use Data::Dumper; sub new { my $class = shift; return bless {}, $class; } sub testString { my ($self, $string) = @_; print __PACKAGE__ . "->testString()\n"; return "got ".$string; } thrift-0.19.0/lib/perl/t/Makefile.in0000644000000000000000000004220214472652517017134 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/perl/t ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = memory_buffer.t processor.t multiplex.t all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/perl/t/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/perl/t/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/perl/t/multiplex.t0000644000000000000000000001175514303740367017302 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use Test::More tests => 6; use strict; use warnings; use Thrift::BinaryProtocol; use Thrift::FramedTransport; use Thrift::MemoryBuffer; use Thrift::MessageType; use Thrift::MultiplexedProcessor; use Thrift::Server; use Thrift::Socket; use BenchmarkService; use Aggr; use constant NAME_BENCHMARKSERVICE => 'BenchmarkService'; use constant NAME_AGGR => 'Aggr'; my $buffer = Thrift::MemoryBuffer->new(1024); my $aggr_protocol = Thrift::MultiplexedProtocol->new(Thrift::BinaryProtocol->new($buffer), NAME_AGGR); my $aggr_client = AggrClient->new($aggr_protocol); my $benchmark_protocol = Thrift::MultiplexedProtocol->new(Thrift::BinaryProtocol->new($buffer), NAME_BENCHMARKSERVICE); my $benchmark_client = BenchmarkServiceClient->new($benchmark_protocol); $buffer->open(); for(my $i = 1; $i <= 5; $i++) { $aggr_client->send_addValue($i); $aggr_client->{seqid}++; } $aggr_client->send_getValues(); for(my $i = 1; $i <= 5; $i++) { $benchmark_client->send_fibonacci($i); $benchmark_client->{seqid}++; } $benchmark_client->{seqid}--; my $client_command_binary = $buffer->getBuffer; $buffer->resetBuffer; # Process by server my $server_output_binary; { my $benchmark_handler = My::BenchmarkService->new(); my $benchmark_processor = BenchmarkServiceProcessor->new($benchmark_handler); my $aggr_handler = My::Aggr->new(); my $aggr_processor = AggrProcessor->new($aggr_handler); my $protocol_factory = Thrift::BinaryProtocolFactory->new(); my $input_buffer = Thrift::MemoryBuffer->new(); $input_buffer->write($client_command_binary); my $input_protocol = $protocol_factory->getProtocol($input_buffer); my $output_buffer = Thrift::MemoryBuffer->new(); my $output_protocol = $protocol_factory->getProtocol($output_buffer); my $processor = Thrift::MultiplexedProcessor->new(); $processor->registerProcessor(NAME_BENCHMARKSERVICE, $benchmark_processor); $processor->registerProcessor(NAME_AGGR, $aggr_processor); my $result; for(my $i = 1; $i <= 11; $i++) { $result = $processor->process($input_protocol, $output_protocol); print "process resulted in $result\n"; } $server_output_binary = $output_buffer->getBuffer(); } $buffer->write($server_output_binary); for(my $i = 1; $i <= 5; $i++) { my ($function_name, $message_type, $sequence_id); $aggr_protocol->readMessageBegin(\$function_name, \$message_type, \$sequence_id); if ($message_type == Thrift::TMessageType::EXCEPTION) { die; } my $aggr_result = Aggr_addValue_result->new(); $aggr_result->read($aggr_protocol); $aggr_protocol->readMessageEnd(); } my ($function_name, $message_type, $sequence_id); $aggr_protocol->readMessageBegin(\$function_name, \$message_type, \$sequence_id); if ($message_type == Thrift::TMessageType::EXCEPTION) { die; } my $aggr_result = Aggr_getValues_result->new(); $aggr_result->read($aggr_protocol); $aggr_protocol->readMessageEnd(); is_deeply($aggr_result->success(), [1,2,3,4,5]); foreach my $val((1,2,3,5,8)) { my ($function_name, $message_type, $sequence_id); $benchmark_protocol->readMessageBegin(\$function_name, \$message_type, \$sequence_id); if ($message_type == Thrift::TMessageType::EXCEPTION) { die; } my $benchmark_result = BenchmarkService_fibonacci_result->new(); $benchmark_result->read($benchmark_protocol); $benchmark_protocol->readMessageEnd(); is($benchmark_result->success(), $val); } package My::Aggr; use base qw(AggrIf); use strict; use warnings; sub new { my $classname = shift; my $self = {}; $self->{values} = (); return bless($self,$classname); } sub addValue{ my $self = shift; my $value = shift; push (@{$self->{values}}, $value); } sub getValues{ my $self = shift; return $self->{values}; } package My::BenchmarkService; use base qw(BenchmarkServiceIf); use strict; use warnings; sub new { my $class = shift; return bless {}, $class; } sub fibonacci { my ($self, $n) = @_; my $prev = 0; my $next; my $result = 1; while ($n > 0) { $next = $result + $prev; $prev = $result; $result = $next; --$n; } return $result; } thrift-0.19.0/lib/perl/lib/0000755000000000000000000000000014472652660015371 5ustar00rootroot00000000000000thrift-0.19.0/lib/perl/lib/Thrift/0000755000000000000000000000000014472652660016631 5ustar00rootroot00000000000000thrift-0.19.0/lib/perl/lib/Thrift/Transport.pm0000644000000000000000000000630514303740367021162 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Exception; # # Transport exceptions # package Thrift::TTransportException; use base('Thrift::TException'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant UNKNOWN => 0; use constant NOT_OPEN => 1; use constant ALREADY_OPEN => 2; use constant TIMED_OUT => 3; use constant END_OF_FILE => 4; sub new { my $classname = shift; my $self = $classname->SUPER::new(@_); return bless($self,$classname); } package Thrift::Transport; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Whether this transport is open. # # @return boolean true if open # sub isOpen { die 'abstract'; } # # Open the transport for reading/writing # # @throws TTransportException if cannot open # sub open { die 'abstract'; } # # Close the transport. # sub close { die 'abstract'; } # # Read some data into the array. # # @param int $len How much to read # @return string The data that has been read # @throws TTransportException if cannot read any more data # sub read { die 'abstract'; } # # Guarantees that the full amount of data is read. # # @return string The data, of exact length # @throws TTransportException if cannot read data # sub readAll { my $self = shift; my $len = shift; my $data = ''; my $got = 0; while (($got = length($data)) < $len) { $data .= $self->read($len - $got); } return $data; } # # Writes the given data out. # # @param string $buf The data to write # @throws TTransportException if writing fails # sub write { die 'abstract'; } # # Flushes any pending data out of a buffer # # @throws TTransportException if a writing error occurs # sub flush {} # # TransportFactory creates transport objects from transports # package Thrift::TransportFactory; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = {}; return bless($self,$classname); } # # Build a transport from the base transport # # @return Thrift::Transport transport # sub getTransport { my $self = shift; my $trans = shift; return $trans; } # # ServerTransport base class module # package Thrift::ServerTransport; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub listen { die 'abstract'; } sub accept { die 'abstract'; } sub close { die 'abstract'; } 1; thrift-0.19.0/lib/perl/lib/Thrift/Socket.pm0000644000000000000000000001516714303740367020424 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Exception; use Thrift::Transport; use IO::Socket::INET; use IO::Select; package Thrift::Socket; use base qw( Thrift::Transport ); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Construction and usage # # my $opts = {} # my $socket = Thrift::Socket->new(\%opts); # # options: # # host => host to connect to # port => port to connect to # sendTimeout => timeout used for send and for connect # recvTimeout => timeout used for recv # sub new { my $classname = shift; my $opts = shift; # default settings: my $self = { host => 'localhost', port => 9090, recvTimeout => 10000, sendTimeout => 10000, proto => 'tcp', handle => undef }; if (defined $opts and ref $opts eq ref {}) { # argument is a hash of options so override the defaults $self->{$_} = $opts->{$_} for keys %$opts; } else { # older style constructor takes 3 arguments, none of which are required $self->{host} = $opts || 'localhost'; $self->{port} = shift || 9090; } return bless($self,$classname); } sub setSendTimeout { my $self = shift; my $timeout = shift; $self->{sendTimeout} = $timeout; } sub setRecvTimeout { my $self = shift; my $timeout = shift; $self->{recvTimeout} = $timeout; } # # Tests whether this is open # # @return bool true if the socket is open # sub isOpen { my $self = shift; if( defined $self->{handle} ){ return ($self->{handle}->handles())[0]->connected; } return 0; } # # Connects the socket. # sub open { my $self = shift; my $sock = $self->__open() || do { my $error = ref($self).': Could not connect to '.$self->{host}.':'.$self->{port}.' ('.$!.')'; die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN); }; $self->{handle} = IO::Select->new( $sock ); } # # Closes the socket. # sub close { my $self = shift; if( defined $self->{handle} ) { $self->__close(); } } # # Uses stream get contents to do the reading # # @param int $len How many bytes # @return string Binary data # sub readAll { my $self = shift; my $len = shift; return unless defined $self->{handle}; my $pre = ""; while (1) { my $sock = $self->__wait(); my $buf = $self->__recv($sock, $len); if (!defined $buf || $buf eq '') { die Thrift::TTransportException->new(ref($self).': Could not read '.$len.' bytes from '. $self->{host}.':'.$self->{port}, Thrift::TTransportException::END_OF_FILE); } elsif ((my $sz = length($buf)) < $len) { $pre .= $buf; $len -= $sz; } else { return $pre.$buf; } } } # # Read from the socket # # @param int $len How many bytes # @return string Binary data # sub read { my $self = shift; my $len = shift; return unless defined $self->{handle}; my $sock = $self->__wait(); my $buf = $self->__recv($sock, $len); if (!defined $buf || $buf eq '') { die Thrift::TTransportException->new(ref($self).': Could not read '.$len.' bytes from '. $self->{host}.':'.$self->{port}, Thrift::TTransportException::END_OF_FILE); } return $buf; } # # Write to the socket. # # @param string $buf The data to write # sub write { my $self = shift; my $buf = shift; return unless defined $self->{handle}; while (length($buf) > 0) { #check for timeout my @sockets = $self->{handle}->can_write( $self->{sendTimeout} / 1000 ); if(@sockets == 0){ die Thrift::TTransportException->new(ref($self).': timed out writing to bytes from '. $self->{host}.':'.$self->{port}, Thrift::TTransportException::TIMED_OUT); } my $sent = $self->__send($sockets[0], $buf); if (!defined $sent || $sent == 0 ) { die Thrift::TTransportException->new(ref($self).': Could not write '.length($buf).' bytes '. $self->{host}.':'.$self->{host}, Thrift::TTransportException::END_OF_FILE); } $buf = substr($buf, $sent); } } # # Flush output to the socket. # sub flush { my $self = shift; return unless defined $self->{handle}; my $ret = ($self->{handle}->handles())[0]->flush; } ### ### Overridable methods ### # # Open a connection to a server. # sub __open { my $self = shift; return IO::Socket::INET->new(PeerAddr => $self->{host}, PeerPort => $self->{port}, Proto => $self->{proto}, Timeout => $self->{sendTimeout} / 1000); } # # Close the connection # sub __close { my $self = shift; CORE::close(($self->{handle}->handles())[0]); } # # Read data # # @param[in] $sock the socket # @param[in] $len the length to read # @returns the data buffer that was read # sub __recv { my $self = shift; my $sock = shift; my $len = shift; my $buf = undef; $sock->recv($buf, $len); return $buf; } # # Send data # # @param[in] $sock the socket # @param[in] $buf the data buffer # @returns the number of bytes written # sub __send { my $self = shift; my $sock = shift; my $buf = shift; return $sock->send($buf); } # # Wait for data to be readable # # @returns a socket that can be read # sub __wait { my $self = shift; my @sockets = $self->{handle}->can_read( $self->{recvTimeout} / 1000 ); if (@sockets == 0) { die Thrift::TTransportException->new(ref($self).': timed out reading from '. $self->{host}.':'.$self->{port}, Thrift::TTransportException::TIMED_OUT); } return $sockets[0]; } 1; thrift-0.19.0/lib/perl/lib/Thrift/MultiplexedProtocol.pm0000644000000000000000000000371314303740367023204 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::MessageType; use Thrift::Protocol; use Thrift::ProtocolDecorator; package Thrift::MultiplexedProtocol; use base qw(Thrift::ProtocolDecorator); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant SEPARATOR => ':'; sub new { my $classname = shift; my $protocol = shift; my $serviceName = shift; my $self = $classname->SUPER::new($protocol); $self->{serviceName} = $serviceName; return bless($self,$classname); } # # Writes the message header. # Prepends the service name to the function name, separated by MultiplexedProtocol::SEPARATOR. # # @param string $name Function name. # @param int $type Message type. # @param int $seqid The sequence id of this message. # sub writeMessageBegin { my $self = shift; my ($name, $type, $seqid) = @_; if ($type == Thrift::TMessageType::CALL || $type == Thrift::TMessageType::ONEWAY) { my $nameWithService = $self->{serviceName}.SEPARATOR.$name; $self->SUPER::writeMessageBegin($nameWithService, $type, $seqid); } else { $self->SUPER::writeMessageBegin($name, $type, $seqid); } } 1; thrift-0.19.0/lib/perl/lib/Thrift/BinaryProtocol.pm0000644000000000000000000002117614303740367022137 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Bit::Vector; use Encode; use Thrift; use Thrift::Exception; use Thrift::MessageType; use Thrift::Protocol; use Thrift::Type; use utf8; # # Binary implementation of the Thrift protocol. # package Thrift::BinaryProtocol; use base('Thrift::Protocol'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant VERSION_MASK => 0xffff0000; use constant VERSION_1 => 0x80010000; use constant IS_BIG_ENDIAN => unpack('h*', pack('s', 1)) =~ m/01/; sub new { my $classname = shift; my $trans = shift; my $self = $classname->SUPER::new($trans); return bless($self,$classname); } sub writeMessageBegin { my $self = shift; my ($name, $type, $seqid) = @_; return $self->writeI32(VERSION_1 | $type) + $self->writeString($name) + $self->writeI32($seqid); } sub writeMessageEnd { my $self = shift; return 0; } sub writeStructBegin { my $self = shift; my $name = shift; return 0; } sub writeStructEnd { my $self = shift; return 0; } sub writeFieldBegin { my $self = shift; my ($fieldName, $fieldType, $fieldId) = @_; return $self->writeByte($fieldType) + $self->writeI16($fieldId); } sub writeFieldEnd { my $self = shift; return 0; } sub writeFieldStop { my $self = shift; return $self->writeByte(Thrift::TType::STOP); } sub writeMapBegin { my $self = shift; my ($keyType, $valType, $size) = @_; return $self->writeByte($keyType) + $self->writeByte($valType) + $self->writeI32($size); } sub writeMapEnd { my $self = shift; return 0; } sub writeListBegin { my $self = shift; my ($elemType, $size) = @_; return $self->writeByte($elemType) + $self->writeI32($size); } sub writeListEnd { my $self = shift; return 0; } sub writeSetBegin { my $self = shift; my ($elemType, $size) = @_; return $self->writeByte($elemType) + $self->writeI32($size); } sub writeSetEnd { my $self = shift; return 0; } sub writeBool { my $self = shift; my $value = shift; my $data = pack('c', $value ? 1 : 0); $self->{trans}->write($data, 1); return 1; } sub writeByte { my $self = shift; my $value= shift; my $data = pack('c', $value); $self->{trans}->write($data, 1); return 1; } sub writeI16 { my $self = shift; my $value= shift; my $data = pack('n', $value); $self->{trans}->write($data, 2); return 2; } sub writeI32 { my $self = shift; my $value= shift; my $data = pack('N', $value); $self->{trans}->write($data, 4); return 4; } sub writeI64 { my $self = shift; my $value= shift; my $data; my $vec; #stop annoying error $vec = Bit::Vector->new_Dec(64, $value); $data = pack 'NN', $vec->Chunk_Read(32, 32), $vec->Chunk_Read(32, 0); $self->{trans}->write($data, 8); return 8; } sub writeDouble { my $self = shift; my $value= shift; my $data = pack('d', $value); if (IS_BIG_ENDIAN) { $self->{trans}->write($data, 8); } else { $self->{trans}->write(scalar reverse($data), 8); } return 8; } sub writeString{ my $self = shift; my $value= shift; if( utf8::is_utf8($value) ){ $value = Encode::encode_utf8($value); } my $len = length($value); my $result = $self->writeI32($len); if ($len) { $self->{trans}->write($value,$len); } return $result + $len; } # #All references # sub readMessageBegin { my $self = shift; my ($name, $type, $seqid) = @_; my $version = 0; my $result = $self->readI32(\$version); if (($version & VERSION_MASK) > 0) { if (($version & VERSION_MASK) != VERSION_1) { die Thrift::TProtocolException->new('Missing version identifier', Thrift::TProtocolException::BAD_VERSION); } $$type = $version & 0x000000ff; return $result + $self->readString($name) + $self->readI32($seqid); } else { # old client support code return $result + $self->readStringBody($name, $version) + # version here holds the size of the string $self->readByte($type) + $self->readI32($seqid); } } sub readMessageEnd { my $self = shift; return 0; } sub readStructBegin { my $self = shift; my $name = shift; $$name = ''; return 0; } sub readStructEnd { my $self = shift; return 0; } sub readFieldBegin { my $self = shift; my ($name, $fieldType, $fieldId) = @_; my $result = $self->readByte($fieldType); if ($$fieldType == Thrift::TType::STOP) { $$fieldId = 0; return $result; } $result += $self->readI16($fieldId); return $result; } sub readFieldEnd() { my $self = shift; return 0; } sub readMapBegin { my $self = shift; my ($keyType, $valType, $size) = @_; return $self->readByte($keyType) + $self->readByte($valType) + $self->readI32($size); } sub readMapEnd() { my $self = shift; return 0; } sub readListBegin { my $self = shift; my ($elemType, $size) = @_; return $self->readByte($elemType) + $self->readI32($size); } sub readListEnd { my $self = shift; return 0; } sub readSetBegin { my $self = shift; my ($elemType, $size) = @_; return $self->readByte($elemType) + $self->readI32($size); } sub readSetEnd { my $self = shift; return 0; } sub readBool { my $self = shift; my $value = shift; my $data = $self->{trans}->readAll(1); my @arr = unpack('c', $data); $$value = $arr[0] == 1; return 1; } sub readByte { my $self = shift; my $value = shift; my $data = $self->{trans}->readAll(1); my @arr = unpack('c', $data); $$value = $arr[0]; return 1; } sub readI16 { my $self = shift; my $value = shift; my $data = $self->{trans}->readAll(2); my @arr = unpack('n', $data); $$value = $arr[0]; if ($$value > 0x7fff) { $$value = 0 - (($$value - 1) ^ 0xffff); } return 2; } sub readI32 { my $self = shift; my $value= shift; my $data = $self->{trans}->readAll(4); my @arr = unpack('N', $data); $$value = $arr[0]; if ($$value > 0x7fffffff) { $$value = 0 - (($$value - 1) ^ 0xffffffff); } return 4; } sub readI64 { my $self = shift; my $value = shift; my $data = $self->{trans}->readAll(8); my ($hi,$lo)=unpack('NN',$data); my $vec = Bit::Vector->new(64); $vec->Chunk_Store(32,32,$hi); $vec->Chunk_Store(32,0,$lo); $$value = $vec->to_Dec(); return 8; } sub readDouble { my $self = shift; my $value = shift; my $data; if (IS_BIG_ENDIAN) { $data = $self->{trans}->readAll(8); } else { $data = scalar reverse($self->{trans}->readAll(8)); } my @arr = unpack('d', $data); $$value = $arr[0]; return 8; } sub readString { my $self = shift; my $value = shift; my $len; my $result = $self->readI32(\$len); if ($len) { $$value = $self->{trans}->readAll($len); } else { $$value = ''; } return $result + $len; } sub readStringBody { my $self = shift; my $value = shift; my $len = shift; if ($len) { $$value = $self->{trans}->readAll($len); } else { $$value = ''; } return $len; } # # Binary Protocol Factory # package Thrift::BinaryProtocolFactory; use base('Thrift::TProtocolFactory'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = $classname->SUPER::new(); return bless($self,$classname); } sub getProtocol{ my $self = shift; my $trans = shift; return Thrift::BinaryProtocol->new($trans); } 1; thrift-0.19.0/lib/perl/lib/Thrift/SSLSocket.pm0000644000000000000000000000705114303740367020777 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Socket; use IO::Socket::SSL; package Thrift::SSLSocket; use base qw( Thrift::Socket ); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Construction and usage # # my $opts = {} # my $socket = Thrift::SSLSocket->new(\%opts); # # options: # # Any option from Socket.pm is valid, and then: # # ca => certificate authority file (PEM file) to authenticate the # server against; if not specified then the server is not # authenticated # cert => certificate to use as the client; if not specified then # the client does not present one but still connects using # secure protocol # ciphers => allowed cipher list # (see http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS) # key => certificate key for "cert" option # version => acceptable SSL/TLS versions - if not specified then the # default is to use SSLv23 handshake but only negotiate # at TLSv1.0 or later # sub new { my $classname = shift; my $self = $classname->SUPER::new(@_); return bless($self, $classname); } sub __open { my $self = shift; my $opts = {PeerAddr => $self->{host}, PeerPort => $self->{port}, Proto => 'tcp', Timeout => $self->{sendTimeout} / 1000}; my $verify = IO::Socket::SSL::SSL_VERIFY_PEER | IO::Socket::SSL::SSL_VERIFY_FAIL_IF_NO_PEER_CERT | IO::Socket::SSL::SSL_VERIFY_CLIENT_ONCE; $opts->{SSL_ca_file} = $self->{ca} if defined $self->{ca}; $opts->{SSL_cert_file} = $self->{cert} if defined $self->{cert}; $opts->{SSL_cipher_list} = $self->{ciphers} if defined $self->{ciphers}; $opts->{SSL_key_file} = $self->{key} if defined $self->{key}; $opts->{SSL_use_cert} = (defined $self->{cert}) ? 1 : 0; $opts->{SSL_verify_mode} = (defined $self->{ca}) ? $verify : IO::Socket::SSL::SSL_VERIFY_NONE; $opts->{SSL_version} = (defined $self->{version}) ? $self->{version} : 'SSLv23:!SSLv3:!SSLv2'; return IO::Socket::SSL->new(%$opts); } sub __close { my $self = shift; my $sock = ($self->{handle}->handles())[0]; if ($sock) { $sock->close(SSL_no_shutdown => 1); } } sub __recv { my $self = shift; my $sock = shift; my $len = shift; my $buf = undef; if ($sock) { sysread($sock, $buf, $len); } return $buf; } sub __send { my $self = shift; my $sock = shift; my $buf = shift; return syswrite($sock, $buf); } sub __wait { my $self = shift; my $sock = ($self->{handle}->handles())[0]; if ($sock and $sock->pending() eq 0) { return $self->SUPER::__wait(); } return $sock; } 1; thrift-0.19.0/lib/perl/lib/Thrift/ServerSocket.pm0000644000000000000000000000603614303740367021606 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use IO::Socket::INET; use IO::Select; use Thrift; use Thrift::Transport; use Thrift::Socket; package Thrift::ServerSocket; use base qw( Thrift::ServerTransport ); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Constructor. # Legacy construction takes one argument, port number. # New construction takes a hash: # @param[in] host host interface to listen on (undef = all interfaces) # @param[in] port port number to listen on (required) # @param[in] queue the listen queue size (default if not specified is 128) # @example my $serversock = Thrift::ServerSocket->new(host => undef, port => port) # sub new { my $classname = shift; my $args = shift; my $self; # Support both old-style "port number" construction and newer... if (ref($args) eq 'HASH') { $self = $args; } else { $self = { port => $args }; } if (not defined $self->{queue}) { $self->{queue} = 128; } return bless($self, $classname); } sub listen { my $self = shift; my $sock = $self->__listen() || do { my $error = ref($self) . ': Could not bind to ' . '*:' . $self->{port} . ' (' . $! . ')'; if ($self->{debug}) { $self->{debugHandler}->($error); } die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN); }; $self->{handle} = $sock; } sub accept { my $self = shift; if ( exists $self->{handle} and defined $self->{handle} ) { my $client = $self->{handle}->accept(); my $result = $self->__client(); $result->{handle} = IO::Select->new($client); return $result; } return undef; } sub close { my $self = shift; if ( exists $self->{handle} and defined $self->{handle} ) { $self->{handle}->close(); } } ### ### Overridable methods ### sub __client { return Thrift::Socket->new(); } sub __listen { my $self = shift; return IO::Socket::INET->new(LocalAddr => $self->{host}, LocalPort => $self->{port}, Proto => 'tcp', Listen => $self->{queue}, ReuseAddr => 1); } 1; thrift-0.19.0/lib/perl/lib/Thrift/UnixServerSocket.pm0000644000000000000000000000453614303740367022455 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::ServerSocket; use Thrift::UnixSocket; use IO::Socket::UNIX; package Thrift::UnixServerSocket; use base qw( Thrift::ServerSocket ); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Constructor. # If a single argument is given that is not a hash, that is the unix domain socket path. # If a single argument is given that is a hash: # @param[in] path unix domain socket file name # @param[in] queue the listen queue size (default is not specified is supplied by ServerSocket) # @example my $serversock = Thrift::UnixServerSocket->new($path); # @example my $serversock = Thrift::UnixServerSocket->new(path => "somepath", queue => 64); # sub new { my $classname = shift; my $args = shift; my $self; if (ref($args) eq 'HASH') { $self = $classname->SUPER::new($args); } else { $self = $classname->SUPER::new(); $self->{path} = $args; } return bless($self, $classname); } sub __client { return Thrift::UnixSocket->new(); } sub __listen { my $self = shift; my $sock = IO::Socket::UNIX->new( Type => IO::Socket::SOCK_STREAM, Local => $self->{path}, Listen => $self->{queue}) || do { my $error = 'UnixServerSocket: Could not bind to ' . $self->{path} . ' (' . $! . ')'; if ($self->{debug}) { $self->{debugHandler}->($error); } die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN); }; return $sock; } 1; thrift-0.19.0/lib/perl/lib/Thrift/ProtocolDecorator.pm0000644000000000000000000001544214303740367022634 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Protocol; package Thrift::ProtocolDecorator; use base qw(Thrift::Protocol); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $protocol = shift; my $self = $classname->SUPER::new($protocol->getTransport()); $self->{concreteProtocol} = $protocol; return bless($self,$classname); } # # Writes the message header # # @param string $name Function name # @param int $type message type TMessageType::CALL or TMessageType::REPLY # @param int $seqid The sequence id of this message # sub writeMessageBegin { my $self = shift; my ($name, $type, $seqid) = @_; return $self->{concreteProtocol}->writeMessageBegin($name, $type, $seqid); } # # Close the message # sub writeMessageEnd { my $self = shift; return $self->{concreteProtocol}->writeMessageEnd(); } # # Writes a struct header. # # @param string $name Struct name # @throws TException on write error # @return int How many bytes written # sub writeStructBegin { my $self = shift; my ($name) = @_; return $self->{concreteProtocol}->writeStructBegin($name); } # # Close a struct. # # @throws TException on write error # @return int How many bytes written # sub writeStructEnd { my $self = shift; return $self->{concreteProtocol}->writeStructEnd(); } # # Starts a field. # # @param string $name Field name # @param int $type Field type # @param int $fid Field id # @throws TException on write error # @return int How many bytes written # sub writeFieldBegin { my $self = shift; my ($fieldName, $fieldType, $fieldId) = @_; return $self->{concreteProtocol}->writeFieldBegin($fieldName, $fieldType, $fieldId); } sub writeFieldEnd { my $self = shift; return $self->{concreteProtocol}->writeFieldEnd(); } sub writeFieldStop { my $self = shift; return $self->{concreteProtocol}->writeFieldStop(); } sub writeMapBegin { my $self = shift; my ($keyType, $valType, $size) = @_; return $self->{concreteProtocol}->writeMapBegin($keyType, $valType, $size); } sub writeMapEnd { my $self = shift; return $self->{concreteProtocol}->writeMapEnd(); } sub writeListBegin { my $self = shift; my ($elemType, $size) = @_; return $self->{concreteProtocol}->writeListBegin($elemType, $size); } sub writeListEnd { my $self = shift; return $self->{concreteProtocol}->writeListEnd(); } sub writeSetBegin { my $self = shift; my ($elemType, $size) = @_; return $self->{concreteProtocol}->writeSetBegin($elemType, $size); } sub writeSetEnd { my $self = shift; return $self->{concreteProtocol}->writeListEnd(); } sub writeBool { my $self = shift; my $bool = shift; return $self->{concreteProtocol}->writeBool($bool); } sub writeByte { my $self = shift; my $byte = shift; return $self->{concreteProtocol}->writeByte($byte); } sub writeI16 { my $self = shift; my $i16 = shift; return $self->{concreteProtocol}->writeI16($i16); } sub writeI32 { my $self = shift; my ($i32) = @_; return $self->{concreteProtocol}->writeI32($i32); } sub writeI64 { my $self = shift; my $i64 = shift; return $self->{concreteProtocol}->writeI64($i64); } sub writeDouble { my $self = shift; my $dub = shift; return $self->{concreteProtocol}->writeDouble($dub); } sub writeString { my $self = shift; my $str = shift; return $self->{concreteProtocol}->writeString($str); } # # Reads the message header # # @param string $name Function name # @param int $type message type TMessageType::CALL or TMessageType::REPLY # @parem int $seqid The sequence id of this message # sub readMessageBegin { my $self = shift; my ($name, $type, $seqid) = @_; return $self->{concreteProtocol}->readMessageBegin($name, $type, $seqid); } # # Read the close of message # sub readMessageEnd { my $self = shift; return $self->{concreteProtocol}->readMessageEnd(); } sub readStructBegin { my $self = shift; my $name = shift; return $self->{concreteProtocol}->readStructBegin($name); } sub readStructEnd { my $self = shift; return $self->{concreteProtocol}->readStructEnd(); } sub readFieldBegin { my $self = shift; my ($name, $fieldType, $fieldId) = @_; return $self->{concreteProtocol}->readFieldBegin($name, $fieldType, $fieldId); } sub readFieldEnd { my $self = shift; return $self->{concreteProtocol}->readFieldEnd(); } sub readMapBegin { my $self = shift; my ($keyType, $valType, $size) = @_; return $self->{concreteProtocol}->readMapBegin($keyType, $valType, $size); } sub readMapEnd { my $self = shift; return $self->{concreteProtocol}->readMapEnd(); } sub readListBegin { my $self = shift; my ($elemType, $size) = @_; return $self->{concreteProtocol}->readListBegin($elemType, $size); } sub readListEnd { my $self = shift; return $self->{concreteProtocol}->readListEnd(); } sub readSetBegin { my $self = shift; my ($elemType, $size) = @_; return $self->{concreteProtocol}->readSetBegin($elemType, $size); } sub readSetEnd { my $self = shift; return $self->{concreteProtocol}->readSetEnd(); } sub readBool { my $self = shift; my $bool = shift; return $self->{concreteProtocol}->readBool($bool); } sub readByte { my $self = shift; my $byte = shift; return $self->{concreteProtocol}->readByte($byte); } sub readI16 { my $self = shift; my $i16 = shift; return $self->{concreteProtocol}->readI16($i16); } sub readI32 { my $self = shift; my $i32 = shift; return $self->{concreteProtocol}->readI32($i32); } sub readI64 { my $self = shift; my $i64 = shift; return $self->{concreteProtocol}->readI64($i64); } sub readDouble { my $self = shift; my $dub = shift; return $self->{concreteProtocol}->readDouble($dub); } sub readString { my $self = shift; my $str = shift; return $self->{concreteProtocol}->readString($str); } 1; thrift-0.19.0/lib/perl/lib/Thrift/UnixSocket.pm0000644000000000000000000000347414303740367021266 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Socket; use IO::Socket::UNIX; package Thrift::UnixSocket; use base qw( Thrift::Socket ); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Constructor. # Takes a unix domain socket filename. # See Thrift::Socket for base class parameters. # @param[in] path path to unix socket file # @example my $sock = Thrift::UnixSocket->new($path); # sub new { my $classname = shift; my $self = $classname->SUPER::new(); $self->{path} = shift; return bless($self, $classname); } sub __open { my $self = shift; my $sock = IO::Socket::UNIX->new( Type => IO::Socket::SOCK_STREAM, Peer => $self->{path}) || do { my $error = 'UnixSocket: Could not connect to ' . $self->{path} . ' (' . $! . ')'; if ($self->{debug}) { $self->{debugHandler}->($error); } die Thrift::TTransportException->new($error, Thrift::TTransportException::NOT_OPEN); }; return $sock; } 1; thrift-0.19.0/lib/perl/lib/Thrift/HttpClient.pm0000644000000000000000000001070414303740367021242 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use HTTP::Request; use IO::String; use LWP::UserAgent; use Thrift; use Thrift::Exception; use Thrift::Transport; package Thrift::HttpClient; use base('Thrift::Transport'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $url = shift || 'http://localhost:9090'; my $out = IO::String->new; binmode($out); my $self = { url => $url, out => $out, timeout => 100, handle => undef, headers => {}, }; return bless($self,$classname); } sub setTimeout { my $self = shift; my $timeout = shift; $self->{timeout} = $timeout; } sub setRecvTimeout { warn 'setRecvTimeout is deprecated - use setTimeout instead'; # note: recvTimeout was never used so we do not need to do anything here } sub setSendTimeout { my $self = shift; my $timeout = shift; warn 'setSendTimeout is deprecated - use setTimeout instead'; $self->setTimeout($timeout); } sub setHeader { my $self = shift; my ($name, $value) = @_; $self->{headers}->{$name} = $value; } # # Tests whether this is open # # @return bool true if the socket is open # sub isOpen { return 1; } sub open {} # # Cleans up the buffer. # sub close { my $self = shift; if (defined($self->{io})) { close($self->{io}); $self->{io} = undef; } } # # Guarantees that the full amount of data is read. # # @return string The data, of exact length # @throws TTransportException if cannot read data # sub readAll { my $self = shift; my $len = shift; my $buf = $self->read($len); if (!defined($buf)) { die Thrift::TTransportException->new("TSocket: Could not read $len bytes from input buffer", Thrift::TTransportException::END_OF_FILE); } return $buf; } # # Read and return string # sub read { my $self = shift; my $len = shift; my $buf; my $in = $self->{in}; if (!defined($in)) { die Thrift::TTransportException->new('Response buffer is empty, no request.', Thrift::TTransportException::END_OF_FILE); } eval { my $ret = sysread($in, $buf, $len); if (! defined($ret)) { die Thrift::TTransportException->new('No more data available.', Thrift::TTransportException::TIMED_OUT); } }; if($@){ die Thrift::TTransportException->new("$@", Thrift::TTransportException::UNKNOWN); } return $buf; } # # Write string # sub write { my $self = shift; my $buf = shift; $self->{out}->print($buf); } # # Flush output (do the actual HTTP/HTTPS request) # sub flush { my $self = shift; my $ua = LWP::UserAgent->new( 'timeout' => ($self->{timeout} / 1000), 'agent' => 'Perl/THttpClient' ); $ua->default_header('Accept' => 'application/x-thrift'); $ua->default_header('Content-Type' => 'application/x-thrift'); $ua->cookie_jar({}); # hash to remember cookies between redirects my $out = $self->{out}; $out->setpos(0); # rewind my $buf = join('', <$out>); my $request = HTTP::Request->new(POST => $self->{url}, undef, $buf); map { $request->header($_ => $self->{headers}->{$_}) } keys %{$self->{headers}}; my $response = $ua->request($request); my $content_ref = $response->content_ref; my $in = IO::String->new($content_ref); binmode($in); $self->{in} = $in; $in->setpos(0); # rewind # reset write buffer $out = IO::String->new; binmode($out); $self->{out} = $out; } 1; thrift-0.19.0/lib/perl/lib/Thrift/MessageType.pm0000644000000000000000000000210014303740367021401 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; # # Message types for RPC # package Thrift::TMessageType; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant CALL => 1; use constant REPLY => 2; use constant EXCEPTION => 3; use constant ONEWAY => 4; 1; thrift-0.19.0/lib/perl/lib/Thrift/FramedTransport.pm0000644000000000000000000000767014303740367022307 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Transport; # # Framed transport. Writes and reads data in chunks that are stamped with # their length. # # @package thrift.transport # package Thrift::FramedTransport; use base('Thrift::Transport'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $transport = shift; my $read = shift || 1; my $write = shift || 1; my $self = { transport => $transport, read => $read, write => $write, wBuf => '', rBuf => '', }; return bless($self,$classname); } sub isOpen { my $self = shift; return $self->{transport}->isOpen(); } sub open { my $self = shift; $self->{transport}->open(); } sub close { my $self = shift; if (defined $self->{transport}) { $self->{transport}->close(); } } # # Reads from the buffer. When more data is required reads another entire # chunk and serves future reads out of that. # # @param int $len How much data # sub read { my $self = shift; my $len = shift; if (!$self->{read}) { return $self->{transport}->read($len); } if (length($self->{rBuf}) == 0) { $self->_readFrame(); } # Just return full buff if ($len > length($self->{rBuf})) { my $out = $self->{rBuf}; $self->{rBuf} = ''; return $out; } # Return substr my $out = substr($self->{rBuf}, 0, $len); $self->{rBuf} = substr($self->{rBuf}, $len); return $out; } # # Reads a chunk of data into the internal read buffer. # (private) sub _readFrame { my $self = shift; my $buf = $self->{transport}->readAll(4); my @val = unpack('N', $buf); my $sz = $val[0]; $self->{rBuf} = $self->{transport}->readAll($sz); } # # Writes some data to the pending output buffer. # # @param string $buf The data # @param int $len Limit of bytes to write # sub write { my $self = shift; my $buf = shift; my $len = shift; unless($self->{write}) { return $self->{transport}->write($buf, $len); } if ( defined $len && $len < length($buf)) { $buf = substr($buf, 0, $len); } $self->{wBuf} .= $buf; } # # Writes the output buffer to the stream in the format of a 4-byte length # followed by the actual data. # sub flush { my $self = shift; unless ($self->{write}) { return $self->{transport}->flush(); } my $out = pack('N', length($self->{wBuf})); $out .= $self->{wBuf}; $self->{transport}->write($out); $self->{transport}->flush(); $self->{wBuf} = ''; } # # FramedTransport factory creates framed transport objects from transports # package Thrift::FramedTransportFactory; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = {}; return bless($self, $classname); } # # Build a framed transport from the base transport # # @return Thrift::FramedTransport transport # sub getTransport { my $self = shift; my $trans = shift; my $buffered = Thrift::FramedTransport->new($trans); return $buffered; } 1; thrift-0.19.0/lib/perl/lib/Thrift/SSLServerSocket.pm0000644000000000000000000000503614303740367022167 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::SSLSocket; use Thrift::ServerSocket; use IO::Socket::SSL; package Thrift::SSLServerSocket; use base qw( Thrift::ServerSocket ); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # Constructor. # Takes a hash: # See Thrift::Socket for base class parameters. # @param[in] ca certificate authority filename - not required # @param[in] cert certificate filename; may contain key in which case key is not required # @param[in] key private key filename for the certificate if it is not inside the cert file # sub new { my $classname = shift; my $self = $classname->SUPER::new(@_); return bless($self, $classname); } sub __client { return Thrift::SSLSocket->new(); } sub __listen { my $self = shift; my $opts = {Listen => $self->{queue}, LocalAddr => $self->{host}, LocalPort => $self->{port}, Proto => 'tcp', ReuseAddr => 1}; my $verify = IO::Socket::SSL::SSL_VERIFY_PEER | IO::Socket::SSL::SSL_VERIFY_FAIL_IF_NO_PEER_CERT | IO::Socket::SSL::SSL_VERIFY_CLIENT_ONCE; $opts->{SSL_ca_file} = $self->{ca} if defined $self->{ca}; $opts->{SSL_cert_file} = $self->{cert} if defined $self->{cert}; $opts->{SSL_cipher_list} = $self->{ciphers} if defined $self->{ciphers}; $opts->{SSL_key_file} = $self->{key} if defined $self->{key}; $opts->{SSL_use_cert} = (defined $self->{cert}) ? 1 : 0; $opts->{SSL_verify_mode} = (defined $self->{ca}) ? $verify : IO::Socket::SSL::SSL_VERIFY_NONE; $opts->{SSL_version} = (defined $self->{version}) ? $self->{version} : 'SSLv23:!SSLv3:!SSLv2'; return IO::Socket::SSL->new(%$opts); } 1; thrift-0.19.0/lib/perl/lib/Thrift/Type.pm0000644000000000000000000000263114303740367020105 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; # # Data types that can be sent via Thrift # package Thrift::TType; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant STOP => 0; use constant VOID => 1; use constant BOOL => 2; use constant BYTE => 3; use constant I08 => 3; use constant DOUBLE => 4; use constant I16 => 6; use constant I32 => 8; use constant I64 => 10; use constant STRING => 11; use constant UTF7 => 11; use constant STRUCT => 12; use constant MAP => 13; use constant SET => 14; use constant LIST => 15; use constant UTF8 => 16; use constant UTF16 => 17; 1; thrift-0.19.0/lib/perl/lib/Thrift/Protocol.pm0000644000000000000000000002500214303740367020762 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Exception; use Thrift::Type; # # Protocol exceptions # package Thrift::TProtocolException; use base('Thrift::TException'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant UNKNOWN => 0; use constant INVALID_DATA => 1; use constant NEGATIVE_SIZE => 2; use constant SIZE_LIMIT => 3; use constant BAD_VERSION => 4; use constant NOT_IMPLEMENTED => 5; use constant DEPTH_LIMIT => 6; sub new { my $classname = shift; my $self = $classname->SUPER::new(); return bless($self,$classname); } # # Protocol base class module. # package Thrift::Protocol; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = {}; my $trans = shift; $self->{trans}= $trans; return bless($self,$classname); } sub getTransport { my $self = shift; return $self->{trans}; } # # Writes the message header # # @param string $name Function name # @param int $type message type TMessageType::CALL or TMessageType::REPLY # @param int $seqid The sequence id of this message # sub writeMessageBegin { my ($name, $type, $seqid); die 'abstract'; } # # Close the message # sub writeMessageEnd { die 'abstract'; } # # Writes a struct header. # # @param string $name Struct name # @throws TProtocolException on write error # @return int How many bytes written # sub writeStructBegin { my ($name); die 'abstract'; } # # Close a struct. # # @throws TProtocolException on write error # @return int How many bytes written # sub writeStructEnd { die 'abstract'; } # # Starts a field. # # @param string $name Field name # @param int $type Field type # @param int $fid Field id # @throws TProtocolException on write error # @return int How many bytes written # sub writeFieldBegin { my ($fieldName, $fieldType, $fieldId); die 'abstract'; } sub writeFieldEnd { die 'abstract'; } sub writeFieldStop { die 'abstract'; } sub writeMapBegin { my ($keyType, $valType, $size); die 'abstract'; } sub writeMapEnd { die 'abstract'; } sub writeListBegin { my ($elemType, $size); die 'abstract'; } sub writeListEnd { die 'abstract'; } sub writeSetBegin { my ($elemType, $size); die 'abstract'; } sub writeSetEnd { die 'abstract'; } sub writeBool { my ($bool); die 'abstract'; } sub writeByte { my ($byte); die 'abstract'; } sub writeI16 { my ($i16); die 'abstract'; } sub writeI32 { my ($i32); die 'abstract'; } sub writeI64 { my ($i64); die 'abstract'; } sub writeDouble { my ($dub); die 'abstract'; } sub writeString { my ($str); die 'abstract'; } # # Reads the message header # # @param string $name Function name # @param int $type message type TMessageType::CALL or TMessageType::REPLY # @parem int $seqid The sequence id of this message # sub readMessageBegin { my ($name, $type, $seqid); die 'abstract'; } # # Read the close of message # sub readMessageEnd { die 'abstract'; } sub readStructBegin { my($name); die 'abstract'; } sub readStructEnd { die 'abstract'; } sub readFieldBegin { my ($name, $fieldType, $fieldId); die 'abstract'; } sub readFieldEnd { die 'abstract'; } sub readMapBegin { my ($keyType, $valType, $size); die 'abstract'; } sub readMapEnd { die 'abstract'; } sub readListBegin { my ($elemType, $size); die 'abstract'; } sub readListEnd { die 'abstract'; } sub readSetBegin { my ($elemType, $size); die 'abstract'; } sub readSetEnd { die 'abstract'; } sub readBool { my ($bool); die 'abstract'; } sub readByte { my ($byte); die 'abstract'; } sub readI16 { my ($i16); die 'abstract'; } sub readI32 { my ($i32); die 'abstract'; } sub readI64 { my ($i64); die 'abstract'; } sub readDouble { my ($dub); die 'abstract'; } sub readString { my ($str); die 'abstract'; } # # The skip function is a utility to parse over unrecognized data without # causing corruption. # # @param TType $type What type is it # sub skip { my $self = shift; my $type = shift; my $ref; my $result; my $i; if($type == Thrift::TType::BOOL) { return $self->readBool(\$ref); } elsif($type == Thrift::TType::BYTE){ return $self->readByte(\$ref); } elsif($type == Thrift::TType::I16){ return $self->readI16(\$ref); } elsif($type == Thrift::TType::I32){ return $self->readI32(\$ref); } elsif($type == Thrift::TType::I64){ return $self->readI64(\$ref); } elsif($type == Thrift::TType::DOUBLE){ return $self->readDouble(\$ref); } elsif($type == Thrift::TType::STRING) { return $self->readString(\$ref); } elsif($type == Thrift::TType::STRUCT) { $result = $self->readStructBegin(\$ref); while (1) { my ($ftype,$fid); $result += $self->readFieldBegin(\$ref, \$ftype, \$fid); if ($ftype == Thrift::TType::STOP) { last; } $result += $self->skip($ftype); $result += $self->readFieldEnd(); } $result += $self->readStructEnd(); return $result; } elsif($type == Thrift::TType::MAP) { my($keyType,$valType,$size); $result = $self->readMapBegin(\$keyType, \$valType, \$size); for ($i = 0; $i < $size; $i++) { $result += $self->skip($keyType); $result += $self->skip($valType); } $result += $self->readMapEnd(); return $result; } elsif($type == Thrift::TType::SET) { my ($elemType,$size); $result = $self->readSetBegin(\$elemType, \$size); for ($i = 0; $i < $size; $i++) { $result += $self->skip($elemType); } $result += $self->readSetEnd(); return $result; } elsif($type == Thrift::TType::LIST) { my ($elemType,$size); $result = $self->readListBegin(\$elemType, \$size); for ($i = 0; $i < $size; $i++) { $result += $self->skip($elemType); } $result += $self->readListEnd(); return $result; } die Thrift::TProtocolException->new("Type $type not recognized --- corrupt data?", Thrift::TProtocolException::INVALID_DATA); } # # Utility for skipping binary data # # @param TTransport $itrans TTransport object # @param int $type Field type # sub skipBinary { my $self = shift; my $itrans = shift; my $type = shift; if($type == Thrift::TType::BOOL) { return $itrans->readAll(1); } elsif($type == Thrift::TType::BYTE) { return $itrans->readAll(1); } elsif($type == Thrift::TType::I16) { return $itrans->readAll(2); } elsif($type == Thrift::TType::I32) { return $itrans->readAll(4); } elsif($type == Thrift::TType::I64) { return $itrans->readAll(8); } elsif($type == Thrift::TType::DOUBLE) { return $itrans->readAll(8); } elsif( $type == Thrift::TType::STRING ) { my @len = unpack('N', $itrans->readAll(4)); my $len = $len[0]; if ($len > 0x7fffffff) { $len = 0 - (($len - 1) ^ 0xffffffff); } return 4 + $itrans->readAll($len); } elsif( $type == Thrift::TType::STRUCT ) { my $result = 0; while (1) { my $ftype = 0; my $fid = 0; my $data = $itrans->readAll(1); my @arr = unpack('c', $data); $ftype = $arr[0]; if ($ftype == Thrift::TType::STOP) { last; } # I16 field id $result += $itrans->readAll(2); $result += $self->skipBinary($itrans, $ftype); } return $result; } elsif($type == Thrift::TType::MAP) { # Ktype my $data = $itrans->readAll(1); my @arr = unpack('c', $data); my $ktype = $arr[0]; # Vtype $data = $itrans->readAll(1); @arr = unpack('c', $data); my $vtype = $arr[0]; # Size $data = $itrans->readAll(4); @arr = unpack('N', $data); my $size = $arr[0]; if ($size > 0x7fffffff) { $size = 0 - (($size - 1) ^ 0xffffffff); } my $result = 6; for (my $i = 0; $i < $size; $i++) { $result += $self->skipBinary($itrans, $ktype); $result += $self->skipBinary($itrans, $vtype); } return $result; } elsif($type == Thrift::TType::SET || $type == Thrift::TType::LIST) { # Vtype my $data = $itrans->readAll(1); my @arr = unpack('c', $data); my $vtype = $arr[0]; # Size $data = $itrans->readAll(4); @arr = unpack('N', $data); my $size = $arr[0]; if ($size > 0x7fffffff) { $size = 0 - (($size - 1) ^ 0xffffffff); } my $result = 5; for (my $i = 0; $i < $size; $i++) { $result += $self->skipBinary($itrans, $vtype); } return $result; } die Thrift::TProtocolException->new("Type $type not recognized --- corrupt data?", Thrift::TProtocolException::INVALID_DATA); } # # Protocol factory creates protocol objects from transports # package Thrift::TProtocolFactory; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = {}; return bless($self,$classname); } # # Build a protocol from the base transport # # @return TProtcol protocol # sub getProtocol { my ($trans); die 'interface'; } 1; thrift-0.19.0/lib/perl/lib/Thrift/Server.pm0000644000000000000000000001665214303740367020442 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::BinaryProtocol; use Thrift::BufferedTransport; use Thrift::Exception; # # Server base class module # package Thrift::Server; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); # # 3 possible constructors: # 1. (processor, serverTransport) # Uses a BufferedTransportFactory and a BinaryProtocolFactory. # 2. (processor, serverTransport, transportFactory, protocolFactory) # Uses the same factory for input and output of each type. # 3. (processor, serverTransport, # inputTransportFactory, outputTransportFactory, # inputProtocolFactory, outputProtocolFactory) # sub new { my $classname = shift; my @args = @_; my $self; if (scalar @args == 2) { $self = _init($args[0], $args[1], Thrift::BufferedTransportFactory->new(), Thrift::BufferedTransportFactory->new(), Thrift::BinaryProtocolFactory->new(), Thrift::BinaryProtocolFactory->new()); } elsif (scalar @args == 4) { $self = _init($args[0], $args[1], $args[2], $args[2], $args[3], $args[3]); } elsif (scalar @args == 6) { $self = _init($args[0], $args[1], $args[2], $args[3], $args[4], $args[5]); } else { die Thrift::TException->new('Thrift::Server expects exactly 2, 4, or 6 args'); } return bless($self,$classname); } sub _init { my $processor = shift; my $serverTransport = shift; my $inputTransportFactory = shift; my $outputTransportFactory = shift; my $inputProtocolFactory = shift; my $outputProtocolFactory = shift; my $self = { processor => $processor, serverTransport => $serverTransport, inputTransportFactory => $inputTransportFactory, outputTransportFactory => $outputTransportFactory, inputProtocolFactory => $inputProtocolFactory, outputProtocolFactory => $outputProtocolFactory, }; } sub serve { die 'abstract'; } sub _clientBegin { my $self = shift; my $iprot = shift; my $oprot = shift; if (exists $self->{serverEventHandler} and defined $self->{serverEventHandler}) { $self->{serverEventHandler}->clientBegin($iprot, $oprot); } } sub _handleException { my $self = shift; my $e = shift; if ($e->isa('Thrift::TException') and exists $e->{message}) { my $message = $e->{message}; my $code = $e->{code}; my $out = $code . ':' . $message; $message =~ m/TTransportException/ and die $out; if ($message =~ m/Socket/) { # suppress Socket messages } else { warn $out; } } else { warn $e; } } # # SimpleServer from the Server base class that handles one connection at a time # package Thrift::SimpleServer; use parent -norequire, 'Thrift::Server'; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = $classname->SUPER::new(@_); return bless($self,$classname); } sub serve { my $self = shift; my $stop = 0; $self->{serverTransport}->listen(); while (!$stop) { my $client = $self->{serverTransport}->accept(); if (defined $client) { my $itrans = $self->{inputTransportFactory}->getTransport($client); my $otrans = $self->{outputTransportFactory}->getTransport($client); my $iprot = $self->{inputProtocolFactory}->getProtocol($itrans); my $oprot = $self->{outputProtocolFactory}->getProtocol($otrans); eval { $self->_clientBegin($iprot, $oprot); while (1) { $self->{processor}->process($iprot, $oprot); } }; if($@) { $self->_handleException($@); } $itrans->close(); $otrans->close(); } else { $stop = 1; } } } # # ForkingServer that forks a new process for each request # package Thrift::ForkingServer; use parent -norequire, 'Thrift::Server'; use POSIX ':sys_wait_h'; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my @args = @_; my $self = $classname->SUPER::new(@args); return bless($self,$classname); } sub serve { my $self = shift; # THRIFT-3848: without ignoring SIGCHLD, perl ForkingServer goes into a tight loop $SIG{CHLD} = 'IGNORE'; $self->{serverTransport}->listen(); while (1) { my $client = $self->{serverTransport}->accept(); $self->_client($client); } } sub _client { my $self = shift; my $client = shift; eval { my $itrans = $self->{inputTransportFactory}->getTransport($client); my $otrans = $self->{outputTransportFactory}->getTransport($client); my $iprot = $self->{inputProtocolFactory}->getProtocol($itrans); my $oprot = $self->{outputProtocolFactory}->getProtocol($otrans); $self->_clientBegin($iprot, $oprot); my $pid = fork(); if ($pid) { $self->_parent($pid, $itrans, $otrans); } else { $self->_child($itrans, $otrans, $iprot, $oprot); } }; if($@) { $self->_handleException($@); } } sub _parent { my $self = shift; my $pid = shift; my $itrans = shift; my $otrans = shift; # Parent must close socket or the connection may not get closed promptly $self->tryClose($itrans); $self->tryClose($otrans); } sub _child { my $self = shift; my $itrans = shift; my $otrans = shift; my $iprot = shift; my $oprot = shift; my $ecode = 0; eval { # THRIFT-4065 ensure child process has normal signal handling in case thrift handler uses it $SIG{CHLD} = 'DEFAULT'; while (1) { $self->{processor}->process($iprot, $oprot); } }; if($@) { $ecode = 1; $self->_handleException($@); } $self->tryClose($itrans); $self->tryClose($otrans); exit($ecode); } sub tryClose { my $self = shift; my $file = shift; eval { if (defined $file) { $file->close(); } }; if($@) { if ($@->isa('Thrift::TException') and exists $@->{message}) { my $message = $@->{message}; my $code = $@->{code}; my $out = $code . ':' . $message; warn $out; } else { warn $@; } } } 1; thrift-0.19.0/lib/perl/lib/Thrift/BufferedTransport.pm0000644000000000000000000000542614303740367022630 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Exception; use Thrift::Transport; package Thrift::BufferedTransport; use base('Thrift::Transport'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $transport = shift; my $rBufSize = shift || 512; my $wBufSize = shift || 512; my $self = { transport => $transport, rBufSize => $rBufSize, wBufSize => $wBufSize, wBuf => '', rBuf => '', }; return bless($self,$classname); } sub isOpen { my $self = shift; return $self->{transport}->isOpen(); } sub open { my $self = shift; $self->{transport}->open(); } sub close() { my $self = shift; $self->{transport}->close(); } sub readAll { my $self = shift; my $len = shift; return $self->{transport}->readAll($len); } sub read { my $self = shift; my $len = shift; my $ret; # Methinks Perl is already buffering these for us return $self->{transport}->read($len); } sub write { my $self = shift; my $buf = shift; $self->{wBuf} .= $buf; if (length($self->{wBuf}) >= $self->{wBufSize}) { $self->{transport}->write($self->{wBuf}); $self->{wBuf} = ''; } } sub flush { my $self = shift; if (length($self->{wBuf}) > 0) { $self->{transport}->write($self->{wBuf}); $self->{wBuf} = ''; } $self->{transport}->flush(); } # # BufferedTransport factory creates buffered transport objects from transports # package Thrift::BufferedTransportFactory; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = {}; return bless($self,$classname); } # # Build a buffered transport from the base transport # # @return Thrift::BufferedTransport transport # sub getTransport { my $self = shift; my $trans = shift; my $buffered = Thrift::BufferedTransport->new($trans); return $buffered; } 1; thrift-0.19.0/lib/perl/lib/Thrift/Exception.pm0000644000000000000000000000760514303740367021130 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Type; package Thrift::TException; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use overload '""' => sub { return sprintf '%s error: %s (code %s)', ref( $_[0] ), ( $_[0]->{message} || 'empty message' ), ( defined $_[0]->{code} ? $_[0]->{code} : 'undefined' ); }; sub new { my $classname = shift; my $self = {message => shift, code => shift || 0}; return bless($self,$classname); } package Thrift::TApplicationException; use parent -norequire, 'Thrift::TException'; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); use constant UNKNOWN => 0; use constant UNKNOWN_METHOD => 1; use constant INVALID_MESSAGE_TYPE => 2; use constant WRONG_METHOD_NAME => 3; use constant BAD_SEQUENCE_ID => 4; use constant MISSING_RESULT => 5; use constant INTERNAL_ERROR => 6; use constant PROTOCOL_ERROR => 7; use constant INVALID_TRANSFORM => 8; use constant INVALID_PROTOCOL => 9; use constant UNSUPPORTED_CLIENT_TYPE => 10; sub new { my $classname = shift; my $self = $classname->SUPER::new(@_); return bless($self,$classname); } sub read { my $self = shift; my $input = shift; my $xfer = 0; my $fname = undef; my $ftype = 0; my $fid = 0; $xfer += $input->readStructBegin(\$fname); while (1) { $xfer += $input->readFieldBegin(\$fname, \$ftype, \$fid); if ($ftype == Thrift::TType::STOP) { last; next; } SWITCH: for($fid) { /1/ && do{ if ($ftype == Thrift::TType::STRING) { $xfer += $input->readString(\$self->{message}); } else { $xfer += $input->skip($ftype); } last; }; /2/ && do{ if ($ftype == Thrift::TType::I32) { $xfer += $input->readI32(\$self->{code}); } else { $xfer += $input->skip($ftype); } last; }; $xfer += $input->skip($ftype); } $xfer += $input->readFieldEnd(); } $xfer += $input->readStructEnd(); return $xfer; } sub write { my $self = shift; my $output = shift; my $xfer = 0; $xfer += $output->writeStructBegin('TApplicationException'); if ($self->getMessage()) { $xfer += $output->writeFieldBegin('message', Thrift::TType::STRING, 1); $xfer += $output->writeString($self->getMessage()); $xfer += $output->writeFieldEnd(); } if ($self->getCode()) { $xfer += $output->writeFieldBegin('type', Thrift::TType::I32, 2); $xfer += $output->writeI32($self->getCode()); $xfer += $output->writeFieldEnd(); } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } sub getMessage { my $self = shift; return $self->{message}; } sub getCode { my $self = shift; return $self->{code}; } 1; thrift-0.19.0/lib/perl/lib/Thrift/MemoryBuffer.pm0000644000000000000000000000525514303740367021573 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::Transport; package Thrift::MemoryBuffer; use base('Thrift::Transport'); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $bufferSize= shift || 1024; my $self = { buffer => '', bufferSize => $bufferSize, wPos => 0, rPos => 0, }; return bless($self,$classname); } sub isOpen { return 1; } sub open { } sub close { } sub peek { my $self = shift; return($self->{rPos} < $self->{wPos}); } sub getBuffer { my $self = shift; return $self->{buffer}; } sub resetBuffer { my $self = shift; my $new_buffer = shift || ''; $self->{buffer} = $new_buffer; $self->{bufferSize} = length($new_buffer); $self->{wPos} = length($new_buffer); $self->{rPos} = 0; } sub available { my $self = shift; return ($self->{wPos} - $self->{rPos}); } sub read { my $self = shift; my $len = shift; my $ret; my $avail = ($self->{wPos} - $self->{rPos}); return '' if $avail == 0; #how much to give my $give = $len; $give = $avail if $avail < $len; $ret = substr($self->{buffer},$self->{rPos},$give); $self->{rPos} += $give; return $ret; } sub readAll { my $self = shift; my $len = shift; my $avail = ($self->{wPos} - $self->{rPos}); if ($avail < $len) { die Thrift::TTransportException->new("Attempt to readAll($len) found only $avail available", Thrift::TTransportException::END_OF_FILE); } my $data = ''; my $got = 0; while (($got = length($data)) < $len) { $data .= $self->read($len - $got); } return $data; } sub write { my $self = shift; my $buf = shift; $self->{buffer} .= $buf; $self->{wPos} += length($buf); } sub flush { } 1; thrift-0.19.0/lib/perl/lib/Thrift/MultiplexedProcessor.pm0000644000000000000000000000743314303740367023365 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; use Thrift; use Thrift::MessageType; use Thrift::MultiplexedProtocol; use Thrift::Protocol; use Thrift::ProtocolDecorator; package Thrift::StoredMessageProtocol; use base qw(Thrift::ProtocolDecorator); use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $protocol = shift; my $fname = shift; my $mtype = shift; my $rseqid = shift; my $self = $classname->SUPER::new($protocol); $self->{fname} = $fname; $self->{mtype} = $mtype; $self->{rseqid} = $rseqid; return bless($self,$classname); } sub readMessageBegin { my $self = shift; my $name = shift; my $type = shift; my $seqid = shift; $$name = $self->{fname}; $$type = $self->{mtype}; $$seqid = $self->{rseqid}; } package Thrift::MultiplexedProcessor; use version 0.77; our $VERSION = version->declare("$Thrift::VERSION"); sub new { my $classname = shift; my $self = {}; $self->{serviceProcessorMap} = {}; $self->{defaultProcessor} = undef; return bless($self,$classname); } sub defaultProcessor { my $self = shift; my $processor = shift; $self->{defaultProcessor} = $processor; } sub registerProcessor { my $self = shift; my $serviceName = shift; my $processor = shift; $self->{serviceProcessorMap}->{$serviceName} = $processor; } sub process { my $self = shift; my $input = shift; my $output = shift; # # Use the actual underlying protocol (e.g. BinaryProtocol) to read the # message header. This pulls the message "off the wire", which we'll # deal with at the end of this method. # my ($fname, $mtype, $rseqid); $input->readMessageBegin(\$fname, \$mtype, \$rseqid); if ($mtype ne Thrift::TMessageType::CALL && $mtype ne Thrift::TMessageType::ONEWAY) { die Thrift::TException->new('This should not have happened!?'); } # Extract the service name and the new Message name. if (index($fname, Thrift::MultiplexedProtocol::SEPARATOR) == -1) { if (defined $self->{defaultProcessor}) { return $self->{defaultProcessor}->process( Thrift::StoredMessageProtocol->new($input, $fname, $mtype, $rseqid), $output ); } else { die Thrift::TException->new("Service name not found in message name: {$fname} and no default processor defined. Did you " . 'forget to use a MultiplexProtocol in your client?'); } } (my $serviceName, my $messageName) = split(':', $fname, 2); if (!exists($self->{serviceProcessorMap}->{$serviceName})) { die Thrift::TException->new("Service name not found: {$serviceName}. Did you forget " . 'to call registerProcessor()?'); } # Dispatch processing to the stored processor my $processor = $self->{serviceProcessorMap}->{$serviceName}; return $processor->process( Thrift::StoredMessageProtocol->new($input, $messageName, $mtype, $rseqid), $output ); } 1; thrift-0.19.0/lib/perl/lib/Thrift.pm0000644000000000000000000000217014454461475017171 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # use 5.10.0; use strict; use warnings; # # Versioning # # Every perl module for Thrift will have the same version # declaration. For a production build, change it below to # something like "v0.11.0" and all of the packages in all # of the files will pick it up from here. # package Thrift; use version 0.77; our $VERSION = version->declare("v0.19.0"); 1; thrift-0.19.0/lib/perl/Makefile.in0000644000000000000000000006357614472652517016712 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/perl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @top_builddir@/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = t EXTRA_DIST = \ coding_standards.md \ build-cpan-dist.sh \ Makefile.PL \ MANIFEST.SKIP \ test.pl \ lib/Thrift.pm \ lib/Thrift.pm \ lib/Thrift/BinaryProtocol.pm \ lib/Thrift/BufferedTransport.pm \ lib/Thrift/Exception.pm \ lib/Thrift/FramedTransport.pm \ lib/Thrift/HttpClient.pm \ lib/Thrift/MemoryBuffer.pm \ lib/Thrift/MessageType.pm \ lib/Thrift/MultiplexedProcessor.pm \ lib/Thrift/MultiplexedProtocol.pm \ lib/Thrift/Protocol.pm \ lib/Thrift/ProtocolDecorator.pm \ lib/Thrift/Server.pm \ lib/Thrift/ServerSocket.pm \ lib/Thrift/Socket.pm \ lib/Thrift/SSLSocket.pm \ lib/Thrift/SSLServerSocket.pm \ lib/Thrift/UnixServerSocket.pm \ lib/Thrift/UnixSocket.pm \ lib/Thrift/Type.pm \ lib/Thrift/Transport.pm \ tools/FixupDist.pl \ README.md THRIFT_IF = @top_srcdir@/test/v0.16/ThriftTest.thrift NAME_BENCHMARKSERVICE = @top_srcdir@/lib/rb/benchmark/Benchmark.thrift NAME_AGGR = @top_srcdir@/contrib/async-test/aggr.thrift THRIFTTEST_GEN = \ gen-perl/ThriftTest/Constants.pm \ gen-perl/ThriftTest/SecondService.pm \ gen-perl/ThriftTest/ThriftTest.pm \ gen-perl/ThriftTest/Types.pm BENCHMARK_GEN = \ gen-perl/BenchmarkService.pm \ gen-perl/Constants.pm \ gen-perl/Types.pm AGGR_GEN = \ gen-perl2/Aggr.pm \ gen-perl2/Constants.pm \ gen-perl2/Types.pm PERL_GEN = \ $(THRIFTTEST_GEN) \ $(BENCHMARK_GEN) \ $(AGGR_GEN) BUILT_SOURCES = $(PERL_GEN) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/perl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/perl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-exec-local install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) all check check-am install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ check check-am check-local clean clean-generic clean-libtool \ clean-local cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-exec-local install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile Makefile-perl.mk : Makefile.PL $(PERL) Makefile.PL MAKEFILE=Makefile-perl.mk INSTALLDIRS=$(INSTALLDIRS) INSTALL_BASE=$(PERL_PREFIX) all-local: Makefile-perl.mk $(MAKE) -f $< find blib -name 'Makefile*' -exec rm -f {} \; install-exec-local: Makefile-perl.mk $(MAKE) -f $< install DESTDIR=$(DESTDIR)/ clean-local: if test -f Makefile-perl.mk ; then \ $(MAKE) -f Makefile-perl.mk clean ; \ fi $(RM) Makefile-perl.mk.old $(RM) -r gen-perl gen-perl2 check-local: $(PERL_GEN) $(PERL) -Iblib/lib -I@abs_srcdir@ -I@builddir@/gen-perl2 -I@builddir@/gen-perl \ @abs_srcdir@/test.pl @abs_srcdir@/t/*.t $(THRIFTTEST_GEN): $(THRIFT_IF) $(THRIFT) $(THRIFT) --gen perl $< $(BENCHMARK_GEN): $(NAME_BENCHMARKSERVICE) $(THRIFT) $(THRIFT) --gen perl $< $(AGGR_GEN): $(NAME_AGGR) $(THRIFT) $(MKDIR_P) gen-perl2 $(THRIFT) -out gen-perl2 --gen perl $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/ocaml/0000777000000000000000000000000014454461475014762 5ustar00rootroot00000000000000thrift-0.19.0/lib/ocaml/descr0000644000000000000000000000006014303740367015766 0ustar00rootroot00000000000000OCaml bindings for the Apache Thrift RPC system thrift-0.19.0/lib/ocaml/TODO0000644000000000000000000000016214303740367015436 0ustar00rootroot00000000000000Write interfaces Clean up the code generator Avoid capture properly instead of relying on the user not to use _ thrift-0.19.0/lib/ocaml/opam0000644000000000000000000000024314303740367015625 0ustar00rootroot00000000000000opam-version: "1" maintainer: "XXX(FILL ME IN WITH EMAIL)" build: [ [make] [make "install"] ] remove: [["ocamlfind" "remove" "thrift"]] depends: ["ocamlfind"] thrift-0.19.0/lib/ocaml/_oasis0000644000000000000000000000105414454461475016156 0ustar00rootroot00000000000000Name: libthrift-ocaml Version: 0.19.0 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers License: Apache-2.0 Homepage: http://thrift.apache.org BuildTools: ocamlbuild Plugins: META (0.3), DevFiles (0.3) Library "libthrift-ocaml" Path: src FindlibName: thrift buildTools: ocamlbuild BuildDepends: threads Modules: Thrift,TBinaryProtocol,TSocket,TFramedTransport,TChannelTransport,TServer,TSimpleServer,TServerSocket,TThreadedServer XMETARequires: threads thrift-0.19.0/lib/ocaml/src/0000777000000000000000000000000014303740367015542 5ustar00rootroot00000000000000thrift-0.19.0/lib/ocaml/src/TServerSocket.ml0000644000000000000000000000272514303740367020641 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift class t port = object inherit Transport.server_t val mutable sock = None method listen = let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in sock <- Some s; Unix.bind s (Unix.ADDR_INET (Unix.inet_addr_any, port)); Unix.listen s 256 method close = match sock with Some s -> Unix.shutdown s Unix.SHUTDOWN_ALL; Unix.close s; sock <- None | _ -> () method acceptImpl = match sock with Some s -> let (fd,_) = Unix.accept s in new TChannelTransport.t (Unix.in_channel_of_descr fd,Unix.out_channel_of_descr fd) | _ -> raise (Transport.E (Transport.NOT_OPEN,"TServerSocket: Not listening but tried to accept")) end thrift-0.19.0/lib/ocaml/src/Makefile0000644000000000000000000000211114303740367017171 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SOURCES = Thrift.ml TBinaryProtocol.ml TSocket.ml TFramedTransport.ml TChannelTransport.ml TServer.ml TSimpleServer.ml TServerSocket.ml TThreadedServer.ml RESULT = thrift LIBS = unix threads THREADS = yes all: native-code-library debug-code-library top OCAMLMAKEFILE = ../OCamlMakefile include $(OCAMLMAKEFILE) thrift-0.19.0/lib/ocaml/src/TSocket.ml0000644000000000000000000000451414303740367017450 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift module T = Transport class t host port= object (self) inherit T.t val mutable chans = None method isOpen = chans != None method opn = try let addr = (let {Unix.h_addr_list=x} = Unix.gethostbyname host in x.(0)) in chans <- Some(Unix.open_connection (Unix.ADDR_INET (addr,port))) with Unix.Unix_error (e,fn,_) -> raise (T.E (T.NOT_OPEN, ("TSocket: Could not connect to "^host^":"^(string_of_int port)^" because: "^fn^":"^(Unix.error_message e)))) | _ -> raise (T.E (T.NOT_OPEN, ("TSocket: Could not connect to "^host^":"^(string_of_int port)))) method close = match chans with None -> () | Some(inc,out) -> (Unix.shutdown_connection inc; close_in inc; chans <- None) method read buf off len = match chans with None -> raise (T.E (T.NOT_OPEN, "TSocket: Socket not open")) | Some(i,o) -> try really_input i buf off len; len with Unix.Unix_error (e,fn,_) -> raise (T.E (T.UNKNOWN, ("TSocket: Could not read "^(string_of_int len)^" from "^host^":"^(string_of_int port)^" because: "^fn^":"^(Unix.error_message e)))) | _ -> raise (T.E (T.UNKNOWN, ("TSocket: Could not read "^(string_of_int len)^" from "^host^":"^(string_of_int port)))) method write buf off len = match chans with None -> raise (T.E (T.NOT_OPEN, "TSocket: Socket not open")) | Some(i,o) -> output o buf off len method flush = match chans with None -> raise (T.E (T.NOT_OPEN, "TSocket: Socket not open")) | Some(i,o) -> flush o end thrift-0.19.0/lib/ocaml/src/TSimpleServer.ml0000644000000000000000000000233714303740367020641 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift module S = TServer class t pf st tf ipf opf = object inherit S.t pf st tf ipf opf method serve = try st#listen; while true do let c = st#accept in let trans = tf#getTransport c in let inp = ipf#getProtocol trans in let op = opf#getProtocol trans in try while (pf#process inp op) do () done; trans#close with e -> trans#close; raise e done with _ -> () end thrift-0.19.0/lib/ocaml/src/Thrift.ml0000644000000000000000000002452514303740367017340 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) exception Break;; exception Thrift_error;; exception Field_empty of string;; class t_exn = object val mutable message = "" method get_message = message method set_message s = message <- s end;; module Transport = struct type exn_type = | UNKNOWN | NOT_OPEN | ALREADY_OPEN | TIMED_OUT | END_OF_FILE;; exception E of exn_type * string class virtual t = object (self) method virtual isOpen : bool method virtual opn : unit method virtual close : unit method virtual read : string -> int -> int -> int method readAll buf off len = let got = ref 0 in let ret = ref 0 in while !got < len do ret := self#read buf (off+(!got)) (len - (!got)); if !ret <= 0 then raise (E (UNKNOWN, "Cannot read. Remote side has closed.")); got := !got + !ret done; !got method virtual write : string -> int -> int -> unit method virtual flush : unit end class factory = object method getTransport (t : t) = t end class virtual server_t = object (self) method virtual listen : unit method accept = self#acceptImpl method virtual close : unit method virtual acceptImpl : t end end;; module Protocol = struct type t_type = | T_STOP | T_VOID | T_BOOL | T_BYTE | T_I08 | T_I16 | T_I32 | T_U64 | T_I64 | T_DOUBLE | T_STRING | T_UTF7 | T_STRUCT | T_MAP | T_SET | T_LIST | T_UTF8 | T_UTF16 let t_type_to_i = function T_STOP -> 0 | T_VOID -> 1 | T_BOOL -> 2 | T_BYTE -> 3 | T_I08 -> 3 | T_I16 -> 6 | T_I32 -> 8 | T_U64 -> 9 | T_I64 -> 10 | T_DOUBLE -> 4 | T_STRING -> 11 | T_UTF7 -> 11 | T_STRUCT -> 12 | T_MAP -> 13 | T_SET -> 14 | T_LIST -> 15 | T_UTF8 -> 16 | T_UTF16 -> 17 let t_type_of_i = function 0 -> T_STOP | 1 -> T_VOID | 2 -> T_BOOL | 3 -> T_BYTE | 6-> T_I16 | 8 -> T_I32 | 9 -> T_U64 | 10 -> T_I64 | 4 -> T_DOUBLE | 11 -> T_STRING | 12 -> T_STRUCT | 13 -> T_MAP | 14 -> T_SET | 15 -> T_LIST | 16 -> T_UTF8 | 17 -> T_UTF16 | _ -> raise Thrift_error type message_type = | CALL | REPLY | EXCEPTION | ONEWAY let message_type_to_i = function | CALL -> 1 | REPLY -> 2 | EXCEPTION -> 3 | ONEWAY -> 4 let message_type_of_i = function | 1 -> CALL | 2 -> REPLY | 3 -> EXCEPTION | 4 -> ONEWAY | _ -> raise Thrift_error class virtual t (trans: Transport.t) = object (self) val mutable trans_ = trans method getTransport = trans_ (* writing methods *) method virtual writeMessageBegin : string * message_type * int -> unit method virtual writeMessageEnd : unit method virtual writeStructBegin : string -> unit method virtual writeStructEnd : unit method virtual writeFieldBegin : string * t_type * int -> unit method virtual writeFieldEnd : unit method virtual writeFieldStop : unit method virtual writeMapBegin : t_type * t_type * int -> unit method virtual writeMapEnd : unit method virtual writeListBegin : t_type * int -> unit method virtual writeListEnd : unit method virtual writeSetBegin : t_type * int -> unit method virtual writeSetEnd : unit method virtual writeBool : bool -> unit method virtual writeByte : int -> unit method virtual writeI16 : int -> unit method virtual writeI32 : Int32.t -> unit method virtual writeI64 : Int64.t -> unit method virtual writeDouble : float -> unit method virtual writeString : string -> unit method virtual writeBinary : string -> unit (* reading methods *) method virtual readMessageBegin : string * message_type * int method virtual readMessageEnd : unit method virtual readStructBegin : string method virtual readStructEnd : unit method virtual readFieldBegin : string * t_type * int method virtual readFieldEnd : unit method virtual readMapBegin : t_type * t_type * int method virtual readMapEnd : unit method virtual readListBegin : t_type * int method virtual readListEnd : unit method virtual readSetBegin : t_type * int method virtual readSetEnd : unit method virtual readBool : bool method virtual readByte : int method virtual readI16 : int method virtual readI32: Int32.t method virtual readI64 : Int64.t method virtual readDouble : float method virtual readString : string method virtual readBinary : string (* skippage *) method skip typ = match typ with | T_BOOL -> ignore self#readBool | T_BYTE | T_I08 -> ignore self#readByte | T_I16 -> ignore self#readI16 | T_I32 -> ignore self#readI32 | T_U64 | T_I64 -> ignore self#readI64 | T_DOUBLE -> ignore self#readDouble | T_STRING -> ignore self#readString | T_UTF7 -> () | T_STRUCT -> ignore ((ignore self#readStructBegin); (try while true do let (_,t,_) = self#readFieldBegin in if t = T_STOP then raise Break else (self#skip t; self#readFieldEnd) done with Break -> ()); self#readStructEnd) | T_MAP -> ignore (let (k,v,s) = self#readMapBegin in for i=0 to s do self#skip k; self#skip v; done; self#readMapEnd) | T_SET -> ignore (let (t,s) = self#readSetBegin in for i=0 to s do self#skip t done; self#readSetEnd) | T_LIST -> ignore (let (t,s) = self#readListBegin in for i=0 to s do self#skip t done; self#readListEnd) | T_UTF8 -> () | T_UTF16 -> () | _ -> raise (Protocol.E (Protocol.INVALID_DATA, "Invalid data")) end class virtual factory = object method virtual getProtocol : Transport.t -> t end type exn_type = | UNKNOWN | INVALID_DATA | NEGATIVE_SIZE | SIZE_LIMIT | BAD_VERSION | NOT_IMPLEMENTED | DEPTH_LIMIT exception E of exn_type * string;; end;; module Processor = struct class virtual t = object method virtual process : Protocol.t -> Protocol.t -> bool end;; class factory (processor : t) = object val processor_ = processor method getProcessor (trans : Transport.t) = processor_ end;; end (* Ugly *) module Application_Exn = struct type typ= | UNKNOWN | UNKNOWN_METHOD | INVALID_MESSAGE_TYPE | WRONG_METHOD_NAME | BAD_SEQUENCE_ID | MISSING_RESULT | INTERNAL_ERROR | PROTOCOL_ERROR | INVALID_TRANSFORM | INVALID_PROTOCOL | UNSUPPORTED_CLIENT_TYPE let typ_of_i = function 0l -> UNKNOWN | 1l -> UNKNOWN_METHOD | 2l -> INVALID_MESSAGE_TYPE | 3l -> WRONG_METHOD_NAME | 4l -> BAD_SEQUENCE_ID | 5l -> MISSING_RESULT | 6l -> INTERNAL_ERROR | 7l -> PROTOCOL_ERROR | 8l -> INVALID_TRANSFORM | 9l -> INVALID_PROTOCOL | 10l -> UNSUPPORTED_CLIENT_TYPE | _ -> raise Thrift_error;; let typ_to_i = function | UNKNOWN -> 0l | UNKNOWN_METHOD -> 1l | INVALID_MESSAGE_TYPE -> 2l | WRONG_METHOD_NAME -> 3l | BAD_SEQUENCE_ID -> 4l | MISSING_RESULT -> 5l | INTERNAL_ERROR -> 6l | PROTOCOL_ERROR -> 7l | INVALID_TRANSFORM -> 8l | INVALID_PROTOCOL -> 9l | UNSUPPORTED_CLIENT_TYPE -> 10l class t = object (self) inherit t_exn val mutable typ = UNKNOWN method get_type = typ method set_type t = typ <- t method write (oprot : Protocol.t) = oprot#writeStructBegin "TApplicationExeception"; if self#get_message != "" then (oprot#writeFieldBegin ("message",Protocol.T_STRING, 1); oprot#writeString self#get_message; oprot#writeFieldEnd) else (); oprot#writeFieldBegin ("type",Protocol.T_I32,2); oprot#writeI32 (typ_to_i typ); oprot#writeFieldEnd; oprot#writeFieldStop; oprot#writeStructEnd end;; let create typ msg = let e = new t in e#set_type typ; e#set_message msg; e let read (iprot : Protocol.t) = let msg = ref "" in let typ = ref 0l in ignore iprot#readStructBegin; (try while true do let (name,ft,id) =iprot#readFieldBegin in if ft = Protocol.T_STOP then raise Break else (); (match id with | 1 -> (if ft = Protocol.T_STRING then msg := (iprot#readString) else iprot#skip ft) | 2 -> (if ft = Protocol.T_I32 then typ := iprot#readI32 else iprot#skip ft) | _ -> iprot#skip ft); iprot#readFieldEnd done with Break -> ()); iprot#readStructEnd; let e = new t in e#set_type (typ_of_i !typ); e#set_message !msg; e;; exception E of t end;; thrift-0.19.0/lib/ocaml/src/TChannelTransport.ml0000644000000000000000000000246314303740367021506 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift module T = Transport class t (i,o) = object (self) val mutable opened = true inherit Transport.t method isOpen = opened method opn = () method close = close_in i; opened <- false method read buf off len = if opened then try really_input i buf off len; len with _ -> raise (T.E (T.UNKNOWN, ("TChannelTransport: Could not read "^(string_of_int len)))) else raise (T.E (T.NOT_OPEN, "TChannelTransport: Channel was closed")) method write buf off len = output o buf off len method flush = flush o end thrift-0.19.0/lib/ocaml/src/TFramedTransport.ml0000644000000000000000000000511514303740367021331 0ustar00rootroot00000000000000open Thrift module T = Transport let c_0xff_32 = Int32.of_string "0xff" (* Copied from OCamlnet rtypes.ml *) let encode_frame_size x = let s = String.create 4 in let n3 = Int32.to_int (Int32.shift_right_logical x 24) land 0xff in let n2 = Int32.to_int (Int32.shift_right_logical x 16) land 0xff in let n1 = Int32.to_int (Int32.shift_right_logical x 8) land 0xff in let n0 = Int32.to_int (Int32.logand x c_0xff_32) in String.unsafe_set s 0 (Char.unsafe_chr n3); String.unsafe_set s 1 (Char.unsafe_chr n2); String.unsafe_set s 2 (Char.unsafe_chr n1); String.unsafe_set s 3 (Char.unsafe_chr n0); s let decode_frame_size s = let n3 = Int32.of_int (Char.code s.[0]) in let n2 = Int32.of_int (Char.code s.[1]) in let n1 = Int32.of_int (Char.code s.[2]) in let n0 = Int32.of_int (Char.code s.[3]) in Int32.logor (Int32.shift_left n3 24) (Int32.logor (Int32.shift_left n2 16) (Int32.logor (Int32.shift_left n1 8) n0)) class t ?(max_length=Sys.max_string_length) (transport: T.t) = object (self) inherit T.t method isOpen = transport#isOpen method opn = transport#opn method close = transport#close val mutable read_buf = None val mutable read_buf_offset = 0 val mutable write_buf = "" method private read_frame = let len_buf = String.create 4 in assert (transport#readAll len_buf 0 4 = 4); let size = Int32.to_int (decode_frame_size len_buf) in (if size < 0 then failwith (Printf.sprintf "Read a negative frame size (%i)!" size)); (if size > max_length then failwith (Printf.sprintf "Frame size (%i) larger than max length (%i)!" size max_length)); let buf = String.create size in assert (transport#readAll buf 0 size = size); read_buf <- Some buf; read_buf_offset <- 0 method private read_from_frame frame buf off len = let to_copy = min len ((String.length frame) - read_buf_offset) in String.blit frame read_buf_offset buf off to_copy; read_buf_offset <- read_buf_offset + to_copy; to_copy method read buf off len = match read_buf with | Some frame -> let i = self#read_from_frame frame buf off len in if i > 0 then i else begin self#read_frame; self#read_from_frame frame buf off len end | None -> self#read_frame; self#read buf off len method write buf off len = write_buf <- write_buf ^ (String.sub buf off len) method flush = let encoded_size = encode_frame_size (Int32.of_int (String.length write_buf)) in transport#write encoded_size 0 (String.length encoded_size); transport#write write_buf 0 (String.length write_buf); transport#flush; write_buf <- "" end thrift-0.19.0/lib/ocaml/src/TThreadedServer.ml0000644000000000000000000000251314303740367021124 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift class t (pf : Processor.t) (st : Transport.server_t) (tf : Transport.factory) (ipf : Protocol.factory) (opf : Protocol.factory)= object inherit TServer.t pf st tf ipf opf method serve = st#listen; while true do let tr = tf#getTransport (st#accept) in ignore (Thread.create (fun _ -> let ip = ipf#getProtocol tr in let op = opf#getProtocol tr in try while pf#process ip op do () done with _ -> ()) ()) done end thrift-0.19.0/lib/ocaml/src/TServer.ml0000644000000000000000000000264714303740367017473 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift class virtual t (pf : Processor.t) (st : Transport.server_t) (tf : Transport.factory) (ipf : Protocol.factory) (opf : Protocol.factory)= object method virtual serve : unit end;; let run_basic_server proc port = Unix.establish_server (fun inp -> fun out -> let trans = new TChannelTransport.t (inp,out) in let proto = new TBinaryProtocol.t (trans :> Transport.t) in try while proc#process proto proto do () done; () with e -> ()) (Unix.ADDR_INET (Unix.inet_addr_of_string "127.0.0.1",port)) thrift-0.19.0/lib/ocaml/src/TBinaryProtocol.ml0000644000000000000000000001170514303740367021166 0ustar00rootroot00000000000000(* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) open Thrift module P = Protocol let get_byte i b = 255 land (i lsr (8*b)) let get_byte32 i b = 255 land (Int32.to_int (Int32.shift_right i (8*b))) let get_byte64 i b = 255 land (Int64.to_int (Int64.shift_right i (8*b))) let tv = P.t_type_to_i let vt = P.t_type_of_i let comp_int b n = let s = ref 0l in let sb = 32 - 8*n in for i=0 to (n-1) do s:= Int32.logor !s (Int32.shift_left (Int32.of_int (int_of_char b.[i])) (8*(n-1-i))) done; Int32.shift_right (Int32.shift_left !s sb) sb let comp_int64 b n = let s = ref 0L in for i=0 to (n-1) do s:=Int64.logor !s (Int64.shift_left (Int64.of_int (int_of_char b.[i])) (8*(n-1-i))) done; !s let version_mask = 0xffff0000l let version_1 = 0x80010000l class t trans = object (self) inherit P.t trans val ibyte = String.create 8 method writeBool b = ibyte.[0] <- char_of_int (if b then 1 else 0); trans#write ibyte 0 1 method writeByte i = ibyte.[0] <- char_of_int (get_byte i 0); trans#write ibyte 0 1 method writeI16 i = let gb = get_byte i in ibyte.[1] <- char_of_int (gb 0); ibyte.[0] <- char_of_int (gb 1); trans#write ibyte 0 2 method writeI32 i = let gb = get_byte32 i in for i=0 to 3 do ibyte.[3-i] <- char_of_int (gb i) done; trans#write ibyte 0 4 method writeI64 i= let gb = get_byte64 i in for i=0 to 7 do ibyte.[7-i] <- char_of_int (gb i) done; trans#write ibyte 0 8 method writeDouble d = self#writeI64 (Int64.bits_of_float d) method writeString s= let n = String.length s in self#writeI32 (Int32.of_int n); trans#write s 0 n method writeBinary a = self#writeString a method writeMessageBegin (n,t,s) = self#writeI32 (Int32.logor version_1 (Int32.of_int (P.message_type_to_i t))); self#writeString n; self#writeI32 (Int32.of_int s) method writeMessageEnd = () method writeStructBegin s = () method writeStructEnd = () method writeFieldBegin (n,t,i) = self#writeByte (tv t); self#writeI16 i method writeFieldEnd = () method writeFieldStop = self#writeByte (tv (P.T_STOP)) method writeMapBegin (k,v,s) = self#writeByte (tv k); self#writeByte (tv v); self#writeI32 (Int32.of_int s) method writeMapEnd = () method writeListBegin (t,s) = self#writeByte (tv t); self#writeI32 (Int32.of_int s) method writeListEnd = () method writeSetBegin (t,s) = self#writeByte (tv t); self#writeI32 (Int32.of_int s) method writeSetEnd = () method readByte = ignore (trans#readAll ibyte 0 1); Int32.to_int (comp_int ibyte 1) method readI16 = ignore (trans#readAll ibyte 0 2); Int32.to_int (comp_int ibyte 2) method readI32 = ignore (trans#readAll ibyte 0 4); comp_int ibyte 4 method readI64 = ignore (trans#readAll ibyte 0 8); comp_int64 ibyte 8 method readDouble = Int64.float_of_bits (self#readI64) method readBool = self#readByte = 1 method readString = let sz = Int32.to_int (self#readI32) in let buf = String.create sz in ignore (trans#readAll buf 0 sz); buf method readBinary = self#readString method readMessageBegin = let ver = self#readI32 in if Int32.compare (Int32.logand ver version_mask) version_1 != 0 then raise (P.E (P.BAD_VERSION, "Missing version identifier")) else let s = self#readString in let mt = P.message_type_of_i (Int32.to_int (Int32.logand ver 0xFFl)) in (s,mt, Int32.to_int self#readI32) method readMessageEnd = () method readStructBegin = "" method readStructEnd = () method readFieldBegin = let t = (vt (self#readByte)) in if t != P.T_STOP then ("",t,self#readI16) else ("",t,0); method readFieldEnd = () method readMapBegin = let kt = vt (self#readByte) in let vt = vt (self#readByte) in (kt,vt, Int32.to_int self#readI32) method readMapEnd = () method readListBegin = let t = vt (self#readByte) in (t, Int32.to_int self#readI32) method readListEnd = () method readSetBegin = let t = vt (self#readByte) in (t, Int32.to_int self#readI32); method readSetEnd = () end class factory = object inherit P.factory method getProtocol tr = new t tr end thrift-0.19.0/lib/ocaml/README.md0000644000000000000000000000554414303740367016236 0ustar00rootroot00000000000000Thrift OCaml Software Library License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Library ======= The library abstract classes, exceptions, and general use functions are mostly jammed in Thrift.ml (an exception being TServer). Generally, classes are used, however they are often put in their own module along with other relevant types and functions. The classes often called t, exceptions are called E. Implementations live in their own files. There is TBinaryProtocol, TSocket, TThreadedServer, TSimpleServer, and TServerSocket. A note on making the library: Running make should create native, debug code libraries, and a toplevel. Struct format ------------- Structs are turned into classes. The fields are all option types and are initially None. Write is a method, but reading is done by a separate function (since there is no such thing as a static class). The class type is t and is in a module with the name of the struct. enum format ----------- Enums are put in their own module along with functions to_i and of_i which convert the ocaml types into ints. For example: enum Numberz { ONE = 1, TWO, THREE, FIVE = 5, SIX, EIGHT = 8 } ==> module Numberz = struct type t = | ONE | TWO | THREE | FIVE | SIX | EIGHT let of_i = ... let to_i = ... end typedef format -------------- Typedef turns into the type declaration: typedef i64 UserId ==> type userid Int64.t exception format ---------------- The same as structs except that the module also has an exception type E of t that is raised/caught. For example, with an exception Xception, raise (Xception.E (new Xception.t)) and try ... with Xception.E e -> ... list format ----------- Lists are turned into OCaml native lists. Map/Set formats --------------- These are both turned into Hashtbl.t's. Set values are bool. Services -------- The client is a class "client" parametrized on input and output protocols. The processor is a class parametrized on a handler. A handler is a class inheriting the iface abstract class. Unlike other implementations, client does not implement iface since iface functions must take option arguments so as to deal with the case where a client does not send all the arguments. thrift-0.19.0/lib/ocaml/coding_standards.md0000644000000000000000000000010314303740367020571 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/ocaml/url0000644000000000000000000000011114303740367015465 0ustar00rootroot00000000000000archive: "XXX(FILL ME IN WITH URL)" checksum: "XXX(FILL ME IN WITH MD5)" thrift-0.19.0/lib/ocaml/DEVELOPMENT0000644000000000000000000000405214303740367016455 0ustar00rootroot00000000000000Thrift OCaml Development ======================== Prerequisites ------------- In order to build this library, you must have the following installed: * The OCaml compiler, preferably >4.00 * The Oasis build tool In addition you may want to install OPAM, which will allow you to setup an OCaml development environment that's isolated from your system installation, much like virutalenv for Python or the myriad systems available for Ruby. If you have OPAM installed, then installing Oasis is as simple as running: $ opam install oasis Building -------- Once all the prerequisites have been installed, run the following commands: $ oasis setup $ ./configure $ make The `oasis setup` command will generate the configure script and Makefile, along with other files that opam will use to create an installable library. The cofigure script will ensure that all build dependencies are installed, and make will actually build the library. To remove files that the compiler geneates, run: $ make clean To remove those files _as well as_ files that the setup and configure process generates, run: $ rm `cat .gitignore` Installing ---------- If you're using opam, simply run the following command: $ make install While development, you may want to install your latest build on the system to test against other libraries or programs. To do this, use: $ make reinstall Distribution ------------ The de facto preferred method for distributing OCaml libraries is through the OPAM package repository. To publish the latest package, issue a pull request against the following github repository: https://github.com/ocaml/opam-repository The pull requestion should add the following directory structure and files: package |__thrift |__thrift. |__ descr |__ opam |__ url Templates for the following files can be found in the opam/ subdirectory of this library's root, with XXX(...) indicating fields that need to be filled out. You can find further documentation here: http://opam.ocaml.org/doc/Packaging.html thrift-0.19.0/lib/ts/0000777000000000000000000000000014472652605014312 5ustar00rootroot00000000000000thrift-0.19.0/lib/ts/dist/0000777000000000000000000000000014303740367015251 5ustar00rootroot00000000000000thrift-0.19.0/lib/ts/dist/thrift.min.js0000644000000000000000000000003114303740367017657 0ustar00rootroot00000000000000/*! thrift 07-01-2019 */ thrift-0.19.0/lib/ts/dist/thrift.js0000644000000000000000000000000014303740367017071 0ustar00rootroot00000000000000thrift-0.19.0/lib/ts/package.json0000644000000000000000000000216314454461475016601 0ustar00rootroot00000000000000{ "name": "thrift", "version": "0.19.0", "description": "Thrift is a software framework for scalable cross-language services development.", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org" }, "bugs": "https://issues.apache.org/jira/projects/THRIFT/summary", "homepage": "http://thrift.apache.org", "repository": "https://github.com/apache/thrift", "license": "Apache-2.0", "devDependencies": { "@types/node-int64": "^0.4.29", "@types/phantom": "^3.2.5", "@types/qunit": "^2.5.4", "browserify": "^16.2.3", "bufferutil": "^4.0.1", "grunt": "^1.4.1", "grunt-cli": "^1.4.3", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-jshint": "^3.2.0", "grunt-contrib-qunit": "^3.1.0", "grunt-contrib-uglify": "^1.0.1", "grunt-jsdoc": "^2.4.1", "grunt-shell-spawn": "^0.3.12", "jslint": "^0.12.0", "node-int64": "^0.4.0", "phantom": "^6.0.3", "typescript": "^3.2.4" }, "dependencies": { "bufferutil": "^4.0.1", "jsdoc": "^3.6.7", "json-int64": "^1.0.0", "nopt": "^4.0.1" }, "types": "./thrift.d.ts" } thrift-0.19.0/lib/ts/Makefile.am0000644000000000000000000000271414303740367016342 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Make sure this doesn't fail if ant is not configured. # We call install twice to work around npm issues # if HAVE_NPM prereq: $(NPM) install || $(NPM) install $(NPM) list check-local: prereq all ./node_modules/.bin/grunt doc: prereq ./node_modules/.bin/grunt jsdoc endif clean-local: $(RM) -r dist $(RM) -r doc $(RM) -r node_modules $(RM) -r test/build/ $(RM) -r test/gen-*/ dist-hook: $(RM) -r $(distdir)/dist/ $(RM) -r $(distdir)/doc/ $(RM) -r $(distdir)/node_modules/ $(RM) -r $(distdir)/test/build/ $(RM) -r $(distdir)/test/gen-*/ EXTRA_DIST = \ coding_standards.md \ Gruntfile.js \ package.json \ package-lock.json \ thrift.d.ts \ tsconfig.json thrift-0.19.0/lib/ts/tsconfig.json0000644000000000000000000000134214303740367017011 0ustar00rootroot00000000000000{ "compilerOptions": { "allowJs": false, "alwaysStrict": true, "baseUrl": ".", "declaration": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "module": "commonjs", "moduleResolution": "node", "noImplicitThis": true, "noUnusedLocals": true, "preserveConstEnums": true, "removeComments": true, "strictFunctionTypes": true, "strictNullChecks": true, "target": "es6", "paths": { "*": [ "*", "test/", "test/gen-js/*" ] }, }, "exclude": [ "./test/gen-nodejs/", "./test/build/", ] } thrift-0.19.0/lib/ts/Makefile0000644000000000000000000004454314472652605015760 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # lib/ts/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = lib/ts ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/lib/ts abs_srcdir = /thrift/src/lib/ts abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. EXTRA_DIST = \ coding_standards.md \ Gruntfile.js \ package.json \ package-lock.json \ thrift.d.ts \ tsconfig.json all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/ts/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/ts/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook #check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # Make sure this doesn't fail if ant is not configured. # We call install twice to work around npm issues # prereq: $(NPM) install || $(NPM) install $(NPM) list check-local: prereq all ./node_modules/.bin/grunt doc: prereq ./node_modules/.bin/grunt jsdoc clean-local: $(RM) -r dist $(RM) -r doc $(RM) -r node_modules $(RM) -r test/build/ $(RM) -r test/gen-*/ dist-hook: $(RM) -r $(distdir)/dist/ $(RM) -r $(distdir)/doc/ $(RM) -r $(distdir)/node_modules/ $(RM) -r $(distdir)/test/build/ $(RM) -r $(distdir)/test/gen-*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/ts/package-lock.json0000644000000000000000000052165514454461475017543 0ustar00rootroot00000000000000{ "name": "thrift", "version": "0.19.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "thrift", "version": "0.19.0", "license": "Apache-2.0", "dependencies": { "bufferutil": "^4.0.1", "jsdoc": "^3.6.7", "json-int64": "^1.0.0", "nopt": "^4.0.1" }, "devDependencies": { "@types/node-int64": "^0.4.29", "@types/phantom": "^3.2.5", "@types/qunit": "^2.5.4", "browserify": "^16.2.3", "bufferutil": "^4.0.1", "grunt": "^1.4.1", "grunt-cli": "^1.4.3", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-jshint": "^3.2.0", "grunt-contrib-qunit": "^3.1.0", "grunt-contrib-uglify": "^1.0.1", "grunt-jsdoc": "^2.4.1", "grunt-shell-spawn": "^0.3.12", "jslint": "^0.12.0", "node-int64": "^0.4.0", "phantom": "^6.0.3", "typescript": "^3.2.4" } }, "node_modules/@babel/parser": { "version": "7.19.3", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.3.tgz", "integrity": "sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==", "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, "engines": { "node": ">=0.1.90" } }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", "dev": true, "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "node_modules/@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==" }, "node_modules/@types/markdown-it": { "version": "12.2.3", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", "dependencies": { "@types/linkify-it": "*", "@types/mdurl": "*" } }, "node_modules/@types/mdurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" }, "node_modules/@types/node": { "version": "10.12.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", "dev": true }, "node_modules/@types/node-int64": { "version": "0.4.29", "resolved": "https://registry.npmjs.org/@types/node-int64/-/node-int64-0.4.29.tgz", "integrity": "sha512-rHXvenLTj/CcsmNAebaBOhxQ2MqEGl3yXZZcZ21XYR+gzGTTcpOy2N4IxpvTCz48loyQNatHvfn6GhIbbZ1R3Q==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/phantom": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/@types/phantom/-/phantom-3.2.5.tgz", "integrity": "sha512-7m36DoKSvZgBGWp0xiJ74eHnuotyrpDyQ6m+lers5iMvW4QX+RvBENn7PCjNix7OVqPWlBM+7AqzYVIQ7NrKrA==", "dev": true }, "node_modules/@types/qunit": { "version": "2.5.4", "resolved": "https://registry.npmjs.org/@types/qunit/-/qunit-2.5.4.tgz", "integrity": "sha512-VHi2lEd4/zp8OOouf43JXGJJ5ZxHvdLL1dU0Yakp6Iy73SjpuXl7yjwAwmh1qhTv8krDgHteSwaySr++uXX9YQ==", "dev": true }, "node_modules/@types/triple-beam": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==", "dev": true }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/acorn": { "version": "6.4.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", "dev": true, "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-dynamic-import": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", "deprecated": "This is probably built in to whatever tool you're using. If you still need it... idk", "dev": true, "peerDependencies": { "acorn": "^6.0.0" } }, "node_modules/acorn-node": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", "dev": true, "dependencies": { "acorn": "^6.0.2", "acorn-dynamic-import": "^4.0.0", "acorn-walk": "^6.1.0", "xtend": "^4.0.1" } }, "node_modules/acorn-walk": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ajv/node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "node_modules/align-text": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "dependencies": { "kind-of": "^3.0.2", "longest": "^1.0.1", "repeat-string": "^1.5.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/align-text/node_modules/kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "dependencies": { "is-buffer": "^1.1.5" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/ansi-styles/node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/ansi-styles/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/argparse/node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, "node_modules/array-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, "dependencies": { "safer-buffer": "~2.1.0" } }, "node_modules/asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "dependencies": { "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "node_modules/assert": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "dev": true, "dependencies": { "util": "0.10.3" } }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true, "engines": { "node": ">=0.8" } }, "node_modules/assert/node_modules/inherits": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", "dev": true }, "node_modules/assert/node_modules/util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "dependencies": { "inherits": "2.0.1" } }, "node_modules/async": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, "node_modules/async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "dev": true }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true, "engines": { "node": "*" } }, "node_modules/aws4": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, "node_modules/base64-js": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "dependencies": { "tweetnacl": "^0.14.3" } }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "dependencies": { "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, "node_modules/browser-pack": { "version": "6.1.0", "resolved": "http://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", "dev": true, "dependencies": { "combine-source-map": "~0.8.0", "defined": "^1.0.0", "JSONStream": "^1.0.3", "safe-buffer": "^5.1.1", "through2": "^2.0.0", "umd": "^3.0.0" }, "bin": { "browser-pack": "bin/cmd.js" } }, "node_modules/browser-resolve": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", "dev": true, "dependencies": { "resolve": "1.1.7" } }, "node_modules/browser-resolve/node_modules/resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", "dev": true }, "node_modules/browserify": { "version": "16.2.3", "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", "dev": true, "dependencies": { "assert": "^1.4.0", "browser-pack": "^6.0.1", "browser-resolve": "^1.11.0", "browserify-zlib": "~0.2.0", "buffer": "^5.0.2", "cached-path-relative": "^1.0.0", "concat-stream": "^1.6.0", "console-browserify": "^1.1.0", "constants-browserify": "~1.0.0", "crypto-browserify": "^3.0.0", "defined": "^1.0.0", "deps-sort": "^2.0.0", "domain-browser": "^1.2.0", "duplexer2": "~0.1.2", "events": "^2.0.0", "glob": "^7.1.0", "has": "^1.0.0", "htmlescape": "^1.1.0", "https-browserify": "^1.0.0", "inherits": "~2.0.1", "insert-module-globals": "^7.0.0", "JSONStream": "^1.0.3", "labeled-stream-splicer": "^2.0.0", "mkdirp": "^0.5.0", "module-deps": "^6.0.0", "os-browserify": "~0.3.0", "parents": "^1.0.1", "path-browserify": "~0.0.0", "process": "~0.11.0", "punycode": "^1.3.2", "querystring-es3": "~0.2.0", "read-only-stream": "^2.0.0", "readable-stream": "^2.0.2", "resolve": "^1.1.4", "shasum": "^1.0.0", "shell-quote": "^1.6.1", "stream-browserify": "^2.0.0", "stream-http": "^2.0.0", "string_decoder": "^1.1.1", "subarg": "^1.0.0", "syntax-error": "^1.1.1", "through2": "^2.0.0", "timers-browserify": "^1.0.1", "tty-browserify": "0.0.1", "url": "~0.11.0", "util": "~0.10.1", "vm-browserify": "^1.0.0", "xtend": "^4.0.0" }, "bin": { "browserify": "bin/cmd.js" }, "engines": { "node": ">= 0.8" } }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.3", "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "node_modules/browserify-cipher": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "dev": true, "dependencies": { "browserify-aes": "^1.0.4", "browserify-des": "^1.0.0", "evp_bytestokey": "^1.0.0" } }, "node_modules/browserify-des": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "dev": true, "dependencies": { "cipher-base": "^1.0.1", "des.js": "^1.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "node_modules/browserify-rsa": { "version": "4.0.1", "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "dependencies": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" } }, "node_modules/browserify-sign": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "dev": true, "dependencies": { "bn.js": "^4.1.1", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "create-hmac": "^1.1.2", "elliptic": "^6.0.0", "inherits": "^2.0.1", "parse-asn1": "^5.0.0" } }, "node_modules/browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "dev": true, "dependencies": { "pako": "~1.0.5" } }, "node_modules/buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", "dev": true, "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4" } }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true, "engines": { "node": "*" } }, "node_modules/buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, "node_modules/buffer-shims": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, "node_modules/bufferutil": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", "dev": true, "hasInstallScript": true, "dependencies": { "node-gyp-build": "~3.7.0" } }, "node_modules/builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "dev": true }, "node_modules/cached-path-relative": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz", "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==", "dev": true }, "node_modules/camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/camelcase-keys": { "version": "2.1.0", "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "dependencies": { "camelcase": "^2.0.0", "map-obj": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, "node_modules/catharsis": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", "dependencies": { "lodash": "^4.17.15" }, "engines": { "node": ">= 10" } }, "node_modules/center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "dependencies": { "align-text": "^0.1.3", "lazy-cache": "^1.0.3" }, "engines": { "node": ">=0.10.0" } }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, "node_modules/cli": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", "integrity": "sha512-41U72MB56TfUMGndAKK8vJ78eooOD4Z5NOL4xEfjc0c23s+6EYKXlXsmACBVclLP1yOfWCgEganVzddVrSNoTg==", "dev": true, "dependencies": { "exit": "0.1.2", "glob": "^7.1.1" }, "engines": { "node": ">=0.2.5" } }, "node_modules/cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "dependencies": { "center-align": "^0.1.1", "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, "node_modules/color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", "dev": true, "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "dependencies": { "color-name": "1.1.3" } }, "node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "node_modules/color-string": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dev": true, "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "node_modules/colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true, "engines": { "node": ">=0.1.90" } }, "node_modules/colorspace": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "dev": true, "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "node_modules/combine-source-map": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", "dev": true, "dependencies": { "convert-source-map": "~1.1.0", "inline-source-map": "~0.6.0", "lodash.memoize": "~3.0.3", "source-map": "~0.5.3" } }, "node_modules/combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "engines": [ "node >= 0.8" ], "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" } }, "node_modules/console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "dependencies": { "date-now": "^0.1.4" } }, "node_modules/constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", "dev": true }, "node_modules/convert-source-map": { "version": "1.1.3", "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", "dev": true }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, "node_modules/create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "dev": true, "dependencies": { "bn.js": "^4.1.0", "elliptic": "^6.0.0" } }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", "md5.js": "^1.3.4", "ripemd160": "^2.0.1", "sha.js": "^2.4.0" } }, "node_modules/create-hmac": { "version": "1.1.7", "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", "inherits": "^2.0.1", "ripemd160": "^2.0.0", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" } }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/cross-spawn/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "dev": true, "dependencies": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", "create-ecdh": "^4.0.0", "create-hash": "^1.1.0", "create-hmac": "^1.1.0", "diffie-hellman": "^5.0.0", "inherits": "^2.0.1", "pbkdf2": "^3.0.3", "public-encrypt": "^4.0.0", "randombytes": "^2.0.0", "randomfill": "^1.0.3" }, "engines": { "node": "*" } }, "node_modules/currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "dependencies": { "array-find-index": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "dependencies": { "assert-plus": "^1.0.0" }, "engines": { "node": ">=0.10" } }, "node_modules/date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", "dev": true }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true, "engines": { "node": "*" } }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { "ms": "2.0.0" } }, "node_modules/decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/defined": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/deps-sort": { "version": "2.0.0", "resolved": "http://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", "dev": true, "dependencies": { "JSONStream": "^1.0.3", "shasum": "^1.0.0", "subarg": "^1.0.0", "through2": "^2.0.0" }, "bin": { "deps-sort": "bin/cmd.js" } }, "node_modules/des.js": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "dev": true, "dependencies": { "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" } }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/detective": { "version": "5.1.0", "resolved": "http://registry.npmjs.org/detective/-/detective-5.1.0.tgz", "integrity": "sha512-TFHMqfOvxlgrfVzTEkNBSh9SvSNX/HfF4OFI2QFGCyPm02EsyILqnUeb5P6q7JZ3SFNTBL5t2sePRgrN4epUWQ==", "dev": true, "dependencies": { "acorn-node": "^1.3.0", "defined": "^1.0.0", "minimist": "^1.1.1" }, "bin": { "detective": "bin/detective.js" }, "engines": { "node": ">=0.8.0" } }, "node_modules/diffie-hellman": { "version": "5.0.3", "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "dependencies": { "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" } }, "node_modules/dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", "dev": true, "dependencies": { "domelementtype": "^2.0.1", "entities": "^2.0.0" } }, "node_modules/dom-serializer/node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } ] }, "node_modules/dom-serializer/node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true, "engines": { "node": ">=0.4", "npm": ">=1.2" } }, "node_modules/domelementtype": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, "node_modules/domhandler": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", "integrity": "sha512-q9bUwjfp7Eif8jWxxxPSykdRZAb6GkguBGSgvvCrhI9wB71W2K/Kvv4E61CF/mcCfnVJDeDWx/Vb/uAqbDj6UQ==", "dev": true, "dependencies": { "domelementtype": "1" } }, "node_modules/domutils": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", "integrity": "sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==", "dev": true, "dependencies": { "dom-serializer": "0", "domelementtype": "1" } }, "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, "dependencies": { "readable-stream": "^2.0.2" } }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "dev": true, "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", "hash.js": "^1.0.0", "hmac-drbg": "^1.0.1", "inherits": "^2.0.4", "minimalistic-assert": "^1.0.1", "minimalistic-crypto-utils": "^1.0.1" } }, "node_modules/elliptic/node_modules/bn.js": { "version": "4.12.0", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, "node_modules/elliptic/node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "node_modules/enabled": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", "dev": true }, "node_modules/entities": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", "integrity": "sha512-LbLqfXgJMmy81t+7c14mnulFHJ170cM6E+0vMXR9k/ZiZwgX8i5pNgjTCX3SO4VeUsFLV+8InixoretwU+MjBQ==", "dev": true }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es6-promise": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, "node_modules/es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "dependencies": { "es6-promise": "^4.0.3" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, "node_modules/eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, "node_modules/events": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", "dev": true, "engines": { "node": ">=0.4.x" } }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" } }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "dependencies": { "homedir-polyfill": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "node_modules/extract-zip": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", "dev": true, "dependencies": { "concat-stream": "^1.6.2", "debug": "^2.6.9", "mkdirp": "^0.5.4", "yauzl": "^2.10.0" }, "bin": { "extract-zip": "cli.js" } }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true, "engines": [ "node >=0.6.0" ] }, "node_modules/fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "dependencies": { "pend": "~1.2.0" } }, "node_modules/fecha": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", "dev": true }, "node_modules/figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "dependencies": { "escape-string-regexp": "^1.0.5", "object-assign": "^4.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "dependencies": { "path-exists": "^2.0.0", "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/findup-sync": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", "dev": true, "dependencies": { "glob": "~5.0.0" }, "engines": { "node": ">= 0.6.0" } }, "node_modules/findup-sync/node_modules/glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "dependencies": { "inflight": "^1.0.4", "inherits": "2", "minimatch": "2 || 3", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" } }, "node_modules/fined": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", "dev": true, "dependencies": { "expand-tilde": "^2.0.2", "is-plain-object": "^2.0.3", "object.defaults": "^1.1.0", "object.pick": "^1.2.0", "parse-filepath": "^1.0.1" }, "engines": { "node": ">= 0.10" } }, "node_modules/flagged-respawn": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true, "engines": { "node": ">= 0.10" } }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", "dev": true }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/for-own": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "dependencies": { "for-in": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true, "engines": { "node": "*" } }, "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" }, "engines": { "node": ">= 0.12" } }, "node_modules/fs-extra": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^2.1.0", "klaw": "^1.0.0" } }, "node_modules/fs-extra/node_modules/klaw": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.9" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "node_modules/get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", "dev": true }, "node_modules/get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/getobject": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "dependencies": { "assert-plus": "^1.0.0" } }, "node_modules/glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" } }, "node_modules/global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "dependencies": { "global-prefix": "^1.0.1", "is-windows": "^1.0.1", "resolve-dir": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "dependencies": { "expand-tilde": "^2.0.2", "homedir-polyfill": "^1.0.1", "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" }, "engines": { "node": ">=0.10.0" } }, "node_modules/graceful-fs": { "version": "4.1.15", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, "node_modules/grunt": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.5.3.tgz", "integrity": "sha512-mKwmo4X2d8/4c/BmcOETHek675uOqw0RuA/zy12jaspWqvTp4+ZeQF1W+OTpcbncnaBsfbQJ6l0l4j+Sn/GmaQ==", "dev": true, "dependencies": { "dateformat": "~3.0.3", "eventemitter2": "~0.4.13", "exit": "~0.1.2", "findup-sync": "~0.3.0", "glob": "~7.1.6", "grunt-cli": "~1.4.3", "grunt-known-options": "~2.0.0", "grunt-legacy-log": "~3.0.0", "grunt-legacy-util": "~2.0.1", "iconv-lite": "~0.4.13", "js-yaml": "~3.14.0", "minimatch": "~3.0.4", "mkdirp": "~1.0.4", "nopt": "~3.0.6", "rimraf": "~3.0.2" }, "bin": { "grunt": "bin/grunt" }, "engines": { "node": ">=8" } }, "node_modules/grunt-cli": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.3.tgz", "integrity": "sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==", "dev": true, "dependencies": { "grunt-known-options": "~2.0.0", "interpret": "~1.1.0", "liftup": "~3.0.1", "nopt": "~4.0.1", "v8flags": "~3.2.0" }, "bin": { "grunt": "bin/grunt" }, "engines": { "node": ">=10" } }, "node_modules/grunt-contrib-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", "integrity": "sha1-YVCYYwhOhx1+ht5IwBUlntl3Rb0=", "dev": true, "dependencies": { "chalk": "^1.0.0", "source-map": "^0.5.3" }, "engines": { "node": ">=0.10.0" }, "peerDependencies": { "grunt": ">=0.4.0" } }, "node_modules/grunt-contrib-concat/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/grunt-contrib-concat/node_modules/chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/grunt-contrib-concat/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/grunt-contrib-jshint": { "version": "3.2.0", "resolved": "http://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-3.2.0.tgz", "integrity": "sha512-pcXWCSZWfoMSvcV4BwH21TUtLtcX0Ms8IGuOPIcLeXK3fud9KclY7iqMKY94jFx8TxZzh028YYtpR+io8DiEaQ==", "dev": true, "dependencies": { "chalk": "~4.1.2", "hooker": "^0.2.3", "jshint": "~2.13.4" }, "engines": { "node": ">=10" } }, "node_modules/grunt-contrib-qunit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.1.0.tgz", "integrity": "sha512-mdk8UltH6mxCD63E0hTXMAts42DOi4z4bBBrY7qnuHiShflMF7IueSMYe0zWaZ2dO8mgujh57Zfny2EbigJhRg==", "dev": true, "dependencies": { "eventemitter2": "^5.0.1", "p-each-series": "^1.0.0", "puppeteer": "^1.11.0" }, "engines": { "node": ">=6" } }, "node_modules/grunt-contrib-qunit/node_modules/eventemitter2": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=", "dev": true }, "node_modules/grunt-contrib-uglify": { "version": "1.0.2", "resolved": "http://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-1.0.2.tgz", "integrity": "sha1-rmekb5FT7dTLEYE6Vetpxw19svs=", "dev": true, "dependencies": { "chalk": "^1.0.0", "lodash": "^4.0.1", "maxmin": "^1.1.0", "uglify-js": "~2.6.2", "uri-path": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/grunt-contrib-uglify/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/grunt-contrib-uglify/node_modules/chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/grunt-contrib-uglify/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/grunt-jsdoc": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", "dev": true, "dependencies": { "cross-spawn": "^7.0.1", "jsdoc": "^3.6.3" }, "bin": { "grunt-jsdoc": "bin/grunt-jsdoc" }, "engines": { "node": ">= 8.12.0" } }, "node_modules/grunt-known-options": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/grunt-legacy-log": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.0.tgz", "integrity": "sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==", "dev": true, "dependencies": { "colors": "~1.1.2", "grunt-legacy-log-utils": "~2.1.0", "hooker": "~0.2.3", "lodash": "~4.17.19" }, "engines": { "node": ">= 0.10.0" } }, "node_modules/grunt-legacy-log-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.0.tgz", "integrity": "sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==", "dev": true, "dependencies": { "chalk": "~4.1.0", "lodash": "~4.17.19" }, "engines": { "node": ">=10" } }, "node_modules/grunt-legacy-util": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", "dev": true, "dependencies": { "async": "~3.2.0", "exit": "~0.1.2", "getobject": "~1.0.0", "hooker": "~0.2.3", "lodash": "~4.17.21", "underscore.string": "~3.3.5", "which": "~2.0.2" }, "engines": { "node": ">=10" } }, "node_modules/grunt-legacy-util/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/grunt-shell-spawn": { "version": "0.3.12", "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.12.tgz", "integrity": "sha512-TprZct92sQ4M2Q92piaeLsCrx4+gq/ageuxjZsRG6cglKt7x7rGA3YHt8D30+G789v+/pw4l0tDjEyrkMXx2tA==", "dev": true, "dependencies": { "grunt": ">=0.4.x" }, "bin": { "grunt-shell-spawn": "bin/grunt-shell-spawn" }, "engines": { "node": ">=0.12.0" } }, "node_modules/grunt/node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/grunt/node_modules/minimatch": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/grunt/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" } }, "node_modules/grunt/node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "node_modules/grunt/node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/gzip-size": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", "dev": true, "dependencies": { "browserify-zlib": "^0.1.4", "concat-stream": "^1.4.1" }, "bin": { "gzip-size": "cli.js" }, "engines": { "node": ">=0.10.0" } }, "node_modules/gzip-size/node_modules/browserify-zlib": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", "dev": true, "dependencies": { "pako": "~0.2.0" } }, "node_modules/gzip-size/node_modules/pako": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/har-validator": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "deprecated": "this library is no longer supported", "dev": true, "dependencies": { "ajv": "^6.5.5", "har-schema": "^2.0.0" }, "engines": { "node": ">=6" } }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "dependencies": { "function-bind": "^1.1.1" }, "engines": { "node": ">= 0.4.0" } }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/hash-base": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" }, "engines": { "node": ">=4" } }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, "node_modules/hasha": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "dependencies": { "is-stream": "^1.0.1", "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.1" } }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "dependencies": { "parse-passwd": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/hooker": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", "dev": true, "engines": { "node": "*" } }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "node_modules/htmlescape": { "version": "1.1.1", "resolved": "http://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", "dev": true, "engines": { "node": ">=0.10" } }, "node_modules/htmlparser2": { "version": "3.8.3", "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", "integrity": "sha512-hBxEg3CYXe+rPIua8ETe7tmG3XDn9B0edOE/e9wH2nLczxzgdu0m0aNHY+5wFZiviLWLdANPJTssa92dMcXQ5Q==", "dev": true, "dependencies": { "domelementtype": "1", "domhandler": "2.3", "domutils": "1.5", "entities": "1.0", "readable-stream": "1.1" } }, "node_modules/htmlparser2/node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true }, "node_modules/htmlparser2/node_modules/readable-stream": { "version": "1.1.14", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "node_modules/htmlparser2/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true }, "node_modules/http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", "sshpk": "^1.7.0" }, "engines": { "node": ">=0.8", "npm": ">=1.3.7" } }, "node_modules/https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, "node_modules/https-proxy-agent": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "dependencies": { "agent-base": "^4.3.0", "debug": "^3.1.0" }, "engines": { "node": ">= 4.5.0" } }, "node_modules/https-proxy-agent/node_modules/agent-base": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", "dev": true, "dependencies": { "es6-promisify": "^5.0.0" }, "engines": { "node": ">= 4.0.0" } }, "node_modules/https-proxy-agent/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "dependencies": { "ms": "^2.1.1" } }, "node_modules/https-proxy-agent/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, "engines": { "node": ">=0.10.0" } }, "node_modules/ieee754": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", "dev": true }, "node_modules/indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "dependencies": { "repeating": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "node_modules/inline-source-map": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", "dev": true, "dependencies": { "source-map": "~0.5.3" } }, "node_modules/insert-module-globals": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", "dev": true, "dependencies": { "acorn-node": "^1.5.2", "combine-source-map": "^0.8.0", "concat-stream": "^1.6.1", "is-buffer": "^1.1.0", "JSONStream": "^1.0.3", "path-is-absolute": "^1.0.1", "process": "~0.11.0", "through2": "^2.0.0", "undeclared-identifiers": "^1.1.2", "xtend": "^4.0.0" }, "bin": { "insert-module-globals": "bin/cmd.js" } }, "node_modules/interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, "node_modules/is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "dependencies": { "is-relative": "^1.0.0", "is-windows": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "node_modules/is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, "node_modules/is-builtin-module": { "version": "1.0.0", "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "dependencies": { "builtin-modules": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-core-module": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "dev": true, "dependencies": { "has": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-finite": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "dependencies": { "number-is-nan": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "engines": { "node": ">=0.12.0" } }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "dependencies": { "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "dependencies": { "is-unc-path": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "dependencies": { "unc-path-regex": "^0.1.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/js2xmlparser": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", "dependencies": { "xmlcreate": "^2.0.4" } }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, "node_modules/jsdoc": { "version": "3.6.11", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", "dependencies": { "@babel/parser": "^7.9.4", "@types/markdown-it": "^12.2.3", "bluebird": "^3.7.2", "catharsis": "^0.9.0", "escape-string-regexp": "^2.0.0", "js2xmlparser": "^4.0.2", "klaw": "^3.0.0", "markdown-it": "^12.3.2", "markdown-it-anchor": "^8.4.1", "marked": "^4.0.10", "mkdirp": "^1.0.4", "requizzle": "^0.2.3", "strip-json-comments": "^3.1.0", "taffydb": "2.6.2", "underscore": "~1.13.2" }, "bin": { "jsdoc": "jsdoc.js" }, "engines": { "node": ">=12.0.0" } }, "node_modules/jsdoc/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "engines": { "node": ">=8" } }, "node_modules/jsdoc/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "bin": { "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" } }, "node_modules/jshint": { "version": "2.13.5", "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.5.tgz", "integrity": "sha512-dB2n1w3OaQ35PLcBGIWXlszjbPZwsgZoxsg6G8PtNf2cFMC1l0fObkYLUuXqTTdi6tKw4sAjfUseTdmDMHQRcg==", "dev": true, "dependencies": { "cli": "~1.0.0", "console-browserify": "1.1.x", "exit": "0.1.x", "htmlparser2": "3.8.x", "lodash": "~4.17.21", "minimatch": "~3.0.2", "strip-json-comments": "1.0.x" }, "bin": { "jshint": "bin/jshint" } }, "node_modules/jshint/node_modules/minimatch": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/jshint/node_modules/strip-json-comments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", "integrity": "sha512-AOPG8EBc5wAikaG1/7uFCNFJwnKOuQwFTpYBdTW6OvWHeZBQBrAA/amefHGrEiOnCPcLFZK6FUPtWVKpQVIRgg==", "dev": true, "bin": { "strip-json-comments": "cli.js" }, "engines": { "node": ">=0.8.0" } }, "node_modules/jslint": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/jslint/-/jslint-0.12.0.tgz", "integrity": "sha512-RoCsyICcKA+6TFsbys9DpKTfPVaC71Mm5QSjvrWA0lDVN+LIvx6apa42FFisMqmCTvJ8DxkcoQGJ0j7m3kTVow==", "dev": true, "dependencies": { "exit": "~0.1.2", "glob": "~7.1.2", "nopt": "~3.0.1", "readable-stream": "~2.1.5" }, "bin": { "jslint": "bin/jslint.js" }, "engines": { "node": ">=0.8.0" } }, "node_modules/jslint/node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "dependencies": { "abbrev": "1" }, "bin": { "nopt": "bin/nopt.js" } }, "node_modules/jslint/node_modules/process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, "node_modules/jslint/node_modules/readable-stream": { "version": "2.1.5", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", "dev": true, "dependencies": { "buffer-shims": "^1.0.0", "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "~1.0.0", "process-nextick-args": "~1.0.6", "string_decoder": "~0.10.x", "util-deprecate": "~1.0.1" } }, "node_modules/jslint/node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "node_modules/json-int64": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.0.tgz", "integrity": "sha512-yrTg9swToElhEPETLMdZkEzDhbXLs+cxkw/b2rglMPOBlM1DE0utH1EReSMLcnpYJk5iUvD12r0fP2/xHitF5Q==", "dependencies": { "node-int64": "0.4.0" } }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, "node_modules/json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", "dev": true, "dependencies": { "jsonify": "~0.0.0" } }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, "node_modules/jsonfile": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true, "engines": { "node": "*" } }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true, "engines": [ "node >= 0.2.0" ] }, "node_modules/JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", "dev": true, "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" }, "bin": { "JSONStream": "bin.js" }, "engines": { "node": "*" } }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", "dev": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" }, "engines": { "node": ">=0.6.0" } }, "node_modules/jsprim/node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", "dev": true }, "node_modules/kew": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", "dev": true }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "dependencies": { "graceful-fs": "^4.1.9" } }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", "dev": true }, "node_modules/labeled-stream-splicer": { "version": "2.0.1", "resolved": "http://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", "dev": true, "dependencies": { "inherits": "^2.0.1", "isarray": "^2.0.4", "stream-splicer": "^2.0.0" } }, "node_modules/labeled-stream-splicer/node_modules/isarray": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", "dev": true }, "node_modules/lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/liftup": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", "dev": true, "dependencies": { "extend": "^3.0.2", "findup-sync": "^4.0.0", "fined": "^1.2.0", "flagged-respawn": "^1.0.1", "is-plain-object": "^2.0.4", "object.map": "^1.0.1", "rechoir": "^0.7.0", "resolve": "^1.19.0" }, "engines": { "node": ">=10" } }, "node_modules/liftup/node_modules/findup-sync": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", "dev": true, "dependencies": { "detect-file": "^1.0.0", "is-glob": "^4.0.0", "micromatch": "^4.0.2", "resolve-dir": "^1.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/liftup/node_modules/resolve": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "dependencies": { "is-core-module": "^2.2.0", "path-parse": "^1.0.6" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", "dependencies": { "uc.micro": "^1.0.1" } }, "node_modules/load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", "pify": "^2.0.0", "pinkie-promise": "^2.0.0", "strip-bom": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.memoize": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", "dev": true }, "node_modules/logform": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", "dev": true, "dependencies": { "@colors/colors": "1.5.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "node_modules/logform/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "dependencies": { "currently-unhandled": "^0.4.1", "signal-exit": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "dependencies": { "kind-of": "^6.0.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", "dependencies": { "argparse": "^2.0.1", "entities": "~2.1.0", "linkify-it": "^3.0.1", "mdurl": "^1.0.1", "uc.micro": "^1.0.5" }, "bin": { "markdown-it": "bin/markdown-it.js" } }, "node_modules/markdown-it-anchor": { "version": "8.6.5", "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.5.tgz", "integrity": "sha512-PI1qEHHkTNWT+X6Ip9w+paonfIQ+QZP9sCeMYi47oqhH+EsW8CrJ8J7CzV19QVOj6il8ATGbK2nTECj22ZHGvQ==", "peerDependencies": { "@types/markdown-it": "*", "markdown-it": "*" } }, "node_modules/markdown-it/node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdown-it/node_modules/entities": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/marked": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz", "integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==", "bin": { "marked": "bin/marked.js" }, "engines": { "node": ">= 12" } }, "node_modules/maxmin": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", "dev": true, "dependencies": { "chalk": "^1.0.0", "figures": "^1.0.1", "gzip-size": "^1.0.0", "pretty-bytes": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true, "engines": { "node": ">=0.8.0" } }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, "node_modules/mdurl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" }, "node_modules/meow": { "version": "3.7.0", "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "dependencies": { "camelcase-keys": "^2.0.0", "decamelize": "^1.1.2", "loud-rejection": "^1.0.0", "map-obj": "^1.0.1", "minimist": "^1.1.3", "normalize-package-data": "^2.3.4", "object-assign": "^4.0.1", "read-pkg-up": "^1.0.1", "redent": "^1.0.0", "trim-newlines": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/micromatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "dependencies": { "braces": "^3.0.1", "picomatch": "^2.2.3" }, "engines": { "node": ">=8.6" } }, "node_modules/miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "dependencies": { "bn.js": "^4.0.0", "brorand": "^1.0.1" }, "bin": { "miller-rabin": "bin/miller-rabin" } }, "node_modules/mime": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true, "bin": { "mime": "cli.js" }, "engines": { "node": ">=4.0.0" } }, "node_modules/mime-db": { "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.21", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "dev": true, "dependencies": { "mime-db": "~1.37.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", "dev": true }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/minimist": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "node_modules/mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "dependencies": { "minimist": "^1.2.5" }, "bin": { "mkdirp": "bin/cmd.js" } }, "node_modules/module-deps": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", "dev": true, "dependencies": { "browser-resolve": "^1.7.0", "cached-path-relative": "^1.0.0", "concat-stream": "~1.6.0", "defined": "^1.0.0", "detective": "^5.0.2", "duplexer2": "^0.1.2", "inherits": "^2.0.1", "JSONStream": "^1.0.3", "parents": "^1.0.0", "readable-stream": "^2.0.2", "resolve": "^1.4.0", "stream-combiner2": "^1.1.1", "subarg": "^1.0.0", "through2": "^2.0.0", "xtend": "^4.0.0" }, "bin": { "module-deps": "bin/cmd.js" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "node_modules/node-gyp-build": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", "dev": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, "node_modules/nopt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dependencies": { "abbrev": "1", "osenv": "^0.1.4" }, "bin": { "nopt": "bin/nopt.js" } }, "node_modules/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "dependencies": { "hosted-git-info": "^2.1.4", "is-builtin-module": "^1.0.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, "engines": { "node": "*" } }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "dependencies": { "array-each": "^1.0.1", "array-slice": "^1.0.0", "for-own": "^1.0.0", "isobject": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/object.map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "dependencies": { "for-own": "^1.0.0", "make-iterator": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "dependencies": { "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "dependencies": { "wrappy": "1" } }, "node_modules/one-time": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "dev": true, "dependencies": { "fn.name": "1.x.x" } }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, "node_modules/os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "engines": { "node": ">=0.10.0" } }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "engines": { "node": ">=0.10.0" } }, "node_modules/osenv": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dependencies": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } }, "node_modules/p-each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, "dependencies": { "p-reduce": "^1.0.0" }, "engines": { "node": ">=4" } }, "node_modules/p-reduce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true, "engines": { "node": ">=4" } }, "node_modules/pako": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", "dev": true }, "node_modules/parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", "dev": true, "dependencies": { "path-platform": "~0.11.15" } }, "node_modules/parse-asn1": { "version": "5.1.1", "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "dev": true, "dependencies": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3" } }, "node_modules/parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "dependencies": { "is-absolute": "^1.0.0", "map-cache": "^0.2.0", "path-root": "^0.1.1" }, "engines": { "node": ">=0.8" } }, "node_modules/parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "dependencies": { "error-ex": "^1.2.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "node_modules/path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "dependencies": { "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "node_modules/path-platform": { "version": "0.11.15", "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/path-root": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "dependencies": { "path-root-regex": "^0.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/path-root-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/pbkdf2": { "version": "3.0.17", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "dev": true, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", "ripemd160": "^2.0.1", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" }, "engines": { "node": ">=0.12" } }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, "node_modules/phantom": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/phantom/-/phantom-6.3.0.tgz", "integrity": "sha512-Ptlwjp5eJiBmr3KQzFr9V/ehhcC+PGyJB38q7mnxJiwrssOEtmIWDEzQ7gIsdOXlHoW0n0+KjdAdP9U89Cm9Pw==", "deprecated": "This package is no longer maintained", "dev": true, "dependencies": { "phantomjs-prebuilt": "^2.1.16", "split": "^1.0.1", "winston": "^3.2.1" }, "bin": { "phantom": "bin/phantom.js" }, "engines": { "node": ">=8" } }, "node_modules/phantomjs-prebuilt": { "version": "2.1.16", "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", "integrity": "sha512-PIiRzBhW85xco2fuj41FmsyuYHKjKuXWmhjy3A/Y+CMpN/63TV+s9uzfVhsUwFe0G77xWtHBG8xmXf5BqEUEuQ==", "deprecated": "this package is now deprecated", "dev": true, "hasInstallScript": true, "dependencies": { "es6-promise": "^4.0.3", "extract-zip": "^1.6.5", "fs-extra": "^1.0.0", "hasha": "^2.2.0", "kew": "^0.7.0", "progress": "^1.1.8", "request": "^2.81.0", "request-progress": "^2.0.1", "which": "^1.2.10" }, "bin": { "phantomjs": "bin/phantomjs" } }, "node_modules/phantomjs-prebuilt/node_modules/progress": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", "dev": true, "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pify": { "version": "2.3.0", "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "dependencies": { "pinkie": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/pretty-bytes": { "version": "1.0.4", "resolved": "http://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", "dev": true, "dependencies": { "get-stdin": "^4.0.1", "meow": "^3.1.0" }, "bin": { "pretty-bytes": "cli.js" }, "engines": { "node": ">=0.10.0" } }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", "dev": true, "engines": { "node": ">= 0.6.0" } }, "node_modules/process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, "node_modules/public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "dependencies": { "bn.js": "^4.1.0", "browserify-rsa": "^4.0.0", "create-hash": "^1.1.0", "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" } }, "node_modules/punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, "node_modules/puppeteer": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.20.0.tgz", "integrity": "sha512-bt48RDBy2eIwZPrkgbcwHtb51mj2nKvHOPMaSH2IsWiv7lOG9k9zhaRzpDZafrk05ajMc3cu+lSQYYOfH2DkVQ==", "deprecated": "< 19.4.0 is no longer supported", "dev": true, "hasInstallScript": true, "dependencies": { "debug": "^4.1.0", "extract-zip": "^1.6.6", "https-proxy-agent": "^2.2.1", "mime": "^2.0.3", "progress": "^2.0.1", "proxy-from-env": "^1.0.0", "rimraf": "^2.6.1", "ws": "^6.1.0" }, "engines": { "node": ">=6.4.0" } }, "node_modules/puppeteer/node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/puppeteer/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, "node_modules/qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", "dev": true, "engines": { "node": ">=0.6" } }, "node_modules/querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", "dev": true, "engines": { "node": ">=0.4.x" } }, "node_modules/querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true, "engines": { "node": ">=0.4.x" } }, "node_modules/randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "dependencies": { "randombytes": "^2.0.5", "safe-buffer": "^5.1.0" } }, "node_modules/read-only-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", "dev": true, "dependencies": { "readable-stream": "^2.0.2" } }, "node_modules/read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "dependencies": { "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", "path-type": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/read-pkg-up": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "dependencies": { "find-up": "^1.0.0", "read-pkg": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/readable-stream": { "version": "2.3.6", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "node_modules/readable-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, "dependencies": { "resolve": "^1.9.0" }, "engines": { "node": ">= 0.10" } }, "node_modules/redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "dependencies": { "indent-string": "^2.1.0", "strip-indent": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true, "engines": { "node": ">=0.10" } }, "node_modules/repeating": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "dependencies": { "is-finite": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", "dev": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", "caseless": "~0.12.0", "combined-stream": "~1.0.6", "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, "engines": { "node": ">= 6" } }, "node_modules/request-progress": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "dependencies": { "throttleit": "^1.0.0" } }, "node_modules/requizzle": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", "dependencies": { "lodash": "^4.17.14" } }, "node_modules/resolve": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", "dev": true, "dependencies": { "path-parse": "^1.0.6" } }, "node_modules/resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "dependencies": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "dependencies": { "align-text": "^0.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "dependencies": { "glob": "^7.0.5" }, "bin": { "rimraf": "bin.js" } }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" } }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "node_modules/safe-stable-stringify": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, "node_modules/semver": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true, "bin": { "semver": "bin/semver" } }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" }, "bin": { "sha.js": "bin.js" } }, "node_modules/shasum": { "version": "1.0.2", "resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", "dev": true, "dependencies": { "json-stable-stringify": "~0.0.0", "sha.js": "~2.4.4" } }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/shell-quote": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", "dev": true }, "node_modules/signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, "node_modules/simple-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", "dev": true }, "node_modules/simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "dev": true, "dependencies": { "is-arrayish": "^0.3.1" } }, "node_modules/simple-swizzle/node_modules/is-arrayish": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "dev": true }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-exceptions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", "dev": true }, "node_modules/split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "dependencies": { "through": "2" }, "engines": { "node": "*" } }, "node_modules/sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "dev": true }, "node_modules/sshpk": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", "dev": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", "bcrypt-pbkdf": "^1.0.0", "dashdash": "^1.12.0", "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" }, "bin": { "sshpk-conv": "bin/sshpk-conv", "sshpk-sign": "bin/sshpk-sign", "sshpk-verify": "bin/sshpk-verify" }, "engines": { "node": ">=0.10.0" } }, "node_modules/stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", "dev": true, "engines": { "node": "*" } }, "node_modules/stream-browserify": { "version": "2.0.1", "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true, "dependencies": { "inherits": "~2.0.1", "readable-stream": "^2.0.2" } }, "node_modules/stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", "dev": true, "dependencies": { "duplexer2": "~0.1.0", "readable-stream": "^2.0.2" } }, "node_modules/stream-http": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "dependencies": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", "readable-stream": "^2.3.6", "to-arraybuffer": "^1.0.0", "xtend": "^4.0.0" } }, "node_modules/stream-splicer": { "version": "2.0.0", "resolved": "http://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", "dev": true, "dependencies": { "inherits": "^2.0.1", "readable-stream": "^2.0.2" } }, "node_modules/string_decoder": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", "dev": true, "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/strip-ansi": { "version": "3.0.1", "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/strip-bom": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "dependencies": { "is-utf8": "^0.2.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "dependencies": { "get-stdin": "^4.0.1" }, "bin": { "strip-indent": "cli.js" }, "engines": { "node": ">=0.10.0" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", "dev": true, "dependencies": { "minimist": "^1.1.0" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/syntax-error": { "version": "1.4.0", "resolved": "http://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", "dev": true, "dependencies": { "acorn-node": "^1.2.0" } }, "node_modules/taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==" }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", "dev": true }, "node_modules/throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", "dev": true }, "node_modules/through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "dependencies": { "readable-stream": "~2.3.6", "xtend": "~4.0.1" } }, "node_modules/timers-browserify": { "version": "1.4.2", "resolved": "http://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", "dev": true, "dependencies": { "process": "~0.11.0" }, "engines": { "node": ">=0.6.0" } }, "node_modules/to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/tough-cookie": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "dependencies": { "psl": "^1.1.28", "punycode": "^2.1.1" }, "engines": { "node": ">=0.8" } }, "node_modules/tough-cookie/node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", "dev": true }, "node_modules/tty-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "dependencies": { "safe-buffer": "^5.0.1" }, "engines": { "node": "*" } }, "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "node_modules/typescript": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=4.2.0" } }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/uglify-js": { "version": "2.6.4", "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", "dev": true, "dependencies": { "async": "~0.2.6", "source-map": "~0.5.1", "uglify-to-browserify": "~1.0.0", "yargs": "~3.10.0" }, "bin": { "uglifyjs": "bin/uglifyjs" }, "engines": { "node": ">=0.8.0" } }, "node_modules/uglify-js/node_modules/async": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==", "dev": true }, "node_modules/uglify-to-browserify": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true }, "node_modules/umd": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", "dev": true, "bin": { "umd": "bin/cli.js" } }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/undeclared-identifiers": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", "dev": true, "dependencies": { "acorn-node": "^1.3.0", "get-assigned-identifiers": "^1.2.0", "simple-concat": "^1.0.0", "xtend": "^4.0.1" }, "bin": { "undeclared-identifiers": "bin.js" } }, "node_modules/underscore": { "version": "1.13.6", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" }, "node_modules/underscore.string": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", "dev": true, "dependencies": { "sprintf-js": "^1.1.1", "util-deprecate": "^1.0.2" }, "engines": { "node": "*" } }, "node_modules/uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "dependencies": { "punycode": "^2.1.0" } }, "node_modules/uri-js/node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", "dev": true, "engines": { "node": ">=6" } }, "node_modules/uri-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", "dev": true, "engines": { "node": ">= 0.10" } }, "node_modules/url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "dev": true, "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "node_modules/url/node_modules/punycode": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true }, "node_modules/util": { "version": "0.10.4", "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, "dependencies": { "inherits": "2.0.3" } }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, "node_modules/uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", "dev": true, "bin": { "uuid": "bin/uuid" } }, "node_modules/v8flags": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dev": true, "dependencies": { "homedir-polyfill": "^1.0.1" }, "engines": { "node": ">= 0.10" } }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "engines": [ "node >=0.6.0" ], "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "node_modules/vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", "dev": true }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/winston": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/winston/-/winston-3.9.0.tgz", "integrity": "sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ==", "dev": true, "dependencies": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.4.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.5.0" }, "engines": { "node": ">= 12.0.0" } }, "node_modules/winston-transport": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", "dev": true, "dependencies": { "logform": "^2.3.2", "readable-stream": "^3.6.0", "triple-beam": "^1.3.0" }, "engines": { "node": ">= 6.4.0" } }, "node_modules/winston-transport/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/winston/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/winston/node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, "node_modules/ws": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", "dev": true, "dependencies": { "async-limiter": "~1.0.0" } }, "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==" }, "node_modules/xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true, "engines": { "node": ">=0.4" } }, "node_modules/yargs": { "version": "3.10.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "dependencies": { "camelcase": "^1.0.2", "cliui": "^2.1.0", "decamelize": "^1.0.0", "window-size": "0.1.0" } }, "node_modules/yargs/node_modules/camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } } } } thrift-0.19.0/lib/ts/coding_standards.md0000644000000000000000000000010314303740367020124 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/ts/test/0000777000000000000000000000000014370300523015253 5ustar00rootroot00000000000000thrift-0.19.0/lib/ts/test/test-int64.html0000644000000000000000000000372214303740367020074 0ustar00rootroot00000000000000+ Int64 Constants in JS: Unit Test

Int64 Constants in JS: Unit Test

thrift-0.19.0/lib/ts/test/test.ts0000644000000000000000000003322114303740367016611 0ustar00rootroot00000000000000import { ThriftTest } from "./gen-js/ThriftTest_types"; import "./gen-js/ThriftTest"; var Int64 = require("node-int64"); var JSONInt64 = require("json-int64"); var QUnit = require("./qunit"); const transport: Thrift.Transport = new Thrift.Transport("/service"); const protocol: Thrift.Protocol = new Thrift.Protocol(transport); const client: ThriftTest.ThriftTestClient = new ThriftTest.ThriftTestClient(protocol); const int64_2_pow_60: typeof Int64 = new Int64('1000000000000000'); const int64_minus_2_pow_60: typeof Int64 = new Int64('f000000000000000'); // Work around for old API used by QUnitAdapter of jsTestDriver if (typeof QUnit.log == 'function') { // When using real QUnit (fron PhantomJS) log failures to console QUnit.log(function(details) { if (!details.result) { console.log('======== FAIL ========'); console.log('TestName: ' + details.name); if (details.message) console.log(details.message); console.log('Expected: ' + JSONInt64.stringify(details.expected)); console.log('Actual : ' + JSONInt64.stringify(details.actual)); console.log('======================'); } }); } // all Languages in UTF-8 const stringTest: string = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Bahasa Melayu, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; function checkRecursively(assert, map1: Object, map2: Object): void { if (typeof map1 !== 'function' && typeof map2 !== 'function') { if (!map1 || typeof map1 !== 'object') { assert.equal(map1, map2); } else { for (let key in map1) { checkRecursively(assert, map1[key], map2[key]); } } } } QUnit.module('Base Types'); QUnit.test('Void', function(assert) { assert.equal(client.testVoid(), undefined); }); QUnit.test('Binary (String)', function(assert) { let binary: string = ''; for (let v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } assert.equal(client.testBinary(binary), binary); }); QUnit.test('Binary (Uint8Array)', function(assert) { let binary: string = ''; for (let v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } const arr: Uint8Array = new Uint8Array(binary.length); for (let i = 0; i < binary.length; ++i) { arr[i] = binary[i].charCodeAt(0); } const hexEncodedString = Array.from(arr, function(byte) { return String.fromCharCode(byte); }).join('') assert.equal(client.testBinary(hexEncodedString), binary); }); QUnit.test('String', function(assert) { assert.equal(client.testString(''), ''); assert.equal(client.testString(stringTest), stringTest); const specialCharacters: string = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; assert.equal(client.testString(specialCharacters), specialCharacters); }); QUnit.test('Double', function(assert) { assert.equal(client.testDouble(0), 0); assert.equal(client.testDouble(-1), -1); assert.equal(client.testDouble(3.14), 3.14); assert.equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60)); }); QUnit.test('Byte', function(assert) { assert.equal(client.testByte(0), 0); assert.equal(client.testByte(0x01), 0x01); }); QUnit.test('I32', function(assert) { assert.equal(client.testI32(0), 0); assert.equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30)); assert.equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30)); }); QUnit.test('I64', function(assert) { assert.equal(client.testI64(new Int64(0)), 0); let int64_2_pow_60_result: typeof Int64 = client.testI64(int64_2_pow_60); assert.ok(int64_2_pow_60.equals(int64_2_pow_60_result)); let int64_minus_2_pow_60_result: typeof Int64 = client.testI64(int64_minus_2_pow_60); assert.ok(int64_minus_2_pow_60.equals(int64_minus_2_pow_60_result)); }); QUnit.module('Structured Types'); QUnit.test('Struct', function(assert) { const structTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); structTestInput.i64_thing = int64_2_pow_60; const structTestOutput: ThriftTest.Xtruct = client.testStruct(structTestInput); assert.equal(structTestOutput.string_thing, structTestInput.string_thing); assert.equal(structTestOutput.byte_thing, structTestInput.byte_thing); assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing); assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing)); assert.ok(structTestInput.i64_thing.equals(structTestOutput.i64_thing)); assert.equal(JSONInt64.stringify(structTestOutput), JSONInt64.stringify(structTestInput)); }); QUnit.test('Nest', function(assert) { const xtrTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); xtrTestInput.i64_thing = int64_2_pow_60; const nestTestInput: ThriftTest.Xtruct2 = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; nestTestInput.struct_thing = xtrTestInput; nestTestInput.i32_thing = Math.pow(2, 15); const nestTestOutput: ThriftTest.Xtruct2 = client.testNest(nestTestInput); assert.equal(nestTestOutput.byte_thing, nestTestInput.byte_thing); assert.equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); assert.equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); assert.equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); assert.ok(nestTestOutput.struct_thing.i64_thing.equals(nestTestInput.struct_thing.i64_thing)); assert.equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); assert.equal(JSONInt64.stringify(nestTestOutput), JSONInt64.stringify(nestTestInput)); }); QUnit.test('Map', function(assert) { const mapTestInput: {[k: number]: number;} = {7: 77, 8: 88, 9: 99}; const mapTestOutput: {[k: number]: number;} = client.testMap(mapTestInput); for (let key in mapTestOutput) { assert.equal(mapTestOutput[key], mapTestInput[key]); } }); QUnit.test('StringMap', function(assert) { const mapTestInput: {[k: string]: string;} = { 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', 'longValue': stringTest, stringTest: 'long key' }; const mapTestOutput: {[k: string]: string;} = client.testStringMap(mapTestInput); for (let key in mapTestOutput) { assert.equal(mapTestOutput[key], mapTestInput[key]); } }); QUnit.test('Set', function(assert) { const setTestInput: number[] = [1, 2, 3]; assert.ok(client.testSet(setTestInput), setTestInput); }); QUnit.test('List', function(assert) { const listTestInput: number[] = [1, 2, 3]; assert.ok(client.testList(listTestInput), listTestInput); }); QUnit.test('Enum', function(assert) { assert.equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE); }); QUnit.test('TypeDef', function(assert) { assert.equal(client.testTypedef(new Int64(69)), 69); }); QUnit.module('deeper!'); QUnit.test('MapMap', function(assert) { const mapMapTestExpectedResult: {[K: number]: {[k: number]: number}} = { '4': {'1': 1, '2': 2, '3': 3, '4': 4}, '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} }; const mapMapTestOutput = client.testMapMap(1); for (let key in mapMapTestOutput) { for (let key2 in mapMapTestOutput[key]) { assert.equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]); } } checkRecursively(assert, mapMapTestOutput, mapMapTestExpectedResult); }); QUnit.module('Exception'); QUnit.test('Xception', function(assert) { assert.expect(2); const done = assert.async(); try { client.testException('Xception'); assert.ok(false); }catch (e) { assert.equal(e.errorCode, 1001); assert.equal(e.message, 'Xception'); done(); } }); QUnit.test('no Exception', function(assert) { assert.expect(1); try { client.testException('no Exception'); assert.ok(true); }catch (e) { assert.ok(false); } }); QUnit.test('TException', function(assert) { //ThriftTest does not list TException as a legal exception so it will // generate an exception on the server that does not propagate back to // the client. This test has been modified to equate to "no exception" assert.expect(1); try { client.testException('TException'); } catch (e) { //assert.ok(false); } assert.ok(true); }); QUnit.module('Insanity'); const crazy: ThriftTest.Insanity = { 'userMap': { '5': new Int64(5), '8': new Int64(8) }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': new Int64(4) }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': new Int64(2) }] }; QUnit.test('testInsanity', function(assert) { const insanity: {[k: number]: (ThriftTest.Insanity | {[k:number]: ThriftTest.Insanity})} = { '1': { '2': crazy, '3': crazy }, '2': { '6': new ThriftTest.Insanity() } }; const res = client.testInsanity(new ThriftTest.Insanity(crazy)); assert.ok(res, JSONInt64.stringify(res)); assert.ok(insanity, JSONInt64.stringify(insanity)); checkRecursively(assert, res, insanity); }); ////////////////////////////////// //Run same tests asynchronously QUnit.module('Async'); QUnit.test('Double', function(assert) { assert.expect(1); const done = assert.async(); client.testDouble(3.14159265, function(result) { assert.equal(result, 3.14159265); done(); }); }); QUnit.test('Byte', function(assert) { assert.expect(1); const done = assert.async(); client.testByte(0x01, function(result) { assert.equal(result, 0x01); done(); }); }); QUnit.test('I32', function(assert) { assert.expect(2); const done = assert.async(2); client.testI32(Math.pow(2, 30), function(result) { assert.equal(result, Math.pow(2, 30)); done(); }); client.testI32(Math.pow(-2, 31), function(result) { assert.equal(result, Math.pow(-2, 31)); done(); }); }); QUnit.test('I64', function(assert) { assert.expect(2); const done = assert.async(2); client.testI64(int64_2_pow_60, function(result) { assert.ok(int64_2_pow_60.equals(result)); done(); }); client.testI64(int64_minus_2_pow_60, function(result) { assert.ok(int64_minus_2_pow_60.equals(result)); done(); }); }); thrift-0.19.0/lib/ts/test/test.html0000644000000000000000000000513714303740367017134 0ustar00rootroot00000000000000 Thrift Javascript Bindings: Unit Test

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

thrift-0.19.0/lib/ts/test/test-int64.ts0000644000000000000000000000760114303740367017556 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ var Int64 = require("node-int64"); var JSONInt64 = require("json-int64"); import { Int64Test } from "./gen-js/Int64Test_types"; // Work around for old API used by QUnitAdapter of jsTestDriver if (typeof QUnit.log == 'function') { // When using real QUnit (fron PhantomJS) log failures to console QUnit.log(function(details) { if (!details.result) { console.log('======== FAIL ========'); console.log('TestName: ' + details.name); if (details.message) console.log(details.message); console.log('Expected: ' + details.expected); console.log('Actual : ' + details.actual); console.log('======================'); } }); } QUnit.module('Int64'); QUnit.test('Int64', function(assert) { console.log('Int64 test -- starts'); const EXPECTED_SMALL_INT64_AS_NUMBER: number = 42; const EXPECTED_SMALL_INT64: typeof Int64 = new Int64(42); const EXPECTED_MAX_JS_SAFE_INT64: typeof Int64 = new Int64(Number.MAX_SAFE_INTEGER); const EXPECTED_MIN_JS_SAFE_INT64: typeof Int64 = new Int64(Number.MIN_SAFE_INTEGER); const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64: typeof Int64 = new Int64("0020000000000000"); // hex-encoded const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64: typeof Int64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement const EXPECTED_MAX_SIGNED_INT64: typeof Int64 = new Int64("7fffffffffffffff"); // hex-encoded const EXPECTED_MIN_SIGNED_INT64: typeof Int64 = new Int64("8000000000000000"); // hex-encoded 2's complement const EXPECTED_INT64_LIST = [ EXPECTED_SMALL_INT64, EXPECTED_MAX_JS_SAFE_INT64, EXPECTED_MIN_JS_SAFE_INT64, EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, EXPECTED_MAX_SIGNED_INT64, EXPECTED_MIN_SIGNED_INT64 ]; assert.ok(EXPECTED_SMALL_INT64.equals(Int64Test.SMALL_INT64)); assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(Int64Test.MAX_JS_SAFE_INT64)); assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(Int64Test.MIN_JS_SAFE_INT64)); assert.ok( EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( Int64Test.MAX_JS_SAFE_PLUS_ONE_INT64 ) ); assert.ok( EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( Int64Test.MIN_JS_SAFE_MINUS_ONE_INT64 ) ); assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(Int64Test.MAX_SIGNED_INT64)); assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(Int64Test.MIN_SIGNED_INT64)); assert.equal( EXPECTED_SMALL_INT64_AS_NUMBER, Int64Test.SMALL_INT64.toNumber() ); assert.equal( Number.MAX_SAFE_INTEGER, Int64Test.MAX_JS_SAFE_INT64.toNumber() ); assert.equal( Number.MIN_SAFE_INTEGER, Int64Test.MIN_JS_SAFE_INT64.toNumber() ); for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(Int64Test.INT64_LIST[i])); } for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i){ let int64Object = EXPECTED_INT64_LIST[i]; assert.ok(Int64Test.INT64_2_INT64_MAP[JSONInt64.toDecimalString(int64Object)].equals(int64Object)); } console.log('Int64 test -- ends'); }); thrift-0.19.0/lib/ts/test/test_handler.js0000644000000000000000000001332214303740367020274 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //This is the server side Node test handler for the standard // Apache Thrift test service. const es6Mode = process.argv.includes('--es6'); const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; const ttypes = require(`./${genFolder}/ThriftTest_types`); const TException = require('../../nodejs/lib/thrift').TException; const Int64 = require('node-int64'); exports.ThriftTestHandler = { testVoid: function(result) { console.log('testVoid()'); result(null); }, testString: function(thing, result) { console.log('testString(\'' + thing + '\')'); result(null, thing); }, testByte: function(thing, result) { console.log('testByte(' + thing + ')'); result(null, thing); }, testI32: function(thing, result) { console.log('testI32(' + thing + ')'); result(null, thing); }, testI64: function(thing, result) { console.log('testI64(' + thing + ')'); result(null, thing); }, testDouble: function(thing, result) { console.log('testDouble(' + thing + ')'); result(null, thing); }, testBinary: function(thing, result) { console.log('testBinary(\'' + thing + '\')'); result(null, thing); }, testStruct: function(thing, result) { console.log('testStruct('); console.log(thing); console.log(')'); result(null, thing); }, testNest: function(nest, result) { console.log('testNest('); console.log(nest); console.log(')'); result(null, nest); }, testMap: function(thing, result) { console.log('testMap('); console.log(thing); console.log(')'); result(null, thing); }, testStringMap: function(thing, result) { console.log('testStringMap('); console.log(thing); console.log(')'); result(null, thing); }, testSet: function(thing, result) { console.log('testSet('); console.log(thing); console.log(')'); result(null, thing); }, testList: function(thing, result) { console.log('testList('); console.log(thing); console.log(')'); result(null, thing); }, testEnum: function(thing, result) { console.log('testEnum(' + thing + ')'); result(null, thing); }, testTypedef: function(thing, result) { console.log('testTypedef(' + thing + ')'); result(null, thing); }, testMapMap: function(hello, result) { console.log('testMapMap(' + hello + ')'); const mapmap = []; const pos = []; const neg = []; for (let i = 1; i < 5; i++) { pos[i] = i; neg[-i] = -i; } mapmap[4] = pos; mapmap[-4] = neg; result(null, mapmap); }, testInsanity: function(argument, result) { console.log('testInsanity('); console.log(argument); console.log(')'); const hello = new ttypes.Xtruct(); hello.string_thing = 'Hello2'; hello.byte_thing = 2; hello.i32_thing = 2; hello.i64_thing = new Int64(2); const goodbye = new ttypes.Xtruct(); goodbye.string_thing = 'Goodbye4'; goodbye.byte_thing = 4; goodbye.i32_thing = 4; goodbye.i64_thing = new Int64(4); const crazy = new ttypes.Insanity(); crazy.userMap = []; crazy.userMap[ttypes.Numberz.EIGHT] = 8; crazy.userMap[ttypes.Numberz.FIVE] = 5; crazy.xtructs = [goodbye, hello]; const first_map = []; const second_map = []; first_map[ttypes.Numberz.TWO] = crazy; first_map[ttypes.Numberz.THREE] = crazy; const looney = new ttypes.Insanity(); second_map[ttypes.Numberz.SIX] = looney; const insane = []; insane[1] = first_map; insane[2] = second_map; console.log('insane result:'); console.log(insane); result(null, insane); }, testMulti: function(arg0, arg1, arg2, arg3, arg4, arg5, result) { console.log('testMulti()'); const hello = new ttypes.Xtruct(); hello.string_thing = 'Hello2'; hello.byte_thing = arg0; hello.i32_thing = arg1; hello.i64_thing = arg2; result(null, hello); }, testException: function(arg, result) { console.log('testException(' + arg + ')'); if (arg === 'Xception') { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = arg; result(x); } else if (arg === 'TException') { result(new TException(arg)); } else { result(null); } }, testMultiException: function(arg0, arg1, result) { console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); if (arg0 === ('Xception')) { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = 'This is an Xception'; result(x); } else if (arg0 === ('Xception2')) { const x2 = new ttypes.Xception2(); x2.errorCode = 2002; x2.struct_thing = new ttypes.Xtruct(); x2.struct_thing.string_thing = 'This is an Xception2'; result(x2); } const res = new ttypes.Xtruct(); res.string_thing = arg1; result(null, res); }, testOneway: function(sleepFor, result) { console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!'); } }; //ThriftTestSvcHandler thrift-0.19.0/lib/ts/test/server_http.js0000644000000000000000000000412414303740367020165 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This HTTP server is designed to serve the test.html browser // based JavaScript test page (which must be in the current directory). // This server also supplies the Thrift based test service, which depends // on the standard ThriftTest.thrift IDL service (which must be compiled // for Node and browser based JavaScript in ./gen-nodejs and ./gen-js // respectively). // // Using the command flag --es6, this server can be run using nodejs code built // for the es6 environment or for pre-es6 environment. // const thrift = require('../../nodejs/lib/thrift'); const es6Mode = process.argv.includes('--es6'); const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; const ThriftTestSvc = require(`./${genFolder}/ThriftTest.js`); const ThriftTestHandler = require('./test_handler').ThriftTestHandler; const ThriftTestSvcOpt = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, processor: ThriftTestSvc, handler: ThriftTestHandler }; const ThriftWebServerOptions = { files: __dirname, services: { '/service': ThriftTestSvcOpt } }; const server = thrift.createWebServer(ThriftWebServerOptions); const port = es6Mode ? 8088 : 8089; server.listen(port); console.log(`Serving files from: ${__dirname}`); console.log(`Http/Thrift Server (ES6 mode ${es6Mode}) running on port: ${port}`); thrift-0.19.0/lib/ts/test/phantom-client.ts0000644000000000000000000003313414303740367020557 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* jshint -W100 */ import { ThriftTest } from "./gen-js/ThriftTest_types"; import "./gen-js/ThriftTest"; var Int64 = require("node-int64"); var phantom = require("phantom"); const int64_2_pow_60: typeof Int64 = new Int64('1000000000000000'); const int64_minus_2_pow_60: typeof Int64 = new Int64('f000000000000000'); (function() { 'use strict'; // Rudimentary test helper functions // TODO: Return error code based on kind of errors rather than throw var ok = function(t, msg) { if (!t) { console.log('*** FAILED ***'); throw new Error(msg); } }; var equal = function(a, b) { if (a !== b) { console.log('*** FAILED ***'); throw new Error(); } }; var test = function(name, f) { console.log('TEST : ' + name); f(); console.log('OK\n'); }; var parseArgs = function(args) { var skips = [ '--transport=http', '--protocol=json' ]; var opts = { port: '9090' // protocol: 'json', }; var keys = {}; for (var key in opts) { keys['--' + key + '='] = key; } for (var i in args) { var arg = args[i]; if (skips.indexOf(arg) != -1) { continue; } var hit = false; for (var k in keys) { if (arg.slice(0, k.length) === k) { opts[keys[k]] = arg.slice(k.length); hit = true; break; } } if (!hit) { throw new Error('Unknown argument: ' + arg); } } var portAsInt: number = parseInt(opts.port, 10); if (!opts.port || portAsInt < 1 || portAsInt > 65535) { throw new Error('Invalid port number'); } return opts; }; var execute = function() { console.log('### Apache Thrift Javascript standalone test client'); console.log('------------------------------------------------------------'); phantom.page.injectJs('thrift.js'); phantom.page.injectJs('gen-js/ThriftTest_types.js'); phantom.page.injectJs('gen-js/ThriftTest.js'); var system = require('system'); var opts = parseArgs(system.args.slice(1)); var port = opts.port; var transport = new Thrift.Transport('http://localhost:' + port + '/service'); var protocol = new Thrift.Protocol(transport); var client = new ThriftTest.ThriftTestClient(protocol); // TODO: Remove duplicate code with test.js. // all Languages in UTF-8 var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Bahasa Melayu, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; function checkRecursively(map1, map2) { if (typeof map1 !== 'function' && typeof map2 !== 'function') { if (!map1 || typeof map1 !== 'object') { equal(map1, map2); } else { for (var key in map1) { checkRecursively(map1[key], map2[key]); } } } } test('Void', function() { equal(client.testVoid(), undefined); }); test('Binary (String)', function() { var binary: string = ''; for (var v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } equal(client.testBinary(binary), binary); }); test('Binary (Uint8Array)', function() { var binary: string = ''; for (var v = 255; v >= 0; --v) { binary += String.fromCharCode(v); } var arr = new Uint8Array(binary.length); for (var i = 0; i < binary.length; ++i) { arr[i] = binary[i].charCodeAt(0); } const hexEncodedString = Array.from(arr, function(byte) { return String.fromCharCode(byte); }).join('') equal(client.testBinary(hexEncodedString), binary); }); test('String', function() { equal(client.testString(''), ''); equal(client.testString(stringTest), stringTest); var specialCharacters = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; equal(client.testString(specialCharacters), specialCharacters); }); test('Double', function() { equal(client.testDouble(0), 0); equal(client.testDouble(-1), -1); equal(client.testDouble(3.14), 3.14); equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60)); }); test('Bool', function() { equal(client.testBool(true), true); equal(client.testBool(false), false); }); test('I8', function() { equal(client.testByte(0), 0); equal(client.testByte(0x01), 0x01); }); test('I32', function() { equal(client.testI32(0), 0); equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30)); equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30)); }); test('I64', function() { equal(client.testI64(new Int64(0)), 0); equal(client.testI64(int64_2_pow_60), Math.pow(2, 52)); equal(client.testI64(int64_minus_2_pow_60), -Math.pow(2, 52)); }); test('Struct', function() { var structTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); structTestInput.i64_thing = int64_2_pow_60; var structTestOutput: ThriftTest.Xtruct = client.testStruct(structTestInput); equal(structTestOutput.string_thing, structTestInput.string_thing); equal(structTestOutput.byte_thing, structTestInput.byte_thing); equal(structTestOutput.i32_thing, structTestInput.i32_thing); equal(structTestOutput.i64_thing, structTestInput.i64_thing); equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput)); }); test('Nest', function() { var xtrTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); xtrTestInput.i64_thing = int64_2_pow_60; var nestTestInput: ThriftTest.Xtruct2 = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; nestTestInput.struct_thing = xtrTestInput; nestTestInput.i32_thing = Math.pow(2, 15); var nestTestOutput = client.testNest(nestTestInput); equal(nestTestOutput.byte_thing, nestTestInput.byte_thing); equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); equal(nestTestOutput.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing); equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput)); }); test('Map', function() { var mapTestInput: {[k: number]: number;} = {7: 77, 8: 88, 9: 99}; var mapTestOutput: {[k: number]: number;} = client.testMap(mapTestInput); for (var key in mapTestOutput) { equal(mapTestOutput[key], mapTestInput[key]); } }); test('StringMap', function() { var mapTestInput: {[k: string]: string;} = { 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', 'longValue': stringTest, stringTest: 'long key' }; var mapTestOutput: {[k: string]: string;} = client.testStringMap(mapTestInput); for (var key in mapTestOutput) { equal(mapTestOutput[key], mapTestInput[key]); } }); test('Set', function() { var setTestInput: number[] = [1, 2, 3]; ok(client.testSet(setTestInput), setTestInput); }); test('List', function() { var listTestInput: number[] = [1, 2, 3]; ok(client.testList(listTestInput), listTestInput); }); test('Enum', function() { equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE); }); test('TypeDef', function() { equal(client.testTypedef(new Int64(69)), 69); }); test('MapMap', function() { var mapMapTestExpectedResult: {[K: number]: {[k: number]: number}} = { '4': {'1': 1, '2': 2, '3': 3, '4': 4}, '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} }; var mapMapTestOutput = client.testMapMap(1); for (var key in mapMapTestOutput) { for (var key2 in mapMapTestOutput[key]) { equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]); } } checkRecursively(mapMapTestOutput, mapMapTestExpectedResult); }); test('Xception', function() { try { client.testException('Xception'); ok(false, "expected an exception but there was no exception"); } catch (e) { equal(e.errorCode, 1001); equal(e.message, 'Xception'); } }); test('no Exception', function() { try { client.testException('no Exception'); } catch (e) { ok(false, "expected no exception but here was an exception"); } }); test('TException', function() { try { client.testException('TException'); ok(false, "expected an exception but there was no exception"); } catch (e) { ok(ok, "succesfully got exception"); } }); const crazy: ThriftTest.Insanity = { 'userMap': { '5': new Int64(5), '8': new Int64(8) }, 'xtructs': [{ 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, 'i64_thing': new Int64(4) }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, 'i64_thing': new Int64(2) }] }; test('Insanity', function() { const insanity: {[k: number]: (ThriftTest.Insanity | {[k:number]: ThriftTest.Insanity})} = { '1': { '2': crazy, '3': crazy }, '2': { '6': new ThriftTest.Insanity() } }; var res = client.testInsanity(new ThriftTest.Insanity(crazy)); ok(res, JSON.stringify(res)); ok(insanity, JSON.stringify(insanity)); checkRecursively(res, insanity); }); console.log('------------------------------------------------------------'); console.log('### All tests succeeded.'); return 0; }; try { var ret = execute(); phantom.exit(ret); } catch (err) { // Catch all and exit to avoid hang. console.error(err); phantom.exit(1); } })(); thrift-0.19.0/lib/ts/test/build.xml0000644000000000000000000002342414370300523017075 0ustar00rootroot00000000000000 Java Script Test based on Thrift Java Library You need libthrift*.jar and libthrift*test.jar located at ${thrift.java.dir}/build/libs Did you compile Thrift Java library and its test suite by "ant compile-test"? Thrift compiler is missing ! check if Xvfb is available: check if phantomjs is available: Running Unit Tests with headless browser! check if gjslint is available: thrift-0.19.0/lib/ts/thrift.d.ts0000644000000000000000000005542214303740367016404 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ declare module Thrift { /** * Thrift JavaScript library version. */ var Version: string; /** * Thrift IDL type string to Id mapping. * @property {number} STOP - End of a set of fields. * @property {number} VOID - No value (only legal for return types). * @property {number} BOOL - True/False integer. * @property {number} BYTE - Signed 8 bit integer. * @property {number} I08 - Signed 8 bit integer. * @property {number} DOUBLE - 64 bit IEEE 854 floating point. * @property {number} I16 - Signed 16 bit integer. * @property {number} I32 - Signed 32 bit integer. * @property {number} I64 - Signed 64 bit integer. * @property {number} STRING - Array of bytes representing a string of characters. * @property {number} UTF7 - Array of bytes representing a string of UTF7 encoded characters. * @property {number} STRUCT - A multifield type. * @property {number} MAP - A collection type (map/associative-array/dictionary). * @property {number} SET - A collection type (unordered and without repeated values). * @property {number} LIST - A collection type (unordered). * @property {number} UTF8 - Array of bytes representing a string of UTF8 encoded characters. * @property {number} UTF16 - Array of bytes representing a string of UTF16 encoded characters. */ interface Type { 'STOP': number; 'VOID': number; 'BOOL': number; 'BYTE': number; 'I08': number; 'DOUBLE': number; 'I16': number; 'I32': number; 'I64': number; 'STRING': number; 'UTF7': number; 'STRUCT': number; 'MAP': number; 'SET': number; 'LIST': number; 'UTF8': number; 'UTF16': number; } var Type: Type; /** * Thrift RPC message type string to Id mapping. * @property {number} CALL - RPC call sent from client to server. * @property {number} REPLY - RPC call normal response from server to client. * @property {number} EXCEPTION - RPC call exception response from server to client. * @property {number} ONEWAY - Oneway RPC call from client to server with no response. */ interface MessageType { 'CALL': number; 'REPLY': number; 'EXCEPTION': number; 'ONEWAY': number; } var MessageType: MessageType; /** * Utility function returning the count of an object's own properties. * @param {object} obj - Object to test. * @returns {number} number of object's own properties */ function objectLength(obj: Object): number; /** * Utility function to establish prototype inheritance. * @param {function} constructor - Contstructor function to set as derived. * @param {function} superConstructor - Contstructor function to set as base. * @param {string} [name] - Type name to set as name property in derived prototype. */ function inherits(constructor: Function, superConstructor: Function, name?: string): void; /** * TException is the base class for all Thrift exceptions types. */ class TException implements Error { name: string; message: string; /** * Initializes a Thrift TException instance. * @param {string} message - The TException message (distinct from the Error message). */ constructor(message: string); /** * Returns the message set on the exception. * @returns {string} exception message */ getMessage(): string; } /** * Thrift Application Exception type string to Id mapping. * @property {number} UNKNOWN - Unknown/undefined. * @property {number} UNKNOWN_METHOD - Client attempted to call a method unknown to the server. * @property {number} INVALID_MESSAGE_TYPE - Client passed an unknown/unsupported MessageType. * @property {number} WRONG_METHOD_NAME - Unused. * @property {number} BAD_SEQUENCE_ID - Unused in Thrift RPC, used to flag proprietary sequence number errors. * @property {number} MISSING_RESULT - Raised by a server processor if a handler fails to supply the required return result. * @property {number} INTERNAL_ERROR - Something bad happened. * @property {number} PROTOCOL_ERROR - The protocol layer failed to serialize or deserialize data. * @property {number} INVALID_TRANSFORM - Unused. * @property {number} INVALID_PROTOCOL - The protocol (or version) is not supported. * @property {number} UNSUPPORTED_CLIENT_TYPE - Unused. */ interface TApplicationExceptionType { 'UNKNOWN': number; 'UNKNOWN_METHOD': number; 'INVALID_MESSAGE_TYPE': number; 'WRONG_METHOD_NAME': number; 'BAD_SEQUENCE_ID': number; 'MISSING_RESULT': number; 'INTERNAL_ERROR': number; 'PROTOCOL_ERROR': number; 'INVALID_TRANSFORM': number; 'INVALID_PROTOCOL': number; 'UNSUPPORTED_CLIENT_TYPE': number; } var TApplicationExceptionType: TApplicationExceptionType; /** * TApplicationException is the exception class used to propagate exceptions from an RPC server back to a calling client. */ class TApplicationException extends TException { message: string; code: number; /** * Initializes a Thrift TApplicationException instance. * @param {string} message - The TApplicationException message (distinct from the Error message). * @param {Thrift.TApplicationExceptionType} [code] - The TApplicationExceptionType code. */ constructor(message: string, code?: number); /** * Read a TApplicationException from the supplied protocol. * @param {object} input - The input protocol to read from. */ read(input: Object): void; /** * Write a TApplicationException to the supplied protocol. * @param {object} output - The output protocol to write to. */ write(output: Object): void; /** * Returns the application exception code set on the exception. * @returns {Thrift.TApplicationExceptionType} exception code */ getCode(): number; } /** * The Apache Thrift Transport layer performs byte level I/O between RPC * clients and servers. The JavaScript Transport object type uses Http[s]/XHR and is * the sole browser based Thrift transport. Target servers must implement the http[s] * transport (see: node.js example server). */ class TXHRTransport { url: string; wpos: number; rpos: number; useCORS: any; send_buf: string; recv_buf: string; /** * If you do not specify a url then you must handle XHR operations on * your own. This type can also be constructed using the Transport alias * for backward compatibility. * @param {string} [url] - The URL to connect to. * @param {object} [options] - Options. */ constructor(url?: string, options?: Object); /** * Gets the browser specific XmlHttpRequest Object. * @returns {object} the browser XHR interface object */ getXmlHttpRequestObject(): Object; /** * Sends the current XRH request if the transport was created with a URL and * the async parameter if false. If the transport was not created with a URL * or the async parameter is True or the URL is an empty string, the current * send buffer is returned. * @param {object} async - If true the current send buffer is returned. * @param {function} callback - Optional async completion callback. * @returns {undefined|string} Nothing or the current send buffer. */ flush(async: any, callback?: Function): string; /** * Creates a jQuery XHR object to be used for a Thrift server call. * @param {object} client - The Thrift Service client object generated by the IDL compiler. * @param {object} postData - The message to send to the server. * @param {function} args - The function to call if the request succeeds. * @param {function} recv_method - The Thrift Service Client receive method for the call. * @returns {object} A new jQuery XHR object. */ jqRequest(client: Object, postData: any, args: Function, recv_method: Function): Object; /** * Sets the buffer to use when receiving server responses. * @param {string} buf - The buffer to receive server responses. */ setRecvBuffer(buf: string): void; /** * Returns true if the transport is open, in browser based JavaScript * this function always returns true. * @returns {boolean} Always True. */ isOpen(): boolean; /** * Opens the transport connection, in browser based JavaScript * this function is a nop. */ open(): void; /** * Closes the transport connection, in browser based JavaScript * this function is a nop. */ close(): void; /** * Returns the specified number of characters from the response * buffer. * @param {number} len - The number of characters to return. * @returns {string} Characters sent by the server. */ read(len: number): string; /** * Returns the entire response buffer. * @returns {string} Characters sent by the server. */ readAll(): string; /** * Sets the send buffer to buf. * @param {string} buf - The buffer to send. */ write(buf: string): void; /** * Returns the send buffer. * @returns {string} The send buffer. */ getSendBuffer(): string; } /** * Old alias of the TXHRTransport for backwards compatibility. */ class Transport extends TXHRTransport { } /** * The Apache Thrift Transport layer performs byte level I/O * between RPC clients and servers. The JavaScript TWebSocketTransport object * uses the WebSocket protocol. Target servers must implement WebSocket. */ class TWebSocketTransport { url: string; //Where to connect socket: any; //The web socket callbacks: Function[]; //Pending callbacks send_pending: any[]; //Buffers/Callback pairs waiting to be sent send_buf: string; //Outbound data, immutable until sent recv_buf: string; //Inbound data rb_wpos: number; //Network write position in receive buffer rb_rpos: number; //Client read position in receive buffer /** * Constructor Function for the WebSocket transport. * @param {string } [url] - The URL to connect to. */ constructor(url: string); __reset(url: string): void; /** * Sends the current WS request and registers callback. The async * parameter is ignored (WS flush is always async) and the callback * function parameter is required. * @param {object} async - Ignored. * @param {function} callback - The client completion callback. * @returns {undefined|string} Nothing (undefined) */ flush(async: any, callback: Function): string; __onOpen(): void; __onClose(): void; __onMessage(): void; __onError(): void; /** * Sets the buffer to use when receiving server responses. * @param {string} buf - The buffer to receive server responses. */ setRecvBuffer(buf: string): void; /** * Returns true if the transport is open * @returns {boolean} */ isOpen(): boolean; /** * Opens the transport connection */ open(): void; /** * Closes the transport connection */ close(): void; /** * Returns the specified number of characters from the response * buffer. * @param {number} len - The number of characters to return. * @returns {string} Characters sent by the server. */ read(len: number): string; /** * Returns the entire response buffer. * @returns {string} Characters sent by the server. */ readAll(): string; /** * Sets the send buffer to buf. * @param {string} buf - The buffer to send. */ write(buf: string): void; /** * Returns the send buffer. * @returns {string} The send buffer. */ getSendBuffer(): string; } /** * Apache Thrift Protocols perform serialization which enables cross * language RPC. The Protocol type is the JavaScript browser implementation * of the Apache Thrift TJSONProtocol. */ class TJSONProtocol { transport: Object; /** * Thrift IDL type Id to string mapping. * The mapping table looks as follows: * Thrift.Type.BOOL -> "tf": True/False integer. * Thrift.Type.BYTE -> "i8": Signed 8 bit integer. * Thrift.Type.I16 -> "i16": Signed 16 bit integer. * Thrift.Type.I32 -> "i32": Signed 32 bit integer. * Thrift.Type.I64 -> "i64": Signed 64 bit integer. * Thrift.Type.DOUBLE -> "dbl": 64 bit IEEE 854 floating point. * Thrift.Type.STRUCT -> "rec": A multifield type. * Thrift.Type.STRING -> "str": Array of bytes representing a string of characters. * Thrift.Type.MAP -> "map": A collection type (map/associative-array/dictionary). * Thrift.Type.LIST -> "lst": A collection type (unordered). * Thrift.Type.SET -> "set": A collection type (unordered and without repeated values). */ Type: { [k: number]: string }; /** * Thrift IDL type string to Id mapping. * The mapping table looks as follows: * "tf" -> Thrift.Type.BOOL * "i8" -> Thrift.Type.BYTE * "i16" -> Thrift.Type.I16 * "i32" -> Thrift.Type.I32 * "i64" -> Thrift.Type.I64 * "dbl" -> Thrift.Type.DOUBLE * "rec" -> Thrift.Type.STRUCT * "str" -> Thrift.Type.STRING * "map" -> Thrift.Type.MAP * "lst" -> Thrift.Type.LIST * "set" -> Thrift.Type.SET */ RType: { [k: string]: number }; /** * The TJSONProtocol version number. */ Version: number; /** * Initializes a Thrift JSON protocol instance. * @param {Thrift.Transport} transport - The transport to serialize to/from. */ constructor(transport: Object); /** * Returns the underlying transport. * @returns {Thrift.Transport} The underlying transport. */ getTransport(): Object; /** * Serializes the beginning of a Thrift RPC message. * @param {string} name - The service method to call. * @param {Thrift.MessageType} messageType - The type of method call. * @param {number} seqid - The sequence number of this call (always 0 in Apache Thrift). */ writeMessageBegin(name: string, messageType: number, seqid: number): void; /** * Serializes the end of a Thrift RPC message. */ writeMessageEnd(): void; /** * Serializes the beginning of a struct. * @param {string} name - The name of the struct. */ writeStructBegin(name?: string): void; /** * Serializes the end of a struct. */ writeStructEnd(): void; /** * Serializes the beginning of a struct field. * @param {string} name - The name of the field. * @param {Thrift.Protocol.Type} fieldType - The data type of the field. * @param {number} fieldId - The field's unique identifier. */ writeFieldBegin(name: string, fieldType: number, fieldId: number): void; /** * Serializes the end of a field. */ writeFieldEnd(): void; /** * Serializes the end of the set of fields for a struct. */ writeFieldStop(): void; /** * Serializes the beginning of a map collection. * @param {Thrift.Type} keyType - The data type of the key. * @param {Thrift.Type} valType - The data type of the value. * @param {number} [size] - The number of elements in the map (ignored). */ writeMapBegin(keyType: number, valType: number, size?: number): void; /** * Serializes the end of a map. */ writeMapEnd(): void; /** * Serializes the beginning of a list collection. * @param {Thrift.Type} elemType - The data type of the elements. * @param {number} size - The number of elements in the list. */ writeListBegin(elemType: number, size: number): void; /** * Serializes the end of a list. */ writeListEnd(): void; /** * Serializes the beginning of a set collection. * @param {Thrift.Type} elemType - The data type of the elements. * @param {number} size - The number of elements in the list. */ writeSetBegin(elemType: number, size: number): void; /** * Serializes the end of a set. */ writeSetEnd(): void; /** Serializes a boolean */ writeBool(value: boolean): void; /** Serializes a number */ writeByte(i8: number): void; /** Serializes a number */ writeI16(i16: number): void; /** Serializes a number */ writeI32(i32: number): void; /** Serializes a number */ writeI64(i64: number): void; /** Serializes a number */ writeDouble(dbl: number): void; /** Serializes a string */ writeString(str: string): void; /** Serializes a string */ writeBinary(str: string): void; /** @class @name AnonReadMessageBeginReturn @property {string} fname - The name of the service method. @property {Thrift.MessageType} mtype - The type of message call. @property {number} rseqid - The sequence number of the message (0 in Thrift RPC). */ /** * Deserializes the beginning of a message. * @returns {AnonReadMessageBeginReturn} */ readMessageBegin(): { fname: string; mtype: number; rseqid: number }; /** Deserializes the end of a message. */ readMessageEnd(): void; /** * Deserializes the beginning of a struct. * @param {string} [name] - The name of the struct (ignored). * @returns {object} - An object with an empty string fname property. */ readStructBegin(name?: string): { fname: string }; /** Deserializes the end of a struct. */ readStructEnd(): void; /** @class @name AnonReadFieldBeginReturn @property {string} fname - The name of the field (always ''). @property {Thrift.Type} ftype - The data type of the field. @property {number} fid - The unique identifier of the field. */ /** * Deserializes the beginning of a field. * @returns {AnonReadFieldBeginReturn} */ readFieldBegin(): { fname: string; ftype: number; fid: number }; /** Deserializes the end of a field. */ readFieldEnd(): void; /** @class @name AnonReadMapBeginReturn @property {Thrift.Type} ktype - The data type of the key. @property {Thrift.Type} vtype - The data type of the value. @property {number} size - The number of elements in the map. */ /** * Deserializes the beginning of a map. * @returns {AnonReadMapBeginReturn} */ readMapBegin(): { ktype: number; vtype: number; size: number }; /** Deserializes the end of a map. */ readMapEnd(): void; /** @class @name AnonReadColBeginReturn @property {Thrift.Type} etype - The data type of the element. @property {number} size - The number of elements in the collection. */ /** * Deserializes the beginning of a list. * @returns {AnonReadColBeginReturn} */ readListBegin(): { etype: number; size: number }; /** Deserializes the end of a list. */ readListEnd(): void; /** * Deserializes the beginning of a set. * @param {Thrift.Type} elemType - The data type of the elements (ignored). * @param {number} size - The number of elements in the list (ignored). * @returns {AnonReadColBeginReturn} */ readSetBegin(elemType?: number, size?: number): { etype: number; size: number }; /** Deserializes the end of a set. */ readSetEnd(): void; /** Returns an object with a value property set to * False unless the next number in the protocol buffer * is 1, in which case the value property is True. */ readBool(): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readByte(): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readI16(): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readI32(f?: any): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readI64(): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readDouble(): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readString(): Object; /** Returns an object with a value property set to the next value found in the protocol buffer. */ readBinary(): Object; /** * Method to arbitrarily skip over data (not implemented). */ skip(type: number): void; } /** * Old alias of the TXHRTransport for backwards compatibility. */ class Protocol extends TJSONProtocol { } class MultiplexProtocol extends TJSONProtocol { serviceName: string; /** * Initializes a MutilplexProtocol Implementation as a Wrapper for Thrift.Protocol. * @param {string} srvName * @param {Thrift.Transport} trans * @param {any} [strictRead] * @param {any} [strictWrite] */ constructor(srvName: string, trans: Object, strictRead?: any, strictWrite?: any); /** * Override writeMessageBegin method of prototype * Serializes the beginning of a Thrift RPC message. * @param {string} name - The service method to call. * @param {Thrift.MessageType} messageType - The type of method call. * @param {number} seqid - The sequence number of this call (always 0 in Apache Thrift). */ writeMessageBegin(name: string, type: number, seqid: number): void; } class Multiplexer { seqid: number; /** * Instantiates a multiplexed client for a specific service. * @param {String} serviceName - The transport to serialize to/from. * @param {Thrift.ServiceClient} SCl - The Service Client Class. * @param {Thrift.Transport} transport - Thrift.Transport instance which provides remote host:port. */ createClient(serviceName: string, SCl: any, transport: Object): any; } } thrift-0.19.0/lib/ts/Makefile.in0000644000000000000000000004405414472652520016356 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/ts ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ coding_standards.md \ Gruntfile.js \ package.json \ package-lock.json \ thrift.d.ts \ tsconfig.json all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/ts/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/ts/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook @HAVE_NPM_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am check check-am check-local clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # Make sure this doesn't fail if ant is not configured. # We call install twice to work around npm issues # @HAVE_NPM_TRUE@prereq: @HAVE_NPM_TRUE@ $(NPM) install || $(NPM) install @HAVE_NPM_TRUE@ $(NPM) list @HAVE_NPM_TRUE@check-local: prereq all @HAVE_NPM_TRUE@ ./node_modules/.bin/grunt @HAVE_NPM_TRUE@doc: prereq @HAVE_NPM_TRUE@ ./node_modules/.bin/grunt jsdoc clean-local: $(RM) -r dist $(RM) -r doc $(RM) -r node_modules $(RM) -r test/build/ $(RM) -r test/gen-*/ dist-hook: $(RM) -r $(distdir)/dist/ $(RM) -r $(distdir)/doc/ $(RM) -r $(distdir)/node_modules/ $(RM) -r $(distdir)/test/build/ $(RM) -r $(distdir)/test/gen-*/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/ts/Gruntfile.js0000644000000000000000000001124014370300523016563 0ustar00rootroot00000000000000//To build dist/thrift.js, dist/thrift.min.js and doc/* //run grunt at the command line in this directory. //Prerequisites: // Node Setup - nodejs.org // Grunt Setup - npm install //reads the ./package.json and installs project dependencies // Run grunt - npx grunt // uses project-local installed version of grunt (from package.json) module.exports = function(grunt) { 'use strict'; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), concat: { options: { separator: ';' }, dist: { src: ['src/**/*.js'], dest: 'dist/<%= pkg.name %>.js' } }, shell: { InstallThriftJS: { command: 'mkdir -p test/build/ts/lib; cp ../js/src/thrift.js test/build/ts/thrift.js' }, InstallThriftNodeJSDep: { command: 'cd ../..; npm install' }, InstallTestLibs: { command: 'cd test; ant download_jslibs' }, ThriftGen: { command: [ 'mkdir -p test/gen-js', '../../compiler/cpp/thrift -gen js:ts --out test/gen-js ../../test/v0.16/ThriftTest.thrift', 'mkdir -p test/gen-nodejs', '../../compiler/cpp/thrift -gen js:node,ts --out test/gen-nodejs ../../test/v0.16/ThriftTest.thrift', ].join(' && ') }, ThriftBrowserifyNodeInt64: { command: [ './node_modules/browserify/bin/cmd.js ./node_modules/node-int64/Int64.js -s Int64 -o test/build/js/lib/Int64.js', './node_modules/browserify/bin/cmd.js ../nodejs/lib/thrift/int64_util.js -s Int64Util -o test/build/js/lib/Int64Util.js', './node_modules/browserify/bin/cmd.js ./node_modules/json-int64/index.js -s JSONInt64 -o test/build/js/lib/JSONInt64.js' ].join(' && ') }, ThriftGenInt64: { command: '../../compiler/cpp/thrift -gen js:ts -o test ../../test/Int64Test.thrift' }, ThriftTestServer: { options: { async: true, execOptions: { cwd: "./test", env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} } }, command: "node server_http.js", }, BuildTS: { options: { execOptions: { cwd: "./test", } }, command : "../node_modules/typescript/bin/tsc --listFiles --outDir build/ts" }, BrowserifyCompiledTS: { command: [ "./node_modules/browserify/bin/cmd.js test/build/ts/test.js -o test/build/ts/lib/test.js --standalone test", "./node_modules/browserify/bin/cmd.js test/build/ts/test-int64.js -o test/build/ts/lib/test-int64.js --standalone testInt64", ].join(" && ") }, InstallGeneratedCode: { command: [ "mkdir -p test/build/ts", "cp -r test/gen-js test/build/ts" ].join(" && ") }, }, qunit: { ThriftJS: { options: { urls: [ 'http://localhost:8089/test.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], }, } }, ThriftJS_Int64: { options: { urls: [ 'http://localhost:8089/test-int64.html' ], puppeteer: { headless: true, args: ['--no-sandbox'], ignoreHTTPSErrors: true, }, } }, }, jshint: { // The main Thrift library file. not es6 yet :( lib: { src: ['../js/src/**/*.js'], }, // The test files use es6 test: { src: ['Gruntfile.js', 'test/*.js'], options: { esversion: 6, } }, gen_js_code: { src: ['test/gen-js/*.js'], }, gen_node_code: { src: ['test/gen-nodejs/*.js'], options: { node: true, } }, }, }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.loadNpmTasks('grunt-shell-spawn'); grunt.registerTask('wait', 'Wait just one second for the server to start', function () { var done = this.async(); setTimeout(function() { done(true); }, 1000); }); grunt.registerTask('installAndGenerate', [ 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', 'shell:ThriftBrowserifyNodeInt64', 'shell:ThriftGenInt64', 'shell:InstallTestLibs', 'shell:BuildTS', 'shell:InstallGeneratedCode', 'shell:BrowserifyCompiledTS', ]); grunt.registerTask('test', [ 'installAndGenerate', 'jshint', 'shell:ThriftTestServer', 'wait', 'qunit:ThriftJS', 'qunit:ThriftJS_Int64', 'shell:ThriftTestServer:kill', ]); grunt.registerTask('default', ['test']); }; thrift-0.19.0/lib/go/0000755000000000000000000000000014472652664014272 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/thrift/0000777000000000000000000000000014472647462015576 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/thrift/buffered_transport_test.go0000644000000000000000000000172414303740367023051 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "testing" ) func TestBufferedTransport(t *testing.T) { trans := NewTBufferedTransport(NewTMemoryBuffer(), 10240) TransportTest(t, trans, trans) } thrift-0.19.0/lib/go/thrift/memory_buffer_test.go0000644000000000000000000000167014303740367022014 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "testing" ) func TestMemoryBuffer(t *testing.T) { trans := NewTMemoryBufferLen(1024) TransportTest(t, trans, trans) } thrift-0.19.0/lib/go/thrift/server_transport.go0000644000000000000000000000244614303740367021540 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Server transport. Object which provides client transports. type TServerTransport interface { Listen() error Accept() (TTransport, error) Close() error // Optional method implementation. This signals to the server transport // that it should break out of any accept() or listen() that it is currently // blocked on. This method, if implemented, MUST be thread safe, as it may // be called from a different thread context than the other TServerTransport // methods. Interrupt() error } thrift-0.19.0/lib/go/thrift/middleware.go0000644000000000000000000001240514303740367020227 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" ) // ProcessorMiddleware is a function that can be passed to WrapProcessor to wrap the // TProcessorFunctions for that TProcessor. // // Middlewares are passed in the name of the function as set in the processor // map of the TProcessor. type ProcessorMiddleware func(name string, next TProcessorFunction) TProcessorFunction // WrapProcessor takes an existing TProcessor and wraps each of its inner // TProcessorFunctions with the middlewares passed in and returns it. // // Middlewares will be called in the order that they are defined: // // 1. Middlewares[0] // 2. Middlewares[1] // ... // N. Middlewares[n] func WrapProcessor(processor TProcessor, middlewares ...ProcessorMiddleware) TProcessor { for name, processorFunc := range processor.ProcessorMap() { wrapped := processorFunc // Add middlewares in reverse so the first in the list is the outermost. for i := len(middlewares) - 1; i >= 0; i-- { wrapped = middlewares[i](name, wrapped) } processor.AddToProcessorMap(name, wrapped) } return processor } // WrappedTProcessorFunction is a convenience struct that implements the // TProcessorFunction interface that can be used when implementing custom // Middleware. type WrappedTProcessorFunction struct { // Wrapped is called by WrappedTProcessorFunction.Process and should be a // "wrapped" call to a base TProcessorFunc.Process call. Wrapped func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) } // Process implements the TProcessorFunction interface using p.Wrapped. func (p WrappedTProcessorFunction) Process(ctx context.Context, seqID int32, in, out TProtocol) (bool, TException) { return p.Wrapped(ctx, seqID, in, out) } // verify that WrappedTProcessorFunction implements TProcessorFunction var ( _ TProcessorFunction = WrappedTProcessorFunction{} _ TProcessorFunction = (*WrappedTProcessorFunction)(nil) ) // ClientMiddleware can be passed to WrapClient in order to wrap TClient calls // with custom middleware. type ClientMiddleware func(TClient) TClient // WrappedTClient is a convenience struct that implements the TClient interface // using inner Wrapped function. // // This is provided to aid in developing ClientMiddleware. type WrappedTClient struct { Wrapped func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) } // Call implements the TClient interface by calling and returning c.Wrapped. func (c WrappedTClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { return c.Wrapped(ctx, method, args, result) } // verify that WrappedTClient implements TClient var ( _ TClient = WrappedTClient{} _ TClient = (*WrappedTClient)(nil) ) // WrapClient wraps the given TClient in the given middlewares. // // Middlewares will be called in the order that they are defined: // // 1. Middlewares[0] // 2. Middlewares[1] // ... // N. Middlewares[n] func WrapClient(client TClient, middlewares ...ClientMiddleware) TClient { // Add middlewares in reverse so the first in the list is the outermost. for i := len(middlewares) - 1; i >= 0; i-- { client = middlewares[i](client) } return client } // ExtractIDLExceptionClientMiddleware is a ClientMiddleware implementation that // extracts exceptions defined in thrift IDL into the error return of // TClient.Call. It uses ExtractExceptionFromResult under the hood. // // By default if a client call gets an exception defined in the thrift IDL, for // example: // // service MyService { // FooResponse foo(1: FooRequest request) throws ( // 1: Exception1 error1, // 2: Exception2 error2, // ) // } // // Exception1 or Exception2 will not be in the err return of TClient.Call, // but in the result TStruct instead, and there's no easy access to them. // If you have a ClientMiddleware that would need to access them, // you can add this middleware into your client middleware chain, // *after* your other middlewares need them, // then your other middlewares will have access to those exceptions from the err // return. // // Alternatively you can also just use ExtractExceptionFromResult in your client // middleware directly to access those exceptions. func ExtractIDLExceptionClientMiddleware(next TClient) TClient { return WrappedTClient{ Wrapped: func(ctx context.Context, method string, args, result TStruct) (_ ResponseMeta, err error) { defer func() { if err == nil { err = ExtractExceptionFromResult(result) } }() return next.Call(ctx, method, args, result) }, } } thrift-0.19.0/lib/go/thrift/ssl_server_socket.go0000644000000000000000000000554714303740367021662 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "crypto/tls" "net" "time" ) type TSSLServerSocket struct { listener net.Listener addr net.Addr clientTimeout time.Duration interrupted bool cfg *tls.Config } func NewTSSLServerSocket(listenAddr string, cfg *tls.Config) (*TSSLServerSocket, error) { return NewTSSLServerSocketTimeout(listenAddr, cfg, 0) } func NewTSSLServerSocketTimeout(listenAddr string, cfg *tls.Config, clientTimeout time.Duration) (*TSSLServerSocket, error) { if cfg.MinVersion == 0 { cfg.MinVersion = tls.VersionTLS10 } addr, err := net.ResolveTCPAddr("tcp", listenAddr) if err != nil { return nil, err } return &TSSLServerSocket{addr: addr, clientTimeout: clientTimeout, cfg: cfg}, nil } func (p *TSSLServerSocket) Listen() error { if p.IsListening() { return nil } l, err := tls.Listen(p.addr.Network(), p.addr.String(), p.cfg) if err != nil { return err } p.listener = l return nil } func (p *TSSLServerSocket) Accept() (TTransport, error) { if p.interrupted { return nil, errTransportInterrupted } if p.listener == nil { return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") } conn, err := p.listener.Accept() if err != nil { return nil, NewTTransportExceptionFromError(err) } return NewTSSLSocketFromConnTimeout(conn, p.cfg, p.clientTimeout), nil } // Checks whether the socket is listening. func (p *TSSLServerSocket) IsListening() bool { return p.listener != nil } // Connects the socket, creating a new socket object if necessary. func (p *TSSLServerSocket) Open() error { if p.IsListening() { return NewTTransportException(ALREADY_OPEN, "Server socket already open") } if l, err := tls.Listen(p.addr.Network(), p.addr.String(), p.cfg); err != nil { return err } else { p.listener = l } return nil } func (p *TSSLServerSocket) Addr() net.Addr { return p.addr } func (p *TSSLServerSocket) Close() error { defer func() { p.listener = nil }() if p.IsListening() { return p.listener.Close() } return nil } func (p *TSSLServerSocket) Interrupt() error { p.interrupted = true return nil } thrift-0.19.0/lib/go/thrift/socket_non_unix_conn.go0000644000000000000000000000222114303740367022327 0ustar00rootroot00000000000000//go:build windows || wasm // +build windows wasm /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift func (sc *socketConn) read0() error { // On non-unix platforms, we fallback to the default behavior of reading 0 bytes. var p []byte _, err := sc.Conn.Read(p) return err } func (sc *socketConn) checkConn() error { // On non-unix platforms, we always return nil for this check. return nil } thrift-0.19.0/lib/go/thrift/json_protocol.go0000644000000000000000000003421614370300523020776 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "encoding/base64" "fmt" ) const ( THRIFT_JSON_PROTOCOL_VERSION = 1 ) // for references to _ParseContext see tsimplejson_protocol.go // JSON protocol implementation for thrift. // Utilizes Simple JSON protocol type TJSONProtocol struct { *TSimpleJSONProtocol } // Constructor func NewTJSONProtocol(t TTransport) *TJSONProtocol { v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)} v.parseContextStack.push(_CONTEXT_IN_TOPLEVEL) v.dumpContext.push(_CONTEXT_IN_TOPLEVEL) return v } // Factory type TJSONProtocolFactory struct{} func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { return NewTJSONProtocol(trans) } func NewTJSONProtocolFactory() *TJSONProtocolFactory { return &TJSONProtocolFactory{} } func (p *TJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error { p.resetContextStack() // THRIFT-3735 if e := p.OutputListBegin(); e != nil { return e } if e := p.WriteI32(ctx, THRIFT_JSON_PROTOCOL_VERSION); e != nil { return e } if e := p.WriteString(ctx, name); e != nil { return e } if e := p.WriteByte(ctx, int8(typeId)); e != nil { return e } if e := p.WriteI32(ctx, seqId); e != nil { return e } return nil } func (p *TJSONProtocol) WriteMessageEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TJSONProtocol) WriteStructBegin(ctx context.Context, name string) error { if e := p.OutputObjectBegin(); e != nil { return e } return nil } func (p *TJSONProtocol) WriteStructEnd(ctx context.Context) error { return p.OutputObjectEnd() } func (p *TJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { if e := p.WriteI16(ctx, id); e != nil { return e } if e := p.OutputObjectBegin(); e != nil { return e } s, e1 := p.TypeIdToString(typeId) if e1 != nil { return e1 } if e := p.WriteString(ctx, s); e != nil { return e } return nil } func (p *TJSONProtocol) WriteFieldEnd(ctx context.Context) error { return p.OutputObjectEnd() } func (p *TJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil } func (p *TJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { if e := p.OutputListBegin(); e != nil { return e } s, e1 := p.TypeIdToString(keyType) if e1 != nil { return e1 } if e := p.WriteString(ctx, s); e != nil { return e } s, e1 = p.TypeIdToString(valueType) if e1 != nil { return e1 } if e := p.WriteString(ctx, s); e != nil { return e } if e := p.WriteI64(ctx, int64(size)); e != nil { return e } return p.OutputObjectBegin() } func (p *TJSONProtocol) WriteMapEnd(ctx context.Context) error { if e := p.OutputObjectEnd(); e != nil { return e } return p.OutputListEnd() } func (p *TJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { return p.OutputElemListBegin(elemType, size) } func (p *TJSONProtocol) WriteListEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { return p.OutputElemListBegin(elemType, size) } func (p *TJSONProtocol) WriteSetEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TJSONProtocol) WriteBool(ctx context.Context, b bool) error { if b { return p.WriteI32(ctx, 1) } return p.WriteI32(ctx, 0) } func (p *TJSONProtocol) WriteByte(ctx context.Context, b int8) error { return p.WriteI32(ctx, int32(b)) } func (p *TJSONProtocol) WriteI16(ctx context.Context, v int16) error { return p.WriteI32(ctx, int32(v)) } func (p *TJSONProtocol) WriteI32(ctx context.Context, v int32) error { return p.OutputI64(int64(v)) } func (p *TJSONProtocol) WriteI64(ctx context.Context, v int64) error { return p.OutputI64(int64(v)) } func (p *TJSONProtocol) WriteDouble(ctx context.Context, v float64) error { return p.OutputF64(v) } func (p *TJSONProtocol) WriteString(ctx context.Context, v string) error { return p.OutputString(v) } func (p *TJSONProtocol) WriteBinary(ctx context.Context, v []byte) error { // JSON library only takes in a string, // not an arbitrary byte array, to ensure bytes are transmitted // efficiently we must convert this into a valid JSON string // therefore we use base64 encoding to avoid excessive escaping/quoting if e := p.OutputPreValue(); e != nil { return e } if _, e := p.write(JSON_QUOTE_BYTES); e != nil { return NewTProtocolException(e) } writer := base64.NewEncoder(base64.StdEncoding, p.writer) if _, e := writer.Write(v); e != nil { p.writer.Reset(p.trans) // THRIFT-3735 return NewTProtocolException(e) } if e := writer.Close(); e != nil { return NewTProtocolException(e) } if _, e := p.write(JSON_QUOTE_BYTES); e != nil { return NewTProtocolException(e) } return p.OutputPostValue() } // Reading methods. func (p *TJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { p.resetContextStack() // THRIFT-3735 if isNull, err := p.ParseListBegin(); isNull || err != nil { return name, typeId, seqId, err } version, err := p.ReadI32(ctx) if err != nil { return name, typeId, seqId, err } if version != THRIFT_JSON_PROTOCOL_VERSION { e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION) return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e) } if name, err = p.ReadString(ctx); err != nil { return name, typeId, seqId, err } bTypeId, err := p.ReadByte(ctx) typeId = TMessageType(bTypeId) if err != nil { return name, typeId, seqId, err } if seqId, err = p.ReadI32(ctx); err != nil { return name, typeId, seqId, err } return name, typeId, seqId, nil } func (p *TJSONProtocol) ReadMessageEnd(ctx context.Context) error { err := p.ParseListEnd() return err } func (p *TJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { _, err = p.ParseObjectStart() return "", err } func (p *TJSONProtocol) ReadStructEnd(ctx context.Context) error { return p.ParseObjectEnd() } func (p *TJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) { b, _ := p.reader.Peek(1) if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] { return "", STOP, -1, nil } fieldId, err := p.ReadI16(ctx) if err != nil { return "", STOP, fieldId, err } if _, err = p.ParseObjectStart(); err != nil { return "", STOP, fieldId, err } sType, err := p.ReadString(ctx) if err != nil { return "", STOP, fieldId, err } fType, err := p.StringToTypeId(sType) return "", fType, fieldId, err } func (p *TJSONProtocol) ReadFieldEnd(ctx context.Context) error { return p.ParseObjectEnd() } func (p *TJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) { if isNull, e := p.ParseListBegin(); isNull || e != nil { return VOID, VOID, 0, e } // read keyType sKeyType, e := p.ReadString(ctx) if e != nil { return keyType, valueType, size, e } keyType, e = p.StringToTypeId(sKeyType) if e != nil { return keyType, valueType, size, e } // read valueType sValueType, e := p.ReadString(ctx) if e != nil { return keyType, valueType, size, e } valueType, e = p.StringToTypeId(sValueType) if e != nil { return keyType, valueType, size, e } // read size iSize, err := p.ReadI64(ctx) if err != nil { return keyType, valueType, size, err } err = checkSizeForProtocol(int32(iSize), p.cfg) if err != nil { return keyType, valueType, 0, err } size = int(iSize) _, e = p.ParseObjectStart() return keyType, valueType, size, e } func (p *TJSONProtocol) ReadMapEnd(ctx context.Context) error { e := p.ParseObjectEnd() if e != nil { return e } return p.ParseListEnd() } func (p *TJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) { return p.ParseElemListBegin() } func (p *TJSONProtocol) ReadListEnd(ctx context.Context) error { return p.ParseListEnd() } func (p *TJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) { return p.ParseElemListBegin() } func (p *TJSONProtocol) ReadSetEnd(ctx context.Context) error { return p.ParseListEnd() } func (p *TJSONProtocol) ReadBool(ctx context.Context) (bool, error) { value, err := p.ReadI32(ctx) return (value != 0), err } func (p *TJSONProtocol) ReadByte(ctx context.Context) (int8, error) { v, err := p.ReadI64(ctx) return int8(v), err } func (p *TJSONProtocol) ReadI16(ctx context.Context) (int16, error) { v, err := p.ReadI64(ctx) return int16(v), err } func (p *TJSONProtocol) ReadI32(ctx context.Context) (int32, error) { v, err := p.ReadI64(ctx) return int32(v), err } func (p *TJSONProtocol) ReadI64(ctx context.Context) (int64, error) { v, _, err := p.ParseI64() return v, err } func (p *TJSONProtocol) ReadDouble(ctx context.Context) (float64, error) { v, _, err := p.ParseF64() return v, err } func (p *TJSONProtocol) ReadString(ctx context.Context) (string, error) { var v string if err := p.ParsePreValue(); err != nil { return v, err } f, _ := p.reader.Peek(1) if len(f) > 0 && f[0] == JSON_QUOTE { p.reader.ReadByte() value, err := p.ParseStringBody() v = value if err != nil { return v, err } } else if len(f) > 0 && f[0] == JSON_NULL[0] { b := make([]byte, len(JSON_NULL)) _, err := p.reader.Read(b) if err != nil { return v, NewTProtocolException(err) } if string(b) != string(JSON_NULL) { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } } else { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } return v, p.ParsePostValue() } func (p *TJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) { var v []byte if err := p.ParsePreValue(); err != nil { return nil, err } f, _ := p.reader.Peek(1) if len(f) > 0 && f[0] == JSON_QUOTE { p.reader.ReadByte() value, err := p.ParseBase64EncodedBody() v = value if err != nil { return v, err } } else if len(f) > 0 && f[0] == JSON_NULL[0] { b := make([]byte, len(JSON_NULL)) _, err := p.reader.Read(b) if err != nil { return v, NewTProtocolException(err) } if string(b) != string(JSON_NULL) { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } } else { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } return v, p.ParsePostValue() } func (p *TJSONProtocol) Flush(ctx context.Context) (err error) { err = p.writer.Flush() if err == nil { err = p.trans.Flush(ctx) } return NewTProtocolException(err) } func (p *TJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) { return SkipDefaultDepth(ctx, p, fieldType) } func (p *TJSONProtocol) Transport() TTransport { return p.trans } func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error { if e := p.OutputListBegin(); e != nil { return e } s, e1 := p.TypeIdToString(elemType) if e1 != nil { return e1 } if e := p.OutputString(s); e != nil { return e } if e := p.OutputI64(int64(size)); e != nil { return e } return nil } func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { if isNull, e := p.ParseListBegin(); isNull || e != nil { return VOID, 0, e } // We don't really use the ctx in ReadString implementation, // so this is safe for now. // We might want to add context to ParseElemListBegin if we start to use // ctx in ReadString implementation in the future. sElemType, err := p.ReadString(context.Background()) if err != nil { return VOID, size, err } elemType, err = p.StringToTypeId(sElemType) if err != nil { return elemType, size, err } nSize, _, err := p.ParseI64() if err != nil { return elemType, 0, err } err = checkSizeForProtocol(int32(nSize), p.cfg) if err != nil { return elemType, 0, err } size = int(nSize) return elemType, size, nil } func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) { switch byte(fieldType) { case BOOL: return "tf", nil case BYTE: return "i8", nil case I16: return "i16", nil case I32: return "i32", nil case I64: return "i64", nil case DOUBLE: return "dbl", nil case STRING: return "str", nil case STRUCT: return "rec", nil case MAP: return "map", nil case SET: return "set", nil case LIST: return "lst", nil case UUID: return "uid", nil } e := fmt.Errorf("Unknown fieldType: %d", int(fieldType)) return "", NewTProtocolExceptionWithType(INVALID_DATA, e) } func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) { switch fieldType { case "tf": return TType(BOOL), nil case "i8": return TType(BYTE), nil case "i16": return TType(I16), nil case "i32": return TType(I32), nil case "i64": return TType(I64), nil case "dbl": return TType(DOUBLE), nil case "str": return TType(STRING), nil case "rec": return TType(STRUCT), nil case "map": return TType(MAP), nil case "set": return TType(SET), nil case "lst": return TType(LIST), nil case "uid": return TType(UUID), nil } e := fmt.Errorf("Unknown type identifier: %s", fieldType) return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e) } var _ TConfigurationSetter = (*TJSONProtocol)(nil) thrift-0.19.0/lib/go/thrift/application_exception.go0000644000000000000000000001270714370300523022466 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "strings" ) const ( UNKNOWN_APPLICATION_EXCEPTION = 0 UNKNOWN_METHOD = 1 INVALID_MESSAGE_TYPE_EXCEPTION = 2 WRONG_METHOD_NAME = 3 BAD_SEQUENCE_ID = 4 MISSING_RESULT = 5 INTERNAL_ERROR = 6 PROTOCOL_ERROR = 7 INVALID_TRANSFORM = 8 INVALID_PROTOCOL = 9 UNSUPPORTED_CLIENT_TYPE = 10 VALIDATION_FAILED = 11 ) var defaultApplicationExceptionMessage = map[int32]string{ UNKNOWN_APPLICATION_EXCEPTION: "unknown application exception", UNKNOWN_METHOD: "unknown method", INVALID_MESSAGE_TYPE_EXCEPTION: "invalid message type", WRONG_METHOD_NAME: "wrong method name", BAD_SEQUENCE_ID: "bad sequence ID", MISSING_RESULT: "missing result", INTERNAL_ERROR: "unknown internal error", PROTOCOL_ERROR: "unknown protocol error", INVALID_TRANSFORM: "Invalid transform", INVALID_PROTOCOL: "Invalid protocol", UNSUPPORTED_CLIENT_TYPE: "Unsupported client type", VALIDATION_FAILED: "validation failed", } // Application level Thrift exception type TApplicationException interface { TException TypeId() int32 Read(ctx context.Context, iprot TProtocol) error Write(ctx context.Context, oprot TProtocol) error } type ValidationError struct { message string check string fieldSymbol string } func (e *ValidationError) Check() string { return e.check } func (e *ValidationError) TypeName() string { return strings.Split(e.fieldSymbol, ".")[0] } func (e *ValidationError) Field() string { if fs := strings.Split(e.fieldSymbol, "."); len(fs) > 1 { return fs[1] } return e.fieldSymbol } func (e *ValidationError) FieldSymbol() string { return e.fieldSymbol } func (e ValidationError) Error() string { return e.message } type tApplicationException struct { message string type_ int32 err error } var _ TApplicationException = (*tApplicationException)(nil) func (tApplicationException) TExceptionType() TExceptionType { return TExceptionTypeApplication } func (e tApplicationException) Error() string { if e.message != "" { return e.message } return defaultApplicationExceptionMessage[e.type_] } func (e tApplicationException) Unwrap() error { return e.err } func NewTApplicationException(type_ int32, message string) TApplicationException { return &tApplicationException{message, type_, nil} } func NewValidationException(type_ int32, check string, field string, message string) TApplicationException { return &tApplicationException{ type_: type_, message: message, err: &ValidationError{message: message, check: check, fieldSymbol: field}, } } func (p *tApplicationException) TypeId() int32 { return p.type_ } func (p *tApplicationException) Read(ctx context.Context, iprot TProtocol) error { // TODO: this should really be generated by the compiler _, err := iprot.ReadStructBegin(ctx) if err != nil { return err } message := "" type_ := int32(UNKNOWN_APPLICATION_EXCEPTION) for { _, ttype, id, err := iprot.ReadFieldBegin(ctx) if err != nil { return err } if ttype == STOP { break } switch id { case 1: if ttype == STRING { if message, err = iprot.ReadString(ctx); err != nil { return err } } else { if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil { return err } } case 2: if ttype == I32 { if type_, err = iprot.ReadI32(ctx); err != nil { return err } } else { if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil { return err } } default: if err = SkipDefaultDepth(ctx, iprot, ttype); err != nil { return err } } if err = iprot.ReadFieldEnd(ctx); err != nil { return err } } if err := iprot.ReadStructEnd(ctx); err != nil { return err } p.message = message p.type_ = type_ return nil } func (p *tApplicationException) Write(ctx context.Context, oprot TProtocol) (err error) { err = oprot.WriteStructBegin(ctx, "TApplicationException") if err != nil { return } if len(p.Error()) > 0 { err = oprot.WriteFieldBegin(ctx, "message", STRING, 1) if err != nil { return } err = oprot.WriteString(ctx, p.Error()) if err != nil { return } err = oprot.WriteFieldEnd(ctx) if err != nil { return } } err = oprot.WriteFieldBegin(ctx, "type", I32, 2) if err != nil { return } err = oprot.WriteI32(ctx, p.type_) if err != nil { return } err = oprot.WriteFieldEnd(ctx) if err != nil { return } err = oprot.WriteFieldStop(ctx) if err != nil { return } err = oprot.WriteStructEnd(ctx) return } thrift-0.19.0/lib/go/thrift/configuration_test.go0000644000000000000000000002434614303740367022027 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "crypto/tls" "testing" "time" ) func TestTConfiguration(t *testing.T) { invalidProtoID := THeaderProtocolID(-1) if invalidProtoID.Validate() == nil { t.Fatalf("Expected %v to be an invalid THeaderProtocolID, it passes the validation", invalidProtoID) } tlsConfig := &tls.Config{ Time: time.Now, } for _, c := range []struct { label string cfg *TConfiguration expectedMessageSize int32 expectedFrameSize int32 expectedConnectTimeout time.Duration expectedSocketTimeout time.Duration expectedTLSConfig *tls.Config expectedBinaryRead bool expectedBinaryWrite bool expectedProtoID THeaderProtocolID }{ { label: "nil", cfg: nil, expectedMessageSize: DEFAULT_MAX_MESSAGE_SIZE, expectedFrameSize: DEFAULT_MAX_FRAME_SIZE, expectedConnectTimeout: DEFAULT_CONNECT_TIMEOUT, expectedSocketTimeout: DEFAULT_SOCKET_TIMEOUT, expectedTLSConfig: nil, expectedBinaryRead: DEFAULT_TBINARY_STRICT_READ, expectedBinaryWrite: DEFAULT_TBINARY_STRICT_WRITE, expectedProtoID: THeaderProtocolDefault, }, { label: "empty", cfg: &TConfiguration{}, expectedMessageSize: DEFAULT_MAX_MESSAGE_SIZE, expectedFrameSize: DEFAULT_MAX_FRAME_SIZE, expectedConnectTimeout: DEFAULT_CONNECT_TIMEOUT, expectedSocketTimeout: DEFAULT_SOCKET_TIMEOUT, expectedTLSConfig: nil, expectedBinaryRead: DEFAULT_TBINARY_STRICT_READ, expectedBinaryWrite: DEFAULT_TBINARY_STRICT_WRITE, expectedProtoID: THeaderProtocolDefault, }, { label: "normal", cfg: &TConfiguration{ MaxMessageSize: 1024, MaxFrameSize: 1024, ConnectTimeout: time.Millisecond, SocketTimeout: time.Millisecond * 2, TLSConfig: tlsConfig, TBinaryStrictRead: BoolPtr(true), TBinaryStrictWrite: BoolPtr(false), THeaderProtocolID: THeaderProtocolIDPtrMust(THeaderProtocolCompact), }, expectedMessageSize: 1024, expectedFrameSize: 1024, expectedConnectTimeout: time.Millisecond, expectedSocketTimeout: time.Millisecond * 2, expectedTLSConfig: tlsConfig, expectedBinaryRead: true, expectedBinaryWrite: false, expectedProtoID: THeaderProtocolCompact, }, { label: "message= 0; i-- { if err := tr.closers[i].Close(); err != nil { return err } } return nil } // AddTransform adds a transform. func (tr *TransformReader) AddTransform(id THeaderTransformID) error { switch id { default: return NewTApplicationException( INVALID_TRANSFORM, fmt.Sprintf("THeaderTransformID %d not supported", id), ) case TransformNone: // no-op case TransformZlib: readCloser, err := zlib.NewReader(tr.Reader) if err != nil { return err } tr.Reader = readCloser tr.closers = append(tr.closers, readCloser) } return nil } // TransformWriter is an io.WriteCloser that handles transforms writing. type TransformWriter struct { io.Writer closers []io.Closer } var _ io.WriteCloser = (*TransformWriter)(nil) // NewTransformWriter creates a new TransformWriter with base writer and transforms. func NewTransformWriter(baseWriter io.Writer, transforms []THeaderTransformID) (io.WriteCloser, error) { writer := &TransformWriter{ Writer: baseWriter, closers: make([]io.Closer, 0, len(transforms)), } for _, id := range transforms { if err := writer.AddTransform(id); err != nil { return nil, err } } return writer, nil } // Close calls the underlying closers in appropriate order, // stops at and returns the first error encountered. func (tw *TransformWriter) Close() error { // Call closers in reversed order for i := len(tw.closers) - 1; i >= 0; i-- { if err := tw.closers[i].Close(); err != nil { return err } } return nil } // AddTransform adds a transform. func (tw *TransformWriter) AddTransform(id THeaderTransformID) error { switch id { default: return NewTApplicationException( INVALID_TRANSFORM, fmt.Sprintf("THeaderTransformID %d not supported", id), ) case TransformNone: // no-op case TransformZlib: writeCloser := zlib.NewWriter(tw.Writer) tw.Writer = writeCloser tw.closers = append(tw.closers, writeCloser) } return nil } // THeaderInfoType is the type id of the info headers. type THeaderInfoType int32 // Supported THeaderInfoType values. const ( _ THeaderInfoType = iota // Skip 0 InfoKeyValue // 1 // Rest of the info types are not supported. ) // THeaderTransport is a Transport mode that implements THeader. // // Note that THeaderTransport handles frame and zlib by itself, // so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), // instead of rich transports like TZlibTransport or TFramedTransport. type THeaderTransport struct { SequenceID int32 Flags uint32 transport TTransport // THeaderMap for read and write readHeaders THeaderMap writeHeaders THeaderMap // Reading related variables. reader *bufio.Reader // When frame is detected, we read the frame fully into frameBuffer. frameBuffer *bytes.Buffer // When it's non-nil, Read should read from frameReader instead of // reader, and EOF error indicates end of frame instead of end of all // transport. frameReader io.ReadCloser // Writing related variables writeBuffer *bytes.Buffer writeTransforms []THeaderTransformID clientType clientType protocolID THeaderProtocolID cfg *TConfiguration // buffer is used in the following scenarios to avoid repetitive // allocations, while 4 is big enough for all those scenarios: // // * header padding (max size 4) // * write the frame size (size 4) buffer [4]byte } var _ TTransport = (*THeaderTransport)(nil) // Deprecated: Use NewTHeaderTransportConf instead. func NewTHeaderTransport(trans TTransport) *THeaderTransport { return NewTHeaderTransportConf(trans, &TConfiguration{ noPropagation: true, }) } // NewTHeaderTransportConf creates THeaderTransport from the // underlying transport, with given TConfiguration attached. // // If trans is already a *THeaderTransport, it will be returned as is, // but with TConfiguration overridden by the value passed in. // // The protocol ID in TConfiguration is only useful for client transports. // For servers, // the protocol ID will be overridden again to the one set by the client, // to ensure that servers always speak the same dialect as the client. func NewTHeaderTransportConf(trans TTransport, conf *TConfiguration) *THeaderTransport { if ht, ok := trans.(*THeaderTransport); ok { ht.SetTConfiguration(conf) return ht } PropagateTConfiguration(trans, conf) return &THeaderTransport{ transport: trans, reader: bufio.NewReader(trans), writeHeaders: make(THeaderMap), protocolID: conf.GetTHeaderProtocolID(), cfg: conf, } } // Open calls the underlying transport's Open function. func (t *THeaderTransport) Open() error { return t.transport.Open() } // IsOpen calls the underlying transport's IsOpen function. func (t *THeaderTransport) IsOpen() bool { return t.transport.IsOpen() } // ReadFrame tries to read the frame header, guess the client type, and handle // unframed clients. func (t *THeaderTransport) ReadFrame(ctx context.Context) error { if !t.needReadFrame() { // No need to read frame, skipping. return nil } // Peek and handle the first 32 bits. // They could either be the length field of a framed message, // or the first bytes of an unframed message. var buf []byte var err error // This is also usually the first read from a connection, // so handle retries around socket timeouts. _, deadlineSet := ctx.Deadline() for { buf, err = t.reader.Peek(size32) if deadlineSet && isTimeoutError(err) && ctx.Err() == nil { // This is I/O timeout and we still have time, // continue trying continue } // For anything else, do not retry break } if err != nil { return err } frameSize := binary.BigEndian.Uint32(buf) if frameSize&VERSION_MASK == VERSION_1 { t.clientType = clientUnframedBinary return nil } if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION { t.clientType = clientUnframedCompact return nil } // At this point it should be a framed message, // sanity check on frameSize then discard the peeked part. if frameSize > THeaderMaxFrameSize || frameSize > uint32(t.cfg.GetMaxFrameSize()) { return NewTProtocolExceptionWithType( SIZE_LIMIT, errors.New("frame too large"), ) } t.reader.Discard(size32) // Read the frame fully into frameBuffer. if t.frameBuffer == nil { t.frameBuffer = bufPool.get() } _, err = io.CopyN(t.frameBuffer, t.reader, int64(frameSize)) if err != nil { return err } t.frameReader = io.NopCloser(t.frameBuffer) // Peek and handle the next 32 bits. buf = t.frameBuffer.Bytes()[:size32] version := binary.BigEndian.Uint32(buf) if version&THeaderHeaderMask == THeaderHeaderMagic { t.clientType = clientHeaders return t.parseHeaders(ctx, frameSize) } if version&VERSION_MASK == VERSION_1 { t.clientType = clientFramedBinary return nil } if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION { t.clientType = clientFramedCompact return nil } if err := t.endOfFrame(); err != nil { return err } return NewTProtocolExceptionWithType( NOT_IMPLEMENTED, errors.New("unsupported client transport type"), ) } // endOfFrame does end of frame handling. // // It closes frameReader, and also resets frame related states. func (t *THeaderTransport) endOfFrame() error { defer func() { bufPool.put(&t.frameBuffer) t.frameReader = nil }() return t.frameReader.Close() } func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) error { if t.clientType != clientHeaders { return nil } var err error var meta headerMeta if err = binary.Read(t.frameBuffer, binary.BigEndian, &meta); err != nil { return err } frameSize -= headerMetaSize t.Flags = meta.MagicFlags & THeaderFlagsMask t.SequenceID = meta.SequenceID headerLength := int64(meta.HeaderLength) * 4 if int64(frameSize) < headerLength { return NewTProtocolExceptionWithType( SIZE_LIMIT, errors.New("header size is larger than the whole frame"), ) } headerBuf := NewTMemoryBuffer() _, err = io.CopyN(headerBuf, t.frameBuffer, headerLength) if err != nil { return err } hp := NewTCompactProtocol(headerBuf) hp.SetTConfiguration(t.cfg) // At this point the header is already read into headerBuf, // and t.frameBuffer starts from the actual payload. protoID, err := hp.readVarint32() if err != nil { return err } t.protocolID = THeaderProtocolID(protoID) var transformCount int32 transformCount, err = hp.readVarint32() if err != nil { return err } if transformCount > 0 { reader := NewTransformReaderWithCapacity( t.frameBuffer, int(transformCount), ) t.frameReader = reader transformIDs := make([]THeaderTransformID, transformCount) for i := 0; i < int(transformCount); i++ { id, err := hp.readVarint32() if err != nil { return err } transformIDs[i] = THeaderTransformID(id) } // The transform IDs on the wire was added based on the order of // writing, so on the reading side we need to reverse the order. for i := transformCount - 1; i >= 0; i-- { id := transformIDs[i] if err := reader.AddTransform(id); err != nil { return err } } } // The info part does not use the transforms yet, so it's // important to continue using headerBuf. headers := make(THeaderMap) for { infoType, err := hp.readVarint32() if errors.Is(err, io.EOF) { break } if err != nil { return err } if THeaderInfoType(infoType) == InfoKeyValue { count, err := hp.readVarint32() if err != nil { return err } for i := 0; i < int(count); i++ { key, err := hp.ReadString(ctx) if err != nil { return err } value, err := hp.ReadString(ctx) if err != nil { return err } headers[key] = value } } else { // Skip reading info section on the first // unsupported info type. break } } t.readHeaders = headers return nil } func (t *THeaderTransport) needReadFrame() bool { if t.clientType == clientUnknown { // This is a new connection that's never read before. return true } if t.isFramed() && t.frameReader == nil { // We just finished the last frame. return true } return false } func (t *THeaderTransport) Read(p []byte) (read int, err error) { // Here using context.Background instead of a context passed in is safe. // First is that there's no way to pass context into this function. // Then, 99% of the case when calling this Read frame is already read // into frameReader. ReadFrame here is more of preventing bugs that // didn't call ReadFrame before calling Read. err = t.ReadFrame(context.Background()) if err != nil { return } if t.frameReader != nil { read, err = t.frameReader.Read(p) if err == nil && t.frameBuffer.Len() <= 0 { // the last Read finished the frame, do endOfFrame // handling here. err = t.endOfFrame() } else if err == io.EOF { err = t.endOfFrame() if err != nil { return } if read == 0 { // Try to read the next frame when we hit EOF // (end of frame) immediately. // When we got here, it means the last read // finished the previous frame, but didn't // do endOfFrame handling yet. // We have to read the next frame here, // as otherwise we would return 0 and nil, // which is a case not handled well by most // protocol implementations. return t.Read(p) } } return } return t.reader.Read(p) } // Write writes data to the write buffer. // // You need to call Flush to actually write them to the transport. func (t *THeaderTransport) Write(p []byte) (int, error) { if t.writeBuffer == nil { t.writeBuffer = bufPool.get() } return t.writeBuffer.Write(p) } // Flush writes the appropriate header and the write buffer to the underlying transport. func (t *THeaderTransport) Flush(ctx context.Context) error { if t.writeBuffer == nil || t.writeBuffer.Len() == 0 { return nil } defer bufPool.put(&t.writeBuffer) switch t.clientType { default: fallthrough case clientUnknown: t.clientType = clientHeaders fallthrough case clientHeaders: headers := NewTMemoryBuffer() hp := NewTCompactProtocol(headers) hp.SetTConfiguration(t.cfg) if _, err := hp.writeVarint32(int32(t.protocolID)); err != nil { return NewTTransportExceptionFromError(err) } if _, err := hp.writeVarint32(int32(len(t.writeTransforms))); err != nil { return NewTTransportExceptionFromError(err) } for _, transform := range t.writeTransforms { if _, err := hp.writeVarint32(int32(transform)); err != nil { return NewTTransportExceptionFromError(err) } } if len(t.writeHeaders) > 0 { if _, err := hp.writeVarint32(int32(InfoKeyValue)); err != nil { return NewTTransportExceptionFromError(err) } if _, err := hp.writeVarint32(int32(len(t.writeHeaders))); err != nil { return NewTTransportExceptionFromError(err) } for key, value := range t.writeHeaders { if err := hp.WriteString(ctx, key); err != nil { return NewTTransportExceptionFromError(err) } if err := hp.WriteString(ctx, value); err != nil { return NewTTransportExceptionFromError(err) } } } padding := 4 - headers.Len()%4 if padding < 4 { buf := t.buffer[:padding] for i := range buf { buf[i] = 0 } if _, err := headers.Write(buf); err != nil { return NewTTransportExceptionFromError(err) } } payload := bufPool.get() defer bufPool.put(&payload) meta := headerMeta{ MagicFlags: THeaderHeaderMagic + t.Flags&THeaderFlagsMask, SequenceID: t.SequenceID, HeaderLength: uint16(headers.Len() / 4), } if err := binary.Write(payload, binary.BigEndian, meta); err != nil { return NewTTransportExceptionFromError(err) } if _, err := io.Copy(payload, headers); err != nil { return NewTTransportExceptionFromError(err) } writer, err := NewTransformWriter(payload, t.writeTransforms) if err != nil { return NewTTransportExceptionFromError(err) } if _, err := io.Copy(writer, t.writeBuffer); err != nil { return NewTTransportExceptionFromError(err) } if err := writer.Close(); err != nil { return NewTTransportExceptionFromError(err) } // First write frame length buf := t.buffer[:size32] binary.BigEndian.PutUint32(buf, uint32(payload.Len())) if _, err := t.transport.Write(buf); err != nil { return NewTTransportExceptionFromError(err) } // Then write the payload if _, err := io.Copy(t.transport, payload); err != nil { return NewTTransportExceptionFromError(err) } case clientFramedBinary, clientFramedCompact: buf := t.buffer[:size32] binary.BigEndian.PutUint32(buf, uint32(t.writeBuffer.Len())) if _, err := t.transport.Write(buf); err != nil { return NewTTransportExceptionFromError(err) } fallthrough case clientUnframedBinary, clientUnframedCompact: if _, err := io.Copy(t.transport, t.writeBuffer); err != nil { return NewTTransportExceptionFromError(err) } } select { default: case <-ctx.Done(): return NewTTransportExceptionFromError(ctx.Err()) } return t.transport.Flush(ctx) } // Close closes the transport, along with its underlying transport. func (t *THeaderTransport) Close() error { if err := t.Flush(context.Background()); err != nil { return err } return t.transport.Close() } // RemainingBytes calls underlying transport's RemainingBytes. // // Even in framed cases, because of all the possible compression transforms // involved, the remaining frame size is likely to be different from the actual // remaining readable bytes, so we don't bother to keep tracking the remaining // frame size by ourselves and just use the underlying transport's // RemainingBytes directly. func (t *THeaderTransport) RemainingBytes() uint64 { return t.transport.RemainingBytes() } // GetReadHeaders returns the THeaderMap read from transport. func (t *THeaderTransport) GetReadHeaders() THeaderMap { return t.readHeaders } // SetWriteHeader sets a header for write. func (t *THeaderTransport) SetWriteHeader(key, value string) { t.writeHeaders[key] = value } // ClearWriteHeaders clears all write headers previously set. func (t *THeaderTransport) ClearWriteHeaders() { t.writeHeaders = make(THeaderMap) } // AddTransform add a transform for writing. func (t *THeaderTransport) AddTransform(transform THeaderTransformID) error { if !supportedTransformIDs[transform] { return NewTProtocolExceptionWithType( NOT_IMPLEMENTED, fmt.Errorf("THeaderTransformID %d not supported", transform), ) } t.writeTransforms = append(t.writeTransforms, transform) return nil } // Protocol returns the wrapped protocol id used in this THeaderTransport. func (t *THeaderTransport) Protocol() THeaderProtocolID { switch t.clientType { default: return t.protocolID case clientFramedBinary, clientUnframedBinary: return THeaderProtocolBinary case clientFramedCompact, clientUnframedCompact: return THeaderProtocolCompact } } func (t *THeaderTransport) isFramed() bool { switch t.clientType { default: return false case clientHeaders, clientFramedBinary, clientFramedCompact: return true } } // SetTConfiguration implements TConfigurationSetter. func (t *THeaderTransport) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(t.transport, cfg) t.cfg = cfg } // THeaderTransportFactory is a TTransportFactory implementation to create // THeaderTransport. // // It also implements TConfigurationSetter. type THeaderTransportFactory struct { // The underlying factory, could be nil. Factory TTransportFactory cfg *TConfiguration } // Deprecated: Use NewTHeaderTransportFactoryConf instead. func NewTHeaderTransportFactory(factory TTransportFactory) TTransportFactory { return NewTHeaderTransportFactoryConf(factory, &TConfiguration{ noPropagation: true, }) } // NewTHeaderTransportFactoryConf creates a new *THeaderTransportFactory with // the given *TConfiguration. func NewTHeaderTransportFactoryConf(factory TTransportFactory, conf *TConfiguration) TTransportFactory { return &THeaderTransportFactory{ Factory: factory, cfg: conf, } } // GetTransport implements TTransportFactory. func (f *THeaderTransportFactory) GetTransport(trans TTransport) (TTransport, error) { if f.Factory != nil { t, err := f.Factory.GetTransport(trans) if err != nil { return nil, err } return NewTHeaderTransportConf(t, f.cfg), nil } return NewTHeaderTransportConf(trans, f.cfg), nil } // SetTConfiguration implements TConfigurationSetter. func (f *THeaderTransportFactory) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(f.Factory, f.cfg) f.cfg = cfg } var ( _ TConfigurationSetter = (*THeaderTransportFactory)(nil) _ TConfigurationSetter = (*THeaderTransport)(nil) ) thrift-0.19.0/lib/go/thrift/serializer_types_test.go0000644000000000000000000004364314303740367022556 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Autogenerated by Thrift Compiler (FIXME) // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING /* THE FOLLOWING THRIFT FILE WAS USED TO CREATE THIS enum MyTestEnum { FIRST = 1, SECOND = 2, THIRD = 3, FOURTH = 4, } struct MyTestStruct { 1: bool on, 2: byte b, 3: i16 int16, 4: i32 int32, 5: i64 int64, 6: double d, 7: string st, 8: binary bin, 9: map stringMap, 10: list stringList, 11: set stringSet, 12: MyTestEnum e, } */ import ( "context" "fmt" ) // (needed to ensure safety because of naive import list construction.) var _ = ZERO var _ = fmt.Printf var GoUnusedProtection__ int type MyTestEnum int64 const ( MyTestEnum_FIRST MyTestEnum = 1 MyTestEnum_SECOND MyTestEnum = 2 MyTestEnum_THIRD MyTestEnum = 3 MyTestEnum_FOURTH MyTestEnum = 4 ) func (p MyTestEnum) String() string { switch p { case MyTestEnum_FIRST: return "FIRST" case MyTestEnum_SECOND: return "SECOND" case MyTestEnum_THIRD: return "THIRD" case MyTestEnum_FOURTH: return "FOURTH" } return "" } func MyTestEnumFromString(s string) (MyTestEnum, error) { switch s { case "FIRST": return MyTestEnum_FIRST, nil case "SECOND": return MyTestEnum_SECOND, nil case "THIRD": return MyTestEnum_THIRD, nil case "FOURTH": return MyTestEnum_FOURTH, nil } return MyTestEnum(0), fmt.Errorf("not a valid MyTestEnum string") } func MyTestEnumPtr(v MyTestEnum) *MyTestEnum { return &v } type MyTestStruct struct { On bool `thrift:"on,1" json:"on"` B int8 `thrift:"b,2" json:"b"` Int16 int16 `thrift:"int16,3" json:"int16"` Int32 int32 `thrift:"int32,4" json:"int32"` Int64 int64 `thrift:"int64,5" json:"int64"` D float64 `thrift:"d,6" json:"d"` St string `thrift:"st,7" json:"st"` Bin []byte `thrift:"bin,8" json:"bin"` StringMap map[string]string `thrift:"stringMap,9" json:"stringMap"` StringList []string `thrift:"stringList,10" json:"stringList"` StringSet map[string]struct{} `thrift:"stringSet,11" json:"stringSet"` E MyTestEnum `thrift:"e,12" json:"e"` } func NewMyTestStruct() *MyTestStruct { return &MyTestStruct{} } func (p *MyTestStruct) GetOn() bool { return p.On } func (p *MyTestStruct) GetB() int8 { return p.B } func (p *MyTestStruct) GetInt16() int16 { return p.Int16 } func (p *MyTestStruct) GetInt32() int32 { return p.Int32 } func (p *MyTestStruct) GetInt64() int64 { return p.Int64 } func (p *MyTestStruct) GetD() float64 { return p.D } func (p *MyTestStruct) GetSt() string { return p.St } func (p *MyTestStruct) GetBin() []byte { return p.Bin } func (p *MyTestStruct) GetStringMap() map[string]string { return p.StringMap } func (p *MyTestStruct) GetStringList() []string { return p.StringList } func (p *MyTestStruct) GetStringSet() map[string]struct{} { return p.StringSet } func (p *MyTestStruct) GetE() MyTestEnum { return p.E } func (p *MyTestStruct) Read(ctx context.Context, iprot TProtocol) error { if _, err := iprot.ReadStructBegin(ctx); err != nil { return PrependError(fmt.Sprintf("%T read error: ", p), err) } for { _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) if err != nil { return PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) } if fieldTypeId == STOP { break } switch fieldId { case 1: if err := p.readField1(ctx, iprot); err != nil { return err } case 2: if err := p.readField2(ctx, iprot); err != nil { return err } case 3: if err := p.readField3(ctx, iprot); err != nil { return err } case 4: if err := p.readField4(ctx, iprot); err != nil { return err } case 5: if err := p.readField5(ctx, iprot); err != nil { return err } case 6: if err := p.readField6(ctx, iprot); err != nil { return err } case 7: if err := p.readField7(ctx, iprot); err != nil { return err } case 8: if err := p.readField8(ctx, iprot); err != nil { return err } case 9: if err := p.readField9(ctx, iprot); err != nil { return err } case 10: if err := p.readField10(ctx, iprot); err != nil { return err } case 11: if err := p.readField11(ctx, iprot); err != nil { return err } case 12: if err := p.readField12(ctx, iprot); err != nil { return err } default: if err := iprot.Skip(ctx, fieldTypeId); err != nil { return err } } if err := iprot.ReadFieldEnd(ctx); err != nil { return err } } if err := iprot.ReadStructEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T read struct end error: ", p), err) } return nil } func (p *MyTestStruct) readField1(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadBool(ctx); err != nil { return PrependError("error reading field 1: ", err) } else { p.On = v } return nil } func (p *MyTestStruct) readField2(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadByte(ctx); err != nil { return PrependError("error reading field 2: ", err) } else { temp := int8(v) p.B = temp } return nil } func (p *MyTestStruct) readField3(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadI16(ctx); err != nil { return PrependError("error reading field 3: ", err) } else { p.Int16 = v } return nil } func (p *MyTestStruct) readField4(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadI32(ctx); err != nil { return PrependError("error reading field 4: ", err) } else { p.Int32 = v } return nil } func (p *MyTestStruct) readField5(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadI64(ctx); err != nil { return PrependError("error reading field 5: ", err) } else { p.Int64 = v } return nil } func (p *MyTestStruct) readField6(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadDouble(ctx); err != nil { return PrependError("error reading field 6: ", err) } else { p.D = v } return nil } func (p *MyTestStruct) readField7(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadString(ctx); err != nil { return PrependError("error reading field 7: ", err) } else { p.St = v } return nil } func (p *MyTestStruct) readField8(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadBinary(ctx); err != nil { return PrependError("error reading field 8: ", err) } else { p.Bin = v } return nil } func (p *MyTestStruct) readField9(ctx context.Context, iprot TProtocol) error { _, _, size, err := iprot.ReadMapBegin(ctx) if err != nil { return PrependError("error reading map begin: ", err) } tMap := make(map[string]string, size) p.StringMap = tMap for i := 0; i < size; i++ { var _key0 string if v, err := iprot.ReadString(ctx); err != nil { return PrependError("error reading field 0: ", err) } else { _key0 = v } var _val1 string if v, err := iprot.ReadString(ctx); err != nil { return PrependError("error reading field 0: ", err) } else { _val1 = v } p.StringMap[_key0] = _val1 } if err := iprot.ReadMapEnd(ctx); err != nil { return PrependError("error reading map end: ", err) } return nil } func (p *MyTestStruct) readField10(ctx context.Context, iprot TProtocol) error { _, size, err := iprot.ReadListBegin(ctx) if err != nil { return PrependError("error reading list begin: ", err) } tSlice := make([]string, 0, size) p.StringList = tSlice for i := 0; i < size; i++ { var _elem2 string if v, err := iprot.ReadString(ctx); err != nil { return PrependError("error reading field 0: ", err) } else { _elem2 = v } p.StringList = append(p.StringList, _elem2) } if err := iprot.ReadListEnd(ctx); err != nil { return PrependError("error reading list end: ", err) } return nil } func (p *MyTestStruct) readField11(ctx context.Context, iprot TProtocol) error { _, size, err := iprot.ReadSetBegin(ctx) if err != nil { return PrependError("error reading set begin: ", err) } tSet := make(map[string]struct{}, size) p.StringSet = tSet for i := 0; i < size; i++ { var _elem3 string if v, err := iprot.ReadString(ctx); err != nil { return PrependError("error reading field 0: ", err) } else { _elem3 = v } p.StringSet[_elem3] = struct{}{} } if err := iprot.ReadSetEnd(ctx); err != nil { return PrependError("error reading set end: ", err) } return nil } func (p *MyTestStruct) readField12(ctx context.Context, iprot TProtocol) error { if v, err := iprot.ReadI32(ctx); err != nil { return PrependError("error reading field 12: ", err) } else { temp := MyTestEnum(v) p.E = temp } return nil } func (p *MyTestStruct) Write(ctx context.Context, oprot TProtocol) error { if err := oprot.WriteStructBegin(ctx, "MyTestStruct"); err != nil { return PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) } if err := p.writeField1(ctx, oprot); err != nil { return err } if err := p.writeField2(ctx, oprot); err != nil { return err } if err := p.writeField3(ctx, oprot); err != nil { return err } if err := p.writeField4(ctx, oprot); err != nil { return err } if err := p.writeField5(ctx, oprot); err != nil { return err } if err := p.writeField6(ctx, oprot); err != nil { return err } if err := p.writeField7(ctx, oprot); err != nil { return err } if err := p.writeField8(ctx, oprot); err != nil { return err } if err := p.writeField9(ctx, oprot); err != nil { return err } if err := p.writeField10(ctx, oprot); err != nil { return err } if err := p.writeField11(ctx, oprot); err != nil { return err } if err := p.writeField12(ctx, oprot); err != nil { return err } if err := oprot.WriteFieldStop(ctx); err != nil { return PrependError("write field stop error: ", err) } if err := oprot.WriteStructEnd(ctx); err != nil { return PrependError("write struct stop error: ", err) } return nil } func (p *MyTestStruct) writeField1(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "on", BOOL, 1); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 1:on: ", p), err) } if err := oprot.WriteBool(ctx, bool(p.On)); err != nil { return PrependError(fmt.Sprintf("%T.on (1) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 1:on: ", p), err) } return err } func (p *MyTestStruct) writeField2(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "b", BYTE, 2); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) } if err := oprot.WriteByte(ctx, int8(p.B)); err != nil { return PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) } return err } func (p *MyTestStruct) writeField3(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "int16", I16, 3); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 3:int16: ", p), err) } if err := oprot.WriteI16(ctx, int16(p.Int16)); err != nil { return PrependError(fmt.Sprintf("%T.int16 (3) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 3:int16: ", p), err) } return err } func (p *MyTestStruct) writeField4(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "int32", I32, 4); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 4:int32: ", p), err) } if err := oprot.WriteI32(ctx, int32(p.Int32)); err != nil { return PrependError(fmt.Sprintf("%T.int32 (4) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 4:int32: ", p), err) } return err } func (p *MyTestStruct) writeField5(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "int64", I64, 5); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 5:int64: ", p), err) } if err := oprot.WriteI64(ctx, int64(p.Int64)); err != nil { return PrependError(fmt.Sprintf("%T.int64 (5) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 5:int64: ", p), err) } return err } func (p *MyTestStruct) writeField6(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "d", DOUBLE, 6); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 6:d: ", p), err) } if err := oprot.WriteDouble(ctx, float64(p.D)); err != nil { return PrependError(fmt.Sprintf("%T.d (6) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 6:d: ", p), err) } return err } func (p *MyTestStruct) writeField7(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "st", STRING, 7); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 7:st: ", p), err) } if err := oprot.WriteString(ctx, string(p.St)); err != nil { return PrependError(fmt.Sprintf("%T.st (7) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 7:st: ", p), err) } return err } func (p *MyTestStruct) writeField8(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "bin", STRING, 8); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 8:bin: ", p), err) } if err := oprot.WriteBinary(ctx, p.Bin); err != nil { return PrependError(fmt.Sprintf("%T.bin (8) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 8:bin: ", p), err) } return err } func (p *MyTestStruct) writeField9(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "stringMap", MAP, 9); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 9:stringMap: ", p), err) } if err := oprot.WriteMapBegin(ctx, STRING, STRING, len(p.StringMap)); err != nil { return PrependError("error writing map begin: ", err) } for k, v := range p.StringMap { if err := oprot.WriteString(ctx, string(k)); err != nil { return PrependError(fmt.Sprintf("%T. (0) field write error: ", p), err) } if err := oprot.WriteString(ctx, string(v)); err != nil { return PrependError(fmt.Sprintf("%T. (0) field write error: ", p), err) } } if err := oprot.WriteMapEnd(ctx); err != nil { return PrependError("error writing map end: ", err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 9:stringMap: ", p), err) } return err } func (p *MyTestStruct) writeField10(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "stringList", LIST, 10); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 10:stringList: ", p), err) } if err := oprot.WriteListBegin(ctx, STRING, len(p.StringList)); err != nil { return PrependError("error writing list begin: ", err) } for _, v := range p.StringList { if err := oprot.WriteString(ctx, string(v)); err != nil { return PrependError(fmt.Sprintf("%T. (0) field write error: ", p), err) } } if err := oprot.WriteListEnd(ctx); err != nil { return PrependError("error writing list end: ", err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 10:stringList: ", p), err) } return err } func (p *MyTestStruct) writeField11(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "stringSet", SET, 11); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 11:stringSet: ", p), err) } if err := oprot.WriteSetBegin(ctx, STRING, len(p.StringSet)); err != nil { return PrependError("error writing set begin: ", err) } for v := range p.StringSet { if err := oprot.WriteString(ctx, string(v)); err != nil { return PrependError(fmt.Sprintf("%T. (0) field write error: ", p), err) } } if err := oprot.WriteSetEnd(ctx); err != nil { return PrependError("error writing set end: ", err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 11:stringSet: ", p), err) } return err } func (p *MyTestStruct) writeField12(ctx context.Context, oprot TProtocol) (err error) { if err := oprot.WriteFieldBegin(ctx, "e", I32, 12); err != nil { return PrependError(fmt.Sprintf("%T write field begin error 12:e: ", p), err) } if err := oprot.WriteI32(ctx, int32(p.E)); err != nil { return PrependError(fmt.Sprintf("%T.e (12) field write error: ", p), err) } if err := oprot.WriteFieldEnd(ctx); err != nil { return PrependError(fmt.Sprintf("%T write field end error 12:e: ", p), err) } return err } func (p *MyTestStruct) String() string { if p == nil { return "" } return fmt.Sprintf("MyTestStruct(%+v)", *p) } thrift-0.19.0/lib/go/thrift/debug_protocol.go0000644000000000000000000004034614370300523021114 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "fmt" ) type TDebugProtocol struct { // Required. The actual TProtocol to do the read/write. Delegate TProtocol // Optional. The logger and prefix to log all the args/return values // from Delegate TProtocol calls. // // If Logger is nil, StdLogger using stdlib log package with os.Stderr // will be used. If disable logging is desired, set Logger to NopLogger // explicitly instead of leaving it as nil/unset. Logger Logger LogPrefix string // Optional. An TProtocol to duplicate everything read/written from Delegate. // // A typical use case of this is to use TSimpleJSONProtocol wrapping // TMemoryBuffer in a middleware to json logging requests/responses. // // This feature is not available from TDebugProtocolFactory. In order to // use it you have to construct TDebugProtocol directly, or set DuplicateTo // field after getting a TDebugProtocol from the factory. // // Deprecated: Please use TDuplicateToProtocol instead. DuplicateTo TProtocol } type TDebugProtocolFactory struct { Underlying TProtocolFactory LogPrefix string Logger Logger } // NewTDebugProtocolFactory creates a TDebugProtocolFactory. // // Deprecated: Please use NewTDebugProtocolFactoryWithLogger or the struct // itself instead. This version will use the default logger from standard // library. func NewTDebugProtocolFactory(underlying TProtocolFactory, logPrefix string) *TDebugProtocolFactory { return &TDebugProtocolFactory{ Underlying: underlying, LogPrefix: logPrefix, Logger: StdLogger(nil), } } // NewTDebugProtocolFactoryWithLogger creates a TDebugProtocolFactory. func NewTDebugProtocolFactoryWithLogger(underlying TProtocolFactory, logPrefix string, logger Logger) *TDebugProtocolFactory { return &TDebugProtocolFactory{ Underlying: underlying, LogPrefix: logPrefix, Logger: logger, } } func (t *TDebugProtocolFactory) GetProtocol(trans TTransport) TProtocol { return &TDebugProtocol{ Delegate: t.Underlying.GetProtocol(trans), LogPrefix: t.LogPrefix, Logger: fallbackLogger(t.Logger), } } func (tdp *TDebugProtocol) logf(format string, v ...interface{}) { fallbackLogger(tdp.Logger)(fmt.Sprintf(format, v...)) } func (tdp *TDebugProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { err := tdp.Delegate.WriteMessageBegin(ctx, name, typeId, seqid) tdp.logf("%sWriteMessageBegin(name=%#v, typeId=%#v, seqid=%#v) => %#v", tdp.LogPrefix, name, typeId, seqid, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid) } return err } func (tdp *TDebugProtocol) WriteMessageEnd(ctx context.Context) error { err := tdp.Delegate.WriteMessageEnd(ctx) tdp.logf("%sWriteMessageEnd() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMessageEnd(ctx) } return err } func (tdp *TDebugProtocol) WriteStructBegin(ctx context.Context, name string) error { err := tdp.Delegate.WriteStructBegin(ctx, name) tdp.logf("%sWriteStructBegin(name=%#v) => %#v", tdp.LogPrefix, name, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteStructBegin(ctx, name) } return err } func (tdp *TDebugProtocol) WriteStructEnd(ctx context.Context) error { err := tdp.Delegate.WriteStructEnd(ctx) tdp.logf("%sWriteStructEnd() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteStructEnd(ctx) } return err } func (tdp *TDebugProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { err := tdp.Delegate.WriteFieldBegin(ctx, name, typeId, id) tdp.logf("%sWriteFieldBegin(name=%#v, typeId=%#v, id%#v) => %#v", tdp.LogPrefix, name, typeId, id, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id) } return err } func (tdp *TDebugProtocol) WriteFieldEnd(ctx context.Context) error { err := tdp.Delegate.WriteFieldEnd(ctx) tdp.logf("%sWriteFieldEnd() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteFieldEnd(ctx) } return err } func (tdp *TDebugProtocol) WriteFieldStop(ctx context.Context) error { err := tdp.Delegate.WriteFieldStop(ctx) tdp.logf("%sWriteFieldStop() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteFieldStop(ctx) } return err } func (tdp *TDebugProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { err := tdp.Delegate.WriteMapBegin(ctx, keyType, valueType, size) tdp.logf("%sWriteMapBegin(keyType=%#v, valueType=%#v, size=%#v) => %#v", tdp.LogPrefix, keyType, valueType, size, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size) } return err } func (tdp *TDebugProtocol) WriteMapEnd(ctx context.Context) error { err := tdp.Delegate.WriteMapEnd(ctx) tdp.logf("%sWriteMapEnd() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMapEnd(ctx) } return err } func (tdp *TDebugProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { err := tdp.Delegate.WriteListBegin(ctx, elemType, size) tdp.logf("%sWriteListBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteListBegin(ctx, elemType, size) } return err } func (tdp *TDebugProtocol) WriteListEnd(ctx context.Context) error { err := tdp.Delegate.WriteListEnd(ctx) tdp.logf("%sWriteListEnd() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteListEnd(ctx) } return err } func (tdp *TDebugProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { err := tdp.Delegate.WriteSetBegin(ctx, elemType, size) tdp.logf("%sWriteSetBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteSetBegin(ctx, elemType, size) } return err } func (tdp *TDebugProtocol) WriteSetEnd(ctx context.Context) error { err := tdp.Delegate.WriteSetEnd(ctx) tdp.logf("%sWriteSetEnd() => %#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteSetEnd(ctx) } return err } func (tdp *TDebugProtocol) WriteBool(ctx context.Context, value bool) error { err := tdp.Delegate.WriteBool(ctx, value) tdp.logf("%sWriteBool(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteBool(ctx, value) } return err } func (tdp *TDebugProtocol) WriteByte(ctx context.Context, value int8) error { err := tdp.Delegate.WriteByte(ctx, value) tdp.logf("%sWriteByte(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteByte(ctx, value) } return err } func (tdp *TDebugProtocol) WriteI16(ctx context.Context, value int16) error { err := tdp.Delegate.WriteI16(ctx, value) tdp.logf("%sWriteI16(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteI16(ctx, value) } return err } func (tdp *TDebugProtocol) WriteI32(ctx context.Context, value int32) error { err := tdp.Delegate.WriteI32(ctx, value) tdp.logf("%sWriteI32(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteI32(ctx, value) } return err } func (tdp *TDebugProtocol) WriteI64(ctx context.Context, value int64) error { err := tdp.Delegate.WriteI64(ctx, value) tdp.logf("%sWriteI64(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteI64(ctx, value) } return err } func (tdp *TDebugProtocol) WriteDouble(ctx context.Context, value float64) error { err := tdp.Delegate.WriteDouble(ctx, value) tdp.logf("%sWriteDouble(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteDouble(ctx, value) } return err } func (tdp *TDebugProtocol) WriteString(ctx context.Context, value string) error { err := tdp.Delegate.WriteString(ctx, value) tdp.logf("%sWriteString(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteString(ctx, value) } return err } func (tdp *TDebugProtocol) WriteBinary(ctx context.Context, value []byte) error { err := tdp.Delegate.WriteBinary(ctx, value) tdp.logf("%sWriteBinary(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteBinary(ctx, value) } return err } func (tdp *TDebugProtocol) WriteUUID(ctx context.Context, value Tuuid) error { err := tdp.Delegate.WriteUUID(ctx, value) tdp.logf("%sWriteUUID(value=%#v) => %#v", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteUUID(ctx, value) } return err } func (tdp *TDebugProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) { name, typeId, seqid, err = tdp.Delegate.ReadMessageBegin(ctx) tdp.logf("%sReadMessageBegin() (name=%#v, typeId=%#v, seqid=%#v, err=%#v)", tdp.LogPrefix, name, typeId, seqid, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid) } return } func (tdp *TDebugProtocol) ReadMessageEnd(ctx context.Context) (err error) { err = tdp.Delegate.ReadMessageEnd(ctx) tdp.logf("%sReadMessageEnd() err=%#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMessageEnd(ctx) } return } func (tdp *TDebugProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { name, err = tdp.Delegate.ReadStructBegin(ctx) tdp.logf("%sReadStructBegin() (name%#v, err=%#v)", tdp.LogPrefix, name, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteStructBegin(ctx, name) } return } func (tdp *TDebugProtocol) ReadStructEnd(ctx context.Context) (err error) { err = tdp.Delegate.ReadStructEnd(ctx) tdp.logf("%sReadStructEnd() err=%#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteStructEnd(ctx) } return } func (tdp *TDebugProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) { name, typeId, id, err = tdp.Delegate.ReadFieldBegin(ctx) tdp.logf("%sReadFieldBegin() (name=%#v, typeId=%#v, id=%#v, err=%#v)", tdp.LogPrefix, name, typeId, id, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id) } return } func (tdp *TDebugProtocol) ReadFieldEnd(ctx context.Context) (err error) { err = tdp.Delegate.ReadFieldEnd(ctx) tdp.logf("%sReadFieldEnd() err=%#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteFieldEnd(ctx) } return } func (tdp *TDebugProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { keyType, valueType, size, err = tdp.Delegate.ReadMapBegin(ctx) tdp.logf("%sReadMapBegin() (keyType=%#v, valueType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, keyType, valueType, size, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size) } return } func (tdp *TDebugProtocol) ReadMapEnd(ctx context.Context) (err error) { err = tdp.Delegate.ReadMapEnd(ctx) tdp.logf("%sReadMapEnd() err=%#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteMapEnd(ctx) } return } func (tdp *TDebugProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { elemType, size, err = tdp.Delegate.ReadListBegin(ctx) tdp.logf("%sReadListBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteListBegin(ctx, elemType, size) } return } func (tdp *TDebugProtocol) ReadListEnd(ctx context.Context) (err error) { err = tdp.Delegate.ReadListEnd(ctx) tdp.logf("%sReadListEnd() err=%#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteListEnd(ctx) } return } func (tdp *TDebugProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { elemType, size, err = tdp.Delegate.ReadSetBegin(ctx) tdp.logf("%sReadSetBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteSetBegin(ctx, elemType, size) } return } func (tdp *TDebugProtocol) ReadSetEnd(ctx context.Context) (err error) { err = tdp.Delegate.ReadSetEnd(ctx) tdp.logf("%sReadSetEnd() err=%#v", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteSetEnd(ctx) } return } func (tdp *TDebugProtocol) ReadBool(ctx context.Context) (value bool, err error) { value, err = tdp.Delegate.ReadBool(ctx) tdp.logf("%sReadBool() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteBool(ctx, value) } return } func (tdp *TDebugProtocol) ReadByte(ctx context.Context) (value int8, err error) { value, err = tdp.Delegate.ReadByte(ctx) tdp.logf("%sReadByte() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteByte(ctx, value) } return } func (tdp *TDebugProtocol) ReadI16(ctx context.Context) (value int16, err error) { value, err = tdp.Delegate.ReadI16(ctx) tdp.logf("%sReadI16() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteI16(ctx, value) } return } func (tdp *TDebugProtocol) ReadI32(ctx context.Context) (value int32, err error) { value, err = tdp.Delegate.ReadI32(ctx) tdp.logf("%sReadI32() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteI32(ctx, value) } return } func (tdp *TDebugProtocol) ReadI64(ctx context.Context) (value int64, err error) { value, err = tdp.Delegate.ReadI64(ctx) tdp.logf("%sReadI64() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteI64(ctx, value) } return } func (tdp *TDebugProtocol) ReadDouble(ctx context.Context) (value float64, err error) { value, err = tdp.Delegate.ReadDouble(ctx) tdp.logf("%sReadDouble() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteDouble(ctx, value) } return } func (tdp *TDebugProtocol) ReadString(ctx context.Context) (value string, err error) { value, err = tdp.Delegate.ReadString(ctx) tdp.logf("%sReadString() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteString(ctx, value) } return } func (tdp *TDebugProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { value, err = tdp.Delegate.ReadBinary(ctx) tdp.logf("%sReadBinary() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteBinary(ctx, value) } return } func (tdp *TDebugProtocol) ReadUUID(ctx context.Context) (value Tuuid, err error) { value, err = tdp.Delegate.ReadUUID(ctx) tdp.logf("%sReadUUID() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.WriteUUID(ctx, value) } return } func (tdp *TDebugProtocol) Skip(ctx context.Context, fieldType TType) (err error) { err = tdp.Delegate.Skip(ctx, fieldType) tdp.logf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.Skip(ctx, fieldType) } return } func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) { err = tdp.Delegate.Flush(ctx) tdp.logf("%sFlush() (err=%#v)", tdp.LogPrefix, err) if tdp.DuplicateTo != nil { tdp.DuplicateTo.Flush(ctx) } return } func (tdp *TDebugProtocol) Transport() TTransport { return tdp.Delegate.Transport() } // SetTConfiguration implements TConfigurationSetter for propagation. func (tdp *TDebugProtocol) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(tdp.Delegate, conf) PropagateTConfiguration(tdp.DuplicateTo, conf) } var _ TConfigurationSetter = (*TDebugProtocol)(nil) thrift-0.19.0/lib/go/thrift/example_processor_middleware_test.go0000644000000000000000000000336614303740367025106 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "log" ) func SimpleProcessorLoggingMiddleware(name string, next TProcessorFunction) TProcessorFunction { return WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { log.Printf("Before: %q", name) success, err := next.Process(ctx, seqId, in, out) log.Printf("After: %q", name) log.Printf("Success: %v", success) if err != nil { log.Printf("Error: %v", err) } return success, err }, } } // This example demonstrates how to define and use a simple logging middleware // to your thrift server/processor. func ExampleProcessorMiddleware() { var ( processor TProcessor trans TServerTransport transFactory TTransportFactory protoFactory TProtocolFactory ) processor = WrapProcessor(processor, SimpleProcessorLoggingMiddleware) server := NewTSimpleServer4(processor, trans, transFactory, protoFactory) log.Fatal(server.Serve()) } thrift-0.19.0/lib/go/thrift/framed_transport.go0000644000000000000000000001455314303740367021472 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bufio" "bytes" "context" "encoding/binary" "fmt" "io" ) // Deprecated: Use DEFAULT_MAX_FRAME_SIZE instead. const DEFAULT_MAX_LENGTH = 16384000 type TFramedTransport struct { transport TTransport cfg *TConfiguration writeBuf *bytes.Buffer reader *bufio.Reader readBuf *bytes.Buffer buffer [4]byte } type tFramedTransportFactory struct { factory TTransportFactory cfg *TConfiguration } // Deprecated: Use NewTFramedTransportFactoryConf instead. func NewTFramedTransportFactory(factory TTransportFactory) TTransportFactory { return NewTFramedTransportFactoryConf(factory, &TConfiguration{ MaxFrameSize: DEFAULT_MAX_LENGTH, noPropagation: true, }) } // Deprecated: Use NewTFramedTransportFactoryConf instead. func NewTFramedTransportFactoryMaxLength(factory TTransportFactory, maxLength uint32) TTransportFactory { return NewTFramedTransportFactoryConf(factory, &TConfiguration{ MaxFrameSize: int32(maxLength), noPropagation: true, }) } func NewTFramedTransportFactoryConf(factory TTransportFactory, conf *TConfiguration) TTransportFactory { PropagateTConfiguration(factory, conf) return &tFramedTransportFactory{ factory: factory, cfg: conf, } } func (p *tFramedTransportFactory) GetTransport(base TTransport) (TTransport, error) { PropagateTConfiguration(base, p.cfg) tt, err := p.factory.GetTransport(base) if err != nil { return nil, err } return NewTFramedTransportConf(tt, p.cfg), nil } func (p *tFramedTransportFactory) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(p.factory, cfg) p.cfg = cfg } // Deprecated: Use NewTFramedTransportConf instead. func NewTFramedTransport(transport TTransport) *TFramedTransport { return NewTFramedTransportConf(transport, &TConfiguration{ MaxFrameSize: DEFAULT_MAX_LENGTH, noPropagation: true, }) } // Deprecated: Use NewTFramedTransportConf instead. func NewTFramedTransportMaxLength(transport TTransport, maxLength uint32) *TFramedTransport { return NewTFramedTransportConf(transport, &TConfiguration{ MaxFrameSize: int32(maxLength), noPropagation: true, }) } func NewTFramedTransportConf(transport TTransport, conf *TConfiguration) *TFramedTransport { PropagateTConfiguration(transport, conf) return &TFramedTransport{ transport: transport, reader: bufio.NewReader(transport), cfg: conf, } } func (p *TFramedTransport) Open() error { return p.transport.Open() } func (p *TFramedTransport) IsOpen() bool { return p.transport.IsOpen() } func (p *TFramedTransport) Close() error { return p.transport.Close() } func (p *TFramedTransport) Read(buf []byte) (read int, err error) { defer func() { // Make sure we return the read buffer back to pool // after we finished reading from it. if p.readBuf != nil && p.readBuf.Len() == 0 { bufPool.put(&p.readBuf) } }() if p.readBuf != nil { read, err = p.readBuf.Read(buf) if err != io.EOF { return } // For bytes.Buffer.Read, EOF would only happen when read is zero, // but still, do a sanity check, // in case that behavior is changed in a future version of go stdlib. // When that happens, just return nil error, // and let the caller call Read again to read the next frame. if read > 0 { return read, nil } } // Reaching here means that the last Read finished the last frame, // so we need to read the next frame into readBuf now. if err = p.readFrame(); err != nil { return read, err } newRead, err := p.Read(buf[read:]) return read + newRead, err } func (p *TFramedTransport) ReadByte() (c byte, err error) { buf := p.buffer[:1] _, err = p.Read(buf) if err != nil { return } c = buf[0] return } func (p *TFramedTransport) ensureWriteBufferBeforeWrite() { if p.writeBuf == nil { p.writeBuf = bufPool.get() } } func (p *TFramedTransport) Write(buf []byte) (int, error) { p.ensureWriteBufferBeforeWrite() n, err := p.writeBuf.Write(buf) return n, NewTTransportExceptionFromError(err) } func (p *TFramedTransport) WriteByte(c byte) error { p.ensureWriteBufferBeforeWrite() return p.writeBuf.WriteByte(c) } func (p *TFramedTransport) WriteString(s string) (n int, err error) { p.ensureWriteBufferBeforeWrite() return p.writeBuf.WriteString(s) } func (p *TFramedTransport) Flush(ctx context.Context) error { defer bufPool.put(&p.writeBuf) size := p.writeBuf.Len() buf := p.buffer[:4] binary.BigEndian.PutUint32(buf, uint32(size)) _, err := p.transport.Write(buf) if err != nil { return NewTTransportExceptionFromError(err) } if size > 0 { if _, err := io.Copy(p.transport, p.writeBuf); err != nil { return NewTTransportExceptionFromError(err) } } err = p.transport.Flush(ctx) return NewTTransportExceptionFromError(err) } func (p *TFramedTransport) readFrame() error { if p.readBuf != nil { bufPool.put(&p.readBuf) } p.readBuf = bufPool.get() buf := p.buffer[:4] if _, err := io.ReadFull(p.reader, buf); err != nil { return err } size := binary.BigEndian.Uint32(buf) if size > uint32(p.cfg.GetMaxFrameSize()) { return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, fmt.Sprintf("Incorrect frame size (%d)", size)) } _, err := io.CopyN(p.readBuf, p.reader, int64(size)) return NewTTransportExceptionFromError(err) } func (p *TFramedTransport) RemainingBytes() (num_bytes uint64) { if p.readBuf == nil { return 0 } return uint64(p.readBuf.Len()) } // SetTConfiguration implements TConfigurationSetter. func (p *TFramedTransport) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(p.transport, cfg) p.cfg = cfg } var ( _ TConfigurationSetter = (*tFramedTransportFactory)(nil) _ TConfigurationSetter = (*TFramedTransport)(nil) ) thrift-0.19.0/lib/go/thrift/framed_transport_test.go0000644000000000000000000000537114303740367022527 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "io" "strings" "testing" "testing/iotest" ) func TestFramedTransport(t *testing.T) { trans := NewTFramedTransport(NewTMemoryBuffer()) TransportTest(t, trans, trans) } func TestTFramedTransportReuseTransport(t *testing.T) { const ( content = "Hello, world!" n = 10 ) trans := NewTMemoryBuffer() reader := NewTFramedTransport(trans) writer := NewTFramedTransport(trans) t.Run("pair", func(t *testing.T) { for i := 0; i < n; i++ { // write if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { t.Fatalf("Failed to write on #%d: %v", i, err) } if err := writer.Flush(context.Background()); err != nil { t.Fatalf("Failed to flush on #%d: %v", i, err) } // read read, err := io.ReadAll(iotest.OneByteReader(reader)) if err != nil { t.Errorf("Failed to read on #%d: %v", i, err) } if string(read) != content { t.Errorf("Read #%d: want %q, got %q", i, content, read) } } }) t.Run("batched", func(t *testing.T) { // write for i := 0; i < n; i++ { if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { t.Fatalf("Failed to write on #%d: %v", i, err) } if err := writer.Flush(context.Background()); err != nil { t.Fatalf("Failed to flush on #%d: %v", i, err) } } // read for i := 0; i < n; i++ { const ( size = len(content) ) var buf []byte var err error if i%2 == 0 { // on even calls, use OneByteReader to make // sure that small reads are fine buf, err = io.ReadAll(io.LimitReader(iotest.OneByteReader(reader), int64(size))) } else { // on odd calls, make sure that we don't read // more than written per frame buf = make([]byte, size*2) var n int n, err = reader.Read(buf) buf = buf[:n] } if err != nil { t.Errorf("Failed to read on #%d: %v", i, err) } if string(buf) != content { t.Errorf("Read #%d: want %q, got %q", i, content, buf) } } }) } thrift-0.19.0/lib/go/thrift/socket_conn_test.go0000644000000000000000000000526114303740367021460 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "io" "net" "strings" "testing" "time" ) type serverSocketConnCallback func(testing.TB, *socketConn) func serverSocketConn(tb testing.TB, f serverSocketConnCallback) (net.Listener, error) { tb.Helper() ln, err := net.Listen("tcp", "localhost:0") if err != nil { return nil, err } go func() { for { sc, err := createSocketConnFromReturn(ln.Accept()) if err != nil { // This is usually caused by Listener being // closed, not really an error. return } go f(tb, sc) } }() return ln, nil } func writeFully(tb testing.TB, w io.Writer, s string) bool { tb.Helper() n, err := io.Copy(w, strings.NewReader(s)) if err != nil { tb.Errorf("Failed to write %q: %v", s, err) return false } if int(n) < len(s) { tb.Errorf("Only wrote %d out of %q", n, s) return false } return true } func TestSocketConn(t *testing.T) { const ( interval = time.Millisecond * 10 first = "hello" second = "world" ) ln, err := serverSocketConn( t, func(tb testing.TB, sc *socketConn) { defer sc.Close() if !writeFully(tb, sc, first) { return } time.Sleep(interval) writeFully(tb, sc, second) }, ) if err != nil { t.Fatal(err) } defer ln.Close() sc, err := createSocketConnFromReturn(net.Dial("tcp", ln.Addr().String())) if err != nil { t.Fatal(err) } buf := make([]byte, 1024) n, err := sc.Read(buf) if err != nil { t.Fatal(err) } read := string(buf[:n]) if read != first { t.Errorf("Expected read %q, got %q", first, read) } n, err = sc.Read(buf) if err != nil { t.Fatal(err) } read = string(buf[:n]) if read != second { t.Errorf("Expected read %q, got %q", second, read) } } func TestSocketConnNilSafe(t *testing.T) { sc := (*socketConn)(nil) if sc.isValid() { t.Error("Expected false for nil.isValid(), got true") } if sc.IsOpen() { t.Error("Expected false for nil.IsOpen(), got true") } } thrift-0.19.0/lib/go/thrift/uuid.go0000644000000000000000000000701414370300523017046 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "encoding/hex" "fmt" ) // Tuuid is a minimal implementation of UUID for thrift's read/write operations. // // This implementation only covers read/write in various thrift protocols. // If you need to generate/manipulate/etc. an UUID, // you likely would need a third party UUID library instead. // // This type should be directly cast-able with most popular third party UUID // libraries. // For example, assuming you are using // https://pkg.go.dev/github.com/google/uuid to generate a v4 UUID for an // optional thrift field: // // id, err := uuid.NewRandom() // if err != nil { // // TODO: handle errors // } // myRequest.Uuid = thrift.Pointer(thrift.Tuuid(id)) type Tuuid [16]byte // String generates the canonical form string for an Tuuid. // // This string is suitable for writing with TJSONProtocol. func (u Tuuid) String() string { var buf [36]byte hex.Encode(buf[0:], u[:4]) buf[8] = '-' hex.Encode(buf[9:], u[4:6]) buf[13] = '-' hex.Encode(buf[14:], u[6:8]) buf[18] = '-' hex.Encode(buf[19:], u[8:10]) buf[23] = '-' hex.Encode(buf[24:], u[10:]) return string(buf[:]) } func hexToDec(b byte) (byte, bool) { switch { case b >= '0' && b <= '9': return b - '0', true case b >= 'a' && b <= 'f': return b - 'a' + 10, true case b >= 'A' && b <= 'F': return b - 'A' + 10, true default: return 0, false } } func hexToByte(b1, b2 byte) (b byte, ok bool) { b1, ok = hexToDec(b1) if !ok { return 0, ok } b2, ok = hexToDec(b2) if !ok { return 0, ok } return b1<<4 + b2, true } // ParseTuuid parses a canonical form UUID string into Tuuid. // // Note that this function only supports case insensitive canonical form // (8-4-4-4-12/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx), // and rejects any other forms. // For a more flexible UUID string parser, // please use third party UUID libraries. // // This function is suitable for reading with TJSONProtocol. func ParseTuuid(s string) (u Tuuid, err error) { if len(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' { return u, fmt.Errorf("malformed Tuuid string: %q", s) } var ok bool for i, j := range []int{ 0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34, } { u[i], ok = hexToByte(s[j], s[j+1]) if !ok { return u, fmt.Errorf("malformed Tuuid string: %q", s) } } return u, nil } // Must is a sugar to be used in places that error handling is impossible (for // example, global variable declarations) and also errors are not in general // expected. // // This is an example to use Must with ParseTuuid to declare a global special // uuid: // // var NameSpaceDNSUUID = thrift.Must(thrift.ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) func Must[T any](v T, err error) T { if err != nil { panic(err) } return v } thrift-0.19.0/lib/go/thrift/socket_unix_conn.go0000644000000000000000000000422614303740367021464 0ustar00rootroot00000000000000//go:build !windows && !wasm // +build !windows,!wasm /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "io" "syscall" "time" ) // We rely on this variable to be the zero time, // but define it as global variable to avoid repetitive allocations. // Please DO NOT mutate this variable in any way. var zeroTime time.Time func (sc *socketConn) read0() error { return sc.checkConn() } func (sc *socketConn) checkConn() error { syscallConn, ok := sc.Conn.(syscall.Conn) if !ok { // No way to check, return nil return nil } // The reading about to be done here is non-blocking so we don't really // need a read deadline. We just need to clear the previously set read // deadline, if any. sc.Conn.SetReadDeadline(zeroTime) rc, err := syscallConn.SyscallConn() if err != nil { return err } var n int if readErr := rc.Read(func(fd uintptr) bool { n, _, err = syscall.Recvfrom(int(fd), sc.buffer[:], syscall.MSG_PEEK|syscall.MSG_DONTWAIT) return true }); readErr != nil { return readErr } if n > 0 { // We got something, which means we are good return nil } if errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EWOULDBLOCK) { // This means the connection is still open but we don't have // anything to read right now. return nil } if err != nil { return err } // At this point, it means the other side already closed the connection. return io.EOF } thrift-0.19.0/lib/go/thrift/socket.go0000644000000000000000000001415314303740367017404 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "net" "time" ) type TSocket struct { conn *socketConn addr net.Addr cfg *TConfiguration } // tcpAddr is a naive implementation of net.Addr that does nothing extra. type tcpAddr string var _ net.Addr = tcpAddr("") func (ta tcpAddr) Network() string { return "tcp" } func (ta tcpAddr) String() string { return string(ta) } // Deprecated: Use NewTSocketConf instead. func NewTSocket(hostPort string) (*TSocket, error) { return NewTSocketConf(hostPort, &TConfiguration{ noPropagation: true, }), nil } // NewTSocketConf creates a net.Conn-backed TTransport, given a host and port. // // Example: // // trans, err := thrift.NewTSocketConf("localhost:9090", &TConfiguration{ // ConnectTimeout: time.Second, // Use 0 for no timeout // SocketTimeout: time.Second, // Use 0 for no timeout // }) func NewTSocketConf(hostPort string, conf *TConfiguration) *TSocket { return NewTSocketFromAddrConf(tcpAddr(hostPort), conf) } // Deprecated: Use NewTSocketConf instead. func NewTSocketTimeout(hostPort string, connTimeout time.Duration, soTimeout time.Duration) (*TSocket, error) { return NewTSocketConf(hostPort, &TConfiguration{ ConnectTimeout: connTimeout, SocketTimeout: soTimeout, noPropagation: true, }), nil } // NewTSocketFromAddrConf creates a TSocket from a net.Addr func NewTSocketFromAddrConf(addr net.Addr, conf *TConfiguration) *TSocket { return &TSocket{ addr: addr, cfg: conf, } } // Deprecated: Use NewTSocketFromAddrConf instead. func NewTSocketFromAddrTimeout(addr net.Addr, connTimeout time.Duration, soTimeout time.Duration) *TSocket { return NewTSocketFromAddrConf(addr, &TConfiguration{ ConnectTimeout: connTimeout, SocketTimeout: soTimeout, noPropagation: true, }) } // NewTSocketFromConnConf creates a TSocket from an existing net.Conn. func NewTSocketFromConnConf(conn net.Conn, conf *TConfiguration) *TSocket { return &TSocket{ conn: wrapSocketConn(conn), addr: conn.RemoteAddr(), cfg: conf, } } // Deprecated: Use NewTSocketFromConnConf instead. func NewTSocketFromConnTimeout(conn net.Conn, socketTimeout time.Duration) *TSocket { return NewTSocketFromConnConf(conn, &TConfiguration{ SocketTimeout: socketTimeout, noPropagation: true, }) } // SetTConfiguration implements TConfigurationSetter. // // It can be used to set connect and socket timeouts. func (p *TSocket) SetTConfiguration(conf *TConfiguration) { p.cfg = conf } // Sets the connect timeout func (p *TSocket) SetConnTimeout(timeout time.Duration) error { if p.cfg == nil { p.cfg = &TConfiguration{ noPropagation: true, } } p.cfg.ConnectTimeout = timeout return nil } // Sets the socket timeout func (p *TSocket) SetSocketTimeout(timeout time.Duration) error { if p.cfg == nil { p.cfg = &TConfiguration{ noPropagation: true, } } p.cfg.SocketTimeout = timeout return nil } func (p *TSocket) pushDeadline(read, write bool) { var t time.Time if timeout := p.cfg.GetSocketTimeout(); timeout > 0 { t = time.Now().Add(time.Duration(timeout)) } if read && write { p.conn.SetDeadline(t) } else if read { p.conn.SetReadDeadline(t) } else if write { p.conn.SetWriteDeadline(t) } } // Connects the socket, creating a new socket object if necessary. func (p *TSocket) Open() error { if p.conn.isValid() { return NewTTransportException(ALREADY_OPEN, "Socket already connected.") } if p.addr == nil { return NewTTransportException(NOT_OPEN, "Cannot open nil address.") } if len(p.addr.Network()) == 0 { return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") } if len(p.addr.String()) == 0 { return NewTTransportException(NOT_OPEN, "Cannot open bad address.") } var err error if p.conn, err = createSocketConnFromReturn(net.DialTimeout( p.addr.Network(), p.addr.String(), p.cfg.GetConnectTimeout(), )); err != nil { return &tTransportException{ typeId: NOT_OPEN, err: err, msg: err.Error(), } } p.addr = p.conn.RemoteAddr() return nil } // Retrieve the underlying net.Conn func (p *TSocket) Conn() net.Conn { return p.conn } // Returns true if the connection is open func (p *TSocket) IsOpen() bool { return p.conn.IsOpen() } // Closes the socket. func (p *TSocket) Close() error { return p.conn.Close() } //Returns the remote address of the socket. func (p *TSocket) Addr() net.Addr { return p.addr } func (p *TSocket) Read(buf []byte) (int, error) { if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(true, false) // NOTE: Calling any of p.IsOpen, p.conn.read0, or p.conn.IsOpen between // p.pushDeadline and p.conn.Read could cause the deadline set inside // p.pushDeadline being reset, thus need to be avoided. n, err := p.conn.Read(buf) return n, NewTTransportExceptionFromError(err) } func (p *TSocket) Write(buf []byte) (int, error) { if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(false, true) return p.conn.Write(buf) } func (p *TSocket) Flush(ctx context.Context) error { return nil } func (p *TSocket) Interrupt() error { if !p.conn.isValid() { return nil } return p.conn.Close() } func (p *TSocket) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } var _ TConfigurationSetter = (*TSocket)(nil) thrift-0.19.0/lib/go/thrift/socket_unix_conn_test.go0000644000000000000000000000461114303740367022521 0ustar00rootroot00000000000000// +build !windows /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "io" "net" "testing" "time" ) func TestSocketConnUnix(t *testing.T) { const ( interval = time.Millisecond * 10 first = "hello" second = "world" ) ln, err := serverSocketConn( t, func(tb testing.TB, sc *socketConn) { defer sc.Close() time.Sleep(interval) if !writeFully(tb, sc, first) { return } time.Sleep(interval) writeFully(tb, sc, second) }, ) if err != nil { t.Fatal(err) } defer ln.Close() sc, err := createSocketConnFromReturn(net.Dial("tcp", ln.Addr().String())) if err != nil { t.Fatal(err) } buf := make([]byte, 1024) if !sc.IsOpen() { t.Error("Expected sc to report open, got false") } n, err := sc.Read(buf) if err != nil { t.Fatal(err) } read := string(buf[:n]) if read != first { t.Errorf("Expected read %q, got %q", first, read) } if !sc.IsOpen() { t.Error("Expected sc to report open, got false") } // Do connection check again twice after server already wrote new data, // make sure we don't cause any data loss with the check. time.Sleep(interval * 10) if !sc.IsOpen() { t.Error("Expected sc to report open, got false") } if !sc.IsOpen() { t.Error("Expected sc to report open, got false") } n, err = sc.Read(buf) if err != nil { t.Fatal(err) } read = string(buf[:n]) if read != second { t.Errorf("Expected read %q, got %q", second, read) } // Now it's supposed to be closed on the server side if err := sc.read0(); err != io.EOF { t.Errorf("Expected to get EOF on read0, got %v", err) } if sc.IsOpen() { t.Error("Expected sc to report not open, got true") } } thrift-0.19.0/lib/go/thrift/transport_factory.go0000644000000000000000000000263014303740367021674 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Factory class used to create wrapped instance of Transports. // This is used primarily in servers, which get Transports from // a ServerTransport and then may want to mutate them (i.e. create // a BufferedTransport from the underlying base transport) type TTransportFactory interface { GetTransport(trans TTransport) (TTransport, error) } type tTransportFactory struct{} // Return a wrapped instance of the base Transport. func (p *tTransportFactory) GetTransport(trans TTransport) (TTransport, error) { return trans, nil } func NewTTransportFactory() TTransportFactory { return &tTransportFactory{} } thrift-0.19.0/lib/go/thrift/server.go0000644000000000000000000000237014303740367017420 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift type TServer interface { ProcessorFactory() TProcessorFactory ServerTransport() TServerTransport InputTransportFactory() TTransportFactory OutputTransportFactory() TTransportFactory InputProtocolFactory() TProtocolFactory OutputProtocolFactory() TProtocolFactory // Starts the server Serve() error // Stops the server. This is optional on a per-implementation basis. Not // all servers are required to be cleanly stoppable. Stop() error } thrift-0.19.0/lib/go/thrift/ssl_socket.go0000644000000000000000000001567614303740367020300 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "crypto/tls" "net" "time" ) type TSSLSocket struct { conn *socketConn // hostPort contains host:port (e.g. "asdf.com:12345"). The field is // only valid if addr is nil. hostPort string // addr is nil when hostPort is not "", and is only used when the // TSSLSocket is constructed from a net.Addr. addr net.Addr cfg *TConfiguration } // NewTSSLSocketConf creates a net.Conn-backed TTransport, given a host and port. // // Example: // // trans := thrift.NewTSSLSocketConf("localhost:9090", &TConfiguration{ // ConnectTimeout: time.Second, // Use 0 for no timeout // SocketTimeout: time.Second, // Use 0 for no timeout // // TLSConfig: &tls.Config{ // // Fill in tls config here. // } // }) func NewTSSLSocketConf(hostPort string, conf *TConfiguration) *TSSLSocket { if cfg := conf.GetTLSConfig(); cfg != nil && cfg.MinVersion == 0 { cfg.MinVersion = tls.VersionTLS10 } return &TSSLSocket{ hostPort: hostPort, cfg: conf, } } // Deprecated: Use NewTSSLSocketConf instead. func NewTSSLSocket(hostPort string, cfg *tls.Config) (*TSSLSocket, error) { return NewTSSLSocketConf(hostPort, &TConfiguration{ TLSConfig: cfg, noPropagation: true, }), nil } // Deprecated: Use NewTSSLSocketConf instead. func NewTSSLSocketTimeout(hostPort string, cfg *tls.Config, connectTimeout, socketTimeout time.Duration) (*TSSLSocket, error) { return NewTSSLSocketConf(hostPort, &TConfiguration{ ConnectTimeout: connectTimeout, SocketTimeout: socketTimeout, TLSConfig: cfg, noPropagation: true, }), nil } // NewTSSLSocketFromAddrConf creates a TSSLSocket from a net.Addr. func NewTSSLSocketFromAddrConf(addr net.Addr, conf *TConfiguration) *TSSLSocket { return &TSSLSocket{ addr: addr, cfg: conf, } } // Deprecated: Use NewTSSLSocketFromAddrConf instead. func NewTSSLSocketFromAddrTimeout(addr net.Addr, cfg *tls.Config, connectTimeout, socketTimeout time.Duration) *TSSLSocket { return NewTSSLSocketFromAddrConf(addr, &TConfiguration{ ConnectTimeout: connectTimeout, SocketTimeout: socketTimeout, TLSConfig: cfg, noPropagation: true, }) } // NewTSSLSocketFromConnConf creates a TSSLSocket from an existing net.Conn. func NewTSSLSocketFromConnConf(conn net.Conn, conf *TConfiguration) *TSSLSocket { return &TSSLSocket{ conn: wrapSocketConn(conn), addr: conn.RemoteAddr(), cfg: conf, } } // Deprecated: Use NewTSSLSocketFromConnConf instead. func NewTSSLSocketFromConnTimeout(conn net.Conn, cfg *tls.Config, socketTimeout time.Duration) *TSSLSocket { return NewTSSLSocketFromConnConf(conn, &TConfiguration{ SocketTimeout: socketTimeout, TLSConfig: cfg, noPropagation: true, }) } // SetTConfiguration implements TConfigurationSetter. // // It can be used to change connect and socket timeouts. func (p *TSSLSocket) SetTConfiguration(conf *TConfiguration) { p.cfg = conf } // Sets the connect timeout func (p *TSSLSocket) SetConnTimeout(timeout time.Duration) error { if p.cfg == nil { p.cfg = &TConfiguration{} } p.cfg.ConnectTimeout = timeout return nil } // Sets the socket timeout func (p *TSSLSocket) SetSocketTimeout(timeout time.Duration) error { if p.cfg == nil { p.cfg = &TConfiguration{} } p.cfg.SocketTimeout = timeout return nil } func (p *TSSLSocket) pushDeadline(read, write bool) { var t time.Time if timeout := p.cfg.GetSocketTimeout(); timeout > 0 { t = time.Now().Add(time.Duration(timeout)) } if read && write { p.conn.SetDeadline(t) } else if read { p.conn.SetReadDeadline(t) } else if write { p.conn.SetWriteDeadline(t) } } // Connects the socket, creating a new socket object if necessary. func (p *TSSLSocket) Open() error { var err error // If we have a hostname, we need to pass the hostname to tls.Dial for // certificate hostname checks. if p.hostPort != "" { if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( &net.Dialer{ Timeout: p.cfg.GetConnectTimeout(), }, "tcp", p.hostPort, p.cfg.GetTLSConfig(), )); err != nil { return &tTransportException{ typeId: NOT_OPEN, err: err, msg: err.Error(), } } } else { if p.conn.isValid() { return NewTTransportException(ALREADY_OPEN, "Socket already connected.") } if p.addr == nil { return NewTTransportException(NOT_OPEN, "Cannot open nil address.") } if len(p.addr.Network()) == 0 { return NewTTransportException(NOT_OPEN, "Cannot open bad network name.") } if len(p.addr.String()) == 0 { return NewTTransportException(NOT_OPEN, "Cannot open bad address.") } if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( &net.Dialer{ Timeout: p.cfg.GetConnectTimeout(), }, p.addr.Network(), p.addr.String(), p.cfg.GetTLSConfig(), )); err != nil { return &tTransportException{ typeId: NOT_OPEN, err: err, msg: err.Error(), } } } return nil } // Retrieve the underlying net.Conn func (p *TSSLSocket) Conn() net.Conn { return p.conn } // Returns true if the connection is open func (p *TSSLSocket) IsOpen() bool { return p.conn.IsOpen() } // Closes the socket. func (p *TSSLSocket) Close() error { return p.conn.Close() } func (p *TSSLSocket) Read(buf []byte) (int, error) { if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(true, false) // NOTE: Calling any of p.IsOpen, p.conn.read0, or p.conn.IsOpen between // p.pushDeadline and p.conn.Read could cause the deadline set inside // p.pushDeadline being reset, thus need to be avoided. n, err := p.conn.Read(buf) return n, NewTTransportExceptionFromError(err) } func (p *TSSLSocket) Write(buf []byte) (int, error) { if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(false, true) return p.conn.Write(buf) } func (p *TSSLSocket) Flush(ctx context.Context) error { return nil } func (p *TSSLSocket) Interrupt() error { if !p.conn.isValid() { return nil } return p.conn.Close() } func (p *TSSLSocket) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } var _ TConfigurationSetter = (*TSSLSocket)(nil) thrift-0.19.0/lib/go/thrift/deserializer.go0000644000000000000000000000626314303740367020601 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" ) type TDeserializer struct { Transport *TMemoryBuffer Protocol TProtocol } func NewTDeserializer() *TDeserializer { transport := NewTMemoryBufferLen(1024) protocol := NewTBinaryProtocolTransport(transport) return &TDeserializer{ Transport: transport, Protocol: protocol, } } type reseter interface { Reset() } func (t *TDeserializer) ReadString(ctx context.Context, msg TStruct, s string) (err error) { t.Transport.Reset() if r, ok := t.Protocol.(reseter); ok { r.Reset() } err = nil if _, err = t.Transport.Write([]byte(s)); err != nil { return } if err = msg.Read(ctx, t.Protocol); err != nil { return } return } func (t *TDeserializer) Read(ctx context.Context, msg TStruct, b []byte) (err error) { t.Transport.Reset() if r, ok := t.Protocol.(reseter); ok { r.Reset() } err = nil if _, err = t.Transport.Write(b); err != nil { return } if err = msg.Read(ctx, t.Protocol); err != nil { return } return } // TDeserializerPool is the thread-safe version of TDeserializer, // it uses resource pool of TDeserializer under the hood. // // It must be initialized with either NewTDeserializerPool or // NewTDeserializerPoolSizeFactory. type TDeserializerPool struct { pool *pool[TDeserializer] } // NewTDeserializerPool creates a new TDeserializerPool. // // NewTDeserializer can be used as the arg here. func NewTDeserializerPool(f func() *TDeserializer) *TDeserializerPool { return &TDeserializerPool{ pool: newPool(f, nil), } } // NewTDeserializerPoolSizeFactory creates a new TDeserializerPool with // the given size and protocol factory. // // Note that the size is not the limit. The TMemoryBuffer underneath can grow // larger than that. It just dictates the initial size. func NewTDeserializerPoolSizeFactory(size int, factory TProtocolFactory) *TDeserializerPool { return &TDeserializerPool{ pool: newPool(func() *TDeserializer { transport := NewTMemoryBufferLen(size) protocol := factory.GetProtocol(transport) return &TDeserializer{ Transport: transport, Protocol: protocol, } }, nil), } } func (t *TDeserializerPool) ReadString(ctx context.Context, msg TStruct, s string) error { d := t.pool.get() defer t.pool.put(&d) return d.ReadString(ctx, msg, s) } func (t *TDeserializerPool) Read(ctx context.Context, msg TStruct, b []byte) error { d := t.pool.get() defer t.pool.put(&d) return d.Read(ctx, msg, b) } thrift-0.19.0/lib/go/thrift/memory_buffer.go0000644000000000000000000000403214303740367020750 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "context" ) // Memory buffer-based implementation of the TTransport interface. type TMemoryBuffer struct { *bytes.Buffer size int } type TMemoryBufferTransportFactory struct { size int } func (p *TMemoryBufferTransportFactory) GetTransport(trans TTransport) (TTransport, error) { if trans != nil { t, ok := trans.(*TMemoryBuffer) if ok && t.size > 0 { return NewTMemoryBufferLen(t.size), nil } } return NewTMemoryBufferLen(p.size), nil } func NewTMemoryBufferTransportFactory(size int) *TMemoryBufferTransportFactory { return &TMemoryBufferTransportFactory{size: size} } func NewTMemoryBuffer() *TMemoryBuffer { return &TMemoryBuffer{Buffer: &bytes.Buffer{}, size: 0} } func NewTMemoryBufferLen(size int) *TMemoryBuffer { buf := make([]byte, 0, size) return &TMemoryBuffer{Buffer: bytes.NewBuffer(buf), size: size} } func (p *TMemoryBuffer) IsOpen() bool { return true } func (p *TMemoryBuffer) Open() error { return nil } func (p *TMemoryBuffer) Close() error { p.Buffer.Reset() return nil } // Flushing a memory buffer is a no-op func (p *TMemoryBuffer) Flush(ctx context.Context) error { return nil } func (p *TMemoryBuffer) RemainingBytes() (num_bytes uint64) { return uint64(p.Buffer.Len()) } thrift-0.19.0/lib/go/thrift/zlib_transport_test.go0000644000000000000000000000337114303740367022227 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "compress/zlib" "testing" ) func TestZlibTransport(t *testing.T) { trans, err := NewTZlibTransport(NewTMemoryBuffer(), zlib.BestCompression) if err != nil { t.Fatal(err) } TransportTest(t, trans, trans) } type DummyTransportFactory struct{} func (p *DummyTransportFactory) GetTransport(trans TTransport) (TTransport, error) { return NewTMemoryBuffer(), nil } func TestZlibFactoryTransportWithFactory(t *testing.T) { factory := NewTZlibTransportFactoryWithFactory( zlib.BestCompression, &DummyTransportFactory{}, ) buffer := NewTMemoryBuffer() trans, err := factory.GetTransport(buffer) if err != nil { t.Fatal(err) } TransportTest(t, trans, trans) } func TestZlibFactoryTransportWithoutFactory(t *testing.T) { factory := NewTZlibTransportFactoryWithFactory(zlib.BestCompression, nil) buffer := NewTMemoryBuffer() trans, err := factory.GetTransport(buffer) if err != nil { t.Fatal(err) } TransportTest(t, trans, trans) } thrift-0.19.0/lib/go/thrift/pool_test.go0000644000000000000000000000252014303740367020117 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "testing" "testing/quick" ) type poolTest int func TestPoolReset(t *testing.T) { p := newPool(nil, func(elem *poolTest) { *elem = 0 }) f := func(i int) (passed bool) { pt := p.get() defer func() { p.put(&pt) if pt != nil { t.Errorf("Expected pt to be nil after put, got %#v", pt) passed = false } }() if *pt != 0 { t.Errorf("Expected *pt to be reset to 0 after get, got %d", *pt) } *pt = poolTest(i) return !t.Failed() } if err := quick.Check(f, nil); err != nil { t.Error(err) } } thrift-0.19.0/lib/go/thrift/socket_conn.go0000644000000000000000000000703614370300523020411 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "net" "sync/atomic" ) // socketConn is a wrapped net.Conn that tries to do connectivity check. type socketConn struct { net.Conn buffer [1]byte closed atomic.Int32 } var _ net.Conn = (*socketConn)(nil) // createSocketConnFromReturn is a language sugar to help create socketConn from // return values of functions like net.Dial, tls.Dial, net.Listener.Accept, etc. func createSocketConnFromReturn(conn net.Conn, err error) (*socketConn, error) { if err != nil { return nil, err } return &socketConn{ Conn: conn, }, nil } // wrapSocketConn wraps an existing net.Conn into *socketConn. func wrapSocketConn(conn net.Conn) *socketConn { // In case conn is already wrapped, // return it as-is and avoid double wrapping. if sc, ok := conn.(*socketConn); ok { return sc } return &socketConn{ Conn: conn, } } // isValid checks whether there's a valid connection. // // It's nil safe, and returns false if sc itself is nil, or if the underlying // connection is nil. // // It's the same as the previous implementation of TSocket.IsOpen and // TSSLSocket.IsOpen before we added connectivity check. func (sc *socketConn) isValid() bool { return sc != nil && sc.Conn != nil && sc.closed.Load() == 0 } // IsOpen checks whether the connection is open. // // It's nil safe, and returns false if sc itself is nil, or if the underlying // connection is nil. // // Otherwise, it tries to do a connectivity check and returns the result. // // It also has the side effect of resetting the previously set read deadline on // the socket. As a result, it shouldn't be called between setting read deadline // and doing actual read. func (sc *socketConn) IsOpen() bool { if !sc.isValid() { return false } if err := sc.checkConn(); err != nil { if !errors.Is(err, net.ErrClosed) { // The connectivity check failed and the error is not // that the connection is already closed, we need to // close the connection explicitly here to avoid // connection leaks. sc.Close() } return false } return true } // Read implements io.Reader. // // On Windows, it behaves the same as the underlying net.Conn.Read. // // On non-Windows, it treats len(p) == 0 as a connectivity check instead of // readability check, which means instead of blocking until there's something to // read (readability check), or always return (0, nil) (the default behavior of // go's stdlib implementation on non-Windows), it never blocks, and will return // an error if the connection is lost. func (sc *socketConn) Read(p []byte) (n int, err error) { if len(p) == 0 { return 0, sc.read0() } return sc.Conn.Read(p) } func (sc *socketConn) Close() error { if !sc.isValid() { // Already closed return net.ErrClosed } sc.closed.Store(1) return sc.Conn.Close() } thrift-0.19.0/lib/go/thrift/application_exception_test.go0000644000000000000000000000305214303740367023530 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "testing" ) func TestTApplicationException(t *testing.T) { exc := NewTApplicationException(UNKNOWN_APPLICATION_EXCEPTION, "") if exc.Error() != defaultApplicationExceptionMessage[UNKNOWN_APPLICATION_EXCEPTION] { t.Fatalf("Expected empty string for exception but found '%s'", exc.Error()) } if exc.TypeId() != UNKNOWN_APPLICATION_EXCEPTION { t.Fatalf("Expected type UNKNOWN for exception but found '%v'", exc.TypeId()) } exc = NewTApplicationException(WRONG_METHOD_NAME, "junk_method") if exc.Error() != "junk_method" { t.Fatalf("Expected 'junk_method' for exception but found '%s'", exc.Error()) } if exc.TypeId() != WRONG_METHOD_NAME { t.Fatalf("Expected type WRONG_METHOD_NAME for exception but found '%v'", exc.TypeId()) } } thrift-0.19.0/lib/go/thrift/protocol_exception.go0000644000000000000000000000455614303740367022041 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "encoding/base64" "errors" ) // Thrift Protocol exception type TProtocolException interface { TException TypeId() int } const ( UNKNOWN_PROTOCOL_EXCEPTION = 0 INVALID_DATA = 1 NEGATIVE_SIZE = 2 SIZE_LIMIT = 3 BAD_VERSION = 4 NOT_IMPLEMENTED = 5 DEPTH_LIMIT = 6 ) type tProtocolException struct { typeId int err error msg string } var _ TProtocolException = (*tProtocolException)(nil) func (tProtocolException) TExceptionType() TExceptionType { return TExceptionTypeProtocol } func (p *tProtocolException) TypeId() int { return p.typeId } func (p *tProtocolException) String() string { return p.msg } func (p *tProtocolException) Error() string { return p.msg } func (p *tProtocolException) Unwrap() error { return p.err } func NewTProtocolException(err error) TProtocolException { if err == nil { return nil } if e, ok := err.(TProtocolException); ok { return e } if errors.As(err, new(base64.CorruptInputError)) { return NewTProtocolExceptionWithType(INVALID_DATA, err) } return NewTProtocolExceptionWithType(UNKNOWN_PROTOCOL_EXCEPTION, err) } func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { if err == nil { return nil } return &tProtocolException{ typeId: errType, err: err, msg: err.Error(), } } func prependTProtocolException(prepend string, err TProtocolException) TProtocolException { return &tProtocolException{ typeId: err.TypeId(), err: err, msg: prepend + err.Error(), } } thrift-0.19.0/lib/go/thrift/server_socket_test.go0000644000000000000000000000317114303740367022027 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "fmt" "testing" ) func TestSocketIsntListeningAfterInterrupt(t *testing.T) { host := "127.0.0.1" port := 9090 addr := fmt.Sprintf("%s:%d", host, port) socket := CreateServerSocket(t, addr) socket.Listen() socket.Interrupt() newSocket := CreateServerSocket(t, addr) err := newSocket.Listen() defer newSocket.Interrupt() if err != nil { t.Fatalf("Failed to rebinds: %s", err) } } func TestSocketConcurrency(t *testing.T) { host := "127.0.0.1" port := 9090 addr := fmt.Sprintf("%s:%d", host, port) socket := CreateServerSocket(t, addr) go func() { socket.Listen() }() go func() { socket.Interrupt() }() } func CreateServerSocket(t *testing.T, addr string) *TServerSocket { socket, err := NewTServerSocket(addr) if err != nil { t.Fatalf("Failed to create server socket: %s", err) } return socket } thrift-0.19.0/lib/go/thrift/transport_test.go0000644000000000000000000001361114303740367021205 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "io" "net" "strconv" "testing" ) const TRANSPORT_BINARY_DATA_SIZE = 4096 var ( transport_bdata []byte // test data for writing; same as data transport_header map[string]string ) func init() { transport_bdata = make([]byte, TRANSPORT_BINARY_DATA_SIZE) for i := 0; i < TRANSPORT_BINARY_DATA_SIZE; i++ { transport_bdata[i] = byte((i + 'a') % 255) } transport_header = map[string]string{"key": "User-Agent", "value": "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36"} } func TransportTest(t *testing.T, writeTrans TTransport, readTrans TTransport) { buf := make([]byte, TRANSPORT_BINARY_DATA_SIZE) if !writeTrans.IsOpen() { t.Fatalf("Transport %T not open: %s", writeTrans, writeTrans) } if !readTrans.IsOpen() { t.Fatalf("Transport %T not open: %s", readTrans, readTrans) } _, err := writeTrans.Write(transport_bdata) if err != nil { t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err) } err = writeTrans.Flush(context.Background()) if err != nil { t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err) } n, err := io.ReadFull(readTrans, buf) if err != nil { t.Errorf("Transport %T cannot read binary data of length %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, err) } if n != TRANSPORT_BINARY_DATA_SIZE { t.Errorf("Transport %T read only %d instead of %d bytes of binary data", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) } for k, v := range buf { if v != transport_bdata[k] { t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) } } _, err = writeTrans.Write(transport_bdata) if err != nil { t.Fatalf("Transport %T cannot write binary data 2 of length %d: %s", writeTrans, len(transport_bdata), err) } err = writeTrans.Flush(context.Background()) if err != nil { t.Fatalf("Transport %T cannot flush write binary data 2: %s", writeTrans, err) } buf = make([]byte, TRANSPORT_BINARY_DATA_SIZE) read := 1 for n = 0; n < TRANSPORT_BINARY_DATA_SIZE && read != 0; { read, err = readTrans.Read(buf[n:]) if err != nil { t.Errorf("Transport %T cannot read binary data 2 of total length %d from offset %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, n, err) } n += read } if n != TRANSPORT_BINARY_DATA_SIZE { t.Errorf("Transport %T read only %d instead of %d bytes of binary data 2", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) } for k, v := range buf { if v != transport_bdata[k] { t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) } } } func TransportHeaderTest(t *testing.T, writeTrans TTransport, readTrans TTransport) { buf := make([]byte, TRANSPORT_BINARY_DATA_SIZE) if !writeTrans.IsOpen() { t.Fatalf("Transport %T not open: %s", writeTrans, writeTrans) } if !readTrans.IsOpen() { t.Fatalf("Transport %T not open: %s", readTrans, readTrans) } // Need to assert type of TTransport to THttpClient to expose the Setter httpWPostTrans := writeTrans.(*THttpClient) httpWPostTrans.SetHeader(transport_header["key"], transport_header["value"]) _, err := writeTrans.Write(transport_bdata) if err != nil { t.Fatalf("Transport %T cannot write binary data of length %d: %s", writeTrans, len(transport_bdata), err) } err = writeTrans.Flush(context.Background()) if err != nil { t.Fatalf("Transport %T cannot flush write of binary data: %s", writeTrans, err) } // Need to assert type of TTransport to THttpClient to expose the Getter httpRPostTrans := readTrans.(*THttpClient) readHeader := httpRPostTrans.GetHeader(transport_header["key"]) if err != nil { t.Errorf("Transport %T cannot read HTTP Header Value", httpRPostTrans) } if transport_header["value"] != readHeader { t.Errorf("Expected HTTP Header Value %s, got %s", transport_header["value"], readHeader) } n, err := io.ReadFull(readTrans, buf) if err != nil { t.Errorf("Transport %T cannot read binary data of length %d: %s", readTrans, TRANSPORT_BINARY_DATA_SIZE, err) } if n != TRANSPORT_BINARY_DATA_SIZE { t.Errorf("Transport %T read only %d instead of %d bytes of binary data", readTrans, n, TRANSPORT_BINARY_DATA_SIZE) } for k, v := range buf { if v != transport_bdata[k] { t.Fatalf("Transport %T read %d instead of %d for index %d of binary data 2", readTrans, v, transport_bdata[k], k) } } } func CloseTransports(t *testing.T, readTrans TTransport, writeTrans TTransport) { err := readTrans.Close() if err != nil { t.Errorf("Transport %T cannot close read transport: %s", readTrans, err) } if writeTrans != readTrans { err = writeTrans.Close() if err != nil { t.Errorf("Transport %T cannot close write transport: %s", writeTrans, err) } } } func FindAvailableTCPServerPort(startPort int) (net.Addr, error) { for i := startPort; i < 65535; i++ { s := "127.0.0.1:" + strconv.Itoa(i) l, err := net.Listen("tcp", s) if err == nil { l.Close() return net.ResolveTCPAddr("tcp", s) } } return nil, NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "Could not find available server port") } thrift-0.19.0/lib/go/thrift/iostream_transport_test.go0000644000000000000000000000323114303740367023105 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "testing" ) func TestStreamTransport(t *testing.T) { trans := NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024))) TransportTest(t, trans, trans) } func TestStreamTransportOpenClose(t *testing.T) { trans := NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 1024))) if !trans.IsOpen() { t.Fatal("StreamTransport should be already open") } if trans.Open() == nil { t.Fatal("StreamTransport should return error when open twice") } if trans.Close() != nil { t.Fatal("StreamTransport should not return error when closing open transport") } if trans.IsOpen() { t.Fatal("StreamTransport should not be open after close") } if trans.Close() == nil { t.Fatal("StreamTransport should return error when closing a non open transport") } if trans.Open() == nil { t.Fatal("StreamTransport should not be able to reopen") } } thrift-0.19.0/lib/go/thrift/zlib_transport.go0000644000000000000000000000741414452237057021174 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "compress/zlib" "context" "io" ) // TZlibTransportFactory is a factory for TZlibTransport instances type TZlibTransportFactory struct { level int factory TTransportFactory } // TZlibTransport is a TTransport implementation that makes use of zlib compression. type TZlibTransport struct { reader io.ReadCloser transport TTransport writer *zlib.Writer } // GetTransport constructs a new instance of NewTZlibTransport func (p *TZlibTransportFactory) GetTransport(trans TTransport) (TTransport, error) { if p.factory != nil { // wrap other factory var err error trans, err = p.factory.GetTransport(trans) if err != nil { return nil, err } } return NewTZlibTransport(trans, p.level) } // NewTZlibTransportFactory constructs a new instance of NewTZlibTransportFactory func NewTZlibTransportFactory(level int) *TZlibTransportFactory { return &TZlibTransportFactory{level: level, factory: nil} } // NewTZlibTransportFactoryWithFactory constructs a new instance of TZlibTransportFactory // as a wrapper over existing transport factory func NewTZlibTransportFactoryWithFactory(level int, factory TTransportFactory) *TZlibTransportFactory { return &TZlibTransportFactory{level: level, factory: factory} } // NewTZlibTransport constructs a new instance of TZlibTransport func NewTZlibTransport(trans TTransport, level int) (*TZlibTransport, error) { w, err := zlib.NewWriterLevel(trans, level) if err != nil { return nil, err } return &TZlibTransport{ writer: w, transport: trans, }, nil } // Close closes the reader and writer (flushing any unwritten data) and closes // the underlying transport. func (z *TZlibTransport) Close() error { if z.reader != nil { if err := z.reader.Close(); err != nil { return err } } if err := z.writer.Close(); err != nil { return err } return z.transport.Close() } // Flush flushes the writer and its underlying transport. func (z *TZlibTransport) Flush(ctx context.Context) error { if err := z.writer.Flush(); err != nil { return err } return z.transport.Flush(ctx) } // IsOpen returns true if the transport is open func (z *TZlibTransport) IsOpen() bool { return z.transport.IsOpen() } // Open opens the transport for communication func (z *TZlibTransport) Open() error { return z.transport.Open() } func (z *TZlibTransport) Read(p []byte) (int, error) { if z.reader == nil { r, err := zlib.NewReader(z.transport) if err != nil { return 0, NewTTransportExceptionFromError(err) } z.reader = r } return z.reader.Read(p) } // RemainingBytes returns the size in bytes of the data that is still to be // read. func (z *TZlibTransport) RemainingBytes() uint64 { return z.transport.RemainingBytes() } func (z *TZlibTransport) Write(p []byte) (int, error) { return z.writer.Write(p) } // SetTConfiguration implements TConfigurationSetter for propagation. func (z *TZlibTransport) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(z.transport, conf) } var _ TConfigurationSetter = (*TZlibTransport)(nil) thrift-0.19.0/lib/go/thrift/context.go0000644000000000000000000000155514303740367017602 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import "context" var defaultCtx = context.Background() thrift-0.19.0/lib/go/thrift/header_transport_test.go0000644000000000000000000002325714303740367022524 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "fmt" "io" "strings" "testing" "testing/iotest" "testing/quick" ) func testTHeaderHeadersReadWriteProtocolID(t *testing.T, protoID THeaderProtocolID) { trans := NewTMemoryBuffer() reader := NewTHeaderTransport(trans) writer := NewTHeaderTransportConf(trans, &TConfiguration{ THeaderProtocolID: &protoID, }) const key1 = "key1" const value1 = "value1" const key2 = "key2" const value2 = "value2" const payload1 = "hello, world1\n" const payload2 = "hello, world2\n" // Write if err := writer.AddTransform(TransformZlib); err != nil { t.Fatalf( "writer.AddTransform(TransformZlib) returned error: %v", err, ) } // Use double zlib to make sure that we close them in the right order. if err := writer.AddTransform(TransformZlib); err != nil { t.Fatalf( "writer.AddTransform(TransformZlib) returned error: %v", err, ) } if err := writer.AddTransform(TransformNone); err != nil { t.Fatalf( "writer.AddTransform(TransformNone) returned error: %v", err, ) } writer.SetWriteHeader(key1, value1) writer.SetWriteHeader(key2, value2) if _, err := writer.Write([]byte(payload1)); err != nil { t.Errorf("writer.Write returned error: %v", err) } if err := writer.Flush(context.Background()); err != nil { t.Errorf("writer.Flush returned error: %v", err) } if _, err := writer.Write([]byte(payload2)); err != nil { t.Errorf("writer.Write returned error: %v", err) } if err := writer.Flush(context.Background()); err != nil { t.Errorf("writer.Flush returned error: %v", err) } // Read // Make sure multiple calls to ReadFrame is fine. if err := reader.ReadFrame(context.Background()); err != nil { t.Errorf("reader.ReadFrame returned error: %v", err) } if err := reader.ReadFrame(context.Background()); err != nil { t.Errorf("reader.ReadFrame returned error: %v", err) } read, err := io.ReadAll(reader) if err != nil { t.Errorf("Read returned error: %v", err) } if err := reader.ReadFrame(context.Background()); err != nil && err != io.EOF { t.Errorf("reader.ReadFrame returned error: %v", err) } if string(read) != payload1+payload2 { t.Errorf( "Read content expected %q, got %q", payload1+payload2, read, ) } if prot := reader.Protocol(); prot != protoID { t.Errorf( "reader.Protocol() expected %d, got %d", protoID, prot, ) } if reader.clientType != clientHeaders { t.Errorf( "reader.clientType expected %d, got %d", clientHeaders, reader.clientType, ) } headers := reader.GetReadHeaders() if len(headers) != 2 || headers[key1] != value1 || headers[key2] != value2 { t.Errorf( "reader.GetReadHeaders() expected size 2, actual content: %+v", headers, ) } } func TestTHeaderHeadersReadWrite(t *testing.T) { for label, id := range map[string]THeaderProtocolID{ "default": THeaderProtocolDefault, "binary": THeaderProtocolBinary, "compact": THeaderProtocolCompact, } { t.Run(label, func(t *testing.T) { testTHeaderHeadersReadWriteProtocolID(t, id) }) } } func TestTHeaderTransportNoDoubleWrapping(t *testing.T) { trans := NewTMemoryBuffer() orig := NewTHeaderTransport(trans) wrapped := NewTHeaderTransport(orig) if wrapped != orig { t.Errorf("NewTHeaderTransport double wrapped THeaderTransport") } } func TestTHeaderTransportNoReadBeyondFrame(t *testing.T) { trans := NewTMemoryBuffer() writeContent := func(writer TTransport, content string) error { if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { return err } if err := writer.Flush(context.Background()); err != nil { return err } return nil } f := func(content string) bool { trans.Reset() if len(content) == 0 { return true } reader := NewTHeaderTransport(trans) writer := NewTHeaderTransport(trans) // Write content twice if err := writeContent(writer, content); err != nil { t.Error(err) } if err := writeContent(writer, content); err != nil { t.Error(err) } // buf is big enough to read both content out, // but it shouldn't read beyond the first one in a single Read call. buf := make([]byte, len(content)*3) read, err := reader.Read(buf) if err != nil { t.Error(err) } if read == 0 || read > len(content) { t.Errorf( "Expected read in no more than %d:%q, got %d:%q", len(content), content, read, buf[:read], ) } // Check for endOfFrame handling if !reader.needReadFrame() { t.Error("Expected needReadFrame to be true after read the frame fully, got false") } return !t.Failed() } if err := quick.Check(f, nil); err != nil { t.Error(err) } } func TestTHeaderTransportEndOfFrameHandling(t *testing.T) { trans := NewTMemoryBuffer() writeContent := func(writer TTransport, content string) error { if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { return err } if err := writer.Flush(context.Background()); err != nil { return err } return nil } readFully := func(content string) bool { trans.Reset() if len(content) == 0 { return true } reader := NewTHeaderTransport(trans) writer := NewTHeaderTransport(trans) // Write content if err := writeContent(writer, content); err != nil { t.Error(err) } buf := make([]byte, len(content)) _, err := reader.Read(buf) if err != nil { t.Error(err) } if !reader.needReadFrame() { t.Error("Expected needReadFrame to be true after read the frame fully, got false") } return !t.Failed() } if err := quick.Check(readFully, nil); err != nil { t.Error(err) } readPartially := func(content string) bool { trans.Reset() if len(content) < 1 { return true } reader := NewTHeaderTransport(trans) writer := NewTHeaderTransport(trans) // Write content if err := writeContent(writer, content); err != nil { t.Error(err) } // Make the buf smaller so it can't read fully buf := make([]byte, len(content)-1) _, err := reader.Read(buf) if err != nil { t.Error(err) } if reader.needReadFrame() { t.Error("Expected needReadFrame to be false before read the frame fully, got true") } return !t.Failed() } if err := quick.Check(readPartially, nil); err != nil { t.Error(err) } } func BenchmarkTHeaderProtocolIDValidate(b *testing.B) { for _, c := range []THeaderProtocolID{ THeaderProtocolBinary, THeaderProtocolCompact, -1, } { b.Run(fmt.Sprintf("%2v", c), func(b *testing.B) { b.RunParallel(func(pb *testing.PB) { for pb.Next() { c.Validate() } }) }) } } func TestSetTHeaderTransportProtocolID(t *testing.T) { const expected = THeaderProtocolCompact factory := NewTHeaderTransportFactoryConf(nil, &TConfiguration{ THeaderProtocolID: THeaderProtocolIDPtrMust(expected), }) buf := NewTMemoryBuffer() trans, err := factory.GetTransport(buf) if err != nil { t.Fatalf("Failed to get transport from factory: %v", err) } ht, ok := trans.(*THeaderTransport) if !ok { t.Fatalf("Transport is not *THeaderTransport: %#v", trans) } if actual := ht.Protocol(); actual != expected { t.Errorf("Expected protocol id %v, got %v", expected, actual) } ht.SetTConfiguration(&TConfiguration{}) if actual := ht.Protocol(); actual != expected { t.Errorf("Expected protocol id %v, got %v", expected, actual) } } func TestTHeaderTransportReuseTransport(t *testing.T) { const ( content = "Hello, world!" n = 10 ) trans := NewTMemoryBuffer() reader := NewTHeaderTransport(trans) writer := NewTHeaderTransport(trans) t.Run("pair", func(t *testing.T) { for i := 0; i < n; i++ { // write if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { t.Fatalf("Failed to write on #%d: %v", i, err) } if err := writer.Flush(context.Background()); err != nil { t.Fatalf("Failed to flush on #%d: %v", i, err) } // read read, err := io.ReadAll(iotest.OneByteReader(reader)) if err != nil { t.Errorf("Failed to read on #%d: %v", i, err) } if string(read) != content { t.Errorf("Read #%d: want %q, got %q", i, content, read) } } }) t.Run("batched", func(t *testing.T) { // write for i := 0; i < n; i++ { if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { t.Fatalf("Failed to write on #%d: %v", i, err) } if err := writer.Flush(context.Background()); err != nil { t.Fatalf("Failed to flush on #%d: %v", i, err) } } // read for i := 0; i < n; i++ { const ( size = len(content) ) var buf []byte var err error if i%2 == 0 { // on even calls, use OneByteReader to make // sure that small reads are fine buf, err = io.ReadAll(io.LimitReader(iotest.OneByteReader(reader), int64(size))) } else { // on odd calls, make sure that we don't read // more than written per frame buf = make([]byte, size*2) var n int n, err = reader.Read(buf) buf = buf[:n] } if err != nil { t.Errorf("Failed to read on #%d: %v", i, err) } if string(buf) != content { t.Errorf("Read #%d: want %q, got %q", i, content, buf) } } }) } thrift-0.19.0/lib/go/thrift/processor_factory.go0000644000000000000000000000464714303740367021671 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import "context" // A processor is a generic object which operates upon an input stream and // writes to some output stream. type TProcessor interface { Process(ctx context.Context, in, out TProtocol) (bool, TException) // ProcessorMap returns a map of thrift method names to TProcessorFunctions. ProcessorMap() map[string]TProcessorFunction // AddToProcessorMap adds the given TProcessorFunction to the internal // processor map at the given key. // // If one is already set at the given key, it will be replaced with the new // TProcessorFunction. AddToProcessorMap(string, TProcessorFunction) } type TProcessorFunction interface { Process(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) } // The default processor factory just returns a singleton // instance. type TProcessorFactory interface { GetProcessor(trans TTransport) TProcessor } type tProcessorFactory struct { processor TProcessor } func NewTProcessorFactory(p TProcessor) TProcessorFactory { return &tProcessorFactory{processor: p} } func (p *tProcessorFactory) GetProcessor(trans TTransport) TProcessor { return p.processor } /** * The default processor factory just returns a singleton * instance. */ type TProcessorFunctionFactory interface { GetProcessorFunction(trans TTransport) TProcessorFunction } type tProcessorFunctionFactory struct { processor TProcessorFunction } func NewTProcessorFunctionFactory(p TProcessorFunction) TProcessorFunctionFactory { return &tProcessorFunctionFactory{processor: p} } func (p *tProcessorFunctionFactory) GetProcessorFunction(trans TTransport) TProcessorFunction { return p.processor } thrift-0.19.0/lib/go/thrift/protocol_test.go0000644000000000000000000005052114370300523021001 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "context" "io" "math" "net" "net/http" "testing" ) const PROTOCOL_BINARY_DATA_SIZE = 155 var ( protocol_bdata []byte // test data for writing; same as data BOOL_VALUES []bool BYTE_VALUES []int8 INT16_VALUES []int16 INT32_VALUES []int32 INT64_VALUES []int64 DOUBLE_VALUES []float64 STRING_VALUES []string UUID_VALUES []Tuuid ) func init() { protocol_bdata = make([]byte, PROTOCOL_BINARY_DATA_SIZE) for i := 0; i < PROTOCOL_BINARY_DATA_SIZE; i++ { protocol_bdata[i] = byte((i + 'a') % 255) } BOOL_VALUES = []bool{false, true, false, false, true} BYTE_VALUES = []int8{117, 0, 1, 32, 127, -128, -1} INT16_VALUES = []int16{459, 0, 1, -1, -128, 127, 32767, -32768} INT32_VALUES = []int32{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535} INT64_VALUES = []int64{459, 0, 1, -1, -128, 127, 32767, 2147483647, -2147483535, 34359738481, -35184372088719, -9223372036854775808, 9223372036854775807} DOUBLE_VALUES = []float64{459.3, 0.0, -1.0, 1.0, 0.5, 0.3333, 3.14159, 1.537e-38, 1.673e25, 6.02214179e23, -6.02214179e23, INFINITY.Float64(), NEGATIVE_INFINITY.Float64(), NAN.Float64()} STRING_VALUES = []string{"", "a", "st[uf]f", "st,u:ff with spaces", "stuff\twith\nescape\\characters'...\"lots{of}fun"} UUID_VALUES = []Tuuid{ {}, Must(ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8")), Must(ParseTuuid("6ba7b811-9dad-11d1-80b4-00c04fd430c8")), Must(ParseTuuid("6ba7b812-9dad-11d1-80b4-00c04fd430c8")), Must(ParseTuuid("6ba7b814-9dad-11d1-80b4-00c04fd430c8")), } } type HTTPEchoServer struct{} type HTTPHeaderEchoServer struct{} func (p *HTTPEchoServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { buf, err := io.ReadAll(req.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write(buf) } else { w.WriteHeader(http.StatusOK) w.Write(buf) } } func (p *HTTPHeaderEchoServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { buf, err := io.ReadAll(req.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write(buf) } else { w.WriteHeader(http.StatusOK) w.Write(buf) } } func HttpClientSetupForTest(t *testing.T) (net.Listener, net.Addr) { addr, err := FindAvailableTCPServerPort(40000) if err != nil { t.Fatalf("Unable to find available tcp port addr: %s", err) return nil, addr } l, err := net.Listen(addr.Network(), addr.String()) if err != nil { t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err) return l, addr } go http.Serve(l, &HTTPEchoServer{}) return l, addr } func HttpClientSetupForHeaderTest(t *testing.T) (net.Listener, net.Addr) { addr, err := FindAvailableTCPServerPort(40000) if err != nil { t.Fatalf("Unable to find available tcp port addr: %s", err) return nil, addr } l, err := net.Listen(addr.Network(), addr.String()) if err != nil { t.Fatalf("Unable to setup tcp listener on %s: %s", addr.String(), err) return l, addr } go http.Serve(l, &HTTPHeaderEchoServer{}) return l, addr } func ReadWriteProtocolTest(t *testing.T, protocolFactory TProtocolFactory) { buf := bytes.NewBuffer(make([]byte, 0, 1024)) l, addr := HttpClientSetupForTest(t) defer l.Close() transports := []TTransportFactory{ NewTMemoryBufferTransportFactory(1024), NewStreamTransportFactory(buf, buf, true), NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)), NewTZlibTransportFactoryWithFactory(0, NewTMemoryBufferTransportFactory(1024)), NewTZlibTransportFactoryWithFactory(6, NewTMemoryBufferTransportFactory(1024)), NewTZlibTransportFactoryWithFactory(9, NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024))), NewTHttpPostClientTransportFactory("http://" + addr.String()), } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteBool(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteByte(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteI16(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteI32(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteI64(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteDouble(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteString(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteBinary(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteUUID(t, p, trans) trans.Close() } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } p := protocolFactory.GetProtocol(trans) ReadWriteI64(t, p, trans) ReadWriteDouble(t, p, trans) ReadWriteBinary(t, p, trans) ReadWriteByte(t, p, trans) ReadWriteUUID(t, p, trans) trans.Close() } t.Run("UnmatchedBeginEnd", func(t *testing.T) { UnmatchedBeginEndProtocolTest(t, protocolFactory) }) } func ReadWriteBool(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(BOOL) thelen := len(BOOL_VALUES) err := p.WriteListBegin(context.Background(), thetype, thelen) if err != nil { t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteBool", p, trans, err, thetype) } for k, v := range BOOL_VALUES { err = p.WriteBool(context.Background(), v) if err != nil { t.Errorf("%s: %T %T %v Error writing bool in list at index %v: %v", "ReadWriteBool", p, trans, err, k, v) } } p.WriteListEnd(context.Background()) if err != nil { t.Errorf("%s: %T %T %v Error writing list end: %v", "ReadWriteBool", p, trans, err, BOOL_VALUES) } p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %v Error reading list: %v", "ReadWriteBool", p, trans, err, BOOL_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteBool", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteBool", p, trans, thelen, thelen2) } } for k, v := range BOOL_VALUES { value, err := p.ReadBool(context.Background()) if err != nil { t.Errorf("%s: %T %T %v Error reading bool at index %v: %v", "ReadWriteBool", p, trans, err, k, v) } if v != value { t.Errorf("%s: index %v %v %v %v != %v", "ReadWriteBool", k, p, trans, v, value) } } err = p.ReadListEnd(context.Background()) if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteBool", p, trans, err) } } func ReadWriteByte(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(BYTE) thelen := len(BYTE_VALUES) err := p.WriteListBegin(context.Background(), thetype, thelen) if err != nil { t.Errorf("%s: %T %T %q Error writing list begin: %q", "ReadWriteByte", p, trans, err, thetype) } for k, v := range BYTE_VALUES { err = p.WriteByte(context.Background(), v) if err != nil { t.Errorf("%s: %T %T %q Error writing byte in list at index %d: %q", "ReadWriteByte", p, trans, err, k, v) } } err = p.WriteListEnd(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error writing list end: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) } err = p.Flush(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error flushing list of bytes: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) } thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteByte", p, trans, err, BYTE_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteByte", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteByte", p, trans, thelen, thelen2) } } for k, v := range BYTE_VALUES { value, err := p.ReadByte(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading byte at index %d: %q", "ReadWriteByte", p, trans, err, k, v) } if v != value { t.Errorf("%s: %T %T %d != %d", "ReadWriteByte", p, trans, v, value) } } err = p.ReadListEnd(context.Background()) if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteByte", p, trans, err) } } func ReadWriteI16(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(I16) thelen := len(INT16_VALUES) p.WriteListBegin(context.Background(), thetype, thelen) for _, v := range INT16_VALUES { p.WriteI16(context.Background(), v) } p.WriteListEnd(context.Background()) p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI16", p, trans, err, INT16_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI16", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI16", p, trans, thelen, thelen2) } } for k, v := range INT16_VALUES { value, err := p.ReadI16(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading int16 at index %d: %q", "ReadWriteI16", p, trans, err, k, v) } if v != value { t.Errorf("%s: %T %T %d != %d", "ReadWriteI16", p, trans, v, value) } } err = p.ReadListEnd(context.Background()) if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI16", p, trans, err) } } func ReadWriteI32(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(I32) thelen := len(INT32_VALUES) p.WriteListBegin(context.Background(), thetype, thelen) for _, v := range INT32_VALUES { p.WriteI32(context.Background(), v) } p.WriteListEnd(context.Background()) p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI32", p, trans, err, INT32_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI32", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI32", p, trans, thelen, thelen2) } } for k, v := range INT32_VALUES { value, err := p.ReadI32(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading int32 at index %d: %q", "ReadWriteI32", p, trans, err, k, v) } if v != value { t.Errorf("%s: %T %T %d != %d", "ReadWriteI32", p, trans, v, value) } } if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI32", p, trans, err) } } func ReadWriteI64(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(I64) thelen := len(INT64_VALUES) p.WriteListBegin(context.Background(), thetype, thelen) for _, v := range INT64_VALUES { p.WriteI64(context.Background(), v) } p.WriteListEnd(context.Background()) p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteI64", p, trans, err, INT64_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteI64", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteI64", p, trans, thelen, thelen2) } } for k, v := range INT64_VALUES { value, err := p.ReadI64(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading int64 at index %d: %q", "ReadWriteI64", p, trans, err, k, v) } if v != value { t.Errorf("%s: %T %T %q != %q", "ReadWriteI64", p, trans, v, value) } } if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteI64", p, trans, err) } } func ReadWriteDouble(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(DOUBLE) thelen := len(DOUBLE_VALUES) p.WriteListBegin(context.Background(), thetype, thelen) for _, v := range DOUBLE_VALUES { p.WriteDouble(context.Background(), v) } p.WriteListEnd(context.Background()) p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %v Error reading list: %v", "ReadWriteDouble", p, trans, err, DOUBLE_VALUES) } if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteDouble", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteDouble", p, trans, thelen, thelen2) } for k, v := range DOUBLE_VALUES { value, err := p.ReadDouble(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading double at index %d: %v", "ReadWriteDouble", p, trans, err, k, v) } if math.IsNaN(v) { if !math.IsNaN(value) { t.Errorf("%s: %T %T math.IsNaN(%v) != math.IsNaN(%v)", "ReadWriteDouble", p, trans, v, value) } } else if v != value { t.Errorf("%s: %T %T %v != %v", "ReadWriteDouble", p, trans, v, value) } } err = p.ReadListEnd(context.Background()) if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteDouble", p, trans, err) } } func ReadWriteString(t testing.TB, p TProtocol, trans TTransport) { thetype := TType(STRING) thelen := len(STRING_VALUES) p.WriteListBegin(context.Background(), thetype, thelen) for _, v := range STRING_VALUES { p.WriteString(context.Background(), v) } p.WriteListEnd(context.Background()) p.Flush(context.Background()) thetype2, thelen2, err := p.ReadListBegin(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteString", p, trans, err, STRING_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteString", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteString", p, trans, thelen, thelen2) } } for k, v := range STRING_VALUES { value, err := p.ReadString(context.Background()) if err != nil { t.Errorf("%s: %T %T %q Error reading string at index %d: %q", "ReadWriteString", p, trans, err, k, v) } if v != value { t.Errorf("%s: %T %T %v != %v", "ReadWriteString", p, trans, v, value) } } if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteString", p, trans, err) } } func ReadWriteBinary(t testing.TB, p TProtocol, trans TTransport) { v := protocol_bdata p.WriteBinary(context.Background(), v) p.Flush(context.Background()) value, err := p.ReadBinary(context.Background()) if err != nil { t.Errorf("%s: %T %T Unable to read binary: %s", "ReadWriteBinary", p, trans, err.Error()) } if len(v) != len(value) { t.Errorf("%s: %T %T len(v) != len(value)... %d != %d", "ReadWriteBinary", p, trans, len(v), len(value)) } else { for i := 0; i < len(v); i++ { if v[i] != value[i] { t.Errorf("%s: %T %T %s != %s", "ReadWriteBinary", p, trans, v, value) } } } } func ReadWriteUUID(t testing.TB, p TProtocol, trans TTransport) { ctx := context.Background() thetype := TType(UUID) thelen := len(UUID_VALUES) p.WriteListBegin(ctx, thetype, thelen) for _, v := range UUID_VALUES { p.WriteUUID(ctx, v) } p.WriteListEnd(ctx) p.Flush(ctx) thetype2, thelen2, err := p.ReadListBegin(ctx) if err != nil { t.Errorf("%s: %T %T %q Error reading list: %q", "ReadWriteUUID", p, trans, err, STRING_VALUES) } _, ok := p.(*TSimpleJSONProtocol) if !ok { if thetype != thetype2 { t.Errorf("%s: %T %T type %s != type %s", "ReadWriteUUID", p, trans, thetype, thetype2) } if thelen != thelen2 { t.Errorf("%s: %T %T len %v != len %v", "ReadWriteUUID", p, trans, thelen, thelen2) } } for k, v := range UUID_VALUES { value, err := p.ReadUUID(ctx) if err != nil { t.Errorf("%s: %T %T %q Error reading UUID at index %d: %q", "ReadWriteUUID", p, trans, err, k, v) } if v != value { t.Errorf("%s: %T %T %v != %v", "ReadWriteUUID", p, trans, v, value) } } if err != nil { t.Errorf("%s: %T %T Unable to read list end: %q", "ReadWriteUUID", p, trans, err) } } func UnmatchedBeginEndProtocolTest(t *testing.T, protocolFactory TProtocolFactory) { // NOTE: not all protocol implementations do strict state check to // return an error on unmatched Begin/End calls. // This test is only meant to make sure that those unmatched Begin/End // calls won't cause panic. There's no real "test" here. trans := NewTMemoryBuffer() t.Run("Read", func(t *testing.T) { t.Run("Message", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.ReadMessageEnd(context.Background()) p.ReadMessageEnd(context.Background()) }) t.Run("Struct", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.ReadStructEnd(context.Background()) p.ReadStructEnd(context.Background()) }) t.Run("Field", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.ReadFieldEnd(context.Background()) p.ReadFieldEnd(context.Background()) }) t.Run("Map", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.ReadMapEnd(context.Background()) p.ReadMapEnd(context.Background()) }) t.Run("List", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.ReadListEnd(context.Background()) p.ReadListEnd(context.Background()) }) t.Run("Set", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.ReadSetEnd(context.Background()) p.ReadSetEnd(context.Background()) }) }) t.Run("Write", func(t *testing.T) { t.Run("Message", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.WriteMessageEnd(context.Background()) p.WriteMessageEnd(context.Background()) }) t.Run("Struct", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.WriteStructEnd(context.Background()) p.WriteStructEnd(context.Background()) }) t.Run("Field", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.WriteFieldEnd(context.Background()) p.WriteFieldEnd(context.Background()) }) t.Run("Map", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.WriteMapEnd(context.Background()) p.WriteMapEnd(context.Background()) }) t.Run("List", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.WriteListEnd(context.Background()) p.WriteListEnd(context.Background()) }) t.Run("Set", func(t *testing.T) { trans.Reset() p := protocolFactory.GetProtocol(trans) p.WriteSetEnd(context.Background()) p.WriteSetEnd(context.Background()) }) }) trans.Close() } thrift-0.19.0/lib/go/thrift/transport_exception.go0000644000000000000000000000536414303740367022232 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "io" ) type timeoutable interface { Timeout() bool } // Thrift Transport exception type TTransportException interface { TException TypeId() int Err() error } const ( UNKNOWN_TRANSPORT_EXCEPTION = 0 NOT_OPEN = 1 ALREADY_OPEN = 2 TIMED_OUT = 3 END_OF_FILE = 4 ) type tTransportException struct { typeId int err error msg string } var _ TTransportException = (*tTransportException)(nil) func (tTransportException) TExceptionType() TExceptionType { return TExceptionTypeTransport } func (p *tTransportException) TypeId() int { return p.typeId } func (p *tTransportException) Error() string { return p.msg } func (p *tTransportException) Err() error { return p.err } func (p *tTransportException) Unwrap() error { return p.err } func (p *tTransportException) Timeout() bool { return p.typeId == TIMED_OUT || isTimeoutError(p.err) } func NewTTransportException(t int, e string) TTransportException { return &tTransportException{ typeId: t, err: errors.New(e), msg: e, } } func NewTTransportExceptionFromError(e error) TTransportException { if e == nil { return nil } if t, ok := e.(TTransportException); ok { return t } te := &tTransportException{ typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e, msg: e.Error(), } if isTimeoutError(e) { te.typeId = TIMED_OUT return te } if errors.Is(e, io.EOF) { te.typeId = END_OF_FILE return te } return te } func prependTTransportException(prepend string, e TTransportException) TTransportException { return &tTransportException{ typeId: e.TypeId(), err: e, msg: prepend + e.Error(), } } // isTimeoutError returns true when err is an error caused by timeout. // // Note that this also includes TTransportException wrapped timeout errors. func isTimeoutError(err error) bool { var t timeoutable if errors.As(err, &t) { return t.Timeout() } return false } thrift-0.19.0/lib/go/thrift/server_socket.go0000644000000000000000000000633314303740367020773 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "net" "sync" "time" ) type TServerSocket struct { listener net.Listener addr net.Addr clientTimeout time.Duration // Protects the interrupted value to make it thread safe. mu sync.RWMutex interrupted bool } func NewTServerSocket(listenAddr string) (*TServerSocket, error) { return NewTServerSocketTimeout(listenAddr, 0) } func NewTServerSocketTimeout(listenAddr string, clientTimeout time.Duration) (*TServerSocket, error) { addr, err := net.ResolveTCPAddr("tcp", listenAddr) if err != nil { return nil, err } return &TServerSocket{addr: addr, clientTimeout: clientTimeout}, nil } // Creates a TServerSocket from a net.Addr func NewTServerSocketFromAddrTimeout(addr net.Addr, clientTimeout time.Duration) *TServerSocket { return &TServerSocket{addr: addr, clientTimeout: clientTimeout} } func (p *TServerSocket) Listen() error { p.mu.Lock() defer p.mu.Unlock() if p.IsListening() { return nil } l, err := net.Listen(p.addr.Network(), p.addr.String()) if err != nil { return err } p.listener = l return nil } func (p *TServerSocket) Accept() (TTransport, error) { p.mu.RLock() interrupted := p.interrupted p.mu.RUnlock() if interrupted { return nil, errTransportInterrupted } p.mu.Lock() listener := p.listener p.mu.Unlock() if listener == nil { return nil, NewTTransportException(NOT_OPEN, "No underlying server socket") } conn, err := listener.Accept() if err != nil { return nil, NewTTransportExceptionFromError(err) } return NewTSocketFromConnTimeout(conn, p.clientTimeout), nil } // Checks whether the socket is listening. func (p *TServerSocket) IsListening() bool { return p.listener != nil } // Connects the socket, creating a new socket object if necessary. func (p *TServerSocket) Open() error { p.mu.Lock() defer p.mu.Unlock() if p.IsListening() { return NewTTransportException(ALREADY_OPEN, "Server socket already open") } if l, err := net.Listen(p.addr.Network(), p.addr.String()); err != nil { return err } else { p.listener = l } return nil } func (p *TServerSocket) Addr() net.Addr { if p.listener != nil { return p.listener.Addr() } return p.addr } func (p *TServerSocket) Close() error { var err error p.mu.Lock() if p.IsListening() { err = p.listener.Close() p.listener = nil } p.mu.Unlock() return err } func (p *TServerSocket) Interrupt() error { p.mu.Lock() p.interrupted = true p.mu.Unlock() p.Close() return nil } thrift-0.19.0/lib/go/thrift/pool.go0000644000000000000000000000316614303740367017067 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "sync" ) // pool is a generic sync.Pool wrapper with bells and whistles. type pool[T any] struct { pool sync.Pool reset func(*T) } // newPool creates a new pool. // // Both generate and reset are optional. // Default generate is just new(T), // When reset is nil we don't do any additional resetting when calling get. func newPool[T any](generate func() *T, reset func(*T)) *pool[T] { if generate == nil { generate = func() *T { return new(T) } } return &pool[T]{ pool: sync.Pool{ New: func() interface{} { return generate() }, }, reset: reset, } } func (p *pool[T]) get() *T { r := p.pool.Get().(*T) if p.reset != nil { p.reset(r) } return r } func (p *pool[T]) put(r **T) { p.pool.Put(*r) *r = nil } var bufPool = newPool(nil, func(buf *bytes.Buffer) { buf.Reset() }) thrift-0.19.0/lib/go/thrift/multiplexed_protocol_test.go0000644000000000000000000000273614303740367023434 0ustar00rootroot00000000000000package thrift import ( "context" "strings" "testing" ) func TestMultiplexedProcessorMap(t *testing.T) { name := "test" processorName := "foo" processor := &TMultiplexedProcessor{} processor.RegisterDefault(&mockWrappableProcessor{ ProcessorFuncs: map[string]TProcessorFunction{ name: WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { return true, nil }, }, }, }) processor.RegisterProcessor(processorName, &mockWrappableProcessor{ ProcessorFuncs: map[string]TProcessorFunction{ name: WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { return true, nil }, }, }, }) processorMap := processor.ProcessorMap() if len(processorMap) != 2 { t.Fatalf("Wrong processor map size %#v", processorMap) } for k := range processorMap { components := strings.SplitN(k, MULTIPLEXED_SEPARATOR, 2) if len(components) == 1 { if components[0] != name { t.Fatalf("Wrong name for default processor func, expected %q, got %q", name, components[0]) } } else if len(components) == 2 { if components[0] != processorName { t.Errorf("Wrong processor name, expected %q, got %q", processorName, components[0]) } if components[1] != name { t.Errorf("Wrong name for processor func, expected %q, got %q", name, components[1]) } } else { t.Fatalf("Wrong number of components %#v", components) } } } thrift-0.19.0/lib/go/thrift/example_client_middleware_test.go0000644000000000000000000000444714303740367024346 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "log" ) // BEGIN THRIFT GENERATED CODE SECTION // // In real code this section should be from thrift generated code instead, // but for this example we just define some placeholders here. type MyEndpointRequest struct{} type MyEndpointResponse struct{} type MyService interface { MyEndpoint(ctx context.Context, req *MyEndpointRequest) (*MyEndpointResponse, error) } func NewMyServiceClient(_ TClient) MyService { // In real code this certainly won't return nil. return nil } // END THRIFT GENERATED CODE SECTION func simpleClientLoggingMiddleware(next TClient) TClient { return WrappedTClient{ Wrapped: func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { log.Printf("Before: %q", method) log.Printf("Args: %#v", args) headers, err := next.Call(ctx, method, args, result) log.Printf("After: %q", method) log.Printf("Result: %#v", result) if err != nil { log.Printf("Error: %v", err) } return headers, err }, } } // This example demonstrates how to define and use a simple logging middleware // to your thrift client. func ExampleClientMiddleware() { var ( trans TTransport protoFactory TProtocolFactory ) var client TClient client = NewTStandardClient( protoFactory.GetProtocol(trans), protoFactory.GetProtocol(trans), ) client = WrapClient(client, simpleClientLoggingMiddleware) myServiceClient := NewMyServiceClient(client) myServiceClient.MyEndpoint(context.Background(), &MyEndpointRequest{}) } thrift-0.19.0/lib/go/thrift/header_protocol.go0000644000000000000000000002520714370300523021255 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "errors" ) // THeaderProtocol is a thrift protocol that implements THeader: // https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md // // It supports either binary or compact protocol as the wrapped protocol. // // Most of the THeader handlings are happening inside THeaderTransport. type THeaderProtocol struct { transport *THeaderTransport // Will be initialized on first read/write. protocol TProtocol cfg *TConfiguration } // Deprecated: Use NewTHeaderProtocolConf instead. func NewTHeaderProtocol(trans TTransport) *THeaderProtocol { return newTHeaderProtocolConf(trans, &TConfiguration{ noPropagation: true, }) } // NewTHeaderProtocolConf creates a new THeaderProtocol from the underlying // transport with given TConfiguration. // // The passed in transport will be wrapped with THeaderTransport. // // Note that THeaderTransport handles frame and zlib by itself, // so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), // instead of rich transports like TZlibTransport or TFramedTransport. func NewTHeaderProtocolConf(trans TTransport, conf *TConfiguration) *THeaderProtocol { return newTHeaderProtocolConf(trans, conf) } func newTHeaderProtocolConf(trans TTransport, cfg *TConfiguration) *THeaderProtocol { t := NewTHeaderTransportConf(trans, cfg) p, _ := t.cfg.GetTHeaderProtocolID().GetProtocol(t) PropagateTConfiguration(p, cfg) return &THeaderProtocol{ transport: t, protocol: p, cfg: cfg, } } type tHeaderProtocolFactory struct { cfg *TConfiguration } func (f tHeaderProtocolFactory) GetProtocol(trans TTransport) TProtocol { return newTHeaderProtocolConf(trans, f.cfg) } func (f *tHeaderProtocolFactory) SetTConfiguration(cfg *TConfiguration) { f.cfg = cfg } // Deprecated: Use NewTHeaderProtocolFactoryConf instead. func NewTHeaderProtocolFactory() TProtocolFactory { return NewTHeaderProtocolFactoryConf(&TConfiguration{ noPropagation: true, }) } // NewTHeaderProtocolFactoryConf creates a factory for THeader with given // TConfiguration. func NewTHeaderProtocolFactoryConf(conf *TConfiguration) TProtocolFactory { return tHeaderProtocolFactory{ cfg: conf, } } // Transport returns the underlying transport. // // It's guaranteed to be of type *THeaderTransport. func (p *THeaderProtocol) Transport() TTransport { return p.transport } // GetReadHeaders returns the THeaderMap read from transport. func (p *THeaderProtocol) GetReadHeaders() THeaderMap { return p.transport.GetReadHeaders() } // SetWriteHeader sets a header for write. func (p *THeaderProtocol) SetWriteHeader(key, value string) { p.transport.SetWriteHeader(key, value) } // ClearWriteHeaders clears all write headers previously set. func (p *THeaderProtocol) ClearWriteHeaders() { p.transport.ClearWriteHeaders() } // AddTransform add a transform for writing. func (p *THeaderProtocol) AddTransform(transform THeaderTransformID) error { return p.transport.AddTransform(transform) } func (p *THeaderProtocol) Flush(ctx context.Context) error { return p.transport.Flush(ctx) } func (p *THeaderProtocol) WriteMessageBegin(ctx context.Context, name string, typeID TMessageType, seqID int32) error { newProto, err := p.transport.Protocol().GetProtocol(p.transport) if err != nil { return err } PropagateTConfiguration(newProto, p.cfg) p.protocol = newProto p.transport.SequenceID = seqID return p.protocol.WriteMessageBegin(ctx, name, typeID, seqID) } func (p *THeaderProtocol) WriteMessageEnd(ctx context.Context) error { if err := p.protocol.WriteMessageEnd(ctx); err != nil { return err } return p.transport.Flush(ctx) } func (p *THeaderProtocol) WriteStructBegin(ctx context.Context, name string) error { return p.protocol.WriteStructBegin(ctx, name) } func (p *THeaderProtocol) WriteStructEnd(ctx context.Context) error { return p.protocol.WriteStructEnd(ctx) } func (p *THeaderProtocol) WriteFieldBegin(ctx context.Context, name string, typeID TType, id int16) error { return p.protocol.WriteFieldBegin(ctx, name, typeID, id) } func (p *THeaderProtocol) WriteFieldEnd(ctx context.Context) error { return p.protocol.WriteFieldEnd(ctx) } func (p *THeaderProtocol) WriteFieldStop(ctx context.Context) error { return p.protocol.WriteFieldStop(ctx) } func (p *THeaderProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { return p.protocol.WriteMapBegin(ctx, keyType, valueType, size) } func (p *THeaderProtocol) WriteMapEnd(ctx context.Context) error { return p.protocol.WriteMapEnd(ctx) } func (p *THeaderProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { return p.protocol.WriteListBegin(ctx, elemType, size) } func (p *THeaderProtocol) WriteListEnd(ctx context.Context) error { return p.protocol.WriteListEnd(ctx) } func (p *THeaderProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { return p.protocol.WriteSetBegin(ctx, elemType, size) } func (p *THeaderProtocol) WriteSetEnd(ctx context.Context) error { return p.protocol.WriteSetEnd(ctx) } func (p *THeaderProtocol) WriteBool(ctx context.Context, value bool) error { return p.protocol.WriteBool(ctx, value) } func (p *THeaderProtocol) WriteByte(ctx context.Context, value int8) error { return p.protocol.WriteByte(ctx, value) } func (p *THeaderProtocol) WriteI16(ctx context.Context, value int16) error { return p.protocol.WriteI16(ctx, value) } func (p *THeaderProtocol) WriteI32(ctx context.Context, value int32) error { return p.protocol.WriteI32(ctx, value) } func (p *THeaderProtocol) WriteI64(ctx context.Context, value int64) error { return p.protocol.WriteI64(ctx, value) } func (p *THeaderProtocol) WriteDouble(ctx context.Context, value float64) error { return p.protocol.WriteDouble(ctx, value) } func (p *THeaderProtocol) WriteString(ctx context.Context, value string) error { return p.protocol.WriteString(ctx, value) } func (p *THeaderProtocol) WriteBinary(ctx context.Context, value []byte) error { return p.protocol.WriteBinary(ctx, value) } func (p *THeaderProtocol) WriteUUID(ctx context.Context, value Tuuid) error { return p.protocol.WriteUUID(ctx, value) } // ReadFrame calls underlying THeaderTransport's ReadFrame function. func (p *THeaderProtocol) ReadFrame(ctx context.Context) error { return p.transport.ReadFrame(ctx) } func (p *THeaderProtocol) ReadMessageBegin(ctx context.Context) (name string, typeID TMessageType, seqID int32, err error) { if err = p.transport.ReadFrame(ctx); err != nil { return } var newProto TProtocol newProto, err = p.transport.Protocol().GetProtocol(p.transport) if err != nil { var tAppExc TApplicationException if !errors.As(err, &tAppExc) { return } if e := p.protocol.WriteMessageBegin(ctx, "", EXCEPTION, seqID); e != nil { return } if e := tAppExc.Write(ctx, p.protocol); e != nil { return } if e := p.protocol.WriteMessageEnd(ctx); e != nil { return } if e := p.transport.Flush(ctx); e != nil { return } return } PropagateTConfiguration(newProto, p.cfg) p.protocol = newProto return p.protocol.ReadMessageBegin(ctx) } func (p *THeaderProtocol) ReadMessageEnd(ctx context.Context) error { return p.protocol.ReadMessageEnd(ctx) } func (p *THeaderProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { return p.protocol.ReadStructBegin(ctx) } func (p *THeaderProtocol) ReadStructEnd(ctx context.Context) error { return p.protocol.ReadStructEnd(ctx) } func (p *THeaderProtocol) ReadFieldBegin(ctx context.Context) (name string, typeID TType, id int16, err error) { return p.protocol.ReadFieldBegin(ctx) } func (p *THeaderProtocol) ReadFieldEnd(ctx context.Context) error { return p.protocol.ReadFieldEnd(ctx) } func (p *THeaderProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { return p.protocol.ReadMapBegin(ctx) } func (p *THeaderProtocol) ReadMapEnd(ctx context.Context) error { return p.protocol.ReadMapEnd(ctx) } func (p *THeaderProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { return p.protocol.ReadListBegin(ctx) } func (p *THeaderProtocol) ReadListEnd(ctx context.Context) error { return p.protocol.ReadListEnd(ctx) } func (p *THeaderProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { return p.protocol.ReadSetBegin(ctx) } func (p *THeaderProtocol) ReadSetEnd(ctx context.Context) error { return p.protocol.ReadSetEnd(ctx) } func (p *THeaderProtocol) ReadBool(ctx context.Context) (value bool, err error) { return p.protocol.ReadBool(ctx) } func (p *THeaderProtocol) ReadByte(ctx context.Context) (value int8, err error) { return p.protocol.ReadByte(ctx) } func (p *THeaderProtocol) ReadI16(ctx context.Context) (value int16, err error) { return p.protocol.ReadI16(ctx) } func (p *THeaderProtocol) ReadI32(ctx context.Context) (value int32, err error) { return p.protocol.ReadI32(ctx) } func (p *THeaderProtocol) ReadI64(ctx context.Context) (value int64, err error) { return p.protocol.ReadI64(ctx) } func (p *THeaderProtocol) ReadDouble(ctx context.Context) (value float64, err error) { return p.protocol.ReadDouble(ctx) } func (p *THeaderProtocol) ReadString(ctx context.Context) (value string, err error) { return p.protocol.ReadString(ctx) } func (p *THeaderProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { return p.protocol.ReadBinary(ctx) } func (p *THeaderProtocol) ReadUUID(ctx context.Context) (value Tuuid, err error) { return p.protocol.ReadUUID(ctx) } func (p *THeaderProtocol) Skip(ctx context.Context, fieldType TType) error { return p.protocol.Skip(ctx, fieldType) } // SetTConfiguration implements TConfigurationSetter. func (p *THeaderProtocol) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(p.transport, cfg) PropagateTConfiguration(p.protocol, cfg) p.cfg = cfg } var ( _ TConfigurationSetter = (*tHeaderProtocolFactory)(nil) _ TConfigurationSetter = (*THeaderProtocol)(nil) ) thrift-0.19.0/lib/go/thrift/staticcheck.conf0000644000000000000000000000017414303740367020717 0ustar00rootroot00000000000000checks = [ "inherit", "-ST1005", # To be consistent with other language libraries we need capitalized error messages. ] thrift-0.19.0/lib/go/thrift/iostream_transport.go0000644000000000000000000001314014303740367022046 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bufio" "context" "io" ) // StreamTransport is a Transport made of an io.Reader and/or an io.Writer type StreamTransport struct { io.Reader io.Writer isReadWriter bool closed bool } type StreamTransportFactory struct { Reader io.Reader Writer io.Writer isReadWriter bool } func (p *StreamTransportFactory) GetTransport(trans TTransport) (TTransport, error) { if trans != nil { t, ok := trans.(*StreamTransport) if ok { if t.isReadWriter { return NewStreamTransportRW(t.Reader.(io.ReadWriter)), nil } if t.Reader != nil && t.Writer != nil { return NewStreamTransport(t.Reader, t.Writer), nil } if t.Reader != nil && t.Writer == nil { return NewStreamTransportR(t.Reader), nil } if t.Reader == nil && t.Writer != nil { return NewStreamTransportW(t.Writer), nil } return &StreamTransport{}, nil } } if p.isReadWriter { return NewStreamTransportRW(p.Reader.(io.ReadWriter)), nil } if p.Reader != nil && p.Writer != nil { return NewStreamTransport(p.Reader, p.Writer), nil } if p.Reader != nil && p.Writer == nil { return NewStreamTransportR(p.Reader), nil } if p.Reader == nil && p.Writer != nil { return NewStreamTransportW(p.Writer), nil } return &StreamTransport{}, nil } func NewStreamTransportFactory(reader io.Reader, writer io.Writer, isReadWriter bool) *StreamTransportFactory { return &StreamTransportFactory{Reader: reader, Writer: writer, isReadWriter: isReadWriter} } func NewStreamTransport(r io.Reader, w io.Writer) *StreamTransport { return &StreamTransport{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)} } func NewStreamTransportR(r io.Reader) *StreamTransport { return &StreamTransport{Reader: bufio.NewReader(r)} } func NewStreamTransportW(w io.Writer) *StreamTransport { return &StreamTransport{Writer: bufio.NewWriter(w)} } func NewStreamTransportRW(rw io.ReadWriter) *StreamTransport { bufrw := bufio.NewReadWriter(bufio.NewReader(rw), bufio.NewWriter(rw)) return &StreamTransport{Reader: bufrw, Writer: bufrw, isReadWriter: true} } func (p *StreamTransport) IsOpen() bool { return !p.closed } // implicitly opened on creation, can't be reopened once closed func (p *StreamTransport) Open() error { if !p.closed { return NewTTransportException(ALREADY_OPEN, "StreamTransport already open.") } else { return NewTTransportException(NOT_OPEN, "cannot reopen StreamTransport.") } } // Closes both the input and output streams. func (p *StreamTransport) Close() error { if p.closed { return NewTTransportException(NOT_OPEN, "StreamTransport already closed.") } p.closed = true closedReader := false if p.Reader != nil { c, ok := p.Reader.(io.Closer) if ok { e := c.Close() closedReader = true if e != nil { return e } } p.Reader = nil } if p.Writer != nil && (!closedReader || !p.isReadWriter) { c, ok := p.Writer.(io.Closer) if ok { e := c.Close() if e != nil { return e } } p.Writer = nil } return nil } // Flushes the underlying output stream if not null. func (p *StreamTransport) Flush(ctx context.Context) error { if p.Writer == nil { return NewTTransportException(NOT_OPEN, "Cannot flush null outputStream") } f, ok := p.Writer.(Flusher) if ok { err := f.Flush() if err != nil { return NewTTransportExceptionFromError(err) } } return nil } func (p *StreamTransport) Read(c []byte) (n int, err error) { n, err = p.Reader.Read(c) if err != nil { err = NewTTransportExceptionFromError(err) } return } func (p *StreamTransport) ReadByte() (c byte, err error) { f, ok := p.Reader.(io.ByteReader) if ok { c, err = f.ReadByte() } else { c, err = readByte(p.Reader) } if err != nil { err = NewTTransportExceptionFromError(err) } return } func (p *StreamTransport) Write(c []byte) (n int, err error) { n, err = p.Writer.Write(c) if err != nil { err = NewTTransportExceptionFromError(err) } return } func (p *StreamTransport) WriteByte(c byte) (err error) { f, ok := p.Writer.(io.ByteWriter) if ok { err = f.WriteByte(c) } else { err = writeByte(p.Writer, c) } if err != nil { err = NewTTransportExceptionFromError(err) } return } func (p *StreamTransport) WriteString(s string) (n int, err error) { f, ok := p.Writer.(stringWriter) if ok { n, err = f.WriteString(s) } else { n, err = p.Writer.Write([]byte(s)) } if err != nil { err = NewTTransportExceptionFromError(err) } return } func (p *StreamTransport) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } // SetTConfiguration implements TConfigurationSetter for propagation. func (p *StreamTransport) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(p.Reader, conf) PropagateTConfiguration(p.Writer, conf) } var _ TConfigurationSetter = (*StreamTransport)(nil) thrift-0.19.0/lib/go/thrift/serializer.go0000644000000000000000000000655114303740367020270 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" ) type TSerializer struct { Transport *TMemoryBuffer Protocol TProtocol } type TStruct interface { Write(ctx context.Context, p TProtocol) error Read(ctx context.Context, p TProtocol) error } func NewTSerializer() *TSerializer { transport := NewTMemoryBufferLen(1024) protocol := NewTBinaryProtocolTransport(transport) return &TSerializer{ Transport: transport, Protocol: protocol, } } func (t *TSerializer) WriteString(ctx context.Context, msg TStruct) (s string, err error) { t.Transport.Reset() if r, ok := t.Protocol.(reseter); ok { r.Reset() } if err = msg.Write(ctx, t.Protocol); err != nil { return } if err = t.Protocol.Flush(ctx); err != nil { return } if err = t.Transport.Flush(ctx); err != nil { return } return t.Transport.String(), nil } func (t *TSerializer) Write(ctx context.Context, msg TStruct) (b []byte, err error) { t.Transport.Reset() if r, ok := t.Protocol.(reseter); ok { r.Reset() } if err = msg.Write(ctx, t.Protocol); err != nil { return } if err = t.Protocol.Flush(ctx); err != nil { return } if err = t.Transport.Flush(ctx); err != nil { return } b = append(b, t.Transport.Bytes()...) return } // TSerializerPool is the thread-safe version of TSerializer, it uses resource // pool of TSerializer under the hood. // // It must be initialized with either NewTSerializerPool or // NewTSerializerPoolSizeFactory. type TSerializerPool struct { pool *pool[TSerializer] } // NewTSerializerPool creates a new TSerializerPool. // // NewTSerializer can be used as the arg here. func NewTSerializerPool(f func() *TSerializer) *TSerializerPool { return &TSerializerPool{ pool: newPool(f, nil), } } // NewTSerializerPoolSizeFactory creates a new TSerializerPool with the given // size and protocol factory. // // Note that the size is not the limit. The TMemoryBuffer underneath can grow // larger than that. It just dictates the initial size. func NewTSerializerPoolSizeFactory(size int, factory TProtocolFactory) *TSerializerPool { return &TSerializerPool{ pool: newPool(func() *TSerializer { transport := NewTMemoryBufferLen(size) protocol := factory.GetProtocol(transport) return &TSerializer{ Transport: transport, Protocol: protocol, } }, nil), } } func (t *TSerializerPool) WriteString(ctx context.Context, msg TStruct) (string, error) { s := t.pool.get() defer t.pool.put(&s) return s.WriteString(ctx, msg) } func (t *TSerializerPool) Write(ctx context.Context, msg TStruct) ([]byte, error) { s := t.pool.get() defer t.pool.put(&s) return s.Write(ctx, msg) } thrift-0.19.0/lib/go/thrift/response_helper_test.go0000644000000000000000000000647614303740367022361 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "testing" ) func TestResponseHelperContext(t *testing.T) { ctx := context.Background() t.Run( "empty-noop", func(t *testing.T) { helper, ok := GetResponseHelper(ctx) if ok { t.Error("GetResponseHelper expected ok == false") } // Just make sure those function calls does not panic helper.SetHeader("foo", "bar") helper.ClearHeaders() }, ) t.Run( "set-get", func(t *testing.T) { trans := NewTHeaderTransport(NewTMemoryBuffer()) proto := NewTHeaderProtocol(trans) ctx = SetResponseHelper( ctx, TResponseHelper{ THeaderResponseHelper: NewTHeaderResponseHelper(proto), }, ) helper, ok := GetResponseHelper(ctx) if !ok { t.Error("GetResponseHelper expected ok == true") } if helper.THeaderResponseHelper == nil { t.Error("GetResponseHelper expected THeaderResponseHelper to be non-nil") } }, ) } func TestHeaderHelper(t *testing.T) { t.Run( "THeaderProtocol", func(t *testing.T) { trans := NewTHeaderTransport(NewTMemoryBuffer()) proto := NewTHeaderProtocol(trans) helper := NewTHeaderResponseHelper(proto) const ( key = "key" value = "value" ) helper.SetHeader(key, value) if len(trans.writeHeaders) != 1 { t.Errorf( "Expected THeaderTransport.writeHeaders to be with size of 1, got %+v", trans.writeHeaders, ) } actual := trans.writeHeaders[key] if actual != value { t.Errorf( "Expected THeaderTransport.writeHeaders to have %q:%q, got %+v", key, value, trans.writeHeaders, ) } helper.ClearHeaders() if len(trans.writeHeaders) != 0 { t.Errorf( "Expected THeaderTransport.writeHeaders to be empty after ClearHeaders call, got %+v", trans.writeHeaders, ) } }, ) t.Run( "other-protocol", func(t *testing.T) { trans := NewTMemoryBuffer() proto := NewTCompactProtocol(trans) helper := NewTHeaderResponseHelper(proto) // We only need to make sure that functions in helper // don't panic here. helper.SetHeader("foo", "bar") helper.ClearHeaders() }, ) t.Run( "zero-value", func(t *testing.T) { var helper *THeaderResponseHelper // We only need to make sure that functions in helper // don't panic here. helper.SetHeader("foo", "bar") helper.ClearHeaders() }, ) } func TestTResponseHelperZeroValue(t *testing.T) { var helper THeaderResponseHelper // We only need to make sure that functions in helper // don't panic here. helper.SetHeader("foo", "bar") helper.ClearHeaders() } thrift-0.19.0/lib/go/thrift/numeric.go0000644000000000000000000000760514303740367017562 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "math" "strconv" ) type Numeric interface { Int64() int64 Int32() int32 Int16() int16 Byte() byte Int() int Float64() float64 Float32() float32 String() string isNull() bool } type numeric struct { iValue int64 dValue float64 sValue string isNil bool } var ( INFINITY Numeric NEGATIVE_INFINITY Numeric NAN Numeric ZERO Numeric NUMERIC_NULL Numeric ) func NewNumericFromDouble(dValue float64) Numeric { if math.IsInf(dValue, 1) { return INFINITY } if math.IsInf(dValue, -1) { return NEGATIVE_INFINITY } if math.IsNaN(dValue) { return NAN } iValue := int64(dValue) sValue := strconv.FormatFloat(dValue, 'g', 10, 64) isNil := false return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} } func NewNumericFromI64(iValue int64) Numeric { dValue := float64(iValue) sValue := strconv.FormatInt(iValue, 10) isNil := false return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} } func NewNumericFromI32(iValue int32) Numeric { dValue := float64(iValue) sValue := strconv.FormatInt(int64(iValue), 10) isNil := false return &numeric{iValue: int64(iValue), dValue: dValue, sValue: sValue, isNil: isNil} } func NewNumericFromString(sValue string) Numeric { if sValue == INFINITY.String() { return INFINITY } if sValue == NEGATIVE_INFINITY.String() { return NEGATIVE_INFINITY } if sValue == NAN.String() { return NAN } iValue, _ := strconv.ParseInt(sValue, 10, 64) dValue, _ := strconv.ParseFloat(sValue, 64) isNil := len(sValue) == 0 return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNil} } func NewNumericFromJSONString(sValue string, isNull bool) Numeric { if isNull { return NewNullNumeric() } if sValue == JSON_INFINITY { return INFINITY } if sValue == JSON_NEGATIVE_INFINITY { return NEGATIVE_INFINITY } if sValue == JSON_NAN { return NAN } iValue, _ := strconv.ParseInt(sValue, 10, 64) dValue, _ := strconv.ParseFloat(sValue, 64) return &numeric{iValue: iValue, dValue: dValue, sValue: sValue, isNil: isNull} } func NewNullNumeric() Numeric { return &numeric{iValue: 0, dValue: 0.0, sValue: "", isNil: true} } func (p *numeric) Int64() int64 { return p.iValue } func (p *numeric) Int32() int32 { return int32(p.iValue) } func (p *numeric) Int16() int16 { return int16(p.iValue) } func (p *numeric) Byte() byte { return byte(p.iValue) } func (p *numeric) Int() int { return int(p.iValue) } func (p *numeric) Float64() float64 { return p.dValue } func (p *numeric) Float32() float32 { return float32(p.dValue) } func (p *numeric) String() string { return p.sValue } func (p *numeric) isNull() bool { return p.isNil } func init() { INFINITY = &numeric{iValue: 0, dValue: math.Inf(1), sValue: "Infinity", isNil: false} NEGATIVE_INFINITY = &numeric{iValue: 0, dValue: math.Inf(-1), sValue: "-Infinity", isNil: false} NAN = &numeric{iValue: 0, dValue: math.NaN(), sValue: "NaN", isNil: false} ZERO = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: false} NUMERIC_NULL = &numeric{iValue: 0, dValue: 0, sValue: "0", isNil: true} } thrift-0.19.0/lib/go/thrift/compact_protocol_test.go0000644000000000000000000000357614303740367022531 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "testing" ) func TestReadWriteCompactProtocol(t *testing.T) { ReadWriteProtocolTest(t, NewTCompactProtocolFactory()) transports := []TTransport{ NewTMemoryBuffer(), NewStreamTransportRW(bytes.NewBuffer(make([]byte, 0, 16384))), NewTFramedTransport(NewTMemoryBuffer()), } zlib0, _ := NewTZlibTransport(NewTMemoryBuffer(), 0) zlib6, _ := NewTZlibTransport(NewTMemoryBuffer(), 6) zlib9, _ := NewTZlibTransport(NewTFramedTransport(NewTMemoryBuffer()), 9) transports = append(transports, zlib0, zlib6, zlib9) for _, trans := range transports { p := NewTCompactProtocol(trans) ReadWriteBool(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteByte(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteI16(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteI32(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteI64(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteDouble(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteString(t, p, trans) p = NewTCompactProtocol(trans) ReadWriteBinary(t, p, trans) trans.Close() } } thrift-0.19.0/lib/go/thrift/buffered_transport.go0000644000000000000000000000504014303740367022005 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bufio" "context" ) type TBufferedTransportFactory struct { size int } type TBufferedTransport struct { bufio.ReadWriter tp TTransport } func (p *TBufferedTransportFactory) GetTransport(trans TTransport) (TTransport, error) { return NewTBufferedTransport(trans, p.size), nil } func NewTBufferedTransportFactory(bufferSize int) *TBufferedTransportFactory { return &TBufferedTransportFactory{size: bufferSize} } func NewTBufferedTransport(trans TTransport, bufferSize int) *TBufferedTransport { return &TBufferedTransport{ ReadWriter: bufio.ReadWriter{ Reader: bufio.NewReaderSize(trans, bufferSize), Writer: bufio.NewWriterSize(trans, bufferSize), }, tp: trans, } } func (p *TBufferedTransport) IsOpen() bool { return p.tp.IsOpen() } func (p *TBufferedTransport) Open() (err error) { return p.tp.Open() } func (p *TBufferedTransport) Close() (err error) { return p.tp.Close() } func (p *TBufferedTransport) Read(b []byte) (int, error) { n, err := p.ReadWriter.Read(b) if err != nil { p.ReadWriter.Reader.Reset(p.tp) } return n, err } func (p *TBufferedTransport) Write(b []byte) (int, error) { n, err := p.ReadWriter.Write(b) if err != nil { p.ReadWriter.Writer.Reset(p.tp) } return n, err } func (p *TBufferedTransport) Flush(ctx context.Context) error { if err := p.ReadWriter.Flush(); err != nil { p.ReadWriter.Writer.Reset(p.tp) return err } return p.tp.Flush(ctx) } func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) { return p.tp.RemainingBytes() } // SetTConfiguration implements TConfigurationSetter for propagation. func (p *TBufferedTransport) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(p.tp, conf) } var _ TConfigurationSetter = (*TBufferedTransport)(nil) thrift-0.19.0/lib/go/thrift/protocol.go0000644000000000000000000001337414370300523017747 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "errors" "fmt" ) const ( VERSION_MASK = 0xffff0000 VERSION_1 = 0x80010000 ) type TProtocol interface { WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error WriteMessageEnd(ctx context.Context) error WriteStructBegin(ctx context.Context, name string) error WriteStructEnd(ctx context.Context) error WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error WriteFieldEnd(ctx context.Context) error WriteFieldStop(ctx context.Context) error WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error WriteMapEnd(ctx context.Context) error WriteListBegin(ctx context.Context, elemType TType, size int) error WriteListEnd(ctx context.Context) error WriteSetBegin(ctx context.Context, elemType TType, size int) error WriteSetEnd(ctx context.Context) error WriteBool(ctx context.Context, value bool) error WriteByte(ctx context.Context, value int8) error WriteI16(ctx context.Context, value int16) error WriteI32(ctx context.Context, value int32) error WriteI64(ctx context.Context, value int64) error WriteDouble(ctx context.Context, value float64) error WriteString(ctx context.Context, value string) error WriteBinary(ctx context.Context, value []byte) error WriteUUID(ctx context.Context, value Tuuid) error ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) ReadMessageEnd(ctx context.Context) error ReadStructBegin(ctx context.Context) (name string, err error) ReadStructEnd(ctx context.Context) error ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) ReadFieldEnd(ctx context.Context) error ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) ReadMapEnd(ctx context.Context) error ReadListBegin(ctx context.Context) (elemType TType, size int, err error) ReadListEnd(ctx context.Context) error ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) ReadSetEnd(ctx context.Context) error ReadBool(ctx context.Context) (value bool, err error) ReadByte(ctx context.Context) (value int8, err error) ReadI16(ctx context.Context) (value int16, err error) ReadI32(ctx context.Context) (value int32, err error) ReadI64(ctx context.Context) (value int64, err error) ReadDouble(ctx context.Context) (value float64, err error) ReadString(ctx context.Context) (value string, err error) ReadBinary(ctx context.Context) (value []byte, err error) ReadUUID(ctx context.Context) (value Tuuid, err error) Skip(ctx context.Context, fieldType TType) (err error) Flush(ctx context.Context) (err error) Transport() TTransport } // The maximum recursive depth the skip() function will traverse const DEFAULT_RECURSION_DEPTH = 64 // Skips over the next data element from the provided input TProtocol object. func SkipDefaultDepth(ctx context.Context, prot TProtocol, typeId TType) (err error) { return Skip(ctx, prot, typeId, DEFAULT_RECURSION_DEPTH) } // Skips over the next data element from the provided input TProtocol object. func Skip(ctx context.Context, self TProtocol, fieldType TType, maxDepth int) (err error) { if maxDepth <= 0 { return NewTProtocolExceptionWithType(DEPTH_LIMIT, errors.New("Depth limit exceeded")) } switch fieldType { case BOOL: _, err = self.ReadBool(ctx) return case BYTE: _, err = self.ReadByte(ctx) return case I16: _, err = self.ReadI16(ctx) return case I32: _, err = self.ReadI32(ctx) return case I64: _, err = self.ReadI64(ctx) return case DOUBLE: _, err = self.ReadDouble(ctx) return case STRING: _, err = self.ReadString(ctx) return case UUID: _, err = self.ReadUUID(ctx) return case STRUCT: if _, err = self.ReadStructBegin(ctx); err != nil { return err } for { _, typeId, _, err := self.ReadFieldBegin(ctx) if err != nil { return err } if typeId == STOP { break } err = Skip(ctx, self, typeId, maxDepth-1) if err != nil { return err } self.ReadFieldEnd(ctx) } return self.ReadStructEnd(ctx) case MAP: keyType, valueType, size, err := self.ReadMapBegin(ctx) if err != nil { return err } for i := 0; i < size; i++ { err := Skip(ctx, self, keyType, maxDepth-1) if err != nil { return err } err = Skip(ctx, self, valueType, maxDepth-1) if err != nil { return err } } return self.ReadMapEnd(ctx) case SET: elemType, size, err := self.ReadSetBegin(ctx) if err != nil { return err } for i := 0; i < size; i++ { err := Skip(ctx, self, elemType, maxDepth-1) if err != nil { return err } } return self.ReadSetEnd(ctx) case LIST: elemType, size, err := self.ReadListBegin(ctx) if err != nil { return err } for i := 0; i < size; i++ { err := Skip(ctx, self, elemType, maxDepth-1) if err != nil { return err } } return self.ReadListEnd(ctx) default: return NewTProtocolExceptionWithType(INVALID_DATA, fmt.Errorf("Unknown data type %d", fieldType)) } } thrift-0.19.0/lib/go/thrift/http_client.go0000644000000000000000000001741114303740367020431 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "context" "errors" "io" "net/http" "net/url" "strconv" ) // Default to using the shared http client. Library users are // free to change this global client or specify one through // THttpClientOptions. var DefaultHttpClient *http.Client = http.DefaultClient type THttpClient struct { client *http.Client response *http.Response url *url.URL requestBuffer *bytes.Buffer header http.Header } type THttpClientTransportFactory struct { options THttpClientOptions url string } func (p *THttpClientTransportFactory) GetTransport(trans TTransport) (TTransport, error) { if trans != nil { t, ok := trans.(*THttpClient) if ok && t.url != nil { return NewTHttpClientWithOptions(t.url.String(), p.options) } } return NewTHttpClientWithOptions(p.url, p.options) } type THttpClientOptions struct { // If nil, DefaultHttpClient is used Client *http.Client } func NewTHttpClientTransportFactory(url string) *THttpClientTransportFactory { return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{}) } func NewTHttpClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { return &THttpClientTransportFactory{url: url, options: options} } func NewTHttpClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { parsedURL, err := url.Parse(urlstr) if err != nil { return nil, err } buf := make([]byte, 0, 1024) client := options.Client if client == nil { client = DefaultHttpClient } httpHeader := map[string][]string{"Content-Type": {"application/x-thrift"}} return &THttpClient{client: client, url: parsedURL, requestBuffer: bytes.NewBuffer(buf), header: httpHeader}, nil } func NewTHttpClient(urlstr string) (TTransport, error) { return NewTHttpClientWithOptions(urlstr, THttpClientOptions{}) } // Set the HTTP Header for this specific Thrift Transport // It is important that you first assert the TTransport as a THttpClient type // like so: // // httpTrans := trans.(THttpClient) // httpTrans.SetHeader("User-Agent","Thrift Client 1.0") func (p *THttpClient) SetHeader(key string, value string) { p.header.Add(key, value) } // Get the HTTP Header represented by the supplied Header Key for this specific Thrift Transport // It is important that you first assert the TTransport as a THttpClient type // like so: // // httpTrans := trans.(THttpClient) // hdrValue := httpTrans.GetHeader("User-Agent") func (p *THttpClient) GetHeader(key string) string { return p.header.Get(key) } // Deletes the HTTP Header given a Header Key for this specific Thrift Transport // It is important that you first assert the TTransport as a THttpClient type // like so: // // httpTrans := trans.(THttpClient) // httpTrans.DelHeader("User-Agent") func (p *THttpClient) DelHeader(key string) { p.header.Del(key) } func (p *THttpClient) Open() error { // do nothing return nil } func (p *THttpClient) IsOpen() bool { return p.response != nil || p.requestBuffer != nil } func (p *THttpClient) closeResponse() error { var err error if p.response != nil && p.response.Body != nil { // The docs specify that if keepalive is enabled and the response body is not // read to completion the connection will never be returned to the pool and // reused. Errors are being ignored here because if the connection is invalid // and this fails for some reason, the Close() method will do any remaining // cleanup. io.Copy(io.Discard, p.response.Body) err = p.response.Body.Close() } p.response = nil return err } func (p *THttpClient) Close() error { if p.requestBuffer != nil { p.requestBuffer.Reset() p.requestBuffer = nil } return p.closeResponse() } func (p *THttpClient) Read(buf []byte) (int, error) { if p.response == nil { return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") } n, err := p.response.Body.Read(buf) if n > 0 && (err == nil || errors.Is(err, io.EOF)) { return n, nil } return n, NewTTransportExceptionFromError(err) } func (p *THttpClient) ReadByte() (c byte, err error) { if p.response == nil { return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") } return readByte(p.response.Body) } func (p *THttpClient) Write(buf []byte) (int, error) { if p.requestBuffer == nil { return 0, NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") } return p.requestBuffer.Write(buf) } func (p *THttpClient) WriteByte(c byte) error { if p.requestBuffer == nil { return NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") } return p.requestBuffer.WriteByte(c) } func (p *THttpClient) WriteString(s string) (n int, err error) { if p.requestBuffer == nil { return 0, NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") } return p.requestBuffer.WriteString(s) } func (p *THttpClient) Flush(ctx context.Context) error { // Close any previous response body to avoid leaking connections. p.closeResponse() // Give up the ownership of the current request buffer to http request, // and create a new buffer for the next request. buf := p.requestBuffer p.requestBuffer = new(bytes.Buffer) req, err := http.NewRequest("POST", p.url.String(), buf) if err != nil { return NewTTransportExceptionFromError(err) } req.Header = p.header if ctx != nil { req = req.WithContext(ctx) } response, err := p.client.Do(req) if err != nil { return NewTTransportExceptionFromError(err) } if response.StatusCode != http.StatusOK { // Close the response to avoid leaking file descriptors. closeResponse does // more than just call Close(), so temporarily assign it and reuse the logic. p.response = response p.closeResponse() // TODO(pomack) log bad response return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, "HTTP Response code: "+strconv.Itoa(response.StatusCode)) } p.response = response return nil } func (p *THttpClient) RemainingBytes() (num_bytes uint64) { len := p.response.ContentLength if len >= 0 { return uint64(len) } const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } // Deprecated: Use NewTHttpClientTransportFactory instead. func NewTHttpPostClientTransportFactory(url string) *THttpClientTransportFactory { return NewTHttpClientTransportFactoryWithOptions(url, THttpClientOptions{}) } // Deprecated: Use NewTHttpClientTransportFactoryWithOptions instead. func NewTHttpPostClientTransportFactoryWithOptions(url string, options THttpClientOptions) *THttpClientTransportFactory { return NewTHttpClientTransportFactoryWithOptions(url, options) } // Deprecated: Use NewTHttpClientWithOptions instead. func NewTHttpPostClientWithOptions(urlstr string, options THttpClientOptions) (TTransport, error) { return NewTHttpClientWithOptions(urlstr, options) } // Deprecated: Use NewTHttpClient instead. func NewTHttpPostClient(urlstr string) (TTransport, error) { return NewTHttpClientWithOptions(urlstr, THttpClientOptions{}) } thrift-0.19.0/lib/go/thrift/duplicate_protocol.go0000644000000000000000000002455314370300523022002 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" ) type TDuplicateToProtocol struct { // Required. The actual TProtocol to do the read/write. Delegate TProtocol // Required. An TProtocol to duplicate everything read/written from Delegate. // // A typical use case of this is to use TSimpleJSONProtocol wrapping // TMemoryBuffer in a middleware to json logging requests/responses, // or wrapping a TTransport that counts bytes written to get the payload // sizes. // // DuplicateTo will be used as write only. For read calls on // TDuplicateToProtocol, the result read from Delegate will be written // to DuplicateTo. DuplicateTo TProtocol } func (tdtp *TDuplicateToProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { err := tdtp.Delegate.WriteMessageBegin(ctx, name, typeId, seqid) tdtp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid) return err } func (tdtp *TDuplicateToProtocol) WriteMessageEnd(ctx context.Context) error { err := tdtp.Delegate.WriteMessageEnd(ctx) tdtp.DuplicateTo.WriteMessageEnd(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteStructBegin(ctx context.Context, name string) error { err := tdtp.Delegate.WriteStructBegin(ctx, name) tdtp.DuplicateTo.WriteStructBegin(ctx, name) return err } func (tdtp *TDuplicateToProtocol) WriteStructEnd(ctx context.Context) error { err := tdtp.Delegate.WriteStructEnd(ctx) tdtp.DuplicateTo.WriteStructEnd(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { err := tdtp.Delegate.WriteFieldBegin(ctx, name, typeId, id) tdtp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id) return err } func (tdtp *TDuplicateToProtocol) WriteFieldEnd(ctx context.Context) error { err := tdtp.Delegate.WriteFieldEnd(ctx) tdtp.DuplicateTo.WriteFieldEnd(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteFieldStop(ctx context.Context) error { err := tdtp.Delegate.WriteFieldStop(ctx) tdtp.DuplicateTo.WriteFieldStop(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { err := tdtp.Delegate.WriteMapBegin(ctx, keyType, valueType, size) tdtp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size) return err } func (tdtp *TDuplicateToProtocol) WriteMapEnd(ctx context.Context) error { err := tdtp.Delegate.WriteMapEnd(ctx) tdtp.DuplicateTo.WriteMapEnd(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { err := tdtp.Delegate.WriteListBegin(ctx, elemType, size) tdtp.DuplicateTo.WriteListBegin(ctx, elemType, size) return err } func (tdtp *TDuplicateToProtocol) WriteListEnd(ctx context.Context) error { err := tdtp.Delegate.WriteListEnd(ctx) tdtp.DuplicateTo.WriteListEnd(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { err := tdtp.Delegate.WriteSetBegin(ctx, elemType, size) tdtp.DuplicateTo.WriteSetBegin(ctx, elemType, size) return err } func (tdtp *TDuplicateToProtocol) WriteSetEnd(ctx context.Context) error { err := tdtp.Delegate.WriteSetEnd(ctx) tdtp.DuplicateTo.WriteSetEnd(ctx) return err } func (tdtp *TDuplicateToProtocol) WriteBool(ctx context.Context, value bool) error { err := tdtp.Delegate.WriteBool(ctx, value) tdtp.DuplicateTo.WriteBool(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteByte(ctx context.Context, value int8) error { err := tdtp.Delegate.WriteByte(ctx, value) tdtp.DuplicateTo.WriteByte(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteI16(ctx context.Context, value int16) error { err := tdtp.Delegate.WriteI16(ctx, value) tdtp.DuplicateTo.WriteI16(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteI32(ctx context.Context, value int32) error { err := tdtp.Delegate.WriteI32(ctx, value) tdtp.DuplicateTo.WriteI32(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteI64(ctx context.Context, value int64) error { err := tdtp.Delegate.WriteI64(ctx, value) tdtp.DuplicateTo.WriteI64(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteDouble(ctx context.Context, value float64) error { err := tdtp.Delegate.WriteDouble(ctx, value) tdtp.DuplicateTo.WriteDouble(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteString(ctx context.Context, value string) error { err := tdtp.Delegate.WriteString(ctx, value) tdtp.DuplicateTo.WriteString(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteBinary(ctx context.Context, value []byte) error { err := tdtp.Delegate.WriteBinary(ctx, value) tdtp.DuplicateTo.WriteBinary(ctx, value) return err } func (tdtp *TDuplicateToProtocol) WriteUUID(ctx context.Context, value Tuuid) error { err := tdtp.Delegate.WriteUUID(ctx, value) tdtp.DuplicateTo.WriteUUID(ctx, value) return err } func (tdtp *TDuplicateToProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) { name, typeId, seqid, err = tdtp.Delegate.ReadMessageBegin(ctx) tdtp.DuplicateTo.WriteMessageBegin(ctx, name, typeId, seqid) return } func (tdtp *TDuplicateToProtocol) ReadMessageEnd(ctx context.Context) (err error) { err = tdtp.Delegate.ReadMessageEnd(ctx) tdtp.DuplicateTo.WriteMessageEnd(ctx) return } func (tdtp *TDuplicateToProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { name, err = tdtp.Delegate.ReadStructBegin(ctx) tdtp.DuplicateTo.WriteStructBegin(ctx, name) return } func (tdtp *TDuplicateToProtocol) ReadStructEnd(ctx context.Context) (err error) { err = tdtp.Delegate.ReadStructEnd(ctx) tdtp.DuplicateTo.WriteStructEnd(ctx) return } func (tdtp *TDuplicateToProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) { name, typeId, id, err = tdtp.Delegate.ReadFieldBegin(ctx) tdtp.DuplicateTo.WriteFieldBegin(ctx, name, typeId, id) return } func (tdtp *TDuplicateToProtocol) ReadFieldEnd(ctx context.Context) (err error) { err = tdtp.Delegate.ReadFieldEnd(ctx) tdtp.DuplicateTo.WriteFieldEnd(ctx) return } func (tdtp *TDuplicateToProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { keyType, valueType, size, err = tdtp.Delegate.ReadMapBegin(ctx) tdtp.DuplicateTo.WriteMapBegin(ctx, keyType, valueType, size) return } func (tdtp *TDuplicateToProtocol) ReadMapEnd(ctx context.Context) (err error) { err = tdtp.Delegate.ReadMapEnd(ctx) tdtp.DuplicateTo.WriteMapEnd(ctx) return } func (tdtp *TDuplicateToProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { elemType, size, err = tdtp.Delegate.ReadListBegin(ctx) tdtp.DuplicateTo.WriteListBegin(ctx, elemType, size) return } func (tdtp *TDuplicateToProtocol) ReadListEnd(ctx context.Context) (err error) { err = tdtp.Delegate.ReadListEnd(ctx) tdtp.DuplicateTo.WriteListEnd(ctx) return } func (tdtp *TDuplicateToProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { elemType, size, err = tdtp.Delegate.ReadSetBegin(ctx) tdtp.DuplicateTo.WriteSetBegin(ctx, elemType, size) return } func (tdtp *TDuplicateToProtocol) ReadSetEnd(ctx context.Context) (err error) { err = tdtp.Delegate.ReadSetEnd(ctx) tdtp.DuplicateTo.WriteSetEnd(ctx) return } func (tdtp *TDuplicateToProtocol) ReadBool(ctx context.Context) (value bool, err error) { value, err = tdtp.Delegate.ReadBool(ctx) tdtp.DuplicateTo.WriteBool(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadByte(ctx context.Context) (value int8, err error) { value, err = tdtp.Delegate.ReadByte(ctx) tdtp.DuplicateTo.WriteByte(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadI16(ctx context.Context) (value int16, err error) { value, err = tdtp.Delegate.ReadI16(ctx) tdtp.DuplicateTo.WriteI16(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadI32(ctx context.Context) (value int32, err error) { value, err = tdtp.Delegate.ReadI32(ctx) tdtp.DuplicateTo.WriteI32(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadI64(ctx context.Context) (value int64, err error) { value, err = tdtp.Delegate.ReadI64(ctx) tdtp.DuplicateTo.WriteI64(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadDouble(ctx context.Context) (value float64, err error) { value, err = tdtp.Delegate.ReadDouble(ctx) tdtp.DuplicateTo.WriteDouble(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadString(ctx context.Context) (value string, err error) { value, err = tdtp.Delegate.ReadString(ctx) tdtp.DuplicateTo.WriteString(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { value, err = tdtp.Delegate.ReadBinary(ctx) tdtp.DuplicateTo.WriteBinary(ctx, value) return } func (tdtp *TDuplicateToProtocol) ReadUUID(ctx context.Context) (value Tuuid, err error) { value, err = tdtp.Delegate.ReadUUID(ctx) tdtp.DuplicateTo.WriteUUID(ctx, value) return } func (tdtp *TDuplicateToProtocol) Skip(ctx context.Context, fieldType TType) (err error) { err = tdtp.Delegate.Skip(ctx, fieldType) tdtp.DuplicateTo.Skip(ctx, fieldType) return } func (tdtp *TDuplicateToProtocol) Flush(ctx context.Context) (err error) { err = tdtp.Delegate.Flush(ctx) tdtp.DuplicateTo.Flush(ctx) return } func (tdtp *TDuplicateToProtocol) Transport() TTransport { return tdtp.Delegate.Transport() } // SetTConfiguration implements TConfigurationSetter for propagation. func (tdtp *TDuplicateToProtocol) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(tdtp.Delegate, conf) PropagateTConfiguration(tdtp.DuplicateTo, conf) } var _ TConfigurationSetter = (*TDuplicateToProtocol)(nil) thrift-0.19.0/lib/go/thrift/transport_exception_test.go0000644000000000000000000000560514303740367023267 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "fmt" "io" "testing" ) type timeout struct{ timedout bool } func (t *timeout) Timeout() bool { return t.timedout } func (t *timeout) Error() string { return fmt.Sprintf("Timeout: %v", t.timedout) } func TestTExceptionTimeout(t *testing.T) { timeout := &timeout{true} exception := NewTTransportExceptionFromError(timeout) if timeout.Error() != exception.Error() { t.Errorf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error()) } if exception.TypeId() != TIMED_OUT { t.Errorf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId()) } if unwrapped := errors.Unwrap(exception); unwrapped != timeout { t.Errorf("Unwrapped exception did not match: expected %v, got %v", timeout, unwrapped) } } func TestTExceptionEOF(t *testing.T) { exception := NewTTransportExceptionFromError(io.EOF) if io.EOF.Error() != exception.Error() { t.Errorf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error()) } if exception.TypeId() != END_OF_FILE { t.Errorf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId()) } if unwrapped := errors.Unwrap(exception); unwrapped != io.EOF { t.Errorf("Unwrapped exception did not match: expected %v, got %v", io.EOF, unwrapped) } } func TestIsTimeoutError(t *testing.T) { te := &timeout{true} if !isTimeoutError(te) { t.Error("isTimeoutError expected true, got false") } e := NewTTransportExceptionFromError(te) if !isTimeoutError(e) { t.Error("isTimeoutError on wrapped TTransportException expected true, got false") } te = &timeout{false} if isTimeoutError(te) { t.Error("isTimeoutError expected false, got true") } e = NewTTransportExceptionFromError(te) if isTimeoutError(e) { t.Error("isTimeoutError on wrapped TTransportException expected false, got true") } err := errors.New("foo") if isTimeoutError(err) { t.Error("isTimeoutError expected false, got true") } e = NewTTransportExceptionFromError(err) if isTimeoutError(e) { t.Error("isTimeoutError on wrapped TTransportException expected false, got true") } } thrift-0.19.0/lib/go/thrift/serializer_test.go0000644000000000000000000001767414370300523021325 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "errors" "fmt" "sync" "sync/atomic" "testing" "testing/quick" ) type ProtocolFactory interface { GetProtocol(t TTransport) TProtocol } func compareStructs(m, m1 MyTestStruct) error { switch { case m.On != m1.On: return errors.New("Boolean not equal") case m.B != m1.B: return errors.New("Byte not equal") case m.Int16 != m1.Int16: return errors.New("Int16 not equal") case m.Int32 != m1.Int32: return errors.New("Int32 not equal") case m.Int64 != m1.Int64: return errors.New("Int64 not equal") case m.D != m1.D: return errors.New("Double not equal") case m.St != m1.St: return errors.New("String not equal") case len(m.Bin) != len(m1.Bin): return errors.New("Binary size not equal") case len(m.Bin) == len(m1.Bin): for i := range m.Bin { if m.Bin[i] != m1.Bin[i] { return errors.New("Binary not equal") } } case len(m.StringMap) != len(m1.StringMap): return errors.New("StringMap size not equal") case len(m.StringList) != len(m1.StringList): return errors.New("StringList size not equal") case len(m.StringSet) != len(m1.StringSet): return errors.New("StringSet size not equal") case m.E != m1.E: return errors.New("MyTestEnum not equal") default: return nil } return nil } type serializer interface { WriteString(context.Context, TStruct) (string, error) } type deserializer interface { ReadString(context.Context, TStruct, string) error } func plainSerializer(pf ProtocolFactory) serializer { t := NewTSerializer() t.Protocol = pf.GetProtocol(t.Transport) return t } func poolSerializer(pf ProtocolFactory) serializer { return NewTSerializerPool( func() *TSerializer { return plainSerializer(pf).(*TSerializer) }, ) } func plainDeserializer(pf ProtocolFactory) deserializer { d := NewTDeserializer() d.Protocol = pf.GetProtocol(d.Transport) return d } func poolDeserializer(pf ProtocolFactory) deserializer { return NewTDeserializerPool( func() *TDeserializer { return plainDeserializer(pf).(*TDeserializer) }, ) } type constructors struct { Label string Serializer func(pf ProtocolFactory) serializer Deserializer func(pf ProtocolFactory) deserializer } var implementations = []constructors{ { Label: "plain", Serializer: plainSerializer, Deserializer: plainDeserializer, }, { Label: "pool", Serializer: poolSerializer, Deserializer: poolDeserializer, }, } func ProtocolTest1(t *testing.T, pf ProtocolFactory) { for _, impl := range implementations { t.Run( impl.Label, func(test *testing.T) { t := impl.Serializer(pf) var m = MyTestStruct{} m.On = true m.B = int8(0) m.Int16 = 1 m.Int32 = 2 m.Int64 = 3 m.D = 4.1 m.St = "Test" m.Bin = make([]byte, 10) m.StringMap = make(map[string]string, 5) m.StringList = make([]string, 5) m.StringSet = make(map[string]struct{}, 5) m.E = 2 s, err := t.WriteString(context.Background(), &m) if err != nil { test.Fatalf("Unable to Serialize struct: %v", err) } t1 := impl.Deserializer(pf) var m1 MyTestStruct if err = t1.ReadString(context.Background(), &m1, s); err != nil { test.Fatalf("Unable to Deserialize struct: %v", err) } if err := compareStructs(m, m1); err != nil { test.Error(err) } }, ) } } func ProtocolTest2(t *testing.T, pf ProtocolFactory) { for _, impl := range implementations { t.Run( impl.Label, func(test *testing.T) { t := impl.Serializer(pf) var m = MyTestStruct{} m.On = false m.B = int8(0) m.Int16 = 1 m.Int32 = 2 m.Int64 = 3 m.D = 4.1 m.St = "Test" m.Bin = make([]byte, 10) m.StringMap = make(map[string]string, 5) m.StringList = make([]string, 5) m.StringSet = make(map[string]struct{}, 5) m.E = 2 s, err := t.WriteString(context.Background(), &m) if err != nil { test.Fatalf("Unable to Serialize struct: %v", err) } t1 := impl.Deserializer(pf) var m1 MyTestStruct if err = t1.ReadString(context.Background(), &m1, s); err != nil { test.Fatalf("Unable to Deserialize struct: %v", err) } if err := compareStructs(m, m1); err != nil { test.Error(err) } }, ) } } func TestSerializer(t *testing.T) { protocolFactories := make(map[string]ProtocolFactory) protocolFactories["Binary"] = NewTBinaryProtocolFactoryDefault() protocolFactories["Compact"] = NewTCompactProtocolFactory() //protocolFactories["SimpleJSON"] = NewTSimpleJSONProtocolFactory() - write only, can't be read back by design protocolFactories["JSON"] = NewTJSONProtocolFactory() tests := make(map[string]func(*testing.T, ProtocolFactory)) tests["Test 1"] = ProtocolTest1 tests["Test 2"] = ProtocolTest2 //tests["Test 3"] = ProtocolTest3 // Example of how to add additional tests for name, pf := range protocolFactories { t.Run( name, func(t *testing.T) { for label, f := range tests { t.Run( label, func(t *testing.T) { f(t, pf) }, ) } }, ) } } func TestSerializerPoolAsync(t *testing.T) { var wg sync.WaitGroup var counter atomic.Int64 s := NewTSerializerPool(NewTSerializer) d := NewTDeserializerPool(NewTDeserializer) f := func(i int64) bool { wg.Add(1) go func() { defer wg.Done() t.Run( fmt.Sprintf("#%d-%d", counter.Add(1), i), func(t *testing.T) { m := MyTestStruct{ Int64: i, } str, err := s.WriteString(context.Background(), &m) if err != nil { t.Error("serialize:", err) return } var m1 MyTestStruct if err = d.ReadString(context.Background(), &m1, str); err != nil { t.Error("deserialize:", err) return } if err := compareStructs(m, m1); err != nil { t.Error(err) } }, ) }() return true } quick.Check(f, nil) wg.Wait() } func BenchmarkSerializer(b *testing.B) { sharedSerializer := NewTSerializer() poolSerializer := NewTSerializerPool(NewTSerializer) sharedDeserializer := NewTDeserializer() poolDeserializer := NewTDeserializerPool(NewTDeserializer) cases := []struct { Label string Serializer func() serializer Deserializer func() deserializer }{ { // Baseline uses shared plain serializer/deserializer Label: "baseline", Serializer: func() serializer { return sharedSerializer }, Deserializer: func() deserializer { return sharedDeserializer }, }, { // Plain creates new serializer/deserializer on every run, // as that's how it's used in real world Label: "plain", Serializer: func() serializer { return NewTSerializer() }, Deserializer: func() deserializer { return NewTDeserializer() }, }, { // Pool uses the shared pool serializer/deserializer Label: "pool", Serializer: func() serializer { return poolSerializer }, Deserializer: func() deserializer { return poolDeserializer }, }, } for _, c := range cases { b.Run( c.Label, func(b *testing.B) { for i := 0; i < b.N; i++ { s := c.Serializer() m := MyTestStruct{} str, _ := s.WriteString(context.Background(), &m) var m1 MyTestStruct d := c.Deserializer() d.ReadString(context.Background(), &m1, str) } }, ) } } thrift-0.19.0/lib/go/thrift/http_transport.go0000644000000000000000000000407514303740367021211 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "compress/gzip" "io" "net/http" "strings" ) // NewThriftHandlerFunc is a function that create a ready to use Apache Thrift Handler function func NewThriftHandlerFunc(processor TProcessor, inPfactory, outPfactory TProtocolFactory) func(w http.ResponseWriter, r *http.Request) { return gz(func(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/x-thrift") transport := NewStreamTransport(r.Body, w) processor.Process(r.Context(), inPfactory.GetProtocol(transport), outPfactory.GetProtocol(transport)) }) } // gz transparently compresses the HTTP response if the client supports it. func gz(handler http.HandlerFunc) http.HandlerFunc { sp := newPool(func() *gzip.Writer { return gzip.NewWriter(nil) }, nil) return func(w http.ResponseWriter, r *http.Request) { if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { handler(w, r) return } w.Header().Set("Content-Encoding", "gzip") gz := sp.get() gz.Reset(w) defer func() { gz.Close() sp.put(&gz) }() gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w} handler(gzw, r) } } type gzipResponseWriter struct { io.Writer http.ResponseWriter } func (w gzipResponseWriter) Write(b []byte) (int, error) { return w.Writer.Write(b) } thrift-0.19.0/lib/go/thrift/pointerize.go0000644000000000000000000000446214370300523020274 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Pointer is the generic (type parameter) version of the helper function that // converts types to pointer types. func Pointer[T any](v T) *T { return &v } /////////////////////////////////////////////////////////////////////////////// // This file is home to helpers that convert from various base types to // respective pointer types. This is necessary because Go does not permit // references to constants, nor can a pointer type to base type be allocated // and initialized in a single expression. // // E.g., this is not allowed: // // var ip *int = &5 // // But this *is* allowed: // // func IntPtr(i int) *int { return &i } // var ip *int = IntPtr(5) // // Since pointers to base types are commonplace as [optional] fields in // exported thrift structs, we factor such helpers here. /////////////////////////////////////////////////////////////////////////////// func Float32Ptr(v float32) *float32 { return &v } func Float64Ptr(v float64) *float64 { return &v } func IntPtr(v int) *int { return &v } func Int8Ptr(v int8) *int8 { return &v } func Int16Ptr(v int16) *int16 { return &v } func Int32Ptr(v int32) *int32 { return &v } func Int64Ptr(v int64) *int64 { return &v } func StringPtr(v string) *string { return &v } func Uint32Ptr(v uint32) *uint32 { return &v } func Uint64Ptr(v uint64) *uint64 { return &v } func BoolPtr(v bool) *bool { return &v } func ByteSlicePtr(v []byte) *[]byte { return &v } func TuuidPtr(v Tuuid) *Tuuid { return &v } thrift-0.19.0/lib/go/thrift/common_test.go0000644000000000000000000000701014303740367020435 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "fmt" ) type mockProcessor struct { ProcessFunc func(in, out TProtocol) (bool, TException) } func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { return m.ProcessFunc(in, out) } func (m *mockProcessor) ProcessorMap() map[string]TProcessorFunction { return map[string]TProcessorFunction{ "mock": WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { return m.ProcessFunc(in, out) }, }, } } func (m *mockProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) {} type mockWrappedProcessorContextKey int const ( processorName mockWrappedProcessorContextKey = iota ) // setMockWrappableProcessorName sets the "name" of the TProcessorFunction to // call on a mockWrappableProcessor when calling Process. // // In a normal TProcessor, the request name is read from the request itself // which happens in TProcessor.Process, so it is not passed into the call to // Process itself, to get around this in testing, mockWrappableProcessor calls // getMockWrappableProcessorName to get the name to use from the context // object. func setMockWrappableProcessorName(ctx context.Context, name string) context.Context { return context.WithValue(ctx, processorName, name) } // getMockWrappableProcessorName gets the "name" of the TProcessorFunction to // call on a mockWrappableProcessor when calling Process. func getMockWrappableProcessorName(ctx context.Context) (string, bool) { val, ok := ctx.Value(processorName).(string) return val, ok } // mockWrappableProcessor can be used to create a mock object that fufills the // TProcessor interface in testing. type mockWrappableProcessor struct { ProcessorFuncs map[string]TProcessorFunction } // Process calls the TProcessorFunction assigned to the "name" set on the // context object by setMockWrappableProcessorName. // // If no name is set on the context or there is no TProcessorFunction mapped to // that name, the call will panic. func (p *mockWrappableProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { name, ok := getMockWrappableProcessorName(ctx) if !ok { panic("MockWrappableProcessorName not set on context") } processor, ok := p.ProcessorMap()[name] if !ok { panic(fmt.Sprintf("No processor set for name %q", name)) } return processor.Process(ctx, 0, in, out) } func (p *mockWrappableProcessor) ProcessorMap() map[string]TProcessorFunction { return p.ProcessorFuncs } func (p *mockWrappableProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) { p.ProcessorFuncs[name] = processorFunc } var ( _ TProcessor = (*mockProcessor)(nil) _ TProcessor = (*mockWrappableProcessor)(nil) ) thrift-0.19.0/lib/go/thrift/messagetype.go0000644000000000000000000000212214303740367020433 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Message type constants in the Thrift protocol. type TMessageType int32 const ( INVALID_TMESSAGE_TYPE TMessageType = 0 CALL TMessageType = 1 REPLY TMessageType = 2 EXCEPTION TMessageType = 3 ONEWAY TMessageType = 4 ) thrift-0.19.0/lib/go/thrift/simple_server.go0000644000000000000000000002670114472647462021006 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "errors" "fmt" "io" "net" "sync" "sync/atomic" "time" ) // ServerConnectivityCheckInterval defines the ticker interval used by // connectivity check in thrift compiled TProcessorFunc implementations. // // It's defined as a variable instead of constant, so that thrift server // implementations can change its value to control the behavior. // // If it's changed to <=0, the feature will be disabled. var ServerConnectivityCheckInterval = time.Millisecond * 5 // ServerStopTimeout defines max stop wait duration used by // server stop to avoid hanging too long to wait for all client connections to be closed gracefully. // // It's defined as a variable instead of constant, so that thrift server // implementations can change its value to control the behavior. // // If it's set to <=0, the feature will be disabled(by default), and the server will wait for // for all the client connections to be closed gracefully. var ServerStopTimeout = time.Duration(0) /* * This is not a typical TSimpleServer as it is not blocked after accept a socket. * It is more like a TThreadedServer that can handle different connections in different goroutines. * This will work if golang user implements a conn-pool like thing in client side. */ type TSimpleServer struct { closed atomic.Int32 wg sync.WaitGroup mu sync.Mutex stopChan chan struct{} processorFactory TProcessorFactory serverTransport TServerTransport inputTransportFactory TTransportFactory outputTransportFactory TTransportFactory inputProtocolFactory TProtocolFactory outputProtocolFactory TProtocolFactory // Headers to auto forward in THeaderProtocol forwardHeaders []string logger Logger } func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { return NewTSimpleServerFactory2(NewTProcessorFactory(processor), serverTransport) } func NewTSimpleServer4(processor TProcessor, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { return NewTSimpleServerFactory4(NewTProcessorFactory(processor), serverTransport, transportFactory, protocolFactory, ) } func NewTSimpleServer6(processor TProcessor, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { return NewTSimpleServerFactory6(NewTProcessorFactory(processor), serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, ) } func NewTSimpleServerFactory2(processorFactory TProcessorFactory, serverTransport TServerTransport) *TSimpleServer { return NewTSimpleServerFactory6(processorFactory, serverTransport, NewTTransportFactory(), NewTTransportFactory(), NewTBinaryProtocolFactoryDefault(), NewTBinaryProtocolFactoryDefault(), ) } func NewTSimpleServerFactory4(processorFactory TProcessorFactory, serverTransport TServerTransport, transportFactory TTransportFactory, protocolFactory TProtocolFactory) *TSimpleServer { return NewTSimpleServerFactory6(processorFactory, serverTransport, transportFactory, transportFactory, protocolFactory, protocolFactory, ) } func NewTSimpleServerFactory6(processorFactory TProcessorFactory, serverTransport TServerTransport, inputTransportFactory TTransportFactory, outputTransportFactory TTransportFactory, inputProtocolFactory TProtocolFactory, outputProtocolFactory TProtocolFactory) *TSimpleServer { return &TSimpleServer{ processorFactory: processorFactory, serverTransport: serverTransport, inputTransportFactory: inputTransportFactory, outputTransportFactory: outputTransportFactory, inputProtocolFactory: inputProtocolFactory, outputProtocolFactory: outputProtocolFactory, stopChan: make(chan struct{}), } } func (p *TSimpleServer) ProcessorFactory() TProcessorFactory { return p.processorFactory } func (p *TSimpleServer) ServerTransport() TServerTransport { return p.serverTransport } func (p *TSimpleServer) InputTransportFactory() TTransportFactory { return p.inputTransportFactory } func (p *TSimpleServer) OutputTransportFactory() TTransportFactory { return p.outputTransportFactory } func (p *TSimpleServer) InputProtocolFactory() TProtocolFactory { return p.inputProtocolFactory } func (p *TSimpleServer) OutputProtocolFactory() TProtocolFactory { return p.outputProtocolFactory } func (p *TSimpleServer) Listen() error { return p.serverTransport.Listen() } // SetForwardHeaders sets the list of header keys that will be auto forwarded // while using THeaderProtocol. // // "forward" means that when the server is also a client to other upstream // thrift servers, the context object user gets in the processor functions will // have both read and write headers set, with write headers being forwarded. // Users can always override the write headers by calling SetWriteHeaderList // before calling thrift client functions. func (p *TSimpleServer) SetForwardHeaders(headers []string) { size := len(headers) if size == 0 { p.forwardHeaders = nil return } keys := make([]string, size) copy(keys, headers) p.forwardHeaders = keys } // SetLogger sets the logger used by this TSimpleServer. // // If no logger was set before Serve is called, a default logger using standard // log library will be used. func (p *TSimpleServer) SetLogger(logger Logger) { p.logger = logger } func (p *TSimpleServer) innerAccept() (int32, error) { client, err := p.serverTransport.Accept() p.mu.Lock() defer p.mu.Unlock() closed := p.closed.Load() if closed != 0 { return closed, nil } if err != nil { return 0, err } if client != nil { ctx, cancel := context.WithCancel(context.Background()) p.wg.Add(2) go func() { defer p.wg.Done() defer cancel() if err := p.processRequests(client); err != nil { p.logger(fmt.Sprintf("error processing request: %v", err)) } }() go func() { defer p.wg.Done() select { case <-ctx.Done(): // client exited, do nothing case <-p.stopChan: // TSimpleServer.Close called, close the client connection client.Close() } }() } return 0, nil } func (p *TSimpleServer) AcceptLoop() error { for { closed, err := p.innerAccept() if err != nil { return err } if closed != 0 { return nil } } } func (p *TSimpleServer) Serve() error { p.logger = fallbackLogger(p.logger) err := p.Listen() if err != nil { return err } p.AcceptLoop() return nil } func (p *TSimpleServer) Stop() error { p.mu.Lock() defer p.mu.Unlock() if !p.closed.CompareAndSwap(0, 1) { // Already closed return nil } p.serverTransport.Interrupt() ctx, cancel := context.WithCancel(context.Background()) go func() { defer cancel() p.wg.Wait() }() if ServerStopTimeout > 0 { timer := time.NewTimer(ServerStopTimeout) select { case <-timer.C: case <-ctx.Done(): } close(p.stopChan) timer.Stop() } <-ctx.Done() p.stopChan = make(chan struct{}) return nil } // If err is actually EOF or NOT_OPEN, return nil, otherwise return err as-is. func treatEOFErrorsAsNil(err error) error { if err == nil { return nil } if errors.Is(err, io.EOF) { return nil } var te TTransportException // NOT_OPEN returned by processor.Process is usually caused by client // abandoning the connection (e.g. client side time out, or just client // closes connections from the pool because of shutting down). // Those logs will be very noisy, so suppress those logs as well. if errors.As(err, &te) && (te.TypeId() == END_OF_FILE || te.TypeId() == NOT_OPEN) { return nil } return err } func (p *TSimpleServer) processRequests(client TTransport) (err error) { defer func() { err = treatEOFErrorsAsNil(err) }() processor := p.processorFactory.GetProcessor(client) inputTransport, err := p.inputTransportFactory.GetTransport(client) if err != nil { return err } inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) var outputTransport TTransport var outputProtocol TProtocol // for THeaderProtocol, we must use the same protocol instance for // input and output so that the response is in the same dialect that // the server detected the request was in. headerProtocol, ok := inputProtocol.(*THeaderProtocol) if ok { outputProtocol = inputProtocol } else { oTrans, err := p.outputTransportFactory.GetTransport(client) if err != nil { return err } outputTransport = oTrans outputProtocol = p.outputProtocolFactory.GetProtocol(outputTransport) } if inputTransport != nil { defer inputTransport.Close() } if outputTransport != nil { defer outputTransport.Close() } for { if p.closed.Load() != 0 { return nil } ctx := SetResponseHelper( defaultCtx, TResponseHelper{ THeaderResponseHelper: NewTHeaderResponseHelper(outputProtocol), }, ) if headerProtocol != nil { // We need to call ReadFrame here, otherwise we won't // get any headers on the AddReadTHeaderToContext call. // // ReadFrame is safe to be called multiple times so it // won't break when it's called again later when we // actually start to read the message. if err := headerProtocol.ReadFrame(ctx); err != nil { return err } ctx = AddReadTHeaderToContext(ctx, headerProtocol.GetReadHeaders()) ctx = SetWriteHeaderList(ctx, p.forwardHeaders) } ok, err := processor.Process(ctx, inputProtocol, outputProtocol) if errors.Is(err, ErrAbandonRequest) { err := client.Close() if errors.Is(err, net.ErrClosed) { // In this case, it's kinda expected to get // net.ErrClosed, treat that as no-error return nil } return err } if errors.As(err, new(TTransportException)) && err != nil { return err } var tae TApplicationException if errors.As(err, &tae) && tae.TypeId() == UNKNOWN_METHOD { continue } if !ok { break } } return nil } // ErrAbandonRequest is a special error that server handler implementations can // return to indicate that the request has been abandoned. // // TSimpleServer and compiler generated Process functions will check for this // error, and close the client connection instead of trying to write the error // back to the client. // // It shall only be used when the server handler implementation know that the // client already abandoned the request (by checking that the passed in context // is already canceled, for example). // // It also implements the interface defined by errors.Unwrap and always unwrap // to context.Canceled error. var ErrAbandonRequest = abandonRequestError{} type abandonRequestError struct{} func (abandonRequestError) Error() string { return "request abandoned" } func (abandonRequestError) Unwrap() error { return context.Canceled } thrift-0.19.0/lib/go/thrift/header_context_test.go0000644000000000000000000000573614303740367022156 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "reflect" "testing" ) func TestSetGetUnsetHeader(t *testing.T) { const ( key = "foo" value = "bar" ) ctx := context.Background() ctx = SetHeader(ctx, key, value) checkGet := func(t *testing.T, ctx context.Context) { t.Helper() got, ok := GetHeader(ctx, key) if !ok { t.Fatalf("Cannot get header %q back after setting it.", key) } if got != value { t.Fatalf("Header value expected %q, got %q instead", value, got) } } checkGet(t, ctx) t.Run( "NoConflicts", func(t *testing.T) { type otherType string const otherValue = "bar2" ctx = context.WithValue(ctx, otherType(key), otherValue) checkGet(t, ctx) }, ) t.Run( "GetHeaderOnNonExistKey", func(t *testing.T) { const otherKey = "foo2" if _, ok := GetHeader(ctx, otherKey); ok { t.Errorf("GetHeader returned ok on non-existing key %q", otherKey) } }, ) t.Run( "Unset", func(t *testing.T) { ctx := UnsetHeader(ctx, key) if _, ok := GetHeader(ctx, key); ok { t.Errorf("GetHeader returned ok on unset key %q", key) } }, ) } func TestReadKeyList(t *testing.T) { headers := THeaderMap{ "key1": "value1", "key2": "value2", } ctx := context.Background() ctx = AddReadTHeaderToContext(ctx, headers) got := make(THeaderMap) keys := GetReadHeaderList(ctx) t.Logf("keys: %+v", keys) for _, key := range keys { value, ok := GetHeader(ctx, key) if ok { got[key] = value } else { t.Errorf("Cannot get key %q from context", key) } } if !reflect.DeepEqual(headers, got) { t.Errorf("Expected header map %+v, got %+v", headers, got) } writtenKeys := GetWriteHeaderList(ctx) if len(writtenKeys) > 0 { t.Errorf( "Expected empty GetWriteHeaderList() result, got %+v", writtenKeys, ) } } func TestWriteKeyList(t *testing.T) { keys := []string{ "key1", "key2", } ctx := context.Background() ctx = SetWriteHeaderList(ctx, keys) got := GetWriteHeaderList(ctx) if !reflect.DeepEqual(keys, got) { t.Errorf("Expected header keys %+v, got %+v", keys, got) } readKeys := GetReadHeaderList(ctx) if len(readKeys) > 0 { t.Errorf( "Expected empty GetReadHeaderList() result, got %+v", readKeys, ) } } thrift-0.19.0/lib/go/thrift/type.go0000644000000000000000000000267414370300523017070 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Type constants in the Thrift protocol type TType byte const ( STOP = 0 VOID = 1 BOOL = 2 BYTE = 3 I08 = 3 DOUBLE = 4 I16 = 6 I32 = 8 I64 = 10 STRING = 11 UTF7 = 11 STRUCT = 12 MAP = 13 SET = 14 LIST = 15 UUID = 16 ) var typeNames = map[int]string{ STOP: "STOP", VOID: "VOID", BOOL: "BOOL", BYTE: "BYTE", DOUBLE: "DOUBLE", I16: "I16", I32: "I32", I64: "I64", STRING: "STRING", STRUCT: "STRUCT", MAP: "MAP", SET: "SET", LIST: "LIST", UUID: "UUID", } func (p TType) String() string { if s, ok := typeNames[int(p)]; ok { return s } return "Unknown" } thrift-0.19.0/lib/go/thrift/exception.go0000644000000000000000000001057514303740367020116 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "reflect" ) // Generic Thrift exception type TException interface { error TExceptionType() TExceptionType } // Prepends additional information to an error without losing the Thrift exception interface func PrependError(prepend string, err error) error { msg := prepend + err.Error() var te TException if errors.As(err, &te) { switch te.TExceptionType() { case TExceptionTypeTransport: if t, ok := err.(TTransportException); ok { return prependTTransportException(prepend, t) } case TExceptionTypeProtocol: if t, ok := err.(TProtocolException); ok { return prependTProtocolException(prepend, t) } case TExceptionTypeApplication: var t TApplicationException if errors.As(err, &t) { return NewTApplicationException(t.TypeId(), msg) } } return wrappedTException{ err: err, msg: msg, tExceptionType: te.TExceptionType(), } } return errors.New(msg) } // TExceptionType is an enum type to categorize different "subclasses" of TExceptions. type TExceptionType byte // TExceptionType values const ( TExceptionTypeUnknown TExceptionType = iota TExceptionTypeCompiled // TExceptions defined in thrift files and generated by thrift compiler TExceptionTypeApplication // TApplicationExceptions TExceptionTypeProtocol // TProtocolExceptions TExceptionTypeTransport // TTransportExceptions ) // WrapTException wraps an error into TException. // // If err is nil or already TException, it's returned as-is. // Otherwise it will be wraped into TException with TExceptionType() returning // TExceptionTypeUnknown, and Unwrap() returning the original error. func WrapTException(err error) TException { if err == nil { return nil } if te, ok := err.(TException); ok { return te } return wrappedTException{ err: err, msg: err.Error(), tExceptionType: TExceptionTypeUnknown, } } type wrappedTException struct { err error msg string tExceptionType TExceptionType } func (w wrappedTException) Error() string { return w.msg } func (w wrappedTException) TExceptionType() TExceptionType { return w.tExceptionType } func (w wrappedTException) Unwrap() error { return w.err } var _ TException = wrappedTException{} // ExtractExceptionFromResult extracts exceptions defined in thrift IDL from // result TStruct used in TClient.Call. // // For a endpoint defined in thrift IDL like this: // // service MyService { // FooResponse foo(1: FooRequest request) throws ( // 1: Exception1 error1, // 2: Exception2 error2, // ) // } // // The thrift compiler generated go code for the result TStruct would be like: // // type MyServiceFooResult struct { // Success *FooResponse `thrift:"success,0" db:"success" json:"success,omitempty"` // Error1 *Exception1 `thrift:"error1,1" db:"error1" json:"error1,omitempty"` // Error2 *Exception2 `thrift:"error2,2" db:"error2" json:"error2,omitempty"` // } // // And this function extracts the first non-nil exception out of // *MyServiceFooResult. func ExtractExceptionFromResult(result TStruct) error { v := reflect.Indirect(reflect.ValueOf(result)) if v.Kind() != reflect.Struct { return nil } typ := v.Type() for i := 0; i < v.NumField(); i++ { if typ.Field(i).Name == "Success" { continue } field := v.Field(i) if field.IsZero() { continue } tExc, ok := field.Interface().(TException) if ok && tExc != nil && tExc.TExceptionType() == TExceptionTypeCompiled { return tExc } } return nil } thrift-0.19.0/lib/go/thrift/uuid_test.go0000644000000000000000000001341414370300523020106 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "fmt" "testing" "testing/quick" ) func TestHexToByte(t *testing.T) { for _, c := range []struct { s string b byte fail bool }{ { s: "ff", b: 0xff, }, { s: "FF", b: 0xff, }, { s: "00", b: 0, }, { s: "77", b: 0x77, }, { s: "aC", b: 0xac, }, { s: "xx", fail: true, }, { s: "x0", fail: true, }, { s: "fx", fail: true, }, } { t.Run(c.s, func(t *testing.T) { b, ok := hexToByte(c.s[0], c.s[1]) if ok != !c.fail { t.Errorf("Want failure, got %x, %v", b, ok) } if !c.fail && b != c.b { t.Errorf("Want %x, got %x", c.b, b) } }) } } func TestUUIDString(t *testing.T) { for _, c := range []struct { uuid Tuuid want string }{ { uuid: Tuuid{}, want: "00000000-0000-0000-0000-000000000000", }, { uuid: Tuuid{ 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, want: "6ba7b810-9dad-11d1-80b4-00c04fd430c8", }, { uuid: Tuuid{ 0x6b, 0xa7, 0xB8, 0x11, 0x9d, 0xAd, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, want: "6ba7b811-9dad-11d1-80b4-00c04fd430c8", }, { uuid: Tuuid{ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, want: "6ba7b812-9dad-11d1-80b4-00c04fd430c8", }, { uuid: Tuuid{ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, want: "6ba7b814-9dad-11d1-80b4-00c04fd430c8", }, } { t.Run(fmt.Sprintf("% 02x", c.uuid[:]), func(t *testing.T) { got := c.uuid.String() if got != c.want { t.Errorf("got %q, want %q", got, c.want) } }) } } func TestUUIDParse(t *testing.T) { for _, c := range []struct { uuid string want Tuuid err bool }{ { uuid: "00000000-0000-0000-0000-000000000000", want: Tuuid{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }, { uuid: "6BA7B810-9DAD-11D1-80B4-00C04FD430C8", want: Tuuid{ 0x6B, 0xA7, 0xB8, 0x10, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8, }, }, { uuid: "6ba7B811-9dAd-11d1-80b4-00c04fd430c8", want: Tuuid{ 0x6b, 0xa7, 0xB8, 0x11, 0x9d, 0xAd, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, }, { uuid: "6ba7b812-9dad-11d1-80b4-00c04fd430c8", want: Tuuid{ 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, }, { uuid: "6ba7b814-9dad-11d1-80b4-00c04fd430c8", want: Tuuid{ 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8, }, }, { uuid: "00000000000000000000000000000000", err: true, // not in canonical form }, { uuid: "6ba7b810-9d-ad11d1-80b4-00c04fd430c8", err: true, // wrong position of hyphens }, { uuid: "urn:uuid:6ba7b811-9dad-11d1-80b4-00c04fd430c8", err: true, // urn form is not supported }, { uuid: "{6ba7b812-9dad-11d1-80b4-00c04fd430c8}", err: true, // guid with braces form is not supported }, { uuid: "6xa7b814-9dad-11d1-80b4-00c04fd430c8", err: true, // non-hex numbers }, } { t.Run(c.uuid, func(t *testing.T) { uuid, err := ParseTuuid(c.uuid) if c.err { if err == nil { t.Errorf("Got %v, want error", uuid) } } else { if err != nil { t.Errorf("Failed to parse: %v", err) } if uuid != c.want { t.Errorf("Got %v, want %v", uuid, c.want) } } }) } } func TestUUIDQuick(t *testing.T) { f := func(u Tuuid) bool { s := u.String() parsed, err := ParseTuuid(s) if err != nil { t.Error(err) } if parsed != u { t.Errorf("Parsed %v want %v", parsed, u) } return !t.Failed() } if err := quick.Check(f, nil); err != nil { t.Error(err) } } func BenchmarkUUIDParse(b *testing.B) { for _, s := range []string{ "00000000-0000-0000-0000-000000000000", "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "6ba7b811-9dad-11d1-80b4-00c04fd430c8", "6ba7b812-9dad-11d1-80b4-00c04fd430c8", "6ba7b814-9dad-11d1-80b4-00c04fd430c8", } { b.Run(s, func(b *testing.B) { b.ReportAllocs() if _, err := ParseTuuid(s); err != nil { b.Fatalf("Unable to parse %q: %v", s, err) } b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { ParseTuuid(s) } }) }) } } func BenchmarkUUIDString(b *testing.B) { for _, u := range []Tuuid{ {}, Must(ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8")), Must(ParseTuuid("6ba7b811-9dad-11d1-80b4-00c04fd430c8")), Must(ParseTuuid("6ba7b812-9dad-11d1-80b4-00c04fd430c8")), Must(ParseTuuid("6ba7b814-9dad-11d1-80b4-00c04fd430c8")), } { b.Run(u.String(), func(b *testing.B) { b.ReportAllocs() b.RunParallel(func(pb *testing.PB) { for pb.Next() { _ = u.String() } }) }) } } thrift-0.19.0/lib/go/thrift/multiplexed_protocol.go0000644000000000000000000002011114303740367022360 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "fmt" "strings" ) /* TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift client to communicate with a multiplexing Thrift server, by prepending the service name to the function name during function calls. NOTE: THIS IS NOT USED BY SERVERS. On the server, use TMultiplexedProcessor to handle request from a multiplexing client. This example uses a single socket transport to invoke two services: socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) transport := thrift.NewTFramedTransport(socket) protocol := thrift.NewTBinaryProtocolTransport(transport) mp := thrift.NewTMultiplexedProtocol(protocol, "Calculator") service := Calculator.NewCalculatorClient(mp) mp2 := thrift.NewTMultiplexedProtocol(protocol, "WeatherReport") service2 := WeatherReport.NewWeatherReportClient(mp2) err := transport.Open() if err != nil { t.Fatal("Unable to open client socket", err) } fmt.Println(service.Add(2,2)) fmt.Println(service2.GetTemperature()) */ type TMultiplexedProtocol struct { TProtocol serviceName string } const MULTIPLEXED_SEPARATOR = ":" func NewTMultiplexedProtocol(protocol TProtocol, serviceName string) *TMultiplexedProtocol { return &TMultiplexedProtocol{ TProtocol: protocol, serviceName: serviceName, } } func (t *TMultiplexedProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { if typeId == CALL || typeId == ONEWAY { return t.TProtocol.WriteMessageBegin(ctx, t.serviceName+MULTIPLEXED_SEPARATOR+name, typeId, seqid) } else { return t.TProtocol.WriteMessageBegin(ctx, name, typeId, seqid) } } /* TMultiplexedProcessor is a TProcessor allowing a single TServer to provide multiple services. To do so, you instantiate the processor and then register additional processors with it, as shown in the following example: var processor = thrift.NewTMultiplexedProcessor() firstProcessor := processor.RegisterProcessor("FirstService", firstProcessor) processor.registerProcessor( "Calculator", Calculator.NewCalculatorProcessor(&CalculatorHandler{}), ) processor.registerProcessor( "WeatherReport", WeatherReport.NewWeatherReportProcessor(&WeatherReportHandler{}), ) serverTransport, err := thrift.NewTServerSocketTimeout(addr, TIMEOUT) if err != nil { t.Fatal("Unable to create server socket", err) } server := thrift.NewTSimpleServer2(processor, serverTransport) server.Serve(); */ type TMultiplexedProcessor struct { serviceProcessorMap map[string]TProcessor DefaultProcessor TProcessor } func NewTMultiplexedProcessor() *TMultiplexedProcessor { return &TMultiplexedProcessor{ serviceProcessorMap: make(map[string]TProcessor), } } // ProcessorMap returns a mapping of "{ProcessorName}{MULTIPLEXED_SEPARATOR}{FunctionName}" // to TProcessorFunction for any registered processors. If there is also a // DefaultProcessor, the keys for the methods on that processor will simply be // "{FunctionName}". If the TMultiplexedProcessor has both a DefaultProcessor and // other registered processors, then the keys will be a mix of both formats. // // The implementation differs with other TProcessors in that the map returned is // a new map, while most TProcessors just return their internal mapping directly. // This means that edits to the map returned by this implementation of ProcessorMap // will not affect the underlying mapping within the TMultiplexedProcessor. func (t *TMultiplexedProcessor) ProcessorMap() map[string]TProcessorFunction { processorFuncMap := make(map[string]TProcessorFunction) for name, processor := range t.serviceProcessorMap { for method, processorFunc := range processor.ProcessorMap() { processorFuncName := name + MULTIPLEXED_SEPARATOR + method processorFuncMap[processorFuncName] = processorFunc } } if t.DefaultProcessor != nil { for method, processorFunc := range t.DefaultProcessor.ProcessorMap() { processorFuncMap[method] = processorFunc } } return processorFuncMap } // AddToProcessorMap updates the underlying TProcessor ProccessorMaps depending on // the format of "name". // // If "name" is in the format "{ProcessorName}{MULTIPLEXED_SEPARATOR}{FunctionName}", // then it sets the given TProcessorFunction on the inner TProcessor with the // ProcessorName component using the FunctionName component. // // If "name" is just in the format "{FunctionName}", that is to say there is no // MULTIPLEXED_SEPARATOR, and the TMultiplexedProcessor has a DefaultProcessor // configured, then it will set the given TProcessorFunction on the DefaultProcessor // using the given name. // // If there is not a TProcessor available for the given name, then this function // does nothing. This can happen when there is no TProcessor registered for // the given ProcessorName or if all that is given is the FunctionName and there // is no DefaultProcessor set. func (t *TMultiplexedProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) { components := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) if len(components) != 2 { if t.DefaultProcessor != nil && len(components) == 1 { t.DefaultProcessor.AddToProcessorMap(components[0], processorFunc) } return } processorName := components[0] funcName := components[1] if processor, ok := t.serviceProcessorMap[processorName]; ok { processor.AddToProcessorMap(funcName, processorFunc) } } // verify that TMultiplexedProcessor implements TProcessor var _ TProcessor = (*TMultiplexedProcessor)(nil) func (t *TMultiplexedProcessor) RegisterDefault(processor TProcessor) { t.DefaultProcessor = processor } func (t *TMultiplexedProcessor) RegisterProcessor(name string, processor TProcessor) { if t.serviceProcessorMap == nil { t.serviceProcessorMap = make(map[string]TProcessor) } t.serviceProcessorMap[name] = processor } func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { name, typeId, seqid, err := in.ReadMessageBegin(ctx) if err != nil { return false, NewTProtocolException(err) } if typeId != CALL && typeId != ONEWAY { return false, NewTProtocolException(fmt.Errorf("Unexpected message type %v", typeId)) } //extract the service name v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) if len(v) != 2 { if t.DefaultProcessor != nil { smb := NewStoredMessageProtocol(in, name, typeId, seqid) return t.DefaultProcessor.Process(ctx, smb, out) } return false, NewTProtocolException(fmt.Errorf( "Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", name, )) } actualProcessor, ok := t.serviceProcessorMap[v[0]] if !ok { return false, NewTProtocolException(fmt.Errorf( "Service name not found: %s. Did you forget to call registerProcessor()?", v[0], )) } smb := NewStoredMessageProtocol(in, v[1], typeId, seqid) return actualProcessor.Process(ctx, smb, out) } //Protocol that use stored message for ReadMessageBegin type storedMessageProtocol struct { TProtocol name string typeId TMessageType seqid int32 } func NewStoredMessageProtocol(protocol TProtocol, name string, typeId TMessageType, seqid int32) *storedMessageProtocol { return &storedMessageProtocol{protocol, name, typeId, seqid} } func (s *storedMessageProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqid int32, err error) { return s.name, s.typeId, s.seqid, nil } thrift-0.19.0/lib/go/thrift/transport.go0000644000000000000000000000340014303740367020141 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "errors" "io" ) var errTransportInterrupted = errors.New("Transport Interrupted") type Flusher interface { Flush() (err error) } type ContextFlusher interface { Flush(ctx context.Context) (err error) } type ReadSizeProvider interface { RemainingBytes() (num_bytes uint64) } // Encapsulates the I/O layer type TTransport interface { io.ReadWriteCloser ContextFlusher ReadSizeProvider // Opens the transport for communication Open() error // Returns true if the transport is open IsOpen() bool } type stringWriter interface { WriteString(s string) (n int, err error) } // This is "enchanced" transport with extra capabilities. You need to use one of these // to construct protocol. // Notably, TSocket does not implement this interface, and it is always a mistake to use // TSocket directly in protocol. type TRichTransport interface { io.ReadWriter io.ByteReader io.ByteWriter stringWriter ContextFlusher ReadSizeProvider } thrift-0.19.0/lib/go/thrift/compact_protocol.go0000644000000000000000000006025614370300523021456 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "encoding/binary" "errors" "fmt" "io" "math" ) const ( COMPACT_PROTOCOL_ID = 0x082 COMPACT_VERSION = 1 COMPACT_VERSION_MASK = 0x1f COMPACT_TYPE_MASK = 0x0E0 COMPACT_TYPE_BITS = 0x07 COMPACT_TYPE_SHIFT_AMOUNT = 5 ) type tCompactType byte const ( COMPACT_BOOLEAN_TRUE = 0x01 COMPACT_BOOLEAN_FALSE = 0x02 COMPACT_BYTE = 0x03 COMPACT_I16 = 0x04 COMPACT_I32 = 0x05 COMPACT_I64 = 0x06 COMPACT_DOUBLE = 0x07 COMPACT_BINARY = 0x08 COMPACT_LIST = 0x09 COMPACT_SET = 0x0A COMPACT_MAP = 0x0B COMPACT_STRUCT = 0x0C COMPACT_UUID = 0x0D ) var ( ttypeToCompactType map[TType]tCompactType ) func init() { ttypeToCompactType = map[TType]tCompactType{ STOP: STOP, BOOL: COMPACT_BOOLEAN_TRUE, BYTE: COMPACT_BYTE, I16: COMPACT_I16, I32: COMPACT_I32, I64: COMPACT_I64, DOUBLE: COMPACT_DOUBLE, STRING: COMPACT_BINARY, LIST: COMPACT_LIST, SET: COMPACT_SET, MAP: COMPACT_MAP, STRUCT: COMPACT_STRUCT, UUID: COMPACT_UUID, } } type TCompactProtocolFactory struct { cfg *TConfiguration } // Deprecated: Use NewTCompactProtocolFactoryConf instead. func NewTCompactProtocolFactory() *TCompactProtocolFactory { return NewTCompactProtocolFactoryConf(&TConfiguration{ noPropagation: true, }) } func NewTCompactProtocolFactoryConf(conf *TConfiguration) *TCompactProtocolFactory { return &TCompactProtocolFactory{ cfg: conf, } } func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { return NewTCompactProtocolConf(trans, p.cfg) } func (p *TCompactProtocolFactory) SetTConfiguration(conf *TConfiguration) { p.cfg = conf } type TCompactProtocol struct { trans TRichTransport origTransport TTransport cfg *TConfiguration // Used to keep track of the last field for the current and previous structs, // so we can do the delta stuff. lastField []int lastFieldId int // If we encounter a boolean field begin, save the TField here so it can // have the value incorporated. booleanFieldName string booleanFieldId int16 booleanFieldPending bool // If we read a field header, and it's a boolean field, save the boolean // value here so that readBool can use it. boolValue bool boolValueIsNotNull bool buffer [64]byte } // Deprecated: Use NewTCompactProtocolConf instead. func NewTCompactProtocol(trans TTransport) *TCompactProtocol { return NewTCompactProtocolConf(trans, &TConfiguration{ noPropagation: true, }) } func NewTCompactProtocolConf(trans TTransport, conf *TConfiguration) *TCompactProtocol { PropagateTConfiguration(trans, conf) p := &TCompactProtocol{ origTransport: trans, cfg: conf, } if et, ok := trans.(TRichTransport); ok { p.trans = et } else { p.trans = NewTRichTransport(trans) } return p } // // Public Writing methods. // // Write a message header to the wire. Compact Protocol messages contain the // protocol version so we can migrate forwards in the future if need be. func (p *TCompactProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqid int32) error { err := p.writeByteDirect(COMPACT_PROTOCOL_ID) if err != nil { return NewTProtocolException(err) } err = p.writeByteDirect((COMPACT_VERSION & COMPACT_VERSION_MASK) | ((byte(typeId) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) if err != nil { return NewTProtocolException(err) } _, err = p.writeVarint32(seqid) if err != nil { return NewTProtocolException(err) } e := p.WriteString(ctx, name) return e } func (p *TCompactProtocol) WriteMessageEnd(ctx context.Context) error { return nil } // Write a struct begin. This doesn't actually put anything on the wire. We // use it as an opportunity to put special placeholder markers on the field // stack so we can get the field id deltas correct. func (p *TCompactProtocol) WriteStructBegin(ctx context.Context, name string) error { p.lastField = append(p.lastField, p.lastFieldId) p.lastFieldId = 0 return nil } // Write a struct end. This doesn't actually put anything on the wire. We use // this as an opportunity to pop the last field from the current struct off // of the field stack. func (p *TCompactProtocol) WriteStructEnd(ctx context.Context) error { if len(p.lastField) <= 0 { return NewTProtocolExceptionWithType(INVALID_DATA, errors.New("WriteStructEnd called without matching WriteStructBegin call before")) } p.lastFieldId = p.lastField[len(p.lastField)-1] p.lastField = p.lastField[:len(p.lastField)-1] return nil } func (p *TCompactProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { if typeId == BOOL { // we want to possibly include the value, so we'll wait. p.booleanFieldName, p.booleanFieldId, p.booleanFieldPending = name, id, true return nil } _, err := p.writeFieldBeginInternal(ctx, name, typeId, id, 0xFF) return NewTProtocolException(err) } // The workhorse of writeFieldBegin. It has the option of doing a // 'type override' of the type header. This is used specifically in the // boolean field case. func (p *TCompactProtocol) writeFieldBeginInternal(ctx context.Context, name string, typeId TType, id int16, typeOverride byte) (int, error) { // short lastField = lastField_.pop(); // if there's a type override, use that. var typeToWrite byte if typeOverride == 0xFF { typeToWrite = byte(p.getCompactType(typeId)) } else { typeToWrite = typeOverride } // check if we can use delta encoding for the field id fieldId := int(id) written := 0 if fieldId > p.lastFieldId && fieldId-p.lastFieldId <= 15 { // write them together err := p.writeByteDirect(byte((fieldId-p.lastFieldId)<<4) | typeToWrite) if err != nil { return 0, err } } else { // write them separate err := p.writeByteDirect(typeToWrite) if err != nil { return 0, err } err = p.WriteI16(ctx, id) written = 1 + 2 if err != nil { return 0, err } } p.lastFieldId = fieldId return written, nil } func (p *TCompactProtocol) WriteFieldEnd(ctx context.Context) error { return nil } func (p *TCompactProtocol) WriteFieldStop(ctx context.Context) error { err := p.writeByteDirect(STOP) return NewTProtocolException(err) } func (p *TCompactProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { if size == 0 { err := p.writeByteDirect(0) return NewTProtocolException(err) } _, err := p.writeVarint32(int32(size)) if err != nil { return NewTProtocolException(err) } err = p.writeByteDirect(byte(p.getCompactType(keyType))<<4 | byte(p.getCompactType(valueType))) return NewTProtocolException(err) } func (p *TCompactProtocol) WriteMapEnd(ctx context.Context) error { return nil } // Write a list header. func (p *TCompactProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { _, err := p.writeCollectionBegin(elemType, size) return NewTProtocolException(err) } func (p *TCompactProtocol) WriteListEnd(ctx context.Context) error { return nil } // Write a set header. func (p *TCompactProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { _, err := p.writeCollectionBegin(elemType, size) return NewTProtocolException(err) } func (p *TCompactProtocol) WriteSetEnd(ctx context.Context) error { return nil } func (p *TCompactProtocol) WriteBool(ctx context.Context, value bool) error { v := byte(COMPACT_BOOLEAN_FALSE) if value { v = byte(COMPACT_BOOLEAN_TRUE) } if p.booleanFieldPending { // we haven't written the field header yet _, err := p.writeFieldBeginInternal(ctx, p.booleanFieldName, BOOL, p.booleanFieldId, v) p.booleanFieldPending = false return NewTProtocolException(err) } // we're not part of a field, so just write the value. err := p.writeByteDirect(v) return NewTProtocolException(err) } // Write a byte. Nothing to see here! func (p *TCompactProtocol) WriteByte(ctx context.Context, value int8) error { err := p.writeByteDirect(byte(value)) return NewTProtocolException(err) } // Write an I16 as a zigzag varint. func (p *TCompactProtocol) WriteI16(ctx context.Context, value int16) error { _, err := p.writeVarint32(p.int32ToZigzag(int32(value))) return NewTProtocolException(err) } // Write an i32 as a zigzag varint. func (p *TCompactProtocol) WriteI32(ctx context.Context, value int32) error { _, err := p.writeVarint32(p.int32ToZigzag(value)) return NewTProtocolException(err) } // Write an i64 as a zigzag varint. func (p *TCompactProtocol) WriteI64(ctx context.Context, value int64) error { _, err := p.writeVarint64(p.int64ToZigzag(value)) return NewTProtocolException(err) } // Write a double to the wire as 8 bytes. func (p *TCompactProtocol) WriteDouble(ctx context.Context, value float64) error { buf := p.buffer[0:8] binary.LittleEndian.PutUint64(buf, math.Float64bits(value)) _, err := p.trans.Write(buf) return NewTProtocolException(err) } // Write a string to the wire with a varint size preceding. func (p *TCompactProtocol) WriteString(ctx context.Context, value string) error { _, e := p.writeVarint32(int32(len(value))) if e != nil { return NewTProtocolException(e) } if len(value) == 0 { return nil } _, e = p.trans.WriteString(value) return e } // Write a byte array, using a varint for the size. func (p *TCompactProtocol) WriteBinary(ctx context.Context, bin []byte) error { _, e := p.writeVarint32(int32(len(bin))) if e != nil { return NewTProtocolException(e) } if len(bin) > 0 { _, e = p.trans.Write(bin) return NewTProtocolException(e) } return nil } // Write a Tuuid to the wire as 16 bytes. func (p *TCompactProtocol) WriteUUID(ctx context.Context, value Tuuid) error { _, err := p.trans.Write(value[:]) return NewTProtocolException(err) } // // Reading methods. // // Read a message header. func (p *TCompactProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { var protocolId byte _, deadlineSet := ctx.Deadline() for { protocolId, err = p.readByteDirect() if deadlineSet && isTimeoutError(err) && ctx.Err() == nil { // keep retrying I/O timeout errors since we still have // time left continue } // For anything else, don't retry break } if err != nil { return } if protocolId != COMPACT_PROTOCOL_ID { e := fmt.Errorf("Expected protocol id %02x but got %02x", COMPACT_PROTOCOL_ID, protocolId) return "", typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, e) } versionAndType, err := p.readByteDirect() if err != nil { return } version := versionAndType & COMPACT_VERSION_MASK typeId = TMessageType((versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS) if version != COMPACT_VERSION { e := fmt.Errorf("Expected version %02x but got %02x", COMPACT_VERSION, version) err = NewTProtocolExceptionWithType(BAD_VERSION, e) return } seqId, e := p.readVarint32() if e != nil { err = NewTProtocolException(e) return } name, err = p.ReadString(ctx) return } func (p *TCompactProtocol) ReadMessageEnd(ctx context.Context) error { return nil } // Read a struct begin. There's nothing on the wire for this, but it is our // opportunity to push a new struct begin marker onto the field stack. func (p *TCompactProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { p.lastField = append(p.lastField, p.lastFieldId) p.lastFieldId = 0 return } // Doesn't actually consume any wire data, just removes the last field for // this struct from the field stack. func (p *TCompactProtocol) ReadStructEnd(ctx context.Context) error { // consume the last field we read off the wire. if len(p.lastField) <= 0 { return NewTProtocolExceptionWithType(INVALID_DATA, errors.New("ReadStructEnd called without matching ReadStructBegin call before")) } p.lastFieldId = p.lastField[len(p.lastField)-1] p.lastField = p.lastField[:len(p.lastField)-1] return nil } // Read a field header off the wire. func (p *TCompactProtocol) ReadFieldBegin(ctx context.Context) (name string, typeId TType, id int16, err error) { t, err := p.readByteDirect() if err != nil { return } // if it's a stop, then we can return immediately, as the struct is over. if (t & 0x0f) == STOP { return "", STOP, 0, nil } // mask off the 4 MSB of the type header. it could contain a field id delta. modifier := int16((t & 0xf0) >> 4) if modifier == 0 { // not a delta. look ahead for the zigzag varint field id. id, err = p.ReadI16(ctx) if err != nil { return } } else { // has a delta. add the delta to the last read field id. id = int16(p.lastFieldId) + modifier } typeId, e := p.getTType(tCompactType(t & 0x0f)) if e != nil { err = NewTProtocolException(e) return } // if this happens to be a boolean field, the value is encoded in the type if p.isBoolType(t) { // save the boolean value in a special instance variable. p.boolValue = (byte(t)&0x0f == COMPACT_BOOLEAN_TRUE) p.boolValueIsNotNull = true } // push the new field onto the field stack so we can keep the deltas going. p.lastFieldId = int(id) return } func (p *TCompactProtocol) ReadFieldEnd(ctx context.Context) error { return nil } // Read a map header off the wire. If the size is zero, skip reading the key // and value type. This means that 0-length maps will yield TMaps without the // "correct" types. func (p *TCompactProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, err error) { size32, e := p.readVarint32() if e != nil { err = NewTProtocolException(e) return } err = checkSizeForProtocol(size32, p.cfg) if err != nil { return } size = int(size32) keyAndValueType := byte(STOP) if size != 0 { keyAndValueType, err = p.readByteDirect() if err != nil { return } } keyType, _ = p.getTType(tCompactType(keyAndValueType >> 4)) valueType, _ = p.getTType(tCompactType(keyAndValueType & 0xf)) return } func (p *TCompactProtocol) ReadMapEnd(ctx context.Context) error { return nil } // Read a list header off the wire. If the list size is 0-14, the size will // be packed into the element type header. If it's a longer list, the 4 MSB // of the element type header will be 0xF, and a varint will follow with the // true size. func (p *TCompactProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, err error) { size_and_type, err := p.readByteDirect() if err != nil { return } size = int((size_and_type >> 4) & 0x0f) if size == 15 { size2, e := p.readVarint32() if e != nil { err = NewTProtocolException(e) return } size = int(size2) } err = checkSizeForProtocol(int32(size), p.cfg) if err != nil { return } elemType, e := p.getTType(tCompactType(size_and_type)) if e != nil { err = NewTProtocolException(e) return } return } func (p *TCompactProtocol) ReadListEnd(ctx context.Context) error { return nil } // Read a set header off the wire. If the set size is 0-14, the size will // be packed into the element type header. If it's a longer set, the 4 MSB // of the element type header will be 0xF, and a varint will follow with the // true size. func (p *TCompactProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, err error) { return p.ReadListBegin(ctx) } func (p *TCompactProtocol) ReadSetEnd(ctx context.Context) error { return nil } // Read a boolean off the wire. If this is a boolean field, the value should // already have been read during readFieldBegin, so we'll just consume the // pre-stored value. Otherwise, read a byte. func (p *TCompactProtocol) ReadBool(ctx context.Context) (value bool, err error) { if p.boolValueIsNotNull { p.boolValueIsNotNull = false return p.boolValue, nil } v, err := p.readByteDirect() return v == COMPACT_BOOLEAN_TRUE, err } // Read a single byte off the wire. Nothing interesting here. func (p *TCompactProtocol) ReadByte(ctx context.Context) (int8, error) { v, err := p.readByteDirect() if err != nil { return 0, NewTProtocolException(err) } return int8(v), err } // Read an i16 from the wire as a zigzag varint. func (p *TCompactProtocol) ReadI16(ctx context.Context) (value int16, err error) { v, err := p.ReadI32(ctx) return int16(v), err } // Read an i32 from the wire as a zigzag varint. func (p *TCompactProtocol) ReadI32(ctx context.Context) (value int32, err error) { v, e := p.readVarint32() if e != nil { return 0, NewTProtocolException(e) } value = p.zigzagToInt32(v) return value, nil } // Read an i64 from the wire as a zigzag varint. func (p *TCompactProtocol) ReadI64(ctx context.Context) (value int64, err error) { v, e := p.readVarint64() if e != nil { return 0, NewTProtocolException(e) } value = p.zigzagToInt64(v) return value, nil } // No magic here - just read a double off the wire. func (p *TCompactProtocol) ReadDouble(ctx context.Context) (value float64, err error) { longBits := p.buffer[0:8] _, e := io.ReadFull(p.trans, longBits) if e != nil { return 0.0, NewTProtocolException(e) } return math.Float64frombits(p.bytesToUint64(longBits)), nil } // Reads a []byte (via readBinary), and then UTF-8 decodes it. func (p *TCompactProtocol) ReadString(ctx context.Context) (value string, err error) { length, e := p.readVarint32() if e != nil { return "", NewTProtocolException(e) } err = checkSizeForProtocol(length, p.cfg) if err != nil { return } if length == 0 { return "", nil } if length < int32(len(p.buffer)) { // Avoid allocation on small reads buf := p.buffer[:length] read, e := io.ReadFull(p.trans, buf) return string(buf[:read]), NewTProtocolException(e) } buf, e := safeReadBytes(length, p.trans) return string(buf), NewTProtocolException(e) } // Read a []byte from the wire. func (p *TCompactProtocol) ReadBinary(ctx context.Context) (value []byte, err error) { length, e := p.readVarint32() if e != nil { return nil, NewTProtocolException(e) } err = checkSizeForProtocol(length, p.cfg) if err != nil { return } if length == 0 { return []byte{}, nil } buf, e := safeReadBytes(length, p.trans) return buf, NewTProtocolException(e) } // Read fixed 16 bytes as UUID. func (p *TCompactProtocol) ReadUUID(ctx context.Context) (value Tuuid, err error) { buf := p.buffer[0:16] _, e := io.ReadFull(p.trans, buf) if e == nil { copy(value[:], buf) } return value, NewTProtocolException(e) } func (p *TCompactProtocol) Flush(ctx context.Context) (err error) { return NewTProtocolException(p.trans.Flush(ctx)) } func (p *TCompactProtocol) Skip(ctx context.Context, fieldType TType) (err error) { return SkipDefaultDepth(ctx, p, fieldType) } func (p *TCompactProtocol) Transport() TTransport { return p.origTransport } // // Internal writing methods // // Abstract method for writing the start of lists and sets. List and sets on // the wire differ only by the type indicator. func (p *TCompactProtocol) writeCollectionBegin(elemType TType, size int) (int, error) { if size <= 14 { return 1, p.writeByteDirect(byte(int32(size<<4) | int32(p.getCompactType(elemType)))) } err := p.writeByteDirect(0xf0 | byte(p.getCompactType(elemType))) if err != nil { return 0, err } m, err := p.writeVarint32(int32(size)) return 1 + m, err } // Write an i32 as a varint. Results in 1-5 bytes on the wire. // TODO(pomack): make a permanent buffer like writeVarint64? func (p *TCompactProtocol) writeVarint32(n int32) (int, error) { i32buf := p.buffer[0:5] idx := 0 for { if (n & ^0x7F) == 0 { i32buf[idx] = byte(n) idx++ // p.writeByteDirect(byte(n)); break // return; } else { i32buf[idx] = byte((n & 0x7F) | 0x80) idx++ // p.writeByteDirect(byte(((n & 0x7F) | 0x80))); u := uint32(n) n = int32(u >> 7) } } return p.trans.Write(i32buf[0:idx]) } // Write an i64 as a varint. Results in 1-10 bytes on the wire. func (p *TCompactProtocol) writeVarint64(n int64) (int, error) { varint64out := p.buffer[0:10] idx := 0 for { if (n & ^0x7F) == 0 { varint64out[idx] = byte(n) idx++ break } else { varint64out[idx] = byte((n & 0x7F) | 0x80) idx++ u := uint64(n) n = int64(u >> 7) } } return p.trans.Write(varint64out[0:idx]) } // Convert l into a zigzag long. This allows negative numbers to be // represented compactly as a varint. func (p *TCompactProtocol) int64ToZigzag(l int64) int64 { return (l << 1) ^ (l >> 63) } // Convert l into a zigzag long. This allows negative numbers to be // represented compactly as a varint. func (p *TCompactProtocol) int32ToZigzag(n int32) int32 { return (n << 1) ^ (n >> 31) } // Writes a byte without any possibility of all that field header nonsense. // Used internally by other writing methods that know they need to write a byte. func (p *TCompactProtocol) writeByteDirect(b byte) error { return p.trans.WriteByte(b) } // // Internal reading methods // // Read an i32 from the wire as a varint. The MSB of each byte is set // if there is another byte to follow. This can read up to 5 bytes. func (p *TCompactProtocol) readVarint32() (int32, error) { // if the wire contains the right stuff, this will just truncate the i64 we // read and get us the right sign. v, err := p.readVarint64() return int32(v), err } // Read an i64 from the wire as a proper varint. The MSB of each byte is set // if there is another byte to follow. This can read up to 10 bytes. func (p *TCompactProtocol) readVarint64() (int64, error) { shift := uint(0) result := int64(0) for { b, err := p.readByteDirect() if err != nil { return 0, err } result |= int64(b&0x7f) << shift if (b & 0x80) != 0x80 { break } shift += 7 } return result, nil } // Read a byte, unlike ReadByte that reads Thrift-byte that is i8. func (p *TCompactProtocol) readByteDirect() (byte, error) { return p.trans.ReadByte() } // // encoding helpers // // Convert from zigzag int to int. func (p *TCompactProtocol) zigzagToInt32(n int32) int32 { u := uint32(n) return int32(u>>1) ^ -(n & 1) } // Convert from zigzag long to long. func (p *TCompactProtocol) zigzagToInt64(n int64) int64 { u := uint64(n) return int64(u>>1) ^ -(n & 1) } // Note that it's important that the mask bytes are long literals, // otherwise they'll default to ints, and when you shift an int left 56 bits, // you just get a messed up int. func (p *TCompactProtocol) bytesToUint64(b []byte) uint64 { return binary.LittleEndian.Uint64(b) } // // type testing and converting // func (p *TCompactProtocol) isBoolType(b byte) bool { return (b&0x0f) == COMPACT_BOOLEAN_TRUE || (b&0x0f) == COMPACT_BOOLEAN_FALSE } // Given a tCompactType constant, convert it to its corresponding // TType value. func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { switch byte(t) & 0x0f { case STOP: return STOP, nil case COMPACT_BOOLEAN_FALSE, COMPACT_BOOLEAN_TRUE: return BOOL, nil case COMPACT_BYTE: return BYTE, nil case COMPACT_I16: return I16, nil case COMPACT_I32: return I32, nil case COMPACT_I64: return I64, nil case COMPACT_DOUBLE: return DOUBLE, nil case COMPACT_BINARY: return STRING, nil case COMPACT_LIST: return LIST, nil case COMPACT_SET: return SET, nil case COMPACT_MAP: return MAP, nil case COMPACT_STRUCT: return STRUCT, nil case COMPACT_UUID: return UUID, nil } return STOP, NewTProtocolException(fmt.Errorf("don't know what type: %v", t&0x0f)) } // Given a TType value, find the appropriate TCompactProtocol.Types constant. func (p *TCompactProtocol) getCompactType(t TType) tCompactType { return ttypeToCompactType[t] } func (p *TCompactProtocol) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(p.trans, conf) PropagateTConfiguration(p.origTransport, conf) p.cfg = conf } var ( _ TConfigurationSetter = (*TCompactProtocolFactory)(nil) _ TConfigurationSetter = (*TCompactProtocol)(nil) ) thrift-0.19.0/lib/go/thrift/exception_test.go0000644000000000000000000000416014303740367021146 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "testing" ) func TestPrependError(t *testing.T) { err := NewTApplicationException(INTERNAL_ERROR, "original error") err2, ok := PrependError("Prepend: ", err).(TApplicationException) if !ok { t.Fatal("Couldn't cast error TApplicationException") } if err2.Error() != "Prepend: original error" { t.Fatal("Unexpected error string") } if err2.TypeId() != INTERNAL_ERROR { t.Fatal("Unexpected type error") } err3 := NewTProtocolExceptionWithType(INVALID_DATA, errors.New("original error")) err4, ok := PrependError("Prepend: ", err3).(TProtocolException) if !ok { t.Fatal("Couldn't cast error TProtocolException") } if err4.Error() != "Prepend: original error" { t.Fatal("Unexpected error string") } if err4.TypeId() != INVALID_DATA { t.Fatal("Unexpected type error") } err5 := NewTTransportException(TIMED_OUT, "original error") err6, ok := PrependError("Prepend: ", err5).(TTransportException) if !ok { t.Fatal("Couldn't cast error TTransportException") } if err6.Error() != "Prepend: original error" { t.Fatal("Unexpected error string") } if err6.TypeId() != TIMED_OUT { t.Fatal("Unexpected type error") } err7 := errors.New("original error") err8 := PrependError("Prepend: ", err7) if err8.Error() != "Prepend: original error" { t.Fatal("Unexpected error string") } } thrift-0.19.0/lib/go/thrift/binary_protocol_test.go0000644000000000000000000001222714303740367022360 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "math" "strings" "testing" ) func TestReadWriteBinaryProtocol(t *testing.T) { ReadWriteProtocolTest(t, NewTBinaryProtocolFactoryDefault()) } const ( safeReadBytesSource = ` Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet tincidunt nibh. Phasellus vel convallis libero, sit amet posuere quam. Nullam blandit velit at nibh fringilla, sed egestas erat dapibus. Sed hendrerit tincidunt accumsan. Curabitur consectetur bibendum dui nec hendrerit. Fusce quis turpis nec magna efficitur volutpat a ut nibh. Vestibulum odio risus, tristique a nisi et, congue mattis mi. Vivamus a nunc justo. Mauris molestie sagittis magna, hendrerit auctor lectus egestas non. Phasellus pretium, odio sit amet bibendum feugiat, velit nunc luctus erat, ac bibendum mi dui molestie nulla. Nullam fermentum magna eu elit vehicula tincidunt. Etiam ornare laoreet dignissim. Ut sed nunc ac neque vulputate fermentum. Morbi volutpat dapibus magna, at porttitor quam facilisis a. Donec eget fermentum risus. Aliquam erat volutpat. Phasellus molestie id ante vel iaculis. Fusce eget quam nec quam viverra laoreet vitae a dui. Mauris blandit blandit dui, iaculis interdum diam mollis at. Morbi vel sem et. ` safeReadBytesSourceLen = len(safeReadBytesSource) ) func TestSafeReadBytes(t *testing.T) { srcData := []byte(safeReadBytesSource) for _, c := range []struct { label string askedSize int32 dataSize int }{ { label: "normal", askedSize: 100, dataSize: 100, }, { label: "max-askedSize", askedSize: math.MaxInt32, dataSize: safeReadBytesSourceLen, }, } { t.Run(c.label, func(t *testing.T) { data := bytes.NewReader(srcData[:c.dataSize]) buf, err := safeReadBytes(c.askedSize, data) if len(buf) != c.dataSize { t.Errorf( "Expected to read %d bytes, got %d", c.dataSize, len(buf), ) } if !strings.HasPrefix(safeReadBytesSource, string(buf)) { t.Errorf("Unexpected read data: %q", buf) } if int32(c.dataSize) < c.askedSize { // We expect error in this case if err == nil { t.Errorf( "Expected error when dataSize %d < askedSize %d, got nil", c.dataSize, c.askedSize, ) } } else { // We expect no error in this case if err != nil { t.Errorf( "Expected no error when dataSize %d >= askedSize %d, got: %v", c.dataSize, c.askedSize, err, ) } } }) } } func generateSafeReadBytesBenchmark(askedSize int32, dataSize int) func(b *testing.B) { return func(b *testing.B) { data := make([]byte, dataSize) b.ResetTimer() for i := 0; i < b.N; i++ { safeReadBytes(askedSize, bytes.NewReader(data)) } } } func TestSafeReadBytesAlloc(t *testing.T) { if testing.Short() { // NOTE: Since this test runs a benchmark test, it takes at // least 1 second. // // In general we try to avoid unit tests taking that long to run, // but it's to verify a security issue so we made an exception // here: // https://issues.apache.org/jira/browse/THRIFT-5322 t.Skip("skipping test in short mode.") } const ( askedSize = int32(math.MaxInt32) dataSize = 4096 ) // The purpose of this test is that in the case a string header says // that it has a string askedSize bytes long, the implementation should // not just allocate askedSize bytes upfront. So when there're actually // not enough data to be read (dataSize), the actual allocated bytes // should be somewhere between dataSize and askedSize. // // Different approachs could have different memory overheads, so this // target is arbitrary in nature. But when dataSize is small enough // compare to askedSize, half the askedSize is a good and safe target. const target = int64(askedSize) / 2 bm := testing.Benchmark(generateSafeReadBytesBenchmark(askedSize, dataSize)) actual := bm.AllocedBytesPerOp() if actual > target { t.Errorf( "Expected allocated bytes per op to be <= %d, got %d", target, actual, ) } else { t.Logf("Allocated bytes: %d B/op", actual) } } func BenchmarkSafeReadBytes(b *testing.B) { for _, c := range []struct { label string askedSize int32 dataSize int }{ { label: "normal", askedSize: 100, dataSize: 100, }, { label: "max-askedSize", askedSize: math.MaxInt32, dataSize: 4096, }, } { b.Run(c.label, generateSafeReadBytesBenchmark(c.askedSize, c.dataSize)) } } thrift-0.19.0/lib/go/thrift/server_test.go0000644000000000000000000000156014303740367020457 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "testing" ) func TestNothing(t *testing.T) { } thrift-0.19.0/lib/go/thrift/lowlevel_benchmarks_test.go0000644000000000000000000002675514303740367023214 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "testing" ) var binaryProtoF = NewTBinaryProtocolFactoryDefault() var compactProtoF = NewTCompactProtocolFactory() var buf = bytes.NewBuffer(make([]byte, 0, 1024)) var tfv = []TTransportFactory{ NewTMemoryBufferTransportFactory(1024), NewStreamTransportFactory(buf, buf, true), NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)), } func BenchmarkBinaryBool_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBool(b, p, trans) } } func BenchmarkBinaryByte_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteByte(b, p, trans) } } func BenchmarkBinaryI16_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI16(b, p, trans) } } func BenchmarkBinaryI32_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI32(b, p, trans) } } func BenchmarkBinaryI64_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI64(b, p, trans) } } func BenchmarkBinaryDouble_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteDouble(b, p, trans) } } func BenchmarkBinaryString_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteString(b, p, trans) } } func BenchmarkBinaryBinary_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBinary(b, p, trans) } } func BenchmarkBinaryBool_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBool(b, p, trans) } } func BenchmarkBinaryByte_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteByte(b, p, trans) } } func BenchmarkBinaryI16_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI16(b, p, trans) } } func BenchmarkBinaryI32_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI32(b, p, trans) } } func BenchmarkBinaryI64_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI64(b, p, trans) } } func BenchmarkBinaryDouble_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteDouble(b, p, trans) } } func BenchmarkBinaryString_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteString(b, p, trans) } } func BenchmarkBinaryBinary_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBinary(b, p, trans) } } func BenchmarkBinaryBool_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBool(b, p, trans) } } func BenchmarkBinaryByte_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteByte(b, p, trans) } } func BenchmarkBinaryI16_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI16(b, p, trans) } } func BenchmarkBinaryI32_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI32(b, p, trans) } } func BenchmarkBinaryI64_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI64(b, p, trans) } } func BenchmarkBinaryDouble_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteDouble(b, p, trans) } } func BenchmarkBinaryString_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteString(b, p, trans) } } func BenchmarkBinaryBinary_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := binaryProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBinary(b, p, trans) } } func BenchmarkCompactBool_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBool(b, p, trans) } } func BenchmarkCompactByte_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteByte(b, p, trans) } } func BenchmarkCompactI16_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI16(b, p, trans) } } func BenchmarkCompactI32_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI32(b, p, trans) } } func BenchmarkCompactI64_0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI64(b, p, trans) } } func BenchmarkCompactDouble0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteDouble(b, p, trans) } } func BenchmarkCompactString0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteString(b, p, trans) } } func BenchmarkCompactBinary0(b *testing.B) { trans, err := tfv[0].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBinary(b, p, trans) } } func BenchmarkCompactBool_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBool(b, p, trans) } } func BenchmarkCompactByte_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteByte(b, p, trans) } } func BenchmarkCompactI16_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI16(b, p, trans) } } func BenchmarkCompactI32_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI32(b, p, trans) } } func BenchmarkCompactI64_1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI64(b, p, trans) } } func BenchmarkCompactDouble1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteDouble(b, p, trans) } } func BenchmarkCompactString1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteString(b, p, trans) } } func BenchmarkCompactBinary1(b *testing.B) { trans, err := tfv[1].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBinary(b, p, trans) } } func BenchmarkCompactBool_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBool(b, p, trans) } } func BenchmarkCompactByte_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteByte(b, p, trans) } } func BenchmarkCompactI16_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI16(b, p, trans) } } func BenchmarkCompactI32_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI32(b, p, trans) } } func BenchmarkCompactI64_2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteI64(b, p, trans) } } func BenchmarkCompactDouble2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteDouble(b, p, trans) } } func BenchmarkCompactString2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteString(b, p, trans) } } func BenchmarkCompactBinary2(b *testing.B) { trans, err := tfv[2].GetTransport(nil) if err != nil { b.Fatal(err) } p := compactProtoF.GetProtocol(trans) for i := 0; i < b.N; i++ { ReadWriteBinary(b, p, trans) } } thrift-0.19.0/lib/go/thrift/middleware_test.go0000644000000000000000000000741514303740367021273 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "testing" ) type counter struct { count int } func (c *counter) incr() { c.count++ } func newCounter(t *testing.T) *counter { c := counter{} if c.count != 0 { t.Fatal("Unexpected initial count.") } return &c } func testProcessorMiddleware(c *counter) ProcessorMiddleware { return func(name string, next TProcessorFunction) TProcessorFunction { return WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { c.incr() return next.Process(ctx, seqId, in, out) }, } } } func testClientMiddleware(c *counter) ClientMiddleware { return func(next TClient) TClient { return WrappedTClient{ Wrapped: func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { c.incr() return next.Call(ctx, method, args, result) }, } } } func TestWrapProcessor(t *testing.T) { name := "test" processor := &mockWrappableProcessor{ ProcessorFuncs: map[string]TProcessorFunction{ name: WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { return true, nil }, }, }, } c := newCounter(t) ctx := setMockWrappableProcessorName(context.Background(), name) wrapped := WrapProcessor(processor, testProcessorMiddleware(c)) wrapped.Process(ctx, nil, nil) if c.count != 1 { t.Fatalf("Unexpected count value %v", c.count) } } func TestWrapTMultiplexedProcessor(t *testing.T) { name := "test" processorName := "foo" c := newCounter(t) processor := &TMultiplexedProcessor{} processor.RegisterDefault(&mockWrappableProcessor{ ProcessorFuncs: map[string]TProcessorFunction{ name: WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { return true, nil }, }, }, }) processor.RegisterProcessor(processorName, &mockWrappableProcessor{ ProcessorFuncs: map[string]TProcessorFunction{ name: WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { return true, nil }, }, }, }) wrapped := WrapProcessor(processor, testProcessorMiddleware(c)) ctx := setMockWrappableProcessorName(context.Background(), name) in := NewStoredMessageProtocol(nil, name, 1, 1) wrapped.Process(ctx, in, nil) if c.count != 1 { t.Fatalf("Unexpected count value %v", c.count) } in = NewStoredMessageProtocol(nil, processorName+MULTIPLEXED_SEPARATOR+name, 1, 1) wrapped.Process(ctx, in, nil) if c.count != 2 { t.Fatalf("Unexpected count value %v", c.count) } } func TestWrapClient(t *testing.T) { client := WrappedTClient{ Wrapped: func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { return ResponseMeta{}, nil }, } c := newCounter(t) wrapped := WrapClient(client, testClientMiddleware(c)) wrapped.Call(context.Background(), "test", nil, nil) if c.count != 1 { t.Fatalf("Unexpected count value %v", c.count) } } thrift-0.19.0/lib/go/thrift/header_context.go0000644000000000000000000000565614303740367021120 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" ) // See https://godoc.org/context#WithValue on why do we need the unexported typedefs. type ( headerKey string headerKeyList int ) // Values for headerKeyList. const ( headerKeyListRead headerKeyList = iota headerKeyListWrite ) // SetHeader sets a header in the context. func SetHeader(ctx context.Context, key, value string) context.Context { return context.WithValue( ctx, headerKey(key), value, ) } // UnsetHeader unsets a previously set header in the context. func UnsetHeader(ctx context.Context, key string) context.Context { return context.WithValue( ctx, headerKey(key), nil, ) } // GetHeader returns a value of the given header from the context. func GetHeader(ctx context.Context, key string) (value string, ok bool) { if v := ctx.Value(headerKey(key)); v != nil { value, ok = v.(string) } return } // SetReadHeaderList sets the key list of read THeaders in the context. func SetReadHeaderList(ctx context.Context, keys []string) context.Context { return context.WithValue( ctx, headerKeyListRead, keys, ) } // GetReadHeaderList returns the key list of read THeaders from the context. func GetReadHeaderList(ctx context.Context) []string { if v := ctx.Value(headerKeyListRead); v != nil { if value, ok := v.([]string); ok { return value } } return nil } // SetWriteHeaderList sets the key list of THeaders to write in the context. func SetWriteHeaderList(ctx context.Context, keys []string) context.Context { return context.WithValue( ctx, headerKeyListWrite, keys, ) } // GetWriteHeaderList returns the key list of THeaders to write from the context. func GetWriteHeaderList(ctx context.Context) []string { if v := ctx.Value(headerKeyListWrite); v != nil { if value, ok := v.([]string); ok { return value } } return nil } // AddReadTHeaderToContext adds the whole THeader headers into context. func AddReadTHeaderToContext(ctx context.Context, headers THeaderMap) context.Context { keys := make([]string, 0, len(headers)) for key, value := range headers { ctx = SetHeader(ctx, key, value) keys = append(keys, key) } return SetReadHeaderList(ctx, keys) } thrift-0.19.0/lib/go/thrift/simple_json_protocol.go0000644000000000000000000010642314370300523022347 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bufio" "bytes" "context" "encoding/base64" "encoding/json" "errors" "fmt" "io" "math" "strconv" ) type _ParseContext int const ( _CONTEXT_INVALID _ParseContext = iota _CONTEXT_IN_TOPLEVEL // 1 _CONTEXT_IN_LIST_FIRST // 2 _CONTEXT_IN_LIST // 3 _CONTEXT_IN_OBJECT_FIRST // 4 _CONTEXT_IN_OBJECT_NEXT_KEY // 5 _CONTEXT_IN_OBJECT_NEXT_VALUE // 6 ) func (p _ParseContext) String() string { switch p { case _CONTEXT_IN_TOPLEVEL: return "TOPLEVEL" case _CONTEXT_IN_LIST_FIRST: return "LIST-FIRST" case _CONTEXT_IN_LIST: return "LIST" case _CONTEXT_IN_OBJECT_FIRST: return "OBJECT-FIRST" case _CONTEXT_IN_OBJECT_NEXT_KEY: return "OBJECT-NEXT-KEY" case _CONTEXT_IN_OBJECT_NEXT_VALUE: return "OBJECT-NEXT-VALUE" } return "UNKNOWN-PARSE-CONTEXT" } type jsonContextStack []_ParseContext func (s *jsonContextStack) push(v _ParseContext) { *s = append(*s, v) } func (s jsonContextStack) peek() (v _ParseContext, ok bool) { l := len(s) if l <= 0 { return } return s[l-1], true } func (s *jsonContextStack) pop() (v _ParseContext, ok bool) { l := len(*s) if l <= 0 { return } v = (*s)[l-1] *s = (*s)[0 : l-1] return v, true } var errEmptyJSONContextStack = NewTProtocolExceptionWithType(INVALID_DATA, errors.New("Unexpected empty json protocol context stack")) // Simple JSON protocol implementation for thrift. // // This protocol produces/consumes a simple output format // suitable for parsing by scripting languages. It should not be // confused with the full-featured TJSONProtocol. type TSimpleJSONProtocol struct { trans TTransport cfg *TConfiguration parseContextStack jsonContextStack dumpContext jsonContextStack writer *bufio.Writer reader *bufio.Reader } // Deprecated: Use NewTSimpleJSONProtocolConf instead.: func NewTSimpleJSONProtocol(t TTransport) *TSimpleJSONProtocol { return NewTSimpleJSONProtocolConf(t, &TConfiguration{ noPropagation: true, }) } func NewTSimpleJSONProtocolConf(t TTransport, conf *TConfiguration) *TSimpleJSONProtocol { PropagateTConfiguration(t, conf) v := &TSimpleJSONProtocol{ trans: t, cfg: conf, writer: bufio.NewWriter(t), reader: bufio.NewReader(t), } v.resetContextStack() return v } // Factory type TSimpleJSONProtocolFactory struct { cfg *TConfiguration } func (p *TSimpleJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { return NewTSimpleJSONProtocolConf(trans, p.cfg) } // SetTConfiguration implements TConfigurationSetter for propagation. func (p *TSimpleJSONProtocolFactory) SetTConfiguration(conf *TConfiguration) { p.cfg = conf } // Deprecated: Use NewTSimpleJSONProtocolFactoryConf instead. func NewTSimpleJSONProtocolFactory() *TSimpleJSONProtocolFactory { return &TSimpleJSONProtocolFactory{ cfg: &TConfiguration{ noPropagation: true, }, } } func NewTSimpleJSONProtocolFactoryConf(conf *TConfiguration) *TSimpleJSONProtocolFactory { return &TSimpleJSONProtocolFactory{ cfg: conf, } } var ( JSON_COMMA []byte JSON_COLON []byte JSON_LBRACE []byte JSON_RBRACE []byte JSON_LBRACKET []byte JSON_RBRACKET []byte JSON_QUOTE byte JSON_QUOTE_BYTES []byte JSON_NULL []byte JSON_TRUE []byte JSON_FALSE []byte JSON_INFINITY string JSON_NEGATIVE_INFINITY string JSON_NAN string JSON_INFINITY_BYTES []byte JSON_NEGATIVE_INFINITY_BYTES []byte JSON_NAN_BYTES []byte ) func init() { JSON_COMMA = []byte{','} JSON_COLON = []byte{':'} JSON_LBRACE = []byte{'{'} JSON_RBRACE = []byte{'}'} JSON_LBRACKET = []byte{'['} JSON_RBRACKET = []byte{']'} JSON_QUOTE = '"' JSON_QUOTE_BYTES = []byte{'"'} JSON_NULL = []byte{'n', 'u', 'l', 'l'} JSON_TRUE = []byte{'t', 'r', 'u', 'e'} JSON_FALSE = []byte{'f', 'a', 'l', 's', 'e'} JSON_INFINITY = "Infinity" JSON_NEGATIVE_INFINITY = "-Infinity" JSON_NAN = "NaN" JSON_INFINITY_BYTES = []byte{'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} JSON_NEGATIVE_INFINITY_BYTES = []byte{'-', 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y'} JSON_NAN_BYTES = []byte{'N', 'a', 'N'} } func jsonQuote(s string) string { b, _ := json.Marshal(s) s1 := string(b) return s1 } func jsonUnquote(s string) (string, bool) { s1 := new(string) err := json.Unmarshal([]byte(s), s1) return *s1, err == nil } func mismatch(expected, actual string) error { return fmt.Errorf("Expected '%s' but found '%s' while parsing JSON.", expected, actual) } func (p *TSimpleJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error { p.resetContextStack() // THRIFT-3735 if e := p.OutputListBegin(); e != nil { return e } if e := p.WriteString(ctx, name); e != nil { return e } if e := p.WriteByte(ctx, int8(typeId)); e != nil { return e } if e := p.WriteI32(ctx, seqId); e != nil { return e } return nil } func (p *TSimpleJSONProtocol) WriteMessageEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TSimpleJSONProtocol) WriteStructBegin(ctx context.Context, name string) error { if e := p.OutputObjectBegin(); e != nil { return e } return nil } func (p *TSimpleJSONProtocol) WriteStructEnd(ctx context.Context) error { return p.OutputObjectEnd() } func (p *TSimpleJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { if e := p.WriteString(ctx, name); e != nil { return e } return nil } func (p *TSimpleJSONProtocol) WriteFieldEnd(ctx context.Context) error { return nil } func (p *TSimpleJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil } func (p *TSimpleJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { if e := p.OutputListBegin(); e != nil { return e } if e := p.WriteByte(ctx, int8(keyType)); e != nil { return e } if e := p.WriteByte(ctx, int8(valueType)); e != nil { return e } return p.WriteI32(ctx, int32(size)) } func (p *TSimpleJSONProtocol) WriteMapEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TSimpleJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { return p.OutputElemListBegin(elemType, size) } func (p *TSimpleJSONProtocol) WriteListEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TSimpleJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { return p.OutputElemListBegin(elemType, size) } func (p *TSimpleJSONProtocol) WriteSetEnd(ctx context.Context) error { return p.OutputListEnd() } func (p *TSimpleJSONProtocol) WriteBool(ctx context.Context, b bool) error { return p.OutputBool(b) } func (p *TSimpleJSONProtocol) WriteByte(ctx context.Context, b int8) error { return p.WriteI32(ctx, int32(b)) } func (p *TSimpleJSONProtocol) WriteI16(ctx context.Context, v int16) error { return p.WriteI32(ctx, int32(v)) } func (p *TSimpleJSONProtocol) WriteI32(ctx context.Context, v int32) error { return p.OutputI64(int64(v)) } func (p *TSimpleJSONProtocol) WriteI64(ctx context.Context, v int64) error { return p.OutputI64(int64(v)) } func (p *TSimpleJSONProtocol) WriteDouble(ctx context.Context, v float64) error { return p.OutputF64(v) } func (p *TSimpleJSONProtocol) WriteString(ctx context.Context, v string) error { return p.OutputString(v) } func (p *TSimpleJSONProtocol) WriteBinary(ctx context.Context, v []byte) error { // JSON library only takes in a string, // not an arbitrary byte array, to ensure bytes are transmitted // efficiently we must convert this into a valid JSON string // therefore we use base64 encoding to avoid excessive escaping/quoting if e := p.OutputPreValue(); e != nil { return e } if _, e := p.write(JSON_QUOTE_BYTES); e != nil { return NewTProtocolException(e) } writer := base64.NewEncoder(base64.StdEncoding, p.writer) if _, e := writer.Write(v); e != nil { p.writer.Reset(p.trans) // THRIFT-3735 return NewTProtocolException(e) } if e := writer.Close(); e != nil { return NewTProtocolException(e) } if _, e := p.write(JSON_QUOTE_BYTES); e != nil { return NewTProtocolException(e) } return p.OutputPostValue() } func (p *TSimpleJSONProtocol) WriteUUID(ctx context.Context, v Tuuid) error { return p.OutputString(v.String()) } // Reading methods. func (p *TSimpleJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { p.resetContextStack() // THRIFT-3735 if isNull, err := p.ParseListBegin(); isNull || err != nil { return name, typeId, seqId, err } if name, err = p.ReadString(ctx); err != nil { return name, typeId, seqId, err } bTypeId, err := p.ReadByte(ctx) typeId = TMessageType(bTypeId) if err != nil { return name, typeId, seqId, err } if seqId, err = p.ReadI32(ctx); err != nil { return name, typeId, seqId, err } return name, typeId, seqId, nil } func (p *TSimpleJSONProtocol) ReadMessageEnd(ctx context.Context) error { return p.ParseListEnd() } func (p *TSimpleJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { _, err = p.ParseObjectStart() return "", err } func (p *TSimpleJSONProtocol) ReadStructEnd(ctx context.Context) error { return p.ParseObjectEnd() } func (p *TSimpleJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) { if err := p.ParsePreValue(); err != nil { return "", STOP, 0, err } b, _ := p.reader.Peek(1) if len(b) > 0 { switch b[0] { case JSON_RBRACE[0]: return "", STOP, 0, nil case JSON_QUOTE: p.reader.ReadByte() name, err := p.ParseStringBody() // simplejson is not meant to be read back into thrift // - see http://wiki.apache.org/thrift/ThriftUsageJava // - use JSON instead if err != nil { return name, STOP, 0, err } return name, STOP, -1, p.ParsePostValue() } e := fmt.Errorf("Expected \"}\" or '\"', but found: '%s'", string(b)) return "", STOP, 0, NewTProtocolExceptionWithType(INVALID_DATA, e) } return "", STOP, 0, NewTProtocolException(io.EOF) } func (p *TSimpleJSONProtocol) ReadFieldEnd(ctx context.Context) error { return nil } func (p *TSimpleJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) { if isNull, e := p.ParseListBegin(); isNull || e != nil { return VOID, VOID, 0, e } // read keyType bKeyType, e := p.ReadByte(ctx) keyType = TType(bKeyType) if e != nil { return keyType, valueType, size, e } // read valueType bValueType, e := p.ReadByte(ctx) valueType = TType(bValueType) if e != nil { return keyType, valueType, size, e } // read size iSize, err := p.ReadI64(ctx) if err != nil { return keyType, valueType, 0, err } err = checkSizeForProtocol(int32(size), p.cfg) if err != nil { return keyType, valueType, 0, err } size = int(iSize) return keyType, valueType, size, err } func (p *TSimpleJSONProtocol) ReadMapEnd(ctx context.Context) error { return p.ParseListEnd() } func (p *TSimpleJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) { return p.ParseElemListBegin() } func (p *TSimpleJSONProtocol) ReadListEnd(ctx context.Context) error { return p.ParseListEnd() } func (p *TSimpleJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) { return p.ParseElemListBegin() } func (p *TSimpleJSONProtocol) ReadSetEnd(ctx context.Context) error { return p.ParseListEnd() } func (p *TSimpleJSONProtocol) ReadBool(ctx context.Context) (bool, error) { var value bool if err := p.ParsePreValue(); err != nil { return value, err } f, _ := p.reader.Peek(1) if len(f) > 0 { switch f[0] { case JSON_TRUE[0]: b := make([]byte, len(JSON_TRUE)) _, err := p.reader.Read(b) if err != nil { return false, NewTProtocolException(err) } if string(b) == string(JSON_TRUE) { value = true } else { e := fmt.Errorf("Expected \"true\" but found: %s", string(b)) return value, NewTProtocolExceptionWithType(INVALID_DATA, e) } case JSON_FALSE[0]: b := make([]byte, len(JSON_FALSE)) _, err := p.reader.Read(b) if err != nil { return false, NewTProtocolException(err) } if string(b) == string(JSON_FALSE) { value = false } else { e := fmt.Errorf("Expected \"false\" but found: %s", string(b)) return value, NewTProtocolExceptionWithType(INVALID_DATA, e) } case JSON_NULL[0]: b := make([]byte, len(JSON_NULL)) _, err := p.reader.Read(b) if err != nil { return false, NewTProtocolException(err) } if string(b) == string(JSON_NULL) { value = false } else { e := fmt.Errorf("Expected \"null\" but found: %s", string(b)) return value, NewTProtocolExceptionWithType(INVALID_DATA, e) } default: e := fmt.Errorf("Expected \"true\", \"false\", or \"null\" but found: %s", string(f)) return value, NewTProtocolExceptionWithType(INVALID_DATA, e) } } return value, p.ParsePostValue() } func (p *TSimpleJSONProtocol) ReadByte(ctx context.Context) (int8, error) { v, err := p.ReadI64(ctx) return int8(v), err } func (p *TSimpleJSONProtocol) ReadI16(ctx context.Context) (int16, error) { v, err := p.ReadI64(ctx) return int16(v), err } func (p *TSimpleJSONProtocol) ReadI32(ctx context.Context) (int32, error) { v, err := p.ReadI64(ctx) return int32(v), err } func (p *TSimpleJSONProtocol) ReadI64(ctx context.Context) (int64, error) { v, _, err := p.ParseI64() return v, err } func (p *TSimpleJSONProtocol) ReadDouble(ctx context.Context) (float64, error) { v, _, err := p.ParseF64() return v, err } func (p *TSimpleJSONProtocol) ReadString(ctx context.Context) (string, error) { var v string if err := p.ParsePreValue(); err != nil { return v, err } f, _ := p.reader.Peek(1) if len(f) > 0 && f[0] == JSON_QUOTE { p.reader.ReadByte() value, err := p.ParseStringBody() v = value if err != nil { return v, err } } else if len(f) > 0 && f[0] == JSON_NULL[0] { b := make([]byte, len(JSON_NULL)) _, err := p.reader.Read(b) if err != nil { return v, NewTProtocolException(err) } if string(b) != string(JSON_NULL) { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } } else { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } return v, p.ParsePostValue() } func (p *TSimpleJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) { var v []byte if err := p.ParsePreValue(); err != nil { return nil, err } f, _ := p.reader.Peek(1) if len(f) > 0 && f[0] == JSON_QUOTE { p.reader.ReadByte() value, err := p.ParseBase64EncodedBody() v = value if err != nil { return v, err } } else if len(f) > 0 && f[0] == JSON_NULL[0] { b := make([]byte, len(JSON_NULL)) _, err := p.reader.Read(b) if err != nil { return v, NewTProtocolException(err) } if string(b) != string(JSON_NULL) { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } } else { e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) return v, NewTProtocolExceptionWithType(INVALID_DATA, e) } return v, p.ParsePostValue() } func (p *TSimpleJSONProtocol) ReadUUID(ctx context.Context) (v Tuuid, err error) { var s string s, err = p.ReadString(ctx) if err != nil { return v, err } v, err = ParseTuuid(s) return v, NewTProtocolExceptionWithType(INVALID_DATA, err) } func (p *TSimpleJSONProtocol) Flush(ctx context.Context) (err error) { return NewTProtocolException(p.writer.Flush()) } func (p *TSimpleJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) { return SkipDefaultDepth(ctx, p, fieldType) } func (p *TSimpleJSONProtocol) Transport() TTransport { return p.trans } func (p *TSimpleJSONProtocol) OutputPreValue() error { cxt, ok := p.dumpContext.peek() if !ok { return errEmptyJSONContextStack } switch cxt { case _CONTEXT_IN_LIST, _CONTEXT_IN_OBJECT_NEXT_KEY: if _, e := p.write(JSON_COMMA); e != nil { return NewTProtocolException(e) } case _CONTEXT_IN_OBJECT_NEXT_VALUE: if _, e := p.write(JSON_COLON); e != nil { return NewTProtocolException(e) } } return nil } func (p *TSimpleJSONProtocol) OutputPostValue() error { cxt, ok := p.dumpContext.peek() if !ok { return errEmptyJSONContextStack } switch cxt { case _CONTEXT_IN_LIST_FIRST: p.dumpContext.pop() p.dumpContext.push(_CONTEXT_IN_LIST) case _CONTEXT_IN_OBJECT_FIRST: p.dumpContext.pop() p.dumpContext.push(_CONTEXT_IN_OBJECT_NEXT_VALUE) case _CONTEXT_IN_OBJECT_NEXT_KEY: p.dumpContext.pop() p.dumpContext.push(_CONTEXT_IN_OBJECT_NEXT_VALUE) case _CONTEXT_IN_OBJECT_NEXT_VALUE: p.dumpContext.pop() p.dumpContext.push(_CONTEXT_IN_OBJECT_NEXT_KEY) } return nil } func (p *TSimpleJSONProtocol) OutputBool(value bool) error { if e := p.OutputPreValue(); e != nil { return e } var v string if value { v = string(JSON_TRUE) } else { v = string(JSON_FALSE) } cxt, ok := p.dumpContext.peek() if !ok { return errEmptyJSONContextStack } switch cxt { case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: v = jsonQuote(v) } if e := p.OutputStringData(v); e != nil { return e } return p.OutputPostValue() } func (p *TSimpleJSONProtocol) OutputNull() error { if e := p.OutputPreValue(); e != nil { return e } if _, e := p.write(JSON_NULL); e != nil { return NewTProtocolException(e) } return p.OutputPostValue() } func (p *TSimpleJSONProtocol) OutputF64(value float64) error { if e := p.OutputPreValue(); e != nil { return e } var v string if math.IsNaN(value) { v = string(JSON_QUOTE) + JSON_NAN + string(JSON_QUOTE) } else if math.IsInf(value, 1) { v = string(JSON_QUOTE) + JSON_INFINITY + string(JSON_QUOTE) } else if math.IsInf(value, -1) { v = string(JSON_QUOTE) + JSON_NEGATIVE_INFINITY + string(JSON_QUOTE) } else { cxt, ok := p.dumpContext.peek() if !ok { return errEmptyJSONContextStack } v = strconv.FormatFloat(value, 'g', -1, 64) switch cxt { case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: v = string(JSON_QUOTE) + v + string(JSON_QUOTE) } } if e := p.OutputStringData(v); e != nil { return e } return p.OutputPostValue() } func (p *TSimpleJSONProtocol) OutputI64(value int64) error { if e := p.OutputPreValue(); e != nil { return e } cxt, ok := p.dumpContext.peek() if !ok { return errEmptyJSONContextStack } v := strconv.FormatInt(value, 10) switch cxt { case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: v = jsonQuote(v) } if e := p.OutputStringData(v); e != nil { return e } return p.OutputPostValue() } func (p *TSimpleJSONProtocol) OutputString(s string) error { if e := p.OutputPreValue(); e != nil { return e } if e := p.OutputStringData(jsonQuote(s)); e != nil { return e } return p.OutputPostValue() } func (p *TSimpleJSONProtocol) OutputStringData(s string) error { _, e := p.write([]byte(s)) return NewTProtocolException(e) } func (p *TSimpleJSONProtocol) OutputObjectBegin() error { if e := p.OutputPreValue(); e != nil { return e } if _, e := p.write(JSON_LBRACE); e != nil { return NewTProtocolException(e) } p.dumpContext.push(_CONTEXT_IN_OBJECT_FIRST) return nil } func (p *TSimpleJSONProtocol) OutputObjectEnd() error { if _, e := p.write(JSON_RBRACE); e != nil { return NewTProtocolException(e) } _, ok := p.dumpContext.pop() if !ok { return errEmptyJSONContextStack } if e := p.OutputPostValue(); e != nil { return e } return nil } func (p *TSimpleJSONProtocol) OutputListBegin() error { if e := p.OutputPreValue(); e != nil { return e } if _, e := p.write(JSON_LBRACKET); e != nil { return NewTProtocolException(e) } p.dumpContext.push(_CONTEXT_IN_LIST_FIRST) return nil } func (p *TSimpleJSONProtocol) OutputListEnd() error { if _, e := p.write(JSON_RBRACKET); e != nil { return NewTProtocolException(e) } _, ok := p.dumpContext.pop() if !ok { return errEmptyJSONContextStack } if e := p.OutputPostValue(); e != nil { return e } return nil } func (p *TSimpleJSONProtocol) OutputElemListBegin(elemType TType, size int) error { if e := p.OutputListBegin(); e != nil { return e } if e := p.OutputI64(int64(elemType)); e != nil { return e } if e := p.OutputI64(int64(size)); e != nil { return e } return nil } func (p *TSimpleJSONProtocol) ParsePreValue() error { if e := p.readNonSignificantWhitespace(); e != nil { return NewTProtocolException(e) } cxt, ok := p.parseContextStack.peek() if !ok { return errEmptyJSONContextStack } b, _ := p.reader.Peek(1) switch cxt { case _CONTEXT_IN_LIST: if len(b) > 0 { switch b[0] { case JSON_RBRACKET[0]: return nil case JSON_COMMA[0]: p.reader.ReadByte() if e := p.readNonSignificantWhitespace(); e != nil { return NewTProtocolException(e) } return nil default: e := fmt.Errorf("Expected \"]\" or \",\" in list context, but found \"%s\"", string(b)) return NewTProtocolExceptionWithType(INVALID_DATA, e) } } case _CONTEXT_IN_OBJECT_NEXT_KEY: if len(b) > 0 { switch b[0] { case JSON_RBRACE[0]: return nil case JSON_COMMA[0]: p.reader.ReadByte() if e := p.readNonSignificantWhitespace(); e != nil { return NewTProtocolException(e) } return nil default: e := fmt.Errorf("Expected \"}\" or \",\" in object context, but found \"%s\"", string(b)) return NewTProtocolExceptionWithType(INVALID_DATA, e) } } case _CONTEXT_IN_OBJECT_NEXT_VALUE: if len(b) > 0 { switch b[0] { case JSON_COLON[0]: p.reader.ReadByte() if e := p.readNonSignificantWhitespace(); e != nil { return NewTProtocolException(e) } return nil default: e := fmt.Errorf("Expected \":\" in object context, but found \"%s\"", string(b)) return NewTProtocolExceptionWithType(INVALID_DATA, e) } } } return nil } func (p *TSimpleJSONProtocol) ParsePostValue() error { if e := p.readNonSignificantWhitespace(); e != nil { return NewTProtocolException(e) } cxt, ok := p.parseContextStack.peek() if !ok { return errEmptyJSONContextStack } switch cxt { case _CONTEXT_IN_LIST_FIRST: p.parseContextStack.pop() p.parseContextStack.push(_CONTEXT_IN_LIST) case _CONTEXT_IN_OBJECT_FIRST, _CONTEXT_IN_OBJECT_NEXT_KEY: p.parseContextStack.pop() p.parseContextStack.push(_CONTEXT_IN_OBJECT_NEXT_VALUE) case _CONTEXT_IN_OBJECT_NEXT_VALUE: p.parseContextStack.pop() p.parseContextStack.push(_CONTEXT_IN_OBJECT_NEXT_KEY) } return nil } func (p *TSimpleJSONProtocol) readNonSignificantWhitespace() error { for { b, _ := p.reader.Peek(1) if len(b) < 1 { return nil } switch b[0] { case ' ', '\r', '\n', '\t': p.reader.ReadByte() continue } break } return nil } func (p *TSimpleJSONProtocol) ParseStringBody() (string, error) { line, err := p.reader.ReadString(JSON_QUOTE) if err != nil { return "", NewTProtocolException(err) } l := len(line) // count number of escapes to see if we need to keep going i := 1 for ; i < l; i++ { if line[l-i-1] != '\\' { break } } if i&0x01 == 1 { v, ok := jsonUnquote(string(JSON_QUOTE) + line) if !ok { return "", NewTProtocolException(err) } return v, nil } s, err := p.ParseQuotedStringBody() if err != nil { return "", NewTProtocolException(err) } str := string(JSON_QUOTE) + line + s v, ok := jsonUnquote(str) if !ok { e := fmt.Errorf("Unable to parse as JSON string %s", str) return "", NewTProtocolExceptionWithType(INVALID_DATA, e) } return v, nil } func (p *TSimpleJSONProtocol) ParseQuotedStringBody() (string, error) { line, err := p.reader.ReadString(JSON_QUOTE) if err != nil { return "", NewTProtocolException(err) } l := len(line) // count number of escapes to see if we need to keep going i := 1 for ; i < l; i++ { if line[l-i-1] != '\\' { break } } if i&0x01 == 1 { return line, nil } s, err := p.ParseQuotedStringBody() if err != nil { return "", NewTProtocolException(err) } v := line + s return v, nil } func (p *TSimpleJSONProtocol) ParseBase64EncodedBody() ([]byte, error) { line, err := p.reader.ReadBytes(JSON_QUOTE) if err != nil { return line, NewTProtocolException(err) } line2 := line[0 : len(line)-1] l := len(line2) if (l % 4) != 0 { pad := 4 - (l % 4) fill := [...]byte{'=', '=', '='} line2 = append(line2, fill[:pad]...) l = len(line2) } output := make([]byte, base64.StdEncoding.DecodedLen(l)) n, err := base64.StdEncoding.Decode(output, line2) return output[0:n], NewTProtocolException(err) } func (p *TSimpleJSONProtocol) ParseI64() (int64, bool, error) { if err := p.ParsePreValue(); err != nil { return 0, false, err } var value int64 var isnull bool if p.safePeekContains(JSON_NULL) { p.reader.Read(make([]byte, len(JSON_NULL))) isnull = true } else { num, err := p.readNumeric() isnull = (num == nil) if !isnull { value = num.Int64() } if err != nil { return value, isnull, err } } return value, isnull, p.ParsePostValue() } func (p *TSimpleJSONProtocol) ParseF64() (float64, bool, error) { if err := p.ParsePreValue(); err != nil { return 0, false, err } var value float64 var isnull bool if p.safePeekContains(JSON_NULL) { p.reader.Read(make([]byte, len(JSON_NULL))) isnull = true } else { num, err := p.readNumeric() isnull = (num == nil) if !isnull { value = num.Float64() } if err != nil { return value, isnull, err } } return value, isnull, p.ParsePostValue() } func (p *TSimpleJSONProtocol) ParseObjectStart() (bool, error) { if err := p.ParsePreValue(); err != nil { return false, err } var b []byte b, err := p.reader.Peek(1) if err != nil { return false, err } if len(b) > 0 && b[0] == JSON_LBRACE[0] { p.reader.ReadByte() p.parseContextStack.push(_CONTEXT_IN_OBJECT_FIRST) return false, nil } else if p.safePeekContains(JSON_NULL) { return true, nil } e := fmt.Errorf("Expected '{' or null, but found '%s'", string(b)) return false, NewTProtocolExceptionWithType(INVALID_DATA, e) } func (p *TSimpleJSONProtocol) ParseObjectEnd() error { if isNull, err := p.readIfNull(); isNull || err != nil { return err } cxt, _ := p.parseContextStack.peek() if (cxt != _CONTEXT_IN_OBJECT_FIRST) && (cxt != _CONTEXT_IN_OBJECT_NEXT_KEY) { e := fmt.Errorf("Expected to be in the Object Context, but not in Object Context (%d)", cxt) return NewTProtocolExceptionWithType(INVALID_DATA, e) } line, err := p.reader.ReadString(JSON_RBRACE[0]) if err != nil { return NewTProtocolException(err) } for _, char := range line { switch char { default: e := fmt.Errorf("Expecting end of object \"}\", but found: \"%s\"", line) return NewTProtocolExceptionWithType(INVALID_DATA, e) case ' ', '\n', '\r', '\t', '}': // do nothing } } p.parseContextStack.pop() return p.ParsePostValue() } func (p *TSimpleJSONProtocol) ParseListBegin() (isNull bool, err error) { if e := p.ParsePreValue(); e != nil { return false, e } var b []byte b, err = p.reader.Peek(1) if err != nil { return false, err } if len(b) >= 1 && b[0] == JSON_LBRACKET[0] { p.parseContextStack.push(_CONTEXT_IN_LIST_FIRST) p.reader.ReadByte() isNull = false } else if p.safePeekContains(JSON_NULL) { isNull = true } else { err = fmt.Errorf("Expected \"null\" or \"[\", received %q", b) } return isNull, NewTProtocolExceptionWithType(INVALID_DATA, err) } func (p *TSimpleJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { if isNull, e := p.ParseListBegin(); isNull || e != nil { return VOID, 0, e } bElemType, _, err := p.ParseI64() elemType = TType(bElemType) if err != nil { return elemType, size, err } nSize, _, err := p.ParseI64() if err != nil { return elemType, 0, err } err = checkSizeForProtocol(int32(nSize), p.cfg) if err != nil { return elemType, 0, err } size = int(nSize) return elemType, size, nil } func (p *TSimpleJSONProtocol) ParseListEnd() error { if isNull, err := p.readIfNull(); isNull || err != nil { return err } cxt, _ := p.parseContextStack.peek() if cxt != _CONTEXT_IN_LIST { e := fmt.Errorf("Expected to be in the List Context, but not in List Context (%d)", cxt) return NewTProtocolExceptionWithType(INVALID_DATA, e) } line, err := p.reader.ReadString(JSON_RBRACKET[0]) if err != nil { return NewTProtocolException(err) } for _, char := range line { switch char { default: e := fmt.Errorf("Expecting end of list \"]\", but found: \"%v\"", line) return NewTProtocolExceptionWithType(INVALID_DATA, e) case ' ', '\n', '\r', '\t', rune(JSON_RBRACKET[0]): // do nothing } } p.parseContextStack.pop() if cxt, ok := p.parseContextStack.peek(); !ok { return errEmptyJSONContextStack } else if cxt == _CONTEXT_IN_TOPLEVEL { return nil } return p.ParsePostValue() } func (p *TSimpleJSONProtocol) readIfNull() (bool, error) { cont := true for cont { b, _ := p.reader.Peek(1) if len(b) < 1 { return false, nil } switch b[0] { default: return false, nil case JSON_NULL[0]: cont = false case ' ', '\n', '\r', '\t': p.reader.ReadByte() } } if p.safePeekContains(JSON_NULL) { p.reader.Read(make([]byte, len(JSON_NULL))) return true, nil } return false, nil } func (p *TSimpleJSONProtocol) readQuoteIfNext() { b, _ := p.reader.Peek(1) if len(b) > 0 && b[0] == JSON_QUOTE { p.reader.ReadByte() } } func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) { isNull, err := p.readIfNull() if isNull || err != nil { return NUMERIC_NULL, err } hasDecimalPoint := false nextCanBeSign := true hasE := false MAX_LEN := 40 buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN)) continueFor := true inQuotes := false for continueFor { c, err := p.reader.ReadByte() if err != nil { if err == io.EOF { break } return NUMERIC_NULL, NewTProtocolException(err) } switch c { case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': buf.WriteByte(c) nextCanBeSign = false case '.': if hasDecimalPoint { e := fmt.Errorf("Unable to parse number with multiple decimal points '%s.'", buf.String()) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } if hasE { e := fmt.Errorf("Unable to parse number with decimal points in the exponent '%s.'", buf.String()) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } buf.WriteByte(c) hasDecimalPoint, nextCanBeSign = true, false case 'e', 'E': if hasE { e := fmt.Errorf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } buf.WriteByte(c) hasE, nextCanBeSign = true, true case '-', '+': if !nextCanBeSign { e := fmt.Errorf("Negative sign within number") return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } buf.WriteByte(c) nextCanBeSign = false case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]: p.reader.UnreadByte() continueFor = false case JSON_NAN[0]: if buf.Len() == 0 { buffer := make([]byte, len(JSON_NAN)) buffer[0] = c _, e := p.reader.Read(buffer[1:]) if e != nil { return NUMERIC_NULL, NewTProtocolException(e) } if JSON_NAN != string(buffer) { e := mismatch(JSON_NAN, string(buffer)) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } if inQuotes { p.readQuoteIfNext() } return NAN, nil } else { e := fmt.Errorf("Unable to parse number starting with character '%c'", c) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } case JSON_INFINITY[0]: if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') { buffer := make([]byte, len(JSON_INFINITY)) buffer[0] = c _, e := p.reader.Read(buffer[1:]) if e != nil { return NUMERIC_NULL, NewTProtocolException(e) } if JSON_INFINITY != string(buffer) { e := mismatch(JSON_INFINITY, string(buffer)) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } if inQuotes { p.readQuoteIfNext() } return INFINITY, nil } else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] { buffer := make([]byte, len(JSON_NEGATIVE_INFINITY)) buffer[0] = JSON_NEGATIVE_INFINITY[0] buffer[1] = c _, e := p.reader.Read(buffer[2:]) if e != nil { return NUMERIC_NULL, NewTProtocolException(e) } if JSON_NEGATIVE_INFINITY != string(buffer) { e := mismatch(JSON_NEGATIVE_INFINITY, string(buffer)) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } if inQuotes { p.readQuoteIfNext() } return NEGATIVE_INFINITY, nil } else { e := fmt.Errorf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String()) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } case JSON_QUOTE: if !inQuotes { inQuotes = true } default: e := fmt.Errorf("Unable to parse number starting with character '%c'", c) return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } } if buf.Len() == 0 { e := fmt.Errorf("Unable to parse number from empty string ''") return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e) } return NewNumericFromJSONString(buf.String(), false), nil } // Safely peeks into the buffer, reading only what is necessary func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool { for i := 0; i < len(b); i++ { a, _ := p.reader.Peek(i + 1) if len(a) < (i+1) || a[i] != b[i] { return false } } return true } // Reset the context stack to its initial state. func (p *TSimpleJSONProtocol) resetContextStack() { p.parseContextStack = jsonContextStack{_CONTEXT_IN_TOPLEVEL} p.dumpContext = jsonContextStack{_CONTEXT_IN_TOPLEVEL} } func (p *TSimpleJSONProtocol) write(b []byte) (int, error) { n, err := p.writer.Write(b) if err != nil { p.writer.Reset(p.trans) // THRIFT-3735 } return n, err } // SetTConfiguration implements TConfigurationSetter for propagation. func (p *TSimpleJSONProtocol) SetTConfiguration(conf *TConfiguration) { PropagateTConfiguration(p.trans, conf) p.cfg = conf } // Reset resets this protocol's internal state. // // It's useful when a single protocol instance is reused after errors, to make // sure the next use will not be in a bad state to begin with. An example is // when it's used in serializer/deserializer pools. func (p *TSimpleJSONProtocol) Reset() { p.resetContextStack() p.writer.Reset(p.trans) p.reader.Reset(p.trans) } var ( _ TConfigurationSetter = (*TSimpleJSONProtocol)(nil) _ TConfigurationSetter = (*TSimpleJSONProtocolFactory)(nil) ) thrift-0.19.0/lib/go/thrift/configuration.go0000644000000000000000000002773114303740367020771 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "crypto/tls" "fmt" "time" ) // Default TConfiguration values. const ( DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024 DEFAULT_MAX_FRAME_SIZE = 16384000 DEFAULT_TBINARY_STRICT_READ = false DEFAULT_TBINARY_STRICT_WRITE = true DEFAULT_CONNECT_TIMEOUT = 0 DEFAULT_SOCKET_TIMEOUT = 0 ) // TConfiguration defines some configurations shared between TTransport, // TProtocol, TTransportFactory, TProtocolFactory, and other implementations. // // When constructing TConfiguration, you only need to specify the non-default // fields. All zero values have sane default values. // // Not all configurations defined are applicable to all implementations. // Implementations are free to ignore the configurations not applicable to them. // // All functions attached to this type are nil-safe. // // See [1] for spec. // // NOTE: When using TConfiguration, fill in all the configurations you want to // set across the stack, not only the ones you want to set in the immediate // TTransport/TProtocol. // // For example, say you want to migrate this old code into using TConfiguration: // // sccket, err := thrift.NewTSocketTimeout("host:port", time.Second, time.Second) // transFactory := thrift.NewTFramedTransportFactoryMaxLength( // thrift.NewTTransportFactory(), // 1024 * 1024 * 256, // ) // protoFactory := thrift.NewTBinaryProtocolFactory(true, true) // // This is the wrong way to do it because in the end the TConfiguration used by // socket and transFactory will be overwritten by the one used by protoFactory // because of TConfiguration propagation: // // // bad example, DO NOT USE // sccket := thrift.NewTSocketConf("host:port", &thrift.TConfiguration{ // ConnectTimeout: time.Second, // SocketTimeout: time.Second, // }) // transFactory := thrift.NewTFramedTransportFactoryConf( // thrift.NewTTransportFactory(), // &thrift.TConfiguration{ // MaxFrameSize: 1024 * 1024 * 256, // }, // ) // protoFactory := thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{ // TBinaryStrictRead: thrift.BoolPtr(true), // TBinaryStrictWrite: thrift.BoolPtr(true), // }) // // This is the correct way to do it: // // conf := &thrift.TConfiguration{ // ConnectTimeout: time.Second, // SocketTimeout: time.Second, // // MaxFrameSize: 1024 * 1024 * 256, // // TBinaryStrictRead: thrift.BoolPtr(true), // TBinaryStrictWrite: thrift.BoolPtr(true), // } // sccket := thrift.NewTSocketConf("host:port", conf) // transFactory := thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), conf) // protoFactory := thrift.NewTBinaryProtocolFactoryConf(conf) // // [1]: https://github.com/apache/thrift/blob/master/doc/specs/thrift-tconfiguration.md type TConfiguration struct { // If <= 0, DEFAULT_MAX_MESSAGE_SIZE will be used instead. MaxMessageSize int32 // If <= 0, DEFAULT_MAX_FRAME_SIZE will be used instead. // // Also if MaxMessageSize < MaxFrameSize, // MaxMessageSize will be used instead. MaxFrameSize int32 // Connect and socket timeouts to be used by TSocket and TSSLSocket. // // 0 means no timeout. // // If <0, DEFAULT_CONNECT_TIMEOUT and DEFAULT_SOCKET_TIMEOUT will be // used. ConnectTimeout time.Duration SocketTimeout time.Duration // TLS config to be used by TSSLSocket. TLSConfig *tls.Config // Strict read/write configurations for TBinaryProtocol. // // BoolPtr helper function is available to use literal values. TBinaryStrictRead *bool TBinaryStrictWrite *bool // The wrapped protocol id to be used in THeader transport/protocol. // // THeaderProtocolIDPtr and THeaderProtocolIDPtrMust helper functions // are provided to help filling this value. THeaderProtocolID *THeaderProtocolID // Used internally by deprecated constructors, to avoid overriding // underlying TTransport/TProtocol's cfg by accidental propagations. // // For external users this is always false. noPropagation bool } // GetMaxMessageSize returns the max message size an implementation should // follow. // // It's nil-safe. DEFAULT_MAX_MESSAGE_SIZE will be returned if tc is nil. func (tc *TConfiguration) GetMaxMessageSize() int32 { if tc == nil || tc.MaxMessageSize <= 0 { return DEFAULT_MAX_MESSAGE_SIZE } return tc.MaxMessageSize } // GetMaxFrameSize returns the max frame size an implementation should follow. // // It's nil-safe. DEFAULT_MAX_FRAME_SIZE will be returned if tc is nil. // // If the configured max message size is smaller than the configured max frame // size, the smaller one will be returned instead. func (tc *TConfiguration) GetMaxFrameSize() int32 { if tc == nil { return DEFAULT_MAX_FRAME_SIZE } maxFrameSize := tc.MaxFrameSize if maxFrameSize <= 0 { maxFrameSize = DEFAULT_MAX_FRAME_SIZE } if maxMessageSize := tc.GetMaxMessageSize(); maxMessageSize < maxFrameSize { return maxMessageSize } return maxFrameSize } // GetConnectTimeout returns the connect timeout should be used by TSocket and // TSSLSocket. // // It's nil-safe. If tc is nil, DEFAULT_CONNECT_TIMEOUT will be returned instead. func (tc *TConfiguration) GetConnectTimeout() time.Duration { if tc == nil || tc.ConnectTimeout < 0 { return DEFAULT_CONNECT_TIMEOUT } return tc.ConnectTimeout } // GetSocketTimeout returns the socket timeout should be used by TSocket and // TSSLSocket. // // It's nil-safe. If tc is nil, DEFAULT_SOCKET_TIMEOUT will be returned instead. func (tc *TConfiguration) GetSocketTimeout() time.Duration { if tc == nil || tc.SocketTimeout < 0 { return DEFAULT_SOCKET_TIMEOUT } return tc.SocketTimeout } // GetTLSConfig returns the tls config should be used by TSSLSocket. // // It's nil-safe. If tc is nil, nil will be returned instead. func (tc *TConfiguration) GetTLSConfig() *tls.Config { if tc == nil { return nil } return tc.TLSConfig } // GetTBinaryStrictRead returns the strict read configuration TBinaryProtocol // should follow. // // It's nil-safe. DEFAULT_TBINARY_STRICT_READ will be returned if either tc or // tc.TBinaryStrictRead is nil. func (tc *TConfiguration) GetTBinaryStrictRead() bool { if tc == nil || tc.TBinaryStrictRead == nil { return DEFAULT_TBINARY_STRICT_READ } return *tc.TBinaryStrictRead } // GetTBinaryStrictWrite returns the strict read configuration TBinaryProtocol // should follow. // // It's nil-safe. DEFAULT_TBINARY_STRICT_WRITE will be returned if either tc or // tc.TBinaryStrictWrite is nil. func (tc *TConfiguration) GetTBinaryStrictWrite() bool { if tc == nil || tc.TBinaryStrictWrite == nil { return DEFAULT_TBINARY_STRICT_WRITE } return *tc.TBinaryStrictWrite } // GetTHeaderProtocolID returns the THeaderProtocolID should be used by // THeaderProtocol clients (for servers, they always use the same one as the // client instead). // // It's nil-safe. If either tc or tc.THeaderProtocolID is nil, // THeaderProtocolDefault will be returned instead. // THeaderProtocolDefault will also be returned if configured value is invalid. func (tc *TConfiguration) GetTHeaderProtocolID() THeaderProtocolID { if tc == nil || tc.THeaderProtocolID == nil { return THeaderProtocolDefault } protoID := *tc.THeaderProtocolID if err := protoID.Validate(); err != nil { return THeaderProtocolDefault } return protoID } // THeaderProtocolIDPtr validates and returns the pointer to id. // // If id is not a valid THeaderProtocolID, a pointer to THeaderProtocolDefault // and the validation error will be returned. func THeaderProtocolIDPtr(id THeaderProtocolID) (*THeaderProtocolID, error) { err := id.Validate() if err != nil { id = THeaderProtocolDefault } return &id, err } // THeaderProtocolIDPtrMust validates and returns the pointer to id. // // It's similar to THeaderProtocolIDPtr, but it panics on validation errors // instead of returning them. func THeaderProtocolIDPtrMust(id THeaderProtocolID) *THeaderProtocolID { ptr, err := THeaderProtocolIDPtr(id) if err != nil { panic(err) } return ptr } // TConfigurationSetter is an optional interface TProtocol, TTransport, // TProtocolFactory, TTransportFactory, and other implementations can implement. // // It's intended to be called during intializations. // The behavior of calling SetTConfiguration on a TTransport/TProtocol in the // middle of a message is undefined: // It may or may not change the behavior of the current processing message, // and it may even cause the current message to fail. // // Note for implementations: SetTConfiguration might be called multiple times // with the same value in quick successions due to the implementation of the // propagation. Implementations should make SetTConfiguration as simple as // possible (usually just overwrite the stored configuration and propagate it to // the wrapped TTransports/TProtocols). type TConfigurationSetter interface { SetTConfiguration(*TConfiguration) } // PropagateTConfiguration propagates cfg to impl if impl implements // TConfigurationSetter and cfg is non-nil, otherwise it does nothing. // // NOTE: nil cfg is not propagated. If you want to propagate a TConfiguration // with everything being default value, use &TConfiguration{} explicitly instead. func PropagateTConfiguration(impl interface{}, cfg *TConfiguration) { if cfg == nil || cfg.noPropagation { return } if setter, ok := impl.(TConfigurationSetter); ok { setter.SetTConfiguration(cfg) } } func checkSizeForProtocol(size int32, cfg *TConfiguration) error { if size < 0 { return NewTProtocolExceptionWithType( NEGATIVE_SIZE, fmt.Errorf("negative size: %d", size), ) } if size > cfg.GetMaxMessageSize() { return NewTProtocolExceptionWithType( SIZE_LIMIT, fmt.Errorf("size exceeded max allowed: %d", size), ) } return nil } type tTransportFactoryConf struct { delegate TTransportFactory cfg *TConfiguration } func (f *tTransportFactoryConf) GetTransport(orig TTransport) (TTransport, error) { trans, err := f.delegate.GetTransport(orig) if err == nil { PropagateTConfiguration(orig, f.cfg) PropagateTConfiguration(trans, f.cfg) } return trans, err } func (f *tTransportFactoryConf) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(f.delegate, f.cfg) f.cfg = cfg } // TTransportFactoryConf wraps a TTransportFactory to propagate // TConfiguration on the factory's GetTransport calls. func TTransportFactoryConf(delegate TTransportFactory, conf *TConfiguration) TTransportFactory { return &tTransportFactoryConf{ delegate: delegate, cfg: conf, } } type tProtocolFactoryConf struct { delegate TProtocolFactory cfg *TConfiguration } func (f *tProtocolFactoryConf) GetProtocol(trans TTransport) TProtocol { proto := f.delegate.GetProtocol(trans) PropagateTConfiguration(trans, f.cfg) PropagateTConfiguration(proto, f.cfg) return proto } func (f *tProtocolFactoryConf) SetTConfiguration(cfg *TConfiguration) { PropagateTConfiguration(f.delegate, f.cfg) f.cfg = cfg } // TProtocolFactoryConf wraps a TProtocolFactory to propagate // TConfiguration on the factory's GetProtocol calls. func TProtocolFactoryConf(delegate TProtocolFactory, conf *TConfiguration) TProtocolFactory { return &tProtocolFactoryConf{ delegate: delegate, cfg: conf, } } var ( _ TConfigurationSetter = (*tTransportFactoryConf)(nil) _ TConfigurationSetter = (*tProtocolFactoryConf)(nil) ) thrift-0.19.0/lib/go/thrift/rich_transport_test.go0000644000000000000000000000510414303740367022210 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "bytes" "errors" "io" "reflect" "testing" ) func TestEnsureTransportsAreRich(t *testing.T) { buf := bytes.NewBuffer(make([]byte, 0, 1024)) transports := []TTransportFactory{ NewTMemoryBufferTransportFactory(1024), NewStreamTransportFactory(buf, buf, true), NewTFramedTransportFactory(NewTMemoryBufferTransportFactory(1024)), NewTHttpPostClientTransportFactory("http://127.0.0.1"), } for _, tf := range transports { trans, err := tf.GetTransport(nil) if err != nil { t.Error(err) continue } _, ok := trans.(TRichTransport) if !ok { t.Errorf("Transport %s does not implement TRichTransport interface", reflect.ValueOf(trans)) } } } // TestReadByte tests whether readByte handles error cases correctly. func TestReadByte(t *testing.T) { for i, test := range readByteTests { v, err := readByte(test.r) if v != test.v { t.Fatalf("TestReadByte %d: value differs. Expected %d, got %d", i, test.v, test.r.v) } if err != test.err { t.Fatalf("TestReadByte %d: error differs. Expected %s, got %s", i, test.err, test.r.err) } } } var errSomeError = errors.New("Some error") var readByteTests = []struct { r *mockReader v byte err error }{ {&mockReader{0, 55, io.EOF}, 0, io.EOF}, // reader sends EOF w/o data {&mockReader{0, 55, errSomeError}, 0, errSomeError}, // reader sends some other error {&mockReader{1, 55, nil}, 55, nil}, // reader sends data w/o error {&mockReader{1, 55, io.EOF}, 55, nil}, // reader sends data with EOF {&mockReader{1, 55, errSomeError}, 55, errSomeError}, // reader sends data withsome error } type mockReader struct { n int v byte err error } func (r *mockReader) Read(p []byte) (n int, err error) { if r.n > 0 { p[0] = r.v } return r.n, r.err } thrift-0.19.0/lib/go/thrift/response_helper.go0000644000000000000000000000575314303740367021317 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" ) // See https://godoc.org/context#WithValue on why do we need the unexported typedefs. type responseHelperKey struct{} // TResponseHelper defines a object with a set of helper functions that can be // retrieved from the context object passed into server handler functions. // // Use GetResponseHelper to retrieve the injected TResponseHelper implementation // from the context object. // // The zero value of TResponseHelper is valid with all helper functions being // no-op. type TResponseHelper struct { // THeader related functions *THeaderResponseHelper } // THeaderResponseHelper defines THeader related TResponseHelper functions. // // The zero value of *THeaderResponseHelper is valid with all helper functions // being no-op. type THeaderResponseHelper struct { proto *THeaderProtocol } // NewTHeaderResponseHelper creates a new THeaderResponseHelper from the // underlying TProtocol. func NewTHeaderResponseHelper(proto TProtocol) *THeaderResponseHelper { if hp, ok := proto.(*THeaderProtocol); ok { return &THeaderResponseHelper{ proto: hp, } } return nil } // SetHeader sets a response header. // // It's no-op if the underlying protocol/transport does not support THeader. func (h *THeaderResponseHelper) SetHeader(key, value string) { if h != nil && h.proto != nil { h.proto.SetWriteHeader(key, value) } } // ClearHeaders clears all the response headers previously set. // // It's no-op if the underlying protocol/transport does not support THeader. func (h *THeaderResponseHelper) ClearHeaders() { if h != nil && h.proto != nil { h.proto.ClearWriteHeaders() } } // GetResponseHelper retrieves the TResponseHelper implementation injected into // the context object. // // If no helper was found in the context object, a nop helper with ok == false // will be returned. func GetResponseHelper(ctx context.Context) (helper TResponseHelper, ok bool) { if v := ctx.Value(responseHelperKey{}); v != nil { helper, ok = v.(TResponseHelper) } return } // SetResponseHelper injects TResponseHelper into the context object. func SetResponseHelper(ctx context.Context, helper TResponseHelper) context.Context { return context.WithValue(ctx, responseHelperKey{}, helper) } thrift-0.19.0/lib/go/thrift/protocol_factory.go0000644000000000000000000000167414303740367021510 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift // Factory interface for constructing protocol instances. type TProtocolFactory interface { GetProtocol(trans TTransport) TProtocol } thrift-0.19.0/lib/go/thrift/header_protocol_test.go0000644000000000000000000000227414303740367022325 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "testing" ) func TestReadWriteHeaderProtocol(t *testing.T) { t.Run( "default", func(t *testing.T) { ReadWriteProtocolTest(t, NewTHeaderProtocolFactory()) }, ) t.Run( "compact", func(t *testing.T) { ReadWriteProtocolTest(t, NewTHeaderProtocolFactoryConf(&TConfiguration{ THeaderProtocolID: THeaderProtocolIDPtrMust(THeaderProtocolCompact), })) }, ) } thrift-0.19.0/lib/go/thrift/simple_server_test.go0000644000000000000000000001536114303740367022034 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "errors" "net" "runtime" "sync" "testing" "time" ) const networkWaitDuration = 10 * time.Millisecond type mockServerTransport struct { ListenFunc func() error AcceptFunc func() (TTransport, error) CloseFunc func() error InterruptFunc func() error } func (m *mockServerTransport) Listen() error { return m.ListenFunc() } func (m *mockServerTransport) Accept() (TTransport, error) { return m.AcceptFunc() } func (m *mockServerTransport) Close() error { return m.CloseFunc() } func (m *mockServerTransport) Interrupt() error { return m.InterruptFunc() } type mockTTransport struct { TTransport } func (m *mockTTransport) Close() error { return nil } func TestMultipleStop(t *testing.T) { proc := &mockProcessor{ ProcessFunc: func(in, out TProtocol) (bool, TException) { return false, nil }, } var interruptCalled bool c := make(chan struct{}) trans := &mockServerTransport{ ListenFunc: func() error { return nil }, AcceptFunc: func() (TTransport, error) { <-c return nil, nil }, CloseFunc: func() error { c <- struct{}{} return nil }, InterruptFunc: func() error { interruptCalled = true return nil }, } serv := NewTSimpleServer2(proc, trans) go serv.Serve() serv.Stop() if !interruptCalled { t.Error("first server transport should have been interrupted") } serv = NewTSimpleServer2(proc, trans) interruptCalled = false go serv.Serve() serv.Stop() if !interruptCalled { t.Error("second server transport should have been interrupted") } } func TestWaitRace(t *testing.T) { proc := &mockProcessor{ ProcessFunc: func(in, out TProtocol) (bool, TException) { return false, nil }, } trans := &mockServerTransport{ ListenFunc: func() error { return nil }, AcceptFunc: func() (TTransport, error) { return &mockTTransport{}, nil }, CloseFunc: func() error { return nil }, InterruptFunc: func() error { return nil }, } serv := NewTSimpleServer2(proc, trans) go serv.Serve() runtime.Gosched() serv.Stop() } func TestNoHangDuringStopFromDanglingLockAcquireDuringAcceptLoop(t *testing.T) { proc := &mockProcessor{ ProcessFunc: func(in, out TProtocol) (bool, TException) { return false, nil }, } trans := &mockServerTransport{ ListenFunc: func() error { return nil }, AcceptFunc: func() (TTransport, error) { return nil, errors.New("no sir") }, CloseFunc: func() error { return nil }, InterruptFunc: func() error { return nil }, } serv := NewTSimpleServer2(proc, trans) go serv.Serve() runtime.Gosched() serv.Stop() } func TestNoHangDuringStopFromClientNoDataSendDuringAcceptLoop(t *testing.T) { ln, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("Failed to listen: %v", err) } proc := &mockProcessor{ ProcessFunc: func(in, out TProtocol) (bool, TException) { in.ReadMessageBegin(context.Background()) return false, nil }, } trans := &mockServerTransport{ ListenFunc: func() error { return nil }, AcceptFunc: func() (TTransport, error) { conn, err := ln.Accept() if err != nil { return nil, err } return NewTSocketFromConnConf(conn, nil), nil }, CloseFunc: func() error { return nil }, InterruptFunc: func() error { return ln.Close() }, } serv := NewTSimpleServer2(proc, trans) go serv.Serve() time.Sleep(networkWaitDuration) netConn, err := net.Dial("tcp", ln.Addr().String()) if err != nil || netConn == nil { t.Fatalf("error when dial server: %v", err) } time.Sleep(networkWaitDuration) const serverStopTimeout = 50 * time.Millisecond backupServerStopTimeout := ServerStopTimeout t.Cleanup(func() { ServerStopTimeout = backupServerStopTimeout }) ServerStopTimeout = serverStopTimeout st := time.Now() if err := serv.Stop(); err != nil { t.Errorf("error when stop server:%v", err) } if elapsed := time.Since(st); elapsed < serverStopTimeout { t.Errorf("stop cost less time than server stop timeout, server stop timeout:%v,cost time:%v", serverStopTimeout, elapsed) } } func TestStopTimeoutWithSocketTimeout(t *testing.T) { ln, err := net.Listen("tcp", "localhost:0") if err != nil { t.Fatalf("Failed to listen: %v", err) } proc := &mockProcessor{ ProcessFunc: func(in, out TProtocol) (bool, TException) { in.ReadMessageBegin(context.Background()) return false, nil }, } conf := &TConfiguration{SocketTimeout: 5 * time.Millisecond} wg := &sync.WaitGroup{} trans := &mockServerTransport{ ListenFunc: func() error { return nil }, AcceptFunc: func() (TTransport, error) { conn, err := ln.Accept() if err != nil { return nil, err } defer wg.Done() return NewTSocketFromConnConf(conn, conf), nil }, CloseFunc: func() error { return nil }, InterruptFunc: func() error { return ln.Close() }, } serv := NewTSimpleServer2(proc, trans) go serv.Serve() time.Sleep(networkWaitDuration) wg.Add(1) netConn, err := net.Dial("tcp", ln.Addr().String()) if err != nil || netConn == nil { t.Fatal("error when dial server") } wg.Wait() expectedStopTimeout := time.Second backupServerStopTimeout := ServerStopTimeout t.Cleanup(func() { ServerStopTimeout = backupServerStopTimeout }) ServerStopTimeout = expectedStopTimeout st := time.Now() err = serv.Stop() if elapsed := time.Since(st); elapsed > expectedStopTimeout/2 { t.Errorf("stop cost more time than socket timeout, socket timeout:%v,server stop timeout:%v,cost time:%v", conf.SocketTimeout, ServerStopTimeout, elapsed) } if err != nil { t.Fatalf("error when stop server:%v", err) } } func TestErrAbandonRequest(t *testing.T) { if !errors.Is(ErrAbandonRequest, ErrAbandonRequest) { t.Error("errors.Is(ErrAbandonRequest, ErrAbandonRequest) returned false") } if !errors.Is(ErrAbandonRequest, context.Canceled) { t.Error("errors.Is(ErrAbandonRequest, context.Canceled) returned false") } if errors.Is(context.Canceled, ErrAbandonRequest) { t.Error("errors.Is(context.Canceled, ErrAbandonRequest) returned true") } } thrift-0.19.0/lib/go/thrift/json_protocol_test.go0000644000000000000000000005400014303740367022040 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "encoding/base64" "encoding/json" "fmt" "math" "strconv" "testing" ) func TestWriteJSONProtocolBool(t *testing.T) { thetype := "boolean" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range BOOL_VALUES { if e := p.WriteBool(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() expected := "" if value { expected = "1" } else { expected = "0" } if s != expected { t.Fatalf("Bad value for %s %v: %s expected", thetype, value, s) } v := -1 if err := json.Unmarshal([]byte(s), &v); err != nil || (v != 0) != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadJSONProtocolBool(t *testing.T) { thetype := "boolean" for _, value := range BOOL_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) if value { trans.Write([]byte{'1'}) // not JSON_TRUE } else { trans.Write([]byte{'0'}) // not JSON_FALSE } trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBool(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } vv := -1 if err := json.Unmarshal([]byte(s), &vv); err != nil || (vv != 0) != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, vv) } trans.Reset() trans.Close() } } func TestWriteJSONProtocolByte(t *testing.T) { thetype := "byte" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range BYTE_VALUES { if e := p.WriteByte(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int8(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadJSONProtocolByte(t *testing.T) { thetype := "byte" for _, value := range BYTE_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadByte(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteJSONProtocolI16(t *testing.T) { thetype := "int16" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range INT16_VALUES { if e := p.WriteI16(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int16(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadJSONProtocolI16(t *testing.T) { thetype := "int16" for _, value := range INT16_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI16(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteJSONProtocolI32(t *testing.T) { thetype := "int32" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range INT32_VALUES { if e := p.WriteI32(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int32(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadJSONProtocolI32(t *testing.T) { thetype := "int32" for _, value := range INT32_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI32(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteJSONProtocolI64(t *testing.T) { thetype := "int64" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range INT64_VALUES { if e := p.WriteI64(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int64(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadJSONProtocolI64(t *testing.T) { thetype := "int64" for _, value := range INT64_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(strconv.FormatInt(value, 10)) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI64(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteJSONProtocolDouble(t *testing.T) { thetype := "double" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range DOUBLE_VALUES { if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if math.IsInf(value, 1) { if s != jsonQuote(JSON_INFINITY) { t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_INFINITY)) } } else if math.IsInf(value, -1) { if s != jsonQuote(JSON_NEGATIVE_INFINITY) { t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) } } else if math.IsNaN(value) { if s != jsonQuote(JSON_NAN) { t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NAN)) } } else { if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := float64(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } } trans.Reset() } trans.Close() } func TestReadJSONProtocolDouble(t *testing.T) { thetype := "double" for _, value := range DOUBLE_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) n := NewNumericFromDouble(value) trans.WriteString(n.String()) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadDouble(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if math.IsInf(value, 1) { if !math.IsInf(v, 1) { t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) } } else if math.IsInf(value, -1) { if !math.IsInf(v, -1) { t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) } } else if math.IsNaN(value) { if !math.IsNaN(v) { t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) } } else { if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } } trans.Reset() trans.Close() } } func TestWriteJSONProtocolString(t *testing.T) { thetype := "string" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) for _, value := range STRING_VALUES { if e := p.WriteString(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s[0] != '"' || s[len(s)-1] != '"' { t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\"")) } v := new(string) if err := json.Unmarshal([]byte(s), v); err != nil || *v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v) } trans.Reset() } trans.Close() } func TestReadJSONProtocolString(t *testing.T) { thetype := "string" for _, value := range STRING_VALUES { trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(jsonQuote(value)) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadString(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } v1 := new(string) if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) } trans.Reset() trans.Close() } } func TestWriteJSONProtocolBinary(t *testing.T) { thetype := "binary" value := protocol_bdata b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) base64.StdEncoding.Encode(b64value, value) b64String := string(b64value) trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) if e := p.WriteBinary(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() expectedString := fmt.Sprint("\"", b64String, "\"") if s != expectedString { t.Fatalf("Bad value for %s %v\n wrote: \"%v\"\nexpected: \"%v\"", thetype, value, s, expectedString) } v1, err := p.ReadBinary(context.Background()) if err != nil { t.Fatalf("Unable to read binary: %s", err.Error()) } if len(v1) != len(value) { t.Fatalf("Invalid value for binary\nexpected: \"%v\"\n read: \"%v\"", value, v1) } for k, v := range value { if v1[k] != v { t.Fatalf("Invalid value for binary at %v\nexpected: \"%v\"\n read: \"%v\"", k, v, v1[k]) } } trans.Close() } func TestReadJSONProtocolBinary(t *testing.T) { thetype := "binary" value := protocol_bdata b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) base64.StdEncoding.Encode(b64value, value) b64String := string(b64value) trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) trans.WriteString(jsonQuote(b64String)) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBinary(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if len(v) != len(value) { t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v)) } for i := 0; i < len(v); i++ { if v[i] != value[i] { t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i]) } } v1 := new(string) if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) } trans.Reset() trans.Close() } func TestWriteJSONProtocolList(t *testing.T) { thetype := "list" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) p.WriteListBegin(context.Background(), TType(DOUBLE), len(DOUBLE_VALUES)) for _, value := range DOUBLE_VALUES { if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } } p.WriteListEnd(context.Background()) if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() str1 := new([]interface{}) err := json.Unmarshal([]byte(str), str1) if err != nil { t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) } l := *str1 if len(l) < 2 { t.Fatalf("List must be at least of length two to include metadata") } if l[0] != "dbl" { t.Fatal("Invalid type for list, expected: ", STRING, ", but was: ", l[0]) } if int(l[1].(float64)) != len(DOUBLE_VALUES) { t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) } for k, value := range DOUBLE_VALUES { s := l[k+2] if math.IsInf(value, 1) { if s.(string) != JSON_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) } } else if math.IsInf(value, 0) { if s.(string) != JSON_NEGATIVE_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) } } else if math.IsNaN(value) { if s.(string) != JSON_NAN { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) } } else { if s.(float64) != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) } } trans.Reset() } trans.Close() } func TestWriteJSONProtocolSet(t *testing.T) { thetype := "set" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) p.WriteSetBegin(context.Background(), TType(DOUBLE), len(DOUBLE_VALUES)) for _, value := range DOUBLE_VALUES { if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } } p.WriteSetEnd(context.Background()) if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() str1 := new([]interface{}) err := json.Unmarshal([]byte(str), str1) if err != nil { t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) } l := *str1 if len(l) < 2 { t.Fatalf("Set must be at least of length two to include metadata") } if l[0] != "dbl" { t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0]) } if int(l[1].(float64)) != len(DOUBLE_VALUES) { t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) } for k, value := range DOUBLE_VALUES { s := l[k+2] if math.IsInf(value, 1) { if s.(string) != JSON_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) } } else if math.IsInf(value, 0) { if s.(string) != JSON_NEGATIVE_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) } } else if math.IsNaN(value) { if s.(string) != JSON_NAN { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) } } else { if s.(float64) != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) } } trans.Reset() } trans.Close() } func TestWriteJSONProtocolMap(t *testing.T) { thetype := "map" trans := NewTMemoryBuffer() p := NewTJSONProtocol(trans) p.WriteMapBegin(context.Background(), TType(I32), TType(DOUBLE), len(DOUBLE_VALUES)) for k, value := range DOUBLE_VALUES { if e := p.WriteI32(context.Background(), int32(k)); e != nil { t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.Error()) } if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.Error()) } } p.WriteMapEnd(context.Background()) if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() if str[0] != '[' || str[len(str)-1] != ']' { t.Fatalf("Bad value for %s, wrote: %v, in go: %v", thetype, str, DOUBLE_VALUES) } expectedKeyType, expectedValueType, expectedSize, err := p.ReadMapBegin(context.Background()) if err != nil { t.Fatalf("Error while reading map begin: %s", err.Error()) } if expectedKeyType != I32 { t.Fatal("Expected map key type ", I32, ", but was ", expectedKeyType) } if expectedValueType != DOUBLE { t.Fatal("Expected map value type ", DOUBLE, ", but was ", expectedValueType) } if expectedSize != len(DOUBLE_VALUES) { t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", expectedSize) } for k, value := range DOUBLE_VALUES { ik, err := p.ReadI32(context.Background()) if err != nil { t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, ik, k, err.Error()) } if int(ik) != k { t.Fatalf("Bad key for %s index %v, wrote: %v, expected: %v", thetype, k, ik, k) } dv, err := p.ReadDouble(context.Background()) if err != nil { t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, dv, value, err.Error()) } s := strconv.FormatFloat(dv, 'g', 10, 64) if math.IsInf(value, 1) { if !math.IsInf(dv, 1) { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_INFINITY)) } } else if math.IsInf(value, 0) { if !math.IsInf(dv, 0) { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) } } else if math.IsNaN(value) { if !math.IsNaN(dv) { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NAN)) } } else { expected := strconv.FormatFloat(value, 'g', 10, 64) if s != expected { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected) } v := float64(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } } } err = p.ReadMapEnd(context.Background()) if err != nil { t.Fatalf("Error while reading map end: %s", err.Error()) } trans.Close() } func TestTJSONProtocolUnmatchedBeginEnd(t *testing.T) { UnmatchedBeginEndProtocolTest(t, NewTJSONProtocolFactory()) } thrift-0.19.0/lib/go/thrift/rich_transport.go0000644000000000000000000000340014303740367021146 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "errors" "io" ) type RichTransport struct { TTransport } // Wraps Transport to provide TRichTransport interface func NewTRichTransport(trans TTransport) *RichTransport { return &RichTransport{trans} } func (r *RichTransport) ReadByte() (c byte, err error) { return readByte(r.TTransport) } func (r *RichTransport) WriteByte(c byte) error { return writeByte(r.TTransport, c) } func (r *RichTransport) WriteString(s string) (n int, err error) { return r.Write([]byte(s)) } func (r *RichTransport) RemainingBytes() (num_bytes uint64) { return r.TTransport.RemainingBytes() } func readByte(r io.Reader) (c byte, err error) { v := [1]byte{0} n, err := r.Read(v[0:1]) if n > 0 && (err == nil || errors.Is(err, io.EOF)) { return v[0], nil } if n > 0 && err != nil { return v[0], err } if err != nil { return 0, err } return v[0], nil } func writeByte(w io.Writer, c byte) error { v := [1]byte{c} _, err := w.Write(v[0:1]) return err } thrift-0.19.0/lib/go/thrift/client.go0000644000000000000000000000555414303740367017377 0ustar00rootroot00000000000000package thrift import ( "context" "fmt" ) // ResponseMeta represents the metadata attached to the response. type ResponseMeta struct { // The headers in the response, if any. // If the underlying transport/protocol is not THeader, this will always be nil. Headers THeaderMap } type TClient interface { Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) } type TStandardClient struct { seqId int32 iprot, oprot TProtocol } // TStandardClient implements TClient, and uses the standard message format for Thrift. // It is not safe for concurrent use. func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClient { return &TStandardClient{ iprot: inputProtocol, oprot: outputProtocol, } } func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error { // Set headers from context object on THeaderProtocol if headerProt, ok := oprot.(*THeaderProtocol); ok { headerProt.ClearWriteHeaders() for _, key := range GetWriteHeaderList(ctx) { if value, ok := GetHeader(ctx, key); ok { headerProt.SetWriteHeader(key, value) } } } if err := oprot.WriteMessageBegin(ctx, method, CALL, seqId); err != nil { return err } if err := args.Write(ctx, oprot); err != nil { return err } if err := oprot.WriteMessageEnd(ctx); err != nil { return err } return oprot.Flush(ctx) } func (p *TStandardClient) Recv(ctx context.Context, iprot TProtocol, seqId int32, method string, result TStruct) error { rMethod, rTypeId, rSeqId, err := iprot.ReadMessageBegin(ctx) if err != nil { return err } if method != rMethod { return NewTApplicationException(WRONG_METHOD_NAME, fmt.Sprintf("%s: wrong method name", method)) } else if seqId != rSeqId { return NewTApplicationException(BAD_SEQUENCE_ID, fmt.Sprintf("%s: out of order sequence response", method)) } else if rTypeId == EXCEPTION { var exception tApplicationException if err := exception.Read(ctx, iprot); err != nil { return err } if err := iprot.ReadMessageEnd(ctx); err != nil { return err } return &exception } else if rTypeId != REPLY { return NewTApplicationException(INVALID_MESSAGE_TYPE_EXCEPTION, fmt.Sprintf("%s: invalid message type", method)) } if err := result.Read(ctx, iprot); err != nil { return err } return iprot.ReadMessageEnd(ctx) } func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { p.seqId++ seqId := p.seqId if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil { return ResponseMeta{}, err } // method is oneway if result == nil { return ResponseMeta{}, nil } err := p.Recv(ctx, p.iprot, seqId, method, result) var headers THeaderMap if hp, ok := p.iprot.(*THeaderProtocol); ok { headers = hp.transport.readHeaders } return ResponseMeta{ Headers: headers, }, err } thrift-0.19.0/lib/go/thrift/logger.go0000644000000000000000000000374614303740367017401 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "log" "os" "testing" ) // Logger is a simple wrapper of a logging function. // // In reality the users might actually use different logging libraries, and they // are not always compatible with each other. // // Logger is meant to be a simple common ground that it's easy to wrap whatever // logging library they use into. // // See https://issues.apache.org/jira/browse/THRIFT-4985 for the design // discussion behind it. type Logger func(msg string) // NopLogger is a Logger implementation that does nothing. func NopLogger(msg string) {} // StdLogger wraps stdlib log package into a Logger. // // If logger passed in is nil, it will fallback to use stderr and default flags. func StdLogger(logger *log.Logger) Logger { if logger == nil { logger = log.New(os.Stderr, "", log.LstdFlags) } return func(msg string) { logger.Print(msg) } } // TestLogger is a Logger implementation can be used in test codes. // // It fails the test when being called. func TestLogger(tb testing.TB) Logger { return func(msg string) { tb.Errorf("logger called with msg: %q", msg) } } func fallbackLogger(logger Logger) Logger { if logger == nil { return StdLogger(nil) } return logger } thrift-0.19.0/lib/go/thrift/simple_json_protocol_test.go0000644000000000000000000006335214303740367023423 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package thrift import ( "context" "encoding/base64" "encoding/json" "fmt" "math" "strconv" "strings" "testing" ) func TestWriteSimpleJSONProtocolBool(t *testing.T) { thetype := "boolean" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range BOOL_VALUES { if e := p.WriteBool(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := false if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolBool(t *testing.T) { thetype := "boolean" for _, value := range BOOL_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) if value { trans.Write(JSON_TRUE) } else { trans.Write(JSON_FALSE) } trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBool(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteSimpleJSONProtocolByte(t *testing.T) { thetype := "byte" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range BYTE_VALUES { if e := p.WriteByte(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int8(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolByte(t *testing.T) { thetype := "byte" for _, value := range BYTE_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadByte(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteSimpleJSONProtocolI16(t *testing.T) { thetype := "int16" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range INT16_VALUES { if e := p.WriteI16(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int16(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolI16(t *testing.T) { thetype := "int16" for _, value := range INT16_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI16(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestWriteSimpleJSONProtocolI32(t *testing.T) { thetype := "int32" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range INT32_VALUES { if e := p.WriteI32(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int32(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolI32(t *testing.T) { thetype := "int32" for _, value := range INT32_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.Itoa(int(value))) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI32(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestReadSimpleJSONProtocolI32Null(t *testing.T) { thetype := "int32" value := "null" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI32(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != 0 { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } trans.Reset() trans.Close() } func TestWriteSimpleJSONProtocolI64(t *testing.T) { thetype := "int64" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range INT64_VALUES { if e := p.WriteI64(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := int64(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolI64(t *testing.T) { thetype := "int64" for _, value := range INT64_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(strconv.FormatInt(value, 10)) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI64(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } trans.Reset() trans.Close() } } func TestReadSimpleJSONProtocolI64Null(t *testing.T) { thetype := "int32" value := "null" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadI64(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != 0 { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } trans.Reset() trans.Close() } func TestWriteSimpleJSONProtocolDouble(t *testing.T) { thetype := "double" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range DOUBLE_VALUES { if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if math.IsInf(value, 1) { if s != jsonQuote(JSON_INFINITY) { t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_INFINITY)) } } else if math.IsInf(value, -1) { if s != jsonQuote(JSON_NEGATIVE_INFINITY) { t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) } } else if math.IsNaN(value) { if s != jsonQuote(JSON_NAN) { t.Fatalf("Bad value for %s %v, wrote: %v, expected: %v", thetype, value, s, jsonQuote(JSON_NAN)) } } else { if s != fmt.Sprint(value) { t.Fatalf("Bad value for %s %v: %s", thetype, value, s) } v := float64(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolDouble(t *testing.T) { thetype := "double" for _, value := range DOUBLE_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) n := NewNumericFromDouble(value) trans.WriteString(n.String()) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadDouble(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if math.IsInf(value, 1) { if !math.IsInf(v, 1) { t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) } } else if math.IsInf(value, -1) { if !math.IsInf(v, -1) { t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) } } else if math.IsNaN(value) { if !math.IsNaN(v) { t.Fatalf("Bad value for %s %v, wrote: %v, received: %v", thetype, value, s, v) } } else { if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } } trans.Reset() trans.Close() } } func TestWriteSimpleJSONProtocolString(t *testing.T) { thetype := "string" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) for _, value := range STRING_VALUES { if e := p.WriteString(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s[0] != '"' || s[len(s)-1] != '"' { t.Fatalf("Bad value for %s '%v', wrote '%v', expected: %v", thetype, value, s, fmt.Sprint("\"", value, "\"")) } v := new(string) if err := json.Unmarshal([]byte(s), v); err != nil || *v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v) } trans.Reset() } trans.Close() } func TestReadSimpleJSONProtocolString(t *testing.T) { thetype := "string" for _, value := range STRING_VALUES { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(jsonQuote(value)) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadString(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != value { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } v1 := new(string) if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) } trans.Reset() trans.Close() } } func TestReadSimpleJSONProtocolStringNull(t *testing.T) { thetype := "string" value := "null" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadString(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != "" { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } trans.Reset() trans.Close() } func TestWriteSimpleJSONProtocolBinary(t *testing.T) { thetype := "binary" value := protocol_bdata b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) base64.StdEncoding.Encode(b64value, value) b64String := string(b64value) trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) if e := p.WriteBinary(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s value %v due to error flushing: %s", thetype, value, e.Error()) } s := trans.String() if s != fmt.Sprint("\"", b64String, "\"") { t.Fatalf("Bad value for %s %v\n wrote: %v\nexpected: %v", thetype, value, s, "\""+b64String+"\"") } v1 := new(string) if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) } trans.Close() } func TestReadSimpleJSONProtocolBinary(t *testing.T) { thetype := "binary" value := protocol_bdata b64value := make([]byte, base64.StdEncoding.EncodedLen(len(protocol_bdata))) base64.StdEncoding.Encode(b64value, value) b64String := string(b64value) trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(jsonQuote(b64String)) trans.Flush(context.Background()) s := trans.String() v, e := p.ReadBinary(context.Background()) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if len(v) != len(value) { t.Fatalf("Bad value for %s value length %v, wrote: %v, received length: %v", thetype, len(value), s, len(v)) } for i := 0; i < len(v); i++ { if v[i] != value[i] { t.Fatalf("Bad value for %s at index %d value %v, wrote: %v, received: %v", thetype, i, value[i], s, v[i]) } } v1 := new(string) if err := json.Unmarshal([]byte(s), v1); err != nil || *v1 != b64String { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, *v1) } trans.Reset() trans.Close() } func TestReadSimpleJSONProtocolBinaryNull(t *testing.T) { thetype := "binary" value := "null" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.WriteString(value) trans.Flush(context.Background()) s := trans.String() b, e := p.ReadBinary(context.Background()) v := string(b) if e != nil { t.Fatalf("Unable to read %s value %v due to error: %s", thetype, value, e.Error()) } if v != "" { t.Fatalf("Bad value for %s value %v, wrote: %v, received: %v", thetype, value, s, v) } trans.Reset() trans.Close() } func TestWriteSimpleJSONProtocolList(t *testing.T) { thetype := "list" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) p.WriteListBegin(context.Background(), TType(DOUBLE), len(DOUBLE_VALUES)) for _, value := range DOUBLE_VALUES { if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } } p.WriteListEnd(context.Background()) if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() str1 := new([]interface{}) err := json.Unmarshal([]byte(str), str1) if err != nil { t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) } l := *str1 if len(l) < 2 { t.Fatalf("List must be at least of length two to include metadata") } if int(l[0].(float64)) != DOUBLE { t.Fatal("Invalid type for list, expected: ", DOUBLE, ", but was: ", l[0]) } if int(l[1].(float64)) != len(DOUBLE_VALUES) { t.Fatal("Invalid length for list, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) } for k, value := range DOUBLE_VALUES { s := l[k+2] if math.IsInf(value, 1) { if s.(string) != JSON_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) } } else if math.IsInf(value, 0) { if s.(string) != JSON_NEGATIVE_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) } } else if math.IsNaN(value) { if s.(string) != JSON_NAN { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) } } else { if s.(float64) != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) } } trans.Reset() } trans.Close() } func TestWriteSimpleJSONProtocolSet(t *testing.T) { thetype := "set" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) p.WriteSetBegin(context.Background(), TType(DOUBLE), len(DOUBLE_VALUES)) for _, value := range DOUBLE_VALUES { if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value %v due to error: %s", thetype, value, e.Error()) } } p.WriteSetEnd(context.Background()) if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() str1 := new([]interface{}) err := json.Unmarshal([]byte(str), str1) if err != nil { t.Fatalf("Unable to decode %s, wrote: %s", thetype, str) } l := *str1 if len(l) < 2 { t.Fatalf("Set must be at least of length two to include metadata") } if int(l[0].(float64)) != DOUBLE { t.Fatal("Invalid type for set, expected: ", DOUBLE, ", but was: ", l[0]) } if int(l[1].(float64)) != len(DOUBLE_VALUES) { t.Fatal("Invalid length for set, expected: ", len(DOUBLE_VALUES), ", but was: ", l[1]) } for k, value := range DOUBLE_VALUES { s := l[k+2] if math.IsInf(value, 1) { if s.(string) != JSON_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_INFINITY), str) } } else if math.IsInf(value, 0) { if s.(string) != JSON_NEGATIVE_INFINITY { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY), str) } } else if math.IsNaN(value) { if s.(string) != JSON_NAN { t.Fatalf("Bad value for %s at index %v %v, wrote: %q, expected: %q, originally wrote: %q", thetype, k, value, s, jsonQuote(JSON_NAN), str) } } else { if s.(float64) != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s'", thetype, value, s) } } trans.Reset() } trans.Close() } func TestWriteSimpleJSONProtocolMap(t *testing.T) { thetype := "map" trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) p.WriteMapBegin(context.Background(), TType(I32), TType(DOUBLE), len(DOUBLE_VALUES)) for k, value := range DOUBLE_VALUES { if e := p.WriteI32(context.Background(), int32(k)); e != nil { t.Fatalf("Unable to write %s key int32 value %v due to error: %s", thetype, k, e.Error()) } if e := p.WriteDouble(context.Background(), value); e != nil { t.Fatalf("Unable to write %s value float64 value %v due to error: %s", thetype, value, e.Error()) } } p.WriteMapEnd(context.Background()) if e := p.Flush(context.Background()); e != nil { t.Fatalf("Unable to write %s due to error flushing: %s", thetype, e.Error()) } str := trans.String() if str[0] != '[' || str[len(str)-1] != ']' { t.Fatalf("Bad value for %s, wrote: %v, in go: %v", thetype, str, DOUBLE_VALUES) } l := strings.Split(str[1:len(str)-1], ",") if len(l) < 3 { t.Fatal("Expected list of at least length 3 for map for metadata, but was of length ", len(l)) } expectedKeyType, _ := strconv.Atoi(l[0]) expectedValueType, _ := strconv.Atoi(l[1]) expectedSize, _ := strconv.Atoi(l[2]) if expectedKeyType != I32 { t.Fatal("Expected map key type ", I32, ", but was ", l[0]) } if expectedValueType != DOUBLE { t.Fatal("Expected map value type ", DOUBLE, ", but was ", l[1]) } if expectedSize != len(DOUBLE_VALUES) { t.Fatal("Expected map size of ", len(DOUBLE_VALUES), ", but was ", l[2]) } for k, value := range DOUBLE_VALUES { strk := l[k*2+3] strv := l[k*2+4] ik, err := strconv.Atoi(strk) if err != nil { t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v, error: %s", thetype, k, strk, k, err.Error()) } if ik != k { t.Fatalf("Bad value for %s index %v, wrote: %v, expected: %v", thetype, k, strk, k) } s := strv if math.IsInf(value, 1) { if s != jsonQuote(JSON_INFINITY) { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_INFINITY)) } } else if math.IsInf(value, 0) { if s != jsonQuote(JSON_NEGATIVE_INFINITY) { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NEGATIVE_INFINITY)) } } else if math.IsNaN(value) { if s != jsonQuote(JSON_NAN) { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected: %v", thetype, k, value, s, jsonQuote(JSON_NAN)) } } else { expected := strconv.FormatFloat(value, 'g', 10, 64) if s != expected { t.Fatalf("Bad value for %s at index %v %v, wrote: %v, expected %v", thetype, k, value, s, expected) } v := float64(0) if err := json.Unmarshal([]byte(s), &v); err != nil || v != value { t.Fatalf("Bad json-decoded value for %s %v, wrote: '%s', expected: '%v'", thetype, value, s, v) } } trans.Reset() } trans.Close() } func TestWriteSimpleJSONProtocolSafePeek(t *testing.T) { trans := NewTMemoryBuffer() p := NewTSimpleJSONProtocol(trans) trans.Write([]byte{'a', 'b'}) trans.Flush(context.Background()) test1 := p.safePeekContains([]byte{'a', 'b'}) if !test1 { t.Fatalf("Should match at test 1") } test2 := p.safePeekContains([]byte{'a', 'b', 'c', 'd'}) if test2 { t.Fatalf("Should not match at test 2") } test3 := p.safePeekContains([]byte{'x', 'y'}) if test3 { t.Fatalf("Should not match at test 3") } } func TestJSONContextStack(t *testing.T) { var stack jsonContextStack t.Run("empty-peek", func(t *testing.T) { v, ok := stack.peek() if ok { t.Error("peek() on empty should return ok: false") } expected := _CONTEXT_INVALID if v != expected { t.Errorf("Expected value from peek() to be %v(%d), got %v(%d)", expected, expected, v, v) } }) t.Run("empty-pop", func(t *testing.T) { v, ok := stack.pop() if ok { t.Error("pop() on empty should return ok: false") } expected := _CONTEXT_INVALID if v != expected { t.Errorf("Expected value from pop() to be %v(%d), got %v(%d)", expected, expected, v, v) } }) t.Run("push-peek-pop", func(t *testing.T) { expected := _CONTEXT_INVALID stack.push(expected) if len(stack) != 1 { t.Errorf("Expected stack to be as size 1 after push, got %#v", stack) } v, ok := stack.peek() if !ok { t.Error("peek() on non-empty should return ok: true") } if v != expected { t.Errorf("Expected value from peek() to be %v(%d), got %v(%d)", expected, expected, v, v) } if len(stack) != 1 { t.Errorf("Expected peek() to be read-only, got %#v", stack) } v, ok = stack.pop() if !ok { t.Error("pop() on non-empty should return ok: true") } if v != expected { t.Errorf("Expected value from pop() to be %v(%d), got %v(%d)", expected, expected, v, v) } if len(stack) != 0 { t.Errorf("Expected pop() to empty the stack, got %#v", stack) } }) } func TestTSimpleJSONProtocolUnmatchedBeginEnd(t *testing.T) { UnmatchedBeginEndProtocolTest(t, NewTSimpleJSONProtocolFactory()) } thrift-0.19.0/lib/go/Makefile.am0000644000000000000000000000320714370300523016305 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . if WITH_TESTS SUBDIRS += test test/fuzz endif if GOVERSION_GE_118 GOBUILDEXTRA = -buildvcs=false else GOBUILDEXTRA = endif install: @echo '##############################################################' @echo '##############################################################' @echo 'The Go client library should be installed via "go get", please see /lib/go/README.md' @echo '##############################################################' @echo '##############################################################' # NOTE: We have to disable stdmethods in go vet until # https://github.com/golang/go/issues/52445 is fixed. check-local: $(GO) vet -stdmethods=false github.com/apache/thrift/lib/go/thrift $(GO) test -race ./thrift clean-local: $(RM) -rf pkg all-local: $(GO) build $(GOBUILDEXTRA) ./thrift EXTRA_DIST = \ thrift \ coding_standards.md \ README.md thrift-0.19.0/lib/go/README.md0000644000000000000000000001401014472647462015545 0ustar00rootroot00000000000000Thrift Go Software Library License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Suppored Go releases ==================== Following the [official Go release policy](https://golang.org/doc/devel/release#policy), we support the latest two Go releases at the time of the Thrift release. For example, at the time of Thrift v0.14.0 release, the latest two Go releases are go1.15 and go1.14, and those are the two Go releases supported by Thrift v0.14.* (including v0.14.1 and v0.14.2 patch releases). Because of Go's backward compatibility guarantee, older Thrift libraries usually works with newer Go releases (e.g. Thrift v0.14.* works with go1.16, although it's not officially supported), but newer Thrift releases might use new APIs introduced in Go releases and no longer work with older Go releases. For example, Thrift v0.14.0 used APIs introduced in go1.13, and as a result no longer works on go1.12. Using Thrift with Go ==================== Thrift supports the currently officially supported Go releases (the latest 2). After initializing the go modules file in your project, use the following command to add the most recent version of the package: $ go get github.com/apache/thrift A note about optional fields ============================ The thrift-to-Go compiler tries to represent thrift IDL structs as Go structs. We must be able to distinguish between optional fields that are set to their default value and optional values which are actually unset, so the generated code represents optional fields via pointers. This is generally intuitive and works well much of the time, but Go does not have a syntax for creating a pointer to a constant in a single expression. That is, given a struct like struct SomeIDLType { OptionalField *int32 } , the following will not compile: x := &SomeIDLType{ OptionalField: &(3), } (Nor is there any other syntax that's built in to the language) As such, we provide some helpers that do just this under lib/go/thrift/. E.g., x := &SomeIDLType{ OptionalField: thrift.Int32Ptr(3), } And so on. The code generator also creates analogous helpers for user-defined typedefs and enums. Adding custom tags to generated Thrift structs ============================================== You can add tags to the auto-generated thrift structs using the following format: struct foo { 1: required string Bar (go.tag = "some_tag:\"some_tag_value\"") } which will generate: type Foo struct { Bar string `thrift:"bar,1,required" some_tag:"some_tag_value"` } A note about server handler implementations =========================================== The context object passed into the server handler function will be canceled when the client closes the connection (this is a best effort check, not a guarantee -- there's no guarantee that the context object is always canceled when client closes the connection, but when it's canceled you can always assume the client closed the connection). The cause of the cancellation (via `context.Cause(ctx)`) would also be set to `thrift.ErrAbandonRequest`. When implementing Go Thrift server, you can take advantage of that to abandon requests that's no longer needed by returning `thrift.ErrAbandonRequest`: func MyEndpoint(ctx context.Context, req *thriftRequestType) (*thriftResponseType, error) { ... if ctx.Err() == context.Canceled { return nil, thrift.ErrAbandonRequest // Or just return ctx.Err(), compiler generated processor code will // handle it for you automatically: // return nil, ctx.Err() } ... } This feature would add roughly 1 millisecond of latency overhead to the server handlers (along with roughly 2 goroutines per request). If that is unacceptable, it can be disabled by having this line early in your main function: thrift.ServerConnectivityCheckInterval = 0 Please be advised that due to a [Go runtime bug](https://github.com/golang/go/issues/27707), currently if this interval is set to a value too low (for example, 1ms), it might cause excessive cpu overhead. This feature is also only enabled on non-oneway endpoints. A note about server stop implementations ======================================== [TSimpleServer.Stop](https://pkg.go.dev/github.com/apache/thrift/lib/go/thrift#TSimpleServer.Stop) will wait for all client connections to be closed after the last received request to be handled, as the time spent by Stop may sometimes be too long: * When socket timeout is not set, server might be hanged before all active clients to finish handling the last received request. * When the socket timeout is too long (e.g one hour), server will hang for that duration before all active clients to finish handling the last received request. To prevent Stop from hanging for too long, you can set thrift.ServerStopTimeout in your main or init function: thrift.ServerStopTimeout = If it's set to <=0, the feature will be disabled (by default), and server will wait for all the client connections to be closed gracefully with zero err time. Otherwise, the stop will wait for all the client connections to be closed gracefully util thrift.ServerStopTimeout is reached, and client connections that are not closed after thrift.ServerStopTimeout will be closed abruptly which may cause some client errors. thrift-0.19.0/lib/go/coding_standards.md0000644000000000000000000000010314303740367020103 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/go/test/0000755000000000000000000000000014472652664015251 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/test/IgnoreInitialismsTest.thrift0000644000000000000000000000161614303740367022757 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct IgnoreInitialismsTest { 1: i64 id, 2: i64 my_id, 3: i64 num_cpu, 4: i64 num_gpu, 5: i64 my_ID, } thrift-0.19.0/lib/go/test/tests/0000777000000000000000000000000014472647462016417 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/test/tests/binary_key_test.go0000644000000000000000000000213014303740367022120 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "testing" "github.com/apache/thrift/lib/go/test/gopath/src/binarykeytest" ) func TestBinaryMapKeyGeneratesString(t *testing.T) { s := binarykeytest.NewTestStruct() //This will only compile if BinToString has type of map[string]string s.BinToString = make(map[string]string) } thrift-0.19.0/lib/go/test/tests/validate_test.go0000644000000000000000000004005114370300523021547 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "encoding/json" "errors" "strconv" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/validatetest" thrift "github.com/apache/thrift/lib/go/thrift" ) func TestBasicValidator(t *testing.T) { bt := validatetest.NewBasicTest() if err := bt.Validate(); err != nil { t.Error(err) } var ve *thrift.ValidationError bt = validatetest.NewBasicTest() bt.Bool1 = thrift.BoolPtr(false) if err := bt.Validate(); err == nil { t.Error("Expected vt.const error for Bool1") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "Bool1" { t.Errorf("Expected error for Bool1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() bt.Byte1 = thrift.Int8Ptr(3) if err := bt.Validate(); err == nil { t.Errorf("Expected vt.lt error for Byte1") } else if errors.As(err, &ve) { if ve.Check() != "vt.lt" { t.Errorf("Expected vt.lt check error, but got %v", ve.Check()) } if ve.Field() != "Byte1" { t.Errorf("Expected error for Byte1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() bt.Double1 = thrift.Float64Ptr(3.0) if err := bt.Validate(); err == nil { t.Errorf("Expected vt.lt error for Double1") } else if errors.As(err, &ve) { if ve.Check() != "vt.lt" { t.Errorf("Expected vt.lt check error, but got %v", ve.Check()) } if ve.Field() != "Double1" { t.Errorf("Expected error for Double1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() bt.String1 = thrift.StringPtr("other string") if err := bt.Validate(); err == nil { t.Errorf("Expected vt.const error for String1") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "String1" { t.Errorf("Expected error for String1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() bt.Binary1 = []byte("other binary") if err := bt.Validate(); err == nil { t.Errorf("Expected vt.const error for Binary1") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "Binary1" { t.Errorf("Expected error for Binary1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() bt.Map1 = make(map[string]string) for i := 0; i < 11; i++ { bt.Map1[strconv.Itoa(i)] = strconv.Itoa(i) } if err := bt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Map1") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Map1" { t.Errorf("Expected error for Map1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt.Map1 = map[string]string{"012345678910": "0"} if err := bt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Map1") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Map1" { t.Errorf("Expected error for Map1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt.Map1 = map[string]string{"0": "012345678910"} if err := bt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Map1") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Map1" { t.Errorf("Expected error for Map1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() for i := 0; i < 11; i++ { bt.Set1 = append(bt.Set1, "0") } if err := bt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Set1") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Set1" { t.Errorf("Expected error for Set1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt.Set1 = []string{"0"} if err := bt.Validate(); err == nil { t.Errorf("Expected vt.min_size error for Set1") } else if errors.As(err, &ve) { if ve.Check() != "vt.min_size" { t.Errorf("Expected vt.min_size check error, but got %v", ve.Check()) } if ve.Field() != "Set1" { t.Errorf("Expected error for Set1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } bt = validatetest.NewBasicTest() bt.Enum1 = (*validatetest.EnumFoo)(thrift.Int64Ptr(int64(validatetest.EnumFoo_e2))) if err := bt.Validate(); err == nil { t.Errorf("Expected vt.in error for Enum1") } else if errors.As(err, &ve) { if ve.Check() != "vt.in" { t.Errorf("Expected vt.in check error, but got %v", ve.Check()) } if ve.Field() != "Enum1" { t.Errorf("Expected error for Enum1, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } } func TestFieldReference(t *testing.T) { frt := validatetest.NewFieldReferenceTest() if err := frt.Validate(); err != nil { t.Error(err) } var ve *thrift.ValidationError frt = validatetest.NewFieldReferenceTest() frt.Bool2 = true if err := frt.Validate(); err == nil { t.Errorf("Expected vt.const error for Bool0") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "Bool0" { t.Errorf("Expected error for Bool0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.Byte4 = 9 if err := frt.Validate(); err == nil { t.Errorf("Expected vt.lt error for Byte0") } else if errors.As(err, &ve) { if ve.Check() != "vt.lt" { t.Errorf("Expected vt.lt check error, but got %v", ve.Check()) } if ve.Field() != "Byte0" { t.Errorf("Expected error for Byte0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.Double4 = 9 if err := frt.Validate(); err == nil { t.Errorf("Expected vt.lt error for Double0") } else if errors.As(err, &ve) { if ve.Check() != "vt.lt" { t.Errorf("Expected vt.lt check error, but got %v", ve.Check()) } if ve.Field() != "Double0" { t.Errorf("Expected error for Double0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.String2 = "other string" if err := frt.Validate(); err == nil { t.Errorf("Expected vt.const error for String0") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "String0" { t.Errorf("Expected error for String0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.Binary2 = []byte("other string") if err := frt.Validate(); err == nil { t.Errorf("Expected vt.const error for Binary0") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "Binary0" { t.Errorf("Expected error for Binary0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.MaxSize = 8 frt.Map0 = make(map[string]string) for i := 0; i < 9; i++ { frt.Map0[strconv.Itoa(i)] = strconv.Itoa(i) } if err := frt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Map0") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Map0" { t.Errorf("Expected error for Map0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.MaxSize = 8 for i := 0; i < 9; i++ { frt.List0 = append(frt.List0, "0") } if err := frt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for List0") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "List0" { t.Errorf("Expected error for List0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } frt = validatetest.NewFieldReferenceTest() frt.MaxSize = 8 for i := 0; i < 9; i++ { frt.Set0 = append(frt.Set0, "0") } if err := frt.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Set0") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Set0" { t.Errorf("Expected error for Set0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } } func TestValidationFunction(t *testing.T) { vft := validatetest.NewValidationFunctionTest() if err := vft.Validate(); err != nil { t.Error(err) } var ve *thrift.ValidationError vft = validatetest.NewValidationFunctionTest() vft.StringFoo = "some string" if err := vft.Validate(); err == nil { t.Errorf("Expected vt.in error for StringLength") } else if errors.As(err, &ve) { if ve.Check() != "vt.in" { t.Errorf("Expected vt.in check error, but got %v", ve.Check()) } if ve.Field() != "StringLength" { t.Errorf("Expected error for StringLength, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } } func TestAnnotationCompatibleTest(t *testing.T) { act := validatetest.NewAnnotationCompatibleTest() if err := act.Validate(); err != nil { t.Error(err) } var ve *thrift.ValidationError act = validatetest.NewAnnotationCompatibleTest() act.Bool0 = false if err := act.Validate(); err == nil { t.Errorf("Expected vt.const error for Bool0") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "Bool0" { t.Errorf("Expected error for Bool0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.Byte0 = 3 if err := act.Validate(); err == nil { t.Errorf("Expected vt.lt error for Byte0") } else if errors.As(err, &ve) { if ve.Check() != "vt.lt" { t.Errorf("Expected vt.lt check error, but got %v", ve.Check()) } if ve.Field() != "Byte0" { t.Errorf("Expected error for Byte0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.Double0 = 3 if err := act.Validate(); err == nil { t.Errorf("Expected vt.lt error for Double0") } else if errors.As(err, &ve) { if ve.Check() != "vt.lt" { t.Errorf("Expected vt.lt check error, but got %v", ve.Check()) } if ve.Field() != "Double0" { t.Errorf("Expected error for Double0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.String0 = "other string" if err := act.Validate(); err == nil { t.Errorf("Expected vt.const error for String0") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "String0" { t.Errorf("Expected error for String0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.Binary0 = []byte("other string") if err := act.Validate(); err == nil { t.Errorf("Expected vt.const error for Binary0") } else if errors.As(err, &ve) { if ve.Check() != "vt.const" { t.Errorf("Expected vt.const check error, but got %v", ve.Check()) } if ve.Field() != "Binary0" { t.Errorf("Expected error for Binary0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.Map0 = map[string]string{"0": "0", "1": "1", "2": "2"} if err := act.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Map0") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Map0" { t.Errorf("Expected error for Map0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.Set0 = []string{"0", "1", "2"} if err := act.Validate(); err == nil { t.Errorf("Expected vt.max_size error for Set0") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "Set0" { t.Errorf("Expected error for Set0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.List0 = []string{"0", "1", "2"} if err := act.Validate(); err == nil { t.Errorf("Expected vt.max_size error for List0") } else if errors.As(err, &ve) { if ve.Check() != "vt.max_size" { t.Errorf("Expected vt.max_size check error, but got %v", ve.Check()) } if ve.Field() != "List0" { t.Errorf("Expected error for List0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } act = validatetest.NewAnnotationCompatibleTest() act.Enum0 = validatetest.EnumFoo_e1 if err := act.Validate(); err == nil { t.Errorf("Expected vt.in error for Enum0") } else if errors.As(err, &ve) { if ve.Check() != "vt.in" { t.Errorf("Expected vt.in check error, but got %v", ve.Check()) } if ve.Field() != "Enum0" { t.Errorf("Expected error for Enum0, but got %v", ve.Field()) } } else { t.Errorf("Error cannot be unwrapped into *ValidationError: %v", err) } fields := []string{"bool1", "byte1", "double1", "string1", "binary1", "enum1", "struct1", "list1", "set1", "map1"} b, err := json.Marshal(act) if err != nil { t.Error(err) } jsonMap := make(map[string]interface{}) if err = json.Unmarshal(b, &jsonMap); err != nil { t.Error(err) } for _, field := range fields { if _, ok := jsonMap[field]; !ok { t.Errorf("Expected field %s in JSON, but not found", field) } } } thrift-0.19.0/lib/go/test/tests/gotag_test.go0000644000000000000000000000413114303740367021070 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "reflect" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/gotagtest" ) func TestDefaultTag(t *testing.T) { s := gotagtest.Tagged{} st := reflect.TypeOf(s) field, ok := st.FieldByName("StringThing") if !ok || field.Tag.Get("json") != "string_thing" { t.Error("Unexpected default tag value") } } func TestCustomTag(t *testing.T) { s := gotagtest.Tagged{} st := reflect.TypeOf(s) field, ok := st.FieldByName("IntThing") if !ok { t.Error("Missing field IntThing") return } if v := field.Tag.Get("json"); v != "custom_thing" { t.Errorf("Expected custom_thing for tag json, got %s", v) } if v := field.Tag.Get("mykey"); v != "myvalue" { t.Errorf("Expected myvalue for tag mykey, got %s", v) } } func TestOptionalTag(t *testing.T) { s := gotagtest.Tagged{} st := reflect.TypeOf(s) field, ok := st.FieldByName("OptionalIntThing") if !ok || field.Tag.Get("json") != "optional_int_thing,omitempty" { t.Error("Unexpected default tag value for optional field") } } func TestOptionalTagWithDefaultValue(t *testing.T) { s := gotagtest.Tagged{} st := reflect.TypeOf(s) field, ok := st.FieldByName("OptionalBoolThing") if !ok || field.Tag.Get("json") != "optional_bool_thing" { t.Error("Unexpected default tag value for optional field that has a default value") } } thrift-0.19.0/lib/go/test/tests/const_optional_field_test.go0000644000000000000000000001136014303740367024167 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "testing" "github.com/apache/thrift/lib/go/test/gopath/src/constoptionalfielda" "github.com/apache/thrift/lib/go/test/gopath/src/constoptionalfieldb" ) func TestConstOptionalField(t *testing.T) { c := constoptionalfieldb.CONSTANTS[0] t.Run("foo", func(t *testing.T) { const expected = constoptionalfielda.Foo_One if *c.OptFoo != expected { t.Errorf("Expected %v, got %v", expected, *c.OptFoo) } if *c.AFoo != constoptionalfielda.TypedefAFoo(expected) { t.Errorf("Typedef a expected %v, got %v", expected, *c.AFoo) } if *c.BFoo != constoptionalfieldb.TypedefBFoo(expected) { t.Errorf("Typedef b expected %v, got %v", expected, *c.BFoo) } }) t.Run("bool", func(t *testing.T) { const expected = true if *c.OptBool != expected { t.Errorf("Expected %v, got %v", expected, *c.OptBool) } if *c.ABool != constoptionalfielda.TypedefABool(expected) { t.Errorf("Typedef a expected %v, got %v", expected, *c.ABool) } if *c.BBool != constoptionalfieldb.TypedefBBool(expected) { t.Errorf("Typedef b expected %v, got %v", expected, *c.BBool) } }) t.Run("i8", func(t *testing.T) { const expected = 8 if *c.OptI8 != expected { t.Errorf("Expected %v, got %v", expected, *c.OptI8) } if *c.AI8 != constoptionalfielda.TypedefAI8(expected) { t.Errorf("Typedef a expected %v, got %v", expected, *c.AI8) } if *c.BI8 != constoptionalfieldb.TypedefBI8(expected) { t.Errorf("Typedef b expected %v, got %v", expected, *c.BI8) } }) t.Run("i16", func(t *testing.T) { const expected = 16 if *c.OptI16 != expected { t.Errorf("Expected %v, got %v", expected, *c.OptI16) } if *c.AI16 != constoptionalfielda.TypedefAI16(expected) { t.Errorf("Typedef a expected %v, got %v", expected, *c.AI16) } if *c.BI16 != constoptionalfieldb.TypedefBI16(expected) { t.Errorf("Typedef b expected %v, got %v", expected, *c.BI16) } }) t.Run("i32", func(t *testing.T) { const expected = 32 if *c.OptI32 != expected { t.Errorf("Expected %v, got %v", expected, *c.OptI32) } if *c.AI32 != constoptionalfielda.TypedefAI32(expected) { t.Errorf("Typedef a expected %v, got %v", expected, *c.AI32) } if *c.BI32 != constoptionalfieldb.TypedefBI32(expected) { t.Errorf("Typedef b expected %v, got %v", expected, *c.BI32) } }) t.Run("i64", func(t *testing.T) { const expected = 64 if *c.OptI64 != expected { t.Errorf("Expected %v, got %v", expected, *c.OptI64) } if *c.AI64 != constoptionalfielda.TypedefAI64(expected) { t.Errorf("Typedef a expected %v, got %v", expected, *c.AI64) } if *c.BI64 != constoptionalfieldb.TypedefBI64(expected) { t.Errorf("Typedef b expected %v, got %v", expected, *c.BI64) } }) t.Run("double", func(t *testing.T) { // To avoid the annoyance of comparing float numbers, // we convert all floats to int in this test. const expected = 1234 if int(*c.OptDouble) != expected { t.Errorf("Expected %v, got %v", expected, *c.OptDouble) } if int(*c.ADouble) != expected { t.Errorf("Typedef a expected %v, got %v", expected, *c.ADouble) } if int(*c.BDouble) != expected { t.Errorf("Typedef b expected %v, got %v", expected, *c.BDouble) } }) t.Run("string", func(t *testing.T) { const expected = "string" if *c.OptString != expected { t.Errorf("Expected %q, got %q", expected, *c.OptString) } if *c.AString != constoptionalfielda.TypedefAString(expected) { t.Errorf("Typedef a expected %q, got %q", expected, *c.AString) } if *c.BString != constoptionalfieldb.TypedefBString(expected) { t.Errorf("Typedef b expected %q, got %q", expected, *c.BString) } }) t.Run("binary", func(t *testing.T) { const expected = "binary" if string(c.OptBinary) != expected { t.Errorf("Expected %q, got %q", expected, c.OptBinary) } if string(c.ABinary) != expected { t.Errorf("Typedef a expected %q, got %q", expected, c.ABinary) } if string(c.BBinary) != expected { t.Errorf("Typedef b expected %q, got %q", expected, c.BBinary) } }) } thrift-0.19.0/lib/go/test/tests/encoding_json_test.go0000644000000000000000000000432414303740367022612 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "encoding" "encoding/json" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/thrifttest" ) func TestEnumIsTextMarshaller(t *testing.T) { one := thrifttest.Numberz_ONE var tm encoding.TextMarshaler = one b, err := tm.MarshalText() if err != nil { t.Fatalf("Unexpected error from MarshalText: %s", err) } if string(b) != one.String() { t.Errorf("MarshalText(%s) = %s, expected = %s", one, b, one) } } func TestEnumIsTextUnmarshaller(t *testing.T) { var tm encoding.TextUnmarshaler = thrifttest.NumberzPtr(thrifttest.Numberz_TWO) err := tm.UnmarshalText([]byte("TWO")) if err != nil { t.Fatalf("Unexpected error from UnmarshalText(TWO): %s", err) } if *(tm.(*thrifttest.Numberz)) != thrifttest.Numberz_TWO { t.Errorf("UnmarshalText(TWO) = %s", tm) } err = tm.UnmarshalText([]byte("NAN")) if err == nil { t.Errorf("Error from UnmarshalText(NAN)") } } func TestJSONMarshalUnmarshal(t *testing.T) { s1 := thrifttest.StructB{ Aa: &thrifttest.StructA{S: "Aa"}, Ab: &thrifttest.StructA{S: "Ab"}, } b, err := json.Marshal(s1) if err != nil { t.Fatalf("Unexpected error from json.Marshal: %s", err) } s2 := thrifttest.StructB{} err = json.Unmarshal(b, &s2) if err != nil { t.Fatalf("Unexpected error from json.Unmarshal: %s", err) } if *s1.Aa != *s2.Aa || *s1.Ab != *s2.Ab { t.Logf("s1 = %+v", s1) t.Logf("s2 = %+v", s2) t.Errorf("json: Unmarshal(Marshal(s)) != s") } } thrift-0.19.0/lib/go/test/tests/server_connectivity_check_test.go0000644000000000000000000000557714472647462025260 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "runtime/debug" "testing" "time" "github.com/apache/thrift/lib/go/test/gopath/src/clientmiddlewareexceptiontest" "github.com/apache/thrift/lib/go/thrift" ) func TestServerConnectivityCheck(t *testing.T) { const ( // Server will sleep for longer than client is willing to wait // so client will close the connection. serverSleep = 50 * time.Millisecond clientSocketTimeout = time.Millisecond ) serverSocket, err := thrift.NewTServerSocket(":0") if err != nil { t.Fatalf("failed to create server socket: %v", err) } processor := clientmiddlewareexceptiontest.NewClientMiddlewareExceptionTestProcessor(fakeClientMiddlewareExceptionTestHandler( func(ctx context.Context) (*clientmiddlewareexceptiontest.FooResponse, error) { time.Sleep(serverSleep) err := ctx.Err() if err == nil { t.Error("Expected server ctx to be cancelled, did not happen") return new(clientmiddlewareexceptiontest.FooResponse), nil } return nil, err }, )) server := thrift.NewTSimpleServer2(processor, serverSocket) if err := server.Listen(); err != nil { t.Fatalf("failed to listen server: %v", err) } server.SetLogger(func(msg string) { t.Errorf("Server logger called with %q", msg) t.Errorf("Server logger callstack:\n%s", debug.Stack()) }) addr := serverSocket.Addr().String() go server.Serve() t.Cleanup(func() { server.Stop() }) cfg := &thrift.TConfiguration{ SocketTimeout: clientSocketTimeout, } socket := thrift.NewTSocketConf(addr, cfg) if err := socket.Open(); err != nil { t.Fatalf("failed to create client connection: %v", err) } t.Cleanup(func() { socket.Close() }) inProtocol := thrift.NewTBinaryProtocolConf(socket, cfg) outProtocol := thrift.NewTBinaryProtocolConf(socket, cfg) client := thrift.NewTStandardClient(inProtocol, outProtocol) ctx, cancel := context.WithTimeout(context.Background(), clientSocketTimeout) defer cancel() _, err = clientmiddlewareexceptiontest.NewClientMiddlewareExceptionTestClient(client).Foo(ctx) socket.Close() if err == nil { t.Error("Expected client to time out, did not happen") } } thrift-0.19.0/lib/go/test/tests/client_error_test.go0000644000000000000000000007044614303740367022472 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "errors" "testing" "github.com/golang/mock/gomock" "github.com/apache/thrift/lib/go/test/gopath/src/errortest" "github.com/apache/thrift/lib/go/thrift" ) // TestCase: Comprehensive call and reply workflow in the client. // Setup mock to fail at a certain position. Return true if position exists otherwise false. func prepareClientCallReply(protocol *MockTProtocol, failAt int, failWith error) bool { // NOTE: here the number 50 is the same as the last number at the end of // this function. If more function calls are added in the future, this // number needs to be increased accordingly. // // It's needed for go 1.14+. Before go 1.14 we only call gomock // controller's Finish function when this function returns true. // Starting from go 1.14 the gomock will take advantage of // testing.T.Cleanup interface, which means the Finish function will // always be called by t.Cleanup, even if we return false here. // As a result, in the case we need to return false by this function, // we must return before calling any of the // protocol.EXPECT().* functions. const lastFailAt = 50 if failAt > lastFailAt { return false } var err error = nil if failAt == 0 { err = failWith } last := protocol.EXPECT().WriteMessageBegin(context.Background(), "testStruct", thrift.CALL, int32(1)).Return(err) if failAt == 0 { return true } if failAt == 1 { err = failWith } last = protocol.EXPECT().WriteStructBegin(context.Background(), "testStruct_args").Return(err).After(last) if failAt == 1 { return true } if failAt == 2 { err = failWith } last = protocol.EXPECT().WriteFieldBegin(context.Background(), "thing", thrift.TType(thrift.STRUCT), int16(1)).Return(err).After(last) if failAt == 2 { return true } if failAt == 3 { err = failWith } last = protocol.EXPECT().WriteStructBegin(context.Background(), "TestStruct").Return(err).After(last) if failAt == 3 { return true } if failAt == 4 { err = failWith } last = protocol.EXPECT().WriteFieldBegin(context.Background(), "m", thrift.TType(thrift.MAP), int16(1)).Return(err).After(last) if failAt == 4 { return true } if failAt == 5 { err = failWith } last = protocol.EXPECT().WriteMapBegin(context.Background(), thrift.TType(thrift.STRING), thrift.TType(thrift.STRING), 0).Return(err).After(last) if failAt == 5 { return true } if failAt == 6 { err = failWith } last = protocol.EXPECT().WriteMapEnd(context.Background()).Return(err).After(last) if failAt == 6 { return true } if failAt == 7 { err = failWith } last = protocol.EXPECT().WriteFieldEnd(context.Background()).Return(err).After(last) if failAt == 7 { return true } if failAt == 8 { err = failWith } last = protocol.EXPECT().WriteFieldBegin(context.Background(), "l", thrift.TType(thrift.LIST), int16(2)).Return(err).After(last) if failAt == 8 { return true } if failAt == 9 { err = failWith } last = protocol.EXPECT().WriteListBegin(context.Background(), thrift.TType(thrift.STRING), 0).Return(err).After(last) if failAt == 9 { return true } if failAt == 10 { err = failWith } last = protocol.EXPECT().WriteListEnd(context.Background()).Return(err).After(last) if failAt == 10 { return true } if failAt == 11 { err = failWith } last = protocol.EXPECT().WriteFieldEnd(context.Background()).Return(err).After(last) if failAt == 11 { return true } if failAt == 12 { err = failWith } last = protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.SET), int16(3)).Return(err).After(last) if failAt == 12 { return true } if failAt == 13 { err = failWith } last = protocol.EXPECT().WriteSetBegin(context.Background(), thrift.TType(thrift.STRING), 0).Return(err).After(last) if failAt == 13 { return true } if failAt == 14 { err = failWith } last = protocol.EXPECT().WriteSetEnd(context.Background()).Return(err).After(last) if failAt == 14 { return true } if failAt == 15 { err = failWith } last = protocol.EXPECT().WriteFieldEnd(context.Background()).Return(err).After(last) if failAt == 15 { return true } if failAt == 16 { err = failWith } last = protocol.EXPECT().WriteFieldBegin(context.Background(), "i", thrift.TType(thrift.I32), int16(4)).Return(err).After(last) if failAt == 16 { return true } if failAt == 17 { err = failWith } last = protocol.EXPECT().WriteI32(context.Background(), int32(3)).Return(err).After(last) if failAt == 17 { return true } if failAt == 18 { err = failWith } last = protocol.EXPECT().WriteFieldEnd(context.Background()).Return(err).After(last) if failAt == 18 { return true } if failAt == 19 { err = failWith } last = protocol.EXPECT().WriteFieldStop(context.Background()).Return(err).After(last) if failAt == 19 { return true } if failAt == 20 { err = failWith } last = protocol.EXPECT().WriteStructEnd(context.Background()).Return(err).After(last) if failAt == 20 { return true } if failAt == 21 { err = failWith } last = protocol.EXPECT().WriteFieldEnd(context.Background()).Return(err).After(last) if failAt == 21 { return true } if failAt == 22 { err = failWith } last = protocol.EXPECT().WriteFieldStop(context.Background()).Return(err).After(last) if failAt == 22 { return true } if failAt == 23 { err = failWith } last = protocol.EXPECT().WriteStructEnd(context.Background()).Return(err).After(last) if failAt == 23 { return true } if failAt == 24 { err = failWith } last = protocol.EXPECT().WriteMessageEnd(context.Background()).Return(err).After(last) if failAt == 24 { return true } if failAt == 25 { err = failWith } last = protocol.EXPECT().Flush(context.Background()).Return(err).After(last) if failAt == 25 { return true } if failAt == 26 { err = failWith } last = protocol.EXPECT().ReadMessageBegin(context.Background()).Return("testStruct", thrift.REPLY, int32(1), err).After(last) if failAt == 26 { return true } if failAt == 27 { err = failWith } last = protocol.EXPECT().ReadStructBegin(context.Background()).Return("testStruct_args", err).After(last) if failAt == 27 { return true } if failAt == 28 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STRUCT), int16(0), err).After(last) if failAt == 28 { return true } if failAt == 29 { err = failWith } last = protocol.EXPECT().ReadStructBegin(context.Background()).Return("TestStruct", err).After(last) if failAt == 29 { return true } if failAt == 30 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("m", thrift.TType(thrift.MAP), int16(1), err).After(last) if failAt == 30 { return true } if failAt == 31 { err = failWith } last = protocol.EXPECT().ReadMapBegin(context.Background()).Return(thrift.TType(thrift.STRING), thrift.TType(thrift.STRING), 0, err).After(last) if failAt == 31 { return true } if failAt == 32 { err = failWith } last = protocol.EXPECT().ReadMapEnd(context.Background()).Return(err).After(last) if failAt == 32 { return true } if failAt == 33 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 33 { return true } if failAt == 34 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("l", thrift.TType(thrift.LIST), int16(2), err).After(last) if failAt == 34 { return true } if failAt == 35 { err = failWith } last = protocol.EXPECT().ReadListBegin(context.Background()).Return(thrift.TType(thrift.STRING), 0, err).After(last) if failAt == 35 { return true } if failAt == 36 { err = failWith } last = protocol.EXPECT().ReadListEnd(context.Background()).Return(err).After(last) if failAt == 36 { return true } if failAt == 37 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 37 { return true } if failAt == 38 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("s", thrift.TType(thrift.SET), int16(3), err).After(last) if failAt == 38 { return true } if failAt == 39 { err = failWith } last = protocol.EXPECT().ReadSetBegin(context.Background()).Return(thrift.TType(thrift.STRING), 0, err).After(last) if failAt == 39 { return true } if failAt == 40 { err = failWith } last = protocol.EXPECT().ReadSetEnd(context.Background()).Return(err).After(last) if failAt == 40 { return true } if failAt == 41 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 41 { return true } if failAt == 42 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("i", thrift.TType(thrift.I32), int16(4), err).After(last) if failAt == 42 { return true } if failAt == 43 { err = failWith } last = protocol.EXPECT().ReadI32(context.Background()).Return(int32(3), err).After(last) if failAt == 43 { return true } if failAt == 44 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 44 { return true } if failAt == 45 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STOP), int16(5), err).After(last) if failAt == 45 { return true } if failAt == 46 { err = failWith } last = protocol.EXPECT().ReadStructEnd(context.Background()).Return(err).After(last) if failAt == 46 { return true } if failAt == 47 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 47 { return true } if failAt == 48 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STOP), int16(1), err).After(last) if failAt == 48 { return true } if failAt == 49 { err = failWith } last = protocol.EXPECT().ReadStructEnd(context.Background()).Return(err).After(last) if failAt == 49 { return true } if failAt == 50 { err = failWith } //lint:ignore SA4006 to keep it consistent with other checks above last = protocol.EXPECT().ReadMessageEnd(context.Background()).Return(err).After(last) //lint:ignore S1008 to keep it consistent with other checks above if failAt == 50 { return true } return false } // TestCase: Comprehensive call and reply workflow in the client. // Expecting TTransportError on fail. func TestClientReportTTransportErrors(t *testing.T) { mockCtrl := gomock.NewController(t) thing := errortest.NewTestStruct() thing.M = make(map[string]string) thing.L = make([]string, 0) thing.S = make([]string, 0) thing.I = 3 err := thrift.NewTTransportException(thrift.TIMED_OUT, "test") for i := 0; ; i++ { protocol := NewMockTProtocol(mockCtrl) if !prepareClientCallReply(protocol, i, err) { return } client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol)) _, retErr := client.TestStruct(defaultCtx, thing) mockCtrl.Finish() mockCtrl = gomock.NewController(t) err2, ok := retErr.(thrift.TTransportException) if !ok { t.Fatal("Expected a TTrasportException") } if err2.TypeId() != thrift.TIMED_OUT { t.Fatal("Expected TIMED_OUT error") } } } // TestCase: Comprehensive call and reply workflow in the client. // Expecting TTransportError on fail. // Similar to TestClientReportTTransportErrors, but using legacy client constructor. func TestClientReportTTransportErrorsLegacy(t *testing.T) { mockCtrl := gomock.NewController(t) transport := thrift.NewTMemoryBuffer() thing := errortest.NewTestStruct() thing.M = make(map[string]string) thing.L = make([]string, 0) thing.S = make([]string, 0) thing.I = 3 err := thrift.NewTTransportException(thrift.TIMED_OUT, "test") for i := 0; ; i++ { protocol := NewMockTProtocol(mockCtrl) if !prepareClientCallReply(protocol, i, err) { return } client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol) _, retErr := client.TestStruct(defaultCtx, thing) mockCtrl.Finish() mockCtrl = gomock.NewController(t) err2, ok := retErr.(thrift.TTransportException) if !ok { t.Fatal("Expected a TTrasportException") } if err2.TypeId() != thrift.TIMED_OUT { t.Fatal("Expected TIMED_OUT error") } } } // TestCase: Comprehensive call and reply workflow in the client. // Expecting TTProtocolErrors on fail. func TestClientReportTProtocolErrors(t *testing.T) { mockCtrl := gomock.NewController(t) thing := errortest.NewTestStruct() thing.M = make(map[string]string) thing.L = make([]string, 0) thing.S = make([]string, 0) thing.I = 3 err := thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, errors.New("test")) for i := 0; ; i++ { protocol := NewMockTProtocol(mockCtrl) if !prepareClientCallReply(protocol, i, err) { return } client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol)) _, retErr := client.TestStruct(defaultCtx, thing) mockCtrl.Finish() mockCtrl = gomock.NewController(t) err2, ok := retErr.(thrift.TProtocolException) if !ok { t.Fatal("Expected a TProtocolException") } if err2.TypeId() != thrift.INVALID_DATA { t.Fatal("Expected INVALID_DATA error") } } } // TestCase: Comprehensive call and reply workflow in the client. // Expecting TTProtocolErrors on fail. // Similar to TestClientReportTProtocolErrors, but using legacy client constructor. func TestClientReportTProtocolErrorsLegacy(t *testing.T) { mockCtrl := gomock.NewController(t) transport := thrift.NewTMemoryBuffer() thing := errortest.NewTestStruct() thing.M = make(map[string]string) thing.L = make([]string, 0) thing.S = make([]string, 0) thing.I = 3 err := thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, errors.New("test")) for i := 0; ; i++ { protocol := NewMockTProtocol(mockCtrl) if !prepareClientCallReply(protocol, i, err) { return } client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol) _, retErr := client.TestStruct(defaultCtx, thing) mockCtrl.Finish() mockCtrl = gomock.NewController(t) err2, ok := retErr.(thrift.TProtocolException) if !ok { t.Fatal("Expected a TProtocolException") } if err2.TypeId() != thrift.INVALID_DATA { t.Fatal("Expected INVALID_DATA error") } } } // TestCase: call and reply with exception workflow in the client. // Setup mock to fail at a certain position. Return true if position exists otherwise false. func prepareClientCallException(protocol *MockTProtocol, failAt int, failWith error) bool { var err error = nil // No need to test failure in this block, because it is covered in other test cases last := protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)) last = protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args").After(last) last = protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)).After(last) last = protocol.EXPECT().WriteString(context.Background(), "test").After(last) last = protocol.EXPECT().WriteFieldEnd(context.Background()).After(last) last = protocol.EXPECT().WriteFieldStop(context.Background()).After(last) last = protocol.EXPECT().WriteStructEnd(context.Background()).After(last) last = protocol.EXPECT().WriteMessageEnd(context.Background()).After(last) last = protocol.EXPECT().Flush(context.Background()).After(last) // Reading the exception, might fail. if failAt == 0 { err = failWith } last = protocol.EXPECT().ReadMessageBegin(context.Background()).Return("testString", thrift.EXCEPTION, int32(1), err).After(last) if failAt == 0 { return true } if failAt == 1 { err = failWith } last = protocol.EXPECT().ReadStructBegin(context.Background()).Return("TApplicationException", err).After(last) if failAt == 1 { return true } if failAt == 2 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("message", thrift.TType(thrift.STRING), int16(1), err).After(last) if failAt == 2 { return true } if failAt == 3 { err = failWith } last = protocol.EXPECT().ReadString(context.Background()).Return("test", err).After(last) if failAt == 3 { return true } if failAt == 4 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 4 { return true } if failAt == 5 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("type", thrift.TType(thrift.I32), int16(2), err).After(last) if failAt == 5 { return true } if failAt == 6 { err = failWith } last = protocol.EXPECT().ReadI32(context.Background()).Return(int32(thrift.PROTOCOL_ERROR), err).After(last) if failAt == 6 { return true } if failAt == 7 { err = failWith } last = protocol.EXPECT().ReadFieldEnd(context.Background()).Return(err).After(last) if failAt == 7 { return true } if failAt == 8 { err = failWith } last = protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STOP), int16(2), err).After(last) if failAt == 8 { return true } if failAt == 9 { err = failWith } last = protocol.EXPECT().ReadStructEnd(context.Background()).Return(err).After(last) if failAt == 9 { return true } if failAt == 10 { err = failWith } //lint:ignore SA4006 to keep it consistent with other checks above last = protocol.EXPECT().ReadMessageEnd(context.Background()).Return(err).After(last) //lint:ignore S1008 to keep it consistent with other checks above if failAt == 10 { return true } return false } // TestCase: call and reply with exception workflow in the client. func TestClientCallException(t *testing.T) { mockCtrl := gomock.NewController(t) err := thrift.NewTTransportException(thrift.TIMED_OUT, "test") for i := 0; ; i++ { protocol := NewMockTProtocol(mockCtrl) willComplete := !prepareClientCallException(protocol, i, err) client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol)) _, retErr := client.TestString(defaultCtx, "test") mockCtrl.Finish() mockCtrl = gomock.NewController(t) if !willComplete { err2, ok := retErr.(thrift.TTransportException) if !ok { t.Fatal("Expected a TTransportException") } if err2.TypeId() != thrift.TIMED_OUT { t.Fatal("Expected TIMED_OUT error") } } else { err2, ok := retErr.(thrift.TApplicationException) if !ok { t.Fatal("Expected a TApplicationException") } if err2.TypeId() != thrift.PROTOCOL_ERROR { t.Fatal("Expected PROTOCOL_ERROR error") } break } } } // TestCase: call and reply with exception workflow in the client. // Similar to TestClientCallException, but using legacy client constructor. func TestClientCallExceptionLegacy(t *testing.T) { mockCtrl := gomock.NewController(t) transport := thrift.NewTMemoryBuffer() err := thrift.NewTTransportException(thrift.TIMED_OUT, "test") for i := 0; ; i++ { protocol := NewMockTProtocol(mockCtrl) willComplete := !prepareClientCallException(protocol, i, err) client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol) _, retErr := client.TestString(defaultCtx, "test") mockCtrl.Finish() mockCtrl = gomock.NewController(t) if !willComplete { err2, ok := retErr.(thrift.TTransportException) if !ok { t.Fatal("Expected a TTransportException") } if err2.TypeId() != thrift.TIMED_OUT { t.Fatal("Expected TIMED_OUT error") } } else { err2, ok := retErr.(thrift.TApplicationException) if !ok { t.Fatal("Expected a TApplicationException") } if err2.TypeId() != thrift.PROTOCOL_ERROR { t.Fatal("Expected PROTOCOL_ERROR error") } break } } } // TestCase: Mismatching sequence id has been received in the client. func TestClientSeqIdMismatch(t *testing.T) { mockCtrl := gomock.NewController(t) protocol := NewMockTProtocol(mockCtrl) gomock.InOrder( protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)), protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args"), protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)), protocol.EXPECT().WriteString(context.Background(), "test"), protocol.EXPECT().WriteFieldEnd(context.Background()), protocol.EXPECT().WriteFieldStop(context.Background()), protocol.EXPECT().WriteStructEnd(context.Background()), protocol.EXPECT().WriteMessageEnd(context.Background()), protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin(context.Background()).Return("testString", thrift.REPLY, int32(2), nil), ) client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol)) _, err := client.TestString(defaultCtx, "test") mockCtrl.Finish() appErr, ok := err.(thrift.TApplicationException) if !ok { t.Fatal("Expected TApplicationException") } if appErr.TypeId() != thrift.BAD_SEQUENCE_ID { t.Fatal("Expected BAD_SEQUENCE_ID error") } } // TestCase: Mismatching sequence id has been received in the client. // Similar to TestClientSeqIdMismatch, but using legacy client constructor. func TestClientSeqIdMismatchLegeacy(t *testing.T) { mockCtrl := gomock.NewController(t) transport := thrift.NewTMemoryBuffer() protocol := NewMockTProtocol(mockCtrl) gomock.InOrder( protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)), protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args"), protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)), protocol.EXPECT().WriteString(context.Background(), "test"), protocol.EXPECT().WriteFieldEnd(context.Background()), protocol.EXPECT().WriteFieldStop(context.Background()), protocol.EXPECT().WriteStructEnd(context.Background()), protocol.EXPECT().WriteMessageEnd(context.Background()), protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin(context.Background()).Return("testString", thrift.REPLY, int32(2), nil), ) client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol) _, err := client.TestString(defaultCtx, "test") mockCtrl.Finish() appErr, ok := err.(thrift.TApplicationException) if !ok { t.Fatal("Expected TApplicationException") } if appErr.TypeId() != thrift.BAD_SEQUENCE_ID { t.Fatal("Expected BAD_SEQUENCE_ID error") } } // TestCase: Wrong method name has been received in the client. func TestClientWrongMethodName(t *testing.T) { mockCtrl := gomock.NewController(t) protocol := NewMockTProtocol(mockCtrl) gomock.InOrder( protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)), protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args"), protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)), protocol.EXPECT().WriteString(context.Background(), "test"), protocol.EXPECT().WriteFieldEnd(context.Background()), protocol.EXPECT().WriteFieldStop(context.Background()), protocol.EXPECT().WriteStructEnd(context.Background()), protocol.EXPECT().WriteMessageEnd(context.Background()), protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin(context.Background()).Return("unknown", thrift.REPLY, int32(1), nil), ) client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol)) _, err := client.TestString(defaultCtx, "test") mockCtrl.Finish() appErr, ok := err.(thrift.TApplicationException) if !ok { t.Fatal("Expected TApplicationException") } if appErr.TypeId() != thrift.WRONG_METHOD_NAME { t.Fatal("Expected WRONG_METHOD_NAME error") } } // TestCase: Wrong method name has been received in the client. // Similar to TestClientWrongMethodName, but using legacy client constructor. func TestClientWrongMethodNameLegacy(t *testing.T) { mockCtrl := gomock.NewController(t) transport := thrift.NewTMemoryBuffer() protocol := NewMockTProtocol(mockCtrl) gomock.InOrder( protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)), protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args"), protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)), protocol.EXPECT().WriteString(context.Background(), "test"), protocol.EXPECT().WriteFieldEnd(context.Background()), protocol.EXPECT().WriteFieldStop(context.Background()), protocol.EXPECT().WriteStructEnd(context.Background()), protocol.EXPECT().WriteMessageEnd(context.Background()), protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin(context.Background()).Return("unknown", thrift.REPLY, int32(1), nil), ) client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol) _, err := client.TestString(defaultCtx, "test") mockCtrl.Finish() appErr, ok := err.(thrift.TApplicationException) if !ok { t.Fatal("Expected TApplicationException") } if appErr.TypeId() != thrift.WRONG_METHOD_NAME { t.Fatal("Expected WRONG_METHOD_NAME error") } } // TestCase: Wrong message type has been received in the client. func TestClientWrongMessageType(t *testing.T) { mockCtrl := gomock.NewController(t) protocol := NewMockTProtocol(mockCtrl) gomock.InOrder( protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)), protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args"), protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)), protocol.EXPECT().WriteString(context.Background(), "test"), protocol.EXPECT().WriteFieldEnd(context.Background()), protocol.EXPECT().WriteFieldStop(context.Background()), protocol.EXPECT().WriteStructEnd(context.Background()), protocol.EXPECT().WriteMessageEnd(context.Background()), protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin(context.Background()).Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil), ) client := errortest.NewErrorTestClient(thrift.NewTStandardClient(protocol, protocol)) _, err := client.TestString(defaultCtx, "test") mockCtrl.Finish() appErr, ok := err.(thrift.TApplicationException) if !ok { t.Fatal("Expected TApplicationException") } if appErr.TypeId() != thrift.INVALID_MESSAGE_TYPE_EXCEPTION { t.Fatal("Expected INVALID_MESSAGE_TYPE_EXCEPTION error") } } // TestCase: Wrong message type has been received in the client. // Similar to TestClientWrongMessageType, but using legacy client constructor. func TestClientWrongMessageTypeLegacy(t *testing.T) { mockCtrl := gomock.NewController(t) transport := thrift.NewTMemoryBuffer() protocol := NewMockTProtocol(mockCtrl) gomock.InOrder( protocol.EXPECT().WriteMessageBegin(context.Background(), "testString", thrift.CALL, int32(1)), protocol.EXPECT().WriteStructBegin(context.Background(), "testString_args"), protocol.EXPECT().WriteFieldBegin(context.Background(), "s", thrift.TType(thrift.STRING), int16(1)), protocol.EXPECT().WriteString(context.Background(), "test"), protocol.EXPECT().WriteFieldEnd(context.Background()), protocol.EXPECT().WriteFieldStop(context.Background()), protocol.EXPECT().WriteStructEnd(context.Background()), protocol.EXPECT().WriteMessageEnd(context.Background()), protocol.EXPECT().Flush(context.Background()), protocol.EXPECT().ReadMessageBegin(context.Background()).Return("testString", thrift.INVALID_TMESSAGE_TYPE, int32(1), nil), ) client := errortest.NewErrorTestClientProtocol(transport, protocol, protocol) _, err := client.TestString(defaultCtx, "test") mockCtrl.Finish() appErr, ok := err.(thrift.TApplicationException) if !ok { t.Fatal("Expected TApplicationException") } if appErr.TypeId() != thrift.INVALID_MESSAGE_TYPE_EXCEPTION { t.Fatal("Expected INVALID_MESSAGE_TYPE_EXCEPTION error") } } thrift-0.19.0/lib/go/test/tests/optional_fields_test.go0000644000000000000000000002253714303740367023154 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "bytes" "context" "testing" "github.com/golang/mock/gomock" "github.com/apache/thrift/lib/go/test/gopath/src/optionalfieldstest" "github.com/apache/thrift/lib/go/thrift" ) func TestIsSetReturnFalseOnCreation(t *testing.T) { ao := optionalfieldstest.NewAllOptional() if ao.IsSetS() { t.Errorf("Optional field S is set on initialization") } if ao.IsSetI() { t.Errorf("Optional field I is set on initialization") } if ao.IsSetB() { t.Errorf("Optional field B is set on initialization") } if ao.IsSetS2() { t.Errorf("Optional field S2 is set on initialization") } if ao.IsSetI2() { t.Errorf("Optional field I2 is set on initialization") } if ao.IsSetB2() { t.Errorf("Optional field B2 is set on initialization") } if ao.IsSetAa() { t.Errorf("Optional field Aa is set on initialization") } if ao.IsSetL() { t.Errorf("Optional field L is set on initialization") } if ao.IsSetL2() { t.Errorf("Optional field L2 is set on initialization") } if ao.IsSetM() { t.Errorf("Optional field M is set on initialization") } if ao.IsSetM2() { t.Errorf("Optional field M2 is set on initialization") } if ao.IsSetBin() { t.Errorf("Optional field Bin is set on initialization") } if ao.IsSetBin2() { t.Errorf("Optional field Bin2 is set on initialization") } } func TestDefaultValuesOnCreation(t *testing.T) { ao := optionalfieldstest.NewAllOptional() if ao.GetS() != "DEFAULT" { t.Errorf("Unexpected default value %#v for field S", ao.GetS()) } if ao.GetI() != 42 { t.Errorf("Unexpected default value %#v for field I", ao.GetI()) } if ao.GetB() != false { t.Errorf("Unexpected default value %#v for field B", ao.GetB()) } if ao.GetS2() != "" { t.Errorf("Unexpected default value %#v for field S2", ao.GetS2()) } if ao.GetI2() != 0 { t.Errorf("Unexpected default value %#v for field I2", ao.GetI2()) } if ao.GetB2() != false { t.Errorf("Unexpected default value %#v for field B2", ao.GetB2()) } if l := ao.GetL(); len(l) != 0 { t.Errorf("Unexpected default value %#v for field L", l) } if l := ao.GetL2(); len(l) != 2 || l[0] != 1 || l[1] != 2 { t.Errorf("Unexpected default value %#v for field L2", l) } //FIXME: should we return empty map here? if m := ao.GetM(); m != nil { t.Errorf("Unexpected default value %#v for field M", m) } if m := ao.GetM2(); len(m) != 2 || m[1] != 2 || m[3] != 4 { t.Errorf("Unexpected default value %#v for field M2", m) } if bv := ao.GetBin(); bv != nil { t.Errorf("Unexpected default value %#v for field Bin", bv) } if bv := ao.GetBin2(); !bytes.Equal(bv, []byte("asdf")) { t.Errorf("Unexpected default value %#v for field Bin2", bv) } } func TestInitialValuesOnCreation(t *testing.T) { ao := optionalfieldstest.NewAllOptional() if ao.S != "DEFAULT" { t.Errorf("Unexpected initial value %#v for field S", ao.S) } if ao.I != 42 { t.Errorf("Unexpected initial value %#v for field I", ao.I) } if ao.B != false { t.Errorf("Unexpected initial value %#v for field B", ao.B) } if ao.S2 != nil { t.Errorf("Unexpected initial value %#v for field S2", ao.S2) } if ao.I2 != nil { t.Errorf("Unexpected initial value %#v for field I2", ao.I2) } if ao.B2 != nil { t.Errorf("Unexpected initial value %#v for field B2", ao.B2) } if ao.L != nil || len(ao.L) != 0 { t.Errorf("Unexpected initial value %#v for field L", ao.L) } if ao.L2 != nil { t.Errorf("Unexpected initial value %#v for field L2", ao.L2) } if ao.M != nil { t.Errorf("Unexpected initial value %#v for field M", ao.M) } if ao.M2 != nil { t.Errorf("Unexpected initial value %#v for field M2", ao.M2) } if ao.Bin != nil || len(ao.Bin) != 0 { t.Errorf("Unexpected initial value %#v for field Bin", ao.Bin) } if !bytes.Equal(ao.Bin2, []byte("asdf")) { t.Errorf("Unexpected initial value %#v for field Bin2", ao.Bin2) } } func TestIsSetReturnTrueAfterUpdate(t *testing.T) { ao := optionalfieldstest.NewAllOptional() ao.S = "somevalue" ao.I = 123 ao.B = true ao.Aa = optionalfieldstest.NewStructA() if !ao.IsSetS() { t.Errorf("Field S should be set") } if !ao.IsSetI() { t.Errorf("Field I should be set") } if !ao.IsSetB() { t.Errorf("Field B should be set") } if !ao.IsSetAa() { t.Errorf("Field aa should be set") } } func TestListNotEmpty(t *testing.T) { ao := optionalfieldstest.NewAllOptional() ao.L = []int64{1, 2, 3} if !ao.IsSetL() { t.Errorf("Field L should be set") } } //Make sure that optional fields are not being serialized func TestNoOptionalUnsetFieldsOnWire(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockTProtocol(mockCtrl) gomock.InOrder( proto.EXPECT().WriteStructBegin(context.Background(), "all_optional").Return(nil), proto.EXPECT().WriteFieldStop(context.Background()).Return(nil), proto.EXPECT().WriteStructEnd(context.Background()).Return(nil), ) ao := optionalfieldstest.NewAllOptional() ao.Write(context.Background(), proto) } func TestNoSetToDefaultFieldsOnWire(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockTProtocol(mockCtrl) gomock.InOrder( proto.EXPECT().WriteStructBegin(context.Background(), "all_optional").Return(nil), proto.EXPECT().WriteFieldStop(context.Background()).Return(nil), proto.EXPECT().WriteStructEnd(context.Background()).Return(nil), ) ao := optionalfieldstest.NewAllOptional() ao.I = 42 ao.Write(context.Background(), proto) } //Make sure that only one field is being serialized when set to non-default func TestOneISetFieldOnWire(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockTProtocol(mockCtrl) gomock.InOrder( proto.EXPECT().WriteStructBegin(context.Background(), "all_optional").Return(nil), proto.EXPECT().WriteFieldBegin(context.Background(), "i", thrift.TType(thrift.I64), int16(2)).Return(nil), proto.EXPECT().WriteI64(context.Background(), int64(123)).Return(nil), proto.EXPECT().WriteFieldEnd(context.Background()).Return(nil), proto.EXPECT().WriteFieldStop(context.Background()).Return(nil), proto.EXPECT().WriteStructEnd(context.Background()).Return(nil), ) ao := optionalfieldstest.NewAllOptional() ao.I = 123 ao.Write(context.Background(), proto) } func TestOneLSetFieldOnWire(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockTProtocol(mockCtrl) gomock.InOrder( proto.EXPECT().WriteStructBegin(context.Background(), "all_optional").Return(nil), proto.EXPECT().WriteFieldBegin(context.Background(), "l", thrift.TType(thrift.LIST), int16(9)).Return(nil), proto.EXPECT().WriteListBegin(context.Background(), thrift.TType(thrift.I64), 2).Return(nil), proto.EXPECT().WriteI64(context.Background(), int64(1)).Return(nil), proto.EXPECT().WriteI64(context.Background(), int64(2)).Return(nil), proto.EXPECT().WriteListEnd(context.Background()).Return(nil), proto.EXPECT().WriteFieldEnd(context.Background()).Return(nil), proto.EXPECT().WriteFieldStop(context.Background()).Return(nil), proto.EXPECT().WriteStructEnd(context.Background()).Return(nil), ) ao := optionalfieldstest.NewAllOptional() ao.L = []int64{1, 2} ao.Write(context.Background(), proto) } func TestOneBinSetFieldOnWire(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockTProtocol(mockCtrl) gomock.InOrder( proto.EXPECT().WriteStructBegin(context.Background(), "all_optional").Return(nil), proto.EXPECT().WriteFieldBegin(context.Background(), "bin", thrift.TType(thrift.STRING), int16(13)).Return(nil), proto.EXPECT().WriteBinary(context.Background(), []byte("somebytestring")).Return(nil), proto.EXPECT().WriteFieldEnd(context.Background()).Return(nil), proto.EXPECT().WriteFieldStop(context.Background()).Return(nil), proto.EXPECT().WriteStructEnd(context.Background()).Return(nil), ) ao := optionalfieldstest.NewAllOptional() ao.Bin = []byte("somebytestring") ao.Write(context.Background(), proto) } func TestOneEmptyBinSetFieldOnWire(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() proto := NewMockTProtocol(mockCtrl) gomock.InOrder( proto.EXPECT().WriteStructBegin(context.Background(), "all_optional").Return(nil), proto.EXPECT().WriteFieldBegin(context.Background(), "bin", thrift.TType(thrift.STRING), int16(13)).Return(nil), proto.EXPECT().WriteBinary(context.Background(), []byte{}).Return(nil), proto.EXPECT().WriteFieldEnd(context.Background()).Return(nil), proto.EXPECT().WriteFieldStop(context.Background()).Return(nil), proto.EXPECT().WriteStructEnd(context.Background()).Return(nil), ) ao := optionalfieldstest.NewAllOptional() ao.Bin = []byte{} ao.Write(context.Background(), proto) } thrift-0.19.0/lib/go/test/tests/conflict_arg_names_test.go0000644000000000000000000000200714303740367023604 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "github.com/apache/thrift/lib/go/test/gopath/src/conflictargnamestest" ) // We just want to make sure that the conflictargnamestest package compiles. var _ = conflictargnamestest.GoUnusedProtection__ thrift-0.19.0/lib/go/test/tests/required_fields_test.go0000644000000000000000000001171714303740367023145 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "testing" "github.com/golang/mock/gomock" "github.com/apache/thrift/lib/go/test/gopath/src/optionalfieldstest" "github.com/apache/thrift/lib/go/test/gopath/src/requiredfieldtest" "github.com/apache/thrift/lib/go/thrift" ) func TestRequiredField_SucecssWhenSet(t *testing.T) { // create a new RequiredField instance with the required field set source := &requiredfieldtest.RequiredField{Name: "this is a test"} sourceData, err := thrift.NewTSerializer().Write(context.Background(), source) if err != nil { t.Fatalf("failed to serialize %T: %v", source, err) } d := thrift.NewTDeserializer() err = d.Read(context.Background(), &requiredfieldtest.RequiredField{}, sourceData) if err != nil { t.Fatalf("Did not expect an error when trying to deserialize the requiredfieldtest.RequiredField: %v", err) } } func TestRequiredField_ErrorWhenMissing(t *testing.T) { // create a new OtherThing instance, without setting the required field source := &requiredfieldtest.OtherThing{} sourceData, err := thrift.NewTSerializer().Write(context.Background(), source) if err != nil { t.Fatalf("failed to serialize %T: %v", source, err) } // attempt to deserialize into a different type (which should fail) d := thrift.NewTDeserializer() err = d.Read(context.Background(), &requiredfieldtest.RequiredField{}, sourceData) if err == nil { t.Fatal("Expected an error when trying to deserialize an object which is missing a required field") } } func TestStructReadRequiredFields(t *testing.T) { mockCtrl := gomock.NewController(t) protocol := NewMockTProtocol(mockCtrl) testStruct := optionalfieldstest.NewStructC() // None of required fields are set gomock.InOrder( protocol.EXPECT().ReadStructBegin(context.Background()).Return("StructC", nil), protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STOP), int16(1), nil), protocol.EXPECT().ReadStructEnd(context.Background()).Return(nil), ) err := testStruct.Read(context.Background(), protocol) mockCtrl.Finish() mockCtrl = gomock.NewController(t) if err == nil { t.Fatal("Expected read to fail") } err2, ok := err.(thrift.TProtocolException) if !ok { t.Fatal("Expected a TProtocolException") } if err2.TypeId() != thrift.INVALID_DATA { t.Fatal("Expected INVALID_DATA TProtocolException") } // One of the required fields is set gomock.InOrder( protocol.EXPECT().ReadStructBegin(context.Background()).Return("StructC", nil), protocol.EXPECT().ReadFieldBegin(context.Background()).Return("I", thrift.TType(thrift.I32), int16(2), nil), protocol.EXPECT().ReadI32(context.Background()).Return(int32(1), nil), protocol.EXPECT().ReadFieldEnd(context.Background()).Return(nil), protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STOP), int16(1), nil), protocol.EXPECT().ReadStructEnd(context.Background()).Return(nil), ) err = testStruct.Read(context.Background(), protocol) mockCtrl.Finish() mockCtrl = gomock.NewController(t) if err == nil { t.Fatal("Expected read to fail") } err2, ok = err.(thrift.TProtocolException) if !ok { t.Fatal("Expected a TProtocolException") } if err2.TypeId() != thrift.INVALID_DATA { t.Fatal("Expected INVALID_DATA TProtocolException") } // Both of the required fields are set gomock.InOrder( protocol.EXPECT().ReadStructBegin(context.Background()).Return("StructC", nil), protocol.EXPECT().ReadFieldBegin(context.Background()).Return("i", thrift.TType(thrift.I32), int16(2), nil), protocol.EXPECT().ReadI32(context.Background()).Return(int32(1), nil), protocol.EXPECT().ReadFieldEnd(context.Background()).Return(nil), protocol.EXPECT().ReadFieldBegin(context.Background()).Return("s2", thrift.TType(thrift.STRING), int16(4), nil), protocol.EXPECT().ReadString(context.Background()).Return("test", nil), protocol.EXPECT().ReadFieldEnd(context.Background()).Return(nil), protocol.EXPECT().ReadFieldBegin(context.Background()).Return("_", thrift.TType(thrift.STOP), int16(1), nil), protocol.EXPECT().ReadStructEnd(context.Background()).Return(nil), ) err = testStruct.Read(context.Background(), protocol) mockCtrl.Finish() if err != nil { t.Fatal("Expected read to succeed") } } thrift-0.19.0/lib/go/test/tests/context.go0000644000000000000000000000156114303740367020420 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" ) var defaultCtx = context.Background() thrift-0.19.0/lib/go/test/tests/union_default_value_test.go0000644000000000000000000000210214303740367024013 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "testing" "github.com/apache/thrift/lib/go/test/gopath/src/uniondefaultvaluetest" ) func TestUnionDefaultValue(t *testing.T) { s := uniondefaultvaluetest.NewTestStruct() d := s.GetDescendant() if d == nil { t.Error("Default Union value not set!") } } thrift-0.19.0/lib/go/test/tests/forwardtype_test.go0000644000000000000000000000240414452237057022340 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "testing" "github.com/apache/thrift/lib/go/test/gopath/src/forwardtypetest" "github.com/apache/thrift/lib/go/thrift" ) func TestForwardType(t *testing.T) { // See https://issues.apache.org/jira/browse/THRIFT-5685 const code = int32(1) foo := &forwardtypetest.Struct{ Foo: &forwardtypetest.Exc{ Code: thrift.Pointer(code), }, } if got, want := foo.GetFoo().GetCode(), code; got != want { t.Errorf("code got %v want %v", got, want) } } thrift-0.19.0/lib/go/test/tests/conflict_namespace_test.go0000644000000000000000000000176014303740367023611 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "github.com/apache/thrift/lib/go/test/gopath/src/conflict/super" ) // We just want to make sure that the compiler generated package compiles. var _ = super.GoUnusedProtection__ thrift-0.19.0/lib/go/test/tests/client_middleware_exception_test.go0000644000000000000000000001447714303740367025536 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "errors" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/clientmiddlewareexceptiontest" "github.com/apache/thrift/lib/go/thrift" ) type fakeClientMiddlewareExceptionTestHandler func(ctx context.Context) (*clientmiddlewareexceptiontest.FooResponse, error) func (f fakeClientMiddlewareExceptionTestHandler) Foo(ctx context.Context) (*clientmiddlewareexceptiontest.FooResponse, error) { return f(ctx) } type clientMiddlewareErrorChecker func(err error) error var clientMiddlewareExceptionCases = []struct { label string handler fakeClientMiddlewareExceptionTestHandler checker clientMiddlewareErrorChecker }{ { label: "no-error", handler: func(_ context.Context) (*clientmiddlewareexceptiontest.FooResponse, error) { return new(clientmiddlewareexceptiontest.FooResponse), nil }, checker: func(err error) error { if err != nil { return errors.New("expected err to be nil") } return nil }, }, { label: "exception-1", handler: func(_ context.Context) (*clientmiddlewareexceptiontest.FooResponse, error) { return nil, new(clientmiddlewareexceptiontest.Exception1) }, checker: func(err error) error { if !errors.As(err, new(*clientmiddlewareexceptiontest.Exception1)) { return errors.New("expected err to be of type *clientmiddlewareexceptiontest.Exception1") } return nil }, }, { label: "no-error", handler: func(_ context.Context) (*clientmiddlewareexceptiontest.FooResponse, error) { return nil, new(clientmiddlewareexceptiontest.Exception2) }, checker: func(err error) error { if !errors.As(err, new(*clientmiddlewareexceptiontest.Exception2)) { return errors.New("expected err to be of type *clientmiddlewareexceptiontest.Exception2") } return nil }, }, } func TestClientMiddlewareException(t *testing.T) { for _, c := range clientMiddlewareExceptionCases { t.Run(c.label, func(t *testing.T) { serverSocket, err := thrift.NewTServerSocket(":0") if err != nil { t.Fatalf("failed to create server socket: %v", err) } processor := clientmiddlewareexceptiontest.NewClientMiddlewareExceptionTestProcessor(c.handler) server := thrift.NewTSimpleServer2(processor, serverSocket) if err := server.Listen(); err != nil { t.Fatalf("failed to listen server: %v", err) } addr := serverSocket.Addr().String() go server.Serve() t.Cleanup(func() { server.Stop() }) var cfg *thrift.TConfiguration socket := thrift.NewTSocketConf(addr, cfg) if err := socket.Open(); err != nil { t.Fatalf("failed to create client connection: %v", err) } t.Cleanup(func() { socket.Close() }) inProtocol := thrift.NewTBinaryProtocolConf(socket, cfg) outProtocol := thrift.NewTBinaryProtocolConf(socket, cfg) middleware := func(next thrift.TClient) thrift.TClient { return thrift.WrappedTClient{ Wrapped: func(ctx context.Context, method string, args, result thrift.TStruct) (_ thrift.ResponseMeta, err error) { defer func() { if checkErr := c.checker(err); checkErr != nil { t.Errorf("middleware result unexpected: %v (result=%#v, err=%#v)", checkErr, result, err) } }() return next.Call(ctx, method, args, result) }, } } client := thrift.WrapClient( thrift.NewTStandardClient(inProtocol, outProtocol), middleware, thrift.ExtractIDLExceptionClientMiddleware, ) result, err := clientmiddlewareexceptiontest.NewClientMiddlewareExceptionTestClient(client).Foo(context.Background()) if checkErr := c.checker(err); checkErr != nil { t.Errorf("final result unexpected: %v (result=%#v, err=%#v)", checkErr, result, err) } }) } } func TestExtractExceptionFromResult(t *testing.T) { for _, c := range clientMiddlewareExceptionCases { t.Run(c.label, func(t *testing.T) { serverSocket, err := thrift.NewTServerSocket(":0") if err != nil { t.Fatalf("failed to create server socket: %v", err) } processor := clientmiddlewareexceptiontest.NewClientMiddlewareExceptionTestProcessor(c.handler) server := thrift.NewTSimpleServer2(processor, serverSocket) if err := server.Listen(); err != nil { t.Fatalf("failed to listen server: %v", err) } addr := serverSocket.Addr().String() go server.Serve() t.Cleanup(func() { server.Stop() }) var cfg *thrift.TConfiguration socket := thrift.NewTSocketConf(addr, cfg) if err := socket.Open(); err != nil { t.Fatalf("failed to create client connection: %v", err) } t.Cleanup(func() { socket.Close() }) inProtocol := thrift.NewTBinaryProtocolConf(socket, cfg) outProtocol := thrift.NewTBinaryProtocolConf(socket, cfg) middleware := func(next thrift.TClient) thrift.TClient { return thrift.WrappedTClient{ Wrapped: func(ctx context.Context, method string, args, result thrift.TStruct) (_ thrift.ResponseMeta, err error) { defer func() { if err == nil { err = thrift.ExtractExceptionFromResult(result) } if checkErr := c.checker(err); checkErr != nil { t.Errorf("middleware result unexpected: %v (result=%#v, err=%#v)", checkErr, result, err) } }() return next.Call(ctx, method, args, result) }, } } client := thrift.WrapClient( thrift.NewTStandardClient(inProtocol, outProtocol), middleware, ) result, err := clientmiddlewareexceptiontest.NewClientMiddlewareExceptionTestClient(client).Foo(context.Background()) if checkErr := c.checker(err); checkErr != nil { t.Errorf("final result unexpected: %v (result=%#v, err=%#v)", checkErr, result, err) } }) } } thrift-0.19.0/lib/go/test/tests/multiplexed_protocol_test.go0000644000000000000000000001464114303740367024253 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "net" "testing" "time" "github.com/apache/thrift/lib/go/test/gopath/src/multiplexedprotocoltest" "github.com/apache/thrift/lib/go/thrift" ) func FindAvailableTCPServerPort() net.Addr { if l, err := net.Listen("tcp", "127.0.0.1:0"); err != nil { panic("Could not find available server port") } else { defer l.Close() return l.Addr() } } type FirstImpl struct{} func (f *FirstImpl) ReturnOne(ctx context.Context) (r int64, err error) { return 1, nil } type SecondImpl struct{} func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) { return 2, nil } func createTransport(addr net.Addr) (thrift.TTransport, error) { cfg := &thrift.TConfiguration{ ConnectTimeout: TIMEOUT, SocketTimeout: TIMEOUT, } socket := thrift.NewTSocketFromAddrConf(addr, cfg) transport := thrift.NewTFramedTransportConf(socket, cfg) err := transport.Open() if err != nil { return nil, err } return transport, nil } func TestMultiplexedProtocolFirst(t *testing.T) { processor := thrift.NewTMultiplexedProcessor() protocolFactory := thrift.NewTBinaryProtocolFactoryConf(nil) transportFactory := thrift.NewTTransportFactory() transportFactory = thrift.NewTFramedTransportFactoryConf(transportFactory, nil) addr := FindAvailableTCPServerPort() serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT) if err != nil { t.Fatal("Unable to create server socket", err) } server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) firstProcessor := multiplexedprotocoltest.NewFirstProcessor(&FirstImpl{}) processor.RegisterProcessor("FirstService", firstProcessor) secondProcessor := multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{}) processor.RegisterProcessor("SecondService", secondProcessor) defer server.Stop() go server.Serve() time.Sleep(10 * time.Millisecond) transport, err := createTransport(addr) if err != nil { t.Fatal(err) } defer transport.Close() protocol := thrift.NewTMultiplexedProtocol(thrift.NewTBinaryProtocolConf(transport, nil), "FirstService") client := multiplexedprotocoltest.NewFirstClient(thrift.NewTStandardClient(protocol, protocol)) ret, err := client.ReturnOne(defaultCtx) if err != nil { t.Fatal("Unable to call first server:", err) } else if ret != 1 { t.Fatal("Unexpected result from server: ", ret) } } func TestMultiplexedProtocolSecond(t *testing.T) { processor := thrift.NewTMultiplexedProcessor() protocolFactory := thrift.NewTBinaryProtocolFactoryConf(nil) transportFactory := thrift.NewTTransportFactory() transportFactory = thrift.NewTFramedTransportFactoryConf(transportFactory, nil) addr := FindAvailableTCPServerPort() serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT) if err != nil { t.Fatal("Unable to create server socket", err) } server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) firstProcessor := multiplexedprotocoltest.NewFirstProcessor(&FirstImpl{}) processor.RegisterProcessor("FirstService", firstProcessor) secondProcessor := multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{}) processor.RegisterProcessor("SecondService", secondProcessor) defer server.Stop() go server.Serve() time.Sleep(10 * time.Millisecond) transport, err := createTransport(addr) if err != nil { t.Fatal(err) } defer transport.Close() protocol := thrift.NewTMultiplexedProtocol(thrift.NewTBinaryProtocolConf(transport, nil), "SecondService") client := multiplexedprotocoltest.NewSecondClient(thrift.NewTStandardClient(protocol, protocol)) ret, err := client.ReturnTwo(defaultCtx) if err != nil { t.Fatal("Unable to call second server:", err) } else if ret != 2 { t.Fatal("Unexpected result from server: ", ret) } } func TestMultiplexedProtocolLegacy(t *testing.T) { processor := thrift.NewTMultiplexedProcessor() protocolFactory := thrift.NewTBinaryProtocolFactoryConf(nil) transportFactory := thrift.NewTTransportFactory() transportFactory = thrift.NewTFramedTransportFactoryConf(transportFactory, nil) addr := FindAvailableTCPServerPort() serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT) if err != nil { t.Fatal("Unable to create server socket", err) } server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) firstProcessor := multiplexedprotocoltest.NewFirstProcessor(&FirstImpl{}) processor.RegisterProcessor("FirstService", firstProcessor) secondProcessor := multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{}) processor.RegisterProcessor("SecondService", secondProcessor) defer server.Stop() go server.Serve() time.Sleep(10 * time.Millisecond) transport, err := createTransport(addr) if err != nil { t.Error(err) return } defer transport.Close() protocol := thrift.NewTBinaryProtocolConf(transport, nil) client := multiplexedprotocoltest.NewSecondClient(thrift.NewTStandardClient(protocol, protocol)) _, err = client.ReturnTwo(defaultCtx) //expect error since default processor is not registered if err == nil { t.Fatal("Expecting error") } //register default processor and call again processor.RegisterDefault(multiplexedprotocoltest.NewSecondProcessor(&SecondImpl{})) transport, err = createTransport(addr) if err != nil { t.Error(err) return } defer transport.Close() protocol = thrift.NewTBinaryProtocolConf(transport, nil) client = multiplexedprotocoltest.NewSecondClient(thrift.NewTStandardClient(protocol, protocol)) ret, err := client.ReturnTwo(defaultCtx) if err != nil { t.Fatal("Unable to call legacy server:", err) } if ret != 2 { t.Fatal("Unexpected result from server: ", ret) } } thrift-0.19.0/lib/go/test/tests/initialisms_test.go0000644000000000000000000000243614303740367022322 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "reflect" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/initialismstest" ) func TestThatCommonInitialismsAreFixed(t *testing.T) { s := initialismstest.InitialismsTest{} st := reflect.TypeOf(s) _, ok := st.FieldByName("UserID") if !ok { t.Error("UserID attribute is missing!") } _, ok = st.FieldByName("ServerURL") if !ok { t.Error("ServerURL attribute is missing!") } _, ok = st.FieldByName("ID") if !ok { t.Error("ID attribute is missing!") } } thrift-0.19.0/lib/go/test/tests/one_way_test.go0000644000000000000000000000543114303740367021434 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "fmt" "net" "testing" "time" "github.com/apache/thrift/lib/go/test/gopath/src/onewaytest" "github.com/apache/thrift/lib/go/thrift" ) func findPort() net.Addr { if l, err := net.Listen("tcp", "127.0.0.1:0"); err != nil { panic("Could not find available server port") } else { defer l.Close() return l.Addr() } } type impl struct{} func (i *impl) Hi(ctx context.Context, in int64, s string) (err error) { fmt.Println("Hi!"); return } func (i *impl) Emptyfunc(ctx context.Context) (err error) { return } func (i *impl) EchoInt(ctx context.Context, param int64) (r int64, err error) { return param, nil } const TIMEOUT = time.Second var addr net.Addr var server *thrift.TSimpleServer var client *onewaytest.OneWayClient func TestInitOneway(t *testing.T) { var err error addr = findPort() serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT) if err != nil { t.Fatal("Unable to create server socket", err) } processor := onewaytest.NewOneWayProcessor(&impl{}) server = thrift.NewTSimpleServer2(processor, serverTransport) go server.Serve() time.Sleep(10 * time.Millisecond) } func TestInitOnewayClient(t *testing.T) { cfg := &thrift.TConfiguration{ ConnectTimeout: TIMEOUT, SocketTimeout: TIMEOUT, } transport := thrift.NewTSocketFromAddrConf(addr, cfg) protocol := thrift.NewTBinaryProtocolConf(transport, cfg) client = onewaytest.NewOneWayClient(thrift.NewTStandardClient(protocol, protocol)) err := transport.Open() if err != nil { t.Fatal("Unable to open client socket", err) } } func TestCallOnewayServer(t *testing.T) { //call oneway function err := client.Hi(defaultCtx, 1, "") if err != nil { t.Fatal("Unexpected error: ", err) } //There is no way to detect protocol problems with single oneway call so we call it second time i, err := client.EchoInt(defaultCtx, 42) if err != nil { t.Fatal("Unexpected error: ", err) } if i != 42 { t.Fatal("Unexpected returned value: ", i) } } thrift-0.19.0/lib/go/test/tests/equals_test.go0000644000000000000000000003444614370300523021263 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "strconv" "testing" "github.com/apache/thrift/lib/go/thrift" "github.com/apache/thrift/lib/go/test/gopath/src/equalstest" ) var ( equalstestUUID1 = thrift.Must(thrift.ParseTuuid("6ba7b810-9dad-11d1-80b4-00c04fd430c8")) equalstestUUID2 = thrift.Must(thrift.ParseTuuid("6ba7b811-9dad-11d1-80b4-00c04fd430c8")) ) func TestEquals(t *testing.T) { // test basic field basicTgt, basicSrc := genBasicFoo(), genBasicFoo() if !basicTgt.Equals(basicSrc) { t.Error("BasicEqualsFoo.Equals() test failed") } basicSrc.EnumFoo = equalstest.EnumFoo_e2 if basicTgt.Equals(basicSrc) { t.Error("BasicEqualsFoo.Equals() test failed") } basicSrc = genBasicFoo() basicSrc.OptBoolFoo = nil if basicTgt.Equals(basicSrc) || basicSrc.Equals(basicTgt) { t.Error("BasicEqualsFoo.Equals() test failed") } if !(&equalstest.BasicEqualsFoo{}).Equals(&equalstest.BasicEqualsFoo{}) { t.Error("BasicEqualsFoo.Equals() test failed") } // test struct field structTgt, structSrc := genStructFoo(), genStructFoo() if !structTgt.Equals(structSrc) { t.Error("StructEqualsFoo.Equals() test failed") } structSrc.OptStructFoo.EnumFoo = equalstest.EnumFoo_e2 if structTgt.Equals(structSrc) { t.Error("StructEqualsFoo.Equals() test failed") } structSrc = genStructFoo() structSrc.OptStructFoo = nil if structTgt.Equals(structSrc) || structSrc.Equals(structTgt) { t.Error("StructEqualsFoo.Equals() test failed") } if !(&equalstest.StructEqualsFoo{}).Equals(&equalstest.StructEqualsFoo{}) { t.Error("StructEqualsFoo.Equals() test failed") } // test list field listTgt, listSrc := genListFoo(), genListFoo() if !listTgt.Equals(listSrc) { t.Error("ListEqualsFoo.Equals() test failed") } listSrc.OptI64StringMapListFoo[0][1] = "0" if listTgt.Equals(listSrc) { t.Error("ListEqualsFoo.Equals() test failed") } listSrc = genListFoo() listSrc.OptI64StringMapListFoo = nil if listTgt.Equals(listSrc) || listSrc.Equals(listTgt) { t.Error("ListEqualsFoo.Equals() test failed") } if !(&equalstest.ListEqualsFoo{}).Equals(&equalstest.ListEqualsFoo{}) { t.Error("ListEqualsFoo.Equals() test failed") } // test set field setTgt, setSrc := genSetFoo(), genSetFoo() if !setTgt.Equals(setSrc) { t.Error("SetEqualsFoo.Equals() test failed") } setSrc.OptI64StringMapSetFoo[0][1] = "0" if setTgt.Equals(setSrc) { t.Error("SetEqualsFoo.Equals() test failed") } setSrc = genSetFoo() setSrc.OptI64StringMapSetFoo = nil if setTgt.Equals(setSrc) || setSrc.Equals(setTgt) { t.Error("SetEqualsFoo.Equals() test failed") } if !(&equalstest.SetEqualsFoo{}).Equals(&equalstest.SetEqualsFoo{}) { t.Error("SetEqualsFoo.Equals() test failed") } // test map field mapTgt, mapSrc := genMapFoo(), genMapFoo() if !mapTgt.Equals(mapSrc) { t.Error("MapEqualsFoo.Equals() test failed") } mapSrc.OptI64I64StringMapMapFoo[1][1] = "0" if mapTgt.Equals(mapSrc) { t.Error("MapEqualsFoo.Equals() test failed") } mapSrc = genMapFoo() mapSrc.OptI64I64StringMapMapFoo = nil if mapTgt.Equals(mapSrc) || mapSrc.Equals(mapTgt) { t.Error("MapEqualsFoo.Equals() test failed") } if !(&equalstest.MapEqualsFoo{}).Equals(&equalstest.MapEqualsFoo{}) { t.Error("MapEqualsFoo.Equals() test failed") } } func genBasicFoo() *equalstest.BasicEqualsFoo { return &equalstest.BasicEqualsFoo{ BoolFoo: true, OptBoolFoo: thrift.BoolPtr(true), I8Foo: 1, OptI8Foo: thrift.Int8Ptr(1), I16Foo: 2, OptI16Foo: thrift.Int16Ptr(2), I32Foo: 3, OptI32Foo: thrift.Int32Ptr(3), I64Foo: 4, OptI64Foo: thrift.Int64Ptr(4), DoubleFoo: 5, OptDoubleFoo: thrift.Float64Ptr(6), StrFoo: "6", OptStrFoo: thrift.StringPtr("6"), BinFoo: []byte("7"), OptBinFoo: []byte("7"), EnumFoo: equalstest.EnumFoo_e1, OptEnumFoo: equalstest.EnumFooPtr(equalstest.EnumFoo_e1), MyByteFoo: equalstest.Mybyte(8), OptMyByteFoo: equalstest.MybytePtr(8), MyStrFoo: equalstest.Mystr("9"), OptMyStrFoo: equalstest.MystrPtr(equalstest.Mystr("9")), MyBinFoo: equalstest.Mybin("10"), OptMyBinFoo: equalstest.Mybin("10"), UUIDFoo: equalstestUUID1, OptUUIDFoo: thrift.TuuidPtr(equalstestUUID1), MyUUIDFoo: equalstest.Myuuid(equalstestUUID1), OptMyUUIDFoo: equalstest.MyuuidPtr(equalstest.Myuuid(equalstestUUID1)), } } func genStructFoo() *equalstest.StructEqualsFoo { return &equalstest.StructEqualsFoo{ StructFoo: genBasicFoo(), OptStructFoo: genBasicFoo(), } } func genListFoo() *equalstest.ListEqualsFoo { return &equalstest.ListEqualsFoo{ I64ListFoo: genInt64Slice(6), OptI64ListFoo: genInt64Slice(6), StrListFoo: genStringSlice(6), OptStrListFoo: genStringSlice(6), BinListFoo: genBytesSlice(6), OptBinListFoo: genBytesSlice(6), StructListFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, OptStructListFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, I64ListListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, OptI64ListListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, I64SetListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, OptI64SetListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, I64StringMapListFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, OptI64StringMapListFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, MyByteListFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, OptMyByteListFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, MyStrListFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, OptMyStrListFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, MyBinListFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, OptMyBinListFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, UUIDListFoo: []thrift.Tuuid{equalstestUUID1, equalstestUUID2}, OptUUIDListFoo: []thrift.Tuuid{equalstestUUID1, equalstestUUID2}, MyUUIDListFoo: []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)}, OptMyUUIDListFoo: []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)}, } } func genSetFoo() *equalstest.SetEqualsFoo { return &equalstest.SetEqualsFoo{ I64SetFoo: genInt64Slice(6), OptI64SetFoo: genInt64Slice(6), StrSetFoo: genStringSlice(6), OptStrSetFoo: genStringSlice(6), BinSetFoo: genBytesSlice(6), OptBinSetFoo: genBytesSlice(6), StructSetFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, OptStructSetFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, I64ListSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, OptI64ListSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, I64SetSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, OptI64SetSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, I64StringMapSetFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, OptI64StringMapSetFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, MyByteSetFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, OptMyByteSetFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, MyStrSetFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, OptMyStrSetFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, MyBinSetFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, OptMyBinSetFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, UUIDSetFoo: []thrift.Tuuid{equalstestUUID1, equalstestUUID2}, OptUUIDSetFoo: []thrift.Tuuid{equalstestUUID1, equalstestUUID2}, MyUUIDSetFoo: []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)}, OptMyUUIDSetFoo: []equalstest.Myuuid{equalstest.Myuuid(equalstestUUID1), equalstest.Myuuid(equalstestUUID2)}, } } var ( structMapKey0 = genBasicFoo() structMapKey1 = &equalstest.BasicEqualsFoo{} ) func genMapFoo() *equalstest.MapEqualsFoo { return &equalstest.MapEqualsFoo{ I64StrMapFoo: genInt64StringMap(6), OptI64StrMapFoo: genInt64StringMap(6), StrI64MapFoo: map[string]int64{"6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "1": 1}, OptStrI64MapFoo: map[string]int64{"6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "1": 1}, StructBinMapFoo: map[*equalstest.BasicEqualsFoo][]byte{structMapKey0: []byte("0"), structMapKey1: []byte("1")}, OptStructBinMapFoo: map[*equalstest.BasicEqualsFoo][]byte{structMapKey0: []byte("0"), structMapKey1: []byte("1")}, BinStructMapFoo: map[string]*equalstest.BasicEqualsFoo{"1": genBasicFoo(), "0": {}}, OptBinStructMapFoo: map[string]*equalstest.BasicEqualsFoo{"1": genBasicFoo(), "0": {}}, I64I64ListMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, OptI64I64ListMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, I64I64SetMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, OptI64I64SetMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, I64I64StringMapMapFoo: map[int64]map[int64]string{6: genInt64StringMap(6), 5: genInt64StringMap(5), 4: genInt64StringMap(4), 3: genInt64StringMap(3), 2: genInt64StringMap(2), 1: genInt64StringMap(1)}, OptI64I64StringMapMapFoo: map[int64]map[int64]string{6: genInt64StringMap(6), 5: genInt64StringMap(5), 4: genInt64StringMap(4), 3: genInt64StringMap(3), 2: genInt64StringMap(2), 1: genInt64StringMap(1)}, MyStrMyBinMapFoo: map[equalstest.Mystr]equalstest.Mybin{equalstest.Mystr("1"): equalstest.Mybin("1"), equalstest.Mystr("0"): equalstest.Mybin("0")}, OptMyStrMyBinMapFoo: map[equalstest.Mystr]equalstest.Mybin{equalstest.Mystr("1"): equalstest.Mybin("1"), equalstest.Mystr("0"): equalstest.Mybin("0")}, Int64MyByteMapFoo: map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)}, OptInt64MyByteMapFoo: map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)}, MyByteInt64MapFoo: map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1}, OptMyByteInt64MapFoo: map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1}, UUIDMapFoo: map[int64]thrift.Tuuid{1: equalstestUUID1, 2: equalstestUUID2}, OptUUIDMapFoo: map[int64]thrift.Tuuid{1: equalstestUUID1, 2: equalstestUUID2}, MyUUIDMapFoo: map[int64]equalstest.Myuuid{1: equalstest.Myuuid(equalstestUUID1), 2: equalstest.Myuuid(equalstestUUID2)}, OptMyUUIDMapFoo: map[int64]equalstest.Myuuid{1: equalstest.Myuuid(equalstestUUID1), 2: equalstest.Myuuid(equalstestUUID2)}, } } func genInt64Slice(length int) []int64 { ret := make([]int64, length) for i := 0; i < length; i++ { ret[i] = int64(length - i) } return ret } func genStringSlice(length int) []string { ret := make([]string, length) for i := 0; i < length; i++ { ret[i] = strconv.Itoa(length - i) } return ret } func genBytesSlice(length int) [][]byte { ret := make([][]byte, length) for i := 0; i < length; i++ { ret[i] = []byte(strconv.Itoa(length - i)) } return ret } func genInt64StringMap(length int) map[int64]string { ret := make(map[int64]string, length) for i := 0; i < length; i++ { ret[int64(i)] = strconv.Itoa(i) } return ret } thrift-0.19.0/lib/go/test/tests/names_test.go0000644000000000000000000000214314303740367021073 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "reflect" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/namestest" ) func TestThatAttributeNameSubstituionDoesNotOccur(t *testing.T) { s := namestest.NamesTest{} st := reflect.TypeOf(s) _, ok := st.FieldByName("Type") if !ok { t.Error("Type attribute is missing!") } } thrift-0.19.0/lib/go/test/tests/protocol_mock.go0000644000000000000000000006235414370300523021603 0ustar00rootroot00000000000000// Code generated by MockGen. DO NOT EDIT. // Source: github.com/apache/thrift/lib/go/thrift (interfaces: TProtocol) // Package tests is a generated GoMock package. package tests import ( context "context" reflect "reflect" thrift "github.com/apache/thrift/lib/go/thrift" gomock "github.com/golang/mock/gomock" ) // MockTProtocol is a mock of TProtocol interface. type MockTProtocol struct { ctrl *gomock.Controller recorder *MockTProtocolMockRecorder } // MockTProtocolMockRecorder is the mock recorder for MockTProtocol. type MockTProtocolMockRecorder struct { mock *MockTProtocol } // NewMockTProtocol creates a new mock instance. func NewMockTProtocol(ctrl *gomock.Controller) *MockTProtocol { mock := &MockTProtocol{ctrl: ctrl} mock.recorder = &MockTProtocolMockRecorder{mock} return mock } // EXPECT returns an object that allows the caller to indicate expected use. func (m *MockTProtocol) EXPECT() *MockTProtocolMockRecorder { return m.recorder } // Flush mocks base method. func (m *MockTProtocol) Flush(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Flush", arg0) ret0, _ := ret[0].(error) return ret0 } // Flush indicates an expected call of Flush. func (mr *MockTProtocolMockRecorder) Flush(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flush", reflect.TypeOf((*MockTProtocol)(nil).Flush), arg0) } // ReadBinary mocks base method. func (m *MockTProtocol) ReadBinary(arg0 context.Context) ([]byte, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadBinary", arg0) ret0, _ := ret[0].([]byte) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadBinary indicates an expected call of ReadBinary. func (mr *MockTProtocolMockRecorder) ReadBinary(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadBinary", reflect.TypeOf((*MockTProtocol)(nil).ReadBinary), arg0) } // ReadBool mocks base method. func (m *MockTProtocol) ReadBool(arg0 context.Context) (bool, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadBool", arg0) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadBool indicates an expected call of ReadBool. func (mr *MockTProtocolMockRecorder) ReadBool(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadBool", reflect.TypeOf((*MockTProtocol)(nil).ReadBool), arg0) } // ReadByte mocks base method. func (m *MockTProtocol) ReadByte(arg0 context.Context) (int8, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadByte", arg0) ret0, _ := ret[0].(int8) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadByte indicates an expected call of ReadByte. func (mr *MockTProtocolMockRecorder) ReadByte(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadByte", reflect.TypeOf((*MockTProtocol)(nil).ReadByte), arg0) } // ReadDouble mocks base method. func (m *MockTProtocol) ReadDouble(arg0 context.Context) (float64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadDouble", arg0) ret0, _ := ret[0].(float64) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadDouble indicates an expected call of ReadDouble. func (mr *MockTProtocolMockRecorder) ReadDouble(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadDouble", reflect.TypeOf((*MockTProtocol)(nil).ReadDouble), arg0) } // ReadFieldBegin mocks base method. func (m *MockTProtocol) ReadFieldBegin(arg0 context.Context) (string, thrift.TType, int16, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadFieldBegin", arg0) ret0, _ := ret[0].(string) ret1, _ := ret[1].(thrift.TType) ret2, _ := ret[2].(int16) ret3, _ := ret[3].(error) return ret0, ret1, ret2, ret3 } // ReadFieldBegin indicates an expected call of ReadFieldBegin. func (mr *MockTProtocolMockRecorder) ReadFieldBegin(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadFieldBegin", reflect.TypeOf((*MockTProtocol)(nil).ReadFieldBegin), arg0) } // ReadFieldEnd mocks base method. func (m *MockTProtocol) ReadFieldEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadFieldEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // ReadFieldEnd indicates an expected call of ReadFieldEnd. func (mr *MockTProtocolMockRecorder) ReadFieldEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadFieldEnd", reflect.TypeOf((*MockTProtocol)(nil).ReadFieldEnd), arg0) } // ReadI16 mocks base method. func (m *MockTProtocol) ReadI16(arg0 context.Context) (int16, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadI16", arg0) ret0, _ := ret[0].(int16) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadI16 indicates an expected call of ReadI16. func (mr *MockTProtocolMockRecorder) ReadI16(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadI16", reflect.TypeOf((*MockTProtocol)(nil).ReadI16), arg0) } // ReadI32 mocks base method. func (m *MockTProtocol) ReadI32(arg0 context.Context) (int32, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadI32", arg0) ret0, _ := ret[0].(int32) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadI32 indicates an expected call of ReadI32. func (mr *MockTProtocolMockRecorder) ReadI32(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadI32", reflect.TypeOf((*MockTProtocol)(nil).ReadI32), arg0) } // ReadI64 mocks base method. func (m *MockTProtocol) ReadI64(arg0 context.Context) (int64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadI64", arg0) ret0, _ := ret[0].(int64) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadI64 indicates an expected call of ReadI64. func (mr *MockTProtocolMockRecorder) ReadI64(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadI64", reflect.TypeOf((*MockTProtocol)(nil).ReadI64), arg0) } // ReadListBegin mocks base method. func (m *MockTProtocol) ReadListBegin(arg0 context.Context) (thrift.TType, int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadListBegin", arg0) ret0, _ := ret[0].(thrift.TType) ret1, _ := ret[1].(int) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ReadListBegin indicates an expected call of ReadListBegin. func (mr *MockTProtocolMockRecorder) ReadListBegin(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadListBegin", reflect.TypeOf((*MockTProtocol)(nil).ReadListBegin), arg0) } // ReadListEnd mocks base method. func (m *MockTProtocol) ReadListEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadListEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // ReadListEnd indicates an expected call of ReadListEnd. func (mr *MockTProtocolMockRecorder) ReadListEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadListEnd", reflect.TypeOf((*MockTProtocol)(nil).ReadListEnd), arg0) } // ReadMapBegin mocks base method. func (m *MockTProtocol) ReadMapBegin(arg0 context.Context) (thrift.TType, thrift.TType, int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadMapBegin", arg0) ret0, _ := ret[0].(thrift.TType) ret1, _ := ret[1].(thrift.TType) ret2, _ := ret[2].(int) ret3, _ := ret[3].(error) return ret0, ret1, ret2, ret3 } // ReadMapBegin indicates an expected call of ReadMapBegin. func (mr *MockTProtocolMockRecorder) ReadMapBegin(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadMapBegin", reflect.TypeOf((*MockTProtocol)(nil).ReadMapBegin), arg0) } // ReadMapEnd mocks base method. func (m *MockTProtocol) ReadMapEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadMapEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // ReadMapEnd indicates an expected call of ReadMapEnd. func (mr *MockTProtocolMockRecorder) ReadMapEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadMapEnd", reflect.TypeOf((*MockTProtocol)(nil).ReadMapEnd), arg0) } // ReadMessageBegin mocks base method. func (m *MockTProtocol) ReadMessageBegin(arg0 context.Context) (string, thrift.TMessageType, int32, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadMessageBegin", arg0) ret0, _ := ret[0].(string) ret1, _ := ret[1].(thrift.TMessageType) ret2, _ := ret[2].(int32) ret3, _ := ret[3].(error) return ret0, ret1, ret2, ret3 } // ReadMessageBegin indicates an expected call of ReadMessageBegin. func (mr *MockTProtocolMockRecorder) ReadMessageBegin(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadMessageBegin", reflect.TypeOf((*MockTProtocol)(nil).ReadMessageBegin), arg0) } // ReadMessageEnd mocks base method. func (m *MockTProtocol) ReadMessageEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadMessageEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // ReadMessageEnd indicates an expected call of ReadMessageEnd. func (mr *MockTProtocolMockRecorder) ReadMessageEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadMessageEnd", reflect.TypeOf((*MockTProtocol)(nil).ReadMessageEnd), arg0) } // ReadSetBegin mocks base method. func (m *MockTProtocol) ReadSetBegin(arg0 context.Context) (thrift.TType, int, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadSetBegin", arg0) ret0, _ := ret[0].(thrift.TType) ret1, _ := ret[1].(int) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // ReadSetBegin indicates an expected call of ReadSetBegin. func (mr *MockTProtocolMockRecorder) ReadSetBegin(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadSetBegin", reflect.TypeOf((*MockTProtocol)(nil).ReadSetBegin), arg0) } // ReadSetEnd mocks base method. func (m *MockTProtocol) ReadSetEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadSetEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // ReadSetEnd indicates an expected call of ReadSetEnd. func (mr *MockTProtocolMockRecorder) ReadSetEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadSetEnd", reflect.TypeOf((*MockTProtocol)(nil).ReadSetEnd), arg0) } // ReadString mocks base method. func (m *MockTProtocol) ReadString(arg0 context.Context) (string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadString", arg0) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadString indicates an expected call of ReadString. func (mr *MockTProtocolMockRecorder) ReadString(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadString", reflect.TypeOf((*MockTProtocol)(nil).ReadString), arg0) } // ReadStructBegin mocks base method. func (m *MockTProtocol) ReadStructBegin(arg0 context.Context) (string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadStructBegin", arg0) ret0, _ := ret[0].(string) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadStructBegin indicates an expected call of ReadStructBegin. func (mr *MockTProtocolMockRecorder) ReadStructBegin(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadStructBegin", reflect.TypeOf((*MockTProtocol)(nil).ReadStructBegin), arg0) } // ReadStructEnd mocks base method. func (m *MockTProtocol) ReadStructEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadStructEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // ReadStructEnd indicates an expected call of ReadStructEnd. func (mr *MockTProtocolMockRecorder) ReadStructEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadStructEnd", reflect.TypeOf((*MockTProtocol)(nil).ReadStructEnd), arg0) } // ReadUUID mocks base method. func (m *MockTProtocol) ReadUUID(arg0 context.Context) (thrift.Tuuid, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ReadUUID", arg0) ret0, _ := ret[0].(thrift.Tuuid) ret1, _ := ret[1].(error) return ret0, ret1 } // ReadUUID indicates an expected call of ReadUUID. func (mr *MockTProtocolMockRecorder) ReadUUID(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadUUID", reflect.TypeOf((*MockTProtocol)(nil).ReadUUID), arg0) } // Skip mocks base method. func (m *MockTProtocol) Skip(arg0 context.Context, arg1 thrift.TType) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Skip", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // Skip indicates an expected call of Skip. func (mr *MockTProtocolMockRecorder) Skip(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Skip", reflect.TypeOf((*MockTProtocol)(nil).Skip), arg0, arg1) } // Transport mocks base method. func (m *MockTProtocol) Transport() thrift.TTransport { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Transport") ret0, _ := ret[0].(thrift.TTransport) return ret0 } // Transport indicates an expected call of Transport. func (mr *MockTProtocolMockRecorder) Transport() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Transport", reflect.TypeOf((*MockTProtocol)(nil).Transport)) } // WriteBinary mocks base method. func (m *MockTProtocol) WriteBinary(arg0 context.Context, arg1 []byte) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteBinary", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteBinary indicates an expected call of WriteBinary. func (mr *MockTProtocolMockRecorder) WriteBinary(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteBinary", reflect.TypeOf((*MockTProtocol)(nil).WriteBinary), arg0, arg1) } // WriteBool mocks base method. func (m *MockTProtocol) WriteBool(arg0 context.Context, arg1 bool) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteBool", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteBool indicates an expected call of WriteBool. func (mr *MockTProtocolMockRecorder) WriteBool(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteBool", reflect.TypeOf((*MockTProtocol)(nil).WriteBool), arg0, arg1) } // WriteByte mocks base method. func (m *MockTProtocol) WriteByte(arg0 context.Context, arg1 int8) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteByte", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteByte indicates an expected call of WriteByte. func (mr *MockTProtocolMockRecorder) WriteByte(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteByte", reflect.TypeOf((*MockTProtocol)(nil).WriteByte), arg0, arg1) } // WriteDouble mocks base method. func (m *MockTProtocol) WriteDouble(arg0 context.Context, arg1 float64) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteDouble", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteDouble indicates an expected call of WriteDouble. func (mr *MockTProtocolMockRecorder) WriteDouble(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteDouble", reflect.TypeOf((*MockTProtocol)(nil).WriteDouble), arg0, arg1) } // WriteFieldBegin mocks base method. func (m *MockTProtocol) WriteFieldBegin(arg0 context.Context, arg1 string, arg2 thrift.TType, arg3 int16) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteFieldBegin", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) return ret0 } // WriteFieldBegin indicates an expected call of WriteFieldBegin. func (mr *MockTProtocolMockRecorder) WriteFieldBegin(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteFieldBegin", reflect.TypeOf((*MockTProtocol)(nil).WriteFieldBegin), arg0, arg1, arg2, arg3) } // WriteFieldEnd mocks base method. func (m *MockTProtocol) WriteFieldEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteFieldEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteFieldEnd indicates an expected call of WriteFieldEnd. func (mr *MockTProtocolMockRecorder) WriteFieldEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteFieldEnd", reflect.TypeOf((*MockTProtocol)(nil).WriteFieldEnd), arg0) } // WriteFieldStop mocks base method. func (m *MockTProtocol) WriteFieldStop(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteFieldStop", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteFieldStop indicates an expected call of WriteFieldStop. func (mr *MockTProtocolMockRecorder) WriteFieldStop(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteFieldStop", reflect.TypeOf((*MockTProtocol)(nil).WriteFieldStop), arg0) } // WriteI16 mocks base method. func (m *MockTProtocol) WriteI16(arg0 context.Context, arg1 int16) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteI16", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteI16 indicates an expected call of WriteI16. func (mr *MockTProtocolMockRecorder) WriteI16(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteI16", reflect.TypeOf((*MockTProtocol)(nil).WriteI16), arg0, arg1) } // WriteI32 mocks base method. func (m *MockTProtocol) WriteI32(arg0 context.Context, arg1 int32) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteI32", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteI32 indicates an expected call of WriteI32. func (mr *MockTProtocolMockRecorder) WriteI32(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteI32", reflect.TypeOf((*MockTProtocol)(nil).WriteI32), arg0, arg1) } // WriteI64 mocks base method. func (m *MockTProtocol) WriteI64(arg0 context.Context, arg1 int64) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteI64", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteI64 indicates an expected call of WriteI64. func (mr *MockTProtocolMockRecorder) WriteI64(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteI64", reflect.TypeOf((*MockTProtocol)(nil).WriteI64), arg0, arg1) } // WriteListBegin mocks base method. func (m *MockTProtocol) WriteListBegin(arg0 context.Context, arg1 thrift.TType, arg2 int) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteListBegin", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // WriteListBegin indicates an expected call of WriteListBegin. func (mr *MockTProtocolMockRecorder) WriteListBegin(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteListBegin", reflect.TypeOf((*MockTProtocol)(nil).WriteListBegin), arg0, arg1, arg2) } // WriteListEnd mocks base method. func (m *MockTProtocol) WriteListEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteListEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteListEnd indicates an expected call of WriteListEnd. func (mr *MockTProtocolMockRecorder) WriteListEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteListEnd", reflect.TypeOf((*MockTProtocol)(nil).WriteListEnd), arg0) } // WriteMapBegin mocks base method. func (m *MockTProtocol) WriteMapBegin(arg0 context.Context, arg1, arg2 thrift.TType, arg3 int) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteMapBegin", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) return ret0 } // WriteMapBegin indicates an expected call of WriteMapBegin. func (mr *MockTProtocolMockRecorder) WriteMapBegin(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteMapBegin", reflect.TypeOf((*MockTProtocol)(nil).WriteMapBegin), arg0, arg1, arg2, arg3) } // WriteMapEnd mocks base method. func (m *MockTProtocol) WriteMapEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteMapEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteMapEnd indicates an expected call of WriteMapEnd. func (mr *MockTProtocolMockRecorder) WriteMapEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteMapEnd", reflect.TypeOf((*MockTProtocol)(nil).WriteMapEnd), arg0) } // WriteMessageBegin mocks base method. func (m *MockTProtocol) WriteMessageBegin(arg0 context.Context, arg1 string, arg2 thrift.TMessageType, arg3 int32) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteMessageBegin", arg0, arg1, arg2, arg3) ret0, _ := ret[0].(error) return ret0 } // WriteMessageBegin indicates an expected call of WriteMessageBegin. func (mr *MockTProtocolMockRecorder) WriteMessageBegin(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteMessageBegin", reflect.TypeOf((*MockTProtocol)(nil).WriteMessageBegin), arg0, arg1, arg2, arg3) } // WriteMessageEnd mocks base method. func (m *MockTProtocol) WriteMessageEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteMessageEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteMessageEnd indicates an expected call of WriteMessageEnd. func (mr *MockTProtocolMockRecorder) WriteMessageEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteMessageEnd", reflect.TypeOf((*MockTProtocol)(nil).WriteMessageEnd), arg0) } // WriteSetBegin mocks base method. func (m *MockTProtocol) WriteSetBegin(arg0 context.Context, arg1 thrift.TType, arg2 int) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteSetBegin", arg0, arg1, arg2) ret0, _ := ret[0].(error) return ret0 } // WriteSetBegin indicates an expected call of WriteSetBegin. func (mr *MockTProtocolMockRecorder) WriteSetBegin(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteSetBegin", reflect.TypeOf((*MockTProtocol)(nil).WriteSetBegin), arg0, arg1, arg2) } // WriteSetEnd mocks base method. func (m *MockTProtocol) WriteSetEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteSetEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteSetEnd indicates an expected call of WriteSetEnd. func (mr *MockTProtocolMockRecorder) WriteSetEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteSetEnd", reflect.TypeOf((*MockTProtocol)(nil).WriteSetEnd), arg0) } // WriteString mocks base method. func (m *MockTProtocol) WriteString(arg0 context.Context, arg1 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteString", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteString indicates an expected call of WriteString. func (mr *MockTProtocolMockRecorder) WriteString(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteString", reflect.TypeOf((*MockTProtocol)(nil).WriteString), arg0, arg1) } // WriteStructBegin mocks base method. func (m *MockTProtocol) WriteStructBegin(arg0 context.Context, arg1 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteStructBegin", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteStructBegin indicates an expected call of WriteStructBegin. func (mr *MockTProtocolMockRecorder) WriteStructBegin(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteStructBegin", reflect.TypeOf((*MockTProtocol)(nil).WriteStructBegin), arg0, arg1) } // WriteStructEnd mocks base method. func (m *MockTProtocol) WriteStructEnd(arg0 context.Context) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteStructEnd", arg0) ret0, _ := ret[0].(error) return ret0 } // WriteStructEnd indicates an expected call of WriteStructEnd. func (mr *MockTProtocolMockRecorder) WriteStructEnd(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteStructEnd", reflect.TypeOf((*MockTProtocol)(nil).WriteStructEnd), arg0) } // WriteUUID mocks base method. func (m *MockTProtocol) WriteUUID(arg0 context.Context, arg1 thrift.Tuuid) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "WriteUUID", arg0, arg1) ret0, _ := ret[0].(error) return ret0 } // WriteUUID indicates an expected call of WriteUUID. func (mr *MockTProtocolMockRecorder) WriteUUID(arg0, arg1 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteUUID", reflect.TypeOf((*MockTProtocol)(nil).WriteUUID), arg0, arg1) } thrift-0.19.0/lib/go/test/tests/processor_middleware_test.go0000644000000000000000000000612014303740367024203 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "errors" "sync" "testing" "time" "github.com/apache/thrift/lib/go/test/gopath/src/processormiddlewaretest" "github.com/apache/thrift/lib/go/thrift" ) const errorMessage = "foo error" type serviceImpl struct{} func (serviceImpl) Ping(_ context.Context) (err error) { return &processormiddlewaretest.Error{ Foo: thrift.StringPtr(errorMessage), } } func middleware(t *testing.T) thrift.ProcessorMiddleware { return func(name string, next thrift.TProcessorFunction) thrift.TProcessorFunction { return thrift.WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out thrift.TProtocol) (_ bool, err thrift.TException) { defer func() { checkError(t, err) }() return next.Process(ctx, seqId, in, out) }, } } } func checkError(tb testing.TB, err error) { tb.Helper() var idlErr *processormiddlewaretest.Error if !errors.As(err, &idlErr) { tb.Errorf("expected error to be of type *processormiddlewaretest.Error, actual %T, %#v", err, err) return } if actual := idlErr.GetFoo(); actual != errorMessage { tb.Errorf("expected error message to be %q, actual %q", errorMessage, actual) } } func TestProcessorMiddleware(t *testing.T) { const timeout = time.Second processor := processormiddlewaretest.NewServiceProcessor(&serviceImpl{}) serverTransport, err := thrift.NewTServerSocket("127.0.0.1:0") if err != nil { t.Fatalf("Could not find available server port: %v", err) } server := thrift.NewTSimpleServer4( thrift.WrapProcessor(processor, middleware(t)), serverTransport, thrift.NewTHeaderTransportFactoryConf(nil, nil), thrift.NewTHeaderProtocolFactoryConf(nil), ) defer server.Stop() var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() server.Serve() }() time.Sleep(10 * time.Millisecond) cfg := &thrift.TConfiguration{ ConnectTimeout: timeout, SocketTimeout: timeout, } transport := thrift.NewTSocketFromAddrConf(serverTransport.Addr(), cfg) if err := transport.Open(); err != nil { t.Fatalf("Could not open client transport: %v", err) } defer transport.Close() protocol := thrift.NewTHeaderProtocolConf(transport, nil) client := processormiddlewaretest.NewServiceClient(thrift.NewTStandardClient(protocol, protocol)) err = client.Ping(context.Background()) checkError(t, err) } thrift-0.19.0/lib/go/test/tests/thrifttest_handler.go0000644000000000000000000001433414370300523022621 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "errors" "time" "github.com/apache/thrift/lib/go/test/gopath/src/thrifttest" "github.com/apache/thrift/lib/go/thrift" ) type SecondServiceHandler struct { } func NewSecondServiceHandler() *SecondServiceHandler { return &SecondServiceHandler{} } func (p *SecondServiceHandler) BlahBlah(ctx context.Context) (err error) { return nil } func (p *SecondServiceHandler) SecondtestString(ctx context.Context, thing string) (r string, err error) { return thing, nil } type ThriftTestHandler struct { } func NewThriftTestHandler() *ThriftTestHandler { return &ThriftTestHandler{} } func (p *ThriftTestHandler) TestVoid(ctx context.Context) (err error) { return nil } func (p *ThriftTestHandler) TestString(ctx context.Context, thing string) (r string, err error) { return thing, nil } func (p *ThriftTestHandler) TestBool(ctx context.Context, thing bool) (r bool, err error) { return thing, nil } func (p *ThriftTestHandler) TestByte(ctx context.Context, thing int8) (r int8, err error) { return thing, nil } func (p *ThriftTestHandler) TestI32(ctx context.Context, thing int32) (r int32, err error) { return thing, nil } func (p *ThriftTestHandler) TestI64(ctx context.Context, thing int64) (r int64, err error) { return thing, nil } func (p *ThriftTestHandler) TestDouble(ctx context.Context, thing float64) (r float64, err error) { return thing, nil } func (p *ThriftTestHandler) TestBinary(ctx context.Context, thing []byte) (r []byte, err error) { return thing, nil } func (p *ThriftTestHandler) TestUuid(ctx context.Context, thing thrift.Tuuid) (r thrift.Tuuid, err error) { return thing, nil } func (p *ThriftTestHandler) TestStruct(ctx context.Context, thing *thrifttest.Xtruct) (r *thrifttest.Xtruct, err error) { return thing, nil } func (p *ThriftTestHandler) TestNest(ctx context.Context, thing *thrifttest.Xtruct2) (r *thrifttest.Xtruct2, err error) { return thing, nil } func (p *ThriftTestHandler) TestMap(ctx context.Context, thing map[int32]int32) (r map[int32]int32, err error) { return thing, nil } func (p *ThriftTestHandler) TestStringMap(ctx context.Context, thing map[string]string) (r map[string]string, err error) { return thing, nil } func (p *ThriftTestHandler) TestSet(ctx context.Context, thing []int32) (r []int32, err error) { return thing, nil } func (p *ThriftTestHandler) TestList(ctx context.Context, thing []int32) (r []int32, err error) { return thing, nil } func (p *ThriftTestHandler) TestEnum(ctx context.Context, thing thrifttest.Numberz) (r thrifttest.Numberz, err error) { return thing, nil } func (p *ThriftTestHandler) TestTypedef(ctx context.Context, thing thrifttest.UserId) (r thrifttest.UserId, err error) { return thing, nil } func (p *ThriftTestHandler) TestMapMap(ctx context.Context, hello int32) (r map[int32]map[int32]int32, err error) { r = make(map[int32]map[int32]int32) pos := make(map[int32]int32) neg := make(map[int32]int32) for i := int32(1); i < 5; i++ { pos[i] = i neg[-i] = -i } r[4] = pos r[-4] = neg return r, nil } func (p *ThriftTestHandler) TestInsanity(ctx context.Context, argument *thrifttest.Insanity) (r map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity, err error) { hello := thrifttest.NewXtruct() hello.StringThing = "Hello2" hello.ByteThing = 2 hello.I32Thing = 2 hello.I64Thing = 2 goodbye := thrifttest.NewXtruct() goodbye.StringThing = "Goodbye4" goodbye.ByteThing = 4 goodbye.I32Thing = 4 goodbye.I64Thing = 4 crazy := thrifttest.NewInsanity() crazy.UserMap = make(map[thrifttest.Numberz]thrifttest.UserId) crazy.UserMap[thrifttest.Numberz_EIGHT] = 8 crazy.UserMap[thrifttest.Numberz_FIVE] = 5 crazy.Xtructs = []*thrifttest.Xtruct{goodbye, hello} first_map := make(map[thrifttest.Numberz]*thrifttest.Insanity) second_map := make(map[thrifttest.Numberz]*thrifttest.Insanity) first_map[thrifttest.Numberz_TWO] = crazy first_map[thrifttest.Numberz_THREE] = crazy looney := thrifttest.NewInsanity() second_map[thrifttest.Numberz_SIX] = looney var insane = make(map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity) insane[1] = first_map insane[2] = second_map return insane, nil } func (p *ThriftTestHandler) TestMulti(ctx context.Context, arg0 int8, arg1 int32, arg2 int64, arg3 map[int16]string, arg4 thrifttest.Numberz, arg5 thrifttest.UserId) (r *thrifttest.Xtruct, err error) { r = thrifttest.NewXtruct() r.StringThing = "Hello2" r.ByteThing = arg0 r.I32Thing = arg1 r.I64Thing = arg2 return r, nil } func (p *ThriftTestHandler) TestException(ctx context.Context, arg string) (err error) { if arg == "Xception" { x := thrifttest.NewXception() x.ErrorCode = 1001 x.Message = arg return x } else if arg == "TException" { return thrift.WrapTException(errors.New(arg)) } else { return nil } } func (p *ThriftTestHandler) TestMultiException(ctx context.Context, arg0 string, arg1 string) (r *thrifttest.Xtruct, err error) { if arg0 == "Xception" { x := thrifttest.NewXception() x.ErrorCode = 1001 x.Message = "This is an Xception" return nil, x } else if arg0 == "Xception2" { x2 := thrifttest.NewXception2() x2.ErrorCode = 2002 x2.StructThing = thrifttest.NewXtruct() x2.StructThing.StringThing = "This is an Xception2" return nil, x2 } res := thrifttest.NewXtruct() res.StringThing = arg1 return res, nil } func (p *ThriftTestHandler) TestOneway(ctx context.Context, secondsToSleep int32) (err error) { time.Sleep(time.Second * time.Duration(secondsToSleep)) return nil } thrift-0.19.0/lib/go/test/tests/protocols_test.go0000644000000000000000000000667714303740367022034 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "testing" "github.com/apache/thrift/lib/go/test/gopath/src/thrifttest" "github.com/apache/thrift/lib/go/thrift" ) func RunSocketTestSuite( t *testing.T, protocolFactory thrift.TProtocolFactory, transportFactory thrift.TTransportFactory, ) { // server var err error addr = FindAvailableTCPServerPort() serverTransport, err := thrift.NewTServerSocketTimeout(addr.String(), TIMEOUT) if err != nil { t.Fatal("Unable to create server socket", err) } processor := thrifttest.NewThriftTestProcessor(NewThriftTestHandler()) server = thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) server.Listen() go server.Serve() // client cfg := &thrift.TConfiguration{ ConnectTimeout: TIMEOUT, SocketTimeout: TIMEOUT, } thrift.PropagateTConfiguration(transportFactory, cfg) var transport thrift.TTransport = thrift.NewTSocketFromAddrConf(addr, cfg) transport, err = transportFactory.GetTransport(transport) if err != nil { t.Fatal(err) } var protocol thrift.TProtocol = protocolFactory.GetProtocol(transport) thriftTestClient := thrifttest.NewThriftTestClient(thrift.NewTStandardClient(protocol, protocol)) err = transport.Open() if err != nil { t.Fatal("Unable to open client socket", err) } driver := NewThriftTestDriver(t, thriftTestClient) driver.Start() } // Run test suite using TJSONProtocol func TestTJSONProtocol(t *testing.T) { RunSocketTestSuite( t, thrift.NewTJSONProtocolFactory(), thrift.NewTTransportFactory(), ) RunSocketTestSuite( t, thrift.NewTJSONProtocolFactory(), thrift.NewTBufferedTransportFactory(8912), ) RunSocketTestSuite( t, thrift.NewTJSONProtocolFactory(), thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), nil), ) } // Run test suite using TBinaryProtocol func TestTBinaryProtocol(t *testing.T) { RunSocketTestSuite( t, thrift.NewTBinaryProtocolFactoryConf(nil), thrift.NewTTransportFactory(), ) RunSocketTestSuite( t, thrift.NewTBinaryProtocolFactoryConf(nil), thrift.NewTBufferedTransportFactory(8912), ) RunSocketTestSuite( t, thrift.NewTBinaryProtocolFactoryConf(nil), thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), nil), ) } // Run test suite using TCompactBinaryProtocol func TestTCompactProtocol(t *testing.T) { RunSocketTestSuite( t, thrift.NewTCompactProtocolFactoryConf(nil), thrift.NewTTransportFactory(), ) RunSocketTestSuite( t, thrift.NewTCompactProtocolFactoryConf(nil), thrift.NewTBufferedTransportFactory(8912), ) RunSocketTestSuite( t, thrift.NewTCompactProtocolFactoryConf(nil), thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), nil), ) } thrift-0.19.0/lib/go/test/tests/thrifttest_driver.go0000644000000000000000000002163514303740367022513 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "reflect" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/thrifttest" ) type ThriftTestDriver struct { client thrifttest.ThriftTest t *testing.T } func NewThriftTestDriver(t *testing.T, client thrifttest.ThriftTest) *ThriftTestDriver { return &ThriftTestDriver{client, t} } func (p *ThriftTestDriver) Start() { client := p.client t := p.t if client.TestVoid(defaultCtx) != nil { t.Fatal("TestVoid failed") } if r, err := client.TestString(defaultCtx, "Test"); r != "Test" || err != nil { t.Fatal("TestString with simple text failed") } if r, err := client.TestString(defaultCtx, ""); r != "" || err != nil { t.Fatal("TestString with empty text failed") } stringTest := "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " + "Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, " + "БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, " + "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, " + "Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, " + "Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, " + "Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, " + "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " + "Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, " + "Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, " + "Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, " + "ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, " + "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " + "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa " + "Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa " + //lint:ignore ST1018 intentionally use unicode characters here "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" + //lint:ignore ST1018 intentionally use unicode characters here "Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, " + "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " + "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " + "РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " + "English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, " + "Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " + "Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, " + "Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " + "Bân-lâm-gú, 粵語" if r, err := client.TestString(defaultCtx, stringTest); r != stringTest || err != nil { t.Fatal("TestString with all languages failed") } specialCharacters := "quote: \" backslash:" + " backspace: \b formfeed: \f newline: \n return: \r tab: " + " now-all-of-them-together: '\\\b\n\r\t'" + " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><" + " char-to-test-json-parsing: ]] \"]] \\\" }}}{ [[[ " if r, err := client.TestString(defaultCtx, specialCharacters); r != specialCharacters || err != nil { t.Fatal("TestString with specialCharacters failed") } if r, err := client.TestByte(defaultCtx, 1); r != 1 || err != nil { t.Fatal("TestByte(1) failed") } if r, err := client.TestByte(defaultCtx, 0); r != 0 || err != nil { t.Fatal("TestByte(0) failed") } if r, err := client.TestByte(defaultCtx, -1); r != -1 || err != nil { t.Fatal("TestByte(-1) failed") } if r, err := client.TestByte(defaultCtx, -127); r != -127 || err != nil { t.Fatal("TestByte(-127) failed") } if r, err := client.TestI32(defaultCtx, -1); r != -1 || err != nil { t.Fatal("TestI32(-1) failed") } if r, err := client.TestI32(defaultCtx, 1); r != 1 || err != nil { t.Fatal("TestI32(1) failed") } if r, err := client.TestI64(defaultCtx, -5); r != -5 || err != nil { t.Fatal("TestI64(-5) failed") } if r, err := client.TestI64(defaultCtx, 5); r != 5 || err != nil { t.Fatal("TestI64(5) failed") } if r, err := client.TestI64(defaultCtx, -34359738368); r != -34359738368 || err != nil { t.Fatal("TestI64(-34359738368) failed") } if r, err := client.TestDouble(defaultCtx, -5.2098523); r != -5.2098523 || err != nil { t.Fatal("TestDouble(-5.2098523) failed") } if r, err := client.TestDouble(defaultCtx, -7.012052175215044); r != -7.012052175215044 || err != nil { t.Fatal("TestDouble(-7.012052175215044) failed") } // TODO: add testBinary() call out := thrifttest.NewXtruct() out.StringThing = "Zero" out.ByteThing = 1 out.I32Thing = -3 out.I64Thing = 1000000 if r, err := client.TestStruct(defaultCtx, out); !reflect.DeepEqual(r, out) || err != nil { t.Fatal("TestStruct failed") } out2 := thrifttest.NewXtruct2() out2.ByteThing = 1 out2.StructThing = out out2.I32Thing = 5 if r, err := client.TestNest(defaultCtx, out2); !reflect.DeepEqual(r, out2) || err != nil { t.Fatal("TestNest failed") } mapout := make(map[int32]int32) for i := int32(0); i < 5; i++ { mapout[i] = i - 10 } if r, err := client.TestMap(defaultCtx, mapout); !reflect.DeepEqual(r, mapout) || err != nil { t.Fatal("TestMap failed") } mapTestInput := map[string]string{ "a": "123", "a b": "with spaces ", "same": "same", "0": "numeric key", "longValue": stringTest, stringTest: "long key", } if r, err := client.TestStringMap(defaultCtx, mapTestInput); !reflect.DeepEqual(r, mapTestInput) || err != nil { t.Fatal("TestStringMap failed") } setTestInput := []int32{1, 2, 3} if r, err := client.TestSet(defaultCtx, setTestInput); !reflect.DeepEqual(r, setTestInput) || err != nil { t.Fatal("TestSet failed") } listTest := []int32{1, 2, 3} if r, err := client.TestList(defaultCtx, listTest); !reflect.DeepEqual(r, listTest) || err != nil { t.Fatal("TestList failed") } if r, err := client.TestEnum(defaultCtx, thrifttest.Numberz_ONE); r != thrifttest.Numberz_ONE || err != nil { t.Fatal("TestEnum failed") } if r, err := client.TestTypedef(defaultCtx, 69); r != 69 || err != nil { t.Fatal("TestTypedef failed") } mapMapTest := map[int32]map[int32]int32{ 4: {1: 1, 2: 2, 3: 3, 4: 4}, -4: {-4: -4, -3: -3, -2: -2, -1: -1}, } if r, err := client.TestMapMap(defaultCtx, 1); !reflect.DeepEqual(r, mapMapTest) || err != nil { t.Fatal("TestMapMap failed") } crazyX1 := thrifttest.NewXtruct() crazyX1.StringThing = "Goodbye4" crazyX1.ByteThing = 4 crazyX1.I32Thing = 4 crazyX1.I64Thing = 4 crazyX2 := thrifttest.NewXtruct() crazyX2.StringThing = "Hello2" crazyX2.ByteThing = 2 crazyX2.I32Thing = 2 crazyX2.I64Thing = 2 crazy := thrifttest.NewInsanity() crazy.UserMap = map[thrifttest.Numberz]thrifttest.UserId{5: 5, 8: 8} crazy.Xtructs = []*thrifttest.Xtruct{crazyX1, crazyX2} crazyEmpty := thrifttest.NewInsanity() crazyEmpty.UserMap = map[thrifttest.Numberz]thrifttest.UserId{} crazyEmpty.Xtructs = []*thrifttest.Xtruct{} insanity := map[thrifttest.UserId]map[thrifttest.Numberz]*thrifttest.Insanity{ 1: {thrifttest.Numberz_TWO: crazy, thrifttest.Numberz_THREE: crazy}, 2: {thrifttest.Numberz_SIX: crazyEmpty}, } if r, err := client.TestInsanity(defaultCtx, crazy); !reflect.DeepEqual(r, insanity) || err != nil { t.Fatal("TestInsanity failed:", err) } if err := client.TestException(defaultCtx, "TException"); err == nil { t.Fatal("TestException TException failed:", err) } err := client.TestException(defaultCtx, "Xception") if e, ok := err.(*thrifttest.Xception); !ok || e == nil { t.Fatal("TestException Xception failed:", err) } else if e.ErrorCode != 1001 || e.Message != "Xception" { t.Fatal("TestException Xception failed:", e) } if err := client.TestException(defaultCtx, "no Exception"); err != nil { t.Fatal("TestException no Exception failed:", err) } if err := client.TestOneway(defaultCtx, 0); err != nil { t.Fatal("TestOneway failed:", err) } } thrift-0.19.0/lib/go/test/tests/json_protocol_deserializer_test.go0000644000000000000000000000374214303740367025432 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "context" "testing" "testing/quick" "github.com/apache/thrift/lib/go/test/gopath/src/thrifttest" "github.com/apache/thrift/lib/go/thrift" ) func TestDeserializerPoolJSONProtocol(t *testing.T) { ctx := context.Background() serializerPool := thrift.NewTSerializerPoolSizeFactory(1024, thrift.NewTJSONProtocolFactory()) msg := &thrifttest.Bonk{ Message: "foo", Type: 42, } valid, err := serializerPool.WriteString(ctx, msg) if err != nil { t.Fatal(err) } invalid := valid[:len(valid)-2] deserializerPool := thrift.NewTDeserializerPoolSizeFactory(1024, thrift.NewTJSONProtocolFactory()) msg = new(thrifttest.Bonk) if err := deserializerPool.ReadString(ctx, msg, invalid); err == nil { t.Fatalf("Deserializing %q did not fail", invalid) } f := func() bool { msg := new(thrifttest.Bonk) if err := deserializerPool.ReadString(ctx, msg, valid); err != nil { t.Errorf("Deserializing string %q failed with %v", valid, err) } if err := deserializerPool.Read(ctx, msg, []byte(valid)); err != nil { t.Errorf("Deserializing bytes %q failed with %v", valid, err) } return !t.Failed() } if err := quick.Check(f, nil); err != nil { t.Error(err) } } thrift-0.19.0/lib/go/test/tests/struct_args_rets_test.go0000644000000000000000000000235014303740367023365 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( st "github.com/apache/thrift/lib/go/test/gopath/src/servicestest" ) // This function is never called, it will fail to compile if check is failed // //lint:ignore U1000 see above ^ func staticCheckStructArgsResults() { //Check that struct args and results are passed by reference var sa *st.StructA = &st.StructA{} var iface st.AServ var err error sa, err = iface.StructAFunc_1structA(defaultCtx, sa) _ = err _ = sa } thrift-0.19.0/lib/go/test/tests/union_binary_test.go0000644000000000000000000000223514303740367022466 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "testing" "github.com/apache/thrift/lib/go/test/gopath/src/unionbinarytest" ) // See https://issues.apache.org/jira/browse/THRIFT-4573 func TestUnionBinary(t *testing.T) { s := unionbinarytest.NewSample() s.U1 = map[string]string{} s.U2 = []byte{} if n := s.CountSetFieldsSample(); n != 2 { t.Errorf("Expected 2 set fields, got %d!", n) } } thrift-0.19.0/lib/go/test/tests/ignoreinitialisms_test.go0000644000000000000000000000273014303740367023523 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package tests import ( "reflect" "testing" "github.com/apache/thrift/lib/go/test/gopath/src/ignoreinitialismstest" ) func TestIgnoreInitialismsFlagIsHonoured(t *testing.T) { s := ignoreinitialismstest.IgnoreInitialismsTest{} st := reflect.TypeOf(s) _, ok := st.FieldByName("Id") if !ok { t.Error("Id attribute is missing!") } _, ok = st.FieldByName("MyId") if !ok { t.Error("MyId attribute is missing!") } _, ok = st.FieldByName("NumCpu") if !ok { t.Error("NumCpu attribute is missing!") } _, ok = st.FieldByName("NumGpu") if !ok { t.Error("NumGpu attribute is missing!") } _, ok = st.FieldByName("My_ID") if !ok { t.Error("My_ID attribute is missing!") } } thrift-0.19.0/lib/go/test/NamesTest.thrift0000644000000000000000000000164714303740367020375 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct NamesTest { 1: required string type } service NameCollisionOne { void blahBlah() } service NameCollisionTwo { void blahBlah() } thrift-0.19.0/lib/go/test/InitialismsTest.thrift0000644000000000000000000000156114303740367021612 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct InitialismsTest { 1: string user_id, 2: string server_url, 3: string id, } thrift-0.19.0/lib/go/test/NamespacedTest.thrift0000644000000000000000000000202214303740367021356 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include "ThriftTest.thrift" namespace go lib.go.test.namespacedtest enum Stuff { ONE = 1, TWO = 2, } const i32 THREE = 3; typedef i64 UserId struct StuffStruct { 2: Stuff stuff, } service NamespacedService { ThriftTest.UserId getUserID(), } thrift-0.19.0/lib/go/test/EqualsTest.thrift0000644000000000000000000001170514370300523020546 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ typedef i8 mybyte typedef string mystr typedef binary mybin typedef uuid myuuid enum EnumFoo { e1 e2 } struct BasicEqualsFoo { 1: bool BoolFoo, 2: optional bool OptBoolFoo, 3: i8 I8Foo, 4: optional i8 OptI8Foo, 5: i16 I16Foo, 6: optional i16 OptI16Foo, 7: i32 I32Foo, 8: optional i32 OptI32Foo, 9: i64 I64Foo, 10: optional i64 OptI64Foo, 11: double DoubleFoo, 12: optional double OptDoubleFoo, 13: string StrFoo, 14: optional string OptStrFoo, 15: binary BinFoo, 16: optional binary OptBinFoo, 17: EnumFoo EnumFoo, 18: optional EnumFoo OptEnumFoo, 19: mybyte MyByteFoo, 20: optional mybyte OptMyByteFoo, 21: mystr MyStrFoo, 22: optional mystr OptMyStrFoo, 23: mybin MyBinFoo, 24: optional mybin OptMyBinFoo, 25: uuid UUIDFoo, 26: optional uuid OptUUIDFoo, 27: myuuid MyUUIDFoo, 28: optional myuuid OptMyUUIDFoo, } struct StructEqualsFoo { 1: BasicEqualsFoo StructFoo, 2: optional BasicEqualsFoo OptStructFoo, } struct ListEqualsFoo { 1: list I64ListFoo, 2: optional list OptI64ListFoo, 3: list StrListFoo, 4: optional list OptStrListFoo, 5: list BinListFoo, 6: optional list OptBinListFoo, 7: list StructListFoo, 8: optional list OptStructListFoo, 9: list> I64ListListFoo, 10: optional list> OptI64ListListFoo, 11: list> I64SetListFoo, 12: optional list> OptI64SetListFoo, 13: list> I64StringMapListFoo, 14: optional list> OptI64StringMapListFoo, 15: list MyByteListFoo, 16: optional list OptMyByteListFoo, 17: list MyStrListFoo, 18: optional list OptMyStrListFoo, 19: list MyBinListFoo, 20: optional list OptMyBinListFoo, 21: list UUIDListFoo, 22: optional list OptUUIDListFoo, 23: list MyUUIDListFoo, 24: optional list OptMyUUIDListFoo, } struct SetEqualsFoo { 1: set I64SetFoo, 2: optional set OptI64SetFoo, 3: set StrSetFoo, 4: optional set OptStrSetFoo, 5: set BinSetFoo, 6: optional set OptBinSetFoo, 7: set StructSetFoo, 8: optional set OptStructSetFoo, 9: set> I64ListSetFoo, 10: optional set> OptI64ListSetFoo, 11: set> I64SetSetFoo, 12: optional set> OptI64SetSetFoo, 13: set> I64StringMapSetFoo, 14: optional set> OptI64StringMapSetFoo, 15: set MyByteSetFoo, 16: optional set OptMyByteSetFoo, 17: set MyStrSetFoo, 18: optional set OptMyStrSetFoo, 19: set MyBinSetFoo, 20: optional set OptMyBinSetFoo, 21: set UUIDSetFoo, 22: optional set OptUUIDSetFoo, 23: set MyUUIDSetFoo, 24: optional set OptMyUUIDSetFoo, } struct MapEqualsFoo { 1: map I64StrMapFoo, 2: optional map OptI64StrMapFoo, 3: map StrI64MapFoo, 4: optional map OptStrI64MapFoo, 5: map StructBinMapFoo, 6: optional map OptStructBinMapFoo, 7: map BinStructMapFoo, 8: optional map OptBinStructMapFoo, 9: map> I64I64ListMapFoo, 10: optional map> OptI64I64ListMapFoo, 11: map> I64I64SetMapFoo, 12: optional map> OptI64I64SetMapFoo, 13: map> I64I64StringMapMapFoo, 14: optional map> OptI64I64StringMapMapFoo, 15: map MyStrMyBinMapFoo, 16: optional map OptMyStrMyBinMapFoo, 17: map Int64MyByteMapFoo, 18: optional map OptInt64MyByteMapFoo, 19: map MyByteInt64MapFoo, 20: optional map OptMyByteInt64MapFoo, 21: map UUIDMapFoo, 22: optional map OptUUIDMapFoo, 23: map MyUUIDMapFoo, 24: optional map OptMyUUIDMapFoo, } thrift-0.19.0/lib/go/test/Makefile.am0000644000000000000000000001453114452237057017302 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # GOBUILDEXTRA = -buildvcs=false THRIFT_GO_ARGS_BASE = thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/lib/go/test/gopath/src/ THRIFTARGS = -out gopath/src/ --gen go:$(THRIFT_GO_ARGS_BASE)$(COMPILER_EXTRAFLAG) THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift THRIFTARGS_SKIP_REMOTE = -out gopath/src/ --gen go:skip_remote,$(THRIFT_GO_ARGS_BASE)$(COMPILER_EXTRAFLAG) # Thrift for GO has problems with complex map keys: THRIFT-2063 gopath: $(THRIFT) $(THRIFTTEST) \ IncludesTest.thrift \ NamespacedTest.thrift \ MultiplexedProtocolTest.thrift \ OnewayTest.thrift \ OptionalFieldsTest.thrift \ RequiredFieldTest.thrift \ ServicesTest.thrift \ GoTagTest.thrift \ TypedefFieldTest.thrift \ RefAnnotationFieldsTest.thrift \ UnionDefaultValueTest.thrift \ UnionBinaryTest.thrift \ ErrorTest.thrift \ NamesTest.thrift \ InitialismsTest.thrift \ DontExportRWTest.thrift \ dontexportrwtest/compile_test.go \ IgnoreInitialismsTest.thrift \ ConflictNamespaceTestA.thrift \ ConflictNamespaceTestB.thrift \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ ConflictNamespaceTestE.thrift \ ConflictNamespaceTestF.thrift \ ConflictNamespaceTestSuperThing.thrift \ ConflictNamespaceServiceTest.thrift \ DuplicateImportsTest.thrift \ EqualsTest.thrift \ ConflictArgNamesTest.thrift \ ConstOptionalFieldImport.thrift \ ConstOptionalField.thrift \ ProcessorMiddlewareTest.thrift \ ClientMiddlewareExceptionTest.thrift \ ValidateTest.thrift \ ForwardType.thrift mkdir -p gopath/src grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set' > ThriftTest.thrift $(THRIFT) $(THRIFTARGS) -r IncludesTest.thrift $(THRIFT) $(THRIFTARGS) BinaryKeyTest.thrift $(THRIFT) $(THRIFTARGS) MultiplexedProtocolTest.thrift $(THRIFT) $(THRIFTARGS) OnewayTest.thrift $(THRIFT) $(THRIFTARGS) OptionalFieldsTest.thrift $(THRIFT) $(THRIFTARGS) RequiredFieldTest.thrift $(THRIFT) $(THRIFTARGS) ServicesTest.thrift $(THRIFT) $(THRIFTARGS) GoTagTest.thrift $(THRIFT) $(THRIFTARGS) TypedefFieldTest.thrift $(THRIFT) $(THRIFTARGS) RefAnnotationFieldsTest.thrift $(THRIFT) $(THRIFTARGS) UnionDefaultValueTest.thrift $(THRIFT) $(THRIFTARGS) UnionBinaryTest.thrift $(THRIFT) $(THRIFTARGS) ErrorTest.thrift $(THRIFT) $(THRIFTARGS) NamesTest.thrift $(THRIFT) $(THRIFTARGS) InitialismsTest.thrift $(THRIFT) $(THRIFTARGS),read_write_private DontExportRWTest.thrift $(THRIFT) $(THRIFTARGS),ignore_initialisms IgnoreInitialismsTest.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestA.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestB.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestC.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestD.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestE.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestF.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestSuperThing.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceServiceTest.thrift $(THRIFT) $(THRIFTARGS) -r DuplicateImportsTest.thrift $(THRIFT) $(THRIFTARGS) EqualsTest.thrift $(THRIFT) $(THRIFTARGS) ConflictArgNamesTest.thrift $(THRIFT) $(THRIFTARGS) -r ConstOptionalField.thrift $(THRIFT) $(THRIFTARGS_SKIP_REMOTE) ProcessorMiddlewareTest.thrift $(THRIFT) $(THRIFTARGS) ClientMiddlewareExceptionTest.thrift $(THRIFT) $(THRIFTARGS) ValidateTest.thrift $(THRIFT) $(THRIFTARGS) ForwardType.thrift ln -nfs ../../tests gopath/src/tests cp -r ./dontexportrwtest gopath/src touch gopath check: gopath $(GO) build $(GOBUILDEXTRA) \ ./gopath/src/includestest \ ./gopath/src/binarykeytest \ ./gopath/src/servicestest \ ./gopath/src/typedeffieldtest \ ./gopath/src/refannotationfieldstest \ ./gopath/src/errortest \ ./gopath/src/namestest \ ./gopath/src/initialismstest \ ./gopath/src/dontexportrwtest \ ./gopath/src/ignoreinitialismstest \ ./gopath/src/unionbinarytest \ ./gopath/src/conflict/super \ ./gopath/src/conflict/context/conflict_service-remote \ ./gopath/src/servicestest/container_test-remote \ ./gopath/src/duplicateimportstest \ ./gopath/src/equalstest \ ./gopath/src/conflictargnamestest \ ./gopath/src/processormiddlewaretest \ ./gopath/src/clientmiddlewareexceptiontest \ ./gopath/src/validatetest \ ./gopath/src/forwardtypetest $(GO) test github.com/apache/thrift/lib/go/thrift $(GO) test ./gopath/src/tests ./gopath/src/dontexportrwtest clean-local: $(RM) -r gopath ThriftTest.thrift gen-go client: stubs $(GO) run TestClient.go EXTRA_DIST = \ dontexportrwtest \ tests \ common \ BinaryKeyTest.thrift \ ClientMiddlewareExceptionTest.thrift \ ConflictArgNamesTest.thrift \ ConflictNamespaceServiceTest.thrift \ ConflictNamespaceTestA.thrift \ ConflictNamespaceTestB.thrift \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ ConflictNamespaceTestE.thrift \ ConflictNamespaceTestF.thrift \ ConflictNamespaceTestSuperThing.thrift \ ConstOptionalField.thrift \ ConstOptionalFieldImport.thrift \ DontExportRWTest.thrift \ DuplicateImportsTest.thrift \ ErrorTest.thrift \ EqualsTest.thrift \ ForwardType.thrift \ GoTagTest.thrift \ IgnoreInitialismsTest.thrift \ IncludesTest.thrift \ InitialismsTest.thrift \ MultiplexedProtocolTest.thrift \ NamespacedTest.thrift \ NamesTest.thrift \ OnewayTest.thrift \ OptionalFieldsTest.thrift \ ProcessorMiddlewareTest.thrift \ RefAnnotationFieldsTest.thrift \ RequiredFieldTest.thrift \ ServicesTest.thrift \ TypedefFieldTest.thrift \ UnionBinaryTest.thrift \ UnionDefaultValueTest.thrift \ ValidateTest.thrift thrift-0.19.0/lib/go/test/RefAnnotationFieldsTest.thrift0000644000000000000000000000420014303740367023214 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct structA { 1: required i64 sa_i } struct all_referenced { 1: optional string s = "DEFAULT" (cpp.ref = ""), 2: optional i64 i = 42 (cpp.ref = ""), 3: optional bool b = false (cpp.ref = ""), 4: optional string s2 (cpp.ref = ""), 5: optional i64 i2 (cpp.ref = ""), 6: optional bool b2 (cpp.ref = ""), 7: optional structA aa (cpp.ref = ""), 9: optional list l (cpp.ref = ""), 10: optional list l2 = [1, 2] (cpp.ref = ""), 11: optional map m (cpp.ref = ""), 12: optional map m2 = {1:2, 3:4} (cpp.ref = ""), 13: optional binary bin (cpp.ref = ""), 14: optional binary bin2 = "asdf" (cpp.ref = ""), 15: required string ref_s = "DEFAULT" (cpp.ref = ""), 16: required i64 ref_i = 42 (cpp.ref = ""), 17: required bool ref_b = false (cpp.ref = ""), 18: required string ref_s2 (cpp.ref = ""), 19: required i64 ref_i2 (cpp.ref = ""), 20: required bool ref_b2 (cpp.ref = ""), 21: required structA ref_aa (cpp.ref = ""), 22: required list ref_l (cpp.ref = ""), 23: required list ref_l2 = [1, 2] (cpp.ref = ""), 24: required map ref_m (cpp.ref = ""), 25: required map ref_m2 = {1:2, 3:4} (cpp.ref = ""), 26: required binary ref_bin (cpp.ref = ""), 27: required binary ref_bin2 = "asdf" (cpp.ref = ""), } struct structB { 1: required structA required_struct_thing 2: optional structA optional_struct_thing } thrift-0.19.0/lib/go/test/ConstOptionalFieldImport.thrift0000644000000000000000000000212614303740367023416 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace go constoptionalfielda enum Foo { One = 1, Two = 2, } typedef Foo TypedefAFoo typedef bool TypedefABool typedef i8 TypedefAI8 typedef i16 TypedefAI16 typedef i32 TypedefAI32 typedef i64 TypedefAI64 typedef double TypedefADouble typedef string TypedefAString typedef binary TypedefABinary thrift-0.19.0/lib/go/test/ConflictNamespaceTestC.thrift0000644000000000000000000000151014303740367023000 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go common struct ThingC { 1: bool value } thrift-0.19.0/lib/go/test/ConflictNamespaceTestE.thrift0000644000000000000000000000152214303740367023005 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflicte.driver struct ThingE { 1: bool value } thrift-0.19.0/lib/go/test/ClientMiddlewareExceptionTest.thrift0000644000000000000000000000214614303740367024420 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ exception Exception1 { } exception Exception2 { } // This is a special case, we want to make sure that the middleware don't // accidentally pull result as error. exception FooResponse { } service ClientMiddlewareExceptionTest { FooResponse foo() throws( 1: Exception1 error1, 2: Exception2 error2, ) } thrift-0.19.0/lib/go/test/ConflictArgNamesTest.thrift0000644000000000000000000000222114303740367022476 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ service ConflictArgNamesTest { /** * Use some names that could conflict with the compiler code as args * to make sure that the compiler handled them correctly. */ void testNameConflicts( // 1: string args, // args is already a reserved keyword in thrift compiler 2: string result, 3: string meta, 4: string r, 5: string err, ) } thrift-0.19.0/lib/go/test/DuplicateImportsTest.thrift0000644000000000000000000000156614370300523022610 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ include "common/a.thrift" include "common/b.thrift" typedef a.A A typedef b.B B thrift-0.19.0/lib/go/test/dontexportrwtest/0000777000000000000000000000000014303740367020723 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/test/dontexportrwtest/compile_test.go0000644000000000000000000000222614303740367023737 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package dontexportrwtest import ( "testing" ) // Make sure that thrift generates non-exported read/write methods if // read_write_private option is specified func TestReadWriteMethodsArePrivate(t *testing.T) { // This will only compile if read/write methods exist s := NewTestStruct() _ = s.read _ = s.write is := NewInnerStruct() _ = is.read _ = is.write } thrift-0.19.0/lib/go/test/UnionDefaultValueTest.thrift0000644000000000000000000000174114303740367022717 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct Option1 { } struct Option2 { 1: optional string name } union Descendant { 1: Option1 option1 2: Option2 option2 } struct TestStruct { 1: optional Descendant descendant = { "option1": {}} } thrift-0.19.0/lib/go/test/OnewayTest.thrift0000644000000000000000000000160314303740367020564 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # service OneWay { oneway void hi(1: i64 i, 2: string s) void emptyfunc() i64 echo_int(1: i64 param) } thrift-0.19.0/lib/go/test/MultiplexedProtocolTest.thrift0000644000000000000000000000154314303740367023343 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # service First { i64 returnOne(); } service Second { i64 returnTwo(); } thrift-0.19.0/lib/go/test/GoTagTest.thrift0000644000000000000000000000174314303740367020330 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct tagged { 1: string string_thing, 2: i64 int_thing (go.tag = "json:\"custom_thing\" mykey:\"myvalue\""), 3: optional i64 optional_int_thing 4: optional bool optional_bool_thing = false } thrift-0.19.0/lib/go/test/common/0000777000000000000000000000000014370300523016522 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/test/common/a.thrift0000644000000000000000000000154014370300523020160 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace go common struct A { 1: optional string a } thrift-0.19.0/lib/go/test/common/b.thrift0000644000000000000000000000154014370300523020161 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace go common struct B { 1: optional string b } thrift-0.19.0/lib/go/test/BinaryKeyTest.thrift0000644000000000000000000000162714303740367021225 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Make sure that thrift produce compilable code for binary key struct testStruct { 1: required map bin_to_string } thrift-0.19.0/lib/go/test/ConflictNamespaceTestD.thrift0000644000000000000000000000152314303740367023005 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflictd.context struct ThingD { 1: bool value } thrift-0.19.0/lib/go/test/ConflictNamespaceTestSuperThing.thrift0000644000000000000000000000262714303740367024720 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflict.super include "ConflictNamespaceTestA.thrift" include "ConflictNamespaceTestB.thrift" include "ConflictNamespaceTestC.thrift" include "ConflictNamespaceTestD.thrift" include "ConflictNamespaceTestE.thrift" include "ConflictNamespaceTestF.thrift" struct SuperThing { 1: ConflictNamespaceTestA.ThingA thing_a 2: ConflictNamespaceTestB.ThingB thing_b 3: ConflictNamespaceTestC.ThingC thing_c 4: ConflictNamespaceTestD.ThingD thing_d 5: ConflictNamespaceTestE.ThingE thing_e 6: ConflictNamespaceTestF.ThingF thing_f } // Define an enum to force the import of database/sql/driver enum Enum { One = 1 Two = 2 } thrift-0.19.0/lib/go/test/ConstOptionalField.thrift0000644000000000000000000000562014303740367022225 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace go constoptionalfieldb include "ConstOptionalFieldImport.thrift" typedef ConstOptionalFieldImport.Foo TypedefBFoo typedef bool TypedefBBool typedef i8 TypedefBI8 typedef i16 TypedefBI16 typedef i32 TypedefBI32 typedef i64 TypedefBI64 typedef double TypedefBDouble typedef string TypedefBString typedef binary TypedefBBinary struct Bar { 1: optional ConstOptionalFieldImport.Foo optFoo, 2: optional ConstOptionalFieldImport.TypedefAFoo aFoo, 3: optional TypedefBFoo bFoo, 4: optional bool optBool, 5: optional ConstOptionalFieldImport.TypedefABool aBool, 6: optional TypedefBBool bBool, 7: optional i8 optI8, 8: optional ConstOptionalFieldImport.TypedefAI8 aI8, 9: optional TypedefBI8 bI8, 10: optional i16 optI16, 11: optional ConstOptionalFieldImport.TypedefAI16 aI16, 12: optional TypedefBI16 bI16, 13: optional i32 optI32, 14: optional ConstOptionalFieldImport.TypedefAI32 aI32, 15: optional TypedefBI32 bI32, 16: optional i64 optI64, 17: optional ConstOptionalFieldImport.TypedefAI64 aI64, 18: optional TypedefBI64 bI64, 19: optional double optDouble, 20: optional ConstOptionalFieldImport.TypedefADouble aDouble, 21: optional TypedefBDouble bDouble, 22: optional string optString, 23: optional ConstOptionalFieldImport.TypedefAString aString, 24: optional TypedefBString bString, 25: optional binary optBinary, 26: optional ConstOptionalFieldImport.TypedefABinary aBinary, 27: optional TypedefBBinary bBinary, } const list CONSTANTS = [ { "optFoo": ConstOptionalFieldImport.Foo.One, "aFoo": ConstOptionalFieldImport.Foo.One, "bFoo": ConstOptionalFieldImport.Foo.One, "optBool": true, "aBool": true, "bBool": true, "optI8": 8, "aI8": 8, "bI8": 8, "optI16": 16, "aI16": 16, "bI16": 16, "optI32": 32, "aI32": 32, "bI32": 32, "optI64": 64, "aI64": 64, "bI64": 64, "optDouble": 1234, "aDouble": 1234, "bDouble": 1234, "optString": "string", "aString": "string", "bString": "string", "optBinary": "binary", "aBinary": "binary", "bBinary": "binary", }, ] thrift-0.19.0/lib/go/test/TypedefFieldTest.thrift0000644000000000000000000000224614303740367021672 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # We are only testing that generated code compiles, no correctness checking is done enum Details { Everything = 0 StateOnly = 1 StateAndOptions = 2 SomethingElse = 3 } typedef list< Details> DetailsWanted struct BaseRequest { 1 : optional string RequestID } struct GetMyDetails { 1 : required BaseRequest base_ 2 : required string ObjectID 3 : optional DetailsWanted DetailsWanted } thrift-0.19.0/lib/go/test/IncludesTest.thrift0000644000000000000000000000363614303740367021100 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include "ThriftTest.thrift" include "NamespacedTest.thrift" const ThriftTest.UserId USERID = 42 const NamespacedTest.UserId USERID1 = 41 const ThriftTest.MapType MAPCONSTANT = {'hello':{}, 'goodnight':{}} const i32 TWO = NamespacedTest.Stuff.TWO const i32 THREE = NamespacedTest.THREE struct testStruct { 1: list listNumbers } struct TestStruct2 { 1: testStruct blah, 2: ThriftTest.UserId id, 3: NamespacedTest.Stuff stuff, } service testService extends ThriftTest.SecondService { ThriftTest.CrazyNesting getCrazyNesting( 1: ThriftTest.StructA a, 2: ThriftTest.Numberz numbers ) throws(1: ThriftTest.Xception err1), void getSomeValue_DO_NOT_CALL(), } service ExtendedService extends testService { void extendedMethod(), NamespacedTest.StuffStruct extendedMethod2(), } service Extended2Service extends NamespacedTest.NamespacedService { void extendedMethod3(), } typedef map > > ComplexMapType struct ComplexMapStruct { 1: ComplexMapType complex, } service ComplexMapService { ComplexMapStruct transformMap(1: ComplexMapStruct input), } thrift-0.19.0/lib/go/test/ProcessorMiddlewareTest.thrift0000644000000000000000000000206114303740367023276 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ exception Error { 1: optional string foo, } service Service { void ping() throws ( 1: Error error, ); } thrift-0.19.0/lib/go/test/RequiredFieldTest.thrift0000644000000000000000000000160714370300523022040 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct RequiredField { 1: required string name } struct OtherThing { 1: required i16 value } thrift-0.19.0/lib/go/test/OptionalFieldsTest.thrift0000644000000000000000000000263714303740367022246 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct structA { 1: required i64 sa_i } struct all_optional { 1: optional string s = "DEFAULT", 2: optional i64 i = 42, 3: optional bool b = false, 4: optional string s2, 5: optional i64 i2, 6: optional bool b2, 7: optional structA aa, 9: optional list l, 10: optional list l2 = [1, 2], 11: optional map m, 12: optional map m2 = {1:2, 3:4}, 13: optional binary bin, 14: optional binary bin2 = "asdf", } struct structB { 1: required structA required_struct_thing 2: optional structA optional_struct_thing } struct structC { 1: string s, 2: required i32 i, 3: optional bool b, 4: required string s2, } thrift-0.19.0/lib/go/test/ValidateTest.thrift0000644000000000000000000001711514370300523021046 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace go validatetest enum EnumFoo { e1 e2 } struct Foo { 1: bool Bool } struct BasicTest { 1: bool Bool0 = true (vt.const = "true") 2: optional bool Bool1 (vt.const = "true") 3: i8 Byte0 = 1 (vt.lt = "2", vt.le = "2", vt.gt = "0", vt.ge = "0", vt.in = "[0, 1, 2]", vt.not_in = "[3, 4, 5]") 4: optional i8 Byte1 (vt.lt = "1", vt.le = "1", vt.gt = "-1", vt.ge = "-1", vt.in = "[-1, 0, 1]", vt.not_in = "[1, 2, 3]") 5: double Double0 = 1.0 (vt.lt = "2.0", vt.le = "2.0", vt.gt = "0", vt.ge = "0", vt.in = "[0, 1.0, 2.0]", vt.not_in = "[3.0, 4.0, 5.0]") 6: optional double Double1 (vt.lt = "2.0", vt.le = "2.0", vt.gt = "0", vt.ge = "0", vt.in = "[0, 1.0, 2.0]", vt.not_in = "[3.0, 4.0, 5.0]") 7: string String0 = "my const string" (vt.const = "my const string", vt.min_size = "0", vt.max_size = "100", vt.pattern = ".*", vt.prefix = "my", vt.suffix = "string", vt.contains = "const", vt.not_contains = "oh") 8: optional string String1 (vt.const = "my const string", vt.min_size = "0", vt.max_size = "100", vt.pattern = ".*", vt.prefix = "my", vt.suffix = "string", vt.contains = "const", vt.not_contains = "oh") 9: binary Binary0 = "my const string" (vt.const = "my const string", vt.min_size = "0", vt.max_size = "100", vt.pattern = ".*", vt.prefix = "my", vt.suffix = "string", vt.contains = "const", vt.not_contains = "oh") 10: optional binary Binary1 = "my const string" (vt.const = "my const string", vt.min_size = "0", vt.max_size = "100", vt.pattern = ".*", vt.prefix = "my", vt.suffix = "string", vt.contains = "const", vt.not_contains = "oh") 11: map Map0 (vt.min_size = "0", vt.max_size = "10", vt.key.min_size = "0", vt.key.max_size = "10", vt.value.min_size = "0", vt.value.max_size = "10") 12: optional map Map1 (vt.min_size = "0", vt.max_size = "10", vt.key.min_size = "0", vt.key.max_size = "10", vt.value.min_size = "0", vt.value.max_size = "10") 13: set Set0 (vt.min_size = "0", vt.max_size = "10", vt.elem.min_size = "5") 14: optional set Set1 (vt.min_size = "0", vt.max_size = "10", vt.elem.min_size = "5") 15: EnumFoo Enum0 = EnumFoo.e2 (vt.in = "[EnumFoo.e2]", vt.defined_only = "true") 16: optional EnumFoo Enum1 (vt.in = "[EnumFoo.e1]", vt.defined_only = "true") 17: Foo Struct0 (vt.skip = "true") 18: optional Foo Struct1 (vt.skip = "true") 19: i8 Byte2 = 1 (vt.in = "1", vt.not_in = "2") 20: double Double2 = 3.0 (vt.in = "3.0", vt.not_in = "4.0") 21: EnumFoo Enum2 = EnumFoo.e2 (vt.in = "EnumFoo.e2", vt.not_in = "EnumFoo.e1") } struct FieldReferenceTest { 1: bool Bool0 (vt.const = "$Bool2") 2: optional bool Bool1 (vt.const = "$Bool2") 3: i8 Byte0 = 10 (vt.lt = "$Byte4", vt.le = "$Byte4", vt.gt = "$Byte2", vt.ge = "$Byte2", vt.in = "[$Byte2, $Byte3, $Byte4]", vt.not_in = "[$Byte2, $Byte4]") 4: optional i8 Byte1 (vt.lt = "$Byte4", vt.le = "$Byte4", vt.gt = "$Byte2", vt.ge = "$Byte2", vt.in = "[$Byte2, $Byte3, $Byte4]", vt.not_in = "[$Byte2, $Byte4]") 5: double Double0 = 10.0 (vt.lt = "$Double4", vt.le = "$Double4", vt.gt = "$Double2", vt.ge = "$Double2", vt.in = "[$Double2, $Double3, $Double4]", vt.not_in = "[$Double2, $Double4]") 6: optional double Double1 (vt.lt = "$Double4", vt.le = "$Double4", vt.gt = "$Double2", vt.ge = "$Double2", vt.in = "[$Double2, $Double3, $Double4]", vt.not_in = "[$Double2, $Double4]") 7: string String0 = "my string" (vt.const = "$String2", vt.min_size = "$Byte2", vt.max_size = "$Byte3", vt.pattern = "$String4", vt.prefix = "$String2", vt.suffix = "$String2", vt.contains = "$String2", vt.not_contains = "$String3") 8: optional string String1 (vt.const = "$String2", vt.min_size = "$Byte2", vt.max_size = "$Byte3", vt.pattern = "$String4", vt.prefix = "$String2", vt.suffix = "$String2", vt.contains = "$String2", vt.not_contains = "$String3") 9: binary Binary0 = "my binary" (vt.const = "$Binary2", vt.min_size = "$Byte2", vt.max_size = "$Byte3", vt.pattern = "$Binary4", vt.prefix = "$Binary2", vt.suffix = "$Binary2", vt.contains = "$Binary2", vt.not_contains = "$Binary3") 10: optional binary Binary1 = "my binary" (vt.const = "$Binary2", vt.min_size = "$Byte2", vt.max_size = "$Byte3", vt.pattern = "$Binary4", vt.prefix = "$Binary2", vt.suffix = "$Binary2", vt.contains = "$Binary2", vt.not_contains = "$Binary3") 11: map Map0 (vt.min_size = "$Byte2", vt.max_size = "$MaxSize", vt.key.min_size = "$Byte2", vt.key.max_size = "$MaxSize", vt.value.min_size = "$Byte2", vt.value.max_size = "$MaxSize") 12: optional map Map1 (vt.min_size = "$Byte2", vt.max_size = "$MaxSize", vt.key.min_size = "$Byte2", vt.key.max_size = "$MaxSize", vt.value.min_size = "$Byte2", vt.value.max_size = "$MaxSize") 13: list List0 (vt.min_size = "$Byte2", vt.max_size = "$MaxSize", vt.elem.min_size = "$Byte2", vt.elem.max_size = "$MaxSize") 14: optional list List1 (vt.min_size = "$Byte2", vt.max_size = "$MaxSize", vt.elem.min_size = "$Byte2", vt.elem.max_size = "$MaxSize") 15: set Set0 (vt.min_size = "$Byte2", vt.max_size = "$MaxSize", vt.elem.min_size = "$Byte2", vt.elem.max_size = "$MaxSize") 16: optional set Set1 (vt.min_size = "$Byte2", vt.max_size = "$MaxSize", vt.elem.min_size = "$Byte2", vt.elem.max_size = "$MaxSize") 17: bool Bool2 = false 18: i8 Byte2 = 0 19: i8 Byte3 = 10 20: i8 Byte4 = 20 21: double Double2 = 0 22: double Double3 = 10.0 23: double Double4 = 20.0 24: string String2 = "my string" 25: string String3 = "other string" 26: string String4 = ".*" 27: binary Binary2 = "my binary" 28: binary Binary3 = "other binary" 29: binary Binary4 = ".*" 30: i64 MaxSize = 10 } struct ValidationFunctionTest { 1: string StringFoo 2: i64 StringLength (vt.in = "[@len($StringFoo)]") } struct AnnotationCompatibleTest { 1: bool Bool0 = true (vt.const = "true", go.tag = 'json:"bool1"') 2: i8 Byte0 = 1 (vt.lt = "2", go.tag = 'json:"byte1"') 3: double Double0 = 1.0 (vt.lt = "2.0", go.tag = 'json:"double1"') 4: string String0 = "my const string" (vt.const = "my const string", go.tag = 'json:"string1"') 5: binary Binary0 = "my const string" (vt.const = "my const string", go.tag = 'json:"binary1"') 6: map Map0 (vt.max_size = "2", go.tag = 'json:"map1"') 7: set Set0 (vt.max_size = "2", go.tag = 'json:"set1"') 8: list List0 (vt.max_size = "2", go.tag = 'json:"list1"') 9: EnumFoo Enum0 = EnumFoo.e2 (vt.in = "[EnumFoo.e2]", go.tag = 'json:"enum1"') 10: Foo Struct0 (vt.skip = "true", go.tag = 'json:"struct1"') } thrift-0.19.0/lib/go/test/DontExportRWTest.thrift0000644000000000000000000000162014303740367021700 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # struct InnerStruct { 1: required string id } struct TestStruct { 1: required string id 2: required InnerStruct inner } thrift-0.19.0/lib/go/test/ConflictNamespaceTestF.thrift0000644000000000000000000000152214303740367023006 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflictf.thrift struct ThingF { 1: bool value } thrift-0.19.0/lib/go/test/ServicesTest.thrift0000644000000000000000000001235514303740367021113 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # We are only testing that generated code compiles, no correctness checking is done exception moderate_disaster { 1: i32 errorCode, 2: string message } exception total_disaster { 1: string message 2: optional bool president_was_woken_up = false } struct struct_a { 1: required i64 whatever } service a_serv { void voidfunc(), void void_with_1ex() throws(1: moderate_disaster err1) void void_with_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2) string stringfunc() string stringfunc_1ex() throws(1: moderate_disaster err1) string stringfunc_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2) i64 i64func() i64 i64func_1ex() throws(1: moderate_disaster err1) i64 i64func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2) list list_of_strings_func() list list_of_strings_func_1ex() throws(1: moderate_disaster err1) list list_of_strings_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2) map map_func() map map_func_1ex() throws(1: moderate_disaster err1) map map_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2) struct_a struct_a_func() struct_a struct_a_func_1ex() throws(1: moderate_disaster err1) struct_a struct_a_func_2ex() throws(1: moderate_disaster err1, 2:total_disaster err2) void voidfunc_1int(1: i64 i), void void_with_1ex_1int(1: i64 i) throws(1: moderate_disaster err1) void void_with_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2) string stringfunc_1int(1: i64 i) string stringfunc_1ex_1int(1: i64 i) throws(1: moderate_disaster err1) string stringfunc_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2) i64 i64func_1int(1: i64 i) i64 i64func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1) i64 i64func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2) list list_of_strings_func_1int(1: i64 i) list list_of_strings_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1) list list_of_strings_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2) map map_func_1int(1: i64 i) map map_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1) map map_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2) struct_a struct_a_func_1int(1: i64 i) struct_a struct_a_func_1ex_1int(1: i64 i) throws(1: moderate_disaster err1) struct_a struct_a_func_2ex_1int(1: i64 i) throws(1: moderate_disaster err1, 2:total_disaster err2) void voidfunc_1int_1s(1: i64 i, 2: string s), void void_with_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1) void void_with_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) string stringfunc_1int_1s(1: i64 i, 2: string s) string stringfunc_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1) string stringfunc_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) i64 i64func_1int_1s(1: i64 i, 2: string s) i64 i64func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1) i64 i64func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) list list_of_strings_func_1int_1s(1: i64 i, 2: string s) list list_of_strings_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1) list list_of_strings_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) map map_func_1int_1s(1: i64 i, 2: string s) map map_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1) map map_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) struct_a struct_a_func_1int_1s(1: i64 i, 2: string s) struct_a struct_a_func_1ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1) struct_a struct_a_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) struct_a struct_a_func_1struct_a(1: struct_a st) } service container_test_parent { void parent_only_func(1: set s) } service container_test extends container_test_parent { void child_only_func(1: set s) } thrift-0.19.0/lib/go/test/ConflictNamespaceTestA.thrift0000644000000000000000000000152214303740367023001 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflicta.common struct ThingA { 1: bool value } thrift-0.19.0/lib/go/test/UnionBinaryTest.thrift0000644000000000000000000000163514303740367021564 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # See https://issues.apache.org/jira/browse/THRIFT-4573 union Sample { 1: map u1, 2: binary u2, 3: list u3 } thrift-0.19.0/lib/go/test/ErrorTest.thrift0000644000000000000000000000223614303740367020416 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ struct TestStruct { 1: map m, 2: list l, 3: set s, 4: i32 i } service ErrorTest { TestStruct testStruct(1: TestStruct thing) string testString(1: string s) } thrift-0.19.0/lib/go/test/Makefile.in0000644000000000000000000005525414472652516017325 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/go/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ GOBUILDEXTRA = -buildvcs=false THRIFT_GO_ARGS_BASE = thrift_import=github.com/apache/thrift/lib/go/thrift,package_prefix=github.com/apache/thrift/lib/go/test/gopath/src/ THRIFTARGS = -out gopath/src/ --gen go:$(THRIFT_GO_ARGS_BASE)$(COMPILER_EXTRAFLAG) THRIFTTEST = $(top_srcdir)/test/ThriftTest.thrift THRIFTARGS_SKIP_REMOTE = -out gopath/src/ --gen go:skip_remote,$(THRIFT_GO_ARGS_BASE)$(COMPILER_EXTRAFLAG) EXTRA_DIST = \ dontexportrwtest \ tests \ common \ BinaryKeyTest.thrift \ ClientMiddlewareExceptionTest.thrift \ ConflictArgNamesTest.thrift \ ConflictNamespaceServiceTest.thrift \ ConflictNamespaceTestA.thrift \ ConflictNamespaceTestB.thrift \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ ConflictNamespaceTestE.thrift \ ConflictNamespaceTestF.thrift \ ConflictNamespaceTestSuperThing.thrift \ ConstOptionalField.thrift \ ConstOptionalFieldImport.thrift \ DontExportRWTest.thrift \ DuplicateImportsTest.thrift \ ErrorTest.thrift \ EqualsTest.thrift \ ForwardType.thrift \ GoTagTest.thrift \ IgnoreInitialismsTest.thrift \ IncludesTest.thrift \ InitialismsTest.thrift \ MultiplexedProtocolTest.thrift \ NamespacedTest.thrift \ NamesTest.thrift \ OnewayTest.thrift \ OptionalFieldsTest.thrift \ ProcessorMiddlewareTest.thrift \ RefAnnotationFieldsTest.thrift \ RequiredFieldTest.thrift \ ServicesTest.thrift \ TypedefFieldTest.thrift \ UnionBinaryTest.thrift \ UnionDefaultValueTest.thrift \ ValidateTest.thrift all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/go/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/go/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile # Thrift for GO has problems with complex map keys: THRIFT-2063 gopath: $(THRIFT) $(THRIFTTEST) \ IncludesTest.thrift \ NamespacedTest.thrift \ MultiplexedProtocolTest.thrift \ OnewayTest.thrift \ OptionalFieldsTest.thrift \ RequiredFieldTest.thrift \ ServicesTest.thrift \ GoTagTest.thrift \ TypedefFieldTest.thrift \ RefAnnotationFieldsTest.thrift \ UnionDefaultValueTest.thrift \ UnionBinaryTest.thrift \ ErrorTest.thrift \ NamesTest.thrift \ InitialismsTest.thrift \ DontExportRWTest.thrift \ dontexportrwtest/compile_test.go \ IgnoreInitialismsTest.thrift \ ConflictNamespaceTestA.thrift \ ConflictNamespaceTestB.thrift \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ ConflictNamespaceTestE.thrift \ ConflictNamespaceTestF.thrift \ ConflictNamespaceTestSuperThing.thrift \ ConflictNamespaceServiceTest.thrift \ DuplicateImportsTest.thrift \ EqualsTest.thrift \ ConflictArgNamesTest.thrift \ ConstOptionalFieldImport.thrift \ ConstOptionalField.thrift \ ProcessorMiddlewareTest.thrift \ ClientMiddlewareExceptionTest.thrift \ ValidateTest.thrift \ ForwardType.thrift mkdir -p gopath/src grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set' > ThriftTest.thrift $(THRIFT) $(THRIFTARGS) -r IncludesTest.thrift $(THRIFT) $(THRIFTARGS) BinaryKeyTest.thrift $(THRIFT) $(THRIFTARGS) MultiplexedProtocolTest.thrift $(THRIFT) $(THRIFTARGS) OnewayTest.thrift $(THRIFT) $(THRIFTARGS) OptionalFieldsTest.thrift $(THRIFT) $(THRIFTARGS) RequiredFieldTest.thrift $(THRIFT) $(THRIFTARGS) ServicesTest.thrift $(THRIFT) $(THRIFTARGS) GoTagTest.thrift $(THRIFT) $(THRIFTARGS) TypedefFieldTest.thrift $(THRIFT) $(THRIFTARGS) RefAnnotationFieldsTest.thrift $(THRIFT) $(THRIFTARGS) UnionDefaultValueTest.thrift $(THRIFT) $(THRIFTARGS) UnionBinaryTest.thrift $(THRIFT) $(THRIFTARGS) ErrorTest.thrift $(THRIFT) $(THRIFTARGS) NamesTest.thrift $(THRIFT) $(THRIFTARGS) InitialismsTest.thrift $(THRIFT) $(THRIFTARGS),read_write_private DontExportRWTest.thrift $(THRIFT) $(THRIFTARGS),ignore_initialisms IgnoreInitialismsTest.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestA.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestB.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestC.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestD.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestE.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestF.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestSuperThing.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceServiceTest.thrift $(THRIFT) $(THRIFTARGS) -r DuplicateImportsTest.thrift $(THRIFT) $(THRIFTARGS) EqualsTest.thrift $(THRIFT) $(THRIFTARGS) ConflictArgNamesTest.thrift $(THRIFT) $(THRIFTARGS) -r ConstOptionalField.thrift $(THRIFT) $(THRIFTARGS_SKIP_REMOTE) ProcessorMiddlewareTest.thrift $(THRIFT) $(THRIFTARGS) ClientMiddlewareExceptionTest.thrift $(THRIFT) $(THRIFTARGS) ValidateTest.thrift $(THRIFT) $(THRIFTARGS) ForwardType.thrift ln -nfs ../../tests gopath/src/tests cp -r ./dontexportrwtest gopath/src touch gopath check: gopath $(GO) build $(GOBUILDEXTRA) \ ./gopath/src/includestest \ ./gopath/src/binarykeytest \ ./gopath/src/servicestest \ ./gopath/src/typedeffieldtest \ ./gopath/src/refannotationfieldstest \ ./gopath/src/errortest \ ./gopath/src/namestest \ ./gopath/src/initialismstest \ ./gopath/src/dontexportrwtest \ ./gopath/src/ignoreinitialismstest \ ./gopath/src/unionbinarytest \ ./gopath/src/conflict/super \ ./gopath/src/conflict/context/conflict_service-remote \ ./gopath/src/servicestest/container_test-remote \ ./gopath/src/duplicateimportstest \ ./gopath/src/equalstest \ ./gopath/src/conflictargnamestest \ ./gopath/src/processormiddlewaretest \ ./gopath/src/clientmiddlewareexceptiontest \ ./gopath/src/validatetest \ ./gopath/src/forwardtypetest $(GO) test github.com/apache/thrift/lib/go/thrift $(GO) test ./gopath/src/tests ./gopath/src/dontexportrwtest clean-local: $(RM) -r gopath ThriftTest.thrift gen-go client: stubs $(GO) run TestClient.go # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/go/test/fuzz/0000755000000000000000000000000014472652664016247 5ustar00rootroot00000000000000thrift-0.19.0/lib/go/test/fuzz/Makefile.am0000644000000000000000000000225414370300523020263 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # gopathfuzz: $(THRIFT) fuzz.go $(THRIFT) -r --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift$(COMPILER_EXTRAFLAG) ../../../../tutorial/tutorial.thrift cd gen-go/shared && go mod init shared cd gen-go/tutorial && go mod init tutorial touch gopathfuzz check: gopathfuzz go test -tags gofuzz clean-local: $(RM) -r gopathfuzz gen-go EXTRA_DIST = \ fuzz.go \ fuzz_test.go \ go.mod \ go.sum thrift-0.19.0/lib/go/test/fuzz/go.mod0000644000000000000000000000053014472647462017353 0ustar00rootroot00000000000000module github.com/apache/thrift/lib/go/test/fuzz go 1.20 replace github.com/apache/thrift => ../../../../ replace shared => ./gen-go/shared replace tutorial => ./gen-go/tutorial require ( github.com/apache/thrift v0.0.0-00010101000000-000000000000 shared v0.0.0-00010101000000-000000000000 tutorial v0.0.0-00010101000000-000000000000 ) thrift-0.19.0/lib/go/test/fuzz/fuzz_test.go0000644000000000000000000000162314303740367020624 0ustar00rootroot00000000000000// +build gofuzz /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package fuzz import ( "testing" ) func TestFuzz(t *testing.T) { Fuzz([]byte{1, 2, 3}) } thrift-0.19.0/lib/go/test/fuzz/fuzz.go0000644000000000000000000000732214303740367017567 0ustar00rootroot00000000000000// +build gofuzz /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package fuzz import ( "context" "fmt" "strconv" "shared" "tutorial" "github.com/apache/thrift/lib/go/thrift" ) const nbFuzzedProtocols = 2 func fuzzChooseProtocol(d byte, t thrift.TTransport) thrift.TProtocol { switch d % nbFuzzedProtocols { default: fallthrough case 0: return thrift.NewTBinaryProtocolFactoryConf(nil).GetProtocol(t) case 1: return thrift.NewTCompactProtocolFactoryConf(nil).GetProtocol(t) } } func Fuzz(data []byte) int { if len(data) < 2 { return 0 } inputTransport := thrift.NewTMemoryBuffer() inputTransport.Buffer.Write(data[2:]) outputTransport := thrift.NewTMemoryBuffer() outputProtocol := fuzzChooseProtocol(data[0], outputTransport) inputProtocol := fuzzChooseProtocol(data[1], inputTransport) ctx := thrift.SetResponseHelper( context.Background(), thrift.TResponseHelper{ THeaderResponseHelper: thrift.NewTHeaderResponseHelper(outputProtocol), }, ) handler := NewCalculatorHandler() processor := tutorial.NewCalculatorProcessor(handler) ok := true var err error for ok { ok, err = processor.Process(ctx, inputProtocol, outputProtocol) if err != nil { // Handle parse error return 0 } res := make([]byte, 1024) n, err := outputTransport.Buffer.Read(res) fmt.Printf("lol %d %s %v\n", n, err, res) } return 1 } type CalculatorHandler struct { log map[int]*shared.SharedStruct } func NewCalculatorHandler() *CalculatorHandler { return &CalculatorHandler{log: make(map[int]*shared.SharedStruct)} } func (p *CalculatorHandler) Ping(ctx context.Context) (err error) { fmt.Print("ping()\n") return nil } func (p *CalculatorHandler) Add(ctx context.Context, num1 int32, num2 int32) (retval17 int32, err error) { fmt.Print("add(", num1, ",", num2, ")\n") return num1 + num2, nil } func (p *CalculatorHandler) Calculate(ctx context.Context, logid int32, w *tutorial.Work) (val int32, err error) { fmt.Print("calculate(", logid, ", {", w.Op, ",", w.Num1, ",", w.Num2, "})\n") switch w.Op { case tutorial.Operation_ADD: val = w.Num1 + w.Num2 break case tutorial.Operation_SUBTRACT: val = w.Num1 - w.Num2 break case tutorial.Operation_MULTIPLY: val = w.Num1 * w.Num2 break case tutorial.Operation_DIVIDE: if w.Num2 == 0 { ouch := tutorial.NewInvalidOperation() ouch.WhatOp = int32(w.Op) ouch.Why = "Cannot divide by 0" err = ouch return } val = w.Num1 / w.Num2 break default: ouch := tutorial.NewInvalidOperation() ouch.WhatOp = int32(w.Op) ouch.Why = "Unknown operation" err = ouch return } entry := shared.NewSharedStruct() entry.Key = logid entry.Value = strconv.Itoa(int(val)) k := int(logid) p.log[k] = entry return val, err } func (p *CalculatorHandler) GetStruct(ctx context.Context, key int32) (*shared.SharedStruct, error) { fmt.Print("getStruct(", key, ")\n") v, _ := p.log[int(key)] return v, nil } func (p *CalculatorHandler) Zip(ctx context.Context) (err error) { fmt.Print("zip()\n") return nil } thrift-0.19.0/lib/go/test/fuzz/go.sum0000644000000000000000000000246314303740367017376 0ustar00rootroot00000000000000github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= thrift-0.19.0/lib/go/test/fuzz/Makefile.in0000644000000000000000000004302214472652516020311 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/go/test/fuzz ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ fuzz.go \ fuzz_test.go \ go.mod \ go.sum all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/go/test/fuzz/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/go/test/fuzz/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile gopathfuzz: $(THRIFT) fuzz.go $(THRIFT) -r --gen go:thrift_import=github.com/apache/thrift/lib/go/thrift$(COMPILER_EXTRAFLAG) ../../../../tutorial/tutorial.thrift cd gen-go/shared && go mod init shared cd gen-go/tutorial && go mod init tutorial touch gopathfuzz check: gopathfuzz go test -tags gofuzz clean-local: $(RM) -r gopathfuzz gen-go # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/go/test/ConflictNamespaceServiceTest.thrift0000644000000000000000000000164314303740367024225 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflict.context include "ConflictNamespaceTestD.thrift" service ConflictService { ConflictNamespaceTestD.ThingD thingFunc() } thrift-0.19.0/lib/go/test/ForwardType.thrift0000644000000000000000000000171314452237057020734 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // https://issues.apache.org/jira/browse/THRIFT-5685 namespace go forwardtypetest struct Struct { 1: optional Exc foo } exception Exc { 1: optional i32 code } thrift-0.19.0/lib/go/test/ConflictNamespaceTestB.thrift0000644000000000000000000000152214303740367023002 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace go conflictb.common struct ThingB { 1: bool value } thrift-0.19.0/lib/go/Makefile.in0000644000000000000000000006043614472652516016344 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_TESTS_TRUE@am__append_1 = test test/fuzz subdir = lib/go ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . test test/fuzz am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . $(am__append_1) @GOVERSION_GE_118_FALSE@GOBUILDEXTRA = @GOVERSION_GE_118_TRUE@GOBUILDEXTRA = -buildvcs=false EXTRA_DIST = \ thrift \ coding_standards.md \ README.md all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/go/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/go/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ check check-am check-local clean clean-generic clean-libtool \ clean-local cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile install: @echo '##############################################################' @echo '##############################################################' @echo 'The Go client library should be installed via "go get", please see /lib/go/README.md' @echo '##############################################################' @echo '##############################################################' # NOTE: We have to disable stdmethods in go vet until # https://github.com/golang/go/issues/52445 is fixed. check-local: $(GO) vet -stdmethods=false github.com/apache/thrift/lib/go/thrift $(GO) test -race ./thrift clean-local: $(RM) -rf pkg all-local: $(GO) build $(GOBUILDEXTRA) ./thrift # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/dart/0000777000000000000000000000000014472652605014616 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/Makefile.am0000644000000000000000000000231214303740367016640 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # all-local: $(DARTPUB) get clean-local: $(RM) -r .pub find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type d -name "packages" | xargs $(RM) -r check-local: all dist-hook: $(RM) -r $(distdir)/.pub find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) find $(distdir) -type d -name "packages" | xargs $(RM) -r thrift-0.19.0/lib/dart/Makefile0000644000000000000000000004420614472652605016260 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # lib/dart/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = lib/dart ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/lib/dart abs_srcdir = /thrift/src/lib/dart abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../ top_builddir = ../.. top_srcdir = ../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/dart/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/dart/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ dist-hook distclean distclean-generic distclean-libtool \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile all-local: $(DARTPUB) get clean-local: $(RM) -r .pub find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type d -name "packages" | xargs $(RM) -r check-local: all dist-hook: $(RM) -r $(distdir)/.pub find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) find $(distdir) -type d -name "packages" | xargs $(RM) -r # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/dart/pubspec.yaml0000644000000000000000000000260014454461475017140 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # 'License'); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. name: thrift version: 0.19.0 description: > A Dart library for Apache Thrift author: Apache Thrift Developers homepage: http://thrift.apache.org documentation: http://thrift.apache.org environment: sdk: ">=2.0.0 <3.0.0" dependencies: fixnum: ">=0.10.2 <2.0.0" http: ">=0.11.3 <0.14.0" logging: ">=0.11.0 <2.0.0" dev_dependencies: build_runner: ">=1.7.1 <3.0.0" build_test: ">=0.10.9 <3.0.0" build_vm_compilers: ^1.0.3 build_web_compilers: ">=2.7.1 <4.0.0" dart_dev: ^3.0.0 dart_style: ">=1.3.1 <3.0.0" mockito: ">=4.1.1 <6.0.0" test: ^1.9.1 workiva_analysis_options: ^1.0.0thrift-0.19.0/lib/dart/LICENSE0000644000000000000000000000135514303740367015617 0ustar00rootroot00000000000000Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. thrift-0.19.0/lib/dart/README.md0000644000000000000000000000154414303740367016071 0ustar00rootroot00000000000000Thrift Dart Library License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Using Thrift with Dart ==================== Dart 1.24.3 or newer is required thrift-0.19.0/lib/dart/coding_standards.md0000644000000000000000000000037314303740367020441 0ustar00rootroot00000000000000# Dart Coding Standards ### Please follow: * [Thrift General Coding Standards](/doc/coding_standards.md) * [Use dartfmt](https://www.dartlang.org/tools/dartfmt/) and follow the [Dart Style Guide](https://www.dartlang.org/articles/style-guide/) thrift-0.19.0/lib/dart/test/0000777000000000000000000000000014303740367015571 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/test/t_application_error_test.dart0000644000000000000000000000276014303740367023544 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. library thrift.test.t_application_error_test; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; void main() { TProtocol protocol; setUp(() { protocol = TBinaryProtocol(TBufferedTransport()); }); test('Write and read an application error', () { var expectedType = TApplicationErrorType.INTERNAL_ERROR; var expectedMessage = 'test error message'; TApplicationError error = TApplicationError(expectedType, expectedMessage); error.write(protocol); protocol.transport.flush(); TApplicationError subject = TApplicationError.read(protocol); expect(subject, isNotNull); expect(subject.type, expectedType); expect(subject.message, expectedMessage); }); } thrift-0.19.0/lib/dart/test/protocol/0000777000000000000000000000000014303740367017432 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/test/protocol/t_protocol_test.dart0000644000000000000000000002624214303740367023533 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. library thrift.test.transport.t_json_protocol_test; import 'dart:async'; import 'dart:convert' show utf8; import 'dart:typed_data' show Uint8List; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; void main() { final message = TMessage('my message', TMessageType.ONEWAY, 123); TProtocol protocol; Primitive getPrimitive(int tType) { switch (tType) { case TType.BOOL: return Primitive(protocol.readBool, protocol.writeBool, false); case TType.BYTE: return Primitive(protocol.readByte, protocol.writeByte, 0); case TType.I16: return Primitive(protocol.readI16, protocol.writeI16, 0); case TType.I32: return Primitive(protocol.readI32, protocol.writeI32, 0); case TType.I64: return Primitive(protocol.readI64, protocol.writeI64, 0); case TType.DOUBLE: return Primitive(protocol.readDouble, protocol.writeDouble, 0); case TType.STRING: return Primitive(protocol.readString, protocol.writeString, ''); default: throw UnsupportedError("Unsupported TType $tType"); } } Future primitiveTest(Primitive primitive, input) async { primitive.write(input); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = primitive.read(); expect(output, input); } Future primitiveNullTest(Primitive primitive) async { primitive.write(null); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = primitive.read(); expect(output, primitive.defaultValue); } var sharedTests = () { test('Test message', () async { protocol.writeMessageEnd(); await protocol.transport.flush(); var subject = protocol.readMessageBegin(); expect(subject.name, message.name); expect(subject.type, message.type); expect(subject.seqid, message.seqid); }); test('Test struct', () async { var input = TStruct(); protocol.writeStructBegin(input); protocol.writeStructEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = protocol.readStructBegin(); // name is not serialized, see C# version for reference expect(output, isNotNull); }); test('Test field', () async { var input = TField('my field', TType.MAP, 123); protocol.writeFieldBegin(input); protocol.writeFieldEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = protocol.readFieldBegin(); // name is not serialized, see C# version for reference expect(output.type, input.type); expect(output.id, input.id); }); test('Test map', () async { var input = TMap(TType.STRING, TType.STRUCT, 123); protocol.writeMapBegin(input); protocol.writeMapEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = protocol.readMapBegin(); expect(output.keyType, input.keyType); expect(output.valueType, input.valueType); expect(output.length, input.length); }); test('Test list', () async { var input = TList(TType.STRING, 123); protocol.writeListBegin(input); protocol.writeListEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = protocol.readListBegin(); expect(output.elementType, input.elementType); expect(output.length, input.length); }); test('Test set', () async { var input = TSet(TType.STRING, 123); protocol.writeSetBegin(input); protocol.writeSetEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = protocol.readListBegin(); expect(output.elementType, input.elementType); expect(output.length, input.length); }); test('Test bool', () async { await primitiveTest(getPrimitive(TType.BOOL), true); }); test('Test bool null', () async { await primitiveNullTest(getPrimitive(TType.BOOL)); }); test('Test byte', () async { await primitiveTest(getPrimitive(TType.BYTE), 64); }); test('Test byte null', () async { await primitiveNullTest(getPrimitive(TType.BYTE)); }); test('Test I16', () async { await primitiveTest(getPrimitive(TType.I16), 32767); }); test('Test I16 null', () async { await primitiveNullTest(getPrimitive(TType.I16)); }); test('Test I32', () async { await primitiveTest(getPrimitive(TType.I32), 2147483647); }); test('Test I32 null', () async { await primitiveNullTest(getPrimitive(TType.I32)); }); test('Test I64', () async { await primitiveTest(getPrimitive(TType.I64), 9223372036854775807); }); test('Test I64 null', () async { await primitiveNullTest(getPrimitive(TType.I64)); }); test('Test double', () async { await primitiveTest(getPrimitive(TType.DOUBLE), 3.1415926); }); test('Test double null', () async { await primitiveNullTest(getPrimitive(TType.DOUBLE)); }); test('Test string', () async { var input = 'There are only two hard things in computer science: ' 'cache invalidation, naming things, and off-by-one errors.'; await primitiveTest(getPrimitive(TType.STRING), input); }); test('Test string null', () async { await primitiveNullTest(getPrimitive(TType.STRING)); }); test('Test binary', () async { var input = Uint8List.fromList(List.filled(100, 123)); protocol.writeBinary(input); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); var output = protocol.readBinary(); expect(output.length, input.length); expect(output.every((i) => i == 123), isTrue); }); test('Test complex struct', () async { // {1: {10: 20}, 2: {30: 40}} protocol.writeStructBegin(TStruct()); protocol.writeFieldBegin(TField('success', TType.MAP, 0)); protocol.writeMapBegin(TMap(TType.I32, TType.MAP, 2)); protocol.writeI32(1); // key protocol.writeMapBegin(TMap(TType.I32, TType.I32, 1)); protocol.writeI32(10); // key protocol.writeI32(20); // value protocol.writeMapEnd(); protocol.writeI32(2); // key protocol.writeMapBegin(TMap(TType.I32, TType.I32, 1)); protocol.writeI32(30); // key protocol.writeI32(40); // value protocol.writeMapEnd(); protocol.writeMapEnd(); protocol.writeFieldEnd(); protocol.writeFieldStop(); protocol.writeStructEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); protocol.readStructBegin(); expect(protocol.readFieldBegin().type, TType.MAP); expect(protocol.readMapBegin().length, 2); expect(protocol.readI32(), 1); // key expect(protocol.readMapBegin().length, 1); expect(protocol.readI32(), 10); // key expect(protocol.readI32(), 20); // value protocol.readMapEnd(); expect(protocol.readI32(), 2); // key expect(protocol.readMapBegin().length, 1); expect(protocol.readI32(), 30); // key expect(protocol.readI32(), 40); // value protocol.readMapEnd(); protocol.readMapEnd(); protocol.readFieldEnd(); protocol.readStructEnd(); protocol.readMessageEnd(); }); test('Test nested maps and lists', () async { // {1: [{10: 20}], 2: [{30: 40}]} protocol.writeMapBegin(TMap(TType.I32, TType.LIST, 2)); protocol.writeI32(1); // key protocol.writeListBegin(TList(TType.MAP, 1)); protocol.writeMapBegin(TMap(TType.I32, TType.I32, 1)); protocol.writeI32(10); // key protocol.writeI32(20); // value protocol.writeMapEnd(); protocol.writeListEnd(); protocol.writeI32(2); // key protocol.writeListBegin(TList(TType.MAP, 1)); protocol.writeMapBegin(TMap(TType.I32, TType.I32, 1)); protocol.writeI32(30); // key protocol.writeI32(40); // value protocol.writeMapEnd(); protocol.writeListEnd(); protocol.writeMapEnd(); protocol.writeMessageEnd(); await protocol.transport.flush(); protocol.readMessageBegin(); expect(protocol.readMapBegin().length, 2); expect(protocol.readI32(), 1); // key expect(protocol.readListBegin().length, 1); expect(protocol.readMapBegin().length, 1); expect(protocol.readI32(), 10); // key expect(protocol.readI32(), 20); // value protocol.readMapEnd(); protocol.readListEnd(); expect(protocol.readI32(), 2); // key expect(protocol.readListBegin().length, 1); expect(protocol.readMapBegin().length, 1); expect(protocol.readI32(), 30); // key expect(protocol.readI32(), 40); // value protocol.readMapEnd(); protocol.readListEnd(); protocol.readMapEnd(); protocol.readMessageEnd(); }); }; group('JSON', () { setUp(() { protocol = TJsonProtocol(TBufferedTransport()); protocol.writeMessageBegin(message); }); test('Test escaped unicode', () async { /* KOR_KAI UTF-8: 0xE0 0xB8 0x81 UTF-16: 0x0E01 G clef: UTF-8: 0xF0 0x9D 0x84 0x9E UTF-16: 0xD834 0xDD1E */ var buffer = utf8.encode(r'"\u0001\u0e01 \ud834\udd1e"'); var transport = TBufferedTransport(); transport.writeAll(buffer); var protocol = TJsonProtocol(transport); await protocol.transport.flush(); var subject = protocol.readString(); expect(subject, utf8.decode([0x01, 0xE0, 0xB8, 0x81, 0x20, 0xF0, 0x9D, 0x84, 0x9E])); }); group('shared tests', sharedTests); }); group('binary', () { setUp(() { protocol = TBinaryProtocol(TBufferedTransport()); protocol.writeMessageBegin(message); }); group('shared tests', sharedTests); }); group('compact', () { setUp(() { protocol = TCompactProtocol(TBufferedTransport()); protocol.writeMessageBegin(message); }); group('shared tests', sharedTests); }); } class Primitive { final Function read; final Function write; final defaultValue; Primitive(this.read, this.write, this.defaultValue); } thrift-0.19.0/lib/dart/test/transport/0000777000000000000000000000000014303740367017625 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/test/transport/t_http_transport_test.dart0000644000000000000000000001226414303740367025157 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. library thrift.test.transport.t_socket_transport_test; import 'dart:async'; import 'dart:convert' show Encoding; import 'dart:convert' show Utf8Codec; import 'dart:convert' show base64; import 'dart:typed_data' show Uint8List; import 'package:http/http.dart' show BaseRequest; import 'package:http/http.dart' show Client; import 'package:http/http.dart' show Response; import 'package:http/http.dart' show StreamedResponse; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; void main() { const utf8Codec = Utf8Codec(); group('THttpClientTransport', () { FakeHttpClient client; THttpClientTransport transport; setUp(() { client = FakeHttpClient(sync: false); var config = THttpConfig(Uri.parse('http://localhost'), {}); transport = THttpClientTransport(client, config); }); test('Test transport sends body', () async { var expectedText = 'my request'; transport.writeAll(utf8Codec.encode(expectedText)); expect(client.postRequest, isEmpty); await transport.flush(); expect(client.postRequest, isNotEmpty); var requestText = utf8Codec.decode(base64.decode(client.postRequest)); expect(requestText, expectedText); }); test('Test transport receives response', () async { var expectedText = 'my response'; var expectedBytes = utf8Codec.encode(expectedText); client.postResponse = base64.encode(expectedBytes); transport.writeAll(utf8Codec.encode('my request')); expect(transport.hasReadData, isFalse); await transport.flush(); expect(transport.hasReadData, isTrue); var buffer = Uint8List(expectedBytes.length); transport.readAll(buffer, 0, expectedBytes.length); var bufferText = utf8Codec.decode(buffer); expect(bufferText, expectedText); }); }); group('THttpClientTransport with multiple messages', () { FakeHttpClient client; THttpClientTransport transport; setUp(() { client = FakeHttpClient(sync: true); var config = THttpConfig(Uri.parse('http://localhost'), {}); transport = THttpClientTransport(client, config); }); test('Test read correct buffer after flush', () async { String bufferText; var expectedText = 'response 1'; var expectedBytes = utf8Codec.encode(expectedText); // prepare a response transport.writeAll(utf8Codec.encode('request 1')); client.postResponse = base64.encode(expectedBytes); Future responseReady = transport.flush().then((_) { var buffer = Uint8List(expectedBytes.length); transport.readAll(buffer, 0, expectedBytes.length); bufferText = utf8Codec.decode(buffer); }); // prepare a second response transport.writeAll(utf8Codec.encode('request 2')); var response2Bytes = utf8Codec.encode('response 2'); client.postResponse = base64.encode(response2Bytes); await transport.flush(); await responseReady; expect(bufferText, expectedText); }); }); } class FakeHttpClient implements Client { String postResponse = ''; String postRequest = ''; final bool sync; FakeHttpClient({this.sync = false}); @override Future post(url, {Map headers, body, Encoding encoding}) { postRequest = body; var response = Response(postResponse, 200); if (sync) { return Future.sync(() => response); } else { return Future.value(response); } } @override Future head(url, {Map headers}) => throw UnimplementedError(); @override Future get(url, {Map headers}) => throw UnimplementedError(); @override Future put(url, {Map headers, body, Encoding encoding}) => throw UnimplementedError(); @override Future patch(url, {Map headers, body, Encoding encoding}) => throw UnimplementedError(); @override Future delete(url, {Map headers}) => throw UnimplementedError(); @override Future read(url, {Map headers}) => throw UnimplementedError(); @override Future readBytes(url, {Map headers}) => throw UnimplementedError(); @override Future send(BaseRequest request) => throw UnimplementedError(); @override void close() => throw UnimplementedError(); } thrift-0.19.0/lib/dart/test/transport/t_framed_transport_test.dart0000644000000000000000000001317514303740367025440 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. library thrift.test.transport.t_framed_transport_test; import 'dart:async'; import 'dart:convert' show utf8; import 'dart:typed_data' show Uint8List; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; void main() { group('TFramedTransport partial reads', () { final flushAwaitDuration = Duration(seconds: 10); FakeReadOnlySocket socket; TSocketTransport socketTransport; TFramedTransport transport; var messageAvailable; setUp(() { socket = FakeReadOnlySocket(); socketTransport = TClientSocketTransport(socket); transport = TFramedTransport(socketTransport); messageAvailable = false; }); expectNoReadableBytes() { var readBuffer = Uint8List(128); var readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); expect(readBytes, 0); expect(messageAvailable, false); } test( 'Test transport reads messages where header and body are sent separately', () async { // buffer into which we'll read var readBuffer = Uint8List(10); var readBytes; // registers for readable bytes var flushFuture = transport.flush().timeout(flushAwaitDuration); flushFuture.then((_) { messageAvailable = true; }); // write header bytes socket.messageController .add(Uint8List.fromList([0x00, 0x00, 0x00, 0x06])); // you shouldn't be able to get any bytes from the read, // because the header has been consumed internally expectNoReadableBytes(); // write first batch of body socket.messageController.add(Uint8List.fromList(utf8.encode("He"))); // you shouldn't be able to get any bytes from the read, // because the frame has been consumed internally expectNoReadableBytes(); // write second batch of body socket.messageController.add(Uint8List.fromList(utf8.encode("llo!"))); // have to wait for the flush to complete, // because it's only then that the frame is available for reading await flushFuture; expect(messageAvailable, true); // at this point the frame is complete, so we expect the read to complete readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); expect(readBytes, 6); expect(readBuffer.sublist(0, 6), utf8.encode("Hello!")); }); test( 'Test transport reads messages where header is sent in pieces ' 'and body is also sent in pieces', () async { // buffer into which we'll read var readBuffer = Uint8List(10); var readBytes; // registers for readable bytes var flushFuture = transport.flush().timeout(flushAwaitDuration); flushFuture.then((_) { messageAvailable = true; }); // write first part of header bytes socket.messageController.add(Uint8List.fromList([0x00, 0x00])); // you shouldn't be able to get any bytes from the read expectNoReadableBytes(); // write second part of header bytes socket.messageController.add(Uint8List.fromList([0x00, 0x03])); // you shouldn't be able to get any bytes from the read again // because only the header was read, and there's no frame body readBytes = expectNoReadableBytes(); // write first batch of body socket.messageController.add(Uint8List.fromList(utf8.encode("H"))); // you shouldn't be able to get any bytes from the read, // because the frame has been consumed internally expectNoReadableBytes(); // write second batch of body socket.messageController.add(Uint8List.fromList(utf8.encode("i!"))); // have to wait for the flush to complete, // because it's only then that the frame is available for reading await flushFuture; expect(messageAvailable, true); // at this point the frame is complete, so we expect the read to complete readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); expect(readBytes, 3); expect(readBuffer.sublist(0, 3), utf8.encode("Hi!")); }); }); } class FakeReadOnlySocket extends TSocket { StreamController messageController = StreamController(sync: true); StreamController errorController = StreamController(); StreamController stateController = StreamController(); @override Future close() async { messageController.close(); errorController.close(); stateController.close(); } @override bool get isClosed => false; @override bool get isOpen => true; @override Stream get onError => errorController.stream; @override Stream get onMessage => messageController.stream; @override Stream get onState => stateController.stream; @override Future open() async { // noop } @override void send(Uint8List data) { // noop } } thrift-0.19.0/lib/dart/test/transport/t_transport_test.dart0000644000000000000000000000255214303740367024117 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. library thrift.test.transport.t_socket_transport_test; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; /// Common transport tests void main() { group('TTransportFactory', () { test('transport is returned from base factory', () async { TTransport result; TTransport transport; var factory = TTransportFactory(); result = await factory.getTransport(transport); expect(result, isNull); transport = TBufferedTransport(); result = await factory.getTransport(transport); expect(result, transport); }); }); } thrift-0.19.0/lib/dart/test/transport/t_socket_transport_test.dart0000644000000000000000000002264614303740367025475 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. library thrift.test.transport.t_socket_transport_test; import 'dart:async'; import 'dart:convert' show Utf8Codec, base64; import 'dart:typed_data' show Uint8List; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; void main() { const utf8Codec = Utf8Codec(); final requestText = 'my test request'; final requestBytes = Uint8List.fromList(utf8Codec.encode(requestText)); final requestBase64 = base64.encode(requestBytes); final responseText = 'response 1'; final responseBytes = Uint8List.fromList(utf8Codec.encode(responseText)); final responseBase64 = base64.encode(responseBytes); final framedResponseBase64 = base64.encode(_getFramedResponse(responseBytes)); group('TClientSocketTransport', () { FakeSocket socket; TTransport transport; setUp(() async { socket = FakeSocket(sync: false); await socket.open(); transport = TClientSocketTransport(socket); await transport.open(); transport.writeAll(requestBytes); }); test('Test client sending data over transport', () async { expect(socket.sendPayload, isNull); Future responseReady = transport.flush(); // allow microtask events to finish await Future.value(); expect(socket.sendPayload, isNotNull); expect(socket.sendPayload, requestBytes); // simulate a response socket.receiveFakeMessage(responseBase64); await responseReady; var buffer = Uint8List(responseBytes.length); transport.readAll(buffer, 0, responseBytes.length); var bufferText = utf8Codec.decode(buffer); expect(bufferText, responseText); }); }, timeout: Timeout(Duration(seconds: 1))); group('TClientSocketTransport with FramedTransport', () { FakeSocket socket; TTransport transport; setUp(() async { socket = FakeSocket(sync: true); await socket.open(); transport = TFramedTransport(TClientSocketTransport(socket)); await transport.open(); transport.writeAll(requestBytes); }); test('Test client sending data over framed transport', () async { String bufferText; Future responseReady = transport.flush().then((_) { var buffer = Uint8List(responseBytes.length); transport.readAll(buffer, 0, responseBytes.length); bufferText = utf8Codec.decode(buffer); }); // simulate a response socket.receiveFakeMessage(framedResponseBase64); await responseReady; expect(bufferText, responseText); }); }, timeout: Timeout(Duration(seconds: 1))); group('TAsyncClientSocketTransport', () { FakeSocket socket; FakeProtocolFactory protocolFactory; TTransport transport; setUp(() async { socket = FakeSocket(sync: true); await socket.open(); protocolFactory = FakeProtocolFactory(); protocolFactory.message = TMessage('foo', TMessageType.CALL, 123); transport = TAsyncClientSocketTransport( socket, TMessageReader(protocolFactory), responseTimeout: Duration.zero); await transport.open(); transport.writeAll(requestBytes); }); test('Test response correlates to correct request', () async { String bufferText; Future responseReady = transport.flush().then((_) { var buffer = Uint8List(responseBytes.length); transport.readAll(buffer, 0, responseBytes.length); bufferText = utf8Codec.decode(buffer); }); // simulate a response protocolFactory.message = TMessage('foo', TMessageType.REPLY, 123); socket.receiveFakeMessage(responseBase64); // simulate a second response var response2Text = 'response 2'; var response2Bytes = Uint8List.fromList(utf8Codec.encode(response2Text)); var response2Base64 = base64.encode(response2Bytes); protocolFactory.message = TMessage('foo2', TMessageType.REPLY, 124); socket.receiveFakeMessage(response2Base64); await responseReady; expect(bufferText, responseText); }); test('Test response timeout', () async { Future responseReady = transport.flush(); expect(responseReady, throwsA(isA())); }); }, timeout: Timeout(Duration(seconds: 1))); group('TAsyncClientSocketTransport with TFramedTransport', () { FakeSocket socket; FakeProtocolFactory protocolFactory; TTransport transport; setUp(() async { socket = FakeSocket(sync: true); await socket.open(); protocolFactory = FakeProtocolFactory(); protocolFactory.message = TMessage('foo', TMessageType.CALL, 123); var messageReader = TMessageReader(protocolFactory, byteOffset: TFramedTransport.headerByteCount); transport = TFramedTransport(TAsyncClientSocketTransport( socket, messageReader, responseTimeout: Duration.zero)); await transport.open(); transport.writeAll(requestBytes); }); test('Test async client sending data over framed transport', () async { String bufferText; Future responseReady = transport.flush().then((_) { var buffer = Uint8List(responseBytes.length); transport.readAll(buffer, 0, responseBytes.length); bufferText = utf8Codec.decode(buffer); }); // simulate a response protocolFactory.message = TMessage('foo', TMessageType.REPLY, 123); socket.receiveFakeMessage(framedResponseBase64); await responseReady; expect(bufferText, responseText); }); }, timeout: Timeout(Duration(seconds: 1))); group('TServerTransport', () { test('Test server transport listens to socket', () async { var socket = FakeSocket(); await socket.open(); expect(socket.isOpen, isTrue); var transport = TServerSocketTransport(socket); expect(transport.hasReadData, isFalse); socket.receiveFakeMessage(requestBase64); // allow microtask events to finish await Future.value(); expect(transport.hasReadData, isTrue); var buffer = Uint8List(requestBytes.length); transport.readAll(buffer, 0, requestBytes.length); var bufferText = utf8Codec.decode(buffer); expect(bufferText, requestText); }); test('Test server sending data over transport', () async { var socket = FakeSocket(); await socket.open(); var transport = TServerSocketTransport(socket); transport.writeAll(responseBytes); expect(socket.sendPayload, isNull); transport.flush(); // allow microtask events to finish await Future.value(); expect(socket.sendPayload, isNotNull); expect(socket.sendPayload, responseBytes); }); }, timeout: Timeout(Duration(seconds: 1))); } class FakeSocket extends TSocket { final StreamController _onStateController; @override Stream get onState => _onStateController.stream; final StreamController _onErrorController; @override Stream get onError => _onErrorController.stream; final StreamController _onMessageController; @override Stream get onMessage => _onMessageController.stream; FakeSocket({bool sync = false}) : _onStateController = StreamController.broadcast(sync: sync), _onErrorController = StreamController.broadcast(sync: sync), _onMessageController = StreamController.broadcast(sync: sync); bool _isOpen; @override bool get isOpen => _isOpen; @override bool get isClosed => !isOpen; @override Future open() async { _isOpen = true; _onStateController.add(TSocketState.OPEN); } @override Future close() async { _isOpen = false; _onStateController.add(TSocketState.CLOSED); } Uint8List _sendPayload; Uint8List get sendPayload => _sendPayload; @override void send(Uint8List data) { if (!isOpen) throw StateError('The socket is not open'); _sendPayload = data; } void receiveFakeMessage(String base64text) { if (!isOpen) throw StateError('The socket is not open'); var message = Uint8List.fromList(base64.decode(base64text)); _onMessageController.add(message); } } class FakeProtocolFactory implements TProtocolFactory { FakeProtocolFactory(); TMessage message; @override getProtocol(TTransport transport) => FakeProtocol(message); } class FakeProtocol extends Mock implements TProtocol { FakeProtocol(this._message); TMessage _message; @override readMessageBegin() => _message; } Uint8List _getFramedResponse(Uint8List responseBytes) { var byteOffset = TFramedTransport.headerByteCount; var response = Uint8List(byteOffset + responseBytes.length); response.buffer.asByteData().setInt32(0, responseBytes.length); response.setAll(byteOffset, responseBytes); return response; } thrift-0.19.0/lib/dart/test/serializer/0000777000000000000000000000000014303740367017742 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/test/serializer/serializer_test.dart0000644000000000000000000000663714303740367024036 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ library thrift.test.serializer.serializer_test; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; import 'serializer_test_data.dart'; void main() { var serializer = () { TDeserializer deserializer; TSerializer serializer; TestTObject testTObject; setUp(() { serializer = TSerializer(); deserializer = TDeserializer(); testTObject = TestTObject(); testTObject.b = true; testTObject.s = "TEST"; testTObject.d = 15.25; testTObject.i = 10; var testList = List(); testList.add("TEST 1"); testList.add("TEST 2"); testTObject.l = testList; }); assertNewObjectEqualsTObject(TestTObject newObject) { expect(newObject.l, equals(testTObject.l)); expect(newObject.b, equals(testTObject.b)); expect(newObject.i, equals(testTObject.i)); expect(newObject.d, equals(testTObject.d)); expect(newObject.s, equals(testTObject.s)); } runWriteStringTest() { var s = serializer.writeString(testTObject); var newObject = TestTObject(); deserializer.readString(newObject, s); assertNewObjectEqualsTObject(newObject); } runWriteTest() { var s = serializer.write(testTObject); var newObject = TestTObject(); deserializer.read(newObject, s); assertNewObjectEqualsTObject(newObject); } test('JSON Protocol String', () { serializer.protocol = TJsonProtocol(serializer.transport); deserializer.protocol = TJsonProtocol(deserializer.transport); runWriteStringTest(); }); test('JSON Protocol', () { serializer.protocol = TJsonProtocol(serializer.transport); deserializer.protocol = TJsonProtocol(deserializer.transport); runWriteTest(); }); test('Binary Protocol String', () { serializer.protocol = TBinaryProtocol(serializer.transport); deserializer.protocol = TBinaryProtocol(deserializer.transport); runWriteStringTest(); }); test('Binary Protocol', () { serializer.protocol = TBinaryProtocol(serializer.transport); deserializer.protocol = TBinaryProtocol(deserializer.transport); runWriteTest(); }); test('Compact Protocol String', () { serializer.protocol = TCompactProtocol(serializer.transport); deserializer.protocol = TCompactProtocol(deserializer.transport); runWriteStringTest(); }); test('Compact Protocol', () { serializer.protocol = TCompactProtocol(serializer.transport); deserializer.protocol = TCompactProtocol(deserializer.transport); runWriteTest(); }); }; group('Serializer', serializer); } thrift-0.19.0/lib/dart/test/serializer/serializer_test_data.dart0000644000000000000000000001675114303740367025025 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ library thrift.test.serializer.serializer_test; import 'package:thrift/thrift.dart'; /// TestTObject is a simple test struct class TestTObject implements TBase { static final TStruct _STRUCT_DESC = TStruct("TestTObject"); static final TField _I_FIELD_DESC = TField("i", TType.I32, 1); static final TField _D_FIELD_DESC = TField("d", TType.DOUBLE, 2); static final TField _S_FIELD_DESC = TField("s", TType.STRING, 3); static final TField _L_FIELD_DESC = TField("l", TType.LIST, 4); static final TField _B_FIELD_DESC = TField("b", TType.BOOL, 5); int _i; static const int I = 1; double _d; static const int D = 2; String _s; static const int S = 3; List _l; static const int L = 4; bool _b; static const int B = 5; bool __isset_i = false; bool __isset_d = false; bool __isset_b = false; TestTObject(); // i int get i => this._i; set i(int i) { this._i = i; this.__isset_i = true; } bool isSetI() => this.__isset_i; unsetI() { this.__isset_i = false; } // d double get d => this._d; set d(double d) { this._d = d; this.__isset_d = true; } bool isSetD() => this.__isset_d; unsetD() { this.__isset_d = false; } // s String get s => this._s; set s(String s) { this._s = s; } bool isSetS() => this.s != null; unsetS() { this.s = null; } // l List get l => this._l; set l(List l) { this._l = l; } bool isSetL() => this.l != null; unsetL() { this.l = null; } // b bool get b => this._b; set b(bool b) { this._b = b; this.__isset_b = true; } bool isSetB() => this.__isset_b; unsetB() { this.__isset_b = false; } @override getFieldValue(int fieldID) { switch (fieldID) { case I: return this.i; case D: return this.d; case S: return this.s; case L: return this.l; case B: return this.b; default: throw ArgumentError("Field $fieldID doesn't exist!"); } } @override setFieldValue(int fieldID, Object value) { switch (fieldID) { case I: if (value == null) { unsetI(); } else { this.i = value; } break; case D: if (value == null) { unsetD(); } else { this.d = value; } break; case S: if (value == null) { unsetS(); } else { this.s = value; } break; case L: if (value == null) { unsetL(); } else { this.l = value as List; } break; case B: if (value == null) { unsetB(); } else { this.b = value; } break; default: throw ArgumentError("Field $fieldID doesn't exist!"); } } // Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise @override bool isSet(int fieldID) { switch (fieldID) { case I: return isSetI(); case D: return isSetD(); case S: return isSetS(); case L: return isSetL(); case B: return isSetB(); default: throw ArgumentError("Field $fieldID doesn't exist!"); } } @override read(TProtocol iprot) { TField field; iprot.readStructBegin(); while (true) { field = iprot.readFieldBegin(); if (field.type == TType.STOP) { break; } switch (field.id) { case I: if (field.type == TType.I32) { this.i = iprot.readI32(); this.__isset_i = true; } else { TProtocolUtil.skip(iprot, field.type); } break; case D: if (field.type == TType.DOUBLE) { this.d = iprot.readDouble(); this.__isset_d = true; } else { TProtocolUtil.skip(iprot, field.type); } break; case S: if (field.type == TType.STRING) { this.s = iprot.readString(); } else { TProtocolUtil.skip(iprot, field.type); } break; case L: if (field.type == TType.LIST) { { TList _list74 = iprot.readListBegin(); this.l = List(); for (int _i75 = 0; _i75 < _list74.length; ++_i75) { String _elem76; _elem76 = iprot.readString(); this.l.add(_elem76); } iprot.readListEnd(); } } else { TProtocolUtil.skip(iprot, field.type); } break; case B: if (field.type == TType.BOOL) { this.b = iprot.readBool(); this.__isset_b = true; } else { TProtocolUtil.skip(iprot, field.type); } break; default: TProtocolUtil.skip(iprot, field.type); break; } iprot.readFieldEnd(); } iprot.readStructEnd(); // check for required fields of primitive type, which can't be checked in the validate method validate(); } @override write(TProtocol oprot) { validate(); oprot.writeStructBegin(_STRUCT_DESC); oprot.writeFieldBegin(_I_FIELD_DESC); oprot.writeI32(this.i); oprot.writeFieldEnd(); oprot.writeFieldBegin(_D_FIELD_DESC); oprot.writeDouble(this.d); oprot.writeFieldEnd(); if (this.s != null) { oprot.writeFieldBegin(_S_FIELD_DESC); oprot.writeString(this.s); oprot.writeFieldEnd(); } if (this.l != null) { oprot.writeFieldBegin(_L_FIELD_DESC); { oprot.writeListBegin(TList(TType.STRING, this.l.length)); for (var elem77 in this.l) { oprot.writeString(elem77); } oprot.writeListEnd(); } oprot.writeFieldEnd(); } oprot.writeFieldBegin(_B_FIELD_DESC); oprot.writeBool(this.b); oprot.writeFieldEnd(); oprot.writeFieldStop(); oprot.writeStructEnd(); } @override String toString() { StringBuffer ret = StringBuffer("TestTObject("); ret.write("i:"); ret.write(this.i); ret.write(", "); ret.write("d:"); ret.write(this.d); ret.write(", "); ret.write("s:"); if (this.s == null) { ret.write("null"); } else { ret.write(this.s); } ret.write(", "); ret.write("l:"); if (this.l == null) { ret.write("null"); } else { ret.write(this.l); } ret.write(", "); ret.write("b:"); ret.write(this.b); ret.write(")"); return ret.toString(); } validate() { // check for required fields // check that fields of type enum have valid values } } thrift-0.19.0/lib/dart/analysis_options.yaml0000644000000000000000000000150414303740367021070 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # include: package:workiva_analysis_options/v1.yaml thrift-0.19.0/lib/dart/lib/0000777000000000000000000000000014303740367015360 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/thrift_console.dart0000644000000000000000000000177214303740367021261 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. library thrift_console; /// Classes that are only supported in console applications go here export 'src/console/t_tcp_socket.dart' show TTcpSocket; export 'src/console/t_web_socket.dart' show TWebSocket; thrift-0.19.0/lib/dart/lib/thrift_browser.dart0000644000000000000000000000170214303740367021273 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. library thrift_browser; /// Classes that are only supported in browser applications go here export 'src/browser/t_web_socket.dart' show TWebSocket; thrift-0.19.0/lib/dart/lib/src/0000777000000000000000000000000014303740367016147 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/src/console/0000777000000000000000000000000014303740367017611 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/src/console/t_web_socket.dart0000644000000000000000000000535314303740367023137 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. library thrift.src.console.t_web_socket; import 'dart:async'; import 'dart:convert' show base64; import 'dart:io'; import 'dart:typed_data' show Uint8List; import 'package:thrift/thrift.dart'; /// A [TSocket] backed by a [WebSocket] from dart:io class TWebSocket implements TSocket { final StreamController _onStateController; @override Stream get onState => _onStateController.stream; final StreamController _onErrorController; @override Stream get onError => _onErrorController.stream; final StreamController _onMessageController; @override Stream get onMessage => _onMessageController.stream; TWebSocket(WebSocket socket) : _onStateController = StreamController.broadcast(), _onErrorController = StreamController.broadcast(), _onMessageController = StreamController.broadcast() { if (socket == null) { throw ArgumentError.notNull('socket'); } _socket = socket; _socket.listen(_onMessage, onError: _onError, onDone: close); } WebSocket _socket; @override bool get isOpen => _socket != null; @override bool get isClosed => _socket == null; @override Future open() async { _onStateController.add(TSocketState.OPEN); } @override Future close() async { if (_socket != null) { await _socket.close(); _socket = null; } _onStateController.add(TSocketState.CLOSED); } @override void send(Uint8List data) { _socket.add(base64.encode(data)); } void _onMessage(String message) { try { Uint8List data = Uint8List.fromList(base64.decode(message)); _onMessageController.add(data); } on FormatException catch (_) { var error = TProtocolError(TProtocolErrorType.INVALID_DATA, "Expected a Base 64 encoded string."); _onErrorController.add(error); } } void _onError(Object error) { close(); _onErrorController.add('$error'); } } thrift-0.19.0/lib/dart/lib/src/console/t_tcp_socket.dart0000644000000000000000000000472314303740367023150 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. library thrift.src.console.t_tcp_socket; import 'dart:async'; import 'dart:io'; import 'dart:typed_data' show Uint8List; import 'package:thrift/thrift.dart'; /// A [TSocket] backed by a [Socket] from dart:io class TTcpSocket implements TSocket { final StreamController _onStateController; @override Stream get onState => _onStateController.stream; final StreamController _onErrorController; @override Stream get onError => _onErrorController.stream; final StreamController _onMessageController; @override Stream get onMessage => _onMessageController.stream; TTcpSocket(Socket socket) : _onStateController = StreamController.broadcast(), _onErrorController = StreamController.broadcast(), _onMessageController = StreamController.broadcast() { if (socket == null) { throw ArgumentError.notNull('socket'); } _socket = socket; _socket.listen(_onMessage, onError: _onError, onDone: close); } Socket _socket; @override bool get isOpen => _socket != null; @override bool get isClosed => _socket == null; @override Future open() async { _onStateController.add(TSocketState.OPEN); } @override Future close() async { if (_socket != null) { await _socket.close(); _socket = null; } _onStateController.add(TSocketState.CLOSED); } @override void send(Uint8List data) { _socket.add(data); } void _onMessage(List message) { Uint8List data = Uint8List.fromList(message); _onMessageController.add(data); } void _onError(Object error) { close(); _onErrorController.add('$error'); } } thrift-0.19.0/lib/dart/lib/src/protocol/0000777000000000000000000000000014303740367020010 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/src/protocol/t_set.dart0000644000000000000000000000164114303740367022000 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TSet { final int elementType; final int length; TSet(this.elementType, this.length); } thrift-0.19.0/lib/dart/lib/src/protocol/t_multiplexed_protocol.dart0000644000000000000000000000276014303740367025465 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// Adapted from the C# version. class TMultiplexedProtocol extends TProtocolDecorator { static const SEPARATOR = ':'; final String _serviceName; TMultiplexedProtocol(TProtocol protocol, String serviceName) : _serviceName = serviceName, super(protocol) { if (serviceName == null) { throw ArgumentError.notNull("serviceName"); } } @override void writeMessageBegin(TMessage message) { if (message.type == TMessageType.CALL || message.type == TMessageType.ONEWAY) { String name = _serviceName + SEPARATOR + message.name; message = TMessage(name, message.type, message.seqid); } super.writeMessageBegin(message); } } thrift-0.19.0/lib/dart/lib/src/protocol/t_protocol_error.dart0000644000000000000000000000235614303740367024263 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TProtocolErrorType { static const int UNKNOWN = 0; static const int INVALID_DATA = 1; static const int NEGATIVE_SIZE = 2; static const int SIZE_LIMIT = 3; static const int BAD_VERSION = 4; static const int NOT_IMPLEMENTED = 5; static const int DEPTH_LIMIT = 6; } class TProtocolError extends TError { TProtocolError([int type = TProtocolErrorType.UNKNOWN, String message = ""]) : super(type, message); } thrift-0.19.0/lib/dart/lib/src/protocol/t_type.dart0000644000000000000000000000231514303740367022165 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TType { static const int STOP = 0; static const int VOID = 1; static const int BOOL = 2; static const int BYTE = 3; static const int DOUBLE = 4; static const int I16 = 6; static const int I32 = 8; static const int I64 = 10; static const int STRING = 11; static const int STRUCT = 12; static const int MAP = 13; static const int SET = 14; static const int LIST = 15; } thrift-0.19.0/lib/dart/lib/src/protocol/t_protocol_decorator.dart0000644000000000000000000000774514303740367025123 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// Forward all operations to the wrapped protocol. Used as a base class. /// /// Adapted from the C# version. class TProtocolDecorator extends TProtocol { final TProtocol _protocol; TProtocolDecorator(TProtocol protocol) : _protocol = protocol, super(protocol.transport); /// Write @override void writeMessageBegin(TMessage message) { _protocol.writeMessageBegin(message); } @override void writeMessageEnd() { _protocol.writeMessageEnd(); } @override void writeStructBegin(TStruct struct) { _protocol.writeStructBegin(struct); } @override void writeStructEnd() { _protocol.writeStructEnd(); } @override void writeFieldBegin(TField field) { _protocol.writeFieldBegin(field); } @override void writeFieldEnd() { _protocol.writeFieldEnd(); } @override void writeFieldStop() { _protocol.writeFieldStop(); } @override void writeMapBegin(TMap map) { _protocol.writeMapBegin(map); } @override void writeMapEnd() { _protocol.writeMapEnd(); } @override void writeListBegin(TList list) { _protocol.writeListBegin(list); } @override void writeListEnd() { _protocol.writeListEnd(); } @override void writeSetBegin(TSet set) { _protocol.writeSetBegin(set); } @override void writeSetEnd() { _protocol.writeSetEnd(); } @override void writeBool(bool b) { _protocol.writeBool(b); } @override void writeByte(int b) { _protocol.writeByte(b); } @override void writeI16(int i16) { _protocol.writeI16(i16); } @override void writeI32(int i32) { _protocol.writeI32(i32); } @override void writeI64(int i64) { _protocol.writeI64(i64); } @override void writeDouble(double d) { _protocol.writeDouble(d); } @override void writeString(String str) { _protocol.writeString(str); } @override void writeBinary(Uint8List bytes) { _protocol.writeBinary(bytes); } /// Read @override TMessage readMessageBegin() => _protocol.readMessageBegin(); @override void readMessageEnd() => _protocol.readMessageEnd(); @override TStruct readStructBegin() => _protocol.readStructBegin(); @override void readStructEnd() => _protocol.readStructEnd(); @override TField readFieldBegin() => _protocol.readFieldBegin(); @override void readFieldEnd() => _protocol.readFieldEnd(); @override TMap readMapBegin() => _protocol.readMapBegin(); @override void readMapEnd() => _protocol.readMapEnd(); @override TList readListBegin() => _protocol.readListBegin(); @override void readListEnd() => _protocol.readListEnd(); @override TSet readSetBegin() => _protocol.readSetBegin(); @override void readSetEnd() => _protocol.readSetEnd(); @override bool readBool() => _protocol.readBool(); @override int readByte() => _protocol.readByte(); @override int readI16() => _protocol.readI16(); @override int readI32() => _protocol.readI32(); @override int readI64() => _protocol.readI64(); @override double readDouble() => _protocol.readDouble(); @override String readString() => _protocol.readString(); @override Uint8List readBinary() => _protocol.readBinary(); } thrift-0.19.0/lib/dart/lib/src/protocol/t_list.dart0000644000000000000000000000164314303740367022162 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TList { final int elementType; final int length; TList(this.elementType, this.length); } thrift-0.19.0/lib/dart/lib/src/protocol/t_protocol_util.dart0000644000000000000000000000562014303740367024104 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TProtocolUtil { // equal to JavaScript Number.MAX_SAFE_INTEGER, 2^53 - 1 static const int defaultRecursionLimit = 9007199254740991; static int maxRecursionLimit = defaultRecursionLimit; static skip(TProtocol prot, int type) { _skip(prot, type, maxRecursionLimit); } static _skip(TProtocol prot, int type, int recursionLimit) { if (recursionLimit <= 0) { throw TProtocolError( TProtocolErrorType.DEPTH_LIMIT, "Depth limit exceeded"); } switch (type) { case TType.BOOL: prot.readBool(); break; case TType.BYTE: prot.readByte(); break; case TType.I16: prot.readI16(); break; case TType.I32: prot.readI32(); break; case TType.I64: prot.readI64(); break; case TType.DOUBLE: prot.readDouble(); break; case TType.STRING: prot.readBinary(); break; case TType.STRUCT: prot.readStructBegin(); while (true) { TField field = prot.readFieldBegin(); if (field.type == TType.STOP) { break; } _skip(prot, field.type, recursionLimit - 1); prot.readFieldEnd(); } prot.readStructEnd(); break; case TType.MAP: TMap map = prot.readMapBegin(); for (int i = 0; i < map.length; i++) { _skip(prot, map.keyType, recursionLimit - 1); _skip(prot, map.valueType, recursionLimit - 1); } prot.readMapEnd(); break; case TType.SET: TSet set = prot.readSetBegin(); for (int i = 0; i < set.length; i++) { _skip(prot, set.elementType, recursionLimit - 1); } prot.readSetEnd(); break; case TType.LIST: TList list = prot.readListBegin(); for (int i = 0; i < list.length; i++) { _skip(prot, list.elementType, recursionLimit - 1); } prot.readListEnd(); break; default: throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Invalid data"); } } } thrift-0.19.0/lib/dart/lib/src/protocol/t_map.dart0000644000000000000000000000170014303740367021756 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TMap { final int keyType; final int valueType; final int length; TMap(this.keyType, this.valueType, this.length); } thrift-0.19.0/lib/dart/lib/src/protocol/t_compact_protocol.dart0000644000000000000000000003031614303740367024555 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// 'License'); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TCompactProtocolFactory implements TProtocolFactory { TCompactProtocolFactory(); @override TCompactProtocol getProtocol(TTransport transport) { return TCompactProtocol(transport); } } /// Compact protocol implementation for Thrift. /// /// Use of fixnum library is required due to bugs like /// https://github.com/dart-lang/sdk/issues/15361 /// /// Adapted from the Java version. class TCompactProtocol extends TProtocol { static const int PROTOCOL_ID = 0x82; static const int VERSION = 1; static const int VERSION_MASK = 0x1f; static const int TYPE_MASK = 0xE0; static const int TYPE_BITS = 0x07; static const int TYPE_SHIFT_AMOUNT = 5; static final TField TSTOP = TField("", TType.STOP, 0); static const int TYPE_BOOLEAN_TRUE = 0x01; static const int TYPE_BOOLEAN_FALSE = 0x02; static const int TYPE_BYTE = 0x03; static const int TYPE_I16 = 0x04; static const int TYPE_I32 = 0x05; static const int TYPE_I64 = 0x06; static const int TYPE_DOUBLE = 0x07; static const int TYPE_BINARY = 0x08; static const int TYPE_LIST = 0x09; static const int TYPE_SET = 0x0A; static const int TYPE_MAP = 0x0B; static const int TYPE_STRUCT = 0x0C; static final List _typeMap = List.unmodifiable(List(16) ..[TType.STOP] = TType.STOP ..[TType.BOOL] = TYPE_BOOLEAN_TRUE ..[TType.BYTE] = TYPE_BYTE ..[TType.I16] = TYPE_I16 ..[TType.I32] = TYPE_I32 ..[TType.I64] = TYPE_I64 ..[TType.DOUBLE] = TYPE_DOUBLE ..[TType.STRING] = TYPE_BINARY ..[TType.LIST] = TYPE_LIST ..[TType.SET] = TYPE_SET ..[TType.MAP] = TYPE_MAP ..[TType.STRUCT] = TYPE_STRUCT); static const Utf8Codec _utf8Codec = Utf8Codec(); // Pretend this is a stack DoubleLinkedQueue _lastField = DoubleLinkedQueue(); int _lastFieldId = 0; TField _booleanField; bool _boolValue; final Uint8List tempList = Uint8List(10); final ByteData tempBD = ByteData(10); TCompactProtocol(TTransport transport) : super(transport); /// Write @override void writeMessageBegin(TMessage message) { writeByte(PROTOCOL_ID); writeByte((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); _writeVarInt32(Int32(message.seqid)); writeString(message.name); } @override void writeMessageEnd() {} @override void writeStructBegin(TStruct struct) { _lastField.addLast(_lastFieldId); _lastFieldId = 0; } @override void writeStructEnd() { _lastFieldId = _lastField.removeLast(); } @override void writeFieldBegin(TField field) { if (field.type == TType.BOOL) { _booleanField = field; } else { _writeFieldBegin(field, -1); } } void _writeFieldBegin(TField field, int typeOverride) { int typeToWrite = typeOverride == -1 ? _getCompactType(field.type) : typeOverride; if (field.id > _lastFieldId && field.id - _lastFieldId <= 15) { writeByte((field.id - _lastFieldId) << 4 | typeToWrite); } else { writeByte(typeToWrite); writeI16(field.id); } _lastFieldId = field.id; } @override void writeFieldEnd() {} @override void writeFieldStop() { writeByte(TType.STOP); } @override void writeMapBegin(TMap map) { if (map.length == 0) { writeByte(0); } else { _writeVarInt32(Int32(map.length)); writeByte( _getCompactType(map.keyType) << 4 | _getCompactType(map.valueType)); } } @override void writeMapEnd() {} @override void writeListBegin(TList list) { _writeCollectionBegin(list.elementType, list.length); } @override void writeListEnd() {} @override void writeSetBegin(TSet set) { _writeCollectionBegin(set.elementType, set.length); } @override void writeSetEnd() {} @override void writeBool(bool b) { if (b == null) b = false; if (_booleanField != null) { _writeFieldBegin( _booleanField, b ? TYPE_BOOLEAN_TRUE : TYPE_BOOLEAN_FALSE); _booleanField = null; } else { writeByte(b ? TYPE_BOOLEAN_TRUE : TYPE_BOOLEAN_FALSE); } } @override void writeByte(int b) { if (b == null) b = 0; tempList[0] = b; transport.write(tempList, 0, 1); } @override void writeI16(int i16) { if (i16 == null) i16 = 0; _writeVarInt32(_int32ToZigZag(Int32(i16))); } @override void writeI32(int i32) { if (i32 == null) i32 = 0; _writeVarInt32(_int32ToZigZag(Int32(i32))); } @override void writeI64(int i64) { if (i64 == null) i64 = 0; _writeVarInt64(_int64ToZigZag(Int64(i64))); } @override void writeDouble(double d) { if (d == null) d = 0.0; tempBD.setFloat64(0, d, Endian.little); transport.write(tempBD.buffer.asUint8List(), 0, 8); } @override void writeString(String str) { Uint8List bytes = str != null ? _utf8Codec.encode(str) : Uint8List.fromList([]); writeBinary(bytes); } @override void writeBinary(Uint8List bytes) { _writeVarInt32(Int32(bytes.length)); transport.write(bytes, 0, bytes.length); } void _writeVarInt32(Int32 n) { int idx = 0; while (true) { if ((n & ~0x7F) == 0) { tempList[idx++] = (n & 0xFF).toInt(); break; } else { tempList[idx++] = (((n & 0x7F) | 0x80) & 0xFF).toInt(); n = n.shiftRightUnsigned(7); } } transport.write(tempList, 0, idx); } void _writeVarInt64(Int64 n) { int idx = 0; while (true) { if ((n & ~0x7F) == 0) { tempList[idx++] = (n & 0xFF).toInt(); break; } else { tempList[idx++] = (((n & 0x7F) | 0x80) & 0xFF).toInt(); n = n.shiftRightUnsigned(7); } } transport.write(tempList, 0, idx); } void _writeCollectionBegin(int elemType, int length) { if (length <= 14) { writeByte(length << 4 | _getCompactType(elemType)); } else { writeByte(0xF0 | _getCompactType(elemType)); _writeVarInt32(Int32(length)); } } Int32 _int32ToZigZag(Int32 n) { return (n << 1) ^ (n >> 31); } Int64 _int64ToZigZag(Int64 n) { return (n << 1) ^ (n >> 63); } // Read @override TMessage readMessageBegin() { int protocolId = readByte(); if (protocolId != PROTOCOL_ID) { throw TProtocolError(TProtocolErrorType.BAD_VERSION, 'Expected protocol id $PROTOCOL_ID but got $protocolId'); } int versionAndType = readByte(); int version = versionAndType & VERSION_MASK; if (version != VERSION) { throw TProtocolError(TProtocolErrorType.BAD_VERSION, 'Expected version $VERSION but got $version'); } int type = (versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS; int seqId = _readVarInt32().toInt(); String messageName = readString(); return TMessage(messageName, type, seqId); } @override void readMessageEnd() {} @override TStruct readStructBegin() { _lastField.addLast(_lastFieldId); _lastFieldId = 0; // TODO make this a constant? return TStruct(); } @override void readStructEnd() { _lastFieldId = _lastField.removeLast(); } @override TField readFieldBegin() { int type = readByte(); if (type == TType.STOP) { return TSTOP; } int fieldId; int modifier = (type & 0xF0) >> 4; if (modifier == 0) { fieldId = readI16(); } else { fieldId = _lastFieldId + modifier; } TField field = TField('', _getTType(type & 0x0F), fieldId); if (_isBoolType(type)) { _boolValue = (type & 0x0F) == TYPE_BOOLEAN_TRUE; } _lastFieldId = field.id; return field; } @override void readFieldEnd() {} @override TMap readMapBegin() { int length = _readVarInt32().toInt(); _checkNegReadLength(length); int keyAndValueType = length == 0 ? 0 : readByte(); int keyType = _getTType(keyAndValueType >> 4); int valueType = _getTType(keyAndValueType & 0x0F); return TMap(keyType, valueType, length); } @override void readMapEnd() {} @override TList readListBegin() { int lengthAndType = readByte(); int length = (lengthAndType >> 4) & 0x0F; if (length == 15) { length = _readVarInt32().toInt(); } _checkNegReadLength(length); int type = _getTType(lengthAndType); return TList(type, length); } @override void readListEnd() {} @override TSet readSetBegin() { TList tlist = readListBegin(); return TSet(tlist.elementType, tlist.length); } @override void readSetEnd() {} @override bool readBool() { if (_boolValue != null) { bool result = _boolValue; _boolValue = null; return result; } return readByte() == TYPE_BOOLEAN_TRUE; } @override int readByte() { transport.readAll(tempList, 0, 1); return tempList.buffer.asByteData().getUint8(0); } @override int readI16() { return _zigzagToInt32(_readVarInt32()).toInt(); } @override int readI32() { return _zigzagToInt32(_readVarInt32()).toInt(); } @override int readI64() { return _zigzagToInt64(_readVarInt64()).toInt(); } @override double readDouble() { transport.readAll(tempList, 0, 8); return tempList.buffer.asByteData().getFloat64(0, Endian.little); } @override String readString() { int length = _readVarInt32().toInt(); _checkNegReadLength(length); // TODO look at using temp for small strings? Uint8List buff = Uint8List(length); transport.readAll(buff, 0, length); return _utf8Codec.decode(buff); } @override Uint8List readBinary() { int length = _readVarInt32().toInt(); _checkNegReadLength(length); Uint8List buff = Uint8List(length); transport.readAll(buff, 0, length); return buff; } Int32 _readVarInt32() { Int32 result = Int32.ZERO; int shift = 0; while (true) { Int32 b = Int32(readByte()); result |= (b & 0x7f) << shift; if ((b & 0x80) != 0x80) break; shift += 7; } return result; } Int64 _readVarInt64() { Int64 result = Int64.ZERO; int shift = 0; while (true) { Int64 b = Int64(readByte()); result |= (b & 0x7f) << shift; if ((b & 0x80) != 0x80) break; shift += 7; } return result; } Int32 _zigzagToInt32(Int32 n) { return (n.shiftRightUnsigned(1)) ^ -(n & 1); } Int64 _zigzagToInt64(Int64 n) { return (n.shiftRightUnsigned(1)) ^ -(n & 1); } void _checkNegReadLength(int length) { if (length < 0) { throw TProtocolError( TProtocolErrorType.NEGATIVE_SIZE, 'Negative length: $length'); } } int _getCompactType(int ttype) { return _typeMap[ttype]; } int _getTType(int type) { switch (type & 0x0F) { case TType.STOP: return TType.STOP; case TYPE_BOOLEAN_FALSE: case TYPE_BOOLEAN_TRUE: return TType.BOOL; case TYPE_BYTE: return TType.BYTE; case TYPE_I16: return TType.I16; case TYPE_I32: return TType.I32; case TYPE_I64: return TType.I64; case TYPE_DOUBLE: return TType.DOUBLE; case TYPE_BINARY: return TType.STRING; case TYPE_LIST: return TType.LIST; case TYPE_SET: return TType.SET; case TYPE_MAP: return TType.MAP; case TYPE_STRUCT: return TType.STRUCT; default: throw TProtocolError( TProtocolErrorType.INVALID_DATA, "Unknown type: ${type & 0x0F}"); } } bool _isBoolType(int b) { int lowerNibble = b & 0x0F; return lowerNibble == TYPE_BOOLEAN_TRUE || lowerNibble == TYPE_BOOLEAN_FALSE; } } thrift-0.19.0/lib/dart/lib/src/protocol/t_protocol_factory.dart0000644000000000000000000000163514303740367024600 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; abstract class TProtocolFactory { T getProtocol(TTransport transport); } thrift-0.19.0/lib/dart/lib/src/protocol/t_field.dart0000644000000000000000000000165714303740367022277 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TField { final String name; final int type; final int id; TField(this.name, this.type, this.id); } thrift-0.19.0/lib/dart/lib/src/protocol/t_binary_protocol.dart0000644000000000000000000001633014303740367024413 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TBinaryProtocolFactory implements TProtocolFactory { TBinaryProtocolFactory({this.strictRead = false, this.strictWrite = true}); final bool strictRead; final bool strictWrite; @override TBinaryProtocol getProtocol(TTransport transport) { return TBinaryProtocol(transport, strictRead: strictRead, strictWrite: strictWrite); } } /// Binary protocol implementation for Thrift. /// /// Adapted from the C# version. class TBinaryProtocol extends TProtocol { static const int VERSION_MASK = 0xffff0000; static const int VERSION_1 = 0x80010000; static const Utf8Codec _utf8Codec = Utf8Codec(); final bool strictRead; final bool strictWrite; TBinaryProtocol(TTransport transport, {this.strictRead = false, this.strictWrite = true}) : super(transport); /// write @override void writeMessageBegin(TMessage message) { if (strictWrite) { int version = VERSION_1 | message.type; writeI32(version); writeString(message.name); writeI32(message.seqid); } else { writeString(message.name); writeByte(message.type); writeI32(message.seqid); } } @override void writeMessageEnd() {} @override void writeStructBegin(TStruct struct) {} @override void writeStructEnd() {} @override void writeFieldBegin(TField field) { writeByte(field.type); writeI16(field.id); } @override void writeFieldEnd() {} @override void writeFieldStop() { writeByte(TType.STOP); } @override void writeMapBegin(TMap map) { writeByte(map.keyType); writeByte(map.valueType); writeI32(map.length); } @override void writeMapEnd() {} @override void writeListBegin(TList list) { writeByte(list.elementType); writeI32(list.length); } @override void writeListEnd() {} @override void writeSetBegin(TSet set) { writeByte(set.elementType); writeI32(set.length); } @override void writeSetEnd() {} @override void writeBool(bool b) { if (b == null) b = false; writeByte(b ? 1 : 0); } final ByteData _byteOut = ByteData(1); @override void writeByte(int byte) { if (byte == null) byte = 0; _byteOut.setUint8(0, byte); transport.write(_byteOut.buffer.asUint8List(), 0, 1); } final ByteData _i16Out = ByteData(2); @override void writeI16(int i16) { if (i16 == null) i16 = 0; _i16Out.setInt16(0, i16); transport.write(_i16Out.buffer.asUint8List(), 0, 2); } final ByteData _i32Out = ByteData(4); @override void writeI32(int i32) { if (i32 == null) i32 = 0; _i32Out.setInt32(0, i32); transport.write(_i32Out.buffer.asUint8List(), 0, 4); } final Uint8List _i64Out = Uint8List(8); @override void writeI64(int i64) { if (i64 == null) i64 = 0; var i = Int64(i64); var bts = i.toBytes(); for (var j = 0; j < 8; j++) { _i64Out[j] = bts[8 - j - 1]; } transport.write(_i64Out, 0, 8); } @override void writeString(String s) { var bytes = s != null ? _utf8Codec.encode(s) : Uint8List.fromList([]); writeI32(bytes.length); transport.write(bytes, 0, bytes.length); } final ByteData _doubleOut = ByteData(8); @override void writeDouble(double d) { if (d == null) d = 0.0; _doubleOut.setFloat64(0, d); transport.write(_doubleOut.buffer.asUint8List(), 0, 8); } @override void writeBinary(Uint8List bytes) { var length = bytes.length; writeI32(length); transport.write(bytes, 0, length); } /// read @override TMessage readMessageBegin() { String name; int type; int seqid; int size = readI32(); if (size < 0) { int version = size & VERSION_MASK; if (version != VERSION_1) { throw TProtocolError(TProtocolErrorType.BAD_VERSION, "Bad version in readMessageBegin: $version"); } type = size & 0x000000ff; name = readString(); seqid = readI32(); } else { if (strictRead) { throw TProtocolError(TProtocolErrorType.BAD_VERSION, "Missing version in readMessageBegin"); } name = _readString(size); type = readByte(); seqid = readI32(); } return TMessage(name, type, seqid); } @override void readMessageEnd() {} @override TStruct readStructBegin() { return TStruct(); } @override void readStructEnd() {} @override TField readFieldBegin() { String name = ""; int type = readByte(); int id = type != TType.STOP ? readI16() : 0; return TField(name, type, id); } @override void readFieldEnd() {} @override TMap readMapBegin() { int keyType = readByte(); int valueType = readByte(); int length = readI32(); return TMap(keyType, valueType, length); } @override void readMapEnd() {} @override TList readListBegin() { int elementType = readByte(); int length = readI32(); return TList(elementType, length); } @override void readListEnd() {} @override TSet readSetBegin() { int elementType = readByte(); int length = readI32(); return TSet(elementType, length); } @override void readSetEnd() {} @override bool readBool() => readByte() == 1; final Uint8List _byteIn = Uint8List(1); @override int readByte() { transport.readAll(_byteIn, 0, 1); return _byteIn.buffer.asByteData().getUint8(0); } final Uint8List _i16In = Uint8List(2); @override int readI16() { transport.readAll(_i16In, 0, 2); return _i16In.buffer.asByteData().getInt16(0); } final Uint8List _i32In = Uint8List(4); @override int readI32() { transport.readAll(_i32In, 0, 4); return _i32In.buffer.asByteData().getInt32(0); } final Uint8List _i64In = Uint8List(8); @override int readI64() { transport.readAll(_i64In, 0, 8); var i = Int64.fromBytesBigEndian(_i64In); return i.toInt(); } final Uint8List _doubleIn = Uint8List(8); @override double readDouble() { transport.readAll(_doubleIn, 0, 8); return _doubleIn.buffer.asByteData().getFloat64(0); } @override String readString() { int size = readI32(); return _readString(size); } String _readString(int size) { Uint8List stringIn = Uint8List(size); transport.readAll(stringIn, 0, size); return _utf8Codec.decode(stringIn); } @override Uint8List readBinary() { int length = readI32(); Uint8List binaryIn = Uint8List(length); transport.readAll(binaryIn, 0, length); return binaryIn; } } thrift-0.19.0/lib/dart/lib/src/protocol/t_json_protocol.dart0000644000000000000000000005131114303740367024076 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TJsonProtocolFactory implements TProtocolFactory { @override TJsonProtocol getProtocol(TTransport transport) { return TJsonProtocol(transport); } } /// JSON protocol implementation for Thrift. /// /// Adapted from the C# version. class TJsonProtocol extends TProtocol { static const int VERSION_1 = 1; static const Utf8Codec utf8Codec = Utf8Codec(); _BaseContext _context; _BaseContext _rootContext; _LookaheadReader _reader; final List<_BaseContext> _contextStack = []; final Uint8List _tempBuffer = Uint8List(4); TJsonProtocol(TTransport transport) : super(transport) { _rootContext = _BaseContext(this); _reader = _LookaheadReader(this); _resetContext(); } void _pushContext(_BaseContext c) { _contextStack.add(c); _context = c; } void _popContext() { _contextStack.removeLast(); _context = _contextStack.isEmpty ? _rootContext : _contextStack.last; } void _resetContext() { _contextStack.clear(); _context = _rootContext; } /// Read a byte that must match [char]; otherwise throw a [TProtocolError]. void _readJsonSyntaxChar(int charByte) { int byte = _reader.read(); if (byte != charByte) { throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Expected character ${String.fromCharCode(charByte)} but found: ${String.fromCharCode(byte)}"); } } int _hexVal(int byte) { if (byte >= _Constants.HEX_0_BYTES[0] && byte <= _Constants.HEX_9_BYTES[0]) { return byte - _Constants.HEX_0_BYTES[0]; } else if (byte >= _Constants.HEX_A_BYTES[0] && byte <= _Constants.HEX_F_BYTES[0]) { byte += 10; return byte - _Constants.HEX_A_BYTES[0]; } else { throw TProtocolError( TProtocolErrorType.INVALID_DATA, "Expected hex character"); } } int _hexChar(int byte) => byte.toRadixString(16).codeUnitAt(0); /// write /// Write the [bytes] as JSON characters, escaping as needed. void _writeJsonString(Uint8List bytes) { _context.write(); transport.writeAll(_Constants.QUOTE_BYTES); int length = bytes.length; for (int i = 0; i < length; i++) { int byte = bytes[i]; if ((byte & 0x00FF) >= 0x30) { if (byte == _Constants.BACKSLASH_BYTES[0]) { transport.writeAll(_Constants.BACKSLASH_BYTES); transport.writeAll(_Constants.BACKSLASH_BYTES); } else { transport.write(bytes, i, 1); } } else { _tempBuffer[0] = _Constants.JSON_CHAR_TABLE[byte]; if (_tempBuffer[0] == 1) { transport.write(bytes, i, 1); } else if (_tempBuffer[0] > 1) { transport.writeAll(_Constants.BACKSLASH_BYTES); transport.write(_tempBuffer, 0, 1); } else { transport.writeAll(_Constants.ESCSEQ_BYTES); _tempBuffer[0] = _hexChar(byte >> 4); _tempBuffer[1] = _hexChar(byte); transport.write(_tempBuffer, 0, 2); } } } transport.writeAll(_Constants.QUOTE_BYTES); } void _writeJsonInteger(int i) { if (i == null) i = 0; _context.write(); String str = i.toString(); if (_context.escapeNumbers) { transport.writeAll(_Constants.QUOTE_BYTES); } transport.writeAll(utf8Codec.encode(str)); if (_context.escapeNumbers) { transport.writeAll(_Constants.QUOTE_BYTES); } } void _writeJsonDouble(double d) { if (d == null) d = 0.0; _context.write(); String str = d.toString(); bool escapeNumbers = d.isNaN || d.isInfinite || _context.escapeNumbers; if (escapeNumbers) { transport.writeAll(_Constants.QUOTE_BYTES); } transport.writeAll(utf8Codec.encode(str)); if (escapeNumbers) { transport.writeAll(_Constants.QUOTE_BYTES); } } void _writeJsonBase64(Uint8List bytes) { _context.write(); transport.writeAll(_Constants.QUOTE_BYTES); String base64text = base64.encode(bytes); transport.writeAll(utf8Codec.encode(base64text)); transport.writeAll(_Constants.QUOTE_BYTES); } void _writeJsonObjectStart() { _context.write(); transport.writeAll(_Constants.LBRACE_BYTES); _pushContext(_PairContext(this)); } void _writeJsonObjectEnd() { _popContext(); transport.writeAll(_Constants.RBRACE_BYTES); } void _writeJsonArrayStart() { _context.write(); transport.writeAll(_Constants.LBRACKET_BYTES); _pushContext(_ListContext(this)); } void _writeJsonArrayEnd() { _popContext(); transport.writeAll(_Constants.RBRACKET_BYTES); } @override void writeMessageBegin(TMessage message) { _resetContext(); _writeJsonArrayStart(); _writeJsonInteger(VERSION_1); _writeJsonString(utf8Codec.encode(message.name)); _writeJsonInteger(message.type); _writeJsonInteger(message.seqid); } @override void writeMessageEnd() { _writeJsonArrayEnd(); } @override void writeStructBegin(TStruct struct) { _writeJsonObjectStart(); } @override void writeStructEnd() { _writeJsonObjectEnd(); } @override void writeFieldBegin(TField field) { _writeJsonInteger(field.id); _writeJsonObjectStart(); _writeJsonString(_Constants.getTypeNameBytesForTypeId(field.type)); } @override void writeFieldEnd() { _writeJsonObjectEnd(); } @override void writeFieldStop() {} @override void writeMapBegin(TMap map) { _writeJsonArrayStart(); _writeJsonString(_Constants.getTypeNameBytesForTypeId(map.keyType)); _writeJsonString(_Constants.getTypeNameBytesForTypeId(map.valueType)); _writeJsonInteger(map.length); _writeJsonObjectStart(); } @override void writeMapEnd() { _writeJsonObjectEnd(); _writeJsonArrayEnd(); } @override void writeListBegin(TList list) { _writeJsonArrayStart(); _writeJsonString(_Constants.getTypeNameBytesForTypeId(list.elementType)); _writeJsonInteger(list.length); } @override void writeListEnd() { _writeJsonArrayEnd(); } @override void writeSetBegin(TSet set) { _writeJsonArrayStart(); _writeJsonString(_Constants.getTypeNameBytesForTypeId(set.elementType)); _writeJsonInteger(set.length); } @override void writeSetEnd() { _writeJsonArrayEnd(); } @override void writeBool(bool b) { if (b == null) b = false; _writeJsonInteger(b ? 1 : 0); } @override void writeByte(int b) { _writeJsonInteger(b); } @override void writeI16(int i16) { _writeJsonInteger(i16); } @override void writeI32(int i32) { _writeJsonInteger(i32); } @override void writeI64(int i64) { _writeJsonInteger(i64); } @override void writeDouble(double d) { _writeJsonDouble(d); } @override void writeString(String s) { var bytes = s != null ? utf8Codec.encode(s) : Uint8List.fromList([]); _writeJsonString(bytes); } @override void writeBinary(Uint8List bytes) { _writeJsonBase64(bytes); } bool _isHighSurrogate(int b) => b >= 0xD800 && b <= 0xDBFF; bool _isLowSurrogate(int b) => b >= 0xDC00 && b <= 0xDFFF; /// read Uint8List _readJsonString({bool skipContext = false}) { List bytes = []; List codeunits = []; if (!skipContext) { _context.read(); } _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); while (true) { int byte = _reader.read(); if (byte == _Constants.QUOTE_BYTES[0]) { break; } // escaped? if (byte != _Constants.ESCSEQ_BYTES[0]) { bytes.add(byte); continue; } byte = _reader.read(); // distinguish between \uXXXX and control chars like \n if (byte != _Constants.ESCSEQ_BYTES[1]) { String char = String.fromCharCode(byte); int offset = _Constants.ESCAPE_CHARS.indexOf(char); if (offset == -1) { throw TProtocolError( TProtocolErrorType.INVALID_DATA, "Expected control char"); } byte = _Constants.ESCAPE_CHAR_VALS.codeUnitAt(offset); bytes.add(byte); continue; } // it's \uXXXX transport.readAll(_tempBuffer, 0, 4); byte = (_hexVal(_tempBuffer[0]) << 12) + (_hexVal(_tempBuffer[1]) << 8) + (_hexVal(_tempBuffer[2]) << 4) + _hexVal(_tempBuffer[3]); if (_isHighSurrogate(byte)) { if (codeunits.isNotEmpty) { throw TProtocolError( TProtocolErrorType.INVALID_DATA, "Expected low surrogate"); } codeunits.add(byte); } else if (_isLowSurrogate(byte)) { if (codeunits.isEmpty) { throw TProtocolError( TProtocolErrorType.INVALID_DATA, "Expected high surrogate"); } codeunits.add(byte); bytes.addAll(utf8Codec.encode(String.fromCharCodes(codeunits))); codeunits.clear(); } else { bytes.addAll(utf8Codec.encode(String.fromCharCode(byte))); } } if (codeunits.isNotEmpty) { throw TProtocolError( TProtocolErrorType.INVALID_DATA, "Expected low surrogate"); } return Uint8List.fromList(bytes); } String _readJsonNumericChars() { StringBuffer buffer = StringBuffer(); while (true) { if (!_Constants.isJsonNumeric(_reader.peek())) { break; } buffer.write(String.fromCharCode(_reader.read())); } return buffer.toString(); } int _readJsonInteger() { _context.read(); if (_context.escapeNumbers) { _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); } String str = _readJsonNumericChars(); if (_context.escapeNumbers) { _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); } try { return int.parse(str); } on FormatException catch (_) { throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Bad data encounted in numeric data"); } } double _readJsonDouble() { _context.read(); if (_reader.peek() == _Constants.QUOTE_BYTES[0]) { Uint8List bytes = _readJsonString(skipContext: true); double d; try { d = double.tryParse(utf8Codec.decode(bytes)); } catch (_) { throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Bad data encounted in numeric data"); } if (!_context.escapeNumbers && !d.isNaN && !d.isInfinite) { throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Numeric data unexpectedly quoted"); } return d; } else { if (_context.escapeNumbers) { // This will throw - we should have had a quote if escapeNumbers == true _readJsonSyntaxChar(_Constants.QUOTE_BYTES[0]); } try { return double.parse(_readJsonNumericChars()); } on FormatException catch (_) { throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Bad data encounted in numeric data"); } } } Uint8List _readJsonBase64() { // convert UTF-8 bytes of a Base 64 encoded string to binary bytes Uint8List base64Bytes = _readJsonString(); String base64text = utf8Codec.decode(base64Bytes); return Uint8List.fromList(base64.decode(base64text)); } void _readJsonObjectStart() { _context.read(); _readJsonSyntaxChar(_Constants.LBRACE_BYTES[0]); _pushContext(_PairContext(this)); } void _readJsonObjectEnd() { _readJsonSyntaxChar(_Constants.RBRACE_BYTES[0]); _popContext(); } void _readJsonArrayStart() { _context.read(); _readJsonSyntaxChar(_Constants.LBRACKET_BYTES[0]); _pushContext(_ListContext(this)); } void _readJsonArrayEnd() { _readJsonSyntaxChar(_Constants.RBRACKET_BYTES[0]); _popContext(); } @override TMessage readMessageBegin() { _resetContext(); _readJsonArrayStart(); if (_readJsonInteger() != VERSION_1) { throw TProtocolError( TProtocolErrorType.BAD_VERSION, "Message contained bad version."); } Uint8List buffer = _readJsonString(); String name = utf8Codec.decode(buffer); int type = _readJsonInteger(); int seqid = _readJsonInteger(); return TMessage(name, type, seqid); } @override void readMessageEnd() { _readJsonArrayEnd(); } @override TStruct readStructBegin() { _readJsonObjectStart(); return TStruct(); } @override void readStructEnd() { _readJsonObjectEnd(); } @override TField readFieldBegin() { String name = ""; int type = TType.STOP; int id = 0; if (_reader.peek() != _Constants.RBRACE_BYTES[0]) { id = _readJsonInteger(); _readJsonObjectStart(); type = _Constants.getTypeIdForTypeName(_readJsonString()); } return TField(name, type, id); } @override void readFieldEnd() { _readJsonObjectEnd(); } @override TMap readMapBegin() { _readJsonArrayStart(); int keyType = _Constants.getTypeIdForTypeName(_readJsonString()); int valueType = _Constants.getTypeIdForTypeName(_readJsonString()); int length = _readJsonInteger(); _readJsonObjectStart(); return TMap(keyType, valueType, length); } @override void readMapEnd() { _readJsonObjectEnd(); _readJsonArrayEnd(); } @override TList readListBegin() { _readJsonArrayStart(); int elementType = _Constants.getTypeIdForTypeName(_readJsonString()); int length = _readJsonInteger(); return TList(elementType, length); } @override void readListEnd() { _readJsonArrayEnd(); } @override TSet readSetBegin() { _readJsonArrayStart(); int elementType = _Constants.getTypeIdForTypeName(_readJsonString()); int length = _readJsonInteger(); return TSet(elementType, length); } @override void readSetEnd() { _readJsonArrayEnd(); } @override bool readBool() { return _readJsonInteger() == 0 ? false : true; } @override int readByte() { return _readJsonInteger(); } @override int readI16() { return _readJsonInteger(); } @override int readI32() { return _readJsonInteger(); } @override int readI64() { return _readJsonInteger(); } @override double readDouble() { return _readJsonDouble(); } @override String readString() { return utf8Codec.decode(_readJsonString()); } @override Uint8List readBinary() { return Uint8List.fromList(_readJsonBase64()); } } class _Constants { static const utf8codec = Utf8Codec(); static final Uint8List HEX_0_BYTES = Uint8List.fromList('0'.codeUnits); static final Uint8List HEX_9_BYTES = Uint8List.fromList('9'.codeUnits); static final Uint8List HEX_A_BYTES = Uint8List.fromList('a'.codeUnits); static final Uint8List HEX_F_BYTES = Uint8List.fromList('f'.codeUnits); static final Uint8List COMMA_BYTES = Uint8List.fromList(','.codeUnits); static final Uint8List COLON_BYTES = Uint8List.fromList(':'.codeUnits); static final Uint8List LBRACE_BYTES = Uint8List.fromList('{'.codeUnits); static final Uint8List RBRACE_BYTES = Uint8List.fromList('}'.codeUnits); static final Uint8List LBRACKET_BYTES = Uint8List.fromList('['.codeUnits); static final Uint8List RBRACKET_BYTES = Uint8List.fromList(']'.codeUnits); static final Uint8List QUOTE_BYTES = Uint8List.fromList('"'.codeUnits); static final Uint8List BACKSLASH_BYTES = Uint8List.fromList(r'\'.codeUnits); static final ESCSEQ_BYTES = Uint8List.fromList(r'\u00'.codeUnits); static final Uint8List JSON_CHAR_TABLE = Uint8List.fromList([ 0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes 'b'.codeUnitAt(0), 't'.codeUnitAt(0), 'n'.codeUnitAt(0), 0, // 4 bytes 'f'.codeUnitAt(0), 'r'.codeUnitAt(0), 0, 0, // 4 bytes 0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes 0, 0, 0, 0, 0, 0, 0, 0, // 8 bytes 1, 1, '"'.codeUnitAt(0), 1, 1, 1, 1, 1, // 8 bytes 1, 1, 1, 1, 1, 1, 1, 1 // 8 bytes ]); static const String ESCAPE_CHARS = r'"\/bfnrt'; static const String ESCAPE_CHAR_VALS = '"\\/\b\f\n\r\t'; static const String NAME_BOOL = 'tf'; static const String NAME_BYTE = 'i8'; static const String NAME_I16 = 'i16'; static const String NAME_I32 = 'i32'; static const String NAME_I64 = 'i64'; static const String NAME_DOUBLE = 'dbl'; static const String NAME_STRUCT = 'rec'; static const String NAME_STRING = 'str'; static const String NAME_MAP = 'map'; static const String NAME_LIST = 'lst'; static const String NAME_SET = 'set'; static final Map _TYPE_ID_TO_NAME_BYTES = Map.unmodifiable({ TType.BOOL: Uint8List.fromList(NAME_BOOL.codeUnits), TType.BYTE: Uint8List.fromList(NAME_BYTE.codeUnits), TType.I16: Uint8List.fromList(NAME_I16.codeUnits), TType.I32: Uint8List.fromList(NAME_I32.codeUnits), TType.I64: Uint8List.fromList(NAME_I64.codeUnits), TType.DOUBLE: Uint8List.fromList(NAME_DOUBLE.codeUnits), TType.STRING: Uint8List.fromList(NAME_STRING.codeUnits), TType.STRUCT: Uint8List.fromList(NAME_STRUCT.codeUnits), TType.MAP: Uint8List.fromList(NAME_MAP.codeUnits), TType.SET: Uint8List.fromList(NAME_SET.codeUnits), TType.LIST: Uint8List.fromList(NAME_LIST.codeUnits) }); static Uint8List getTypeNameBytesForTypeId(int typeId) { if (!_TYPE_ID_TO_NAME_BYTES.containsKey(typeId)) { throw TProtocolError( TProtocolErrorType.NOT_IMPLEMENTED, "Unrecognized type"); } return _TYPE_ID_TO_NAME_BYTES[typeId]; } static final Map _NAME_TO_TYPE_ID = Map.unmodifiable({ NAME_BOOL: TType.BOOL, NAME_BYTE: TType.BYTE, NAME_I16: TType.I16, NAME_I32: TType.I32, NAME_I64: TType.I64, NAME_DOUBLE: TType.DOUBLE, NAME_STRING: TType.STRING, NAME_STRUCT: TType.STRUCT, NAME_MAP: TType.MAP, NAME_SET: TType.SET, NAME_LIST: TType.LIST }); static int getTypeIdForTypeName(Uint8List bytes) { String name = utf8codec.decode(bytes); if (!_NAME_TO_TYPE_ID.containsKey(name)) { throw TProtocolError( TProtocolErrorType.NOT_IMPLEMENTED, "Unrecognized type"); } return _NAME_TO_TYPE_ID[name]; } static final Set _JSON_NUMERICS = Set.from([ '+'.codeUnitAt(0), '-'.codeUnitAt(0), '.'.codeUnitAt(0), '0'.codeUnitAt(0), '1'.codeUnitAt(0), '2'.codeUnitAt(0), '3'.codeUnitAt(0), '4'.codeUnitAt(0), '5'.codeUnitAt(0), '6'.codeUnitAt(0), '7'.codeUnitAt(0), '8'.codeUnitAt(0), '9'.codeUnitAt(0), 'E'.codeUnitAt(0), 'e'.codeUnitAt(0) ]); static bool isJsonNumeric(int byte) { return _JSON_NUMERICS.contains(byte); } } class _LookaheadReader { final TJsonProtocol protocol; _LookaheadReader(this.protocol); bool _hasData = false; final Uint8List _data = Uint8List(1); int read() { if (_hasData) { _hasData = false; } else { protocol.transport.readAll(_data, 0, 1); } return _data[0]; } int peek() { if (!_hasData) { protocol.transport.readAll(_data, 0, 1); } _hasData = true; return _data[0]; } } class _BaseContext { final TJsonProtocol protocol; _BaseContext(this.protocol); void write() {} void read() {} bool get escapeNumbers => false; @override String toString() => 'BaseContext'; } class _ListContext extends _BaseContext { _ListContext(TJsonProtocol protocol) : super(protocol); bool _first = true; @override void write() { if (_first) { _first = false; } else { protocol.transport.writeAll(_Constants.COMMA_BYTES); } } @override void read() { if (_first) { _first = false; } else { protocol._readJsonSyntaxChar(_Constants.COMMA_BYTES[0]); } } @override String toString() => 'ListContext'; } class _PairContext extends _BaseContext { _PairContext(TJsonProtocol protocol) : super(protocol); bool _first = true; bool _colon = true; Uint8List get symbolBytes => _colon ? _Constants.COLON_BYTES : _Constants.COMMA_BYTES; @override void write() { if (_first) { _first = false; _colon = true; } else { protocol.transport.writeAll(symbolBytes); _colon = !_colon; } } @override void read() { if (_first) { _first = false; _colon = true; } else { protocol._readJsonSyntaxChar(symbolBytes[0]); _colon = !_colon; } } @override bool get escapeNumbers => _colon; @override String toString() => 'PairContext'; } thrift-0.19.0/lib/dart/lib/src/protocol/t_protocol.dart0000644000000000000000000000377014303740367023053 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; abstract class TProtocol { final TTransport transport; TProtocol(this.transport); /// Write void writeMessageBegin(TMessage message); void writeMessageEnd(); void writeStructBegin(TStruct struct); void writeStructEnd(); void writeFieldBegin(TField field); void writeFieldEnd(); void writeFieldStop(); void writeMapBegin(TMap map); void writeMapEnd(); void writeListBegin(TList list); void writeListEnd(); void writeSetBegin(TSet set); void writeSetEnd(); void writeBool(bool b); void writeByte(int b); void writeI16(int i16); void writeI32(int i32); void writeI64(int i64); void writeDouble(double d); void writeString(String str); void writeBinary(Uint8List bytes); /// Read TMessage readMessageBegin(); void readMessageEnd(); TStruct readStructBegin(); void readStructEnd(); TField readFieldBegin(); void readFieldEnd(); TMap readMapBegin(); void readMapEnd(); TList readListBegin(); void readListEnd(); TSet readSetBegin(); void readSetEnd(); bool readBool(); int readByte(); int readI16(); int readI32(); int readI64(); double readDouble(); String readString(); Uint8List readBinary(); } thrift-0.19.0/lib/dart/lib/src/protocol/t_struct.dart0000644000000000000000000000160214303740367022526 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TStruct { final String name; TStruct([this.name = ""]); } thrift-0.19.0/lib/dart/lib/src/protocol/t_message.dart0000644000000000000000000000224714303740367022634 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TMessageType { static const int CALL = 1; static const int REPLY = 2; static const int EXCEPTION = 3; static const int ONEWAY = 4; } class TMessage { final String name; final int type; final int seqid; TMessage(this.name, this.type, this.seqid); @override String toString() => ""; } thrift-0.19.0/lib/dart/lib/src/t_error.dart0000644000000000000000000000177214303740367020502 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TError extends Error { final String message; final int type; TError(this.type, this.message); @override String toString() => ""; } thrift-0.19.0/lib/dart/lib/src/t_processor.dart0000644000000000000000000000177414303740367021372 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// A processor is a generic object which operates upon an input stream and /// writes to some output stream. abstract class TProcessor { bool process(TProtocol input, TProtocol output); } thrift-0.19.0/lib/dart/lib/src/transport/0000777000000000000000000000000014303740367020203 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/src/transport/t_transport_factory.dart0000644000000000000000000000210614303740367025160 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// Factory class used to create wrapped instance of a [TTransport]. This is /// used primarily in servers. /// /// Adapted from the Java version. class TTransportFactory { Future getTransport(TTransport transport) => Future.value(transport); } thrift-0.19.0/lib/dart/lib/src/transport/t_transport.dart0000644000000000000000000000501114303740367023427 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; abstract class TTransport { /// Queries whether the transport is open. /// Returns [true] if the transport is open. bool get isOpen; /// Opens the transport for reading/writing. /// Throws [TTransportError] if the transport could not be opened. Future open(); /// Closes the transport. Future close(); /// Reads up to [length] bytes into [buffer], starting at [offset]. /// Returns the number of bytes actually read. /// Throws [TTransportError] if there was an error reading data int read(Uint8List buffer, int offset, int length); /// Guarantees that all of [length] bytes are actually read off the transport. /// Returns the number of bytes actually read, which must be equal to /// [length]. /// Throws [TTransportError] if there was an error reading data int readAll(Uint8List buffer, int offset, int length) { int got = 0; int ret = 0; while (got < length) { ret = read(buffer, offset + got, length - got); if (ret <= 0) { throw TTransportError( TTransportErrorType.UNKNOWN, "Cannot read. Remote side has closed. Tried to read $length " "bytes, but only got $got bytes."); } got += ret; } return got; } /// Writes up to [len] bytes from the buffer. /// Throws [TTransportError] if there was an error writing data void write(Uint8List buffer, int offset, int length); /// Writes the [bytes] to the output. /// Throws [TTransportError] if there was an error writing data void writeAll(Uint8List buffer) { write(buffer, 0, buffer.length); } /// Flush any pending data out of a transport buffer. /// Throws [TTransportError] if there was an error writing out data. Future flush(); } thrift-0.19.0/lib/dart/lib/src/transport/t_transport_error.dart0000644000000000000000000000224014303740367024641 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TTransportErrorType { static const int UNKNOWN = 0; static const int NOT_OPEN = 1; static const int ALREADY_OPEN = 2; static const int TIMED_OUT = 3; static const int END_OF_FILE = 4; } class TTransportError extends TError { TTransportError([int type = TTransportErrorType.UNKNOWN, String message = ""]) : super(type, message); } thrift-0.19.0/lib/dart/lib/src/transport/t_socket.dart0000644000000000000000000000212014303740367022661 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; enum TSocketState { CLOSED, OPEN } abstract class TSocket { Stream get onState; Stream get onError; Stream get onMessage; bool get isOpen; bool get isClosed; Future open(); Future close(); void send(Uint8List data); } thrift-0.19.0/lib/dart/lib/src/transport/t_framed_transport.dart0000644000000000000000000001051614303740367024753 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// Framed [TTransport]. /// /// Adapted from the Java Framed transport. class TFramedTransport extends TBufferedTransport { static const int headerByteCount = 4; final TTransport _transport; final Uint8List _headerBytes = Uint8List(headerByteCount); int _receivedHeaderBytes = 0; int _bodySize = 0; Uint8List _body; int _receivedBodyBytes = 0; Completer _frameCompleter; TFramedTransport(TTransport transport) : _transport = transport { if (transport == null) { throw ArgumentError.notNull("transport"); } } @override bool get isOpen => _transport.isOpen; @override Future open() { _reset(isOpen: true); return _transport.open(); } @override Future close() { _reset(isOpen: false); return _transport.close(); } @override int read(Uint8List buffer, int offset, int length) { if (hasReadData) { int got = super.read(buffer, offset, length); if (got > 0) return got; } // IMPORTANT: by the time you've got here, // an entire frame is available for reading return super.read(buffer, offset, length); } void _readFrame() { if (_body == null) { bool gotFullHeader = _readFrameHeader(); if (!gotFullHeader) { return; } } _readFrameBody(); } bool _readFrameHeader() { var remainingHeaderBytes = headerByteCount - _receivedHeaderBytes; int got = _transport.read( _headerBytes, _receivedHeaderBytes, remainingHeaderBytes); if (got < 0) { throw TTransportError(TTransportErrorType.UNKNOWN, "Socket closed during frame header read"); } _receivedHeaderBytes += got; if (_receivedHeaderBytes == headerByteCount) { int size = _headerBytes.buffer.asByteData().getUint32(0); _receivedHeaderBytes = 0; if (size < 0) { throw TTransportError( TTransportErrorType.UNKNOWN, "Read a negative frame size: $size"); } _bodySize = size; _body = Uint8List(_bodySize); _receivedBodyBytes = 0; return true; } else { _registerForReadableBytes(); return false; } } void _readFrameBody() { var remainingBodyBytes = _bodySize - _receivedBodyBytes; int got = _transport.read(_body, _receivedBodyBytes, remainingBodyBytes); if (got < 0) { throw TTransportError( TTransportErrorType.UNKNOWN, "Socket closed during frame body read"); } _receivedBodyBytes += got; if (_receivedBodyBytes == _bodySize) { var body = _body; _bodySize = 0; _body = null; _receivedBodyBytes = 0; _setReadBuffer(body); var completer = _frameCompleter; _frameCompleter = null; completer.complete(Uint8List(0)); } else { _registerForReadableBytes(); } } @override Future flush() { if (_frameCompleter == null) { Uint8List buffer = consumeWriteBuffer(); int length = buffer.length; _headerBytes.buffer.asByteData().setUint32(0, length); _transport.write(_headerBytes, 0, headerByteCount); _transport.write(buffer, 0, length); _frameCompleter = Completer(); _registerForReadableBytes(); } return _frameCompleter.future; } void _registerForReadableBytes() { _transport.flush().then((_) { _readFrame(); }).catchError((e) { var completer = _frameCompleter; _receivedHeaderBytes = 0; _bodySize = 0; _body = null; _receivedBodyBytes = 0; _frameCompleter = null; completer.completeError(e); }); } } thrift-0.19.0/lib/dart/lib/src/transport/t_message_reader.dart0000644000000000000000000000604014303740367024344 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// [TMessageReader] extracts a [TMessage] from bytes. This is used to allow a /// transport to inspect the message seqid and map responses to requests. class TMessageReader { final TProtocolFactory protocolFactory; final int byteOffset; final _TMessageReaderTransport _transport; /// Construct a [MessageReader]. The optional [byteOffset] specifies the /// number of bytes to skip before reading the [TMessage]. TMessageReader(this.protocolFactory, {int byteOffset = 0}) : _transport = _TMessageReaderTransport(), this.byteOffset = byteOffset; TMessage readMessage(Uint8List bytes) { _transport.reset(bytes, byteOffset); TProtocol protocol = protocolFactory.getProtocol(_transport); TMessage message = protocol.readMessageBegin(); _transport.reset(null); return message; } } /// An internal class used to support [TMessageReader]. class _TMessageReaderTransport extends TTransport { _TMessageReaderTransport(); Iterator _readIterator; void reset(Uint8List bytes, [int offset = 0]) { if (bytes == null) { _readIterator = null; return; } if (offset > bytes.length) { throw ArgumentError("The offset exceeds the bytes length"); } _readIterator = bytes.iterator; for (var i = 0; i < offset; i++) { _readIterator.moveNext(); } } @override get isOpen => true; @override Future open() => throw UnsupportedError("Unsupported in MessageReader"); @override Future close() => throw UnsupportedError("Unsupported in MessageReader"); @override int read(Uint8List buffer, int offset, int length) { if (buffer == null) { throw ArgumentError.notNull("buffer"); } if (offset + length > buffer.length) { throw ArgumentError("The range exceeds the buffer length"); } if (_readIterator == null || length <= 0) { return 0; } int i = 0; while (i < length && _readIterator.moveNext()) { buffer[offset + i] = _readIterator.current; i++; } return i; } @override void write(Uint8List buffer, int offset, int length) => throw UnsupportedError("Unsupported in MessageReader"); @override Future flush() => throw UnsupportedError("Unsupported in MessageReader"); } thrift-0.19.0/lib/dart/lib/src/transport/t_http_transport.dart0000644000000000000000000000560714303740367024501 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// HTTP implementation of [TTransport]. /// /// For example: /// /// var transport = new THttpClientTransport(new BrowserClient(), /// new THttpConfig(url, {'X-My-Custom-Header': 'my value'})); /// var protocol = new TJsonProtocol(transport); /// var client = new MyThriftServiceClient(protocol); /// var result = client.myMethod(); /// /// Adapted from the JS XHR HTTP transport. class THttpClientTransport extends TBufferedTransport { final Client httpClient; final THttpConfig config; THttpClientTransport(this.httpClient, this.config) { if (httpClient == null) { throw ArgumentError.notNull("httpClient"); } } @override Future close() async { _reset(isOpen: false); httpClient.close(); } @override Future flush() { var requestBody = base64.encode(consumeWriteBuffer()); // Use a sync completer to ensure that the buffer can be read immediately // after the read buffer is set, and avoid a race condition where another // response could overwrite the read buffer. var completer = Completer.sync(); httpClient .post(config.url, headers: config.headers, body: requestBody) .then((response) { Uint8List data; try { data = Uint8List.fromList(base64.decode(response.body)); } on FormatException catch (_) { throw TProtocolError(TProtocolErrorType.INVALID_DATA, "Expected a Base 64 encoded string."); } _setReadBuffer(data); completer.complete(); }); return completer.future; } } class THttpConfig { final Uri url; Map _headers; Map get headers => _headers; THttpConfig(this.url, Map headers) { if (url == null || !url.hasAuthority) { throw ArgumentError("Invalid url"); } _initHeaders(headers); } void _initHeaders(Map initial) { var h = {}; if (initial != null) { h.addAll(initial); } h['Content-Type'] = 'application/x-thrift'; h['Accept'] = 'application/x-thrift'; _headers = Map.unmodifiable(h); } } thrift-0.19.0/lib/dart/lib/src/transport/t_socket_transport.dart0000644000000000000000000001306314303740367025005 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// Socket implementation of [TTransport]. /// /// For example: /// /// var transport = new TClientSocketTransport(new TWebSocket(url)); /// var protocol = new TBinaryProtocol(transport); /// var client = new MyThriftServiceClient(protocol); /// var result = client.myMethod(); /// /// Adapted from the JS WebSocket transport. abstract class TSocketTransport extends TBufferedTransport { final Logger logger = Logger('thrift.TSocketTransport'); final TSocket socket; /// A transport using the provided [socket]. TSocketTransport(this.socket) { if (socket == null) { throw ArgumentError.notNull('socket'); } socket.onError.listen((e) => logger.warning(e)); socket.onMessage.listen(handleIncomingMessage); } @override bool get isOpen => socket.isOpen; @override Future open() { _reset(isOpen: true); return socket.open(); } @override Future close() { _reset(isOpen: false); return socket.close(); } /// Make an incoming message available to read from the transport. void handleIncomingMessage(Uint8List messageBytes) { _setReadBuffer(messageBytes); } } /// [TClientSocketTransport] is a basic client socket transport. It sends /// outgoing messages and expects a response. /// /// NOTE: This transport expects a single threaded server, as it will process /// responses in FIFO order. class TClientSocketTransport extends TSocketTransport { final List> _completers = []; TClientSocketTransport(TSocket socket) : super(socket); @override Future flush() { Uint8List bytes = consumeWriteBuffer(); // Use a sync completer to ensure that the buffer can be read immediately // after the read buffer is set, and avoid a race condition where another // response could overwrite the read buffer. var completer = Completer.sync(); _completers.add(completer); if (bytes.lengthInBytes > 0) { socket.send(bytes); } return completer.future; } @override void handleIncomingMessage(Uint8List messageBytes) { super.handleIncomingMessage(messageBytes); if (_completers.isNotEmpty) { var completer = _completers.removeAt(0); completer.complete(); } } } /// [TAsyncClientSocketTransport] sends outgoing messages and expects an /// asynchronous response. /// /// NOTE: This transport uses a [MessageReader] to read a [TMessage] when an /// incoming message arrives to correlate a response to a request, using the /// seqid. class TAsyncClientSocketTransport extends TSocketTransport { static const defaultTimeout = Duration(seconds: 30); final Map> _completers = {}; final TMessageReader messageReader; final Duration responseTimeout; TAsyncClientSocketTransport(TSocket socket, TMessageReader messageReader, {Duration responseTimeout = defaultTimeout}) : this.messageReader = messageReader, this.responseTimeout = responseTimeout, super(socket); @override Future flush() { Uint8List bytes = consumeWriteBuffer(); TMessage message = messageReader.readMessage(bytes); int seqid = message.seqid; // Use a sync completer to ensure that the buffer can be read immediately // after the read buffer is set, and avoid a race condition where another // response could overwrite the read buffer. var completer = Completer.sync(); _completers[seqid] = completer; if (responseTimeout != null) { Future.delayed(responseTimeout, () { var completer = _completers.remove(seqid); if (completer != null) { completer.completeError( TimeoutException("Response timed out.", responseTimeout)); } }); } socket.send(bytes); return completer.future; } @override void handleIncomingMessage(Uint8List messageBytes) { super.handleIncomingMessage(messageBytes); TMessage message = messageReader.readMessage(messageBytes); var completer = _completers.remove(message.seqid); if (completer != null) { completer.complete(); } } } /// [TServerSocketTransport] listens for incoming messages. When it sends a /// response, it does not expect an acknowledgement. class TServerSocketTransport extends TSocketTransport { final StreamController _onIncomingMessageController; Stream get onIncomingMessage => _onIncomingMessageController.stream; TServerSocketTransport(TSocket socket) : _onIncomingMessageController = StreamController.broadcast(), super(socket); @override Future flush() async { Uint8List message = consumeWriteBuffer(); socket.send(message); } @override void handleIncomingMessage(Uint8List messageBytes) { super.handleIncomingMessage(messageBytes); _onIncomingMessageController.add(null); } } thrift-0.19.0/lib/dart/lib/src/transport/t_buffered_transport.dart0000644000000000000000000000516614303740367025304 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; /// Buffered implementation of [TTransport]. class TBufferedTransport extends TTransport { final List _writeBuffer = []; Iterator _readIterator; Uint8List consumeWriteBuffer() { Uint8List buffer = Uint8List.fromList(_writeBuffer); _writeBuffer.clear(); return buffer; } void _setReadBuffer(Uint8List readBuffer) { _readIterator = readBuffer != null ? readBuffer.iterator : null; } void _reset({bool isOpen = false}) { _isOpen = isOpen; _writeBuffer.clear(); _readIterator = null; } bool get hasReadData => _readIterator != null; bool _isOpen; @override bool get isOpen => _isOpen; @override Future open() async { _reset(isOpen: true); } @override Future close() async { _reset(isOpen: false); } @override int read(Uint8List buffer, int offset, int length) { if (buffer == null) { throw ArgumentError.notNull("buffer"); } if (offset + length > buffer.length) { throw ArgumentError("The range exceeds the buffer length"); } if (_readIterator == null || length <= 0) { return 0; } int i = 0; while (i < length && _readIterator.moveNext()) { buffer[offset + i] = _readIterator.current; i++; } // cleanup iterator when we've reached the end if (_readIterator.current == null) { _readIterator = null; } return i; } @override void write(Uint8List buffer, int offset, int length) { if (buffer == null) { throw ArgumentError.notNull("buffer"); } if (offset + length > buffer.length) { throw ArgumentError("The range exceeds the buffer length"); } _writeBuffer.addAll(buffer.sublist(offset, offset + length)); } @override Future flush() { _readIterator = consumeWriteBuffer().iterator; return Future.value(); } } thrift-0.19.0/lib/dart/lib/src/browser/0000777000000000000000000000000014303740367017632 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/src/browser/t_web_socket.dart0000644000000000000000000000742314303740367023160 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. library thrift.src.browser; import 'dart:async'; import 'dart:convert' show base64; import 'dart:html' show CloseEvent; import 'dart:html' show Event; import 'dart:html' show MessageEvent; import 'dart:html' show WebSocket; import 'dart:typed_data' show Uint8List; import 'package:thrift/thrift.dart'; /// A [TSocket] backed by a [WebSocket] from dart:html class TWebSocket implements TSocket { final Uri url; final StreamController _onStateController; @override Stream get onState => _onStateController.stream; final StreamController _onErrorController; @override Stream get onError => _onErrorController.stream; final StreamController _onMessageController; @override Stream get onMessage => _onMessageController.stream; final List _requests = []; TWebSocket(this.url) : _onStateController = StreamController.broadcast(), _onErrorController = StreamController.broadcast(), _onMessageController = StreamController.broadcast() { if (url == null || !url.hasAuthority || !url.hasPort) { throw ArgumentError('Invalid url'); } } WebSocket _socket; @override bool get isOpen => _socket != null && _socket.readyState == WebSocket.OPEN; @override bool get isClosed => _socket == null || _socket.readyState == WebSocket.CLOSED; @override Future open() { if (!isClosed) { throw TTransportError( TTransportErrorType.ALREADY_OPEN, 'Socket already connected'); } _socket = WebSocket(url.toString()); _socket.onError.listen(_onError); _socket.onOpen.listen(_onOpen); _socket.onClose.listen(_onClose); _socket.onMessage.listen(_onMessage); return _socket.onOpen.first; } @override Future close() { if (_socket != null) { _socket.close(); return _socket.onClose.first; } else { return Future.value(); } } @override void send(Uint8List data) { _requests.add(data); _sendRequests(); } void _sendRequests() { while (isOpen && _requests.isNotEmpty) { Uint8List data = _requests.removeAt(0); _socket.sendString(base64.encode(data)); } } void _onOpen(Event event) { _onStateController.add(TSocketState.OPEN); _sendRequests(); } void _onClose(CloseEvent event) { _socket = null; if (_requests.isNotEmpty) { _onErrorController .add(StateError('Socket was closed with pending requests')); } _requests.clear(); _onStateController.add(TSocketState.CLOSED); } void _onMessage(MessageEvent message) { try { Uint8List data = Uint8List.fromList(base64.decode(message.data)); _onMessageController.add(data); } on FormatException catch (_) { var error = TProtocolError(TProtocolErrorType.INVALID_DATA, "Expected a Base 64 encoded string."); _onErrorController.add(error); } } void _onError(Event event) { close(); _onErrorController.add(event.toString()); } } thrift-0.19.0/lib/dart/lib/src/t_application_error.dart0000644000000000000000000000575014303740367023065 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TApplicationErrorType { static const int UNKNOWN = 0; static const int UNKNOWN_METHOD = 1; static const int INVALID_MESSAGE_TYPE = 2; static const int WRONG_METHOD_NAME = 3; static const int BAD_SEQUENCE_ID = 4; static const int MISSING_RESULT = 5; static const int INTERNAL_ERROR = 6; static const int PROTOCOL_ERROR = 7; static const int INVALID_TRANSFORM = 8; static const int INVALID_PROTOCOL = 9; static const int UNSUPPORTED_CLIENT_TYPE = 10; } class TApplicationError extends TError { static final TStruct _struct = TStruct("TApplicationError"); static const int MESSAGE = 1; static final TField _messageField = TField("message", TType.STRING, MESSAGE); static const int TYPE = 2; static final TField _typeField = TField("type", TType.I32, TYPE); TApplicationError( [int type = TApplicationErrorType.UNKNOWN, String message = ""]) : super(type, message); static TApplicationError read(TProtocol iprot) { TField field; String message; int type = TApplicationErrorType.UNKNOWN; iprot.readStructBegin(); while (true) { field = iprot.readFieldBegin(); if (field.type == TType.STOP) { break; } switch (field.id) { case MESSAGE: if (field.type == TType.STRING) { message = iprot.readString(); } else { TProtocolUtil.skip(iprot, field.type); } break; case TYPE: if (field.type == TType.I32) { type = iprot.readI32(); } else { TProtocolUtil.skip(iprot, field.type); } break; default: TProtocolUtil.skip(iprot, field.type); break; } iprot.readFieldEnd(); } iprot.readStructEnd(); return TApplicationError(type, message); } write(TProtocol oprot) { oprot.writeStructBegin(_struct); if (message != null && message.isNotEmpty) { oprot.writeFieldBegin(_messageField); oprot.writeString(message); oprot.writeFieldEnd(); } oprot.writeFieldBegin(_typeField); oprot.writeI32(type); oprot.writeFieldEnd(); oprot.writeFieldStop(); oprot.writeStructEnd(); } } thrift-0.19.0/lib/dart/lib/src/serializer/0000777000000000000000000000000014303740367020320 5ustar00rootroot00000000000000thrift-0.19.0/lib/dart/lib/src/serializer/t_deserializer.dart0000644000000000000000000000274214303740367024202 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TDeserializer { final message = TMessage('Deserializer', TMessageType.ONEWAY, 1); TBufferedTransport transport; TProtocol protocol; TDeserializer({TProtocolFactory protocolFactory}) { this.transport = TBufferedTransport(); if (protocolFactory == null) { protocolFactory = TBinaryProtocolFactory(); } this.protocol = protocolFactory.getProtocol(this.transport); } void read(TBase base, Uint8List data) { transport.writeAll(data); transport.flush(); base.read(protocol); } void readString(TBase base, String data) { transport.writeAll(base64.decode(data)); transport.flush(); base.read(protocol); } } thrift-0.19.0/lib/dart/lib/src/serializer/t_serializer.dart0000644000000000000000000000272314303740367023670 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; class TSerializer { final message = TMessage('Serializer', TMessageType.ONEWAY, 1); TBufferedTransport transport; TProtocol protocol; TSerializer({TProtocolFactory protocolFactory}) { this.transport = TBufferedTransport(); if (protocolFactory == null) { protocolFactory = TBinaryProtocolFactory(); } this.protocol = protocolFactory.getProtocol(this.transport); } Uint8List write(TBase base) { base.write(protocol); return transport.consumeWriteBuffer(); } String writeString(TBase base) { base.write(protocol); Uint8List bytes = transport.consumeWriteBuffer(); return base64.encode(bytes); } } thrift-0.19.0/lib/dart/lib/src/t_base.dart0000644000000000000000000000262614303740367020262 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. part of thrift; abstract class TBase { /// Reads the TObject from the given input protocol. void read(TProtocol iprot); /// Writes the objects out to the [oprot] protocol. void write(TProtocol oprot); /// Check if a field is currently set or unset, using the [fieldId]. bool isSet(int fieldId); /// Get a field's value by [fieldId]. Primitive types will be wrapped in the /// appropriate "boxed" types. getFieldValue(int fieldId); /// Set a field's value by [fieldId]. Primitive types must be "boxed" in the /// appropriate object wrapper type. setFieldValue(int fieldId, Object value); } thrift-0.19.0/lib/dart/lib/thrift.dart0000644000000000000000000000443214303740367017533 0ustar00rootroot00000000000000/// Licensed to the Apache Software Foundation (ASF) under one /// or more contributor license agreements. See the NOTICE file /// distributed with this work for additional information /// regarding copyright ownership. The ASF licenses this file /// to you under the Apache License, Version 2.0 (the /// "License"); you may not use this file except in compliance /// with the License. You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, /// software distributed under the License is distributed on an /// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY /// KIND, either express or implied. See the License for the /// specific language governing permissions and limitations /// under the License. library thrift; import 'dart:async'; import 'dart:collection'; import 'dart:convert' show Utf8Codec, base64; import 'dart:typed_data' show ByteData, Uint8List, Endian; import 'package:fixnum/fixnum.dart'; import 'package:http/http.dart' show Client; import 'package:logging/logging.dart'; part 'src/t_application_error.dart'; part 'src/t_base.dart'; part 'src/t_error.dart'; part 'src/t_processor.dart'; part 'src/protocol/t_binary_protocol.dart'; part 'src/protocol/t_compact_protocol.dart'; part 'src/protocol/t_field.dart'; part 'src/protocol/t_json_protocol.dart'; part 'src/protocol/t_list.dart'; part 'src/protocol/t_map.dart'; part 'src/protocol/t_message.dart'; part 'src/protocol/t_multiplexed_protocol.dart'; part 'src/protocol/t_protocol.dart'; part 'src/protocol/t_protocol_decorator.dart'; part 'src/protocol/t_protocol_error.dart'; part 'src/protocol/t_protocol_factory.dart'; part 'src/protocol/t_protocol_util.dart'; part 'src/protocol/t_set.dart'; part 'src/protocol/t_struct.dart'; part 'src/protocol/t_type.dart'; part 'src/serializer/t_deserializer.dart'; part 'src/serializer/t_serializer.dart'; part 'src/transport/t_buffered_transport.dart'; part 'src/transport/t_framed_transport.dart'; part 'src/transport/t_http_transport.dart'; part 'src/transport/t_message_reader.dart'; part 'src/transport/t_socket.dart'; part 'src/transport/t_transport.dart'; part 'src/transport/t_transport_error.dart'; part 'src/transport/t_transport_factory.dart'; part 'src/transport/t_socket_transport.dart'; thrift-0.19.0/lib/dart/Makefile.in0000644000000000000000000004332114472652515016662 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/dart ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/dart/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/dart/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ dist-hook distclean distclean-generic distclean-libtool \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile all-local: $(DARTPUB) get clean-local: $(RM) -r .pub find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type d -name "packages" | xargs $(RM) -r check-local: all dist-hook: $(RM) -r $(distdir)/.pub find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r find $(distdir) -type f -name ".packages" | xargs $(RM) find $(distdir) -type d -name "packages" | xargs $(RM) -r # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/java/0000755000000000000000000000000014472652656014607 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/Makefile.am0000644000000000000000000000351514303740367016635 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # export CLASSPATH all-local: $(GRADLE) $(GRADLE_OPTS) assemble \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ --console=plain install-exec-hook: $(GRADLE) $(GRADLE_OPTS) publishToMavenLocal \ -Prelease=true \ -Pinstall.path=$(DESTDIR)$(JAVA_PREFIX) \ -Pinstall.javadoc.path=$(DESTDIR)$(docdir)/java \ -Pthrift.version=$(PACKAGE_VERSION) \ --console=plain clean-local: $(GRADLE) $(GRADLE_OPTS) clean --console=plain precross: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) shadowJar \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain check-local: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) test \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain maven-publish: $(GRADLE) $(GRADLE_OPTS) publish \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ --console=plain EXTRA_DIST = \ build.gradle \ gradle.properties \ settings.gradle \ gradle \ CMakeLists.txt \ coding_standards.md \ android \ src \ code_quality_tools \ README.md thrift-0.19.0/lib/java/CMakeLists.txt0000644000000000000000000000776314303740367017352 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # if(ANDROID) set(THRIFT_AAR outputs/aar/thrift-debug.aar outputs/aar/thrift-release.aar) add_custom_command( OUTPUT ${THRIFT_AAR} COMMAND ${GRADLE_EXECUTABLE} -p "${CMAKE_CURRENT_SOURCE_DIR}/android" "-PbuildDir=${CMAKE_CURRENT_BINARY_DIR}/android/build" assemble ) add_custom_target(thrift_aar ALL DEPENDS ${THRIFT_AAR}) else() if(NOT JAVA_INSTALL_DIR) if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") set(JAVA_INSTALL_DIR "${LIB_INSTALL_DIR}/java") else() set(JAVA_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/java") endif() endif() if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") set(JAVA_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/java") else() set(JAVA_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/java") endif() set(PRELEASE "true") if (CMAKE_BUILD_TYPE MATCHES DEBUG) set(PRELEASE "false") endif () file(GLOB_RECURSE THRIFTJAVA_SOURCES LIST_DIRECTORIES false "${CMAKE_CURRENT_SOURCE_DIR}/src/*") add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/libs/libthrift.jar" COMMENT "Building Java library using Gradle" COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_OPTS} assemble --console=plain --no-daemon -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" DEPENDS ${THRIFTJAVA_SOURCES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target(ThriftJava ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/build/libs/libthrift.jar") # Enable publishing from CMake if the publishing information is provided add_custom_target(MavenPublish COMMENT "Publishing Java Library to Apache Maven staging" DEPENDS ThriftJava COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_OPTS} clean uploadArchives --console=plain --no-daemon -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) # Hook the CMake install process to the results from make ALL. # This works best when 'make all && sudo make install/fast' is used. # Using slash to end the source location to avoid copying the directory path. install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/libs/ DESTINATION ${JAVA_INSTALL_DIR} FILES_MATCHING PATTERN "libthrift-${thrift_VERSION}.jar") install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/deps/ DESTINATION ${JAVA_INSTALL_DIR} FILES_MATCHING PATTERN "*.jar") install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/docs/javadoc/ DESTINATION ${JAVA_DOC_INSTALL_DIR}) if(BUILD_TESTING) add_test(NAME JavaTest COMMAND ${GRADLE_EXECUTABLE} ${GRADLE_OPTS} test --console=plain --no-daemon -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" "-Pthrift.compiler=${THRIFT_COMPILER}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif() endif() thrift-0.19.0/lib/java/build.gradle0000644000000000000000000000442414452237057017062 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Using the legacy plugin classpath for Clover so it can be loaded optionally buildscript { // strictly enforce the minimum version of Java required to build and fail fast if (JavaVersion.current() < JavaVersion.VERSION_1_8) { throw new GradleException("The java version used is ${JavaVersion.current()}, but must be at least ${JavaVersion.VERSION_1_8}") } repositories { mavenCentral() google() gradlePluginPortal() } dependencies { classpath 'com.bmuschko:gradle-clover-plugin:2.2.1' } } plugins { id 'java-library' id 'maven-publish' id 'signing' id 'pmd' id 'com.github.johnrengelman.shadow' version '8.1.1' id "com.github.spotbugs" version "5.0.14" id "com.diffplug.spotless" version "6.19.0" } description = 'Apache Thrift Java Library' defaultTasks 'build' // Version components for this project group = property('thrift.groupid') if (Boolean.parseBoolean(project.release)) { version = property('thrift.version') } else { version = property('thrift.version') + '-SNAPSHOT' } // Keeping the rest of the build logic in functional named scripts for clarity apply from: 'gradle/environment.gradle' apply from: 'gradle/sourceConfiguration.gradle' apply from: 'gradle/generateTestThrift.gradle' apply from: 'gradle/unitTests.gradle' apply from: 'gradle/cloverCoverage.gradle' apply from: 'gradle/functionalTests.gradle' apply from: 'gradle/publishing.gradle' apply from: 'gradle/codeQualityChecks.gradle' thrift-0.19.0/lib/java/gradle.properties0000644000000000000000000000262614454461475020166 0ustar00rootroot00000000000000# This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. thrift.version=0.19.0 thrift.groupid=org.apache.thrift release=false # Local Install paths install.path=/usr/local/lib install.javadoc.path=/usr/local/lib # Test execution properties testPort=9090 # Test with Clover Code coverage (disabled by default) cloverEnabled=false # Maven dependency download locations mvn.repo=https://repo1.maven.org/maven2 apache.repo=https://repository.apache.org/content/repositories/releases # Apache Maven publish license=https://www.apache.org/licenses/LICENSE-2.0.txt maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 maven-repository-id=apache.releases.https # Dependency versions httpclient.version=5.2.1 httpcore.version=5.2 slf4j.version=1.7.36 servlet.version=5.0.0 tomcat.embed.version=10.1.4 junit.version=5.9.1 mockito.version=5.3.0 javax.annotation.version=2.1.1 commons-lang3.version=3.12.0 org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED thrift-0.19.0/lib/java/src/0000777000000000000000000000000014303472263015365 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/0000777000000000000000000000000014303472263016311 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/0000777000000000000000000000000014303472263017232 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/0000777000000000000000000000000014303472263020021 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/0000777000000000000000000000000014303472263021242 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/0000777000000000000000000000000014452237057022547 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TFieldIdEnum.java0000644000000000000000000000230614370300523025644 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** Interface for all generated struct Fields objects. */ public interface TFieldIdEnum { /** * Gets the Thrift field id for the named field. * * @return the Thrift field id for the named field. */ short getThriftFieldId(); /** * Gets the field's name, exactly as in the IDL. * * @return the field's name, exactly as in the IDL. */ String getFieldName(); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TConfiguration.java0000644000000000000000000000570314303740367026344 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; public class TConfiguration { public static final int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; public static final int DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries public static final int DEFAULT_RECURSION_DEPTH = 64; private int maxMessageSize; private int maxFrameSize; private int recursionLimit; public TConfiguration() { this(DEFAULT_MAX_MESSAGE_SIZE, DEFAULT_MAX_FRAME_SIZE, DEFAULT_RECURSION_DEPTH); } public TConfiguration(int maxMessageSize, int maxFrameSize, int recursionLimit) { this.maxFrameSize = maxFrameSize; this.maxMessageSize = maxMessageSize; this.recursionLimit = recursionLimit; } public int getMaxMessageSize() { return maxMessageSize; } public int getMaxFrameSize() { return maxFrameSize; } public int getRecursionLimit() { return recursionLimit; } public void setMaxMessageSize(int maxMessageSize) { this.maxMessageSize = maxMessageSize; } public void setMaxFrameSize(int maxFrameSize) { this.maxFrameSize = maxFrameSize; } public void setRecursionLimit(int recursionLimit) { this.recursionLimit = recursionLimit; } public static final TConfiguration DEFAULT = new Builder().build(); public static TConfiguration.Builder custom() { return new Builder(); } public static class Builder { private int maxMessageSize; private int maxFrameSize; private int recursionLimit; Builder() { super(); this.maxFrameSize = DEFAULT_MAX_FRAME_SIZE; this.maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE; this.recursionLimit = DEFAULT_RECURSION_DEPTH; } public Builder setMaxMessageSize(int maxMessageSize) { this.maxMessageSize = maxMessageSize; return this; } public Builder setMaxFrameSize(int maxFrameSize) { this.maxFrameSize = maxFrameSize; return this; } public Builder setRecursionLimit(int recursionLimit) { this.recursionLimit = recursionLimit; return this; } public TConfiguration build() { return new TConfiguration(maxMessageSize, maxFrameSize, recursionLimit); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TBaseHelper.java0000644000000000000000000002053614303740367025550 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.Serializable; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; public final class TBaseHelper { private TBaseHelper() {} private static final Comparator comparator = new NestedStructureComparator(); public static int compareTo(Object o1, Object o2) { if (o1 instanceof Comparable) { return compareTo((Comparable) o1, (Comparable) o2); } else if (o1 instanceof List) { return compareTo((List) o1, (List) o2); } else if (o1 instanceof Set) { return compareTo((Set) o1, (Set) o2); } else if (o1 instanceof Map) { return compareTo((Map) o1, (Map) o2); } else if (o1 instanceof byte[]) { return compareTo((byte[]) o1, (byte[]) o2); } else { throw new IllegalArgumentException("Cannot compare objects of type " + o1.getClass()); } } public static int compareTo(boolean a, boolean b) { return Boolean.compare(a, b); } public static int compareTo(byte a, byte b) { return Byte.compare(a, b); } public static int compareTo(short a, short b) { return Short.compare(a, b); } public static int compareTo(int a, int b) { return Integer.compare(a, b); } public static int compareTo(long a, long b) { return Long.compare(a, b); } public static int compareTo(double a, double b) { return Double.compare(a, b); } public static int compareTo(String a, String b) { return a.compareTo(b); } public static int compareTo(byte[] a, byte[] b) { int compare = compareTo(a.length, b.length); if (compare == 0) { for (int i = 0; i < a.length; i++) { compare = compareTo(a[i], b[i]); if (compare != 0) { break; } } } return compare; } public static int compareTo(Comparable a, Comparable b) { return a.compareTo(b); } public static int compareTo(List a, List b) { int compare = compareTo(a.size(), b.size()); if (compare == 0) { for (int i = 0; i < a.size(); i++) { compare = comparator.compare(a.get(i), b.get(i)); if (compare != 0) { break; } } } return compare; } public static int compareTo(Set a, Set b) { int compare = compareTo(a.size(), b.size()); if (compare == 0) { ArrayList sortedA = new ArrayList(a); ArrayList sortedB = new ArrayList(b); Collections.sort(sortedA, comparator); Collections.sort(sortedB, comparator); Iterator iterA = sortedA.iterator(); Iterator iterB = sortedB.iterator(); // Compare each item. while (iterA.hasNext() && iterB.hasNext()) { compare = comparator.compare(iterA.next(), iterB.next()); if (compare != 0) { break; } } } return compare; } public static int compareTo(Map a, Map b) { int lastComparison = compareTo(a.size(), b.size()); if (lastComparison != 0) { return lastComparison; } // Sort a and b so we can compare them. SortedMap sortedA = new TreeMap(comparator); sortedA.putAll(a); Iterator iterA = sortedA.entrySet().iterator(); SortedMap sortedB = new TreeMap(comparator); sortedB.putAll(b); Iterator iterB = sortedB.entrySet().iterator(); // Compare each item. while (iterA.hasNext() && iterB.hasNext()) { Map.Entry entryA = iterA.next(); Map.Entry entryB = iterB.next(); lastComparison = comparator.compare(entryA.getKey(), entryB.getKey()); if (lastComparison != 0) { return lastComparison; } lastComparison = comparator.compare(entryA.getValue(), entryB.getValue()); if (lastComparison != 0) { return lastComparison; } } return 0; } /** Comparator to compare items inside a structure (e.g. a list, set, or map). */ private static class NestedStructureComparator implements Comparator, Serializable { public int compare(Object oA, Object oB) { if (oA == null && oB == null) { return 0; } else if (oA == null) { return -1; } else if (oB == null) { return 1; } else if (oA instanceof List) { return compareTo((List) oA, (List) oB); } else if (oA instanceof Set) { return compareTo((Set) oA, (Set) oB); } else if (oA instanceof Map) { return compareTo((Map) oA, (Map) oB); } else if (oA instanceof byte[]) { return compareTo((byte[]) oA, (byte[]) oB); } else { return compareTo((Comparable) oA, (Comparable) oB); } } } public static void toString(Collection bbs, StringBuilder sb) { Iterator it = bbs.iterator(); if (!it.hasNext()) { sb.append("[]"); } else { sb.append("["); while (true) { ByteBuffer bb = it.next(); org.apache.thrift.TBaseHelper.toString(bb, sb); if (!it.hasNext()) { sb.append("]"); return; } else { sb.append(", "); } } } } public static void toString(ByteBuffer bb, StringBuilder sb) { byte[] buf = bb.array(); int arrayOffset = bb.arrayOffset(); int offset = arrayOffset + bb.position(); int origLimit = arrayOffset + bb.limit(); int limit = (origLimit - offset > 128) ? offset + 128 : origLimit; for (int i = offset; i < limit; i++) { if (i > offset) { sb.append(" "); } sb.append(paddedByteString(buf[i])); } if (origLimit != limit) { sb.append("..."); } } public static String paddedByteString(byte b) { int extended = (b | 0x100) & 0x1ff; return Integer.toHexString(extended).toUpperCase().substring(1); } public static byte[] byteBufferToByteArray(ByteBuffer byteBuffer) { if (wrapsFullArray(byteBuffer)) { return byteBuffer.array(); } byte[] target = new byte[byteBuffer.remaining()]; byteBufferToByteArray(byteBuffer, target, 0); return target; } public static boolean wrapsFullArray(ByteBuffer byteBuffer) { return byteBuffer.hasArray() && byteBuffer.position() == 0 && byteBuffer.arrayOffset() == 0 && byteBuffer.remaining() == byteBuffer.capacity(); } public static int byteBufferToByteArray(ByteBuffer byteBuffer, byte[] target, int offset) { int remaining = byteBuffer.remaining(); System.arraycopy( byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), target, offset, remaining); return remaining; } public static ByteBuffer rightSize(ByteBuffer in) { if (in == null) { return null; } if (wrapsFullArray(in)) { return in; } return ByteBuffer.wrap(byteBufferToByteArray(in)); } public static ByteBuffer copyBinary(final ByteBuffer orig) { if (orig == null) { return null; } ByteBuffer copy = ByteBuffer.wrap(new byte[orig.remaining()]); if (orig.hasArray()) { System.arraycopy( orig.array(), orig.arrayOffset() + orig.position(), copy.array(), 0, orig.remaining()); } else { orig.slice().get(copy.array()); } return copy; } public static byte[] copyBinary(final byte[] orig) { return (orig == null) ? null : Arrays.copyOf(orig, orig.length); } public static int hashCode(long value) { return Long.hashCode(value); } public static int hashCode(double value) { return Double.hashCode(value); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TMultiplexedProcessor.java0000644000000000000000000001412414303740367027726 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.util.HashMap; import java.util.Map; import org.apache.thrift.protocol.*; /** * TMultiplexedProcessor is a TProcessor allowing a single TServer * to provide multiple services. * *

To do so, you instantiate the processor and then register additional processors with it, as * shown in the following example: * *

* * * TMultiplexedProcessor processor = new TMultiplexedProcessor(); * * processor.registerProcessor( * "Calculator", * new Calculator.Processor(new CalculatorHandler())); * * processor.registerProcessor( * "WeatherReport", * new WeatherReport.Processor(new WeatherReportHandler())); * * TServerTransport t = new TServerSocket(9090); * TSimpleServer server = new TSimpleServer(processor, t); * * server.serve(); * * *
*/ public class TMultiplexedProcessor implements TProcessor { private final Map SERVICE_PROCESSOR_MAP = new HashMap(); private TProcessor defaultProcessor; /** * 'Register' a service with this TMultiplexedProcessor. This allows us to broker * requests to individual services by using the service name to select them at request time. * * @param serviceName Name of a service, has to be identical to the name declared in the Thrift * IDL, e.g. "WeatherReport". * @param processor Implementation of a service, usually referred to as "handlers", e.g. * WeatherReportHandler implementing WeatherReport.Iface. */ public void registerProcessor(String serviceName, TProcessor processor) { SERVICE_PROCESSOR_MAP.put(serviceName, processor); } /** * Register a service to be called to process queries without service name * * @param processor the service to be called. */ public void registerDefault(TProcessor processor) { defaultProcessor = processor; } /** * This implementation of process performs the following steps: * *
    *
  1. Read the beginning of the message. *
  2. Extract the service name from the message. *
  3. Using the service name to locate the appropriate processor. *
  4. Dispatch to the processor, with a decorated instance of TProtocol that allows * readMessageBegin() to return the original TMessage. *
* * @throws TProtocolException If the message type is not CALL or ONEWAY, if the service name was * not found in the message, or if the service name was not found in the service map. You * called {@link #registerProcessor(String, TProcessor) registerProcessor} during * initialization, right? :) */ @Override public void process(TProtocol iprot, TProtocol oprot) throws TException { /* Use the actual underlying protocol (e.g. TBinaryProtocol) to read the message header. This pulls the message "off the wire", which we'll deal with at the end of this method. */ TMessage message = iprot.readMessageBegin(); if (message.type != TMessageType.CALL && message.type != TMessageType.ONEWAY) { throw new TProtocolException( TProtocolException.NOT_IMPLEMENTED, "This should not have happened!?"); } // Extract the service name int index = message.name.indexOf(TMultiplexedProtocol.SEPARATOR); if (index < 0) { if (defaultProcessor != null) { // Dispatch processing to the stored processor defaultProcessor.process(new StoredMessageProtocol(iprot, message), oprot); return; } throw new TProtocolException( TProtocolException.NOT_IMPLEMENTED, "Service name not found in message name: " + message.name + ". Did you " + "forget to use a TMultiplexProtocol in your client?"); } // Create a new TMessage, something that can be consumed by any TProtocol String serviceName = message.name.substring(0, index); TProcessor actualProcessor = SERVICE_PROCESSOR_MAP.get(serviceName); if (actualProcessor == null) { throw new TProtocolException( TProtocolException.NOT_IMPLEMENTED, "Service name not found: " + serviceName + ". Did you forget " + "to call registerProcessor()?"); } // Create a new TMessage, removing the service name TMessage standardMessage = new TMessage( message.name.substring(serviceName.length() + TMultiplexedProtocol.SEPARATOR.length()), message.type, message.seqid); // Dispatch processing to the stored processor actualProcessor.process(new StoredMessageProtocol(iprot, standardMessage), oprot); } /** * Our goal was to work with any protocol. In order to do that, we needed to allow them to call * readMessageBegin() and get a TMessage in exactly the standard format, without the service name * prepended to TMessage.name. */ private static class StoredMessageProtocol extends TProtocolDecorator { TMessage messageBegin; public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) { super(protocol); this.messageBegin = messageBegin; } @Override public TMessage readMessageBegin() throws TException { return messageBegin; } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TEnum.java0000644000000000000000000000155614370300523024431 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; public interface TEnum { int getValue(); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/AsyncProcessFunction.java0000644000000000000000000000377114303740367027536 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.async.AsyncMethodCallback; import org.apache.thrift.protocol.TMessage; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.server.AbstractNonblockingServer; public abstract class AsyncProcessFunction { final String methodName; public AsyncProcessFunction(String methodName) { this.methodName = methodName; } protected abstract boolean isOneway(); public abstract void start(I iface, T args, AsyncMethodCallback resultHandler) throws TException; public abstract T getEmptyArgsInstance(); public abstract AsyncMethodCallback getResultHandler( final AbstractNonblockingServer.AsyncFrameBuffer fb, int seqid); public String getMethodName() { return methodName; } public void sendResponse( final AbstractNonblockingServer.AsyncFrameBuffer fb, final TSerializable result, final byte type, final int seqid) throws TException { TProtocol oprot = fb.getOutputProtocol(); oprot.writeMessageBegin(new TMessage(getMethodName(), type, seqid)); result.write(oprot); oprot.writeMessageEnd(); oprot.getTransport().flush(); fb.responseReady(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/0000777000000000000000000000000014370300523023650 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/TAsyncClientFactory.java0000644000000000000000000000176714370300523030412 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.async; import org.apache.thrift.transport.TNonblockingTransport; public interface TAsyncClientFactory { T getAsyncClient(TNonblockingTransport transport); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/TAsyncClient.java0000644000000000000000000000621214370300523027050 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.async; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TNonblockingTransport; public abstract class TAsyncClient { protected final TProtocolFactory ___protocolFactory; protected final TNonblockingTransport ___transport; protected final TAsyncClientManager ___manager; protected TAsyncMethodCall ___currentMethod; private Exception ___error; private long ___timeout; public TAsyncClient( TProtocolFactory protocolFactory, TAsyncClientManager manager, TNonblockingTransport transport) { this(protocolFactory, manager, transport, 0); } public TAsyncClient( TProtocolFactory protocolFactory, TAsyncClientManager manager, TNonblockingTransport transport, long timeout) { this.___protocolFactory = protocolFactory; this.___manager = manager; this.___transport = transport; this.___timeout = timeout; } public TProtocolFactory getProtocolFactory() { return ___protocolFactory; } public long getTimeout() { return ___timeout; } public boolean hasTimeout() { return ___timeout > 0; } public void setTimeout(long timeout) { this.___timeout = timeout; } /** * Is the client in an error state? * * @return If client in an error state? */ public boolean hasError() { return ___error != null; } /** * Get the client's error - returns null if no error * * @return Get the client's error. *

returns null if no error */ public Exception getError() { return ___error; } protected void checkReady() { // Ensure we are not currently executing a method if (___currentMethod != null) { throw new IllegalStateException( "Client is currently executing another method: " + ___currentMethod.getClass().getName()); } // Ensure we're not in an error state if (___error != null) { throw new IllegalStateException("Client has an error!", ___error); } } /** Called by delegate method when finished */ protected void onComplete() { ___currentMethod = null; } /** * Called by delegate method on error. * * @param exception the exception indicating the current error condition. */ protected void onError(Exception exception) { ___transport.close(); ___currentMethod = null; ___error = exception; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/TAsyncMethodCall.java0000644000000000000000000002124514370300523027651 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.async; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.concurrent.atomic.AtomicLong; import org.apache.thrift.TException; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TMemoryBuffer; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.layered.TFramedTransport; /** * Encapsulates an async method call. * *

Need to generate: * *

    *
  • protected abstract void write_args(TProtocol protocol) *
  • protected abstract T getResult() throws <Exception_1>, <Exception_2>, ... *
* * @param The return type of the encapsulated method call. */ public abstract class TAsyncMethodCall { private static final int INITIAL_MEMORY_BUFFER_SIZE = 128; private static final AtomicLong sequenceIdCounter = new AtomicLong(0); public enum State { CONNECTING, WRITING_REQUEST_SIZE, WRITING_REQUEST_BODY, READING_RESPONSE_SIZE, READING_RESPONSE_BODY, RESPONSE_READ, ERROR; } /** Next step in the call, initialized by start() */ private State state = null; protected final TNonblockingTransport transport; private final TProtocolFactory protocolFactory; protected final TAsyncClient client; private final AsyncMethodCallback callback; private final boolean isOneway; private final long sequenceId; private final long timeout; private ByteBuffer sizeBuffer; private final byte[] sizeBufferArray = new byte[4]; private ByteBuffer frameBuffer; private final long startTime = System.currentTimeMillis(); protected TAsyncMethodCall( TAsyncClient client, TProtocolFactory protocolFactory, TNonblockingTransport transport, AsyncMethodCallback callback, boolean isOneway) { this.transport = transport; this.callback = callback; this.protocolFactory = protocolFactory; this.client = client; this.isOneway = isOneway; this.sequenceId = TAsyncMethodCall.sequenceIdCounter.getAndIncrement(); this.timeout = client.getTimeout(); } protected State getState() { return state; } protected boolean isFinished() { return state == State.RESPONSE_READ; } protected long getStartTime() { return startTime; } protected long getSequenceId() { return sequenceId; } public TAsyncClient getClient() { return client; } public boolean hasTimeout() { return timeout > 0; } public long getTimeoutTimestamp() { return timeout + startTime; } protected abstract void write_args(TProtocol protocol) throws TException; protected abstract T getResult() throws Exception; /** * Initialize buffers. * * @throws TException if buffer initialization fails */ protected void prepareMethodCall() throws TException { TMemoryBuffer memoryBuffer = new TMemoryBuffer(INITIAL_MEMORY_BUFFER_SIZE); TProtocol protocol = protocolFactory.getProtocol(memoryBuffer); write_args(protocol); int length = memoryBuffer.length(); frameBuffer = ByteBuffer.wrap(memoryBuffer.getArray(), 0, length); TFramedTransport.encodeFrameSize(length, sizeBufferArray); sizeBuffer = ByteBuffer.wrap(sizeBufferArray); } /** * Register with selector and start first state, which could be either connecting or writing. * * @throws IOException if register or starting fails */ void start(Selector sel) throws IOException { SelectionKey key; if (transport.isOpen()) { state = State.WRITING_REQUEST_SIZE; key = transport.registerSelector(sel, SelectionKey.OP_WRITE); } else { state = State.CONNECTING; key = transport.registerSelector(sel, SelectionKey.OP_CONNECT); // non-blocking connect can complete immediately, // in which case we should not expect the OP_CONNECT if (transport.startConnect()) { registerForFirstWrite(key); } } key.attach(this); } void registerForFirstWrite(SelectionKey key) throws IOException { state = State.WRITING_REQUEST_SIZE; key.interestOps(SelectionKey.OP_WRITE); } protected ByteBuffer getFrameBuffer() { return frameBuffer; } /** * Transition to next state, doing whatever work is required. Since this method is only called by * the selector thread, we can make changes to our select interests without worrying about * concurrency. * * @param key selection key */ void transition(SelectionKey key) { // Ensure key is valid if (!key.isValid()) { key.cancel(); Exception e = new TTransportException("Selection key not valid!"); onError(e); return; } // Transition function try { switch (state) { case CONNECTING: doConnecting(key); break; case WRITING_REQUEST_SIZE: doWritingRequestSize(); break; case WRITING_REQUEST_BODY: doWritingRequestBody(key); break; case READING_RESPONSE_SIZE: doReadingResponseSize(); break; case READING_RESPONSE_BODY: doReadingResponseBody(key); break; default: // RESPONSE_READ, ERROR, or bug throw new IllegalStateException( "Method call in state " + state + " but selector called transition method. Seems like a bug..."); } } catch (Exception e) { key.cancel(); key.attach(null); onError(e); } } protected void onError(Exception e) { client.onError(e); callback.onError(e); state = State.ERROR; } private void doReadingResponseBody(SelectionKey key) throws TTransportException { if (transport.read(frameBuffer) < 0) { throw new TTransportException(TTransportException.END_OF_FILE, "Read call frame failed"); } if (frameBuffer.remaining() == 0) { cleanUpAndFireCallback(key); } } private void cleanUpAndFireCallback(SelectionKey key) { state = State.RESPONSE_READ; key.interestOps(0); // this ensures that the TAsyncMethod instance doesn't hang around key.attach(null); try { T result = this.getResult(); client.onComplete(); callback.onComplete(result); } catch (Exception e) { key.cancel(); onError(e); } } private void doReadingResponseSize() throws TTransportException { if (transport.read(sizeBuffer) < 0) { throw new TTransportException(TTransportException.END_OF_FILE, "Read call frame size failed"); } if (sizeBuffer.remaining() == 0) { state = State.READING_RESPONSE_BODY; frameBuffer = ByteBuffer.allocate(TFramedTransport.decodeFrameSize(sizeBufferArray)); } } private void doWritingRequestBody(SelectionKey key) throws TTransportException { if (transport.write(frameBuffer) < 0) { throw new TTransportException(TTransportException.END_OF_FILE, "Write call frame failed"); } if (frameBuffer.remaining() == 0) { if (isOneway) { cleanUpAndFireCallback(key); } else { state = State.READING_RESPONSE_SIZE; sizeBuffer.rewind(); // Prepare to read incoming frame size key.interestOps(SelectionKey.OP_READ); } } } private void doWritingRequestSize() throws TTransportException { if (transport.write(sizeBuffer) < 0) { throw new TTransportException( TTransportException.END_OF_FILE, "Write call frame size failed"); } if (sizeBuffer.remaining() == 0) { state = State.WRITING_REQUEST_BODY; } } private void doConnecting(SelectionKey key) throws IOException { if (!key.isConnectable() || !transport.finishConnect()) { throw new IOException( "not connectable or finishConnect returned false after we got an OP_CONNECT"); } registerForFirstWrite(key); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/TAsyncClientManager.java0000644000000000000000000001625414370300523030352 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.async; import java.io.IOException; import java.io.Serializable; import java.nio.channels.ClosedSelectorException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.SelectorProvider; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeoutException; import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Contains selector thread which transitions method call objects */ public class TAsyncClientManager { private static final Logger LOGGER = LoggerFactory.getLogger(TAsyncClientManager.class.getName()); private final SelectThread selectThread; private final ConcurrentLinkedQueue> pendingCalls = new ConcurrentLinkedQueue<>(); public TAsyncClientManager() throws IOException { this.selectThread = new SelectThread(); selectThread.start(); } public void call(TAsyncMethodCall method) throws TException { if (!isRunning()) { throw new TException("SelectThread is not running"); } method.prepareMethodCall(); pendingCalls.add(method); selectThread.getSelector().wakeup(); } public void stop() { selectThread.finish(); } public boolean isRunning() { return selectThread.isAlive(); } private class SelectThread extends Thread { private final Selector selector; private volatile boolean running; private final TreeSet> timeoutWatchSet = new TreeSet<>(new TAsyncMethodCallTimeoutComparator()); public SelectThread() throws IOException { this.selector = SelectorProvider.provider().openSelector(); this.running = true; this.setName("TAsyncClientManager#SelectorThread " + this.getId()); // We don't want to hold up the JVM when shutting down setDaemon(true); } public Selector getSelector() { return selector; } public void finish() { running = false; selector.wakeup(); } public void run() { while (running) { try { try { if (timeoutWatchSet.size() == 0) { // No timeouts, so select indefinitely selector.select(); } else { // We have a timeout pending, so calculate the time until then and select // appropriately long nextTimeout = timeoutWatchSet.first().getTimeoutTimestamp(); long selectTime = nextTimeout - System.currentTimeMillis(); if (selectTime > 0) { // Next timeout is in the future, select and wake up then selector.select(selectTime); } else { // Next timeout is now or in the past, select immediately, so we can time out selector.selectNow(); } } } catch (IOException e) { LOGGER.error("Caught IOException in TAsyncClientManager!", e); } transitionMethods(); timeoutMethods(); startPendingMethods(); } catch (Exception exception) { LOGGER.error("Ignoring uncaught exception in SelectThread", exception); } } try { selector.close(); } catch (IOException ex) { LOGGER.warn("Could not close selector. This may result in leaked resources!", ex); } } // Transition methods for ready keys private void transitionMethods() { try { Iterator keys = selector.selectedKeys().iterator(); while (keys.hasNext()) { SelectionKey key = keys.next(); keys.remove(); if (!key.isValid()) { // this can happen if the method call experienced an error and the // key was cancelled. can also happen if we time out a method, which // results in a channel close. // just skip continue; } TAsyncMethodCall methodCall = (TAsyncMethodCall) key.attachment(); methodCall.transition(key); // If done or error occurred, remove from timeout watch set if (methodCall.isFinished() || methodCall.getClient().hasError()) { timeoutWatchSet.remove(methodCall); } } } catch (ClosedSelectorException e) { LOGGER.error("Caught ClosedSelectorException in TAsyncClientManager!", e); } } // Timeout any existing method calls private void timeoutMethods() { Iterator> iterator = timeoutWatchSet.iterator(); long currentTime = System.currentTimeMillis(); while (iterator.hasNext()) { TAsyncMethodCall methodCall = iterator.next(); if (currentTime >= methodCall.getTimeoutTimestamp()) { iterator.remove(); methodCall.onError( new TimeoutException( "Operation " + methodCall.getClass() + " timed out after " + (currentTime - methodCall.getStartTime()) + " ms.")); } else { break; } } } // Start any new calls private void startPendingMethods() { TAsyncMethodCall methodCall; while ((methodCall = pendingCalls.poll()) != null) { // Catch registration errors. method will catch transition errors and cleanup. try { methodCall.start(selector); // If timeout specified and first transition went smoothly, add to timeout watch set TAsyncClient client = methodCall.getClient(); if (client.hasTimeout() && !client.hasError()) { timeoutWatchSet.add(methodCall); } } catch (Exception exception) { LOGGER.warn("Caught exception in TAsyncClientManager!", exception); methodCall.onError(exception); } } } } /** Comparator used in TreeSet */ private static class TAsyncMethodCallTimeoutComparator implements Comparator>, Serializable { @Override public int compare(TAsyncMethodCall left, TAsyncMethodCall right) { if (left.getTimeoutTimestamp() == right.getTimeoutTimestamp()) { return (int) (left.getSequenceId() - right.getSequenceId()); } else { return (int) (left.getTimeoutTimestamp() - right.getTimeoutTimestamp()); } } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/AsyncMethodFutureAdapter.java0000644000000000000000000000163114303740367031434 0ustar00rootroot00000000000000package org.apache.thrift.async; import java.util.concurrent.CompletableFuture; /** * A simple adapter that bridges {@link AsyncMethodCallback} with {@link * CompletableFuture}-returning style clients. Compiler generated code will invoke this adapter to * implement {@code FutureClient}s. * * @param return type (can be {@link Void}). */ public final class AsyncMethodFutureAdapter implements AsyncMethodCallback { private AsyncMethodFutureAdapter() {} public static AsyncMethodFutureAdapter create() { return new AsyncMethodFutureAdapter<>(); } private final CompletableFuture future = new CompletableFuture<>(); public CompletableFuture getFuture() { return future; } @Override public void onComplete(T response) { future.complete(response); } @Override public void onError(Exception exception) { future.completeExceptionally(exception); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/async/AsyncMethodCallback.java0000644000000000000000000000372314303740367030361 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.async; /** * A handler interface asynchronous clients can implement to receive future notice of the results of * an asynchronous method call. * * @param The return type of the asynchronously invoked method. */ public interface AsyncMethodCallback { /** * This method will be called when the remote side has completed invoking your method call and the * result is fully read. For {@code oneway} method calls, this method will be called as soon as we * have completed writing out the request. * * @param response The return value of the asynchronously invoked method; {@code null} for void * methods which includes {@code oneway} methods. */ void onComplete(T response); /** * This method will be called when there is either an unexpected client-side exception like an * IOException or else when the remote method raises an exception, either declared in the IDL or * due to an unexpected server-side error. * * @param exception The exception encountered processing the the asynchronous method call, may be * a local exception or an unmarshalled remote exception. */ void onError(Exception exception); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/ProcessFunction.java0000644000000000000000000000577014303740367026541 0ustar00rootroot00000000000000package org.apache.thrift; import org.apache.thrift.protocol.TMessage; import org.apache.thrift.protocol.TMessageType; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolException; import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class ProcessFunction { private final String methodName; private static final Logger LOGGER = LoggerFactory.getLogger(ProcessFunction.class.getName()); public ProcessFunction(String methodName) { this.methodName = methodName; } public final void process(int seqid, TProtocol iprot, TProtocol oprot, I iface) throws TException { T args = getEmptyArgsInstance(); try { args.read(iprot); } catch (TProtocolException e) { iprot.readMessageEnd(); TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage()); oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid)); x.write(oprot); oprot.writeMessageEnd(); oprot.getTransport().flush(); return; } iprot.readMessageEnd(); TSerializable result = null; byte msgType = TMessageType.REPLY; try { result = getResult(iface, args); } catch (TTransportException ex) { LOGGER.error("Transport error while processing " + getMethodName(), ex); throw ex; } catch (TApplicationException ex) { LOGGER.error("Internal application error processing " + getMethodName(), ex); result = ex; msgType = TMessageType.EXCEPTION; } catch (Exception ex) { LOGGER.error("Internal error processing " + getMethodName(), ex); if (rethrowUnhandledExceptions()) throw new RuntimeException(ex.getMessage(), ex); if (!isOneway()) { result = new TApplicationException( TApplicationException.INTERNAL_ERROR, "Internal error processing " + getMethodName()); msgType = TMessageType.EXCEPTION; } } if (!isOneway()) { oprot.writeMessageBegin(new TMessage(getMethodName(), msgType, seqid)); result.write(oprot); oprot.writeMessageEnd(); oprot.getTransport().flush(); } } private void handleException(int seqid, TProtocol oprot) throws TException { if (!isOneway()) { TApplicationException x = new TApplicationException( TApplicationException.INTERNAL_ERROR, "Internal error processing " + getMethodName()); oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid)); x.write(oprot); oprot.writeMessageEnd(); oprot.getTransport().flush(); } } protected boolean rethrowUnhandledExceptions() { return false; } protected abstract boolean isOneway(); public abstract TBase getResult(I iface, T args) throws TException; public abstract T getEmptyArgsInstance(); public String getMethodName() { return methodName; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TByteArrayOutputStream.java0000644000000000000000000000302414303740367030026 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.ByteArrayOutputStream; import java.nio.charset.Charset; /** Class that allows access to the underlying buf without doing deep copies on it. */ public class TByteArrayOutputStream extends ByteArrayOutputStream { private final int initialSize; public TByteArrayOutputStream(int size) { super(size); this.initialSize = size; } public TByteArrayOutputStream() { this(32); } public byte[] get() { return buf; } public void reset() { super.reset(); if (buf.length > initialSize) { buf = new byte[initialSize]; } } public int len() { return count; } public String toString(Charset charset) { return new String(buf, 0, count, charset); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/0000777000000000000000000000000014472647462024417 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TProtocolException.java0000644000000000000000000000404214303740367031051 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TException; /** Protocol exceptions. */ public class TProtocolException extends TException { private static final long serialVersionUID = 1L; public static final int UNKNOWN = 0; public static final int INVALID_DATA = 1; public static final int NEGATIVE_SIZE = 2; public static final int SIZE_LIMIT = 3; public static final int BAD_VERSION = 4; public static final int NOT_IMPLEMENTED = 5; public static final int DEPTH_LIMIT = 6; protected int type_ = UNKNOWN; public TProtocolException() { super(); } public TProtocolException(int type) { super(); type_ = type; } public TProtocolException(int type, String message) { super(message); type_ = type; } public TProtocolException(String message) { super(message); } public TProtocolException(int type, Throwable cause) { super(cause); type_ = type; } public TProtocolException(Throwable cause) { super(cause); } public TProtocolException(String message, Throwable cause) { super(message, cause); } public TProtocolException(int type, String message, Throwable cause) { super(message, cause); type_ = type; } public int getType() { return type_; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TProtocolUtil.java0000644000000000000000000001556314370300523030030 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TException; /** Utility class with static methods for interacting with protocol data streams. */ public class TProtocolUtil { // no instantiation private TProtocolUtil() {} /** The maximum recursive depth the skip() function will traverse before throwing a TException. */ private static int maxSkipDepth = Integer.MAX_VALUE; /** * Specifies the maximum recursive depth that the skip function will traverse before throwing a * TException. This is a global setting, so any call to skip in this JVM will enforce this value. * * @param depth the maximum recursive depth. A value of 2 would allow the skip function to skip a * structure or collection with basic children, but it would not permit skipping a struct that * had a field containing a child struct. A value of 1 would only allow skipping of simple * types and empty structs/collections. */ public static void setMaxSkipDepth(int depth) { maxSkipDepth = depth; } /** * Skips over the next data element from the provided input TProtocol object. * * @param prot the protocol object to read from * @param type the next value will be interpreted as this TType value. */ public static void skip(TProtocol prot, byte type) throws TException { skip(prot, type, maxSkipDepth); } /** * Skips over the next data element from the provided input TProtocol object. * * @param prot the protocol object to read from * @param type the next value will be interpreted as this TType value. * @param maxDepth this function will only skip complex objects to this recursive depth, to * prevent Java stack overflow. */ public static void skip(TProtocol prot, byte type, int maxDepth) throws TException { if (maxDepth <= 0) { throw new TException("Maximum skip depth exceeded"); } switch (type) { case TType.BOOL: prot.readBool(); break; case TType.BYTE: prot.readByte(); break; case TType.I16: prot.readI16(); break; case TType.I32: prot.readI32(); break; case TType.I64: prot.readI64(); break; case TType.UUID: prot.readUuid(); break; case TType.DOUBLE: prot.readDouble(); break; case TType.STRING: prot.readBinary(); break; case TType.STRUCT: prot.readStructBegin(); while (true) { TField field = prot.readFieldBegin(); if (field.type == TType.STOP) { break; } skip(prot, field.type, maxDepth - 1); prot.readFieldEnd(); } prot.readStructEnd(); break; case TType.MAP: TMap map = prot.readMapBegin(); for (int i = 0; i < map.size; i++) { skip(prot, map.keyType, maxDepth - 1); skip(prot, map.valueType, maxDepth - 1); } prot.readMapEnd(); break; case TType.SET: TSet set = prot.readSetBegin(); for (int i = 0; i < set.size; i++) { skip(prot, set.elemType, maxDepth - 1); } prot.readSetEnd(); break; case TType.LIST: TList list = prot.readListBegin(); for (int i = 0; i < list.size; i++) { skip(prot, list.elemType, maxDepth - 1); } prot.readListEnd(); break; default: throw new TProtocolException(TProtocolException.INVALID_DATA, "Unrecognized type " + type); } } /** * Attempt to determine the protocol used to serialize some data. * *

The guess is based on known specificities of supported protocols. In some cases, no guess * can be done, in that case we return the fallback TProtocolFactory. To be certain to correctly * detect the protocol, the first encoded field should have a field id < 256 * * @param data The serialized data to guess the protocol for. * @param fallback The TProtocol to return if no guess can be made. * @return a Class implementing TProtocolFactory which can be used to create a deserializer. */ public static TProtocolFactory guessProtocolFactory(byte[] data, TProtocolFactory fallback) { // // If the first and last bytes are opening/closing curly braces we guess the protocol as // being TJSONProtocol. // It could not be a TCompactBinary encoding for a field of type 0xb (Map) // with delta id 7 as the last byte for TCompactBinary is always 0. // if ('{' == data[0] && '}' == data[data.length - 1]) { return new TJSONProtocol.Factory(); } // // If the last byte is not 0, then it cannot be TCompactProtocol, it must be // TBinaryProtocol. // if (data[data.length - 1] != 0) { return new TBinaryProtocol.Factory(); } // // A first byte of value > 16 indicates TCompactProtocol was used, and the first byte // encodes a delta field id (id <= 15) and a field type. // if (data[0] > 0x10) { return new TCompactProtocol.Factory(); } // // If the second byte is 0 then it is a field id < 256 encoded by TBinaryProtocol. // It cannot possibly be TCompactProtocol since a value of 0 would imply a field id // of 0 as the zig zag varint encoding would end. // if (data.length > 1 && 0 == data[1]) { return new TBinaryProtocol.Factory(); } // // If bit 7 of the first byte of the field id is set then we have two choices: // 1. A field id > 63 was encoded with TCompactProtocol. // 2. A field id > 0x7fff (32767) was encoded with TBinaryProtocol and the last byte of the // serialized data is 0. // Option 2 is impossible since field ids are short and thus limited to 32767. // if (data.length > 1 && (data[1] & 0x80) != 0) { return new TCompactProtocol.Factory(); } // // The remaining case is either a field id <= 63 encoded as TCompactProtocol, // one >= 256 encoded with TBinaryProtocol with a last byte at 0, or an empty structure. // As we cannot really decide, we return the fallback protocol. // return fallback; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TType.java0000644000000000000000000000305014472647462026321 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Type constants in the Thrift protocol. */ public final class TType { public static final byte STOP = 0; public static final byte VOID = 1; public static final byte BOOL = 2; public static final byte BYTE = 3; public static final byte DOUBLE = 4; public static final byte I16 = 6; public static final byte I32 = 8; public static final byte I64 = 10; public static final byte STRING = 11; public static final byte STRUCT = 12; public static final byte MAP = 13; public static final byte SET = 14; public static final byte LIST = 15; public static final byte UUID = 16; /** This is not part of the TBinaryProtocol spec but Java specific implementation detail */ public static final byte ENUM = -1; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TBase64Utils.java0000644000000000000000000001264614370300523027435 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Class for encoding and decoding Base64 data. * *

This class is kept at package level because the interface does no input validation and is * therefore too low-level for generalized reuse. * *

Note also that the encoding does not pad with equal signs , as discussed in section 2.2 of the * RFC (http://www.faqs.org/rfcs/rfc3548.html). Furthermore, bad data encountered when decoding is * neither rejected or ignored but simply results in bad decoded data -- this is not in compliance * with the RFC but is done in the interest of performance. */ class TBase64Utils { private static final String ENCODE_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * Encode len bytes of data in src at offset srcOff, storing the result into dst at offset dstOff. * len must be 1, 2, or 3. dst must have at least len+1 bytes of space at dstOff. src and dst * should not be the same object. This method does no validation of the input values in the * interest of performance. * * @param src the source of bytes to encode * @param srcOff the offset into the source to read the unencoded bytes * @param len the number of bytes to encode (must be 1, 2, or 3). * @param dst the destination for the encoding * @param dstOff the offset into the destination to place the encoded bytes */ static void encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) { dst[dstOff] = (byte) ENCODE_TABLE.charAt((src[srcOff] >> 2) & 0x3F); if (len == 3) { dst[dstOff + 1] = (byte) ENCODE_TABLE.charAt(((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)); dst[dstOff + 2] = (byte) ENCODE_TABLE.charAt( ((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)); dst[dstOff + 3] = (byte) ENCODE_TABLE.charAt(src[srcOff + 2] & 0x3F); } else if (len == 2) { dst[dstOff + 1] = (byte) ENCODE_TABLE.charAt(((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)); dst[dstOff + 2] = (byte) ENCODE_TABLE.charAt((src[srcOff + 1] << 2) & 0x3C); } else { // len == 1) { dst[dstOff + 1] = (byte) ENCODE_TABLE.charAt((src[srcOff] << 4) & 0x30); } } private static final byte[] DECODE_TABLE = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; /** * Decode len bytes of data in src at offset srcOff, storing the result into dst at offset dstOff. * len must be 2, 3, or 4. dst must have at least len-1 bytes of space at dstOff. src and dst may * be the same object as long as dstoff <= srcOff. This method does no validation of the input * values in the interest of performance. * * @param src the source of bytes to decode * @param srcOff the offset into the source to read the encoded bytes * @param len the number of bytes to decode (must be 2, 3, or 4) * @param dst the destination for the decoding * @param dstOff the offset into the destination to place the decoded bytes */ static void decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) { dst[dstOff] = (byte) ((DECODE_TABLE[src[srcOff] & 0x0FF] << 2) | (DECODE_TABLE[src[srcOff + 1] & 0x0FF] >> 4)); if (len > 2) { dst[dstOff + 1] = (byte) (((DECODE_TABLE[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DECODE_TABLE[src[srcOff + 2] & 0x0FF] >> 2)); if (len > 3) { dst[dstOff + 2] = (byte) (((DECODE_TABLE[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DECODE_TABLE[src[srcOff + 3] & 0x0FF]); } } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TMessage.java0000644000000000000000000000411514303740367026756 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Helper class that encapsulates struct metadata. */ public final class TMessage { public TMessage() { this("", TType.STOP, 0); } public TMessage(String n, byte t, int s) { name = n; type = t; seqid = s; } public final String name; public final byte type; public final int seqid; public String getName() { return name; } public byte getType() { return type; } public int getSeqid() { return seqid; } @Override public String toString() { return ""; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + seqid; result = prime * result + type; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TMessage other = (TMessage) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (seqid != other.seqid) return false; if (type != other.type) return false; return true; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TMap.java0000644000000000000000000000245014303740367026107 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Helper class that encapsulates map metadata. */ public final class TMap { public TMap() { this(TType.STOP, TType.STOP, 0); } public TMap(byte k, byte v, int s) { keyType = k; valueType = v; size = s; } public final byte keyType; public final byte valueType; public final int size; public byte getKeyType() { return keyType; } public byte getValueType() { return valueType; } public int getSize() { return size; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TTupleProtocol.java0000644000000000000000000000724714370300523030204 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.util.BitSet; import org.apache.thrift.TException; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.TupleScheme; import org.apache.thrift.transport.TTransport; public final class TTupleProtocol extends TCompactProtocol { public static class Factory implements TProtocolFactory { public Factory() {} @Override public TProtocol getProtocol(TTransport trans) { return new TTupleProtocol(trans); } } public TTupleProtocol(TTransport transport) { super(transport); } @Override public Class getScheme() { return TupleScheme.class; } public void writeBitSet(BitSet bs, int vectorWidth) throws TException { byte[] bytes = toByteArray(bs, vectorWidth); for (byte b : bytes) { writeByte(b); } } public BitSet readBitSet(int i) throws TException { int length = (int) Math.ceil(i / 8.0); byte[] bytes = new byte[length]; for (int j = 0; j < length; j++) { bytes[j] = readByte(); } BitSet bs = fromByteArray(bytes); return bs; } /** Returns a bitset containing the values in bytes. The byte-ordering must be big-endian. */ public static BitSet fromByteArray(byte[] bytes) { BitSet bits = new BitSet(); for (int i = 0; i < bytes.length * 8; i++) { if ((bytes[bytes.length - i / 8 - 1] & (1 << (i % 8))) > 0) { bits.set(i); } } return bits; } /** * Returns a byte array of at least length 1. The most significant bit in the result is guaranteed * not to be a 1 (since BitSet does not support sign extension). The byte-ordering of the result * is big-endian which means the most significant bit is in element 0. The bit at index 0 of the * bit set is assumed to be the least significant bit. * * @param bits bit set * @param vectorWidth width of the vector * @return a byte array of at least length 1 */ public static byte[] toByteArray(BitSet bits, int vectorWidth) { byte[] bytes = new byte[(int) Math.ceil(vectorWidth / 8.0)]; for (int i = 0; i < bits.length(); i++) { if (bits.get(i)) { bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8); } } return bytes; } public TMap readMapBegin(byte keyType, byte valTyep) throws TException { int size = super.readI32(); TMap map = new TMap(keyType, valTyep, size); checkReadBytesAvailable(map); return map; } public TList readListBegin(byte type) throws TException { int size = super.readI32(); TList list = new TList(type, size); checkReadBytesAvailable(list); return list; } public TSet readSetBegin(byte type) throws TException { return new TSet(readListBegin(type)); } @Override public void readMapEnd() throws TException {} @Override public void readListEnd() throws TException {} @Override public void readSetEnd() throws TException {} } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TProtocol.java0000644000000000000000000003767214303740367027211 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.IntFunction; import org.apache.thrift.TException; import org.apache.thrift.partial.TFieldData; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.StandardScheme; import org.apache.thrift.transport.TTransport; /** Protocol interface definition. */ public abstract class TProtocol implements TWriteProtocol, TReadProtocol { /** Prevent direct instantiation */ @SuppressWarnings("unused") private TProtocol() {} /** Transport */ protected TTransport trans_; /** Constructor */ protected TProtocol(TTransport trans) { trans_ = trans; } /** Transport accessor */ public TTransport getTransport() { return trans_; } protected void checkReadBytesAvailable(TMap map) throws TException { long elemSize = getMinSerializedSize(map.keyType) + getMinSerializedSize(map.valueType); trans_.checkReadBytesAvailable(map.size * elemSize); } protected void checkReadBytesAvailable(TList list) throws TException { long size = list.getSize(); trans_.checkReadBytesAvailable(size * getMinSerializedSize(list.elemType)); } protected void checkReadBytesAvailable(TSet set) throws TException { long size = set.getSize(); trans_.checkReadBytesAvailable(size * getMinSerializedSize(set.elemType)); } /** * Return min serialized size in bytes * * @param type Returns the minimum amount of bytes needed to store the smallest possible instance * of TType. * @return min serialized size * @throws TException when error happens */ public abstract int getMinSerializedSize(byte type) throws TException; public interface WriteCallback { void call(T e) throws TException; } public interface ReadCallback { R accept(T t) throws TException; } public interface ReadCollectionCallback { R call() throws TException; } public interface ReadMapEntryCallback { K getKey() throws TException; V getValue() throws TException; } public final void writeSet(byte elementType, Set set, WriteCallback callback) throws TException { writeSetBegin(new TSet(elementType, set.size())); for (T t : set) { callback.call(t); } writeSetEnd(); } public final void writeList(byte elementType, List list, WriteCallback callback) throws TException { writeListBegin(new TList(elementType, list.size())); for (T t : list) { callback.call(t); } writeListEnd(); } public final void writeMap( byte keyType, byte valueType, Map map, WriteCallback> callback) throws TException { writeMapBegin(new TMap(keyType, valueType, map.size())); for (Map.Entry entry : map.entrySet()) { callback.call(entry); } writeMapEnd(); } public final void writeField(TField field, WriteCallback callback) throws TException { writeFieldBegin(field); callback.call(null); writeFieldEnd(); } public final void writeStruct(TStruct struct, WriteCallback callback) throws TException { writeStructBegin(struct); callback.call(null); writeStructEnd(); } public final void writeMessage(TMessage message, WriteCallback callback) throws TException { writeMessageBegin(message); callback.call(null); writeMessageEnd(); } /** * read a message by delegating to a callback, handles {@link #readMessageBegin() begin} and * {@link #readMessageEnd() end} automatically. * * @param callback callback for actual reading * @param result message type * @return the message read * @throws TException when any sub-operation failed */ public final T readMessage(ReadCallback callback) throws TException { TMessage tMessage = readMessageBegin(); T t = callback.accept(tMessage); readMessageEnd(); return t; } /** * read a struct by delegating to a callback, handles {@link #readStructBegin() begin} and {@link * #readStructEnd() end} automatically. * * @param callback callback for actual reading * @param result struct type * @return the struct read * @throws TException when any sub-operation failed */ public final T readStruct(ReadCallback callback) throws TException { TStruct tStruct = readStructBegin(); T t = callback.accept(tStruct); readStructEnd(); return t; } /** * read a field by delegating to a callback, handles {@link #readFieldBegin() begin} and {@link * #readFieldEnd() end} automatically, and returns whether the {@link TType#STOP stop signal} was * encountered. Because the value is not returned, you (the compiler generated code in most cases) * are expected to set the field yourself within the callback. * * @param callback callback for reading a field * @param result field type * @return true if a stop signal was encountered, false otherwise * @throws Exception when any sub-operation failed */ public final boolean readField(ReadCallback callback) throws Exception { TField tField = readFieldBegin(); if (tField.type == org.apache.thrift.protocol.TType.STOP) { return true; } callback.accept(tField); readFieldEnd(); return false; } /** * read a {@link Map} of elements by delegating to the callback, handles {@link #readMapBegin() * begin} and {@link #readMapEnd() end} automatically. * * @param callback callback for reading the map * @param result map type * @return the map read * @throws TException when any sub-operation fails */ public final > T readMap(ReadCallback callback) throws TException { TMap tMap = readMapBegin(); T t = callback.accept(tMap); readMapEnd(); return t; } /** * read a {@link Map} of elements by delegating key and value reading to the callback, handles * {@link #readMapBegin() begin} and {@link #readMapEnd() end} automatically. * * @param callback callback for reading keys and values, calls to {@link * ReadMapEntryCallback#getKey()} and {@link ReadMapEntryCallback#getValue()} will be in * alternating orders, i.e. k1, v1, k2, v2, .., k_n, v_n * @param key type * @param value type * @return the map read * @throws TException when any sub-operation fails */ public final Map readMap(ReadMapEntryCallback callback) throws TException { return readMap(callback, HashMap::new); } /** * read a {@link Map} of elements by delegating key and value reading to the callback, handles * {@link #readMapBegin() begin} and {@link #readMapEnd() end} automatically, with a specialized * map creator given the size hint. * * @param callback callback for reading keys and values, calls to {@link * ReadMapEntryCallback#getKey()} and {@link ReadMapEntryCallback#getValue()} will be in * alternating orders, i.e. k1, v1, k2, v2, .., k_n, v_n * @param mapCreator map creator given the size hint * @param key type * @param value type * @return the map read * @throws TException when any sub-operation fails */ public final Map readMap( ReadMapEntryCallback callback, IntFunction> mapCreator) throws TException { return readMap( tMap -> { Map map = mapCreator.apply(tMap.size); for (int i = 0; i < tMap.size; i += 1) { map.put(callback.getKey(), callback.getValue()); } return map; }); } /** * read a {@link List} by delegating to the callback, handles {@link #readListBegin() begin} and * {@link #readListEnd() end} automatically. * * @param callback callback for reading the list * @param result list type * @return the list read * @throws TException when any sub-operation fails */ public final > T readList(ReadCallback callback) throws TException { TList tList = readListBegin(); T t = callback.accept(tList); readListEnd(); return t; } /** * read a {@link List} by delegating element reading to the callback, handles {@link * #readListBegin() begin} and {@link #readListEnd() end} automatically. * * @param callback callback for reading one element * @param element type * @return list of elements read * @throws TException when any sub-operation fails */ public final List readList(ReadCollectionCallback callback) throws TException { return readList(callback, ArrayList::new); } /** * read a {@link List} by delegating element reading to the callback, handles {@link * #readListBegin() begin} and {@link #readListEnd() end} automatically, with a specialized list * creator given the size hint. * * @param callback callback for reading one element * @param listCreator list creator given size hint * @param element type * @return list of elements read * @throws TException when any sub-operation fails */ public final List readList( ReadCollectionCallback callback, IntFunction> listCreator) throws TException { return readList( tList -> { List list = listCreator.apply(tList.size); for (int i = 0; i < tList.size; i += 1) { list.add(callback.call()); } return list; }); } /** * read a {@link Set} of elements by delegating to the callback, handles {@link #readSetBegin() * begin} and {@link #readSetEnd() end} automatically * * @param callback callback for reading the set * @param result set type * @return the set read * @throws TException when any sub-operation fails */ public final > T readSet(ReadCallback callback) throws TException { TSet tSet = readSetBegin(); T t = callback.accept(tSet); readSetEnd(); return t; } /** * read a {@link Set} of elements by delegating element reading to the callback, handles {@link * #readSetBegin() begin} and {@link #readSetEnd() end} automatically * * @param callback callback for reading one element * @param element type * @return set of elements read * @throws TException when any sub-operation fails */ public final Set readSet(ReadCollectionCallback callback) throws TException { return readSet(callback, HashSet::new); } /** * read a {@link Set} of elements by delegating element reading to the callback, handles {@link * #readSetBegin() begin} and {@link #readSetEnd() end} automatically, with a specialized set * creator given the size hint. * * @param callback callback for reading one elment * @param setCreator set creator given size hint * @param element type * @return set of elements read * @throws TException when any sub-operation fails */ public final Set readSet( ReadCollectionCallback callback, IntFunction> setCreator) throws TException { return readSet( tSet -> { Set set = setCreator.apply(tSet.size); for (int i = 0; i < tSet.size; i += 1) { set.add(callback.call()); } return set; }); } /** * Reset any internal state back to a blank slate. This method only needs to be implemented for * stateful protocols. */ public void reset() {} /** Scheme accessor */ public Class getScheme() { return StandardScheme.class; } // ----------------------------------------------------------------- // Additional methods to improve performance. public int readFieldBeginData() throws TException { // Derived classes should provide a more efficient version of this // method if allowed by the encoding used by that protocol. TField tfield = this.readFieldBegin(); return TFieldData.encode(tfield.type, tfield.id); } public void skip(byte fieldType) throws TException { this.skip(fieldType, Integer.MAX_VALUE); } public void skip(byte fieldType, int maxDepth) throws TException { if (maxDepth <= 0) { throw new TException("Maximum skip depth exceeded"); } switch (fieldType) { case TType.BOOL: this.skipBool(); break; case TType.BYTE: this.skipByte(); break; case TType.I16: this.skipI16(); break; case TType.I32: this.skipI32(); break; case TType.I64: this.skipI64(); break; case TType.DOUBLE: this.skipDouble(); break; case TType.STRING: this.skipBinary(); break; case TType.STRUCT: this.readStructBegin(); while (true) { int tfieldData = this.readFieldBeginData(); byte tfieldType = TFieldData.getType(tfieldData); if (tfieldType == TType.STOP) { break; } this.skip(tfieldType, maxDepth - 1); this.readFieldEnd(); } this.readStructEnd(); break; case TType.MAP: TMap map = this.readMapBegin(); for (int i = 0; i < map.size; i++) { this.skip(map.keyType, maxDepth - 1); this.skip(map.valueType, maxDepth - 1); } this.readMapEnd(); break; case TType.SET: TSet set = this.readSetBegin(); for (int i = 0; i < set.size; i++) { this.skip(set.elemType, maxDepth - 1); } this.readSetEnd(); break; case TType.LIST: TList list = this.readListBegin(); for (int i = 0; i < list.size; i++) { this.skip(list.elemType, maxDepth - 1); } this.readListEnd(); break; default: throw new TProtocolException( TProtocolException.INVALID_DATA, "Unrecognized type " + fieldType); } } /** * The default implementation of all skip() methods calls the corresponding read() method. * Protocols that derive from this class are strongly encouraged to provide a more efficient * alternative. */ protected void skipBool() throws TException { this.readBool(); } protected void skipByte() throws TException { this.readByte(); } protected void skipI16() throws TException { this.readI16(); } protected void skipI32() throws TException { this.readI32(); } protected void skipI64() throws TException { this.readI64(); } protected void skipDouble() throws TException { this.readDouble(); } protected void skipBinary() throws TException { this.readBinary(); } static final int MAX_SKIPPED_BYTES = 256; protected byte[] skippedBytes = new byte[MAX_SKIPPED_BYTES]; protected void skipBytes(int numBytes) throws TException { if (numBytes <= MAX_SKIPPED_BYTES) { if (this.getTransport().getBytesRemainingInBuffer() >= numBytes) { this.getTransport().consumeBuffer(numBytes); } else { this.getTransport().readAll(skippedBytes, 0, numBytes); } } else { int remaining = numBytes; while (remaining > 0) { skipBytes(Math.min(remaining, MAX_SKIPPED_BYTES)); remaining -= MAX_SKIPPED_BYTES; } } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TSet.java0000644000000000000000000000236114303740367026126 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Helper class that encapsulates set metadata. */ public final class TSet { public TSet() { this(TType.STOP, 0); } public TSet(byte t, int s) { elemType = t; size = s; } public TSet(TList list) { this(list.elemType, list.size); } public final byte elemType; public final int size; public byte getElemType() { return elemType; } public int getSize() { return size; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TMultiplexedProtocol.java0000644000000000000000000000655114303740367031416 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TException; /** * TMultiplexedProtocol is a protocol-independent concrete decorator that allows a * Thrift client to communicate with a multiplexing Thrift server, by prepending the service name to * the function name during function calls. * *

NOTE: THIS IS NOT USED BY SERVERS. On the server, use {@link * org.apache.thrift.TMultiplexedProcessor TMultiplexedProcessor} to handle requests from a * multiplexing client. * *

This example uses a single socket transport to invoke two services: * *

{@code
 * TSocket transport = new TSocket("localhost", 9090);
 * transport.open();
 *
 * TBinaryProtocol protocol = new TBinaryProtocol(transport);
 *
 * TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator");
 * Calculator.Client service = new Calculator.Client(mp);
 *
 * TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport");
 * WeatherReport.Client service2 = new WeatherReport.Client(mp2);
 *
 * System.out.println(service.add(2,2));
 * System.out.println(service2.getTemperature());
 * }
* * @see org.apache.thrift.protocol.TProtocolDecorator */ public class TMultiplexedProtocol extends TProtocolDecorator { /** Used to delimit the service name from the function name */ public static final String SEPARATOR = ":"; private final String SERVICE_NAME; /** * Wrap the specified protocol, allowing it to be used to communicate with a multiplexing server. * The serviceName is required as it is prepended to the message header so that the * multiplexing server can broker the function call to the proper service. * * @param protocol Your communication protocol of choice, e.g. TBinaryProtocol. * @param serviceName The service name of the service communicating via this protocol. */ public TMultiplexedProtocol(TProtocol protocol, String serviceName) { super(protocol); SERVICE_NAME = serviceName; } /** * Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR. * * @param tMessage The original message. * @throws TException Passed through from wrapped TProtocol instance. */ @Override public void writeMessageBegin(TMessage tMessage) throws TException { if (tMessage.type == TMessageType.CALL || tMessage.type == TMessageType.ONEWAY) { super.writeMessageBegin( new TMessage(SERVICE_NAME + SEPARATOR + tMessage.name, tMessage.type, tMessage.seqid)); } else { super.writeMessageBegin(tMessage); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TReadProtocol.java0000644000000000000000000000202114370300523027747 0ustar00rootroot00000000000000package org.apache.thrift.protocol; import java.nio.ByteBuffer; import java.util.UUID; import org.apache.thrift.TException; public interface TReadProtocol { TMessage readMessageBegin() throws TException; void readMessageEnd() throws TException; TStruct readStructBegin() throws TException; void readStructEnd() throws TException; TField readFieldBegin() throws TException; void readFieldEnd() throws TException; TMap readMapBegin() throws TException; void readMapEnd() throws TException; TList readListBegin() throws TException; void readListEnd() throws TException; TSet readSetBegin() throws TException; void readSetEnd() throws TException; boolean readBool() throws TException; byte readByte() throws TException; short readI16() throws TException; int readI32() throws TException; long readI64() throws TException; UUID readUuid() throws TException; double readDouble() throws TException; String readString() throws TException; ByteBuffer readBinary() throws TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TMessageType.java0000644000000000000000000000210014303740367027610 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Message type constants in the Thrift protocol. */ public final class TMessageType { public static final byte CALL = 1; public static final byte REPLY = 2; public static final byte EXCEPTION = 3; public static final byte ONEWAY = 4; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TSimpleJSONProtocol.java0000644000000000000000000003156514370300523031036 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Stack; import java.util.UUID; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; /** * JSON protocol implementation for thrift. * *

This protocol is write-only and produces a simple output format suitable for parsing by * scripting languages. It should not be confused with the full-featured TJSONProtocol. */ public class TSimpleJSONProtocol extends TProtocol { /** Factory */ public static class Factory implements TProtocolFactory { @Override public TProtocol getProtocol(TTransport trans) { return new TSimpleJSONProtocol(trans); } } private static final byte[] COMMA = new byte[] {','}; private static final byte[] COLON = new byte[] {':'}; private static final byte[] LBRACE = new byte[] {'{'}; private static final byte[] RBRACE = new byte[] {'}'}; private static final byte[] LBRACKET = new byte[] {'['}; private static final byte[] RBRACKET = new byte[] {']'}; private static final char QUOTE = '"'; private static final String LIST = "list"; private static final String SET = "set"; private static final String MAP = "map"; protected static class Context { protected void write() throws TException {} /** Returns whether the current value is a key in a map */ protected boolean isMapKey() { return false; } } protected class ListContext extends Context { protected boolean first_ = true; protected void write() throws TException { if (first_) { first_ = false; } else { trans_.write(COMMA); } } } protected class StructContext extends Context { protected boolean first_ = true; protected boolean colon_ = true; protected void write() throws TException { if (first_) { first_ = false; colon_ = true; } else { trans_.write(colon_ ? COLON : COMMA); colon_ = !colon_; } } } protected class MapContext extends StructContext { protected boolean isKey = true; @Override protected void write() throws TException { super.write(); isKey = !isKey; } protected boolean isMapKey() { // we want to coerce map keys to json strings regardless // of their type return isKey; } } protected final Context BASE_CONTEXT = new Context(); /** Stack of nested contexts that we may be in. */ protected Stack writeContextStack_ = new Stack(); /** Current context that we are in */ protected Context writeContext_ = BASE_CONTEXT; /** Push a new write context onto the stack. */ protected void pushWriteContext(Context c) { writeContextStack_.push(writeContext_); writeContext_ = c; } /** Pop the last write context off the stack */ protected void popWriteContext() { writeContext_ = writeContextStack_.pop(); } /** Reset the write context stack to its initial state. */ protected void resetWriteContext() { while (!writeContextStack_.isEmpty()) { popWriteContext(); } } /** Used to make sure that we are not encountering a map whose keys are containers */ protected void assertContextIsNotMapKey(String invalidKeyType) throws CollectionMapKeyException { if (writeContext_.isMapKey()) { throw new CollectionMapKeyException( "Cannot serialize a map with keys that are of type " + invalidKeyType); } } /** Constructor */ public TSimpleJSONProtocol(TTransport trans) { super(trans); } @Override public void writeMessageBegin(TMessage message) throws TException { resetWriteContext(); // THRIFT-3743 trans_.write(LBRACKET); pushWriteContext(new ListContext()); writeString(message.name); writeByte(message.type); writeI32(message.seqid); } @Override public void writeMessageEnd() throws TException { popWriteContext(); trans_.write(RBRACKET); } @Override public void writeStructBegin(TStruct struct) throws TException { writeContext_.write(); trans_.write(LBRACE); pushWriteContext(new StructContext()); } @Override public void writeStructEnd() throws TException { popWriteContext(); trans_.write(RBRACE); } @Override public void writeFieldBegin(TField field) throws TException { // Note that extra type information is omitted in JSON! writeString(field.name); } @Override public void writeFieldEnd() throws TException {} @Override public void writeFieldStop() throws TException {} @Override public void writeMapBegin(TMap map) throws TException { assertContextIsNotMapKey(MAP); writeContext_.write(); trans_.write(LBRACE); pushWriteContext(new MapContext()); // No metadata! } @Override public void writeMapEnd() throws TException { popWriteContext(); trans_.write(RBRACE); } @Override public void writeListBegin(TList list) throws TException { assertContextIsNotMapKey(LIST); writeContext_.write(); trans_.write(LBRACKET); pushWriteContext(new ListContext()); // No metadata! } @Override public void writeListEnd() throws TException { popWriteContext(); trans_.write(RBRACKET); } @Override public void writeSetBegin(TSet set) throws TException { assertContextIsNotMapKey(SET); writeContext_.write(); trans_.write(LBRACKET); pushWriteContext(new ListContext()); // No metadata! } @Override public void writeSetEnd() throws TException { popWriteContext(); trans_.write(RBRACKET); } @Override public void writeBool(boolean b) throws TException { writeByte(b ? (byte) 1 : (byte) 0); } @Override public void writeByte(byte b) throws TException { writeI32(b); } @Override public void writeI16(short i16) throws TException { writeI32(i16); } @Override public void writeI32(int i32) throws TException { if (writeContext_.isMapKey()) { writeString(Integer.toString(i32)); } else { writeContext_.write(); _writeStringData(Integer.toString(i32)); } } public void _writeStringData(String s) throws TException { byte[] b = s.getBytes(StandardCharsets.UTF_8); trans_.write(b); } @Override public void writeI64(long i64) throws TException { if (writeContext_.isMapKey()) { writeString(Long.toString(i64)); } else { writeContext_.write(); _writeStringData(Long.toString(i64)); } } @Override public void writeUuid(UUID uuid) throws TException { writeString(uuid.toString()); } @Override public void writeDouble(double dub) throws TException { if (writeContext_.isMapKey()) { writeString(Double.toString(dub)); } else { writeContext_.write(); _writeStringData(Double.toString(dub)); } } @Override public void writeString(String str) throws TException { writeContext_.write(); int length = str.length(); StringBuilder escape = new StringBuilder(length + 16); escape.append(QUOTE); for (int i = 0; i < length; ++i) { char c = str.charAt(i); switch (c) { case '"': case '\\': escape.append('\\'); escape.append(c); break; case '\b': escape.append('\\'); escape.append('b'); break; case '\f': escape.append('\\'); escape.append('f'); break; case '\n': escape.append('\\'); escape.append('n'); break; case '\r': escape.append('\\'); escape.append('r'); break; case '\t': escape.append('\\'); escape.append('t'); break; default: // Control characters! According to JSON RFC u0020 (space) if (c < ' ') { String hex = Integer.toHexString(c); escape.append('\\'); escape.append('u'); for (int j = 4; j > hex.length(); --j) { escape.append('0'); } escape.append(hex); } else { escape.append(c); } break; } } escape.append(QUOTE); _writeStringData(escape.toString()); } @Override public void writeBinary(ByteBuffer bin) throws TException { // TODO(mcslee): Fix this writeString( new String( bin.array(), bin.position() + bin.arrayOffset(), bin.limit() - bin.position() - bin.arrayOffset(), StandardCharsets.UTF_8)); } /** * Reading methods. * *

simplejson is not meant to be read back into thrift - see ThriftUsageJava - use JSON instead */ @Override public TMessage readMessageBegin() throws TException { throw new TException("Not implemented"); } @Override public void readMessageEnd() throws TException { throw new TException("Not implemented"); } @Override public TStruct readStructBegin() throws TException { throw new TException("Not implemented"); } @Override public void readStructEnd() throws TException { throw new TException("Not implemented"); } @Override public TField readFieldBegin() throws TException { throw new TException("Not implemented"); } @Override public void readFieldEnd() throws TException { throw new TException("Not implemented"); } @Override public TMap readMapBegin() throws TException { throw new TException("Not implemented"); } @Override public void readMapEnd() throws TException { throw new TException("Not implemented"); } @Override public TList readListBegin() throws TException { throw new TException("Not implemented"); } @Override public void readListEnd() throws TException { throw new TException("Not implemented"); } @Override public TSet readSetBegin() throws TException { throw new TException("Not implemented"); } @Override public void readSetEnd() throws TException { throw new TException("Not implemented"); } @Override public boolean readBool() throws TException { throw new TException("Not implemented"); } @Override public byte readByte() throws TException { throw new TException("Not implemented"); } @Override public short readI16() throws TException { throw new TException("Not implemented"); } @Override public int readI32() throws TException { throw new TException("Not implemented"); } @Override public long readI64() throws TException { throw new TException("Not implemented"); } @Override public UUID readUuid() throws TException { throw new TException("Not implemented"); } @Override public double readDouble() throws TException { throw new TException("Not implemented"); } @Override public String readString() throws TException { throw new TException("Not implemented"); } public String readStringBody(int size) throws TException { throw new TException("Not implemented"); } @Override public ByteBuffer readBinary() throws TException { throw new TException("Not implemented"); } public static class CollectionMapKeyException extends TException { public CollectionMapKeyException(String message) { super(message); } } /** Return the minimum number of bytes a type will consume on the wire */ @Override public int getMinSerializedSize(byte type) throws TException { switch (type) { case 0: return 0; // Stop case 1: return 0; // Void case 2: return 1; // Bool case 3: return 1; // Byte case 4: return 1; // Double case 6: return 1; // I16 case 8: return 1; // I32 case 10: return 1; // I64 case 11: return 2; // string length case 12: return 2; // empty struct case 13: return 2; // element count Map case 14: return 2; // element count Set case 15: return 2; // element count List default: throw new TTransportException(TTransportException.UNKNOWN, "unrecognized type code"); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/ShortStack.java0000644000000000000000000000403614303740367027335 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.util.Arrays; /** * ShortStack is a short-specific Stack implementation written for the express purpose of very fast * operations on TCompactProtocol's field id stack. This implementation performs at least 10x faster * than java.util.Stack. */ class ShortStack { private short[] vector; /** Always points to the next location */ private int top = 0; public ShortStack(int initialCapacity) { vector = new short[initialCapacity]; } public short pop() { return vector[--top]; } public void push(short pushed) { if (vector.length == top) { grow(); } vector[top++] = pushed; } private void grow() { vector = Arrays.copyOf(vector, vector.length << 1); } public void clear() { top = 0; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(">").append(value).append("<<"); } else { sb.append(value); } } sb.append("]>"); return sb.toString(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TProtocolFactory.java0000644000000000000000000000207314303740367030524 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.io.Serializable; import org.apache.thrift.transport.TTransport; /** Factory interface for constructing protocol instances. */ public interface TProtocolFactory extends Serializable { TProtocol getProtocol(TTransport trans); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TList.java0000644000000000000000000000226014303740367026304 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Helper class that encapsulates list metadata. */ public final class TList { public TList() { this(TType.STOP, 0); } public TList(byte t, int s) { elemType = t; size = s; } public final byte elemType; public final int size; public byte getElemType() { return elemType; } public int getSize() { return size; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TCompactProtocol.java0000644000000000000000000007167714452237057030525 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.UUID; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; /** * TCompactProtocol2 is the Java implementation of the compact protocol specified in THRIFT-110. The * fundamental approach to reducing the overhead of structures is a) use variable-length integers * all over the place and b) make use of unused bits wherever possible. Your savings will obviously * vary based on the specific makeup of your structs, but in general, the more fields, nested * structures, short strings and collections, and low-value i32 and i64 fields you have, the more * benefit you'll see. */ public class TCompactProtocol extends TProtocol { private static final byte[] EMPTY_BYTES = new byte[0]; private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.wrap(EMPTY_BYTES); private static final long NO_LENGTH_LIMIT = -1; private static final TStruct ANONYMOUS_STRUCT = new TStruct(""); private static final TField TSTOP = new TField("", TType.STOP, (short) 0); private static final byte[] ttypeToCompactType = new byte[18]; static { ttypeToCompactType[TType.STOP] = TType.STOP; ttypeToCompactType[TType.BOOL] = Types.BOOLEAN_TRUE; ttypeToCompactType[TType.BYTE] = Types.BYTE; ttypeToCompactType[TType.I16] = Types.I16; ttypeToCompactType[TType.I32] = Types.I32; ttypeToCompactType[TType.I64] = Types.I64; ttypeToCompactType[TType.DOUBLE] = Types.DOUBLE; ttypeToCompactType[TType.STRING] = Types.BINARY; ttypeToCompactType[TType.LIST] = Types.LIST; ttypeToCompactType[TType.SET] = Types.SET; ttypeToCompactType[TType.MAP] = Types.MAP; ttypeToCompactType[TType.STRUCT] = Types.STRUCT; ttypeToCompactType[TType.UUID] = Types.UUID; } /** TProtocolFactory that produces TCompactProtocols. */ public static class Factory implements TProtocolFactory { private final long stringLengthLimit_; private final long containerLengthLimit_; public Factory() { this(NO_LENGTH_LIMIT, NO_LENGTH_LIMIT); } public Factory(long stringLengthLimit) { this(stringLengthLimit, NO_LENGTH_LIMIT); } public Factory(long stringLengthLimit, long containerLengthLimit) { this.containerLengthLimit_ = containerLengthLimit; this.stringLengthLimit_ = stringLengthLimit; } @Override public TProtocol getProtocol(TTransport trans) { return new TCompactProtocol(trans, stringLengthLimit_, containerLengthLimit_); } } private static final byte PROTOCOL_ID = (byte) 0x82; private static final byte VERSION = 1; private static final byte VERSION_MASK = 0x1f; // 0001 1111 private static final byte TYPE_MASK = (byte) 0xE0; // 1110 0000 private static final byte TYPE_BITS = 0x07; // 0000 0111 private static final int TYPE_SHIFT_AMOUNT = 5; /** All of the on-wire type codes. */ private static class Types { public static final byte BOOLEAN_TRUE = 0x01; public static final byte BOOLEAN_FALSE = 0x02; public static final byte BYTE = 0x03; public static final byte I16 = 0x04; public static final byte I32 = 0x05; public static final byte I64 = 0x06; public static final byte DOUBLE = 0x07; public static final byte BINARY = 0x08; public static final byte LIST = 0x09; public static final byte SET = 0x0A; public static final byte MAP = 0x0B; public static final byte STRUCT = 0x0C; public static final byte UUID = 0x0D; } /** * Used to keep track of the last field for the current and previous structs, so we can do the * delta stuff. */ private final ShortStack lastField_ = new ShortStack(15); private short lastFieldId_ = 0; /** * If we encounter a boolean field begin, save the TField here so it can have the value * incorporated. */ private TField booleanField_ = null; /** * If we read a field header, and it's a boolean field, save the boolean value here so that * readBool can use it. */ private Boolean boolValue_ = null; /** * The maximum number of bytes to read from the transport for variable-length fields (such as * strings or binary) or {@link #NO_LENGTH_LIMIT} for unlimited. */ private final long stringLengthLimit_; /** * The maximum number of elements to read from the network for containers (maps, sets, lists), or * {@link #NO_LENGTH_LIMIT} for unlimited. */ private final long containerLengthLimit_; /** * Temporary buffer used for various operations that would otherwise require a small allocation. */ private final byte[] temp = new byte[16]; /** * Create a TCompactProtocol. * * @param transport the TTransport object to read from or write to. * @param stringLengthLimit the maximum number of bytes to read for variable-length fields. * @param containerLengthLimit the maximum number of elements to read for containers. */ public TCompactProtocol(TTransport transport, long stringLengthLimit, long containerLengthLimit) { super(transport); this.stringLengthLimit_ = stringLengthLimit; this.containerLengthLimit_ = containerLengthLimit; } /** * Create a TCompactProtocol. * * @param transport the TTransport object to read from or write to. * @param stringLengthLimit the maximum number of bytes to read for variable-length fields. * @deprecated Use constructor specifying both string limit and container limit instead */ @Deprecated public TCompactProtocol(TTransport transport, long stringLengthLimit) { this(transport, stringLengthLimit, NO_LENGTH_LIMIT); } /** * Create a TCompactProtocol. * * @param transport the TTransport object to read from or write to. */ public TCompactProtocol(TTransport transport) { this(transport, NO_LENGTH_LIMIT, NO_LENGTH_LIMIT); } @Override public void reset() { lastField_.clear(); lastFieldId_ = 0; } // // Public Writing methods. // /** * Write a message header to the wire. Compact Protocol messages contain the protocol version so * we can migrate forwards in the future if need be. */ @Override public void writeMessageBegin(TMessage message) throws TException { writeByteDirect(PROTOCOL_ID); writeByteDirect((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); writeVarint32(message.seqid); writeString(message.name); } /** * Write a struct begin. This doesn't actually put anything on the wire. We use it as an * opportunity to put special placeholder markers on the field stack so we can get the field id * deltas correct. */ @Override public void writeStructBegin(TStruct struct) throws TException { lastField_.push(lastFieldId_); lastFieldId_ = 0; } /** * Write a struct end. This doesn't actually put anything on the wire. We use this as an * opportunity to pop the last field from the current struct off of the field stack. */ @Override public void writeStructEnd() throws TException { lastFieldId_ = lastField_.pop(); } /** * Write a field header containing the field id and field type. If the difference between the * current field id and the last one is small (< 15), then the field id will be encoded in the * 4 MSB as a delta. Otherwise, the field id will follow the type header as a zigzag varint. */ @Override public void writeFieldBegin(TField field) throws TException { if (field.type == TType.BOOL) { // we want to possibly include the value, so we'll wait. booleanField_ = field; } else { writeFieldBeginInternal(field, (byte) -1); } } /** * The workhorse of writeFieldBegin. It has the option of doing a 'type override' of the type * header. This is used specifically in the boolean field case. */ private void writeFieldBeginInternal(TField field, byte typeOverride) throws TException { // short lastField = lastField_.pop(); // if there's a type override, use that. byte typeToWrite = typeOverride == -1 ? getCompactType(field.type) : typeOverride; // check if we can use delta encoding for the field id if (field.id > lastFieldId_ && field.id - lastFieldId_ <= 15) { // write them together writeByteDirect((field.id - lastFieldId_) << 4 | typeToWrite); } else { // write them separate writeByteDirect(typeToWrite); writeI16(field.id); } lastFieldId_ = field.id; // lastField_.push(field.id); } /** Write the STOP symbol so we know there are no more fields in this struct. */ @Override public void writeFieldStop() throws TException { writeByteDirect(TType.STOP); } /** * Write a map header. If the map is empty, omit the key and value type headers, as we don't need * any additional information to skip it. */ @Override public void writeMapBegin(TMap map) throws TException { if (map.size == 0) { writeByteDirect(0); } else { writeVarint32(map.size); writeByteDirect(getCompactType(map.keyType) << 4 | getCompactType(map.valueType)); } } /** Write a list header. */ @Override public void writeListBegin(TList list) throws TException { writeCollectionBegin(list.elemType, list.size); } /** Write a set header. */ @Override public void writeSetBegin(TSet set) throws TException { writeCollectionBegin(set.elemType, set.size); } /** * Write a boolean value. Potentially, this could be a boolean field, in which case the field * header info isn't written yet. If so, decide what the right type header is for the value and * then write the field header. Otherwise, write a single byte. */ @Override public void writeBool(boolean b) throws TException { if (booleanField_ != null) { // we haven't written the field header yet writeFieldBeginInternal(booleanField_, b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE); booleanField_ = null; } else { // we're not part of a field, so just write the value. writeByteDirect(b ? Types.BOOLEAN_TRUE : Types.BOOLEAN_FALSE); } } /** Write a byte. Nothing to see here! */ @Override public void writeByte(byte b) throws TException { writeByteDirect(b); } /** Write an I16 as a zigzag varint. */ @Override public void writeI16(short i16) throws TException { writeVarint32(intToZigZag(i16)); } /** Write an i32 as a zigzag varint. */ @Override public void writeI32(int i32) throws TException { writeVarint32(intToZigZag(i32)); } /** Write an i64 as a zigzag varint. */ @Override public void writeI64(long i64) throws TException { writeVarint64(longToZigzag(i64)); } /** Write a double to the wire as 8 bytes. */ @Override public void writeDouble(double dub) throws TException { fixedLongToBytes(Double.doubleToLongBits(dub), temp, 0); trans_.write(temp, 0, 8); } @Override public void writeUuid(UUID uuid) throws TException { fixedLongToBytes(uuid.getLeastSignificantBits(), temp, 0); fixedLongToBytes(uuid.getMostSignificantBits(), temp, 8); trans_.write(temp, 0, 16); } /** Write a string to the wire with a varint size preceding. */ @Override public void writeString(String str) throws TException { byte[] bytes = str.getBytes(StandardCharsets.UTF_8); writeVarint32(bytes.length); trans_.write(bytes, 0, bytes.length); } /** Write a byte array, using a varint for the size. */ @Override public void writeBinary(ByteBuffer bin) throws TException { ByteBuffer bb = bin.asReadOnlyBuffer(); writeVarint32(bb.remaining()); trans_.write(bb); } // // These methods are called by structs, but don't actually have any wire // output or purpose. // @Override public void writeMessageEnd() throws TException {} @Override public void writeMapEnd() throws TException {} @Override public void writeListEnd() throws TException {} @Override public void writeSetEnd() throws TException {} @Override public void writeFieldEnd() throws TException {} // // Internal writing methods // /** * Abstract method for writing the start of lists and sets. List and sets on the wire differ only * by the type indicator. */ protected void writeCollectionBegin(byte elemType, int size) throws TException { if (size <= 14) { writeByteDirect(size << 4 | getCompactType(elemType)); } else { writeByteDirect(0xf0 | getCompactType(elemType)); writeVarint32(size); } } /** * Write an i32 as a varint. Results in 1-5 bytes on the wire. TODO: make a permanent buffer like * writeVarint64? */ private void writeVarint32(int n) throws TException { int idx = 0; while (true) { if ((n & ~0x7F) == 0) { temp[idx++] = (byte) n; // writeByteDirect((byte)n); break; // return; } else { temp[idx++] = (byte) ((n & 0x7F) | 0x80); // writeByteDirect((byte)((n & 0x7F) | 0x80)); n >>>= 7; } } trans_.write(temp, 0, idx); } /** Write an i64 as a varint. Results in 1-10 bytes on the wire. */ private void writeVarint64(long n) throws TException { int idx = 0; while (true) { if ((n & ~0x7FL) == 0) { temp[idx++] = (byte) n; break; } else { temp[idx++] = ((byte) ((n & 0x7F) | 0x80)); n >>>= 7; } } trans_.write(temp, 0, idx); } /** * Convert l into a zigzag long. This allows negative numbers to be represented compactly as a * varint. */ private long longToZigzag(long l) { return (l << 1) ^ (l >> 63); } /** * Convert n into a zigzag int. This allows negative numbers to be represented compactly as a * varint. */ private int intToZigZag(int n) { return (n << 1) ^ (n >> 31); } /** Convert a long into little-endian bytes in buf starting at off and going until off+7. */ private void fixedLongToBytes(long n, byte[] buf, int off) { buf[off + 0] = (byte) (n & 0xff); buf[off + 1] = (byte) ((n >> 8) & 0xff); buf[off + 2] = (byte) ((n >> 16) & 0xff); buf[off + 3] = (byte) ((n >> 24) & 0xff); buf[off + 4] = (byte) ((n >> 32) & 0xff); buf[off + 5] = (byte) ((n >> 40) & 0xff); buf[off + 6] = (byte) ((n >> 48) & 0xff); buf[off + 7] = (byte) ((n >> 56) & 0xff); } /** * Writes a byte without any possibility of all that field header nonsense. Used internally by * other writing methods that know they need to write a byte. */ private void writeByteDirect(byte b) throws TException { temp[0] = b; trans_.write(temp, 0, 1); } /** Writes a byte without any possibility of all that field header nonsense. */ private void writeByteDirect(int n) throws TException { writeByteDirect((byte) n); } // // Reading methods. // /** Read a message header. */ @Override public TMessage readMessageBegin() throws TException { byte protocolId = readByte(); if (protocolId != PROTOCOL_ID) { throw new TProtocolException( "Expected protocol id " + Integer.toHexString(PROTOCOL_ID) + " but got " + Integer.toHexString(protocolId)); } byte versionAndType = readByte(); byte version = (byte) (versionAndType & VERSION_MASK); if (version != VERSION) { throw new TProtocolException("Expected version " + VERSION + " but got " + version); } byte type = (byte) ((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); int seqid = readVarint32(); String messageName = readString(); return new TMessage(messageName, type, seqid); } /** * Read a struct begin. There's nothing on the wire for this, but it is our opportunity to push a * new struct begin marker onto the field stack. */ @Override public TStruct readStructBegin() throws TException { lastField_.push(lastFieldId_); lastFieldId_ = 0; return ANONYMOUS_STRUCT; } /** * Doesn't actually consume any wire data, just removes the last field for this struct from the * field stack. */ @Override public void readStructEnd() throws TException { // consume the last field we read off the wire. lastFieldId_ = lastField_.pop(); } /** Read a field header off the wire. */ @Override public TField readFieldBegin() throws TException { byte type = readByte(); // if it's a stop, then we can return immediately, as the struct is over. if (type == TType.STOP) { return TSTOP; } short fieldId; // mask off the 4 MSB of the type header. it could contain a field id delta. short modifier = (short) ((type & 0xf0) >> 4); if (modifier == 0) { // not a delta. look ahead for the zigzag varint field id. fieldId = readI16(); } else { // has a delta. add the delta to the last read field id. fieldId = (short) (lastFieldId_ + modifier); } TField field = new TField("", getTType((byte) (type & 0x0f)), fieldId); // if this happens to be a boolean field, the value is encoded in the type if (isBoolType(type)) { // save the boolean value in a special instance variable. boolValue_ = (byte) (type & 0x0f) == Types.BOOLEAN_TRUE ? Boolean.TRUE : Boolean.FALSE; } // push the new field onto the field stack so we can keep the deltas going. lastFieldId_ = field.id; return field; } /** * Read a map header off the wire. If the size is zero, skip reading the key and value type. This * means that 0-length maps will yield TMaps without the "correct" types. */ @Override public TMap readMapBegin() throws TException { int size = readVarint32(); checkContainerReadLength(size); byte keyAndValueType = size == 0 ? 0 : readByte(); TMap map = new TMap( getTType((byte) (keyAndValueType >> 4)), getTType((byte) (keyAndValueType & 0xf)), size); checkReadBytesAvailable(map); return map; } /** * Read a list header off the wire. If the list size is 0-14, the size will be packed into the * element type header. If it's a longer list, the 4 MSB of the element type header will be 0xF, * and a varint will follow with the true size. */ @Override public TList readListBegin() throws TException { byte size_and_type = readByte(); int size = (size_and_type >> 4) & 0x0f; if (size == 15) { size = readVarint32(); } checkContainerReadLength(size); TList list = new TList(getTType(size_and_type), size); checkReadBytesAvailable(list); return list; } /** * Read a set header off the wire. If the set size is 0-14, the size will be packed into the * element type header. If it's a longer set, the 4 MSB of the element type header will be 0xF, * and a varint will follow with the true size. */ @Override public TSet readSetBegin() throws TException { return new TSet(readListBegin()); } /** * Read a boolean off the wire. If this is a boolean field, the value should already have been * read during readFieldBegin, so we'll just consume the pre-stored value. Otherwise, read a byte. */ @Override public boolean readBool() throws TException { if (boolValue_ != null) { boolean result = boolValue_; boolValue_ = null; return result; } return readByte() == Types.BOOLEAN_TRUE; } /** Read a single byte off the wire. Nothing interesting here. */ @Override public byte readByte() throws TException { byte b; if (trans_.getBytesRemainingInBuffer() > 0) { b = trans_.getBuffer()[trans_.getBufferPosition()]; trans_.consumeBuffer(1); } else { trans_.readAll(temp, 0, 1); b = temp[0]; } return b; } /** Read an i16 from the wire as a zigzag varint. */ @Override public short readI16() throws TException { return (short) zigzagToInt(readVarint32()); } /** Read an i32 from the wire as a zigzag varint. */ @Override public int readI32() throws TException { return zigzagToInt(readVarint32()); } /** Read an i64 from the wire as a zigzag varint. */ @Override public long readI64() throws TException { return zigzagToLong(readVarint64()); } /** No magic here - just read a double off the wire. */ @Override public double readDouble() throws TException { trans_.readAll(temp, 0, 8); return Double.longBitsToDouble(bytesToLong(temp)); } @Override public UUID readUuid() throws TException { trans_.readAll(temp, 0, 16); long mostSigBits = bytesToLong(temp, 8); long leastSigBits = bytesToLong(temp, 0); return new UUID(mostSigBits, leastSigBits); } /** Reads a byte[] (via readBinary), and then UTF-8 decodes it. */ @Override public String readString() throws TException { int length = readVarint32(); checkStringReadLength(length); if (length == 0) { return ""; } final String str; if (trans_.getBytesRemainingInBuffer() >= length) { str = new String( trans_.getBuffer(), trans_.getBufferPosition(), length, StandardCharsets.UTF_8); trans_.consumeBuffer(length); } else { str = new String(readBinary(length), StandardCharsets.UTF_8); } return str; } /** Read a ByteBuffer from the wire. */ @Override public ByteBuffer readBinary() throws TException { int length = readVarint32(); if (length == 0) { return EMPTY_BUFFER; } getTransport().checkReadBytesAvailable(length); if (trans_.getBytesRemainingInBuffer() >= length) { ByteBuffer bb = ByteBuffer.wrap(trans_.getBuffer(), trans_.getBufferPosition(), length); trans_.consumeBuffer(length); return bb; } byte[] buf = new byte[length]; trans_.readAll(buf, 0, length); return ByteBuffer.wrap(buf); } /** Read a byte[] of a known length from the wire. */ private byte[] readBinary(int length) throws TException { if (length == 0) return EMPTY_BYTES; byte[] buf = new byte[length]; trans_.readAll(buf, 0, length); return buf; } private void checkStringReadLength(int length) throws TException { if (length < 0) { throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, "Negative length: " + length); } getTransport().checkReadBytesAvailable(length); if (stringLengthLimit_ != NO_LENGTH_LIMIT && length > stringLengthLimit_) { throw new TProtocolException( TProtocolException.SIZE_LIMIT, "Length exceeded max allowed: " + length); } } private void checkContainerReadLength(int length) throws TProtocolException { if (length < 0) { throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, "Negative length: " + length); } if (containerLengthLimit_ != NO_LENGTH_LIMIT && length > containerLengthLimit_) { throw new TProtocolException( TProtocolException.SIZE_LIMIT, "Length exceeded max allowed: " + length); } } // // These methods are here for the struct to call, but don't have any wire // encoding. // @Override public void readMessageEnd() throws TException {} @Override public void readFieldEnd() throws TException {} @Override public void readMapEnd() throws TException {} @Override public void readListEnd() throws TException {} @Override public void readSetEnd() throws TException {} // // Internal reading methods // /** * Read an i32 from the wire as a varint. The MSB of each byte is set if there is another byte to * follow. This can read up to 5 bytes. */ private int readVarint32() throws TException { int result = 0; int shift = 0; if (trans_.getBytesRemainingInBuffer() >= 5) { byte[] buf = trans_.getBuffer(); int pos = trans_.getBufferPosition(); int off = 0; while (true) { byte b = buf[pos + off]; result |= (b & 0x7f) << shift; if ((b & 0x80) != 0x80) break; shift += 7; off++; } trans_.consumeBuffer(off + 1); } else { while (true) { byte b = readByte(); result |= (b & 0x7f) << shift; if ((b & 0x80) != 0x80) break; shift += 7; } } return result; } /** * Read an i64 from the wire as a proper varint. The MSB of each byte is set if there is another * byte to follow. This can read up to 10 bytes. */ private long readVarint64() throws TException { int shift = 0; long result = 0; if (trans_.getBytesRemainingInBuffer() >= 10) { byte[] buf = trans_.getBuffer(); int pos = trans_.getBufferPosition(); int off = 0; while (true) { byte b = buf[pos + off]; result |= (long) (b & 0x7f) << shift; if ((b & 0x80) != 0x80) break; shift += 7; off++; } trans_.consumeBuffer(off + 1); } else { while (true) { byte b = readByte(); result |= (long) (b & 0x7f) << shift; if ((b & 0x80) != 0x80) break; shift += 7; } } return result; } // // encoding helpers // /** Convert from zigzag int to int. */ private int zigzagToInt(int n) { return (n >>> 1) ^ -(n & 1); } /** Convert from zigzag long to long. */ private long zigzagToLong(long n) { return (n >>> 1) ^ -(n & 1); } /** * Note that it's important that the mask bytes are long literals, otherwise they'll default to * ints, and when you shift an int left 56 bits, you just get a messed up int. */ private long bytesToLong(byte[] bytes) { return bytesToLong(bytes, 0); } private long bytesToLong(byte[] bytes, int offset) { return ((bytes[offset + 7] & 0xffL) << 56) | ((bytes[offset + 6] & 0xffL) << 48) | ((bytes[offset + 5] & 0xffL) << 40) | ((bytes[offset + 4] & 0xffL) << 32) | ((bytes[offset + 3] & 0xffL) << 24) | ((bytes[offset + 2] & 0xffL) << 16) | ((bytes[offset + 1] & 0xffL) << 8) | ((bytes[offset + 0] & 0xffL)); } // // type testing and converting // private boolean isBoolType(byte b) { int lowerNibble = b & 0x0f; return lowerNibble == Types.BOOLEAN_TRUE || lowerNibble == Types.BOOLEAN_FALSE; } /** Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. */ private byte getTType(byte type) throws TProtocolException { switch ((byte) (type & 0x0f)) { case TType.STOP: return TType.STOP; case Types.BOOLEAN_FALSE: case Types.BOOLEAN_TRUE: return TType.BOOL; case Types.BYTE: return TType.BYTE; case Types.I16: return TType.I16; case Types.I32: return TType.I32; case Types.I64: return TType.I64; case Types.UUID: return TType.UUID; case Types.DOUBLE: return TType.DOUBLE; case Types.BINARY: return TType.STRING; case Types.LIST: return TType.LIST; case Types.SET: return TType.SET; case Types.MAP: return TType.MAP; case Types.STRUCT: return TType.STRUCT; default: throw new TProtocolException("don't know what type: " + (byte) (type & 0x0f)); } } /** Given a TType value, find the appropriate TCompactProtocol.Types constant. */ private byte getCompactType(byte ttype) { return ttypeToCompactType[ttype]; } /** Return the minimum number of bytes a type will consume on the wire */ @Override public int getMinSerializedSize(byte type) throws TTransportException { switch (type) { case 0: return 0; // Stop case 1: return 0; // Void case 2: return 1; // Bool sizeof(byte) case 3: return 1; // Byte sizeof(byte) case 4: return 8; // Double sizeof(double) case 6: return 1; // I16 sizeof(byte) case 8: return 1; // I32 sizeof(byte) case 10: return 1; // I64 sizeof(byte) case 11: return 1; // string length sizeof(byte) case 12: return 0; // empty struct case 13: return 1; // element count Map sizeof(byte) case 14: return 1; // element count Set sizeof(byte) case 15: return 1; // element count List sizeof(byte) default: throw new TTransportException(TTransportException.UNKNOWN, "unrecognized type code"); } } // ----------------------------------------------------------------- // Additional methods to improve performance. @Override protected void skipBinary() throws TException { int size = intToZigZag(readI32()); this.skipBytes(size); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TField.java0000644000000000000000000000340514303740367026416 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** * Helper class that encapsulates field metadata. * *

Two fields are considered equal if they have the same type and id. */ public class TField { public TField() { this("", TType.STOP, (short) 0); } public TField(String n, byte t, short i) { name = n; type = t; id = i; } public final String name; public final byte type; public final short id; public String toString() { return ""; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; result = prime * result + type; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TField otherField = (TField) obj; return type == otherField.type && id == otherField.id; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TProtocolDecorator.java0000644000000000000000000001522514370300523031030 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.nio.ByteBuffer; import java.util.UUID; import org.apache.thrift.TException; /** * TProtocolDecorator forwards all requests to an enclosed TProtocol * instance, providing a way to author concise concrete decorator subclasses. While it has no * abstract methods, it is marked abstract as a reminder that by itself, it does not modify the * behaviour of the enclosed TProtocol. * *

See p.175 of Design Patterns (by Gamma et al.) * * @see org.apache.thrift.protocol.TMultiplexedProtocol */ public abstract class TProtocolDecorator extends TProtocol { private final TProtocol concreteProtocol; /** * Encloses the specified protocol. * * @param protocol All operations will be forward to this protocol. Must be non-null. */ public TProtocolDecorator(TProtocol protocol) { super(protocol.getTransport()); concreteProtocol = protocol; } @Override public void writeMessageBegin(TMessage tMessage) throws TException { concreteProtocol.writeMessageBegin(tMessage); } @Override public void writeMessageEnd() throws TException { concreteProtocol.writeMessageEnd(); } @Override public void writeStructBegin(TStruct tStruct) throws TException { concreteProtocol.writeStructBegin(tStruct); } @Override public UUID readUuid() throws TException { return concreteProtocol.readUuid(); } @Override public void writeUuid(UUID uuid) throws TException { concreteProtocol.writeUuid(uuid); } @Override public void writeStructEnd() throws TException { concreteProtocol.writeStructEnd(); } @Override public void writeFieldBegin(TField tField) throws TException { concreteProtocol.writeFieldBegin(tField); } @Override public void writeFieldEnd() throws TException { concreteProtocol.writeFieldEnd(); } @Override public void writeFieldStop() throws TException { concreteProtocol.writeFieldStop(); } @Override public void writeMapBegin(TMap tMap) throws TException { concreteProtocol.writeMapBegin(tMap); } @Override public void writeMapEnd() throws TException { concreteProtocol.writeMapEnd(); } @Override public void writeListBegin(TList tList) throws TException { concreteProtocol.writeListBegin(tList); } @Override public void writeListEnd() throws TException { concreteProtocol.writeListEnd(); } @Override public void writeSetBegin(TSet tSet) throws TException { concreteProtocol.writeSetBegin(tSet); } @Override public void writeSetEnd() throws TException { concreteProtocol.writeSetEnd(); } @Override public void writeBool(boolean b) throws TException { concreteProtocol.writeBool(b); } @Override public void writeByte(byte b) throws TException { concreteProtocol.writeByte(b); } @Override public void writeI16(short i) throws TException { concreteProtocol.writeI16(i); } @Override public void writeI32(int i) throws TException { concreteProtocol.writeI32(i); } @Override public void writeI64(long l) throws TException { concreteProtocol.writeI64(l); } @Override public void writeDouble(double v) throws TException { concreteProtocol.writeDouble(v); } @Override public void writeString(String s) throws TException { concreteProtocol.writeString(s); } @Override public void writeBinary(ByteBuffer buf) throws TException { concreteProtocol.writeBinary(buf); } @Override public TMessage readMessageBegin() throws TException { return concreteProtocol.readMessageBegin(); } @Override public void readMessageEnd() throws TException { concreteProtocol.readMessageEnd(); } @Override public TStruct readStructBegin() throws TException { return concreteProtocol.readStructBegin(); } @Override public void readStructEnd() throws TException { concreteProtocol.readStructEnd(); } @Override public TField readFieldBegin() throws TException { return concreteProtocol.readFieldBegin(); } @Override public void readFieldEnd() throws TException { concreteProtocol.readFieldEnd(); } @Override public TMap readMapBegin() throws TException { return concreteProtocol.readMapBegin(); } @Override public void readMapEnd() throws TException { concreteProtocol.readMapEnd(); } @Override public TList readListBegin() throws TException { return concreteProtocol.readListBegin(); } @Override public void readListEnd() throws TException { concreteProtocol.readListEnd(); } @Override public TSet readSetBegin() throws TException { return concreteProtocol.readSetBegin(); } @Override public void readSetEnd() throws TException { concreteProtocol.readSetEnd(); } @Override public boolean readBool() throws TException { return concreteProtocol.readBool(); } @Override public byte readByte() throws TException { return concreteProtocol.readByte(); } @Override public short readI16() throws TException { return concreteProtocol.readI16(); } @Override public int readI32() throws TException { return concreteProtocol.readI32(); } @Override public long readI64() throws TException { return concreteProtocol.readI64(); } @Override public double readDouble() throws TException { return concreteProtocol.readDouble(); } @Override public String readString() throws TException { return concreteProtocol.readString(); } @Override public ByteBuffer readBinary() throws TException { return concreteProtocol.readBinary(); } /** * @param type Returns the minimum amount of bytes needed to store the smallest possible instance * of TType. * @return size * @throws TException if underlying protocol throws */ @Override public int getMinSerializedSize(byte type) throws TException { return concreteProtocol.getMinSerializedSize(type); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TWriteProtocol.java0000644000000000000000000000232214370300523030172 0ustar00rootroot00000000000000package org.apache.thrift.protocol; import java.nio.ByteBuffer; import java.util.UUID; import org.apache.thrift.TException; public interface TWriteProtocol { void writeMessageBegin(TMessage message) throws TException; void writeMessageEnd() throws TException; void writeStructBegin(TStruct struct) throws TException; void writeStructEnd() throws TException; void writeFieldBegin(TField field) throws TException; void writeFieldEnd() throws TException; void writeFieldStop() throws TException; void writeMapBegin(TMap map) throws TException; void writeMapEnd() throws TException; void writeListBegin(TList list) throws TException; void writeListEnd() throws TException; void writeSetBegin(TSet set) throws TException; void writeSetEnd() throws TException; void writeBool(boolean b) throws TException; void writeByte(byte b) throws TException; void writeI16(short i16) throws TException; void writeI32(int i32) throws TException; void writeI64(long i64) throws TException; void writeUuid(UUID uuid) throws TException; void writeDouble(double dub) throws TException; void writeString(String str) throws TException; void writeBinary(ByteBuffer buf) throws TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TJSONProtocol.java0000644000000000000000000006746014370300523027667 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Stack; import java.util.UUID; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; /** * JSON protocol implementation for thrift. * *

This is a full-featured protocol supporting write and read. * *

Please see the C++ class header for a detailed description of the protocol's wire format. */ public class TJSONProtocol extends TProtocol { /** Factory for JSON protocol objects */ public static class Factory implements TProtocolFactory { protected boolean fieldNamesAsString_ = false; public Factory() {} public Factory(boolean fieldNamesAsString) { fieldNamesAsString_ = fieldNamesAsString; } public TProtocol getProtocol(TTransport trans) { return new TJSONProtocol(trans, fieldNamesAsString_); } } private static final byte[] COMMA = new byte[] {','}; private static final byte[] COLON = new byte[] {':'}; private static final byte[] LBRACE = new byte[] {'{'}; private static final byte[] RBRACE = new byte[] {'}'}; private static final byte[] LBRACKET = new byte[] {'['}; private static final byte[] RBRACKET = new byte[] {']'}; private static final byte[] QUOTE = new byte[] {'"'}; private static final byte[] BACKSLASH = new byte[] {'\\'}; private static final byte[] ESCSEQ = new byte[] {'\\', 'u', '0', '0'}; private static final long VERSION = 1; private static final byte[] JSON_CHAR_TABLE = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, // 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 1, 1, '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 }; private static final String ESCAPE_CHARS = "\"\\/bfnrt"; private static final byte[] ESCAPE_CHAR_VALS = { '"', '\\', '/', '\b', '\f', '\n', '\r', '\t', }; private static final int DEF_STRING_SIZE = 16; private static final byte[] NAME_BOOL = new byte[] {'t', 'f'}; private static final byte[] NAME_BYTE = new byte[] {'i', '8'}; private static final byte[] NAME_I16 = new byte[] {'i', '1', '6'}; private static final byte[] NAME_I32 = new byte[] {'i', '3', '2'}; private static final byte[] NAME_I64 = new byte[] {'i', '6', '4'}; private static final byte[] NAME_UUID = new byte[] {'u', 'i', 'd'}; private static final byte[] NAME_DOUBLE = new byte[] {'d', 'b', 'l'}; private static final byte[] NAME_STRUCT = new byte[] {'r', 'e', 'c'}; private static final byte[] NAME_STRING = new byte[] {'s', 't', 'r'}; private static final byte[] NAME_MAP = new byte[] {'m', 'a', 'p'}; private static final byte[] NAME_LIST = new byte[] {'l', 's', 't'}; private static final byte[] NAME_SET = new byte[] {'s', 'e', 't'}; private static final TStruct ANONYMOUS_STRUCT = new TStruct(); private static byte[] getTypeNameForTypeID(byte typeID) throws TException { switch (typeID) { case TType.BOOL: return NAME_BOOL; case TType.BYTE: return NAME_BYTE; case TType.I16: return NAME_I16; case TType.I32: return NAME_I32; case TType.I64: return NAME_I64; case TType.UUID: return NAME_UUID; case TType.DOUBLE: return NAME_DOUBLE; case TType.STRING: return NAME_STRING; case TType.STRUCT: return NAME_STRUCT; case TType.MAP: return NAME_MAP; case TType.SET: return NAME_SET; case TType.LIST: return NAME_LIST; default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized type"); } } private static byte getTypeIDForTypeName(byte[] name) throws TException { byte result = TType.STOP; if (name.length > 1) { switch (name[0]) { case 'd': result = TType.DOUBLE; break; case 'i': switch (name[1]) { case '8': result = TType.BYTE; break; case '1': result = TType.I16; break; case '3': result = TType.I32; break; case '6': result = TType.I64; break; } break; case 'l': result = TType.LIST; break; case 'm': result = TType.MAP; break; case 'r': result = TType.STRUCT; break; case 's': if (name[1] == 't') { result = TType.STRING; } else if (name[1] == 'e') { result = TType.SET; } break; case 'u': result = TType.UUID; break; case 't': result = TType.BOOL; break; } } if (result == TType.STOP) { throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized type"); } return result; } // Base class for tracking JSON contexts that may require inserting/reading // additional JSON syntax characters // This base context does nothing. protected static class JSONBaseContext { protected void write() throws TException {} protected void read() throws TException {} protected boolean escapeNum() { return false; } } // Context for JSON lists. Will insert/read commas before each item except // for the first one protected class JSONListContext extends JSONBaseContext { private boolean first_ = true; @Override protected void write() throws TException { if (first_) { first_ = false; } else { trans_.write(COMMA); } } @Override protected void read() throws TException { if (first_) { first_ = false; } else { readJSONSyntaxChar(COMMA); } } } // Context for JSON records. Will insert/read colons before the value portion // of each record pair, and commas before each key except the first. In // addition, will indicate that numbers in the key position need to be // escaped in quotes (since JSON keys must be strings). protected class JSONPairContext extends JSONBaseContext { private boolean first_ = true; private boolean colon_ = true; @Override protected void write() throws TException { if (first_) { first_ = false; colon_ = true; } else { trans_.write(colon_ ? COLON : COMMA); colon_ = !colon_; } } @Override protected void read() throws TException { if (first_) { first_ = false; colon_ = true; } else { readJSONSyntaxChar(colon_ ? COLON : COMMA); colon_ = !colon_; } } @Override protected boolean escapeNum() { return colon_; } } // Holds up to one byte from the transport protected class LookaheadReader { private boolean hasData_; private final byte[] data_ = new byte[1]; // Return and consume the next byte to be read, either taking it from the // data buffer if present or getting it from the transport otherwise. protected byte read() throws TException { if (hasData_) { hasData_ = false; } else { trans_.readAll(data_, 0, 1); } return data_[0]; } // Return the next byte to be read without consuming, filling the data // buffer if it has not been filled already. protected byte peek() throws TException { if (!hasData_) { trans_.readAll(data_, 0, 1); } hasData_ = true; return data_[0]; } } // Stack of nested contexts that we may be in private final Stack contextStack_ = new Stack<>(); // Current context that we are in private JSONBaseContext context_ = new JSONBaseContext(); // Reader that manages a 1-byte buffer private LookaheadReader reader_ = new LookaheadReader(); // Write out the TField names as a string instead of the default integer value private boolean fieldNamesAsString_ = false; // Push a new JSON context onto the stack. private void pushContext(JSONBaseContext c) { contextStack_.push(context_); context_ = c; } // Pop the last JSON context off the stack private void popContext() { context_ = contextStack_.pop(); } // Reset the context stack to its initial state private void resetContext() { while (!contextStack_.isEmpty()) { popContext(); } } /** Constructor */ public TJSONProtocol(TTransport trans) { super(trans); } public TJSONProtocol(TTransport trans, boolean fieldNamesAsString) { super(trans); fieldNamesAsString_ = fieldNamesAsString; } @Override public void reset() { contextStack_.clear(); context_ = new JSONBaseContext(); reader_ = new LookaheadReader(); } // Temporary buffer used by several methods private final byte[] tmpbuf_ = new byte[4]; // Read a byte that must match b[0]; otherwise an exception is thrown. // Marked protected to avoid synthetic accessor in JSONListContext.read // and JSONPairContext.read protected void readJSONSyntaxChar(byte[] b) throws TException { byte ch = reader_.read(); if (ch != b[0]) { throw new TProtocolException( TProtocolException.INVALID_DATA, "Unexpected character:" + (char) ch); } } // Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its // corresponding hex value private static byte hexVal(byte ch) throws TException { if ((ch >= '0') && (ch <= '9')) { return (byte) ((char) ch - '0'); } else if ((ch >= 'a') && (ch <= 'f')) { return (byte) ((char) ch - 'a' + 10); } else { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); } } // Convert a byte containing a hex value to its corresponding hex character private static byte hexChar(byte val) { val &= 0x0F; if (val < 10) { return (byte) ((char) val + '0'); } else { return (byte) ((char) (val - 10) + 'a'); } } // Write the bytes in array buf as a JSON characters, escaping as needed private void writeJSONString(byte[] b) throws TException { context_.write(); trans_.write(QUOTE); int len = b.length; for (int i = 0; i < len; i++) { if ((b[i] & 0x00FF) >= 0x30) { if (b[i] == BACKSLASH[0]) { trans_.write(BACKSLASH); trans_.write(BACKSLASH); } else { trans_.write(b, i, 1); } } else { tmpbuf_[0] = JSON_CHAR_TABLE[b[i]]; if (tmpbuf_[0] == 1) { trans_.write(b, i, 1); } else if (tmpbuf_[0] > 1) { trans_.write(BACKSLASH); trans_.write(tmpbuf_, 0, 1); } else { trans_.write(ESCSEQ); tmpbuf_[0] = hexChar((byte) (b[i] >> 4)); tmpbuf_[1] = hexChar(b[i]); trans_.write(tmpbuf_, 0, 2); } } } trans_.write(QUOTE); } // Write out number as a JSON value. If the context dictates so, it will be // wrapped in quotes to output as a JSON string. private void writeJSONInteger(long num) throws TException { context_.write(); String str = Long.toString(num); boolean escapeNum = context_.escapeNum(); if (escapeNum) { trans_.write(QUOTE); } byte[] buf = str.getBytes(StandardCharsets.UTF_8); trans_.write(buf); if (escapeNum) { trans_.write(QUOTE); } } // Write out a double as a JSON value. If it is NaN or infinity or if the // context dictates escaping, write out as JSON string. private void writeJSONDouble(double num) throws TException { context_.write(); String str = Double.toString(num); boolean special = false; switch (str.charAt(0)) { case 'N': // NaN case 'I': // Infinity special = true; break; case '-': if (str.charAt(1) == 'I') { // -Infinity special = true; } break; default: break; } boolean escapeNum = special || context_.escapeNum(); if (escapeNum) { trans_.write(QUOTE); } byte[] b = str.getBytes(StandardCharsets.UTF_8); trans_.write(b, 0, b.length); if (escapeNum) { trans_.write(QUOTE); } } // Write out contents of byte array b as a JSON string with base-64 encoded // data private void writeJSONBase64(byte[] b, int offset, int length) throws TException { context_.write(); trans_.write(QUOTE); int len = length; int off = offset; while (len >= 3) { // Encode 3 bytes at a time TBase64Utils.encode(b, off, 3, tmpbuf_, 0); trans_.write(tmpbuf_, 0, 4); off += 3; len -= 3; } if (len > 0) { // Encode remainder TBase64Utils.encode(b, off, len, tmpbuf_, 0); trans_.write(tmpbuf_, 0, len + 1); } trans_.write(QUOTE); } private void writeJSONObjectStart() throws TException { context_.write(); trans_.write(LBRACE); pushContext(new JSONPairContext()); } private void writeJSONObjectEnd() throws TException { popContext(); trans_.write(RBRACE); } private void writeJSONArrayStart() throws TException { context_.write(); trans_.write(LBRACKET); pushContext(new JSONListContext()); } private void writeJSONArrayEnd() throws TException { popContext(); trans_.write(RBRACKET); } @Override public void writeMessageBegin(TMessage message) throws TException { resetContext(); // THRIFT-3743 writeJSONArrayStart(); writeJSONInteger(VERSION); byte[] b = message.name.getBytes(StandardCharsets.UTF_8); writeJSONString(b); writeJSONInteger(message.type); writeJSONInteger(message.seqid); } @Override public void writeMessageEnd() throws TException { writeJSONArrayEnd(); } @Override public void writeStructBegin(TStruct struct) throws TException { writeJSONObjectStart(); } @Override public void writeStructEnd() throws TException { writeJSONObjectEnd(); } @Override public void writeFieldBegin(TField field) throws TException { if (fieldNamesAsString_) { writeString(field.name); } else { writeJSONInteger(field.id); } writeJSONObjectStart(); writeJSONString(getTypeNameForTypeID(field.type)); } @Override public void writeFieldEnd() throws TException { writeJSONObjectEnd(); } @Override public void writeFieldStop() {} @Override public void writeMapBegin(TMap map) throws TException { writeJSONArrayStart(); writeJSONString(getTypeNameForTypeID(map.keyType)); writeJSONString(getTypeNameForTypeID(map.valueType)); writeJSONInteger(map.size); writeJSONObjectStart(); } @Override public void writeMapEnd() throws TException { writeJSONObjectEnd(); writeJSONArrayEnd(); } @Override public void writeListBegin(TList list) throws TException { writeJSONArrayStart(); writeJSONString(getTypeNameForTypeID(list.elemType)); writeJSONInteger(list.size); } @Override public void writeListEnd() throws TException { writeJSONArrayEnd(); } @Override public void writeSetBegin(TSet set) throws TException { writeJSONArrayStart(); writeJSONString(getTypeNameForTypeID(set.elemType)); writeJSONInteger(set.size); } @Override public void writeSetEnd() throws TException { writeJSONArrayEnd(); } @Override public void writeBool(boolean b) throws TException { writeJSONInteger(b ? (long) 1 : (long) 0); } @Override public void writeByte(byte b) throws TException { writeJSONInteger(b); } @Override public void writeI16(short i16) throws TException { writeJSONInteger(i16); } @Override public void writeI32(int i32) throws TException { writeJSONInteger(i32); } @Override public void writeI64(long i64) throws TException { writeJSONInteger(i64); } @Override public void writeUuid(UUID uuid) throws TException { writeJSONString(uuid.toString().getBytes(StandardCharsets.UTF_8)); } @Override public void writeDouble(double dub) throws TException { writeJSONDouble(dub); } @Override public void writeString(String str) throws TException { byte[] b = str.getBytes(StandardCharsets.UTF_8); writeJSONString(b); } @Override public void writeBinary(ByteBuffer bin) throws TException { writeJSONBase64( bin.array(), bin.position() + bin.arrayOffset(), bin.limit() - bin.position() - bin.arrayOffset()); } /** Reading methods. */ // Read in a JSON string, unescaping as appropriate.. Skip reading from the // context if skipContext is true. private TByteArrayOutputStream readJSONString(boolean skipContext) throws TException { TByteArrayOutputStream arr = new TByteArrayOutputStream(DEF_STRING_SIZE); ArrayList codeunits = new ArrayList(); if (!skipContext) { context_.read(); } readJSONSyntaxChar(QUOTE); while (true) { byte ch = reader_.read(); if (ch == QUOTE[0]) { break; } if (ch == ESCSEQ[0]) { ch = reader_.read(); if (ch == ESCSEQ[1]) { trans_.readAll(tmpbuf_, 0, 4); short cu = (short) (((short) hexVal(tmpbuf_[0]) << 12) + ((short) hexVal(tmpbuf_[1]) << 8) + ((short) hexVal(tmpbuf_[2]) << 4) + (short) hexVal(tmpbuf_[3])); try { if (Character.isHighSurrogate((char) cu)) { if (codeunits.size() > 0) { throw new TProtocolException( TProtocolException.INVALID_DATA, "Expected low surrogate char"); } codeunits.add((char) cu); } else if (Character.isLowSurrogate((char) cu)) { if (codeunits.size() == 0) { throw new TProtocolException( TProtocolException.INVALID_DATA, "Expected high surrogate char"); } codeunits.add((char) cu); arr.write( (new String(new int[] {codeunits.get(0), codeunits.get(1)}, 0, 2)) .getBytes(StandardCharsets.UTF_8)); codeunits.clear(); } else { arr.write((new String(new int[] {cu}, 0, 1)).getBytes(StandardCharsets.UTF_8)); } continue; } catch (IOException ex) { throw new TProtocolException( TProtocolException.INVALID_DATA, "Invalid unicode sequence"); } } else { int off = ESCAPE_CHARS.indexOf(ch); if (off == -1) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); } ch = ESCAPE_CHAR_VALS[off]; } } arr.write(ch); } return arr; } // Return true if the given byte could be a valid part of a JSON number. private boolean isJSONNumeric(byte b) { switch (b) { case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'E': case 'e': return true; } return false; } // Read in a sequence of characters that are all valid in JSON numbers. Does // not do a complete regex check to validate that this is actually a number. private String readJSONNumericChars() throws TException { StringBuilder strbld = new StringBuilder(); while (true) { byte ch = reader_.peek(); if (!isJSONNumeric(ch)) { break; } strbld.append((char) reader_.read()); } return strbld.toString(); } // Read in a JSON number. If the context dictates, read in enclosing quotes. private long readJSONInteger() throws TException { context_.read(); if (context_.escapeNum()) { readJSONSyntaxChar(QUOTE); } String str = readJSONNumericChars(); if (context_.escapeNum()) { readJSONSyntaxChar(QUOTE); } try { return Long.parseLong(str); } catch (NumberFormatException ex) { throw new TProtocolException( TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); } } // Read in a JSON double value. Throw if the value is not wrapped in quotes // when expected or if wrapped in quotes when not expected. private double readJSONDouble() throws TException { context_.read(); if (reader_.peek() == QUOTE[0]) { TByteArrayOutputStream arr = readJSONString(true); double dub = Double.parseDouble(arr.toString(StandardCharsets.UTF_8)); if (!context_.escapeNum() && !Double.isNaN(dub) && !Double.isInfinite(dub)) { // Throw exception -- we should not be in a string in this case throw new TProtocolException( TProtocolException.INVALID_DATA, "Numeric data unexpectedly quoted"); } return dub; } else { if (context_.escapeNum()) { // This will throw - we should have had a quote if escapeNum == true readJSONSyntaxChar(QUOTE); } try { return Double.parseDouble(readJSONNumericChars()); } catch (NumberFormatException ex) { throw new TProtocolException( TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); } } } // Read in a JSON string containing base-64 encoded data and decode it. private byte[] readJSONBase64() throws TException { TByteArrayOutputStream arr = readJSONString(false); byte[] b = arr.get(); int len = arr.len(); int off = 0; int size = 0; // Ignore padding int bound = len >= 2 ? len - 2 : 0; for (int i = len - 1; i >= bound && b[i] == '='; --i) { --len; } while (len >= 4) { // Decode 4 bytes at a time TBase64Utils.decode(b, off, 4, b, size); // NB: decoded in place off += 4; len -= 4; size += 3; } // Don't decode if we hit the end or got a single leftover byte (invalid // base64 but legal for skip of regular string type) if (len > 1) { // Decode remainder TBase64Utils.decode(b, off, len, b, size); // NB: decoded in place size += len - 1; } // Sadly we must copy the byte[] (any way around this?) byte[] result = new byte[size]; System.arraycopy(b, 0, result, 0, size); return result; } private void readJSONObjectStart() throws TException { context_.read(); readJSONSyntaxChar(LBRACE); pushContext(new JSONPairContext()); } private void readJSONObjectEnd() throws TException { readJSONSyntaxChar(RBRACE); popContext(); } private void readJSONArrayStart() throws TException { context_.read(); readJSONSyntaxChar(LBRACKET); pushContext(new JSONListContext()); } private void readJSONArrayEnd() throws TException { readJSONSyntaxChar(RBRACKET); popContext(); } @Override public TMessage readMessageBegin() throws TException { resetContext(); // THRIFT-3743 readJSONArrayStart(); if (readJSONInteger() != VERSION) { throw new TProtocolException( TProtocolException.BAD_VERSION, "Message contained bad version."); } String name = readJSONString(false).toString(StandardCharsets.UTF_8); byte type = (byte) readJSONInteger(); int seqid = (int) readJSONInteger(); return new TMessage(name, type, seqid); } @Override public void readMessageEnd() throws TException { readJSONArrayEnd(); } @Override public TStruct readStructBegin() throws TException { readJSONObjectStart(); return ANONYMOUS_STRUCT; } @Override public void readStructEnd() throws TException { readJSONObjectEnd(); } @Override public TField readFieldBegin() throws TException { byte ch = reader_.peek(); byte type; short id = 0; if (ch == RBRACE[0]) { type = TType.STOP; } else { id = (short) readJSONInteger(); readJSONObjectStart(); type = getTypeIDForTypeName(readJSONString(false).get()); } return new TField("", type, id); } @Override public void readFieldEnd() throws TException { readJSONObjectEnd(); } @Override public TMap readMapBegin() throws TException { readJSONArrayStart(); byte keyType = getTypeIDForTypeName(readJSONString(false).get()); byte valueType = getTypeIDForTypeName(readJSONString(false).get()); int size = (int) readJSONInteger(); readJSONObjectStart(); TMap map = new TMap(keyType, valueType, size); checkReadBytesAvailable(map); return map; } @Override public void readMapEnd() throws TException { readJSONObjectEnd(); readJSONArrayEnd(); } @Override public TList readListBegin() throws TException { readJSONArrayStart(); byte elemType = getTypeIDForTypeName(readJSONString(false).get()); int size = (int) readJSONInteger(); TList list = new TList(elemType, size); checkReadBytesAvailable(list); return list; } @Override public void readListEnd() throws TException { readJSONArrayEnd(); } @Override public TSet readSetBegin() throws TException { readJSONArrayStart(); byte elemType = getTypeIDForTypeName(readJSONString(false).get()); int size = (int) readJSONInteger(); TSet set = new TSet(elemType, size); checkReadBytesAvailable(set); return set; } @Override public void readSetEnd() throws TException { readJSONArrayEnd(); } @Override public boolean readBool() throws TException { return (readJSONInteger() != 0); } @Override public byte readByte() throws TException { return (byte) readJSONInteger(); } @Override public short readI16() throws TException { return (short) readJSONInteger(); } @Override public int readI32() throws TException { return (int) readJSONInteger(); } @Override public long readI64() throws TException { return readJSONInteger(); } @Override public UUID readUuid() throws TException { return UUID.fromString(readString()); } @Override public double readDouble() throws TException { return readJSONDouble(); } @Override public String readString() throws TException { return readJSONString(false).toString(StandardCharsets.UTF_8); } @Override public ByteBuffer readBinary() throws TException { return ByteBuffer.wrap(readJSONBase64()); } /** Return the minimum number of bytes a type will consume on the wire */ @Override public int getMinSerializedSize(byte type) throws TTransportException { switch (type) { case 0: return 0; // Stop case 1: return 0; // Void case 2: return 1; // Bool case 3: return 1; // Byte case 4: return 1; // Double case 6: return 1; // I16 case 8: return 1; // I32 case 10: return 1; // I64 case 11: return 2; // string length case 12: return 2; // empty struct case 13: return 2; // element count Map case 14: return 2; // element count Set case 15: return 2; // element count List default: throw new TTransportException(TTransportException.UNKNOWN, "unrecognized type code"); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TStruct.java0000644000000000000000000000210614303740367026654 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; /** Helper class that encapsulates struct metadata. */ public final class TStruct { public TStruct() { this(""); } public TStruct(String n) { name = n; } public final String name; public String getName() { return name; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/protocol/TBinaryProtocol.java0000644000000000000000000004167014452237057030351 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.UUID; import org.apache.thrift.TException; import org.apache.thrift.partial.TFieldData; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; /** Binary protocol implementation for thrift. */ public class TBinaryProtocol extends TProtocol { private static final TStruct ANONYMOUS_STRUCT = new TStruct(); private static final long NO_LENGTH_LIMIT = -1; protected static final int VERSION_MASK = 0xffff0000; protected static final int VERSION_1 = 0x80010000; /** * The maximum number of bytes to read from the transport for variable-length fields (such as * strings or binary) or {@link #NO_LENGTH_LIMIT} for unlimited. */ private final long stringLengthLimit_; /** * The maximum number of elements to read from the network for containers (maps, sets, lists), or * {@link #NO_LENGTH_LIMIT} for unlimited. */ private final long containerLengthLimit_; protected boolean strictRead_; protected boolean strictWrite_; private final byte[] inoutTemp = new byte[16]; /** Factory */ public static class Factory implements TProtocolFactory { protected long stringLengthLimit_; protected long containerLengthLimit_; protected boolean strictRead_; protected boolean strictWrite_; public Factory() { this(false, true); } public Factory(boolean strictRead, boolean strictWrite) { this(strictRead, strictWrite, NO_LENGTH_LIMIT, NO_LENGTH_LIMIT); } public Factory(long stringLengthLimit, long containerLengthLimit) { this(false, true, stringLengthLimit, containerLengthLimit); } public Factory( boolean strictRead, boolean strictWrite, long stringLengthLimit, long containerLengthLimit) { stringLengthLimit_ = stringLengthLimit; containerLengthLimit_ = containerLengthLimit; strictRead_ = strictRead; strictWrite_ = strictWrite; } public TProtocol getProtocol(TTransport trans) { return new TBinaryProtocol( trans, stringLengthLimit_, containerLengthLimit_, strictRead_, strictWrite_); } } /** Constructor */ public TBinaryProtocol(TTransport trans) { this(trans, false, true); } public TBinaryProtocol(TTransport trans, boolean strictRead, boolean strictWrite) { this(trans, NO_LENGTH_LIMIT, NO_LENGTH_LIMIT, strictRead, strictWrite); } public TBinaryProtocol(TTransport trans, long stringLengthLimit, long containerLengthLimit) { this(trans, stringLengthLimit, containerLengthLimit, false, true); } public TBinaryProtocol( TTransport trans, long stringLengthLimit, long containerLengthLimit, boolean strictRead, boolean strictWrite) { super(trans); stringLengthLimit_ = stringLengthLimit; containerLengthLimit_ = containerLengthLimit; strictRead_ = strictRead; strictWrite_ = strictWrite; } @Override public void writeMessageBegin(TMessage message) throws TException { if (strictWrite_) { int version = VERSION_1 | message.type; writeI32(version); writeString(message.name); writeI32(message.seqid); } else { writeString(message.name); writeByte(message.type); writeI32(message.seqid); } } @Override public void writeMessageEnd() throws TException {} @Override public void writeStructBegin(TStruct struct) throws TException {} @Override public void writeStructEnd() throws TException {} @Override public void writeFieldBegin(TField field) throws TException { writeByte(field.type); writeI16(field.id); } @Override public void writeFieldEnd() throws TException {} @Override public void writeFieldStop() throws TException { writeByte(TType.STOP); } @Override public void writeMapBegin(TMap map) throws TException { writeByte(map.keyType); writeByte(map.valueType); writeI32(map.size); } @Override public void writeMapEnd() throws TException {} @Override public void writeListBegin(TList list) throws TException { writeByte(list.elemType); writeI32(list.size); } @Override public void writeListEnd() throws TException {} @Override public void writeSetBegin(TSet set) throws TException { writeByte(set.elemType); writeI32(set.size); } @Override public void writeSetEnd() throws TException {} @Override public void writeBool(boolean b) throws TException { writeByte(b ? (byte) 1 : (byte) 0); } @Override public void writeByte(byte b) throws TException { inoutTemp[0] = b; trans_.write(inoutTemp, 0, 1); } @Override public void writeI16(short i16) throws TException { inoutTemp[0] = (byte) (0xff & (i16 >> 8)); inoutTemp[1] = (byte) (0xff & (i16)); trans_.write(inoutTemp, 0, 2); } @Override public void writeI32(int i32) throws TException { inoutTemp[0] = (byte) (0xff & (i32 >> 24)); inoutTemp[1] = (byte) (0xff & (i32 >> 16)); inoutTemp[2] = (byte) (0xff & (i32 >> 8)); inoutTemp[3] = (byte) (0xff & (i32)); trans_.write(inoutTemp, 0, 4); } @Override public void writeI64(long i64) throws TException { inoutTemp[0] = (byte) (0xff & (i64 >> 56)); inoutTemp[1] = (byte) (0xff & (i64 >> 48)); inoutTemp[2] = (byte) (0xff & (i64 >> 40)); inoutTemp[3] = (byte) (0xff & (i64 >> 32)); inoutTemp[4] = (byte) (0xff & (i64 >> 24)); inoutTemp[5] = (byte) (0xff & (i64 >> 16)); inoutTemp[6] = (byte) (0xff & (i64 >> 8)); inoutTemp[7] = (byte) (0xff & (i64)); trans_.write(inoutTemp, 0, 8); } @Override public void writeUuid(UUID uuid) throws TException { { long lsb = uuid.getLeastSignificantBits(); inoutTemp[0] = (byte) (0xff & (lsb >> 56)); inoutTemp[1] = (byte) (0xff & (lsb >> 48)); inoutTemp[2] = (byte) (0xff & (lsb >> 40)); inoutTemp[3] = (byte) (0xff & (lsb >> 32)); inoutTemp[4] = (byte) (0xff & (lsb >> 24)); inoutTemp[5] = (byte) (0xff & (lsb >> 16)); inoutTemp[6] = (byte) (0xff & (lsb >> 8)); inoutTemp[7] = (byte) (0xff & (lsb)); } { long msb = uuid.getMostSignificantBits(); inoutTemp[8] = (byte) (0xff & (msb >> 56)); inoutTemp[1 + 8] = (byte) (0xff & (msb >> 48)); inoutTemp[2 + 8] = (byte) (0xff & (msb >> 40)); inoutTemp[3 + 8] = (byte) (0xff & (msb >> 32)); inoutTemp[4 + 8] = (byte) (0xff & (msb >> 24)); inoutTemp[5 + 8] = (byte) (0xff & (msb >> 16)); inoutTemp[6 + 8] = (byte) (0xff & (msb >> 8)); inoutTemp[7 + 8] = (byte) (0xff & (msb)); } trans_.write(inoutTemp, 0, 16); } @Override public void writeDouble(double dub) throws TException { writeI64(Double.doubleToLongBits(dub)); } @Override public void writeString(String str) throws TException { byte[] dat = str.getBytes(StandardCharsets.UTF_8); writeI32(dat.length); trans_.write(dat, 0, dat.length); } @Override public void writeBinary(ByteBuffer bin) throws TException { int length = bin.limit() - bin.position(); writeI32(length); trans_.write(bin.array(), bin.position() + bin.arrayOffset(), length); } /** Reading methods. */ @Override public TMessage readMessageBegin() throws TException { int size = readI32(); if (size < 0) { int version = size & VERSION_MASK; if (version != VERSION_1) { throw new TProtocolException( TProtocolException.BAD_VERSION, "Bad version in readMessageBegin"); } return new TMessage(readString(), (byte) (size & 0x000000ff), readI32()); } else { if (strictRead_) { throw new TProtocolException( TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); } return new TMessage(readStringBody(size), readByte(), readI32()); } } @Override public void readMessageEnd() throws TException {} @Override public TStruct readStructBegin() throws TException { return ANONYMOUS_STRUCT; } @Override public void readStructEnd() throws TException {} @Override public TField readFieldBegin() throws TException { byte type = readByte(); short id = type == TType.STOP ? 0 : readI16(); return new TField("", type, id); } @Override public void readFieldEnd() throws TException {} @Override public TMap readMapBegin() throws TException { TMap map = new TMap(readByte(), readByte(), readI32()); checkReadBytesAvailable(map); checkContainerReadLength(map.size); return map; } @Override public void readMapEnd() throws TException {} @Override public TList readListBegin() throws TException { TList list = new TList(readByte(), readI32()); checkReadBytesAvailable(list); checkContainerReadLength(list.size); return list; } @Override public void readListEnd() throws TException {} @Override public TSet readSetBegin() throws TException { TSet set = new TSet(readByte(), readI32()); checkReadBytesAvailable(set); checkContainerReadLength(set.size); return set; } @Override public void readSetEnd() throws TException {} @Override public boolean readBool() throws TException { return (readByte() == 1); } @Override public byte readByte() throws TException { if (trans_.getBytesRemainingInBuffer() >= 1) { byte b = trans_.getBuffer()[trans_.getBufferPosition()]; trans_.consumeBuffer(1); return b; } readAll(inoutTemp, 0, 1); return inoutTemp[0]; } @Override public short readI16() throws TException { byte[] buf = inoutTemp; int off = 0; if (trans_.getBytesRemainingInBuffer() >= 2) { buf = trans_.getBuffer(); off = trans_.getBufferPosition(); trans_.consumeBuffer(2); } else { readAll(inoutTemp, 0, 2); } return (short) (((buf[off] & 0xff) << 8) | ((buf[off + 1] & 0xff))); } @Override public int readI32() throws TException { byte[] buf = inoutTemp; int off = 0; if (trans_.getBytesRemainingInBuffer() >= 4) { buf = trans_.getBuffer(); off = trans_.getBufferPosition(); trans_.consumeBuffer(4); } else { readAll(inoutTemp, 0, 4); } return ((buf[off] & 0xff) << 24) | ((buf[off + 1] & 0xff) << 16) | ((buf[off + 2] & 0xff) << 8) | ((buf[off + 3] & 0xff)); } @Override public long readI64() throws TException { byte[] buf = inoutTemp; int off = 0; if (trans_.getBytesRemainingInBuffer() >= 8) { buf = trans_.getBuffer(); off = trans_.getBufferPosition(); trans_.consumeBuffer(8); } else { readAll(inoutTemp, 0, 8); } return ((long) (buf[off] & 0xff) << 56) | ((long) (buf[off + 1] & 0xff) << 48) | ((long) (buf[off + 2] & 0xff) << 40) | ((long) (buf[off + 3] & 0xff) << 32) | ((long) (buf[off + 4] & 0xff) << 24) | ((long) (buf[off + 5] & 0xff) << 16) | ((long) (buf[off + 6] & 0xff) << 8) | ((long) (buf[off + 7] & 0xff)); } @Override public UUID readUuid() throws TException { byte[] buf = inoutTemp; int off = 0; if (trans_.getBytesRemainingInBuffer() >= 16) { buf = trans_.getBuffer(); off = trans_.getBufferPosition(); trans_.consumeBuffer(16); } else { readAll(inoutTemp, 0, 16); } long lsb = ((long) (buf[off] & 0xff) << 56) | ((long) (buf[off + 1] & 0xff) << 48) | ((long) (buf[off + 2] & 0xff) << 40) | ((long) (buf[off + 3] & 0xff) << 32) | ((long) (buf[off + 4] & 0xff) << 24) | ((long) (buf[off + 5] & 0xff) << 16) | ((long) (buf[off + 6] & 0xff) << 8) | ((long) (buf[off + 7] & 0xff)); long msb = ((long) (buf[off + 8] & 0xff) << 56) | ((long) (buf[off + 8 + 1] & 0xff) << 48) | ((long) (buf[off + 8 + 2] & 0xff) << 40) | ((long) (buf[off + 8 + 3] & 0xff) << 32) | ((long) (buf[off + 8 + 4] & 0xff) << 24) | ((long) (buf[off + 8 + 5] & 0xff) << 16) | ((long) (buf[off + 8 + 6] & 0xff) << 8) | ((long) (buf[off + 8 + 7] & 0xff)); return new UUID(msb, lsb); } @Override public double readDouble() throws TException { return Double.longBitsToDouble(readI64()); } @Override public String readString() throws TException { int size = readI32(); if (trans_.getBytesRemainingInBuffer() >= size) { String s = new String(trans_.getBuffer(), trans_.getBufferPosition(), size, StandardCharsets.UTF_8); trans_.consumeBuffer(size); return s; } return readStringBody(size); } public String readStringBody(int size) throws TException { checkStringReadLength(size); byte[] buf = new byte[size]; trans_.readAll(buf, 0, size); return new String(buf, StandardCharsets.UTF_8); } @Override public ByteBuffer readBinary() throws TException { int size = readI32(); checkStringReadLength(size); if (trans_.getBytesRemainingInBuffer() >= size) { ByteBuffer bb = ByteBuffer.wrap(trans_.getBuffer(), trans_.getBufferPosition(), size); trans_.consumeBuffer(size); return bb; } byte[] buf = new byte[size]; trans_.readAll(buf, 0, size); return ByteBuffer.wrap(buf); } private void checkStringReadLength(int length) throws TException { if (length < 0) { throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, "Negative length: " + length); } getTransport().checkReadBytesAvailable(length); if (stringLengthLimit_ != NO_LENGTH_LIMIT && length > stringLengthLimit_) { throw new TProtocolException( TProtocolException.SIZE_LIMIT, "Length exceeded max allowed: " + length); } } private void checkContainerReadLength(int length) throws TProtocolException { if (length < 0) { throw new TProtocolException(TProtocolException.NEGATIVE_SIZE, "Negative length: " + length); } if (containerLengthLimit_ != NO_LENGTH_LIMIT && length > containerLengthLimit_) { throw new TProtocolException( TProtocolException.SIZE_LIMIT, "Length exceeded max allowed: " + length); } } private int readAll(byte[] buf, int off, int len) throws TException { return trans_.readAll(buf, off, len); } /** Return the minimum number of bytes a type will consume on the wire */ @Override public int getMinSerializedSize(byte type) throws TTransportException { switch (type) { case 0: return 0; // Stop case 1: return 0; // Void case 2: return 1; // Bool sizeof(byte) case 3: return 1; // Byte sizeof(byte) case 4: return 8; // Double sizeof(double) case 6: return 2; // I16 sizeof(short) case 8: return 4; // I32 sizeof(int) case 10: return 8; // I64 sizeof(long) case 11: return 4; // string length sizeof(int) case 12: return 0; // empty struct case 13: return 4; // element count Map sizeof(int) case 14: return 4; // element count Set sizeof(int) case 15: return 4; // element count List sizeof(int) default: throw new TTransportException(TTransportException.UNKNOWN, "unrecognized type code"); } } // ----------------------------------------------------------------- // Additional methods to improve performance. @Override public int readFieldBeginData() throws TException { byte type = this.readByte(); if (type == TType.STOP) { return TFieldData.encode(type); } short id = this.readI16(); return TFieldData.encode(type, id); } @Override protected void skipBool() throws TException { this.skipBytes(1); } @Override protected void skipByte() throws TException { this.skipBytes(1); } @Override protected void skipI16() throws TException { this.skipBytes(2); } @Override protected void skipI32() throws TException { this.skipBytes(4); } @Override protected void skipI64() throws TException { this.skipBytes(8); } @Override protected void skipDouble() throws TException { this.skipBytes(8); } @Override protected void skipBinary() throws TException { int size = readI32(); this.skipBytes(size); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TSerializer.java0000644000000000000000000000615514370300523025636 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.ByteArrayOutputStream; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransportException; /** Generic utility for easily serializing objects into a byte array or Java String. */ public class TSerializer { /** This is the byte array that data is actually serialized into */ private final ByteArrayOutputStream baos_ = new ByteArrayOutputStream(); /** Internal protocol used for serializing objects. */ private final TProtocol protocol_; /** * Create a new TSerializer that uses the TBinaryProtocol by default. * * @throws TTransportException if there an error initializing the underlying transport. */ public TSerializer() throws TTransportException { this(new TBinaryProtocol.Factory()); } /** * Create a new TSerializer. It will use the TProtocol specified by the factory that is passed in. * * @param protocolFactory Factory to create a protocol * @throws TTransportException if there is an error initializing the underlying transport. */ public TSerializer(TProtocolFactory protocolFactory) throws TTransportException { /* This transport wraps that byte array */ TIOStreamTransport transport_ = new TIOStreamTransport(new TConfiguration(), baos_); protocol_ = protocolFactory.getProtocol(transport_); } /** * Serialize the Thrift object into a byte array. The process is simple, just clear the byte array * output, write the object into it, and grab the raw bytes. * * @param base The object to serialize * @return Serialized object in byte[] format * @throws TException if an error is encountered during serialization. */ public byte[] serialize(TBase base) throws TException { baos_.reset(); base.write(protocol_); return baos_.toByteArray(); } /** * Serialize the Thrift object into a Java string, using the default JVM charset encoding. * * @param base The object to serialize * @return Serialized object as a String * @throws TException if an error is encountered during serialization. */ public String toString(TBase base) throws TException { return new String(serialize(base)); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TException.java0000644000000000000000000000231414303740367025466 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** Generic exception class for Thrift. */ public class TException extends Exception { private static final long serialVersionUID = 1L; public TException() { super(); } public TException(String message) { super(message); } public TException(Throwable cause) { super(cause); } public TException(String message, Throwable cause) { super(message, cause); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TNonblockingMultiFetchStats.java0000644000000000000000000000702014370300523030764 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** This class keeps track of statistics for TNonblockinMultiFetchClient. */ public class TNonblockingMultiFetchStats { private int numTotalServers; private int numReadCompletedServers; private int numConnectErrorServers; private int totalRecvBufBytes; private int maxResponseBytes; private int numOverflowedRecvBuf; private int numInvalidFrameSize; // time from the beginning of fetch() function to the reading finish // time of the last socket (in millisecond) private long readTime; public TNonblockingMultiFetchStats() { clear(); } public void clear() { numTotalServers = 0; numReadCompletedServers = 0; numConnectErrorServers = 0; totalRecvBufBytes = 0; maxResponseBytes = 0; numOverflowedRecvBuf = 0; numInvalidFrameSize = 0; readTime = 0; } public String toString() { String stats = String.format( "numTotalServers=%d, " + "numReadCompletedServers=%d, numConnectErrorServers=%d, " + "numUnresponsiveServers=%d, totalRecvBufBytes=%fM, " + "maxResponseBytes=%d, numOverflowedRecvBuf=%d, " + "numInvalidFrameSize=%d, readTime=%dms", numTotalServers, numReadCompletedServers, numConnectErrorServers, (numTotalServers - numReadCompletedServers - numConnectErrorServers), totalRecvBufBytes / 1024.0 / 1024, maxResponseBytes, numOverflowedRecvBuf, numInvalidFrameSize, readTime); return stats; } public void setNumTotalServers(int val) { numTotalServers = val; } public void setMaxResponseBytes(int val) { maxResponseBytes = val; } public void setReadTime(long val) { readTime = val; } public void incNumReadCompletedServers() { numReadCompletedServers++; } public void incNumConnectErrorServers() { numConnectErrorServers++; } public void incNumOverflowedRecvBuf() { numOverflowedRecvBuf++; } public void incTotalRecvBufBytes(int val) { totalRecvBufBytes += val; } public void incNumInvalidFrameSize() { numInvalidFrameSize++; } public int getMaxResponseBytes() { return maxResponseBytes; } public int getNumReadCompletedServers() { return numReadCompletedServers; } public int getNumConnectErrorServers() { return numConnectErrorServers; } public int getNumTotalServers() { return numTotalServers; } public int getNumOverflowedRecvBuf() { return numOverflowedRecvBuf; } public int getTotalRecvBufBytes() { return totalRecvBufBytes; } public int getNumInvalidFrameSize() { return numInvalidFrameSize; } public long getReadTime() { return readTime; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/annotation/0000777000000000000000000000000014303740367024717 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/annotation/Nullable.java0000644000000000000000000000222114303740367027311 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Annotation indicating a field, method return, or method parameter may be {@code null}. We package * our own annotation to avoid a mandatory third-party dependency. */ @Retention(RetentionPolicy.CLASS) public @interface Nullable {} thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TSerializable.java0000644000000000000000000000256614370300523026135 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TProtocol; /** Generic base interface for generated Thrift objects. */ public interface TSerializable { /** * Reads the TObject from the given input protocol. * * @param iprot Input protocol * @throws TException if there is an error reading from iprot */ void read(TProtocol iprot) throws TException; /** * Writes the objects out to the protocol * * @param oprot Output protocol * @throws TException if there is an error writing to oprot */ void write(TProtocol oprot) throws TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TProcessor.java0000644000000000000000000000210214370300523025470 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TProtocol; /** * A processor is a generic object which operates upon an input stream and writes to some output * stream. */ public interface TProcessor { void process(TProtocol in, TProtocol out) throws TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/0000777000000000000000000000000014370300523024167 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/ThriftStructProcessor.java0000644000000000000000000001225614303740367031413 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import org.apache.thrift.TBase; import org.apache.thrift.TEnum; import org.apache.thrift.TFieldIdEnum; /** * Provides a way to create and initialize an instance of TBase during partial deserialization. * *

This class is supposed to be used as a helper class for {@code PartialThriftDeserializer}. */ public class ThriftStructProcessor implements ThriftFieldValueProcessor { private static final EnumCache enums = new EnumCache(); @Override public Object createNewStruct(ThriftMetadata.ThriftStruct metadata) { return metadata.createNewStruct(); } @Override public TBase prepareStruct(Object instance) { return (TBase) instance; } @Override public Object createNewList(int expectedSize) { return new Object[expectedSize]; } @Override public void setListElement(Object instance, int index, Object value) { ((Object[]) instance)[index] = value; } @Override public Object prepareList(Object instance) { return Arrays.asList((Object[]) instance); } @Override public Object createNewMap(int expectedSize) { return new HashMap(expectedSize); } @Override public void setMapElement(Object instance, int index, Object key, Object value) { ((HashMap) instance).put(key, value); } @Override public Object prepareMap(Object instance) { return instance; } @Override public Object createNewSet(int expectedSize) { return new HashSet(expectedSize); } @Override public void setSetElement(Object instance, int index, Object value) { ((HashSet) instance).add(value); } @Override public Object prepareSet(Object instance) { return instance; } @Override public Object prepareEnum(Class enumClass, int ordinal) { return enums.get(enumClass, ordinal); } @Override public Object prepareString(ByteBuffer buffer) { return byteBufferToString(buffer); } @Override public Object prepareBinary(ByteBuffer buffer) { return buffer; } @Override public void setBool(TBase valueCollection, TFieldIdEnum fieldId, boolean value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setByte(TBase valueCollection, TFieldIdEnum fieldId, byte value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setInt16(TBase valueCollection, TFieldIdEnum fieldId, short value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setInt32(TBase valueCollection, TFieldIdEnum fieldId, int value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setInt64(TBase valueCollection, TFieldIdEnum fieldId, long value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setDouble(TBase valueCollection, TFieldIdEnum fieldId, double value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setBinary(TBase valueCollection, TFieldIdEnum fieldId, ByteBuffer value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setString(TBase valueCollection, TFieldIdEnum fieldId, ByteBuffer buffer) { String value = byteBufferToString(buffer); valueCollection.setFieldValue(fieldId, value); } @Override public void setEnumField(TBase valueCollection, TFieldIdEnum fieldId, Object value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setListField(TBase valueCollection, TFieldIdEnum fieldId, Object value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setMapField(TBase valueCollection, TFieldIdEnum fieldId, Object value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setSetField(TBase valueCollection, TFieldIdEnum fieldId, Object value) { valueCollection.setFieldValue(fieldId, value); } @Override public void setStructField(TBase valueCollection, TFieldIdEnum fieldId, Object value) { valueCollection.setFieldValue(fieldId, value); } private static String byteBufferToString(ByteBuffer buffer) { byte[] bytes = buffer.array(); int pos = buffer.position(); return new String(bytes, pos, buffer.limit() - pos, StandardCharsets.UTF_8); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/EnumCache.java0000644000000000000000000000547114370300523026665 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import org.apache.thrift.TEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Provides a memoized way to lookup an enum by its value. * *

This class is used internally by {@code TDeserializer}. It is not intended to be used * separately on its own. */ public class EnumCache { private static final Logger LOG = LoggerFactory.getLogger(EnumCache.class); private Map, Map> classMap; public EnumCache() { this.classMap = new HashMap<>(); } /** * Gets an instance of the enum type {@code enumClass} corresponding to the given {@code value}. * * @param enumClass class of the enum to be returned. * @param value value returned by {@code getValue()}. */ public TEnum get(Class enumClass, int value) { Validate.checkNotNull(enumClass, "enumClass"); Map valueMap = classMap.get(enumClass); if (valueMap == null) { valueMap = addClass(enumClass); if (valueMap == null) { return null; } } return valueMap.get(value); } private Map addClass(Class enumClass) { try { Method valuesMethod = enumClass.getMethod("values"); TEnum[] enumValues = (TEnum[]) valuesMethod.invoke(null); Map valueMap = new HashMap<>(); for (TEnum enumValue : enumValues) { valueMap.put(enumValue.getValue(), enumValue); } classMap.put(enumClass, valueMap); return valueMap; } catch (NoSuchMethodException e) { LOG.error("enum class does not have values() method", e); return null; } catch (IllegalAccessException e) { LOG.error("Enum.values() method should be public!", e); return null; } catch (InvocationTargetException e) { LOG.error("Enum.values() threw exception", e); return null; } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/README.md0000644000000000000000000001562714303740367025467 0ustar00rootroot00000000000000# Partial Thrift Deserialization ## Overview This document describes how partial deserialization of Thrift works. There are two main goals of this documentation: 1. Make it easier to understand the current Java implementation in this folder. 1. Be useful in implementing partial deserialization support in additional languages. This document is divided into two high level areas. The first part explains important concepts relevant to partial deserialization. The second part describes components involved in the Java implementation in this folder. Moreover, this blog provides some performance numbers and addtional information: https://medium.com/pinterest-engineering/improving-data-processing-efficiency-using-partial-deserialization-of-thrift-16bc3a4a38b4 ## Basic Concepts ### Motivation The main motivation behind implementing this feature is to improve performance when we need to access only a subset of fields in any Thrift object. This situation arises often when big data is stored in Thrift encoded format (for example, SequenceFile with serialized Thrift values). Many data processing jobs may access this data. However, not every job needs to access every field of each object. In such cases, if we have prior knowledge of the fields needed for a given job, we can deserialize only that subset of fields and avoid the cost deserializing the rest of the fields. There are two benefits of this approach: we save cpu cycles by not deserializing unnecessary fields and we end up reducing gc pressure. Both of the savings quickly add up when processing billions of instances in a data processing job. ### Partial deserialization Partial deserialization involves deserializing only a subset of the fields of a serialized Thrift object while efficiently skipping over the rest. One very important benefit of partial deserialization is that the output of the deserialization process is not limited to a `TBase` derived object. It can deserialize a serialized blob into any type by using an appropriate `ThriftFieldValueProcessor`. ### Defining the subset of fields to deserialize The subset of fields to deserialize is defined using a list of fully qualified field names. For example, consider the Thrift `struct` definition below: ```Thrift struct SmallStruct { 1: optional string stringValue; 2: optional i16 i16Value; } struct TestStruct { 1: optional i16 i16Field; 2: optional list structList; 3: optional set structSet; 4: optional map structMap; 5: optional SmallStruct structField; } ``` For the Thrift `struct`, each of the following line shows a fully qualified field definition. Partial deserialization uses a non-empty set of such field definitions to identify the subset of fields to deserialize. ``` - i16Field - structList.stringValue - structSet.i16Value - structMap.stringValue - structField.i16Value ``` Note that the syntax of denoting paths involving map fields do not support a way to define sub-fields of the key type. However, that limitation can be addressed in future by amending the syntax in a backword compatible way. For example, the field path `structMap.stringValue` shown above has leaf segment `stringValue` which is a field in map values. ## Components The process of partial deserialization involves the following major components. We have listed names of the Java file(s) implementing each component for easier mapping to the source code. ### Thrift Metadata Source files: - ThriftField.java - ThriftMetadata.java - TDeserializer.java We saw in the previous section how we can identify the subset of fields to deserialize. As the first step, we need to compile the collection of field definitions into an internal efficient data structure that we can traverse at runtime. The compilation takes place internally when one creates an instance of TDeserializer using a constructor that accepts a list of field names. ```Java // First, create a collection of fully qualified field names. List fieldNames = Arrays.asList("i16Field", "structField.i16Value"); // Create an instance of TDeserializer that supports partial deserialization. TDeserializer deserializer = new TDeserializer(TestStruct.class, fieldNames, new TBinaryProtocol.Factory()); ``` At this point, we have an efficient internal representation of the fields that need to get deserialized. ### Partial Thrift Protocol Source files: - TProtocol.java - TBinaryProtocol.java - TCompactProtocol.java This component implements efficient skipping over fields that need not be deserialized. The functionality to skip over fields has been added to the above protocols by addition of `skip*()` methods. The default implementation of each such method simply calls the corresponding `read*()` method in `TProtocol.java`. A derived protocol (for example, `TBinaryProtocol`) provides a more efficient implementation of each `skip*()` method. For example, `TBinaryProtocol` skips a field by incrementing internal offset into the transport buffer. ### Partial Thrift Deserializer Source files: - TDeserializer.java This component, traverses a serialized blob sequentially one field at a time. At the beginning of each field, it consults the informations stored in the compiled `ThriftMetadata` to see if that field needs to be deserialized. If yes, then the field is deserialized into a value as would normally take place during regular deserialization process. If that field is not in the target subset then the deserializer efficiently skips over that field. ### Field Value Processor Source files: - ThriftFieldValueProcessor.java - ThriftStructProcessor.java One very important benefit of partial deserialization is that the output of the deserialization process is not limited to a `TBase` derived object. It can deserialize a serialized blob into any type by using an appropriate `ThriftFieldValueProcessor`. When the partial Thrift deserializer deserializes a field, it passes its value to a `ThriftFieldValueProcessor`. The processor gets to decide whether the value is stored as-is or is stored in some intermediate form. The default implementation of this interface is `ThriftStructProcessor`. This implementation outputs a `TBase` derived object. There are other implementations that exist (not included in this drop at present). For example, one implementation enables deserializing a Thrift blob directly into an `InternalRow` used by `Spark`. That has yielded orders of magnitude performance improvement over a `Spark` engine that consumes `Thrift` data using its default deserializer. ### Miscellanious Helpers Files: - TFieldData.java : Holds the type and id members of a TField into a single int. This encoding scheme obviates the need to instantiate TField during the partial deserialization process. - EnumCache.java : Provides a memoized way to lookup an enum by its value. - PartialThriftComparer.java : Enables comparison of two TBase instances such that the comparison is limited to the subset of fields defined by the supplied metadata. thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/ThriftMetadata.java0000644000000000000000000004261614303740367027752 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.io.Serializable; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.thrift.TBase; import org.apache.thrift.TFieldIdEnum; import org.apache.thrift.TFieldRequirementType; import org.apache.thrift.TUnion; import org.apache.thrift.meta_data.FieldMetaData; import org.apache.thrift.meta_data.ListMetaData; import org.apache.thrift.meta_data.MapMetaData; import org.apache.thrift.meta_data.SetMetaData; import org.apache.thrift.meta_data.StructMetaData; import org.apache.thrift.protocol.TType; /** * Container for Thrift metadata classes such as {@link ThriftPrimitive}, {@link ThriftList}, etc. * *

This class is mainly used by {@code TDeserializer}. */ public class ThriftMetadata { enum FieldTypeEnum implements TFieldIdEnum { ROOT((short) 0, "root"), ENUM((short) 1, "enum"), LIST_ELEMENT((short) 2, "listElement"), MAP_KEY((short) 3, "mapKey"), MAP_VALUE((short) 4, "mapValue"), SET_ELEMENT((short) 5, "setElement"); private final short id; private final String name; FieldTypeEnum(short id, String name) { this.id = id; this.name = name; } @Override public short getThriftFieldId() { return id; } @Override public String getFieldName() { return name; } } private enum ComparisonResult { UNKNOWN, EQUAL, NOT_EQUAL } /** * Base class of field types that can be partially deserialized. * *

Holds metadata necessary for partial deserialization. The metadata is internally computed * and used; therefore it is not visible to the users of {@code TDeserializer}. */ public abstract static class ThriftObject implements Serializable { public final ThriftObject parent; public final TFieldIdEnum fieldId; public final FieldMetaData data; // Placeholder to attach additional data. This class or its descendents // do not try to access or interpret this field. public Object additionalData; ThriftObject(ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data) { this.parent = parent; this.fieldId = fieldId; this.data = data; } /** * Converts this instance to formatted and indented string representation. * * @param sb the {@code StringBuilder} to add formatted strings to. * @param level the current indent level. */ protected abstract void toPrettyString(StringBuilder sb, int level); /** Gets a space string whose length is proportional to the given indent level. */ protected String getIndent(int level) { return StringUtils.repeat(" ", level * 4); } /** Helper method to append a formatted string to the given {@code StringBuilder}. */ protected void append(StringBuilder sb, String format, Object... args) { sb.append(String.format(format, args)); } /** Gets the name of this field. */ protected String getName() { return this.fieldId.getFieldName(); } protected List noFields = Collections.emptyList(); protected String getSubElementName(TFieldIdEnum fieldId) { return getSubElementName(fieldId, "element"); } protected String getSubElementName(TFieldIdEnum fieldId, String suffix) { return String.format("%s_%s", fieldId.getFieldName(), suffix); } private static class Factory { static ThriftObject createNew( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, List fields) { byte fieldType = data.valueMetaData.type; switch (fieldType) { case TType.STRUCT: return ThriftStructBase.create(parent, fieldId, data, fields); case TType.LIST: return new ThriftList(parent, fieldId, data, fields); case TType.MAP: return new ThriftMap(parent, fieldId, data, fields); case TType.SET: return new ThriftSet(parent, fieldId, data, fields); case TType.ENUM: return new ThriftEnum(parent, fieldId, data); case TType.BOOL: case TType.BYTE: case TType.I16: case TType.I32: case TType.I64: case TType.DOUBLE: case TType.STRING: return new ThriftPrimitive(parent, fieldId, data); default: throw unsupportedFieldTypeException(fieldType); } } } } /** Metadata about primitive types. */ public static class ThriftPrimitive extends ThriftObject { ThriftPrimitive(ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data) { super(parent, fieldId, data); } public boolean isBinary() { return this.data.valueMetaData.isBinary(); } @Override protected void toPrettyString(StringBuilder sb, int level) { String fieldType = this.getTypeName(); this.append(sb, "%s%s %s;\n", this.getIndent(level), fieldType, this.getName()); } private String getTypeName() { byte fieldType = this.data.valueMetaData.type; switch (fieldType) { case TType.BOOL: return "bool"; case TType.BYTE: return "byte"; case TType.I16: return "i16"; case TType.I32: return "i32"; case TType.I64: return "i64"; case TType.DOUBLE: return "double"; case TType.STRING: if (this.isBinary()) { return "binary"; } else { return "string"; } default: throw unsupportedFieldTypeException(fieldType); } } } public static class ThriftEnum extends ThriftObject { private static EnumCache enums = new EnumCache(); ThriftEnum(ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data) { super(parent, fieldId, data); } @Override protected void toPrettyString(StringBuilder sb, int level) { this.append(sb, "%senum %s;\n", this.getIndent(level), this.getName()); } } /** Metadata of container like objects: list, set, map */ public abstract static class ThriftContainer extends ThriftObject { public ThriftContainer(ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data) { super(parent, fieldId, data); } public abstract boolean hasUnion(); } public static class ThriftList extends ThriftContainer { public final ThriftObject elementData; ThriftList( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, List fields) { super(parent, fieldId, data); this.elementData = ThriftObject.Factory.createNew( this, FieldTypeEnum.LIST_ELEMENT, new FieldMetaData( getSubElementName(fieldId), TFieldRequirementType.REQUIRED, ((ListMetaData) data.valueMetaData).elemMetaData), fields); } @Override public boolean hasUnion() { return this.elementData instanceof ThriftUnion; } @Override protected void toPrettyString(StringBuilder sb, int level) { this.append(sb, "%slist<\n", this.getIndent(level)); this.elementData.toPrettyString(sb, level + 1); this.append(sb, "%s> %s;\n", this.getIndent(level), this.getName()); } } public static class ThriftSet extends ThriftContainer { public final ThriftObject elementData; ThriftSet( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, List fields) { super(parent, fieldId, data); this.elementData = ThriftObject.Factory.createNew( this, FieldTypeEnum.SET_ELEMENT, new FieldMetaData( getSubElementName(fieldId), TFieldRequirementType.REQUIRED, ((SetMetaData) data.valueMetaData).elemMetaData), fields); } @Override public boolean hasUnion() { return this.elementData instanceof ThriftUnion; } @Override protected void toPrettyString(StringBuilder sb, int level) { this.append(sb, "%sset<\n", this.getIndent(level)); this.elementData.toPrettyString(sb, level + 1); this.append(sb, "%s> %s;\n", this.getIndent(level), this.getName()); } } public static class ThriftMap extends ThriftContainer { public final ThriftObject keyData; public final ThriftObject valueData; ThriftMap( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, List fields) { super(parent, fieldId, data); this.keyData = ThriftObject.Factory.createNew( this, FieldTypeEnum.MAP_KEY, new FieldMetaData( getSubElementName(fieldId, "key"), TFieldRequirementType.REQUIRED, ((MapMetaData) data.valueMetaData).keyMetaData), Collections.emptyList()); this.valueData = ThriftObject.Factory.createNew( this, FieldTypeEnum.MAP_VALUE, new FieldMetaData( getSubElementName(fieldId, "value"), TFieldRequirementType.REQUIRED, ((MapMetaData) data.valueMetaData).valueMetaData), fields); } @Override public boolean hasUnion() { return (this.keyData instanceof ThriftUnion) || (this.valueData instanceof ThriftUnion); } @Override protected void toPrettyString(StringBuilder sb, int level) { this.append(sb, "%smap<\n", this.getIndent(level)); this.append(sb, "%skey = {\n", this.getIndent(level + 1)); this.keyData.toPrettyString(sb, level + 2); this.append(sb, "%s},\n", this.getIndent(level + 1)); this.append(sb, "%svalue = {\n", this.getIndent(level + 1)); this.valueData.toPrettyString(sb, level + 2); this.append(sb, "%s}\n", this.getIndent(level + 1)); this.append(sb, "%s> %s;\n", this.getIndent(level), this.getName()); } } /** * Base class for metadata of ThriftStruct and ThriftUnion. Holds functionality that is common to * both. */ public abstract static class ThriftStructBase extends ThriftObject { public ThriftStructBase(ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data) { super(parent, fieldId, data); } public Class getStructClass() { return getStructClass(this.data); } public static Class getStructClass(FieldMetaData data) { return (Class) ((StructMetaData) data.valueMetaData).structClass; } public boolean isUnion() { return isUnion(this.data); } public static boolean isUnion(FieldMetaData data) { return TUnion.class.isAssignableFrom(getStructClass(data)); } public static ThriftStructBase create( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, Iterable fieldsData) { if (isUnion(data)) { return new ThriftUnion<>(parent, fieldId, data, fieldsData); } else { return new ThriftStruct<>(parent, fieldId, data, fieldsData); } } } /** Metadata of a Thrift union. Currently not adequately supported. */ public static class ThriftUnion extends ThriftStructBase { public ThriftUnion( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, Iterable fieldsData) { super(parent, fieldId, data); } @Override protected void toPrettyString(StringBuilder sb, int level) { String indent = this.getIndent(level); String indent2 = this.getIndent(level + 1); this.append(sb, "%sunion %s {\n", indent, this.getName()); this.append(sb, "%s// unions not adequately supported at present.\n", indent2); this.append(sb, "%s}\n", indent); } } /** Metadata of a Thrift struct. */ public static class ThriftStruct extends ThriftStructBase { public final Map fields; ThriftStruct( ThriftObject parent, TFieldIdEnum fieldId, FieldMetaData data, Iterable fieldsData) { super(parent, fieldId, data); Class clasz = getStructClass(data); this.fields = getFields(this, clasz, fieldsData); } public T createNewStruct() { try { Class structClass = getStructClass(this.data); Constructor declaredConstructor = structClass.getDeclaredConstructor(); return declaredConstructor.newInstance(); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } public static ThriftStruct of(Class clasz) { return ThriftStruct.fromFields(clasz, Collections.emptyList()); } public static ThriftStruct fromFieldNames( Class clasz, Collection fieldNames) { return fromFields(clasz, ThriftField.fromNames(fieldNames)); } public static ThriftStruct fromFields( Class clasz, Iterable fields) { Validate.checkNotNull(clasz, "clasz"); Validate.checkNotNull(fields, "fields"); return new ThriftStruct<>( null, FieldTypeEnum.ROOT, new FieldMetaData( FieldTypeEnum.ROOT.getFieldName(), TFieldRequirementType.REQUIRED, new StructMetaData(TType.STRUCT, clasz)), fields); } @Override public String toString() { StringBuilder sb = new StringBuilder(); this.toPrettyString(sb, 0); return sb.toString(); } @Override protected void toPrettyString(StringBuilder sb, int level) { String indent = this.getIndent(level); String indent2 = this.getIndent(level + 1); this.append(sb, "%sstruct %s {\n", indent, this.getName()); if (this.fields.size() == 0) { this.append(sb, "%s*;", indent2); } else { List ids = new ArrayList<>(this.fields.keySet()); Collections.sort(ids); for (Integer id : ids) { this.fields.get(id).toPrettyString(sb, level + 1); } } this.append(sb, "%s}\n", indent); } private static Map getFields( ThriftStruct parent, Class clasz, Iterable fieldsData) { Map fieldsMetaData = FieldMetaData.getStructMetaDataMap(clasz); Map fields = new HashMap<>(); boolean getAllFields = !fieldsData.iterator().hasNext(); if (getAllFields) { for (Map.Entry entry : fieldsMetaData.entrySet()) { TFieldIdEnum fieldId = entry.getKey(); FieldMetaData fieldMetaData = entry.getValue(); ThriftObject field = ThriftObject.Factory.createNew( parent, fieldId, fieldMetaData, Collections.emptyList()); fields.put((int) fieldId.getThriftFieldId(), field); } } else { for (ThriftField fieldData : fieldsData) { String fieldName = fieldData.name; FieldMetaData fieldMetaData = findFieldMetaData(fieldsMetaData, fieldName); TFieldIdEnum fieldId = findFieldId(fieldsMetaData, fieldName); ThriftObject field = ThriftObject.Factory.createNew(parent, fieldId, fieldMetaData, fieldData.fields); fields.put((int) fieldId.getThriftFieldId(), field); } } return fields; } private static FieldMetaData findFieldMetaData( Map fieldsMetaData, String fieldName) { for (FieldMetaData fieldData : fieldsMetaData.values()) { if (fieldData.fieldName.equals(fieldName)) { return fieldData; } } throw fieldNotFoundException(fieldName); } private static TFieldIdEnum findFieldId( Map fieldsMetaData, String fieldName) { for (TFieldIdEnum fieldId : fieldsMetaData.keySet()) { if (fieldId.getFieldName().equals(fieldName)) { return fieldId; } } throw fieldNotFoundException(fieldName); } } static IllegalArgumentException fieldNotFoundException(String fieldName) { return new IllegalArgumentException("field not found: '" + fieldName + "'"); } static UnsupportedOperationException unsupportedFieldTypeException(byte fieldType) { return new UnsupportedOperationException("field type not supported: '" + fieldType + "'"); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/TFieldData.java0000644000000000000000000000262714303740367027010 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; /** * Holds the type and id members of a {@link org.apache.thrift.protocol.TField} into a single int. * *

This encoding scheme obviates the need to instantiate TField during the partial * deserialization process. */ public class TFieldData { public static int encode(byte type) { return type & 0xff; } public static int encode(byte type, short id) { return (type & 0xff) | (((int) id) << 8); } public static byte getType(int data) { return (byte) (0xff & data); } public static short getId(int data) { return (short) ((0xffff00 & data) >> 8); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/ThriftFieldValueProcessor.java0000644000000000000000000000612614303740367032146 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.nio.ByteBuffer; import org.apache.thrift.TEnum; import org.apache.thrift.TFieldIdEnum; /** * Provides an abstraction to process deserialized field values and place them into the collection * that holds them. This abstraction allows different types of collections to be output from partial * deserialization. * *

In case of the usual Thrift deserialization, the collection that holds field values is simply * an instance of TBase. */ public interface ThriftFieldValueProcessor { // Struct related methods; Object createNewStruct(ThriftMetadata.ThriftStruct metadata); V prepareStruct(Object instance); void setBool(V valueCollection, TFieldIdEnum fieldId, boolean value); void setByte(V valueCollection, TFieldIdEnum fieldId, byte value); void setInt16(V valueCollection, TFieldIdEnum fieldId, short value); void setInt32(V valueCollection, TFieldIdEnum fieldId, int value); void setInt64(V valueCollection, TFieldIdEnum fieldId, long value); void setDouble(V valueCollection, TFieldIdEnum fieldId, double value); void setBinary(V valueCollection, TFieldIdEnum fieldId, ByteBuffer value); void setString(V valueCollection, TFieldIdEnum fieldId, ByteBuffer buffer); void setEnumField(V valueCollection, TFieldIdEnum fieldId, Object value); void setListField(V valueCollection, TFieldIdEnum fieldId, Object value); void setMapField(V valueCollection, TFieldIdEnum fieldId, Object value); void setSetField(V valueCollection, TFieldIdEnum fieldId, Object value); void setStructField(V valueCollection, TFieldIdEnum fieldId, Object value); Object prepareEnum(Class enumClass, int ordinal); Object prepareString(ByteBuffer buffer); Object prepareBinary(ByteBuffer buffer); // List field related methods. Object createNewList(int expectedSize); void setListElement(Object instance, int index, Object value); Object prepareList(Object instance); // Map field related methods. Object createNewMap(int expectedSize); void setMapElement(Object instance, int index, Object key, Object value); Object prepareMap(Object instance); // Set field related methods. Object createNewSet(int expectedSize); void setSetElement(Object instance, int index, Object value); Object prepareSet(Object instance); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/Validate.java0000644000000000000000000002111614303740367026572 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collection; /** * A superset of Validate class in Apache commons lang3. * *

It provides consistent message strings for frequently encountered checks. That simplifies * callers because they have to supply only the name of the argument that failed a check instead of * having to supply the entire message. */ public final class Validate { private Validate() {} /** Validates that the given reference argument is not null. */ public static void checkNotNull(Object obj, String argName) { checkArgument(obj != null, "'%s' must not be null.", argName); } /** Validates that the given integer argument is not zero or negative. */ public static void checkPositiveInteger(long value, String argName) { checkArgument(value > 0, "'%s' must be a positive integer.", argName); } /** Validates that the given integer argument is not negative. */ public static void checkNotNegative(long value, String argName) { checkArgument(value >= 0, "'%s' must not be negative.", argName); } /* * Validates that the expression (that checks a required field is present) is true. */ public static void checkRequired(boolean isPresent, String argName) { checkArgument(isPresent, "'%s' is required.", argName); } /** Validates that the expression (that checks a field is valid) is true. */ public static void checkValid(boolean isValid, String argName) { checkArgument(isValid, "'%s' is invalid.", argName); } /** Validates that the expression (that checks a field is valid) is true. */ public static void checkValid(boolean isValid, String argName, String validValues) { checkArgument(isValid, "'%s' is invalid. Valid values are: %s.", argName, validValues); } /** Validates that the given string is not null and has non-zero length. */ public static void checkNotNullAndNotEmpty(String arg, String argName) { Validate.checkNotNull(arg, argName); Validate.checkArgument(arg.length() > 0, "'%s' must not be empty.", argName); } /** Validates that the given array is not null and has at least one element. */ public static void checkNotNullAndNotEmpty(T[] array, String argName) { Validate.checkNotNull(array, argName); checkNotEmpty(array.length, argName); } /** Validates that the given array is not null and has at least one element. */ public static void checkNotNullAndNotEmpty(byte[] array, String argName) { Validate.checkNotNull(array, argName); checkNotEmpty(array.length, argName); } /** Validates that the given array is not null and has at least one element. */ public static void checkNotNullAndNotEmpty(short[] array, String argName) { Validate.checkNotNull(array, argName); checkNotEmpty(array.length, argName); } /** Validates that the given array is not null and has at least one element. */ public static void checkNotNullAndNotEmpty(int[] array, String argName) { Validate.checkNotNull(array, argName); checkNotEmpty(array.length, argName); } /** Validates that the given array is not null and has at least one element. */ public static void checkNotNullAndNotEmpty(long[] array, String argName) { Validate.checkNotNull(array, argName); checkNotEmpty(array.length, argName); } /** Validates that the given buffer is not null and has non-zero capacity. */ public static void checkNotNullAndNotEmpty(Iterable iter, String argName) { Validate.checkNotNull(iter, argName); int minNumElements = iter.iterator().hasNext() ? 1 : 0; checkNotEmpty(minNumElements, argName); } /** Validates that the given set is not null and has an exact number of items. */ public static void checkNotNullAndNumberOfElements( Collection collection, int numElements, String argName) { Validate.checkNotNull(collection, argName); checkArgument( collection.size() == numElements, "Number of elements in '%s' must be exactly %s, %s given.", argName, numElements, collection.size()); } /** Validates that the given two values are equal. */ public static void checkValuesEqual( long value1, String value1Name, long value2, String value2Name) { checkArgument( value1 == value2, "'%s' (%s) must equal '%s' (%s).", value1Name, value1, value2Name, value2); } /** Validates that the first value is an integer multiple of the second value. */ public static void checkIntegerMultiple( long value1, String value1Name, long value2, String value2Name) { checkArgument( (value1 % value2) == 0, "'%s' (%s) must be an integer multiple of '%s' (%s).", value1Name, value1, value2Name, value2); } /** Validates that the first value is greater than the second value. */ public static void checkGreater(long value1, String value1Name, long value2, String value2Name) { checkArgument( value1 > value2, "'%s' (%s) must be greater than '%s' (%s).", value1Name, value1, value2Name, value2); } /** Validates that the first value is greater than or equal to the second value. */ public static void checkGreaterOrEqual( long value1, String value1Name, long value2, String value2Name) { checkArgument( value1 >= value2, "'%s' (%s) must be greater than or equal to '%s' (%s).", value1Name, value1, value2Name, value2); } /** Validates that the first value is less than or equal to the second value. */ public static void checkLessOrEqual( long value1, String value1Name, long value2, String value2Name) { checkArgument( value1 <= value2, "'%s' (%s) must be less than or equal to '%s' (%s).", value1Name, value1, value2Name, value2); } /** Validates that the given value is within the given range of values. */ public static void checkWithinRange( long value, String valueName, long minValueInclusive, long maxValueInclusive) { checkArgument( (value >= minValueInclusive) && (value <= maxValueInclusive), "'%s' (%s) must be within the range [%s, %s].", valueName, value, minValueInclusive, maxValueInclusive); } /** Validates that the given value is within the given range of values. */ public static void checkWithinRange( double value, String valueName, double minValueInclusive, double maxValueInclusive) { checkArgument( (value >= minValueInclusive) && (value <= maxValueInclusive), "'%s' (%s) must be within the range [%s, %s].", valueName, value, minValueInclusive, maxValueInclusive); } public static void checkPathExists(Path path, String argName) { checkNotNull(path, argName); checkArgument(Files.exists(path), "Path %s (%s) does not exist.", argName, path); } public static void checkPathExistsAsDir(Path path, String argName) { checkPathExists(path, argName); checkArgument( Files.isDirectory(path), "Path %s (%s) must point to a directory.", argName, path); } public static void checkPathExistsAsFile(Path path, String argName) { checkPathExists(path, argName); checkArgument(Files.isRegularFile(path), "Path %s (%s) must point to a file.", argName, path); } public static void checkArgument(boolean expression, String format, Object... args) { org.apache.commons.lang3.Validate.isTrue(expression, format, args); } public static void checkState(boolean expression, String format, Object... args) { org.apache.commons.lang3.Validate.validState(expression, format, args); } private static void checkNotEmpty(int arraySize, String argName) { Validate.checkArgument(arraySize > 0, "'%s' must have at least one element.", argName); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/ThriftField.java0000644000000000000000000001267414303740367027256 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Holds name of a thrift field and of its sub-fields recursively. * *

This class is meant to be used in conjunction with {@code TDeserializer}. */ public class ThriftField { /** Name of this field as it appears in a thrift file. Case sensitive. */ public final String name; /** * List of sub-fields of this field. * *

This list should have only those sub-fields that need to be deserialized by the {@code * TDeserializer}. */ public final List fields; /** * Constructs a {@link ThriftField}. * * @param name the name of this field as it appears in a thrift file. Case sensitive. * @param fields List of sub-fields of this field. */ ThriftField(String name, List fields) { Validate.checkNotNullAndNotEmpty(name, "name"); Validate.checkNotNull(fields, "fields"); this.name = name; this.fields = Collections.unmodifiableList(fields); } /** Constructs a {@link ThriftField} that does not have any sub-fields. */ ThriftField(String name) { this(name, Collections.emptyList()); } // Internal-only constructor that does not mark fields as read-only. // That allows fromNames() to construct fields from names. // The actual value of allowFieldAdds is ignored. // It is used only for generating a different function signature. ThriftField(String name, List fields, boolean allowFieldAdds) { Validate.checkNotNullAndNotEmpty(name, "name"); Validate.checkNotNull(fields, "fields"); this.name = name; this.fields = fields; } private int hashcode = 0; @Override public int hashCode() { if (this.hashcode == 0) { int hc = this.name.toLowerCase().hashCode(); for (ThriftField subField : this.fields) { hc ^= subField.hashCode(); } this.hashcode = hc; } return this.hashcode; } @Override public boolean equals(Object o) { if (o == null) { return false; } if (!(o instanceof ThriftField)) { return false; } ThriftField other = (ThriftField) o; if (!this.name.equalsIgnoreCase(other.name)) { return false; } if (this.fields.size() != other.fields.size()) { return false; } for (int i = 0; i < this.fields.size(); i++) { if (!this.fields.get(i).equals(other.fields.get(i))) { return false; } } return true; } @Override public String toString() { return String.join(", ", this.getFieldNames()); } public List getFieldNames() { List fieldsList = new ArrayList<>(); if (this.fields.size() == 0) { fieldsList.add(this.name); } else { for (ThriftField f : this.fields) { for (String subF : f.getFieldNames()) { fieldsList.add(this.name + "." + subF); } } } return fieldsList; } /** * Generates and returns n-ary tree of fields and their sub-fields. * *

* * @param fieldNames collection of fully qualified field names. *

for example, In case of PinJoin thrift struct, the following are valid field names -- * signature -- pins.user.userId -- textSignal.termSignal.termDataMap * @return n-ary tree of fields and their sub-fields. */ public static List fromNames(Collection fieldNames) { Validate.checkNotNullAndNotEmpty(fieldNames, "fieldNames"); List fieldNamesList = new ArrayList<>(fieldNames); Collections.sort(fieldNamesList, String.CASE_INSENSITIVE_ORDER); List fields = new ArrayList<>(); for (String fieldName : fieldNamesList) { List tfields = fields; String[] tokens = fieldName.split("\\."); for (String token : tokens) { ThriftField field = findField(token, tfields); if (field == null) { field = new ThriftField(token, new ArrayList<>(), true); tfields.add(field); } tfields = field.fields; } } return makeReadOnly(fields); } private static ThriftField findField(String name, List fields) { for (ThriftField field : fields) { if (field.name.equalsIgnoreCase(name)) { return field; } } return null; } private static List makeReadOnly(List fields) { List result = new ArrayList<>(fields.size()); for (ThriftField field : fields) { ThriftField copy = new ThriftField(field.name, makeReadOnly(field.fields)); result.add(copy); } return Collections.unmodifiableList(result); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/partial/PartialThriftComparer.java0000644000000000000000000002314214303740367031310 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.thrift.TBase; import org.apache.thrift.protocol.TType; /** * Enables comparison of two TBase instances such that the comparison is limited to the subset of * fields defined by the supplied metadata. * *

This comparer is useful when comparing two instances where: -- one is generated by full * deserialization. -- the other is generated by partial deserialization. * *

The typical use case is to establish correctness of partial deserialization. */ public class PartialThriftComparer { private enum ComparisonResult { UNKNOWN, EQUAL, NOT_EQUAL } // Metadata that defines the scope of comparison. private ThriftMetadata.ThriftStruct metadata; /** * Constructs an instance of {@link PartialThriftComparer}. * * @param metadata defines the scope of comparison. */ public PartialThriftComparer(ThriftMetadata.ThriftStruct metadata) { this.metadata = metadata; } /** * Compares thrift objects {@code t1} and {@code t2} and returns true if they are equal false * otherwise. The comparison is limited to the scope defined by {@code metadata}. * *

If the objects are not equal then it optionally records their differences if {@code sb} is * supplied. * *

* * @param t1 the first object. * @param t2 the second object. * @param sb if non-null, results of the comparison are returned in it. * @return true if objects are equivalent, false otherwise. */ public boolean areEqual(T t1, T t2, StringBuilder sb) { return this.areEqual(this.metadata, t1, t2, sb); } private boolean areEqual( ThriftMetadata.ThriftObject data, Object o1, Object o2, StringBuilder sb) { byte fieldType = data.data.valueMetaData.type; switch (fieldType) { case TType.STRUCT: return this.areEqual((ThriftMetadata.ThriftStruct) data, o1, o2, sb); case TType.LIST: return this.areEqual((ThriftMetadata.ThriftList) data, o1, o2, sb); case TType.MAP: return this.areEqual((ThriftMetadata.ThriftMap) data, o1, o2, sb); case TType.SET: return this.areEqual((ThriftMetadata.ThriftSet) data, o1, o2, sb); case TType.ENUM: return this.areEqual((ThriftMetadata.ThriftEnum) data, o1, o2, sb); case TType.BOOL: case TType.BYTE: case TType.I16: case TType.I32: case TType.I64: case TType.DOUBLE: case TType.STRING: return this.areEqual((ThriftMetadata.ThriftPrimitive) data, o1, o2, sb); default: throw unsupportedFieldTypeException(fieldType); } } private boolean areEqual( ThriftMetadata.ThriftStruct data, Object o1, Object o2, StringBuilder sb) { ComparisonResult result = checkNullEquality(data, o1, o2, sb); if (result != ComparisonResult.UNKNOWN) { return result == ComparisonResult.EQUAL; } TBase t1 = (TBase) o1; TBase t2 = (TBase) o2; if (data.fields.size() == 0) { if (t1.equals(t2)) { return true; } else { appendNotEqual(data, sb, t1, t2, "struct1", "struct2"); return false; } } else { boolean overallResult = true; for (Object o : data.fields.values()) { ThriftMetadata.ThriftObject field = (ThriftMetadata.ThriftObject) o; Object f1 = t1.getFieldValue(field.fieldId); Object f2 = t2.getFieldValue(field.fieldId); overallResult = overallResult && this.areEqual(field, f1, f2, sb); } return overallResult; } } private boolean areEqual( ThriftMetadata.ThriftPrimitive data, Object o1, Object o2, StringBuilder sb) { ComparisonResult result = checkNullEquality(data, o1, o2, sb); if (result != ComparisonResult.UNKNOWN) { return result == ComparisonResult.EQUAL; } if (data.isBinary()) { if (areBinaryFieldsEqual(o1, o2)) { return true; } } else if (o1.equals(o2)) { return true; } appendNotEqual(data, sb, o1, o2, "o1", "o2"); return false; } private boolean areEqual(ThriftMetadata.ThriftEnum data, Object o1, Object o2, StringBuilder sb) { ComparisonResult result = checkNullEquality(data, o1, o2, sb); if (result != ComparisonResult.UNKNOWN) { return result == ComparisonResult.EQUAL; } if (o1.equals(o2)) { return true; } appendNotEqual(data, sb, o1, o2, "o1", "o2"); return false; } private boolean areEqual(ThriftMetadata.ThriftList data, Object o1, Object o2, StringBuilder sb) { List l1 = (List) o1; List l2 = (List) o2; ComparisonResult result = checkNullEquality(data, o1, o2, sb); if (result != ComparisonResult.UNKNOWN) { return result == ComparisonResult.EQUAL; } if (!checkSizeEquality(data, l1, l2, sb, "list")) { return false; } for (int i = 0; i < l1.size(); i++) { Object e1 = l1.get(i); Object e2 = l2.get(i); if (!this.areEqual(data.elementData, e1, e2, sb)) { return false; } } return true; } private boolean areEqual(ThriftMetadata.ThriftSet data, Object o1, Object o2, StringBuilder sb) { Set s1 = (Set) o1; Set s2 = (Set) o2; ComparisonResult result = checkNullEquality(data, o1, o2, sb); if (result != ComparisonResult.UNKNOWN) { return result == ComparisonResult.EQUAL; } if (!checkSizeEquality(data, s1, s2, sb, "set")) { return false; } for (Object e1 : s1) { if (!s2.contains(e1)) { appendResult(data, sb, "Element %s in s1 not found in s2", e1); return false; } } return true; } private boolean areEqual(ThriftMetadata.ThriftMap data, Object o1, Object o2, StringBuilder sb) { Map m1 = (Map) o1; Map m2 = (Map) o2; ComparisonResult result = checkNullEquality(data, o1, o2, sb); if (result != ComparisonResult.UNKNOWN) { return result == ComparisonResult.EQUAL; } if (!checkSizeEquality(data, m1.keySet(), m2.keySet(), sb, "map.keySet")) { return false; } for (Map.Entry e1 : m1.entrySet()) { Object k1 = e1.getKey(); if (!m2.containsKey(k1)) { appendResult(data, sb, "Key %s in m1 not found in m2", k1); return false; } Object v1 = e1.getValue(); Object v2 = m2.get(k1); if (!this.areEqual(data.valueData, v1, v2, sb)) { return false; } } return true; } private boolean areBinaryFieldsEqual(Object o1, Object o2) { if (o1 instanceof byte[]) { if (Arrays.equals((byte[]) o1, (byte[]) o2)) { return true; } } else if (o1 instanceof ByteBuffer) { if (((ByteBuffer) o1).compareTo((ByteBuffer) o2) == 0) { return true; } } else { throw new UnsupportedOperationException( String.format("Unsupported binary field type: %s", o1.getClass().getName())); } return false; } private void appendResult( ThriftMetadata.ThriftObject data, StringBuilder sb, String format, Object... args) { if (sb != null) { String msg = String.format(format, args); sb.append(data.fieldId.getFieldName()); sb.append(" : "); sb.append(msg); } } private void appendNotEqual( ThriftMetadata.ThriftObject data, StringBuilder sb, Object o1, Object o2, String o1name, String o2name) { String o1s = o1.toString(); String o2s = o2.toString(); if ((o1s.length() + o2s.length()) < 100) { appendResult(data, sb, "%s (%s) != %s (%s)", o1name, o1s, o2name, o2s); } else { appendResult( data, sb, "%s != %s\n%s =\n%s\n%s =\n%s\n", o1name, o2name, o1name, o1s, o2name, o2s); } } private ComparisonResult checkNullEquality( ThriftMetadata.ThriftObject data, Object o1, Object o2, StringBuilder sb) { if ((o1 == null) && (o2 == null)) { return ComparisonResult.EQUAL; } if (o1 == null) { appendResult(data, sb, "o1 (null) != o2"); } if (o2 == null) { appendResult(data, sb, "o1 != o2 (null)"); } return ComparisonResult.UNKNOWN; } private boolean checkSizeEquality( ThriftMetadata.ThriftObject data, Collection c1, Collection c2, StringBuilder sb, String typeName) { if (c1.size() != c2.size()) { appendResult( data, sb, "%s1.size(%d) != %s2.size(%d)", typeName, c1.size(), typeName, c2.size()); return false; } return true; } static UnsupportedOperationException unsupportedFieldTypeException(byte fieldType) { return new UnsupportedOperationException("field type not supported: '" + fieldType + "'"); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/scheme/0000777000000000000000000000000014370300523023777 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/scheme/IScheme.java0000644000000000000000000000216514370300523026157 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.scheme; import org.apache.thrift.TBase; public interface IScheme { void read(org.apache.thrift.protocol.TProtocol iproto, T struct) throws org.apache.thrift.TException; void write(org.apache.thrift.protocol.TProtocol oproto, T struct) throws org.apache.thrift.TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/scheme/StandardScheme.java0000644000000000000000000000166714303740367027547 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.scheme; import org.apache.thrift.TBase; public abstract class StandardScheme implements IScheme {} thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/scheme/TupleScheme.java0000644000000000000000000000166414303740367027075 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.scheme; import org.apache.thrift.TBase; public abstract class TupleScheme implements IScheme {} thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/scheme/SchemeFactory.java0000644000000000000000000000162014370300523027371 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.scheme; public interface SchemeFactory { S getScheme(); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TServiceClient.java0000644000000000000000000000571614303740367026300 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TMessage; import org.apache.thrift.protocol.TMessageType; import org.apache.thrift.protocol.TProtocol; /** * A TServiceClient is used to communicate with a TService implementation across protocols and * transports. */ public abstract class TServiceClient { public TServiceClient(TProtocol prot) { this(prot, prot); } public TServiceClient(TProtocol iprot, TProtocol oprot) { iprot_ = iprot; oprot_ = oprot; } protected TProtocol iprot_; protected TProtocol oprot_; protected int seqid_; /** * Get the TProtocol being used as the input (read) protocol. * * @return the TProtocol being used as the input (read) protocol. */ public TProtocol getInputProtocol() { return this.iprot_; } /** * Get the TProtocol being used as the output (write) protocol. * * @return the TProtocol being used as the output (write) protocol. */ public TProtocol getOutputProtocol() { return this.oprot_; } protected void sendBase(String methodName, TBase args) throws TException { sendBase(methodName, args, TMessageType.CALL); } protected void sendBaseOneway(String methodName, TBase args) throws TException { sendBase(methodName, args, TMessageType.ONEWAY); } private void sendBase(String methodName, TBase args, byte type) throws TException { oprot_.writeMessageBegin(new TMessage(methodName, type, ++seqid_)); args.write(oprot_); oprot_.writeMessageEnd(); oprot_.getTransport().flush(); } protected void receiveBase(TBase result, String methodName) throws TException { TMessage msg = iprot_.readMessageBegin(); if (msg.type == TMessageType.EXCEPTION) { TApplicationException x = new TApplicationException(); x.read(iprot_); iprot_.readMessageEnd(); throw x; } if (msg.seqid != seqid_) { throw new TApplicationException( TApplicationException.BAD_SEQUENCE_ID, String.format( "%s failed: out of sequence response: expected %d but got %d", methodName, seqid_, msg.seqid)); } result.read(iprot_); iprot_.readMessageEnd(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TDeserializer.java0000644000000000000000000006475414303740367026172 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.Collection; import org.apache.thrift.meta_data.EnumMetaData; import org.apache.thrift.meta_data.StructMetaData; import org.apache.thrift.partial.TFieldData; import org.apache.thrift.partial.ThriftFieldValueProcessor; import org.apache.thrift.partial.ThriftMetadata; import org.apache.thrift.partial.ThriftStructProcessor; import org.apache.thrift.partial.Validate; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TField; import org.apache.thrift.protocol.TList; import org.apache.thrift.protocol.TMap; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.protocol.TProtocolUtil; import org.apache.thrift.protocol.TSet; import org.apache.thrift.protocol.TType; import org.apache.thrift.transport.TMemoryInputTransport; import org.apache.thrift.transport.TTransportException; /** Generic utility for easily deserializing objects from a byte array or Java String. */ public class TDeserializer { private final TProtocol protocol_; private final TMemoryInputTransport trans_; // Metadata that describes fields to deserialize during partial deserialization. private ThriftMetadata.ThriftStruct metadata_ = null; // Processor that handles deserialized field values during partial deserialization. private ThriftFieldValueProcessor processor_ = null; /** * Create a new TDeserializer that uses the TBinaryProtocol by default. * * @throws TTransportException if there an error initializing the underlying transport. */ public TDeserializer() throws TTransportException { this(new TBinaryProtocol.Factory()); } /** * Create a new TDeserializer. It will use the TProtocol specified by the factory that is passed * in. * * @param protocolFactory Factory to create a protocol * @throws TTransportException if there an error initializing the underlying transport. */ public TDeserializer(TProtocolFactory protocolFactory) throws TTransportException { trans_ = new TMemoryInputTransport(new TConfiguration()); protocol_ = protocolFactory.getProtocol(trans_); } /** * Construct a new TDeserializer that supports partial deserialization that outputs instances of * type controlled by the given {@code processor}. * * @param thriftClass a TBase derived class. * @param fieldNames list of fields to deserialize. * @param processor the Processor that handles deserialized field values. * @param protocolFactory the Factory to create a protocol. */ public TDeserializer( Class thriftClass, Collection fieldNames, ThriftFieldValueProcessor processor, TProtocolFactory protocolFactory) throws TTransportException { this(protocolFactory); Validate.checkNotNull(thriftClass, "thriftClass"); Validate.checkNotNull(fieldNames, "fieldNames"); Validate.checkNotNull(processor, "processor"); metadata_ = ThriftMetadata.ThriftStruct.fromFieldNames(thriftClass, fieldNames); processor_ = processor; } /** * Construct a new TDeserializer that supports partial deserialization that outputs {@code TBase} * instances. * * @param thriftClass a TBase derived class. * @param fieldNames list of fields to deserialize. * @param protocolFactory the Factory to create a protocol. */ public TDeserializer( Class thriftClass, Collection fieldNames, TProtocolFactory protocolFactory) throws TTransportException { this(thriftClass, fieldNames, new ThriftStructProcessor(), protocolFactory); } /** * Gets the metadata used for partial deserialization. * * @return the metadata used for partial deserialization. */ public ThriftMetadata.ThriftStruct getMetadata() { return metadata_; } /** * Deserialize the Thrift object from a byte array. * * @param base The object to read into * @param bytes The array to read from * @throws TException if an error is encountered during deserialization. */ public void deserialize(TBase base, byte[] bytes) throws TException { deserialize(base, bytes, 0, bytes.length); } /** * Deserialize the Thrift object from a byte array. * * @param base The object to read into * @param bytes The array to read from * @param offset The offset into {@code bytes} * @param length The length to read from {@code bytes} * @throws TException if an error is encountered during deserialization. */ public void deserialize(TBase base, byte[] bytes, int offset, int length) throws TException { if (this.isPartialDeserializationMode()) { this.partialDeserializeThriftObject(base, bytes, offset, length); } else { try { trans_.reset(bytes, offset, length); base.read(protocol_); } finally { trans_.clear(); protocol_.reset(); } } } /** * Deserialize the Thrift object from a Java string, using a specified character set for decoding. * * @param base The object to read into * @param data The string to read from * @param charset Valid JVM charset * @throws TException if an error is encountered during deserialization. */ public void deserialize(TBase base, String data, String charset) throws TException { try { deserialize(base, data.getBytes(charset)); } catch (UnsupportedEncodingException uex) { throw new TException("JVM DOES NOT SUPPORT ENCODING: " + charset); } finally { protocol_.reset(); } } /** * Deserialize only a single Thrift object (addressed by recursively using field id) from a byte * record. * * @param tb The object to read into * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path tb * @param fieldIdPathRest The rest FieldId's that define a path tb * @throws TException if an error is encountered during deserialization. */ public void partialDeserialize( TBase tb, byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { try { if (locateField(bytes, fieldIdPathFirst, fieldIdPathRest) != null) { // if this line is reached, iprot will be positioned at the start of tb. tb.read(protocol_); } } catch (Exception e) { throw new TException(e); } finally { trans_.clear(); protocol_.reset(); } } /** * Deserialize only a boolean field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to a boolean field * @param fieldIdPathRest The rest FieldId's that define a path to a boolean field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Boolean partialDeserializeBool( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (Boolean) partialDeserializeField(TType.BOOL, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only a byte field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to a byte field * @param fieldIdPathRest The rest FieldId's that define a path to a byte field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Byte partialDeserializeByte( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (Byte) partialDeserializeField(TType.BYTE, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only a double field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to a double field * @param fieldIdPathRest The rest FieldId's that define a path to a double field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Double partialDeserializeDouble( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (Double) partialDeserializeField(TType.DOUBLE, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only an i16 field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to an i16 field * @param fieldIdPathRest The rest FieldId's that define a path to an i16 field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Short partialDeserializeI16( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (Short) partialDeserializeField(TType.I16, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only an i32 field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to an i32 field * @param fieldIdPathRest The rest FieldId's that define a path to an i32 field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Integer partialDeserializeI32( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (Integer) partialDeserializeField(TType.I32, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only an i64 field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to an i64 field * @param fieldIdPathRest The rest FieldId's that define a path to an i64 field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Long partialDeserializeI64( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (Long) partialDeserializeField(TType.I64, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only a string field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to a string field * @param fieldIdPathRest The rest FieldId's that define a path to a string field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public String partialDeserializeString( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { return (String) partialDeserializeField(TType.STRING, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only a binary field (addressed by recursively using field id) from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to a binary field * @param fieldIdPathRest The rest FieldId's that define a path to a binary field * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public ByteBuffer partialDeserializeByteArray( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { // TType does not have binary, so we use the arbitrary num 100 return (ByteBuffer) partialDeserializeField((byte) 100, bytes, fieldIdPathFirst, fieldIdPathRest); } /** * Deserialize only the id of the field set in a TUnion (addressed by recursively using field id) * from a byte record. * * @param bytes The serialized object to read from * @param fieldIdPathFirst First of the FieldId's that define a path to a TUnion * @param fieldIdPathRest The rest FieldId's that define a path to a TUnion * @return the deserialized value. * @throws TException if an error is encountered during deserialization. */ public Short partialDeserializeSetFieldIdInUnion( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { try { TField field = locateField(bytes, fieldIdPathFirst, fieldIdPathRest); if (field != null) { protocol_.readStructBegin(); // The Union return protocol_.readFieldBegin().id; // The field set in the union } return null; } catch (Exception e) { throw new TException(e); } finally { trans_.clear(); protocol_.reset(); } } private Object partialDeserializeField( byte ttype, byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { try { TField field = locateField(bytes, fieldIdPathFirst, fieldIdPathRest); if (field != null) { if (ttype == field.type) { // if this point is reached, iprot will be positioned at the start of // the field switch (ttype) { case TType.BOOL: return protocol_.readBool(); case TType.BYTE: return protocol_.readByte(); case TType.DOUBLE: return protocol_.readDouble(); case TType.I16: return protocol_.readI16(); case TType.I32: return protocol_.readI32(); case TType.I64: return protocol_.readI64(); case TType.STRING: return protocol_.readString(); default: return null; } } // hack to differentiate between string and binary if (ttype == 100 && field.type == TType.STRING) { return protocol_.readBinary(); } } return null; } catch (Exception e) { throw new TException(e); } finally { trans_.clear(); protocol_.reset(); } } private TField locateField( byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { trans_.reset(bytes); TFieldIdEnum[] fieldIdPath = new TFieldIdEnum[fieldIdPathRest.length + 1]; fieldIdPath[0] = fieldIdPathFirst; System.arraycopy(fieldIdPathRest, 0, fieldIdPath, 1, fieldIdPathRest.length); // index into field ID path being currently searched for int curPathIndex = 0; // this will be the located field, or null if it is not located TField field = null; protocol_.readStructBegin(); while (curPathIndex < fieldIdPath.length) { field = protocol_.readFieldBegin(); // we can stop searching if we either see a stop or we go past the field // id we're looking for (since fields should now be serialized in asc // order). if (field.type == TType.STOP || field.id > fieldIdPath[curPathIndex].getThriftFieldId()) { return null; } if (field.id != fieldIdPath[curPathIndex].getThriftFieldId()) { // Not the field we're looking for. Skip field. TProtocolUtil.skip(protocol_, field.type); protocol_.readFieldEnd(); } else { // This field is the next step in the path. Step into field. curPathIndex++; if (curPathIndex < fieldIdPath.length) { protocol_.readStructBegin(); } } } return field; } /** * Deserialize the Thrift object from a Java string, using the default JVM charset encoding. * * @param base The object to read into * @param data The string to read from * @throws TException if an error is encountered during deserialization. */ public void fromString(TBase base, String data) throws TException { deserialize(base, data.getBytes()); } // ---------------------------------------------------------------------- // Methods related to partial deserialization. /** * Partially deserializes the given serialized blob. * * @param bytes the serialized blob. * @return deserialized instance. * @throws TException if an error is encountered during deserialization. */ public Object partialDeserializeObject(byte[] bytes) throws TException { return this.partialDeserializeObject(bytes, 0, bytes.length); } /** * Partially deserializes the given serialized blob into the given {@code TBase} instance. * * @param base the instance into which the given blob is deserialized. * @param bytes the serialized blob. * @param offset the blob is read starting at this offset. * @param length the size of blob read (in number of bytes). * @return deserialized instance. * @throws TException if an error is encountered during deserialization. */ public Object partialDeserializeThriftObject(TBase base, byte[] bytes, int offset, int length) throws TException { ensurePartialThriftDeserializationMode(); return this.partialDeserializeObject(base, bytes, offset, length); } /** * Partially deserializes the given serialized blob. * * @param bytes the serialized blob. * @param offset the blob is read starting at this offset. * @param length the size of blob read (in number of bytes). * @return deserialized instance. * @throws TException if an error is encountered during deserialization. */ public Object partialDeserializeObject(byte[] bytes, int offset, int length) throws TException { ensurePartialDeserializationMode(); return this.partialDeserializeObject(null, bytes, offset, length); } /** * Partially deserializes the given serialized blob. * * @param instance the instance into which the given blob is deserialized. * @param bytes the serialized blob. * @param offset the blob is read starting at this offset. * @param length the size of blob read (in number of bytes). * @return deserialized instance. * @throws TException if an error is encountered during deserialization. */ private Object partialDeserializeObject(Object instance, byte[] bytes, int offset, int length) throws TException { ensurePartialDeserializationMode(); this.trans_.reset(bytes, offset, length); this.protocol_.reset(); return this.deserializeStruct(instance, this.metadata_); } private Object deserialize(ThriftMetadata.ThriftObject data) throws TException { Object value; byte fieldType = data.data.valueMetaData.type; switch (fieldType) { case TType.STRUCT: return this.deserializeStruct(null, (ThriftMetadata.ThriftStruct) data); case TType.LIST: return this.deserializeList((ThriftMetadata.ThriftList) data); case TType.MAP: return this.deserializeMap((ThriftMetadata.ThriftMap) data); case TType.SET: return this.deserializeSet((ThriftMetadata.ThriftSet) data); case TType.ENUM: return this.deserializeEnum((ThriftMetadata.ThriftEnum) data); case TType.BOOL: return this.protocol_.readBool(); case TType.BYTE: return this.protocol_.readByte(); case TType.I16: return this.protocol_.readI16(); case TType.I32: return this.protocol_.readI32(); case TType.I64: return this.protocol_.readI64(); case TType.DOUBLE: return this.protocol_.readDouble(); case TType.STRING: if (((ThriftMetadata.ThriftPrimitive) data).isBinary()) { return this.processor_.prepareBinary(this.protocol_.readBinary()); } else { return this.processor_.prepareString(this.protocol_.readBinary()); } default: throw unsupportedFieldTypeException(fieldType); } } private Object deserializeStruct(Object instance, ThriftMetadata.ThriftStruct data) throws TException { if (instance == null) { instance = this.processor_.createNewStruct(data); } this.protocol_.readStructBegin(); while (true) { int tfieldData = this.protocol_.readFieldBeginData(); byte tfieldType = TFieldData.getType(tfieldData); if (tfieldType == TType.STOP) { break; } Integer id = (int) TFieldData.getId(tfieldData); ThriftMetadata.ThriftObject field = (ThriftMetadata.ThriftObject) data.fields.get(id); if (field != null) { this.deserializeStructField(instance, field.fieldId, field); } else { this.protocol_.skip(tfieldType); } this.protocol_.readFieldEnd(); } this.protocol_.readStructEnd(); return this.processor_.prepareStruct(instance); } private void deserializeStructField( Object instance, TFieldIdEnum fieldId, ThriftMetadata.ThriftObject data) throws TException { byte fieldType = data.data.valueMetaData.type; Object value; switch (fieldType) { case TType.BOOL: this.processor_.setBool(instance, fieldId, this.protocol_.readBool()); break; case TType.BYTE: this.processor_.setByte(instance, fieldId, this.protocol_.readByte()); break; case TType.I16: this.processor_.setInt16(instance, fieldId, this.protocol_.readI16()); break; case TType.I32: this.processor_.setInt32(instance, fieldId, this.protocol_.readI32()); break; case TType.I64: this.processor_.setInt64(instance, fieldId, this.protocol_.readI64()); break; case TType.DOUBLE: this.processor_.setDouble(instance, fieldId, this.protocol_.readDouble()); break; case TType.STRING: if (((ThriftMetadata.ThriftPrimitive) data).isBinary()) { this.processor_.setBinary(instance, fieldId, this.protocol_.readBinary()); } else { this.processor_.setString(instance, fieldId, this.protocol_.readBinary()); } break; case TType.STRUCT: value = this.deserializeStruct(null, (ThriftMetadata.ThriftStruct) data); this.processor_.setStructField(instance, fieldId, value); break; case TType.LIST: value = this.deserializeList((ThriftMetadata.ThriftList) data); this.processor_.setListField(instance, fieldId, value); break; case TType.MAP: value = this.deserializeMap((ThriftMetadata.ThriftMap) data); this.processor_.setMapField(instance, fieldId, value); break; case TType.SET: value = this.deserializeSet((ThriftMetadata.ThriftSet) data); this.processor_.setSetField(instance, fieldId, value); break; case TType.ENUM: value = this.deserializeEnum((ThriftMetadata.ThriftEnum) data); this.processor_.setEnumField(instance, fieldId, value); break; default: throw new RuntimeException("Unsupported field type: " + fieldId.toString()); } } private Object deserializeList(ThriftMetadata.ThriftList data) throws TException { TList tlist = this.protocol_.readListBegin(); Object instance = this.processor_.createNewList(tlist.size); for (int i = 0; i < tlist.size; i++) { Object value = this.deserialize(data.elementData); this.processor_.setListElement(instance, i, value); } this.protocol_.readListEnd(); return this.processor_.prepareList(instance); } private Object deserializeMap(ThriftMetadata.ThriftMap data) throws TException { TMap tmap = this.protocol_.readMapBegin(); Object instance = this.processor_.createNewMap(tmap.size); for (int i = 0; i < tmap.size; i++) { Object key = this.deserialize(data.keyData); Object val = this.deserialize(data.valueData); this.processor_.setMapElement(instance, i, key, val); } this.protocol_.readMapEnd(); return this.processor_.prepareMap(instance); } private Object deserializeSet(ThriftMetadata.ThriftSet data) throws TException { TSet tset = this.protocol_.readSetBegin(); Object instance = this.processor_.createNewSet(tset.size); for (int i = 0; i < tset.size; i++) { Object eltValue = this.deserialize(data.elementData); this.processor_.setSetElement(instance, i, eltValue); } this.protocol_.readSetEnd(); return this.processor_.prepareSet(instance); } private Object deserializeEnum(ThriftMetadata.ThriftEnum data) throws TException { int ordinal = this.protocol_.readI32(); Class enumClass = ((EnumMetaData) data.data.valueMetaData).enumClass; return this.processor_.prepareEnum(enumClass, ordinal); } private Class getStructClass(ThriftMetadata.ThriftStruct data) { return (Class) ((StructMetaData) data.data.valueMetaData).structClass; } private static UnsupportedOperationException unsupportedFieldTypeException(byte fieldType) { return new UnsupportedOperationException("field type not supported: " + fieldType); } private boolean isPartialDeserializationMode() { return (this.metadata_ != null) && (this.processor_ != null); } private void ensurePartialDeserializationMode() throws IllegalStateException { if (!this.isPartialDeserializationMode()) { throw new IllegalStateException( "Members metadata and processor must be correctly initialized in order to use this method"); } } private void ensurePartialThriftDeserializationMode() throws IllegalStateException { this.ensurePartialDeserializationMode(); if (!(this.processor_ instanceof ThriftStructProcessor)) { throw new IllegalStateException( "processor must be an instance of ThriftStructProcessor to use this method"); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TBase.java0000644000000000000000000000436214370300523024375 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.Serializable; /** Generic base interface for generated Thrift objects. */ public interface TBase, F extends TFieldIdEnum> extends Comparable, TSerializable, Serializable { /** * Get the F instance that corresponds to fieldId. * * @param fieldId the ID of the requested field. * @return F instance that corresponds to fieldId. */ F fieldForId(int fieldId); /** * Check if a field is currently set or unset. * * @param field the field to check. * @return true if the field is set, false otherwise. */ boolean isSet(F field); /** * Get a field's value by field variable. Primitive types will be wrapped in the appropriate * "boxed" types. * * @param field the field whose value is requested. * @return the value of the requested field. */ Object getFieldValue(F field); /** * Set a field's value by field variable. Primitive types must be "boxed" in the appropriate * object wrapper type. * * @param field the field whose value is to be set. * @param value the value to be assigned to field. */ void setFieldValue(F field, Object value); /** * Performs a deep copy of this instance and returns the copy. * * @return a deep copy of this instance. */ T deepCopy(); /** * Return to the state of having just been initialized, as though you had just called the default * constructor. */ void clear(); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/0000777000000000000000000000000014303740367024464 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/FieldMetaData.java0000644000000000000000000001021414303740367027745 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import java.util.Collections; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.apache.thrift.TBase; import org.apache.thrift.TFieldIdEnum; /** * This class is used to store meta data about thrift fields. Every field in a a struct should have * a corresponding instance of this class describing it. * *

The meta data is registered by ALL Thrift struct classes via a static {...} initializer block * in the generated Thrift code. * *

Since different threads could be initializing different Thrift classes, calls to the public * static methods of this class could be racy. * *

All methods of this class should be made thread safe. */ public class FieldMetaData implements java.io.Serializable { public final String fieldName; public final byte requirementType; public final FieldValueMetaData valueMetaData; private final Map fieldAnnotations; private static final ConcurrentMap< Class, Map> structMap = new ConcurrentHashMap<>(); public FieldMetaData(String name, byte req, FieldValueMetaData vMetaData) { this(name, req, vMetaData, Collections.emptyMap()); } public FieldMetaData( String fieldName, byte requirementType, FieldValueMetaData valueMetaData, Map fieldAnnotations) { this.fieldName = fieldName; this.requirementType = requirementType; this.valueMetaData = valueMetaData; this.fieldAnnotations = fieldAnnotations; } /** * @return an unmodifiable view of the annotations for this field, empty if no annotations present * or code gen param is not turned on */ public Map getFieldAnnotations() { return Collections.unmodifiableMap(fieldAnnotations); } public static , F extends TFieldIdEnum> void addStructMetaDataMap( Class sClass, Map map) { structMap.put(sClass, map); } /** * Returns a map with metadata (i.e. instances of FieldMetaData) that describe the fields of the * given class. * * @param sClass The TBase class for which the metadata map is requested. It is not guaranteed * that sClass will have been statically initialized before this method is called. A racy call * to {@link FieldMetaData#addStructMetaDataMap(Class, Map)} from a different thread during * static initialization of the Thrift class is possible. */ public static , F extends TFieldIdEnum> Map getStructMetaDataMap(Class sClass) { // Note: Do not use synchronized on this method declaration - it leads to a deadlock. // Similarly, do not trigger sClass.newInstance() while holding a lock on structMap, // it will lead to the same deadlock. // See: https://issues.apache.org/jira/browse/THRIFT-5430 for details. if (!structMap.containsKey(sClass)) { // Load class if it hasn't been loaded try { sClass.getDeclaredConstructor().newInstance(); } catch (ReflectiveOperationException e) { throw new RuntimeException( e.getClass().getSimpleName() + " for TBase class: " + sClass.getName(), e); } } //noinspection unchecked return (Map) structMap.get(sClass); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/SetMetaData.java0000644000000000000000000000205414303740367027460 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; public class SetMetaData extends FieldValueMetaData { public final FieldValueMetaData elemMetaData; public SetMetaData(byte type, FieldValueMetaData eMetaData) { super(type); this.elemMetaData = eMetaData; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/StructMetaData.java0000644000000000000000000000212314303740367030206 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.TBase; public class StructMetaData extends FieldValueMetaData { public final Class structClass; public StructMetaData(byte type, Class sClass) { super(type); this.structClass = sClass; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/EnumMetaData.java0000644000000000000000000000211314303740367027625 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.TEnum; public class EnumMetaData extends FieldValueMetaData { public final Class enumClass; public EnumMetaData(byte type, Class sClass) { super(type); this.enumClass = sClass; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/ListMetaData.java0000644000000000000000000000205614303740367027642 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; public class ListMetaData extends FieldValueMetaData { public final FieldValueMetaData elemMetaData; public ListMetaData(byte type, FieldValueMetaData eMetaData) { super(type); this.elemMetaData = eMetaData; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/FieldValueMetaData.java0000644000000000000000000000367514303740367030757 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; import org.apache.thrift.protocol.TType; /** * FieldValueMetaData and collection of subclasses to store metadata about the value(s) of a field */ public class FieldValueMetaData implements java.io.Serializable { public final byte type; private final boolean isTypedefType; private final String typedefName; private final boolean isBinary; public FieldValueMetaData(byte type, boolean binary) { this.type = type; this.isTypedefType = false; this.typedefName = null; this.isBinary = binary; } public FieldValueMetaData(byte type) { this(type, false); } public FieldValueMetaData(byte type, String typedefName) { this.type = type; this.isTypedefType = true; this.typedefName = typedefName; this.isBinary = false; } public boolean isTypedef() { return isTypedefType; } public String getTypedefName() { return typedefName; } public boolean isStruct() { return type == TType.STRUCT; } public boolean isContainer() { return type == TType.LIST || type == TType.MAP || type == TType.SET; } public boolean isBinary() { return isBinary; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/meta_data/MapMetaData.java0000644000000000000000000000223514303740367027443 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.meta_data; public class MapMetaData extends FieldValueMetaData { public final FieldValueMetaData keyMetaData; public final FieldValueMetaData valueMetaData; public MapMetaData(byte type, FieldValueMetaData kMetaData, FieldValueMetaData vMetaData) { super(type); this.keyMetaData = kMetaData; this.valueMetaData = vMetaData; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/Option.java0000644000000000000000000000672214303740367024663 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.util.Optional; /** Implementation of the Option type pattern */ public abstract class Option { @SuppressWarnings("rawtypes") private static final Option NONE = new None(); /** * Whether the Option is defined or not * * @return true if the Option is defined (of type Some) false if the Option is not defined (of * type None) */ public abstract boolean isDefined(); /** * Get the value of the Option (if it is defined) * * @return the value * @throws IllegalStateException if called on a None */ public abstract T get(); /** * Get the contained value (if defined) or else return a default value * * @param other what to return if the value is not defined (a None) * @return either the value, or other if the value is not defined */ public T or(T other) { if (isDefined()) { return get(); } else { return other; } } /** * Turn this Option into Java 8 Optional type * * @return Java 8+ Optional Type */ public Optional toOptional() { if (isDefined()) { return Optional.of(get()); } else { return Optional.empty(); } } /** The None type, representing an absent value (instead of "null") */ public static class None extends Option { public boolean isDefined() { return false; } public T get() { throw new IllegalStateException("Cannot call get() on None"); } public String toString() { return "None"; } } /** * The Some type, representing an existence of some value * * @param The type of value */ public static class Some extends Option { private final T value; public Some(T value) { this.value = value; } public boolean isDefined() { return true; } public T get() { return value; } public String toString() { return "Some(" + value + ")"; } } /** * Wraps value in an Option type, depending on whether or not value is null * * @param value the value to wrap in Option * @param the type of value * @return Some(value) if value is not null, None if value is null */ public static Option fromNullable(T value) { if (value != null) { return some(value); } else { return none(); } } /** * Wrap value in a Some type (NB! value must not be null!) * * @param value the value to wrap. * @param the type of value * @return a new Some(value) */ public static Some some(T value) { return new Some(value); } @SuppressWarnings("unchecked") public static None none() { return (None) NONE; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TBaseProcessor.java0000644000000000000000000000270014303740367026301 0ustar00rootroot00000000000000package org.apache.thrift; import java.util.Collections; import java.util.Map; import org.apache.thrift.protocol.TMessage; import org.apache.thrift.protocol.TMessageType; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolUtil; import org.apache.thrift.protocol.TType; public abstract class TBaseProcessor implements TProcessor { private final I iface; private final Map> processMap; protected TBaseProcessor( I iface, Map> processFunctionMap) { this.iface = iface; this.processMap = processFunctionMap; } public Map> getProcessMapView() { return Collections.unmodifiableMap(processMap); } @Override public void process(TProtocol in, TProtocol out) throws TException { TMessage msg = in.readMessageBegin(); ProcessFunction fn = processMap.get(msg.name); if (fn == null) { TProtocolUtil.skip(in, TType.STRUCT); in.readMessageEnd(); TApplicationException x = new TApplicationException( TApplicationException.UNKNOWN_METHOD, "Invalid method name: '" + msg.name + "'"); out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); x.write(out); out.writeMessageEnd(); out.getTransport().flush(); } else { fn.process(msg.seqid, in, out, iface); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/utils/0000777000000000000000000000000014303740367023705 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/utils/StringUtils.java0000644000000000000000000000455014303740367027037 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.utils; public final class StringUtils { private StringUtils() { // Utility class. } private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * Stringify a byte array to the hex representation for each byte. * * @param bytes the byte array to convert to hex string. * @return hex string. */ public static String bytesToHexString(byte[] bytes) { if (bytes == null) { return null; } return bytesToHexString(bytes, 0, bytes.length); } /** * Stringify a portion of the byte array. * * @param bytes byte array. * @param offset portion start. * @param length portion length. * @return hex string. */ public static String bytesToHexString(byte[] bytes, int offset, int length) { if (length < 0) { throw new IllegalArgumentException("Negative length " + length); } if (offset < 0) { throw new IndexOutOfBoundsException("Negative start offset " + offset); } if (length > bytes.length - offset) { throw new IndexOutOfBoundsException( "Invalid range, bytes.length: " + bytes.length + " offset: " + offset + " length: " + length); } char[] chars = new char[length * 2]; for (int i = 0; i < length; i++) { int unsignedInt = bytes[i + offset] & 0xFF; chars[2 * i] = HEX_CHARS[unsignedInt >>> 4]; chars[2 * i + 1] = HEX_CHARS[unsignedInt & 0x0F]; } return new String(chars); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TUnion.java0000644000000000000000000002125214303740367024622 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.thrift.protocol.TField; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolException; import org.apache.thrift.protocol.TStruct; import org.apache.thrift.scheme.IScheme; import org.apache.thrift.scheme.SchemeFactory; import org.apache.thrift.scheme.StandardScheme; import org.apache.thrift.scheme.TupleScheme; public abstract class TUnion, F extends TFieldIdEnum> implements TBase { protected Object value_; protected F setField_; protected TUnion() { setField_ = null; value_ = null; } private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); static { schemes.put(StandardScheme.class, new TUnionStandardSchemeFactory()); schemes.put(TupleScheme.class, new TUnionTupleSchemeFactory()); } protected TUnion(F setField, Object value) { setFieldValue(setField, value); } protected TUnion(TUnion other) { if (!other.getClass().equals(this.getClass())) { throw new ClassCastException(); } setField_ = other.setField_; value_ = deepCopyObject(other.value_); } private static Object deepCopyObject(Object o) { if (o instanceof TBase) { return ((TBase) o).deepCopy(); } else if (o instanceof ByteBuffer) { return TBaseHelper.copyBinary((ByteBuffer) o); } else if (o instanceof List) { return deepCopyList((List) o); } else if (o instanceof Set) { return deepCopySet((Set) o); } else if (o instanceof Map) { return deepCopyMap((Map) o); } else { return o; } } private static Map deepCopyMap(Map map) { Map copy = new HashMap(map.size()); for (Map.Entry entry : map.entrySet()) { copy.put(deepCopyObject(entry.getKey()), deepCopyObject(entry.getValue())); } return copy; } private static Set deepCopySet(Set set) { Set copy = new HashSet(set.size()); for (Object o : set) { copy.add(deepCopyObject(o)); } return copy; } private static List deepCopyList(List list) { List copy = new ArrayList(list.size()); for (Object o : list) { copy.add(deepCopyObject(o)); } return copy; } public F getSetField() { return setField_; } public Object getFieldValue() { return value_; } public Object getFieldValue(F fieldId) { if (fieldId != setField_) { throw new IllegalArgumentException( "Cannot get the value of field " + fieldId + " because union's set field is " + setField_); } return getFieldValue(); } public Object getFieldValue(int fieldId) { return getFieldValue(enumForId((short) fieldId)); } public boolean isSet() { return setField_ != null; } public boolean isSet(F fieldId) { return setField_ == fieldId; } public boolean isSet(int fieldId) { return isSet(enumForId((short) fieldId)); } public void read(TProtocol iprot) throws TException { schemes.get(iprot.getScheme()).getScheme().read(iprot, this); } public void setFieldValue(F fieldId, Object value) { checkType(fieldId, value); setField_ = fieldId; value_ = value; } public void setFieldValue(int fieldId, Object value) { setFieldValue(enumForId((short) fieldId), value); } public void write(TProtocol oprot) throws TException { schemes.get(oprot.getScheme()).getScheme().write(oprot, this); } /** * Implementation should be generated so that we can efficiently type check various values. * * @param setField the field to assign value to. * @param value the value to be assigned to setField. * @throws ClassCastException if the type of value is incompatible with the type of setField. */ protected abstract void checkType(F setField, Object value) throws ClassCastException; /** * Implementation should be generated to read the right stuff from the wire based on the field * header. * * @param iprot input protocol from which to read a value. * @param field the field whose value is to be read from iprot. * @return read Object based on the field header, as specified by the argument. * @throws TException on error during read. */ protected abstract Object standardSchemeReadValue(TProtocol iprot, TField field) throws TException; protected abstract void standardSchemeWriteValue(TProtocol oprot) throws TException; protected abstract Object tupleSchemeReadValue(TProtocol iprot, short fieldID) throws TException; protected abstract void tupleSchemeWriteValue(TProtocol oprot) throws TException; protected abstract TStruct getStructDesc(); protected abstract TField getFieldDesc(F setField); protected abstract F enumForId(short id); @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("<"); sb.append(this.getClass().getSimpleName()); sb.append(" "); if (getSetField() != null) { Object v = getFieldValue(); sb.append(getFieldDesc(getSetField()).name); sb.append(":"); if (v instanceof ByteBuffer) { TBaseHelper.toString((ByteBuffer) v, sb); } else { sb.append(v.toString()); } } sb.append(">"); return sb.toString(); } public final void clear() { this.setField_ = null; this.value_ = null; } private static class TUnionStandardSchemeFactory implements SchemeFactory { public TUnionStandardScheme getScheme() { return new TUnionStandardScheme(); } } private static class TUnionStandardScheme extends StandardScheme { @Override public void read(TProtocol iprot, TUnion struct) throws TException { struct.setField_ = null; struct.value_ = null; iprot.readStructBegin(); TField field = iprot.readFieldBegin(); struct.value_ = struct.standardSchemeReadValue(iprot, field); if (struct.value_ != null) { struct.setField_ = struct.enumForId(field.id); } iprot.readFieldEnd(); // this is so that we will eat the stop byte. we could put a check here to // make sure that it actually *is* the stop byte, but it's faster to do it // this way. iprot.readFieldBegin(); iprot.readStructEnd(); } @Override public void write(TProtocol oprot, TUnion struct) throws TException { if (struct.getSetField() == null || struct.getFieldValue() == null) { throw new TProtocolException("Cannot write a TUnion with no set value!"); } oprot.writeStructBegin(struct.getStructDesc()); oprot.writeFieldBegin(struct.getFieldDesc(struct.setField_)); struct.standardSchemeWriteValue(oprot); oprot.writeFieldEnd(); oprot.writeFieldStop(); oprot.writeStructEnd(); } } private static class TUnionTupleSchemeFactory implements SchemeFactory { public TUnionTupleScheme getScheme() { return new TUnionTupleScheme(); } } private static class TUnionTupleScheme extends TupleScheme { @Override public void read(TProtocol iprot, TUnion struct) throws TException { struct.setField_ = null; struct.value_ = null; short fieldID = iprot.readI16(); struct.value_ = struct.tupleSchemeReadValue(iprot, fieldID); if (struct.value_ != null) { struct.setField_ = struct.enumForId(fieldID); } } @Override public void write(TProtocol oprot, TUnion struct) throws TException { if (struct.getSetField() == null || struct.getFieldValue() == null) { throw new TProtocolException("Cannot write a TUnion with no set value!"); } oprot.writeI16(struct.setField_.getThriftFieldId()); struct.tupleSchemeWriteValue(oprot); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TApplicationException.java0000644000000000000000000001053314303740367027654 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TField; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolUtil; import org.apache.thrift.protocol.TStruct; import org.apache.thrift.protocol.TType; /** Application level exception */ public class TApplicationException extends TException implements TSerializable { private static final TStruct TAPPLICATION_EXCEPTION_STRUCT = new TStruct("TApplicationException"); private static final TField MESSAGE_FIELD = new TField("message", TType.STRING, (short) 1); private static final TField TYPE_FIELD = new TField("type", TType.I32, (short) 2); private static final long serialVersionUID = 1L; public static final int UNKNOWN = 0; public static final int UNKNOWN_METHOD = 1; public static final int INVALID_MESSAGE_TYPE = 2; public static final int WRONG_METHOD_NAME = 3; public static final int BAD_SEQUENCE_ID = 4; public static final int MISSING_RESULT = 5; public static final int INTERNAL_ERROR = 6; public static final int PROTOCOL_ERROR = 7; public static final int INVALID_TRANSFORM = 8; public static final int INVALID_PROTOCOL = 9; public static final int UNSUPPORTED_CLIENT_TYPE = 10; protected int type_ = UNKNOWN; private String message_ = null; public TApplicationException() { super(); } public TApplicationException(int type) { super(); type_ = type; } public TApplicationException(int type, String message) { super(message); type_ = type; } public TApplicationException(String message) { super(message); } public int getType() { return type_; } @Override public String getMessage() { if (message_ == null) { return super.getMessage(); } else { return message_; } } public void read(TProtocol iprot) throws TException { TField field; iprot.readStructBegin(); String message = null; int type = UNKNOWN; while (true) { field = iprot.readFieldBegin(); if (field.type == TType.STOP) { break; } switch (field.id) { case 1: if (field.type == TType.STRING) { message = iprot.readString(); } else { TProtocolUtil.skip(iprot, field.type); } break; case 2: if (field.type == TType.I32) { type = iprot.readI32(); } else { TProtocolUtil.skip(iprot, field.type); } break; default: TProtocolUtil.skip(iprot, field.type); break; } iprot.readFieldEnd(); } iprot.readStructEnd(); type_ = type; message_ = message; } /** * Convenience factory method for constructing a TApplicationException given a TProtocol input * * @param iprot protocol from which an instance of TApplicationException is read. * @return an instance of TApplicationException read from iprot. * @throws TException if there is an error reading from iprot. */ public static TApplicationException readFrom(TProtocol iprot) throws TException { TApplicationException result = new TApplicationException(); result.read(iprot); return result; } public void write(TProtocol oprot) throws TException { oprot.writeStructBegin(TAPPLICATION_EXCEPTION_STRUCT); if (getMessage() != null) { oprot.writeFieldBegin(MESSAGE_FIELD); oprot.writeString(getMessage()); oprot.writeFieldEnd(); } oprot.writeFieldBegin(TYPE_FIELD); oprot.writeI32(type_); oprot.writeFieldEnd(); oprot.writeFieldStop(); oprot.writeStructEnd(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/0000777000000000000000000000000014452237057024055 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/ServerContext.java0000644000000000000000000000342514303740367027531 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** Interface for storing server's connection context. */ package org.apache.thrift.server; public interface ServerContext { /** * Returns an object that implements the given interface to allow access to application specific * contexts. * * @param iface A Class defining an interface that the result must implement * @return an object that implements the interface * @throws RuntimeException If the context cannot be unwrapped to the provided class */ T unwrap(Class iface); /** * Returns true if this server context is a wrapper for the provided application specific context * interface argument or returns false otherwise. * * @param iface a Class defining the underlying context * @return true if this implements the interface can be unwrapped to the provided class * @throws RuntimeException if an error occurs while determining whether the provided class can be * unwrapped from this context. */ boolean isWrapperFor(Class iface); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TServerEventHandler.java0000644000000000000000000000412214303740367030603 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TTransport; /** * Interface that can handle events from the server core. To use this you should subclass it and * implement the methods that you care about. Your subclass can also store local data that you may * care about, such as additional "arguments" to these methods (stored in the object instance's * state). * *

TODO: It seems this is a custom code entry point created for some resource management purpose * in hive. But when looking into hive code, we see that the argments of TProtocol and TTransport * are never used. We probably should remove these arguments from all the methods. */ public interface TServerEventHandler { /** Called before the server begins. */ void preServe(); /** Called when a new client has connected and is about to being processing. */ ServerContext createContext(TProtocol input, TProtocol output); /** Called when a client has finished request-handling to delete server context. */ void deleteContext(ServerContext serverContext, TProtocol input, TProtocol output); /** Called when a client is about to call the processor. */ void processContext( ServerContext serverContext, TTransport inputTransport, TTransport outputTransport); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TNonblockingServer.java0000644000000000000000000001700014370300523030454 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import java.io.IOException; import java.nio.channels.SelectionKey; import java.util.Iterator; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransportException; /** * A nonblocking TServer implementation. This allows for fairness amongst all connected clients in * terms of invocations. * *

This server is inherently single-threaded. If you want a limited thread pool coupled with * invocation-fairness, see THsHaServer. * *

To use this server, you MUST use a TFramedTransport at the outermost transport, otherwise this * server will be unable to determine when a whole method call has been read off the wire. Clients * must also use TFramedTransport. */ public class TNonblockingServer extends AbstractNonblockingServer { public static class Args extends AbstractNonblockingServerArgs { public Args(TNonblockingServerTransport transport) { super(transport); } } private SelectAcceptThread selectAcceptThread_; public TNonblockingServer(AbstractNonblockingServerArgs args) { super(args); } /** * Start the selector thread to deal with accepts and client messages. * * @return true if everything went ok, false if we couldn't start for some reason. */ @Override protected boolean startThreads() { // start the selector try { selectAcceptThread_ = new SelectAcceptThread((TNonblockingServerTransport) serverTransport_); selectAcceptThread_.start(); return true; } catch (IOException e) { LOGGER.error("Failed to start selector thread!", e); return false; } } @Override protected void waitForShutdown() { joinSelector(); } /** Block until the selector thread exits. */ protected void joinSelector() { // wait until the selector thread exits try { selectAcceptThread_.join(); } catch (InterruptedException e) { LOGGER.debug("Interrupted while waiting for accept thread", e); Thread.currentThread().interrupt(); } } /** Stop serving and shut everything down. */ @Override public void stop() { stopped_ = true; if (selectAcceptThread_ != null) { selectAcceptThread_.wakeupSelector(); } } /** * Perform an invocation. This method could behave several different ways - invoke immediately * inline, queue for separate execution, etc. */ @Override protected boolean requestInvoke(FrameBuffer frameBuffer) { frameBuffer.invoke(); return true; } public boolean isStopped() { return selectAcceptThread_.isStopped(); } /** * The thread that will be doing all the selecting, managing new connections and those that still * need to be read. */ protected class SelectAcceptThread extends AbstractSelectThread { // The server transport on which new client transports will be accepted private final TNonblockingServerTransport serverTransport; /** Set up the thread that will handle the non-blocking accepts, reads, and writes. */ public SelectAcceptThread(final TNonblockingServerTransport serverTransport) throws IOException { this.serverTransport = serverTransport; serverTransport.registerSelector(selector); } public boolean isStopped() { return stopped_; } /** * The work loop. Handles both selecting (all IO operations) and managing the selection * preferences of all existing connections. */ @Override public void run() { try { if (eventHandler_ != null) { eventHandler_.preServe(); } while (!stopped_) { select(); processInterestChanges(); } for (SelectionKey selectionKey : selector.keys()) { cleanupSelectionKey(selectionKey); } } catch (Throwable t) { LOGGER.error("run() exiting due to uncaught error", t); } finally { try { selector.close(); } catch (IOException e) { LOGGER.error("Got an IOException while closing selector!", e); } stopped_ = true; } } /** * Select and process IO events appropriately: If there are connections to be accepted, accept * them. If there are existing connections with data waiting to be read, read it, buffering * until a whole frame has been read. If there are any pending responses, buffer them until * their target client is available, and then send the data. */ private void select() { try { // wait for io events. selector.select(); // process the io events we received Iterator selectedKeys = selector.selectedKeys().iterator(); while (!stopped_ && selectedKeys.hasNext()) { SelectionKey key = selectedKeys.next(); selectedKeys.remove(); // skip if not valid if (!key.isValid()) { cleanupSelectionKey(key); continue; } // if the key is marked Accept, then it has to be the server // transport. if (key.isAcceptable()) { handleAccept(); } else if (key.isReadable()) { // deal with reads handleRead(key); } else if (key.isWritable()) { // deal with writes handleWrite(key); } else { LOGGER.warn("Unexpected state in select! " + key.interestOps()); } } } catch (IOException e) { LOGGER.warn("Got an IOException while selecting!", e); } } protected FrameBuffer createFrameBuffer( final TNonblockingTransport trans, final SelectionKey selectionKey, final AbstractSelectThread selectThread) throws TTransportException { return processorFactory_.isAsyncProcessor() ? new AsyncFrameBuffer(trans, selectionKey, selectThread) : new FrameBuffer(trans, selectionKey, selectThread); } /** Accept a new connection. */ private void handleAccept() throws IOException { SelectionKey clientKey = null; TNonblockingTransport client = null; try { // accept the connection client = serverTransport.accept(); clientKey = client.registerSelector(selector, SelectionKey.OP_READ); // add this key to the map FrameBuffer frameBuffer = createFrameBuffer(client, clientKey, SelectAcceptThread.this); clientKey.attach(frameBuffer); } catch (TTransportException tte) { // something went wrong accepting. LOGGER.warn("Exception trying to accept!", tte); if (clientKey != null) cleanupSelectionKey(clientKey); if (client != null) client.close(); } } } // SelectAcceptThread } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TServlet.java0000644000000000000000000000670414452237057026473 0ustar00rootroot00000000000000package org.apache.thrift.server; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; /** Servlet implementation class ThriftServer */ public class TServlet extends HttpServlet { private final TProcessor processor; private final TProtocolFactory inProtocolFactory; private final TProtocolFactory outProtocolFactory; private final Collection> customHeaders; /** * @see HttpServlet#HttpServlet() */ public TServlet( TProcessor processor, TProtocolFactory inProtocolFactory, TProtocolFactory outProtocolFactory) { super(); this.processor = processor; this.inProtocolFactory = inProtocolFactory; this.outProtocolFactory = outProtocolFactory; this.customHeaders = new ArrayList>(); } /** * @see HttpServlet#HttpServlet() */ public TServlet(TProcessor processor, TProtocolFactory protocolFactory) { this(processor, protocolFactory, protocolFactory); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { TTransport inTransport = null; TTransport outTransport = null; try { response.setContentType("application/x-thrift"); if (null != this.customHeaders) { for (Map.Entry header : this.customHeaders) { response.addHeader(header.getKey(), header.getValue()); } } InputStream in = request.getInputStream(); OutputStream out = response.getOutputStream(); TTransport transport = new TIOStreamTransport(in, out); inTransport = transport; outTransport = transport; TProtocol inProtocol = inProtocolFactory.getProtocol(inTransport); TProtocol outProtocol = outProtocolFactory.getProtocol(outTransport); processor.process(inProtocol, outProtocol); out.flush(); } catch (TException te) { throw new ServletException(te); } } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void addCustomHeader(final String key, final String value) { this.customHeaders.add( new Map.Entry() { @Override public String getKey() { return key; } @Override public String getValue() { return value; } @Override public String setValue(String value) { return null; } }); } public void setCustomHeaders(Collection> headers) { this.customHeaders.clear(); this.customHeaders.addAll(headers); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/THsHaServer.java0000644000000000000000000001345314303740367027056 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.apache.thrift.transport.TNonblockingServerTransport; /** * An extension of the TNonblockingServer to a Half-Sync/Half-Async server. Like TNonblockingServer, * it relies on the use of TFramedTransport. */ public class THsHaServer extends TNonblockingServer { public static class Args extends AbstractNonblockingServerArgs { public int minWorkerThreads = 5; public int maxWorkerThreads = Integer.MAX_VALUE; private int stopTimeoutVal = 60; private TimeUnit stopTimeoutUnit = TimeUnit.SECONDS; private ExecutorService executorService = null; public Args(TNonblockingServerTransport transport) { super(transport); } /** * Sets the min and max threads. * * @deprecated use {@link #minWorkerThreads(int)} and {@link #maxWorkerThreads(int)} instead. */ @Deprecated public Args workerThreads(int n) { minWorkerThreads = n; maxWorkerThreads = n; return this; } /** * @return what the min threads was set to. * @deprecated use {@link #getMinWorkerThreads()} and {@link #getMaxWorkerThreads()} instead. */ @Deprecated public int getWorkerThreads() { return minWorkerThreads; } public Args minWorkerThreads(int n) { minWorkerThreads = n; return this; } public Args maxWorkerThreads(int n) { maxWorkerThreads = n; return this; } public int getMinWorkerThreads() { return minWorkerThreads; } public int getMaxWorkerThreads() { return maxWorkerThreads; } public int getStopTimeoutVal() { return stopTimeoutVal; } public Args stopTimeoutVal(int stopTimeoutVal) { this.stopTimeoutVal = stopTimeoutVal; return this; } public TimeUnit getStopTimeoutUnit() { return stopTimeoutUnit; } public Args stopTimeoutUnit(TimeUnit stopTimeoutUnit) { this.stopTimeoutUnit = stopTimeoutUnit; return this; } public ExecutorService getExecutorService() { return executorService; } public Args executorService(ExecutorService executorService) { this.executorService = executorService; return this; } } // This wraps all the functionality of queueing and thread pool management // for the passing of Invocations from the Selector to workers. private final ExecutorService invoker; private final Args args; /** Create the server with the specified Args configuration */ public THsHaServer(Args args) { super(args); invoker = args.executorService == null ? createInvokerPool(args) : args.executorService; this.args = args; } /** {@inheritDoc} */ @Override protected void waitForShutdown() { joinSelector(); gracefullyShutdownInvokerPool(); } /** Helper to create an invoker pool */ protected static ExecutorService createInvokerPool(Args options) { int minWorkerThreads = options.minWorkerThreads; int maxWorkerThreads = options.maxWorkerThreads; int stopTimeoutVal = options.stopTimeoutVal; TimeUnit stopTimeoutUnit = options.stopTimeoutUnit; LinkedBlockingQueue queue = new LinkedBlockingQueue(); ExecutorService invoker = new ThreadPoolExecutor( minWorkerThreads, maxWorkerThreads, stopTimeoutVal, stopTimeoutUnit, queue); return invoker; } protected ExecutorService getInvoker() { return invoker; } protected void gracefullyShutdownInvokerPool() { // try to gracefully shut down the executor service invoker.shutdown(); // Loop until awaitTermination finally does return without a interrupted // exception. If we don't do this, then we'll shut down prematurely. We want // to let the executorService clear it's task queue, closing client sockets // appropriately. long timeoutMS = args.stopTimeoutUnit.toMillis(args.stopTimeoutVal); long now = System.currentTimeMillis(); while (timeoutMS >= 0) { try { invoker.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); break; } catch (InterruptedException ix) { long newnow = System.currentTimeMillis(); timeoutMS -= (newnow - now); now = newnow; } } } /** * We override the standard invoke method here to queue the invocation for invoker service instead * of immediately invoking. The thread pool takes care of the rest. */ @Override protected boolean requestInvoke(FrameBuffer frameBuffer) { try { Runnable invocation = getRunnable(frameBuffer); invoker.execute(invocation); return true; } catch (RejectedExecutionException rx) { LOGGER.warn("ExecutorService rejected execution!", rx); return false; } } protected Runnable getRunnable(FrameBuffer frameBuffer) { return new Invocation(frameBuffer); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TThreadedSelectorServer.java0000644000000000000000000005612514452237057031461 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import java.io.IOException; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.SelectorProvider; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeUnit; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Half-Sync/Half-Async server with a separate pool of threads to handle non-blocking I/O. Accepts * are handled on a single thread, and a configurable number of nonblocking selector threads manage * reading and writing of client connections. A synchronous worker thread pool handles processing of * requests. * *

Performs better than TNonblockingServer/THsHaServer in multi-core environments when the * bottleneck is CPU on the single selector thread handling I/O. In addition, because the accept * handling is decoupled from reads/writes and invocation, the server has better ability to handle * back-pressure from new connections (e.g. stop accepting when busy). * *

Like TNonblockingServer, it relies on the use of TFramedTransport. */ public class TThreadedSelectorServer extends AbstractNonblockingServer { private static final Logger LOGGER = LoggerFactory.getLogger(TThreadedSelectorServer.class.getName()); public static class Args extends AbstractNonblockingServerArgs { /** The number of threads for selecting on already-accepted connections */ public int selectorThreads = 2; /** * The size of the executor service (if none is specified) that will handle invocations. This * may be set to 0, in which case invocations will be handled directly on the selector threads * (as is in TNonblockingServer) */ private int workerThreads = 5; /** Time to wait for server to stop gracefully */ private int stopTimeoutVal = 60; private TimeUnit stopTimeoutUnit = TimeUnit.SECONDS; /** The ExecutorService for handling dispatched requests */ private ExecutorService executorService = null; /** * The size of the blocking queue per selector thread for passing accepted connections to the * selector thread */ private int acceptQueueSizePerThread = 4; /** Determines the strategy for handling new accepted connections. */ public static enum AcceptPolicy { /** * Require accepted connection registration to be handled by the executor. If the worker pool * is saturated, further accepts will be closed immediately. Slightly increases latency due to * an extra scheduling. */ FAIR_ACCEPT, /** * Handle the accepts as fast as possible, disregarding the status of the executor service. */ FAST_ACCEPT } private AcceptPolicy acceptPolicy = AcceptPolicy.FAST_ACCEPT; public Args(TNonblockingServerTransport transport) { super(transport); } public Args selectorThreads(int i) { selectorThreads = i; return this; } public int getSelectorThreads() { return selectorThreads; } public Args workerThreads(int i) { workerThreads = i; return this; } public int getWorkerThreads() { return workerThreads; } public int getStopTimeoutVal() { return stopTimeoutVal; } public Args stopTimeoutVal(int stopTimeoutVal) { this.stopTimeoutVal = stopTimeoutVal; return this; } public TimeUnit getStopTimeoutUnit() { return stopTimeoutUnit; } public Args stopTimeoutUnit(TimeUnit stopTimeoutUnit) { this.stopTimeoutUnit = stopTimeoutUnit; return this; } public ExecutorService getExecutorService() { return executorService; } public Args executorService(ExecutorService executorService) { this.executorService = executorService; return this; } public int getAcceptQueueSizePerThread() { return acceptQueueSizePerThread; } public Args acceptQueueSizePerThread(int acceptQueueSizePerThread) { this.acceptQueueSizePerThread = acceptQueueSizePerThread; return this; } public AcceptPolicy getAcceptPolicy() { return acceptPolicy; } public Args acceptPolicy(AcceptPolicy acceptPolicy) { this.acceptPolicy = acceptPolicy; return this; } public void validate() { if (selectorThreads <= 0) { throw new IllegalArgumentException("selectorThreads must be positive."); } if (workerThreads < 0) { throw new IllegalArgumentException("workerThreads must be non-negative."); } if (acceptQueueSizePerThread <= 0) { throw new IllegalArgumentException("acceptQueueSizePerThread must be positive."); } } } // The thread handling all accepts private AcceptThread acceptThread; // Threads handling events on client transports private final Set selectorThreads = new HashSet<>(); // This wraps all the functionality of queueing and thread pool management // for the passing of Invocations from the selector thread(s) to the workers // (if any). private final ExecutorService invoker; private final Args args; /** Create the server with the specified Args configuration */ public TThreadedSelectorServer(Args args) { super(args); args.validate(); invoker = args.executorService == null ? createDefaultExecutor(args) : args.executorService; this.args = args; } /** * Start the accept and selector threads running to deal with clients. * * @return true if everything went ok, false if we couldn't start for some reason. */ @Override protected boolean startThreads() { try { for (int i = 0; i < args.selectorThreads; ++i) { selectorThreads.add(new SelectorThread(args.acceptQueueSizePerThread)); } acceptThread = new AcceptThread( (TNonblockingServerTransport) serverTransport_, createSelectorThreadLoadBalancer(selectorThreads)); for (SelectorThread thread : selectorThreads) { thread.start(); } acceptThread.start(); return true; } catch (IOException e) { LOGGER.error("Failed to start threads!", e); return false; } } /** Joins the accept and selector threads and shuts down the executor service. */ @Override protected void waitForShutdown() { try { joinThreads(); } catch (InterruptedException e) { // Non-graceful shutdown occurred LOGGER.error("Interrupted while joining threads!", e); } gracefullyShutdownInvokerPool(); } protected void joinThreads() throws InterruptedException { // wait until the io threads exit acceptThread.join(); for (SelectorThread thread : selectorThreads) { thread.join(); } } /** Stop serving and shut everything down. */ @Override public void stop() { stopped_ = true; // Stop queuing connect attempts asap stopListening(); if (acceptThread != null) { acceptThread.wakeupSelector(); } for (SelectorThread thread : selectorThreads) { if (thread != null) thread.wakeupSelector(); } } protected void gracefullyShutdownInvokerPool() { // try to gracefully shut down the executor service invoker.shutdown(); // Loop until awaitTermination finally does return without a interrupted // exception. If we don't do this, then we'll shut down prematurely. We want // to let the executorService clear it's task queue, closing client sockets // appropriately. long timeoutMS = args.stopTimeoutUnit.toMillis(args.stopTimeoutVal); long now = System.currentTimeMillis(); while (timeoutMS >= 0) { try { invoker.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); break; } catch (InterruptedException ix) { long newnow = System.currentTimeMillis(); timeoutMS -= (newnow - now); now = newnow; } } } /** * We override the standard invoke method here to queue the invocation for invoker service instead * of immediately invoking. If there is no thread pool, handle the invocation inline on this * thread */ @Override protected boolean requestInvoke(FrameBuffer frameBuffer) { Runnable invocation = getRunnable(frameBuffer); if (invoker != null) { try { invoker.execute(invocation); return true; } catch (RejectedExecutionException rx) { LOGGER.warn("ExecutorService rejected execution!", rx); return false; } } else { // Invoke on the caller's thread invocation.run(); return true; } } protected Runnable getRunnable(FrameBuffer frameBuffer) { return new Invocation(frameBuffer); } /** Helper to create the invoker if one is not specified */ protected static ExecutorService createDefaultExecutor(Args options) { return (options.workerThreads > 0) ? Executors.newFixedThreadPool(options.workerThreads) : null; } private static BlockingQueue createDefaultAcceptQueue(int queueSize) { if (queueSize == 0) { // Unbounded queue return new LinkedBlockingQueue(); } return new ArrayBlockingQueue(queueSize); } /** * The thread that selects on the server transport (listen socket) and accepts new connections to * hand off to the IO selector threads */ protected class AcceptThread extends Thread { // The listen socket to accept on private final TNonblockingServerTransport serverTransport; private final Selector acceptSelector; private final SelectorThreadLoadBalancer threadChooser; /** * Set up the AcceptThead * * @throws IOException if failed to register selector */ public AcceptThread( TNonblockingServerTransport serverTransport, SelectorThreadLoadBalancer threadChooser) throws IOException { this.serverTransport = serverTransport; this.threadChooser = threadChooser; this.acceptSelector = SelectorProvider.provider().openSelector(); this.serverTransport.registerSelector(acceptSelector); } /** * The work loop. Selects on the server transport and accepts. If there was a server transport * that had blocking accepts, and returned on blocking client transports, that should be used * instead */ public void run() { try { if (eventHandler_ != null) { eventHandler_.preServe(); } while (!stopped_) { select(); } } catch (Throwable t) { LOGGER.error("run() on AcceptThread exiting due to uncaught error", t); } finally { try { acceptSelector.close(); } catch (IOException e) { LOGGER.error("Got an IOException while closing accept selector!", e); } // This will wake up the selector threads TThreadedSelectorServer.this.stop(); } } /** If the selector is blocked, wake it up. */ public void wakeupSelector() { acceptSelector.wakeup(); } /** * Select and process IO events appropriately: If there are connections to be accepted, accept * them. */ private void select() { try { // wait for connect events. acceptSelector.select(); // process the io events we received Iterator selectedKeys = acceptSelector.selectedKeys().iterator(); while (!stopped_ && selectedKeys.hasNext()) { SelectionKey key = selectedKeys.next(); selectedKeys.remove(); // skip if not valid if (!key.isValid()) { continue; } if (key.isAcceptable()) { handleAccept(); } else { LOGGER.warn("Unexpected state in select! " + key.interestOps()); } } } catch (IOException e) { LOGGER.warn("Got an IOException while selecting!", e); } } /** Accept a new connection. */ private void handleAccept() { final TNonblockingTransport client = doAccept(); if (client != null) { // Pass this connection to a selector thread final SelectorThread targetThread = threadChooser.nextThread(); if (args.acceptPolicy == Args.AcceptPolicy.FAST_ACCEPT || invoker == null) { doAddAccept(targetThread, client); } else { // FAIR_ACCEPT try { invoker.submit( new Runnable() { public void run() { doAddAccept(targetThread, client); } }); } catch (RejectedExecutionException rx) { LOGGER.warn("ExecutorService rejected accept registration!", rx); // close immediately client.close(); } } } } private TNonblockingTransport doAccept() { try { return serverTransport.accept(); } catch (TTransportException tte) { // something went wrong accepting. LOGGER.warn("Exception trying to accept!", tte); return null; } } private void doAddAccept(SelectorThread thread, TNonblockingTransport client) { if (!thread.addAcceptedConnection(client)) { client.close(); } } } // AcceptThread /** The SelectorThread(s) will be doing all the selecting on accepted active connections. */ protected class SelectorThread extends AbstractSelectThread { // Accepted connections added by the accept thread. private final BlockingQueue acceptedQueue; private static final int SELECTOR_AUTO_REBUILD_THRESHOLD = 512; private static final long MONITOR_PERIOD = 1000L; private int jvmBug = 0; /** * Set up the SelectorThread with an unbounded queue for incoming accepts. * * @throws IOException if a selector cannot be created */ public SelectorThread() throws IOException { this(new LinkedBlockingQueue()); } /** * Set up the SelectorThread with an bounded queue for incoming accepts. * * @throws IOException if a selector cannot be created */ public SelectorThread(int maxPendingAccepts) throws IOException { this(createDefaultAcceptQueue(maxPendingAccepts)); } /** * Set up the SelectorThread with a specified queue for connections. * * @param acceptedQueue The BlockingQueue implementation for holding incoming accepted * connections. * @throws IOException if a selector cannot be created. */ public SelectorThread(BlockingQueue acceptedQueue) throws IOException { this.acceptedQueue = acceptedQueue; } /** * Hands off an accepted connection to be handled by this thread. This method will block if the * queue for new connections is at capacity. * * @param accepted The connection that has been accepted. * @return true if the connection has been successfully added. */ public boolean addAcceptedConnection(TNonblockingTransport accepted) { try { acceptedQueue.put(accepted); } catch (InterruptedException e) { LOGGER.warn("Interrupted while adding accepted connection!", e); return false; } selector.wakeup(); return true; } /** * The work loop. Handles selecting (read/write IO), dispatching, and managing the selection * preferences of all existing connections. */ public void run() { try { while (!stopped_) { select(); processAcceptedConnections(); processInterestChanges(); } for (SelectionKey selectionKey : selector.keys()) { cleanupSelectionKey(selectionKey); } } catch (Throwable t) { LOGGER.error("run() on SelectorThread exiting due to uncaught error", t); } finally { try { selector.close(); } catch (IOException e) { LOGGER.error("Got an IOException while closing selector!", e); } // This will wake up the accept thread and the other selector threads TThreadedSelectorServer.this.stop(); } } /** * Select and process IO events appropriately: If there are existing connections with data * waiting to be read, read it, buffering until a whole frame has been read. If there are any * pending responses, buffer them until their target client is available, and then send the * data. */ private void select() { try { doSelect(); // process the io events we received Iterator selectedKeys = selector.selectedKeys().iterator(); while (!stopped_ && selectedKeys.hasNext()) { SelectionKey key = selectedKeys.next(); selectedKeys.remove(); // skip if not valid if (!key.isValid()) { cleanupSelectionKey(key); continue; } if (key.isReadable()) { // deal with reads handleRead(key); } else if (key.isWritable()) { // deal with writes handleWrite(key); } else { LOGGER.warn("Unexpected state in select! " + key.interestOps()); } } } catch (IOException e) { LOGGER.warn("Got an IOException while selecting!", e); } } /** * Do select and judge epoll bug happen. See THRIFT-4251 */ private void doSelect() throws IOException { long beforeSelect = System.currentTimeMillis(); int selectedNums = selector.select(); long afterSelect = System.currentTimeMillis(); if (selectedNums == 0) { jvmBug++; } else { jvmBug = 0; } long selectedTime = afterSelect - beforeSelect; if (selectedTime >= MONITOR_PERIOD) { jvmBug = 0; } else if (jvmBug > SELECTOR_AUTO_REBUILD_THRESHOLD) { LOGGER.warn( "In {} ms happen {} times jvm bug; rebuilding selector.", MONITOR_PERIOD, jvmBug); rebuildSelector(); selector.selectNow(); jvmBug = 0; } } /** * Replaces the current Selector of this SelectorThread with newly created Selector to work * around the infamous epoll 100% CPU bug. */ private synchronized void rebuildSelector() { final Selector oldSelector = selector; if (oldSelector == null) { return; } Selector newSelector = null; try { newSelector = Selector.open(); LOGGER.warn("Created new Selector."); } catch (IOException e) { LOGGER.error("Create new Selector error.", e); } for (SelectionKey key : oldSelector.selectedKeys()) { if (!key.isValid() && key.readyOps() == 0) continue; SelectableChannel channel = key.channel(); Object attachment = key.attachment(); try { if (attachment == null) { channel.register(newSelector, key.readyOps()); } else { channel.register(newSelector, key.readyOps(), attachment); } } catch (ClosedChannelException e) { LOGGER.error("Register new selector key error.", e); } } selector = newSelector; try { oldSelector.close(); } catch (IOException e) { LOGGER.error("Close old selector error.", e); } LOGGER.warn("Replace new selector success."); } private void processAcceptedConnections() { // Register accepted connections while (!stopped_) { TNonblockingTransport accepted = acceptedQueue.poll(); if (accepted == null) { break; } registerAccepted(accepted); } } protected FrameBuffer createFrameBuffer( final TNonblockingTransport trans, final SelectionKey selectionKey, final AbstractSelectThread selectThread) throws TTransportException { return processorFactory_.isAsyncProcessor() ? new AsyncFrameBuffer(trans, selectionKey, selectThread) : new FrameBuffer(trans, selectionKey, selectThread); } private void registerAccepted(TNonblockingTransport accepted) { SelectionKey clientKey = null; try { clientKey = accepted.registerSelector(selector, SelectionKey.OP_READ); FrameBuffer frameBuffer = createFrameBuffer(accepted, clientKey, SelectorThread.this); clientKey.attach(frameBuffer); } catch (IOException | TTransportException e) { LOGGER.warn("Failed to register accepted connection to selector!", e); if (clientKey != null) { cleanupSelectionKey(clientKey); } accepted.close(); } } } // SelectorThread /** * Creates a SelectorThreadLoadBalancer to be used by the accept thread for assigning newly * accepted connections across the threads. */ protected SelectorThreadLoadBalancer createSelectorThreadLoadBalancer( Collection threads) { return new SelectorThreadLoadBalancer(threads); } /** A round robin load balancer for choosing selector threads for new connections. */ protected static class SelectorThreadLoadBalancer { private final Collection threads; private Iterator nextThreadIterator; public SelectorThreadLoadBalancer(Collection threads) { if (threads.isEmpty()) { throw new IllegalArgumentException("At least one selector thread is required"); } this.threads = Collections.unmodifiableList(new ArrayList(threads)); nextThreadIterator = this.threads.iterator(); } public SelectorThread nextThread() { // Choose a selector thread (round robin) if (!nextThreadIterator.hasNext()) { nextThreadIterator = threads.iterator(); } return nextThreadIterator.next(); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/Invocation.java0000644000000000000000000000110314370300523027004 0ustar00rootroot00000000000000package org.apache.thrift.server; import org.apache.thrift.server.AbstractNonblockingServer.FrameBuffer; /** * An Invocation represents a method call that is prepared to execute, given an idle worker thread. * It contains the input and output protocols the thread's processor should use to perform the usual * Thrift invocation. */ class Invocation implements Runnable { private final FrameBuffer frameBuffer; public Invocation(final FrameBuffer frameBuffer) { this.frameBuffer = frameBuffer; } @Override public void run() { frameBuffer.invoke(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TServer.java0000644000000000000000000001150714303740367026310 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import org.apache.thrift.TProcessor; import org.apache.thrift.TProcessorFactory; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TTransportFactory; /** Generic interface for a Thrift server. */ public abstract class TServer { public static class Args extends AbstractServerArgs { public Args(TServerTransport transport) { super(transport); } } public abstract static class AbstractServerArgs> { final TServerTransport serverTransport; TProcessorFactory processorFactory; TTransportFactory inputTransportFactory = new TTransportFactory(); TTransportFactory outputTransportFactory = new TTransportFactory(); TProtocolFactory inputProtocolFactory = new TBinaryProtocol.Factory(); TProtocolFactory outputProtocolFactory = new TBinaryProtocol.Factory(); public AbstractServerArgs(TServerTransport transport) { serverTransport = transport; } public T processorFactory(TProcessorFactory factory) { this.processorFactory = factory; return (T) this; } public T processor(TProcessor processor) { this.processorFactory = new TProcessorFactory(processor); return (T) this; } public T transportFactory(TTransportFactory factory) { this.inputTransportFactory = factory; this.outputTransportFactory = factory; return (T) this; } public T inputTransportFactory(TTransportFactory factory) { this.inputTransportFactory = factory; return (T) this; } public T outputTransportFactory(TTransportFactory factory) { this.outputTransportFactory = factory; return (T) this; } public T protocolFactory(TProtocolFactory factory) { this.inputProtocolFactory = factory; this.outputProtocolFactory = factory; return (T) this; } public T inputProtocolFactory(TProtocolFactory factory) { this.inputProtocolFactory = factory; return (T) this; } public T outputProtocolFactory(TProtocolFactory factory) { this.outputProtocolFactory = factory; return (T) this; } } /** Core processor */ protected TProcessorFactory processorFactory_; /** Server transport */ protected TServerTransport serverTransport_; /** Input Transport Factory */ protected TTransportFactory inputTransportFactory_; /** Output Transport Factory */ protected TTransportFactory outputTransportFactory_; /** Input Protocol Factory */ protected TProtocolFactory inputProtocolFactory_; /** Output Protocol Factory */ protected TProtocolFactory outputProtocolFactory_; private volatile boolean isServing; protected TServerEventHandler eventHandler_; // Flag for stopping the server // Please see THRIFT-1795 for the usage of this flag protected volatile boolean stopped_ = false; protected TServer(AbstractServerArgs args) { processorFactory_ = args.processorFactory; serverTransport_ = args.serverTransport; inputTransportFactory_ = args.inputTransportFactory; outputTransportFactory_ = args.outputTransportFactory; inputProtocolFactory_ = args.inputProtocolFactory; outputProtocolFactory_ = args.outputProtocolFactory; } /** The run method fires up the server and gets things going. */ public abstract void serve(); /** * Stop the server. This is optional on a per-implementation basis. Not all servers are required * to be cleanly stoppable. */ public void stop() {} public boolean isServing() { return isServing; } protected void setServing(boolean serving) { isServing = serving; } public void setServerEventHandler(TServerEventHandler eventHandler) { eventHandler_ = eventHandler; } public TServerEventHandler getEventHandler() { return eventHandler_; } public boolean getShouldStop() { return this.stopped_; } public void setShouldStop(boolean shouldStop) { this.stopped_ = shouldStop; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TExtensibleServlet.java0000644000000000000000000001263514452237057030516 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import jakarta.servlet.ServletConfig; import jakarta.servlet.ServletContext; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Map; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; /** * Servlet implementation class ThriftServer, that allows {@link TProcessor} and {@link * TProtocolFactory} to be supplied after the {@link #init()} method has finished.
* Subclasses must implement the abstract methods that return the TProcessor and two * TProtocolFactory. Those methods are guaranteed to be called exactly once, and that {@link * ServletContext} is available. */ public abstract class TExtensibleServlet extends HttpServlet { private static final long serialVersionUID = 1L; private TProcessor processor; private TProtocolFactory inFactory; private Collection> customHeaders; /** * Returns the appropriate {@link TProcessor}. This will be called once just after the * {@link #init()} method * * @return the appropriate {@link TProcessor} */ protected abstract TProcessor getProcessor(); /** * Returns the appropriate in {@link TProtocolFactory}. This will be called once just after * the {@link #init()} method * * @return the appropriate in {@link TProtocolFactory} */ protected abstract TProtocolFactory getInProtocolFactory(); /** * Returns the appropriate out {@link TProtocolFactory}. This will be called once just * after the {@link #init()} method * * @return the appropriate out {@link TProtocolFactory} */ protected abstract TProtocolFactory getOutProtocolFactory(); @Override public final void init(ServletConfig config) throws ServletException { super.init(config); // no-args init() happens here this.processor = getProcessor(); this.inFactory = getInProtocolFactory(); TProtocolFactory outFactory = getOutProtocolFactory(); this.customHeaders = new ArrayList>(); if (processor == null) { throw new ServletException("processor must be set"); } if (inFactory == null) { throw new ServletException("inFactory must be set"); } if (outFactory == null) { throw new ServletException("outFactory must be set"); } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { TTransport inTransport; TTransport outTransport; try { response.setContentType("application/x-thrift"); if (null != this.customHeaders) { for (Map.Entry header : this.customHeaders) { response.addHeader(header.getKey(), header.getValue()); } } InputStream in = request.getInputStream(); OutputStream out = response.getOutputStream(); TTransport transport = new TIOStreamTransport(in, out); inTransport = transport; outTransport = transport; TProtocol inProtocol = inFactory.getProtocol(inTransport); TProtocol outProtocol = inFactory.getProtocol(outTransport); processor.process(inProtocol, outProtocol); out.flush(); } catch (TException te) { throw new ServletException(te); } } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } public void addCustomHeader(final String key, final String value) { this.customHeaders.add( new Map.Entry() { @Override public String getKey() { return key; } @Override public String getValue() { return value; } @Override public String setValue(String value) { return null; } }); } public void setCustomHeaders(Collection> headers) { this.customHeaders.clear(); this.customHeaders.addAll(headers); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TThreadPoolServer.java0000644000000000000000000002306214452237057030273 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import java.net.SocketException; import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Server which uses Java's built in ThreadPool management to spawn off a worker pool that deals * with client connections in blocking way. */ public class TThreadPoolServer extends TServer { private static final Logger LOGGER = LoggerFactory.getLogger(TThreadPoolServer.class); public static class Args extends AbstractServerArgs { public int minWorkerThreads = 5; public int maxWorkerThreads = Integer.MAX_VALUE; public ExecutorService executorService; public int stopTimeoutVal = 60; public TimeUnit stopTimeoutUnit = TimeUnit.SECONDS; public Args(TServerTransport transport) { super(transport); } public Args minWorkerThreads(int n) { minWorkerThreads = n; return this; } public Args maxWorkerThreads(int n) { maxWorkerThreads = n; return this; } public Args stopTimeoutVal(int n) { stopTimeoutVal = n; return this; } public Args stopTimeoutUnit(TimeUnit tu) { stopTimeoutUnit = tu; return this; } public Args executorService(ExecutorService executorService) { this.executorService = executorService; return this; } } // Executor service for handling client connections private final ExecutorService executorService_; private final TimeUnit stopTimeoutUnit; private final long stopTimeoutVal; public TThreadPoolServer(Args args) { super(args); stopTimeoutUnit = args.stopTimeoutUnit; stopTimeoutVal = args.stopTimeoutVal; executorService_ = args.executorService != null ? args.executorService : createDefaultExecutorService(args); } private static ExecutorService createDefaultExecutorService(Args args) { return new ThreadPoolExecutor( args.minWorkerThreads, args.maxWorkerThreads, 60L, TimeUnit.SECONDS, new SynchronousQueue<>(), new ThreadFactory() { final AtomicLong count = new AtomicLong(); @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setDaemon(true); thread.setName( String.format("TThreadPoolServer WorkerProcess-%d", count.getAndIncrement())); return thread; } }); } protected ExecutorService getExecutorService() { return executorService_; } protected boolean preServe() { try { serverTransport_.listen(); } catch (TTransportException ttx) { LOGGER.error("Error occurred during listening.", ttx); return false; } // Run the preServe event if (eventHandler_ != null) { eventHandler_.preServe(); } stopped_ = false; setServing(true); return true; } @Override public void serve() { if (!preServe()) { return; } execute(); executorService_.shutdownNow(); if (!waitForShutdown()) { LOGGER.error("Shutdown is not done after " + stopTimeoutVal + stopTimeoutUnit); } setServing(false); } protected void execute() { while (!stopped_) { try { TTransport client = serverTransport_.accept(); try { executorService_.execute(new WorkerProcess(client)); } catch (RejectedExecutionException ree) { if (!stopped_) { LOGGER.warn( "ThreadPool is saturated with incoming requests. Closing latest connection."); } client.close(); } } catch (TTransportException ttx) { if (!stopped_) { LOGGER.warn("Transport error occurred during acceptance of message", ttx); } } } } protected boolean waitForShutdown() { // Loop until awaitTermination finally does return without a interrupted // exception. If we don't do this, then we'll shut down prematurely. We want // to let the executorService clear it's task queue, closing client sockets // appropriately. long timeoutMS = stopTimeoutUnit.toMillis(stopTimeoutVal); long now = System.currentTimeMillis(); while (timeoutMS >= 0) { try { return executorService_.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); } catch (InterruptedException ix) { long newnow = System.currentTimeMillis(); timeoutMS -= (newnow - now); now = newnow; } } return false; } @Override public void stop() { stopped_ = true; serverTransport_.interrupt(); } private class WorkerProcess implements Runnable { /** Client that this services. */ private final TTransport client_; /** * Default constructor. * * @param client Transport to process */ private WorkerProcess(TTransport client) { client_ = client; } /** Loops on processing a client forever */ @Override public void run() { TProcessor processor = null; TTransport inputTransport = null; TTransport outputTransport = null; TProtocol inputProtocol = null; TProtocol outputProtocol = null; Optional eventHandler = Optional.empty(); ServerContext connectionContext = null; try { processor = processorFactory_.getProcessor(client_); inputTransport = inputTransportFactory_.getTransport(client_); outputTransport = outputTransportFactory_.getTransport(client_); inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); eventHandler = Optional.ofNullable(getEventHandler()); if (eventHandler.isPresent()) { connectionContext = eventHandler.get().createContext(inputProtocol, outputProtocol); } while (true) { if (Thread.currentThread().isInterrupted()) { LOGGER.debug("WorkerProcess requested to shutdown"); break; } if (eventHandler.isPresent()) { eventHandler.get().processContext(connectionContext, inputTransport, outputTransport); } // This process cannot be interrupted by Interrupting the Thread. This // will return once a message has been processed or the socket timeout // has elapsed, at which point it will return and check the interrupt // state of the thread. processor.process(inputProtocol, outputProtocol); } } catch (Exception x) { logException(x); } finally { if (eventHandler.isPresent()) { eventHandler.get().deleteContext(connectionContext, inputProtocol, outputProtocol); } if (inputTransport != null) { inputTransport.close(); } if (outputTransport != null) { outputTransport.close(); } if (client_.isOpen()) { client_.close(); } } } private void logException(Exception x) { // We'll usually receive RuntimeException types here // Need to unwrap to ascertain real causing exception before we choose to ignore // Ignoring err-logging all transport-level/type exceptions and SocketExceptions TTransportException tTransportException = null; if (x instanceof TTransportException) { tTransportException = (TTransportException) x; } else if (x.getCause() instanceof TTransportException) { tTransportException = (TTransportException) x.getCause(); } if (tTransportException != null) { switch (tTransportException.getType()) { case TTransportException.END_OF_FILE: case TTransportException.TIMED_OUT: return; // don't log these } if (tTransportException.getCause() != null && (tTransportException.getCause() instanceof SocketException)) { LOGGER.warn( "SocketException occurred during processing of message.", tTransportException.getCause()); return; } } // Log the exception at error level and continue LOGGER.error( (x instanceof TException ? "Thrift " : "") + "Error occurred during processing of message.", x); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TSimpleServer.java0000644000000000000000000000716614370300523027456 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Simple singlethreaded server for testing. */ public class TSimpleServer extends TServer { private static final Logger LOGGER = LoggerFactory.getLogger(TSimpleServer.class.getName()); public TSimpleServer(AbstractServerArgs args) { super(args); } @Override public void serve() { try { serverTransport_.listen(); } catch (TTransportException ttx) { LOGGER.error("Error occurred during listening.", ttx); return; } // Run the preServe event if (eventHandler_ != null) { eventHandler_.preServe(); } setServing(true); while (!stopped_) { TTransport client = null; TProcessor processor = null; TTransport inputTransport = null; TTransport outputTransport = null; TProtocol inputProtocol = null; TProtocol outputProtocol = null; ServerContext connectionContext = null; try { client = serverTransport_.accept(); if (client != null) { processor = processorFactory_.getProcessor(client); inputTransport = inputTransportFactory_.getTransport(client); outputTransport = outputTransportFactory_.getTransport(client); inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); if (eventHandler_ != null) { connectionContext = eventHandler_.createContext(inputProtocol, outputProtocol); } while (true) { if (eventHandler_ != null) { eventHandler_.processContext(connectionContext, inputTransport, outputTransport); } processor.process(inputProtocol, outputProtocol); } } } catch (TTransportException ttx) { // Client died, just move on LOGGER.debug("Client Transportation Exception", ttx); } catch (TException tx) { if (!stopped_) { LOGGER.error("Thrift error occurred during processing of message.", tx); } } catch (Exception x) { if (!stopped_) { LOGGER.error("Error occurred during processing of message.", x); } } if (eventHandler_ != null) { eventHandler_.deleteContext(connectionContext, inputProtocol, outputProtocol); } if (inputTransport != null) { inputTransport.close(); } if (outputTransport != null) { outputTransport.close(); } } setServing(false); } public void stop() { stopped_ = true; serverTransport_.interrupt(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/TSaslNonblockingServer.java0000644000000000000000000003711714303740367031324 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.security.auth.callback.CallbackHandler; import org.apache.thrift.TProcessor; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.sasl.NonblockingSaslHandler; import org.apache.thrift.transport.sasl.NonblockingSaslHandler.Phase; import org.apache.thrift.transport.sasl.TBaseSaslProcessorFactory; import org.apache.thrift.transport.sasl.TSaslProcessorFactory; import org.apache.thrift.transport.sasl.TSaslServerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** TServer with sasl support, using asynchronous execution and nonblocking io. */ public class TSaslNonblockingServer extends TServer { private static final Logger LOGGER = LoggerFactory.getLogger(TSaslNonblockingServer.class); private static final int DEFAULT_NETWORK_THREADS = 1; private static final int DEFAULT_AUTHENTICATION_THREADS = 1; private static final int DEFAULT_PROCESSING_THREADS = Runtime.getRuntime().availableProcessors(); private final AcceptorThread acceptor; private final NetworkThreadPool networkThreadPool; private final ExecutorService authenticationExecutor; private final ExecutorService processingExecutor; private final TSaslServerFactory saslServerFactory; private final TSaslProcessorFactory saslProcessorFactory; public TSaslNonblockingServer(Args args) throws IOException { super(args); acceptor = new AcceptorThread((TNonblockingServerSocket) serverTransport_); networkThreadPool = new NetworkThreadPool(args.networkThreads); authenticationExecutor = Executors.newFixedThreadPool(args.saslThreads); processingExecutor = Executors.newFixedThreadPool(args.processingThreads); saslServerFactory = args.saslServerFactory; saslProcessorFactory = args.saslProcessorFactory; } @Override public void serve() { if (eventHandler_ != null) { eventHandler_.preServe(); } networkThreadPool.start(); acceptor.start(); setServing(true); } /** Trigger a graceful shutdown, but it does not block to wait for the shutdown to finish. */ @Override public void stop() { if (!stopped_) { setServing(false); stopped_ = true; acceptor.wakeup(); networkThreadPool.wakeupAll(); authenticationExecutor.shutdownNow(); processingExecutor.shutdownNow(); } } /** * Gracefully shut down the server and block until all threads are stopped. * * @throws InterruptedException if is interrupted while waiting for shutdown. */ public void shutdown() throws InterruptedException { stop(); acceptor.join(); for (NetworkThread networkThread : networkThreadPool.networkThreads) { networkThread.join(); } while (!authenticationExecutor.isTerminated()) { authenticationExecutor.awaitTermination(10, TimeUnit.SECONDS); } while (!processingExecutor.isTerminated()) { processingExecutor.awaitTermination(10, TimeUnit.SECONDS); } } private class AcceptorThread extends Thread { private final TNonblockingServerTransport serverTransport; private final Selector acceptSelector; private AcceptorThread(TNonblockingServerSocket serverTransport) throws IOException { super("acceptor-thread"); this.serverTransport = serverTransport; acceptSelector = Selector.open(); serverTransport.registerSelector(acceptSelector); } @Override public void run() { try { serverTransport.listen(); while (!stopped_) { select(); acceptNewConnection(); } } catch (TTransportException e) { // Failed to listen. LOGGER.error("Failed to listen on server socket, error " + e.getType(), e); } catch (Throwable e) { // Unexpected errors. LOGGER.error("Unexpected error in acceptor thread.", e); } finally { TSaslNonblockingServer.this.stop(); close(); } } void wakeup() { acceptSelector.wakeup(); } private void acceptNewConnection() { Iterator selectedKeyItr = acceptSelector.selectedKeys().iterator(); while (!stopped_ && selectedKeyItr.hasNext()) { SelectionKey selected = selectedKeyItr.next(); selectedKeyItr.remove(); if (selected.isAcceptable()) { try { while (true) { // Accept all available connections from the backlog. TNonblockingTransport connection = serverTransport.accept(); if (connection == null) { break; } if (!networkThreadPool.acceptNewConnection(connection)) { LOGGER.error("Network thread does not accept: " + connection); connection.close(); } } } catch (TTransportException e) { LOGGER.warn("Failed to accept incoming connection.", e); } } else { LOGGER.error("Not acceptable selection: " + selected.channel()); } } } private void select() { try { acceptSelector.select(); } catch (IOException e) { LOGGER.error("Failed to select on the server socket.", e); } } private void close() { LOGGER.info("Closing acceptor thread."); serverTransport.close(); try { acceptSelector.close(); } catch (IOException e) { LOGGER.error("Failed to close accept selector.", e); } } } private class NetworkThread extends Thread { private final BlockingQueue incomingConnections = new LinkedBlockingQueue<>(); private final BlockingQueue stateTransitions = new LinkedBlockingQueue<>(); private final Selector ioSelector; NetworkThread(String name) throws IOException { super(name); ioSelector = Selector.open(); } @Override public void run() { try { while (!stopped_) { handleIncomingConnections(); handleStateChanges(); select(); handleIO(); } } catch (Throwable e) { LOGGER.error("Unreoverable error in " + getName(), e); } finally { close(); } } private void handleStateChanges() { while (true) { NonblockingSaslHandler statemachine = stateTransitions.poll(); if (statemachine == null) { return; } tryRunNextPhase(statemachine); } } private void select() { try { ioSelector.select(); } catch (IOException e) { LOGGER.error("Failed to select in " + getName(), e); } } private void handleIO() { Iterator selectedKeyItr = ioSelector.selectedKeys().iterator(); while (!stopped_ && selectedKeyItr.hasNext()) { SelectionKey selected = selectedKeyItr.next(); selectedKeyItr.remove(); if (!selected.isValid()) { closeChannel(selected); } NonblockingSaslHandler saslHandler = (NonblockingSaslHandler) selected.attachment(); if (selected.isReadable()) { saslHandler.handleRead(); } else if (selected.isWritable()) { saslHandler.handleWrite(); } else { LOGGER.error("Invalid intrest op " + selected.interestOps()); closeChannel(selected); continue; } if (saslHandler.isCurrentPhaseDone()) { tryRunNextPhase(saslHandler); } } } // The following methods are modifying the registered channel set on the selector, which itself // is not thread safe. Thus we need a lock to protect it from race condition. private synchronized void handleIncomingConnections() { while (true) { TNonblockingTransport connection = incomingConnections.poll(); if (connection == null) { return; } if (!connection.isOpen()) { LOGGER.warn("Incoming connection is already closed"); continue; } try { SelectionKey selectionKey = connection.registerSelector(ioSelector, SelectionKey.OP_READ); if (selectionKey.isValid()) { NonblockingSaslHandler saslHandler = new NonblockingSaslHandler( selectionKey, connection, saslServerFactory, saslProcessorFactory, inputProtocolFactory_, outputProtocolFactory_, eventHandler_); selectionKey.attach(saslHandler); } } catch (IOException e) { LOGGER.error("Failed to register connection for the selector, close it.", e); connection.close(); } } } private synchronized void close() { LOGGER.warn("Closing " + getName()); while (true) { TNonblockingTransport incomingConnection = incomingConnections.poll(); if (incomingConnection == null) { break; } incomingConnection.close(); } Set registered = ioSelector.keys(); for (SelectionKey selection : registered) { closeChannel(selection); } try { ioSelector.close(); } catch (IOException e) { LOGGER.error("Failed to close io selector " + getName(), e); } } private synchronized void closeChannel(SelectionKey selectionKey) { if (selectionKey.attachment() == null) { try { selectionKey.channel().close(); } catch (IOException e) { LOGGER.error("Failed to close channel.", e); } finally { selectionKey.cancel(); } } else { NonblockingSaslHandler saslHandler = (NonblockingSaslHandler) selectionKey.attachment(); saslHandler.close(); } } private void tryRunNextPhase(NonblockingSaslHandler saslHandler) { Phase nextPhase = saslHandler.getNextPhase(); saslHandler.stepToNextPhase(); switch (nextPhase) { case EVALUATING_SASL_RESPONSE: authenticationExecutor.submit(new Computation(saslHandler)); break; case PROCESSING: processingExecutor.submit(new Computation(saslHandler)); break; case CLOSING: saslHandler.runCurrentPhase(); break; default: // waiting for next io event for the current state machine } } public boolean accept(TNonblockingTransport connection) { if (stopped_) { return false; } if (incomingConnections.offer(connection)) { wakeup(); return true; } return false; } private void wakeup() { ioSelector.wakeup(); } private class Computation implements Runnable { private final NonblockingSaslHandler statemachine; private Computation(NonblockingSaslHandler statemachine) { this.statemachine = statemachine; } @Override public void run() { try { while (!statemachine.isCurrentPhaseDone()) { statemachine.runCurrentPhase(); } stateTransitions.add(statemachine); wakeup(); } catch (Throwable e) { LOGGER.error("Damn it!", e); } } } } private class NetworkThreadPool { private final List networkThreads; private int accepted = 0; NetworkThreadPool(int size) throws IOException { networkThreads = new ArrayList<>(size); int digits = (int) Math.log10(size) + 1; String threadNamePattern = "network-thread-%0" + digits + "d"; for (int i = 0; i < size; i++) { networkThreads.add(new NetworkThread(String.format(threadNamePattern, i))); } } /** * Round robin new connection among all the network threads. * * @param connection incoming connection. * @return true if the incoming connection is accepted by network thread pool. */ boolean acceptNewConnection(TNonblockingTransport connection) { return networkThreads.get((accepted++) % networkThreads.size()).accept(connection); } public void start() { for (NetworkThread thread : networkThreads) { thread.start(); } } void wakeupAll() { for (NetworkThread networkThread : networkThreads) { networkThread.wakeup(); } } } public static class Args extends AbstractServerArgs { private int networkThreads = DEFAULT_NETWORK_THREADS; private int saslThreads = DEFAULT_AUTHENTICATION_THREADS; private int processingThreads = DEFAULT_PROCESSING_THREADS; private TSaslServerFactory saslServerFactory = new TSaslServerFactory(); private TSaslProcessorFactory saslProcessorFactory; public Args(TNonblockingServerTransport transport) { super(transport); } public Args networkThreads(int networkThreads) { this.networkThreads = networkThreads <= 0 ? DEFAULT_NETWORK_THREADS : networkThreads; return this; } public Args saslThreads(int authenticationThreads) { this.saslThreads = authenticationThreads <= 0 ? DEFAULT_AUTHENTICATION_THREADS : authenticationThreads; return this; } public Args processingThreads(int processingThreads) { this.processingThreads = processingThreads <= 0 ? DEFAULT_PROCESSING_THREADS : processingThreads; return this; } public Args processor(TProcessor processor) { saslProcessorFactory = new TBaseSaslProcessorFactory(processor); return this; } public Args saslProcessorFactory(TSaslProcessorFactory saslProcessorFactory) { if (saslProcessorFactory == null) { throw new NullPointerException("Processor factory cannot be null"); } this.saslProcessorFactory = saslProcessorFactory; return this; } public Args addSaslMechanism( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { saslServerFactory.addSaslMechanism(mechanism, protocol, serverName, props, cbh); return this; } public Args saslServerFactory(TSaslServerFactory saslServerFactory) { if (saslServerFactory == null) { throw new NullPointerException("saslServerFactory cannot be null"); } this.saslServerFactory = saslServerFactory; return this; } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/server/AbstractNonblockingServer.java0000644000000000000000000005001114370300523032013 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.spi.SelectorProvider; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import org.apache.thrift.TAsyncProcessor; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TException; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TMemoryInputTransport; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.layered.TFramedTransport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Provides common methods and classes used by nonblocking TServer implementations. */ public abstract class AbstractNonblockingServer extends TServer { protected final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); public abstract static class AbstractNonblockingServerArgs< T extends AbstractNonblockingServerArgs> extends AbstractServerArgs { public long maxReadBufferBytes = 256 * 1024 * 1024; public AbstractNonblockingServerArgs(TNonblockingServerTransport transport) { super(transport); transportFactory(new TFramedTransport.Factory()); } } /** * The maximum amount of memory we will allocate to client IO buffers at a time. Without this * limit, the server will gladly allocate client buffers right into an out of memory exception, * rather than waiting. */ final long MAX_READ_BUFFER_BYTES; /** How many bytes are currently allocated to read buffers. */ final AtomicLong readBufferBytesAllocated = new AtomicLong(0); public AbstractNonblockingServer(AbstractNonblockingServerArgs args) { super(args); MAX_READ_BUFFER_BYTES = args.maxReadBufferBytes; } /** Begin accepting connections and processing invocations. */ public void serve() { // start any IO threads if (!startThreads()) { return; } // start listening, or exit if (!startListening()) { return; } setServing(true); // this will block while we serve waitForShutdown(); setServing(false); // do a little cleanup stopListening(); } /** * Starts any threads required for serving. * * @return true if everything went ok, false if threads could not be started. */ protected abstract boolean startThreads(); /** A method that will block until when threads handling the serving have been shut down. */ protected abstract void waitForShutdown(); /** * Have the server transport start accepting connections. * * @return true if we started listening successfully, false if something went wrong. */ protected boolean startListening() { try { serverTransport_.listen(); return true; } catch (TTransportException ttx) { LOGGER.error("Failed to start listening on server socket!", ttx); return false; } } /** Stop listening for connections. */ protected void stopListening() { serverTransport_.close(); } /** * Perform an invocation. This method could behave several different ways - invoke immediately * inline, queue for separate execution, etc. * * @return true if invocation was successfully requested, which is not a guarantee that invocation * has completed. False if the request failed. */ protected abstract boolean requestInvoke(FrameBuffer frameBuffer); /** * An abstract thread that handles selecting on a set of transports and {@link FrameBuffer * FrameBuffers} associated with selected keys corresponding to requests. */ protected abstract class AbstractSelectThread extends Thread { protected Selector selector; // List of FrameBuffers that want to change their selection interests. protected final Set selectInterestChanges = new HashSet(); public AbstractSelectThread() throws IOException { this.selector = SelectorProvider.provider().openSelector(); } /** If the selector is blocked, wake it up. */ public void wakeupSelector() { selector.wakeup(); } /** * Add FrameBuffer to the list of select interest changes and wake up the selector if it's * blocked. When the select() call exits, it'll give the FrameBuffer a chance to change its * interests. */ public void requestSelectInterestChange(FrameBuffer frameBuffer) { synchronized (selectInterestChanges) { selectInterestChanges.add(frameBuffer); } // wakeup the selector, if it's currently blocked. selector.wakeup(); } /** * Check to see if there are any FrameBuffers that have switched their interest type from read * to write or vice versa. */ protected void processInterestChanges() { synchronized (selectInterestChanges) { for (FrameBuffer fb : selectInterestChanges) { fb.changeSelectInterests(); } selectInterestChanges.clear(); } } /** * Do the work required to read from a readable client. If the frame is fully read, then invoke * the method call. */ protected void handleRead(SelectionKey key) { FrameBuffer buffer = (FrameBuffer) key.attachment(); if (!buffer.read()) { cleanupSelectionKey(key); return; } // if the buffer's frame read is complete, invoke the method. if (buffer.isFrameFullyRead() && !requestInvoke(buffer)) { cleanupSelectionKey(key); } } /** Let a writable client get written, if there's data to be written. */ protected void handleWrite(SelectionKey key) { FrameBuffer buffer = (FrameBuffer) key.attachment(); if (!buffer.write()) { cleanupSelectionKey(key); } } /** Do connection-close cleanup on a given SelectionKey. */ protected void cleanupSelectionKey(SelectionKey key) { // remove the records from the two maps FrameBuffer buffer = (FrameBuffer) key.attachment(); if (buffer != null) { // close the buffer buffer.close(); } // cancel the selection key key.cancel(); } } // SelectThread /** Possible states for the FrameBuffer state machine. */ private enum FrameBufferState { // in the midst of reading the frame size off the wire READING_FRAME_SIZE, // reading the actual frame data now, but not all the way done yet READING_FRAME, // completely read the frame, so an invocation can now happen READ_FRAME_COMPLETE, // waiting to get switched to listening for write events AWAITING_REGISTER_WRITE, // started writing response data, not fully complete yet WRITING, // another thread wants this framebuffer to go back to reading AWAITING_REGISTER_READ, // we want our transport and selection key invalidated in the selector // thread AWAITING_CLOSE } /** * Class that implements a sort of state machine around the interaction with a client and an * invoker. It manages reading the frame size and frame data, getting it handed off as wrapped * transports, and then the writing of response data back to the client. In the process it manages * flipping the read and write bits on the selection key for its client. */ public class FrameBuffer { private final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); // the actual transport hooked up to the client. protected final TNonblockingTransport trans_; // the SelectionKey that corresponds to our transport protected final SelectionKey selectionKey_; // the SelectThread that owns the registration of our transport protected final AbstractSelectThread selectThread_; // where in the process of reading/writing are we? protected FrameBufferState state_ = FrameBufferState.READING_FRAME_SIZE; // the ByteBuffer we'll be using to write and read, depending on the state protected ByteBuffer buffer_; protected final TByteArrayOutputStream response_; // the frame that the TTransport should wrap. protected final TMemoryInputTransport frameTrans_; // the transport that should be used to connect to clients protected final TTransport inTrans_; protected final TTransport outTrans_; // the input protocol to use on frames protected final TProtocol inProt_; // the output protocol to use on frames protected final TProtocol outProt_; // context associated with this connection protected final ServerContext context_; public FrameBuffer( final TNonblockingTransport trans, final SelectionKey selectionKey, final AbstractSelectThread selectThread) throws TTransportException { trans_ = trans; selectionKey_ = selectionKey; selectThread_ = selectThread; buffer_ = ByteBuffer.allocate(4); frameTrans_ = new TMemoryInputTransport(); response_ = new TByteArrayOutputStream(); inTrans_ = inputTransportFactory_.getTransport(frameTrans_); outTrans_ = outputTransportFactory_.getTransport(new TIOStreamTransport(response_)); inProt_ = inputProtocolFactory_.getProtocol(inTrans_); outProt_ = outputProtocolFactory_.getProtocol(outTrans_); if (eventHandler_ != null) { context_ = eventHandler_.createContext(inProt_, outProt_); } else { context_ = null; } } /** * Give this FrameBuffer a chance to read. The selector loop should have received a read event * for this FrameBuffer. * * @return true if the connection should live on, false if it should be closed */ public boolean read() { if (state_ == FrameBufferState.READING_FRAME_SIZE) { // try to read the frame size completely if (!internalRead()) { return false; } // if the frame size has been read completely, then prepare to read the // actual frame. if (buffer_.remaining() == 0) { // pull out the frame size as an integer. int frameSize = buffer_.getInt(0); if (frameSize <= 0) { LOGGER.error( "Read an invalid frame size of " + frameSize + ". Are you using TFramedTransport on the client side?"); return false; } // if this frame will always be too large for this server, log the // error and close the connection. if (frameSize > trans_.getMaxFrameSize()) { LOGGER.error( "Read a frame size of " + frameSize + ", which is bigger than the maximum allowable frame size " + trans_.getMaxFrameSize() + " for ALL connections."); return false; } // if this frame will push us over the memory limit, then return. // with luck, more memory will free up the next time around. if (readBufferBytesAllocated.get() + frameSize > MAX_READ_BUFFER_BYTES) { return true; } // increment the amount of memory allocated to read buffers readBufferBytesAllocated.addAndGet(frameSize + 4); // reallocate the readbuffer as a frame-sized buffer buffer_ = ByteBuffer.allocate(frameSize + 4); buffer_.putInt(frameSize); state_ = FrameBufferState.READING_FRAME; } else { // this skips the check of READING_FRAME state below, since we can't // possibly go on to that state if there's data left to be read at // this one. return true; } } // it is possible to fall through from the READING_FRAME_SIZE section // to READING_FRAME if there's already some frame data available once // READING_FRAME_SIZE is complete. if (state_ == FrameBufferState.READING_FRAME) { if (!internalRead()) { return false; } // since we're already in the select loop here for sure, we can just // modify our selection key directly. if (buffer_.remaining() == 0) { // get rid of the read select interests selectionKey_.interestOps(0); state_ = FrameBufferState.READ_FRAME_COMPLETE; } return true; } // if we fall through to this point, then the state must be invalid. LOGGER.error("Read was called but state is invalid (" + state_ + ")"); return false; } /** Give this FrameBuffer a chance to write its output to the final client. */ public boolean write() { if (state_ == FrameBufferState.WRITING) { try { if (trans_.write(buffer_) < 0) { return false; } } catch (TTransportException e) { LOGGER.warn("Got an Exception during write", e); return false; } // we're done writing. now we need to switch back to reading. if (buffer_.remaining() == 0) { prepareRead(); } return true; } LOGGER.error("Write was called, but state is invalid (" + state_ + ")"); return false; } /** Give this FrameBuffer a chance to set its interest to write, once data has come in. */ public void changeSelectInterests() { switch (state_) { case AWAITING_REGISTER_WRITE: // set the OP_WRITE interest selectionKey_.interestOps(SelectionKey.OP_WRITE); state_ = FrameBufferState.WRITING; break; case AWAITING_REGISTER_READ: prepareRead(); break; case AWAITING_CLOSE: close(); selectionKey_.cancel(); break; default: LOGGER.error("changeSelectInterest was called, but state is invalid ({})", state_); } } /** Shut the connection down. */ public void close() { // if we're being closed due to an error, we might have allocated a // buffer that we need to subtract for our memory accounting. if (state_ == FrameBufferState.READING_FRAME || state_ == FrameBufferState.READ_FRAME_COMPLETE || state_ == FrameBufferState.AWAITING_CLOSE) { readBufferBytesAllocated.addAndGet(-buffer_.array().length); } trans_.close(); if (eventHandler_ != null) { eventHandler_.deleteContext(context_, inProt_, outProt_); } } /** Check if this FrameBuffer has a full frame read. */ public boolean isFrameFullyRead() { return state_ == FrameBufferState.READ_FRAME_COMPLETE; } /** * After the processor has processed the invocation, whatever thread is managing invocations * should call this method on this FrameBuffer so we know it's time to start trying to write * again. Also, if it turns out that there actually isn't any data in the response buffer, we'll * skip trying to write and instead go back to reading. */ public void responseReady() { // the read buffer is definitely no longer in use, so we will decrement // our read buffer count. we do this here as well as in close because // we'd like to free this read memory up as quickly as possible for other // clients. readBufferBytesAllocated.addAndGet(-buffer_.array().length); if (response_.len() == 0) { // go straight to reading again. this was probably an oneway method state_ = FrameBufferState.AWAITING_REGISTER_READ; buffer_ = null; } else { buffer_ = ByteBuffer.wrap(response_.get(), 0, response_.len()); // set state that we're waiting to be switched to write. we do this // asynchronously through requestSelectInterestChange() because there is // a possibility that we're not in the main thread, and thus currently // blocked in select(). (this functionality is in place for the sake of // the HsHa server.) state_ = FrameBufferState.AWAITING_REGISTER_WRITE; } requestSelectInterestChange(); } /** Actually invoke the method signified by this FrameBuffer. */ public void invoke() { frameTrans_.reset(buffer_.array()); response_.reset(); try { if (eventHandler_ != null) { eventHandler_.processContext(context_, inTrans_, outTrans_); } processorFactory_.getProcessor(inTrans_).process(inProt_, outProt_); responseReady(); return; } catch (TException te) { LOGGER.warn("Exception while invoking!", te); } catch (Throwable t) { LOGGER.error("Unexpected throwable while invoking!", t); } // This will only be reached when there is a throwable. state_ = FrameBufferState.AWAITING_CLOSE; requestSelectInterestChange(); } /** * Perform a read into buffer. * * @return true if the read succeeded, false if there was an error or the connection closed. */ private boolean internalRead() { try { return trans_.read(buffer_) >= 0; } catch (TTransportException e) { LOGGER.warn("Got an Exception in internalRead", e); return false; } } /** We're done writing, so reset our interest ops and change state accordingly. */ private void prepareRead() { // we can set our interest directly without using the queue because // we're in the select thread. selectionKey_.interestOps(SelectionKey.OP_READ); // get ready for another go-around buffer_ = ByteBuffer.allocate(4); state_ = FrameBufferState.READING_FRAME_SIZE; } /** * When this FrameBuffer needs to change its select interests and execution might not be in its * select thread, then this method will make sure the interest change gets done when the select * thread wakes back up. When the current thread is this FrameBuffer's select thread, then it * just does the interest change immediately. */ protected void requestSelectInterestChange() { if (Thread.currentThread() == this.selectThread_) { changeSelectInterests(); } else { this.selectThread_.requestSelectInterestChange(this); } } } // FrameBuffer public class AsyncFrameBuffer extends FrameBuffer { public AsyncFrameBuffer( TNonblockingTransport trans, SelectionKey selectionKey, AbstractSelectThread selectThread) throws TTransportException { super(trans, selectionKey, selectThread); } public TProtocol getInputProtocol() { return inProt_; } public TProtocol getOutputProtocol() { return outProt_; } public void invoke() { frameTrans_.reset(buffer_.array()); response_.reset(); try { if (eventHandler_ != null) { eventHandler_.processContext(context_, inTrans_, outTrans_); } ((TAsyncProcessor) processorFactory_.getProcessor(inTrans_)).process(this); return; } catch (TException te) { LOGGER.warn("Exception while invoking!", te); } catch (Throwable t) { LOGGER.error("Unexpected throwable while invoking!", t); } // This will only be reached when there is a throwable. state_ = FrameBufferState.AWAITING_CLOSE; requestSelectInterestChange(); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/0000777000000000000000000000000014452237057024603 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TNonblockingTransport.java0000644000000000000000000000322414303740367031745 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.net.SocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import org.apache.thrift.TConfiguration; public abstract class TNonblockingTransport extends TEndpointTransport { public TNonblockingTransport(TConfiguration config) throws TTransportException { super(config); } /** * Non-blocking connection initialization. * * @see java.nio.channels.SocketChannel#connect(SocketAddress remote) */ public abstract boolean startConnect() throws IOException; /** * Non-blocking connection completion. * * @see java.nio.channels.SocketChannel#finishConnect() */ public abstract boolean finishConnect() throws IOException; public abstract SelectionKey registerSelector(Selector selector, int interests) throws IOException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TFileTransport.java0000644000000000000000000004061714312132005030350 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Random; import org.apache.thrift.TConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * FileTransport implementation of the TTransport interface. Currently this is a straightforward * port of the cpp implementation * *

It may make better sense to provide a basic stream access on top of the framed file format The * FileTransport can then be a user of this framed file format with some additional logic for * chunking. */ public class TFileTransport extends TTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TFileTransport.class.getName()); public static class TruncableBufferedInputStream extends BufferedInputStream { public void trunc() { pos = count = 0; } public TruncableBufferedInputStream(InputStream in) { super(in); } public TruncableBufferedInputStream(InputStream in, int size) { super(in, size); } } public static class Event { private byte[] buf_; private int nread_; private int navailable_; /** * Initialize an event. Initially, it has no valid contents * * @param buf byte array buffer to store event */ public Event(byte[] buf) { buf_ = buf; nread_ = navailable_ = 0; } public byte[] getBuf() { return buf_; } public int getSize() { return buf_.length; } public void setAvailable(int sz) { nread_ = 0; navailable_ = sz; } public int getRemaining() { return (navailable_ - nread_); } public int emit(byte[] buf, int offset, int ndesired) { if ((ndesired == 0) || (ndesired > getRemaining())) ndesired = getRemaining(); if (ndesired <= 0) return (ndesired); System.arraycopy(buf_, nread_, buf, offset, ndesired); nread_ += ndesired; return (ndesired); } } public static class ChunkState { /** Chunk Size. Must be same across all implementations */ public static final int DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; private int chunk_size_ = DEFAULT_CHUNK_SIZE; private long offset_ = 0; public ChunkState() {} public ChunkState(int chunk_size) { chunk_size_ = chunk_size; } public void skip(int size) { offset_ += size; } public void seek(long offset) { offset_ = offset; } public int getChunkSize() { return chunk_size_; } public int getChunkNum() { return ((int) (offset_ / chunk_size_)); } public int getRemaining() { return (chunk_size_ - ((int) (offset_ % chunk_size_))); } public long getOffset() { return (offset_); } } public enum TailPolicy { NOWAIT(0, 0), WAIT_FOREVER(500, -1); /** Time in milliseconds to sleep before next read If 0, no sleep */ public final int timeout_; /** Number of retries before giving up if 0, no retries if -1, retry forever */ public final int retries_; /** * ctor for policy * * @param timeout sleep time for this particular policy * @param retries number of retries */ TailPolicy(int timeout, int retries) { timeout_ = timeout; retries_ = retries; } } /** Current tailing policy */ TailPolicy currentPolicy_ = TailPolicy.NOWAIT; /** Underlying file being read */ protected TSeekableFile inputFile_ = null; /** Underlying outputStream */ protected OutputStream outputStream_ = null; /** Event currently read in */ Event currentEvent_ = null; /** InputStream currently being used for reading */ InputStream inputStream_ = null; /** current Chunk state */ ChunkState cs = null; /** is read only? */ private boolean readOnly_ = false; /** * Get File Tailing Policy * * @return current read policy */ public TailPolicy getTailPolicy() { return (currentPolicy_); } /** * Set file Tailing Policy * * @param policy New policy to set * @return Old policy */ public TailPolicy setTailPolicy(TailPolicy policy) { TailPolicy old = currentPolicy_; currentPolicy_ = policy; return (old); } /** * Initialize read input stream * * @return input stream to read from file */ private InputStream createInputStream() throws TTransportException { InputStream is; try { if (inputStream_ != null) { ((TruncableBufferedInputStream) inputStream_).trunc(); is = inputStream_; } else { is = new TruncableBufferedInputStream(inputFile_.getInputStream()); } } catch (IOException iox) { throw new TTransportException(iox.getMessage(), iox); } return (is); } /** * Read (potentially tailing) an input stream * * @param is InputStream to read from * @param buf Buffer to read into * @param off Offset in buffer to read into * @param len Number of bytes to read * @param tp policy to use if we hit EOF * @return number of bytes read */ private int tailRead(InputStream is, byte[] buf, int off, int len, TailPolicy tp) throws TTransportException { int orig_len = len; try { int retries = 0; while (len > 0) { int cnt = is.read(buf, off, len); if (cnt > 0) { off += cnt; len -= cnt; retries = 0; cs.skip(cnt); // remember that we read so many bytes } else if (cnt == -1) { // EOF retries++; if ((tp.retries_ != -1) && tp.retries_ < retries) return (orig_len - len); if (tp.timeout_ > 0) { try { Thread.sleep(tp.timeout_); } catch (InterruptedException e) { } } } else { // either non-zero or -1 is what the contract says! throw new TTransportException("Unexpected return from InputStream.read = " + cnt); } } } catch (IOException iox) { throw new TTransportException(iox.getMessage(), iox); } return (orig_len - len); } /** * Event is corrupted. Do recovery * * @return true if recovery could be performed and we can read more data false is returned only * when nothing more can be read */ private boolean performRecovery() throws TTransportException { int numChunks = getNumChunks(); int curChunk = cs.getChunkNum(); if (curChunk >= (numChunks - 1)) { return false; } seekToChunk(curChunk + 1); return true; } /** * Read event from underlying file * * @return true if event could be read, false otherwise (on EOF) */ private boolean readEvent() throws TTransportException { byte[] ebytes = new byte[4]; int esize; int nread; int nrequested; retry: do { // corner case. read to end of chunk nrequested = cs.getRemaining(); if (nrequested < 4) { nread = tailRead(inputStream_, ebytes, 0, nrequested, currentPolicy_); if (nread != nrequested) { return (false); } } // assuming serialized on little endian machine nread = tailRead(inputStream_, ebytes, 0, 4, currentPolicy_); if (nread != 4) { return (false); } esize = 0; for (int i = 3; i >= 0; i--) { int val = (0x000000ff & (int) ebytes[i]); esize |= (val << (i * 8)); } // check if event is corrupted and do recovery as required if (esize > cs.getRemaining()) { throw new TTransportException("FileTransport error: bad event size"); /* if(performRecovery()) { esize=0; } else { return false; } */ } } while (esize == 0); // reset existing event or get a larger one if (currentEvent_.getSize() < esize) currentEvent_ = new Event(new byte[esize]); // populate the event byte[] buf = currentEvent_.getBuf(); nread = tailRead(inputStream_, buf, 0, esize, currentPolicy_); if (nread != esize) { return (false); } currentEvent_.setAvailable(esize); return (true); } /** * open if both input/output open unless readonly * * @return true */ public boolean isOpen() { return ((inputStream_ != null) && (readOnly_ || (outputStream_ != null))); } /** * Diverging from the cpp model and sticking to the TSocket model Files are not opened in ctor - * but in explicit open call */ public void open() throws TTransportException { if (isOpen()) throw new TTransportException(TTransportException.ALREADY_OPEN); try { inputStream_ = createInputStream(); cs = new ChunkState(); currentEvent_ = new Event(new byte[256]); if (!readOnly_) outputStream_ = new BufferedOutputStream(inputFile_.getOutputStream()); } catch (IOException iox) { throw new TTransportException(TTransportException.NOT_OPEN, iox); } } /** Closes the transport. */ public void close() { if (inputFile_ != null) { try { inputFile_.close(); } catch (IOException iox) { LOGGER.warn("WARNING: Error closing input file: " + iox.getMessage()); } inputFile_ = null; } if (outputStream_ != null) { try { outputStream_.close(); } catch (IOException iox) { LOGGER.warn("WARNING: Error closing output stream: " + iox.getMessage()); } outputStream_ = null; } } /** * File Transport ctor * * @param path File path to read and write from * @param readOnly Whether this is a read-only transport * @throws IOException if there is an error accessing the file. */ public TFileTransport(final String path, boolean readOnly) throws IOException { inputFile_ = new TStandardFile(path); readOnly_ = readOnly; } /** * File Transport ctor * * @param inputFile open TSeekableFile to read/write from * @param readOnly Whether this is a read-only transport */ public TFileTransport(TSeekableFile inputFile, boolean readOnly) { inputFile_ = inputFile; readOnly_ = readOnly; } /** * Cloned from TTransport.java:readAll(). Only difference is throwing an EOF exception where one * is detected. */ public int readAll(byte[] buf, int off, int len) throws TTransportException { int got = 0; int ret = 0; while (got < len) { ret = read(buf, off + got, len - got); if (ret < 0) { throw new TTransportException("Error in reading from file"); } if (ret == 0) { throw new TTransportException(TTransportException.END_OF_FILE, "End of File reached"); } got += ret; } return got; } /** * Reads up to len bytes into buffer buf, starting at offset off. * * @param buf Array to read into * @param off Index to start reading at * @param len Maximum number of bytes to read * @return The number of bytes actually read * @throws TTransportException if there was an error reading data */ public int read(byte[] buf, int off, int len) throws TTransportException { if (!isOpen()) throw new TTransportException(TTransportException.NOT_OPEN, "Must open before reading"); if (currentEvent_.getRemaining() == 0 && !readEvent()) { return 0; } return currentEvent_.emit(buf, off, len); } public int getNumChunks() throws TTransportException { if (!isOpen()) throw new TTransportException(TTransportException.NOT_OPEN, "Must open before getNumChunks"); try { long len = inputFile_.length(); if (len == 0) return 0; else return (((int) (len / cs.getChunkSize())) + 1); } catch (IOException iox) { throw new TTransportException(iox.getMessage(), iox); } } public int getCurChunk() throws TTransportException { if (!isOpen()) throw new TTransportException(TTransportException.NOT_OPEN, "Must open before getCurChunk"); return (cs.getChunkNum()); } public void seekToChunk(int chunk) throws TTransportException { if (!isOpen()) throw new TTransportException(TTransportException.NOT_OPEN, "Must open before seeking"); int numChunks = getNumChunks(); // file is empty, seeking to chunk is pointless if (numChunks == 0) { return; } // negative indicates reverse seek (from the end) if (chunk < 0) { chunk += numChunks; } // too large a value for reverse seek, just seek to beginning if (chunk < 0) { chunk = 0; } long eofOffset = 0; boolean seekToEnd = (chunk >= numChunks); if (seekToEnd) { chunk = chunk - 1; try { eofOffset = inputFile_.length(); } catch (IOException iox) { throw new TTransportException(iox.getMessage(), iox); } } if (chunk * cs.getChunkSize() != cs.getOffset()) { try { inputFile_.seek((long) chunk * cs.getChunkSize()); } catch (IOException iox) { throw new TTransportException("Seek to chunk " + chunk + " " + iox.getMessage(), iox); } cs.seek((long) chunk * cs.getChunkSize()); currentEvent_.setAvailable(0); inputStream_ = createInputStream(); } if (seekToEnd) { // waiting forever here - otherwise we can hit EOF and end up // having consumed partial data from the data stream. TailPolicy old = setTailPolicy(TailPolicy.WAIT_FOREVER); while (cs.getOffset() < eofOffset) { readEvent(); } currentEvent_.setAvailable(0); setTailPolicy(old); } } public void seekToEnd() throws TTransportException { if (!isOpen()) throw new TTransportException(TTransportException.NOT_OPEN, "Must open before seeking"); seekToChunk(getNumChunks()); } /** * Writes up to len bytes from the buffer. * * @param buf The output data buffer * @param off The offset to start writing from * @param len The number of bytes to write * @throws TTransportException if there was an error writing data */ public void write(byte[] buf, int off, int len) throws TTransportException { throw new TTransportException("Not Supported"); } /** * Flush any pending data out of a transport buffer. * * @throws TTransportException if there was an error writing out data. */ public void flush() throws TTransportException { throw new TTransportException("Not Supported"); } @Override public TConfiguration getConfiguration() { return null; } @Override public void updateKnownMessageSize(long size) throws TTransportException {} @Override public void checkReadBytesAvailable(long numBytes) throws TTransportException {} /** test program */ public static void main(String[] args) throws Exception { int num_chunks = 10; if ((args.length < 1) || args[0].equals("--help") || args[0].equals("-h") || args[0].equals("-?")) { printUsage(); } if (args.length > 1) { try { num_chunks = Integer.parseInt(args[1]); } catch (Exception e) { LOGGER.error("Cannot parse " + args[1]); printUsage(); } } TFileTransport t = new TFileTransport(args[0], true); t.open(); LOGGER.info("NumChunks=" + t.getNumChunks()); Random r = new Random(); for (int j = 0; j < num_chunks; j++) { byte[] buf = new byte[4096]; int cnum = r.nextInt(t.getNumChunks() - 1); LOGGER.info("Reading chunk " + cnum); t.seekToChunk(cnum); for (int i = 0; i < 4096; i++) { t.read(buf, 0, 4096); } } } private static void printUsage() { LOGGER.error("Usage: TFileTransport [num_chunks]"); LOGGER.error(" (Opens and reads num_chunks chunks from file randomly)"); System.exit(1); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TMemoryInputTransport.java0000644000000000000000000000644114303740367031776 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TConfiguration; public final class TMemoryInputTransport extends TEndpointTransport { private byte[] buf_; private int pos_; private int endPos_; public TMemoryInputTransport() throws TTransportException { this(new TConfiguration()); } public TMemoryInputTransport(TConfiguration _configuration) throws TTransportException { this(_configuration, new byte[0]); } public TMemoryInputTransport(byte[] buf) throws TTransportException { this(new TConfiguration(), buf); } public TMemoryInputTransport(TConfiguration _configuration, byte[] buf) throws TTransportException { this(_configuration, buf, 0, buf.length); } public TMemoryInputTransport(byte[] buf, int offset, int length) throws TTransportException { this(new TConfiguration(), buf, offset, length); } public TMemoryInputTransport(TConfiguration _configuration, byte[] buf, int offset, int length) throws TTransportException { super(_configuration); reset(buf, offset, length); updateKnownMessageSize(length); } public void reset(byte[] buf) { reset(buf, 0, buf.length); } public void reset(byte[] buf, int offset, int length) { buf_ = buf; pos_ = offset; endPos_ = offset + length; try { resetConsumedMessageSize(-1); } catch (TTransportException e) { // ignore } } public void clear() { buf_ = null; try { resetConsumedMessageSize(-1); } catch (TTransportException e) { // ignore } } @Override public void close() {} @Override public boolean isOpen() { return true; } @Override public void open() throws TTransportException {} @Override public int read(byte[] buf, int off, int len) throws TTransportException { int bytesRemaining = getBytesRemainingInBuffer(); int amtToRead = (len > bytesRemaining ? bytesRemaining : len); if (amtToRead > 0) { System.arraycopy(buf_, pos_, buf, off, amtToRead); consumeBuffer(amtToRead); countConsumedMessageBytes(amtToRead); } return amtToRead; } @Override public void write(byte[] buf, int off, int len) throws TTransportException { throw new UnsupportedOperationException("No writing allowed!"); } @Override public byte[] getBuffer() { return buf_; } public int getBufferPosition() { return pos_; } public int getBytesRemainingInBuffer() { return endPos_ - pos_; } public void consumeBuffer(int len) { pos_ += len; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TIOStreamTransport.java0000644000000000000000000001431714452237057031174 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketTimeoutException; import org.apache.thrift.TConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is the most commonly used base transport. It takes an InputStream or an OutputStream or both * and uses it/them to perform transport operations. This allows for compatibility with all the nice * constructs Java already has to provide a variety of types of streams. */ public class TIOStreamTransport extends TEndpointTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TIOStreamTransport.class.getName()); /** Underlying inputStream */ protected InputStream inputStream_ = null; /** Underlying outputStream */ protected OutputStream outputStream_ = null; /** * Subclasses can invoke the default constructor and then assign the input streams in the open * method. */ protected TIOStreamTransport(TConfiguration config) throws TTransportException { super(config); } /** * Subclasses can invoke the default constructor and then assign the input streams in the open * method. */ protected TIOStreamTransport() throws TTransportException { super(new TConfiguration()); } /** * Input stream constructor, constructs an input only transport. * * @param config * @param is Input stream to read from */ public TIOStreamTransport(TConfiguration config, InputStream is) throws TTransportException { super(config); inputStream_ = is; } /** * Input stream constructor, constructs an input only transport. * * @param is Input stream to read from */ public TIOStreamTransport(InputStream is) throws TTransportException { super(new TConfiguration()); inputStream_ = is; } /** * Output stream constructor, constructs an output only transport. * * @param config * @param os Output stream to write to */ public TIOStreamTransport(TConfiguration config, OutputStream os) throws TTransportException { super(config); outputStream_ = os; } /** * Output stream constructor, constructs an output only transport. * * @param os Output stream to write to */ public TIOStreamTransport(OutputStream os) throws TTransportException { super(new TConfiguration()); outputStream_ = os; } /** * Two-way stream constructor. * * @param config * @param is Input stream to read from * @param os Output stream to read from */ public TIOStreamTransport(TConfiguration config, InputStream is, OutputStream os) throws TTransportException { super(config); inputStream_ = is; outputStream_ = os; } /** * Two-way stream constructor. * * @param is Input stream to read from * @param os Output stream to read from */ public TIOStreamTransport(InputStream is, OutputStream os) throws TTransportException { super(new TConfiguration()); inputStream_ = is; outputStream_ = os; } /** * @return false after close is called. */ public boolean isOpen() { return inputStream_ != null || outputStream_ != null; } /** The streams must already be open. This method does nothing. */ public void open() throws TTransportException {} /** Closes both the input and output streams. */ public void close() { try { if (inputStream_ != null) { try { inputStream_.close(); } catch (IOException iox) { LOGGER.warn("Error closing input stream.", iox); } } if (outputStream_ != null) { try { outputStream_.close(); } catch (IOException iox) { LOGGER.warn("Error closing output stream.", iox); } } } finally { inputStream_ = null; outputStream_ = null; } } /** Reads from the underlying input stream if not null. */ public int read(byte[] buf, int off, int len) throws TTransportException { if (inputStream_ == null) { throw new TTransportException( TTransportException.NOT_OPEN, "Cannot read from null inputStream"); } int bytesRead; try { bytesRead = inputStream_.read(buf, off, len); } catch (SocketTimeoutException ste) { throw new TTransportException(TTransportException.TIMED_OUT, ste); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } if (bytesRead < 0) { throw new TTransportException(TTransportException.END_OF_FILE, "Socket is closed by peer."); } return bytesRead; } /** Writes to the underlying output stream if not null. */ public void write(byte[] buf, int off, int len) throws TTransportException { if (outputStream_ == null) { throw new TTransportException( TTransportException.NOT_OPEN, "Cannot write to null outputStream"); } try { outputStream_.write(buf, off, len); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } /** Flushes the underlying output stream if not null. */ public void flush() throws TTransportException { if (outputStream_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "Cannot flush null outputStream"); } try { outputStream_.flush(); resetConsumedMessageSize(-1); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TZlibTransport.java0000644000000000000000000001017714303740367030407 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Objects; import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; import java.util.zip.Inflater; import java.util.zip.InflaterInputStream; import org.apache.thrift.TConfiguration; /** TZlibTransport deflates on write and inflates on read. */ public class TZlibTransport extends TIOStreamTransport { private TTransport transport_ = null; public static class Factory extends TTransportFactory { public Factory() {} @Override public TTransport getTransport(TTransport base) throws TTransportException { return new TZlibTransport(base); } } /** * Constructs a new TZlibTransport instance. * * @param transport the underlying transport to read from and write to */ public TZlibTransport(TTransport transport) throws TTransportException { this(transport, Deflater.BEST_COMPRESSION); } /** * Constructs a new TZlibTransport instance. * * @param transport the underlying transport to read from and write to * @param compressionLevel 0 for no compression, 9 for maximum compression */ public TZlibTransport(TTransport transport, int compressionLevel) throws TTransportException { super( Objects.isNull(transport.getConfiguration()) ? new TConfiguration() : transport.getConfiguration()); transport_ = transport; inputStream_ = new InflaterInputStream(new TTransportInputStream(transport_), new Inflater()); outputStream_ = new DeflaterOutputStream( new TTransportOutputStream(transport_), new Deflater(compressionLevel, false), true); } @Override public boolean isOpen() { return transport_.isOpen(); } @Override public void open() throws TTransportException { transport_.open(); } @Override public void close() { super.close(); if (transport_.isOpen()) { transport_.close(); } } } class TTransportInputStream extends InputStream { private TTransport transport = null; public TTransportInputStream(TTransport transport) { this.transport = transport; } @Override public int read() throws IOException { try { byte[] buf = new byte[1]; transport.read(buf, 0, 1); return buf[0]; } catch (TTransportException e) { throw new IOException(e); } } @Override public int read(byte b[], int off, int len) throws IOException { try { return transport.read(b, off, len); } catch (TTransportException e) { throw new IOException(e); } } } class TTransportOutputStream extends OutputStream { private TTransport transport = null; public TTransportOutputStream(TTransport transport) { this.transport = transport; } @Override public void write(final int b) throws IOException { try { transport.write(new byte[] {(byte) b}); } catch (TTransportException e) { throw new IOException(e); } } @Override public void write(byte b[], int off, int len) throws IOException { try { transport.write(b, off, len); } catch (TTransportException e) { throw new IOException(e); } } @Override public void flush() throws IOException { try { transport.flush(); } catch (TTransportException e) { throw new IOException(e); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TNonblockingServerTransport.java0000644000000000000000000000244714303740367033142 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.nio.channels.Selector; /** Server transport that can be operated in a nonblocking fashion. */ public abstract class TNonblockingServerTransport extends TServerTransport { public abstract void registerSelector(Selector selector); /** * @return an incoming connection or null if there is none. * @throws TTransportException on error during this operation. */ @Override public abstract TNonblockingTransport accept() throws TTransportException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TEOFException.java0000644000000000000000000000205214303740367030053 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; /** End of file, especially, the underlying socket is closed. */ public class TEOFException extends TTransportException { public TEOFException(String message) { super(TTransportException.END_OF_FILE, message); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/0000777000000000000000000000000014370300523025531 5ustar00rootroot00000000000000SaslNegotiationHeaderReader.java0000644000000000000000000000355514303740367033672 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.PROTOCOL_ERROR; /** * Header for sasl negotiation frames. It contains status byte of negotiation and a 4-byte integer * (payload size). */ public class SaslNegotiationHeaderReader extends FixedSizeHeaderReader { public static final int STATUS_BYTES = 1; public static final int PAYLOAD_LENGTH_BYTES = 4; private NegotiationStatus negotiationStatus; private int payloadSize; @Override protected int headerSize() { return STATUS_BYTES + PAYLOAD_LENGTH_BYTES; } @Override protected void onComplete() throws TSaslNegotiationException { negotiationStatus = NegotiationStatus.byValue(byteBuffer.get(0)); payloadSize = byteBuffer.getInt(1); if (payloadSize < 0) { throw new TSaslNegotiationException( PROTOCOL_ERROR, "Payload size is negative: " + payloadSize); } } @Override public int payloadSize() { return payloadSize; } public NegotiationStatus getStatus() { return negotiationStatus; } } TInvalidSaslFrameException.java0000644000000000000000000000212314303740367033510 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; /** Got an invalid frame that does not respect the thrift sasl protocol. */ public class TInvalidSaslFrameException extends TSaslNegotiationException { public TInvalidSaslFrameException(String message) { super(ErrorType.PROTOCOL_ERROR, message); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/ServerSaslPeer.java0000644000000000000000000000643114303740367031313 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.AUTHENTICATION_FAILURE; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import org.apache.thrift.transport.TTransportException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Server side sasl peer, a wrapper around SaslServer to provide some handy methods. */ public class ServerSaslPeer implements SaslPeer { private static final Logger LOGGER = LoggerFactory.getLogger(ServerSaslPeer.class); private static final String QOP_AUTH_INT = "auth-int"; private static final String QOP_AUTH_CONF = "auth-conf"; private final SaslServer saslServer; public ServerSaslPeer(SaslServer saslServer) { this.saslServer = saslServer; } @Override public byte[] evaluate(byte[] negotiationMessage) throws TSaslNegotiationException { try { return saslServer.evaluateResponse(negotiationMessage); } catch (SaslException e) { throw new TSaslNegotiationException( AUTHENTICATION_FAILURE, "Authentication failed with " + saslServer.getMechanismName(), e); } } @Override public boolean isAuthenticated() { return saslServer.isComplete(); } @Override public boolean isDataProtected() { Object qop = saslServer.getNegotiatedProperty(Sasl.QOP); if (qop == null) { return false; } for (String word : qop.toString().split("\\s*,\\s*")) { String lowerCaseWord = word.toLowerCase(); if (QOP_AUTH_INT.equals(lowerCaseWord) || QOP_AUTH_CONF.equals(lowerCaseWord)) { return true; } } return false; } @Override public byte[] wrap(byte[] data, int offset, int length) throws TTransportException { try { return saslServer.wrap(data, offset, length); } catch (SaslException e) { throw new TTransportException("Failed to wrap data", e); } } @Override public byte[] unwrap(byte[] data, int offset, int length) throws TTransportException { try { return saslServer.unwrap(data, offset, length); } catch (SaslException e) { throw new TTransportException(TTransportException.CORRUPTED_DATA, "Failed to unwrap data", e); } } @Override public void dispose() { try { saslServer.dispose(); } catch (Exception e) { LOGGER.warn("Failed to close sasl server " + saslServer.getMechanismName(), e); } } SaslServer getSaslServer() { return saslServer; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/FrameReader.java0000644000000000000000000001130514303740367030557 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import java.nio.ByteBuffer; import org.apache.thrift.transport.TEOFException; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; /** * Read frames from a transport. Each frame has a header and a payload. A header will indicate the * size of the payload and other informations about how to decode payload. Implementations should * subclass it by providing a header reader implementation. * * @param Header type. */ public abstract class FrameReader { private final T header; private ByteBuffer payload; protected FrameReader(T header) { this.header = header; } /** * (Nonblocking) Read available bytes out of the transport without blocking to wait for incoming * data. * * @param transport TTransport * @return true if current frame is complete after read. * @throws TSaslNegotiationException if fail to read back a valid sasl negotiation message. * @throws TTransportException if io error. */ public boolean read(TTransport transport) throws TSaslNegotiationException, TTransportException { if (!header.isComplete()) { if (readHeader(transport)) { payload = ByteBuffer.allocate(header.payloadSize()); } else { return false; } } if (header.payloadSize() == 0) { return true; } return readPayload(transport); } /** * (Nonblocking) Try to read available header bytes from transport. * * @return true if header is complete after read. * @throws TSaslNegotiationException if fail to read back a validd sasl negotiation header. * @throws TTransportException if io error. */ private boolean readHeader(TTransport transport) throws TSaslNegotiationException, TTransportException { return header.read(transport); } /** * (Nonblocking) Try to read available * * @param transport underlying transport. * @return true if payload is complete after read. * @throws TTransportException if io error. */ private boolean readPayload(TTransport transport) throws TTransportException { readAvailable(transport, payload); return payload.hasRemaining(); } /** * @return header of the frame */ public T getHeader() { return header; } /** * @return number of bytes of the header */ public int getHeaderSize() { return header.toBytes().length; } /** * @return byte array of the payload */ public byte[] getPayload() { return payload.array(); } /** * @return size of the payload */ public int getPayloadSize() { return header.payloadSize(); } /** * @return true if the reader has fully read a frame */ public boolean isComplete() { return !(payload == null || payload.hasRemaining()); } /** Reset the state of the reader so that it can be reused to read a new frame. */ public void clear() { header.clear(); payload = null; } /** * Read immediately available bytes from the transport into the byte buffer. * * @param transport TTransport * @param recipient ByteBuffer * @return number of bytes read out of the transport * @throws TTransportException if io error */ static int readAvailable(TTransport transport, ByteBuffer recipient) throws TTransportException { if (!recipient.hasRemaining()) { throw new IllegalStateException( "Trying to fill a full recipient with " + recipient.limit() + " bytes"); } int currentPosition = recipient.position(); byte[] bytes = recipient.array(); int offset = recipient.arrayOffset() + currentPosition; int expectedLength = recipient.remaining(); int got = transport.read(bytes, offset, expectedLength); if (got < 0) { throw new TEOFException( "Transport is closed, while trying to read " + expectedLength + " bytes"); } recipient.position(currentPosition + got); return got; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/DataFrameWriter.java0000644000000000000000000000465014370300523031416 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES; import java.nio.ByteBuffer; import org.apache.thrift.EncodingUtils; import org.apache.thrift.utils.StringUtils; /** * Write frames of thrift messages. It expects an empty/null header to be provided with a payload to * be written out. Non empty headers are considered as error. */ public class DataFrameWriter extends FrameWriter { @Override public void withOnlyPayload(byte[] payload, int offset, int length) { if (!isComplete()) { throw new IllegalStateException( "Previous write is not yet complete, with " + frameBytes.remaining() + " bytes left."); } frameBytes = buildFrameWithPayload(payload, offset, length); } @Override protected ByteBuffer buildFrame( byte[] header, int headerOffset, int headerLength, byte[] payload, int payloadOffset, int payloadLength) { if (header != null && headerLength > 0) { throw new IllegalArgumentException( "Extra header [" + StringUtils.bytesToHexString(header) + "] offset " + payloadOffset + " length " + payloadLength); } return buildFrameWithPayload(payload, payloadOffset, payloadLength); } private ByteBuffer buildFrameWithPayload(byte[] payload, int offset, int length) { byte[] bytes = new byte[PAYLOAD_LENGTH_BYTES + length]; EncodingUtils.encodeBigEndian(length, bytes, 0); System.arraycopy(payload, offset, bytes, PAYLOAD_LENGTH_BYTES, length); return ByteBuffer.wrap(bytes); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/TBaseSaslProcessorFactory.java0000644000000000000000000000226714303740367033462 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import org.apache.thrift.TProcessor; public class TBaseSaslProcessorFactory implements TSaslProcessorFactory { private final TProcessor processor; public TBaseSaslProcessorFactory(TProcessor processor) { this.processor = processor; } @Override public TProcessor getProcessor(NonblockingSaslHandler saslHandler) { return processor; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/TSaslServerDefinition.java0000644000000000000000000000277314303740367032641 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import java.util.Map; import javax.security.auth.callback.CallbackHandler; /** Contains all the parameters used to define a SASL server implementation. */ public class TSaslServerDefinition { public final String mechanism; public final String protocol; public final String serverName; public final Map props; public final CallbackHandler cbh; public TSaslServerDefinition( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { this.mechanism = mechanism; this.protocol = protocol; this.serverName = serverName; this.props = props; this.cbh = cbh; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/TSaslProcessorFactory.java0000644000000000000000000000225714303740367032666 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; /** * Get processor for a given state machine, so that users can customize the behavior of a TProcessor * by interacting with the state machine. */ public interface TSaslProcessorFactory { TProcessor getProcessor(NonblockingSaslHandler saslHandler) throws TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/FixedSizeHeaderReader.java0000644000000000000000000000417414303740367032536 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import java.nio.ByteBuffer; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.utils.StringUtils; /** Headers' size should be predefined. */ public abstract class FixedSizeHeaderReader implements FrameHeaderReader { protected final ByteBuffer byteBuffer = ByteBuffer.allocate(headerSize()); @Override public boolean isComplete() { return !byteBuffer.hasRemaining(); } @Override public void clear() { byteBuffer.clear(); } @Override public byte[] toBytes() { if (!isComplete()) { throw new IllegalStateException( "Header is not yet complete " + StringUtils.bytesToHexString(byteBuffer.array(), 0, byteBuffer.position())); } return byteBuffer.array(); } @Override public boolean read(TTransport transport) throws TTransportException { FrameReader.readAvailable(transport, byteBuffer); if (byteBuffer.hasRemaining()) { return false; } onComplete(); return true; } /** * @return Size of the header. */ protected abstract int headerSize(); /** * Actions (e.g. validation) to carry out when the header is complete. * * @throws TTransportException */ protected abstract void onComplete() throws TTransportException; } SaslNegotiationFrameReader.java0000644000000000000000000000206314303740367033525 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; /** Read frames for sasl negotiatiions. */ public class SaslNegotiationFrameReader extends FrameReader { public SaslNegotiationFrameReader() { super(new SaslNegotiationHeaderReader()); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/FrameHeaderReader.java0000644000000000000000000000404514303740367031673 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; /** * Read headers for a frame. For each frame, the header contains payload size and other metadata. */ public interface FrameHeaderReader { /** * As the thrift sasl specification states, all sasl messages (both for negotiatiing and for * sending data) should have a header to indicate the size of the payload. * * @return size of the payload. */ int payloadSize(); /** * @return The received bytes for the header. * @throws IllegalStateException if isComplete returns false. */ byte[] toBytes(); /** * @return true if this header has all its fields set. */ boolean isComplete(); /** Clear the header and make it available to read a new header. */ void clear(); /** * (Nonblocking) Read fields from underlying transport layer. * * @param transport underlying transport. * @return true if header is complete after read. * @throws TSaslNegotiationException if fail to read a valid header of a sasl negotiation message. * @throws TTransportException if io error. */ boolean read(TTransport transport) throws TSaslNegotiationException, TTransportException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/TSaslServerFactory.java0000644000000000000000000000506214303740367032152 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.MECHANISME_MISMATCH; import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.PROTOCOL_ERROR; import java.util.HashMap; import java.util.Map; import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; /** * Factory to create sasl server. Users can extend this class to customize the SaslServer creation. */ public class TSaslServerFactory { private final Map saslMechanisms; public TSaslServerFactory() { this.saslMechanisms = new HashMap<>(); } public void addSaslMechanism( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { TSaslServerDefinition definition = new TSaslServerDefinition(mechanism, protocol, serverName, props, cbh); saslMechanisms.put(definition.mechanism, definition); } public ServerSaslPeer getSaslPeer(String mechanism) throws TSaslNegotiationException { if (!saslMechanisms.containsKey(mechanism)) { throw new TSaslNegotiationException( MECHANISME_MISMATCH, "Unsupported mechanism " + mechanism); } TSaslServerDefinition saslDef = saslMechanisms.get(mechanism); try { SaslServer saslServer = Sasl.createSaslServer( saslDef.mechanism, saslDef.protocol, saslDef.serverName, saslDef.props, saslDef.cbh); return new ServerSaslPeer(saslServer); } catch (SaslException e) { throw new TSaslNegotiationException( PROTOCOL_ERROR, "Fail to create sasl server " + mechanism, e); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/DataFrameHeaderReader.java0000644000000000000000000000267214303740367032471 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; /** The header for data frame, it only contains a 4-byte payload size. */ public class DataFrameHeaderReader extends FixedSizeHeaderReader { public static final int PAYLOAD_LENGTH_BYTES = 4; private int payloadSize; @Override protected int headerSize() { return PAYLOAD_LENGTH_BYTES; } @Override protected void onComplete() throws TInvalidSaslFrameException { payloadSize = byteBuffer.getInt(0); if (payloadSize < 0) { throw new TInvalidSaslFrameException("Payload size is negative: " + payloadSize); } } @Override public int payloadSize() { return payloadSize; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java0000644000000000000000000004270414370300523032763 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.NegotiationStatus.COMPLETE; import static org.apache.thrift.transport.sasl.NegotiationStatus.OK; import java.nio.channels.SelectionKey; import java.nio.charset.StandardCharsets; import javax.security.sasl.SaslServer; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.ServerContext; import org.apache.thrift.server.TServerEventHandler; import org.apache.thrift.transport.TMemoryTransport; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** State machine managing one sasl connection in a nonblocking way. */ public class NonblockingSaslHandler { private static final Logger LOGGER = LoggerFactory.getLogger(NonblockingSaslHandler.class); private static final int INTEREST_NONE = 0; private static final int INTEREST_READ = SelectionKey.OP_READ; private static final int INTEREST_WRITE = SelectionKey.OP_WRITE; // Tracking the current running phase private Phase currentPhase = Phase.INITIIALIIZING; // Tracking the next phase on the next invocation of the state machine. // It should be the same as current phase if current phase is not yet finished. // Otherwise, if it is different from current phase, the statemachine is in a transition state: // current phase is done, and next phase is not yet started. private Phase nextPhase = currentPhase; // Underlying nonblocking transport private SelectionKey selectionKey; private TNonblockingTransport underlyingTransport; // APIs for intercepting event / customizing behaviors: // Factories (decorating the base implementations) & EventHandler (intercepting) private TSaslServerFactory saslServerFactory; private TSaslProcessorFactory processorFactory; private TProtocolFactory inputProtocolFactory; private TProtocolFactory outputProtocolFactory; private TServerEventHandler eventHandler; private ServerContext serverContext; // It turns out the event handler implementation in hive sometimes creates a null ServerContext. // In order to know whether TServerEventHandler#createContext is called we use such a flag. private boolean serverContextCreated = false; // Wrapper around sasl server private ServerSaslPeer saslPeer; // Sasl negotiation io private SaslNegotiationFrameReader saslResponse; private SaslNegotiationFrameWriter saslChallenge; // IO for request from and response to the socket private DataFrameReader requestReader; private DataFrameWriter responseWriter; // If sasl is negotiated for integrity/confidentiality protection private boolean dataProtected; public NonblockingSaslHandler( SelectionKey selectionKey, TNonblockingTransport underlyingTransport, TSaslServerFactory saslServerFactory, TSaslProcessorFactory processorFactory, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, TServerEventHandler eventHandler) { this.selectionKey = selectionKey; this.underlyingTransport = underlyingTransport; this.saslServerFactory = saslServerFactory; this.processorFactory = processorFactory; this.inputProtocolFactory = inputProtocolFactory; this.outputProtocolFactory = outputProtocolFactory; this.eventHandler = eventHandler; saslResponse = new SaslNegotiationFrameReader(); saslChallenge = new SaslNegotiationFrameWriter(); requestReader = new DataFrameReader(); responseWriter = new DataFrameWriter(); } /** * Get current phase of the state machine. * * @return current phase. */ public Phase getCurrentPhase() { return currentPhase; } /** * Get next phase of the state machine. It is different from current phase iff current phase is * done (and next phase not yet started). * * @return next phase. */ public Phase getNextPhase() { return nextPhase; } /** * @return underlying nonblocking socket */ public TNonblockingTransport getUnderlyingTransport() { return underlyingTransport; } /** * @return SaslServer instance */ public SaslServer getSaslServer() { return saslPeer.getSaslServer(); } /** * @return true if current phase is done. */ public boolean isCurrentPhaseDone() { return currentPhase != nextPhase; } /** * Run state machine. * * @throws IllegalStateException if current state is already done. */ public void runCurrentPhase() { currentPhase.runStateMachine(this); } /** * When current phase is intrested in read selection, calling this will run the current phase and * its following phases if the following ones are interested to read, until there is nothing * available in the underlying transport. * * @throws IllegalStateException if is called in an irrelevant phase. */ public void handleRead() { handleOps(INTEREST_READ); } /** * Similiar to handleRead. But it is for write ops. * * @throws IllegalStateException if it is called in an irrelevant phase. */ public void handleWrite() { handleOps(INTEREST_WRITE); } private void handleOps(int interestOps) { if (currentPhase.selectionInterest != interestOps) { throw new IllegalStateException( "Current phase " + currentPhase + " but got interest " + interestOps); } runCurrentPhase(); if (isCurrentPhaseDone() && nextPhase.selectionInterest == interestOps) { stepToNextPhase(); handleOps(interestOps); } } /** * When current phase is finished, it's expected to call this method first before running the * state machine again. By calling this, "next phase" is marked as started (and not done), thus is * ready to run. * * @throws IllegalArgumentException if current phase is not yet done. */ public void stepToNextPhase() { if (!isCurrentPhaseDone()) { throw new IllegalArgumentException("Not yet done with current phase: " + currentPhase); } LOGGER.debug("Switch phase {} to {}", currentPhase, nextPhase); switch (nextPhase) { case INITIIALIIZING: throw new IllegalStateException("INITIALIZING cannot be the next phase of " + currentPhase); default: } // If next phase's interest is not the same as current, nor the same as the selection key, // we need to change interest on the selector. if (!(nextPhase.selectionInterest == currentPhase.selectionInterest || nextPhase.selectionInterest == selectionKey.interestOps())) { changeSelectionInterest(nextPhase.selectionInterest); } currentPhase = nextPhase; } private void changeSelectionInterest(int selectionInterest) { selectionKey.interestOps(selectionInterest); } // sasl negotiation failure handling private void failSaslNegotiation(TSaslNegotiationException e) { LOGGER.error("Sasl negotiation failed", e); String errorMsg = e.getDetails(); saslChallenge.withHeaderAndPayload( new byte[] {e.getErrorType().code.getValue()}, errorMsg.getBytes(StandardCharsets.UTF_8)); nextPhase = Phase.WRITING_FAILURE_MESSAGE; } private void fail(Exception e) { LOGGER.error("Failed io in " + currentPhase, e); nextPhase = Phase.CLOSING; } private void failIO(TTransportException e) { StringBuilder errorMsg = new StringBuilder("IO failure ").append(e.getType()).append(" in ").append(currentPhase); if (e.getMessage() != null) { errorMsg.append(": ").append(e.getMessage()); } LOGGER.error(errorMsg.toString(), e); nextPhase = Phase.CLOSING; } // Read handlings private void handleInitializing() { try { saslResponse.read(underlyingTransport); if (saslResponse.isComplete()) { SaslNegotiationHeaderReader startHeader = saslResponse.getHeader(); if (startHeader.getStatus() != NegotiationStatus.START) { throw new TInvalidSaslFrameException( "Expecting START status but got " + startHeader.getStatus()); } String mechanism = new String(saslResponse.getPayload(), StandardCharsets.UTF_8); saslPeer = saslServerFactory.getSaslPeer(mechanism); saslResponse.clear(); nextPhase = Phase.READING_SASL_RESPONSE; } } catch (TSaslNegotiationException e) { failSaslNegotiation(e); } catch (TTransportException e) { failIO(e); } } private void handleReadingSaslResponse() { try { saslResponse.read(underlyingTransport); if (saslResponse.isComplete()) { nextPhase = Phase.EVALUATING_SASL_RESPONSE; } } catch (TSaslNegotiationException e) { failSaslNegotiation(e); } catch (TTransportException e) { failIO(e); } } private void handleReadingRequest() { try { requestReader.read(underlyingTransport); if (requestReader.isComplete()) { nextPhase = Phase.PROCESSING; } } catch (TTransportException e) { failIO(e); } } // Computation executions private void executeEvaluatingSaslResponse() { if (!(saslResponse.getHeader().getStatus() == OK || saslResponse.getHeader().getStatus() == COMPLETE)) { String error = "Expect status OK or COMPLETE, but got " + saslResponse.getHeader().getStatus(); failSaslNegotiation(new TSaslNegotiationException(ErrorType.PROTOCOL_ERROR, error)); return; } try { byte[] response = saslResponse.getPayload(); saslResponse.clear(); byte[] newChallenge = saslPeer.evaluate(response); if (saslPeer.isAuthenticated()) { dataProtected = saslPeer.isDataProtected(); saslChallenge.withHeaderAndPayload(new byte[] {COMPLETE.getValue()}, newChallenge); nextPhase = Phase.WRITING_SUCCESS_MESSAGE; } else { saslChallenge.withHeaderAndPayload(new byte[] {OK.getValue()}, newChallenge); nextPhase = Phase.WRITING_SASL_CHALLENGE; } } catch (TSaslNegotiationException e) { failSaslNegotiation(e); } } private void executeProcessing() { try { byte[] inputPayload = requestReader.getPayload(); requestReader.clear(); byte[] rawInput = dataProtected ? saslPeer.unwrap(inputPayload) : inputPayload; TMemoryTransport memoryTransport = new TMemoryTransport(rawInput); TProtocol requestProtocol = inputProtocolFactory.getProtocol(memoryTransport); TProtocol responseProtocol = outputProtocolFactory.getProtocol(memoryTransport); if (eventHandler != null) { if (!serverContextCreated) { serverContext = eventHandler.createContext(requestProtocol, responseProtocol); serverContextCreated = true; } eventHandler.processContext(serverContext, memoryTransport, memoryTransport); } TProcessor processor = processorFactory.getProcessor(this); processor.process(requestProtocol, responseProtocol); TByteArrayOutputStream rawOutput = memoryTransport.getOutput(); if (rawOutput.len() == 0) { // This is a oneway request, no response to send back. Waiting for next incoming request. nextPhase = Phase.READING_REQUEST; return; } if (dataProtected) { byte[] outputPayload = saslPeer.wrap(rawOutput.get(), 0, rawOutput.len()); responseWriter.withOnlyPayload(outputPayload); } else { responseWriter.withOnlyPayload(rawOutput.get(), 0, rawOutput.len()); } nextPhase = Phase.WRITING_RESPONSE; } catch (TTransportException e) { failIO(e); } catch (Exception e) { fail(e); } } // Write handlings private void handleWritingSaslChallenge() { try { saslChallenge.write(underlyingTransport); if (saslChallenge.isComplete()) { saslChallenge.clear(); nextPhase = Phase.READING_SASL_RESPONSE; } } catch (TTransportException e) { fail(e); } } private void handleWritingSuccessMessage() { try { saslChallenge.write(underlyingTransport); if (saslChallenge.isComplete()) { LOGGER.debug("Authentication is done."); saslChallenge = null; saslResponse = null; nextPhase = Phase.READING_REQUEST; } } catch (TTransportException e) { fail(e); } } private void handleWritingFailureMessage() { try { saslChallenge.write(underlyingTransport); if (saslChallenge.isComplete()) { nextPhase = Phase.CLOSING; } } catch (TTransportException e) { fail(e); } } private void handleWritingResponse() { try { responseWriter.write(underlyingTransport); if (responseWriter.isComplete()) { responseWriter.clear(); nextPhase = Phase.READING_REQUEST; } } catch (TTransportException e) { fail(e); } } /** * Release all the resources managed by this state machine (connection, selection and sasl * server). To avoid being blocked, this should be invoked in the network thread that manages the * selector. */ public void close() { underlyingTransport.close(); selectionKey.cancel(); if (saslPeer != null) { saslPeer.dispose(); } if (serverContextCreated) { eventHandler.deleteContext( serverContext, inputProtocolFactory.getProtocol(underlyingTransport), outputProtocolFactory.getProtocol(underlyingTransport)); } nextPhase = Phase.CLOSED; currentPhase = Phase.CLOSED; LOGGER.trace("Connection closed: {}", underlyingTransport); } public enum Phase { INITIIALIIZING(INTEREST_READ) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleInitializing(); } }, READING_SASL_RESPONSE(INTEREST_READ) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleReadingSaslResponse(); } }, EVALUATING_SASL_RESPONSE(INTEREST_NONE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.executeEvaluatingSaslResponse(); } }, WRITING_SASL_CHALLENGE(INTEREST_WRITE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleWritingSaslChallenge(); } }, WRITING_SUCCESS_MESSAGE(INTEREST_WRITE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleWritingSuccessMessage(); } }, WRITING_FAILURE_MESSAGE(INTEREST_WRITE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleWritingFailureMessage(); } }, READING_REQUEST(INTEREST_READ) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleReadingRequest(); } }, PROCESSING(INTEREST_NONE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.executeProcessing(); } }, WRITING_RESPONSE(INTEREST_WRITE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.handleWritingResponse(); } }, CLOSING(INTEREST_NONE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { statemachine.close(); } }, CLOSED(INTEREST_NONE) { @Override void unsafeRun(NonblockingSaslHandler statemachine) { // Do nothing. } }; // The interest on the selection key during the phase private final int selectionInterest; Phase(int selectionInterest) { this.selectionInterest = selectionInterest; } /** * Provide the execution to run for the state machine in current phase. The execution should * return the next phase after running on the state machine. * * @param statemachine The state machine to run. * @throws IllegalArgumentException if the state machine's current phase is different. * @throws IllegalStateException if the state machine' current phase is already done. */ void runStateMachine(NonblockingSaslHandler statemachine) { if (statemachine.currentPhase != this) { throw new IllegalArgumentException( "State machine is " + statemachine.currentPhase + " but is expected to be " + this); } if (statemachine.isCurrentPhaseDone()) { throw new IllegalStateException("State machine should step into " + statemachine.nextPhase); } unsafeRun(statemachine); } // Run the state machine without checkiing its own phase // It should not be called direcly by users. abstract void unsafeRun(NonblockingSaslHandler statemachine); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/TSaslNegotiationException.java0000644000000000000000000000456214303740367033517 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import org.apache.thrift.transport.TTransportException; /** Exception for sasl negotiation errors. */ public class TSaslNegotiationException extends TTransportException { private final ErrorType error; public TSaslNegotiationException(ErrorType error, String summary) { super(summary); this.error = error; } public TSaslNegotiationException(ErrorType error, String summary, Throwable cause) { super(summary, cause); this.error = error; } public ErrorType getErrorType() { return error; } /** * @return Errory type plus the message. */ public String getSummary() { return error.name() + ": " + getMessage(); } /** * @return Summary and eventually the cause's message. */ public String getDetails() { return getCause() == null ? getSummary() : getSummary() + "\nReason: " + getCause().getMessage(); } public enum ErrorType { // Unexpected system internal error during negotiation (e.g. sasl initialization failure) INTERNAL_ERROR(NegotiationStatus.ERROR), // Cannot read correct sasl frames from the connection => Send "ERROR" status byte to peer PROTOCOL_ERROR(NegotiationStatus.ERROR), // Peer is using unsupported sasl mechanisms => Send "BAD" status byte to peer MECHANISME_MISMATCH(NegotiationStatus.BAD), // Sasl authentication failure => Send "BAD" status byte to peer AUTHENTICATION_FAILURE(NegotiationStatus.BAD), ; public final NegotiationStatus code; ErrorType(NegotiationStatus code) { this.code = code; } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/NegotiationStatus.java0000644000000000000000000000341314303740367032067 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.PROTOCOL_ERROR; import java.util.HashMap; import java.util.Map; /** Status bytes used during the initial Thrift SASL handshake. */ public enum NegotiationStatus { START((byte) 0x01), OK((byte) 0x02), BAD((byte) 0x03), ERROR((byte) 0x04), COMPLETE((byte) 0x05); private static final Map reverseMap = new HashMap<>(); static { for (NegotiationStatus s : NegotiationStatus.values()) { reverseMap.put(s.getValue(), s); } } private final byte value; NegotiationStatus(byte val) { this.value = val; } public byte getValue() { return value; } public static NegotiationStatus byValue(byte val) throws TSaslNegotiationException { if (!reverseMap.containsKey(val)) { throw new TSaslNegotiationException(PROTOCOL_ERROR, "Invalid status " + val); } return reverseMap.get(val); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/FrameWriter.java0000644000000000000000000001044514303740367030635 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import java.nio.ByteBuffer; import org.apache.thrift.transport.TNonblockingTransport; import org.apache.thrift.transport.TTransportException; /** Write frame (header and payload) to transport in a nonblocking way. */ public abstract class FrameWriter { protected ByteBuffer frameBytes; /** * Provide (maybe empty) header and payload to the frame. This can be called only when isComplete * returns true (last frame has been written out). * * @param header Some extra header bytes (without the 4 bytes for payload length), which will be * the start of the frame. It can be empty, depending on the message format * @param payload Payload as a byte array * @throws IllegalStateException if it is called when isComplete returns false * @throws IllegalArgumentException if header or payload is invalid */ public void withHeaderAndPayload(byte[] header, byte[] payload) { if (payload == null) { payload = new byte[0]; } if (header == null) { withOnlyPayload(payload); } else { withHeaderAndPayload(header, 0, header.length, payload, 0, payload.length); } } /** * Provide extra header and payload to the frame. * * @param header byte array containing the extra header * @param headerOffset starting offset of the header portition * @param headerLength length of the extra header * @param payload byte array containing the payload * @param payloadOffset starting offset of the payload portion * @param payloadLength length of the payload * @throws IllegalStateException if preivous frame is not yet complete (isComplete returns fals) * @throws IllegalArgumentException if header or payload is invalid */ public void withHeaderAndPayload( byte[] header, int headerOffset, int headerLength, byte[] payload, int payloadOffset, int payloadLength) { if (!isComplete()) { throw new IllegalStateException( "Previsous write is not yet complete, with " + frameBytes.remaining() + " bytes left."); } frameBytes = buildFrame(header, headerOffset, headerLength, payload, payloadOffset, payloadLength); } /** * Provide only payload to the frame. Throws UnsupportedOperationException if the frame expects a * header. * * @param payload payload as a byte array */ public void withOnlyPayload(byte[] payload) { withOnlyPayload(payload, 0, payload.length); } /** * Provide only payload to the frame. Throws UnsupportedOperationException if the frame expects a * header. * * @param payload The underlying byte array as a recipient of the payload * @param offset The offset in the byte array starting from where the payload is located * @param length The length of the payload */ public abstract void withOnlyPayload(byte[] payload, int offset, int length); protected abstract ByteBuffer buildFrame( byte[] header, int headerOffset, int headerLength, byte[] payload, int payloadOffset, int payloadLength); /** * Nonblocking write to the underlying transport. * * @throws TTransportException */ public void write(TNonblockingTransport transport) throws TTransportException { transport.write(frameBytes); } /** * @return true when no more data needs to be written out */ public boolean isComplete() { return frameBytes == null || !frameBytes.hasRemaining(); } /** Release the byte buffer. */ public void clear() { frameBytes = null; } } SaslNegotiationFrameWriter.java0000644000000000000000000000460214303740367033600 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.SaslNegotiationHeaderReader.PAYLOAD_LENGTH_BYTES; import static org.apache.thrift.transport.sasl.SaslNegotiationHeaderReader.STATUS_BYTES; import java.nio.ByteBuffer; import org.apache.thrift.EncodingUtils; import org.apache.thrift.utils.StringUtils; /** * Writer for sasl negotiation frames. It expect a status byte as header with a payload to be * written out (any header whose size is not equal to 1 would be considered as error). */ public class SaslNegotiationFrameWriter extends FrameWriter { public static final int HEADER_BYTES = STATUS_BYTES + PAYLOAD_LENGTH_BYTES; @Override public void withOnlyPayload(byte[] payload, int offset, int length) { throw new UnsupportedOperationException("Status byte is expected for sasl frame header."); } @Override protected ByteBuffer buildFrame( byte[] header, int headerOffset, int headerLength, byte[] payload, int payloadOffset, int payloadLength) { if (header == null || headerLength != STATUS_BYTES) { throw new IllegalArgumentException( "Header " + StringUtils.bytesToHexString(header) + " does not have expected length " + STATUS_BYTES); } byte[] bytes = new byte[HEADER_BYTES + payloadLength]; System.arraycopy(header, headerOffset, bytes, 0, STATUS_BYTES); EncodingUtils.encodeBigEndian(payloadLength, bytes, STATUS_BYTES); System.arraycopy(payload, payloadOffset, bytes, HEADER_BYTES, payloadLength); return ByteBuffer.wrap(bytes); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/DataFrameReader.java0000644000000000000000000000202614303740367031351 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; /** Frames for thrift (serialized) messages. */ public class DataFrameReader extends FrameReader { public DataFrameReader() { super(new DataFrameHeaderReader()); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/sasl/SaslPeer.java0000644000000000000000000000614614303740367030127 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import org.apache.thrift.transport.TTransportException; /** A peer in a sasl negotiation. */ public interface SaslPeer { /** * Evaluate and validate the negotiation message (response/challenge) received from peer. * * @param negotiationMessage response/challenge received from peer. * @return new response/challenge to send to peer, can be null if authentication becomes success. * @throws TSaslNegotiationException if sasl authentication fails. */ byte[] evaluate(byte[] negotiationMessage) throws TSaslNegotiationException; /** * @return true if authentication is done. */ boolean isAuthenticated(); /** * This method can only be called when the negotiation is complete (isAuthenticated returns true). * Otherwise it will throw IllegalStateExceptiion. * * @return if the qop requires some integrity/confidential protection. * @throws IllegalStateException if negotiation is not yet complete. */ boolean isDataProtected(); /** * Wrap raw bytes to protect it. * * @param data raw bytes. * @param offset the start position of the content to wrap. * @param length the length of the content to wrap. * @return bytes with protection to send to peer. * @throws TTransportException if failure. */ byte[] wrap(byte[] data, int offset, int length) throws TTransportException; /** * Wrap the whole byte array. * * @param data raw bytes. * @return wrapped bytes. * @throws TTransportException if failure. */ default byte[] wrap(byte[] data) throws TTransportException { return wrap(data, 0, data.length); } /** * Unwrap protected data to raw bytes. * * @param data protected data received from peer. * @param offset the start position of the content to unwrap. * @param length the length of the content to unwrap. * @return raw bytes. * @throws TTransportException if failed. */ byte[] unwrap(byte[] data, int offset, int length) throws TTransportException; /** * Unwrap the whole byte array. * * @param data wrapped bytes. * @return raw bytes. * @throws TTransportException if failure. */ default byte[] unwrap(byte[] data) throws TTransportException { return unwrap(data, 0, data.length); } /** Close this peer and release resources. */ void dispose(); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TTransportException.java0000644000000000000000000000377414303740367031452 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TException; /** Transport exceptions. */ public class TTransportException extends TException { private static final long serialVersionUID = 1L; public static final int UNKNOWN = 0; public static final int NOT_OPEN = 1; public static final int ALREADY_OPEN = 2; public static final int TIMED_OUT = 3; public static final int END_OF_FILE = 4; public static final int CORRUPTED_DATA = 5; protected int type_ = UNKNOWN; public TTransportException() { super(); } public TTransportException(int type) { super(); type_ = type; } public TTransportException(int type, String message) { super(message); type_ = type; } public TTransportException(String message) { super(message); } public TTransportException(int type, Throwable cause) { super(cause); type_ = type; } public TTransportException(Throwable cause) { super(cause); } public TTransportException(String message, Throwable cause) { super(message, cause); } public TTransportException(int type, String message, Throwable cause) { super(message, cause); type_ = type; } public int getType() { return type_; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TServerTransport.java0000644000000000000000000000537714303740367030763 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.Closeable; import java.net.InetSocketAddress; import org.apache.thrift.TConfiguration; /** Server transport. Object which provides client transports. */ public abstract class TServerTransport implements Closeable { public abstract static class AbstractServerTransportArgs< T extends AbstractServerTransportArgs> { int backlog = 0; // A value of 0 means the default value will be used (currently set at 50) int clientTimeout = 0; InetSocketAddress bindAddr; int maxFrameSize = TConfiguration.DEFAULT_MAX_FRAME_SIZE; public T backlog(int backlog) { this.backlog = backlog; return (T) this; } public T clientTimeout(int clientTimeout) { this.clientTimeout = clientTimeout; return (T) this; } public T port(int port) { this.bindAddr = new InetSocketAddress(port); return (T) this; } public T bindAddr(InetSocketAddress bindAddr) { this.bindAddr = bindAddr; return (T) this; } public T maxFrameSize(int maxFrameSize) { this.maxFrameSize = maxFrameSize; return (T) this; } } public abstract void listen() throws TTransportException; /** * Accept incoming connection on the server socket. When there is no incoming connection * available: either it should block infinitely in a blocking implementation, either it should * return null in a nonblocking implementation. * * @return new connection * @throws TTransportException if IO error. */ public abstract TTransport accept() throws TTransportException; public abstract void close(); /** * Optional method implementation. This signals to the server transport that it should break out * of any accept() or listen() that it is currently blocked on. This method, if implemented, MUST * be thread safe, as it may be called from a different thread context than the other * TServerTransport methods. */ public void interrupt() {} } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TFileProcessor.java0000644000000000000000000000775314303740367030357 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; /** * FileProcessor: helps in processing files generated by TFileTransport. Port of original cpp * implementation */ public class TFileProcessor { private TProcessor processor_; private TProtocolFactory inputProtocolFactory_; private TProtocolFactory outputProtocolFactory_; private TFileTransport inputTransport_; private TTransport outputTransport_; public TFileProcessor( TProcessor processor, TProtocolFactory protocolFactory, TFileTransport inputTransport, TTransport outputTransport) { processor_ = processor; inputProtocolFactory_ = outputProtocolFactory_ = protocolFactory; inputTransport_ = inputTransport; outputTransport_ = outputTransport; } public TFileProcessor( TProcessor processor, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, TFileTransport inputTransport, TTransport outputTransport) { processor_ = processor; inputProtocolFactory_ = inputProtocolFactory; outputProtocolFactory_ = outputProtocolFactory; inputTransport_ = inputTransport; outputTransport_ = outputTransport; } private void processUntil(int lastChunk) throws TException { TProtocol ip = inputProtocolFactory_.getProtocol(inputTransport_); TProtocol op = outputProtocolFactory_.getProtocol(outputTransport_); int curChunk = inputTransport_.getCurChunk(); try { while (lastChunk >= curChunk) { processor_.process(ip, op); int newChunk = inputTransport_.getCurChunk(); curChunk = newChunk; } } catch (TTransportException e) { // if we are processing the last chunk - we could have just hit EOF // on EOF - trap the error and stop processing. if (e.getType() != TTransportException.END_OF_FILE) throw e; else { return; } } } /** * Process from start to last chunk both inclusive where chunks begin from 0 * * @param startChunkNum first chunk to be processed * @param endChunkNum last chunk to be processed * @throws TException if endChunkNum is less than startChunkNum. */ public void processChunk(int startChunkNum, int endChunkNum) throws TException { int numChunks = inputTransport_.getNumChunks(); if (endChunkNum < 0) endChunkNum += numChunks; if (startChunkNum < 0) startChunkNum += numChunks; if (endChunkNum < startChunkNum) throw new TException("endChunkNum " + endChunkNum + " is less than " + startChunkNum); inputTransport_.seekToChunk(startChunkNum); processUntil(endChunkNum); } /** * Process a single chunk * * @param chunkNum chunk to be processed * @throws TException on error while processing the given chunk. */ public void processChunk(int chunkNum) throws TException { processChunk(chunkNum, chunkNum); } /** * Process a current chunk * * @throws TException on error while processing the given chunk. */ public void processChunk() throws TException { processChunk(inputTransport_.getCurChunk()); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/THttpClient.java0000644000000000000000000002445514452237057027656 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.hc.client5.http.classic.HttpClient; import org.apache.hc.client5.http.classic.methods.HttpPost; import org.apache.hc.client5.http.config.ConnectionConfig; import org.apache.hc.client5.http.config.RequestConfig; import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.http.io.entity.ByteArrayEntity; import org.apache.hc.core5.util.Timeout; import org.apache.thrift.TConfiguration; import org.apache.thrift.THttpClientResponseHandler; /** * HTTP implementation of the TTransport interface. Used for working with a Thrift web services * implementation (using for example TServlet). * *

This class offers two implementations of the HTTP transport. One uses HttpURLConnection * instances, the other HttpClient from Apache Http Components. The chosen implementation depends on * the constructor used to create the THttpClient instance. Using the THttpClient(String url) * constructor or passing null as the HttpClient to THttpClient(String url, HttpClient client) will * create an instance which will use HttpURLConnection. * *

When using HttpClient, the following configuration leads to 5-15% better performance than the * HttpURLConnection implementation: * *

http.protocol.version=HttpVersion.HTTP_1_1 http.protocol.content-charset=UTF-8 * http.protocol.expect-continue=false http.connection.stalecheck=false * *

Also note that under high load, the HttpURLConnection implementation may exhaust the open file * descriptor limit. * * @see THRIFT-970 */ public class THttpClient extends TEndpointTransport { private final URL url_; private final ByteArrayOutputStream requestBuffer_ = new ByteArrayOutputStream(); private InputStream inputStream_ = null; private int connectTimeout_ = 0; private int readTimeout_ = 0; private Map customHeaders_ = null; private final HttpHost host; private final HttpClient client; private static final Map DEFAULT_HEADERS = Collections.unmodifiableMap(getDefaultHeaders()); public static class Factory extends TTransportFactory { private final String url; private final HttpClient client; public Factory(String url) { this.url = url; this.client = null; } public Factory(String url, HttpClient client) { this.url = url; this.client = client; } @Override public TTransport getTransport(TTransport trans) { try { if (null != client) { return new THttpClient(trans.getConfiguration(), url, client); } else { return new THttpClient(trans.getConfiguration(), url); } } catch (TTransportException tte) { return null; } } } public THttpClient(TConfiguration config, String url) throws TTransportException { super(config); try { url_ = new URL(url); this.client = null; this.host = null; } catch (IOException iox) { throw new TTransportException(iox); } } public THttpClient(String url) throws TTransportException { super(new TConfiguration()); try { url_ = new URL(url); this.client = null; this.host = null; } catch (IOException iox) { throw new TTransportException(iox); } } public THttpClient(TConfiguration config, String url, HttpClient client) throws TTransportException { super(config); try { url_ = new URL(url); this.client = client; this.host = new HttpHost( url_.getProtocol(), url_.getHost(), -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort()); } catch (IOException iox) { throw new TTransportException(iox); } } public THttpClient(String url, HttpClient client) throws TTransportException { super(new TConfiguration()); try { url_ = new URL(url); this.client = client; this.host = new HttpHost( url_.getProtocol(), url_.getHost(), -1 == url_.getPort() ? url_.getDefaultPort() : url_.getPort()); } catch (IOException iox) { throw new TTransportException(iox); } } public void setConnectTimeout(int timeout) { connectTimeout_ = timeout; } /** * Use instead {@link * org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager#setConnectionConfig} or * {@link * org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager#setDefaultConnectionConfig} */ @Deprecated public void setReadTimeout(int timeout) { readTimeout_ = timeout; } public void setCustomHeaders(Map headers) { customHeaders_ = new HashMap<>(headers); } public void setCustomHeader(String key, String value) { if (customHeaders_ == null) { customHeaders_ = new HashMap<>(); } customHeaders_.put(key, value); } @Override public void open() {} @Override public void close() { if (null != inputStream_) { try { inputStream_.close(); } catch (IOException ioe) { } inputStream_ = null; } } @Override public boolean isOpen() { return true; } @Override public int read(byte[] buf, int off, int len) throws TTransportException { if (inputStream_ == null) { throw new TTransportException("Response buffer is empty, no request."); } checkReadBytesAvailable(len); try { int ret = inputStream_.read(buf, off, len); if (ret == -1) { throw new TTransportException("No more data available."); } countConsumedMessageBytes(ret); return ret; } catch (IOException iox) { throw new TTransportException(iox); } } @Override public void write(byte[] buf, int off, int len) { requestBuffer_.write(buf, off, len); } private RequestConfig getRequestConfig() { RequestConfig requestConfig = RequestConfig.DEFAULT; if (connectTimeout_ > 0) { requestConfig = RequestConfig.copy(requestConfig) .setConnectionRequestTimeout(Timeout.ofMilliseconds(connectTimeout_)) .build(); } return requestConfig; } private ConnectionConfig getConnectionConfig() { ConnectionConfig connectionConfig = ConnectionConfig.DEFAULT; if (readTimeout_ > 0) { connectionConfig = ConnectionConfig.copy(connectionConfig) .setSocketTimeout(Timeout.ofMilliseconds(readTimeout_)) .build(); } return connectionConfig; } private static Map getDefaultHeaders() { Map headers = new HashMap<>(); headers.put("Content-Type", "application/x-thrift"); headers.put("Accept", "application/x-thrift"); headers.put("User-Agent", "Java/THttpClient/HC"); return headers; } private void flushUsingHttpClient() throws TTransportException { if (null == this.client) { throw new TTransportException("Null HttpClient, aborting."); } // Extract request and reset buffer byte[] data = requestBuffer_.toByteArray(); requestBuffer_.reset(); HttpPost post = new HttpPost(this.url_.getFile()); try { // Set request to path + query string post.setConfig(getRequestConfig()); DEFAULT_HEADERS.forEach(post::addHeader); if (null != customHeaders_) { customHeaders_.forEach(post::addHeader); } post.setEntity(new ByteArrayEntity(data, null)); inputStream_ = client.execute(this.host, post, new THttpClientResponseHandler()); } catch (IOException ioe) { // Abort method so the connection gets released back to the connection manager post.abort(); throw new TTransportException(ioe); } finally { resetConsumedMessageSize(-1); } } public void flush() throws TTransportException { if (null != this.client) { flushUsingHttpClient(); return; } // Extract request and reset buffer byte[] data = requestBuffer_.toByteArray(); requestBuffer_.reset(); try { // Create connection object HttpURLConnection connection = (HttpURLConnection) url_.openConnection(); // Timeouts, only if explicitly set if (connectTimeout_ > 0) { connection.setConnectTimeout(connectTimeout_); } if (readTimeout_ > 0) { connection.setReadTimeout(readTimeout_); } // Make the request connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/x-thrift"); connection.setRequestProperty("Accept", "application/x-thrift"); connection.setRequestProperty("User-Agent", "Java/THttpClient"); if (customHeaders_ != null) { for (Map.Entry header : customHeaders_.entrySet()) { connection.setRequestProperty(header.getKey(), header.getValue()); } } connection.setDoOutput(true); connection.connect(); connection.getOutputStream().write(data); int responseCode = connection.getResponseCode(); if (responseCode != HttpURLConnection.HTTP_OK) { throw new TTransportException("HTTP Response code: " + responseCode); } // Read the responses inputStream_ = connection.getInputStream(); } catch (IOException iox) { throw new TTransportException(iox); } finally { resetConsumedMessageSize(-1); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSaslClientTransport.java0000644000000000000000000000745614303740367031556 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.nio.charset.StandardCharsets; import java.util.Map; import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; import org.apache.thrift.transport.sasl.NegotiationStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Wraps another Thrift TTransport, but performs SASL client negotiation on the call to * open(). This class will wrap ensuing communication over it, if a SASL QOP is * negotiated with the other party. */ public class TSaslClientTransport extends TSaslTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TSaslClientTransport.class); /** The name of the mechanism this client supports. */ private final String mechanism; /** * Uses the given SaslClient. * * @param saslClient The SaslClient to use for the subsequent SASL negotiation. * @param transport Transport underlying this one. */ public TSaslClientTransport(SaslClient saslClient, TTransport transport) throws TTransportException { super(saslClient, transport); mechanism = saslClient.getMechanismName(); } /** * Creates a SaslClient using the given SASL-specific parameters. See the Java * documentation for Sasl.createSaslClient for the details of the parameters. * * @param transport The underlying Thrift transport. * @throws SaslException */ public TSaslClientTransport( String mechanism, String authorizationId, String protocol, String serverName, Map props, CallbackHandler cbh, TTransport transport) throws SaslException, TTransportException { super( Sasl.createSaslClient( new String[] {mechanism}, authorizationId, protocol, serverName, props, cbh), transport); this.mechanism = mechanism; } @Override protected SaslRole getRole() { return SaslRole.CLIENT; } /** * Performs the client side of the initial portion of the Thrift SASL protocol. Generates and * sends the initial response to the server, including which mechanism this client wants to use. */ @Override protected void handleSaslStartMessage() throws TTransportException, SaslException { SaslClient saslClient = getSaslClient(); byte[] initialResponse = new byte[0]; if (saslClient.hasInitialResponse()) initialResponse = saslClient.evaluateChallenge(initialResponse); LOGGER.debug( "Sending mechanism name {} and initial response of length {}", mechanism, initialResponse.length); byte[] mechanismBytes = mechanism.getBytes(StandardCharsets.UTF_8); sendSaslMessage(NegotiationStatus.START, mechanismBytes); // Send initial response sendSaslMessage( saslClient.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK, initialResponse); underlyingTransport.flush(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/layered/0000777000000000000000000000000014370300523026214 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/layered/TFastFramedTransport.java0000644000000000000000000001547714303740367033160 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.layered; import java.util.Objects; import org.apache.thrift.TConfiguration; import org.apache.thrift.transport.*; /** * This transport is wire compatible with {@link TFramedTransport}, but makes use of reusable, * expanding read and write buffers in order to avoid allocating new byte[]s all the time. Since the * buffers only expand, you should probably only use this transport if your messages are not too * variably large, unless the persistent memory cost is not an issue. * *

This implementation is NOT threadsafe. */ public class TFastFramedTransport extends TLayeredTransport { public static class Factory extends TTransportFactory { private final int initialCapacity; private final int maxLength; public Factory() { this(DEFAULT_BUF_CAPACITY, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } public Factory(int initialCapacity) { this(initialCapacity, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } public Factory(int initialCapacity, int maxLength) { this.initialCapacity = initialCapacity; this.maxLength = maxLength; } @Override public TTransport getTransport(TTransport trans) throws TTransportException { return new TFastFramedTransport(trans, initialCapacity, maxLength); } } /** How big should the default read and write buffers be? */ public static final int DEFAULT_BUF_CAPACITY = 1024; private final AutoExpandingBufferWriteTransport writeBuffer; private AutoExpandingBufferReadTransport readBuffer; private final int initialBufferCapacity; private final byte[] i32buf = new byte[4]; private final int maxLength; /** * Create a new {@link TFastFramedTransport}. Use the defaults for initial buffer size and max * frame length. * * @param underlying Transport that real reads and writes will go through to. */ public TFastFramedTransport(TTransport underlying) throws TTransportException { this(underlying, DEFAULT_BUF_CAPACITY, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } /** * Create a new {@link TFastFramedTransport}. Use the specified initial buffer capacity and the * default max frame length. * * @param underlying Transport that real reads and writes will go through to. * @param initialBufferCapacity The initial size of the read and write buffers. In practice, it's * not critical to set this unless you know in advance that your messages are going to be very * large. */ public TFastFramedTransport(TTransport underlying, int initialBufferCapacity) throws TTransportException { this(underlying, initialBufferCapacity, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } /** * @param underlying Transport that real reads and writes will go through to. * @param initialBufferCapacity The initial size of the read and write buffers. In practice, it's * not critical to set this unless you know in advance that your messages are going to be very * large. (You can pass TFramedTransportWithReusableBuffer.DEFAULT_BUF_CAPACITY if you're only * using this constructor because you want to set the maxLength.) * @param maxLength The max frame size you are willing to read. You can use this parameter to * limit how much memory can be allocated. */ public TFastFramedTransport(TTransport underlying, int initialBufferCapacity, int maxLength) throws TTransportException { super(underlying); TConfiguration config = Objects.isNull(underlying.getConfiguration()) ? new TConfiguration() : underlying.getConfiguration(); this.maxLength = maxLength; config.setMaxFrameSize(maxLength); this.initialBufferCapacity = initialBufferCapacity; readBuffer = new AutoExpandingBufferReadTransport(config, initialBufferCapacity); writeBuffer = new AutoExpandingBufferWriteTransport(config, initialBufferCapacity, 4); } @Override public void close() { getInnerTransport().close(); } @Override public boolean isOpen() { return getInnerTransport().isOpen(); } @Override public void open() throws TTransportException { getInnerTransport().open(); } @Override public int read(byte[] buf, int off, int len) throws TTransportException { int got = readBuffer.read(buf, off, len); if (got > 0) { return got; } // Read another frame of data readFrame(); return readBuffer.read(buf, off, len); } private void readFrame() throws TTransportException { getInnerTransport().readAll(i32buf, 0, 4); int size = TFramedTransport.decodeFrameSize(i32buf); if (size < 0) { close(); throw new TTransportException( TTransportException.CORRUPTED_DATA, "Read a negative frame size (" + size + ")!"); } if (size > getInnerTransport().getConfiguration().getMaxFrameSize()) { close(); throw new TTransportException( TTransportException.CORRUPTED_DATA, "Frame size (" + size + ") larger than max length (" + maxLength + ")!"); } readBuffer.fill(getInnerTransport(), size); } @Override public void write(byte[] buf, int off, int len) throws TTransportException { writeBuffer.write(buf, off, len); } @Override public void consumeBuffer(int len) { readBuffer.consumeBuffer(len); } /** Only clears the read buffer! */ public void clear() throws TTransportException { readBuffer = new AutoExpandingBufferReadTransport(getConfiguration(), initialBufferCapacity); } @Override public void flush() throws TTransportException { int payloadLength = writeBuffer.getLength() - 4; byte[] data = writeBuffer.getBuf().array(); TFramedTransport.encodeFrameSize(payloadLength, data); getInnerTransport().write(data, 0, payloadLength + 4); writeBuffer.reset(); getInnerTransport().flush(); } @Override public byte[] getBuffer() { return readBuffer.getBuffer(); } @Override public int getBufferPosition() { return readBuffer.getBufferPosition(); } @Override public int getBytesRemainingInBuffer() { return readBuffer.getBytesRemainingInBuffer(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/layered/TLayeredTransport.java0000644000000000000000000000334314370300523032504 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.layered; import java.util.Objects; import org.apache.thrift.TConfiguration; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; public abstract class TLayeredTransport extends TTransport { private final TTransport innerTransport; @Override public TConfiguration getConfiguration() { return innerTransport.getConfiguration(); } public TLayeredTransport(TTransport transport) { Objects.requireNonNull(transport, "TTransport cannot be null."); innerTransport = transport; } @Override public void updateKnownMessageSize(long size) throws TTransportException { innerTransport.updateKnownMessageSize(size); } @Override public void checkReadBytesAvailable(long numBytes) throws TTransportException { innerTransport.checkReadBytesAvailable(numBytes); } public TTransport getInnerTransport() { return innerTransport; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/layered/TFramedTransport.java0000644000000000000000000001320314370300523032311 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.layered; import java.util.Objects; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TConfiguration; import org.apache.thrift.transport.TMemoryInputTransport; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportFactory; /** * TFramedTransport is a buffered TTransport that ensures a fully read message every time by * preceding messages with a 4-byte frame size. */ public class TFramedTransport extends TLayeredTransport { /** Buffer for output */ private final TByteArrayOutputStream writeBuffer_ = new TByteArrayOutputStream(1024); /** Buffer for input */ private final TMemoryInputTransport readBuffer_; public static class Factory extends TTransportFactory { private final int maxLength_; public Factory() { maxLength_ = TConfiguration.DEFAULT_MAX_FRAME_SIZE; } public Factory(int maxLength) { maxLength_ = maxLength; } @Override public TTransport getTransport(TTransport base) throws TTransportException { return new TFramedTransport(base, maxLength_); } } /** * Something to fill in the first four bytes of the buffer to make room for the frame size. This * allows the implementation to write once instead of twice. */ private static final byte[] sizeFiller_ = new byte[] {0x00, 0x00, 0x00, 0x00}; /** Constructor wraps around another transport */ public TFramedTransport(TTransport transport, int maxLength) throws TTransportException { super(transport); TConfiguration _configuration = Objects.isNull(transport.getConfiguration()) ? new TConfiguration() : transport.getConfiguration(); _configuration.setMaxFrameSize(maxLength); writeBuffer_.write(sizeFiller_, 0, 4); readBuffer_ = new TMemoryInputTransport(_configuration, new byte[0]); } public TFramedTransport(TTransport transport) throws TTransportException { this(transport, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } public void open() throws TTransportException { getInnerTransport().open(); } public boolean isOpen() { return getInnerTransport().isOpen(); } public void close() { getInnerTransport().close(); } public int read(byte[] buf, int off, int len) throws TTransportException { int got = readBuffer_.read(buf, off, len); if (got > 0) { return got; } // Read another frame of data readFrame(); return readBuffer_.read(buf, off, len); } @Override public byte[] getBuffer() { return readBuffer_.getBuffer(); } @Override public int getBufferPosition() { return readBuffer_.getBufferPosition(); } @Override public int getBytesRemainingInBuffer() { return readBuffer_.getBytesRemainingInBuffer(); } @Override public void consumeBuffer(int len) { readBuffer_.consumeBuffer(len); } public void clear() { readBuffer_.clear(); } private final byte[] i32buf = new byte[4]; private void readFrame() throws TTransportException { getInnerTransport().readAll(i32buf, 0, 4); int size = decodeFrameSize(i32buf); if (size < 0) { close(); throw new TTransportException( TTransportException.CORRUPTED_DATA, "Read a negative frame size (" + size + ")!"); } if (size > getInnerTransport().getConfiguration().getMaxFrameSize()) { close(); throw new TTransportException( TTransportException.CORRUPTED_DATA, "Frame size (" + size + ") larger than max length (" + getInnerTransport().getConfiguration().getMaxFrameSize() + ")!"); } byte[] buff = new byte[size]; getInnerTransport().readAll(buff, 0, size); readBuffer_.reset(buff); } public void write(byte[] buf, int off, int len) throws TTransportException { writeBuffer_.write(buf, off, len); } @Override public void flush() throws TTransportException { byte[] buf = writeBuffer_.get(); int len = writeBuffer_.len() - 4; // account for the prepended frame size writeBuffer_.reset(); writeBuffer_.write(sizeFiller_, 0, 4); // make room for the next frame's size data encodeFrameSize(len, buf); // this is the frame length without the filler getInnerTransport().write(buf, 0, len + 4); // we have to write the frame size and frame data getInnerTransport().flush(); } public static void encodeFrameSize(final int frameSize, final byte[] buf) { buf[0] = (byte) (0xff & (frameSize >> 24)); buf[1] = (byte) (0xff & (frameSize >> 16)); buf[2] = (byte) (0xff & (frameSize >> 8)); buf[3] = (byte) (0xff & (frameSize)); } public static int decodeFrameSize(final byte[] buf) { return ((buf[0] & 0xff) << 24) | ((buf[1] & 0xff) << 16) | ((buf[2] & 0xff) << 8) | ((buf[3] & 0xff)); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSaslTransport.java0000644000000000000000000004347314303740367030416 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.nio.charset.StandardCharsets; import java.util.Objects; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import org.apache.thrift.EncodingUtils; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TConfiguration; import org.apache.thrift.transport.layered.TFramedTransport; import org.apache.thrift.transport.sasl.NegotiationStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A superclass for SASL client/server thrift transports. A subclass need only implement the * open method. */ abstract class TSaslTransport extends TEndpointTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TSaslTransport.class); protected static final int DEFAULT_MAX_LENGTH = 0x7FFFFFFF; protected static final int MECHANISM_NAME_BYTES = 1; protected static final int STATUS_BYTES = 1; protected static final int PAYLOAD_LENGTH_BYTES = 4; protected static enum SaslRole { SERVER, CLIENT; } /** Transport underlying this one. */ protected TTransport underlyingTransport; /** Either a SASL client or a SASL server. */ private SaslParticipant sasl; /** * Whether or not we should wrap/unwrap reads/writes. Determined by whether or not a QOP is * negotiated during the SASL handshake. */ private boolean shouldWrap = false; /** Buffer for input. */ private TMemoryInputTransport readBuffer; /** Buffer for output. */ private final TByteArrayOutputStream writeBuffer = new TByteArrayOutputStream(1024); /** * Create a TSaslTransport. It's assumed that setSaslServer will be called later to initialize the * SASL endpoint underlying this transport. * * @param underlyingTransport The thrift transport which this transport is wrapping. */ protected TSaslTransport(TTransport underlyingTransport) throws TTransportException { super( Objects.isNull(underlyingTransport.getConfiguration()) ? new TConfiguration() : underlyingTransport.getConfiguration()); this.underlyingTransport = underlyingTransport; this.readBuffer = new TMemoryInputTransport(underlyingTransport.getConfiguration()); } /** * Create a TSaslTransport which acts as a client. * * @param saslClient The SaslClient which this transport will use for SASL * negotiation. * @param underlyingTransport The thrift transport which this transport is wrapping. */ protected TSaslTransport(SaslClient saslClient, TTransport underlyingTransport) throws TTransportException { super( Objects.isNull(underlyingTransport.getConfiguration()) ? new TConfiguration() : underlyingTransport.getConfiguration()); sasl = new SaslParticipant(saslClient); this.underlyingTransport = underlyingTransport; this.readBuffer = new TMemoryInputTransport(underlyingTransport.getConfiguration()); } protected void setSaslServer(SaslServer saslServer) { sasl = new SaslParticipant(saslServer); } // Used to read the status byte and payload length. private final byte[] messageHeader = new byte[STATUS_BYTES + PAYLOAD_LENGTH_BYTES]; /** * Send a complete Thrift SASL message. * * @param status The status to send. * @param payload The data to send as the payload of this message. * @throws TTransportException */ protected void sendSaslMessage(NegotiationStatus status, byte[] payload) throws TTransportException { if (payload == null) payload = new byte[0]; messageHeader[0] = status.getValue(); EncodingUtils.encodeBigEndian(payload.length, messageHeader, STATUS_BYTES); LOGGER.debug( "{}: Writing message with status {} and payload length {}", getRole(), status, payload.length); underlyingTransport.write(messageHeader); underlyingTransport.write(payload); underlyingTransport.flush(); } /** * Read a complete Thrift SASL message. * * @return The SASL status and payload from this message. * @throws TTransportException Thrown if there is a failure reading from the underlying transport, * or if a status code of BAD or ERROR is encountered. */ protected SaslResponse receiveSaslMessage() throws TTransportException { underlyingTransport.readAll(messageHeader, 0, messageHeader.length); byte statusByte = messageHeader[0]; NegotiationStatus status = NegotiationStatus.byValue(statusByte); if (status == null) { throw sendAndThrowMessage(NegotiationStatus.ERROR, "Invalid status " + statusByte); } int payloadBytes = EncodingUtils.decodeBigEndian(messageHeader, STATUS_BYTES); if (payloadBytes < 0 || payloadBytes > getConfiguration().getMaxMessageSize() /* 100 MB */) { throw sendAndThrowMessage( NegotiationStatus.ERROR, "Invalid payload header length: " + payloadBytes); } byte[] payload = new byte[payloadBytes]; underlyingTransport.readAll(payload, 0, payload.length); if (status == NegotiationStatus.BAD || status == NegotiationStatus.ERROR) { String remoteMessage = new String(payload, StandardCharsets.UTF_8); throw new TTransportException("Peer indicated failure: " + remoteMessage); } LOGGER.debug( "{}: Received message with status {} and payload length {}", getRole(), status, payload.length); return new SaslResponse(status, payload); } /** * Send a Thrift SASL message with the given status (usually BAD or ERROR) and string message, and * then throw a TTransportException with the given message. * * @param status The Thrift SASL status code to send. Usually BAD or ERROR. * @param message The optional message to send to the other side. * @throws TTransportException Always thrown with the message provided. * @return always throws TTransportException but declares return type to allow throw * sendAndThrowMessage(...) to inform compiler control flow */ protected TTransportException sendAndThrowMessage(NegotiationStatus status, String message) throws TTransportException { try { sendSaslMessage(status, message.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { LOGGER.warn("Could not send failure response", e); message += "\nAlso, could not send response: " + e.toString(); } throw new TTransportException(message); } /** * Implemented by subclasses to start the Thrift SASL handshake process. When this method * completes, the SaslParticipant in this class is assumed to be initialized. * * @throws TTransportException * @throws SaslException */ protected abstract void handleSaslStartMessage() throws TTransportException, SaslException; protected abstract SaslRole getRole(); /** * Opens the underlying transport if it's not already open and then performs SASL negotiation. If * a QOP is negotiated during this SASL handshake, it used for all communication on this transport * after this call is complete. */ @Override public void open() throws TTransportException { /* * readSaslHeader is used to tag whether the SASL header has been read properly. * If there is a problem in reading the header, there might not be any * data in the stream, possibly a TCP health check from load balancer. */ boolean readSaslHeader = false; LOGGER.debug("opening transport {}", this); if (sasl != null && sasl.isComplete()) throw new TTransportException("SASL transport already open"); if (!underlyingTransport.isOpen()) underlyingTransport.open(); try { // Negotiate a SASL mechanism. The client also sends its // initial response, or an empty one. handleSaslStartMessage(); readSaslHeader = true; LOGGER.debug("{}: Start message handled", getRole()); SaslResponse message = null; while (!sasl.isComplete()) { message = receiveSaslMessage(); if (message.status != NegotiationStatus.COMPLETE && message.status != NegotiationStatus.OK) { throw new TTransportException("Expected COMPLETE or OK, got " + message.status); } byte[] challenge = sasl.evaluateChallengeOrResponse(message.payload); // If we are the client, and the server indicates COMPLETE, we don't need to // send back any further response. if (message.status == NegotiationStatus.COMPLETE && getRole() == SaslRole.CLIENT) { LOGGER.debug("{}: All done!", getRole()); continue; } sendSaslMessage( sasl.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK, challenge); } LOGGER.debug("{}: Main negotiation loop complete", getRole()); // If we're the client, and we're complete, but the server isn't // complete yet, we need to wait for its response. This will occur // with ANONYMOUS auth, for example, where we send an initial response // and are immediately complete. if (getRole() == SaslRole.CLIENT && (message == null || message.status == NegotiationStatus.OK)) { LOGGER.debug("{}: SASL Client receiving last message", getRole()); message = receiveSaslMessage(); if (message.status != NegotiationStatus.COMPLETE) { throw new TTransportException("Expected SASL COMPLETE, but got " + message.status); } } } catch (SaslException e) { try { LOGGER.error("SASL negotiation failure", e); throw sendAndThrowMessage(NegotiationStatus.BAD, e.getMessage()); } finally { underlyingTransport.close(); } } catch (TTransportException e) { // If there is no-data or no-sasl header in the stream, // log the failure, and clean up the underlying transport. if (!readSaslHeader && e.getType() == TTransportException.END_OF_FILE) { underlyingTransport.close(); LOGGER.debug("No data or no sasl data in the stream during negotiation"); } throw e; } String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP); if (qop != null && !qop.equalsIgnoreCase("auth")) shouldWrap = true; } /** * Get the underlying SaslClient. * * @return The SaslClient, or null if this transport is backed by a * SaslServer. */ public SaslClient getSaslClient() { return sasl.saslClient; } /** * Get the underlying transport that Sasl is using. * * @return The TTransport transport */ public TTransport getUnderlyingTransport() { return underlyingTransport; } /** * Get the underlying SaslServer. * * @return The SaslServer, or null if this transport is backed by a * SaslClient. */ public SaslServer getSaslServer() { return sasl.saslServer; } /** * Read a 4-byte word from the underlying transport and interpret it as an integer. * * @return The length prefix of the next SASL message to read. * @throws TTransportException Thrown if reading from the underlying transport fails. */ protected int readLength() throws TTransportException { byte[] lenBuf = new byte[4]; underlyingTransport.readAll(lenBuf, 0, lenBuf.length); return EncodingUtils.decodeBigEndian(lenBuf); } /** * Write the given integer as 4 bytes to the underlying transport. * * @param length The length prefix of the next SASL message to write. * @throws TTransportException Thrown if writing to the underlying transport fails. */ protected void writeLength(int length) throws TTransportException { byte[] lenBuf = new byte[4]; TFramedTransport.encodeFrameSize(length, lenBuf); underlyingTransport.write(lenBuf); } // Below is the SASL implementation of the TTransport interface. /** * Closes the underlying transport and disposes of the SASL implementation underlying this * transport. */ @Override public void close() { underlyingTransport.close(); try { sasl.dispose(); } catch (SaslException e) { LOGGER.warn("Failed to dispose sasl participant.", e); } } /** True if the underlying transport is open and the SASL handshake is complete. */ @Override public boolean isOpen() { return underlyingTransport.isOpen() && sasl != null && sasl.isComplete(); } /** * Read from the underlying transport. Unwraps the contents if a QOP was negotiated during the * SASL handshake. */ @Override public int read(byte[] buf, int off, int len) throws TTransportException { if (!isOpen()) throw new TTransportException("SASL authentication not complete"); int got = readBuffer.read(buf, off, len); if (got > 0) { return got; } // Read another frame of data try { readFrame(); } catch (SaslException e) { throw new TTransportException(e); } catch (TTransportException transportException) { // If there is no-data or no-sasl header in the stream, log the failure, and rethrow. if (transportException.getType() == TTransportException.END_OF_FILE) { LOGGER.debug("No data or no sasl data in the stream during negotiation"); } throw transportException; } return readBuffer.read(buf, off, len); } /** * Read a single frame of data from the underlying transport, unwrapping if necessary. * * @throws TTransportException Thrown if there's an error reading from the underlying transport. * @throws SaslException Thrown if there's an error unwrapping the data. */ private void readFrame() throws TTransportException, SaslException { int dataLength = readLength(); if (dataLength < 0) throw new TTransportException("Read a negative frame size (" + dataLength + ")!"); byte[] buff = new byte[dataLength]; LOGGER.debug("{}: reading data length: {}", getRole(), dataLength); underlyingTransport.readAll(buff, 0, dataLength); if (shouldWrap) { buff = sasl.unwrap(buff, 0, buff.length); LOGGER.debug("data length after unwrap: {}", buff.length); } readBuffer.reset(buff); } /** Write to the underlying transport. */ @Override public void write(byte[] buf, int off, int len) throws TTransportException { if (!isOpen()) throw new TTransportException("SASL authentication not complete"); writeBuffer.write(buf, off, len); } /** * Flushes to the underlying transport. Wraps the contents if a QOP was negotiated during the SASL * handshake. */ @Override public void flush() throws TTransportException { byte[] buf = writeBuffer.get(); int dataLength = writeBuffer.len(); writeBuffer.reset(); if (shouldWrap) { LOGGER.debug("data length before wrap: {}", dataLength); try { buf = sasl.wrap(buf, 0, dataLength); } catch (SaslException e) { throw new TTransportException(e); } dataLength = buf.length; } LOGGER.debug("writing data length: {}", dataLength); writeLength(dataLength); underlyingTransport.write(buf, 0, dataLength); underlyingTransport.flush(); } /** Used exclusively by readSaslMessage to return both a status and data. */ protected static class SaslResponse { public NegotiationStatus status; public byte[] payload; public SaslResponse(NegotiationStatus status, byte[] payload) { this.status = status; this.payload = payload; } } /** * Used to abstract over the SaslServer and SaslClient classes, which * share a lot of their interface, but unfortunately don't share a common superclass. */ private static class SaslParticipant { // One of these will always be null. public SaslServer saslServer; public SaslClient saslClient; public SaslParticipant(SaslServer saslServer) { this.saslServer = saslServer; } public SaslParticipant(SaslClient saslClient) { this.saslClient = saslClient; } public byte[] evaluateChallengeOrResponse(byte[] challengeOrResponse) throws SaslException { if (saslClient != null) { return saslClient.evaluateChallenge(challengeOrResponse); } else { return saslServer.evaluateResponse(challengeOrResponse); } } public boolean isComplete() { if (saslClient != null) return saslClient.isComplete(); else return saslServer.isComplete(); } public void dispose() throws SaslException { if (saslClient != null) saslClient.dispose(); else saslServer.dispose(); } public byte[] unwrap(byte[] buf, int off, int len) throws SaslException { if (saslClient != null) return saslClient.unwrap(buf, off, len); else return saslServer.unwrap(buf, off, len); } public byte[] wrap(byte[] buf, int off, int len) throws SaslException { if (saslClient != null) return saslClient.wrap(buf, off, len); else return saslServer.wrap(buf, off, len); } public Object getNegotiatedProperty(String propName) { if (saslClient != null) return saslClient.getNegotiatedProperty(propName); else return saslServer.getNegotiatedProperty(propName); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSSLTransportFactory.java0000644000000000000000000003661314370300523031471 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.URL; import java.security.KeyStore; import java.util.Arrays; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Factory for providing and setting up Client and Server SSL wrapped TSocket and TServerSocket */ public class TSSLTransportFactory { private static final Logger LOGGER = LoggerFactory.getLogger(TSSLTransportFactory.class); /** * Get a SSL wrapped TServerSocket bound to the specified port. In this configuration the default * settings are used. Default settings are retrieved from System properties that are set. * *

Example system properties: -Djavax.net.ssl.trustStore=<truststore location> * -Djavax.net.ssl.trustStorePassword=password -Djavax.net.ssl.keyStore=<keystore location> * -Djavax.net.ssl.keyStorePassword=password * * @param port server port * @return A SSL wrapped TServerSocket * @throws TTransportException when failed to create server socket */ public static TServerSocket getServerSocket(int port) throws TTransportException { return getServerSocket(port, 0); } /** * Get a default SSL wrapped TServerSocket bound to the specified port * * @param port * @param clientTimeout * @return A SSL wrapped TServerSocket * @throws TTransportException */ public static TServerSocket getServerSocket(int port, int clientTimeout) throws TTransportException { return getServerSocket(port, clientTimeout, false, null); } /** * Get a default SSL wrapped TServerSocket bound to the specified port and interface * * @param port * @param clientTimeout * @param ifAddress * @return A SSL wrapped TServerSocket * @throws TTransportException */ public static TServerSocket getServerSocket( int port, int clientTimeout, boolean clientAuth, InetAddress ifAddress) throws TTransportException { SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); return createServer(factory, port, clientTimeout, clientAuth, ifAddress, null); } /** * Get a configured SSL wrapped TServerSocket bound to the specified port and interface. Here the * TSSLTransportParameters are used to set the values for the algorithms, keystore, truststore and * other settings * * @param port * @param clientTimeout * @param ifAddress * @param params * @return A SSL wrapped TServerSocket * @throws TTransportException */ public static TServerSocket getServerSocket( int port, int clientTimeout, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { throw new TTransportException( "Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); } SSLContext ctx = createSSLContext(params); return createServer( ctx.getServerSocketFactory(), port, clientTimeout, params.clientAuth, ifAddress, params); } private static TServerSocket createServer( SSLServerSocketFactory factory, int port, int timeout, boolean clientAuth, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { try { SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(port, 100, ifAddress); serverSocket.setSoTimeout(timeout); serverSocket.setNeedClientAuth(clientAuth); if (params != null && params.cipherSuites != null) { serverSocket.setEnabledCipherSuites(params.cipherSuites); } return new TServerSocket( new TServerSocket.ServerSocketTransportArgs() .serverSocket(serverSocket) .clientTimeout(timeout)); } catch (Exception e) { throw new TTransportException("Could not bind to port " + port, e); } } /** * Get a default SSL wrapped TSocket connected to the specified host and port. All the client * methods return a bound connection. So there is no need to call open() on the TTransport. * * @param host * @param port * @param timeout * @return A SSL wrapped TSocket * @throws TTransportException */ public static TSocket getClientSocket(String host, int port, int timeout) throws TTransportException { SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); return createClient(factory, host, port, timeout); } /** * Get a default SSL wrapped TSocket connected to the specified host and port. * * @param host * @param port * @return A SSL wrapped TSocket * @throws TTransportException */ public static TSocket getClientSocket(String host, int port) throws TTransportException { return getClientSocket(host, port, 0); } /** * Get a custom configured SSL wrapped TSocket. The SSL settings are obtained from the passed in * TSSLTransportParameters. * * @param host * @param port * @param timeout * @param params * @return A SSL wrapped TSocket * @throws TTransportException */ public static TSocket getClientSocket( String host, int port, int timeout, TSSLTransportParameters params) throws TTransportException { if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { throw new TTransportException( TTransportException.NOT_OPEN, "Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); } SSLContext ctx = createSSLContext(params); return createClient(ctx.getSocketFactory(), host, port, timeout); } private static SSLContext createSSLContext(TSSLTransportParameters params) throws TTransportException { SSLContext ctx; InputStream in = null; InputStream is = null; try { ctx = SSLContext.getInstance(params.protocol); TrustManagerFactory tmf = null; KeyManagerFactory kmf = null; if (params.isTrustStoreSet) { tmf = TrustManagerFactory.getInstance(params.trustManagerType); KeyStore ts = KeyStore.getInstance(params.trustStoreType); if (params.trustStoreStream != null) { in = params.trustStoreStream; } else { in = getStoreAsStream(params.trustStore); } ts.load(in, (params.trustPass != null ? params.trustPass.toCharArray() : null)); tmf.init(ts); } if (params.isKeyStoreSet) { kmf = KeyManagerFactory.getInstance(params.keyManagerType); KeyStore ks = KeyStore.getInstance(params.keyStoreType); if (params.keyStoreStream != null) { is = params.keyStoreStream; } else { is = getStoreAsStream(params.keyStore); } ks.load(is, params.keyPass.toCharArray()); kmf.init(ks, params.keyPass.toCharArray()); } if (params.isKeyStoreSet && params.isTrustStoreSet) { ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); } else if (params.isKeyStoreSet) { ctx.init(kmf.getKeyManagers(), null, null); } else { ctx.init(null, tmf.getTrustManagers(), null); } } catch (Exception e) { throw new TTransportException( TTransportException.NOT_OPEN, "Error creating the transport", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { LOGGER.warn("Unable to close stream", e); } } if (is != null) { try { is.close(); } catch (IOException e) { LOGGER.warn("Unable to close stream", e); } } } return ctx; } private static InputStream getStoreAsStream(String store) throws IOException { try { return new FileInputStream(store); } catch (FileNotFoundException e) { } InputStream storeStream; try { storeStream = new URL(store).openStream(); if (storeStream != null) { return storeStream; } } catch (MalformedURLException e) { } storeStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(store); if (storeStream != null) { return storeStream; } else { throw new IOException("Could not load file: " + store); } } private static TSocket createClient(SSLSocketFactory factory, String host, int port, int timeout) throws TTransportException { try { SSLSocket socket = (SSLSocket) factory.createSocket(host, port); socket.setSoTimeout(timeout); return new TSocket(socket); } catch (TTransportException tte) { throw tte; } catch (Exception e) { throw new TTransportException( TTransportException.NOT_OPEN, "Could not connect to " + host + " on port " + port, e); } } /** A Class to hold all the SSL parameters */ public static class TSSLTransportParameters { protected String protocol = "TLS"; protected String keyStore; protected InputStream keyStoreStream; protected String keyPass; protected String keyManagerType = KeyManagerFactory.getDefaultAlgorithm(); protected String keyStoreType = "JKS"; protected String trustStore; protected InputStream trustStoreStream; protected String trustPass; protected String trustManagerType = TrustManagerFactory.getDefaultAlgorithm(); protected String trustStoreType = "JKS"; protected String[] cipherSuites; protected boolean clientAuth = false; protected boolean isKeyStoreSet = false; protected boolean isTrustStoreSet = false; public TSSLTransportParameters() {} /** * Create parameters specifying the protocol and cipher suites * * @param protocol The specific protocol (TLS/SSL) can be specified with versions * @param cipherSuites */ public TSSLTransportParameters(String protocol, String[] cipherSuites) { this(protocol, cipherSuites, false); } /** * Create parameters specifying the protocol, cipher suites and if client authentication is * required * * @param protocol The specific protocol (TLS/SSL) can be specified with versions * @param cipherSuites * @param clientAuth */ public TSSLTransportParameters(String protocol, String[] cipherSuites, boolean clientAuth) { if (protocol != null) { this.protocol = protocol; } this.cipherSuites = cipherSuites != null ? Arrays.copyOf(cipherSuites, cipherSuites.length) : null; this.clientAuth = clientAuth; } /** * Set the keystore, password, certificate type and the store type * * @param keyStore Location of the Keystore on disk * @param keyPass Keystore password * @param keyManagerType The default is X509 * @param keyStoreType The default is JKS */ public void setKeyStore( String keyStore, String keyPass, String keyManagerType, String keyStoreType) { this.keyStore = keyStore; this.keyPass = keyPass; if (keyManagerType != null) { this.keyManagerType = keyManagerType; } if (keyStoreType != null) { this.keyStoreType = keyStoreType; } isKeyStoreSet = true; } /** * Set the keystore, password, certificate type and the store type * * @param keyStoreStream Keystore content input stream * @param keyPass Keystore password * @param keyManagerType The default is X509 * @param keyStoreType The default is JKS */ public void setKeyStore( InputStream keyStoreStream, String keyPass, String keyManagerType, String keyStoreType) { this.keyStoreStream = keyStoreStream; setKeyStore("", keyPass, keyManagerType, keyStoreType); } /** * Set the keystore and password * * @param keyStore Location of the Keystore on disk * @param keyPass Keystore password */ public void setKeyStore(String keyStore, String keyPass) { setKeyStore(keyStore, keyPass, null, null); } /** * Set the keystore and password * * @param keyStoreStream Keystore content input stream * @param keyPass Keystore password */ public void setKeyStore(InputStream keyStoreStream, String keyPass) { setKeyStore(keyStoreStream, keyPass, null, null); } /** * Set the truststore, password, certificate type and the store type * * @param trustStore Location of the Truststore on disk * @param trustPass Truststore password * @param trustManagerType The default is X509 * @param trustStoreType The default is JKS */ public void setTrustStore( String trustStore, String trustPass, String trustManagerType, String trustStoreType) { this.trustStore = trustStore; this.trustPass = trustPass; if (trustManagerType != null) { this.trustManagerType = trustManagerType; } if (trustStoreType != null) { this.trustStoreType = trustStoreType; } isTrustStoreSet = true; } /** * Set the truststore, password, certificate type and the store type * * @param trustStoreStream Truststore content input stream * @param trustPass Truststore password * @param trustManagerType The default is X509 * @param trustStoreType The default is JKS */ public void setTrustStore( InputStream trustStoreStream, String trustPass, String trustManagerType, String trustStoreType) { this.trustStoreStream = trustStoreStream; setTrustStore("", trustPass, trustManagerType, trustStoreType); } /** * Set the truststore and password * * @param trustStore Location of the Truststore on disk * @param trustPass Truststore password */ public void setTrustStore(String trustStore, String trustPass) { setTrustStore(trustStore, trustPass, null, null); } /** * Set the truststore and password * * @param trustStoreStream Truststore content input stream * @param trustPass Truststore password */ public void setTrustStore(InputStream trustStoreStream, String trustPass) { setTrustStore(trustStoreStream, trustPass, null, null); } /** * Set if client authentication is required * * @param clientAuth */ public void requireClientAuth(boolean clientAuth) { this.clientAuth = clientAuth; } } } AutoExpandingBufferReadTransport.java0000644000000000000000000000462714303740367034003 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TConfiguration; /** TTransport for reading from an AutoExpandingBuffer. */ public class AutoExpandingBufferReadTransport extends TEndpointTransport { private final AutoExpandingBuffer buf; private int pos = 0; private int limit = 0; public AutoExpandingBufferReadTransport(TConfiguration config, int initialCapacity) throws TTransportException { super(config); this.buf = new AutoExpandingBuffer(initialCapacity); } public void fill(TTransport inTrans, int length) throws TTransportException { buf.resizeIfNecessary(length); inTrans.readAll(buf.array(), 0, length); pos = 0; limit = length; } @Override public void close() {} @Override public boolean isOpen() { return true; } @Override public void open() throws TTransportException {} @Override public final int read(byte[] target, int off, int len) throws TTransportException { int amtToRead = Math.min(len, getBytesRemainingInBuffer()); if (amtToRead > 0) { System.arraycopy(buf.array(), pos, target, off, amtToRead); consumeBuffer(amtToRead); } return amtToRead; } @Override public void write(byte[] buf, int off, int len) throws TTransportException { throw new UnsupportedOperationException(); } @Override public final void consumeBuffer(int len) { pos += len; } @Override public final byte[] getBuffer() { return buf.array(); } @Override public final int getBufferPosition() { return pos; } @Override public final int getBytesRemainingInBuffer() { return limit - pos; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TNonblockingSocket.java0000644000000000000000000001540214303740367031202 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import org.apache.thrift.TConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Transport for use with async client. */ public class TNonblockingSocket extends TNonblockingTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TNonblockingSocket.class.getName()); /** Host and port if passed in, used for lazy non-blocking connect. */ private final SocketAddress socketAddress_; private final SocketChannel socketChannel_; public TNonblockingSocket(String host, int port) throws IOException, TTransportException { this(host, port, 0); } /** * Create a new nonblocking socket transport that will be connected to host:port. * * @param host * @param port * @throws IOException */ public TNonblockingSocket(String host, int port, int timeout) throws IOException, TTransportException { this(SocketChannel.open(), timeout, new InetSocketAddress(host, port)); } /** * Constructor that takes an already created socket. * * @param socketChannel Already created SocketChannel object * @throws IOException if there is an error setting up the streams */ public TNonblockingSocket(SocketChannel socketChannel) throws IOException, TTransportException { this(socketChannel, 0, null); if (!socketChannel.isConnected()) throw new IOException("Socket must already be connected"); } private TNonblockingSocket(SocketChannel socketChannel, int timeout, SocketAddress socketAddress) throws IOException, TTransportException { this(new TConfiguration(), socketChannel, timeout, socketAddress); } private TNonblockingSocket( TConfiguration config, SocketChannel socketChannel, int timeout, SocketAddress socketAddress) throws IOException, TTransportException { super(config); socketChannel_ = socketChannel; socketAddress_ = socketAddress; // make it a nonblocking channel socketChannel.configureBlocking(false); // set options Socket socket = socketChannel.socket(); socket.setSoLinger(false, 0); socket.setTcpNoDelay(true); socket.setKeepAlive(true); setTimeout(timeout); } /** * Register the new SocketChannel with our Selector, indicating we'd like to be notified when it's * ready for I/O. * * @param selector * @return the selection key for this socket. */ public SelectionKey registerSelector(Selector selector, int interests) throws IOException { return socketChannel_.register(selector, interests); } /** * Sets the socket timeout, although this implementation never uses blocking operations so it is * unused. * * @param timeout Milliseconds timeout */ public void setTimeout(int timeout) { try { socketChannel_.socket().setSoTimeout(timeout); } catch (SocketException sx) { LOGGER.warn("Could not set socket timeout.", sx); } } /** Returns a reference to the underlying SocketChannel. */ public SocketChannel getSocketChannel() { return socketChannel_; } /** Checks whether the socket is connected. */ public boolean isOpen() { // isConnected() does not return false after close(), but isOpen() does return socketChannel_.isOpen() && socketChannel_.isConnected(); } /** Do not call, the implementation provides its own lazy non-blocking connect. */ public void open() throws TTransportException { throw new RuntimeException("open() is not implemented for TNonblockingSocket"); } /** Perform a nonblocking read into buffer. */ public int read(ByteBuffer buffer) throws TTransportException { try { return socketChannel_.read(buffer); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } /** Reads from the underlying input stream if not null. */ public int read(byte[] buf, int off, int len) throws TTransportException { if ((socketChannel_.validOps() & SelectionKey.OP_READ) != SelectionKey.OP_READ) { throw new TTransportException( TTransportException.NOT_OPEN, "Cannot read from write-only socket channel"); } try { return socketChannel_.read(ByteBuffer.wrap(buf, off, len)); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } /** Perform a nonblocking write of the data in buffer; */ public int write(ByteBuffer buffer) throws TTransportException { try { return socketChannel_.write(buffer); } catch (IOException iox) { throw new TTransportException(TTransportException.UNKNOWN, iox); } } /** Writes to the underlying output stream if not null. */ public void write(byte[] buf, int off, int len) throws TTransportException { if ((socketChannel_.validOps() & SelectionKey.OP_WRITE) != SelectionKey.OP_WRITE) { throw new TTransportException( TTransportException.NOT_OPEN, "Cannot write to write-only socket channel"); } write(ByteBuffer.wrap(buf, off, len)); } /** Noop. */ public void flush() throws TTransportException { // Not supported by SocketChannel. } /** Closes the socket. */ public void close() { try { socketChannel_.close(); } catch (IOException iox) { LOGGER.warn("Could not close socket.", iox); } } /** {@inheritDoc} */ public boolean startConnect() throws IOException { return socketChannel_.connect(socketAddress_); } /** {@inheritDoc} */ public boolean finishConnect() throws IOException { return socketChannel_.finishConnect(); } @Override public String toString() { return "[remote: " + socketChannel_.socket().getRemoteSocketAddress() + ", local: " + socketChannel_.socket().getLocalAddress() + "]"; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSimpleFileTransport.java0000644000000000000000000001500114370300523031515 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.io.RandomAccessFile; import org.apache.thrift.TConfiguration; /** Basic file support for the TTransport interface */ public final class TSimpleFileTransport extends TEndpointTransport { private RandomAccessFile file = null; private final boolean readable; private final boolean writable; private final String path_; /** * Create a transport backed by a simple file * * @param path the path to the file to open/create * @param read true to support read operations * @param write true to support write operations * @param openFile true to open the file on construction * @throws TTransportException if file open fails */ public TSimpleFileTransport(String path, boolean read, boolean write, boolean openFile) throws TTransportException { this(new TConfiguration(), path, read, write, openFile); } /** * Create a transport backed by a simple file * * @param config * @param path the path to the file to open/create * @param read true to support read operations * @param write true to support write operations * @param openFile true to open the file on construction * @throws TTransportException if file open fails */ public TSimpleFileTransport( TConfiguration config, String path, boolean read, boolean write, boolean openFile) throws TTransportException { super(config); if (path.length() <= 0) { throw new TTransportException("No path specified"); } if (!read && !write) { throw new TTransportException("Neither READ nor WRITE specified"); } readable = read; writable = write; path_ = path; if (openFile) { open(); } } /** * Create a transport backed by a simple file Implicitly opens file to conform to C++ behavior. * * @param path the path to the file to open/create * @param read true to support read operations * @param write true to support write operations * @throws TTransportException if file open fails */ public TSimpleFileTransport(String path, boolean read, boolean write) throws TTransportException { this(path, read, write, true); } /** * Create a transport backed by a simple read only disk file (implicitly opens file) * * @param path the path to the file to open/create * @throws TTransportException if file open fails */ public TSimpleFileTransport(String path) throws TTransportException { this(path, true, false, true); } /** * Test file status * * @return true if open, otherwise false */ @Override public boolean isOpen() { return (file != null); } /** * Open file if not previously opened. * * @throws TTransportException if open fails */ @Override public void open() throws TTransportException { if (file == null) { try { String access = "r"; // RandomAccessFile objects must be readable if (writable) { access += "w"; } file = new RandomAccessFile(path_, access); } catch (IOException ioe) { file = null; throw new TTransportException(ioe.getMessage()); } } } /** Close file, subsequent read/write activity will throw exceptions */ @Override public void close() { if (file != null) { try { file.close(); } catch (Exception e) { // Nothing to do } file = null; } } /** * Read up to len many bytes into buf at offset * * @param buf houses bytes read * @param off offset into buff to begin writing to * @param len maximum number of bytes to read * @return number of bytes actually read * @throws TTransportException on read failure */ @Override public int read(byte[] buf, int off, int len) throws TTransportException { if (!readable) { throw new TTransportException("Read operation on write only file"); } checkReadBytesAvailable(len); int iBytesRead = 0; try { iBytesRead = file.read(buf, off, len); } catch (IOException ioe) { file = null; throw new TTransportException(ioe.getMessage()); } return iBytesRead; } /** * Write len many bytes from buff starting at offset * * @param buf buffer containing bytes to write * @param off offset into buffer to begin writing from * @param len number of bytes to write * @throws TTransportException on write failure */ @Override public void write(byte[] buf, int off, int len) throws TTransportException { try { file.write(buf, off, len); } catch (IOException ioe) { file = null; throw new TTransportException(ioe.getMessage()); } } /** * Move file pointer to specified offset, new read/write calls will act here * * @param offset bytes from beginning of file to move pointer to * @throws TTransportException is seek fails */ public void seek(long offset) throws TTransportException { try { file.seek(offset); } catch (IOException ex) { throw new TTransportException(ex.getMessage()); } } /** * Return the length of the file in bytes * * @return length of the file in bytes * @throws TTransportException if file access fails */ public long length() throws TTransportException { try { return file.length(); } catch (IOException ex) { throw new TTransportException(ex.getMessage()); } } /** * Return current file pointer position in bytes from beginning of file * * @return file pointer position * @throws TTransportException if file access fails */ public long getFilePointer() throws TTransportException { try { return file.getFilePointer(); } catch (IOException ex) { throw new TTransportException(ex.getMessage()); } } } AutoExpandingBufferWriteTransport.java0000644000000000000000000000566214303740367034222 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TConfiguration; /** TTransport for writing to an AutoExpandingBuffer. */ public final class AutoExpandingBufferWriteTransport extends TEndpointTransport { private final AutoExpandingBuffer buf; private int pos; private int res; /** * Constructor. * * @param config the configuration to use. Currently used for defining the maximum message size. * @param initialCapacity the initial capacity of the buffer * @param frontReserve space, if any, to reserve at the beginning such that the first write is * after this reserve. This allows framed transport to reserve space for the frame buffer * length. * @throws IllegalArgumentException if initialCapacity is less than one * @throws IllegalArgumentException if frontReserve is less than zero * @throws IllegalArgumentException if frontReserve is greater than initialCapacity */ public AutoExpandingBufferWriteTransport( TConfiguration config, int initialCapacity, int frontReserve) throws TTransportException { super(config); if (initialCapacity < 1) { throw new IllegalArgumentException("initialCapacity"); } if (frontReserve < 0 || initialCapacity < frontReserve) { throw new IllegalArgumentException("frontReserve"); } this.buf = new AutoExpandingBuffer(initialCapacity); this.pos = frontReserve; this.res = frontReserve; } @Override public void close() {} @Override public boolean isOpen() { return true; } @Override public void open() throws TTransportException {} @Override public int read(byte[] buf, int off, int len) throws TTransportException { throw new UnsupportedOperationException(); } @Override public void write(byte[] toWrite, int off, int len) throws TTransportException { buf.resizeIfNecessary(pos + len); System.arraycopy(toWrite, off, buf.array(), pos, len); pos += len; } public AutoExpandingBuffer getBuf() { return buf; } /** * @return length of the buffer, including any front reserve */ public int getLength() { return pos; } public void reset() { pos = res; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TEndpointTransport.java0000644000000000000000000000667214303740367031274 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.util.Objects; import org.apache.thrift.TConfiguration; public abstract class TEndpointTransport extends TTransport { protected long getMaxMessageSize() { return getConfiguration().getMaxMessageSize(); } public int getMaxFrameSize() { return getConfiguration().getMaxFrameSize(); } public void setMaxFrameSize(int maxFrameSize) { getConfiguration().setMaxFrameSize(maxFrameSize); } protected long knownMessageSize; protected long remainingMessageSize; private TConfiguration _configuration; public TConfiguration getConfiguration() { return _configuration; } public TEndpointTransport(TConfiguration config) throws TTransportException { _configuration = Objects.isNull(config) ? new TConfiguration() : config; resetConsumedMessageSize(-1); } /** * Resets RemainingMessageSize to the configured maximum * * @param newSize */ protected void resetConsumedMessageSize(long newSize) throws TTransportException { // full reset if (newSize < 0) { knownMessageSize = getMaxMessageSize(); remainingMessageSize = getMaxMessageSize(); return; } // update only: message size can shrink, but not grow if (newSize > knownMessageSize) throw new TTransportException(TTransportException.END_OF_FILE, "MaxMessageSize reached"); knownMessageSize = newSize; remainingMessageSize = newSize; } /** * Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). * Will throw if we already consumed too many bytes or if the new size is larger than allowed. * * @param size */ public void updateKnownMessageSize(long size) throws TTransportException { long consumed = knownMessageSize - remainingMessageSize; resetConsumedMessageSize(size == 0 ? -1 : size); countConsumedMessageBytes(consumed); } /** * Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of * data * * @param numBytes */ public void checkReadBytesAvailable(long numBytes) throws TTransportException { if (remainingMessageSize < numBytes) throw new TTransportException(TTransportException.END_OF_FILE, "MaxMessageSize reached"); } /** * Consumes numBytes from the RemainingMessageSize. * * @param numBytes */ protected void countConsumedMessageBytes(long numBytes) throws TTransportException { if (remainingMessageSize >= numBytes) { remainingMessageSize -= numBytes; } else { remainingMessageSize = 0; throw new TTransportException(TTransportException.END_OF_FILE, "MaxMessageSize reached"); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSaslServerTransport.java0000644000000000000000000002073514303740367031601 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.lang.ref.WeakReference; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import org.apache.thrift.transport.sasl.NegotiationStatus; import org.apache.thrift.transport.sasl.TSaslServerDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Wraps another Thrift TTransport, but performs SASL server negotiation on the call to * open(). This class will wrap ensuing communication over it, if a SASL QOP is * negotiated with the other party. */ public class TSaslServerTransport extends TSaslTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TSaslServerTransport.class); /** * Mapping from SASL mechanism name -> all the parameters required to instantiate a SASL server. */ private Map serverDefinitionMap = new HashMap(); /** * Uses the given underlying transport. Assumes that addServerDefinition is called later. * * @param transport Transport underlying this one. */ public TSaslServerTransport(TTransport transport) throws TTransportException { super(transport); } /** * Creates a SaslServer using the given SASL-specific parameters. See the Java * documentation for Sasl.createSaslServer for the details of the parameters. * * @param transport The underlying Thrift transport. */ public TSaslServerTransport( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh, TTransport transport) throws TTransportException { super(transport); addServerDefinition(mechanism, protocol, serverName, props, cbh); } private TSaslServerTransport( Map serverDefinitionMap, TTransport transport) throws TTransportException { super(transport); this.serverDefinitionMap.putAll(serverDefinitionMap); } /** * Add a supported server definition to this transport. See the Java documentation for * Sasl.createSaslServer for the details of the parameters. */ public void addServerDefinition( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { serverDefinitionMap.put( mechanism, new TSaslServerDefinition(mechanism, protocol, serverName, props, cbh)); } @Override protected SaslRole getRole() { return SaslRole.SERVER; } /** * Performs the server side of the initial portion of the Thrift SASL protocol. Receives the * initial response from the client, creates a SASL server using the mechanism requested by the * client (if this server supports it), and sends the first challenge back to the client. */ @Override protected void handleSaslStartMessage() throws TTransportException, SaslException { SaslResponse message = receiveSaslMessage(); LOGGER.debug("Received start message with status {}", message.status); if (message.status != NegotiationStatus.START) { throw sendAndThrowMessage( NegotiationStatus.ERROR, "Expecting START status, received " + message.status); } // Get the mechanism name. String mechanismName = new String(message.payload, StandardCharsets.UTF_8); TSaslServerDefinition serverDefinition = serverDefinitionMap.get(mechanismName); LOGGER.debug("Received mechanism name '{}'", mechanismName); if (serverDefinition == null) { throw sendAndThrowMessage( NegotiationStatus.BAD, "Unsupported mechanism type " + mechanismName); } SaslServer saslServer = Sasl.createSaslServer( serverDefinition.mechanism, serverDefinition.protocol, serverDefinition.serverName, serverDefinition.props, serverDefinition.cbh); setSaslServer(saslServer); } /** * TTransportFactory to create TSaslServerTransports. Ensures that a * given underlying TTransport instance receives the same TSaslServerTransport * . This is kind of an awful hack to work around the fact that Thrift is designed assuming * that TTransport instances are stateless, and thus the existing TServers * use different TTransport instances for input and output. */ public static class Factory extends TTransportFactory { /** * This is the implementation of the awful hack described above. WeakHashMap is * used to ensure that we don't leak memory. */ private static Map> transportMap = Collections.synchronizedMap( new WeakHashMap>()); /** * Mapping from SASL mechanism name -> all the parameters required to instantiate a SASL server. */ private Map serverDefinitionMap = new HashMap(); /** Create a new Factory. Assumes that addServerDefinition will be called later. */ public Factory() { super(); } /** * Create a new Factory, initially with the single server definition given. You may * still call addServerDefinition later. See the Java documentation for * Sasl.createSaslServer for the details of the parameters. */ public Factory( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { super(); addServerDefinition(mechanism, protocol, serverName, props, cbh); } /** * Add a supported server definition to the transports created by this factory. See the Java * documentation for Sasl.createSaslServer for the details of the parameters. */ public void addServerDefinition( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { serverDefinitionMap.put( mechanism, new TSaslServerDefinition(mechanism, protocol, serverName, props, cbh)); } /** * Get a new TSaslServerTransport instance, or reuse the existing one if a * TSaslServerTransport has already been created before using the given TTransport * as an underlying transport. This ensures that a given underlying transport instance * receives the same TSaslServerTransport. */ @Override public TTransport getTransport(TTransport base) throws TTransportException { WeakReference ret = transportMap.get(base); if (ret == null || ret.get() == null) { LOGGER.debug("transport map does not contain key", base); ret = new WeakReference( new TSaslServerTransport(serverDefinitionMap, base)); try { ret.get().open(); } catch (TTransportException e) { LOGGER.debug("failed to open server transport", e); throw new RuntimeException(e); } transportMap.put(base, ret); // No need for putIfAbsent(). // Concurrent calls to getTransport() will pass in different TTransports. } else { LOGGER.debug("transport map does contain key {}", base); } return ret.get(); } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TNonblockingServerSocket.java0000644000000000000000000001371014303740367032371 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.SocketException; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import org.apache.thrift.TConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Wrapper around ServerSocketChannel */ public class TNonblockingServerSocket extends TNonblockingServerTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TNonblockingServerSocket.class.getName()); /** This channel is where all the nonblocking magic happens. */ private ServerSocketChannel serverSocketChannel = null; /** Underlying ServerSocket object */ private ServerSocket serverSocket_ = null; /** Timeout for client sockets from accept */ private int clientTimeout_ = 0; /** Limit for client sockets request size */ private int maxFrameSize_ = 0; public static class NonblockingAbstractServerSocketArgs extends AbstractServerTransportArgs {} /** Creates just a port listening server socket */ public TNonblockingServerSocket(int port) throws TTransportException { this(port, 0); } /** Creates just a port listening server socket */ public TNonblockingServerSocket(int port, int clientTimeout) throws TTransportException { this(port, clientTimeout, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } public TNonblockingServerSocket(int port, int clientTimeout, int maxFrameSize) throws TTransportException { this( new NonblockingAbstractServerSocketArgs() .port(port) .clientTimeout(clientTimeout) .maxFrameSize(maxFrameSize)); } public TNonblockingServerSocket(InetSocketAddress bindAddr) throws TTransportException { this(bindAddr, 0); } public TNonblockingServerSocket(InetSocketAddress bindAddr, int clientTimeout) throws TTransportException { this(bindAddr, clientTimeout, TConfiguration.DEFAULT_MAX_FRAME_SIZE); } public TNonblockingServerSocket(InetSocketAddress bindAddr, int clientTimeout, int maxFrameSize) throws TTransportException { this( new NonblockingAbstractServerSocketArgs() .bindAddr(bindAddr) .clientTimeout(clientTimeout) .maxFrameSize(maxFrameSize)); } public TNonblockingServerSocket(NonblockingAbstractServerSocketArgs args) throws TTransportException { clientTimeout_ = args.clientTimeout; maxFrameSize_ = args.maxFrameSize; try { serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); // Make server socket serverSocket_ = serverSocketChannel.socket(); // Prevent 2MSL delay problem on server restarts serverSocket_.setReuseAddress(true); // Bind to listening port serverSocket_.bind(args.bindAddr, args.backlog); } catch (IOException ioe) { serverSocket_ = null; throw new TTransportException( "Could not create ServerSocket on address " + args.bindAddr.toString() + ".", ioe); } } public void listen() throws TTransportException { // Make sure not to block on accept if (serverSocket_ != null) { try { serverSocket_.setSoTimeout(0); } catch (SocketException sx) { LOGGER.error("Socket exception while setting socket timeout", sx); } } } @Override public TNonblockingSocket accept() throws TTransportException { if (serverSocket_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); } try { SocketChannel socketChannel = serverSocketChannel.accept(); if (socketChannel == null) { return null; } TNonblockingSocket tsocket = new TNonblockingSocket(socketChannel); tsocket.setTimeout(clientTimeout_); tsocket.setMaxFrameSize(maxFrameSize_); return tsocket; } catch (IOException iox) { throw new TTransportException(iox); } } public void registerSelector(Selector selector) { try { // Register the server socket channel, indicating an interest in // accepting new connections serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); } catch (ClosedChannelException e) { // this shouldn't happen, ideally... // TODO: decide what to do with this. } } public void close() { if (serverSocket_ != null) { try { serverSocket_.close(); } catch (IOException iox) { LOGGER.warn("WARNING: Could not close server socket: " + iox.getMessage()); } serverSocket_ = null; } } public void interrupt() { // The thread-safeness of this is dubious, but Java documentation suggests // that it is safe to do this from a different thread context close(); } public int getPort() { if (serverSocket_ == null) return -1; return serverSocket_.getLocalPort(); } // Expose it for test purpose. ServerSocketChannel getServerSocketChannel() { return serverSocketChannel; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TServerSocket.java0000644000000000000000000001134614303740367030210 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Wrapper around ServerSocket for Thrift. */ public class TServerSocket extends TServerTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TServerSocket.class.getName()); /** Underlying ServerSocket object */ private ServerSocket serverSocket_ = null; /** Timeout for client sockets from accept */ private int clientTimeout_ = 0; public static class ServerSocketTransportArgs extends AbstractServerTransportArgs { ServerSocket serverSocket; public ServerSocketTransportArgs serverSocket(ServerSocket serverSocket) { this.serverSocket = serverSocket; return this; } } /** Creates a server socket from underlying socket object */ public TServerSocket(ServerSocket serverSocket) throws TTransportException { this(serverSocket, 0); } /** Creates a server socket from underlying socket object */ public TServerSocket(ServerSocket serverSocket, int clientTimeout) throws TTransportException { this(new ServerSocketTransportArgs().serverSocket(serverSocket).clientTimeout(clientTimeout)); } /** Creates just a port listening server socket */ public TServerSocket(int port) throws TTransportException { this(port, 0); } /** Creates just a port listening server socket */ public TServerSocket(int port, int clientTimeout) throws TTransportException { this(new InetSocketAddress(port), clientTimeout); } public TServerSocket(InetSocketAddress bindAddr) throws TTransportException { this(bindAddr, 0); } public TServerSocket(InetSocketAddress bindAddr, int clientTimeout) throws TTransportException { this(new ServerSocketTransportArgs().bindAddr(bindAddr).clientTimeout(clientTimeout)); } public TServerSocket(ServerSocketTransportArgs args) throws TTransportException { clientTimeout_ = args.clientTimeout; if (args.serverSocket != null) { this.serverSocket_ = args.serverSocket; return; } try { // Make server socket serverSocket_ = new ServerSocket(); // Prevent 2MSL delay problem on server restarts serverSocket_.setReuseAddress(true); // Bind to listening port serverSocket_.bind(args.bindAddr, args.backlog); } catch (IOException ioe) { close(); throw new TTransportException( "Could not create ServerSocket on address " + args.bindAddr.toString() + ".", ioe); } } public void listen() throws TTransportException { // Make sure to block on accept if (serverSocket_ != null) { try { serverSocket_.setSoTimeout(0); } catch (SocketException sx) { LOGGER.error("Could not set socket timeout.", sx); } } } @Override public TSocket accept() throws TTransportException { if (serverSocket_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); } Socket result; try { result = serverSocket_.accept(); } catch (Exception e) { throw new TTransportException(e); } if (result == null) { throw new TTransportException("Blocking server's accept() may not return NULL"); } TSocket socket = new TSocket(result); socket.setTimeout(clientTimeout_); return socket; } public void close() { if (serverSocket_ != null) { try { serverSocket_.close(); } catch (IOException iox) { LOGGER.warn("Could not close server socket.", iox); } serverSocket_ = null; } } public void interrupt() { // The thread-safeness of this is dubious, but Java documentation suggests // that it is safe to do this from a different thread context close(); } public ServerSocket getServerSocket() { return serverSocket_; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSeekableFile.java0000644000000000000000000000230514303740367030077 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public interface TSeekableFile { public InputStream getInputStream() throws IOException; public OutputStream getOutputStream() throws IOException; public void close() throws IOException; public long length() throws IOException; public void seek(long pos) throws IOException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TStandardFile.java0000644000000000000000000000337614303740367030135 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.RandomAccessFile; public class TStandardFile implements TSeekableFile { protected String path_ = null; protected RandomAccessFile inputFile_ = null; public TStandardFile(String path) throws IOException { path_ = path; inputFile_ = new RandomAccessFile(path_, "r"); } public InputStream getInputStream() throws IOException { return new FileInputStream(inputFile_.getFD()); } public OutputStream getOutputStream() throws IOException { return new FileOutputStream(path_); } public void close() throws IOException { if (inputFile_ != null) { inputFile_.close(); } } public long length() throws IOException { return inputFile_.length(); } public void seek(long pos) throws IOException { inputFile_.seek(pos); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TTransport.java0000644000000000000000000001513714303740367027567 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.Closeable; import java.nio.ByteBuffer; import org.apache.thrift.TConfiguration; /** * Generic class that encapsulates the I/O layer. This is basically a thin wrapper around the * combined functionality of Java input/output streams. */ public abstract class TTransport implements Closeable { /** * Queries whether the transport is open. * * @return True if the transport is open. */ public abstract boolean isOpen(); /** * Is there more data to be read? * * @return True if the remote side is still alive and feeding us */ public boolean peek() { return isOpen(); } /** * Opens the transport for reading/writing. * * @throws TTransportException if the transport could not be opened */ public abstract void open() throws TTransportException; /** Closes the transport. */ public abstract void close(); /** * Reads a sequence of bytes from this channel into the given buffer. An attempt is made to read * up to the number of bytes remaining in the buffer, that is, dst.remaining(), at the moment this * method is invoked. Upon return the buffer's position will move forward the number of bytes * read; its limit will not have changed. Subclasses are encouraged to provide a more efficient * implementation of this method. * * @param dst The buffer into which bytes are to be transferred * @return The number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream * @throws TTransportException if there was an error reading data */ public int read(ByteBuffer dst) throws TTransportException { byte[] arr = new byte[dst.remaining()]; int n = read(arr, 0, arr.length); dst.put(arr, 0, n); return n; } /** * Reads up to len bytes into buffer buf, starting at offset off. * * @param buf Array to read into * @param off Index to start reading at * @param len Maximum number of bytes to read * @return The number of bytes actually read * @throws TTransportException if there was an error reading data */ public abstract int read(byte[] buf, int off, int len) throws TTransportException; /** * Guarantees that all of len bytes are actually read off the transport. * * @param buf Array to read into * @param off Index to start reading at * @param len Maximum number of bytes to read * @return The number of bytes actually read, which must be equal to len * @throws TTransportException if there was an error reading data */ public int readAll(byte[] buf, int off, int len) throws TTransportException { int got = 0; int ret = 0; while (got < len) { ret = read(buf, off + got, len - got); if (ret <= 0) { throw new TTransportException( "Cannot read. Remote side has closed. Tried to read " + len + " bytes, but only got " + got + " bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)"); } got += ret; } return got; } /** * Writes the buffer to the output * * @param buf The output data buffer * @throws TTransportException if an error occurs writing data */ public void write(byte[] buf) throws TTransportException { write(buf, 0, buf.length); } /** * Writes up to len bytes from the buffer. * * @param buf The output data buffer * @param off The offset to start writing from * @param len The number of bytes to write * @throws TTransportException if there was an error writing data */ public abstract void write(byte[] buf, int off, int len) throws TTransportException; /** * Writes a sequence of bytes to the buffer. An attempt is made to write all remaining bytes in * the buffer, that is, src.remaining(), at the moment this method is invoked. Upon return the * buffer's position will updated; its limit will not have changed. Subclasses are encouraged to * provide a more efficient implementation of this method. * * @param src The buffer from which bytes are to be retrieved * @return The number of bytes written, possibly zero * @throws TTransportException if there was an error writing data */ public int write(ByteBuffer src) throws TTransportException { byte[] arr = new byte[src.remaining()]; src.get(arr); write(arr, 0, arr.length); return arr.length; } /** * Flush any pending data out of a transport buffer. * * @throws TTransportException if there was an error writing out data. */ public void flush() throws TTransportException {} /** * Access the protocol's underlying buffer directly. If this is not a buffered transport, return * null. * * @return protocol's Underlying buffer */ public byte[] getBuffer() { return null; } /** * Return the index within the underlying buffer that specifies the next spot that should be read * from. * * @return index within the underlying buffer that specifies the next spot that should be read * from */ public int getBufferPosition() { return 0; } /** * Get the number of bytes remaining in the underlying buffer. Returns -1 if this is a * non-buffered transport. * * @return the number of bytes remaining in the underlying buffer.
* Returns -1 if this is a non-buffered transport. */ public int getBytesRemainingInBuffer() { return -1; } /** * Consume len bytes from the underlying buffer. * * @param len the number of bytes to consume from the underlying buffer. */ public void consumeBuffer(int len) {} public abstract TConfiguration getConfiguration(); public abstract void updateKnownMessageSize(long size) throws TTransportException; public abstract void checkReadBytesAvailable(long numBytes) throws TTransportException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/AutoExpandingBuffer.java0000644000000000000000000000343414303740367031344 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.util.Arrays; /** * Helper class that wraps a byte[] so that it can expand and be reused. Users should call * resizeIfNecessary to make sure the buffer has suitable capacity, and then use the array as * needed. Note that the internal array will grow at a rate slightly faster than the requested * capacity with the (untested) objective of avoiding expensive buffer allocations and copies. */ public class AutoExpandingBuffer { private byte[] array; public AutoExpandingBuffer(int initialCapacity) { this.array = new byte[initialCapacity]; } public void resizeIfNecessary(int size) { final int currentCapacity = this.array.length; if (currentCapacity < size) { // Increase by a factor of 1.5x int growCapacity = currentCapacity + (currentCapacity >> 1); int newCapacity = Math.max(growCapacity, size); this.array = Arrays.copyOf(array, newCapacity); } } public byte[] array() { return this.array; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TMemoryBuffer.java0000644000000000000000000000705014303740367030170 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.nio.charset.Charset; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TConfiguration; /** Memory buffer-based implementation of the TTransport interface. */ public class TMemoryBuffer extends TEndpointTransport { /** * Create a TMemoryBuffer with an initial buffer size of size. The internal buffer will * grow as necessary to accommodate the size of the data being written to it. * * @param size the initial size of the buffer * @throws TTransportException on error initializing the underlying transport. */ public TMemoryBuffer(int size) throws TTransportException { super(new TConfiguration()); arr_ = new TByteArrayOutputStream(size); updateKnownMessageSize(size); } /** * Create a TMemoryBuffer with an initial buffer size of size. The internal buffer will * grow as necessary to accommodate the size of the data being written to it. * * @param config the configuration to use. * @param size the initial size of the buffer * @throws TTransportException on error initializing the underlying transport. */ public TMemoryBuffer(TConfiguration config, int size) throws TTransportException { super(config); arr_ = new TByteArrayOutputStream(size); updateKnownMessageSize(size); } @Override public boolean isOpen() { return true; } @Override public void open() { /* Do nothing */ } @Override public void close() { /* Do nothing */ } @Override public int read(byte[] buf, int off, int len) throws TTransportException { checkReadBytesAvailable(len); byte[] src = arr_.get(); int amtToRead = (len > arr_.len() - pos_ ? arr_.len() - pos_ : len); if (amtToRead > 0) { System.arraycopy(src, pos_, buf, off, amtToRead); pos_ += amtToRead; } return amtToRead; } @Override public void write(byte[] buf, int off, int len) { arr_.write(buf, off, len); } /** * Output the contents of the memory buffer as a String, using the supplied encoding * * @param charset the encoding to use * @return the contents of the memory buffer as a String */ public String toString(Charset charset) { return arr_.toString(charset); } public String inspect() { StringBuilder buf = new StringBuilder(); byte[] bytes = arr_.toByteArray(); for (int i = 0; i < bytes.length; i++) { buf.append(pos_ == i ? "==>" : "").append(Integer.toHexString(bytes[i] & 0xff)).append(" "); } return buf.toString(); } // The contents of the buffer private TByteArrayOutputStream arr_; // Position to read next byte from private int pos_; public int length() { return arr_.size(); } public byte[] getArray() { return arr_.get(); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TByteBuffer.java0000644000000000000000000000537614452237057027636 0ustar00rootroot00000000000000package org.apache.thrift.transport; import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import org.apache.thrift.TConfiguration; /** ByteBuffer-backed implementation of TTransport. */ public final class TByteBuffer extends TEndpointTransport { private final ByteBuffer byteBuffer; /** * Creates a new TByteBuffer wrapping a given NIO ByteBuffer and custom TConfiguration. * * @param configuration the custom TConfiguration. * @param byteBuffer the NIO ByteBuffer to wrap. * @throws TTransportException on error. */ public TByteBuffer(TConfiguration configuration, ByteBuffer byteBuffer) throws TTransportException { super(configuration); this.byteBuffer = byteBuffer; updateKnownMessageSize(byteBuffer.capacity()); } /** * Creates a new TByteBuffer wrapping a given NIO ByteBuffer. * * @param byteBuffer the NIO ByteBuffer to wrap. * @throws TTransportException on error. */ public TByteBuffer(ByteBuffer byteBuffer) throws TTransportException { this(new TConfiguration(), byteBuffer); } @Override public boolean isOpen() { return true; } @Override public void open() {} @Override public void close() {} @Override public int read(byte[] buf, int off, int len) throws TTransportException { // checkReadBytesAvailable(len); final int n = Math.min(byteBuffer.remaining(), len); if (n > 0) { try { byteBuffer.get(buf, off, n); } catch (BufferUnderflowException e) { throw new TTransportException("Unexpected end of input buffer", e); } } return n; } @Override public void write(byte[] buf, int off, int len) throws TTransportException { try { byteBuffer.put(buf, off, len); } catch (BufferOverflowException e) { throw new TTransportException("Not enough room in output buffer", e); } } /** * Gets the underlying NIO ByteBuffer. * * @return the underlying NIO ByteBuffer. */ public ByteBuffer getByteBuffer() { return byteBuffer; } /** * Convenience method to call clear() on the underlying NIO ByteBuffer. * * @return this instance. */ public TByteBuffer clear() { byteBuffer.clear(); return this; } /** * Convenience method to call flip() on the underlying NIO ByteBuffer. * * @return this instance. */ public TByteBuffer flip() { byteBuffer.flip(); return this; } /** * Convenience method to convert the underlying NIO ByteBuffer to a plain old byte array. * * @return the byte array backing the underlying NIO ByteBuffer. */ public byte[] toByteArray() { final byte[] data = new byte[byteBuffer.remaining()]; byteBuffer.slice().get(data); return data; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TTransportFactory.java0000644000000000000000000000254314303740367031114 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; /** * Factory class used to create wrapped instance of Transports. This is used primarily in servers, * which get Transports from a ServerTransport and then may want to mutate them (i.e. create a * BufferedTransport from the underlying base transport) */ public class TTransportFactory { /** * Return a wrapped instance of the base Transport. * * @param trans The base transport * @return Wrapped Transport */ public TTransport getTransport(TTransport trans) throws TTransportException { return trans; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TMemoryTransport.java0000644000000000000000000000514114303740367030752 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.nio.ByteBuffer; import org.apache.thrift.TByteArrayOutputStream; import org.apache.thrift.TConfiguration; /** In memory transport with separate buffers for input and output. */ public class TMemoryTransport extends TEndpointTransport { private final ByteBuffer inputBuffer; private final TByteArrayOutputStream outputBuffer; public TMemoryTransport(byte[] input) throws TTransportException { super(new TConfiguration()); inputBuffer = ByteBuffer.wrap(input); outputBuffer = new TByteArrayOutputStream(1024); updateKnownMessageSize(input.length); } public TMemoryTransport(TConfiguration config, byte[] input) throws TTransportException { super(config); inputBuffer = ByteBuffer.wrap(input); outputBuffer = new TByteArrayOutputStream(1024); updateKnownMessageSize(input.length); } @Override public boolean isOpen() { return true; } /** Opening on an in memory transport should have no effect. */ @Override public void open() { // Do nothing. } @Override public void close() { // Do nothing. } @Override public int read(byte[] buf, int off, int len) throws TTransportException { checkReadBytesAvailable(len); int remaining = inputBuffer.remaining(); if (remaining < len) { throw new TTransportException( TTransportException.END_OF_FILE, "There's only " + remaining + "bytes, but it asks for " + len); } inputBuffer.get(buf, off, len); return len; } @Override public void write(byte[] buf, int off, int len) throws TTransportException { outputBuffer.write(buf, off, len); } /** * Get all the bytes written by thrift output protocol. * * @return a byte array. */ public TByteArrayOutputStream getOutput() { return outputBuffer; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/transport/TSocket.java0000644000000000000000000001617014303740367027021 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import org.apache.thrift.TConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Socket implementation of the TTransport interface. To be commented soon! */ public class TSocket extends TIOStreamTransport { private static final Logger LOGGER = LoggerFactory.getLogger(TSocket.class.getName()); /** Wrapped Socket object */ private Socket socket_; /** Remote host */ private String host_; /** Remote port */ private int port_; /** Socket timeout - read timeout on the socket */ private int socketTimeout_; /** Connection timeout */ private int connectTimeout_; /** * Constructor that takes an already created socket. * * @param socket Already created socket object * @throws TTransportException if there is an error setting up the streams */ public TSocket(Socket socket) throws TTransportException { super(new TConfiguration()); socket_ = socket; try { socket_.setSoLinger(false, 0); socket_.setTcpNoDelay(true); socket_.setKeepAlive(true); } catch (SocketException sx) { LOGGER.warn("Could not configure socket.", sx); } if (isOpen()) { try { inputStream_ = new BufferedInputStream(socket_.getInputStream()); outputStream_ = new BufferedOutputStream(socket_.getOutputStream()); } catch (IOException iox) { close(); throw new TTransportException(TTransportException.NOT_OPEN, iox); } } } /** * Creates a new unconnected socket that will connect to the given host on the given port. * * @param config check config * @param host Remote host * @param port Remote port */ public TSocket(TConfiguration config, String host, int port) throws TTransportException { this(config, host, port, 0); } /** * Creates a new unconnected socket that will connect to the given host on the given port. * * @param host Remote host * @param port Remote port */ public TSocket(String host, int port) throws TTransportException { this(new TConfiguration(), host, port, 0); } /** * Creates a new unconnected socket that will connect to the given host on the given port. * * @param host Remote host * @param port Remote port * @param timeout Socket timeout and connection timeout */ public TSocket(String host, int port, int timeout) throws TTransportException { this(new TConfiguration(), host, port, timeout, timeout); } /** * Creates a new unconnected socket that will connect to the given host on the given port. * * @param config check config * @param host Remote host * @param port Remote port * @param timeout Socket timeout and connection timeout */ public TSocket(TConfiguration config, String host, int port, int timeout) throws TTransportException { this(config, host, port, timeout, timeout); } /** * Creates a new unconnected socket that will connect to the given host on the given port, with a * specific connection timeout and a specific socket timeout. * * @param config check config * @param host Remote host * @param port Remote port * @param socketTimeout Socket timeout * @param connectTimeout Connection timeout */ public TSocket( TConfiguration config, String host, int port, int socketTimeout, int connectTimeout) throws TTransportException { super(config); host_ = host; port_ = port; socketTimeout_ = socketTimeout; connectTimeout_ = connectTimeout; initSocket(); } /** Initializes the socket object */ private void initSocket() { socket_ = new Socket(); try { socket_.setSoLinger(false, 0); socket_.setTcpNoDelay(true); socket_.setKeepAlive(true); socket_.setSoTimeout(socketTimeout_); } catch (SocketException sx) { LOGGER.error("Could not configure socket.", sx); } } /** * Sets the socket timeout and connection timeout. * * @param timeout Milliseconds timeout */ public void setTimeout(int timeout) { this.setConnectTimeout(timeout); this.setSocketTimeout(timeout); } /** * Sets the time after which the connection attempt will time out * * @param timeout Milliseconds timeout */ public void setConnectTimeout(int timeout) { connectTimeout_ = timeout; } /** * Sets the socket timeout * * @param timeout Milliseconds timeout */ public void setSocketTimeout(int timeout) { socketTimeout_ = timeout; try { socket_.setSoTimeout(timeout); } catch (SocketException sx) { LOGGER.warn("Could not set socket timeout.", sx); } } /** Returns a reference to the underlying socket. */ public Socket getSocket() { if (socket_ == null) { initSocket(); } return socket_; } /** Checks whether the socket is connected. */ public boolean isOpen() { if (socket_ == null) { return false; } return socket_.isConnected(); } /** Connects the socket, creating a new socket object if necessary. */ public void open() throws TTransportException { if (isOpen()) { throw new TTransportException(TTransportException.ALREADY_OPEN, "Socket already connected."); } if (host_ == null || host_.length() == 0) { throw new TTransportException(TTransportException.NOT_OPEN, "Cannot open null host."); } if (port_ <= 0 || port_ > 65535) { throw new TTransportException(TTransportException.NOT_OPEN, "Invalid port " + port_); } if (socket_ == null) { initSocket(); } try { socket_.connect(new InetSocketAddress(host_, port_), connectTimeout_); inputStream_ = new BufferedInputStream(socket_.getInputStream()); outputStream_ = new BufferedOutputStream(socket_.getOutputStream()); } catch (IOException iox) { close(); throw new TTransportException(TTransportException.NOT_OPEN, iox); } } /** Closes the socket. */ public void close() { // Close the underlying streams super.close(); // Close the socket if (socket_ != null) { try { socket_.close(); } catch (IOException iox) { LOGGER.warn("Could not close socket.", iox); } socket_ = null; } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/THttpClientResponseHandler.java0000644000000000000000000000471614452237057030635 0ustar00rootroot00000000000000package org.apache.thrift; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.hc.core5.http.ClassicHttpResponse; import org.apache.hc.core5.http.HttpEntity; import org.apache.hc.core5.http.HttpException; import org.apache.hc.core5.http.HttpStatus; import org.apache.hc.core5.http.io.HttpClientResponseHandler; public class THttpClientResponseHandler implements HttpClientResponseHandler { @Override public InputStream handleResponse(ClassicHttpResponse response) throws HttpException, IOException { try (InputStream is = response.getEntity().getContent()) { int responseCode = response.getCode(); if (responseCode != HttpStatus.SC_OK) { throw new IOException("HTTP Response code: " + responseCode); } byte[] readByteArray = readIntoByteArray(is); try { // Indicate we're done with the content. consume(response.getEntity()); } catch (IOException ioe) { // We ignore this exception, it might only mean the server has no // keep-alive capability. } return new ByteArrayInputStream(readByteArray); } catch (IOException ioe) { throw ioe; } } /** * Read the responses into a byte array so we can release the connection early. This implies that * the whole content will have to be read in memory, and that momentarily we might use up twice * the memory (while the thrift struct is being read up the chain). Proceeding differently might * lead to exhaustion of connections and thus to app failure. * * @param is input stream * @return read bytes * @throws IOException when exception during read */ private static byte[] readIntoByteArray(InputStream is) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int len; do { len = is.read(buf); if (len > 0) { baos.write(buf, 0, len); } } while (-1 != len); return baos.toByteArray(); } /** * copy from org.apache.http.util.EntityUtils#consume. Android has it's own httpcore that doesn't * have a consume. */ private static void consume(final HttpEntity entity) throws IOException { if (entity == null) { return; } if (entity.isStreaming()) { InputStream instream = entity.getContent(); if (instream != null) { instream.close(); } } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TAsyncProcessor.java0000644000000000000000000000234514370300523026477 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer; public interface TAsyncProcessor { /** * Process a single frame. * *

Note: Implementations must call fb.responseReady() once processing is complete * * @param fb the frame buffer to process. * @throws TException if the frame cannot be processed */ void process(final AsyncFrameBuffer fb) throws TException; } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TBaseAsyncProcessor.java0000644000000000000000000000717214303740367027307 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.util.Collections; import java.util.Map; import org.apache.thrift.async.AsyncMethodCallback; import org.apache.thrift.protocol.*; import org.apache.thrift.server.AbstractNonblockingServer.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TBaseAsyncProcessor implements TAsyncProcessor, TProcessor { protected final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); final I iface; final Map> processMap; public TBaseAsyncProcessor( I iface, Map> processMap) { this.iface = iface; this.processMap = processMap; } public Map> getProcessMapView() { return Collections.unmodifiableMap(processMap); } public void process(final AsyncFrameBuffer fb) throws TException { final TProtocol in = fb.getInputProtocol(); final TProtocol out = fb.getOutputProtocol(); // Find processing function final TMessage msg = in.readMessageBegin(); AsyncProcessFunction fn = processMap.get(msg.name); if (fn == null) { TProtocolUtil.skip(in, TType.STRUCT); in.readMessageEnd(); TApplicationException x = new TApplicationException( TApplicationException.UNKNOWN_METHOD, "Invalid method name: '" + msg.name + "'"); LOGGER.debug("Invalid method name", x); // this means it is a two-way request, so we can send a reply if (msg.type == TMessageType.CALL) { out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); x.write(out); out.writeMessageEnd(); out.getTransport().flush(); } fb.responseReady(); return; } // Get Args TBase args = fn.getEmptyArgsInstance(); try { args.read(in); } catch (TProtocolException e) { in.readMessageEnd(); TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, e.getMessage()); LOGGER.debug("Could not retrieve function arguments", x); if (!fn.isOneway()) { out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); x.write(out); out.writeMessageEnd(); out.getTransport().flush(); } fb.responseReady(); return; } in.readMessageEnd(); if (fn.isOneway()) { fb.responseReady(); } // start off processing function AsyncMethodCallback resultHandler = fn.getResultHandler(fb, msg.seqid); try { fn.start(iface, args, resultHandler); } catch (Exception e) { LOGGER.debug("Exception handling function", e); resultHandler.onError(e); } return; } @Override public void process(TProtocol in, TProtocol out) throws TException {} } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TProcessorFactory.java0000644000000000000000000000240614303740367027041 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.transport.TTransport; /** The default processor factory just returns a singleton instance. */ public class TProcessorFactory { private final TProcessor processor_; public TProcessorFactory(TProcessor processor) { processor_ = processor; } public TProcessor getProcessor(TTransport trans) { return processor_; } public boolean isAsyncProcessor() { return processor_ instanceof TAsyncProcessor; } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TEnumHelper.java0000644000000000000000000000333614370300523025567 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.lang.reflect.Method; /** Utility class with static methods for interacting with TEnum */ public class TEnumHelper { /* no instantiation */ private TEnumHelper() {} /** * Given a TEnum class and integer value, this method will return the associated constant from the * given TEnum class. This method MUST be modified should the name of the 'findByValue' method * change. * * @param enumClass TEnum from which to return a matching constant. * @param value Value for which to return the constant. * @return The constant in 'enumClass' whose value is 'value' or null if something went wrong. */ public static TEnum getByValue(Class enumClass, int value) { try { Method method = enumClass.getMethod("findByValue", int.class); return (TEnum) method.invoke(null, value); } catch (ReflectiveOperationException nsme) { return null; } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/EncodingUtils.java0000644000000000000000000001177614303740367026167 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** Utility methods for use when encoding/decoding raw data as byte arrays. */ public class EncodingUtils { /** * Encode integer as a series of 4 bytes into buf starting at position 0 * within that buffer. * * @param integer The integer to encode. * @param buf The buffer to write to. */ public static final void encodeBigEndian(final int integer, final byte[] buf) { encodeBigEndian(integer, buf, 0); } /** * Encode integer as a series of 4 bytes into buf starting at position * offset. * * @param integer The integer to encode. * @param buf The buffer to write to. * @param offset The offset within buf to start the encoding. */ public static final void encodeBigEndian(final int integer, final byte[] buf, int offset) { buf[offset] = (byte) (0xff & (integer >> 24)); buf[offset + 1] = (byte) (0xff & (integer >> 16)); buf[offset + 2] = (byte) (0xff & (integer >> 8)); buf[offset + 3] = (byte) (0xff & (integer)); } /** * Decode a series of 4 bytes from buf, starting at position 0, and interpret them as * an integer. * * @param buf The buffer to read from. * @return An integer, as read from the buffer. */ public static final int decodeBigEndian(final byte[] buf) { return decodeBigEndian(buf, 0); } /** * Decode a series of 4 bytes from buf, start at offset, and interpret * them as an integer. * * @param buf The buffer to read from. * @param offset The offset with buf to start the decoding. * @return An integer, as read from the buffer. */ public static final int decodeBigEndian(final byte[] buf, int offset) { return ((buf[offset] & 0xff) << 24) | ((buf[offset + 1] & 0xff) << 16) | ((buf[offset + 2] & 0xff) << 8) | ((buf[offset + 3] & 0xff)); } /** * Bitfield utilities. Returns true if the bit at position is set in v. * * @param v the value whose bit is to be checked. * @param position the 0 based bit number indicating the bit to check. * @return true if the bit at position is set in v. */ public static final boolean testBit(byte v, int position) { return testBit((int) v, position); } public static final boolean testBit(short v, int position) { return testBit((int) v, position); } public static final boolean testBit(int v, int position) { return (v & (1 << position)) != 0; } public static final boolean testBit(long v, int position) { return (v & (1L << position)) != 0L; } /** * Returns v, with the bit at position set to zero. * * @param v the value whose bit is to be cleared. * @param position the 0 based bit number indicating the bit to clear. * @return v, with the bit at position set to zero. */ public static final byte clearBit(byte v, int position) { return (byte) clearBit((int) v, position); } public static final short clearBit(short v, int position) { return (short) clearBit((int) v, position); } public static final int clearBit(int v, int position) { return v & ~(1 << position); } public static final long clearBit(long v, int position) { return v & ~(1L << position); } /** * Returns v, with the bit at position set to 1 or 0 depending on value. * * @param v the value whose bit is to be set. * @param position the 0 based bit number indicating the bit to set. * @param value if true, the given bit is set to 1; otherwise it is set to 0. * @return v, with the bit at position set to 0 (if value is false) or 1 (if value is true). */ public static final byte setBit(byte v, int position, boolean value) { return (byte) setBit((int) v, position, value); } public static final short setBit(short v, int position, boolean value) { return (short) setBit((int) v, position, value); } public static final int setBit(int v, int position, boolean value) { if (value) return v | (1 << position); else return clearBit(v, position); } public static final long setBit(long v, int position, boolean value) { if (value) return v | (1L << position); else return clearBit(v, position); } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TNonblockingMultiFetchClient.java0000644000000000000000000003211314370300523031105 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class uses a single thread to set up non-blocking sockets to a set of remote servers * (hostname and port pairs), and sends a same request to all these servers. It then fetches * responses from servers. * *

Parameters: int maxRecvBufBytesPerServer - an upper limit for receive buffer size per server * (in byte). If a response from a server exceeds this limit, the client will not allocate memory or * read response data for it. * *

int fetchTimeoutSeconds - time limit for fetching responses from all servers (in second). * After the timeout, the fetch job is stopped and available responses are returned. * *

ByteBuffer requestBuf - request message that is sent to all servers. * *

Output: Responses are stored in an array of ByteBuffers. Index of elements in this array * corresponds to index of servers in the server list. Content in a ByteBuffer may be in one of the * following forms: 1. First 4 bytes form an integer indicating length of following data, then * followed by the data. 2. First 4 bytes form an integer indicating length of following data, then * followed by nothing - this happens when the response data size exceeds maxRecvBufBytesPerServer, * and the client will not read any response data. 3. No data in the ByteBuffer - this happens when * the server does not return any response within fetchTimeoutSeconds. * *

In some special cases (no servers are given, fetchTimeoutSeconds less than or equal to 0, * requestBuf is null), the return is null. * *

Note: It assumes all remote servers are TNonblockingServers and use TFramedTransport. */ public class TNonblockingMultiFetchClient { private static final Logger LOGGER = LoggerFactory.getLogger(TNonblockingMultiFetchClient.class); // if the size of the response msg exceeds this limit (in byte), we will // not read the msg private final int maxRecvBufBytesPerServer; // time limit for fetching data from all servers (in second) private final int fetchTimeoutSeconds; // store request that will be sent to servers private final ByteBuffer requestBuf; private ByteBuffer requestBufDuplication; // a list of remote servers private final List servers; // store fetch results private final TNonblockingMultiFetchStats stats; private ByteBuffer[] recvBuf; public TNonblockingMultiFetchClient( int maxRecvBufBytesPerServer, int fetchTimeoutSeconds, ByteBuffer requestBuf, List servers) { this.maxRecvBufBytesPerServer = maxRecvBufBytesPerServer; this.fetchTimeoutSeconds = fetchTimeoutSeconds; this.requestBuf = requestBuf; this.servers = servers; stats = new TNonblockingMultiFetchStats(); recvBuf = null; } public synchronized int getMaxRecvBufBytesPerServer() { return maxRecvBufBytesPerServer; } public synchronized int getFetchTimeoutSeconds() { return fetchTimeoutSeconds; } /** * Returns a copy of requestBuf, so that requestBuf will not be modified by others. * * @return a copy of requestBuf. */ public synchronized ByteBuffer getRequestBuf() { if (requestBuf == null) { return null; } else { if (requestBufDuplication == null) { requestBufDuplication = requestBuf.duplicate(); } return requestBufDuplication; } } public synchronized List getServerList() { if (servers == null) { return null; } return Collections.unmodifiableList(servers); } public synchronized TNonblockingMultiFetchStats getFetchStats() { return stats; } /** * Main entry function for fetching from servers. * * @return The fetched data. */ public synchronized ByteBuffer[] fetch() { // clear previous results recvBuf = null; stats.clear(); if (servers == null || servers.size() == 0 || requestBuf == null || fetchTimeoutSeconds <= 0) { return recvBuf; } ExecutorService executor = Executors.newSingleThreadExecutor(); MultiFetch multiFetch = new MultiFetch(); FutureTask task = new FutureTask(multiFetch, null); executor.execute(task); try { task.get(fetchTimeoutSeconds, TimeUnit.SECONDS); } catch (InterruptedException ie) { // attempt to cancel execution of the task. task.cancel(true); LOGGER.error("Interrupted during fetch", ie); } catch (ExecutionException ee) { // attempt to cancel execution of the task. task.cancel(true); LOGGER.error("Exception during fetch", ee); } catch (TimeoutException te) { // attempt to cancel execution of the task. task.cancel(true); LOGGER.error("Timeout for fetch", te); } executor.shutdownNow(); multiFetch.close(); return recvBuf; } /** * Private class that does real fetch job. Users are not allowed to directly use this class, as * its run() function may run forever. */ private class MultiFetch implements Runnable { private Selector selector; /** * main entry function for fetching. * *

Server responses are stored in TNonblocingMultiFetchClient.recvBuf, and fetch statistics * is in TNonblockingMultiFetchClient.stats. * *

Sanity check for parameters has been done in TNonblockingMultiFetchClient before calling * this function. */ public void run() { long t1 = System.currentTimeMillis(); int numTotalServers = servers.size(); stats.setNumTotalServers(numTotalServers); // buffer for receiving response from servers recvBuf = new ByteBuffer[numTotalServers]; // buffer for sending request ByteBuffer[] sendBuf = new ByteBuffer[numTotalServers]; long[] numBytesRead = new long[numTotalServers]; int[] frameSize = new int[numTotalServers]; boolean[] hasReadFrameSize = new boolean[numTotalServers]; try { selector = Selector.open(); } catch (IOException ioe) { LOGGER.error("Selector opens error", ioe); return; } for (int i = 0; i < numTotalServers; i++) { // create buffer to send request to server. sendBuf[i] = requestBuf.duplicate(); // create buffer to read response's frame size from server recvBuf[i] = ByteBuffer.allocate(4); stats.incTotalRecvBufBytes(4); InetSocketAddress server = servers.get(i); SocketChannel s = null; SelectionKey key = null; try { s = SocketChannel.open(); s.configureBlocking(false); // now this method is non-blocking s.connect(server); key = s.register(selector, s.validOps()); // attach index of the key key.attach(i); } catch (Exception e) { stats.incNumConnectErrorServers(); LOGGER.error("Set up socket to server {} error", server, e); // free resource if (s != null) { try { s.close(); } catch (Exception ex) { LOGGER.error("failed to free up socket", ex); } } if (key != null) { key.cancel(); } } } // wait for events while (stats.getNumReadCompletedServers() + stats.getNumConnectErrorServers() < stats.getNumTotalServers()) { // if the thread is interrupted (e.g., task is cancelled) if (Thread.currentThread().isInterrupted()) { return; } try { selector.select(); } catch (Exception e) { LOGGER.error("Selector selects error", e); continue; } Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey selKey = it.next(); it.remove(); // get previously attached index int index = (Integer) selKey.attachment(); if (selKey.isValid() && selKey.isConnectable()) { // if this socket throws an exception (e.g., connection refused), // print error msg and skip it. try { SocketChannel sChannel = (SocketChannel) selKey.channel(); sChannel.finishConnect(); } catch (Exception e) { stats.incNumConnectErrorServers(); LOGGER.error("Socket {} connects to server {} error", index, servers.get(index), e); } } if (selKey.isValid() && selKey.isWritable() && sendBuf[index].hasRemaining()) { // if this socket throws an exception, print error msg and // skip it. try { SocketChannel sChannel = (SocketChannel) selKey.channel(); sChannel.write(sendBuf[index]); } catch (Exception e) { LOGGER.error("Socket {} writes to server {} error", index, servers.get(index), e); } } if (selKey.isValid() && selKey.isReadable()) { // if this socket throws an exception, print error msg and // skip it. try { SocketChannel sChannel = (SocketChannel) selKey.channel(); int bytesRead = sChannel.read(recvBuf[index]); if (bytesRead > 0) { numBytesRead[index] += bytesRead; if (!hasReadFrameSize[index] && recvBuf[index].remaining() == 0) { // if the frame size has been read completely, then prepare // to read the actual frame. frameSize[index] = recvBuf[index].getInt(0); if (frameSize[index] <= 0) { stats.incNumInvalidFrameSize(); LOGGER.error( "Read an invalid frame size {} from {}. Does the server use TFramedTransport?", frameSize[index], servers.get(index)); sChannel.close(); continue; } if (frameSize[index] + 4 > stats.getMaxResponseBytes()) { stats.setMaxResponseBytes(frameSize[index] + 4); } if (frameSize[index] + 4 > maxRecvBufBytesPerServer) { stats.incNumOverflowedRecvBuf(); LOGGER.error( "Read frame size {} from {}, total buffer size would exceed limit {}", frameSize[index], servers.get(index), maxRecvBufBytesPerServer); sChannel.close(); continue; } // reallocate buffer for actual frame data recvBuf[index] = ByteBuffer.allocate(frameSize[index] + 4); recvBuf[index].putInt(frameSize[index]); stats.incTotalRecvBufBytes(frameSize[index]); hasReadFrameSize[index] = true; } if (hasReadFrameSize[index] && numBytesRead[index] >= frameSize[index] + 4) { // has read all data sChannel.close(); stats.incNumReadCompletedServers(); long t2 = System.currentTimeMillis(); stats.setReadTime(t2 - t1); } } } catch (Exception e) { LOGGER.error("Socket {} reads from server {} error", index, servers.get(index), e); } } } } } /** dispose any resource allocated */ public void close() { try { if (selector.isOpen()) { for (SelectionKey selKey : selector.keys()) { SocketChannel sChannel = (SocketChannel) selKey.channel(); sChannel.close(); } selector.close(); } } catch (IOException e) { LOGGER.error("Free resource error", e); } } } } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TServiceClientFactory.java0000644000000000000000000000337514370300523027615 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import org.apache.thrift.protocol.TProtocol; /** * A TServiceClientFactory provides a general way to get a TServiceClient connected to a remote * TService via a protocol. * * @param the type of TServiceClient to get. */ public interface TServiceClientFactory { /** * Get a brand-new T using prot as both the input and output protocol. * * @param prot The protocol to use for getting T. * @return A brand-new T using prot as both the input and output protocol. */ T getClient(TProtocol prot); /** * Get a brand new T using the specified input and output protocols. The input and output * protocols may be the same instance. * * @param iprot The input protocol to use for getting T. * @param oprot The output protocol to use for getting T. * @return a brand new T using the specified input and output protocols */ T getClient(TProtocol iprot, TProtocol oprot); } thrift-0.19.0/lib/java/src/main/java/org/apache/thrift/TFieldRequirementType.java0000644000000000000000000000211314370300523027621 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; /** Requirement type constants. */ public final class TFieldRequirementType { /* no instantiation */ private TFieldRequirementType() {} public static final byte REQUIRED = 1; public static final byte OPTIONAL = 2; public static final byte DEFAULT = 3; } thrift-0.19.0/lib/java/src/test/0000777000000000000000000000000014303472263016344 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/resources/0000777000000000000000000000000014452237057020363 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/resources/JavaOptionTypeJdk8Test.thrift0000644000000000000000000000244314303740367026077 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace java thrift.test.optiontypejdk8 struct Person { 1: required i64 id; 2: required string name; 3: optional i64 age; 4: optional string phone; 5: optional list addresses; 6: optional map pets; } enum PetType { Cat = 1 Dog = 2 Bunny = 3 } struct Pet { 1: required string name; 2: optional PetType type; } thrift-0.19.0/lib/java/src/test/resources/log4j.properties0000644000000000000000000000046414452237057023520 0ustar00rootroot00000000000000# log4j configuration used during build and unit tests log4j.rootLogger=warn,stdout log4j.threshold=ALL log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ISO8601} %-5p %c{2} (%F:%M(%L)) - %m%n thrift-0.19.0/lib/java/src/test/resources/JavaDefinitionOrderB.thrift0000644000000000000000000000314214452237057025571 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Define Child, then Parent. Parent is a forward declaration and was problematic for our Java compiler before // fixing THRIFT-4086: Java compiler generates different meta data depending on order of structures in file struct Child { 1: required string Name 2: required Age Age 3: required Parent Parent1 4: required MyParent Parent2 5: required Parents GrandParents 6: required MyEnum MyEnum 7: required MyEnumV2 MyEnumV2 8: required MyEnums MyEnums 9: required MyMapping MyMapping 10: required MyBinary MyBinary } typedef i8 Age typedef Parent MyParent typedef list Parents typedef MyEnum MyEnumV2 typedef set MyEnums typedef map MyMapping typedef binary MyBinary struct Parent { 1: required string Name } enum MyEnum { FOO = 1 BAR = 2 } thrift-0.19.0/lib/java/src/test/resources/JavaBinaryDefault.thrift0000644000000000000000000000163614303740367025140 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test struct StringAndBinary { 1: optional string strval = "" 2: optional binary binval = "" } thrift-0.19.0/lib/java/src/test/resources/JavaTypes.thrift0000644000000000000000000000357014370300523023500 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test struct Integer { 1: i32 val } struct String { 1: string val } struct Binary { 1: binary val } struct Boolean { 1: bool val } struct Double { 1: double val } struct Long { 1: i64 val } struct Byte { 1: byte val } struct Float { 1: double val } struct Uuid { 1: uuid val } struct List { 1: list vals } struct ArrayList { 1: list vals } struct SortedMap { 1: map vals } struct TreeMap { 1: map vals } struct HashMap { 1: map vals } struct Map { 1: map vals } struct Object { 1: Integer integer, 2: String str, 3: Boolean boolean_field, 4: Double dbl, 5: Byte bite, 6: map intmap, 7: Map somemap, } exception Exception { 1: string msg } service AsyncNonblockingService { Object mymethod( 1: Integer integer, 2: String str, 3: Boolean boolean_field, 4: Double dbl, 5: Byte bite, 6: map intmap, 7: Map somemap, ) throws (1:Exception ex); } struct SafeBytes { 1: binary bytes; } thrift-0.19.0/lib/java/src/test/resources/JavaDefinitionOrderA.thrift0000644000000000000000000000267714452237057025604 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Define Parent, then Child. No forward declarations. struct Parent { 1: required string Name } typedef Parent MyParent typedef list Parents enum MyEnum { FOO = 1 BAR = 2 } typedef i8 Age typedef MyEnum MyEnumV2 typedef set MyEnums typedef map MyMapping typedef binary MyBinary struct Child { 1: required string Name 2: required Age Age 3: required Parent Parent1 4: required MyParent Parent2 5: required Parents GrandParents 6: required MyEnum MyEnum 7: required MyEnumV2 MyEnumV2 8: required MyEnums MyEnums 9: required MyMapping MyMapping 10: required MyBinary MyBinary } thrift-0.19.0/lib/java/src/test/resources/JavaAnnotationTest.thrift0000644000000000000000000000233614303740367025357 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test.annotations struct OneOfEachBeansWithAnnotations { 1: bool boolean_field, 2: byte a_bite (compression = "false"), 3: i16 integer16 (must_be_postive = "true"), 4: i32 integer32, 5: i64 integer64, 6: double double_precision (nan_inf_allowed = "false"), 7: string some_characters, 8: binary base64, 9: list byte_list (non_empty = "true"), 10: list i16_list, 11: list i64_list } thrift-0.19.0/lib/java/src/test/resources/JavaBeansTest.thrift0000644000000000000000000000221614303740367024272 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java thrift.test struct OneOfEachBeans { 1: bool boolean_field, 2: byte a_bite, 3: i16 integer16, 4: i32 integer32, 5: i64 integer64, 6: double double_precision, 7: string some_characters, 8: binary base64, 9: list byte_list, 10: list i16_list, 11: list i64_list } service Service { i64 mymethod(i64 blah); }thrift-0.19.0/lib/java/src/test/resources/JavaDeepCopyTest.thrift0000644000000000000000000000233614370300523024743 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ include "JavaTypes.thrift" namespace java thrift.test struct DeepCopyFoo { 1: optional list l, 2: optional set s, 3: optional map m, 4: optional list li, 5: optional set si, 6: optional map mi, 7: optional DeepCopyBar bar, } struct DeepCopyBar { 1: optional string a, 2: optional i32 b, 3: optional bool c, } thrift-0.19.0/lib/java/src/test/java/0000777000000000000000000000000014303472263017265 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/0000777000000000000000000000000014303472263020054 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/0000777000000000000000000000000014303472263021275 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/0000777000000000000000000000000014452237057022602 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestEnumContainers.java0000644000000000000000000000636014303740367027236 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import org.junit.jupiter.api.Test; import thrift.test.enumcontainers.EnumContainersTestConstants; import thrift.test.enumcontainers.GodBean; import thrift.test.enumcontainers.GreekGodGoddess; public class TestEnumContainers { @Test public void testEnumContainers() throws Exception { final GodBean b1 = new GodBean(); b1.addToGoddess(GreekGodGoddess.HERA); b1.getGoddess().add(GreekGodGoddess.APHRODITE); b1.putToPower(GreekGodGoddess.ZEUS, 1000); b1.getPower().put(GreekGodGoddess.HERA, 333); b1.putToByAlias("Mr. Z", GreekGodGoddess.ZEUS); b1.addToImages("Baths of Aphrodite 01.jpeg"); final GodBean b2 = new GodBean(b1); final GodBean b3 = new GodBean(); { final TSerializer serializer = new TSerializer(); final TDeserializer deserializer = new TDeserializer(); final byte[] bytes = serializer.serialize(b1); deserializer.deserialize(b3, bytes); } assertNotSame(b1.getGoddess(), b2.getGoddess()); assertNotSame(b1.getPower(), b2.getPower()); assertNotSame(b1.getGoddess(), b3.getGoddess()); assertNotSame(b1.getPower(), b3.getPower()); for (GodBean each : new GodBean[] {b1, b2, b3}) { assertTrue(each.getGoddess().contains(GreekGodGoddess.HERA)); assertFalse(each.getGoddess().contains(GreekGodGoddess.POSEIDON)); assertTrue(each.getGoddess() instanceof EnumSet); assertEquals(Integer.valueOf(1000), each.getPower().get(GreekGodGoddess.ZEUS)); assertEquals(Integer.valueOf(333), each.getPower().get(GreekGodGoddess.HERA)); assertTrue(each.getPower() instanceof EnumMap); assertTrue(each.getByAlias() instanceof HashMap); assertTrue(each.getImages() instanceof HashSet); } } @Test public void testEnumConstants() { assertEquals( "lightning bolt", EnumContainersTestConstants.ATTRIBUTES.get(GreekGodGoddess.ZEUS)); assertTrue(EnumContainersTestConstants.ATTRIBUTES instanceof EnumMap); assertTrue(EnumContainersTestConstants.BEAUTY.contains(GreekGodGoddess.APHRODITE)); assertTrue(EnumContainersTestConstants.BEAUTY instanceof EnumSet); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestAnnotationMetadata.java0000644000000000000000000000471414303740367030060 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.thrift.meta_data.FieldMetaData; import org.junit.jupiter.api.Test; import thrift.test.OneOfEachBeans; import thrift.test.annotations.OneOfEachBeansWithAnnotations; public class TestAnnotationMetadata { @Test public void testWithoutParamShouldGenerateEmpty() { Map structMetaDataMap = FieldMetaData.getStructMetaDataMap(OneOfEachBeans.class); { Map metadata = structMetaDataMap.get(OneOfEachBeans._Fields.I16_LIST).getFieldAnnotations(); assertEquals(Collections.emptyMap(), metadata); } { Map metadata = structMetaDataMap.get(OneOfEachBeans._Fields.A_BITE).getFieldAnnotations(); assertEquals(Collections.emptyMap(), metadata); } } @Test public void testGeneratedAnnotations() { Map structMetaDataMap = FieldMetaData.getStructMetaDataMap(OneOfEachBeansWithAnnotations.class); { Map metadata = structMetaDataMap .get(OneOfEachBeansWithAnnotations._Fields.I16_LIST) .getFieldAnnotations(); assertEquals(Collections.emptyMap(), metadata); } { Map metadata = structMetaDataMap.get(OneOfEachBeansWithAnnotations._Fields.A_BITE).getFieldAnnotations(); Map expected = new HashMap<>(); expected.put("compression", "false"); assertEquals(expected, metadata); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestOptionalsWithJdk8.java0000644000000000000000000000507514303740367027633 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import thrift.test.optiontypejdk8.Person; // Tests and documents behavior for the JDK8 "Option" type public class TestOptionalsWithJdk8 { @Test public void testConstruction() { Person person = new Person(1L, "name"); assertFalse(person.getAge().isPresent()); assertFalse(person.isSetAge()); assertFalse(person.getPhone().isPresent()); assertFalse(person.isSetPhone()); assertEquals(1L, person.getId()); assertTrue(person.isSetId()); assertEquals("name", person.getName()); assertTrue(person.isSetName()); assertFalse(person.getAddresses().isPresent()); assertEquals(Integer.valueOf(0), person.getAddressesSize().orElse(0)); assertFalse(person.getPets().isPresent()); assertEquals(Integer.valueOf(0), person.getPetsSize().orElse(0)); } @Test public void testEmpty() { Person person = new Person(); person.setPhone("phone"); assertFalse(person.getAge().isPresent()); assertFalse(person.isSetAge()); assertTrue(person.getPhone().isPresent()); assertEquals("phone", person.getPhone().get()); assertTrue(person.isSetPhone()); assertEquals(0L, person.getId()); assertFalse(person.isSetId()); assertNull(person.getName()); assertFalse(person.isSetName()); assertFalse(person.getAddresses().isPresent()); assertEquals(Integer.valueOf(0), person.getAddressesSize().orElse(0)); assertFalse(person.getPets().isPresent()); assertEquals(Integer.valueOf(0), person.getPetsSize().orElse(0)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestTBaseHelper.java0000644000000000000000000001457414303740367026450 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.junit.jupiter.api.Test; public class TestTBaseHelper { @Test public void testByteArrayComparison() { assertTrue(TBaseHelper.compareTo(new byte[] {'a', 'b'}, new byte[] {'a', 'c'}) < 0); } @Test public void testSets() { Set a = new HashSet<>(); Set b = new HashSet<>(); assertEquals(0, TBaseHelper.compareTo(a, b)); a.add("test"); assertTrue(TBaseHelper.compareTo(a, b) > 0); b.add("test"); assertEquals(0, TBaseHelper.compareTo(a, b)); b.add("aardvark"); assertTrue(TBaseHelper.compareTo(a, b) < 0); a.add("test2"); assertTrue(TBaseHelper.compareTo(a, b) > 0); } @Test public void testNestedStructures() { Set> a = new HashSet<>(); Set> b = new HashSet<>(); a.add(Arrays.asList("a", "b")); b.add(Arrays.asList("a", "b", "c")); a.add(Arrays.asList("a", "b")); b.add(Arrays.asList("a", "b", "c")); assertTrue(TBaseHelper.compareTo(a, b) < 0); } @Test public void testMapsInSets() { Set> a = new HashSet<>(); Set> b = new HashSet<>(); assertEquals(0, TBaseHelper.compareTo(a, b)); Map innerA = new HashMap<>(); Map innerB = new HashMap<>(); a.add(innerA); b.add(innerB); innerA.put("a", 1L); innerB.put("a", 2L); assertTrue(TBaseHelper.compareTo(a, b) < 0); } @Test public void testByteArraysInMaps() { Map a = new HashMap<>(); Map b = new HashMap<>(); assertEquals(0, TBaseHelper.compareTo(a, b)); a.put(new byte[] {'a', 'b'}, 1000L); b.put(new byte[] {'a', 'b'}, 1000L); a.put(new byte[] {'a', 'b', 'd'}, 1000L); b.put(new byte[] {'a', 'b', 'a'}, 1000L); assertTrue(TBaseHelper.compareTo(a, b) > 0); } @Test public void testMapsWithNulls() { Map a = new HashMap<>(); Map b = new HashMap<>(); a.put("a", null); a.put("b", null); b.put("a", null); b.put("b", null); assertEquals(0, TBaseHelper.compareTo(a, b)); } @Test public void testMapKeyComparison() { Map a = new HashMap<>(); Map b = new HashMap<>(); a.put("a", "a"); b.put("b", "a"); assertTrue(TBaseHelper.compareTo(a, b) < 0); } @Test public void testMapValueComparison() { Map a = new HashMap<>(); Map b = new HashMap<>(); a.put("a", "b"); b.put("a", "a"); assertTrue(TBaseHelper.compareTo(a, b) > 0); } @Test public void testByteArraysInSets() { Set a = new HashSet<>(); Set b = new HashSet<>(); if (TBaseHelper.compareTo(a, b) != 0) throw new RuntimeException("Set compare failed:" + a + " vs. " + b); a.add(new byte[] {'a', 'b'}); b.add(new byte[] {'a', 'b'}); a.add(new byte[] {'a', 'b', 'd'}); b.add(new byte[] {'a', 'b', 'a'}); assertTrue(TBaseHelper.compareTo(a, b) > 0); } @Test public void testByteBufferToByteArray() throws Exception { byte[] b1 = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; byte[] b2 = TBaseHelper.byteBufferToByteArray(ByteBuffer.wrap(b1)); assertEquals(b1, b2, "b1 and b2 should be the exact same array (identity) due to fast path"); byte[] b3 = TBaseHelper.byteBufferToByteArray(ByteBuffer.wrap(b1, 1, 3)); assertEquals(3, b3.length); assertEquals(ByteBuffer.wrap(b1, 1, 3), ByteBuffer.wrap(b3)); } @Test public void testRightSize() throws Exception { assertNull(TBaseHelper.rightSize(null)); } @Test public void testByteBufferToString() { byte[] array = new byte[] {1, 2, 3}; ByteBuffer bb = ByteBuffer.wrap(array, 1, 2); StringBuilder sb = new StringBuilder(); TBaseHelper.toString(bb, sb); assertEquals("02 03", sb.toString()); bb = ByteBuffer.wrap(array, 0, array.length); bb.position(1); bb = bb.slice(); assertEquals(1, bb.arrayOffset()); assertEquals(0, bb.position()); assertEquals(2, bb.limit()); sb = new StringBuilder(); TBaseHelper.toString(bb, sb); assertEquals("02 03", sb.toString()); } @Test public void testCopyBinaryWithByteBuffer() throws Exception { byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5}; ByteBuffer b = ByteBuffer.wrap(bytes); ByteBuffer bCopy = TBaseHelper.copyBinary(b); assertEquals(b, bCopy); assertEquals(0, b.position()); b = ByteBuffer.allocateDirect(6); b.put(bytes); b.position(0); bCopy = TBaseHelper.copyBinary(b); assertEquals(6, b.remaining()); assertEquals(0, b.position()); assertEquals(b, bCopy); b.mark(); b.get(); bCopy = TBaseHelper.copyBinary(b); assertEquals(ByteBuffer.wrap(bytes, 1, 5), bCopy); assertEquals(1, b.position()); b.reset(); assertEquals(0, b.position()); assertNull(TBaseHelper.copyBinary((ByteBuffer) null)); } @Test public void testCopyBinaryWithByteArray() throws Exception { byte[] bytes = new byte[] {0, 1, 2, 3, 4, 5}; byte[] copy = TBaseHelper.copyBinary(bytes); assertEquals(ByteBuffer.wrap(bytes), ByteBuffer.wrap(copy)); assertNotSame(bytes, copy); assertNull(TBaseHelper.copyBinary((byte[]) null)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestTUnion.java0000644000000000000000000002063014303740367025514 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TTupleProtocol; import org.apache.thrift.transport.TMemoryBuffer; import org.junit.jupiter.api.Test; import thrift.test.ComparableUnion; import thrift.test.Empty; import thrift.test.RandomStuff; import thrift.test.SomeEnum; import thrift.test.StructWithAUnion; import thrift.test.TestUnion; import thrift.test.TestUnionMinusStringField; public class TestTUnion { @Test public void testBasic() throws Exception { { TestUnion union = new TestUnion(); assertFalse(union.isSet()); assertFalse(union.isSetI32_field()); assertNull(union.getFieldValue()); } { TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25); assertEquals(25, union.getFieldValue()); assertEquals(25, union.getFieldValue(TestUnion._Fields.I32_FIELD)); assertTrue(union.isSetI32_field()); assertThrows( IllegalArgumentException.class, () -> union.getFieldValue(TestUnion._Fields.STRING_FIELD)); } { TestUnion union = new TestUnion(); // should not throw an exception here union.hashCode(); union.setI32_field(1); assertEquals(1, union.getI32_field()); union.hashCode(); assertFalse(union.isSetString_field()); assertThrows(Exception.class, union::getString_field); } { TestUnion union = TestUnion.i32_field(1); assertFalse(union.equals(null)); } { TestUnion union = TestUnion.enum_field(SomeEnum.ONE); union.hashCode(); } { TestUnion union = new TestUnion(); // should not throw an exception union.toString(); } } @Test public void testCompareTo() throws Exception { ComparableUnion cu = ComparableUnion.string_field("a"); ComparableUnion cu2 = ComparableUnion.string_field("b"); assertEquals(0, cu.compareTo(cu)); assertEquals(0, cu2.compareTo(cu2)); assertTrue(cu.compareTo(cu2) < 0); assertTrue(cu2.compareTo(cu) > 0); cu2 = ComparableUnion.binary_field(ByteBuffer.wrap(new byte[] {2})); assertTrue(cu.compareTo(cu2) < 0); assertTrue(cu2.compareTo(cu) > 0); cu = ComparableUnion.binary_field(ByteBuffer.wrap(new byte[] {1})); assertTrue(cu.compareTo(cu2) < 0); assertTrue(cu2.compareTo(cu) > 0); TestUnion union1 = new TestUnion(TestUnion._Fields.STRUCT_LIST, new ArrayList()); TestUnion union2 = new TestUnion(TestUnion._Fields.STRUCT_LIST, new ArrayList()); assertEquals(0, union1.compareTo(union2)); TestUnion union3 = new TestUnion(TestUnion._Fields.I32_SET, new HashSet()); Set i32_set = new HashSet(); i32_set.add(1); TestUnion union4 = new TestUnion(TestUnion._Fields.I32_SET, i32_set); assertTrue(union3.compareTo(union4) < 0); Map i32_map = new HashMap(); i32_map.put(1, 1); TestUnion union5 = new TestUnion(TestUnion._Fields.I32_MAP, i32_map); TestUnion union6 = new TestUnion(TestUnion._Fields.I32_MAP, new HashMap()); assertTrue(union5.compareTo(union6) > 0); } @Test public void testEquality() throws Exception { TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25); TestUnion otherUnion = new TestUnion(TestUnion._Fields.STRING_FIELD, "blah!!!"); assertFalse(union.equals(otherUnion)); otherUnion = new TestUnion(TestUnion._Fields.I32_FIELD, 400); assertFalse(union.equals(otherUnion)); otherUnion = new TestUnion(TestUnion._Fields.OTHER_I32_FIELD, 25); assertFalse(union.equals(otherUnion)); } @Test public void testSerialization() throws Exception { TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25); union.setI32_set(Collections.singleton(42)); TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = new TBinaryProtocol(buf); union.write(proto); TestUnion u2 = new TestUnion(); u2.read(proto); assertEquals(u2, union); StructWithAUnion swau = new StructWithAUnion(u2); buf = new TMemoryBuffer(0); proto = new TBinaryProtocol(buf); swau.write(proto); StructWithAUnion swau2 = new StructWithAUnion(); assertFalse(swau2.equals(swau)); swau2.read(proto); assertEquals(swau2, swau); // this should NOT throw an exception. buf = new TMemoryBuffer(0); proto = new TBinaryProtocol(buf); swau.write(proto); new Empty().read(proto); } @Test public void testTupleProtocolSerialization() throws Exception { TestUnion union = new TestUnion(TestUnion._Fields.I32_FIELD, 25); union.setI32_set(Collections.singleton(42)); TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = new TTupleProtocol(buf); union.write(proto); TestUnion u2 = new TestUnion(); u2.read(proto); assertEquals(u2, union); StructWithAUnion swau = new StructWithAUnion(u2); buf = new TMemoryBuffer(0); proto = new TBinaryProtocol(buf); swau.write(proto); StructWithAUnion swau2 = new StructWithAUnion(); assertFalse(swau2.equals(swau)); swau2.read(proto); assertEquals(swau2, swau); // this should NOT throw an exception. buf = new TMemoryBuffer(0); proto = new TTupleProtocol(buf); swau.write(proto); new Empty().read(proto); } @Test public void testSkip() throws Exception { TestUnion tu = TestUnion.string_field("string"); byte[] tuSerialized = new TSerializer().serialize(tu); TestUnionMinusStringField tums = new TestUnionMinusStringField(); new TDeserializer().deserialize(tums, tuSerialized); assertNull(tums.getSetField()); assertNull(tums.getFieldValue()); } @Test public void testDeepCopy() throws Exception { byte[] bytes = {1, 2, 3}; ByteBuffer value = ByteBuffer.wrap(bytes); ComparableUnion cu = ComparableUnion.binary_field(value); ComparableUnion copy = cu.deepCopy(); assertEquals(cu, copy); assertNotSame(cu.bufferForBinary_field().array(), copy.bufferForBinary_field().array()); } @Test public void testToString() throws Exception { byte[] bytes = {1, 2, 3}; ByteBuffer value = ByteBuffer.wrap(bytes); ComparableUnion cu = ComparableUnion.binary_field(value); String expectedString = ""; assertEquals(expectedString, cu.toString()); } @Test public void testJavaSerializable() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); TestUnion tu = TestUnion.string_field("string"); // Serialize tu the Java way... oos.writeObject(tu); byte[] serialized = baos.toByteArray(); // Attempt to deserialize it ByteArrayInputStream bais = new ByteArrayInputStream(serialized); ObjectInputStream ois = new ObjectInputStream(bais); TestUnion tu2 = (TestUnion) ois.readObject(); assertEquals(tu, tu2); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestUnsafeBinaries.java0000644000000000000000000000631614303740367027203 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import java.nio.ByteBuffer; import org.junit.jupiter.api.Test; import thrift.test.SafeBytes; import thrift.test.UnsafeBytes; // test generating types with un-copied byte[]/ByteBuffer input/output // public class TestUnsafeBinaries { private static byte[] input() { return new byte[] {1, 1}; } // // verify that the unsafe_binaries option modifies behavior // // constructor doesn't copy @Test public void testUnsafeConstructor() throws Exception { byte[] input = input(); UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input)); input[0] = 2; assertArrayEquals(new byte[] {2, 1}, struct.getBytes()); } // getter doesn't copy // note: this behavior is the same with/without the flag, but if this default ever changes, the // current behavior // should be retained when using this flag @Test public void testUnsafeGetter() { UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input())); byte[] val = struct.getBytes(); val[0] = 2; assertArrayEquals(new byte[] {2, 1}, struct.getBytes()); } // setter doesn't copy @Test public void testUnsafeSetter() { UnsafeBytes struct = new UnsafeBytes(); byte[] val = input(); struct.setBytes(val); val[0] = 2; assertArrayEquals(new byte[] {2, 1}, struct.getBytes()); } // buffer doens't copy @Test public void testUnsafeBufferFor() { UnsafeBytes struct = new UnsafeBytes(ByteBuffer.wrap(input())); ByteBuffer val = struct.bufferForBytes(); val.array()[0] = 2; assertArrayEquals(new byte[] {2, 1}, struct.getBytes()); } // // verify that the default generator does not change behavior // @Test public void testSafeConstructor() { byte[] input = input(); SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input)); input[0] = 2; assertArrayEquals(new byte[] {1, 1}, struct.getBytes()); } @Test public void testSafeSetter() { byte[] input = input(); SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input)); input[0] = 2; assertArrayEquals(new byte[] {1, 1}, struct.getBytes()); } @Test public void testSafeBufferFor() { SafeBytes struct = new SafeBytes(ByteBuffer.wrap(input())); ByteBuffer val = struct.bufferForBytes(); val.array()[0] = 2; assertArrayEquals(new byte[] {1, 1}, struct.getBytes()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/async/0000777000000000000000000000000014303740367023715 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/async/TestTAsyncClient.java0000644000000000000000000000131414303740367027753 0ustar00rootroot00000000000000package org.apache.thrift.async; import static org.junit.jupiter.api.Assertions.assertThrows; import org.apache.thrift.TException; import org.junit.jupiter.api.Test; import thrift.test.Srv; import thrift.test.Srv.AsyncClient; public class TestTAsyncClient { @Test public void testRaisesExceptionWhenUsedConcurrently() throws Exception { TAsyncClientManager mockClientManager = new TAsyncClientManager() { @Override public void call(TAsyncMethodCall method) throws TException { // do nothing } }; Srv.AsyncClient c = new AsyncClient(null, mockClientManager, null); c.Janky(0, null); assertThrows(Exception.class, c::checkReady); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/async/TestTAsyncClientManager.java0000644000000000000000000003250314303740367031252 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.async; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.ServerTestBase; import org.apache.thrift.server.THsHaServer; import org.apache.thrift.server.THsHaServer.Args; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TNonblockingSocket; import org.apache.thrift.transport.TTransportException; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import thrift.test.CompactProtoTestStruct; import thrift.test.ExceptionWithAMap; import thrift.test.Srv; import thrift.test.Srv.Iface; public class TestTAsyncClientManager { private THsHaServer server_; private Thread serverThread_; private TAsyncClientManager clientManager_; @BeforeEach public void setUp() throws Exception { server_ = new THsHaServer( new Args( new TNonblockingServerSocket( new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs() .port(ServerTestBase.PORT))) .processor(new Srv.Processor(new SrvHandler()))); serverThread_ = new Thread( new Runnable() { public void run() { server_.serve(); } }); serverThread_.start(); clientManager_ = new TAsyncClientManager(); Thread.sleep(500); } @AfterEach public void tearDown() throws Exception { server_.stop(); clientManager_.stop(); serverThread_.join(); } @Test public void testBasicCall() throws Exception { Srv.AsyncClient client = getClient(); basicCall(client); } @Test public void testBasicCallWithTimeout() throws Exception { Srv.AsyncClient client = getClient(); client.setTimeout(5000); basicCall(client); } private abstract static class ErrorCallTest { final void runTest() throws Exception { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference error = new AtomicReference(); C client = executeErroringCall( new AsyncMethodCallback() { @Override public void onComplete(R response) { latch.countDown(); } @Override public void onError(Exception exception) { error.set(exception); latch.countDown(); } }); latch.await(2, TimeUnit.SECONDS); assertTrue(client.hasError()); Exception exception = error.get(); assertNotNull(exception); assertSame(exception, client.getError()); validateError(client, exception); } /** * Executes a call that is expected to raise an exception. * * @param callback The testing callback that should be installed. * @return The client the call was made against. * @throws Exception if there was a problem setting up the client or making the call. */ abstract C executeErroringCall(AsyncMethodCallback callback) throws Exception; /** * Further validates the properties of the error raised in the remote call and the state of the * client after that call. * * @param client The client returned from {@link #executeErroringCall(AsyncMethodCallback)}. * @param error The exception raised by the remote call. */ abstract void validateError(C client, Exception error); } @Test public void testUnexpectedRemoteExceptionCall() throws Exception { new ErrorCallTest() { @Override Srv.AsyncClient executeErroringCall(AsyncMethodCallback callback) throws Exception { Srv.AsyncClient client = getClient(); client.declaredExceptionMethod(false, callback); return client; } @Override void validateError(Srv.AsyncClient client, Exception error) { assertFalse(client.hasTimeout()); assertTrue(error instanceof TException); } }.runTest(); } @Test public void testDeclaredRemoteExceptionCall() throws Exception { new ErrorCallTest() { @Override Srv.AsyncClient executeErroringCall(AsyncMethodCallback callback) throws Exception { Srv.AsyncClient client = getClient(); client.declaredExceptionMethod(true, callback); return client; } @Override void validateError(Srv.AsyncClient client, Exception error) { assertFalse(client.hasTimeout()); assertEquals(ExceptionWithAMap.class, error.getClass()); ExceptionWithAMap exceptionWithAMap = (ExceptionWithAMap) error; assertEquals("blah", exceptionWithAMap.getBlah()); assertEquals(new HashMap(), exceptionWithAMap.getMap_field()); } }.runTest(); } @Test public void testTimeoutCall() throws Exception { new ErrorCallTest() { @Override Srv.AsyncClient executeErroringCall(AsyncMethodCallback callback) throws Exception { Srv.AsyncClient client = getClient(); client.setTimeout(100); client.primitiveMethod(callback); return client; } @Override void validateError(Srv.AsyncClient client, Exception error) { assertTrue(client.hasTimeout()); assertTrue(error instanceof TimeoutException); } }.runTest(); } @Test public void testVoidCall() throws Exception { final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean returned = new AtomicBoolean(false); Srv.AsyncClient client = getClient(); client.voidMethod( new FailureLessCallback() { @Override public void onComplete(Void response) { returned.set(true); latch.countDown(); } }); latch.await(1, TimeUnit.SECONDS); assertTrue(returned.get()); } @Test public void testOnewayCall() throws Exception { final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean returned = new AtomicBoolean(false); Srv.AsyncClient client = getClient(); client.onewayMethod( new FailureLessCallback() { @Override public void onComplete(Void response) { returned.set(true); latch.countDown(); } }); latch.await(1, TimeUnit.SECONDS); assertTrue(returned.get()); } @Test public void testParallelCalls() throws Exception { // make multiple calls with deserialization in the selector thread (repro Eric's issue) int numThreads = 50; int numCallsPerThread = 100; List runnables = new ArrayList(); List threads = new ArrayList(); for (int i = 0; i < numThreads; i++) { JankyRunnable runnable = new JankyRunnable(numCallsPerThread); Thread thread = new Thread(runnable); thread.start(); threads.add(thread); runnables.add(runnable); } for (Thread thread : threads) { thread.join(); } int numSuccesses = 0; for (JankyRunnable runnable : runnables) { numSuccesses += runnable.getNumSuccesses(); } assertEquals(numThreads * numCallsPerThread, numSuccesses); } private Srv.AsyncClient getClient() throws IOException, TTransportException { TNonblockingSocket clientSocket = new TNonblockingSocket(ServerTestBase.HOST, ServerTestBase.PORT); return new Srv.AsyncClient(new TBinaryProtocol.Factory(), clientManager_, clientSocket); } private void basicCall(Srv.AsyncClient client) throws Exception { final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean returned = new AtomicBoolean(false); client.Janky( 1, new FailureLessCallback() { @Override public void onComplete(Integer response) { assertEquals(3, response.intValue()); returned.set(true); latch.countDown(); } @Override public void onError(Exception exception) { try { StringWriter sink = new StringWriter(); exception.printStackTrace(new PrintWriter(sink, true)); Assertions.fail("unexpected onError with exception " + sink.toString()); } finally { latch.countDown(); } } }); latch.await(100, TimeUnit.SECONDS); assertTrue(returned.get()); } public static class SrvHandler implements Iface { // Use this method for a standard call testing @Override public int Janky(int arg) throws TException { assertEquals(1, arg); return 3; } // Using this method for timeout testing - sleeps for 1 second before returning @Override public int primitiveMethod() throws TException { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return 0; } @Override public void methodWithDefaultArgs(int something) throws TException {} @Override public CompactProtoTestStruct structMethod() throws TException { return null; } @Override public void voidMethod() throws TException {} @Override public void onewayMethod() throws TException {} @Override public boolean declaredExceptionMethod(boolean shouldThrowDeclared) throws TException { if (shouldThrowDeclared) { throw new ExceptionWithAMap("blah", new HashMap()); } else { throw new TException("Unexpected!"); } } } private abstract static class FailureLessCallback implements AsyncMethodCallback { @Override public void onError(Exception exception) { fail(exception); } } private static void fail(Exception exception) { StringWriter sink = new StringWriter(); exception.printStackTrace(new PrintWriter(sink, true)); Assertions.fail("unexpected error " + sink); } private class JankyRunnable implements Runnable { private final int numCalls_; private int numSuccesses_ = 0; private final Srv.AsyncClient client_; public JankyRunnable(int numCalls) throws Exception { numCalls_ = numCalls; client_ = getClient(); client_.setTimeout(20000); } public int getNumSuccesses() { return numSuccesses_; } public void run() { for (int i = 0; i < numCalls_ && !client_.hasError(); i++) { final int iteration = i; try { // connect an async client final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean returned = new AtomicBoolean(false); client_.Janky( 1, new AsyncMethodCallback() { @Override public void onComplete(Integer result) { assertEquals(3, result.intValue()); returned.set(true); latch.countDown(); } @Override public void onError(Exception exception) { try { StringWriter sink = new StringWriter(); exception.printStackTrace(new PrintWriter(sink, true)); Assertions.fail( "unexpected onError on iteration " + iteration + ": " + sink.toString()); } finally { latch.countDown(); } } }); boolean calledBack = latch.await(30, TimeUnit.SECONDS); assertTrue(calledBack, "wasn't called back in time on iteration " + iteration); assertTrue(returned.get(), "onComplete not called on iteration " + iteration); this.numSuccesses_++; } catch (Exception e) { fail(e); } } } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/0000777000000000000000000000000014370300523024427 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTJSONProtocol.java0000644000000000000000000000440014303740367030555 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.charset.StandardCharsets; import org.apache.thrift.TException; import org.apache.thrift.transport.TMemoryBuffer; import org.junit.jupiter.api.Test; public class TestTJSONProtocol extends ProtocolTestBase { @Override protected TProtocolFactory getFactory() { return new TJSONProtocol.Factory(); } @Override protected boolean canBeUsedNaked() { return false; } @Test public void testEscapedUnicode() throws TException { String jsonString = "\"hello unicode \\u0e01\\ud834\\udd1e world\""; String expectedString = "hello unicode \u0e01\ud834\udd1e world"; TMemoryBuffer buffer = new TMemoryBuffer(1000); TJSONProtocol protocol = new TJSONProtocol(buffer); buffer.write(jsonString.getBytes(StandardCharsets.UTF_8)); assertEquals(expectedString, protocol.readString()); } @Test public void testExactlySizedBuffer() throws TException { // Regression test for https://issues.apache.org/jira/browse/THRIFT-5383. // Ensures that a JSON string can be read after writing to a buffer just // large enough to contain it. String inputString = "abcdefg"; TMemoryBuffer buffer = new TMemoryBuffer(inputString.length() + 2); TJSONProtocol protocol = new TJSONProtocol(buffer); protocol.writeString(inputString); String outputString = protocol.readString(); assertEquals(inputString, outputString); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTTupleProtocol.java0000644000000000000000000000144614303740367031104 0ustar00rootroot00000000000000package org.apache.thrift.protocol; import org.apache.thrift.TDeserializer; import org.apache.thrift.TSerializer; import org.junit.jupiter.api.Test; import thrift.test.TupleProtocolTestStruct; public class TestTTupleProtocol extends ProtocolTestBase { @Override protected boolean canBeUsedNaked() { return false; } @Override protected TProtocolFactory getFactory() { return new TTupleProtocol.Factory(); } @Test public void testBitsetLengthIssue() throws Exception { final TupleProtocolTestStruct t1 = new TupleProtocolTestStruct(); t1.setField1(0); t1.setField2(12); new TDeserializer(new TTupleProtocol.Factory()) .deserialize( new TupleProtocolTestStruct(), new TSerializer(new TTupleProtocol.Factory()).serialize(t1)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestShortStack.java0000644000000000000000000000261514303740367030231 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; public class TestShortStack { @Test public void testOps() throws Exception { ShortStack s = new ShortStack(1); s.push((short) 10); s.push((short) 11); s.push((short) 12); assertEquals((short) 12, s.pop()); assertEquals((short) 11, s.pop()); s.push((short) 40); assertEquals((short) 40, s.pop()); assertEquals((short) 10, s.pop()); assertThrows(Exception.class, s::pop); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java0000644000000000000000000001503114303740367031731 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.charset.StandardCharsets; import org.apache.thrift.Fixtures; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.transport.TMemoryBuffer; import org.apache.thrift.transport.TTransportException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import thrift.test.CompactProtoTestStruct; import thrift.test.HolyMoley; public class TestTSimpleJSONProtocol { private TMemoryBuffer buf; private TSimpleJSONProtocol proto; @BeforeEach public void setUp() throws Exception { buf = new TMemoryBuffer(1000); proto = new TSimpleJSONProtocol(buf); } private String bufToString() { return buf.toString(StandardCharsets.UTF_8); } @Test public void testHolyMoley() throws TException { final HolyMoley holyMoley = Fixtures.getHolyMoley().deepCopy(); // unset sets that produce inconsistent ordering between JDK7/8 holyMoley.unsetBonks(); holyMoley.unsetContain(); holyMoley.write(proto); assertEquals( "{\"big\":[{\"im_true\":1,\"im_false\":0,\"a_bite\":35,\"integer16\":27000,\"integer32\":16777216,\"integer64\":6000000000,\"double_precision\":3.141592653589793,\"some_characters\":\"JSON THIS! \\\"\\u0001\",\"zomg_unicode\":\"ӀⅮΠÐοⅿоɡгаÏℎ Αttαⅽκ�‼\",\"what_who\":0,\"base64\":\"base64\",\"byte_list\":[1,2,3],\"i16_list\":[1,2,3],\"i64_list\":[1,2,3]},{\"im_true\":1,\"im_false\":0,\"a_bite\":-42,\"integer16\":27000,\"integer32\":16777216,\"integer64\":6000000000,\"double_precision\":3.141592653589793,\"some_characters\":\"JSON THIS! \\\"\\u0001\",\"zomg_unicode\":\"ӀⅮΠÐοⅿоɡгаÏℎ Αttαⅽκ�‼\",\"what_who\":0,\"base64\":\"base64\",\"byte_list\":[1,2,3],\"i16_list\":[1,2,3],\"i64_list\":[1,2,3]}]}", bufToString()); } @Test public void testNesting() throws TException { Fixtures.getNesting().write(proto); assertEquals( "{\"my_bonk\":{\"type\":31337,\"message\":\"I am a bonk... xor!\"},\"my_ooe\":{\"im_true\":1,\"im_false\":0,\"a_bite\":-42,\"integer16\":27000,\"integer32\":16777216,\"integer64\":6000000000,\"double_precision\":3.141592653589793,\"some_characters\":\"JSON THIS! \\\"\\u0001\",\"zomg_unicode\":\"ӀⅮΠÐοⅿоɡгаÏℎ Αttαⅽκ�‼\",\"what_who\":0,\"base64\":\"base64\",\"byte_list\":[1,2,3],\"i16_list\":[1,2,3],\"i64_list\":[1,2,3]}}", bufToString()); } @Test public void testOneOfEach() throws TException { Fixtures.getOneOfEach().write(proto); assertEquals( "{\"im_true\":1,\"im_false\":0,\"a_bite\":-42,\"integer16\":27000,\"integer32\":16777216,\"integer64\":6000000000,\"double_precision\":3.141592653589793,\"some_characters\":\"JSON THIS! \\\"\\u0001\",\"zomg_unicode\":\"ӀⅮΠÐοⅿоɡгаÏℎ Αttαⅽκ�‼\",\"what_who\":0,\"base64\":\"base64\",\"byte_list\":[1,2,3],\"i16_list\":[1,2,3],\"i64_list\":[1,2,3]}", bufToString()); } @Test public void testSanePartsOfCompactProtoTestStruct() throws TException { // unset all the maps with container keys CompactProtoTestStruct struct = Fixtures.getCompactProtoTestStruct().deepCopy(); struct.unsetList_byte_map(); struct.unsetSet_byte_map(); struct.unsetMap_byte_map(); // unset sets and maps that produce inconsistent ordering between JDK7/8 struct.unsetByte_set(); struct.unsetI16_set(); struct.unsetI64_set(); struct.unsetDouble_set(); struct.unsetString_set(); struct.unsetI16_byte_map(); struct.unsetI32_byte_map(); struct.unsetI64_byte_map(); struct.unsetDouble_byte_map(); struct.unsetString_byte_map(); struct.write(proto); assertEquals( "{\"a_byte\":127,\"a_i16\":32000,\"a_i32\":1000000000,\"a_i64\":1099511627775,\"a_double\":5.6789,\"a_string\":\"my string\",\"a_binary\":\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\",\"true_field\":1,\"false_field\":0,\"empty_struct_field\":{},\"byte_list\":[-127,-1,0,1,127],\"i16_list\":[-1,0,1,32767],\"i32_list\":[-1,0,255,65535,16777215,2147483647],\"i64_list\":[-1,0,255,65535,16777215,4294967295,1099511627775,281474976710655,72057594037927935,9223372036854775807],\"double_list\":[0.1,0.2,0.3],\"string_list\":[\"first\",\"second\",\"third\"],\"boolean_list\":[1,1,1,0,0,0],\"struct_list\":[{},{}],\"i32_set\":[1,2,3],\"boolean_set\":[0,1],\"struct_set\":[{}],\"byte_byte_map\":{\"1\":2},\"boolean_byte_map\":{\"0\":0,\"1\":1},\"byte_i16_map\":{\"1\":1,\"2\":-1,\"3\":32767},\"byte_i32_map\":{\"1\":1,\"2\":-1,\"3\":2147483647},\"byte_i64_map\":{\"1\":1,\"2\":-1,\"3\":9223372036854775807},\"byte_double_map\":{\"1\":0.1,\"2\":-0.1,\"3\":1000000.1},\"byte_string_map\":{\"1\":\"\",\"2\":\"blah\",\"3\":\"loooooooooooooong string\"},\"byte_boolean_map\":{\"1\":1,\"2\":0},\"byte_map_map\":{\"0\":{},\"1\":{\"1\":1},\"2\":{\"1\":1,\"2\":2}},\"byte_set_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]},\"byte_list_map\":{\"0\":[],\"1\":[1],\"2\":[1,2]},\"field500\":500,\"field5000\":5000,\"field20000\":20000}", bufToString()); } @Test public void testThrowsOnCollectionKeys() throws TException { assertThrows( TSimpleJSONProtocol.CollectionMapKeyException.class, () -> Fixtures.getCompactProtoTestStruct().write(proto)); } @Test public void testReadingThrows() throws TTransportException { String input = "{\"test\": \"value\"}"; TDeserializer deserializer = new TDeserializer(new TSimpleJSONProtocol.Factory()); TException e = assertThrows( TException.class, () -> { deserializer.fromString(Fixtures.getOneOfEach(), input); }); assertEquals("Not implemented", e.getMessage()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTCompactProtocol.java0000644000000000000000000000337714303740367031406 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.junit.jupiter.api.Test; import thrift.test.Bonk; public class TestTCompactProtocol extends ProtocolTestBase { @Override protected TProtocolFactory getFactory() { return new TCompactProtocol.Factory(); } @Override protected boolean canBeUsedNaked() { return true; } @Test public void testOOMDenialOfService() throws Exception { // Struct header, Integer.MAX_VALUE length, and only one real // byte of data byte[] bytes = {24, -1, -1, -1, -17, 49}; TDeserializer deser = new TDeserializer(new TCompactProtocol.Factory(1000)); Bonk bonk = new Bonk(); try { deser.deserialize(bonk, bytes); } catch (TException e) { // Ignore as we are only checking for OOM in the failure case } } public static void main(String args[]) throws Exception { new TestTCompactProtocol().benchmark(); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTBinaryProtocol.java0000644000000000000000000000206714303740367031237 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; public class TestTBinaryProtocol extends ProtocolTestBase { @Override protected TProtocolFactory getFactory() { return new TBinaryProtocol.Factory(); } @Override protected boolean canBeUsedNaked() { return true; } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/ProtocolTestBase.java0000644000000000000000000005000414370300523030521 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.thrift.Fixtures; import org.apache.thrift.TBase; import org.apache.thrift.TConfiguration; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.TSerializer; import org.apache.thrift.server.ServerTestBase; import org.apache.thrift.transport.TMemoryBuffer; import org.apache.thrift.transport.TTransportException; import org.junit.jupiter.api.Test; import thrift.test.CompactProtoTestStruct; import thrift.test.HolyMoley; import thrift.test.Nesting; import thrift.test.OneOfEach; import thrift.test.Srv; import thrift.test.ThriftTest; public abstract class ProtocolTestBase { /** Does it make sense to call methods like writeI32 directly on your protocol? */ protected abstract boolean canBeUsedNaked(); /** The protocol factory for the protocol being tested. */ protected abstract TProtocolFactory getFactory(); @Test public void testDouble() throws Exception { if (canBeUsedNaked()) { TMemoryBuffer buf = new TMemoryBuffer(1000); TProtocol proto = getFactory().getProtocol(buf); proto.writeDouble(123.456); assertEquals(123.456, proto.readDouble()); } internalTestStructField( new StructFieldTestCase(TType.DOUBLE, (short) 15) { @Override public void readMethod(TProtocol proto) throws TException { assertEquals(123.456, proto.readDouble()); } @Override public void writeMethod(TProtocol proto) throws TException { proto.writeDouble(123.456); } }); } @Test public void testSerialization() throws Exception { internalTestSerialization(OneOfEach.class, Fixtures.getOneOfEach()); internalTestSerialization(Nesting.class, Fixtures.getNesting()); internalTestSerialization(HolyMoley.class, Fixtures.getHolyMoley()); internalTestSerialization(CompactProtoTestStruct.class, Fixtures.getCompactProtoTestStruct()); } @Test public void testBinary() throws Exception { for (byte[] b : Arrays.asList( new byte[0], new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, new byte[] {0x5D}, new byte[] {(byte) 0xD5, (byte) 0x5D}, new byte[] {(byte) 0xFF, (byte) 0xD5, (byte) 0x5D}, new byte[128])) { if (canBeUsedNaked()) { internalTestNakedBinary(b); } internalTestBinaryField(b); } if (canBeUsedNaked()) { byte[] data = {1, 2, 3, 4, 5, 6}; TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); ByteBuffer bb = ByteBuffer.wrap(data); bb.get(); proto.writeBinary(bb.slice()); assertEquals(ByteBuffer.wrap(data, 1, 5), proto.readBinary()); } } @Test public void testString() throws Exception { for (String s : Arrays.asList("", "short", "borderlinetiny", "a bit longer than the smallest possible")) { if (canBeUsedNaked()) { internalTestNakedString(s); } internalTestStringField(s); } } @Test public void testUuid() throws Exception { UUID uuid = UUID.fromString("00112233-4455-6677-8899-aabbccddeeff"); if (canBeUsedNaked()) { internalTestNakedUuid(uuid); } internalTestUuidField(uuid); } @Test public void testLong() throws Exception { if (canBeUsedNaked()) { internalTestNakedI64(0); } internalTestI64Field(0); for (int i = 0; i < 62; i++) { if (canBeUsedNaked()) { internalTestNakedI64(1L << i); internalTestNakedI64(-(1L << i)); } internalTestI64Field(1L << i); internalTestI64Field(-(1L << i)); } } @Test public void testInt() throws Exception { for (int i : Arrays.asList( 0, 1, 7, 150, 15000, 31337, 0xffff, 0xffffff, -1, -7, -150, -15000, -0xffff, -0xffffff)) { if (canBeUsedNaked()) { internalTestNakedI32(i); } internalTestI32Field(i); } } @Test public void testShort() throws Exception { for (int s : Arrays.asList(0, 1, 7, 150, 15000, 0x7fff, -1, -7, -150, -15000, -0x7fff)) { if (canBeUsedNaked()) { internalTestNakedI16((short) s); } internalTestI16Field((short) s); } } @Test public void testByte() throws Exception { if (canBeUsedNaked()) { internalTestNakedByte(); } for (int i = 0; i < 128; i++) { internalTestByteField((byte) i); internalTestByteField((byte) -i); } } private void internalTestNakedByte() throws Exception { TMemoryBuffer buf = new TMemoryBuffer(1000); TProtocol proto = getFactory().getProtocol(buf); proto.writeByte((byte) 123); assertEquals((byte) 123, proto.readByte()); } private void internalTestByteField(final byte b) throws Exception { internalTestStructField( new StructFieldTestCase(TType.BYTE, (short) 15) { public void writeMethod(TProtocol proto) throws TException { proto.writeByte(b); } public void readMethod(TProtocol proto) throws TException { assertEquals(b, proto.readByte()); } }); } private void internalTestNakedI16(short n) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); proto.writeI16(n); assertEquals(n, proto.readI16()); } private void internalTestI16Field(final short n) throws Exception { internalTestStructField( new StructFieldTestCase(TType.I16, (short) 15) { public void writeMethod(TProtocol proto) throws TException { proto.writeI16(n); } public void readMethod(TProtocol proto) throws TException { assertEquals(n, proto.readI16()); } }); } private void internalTestNakedUuid(UUID uuid) throws TException { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol protocol = getFactory().getProtocol(buf); protocol.writeUuid(uuid); assertEquals(uuid, protocol.readUuid()); } private void internalTestUuidField(UUID uuid) throws Exception { internalTestStructField( new StructFieldTestCase(TType.UUID, (short) 17) { @Override public void writeMethod(TProtocol proto) throws TException { proto.writeUuid(uuid); } @Override public void readMethod(TProtocol proto) throws TException { assertEquals(uuid, proto.readUuid()); } }); } private void internalTestNakedI32(int n) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); proto.writeI32(n); assertEquals(n, proto.readI32()); } private void internalTestI32Field(final int n) throws Exception { internalTestStructField( new StructFieldTestCase(TType.I32, (short) 15) { public void writeMethod(TProtocol proto) throws TException { proto.writeI32(n); } public void readMethod(TProtocol proto) throws TException { assertEquals(n, proto.readI32()); } }); } private void internalTestNakedI64(long n) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); proto.writeI64(n); assertEquals(n, proto.readI64()); } private void internalTestI64Field(final long n) throws Exception { internalTestStructField( new StructFieldTestCase(TType.I64, (short) 15) { public void writeMethod(TProtocol proto) throws TException { proto.writeI64(n); } public void readMethod(TProtocol proto) throws TException { assertEquals(n, proto.readI64()); } }); } private void internalTestNakedString(String str) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); proto.writeString(str); assertEquals(str, proto.readString()); } private void internalTestStringField(final String str) throws Exception { internalTestStructField( new StructFieldTestCase(TType.STRING, (short) 15) { public void writeMethod(TProtocol proto) throws TException { proto.writeString(str); } public void readMethod(TProtocol proto) throws TException { assertEquals(str, proto.readString()); } }); } private void internalTestNakedBinary(byte[] data) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); proto.writeBinary(ByteBuffer.wrap(data)); assertEquals(ByteBuffer.wrap(data), proto.readBinary()); } private void internalTestBinaryField(final byte[] data) throws Exception { internalTestStructField( new StructFieldTestCase(TType.STRING, (short) 15) { public void writeMethod(TProtocol proto) throws TException { proto.writeBinary(ByteBuffer.wrap(data)); } public void readMethod(TProtocol proto) throws TException { assertEquals(ByteBuffer.wrap(data), proto.readBinary()); } }); } private void internalTestSerialization(Class klass, T expected) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TBinaryProtocol binproto = new TBinaryProtocol(buf); expected.write(binproto); buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); expected.write(proto); System.out.println("Size in " + proto.getClass().getSimpleName() + ": " + buf.length()); T actual = klass.getDeclaredConstructor().newInstance(); actual.read(proto); assertEquals(expected, actual); } @Test public void testMessage() throws Exception { List msgs = Arrays.asList( new TMessage[] { new TMessage("short message name", TMessageType.CALL, 0), new TMessage("1", TMessageType.REPLY, 12345), new TMessage( "loooooooooooooooooooooooooooooooooong", TMessageType.EXCEPTION, 1 << 16), new TMessage("Janky", TMessageType.CALL, 0), }); for (TMessage msg : msgs) { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); TMessage output = null; proto.writeMessageBegin(msg); proto.writeMessageEnd(); output = proto.readMessageBegin(); assertEquals(msg, output); } } @Test public void testServerRequest() throws Exception { Srv.Iface handler = new Srv.Iface() { public int Janky(int i32arg) throws TException { return i32arg * 2; } public int primitiveMethod() throws TException { return 0; } public CompactProtoTestStruct structMethod() throws TException { return null; } public void voidMethod() throws TException {} public void methodWithDefaultArgs(int something) throws TException {} @Override public void onewayMethod() throws TException {} @Override public boolean declaredExceptionMethod(boolean shouldThrow) throws TException { return shouldThrow; } }; Srv.Processor testProcessor = new Srv.Processor(handler); TMemoryBuffer clientOutTrans = new TMemoryBuffer(0); TProtocol clientOutProto = getFactory().getProtocol(clientOutTrans); TMemoryBuffer clientInTrans = new TMemoryBuffer(0); TProtocol clientInProto = getFactory().getProtocol(clientInTrans); Srv.Client testClient = new Srv.Client(clientInProto, clientOutProto); testClient.send_Janky(1); // System.out.println(clientOutTrans.inspect()); testProcessor.process(clientOutProto, clientInProto); // System.out.println(clientInTrans.inspect()); assertEquals(2, testClient.recv_Janky()); } @Test public void testTDeserializer() throws TException { TSerializer ser = new TSerializer(getFactory()); byte[] bytes = ser.serialize(Fixtures.getCompactProtoTestStruct()); TDeserializer deser = new TDeserializer(getFactory()); CompactProtoTestStruct cpts = new CompactProtoTestStruct(); deser.deserialize(cpts, bytes); assertEquals(Fixtures.getCompactProtoTestStruct(), cpts); } // // Helper methods // private void internalTestStructField(StructFieldTestCase testCase) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); TProtocol proto = getFactory().getProtocol(buf); TField field = new TField("test_field", testCase.type_, testCase.id_); proto.writeStructBegin(new TStruct("test_struct")); proto.writeFieldBegin(field); testCase.writeMethod(proto); proto.writeFieldEnd(); proto.writeStructEnd(); proto.readStructBegin(); TField readField = proto.readFieldBegin(); assertEquals(testCase.id_, readField.id); assertEquals(testCase.type_, readField.type); testCase.readMethod(proto); proto.readStructEnd(); } private abstract static class StructFieldTestCase { byte type_; short id_; public StructFieldTestCase(byte type, short id) { type_ = type; id_ = id; } public abstract void writeMethod(TProtocol proto) throws TException; public abstract void readMethod(TProtocol proto) throws TException; } private static final int NUM_TRIALS = 5; private static final int NUM_REPS = 10000; protected void benchmark() throws Exception { for (int trial = 0; trial < NUM_TRIALS; trial++) { TSerializer ser = new TSerializer(getFactory()); byte[] serialized = null; long serStart = System.currentTimeMillis(); for (int rep = 0; rep < NUM_REPS; rep++) { serialized = ser.serialize(Fixtures.getHolyMoley()); } long serEnd = System.currentTimeMillis(); long serElapsed = serEnd - serStart; System.out.println( "Ser:\t" + serElapsed + "ms\t" + ((double) serElapsed / NUM_REPS) + "ms per serialization"); HolyMoley cpts = new HolyMoley(); TDeserializer deser = new TDeserializer(getFactory()); long deserStart = System.currentTimeMillis(); for (int rep = 0; rep < NUM_REPS; rep++) { deser.deserialize(cpts, serialized); } long deserEnd = System.currentTimeMillis(); long deserElapsed = deserEnd - deserStart; System.out.println( "Des:\t" + deserElapsed + "ms\t" + ((double) deserElapsed / NUM_REPS) + "ms per deserialization"); } } private final ServerTestBase.TestHandler testHandler = new ServerTestBase.TestHandler() { @Override public String testString(String thing) { thing = thing + " Apache Thrift Java " + thing; return thing; } @Override public List testList(List thing) { thing.addAll(thing); thing.addAll(thing); return thing; } @Override public Set testSet(Set thing) { thing.addAll(thing.stream().map(x -> x + 100).collect(Collectors.toSet())); return thing; } @Override public Map testStringMap(Map thing) { thing.put("a", "123"); thing.put(" x y ", " with spaces "); thing.put("same", "same"); thing.put("0", "numeric key"); thing.put("1", ""); thing.put("ok", "2355555"); thing.put("end", "0"); return thing; } }; private TProtocol initConfig(int maxSize) throws TException { TConfiguration config = TConfiguration.custom().setMaxMessageSize(maxSize).build(); TMemoryBuffer bufferTrans = new TMemoryBuffer(config, 0); return getFactory().getProtocol(bufferTrans); } @Test public void testReadCheckMaxMessageRequestForString() throws TException { TProtocol clientOutProto = initConfig(15); TProtocol clientInProto = initConfig(15); ThriftTest.Client testClient = new ThriftTest.Client(clientInProto, clientOutProto); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); try { testClient.send_testString("test"); testProcessor.process(clientOutProto, clientInProto); String result = testClient.recv_testString(); System.out.println("----result: " + result); } catch (TException e) { assertEquals("MaxMessageSize reached", e.getMessage()); } } @Test public void testReadCheckMaxMessageRequestForList() throws TException { TProtocol clientOutProto = initConfig(15); TProtocol clientInProto = initConfig(15); ThriftTest.Client testClient = new ThriftTest.Client(clientInProto, clientOutProto); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); TTransportException e = assertThrows( TTransportException.class, () -> { testClient.send_testList(Arrays.asList(1, 23242346, 888888, 90)); testProcessor.process(clientOutProto, clientInProto); testClient.recv_testList(); }, "Limitations not achieved as expected"); assertEquals("MaxMessageSize reached", e.getMessage()); } @Test public void testReadCheckMaxMessageRequestForMap() throws TException { TProtocol clientOutProto = initConfig(13); TProtocol clientInProto = initConfig(13); ThriftTest.Client testClient = new ThriftTest.Client(clientInProto, clientOutProto); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); Map thing = new HashMap<>(); thing.put("key", "Thrift"); TTransportException e = assertThrows( TTransportException.class, () -> { testClient.send_testStringMap(thing); testProcessor.process(clientOutProto, clientInProto); testClient.recv_testStringMap(); }, "Limitations not achieved as expected"); assertEquals("MaxMessageSize reached", e.getMessage()); } @Test public void testReadCheckMaxMessageRequestForSet() throws TException { TProtocol clientOutProto = initConfig(10); TProtocol clientInProto = initConfig(10); ThriftTest.Client testClient = new ThriftTest.Client(clientInProto, clientOutProto); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); TTransportException e = assertThrows( TTransportException.class, () -> { testClient.send_testSet( Stream.of(234, 0, 987087, 45, 88888888, 9).collect(Collectors.toSet())); testProcessor.process(clientOutProto, clientInProto); testClient.recv_testSet(); }, "Limitations not achieved as expected"); assertEquals("MaxMessageSize reached", e.getMessage()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTProtocolUtil.java0000644000000000000000000000665414303740367030736 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.thrift.TSerializer; import org.junit.jupiter.api.Test; import thrift.test.GuessProtocolStruct; public class TestTProtocolUtil { @Test public void testGuessProtocolFactory_JSON() throws Exception { byte[] data = "{foo}".getBytes(); TProtocolFactory factory = TProtocolUtil.guessProtocolFactory(data, new TCompactProtocol.Factory()); assertTrue(factory instanceof TJSONProtocol.Factory); // Make sure data serialized with TCompact and which starts with '{' // is not mistakenly guessed as serialized with JSON. GuessProtocolStruct s = new GuessProtocolStruct(); s.putToMap_field("}", "}"); byte[] ser = new TSerializer(new TCompactProtocol.Factory()).serialize(s); factory = TProtocolUtil.guessProtocolFactory(ser, new TCompactProtocol.Factory()); assertFalse(factory instanceof TJSONProtocol.Factory); } @Test public void testGuessProtocolFactory_Binary() throws Exception { // Check that a last byte != 0 is correctly reported as Binary byte[] buf = new byte[1]; for (int i = 1; i < 256; i++) { buf[0] = (byte) i; TProtocolFactory factory = TProtocolUtil.guessProtocolFactory(buf, new TCompactProtocol.Factory()); assertTrue(factory instanceof TBinaryProtocol.Factory); } // Check that a second byte set to 0 is reported as Binary buf = new byte[2]; TProtocolFactory factory = TProtocolUtil.guessProtocolFactory(buf, new TCompactProtocol.Factory()); assertTrue(factory instanceof TBinaryProtocol.Factory); } @Test public void testGuessProtocolFactory_Compact() throws Exception { // Check that a first byte > 0x10 is reported as Compact byte[] buf = new byte[3]; buf[0] = 0x11; TProtocolFactory factory = TProtocolUtil.guessProtocolFactory(buf, new TBinaryProtocol.Factory()); assertTrue(factory instanceof TCompactProtocol.Factory); // Check that second byte >= 0x80 is reported as Compact buf[0] = 0; for (int i = 0x80; i < 0x100; i++) { buf[1] = (byte) i; factory = TProtocolUtil.guessProtocolFactory(buf, new TBinaryProtocol.Factory()); assertTrue(factory instanceof TCompactProtocol.Factory); } } @Test public void testGuessProtocolFactory_Undecided() throws Exception { byte[] buf = new byte[3]; buf[1] = 0x7e; TProtocolFactory factory = TProtocolUtil.guessProtocolFactory(buf, new TSimpleJSONProtocol.Factory()); assertTrue(factory instanceof TSimpleJSONProtocol.Factory); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/TestTField.java0000644000000000000000000000417014303740367027311 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.protocol; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.Test; public abstract class TestTField { @Test public void testConstructor() { TField uut = new TField(); assertEquals("", uut.name); assertEquals(TType.STOP, uut.type); assertEquals(0, uut.id); uut = new TField("foo", TType.VOID, (short) 42); assertEquals("foo", uut.name); assertEquals(TType.VOID, uut.type); assertEquals(42, uut.id); } @Test public void testEquality() { TField uut1 = new TField(); TField uut2 = new TField(); assertEquals(uut1, uut2); assertEquals(uut1.hashCode(), uut2.hashCode()); uut1 = new TField("foo", TType.I32, (short) 1); uut2 = new TField("foo", TType.I32, (short) 2); assertNotEquals(uut1, uut2); assertNotEquals(uut1.hashCode(), uut2.hashCode()); uut1 = new TField("foo", TType.VOID, (short) 1); uut2 = new TField("foo", TType.I32, (short) 1); assertNotEquals(uut1, uut2); assertNotEquals(uut1.hashCode(), uut2.hashCode()); uut1 = new TField("foo", TType.VOID, (short) 5); uut2 = new TField("bar", TType.I32, (short) 5); assertEquals(uut1, uut2); // name field is ignored assertEquals(uut1.hashCode(), uut2.hashCode()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/protocol/BenchmarkProtocols.java0000644000000000000000000000544014303740367031102 0ustar00rootroot00000000000000package org.apache.thrift.protocol; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.thrift.Fixtures; import org.apache.thrift.TException; import org.apache.thrift.transport.TMemoryBuffer; public class BenchmarkProtocols { private static final Set FACTORIES = new LinkedHashSet() { { add(new TTupleProtocol.Factory()); add(new TCompactProtocol.Factory()); add(new TBinaryProtocol.Factory()); } }; private static final int NUM_REPS = 100000; private static final int NUM_TRIALS = 10; public static void main(String[] args) throws TException { Map> timesByFactory = new HashMap>(); for (int trial = 0; trial < NUM_TRIALS; trial++) { for (int i = 0; i < 16; i++) { System.gc(); } // TProtocol proto = factory.getProtocol(new TTransport() { // @Override // public void write(byte[] buf, int off, int len) throws TTransportException { // } // // @Override // public int read(byte[] buf, int off, int len) throws TTransportException { // return 0; // } // // @Override // public void open() throws TTransportException { // } // // @Override // public boolean isOpen() { // return true; // } // // @Override // public void close() { // } // }); for (TProtocolFactory factory : FACTORIES) { if (timesByFactory.get(factory) == null) { timesByFactory.put(factory, new ArrayList()); } long start = System.currentTimeMillis(); for (int rep = 0; rep < NUM_REPS; rep++) { TProtocol proto = factory.getProtocol(new TMemoryBuffer(128 * 1024)); Fixtures.getCompactProtoTestStruct().write(proto); Fixtures.getNesting().write(proto); } long end = System.currentTimeMillis(); timesByFactory.get(factory).add(end - start); } } for (TProtocolFactory factory : FACTORIES) { List times = timesByFactory.get(factory); // System.out.println("raw times pre-drop: " + times ); times.remove(Collections.max(times)); long total = 0; for (long t : times) { total += t; } Collections.sort(times); System.out.println( factory.getClass().getName() + " average time: " + (total / times.size()) + "ms"); System.out.println("raw times: " + times); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestOptionals.java0000644000000000000000000000567314303740367026262 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import thrift.test.Opt30; import thrift.test.Opt4; import thrift.test.Opt64; import thrift.test.Opt80; // Exercises the isSet methods using structs from ManyOptionals.thrift public class TestOptionals { @Test public void testEncodingUtils() throws Exception { assertEquals((short) 0x8, EncodingUtils.setBit((short) 0, 3, true)); assertEquals((short) 0, EncodingUtils.setBit((short) 0x8, 3, false)); assertTrue(EncodingUtils.testBit((short) 0x8, 3)); assertFalse(EncodingUtils.testBit((short) 0x8, 4)); assertEquals(Short.MIN_VALUE, EncodingUtils.setBit((short) 0, 15, true)); assertEquals((short) 0, EncodingUtils.setBit(Short.MIN_VALUE, 15, false)); assertTrue(EncodingUtils.testBit(Short.MIN_VALUE, 15)); assertFalse(EncodingUtils.testBit(Short.MIN_VALUE, 14)); } @Test public void testOpt4() throws Exception { Opt4 x = new Opt4(); assertFalse(x.isSetDef1()); x.setDef1(3); assertTrue(x.isSetDef1()); assertFalse(x.isSetDef2()); Opt4 copy = new Opt4(x); assertTrue(copy.isSetDef1()); copy.unsetDef1(); assertFalse(copy.isSetDef1()); assertTrue(x.isSetDef1()); } @Test public void testOpt30() throws Exception { Opt30 x = new Opt30(); assertFalse(x.isSetDef1()); x.setDef1(3); assertTrue(x.isSetDef1()); assertFalse(x.isSetDef2()); } @Test public void testOpt64() throws Exception { Opt64 x = new Opt64(); assertFalse(x.isSetDef1()); x.setDef1(3); assertTrue(x.isSetDef1()); assertFalse(x.isSetDef2()); x.setDef64(22); assertTrue(x.isSetDef64()); assertFalse(x.isSetDef63()); } @Test public void testOpt80() throws Exception { Opt80 x = new Opt80(); assertFalse(x.isSetDef1()); x.setDef1(3); assertTrue(x.isSetDef1()); assertFalse(x.isSetDef2()); Opt80 copy = new Opt80(x); copy.unsetDef1(); assertFalse(copy.isSetDef1()); assertTrue(x.isSetDef1()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestTEnumHelper.java0000644000000000000000000000272014303740367026470 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Test; import thrift.test.Numberz; public class TestTEnumHelper { @Test public void testGetByValue_ValidValues() { for (Numberz n : Numberz.values()) { int value = n.getValue(); assertEquals(n, TEnumHelper.getByValue(Numberz.class, value)); } } @Test public void testGetByValue_InvalidValue() { assertNull(TEnumHelper.getByValue(Numberz.class, 0)); } @Test public void testGetByValue_InvalidClass() { assertNull(TEnumHelper.getByValue(TEnum.class, 0)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/0000777000000000000000000000000014370300523024222 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/TFieldDataTest.java0000644000000000000000000000323014303740367027672 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertEquals; import org.apache.thrift.protocol.TField; import org.apache.thrift.protocol.TType; import org.junit.jupiter.api.Test; public class TFieldDataTest { @Test public void testEncodeStop() { TField field = new TField("", TType.STOP, (short) 0); int data = TFieldData.encode(TType.STOP); assertEquals(field.type, TFieldData.getType(data)); assertEquals(field.id, TFieldData.getId(data)); } @Test public void testEncodeRest() { for (byte type = 1; type <= 16; type++) { for (short id = 0; id < Short.MAX_VALUE; id++) { TField field = new TField("", type, id); int data = TFieldData.encode(type, id); assertEquals(field.type, TFieldData.getType(data)); assertEquals(field.id, TFieldData.getId(data)); } } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/ThriftStructProcessorTest.java0000644000000000000000000002553714303740367032314 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.thrift.TBase; import org.apache.thrift.TException; import org.apache.thrift.TFieldIdEnum; import org.junit.jupiter.api.Test; public class ThriftStructProcessorTest { private PartialThriftTestData testData = new PartialThriftTestData(); @Test public void testStruct() throws TException { List fields = ThriftField.fromNames(Collections.singletonList("i32Field")); ThriftMetadata.ThriftStruct metadata = ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, fields); ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.createNewStruct(metadata); assertNotNull(instance); assertTrue(instance instanceof TBase); assertTrue(instance instanceof TestStruct); Object instance2 = processor.prepareStruct(instance); assertSame(instance, instance2); } @Test public void testList() throws TException { final int numItems = 10; ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.createNewList(numItems); assertNotNull(instance); assertTrue(instance instanceof Object[]); Object[] items = (Object[]) instance; for (int i = 0; i < numItems; i++) { assertNull(items[i]); processor.setListElement(instance, i, Integer.valueOf(i)); assertEquals(i, items[i]); } assertTrue(processor.prepareList(instance) instanceof List); } @Test public void testMap() throws TException { final int numItems = 10; ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.createNewMap(numItems); assertNotNull(instance); assertTrue(instance instanceof Map); Map items = (Map) instance; int ignoredIndex = -1; for (int i = 0; i < numItems; i++) { assertNull(items.get(i)); processor.setMapElement(instance, ignoredIndex, Integer.valueOf(i), Integer.valueOf(i)); assertEquals(i, items.get(i)); } assertTrue(processor.prepareMap(instance) instanceof Map); } @Test public void testSet() throws TException { final int numItems = 10; ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.createNewSet(numItems); assertNotNull(instance); assertTrue(instance instanceof HashSet); Set items = (HashSet) instance; int ignoredIndex = -1; for (int i = 0; i < numItems; i++) { assertFalse(items.contains(i)); processor.setSetElement(instance, ignoredIndex, Integer.valueOf(i)); assertTrue(items.contains(i)); } assertTrue(processor.prepareSet(instance) instanceof Set); } @Test public void testPrepareEnum() throws TException { ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.prepareEnum(TstEnum.class, 1); assertNotNull(instance); assertEquals(TstEnum.E_ONE, instance); instance = processor.prepareEnum(TstEnum.class, 2); assertNotNull(instance); assertEquals(TstEnum.E_TWO, instance); } @Test public void testPrepareString() throws TException { ThriftStructProcessor processor = new ThriftStructProcessor(); ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]); Object instance = processor.prepareString(emptyBuffer); assertNotNull(instance); assertTrue(instance instanceof String); assertEquals("", instance); String value = "Hello world!"; ByteBuffer buffer = ByteBuffer.wrap(value.getBytes(StandardCharsets.UTF_8)); instance = processor.prepareString(buffer); assertNotNull(instance); assertTrue(instance instanceof String); assertEquals(value, instance); } @Test public void testPrepareBinary() throws TException { ThriftStructProcessor processor = new ThriftStructProcessor(); ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]); Object instance = processor.prepareBinary(emptyBuffer); assertNotNull(instance); assertTrue(instance instanceof ByteBuffer); assertSame(emptyBuffer, instance); } @Test public void testStructPrimitiveFields() throws TException { List fields = ThriftField.fromNames( Arrays.asList( "byteField", "i16Field", "i32Field", "i64Field", "doubleField", "stringField", "enumField", "binaryField")); ThriftMetadata.ThriftStruct metadata = ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, fields); ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.createNewStruct(metadata); assertNotNull(instance); assertTrue(instance instanceof TBase); assertTrue(instance instanceof TestStruct); TestStruct struct = (TestStruct) instance; // byte TFieldIdEnum fieldId = findFieldId(metadata, "byteField"); assertNull(getFieldValue(struct, fieldId)); processor.setByte(struct, fieldId, (byte) 42); assertEquals(42, struct.getByteField()); // short fieldId = findFieldId(metadata, "i16Field"); assertNull(getFieldValue(struct, fieldId)); processor.setInt16(struct, fieldId, (short) 42); assertEquals(42, struct.getI16Field()); // int fieldId = findFieldId(metadata, "i32Field"); assertNull(getFieldValue(struct, fieldId)); processor.setInt32(struct, fieldId, 42); assertEquals(42, struct.getI32Field()); // long fieldId = findFieldId(metadata, "i64Field"); assertNull(getFieldValue(struct, fieldId)); processor.setInt64(struct, fieldId, 42L); assertEquals(42, struct.getI64Field()); // binary fieldId = findFieldId(metadata, "binaryField"); assertNull(getFieldValue(struct, fieldId)); byte[] noBytes = new byte[0]; ByteBuffer emptyBuffer = ByteBuffer.wrap(noBytes); processor.setBinary(struct, fieldId, emptyBuffer); assertArrayEquals(noBytes, struct.getBinaryField()); // string fieldId = findFieldId(metadata, "stringField"); assertNull(getFieldValue(struct, fieldId)); String value = "Hello world!"; ByteBuffer buffer = ByteBuffer.wrap(value.getBytes(StandardCharsets.UTF_8)); processor.setString(struct, fieldId, buffer); assertEquals(value, struct.getStringField()); // enum fieldId = findFieldId(metadata, "enumField"); assertNull(getFieldValue(struct, fieldId)); TstEnum e1 = TstEnum.E_ONE; processor.setEnumField(struct, fieldId, e1); assertEquals(TstEnum.E_ONE, struct.getEnumField()); } @Test public void testStructContainerFields() throws TException { List fields = ThriftField.fromNames( Arrays.asList( // List field "i32List", // Set field "stringSet", // Map field "stringMap", // Struct field "structField")); ThriftMetadata.ThriftStruct metadata = ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, fields); ThriftStructProcessor processor = new ThriftStructProcessor(); Object instance = processor.createNewStruct(metadata); assertNotNull(instance); assertTrue(instance instanceof TBase); assertTrue(instance instanceof TestStruct); TestStruct struct = (TestStruct) instance; // list TFieldIdEnum fieldId = findFieldId(metadata, "i32List"); assertNull(getFieldValue(struct, fieldId)); Integer[] ints = new Integer[] {1, 2, 3}; List intList = Arrays.asList(ints); processor.setListField(struct, fieldId, intList); assertArrayEquals(ints, struct.getI32List().toArray()); // set fieldId = findFieldId(metadata, "stringSet"); assertNull(getFieldValue(struct, fieldId)); String[] strings = new String[] {"Hello", "World!"}; Set stringSet = new HashSet<>(Arrays.asList(strings)); processor.setSetField(struct, fieldId, stringSet); assertEquals(stringSet, struct.getStringSet()); // map fieldId = findFieldId(metadata, "stringMap"); assertNull(getFieldValue(struct, fieldId)); Map stringMap = new HashMap<>(); stringMap.put("foo", "bar"); stringMap.put("Hello", "World!"); processor.setMapField(struct, fieldId, stringMap); assertEquals(stringMap, struct.getStringMap()); // struct fieldId = findFieldId(metadata, "structField"); assertNull(getFieldValue(struct, fieldId)); SmallStruct smallStruct = new SmallStruct(); smallStruct.setI32Field(42); SmallStruct smallStruct2 = new SmallStruct(); smallStruct2.setI32Field(42); processor.setStructField(struct, fieldId, smallStruct); assertEquals(smallStruct2, struct.getStructField()); } private TFieldIdEnum findFieldId(ThriftMetadata.ThriftStruct metadata, String fieldName) { Collection fields = metadata.fields.values(); for (ThriftMetadata.ThriftObject field : fields) { if (fieldName.equalsIgnoreCase(field.fieldId.getFieldName())) { return field.fieldId; } } throw new IllegalStateException("Field not found: " + fieldName); } private Object getFieldValue(TBase struct, TFieldIdEnum fieldId) { TFieldIdEnum fieldRef = struct.fieldForId(fieldId.getThriftFieldId()); if (struct.isSet(fieldRef)) { return struct.getFieldValue(fieldRef); } else { return null; } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/TestData.java0000644000000000000000000000370414303740367026610 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** Frequently used test data items. */ public final class TestData { private TestData() {} // Array data. public static Object[] nullArray = null; public static Object[] emptyArray = new Object[0]; public static Object[] nonEmptyArray = new Object[1]; public static byte[] nullByteArray = null; public static byte[] emptyByteArray = new byte[0]; public static byte[] nonEmptyByteArray = new byte[1]; public static short[] nullShortArray = null; public static short[] emptyShortArray = new short[0]; public static short[] nonEmptyShortArray = new short[1]; public static int[] nullIntArray = null; public static int[] emptyIntArray = new int[0]; public static int[] nonEmptyIntArray = new int[1]; public static long[] nullLongArray = null; public static long[] emptyLongArray = new long[0]; public static long[] nonEmptyLongArray = new long[1]; public static List nullList = null; public static List emptyList = new ArrayList(); public static List validList = Arrays.asList(new Object[1]); } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/ThriftFieldTest.java0000644000000000000000000001064614303740367030146 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.junit.jupiter.api.Test; public class ThriftFieldTest { @Test public void testArgChecks() { ThriftField test; List testFields; // Should not throw. test = new ThriftField("foo"); test = new ThriftField("foo", Collections.singletonList(new ThriftField("bar"))); testFields = ThriftField.fromNames(Collections.singletonList("foo")); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> new ThriftField(null, Collections.emptyList()), "'name' must not be null"); assertThrows( IllegalArgumentException.class, () -> new ThriftField("foo", null), "'fields' must not be null"); assertThrows( IllegalArgumentException.class, () -> ThriftField.fromNames(null), "'fieldNames' must not be null"); assertThrows( IllegalArgumentException.class, () -> ThriftField.fromNames(Collections.emptyList()), "'fieldNames' must have at least one element"); } @Test public void testFromNames() { List fieldNames = Arrays.asList("f1", "f2.f21", "f3.f31.f311", "f3.f32.f321", "f3.f32.f322"); List testFields = ThriftField.fromNames(fieldNames); assertEquals(3, testFields.size()); ThriftField f1 = testFields.get(0); ThriftField f2 = testFields.get(1); ThriftField f3 = testFields.get(2); assertEquals("f1", f1.name); assertEquals("f2", f2.name); assertEquals("f3", f3.name); assertEquals(0, f1.fields.size()); assertEquals(1, f2.fields.size()); assertEquals(2, f3.fields.size()); ThriftField f21 = f2.fields.get(0); ThriftField f31 = f3.fields.get(0); ThriftField f32 = f3.fields.get(1); assertEquals("f21", f21.name); assertEquals("f31", f31.name); assertEquals("f32", f32.name); assertEquals(0, f21.fields.size()); assertEquals(1, f31.fields.size()); assertEquals(2, f32.fields.size()); ThriftField f311 = f31.fields.get(0); ThriftField f321 = f32.fields.get(0); ThriftField f322 = f32.fields.get(1); assertEquals("f311", f311.name); assertEquals("f321", f321.name); assertEquals("f322", f322.name); assertEquals(0, f311.fields.size()); assertEquals(0, f321.fields.size()); assertEquals(0, f322.fields.size()); } @Test public void testEquality() { List fieldNames = Arrays.asList("f1", "f2.f21", "f3.f31.f311", "f3.f32.f321", "f3.f32.f322"); List testFields = ThriftField.fromNames(fieldNames); List testFields2 = testFields; assertSame(testFields, testFields2); assertEquals(testFields, testFields2); List testFields3 = ThriftField.fromNames(fieldNames); assertNotSame(testFields, testFields3); assertEquals(testFields, testFields3); assertEquals(testFields.hashCode(), testFields3.hashCode()); List fieldNamesDiff = Arrays.asList("f1", "f2.f21", "f3.f31.f311", "f3.f32.f323", "f3.f32.f322"); List testFields4 = ThriftField.fromNames(fieldNamesDiff); assertNotSame(testFields, testFields4); assertNotEquals(testFields, testFields4); assertNotEquals(testFields.hashCode(), testFields4.hashCode()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/PartialThriftComparerTest.java0000644000000000000000000000500614303740367032202 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.Arrays; import java.util.List; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.junit.jupiter.api.Test; public class PartialThriftComparerTest { private ThriftSerDe serde; private PartialThriftTestData testData = new PartialThriftTestData(); public PartialThriftComparerTest() throws TException { this.serde = new ThriftSerDe(); } @Test public void testCompareSimple() throws TException, IOException { TestStruct ts1 = testData.createTestStruct(1, 1); assertTrue(ts1.isSetI16Field()); assertTrue(ts1.isSetI32Field()); byte[] bytesBinary = serde.serializeBinary(ts1); byte[] bytesCompact = serde.serializeCompact(ts1); List fieldNames = Arrays.asList("i32Field"); TDeserializer partialBinaryDeser = new TDeserializer(TestStruct.class, fieldNames, new TBinaryProtocol.Factory()); TDeserializer partialCompactDeser = new TDeserializer(TestStruct.class, fieldNames, new TCompactProtocol.Factory()); ThriftMetadata.ThriftStruct metadata = partialBinaryDeser.getMetadata(); PartialThriftComparer comparer = new PartialThriftComparer(metadata); StringBuilder sb = new StringBuilder(); TestStruct ts2 = (TestStruct) partialBinaryDeser.partialDeserializeObject(bytesBinary); assertTrue(comparer.areEqual(ts1, ts2, sb), sb::toString); ts2 = (TestStruct) partialCompactDeser.partialDeserializeObject(bytesCompact); assertTrue(comparer.areEqual(ts1, ts2, sb), sb::toString); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/ThriftMetadataTest.java0000644000000000000000000002531214303740367030637 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Arrays; import java.util.List; import org.apache.thrift.TBase; import org.apache.thrift.meta_data.EnumMetaData; import org.apache.thrift.meta_data.FieldValueMetaData; import org.apache.thrift.meta_data.ListMetaData; import org.apache.thrift.meta_data.MapMetaData; import org.apache.thrift.meta_data.SetMetaData; import org.apache.thrift.meta_data.StructMetaData; import org.apache.thrift.protocol.TType; import org.junit.jupiter.api.Test; public class ThriftMetadataTest { private PartialThriftTestData testData = new PartialThriftTestData(); @Test public void testArgChecks() { // Should not throw. List testFields = ThriftField.fromNames(Arrays.asList("byteField")); ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, testFields); // Verify it throws correctly. assertThrows( IllegalArgumentException.class, () -> ThriftMetadata.ThriftStruct.fromFields(null, testFields), "'clasz' must not be null"); assertThrows( IllegalArgumentException.class, () -> ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, null), "'fields' must not be null"); } @Test public void testThriftStructOf() { ThriftMetadata.ThriftStruct testStruct = ThriftMetadata.ThriftStruct.of(TestStruct.class); assertEquals(45, testStruct.fields.keySet().size()); validateFieldMetadata(testStruct, 1, "byteField", TType.BYTE); validateFieldMetadata(testStruct, 2, "i16Field", TType.I16); validateFieldMetadata(testStruct, 3, "i32Field", TType.I32); validateFieldMetadata(testStruct, 4, "i64Field", TType.I64); validateFieldMetadata(testStruct, 5, "doubleField", TType.DOUBLE); validateFieldMetadata(testStruct, 6, "stringField", TType.STRING); validateFieldMetadata(testStruct, 7, "enumField", TType.ENUM); validateFieldMetadata(testStruct, 8, "binaryField", TType.STRING); validateListFieldMetadata(testStruct, 10, "byteList", TType.BYTE); validateSetFieldMetadata(testStruct, 35, "stringSet", TType.STRING); validateMapFieldMetadata(testStruct, 61, "binaryMap", TType.I32, TType.STRING); } @Test public void testUnion() { ThriftMetadata.ThriftStruct structWithUnions = ThriftMetadata.ThriftStruct.of(StructWithUnions.class); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 1, "intValue"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 2, "smallStruct"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 3, "simpleUnion"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 4, "unionList"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 5, "unionSet"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 6, "keyUnionMap"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 7, "valUnionMap"); validateBasicFieldMetadata(structWithUnions, StructWithUnions.class, 8, "unionMap"); ThriftMetadata.ThriftStructBase smallStructMetadata = (ThriftMetadata.ThriftStructBase) structWithUnions.fields.get(2); assertFalse(smallStructMetadata.isUnion()); ThriftMetadata.ThriftStructBase simpleUnionMetadata = (ThriftMetadata.ThriftStructBase) structWithUnions.fields.get(3); assertTrue(simpleUnionMetadata.isUnion()); ThriftMetadata.ThriftList unionListMetadata = (ThriftMetadata.ThriftList) structWithUnions.fields.get(4); assertTrue(unionListMetadata.hasUnion()); ThriftMetadata.ThriftSet unionSetMetadata = (ThriftMetadata.ThriftSet) structWithUnions.fields.get(5); assertTrue(unionSetMetadata.hasUnion()); ThriftMetadata.ThriftMap keyUnionMapMetadata = (ThriftMetadata.ThriftMap) structWithUnions.fields.get(6); assertTrue(keyUnionMapMetadata.hasUnion()); ThriftMetadata.ThriftMap valUnionMapMetadata = (ThriftMetadata.ThriftMap) structWithUnions.fields.get(7); assertTrue(valUnionMapMetadata.hasUnion()); ThriftMetadata.ThriftMap unionMapMetadata = (ThriftMetadata.ThriftMap) structWithUnions.fields.get(8); assertTrue(unionMapMetadata.hasUnion()); } private ThriftMetadata.ThriftObject validateBasicFieldMetadata( ThriftMetadata.ThriftStruct testStruct, int id, String fieldName) { return validateBasicFieldMetadata(testStruct, TestStruct.class, id, fieldName); } private ThriftMetadata.ThriftObject validateBasicFieldMetadata( ThriftMetadata.ThriftStruct testStruct, Class clazz, int id, String fieldName) { assertNotNull(testStruct); assertNull(testStruct.parent); assertEquals(clazz, ((StructMetaData) testStruct.data.valueMetaData).structClass); assertTrue(testStruct.fields.containsKey(id)); ThriftMetadata.ThriftObject fieldMetadata = (ThriftMetadata.ThriftObject) testStruct.fields.get(id); assertEquals(testStruct, fieldMetadata.parent); assertEquals(id, fieldMetadata.fieldId.getThriftFieldId()); assertEquals(fieldName, fieldMetadata.fieldId.getFieldName()); assertEquals(fieldName, fieldMetadata.data.fieldName); assertEquals("root ==> " + fieldName, fieldMetadata.toString()); return fieldMetadata; } private void validateBasicFieldValueMetadata( ThriftMetadata.ThriftObject fieldMetadata, String fieldName, byte ttype) { assertEquals(ttype, fieldMetadata.data.valueMetaData.type); assertEquals(getMetaDataClassForTType(ttype), fieldMetadata.data.valueMetaData.getClass()); Class fieldMetadataClass = getClassForTType(ttype); assertEquals(fieldMetadataClass, fieldMetadata.getClass()); if (fieldMetadataClass == ThriftMetadata.ThriftPrimitive.class) { ThriftMetadata.ThriftPrimitive primitive = (ThriftMetadata.ThriftPrimitive) fieldMetadata; if (fieldName.startsWith("binary") && (ttype == TType.STRING)) { assertTrue(primitive.isBinary()); } else { assertFalse(primitive.isBinary()); } } } private void validateFieldMetadata( ThriftMetadata.ThriftStruct testStruct, int id, String fieldName, byte ttype) { ThriftMetadata.ThriftObject fieldMetadata = validateBasicFieldMetadata(testStruct, id, fieldName); validateBasicFieldValueMetadata(fieldMetadata, fieldName, ttype); } private void validateListFieldMetadata( ThriftMetadata.ThriftStruct testStruct, int id, String fieldName, byte ttype) { ThriftMetadata.ThriftObject fieldMetadata = validateBasicFieldMetadata(testStruct, id, fieldName); validateBasicFieldValueMetadata(fieldMetadata, fieldName, TType.LIST); ThriftMetadata.ThriftList thriftList = (ThriftMetadata.ThriftList) fieldMetadata; ThriftMetadata.ThriftObject elementMetadata = thriftList.elementData; validateBasicFieldValueMetadata(elementMetadata, fieldName + "_element", ttype); } private void validateSetFieldMetadata( ThriftMetadata.ThriftStruct testStruct, int id, String fieldName, byte ttype) { ThriftMetadata.ThriftObject fieldMetadata = validateBasicFieldMetadata(testStruct, id, fieldName); validateBasicFieldValueMetadata(fieldMetadata, fieldName, TType.SET); ThriftMetadata.ThriftSet thriftSet = (ThriftMetadata.ThriftSet) fieldMetadata; ThriftMetadata.ThriftObject elementMetadata = thriftSet.elementData; validateBasicFieldValueMetadata(elementMetadata, fieldName + "_element", ttype); } private void validateMapFieldMetadata( ThriftMetadata.ThriftStruct testStruct, int id, String fieldName, byte keyType, byte valueType) { ThriftMetadata.ThriftObject fieldMetadata = validateBasicFieldMetadata(testStruct, id, fieldName); validateBasicFieldValueMetadata(fieldMetadata, fieldName, TType.MAP); ThriftMetadata.ThriftMap thriftMap = (ThriftMetadata.ThriftMap) fieldMetadata; ThriftMetadata.ThriftObject keyMetadata = thriftMap.keyData; ThriftMetadata.ThriftObject valueMetadata = thriftMap.valueData; validateBasicFieldValueMetadata(keyMetadata, fieldName + "_key", keyType); validateBasicFieldValueMetadata(valueMetadata, fieldName + "_value", valueType); } private Class getMetaDataClassForTType(byte ttype) { switch (ttype) { case TType.STRUCT: return StructMetaData.class; case TType.LIST: return ListMetaData.class; case TType.MAP: return MapMetaData.class; case TType.SET: return SetMetaData.class; case TType.ENUM: return EnumMetaData.class; case TType.BOOL: case TType.BYTE: case TType.I16: case TType.I32: case TType.I64: case TType.DOUBLE: case TType.STRING: return FieldValueMetaData.class; default: throw ThriftMetadata.unsupportedFieldTypeException(ttype); } } private Class getClassForTType(byte ttype) { switch (ttype) { case TType.STRUCT: return ThriftMetadata.ThriftStruct.class; case TType.LIST: return ThriftMetadata.ThriftList.class; case TType.MAP: return ThriftMetadata.ThriftMap.class; case TType.SET: return ThriftMetadata.ThriftSet.class; case TType.ENUM: return ThriftMetadata.ThriftEnum.class; case TType.BOOL: case TType.BYTE: case TType.I16: case TType.I32: case TType.I64: case TType.DOUBLE: case TType.STRING: return ThriftMetadata.ThriftPrimitive.class; default: throw ThriftMetadata.unsupportedFieldTypeException(ttype); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/PartialThriftTestData.java0000644000000000000000000002300614303740367031303 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; /** Helpers for creating test data related to partial deserialization. */ public class PartialThriftTestData { public final byte[] BYTES = new byte[] {1, 2, 3}; public SmallStruct createSmallStruct(int id) { return new SmallStruct() .setByteField((byte) id) .setI16Field((short) id) .setI32Field(id) .setI64Field(id) .setDoubleField(id) .setStringField(Integer.toString(id)) .setEnumField(TstEnum.E_ONE); } public TestStruct createTestStruct(int id, int numItems) { TestStruct ts = new TestStruct() .setByteField((byte) id) .setI16Field((short) id) .setI32Field(id) .setI64Field(id) .setDoubleField(id) .setStringField(Integer.toString(id)) .setEnumField(TstEnum.E_ONE) .setBinaryField(BYTES) .setStructField(createSmallStruct(id)); initListFields(ts, id, numItems); initSetFields(ts, id, numItems); initMapFields(ts, id, numItems); return ts; } public void initListFields(TestStruct ts, int id, int numItems) { List byteList = new ArrayList<>(numItems); List i16List = new ArrayList<>(numItems); List i32List = new ArrayList<>(numItems); List i64List = new ArrayList<>(numItems); List doubleList = new ArrayList<>(numItems); List stringList = new ArrayList<>(numItems); List enumList = new ArrayList<>(numItems); List> listList = new ArrayList<>(numItems); List> setList = new ArrayList<>(numItems); List> mapList = new ArrayList<>(numItems); List structList = new ArrayList<>(numItems); List binaryList = new ArrayList<>(numItems); for (int i = 0; i < numItems; i++) { byteList.add((byte) i); i16List.add((short) i); i32List.add(i); i64List.add((long) i); doubleList.add((double) i); stringList.add(Integer.toString(i)); enumList.add(TstEnum.E_ONE); structList.add(createSmallStruct(i)); binaryList.add(ByteBuffer.wrap(BYTES)); List listItem = new ArrayList<>(numItems); listList.add(listItem); Set setItem = new HashSet<>(); setList.add(setItem); Map mapItem = new HashMap<>(); mapList.add(mapItem); for (int j = 0; j < numItems; j++) { listItem.add(j); setItem.add(j); mapItem.put(Integer.toString(j), j); } } ts.setByteList(byteList) .setI16List(i16List) .setI32List(i32List) .setI64List(i64List) .setDoubleList(doubleList) .setStringList(stringList) .setEnumList(enumList) .setListList(listList) .setSetList(setList) .setMapList(mapList) .setStructList(structList) .setBinaryList(binaryList); } public void initSetFields(TestStruct ts, int id, int numItems) { Set byteSet = new HashSet<>(); Set i16Set = new HashSet<>(); Set i32Set = new HashSet<>(); Set i64Set = new HashSet<>(); Set doubleSet = new HashSet<>(); Set stringSet = new HashSet<>(); Set enumSet = new HashSet<>(); Set> listSet = new HashSet<>(); Set> setSet = new HashSet<>(); Set> mapSet = new HashSet<>(); Set structSet = new HashSet<>(); Set binarySet = new HashSet<>(); for (int i = 0; i < numItems; i++) { byteSet.add((byte) i); i16Set.add((short) i); i32Set.add(i); i64Set.add((long) i); doubleSet.add((double) i); stringSet.add(Integer.toString(i)); enumSet.add(TstEnum.E_ONE); structSet.add(createSmallStruct(i)); binarySet.add(ByteBuffer.wrap(BYTES)); List listItem = new ArrayList<>(numItems); Set setItem = new HashSet<>(); Map mapItem = new HashMap<>(); for (int j = 0; j < numItems; j++) { setItem.add(j); listItem.add(j); mapItem.put(Integer.toString(j), j); } listSet.add(listItem); setSet.add(setItem); mapSet.add(mapItem); } ts.setByteSet(byteSet) .setI16Set(i16Set) .setI32Set(i32Set) .setI64Set(i64Set) .setDoubleSet(doubleSet) .setStringSet(stringSet) .setEnumSet(enumSet) .setListSet(listSet) .setSetSet(setSet) .setMapSet(mapSet) .setStructSet(structSet) .setBinarySet(binarySet); } public void initMapFields(TestStruct ts, int id, int numItems) { Map byteMap = new HashMap<>(); Map i16Map = new HashMap<>(); Map i32Map = new HashMap<>(); Map i64Map = new HashMap<>(); Map doubleMap = new HashMap<>(); Map stringMap = new HashMap<>(); Map enumMap = new HashMap<>(); Map> listMap = new HashMap<>(); Map> setMap = new HashMap<>(); Map> mapMap = new HashMap<>(); Map structMap = new HashMap<>(); Map binaryMap = new HashMap<>(); for (int i = 0; i < numItems; i++) { byteMap.put((byte) i, (byte) i); i16Map.put((short) i, (short) i); i32Map.put(i, i); i64Map.put((long) i, (long) i); doubleMap.put((double) i, (double) i); stringMap.put(Integer.toString(i), Integer.toString(i)); enumMap.put(TstEnum.E_ONE, TstEnum.E_ONE); structMap.put(createSmallStruct(i), createSmallStruct(i)); binaryMap.put(i, ByteBuffer.wrap(BYTES)); List listItem = new ArrayList<>(numItems); listMap.put(i, listItem); Set setItem = new HashSet<>(); setMap.put(i, setItem); Map mapItem = new HashMap<>(); mapMap.put(i, mapItem); for (int j = 0; j < numItems; j++) { listItem.add(j); setItem.add(j); mapItem.put(j, j); } } ts.setByteMap(byteMap) .setI16Map(i16Map) .setI32Map(i32Map) .setI64Map(i64Map) .setDoubleMap(doubleMap) .setStringMap(stringMap) .setEnumMap(enumMap) .setListMap(listMap) .setSetMap(setMap) .setMapMap(mapMap) .setStructMap(structMap) .setBinaryMap(binaryMap); } public List allFieldsOfTestStruct() { return new ArrayList<>( Arrays.asList( "byteField", "i16Field", "i32Field", "i64Field", "doubleField", "stringField", "structField.byteField", "structField.i16Field", "structField.i32Field", "structField.i64Field", "structField.doubleField", "structField.stringField", "structField.enumField", "enumField", "binaryField", "byteList", "i16List", "i32List", "i64List", "doubleList", "stringList", "enumList", "listList", "setList", "mapList", "structList.byteField", "structList.i16Field", "structList.i32Field", "structList.i64Field", "structList.doubleField", "structList.stringField", "structList.enumField", "binaryList", "byteSet", "i16Set", "i32Set", "i64Set", "doubleSet", "stringSet", "enumSet", "listSet", "setSet", "mapSet", "structSet.byteField", "structSet.i16Field", "structSet.i32Field", "structSet.i64Field", "structSet.doubleField", "structSet.stringField", "structSet.enumField", "binarySet", "byteMap", "i16Map", "i32Map", "i64Map", "doubleMap", "stringMap", "enumMap", "listMap", "setMap", "mapMap", "structMap.byteField", "structMap.i16Field", "structMap.i32Field", "structMap.i64Field", "structMap.doubleField", "structMap.stringField", "structMap.enumField", "binaryMap")); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/ValidateTest.java0000644000000000000000000002341614303740367027472 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import org.junit.jupiter.api.Test; public class ValidateTest { @Test public void testCheckNotNull() { String nonNullArg = "nonNullArg"; String nullArg = null; // Should not throw. Validate.checkNotNull(nonNullArg, "nonNullArg"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNull(nullArg, "nullArg"), "'nullArg' must not be null"); } @Test public void testCheckPositiveInteger() { int positiveArg = 1; int zero = 0; int negativeArg = -1; // Should not throw. Validate.checkPositiveInteger(positiveArg, "positiveArg"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkPositiveInteger(negativeArg, "negativeArg"), "'negativeArg' must be a positive integer"); assertThrows( IllegalArgumentException.class, () -> Validate.checkPositiveInteger(zero, "zero"), "'zero' must be a positive integer"); } @Test public void testCheckNotNegative() { int positiveArg = 1; int zero = 0; int negativeArg = -1; // Should not throw. Validate.checkNotNegative(zero, "zeroArg"); Validate.checkNotNegative(positiveArg, "positiveArg"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNegative(negativeArg, "negativeArg"), "'negativeArg' must not be negative"); } @Test public void testCheckRequired() { // Should not throw. Validate.checkRequired(true, "arg"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkRequired(false, "arg"), "'arg' is required"); } @Test public void testCheckValid() { // Should not throw. Validate.checkValid(true, "arg"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkValid(false, "arg"), "'arg' is invalid"); } @Test public void testCheckValidWithValues() { String validValues = "foo, bar"; // Should not throw. Validate.checkValid(true, "arg", validValues); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkValid(false, "arg", validValues), "'arg' is invalid. Valid values are: foo, bar"); } @Test public void testCheckNotNullAndNotEmpty() { // Should not throw. Validate.checkNotNullAndNotEmpty(TestData.nonEmptyArray, "array"); Validate.checkNotNullAndNotEmpty(TestData.nonEmptyByteArray, "array"); Validate.checkNotNullAndNotEmpty(TestData.nonEmptyShortArray, "array"); Validate.checkNotNullAndNotEmpty(TestData.nonEmptyIntArray, "array"); Validate.checkNotNullAndNotEmpty(TestData.nonEmptyLongArray, "array"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty("", "string"), "'string' must not be empty"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.nullArray, "array"), "'array' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.emptyArray, "array"), "'array' must have at least one element"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.nullByteArray, "array"), "'array' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.emptyByteArray, "array"), "'array' must have at least one element"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.nullShortArray, "array"), "'array' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.emptyShortArray, "array"), "'array' must have at least one element"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.nullIntArray, "array"), "'array' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.emptyIntArray, "array"), "'array' must have at least one element"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.nullLongArray, "array"), "'array' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.emptyLongArray, "array"), "'array' must have at least one element"); } @Test public void testCheckListNotNullAndNotEmpty() { // Should not throw. Validate.checkNotNullAndNotEmpty(TestData.validList, "list"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.nullList, "list"), "'list' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNotEmpty(TestData.emptyList, "list"), "'list' must have at least one element"); } @Test public void testCheckNotNullAndNumberOfElements() { // Should not throw. Validate.checkNotNullAndNumberOfElements(Arrays.asList(1, 2, 3), 3, "arg"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNumberOfElements(null, 3, "arg"), "'arg' must not be null"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkNotNullAndNumberOfElements(Arrays.asList(1, 2), 3, "arg"), "Number of elements in 'arg' must be exactly 3, 2 given."); } @Test public void testCheckValuesEqual() { // Should not throw. Validate.checkValuesEqual(1, "arg1", 1, "arg2"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkValuesEqual(1, "arg1", 2, "arg2"), "'arg1' (1) must equal 'arg2' (2)"); } @Test public void testCheckIntegerMultiple() { // Should not throw. Validate.checkIntegerMultiple(10, "arg1", 5, "arg2"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkIntegerMultiple(10, "arg1", 3, "arg2"), "'arg1' (10) must be an integer multiple of 'arg2' (3)"); } @Test public void testCheckGreater() { // Should not throw. Validate.checkGreater(10, "arg1", 5, "arg2"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkGreater(5, "arg1", 10, "arg2"), "'arg1' (5) must be greater than 'arg2' (10)"); } @Test public void testCheckGreaterOrEqual() { // Should not throw. Validate.checkGreaterOrEqual(10, "arg1", 5, "arg2"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkGreaterOrEqual(5, "arg1", 10, "arg2"), "'arg1' (5) must be greater than or equal to 'arg2' (10)"); } @Test public void testCheckWithinRange() { // Should not throw. Validate.checkWithinRange(10, "arg", 5, 15); Validate.checkWithinRange(10.0, "arg", 5.0, 15.0); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkWithinRange(5, "arg", 10, 20), "'arg' (5) must be within the range [10, 20]"); assertThrows( IllegalArgumentException.class, () -> Validate.checkWithinRange(5.0, "arg", 10.0, 20.0), "'arg' (5.0) must be within the range [10.0, 20.0]"); } @Test public void testCheckPathExists() throws IOException { Path tempFile = Files.createTempFile("foo", "bar"); Path tempDir = tempFile.getParent(); Path notFound = Paths.get(""); // Should not throw. Validate.checkPathExists(tempFile, "tempFile"); Validate.checkPathExists(tempDir, "tempDir"); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> Validate.checkPathExists(null, "nullArg"), "'nullArg' must not be null"); assertThrows( IllegalArgumentException.class, () -> Validate.checkPathExists(notFound, "notFound"), "Path notFound () does not exist"); assertThrows( IllegalArgumentException.class, () -> Validate.checkPathExistsAsDir(tempFile, "tempFile"), "must point to a directory"); assertThrows( IllegalArgumentException.class, () -> Validate.checkPathExistsAsFile(tempDir, "tempDir"), "must point to a file"); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/TestPartialThriftDeserializer.java0000644000000000000000000004511414303740367033060 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.junit.jupiter.api.Test; public class TestPartialThriftDeserializer { private ThriftSerDe serde = new ThriftSerDe(); private TBinaryProtocol.Factory binaryProtocolFactory = new TBinaryProtocol.Factory(); private TCompactProtocol.Factory compactProtocolFactory = new TCompactProtocol.Factory(); private PartialThriftTestData testData = new PartialThriftTestData(); public TestPartialThriftDeserializer() throws TException {} @Test public void testArgChecks() throws TException { // Should not throw. List fieldNames = Collections.singletonList("i32Field"); new TDeserializer(TestStruct.class, fieldNames, binaryProtocolFactory); // Verify it throws correctly. assertThrows( IllegalArgumentException.class, () -> new TDeserializer(null, fieldNames, binaryProtocolFactory), "'thriftClass' must not be null"); assertThrows( IllegalArgumentException.class, () -> new TDeserializer(TestStruct.class, null, binaryProtocolFactory), "'fieldNames' must not be null"); assertThrows( IllegalArgumentException.class, () -> new TDeserializer(TestStruct.class, fieldNames, null, binaryProtocolFactory), "'processor' must not be null"); } /** * This test does not use partial deserialization. It is used to establish correctness of full * serialization used in the other tests. */ @Test public void testRoundTripFull() throws TException { TestStruct ts1 = testData.createTestStruct(1, 2); byte[] bytesBinary = serde.serializeBinary(ts1); byte[] bytesCompact = serde.serializeCompact(ts1); TestStruct ts2 = serde.deserializeBinary(bytesBinary, TestStruct.class); assertEquals(ts1, ts2); ts2 = serde.deserializeCompact(bytesCompact, TestStruct.class); assertEquals(ts1, ts2); } @Test public void testPartialSimpleField() throws TException, IOException { TestStruct ts1 = testData.createTestStruct(1, 1); assertTrue(ts1.isSetI16Field()); assertTrue(ts1.isSetI32Field()); byte[] bytesBinary = serde.serializeBinary(ts1); byte[] bytesCompact = serde.serializeCompact(ts1); List fieldNames = Arrays.asList("i32Field"); TDeserializer partialBinaryDeserializer = new TDeserializer(TestStruct.class, fieldNames, binaryProtocolFactory); TDeserializer partialCompactDeserializer = new TDeserializer(TestStruct.class, fieldNames, compactProtocolFactory); PartialThriftComparer comparer = new PartialThriftComparer(partialBinaryDeserializer.getMetadata()); StringBuilder sb = new StringBuilder(); TestStruct ts2 = (TestStruct) partialBinaryDeserializer.partialDeserializeObject(bytesBinary); validatePartialSimpleField(ts1, ts2); assertTrue(comparer.areEqual(ts1, ts2, sb), sb::toString); ts2 = (TestStruct) partialCompactDeserializer.partialDeserializeObject(bytesCompact); validatePartialSimpleField(ts1, ts2); assertTrue(comparer.areEqual(ts1, ts2, sb), sb::toString); } private void validatePartialSimpleField(TestStruct ts1, TestStruct ts2) { assertTrue(ts2.isSetI32Field(), ts2.toString()); assertEquals(ts1.getI32Field(), ts2.getI32Field()); assertFalse(ts2.isSetI16Field()); } @Test public void testPartialComplex() throws TException { int id = 1; int numItems = 10; TestStruct ts1 = testData.createTestStruct(id, numItems); byte[] bytesBinary = serde.serializeBinary(ts1); byte[] bytesCompact = serde.serializeCompact(ts1); List fieldNames = Arrays.asList( "byteField", "i16Field", "i32Field", "i64Field", "doubleField", "stringField", "enumField", "binaryField", // List fields "byteList", "i16List", "i32List", "i64List", "doubleList", "stringList", "enumList", "listList", "setList", "mapList", "structList", "binaryList", // Set fields "byteSet", "i16Set", "i32Set", "i64Set", "doubleSet", "stringSet", "enumSet", "listSet", "setSet", "mapSet", "structSet", "binarySet", // Map fields "byteMap", "i16Map", "i32Map", "i64Map", "doubleMap", "stringMap", "enumMap", "listMap", "setMap", "mapMap", "structMap", "binaryMap", // Struct field "structField"); StringBuilder sb = new StringBuilder(); TDeserializer partialBinaryDeserializer = new TDeserializer(TestStruct.class, fieldNames, binaryProtocolFactory); TDeserializer partialCompactDeserializer = new TDeserializer(TestStruct.class, fieldNames, compactProtocolFactory); PartialThriftComparer comparer = new PartialThriftComparer(partialBinaryDeserializer.getMetadata()); TestStruct ts2 = (TestStruct) partialBinaryDeserializer.partialDeserializeObject(bytesBinary); validatePartialComplex(ts1, ts2, id, numItems); assertTrue(comparer.areEqual(ts1, ts2, sb), sb::toString); ts2 = (TestStruct) partialCompactDeserializer.partialDeserializeObject(bytesCompact); validatePartialComplex(ts1, ts2, id, numItems); assertTrue(comparer.areEqual(ts1, ts2, sb), sb::toString); } private void validatePartialComplex(TestStruct ts1, TestStruct ts2, int id, int numItems) { // Validate primitive fields. assertTrue(ts2.isSetByteField(), ts2.toString()); assertEquals(ts1.getByteField(), ts2.getByteField()); assertTrue(ts2.isSetI16Field()); assertEquals(ts1.getI16Field(), ts2.getI16Field()); assertTrue(ts2.isSetI32Field()); assertEquals(ts1.getI32Field(), ts2.getI32Field()); assertTrue(ts2.isSetI64Field()); assertEquals(ts1.getI64Field(), ts2.getI64Field()); assertTrue(ts2.isSetDoubleField()); assertEquals(ts1.getDoubleField(), ts2.getDoubleField(), 0.0001); assertTrue(ts2.isSetStringField()); assertEquals(ts1.getStringField(), ts2.getStringField()); assertTrue(ts2.isSetEnumField()); assertEquals(ts1.getEnumField(), ts2.getEnumField()); assertTrue(ts2.isSetBinaryField()); assertArrayEquals(ts1.getBinaryField(), ts2.getBinaryField()); // Validate list fields. validateList(ts2.getByteList(), id, numItems); validateList(ts2.getI16List(), id, numItems); validateList(ts2.getI32List(), id, numItems); validateList(ts2.getI64List(), id, numItems); validateList(ts2.getDoubleList(), id, numItems); validateStringList(ts2.getStringList(), id, numItems); validateEnumList(ts2.getEnumList(), id, numItems); validateListOfList(ts2.getListList(), id, numItems); validateListOfSet(ts2.getSetList(), id, numItems); validateListOfMap(ts2.getMapList(), id, numItems); validateListOfStruct(ts2.getStructList(), id, numItems); validateListOfBinary(ts2.getBinaryList(), id, numItems); // Validate set fields. validateSet(ts2.getByteSet(), Byte.class, numItems); validateSet(ts2.getI16Set(), Short.class, numItems); validateSet(ts2.getI32Set(), Integer.class, numItems); validateSet(ts2.getI64Set(), Long.class, numItems); validateSet(ts2.getDoubleSet(), Double.class, numItems); validateStringSet(ts2.getStringSet(), id, numItems); validateEnumSet(ts2.getEnumSet(), id, numItems); validateSetOfList(ts2.getListSet(), id, numItems); validateSetOfSet(ts2.getSetSet(), id, numItems); validateSetOfMap(ts2.getMapSet(), id, numItems); validateSetOfStruct(ts2.getStructSet(), id, numItems); validateSetOfBinary(ts2.getBinarySet(), id, numItems); // Validate map fields. validateMap(ts2.getByteMap(), Byte.class, numItems); validateMap(ts2.getI16Map(), Short.class, numItems); validateMap(ts2.getI32Map(), Integer.class, numItems); validateMap(ts2.getI64Map(), Long.class, numItems); validateMap(ts2.getDoubleMap(), Double.class, numItems); validateStringMap(ts2.getStringMap(), id, numItems); validateEnumMap(ts2.getEnumMap(), id, numItems); validateMapOfList(ts2.getListMap(), id, numItems); validateMapOfSet(ts2.getSetMap(), id, numItems); validateMapOfMap(ts2.getMapMap(), id, numItems); validateMapOfStruct(ts2.getStructMap(), id, numItems); validateMapOfBinary(ts2.getBinaryMap(), id, numItems); // Validate struct field. assertEquals(testData.createSmallStruct(id), ts2.getStructField()); } private void validateNotNullAndNotEmpty(Collection collection, int numItems) { assertNotNull(collection); assertEquals(numItems, collection.size()); } // ---------------------------------------------------------------------- // List validation helpers. private void validateList(List list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { assertEquals(i, list.get(i).longValue()); } } private void validateStringList(List list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { assertEquals(Integer.valueOf(i), Integer.valueOf(list.get(i))); } } private void validateEnumList(List list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { assertEquals(TstEnum.E_ONE, list.get(i)); } } private void validateListOfList(List> list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { validateList(list.get(i), id, numItems); } } private void validateListOfSet(List> list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { Set set = list.get(i); for (int j = 0; j < numItems; j++) { assertTrue(set.contains(j)); } } } private void validateListOfMap( List> list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { Map map = list.get(i); for (int j = 0; j < numItems; j++) { String key = Integer.toString(j); assertTrue(map.containsKey(key)); assertEquals(j, map.get(key)); } } } private void validateListOfStruct(List list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { SmallStruct ss = testData.createSmallStruct(i); for (int j = 0; j < numItems; j++) { assertEquals(ss, list.get(i)); } } } private void validateListOfBinary(List list, int id, int numItems) { validateNotNullAndNotEmpty(list, numItems); for (int i = 0; i < numItems; i++) { ByteBuffer bb = ByteBuffer.wrap(testData.BYTES); assertEquals(0, bb.compareTo(list.get(i))); } } // ---------------------------------------------------------------------- // Set validation helpers. private void validateSet(Set set, Class clasz, int numItems) { validateNotNullAndNotEmpty(set, numItems); for (int i = 0; i < numItems; i++) { if (clasz == Byte.class) { assertTrue(set.contains((byte) i)); } else if (clasz == Short.class) { assertTrue(set.contains((short) i)); } else if (clasz == Integer.class) { assertTrue(set.contains(i)); } else if (clasz == Long.class) { assertTrue(set.contains((long) i)); } else if (clasz == Double.class) { assertTrue(set.contains((double) i)); } } } private void validateStringSet(Set set, int id, int numItems) { validateNotNullAndNotEmpty(set, numItems); for (int i = 0; i < numItems; i++) { assertTrue(set.contains(Integer.toString(i))); } } private void validateEnumSet(Set set, int id, int numItems) { validateNotNullAndNotEmpty(set, 1); assertTrue(set.contains(TstEnum.E_ONE)); } private void validateSetOfList(Set> set, int id, int numItems) { validateNotNullAndNotEmpty(set, 1); List list = new ArrayList<>(numItems); for (int i = 0; i < numItems; i++) { list.add(i); } assertTrue(set.contains(list)); } private void validateSetOfSet(Set> set, int id, int numItems) { validateNotNullAndNotEmpty(set, 1); Set setElt = new HashSet<>(); for (int i = 0; i < numItems; i++) { setElt.add(i); } assertTrue(set.contains(setElt)); } private void validateSetOfMap(Set> set, int id, int numItems) { validateNotNullAndNotEmpty(set, 1); Map map = new HashMap<>(); for (int i = 0; i < numItems; i++) { map.put(Integer.toString(i), i); } assertTrue(set.contains(map)); } private void validateSetOfStruct(Set set, int id, int numItems) { validateNotNullAndNotEmpty(set, numItems); for (int i = 0; i < numItems; i++) { SmallStruct ss = testData.createSmallStruct(i); assertTrue(set.contains(ss)); } } private void validateSetOfBinary(Set set, int id, int numItems) { validateNotNullAndNotEmpty(set, 1); for (ByteBuffer b : set) { ByteBuffer bb = ByteBuffer.wrap(testData.BYTES); assertEquals(0, bb.compareTo(b)); } } // ---------------------------------------------------------------------- // Map validation helpers. void validateNotNullAndNotEmpty(Map map, int numItems) { assertNotNull(map); assertEquals(numItems, map.size()); } private void validateMap(Map map, Class clasz, int numItems) { validateNotNullAndNotEmpty(map, numItems); for (int i = 0; i < numItems; i++) { if (clasz == Byte.class) { assertTrue(map.containsKey((byte) i)); assertEquals((byte) i, map.get((byte) i)); } else if (clasz == Short.class) { assertTrue(map.containsKey((short) i)); assertEquals((short) i, map.get((short) i)); } else if (clasz == Integer.class) { assertTrue(map.containsKey(i)); assertEquals(i, map.get(i)); } else if (clasz == Long.class) { assertTrue(map.containsKey((long) i)); assertEquals((long) i, map.get((long) i)); } else if (clasz == Double.class) { assertTrue(map.containsKey((double) i)); assertEquals((double) i, map.get((double) i)); } } } private void validateStringMap(Map map, int id, int numItems) { validateNotNullAndNotEmpty(map, numItems); for (int i = 0; i < numItems; i++) { String key = Integer.toString(i); assertTrue(map.containsKey(key)); assertEquals(key, map.get(key)); } } private void validateEnumMap(Map map, int id, int numItems) { validateNotNullAndNotEmpty(map, 1); assertTrue(map.containsKey(TstEnum.E_ONE)); assertEquals(TstEnum.E_ONE, map.get(TstEnum.E_ONE)); } private void validateMapOfList(Map> map, int id, int numItems) { validateNotNullAndNotEmpty(map, numItems); List list = new ArrayList<>(numItems); for (int i = 0; i < numItems; i++) { list.add(i); } for (int i = 0; i < numItems; i++) { assertTrue(map.containsKey(i)); assertEquals(list, map.get(i)); } } private void validateMapOfSet(Map> map, int id, int numItems) { validateNotNullAndNotEmpty(map, numItems); Set setElt = new HashSet<>(); for (int i = 0; i < numItems; i++) { setElt.add(i); } for (int i = 0; i < numItems; i++) { assertTrue(map.containsKey(i)); assertEquals(setElt, map.get(i)); } } private void validateMapOfMap(Map> map, int id, int numItems) { validateNotNullAndNotEmpty(map, numItems); Map mapElt = new HashMap<>(); for (int i = 0; i < numItems; i++) { mapElt.put(i, i); } for (int i = 0; i < numItems; i++) { assertTrue(map.containsKey(i)); assertEquals(mapElt, map.get(i)); } } private void validateMapOfStruct(Map map, int id, int numItems) { validateNotNullAndNotEmpty(map, numItems); for (int i = 0; i < numItems; i++) { SmallStruct ss = testData.createSmallStruct(i); assertTrue(map.containsKey(ss)); assertEquals(ss, map.get(ss)); } } private void validateMapOfBinary(Map map, int id, int numItems) { validateNotNullAndNotEmpty(map, numItems); for (int i = 0; i < numItems; i++) { ByteBuffer bb = ByteBuffer.wrap(testData.BYTES); assertTrue(map.containsKey(i)); assertEquals(0, bb.compareTo(map.get(i))); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/EnumCacheTest.java0000644000000000000000000000570014303740367027565 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import org.apache.thrift.TEnum; import org.junit.jupiter.api.Test; /** Test ThriftCodec serializes and deserializes thrift objects correctly. */ public class EnumCacheTest { enum TestEnum implements TEnum { Alice(-1), Bob(0), Charlie(1); private int value; TestEnum(int value) { this.value = value; } @Override public int getValue() { return this.value; } } static class NotEnum implements TEnum { public static final NotEnum Alice = new NotEnum(-11); public static final NotEnum Bob = new NotEnum(10); public static final NotEnum Charlie = new NotEnum(11); private static final NotEnum[] allValues = {Alice, Bob, Charlie}; private int value; private NotEnum(int value) { this.value = value; } public static TEnum[] values() { return NotEnum.allValues; } @Override public int getValue() { return this.value; } @Override public String toString() { return String.format("NotEnum : %d", this.value); } } @Test public void testArgChecks() { EnumCache cache = new EnumCache(); // Should not throw. cache.get(TestEnum.class, 0); // Verify it throws. assertThrows( IllegalArgumentException.class, () -> cache.get(null, 1), "'enumClass' must not be null"); } @Test public void testGet() { EnumCache cache = new EnumCache(); assertEquals(TestEnum.Alice, cache.get(TestEnum.class, -1)); assertEquals(TestEnum.Bob, cache.get(TestEnum.class, 0)); assertEquals(TestEnum.Charlie, cache.get(TestEnum.class, 1)); assertEquals(NotEnum.Alice, cache.get(NotEnum.class, -11)); assertEquals(NotEnum.Bob, cache.get(NotEnum.class, 10)); assertEquals(NotEnum.Charlie, cache.get(NotEnum.class, 11)); } @Test public void testGetInvalid() { EnumCache cache = new EnumCache(); assertNull(cache.get(TestEnum.class, 42)); assertNull(cache.get(NotEnum.class, 42)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/partial/ThriftSerDe.java0000644000000000000000000000510314370300523027243 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.partial; import org.apache.thrift.TBase; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.TSerializer; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; public class ThriftSerDe { private TSerializer binarySerializer; private TSerializer compactSerializer; private TDeserializer binaryDeserializer; private TDeserializer compactDeserializer; public ThriftSerDe() throws TException { this.binarySerializer = new TSerializer(new TBinaryProtocol.Factory()); this.compactSerializer = new TSerializer(new TCompactProtocol.Factory()); this.binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory()); this.compactDeserializer = new TDeserializer(new TCompactProtocol.Factory()); } public byte[] serializeBinary(TBase obj) throws TException { return binarySerializer.serialize(obj); } public byte[] serializeCompact(TBase obj) throws TException { return compactSerializer.serialize(obj); } public T deserializeBinary(byte[] bytes, Class clazz) throws TException { T instance = this.newInstance(clazz); binaryDeserializer.deserialize(instance, bytes); return clazz.cast(instance); } public T deserializeCompact(byte[] bytes, Class clazz) throws TException { T instance = this.newInstance(clazz); compactDeserializer.deserialize(instance, bytes); return clazz.cast(instance); } private T newInstance(Class clazz) { T instance = null; try { instance = clazz.getDeclaredConstructor().newInstance(); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } return clazz.cast(instance); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestDefinitionOrder.java0000644000000000000000000000446614452237057027377 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.*; import java.io.*; import java.util.Arrays; import java.util.List; import org.junit.jupiter.api.Test; // Tests that declaring fields in different order (esp. when they reference each other) generates // identical code public class TestDefinitionOrder { @Test public void testDefinitionOrder() throws Exception { List filenames = Arrays.asList("Parent.java", "Child.java", "MyEnum.java"); for (String fn : filenames) { String fnA = "definition-order-test/a/" + fn; String fnB = "definition-order-test/b/" + fn; try (InputStream isA = TestDefinitionOrder.class.getClassLoader().getResourceAsStream(fnA); InputStream isB = TestDefinitionOrder.class.getClassLoader().getResourceAsStream(fnB)) { assertNotNull(isA, "Resource not found: " + fnA); assertNotNull(isB, "Resource not found: " + fnB); int hashA = Arrays.hashCode(readAllBytes(isA)); assertEquals( hashA, Arrays.hashCode(readAllBytes(isB)), String.format("Generated Java files %s and %s differ", fnA, fnB)); } } } // TODO Use InputStream.readAllBytes post-Java8 private byte[] readAllBytes(InputStream is) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int bytesRead; while ((bytesRead = is.read(buff, 0, buff.length)) != -1) { os.write(buff, 0, bytesRead); } return os.toByteArray(); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/0000777000000000000000000000000014370300523023545 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/TestServlet.java0000644000000000000000000000342314303740367026704 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.ServerTestBase.TestHandler; import org.apache.thrift.server.TExtensibleServlet; import thrift.test.ThriftTest; @SuppressWarnings("serial") public class TestServlet extends TExtensibleServlet { @Override protected TProtocolFactory getInProtocolFactory() { TProtocolFactory tProtocolFactory = new TCompactProtocol.Factory(); return tProtocolFactory; } @Override protected TProtocolFactory getOutProtocolFactory() { TProtocolFactory tProtocolFactory = new TCompactProtocol.Factory(); return tProtocolFactory; } @SuppressWarnings({"rawtypes", "unchecked"}) @Override protected TProcessor getProcessor() { TestHandler testHandler = new TestHandler(); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); return testProcessor; } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/SerializationBenchmark.java0000644000000000000000000000663314303740367031056 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import org.apache.thrift.Fixtures; import org.apache.thrift.TBase; import org.apache.thrift.TConfiguration; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TMemoryBuffer; import org.apache.thrift.transport.TMemoryInputTransport; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import thrift.test.OneOfEach; public class SerializationBenchmark { private static final int HOW_MANY = 10000000; public static void main(String[] args) throws Exception { TProtocolFactory factory = new TBinaryProtocol.Factory(); testSerialization(factory, Fixtures.getOneOfEach()); testDeserialization(factory, Fixtures.getOneOfEach(), OneOfEach.class); } public static void testSerialization(TProtocolFactory factory, TBase object) throws Exception { TTransport trans = new TTransport() { public void write(byte[] bin, int x, int y) throws TTransportException {} public TConfiguration getConfiguration() { return new TConfiguration(); } public void updateKnownMessageSize(long size) throws TTransportException {} public void checkReadBytesAvailable(long numBytes) throws TTransportException {} public int read(byte[] bin, int x, int y) throws TTransportException { return 0; } public void close() {} public void open() {} public boolean isOpen() { return true; } }; TProtocol proto = factory.getProtocol(trans); long startTime = System.currentTimeMillis(); for (int i = 0; i < HOW_MANY; i++) { object.write(proto); } long endTime = System.currentTimeMillis(); System.out.println("Serialization test time: " + (endTime - startTime) + " ms"); } public static void testDeserialization( TProtocolFactory factory, T object, Class klass) throws Exception { TMemoryBuffer buf = new TMemoryBuffer(0); object.write(factory.getProtocol(buf)); byte[] serialized = new byte[100 * 1024]; buf.read(serialized, 0, 100 * 1024); long startTime = System.currentTimeMillis(); for (int i = 0; i < HOW_MANY; i++) { T o2 = klass.getConstructor().newInstance(); o2.read(factory.getProtocol(new TMemoryInputTransport(new TConfiguration(), serialized))); } long endTime = System.currentTimeMillis(); System.out.println("Deserialization test time: " + (endTime - startTime) + " ms"); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/JavaBeansTest.java0000644000000000000000000001147514303740367027120 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import java.nio.ByteBuffer; import java.util.LinkedList; import thrift.test.OneOfEachBeans; public class JavaBeansTest { public static void main(String[] args) throws Exception { // Test isSet methods OneOfEachBeans ooe = new OneOfEachBeans(); // Nothing should be set if (ooe.is_set_a_bite()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_base64()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_byte_list()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_double_precision()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_i16_list()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_i64_list()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_boolean_field()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_integer16()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_integer32()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_integer64()) throw new RuntimeException("isSet method error: unset field returned as set!"); if (ooe.is_set_some_characters()) throw new RuntimeException("isSet method error: unset field returned as set!"); for (int i = 1; i < 12; i++) { if (ooe.isSet(ooe.fieldForId(i))) throw new RuntimeException("isSet method error: unset field " + i + " returned as set!"); } // Everything is set ooe.set_a_bite((byte) 1); ooe.set_base64(ByteBuffer.wrap("bytes".getBytes())); ooe.set_byte_list(new LinkedList<>()); ooe.set_double_precision(1); ooe.set_i16_list(new LinkedList<>()); ooe.set_i64_list(new LinkedList<>()); ooe.set_boolean_field(true); ooe.set_integer16((short) 1); ooe.set_integer32(1); ooe.set_integer64(1); ooe.set_some_characters("string"); if (!ooe.is_set_a_bite()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_base64()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_byte_list()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_double_precision()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_i16_list()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_i64_list()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_boolean_field()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_integer16()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_integer32()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_integer64()) throw new RuntimeException("isSet method error: set field returned as unset!"); if (!ooe.is_set_some_characters()) throw new RuntimeException("isSet method error: set field returned as unset!"); for (int i = 1; i < 12; i++) { if (!ooe.isSet(ooe.fieldForId(i))) throw new RuntimeException("isSet method error: set field " + i + " returned as unset!"); } // Should throw exception when field doesn't exist boolean exceptionThrown = false; try { ooe.isSet(ooe.fieldForId(100)); } catch (IllegalArgumentException e) { exceptionThrown = true; } if (!exceptionThrown) throw new RuntimeException( "isSet method error: non-existent field provided as agument but no exception thrown!"); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/EqualityTest.java0000644000000000000000000004742714303740367027071 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* This program was generated by the following Python script: #!/usr/bin/python2.5 # Remove this when Python 2.6 hits the streets. from __future__ import with_statement import sys import os.path # Quines the easy way. with open(sys.argv[0], 'r') as handle: source = handle.read() with open(os.path.join(os.path.dirname(sys.argv[0]), 'EqualityTest.java'), 'w') as out: print >> out, ("/""*" r""" * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. """ "*""/") print >> out print >> out, "/""*" print >> out, "This program was generated by the following Python script:" print >> out out.write(source) print >> out, "*""/" print >> out, r''' package org.apache.thrift.test; // Generated code import thrift.test.*; /'''r'''** *'''r'''/ public class EqualityTest { public static void main(String[] args) throws Exception { JavaTestHelper lhs, rhs; ''' vals = { 'int': ("1", "2"), 'obj': ("\"foo\"", "\"bar\""), 'bin': ("new byte[]{1,2}", "new byte[]{3,4}"), } matrix = ( (False,False), (False,True ), (True ,False), (True ,True ), ) for type in ('int', 'obj', 'bin'): for option in ('req', 'opt'): nulls = matrix[0:1] if type == 'int' else matrix[-1::-1] issets = matrix for is_null in nulls: for is_set in issets: # isset is implied for non-primitives, so only consider the case # where isset and non-null match. if type != 'int' and list(is_set) != [ not null for null in is_null ]: continue for equal in (True, False): print >> out print >> out, " lhs = new JavaTestHelper();" print >> out, " rhs = new JavaTestHelper();" print >> out, " lhs." + option + "_" + type, "=", vals[type][0] + ";" print >> out, " rhs." + option + "_" + type, "=", vals[type][0 if equal else 1] + ";" isset_setter = "set" + option[0].upper() + option[1:] + "_" + type + "IsSet" if (type == 'int' and is_set[0]): print >> out, " lhs." + isset_setter + "(true);" if (type == 'int' and is_set[1]): print >> out, " rhs." + isset_setter + "(true);" if (is_null[0]): print >> out, " lhs." + option + "_" + type, "= null;" if (is_null[1]): print >> out, " rhs." + option + "_" + type, "= null;" this_present = not is_null[0] and (option == 'req' or is_set[0]) that_present = not is_null[1] and (option == 'req' or is_set[1]) print >> out, " // this_present = " + repr(this_present) print >> out, " // that_present = " + repr(that_present) is_equal = \ (not this_present and not that_present) or \ (this_present and that_present and equal) eq_str = 'true' if is_equal else 'false' print >> out, " if (lhs.equals(rhs) != "+eq_str+")" print >> out, " throw new RuntimeException(\"Failure\");" if is_equal: print >> out, " if (lhs.hashCode() != rhs.hashCode())" print >> out, " throw new RuntimeException(\"Failure\");" print >> out, r''' } } ''' */ package org.apache.thrift.test; // Generated code import java.nio.ByteBuffer; import thrift.test.JavaTestHelper; /** */ public class EqualityTest { public static void main(String[] args) throws Exception { JavaTestHelper lhs, rhs; lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 1; // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 2; // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 1; rhs.setReq_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 2; rhs.setReq_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 1; lhs.setReq_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 2; lhs.setReq_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 1; lhs.setReq_intIsSet(true); rhs.setReq_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_int = 1; rhs.req_int = 2; lhs.setReq_intIsSet(true); rhs.setReq_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 1; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 2; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 1; rhs.setOpt_intIsSet(true); // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 2; rhs.setOpt_intIsSet(true); // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 1; lhs.setOpt_intIsSet(true); // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 2; lhs.setOpt_intIsSet(true); // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 1; lhs.setOpt_intIsSet(true); rhs.setOpt_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_int = 1; rhs.opt_int = 2; lhs.setOpt_intIsSet(true); rhs.setOpt_intIsSet(true); // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "foo"; lhs.req_obj = null; rhs.req_obj = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "bar"; lhs.req_obj = null; rhs.req_obj = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "foo"; lhs.req_obj = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "bar"; lhs.req_obj = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "foo"; rhs.req_obj = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "bar"; rhs.req_obj = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "foo"; // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_obj = "foo"; rhs.req_obj = "bar"; // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "foo"; lhs.opt_obj = null; rhs.opt_obj = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "bar"; lhs.opt_obj = null; rhs.opt_obj = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "foo"; lhs.opt_obj = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "bar"; lhs.opt_obj = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "foo"; rhs.opt_obj = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "bar"; rhs.opt_obj = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "foo"; // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_obj = "foo"; rhs.opt_obj = "bar"; // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); lhs.req_bin = null; rhs.req_bin = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {3, 4}); lhs.req_bin = null; rhs.req_bin = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); lhs.req_bin = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {3, 4}); lhs.req_bin = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {3, 4}); rhs.req_bin = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.req_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.req_bin = ByteBuffer.wrap(new byte[] {3, 4}); // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); lhs.opt_bin = null; rhs.opt_bin = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {3, 4}); lhs.opt_bin = null; rhs.opt_bin = null; // this_present = False // that_present = False if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); lhs.opt_bin = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {3, 4}); lhs.opt_bin = null; // this_present = False // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {3, 4}); rhs.opt_bin = null; // this_present = True // that_present = False if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); // this_present = True // that_present = True if (lhs.equals(rhs) != true) throw new RuntimeException("Failure"); if (lhs.hashCode() != rhs.hashCode()) throw new RuntimeException("Failure"); lhs = new JavaTestHelper(); rhs = new JavaTestHelper(); lhs.opt_bin = ByteBuffer.wrap(new byte[] {1, 2}); rhs.opt_bin = ByteBuffer.wrap(new byte[] {3, 4}); // this_present = True // that_present = True if (lhs.equals(rhs) != false) throw new RuntimeException("Failure"); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/ReadStruct.java0000644000000000000000000000464014370300523026470 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import java.io.BufferedInputStream; import java.io.FileInputStream; import org.apache.thrift.Fixtures; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; import thrift.test.CompactProtoTestStruct; public class ReadStruct { public static void main(String[] args) throws Exception { if (args.length != 2) { System.out.println( "usage: java -cp build/classes org.apache.thrift.test.ReadStruct filename proto_factory_class"); System.out.println( "Read in an instance of CompactProtocolTestStruct from 'file', making sure that it is equivalent to Fixtures.compactProtoTestStruct. Use a protocol from 'proto_factory_class'."); } TTransport trans = new TIOStreamTransport(new BufferedInputStream(new FileInputStream(args[0]))); TProtocolFactory factory = (TProtocolFactory) Class.forName(args[1]).getDeclaredConstructor().newInstance(); TProtocol proto = factory.getProtocol(trans); CompactProtoTestStruct cpts = new CompactProtoTestStruct(); for (CompactProtoTestStruct._Fields fid : CompactProtoTestStruct.metaDataMap.keySet()) { cpts.setFieldValue(fid, null); } cpts.read(proto); if (cpts.equals(Fixtures.getCompactProtoTestStruct())) { System.out.println("Object verified successfully!"); } else { System.out.println("Object failed verification!"); System.out.println("Expected: " + Fixtures.getCompactProtoTestStruct() + " but got " + cpts); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/WriteStruct.java0000644000000000000000000000357714370300523026717 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import org.apache.thrift.Fixtures; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TIOStreamTransport; import org.apache.thrift.transport.TTransport; public class WriteStruct { public static void main(String[] args) throws Exception { if (args.length != 2) { System.out.println( "usage: java -cp build/classes org.apache.thrift.test.WriteStruct filename proto_factory_class"); System.out.println( "Write out an instance of Fixtures.compactProtocolTestStruct to 'file'. Use a protocol from 'proto_factory_class'."); } TTransport trans = new TIOStreamTransport(new BufferedOutputStream(new FileOutputStream(args[0]))); TProtocolFactory factory = (TProtocolFactory) Class.forName(args[1]).getDeclaredConstructor().newInstance(); TProtocol proto = factory.getProtocol(trans); Fixtures.getCompactProtoTestStruct().write(proto); trans.flush(); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/voidmethexceptions/0000777000000000000000000000000014303740367027500 5ustar00rootroot00000000000000TestVoidMethExceptions.java0000644000000000000000000004640314303740367034710 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/voidmethexceptions/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test.voidmethexceptions; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import java.util.stream.Stream; import org.apache.commons.lang3.tuple.Pair; import org.apache.thrift.TApplicationException; import org.apache.thrift.TConfiguration; import org.apache.thrift.TProcessor; import org.apache.thrift.async.AsyncMethodCallback; import org.apache.thrift.async.TAsyncClientManager; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TNonblockingServer; import org.apache.thrift.server.TServer; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TNonblockingSocket; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.layered.TFramedTransport; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import thrift.test.voidmethexceptions.TAppService01; import thrift.test.voidmethexceptions.TExampleException; public class TestVoidMethExceptions { private static final Logger log = LoggerFactory.getLogger(TestVoidMethExceptions.class); private static Stream provideParameters() throws Exception { return Stream.builder() .add(new TestParameters(ServerImplementationType.SYNC_SERVER)) .add(new TestParameters(ServerImplementationType.ASYNC_SERVER)) .build(); } public static class TestParameters { private static final int TIMEOUT_MILLIS = 5_000; private final TServer server; private final Thread serverThread; private final TNonblockingServerSocket serverTransport; private int serverPort; private final ServerImplementationType serverImplementationType; private final CompletableFuture futureServerStarted = new CompletableFuture<>(); TestParameters(ServerImplementationType serverImplementationType) throws Exception { this.serverImplementationType = serverImplementationType; serverPort = -1; serverImplementationType.service.setCancelled(false); serverTransport = new TNonblockingServerSocket(0); TNonblockingServer.Args args = new TNonblockingServer.Args(serverTransport); args.processor(serverImplementationType.processor); server = new TNonblockingServer(args) { @Override protected void setServing(boolean serving) { super.setServing(serving); if (serving) { serverPort = serverTransport.getPort(); futureServerStarted.complete(null); } } }; serverThread = new Thread(server::serve, "thrift-server"); serverThread.setDaemon(true); } public AutoCloseable start() throws Exception { serverThread.start(); futureServerStarted.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); return () -> { serverImplementationType.service.setCancelled(true); server.stop(); serverThread.join(TIMEOUT_MILLIS); }; } private void checkSyncClient( String desc, String msg, boolean throwException, String expectedResult, Class expectedExceptionClass, String expectedExceptionMsg, SyncCall call) throws Exception { if (log.isInfoEnabled()) { log.info( "start test checkSyncClient::" + desc + ", throwException: " + throwException + ", serverImplementationType: " + serverImplementationType); } assertNotEquals(-1, serverPort); try (TTransport clientTransport = new TFramedTransport( new TSocket(new TConfiguration(), "localhost", serverPort, TIMEOUT_MILLIS))) { clientTransport.open(); TAppService01.Iface client = new TAppService01.Client(new TBinaryProtocol(clientTransport)); if (throwException && expectedExceptionClass != null) { Exception ex = assertThrows( expectedExceptionClass, () -> { call.apply(client, msg, throwException); }); assertEquals(expectedExceptionClass, ex.getClass()); if (expectedExceptionMsg != null) { assertEquals(expectedExceptionMsg, ex.getMessage()); } } else { // expected String result = call.apply(client, msg, throwException); assertEquals(expectedResult, result); } } } private void checkAsyncClient( String desc, String msg, boolean throwException, T expectedResult, Class expectedExceptionClass, String expectedExceptionMsg, AsyncCall> call) throws Throwable { if (log.isInfoEnabled()) { log.info( "start test checkAsyncClient::" + desc + ", throwException: " + throwException + ", serverImplementationType: " + serverImplementationType); } assertNotEquals(serverPort, -1); try (TNonblockingSocket clientTransportAsync = new TNonblockingSocket("localhost", serverPort, TIMEOUT_MILLIS)) { TAsyncClientManager asyncClientManager = new TAsyncClientManager(); try { TAppService01.AsyncClient asyncClient = new TAppService01.AsyncClient( new TBinaryProtocol.Factory(), asyncClientManager, clientTransportAsync); asyncClient.setTimeout(TIMEOUT_MILLIS); CompletableFuture futureResult = new CompletableFuture<>(); call.apply( asyncClient, msg, throwException, new AsyncMethodCallback() { @Override public void onError(Exception exception) { futureResult.completeExceptionally(exception); } @Override public void onComplete(T response) { futureResult.complete(response); } }); if (throwException && expectedExceptionClass != null) { Exception ex = assertThrows( expectedExceptionClass, () -> { try { futureResult.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (ExecutionException x) { throw x.getCause(); } }); assertEquals(expectedExceptionClass, ex.getClass()); if (expectedExceptionMsg != null) { assertEquals(expectedExceptionMsg, ex.getMessage()); } } else { T result; try { result = futureResult.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); } catch (ExecutionException x) { throw x.getCause(); } assertEquals(expectedResult, result); } } finally { asyncClientManager.stop(); } } } public TServer getServer() { return server; } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustReturnResultReturnString(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnString", "sent msg", false, "sent msg", null, null, TAppService01.Iface::returnString); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustReturnResultReturnVoidThrows(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnVoidThrows", "sent msg", false, null, null, null, (client, msg, throwException) -> { client.returnVoidThrows(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustReturnResultReturnVoidNoThrowsRuntimeException(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnVoidNoThrowsRuntimeException", "sent msg", false, null, null, null, (client, msg, throwException) -> { client.returnVoidNoThrowsRuntimeException(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustReturnResultReturnVoidNoThrowsTApplicationException( TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnVoidNoThrowsTApplicationException", "sent msg", false, null, null, null, (client, msg, throwException) -> { client.returnVoidNoThrowsTApplicationException(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustThrowExceptionReturnString(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnString", "sent msg", true, null, TExampleException.class, "sent msg", TAppService01.Iface::returnString); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustThrowExceptionReturnVoidThrows(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnVoidThrows", "sent msg", true, null, TExampleException.class, "sent msg", (client, msg, throwException) -> { client.returnVoidThrows(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustThrowExceptionReturnVoidNoThrowsRuntimeException(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnVoidNoThrowsRuntimeException", "sent msg", true, null, TApplicationException.class, p.serverImplementationType == ServerImplementationType.ASYNC_SERVER ? "sent msg" : null, // sync server return "Internal error processing // returnVoidNoThrowsRuntimeException" message (client, msg, throwException) -> { client.returnVoidNoThrowsRuntimeException(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientMustThrowExceptionReturnVoidNoThrowsTApplicationException( TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "returnVoidNoThrowsTApplicationException", "sent msg", true, null, TApplicationException.class, "sent msg", (client, msg, throwException) -> { client.returnVoidNoThrowsTApplicationException(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustReturnResultReturnString(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnString", "sent msg", false, "sent msg", null, null, TAppService01.AsyncClient::returnString); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustReturnResultReturnVoidThrows(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnVoidThrows", "sent msg", false, null, null, null, TAppService01.AsyncClient::returnVoidThrows); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustReturnResultReturnVoidNoThrowsRuntimeException(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnVoidNoThrowsRuntimeException", "sent msg", false, null, null, null, TAppService01.AsyncClient::returnVoidNoThrowsRuntimeException); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustReturnResultReturnVoidNoThrowsTApplicationException( TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnVoidNoThrowsTApplicationException", "sent msg", false, null, null, null, TAppService01.AsyncClient::returnVoidNoThrowsTApplicationException); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustThrowExceptionReturnString(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnString", "sent msg", true, null, TExampleException.class, "sent msg", TAppService01.AsyncClient::returnString); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustThrowExceptionReturnVoidThrows(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnVoidThrows", "sent msg", true, null, TExampleException.class, "sent msg", TAppService01.AsyncClient::returnVoidThrows); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustThrowExceptionReturnVoidNoThrowsRuntimeException(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnVoidNoThrowsRuntimeException", "sent msg", true, null, TApplicationException.class, p.serverImplementationType == ServerImplementationType.ASYNC_SERVER ? "sent msg" : null, // sync server return "Internal error processing // returnVoidNoThrowsRuntimeException" message TAppService01.AsyncClient::returnVoidNoThrowsRuntimeException); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientMustThrowExceptionReturnVoidNoThrowsTApplicationException( TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "returnVoidNoThrowsTApplicationException", "sent msg", true, null, TApplicationException.class, "sent msg", TAppService01.AsyncClient::returnVoidNoThrowsTApplicationException); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientNoWaitForResultNoExceptionOnewayVoidNoThrows(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "onewayVoidNoThrows", "sent msg", false, null, null, null, (client, msg, throwException) -> { client.onewayVoidNoThrows(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testSyncClientNoWaitForResultExceptionOnewayVoidNoThrows(TestParameters p) throws Exception { try (AutoCloseable ignored = p.start()) { p.checkSyncClient( "onewayVoidNoThrows", "sent msg", true, null, null, null, (client, msg, throwException) -> { client.onewayVoidNoThrows(msg, throwException); return null; }); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientNoWaitForResultNoExceptionOnewayVoidNoThrows(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "onewayVoidNoThrows", "sent msg", false, null, null, null, TAppService01.AsyncClient::onewayVoidNoThrows); } } @ParameterizedTest @MethodSource("provideParameters") public void testAsyncClientNoWaitForResultExceptionOnewayVoidNoThrows(TestParameters p) throws Throwable { try (AutoCloseable ignored = p.start()) { p.checkAsyncClient( "onewayVoidNoThrows", "sent msg", true, null, null, null, TAppService01.AsyncClient::onewayVoidNoThrows); } } private enum ServerImplementationType { SYNC_SERVER( () -> { ServiceSyncImp service = new ServiceSyncImp(); return Pair.of(new TAppService01.Processor<>(service), service); }), ASYNC_SERVER( () -> { ServiceAsyncImp service = new ServiceAsyncImp(); return Pair.of(new TAppService01.AsyncProcessor<>(service), service); }); final TProcessor processor; final ServiceBase service; ServerImplementationType(Supplier> supplier) { Pair pair = supplier.get(); this.processor = pair.getLeft(); this.service = pair.getRight(); } } @FunctionalInterface private interface SyncCall { R apply(T t, U u, V v) throws Exception; } @FunctionalInterface private interface AsyncCall { void apply(T t, U u, V v, X x) throws Exception; } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/voidmethexceptions/ServiceAsyncImp.java0000644000000000000000000000535314303740367033411 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test.voidmethexceptions; import org.apache.thrift.TApplicationException; import org.apache.thrift.TException; import org.apache.thrift.async.AsyncMethodCallback; import thrift.test.voidmethexceptions.TAppService01; import thrift.test.voidmethexceptions.TExampleException; public class ServiceAsyncImp extends ServiceBase implements TAppService01.AsyncIface { @Override public void returnString( String msg, boolean throwException, AsyncMethodCallback resultHandler) throws TException { if (throwException) { resultHandler.onError(new TExampleException(msg)); } else { resultHandler.onComplete(msg); } } @Override public void returnVoidThrows( String msg, boolean throwException, AsyncMethodCallback resultHandler) throws TException { if (throwException) { resultHandler.onError(new TExampleException(msg)); } else { resultHandler.onComplete(null); } } @Override public void returnVoidNoThrowsRuntimeException( String msg, boolean throwException, AsyncMethodCallback resultHandler) throws TException { if (throwException) { resultHandler.onError(new RuntimeException(msg)); } else { resultHandler.onComplete(null); } } @Override public void returnVoidNoThrowsTApplicationException( String msg, boolean throwException, AsyncMethodCallback resultHandler) throws TException { if (throwException) { resultHandler.onError(new TApplicationException(TApplicationException.INTERNAL_ERROR, msg)); } else { resultHandler.onComplete(null); } } @Override public void onewayVoidNoThrows( String msg, boolean throwException, AsyncMethodCallback resultHandler) throws TException { if (throwException) { resultHandler.onError(new TApplicationException(TApplicationException.INTERNAL_ERROR, msg)); } else { // simulate hang up } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/voidmethexceptions/ServiceBase.java0000644000000000000000000000235014303740367032532 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test.voidmethexceptions; public class ServiceBase { private volatile boolean cancelled = false; public boolean isCancelled() { return cancelled; } public void setCancelled(boolean cancelled) { this.cancelled = cancelled; } protected void waitForCancel() { while (!isCancelled()) { try { Thread.sleep(10L); } catch (InterruptedException x) { break; } } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/test/voidmethexceptions/ServiceSyncImp.java0000644000000000000000000000435014303740367033244 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test.voidmethexceptions; import org.apache.thrift.TApplicationException; import org.apache.thrift.TException; import thrift.test.voidmethexceptions.TAppService01; import thrift.test.voidmethexceptions.TExampleException; public class ServiceSyncImp extends ServiceBase implements TAppService01.Iface { @Override public String returnString(String msg, boolean throwException) throws TExampleException, TException { if (throwException) { throw new TExampleException(msg); } return msg; } @Override public void returnVoidThrows(String msg, boolean throwException) throws TExampleException, TException { if (throwException) { throw new TExampleException(msg); } } @Override public void returnVoidNoThrowsRuntimeException(String msg, boolean throwException) throws TException { if (throwException) { throw new RuntimeException(msg); } } @Override public void returnVoidNoThrowsTApplicationException(String msg, boolean throwException) throws TException { if (throwException) { throw new TApplicationException(TApplicationException.INTERNAL_ERROR, msg); } } @Override public void onewayVoidNoThrows(String msg, boolean throwException) throws TException { if (throwException) { throw new TApplicationException(TApplicationException.INTERNAL_ERROR, msg); } else { // simulate hang up waitForCancel(); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/scheme/0000777000000000000000000000000014303740367024044 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/scheme/TestStandardScheme.java0000644000000000000000000000321114303740367030425 0ustar00rootroot00000000000000package org.apache.thrift.scheme; import static org.junit.jupiter.api.Assertions.assertEquals; import org.apache.thrift.Fixtures; import org.apache.thrift.TBase; import org.apache.thrift.TDeserializer; import org.apache.thrift.TException; import org.apache.thrift.TSerializer; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TMemoryBuffer; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.junit.jupiter.api.Test; import thrift.test.HolyMoley; import thrift.test.Nesting; import thrift.test.OneOfEach; public class TestStandardScheme { TSerializer serializer = new TSerializer(); TDeserializer deserializer = new TDeserializer(); public TestStandardScheme() throws TTransportException {} /** * This tests whether the Standard Scheme properly reads structs serialized using an older version * of thrift. */ @Test public void testPersistentStructs() throws TException { readAndCompare( new OneOfEach(), Fixtures.getOneOfEach(), Fixtures.getPersistentBytesOneOfEach()); readAndCompare( new HolyMoley(), Fixtures.getHolyMoley(), Fixtures.getPersistentBytesHolyMoley()); readAndCompare(new Nesting(), Fixtures.getNesting(), Fixtures.getPersistentBytesNesting()); } private void readAndCompare(TBase struct, TBase fixture, byte[] inputBytes) throws TException { TTransport trans = new TMemoryBuffer(0); trans.write(inputBytes, 0, inputBytes.length); TProtocol iprot = new TBinaryProtocol(trans); struct.read(iprot); assertEquals(fixture, struct); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/utils/0000777000000000000000000000000014303740367023740 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/utils/TestStringUtils.java0000644000000000000000000000374514303740367027737 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.utils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class TestStringUtils { @Test public void testToHexString() { byte[] bytes = {0x00, 0x1A, (byte) 0xEF, (byte) 0xAB, (byte) 0x92}; assertEquals("001AEFAB92", StringUtils.bytesToHexString(bytes)); assertEquals("EFAB92", StringUtils.bytesToHexString(bytes, 2, 3)); assertNull(StringUtils.bytesToHexString(null)); } private byte[] bytes; @BeforeEach public void setUp() throws Exception { bytes = new byte[] {1, 2, 3, 4, 5}; } @Test public void testNegativeLength() { assertThrows(IllegalArgumentException.class, () -> StringUtils.bytesToHexString(bytes, 0, -1)); } @Test public void testNegativeStartOffset() { assertThrows(IndexOutOfBoundsException.class, () -> StringUtils.bytesToHexString(bytes, -1, 1)); } @Test public void testInvalidRange() { assertThrows(IndexOutOfBoundsException.class, () -> StringUtils.bytesToHexString(bytes, 5, 1)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestOptionType.java0000644000000000000000000000434114303740367026413 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; // Tests and documents behavior for the "Option" type public class TestOptionType { @Test public void testSome() { String name = "Chuck Norris"; Option option = Option.fromNullable(name); assertTrue(option instanceof Option.Some); assertTrue(option.isDefined()); assertEquals("Some(Chuck Norris)", option.toString()); assertEquals(option.or("default value"), "Chuck Norris"); assertEquals(option.get(), "Chuck Norris"); } @Test public void testNone() throws Exception { String name = null; Option option = Option.fromNullable(name); assertTrue(option instanceof Option.None); assertFalse(option.isDefined()); assertEquals("None", option.toString()); assertEquals(option.or("default value"), "default value"); // Expect exception assertThrows(IllegalStateException.class, option::get); } @Test public void testMakeSome() throws Exception { Option some = Option.some("wee"); assertTrue(some.isDefined()); } @Test public void testMakeNone() throws Exception { Option none = Option.none(); assertFalse(none.isDefined()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestDeepCopy.java0000644000000000000000000000242414303740367026011 0ustar00rootroot00000000000000package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertNotSame; import org.junit.jupiter.api.Test; import thrift.test.DeepCopyBar; import thrift.test.DeepCopyFoo; public class TestDeepCopy { @Test public void testDeepCopy() throws Exception { final DeepCopyFoo foo = new DeepCopyFoo(); foo.addToL(new DeepCopyBar()); foo.addToS(new DeepCopyBar()); foo.putToM("test 3", new DeepCopyBar()); foo.addToLi(new thrift.test.Object()); foo.addToSi(new thrift.test.Object()); foo.putToMi("test 3", new thrift.test.Object()); foo.setBar(new DeepCopyBar()); final DeepCopyFoo deepCopyFoo = foo.deepCopy(); assertNotSame(foo.getBar(), deepCopyFoo.getBar()); assertNotSame(foo.getL().get(0), deepCopyFoo.getL().get(0)); assertNotSame( foo.getS().toArray(new DeepCopyBar[0])[0], deepCopyFoo.getS().toArray(new DeepCopyBar[0])[0]); assertNotSame(foo.getM().get("test 3"), deepCopyFoo.getM().get("test 3")); assertNotSame(foo.getLi().get(0), deepCopyFoo.getLi().get(0)); assertNotSame( foo.getSi().toArray(new thrift.test.Object[0])[0], deepCopyFoo.getSi().toArray(new thrift.test.Object[0])[0]); assertNotSame(foo.getMi().get("test 3"), deepCopyFoo.getMi().get("test 3")); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestMultiplexedProcessor.java0000644000000000000000000000601414452237057030476 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.apache.thrift.protocol.TMessage; import org.apache.thrift.protocol.TMessageType; import org.apache.thrift.protocol.TProtocol; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class TestMultiplexedProcessor { private TMultiplexedProcessor mp; private TProtocol iprot; private TProtocol oprot; @BeforeEach public void setUp() throws Exception { mp = new TMultiplexedProcessor(); iprot = mock(TProtocol.class); oprot = mock(TProtocol.class); } @Test public void testWrongMessageType() throws TException { when(iprot.readMessageBegin()).thenReturn(new TMessage("service:func", TMessageType.REPLY, 42)); assertThrows(TException.class, () -> mp.process(iprot, oprot)); } @Test public void testNoSuchService() throws TException { when(iprot.readMessageBegin()).thenReturn(new TMessage("service:func", TMessageType.CALL, 42)); assertThrows(TException.class, () -> mp.process(iprot, oprot)); } static class StubProcessor implements TProcessor { @Override public void process(TProtocol in, TProtocol out) throws TException { TMessage msg = in.readMessageBegin(); if (!"func".equals(msg.name) || msg.type != TMessageType.CALL || msg.seqid != 42) { throw new TException("incorrect parameters"); } out.writeMessageBegin(new TMessage("func", TMessageType.REPLY, 42)); } } @Test public void testExistingService() throws TException { when(iprot.readMessageBegin()).thenReturn(new TMessage("service:func", TMessageType.CALL, 42)); mp.registerProcessor("service", new StubProcessor()); mp.process(iprot, oprot); verify(oprot).writeMessageBegin(any(TMessage.class)); } @Test public void testDefaultService() throws TException { when(iprot.readMessageBegin()).thenReturn(new TMessage("func", TMessageType.CALL, 42)); mp.registerDefault(new StubProcessor()); mp.process(iprot, oprot); verify(oprot).writeMessageBegin(any(TMessage.class)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/0000777000000000000000000000000014370300523024074 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/TestNonblockingServer.java0000644000000000000000000001051314303740367031237 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import static org.junit.jupiter.api.Assertions.fail; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.TNonblockingServer.Args; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportFactory; import org.apache.thrift.transport.layered.TFramedTransport; import org.junit.jupiter.api.Test; import thrift.test.ThriftTest; public class TestNonblockingServer extends ServerTestBase { private Thread serverThread; private TServer server; private static final int NUM_QUERIES = 1000; protected TServer getServer( TProcessor processor, TNonblockingServerSocket socket, TProtocolFactory protoFactory, TTransportFactory factory) { final Args args = new Args(socket).processor(processor).protocolFactory(protoFactory); if (factory != null) { args.transportFactory(factory); } return new TNonblockingServer(args); } @Override public void startServer( final TProcessor processor, final TProtocolFactory protoFactory, final TTransportFactory factory) throws Exception { serverThread = new Thread() { public void run() { try { // Transport TNonblockingServerSocket tServerSocket = new TNonblockingServerSocket( new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs() .port(PORT)); server = getServer(processor, tServerSocket, protoFactory, factory); // Run it System.out.println("Starting the server on port " + PORT + "..."); server.serve(); } catch (Exception e) { e.printStackTrace(); fail(); } } }; serverThread.start(); Thread.sleep(1000); } @Override public void stopServer() throws Exception { server.stop(); try { serverThread.join(); } catch (InterruptedException e) { } } @Override public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { return new TFramedTransport(underlyingTransport); } @Test public void testCleanupAllSelectionKeys() throws Exception { for (TProtocolFactory protoFactory : getProtocols()) { TestHandler handler = new TestHandler(); ThriftTest.Processor processor = new ThriftTest.Processor(handler); startServer(processor, protoFactory); TSocket socket = new TSocket(HOST, PORT); socket.setTimeout(SOCKET_TIMEOUT); TTransport transport = getClientTransport(socket); TProtocol protocol = protoFactory.getProtocol(transport); ThriftTest.Client testClient = new ThriftTest.Client(protocol); open(transport); for (int i = 0; i < NUM_QUERIES; ++i) { testClient.testI32(1); } server.stop(); for (int i = 0; i < NUM_QUERIES; ++i) { try { testClient.testI32(1); } catch (TTransportException e) { System.err.println(e); e.printStackTrace(); if (e.getCause() instanceof java.net.SocketTimeoutException) { fail("timed out when it should have thrown another kind of error!"); } } } transport.close(); stopServer(); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/TestThreadedSelectorServer.java0000644000000000000000000000253514303740367032222 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.TThreadedSelectorServer.Args; import org.apache.thrift.transport.TNonblockingServerSocket; public class TestThreadedSelectorServer extends TestNonblockingServer { protected TServer getServer( TProcessor processor, TNonblockingServerSocket socket, TProtocolFactory protoFactory) { return new TThreadedSelectorServer( new Args(socket).processor(processor).protocolFactory(protoFactory)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/TestAsyncServer.java0000644000000000000000000000171714303740367030057 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; public class TestAsyncServer extends TestNonblockingServer { @Override public boolean useAsyncProcessor() { return true; } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/TestSaslNonblockingServer.java0000644000000000000000000001055014303740367032063 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.AUTHENTICATION_FAILURE; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TNonblockingServerSocket; import org.apache.thrift.transport.TNonblockingServerTransport; import org.apache.thrift.transport.TSaslClientTransport; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportFactory; import org.apache.thrift.transport.TestTSaslTransports; import org.apache.thrift.transport.TestTSaslTransports.TestSaslCallbackHandler; import org.apache.thrift.transport.sasl.TSaslNegotiationException; import org.junit.jupiter.api.Test; import thrift.test.ThriftTest; public class TestSaslNonblockingServer extends TestTSaslTransports.TestTSaslTransportsWithServer { private TSaslNonblockingServer server; @Override public void startServer( TProcessor processor, TProtocolFactory protoFactory, TTransportFactory factory) throws Exception { TNonblockingServerTransport serverSocket = new TNonblockingServerSocket( new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs().port(PORT)); TSaslNonblockingServer.Args args = new TSaslNonblockingServer.Args(serverSocket) .processor(processor) .transportFactory(factory) .protocolFactory(protoFactory) .addSaslMechanism( TestTSaslTransports.WRAPPED_MECHANISM, TestTSaslTransports.SERVICE, TestTSaslTransports.HOST, TestTSaslTransports.WRAPPED_PROPS, new TestSaslCallbackHandler(TestTSaslTransports.PASSWORD)); server = new TSaslNonblockingServer(args); server.serve(); } @Override public void stopServer() throws Exception { server.shutdown(); } @Override @Test public void testIt() throws Exception { super.testIt(); } @Test public void testBadPassword() throws Exception { TProtocolFactory protocolFactory = new TBinaryProtocol.Factory(); TProcessor processor = new ThriftTest.Processor<>(new TestHandler()); startServer(processor, protocolFactory); TSocket socket = new TSocket(HOST, PORT); socket.setTimeout(SOCKET_TIMEOUT); try (TSaslClientTransport client = new TSaslClientTransport( TestTSaslTransports.WRAPPED_MECHANISM, TestTSaslTransports.PRINCIPAL, TestTSaslTransports.SERVICE, TestTSaslTransports.HOST, TestTSaslTransports.WRAPPED_PROPS, new TestSaslCallbackHandler("bad_password"), socket)) { TTransportException error = assertThrows( TTransportException.class, client::open, "Client should fail with sasl negotiation."); TSaslNegotiationException serverSideError = new TSaslNegotiationException( AUTHENTICATION_FAILURE, "Authentication failed with " + TestTSaslTransports.WRAPPED_MECHANISM); assertTrue( error.getMessage().contains(serverSideError.getSummary()), "Server should return error message \"" + serverSideError.getSummary() + "\""); } finally { stopServer(); } } @Test @Override public void testTransportFactory() { // This test is irrelevant here, so skipped. } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/TestHsHaServer.java0000644000000000000000000000246014303740367027621 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.THsHaServer.Args; import org.apache.thrift.transport.TNonblockingServerSocket; public class TestHsHaServer extends TestNonblockingServer { protected TServer getServer( TProcessor processor, TNonblockingServerSocket socket, TProtocolFactory protoFactory) { return new THsHaServer(new Args(socket).processor(processor).protocolFactory(protoFactory)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/ServerTestBase.java0000644000000000000000000006064514370300523027647 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.async.AsyncMethodCallback; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportFactory; import org.apache.thrift.transport.layered.TFramedTransport; import org.apache.thrift.transport.layered.TFramedTransport.Factory; import org.junit.jupiter.api.Test; import thrift.test.Insanity; import thrift.test.Numberz; import thrift.test.ThriftTest; import thrift.test.Xception; import thrift.test.Xception2; import thrift.test.Xtruct; import thrift.test.Xtruct2; public abstract class ServerTestBase { public static class TestHandler implements ThriftTest.Iface { public TestHandler() {} @Override public void testVoid() { System.out.print("testVoid()\n"); } @Override public String testString(String thing) { System.out.print("testString(\"" + thing + "\")\n"); return thing; } @Override public boolean testBool(boolean thing) { System.out.print("testBool(" + thing + ")\n"); return thing; } @Override public byte testByte(byte thing) { System.out.print("testByte(" + thing + ")\n"); return thing; } @Override public int testI32(int thing) { System.out.print("testI32(" + thing + ")\n"); return thing; } @Override public long testI64(long thing) { System.out.print("testI64(" + thing + ")\n"); return thing; } @Override public double testDouble(double thing) { System.out.print("testDouble(" + thing + ")\n"); return thing; } @Override public ByteBuffer testBinary(ByteBuffer thing) { StringBuilder sb = new StringBuilder(thing.remaining() * 3); thing.mark(); int limit = 0; // limit output to keep the log size sane while ((thing.remaining() > 0) && (++limit < 1024)) { sb.append(String.format("%02X ", thing.get())); } if (thing.remaining() > 0) { sb.append("..."); // indicate we have more date } System.out.print("testBinary(" + sb + ")\n"); thing.reset(); return thing; } @Override public UUID testUuid(UUID thing) throws TException { System.out.println("testUuid(" + thing + ")"); return thing; } @Override public Xtruct testStruct(Xtruct thing) { System.out.print( "testStruct({" + "\"" + thing.string_thing + "\", " + thing.byte_thing + ", " + thing.i32_thing + ", " + thing.i64_thing + "})\n"); return thing; } @Override public Xtruct2 testNest(Xtruct2 nest) { Xtruct thing = nest.struct_thing; System.out.print( "testNest({" + nest.byte_thing + ", {" + "\"" + thing.string_thing + "\", " + thing.byte_thing + ", " + thing.i32_thing + ", " + thing.i64_thing + "}, " + nest.i32_thing + "})\n"); return nest; } @Override public Map testMap(Map thing) { System.out.print("testMap({"); System.out.print(thing); System.out.print("})\n"); return thing; } @Override public Map testStringMap(Map thing) { System.out.print("testStringMap({"); System.out.print(thing); System.out.print("})\n"); return thing; } @Override public Set testSet(Set thing) { System.out.print("testSet({"); boolean first = true; for (int elem : thing) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(elem); } System.out.print("})\n"); return thing; } @Override public List testList(List thing) { System.out.print("testList({"); boolean first = true; for (int elem : thing) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(elem); } System.out.print("})\n"); return thing; } @Override public Numberz testEnum(Numberz thing) { System.out.print("testEnum(" + thing + ")\n"); return thing; } @Override public long testTypedef(long thing) { System.out.print("testTypedef(" + thing + ")\n"); return thing; } @Override public Map> testMapMap(int hello) { System.out.print("testMapMap(" + hello + ")\n"); Map> mapmap = new HashMap<>(); HashMap pos = new HashMap<>(); HashMap neg = new HashMap<>(); for (int i = 1; i < 5; i++) { pos.put(i, i); neg.put(-i, -i); } mapmap.put(4, pos); mapmap.put(-4, neg); return mapmap; } @Override public Map> testInsanity(Insanity argument) { System.out.print("testInsanity()\n"); HashMap first_map = new HashMap<>(); HashMap second_map = new HashMap<>(); first_map.put(Numberz.TWO, argument); first_map.put(Numberz.THREE, argument); Insanity looney = new Insanity(new HashMap<>(), Arrays.asList()); second_map.put(Numberz.SIX, looney); Map> insane = new HashMap<>(); insane.put((long) 1, first_map); insane.put((long) 2, second_map); return insane; } @Override public Xtruct testMulti( byte arg0, int arg1, long arg2, Map arg3, Numberz arg4, long arg5) { System.out.print("testMulti()\n"); Xtruct hello = new Xtruct(); hello.string_thing = "Hello2"; hello.byte_thing = arg0; hello.i32_thing = arg1; hello.i64_thing = arg2; return hello; } @Override public void testException(String arg) throws TException { System.out.print("testException(" + arg + ")\n"); if ("Xception".equals(arg)) { Xception x = new Xception(); x.errorCode = 1001; x.message = arg; throw x; } else if ("TException".equals(arg)) { // Unspecified exception should yield a TApplicationException on client side throw new RuntimeException(arg); } else { Xtruct result = new Xtruct(); result.string_thing = arg; } return; } @Override public Xtruct testMultiException(String arg0, String arg1) throws Xception, Xception2 { System.out.print("testMultiException(" + arg0 + ", " + arg1 + ")\n"); if (arg0.equals("Xception")) { Xception x = new Xception(); x.errorCode = 1001; x.message = "This is an Xception"; throw x; } else if (arg0.equals("Xception2")) { Xception2 x = new Xception2(); x.errorCode = 2002; x.struct_thing = new Xtruct(); x.struct_thing.string_thing = "This is an Xception2"; throw x; } Xtruct result = new Xtruct(); result.string_thing = arg1; return result; } @Override public void testOneway(int sleepFor) { System.out.println("testOneway(" + sleepFor + ") => sleeping..."); try { Thread.sleep(sleepFor * SLEEP_DELAY); System.out.println("Done sleeping!"); } catch (InterruptedException ie) { throw new RuntimeException(ie); } } } // class TestHandler private static final List PROTOCOLS = Arrays.asList(new TBinaryProtocol.Factory(), new TCompactProtocol.Factory()); public static final String HOST = "localhost"; public static final int PORT = Integer.parseInt(System.getProperty("test.port", "9090")); protected static final long SLEEP_DELAY = 1000; protected static final int SOCKET_TIMEOUT = 1500; private static final Xtruct XSTRUCT = new Xtruct("Zero", (byte) 1, -3, -5); private static final Xtruct2 XSTRUCT2 = new Xtruct2((byte) 1, XSTRUCT, 5); public void startServer(TProcessor processor, TProtocolFactory protoFactory) throws Exception { startServer(processor, protoFactory, null); } public abstract void startServer( TProcessor processor, TProtocolFactory protoFactory, TTransportFactory factory) throws Exception; public abstract void stopServer() throws Exception; public abstract TTransport getClientTransport(TTransport underlyingTransport) throws Exception; private void testBool(ThriftTest.Client testClient) throws TException { boolean t = testClient.testBool(true); assertTrue(t); boolean f = testClient.testBool(false); assertFalse(f); } private void testByte(ThriftTest.Client testClient) throws TException { byte i8 = testClient.testByte((byte) 1); assertEquals(1, i8); } private void testUuid(ThriftTest.Client testClient) throws TException { UUID uuid = UUID.fromString("00112233-4455-6677-8899-aabbccddeeff"); UUID got = testClient.testUuid(uuid); assertEquals(uuid, got); } private void testDouble(ThriftTest.Client testClient) throws TException { double dub = testClient.testDouble(5.325098235); assertEquals(5.325098235, dub); } private void testEnum(ThriftTest.Client testClient) throws TException { assertEquals(Numberz.ONE, testClient.testEnum(Numberz.ONE)); assertEquals(Numberz.TWO, testClient.testEnum(Numberz.TWO)); assertEquals(Numberz.THREE, testClient.testEnum(Numberz.THREE)); assertEquals(Numberz.FIVE, testClient.testEnum(Numberz.FIVE)); assertEquals(Numberz.EIGHT, testClient.testEnum(Numberz.EIGHT)); } private void testI32(ThriftTest.Client testClient) throws TException { int i32 = testClient.testI32(-1); assertEquals(i32, -1); } private void testI64(ThriftTest.Client testClient) throws TException { long i64 = testClient.testI64(-34359738368L); assertEquals(i64, -34359738368L); } // todo: add assertions private void testInsanity(ThriftTest.Client testClient) throws TException { Insanity insane; insane = new Insanity(); insane.userMap = new HashMap<>(); insane.userMap.put(Numberz.FIVE, (long) 5000); Xtruct truck = new Xtruct(); truck.string_thing = "Truck"; truck.byte_thing = (byte) 8; truck.i32_thing = 8; truck.i64_thing = 8; insane.xtructs = new ArrayList<>(); insane.xtructs.add(truck); System.out.print("testInsanity()"); Map> whoa = testClient.testInsanity(insane); System.out.print(" = {"); for (long key : whoa.keySet()) { Map val = whoa.get(key); System.out.print(key + " => {"); for (Numberz k2 : val.keySet()) { Insanity v2 = val.get(k2); System.out.print(k2 + " => {"); Map userMap = v2.userMap; System.out.print("{"); if (userMap != null) { for (Numberz k3 : userMap.keySet()) { System.out.print(k3 + " => " + userMap.get(k3) + ", "); } } System.out.print("}, "); List xtructs = v2.xtructs; System.out.print("{"); if (xtructs != null) { for (Xtruct x : xtructs) { System.out.print( "{" + "\"" + x.string_thing + "\", " + x.byte_thing + ", " + x.i32_thing + ", " + x.i64_thing + "}, "); } } System.out.print("}"); System.out.print("}, "); } System.out.print("}, "); } System.out.print("}\n"); } public boolean useAsyncProcessor() { return false; } @Test public void testIt() throws Exception { for (TProtocolFactory protoFactory : getProtocols()) { TProcessor processor = useAsyncProcessor() ? new ThriftTest.AsyncProcessor<>(new AsyncTestHandler()) : new ThriftTest.Processor<>(new TestHandler()); startServer(processor, protoFactory); TSocket socket = new TSocket(HOST, PORT); socket.setTimeout(SOCKET_TIMEOUT); TTransport transport = getClientTransport(socket); TProtocol protocol = protoFactory.getProtocol(transport); ThriftTest.Client testClient = new ThriftTest.Client(protocol); open(transport); testVoid(testClient); testString(testClient); testBool(testClient); testByte(testClient); testI32(testClient); testI64(testClient); testDouble(testClient); testStruct(testClient); testNestedStruct(testClient); testMap(testClient); testUuid(testClient); testStringMap(testClient); testSet(testClient); testList(testClient); testEnum(testClient); testTypedef(testClient); testNestedMap(testClient); testInsanity(testClient); testException(testClient); testOneway(testClient); testI32(testClient); transport.close(); socket.close(); stopServer(); } } public void open(TTransport transport) throws Exception { transport.open(); } public List getProtocols() { return PROTOCOLS; } private void testList(ThriftTest.Client testClient) throws TException { List listout = new ArrayList<>(); for (int i = -2; i < 3; ++i) { listout.add(i); } List listin = testClient.testList(listout); assertEquals(listout, listin); } private void testMap(ThriftTest.Client testClient) throws TException { Map mapout = new HashMap<>(); for (int i = 0; i < 5; ++i) { mapout.put(i, i - 10); } Map mapin = testClient.testMap(mapout); assertEquals(mapout, mapin); } private void testStringMap(ThriftTest.Client testClient) throws TException { Map mapout = new HashMap<>(); mapout.put("a", "123"); mapout.put(" x y ", " with spaces "); mapout.put("same", "same"); mapout.put("0", "numeric key"); Map mapin = testClient.testStringMap(mapout); assertEquals(mapout, mapin); } private void testNestedMap(ThriftTest.Client testClient) throws TException { Map> mm = testClient.testMapMap(1); Map> mapmap = new HashMap<>(); HashMap pos = new HashMap<>(); HashMap neg = new HashMap<>(); for (int i = 1; i < 5; i++) { pos.put(i, i); neg.put(-i, -i); } mapmap.put(4, pos); mapmap.put(-4, neg); assertEquals(mapmap, mm); } private void testNestedStruct(ThriftTest.Client testClient) throws TException { Xtruct2 in2 = testClient.testNest(XSTRUCT2); assertEquals(XSTRUCT2, in2); } private void testOneway(ThriftTest.Client testClient) throws Exception { long begin = System.currentTimeMillis(); testClient.testOneway(1); long elapsed = System.currentTimeMillis() - begin; assertTrue(elapsed < 500); } private void testSet(ThriftTest.Client testClient) throws TException { Set setout = new HashSet<>(); for (int i = -2; i < 3; ++i) { setout.add(i); } Set setin = testClient.testSet(setout); assertEquals(setout, setin); } private void testString(ThriftTest.Client testClient) throws TException { String s = testClient.testString("Test"); assertEquals("Test", s); } private void testStruct(ThriftTest.Client testClient) throws TException { assertEquals(XSTRUCT, testClient.testStruct(XSTRUCT)); } private void testTypedef(ThriftTest.Client testClient) throws TException { assertEquals(309858235082523L, testClient.testTypedef(309858235082523L)); } private void testVoid(ThriftTest.Client testClient) throws TException { testClient.testVoid(); } private static class CallCountingTransportFactory extends TTransportFactory { public int count = 0; private final Factory factory; public CallCountingTransportFactory(Factory factory) { this.factory = factory; } @Override public TTransport getTransport(TTransport trans) throws TTransportException { count++; return factory.getTransport(trans); } } @Test public void testTransportFactory() throws Exception { for (TProtocolFactory protoFactory : getProtocols()) { TestHandler handler = new TestHandler(); ThriftTest.Processor processor = new ThriftTest.Processor<>(handler); final CallCountingTransportFactory factory = new CallCountingTransportFactory(new TFramedTransport.Factory()); startServer(processor, protoFactory, factory); assertEquals(0, factory.count); TSocket socket = new TSocket(HOST, PORT); socket.setTimeout(SOCKET_TIMEOUT); TTransport transport = getClientTransport(socket); open(transport); TProtocol protocol = protoFactory.getProtocol(transport); ThriftTest.Client testClient = new ThriftTest.Client(protocol); assertEquals(0, testClient.testByte((byte) 0)); assertEquals(2, factory.count); socket.close(); stopServer(); } } private void testException(ThriftTest.Client testClient) throws TException { try { testClient.testException("Xception"); assert false; } catch (Xception e) { assertEquals(e.message, "Xception"); assertEquals(e.errorCode, 1001); } try { testClient.testException("TException"); assert false; } catch (TException e) { } testClient.testException("no Exception"); } public static class AsyncTestHandler implements ThriftTest.AsyncIface { TestHandler handler = new TestHandler(); @Override public void testVoid(AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(null); } @Override public void testString(String thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testString(thing)); } @Override public void testBool(boolean thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testBool(thing)); } @Override public void testByte(byte thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testByte(thing)); } @Override public void testI32(int thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testI32(thing)); } @Override public void testI64(long thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testI64(thing)); } @Override public void testDouble(double thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testDouble(thing)); } @Override public void testBinary(ByteBuffer thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testBinary(thing)); } @Override public void testUuid(UUID thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testUuid(thing)); } @Override public void testStruct(Xtruct thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testStruct(thing)); } @Override public void testNest(Xtruct2 thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testNest(thing)); } @Override public void testMap( Map thing, AsyncMethodCallback> resultHandler) throws TException { resultHandler.onComplete(handler.testMap(thing)); } @Override public void testStringMap( Map thing, AsyncMethodCallback> resultHandler) throws TException { resultHandler.onComplete(handler.testStringMap(thing)); } @Override public void testSet(Set thing, AsyncMethodCallback> resultHandler) throws TException { resultHandler.onComplete(handler.testSet(thing)); } @Override public void testList(List thing, AsyncMethodCallback> resultHandler) throws TException { resultHandler.onComplete(handler.testList(thing)); } @Override public void testEnum(Numberz thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testEnum(thing)); } @Override public void testTypedef(long thing, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testTypedef(thing)); } @Override public void testMapMap( int hello, AsyncMethodCallback>> resultHandler) throws TException { resultHandler.onComplete(handler.testMapMap(hello)); } @Override public void testInsanity( Insanity argument, AsyncMethodCallback>> resultHandler) throws TException { resultHandler.onComplete(handler.testInsanity(argument)); } @Override public void testMulti( byte arg0, int arg1, long arg2, Map arg3, Numberz arg4, long arg5, AsyncMethodCallback resultHandler) throws TException { resultHandler.onComplete(handler.testMulti(arg0, arg1, arg2, arg3, arg4, arg5)); } @Override public void testException(String arg, AsyncMethodCallback resultHandler) throws TException { System.out.print("testException(" + arg + ")\n"); if ("Xception".equals(arg)) { Xception x = new Xception(); x.errorCode = 1001; x.message = arg; // throw and onError yield the same result. // throw x; resultHandler.onError(x); return; } else if ("TException".equals(arg)) { // throw and onError yield the same result. // resultHandler.onError(new TException(arg)); // return; // Unspecified exception should yield a TApplicationException on client side throw new RuntimeException(arg); } resultHandler.onComplete(null); } @Override public void testMultiException( String arg0, String arg1, AsyncMethodCallback resultHandler) throws TException { // To change body of implemented methods use File | Settings | File Templates. } @Override public void testOneway(int secondsToSleep, AsyncMethodCallback resultHandler) throws TException { handler.testOneway(secondsToSleep); resultHandler.onComplete(null); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/server/TestThreadPoolServer.java0000644000000000000000000000545214303740367031043 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.server; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.concurrent.ThreadPoolExecutor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TSocket; import org.junit.jupiter.api.Test; import thrift.test.ThriftTest; public class TestThreadPoolServer { /** Test server is shut down properly even with some open clients. */ @Test public void testStopServerWithOpenClient() throws Exception { TServerSocket serverSocket = new TServerSocket(0, 3000); TThreadPoolServer server = buildServer(serverSocket); Thread serverThread = new Thread(server::serve); serverThread.start(); try (TSocket client = new TSocket("localhost", serverSocket.getServerSocket().getLocalPort())) { client.open(); Thread.sleep(1000); // There is a thread listening to the client assertEquals(1, ((ThreadPoolExecutor) server.getExecutorService()).getActiveCount()); // Trigger the server to stop, but it does not wait server.stop(); assertTrue(server.waitForShutdown()); // After server is stopped, the executor thread pool should be shut down assertTrue( server.getExecutorService().isTerminated(), "Server thread pool should be terminated"); // TODO: The socket is actually closed (timeout) but the client code // ignores the timeout Exception and maintains the socket open state assertTrue(client.isOpen(), "Client should be closed after server shutdown"); } } private TThreadPoolServer buildServer(TServerTransport serverSocket) { TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverSocket) .protocolFactory(new TBinaryProtocol.Factory()) .processor(new ThriftTest.Processor<>(new ServerTestBase.TestHandler())); return new TThreadPoolServer(args); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/Fixtures.java0000644000000000000000000006461114303740367025260 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import thrift.test.Bonk; import thrift.test.CompactProtoTestStruct; import thrift.test.HolyMoley; import thrift.test.Nesting; import thrift.test.OneOfEach; public class Fixtures { public static OneOfEach getOneOfEach() { return oneOfEach.deepCopy(); } public static Nesting getNesting() { return nesting.deepCopy(); } public static HolyMoley getHolyMoley() { return holyMoley.deepCopy(); } public static CompactProtoTestStruct getCompactProtoTestStruct() { return compactProtoTestStruct.deepCopy(); } public static byte[] getPersistentBytesOneOfEach() { return persistentBytesOneOfEach.clone(); } public static byte[] getPersistentBytesHolyMoley() { return persistentBytesHolyMoley.clone(); } public static byte[] getPersistentBytesNesting() { return persistentBytesNesting.clone(); } private static final OneOfEach oneOfEach; private static final Nesting nesting; private static final HolyMoley holyMoley; private static final CompactProtoTestStruct compactProtoTestStruct; // These byte arrays are serialized versions of the above structs. // They were serialized in binary protocol using thrift 0.6.x and are used to // test backwards compatibility with respect to the standard scheme. private static final byte[] persistentBytesOneOfEach = new byte[] { (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0xD6, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x69, (byte) 0x78, (byte) 0x08, (byte) 0x00, (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x65, (byte) 0xA0, (byte) 0xBC, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0x40, (byte) 0x09, (byte) 0x21, (byte) 0xFB, (byte) 0x54, (byte) 0x44, (byte) 0x2D, (byte) 0x18, (byte) 0x0B, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0D, (byte) 0x4A, (byte) 0x53, (byte) 0x4F, (byte) 0x4E, (byte) 0x20, (byte) 0x54, (byte) 0x48, (byte) 0x49, (byte) 0x53, (byte) 0x21, (byte) 0x20, (byte) 0x22, (byte) 0x01, (byte) 0x0B, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2E, (byte) 0xD3, (byte) 0x80, (byte) 0xE2, (byte) 0x85, (byte) 0xAE, (byte) 0xCE, (byte) 0x9D, (byte) 0x20, (byte) 0xD0, (byte) 0x9D, (byte) 0xCE, (byte) 0xBF, (byte) 0xE2, (byte) 0x85, (byte) 0xBF, (byte) 0xD0, (byte) 0xBE, (byte) 0xC9, (byte) 0xA1, (byte) 0xD0, (byte) 0xB3, (byte) 0xD0, (byte) 0xB0, (byte) 0xCF, (byte) 0x81, (byte) 0xE2, (byte) 0x84, (byte) 0x8E, (byte) 0x20, (byte) 0xCE, (byte) 0x91, (byte) 0x74, (byte) 0x74, (byte) 0xCE, (byte) 0xB1, (byte) 0xE2, (byte) 0x85, (byte) 0xBD, (byte) 0xCE, (byte) 0xBA, (byte) 0xEF, (byte) 0xBF, (byte) 0xBD, (byte) 0xE2, (byte) 0x80, (byte) 0xBC, (byte) 0x02, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x62, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x36, (byte) 0x34, (byte) 0x0F, (byte) 0x00, (byte) 0x0C, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0D, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0E, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00 }; private static final byte[] persistentBytesNesting = new byte[] { (byte) 0x0C, (byte) 0x00, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x7A, (byte) 0x69, (byte) 0x0B, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x13, (byte) 0x49, (byte) 0x20, (byte) 0x61, (byte) 0x6D, (byte) 0x20, (byte) 0x61, (byte) 0x20, (byte) 0x62, (byte) 0x6F, (byte) 0x6E, (byte) 0x6B, (byte) 0x2E, (byte) 0x2E, (byte) 0x2E, (byte) 0x20, (byte) 0x78, (byte) 0x6F, (byte) 0x72, (byte) 0x21, (byte) 0x00, (byte) 0x0C, (byte) 0x00, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0xD6, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x69, (byte) 0x78, (byte) 0x08, (byte) 0x00, (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x65, (byte) 0xA0, (byte) 0xBC, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0x40, (byte) 0x09, (byte) 0x21, (byte) 0xFB, (byte) 0x54, (byte) 0x44, (byte) 0x2D, (byte) 0x18, (byte) 0x0B, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0D, (byte) 0x4A, (byte) 0x53, (byte) 0x4F, (byte) 0x4E, (byte) 0x20, (byte) 0x54, (byte) 0x48, (byte) 0x49, (byte) 0x53, (byte) 0x21, (byte) 0x20, (byte) 0x22, (byte) 0x01, (byte) 0x0B, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2E, (byte) 0xD3, (byte) 0x80, (byte) 0xE2, (byte) 0x85, (byte) 0xAE, (byte) 0xCE, (byte) 0x9D, (byte) 0x20, (byte) 0xD0, (byte) 0x9D, (byte) 0xCE, (byte) 0xBF, (byte) 0xE2, (byte) 0x85, (byte) 0xBF, (byte) 0xD0, (byte) 0xBE, (byte) 0xC9, (byte) 0xA1, (byte) 0xD0, (byte) 0xB3, (byte) 0xD0, (byte) 0xB0, (byte) 0xCF, (byte) 0x81, (byte) 0xE2, (byte) 0x84, (byte) 0x8E, (byte) 0x20, (byte) 0xCE, (byte) 0x91, (byte) 0x74, (byte) 0x74, (byte) 0xCE, (byte) 0xB1, (byte) 0xE2, (byte) 0x85, (byte) 0xBD, (byte) 0xCE, (byte) 0xBA, (byte) 0xEF, (byte) 0xBF, (byte) 0xBD, (byte) 0xE2, (byte) 0x80, (byte) 0xBC, (byte) 0x02, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x62, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x36, (byte) 0x34, (byte) 0x0F, (byte) 0x00, (byte) 0x0C, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0D, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0E, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00 }; private static final byte[] persistentBytesHolyMoley = new byte[] { (byte) 0x0F, (byte) 0x00, (byte) 0x01, (byte) 0x0C, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0x23, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x69, (byte) 0x78, (byte) 0x08, (byte) 0x00, (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x65, (byte) 0xA0, (byte) 0xBC, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0x40, (byte) 0x09, (byte) 0x21, (byte) 0xFB, (byte) 0x54, (byte) 0x44, (byte) 0x2D, (byte) 0x18, (byte) 0x0B, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0D, (byte) 0x4A, (byte) 0x53, (byte) 0x4F, (byte) 0x4E, (byte) 0x20, (byte) 0x54, (byte) 0x48, (byte) 0x49, (byte) 0x53, (byte) 0x21, (byte) 0x20, (byte) 0x22, (byte) 0x01, (byte) 0x0B, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2E, (byte) 0xD3, (byte) 0x80, (byte) 0xE2, (byte) 0x85, (byte) 0xAE, (byte) 0xCE, (byte) 0x9D, (byte) 0x20, (byte) 0xD0, (byte) 0x9D, (byte) 0xCE, (byte) 0xBF, (byte) 0xE2, (byte) 0x85, (byte) 0xBF, (byte) 0xD0, (byte) 0xBE, (byte) 0xC9, (byte) 0xA1, (byte) 0xD0, (byte) 0xB3, (byte) 0xD0, (byte) 0xB0, (byte) 0xCF, (byte) 0x81, (byte) 0xE2, (byte) 0x84, (byte) 0x8E, (byte) 0x20, (byte) 0xCE, (byte) 0x91, (byte) 0x74, (byte) 0x74, (byte) 0xCE, (byte) 0xB1, (byte) 0xE2, (byte) 0x85, (byte) 0xBD, (byte) 0xCE, (byte) 0xBA, (byte) 0xEF, (byte) 0xBF, (byte) 0xBD, (byte) 0xE2, (byte) 0x80, (byte) 0xBC, (byte) 0x02, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x62, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x36, (byte) 0x34, (byte) 0x0F, (byte) 0x00, (byte) 0x0C, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0D, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0E, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x03, (byte) 0xD6, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x69, (byte) 0x78, (byte) 0x08, (byte) 0x00, (byte) 0x05, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x65, (byte) 0xA0, (byte) 0xBC, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0x40, (byte) 0x09, (byte) 0x21, (byte) 0xFB, (byte) 0x54, (byte) 0x44, (byte) 0x2D, (byte) 0x18, (byte) 0x0B, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0D, (byte) 0x4A, (byte) 0x53, (byte) 0x4F, (byte) 0x4E, (byte) 0x20, (byte) 0x54, (byte) 0x48, (byte) 0x49, (byte) 0x53, (byte) 0x21, (byte) 0x20, (byte) 0x22, (byte) 0x01, (byte) 0x0B, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x2E, (byte) 0xD3, (byte) 0x80, (byte) 0xE2, (byte) 0x85, (byte) 0xAE, (byte) 0xCE, (byte) 0x9D, (byte) 0x20, (byte) 0xD0, (byte) 0x9D, (byte) 0xCE, (byte) 0xBF, (byte) 0xE2, (byte) 0x85, (byte) 0xBF, (byte) 0xD0, (byte) 0xBE, (byte) 0xC9, (byte) 0xA1, (byte) 0xD0, (byte) 0xB3, (byte) 0xD0, (byte) 0xB0, (byte) 0xCF, (byte) 0x81, (byte) 0xE2, (byte) 0x84, (byte) 0x8E, (byte) 0x20, (byte) 0xCE, (byte) 0x91, (byte) 0x74, (byte) 0x74, (byte) 0xCE, (byte) 0xB1, (byte) 0xE2, (byte) 0x85, (byte) 0xBD, (byte) 0xCE, (byte) 0xBA, (byte) 0xEF, (byte) 0xBF, (byte) 0xBD, (byte) 0xE2, (byte) 0x80, (byte) 0xBC, (byte) 0x02, (byte) 0x00, (byte) 0x0A, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x62, (byte) 0x61, (byte) 0x73, (byte) 0x65, (byte) 0x36, (byte) 0x34, (byte) 0x0F, (byte) 0x00, (byte) 0x0C, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0D, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x0F, (byte) 0x00, (byte) 0x0E, (byte) 0x0A, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x0E, (byte) 0x00, (byte) 0x02, (byte) 0x0F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0x74, (byte) 0x68, (byte) 0x65, (byte) 0x6E, (byte) 0x20, (byte) 0x61, (byte) 0x20, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x2C, (byte) 0x20, (byte) 0x74, (byte) 0x77, (byte) 0x6F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x74, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x65, (byte) 0x21, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x06, (byte) 0x46, (byte) 0x4F, (byte) 0x55, (byte) 0x52, (byte) 0x21, (byte) 0x21, (byte) 0x0B, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x09, (byte) 0x61, (byte) 0x6E, (byte) 0x64, (byte) 0x20, (byte) 0x61, (byte) 0x20, (byte) 0x6F, (byte) 0x6E, (byte) 0x65, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x09, (byte) 0x61, (byte) 0x6E, (byte) 0x64, (byte) 0x20, (byte) 0x61, (byte) 0x20, (byte) 0x74, (byte) 0x77, (byte) 0x6F, (byte) 0x0D, (byte) 0x00, (byte) 0x03, (byte) 0x0B, (byte) 0x0F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x03, (byte) 0x74, (byte) 0x77, (byte) 0x6F, (byte) 0x0C, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x08, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x0B, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x57, (byte) 0x61, (byte) 0x69, (byte) 0x74, (byte) 0x2E, (byte) 0x00, (byte) 0x08, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x0B, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x57, (byte) 0x68, (byte) 0x61, (byte) 0x74, (byte) 0x3F, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05, (byte) 0x74, (byte) 0x68, (byte) 0x72, (byte) 0x65, (byte) 0x65, (byte) 0x0C, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x7A, (byte) 0x65, (byte) 0x72, (byte) 0x6F, (byte) 0x0C, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; private static final byte[] kUnicodeBytes = { (byte) 0xd3, (byte) 0x80, (byte) 0xe2, (byte) 0x85, (byte) 0xae, (byte) 0xce, (byte) 0x9d, (byte) 0x20, (byte) 0xd0, (byte) 0x9d, (byte) 0xce, (byte) 0xbf, (byte) 0xe2, (byte) 0x85, (byte) 0xbf, (byte) 0xd0, (byte) 0xbe, (byte) 0xc9, (byte) 0xa1, (byte) 0xd0, (byte) 0xb3, (byte) 0xd0, (byte) 0xb0, (byte) 0xcf, (byte) 0x81, (byte) 0xe2, (byte) 0x84, (byte) 0x8e, (byte) 0x20, (byte) 0xce, (byte) 0x91, (byte) 0x74, (byte) 0x74, (byte) 0xce, (byte) 0xb1, (byte) 0xe2, (byte) 0x85, (byte) 0xbd, (byte) 0xce, (byte) 0xba, (byte) 0x83, (byte) 0xe2, (byte) 0x80, (byte) 0xbc }; static { try { oneOfEach = new OneOfEach(); oneOfEach.setIm_true(true); oneOfEach.setIm_false(false); oneOfEach.setA_bite((byte) 0xd6); oneOfEach.setInteger16((short) 27000); oneOfEach.setInteger32(1 << 24); oneOfEach.setInteger64((long) 6000 * 1000 * 1000); oneOfEach.setDouble_precision(Math.PI); oneOfEach.setSome_characters("JSON THIS! \"\1"); oneOfEach.setZomg_unicode(new String(kUnicodeBytes, StandardCharsets.UTF_8)); oneOfEach.setBase64(ByteBuffer.wrap("base64".getBytes())); // byte, i16, and i64 lists are populated by default constructor Bonk bonk = new Bonk(); bonk.setType(31337); bonk.setMessage("I am a bonk... xor!"); nesting = new Nesting(bonk, oneOfEach); holyMoley = new HolyMoley(); List big = new ArrayList<>(); big.add(new OneOfEach(oneOfEach)); big.add(nesting.my_ooe); holyMoley.setBig(big); holyMoley.getBig().get(0).setA_bite((byte) 0x22); holyMoley.getBig().get(0).setA_bite((byte) 0x23); holyMoley.setContain(new HashSet<>()); ArrayList stage1 = new ArrayList<>(2); stage1.add("and a one"); stage1.add("and a two"); holyMoley.getContain().add(stage1); stage1 = new ArrayList<>(3); stage1.add("then a one, two"); stage1.add("three!"); stage1.add("FOUR!!"); holyMoley.getContain().add(stage1); stage1 = new ArrayList<>(0); holyMoley.getContain().add(stage1); ArrayList stage2 = new ArrayList<>(); holyMoley.setBonks(new HashMap<>()); // one empty holyMoley.getBonks().put("zero", stage2); // one with two stage2 = new ArrayList<>(); Bonk b = new Bonk(); b.setType(1); b.setMessage("Wait."); stage2.add(b); b = new Bonk(); b.setType(2); b.setMessage("What?"); stage2.add(b); holyMoley.getBonks().put("two", stage2); // one with three stage2 = new ArrayList<>(); b = new Bonk(); b.setType(3); b.setMessage("quoth"); b = new Bonk(); b.setType(4); b.setMessage("the raven"); b = new Bonk(); b.setType(5); b.setMessage("nevermore"); holyMoley.getBonks().put("three", stage2); // superhuge compact proto test struct compactProtoTestStruct = new CompactProtoTestStruct(thrift.test.DebugProtoTestConstants.COMPACT_TEST); compactProtoTestStruct.setA_binary(ByteBuffer.wrap(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8})); } catch (Exception e) { throw new RuntimeException(e); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestStruct.java0000644000000000000000000004210114370300523025547 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import org.apache.thrift.meta_data.FieldMetaData; import org.apache.thrift.meta_data.ListMetaData; import org.apache.thrift.meta_data.MapMetaData; import org.apache.thrift.meta_data.SetMetaData; import org.apache.thrift.meta_data.StructMetaData; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TType; import org.junit.jupiter.api.Test; import thrift.test.Bonk; import thrift.test.CrazyNesting; import thrift.test.HolyMoley; import thrift.test.Insanity; import thrift.test.JavaTestHelper; import thrift.test.Nesting; import thrift.test.Numberz; import thrift.test.OneOfEach; import thrift.test.StructA; import thrift.test.StructB; import thrift.test.Xtruct; public class TestStruct { @Test public void testIdentity() throws Exception { TSerializer binarySerializer = new TSerializer(new TBinaryProtocol.Factory()); TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory()); OneOfEach ooe = Fixtures.getOneOfEach(); Nesting n = new Nesting(); n.my_ooe = ooe; n.my_ooe.integer16 = 16; n.my_ooe.integer32 = 32; n.my_ooe.integer64 = 64; n.my_ooe.double_precision = (Math.sqrt(5) + 1) / 2; n.my_ooe.some_characters = ":R (me going \"rrrr\")"; n.my_ooe.zomg_unicode = "\u04c0\u216e\u039d\u0020\u041d\u03bf\u217f" + "\u043e\u0261\u0433\u0430\u03c1\u210e\u0020" + "\u0391\u0074\u0074\u03b1\u217d\u03ba\u01c3" + "\u203c"; n.my_bonk = Fixtures.getNesting().my_bonk; HolyMoley hm = Fixtures.getHolyMoley(); OneOfEach ooe2 = new OneOfEach(); binaryDeserializer.deserialize(ooe2, binarySerializer.serialize(ooe)); assertEquals(ooe, ooe2); assertEquals(ooe.hashCode(), ooe2.hashCode()); Nesting n2 = new Nesting(); binaryDeserializer.deserialize(n2, binarySerializer.serialize(n)); assertEquals(n, n2); assertEquals(n.hashCode(), n2.hashCode()); HolyMoley hm2 = new HolyMoley(); binaryDeserializer.deserialize(hm2, binarySerializer.serialize(hm)); assertEquals(hm, hm2); assertEquals(hm.hashCode(), hm2.hashCode()); } @Test public void testDeepCopy() throws Exception { TSerializer binarySerializer = new TSerializer(new TBinaryProtocol.Factory()); TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory()); HolyMoley hm = Fixtures.getHolyMoley(); byte[] binaryCopy = binarySerializer.serialize(hm); HolyMoley hmCopy = new HolyMoley(); binaryDeserializer.deserialize(hmCopy, binaryCopy); HolyMoley hmCopy2 = new HolyMoley(hm); assertEquals(hm, hmCopy); assertEquals(hmCopy, hmCopy2); // change binary value in original object hm.big.get(0).base64.array()[0]++; // make sure the change didn't propagate to the copied object assertFalse(hm.equals(hmCopy2)); hm.big.get(0).base64.array()[0]--; // undo change hmCopy2.bonks.get("two").get(1).message = "What else?"; assertFalse(hm.equals(hmCopy2)); } @Test public void testCompareTo() throws Exception { Bonk bonk1 = new Bonk(); Bonk bonk2 = new Bonk(); // Compare empty thrift objects. assertEquals(0, bonk1.compareTo(bonk2)); bonk1.setMessage("m"); // Compare one thrift object with a filled in field and another without it. assertTrue(bonk1.compareTo(bonk2) > 0); assertTrue(bonk2.compareTo(bonk1) < 0); // Compare both have filled-in fields. bonk2.setMessage("z"); assertTrue(bonk1.compareTo(bonk2) < 0); assertTrue(bonk2.compareTo(bonk1) > 0); // Compare bonk1 has a field filled in that bonk2 doesn't. bonk1.setType(123); assertTrue(bonk1.compareTo(bonk2) > 0); assertTrue(bonk2.compareTo(bonk1) < 0); // Compare bonk1 and bonk2 equal. bonk2.setType(123); bonk2.setMessage("m"); assertEquals(0, bonk1.compareTo(bonk2)); } @Test public void testCompareToWithDataStructures() { Insanity insanity1 = new Insanity(); Insanity insanity2 = new Insanity(); // Both empty. expectEquals(insanity1, insanity2); insanity1.setUserMap(new HashMap()); // insanity1.map = {}, insanity2.map = null expectGreaterThan(insanity1, insanity2); // insanity1.map = {2:1}, insanity2.map = null insanity1.getUserMap().put(Numberz.TWO, 1L); expectGreaterThan(insanity1, insanity2); // insanity1.map = {2:1}, insanity2.map = {} insanity2.setUserMap(new HashMap()); expectGreaterThan(insanity1, insanity2); // insanity1.map = {2:1}, insanity2.map = {2:2} insanity2.getUserMap().put(Numberz.TWO, 2L); expectLessThan(insanity1, insanity2); // insanity1.map = {2:1, 3:5}, insanity2.map = {2:2} insanity1.getUserMap().put(Numberz.THREE, 5L); expectGreaterThan(insanity1, insanity2); // insanity1.map = {2:1, 3:5}, insanity2.map = {2:1, 4:5} insanity2.getUserMap().put(Numberz.TWO, 1L); insanity2.getUserMap().put(Numberz.FIVE, 5L); expectLessThan(insanity1, insanity2); } private void expectLessThan(Insanity insanity1, Insanity insanity2) { int compareTo = insanity1.compareTo(insanity2); assertTrue( compareTo < 0, insanity1 + " should be less than " + insanity2 + ", but is: " + compareTo); } private void expectGreaterThan(Insanity insanity1, Insanity insanity2) { int compareTo = insanity1.compareTo(insanity2); assertTrue( compareTo > 0, insanity1 + " should be greater than " + insanity2 + ", but is: " + compareTo); } private void expectEquals(Insanity insanity1, Insanity insanity2) { int compareTo = insanity1.compareTo(insanity2); assertEquals( 0, compareTo, insanity1 + " should be equal to " + insanity2 + ", but is: " + compareTo); } @Test public void testMetaData() throws Exception { Map mdMap = CrazyNesting.metaDataMap; // Check for struct fields existence assertEquals(5, mdMap.size()); assertTrue(mdMap.containsKey(CrazyNesting._Fields.SET_FIELD)); assertTrue(mdMap.containsKey(CrazyNesting._Fields.LIST_FIELD)); assertTrue(mdMap.containsKey(CrazyNesting._Fields.STRING_FIELD)); assertTrue(mdMap.containsKey(CrazyNesting._Fields.BINARY_FIELD)); assertTrue(mdMap.containsKey(CrazyNesting._Fields.UUID_FIELD)); // Check for struct fields contents assertEquals("string_field", mdMap.get(CrazyNesting._Fields.STRING_FIELD).fieldName); assertEquals("list_field", mdMap.get(CrazyNesting._Fields.LIST_FIELD).fieldName); assertEquals("set_field", mdMap.get(CrazyNesting._Fields.SET_FIELD).fieldName); assertEquals("binary_field", mdMap.get(CrazyNesting._Fields.BINARY_FIELD).fieldName); assertEquals("uuid_field", mdMap.get(CrazyNesting._Fields.UUID_FIELD).fieldName); assertEquals( TFieldRequirementType.DEFAULT, mdMap.get(CrazyNesting._Fields.STRING_FIELD).requirementType); assertEquals( TFieldRequirementType.REQUIRED, mdMap.get(CrazyNesting._Fields.LIST_FIELD).requirementType); assertEquals( TFieldRequirementType.OPTIONAL, mdMap.get(CrazyNesting._Fields.SET_FIELD).requirementType); assertEquals(TType.STRING, mdMap.get(CrazyNesting._Fields.STRING_FIELD).valueMetaData.type); assertFalse(mdMap.get(CrazyNesting._Fields.STRING_FIELD).valueMetaData.isBinary()); assertEquals(TType.LIST, mdMap.get(CrazyNesting._Fields.LIST_FIELD).valueMetaData.type); assertEquals(TType.SET, mdMap.get(CrazyNesting._Fields.SET_FIELD).valueMetaData.type); assertEquals(TType.STRING, mdMap.get(CrazyNesting._Fields.BINARY_FIELD).valueMetaData.type); assertEquals(TType.UUID, mdMap.get(CrazyNesting._Fields.UUID_FIELD).valueMetaData.type); assertTrue(mdMap.get(CrazyNesting._Fields.BINARY_FIELD).valueMetaData.isBinary()); // Check nested structures assertTrue(mdMap.get(CrazyNesting._Fields.LIST_FIELD).valueMetaData.isContainer()); assertFalse(mdMap.get(CrazyNesting._Fields.LIST_FIELD).valueMetaData.isStruct()); assertEquals( TType.STRUCT, ((MapMetaData) ((ListMetaData) ((SetMetaData) ((MapMetaData) ((MapMetaData) ((ListMetaData) mdMap.get(CrazyNesting._Fields.LIST_FIELD) .valueMetaData) .elemMetaData) .valueMetaData) .valueMetaData) .elemMetaData) .elemMetaData) .keyMetaData .type); assertEquals( Insanity.class, ((StructMetaData) ((MapMetaData) ((ListMetaData) ((SetMetaData) ((MapMetaData) ((MapMetaData) ((ListMetaData) mdMap.get( CrazyNesting._Fields .LIST_FIELD) .valueMetaData) .elemMetaData) .valueMetaData) .valueMetaData) .elemMetaData) .elemMetaData) .keyMetaData) .structClass); // Check that FieldMetaData contains a map with metadata for all generated struct classes assertNotNull(FieldMetaData.getStructMetaDataMap(CrazyNesting.class)); assertNotNull(FieldMetaData.getStructMetaDataMap(Insanity.class)); assertNotNull(FieldMetaData.getStructMetaDataMap(Xtruct.class)); assertEquals(CrazyNesting.metaDataMap, FieldMetaData.getStructMetaDataMap(CrazyNesting.class)); assertEquals(Insanity.metaDataMap, FieldMetaData.getStructMetaDataMap(Insanity.class)); for (Map.Entry mdEntry : mdMap.entrySet()) { assertEquals(mdEntry.getKey(), CrazyNesting._Fields.findByName(mdEntry.getValue().fieldName)); } MapMetaData vmd = (MapMetaData) Insanity.metaDataMap.get(Insanity._Fields.USER_MAP).valueMetaData; assertTrue(vmd.valueMetaData.isTypedef()); assertFalse(vmd.keyMetaData.isTypedef()); } @Test public void testToString() throws Exception { JavaTestHelper object = new JavaTestHelper(); object.req_int = 0; object.req_obj = ""; object.req_bin = ByteBuffer.wrap( new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20, -21, 22, -23, 24, -25, 26, -27, 28, -29, 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74, -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89, 90, -91, 92, -93, 94, -95, 96, -97, 98, -99, 100, -101, 102, -103, 104, -105, 106, -107, 108, -109, 110, -111, 112, -113, 114, -115, 116, -117, 118, -119, 120, -121, 122, -123, 124, -125, 126, -127, }); assertEquals( "JavaTestHelper(req_int:0, req_obj:, req_bin:" + "00 FF 02 FD 04 FB 06 F9 08 F7 0A F5 0C F3 0E F1 10 EF 12 ED 14 " + "EB 16 E9 18 E7 1A E5 1C E3 1E E1 20 DF 22 DD 24 DB 26 D9 28 D7 " + "2A D5 2C D3 2E D1 30 CF 32 CD 34 CB 36 C9 38 C7 3A C5 3C C3 3E " + "C1 40 BF 42 BD 44 BB 46 B9 48 B7 4A B5 4C B3 4E B1 50 AF 52 AD " + "54 AB 56 A9 58 A7 5A A5 5C A3 5E A1 60 9F 62 9D 64 9B 66 99 68 " + "97 6A 95 6C 93 6E 91 70 8F 72 8D 74 8B 76 89 78 87 7A 85 7C 83 " + "7E 81)", object.toString()); object.req_bin = ByteBuffer.wrap( new byte[] { 0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11, 12, -13, 14, -15, 16, -17, 18, -19, 20, -21, 22, -23, 24, -25, 26, -27, 28, -29, 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74, -75, 76, -77, 78, -79, 80, -81, 82, -83, 84, -85, 86, -87, 88, -89, 90, -91, 92, -93, 94, -95, 96, -97, 98, -99, 100, -101, 102, -103, 104, -105, 106, -107, 108, -109, 110, -111, 112, -113, 114, -115, 116, -117, 118, -119, 120, -121, 122, -123, 124, -125, 126, -127, 0, }); assertEquals( "JavaTestHelper(req_int:0, req_obj:, req_bin:" + "00 FF 02 FD 04 FB 06 F9 08 F7 0A F5 0C F3 0E F1 10 EF 12 ED 14 " + "EB 16 E9 18 E7 1A E5 1C E3 1E E1 20 DF 22 DD 24 DB 26 D9 28 D7 " + "2A D5 2C D3 2E D1 30 CF 32 CD 34 CB 36 C9 38 C7 3A C5 3C C3 3E " + "C1 40 BF 42 BD 44 BB 46 B9 48 B7 4A B5 4C B3 4E B1 50 AF 52 AD " + "54 AB 56 A9 58 A7 5A A5 5C A3 5E A1 60 9F 62 9D 64 9B 66 99 68 " + "97 6A 95 6C 93 6E 91 70 8F 72 8D 74 8B 76 89 78 87 7A 85 7C 83 " + "7E 81...)", object.toString()); object.req_bin = ByteBuffer.wrap(new byte[] {}); object.setOpt_binIsSet(true); assertEquals("JavaTestHelper(req_int:0, req_obj:, req_bin:)", object.toString()); } @Test public void testBytesBufferFeatures() throws Exception { final String testString = "testBytesBufferFeatures"; final JavaTestHelper o = new JavaTestHelper(); o.setReq_bin((ByteBuffer) null); assertNull(o.getReq_bin()); o.setReq_bin(ByteBuffer.wrap(testString.getBytes())); assertArrayEquals(testString.getBytes(), o.getReq_bin()); o.setReq_bin((byte[]) null); assertNull(o.getReq_bin()); o.setReq_bin(testString.getBytes()); assertArrayEquals(testString.getBytes(), o.getReq_bin()); o.setFieldValue(JavaTestHelper._Fields.REQ_BIN, null); assertNull(o.getReq_bin()); o.setFieldValue(JavaTestHelper._Fields.REQ_BIN, testString.getBytes()); assertArrayEquals(testString.getBytes(), o.getReq_bin()); o.setFieldValue(JavaTestHelper._Fields.REQ_BIN, null); assertNull(o.getReq_bin()); o.setFieldValue(JavaTestHelper._Fields.REQ_BIN, ByteBuffer.wrap(testString.getBytes())); assertArrayEquals(testString.getBytes(), o.getReq_bin()); } @Test public void testJavaSerializable() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); OneOfEach ooe = Fixtures.getOneOfEach(); // Serialize ooe the Java way... oos.writeObject(ooe); byte[] serialized = baos.toByteArray(); // Attempt to deserialize it ByteArrayInputStream bais = new ByteArrayInputStream(serialized); ObjectInputStream ois = new ObjectInputStream(bais); OneOfEach ooe2 = (OneOfEach) ois.readObject(); assertEquals(ooe, ooe2); } @Test public void testSubStructValidation() throws Exception { StructA valid = new StructA("valid"); StructA invalid = new StructA(); StructB b = new StructB(); assertThrows(TException.class, b::validate); b = new StructB().setAb(valid); b.validate(); b = new StructB().setAb(invalid); assertThrows(TException.class, b::validate); b = new StructB().setAb(valid).setAa(invalid); assertThrows(TException.class, b::validate); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/0000777000000000000000000000000014452237057024636 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTFramedTransport.java0000644000000000000000000001764214303740367031604 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import org.apache.thrift.transport.layered.TFastFramedTransport; import org.apache.thrift.transport.layered.TFramedTransport; import org.junit.jupiter.api.Test; public class TestTFramedTransport { protected TTransport getTransport(TTransport underlying) throws TTransportException { return new TFramedTransport(underlying); } protected TTransport getTransport(TTransport underlying, int maxLength) throws TTransportException { return new TFramedTransport(underlying, maxLength); } public static byte[] byteSequence(int start, int end) { byte[] result = new byte[end - start + 1]; for (int i = 0; i <= (end - start); i++) { result[i] = (byte) (start + i); } return result; } @Test public void testRead() throws IOException, TTransportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(50); dos.write(byteSequence(0, 49)); dos.writeInt(220); dos.write(byteSequence(0, 219)); TMemoryBuffer membuf = new TMemoryBuffer(0); membuf.write(baos.toByteArray()); ReadCountingTransport countTrans = new ReadCountingTransport(membuf); TTransport trans = getTransport(countTrans); byte[] readBuf = new byte[10]; trans.read(readBuf, 0, 10); assertArrayEquals(readBuf, byteSequence(0, 9)); assertEquals(2, countTrans.readCount); trans.read(readBuf, 0, 10); assertArrayEquals(readBuf, byteSequence(10, 19)); assertEquals(2, countTrans.readCount); assertEquals(30, trans.read(new byte[30], 0, 30)); assertEquals(2, countTrans.readCount); // Known message size exceeded readBuf = new byte[220]; assertEquals(220, trans.read(readBuf, 0, 220)); assertArrayEquals(readBuf, byteSequence(0, 219)); assertEquals(4, countTrans.readCount); } @Test public void testInvalidFrameSize() throws IOException, TTransportException { int maxLength = 128; ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(130); dos.write(byteSequence(0, 129)); TMemoryBuffer membuf = new TMemoryBuffer(0); membuf.write(baos.toByteArray()); ReadCountingTransport countTrans = new ReadCountingTransport(membuf); TTransport trans = getTransport(countTrans, maxLength); byte[] readBuf = new byte[10]; TTransportException e = assertThrows(TTransportException.class, () -> trans.read(readBuf, 0, 4)); // We expect this exception because the frame we're trying to read is larger than our max frame // length assertEquals(TTransportException.CORRUPTED_DATA, e.getType()); assertFalse(trans.isOpen()); TTransportException e2 = assertThrows(TTransportException.class, () -> trans.read(readBuf, 0, 4)); // This time we get an exception indicating the connection was closed assertEquals(TTransportException.NOT_OPEN, e2.getType()); } @Test public void testWrite() throws TTransportException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); WriteCountingTransport countingTrans = new WriteCountingTransport(new TIOStreamTransport(new BufferedOutputStream(baos))); TTransport trans = getTransport(countingTrans); trans.write(byteSequence(0, 100)); assertEquals(0, countingTrans.writeCount); trans.write(byteSequence(101, 200)); trans.write(byteSequence(201, 255)); assertEquals(0, countingTrans.writeCount); trans.flush(); assertEquals(1, countingTrans.writeCount); trans.write(byteSequence(0, 245)); trans.flush(); assertEquals(2, countingTrans.writeCount); DataInputStream din = new DataInputStream(new ByteArrayInputStream(baos.toByteArray())); assertEquals(256, din.readInt()); byte[] buf = new byte[256]; int readBytes = din.read(buf, 0, 256); assertArrayEquals(byteSequence(0, 255), buf); assertEquals(246, din.readInt()); buf = new byte[246]; int readBytes2 = din.read(buf, 0, 246); assertArrayEquals(byteSequence(0, 245), buf); } @Test public void testDirectRead() throws IOException, TTransportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(50); dos.write(byteSequence(0, 49)); dos.writeInt(50); dos.write(byteSequence(125, 175)); TMemoryBuffer membuf = new TMemoryBuffer(0); membuf.write(baos.toByteArray()); ReadCountingTransport countTrans = new ReadCountingTransport(membuf); TTransport trans = getTransport(countTrans); assertEquals(0, trans.getBytesRemainingInBuffer()); byte[] readBuf = new byte[10]; trans.read(readBuf, 0, 10); assertArrayEquals(readBuf, byteSequence(0, 9)); assertEquals(40, trans.getBytesRemainingInBuffer()); assertEquals(10, trans.getBufferPosition()); trans.consumeBuffer(5); assertEquals(35, trans.getBytesRemainingInBuffer()); assertEquals(15, trans.getBufferPosition()); assertEquals(2, countTrans.readCount); assertEquals(35, trans.read(new byte[35], 0, 35)); assertEquals(0, trans.getBytesRemainingInBuffer()); assertEquals(50, trans.getBufferPosition()); // Known message size exceeded trans.read(readBuf, 0, 10); assertEquals(4, countTrans.readCount); assertArrayEquals(readBuf, byteSequence(125, 134)); assertEquals(40, trans.getBytesRemainingInBuffer()); assertEquals(10, trans.getBufferPosition()); } @Test public void testClear() throws IOException, TTransportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeInt(220); dos.write(byteSequence(0, 219)); TMemoryBuffer membuf = new TMemoryBuffer(0); membuf.write(baos.toByteArray()); ReadCountingTransport countTrans = new ReadCountingTransport(membuf); TTransport trans = getTransport(countTrans); byte[] readBuf = new byte[220]; trans.read(readBuf, 0, 220); assertArrayEquals(readBuf, byteSequence(0, 219)); assertTrue(trans instanceof TFramedTransport || trans instanceof TFastFramedTransport); if (trans instanceof TFramedTransport) { assertTrue(trans.getBuffer() != null && trans.getBuffer().length > 0); ((TFramedTransport) trans).clear(); assertNull(trans.getBuffer()); } else { assertTrue(trans.getBuffer().length > TestTFastFramedTransport.INITIAL_CAPACITY); ((TFastFramedTransport) trans).clear(); assertEquals(TestTFastFramedTransport.INITIAL_CAPACITY, trans.getBuffer().length); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/WriteCountingTransport.java0000644000000000000000000000366614303740367032224 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TConfiguration; public class WriteCountingTransport extends TTransport { public int writeCount = 0; private final TTransport trans; public WriteCountingTransport(TTransport underlying) { trans = underlying; } @Override public void close() {} @Override public boolean isOpen() { return true; } @Override public void open() throws TTransportException {} @Override public int read(byte[] buf, int off, int len) throws TTransportException { return 0; } @Override public void write(byte[] buf, int off, int len) throws TTransportException { writeCount++; trans.write(buf, off, len); } @Override public void flush() throws TTransportException { trans.flush(); } @Override public TConfiguration getConfiguration() { return trans.getConfiguration(); } @Override public void updateKnownMessageSize(long size) throws TTransportException { trans.updateKnownMessageSize(size); } @Override public void checkReadBytesAvailable(long numBytes) throws TTransportException { trans.checkReadBytesAvailable(numBytes); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestAutoExpandingBuffer.java0000644000000000000000000000263614303740367032242 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class TestAutoExpandingBuffer { @Test public void testExpands() throws Exception { // has expected initial capacity AutoExpandingBuffer b = new AutoExpandingBuffer(10); assertEquals(10, b.array().length); // doesn't shrink b.resizeIfNecessary(8); assertEquals(10, b.array().length); // grows when more capacity is needed b.resizeIfNecessary(100); assertTrue(b.array().length >= 100); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/sasl/0000777000000000000000000000000014303740367025576 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/sasl/TestDataFrameWriter.java0000644000000000000000000001014214303740367032314 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import org.apache.thrift.EncodingUtils; import org.apache.thrift.transport.TNonblockingTransport; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; public class TestDataFrameWriter { private static final byte[] BYTES = new byte[] {0x32, 0x2A, (byte) 0xE1, 0x18, (byte) 0x90, 0x75}; @Test public void testProvideEntireByteArrayAsPayload() { DataFrameWriter frameWriter = new DataFrameWriter(); frameWriter.withOnlyPayload(BYTES); byte[] expectedBytes = new byte[BYTES.length + PAYLOAD_LENGTH_BYTES]; EncodingUtils.encodeBigEndian(BYTES.length, expectedBytes); System.arraycopy(BYTES, 0, expectedBytes, PAYLOAD_LENGTH_BYTES, BYTES.length); assertEquals(ByteBuffer.wrap(expectedBytes), frameWriter.frameBytes); } @Test public void testProvideByteArrayPortionAsPayload() { DataFrameWriter frameWriter = new DataFrameWriter(); int portionOffset = 2; int portionLength = 3; frameWriter.withOnlyPayload(BYTES, portionOffset, portionLength); byte[] expectedBytes = new byte[portionLength + PAYLOAD_LENGTH_BYTES]; EncodingUtils.encodeBigEndian(portionLength, expectedBytes); System.arraycopy(BYTES, portionOffset, expectedBytes, PAYLOAD_LENGTH_BYTES, portionLength); assertEquals(ByteBuffer.wrap(expectedBytes), frameWriter.frameBytes); } @Test public void testProvideHeaderAndPayload() { DataFrameWriter frameWriter = new DataFrameWriter(); assertThrows( IllegalArgumentException.class, () -> frameWriter.withHeaderAndPayload(new byte[1], new byte[1])); } @Test public void testProvidePayloadToIncompleteFrame() { DataFrameWriter frameWriter = new DataFrameWriter(); assertThrows( IllegalStateException.class, () -> { frameWriter.withOnlyPayload(BYTES); frameWriter.withOnlyPayload(new byte[1]); }); } @Test public void testWrite() throws Exception { DataFrameWriter frameWriter = new DataFrameWriter(); frameWriter.withOnlyPayload(BYTES); // Slow socket which writes one byte per call. TNonblockingTransport transport = Mockito.mock(TNonblockingTransport.class); SlowWriting slowWriting = new SlowWriting(); Mockito.when(transport.write(frameWriter.frameBytes)).thenAnswer(slowWriting); frameWriter.write(transport); while (slowWriting.written < frameWriter.frameBytes.limit()) { assertFalse(frameWriter.isComplete(), "Frame writer should not be complete"); frameWriter.write(transport); } assertTrue(frameWriter.isComplete(), "Frame writer should be complete"); } private static class SlowWriting implements Answer { int written = 0; @Override public Integer answer(InvocationOnMock invocation) throws Throwable { ByteBuffer bytes = (ByteBuffer) invocation.getArguments()[0]; bytes.get(); written++; return 1; } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/sasl/TestDataFrameReader.java0000644000000000000000000000534714303740367032255 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import org.apache.thrift.transport.TMemoryInputTransport; import org.apache.thrift.transport.TTransportException; import org.junit.jupiter.api.Test; public class TestDataFrameReader { @Test public void testRead() throws TTransportException { // Prepare data int payloadSize = 23; ByteBuffer buffer = ByteBuffer.allocate(DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES + payloadSize); buffer.putInt(payloadSize); for (int i = 0; i < payloadSize; i++) { buffer.put((byte) i); } buffer.rewind(); TMemoryInputTransport transport = new TMemoryInputTransport(); DataFrameReader dataFrameReader = new DataFrameReader(); // No bytes received. dataFrameReader.read(transport); assertFalse(dataFrameReader.isComplete(), "No bytes received"); assertFalse(dataFrameReader.getHeader().isComplete(), "No bytes received"); // Payload size (header) and part of the payload are received. transport.reset(buffer.array(), 0, 6); dataFrameReader.read(transport); assertFalse(dataFrameReader.isComplete(), "Only header is complete"); assertTrue(dataFrameReader.getHeader().isComplete(), "Header should be complete"); assertEquals( payloadSize, dataFrameReader.getHeader().payloadSize(), "Payload size should be " + payloadSize); // Read the rest of payload. transport.reset(buffer.array(), 6, 21); dataFrameReader.read(transport); assertTrue(dataFrameReader.isComplete(), "Reader should be complete"); buffer.position(DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES); assertEquals( buffer, ByteBuffer.wrap(dataFrameReader.getPayload()), "Payload should be the same as from the transport"); } } TestSaslNegotiationFrameReader.java0000644000000000000000000000561314303740367034424 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/sasl/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import org.apache.thrift.transport.TMemoryInputTransport; import org.apache.thrift.transport.TTransportException; import org.junit.jupiter.api.Test; public class TestSaslNegotiationFrameReader { @Test public void testRead() throws TTransportException { TMemoryInputTransport transport = new TMemoryInputTransport(); SaslNegotiationFrameReader negotiationReader = new SaslNegotiationFrameReader(); // No bytes received negotiationReader.read(transport); assertFalse(negotiationReader.isComplete(), "No bytes received"); assertFalse(negotiationReader.getHeader().isComplete(), "No bytes received"); // Read header ByteBuffer buffer = ByteBuffer.allocate(5); buffer.put(0, NegotiationStatus.OK.getValue()); buffer.putInt(1, 10); transport.reset(buffer.array()); negotiationReader.read(transport); assertFalse(negotiationReader.isComplete(), "Only header is complete"); assertTrue(negotiationReader.getHeader().isComplete(), "Header should be complete"); assertEquals(10, negotiationReader.getHeader().payloadSize(), "Payload size should be 10"); // Read payload transport.reset(new byte[20]); negotiationReader.read(transport); assertTrue(negotiationReader.isComplete(), "Reader should be complete"); assertEquals(10, negotiationReader.getPayload().length, "Payload length should be 10"); } @Test public void testReadInvalidNegotiationStatus() throws TTransportException { byte[] bytes = new byte[5]; // Invalid status byte. bytes[0] = -1; TMemoryInputTransport transport = new TMemoryInputTransport(bytes); SaslNegotiationFrameReader negotiationReader = new SaslNegotiationFrameReader(); assertThrows( TSaslNegotiationException.class, () -> { negotiationReader.read(transport); }); } } TestSaslNegotiationFrameWriter.java0000644000000000000000000000454414303740367034500 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/sasl/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport.sasl; import static org.apache.thrift.transport.sasl.SaslNegotiationFrameWriter.HEADER_BYTES; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.ByteBuffer; import org.apache.thrift.EncodingUtils; import org.junit.jupiter.api.Test; public class TestSaslNegotiationFrameWriter { private static final byte[] PAYLOAD = {0x11, 0x08, 0x3F, 0x58, 0x73, 0x22, 0x00, (byte) 0xFF}; @Test public void testWithHeaderAndPayload() { SaslNegotiationFrameWriter frameWriter = new SaslNegotiationFrameWriter(); frameWriter.withHeaderAndPayload(new byte[] {NegotiationStatus.OK.getValue()}, PAYLOAD); byte[] expectedBytes = new byte[HEADER_BYTES + PAYLOAD.length]; expectedBytes[0] = NegotiationStatus.OK.getValue(); EncodingUtils.encodeBigEndian(PAYLOAD.length, expectedBytes, 1); System.arraycopy(PAYLOAD, 0, expectedBytes, HEADER_BYTES, PAYLOAD.length); assertEquals(ByteBuffer.wrap(expectedBytes), frameWriter.frameBytes); } @Test public void testWithInvalidHeaderLength() { SaslNegotiationFrameWriter frameWriter = new SaslNegotiationFrameWriter(); assertThrows( IllegalArgumentException.class, () -> frameWriter.withHeaderAndPayload(new byte[5], 0, 2, PAYLOAD, 0, 1)); } @Test public void testWithOnlyPayload() { SaslNegotiationFrameWriter frameWriter = new SaslNegotiationFrameWriter(); assertThrows( UnsupportedOperationException.class, () -> frameWriter.withOnlyPayload(new byte[0])); } } TestTSSLTransportFactoryCustomClient2.java0000644000000000000000000000242114303740367034721 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; public class TestTSSLTransportFactoryCustomClient2 extends TestTSSLTransportFactory { @Override public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters(); params.setTrustStore(getTrustStoreLocation(), null); return TSSLTransportFactory.getClientSocket(HOST, PORT, 0 /*timeout*/, params); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTSaslTransports.java0000644000000000000000000004355214452237057031474 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.sasl.AuthorizeCallback; import javax.security.sasl.RealmCallback; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; import javax.security.sasl.SaslClientFactory; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; import javax.security.sasl.SaslServerFactory; import org.apache.thrift.TConfiguration; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.ServerTestBase; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TServer.Args; import org.apache.thrift.server.TSimpleServer; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestTSaslTransports { private static final Logger LOGGER = LoggerFactory.getLogger(TestTSaslTransports.class); public static final String HOST = "localhost"; public static final String SERVICE = "thrift-test"; public static final String PRINCIPAL = "thrift-test-principal"; public static final String PASSWORD = "super secret password"; public static final String REALM = "thrift-test-realm"; public static final String UNWRAPPED_MECHANISM = "CRAM-MD5"; public static final Map UNWRAPPED_PROPS = null; public static final String WRAPPED_MECHANISM = "DIGEST-MD5"; public static final Map WRAPPED_PROPS = new HashMap(); static { WRAPPED_PROPS.put(Sasl.QOP, "auth-int"); WRAPPED_PROPS.put("com.sun.security.sasl.digest.realm", REALM); } private static final String testMessage1 = "Hello, world! Also, four " + "score and seven years ago our fathers brought forth on this " + "continent a new nation, conceived in liberty, and dedicated to the " + "proposition that all men are created equal."; private static final String testMessage2 = "I have a dream that one day " + "this nation will rise up and live out the true meaning of its creed: " + "'We hold these truths to be self-evident, that all men are created equal.'"; public static class TestSaslCallbackHandler implements CallbackHandler { private final String password; public TestSaslCallbackHandler(String password) { this.password = password; } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (Callback c : callbacks) { if (c instanceof NameCallback) { ((NameCallback) c).setName(PRINCIPAL); } else if (c instanceof PasswordCallback) { ((PasswordCallback) c).setPassword(password.toCharArray()); } else if (c instanceof AuthorizeCallback) { ((AuthorizeCallback) c).setAuthorized(true); } else if (c instanceof RealmCallback) { ((RealmCallback) c).setText(REALM); } else { throw new UnsupportedCallbackException(c); } } } } private static class ServerThread extends Thread { final String mechanism; final Map props; volatile Throwable thrown; public ServerThread(String mechanism, Map props) { this.mechanism = mechanism; this.props = props; } public void run() { try { internalRun(); } catch (Throwable t) { thrown = t; } } private void internalRun() throws Exception { try (TServerSocket serverSocket = new TServerSocket( new TServerSocket.ServerSocketTransportArgs().port(ServerTestBase.PORT))) { acceptAndWrite(serverSocket); } } private void acceptAndWrite(TServerSocket serverSocket) throws Exception { TTransport serverTransport = serverSocket.accept(); TTransport saslServerTransport = new TSaslServerTransport( mechanism, SERVICE, HOST, props, new TestSaslCallbackHandler(PASSWORD), serverTransport); saslServerTransport.open(); byte[] inBuf = new byte[testMessage1.getBytes().length]; // Deliberately read less than the full buffer to ensure // that TSaslTransport is correctly buffering reads. This // will fail for the WRAPPED test, if it doesn't work. saslServerTransport.readAll(inBuf, 0, 5); saslServerTransport.readAll(inBuf, 5, 10); saslServerTransport.readAll(inBuf, 15, inBuf.length - 15); LOGGER.debug("server got: {}", new String(inBuf)); assertEquals(new String(inBuf), testMessage1); LOGGER.debug("server writing: {}", testMessage2); saslServerTransport.write(testMessage2.getBytes()); saslServerTransport.flush(); saslServerTransport.close(); } } private void testSaslOpen(final String mechanism, final Map props) throws Exception { ServerThread serverThread = new ServerThread(mechanism, props); serverThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { // Ah well. } try { TSocket clientSocket = new TSocket(HOST, ServerTestBase.PORT); TTransport saslClientTransport = new TSaslClientTransport( mechanism, PRINCIPAL, SERVICE, HOST, props, new TestSaslCallbackHandler(PASSWORD), clientSocket); saslClientTransport.open(); LOGGER.debug("client writing: {}", testMessage1); saslClientTransport.write(testMessage1.getBytes()); saslClientTransport.flush(); byte[] inBuf = new byte[testMessage2.getBytes().length]; saslClientTransport.readAll(inBuf, 0, inBuf.length); LOGGER.debug("client got: {}", new String(inBuf)); assertEquals(new String(inBuf), testMessage2); TTransportException expectedException = null; try { saslClientTransport.open(); } catch (TTransportException e) { expectedException = e; } assertNotNull(expectedException); saslClientTransport.close(); } catch (Exception e) { LOGGER.warn("Exception caught", e); throw e; } finally { serverThread.interrupt(); try { serverThread.join(); } catch (InterruptedException e) { // Ah well. } assertNull(serverThread.thrown); } } @Test public void testUnwrappedOpen() throws Exception { testSaslOpen(UNWRAPPED_MECHANISM, UNWRAPPED_PROPS); } @Test public void testWrappedOpen() throws Exception { testSaslOpen(WRAPPED_MECHANISM, WRAPPED_PROPS); } @Test public void testAnonymousOpen() throws Exception { testSaslOpen("ANONYMOUS", null); } /** * Test that we get the proper exceptions thrown back the server when the client provides invalid * password. */ @Test public void testBadPassword() throws Exception { ServerThread serverThread = new ServerThread(UNWRAPPED_MECHANISM, UNWRAPPED_PROPS); serverThread.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { // Ah well. } TTransportException tte = assertThrows( TTransportException.class, () -> { TSocket clientSocket = new TSocket(HOST, ServerTestBase.PORT); TTransport saslClientTransport = new TSaslClientTransport( UNWRAPPED_MECHANISM, PRINCIPAL, SERVICE, HOST, UNWRAPPED_PROPS, new TestSaslCallbackHandler("NOT THE PASSWORD"), clientSocket); saslClientTransport.open(); }, "Was able to open transport with bad password"); LOGGER.error("Exception for bad password", tte); assertNotNull(tte.getMessage()); assertTrue(tte.getMessage().contains("Invalid response")); serverThread.interrupt(); serverThread.join(); assertNotNull(serverThread.thrown); assertTrue(serverThread.thrown.getMessage().contains("Invalid response")); } @Test public void testWithServer() throws Exception { new TestTSaslTransportsWithServer().testIt(); } public static class TestTSaslTransportsWithServer extends ServerTestBase { private Thread serverThread; private TServer server; @Override public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { return new TSaslClientTransport( WRAPPED_MECHANISM, PRINCIPAL, SERVICE, HOST, WRAPPED_PROPS, new TestSaslCallbackHandler(PASSWORD), underlyingTransport); } @Override public void startServer( final TProcessor processor, final TProtocolFactory protoFactory, final TTransportFactory factory) throws Exception { serverThread = new Thread() { public void run() { try { // Transport TServerSocket socket = new TServerSocket(new TServerSocket.ServerSocketTransportArgs().port(PORT)); TTransportFactory factory = new TSaslServerTransport.Factory( WRAPPED_MECHANISM, SERVICE, HOST, WRAPPED_PROPS, new TestSaslCallbackHandler(PASSWORD)); server = new TSimpleServer( new Args(socket) .processor(processor) .transportFactory(factory) .protocolFactory(protoFactory)); // Run it LOGGER.debug("Starting the server on port {}", PORT); server.serve(); } catch (Exception e) { e.printStackTrace(); fail(e); } } }; serverThread.start(); Thread.sleep(1000); } @Override public void stopServer() throws Exception { server.stop(); try { serverThread.join(); } catch (InterruptedException e) { LOGGER.debug("interrupted during sleep", e); } } } /** Implementation of SASL ANONYMOUS, used for testing client-side initial responses. */ private static class AnonymousClient implements SaslClient { private final String username; private boolean hasProvidedInitialResponse; public AnonymousClient(String username) { this.username = username; } @Override public String getMechanismName() { return "ANONYMOUS"; } @Override public boolean hasInitialResponse() { return true; } @Override public byte[] evaluateChallenge(byte[] challenge) throws SaslException { if (hasProvidedInitialResponse) { throw new SaslException("Already complete!"); } hasProvidedInitialResponse = true; return username.getBytes(StandardCharsets.UTF_8); } @Override public boolean isComplete() { return hasProvidedInitialResponse; } @Override public byte[] unwrap(byte[] incoming, int offset, int len) { throw new UnsupportedOperationException(); } @Override public byte[] wrap(byte[] outgoing, int offset, int len) { throw new UnsupportedOperationException(); } @Override public Object getNegotiatedProperty(String propName) { return null; } @Override public void dispose() {} } private static class AnonymousServer implements SaslServer { private String user; @Override public String getMechanismName() { return "ANONYMOUS"; } @Override public byte[] evaluateResponse(byte[] response) throws SaslException { this.user = new String(response, StandardCharsets.UTF_8); return null; } @Override public boolean isComplete() { return user != null; } @Override public String getAuthorizationID() { return user; } @Override public byte[] unwrap(byte[] incoming, int offset, int len) { throw new UnsupportedOperationException(); } @Override public byte[] wrap(byte[] outgoing, int offset, int len) { throw new UnsupportedOperationException(); } @Override public Object getNegotiatedProperty(String propName) { return null; } @Override public void dispose() {} } public static class SaslAnonymousFactory implements SaslClientFactory, SaslServerFactory { @Override public SaslClient createSaslClient( String[] mechanisms, String authorizationId, String protocol, String serverName, Map props, CallbackHandler cbh) { for (String mech : mechanisms) { if ("ANONYMOUS".equals(mech)) { return new AnonymousClient(authorizationId); } } return null; } @Override public SaslServer createSaslServer( String mechanism, String protocol, String serverName, Map props, CallbackHandler cbh) { if ("ANONYMOUS".equals(mechanism)) { return new AnonymousServer(); } return null; } @Override public String[] getMechanismNames(Map props) { return new String[] {"ANONYMOUS"}; } } static { java.security.Security.addProvider(new SaslAnonymousProvider()); } public static class SaslAnonymousProvider extends java.security.Provider { public SaslAnonymousProvider() { super("ThriftSaslAnonymous", 1.0, "Thrift Anonymous SASL provider"); put("SaslClientFactory.ANONYMOUS", SaslAnonymousFactory.class.getName()); put("SaslServerFactory.ANONYMOUS", SaslAnonymousFactory.class.getName()); } } private static class MockTTransport extends TTransport { byte[] badHeader = null; private final TMemoryInputTransport readBuffer; public MockTTransport(int mode) throws TTransportException { readBuffer = new TMemoryInputTransport(); if (mode == 1) { // Invalid status byte badHeader = new byte[] {(byte) 0xFF, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x05}; } else if (mode == 2) { // Valid status byte, negative payload length badHeader = new byte[] {(byte) 0x01, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; } else if (mode == 3) { // Valid status byte, excessively large, bogus payload length badHeader = new byte[] {(byte) 0x01, (byte) 0x64, (byte) 0x00, (byte) 0x00, (byte) 0x00}; } readBuffer.reset(badHeader); } @Override public boolean isOpen() { return true; } @Override public void open() throws TTransportException {} @Override public void close() {} @Override public int read(byte[] buf, int off, int len) throws TTransportException { return readBuffer.read(buf, off, len); } @Override public void write(byte[] buf, int off, int len) throws TTransportException {} @Override public TConfiguration getConfiguration() { return readBuffer.getConfiguration(); } @Override public void updateKnownMessageSize(long size) throws TTransportException { readBuffer.updateKnownMessageSize(size); } @Override public void checkReadBytesAvailable(long numBytes) throws TTransportException { readBuffer.checkReadBytesAvailable(numBytes); } } @Test public void testBadHeader() { TSaslTransport saslTransport; try { saslTransport = new TSaslServerTransport(new MockTTransport(1)); saslTransport.receiveSaslMessage(); fail("Should have gotten an error due to incorrect status byte value."); } catch (TTransportException e) { assertEquals(e.getMessage(), "Invalid status -1"); } try { saslTransport = new TSaslServerTransport(new MockTTransport(2)); saslTransport.receiveSaslMessage(); fail("Should have gotten an error due to negative payload length."); } catch (TTransportException e) { assertEquals(e.getMessage(), "Invalid payload header length: -1"); } try { saslTransport = new TSaslServerTransport(new MockTTransport(3)); saslTransport.receiveSaslMessage(); fail("Should have gotten an error due to bogus (large) payload length."); } catch (TTransportException e) { assertEquals(e.getMessage(), "Invalid payload header length: 1677721600"); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTSSLTransportFactory.java0000644000000000000000000000717014303740367032372 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.util.Collections; import java.util.List; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.apache.thrift.server.ServerTestBase; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TServer.Args; import org.apache.thrift.server.TSimpleServer; public class TestTSSLTransportFactory extends ServerTestBase { private Thread serverThread; private TServer server; // TODO: Only supported on TBinaryProtocol. Doesn't work for TCompactProtocol private static final List protocols = Collections.singletonList(new TBinaryProtocol.Factory()); private static final String keyStoreLocation = System.getProperty("javax.net.ssl.keyStore"); private static final String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword"); private static final String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); private static final String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); protected final String getKeyStoreLocation() { return keyStoreLocation; } protected final String getKeyStorePassword() { return keyStorePassword; } protected final String getTrustStoreLocation() { return trustStoreLocation; } protected final String getTrustStorePassword() { return trustStorePassword; } @Override public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { return TSSLTransportFactory.getClientSocket(HOST, PORT); } protected TServerSocket getServerTransport() throws Exception { return TSSLTransportFactory.getServerSocket(PORT); } @Override public void startServer( final TProcessor processor, final TProtocolFactory protoFactory, final TTransportFactory factory) throws Exception { serverThread = new Thread( () -> { try { TServerTransport serverTransport = getServerTransport(); final Args args = new Args(serverTransport).processor(processor); server = new TSimpleServer(args); server.serve(); } catch (Exception e) { e.printStackTrace(); assert false; } }); serverThread.start(); Thread.sleep(SLEEP_DELAY); } @Override public void stopServer() throws Exception { server.stop(); serverThread.join(); } @Override public void open(TTransport transport) throws Exception {} @Override public List getProtocols() { return protocols; } @Override public void testTransportFactory() throws Exception { // this test doesn't really apply to this suite, so let's skip it. } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTByteBuffer.java0000644000000000000000000000523014452237057030516 0ustar00rootroot00000000000000package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import org.apache.thrift.TConfiguration; import org.junit.jupiter.api.Test; public class TestTByteBuffer { @Test public void testReadWrite() throws Exception { final TByteBuffer byteBuffer = new TByteBuffer(ByteBuffer.allocate(16)); byteBuffer.write("Hello World".getBytes(StandardCharsets.UTF_8)); assertEquals( "Hello World", new String(byteBuffer.flip().toByteArray(), StandardCharsets.UTF_8)); } @Test public void testReuseReadWrite() throws Exception { final TByteBuffer byteBuffer = new TByteBuffer(ByteBuffer.allocate(16)); byteBuffer.write("Hello World".getBytes(StandardCharsets.UTF_8)); assertEquals( "Hello World", new String(byteBuffer.flip().toByteArray(), StandardCharsets.UTF_8)); byteBuffer.clear(); byteBuffer.write("Goodbye Horses".getBytes(StandardCharsets.UTF_8)); assertEquals( "Goodbye Horses", new String(byteBuffer.flip().toByteArray(), StandardCharsets.UTF_8)); } @Test public void testOverflow() throws Exception { final TByteBuffer byteBuffer = new TByteBuffer(ByteBuffer.allocate(4)); TTransportException e = assertThrows( TTransportException.class, () -> byteBuffer.write("Hello World".getBytes(StandardCharsets.UTF_8))); assertEquals("Not enough room in output buffer", e.getMessage()); } @Test public void testSmallTConfiguration() throws Exception { // Test that TByteBuffer init fail with small max message size. final TConfiguration configSmall = new TConfiguration( 4, TConfiguration.DEFAULT_MAX_FRAME_SIZE, TConfiguration.DEFAULT_RECURSION_DEPTH); TTransportException e = assertThrows( TTransportException.class, () -> new TByteBuffer(configSmall, ByteBuffer.allocate(100))); assertEquals("MaxMessageSize reached", e.getMessage()); } @Test public void testLargeTConfiguration() throws Exception { // Test that TByteBuffer init pass with large max message size beyond // TConfiguration.DEFAULT_MAX_MESSAGE_SIZE. int maxSize = 101 * 1024 * 1024; int bufferSize = (100 * 1024 + 512) * 1024; final TConfiguration configLarge = new TConfiguration( maxSize, TConfiguration.DEFAULT_MAX_FRAME_SIZE, TConfiguration.DEFAULT_RECURSION_DEPTH); assertDoesNotThrow(() -> new TByteBuffer(configLarge, ByteBuffer.allocate(bufferSize))); } } TestTSSLTransportFactoryCustomClient1.java0000644000000000000000000000244414303740367034725 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; public class TestTSSLTransportFactoryCustomClient1 extends TestTSSLTransportFactory { @Override public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters(); params.setTrustStore(getTrustStoreLocation(), getTrustStorePassword()); return TSSLTransportFactory.getClientSocket(HOST, PORT, 0 /*timeout*/, params); } } TestAutoExpandingBufferReadTransport.java0000644000000000000000000000351114303740367034665 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.ByteBuffer; import org.apache.thrift.TConfiguration; import org.junit.jupiter.api.Test; public class TestAutoExpandingBufferReadTransport { private static final byte[] HUNDRED_BYTES = new byte[100]; static { for (byte i = 0; i < 100; i++) { HUNDRED_BYTES[i] = i; } } @Test public void testIt() throws Exception { AutoExpandingBufferReadTransport t = new AutoExpandingBufferReadTransport(new TConfiguration(), 150); TMemoryInputTransport membuf = new TMemoryInputTransport(new TConfiguration(), HUNDRED_BYTES); t.fill(membuf, 100); assertEquals(100, t.getBytesRemainingInBuffer()); assertEquals(0, t.getBufferPosition()); byte[] target = new byte[10]; assertEquals(10, t.read(target, 0, 10)); assertEquals(ByteBuffer.wrap(HUNDRED_BYTES, 0, 10), ByteBuffer.wrap(target)); assertEquals(90, t.getBytesRemainingInBuffer()); assertEquals(10, t.getBufferPosition()); } } TestTSSLTransportFactoryStreamedStore.java0000644000000000000000000000342314303740367035012 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import java.io.FileInputStream; import java.net.InetAddress; public class TestTSSLTransportFactoryStreamedStore extends TestTSSLTransportFactory { @Override public TTransport getClientTransport(TTransport underlyingTransport) throws Exception { TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters(); params.setTrustStore(new FileInputStream(getTrustStoreLocation()), getTrustStorePassword()); return TSSLTransportFactory.getClientSocket(HOST, PORT, 0 /*timeout*/, params); } @Override protected TServerSocket getServerTransport() throws Exception { TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters(); params.setKeyStore(new FileInputStream(getKeyStoreLocation()), getKeyStorePassword()); return TSSLTransportFactory.getServerSocket( PORT, 0 /*timeout*/, InetAddress.getByName(HOST), params); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTSimpleFileTransport.java0000644000000000000000000000545414303740367032435 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import java.nio.file.Files; import java.nio.file.Path; import org.junit.jupiter.api.Test; public class TestTSimpleFileTransport { @Test public void testFresh() throws Exception { // Test write side Path tempFilePathName = Files.createTempFile("TSimpleFileTransportTest", null); Files.delete(tempFilePathName); byte[] input_buf = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; TSimpleFileTransport trans_write = new TSimpleFileTransport(tempFilePathName.toString(), false, true, false); assert (!trans_write.isOpen()); trans_write.open(); assert (trans_write.isOpen()); trans_write.write(input_buf); trans_write.write(input_buf, 2, 2); trans_write.flush(); trans_write.close(); // Test read side TSimpleFileTransport trans = new TSimpleFileTransport(tempFilePathName.toString(), true, false); assert (trans.isOpen()); // Simple file trans provides no buffer access assertEquals(0, trans.getBufferPosition()); assertNull(trans.getBuffer()); assertEquals(-1, trans.getBytesRemainingInBuffer()); // Test file pointer operations assertEquals(0, trans.getFilePointer()); assertEquals(12, trans.length()); final int BUFSIZ = 4; byte[] buf1 = new byte[BUFSIZ]; trans.readAll(buf1, 0, BUFSIZ); assertEquals(BUFSIZ, trans.getFilePointer()); assertArrayEquals(new byte[] {1, 2, 3, 4}, buf1); int bytesRead = trans.read(buf1, 0, BUFSIZ); assert (bytesRead > 0); for (int i = 0; i < bytesRead; ++i) { assertEquals(buf1[i], i + 5); } trans.seek(0); assertEquals(0, trans.getFilePointer()); trans.readAll(buf1, 0, BUFSIZ); assertArrayEquals(new byte[] {1, 2, 3, 4}, buf1); assertEquals(BUFSIZ, trans.getFilePointer()); trans.close(); Files.delete(tempFilePathName); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTIOStreamTransport.java0000644000000000000000000000437214303740367032065 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import org.junit.jupiter.api.Test; public class TestTIOStreamTransport { // THRIFT-5022 @Test public void testOpenClose_2streams() throws TTransportException { byte[] dummy = {20}; // So the input stream isn't EOF immediately. InputStream input = new ByteArrayInputStream(dummy); OutputStream output = new ByteArrayOutputStream(); TTransport transport = new TIOStreamTransport(input, output); runOpenClose(transport); } // THRIFT-5022 @Test public void testOpenClose_1input() throws TTransportException { byte[] dummy = {20}; InputStream input = new ByteArrayInputStream(dummy); TTransport transport = new TIOStreamTransport(input); runOpenClose(transport); } // THRIFT-5022 @Test public void testIOpenClose_1output() throws TTransportException { OutputStream output = new ByteArrayOutputStream(); TTransport transport = new TIOStreamTransport(output); runOpenClose(transport); } private void runOpenClose(TTransport transport) throws TTransportException { transport.open(); boolean b1 = transport.isOpen(); assertTrue(b1); transport.close(); boolean b2 = transport.isOpen(); assertFalse(b2); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/ReadCountingTransport.java0000644000000000000000000000417714303740367032003 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.TConfiguration; public class ReadCountingTransport extends TTransport { public int readCount = 0; private TTransport trans; private boolean open = true; public ReadCountingTransport(TTransport underlying) { trans = underlying; } @Override public void close() { open = false; } @Override public boolean isOpen() { return open; } @Override public void open() throws TTransportException { open = true; } @Override public int read(byte[] buf, int off, int len) throws TTransportException { if (!isOpen()) { throw new TTransportException(TTransportException.NOT_OPEN, "Transport is closed"); } readCount++; return trans.read(buf, off, len); } @Override public void write(byte[] buf, int off, int len) throws TTransportException { if (!isOpen()) { throw new TTransportException(TTransportException.NOT_OPEN, "Transport is closed"); } } @Override public TConfiguration getConfiguration() { return trans.getConfiguration(); } @Override public void updateKnownMessageSize(long size) throws TTransportException { trans.updateKnownMessageSize(size); } @Override public void checkReadBytesAvailable(long numBytes) throws TTransportException { trans.checkReadBytesAvailable(numBytes); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestNonblockingServerSocket.java0000644000000000000000000000255314303740367033143 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertFalse; import java.nio.channels.ServerSocketChannel; import org.junit.jupiter.api.Test; public class TestNonblockingServerSocket { @Test public void testSocketChannelBlockingMode() throws TTransportException { try (TNonblockingServerSocket nonblockingServer = new TNonblockingServerSocket(0)) { ServerSocketChannel socketChannel = nonblockingServer.getServerSocketChannel(); assertFalse(socketChannel.isBlocking(), "Socket channel should be nonblocking"); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTFastFramedTransport.java0000644000000000000000000000262114303740367032411 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import org.apache.thrift.transport.layered.TFastFramedTransport; public class TestTFastFramedTransport extends TestTFramedTransport { protected static final int INITIAL_CAPACITY = 50; @Override protected TTransport getTransport(TTransport underlying) throws TTransportException { return new TFastFramedTransport(underlying, INITIAL_CAPACITY, 10 * 1024 * 1024); } @Override protected TTransport getTransport(TTransport underlying, int maxLength) throws TTransportException { return new TFastFramedTransport(underlying, INITIAL_CAPACITY, maxLength); } } TestAutoExpandingBufferWriteTransport.java0000644000000000000000000000567214303740367035116 0ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.nio.ByteBuffer; import org.apache.thrift.TConfiguration; import org.junit.jupiter.api.Test; public class TestAutoExpandingBufferWriteTransport { private final TConfiguration config = new TConfiguration(); @Test public void testIt() throws Exception { AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(config, 1, 0); assertEquals(0, t.getLength()); assertEquals(1, t.getBuf().array().length); byte[] b1 = new byte[] {1, 2, 3}; t.write(b1); assertEquals(3, t.getLength()); assertTrue(t.getBuf().array().length >= 3); assertEquals(ByteBuffer.wrap(b1), ByteBuffer.wrap(t.getBuf().array(), 0, 3)); t.reset(); assertEquals(0, t.getLength()); assertTrue(t.getBuf().array().length >= 3); byte[] b2 = new byte[] {4, 5}; t.write(b2); assertEquals(2, t.getLength()); assertEquals(ByteBuffer.wrap(b2), ByteBuffer.wrap(t.getBuf().array(), 0, 2)); AutoExpandingBufferWriteTransport uut = new AutoExpandingBufferWriteTransport(config, 8, 4); assertEquals(4, uut.getLength()); assertEquals(8, uut.getBuf().array().length); uut.write(b1); assertEquals(7, uut.getLength()); assertEquals(8, uut.getBuf().array().length); assertEquals(ByteBuffer.wrap(b1), ByteBuffer.wrap(uut.getBuf().array(), 4, 3)); } @Test public void testBadInitialSize() throws TTransportException { assertThrows( IllegalArgumentException.class, () -> new AutoExpandingBufferWriteTransport(config, 0, 0)); } @Test public void testBadFrontReserveSize() throws IllegalArgumentException, TTransportException { assertThrows( IllegalArgumentException.class, () -> new AutoExpandingBufferWriteTransport(config, 4, -1)); } @Test public void testTooSmallFrontReserveSize() throws IllegalArgumentException, TTransportException { assertThrows( IllegalArgumentException.class, () -> new AutoExpandingBufferWriteTransport(config, 4, 5)); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTZlibTransport.java0000644000000000000000000001212314303740367031273 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.zip.DataFormatException; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; import org.junit.jupiter.api.Test; public class TestTZlibTransport { protected TTransport getTransport(TTransport underlying) throws TTransportException { return new TZlibTransport(underlying); } public static byte[] byteSequence(int start, int end) { byte[] result = new byte[end - start + 1]; for (int i = 0; i <= (end - start); i++) { result[i] = (byte) (start + i); } return result; } @Test public void testClose() throws TTransportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); WriteCountingTransport countingTrans = new WriteCountingTransport(new TIOStreamTransport(new BufferedOutputStream(baos))); TTransport trans = getTransport(countingTrans); trans.write(byteSequence(0, 245)); countingTrans.close(); trans.close(); } @Test public void testCloseOpen() throws TTransportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); TTransport trans = getTransport(new TIOStreamTransport(baos)); byte[] uncompressed = byteSequence(0, 245); trans.write(uncompressed); trans.close(); final byte[] compressed = baos.toByteArray(); final byte[] buf = new byte[255]; TTransport transRead = getTransport(new TIOStreamTransport(new ByteArrayInputStream(compressed))); int readBytes = transRead.read(buf, 0, buf.length); assertEquals(uncompressed.length, readBytes); transRead.close(); } @Test public void testRead() throws IOException, TTransportException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(baos); DataOutputStream dos = new DataOutputStream(deflaterOutputStream); dos.write(byteSequence(0, 49)); dos.write(byteSequence(0, 219)); deflaterOutputStream.finish(); TMemoryBuffer membuf = new TMemoryBuffer(0); membuf.write(baos.toByteArray()); ReadCountingTransport countTrans = new ReadCountingTransport(membuf); TTransport trans = getTransport(countTrans); byte[] readBuf = new byte[10]; trans.read(readBuf, 0, 10); assertArrayEquals(readBuf, byteSequence(0, 9)); assertEquals(1, countTrans.readCount); trans.read(readBuf, 0, 10); assertArrayEquals(readBuf, byteSequence(10, 19)); assertEquals(1, countTrans.readCount); assertEquals(30, trans.read(new byte[30], 0, 30)); assertEquals(1, countTrans.readCount); readBuf = new byte[220]; assertEquals(220, trans.read(readBuf, 0, 220)); assertArrayEquals(readBuf, byteSequence(0, 219)); assertEquals(1, countTrans.readCount); } @Test public void testWrite() throws TTransportException, IOException, DataFormatException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); WriteCountingTransport countingTrans = new WriteCountingTransport(new TIOStreamTransport(new BufferedOutputStream(baos))); TTransport trans = getTransport(countingTrans); trans.write(byteSequence(0, 100)); assertEquals(1, countingTrans.writeCount); trans.write(byteSequence(101, 200)); trans.write(byteSequence(201, 255)); assertEquals(1, countingTrans.writeCount); trans.flush(); assertEquals(2, countingTrans.writeCount); trans.write(byteSequence(0, 245)); trans.flush(); assertEquals(3, countingTrans.writeCount); DataInputStream din = new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(baos.toByteArray()))); byte[] buf = new byte[256]; int n = din.read(buf, 0, 256); assertEquals(n, 256); assertArrayEquals(byteSequence(0, 255), buf); buf = new byte[246]; n = din.read(buf, 0, 246); assertEquals(n, 246); for (int i = 0; i < buf.length; i++) { assertEquals(byteSequence(0, 245)[i], buf[i], "for " + i); } assertArrayEquals(byteSequence(0, 245), buf); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTMemoryTransport.java0000644000000000000000000000551714303740367031654 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import java.nio.ByteBuffer; import java.util.Random; import org.apache.thrift.TByteArrayOutputStream; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.function.Executable; public class TestTMemoryTransport { @Test public void testReadBatches() throws TTransportException { byte[] inputBytes = {0x10, 0x7A, (byte) 0xBF, (byte) 0xFE, 0x53, (byte) 0x82, (byte) 0xFF}; TMemoryTransport transport = new TMemoryTransport(inputBytes); byte[] read = new byte[inputBytes.length]; int firstBatch = new Random().nextInt(inputBytes.length); int secondBatch = inputBytes.length - firstBatch; transport.read(read, 0, firstBatch); transport.read(read, firstBatch, secondBatch); boolean equal = true; for (int i = 0; i < inputBytes.length; i++) { equal = equal && inputBytes[i] == read[i]; } assertEquals(ByteBuffer.wrap(inputBytes), ByteBuffer.wrap(read)); } @Test public void testReadMoreThanRemaining() throws TTransportException { TMemoryTransport transport = new TMemoryTransport(new byte[] {0x00, 0x32}); byte[] read = new byte[3]; assertThrows( TTransportException.class, new Executable() { @Override public void execute() throws Throwable { transport.read(read, 0, 3); } }); } @Test public void testWrite() throws TTransportException { TMemoryTransport transport = new TMemoryTransport(new byte[0]); byte[] output1 = {0x72, 0x56, 0x29, (byte) 0xAF, (byte) 0x9B}; transport.write(output1); byte[] output2 = {(byte) 0x83, 0x10, 0x00}; transport.write(output2, 0, 2); byte[] expected = {0x72, 0x56, 0x29, (byte) 0xAF, (byte) 0x9B, (byte) 0x83, 0x10}; TByteArrayOutputStream outputByteArray = transport.getOutput(); assertEquals( ByteBuffer.wrap(expected), ByteBuffer.wrap(outputByteArray.get(), 0, outputByteArray.len())); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/transport/TestTMemoryInputTransport.java0000644000000000000000000000637714303740367032701 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.transport; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import org.junit.jupiter.api.Test; public class TestTMemoryInputTransport { @Test public void testFresh() throws Exception { byte[] input_buf = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; TMemoryInputTransport trans = new TMemoryInputTransport(input_buf); assertEquals(0, trans.getBufferPosition()); assertEquals(input_buf, trans.getBuffer()); assertEquals(10, trans.getBytesRemainingInBuffer()); byte[] buf1 = new byte[4]; trans.readAll(buf1, 0, 4); assertArrayEquals(new byte[] {1, 2, 3, 4}, buf1); assertEquals(4, trans.getBufferPosition()); assertEquals(6, trans.getBytesRemainingInBuffer()); trans.consumeBuffer(2); assertEquals(6, trans.getBufferPosition()); assertEquals(4, trans.getBytesRemainingInBuffer()); trans.readAll(buf1, 0, 4); assertArrayEquals(new byte[] {7, 8, 9, 10}, buf1); assertEquals(10, trans.getBufferPosition()); assertEquals(0, trans.getBytesRemainingInBuffer()); } @Test public void testReused() throws Exception { byte[] input_buf = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; TMemoryInputTransport trans = new TMemoryInputTransport(input_buf); assertEquals(0, trans.getBufferPosition()); assertEquals(input_buf, trans.getBuffer()); assertEquals(10, trans.getBytesRemainingInBuffer()); byte[] new_buf = new byte[] {10, 9, 8}; trans.reset(new_buf); assertEquals(0, trans.getBufferPosition()); assertEquals(new_buf, trans.getBuffer()); assertEquals(3, trans.getBytesRemainingInBuffer()); } @Test public void testWithOffsetAndLength() throws TTransportException { byte[] input_buf = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; TMemoryInputTransport trans = new TMemoryInputTransport(input_buf, 1, 3); assertEquals(1, trans.getBufferPosition()); assertEquals(3, trans.getBytesRemainingInBuffer()); { byte[] readBuffer = new byte[3]; trans.readAll(readBuffer, 0, 3); assertArrayEquals(new byte[] {2, 3, 4}, readBuffer); assertThrows(Exception.class, () -> trans.readAll(readBuffer, 0, 3)); } { trans.reset(input_buf, 3, 4); byte[] readBuffer2 = new byte[4]; trans.readAll(readBuffer2, 0, 4); assertArrayEquals(new byte[] {4, 5, 6, 7}, readBuffer2); } } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestReuse.java0000644000000000000000000000352314303740367025365 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertSame; import java.util.HashSet; import org.apache.thrift.protocol.TBinaryProtocol; import org.junit.jupiter.api.Test; import thrift.test.Reuse; // Tests reusing objects for deserialization. // public class TestReuse extends TestStruct { @Test public void testReuseObject() throws Exception { TSerializer binarySerializer = new TSerializer(new TBinaryProtocol.Factory()); TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory()); Reuse ru1 = new Reuse(); HashSet hs1 = new HashSet<>(); byte[] serBytes; String st1 = "string1"; String st2 = "string2"; ru1.setVal1(11); ru1.setVal2(hs1); ru1.addToVal2(st1); serBytes = binarySerializer.serialize(ru1); // update hash set after serialization hs1.add(st2); binaryDeserializer.deserialize(ru1, serBytes); assertSame(hs1, ru1.getVal2()); assertEquals(2, hs1.size()); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestRenderedDoubleConstants.java0000644000000000000000000002541514303740367031066 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import thrift.test.DoubleConstantsTestConstants; public class TestRenderedDoubleConstants { private static final double EPSILON = 0.0000001; private static final String ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST = "failed to verify a double constant generated by Thrift (expected = %f, got = %f)"; private static final String ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST = "failed to verify a list item by Thrift (expected = %f, got = %f)"; private static final String ASSERTION_MESSAGE_FOR_TYPE_CHECKS = "the rendered variable with name %s is not of double type"; // to make sure lists containing doubles are generated correctly @Test public void testRenderedDoubleList() throws Exception { final double[] EXPECTED_LIST = { 1d, -100d, 100d, 9223372036854775807d, -9223372036854775807d, 3.14159265359, 1000000.1, -1000000.1, 1.7e+308, -1.7e+308, 9223372036854775816.43, -9223372036854775816.43 }; assertEquals(EXPECTED_LIST.length, DoubleConstantsTestConstants.DOUBLE_LIST_TEST.size()); for (int i = 0; i < EXPECTED_LIST.length; ++i) { assertEquals( EXPECTED_LIST[i], DoubleConstantsTestConstants.DOUBLE_LIST_TEST.get(i), EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_LIST_TEST, EXPECTED_LIST[i], DoubleConstantsTestConstants.DOUBLE_LIST_TEST.get(i))); } } // to make sure the variables inside Thrift files are generated correctly @Test public void testRenderedDoubleConstants() throws Exception { final double EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0; final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0; final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0; final double EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0; final double EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359; final double EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1; final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1; final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308; final double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43; final double EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308; final double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43; assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)); assertEquals( EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, EPSILON, String.format( ASSERTION_MESSAGE_FOR_RENDERED_DOUBLE_CONSTANTS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, DoubleConstantsTestConstants .DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)); assertTrue( Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST), String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST")); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST")); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST")); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST")); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST")); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST")); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST")); // assertTrue( // String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST"), // // Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST")); // assertTrue( // String.format(ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST"), // // Double.class.isInstance(DoubleConstantsTestConstants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)); assertTrue( Double.class.isInstance( DoubleConstantsTestConstants .DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST), String.format( ASSERTION_MESSAGE_FOR_TYPE_CHECKS, "DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST")); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestFullCamel.java0000644000000000000000000000400214303740367026137 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.thrift.protocol.TBinaryProtocol; import org.junit.jupiter.api.Test; import thrift.test.fullcamel.OneOfEachZZ; import thrift.test.fullcamel.UnderscoreSrv; // Sanity check for the code generated by 'fullcamel'. // public class TestFullCamel { @Test public void testCamelCaseSyntax() throws Exception { TSerializer binarySerializer = new TSerializer(new TBinaryProtocol.Factory()); TDeserializer binaryDeserializer = new TDeserializer(new TBinaryProtocol.Factory()); OneOfEachZZ obj = new OneOfEachZZ(); obj.setABite((byte) 0xae); obj.setImFalse(true); byte[] serBytes = binarySerializer.serialize(obj); binaryDeserializer.deserialize(obj, serBytes); assertEquals((byte) 0xae, obj.getABite()); assertTrue(obj.isImFalse()); } @Test public void testCamelCaseRpcMethods() throws Exception { final UnderscoreSrv.Iface srv = new UnderscoreSrv.Iface() { @Override public long someRpcCall(String message) { return 1l; } }; assertTrue(1l == srv.someRpcCall("test")); } } thrift-0.19.0/lib/java/src/test/java/org/apache/thrift/TestTDeserializer.java0000644000000000000000000001645414303740367027057 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift; import static org.junit.jupiter.api.Assertions.assertEquals; import java.nio.ByteBuffer; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TJSONProtocol; import org.apache.thrift.protocol.TProtocolFactory; import org.junit.jupiter.api.Test; import thrift.test.Backwards; import thrift.test.OneOfEach; import thrift.test.PrimitiveThenStruct; import thrift.test.StructWithAUnion; import thrift.test.TestUnion; public class TestTDeserializer { private static final TProtocolFactory[] PROTOCOLS = new TProtocolFactory[] { new TBinaryProtocol.Factory(), new TCompactProtocol.Factory(), new TJSONProtocol.Factory() }; @Test public void testPartialDeserialize() throws Exception { // Root:StructWithAUnion // 1:Union // 1.3:OneOfEach OneOfEach level3OneOfEach = Fixtures.getOneOfEach(); TestUnion level2TestUnion = new TestUnion(TestUnion._Fields.STRUCT_FIELD, level3OneOfEach); StructWithAUnion level1SWU = new StructWithAUnion(level2TestUnion); Backwards bw = new Backwards(2, 1); PrimitiveThenStruct pts = new PrimitiveThenStruct(12345, 67890, bw); for (TProtocolFactory factory : PROTOCOLS) { // Level 2 test testPartialDeserialize( factory, level1SWU, new TestUnion(), level2TestUnion, StructWithAUnion._Fields.TEST_UNION); // Level 3 on 3rd field test testPartialDeserialize( factory, level1SWU, new OneOfEach(), level3OneOfEach, StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD); // Test early termination when traversed path Field.id exceeds the one being searched for testPartialDeserialize( factory, level1SWU, new OneOfEach(), new OneOfEach(), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.I32_FIELD); // Test that readStructBegin isn't called on primitive testPartialDeserialize(factory, pts, new Backwards(), bw, PrimitiveThenStruct._Fields.BW); // Test primitive types TDeserializer deserializer = new TDeserializer(factory); Boolean expectedBool = level3OneOfEach.isIm_true(); Boolean resultBool = deserializer.partialDeserializeBool( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.IM_TRUE); assertEquals(expectedBool, resultBool); Byte expectedByte = level3OneOfEach.getA_bite(); Byte resultByte = deserializer.partialDeserializeByte( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.A_BITE); assertEquals(expectedByte, resultByte); Double expectedDouble = level3OneOfEach.getDouble_precision(); Double resultDouble = deserializer.partialDeserializeDouble( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.DOUBLE_PRECISION); assertEquals(expectedDouble, resultDouble); Short expectedI16 = level3OneOfEach.getInteger16(); Short resultI16 = deserializer.partialDeserializeI16( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.INTEGER16); assertEquals(expectedI16, resultI16); Integer expectedI32 = level3OneOfEach.getInteger32(); Integer resultI32 = deserializer.partialDeserializeI32( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.INTEGER32); assertEquals(expectedI32, resultI32); Long expectedI64 = level3OneOfEach.getInteger64(); Long resultI64 = deserializer.partialDeserializeI64( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.INTEGER64); assertEquals(expectedI64, resultI64); String expectedString = level3OneOfEach.getSome_characters(); String resultString = deserializer.partialDeserializeString( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.SOME_CHARACTERS); assertEquals(expectedString, resultString); byte[] expectedBinary = level3OneOfEach.getBase64(); ByteBuffer resultBinary = deserializer.partialDeserializeByteArray( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION, TestUnion._Fields.STRUCT_FIELD, OneOfEach._Fields.BASE64); assertEquals( expectedBinary.length, resultBinary.limit() - resultBinary.position() - resultBinary.arrayOffset()); assertEquals(ByteBuffer.wrap(expectedBinary), resultBinary); // Test field id in Union short id = deserializer.partialDeserializeSetFieldIdInUnion( serialize(level1SWU, factory), StructWithAUnion._Fields.TEST_UNION); assertEquals(level2TestUnion.getSetField().getThriftFieldId(), id); } } private void testPartialDeserialize( TProtocolFactory protocolFactory, TBase input, TBase output, TBase expected, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum... fieldIdPathRest) throws TException { byte[] record = serialize(input, protocolFactory); TDeserializer deserializer = new TDeserializer(protocolFactory); for (int i = 0; i < 2; i++) { TBase outputCopy = output.deepCopy(); deserializer.partialDeserialize(outputCopy, record, fieldIdPathFirst, fieldIdPathRest); assertEquals( expected, outputCopy, "on attempt " + i + ", with " + protocolFactory + ", expected " + expected + " but got " + outputCopy); } } private static byte[] serialize(TBase input, TProtocolFactory protocolFactory) throws TException { return new TSerializer(protocolFactory).serialize(input); } } thrift-0.19.0/lib/java/src/crossTest/0000777000000000000000000000000014303472263017356 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/crossTest/resources/0000777000000000000000000000000014303740367021373 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/src/crossTest/resources/.keystore0000644000000000000000000000457514303740367023250 0ustar00rootroot00000000000000þíþí1E=¹µ0‚ü0 +*‚èÂÓ£ÓÇ·Ãùé<[Å´Í87gÐ-þof²-ÈÃâá;­ËéÂo×{7ɺuoækÑt;ÄBù=›Ìmñ ësÂ]_Xä<-<ÿ\Mo&˜á,H®Q:¸Áœ šÌ_+&D…}Zo»o¼úùPV,&úíþ@^–¨œÃ,R:d4æµ¾ŒéeA¡NGOÈí8Ð(!çSÄ-Þt ±°ÞDœŸz|VR‘Ál}ˆ¿V3f°} ÚžˆçŸÁ«F<ÅÎÛÞÀb†[U…þ®áðd¢—9ˣÛæï¯A4›j*™z·ÃÙ ±X ˆŽ:aïçM·ëz¸98ñ]™šÀeh„Î`ÜÂÓÑÀk~-»TîKÛqylب»p\¶U/É9¨¹wqž¸É™i‡^94$ XY~ñ½Q×"Æ„ÙVQ Rkcµ˜b§°çÓc¿¸/ VÞ>ú­+šaÑ'šcpó¤Úr4ÉÂ{$¢Š¯hMâÆ^x;¿­Æ @$/}S`wŸÄTßÓªO`÷œ¹KlxÌ¹Š³»žô+}çº|KèÅþ&. 9é(”j]‡à7R>«nj(ë5é8¾¶œö×¶=ÐS M¸µ)Ū¥ÎȪõet @?:X£Ìá—¿chfvy.¡–£Î[Hö›cyŒIÚ(Ô6£.ô@¶~``ÙÞ«í©õÖÜàv~Àsã̈åÕVª:ʤ„¾F,RK ` ¨N×/ñýyɯaì´¦ÅÃû933¸Ý§R”)×c#¡5 L–‡þ ñ/\EWE†Lb€àü^AS2}SÌO°ìåN±„>[ô/¥vØn —_ Œ³–~“Ñù¸Ñ±¼œ6–Š«Æ#€Ÿ“qÓ–9f®¦´Aèå^æÃA£×d£’à°Maž$-bz]TÎÚ–«çÓƒ@ηô÷cáœ3¦ìªýŠ\,ç²Y– ±«è.²•&|w\!´!`â–tò2È$¨«0Ãʼ¬Éݧºÿm„N9þAÔeβÃhvQ¤ñQ¸8/ßu§xŸ§Zd™7‚~莔I‰jlnq§aív=lÎ>%X©Eù¾d–᎛åùà¾qÝu•P^Æ)F¬§vÝôí•“g“kúatùk¥µ²À¦m³O Uèñˆ×m]ð—.<`îîåÏ ´¡Â¢¡pF™·µBÿÃ& ¹Þý¯sȼãw^8P«r7áYñ†à’8– á„Nx<÷ÝéDìÊnvòÄÓXùmŠî?&|šT+œ¸+þ¾Åòj> ÿɯëvÖ¼°SP¨À™+1ÎÎøUª) >ŸFÞË'¦ÍRÙ‰Vº2ºÄÃv«“BœÏÀ‘3ô,¼ù….qržx¨Ånu´³Q½[çA-ÃÈ×Yõ-Yn¿uøX!ÊK‘0#ç8¿fÑÁ‘ÉT èð^1ß¶ÍnÎ$àñ Ñ+LeD5ÿëé&•ËÇ™yss@|­Jï¥z½+T³àvíŒRï4 ª.EíÁƒWµñhÊ}‡ŠvcoõAMd£Xè÷.?+âIÊo ›9ýG1iô¢ëzŒt5ÓèkN%ÊIKô&ÃW}•˜Öþ'Ôç›Mü0q°ëÇV%¯š0[邏ËßjX.509;0‚70‚  æaü;4#œ0  *†H†÷ 0±1 0 UUS10U Maryland10U Forest Hill1'0%U The Apache Software Foundation10U Apache Thrift10U localhost1$0" *†H†÷  dev@thrift.apache.org0 140407185800Z 220624185800Z0±1 0 UUS10U Maryland10U Forest Hill1'0%U The Apache Software Foundation10U Apache Thrift10U localhost1$0" *†H†÷  dev@thrift.apache.org0‚"0  *†H†÷ ‚0‚ ‚ªÔÄ÷§’Ñ´´ !^üû¶m?ò?e¢zC¦F•üCöc^÷±ãaùJ•‰¿ùH‚ç4à²HßÙ|:/Ó èïÂA } 8x:1fs™ŒÑy'_åfÐ^:Œ ’sÁõEÛ7ç_ÇŒ£`é’ Ø)]wHû°í,N.Û=Aq¦+.³LjÇ÷©~ÇÏÛòç¶ów$ff0…0)Ä»÷Í?‰K_ô‘–ûé9òF–=Š#µ.‚žAþ@¶'±D\–0Uä»­‹Š™À)NvyK1~…<¨#@TX5ÆüÝ=ëãÑQ†×°Ÿ sjZÐæ¶¸U@^'£P0N0U(òý0ÍñÜAēƗÊÔú`*0U#0€(òý0ÍñÜAēƗÊÔú`*0 U0ÿ0  *†H†÷ ‚F‰²WÑ¢dÁšsO”v)ºo4FÂ6Õh…ôLŽþƒySìª ’`Þóš:è€f¬‡p‰Yò¬ž°(7}xN^?%¾ o&*=fy8(åqq–&OÛì#p¾79üà2 €fǬ¤´‹w@â™D:sÈùÏ2'ÂxÛ°ÚŠ`ë4~}<Ô8t÷ž2tšç7•ÔqÈ”ê {­-ëpCò2~c„Œ~žðy®éÏù¾þ•ҽȧÂqÙÃP1‰mú­¢«4Xï–Zë0©Ž„6ï= T unwrap(Class iface) { try { if (isWrapperFor(iface)) { return iface.cast(this); } else { throw new RuntimeException("The context is not a wrapper for " + iface.getName()); } } catch (Exception e) { throw new RuntimeException( "The context is not a wrapper and does not implement the interface"); } } @Override public boolean isWrapperFor(Class iface) { return iface.isInstance(this); } } static class TestServerEventHandler implements TServerEventHandler { private int nextConnectionId = 1; public void preServe() { System.out.println( "TServerEventHandler.preServe - called only once before server starts accepting connections"); } public ServerContext createContext(TProtocol input, TProtocol output) { // we can create some connection level data which is stored while connection is alive & served TestServerContext ctx = new TestServerContext(nextConnectionId++); System.out.println( "TServerEventHandler.createContext - connection #" + ctx.getConnectionId() + " established"); return ctx; } public void deleteContext(ServerContext serverContext, TProtocol input, TProtocol output) { TestServerContext ctx = serverContext.unwrap(TestServerContext.class); System.out.println( "TServerEventHandler.deleteContext - connection #" + ctx.getConnectionId() + " terminated"); } public void processContext( ServerContext serverContext, TTransport inputTransport, TTransport outputTransport) { TestServerContext ctx = serverContext.unwrap(TestServerContext.class); System.out.println( "TServerEventHandler.processContext - connection #" + ctx.getConnectionId() + " is ready to process next request"); } } public static void main(String[] args) { try { int port = 9090; boolean ssl = false; boolean zlib = false; String transport_type = "buffered"; String protocol_type = "binary"; String server_type = "thread-pool"; String domain_socket = ""; int string_limit = -1; int container_limit = -1; try { for (int i = 0; i < args.length; i++) { if (args[i].startsWith("--port")) { port = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].startsWith("--server-type")) { server_type = args[i].split("=")[1]; server_type.trim(); } else if (args[i].startsWith("--port")) { port = Integer.parseInt(args[i].split("=")[1]); } else if (args[i].startsWith("--protocol")) { protocol_type = args[i].split("=")[1]; protocol_type.trim(); } else if (args[i].startsWith("--transport")) { transport_type = args[i].split("=")[1]; transport_type.trim(); } else if (args[i].equals("--ssl")) { ssl = true; } else if (args[i].equals("--zlib")) { zlib = true; } else if (args[i].startsWith("--string-limit")) { string_limit = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].startsWith("--container-limit")) { container_limit = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].equals("--help")) { System.out.println("Allowed options:"); System.out.println(" --help\t\t\tProduce help message"); System.out.println(" --port=arg (=" + port + ")\tPort number to connect"); System.out.println( " --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed, zlib"); System.out.println( " --protocol=arg (=" + protocol_type + ")\tProtocol: binary, compact, json, multi, multic, multij"); System.out.println(" --ssl\t\t\tEncrypted Transport using SSL"); System.out.println(" --zlib\t\t\tCompressed Transport using Zlib"); System.out.println( " --server-type=arg (=" + server_type + ")\n\t\t\t\tType of server: simple, thread-pool, nonblocking, threaded-selector"); System.out.println( " --string-limit=arg (=" + string_limit + ")\tString read length limit"); System.out.println( " --container-limit=arg (=" + container_limit + ")\tContainer read length limit"); System.exit(0); } } } catch (Exception e) { System.err.println("Can not parse arguments! See --help"); System.exit(1); } try { if (server_type.equals("simple")) { } else if (server_type.equals("thread-pool")) { } else if (server_type.equals("nonblocking")) { if (ssl == true) { throw new Exception("SSL is not supported over nonblocking servers!"); } } else if (server_type.equals("threaded-selector")) { if (ssl == true) { throw new Exception("SSL is not supported over nonblocking servers!"); } } else { throw new Exception("Unknown server type! " + server_type); } if (protocol_type.equals("binary")) { } else if (protocol_type.equals("compact")) { } else if (protocol_type.equals("json")) { } else if (protocol_type.equals("multi")) { } else if (protocol_type.equals("multic")) { } else if (protocol_type.equals("multij")) { } else { throw new Exception("Unknown protocol type! " + protocol_type); } if (transport_type.equals("buffered")) { } else if (transport_type.equals("framed")) { } else if (transport_type.equals("fastframed")) { } else if (transport_type.equals("zlib")) { } else { throw new Exception("Unknown transport type! " + transport_type); } } catch (Exception e) { System.err.println("Error: " + e.getMessage()); System.exit(1); } // Processors TestHandler testHandler = new TestHandler(); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); SecondHandler secondHandler = new SecondHandler(); SecondService.Processor secondProcessor = new SecondService.Processor(secondHandler); // Protocol factory TProtocolFactory tProtocolFactory = null; if (protocol_type.equals("json") || protocol_type.equals("multij")) { tProtocolFactory = new TJSONProtocol.Factory(); } else if (protocol_type.equals("compact") || protocol_type.equals("multic")) { tProtocolFactory = new TCompactProtocol.Factory(string_limit, container_limit); } else { // also covers multi tProtocolFactory = new TBinaryProtocol.Factory(string_limit, container_limit); } TTransportFactory tTransportFactory = null; if (transport_type.equals("framed")) { tTransportFactory = new TFramedTransport.Factory(); } else if (transport_type.equals("fastframed")) { tTransportFactory = new TFastFramedTransport.Factory(); } else if (transport_type.equals("zlib")) { tTransportFactory = new TZlibTransport.Factory(); } else { // .equals("buffered") => default value tTransportFactory = new TTransportFactory(); } TServer serverEngine = null; // If we are multiplexing services in one server... TMultiplexedProcessor multiplexedProcessor = new TMultiplexedProcessor(); multiplexedProcessor.registerDefault(testProcessor); multiplexedProcessor.registerProcessor("ThriftTest", testProcessor); multiplexedProcessor.registerProcessor("SecondService", secondProcessor); if (server_type.equals("nonblocking") || server_type.equals("threaded-selector")) { // Nonblocking servers TNonblockingServerSocket tNonblockingServerSocket = new TNonblockingServerSocket( new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs().port(port)); if (server_type.contains("nonblocking")) { // Nonblocking Server TNonblockingServer.Args tNonblockingServerArgs = new TNonblockingServer.Args(tNonblockingServerSocket); tNonblockingServerArgs.processor( protocol_type.startsWith("multi") ? multiplexedProcessor : testProcessor); tNonblockingServerArgs.protocolFactory(tProtocolFactory); tNonblockingServerArgs.transportFactory(tTransportFactory); serverEngine = new TNonblockingServer(tNonblockingServerArgs); } else { // server_type.equals("threaded-selector") // ThreadedSelector Server TThreadedSelectorServer.Args tThreadedSelectorServerArgs = new TThreadedSelectorServer.Args(tNonblockingServerSocket); tThreadedSelectorServerArgs.processor( protocol_type.startsWith("multi") ? multiplexedProcessor : testProcessor); tThreadedSelectorServerArgs.protocolFactory(tProtocolFactory); tThreadedSelectorServerArgs.transportFactory(tTransportFactory); serverEngine = new TThreadedSelectorServer(tThreadedSelectorServerArgs); } } else { // Blocking servers // SSL socket TServerSocket tServerSocket = null; if (ssl) { tServerSocket = TSSLTransportFactory.getServerSocket(port, 0); } else { tServerSocket = new TServerSocket(new TServerSocket.ServerSocketTransportArgs().port(port)); } if (server_type.equals("simple")) { // Simple Server TServer.Args tServerArgs = new TServer.Args(tServerSocket); tServerArgs.processor( protocol_type.startsWith("multi") ? multiplexedProcessor : testProcessor); tServerArgs.protocolFactory(tProtocolFactory); tServerArgs.transportFactory(tTransportFactory); serverEngine = new TSimpleServer(tServerArgs); } else { // server_type.equals("threadpool") // ThreadPool Server TThreadPoolServer.Args tThreadPoolServerArgs = new TThreadPoolServer.Args(tServerSocket); tThreadPoolServerArgs.processor( protocol_type.startsWith("multi") ? multiplexedProcessor : testProcessor); tThreadPoolServerArgs.protocolFactory(tProtocolFactory); tThreadPoolServerArgs.transportFactory(tTransportFactory); serverEngine = new TThreadPoolServer(tThreadPoolServerArgs); } } // Set server event handler serverEngine.setServerEventHandler(new TestServerEventHandler()); // Run it System.out.println( "Starting the " + (ssl ? "ssl server" : "server") + " [" + protocol_type + "/" + transport_type + "/" + server_type + "] on " + ((domain_socket == "") ? ("port " + port) : ("unix socket " + domain_socket))); serverEngine.serve(); } catch (Exception x) { x.printStackTrace(); } System.out.println("done."); } } thrift-0.19.0/lib/java/src/crossTest/java/org/apache/thrift/test/TestNonblockingServer.java0000644000000000000000000000467414303740367031735 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import org.apache.thrift.server.ServerTestBase.TestHandler; import org.apache.thrift.server.THsHaServer; import org.apache.thrift.server.THsHaServer.Args; import org.apache.thrift.server.TNonblockingServer; import org.apache.thrift.server.TServer; import org.apache.thrift.transport.TNonblockingServerSocket; import thrift.test.ThriftTest; public class TestNonblockingServer extends TestServer { public static void main(String[] args) { try { int port = 9090; boolean hsha = false; for (int i = 0; i < args.length; i++) { if (args[i].equals("-p")) { port = Integer.valueOf(args[i++]); } else if (args[i].equals("-hsha")) { hsha = true; } } // @TODO add other protocol and transport types // Processor TestHandler testHandler = new TestHandler(); ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); // Transport TNonblockingServerSocket tServerSocket = new TNonblockingServerSocket( new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs().port(port)); TServer serverEngine; if (hsha) { // HsHa Server serverEngine = new THsHaServer(new Args(tServerSocket).processor(testProcessor)); } else { // Nonblocking Server serverEngine = new TNonblockingServer(new Args(tServerSocket).processor(testProcessor)); } // Run it System.out.println("Starting the server on port " + port + "..."); serverEngine.serve(); } catch (Exception x) { x.printStackTrace(); } System.out.println("done."); } } thrift-0.19.0/lib/java/src/crossTest/java/org/apache/thrift/test/TestTServletServer.java0000644000000000000000000000331714303740367031233 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import org.apache.catalina.core.StandardContext; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.Tomcat.FixContextListener; /** run tomcat for test TServlet */ public class TestTServletServer { static final int port = 9090; public static void main(String[] args) throws Exception { Tomcat tomcat = new Tomcat(); tomcat.setPort(port); tomcat.setBaseDir(System.getProperty("user.dir") + "\\build"); tomcat.getHost().setAutoDeploy(false); String contextPath = "/test"; StandardContext context = new StandardContext(); context.setPath(contextPath); context.addLifecycleListener(new FixContextListener()); tomcat.getHost().addChild(context); tomcat.addServlet(contextPath, "testServlet", new TestServlet()); context.addServletMappingDecoded("/service", "testServlet"); tomcat.start(); tomcat.getServer().await(); } } thrift-0.19.0/lib/java/src/crossTest/java/org/apache/thrift/test/TestClient.java0000644000000000000000000007152014452237057027515 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.stream.IntStream; import org.apache.hc.client5.http.impl.classic.HttpClients; import org.apache.thrift.TApplicationException; import org.apache.thrift.TException; import org.apache.thrift.TSerializer; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TCompactProtocol; import org.apache.thrift.protocol.TJSONProtocol; import org.apache.thrift.protocol.TMultiplexedProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.protocol.TSimpleJSONProtocol; import org.apache.thrift.transport.THttpClient; import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TZlibTransport; import org.apache.thrift.transport.layered.TFastFramedTransport; import org.apache.thrift.transport.layered.TFramedTransport; import thrift.test.Insanity; import thrift.test.Numberz; import thrift.test.SecondService; import thrift.test.ThriftTest; import thrift.test.Xception; import thrift.test.Xception2; import thrift.test.Xtruct; import thrift.test.Xtruct2; /** * Test Java client for thrift. Essentially just a copy of the C++ version, this makes a variety of * requests to enable testing for both performance and correctness of the output. */ public class TestClient { private static int ERR_BASETYPES = 1; private static int ERR_STRUCTS = 2; private static int ERR_CONTAINERS = 4; private static int ERR_EXCEPTIONS = 8; private static int ERR_PROTOCOLS = 16; private static int ERR_UNKNOWN = 64; public static void main(String[] args) { String host = "localhost"; int port = 9090; int numTests = 1; String protocol_type = "binary"; String transport_type = "buffered"; boolean ssl = false; boolean zlib = false; boolean http_client = false; int socketTimeout = 1000; try { for (int i = 0; i < args.length; ++i) { if (args[i].startsWith("--host")) { host = args[i].split("=")[1]; host.trim(); } else if (args[i].startsWith("--port")) { port = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].startsWith("--n") || args[i].startsWith("--testloops")) { numTests = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].equals("--timeout")) { socketTimeout = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].startsWith("--protocol")) { protocol_type = args[i].split("=")[1]; protocol_type.trim(); } else if (args[i].startsWith("--transport")) { transport_type = args[i].split("=")[1]; transport_type.trim(); } else if (args[i].equals("--ssl")) { ssl = true; } else if (args[i].equals("--zlib")) { zlib = true; } else if (args[i].equals("--client")) { http_client = true; } else if (args[i].equals("--help")) { System.out.println("Allowed options:"); System.out.println(" --help\t\t\tProduce help message"); System.out.println(" --host=arg (=" + host + ")\tHost to connect"); System.out.println(" --port=arg (=" + port + ")\tPort number to connect"); System.out.println( " --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed, http, zlib"); System.out.println( " --protocol=arg (=" + protocol_type + ")\tProtocol: binary, compact, json, multi, multic, multij"); System.out.println(" --ssl\t\t\tEncrypted Transport using SSL"); System.out.println(" --zlib\t\t\tCompressed Transport using Zlib"); System.out.println(" --testloops[--n]=arg (=" + numTests + ")\tNumber of Tests"); System.exit(0); } } } catch (Exception x) { System.err.println("Can not parse arguments! See --help"); System.exit(ERR_UNKNOWN); } try { if (protocol_type.equals("binary")) { } else if (protocol_type.equals("compact")) { } else if (protocol_type.equals("json")) { } else if (protocol_type.equals("multi")) { } else if (protocol_type.equals("multic")) { } else if (protocol_type.equals("multij")) { } else { throw new Exception("Unknown protocol type! " + protocol_type); } if (transport_type.equals("buffered")) { } else if (transport_type.equals("framed")) { } else if (transport_type.equals("fastframed")) { } else if (transport_type.equals("http")) { } else if (transport_type.equals("zlib")) { } else { throw new Exception("Unknown transport type! " + transport_type); } if (transport_type.equals("http") && ssl == true) { throw new Exception("SSL is not supported over http."); } } catch (Exception e) { System.err.println("Error: " + e.getMessage()); System.exit(ERR_UNKNOWN); } TTransport transport = null; try { if (transport_type.equals("http")) { String url = "http://" + host + ":" + port + "/test/service"; if (http_client == true) { transport = new THttpClient(url, HttpClients.createDefault()); } else { transport = new THttpClient(url); } } else { TSocket socket = null; if (ssl == true) { socket = TSSLTransportFactory.getClientSocket(host, port, 0); } else { socket = new TSocket(host, port); } socket.setTimeout(socketTimeout); transport = socket; if (transport_type.equals("zlib")) { transport = new TZlibTransport(transport); } else { if (transport_type.equals("buffered")) { } else if (transport_type.equals("framed")) { transport = new TFramedTransport(transport); } else if (transport_type.equals("fastframed")) { transport = new TFastFramedTransport(transport); } if (zlib) { transport = new TZlibTransport(transport); } } } } catch (Exception x) { x.printStackTrace(); System.exit(ERR_UNKNOWN); } TProtocol tProtocol = null; TProtocol tProtocol2 = null; if (protocol_type.equals("json") || protocol_type.equals("multij")) { tProtocol = new TJSONProtocol(transport); } else if (protocol_type.equals("compact") || protocol_type.equals("multic")) { tProtocol = new TCompactProtocol(transport); } else { tProtocol = new TBinaryProtocol(transport); } if (protocol_type.startsWith("multi")) { tProtocol2 = new TMultiplexedProtocol(tProtocol, "SecondService"); tProtocol = new TMultiplexedProtocol(tProtocol, "ThriftTest"); } ThriftTest.Client testClient = new ThriftTest.Client(tProtocol); Insanity insane = new Insanity(); long timeMin = 0; long timeMax = 0; long timeTot = 0; int returnCode = 0; for (int test = 0; test < numTests; ++test) { try { /** CONNECT TEST */ System.out.println("Test #" + (test + 1) + ", " + "connect " + host + ":" + port); if (transport.isOpen() == false) { try { transport.open(); } catch (TTransportException ttx) { ttx.printStackTrace(); System.out.println("Connect failed: " + ttx.getMessage()); System.exit(ERR_UNKNOWN); } } long start = System.nanoTime(); /** VOID TEST */ try { System.out.print("testVoid()"); testClient.testVoid(); System.out.print(" = void\n"); } catch (TApplicationException tax) { tax.printStackTrace(); returnCode |= ERR_BASETYPES; } /** STRING TEST */ System.out.print("testString(\"Test\")"); String s = testClient.testString("Test"); System.out.print(" = \"" + s + "\"\n"); if (!s.equals("Test")) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** UUID TEST */ System.out.println("testUuid(\"00112233-4455-6677-8899-aabbccddeeff\")"); UUID uuid = testClient.testUuid(UUID.fromString("00112233-4455-6677-8899-aabbccddeeff")); System.out.print(" = \"" + uuid + "\"\n"); if (!uuid.equals(UUID.fromString("00112233-4455-6677-8899-aabbccddeeff"))) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** Multiplexed test */ if (protocol_type.startsWith("multi")) { SecondService.Client secondClient = new SecondService.Client(tProtocol2); System.out.print("secondtestString(\"Test2\")"); s = secondClient.secondtestString("Test2"); System.out.print(" = \"" + s + "\"\n"); if (!s.equals("testString(\"Test2\")")) { returnCode |= ERR_PROTOCOLS; System.out.println("*** FAILURE ***\n"); } } /** BYTE TEST */ System.out.print("testByte(1)"); byte i8 = testClient.testByte((byte) 1); System.out.print(" = " + i8 + "\n"); if (i8 != 1) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** I32 TEST */ System.out.print("testI32(-1)"); int i32 = testClient.testI32(-1); System.out.print(" = " + i32 + "\n"); if (i32 != -1) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** I64 TEST */ System.out.print("testI64(-34359738368)"); long i64 = testClient.testI64(-34359738368L); System.out.print(" = " + i64 + "\n"); if (i64 != -34359738368L) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** DOUBLE TEST */ System.out.print("testDouble(-5.325098235)"); double dub = testClient.testDouble(-5.325098235); System.out.print(" = " + dub + "\n"); if (Math.abs(dub - (-5.325098235)) > 0.001) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** BINARY TEST */ try { System.out.print("testBinary(-128...127) = "); byte[] data = getBytesData(); ByteBuffer bin = testClient.testBinary(ByteBuffer.wrap(data)); bin.mark(); byte[] bytes = new byte[bin.limit() - bin.position()]; bin.get(bytes); bin.reset(); System.out.print("{"); boolean first = true; for (int i = 0; i < bytes.length; ++i) { if (first) first = false; else System.out.print(", "); System.out.print(bytes[i]); } System.out.println("}"); if (!ByteBuffer.wrap(data).equals(bin)) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } } catch (Exception ex) { returnCode |= ERR_BASETYPES; System.out.println("\n*** FAILURE ***\n"); ex.printStackTrace(System.out); } /** STRUCT TEST */ System.out.print("testStruct({\"Zero\", 1, -3, -5})"); Xtruct out = new Xtruct(); out.string_thing = "Zero"; out.byte_thing = (byte) 1; out.i32_thing = -3; out.i64_thing = -5; Xtruct in = testClient.testStruct(out); System.out.print( " = {" + "\"" + in.string_thing + "\"," + in.byte_thing + ", " + in.i32_thing + ", " + in.i64_thing + "}\n"); if (!in.equals(out)) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } /** NESTED STRUCT TEST */ System.out.print("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); Xtruct2 out2 = new Xtruct2(); out2.byte_thing = (short) 1; out2.struct_thing = out; out2.i32_thing = 5; Xtruct2 in2 = testClient.testNest(out2); in = in2.struct_thing; System.out.print( " = {" + in2.byte_thing + ", {" + "\"" + in.string_thing + "\", " + in.byte_thing + ", " + in.i32_thing + ", " + in.i64_thing + "}, " + in2.i32_thing + "}\n"); if (!in2.equals(out2)) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } /** MAP TEST */ Map mapout = new HashMap(); for (int i = 0; i < 5; ++i) { mapout.put(i, i - 10); } System.out.print("testMap({"); boolean first = true; for (int key : mapout.keySet()) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(key + " => " + mapout.get(key)); } System.out.print("})"); Map mapin = testClient.testMap(mapout); System.out.print(" = {"); first = true; for (int key : mapin.keySet()) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(key + " => " + mapout.get(key)); } System.out.print("}\n"); if (!mapout.equals(mapin)) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); } /** STRING MAP TEST */ try { Map smapout = new HashMap(); smapout.put("a", "2"); smapout.put("b", "blah"); smapout.put("some", "thing"); for (String key : smapout.keySet()) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(key + " => " + smapout.get(key)); } System.out.print("})"); Map smapin = testClient.testStringMap(smapout); System.out.print(" = {"); first = true; for (String key : smapin.keySet()) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(key + " => " + smapout.get(key)); } System.out.print("}\n"); if (!smapout.equals(smapin)) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); } } catch (Exception ex) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); ex.printStackTrace(System.out); } /** SET TEST */ Set setout = new HashSet(); for (int i = -2; i < 3; ++i) { setout.add(i); } System.out.print("testSet({"); first = true; for (int elem : setout) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(elem); } System.out.print("})"); Set setin = testClient.testSet(setout); System.out.print(" = {"); first = true; for (int elem : setin) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(elem); } System.out.print("}\n"); if (!setout.equals(setin)) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); } /** LIST TEST */ List listout = new ArrayList(); for (int i = -2; i < 3; ++i) { listout.add(i); } System.out.print("testList({"); first = true; for (int elem : listout) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(elem); } System.out.print("})"); List listin = testClient.testList(listout); System.out.print(" = {"); first = true; for (int elem : listin) { if (first) { first = false; } else { System.out.print(", "); } System.out.print(elem); } System.out.print("}\n"); if (!listout.equals(listin)) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); } /** ENUM TEST */ System.out.print("testEnum(ONE)"); Numberz ret = testClient.testEnum(Numberz.ONE); System.out.print(" = " + ret + "\n"); if (ret != Numberz.ONE) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } System.out.print("testEnum(TWO)"); ret = testClient.testEnum(Numberz.TWO); System.out.print(" = " + ret + "\n"); if (ret != Numberz.TWO) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } System.out.print("testEnum(THREE)"); ret = testClient.testEnum(Numberz.THREE); System.out.print(" = " + ret + "\n"); if (ret != Numberz.THREE) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } System.out.print("testEnum(FIVE)"); ret = testClient.testEnum(Numberz.FIVE); System.out.print(" = " + ret + "\n"); if (ret != Numberz.FIVE) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } System.out.print("testEnum(EIGHT)"); ret = testClient.testEnum(Numberz.EIGHT); System.out.print(" = " + ret + "\n"); if (ret != Numberz.EIGHT) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } /** TYPEDEF TEST */ System.out.print("testTypedef(309858235082523)"); long uid = testClient.testTypedef(309858235082523L); System.out.print(" = " + uid + "\n"); if (uid != 309858235082523L) { returnCode |= ERR_BASETYPES; System.out.println("*** FAILURE ***\n"); } /** NESTED MAP TEST */ System.out.print("testMapMap(1)"); Map> mm = testClient.testMapMap(1); System.out.print(" = {"); for (int key : mm.keySet()) { System.out.print(key + " => {"); Map m2 = mm.get(key); for (int k2 : m2.keySet()) { System.out.print(k2 + " => " + m2.get(k2) + ", "); } System.out.print("}, "); } System.out.print("}\n"); if (mm.size() != 2 || !mm.containsKey(4) || !mm.containsKey(-4)) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); } else { Map m1 = mm.get(4); Map m2 = mm.get(-4); if (m1.get(1) != 1 || m1.get(2) != 2 || m1.get(3) != 3 || m1.get(4) != 4 || m2.get(-1) != -1 || m2.get(-2) != -2 || m2.get(-3) != -3 || m2.get(-4) != -4) { returnCode |= ERR_CONTAINERS; System.out.println("*** FAILURE ***\n"); } } /** INSANITY TEST */ boolean insanityFailed = true; try { Xtruct hello = new Xtruct(); hello.string_thing = "Hello2"; hello.byte_thing = 2; hello.i32_thing = 2; hello.i64_thing = 2; Xtruct goodbye = new Xtruct(); goodbye.string_thing = "Goodbye4"; goodbye.byte_thing = (byte) 4; goodbye.i32_thing = 4; goodbye.i64_thing = (long) 4; insane.userMap = new HashMap(); insane.userMap.put(Numberz.EIGHT, (long) 8); insane.userMap.put(Numberz.FIVE, (long) 5); insane.xtructs = new ArrayList(); insane.xtructs.add(goodbye); insane.xtructs.add(hello); System.out.print("testInsanity()"); Map> whoa = testClient.testInsanity(insane); System.out.print(" = {"); for (long key : whoa.keySet()) { Map val = whoa.get(key); System.out.print(key + " => {"); for (Numberz k2 : val.keySet()) { Insanity v2 = val.get(k2); System.out.print(k2 + " => {"); Map userMap = v2.userMap; System.out.print("{"); if (userMap != null) { for (Numberz k3 : userMap.keySet()) { System.out.print(k3 + " => " + userMap.get(k3) + ", "); } } System.out.print("}, "); List xtructs = v2.xtructs; System.out.print("{"); if (xtructs != null) { for (Xtruct x : xtructs) { System.out.print( "{" + "\"" + x.string_thing + "\", " + x.byte_thing + ", " + x.i32_thing + ", " + x.i64_thing + "}, "); } } System.out.print("}"); System.out.print("}, "); } System.out.print("}, "); } System.out.print("}\n"); if (whoa.size() == 2 && whoa.containsKey(1L) && whoa.containsKey(2L)) { Map first_map = whoa.get(1L); Map second_map = whoa.get(2L); if (first_map.size() == 2 && first_map.containsKey(Numberz.TWO) && first_map.containsKey(Numberz.THREE) && second_map.size() == 1 && second_map.containsKey(Numberz.SIX) && insane.equals(first_map.get(Numberz.TWO)) && insane.equals(first_map.get(Numberz.THREE))) { Insanity six = second_map.get(Numberz.SIX); // Cannot use "new Insanity().equals(six)" because as of now, struct/container // fields with default requiredness have isset=false for local instances and yet // received empty values from other languages like C++ have isset=true . if (six.getUserMapSize() == 0 && six.getXtructsSize() == 0) { // OK insanityFailed = false; } } } } catch (Exception ex) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); ex.printStackTrace(System.out); insanityFailed = false; } if (insanityFailed) { returnCode |= ERR_STRUCTS; System.out.println("*** FAILURE ***\n"); } /** EXECPTION TEST */ try { System.out.print("testClient.testException(\"Xception\") =>"); testClient.testException("Xception"); System.out.print(" void\n*** FAILURE ***\n"); returnCode |= ERR_EXCEPTIONS; } catch (Xception e) { System.out.printf(" {%d, \"%s\"}\n", e.errorCode, e.message); } try { System.out.print("testClient.testException(\"TException\") =>"); testClient.testException("TException"); System.out.print(" void\n*** FAILURE ***\n"); returnCode |= ERR_EXCEPTIONS; } catch (TException e) { System.out.printf(" {\"%s\"}\n", e.getMessage()); } try { System.out.print("testClient.testException(\"success\") =>"); testClient.testException("success"); System.out.print(" void\n"); } catch (Exception e) { System.out.printf(" exception\n*** FAILURE ***\n"); returnCode |= ERR_EXCEPTIONS; } /** MULTI EXCEPTION TEST */ try { System.out.printf("testClient.testMultiException(\"Xception\", \"test 1\") =>"); testClient.testMultiException("Xception", "test 1"); System.out.print(" result\n*** FAILURE ***\n"); returnCode |= ERR_EXCEPTIONS; } catch (Xception e) { System.out.printf(" {%d, \"%s\"}\n", e.errorCode, e.message); } try { System.out.printf("testClient.testMultiException(\"Xception2\", \"test 2\") =>"); testClient.testMultiException("Xception2", "test 2"); System.out.print(" result\n*** FAILURE ***\n"); returnCode |= ERR_EXCEPTIONS; } catch (Xception2 e) { System.out.printf(" {%d, {\"%s\"}}\n", e.errorCode, e.struct_thing.string_thing); } try { System.out.print("testClient.testMultiException(\"success\", \"test 3\") =>"); Xtruct result; result = testClient.testMultiException("success", "test 3"); System.out.printf(" {{\"%s\"}}\n", result.string_thing); } catch (Exception e) { System.out.printf(" exception\n*** FAILURE ***\n"); returnCode |= ERR_EXCEPTIONS; } /** ONEWAY TEST */ System.out.print("testOneway(3)..."); long startOneway = System.nanoTime(); testClient.testOneway(3); long onewayElapsedMillis = (System.nanoTime() - startOneway) / 1000000; if (onewayElapsedMillis > 200) { System.out.println( "Oneway test took too long to execute failed: took " + onewayElapsedMillis + "ms"); System.out.println( "oneway calls are 'fire and forget' and therefore should not cause blocking."); System.out.println( "Some transports (HTTP) have a required response, and typically this failure"); System.out.println("means the transport response was delayed until after the execution"); System.out.println( "of the RPC. The server should post the transport response immediately and"); System.out.println("before executing the RPC."); System.out.println("*** FAILURE ***"); returnCode |= ERR_BASETYPES; } else { System.out.println("Success - fire and forget only took " + onewayElapsedMillis + "ms"); } long stop = System.nanoTime(); long tot = stop - start; System.out.println("Total time: " + tot / 1000 + "us"); if (timeMin == 0 || tot < timeMin) { timeMin = tot; } if (tot > timeMax) { timeMax = tot; } timeTot += tot; transport.close(); } catch (Exception x) { System.out.printf("*** FAILURE ***\n"); x.printStackTrace(); returnCode |= ERR_UNKNOWN; } } long timeAvg = timeTot / numTests; System.out.println("Min time: " + timeMin / 1000 + "us"); System.out.println("Max time: " + timeMax / 1000 + "us"); System.out.println("Avg time: " + timeAvg / 1000 + "us"); try { String json = (new TSerializer(new TSimpleJSONProtocol.Factory())).toString(insane); System.out.println("\nSample TSimpleJSONProtocol output:\n" + json); } catch (TException x) { System.out.println("*** FAILURE ***"); x.printStackTrace(); returnCode |= ERR_BASETYPES; } System.exit(returnCode); } private static byte[] getBytesData() { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(256); IntStream.range(-128, 128).forEach(byteArrayOutputStream::write); return byteArrayOutputStream.toByteArray(); } } thrift-0.19.0/lib/java/README.md0000644000000000000000000002060614452237057016062 0ustar00rootroot00000000000000Thrift Java Software Library License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Building and installing from source =================================== When using a CMake build from the source distribution on Linux the easiest way to build and install is this simple command line: make all && sudo make install/fast It is important to use the install/fast option to eliminate the automatic rebuild by dependency that causes issues because the build tooling is designed to work with cached files in the user home directory during the build process. Instead this builds the code in the expected local build tree and then uses CMake install code to copy to the target destination. Building Thrift with Gradle without CMake/Autoconf ================================================== The Thrift Java source is not build using the GNU tools, but rather uses the Gradle build system, which tends to be predominant amongst Java developers. Currently we use gradle 8.0 to build the Thrift Java source. The usual way to setup gradle project is to include the gradle-wrapper.jar in the project and then run the gradle wrapper to bootstrap setting up gradle binaries. However to avoid putting binary files into the source tree we have ignored the gradle wrapper files. You are expected to install it manually, as described in the [gradle documentation](https://docs.gradle.org/current/userguide/installation.html), or following this step (which is also done in the travis CI docker images): ```bash export GRADLE_VERSION="8.0.2" # install dependencies apt-get install -y --no-install-recommends openjdk-17-jdk-headless wget unzip # download gradle distribution wget https://services.gradle.org/distributions/gradle-$GRADLE_VERSION-bin.zip -q -O /tmp/gradle-$GRADLE_VERSION-bin.zip # check binary integrity echo "ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7 /tmp/gradle-$GRADLE_VERSION-bin.zip" | sha256sum -c - # unzip and install unzip -d /tmp /tmp/gradle-$GRADLE_VERSION-bin.zip mv /tmp/gradle-$GRADLE_VERSION /usr/local/gradle ln -s /usr/local/gradle/bin/gradle /usr/local/bin ``` After the above step, `gradle` binary will be available in `/usr/local/bin/`. You can further choose to locally create the gradle wrapper (even if they are ignored) using: ```bash gradle wrapper --gradle-version $GRADLE_VERSION ``` To compile the Java Thrift libraries, simply do the following: ```bash gradle ``` Yep, that's easy. Look for `libthrift-.jar` in the build/libs directory. The default build will run the unit tests which expect a usable Thrift compiler to exist on the system. You have two choices for that. * Build the Thrift executable from source at the default location in the source tree. The project is configured to look for it there. * Install the published binary distribution to have Thrift executable in a known location and add the path to the ~/.gradle/gradle.properties file using the property name "thrift.compiler". For example this would set the path in a Windows box if Thrift was installed under C:\Thrift thrift.compiler=C:/Thrift/thrift.exe To just build the library without running unit tests you simply do this. ```bash gradle assemble ``` To install the library in the local Maven repository location where other Maven or Gradle builds can reference it simply do this. ```bash gradle publishToMavenLocal ``` The library will be placed in your home directory under .m2/repository To include Thrift in your applications simply add libthrift.jar to your classpath, or install if in your default system classpath of choice. Build Thrift behind a proxy: ```bash gradle -Dhttp.proxyHost=myproxyhost -Dhttp.proxyPort=8080 -Dhttp.proxyUser=thriftuser -Dhttp.proxyPassword=topsecret ``` or via ```bash ./configure --with-java GRADLE_OPTS='-Dhttp.proxyHost=myproxyhost -Dhttp.proxyPort=8080 -Dhttp.proxyUser=thriftuser -Dhttp.proxyPassword=topsecret' ``` Unit Test HTML Reports ====================== The build will automatically generate an HTML Unit Test report. This can be found under build/reports/tests/test/index.html. It can be viewed with a browser directly from that location. Clover Code Coverage for Thrift =============================== The build will optionally generate Clover Code coverage if the Gradle property `cloverEnabled=true` is set in ~/.gradle/gradle.properties or on the command line via `-PcloverEnabled=true`. The generated report can be found under the location build/reports/clover/html/index.html. It can be viewed with a browser directly from that location. Additionally, a PDF report is generated and is found under the location build/reports/clover/clover.pdf. The following command will build, unit test, and generate Clover reports: ```bash gradle -PcloverEnabled=true ``` Publishing Maven Artifacts to Maven Central =========================================== The Automake build generates a Makefile that provides the correct parameters when you run the build provided the configure.ac has been set with the correct version number. The Gradle build will receive the correct value for the build. The same applies to the CMake build, the value from the configure.ac file will be used if you execute these commands: ```bash make maven-publish -- This is for an Automake Linux build make MavenPublish -- This is for a CMake generated build ``` The `publish` task in Gradle is preconfigured with all necessary details to sign and publish the artifacts from the build to the Apache Maven staging repository. The task requires the following externally provided properties to authenticate to the repository and sign the artifacts. The preferred approach is to create or edit the ~/.gradle/gradle.properties file and add the following properties to it. ```properties # Signing key information for artifacts PGP signature (values are examples) signing.keyId=24875D73 signing.password=secret signing.secretKeyRingFile=/Users/me/.gnupg/secring.gpg # Apache Maven staging repository user credentials mavenUser=meMyselfAndI mavenPassword=MySuperAwesomeSecretPassword ``` NOTE: If you do not have a secring.gpg file, see the [gradle signing docs](https://docs.gradle.org/current/userguide/signing_plugin.html) for instructions on how to generate it. It is also possible to manually publish using the Gradle build directly. With the key information and credentials in place the following will generate if needed the build artifacts and proceed to publish the results. ```bash gradle -Prelease=true publish ``` It is also possible to override the target repository for the Maven Publication by using a Gradle property, for example you can publish signed JAR files to your company internal server if you add this to the command line or in the ~/.gradle/gradle.properties file. The URL below assumes a Nexus Repository. ```properties maven-repository-url=https://my.company.com/service/local/staging/deploy/maven2 ``` Or the same on the command line: ```bash gradle -Pmaven-repository-url=https://my.company.com/service/local/staging/deploy/maven2 -Prelease=true -Pthrift.version=0.11.0 publish ``` Dependencies ============ Gradle http://gradle.org/ # Breaking Changes ## 0.13.0 * The signature of the 'process' method in TAsyncProcessor and TProcessor has changed to remove the boolean return type and instead rely on Exceptions. * Per THRIFT-4805, TSaslTransportException has been removed. The same condition is now covered by TTansportException, where `TTransportException.getType() == END_OF_FILE`. ## 0.12.0 The access modifier of the AutoExpandingBuffer class has been changed from public to default (package) and will no longer be accessible by third-party libraries. The access modifier of the ShortStack class has been changed from public to default (package) and will no longer be accessible by third-party libraries. thrift-0.19.0/lib/java/code_quality_tools/0000777000000000000000000000000014303740367020503 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/code_quality_tools/findbugs-filter.xml0000644000000000000000000000401714303740367024307 0ustar00rootroot00000000000000 thrift-0.19.0/lib/java/coding_standards.md0000644000000000000000000000010314303740367020417 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/java/gradle/0000777000000000000000000000000014452237057016041 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/gradle/functionalTests.gradle0000644000000000000000000001526514303740367022411 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // ---------------------------------------------------------------------------- // Functional testing harness creation. This helps run the cross-check tests. // The Makefile precross target invokes the shadowJar task and the tests.json // code is changed to call runclient or runserver as needed. // ---------------------------------------------------------------------------- // Cross Test sources are separated in their own sourceSet // sourceSets { crossTest { java { } } } // see https://docs.gradle.org/current/userguide/java_library_plugin.html // 1. defines cross test implementation that includes all test implementation, which in turn // contains all implementation dependencies // 2. defines cross test runtime that further includes test runtime only dependencies // 3. the cross test implementation will need to depends on main and test output // 4. shadow jar will package both main and test source set, along with cross test runtime dependencies configurations { crossTestImplementation { description "implementation for cross test" extendsFrom testImplementation } crossTestRuntime { description "runtime dependencies for cross test" extendsFrom crossTestImplementation, testRuntimeOnly } } dependencies { crossTestImplementation "org.apache.tomcat.embed:tomcat-embed-core:${tomcatEmbedVersion}" crossTestImplementation sourceSets.main.output crossTestImplementation sourceSets.test.output } // I am using shadow plugin to make a self contained functional test Uber JAR that // eliminates startup problems with wrapping the cross-check harness in Gradle. // This is used by the runner scripts as the single classpath entry which // allows the process to be as lightweight as it can. shadowJar { description = 'Assemble a test JAR file for cross-check execution' // make sure the runners are created when this runs dependsOn 'generateRunnerScriptForClient', 'generateRunnerScriptForServer', 'generateRunnerScriptForNonblockingServer', 'generateRunnerScriptForTServletServer' archiveBaseName.set('functionalTest') destinationDirectory = file("$buildDir/functionalTestJar") // We do not need a version number for this internal jar archiveVersion.set(null) // Bundle the complete set of unit test classes including generated code // and the runtime dependencies in one JAR to expedite execution. // see https://imperceptiblethoughts.com/shadow/custom-tasks/ from sourceSets.test.output from sourceSets.crossTest.output configurations = [project.configurations.crossTestRuntime] } // Common script runner configuration elements def scriptExt = '' def execExt = '' def scriptHead = '#!/bin/bash' def args = '$*' // Although this is marked internal it is an available and stable interface if (org.gradle.internal.os.OperatingSystem.current().windows) { scriptExt = '.bat' execExt = '.exe' scriptHead = '@echo off' args = '%*' } // The Java executable to use with the runner scripts def javaExe = file("${System.getProperty('java.home')}/bin/java${execExt}").canonicalPath // The common Uber jar path def jarPath = shadowJar.archiveFile.get().asFile.canonicalPath def trustStore = file("${projectDir}/src/crossTest/resources/.truststore").canonicalPath def keyStore = file("${projectDir}/src/crossTest/resources/.keystore").canonicalPath task generateRunnerScriptForClient(group: 'Build') { description = 'Generate a runner script for cross-check tests with TestClient' def clientFile = file("$buildDir/runclient${scriptExt}") def runClientText = """\ ${scriptHead} "${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.trustStore=$trustStore" -Djavax.net.ssl.trustStorePassword=thrift org.apache.thrift.test.TestClient $args """ inputs.property 'runClientText', runClientText outputs.file clientFile doLast { clientFile.parentFile.mkdirs() clientFile.text = runClientText clientFile.setExecutable(true, false) } } task generateRunnerScriptForServer(group: 'Build') { description = 'Generate a runner script for cross-check tests with TestServer' def serverFile = file("$buildDir/runserver${scriptExt}") def runServerText = """\ ${scriptHead} "${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.keyStore=$keyStore" -Djavax.net.ssl.keyStorePassword=thrift org.apache.thrift.test.TestServer $args """ inputs.property 'runServerText', runServerText outputs.file serverFile doLast { serverFile.parentFile.mkdirs() serverFile.text = runServerText serverFile.setExecutable(true, false) } } task generateRunnerScriptForNonblockingServer(group: 'Build') { description = 'Generate a runner script for cross-check tests with TestNonblockingServer' def serverFile = file("$buildDir/runnonblockingserver${scriptExt}") def runServerText = """\ ${scriptHead} "${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.keyStore=$keyStore" -Djavax.net.ssl.keyStorePassword=thrift org.apache.thrift.test.TestNonblockingServer $args """ inputs.property 'runServerText', runServerText outputs.file serverFile doLast { serverFile.parentFile.mkdirs() serverFile.text = runServerText serverFile.setExecutable(true, false) } } task generateRunnerScriptForTServletServer(group: 'Build') { description = 'Generate a runner script for cross-check tests with TestTServletServer' def serverFile = file("$buildDir/runservletserver${scriptExt}") def runServerText = """\ ${scriptHead} "${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.keyStore=$keyStore" -Djavax.net.ssl.keyStorePassword=thrift org.apache.thrift.test.TestTServletServer $args """ inputs.property 'runServerText', runServerText outputs.file serverFile doLast { serverFile.parentFile.mkdirs() serverFile.text = runServerText serverFile.setExecutable(true, false) } } thrift-0.19.0/lib/java/gradle/unitTests.gradle0000644000000000000000000000634414452237057021226 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // Bundle the test classes in a JAR for other Ant based builds task testJar(type: Jar, group: 'Build') { description = 'Assembles a jar archive containing the test classes.' project.test.dependsOn it archiveClassifier = 'test' from sourceSets.test.output } // ---------------------------------------------------------------------------- // Unit test tasks and configurations // Help the up to date algorithm to make these tests done ext.markTaskDone = { task -> def buildFile = file("$buildDir/${task.name}.flag") task.inputs.files task.classpath task.outputs.file buildFile task.doLast { buildFile.text = 'Passed!' } } task deprecatedEqualityTest(type: JavaExec, group: 'Verification') { description = 'Run the non-JUnit test suite ' classpath = sourceSets.test.runtimeClasspath mainClass.set('org.apache.thrift.test.EqualityTest') markTaskDone(it) } task deprecatedJavaBeansTest(type: JavaExec, group: 'Verification') { description = 'Run the non-JUnit test suite ' classpath = sourceSets.test.runtimeClasspath mainClass.set('org.apache.thrift.test.JavaBeansTest') markTaskDone(it) } // Main Unit Test task configuration test { description="Run the full test suite" dependsOn deprecatedEqualityTest, deprecatedJavaBeansTest // Allow repeating tests even after successful execution if (project.hasProperty('rerunTests')) { outputs.upToDateWhen { false } } include '**/Test*.class' exclude '**/Test*\$*.class' // https://junit.org/junit5/docs/current/user-guide/#running-tests-build-gradle useJUnitPlatform() { // https://junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution systemProperty("junit.jupiter.execution.parallel.enabled", "true") systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") systemProperty("junit.jupiter.execution.parallel.mode.classes.default", "concurrent") } maxHeapSize = '512m' systemProperties = [ 'build.test': "${compileTestJava.destinationDir}", 'test.port': "${testPort}", 'javax.net.ssl.trustStore': "${projectDir}/src/crossTest/resources/.truststore", 'javax.net.ssl.trustStorePassword': 'thrift', 'javax.net.ssl.keyStore': "${projectDir}/src/crossTest/resources/.keystore", 'javax.net.ssl.keyStorePassword': 'thrift' ] } thrift-0.19.0/lib/java/gradle/wrapper/0000755000000000000000000000000014373235760017516 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/gradle/wrapper/gradle-wrapper.jar0000644000000000000000000016652414373235760023146 0ustar00rootroot00000000000000PK A META-INF/PK Am±>=@?META-INF/MANIFEST.MFóMÌËLK-.Ñ K-*ÎÌϳR0Ô3àåòÌ-ÈIÍMÍ+I, ê†d–ä¤Z)¸%¦ä¤*„%¤ñrñrPK Aorg/PK A org/gradle/PK Aorg/gradle/wrapper/PK APrº™« -*org/gradle/wrapper/GradleWrapperMain.classXxÇþ´§Õ¢r¢‰"ŸE;‰"L1XÂ! $| @Dà‹´’înÅÞ%Nât§’FЧ'q Nœ“°ÄNwzïÕ齓â8ùg÷tº² }ù>4·óæÍ+ÿ{óÞ >ñÐekÅ"ÏT±ÏR¡âÙrxŽž«ày*J$¹ÏWp—‚øñB?^$ /Vñ¼Ôs~¼LÁËUTIÆ*¼B.¾RÅ«p^Á«UÌqɯQñZ¼Nн[÷Èáõ*îżÑ7ùñfoQðVux›ŠZ¼]Á;T,•îÅ;ÜçÇ»T„ðnïÁýòë½rxŸÞïÇü¸ ¢ÈùU|ªø0R*F1¦â"R0®à#*6á’Š;pÙ+rÃGýxXÁ#òócrñã*>O–áSø´‚ÏHÎG¥H’?‹ÏÉáó*¾€/ªø¾¬à+*vâ«swìki ·éínßw¤£kWû‘®==]»áãú)½1ªÇ‡»m+j˜Ùjƶ·÷ëѤ!,ØÞÖÞÓÒnoËÈ©N³ìíílïÉPæP 6•lŽÄ#ö¢Pý~_«9@máHÜØŒ3¬ýXÔFšýzt¿nEä D*ämpn˜rg2ⵡâ$¿‚¯ ¬ MÞS·NkÓõb©v›I«ßpó|NÁA[-2Eå­š‰Zx•ÊÇ´0Íœ×-N7J3s¦àD²ç^ž²ìÖå}Q³Œ‘¨.oV‚ü›BÓŠµ—ÌåÓÛJT*&©Nåu]§Ó6‹6«G›é> ê&ŒO0¤VÄ>Û˜ÏÓRÓâ#€3øÛPSX—Âú6¤póm÷afx›úVŒâ–+TÑhNaó=˜'‰[}—°¥¯¨¡{ [Gñ¤+„ªå"¶ \§ÍjEûGrSh#nÅv"×J´¤mË"в ŸR5h!Rˆ‰q+mÜÁdè nÒö†¯‚û’8ÅY5wžfŠ ®kü:˯…L8wõ©ü«‚oŸ‚£TÁÁN…JUùM;ÜçdPÛ(KaûݘåX,';Rèf¡SÂX”tƒj1ŸAž„³ÖÉDWiø¬QåC7­fSZMù8vRzUâ¶üèD³Ä•§Å <ÃáºóPK AÛÆ.q/3#gradle-wrapper-classpath.properties+(ÊÏJM.)¶M/JLÉIÕMÎÉÔ2Ë‹ R‹t‹3‹RS¸ŠJóJ2sSm¹PK A)gradle-wrapper-parameter-names.propertiesPK Aorg/gradle/cli/PK AÕÜ?®<S1org/gradle/cli/AbstractCommandLineConverter.class•T]oA= ‹ëÚ"¶µ~C?”R*O¦Òh4!­ÒÄÇaY×m`— C£Âߢ/4ÑÄà2ÞP–´ôaçÞ9{ï¹sæÞÝ?þPFÙ@;:v D°c@ÇóÀ{xY9y†xÕõ\Ycˆfs§ Ú‘ß±V®g{m[´x»KHªá[¼{Ê…ì' &?»†bÃNɼӵKV×-ÕÛ)¸%ü^{€ìÈ÷Îm!mQaظÌõµÿŸ¯|¢j«U©›n†Ãl㌟óR—{Né…¬•ì¤}f[²’ C¤… ‡´¬-¢ k’ôÚ–Á=,È÷¹Ø‚ak^ÀÌÁß«Š^tÊê Ö”Âõ¥-JŒ×_,»/]ßèØc¸ÕtË¡ +;Xš¨rŠîCµuVQ CWˆ uÁhúCaÙoÜ ™«ú¶Ô1aà6Cúºë2Qľ‰LÜÃK†Â &„!9¯‰a{ Qá23Quá {¶'§M¡†Ð~rÕÝìõ3|i153 ¯mnžDevf¨èÎ߆J…£–š~-C…Hý;"d©9´š´«“edcù °äDq‡Ö¸SX¡Õ`I²w/!)²Œ:·FyÝ7²ÙÍ_ˆ|¼@ô8_AË #ÄöFˆŸVX! ÊK`öªR~œ;©xëô†)ï>=ŠNâRnpŽ´âØœœcÿhÿ˜âŸ¯òÏ”ô4=c/ƒ-e·ÿPK A׃µ³Xì ;org/gradle/cli/AbstractPropertiesCommandLineConverter.class­V[WUþN2ÉÀ0å H¡°Ô„¤ÄKKµIQJ©†‹¦‚Ø;L†0fâÌáOøîZ¾ûZ_¢t­ºúìÿñA—·}N.iÊ2Y9çì}öÞç;ûvòëßOð6¾Q0Œ÷e| `ó|¸£`w,â'?ä«û ÒøHÁÇÈô` Ë=˜Å V»ð‰>íB¶ƒxÀ‰Ïø°&cë.cCÆ Á”i™Þƒ?]cì¼ÁЗ1-c¹¼·i8´Í"qB[׊kšcrºÆ”¼mÓe¸™±B¢àhù¢‘Ћfb~ÓõM÷V»d8ži¸ öÞžfå¹ÙÛÚ'¦á$ F]èp¥ä™¶Å0‰fv´}-QÔ¬B"ë9¦U ёѻ†§™E#Ï0ÖfÏÕ³f±[·­-³PvòTä4ØÐV5Ç%\ÜÁ’X3L¾Xž¤íÚQgIW‘‘´¬W]Àp§0™?¡•¬:£ì™ÅÄ’VJFOѹ’MA`i Ò®q¸¦ËÆâAÉ1\W@ µó¦\ì¶AÜŠ€A)5"É“ã4‚¡æä8,ÕäF³hªJ+gŽ ^Èzš¾KÂŽŒ‡añ@7ª e<¢ fÍ‚¥y"¨ß¾´;D='þûš+›;†î%£­,†üW»’J /G¬dí²£÷L¶Xg<Ãm©x# ý§íªx ã*&0.ãKo 'ã+A“|gºŒ<ß¡o©(`[†©b»*ŠØSaÁ¦¼¾­¢„¯ Â«ÂC™û”%M—UÅ4¥Ü¹zÝù%ÜLEu|tššg·1qBuÞ)”÷ Ëk$1Ãø‹ú 5ÖÈÃÖxE;i1g¯÷Yu[së°¨ª¯D:2ÜKZMÍu6ò?Al©†T'¶[ô'\íL’z ½¢o’B‘“EŸ1]^„½Í†.³õ¡&…z6ðK®Z6<ñ¶ÒS+Y‚h~ßu.›VÞ8XÙb·»uš÷ù2©¿iÕî°•t»ežÔd£N§Û¾³áH;¾4A†Á?2/y/• ™jéŸÀ~¤…£43Œ1𺸄ˀ$ñ¾ æ‰Ú<Ég’yWjFK$í§ùj,ð ¾ ÿtþì†D“”­ °¯ ¸'R® kýøÔ$G è}/aŠNäƫ֪ÄjŠ~Œäú¨ýDH›ñæARüôßèô ͹?·‚î ”#ô0,_;‚Êðiqá9|·¤)Ô[Aßl øq"û0àÇú%ÊT‘Âéq¯Ô¶þù9þ„NêËäR7¦È3ä…wÈó„oƒ="\ü× Ó bôÓjŠèkDóÛæ·ÊQ0Þ¾Îá-úé#KuïsÎuâÜQ‘þÄ€ŒÙ¿ác¿cøÚº)Q‚á=áÐ[ýótx’V¿p¢2‹?Ç`á'g[©:¶é«YMᶘçþPK A}­ÎyGK1org/gradle/cli/CommandLineArgumentException.class•‘ÍJ1…Oú3£µ¶Zm+êÂî´UÜV " Âà–îÓi˜FfĘ́¯åªàÂð¡Ä$-U´fq“{rïwOÈûÇë€34K(`Ë„mu çœ žöê‡þ=}¤^DEèõSÅEØ=.å˜T}.Øm˜ÐQ¤•š/ ©â&Ÿ‹…t‚_ªÐ GÌ "î]Ê8¦bl *Ìb&Ò«ç€=¤\Š.³$¡¡¥þrAÐ^âí›2˜(ùdæ[ÃÅ€f‰&Õ—V”ú2S»æÆoë/c§PFŽ ‚Î?^E°û5ÿ.)Ùâ-äõ/˜•1ttuÖÓyNïN»3y±÷+:–¬ÚÔ•;XէƬJëk–â ŒuÍ0¬Êœu£gäõî¶;ÇSä~ÂötÓ¾…ÌÊ0w3§*6¬ÅMÛ]ûPK A³ßâúg)org/gradle/cli/CommandLineConverter.classQMKÃ@}ÓÖÆÔ¯ª'Ï"4 F<6¥ EQ($xߦë²%ÝÈvSúÛ<øüQâ6…L ]XvæÍ¾÷†™Ÿß¯o÷8wÐupJp’L-¸6„~/œ²óS¦„ÿb¸fã”%ìu<å‰ ¼*Dè<.þid¦æÎn$…b&לpW'<(a‘ÑR‰`ÄqàÙKxî…™¾Ðl’r?I¥ÿÆôœOFÙlÆÔ$”jçήwÚøºvRm_Uˆ%J¡¡ïÐÄýªñ°vJQ–ë„?ÉÔê_”äFë%p}»b.·;o¾ºÿ-7Û‰Zä3®ÌfSm¡Õi¶M´l¶g³–ÅÛplÔÀ~Qqk*[9Àa¯‘#ïÉPK ASf Õg&org/gradle/cli/CommandLineOption.classV[wUÝ“¦4™^ˆ´i¡\ä"iBµ´ ­ÜZ.Å^ÐÖŠÓdL¦™0™pïwü¼ø¦¼ð .UYË哾ùü.—¸Ïd:™Ü¤Ë‡œós¾³¿ÛþNæ÷~þÀËø&Œm8'ã|œkE–Zqo é¢Þ‰à.Eð .‹A•±AšŒwÃh/ÝÊ iEHzWœ¯Š…ª8ɉÁC^ܾ&KFA†-A6ó¶næ :¦®¨×ÕTÑÖÔœfJhÓ³9Õ.Zš„Ý•§c¥¥¡æ²©9ÛÒsÙÑü¡¨V¶¸ªåìù[y^ÚäÓ7ÔB*›«÷Æâf$£Ò–î8#!Z /!¬çÒÅeÕæJ‚´Dÿ²–YÌ/êöŠ„¡jÿL+›ÊZjÆÐRiCO›««j.3¥ç´YLjão8£å--­ÚZFB˘žÓíÃbqŸùI[³ÔeCí_73šHafŠ«Ëš5/΄ÃfZ5TKkw³Åtà Ú+:3¼ëÙNUæÇ³-¡»ÒÓë©çkƒê´ÍÙjúê´šw®Ê(ʸ.!¹a‘pV³g×)³)Þ_Cš½Õ{ œ‰¬¨…c.[$ Çk¨Ò¿‘lª¹'è´¡«{âRS|~2ävÆ?á§êæõx+ÉÚbi…¢ÁÈzkNu#£Y¢ j>¯å2ÓZ¡ fYËT¼¡òR­QŽ–ûxu¤Wx8R‹º± Eë1Ã0oøÐïgëmñަ¥ž74ŸŠ¢Ór_q9éë\…WO•w¸–/jÝh¼Šz"#ñÿåÐzÎ,Zií¤.Zª»FkP *Ø$}ÙÂiµ°B+ ¶c‡Œ› na·‚]bèÇïá¶‚÷1£à|(¡³º 2>Rð1>aÑÊ Sz´‰5 ‚‚½xAÁ$>UDœé¼P~Ã.*8…Ó ö•Êï%>Ä‚Ïñ…¸û¥‚¯ðµ‚;ÂôÎg¥¨ÂñÙå+ZšþEkߌõM' gÓ6-‡0 ë:ú ¦NVçÏŸ=!!¤{ŠÝLX`©e2zF»I«Áœ3Uö\É%ÑNµ§e5CC]ñZ]AáºmѸYC¶YÚb×Z.+ÈËØ&%ôÅÇÿëb Ý`¯ð)ð³sÜ4 º"((¼á{±j^×ð<ÿ¸·ñë QÁ*°>\¸ÄòÖ{ø#™åæœóÎü%ýNîíÇ׃\ý&9ŸI<†”x‚ÀùÇhzˆ`âG4?DKyGN®!$azÿZ%ÜÅV a ¿"2“ø Á5(,Þ{ú碑⸠!ŽÛ¹Š¡=èÆVú½£ôé$¥Ij¼Hôa¼Dÿ›„/üi;ÐßaÊ çÒÎ¥ƒ”»xÊšdôÉ8$ó‹¬ð«TŘfŠ+q½Yøúƒ£r²*6÷:^”ð›]Û%׸wG\788ˉ¤H€ir`ÂÎv?/'¨î’š†ì–ª†ØÙãç¨cæGaf„;B'”ˆFÖí|vévÊçrȵ#áx=Œ¶zCÄ8Pc.ÆÎÑ}‚vr cйëü JR̰i1!¤hô¹ÇØìˆ]ÑnŠÉGˆ•S³…†À¯Ö«ÓÁ¢ô0§»ì ƒ.§jÈ5"GO¥ú† ý™ªñ޹nÝæJ0¶·ï.b4Öó-ÂÉÎл˜n=ðŒw³"`´á‚~´r<ña³s>Ìã)C—ÓÕ0Œ9y®mjú®V!:«©|¸Šk‚Ø"%²£ƒ…*ðÕý5&˜@TZ¥[AkI )†áª±Zb²=Níʆr2¦jŠÁ³ å¾sš¶噜É(…B`4JY:TCaôÙeºcªùU•¨°*çœb2ô”vŒTzCɘ‡gKEËÔ·N„ö¶R¯9‡r,m:µïBM}¯V´Î÷{"O.6¸ÿu1á³ ¢‹~è-ôëg~¿hW´ªƒKt/ÐO‘vs´¯£Ù }„+ ï£î=í]h§±YèØ,êÙ¼l$ë Ùã®ÖŠúÉ®“7õ½ Ü4O?Àõ îðgԻ𠞥þïh;_‘¦!ÈöѸwiýÞõP˜¶¾þCEÓžEVÐh`l­l í,…[±¨m'GT&p ÝDA¬nÓÊE‡ÀÂé!iØ/8<~Ù[$›"­ÀáVôì8z€b3%®ø‘+Ž>gÖ*hÅ/V!r'î·ßÂÀeš§Ém3=³:Irƒæ›n w„¿NÄ0ñ¾Š!ñØŠuñ2‹aÚíÂÍI·ôPK A¥D£¢&3org/gradle/cli/CommandLineParser$AfterOptions.class­•mOAÇÿ{-½r-´¨ >W+p€Š"ÆDð!$MFxa²´g9½î™í¡øü.¾D%ÑÄà‡2Î^ÏrÒ’cšìÎÌÎþffwnûó×·fqÛ€ŽQiŒu“4®£h ‰IS°tLë˜aÈT¼z‹jÉ6ÃPÉ“5«&yÕµ­ŠëXO¹lØÕ¥}Ÿ†ÔG8þ]†‘±x÷ñ2CrÉ«<§ +ÛõM[>ã›.YN”¼ wË\:JIËi0dï½ômùäïxB©ËBØrÉå†Mªu0r$f„Žî§¬óuþ~Ó^õ¹ô›F†þ±Ò+þ–[.5k՗ލ-Œo0$¸¬©äÚz<Aè˜eèkÊͨ´èS ÈbÅÑÆVçï…ùg<±â‰?ÕdþÊ`±Smññ¢‘t\cX>ÂÇcg‚>Ðv¦Õ@]7|”- ƪ·-+öCGõÅ@›Ï”ª0‹ ²j¸žE7 7æcékâµðÞ‰W7xØ’Š1§ãf·0Ï0y¬d˜8ÎÙ3Ì¿5èó?U†Ñ¶=ì¾ q~ :5úh˜hþkºmqéóåÕêƒ_ò2w·íC^€2 ô\¦é ¥G@õI]ÐTŸ‘¥‡´G¤i4gL¶Í,~Ab—T ½4ö"A;Ÿ£‹­Ã`È‘m éŽò:CóÙ¤ú÷3q‘æ‚äÓôhbÆoPK AŒ‹Müu <org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classÅVërÛTþޭ䏲Ò:¦I à§I|‰sk›ØiK’^‰Üœr“Õ¨±¥Ž,Ó¾À[”˜2ÐþƒáxöHnb×Nä0áϹìÙ³ûí§=«ýóŸ_~0‡‡2Ncñ K2†°È‘“!aYF—ø‚«ŠÍ ǪP»&CÆuŽ!Üä¸%ã6>’1€u޼Œ(68 wúoŒz|†a,oÙ•LÅV·«zF«™5«VSÍí¼aêwU»®Û9Ò^6LùÂpsÒ_ýu W¼Ý¢—›ÚdÖ¬má”l4jeݾ§–«$‰æ-M­nª¶!öM¡$à2 ­ê-[¿aØu§Ø(7m2(·MS·×ªj½®“Ú¢/ÈxWCiX;PíBNg, –YtTÛ)§âò}›ø”ã3%l1ÄüøTðŸ3,ùzºoî˜Ö³Kfž=ìHÁ9Œ T_1$w°bW5Ýt®?ÕôfœkšŒ5s$]%½˜—€±‰ñúÄ4Cä Y åGºæp|­@EYxÔ.ù†´~H@ÃÝ„]*ÿ[qèçrå‰jëí€;˜;þk§G柮G&ާİÞSEêõQɪ¦éõz|q†×|ïyÊóÕpŒj†Š( mªjÝa8ß ÓË”Ww[E–‚ñ^lqŸá6v¿ëÆÊ(=­»WN#¯#¡rN©YS‰–¥.8ÍÔ~éêrWøûß´ö¿€¹ÿ¿¨KÇ*bÔ; QËÅ"Q¼iD@Ôr0¼M»[´Ò¬$’?!H¦vüö¼CãIqÆæÑÇfð.ɆéŒô1J¶á®¨–’ŒáœoZý }4«{JÉÛEßFâGž£?õ3x/ÊJ#Òï˜õÄ'¾Gtr)IÛp‚ô•g{(EOJ¿âT)˜.>Gdƒ/ö-¥G¤WZo=sPß#—`K3‹Q–Ã[FŠ]FŽ]¥¶pÕ…¾àÚ‡®b“Y¬¦h@˜~R ¤Èæ(®!ijJ3n¿‘ã8B§# g›¡HW¢™»Ü±îú…a6ç:Nx*ûŽ9µÀg\Çó.{bµ€ î×¹èÚ¸„÷i^Eˆ¾`– Nó¸$úä,’ÔÏS‘DŸ¼Ñgq¢ŸÎâc)€/hþR’ÿPK A´*«ZMïForg/gradle/cli/CommandLineParser$CaseInsensitiveStringComparator.class¥S]OA=wû±P·RˇŠ"ˆUhAx1¦„¨MLšÔ¤„÷¡êàv—Ìn‰ÅÿÀ‹/˜ø`|öñãÎîƒEkâCçÎÜ9÷Ü{Ng?ÿðÀ&6 °Q)`Ì,9Ü5Ë=K&½l£fcÅÆ*!¿¥|m2ËÕ]B¶t%a¢¥|ù|Ðß“zGìyœ)·‚Žðv…Væœ&³Ñ+æ"”M?”~¨"u$Û‘V~¯ô…Q  NÓ÷¥nx" %œ©6mÜÁ#¥nÔóÖ›uBå_Єñ¶êù"ñ[šf)ÏýåØÖ°àm¦*´ƒîȧÊH›j·fŠpÉÁ\ëp ¥ß©LbÊûúèÿÙsì‰ ÂÔEŠ‹£Ý"L¦ïd'höü@KÓŸ0}Á›1/dü MXEÏnØü…qsYXÆ'>9|r9Ç\í=¬w¼±Pä5o’ô—yï$L Ì‘Œ…i±ft–cyeõ™í¹·ÈÍ›}ö˜³™˜©lôy:E¾Á¡1k-©LYÍn3q§2®òÎâ\Ãuæ™M&:åâÒcî#íÿ€ï2‹µ•OÈ­òïù㿈(&íJ`æR’‡­ÔºØ™p6k·0Ï÷,ÄøÛXŒã\‰ç·Øî*w™ÅM/ýPK A|ìRÎÐ&=org/gradle/cli/CommandLineParser$KnownOptionParserState.classÍXéwUÿ½6ͤÓK‘*EqDè’t‚;VkE¬´E­+. ɤ3ufÒ‚ŠHQpCqPð![ÿ>žäu¿\|ÂÿŸIø\@-V< á°À¥gØZ§YÍ“ˆæ€5ͨ-4Τ¦j§×ª¨ 窬ÓÕm͵løÅ Z n­ÍïÔpi S¬5ê¿—˜$뻦 —b^¡)ÄÌSº™tçÐd%f³ùâsT‹CPÅž`Åg^íá •€ôt ¤µÒÎH‘@Ú'ÙØ„N‚rŒ"#ÁŸ^häÛÁN°oGQ7AUß‘çt$‹ åYFRkº|²ôžÃyÞaCè@Æçg‚²°pPÆÉëèn'»Iì<:\(ð=õÄšÆpÑÁÿòÙ,§œÊá›Á«ía…µîà¿Ò±<çÔV²â8æŠoßSTÀ=âGŒˆŸ°KüŒQñ ½’~Ãqñ;~àWqÂóW”|²‹ò¶›â\Šãä¹ÊTÎÏÛ°kqS Žä'×Í'Q.á–¿QsŠw8¿Th·áÚDL)Ù GcMóCG!O Ø+žm>V6ådÜŒ¾ hd¬ ŠFÆí^Ñð©wŒ¬÷øÞ‰&Ï aÄà ‘îWÐ~qˆÿªpÐN߽̾2BIî þ7ÄÁ³!ù?PK A$ľ¢¥ô<org/gradle/cli/CommandLineParser$MissingOptionArgState.class•mOÓPÇÿwÝÖ*ˆLDÙ² ‘!¨ ·'š`0ÁWÖÌšîo;¢ñoôÓøB…Ä~?”ñܶÌKË’îœÛs~ç±íŸ¿¿~˜Å’Žr:’È'I*(uZG 7ÕÙŒ’Šq”ã˜eМ-ÏrD·†_øòK.]S®zÜ3Œ§B˜²js×5]†¹š#ņäuÛ,nÚV±ê4›\Ôk–0¿É#%Šr×–wŸ¡’í[cˆU:å3¤ WZÍ S¾â6œ®9›Ü^ãÒRzxóÞZ”îÈsËu-Ñ˲VµÐ;‹®žTJºÉ?n˜¤I/¸GQ²µw|›m.ÅUO’ÛRn!ÊeCåwä&à# Ö» º@ûë~Ê+ŽØ•:0ßÝrïæ`€´#:L‰:՞ͭÅ1Ç𦯉÷ö)û[ùPR—2Ãäq\ôU§%7ÍÇ–Ú’Ñ#63ª†V—Ûtœ201,¸ˆKî`<ŽE†ùþ–ˆaú$ýe˜=y&z·ƒaêà °ÜýÒýioÙ¦ SÊžx[t¿­¦)<†L/gdè핤÷=Ij$iˆ¨ ÑÉ0iOH‹Ð*ÏöÉ~"ºCj„ÌAæQòÜÂ{Iœ¡³ÑÀgI‚/),£ß9Œ…ÐÅªå »ˆ}kó4º¶ÝÁÑÚ çqÁçЖ„œgŸ2À`þ¢»(LïBû~÷ÉÇeÃ6n0Ä)I')BòeŒ‡à{a‚I¦㇡Ÿ;rL¶¡ÉvŽ\ Q_Q”ãëÿíÓ•;û‚ûêãŒÀ0À¥AS¸B’e4hØØÎ¡dšv6lÒo¼’®ã†_єš Äh8%1õ+aêûUÂÒ' øPK ATK>ªÄ=org/gradle/cli/CommandLineParser$OptionAwareParserState.class­UÛnÓ@=›¤qâ¸$”6\Ê%¤)MÝKÚ@)½p)E¡ E*oÇÓĮօOá xá$ ˆJ|…˜MÝ’*A./Þ™³çŒgf퟿¾ÿPĽ8È©Ð0*w×TzŒ©Èc\…Ž “*L+(¨ˆcVAQÁu†„á4›Ü®•,ÛdÈ–Q/Ô¯5̂Ѱ O¹pÍÚêÌCÔ{i¹¹™è\û èe˶¼; óÁð`ùñ CdÕ©Q²IéØh5«¦xÆ« ò ”ƒ7*\XÒö™.Cúɶg9öʾZÙãŵuÛ6Åjƒ»®I¸…À,s½™è]SMþ¶j’%¼} ÃP¾ôŠ¿æ…·ë…²',»¾4þœ!ÌE]&ܤ–8ö†c$Ž${¿]pÆGÓì§±õ˜oûRËNKæš%t×éi©¨!‰”†Ó˜ÓÐSnbXÁ¼†[XP°¨a Ë s™¬¼ðL±f ×+·ª~˜a°—[ªÝf˜:ç~½¨Z§)9höæOØS†É©­‚» cÁsž›mÏqÌrºœ |ê¯Õ¼ñ¯ðFËüËdUº©ºÔ©áÜ0L×ÍÍÍÐ-=ƽ”»õ_îïqk³Þ¥vr®l0.’¡Ï¥FÒå|©”œxò„¡!òJ„ÓšÒ'vÁtö!}ráOþYÐYг,T6‚$Ëaˆ|iŠÑZÏíÔç ûÌ‹dKTTŸø‚ȇC¾(ÅÁò<ÑCž(.âÅ.#ãóì ¯*êŸ&ª>ZÙ7Dß!½eSZ2B™ÇÞ#¹‡ø¦oªÛo+5UÉÀ¦cÓºÅCÝ¢¯{•ö B£*^ÙvÒ#8G«Ni$èy6¢˜Ž+ùÿÑ1Eˆ8­3$r£]‹ØoPK A˜%àÌ»ª7org/gradle/cli/CommandLineParser$OptionComparator.class•TmOÓP~îÖÑQ:¯ ¾€ Ý ƒ2@Š.Ñ,YÀd†Äe4³¤kIÛ†?„/~#‰á³ÿƨ_ç¶ N6).]ÏË}Îsî=çô~ýõù €E”%d0#¡Ÿ¿ú0+bN‚UÂJ"E,IHs;'"V8|UÄSk"Öz6LÛô7’eA(;íªi;­æ¾á¾Ñ÷-ò Vºníé®ÉíÈ)øïL!»{䛎]všGº«ûŽË WlÛpË–îy!–ªŽÛP®~`jÝ2UÂ6uû€§y­»žáN_åÐÄz`Q¢W…kÂH-¡TˆÓ ôÃT|À%|‘ÎÚ4yÔ`õP?ÖUK·jÍwM»¡…kÉÚw÷º¯uz”Š-ÇÖ¤¤ñž$Þ/0LßÍÐ[3¶î·xѪÿÚMË7-õO¥7â ±IÔRÍi¹uã¥É;?Ú‘~žSËÈb@Æž‰ ™Z½a×ÃB¶ÏÏh÷Οñ\ƶið®ö‚a+6eY÷ŒŠí¶gúæ±Ñ™{"!c /&ãªÆqã ¥ÿý¿vŽa¸[ëhŠãÇ‚Z×0ü0 }‹¥m j†¯]{–…a¤=¿eÑžBº$Í>•½Pí¶Þ}à4¥s2¯|=ѧÕéQ*t±e躣KŠ.@ >rd ’¥’d$S3gH|$%!z÷p'û†aÒå€Ü!Éx‹¢àD–"¹2{Šä9„·ì ©Oè¹€¸Sìp­ çHs»wnL8…tr™­I"þŽ!öyö3Ⱥ2GY¹v÷‚¬à>i<2‡˜ Ø<l’4!»M»{ín•Vˆ™™Ù ôé ùäš#fÂdYþä"’5’‰¨>¬{}FCÀåNS˜Æ#ZOâq€Ï£H·INQÍ2(RÔ8éô˦ÉSÄ<Ùi’Ëÿ PK AäfC˜§£8org/gradle/cli/CommandLineParser$OptionParserState.class•’ßJAÆ¿³Y³º¦ÿ4Õ¶Ö¨£×JoJ¤P¥… …H.¼›$Ã:²™•Ù‰ø }¯/ú}¨Ò3›€ˆ…4»ß™³ßùΜýýçá€#ÔB°ÂÇF€ÍUBñXie? õ½Áo¦}IXl)-O‡ƒ®4碛pf¹•öDÒF¹ó8éÛK•–ή­Jõa2iÚVXþTú®µ4ÍDd™dËÇVjâ(6¢ŸÈ¨—¨¨™B÷]ŸQ]í¤AXH5‡ÆžÊ[ûÅĶóOúÖ÷&£ŸBÃT3k8ÚNê­+q#¢Dè8j[£tܘš¸KûMdT¾Ì‹¼W^'ÒÊÛ„Ýúdð‡†[ƒw{H¨ý›»´Ó¡éɯÊm¤òÌsàÆ+aÅ;„£é÷@(?^ÑY÷JöxÂ÷Ó\a{ò(„ê$“_åÿׇ{ŠðÜL |ŠX‰ufÿÞfs'é'æ8. ñðygXÊu+¹®âe®—/;çÚþ‰ÕÃéßðÊÈ0‚çÑ:^çeorÿ[nÎø}‡y?Ä"k™õ•³—gÿPK A¢Æ÷E«¶3org/gradle/cli/CommandLineParser$OptionString.class•TÿNAþözåÊq”ZDQ‹´GËQÄŸ kLŒ&(ÿ[®—rx½kî£âø/$‰&>€ï¤qv[l“B“ÎîÌÎ|óÍÌîýúóý'€9<éE?LÄ´Ž4ŠB-¥0£ã, ³:4…( 1—Âmá;¯á®†{ Ö²ËÛü#·<î׬µ8týÚCOЈÝÀ§Í¢ë»ñÃT¾Ý¯ÝRXgP+AÕaXv}ge§¾é„oø¦çˆLͽuºBoÕxËŒU™° Cê ßwŠǣȡSk9kV-äUϱlϵ*A½ÎýªHñš‡‘æNÆSéš?s£†Ç?¯ð:幘/t*´-æö‡W¼!éh¸ÏŠƒæ±† /ÏTww~eÙåÓ¬e!ærg‰cèã¶íDQ®ä¹ŽÀOE„–;McBÒ»…ÛÉ-Ü!¹%Œá.ÕÌ"‡{ä©äN'Möë¬zz‹ÆÇY%¼B65[ümŽ~çèkÿE“T‡BZÆ“q‘5²<”]/h¦¸äŸÀ}LѾ‚>‡‡‘ÆM²c”ïGÃäMHxº¦) ˆ±ïPK A`M~U¸2org/gradle/cli/CommandLineParser$ParserState.class•SßoÒPþN) s€ÛÔ97Õ½Œ&MLÈf‚ÙÃÞ.а.åÖÜvFÿ'_|ÑÄÿÿ(ã¹-›Ý Aš´çG¿óïœÛþþóó€´mdQ³‘C-Ç6êxbaÇBƒ{áI/zIÈ4šÇ³Œ\ÂjÏ“îáùdàªbàs¦Ò †Â?ÊÓñ4iF§^H(¼*tU?'‹ï¤tU×aèòËv/Pcg¬ÄÈw¡ï9Ý`2r¤;$uõTy‡Pšˆ/—#}Œ¼@Ö½3ñI8¾c§)OŽ;ÍBÞ / ¡ÆZå Ž°È›…&¡œøWtŸÌi2§íâqf¸YC!‡¼ûzÞPÚ•h&ß—ûP2£»e²»gÆv¡nÓ‚$Ù$T@|„*>AŸÑ%¾ W|Å):ËT Ð3€¿â‚Â_qIÅ_q3!ŠžÅ¹ t–¯^= xÎc @椚ÙCäÍ!ð÷:°Z_ eªàYòÊqà>8YM¨ÝHÅEÿF‚Ÿw@³@9\"žÙ!µvÚC”œzÀ¨1‹ø‰vñ«®¥x••&Òƒá€k$}ËŒfÇö!¶uõÁÇÏTsj]Åp9Ð9†+Î1Œø:ó*…4ñ*4fEù!Š´“æ¿Ëœ¦./1YœŸÍ ®‡µ?PK A£=l)&org/gradle/cli/CommandLineParser.classYi`\Å‘þJš™7zz¶eÙ²=`láë–1¶°åS>K6–±‘ÌXz’Fψ™¶8B¸ÂŽŽ``‡‚¹d ÙM¸ÂÈîØÍ²aÙƒ=€ !lÇÇ~ýÞ›ÑÌè‰üPwOwUuUuÕ×ÕO¯{ö€YòT:ñ±jþW5¿×±Ÿhøƒ/>Ññ)þ¨sú3 ÿ§áOùø >סã yøRÃa#ñç|ÁÑ|ìÇ1ÕׄW‹ø%GÇÉÕÄ£c¼xýâS¿5ÕøEžŽ]¢û%_ͪ¡fFúeu‘¿ŒÖ¤PÇt|ÂeŒ&cu”࿱—qª¯8&¨& œ¤äž¬š‰JO‹ï”|7#ñP"t‰™M$(°¹ÓùÎL8?²=ݱ×cq3Ö”&LMÖsÇsO°¶A0ÚeúAQC(çÖöj]¬ÝZ¢-um 3fÏÆ5iŒµfÎ Å≦îmÔkG0ÒJKͶhÌÌš×dcÊu;ƒ13cßM‚üŒ‰ÍÜ0Ý[‚1«×¬«_ݸµ±®aÅÖ5uëÖ­XÛ(¬ê ^¬îN„ÂÕ1³ÝÜU½&˜ V‘ù‚QQ[Ù¥=I£Ò¨‚]¤Ék µG‚‰î-\‘¹ºÀþFÚ«móWEcíÕí±`kجn ‡ªÛV…"¦­ìüE”9:Gw6„v™­Ž»Êú1Ö|ÆyqeÌ41ë×òP<¸-lÒ‰¾¡H(±H[RÊsô,‹¶šJîÔØ½c›[§…«¢-Áðú`,¤~;“žDGˆ’§|…º¶³©¬·Kg–lloi¶‹­5M%ä· ü¤9.bˆI+vµ˜ÉÐÙ"˜[’FUÏóRŠo;ÃRØñ¬`öFNç”â3#­ŒmL=ƒ šŒ4åPõ%$Ðl¢ÓÉuöÎ * cÝLate+ïr"n꣓uUC›—iظ̀èéJ…›Ç]B\ð kÙΰX5¹P°jØìÃ:ÄÉ)Bˆp(^H˜i%ƒ¹…¯n ZÍükn »‰Ý’É_>N¶§¢‚ Ïœ&3A†32g R4ìÑd«Š Z”8?lçyÒO¤®«‹m'áˆf@çØh¬ÕŒ%sÆžUÊuÅÌ6ë’3iÊ­ Å•¾¹ÛÍ¢Ä%Áp77õš‘DLý^a÷E™9ÍšV\ÑEW ™p¼ vX8)â¬ä4iFf(Må¼aú„}îŽà.ÁÔl?ºFò´,ƒN@6ßÍ 7üwåž3ô½á§ÉEš5ÙF¼îŒ†p JÒ-‹†Ãf‹n1íR^¢¾:ít[½­“BÞY‹ñÔ™dïÁ3‰›©R÷­»­M΄A-µVÔvmê‚ϼ.(SžYìn‘Z¦Q_;¥S™©[ZÌx|Úœ™3ÓK†FR^Ñ9»fpÎUœg ‡sPY‘1O‰ð/ ›}›ëMÑîX k#…ÈãIªRr ÜŠ[ Ü€ ܬFßÁíD¨-Î Æ;¸&-†´Šià{¸OP<ì’Á´1¤MÚ¹ƒt¨†·\Í×ku§¸;5ÙnHXv‘¨!]r1%ûð ‰ Ã0§²Ò„t *‡Ü1½ðT]BØ­¬ÜtáÂ-å†ì”¸!»¤ÇKå2C.—+%‹ã¥Ū2C¾!W*¢or•\Mx´ÖÕ²ZÅm¸…UŒ3W¹¥ªŒqŸ\ÉêlE,rRzüà´…[UÆíºV®3ä[r½!7(GÜ(Wr“|Û›åjCnÁí†Ü*·ò%*ûÜŲ!·ËwYX¹À¤Š2Îu]Ì4y®‚Ó‡Y <'”kïP͆Ü%w't°3²ÝluY9LáÙC¾'÷d˜R‹{23$*Š ¼ƒ0d·\/€!{ä^C¾/÷hrŸ7å†ÜŸÅžkCPáæ™ŸɈ: ù¡\lȃò÷™nÑEñâbÅ`ÈÃ*ÅÆ¹c&{ý>Vi%±¬=f Ù½ƒwbª¼eic›^ÏRĉ^ÒÉw÷w¶`Ö× „OðFŸ3<,ôdn>g?Ü_çy2°Ï|ô—Ÿ˜Þ%õ €Áz¢Xç>"£Nd1ìV“fY72³pLbÊh1s}Á¸½6=£JqŠ®ÒÁÅ´Ï*£É9¡¤ôDuXàU ªëÇ»?›¹²}eÊг¡›§[»Ö‚eN(åóqæ%ÏB=—:‚ñFsWÂú®Áz˱~Œ-)u+Z v{¶©—p,‘|”•¸”ƒÕ{þâî`8žE< ÔrÐ_n¾ÆÛ·¥Cc^¼{[܉բ’z×v„ ç46º˜ð—<[]¿kŒt6SN¶¾oÌÆ;:낊´š»ÔƒÚC“êÕqÖ»›¦[àc¥¡`©ÛÑ|ݽóÛ(~®zvú‚V†7\eŸ £"šzü–¸ª>²ÝL°žP_·k¡°©pÊ6#í‰+Lé€üh¤1I`E™4c…Ò/·]AËin±çع¼™<í±hw׆ڧ0=ëÕ—g3†Nj'"³@#yëYk>nV²0=tziÎH_û»…ò×r3Þ %?~u©'þ\“‡éßv³ÇBä‘‹ Aå ¯Š7ºÝo}m°hüÜ~½ý ÂÇ¡öW„‡sú Èé_&º%î@,yÛÂÝñŽäÅ‘å<ހà MçÙ<ïkéš³®àÇÖ­²0nGRZÕžñA<[1ëQ; hK½&§i13|d³7ØLó]$7$åJ“¦þÙAÈh5㡘ٚz=©ïæ‚ÖÂè´ž¿_‘Ó.Ÿóq*:±€'©ª—£õF†à&kümþñ¹loU}Áõ²ãï¤ášíwùkr9ârÙxÊúám>ß3ÈyÂ⼃­Î˜æâNŽ ›wánöWñ¹})”¬…ìm^YùAh½ðïO ñYL+,ãl"G€íÆ®ß˱‡ý÷ùÇ7<£ÐÜ7hb>Åxú‘×ܽ¹ìiäô!_pÆŒhèÇÈæ² 9€Qå}(à Âðôa´`·¼®F…‚¿Â˜ZoeÀÛ‹±»å±€·°¨ãv£ ã›ë„Æ}r§½8i7N"eÀKâ“{1±Öðõâ\N‚IAUÀ[°°“k|6e)Š­Ðüå¹Èâ=•Lg“iŠÅtªEëñ:¤ðúRt“ŸÄÔ=("õ4RïA~?¦ó(N{,$ªõ)³¾>ÌÈ¡»Æ)Y>gGK;¼åÈ®Õ,JÍ¡¼ª²%TZXÖ‹rE\Þ‹ ÕO¬õü½¨Ü€?i.UÁMjºªÑ[“W”§\Vý æÒ*þRv×ê™"uG¤žYÕxmžì;þâ>,¦.’®®³¾Ó‡ÒKéÖ‘ÍlÜwlfe/N¯ØoEˆŠ§'QÁöÛõb¶ãô Wb#Ó`cm3Æ< ñרŠ_ã"¼KÊ÷° Ÿ£ÇÑ*#`Êx´É)h—btH):åLl—&„evH'¢Ò….¹ËMˆÉ^ÄåQþ~;å9ôÈ˸TÞÄ7äC\)À5ò®“?ãz9†sr˜–*öÅhêåÃp?Û»0à‡=ŒQÖœFÍ {•ºØtw›‚ñt‰c1~DŽÌÎÁ†k½ŒûßUôaŽ ±Ò!Œ¯t0¨F!SE/ÎÜwüƒ²XžÂSýá'æMâ©Íd_ø8ç¼ç¾‘g¦ôMÍ'¡Ð9Íóø×K ô(=SXº-,õ3úð,-Nž¡=ÓÏu†Sá9ÎPôièÔðœ†çÙ Ýñ¦Q³ûc"™áÛ%¹Ïp;°üªs›Ë`q·–x<¿™ð¹à6V¦€¹‹è‹~,¦ï–Ôz*-wÔü‡¼®FŽG|¶˜:%f)ÅXJ¨X–²œBV4[J^ Ï‘²^l×úT{À”€ß œúp…íÃäå¢ÁËÇ÷ü…gÄ9Ü…*Ô+±/#ß’½ZáJNxy½çæ*ú™ŒuìR6+í|*,í&©‘£VäUÀV} 5^ƇbiÌÒ•bY­¼Ð‡5»µùÉ…çyžÇÚæ\µÐ$hêÅ:4¯"iÏù4¥ˆh¹¾pƒm”7ƒ¼ÙãH´ßÌ8¼à‰T ^ÊÈRè”Çx 0ÓK%³°k˜ŸAæg„鵓r7sä~ÆÝ!ÆÙo_ÿŒçðžÇÇœ9Ì`9†Ÿ‹Ž_K_”¼$³ñ²,Á+² ¯J;~);ñšÜ†×å%¼!¯âMyxw§•Ø#){9í%ÊqÇGˆÒÏ2wR»ŸãŒÞ0 /r5{‚—,º5¤ÙËðqÃBH»\ˆ—‰ƒš Öd^pôK¼ÆPΓñ7xY§ñ+òçb–Ü‹7X:y¨ñóx“Yçµ²F园ɯSšü-1ÍÞáï8gËèOÉø{zSe× yµNv½¥a®•`¿aZx¼úà 5Öøm‹èCãd"æQL´ðtLîq:ɛŠeÍc%,3w„…Çä]}sÚêê²Sž}ÆÞÇ~e?š2<‹Ê_¯p媲>lJ¯›0Ý©›j½§ìA^Ãió† uoQ£ÜEûŽ¿Ãø¹pê8Ð~?ÞâžoSÑw/¿å-ýOijw‰g¿ÃÞ¶Kñ/´ÿýžU°üGÒy•^¤}×B±•Œ«‡,ÌZJ¾÷,;–ó–ô;É¢Ÿ½òøxŽb´†f9Ír¶öKêaß2ÿJ|ß‹sð=ijSž8TÞPqhQn§ÈsʃØYQä™Uëµ@Ýë”O~lm.¼ÈI=oÓA`‹2/-ÉõÖìõ'a*oµõ¢}CÓ‘Ms­‡wÅý¨iVÕò„*,ØK¿:&U¦@Äcéå©HbÏ{V5”ky¿†E=ð!Æâ#Þ&³Pÿ==÷ k Oц?âr®]?1Ë>gŽAäù’y{8u cÑaÝ*^®Ž°òHÝ*‡R·Ê!çV¹•g©ò-y‡hÇà·.Ž#¨f€N>Œ©_À{EV43$§øñïøçf®f¯N¹8÷Ѭ·Áœ´;ÙËlçÎdþOü— sNöÃÂù¿]w–aìÌÈûŸÔi‰µ ;{±g<¹Oajaø v<sð[©€Gò¸%.ÇX"œüÐ"ùQ kGOa©XÇg\Ÿp³±ŸÏ>Î>Á¾›â.a¿“ý.ö=¼¸Œ¿Ç³¿œýì¿AÉ#Ù_Éþ›ì¯òäð´;q é¯eéV)^ñåý?PK A‹å>É&org/gradle/cli/ParsedCommandLine.class•Wiwg~FÛÈòÄ‹ê%v“TMc[–å’ñR·Ž›8¶SâÆÆ)-L¬‰¬TÖ(£‘·”.PhÙ¡liÙ7 ’`rX¾Áá;ßøÆŸ œœ˜ç}g$KÖ¸1GçÌÜ÷Î}Ÿ÷Þç.3úǽ?þÀü.‚v˜*òø`Ö!‰‹*¬‚΢ .¶ŠbuŽf¹¸T“¸,.+*žWñBM0#hÄ'ëñ".©øT=^ÂËa¼¢âÕ·}:‚|FÅkt ã³âþ¹0^÷7„ÅçÅÎ/Ô㋸$–__Vñ•0¾A¾V¯ãMaó qù¦¸¼©â[ ͼ1s…#+3¶•É¥©™¼ /ëE;“˜Òóà êf2éœn-CÁÉê§#Î2«çÒÀð¤i¥Ò–žÊ ÙÌÀ“ºU0RãæÒ’žKMfrÆ)yâð(‘ò–Q0r¶£*T>cØ4y¤Zãq ²Œ%sÙH•ŒË¶¥Yéâñ©hªÀ™Ìô¾Mª-°C#™\ÆUЯ08a–~.k ÷Î*Œ›)CxÏð¦‹Kç ë)ñLAtÒ\г³º•kWYçpÎ#„AÍ™ ´¼äÌ FA|»”ÒWÓݳwó/뀽˜)xØÖàÓV5KÔ¶x±  ­:Ô•|)ÜÃö#÷wOP¿cÆÖžcI(ßVñÃ^yØ¢ÈUØ6K¥Þïõ¤ÿbÑ´±\jÂÌú½Óîµ3Tp‘UG(ˆŒí|ÑVÐQ³áH1“M– 7S8–± ´RΊ|{…çY›#Û¶õô·nQ/”ª¬5^kÑKošu·O;=F‚¸m,·RÚÙ¯h¤q3›5$ßbwcÖLOËF¶Ü™mÞÆ ž¶¼ßûLïÐÏn"ªÝöûª9mØG7M”h©z*gJwr‹vè©”DœÕ³Ec úY®ÁeçyíK„?ëa{ÿòÿ?ÂÕœqZ:¯«fy Ó×ÈŒY´ŒcÑöm5ðû…Óã Ý é¸^Xd‹kèÇþšùÞဂ6žŽY–¾"Öð|PÃ[x[Ãwñ= ßÇÄîç1sµ=>4ü?Rñc¶ÂfÖUüDÃOñ3Ýñ8ë*$cÕ/GWý†º*ÀSç.°„5œÂ“~ŽU¾n¶˜ |ɘ†_à—=¦0­a ç4ü WU\Ó0³~ßp´WLöHZÏ–¼:zyÁpyØéøëé*ôÄr¦Kç}j¿Ècü­†ë¸ªážÑð®Ö’[û£v.•”2}Ri›ŒÆ—c9SV´UõPÉPŒIÎir+÷°©9¹¨ã‘´Ž°gËS§¹ Óù´ØQ¥¨Z³yˆœÛ‡ãµàµOBçMkI'Æ GÃ>ýÞ ï=Ÿ7r©‘W=¶~©„Ìœ­gDô­1[¼f(O :º½6y…ÙP=𸟳J8žJe³œÒÇÃü2mç‡sQÑëP0À•ïãš-^^äúЦ5[¼¼þêy?ŒAÊC€2?TjÞH܆’¸ßümøo"@1H1tꆦXG1rõ}kÐL%×°CÁœ¤Ð à¯hœ¾ƒ&Ú4úo!º† ;‚®]LHÒ°e(”ø=¡ŽÀZý˜[]ÿ×êú;7dÃò?‚Æk'W­ü¾o£ÔÎÏñ ùAþØ…ì†=xá5Äð:IáŽCüa£b!ZÀcxœ(DÃÌp1Ž')Å1ÒóaÊïŽæ8¥”÷!°NÎü*’*&TþïÀ=t«hTÑÄÕÐý_éP;É=œ'¼’XœáÙ­/ÚúÚçý F«ÞÆÎ™ù€ë¥bXˆ@Çu #Bw¶vÉp§ú\‡}bÈ9¹Ã»¼‡x?}düÁ©À¨“•¡€àTò}HH.ßÁÝo!’Œîº…ÝsÉèyëV¬ü£«ëOÞÂC×ËIØ/ë¥a$¡qÖa’xA1c¬¾ã¤x‚š)R_J@{ñ& (ü+“}š?Av˜ö3xŠþG¸û f™”«97­ðßCTE§Bºï"¦¢å]t¸Œ”Fœ×.ã'¨ññޜ軅؜ ›t<ìõ2¯i Êâ1éi›³¡ì_3ã%œ‚§ß6ì ;AØ“÷ýžq“÷6ïA-ÁöV4Rg©‘Z¦l G® ¸¶ºþoÿµrNÚ$«gسdyŽE:ú+ŽŽ‘ÉN:$ôËÌ•œèųøxU¡ Í'\ž5øïB%Ç»6 Zç3¾]^ᜈ¢kéô>lšJþ ;ï k>ÚeÞ'*ù6zþ’Eä—Ge¤)ö¤Aù<],;[í¢ÃS;\ô¬Oº†r=l8>Y ŠÃ߀äŠ^ÚÜ9ÙŠÎ ºðNL¯ç‘vczÂÍ­&@S܇¹›Òšg\¬H«VvWc£òŒ .¸ˆ97­{ªXšŘ”ã°—GôoøÛ )ãªÈ‘¶,ÏI8åsöÈQ¦HI 0­›$AbïsŒÖ9ûŠ{ö`_ið–«*^QUt¥ Õ ¢š¹èó‰ñûÏåŒ9%ö<'ì tçE¾B^âKãårÖvs?ê–Ø`ÙÑAé^EAEXP QP –dȹÿPK AyßtÚE,org/gradle/cli/ParsedCommandLineOption.classS]OÔ@=ݯîGeùPa„eQª¨ø"ˆhHV1YƒÁ·awR»í¦íá§ðl⋘¨IÔg”ñN[`Y$ñ¡Ó™Û{Ï=çÜéï?ߘ“4²(ª˜H#‚b ¸ž¦å†ŠÉ$ô4¸™Á-L%q[¾ï¨¸+ßÓr¹§â¾Š [ÌlpWA¶´É¶˜Þð„©—„ëÍ(H•…a1¯áp#-Ÿgƒ³É,C/{ްŒ™9*IÌ Kxs ¢…ñU±E»JÅ%añ—Ú:w^³u“"¹’]aæ*s„<‡Á˜·!ˆI¡d;†n8¬jr½b ýs\^]´k5fU%ÔJݶEí’÷V¥Ý…ñ³”´•=Vy÷‚Õé£ j”;*i=z&xŽÔ «V£Qã–§ §p6K:dÇ)¹ñKn07T@–½U.Û §ÂŸ Évàé“ICzt°]p¶-)kèDNÃ(Æ t]6Mn0“,ñøÒû ÷±(#ÍWmîæ-ÛËo°-žgÖvÞ¿“²Ñ°Š‡f0« ?L'æùZÃôDÝäA¦K©@Ó϶*Õðó$¡Ñÿï)”•õM^!ÛO†îŒ+vï–i¥áÊQ,7_… ”¬ŽÒÀZ~“¾«Â]ªÕ½m\¡(K? LºHï.:EÐ8íÉrZ/PdQÚÙâ>”â!"kûˆ~E쳟}‘Vù_‚*bTÓG;-ÈÇ%ôûø¸bí„XÓÅoˆï¢í‰µœºäÏâÄ"¡Âpú(=@&‚_Ðö¨2êwì%Ž ^*õè$üAêPÀPS÷é°û =1D:¥š!䉩ä¡ÓIfÅ%þÞ±„n‚‰‡05W(v•¾bžRD ×$ÈÄÚ"xÓjÊ2D¬Ï§ìç†xr7‚k> º½!âóV.p£]Á.ÔØG²àÓ±ô€ãDÇ\“Ô8"Ùy Rð‰ŒÿPK A\vÆB| :org/gradle/cli/ProjectPropertiesCommandLineConverter.class’KOÂ@…ÏD|?PâìÀšuã#QŒ+¢$÷C;–1m‡  ÿJW&.üþ(ãª1ØDã,îéœ9ßôv¦oï/¯ö±[@yl汕G)‡ívÙ }FHWkw„LSºœ°Ü!¿]®nY×7ÎZK:Ì¿cJDóØÌ螎ZRy¶§˜ësÛñ…ÝVò;ÚHŸ+-ø )ƒ€…n´kS†#cruLXõøgh|Ó×B†„j­õÀFÌöYèÙ­Dè™èÎè%×LøÜ%”ÖŽñŽ…Ž*‡_‰¨å½?õÖˆ:("‡<Ú„bJÕö ®­ØŠtòfë^*K÷¸Õ ßµ¦ XUÞðV½Œ£Üi01Èk ÂÁp8ƒwZ±ß8T0gî?Pôa¦Î›™m”ŒÎí=ƒžÌC S³s ¦§£‹| Ë1\áôZêq-}CÓ_èJšžEˉèjš™E+ ¨ùw'©õPK A Ï8=|ü9org/gradle/cli/SystemPropertiesCommandLineConverter.class’ËJÃ@†ÏØ«mµ¶ÖjÕEÜ5BPÄ…R/Pé~šÓ‘$&ÓBÞJW‚ À‡'i©AÄYœ3óÏÿÍœ¹¼¼¾Àl— "l¡Y„Íl E Ê<&Ï dÚú@¶ËÇH ÚgÞLÝŠ{:r”Rïs‹:C*X4NĬœ°€ÀQŸ Û´;hZ3a ѽÜG!]îºÔG‹v¹7S"Š5eb o}ɸG ÑÖûtFM‡z¶9‚y¶²¶~X{()spL`7e.°KV, øTXxÉ¢Šõ¿”fDT E¤G ÄPÇWãJm®h~²­Æ49Aíjx­µÑ° ­ÓsÃhöÌ gÔ™¢n8üÇ5©Û] .FÔ’¿s°9õàQˉ΢ⲙ*•sû/@žUg J*æc±e+sƒÊ+1¾ Õî$p¦¾ô´€6¿¡™/t-Í,¢;©h-Í.¢Z ª>kìZÿPK Aorg/gradle/util/PK Aorg/gradle/util/internal/PK Aþ¡Êú'&org/gradle/util/internal/ZipSlip.class…T[SÓ@þ–J¸TĨ µñ *¨(ⵂ3õ2 /KYÊbšÔd+â›?þ€/>¨Èè¨ïþ(dz¡BÕΘ‡=»çö}çÒþøùù€3˜Í ÃìÁˆ×Äq'28‰l)xúvÊÄi-Ϙ8k✾ž71ªCÆL\Èà".5cÚrÙÄWš&d Õ†ÔðÈc†ôT¸(Ús23•Ò‚ˆòŸ4v.,pÿ1¤~W•iµ,c†#¹0*zň/ú«(é{2P" ¸ïÍËrÞ—åq†Ž˜/ zN*Z›á% ?6œ[á/¹çó èåU$ƒâøÈ¿* »ž­5¯xáù}^®rê–ñ£à_¬=õ°æšeüD‹ájœ´€4™|X‰ â¦ÔÙ¬jYla/öY8‚£Tón¶;¾/ŠÜ¿+%¨éWQV2 Èih0rdì¡r¸£Y9¯eÙ𗣋ÊRcv3Í.¬ˆ‚20iá®k¸) 70ÈÀ< Ó—=chÈf-ÜÄ-z]²0 íFgu>·-ÜA¿»î!gá>fȼú»Fç£úƒÐv£hK–¨ÄÃÅ:m|šû»‚úS¬;Ú9CÆÓ¥²Z£ÖÇŠGŠ¢–ÌB(."Ý[9µÌ£¼xQAA$#¬å»+Qbh) õ Ë"Òi·’j“-¦¹6<ÊïìSX¶¨0®ŠhŠÇ5+ZëS§8¦_Y#ô—ÓkBg½<’Œd£û ì]°ŸÎ¦DÙƒtZÛèEÉfD5xFbëw·Ð°Žž/HÍÙéôW4Î¥Üüš>Áøî¾'T’µ$h R®¡šìý8‡äáÄ—õ mqæ ‘ÒNcî&Ì œtíæMd60àÚ-É¥×µ­M´nÀví6º¬£u íë0Òo‘N½ÛÁ?@uÇ‘Á tÑŸL²ÄÄÃ(év¹ŒÕpiBêtj’¯·¸Jg„èè¯ÓîØBçG؛費 V±šö¥óXÒÒ¡_PK A•%Ó¦¹/org/gradle/wrapper/BootstrapMainStarter$1.classRËnÓ@=Ó¸u1¦„ôEy”@_IikÁ6ˆU‘@.,RuØLì!™ÊGã ü6 ±àø(ı ]t1ssÎÕ¹÷ÎÏ_ßxŠ½ó¸³ˆ»îá¾M|4ži£ÝsZ«}.à穸k£ÞŒ‡=eÏd/c¦ç‰ÌÎ¥Õeié0“c“ ”=<ÚO¦õ±b»í+7.Pÿ£ômïB%œÀÚßM• Ñ-°wźláƒ6i<øZ2³93Ööìèê³#ð‡Ò±w¹Úºl hÂãâòø¹æx8F×èE´‚v~ÿÄ—ê9à½P%pw8Ð.ÑR3êSò ѵ²ÜAcî+jŸgèQEoN SzéÝB£z÷±Œ•ªÄjÅ\Ã:­‡ÛØÀ zQ^ÅÁoPK Ai,«$ -org/gradle/wrapper/BootstrapMainStarter.classVÛSWÿsÙ°,ˆ1*‰‚±BI/µV°V(Ð-m´Ú.É!¬nvéf£Ðjï­½<÷·þ ö%Ø2µÓ—v¦“ãô;»IIb¼ÀÌÙ³ßõ÷]7ÿ>ýý1€£øIF2^à C˜”0%cïÊðA•0#aVF —d\Æ{2æǼŒd\ÁUq¼BNP®…p]ÂR2"¸!c7%|؉^|$A aQØÊ‹£ .aIÆ~ †¢„eeÊ4¹1´r™—‚§tSwN3øÉ+ þŒUà ÛUÝ䳕Ò"·çµEƒ(aÕÊkÆÍÖÅ{èw–u²‘T-»˜.ÚZÁàé»¶¶²Âíô9ËrʽÌhº™u4Ûáö8C ,® ‰ëê-펖64³˜Î:¶nÇ=Šn¥/èwñhv‘<ìl#Ì {.'­aénVfèð¸ÓšMèó–éðUÇ [µ´'bÔÓ0¹“^˜SXB¹D¨]ÃŽß.I¸üî,[†Xƒ€Í— žwÒ$w7'nm¥ž¼H«ÙSçI¾‹r•¿=£­¸btr6±šç+Žn™e ·¨:KºYPµŠ™_æ¶_¢%u­ÉPŒ-q iûõgôÅóºMÐ-{\f­Šç‚I‰jWË”0 `ƒ NãÊÂV8sÓÑKüØ «bâ¦åÄ Ê‡ÃãÎ2_t+¯c‹OŸ‹ëf\Ðɧ¾XâCƒå¡CÏ–“K‹·­„Û ”ò³ç9%¥9 ,¬HøX Ê©£ ‚; îŠc«Ö|‚OÜÃ}Ê.µwÊë¦TkÊ)¢à3|N­*Z‚RÛRU_àK_ákê¤zÒ3†U梾 ¾Á`\­4‹T ä[ßá‚ïñ€¦ì‡làˆ‚ð#ÃÐ+*0ô>¯iò¶X åìiFZ$K–]Òh²O&žÕÆñõêVoÑæ‰ÞÕFW¬€c-ÌM‘ßD²qh§Æ›ë:U“TŸ‘T…ñ–ÊÔ;#RäNv­ìðRózH$['tk=ÊeÍæ&Å›¬o²º§çh‰8ò6¿lsÜ•¯ØÂPý=ÒäÖ£ ðeîdÚ,±Xâî: º×¶Ø`»Ô¶Ùl"´zñϼ¤”žNòEë/¨›w¬Û¼¥-j=𒶨‘¨¨y1/ [Ö\ûf òUÚe÷“v¡S/7,¶ƒxBY|·šÍ™ZI,<ñJ¶ìG xâÏ&–¯Ó[šžŒžá °_é² Ct]b :OI Ó“a£$EÊì$úî>¶ÙCÿ w¾\Øïÿœo4ûÁ Hn"”#RGÎw¨ ¹ŠNb(Utm {ÌÿÛ£þ*z¢þðŽ*Âch ¼“¤#9_xW¶ŠÝcÁhyGè}ÏÕ¨ÿ/ô®CŽúC”A€ö» Sè¤s/A݇ô¡Ÿ~8Œ#Ž E¯Rü7q%нBÑß# ܤ@-8q;Dv˜{Kã0À*ŽÐÍG¶ÎÑ¢cäM%Ê8N¼›äãMœ „½UK•Ç;I¼1¢D°í ú%Ğↄ„ˆDvN¹˜Þ¦ŸDôí©Õâg¢ùèy|±Üpxïö©#Uô­c€ýëèÙÄþÜâU˜ý]£ý¿@õ}Ⱥ¥iˆP8T©(Õj@§ ö1*BŽ“Ü ºqg)øÔ—¾è“Ó_:#Bu¦}Ó™þ#þzÑÑqF=÷~t 8“ɹ7÷Üs¾ï»çìÝ'ýÀ+øÈDo4¢ÃÒŒH“5ÉœmÀ9çñf’¸ W.š¸„Ñ&ŒaÜ@ÎÀ[&¢x;raêc" i.˜4pÅÀCÄñ*á3t<¿’©ø¼ìˆÌªÏ——…Ÿ)(g–¡¡,Qá`8µ×Æ1oÕu<^¾ê{_T«»W…^öÅŠíÕªÛ{„_nÀÀò„Övíà<ÃåÔž ²o–!<ꕉksÁvÅ•ÚÒ‚ðgø‚C+-¯ÄYîÛò}1,ÚU†î1qƒ×œ`¿Ì VÞ¥qÔáÕª €sñ:þÙèh’庯ð V]änE”ZS…›|…g\d®Mç³R“ÁËe™€!ö´›!Zò\J„[ éd'Ì­ä2c”J·&ùr]qRru·JÁ+¢èå8 ÔS›Xm¥šï“çÙšÉàMxÛËä§Æo—Är`{.±h§“-Õê’gÂT^*wSàÜ٢ߡ¸µd½ÅälÉ2º•gPZèÂU m8l¡Ž ÓÂ) «AïX˜FÑ œ´è¹yÕÀŒ…k˜50'=ïÒ±îA›áˆZuèè3Ó57°—ĶS"ÎxÏÂû¸ná\7ð!CöTDïàM-Ü%:þçho-%+Ô±ïÓBÕfuN×I¡Q{ùEñqM¸%‘íÛ帨vËÆÈ>E¯ø¶[¡Æ[áNMLݠʧò»77PPb¯dÄ15º/Nûnj3‹¾·ªRZlÇ1ÉeShKü¶ì¡|^ö¶dSÙ:83ôÐm˜ñ…†Ù1týµÈ¦¡1$û†Æ0ù»p”ì1ú·@ë‰ô:Xº ¡ôÀ´´¶†ðÕM¶ :Ùï)ö4âGÄð!ýLx ŸŠG/Ž«ë6¡p™šIäÍ©7ëxŸ#B_`¤§ñî§8”þÚw0Ó=máuèdïÞC”C-‘¯`ÌI÷·ˆË¡ŸœÑd¥)VÇ`ý….û_ ë7R÷;!ýü‰aü¥Ø¥‰3¡m³ÁKH)v#è#oHÍúÕ¾šëÐñVZ¦ç«NùIr.n¦»{×Ñ7Å!=©ßÃIbNêŸá¨äœÔ7`íø‰‡h a.Ôéï£yDÿÑù}±Çø´ê2^@Ù#G£æe! ±†YY¦cœJÊ"#òª#KïµÓxY&·-/§D15“¢4%ªÚÐ%V颢®kšTÉèD¼¬õÞé¾ã%Ð|ë“ Ú@ËÛ¥ÈlÌܧÔgêh ¼¦Ðˆ¹Š|/ª7/]>(Bó_PK Až‚­Û¡~4org/gradle/wrapper/Download$ProxyAuthenticator.class•UÝsSEÿíMèMn74ÄJ©X©1IÛ$Eü E ¤ `úa¿ ´Û›ôâõÞxscé?ä3:š¢Ì8>é Ì8€:>øWøàÃÙÛ´“¤;éî9»¿söœß9»÷ÑóŸ~p%G1¥á´>¼«Ô3Q¼‡÷•ôqÖÀÆuœ3U€(>Šà¼š/tã"&t\Š Á¤ŽËzpÅ@+oŸè¸ªãC—¿nU“y†¢ë•seO”l™ÛðD¥"½Ü¤»áØ®(ðœåXþy†ÁTGdz‰!\pK’¡§h9rºöåšôÄšM+‰¢k {Ix–Ò‹aíÍzî½Í‰š¿.ß2…ïz üªãH¯`‹jU&ßéèä^wYú³d¾áz¥¦=ËuN¦ÒÅ»âk‘s¤ŸÛDbåwg[%ØØÂ)çæ}ÏrÊŠÈwM×fˆøÅª¤øcó¾0¿˜• WŸ2\èÌ_Ç Gzµ{y5Œ2œ8Í`Ì»5Ï”W,Åtlg+«2àx Ç9Ž¡_IEŽ)Ìè˜åø sóXбȱ„ë:np,ã&C_{æ—j–]’Ç Vé°ìnêŸ+Ã[·q‡!ÞnÈp8ÛÆ+(ŸªÁ!°¦¢59N"ÉýýÀpt÷„¶ŽL2„RŠú8uÓœüª&«d´°YQ¤¶é©æ¦j9$Ù‚¤â$_ÇphvnæÆ2é—õÛ%Q½8W¤¥æ¨h…P¼YgèVe·‰{wð­m~¼KTaš²ZMŽæ©A³¼Ûîk¾eçè~¨F!r3’Ú{ôÞh­§îžïî4U¬Å)U’"âšάݕ¦ßâ°±Døna]xž'6éaJ¥W Ôôû„³RH/aÞá>z«Y<®nI!hêRQ'¿NÚÒ4šÌÐÐ2[}Kš†»<Æ4ò@6poÑVÝðð/iašk™:ÂßáÐ7°HêªC/f¾‡ö‘‡ˆ.oÁª£;Ái¨#ö#kø=SÿblX¼6=òºG¦"±<ÇZÞ³ôÛJâDI²8^I Ø`ˆ+ñ’Xv‚Bx±žm%²$¤§,”%”¦{X ´,¥t¡„¥ÐÐ9Á@ - {éltöé´)3̾vhëþ÷¾'Y²…Iç›ï›|ñ}÷ž{î¹çžóŸsîµ_ÿÍs/Ñ*þQ)ÕÑxè?é¿<èý·h~©ÐÿxÈExèqú•—~M¿ñÒc4†Iaö’—KOáóÅ÷Ñ,ÍRÑ,óЛ¼ÜÃÕ¼B45 ת\ç¡Õ\ï"ñ¯‚ 7zèu¾På•^ʼnE«eµÂ+¼ÆCWÒ*¯Å—/Í¥*7‰¯CHjVø2¡éå¢iÍ¢¹R4ëDÓ*š6…×+Ü®òmáf¡ûU*wx(ÂA•7ª¼IåNAífíöÐuÜ£òfý”·¨Ü«pHúTîWy«B'Þæá«y@åíBÆ…¯Qx§Êת¼KåëTÖUÞ-t»‡U6TRyXå•#*ïQy¯XUxTᓌŌd[TO¥ŒÓ¹ë!=5×Ç÷Ç¢q=¼9N©Tg$e`dòtàິ9bÄÌÈ nÆA,ïïÞÔݳ­{×ÖöÞP°§l{ô}zcT 7†Ìd$6ÜÌTÖ¥L=fnÕ£ihgò¶öoØÐÞ»+ÜÞÎÄAQ51ÍÚÜÛsUo{(´«­²ÂcЮ­§»»½­;ìê vµ÷ô÷íê vvCí˜YÂâåLþÞöuë‹20¹£ñáaqŽ…ñäpãpRGÆýI=‘0’rš*w룓½­F2‰ÃZ‰iö¨/&çÃÌÉ©ƒèbŒfD½Ü²UÚŒD»ô˜JC‘á˜n¦“PàâÂÙ˦v:¥2Ü—Eb³…©µz†£ž´[™œmñ°!TÄŒîôèn#Ù§ïŽÂÑñA=ºUOFÄØ&:Í‘vÎL¶Šóã±}°BhšI–Wçzr¢yÅ4S¹ÃäA|Û­ïÜBŽ%’ >O"O|Uqé0¼ø Ž‚cLdÖ\L~¾Szvï1Íæéᔲ©îÅ:)Má„Â×+ uÝÏÚû7Ïèôß²g³ã¯À<òÿ¨ÀYZI¨¹Š #Ò¦æ5ðŽjÁ¤†mÝ‚l?Å ³±¿7hËÄ7D¢†”¨èá°ÐI¬É.l¤ÌHÌ–=«p- Ú~`ÐHˆI,®ÈF2¦G± 2’ë† ;­»ÓCC" •ìhÅÆ±ôh¯!”ôšqSv±as$O’Î’x#B9›ËÚâi±¢¶€^óóÕîDÊŽ½P 26=or:Ük˜}‘Q#ž6sʃÏq.ÊpÀž´™H›0¼¡bº$Ë*fƒ±üI%¥ýÉèûu¢à¦6N+¼Oáý È1G˜OqÌŠ©Æ?§€:3õ:§…˜*x¯UOE§"aEQÇO7’€€g07x„ׂ±!;m·ž2Ö¬n Êdº¬ºH®-V7+† ÓZ”ì2Ì‘8\¼ /i E±[£5~ÍÌY^Å& «²•`fA»¸'Ù®'£Á57+ßB’qm£[¢ yy+ä]¢SNÀeÈÈ•H¤ƒé¨ný9Kœ_Ü[…Ç––‹É*¬& t<‰Óø ÄÉp`šS]T‚Gж±°¸¤x­]Ê+'§r4wŒ+Ý ·¡UÖ À¯x“Ù4%Ñj|šÏØ€Î_»$·b–•ýûâ–§í}òk€Â¯jü¿ûõ÷m¨¿Dã7øÍ¾ìÒÙE S@P46ìŽÄ ëuS7qcn³n÷V 0-ÕZq7õùP+b×T`Ä™Áo‘T 7©t"Ç6áh‘`·vÁî>+4ìдòMU!q³]V¾ßÒømè²N4쳫†fìjPn G')J<Õ`)zd]Ö…KSKSꥩfùE^Wãò;HWE2Ip}îÒyÎLIr%®e(-ei§Ÿáë>§Ø#¾v:ÌrM¹¶ÁtÅo<ù9,–ÇžŸ:  Ó7’Œï·^Ss‹Þ ±'‡8  _éùÕùE¶à§Ê7aÈÀÅ ²€ ¤æSI5’3PU{ÖpâV:¢§º¦|lÇ]9&…÷ŽÜ•Ê ]7À¸jæÂN;·;âz|Iõô¥Ó)Eåoú?{\‰ëªcXXaYuŠn~ÅÌWŸ™&—¬”N"iÊï‘<)ôoˆ›¼;bŸ”!á 'A´@[‘õÄä{Ê=º7I*.3.1˜ãÉ>)>¦¿àü“´‚‡‹˜›˜ÅòÁ¿`ŠÌ‚÷’çé5®OãÙgôàäï6>ú—.•Xn˳k8€W”zHÉz8GŸ{Äß¼<ƒ¾°Äsb3û ¨ƒ”ÏGWõŽV1¬(Y9U†ú(lžâߢŠ‹¤‚“—„y±—NQû;@R²•8„ú’Nµ@š>{ÊcbãF!Ûµ?‰¸Fäâ4Ai3ÿ‡Æ #F]ƒÑxJ<¬Åd ¢ëÏê‰fßžš§ð ¢©ü53c!—)¥µJá·Ðàˆ!j‚~G<*ßI‰³ÂÞtJð·Lhíþõhj ²¶Ùn)+“¿ðd¾±$±Ù‚vAuðOg³œ0’ˆ-néGx/»0lö±|e‘5;¦­É—2íù=ÿÃæ`ŒHl_|/üwicì˜;¹, ÖzД¿È,vBñË EÕm3áN bò5îŠ'GusŠVEÿ¡ˆn¦ó¨Ž bº<ä§[èú·Q }œÐmô‰Üø0ÆŸÌ ãOç?ƒñg Æ>ñTEß'^«ò{»ýŃS~ñvÿÝ’ÿÒп—¾ˆöK ì 79ñ-¯©åºúTr‚cä|F2߇փ/ÑE4‹VÓýèÕXìô=(ÿZT.·gÙ ”ÈžPÁµx©ƒ‚رX¹yœ\cäî¬Ér’T¦®º“TʾÓKäí®­?IãáZ†Î,¦3xÆ%Í€z’Ê´íèÄ™Úc锚V‘øûÕZRéZJ—Ò&j¢nj–Z°ûRZF_¡¯¢-èkôu|Uê oHó<"%”Ø\ß—5wæÅ\9M>…Ž*ôØ­ §B[#…¼T"»‘ ,*œpXøÿKÌY>xBzàIË08 > ª«£ŠšÚãTYSœ|5~çqš]ãw'®§9µuc4÷8UmžpCú|H%j ® RºnZGs¨(i£å´žj©] ÅÚ#綺œÛê$NJdïˆt›è :eO Ç%Í£ÙüwÁ(.û,ßÂÏSô´&kÏŠšg‰}óO’¿®«”£rtšÊÇiá@ žÁ‹NÐ9“™%7î E´‘ª©S*mm¸ÂVúQéé’E^P¿MÇlóõ“C®,¯ËÐâ »­F*0 `Kpì´ý-98‚øúŽ âïÒ³Xy\nÆ´ýLv3ÇXQü±mws“«ö—¡ó›ÜãtÁÀ8-ÀÆKÇhY·ß¡åMΚZ¿sŒªá°MŠß —*­ryE†êíoƒß™¡Æ&We5=¯6©btáOéZoéÚ2¿Ë¯fhåÀšÒ’‡iç Z•¡‹î§²qZ=à»xŒÖœªòÎ-=¬¯õV•ÉoYUÙZ;ZzÏC¤aÊsøžh¤kËà„ªZЪ¼'éR7öWsK3ÔttâALUúš3t™ßušT¿+C—ן¦žú µ¥Ž&El8NW"l×ùZ3Ô&ηÞ׎^†6ø•1ºêTSyq!Šâ/?õ ,>‹Þ¦÷S|¹ö}Ÿg˯€xÂ%´ èº\Ûi1íD@î殣U¤#˜w׃í0õm4Œ™P"4_™´—n¢(²f¨NÀgIÄY >5é{´ûßHï‚ãÏèfú þsdÑ÷é ý#ÝMnäEtŸG7ó2:Ä5t+7Ðm¼ÙV`æ>`cÚÖ)Ø9M'ù »\KϧšÄh=ôÙKÏÓ ˆÿ!h÷"ze8Ç:…äæÄnÐËÐGHÊb=ƒèY,á éûôr@¶×º¸ž^A¹—@â«@¤ŒwÈ;ÍʪS¨C¡×z]¡7zS¡·d ;ÑÿL\,¹.¨š€òJQ>”” œ±`’ì)V芰BoO Uc°ÿÍùa{äE *~wig˜›`g‘«êÇ©c%$Èh6âg~DMéÂO÷õë§-¾ÞÚ1 ’¡@Þ\mnå¤Ð;¥ƒEö?§~™~$ùëé÷à+︉u«KÄï<íÌóœ RdK öèë®?ƒ²é믅NÚúi2 ¶! ê|Wg£g1SS?FÛ­ØA:˜Ì€‹ PÜ(Îìà…Vó@w9êèdõmÉ%®–\âj¡?@J°úú#™Æ…Þ0Ö¯È ÏÎÉÙs5˜Þ¥[öä(6•á̶#C×tÕùvfèZß.Ç t]†ôî:ßn1tb<àð…C 69ëóF††š\~§ß…IcÀQëÎІ^¢È1¬Ü+VF Wú\Œ»É)Ý5*2&üU"Óõ8¿¡z ¾–j`BH«°þ|”T‚K‘ž·À½›Î-8ê­HÚÂ^×ÀóÁñÇô'ЀÀûSôœ ÌGøsxp6¶h·¢Þüý%z½H4…žÀÈ‘œ­H»â†‰KÚO诡£°p-•L`{‡„1è§"öL=Î IÅ’Ÿ!çXH•S8³MVǘ¬Ž°D—ƳÃîºÓt.òèBA¨rmMJÔ[:¼],‡!ëô Š4Úv‡»9œ×ûñ°ÂÀƒç¡O˜Äª.r%ãÐJ[™ÍM Ç„ñ,Èä]Š‚­8Ÿökߟ_ÃPU:â]š3aºý©G­ÍÆ©±\°^¶&a¡t"-ãœE­eY²ÿÂè›Ë›¼8\3ެK tÐŽBNûÐkØûPK A!9|¶„ 3org/gradle/wrapper/ExclusiveFileAccessManager.class•WÛsWÿYÒÚ«u|iªVÍMNZ*;±•JŠlB×NåKœÆŽ[—t-دvÅjÇÜSšB[(·¶ÐP`x¡ 3íL«$x†ô©Ì0à }á…0¿³+9¾%L=öÙs¾óÝ¿ß÷íúOÿýýÁ¯t<ŠgZ ãYµÌjxNG_ÔpNGϨ×Ô Íx^mMEœSKA-EµH ›1¯¶ ::`éÔvIÃb3lIÅžDIGŽºqu”ñåfxJ_¥~O¡ªc—u,áJ ê§íÄñ–ñ _Õð5öñÉ¡± #ùñá SgGFòÏ tŽ_2/›YÛtæ³S¾g9óý­C®SñMÇŸ1íªhñ­’t«þDE@äv”]ÛÎ;¾ô.›¶"Æ,Çò Ä2ù|÷Œ@tÈ-R°mÜrä©jiNzÓæœ-•=·`Ú3¦g©sõ,jÉŽ»Þ|vÞ3‹¶Ì.yf¹,½ìð•‚]­X—åˆeËÁBAV*¦cÎKŽÆÍ€ 0˜ ã°Ü¬âëOUß²³×)T=O:~vÈ´me±¿{]Ô“s—dÁWÊ䕲å-3ÄQºd»…EÝ!£C½…Óq¤] 0ŠE•(¹Þ;&f£*2³B5ûþ?ÍÊ^¨¤£±}Òò虫\j÷L§è–ÂøC¶‡ÖlÙtGuZÝÛ5Ó[" äMn,Ér¹Q–‡ïíõÀôtÿ1•„)ß,,N˜å@LÃ×5|CÃ75|K@gùdÙ·ˆ'ÂhÊšwL¿êQ÷ÄÀtnkŽ}¢2†ts¥óÒŸ&J',ÛVXjÊt³Š%syNÙnE>]µ¤o3•É;6‚‹ÄlK¡q¸oF3åV½B½ÖûîŽÌ>%l W Ä!½8$`¬ÍÀ ø¶À›»ïDÕ²‹Ò3ð"®x ßèýD]AÌõÙ…EßU úð²Wðªï©åûx•À¹cóLÕQ­½V$ÃCnÕ.¦×O#€&¤A7zxŠ N5@¸ïT3„Ï(ïúåz˜§Yò4©}Ï ˆž] Ò³û4½?ˆE¹vqÝÀ<Ì ŠáÓøLø¥˜ÁNŠpÿ8>K.š‰ü1´â‰DgÖ[A|ö4n›khéLp©Á¸ÖS½¼ÍESÑv\ÇcêÙöêÙ~]+蘭ËvvRˆÜ÷5dwÞ¹˜ÈÅÊý=ï#rÍ<ª‰\KªåT´¤öúÛ8º‚äloç7ð`.–ŠÕÊÅSñ WÿšŠßÄ®TŒ U4]»‰Ýï¬~¨Tô®7½‡6•‰övîãþà7ÝBZ §§Hè Ò«@'¼c ¥¿›KlÏ“¸3Ö1·™ÿ¿ãcÑÆ¶‰õDQDDwp>¨žäPõzp}”ÕÊ@8B gmγ*& _$W™Ô ëö+ôkôŽrÖ}¿F¿A?~‹Ô(µ‚AZÆÇ8‰ðÃñŸü:üưŠqÁ¤Ð8­ Ó›“"‰¼Ø…Q±câï?… z5)“çqj…™sDP·hí hô F›9Òˆ‹ޏë§uì>cÄÑ~êþiMȈvz5ÀHMü¾ ªŠø †ð$?b‡)n¬IŽPò$)SÐþƒã¢üݳŠhÑ ǧB¢†¤†<£À¿q¢ÏÒ0¶Ê.Ò¶åƒÃx½dÐ(§øÇWW½§Žw@óMì߉¥ß­5S< Ÿ ’a„<õÀuõ.«ËŸç3ôäGhí¹…GÞAtü=’£dl¥Ù¦@]± …ùßéçysŽýùü:õmŒšO• ‘ ²¼8x4ó?PK Aì„,y†-org/gradle/wrapper/GradleUserHomeLookup.classSÛNÛ@= $vŒÔ”K J)$´ÄÚÒ E¢`@"\”@¤Õ-Þsc-ÂÄg¥ØOˆN™QMž} (1ŠáìÁ#Šj€ RŽ`뛿Í€i­õm¹õßP/ÊQ«ðWM:‡Ü‰â;"¢¬+) Q¤g±ŠJ±Ù„¢÷Özߢ­Zï«þa?UÔßofw³»YRb>Ÿ¼7ï½ßýûþ~ïíÙÿ<ô0€uøÇ"´Ââ!Áà x°yHòàÈhCJÂaAŒK8"CFŠGùëö ^Èó‹xçÅ<¼„‡c<Ü!#Ž—ÊèÃËx¸sîÂËùën¯À+™äU2^{‚x “¾6ˆ×±¬×ËxÞÈ;oªÀ½x3¾…—o­@o«@oça"ˆûxû2Þ‰wÉf+âx7ï‘ðÞ ÞÄûƒø@”ÑŒñÁ‡YÚq ‘±÷ËäáG%|L ¨:¬k +¢Czâ&ÝÐwª‡Õ°n…y½I ‚i¢zÒéÔm¥Ù•­§Ý2÷ØFŽÉÔœðž¾.bº„É"–yH¥l•éêº-;ŽÙjÔÐÂã¶šHhvxÀ›;òI‰?T¬¦D]·~C*.Pí)3T3î'3F gDO®Y+°º”–.3騆Át›uSw¶ ÜU;aaJ­²¾^´Ss­®Û+àï°¢õ%ݺ©õ¦âÚ½[æ£àaÌ(ø,Ÿã½Ïã ¾ˆ/)ø2¾"á« ¾†³ ¾ŽoHxDÁ7ñ¨‚oaF·|ß(oN¨¶£à{ø>•é®a…?ðC?b®ã'~ªàgø¹‚sø…‚_â1ãW ~Íúƒa¦S34‡Ù qË>J‚žÀo%üNÁïñÄŸü!âÀ$DuX)#ZcZNMʼ]OÔPÕ8M¢Y ا©IËl#©e‡ÿ†¿+x3+g£×—2=®å„r¬È…äÕó+i/ÆŒÀåó‚FàÚ‹,ÑlÒ3­‹Úva9PÓ™Ýèr4j\–’kQ^”V^X)¡6bkªãÖ®@kÉN[²GÎéO¾Zn’•1ÍÙ¥²×^H´îUãZqÎÞ,Û¤6ÒT[¢íÎÙÊÀœƒŽåm \][ªí÷ï =Ù™šk.õ­€žôì\Bv¶'-#åh»Tg„£F"Z’.ªµtUÅ|º±€ÎœQÛÂjçS[ÈÉÞdy×1oé\–æ-Îe²û&®rŸfÛùÄ.òÌ!ÿ45žgõu¬yË‚5Bbi „¤¯ Âó²RH¡¢ÜP(™«J¨Ÿ½¯$¾«öØ:ÝÆµ…„ºâ·QÖ­ëŸ1 ¥sÜmÅb.X À¹`æwè‚Â(†›5m=›¶yá¦ue²é}n6`ÁhîóÊ¢ˆ‡“¤Ú§zßmÑ˲¨,ó!ºá™Í.bžûxê¹Æ·¼6ÿ<Û‰FQ“½Úêm~Ó²ÜÀ4-Ä€¡Òí»TwôúIþ{(ïI7^Ù–›/–|Ä_LËË*he›þïg´+Šê!YjŒ ¬b¶I-4Š|GxWN¯6Î[¨¡_:m û¨ªâ§@óÖÌL"w¦7‘;Ó³ÈéÝD¿}ô¿Ï%î.úB$š¯©o˜„¨oœDY}Ó$|õ!ÿ$üõ¡òI”ׇ“ÔOAz€(Ëð<ÄÒô|—ÓI@7z÷‹5у‚ŸtFz|·¡œõ”Ég¬ei,:yp ÞJI£²z1 i,™¢w/íúÒ¸dÒ¨ž@ mÞô–NãÒžÆi,›@¦å'OaÍ—¥"ú•žÐêû ùÃïÛBkÿ4Võ®žÀؼ&¬Î™Ðæù3¢Ä4.ÏV_AMi\IDiÔx‡W±øÿ4žåCÈïI»z kñ4Ö´¹§Ïh+•ŸÆ5ØÂ_× z^ÛEJjII(@nzÖd…Ó¨8þß™Œäò4êÓh`}ôO‡™ƒ2OmÓql+/&‘ž…,¼z­·ôe–- óØÖ±E¤ðºA¨Bë0¡(F;ãèÁ1ÂÕ„¬¸§Ð‡G‰ê1즧ïžÂ>±ƒb#†Ä6ìÛq«8€ƒ"4©Âư¸qQñ=©ÏaD<]<‰QñOŒ‰ó0]L‚LÚV‘†Ý„à„ô=T]~’Ý€½ô IûIß>Â5¡:ƒýZñ8éT`\ÜKµµŸx‰{p U¤O‰jÜŠ$å]É常¢÷ÎR$TÚi|û$%ô=Å•7’]Ž0|Ë$D$DŸFǨ„æá–#LTЈÍO‚UµSxb^Ù!ì–!¨†ÓØx²dõ*AƃœG\z£î<Ã=‹S„z諚öZáýõÑn?äÿPK AÑåQê{-org/gradle/wrapper/Install$InstallCheck.class•”]OA†ßi·]ºl Öoü¥J)¥[ šÅ›M@/jšàݰ eaiÉn«þ#o¸ÐD¢ÑÄK/üQÆ3³ÛOjhÓôÌœÝyŸóžÙýó÷Ç/%<6GN†¥…¼ Ë2-è(ÊqÅ@%« FÍã{®xÙ8 ©­Cþž[NÃÚt\ñ„.ìsÇmyb[ø>¯ÑŠt°ÂåõšUizN½F«ôpƒùªî7¹ë–„}¤ÒºðÊ.÷}á3ldÏ«·^Í LX<~r"<+¤dziTG+7ö¨ÈÔ–S¯[Ç»Â{Ëw]åªas·Ê=GæáEý¸mZ÷[¶M Ãz¶¿ÃqªÇŸ:u§ùŒa~2¤©*™m8Tqœ †ãW…çì;b!š]|Ǭ4¹}´ÍO¦ ®:ɬ‹ ùìÈpÉŠ|,v% X0x4Ú U ÚÔ‚&Ûm©¾:™2iT-ϲl÷€$ÄÄ5\7‘Â%&’& Lš¸;:ÖFtdânÊðˆaºëíÍî¡°› 3ÿǨMªbŽÞ¨½x¤¥š¥¥”“;Ð ¥l Íã'â;,÷ úg¥ºL1.ï° ®ÐÜ Váªb²Éa„BÈö7Ù`HØ¡,J㕟È-AËåÏýÒÁ¤©Ø4–G‚-#Å 9È0ƒ[€šI8S3Ùl„~ôäÃ2/h”÷’¹¯Ð~C×>A‹žÒ…hו¯É|—þ1D&Ÿ³é ÌRÕ€g…¼ÙŽô<ÛÉážäø>æÏ‰ÉÌà.ÎàÁqt4ñÃÎŽwÅß¹HœTâ…Îf÷ŠÙEâ`Ÿ³*.bZí>}²BõPK AºÝ€4Ö- org/gradle/wrapper/Install.class­Z |\UÕ?'3™7yyÝÒ¦éÐ…š6kÓ½tRŠišÒ”4-MÓÊò’¼$³Ä™7m*P‘]Q‘}­"*š´(ˆ² îŠ(à‚↠Å|ÿsßÌd’¼ÒÖß×_zï{w9÷,ÿ³¼›<óß!¢…ü®NðiŠ¥™*M‰4Ó Ð¤9N^§ëTÎ34žé!þñ£:é¦ñ…:Eù"/æÝòt†¬þ¸Æ—hü ’²!Á—Ê®ËDâËuzGlÑ-Í;|…ÆWj|“ÑKÚf$RßmµŸ§^cV¢>b&“V’)°ºaMÝ–¦Íg¯nlÙ¼©qÕ–ÍšÏÞX·y-SQÓ¹æN³&bƺjZìD8ÖUË4®>.ôböV3’²ü|5“/ïê²Lӛ≮š®„Ù±jv%Ìž+QÓ¤&±Óßß‹ÄͦYn W§çå”ÓѶˆP>ÑmÃÆÜ5ØtœÕÛI%Ã;­5áˆU×Þn%“ë͘©x«q£ÐpØ ç[Ž…í•Lg•½\ï/É‘Ù.ßÊä­wXLšÂ1«9m³›MLŠâífd«™Ë{zÐkw‡a¹®';¶÷z{Â2mku8i3-w•`›Óàá®T´ÃñXm¹côp¼Ft"¦hÏg*?jR¨Ç'Âm)yß’ˆ0wÈÇ,»f˦F,)Î]ÒÒm.\²´%ešÑWçLjüI 7fZ|D-ϳ 'kròêp"Ë԰̆:|{¸GÞ¡KàÄê‘mI?³`²=zs>±l$•r7ïa°ËÀV[ª³S`™·c“§ÛêÅx¶íTæEá$3I«=•Û}5ëN@su¸ËJÚ åégOmŒõ¤lœd™Qñ¶¶>Xß´M¦w8`š6†«UŠ1t‹m¶Ÿ·ÞìQ8Óø?­Ñ?Ã4u§•wöåjpS<d>Jê±B»â%ÓÙ¹± ,”ä‚aµ•lO„{{; H;Ñ¡ùHMSX©AwH¯G¡¸©#¦¯'ã4ÁQWŒd{e­ÆŸ3í¾Š­¤wIÙXÁŽ(8<[‹:FƒÌv;eFT ’ñT¢ÝRQhõöXí¶Õ¡fü“5莧\Ñó-X:aÇÈ¥=CZÂ]1ÓN%pøü#У %iÙ ½Àž- Üh%¢ádR<>8šÍ,NËŽ; ²:6Yf‡L“vGZÛ‡7Ÿ,›Ï8ŠÍÇ©óz Ÿ²\N©=f$äºcašÔ‚ùÇ,.vë-*C¤}5½nž,3è9zÞ ?Ñk=JôkúAOГ}‚.5èãt‰A´ß «øó8ø˜ª^Ùt½AWЕ]F—küƒoà ¾‰oÖøy¹ÕàÛøvƒïàÛQƒ¾Ú±; þ"ßr%DhY[WÂÉà/ñ—)rgsœ +ïá¯üU¾Ûà¯ñç ¾‡¿Ž€å^Æhü ƒ¿É÷¼—ï3ø~~@š}÷óÍÐ+L眦ø æ–Á¹¥É¹Áޏ• Æâv¯m†cA3Ö‡e ¤ç¸ÄÀyÁ†t®Úñ`'2AÐêEZôd×õÍC•2Ì܆¶s1lð~>`ðƒhð£üÓº#K,¦3B4+{Ðe(‹7èNú¢ÁßæïüTÊÝ[¥l ·«(Œwºm vš0nÇ ¥±ÒX+Àíº&jö»ÍV°Í²bAÛŒöHܶ»ç•ÆÔ×E"´»Mœëúí07Ø“ˆc£Ý„}r–Ñê4Dç¥ç¡Ð TPÁpb'D{0y‡l š °–Žƒ@—:.½=Ø™ˆG¡;‘JŠ%œbnžÌ-ƒ¨ïBÁÒdi,PƒRÊ”3œµe{ºÎ )«€L°N‹c& ~’oF}4Œ¯M©˜ŽZÙ:Fœî)TÃÑ·.‘0û$ü4½bð3ü¬Áß•§ç`@zY|Bo ÇÒ~,žGq¸ lº3_ùíÝÑ8J&ϲ%K þ| T¾oðø‡ÿH?Õ½2d ¸$ogÎàóO„ÐO¥ùÙ¡²•£Á/ˆF¼¢Oñ²Ÿg–¬ ~Q–Ízÿ"Pã_üK~Éà—%v–Œ1iTÔÇS‘å9(“კ:9Ø3\(;ã‰PPâÏ+ÿÊà_‹a´xr^ £Æ¿1ø·üªÆ¿3ø÷üƒÿÈÂô.§¾4ø5þ³Á¯ó(i]Ë(ƒÞâ7 þ‹ò-þkFÃcj'ƒÿ&±ûïÿƒ_5øŸbaD18-7çN‰Þ³üË wéß¿Ãw‡OLs²Bù™§F½¹ðØ?ê3¶W&ËZ•iúû|Hçâ%·¬Ì¡´¹;ßå|FŽYÕ Öã'# –SÝ2Mq+IÕ—„”ïeÒ»)Ìív¥p—e”~bYùèë•i£å\XL)s½¢IïLgËuÒÿt7S4Šmõ]•oø¢FǺì5Í%ÿsÁ6RkG-œ{%é3Ó_zu®ßl Ȳ#>íšz0'àqaä” °* bípË5Dù®‰¼@Y‡àkǪr¹yJõt˜¶Ô`p —߉'1âëH{„·¬\®¥&Œ–êµÐޝ¾M*.ktÅßU]v·Â¶œ)º“Oêéeõc×g/ ª/Ûr¿Ïð¡…“ Ñ_¿¾N•ÔÔb;ÆjØ•ýlí¾@j÷S\Ù:úï´ë%Çh,kg7·_Ûp³g= ²ÛLØb Rö5™©ŠƒÄ:#³Üow†½$+ÏÂô·å¨åG/‹Ïú0ê‰qe.º” çĉNumÉx$e[âäú‹ÕëDü¹üZã\iMLjN®ÎԸЧÙDtäûG1ÌÔ›±x 5jÄáfj™ËÅ‹ò†¤hZØÍ5Ôð-“¶Ë Û¨? ”oæDò’œ5ò6všû%…œ7yx*}[&£~ñÚ&u%¶â˜<æbMBäúÌ-dN톬¦øt ʼL Îh­Ü}e &õ5{TŽš¹² öºB®`â]#kÊ>TÕQ'òmLòLsŽêÈÚ %'CKb‘;Å--Ù_fåLÔªhÖß…°nJüËœ‘»Æõ æ#M"Z΂ún3ѱ¬•7x#ªH(΂y$@Y®ÑF^ªMè6“ëã «!bEaU³zíôëh3e㈭97’¹y\ÑWŒ™) ["re71ivZ™BÑÙ勞çÜ´†a9æ­&WQ#.ê‡ÿü]ÈM@P9åS€.¤‹ˆéb¼åÑn*’‹ <É-†ê/£ËU]‰~2Ö^EW£ý$Þ./úÙTP1HzkQá$zj€Œ}4®¢riUûÈWQ½ÆïU'| íqäC»;kh -‹h-¦“h ]ƒ™ ‡&}š>C¤ž„'VOÂUžz¾<ý,]‹áf?餡_YÙOÖ£™Ø\ñÇä7àí§¢P¾t“C>Œ øiJkEÀȯª¬ â~šú(•Ü;ŠÏ“!ãrP®¯+h:B'Ò©ŠÏµÎiY>WÒçè:p$ë?O׃Š©¾-y°·‚n ›!ÙtÈy ÝŠU'Ò º O>º»½Øyöà›Þ‘‡ïǘ3×MÛOõƒt\kåMoö,õNšHùCùÅÞ¼ÛhFu ¿Ÿf,õ{oz«*ï)†3÷ ½ZÝO³öòÉCÀw°ªŸŽy)Ø:@'„ò=K}ž€÷‘;iþ$ x‹}‹>¶ŸN i­ŸNòÞN…ü‰óûiö¶@¾ •n»ÄÇ{†ž—ãæÜ &'@9§‚ÁS©Nõ¥¶­TŒ6±vbE/ ÓŸOÇtsé#TEž‹¡ÌÝØu15 _ 7øÛ`Þ6˜¶Æíä.Ø®ÀØ5 ,*ï„J‹hÝE_‚r ùeÚUöàù+P´FÛ¢¯bVLw]Ö4×ÑÝP4Ü T¾F÷(Þ/¥¯Ó7Às3Fß/N_I÷Ò^л{“6²>.ШD£û5z€5ÚGøæšµF£~ÿiÞ5 ò!š£Qý»4n„)IÇQ†@3_ø¯€ó›«Ð\¦•y¦òVOUË~ªØO•÷b¦ ñê6LUžò yyˆ š÷SÍ“X4Ô"™Xp¯âAl1‡ Ð~r_ ‰?GA³Ь¥!õM´<š¹FÉ«8Ìê¬SÁ”ÕÓè6TΡi:; š³^zó†Ò¬Ì=‚9ÑÝò¢ F;D³¡=¾Kûé38HÌS_ýÕUT зZsÑ´]¼­h‰¦Äªliõb`iKk~uK+°*b†òiYk €N>¸7‹:GÒ;ÁÑ]TûO2°êXtú“Á×*ïå¨>¼ëô-À i=Ž' :õYéëéÛ*0Ê“8ižzúŽræûTèäÿ€`®¹Ÿ 'Ó¡Ï]7HËák! Fµ7Ð t+š!õ¢j1á#K,ο“N÷[è¸Þ)7QÐÐÊŽüYJ~Prê?´ëÔ)~¸Ž„îŒïÀ9ãáBy.FÌs?æý(Çä „'Â/]”Áî´£ Êã"YÏ“éc é|,\€]Eùw#ÏFV,ø?PK Að¿:öo4org/gradle/wrapper/Logger.class…“koÒ`Çÿ—UncŒá@Ø&s*]7¼‹11$KHð’°`²wÏÊ“®³´¬_ÅO¡Fgâ ?€ÊxžRŽ5KÓÓçrÎÿw.éï??h G ·b¸‚Û1TP£†º4w¤¹+ͶUÁŽ‚]†èÉØ.;`XxfX†ûœ!R9¨öèÓ²û‚!Ý1,ñj<8Î>?4éd¹ckÜìqÇ{ÿ0â#†bÇvtUwxßꇇÂQ;¶® §É6m!Wéó÷\5¹¥«]×1,½)Ê@ŒF\÷s ©®Ëµw/ùÐ'.Hq«Ï°3«×:âNWœŒ…¥‰fuæâ…ç-Ce"Úè„!ÇÐÔl·U£#—;²›m"x©*­@o¦ÑÛbˆwí±£‰=C•˜ôj[Æ$‘B#‰’ î%qŸc”‰±I![3ŒÌ”‘¡JgŒ´ÇXó&Õ¡ovÂHIFií ó” Qª¤V÷(µIØ”’õ)rµŽ /‡,®Ó*üœñÈåàꊧPæ¹*qw(¤PÝ&nü_Ý–7Û›PK Aé`˜Žï8org/gradle/wrapper/PathAssembler$LocalDistribution.class•QÛJÃ@=›¤­ÑÖx¿+øP«ßAA(*(‚¾mۥݓºMÕÏRPü?JœÝ±*ˆ/3sfæÌœÙ}{y°Žù,RÏÀÁ„6“.¦]Ì0¸UÙJ.d“a°Ôà7¸Òp]Ì1¬ÿ_ 1*BÕ‚£rCT» _qá¯iX¤OLÑÏZðµŠ|-ˆ¼ Fú²dû S‡M>W|+®<Á*®>Á~0TÏвu²’h â”YèÐ&Ò㙉ôB‹bÃÝ5y]KaÝO›äµèuºF~%ÛßÉw¿-Œ;† ãVZG‘‡Õ0T\“u…‡e/ë<©ˆx<Œ6¬ðŠÁ–‚ÅO;Œ®òò5ÖD\£ß ã[øvßa‡8¾Â÷Âø>žã~ÀÖ“"nðó©0úñ4ψxVÄs!<Æ~ÂØù^ä@?fë'"^ áe6_ áÕ^ áuöCÄ›n›Òóri\5-CÍÙ–ªk¤Œ¦)ÆXI6MŰÿìì™ñ©‰å…¹‰ÙåÉ™ìÄòÜülfú¬€ÈÔeùªœ*ÉZ15G´â¨€ö1]3-Y³å’­è8?;snbl¾¾«£hÈ…’²`*Ƥ^f7Œª§TK …èªúe%o«ºq]@𔪩ÖicÛ½·Ï†øÇôEíœR5eÚ.çc^Ε¦Ë¹.ʆÊsoÑo­ª”äÀ”nS.³Ô5C®T#u^¶VÏeò4ˆWgQ±¶Kµk¶ïa÷IB¬¨EÛÙwtèsŽ|æ,XÎüÖ(š†i ( ”“MeZfC ëšm†®³´îLä4ó¬ jEÀLì³û%òlR¢m”&es•,ÒеŽ6Aiº¹½¬˜¦\TÆÕ¢bZú]'SÉÛ†j]Oe·¾&ÿ@îºÅ…Ûr1-@ ÷n‰:±–W*ž>AÓ „9KÎ_Éʯ(: ¥¬_U&Ö,E3Ùýš£–@êÒЫWÃ/M±R ³™]$`yŒR½Þ7½)x…Ê@Ä[Â7M‡æÈÀî5¾?Ÿ1mœÓm#¯ð"ú¶²áFñ¶„¯â> 'qŸˆŸJHã ñˆ„‡1-aÑ·¿5¼„Ÿá] 2rÔvRIÛj© ~Î>¿À/I™”„_ñl¿–ð¶~‹wÿò•Ï1N‰ø„ßã=Å´_vü„ˆ?Jøþ,á/ø«„¿a]@·Ã®L1Siµ˜Ñ,¥ÈÔÞg‡QüiýCÀž&e  ·±:kk–ZV¶¼ìÓíR!ªéVt•ª6ªjÛŠºu3±? ´É¸‰ª„nIø'§]c¸èç¥Mngo•ð!6¨X¼¦I5Êåp2J%Uͨ­]ÑôkŽ:ÿ¢Ý æ39n˜Û–æ¼âöŸ+~Áï—BĆvèž/íÔ\w¬i¡ïtæ”)†Ò †¿ÐgïU71KßÌäpÓÞ¿-Тû Qs9z—ÃM4'9KºLÄDS^Q UÀæßsCiëœâþŸ~äöŠŒóKÌ¡c»§¿kC qWp{š?6Ä]-hW ²E᱋iN:XðЂ±Œ»²7–iz<ñfͽ±2¿jè׸ :Z¶Ñ%€È”µ™Ù„;åßjÚ¹ÍVº/–iŽËß+åq[.™;â¹<:taœE¢{Ñ1ºùу»qî¡Y 4¿wË|ntdG¸×ÑS¤wÔOh¼ŸfKäã£gg¼!ž¸‰–xò&|ï;›O;Ûü4 ñ ZEAV¢î6<€3€c1ŒàX ÔBvç0p#ž¨Â_C OÖœŽ'jOú7ZâW­5„7жTƒD³ö*:"4ôøi¨¢«†ÛN6}#Û|÷lóu¬dcSpÝK=ž` {×ë¹õ"Hã å#ÖCØO¢Ž‘„kH:9Nºœë9ÞÀ8&(£Vºž>H"·Ð.gÉòÑÞ2ùŸ ÆÈ;C (Ž„sdÉ“þ(ž&ÍXÓÁ8ôß¾*ö×pût#—þ°K¿A7LOà.=æÐ‹»aêô*‚c1Q¦w;¦z-üÏð¼GûxçH¤çz³xÇt’Ðú6пä'Rj8Øu¤ŠèzvK‘ÃtVG>q"¢Ûò!Š×ïÏÐ]>.J}€6ó»›$¢38Oøm$Ñ×1K{“=‡y'›‘:û,8ìÉBȉ„ÓÂcõeÚÉ%׈ÜYÅÑûûÞA ±žðõU1Èù¶”ë9:¸‡e í´¿Q®Ýu´n|ÃAÉc ÉÃýÚé¶ÄW÷ ÚÉ1{I§X6ÉGsôt?'דýþKU 5Ð÷QÆ ”ŸDvQNÊ¡qZ½u½xF{±ì“Dsñ9\Z!ü—˜];<:ÏSîT"B„’o!ÿ-ë‰Èp}æ[çSóÊ)2BeäÔTjós¸ë“„/Ø#þ(Ñct`—Âû\œ:áSÈ׈8t´Óû‚Sœ ¾â”'ý)ÍãhýPK A„ÍëÂ| 0org/gradle/wrapper/SystemPropertiesHandler.classVÝSUÿ]’°!,-Ð Ò‹-á3­ŠTR°–‰ò%A(õ£.a›,„ݸٔâWý~ì“ãL}ðÍÁÇ™ú’2cÇWÿ¤Ú±þî& $¤µ9÷Üs~çÜsçÞ›ýûß?þð"¾  QÔ ÀÞP0€Oc(xSNÞ’Ú”‚i3 fh@Ô99¾-żñT,Hø;õXÄR=.âŠËr‘¸‚«~¼À{x_Ф¸&ÑÖcš‚æør|!:}mn~vŽ":»BãÔšvC §53Ž;¶a&# ã–™u4ÓYÔÒ9] ö‚aΘ€'Ô³(à·Vi=g:Ɔ¾ÏÙV¹¥K9#½ªÛ]QÛ¶ìÎÍ”nv¦-m•¾Î½†v^g-£*6`Ja©Èà#Y­" GANÅ lª¸‰”Š-|,Ðûì÷ƒg+[ò *øDŧøLÅ縥â |©â+|­â|+ÐXyvyÊ) î'ð1MnÄBʶ6‹w{/(æè¶æX,£Ö(~> WÙ¹Ê## IŽÀ±=×þ›(¾DÚÊÊWFîÙ$v tð$õ0;©À/èÓð~Ç*˜x¤BDôV©`ª -nýµ|/âº#·¿ÿŽÐ)ãÚÅøy­eðǤ2FIiÙý&Ñ^ÓÊ«,=A•5ò²ñÙ¶ì’áð¾´Tã‘mªMëfRص/}6·’-Æ·„bU ñ$eñgþ‡èRevXà|ø3%Àóò_ ๡~Šcg5hçOÈW‚ò -aŽ‚£¯÷Äï.¤›²Ö5¢T ô —cúÐOƒÅ_ð ü¶‹šå{ðLõæáý¾¾»»ðÑP;½ e™™ý3ýyÔñ؆:â•JÐ{3»P—wÑ@ô¡æÃy42ESÍ÷pä~GwÐ"03°ƒV;¸L¥M`Äôæq¬¹=çî ¿4éÈãøˆ/è£öZú‚>×u‚Þœô`iûÑNß]xÈG7Yø κcÃA=·#7?£”ÇáÇ ÆI4¹lv1ê4ýÝ$ Ĩn¼Ìq˜³R!9K€MÏ-²z›™À9üBÔ¯r‰œäWÊ)´5È"è î,µÛìÊ9z|Œ~…_=/±’ÊÈ!Ž~üLë0›Ä÷8WIþH±-_„Ú÷{ÉÿM F1µWÁU>…Ë ¯=€ÿ’‚úއ¨SpñL<`¦×Ý–_b†qW»üPK Aª=©°?-org/gradle/wrapper/WrapperConfiguration.class“mOAÇg¡ôÚãJKŸ|iᤠ" HULCß-œåH¹’»«&~*M$&¾ðø¡Œ3w ”e›˜&3³3óŸýíîõÏß_¿ Ë:¤ÀÒàaæ’`@EƒG xLá<™2OÈ<%³¨Á’ÏŽxN£8m—ÁPíˆæ–kÖöÖÖ3Ýõ5îÛ ²QO‹»M«Ž5·)÷½çÁ!ƒBwª~È+ó õÎ1í«sM¢(ê/;®¬0è/•wÄ^´°ž®9®ý®sܰ½¼Ñ ÷nïóÖ÷Z‹d,8t|åZÛkZM´lë‹ÇONlÏÚü‹¶ûÉiv,.âsñmâìî£nsúô =ÌN æN8¡u‰ Ñ½ÐÆØq$&ƒL*AîÂ=HL)£ÆìBCO*A4dF r_ ¢É s¨©ôÉ )%È  2¯)©AeEÔ,õÉ ²$!ƒÂçX Ìþywã ¬âyõ%^}9„¯°úÏ3à 2¦y~žÉOȸ¨`;¾Êä¯)Hãƒ^V0ƒYWðõ^”а¿;98ÐÝ14ØÝß724Ð3’èOt K÷×Njí-;Þž´-#;¾[ÂüN3›·µ¬}HËt eû’]„rbbßàAqy1ypßÈ–mÛG’C½–éNŒ$ûº*=” 8%g™9ݲ =/a©£zÁ62í‰â9©¿ ÄuÀÈþ NÃlç=qÔ¤Ìì˜1.aCi·[Z:£·Ÿ²´Ýk?ìÌ‚§`i¶aféRݘi‘œãzÊÞoX4šÖ”„­ÑrðÛ!vÖSºF`N3Mš-ì1²z_arT·µQÖ5Üc¦´Ì!Í2xï²Ý®\ò)éá&* Ÿ´µÔ‰^-çÞ«Ùcd {¯„õZú»nÃ! ]«÷$E×锞s=°' r|Ë™¸4gé9ÍÒ÷yJ¬Ñƒ Y†„EÑ Ž€¬n· ts@òfÁJ•BU¢(Eò2æÈDK×ÒÒ²2t!cjé„'-BF–Y×&‹vÑÝÙ\ÁvŽwËø†Œ—d¼Lî×m¯z¤”^B<úÿd‰¬ )G£Go..?¤n.¶LÆ—Öaš6é§åz5¶K³lÝq hÖ8Y[ç#ƒ”0H M·(aɨþ-ÊÂW ÃvМ$›ç‘ûÜ`Pm¬‹Þ¬Ü?}U·b§ú4FÙásïN‘Òú˜VÈÜè\;ïéˆ/TÈÒ,P¡§©(ŽHždHW)¯(±MËî5òyb-Ù«$E;µ¸¤¢"6² Íÿ»vÈ o±JˆVð;Û6w»±ÔîT â›$Ú¯º™ö-†T|ß¡Æ]²y µI½XjZ]"%ðÈ)Y¿6¿>’6i›5íˆ~šªg#•M «”;•Šïâ{,í5Ÿ;¬¯ÃëUÀkUD· u=‚£*®ãû$$í)Õ-¯«ø^Q‘ÇI?dIe ÍžPñ#æø1ë½Ää„F/Q²0©â'Æi?e6õ!#—¤(莄Ÿ1õçeøLø%ê|º%y°Ó,dÒÂKÜ¢"§|j™“¡ÙS¿RqŒmý5ÿ¿Uñ;^ýG©Q¥Ëšh†&Ÿ…}#YÜŽI¯§7w<}EüAÅñ'æLÇQQñWüMÆßUüÿ”°¯ÏŒˆDœ2ì‰È }ʉx>§§Œ1COGŒ¬¯)7rƒ’a…W¡äTÖÖN{üRçÓ“Ë|88a™§œ÷«ÄÛïAXTY¬Öø¾oeÝ‚zfu”Ç‘´y±¥º®¡çtR³ý{…·»:‰íßvêý:ÉZ˜¯|`GË_8檫x†8󨊣¾¢êò~Ì•œ£7ó:§Ë+x‹µ@¤ü-I Ý:bäqJÞ»q(¸Kq6±Û·ßb¤…j &™šÐù˜Ïï};dm§?JßpõEö¤“›)º@a Ú¦¨ƒÅ•führ%’•Qßæ¦2&ÛÔxëg“lL¿->lDÚÜé×ÁM6øuF¿g–ôÊÛºߊ C±šþ!Ì£BµhÀ^ÜG»×Ю ›h¿Ï³_FûÏ~í;=ûU´ßïÙ7Ӿ˳_‹0·kZ‡¹c‹™z8ÍóIvz‰³v¨¡Ð0ixUñpõ,sÏ¢fò´€ë§Ña\‡ªs oе(ŽC´ÖØ BÏbùj‡ÃJà%Ì®Ž%¯@Åü«,,V.£ZÈX@3#Œ8šÐæ‘Õêš‘¼RMô`:B¥ûéB€N¦c³X@À xÑe,޵^F8¿Œº8isOÆ[¯`IìQfQ?ƒ¥b^ÆÓ –Ï¢aÎÙ ç¬Iœ­tÎV9gw‘‡"3Xí6;‡kc‹s¶Ö9['ÎÖ_@cŸpÃÇ qvCÛ,bW/’þ<…guÐE4n"kÖÐÿÅÍXBÿ™èeÛ(¦Û‰rÅ}îÇNLbÅnº¿—öà<îÅ ÿ„pa€öKq‡…K§éÆ0 VìHI¬8Cª„K—¢ê?RMÁ“Q%Ó¿Vš£tʯ<Z‹0«hn!çÅ{È£­×9o(g.¡nmt²‘rgíÓñRHÃ"2„¸ü ÑLòŽDÆrõ â.<€7’^¬MÒ«h–Éî7Ñ.@§#Ä}¬¨Éâ "áð¦l¾%Þ4‹-‡çp÷°XnŶÊÌê%úPG ”2kµ«‚›Yu™ è¸2Ÿ&"[²rÛ‡É÷ôÆ[g°ƒ~;/@éã¹M´–dÕ客ÔäT­¥P, Ia’UOs#ÍMä\Ö#"t[éf8¯80Œ´£HyCTÏ!âøÈHsˆôš¢ºcô£/··ÐÌÖ…œTÜUYÇÇ<¹0ýßîÞòýÊËãžËÁâåã8áú*C9ö­ŽôÝ»mñÊŒ=‹HN@N3XL¹Ìˆ[[Å\ mRH # SdL9¾\ö¸ÙŠÅ¥l¥ 9O†ŠC(ˆ.ÊH']¤„Tí µú!Ùž ތīS´ª˜§]ÌçhµDL…³yW !p 5 éÖk¶N¯<ÚXœzZ*%q3a0LQwxˆ|q†,8‹åx˜’é¢?æñcKQ—–¢.-®.¼š"öc#ÞLg‘d ª_EXÆ™`-q-z3AiÌ·šD#»7è6²á×þ¶^á—Ç=n*êÒäê"á-‚ÿáÿPK A íAMETA-INF/PK Am±>=@?¤)META-INF/MANIFEST.MFPK AíA›org/PK A íA¿org/gradle/PK AíAêorg/gradle/wrapper/PK APrº™« -*¤org/gradle/wrapper/GradleWrapperMain.classPK AÛÆ.q/3#¤ gradle-wrapper-classpath.propertiesPK A)¤€ gradle-wrapper-parameter-names.propertiesPK AíAÉ org/gradle/cli/PK AÕÜ?®<S1¤ø org/gradle/cli/AbstractCommandLineConverter.classPK A׃µ³Xì ;¤ƒorg/gradle/cli/AbstractPropertiesCommandLineConverter.classPK A}­ÎyGK1¤4org/gradle/cli/CommandLineArgumentException.classPK A³ßâúg)¤Êorg/gradle/cli/CommandLineConverter.classPK ASf Õg&¤*org/gradle/cli/CommandLineOption.classPK Aü튯¥å(¤porg/gradle/cli/CommandLineParser$1.classPK A$f{K¿ ;¤[org/gradle/cli/CommandLineParser$AfterFirstSubCommand.classPK A¥D£¢&3¤ÿ org/gradle/cli/CommandLineParser$AfterOptions.classPK AŒ‹Müu <¤ò#org/gradle/cli/CommandLineParser$BeforeFirstSubCommand.classPK A´*«ZMïF¤H(org/gradle/cli/CommandLineParser$CaseInsensitiveStringComparator.classPK A|ìRÎÐ&=¤ù*org/gradle/cli/CommandLineParser$KnownOptionParserState.classPK A$ľ¢¥ô<¤$2org/gradle/cli/CommandLineParser$MissingOptionArgState.classPK ATK>ªÄ=¤#5org/gradle/cli/CommandLineParser$OptionAwareParserState.classPK A˜%àÌ»ª7¤(8org/gradle/cli/CommandLineParser$OptionComparator.classPK AäfC˜§£8¤8;org/gradle/cli/CommandLineParser$OptionParserState.classPK A¢Æ÷E«¶3¤5=org/gradle/cli/CommandLineParser$OptionString.classPK AgAq²”x=¤1@org/gradle/cli/CommandLineParser$OptionStringComparator.classPK A`M~U¸2¤ Corg/gradle/cli/CommandLineParser$ParserState.classPK ApÍX Ýk?¤tEorg/gradle/cli/CommandLineParser$UnknownOptionParserState.classPK A£=l)&¤®Horg/gradle/cli/CommandLineParser.classPK A‹å>É&¤[org/gradle/cli/ParsedCommandLine.classPK AyßtÚE,¤corg/gradle/cli/ParsedCommandLineOption.classPK A\vÆB| :¤9forg/gradle/cli/ProjectPropertiesCommandLineConverter.classPK A Ï8=|ü9¤ horg/gradle/cli/SystemPropertiesCommandLineConverter.classPK AíAàiorg/gradle/util/PK AíAjorg/gradle/util/internal/PK Aþ¡Êú'&¤Ijorg/gradle/util/internal/ZipSlip.classPK A•%Ó¦¹/¤‡morg/gradle/wrapper/BootstrapMainStarter$1.classPK Ai,«$ -¤oorg/gradle/wrapper/BootstrapMainStarter.classPK AhQþ}¢Ò#¤÷torg/gradle/wrapper/Download$1.classPK Ay´[À4ØA¤Úuorg/gradle/wrapper/Download$DefaultDownloadProgressListener.classPK Až‚­Û¡~4¤mzorg/gradle/wrapper/Download$ProxyAuthenticator.classPK ApOÌ)¨&!¤`~org/gradle/wrapper/Download.classPK AyL¢¡Ê1¤Èorg/gradle/wrapper/DownloadProgressListener.classPK A!9|¶„ 3¤¸‘org/gradle/wrapper/ExclusiveFileAccessManager.classPK Aì„,y†-¤¿˜org/gradle/wrapper/GradleUserHomeLookup.classPK AúâæªÛ"¤ƒ›org/gradle/wrapper/IDownload.classPK Aÿ%²V†"¤mœorg/gradle/wrapper/Install$1.classPK AÑåQê{-¤¥org/gradle/wrapper/Install$InstallCheck.classPK AºÝ€4Ö- ¤É§org/gradle/wrapper/Install.classPK Að¿:öo4¤Ý¼org/gradle/wrapper/Logger.classPK Aé`˜Žï8¤‰¿org/gradle/wrapper/PathAssembler$LocalDistribution.classPK A á¶;+&¤mÁorg/gradle/wrapper/PathAssembler.classPK A„ÍëÂ| 0¤µÈorg/gradle/wrapper/SystemPropertiesHandler.classPK Aª=©°?-¤ÅÍorg/gradle/wrapper/WrapperConfiguration.classPK AGü¨ (¤ÀÐorg/gradle/wrapper/WrapperExecutor.classPK77#Úthrift-0.19.0/lib/java/gradle/wrapper/gradle-wrapper.properties0000644000000000000000000000031214373235760024544 0ustar00rootroot00000000000000distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists thrift-0.19.0/lib/java/gradle/generateTestThrift.gradle0000644000000000000000000001347414452237057023041 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // Generated code locations for Unit tests ext.genSrc = file("$buildDir/gen-java") ext.genBeanSrc = file("$buildDir/gen-javabean") ext.genReuseSrc = file("$buildDir/gen-javareuse") ext.genFullCamelSrc = file("$buildDir/gen-fullcamel") ext.genOptionTypeJdk8Src = file("$buildDir/gen-option-type-jdk8") ext.genUnsafeSrc = file("$buildDir/gen-unsafe") ext.genDefinitionOrderTestASrc = file("$buildDir/resources/test/definition-order-test/a") ext.genDefinitionOrderTestBSrc = file("$buildDir/resources/test/definition-order-test/b") // Add the generated code directories to the test source set sourceSets { test.java.srcDirs genSrc, genBeanSrc, genReuseSrc, genFullCamelSrc, genUnsafeSrc, genOptionTypeJdk8Src } // ---------------------------------------------------------------------------- // Code generation for Unit Testing // A callable closure to make this easier ext.thriftCompile = { Task task, String thriftFileName, String generator = 'java:jakarta_annotations', File outputDir = genSrc -> def thriftFile = file("$thriftRoot/test/$thriftFileName") if (!thriftFile.exists()) { thriftFile = file("$projectDir/src/test/resources/$thriftFileName") assert thriftFile.exists(), "can't find $thriftFile" } task.inputs.file thriftFile task.outputs.dir outputDir task.doLast { outputDir.mkdirs() def result = exec { executable file(thriftCompiler) args '--gen', generator args '-out', outputDir args thriftFile standardOutput = task.outputBuffer errorOutput = task.outputBuffer ignoreExitValue = true } if (result.exitValue != 0) { // Only show the Thrift compiler output on failures, cuts down on noise! println task.outputBuffer.toString() result.rethrowFailure() } } } task generate(group: 'Build') { description = 'Generate all unit test Thrift sources' compileTestJava.dependsOn it } task generateJava(group: 'Build') { description = 'Generate the thrift gen-java source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'ThriftTest.thrift') thriftCompile(it, 'JavaTypes.thrift') thriftCompile(it, 'DebugProtoTest.thrift') thriftCompile(it, 'DoubleConstantsTest.thrift') thriftCompile(it, 'OptionalRequiredTest.thrift') thriftCompile(it, 'ManyOptionals.thrift') thriftCompile(it, 'JavaDeepCopyTest.thrift') thriftCompile(it, 'EnumContainersTest.thrift') thriftCompile(it, 'JavaBinaryDefault.thrift') thriftCompile(it, 'VoidMethExceptionsTest.thrift') thriftCompile(it, 'JavaAnnotationTest.thrift') thriftCompile(it, 'partial/thrift_test_schema.thrift') } task generateOptionalTypeJava(group: 'Build') { description = 'Generate the thrift gen-option-type-jdk8 source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'JavaOptionTypeJdk8Test.thrift', 'java:option_type=jdk8,jakarta_annotations', genOptionTypeJdk8Src) } task generateBeanJava(group: 'Build') { description = 'Generate the thrift gen-javabean source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'JavaBeansTest.thrift', 'java:beans,nocamel,future_iface,jakarta_annotations', genBeanSrc) } task generateReuseJava(group: 'Build') { description = 'Generate the thrift gen-javareuse source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'FullCamelTest.thrift', 'java:fullcamel,future_iface,jakarta_annotations', genFullCamelSrc) } task generateFullCamelJava(group: 'Build') { description = 'Generate the thrift gen-fullcamel source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'ReuseObjects.thrift', 'java:reuse_objects,jakarta_annotations', genReuseSrc) } task generateUnsafeBinariesJava(group: 'Build') { description = 'Generate the thrift gen-unsafebinaries source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'UnsafeTypes.thrift', 'java:unsafe_binaries,jakarta_annotations', genUnsafeSrc) } task generateWithAnnotationMetadata(group: 'Build') { description = 'Generate with annotation enabled and add to the default source' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'JavaAnnotationTest.thrift', 'java:annotations_as_metadata,jakarta_annotations', genSrc) } task generateJavaDefinitionOrderTestJava(group: 'Build') { description = 'Generate fields defined in different order and add to build dir so we can compare them' generate.dependsOn it ext.outputBuffer = new ByteArrayOutputStream() thriftCompile(it, 'JavaDefinitionOrderA.thrift', 'java:jakarta_annotations', genDefinitionOrderTestASrc) thriftCompile(it, 'JavaDefinitionOrderB.thrift', 'java:jakarta_annotations', genDefinitionOrderTestBSrc) } thrift-0.19.0/lib/java/gradle/cloverCoverage.gradle0000644000000000000000000000270514303740367022165 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // Keep this as an optional feature for now, disabled by default if (Boolean.parseBoolean(project.cloverEnabled)) { apply plugin: 'com.bmuschko.clover' dependencies { clover 'org.openclover:clover:4.2.+' } clover { testIncludes = ['**/Test*.java'] // Exclude the generated test code from code coverage testExcludes = ['thrift/test/Test*.java'] compiler { encoding = 'UTF-8' debug = true } report { html = true pdf = true } } build.dependsOn cloverGenerateReport } thrift-0.19.0/lib/java/gradle/codeQualityChecks.gradle0000644000000000000000000000206314303740367022620 0ustar00rootroot00000000000000 // ================================================================= // Configure the Gradle code quality plugins here. // dependencies { spotbugs configurations.spotbugsPlugins.dependencies spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0' } // see https://spotbugs-gradle-plugin.netlify.app/com/github/spotbugs/snom/spotbugsextension spotbugs { ignoreFailures = true toolVersion = '4.5.3' effort = 'max' reportLevel = 'low' excludeFilter = file('code_quality_tools/findbugs-filter.xml') } // see https://spotbugs-gradle-plugin.netlify.app/com/github/spotbugs/snom/spotbugstask spotbugsMain { reports { text.enabled = false html.enabled = true xml.enabled = false } } pmd { ignoreFailures = true toolVersion = '6.0.0' sourceSets = [ sourceSets.main ] ruleSets = [ 'java-basic' ] } tasks.withType(Pmd) { reports { html.required = true xml.required = false } } spotless { java { target 'src/**/*.java' googleJavaFormat() } } thrift-0.19.0/lib/java/gradle/environment.gradle0000644000000000000000000000567714452237057021600 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // Override the build directory if CMake is used (allows for out-of-tree-builds) if (hasProperty('build.dir')) { buildDir = file(property('build.dir')) } // In order to remain compatible with other Ant based builds in the system // we convert the gradle.properties into DSL friendly camelCased properties ext.installPath = property('install.path') ext.installJavadocPath = property('install.javadoc.path') ext.thriftRoot = rootProject.file('../..') ext.thriftCompiler = findProperty('thrift.compiler') ?: "$thriftRoot/compiler/cpp/thrift" ext.mvnRepo = property('mvn.repo') ext.apacheRepo = property('apache.repo') ext.mavenRepositoryUrl = property('maven-repository-url') // Versions used in this project ext.httpclientVersion = property('httpclient.version') ext.httpcoreVersion = property('httpcore.version') ext.servletVersion = property('servlet.version') ext.tomcatEmbedVersion = property('tomcat.embed.version') ext.slf4jVersion = property('slf4j.version') ext.junitVersion = property('junit.version') ext.mockitoVersion = property('mockito.version') ext.javaxAnnotationVersion = property('javax.annotation.version') ext.commonsLang3Version = property('commons-lang3.version') // In this section you declare where to find the dependencies of your project repositories { maven { name 'Maven Central Repository' url mvnRepo } maven { name 'Apache Maven Repository' url apacheRepo } } dependencies { implementation "org.slf4j:slf4j-api:${slf4jVersion}" implementation "org.apache.httpcomponents.client5:httpclient5:${httpclientVersion}" implementation "org.apache.httpcomponents.core5:httpcore5:${httpcoreVersion}" implementation "jakarta.servlet:jakarta.servlet-api:${servletVersion}" implementation "jakarta.annotation:jakarta.annotation-api:${javaxAnnotationVersion}" implementation "org.apache.commons:commons-lang3:${commonsLang3Version}" testImplementation "org.junit.jupiter:junit-jupiter:${junitVersion}" testImplementation "org.mockito:mockito-core:${mockitoVersion}" testRuntimeOnly "org.slf4j:slf4j-log4j12:${slf4jVersion}" } thrift-0.19.0/lib/java/gradle/sourceConfiguration.gradle0000644000000000000000000001133714452237057023252 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // ---------------------------------------------------------------------------- // Compiler configuration details // We are using Java 17 (latest LTS) toolchain to compile. // This enables decoupling from the Java version that gradle runs, from // the actual JDK version for the project. For more details, see // https://docs.gradle.org/current/userguide/toolchains.html // // The '--release' option added below makes sure that even if we are using // the toolchain version > 11, the final artifact is at version 11. There is // also a runtime CI that's based on Java 11 to ensure that. java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.debug = true options.deprecation = true // the following is to build with Java 8 specifications, even when building with later JDK options.release = 8 options.compilerArgs += [ '-Werror', '-Xlint:deprecation', '-Xlint:cast', '-Xlint:empty', '-Xlint:fallthrough', '-Xlint:finally', '-Xlint:overrides', // we can't enable -Xlint:unchecked just yet ] } tasks.withType(Javadoc) { failOnError false options.addStringOption('Xdoclint:none', '-quiet') options.addStringOption('encoding', 'UTF-8') options.addStringOption('charSet', 'UTF-8') } // ---------------------------------------------------------------------------- // Jar packaging details processResources { into('META-INF') { from "$thriftRoot/LICENSE" from "$thriftRoot/NOTICE" rename('(.+)', '$1.txt') } } jar { project.test.dependsOn it manifest { attributes([ "Implementation-Version": "${project.version}", "Automatic-Module-Name": "${project.group}", "Bundle-ManifestVersion": "2", "Bundle-SymbolicName": "${project.group}", "Bundle-Name": "Apache Thrift", "Bundle-Version": "${project.version}", "Bundle-Description": "Apache Thrift library", "Bundle-License": "${project.license}", "Bundle-ActivationPolicy": "lazy", "Export-Package": "${project.group}.async;uses:=\"${project.group}.protocol,${project.group}.transport,org.slf4j,${project.group}\";version=\"${project.version}\",${project.group}.protocol;uses:=\"${project.group}.transport,${project.group},${project.group}.scheme\";version=\"${project.version}\",${project.group}.server;uses:=\"${project.group}.transport,${project.group}.protocol,${project.group},org.slf4j,javax.servlet,javax.servlet.http\";version=\"${project.version}\",${project.group}.transport;uses:=\"${project.group}.protocol,${project.group},org.apache.http.client,org.apache.http.params,org.apache.http.entity,org.apache.http.client.methods,org.apache.http,org.slf4j,javax.net.ssl,javax.net,javax.security.sasl,javax.security.auth.callback\";version=\"${project.version}\",${project.group};uses:=\"${project.group}.protocol,${project.group}.async,${project.group}.server,${project.group}.transport,org.slf4j,org.apache.log4j,${project.group}.scheme\";version=\"${project.version}\",${project.group}.meta_data;uses:=\"${project.group}\";version=\"${project.version}\",${project.group}.scheme;uses:=\"${project.group}.protocol,${project.group}\";version=\"${project.version}\",${project.group}.annotation;version=\"${project.version}\"", "Import-Package": "javax.net,javax.net.ssl,javax.security.auth.callback,javax.security.sasl,javax.servlet;resolution:=optional,javax.servlet.http;resolution:=optional,org.slf4j;resolution:=optional;version=\"[1.4,2)\",org.apache.http.client;resolution:=optional,org.apache.http.params;resolution:=optional,org.apache.http.entity;resolution:=optional,org.apache.http.client.methods;resolution:=optional,org.apache.http;resolution:=optional" ]) } } thrift-0.19.0/lib/java/gradle/publishing.gradle0000644000000000000000000000677214452237057021375 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Following Gradle best practices to keep build logic organized // ---------------------------------------------------------------------------- // Installation subtasks, not used currently, we use "make install/fast" task installDist(type: Copy, group: 'Install') { description = "Copy Thrift JAR and dependencies into $installPath location" destinationDir = file(installPath) from jar from configurations.implementation } task installJavadoc(type: Copy, group: 'Install', dependsOn: javadoc) { description = "Install Thrift JavaDoc into $installJavadocPath location" destinationDir = file(installJavadocPath) from javadoc.destinationDir } java { withJavadocJar() withSourcesJar() } // skip shadow jar from publishing. Workaround for https://github.com/johnrengelman/shadow/issues/651 components.java.withVariantsFromConfiguration(configurations.shadowRuntimeElements) { skip() } publishing { publications { mavenJava(MavenPublication) { artifactId = "libthrift" from components.java pom { name = 'Apache Thrift' description = 'Thrift is a software framework for scalable cross-language services development.' url = 'http://thrift.apache.org' licenses { license { name = 'The Apache Software License, Version 2.0' url = "${project.license}" distribution = 'repo' } } developers { developer { id = 'dev' name = 'Apache Thrift Developers' email = 'dev@thrift.apache.org' } } scm { url = 'https://github.com/apache/thrift' connection = 'scm:git:https://github.com/apache/thrift.git' developerConnection = 'scm:git:git@github.com:apache/thrift.git' } } } } repositories { maven { url = mavenRepositoryUrl if (project.hasProperty("mavenUser") && project.hasProperty("mavenPassword")) { credentials { username = mavenUser password = mavenPassword } } } } } // Signing configuration, optional, only when release and publish is activated signing { required { !version.endsWith("SNAPSHOT") && gradle.taskGraph.hasTask("publish") } sign publishing.publications.mavenJava } javadoc { if(JavaVersion.current().isJava9Compatible()) { options.addBooleanOption('html5', true) } } thrift-0.19.0/lib/java/android/0000777000000000000000000000000014303740367016221 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/android/build.gradle0000644000000000000000000000302614303740367020475 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ apply plugin: 'com.android.library' android { compileSdkVersion 23 buildToolsVersion "23.0.1" useLibrary 'org.apache.http.legacy' sourceSets.main.java { srcDir '../src' exclude 'org/apache/thrift/transport/TSaslClientTransport.java' exclude 'org/apache/thrift/transport/TSaslServerTransport.java' exclude 'org/apache/thrift/transport/TSaslTransport.java' } } repositories { mavenCentral() } dependencies { compile 'org.slf4j:slf4j-api:1.7.13' compile 'javax.servlet:servlet-api:2.5' compile 'org.apache.httpcomponents:httpcore:4.4.4' } buildscript { repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' } } thrift-0.19.0/lib/java/android/src/0000777000000000000000000000000014062750226017005 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/android/src/main/0000777000000000000000000000000014303740367017734 5ustar00rootroot00000000000000thrift-0.19.0/lib/java/android/src/main/AndroidManifest.xml0000644000000000000000000000015414303740367023521 0ustar00rootroot00000000000000 thrift-0.19.0/lib/java/android/settings.gradle0000644000000000000000000000003214303740367021230 0ustar00rootroot00000000000000rootProject.name='thrift' thrift-0.19.0/lib/java/settings.gradle0000644000000000000000000000150414303740367017615 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ rootProject.name = 'libthrift' thrift-0.19.0/lib/java/Makefile.in0000644000000000000000000004451414472652516016657 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/java ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ build.gradle \ gradle.properties \ settings.gradle \ gradle \ CMakeLists.txt \ coding_standards.md \ android \ src \ code_quality_tools \ README.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/java/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/java/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-exec-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile export CLASSPATH all-local: $(GRADLE) $(GRADLE_OPTS) assemble \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ --console=plain install-exec-hook: $(GRADLE) $(GRADLE_OPTS) publishToMavenLocal \ -Prelease=true \ -Pinstall.path=$(DESTDIR)$(JAVA_PREFIX) \ -Pinstall.javadoc.path=$(DESTDIR)$(docdir)/java \ -Pthrift.version=$(PACKAGE_VERSION) \ --console=plain clean-local: $(GRADLE) $(GRADLE_OPTS) clean --console=plain precross: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) shadowJar \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain check-local: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) test \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain maven-publish: $(GRADLE) $(GRADLE_OPTS) publish \ -Prelease=true \ -Pthrift.version=$(PACKAGE_VERSION) \ --console=plain # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/nodejs/0000755000000000000000000000000014472652666015151 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodejs/Makefile.am0000644000000000000000000000274614370300523017171 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # We call npm twice to work around npm issues stubs: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen js:node -o test/ $(top_srcdir)/test/v0.16/ThriftTest.thrift deps: $(top_srcdir)/package.json $(NPM) install $(top_srcdir)/ || $(NPM) install $(top_srcdir)/ all-local: deps precross: deps stubs # TODO: Lint nodejs lib and gen-code as part of build check: deps cd $(top_srcdir) && $(NPM) test && $(NPM) run lint-tests && cd lib/nodejs clean-local: $(RM) -r test/gen-* $(RM) -r $(top_srcdir)/node_modules $(RM) -r test/episodic-code-generation-test/gen* $(RM) -r test/episodic-code-generation-test/node_modules EXTRA_DIST = \ examples \ lib \ test \ coding_standards.md \ CMakeLists.txt \ README.md thrift-0.19.0/lib/nodejs/CMakeLists.txt0000644000000000000000000000313414303740367017677 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # if(NOT NODEJS_INSTALL_DIR) if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") set(NODEJS_INSTALL_DIR "${LIB_INSTALL_DIR}/nodejs") else() set(NODEJS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/nodejs") endif() endif() # Currently no doc #if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") # set(NODEJS_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/nodejs") #else() # set(NODEJS_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/nodejs") #endif() add_custom_target(ThriftNodeJS ALL COMMENT "Installing NodeJS dependencies with npm" COMMAND npm install WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../" ) install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/" DESTINATION "${NODEJS_INSTALL_DIR}") #install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/doc/" # DESTINATION "${NODEJS_DOC_INSTALL_DIR}") thrift-0.19.0/lib/nodejs/README.md0000644000000000000000000000756614303740367016433 0ustar00rootroot00000000000000Thrift Node.js Library ========================= License ------- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ## Compatibility node version 6 or later is required ## Install npm install thrift ## Thrift Compiler You can compile IDL sources for Node.js with the following command: thrift --gen js:node thrift_file ## Cassandra Client Example: Here is a Cassandra example: ```js var thrift = require('thrift'), Cassandra = require('./gen-nodejs/Cassandra') ttypes = require('./gen-nodejs/cassandra_types'); var connection = thrift.createConnection("localhost", 9160), client = thrift.createClient(Cassandra, connection); connection.on('error', function(err) { console.error(err); }); client.get_slice("Keyspace", "key", new ttypes.ColumnParent({column_family: "ExampleCF"}), new ttypes.SlicePredicate({slice_range: new ttypes.SliceRange({start: '', finish: ''})}), ttypes.ConsistencyLevel.ONE, function(err, data) { if (err) { // handle err } else { // data == [ttypes.ColumnOrSuperColumn, ...] } connection.end(); }); ``` ## Int64 Since JavaScript represents all numbers as doubles, int64 values cannot be accurately represented naturally. To solve this, int64 values in responses will be wrapped with Thrift.Int64 objects. The Int64 implementation used is [broofa/node-int64](https://github.com/broofa/node-int64). ## Client and server examples Several example clients and servers are included in the thrift/lib/nodejs/examples folder and the cross language tutorial thrift/tutorial/nodejs folder. ## Use on browsers You can use code generated with js:node on browsers with Webpack. Here is an example. thrift --gen js:node,ts,es6,with_ns ```javascript import * as thrift from 'thrift'; import { MyServiceClient } from '../gen-nodejs/MyService'; let host = window.location.hostname; let port = 443; let opts = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, headers: { 'Content-Type': 'application/vnd.apache.thrift.json', }, https: true, path: '/url/path', useCORS: true, }; let connection = thrift.createXHRConnection(host, port, opts); let thriftClient = thrift.createXHRClient(MyServiceClient, connection); connection.on('error', (err) => { console.error(err); }); thriftClient.myService(param) .then((result) => { console.log(result); }) .catch((err) => { .... }); ``` Bundlers, like webpack, will use thrift/browser.js by default because of the `"browser": "./lib/nodejs/lib/thrift/browser.js"` field in package.json. ### Browser example with WebSocket, BufferedTransport and BinaryProtocol ```javascript import thrift from 'thrift'; import { MyServiceClient } from '../gen-nodejs/MyService'; const host = window.location.hostname; const port = 9090; const opts = { transport: thrift.TBufferedTransport, protocol: thrift.TBinaryProtocol } const connection = thrift.createWSConnection(host, port, opts); connection.open(); const thriftClient = thrift.createWSClient(MyServiceClient, connection); connection.on('error', (err) => { console.error(err); }); thriftClient.myService(param) .then((result) => { console.log(result); }) .catch((err) => { .... }); ``` thrift-0.19.0/lib/nodejs/examples/0000777000000000000000000000000014303740367016760 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodejs/examples/server_multitransport.js0000644000000000000000000000276214303740367024016 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'), ttransport = require('thrift/transport'); var UserStorage = require('./gen-nodejs/UserStorage'), ttypes = require('./gen-nodejs/user_types'); var users = {}; var store = function(user, result) { console.log("stored:", user.uid); users[user.uid] = user; result(null); }; var retrieve = function(uid, result) { console.log("retrieved:", uid); result(null, users[uid]); }; var server_framed = thrift.createServer(UserStorage, { store: store, retrieve: retrieve }); server_framed.listen(9090); var server_buffered = thrift.createServer(UserStorage, { store: store, retrieve: retrieve }, {transport: ttransport.TBufferedTransport}); server_buffered.listen(9091); thrift-0.19.0/lib/nodejs/examples/hello.html0000644000000000000000000000761414303740367020755 0ustar00rootroot00000000000000 Apache Thrift JavaScript Browser Client Demo

Apache Thrift JavaScript Browser Client Demo

This html file demonstrates Apache Thrift JavaScrpt RPC between a browser client to a node.js server. Clicking the buttons below will call the RPC functions hosted by the Apache Thrift server at localhost:8585. The file hello.js contains the JavaScript node.js server required. Here are the steps to get the example running:

  1. Install Node.js
    nodejs.org
  2. Install Apache Thrift for node (note that the node package manager will create the node_modules folder in the current directory so make sure to run npm from the same directory as hello.js so that the server can find the Thrift libraries. This example requires Apache Thrift 0.9.2+)
    $ npm install thrift
  3. Compile the hello.idl for JavaScript and Node.js (you'll need to have the Apache Thrift compiler installed for this step. This also needs to be executed in the same directory as hello.js because hello.js and hello.html look for the gen-nodejs and gen-js directories here.)
    $ thrift -gen js -gen js:node hello.thrift
  4. Run the node server in the directory with the hello.html file
    $ node hello.js
  5. Copy the Apache Thrift JavaScript library, thrift.js, into the directory with this html file.
    $ cp ...../thrift.js . (you should be able to use Bower to install the browser based Apache Thrift library in the near future.)
  6. Reload this page in a browser through the node server using using the URL:
    http://localhost:8585/hello.html
    then click a button below to make an RPC call

Server Response:

Server Dbl:

thrift-0.19.0/lib/nodejs/examples/client_multitransport.js0000644000000000000000000000455214303740367023765 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'), ttransport = require('thrift/transport'); var UserStorage = require('./gen-nodejs/UserStorage'), ttypes = require('./gen-nodejs/user_types'); var f_conn = thrift.createConnection('localhost', 9090), // default: framed f_client = thrift.createClient(UserStorage, f_conn); var b_conn = thrift.createConnection('localhost', 9091, {transport: ttransport.TBufferedTransport}), b_client = thrift.createClient(UserStorage, b_conn); var user1 = new ttypes.UserProfile({uid: 1, name: "Mark Slee", blurb: "I'll find something to put here."}); var user2 = new ttypes.UserProfile({uid: 2, name: "Satoshi Tagomori", blurb: "ok, let's test with buffered transport."}); f_conn.on('error', function(err) { console.error("framed:", err); }); f_client.store(user1, function(err, response) { if (err) { console.error(err); return; } console.log("stored:", user1.uid, " as ", user1.name); b_client.retrieve(user1.uid, function(err, responseUser) { if (err) { console.error(err); return; } console.log("retrieved:", responseUser.uid, " as ", responseUser.name); }); }); b_client.store(user2, function(err, response) { if (err) { console.error(err); return; } console.log("stored:", user2.uid, " as ", user2.name); f_client.retrieve(user2.uid, function(err, responseUser) { if (err) { console.error(err); return; } console.log("retrieved:", responseUser.uid, " as ", responseUser.name); }); }); thrift-0.19.0/lib/nodejs/examples/user.thrift0000644000000000000000000000166614303740367021165 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. struct UserProfile { 1: i32 uid, 2: string name, 3: string blurb } service UserStorage { void store(1: UserProfile user), UserProfile retrieve(1: i32 uid) } thrift-0.19.0/lib/nodejs/examples/hello.js0000644000000000000000000000346314303740367020423 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'); var HelloSvc = require('./gen-nodejs/HelloSvc.js'); var TimesTwoSvc = require('./gen-nodejs/TimesTwo.js'); var helloHandler = { hello_func: function(result) { this.call_counter = this.call_counter || 0; console.log("Client call: " + (++this.call_counter)); result(null, "Hello Apache Thrift for JavaScript " + this.call_counter); } } var timesTwoHandler = { dbl: function(val, result) { console.log("Client call: " + val); result(null, val * 2); } } var helloService = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, processor: HelloSvc, handler: helloHandler }; var dblService = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, processor: TimesTwoSvc, handler: timesTwoHandler }; var ServerOptions = { files: ".", services: { "/hello": helloService, "/dbl": dblService, } } var server = thrift.createWebServer(ServerOptions); var port = 8585; server.listen(port); console.log("Http/Thrift Server running on port: " + port); thrift-0.19.0/lib/nodejs/examples/Makefile0000644000000000000000000000173714303740367020424 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. all: ../../../compiler/cpp/thrift --gen js:node user.thrift server: all NODE_PATH=../lib:../lib/thrift:$(NODE_PATH) node server.js client: all NODE_PATH=../lib:../lib/thrift:$(NODE_PATH) node client.js thrift-0.19.0/lib/nodejs/examples/README.md0000644000000000000000000000262014303740367020233 0ustar00rootroot00000000000000# Thrift Node.js Examples ## License Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ## Running the user example Generate the bindings: ../../../compiler/cpp/thrift --gen js:node user.thrift ../../../compiler/cpp/thrift --gen js:node --gen py hello.thrift To run the user example, first start up the server in one terminal: NODE_PATH=../lib:../lib/thrift node server.js Now run the client: NODE_PATH=../lib:../lib/thrift node client.js For an example using JavaScript in the browser to connect to a node.js server look at hello.html, hello.js and hello.thrift HTTP examples are provided also: httpClient.js and httpServer.js You can test HTTP cross platform with the httpServer.py Python server thrift-0.19.0/lib/nodejs/examples/server.js0000644000000000000000000000240114303740367020615 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'); var UserStorage = require('./gen-nodejs/UserStorage.js'), ttypes = require('./gen-nodejs/user_types'); var users = {}; var server = thrift.createServer(UserStorage, { store: function(user, result) { console.log("server stored:", user.uid); users[user.uid] = user; result(null); }, retrieve: function(uid, result) { console.log("server retrieved:", uid); result(null, users[uid]); }, }); server.listen(9090); thrift-0.19.0/lib/nodejs/examples/server_http.js0000644000000000000000000000316514303740367021664 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var connect = require('connect'); var thrift = require('thrift'); var UserStorage = require('./gen-nodejs/UserStorage'), ttypes = require('./gen-nodejs/user_types'); var users = {}; var store = function(user, result) { console.log("stored:", user.uid); users[user.uid] = user; result(null); }; var retrieve = function(uid, result) { console.log("retrieved:", uid); result(null, users[uid]); }; var server_http = thrift.createHttpServer(UserStorage, { store: store, retrieve: retrieve }); server_http.listen(9090); var server_connect = connect(thrift.httpMiddleware(UserStorage, { store: store, retrieve: retrieve })); server_http.listen(9091); var server_connect_json = connect(thrift.httpMiddleware(UserStorage, { store: store, retrieve: retrieve }, {protocol: thrift.TJSONProtocol})); server_connect_json.listen(9092); thrift-0.19.0/lib/nodejs/examples/httpServer.js0000644000000000000000000000207014303740367021457 0ustar00rootroot00000000000000var thrift = require('thrift'); var helloSvc = require('./gen-nodejs/HelloSvc'); //ServiceHandler: Implement the hello service var helloHandler = { hello_func: function (result) { console.log("Received Hello call"); result(null, "Hello from Node.js"); } }; //ServiceOptions: The I/O stack for the service var helloSvcOpt = { handler: helloHandler, processor: helloSvc, protocol: thrift.TJSONProtocol, transport: thrift.TBufferedTransport }; //ServerOptions: Define server features var serverOpt = { services: { "/hello": helloSvcOpt } } //Create and start the web server var port = 9090; thrift.createWebServer(serverOpt).listen(port); console.log("Http/Thrift Server running on port: " + port); thrift-0.19.0/lib/nodejs/examples/parse.js0000644000000000000000000000343214303740367020426 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** This is a standalone deserialize/parse example if you just want to deserialize thrift decoupled from cassandra server 1. acquire thrift template specification files from who ever built it (eg: EXAMPLE.thrift) 2. Install thrift on local machine 3. generate thrift clients for nodejs using template specification files (#1) thrift --gen js:node schema/EXAMPLE.thrift This creates creates gen-node.js directory containing a new file, GENERATED.js 4. Inside GENERATED.js is a class you will want to instanciate. Find this class name and plug it into the example code below (ie, "YOUR_CLASS_NAME") */ function parseThrift(thriftEncodedData, callback) { var thrift = require('thrift'); var transport = new thrift.TFramedTransport(thriftEncodedData); var protocol = new thrift.TBinaryProtocol(transport); var clientClass = require('../gen-nodejs/GENERATED').YOUR_CLASS_NAME; var client = new clientClass(); client.read(protocol); callback(null, client); } thrift-0.19.0/lib/nodejs/examples/hello.thrift0000644000000000000000000000160314303740367021301 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ service HelloSvc { string hello_func(), } service TimesTwo { i64 dbl(1: i64 val), } thrift-0.19.0/lib/nodejs/examples/httpServer.py0000644000000000000000000000101214303740367021466 0ustar00rootroot00000000000000import sys sys.path.append('gen-py') from hello import HelloSvc from thrift.protocol import TJSONProtocol from thrift.server import THttpServer class HelloSvcHandler: def hello_func(self): print("Hello Called") return "hello from Python" processor = HelloSvc.Processor(HelloSvcHandler()) protoFactory = TJSONProtocol.TJSONProtocolFactory() port = 9090 server = THttpServer.THttpServer(processor, ("localhost", port), protoFactory) print "Python server running on port " + str(port) server.serve() thrift-0.19.0/lib/nodejs/examples/httpClient.js0000644000000000000000000000106114303740367021426 0ustar00rootroot00000000000000var thrift = require('thrift'); var helloSvc = require('./gen-nodejs/HelloSvc.js'); var options = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol, path: "/hello", headers: {"Connection": "close"}, https: false }; var connection = thrift.createHttpConnection("localhost", 9090, options); var client = thrift.createHttpClient(helloSvc, connection); connection.on("error", function(err) { console.log("Error: " + err); }); client.hello_func(function(error, result) { console.log("Msg from server: " + result); }); thrift-0.19.0/lib/nodejs/examples/client.js0000644000000000000000000000321614303740367020572 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var thrift = require('thrift'); var UserStorage = require('./gen-nodejs/UserStorage.js'), ttypes = require('./gen-nodejs/user_types'); var connection = thrift.createConnection('localhost', 9090), client = thrift.createClient(UserStorage, connection); var user = new ttypes.UserProfile({uid: 1, name: "Mark Slee", blurb: "I'll find something to put here."}); connection.on('error', function(err) { console.error(err); }); client.store(user, function(err, response) { if (err) { console.error(err); } else { console.log("client stored:", user.uid); client.retrieve(user.uid, function(err, responseUser) { if (err) { console.error(err); } else { console.log("client retrieved:", responseUser.uid); connection.end(); } }); } }); thrift-0.19.0/lib/nodejs/coding_standards.md0000644000000000000000000000010314303740367020760 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/nodejs/test/0000777000000000000000000000000014452237057016123 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodejs/test/header.test.js0000644000000000000000000001015314452237057020663 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const TFramedTransport = require("../lib/thrift/framed_transport"); const THeaderTransport = require("../lib/thrift/header_transport"); const THeaderProtocol = require("../lib/thrift/header_protocol"); const thrift = require("../lib/thrift"); const fs = require("fs"); const test = require("tape"); const path = require("path"); const headerPayload = fs.readFileSync( path.join(__dirname, "test_header_payload") ); const cases = { "Should read headers from payload": function(assert) { const transport = new TFramedTransport(); transport.inBuf = Buffer.from(headerPayload); const headers = transport.readHeaders(); assert.equals(headers.Parent, "shoobar"); assert.equals(headers.Trace, "abcde"); assert.end(); }, "Should read different headers from different payload": function(assert) { const transport = new TFramedTransport(); const buf = Buffer.from(headerPayload); buf[24] = 115; // Change Parent to Parens buf[32] = 122; // Change shoobar to shoobaz transport.inBuf = buf; const headers = transport.readHeaders(); assert.equals(headers.Parent, undefined); assert.equals(headers.Parens, "shoobaz"); assert.equals(headers.Trace, "abcde"); assert.end(); }, "Should read headers when reading message begin": function(assert) { const transport = new TFramedTransport(); transport.inBuf = Buffer.from(headerPayload); const protocol = new THeaderProtocol(transport); const result = protocol.readMessageBegin(); const headers = transport.getReadHeaders(); assert.equals(headers.Parent, "shoobar"); assert.equals(headers.Trace, "abcde"); assert.equals(result.fname, "add"); assert.equals(result.mtype, thrift.Thrift.MessageType.CALL); assert.end(); }, "Should be able to write headers": function(assert) { const writeTransport = new TFramedTransport(); writeTransport.setProtocolId(THeaderTransport.SubprotocolId.BINARY); writeTransport.setWriteHeader("Hihihihi", "hohohoho"); writeTransport.setWriteHeader("boobooboo", "fooshoopoo"); writeTransport.setWriteHeader("a", "z"); writeTransport.writeHeaders(); const writeBuffer = writeTransport.outBuffers[0]; const readTransport = new TFramedTransport(); readTransport.inBuf = writeBuffer; readTransport.readHeaders(); const headers = readTransport.getReadHeaders(); assert.equals(headers.Hihihihi, "hohohoho"); assert.equals(headers.boobooboo, "fooshoopoo"); assert.equals(headers.a, "z"); assert.end(); }, "Separate transports should have separate headers": function(assert) { const writeTransport = new TFramedTransport(); writeTransport.setProtocolId(THeaderTransport.SubprotocolId.BINARY); writeTransport.setWriteHeader("foo", "bar"); const headers = writeTransport.getWriteHeaders(); const otherWriteTransport = new TFramedTransport(); otherWriteTransport.setProtocolId(THeaderTransport.SubprotocolId.BINARY); otherWriteTransport.setWriteHeader("otherfoo", "baz"); const otherHeaders = otherWriteTransport.getWriteHeaders(); assert.equals(headers.foo, "bar"); assert.equals(headers.otherfoo, undefined); assert.equals(otherHeaders.foo, undefined); assert.equals(otherHeaders.otherfoo, "baz"); assert.end(); } }; Object.keys(cases).forEach(function(caseName) { test(caseName, cases[caseName]); }); thrift-0.19.0/lib/nodejs/test/test-cases.js0000644000000000000000000001355114303740367020533 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ "use strict"; const helpers = require("./helpers"); const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); const Int64 = require("node-int64"); //all Languages in UTF-8 /*jshint -W100 */ const stringTest = (module.exports.stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " + "Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, " + "БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, " + "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, " + "Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, " + "Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, " + "Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, " + "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " + "Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, " + "Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, " + "Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, " + "ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, " + "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " + "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa " + "Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa " + "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" + "Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, " + "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " + "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " + "РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " + "English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, " + "Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " + "Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, " + "Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " + "Bân-lâm-gú, 粵語"); /*jshint +W100 */ const specialCharacters = (module.exports.specialCharacters = 'quote: " backslash:' + " forwardslash-escaped: / " + " backspace: \b formfeed: \f newline: \n return: \r tab: " + ' now-all-of-them-together: "\\/\b\n\r\t' + " now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><" + ' char-to-test-json-parsing: ]] "]] \\" }}}{ [[[ '); const mapTestInput = (module.exports.mapTestInput = { a: "123", "a b": "with spaces ", same: "same", "0": "numeric key", longValue: stringTest, stringTest: "long key" }); const simple = [ ["testVoid", undefined], ["testString", "Test"], ["testString", ""], ["testString", stringTest], ["testString", specialCharacters], ["testBool", true], ["testBool", false], ["testByte", 1], ["testByte", 0], ["testByte", -1], ["testByte", -127], ["testI32", -1], ["testDouble", -5.2098523], ["testDouble", 7.012052175215044], ["testEnum", ttypes.Numberz.ONE], ["testI64", 5], ["testI64", -5], ["testI64", 734359738368], ["testI64", -734359738368], ["testI64", new Int64(new Buffer([0, 0x20, 0, 0, 0, 0, 0, 1]))], // 2^53+1 [ "testI64", new Int64(new Buffer([0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])) ], // -2^53-1 ["testTypedef", 69] ]; const mapout = {}; for (let i = 0; i < 5; ++i) { mapout[i] = i - 10; } const deep = [ [ "testList", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] ] ]; const deepUnordered = [ ["testMap", mapout], ["testSet", [1, 2, 3]], ["testStringMap", mapTestInput] ]; const out = new ttypes.Xtruct({ string_thing: "Zero", byte_thing: 1, i32_thing: -3, i64_thing: 1000000 }); const out2 = new ttypes.Xtruct2(); out2.byte_thing = 1; out2.struct_thing = out; out2.i32_thing = 5; const crazy = new ttypes.Insanity({ userMap: { "5": 5, "8": 8 }, xtructs: [ new ttypes.Xtruct({ string_thing: "Goodbye4", byte_thing: 4, i32_thing: 4, i64_thing: 4 }), new ttypes.Xtruct({ string_thing: "Hello2", byte_thing: 2, i32_thing: 2, i64_thing: 2 }) ] }); const crazy2 = new ttypes.Insanity({ userMap: { "5": 5, "8": 8 }, xtructs: [ { string_thing: "Goodbye4", byte_thing: 4, i32_thing: 4, i64_thing: 4 }, { string_thing: "Hello2", byte_thing: 2, i32_thing: 2, i64_thing: 2 } ] }); const insanity = { "1": { "2": crazy, "3": crazy }, "2": { "6": { userMap: {}, xtructs: [] } } }; module.exports.simple = simple; module.exports.deep = deep; module.exports.deepUnordered = deepUnordered; module.exports.out = out; module.exports.out2 = out2; module.exports.crazy = crazy; module.exports.crazy2 = crazy2; module.exports.insanity = insanity; thrift-0.19.0/lib/nodejs/test/test_driver.js0000644000000000000000000002654114303740367021015 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This is the Node.js test driver for the standard Apache Thrift // test service. The driver invokes every function defined in the // Thrift Test service with a representative range of parameters. // // The ThriftTestDriver function requires a client object // connected to a server hosting the Thrift Test service and // supports an optional callback function which is called with // a status message when the test is complete. const test = require("tape"); const helpers = require("./helpers"); const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); const TException = require("thrift").Thrift.TException; const Int64 = require("node-int64"); const testCases = require("./test-cases"); exports.ThriftTestDriver = function(client, callback) { test( "NodeJS Style Callback Client Tests", { skip: helpers.ecmaMode === "es6" }, function(assert) { const checkRecursively = makeRecursiveCheck(assert); function makeAsserter(assertionFn) { return function(c) { const fnName = c[0]; const expected = c[1]; client[fnName](expected, function(err, actual) { assert.error(err, fnName + ": no callback error"); assertionFn(actual, expected, fnName); }); }; } testCases.simple.forEach( makeAsserter(function(a, e, m) { if (a instanceof Int64) { const e64 = e instanceof Int64 ? e : new Int64(e); assert.deepEqual(a.buffer, e64.buffer, m); } else { assert.equal(a, e, m); } }) ); testCases.deep.forEach(makeAsserter(assert.deepEqual)); testCases.deepUnordered.forEach( makeAsserter(makeUnorderedDeepEqual(assert)) ); const arr = []; for (let i = 0; i < 256; ++i) { arr[i] = 255 - i; } let buf = new Buffer(arr); client.testBinary(buf, function(err, response) { assert.error(err, "testBinary: no callback error"); assert.equal(response.length, 256, "testBinary"); assert.deepEqual(response, buf, "testBinary(Buffer)"); }); buf = new Buffer(arr); client.testBinary(buf.toString("binary"), function(err, response) { assert.error(err, "testBinary: no callback error"); assert.equal(response.length, 256, "testBinary"); assert.deepEqual(response, buf, "testBinary(string)"); }); client.testMapMap(42, function(err, response) { const expected = { "4": { "1": 1, "2": 2, "3": 3, "4": 4 }, "-4": { "-4": -4, "-3": -3, "-2": -2, "-1": -1 } }; assert.error(err, "testMapMap: no callback error"); assert.deepEqual(expected, response, "testMapMap"); }); client.testStruct(testCases.out, function(err, response) { assert.error(err, "testStruct: no callback error"); checkRecursively(testCases.out, response, "testStruct"); }); client.testNest(testCases.out2, function(err, response) { assert.error(err, "testNest: no callback error"); checkRecursively(testCases.out2, response, "testNest"); }); client.testInsanity(testCases.crazy, function(err, response) { assert.error(err, "testInsanity: no callback error"); checkRecursively(testCases.insanity, response, "testInsanity"); }); client.testInsanity(testCases.crazy2, function(err, response) { assert.error(err, "testInsanity2: no callback error"); checkRecursively(testCases.insanity, response, "testInsanity2"); }); client.testException("TException", function(err, response) { assert.ok( err instanceof TException, "testException: correct error type" ); assert.ok(!response, "testException: no response"); }); client.testException("Xception", function(err, response) { assert.ok( err instanceof ttypes.Xception, "testException: correct error type" ); assert.ok(!response, "testException: no response"); assert.equal(err.errorCode, 1001, "testException: correct error code"); assert.equal( "Xception", err.message, "testException: correct error message" ); }); client.testException("no Exception", function(err, response) { assert.error(err, "testException: no callback error"); assert.ok(!response, "testException: no response"); }); client.testOneway(0, function(err, response) { assert.error(err, "testOneway: no callback error"); assert.strictEqual(response, undefined, "testOneway: void response"); }); checkOffByOne(function(done) { client.testI32(-1, function(err, response) { assert.error(err, "checkOffByOne: no callback error"); assert.equal(-1, response); assert.end(); done(); }); }, callback); } ); // ES6 does not support callback style if (helpers.ecmaMode === "es6") { checkOffByOne(done => done(), callback); } }; exports.ThriftTestDriverPromise = function(client, callback) { test("Promise Client Tests", function(assert) { const checkRecursively = makeRecursiveCheck(assert); function makeAsserter(assertionFn) { return function(c) { const fnName = c[0]; const expected = c[1]; client[fnName](expected) .then(function(actual) { assertionFn(actual, expected, fnName); }) .catch(() => assert.fail("fnName")); }; } testCases.simple.forEach( makeAsserter(function(a, e, m) { if (a instanceof Int64) { const e64 = e instanceof Int64 ? e : new Int64(e); assert.deepEqual(a.buffer, e64.buffer, m); } else { assert.equal(a, e, m); } }) ); testCases.deep.forEach(makeAsserter(assert.deepEqual)); testCases.deepUnordered.forEach( makeAsserter(makeUnorderedDeepEqual(assert)) ); client .testStruct(testCases.out) .then(function(response) { checkRecursively(testCases.out, response, "testStruct"); }) .catch(() => assert.fail("testStruct")); client .testNest(testCases.out2) .then(function(response) { checkRecursively(testCases.out2, response, "testNest"); }) .catch(() => assert.fail("testNest")); client .testInsanity(testCases.crazy) .then(function(response) { checkRecursively(testCases.insanity, response, "testInsanity"); }) .catch(() => assert.fail("testInsanity")); client .testInsanity(testCases.crazy2) .then(function(response) { checkRecursively(testCases.insanity, response, "testInsanity2"); }) .catch(() => assert.fail("testInsanity2")); client .testException("TException") .then(function() { assert.fail("testException: TException"); }) .catch(function(err) { assert.ok(err instanceof TException); }); client .testException("Xception") .then(function() { assert.fail("testException: Xception"); }) .catch(function(err) { assert.ok(err instanceof ttypes.Xception); assert.equal(err.errorCode, 1001); assert.equal("Xception", err.message); }); client .testException("no Exception") .then(function(response) { assert.equal(undefined, response); //void }) .catch(() => assert.fail("testException")); client .testOneway(0) .then(function(response) { assert.strictEqual(response, undefined, "testOneway: void response"); }) .catch(() => assert.fail("testOneway: should not reject")); checkOffByOne(function(done) { client .testI32(-1) .then(function(response) { assert.equal(-1, response); assert.end(); done(); }) .catch(() => assert.fail("checkOffByOne")); }, callback); }); }; // Helper Functions // ========================================================= function makeRecursiveCheck(assert) { return function(map1, map2, msg) { const equal = checkRecursively(map1, map2); assert.ok(equal, msg); // deepEqual doesn't work with fields using node-int64 function checkRecursively(map1, map2) { if (typeof map1 !== "function" && typeof map2 !== "function") { if (!map1 || typeof map1 !== "object") { //Handle int64 types (which use node-int64 in Node.js JavaScript) if ( typeof map1 === "number" && typeof map2 === "object" && map2.buffer && map2.buffer instanceof Buffer && map2.buffer.length === 8 ) { const n = new Int64(map2.buffer); return map1 === n.toNumber(); } else { return map1 == map2; } } else { return Object.keys(map1).every(function(key) { return checkRecursively(map1[key], map2[key]); }); } } } }; } function checkOffByOne(done, callback) { const retry_limit = 30; const retry_interval = 100; let test_complete = false; let retrys = 0; /** * redo a simple test after the oneway to make sure we aren't "off by one" -- * if the server treated oneway void like normal void, this next test will * fail since it will get the void confirmation rather than the correct * result. In this circumstance, the client will throw the exception: * * Because this is the last test against the server, when it completes * the entire suite is complete by definition (the tests run serially). */ done(function() { test_complete = true; }); //We wait up to retry_limit * retry_interval for the test suite to complete function TestForCompletion() { if (test_complete && callback) { callback("Server successfully tested!"); } else { if (++retrys < retry_limit) { setTimeout(TestForCompletion, retry_interval); } else if (callback) { callback( "Server test failed to complete after " + (retry_limit * retry_interval) / 1000 + " seconds" ); } } } setTimeout(TestForCompletion, retry_interval); } function makeUnorderedDeepEqual(assert) { return function(actual, expected, name) { assert.equal(actual.length, expected.length, name); for (const k in actual) { let found = false; for (const k2 in expected) { if (actual[k] === expected[k2]) { found = true; } } if (!found) { assert.fail("Unexpected value " + actual[k] + " with key " + k); } } }; } thrift-0.19.0/lib/nodejs/test/testAll.sh0000755000000000000000000001161514370300523020056 0ustar00rootroot00000000000000#! /bin/sh # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. if [ -n "${1}" ]; then COVER=${1}; fi DIR="$( cd "$( dirname "$0" )" && pwd )" EPISODIC_DIR=${DIR}/episodic-code-generation-test THRIFT_FILES_DIR=${DIR}/../../../test THRIFT_COMPILER=${DIR}/../../../compiler/cpp/thrift ISTANBUL="$DIR/../../../node_modules/istanbul/lib/cli.js" REPORT_PREFIX="${DIR}/../coverage/report" COUNT=0 export NODE_PATH="${DIR}:${DIR}/../lib:${NODE_PATH}" testServer() { echo " [ECMA $1] Testing $2 Client/Server with protocol $3 and transport $4 $5"; RET=0 if [ -n "${COVER}" ]; then ${ISTANBUL} cover ${DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint -- --type $2 -p $3 -t $4 $5 & COUNT=$((COUNT+1)) else node ${DIR}/server.js --${1} --type $2 -p $3 -t $4 $5 & fi SERVERPID=$! sleep 0.1 if [ -n "${COVER}" ]; then ${ISTANBUL} cover ${DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} -- --${1} --type $2 -p $3 -t $4 $5 || RET=1 COUNT=$((COUNT+1)) else node ${DIR}/client.js --${1} --type $2 -p $3 -t $4 $5 || RET=1 fi kill -2 $SERVERPID || RET=1 wait $SERVERPID return $RET } testEpisodicCompilation() { RET=0 if [ -n "${COVER}" ]; then ${ISTANBUL} cover ${EPISODIC_DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint & COUNT=$((COUNT+1)) else node ${EPISODIC_DIR}/server.js & fi SERVERPID=$! sleep 0.1 if [ -n "${COVER}" ]; then ${ISTANBUL} cover ${EPISODIC_DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} || RET=1 COUNT=$((COUNT+1)) else node ${EPISODIC_DIR}/client.js || RET=1 fi kill -2 $SERVERPID || RET=1 wait $SERVERPID return $RET } TESTOK=0 # generating Thrift code ${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/v0.16/ThriftTest.thrift ${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift ${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/Int64Test.thrift mkdir ${DIR}/gen-nodejs-es6 ${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/v0.16/ThriftTest.thrift ${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift ${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/Int64Test.thrift # generate episodic compilation test code TYPES_PACKAGE=${EPISODIC_DIR}/node_modules/types-package # generate the first episode mkdir --parents ${EPISODIC_DIR}/gen-1/first-episode ${THRIFT_COMPILER} -o ${EPISODIC_DIR}/gen-1/first-episode --gen js:node,thrift_package_output_directory=first-episode ${THRIFT_FILES_DIR}/Types.thrift # create a "package" from the first episode and "install" it, the episode file must be at the module root mkdir --parents ${TYPES_PACKAGE}/first-episode cp --force ${EPISODIC_DIR}/episodic_compilation.package.json ${TYPES_PACKAGE}/package.json cp --force ${EPISODIC_DIR}/gen-1/first-episode/gen-nodejs/Types_types.js ${TYPES_PACKAGE}/first-episode/ cp --force ${EPISODIC_DIR}/gen-1/first-episode/gen-nodejs/thrift.js.episode ${TYPES_PACKAGE} # generate the second episode mkdir --parents ${EPISODIC_DIR}/gen-2/second-episode ${THRIFT_COMPILER} -o ${EPISODIC_DIR}/gen-2/second-episode --gen js:node,imports=${TYPES_PACKAGE} ${THRIFT_FILES_DIR}/Service.thrift if [ -f ${EPISODIC_DIR}/gen-2/second-episode/Types_types.js ]; then TESTOK=1 fi # unit tests node ${DIR}/binary.test.js || TESTOK=1 node ${DIR}/int64.test.js || TESTOK=1 node ${DIR}/deep-constructor.test.js || TESTOK=1 # integration tests for type in tcp multiplex websocket http do for protocol in compact binary json do for transport in buffered framed do for ecma_version in es5 es6 do testServer $ecma_version $type $protocol $transport || TESTOK=1 testServer $ecma_version $type $protocol $transport --ssl || TESTOK=1 testServer $ecma_version $type $protocol $transport --callback || TESTOK=1 done done done done # episodic compilation test testEpisodicCompilation if [ -n "${COVER}" ]; then ${ISTANBUL} report --dir "${DIR}/../coverage" --include "${DIR}/../coverage/report*/coverage.json" lcov cobertura html rm -r ${DIR}/../coverage/report*/* rmdir ${DIR}/../coverage/report* fi exit $TESTOK thrift-0.19.0/lib/nodejs/test/test_handler.js0000644000000000000000000001244614303740367021136 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //This is the server side Node test handler for the standard // Apache Thrift test service. const helpers = require("./helpers"); const ttypes = require(`./${helpers.genPath}/ThriftTest_types`); const TException = require("thrift").Thrift.TException; function makeSyncHandler() { return function(thing) { return thing; }; } const syncHandlers = { testVoid: testVoid, testMapMap: testMapMap, testInsanity: testInsanity, testMulti: testMulti, testException: testException, testMultiException: testMultiException, testOneway: testOneway }; function makeAsyncHandler(label) { return function(thing, result) { thing = syncHandlers[label](thing); result(null, thing); }; } const asyncHandlers = { testVoid: testVoidAsync, testMulti: testMultiAsync, testException: testExceptionAsync, testMultiException: testMultiExceptionAsync, testOneway: testOnewayAsync }; const identityHandlers = [ "testString", "testBool", "testByte", "testI32", "testI64", "testDouble", "testBinary", "testStruct", "testNest", "testMap", "testStringMap", "testSet", "testList", "testEnum", "testTypedef" ]; function testVoid() { //console.log('testVoid()'); } function testVoidAsync(result) { result(testVoid()); } function testMapMap() { const mapmap = []; const pos = []; const neg = []; for (let i = 1; i < 5; i++) { pos[i] = i; neg[-i] = -i; } mapmap[4] = pos; mapmap[-4] = neg; return mapmap; } function testInsanity(argument) { //console.log('testInsanity('); //console.log(argument); //console.log(')'); const first_map = []; const second_map = []; first_map[ttypes.Numberz.TWO] = argument; first_map[ttypes.Numberz.THREE] = argument; const looney = new ttypes.Insanity(); second_map[ttypes.Numberz.SIX] = looney; const insane = []; insane[1] = first_map; insane[2] = second_map; //console.log('insane result:'); //console.log(insane); return insane; } function testMulti(arg0, arg1, arg2) { //console.log('testMulti()'); const hello = new ttypes.Xtruct(); hello.string_thing = "Hello2"; hello.byte_thing = arg0; hello.i32_thing = arg1; hello.i64_thing = arg2; return hello; } function testMultiAsync(arg0, arg1, arg2, arg3, arg4, arg5, result) { const hello = testMulti(arg0, arg1, arg2, arg3, arg4, arg5); result(null, hello); } function testException(arg) { //console.log('testException('+arg+')'); if (arg === "Xception") { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = arg; throw x; } else if (arg === "TException") { throw new TException(arg); } else { return; } } function testExceptionAsync(arg, result) { //console.log('testException('+arg+')'); if (arg === "Xception") { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = arg; result(x); } else if (arg === "TException") { result(new TException(arg)); } else { result(null); } } function testMultiException(arg0, arg1) { //console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); if (arg0 === "Xception") { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = "This is an Xception"; throw x; } else if (arg0 === "Xception2") { const x2 = new ttypes.Xception2(); x2.errorCode = 2002; x2.struct_thing = new ttypes.Xtruct(); x2.struct_thing.string_thing = "This is an Xception2"; throw x2; } const res = new ttypes.Xtruct(); res.string_thing = arg1; return res; } function testMultiExceptionAsync(arg0, arg1, result) { //console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); if (arg0 === "Xception") { const x = new ttypes.Xception(); x.errorCode = 1001; x.message = "This is an Xception"; result(x); } else if (arg0 === "Xception2") { const x2 = new ttypes.Xception2(); x2.errorCode = 2002; x2.struct_thing = new ttypes.Xtruct(); x2.struct_thing.string_thing = "This is an Xception2"; result(x2); } else { const res = new ttypes.Xtruct(); res.string_thing = arg1; result(null, res); } } //console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!'); function testOneway() {} function testOnewayAsync(sleepFor) { testOneway(sleepFor); } identityHandlers.forEach(function(label) { syncHandlers[label] = makeSyncHandler(label); asyncHandlers[label] = makeAsyncHandler(label); }); ["testMapMap", "testInsanity"].forEach(function(label) { asyncHandlers[label] = makeAsyncHandler(label); }); exports.ThriftTestHandler = asyncHandlers; thrift-0.19.0/lib/nodejs/test/certificates.README0000644000000000000000000000035114303740367021440 0ustar00rootroot00000000000000server.crt AND server.key ARE PROVIDED FOR TEST PURPOSE AND SHOULD *NEVER* BE USED IN PRODUCTION Origin of the test key and cert is the folder test/keys of Apache Thrift source code distribution We need copies for npm deployment thrift-0.19.0/lib/nodejs/test/exceptions.js0000644000000000000000000001155214303740367020640 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ "use strict"; const test = require("tape"); const thrift = require("../lib/thrift/thrift.js"); const InputBufferUnderrunError = require("../lib/thrift/input_buffer_underrun_error"); test("TApplicationException", function t(assert) { const e = new thrift.TApplicationException(1, "foo"); assert.ok( e instanceof thrift.TApplicationException, "is instanceof TApplicationException" ); assert.ok(e instanceof thrift.TException, "is instanceof TException"); assert.ok(e instanceof Error, "is instanceof Error"); assert.equal(typeof e.stack, "string", "has stack trace"); assert.ok( /^TApplicationException: foo/.test(e.stack), "Stack trace has correct error name and message" ); assert.ok( e.stack.indexOf("test/exceptions.js:7:11") !== -1, "stack trace starts on correct line and column" ); assert.equal( e.name, "TApplicationException", "has function name TApplicationException" ); assert.equal(e.message, "foo", 'has error message "foo"'); assert.equal(e.type, 1, "has type 1"); assert.end(); }); test("unexpected TApplicationException ", function t(assert) { const e = new thrift.TApplicationException(1, 100); assert.ok( e instanceof thrift.TApplicationException, "is instanceof TApplicationException" ); assert.ok(e instanceof thrift.TException, "is instanceof TException"); assert.ok(e instanceof Error, "is instanceof Error"); assert.equal(typeof e.stack, "string", "has stack trace"); assert.ok( /^TApplicationException: 100/.test(e.stack), "Stack trace has correct error name and message" ); assert.ok( e.stack.indexOf("test/exceptions.js:7:11") !== -1, "stack trace starts on correct line and column" ); assert.equal( e.name, "TApplicationException", "has function name TApplicationException" ); assert.equal(e.message, 100, "has error message 100"); assert.equal(e.type, 1, "has type 1"); assert.end(); }); test("TException", function t(assert) { const e = new thrift.TException("foo"); assert.ok(e instanceof thrift.TException, "is instanceof TException"); assert.ok(e instanceof Error, "is instanceof Error"); assert.equal(typeof e.stack, "string", "has stack trace"); assert.ok( /^TException: foo/.test(e.stack), "Stack trace has correct error name and message" ); assert.ok( e.stack.indexOf("test/exceptions.js:21:11") !== -1, "stack trace starts on correct line and column" ); assert.equal(e.name, "TException", "has function name TException"); assert.equal(e.message, "foo", 'has error message "foo"'); assert.end(); }); test("TProtocolException", function t(assert) { const e = new thrift.TProtocolException(1, "foo"); assert.ok( e instanceof thrift.TProtocolException, "is instanceof TProtocolException" ); assert.ok(e instanceof Error, "is instanceof Error"); assert.equal(typeof e.stack, "string", "has stack trace"); assert.ok( /^TProtocolException: foo/.test(e.stack), "Stack trace has correct error name and message" ); assert.ok( e.stack.indexOf("test/exceptions.js:33:11") !== -1, "stack trace starts on correct line and column" ); assert.equal( e.name, "TProtocolException", "has function name TProtocolException" ); assert.equal(e.message, "foo", 'has error message "foo"'); assert.equal(e.type, 1, "has type 1"); assert.end(); }); test("InputBufferUnderrunError", function t(assert) { const e = new InputBufferUnderrunError("foo"); assert.ok( e instanceof InputBufferUnderrunError, "is instanceof InputBufferUnderrunError" ); assert.ok(e instanceof Error, "is instanceof Error"); assert.equal(typeof e.stack, "string", "has stack trace"); assert.ok( /^InputBufferUnderrunError: foo/.test(e.stack), "Stack trace has correct error name and message" ); assert.ok( e.stack.indexOf("test/exceptions.js:46:11") !== -1, "stack trace starts on correct line and column" ); assert.equal( e.name, "InputBufferUnderrunError", "has function name InputBufferUnderrunError" ); assert.equal(e.message, "foo", 'has error message "foo"'); assert.end(); }); thrift-0.19.0/lib/nodejs/test/server.crt0000644000000000000000000000276114303740367020143 0ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIENzCCAx+gAwIBAgIJAOYfYfw7NCOcMA0GCSqGSIb3DQEBBQUAMIGxMQswCQYD VQQGEwJVUzERMA8GA1UECAwITWFyeWxhbmQxFDASBgNVBAcMC0ZvcmVzdCBIaWxs MScwJQYDVQQKDB5UaGUgQXBhY2hlIFNvZnR3YXJlIEZvdW5kYXRpb24xFjAUBgNV BAsMDUFwYWNoZSBUaHJpZnQxEjAQBgNVBAMMCWxvY2FsaG9zdDEkMCIGCSqGSIb3 DQEJARYVZGV2QHRocmlmdC5hcGFjaGUub3JnMB4XDTE0MDQwNzE4NTgwMFoXDTIy MDYyNDE4NTgwMFowgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEU MBIGA1UEBwwLRm9yZXN0IEhpbGwxJzAlBgNVBAoMHlRoZSBBcGFjaGUgU29mdHdh cmUgRm91bmRhdGlvbjEWMBQGA1UECwwNQXBhY2hlIFRocmlmdDESMBAGA1UEAwwJ bG9jYWxob3N0MSQwIgYJKoZIhvcNAQkBFhVkZXZAdGhyaWZ0LmFwYWNoZS5vcmcw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqE9TE9wEXp5LRtLQVDSGQ GV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCySN8I2Xw6 L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/HjKNg6ZKg 2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQBGmZmMIUw AinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xku62LipkX wCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDmtrhVQF4n AgMBAAGjUDBOMB0GA1UdDgQWBBQo8v0wzQPx3EEexJPGlxPK1PpgKjAfBgNVHSME GDAWgBQo8v0wzQPx3EEexJPGlxPK1PpgKjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3 DQEBBQUAA4IBAQBGFRiJslcX0aJkwZpzTwSUdgcfKbpvNEbCNtVohfQVTI4a/oN5 U+yqDZJg3vOaOuiAZqyHcIlZ8qyesCgRN314Tl4/JQ++CW8mKj1meTgo5YFxcZYm T9vsI3C+Nzn84DINgI9mx6yktIt3QOKZRDpzyPkUzxsyJ8J427DaimDrjTR+fTwD 1Dh09xeeMnSa5zeV1HEDyJTqCXutLetwQ/IyfmMBhIx+nvB5f67pz/m+Dv6V0r3I p4HCcdnDUDGJbfqtoqsAATQQWO+WWuswB6mOhDbvPTxhRpZq6AkgWqv4S+u3M2GO r5p9FrBgavAw5bKO54C0oQKpN/5fta5l6Ws0 -----END CERTIFICATE----- thrift-0.19.0/lib/nodejs/test/server.js0000644000000000000000000000731514303740367017767 0ustar00rootroot00000000000000#!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const fs = require("fs"); const path = require("path"); const thrift = require("../lib/thrift"); const program = require("commander"); const helpers = require("./helpers"); program .option( "-p, --protocol ", "Set thrift protocol (binary|compact|json)", "binary" ) .option( "-t, --transport ", "Set thrift transport (buffered|framed|http)", "buffered" ) .option("--ssl", "use ssl transport") .option("--port ", "Set thrift server port", 9090) .option("--domain-socket ", "Set thift server unix domain socket") .option( "-t, --type ", "Select server type (http|multiplex|tcp|websocket)", "tcp" ) .option("--callback", "test with callback style functions") .option("--es6", "Use es6 code") .option("--es5", "Use es5 code") .parse(process.argv); const ThriftTest = require(`./${helpers.genPath}/ThriftTest`); const SecondService = require(`./${helpers.genPath}/SecondService`); const { ThriftTestHandler } = require("./test_handler"); const port = program.port; const domainSocket = program.domainSocket; const ssl = program.ssl; let type = program.type; if (program.transport === "http") { program.transport = "buffered"; type = "http"; } else if (program.transport === "websocket") { program.transport = "buffered"; type = "websocket"; } let options = { transport: helpers.transports[program.transport], protocol: helpers.protocols[program.protocol] }; if (type === "http" || type === "websocket") { options.handler = ThriftTestHandler; options.processor = ThriftTest; options = { services: { "/test": options }, cors: { "*": true } }; } let processor; if (type === "multiplex") { const SecondServiceHandler = { secondtestString: function(thing, result) { console.log('testString("' + thing + '")'); result(null, 'testString("' + thing + '")'); } }; processor = new thrift.MultiplexedProcessor(); processor.registerProcessor( "ThriftTest", new ThriftTest.Processor(ThriftTestHandler) ); processor.registerProcessor( "SecondService", new SecondService.Processor(SecondServiceHandler) ); } if (ssl) { if ( type === "tcp" || type === "multiplex" || type === "http" || type === "websocket" ) { options.tls = { key: fs.readFileSync(path.resolve(__dirname, "server.key")), cert: fs.readFileSync(path.resolve(__dirname, "server.crt")) }; } } let server; if (type === "tcp") { server = thrift.createServer(ThriftTest, ThriftTestHandler, options); } else if (type === "multiplex") { server = thrift.createMultiplexServer(processor, options); } else if (type === "http" || type === "websocket") { server = thrift.createWebServer(options); } if (domainSocket) { server.listen(domainSocket); } else if ( type === "tcp" || type === "multiplex" || type === "http" || type === "websocket" ) { server.listen(port); } thrift-0.19.0/lib/nodejs/test/helpers.js0000644000000000000000000000242714303740367020122 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ "use strict"; const thrift = require("../lib/thrift"); module.exports.transports = { buffered: thrift.TBufferedTransport, framed: thrift.TFramedTransport }; module.exports.protocols = { json: thrift.TJSONProtocol, binary: thrift.TBinaryProtocol, compact: thrift.TCompactProtocol, header: thrift.THeaderProtocol }; module.exports.ecmaMode = process.argv.includes("--es6") ? "es6" : "es5"; module.exports.genPath = process.argv.includes("--es6") ? "gen-nodejs-es6" : "gen-nodejs"; thrift-0.19.0/lib/nodejs/test/test_header_payload0000644000000000000000000000011414303740367022034 0ustar00rootroot00000000000000HÿParentshoobarTraceabcde€addthrift-0.19.0/lib/nodejs/test/int64.test.js0000644000000000000000000000653114303740367020402 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const Int64 = require("node-int64"); const JSONInt64 = require("json-int64"); const i64types = require("./gen-nodejs-es6/Int64Test_types.js"); const test = require("tape"); const cases = { "should correctly generate Int64 constants": function(assert) { const EXPECTED_SMALL_INT64_AS_NUMBER = 42; const EXPECTED_SMALL_INT64 = new Int64(42); const EXPECTED_MAX_JS_SAFE_INT64 = new Int64(Number.MAX_SAFE_INTEGER); const EXPECTED_MIN_JS_SAFE_INT64 = new Int64(Number.MIN_SAFE_INTEGER); const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64 = new Int64("0020000000000000"); // hex-encoded const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement const EXPECTED_MAX_SIGNED_INT64 = new Int64("7fffffffffffffff"); // hex-encoded const EXPECTED_MIN_SIGNED_INT64 = new Int64("8000000000000000"); // hex-encoded 2's complement const EXPECTED_INT64_LIST = [ EXPECTED_SMALL_INT64, EXPECTED_MAX_JS_SAFE_INT64, EXPECTED_MIN_JS_SAFE_INT64, EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, EXPECTED_MAX_SIGNED_INT64, EXPECTED_MIN_SIGNED_INT64 ]; assert.ok(EXPECTED_SMALL_INT64.equals(i64types.SMALL_INT64)); assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(i64types.MAX_JS_SAFE_INT64)); assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(i64types.MIN_JS_SAFE_INT64)); assert.ok( EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( i64types.MAX_JS_SAFE_PLUS_ONE_INT64 ) ); assert.ok( EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( i64types.MIN_JS_SAFE_MINUS_ONE_INT64 ) ); assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(i64types.MAX_SIGNED_INT64)); assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(i64types.MIN_SIGNED_INT64)); assert.equal( EXPECTED_SMALL_INT64_AS_NUMBER, i64types.SMALL_INT64.toNumber() ); assert.equal( Number.MAX_SAFE_INTEGER, i64types.MAX_JS_SAFE_INT64.toNumber() ); assert.equal( Number.MIN_SAFE_INTEGER, i64types.MIN_JS_SAFE_INT64.toNumber() ); for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); } for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { const int64Object = EXPECTED_INT64_LIST[i]; assert.ok( i64types.INT64_2_INT64_MAP[ JSONInt64.toDecimalString(int64Object) ].equals(int64Object) ); } assert.end(); } }; Object.keys(cases).forEach(function(caseName) { test(caseName, cases[caseName]); }); thrift-0.19.0/lib/nodejs/test/server.key0000644000000000000000000000325014303740367020135 0ustar00rootroot00000000000000-----BEGIN PRIVATE KEY----- MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCqE9TE9wEXp5LR tLQVDSGQGV78+7ZtP/I/ZaJ6Q6ZGlfxDFvZjFF73seNhAvlKlYm/jflIHYLnNOCy SN8I2Xw6L9MbC+jvwkEKfQo4eDoxZnOZjNF5J1/lZtBeOowMkhhzBMH1Rds351/H jKNg6ZKg2Cldd0j7HbDtEixOLgLbPRpBcaYrLrNMasf3Hal+x8/b8ue28x93HSQB GmZmMIUwAinEu/fNP4lLGl/0kZb76TnyRpYSPYojtS6CnkH+QLYnsRREXJYwD1Xk u62LipkXwCkRTnZ5nUsDMX6FPKgjQFQCWDXG/N096+PRUQAChhrXsJ+gF3NqWtDm trhVQF4nAgMBAAECggEAW/y52YYW6ypROGbZ94DQpFV0kLO7qT8q0Ksxw5sPNaIt fEPRIymDa8ikyHWJS5Oxmw84wo5jnJV26jaLmwe2Lupq7Xf1lqej8f5LJtuv7cQR xfzp1vM65KJFFJHp6WqjGqJ6HSSZOpVDsnQYcXQjQCdpyAmaSWd3p+FqYSZ1mQmD bFNI7jqpczWSZhTdotQ7p7Hn9TVCehflP3yGIB3bQ+wCcCB85dOBz201L+YgaIck Sz43A4NvWaQIRLRDw7s9GW4jY5T0Jv282WIeAlVpVxLIwu48r4R4yGTIx9Ydowvq 57+Y5iPPjAXxu0V9t00oS3bYxDaKh2DUfc/5zowq8QKBgQDYNVPXmaG0aIH4vjQ9 7fRdw/UDkYcQbn6CnglQOu77/S8ogQzpKCVJgJgkZNqOVtQMEPzekGEcLTbje1gU 8Bky2k+PL9UwbFy0emnOVh4rqrNXHsRvJcehNT/PRb5hjF3MUMFV/0iD4b+naFaE jrSWiZ2ZXj2qfwAK52GFbtOuBQKBgQDJYQuGiY0r22E4waJmCSKczoBT3cwlVzWj V2ljgA9RHLNTVkvNNYQLGu2qngFrtwpeaSnsMDerVG4wKAQWyCnYzxVrlnC4uDrJ HXuFEltBWi9Ffbgfsnd3749AT0oBP1NT2tMleguyf5DFgjCR3VRJLdrVaaZ8row/ LqKcFMqnOwKBgB+OIO99l7E584Y3VG6ZdSneOLtNmRXX2pT7tcZE465ZdHGH7Dd3 SYHhx9K/+Xn+yDH+pLli/xlarAEldmSP6k2WuTfftlC78AfTOfAId5zN7CDR9791 Fx67I9X/itq33tS8EIuZl57P6uXm/4GXRloWOa8xpvRkVsBApuYPl8t1AoGATQDS y2sllDObBXzlgGbV2WgNIgSZ311toTv3jJiXQsjauW8yJRHln+l4H9mzaWDgkiFc ang1kUoDqF5k0eFQPxtQcYdhKwEnWWfwp33RbzfxA32DPnubuzzbZhfrkHaKgnIW cyor9uFYlm2l7ODZLfJez2RKyTplXnOSsmQw6akCgYAz3dj9Hskyj+HVJ+ht1OcE c7ai/ESkSA7Vajp0tjJp0EKjW/zq8DvUSXOtcdnJgkKycFluLwbmnaN4txBds1C1 Qr8Rt2sUCCBNZe1L6DHe3XBdbkJe9sgZVNTjtUSQrzy8UhvsCqG4YWeCu07Szcbc rdPUV9/uQkdx8VrShxlD8A== -----END PRIVATE KEY----- thrift-0.19.0/lib/nodejs/test/deep-constructor.test.js0000644000000000000000000002465314303740367022743 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const ttypes = require("./gen-nodejs/JsDeepConstructorTest_types"); const thrift = require("thrift"); const test = require("tape"); const bufferEquals = require("buffer-equals"); function serializeBinary(data) { let buff; const transport = new thrift.TBufferedTransport(null, function(msg) { buff = msg; }); const prot = new thrift.TBinaryProtocol(transport); data.write(prot); prot.flush(); return buff; } function deserializeBinary(serialized, type) { const t = new thrift.TFramedTransport(serialized); const p = new thrift.TBinaryProtocol(t); const data = new type(); data.read(p); return data; } function serializeJSON(data) { let buff; const transport = new thrift.TBufferedTransport(null, function(msg) { buff = msg; }); const protocol = new thrift.TJSONProtocol(transport); protocol.writeMessageBegin("", 0, 0); data.write(protocol); protocol.writeMessageEnd(); protocol.flush(); return buff; } function deserializeJSON(serialized, type) { const transport = new thrift.TFramedTransport(serialized); const protocol = new thrift.TJSONProtocol(transport); protocol.readMessageBegin(); const data = new type(); data.read(protocol); protocol.readMessageEnd(); return data; } function createThriftObj() { return new ttypes.Complex({ struct_field: new ttypes.Simple({ value: "a" }), struct_list_field: [ new ttypes.Simple({ value: "b" }), new ttypes.Simple({ value: "c" }) ], struct_set_field: [ new ttypes.Simple({ value: "d" }), new ttypes.Simple({ value: "e" }) ], struct_map_field: { A: new ttypes.Simple({ value: "f" }), B: new ttypes.Simple({ value: "g" }) }, struct_nested_containers_field: [ [ { C: [ new ttypes.Simple({ value: "h" }), new ttypes.Simple({ value: "i" }) ] } ] ], struct_nested_containers_field2: { D: [ { DA: new ttypes.Simple({ value: "j" }) }, { DB: new ttypes.Simple({ value: "k" }) } ] }, list_of_list_field: [ ["l00", "l01", "l02"], ["l10", "l11", "l12"], ["l20", "l21", "l22"] ], list_of_list_of_list_field: [ [ ["m000", "m001", "m002"], ["m010", "m011", "m012"], ["m020", "m021", "m022"] ], [ ["m100", "m101", "m102"], ["m110", "m111", "m112"], ["m120", "m121", "m122"] ], [ ["m200", "m201", "m202"], ["m210", "m211", "m212"], ["m220", "m221", "m222"] ] ] }); } function createJsObj() { return { struct_field: { value: "a" }, struct_list_field: [{ value: "b" }, { value: "c" }], struct_set_field: [{ value: "d" }, { value: "e" }], struct_map_field: { A: { value: "f" }, B: { value: "g" } }, struct_nested_containers_field: [ [ { C: [{ value: "h" }, { value: "i" }] } ] ], struct_nested_containers_field2: { D: [ { DA: { value: "j" } }, { DB: { value: "k" } } ] }, list_of_list_field: [ ["l00", "l01", "l02"], ["l10", "l11", "l12"], ["l20", "l21", "l22"] ], list_of_list_of_list_field: [ [ ["m000", "m001", "m002"], ["m010", "m011", "m012"], ["m020", "m021", "m022"] ], [ ["m100", "m101", "m102"], ["m110", "m111", "m112"], ["m120", "m121", "m122"] ], [ ["m200", "m201", "m202"], ["m210", "m211", "m212"], ["m220", "m221", "m222"] ] ] }; } function assertValues(obj, assert) { assert.equals(obj.struct_field.value, "a"); assert.equals(obj.struct_list_field[0].value, "b"); assert.equals(obj.struct_list_field[1].value, "c"); assert.equals(obj.struct_set_field[0].value, "d"); assert.equals(obj.struct_set_field[1].value, "e"); assert.equals(obj.struct_map_field.A.value, "f"); assert.equals(obj.struct_map_field.B.value, "g"); assert.equals(obj.struct_nested_containers_field[0][0].C[0].value, "h"); assert.equals(obj.struct_nested_containers_field[0][0].C[1].value, "i"); assert.equals(obj.struct_nested_containers_field2.D[0].DA.value, "j"); assert.equals(obj.struct_nested_containers_field2.D[1].DB.value, "k"); assert.equals(obj.list_of_list_field[0][0], "l00"); assert.equals(obj.list_of_list_field[0][1], "l01"); assert.equals(obj.list_of_list_field[0][2], "l02"); assert.equals(obj.list_of_list_field[1][0], "l10"); assert.equals(obj.list_of_list_field[1][1], "l11"); assert.equals(obj.list_of_list_field[1][2], "l12"); assert.equals(obj.list_of_list_field[2][0], "l20"); assert.equals(obj.list_of_list_field[2][1], "l21"); assert.equals(obj.list_of_list_field[2][2], "l22"); assert.equals(obj.list_of_list_of_list_field[0][0][0], "m000"); assert.equals(obj.list_of_list_of_list_field[0][0][1], "m001"); assert.equals(obj.list_of_list_of_list_field[0][0][2], "m002"); assert.equals(obj.list_of_list_of_list_field[0][1][0], "m010"); assert.equals(obj.list_of_list_of_list_field[0][1][1], "m011"); assert.equals(obj.list_of_list_of_list_field[0][1][2], "m012"); assert.equals(obj.list_of_list_of_list_field[0][2][0], "m020"); assert.equals(obj.list_of_list_of_list_field[0][2][1], "m021"); assert.equals(obj.list_of_list_of_list_field[0][2][2], "m022"); assert.equals(obj.list_of_list_of_list_field[1][0][0], "m100"); assert.equals(obj.list_of_list_of_list_field[1][0][1], "m101"); assert.equals(obj.list_of_list_of_list_field[1][0][2], "m102"); assert.equals(obj.list_of_list_of_list_field[1][1][0], "m110"); assert.equals(obj.list_of_list_of_list_field[1][1][1], "m111"); assert.equals(obj.list_of_list_of_list_field[1][1][2], "m112"); assert.equals(obj.list_of_list_of_list_field[1][2][0], "m120"); assert.equals(obj.list_of_list_of_list_field[1][2][1], "m121"); assert.equals(obj.list_of_list_of_list_field[1][2][2], "m122"); assert.equals(obj.list_of_list_of_list_field[2][0][0], "m200"); assert.equals(obj.list_of_list_of_list_field[2][0][1], "m201"); assert.equals(obj.list_of_list_of_list_field[2][0][2], "m202"); assert.equals(obj.list_of_list_of_list_field[2][1][0], "m210"); assert.equals(obj.list_of_list_of_list_field[2][1][1], "m211"); assert.equals(obj.list_of_list_of_list_field[2][1][2], "m212"); assert.equals(obj.list_of_list_of_list_field[2][2][0], "m220"); assert.equals(obj.list_of_list_of_list_field[2][2][1], "m221"); assert.equals(obj.list_of_list_of_list_field[2][2][2], "m222"); } function createTestCases(serialize, deserialize) { const cases = { "Serialize/deserialize should return equal object": function(assert) { const tObj = createThriftObj(); const received = deserialize(serialize(tObj), ttypes.Complex); assert.ok(tObj !== received, "not the same object"); assert.deepEqual(tObj, received); assert.end(); }, "Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects": function( assert ) { const tObj1 = createThriftObj(); const tObj2 = new ttypes.Complex(createJsObj()); assertValues(tObj2, assert); const s1 = serialize(tObj1); const s2 = serialize(tObj2); assert.ok(bufferEquals(s1, s2)); assert.end(); }, "Modifications to args object should not affect constructed Thrift object": function( assert ) { const args = createJsObj(); assertValues(args, assert); const tObj = new ttypes.Complex(args); assertValues(tObj, assert); args.struct_field.value = "ZZZ"; args.struct_list_field[0].value = "ZZZ"; args.struct_list_field[1].value = "ZZZ"; args.struct_set_field[0].value = "ZZZ"; args.struct_set_field[1].value = "ZZZ"; args.struct_map_field.A.value = "ZZZ"; args.struct_map_field.B.value = "ZZZ"; args.struct_nested_containers_field[0][0].C[0] = "ZZZ"; args.struct_nested_containers_field[0][0].C[1] = "ZZZ"; args.struct_nested_containers_field2.D[0].DA = "ZZZ"; args.struct_nested_containers_field2.D[0].DB = "ZZZ"; assertValues(tObj, assert); assert.end(); }, "nulls are ok": function(assert) { const tObj = new ttypes.Complex({ struct_field: null, struct_list_field: null, struct_set_field: null, struct_map_field: null, struct_nested_containers_field: null, struct_nested_containers_field2: null }); const received = deserialize(serialize(tObj), ttypes.Complex); assert.strictEqual(tObj.struct_field, null); assert.ok(tObj !== received); assert.deepEqual(tObj, received); assert.end(); }, "Can make list with objects": function(assert) { const tObj = new ttypes.ComplexList({ struct_list_field: [new ttypes.Complex({})] }); const innerObj = tObj.struct_list_field[0]; assert.ok(innerObj instanceof ttypes.Complex); assert.strictEqual(innerObj.struct_field, null); assert.strictEqual(innerObj.struct_list_field, null); assert.strictEqual(innerObj.struct_set_field, null); assert.strictEqual(innerObj.struct_map_field, null); assert.strictEqual(innerObj.struct_nested_containers_field, null); assert.strictEqual(innerObj.struct_nested_containers_field2, null); assert.end(); } }; return cases; } function run(name, cases) { Object.keys(cases).forEach(function(caseName) { test(name + ": " + caseName, cases[caseName]); }); } run("binary", createTestCases(serializeBinary, deserializeBinary)); run("json", createTestCases(serializeJSON, deserializeJSON)); thrift-0.19.0/lib/nodejs/test/episodic-code-generation-test/0000777000000000000000000000000014303740367023736 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json0000644000000000000000000000004014303740367032406 0ustar00rootroot00000000000000{ "name": "types-package" } thrift-0.19.0/lib/nodejs/test/episodic-code-generation-test/server.js0000644000000000000000000000316214303740367025600 0ustar00rootroot00000000000000#!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const thrift = require("../../lib/thrift"); const program = require("commander"); program .option("--port ", "Set the thrift server port", 9090) .parse(process.argv); const Service = require("./gen-2/second-episode/gen-nodejs/Service"); const Types = require("types-package/first-episode/Types_types"); const port = program.port; const options = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol }; const ServiceHandler = { testEpisode: function(receivedType1Object) { const type1Object = new Types.Type1(); type1Object.number = receivedType1Object.number + 1; type1Object.message = receivedType1Object.message + " [Hello from the server]"; return type1Object; } }; const server = thrift.createServer(Service, ServiceHandler, options); server.listen(port); thrift-0.19.0/lib/nodejs/test/episodic-code-generation-test/client.js0000644000000000000000000000455014303740367025552 0ustar00rootroot00000000000000#!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const assert = require("assert"); const test = require("tape"); const thrift = require("thrift"); const program = require("commander"); program .option("--host ", "Set the thrift server host to connect", "localhost") .option("--port ", "Set the thrift server port number to connect", 9090) .parse(process.argv); const Service = require("./gen-2/second-episode/gen-nodejs/Service"); const Types = require("types-package/first-episode/Types_types"); const host = program.host; const port = program.port; const options = { transport: thrift.TBufferedTransport, protocol: thrift.TJSONProtocol }; const connection = thrift.createConnection(host, port, options); const testDriver = function(client, callback) { test("NodeJS episodic compilation client-server test", function(assert) { const type1Object = new Types.Type1(); type1Object.number = 42; type1Object.message = "The answer"; client.testEpisode(type1Object, function(err, response) { assert.error(err, "no callback error"); assert.equal(response.number, type1Object.number + 1); assert.equal( response.message, type1Object.message + " [Hello from the server]" ); assert.end(); callback("Server successfully tested"); }); }); }; connection.on("error", function(err) { assert(false, err); }); const client = thrift.createClient(Service, connection); runTests(); function runTests() { testDriver(client, function(status) { console.log(status); connection.destroy(); }); } exports.expressoTest = function() {}; thrift-0.19.0/lib/nodejs/test/binary.test.js0000644000000000000000000001440714303740367020723 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const test = require("tape"); const binary = require("thrift/binary"); const cases = { "Should read signed byte": function(assert) { assert.equal(1, binary.readByte(0x01)); assert.equal(-1, binary.readByte(0xff)); assert.equal(127, binary.readByte(0x7f)); assert.equal(-128, binary.readByte(0x80)); assert.end(); }, "Should write byte": function(assert) { //Protocol simply writes to the buffer. Nothing to test.. yet. assert.ok(true); assert.end(); }, "Should read I16": function(assert) { assert.equal(0, binary.readI16([0x00, 0x00])); assert.equal(1, binary.readI16([0x00, 0x01])); assert.equal(-1, binary.readI16([0xff, 0xff])); // Min I16 assert.equal(-32768, binary.readI16([0x80, 0x00])); // Max I16 assert.equal(32767, binary.readI16([0x7f, 0xff])); assert.end(); }, "Should write I16": function(assert) { assert.deepEqual([0x00, 0x00], binary.writeI16([], 0)); assert.deepEqual([0x00, 0x01], binary.writeI16([], 1)); assert.deepEqual([0xff, 0xff], binary.writeI16([], -1)); // Min I16 assert.deepEqual([0x80, 0x00], binary.writeI16([], -32768)); // Max I16 assert.deepEqual([0x7f, 0xff], binary.writeI16([], 32767)); assert.end(); }, "Should read I32": function(assert) { assert.equal(0, binary.readI32([0x00, 0x00, 0x00, 0x00])); assert.equal(1, binary.readI32([0x00, 0x00, 0x00, 0x01])); assert.equal(-1, binary.readI32([0xff, 0xff, 0xff, 0xff])); // Min I32 assert.equal(-2147483648, binary.readI32([0x80, 0x00, 0x00, 0x00])); // Max I32 assert.equal(2147483647, binary.readI32([0x7f, 0xff, 0xff, 0xff])); assert.end(); }, "Should write I32": function(assert) { assert.deepEqual([0x00, 0x00, 0x00, 0x00], binary.writeI32([], 0)); assert.deepEqual([0x00, 0x00, 0x00, 0x01], binary.writeI32([], 1)); assert.deepEqual([0xff, 0xff, 0xff, 0xff], binary.writeI32([], -1)); // Min I32 assert.deepEqual( [0x80, 0x00, 0x00, 0x00], binary.writeI32([], -2147483648) ); // Max I32 assert.deepEqual([0x7f, 0xff, 0xff, 0xff], binary.writeI32([], 2147483647)); assert.end(); }, "Should read doubles": function(assert) { assert.equal( 0, binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.equal( 0, binary.readDouble([0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.equal( 1, binary.readDouble([0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.equal( 2, binary.readDouble([0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.equal( -2, binary.readDouble([0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.equal( Math.PI, binary.readDouble([0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18]) ); assert.equal( Infinity, binary.readDouble([0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.equal( -Infinity, binary.readDouble([0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); assert.ok( isNaN(binary.readDouble([0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])) ); assert.equal( 1 / 3, binary.readDouble([0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55]) ); // Min subnormal positive double assert.equal( 4.9406564584124654e-324, binary.readDouble([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]) ); // Min normal positive double assert.equal( 2.2250738585072014e-308, binary.readDouble([0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) ); // Max positive double assert.equal( 1.7976931348623157e308, binary.readDouble([0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) ); assert.end(); }, "Should write doubles": function(assert) { assert.deepEqual( [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 0) ); assert.deepEqual( [0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 1) ); assert.deepEqual( [0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 2) ); assert.deepEqual( [0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], -2) ); assert.deepEqual( [0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], binary.writeDouble([], Math.PI) ); assert.deepEqual( [0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], Infinity) ); assert.deepEqual( [0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], -Infinity) ); assert.deepEqual( [0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], NaN) ); assert.deepEqual( [0x3f, 0xd5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55], binary.writeDouble([], 1 / 3) ); // Min subnormal positive double assert.deepEqual( [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01], binary.writeDouble([], 4.9406564584124654e-324) ); // Min normal positive double assert.deepEqual( [0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], binary.writeDouble([], 2.2250738585072014e-308) ); // Max positive double assert.deepEqual( [0x7f, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], binary.writeDouble([], 1.7976931348623157e308) ); assert.end(); } }; Object.keys(cases).forEach(function(caseName) { test(caseName, cases[caseName]); }); thrift-0.19.0/lib/nodejs/test/client.js0000644000000000000000000001163514303740367017737 0ustar00rootroot00000000000000#!/usr/bin/env node /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ const assert = require("assert"); const thrift = require("thrift"); const helpers = require("./helpers"); const ThriftTest = require(`./${helpers.genPath}/ThriftTest`); const ThriftTestDriver = require("./test_driver").ThriftTestDriver; const ThriftTestDriverPromise = require("./test_driver") .ThriftTestDriverPromise; const SecondService = require(`./${helpers.genPath}/SecondService`); const program = require("commander"); program .option( "-p, --protocol ", "Set thrift protocol (binary|compact|json) [protocol]" ) .option( "-t, --transport ", "Set thrift transport (buffered|framed|http) [transport]" ) .option("--port ", "Set thrift server port number to connect", 9090) .option("--host ", "Set thrift server host to connect", "localhost") .option( "--domain-socket ", "Set thrift server unix domain socket to connect" ) .option("--ssl", "use SSL transport") .option("--callback", "test with callback style functions") .option( "-t, --type ", "Select server type (http|multiplex|tcp|websocket)", "tcp" ) .option("--es6", "Use es6 code") .option("--es5", "Use es5 code") .parse(process.argv); const host = program.host; const port = program.port; const domainSocket = program.domainSocket; const ssl = program.ssl; let type = program.type; /* for compatibility with cross test invocation for http transport testing */ if (program.transport === "http") { program.transport = "buffered"; type = "http"; } if (program.transport === "websocket") { program.transport = "buffered"; type = "websocket"; } const options = { transport: helpers.transports[program.transport], protocol: helpers.protocols[program.protocol] }; if (type === "http" || type === "websocket") { options.path = "/test"; } if (type === "http") { options.headers = { Connection: "close" }; } if (ssl) { if (type === "tcp" || type === "multiplex") { options.rejectUnauthorized = false; } else if (type === "http") { options.nodeOptions = { rejectUnauthorized: false }; options.https = true; } else if (type === "websocket") { options.wsOptions = { rejectUnauthorized: false }; options.secure = true; } } let connection; let client; const testDriver = program.callback ? ThriftTestDriver : ThriftTestDriverPromise; if (helpers.ecmaMode === "es6" && program.callback) { console.log("ES6 does not support callback style"); process.exit(0); } if (type === "tcp" || type === "multiplex") { if (domainSocket) { connection = thrift.createUDSConnection(domainSocket, options); } else { connection = ssl ? thrift.createSSLConnection(host, port, options) : thrift.createConnection(host, port, options); } } else if (type === "http") { if (domainSocket) { connection = thrift.createHttpUDSConnection(domainSocket, options); } else { connection = thrift.createHttpConnection(host, port, options); } } else if (type === "websocket") { connection = thrift.createWSConnection(host, port, options); connection.open(); } connection.on("error", function(err) { assert(false, err); }); if (type === "tcp") { client = thrift.createClient(ThriftTest, connection); runTests(); } else if (type === "multiplex") { const mp = new thrift.Multiplexer(); client = mp.createClient("ThriftTest", ThriftTest, connection); const secondclient = mp.createClient( "SecondService", SecondService, connection ); connection.on("connect", function() { secondclient.secondtestString("Test", function(err, response) { assert(!err); assert.equal('testString("Test")', response); }); runTests(); }); } else if (type === "http") { client = thrift.createHttpClient(ThriftTest, connection); runTests(); } else if (type === "websocket") { client = thrift.createWSClient(ThriftTest, connection); runTests(); } function runTests() { testDriver(client, function(status) { console.log(status); if (type !== "http" && type !== "websocket") { connection.end(); } if (type !== "multiplex") { process.exit(0); } }); } exports.expressoTest = function() {}; thrift-0.19.0/lib/nodejs/lib/0000777000000000000000000000000014062750226015705 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodejs/lib/thrift/0000777000000000000000000000000014452237057017212 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodejs/lib/thrift/browser.js0000644000000000000000000000420114303740367021222 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ exports.Thrift = require('./thrift'); var wsConnection = require('./ws_connection'); exports.WSConnection = wsConnection.WSConnection; exports.createWSConnection = wsConnection.createWSConnection; exports.createWSClient = wsConnection.createWSClient; var xhrConnection = require('./xhr_connection'); exports.XHRConnection = xhrConnection.XHRConnection; exports.createXHRConnection = xhrConnection.createXHRConnection; exports.createXHRClient = xhrConnection.createXHRClient; var ohosConnection = require('./ohos_connection'); exports.OhosConnection = ohosConnection.OhosConnection; exports.createOhosConnection = ohosConnection.createOhosConnection; exports.createOhosClient = ohosConnection.createOhosClient; exports.Int64 = require('node-int64'); exports.Q = require('q'); var mpxProtocol = require('./multiplexed_protocol'); exports.Multiplexer = mpxProtocol.Multiplexer; /* * Export transport and protocol so they can be used outside of a * cassandra/server context */ exports.TBufferedTransport = require('./buffered_transport'); exports.TFramedTransport = require('./framed_transport'); exports.TWebSocketTransport = require('./ws_transport'); exports.Protocol = require('./json_protocol'); exports.TJSONProtocol = require('./json_protocol'); exports.TBinaryProtocol = require('./binary_protocol'); exports.TCompactProtocol = require('./compact_protocol'); thrift-0.19.0/lib/nodejs/lib/thrift/compact_protocol.js0000644000000000000000000006256714303740367023131 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var log = require('./log'); var Int64 = require('node-int64'); var Thrift = require('./thrift'); var Type = Thrift.Type; module.exports = TCompactProtocol; var POW_8 = Math.pow(2, 8); var POW_24 = Math.pow(2, 24); var POW_32 = Math.pow(2, 32); var POW_40 = Math.pow(2, 40); var POW_48 = Math.pow(2, 48); var POW_52 = Math.pow(2, 52); var POW_1022 = Math.pow(2, 1022); /** * Constructor Function for the Compact Protocol. * @constructor * @param {object} [trans] - The underlying transport to read/write. * @classdesc The Apache Thrift Protocol layer performs serialization * of base types, the compact protocol serializes data in binary * form with minimal space used for scalar values. */ function TCompactProtocol(trans) { this.trans = trans; this.lastField_ = []; this.lastFieldId_ = 0; this.string_limit_ = 0; this.string_buf_ = null; this.string_buf_size_ = 0; this.container_limit_ = 0; this.booleanField_ = { name: null, hasBoolValue: false }; this.boolValue_ = { hasBoolValue: false, boolValue: false }; }; // // Compact Protocol Constants // /** * Compact Protocol ID number. * @readonly * @const {number} PROTOCOL_ID */ TCompactProtocol.PROTOCOL_ID = -126; //1000 0010 /** * Compact Protocol version number. * @readonly * @const {number} VERSION_N */ TCompactProtocol.VERSION_N = 1; /** * Compact Protocol version mask for combining protocol version and message type in one byte. * @readonly * @const {number} VERSION_MASK */ TCompactProtocol.VERSION_MASK = 0x1f; //0001 1111 /** * Compact Protocol message type mask for combining protocol version and message type in one byte. * @readonly * @const {number} TYPE_MASK */ TCompactProtocol.TYPE_MASK = -32; //1110 0000 /** * Compact Protocol message type bits for ensuring message type bit size. * @readonly * @const {number} TYPE_BITS */ TCompactProtocol.TYPE_BITS = 7; //0000 0111 /** * Compact Protocol message type shift amount for combining protocol version and message type in one byte. * @readonly * @const {number} TYPE_SHIFT_AMOUNT */ TCompactProtocol.TYPE_SHIFT_AMOUNT = 5; /** * Compact Protocol type IDs used to keep type data within one nibble. * @readonly * @property {number} CT_STOP - End of a set of fields. * @property {number} CT_BOOLEAN_TRUE - Flag for Boolean field with true value (packed field and value). * @property {number} CT_BOOLEAN_FALSE - Flag for Boolean field with false value (packed field and value). * @property {number} CT_BYTE - Signed 8 bit integer. * @property {number} CT_I16 - Signed 16 bit integer. * @property {number} CT_I32 - Signed 32 bit integer. * @property {number} CT_I64 - Signed 64 bit integer (2^53 max in JavaScript). * @property {number} CT_DOUBLE - 64 bit IEEE 854 floating point. * @property {number} CT_BINARY - Array of bytes (used for strings also). * @property {number} CT_LIST - A collection type (unordered). * @property {number} CT_SET - A collection type (unordered and without repeated values). * @property {number} CT_MAP - A collection type (map/associative-array/dictionary). * @property {number} CT_STRUCT - A multifield type. */ TCompactProtocol.Types = { CT_STOP: 0x00, CT_BOOLEAN_TRUE: 0x01, CT_BOOLEAN_FALSE: 0x02, CT_BYTE: 0x03, CT_I16: 0x04, CT_I32: 0x05, CT_I64: 0x06, CT_DOUBLE: 0x07, CT_BINARY: 0x08, CT_LIST: 0x09, CT_SET: 0x0A, CT_MAP: 0x0B, CT_STRUCT: 0x0C }; /** * Array mapping Compact type IDs to standard Thrift type IDs. * @readonly */ TCompactProtocol.TTypeToCType = [ TCompactProtocol.Types.CT_STOP, // T_STOP 0, // unused TCompactProtocol.Types.CT_BOOLEAN_TRUE, // T_BOOL TCompactProtocol.Types.CT_BYTE, // T_BYTE TCompactProtocol.Types.CT_DOUBLE, // T_DOUBLE 0, // unused TCompactProtocol.Types.CT_I16, // T_I16 0, // unused TCompactProtocol.Types.CT_I32, // T_I32 0, // unused TCompactProtocol.Types.CT_I64, // T_I64 TCompactProtocol.Types.CT_BINARY, // T_STRING TCompactProtocol.Types.CT_STRUCT, // T_STRUCT TCompactProtocol.Types.CT_MAP, // T_MAP TCompactProtocol.Types.CT_SET, // T_SET TCompactProtocol.Types.CT_LIST, // T_LIST ]; // // Compact Protocol Utilities // /** * Returns the underlying transport layer. * @return {object} The underlying transport layer. */TCompactProtocol.prototype.getTransport = function() { return this.trans; }; /** * Lookup a Compact Protocol Type value for a given Thrift Type value. * N.B. Used only internally. * @param {number} ttype - Thrift type value * @returns {number} Compact protocol type value */ TCompactProtocol.prototype.getCompactType = function(ttype) { return TCompactProtocol.TTypeToCType[ttype]; }; /** * Lookup a Thrift Type value for a given Compact Protocol Type value. * N.B. Used only internally. * @param {number} type - Compact Protocol type value * @returns {number} Thrift Type value */ TCompactProtocol.prototype.getTType = function(type) { switch (type) { case Type.STOP: return Type.STOP; case TCompactProtocol.Types.CT_BOOLEAN_FALSE: case TCompactProtocol.Types.CT_BOOLEAN_TRUE: return Type.BOOL; case TCompactProtocol.Types.CT_BYTE: return Type.BYTE; case TCompactProtocol.Types.CT_I16: return Type.I16; case TCompactProtocol.Types.CT_I32: return Type.I32; case TCompactProtocol.Types.CT_I64: return Type.I64; case TCompactProtocol.Types.CT_DOUBLE: return Type.DOUBLE; case TCompactProtocol.Types.CT_BINARY: return Type.STRING; case TCompactProtocol.Types.CT_LIST: return Type.LIST; case TCompactProtocol.Types.CT_SET: return Type.SET; case TCompactProtocol.Types.CT_MAP: return Type.MAP; case TCompactProtocol.Types.CT_STRUCT: return Type.STRUCT; default: throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Unknown type: " + type); } return Type.STOP; }; // // Compact Protocol write operations // /** * Send any buffered bytes to the end point. */ TCompactProtocol.prototype.flush = function() { return this.trans.flush(); }; /** * Writes an RPC message header * @param {string} name - The method name for the message. * @param {number} type - The type of message (CALL, REPLY, EXCEPTION, ONEWAY). * @param {number} seqid - The call sequence number (if any). */ TCompactProtocol.prototype.writeMessageBegin = function(name, type, seqid) { this.writeByte(TCompactProtocol.PROTOCOL_ID); this.writeByte((TCompactProtocol.VERSION_N & TCompactProtocol.VERSION_MASK) | ((type << TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_MASK)); this.writeVarint32(seqid); this.writeString(name); // Record client seqid to find callback again if (this._seqid) { log.warning('SeqId already set', { 'name': name }); } else { this._seqid = seqid; this.trans.setCurrSeqId(seqid); } }; TCompactProtocol.prototype.writeMessageEnd = function() { }; TCompactProtocol.prototype.writeStructBegin = function(name) { this.lastField_.push(this.lastFieldId_); this.lastFieldId_ = 0; }; TCompactProtocol.prototype.writeStructEnd = function() { this.lastFieldId_ = this.lastField_.pop(); }; /** * Writes a struct field header * @param {string} name - The field name (not written with the compact protocol). * @param {number} type - The field data type (a normal Thrift field Type). * @param {number} id - The IDL field Id. */ TCompactProtocol.prototype.writeFieldBegin = function(name, type, id) { if (type != Type.BOOL) { return this.writeFieldBeginInternal(name, type, id, -1); } this.booleanField_.name = name; this.booleanField_.fieldType = type; this.booleanField_.fieldId = id; }; TCompactProtocol.prototype.writeFieldEnd = function() { }; TCompactProtocol.prototype.writeFieldStop = function() { this.writeByte(TCompactProtocol.Types.CT_STOP); }; /** * Writes a map collection header * @param {number} keyType - The Thrift type of the map keys. * @param {number} valType - The Thrift type of the map values. * @param {number} size - The number of k/v pairs in the map. */ TCompactProtocol.prototype.writeMapBegin = function(keyType, valType, size) { if (size === 0) { this.writeByte(0); } else { this.writeVarint32(size); this.writeByte(this.getCompactType(keyType) << 4 | this.getCompactType(valType)); } }; TCompactProtocol.prototype.writeMapEnd = function() { }; /** * Writes a list collection header * @param {number} elemType - The Thrift type of the list elements. * @param {number} size - The number of elements in the list. */ TCompactProtocol.prototype.writeListBegin = function(elemType, size) { this.writeCollectionBegin(elemType, size); }; TCompactProtocol.prototype.writeListEnd = function() { }; /** * Writes a set collection header * @param {number} elemType - The Thrift type of the set elements. * @param {number} size - The number of elements in the set. */ TCompactProtocol.prototype.writeSetBegin = function(elemType, size) { this.writeCollectionBegin(elemType, size); }; TCompactProtocol.prototype.writeSetEnd = function() { }; TCompactProtocol.prototype.writeBool = function(value) { if (this.booleanField_.name !== null) { // we haven't written the field header yet this.writeFieldBeginInternal(this.booleanField_.name, this.booleanField_.fieldType, this.booleanField_.fieldId, (value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE : TCompactProtocol.Types.CT_BOOLEAN_FALSE)); this.booleanField_.name = null; } else { // we're not part of a field, so just write the value this.writeByte((value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE : TCompactProtocol.Types.CT_BOOLEAN_FALSE)); } }; TCompactProtocol.prototype.writeByte = function(b) { this.trans.write(new Buffer([b])); }; TCompactProtocol.prototype.writeI16 = function(i16) { this.writeVarint32(this.i32ToZigzag(i16)); }; TCompactProtocol.prototype.writeI32 = function(i32) { this.writeVarint32(this.i32ToZigzag(i32)); }; TCompactProtocol.prototype.writeI64 = function(i64) { this.writeVarint64(this.i64ToZigzag(i64)); }; // Little-endian, unlike TBinaryProtocol TCompactProtocol.prototype.writeDouble = function(v) { var buff = new Buffer(8); var m, e, c; buff[7] = (v < 0 ? 0x80 : 0x00); v = Math.abs(v); if (v !== v) { // NaN, use QNaN IEEE format m = 2251799813685248; e = 2047; } else if (v === Infinity) { m = 0; e = 2047; } else { e = Math.floor(Math.log(v) / Math.LN2); c = Math.pow(2, -e); if (v * c < 1) { e--; c *= 2; } if (e + 1023 >= 2047) { // Overflow m = 0; e = 2047; } else if (e + 1023 >= 1) { // Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow m = (v*c-1) * POW_52; e += 1023; } else { // Denormalized - also catches the '0' case, somewhat by chance m = (v * POW_1022) * POW_52; e = 0; } } buff[6] = (e << 4) & 0xf0; buff[7] |= (e >> 4) & 0x7f; buff[0] = m & 0xff; m = Math.floor(m / POW_8); buff[1] = m & 0xff; m = Math.floor(m / POW_8); buff[2] = m & 0xff; m = Math.floor(m / POW_8); buff[3] = m & 0xff; m >>= 8; buff[4] = m & 0xff; m >>= 8; buff[5] = m & 0xff; m >>= 8; buff[6] |= m & 0x0f; this.trans.write(buff); }; TCompactProtocol.prototype.writeStringOrBinary = function(name, encoding, arg) { if (typeof arg === 'string') { this.writeVarint32(Buffer.byteLength(arg, encoding)) ; this.trans.write(new Buffer(arg, encoding)); } else if (arg instanceof Buffer || Object.prototype.toString.call(arg) == '[object Uint8Array]') { // Buffers in Node.js under Browserify may extend UInt8Array instead of // defining a new object. We detect them here so we can write them // correctly this.writeVarint32(arg.length); this.trans.write(arg); } else { throw new Error(name + ' called without a string/Buffer argument: ' + arg); } }; TCompactProtocol.prototype.writeString = function(arg) { this.writeStringOrBinary('writeString', 'utf8', arg); }; TCompactProtocol.prototype.writeBinary = function(arg) { this.writeStringOrBinary('writeBinary', 'binary', arg); }; // // Compact Protocol internal write methods // TCompactProtocol.prototype.writeFieldBeginInternal = function(name, fieldType, fieldId, typeOverride) { //If there's a type override, use that. var typeToWrite = (typeOverride == -1 ? this.getCompactType(fieldType) : typeOverride); //Check if we can delta encode the field id if (fieldId > this.lastFieldId_ && fieldId - this.lastFieldId_ <= 15) { //Include the type delta with the field ID this.writeByte((fieldId - this.lastFieldId_) << 4 | typeToWrite); } else { //Write separate type and ID values this.writeByte(typeToWrite); this.writeI16(fieldId); } this.lastFieldId_ = fieldId; }; TCompactProtocol.prototype.writeCollectionBegin = function(elemType, size) { if (size <= 14) { //Combine size and type in one byte if possible this.writeByte(size << 4 | this.getCompactType(elemType)); } else { this.writeByte(0xf0 | this.getCompactType(elemType)); this.writeVarint32(size); } }; /** * Write an i32 as a varint. Results in 1-5 bytes on the wire. */ TCompactProtocol.prototype.writeVarint32 = function(n) { var buf = new Buffer(5); var wsize = 0; while (true) { if ((n & ~0x7F) === 0) { buf[wsize++] = n; break; } else { buf[wsize++] = ((n & 0x7F) | 0x80); n = n >>> 7; } } var wbuf = new Buffer(wsize); buf.copy(wbuf,0,0,wsize); this.trans.write(wbuf); }; /** * Write an i64 as a varint. Results in 1-10 bytes on the wire. * N.B. node-int64 is always big endian */ TCompactProtocol.prototype.writeVarint64 = function(n) { if (typeof n === "number"){ n = new Int64(n); } if (! (n instanceof Int64)) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Expected Int64 or Number, found: " + n); } var buf = new Buffer(10); var wsize = 0; var hi = n.buffer.readUInt32BE(0, true); var lo = n.buffer.readUInt32BE(4, true); var mask = 0; while (true) { if (((lo & ~0x7F) === 0) && (hi === 0)) { buf[wsize++] = lo; break; } else { buf[wsize++] = ((lo & 0x7F) | 0x80); mask = hi << 25; lo = lo >>> 7; hi = hi >>> 7; lo = lo | mask; } } var wbuf = new Buffer(wsize); buf.copy(wbuf,0,0,wsize); this.trans.write(wbuf); }; /** * Convert l into a zigzag long. This allows negative numbers to be * represented compactly as a varint. */ TCompactProtocol.prototype.i64ToZigzag = function(l) { if (typeof l === 'string') { l = new Int64(parseInt(l, 10)); } else if (typeof l === 'number') { l = new Int64(l); } if (! (l instanceof Int64)) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Expected Int64 or Number, found: " + l); } var hi = l.buffer.readUInt32BE(0, true); var lo = l.buffer.readUInt32BE(4, true); var sign = hi >>> 31; hi = ((hi << 1) | (lo >>> 31)) ^ ((!!sign) ? 0xFFFFFFFF : 0); lo = (lo << 1) ^ ((!!sign) ? 0xFFFFFFFF : 0); return new Int64(hi, lo); }; /** * Convert n into a zigzag int. This allows negative numbers to be * represented compactly as a varint. */ TCompactProtocol.prototype.i32ToZigzag = function(n) { return (n << 1) ^ ((n & 0x80000000) ? 0xFFFFFFFF : 0); }; // // Compact Protocol read operations // TCompactProtocol.prototype.readMessageBegin = function() { //Read protocol ID var protocolId = this.trans.readByte(); if (protocolId != TCompactProtocol.PROTOCOL_ID) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad protocol identifier " + protocolId); } //Read Version and Type var versionAndType = this.trans.readByte(); var version = (versionAndType & TCompactProtocol.VERSION_MASK); if (version != TCompactProtocol.VERSION_N) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad protocol version " + version); } var type = ((versionAndType >> TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_BITS); //Read SeqId var seqid = this.readVarint32(); //Read name var name = this.readString(); return {fname: name, mtype: type, rseqid: seqid}; }; TCompactProtocol.prototype.readMessageEnd = function() { }; TCompactProtocol.prototype.readStructBegin = function() { this.lastField_.push(this.lastFieldId_); this.lastFieldId_ = 0; return {fname: ''}; }; TCompactProtocol.prototype.readStructEnd = function() { this.lastFieldId_ = this.lastField_.pop(); }; TCompactProtocol.prototype.readFieldBegin = function() { var fieldId = 0; var b = this.trans.readByte(b); var type = (b & 0x0f); if (type == TCompactProtocol.Types.CT_STOP) { return {fname: null, ftype: Thrift.Type.STOP, fid: 0}; } //Mask off the 4 MSB of the type header to check for field id delta. var modifier = ((b & 0x000000f0) >>> 4); if (modifier === 0) { //If not a delta read the field id. fieldId = this.readI16(); } else { //Recover the field id from the delta fieldId = (this.lastFieldId_ + modifier); } var fieldType = this.getTType(type); //Boolean are encoded with the type if (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE || type == TCompactProtocol.Types.CT_BOOLEAN_FALSE) { this.boolValue_.hasBoolValue = true; this.boolValue_.boolValue = (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE ? true : false); } //Save the new field for the next delta computation. this.lastFieldId_ = fieldId; return {fname: null, ftype: fieldType, fid: fieldId}; }; TCompactProtocol.prototype.readFieldEnd = function() { }; TCompactProtocol.prototype.readMapBegin = function() { var msize = this.readVarint32(); if (msize < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative map size"); } var kvType = 0; if (msize !== 0) { kvType = this.trans.readByte(); } var keyType = this.getTType((kvType & 0xf0) >>> 4); var valType = this.getTType(kvType & 0xf); return {ktype: keyType, vtype: valType, size: msize}; }; TCompactProtocol.prototype.readMapEnd = function() { }; TCompactProtocol.prototype.readListBegin = function() { var size_and_type = this.trans.readByte(); var lsize = (size_and_type >>> 4) & 0x0000000f; if (lsize == 15) { lsize = this.readVarint32(); } if (lsize < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative list size"); } var elemType = this.getTType(size_and_type & 0x0000000f); return {etype: elemType, size: lsize}; }; TCompactProtocol.prototype.readListEnd = function() { }; TCompactProtocol.prototype.readSetBegin = function() { return this.readListBegin(); }; TCompactProtocol.prototype.readSetEnd = function() { }; TCompactProtocol.prototype.readBool = function() { var value = false; var rsize = 0; if (this.boolValue_.hasBoolValue === true) { value = this.boolValue_.boolValue; this.boolValue_.hasBoolValue = false; } else { var res = this.trans.readByte(); rsize = res.rsize; value = (res.value == TCompactProtocol.Types.CT_BOOLEAN_TRUE); } return value; }; TCompactProtocol.prototype.readByte = function() { return this.trans.readByte(); }; TCompactProtocol.prototype.readI16 = function() { return this.readI32(); }; TCompactProtocol.prototype.readI32 = function() { return this.zigzagToI32(this.readVarint32()); }; TCompactProtocol.prototype.readI64 = function() { return this.zigzagToI64(this.readVarint64()); }; // Little-endian, unlike TBinaryProtocol TCompactProtocol.prototype.readDouble = function() { var buff = this.trans.read(8); var off = 0; var signed = buff[off + 7] & 0x80; var e = (buff[off+6] & 0xF0) >> 4; e += (buff[off+7] & 0x7F) << 4; var m = buff[off]; m += buff[off+1] << 8; m += buff[off+2] << 16; m += buff[off+3] * POW_24; m += buff[off+4] * POW_32; m += buff[off+5] * POW_40; m += (buff[off+6] & 0x0F) * POW_48; switch (e) { case 0: e = -1022; break; case 2047: return m ? NaN : (signed ? -Infinity : Infinity); default: m += POW_52; e -= 1023; } if (signed) { m *= -1; } return m * Math.pow(2, e - 52); }; TCompactProtocol.prototype.readBinary = function() { var size = this.readVarint32(); if (size === 0) { return new Buffer(0); } if (size < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative binary size"); } return this.trans.read(size); }; TCompactProtocol.prototype.readString = function() { var size = this.readVarint32(); // Catch empty string case if (size === 0) { return ""; } // Catch error cases if (size < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative string size"); } return this.trans.readString(size); }; // // Compact Protocol internal read operations // /** * Read an i32 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 5 bytes. */ TCompactProtocol.prototype.readVarint32 = function() { return this.readVarint64().toNumber(); }; /** * Read an i64 from the wire as a proper varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 10 bytes. */ TCompactProtocol.prototype.readVarint64 = function() { var rsize = 0; var lo = 0; var hi = 0; var shift = 0; while (true) { var b = this.trans.readByte(); rsize ++; if (shift <= 25) { lo = lo | ((b & 0x7f) << shift); } else if (25 < shift && shift < 32) { lo = lo | ((b & 0x7f) << shift); hi = hi | ((b & 0x7f) >>> (32-shift)); } else { hi = hi | ((b & 0x7f) << (shift-32)); } shift += 7; if (!(b & 0x80)) { break; } if (rsize >= 10) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Variable-length int over 10 bytes."); } } return new Int64(hi, lo); }; /** * Convert from zigzag int to int. */ TCompactProtocol.prototype.zigzagToI32 = function(n) { return (n >>> 1) ^ (-1 * (n & 1)); }; /** * Convert from zigzag long to long. */ TCompactProtocol.prototype.zigzagToI64 = function(n) { var hi = n.buffer.readUInt32BE(0, true); var lo = n.buffer.readUInt32BE(4, true); var neg = new Int64(hi & 0, lo & 1); neg._2scomp(); var hi_neg = neg.buffer.readUInt32BE(0, true); var lo_neg = neg.buffer.readUInt32BE(4, true); var hi_lo = (hi << 31); hi = (hi >>> 1) ^ (hi_neg); lo = ((lo >>> 1) | hi_lo) ^ (lo_neg); return new Int64(hi, lo); }; TCompactProtocol.prototype.skip = function(type) { switch (type) { case Type.BOOL: this.readBool(); break; case Type.BYTE: this.readByte(); break; case Type.I16: this.readI16(); break; case Type.I32: this.readI32(); break; case Type.I64: this.readI64(); break; case Type.DOUBLE: this.readDouble(); break; case Type.STRING: this.readString(); break; case Type.STRUCT: this.readStructBegin(); while (true) { var r = this.readFieldBegin(); if (r.ftype === Type.STOP) { break; } this.skip(r.ftype); this.readFieldEnd(); } this.readStructEnd(); break; case Type.MAP: var mapBegin = this.readMapBegin(); for (var i = 0; i < mapBegin.size; ++i) { this.skip(mapBegin.ktype); this.skip(mapBegin.vtype); } this.readMapEnd(); break; case Type.SET: var setBegin = this.readSetBegin(); for (var i2 = 0; i2 < setBegin.size; ++i2) { this.skip(setBegin.etype); } this.readSetEnd(); break; case Type.LIST: var listBegin = this.readListBegin(); for (var i3 = 0; i3 < listBegin.size; ++i3) { this.skip(listBegin.etype); } this.readListEnd(); break; default: throw new Error("Invalid type: " + type); } }; thrift-0.19.0/lib/nodejs/lib/thrift/header_protocol.js0000644000000000000000000001621014303740367022713 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var TBinaryProtocol = require('./binary_protocol'); var TCompactProtocol = require('./compact_protocol'); var THeaderTransport = require('./header_transport'); var ProtocolMap = {}; ProtocolMap[THeaderTransport.SubprotocolId.BINARY] = TBinaryProtocol; ProtocolMap[THeaderTransport.SubprotocolId.COMPACT] = TCompactProtocol; module.exports = THeaderProtocol; function THeaderProtocolError(message) { Error.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.name = this.constructor.name; this.message = message; } util.inherits(THeaderProtocolError, Error); /** * A framed protocol with headers. * * THeaderProtocol frames other Thrift protocols and adds support for * optional out-of-band headers. The currently supported subprotocols are * TBinaryProtocol and TCompactProtocol. It can currently only be used with * transports that inherit THeaderTransport. * * THeaderProtocol does not currently support THTTPServer, TNonblockingServer, * or TProcessPoolServer. * * See doc/specs/HeaderFormat.md for details of the wire format. */ function THeaderProtocol(trans) { if (!(trans instanceof THeaderTransport)) { throw new THeaderProtocolError( 'Only transports that inherit THeaderTransport can be' + ' used with THeaderProtocol' ); } this.trans = trans; this.setProtocol(); }; THeaderProtocol.prototype.flush = function() { // Headers must be written prior to flushing because because // you need to calculate the length of the payload for the length // field of the header this.trans.writeHeaders(); return this.trans.flush(); }; THeaderProtocol.prototype.writeMessageBegin = function(name, type, seqid) { return this.protocol.writeMessageBegin(name, type, seqid); }; THeaderProtocol.prototype.writeMessageEnd = function() { return this.protocol.writeMessageEnd(); }; THeaderProtocol.prototype.writeStructBegin = function(name) { return this.protocol.writeStructBegin(name); }; THeaderProtocol.prototype.writeStructEnd = function() { return this.protocol.writeStructEnd(); }; THeaderProtocol.prototype.writeFieldBegin = function(name, type, id) { return this.protocol.writeFieldBegin(name, type, id); } THeaderProtocol.prototype.writeFieldEnd = function() { return this.protocol.writeFieldEnd(); }; THeaderProtocol.prototype.writeFieldStop = function() { return this.protocol.writeFieldStop(); }; THeaderProtocol.prototype.writeMapBegin = function(ktype, vtype, size) { return this.protocol.writeMapBegin(ktype, vtype, size); }; THeaderProtocol.prototype.writeMapEnd = function() { return this.protocol.writeMapEnd(); }; THeaderProtocol.prototype.writeListBegin = function(etype, size) { return this.protocol.writeListBegin(etype, size); }; THeaderProtocol.prototype.writeListEnd = function() { return this.protocol.writeListEnd(); }; THeaderProtocol.prototype.writeSetBegin = function(etype, size) { return this.protocol.writeSetBegin(etype, size); }; THeaderProtocol.prototype.writeSetEnd = function() { return this.protocol.writeSetEnd(); }; THeaderProtocol.prototype.writeBool = function(b) { return this.protocol.writeBool(b); }; THeaderProtocol.prototype.writeByte = function(b) { return this.protocol.writeByte(b); }; THeaderProtocol.prototype.writeI16 = function(i16) { return this.protocol.writeI16(i16); }; THeaderProtocol.prototype.writeI32 = function(i32) { return this.protocol.writeI32(i32); }; THeaderProtocol.prototype.writeI64 = function(i64) { return this.protocol.writeI64(i64); }; THeaderProtocol.prototype.writeDouble = function(dub) { return this.protocol.writeDouble(dub); }; THeaderProtocol.prototype.writeStringOrBinary = function(name, encoding, arg) { return this.protocol.writeStringOrBinary(name, encoding, arg); }; THeaderProtocol.prototype.writeString = function(arg) { return this.protocol.writeString(arg); }; THeaderProtocol.prototype.writeBinary = function(arg) { return this.protocol.writeBinary(arg); }; THeaderProtocol.prototype.readMessageBegin = function() { this.trans.readHeaders(); this.setProtocol(); return this.protocol.readMessageBegin(); }; THeaderProtocol.prototype.readMessageEnd = function() { return this.protocol.readMessageEnd(); }; THeaderProtocol.prototype.readStructBegin = function() { return this.protocol.readStructBegin(); }; THeaderProtocol.prototype.readStructEnd = function() { return this.protocol.readStructEnd(); }; THeaderProtocol.prototype.readFieldBegin = function() { return this.protocol.readFieldBegin(); }; THeaderProtocol.prototype.readFieldEnd = function() { return this.protocol.readFieldEnd(); }; THeaderProtocol.prototype.readMapBegin = function() { return this.protocol.readMapBegin(); }; THeaderProtocol.prototype.readMapEnd = function() { return this.protocol.readMapEnd(); }; THeaderProtocol.prototype.readListBegin = function() { return this.protocol.readListBegin(); }; THeaderProtocol.prototype.readListEnd = function() { return this.protocol.readListEnd(); }; THeaderProtocol.prototype.readSetBegin = function() { return this.protocol.readSetBegin(); }; THeaderProtocol.prototype.readSetEnd = function() { return this.protocol.readSetEnd(); }; THeaderProtocol.prototype.readBool = function() { return this.protocol.readBool(); }; THeaderProtocol.prototype.readByte = function() { return this.protocol.readByte(); }; THeaderProtocol.prototype.readI16 = function() { return this.protocol.readI16(); }; THeaderProtocol.prototype.readI32 = function() { return this.protocol.readI32(); }; THeaderProtocol.prototype.readI64 = function() { return this.protocol.readI64(); }; THeaderProtocol.prototype.readDouble = function() { return this.protocol.readDouble(); }; THeaderProtocol.prototype.readBinary = function() { return this.protocol.readBinary(); }; THeaderProtocol.prototype.readString = function() { return this.protocol.readString(); }; THeaderProtocol.prototype.getTransport = function() { return this.trans; }; THeaderProtocol.prototype.skip = function(type) { return this.protocol.skip(type); }; THeaderProtocol.prototype.setProtocol = function(subProtocolId) { var subProtocolId = this.trans.getProtocolId(); if (!ProtocolMap[subProtocolId]) { throw new THeaderProtocolError('Headers not supported for protocol ' + subProtocolId); } this.protocol = new ProtocolMap[subProtocolId](this.trans); }; thrift-0.19.0/lib/nodejs/lib/thrift/web_server.js0000644000000000000000000004712114303740367021712 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var http = require('http'); var https = require('https'); var url = require("url"); var path = require("path"); var fs = require("fs"); var crypto = require("crypto"); var log = require('./log'); var MultiplexedProcessor = require('./multiplexed_processor').MultiplexedProcessor; var TBufferedTransport = require('./buffered_transport'); var TBinaryProtocol = require('./binary_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); // WSFrame constructor and prototype ///////////////////////////////////////////////////////////////////// /** Apache Thrift RPC Web Socket Transport * Frame layout conforming to RFC 6455 circa 12/2011 * * Theoretical frame size limit is 4GB*4GB, however the Node Buffer * limit is 1GB as of v0.10. The frame length encoding is also * configured for a max of 4GB presently and needs to be adjusted * if Node/Browsers become capabile of > 4GB frames. * * - FIN is 1 if the message is complete * - RSV1/2/3 are always 0 * - Opcode is 1(TEXT) for TJSONProtocol and 2(BIN) for TBinaryProtocol * - Mask Present bit is 1 sending to-server and 0 sending to-client * - Payload Len: * + If < 126: then represented directly * + If >=126: but within range of an unsigned 16 bit integer * then Payload Len is 126 and the two following bytes store * the length * + Else: Payload Len is 127 and the following 8 bytes store the * length as an unsigned 64 bit integer * - Masking key is a 32 bit key only present when sending to the server * - Payload follows the masking key or length * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-------+-+-------------+-------------------------------+ * |F|R|R|R| opcode|M| Payload len | Extended payload length | * |I|S|S|S| (4) |A| (7) | (16/64) | * |N|V|V|V| |S| | (if payload len==126/127) | * | |1|2|3| |K| | | * +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + * | Extended payload length continued, if payload len == 127 | * + - - - - - - - - - - - - - - - +-------------------------------+ * | |Masking-key, if MASK set to 1 | * +-------------------------------+-------------------------------+ * | Masking-key (continued) | Payload Data | * +-------------------------------- - - - - - - - - - - - - - - - + * : Payload Data continued ... : * + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * | Payload Data continued ... | * +---------------------------------------------------------------+ */ var wsFrame = { /** Encodes a WebSocket frame * * @param {Buffer} data - The raw data to encode * @param {Buffer} mask - The mask to apply when sending to server, null for no mask * @param {Boolean} binEncoding - True for binary encoding, false for text encoding * @returns {Buffer} - The WebSocket frame, ready to send */ encode: function(data, mask, binEncoding) { var frame = new Buffer(wsFrame.frameSizeFromData(data, mask)); //Byte 0 - FIN & OPCODE frame[0] = wsFrame.fin.FIN + (binEncoding ? wsFrame.frameOpCodes.BIN : wsFrame.frameOpCodes.TEXT); //Byte 1 or 1-3 or 1-9 - MASK FLAG & SIZE var payloadOffset = 2; if (data.length < 0x7E) { frame[1] = data.length + (mask ? wsFrame.mask.TO_SERVER : wsFrame.mask.TO_CLIENT); } else if (data.length < 0xFFFF) { frame[1] = 0x7E + (mask ? wsFrame.mask.TO_SERVER : wsFrame.mask.TO_CLIENT); frame.writeUInt16BE(data.length, 2, true); payloadOffset = 4; } else { frame[1] = 0x7F + (mask ? wsFrame.mask.TO_SERVER : wsFrame.mask.TO_CLIENT); frame.writeUInt32BE(0, 2, true); frame.writeUInt32BE(data.length, 6, true); payloadOffset = 10; } //MASK if (mask) { mask.copy(frame, payloadOffset, 0, 4); payloadOffset += 4; } //Payload data.copy(frame, payloadOffset); if (mask) { wsFrame.applyMask(frame.slice(payloadOffset), frame.slice(payloadOffset-4,payloadOffset)); } return frame; }, /** * @class * @name WSDecodeResult * @property {Buffer} data - The decoded data for the first ATRPC message * @property {Buffer} mask - The frame mask * @property {Boolean} binEncoding - True if binary (TBinaryProtocol), * False if text (TJSONProtocol) * @property {Buffer} nextFrame - Multiple ATRPC messages may be sent in a * single WebSocket frame, this Buffer contains * any bytes remaining to be decoded * @property {Boolean} FIN - True is the message is complete */ /** Decodes a WebSocket frame * * @param {Buffer} frame - The raw inbound frame, if this is a continuation * frame it must have a mask property with the mask. * @returns {WSDecodeResult} - The decoded payload * * @see {@link WSDecodeResult} */ decode: function(frame) { var result = { data: null, mask: null, binEncoding: false, nextFrame: null, FIN: true }; //Byte 0 - FIN & OPCODE if (wsFrame.fin.FIN != (frame[0] & wsFrame.fin.FIN)) { result.FIN = false; } result.binEncoding = (wsFrame.frameOpCodes.BIN == (frame[0] & wsFrame.frameOpCodes.BIN)); //Byte 1 or 1-3 or 1-9 - SIZE var lenByte = (frame[1] & 0x0000007F); var len = lenByte; var dataOffset = 2; if (lenByte == 0x7E) { len = frame.readUInt16BE(2); dataOffset = 4; } else if (lenByte == 0x7F) { len = frame.readUInt32BE(6); dataOffset = 10; } //MASK if (wsFrame.mask.TO_SERVER == (frame[1] & wsFrame.mask.TO_SERVER)) { result.mask = new Buffer(4); frame.copy(result.mask, 0, dataOffset, dataOffset + 4); dataOffset += 4; } //Payload result.data = new Buffer(len); frame.copy(result.data, 0, dataOffset, dataOffset+len); if (result.mask) { wsFrame.applyMask(result.data, result.mask); } //Next Frame if (frame.length > dataOffset+len) { result.nextFrame = new Buffer(frame.length - (dataOffset+len)); frame.copy(result.nextFrame, 0, dataOffset+len, frame.length); } //Don't forward control frames if (frame[0] & wsFrame.frameOpCodes.FINCTRL) { result.data = null; } return result; }, /** Masks/Unmasks data * * @param {Buffer} data - data to mask/unmask in place * @param {Buffer} mask - the mask */ applyMask: function(data, mask){ //TODO: look into xoring words at a time var dataLen = data.length; var maskLen = mask.length; for (var i = 0; i < dataLen; i++) { data[i] = data[i] ^ mask[i%maskLen]; } }, /** Computes frame size on the wire from data to be sent * * @param {Buffer} data - data.length is the assumed payload size * @param {Boolean} mask - true if a mask will be sent (TO_SERVER) */ frameSizeFromData: function(data, mask) { var headerSize = 10; if (data.length < 0x7E) { headerSize = 2; } else if (data.length < 0xFFFF) { headerSize = 4; } return headerSize + data.length + (mask ? 4 : 0); }, frameOpCodes: { CONT: 0x00, TEXT: 0x01, BIN: 0x02, CTRL: 0x80 }, mask: { TO_SERVER: 0x80, TO_CLIENT: 0x00 }, fin: { CONT: 0x00, FIN: 0x80 } }; // createWebServer constructor and options ///////////////////////////////////////////////////////////////////// /** * @class * @name ServerOptions * @property {array} cors - Array of CORS origin strings to permit requests from. * @property {string} files - Path to serve static files from, if absent or "" * static file service is disabled. * @property {object} headers - An object hash mapping header strings to header value * strings, these headers are transmitted in response to * static file GET operations. * @property {object} services - An object hash mapping service URI strings * to ServiceOptions objects * @property {object} tls - Node.js TLS options (see: nodejs.org/api/tls.html), * if not present or null regular http is used, * at least a key and a cert must be defined to use SSL/TLS * @see {@link ServiceOptions} */ /** * @class * @name ServiceOptions * @property {object} transport - The layered transport to use (defaults * to TBufferedTransport). * @property {object} protocol - The serialization Protocol to use (defaults to * TBinaryProtocol). * @property {object} processor - The Thrift Service class/processor generated * by the IDL Compiler for the service (the "cls" * key can also be used for this attribute). * @property {object} handler - The handler methods for the Thrift Service. */ /** * Create a Thrift server which can serve static files and/or one or * more Thrift Services. * @param {ServerOptions} options - The server configuration. * @returns {object} - The Apache Thrift Web Server. */ exports.createWebServer = function(options) { var baseDir = options.files; var contentTypesByExtension = { '.txt': 'text/plain', '.html': 'text/html', '.css': 'text/css', '.xml': 'application/xml', '.json': 'application/json', '.js': 'application/javascript', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.png': 'image/png', '.svg': 'image/svg+xml' }; //Setup all of the services var services = options.services; for (var uri in services) { var svcObj = services[uri]; //Setup the processor if (svcObj.processor instanceof MultiplexedProcessor) { //Multiplex processors have pre embedded processor/handler pairs, save as is svcObj.processor = svcObj.processor; } else { //For historical reasons Node.js supports processors passed in directly or via the // IDL Compiler generated class housing the processor. Also, the options property // for a Processor has been called both cls and processor at different times. We // support any of the four possibilities here. var processor = (svcObj.processor) ? (svcObj.processor.Processor || svcObj.processor) : (svcObj.cls.Processor || svcObj.cls); //Processors can be supplied as constructed objects with handlers already embedded, // if a handler is provided we construct a new processor, if not we use the processor // object directly if (svcObj.handler) { svcObj.processor = new processor(svcObj.handler); } else { svcObj.processor = processor; } } svcObj.transport = svcObj.transport ? svcObj.transport : TBufferedTransport; svcObj.protocol = svcObj.protocol ? svcObj.protocol : TBinaryProtocol; } //Verify CORS requirements function VerifyCORSAndSetHeaders(request, response) { if (request.headers.origin && options.cors) { if (options.cors["*"] || options.cors[request.headers.origin]) { //Allow, origin allowed response.setHeader("access-control-allow-origin", request.headers.origin); response.setHeader("access-control-allow-methods", "GET, POST, OPTIONS"); response.setHeader("access-control-allow-headers", "content-type, accept"); response.setHeader("access-control-max-age", "60"); return true; } else { //Disallow, origin denied return false; } } //Allow, CORS is not in use return true; } //Handle OPTIONS method (CORS) /////////////////////////////////////////////////// function processOptions(request, response) { if (VerifyCORSAndSetHeaders(request, response)) { response.writeHead("204", "No Content", {"content-length": 0}); } else { response.writeHead("403", "Origin " + request.headers.origin + " not allowed", {}); } response.end(); } //Handle POST methods (TXHRTransport) /////////////////////////////////////////////////// function processPost(request, response) { //Lookup service var uri = url.parse(request.url).pathname; var svc = services[uri]; if (!svc) { response.writeHead("403", "No Apache Thrift Service at " + uri, {}); response.end(); return; } //Verify CORS requirements if (!VerifyCORSAndSetHeaders(request, response)) { response.writeHead("403", "Origin " + request.headers.origin + " not allowed", {}); response.end(); return; } //Process XHR payload request.on('data', svc.transport.receiver(function(transportWithData) { var input = new svc.protocol(transportWithData); var output = new svc.protocol(new svc.transport(undefined, function(buf) { try { response.writeHead(200); response.end(buf); } catch (err) { response.writeHead(500); response.end(); } })); try { svc.processor.process(input, output); transportWithData.commitPosition(); } catch (err) { if (err instanceof InputBufferUnderrunError) { transportWithData.rollbackPosition(); } else { response.writeHead(500); response.end(); } } })); } //Handle GET methods (Static Page Server) /////////////////////////////////////////////////// function processGet(request, response) { //Undefined or empty base directory means do not serve static files if (!baseDir || "" === baseDir) { response.writeHead(404); response.end(); return; } //Verify CORS requirements if (!VerifyCORSAndSetHeaders(request, response)) { response.writeHead("403", "Origin " + request.headers.origin + " not allowed", {}); response.end(); return; } //Locate the file requested and send it var uri = url.parse(request.url).pathname; var filename = path.resolve(path.join(baseDir, uri)); //Ensure the basedir path is not able to be escaped if (filename.indexOf(baseDir) != 0) { response.writeHead(400, "Invalid request path", {}); response.end(); return; } fs.exists(filename, function(exists) { if(!exists) { response.writeHead(404); response.end(); return; } if (fs.statSync(filename).isDirectory()) { filename += '/index.html'; } fs.readFile(filename, "binary", function(err, file) { if (err) { response.writeHead(500); response.end(err + "\n"); return; } var headers = {}; var contentType = contentTypesByExtension[path.extname(filename)]; if (contentType) { headers["Content-Type"] = contentType; } for (var k in options.headers) { headers[k] = options.headers[k]; } response.writeHead(200, headers); response.write(file, "binary"); response.end(); }); }); } //Handle WebSocket calls (TWebSocketTransport) /////////////////////////////////////////////////// function processWS(data, socket, svc, binEncoding) { svc.transport.receiver(function(transportWithData) { var input = new svc.protocol(transportWithData); var output = new svc.protocol(new svc.transport(undefined, function(buf) { try { var frame = wsFrame.encode(buf, null, binEncoding); socket.write(frame); } catch (err) { //TODO: Add better error processing } })); try { svc.processor.process(input, output); transportWithData.commitPosition(); } catch (err) { if (err instanceof InputBufferUnderrunError) { transportWithData.rollbackPosition(); } else { //TODO: Add better error processing } } })(data); } //Create the server (HTTP or HTTPS) var server = null; if (options.tls) { server = https.createServer(options.tls); } else { server = http.createServer(); } //Wire up listeners for upgrade(to WebSocket) & request methods for: // - GET static files, // - POST XHR Thrift services // - OPTIONS CORS requests server.on('request', function(request, response) { if (request.method === 'POST') { processPost(request, response); } else if (request.method === 'GET') { processGet(request, response); } else if (request.method === 'OPTIONS') { processOptions(request, response); } else { response.writeHead(500); response.end(); } }).on('upgrade', function(request, socket, head) { //Lookup service var svc; try { svc = services[Object.keys(services)[0]]; } catch(e) { socket.write("HTTP/1.1 403 No Apache Thrift Service available\r\n\r\n"); return; } //Perform upgrade var hash = crypto.createHash("sha1"); hash.update(request.headers['sec-websocket-key'] + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); socket.write("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: " + hash.digest("base64") + "\r\n" + "Sec-WebSocket-Origin: " + request.headers.origin + "\r\n" + "Sec-WebSocket-Location: ws://" + request.headers.host + request.url + "\r\n" + "\r\n"); //Handle WebSocket traffic var data = null; socket.on('data', function(frame) { try { while (frame) { var result = wsFrame.decode(frame); //Prepend any existing decoded data if (data) { if (result.data) { var newData = new Buffer(data.length + result.data.length); data.copy(newData); result.data.copy(newData, data.length); result.data = newData; } else { result.data = data; } data = null; } //If this completes a message process it if (result.FIN) { processWS(result.data, socket, svc, result.binEncoding); } else { data = result.data; } //Prepare next frame for decoding (if any) frame = result.nextFrame; } } catch(e) { log.error('TWebSocketTransport Exception: ' + e); socket.destroy(); } }); }); //Return the server return server; }; thrift-0.19.0/lib/nodejs/lib/thrift/ws_transport.js0000644000000000000000000001347114303740367022315 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var log = require('./log'); module.exports = TWebSocketTransport; /** * Constructor Function for the WebSocket transport. * @constructor * @param {string} [url] - The URL to connect to. * @classdesc The Apache Thrift Transport layer performs byte level I/O * between RPC clients and servers. The JavaScript TWebSocketTransport object * uses the WebSocket protocol. Target servers must implement WebSocket. * (see: node.js example server_http.js). * @example * var transport = new Thrift.TWebSocketTransport("http://localhost:8585"); */ function TWebSocketTransport(url) { this.__reset(url); }; TWebSocketTransport.prototype.__reset = function(url) { this.url = url; //Where to connect this.socket = null; //The web socket this.callbacks = []; //Pending callbacks this.send_pending = []; //Buffers/Callback pairs waiting to be sent this.send_buf = ''; //Outbound data, immutable until sent this.recv_buf = ''; //Inbound data this.rb_wpos = 0; //Network write position in receive buffer this.rb_rpos = 0; //Client read position in receive buffer }; /** * Sends the current WS request and registers callback. The async * parameter is ignored (WS flush is always async) and the callback * function parameter is required. * @param {object} async - Ignored. * @param {object} callback - The client completion callback. * @returns {undefined|string} Nothing (undefined) */ TWebSocketTransport.prototype.flush = function(async, callback) { var self = this; if (this.isOpen()) { //Send data and register a callback to invoke the client callback this.socket.send(this.send_buf); this.callbacks.push((function() { var clientCallback = callback; return function(msg) { self.setRecvBuffer(msg); clientCallback(); }; }())); } else { //Queue the send to go out __onOpen this.send_pending.push({ buf: this.send_buf, cb: callback }); } }; TWebSocketTransport.prototype.__onOpen = function() { var self = this; if (this.send_pending.length > 0) { //If the user made calls before the connection was fully //open, send them now this.send_pending.forEach(function(elem) { self.socket.send(elem.buf); self.callbacks.push((function() { var clientCallback = elem.cb; return function(msg) { self.setRecvBuffer(msg); clientCallback(); }; }())); }); this.send_pending = []; } }; TWebSocketTransport.prototype.__onClose = function(evt) { this.__reset(this.url); }; TWebSocketTransport.prototype.__onMessage = function(evt) { if (this.callbacks.length) { this.callbacks.shift()(evt.data); } }; TWebSocketTransport.prototype.__onError = function(evt) { log.error('websocket: ' + evt.toString()); this.socket.close(); }; /** * Sets the buffer to use when receiving server responses. * @param {string} buf - The buffer to receive server responses. */ TWebSocketTransport.prototype.setRecvBuffer = function(buf) { this.recv_buf = buf; this.recv_buf_sz = this.recv_buf.length; this.wpos = this.recv_buf.length; this.rpos = 0; }; /** * Returns true if the transport is open * @readonly * @returns {boolean} */ TWebSocketTransport.prototype.isOpen = function() { return this.socket && this.socket.readyState == this.socket.OPEN; }; /** * Opens the transport connection */ TWebSocketTransport.prototype.open = function() { //If OPEN/CONNECTING/CLOSING ignore additional opens if (this.socket && this.socket.readyState != this.socket.CLOSED) { return; } //If there is no socket or the socket is closed: this.socket = new WebSocket(this.url); this.socket.onopen = this.__onOpen.bind(this); this.socket.onmessage = this.__onMessage.bind(this); this.socket.onerror = this.__onError.bind(this); this.socket.onclose = this.__onClose.bind(this); }; /** * Closes the transport connection */ TWebSocketTransport.prototype.close = function() { this.socket.close(); }; /** * Returns the specified number of characters from the response * buffer. * @param {number} len - The number of characters to return. * @returns {string} Characters sent by the server. */ TWebSocketTransport.prototype.read = function(len) { var avail = this.wpos - this.rpos; if (avail === 0) { return ''; } var give = len; if (avail < len) { give = avail; } var ret = this.read_buf.substr(this.rpos, give); this.rpos += give; //clear buf when complete? return ret; }; /** * Returns the entire response buffer. * @returns {string} Characters sent by the server. */ TWebSocketTransport.prototype.readAll = function() { return this.recv_buf; }; /** * Sets the send buffer to buf. * @param {string} buf - The buffer to send. */ TWebSocketTransport.prototype.write = function(buf) { this.send_buf = buf; }; /** * Returns the send buffer. * @readonly * @returns {string} The send buffer. */ TWebSocketTransport.prototype.getSendBuffer = function() { return this.send_buf; }; thrift-0.19.0/lib/nodejs/lib/thrift/ws_connection.js0000644000000000000000000002347014303740367022420 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var WebSocket = require('isomorphic-ws'); var EventEmitter = require("events").EventEmitter; var thrift = require('./thrift'); var TBufferedTransport = require('./buffered_transport'); var TJSONProtocol = require('./json_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var createClient = require('./create_client'); var jsEnv = require('browser-or-node'); exports.WSConnection = WSConnection; /** * @class * @name WSConnectOptions * @property {string} transport - The Thrift layered transport to use (TBufferedTransport, etc). * @property {string} protocol - The Thrift serialization protocol to use (TJSONProtocol, etc.). * @property {string} path - The URL path to connect to (e.g. "/", "/mySvc", "/thrift/quoteSvc", etc.). * @property {object} headers - A standard Node.js header hash, an object hash containing key/value * pairs where the key is the header name string and the value is the header value string. * @property {boolean} secure - True causes the connection to use wss, otherwise ws is used. * @property {object} wsOptions - Options passed on to WebSocket. * @example * //Use a secured websocket connection * // uses the buffered transport layer, uses the JSON protocol and directs RPC traffic * // to wss://thrift.example.com:9090/hello * var thrift = require('thrift'); * var options = { * transport: thrift.TBufferedTransport, * protocol: thrift.TJSONProtocol, * path: "/hello", * secure: true * }; * var con = thrift.createWSConnection("thrift.example.com", 9090, options); * con.open() * var client = thrift.createWSClient(myService, connection); * client.myServiceFunction(); * con.close() */ /** * Initializes a Thrift WSConnection instance (use createWSConnection() rather than * instantiating directly). * @constructor * @param {string} host - The host name or IP to connect to. * @param {number} port - The TCP port to connect to. * @param {WSConnectOptions} options - The configuration options to use. * @throws {error} Exceptions other than ttransport.InputBufferUnderrunError are rethrown * @event {error} The "error" event is fired when a Node.js error event occurs during * request or response processing, in which case the node error is passed on. An "error" * event may also be fired when the connection can not map a response back to the * appropriate client (an internal error), generating a TApplicationException. * @classdesc WSConnection objects provide Thrift end point transport * semantics implemented using Websockets. * @see {@link createWSConnection} */ function WSConnection(host, port, options) { //Initialize the emitter base object EventEmitter.call(this); //Set configuration this.options = options || {}; this.host = host; this.port = port; this.secure = this.options.secure || false; this.transport = this.options.transport || TBufferedTransport; this.protocol = this.options.protocol || TJSONProtocol; this.path = this.options.path; this.send_pending = []; //The sequence map is used to map seqIDs back to the // calling client in multiplexed scenarios this.seqId2Service = {}; //Prepare WebSocket options this.wsOptions = { host: this.host, port: this.port || 80, path: this.options.path || '/', headers: this.options.headers || {} }; for (var attrname in this.options.wsOptions) { this.wsOptions[attrname] = this.options.wsOptions[attrname]; } }; util.inherits(WSConnection, EventEmitter); WSConnection.prototype.__reset = function() { this.socket = null; //The web socket this.send_pending = []; //Buffers/Callback pairs waiting to be sent }; WSConnection.prototype.__onOpen = function() { this.emit("open"); if (this.send_pending.length > 0) { //If the user made calls before the connection was fully //open, send them now this.send_pending.forEach(function(data) { this.socket.send(data); }, this); this.send_pending = []; } }; WSConnection.prototype.__onClose = function(evt) { this.emit("close"); this.__reset(); }; WSConnection.prototype.__decodeCallback = function(transport_with_data) { var proto = new this.protocol(transport_with_data); try { while (true) { var header = proto.readMessageBegin(); var dummy_seqid = header.rseqid * -1; var client = this.client; //The Multiplexed Protocol stores a hash of seqid to service names // in seqId2Service. If the SeqId is found in the hash we need to // lookup the appropriate client for this call. // The client var is a single client object when not multiplexing, // when using multiplexing it is a service name keyed hash of client // objects. //NOTE: The 2 way interdependencies between protocols, transports, // connections and clients in the Node.js implementation are irregular // and make the implementation difficult to extend and maintain. We // should bring this stuff inline with typical thrift I/O stack // operation soon. // --ra var service_name = this.seqId2Service[header.rseqid]; if (service_name) { client = this.client[service_name]; delete this.seqId2Service[header.rseqid]; } /*jshint -W083 */ client._reqs[dummy_seqid] = function(err, success) { transport_with_data.commitPosition(); var clientCallback = client._reqs[header.rseqid]; delete client._reqs[header.rseqid]; if (clientCallback) { clientCallback(err, success); } }; /*jshint +W083 */ if (client['recv_' + header.fname]) { client['recv_' + header.fname](proto, header.mtype, dummy_seqid); } else { delete client._reqs[dummy_seqid]; this.emit("error", new thrift.TApplicationException( thrift.TApplicationExceptionType.WRONG_METHOD_NAME, "Received a response to an unknown RPC function")); } } } catch (e) { if (e instanceof InputBufferUnderrunError) { transport_with_data.rollbackPosition(); } else { throw e; } } }; WSConnection.prototype.__onData = function(data) { if (Object.prototype.toString.call(data) === "[object ArrayBuffer]") { data = new Uint8Array(data); } var buf = new Buffer(data); this.transport.receiver(this.__decodeCallback.bind(this))(buf); }; WSConnection.prototype.__onMessage = function(evt) { this.__onData(evt.data); }; WSConnection.prototype.__onError = function(evt) { this.emit("error", evt); this.socket.close(); }; /** * Returns true if the transport is open * @readonly * @returns {boolean} */ WSConnection.prototype.isOpen = function() { return this.socket && this.socket.readyState === this.socket.OPEN; }; /** * Opens the transport connection */ WSConnection.prototype.open = function() { //If OPEN/CONNECTING/CLOSING ignore additional opens if (this.socket && this.socket.readyState !== this.socket.CLOSED) { return; } //If there is no socket or the socket is closed: if (jsEnv.isBrowser) { this.socket = new WebSocket(this.uri()); } else { this.socket = new WebSocket(this.uri(), "", this.wsOptions); } this.socket.binaryType = 'arraybuffer'; this.socket.onopen = this.__onOpen.bind(this); this.socket.onmessage = this.__onMessage.bind(this); this.socket.onerror = this.__onError.bind(this); this.socket.onclose = this.__onClose.bind(this); }; /** * Closes the transport connection */ WSConnection.prototype.close = function() { this.socket.close(); }; /** * Return URI for the connection * @returns {string} URI */ WSConnection.prototype.uri = function() { var schema = this.secure ? 'wss' : 'ws'; var port = ''; var path = this.path || '/'; var host = this.host; // avoid port if default for schema if (this.port && (('wss' === schema && this.port !== 443) || ('ws' === schema && this.port !== 80))) { port = ':' + this.port; } return schema + '://' + host + port + path; }; /** * Writes Thrift message data to the connection * @param {Buffer} data - A Node.js Buffer containing the data to write * @returns {void} No return value. * @event {error} the "error" event is raised upon request failure passing the * Node.js error object to the listener. */ WSConnection.prototype.write = function(data) { if (this.isOpen()) { //Send data and register a callback to invoke the client callback this.socket.send(data); } else { //Queue the send to go out __onOpen this.send_pending.push(data); } }; /** * Creates a new WSConnection object, used by Thrift clients to connect * to Thrift HTTP based servers. * @param {string} host - The host name or IP to connect to. * @param {number} port - The TCP port to connect to. * @param {WSConnectOptions} options - The configuration options to use. * @returns {WSConnection} The connection object. * @see {@link WSConnectOptions} */ exports.createWSConnection = function(host, port, options) { return new WSConnection(host, port, options); }; exports.createWSClient = createClient; thrift-0.19.0/lib/nodejs/lib/thrift/transport.js0000644000000000000000000000177714303740367021612 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ module.exports.TBufferedTransport = require('./buffered_transport'); module.exports.TFramedTransport = require('./framed_transport'); module.exports.InputBufferUnderrunError = require('./input_buffer_underrun_error'); thrift-0.19.0/lib/nodejs/lib/thrift/json_protocol.js0000644000000000000000000005203114303740367022435 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var Int64 = require('node-int64'); var Thrift = require('./thrift'); var Type = Thrift.Type; var util = require("util"); var Int64Util = require('./int64_util'); var json_parse = require('./json_parse'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); module.exports = TJSONProtocol; /** * Initializes a Thrift JSON protocol instance. * @constructor * @param {Thrift.Transport} trans - The transport to serialize to/from. * @classdesc Apache Thrift Protocols perform serialization which enables cross * language RPC. The Protocol type is the JavaScript browser implementation * of the Apache Thrift TJSONProtocol. * @example * var protocol = new Thrift.Protocol(transport); */ function TJSONProtocol(trans) { this.tstack = []; this.tpos = []; this.trans = trans; }; /** * Thrift IDL type Id to string mapping. * @readonly * @see {@link Thrift.Type} */ TJSONProtocol.Type = {}; TJSONProtocol.Type[Type.BOOL] = '"tf"'; TJSONProtocol.Type[Type.BYTE] = '"i8"'; TJSONProtocol.Type[Type.I16] = '"i16"'; TJSONProtocol.Type[Type.I32] = '"i32"'; TJSONProtocol.Type[Type.I64] = '"i64"'; TJSONProtocol.Type[Type.DOUBLE] = '"dbl"'; TJSONProtocol.Type[Type.STRUCT] = '"rec"'; TJSONProtocol.Type[Type.STRING] = '"str"'; TJSONProtocol.Type[Type.MAP] = '"map"'; TJSONProtocol.Type[Type.LIST] = '"lst"'; TJSONProtocol.Type[Type.SET] = '"set"'; /** * Thrift IDL type string to Id mapping. * @readonly * @see {@link Thrift.Type} */ TJSONProtocol.RType = {}; TJSONProtocol.RType.tf = Type.BOOL; TJSONProtocol.RType.i8 = Type.BYTE; TJSONProtocol.RType.i16 = Type.I16; TJSONProtocol.RType.i32 = Type.I32; TJSONProtocol.RType.i64 = Type.I64; TJSONProtocol.RType.dbl = Type.DOUBLE; TJSONProtocol.RType.rec = Type.STRUCT; TJSONProtocol.RType.str = Type.STRING; TJSONProtocol.RType.map = Type.MAP; TJSONProtocol.RType.lst = Type.LIST; TJSONProtocol.RType.set = Type.SET; /** * The TJSONProtocol version number. * @readonly * @const {number} Version * @memberof Thrift.Protocol */ TJSONProtocol.Version = 1; TJSONProtocol.prototype.flush = function() { this.writeToTransportIfStackIsFlushable(); return this.trans.flush(); }; TJSONProtocol.prototype.writeToTransportIfStackIsFlushable = function() { if (this.tstack.length === 1) { this.trans.write(this.tstack.pop()); } }; /** * Serializes the beginning of a Thrift RPC message. * @param {string} name - The service method to call. * @param {Thrift.MessageType} messageType - The type of method call. * @param {number} seqid - The sequence number of this call (always 0 in Apache Thrift). */ TJSONProtocol.prototype.writeMessageBegin = function(name, messageType, seqid) { this.tstack.push([TJSONProtocol.Version, '"' + name + '"', messageType, seqid]); }; /** * Serializes the end of a Thrift RPC message. */ TJSONProtocol.prototype.writeMessageEnd = function() { var obj = this.tstack.pop(); this.wobj = this.tstack.pop(); this.wobj.push(obj); this.wbuf = '[' + this.wobj.join(',') + ']'; // we assume there is nothing more to come so we write this.trans.write(this.wbuf); }; /** * Serializes the beginning of a struct. * @param {string} name - The name of the struct. */ TJSONProtocol.prototype.writeStructBegin = function(name) { this.tpos.push(this.tstack.length); this.tstack.push({}); }; /** * Serializes the end of a struct. */ TJSONProtocol.prototype.writeStructEnd = function() { var p = this.tpos.pop(); var struct = this.tstack[p]; var str = '{'; var first = true; for (var key in struct) { if (first) { first = false; } else { str += ','; } str += key + ':' + struct[key]; } str += '}'; this.tstack[p] = str; this.writeToTransportIfStackIsFlushable(); }; /** * Serializes the beginning of a struct field. * @param {string} name - The name of the field. * @param {Thrift.Protocol.Type} fieldType - The data type of the field. * @param {number} fieldId - The field's unique identifier. */ TJSONProtocol.prototype.writeFieldBegin = function(name, fieldType, fieldId) { this.tpos.push(this.tstack.length); this.tstack.push({ 'fieldId': '"' + fieldId + '"', 'fieldType': TJSONProtocol.Type[fieldType] }); }; /** * Serializes the end of a field. */ TJSONProtocol.prototype.writeFieldEnd = function() { var value = this.tstack.pop(); var fieldInfo = this.tstack.pop(); if (':' + value === ":[object Object]") { this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' + fieldInfo.fieldType + ':' + JSON.stringify(value) + '}'; } else { this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' + fieldInfo.fieldType + ':' + value + '}'; } this.tpos.pop(); this.writeToTransportIfStackIsFlushable(); }; /** * Serializes the end of the set of fields for a struct. */ TJSONProtocol.prototype.writeFieldStop = function() { }; /** * Serializes the beginning of a map collection. * @param {Thrift.Type} keyType - The data type of the key. * @param {Thrift.Type} valType - The data type of the value. * @param {number} [size] - The number of elements in the map (ignored). */ TJSONProtocol.prototype.writeMapBegin = function(keyType, valType, size) { //size is invalid, we'll set it on end. this.tpos.push(this.tstack.length); this.tstack.push([TJSONProtocol.Type[keyType], TJSONProtocol.Type[valType], 0]); }; /** * Serializes the end of a map. */ TJSONProtocol.prototype.writeMapEnd = function() { var p = this.tpos.pop(); if (p == this.tstack.length) { return; } if ((this.tstack.length - p - 1) % 2 !== 0) { this.tstack.push(''); } var size = (this.tstack.length - p - 1) / 2; this.tstack[p][this.tstack[p].length - 1] = size; var map = '}'; var first = true; while (this.tstack.length > p + 1) { var v = this.tstack.pop(); var k = this.tstack.pop(); if (first) { first = false; } else { map = ',' + map; } if (! isNaN(k)) { k = '"' + k + '"'; } //json "keys" need to be strings map = k + ':' + v + map; } map = '{' + map; this.tstack[p].push(map); this.tstack[p] = '[' + this.tstack[p].join(',') + ']'; this.writeToTransportIfStackIsFlushable(); }; /** * Serializes the beginning of a list collection. * @param {Thrift.Type} elemType - The data type of the elements. * @param {number} size - The number of elements in the list. */ TJSONProtocol.prototype.writeListBegin = function(elemType, size) { this.tpos.push(this.tstack.length); this.tstack.push([TJSONProtocol.Type[elemType], size]); }; /** * Serializes the end of a list. */ TJSONProtocol.prototype.writeListEnd = function() { var p = this.tpos.pop(); while (this.tstack.length > p + 1) { var tmpVal = this.tstack[p + 1]; this.tstack.splice(p + 1, 1); this.tstack[p].push(tmpVal); } this.tstack[p] = '[' + this.tstack[p].join(',') + ']'; this.writeToTransportIfStackIsFlushable(); }; /** * Serializes the beginning of a set collection. * @param {Thrift.Type} elemType - The data type of the elements. * @param {number} size - The number of elements in the list. */ TJSONProtocol.prototype.writeSetBegin = function(elemType, size) { this.tpos.push(this.tstack.length); this.tstack.push([TJSONProtocol.Type[elemType], size]); }; /** * Serializes the end of a set. */ TJSONProtocol.prototype.writeSetEnd = function() { var p = this.tpos.pop(); while (this.tstack.length > p + 1) { var tmpVal = this.tstack[p + 1]; this.tstack.splice(p + 1, 1); this.tstack[p].push(tmpVal); } this.tstack[p] = '[' + this.tstack[p].join(',') + ']'; this.writeToTransportIfStackIsFlushable(); }; /** Serializes a boolean */ TJSONProtocol.prototype.writeBool = function(bool) { this.tstack.push(bool ? 1 : 0); }; /** Serializes a number */ TJSONProtocol.prototype.writeByte = function(byte) { this.tstack.push(byte); }; /** Serializes a number */ TJSONProtocol.prototype.writeI16 = function(i16) { this.tstack.push(i16); }; /** Serializes a number */ TJSONProtocol.prototype.writeI32 = function(i32) { this.tstack.push(i32); }; /** Serializes a number */ TJSONProtocol.prototype.writeI64 = function(i64) { if (i64 instanceof Int64) { this.tstack.push(Int64Util.toDecimalString(i64)); } else { this.tstack.push(i64); } }; /** Serializes a number */ TJSONProtocol.prototype.writeDouble = function(dub) { this.tstack.push(dub); }; /** Serializes a string */ TJSONProtocol.prototype.writeString = function(arg) { // We do not encode uri components for wire transfer: if (arg === null) { this.tstack.push(null); } else { if (typeof arg === 'string') { var str = arg; } else if (arg instanceof Buffer) { var str = arg.toString('utf8'); } else { throw new Error('writeString called without a string/Buffer argument: ' + arg); } // concat may be slower than building a byte buffer var escapedString = ''; for (var i = 0; i < str.length; i++) { var ch = str.charAt(i); // a single double quote: " if (ch === '\"') { escapedString += '\\\"'; // write out as: \" } else if (ch === '\\') { // a single backslash: \ escapedString += '\\\\'; // write out as: \\ /* Currently escaped forward slashes break TJSONProtocol. * As it stands, we can simply pass forward slashes into * our strings across the wire without being escaped. * I think this is the protocol's bug, not thrift.js * } else if(ch === '/') { // a single forward slash: / * escapedString += '\\/'; // write out as \/ * } */ } else if (ch === '\b') { // a single backspace: invisible escapedString += '\\b'; // write out as: \b" } else if (ch === '\f') { // a single formfeed: invisible escapedString += '\\f'; // write out as: \f" } else if (ch === '\n') { // a single newline: invisible escapedString += '\\n'; // write out as: \n" } else if (ch === '\r') { // a single return: invisible escapedString += '\\r'; // write out as: \r" } else if (ch === '\t') { // a single tab: invisible escapedString += '\\t'; // write out as: \t" } else { escapedString += ch; // Else it need not be escaped } } this.tstack.push('"' + escapedString + '"'); } }; /** Serializes a string */ TJSONProtocol.prototype.writeBinary = function(arg) { if (typeof arg === 'string') { var buf = new Buffer(arg, 'binary'); } else if (arg instanceof Buffer || Object.prototype.toString.call(arg) == '[object Uint8Array]') { var buf = arg; } else { throw new Error('writeBinary called without a string/Buffer argument: ' + arg); } this.tstack.push('"' + buf.toString('base64') + '"'); }; /** * @class * @name AnonReadMessageBeginReturn * @property {string} fname - The name of the service method. * @property {Thrift.MessageType} mtype - The type of message call. * @property {number} rseqid - The sequence number of the message (0 in Thrift RPC). */ /** * Deserializes the beginning of a message. * @returns {AnonReadMessageBeginReturn} */ TJSONProtocol.prototype.readMessageBegin = function() { this.rstack = []; this.rpos = []; //Borrow the inbound transport buffer and ensure data is present/consistent var transBuf = this.trans.borrow(); if (transBuf.readIndex >= transBuf.writeIndex) { throw new InputBufferUnderrunError(); } var cursor = transBuf.readIndex; if (transBuf.buf[cursor] !== 0x5B) { //[ throw new Error("Malformed JSON input, no opening bracket"); } //Parse a single message (there may be several in the buffer) // TODO: Handle characters using multiple code units cursor++; var openBracketCount = 1; var inString = false; for (; cursor < transBuf.writeIndex; cursor++) { var chr = transBuf.buf[cursor]; //we use hexa charcode here because data[i] returns an int and not a char if (inString) { if (chr === 0x22) { //" inString = false; } else if (chr === 0x5C) { //\ //escaped character, skip cursor += 1; } } else { if (chr === 0x5B) { //[ openBracketCount += 1; } else if (chr === 0x5D) { //] openBracketCount -= 1; if (openBracketCount === 0) { //end of json message detected break; } } else if (chr === 0x22) { //" inString = true; } } } if (openBracketCount !== 0) { // Missing closing bracket. Can be buffer underrun. throw new InputBufferUnderrunError(); } //Reconstitute the JSON object and conume the necessary bytes this.robj = json_parse(transBuf.buf.slice(transBuf.readIndex, cursor+1).toString()); this.trans.consume(cursor + 1 - transBuf.readIndex); //Verify the protocol version var version = this.robj.shift(); if (version != TJSONProtocol.Version) { throw new Error('Wrong thrift protocol version: ' + version); } //Objectify the thrift message {name/type/sequence-number} for return // and then save the JSON object in rstack var r = {}; r.fname = this.robj.shift(); r.mtype = this.robj.shift(); r.rseqid = this.robj.shift(); this.rstack.push(this.robj.shift()); return r; }; /** Deserializes the end of a message. */ TJSONProtocol.prototype.readMessageEnd = function() { }; /** * Deserializes the beginning of a struct. * @param {string} [name] - The name of the struct (ignored) * @returns {object} - An object with an empty string fname property */ TJSONProtocol.prototype.readStructBegin = function() { var r = {}; r.fname = ''; //incase this is an array of structs if (this.rstack[this.rstack.length - 1] instanceof Array) { this.rstack.push(this.rstack[this.rstack.length - 1].shift()); } return r; }; /** Deserializes the end of a struct. */ TJSONProtocol.prototype.readStructEnd = function() { this.rstack.pop(); }; /** * @class * @name AnonReadFieldBeginReturn * @property {string} fname - The name of the field (always ''). * @property {Thrift.Type} ftype - The data type of the field. * @property {number} fid - The unique identifier of the field. */ /** * Deserializes the beginning of a field. * @returns {AnonReadFieldBeginReturn} */ TJSONProtocol.prototype.readFieldBegin = function() { var r = {}; var fid = -1; var ftype = Type.STOP; //get a fieldId for (var f in (this.rstack[this.rstack.length - 1])) { if (f === null) { continue; } fid = parseInt(f, 10); this.rpos.push(this.rstack.length); var field = this.rstack[this.rstack.length - 1][fid]; //remove so we don't see it again delete this.rstack[this.rstack.length - 1][fid]; this.rstack.push(field); break; } if (fid != -1) { //should only be 1 of these but this is the only //way to match a key for (var i in (this.rstack[this.rstack.length - 1])) { if (TJSONProtocol.RType[i] === null) { continue; } ftype = TJSONProtocol.RType[i]; this.rstack[this.rstack.length - 1] = this.rstack[this.rstack.length - 1][i]; } } r.fname = ''; r.ftype = ftype; r.fid = fid; return r; }; /** Deserializes the end of a field. */ TJSONProtocol.prototype.readFieldEnd = function() { var pos = this.rpos.pop(); //get back to the right place in the stack while (this.rstack.length > pos) { this.rstack.pop(); } }; /** * @class * @name AnonReadMapBeginReturn * @property {Thrift.Type} ktype - The data type of the key. * @property {Thrift.Type} vtype - The data type of the value. * @property {number} size - The number of elements in the map. */ /** * Deserializes the beginning of a map. * @returns {AnonReadMapBeginReturn} */ TJSONProtocol.prototype.readMapBegin = function() { var map = this.rstack.pop(); var first = map.shift(); if (first instanceof Array) { this.rstack.push(map); map = first; first = map.shift(); } var r = {}; r.ktype = TJSONProtocol.RType[first]; r.vtype = TJSONProtocol.RType[map.shift()]; r.size = map.shift(); this.rpos.push(this.rstack.length); this.rstack.push(map.shift()); return r; }; /** Deserializes the end of a map. */ TJSONProtocol.prototype.readMapEnd = function() { this.readFieldEnd(); }; /** * @class * @name AnonReadColBeginReturn * @property {Thrift.Type} etype - The data type of the element. * @property {number} size - The number of elements in the collection. */ /** * Deserializes the beginning of a list. * @returns {AnonReadColBeginReturn} */ TJSONProtocol.prototype.readListBegin = function() { var list = this.rstack[this.rstack.length - 1]; var r = {}; r.etype = TJSONProtocol.RType[list.shift()]; r.size = list.shift(); this.rpos.push(this.rstack.length); this.rstack.push(list.shift()); return r; }; /** Deserializes the end of a list. */ TJSONProtocol.prototype.readListEnd = function() { var pos = this.rpos.pop() - 2; var st = this.rstack; st.pop(); if (st instanceof Array && st.length > pos && st[pos].length > 0) { st.push(st[pos].shift()); } }; /** * Deserializes the beginning of a set. * @returns {AnonReadColBeginReturn} */ TJSONProtocol.prototype.readSetBegin = function() { return this.readListBegin(); }; /** Deserializes the end of a set. */ TJSONProtocol.prototype.readSetEnd = function() { return this.readListEnd(); }; TJSONProtocol.prototype.readBool = function() { return this.readValue() == '1'; }; TJSONProtocol.prototype.readByte = function() { return this.readI32(); }; TJSONProtocol.prototype.readI16 = function() { return this.readI32(); }; TJSONProtocol.prototype.readI32 = function(f) { return +this.readValue(); } /** Returns the next value found in the protocol buffer */ TJSONProtocol.prototype.readValue = function(f) { if (f === undefined) { f = this.rstack[this.rstack.length - 1]; } var r = {}; if (f instanceof Array) { if (f.length === 0) { r.value = undefined; } else { r.value = f.shift(); } } else if (!(f instanceof Int64) && f instanceof Object) { for (var i in f) { if (i === null) { continue; } this.rstack.push(f[i]); delete f[i]; r.value = i; break; } } else { r.value = f; this.rstack.pop(); } return r.value; }; TJSONProtocol.prototype.readI64 = function() { var n = this.readValue() if (typeof n === 'string') { // Assuming no one is sending in 1.11111e+33 format return Int64Util.fromDecimalString(n); } else { return new Int64(n); } }; TJSONProtocol.prototype.readDouble = function() { return this.readI32(); }; TJSONProtocol.prototype.readBinary = function() { return new Buffer(this.readValue(), 'base64'); }; TJSONProtocol.prototype.readString = function() { return this.readValue(); }; /** * Returns the underlying transport. * @readonly * @returns {Thrift.Transport} The underlying transport. */ TJSONProtocol.prototype.getTransport = function() { return this.trans; }; /** * Method to arbitrarily skip over data */ TJSONProtocol.prototype.skip = function(type) { switch (type) { case Type.BOOL: this.readBool(); break; case Type.BYTE: this.readByte(); break; case Type.I16: this.readI16(); break; case Type.I32: this.readI32(); break; case Type.I64: this.readI64(); break; case Type.DOUBLE: this.readDouble(); break; case Type.STRING: this.readString(); break; case Type.STRUCT: this.readStructBegin(); while (true) { var r = this.readFieldBegin(); if (r.ftype === Type.STOP) { break; } this.skip(r.ftype); this.readFieldEnd(); } this.readStructEnd(); break; case Type.MAP: var mapBegin = this.readMapBegin(); for (var i = 0; i < mapBegin.size; ++i) { this.skip(mapBegin.ktype); this.skip(mapBegin.vtype); } this.readMapEnd(); break; case Type.SET: var setBegin = this.readSetBegin(); for (var i2 = 0; i2 < setBegin.size; ++i2) { this.skip(setBegin.etype); } this.readSetEnd(); break; case Type.LIST: var listBegin = this.readListBegin(); for (var i3 = 0; i3 < listBegin.size; ++i3) { this.skip(listBegin.etype); } this.readListEnd(); break; default: throw new Error("Invalid type: " + type); } }; thrift-0.19.0/lib/nodejs/lib/thrift/index.js0000644000000000000000000000611114303740367020650 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ exports.Thrift = require('./thrift'); var log = require('./log'); exports.setLogFunc = log.setLogFunc; exports.setLogLevel = log.setLogLevel; exports.getLogLevel = log.getLogLevel; var connection = require('./connection'); exports.Connection = connection.Connection; exports.createClient = connection.createClient; exports.createConnection = connection.createConnection; exports.createUDSConnection = connection.createUDSConnection; exports.createSSLConnection = connection.createSSLConnection; exports.createStdIOClient = connection.createStdIOClient; exports.createStdIOConnection = connection.createStdIOConnection; var httpConnection = require('./http_connection'); exports.HttpConnection = httpConnection.HttpConnection; exports.createHttpConnection = httpConnection.createHttpConnection; exports.createHttpUDSConnection = httpConnection.createHttpUDSConnection; exports.createHttpClient = httpConnection.createHttpClient; var wsConnection = require('./ws_connection'); exports.WSConnection = wsConnection.WSConnection; exports.createWSConnection = wsConnection.createWSConnection; exports.createWSClient = wsConnection.createWSClient; var xhrConnection = require('./xhr_connection'); exports.XHRConnection = xhrConnection.XHRConnection; exports.createXHRConnection = xhrConnection.createXHRConnection; exports.createXHRClient = xhrConnection.createXHRClient; var server = require('./server'); exports.createServer = server.createServer; exports.createMultiplexServer = server.createMultiplexServer; var web_server = require('./web_server'); exports.createWebServer = web_server.createWebServer; exports.Int64 = require('node-int64'); exports.Q = require('q'); var mpxProcessor = require('./multiplexed_processor'); var mpxProtocol = require('./multiplexed_protocol'); exports.MultiplexedProcessor = mpxProcessor.MultiplexedProcessor; exports.Multiplexer = mpxProtocol.Multiplexer; /* * Export transport and protocol so they can be used outside of a * cassandra/server context */ exports.TBufferedTransport = require('./buffered_transport'); exports.TFramedTransport = require('./framed_transport'); exports.TJSONProtocol = require('./json_protocol'); exports.TBinaryProtocol = require('./binary_protocol'); exports.TCompactProtocol = require('./compact_protocol'); exports.THeaderProtocol = require('./header_protocol'); thrift-0.19.0/lib/nodejs/lib/thrift/header_transport.js0000644000000000000000000002406514303740367023115 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var TCompactProtocol = require('./compact_protocol'); var TBinaryProtocol = require('./binary_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); function THeaderTransportError(message) { Error.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.name = this.constructor.name; this.message = message; } util.inherits(THeaderTransportError, Error); module.exports = THeaderTransport; // from HeaderFormat.md var COMPACT_PROTOCOL_OFFSET = 0; var COMPACT_PROTOCOL_VERSION_OFFSET = 1; var FRAME_SIZE_OFFSET = 0; var HEADER_MAGIC_OFFSET = 32 / 8; var FLAGS_OFFSET = 48 / 8; var SEQID_OFFSET = 64 / 8; var HEADER_SIZE_OFFSET = 96 / 8; var HEADER_START_OFFSET = 112 / 8; var HEADER_MAGIC = 0x0FFF; var TINFO_HEADER_KEY_VALUE_TYPE = 0x01; var MAX_FRAME_SIZE = 0x3FFFFFFF; // A helper class for reading/writing varints. Uses // TCompactProtocol under the hood function VarintHelper(readBuffer) { var TBufferedTransport = require('./buffered_transport'); this.outputBuffer = null; var _this = this; this.transport = new TBufferedTransport(null, function(output) { _this.outputBuffer = output; }); this.transport.inBuf = readBuffer || Buffer.alloc(0); this.transport.writeCursor = this.transport.inBuf.length; this.protocol = new TCompactProtocol(this.transport); }; VarintHelper.prototype.readVarint32 = function() { return this.protocol.readVarint32(); }; VarintHelper.prototype.writeVarint32 = function(i) { this.protocol.writeVarint32(i); }; VarintHelper.prototype.readString = function() { return this.protocol.readString(); }; VarintHelper.prototype.writeString = function(str) { this.protocol.writeString(str); } VarintHelper.prototype.getOutCount = function() { return this.transport.outCount; }; VarintHelper.prototype.write = function(str) { this.transport.write(str); }; VarintHelper.prototype.toBuffer = function() { this.transport.flush(); return this.outputBuffer; }; // from lib/cpp/src/thrift/protocol/TProtocolTypes.h THeaderTransport.SubprotocolId = { BINARY: 0, JSON: 1, COMPACT: 2, }; /** An abstract transport used as a prototype for other transports to enable reading/writing theaders. This should NOT be used as a standalone transport The methods in this transport are called by THeaderProtocol, which will call readHeaders/writeHeaders in the read/writeMessageBegin methods and parse/write headers to/from a request prior to reading/writing. The reason this is not a standalone transport type is because different transport types have their own individual static receiver methods that are called prior to instantiation. There doesn't seem to be a way for THeaderTransport to know which receiver method to use without reworking the server API. For reading headers from a request, the parsed headers can be retrieved via getReadHeader. Similarly, you can set headers to be written on the client via setWriteHeader. */ function THeaderTransport() { this.maxFrameSize = MAX_FRAME_SIZE; this.protocolId = THeaderTransport.SubprotocolId.BINARY; this.rheaders = {}; this.wheaders = {}; this.inBuf = Buffer.alloc(0); this.outCount = 0; this.flags = null; this.seqid = 0; this.shouldWriteHeaders = true; }; var validateHeaders = function(key, value) { if (typeof key !== 'string' || typeof value !== 'string') { throw new THeaderTransportError('Header key and values must be strings'); } }; var validateProtocolId = function(protocolId) { var protocols = Object.keys(THeaderTransport.SubprotocolId); for (var i = 0; i < protocols.length; i++) { if (protocolId === THeaderTransport.SubprotocolId[protocols[i]]) return true; } throw new Error(protocolId + ' is not a valid protocol id'); }; THeaderTransport.prototype.setSeqId = function(seqid) { this.seqid = seqid; }; THeaderTransport.prototype.getSeqId = function(seqid) { return this.seqid; }; THeaderTransport.prototype.setFlags = function(flags) { this.flags = flags; }; THeaderTransport.prototype.getReadHeaders = function() { return this.rheaders; }; THeaderTransport.prototype.setReadHeader = function(key, value) { validateHeaders(key, value); this.rheaders[key] = value; }; THeaderTransport.prototype.clearReadHeaders = function() { this.rheaders = {}; }; THeaderTransport.prototype.getWriteHeaders = function() { return this.wheaders; }; THeaderTransport.prototype.setWriteHeader = function(key, value) { validateHeaders(key, value); this.wheaders[key] = value; }; THeaderTransport.prototype.clearWriteHeaders = function() { this.wheaders = {}; }; THeaderTransport.prototype.setMaxFrameSize = function(frameSize) { this.maxFrameSize = frameSize; }; THeaderTransport.prototype.setProtocolId = function(protocolId) { validateProtocolId(protocolId); this.protocolId = protocolId; }; THeaderTransport.prototype.getProtocolId = function() { return this.protocolId; }; var isUnframedBinary = function(readBuffer) { var version = readBuffer.readInt32BE(); return (version & TBinaryProtocol.VERSION_MASK) === TBinaryProtocol.VERSION_1; } var isUnframedCompact = function(readBuffer) { var protocolId = readBuffer.readInt8(COMPACT_PROTOCOL_OFFSET); var version = readBuffer.readInt8(COMPACT_PROTOCOL_VERSION_OFFSET); return protocolId === TCompactProtocol.PROTOCOL_ID && (version & TCompactProtocol.VERSION_MASK) === TCompactProtocol.VERSION_N; } THeaderTransport.prototype.readHeaders = function() { var readBuffer = this.inBuf; var isUnframed = false; if (isUnframedBinary(readBuffer)) { this.setProtocolId(THeaderTransport.SubprotocolId.BINARY); isUnframed = true; } if (isUnframedCompact(readBuffer)) { this.setProtocolId(THeaderTransport.SubprotocolId.COMPACT); isUnframed = true; } if (isUnframed) { this.shouldWriteHeaders = false; return; } var frameSize = readBuffer.readInt32BE(FRAME_SIZE_OFFSET); if (frameSize > this.maxFrameSize) { throw new THeaderTransportError('Frame exceeds maximum frame size'); } var headerMagic = readBuffer.readInt16BE(HEADER_MAGIC_OFFSET); this.shouldWriteHeaders = headerMagic === HEADER_MAGIC; if (!this.shouldWriteHeaders) { return; } this.setFlags(readBuffer.readInt16BE(FLAGS_OFFSET)); this.setSeqId(readBuffer.readInt32BE(SEQID_OFFSET)); var headerSize = readBuffer.readInt16BE(HEADER_SIZE_OFFSET) * 4; var endOfHeaders = HEADER_START_OFFSET + headerSize; if (endOfHeaders > readBuffer.length) { throw new THeaderTransportError('Header size is greater than frame size'); } var headerBuffer = Buffer.alloc(headerSize); readBuffer.copy(headerBuffer, 0, HEADER_START_OFFSET, endOfHeaders); var varintHelper = new VarintHelper(headerBuffer); this.setProtocolId(varintHelper.readVarint32()); var transformCount = varintHelper.readVarint32(); if (transformCount > 0) { throw new THeaderTransportError('Transforms are not yet supported'); } while (true) { try { var headerType = varintHelper.readVarint32(); if (headerType !== TINFO_HEADER_KEY_VALUE_TYPE) { break; } var numberOfHeaders = varintHelper.readVarint32(); for (var i = 0; i < numberOfHeaders; i++) { var key = varintHelper.readString(); var value = varintHelper.readString(); this.setReadHeader(key, value); } } catch (e) { if (e instanceof InputBufferUnderrunError) { break; } throw e; } } // moves the read cursor past the headers this.read(endOfHeaders); return this.getReadHeaders(); }; THeaderTransport.prototype.writeHeaders = function() { // only write headers on the server if the client contained headers if (!this.shouldWriteHeaders) { return; } var headers = this.getWriteHeaders(); var varintWriter = new VarintHelper(); varintWriter.writeVarint32(this.protocolId); varintWriter.writeVarint32(0); // transforms not supported // writing info header key values var headerKeys = Object.keys(headers); if (headerKeys.length > 0) { varintWriter.writeVarint32(TINFO_HEADER_KEY_VALUE_TYPE); varintWriter.writeVarint32(headerKeys.length); for (var i = 0; i < headerKeys.length; i++) { var key = headerKeys[i]; var value = headers[key]; varintWriter.writeString(key); varintWriter.writeString(value); } } var headerSizeWithoutPadding = varintWriter.getOutCount(); var paddingNeeded = (4 - (headerSizeWithoutPadding % 4)) % 4; var headerSize = Buffer.alloc(2); headerSize.writeInt16BE(Math.floor((headerSizeWithoutPadding + paddingNeeded) / 4)); var paddingBuffer = Buffer.alloc(paddingNeeded); paddingBuffer.fill(0x00); varintWriter.write(paddingBuffer); var headerContentBuffer = varintWriter.toBuffer(); var frameSize = Buffer.alloc(4); frameSize.writeInt32BE(10 + this.outCount + headerContentBuffer.length); var headerMagic = Buffer.alloc(2); headerMagic.writeInt16BE(HEADER_MAGIC); // flags are not yet supported, so write a zero var flags = Buffer.alloc(2); flags.writeInt16BE(0); var seqid = Buffer.alloc(4); seqid.writeInt32BE(this.getSeqId()); var headerBuffer = Buffer.concat([ frameSize, headerMagic, flags, seqid, headerSize, headerContentBuffer, ]); this.outBuffers.unshift(headerBuffer); this.outCount += headerBuffer.length; }; thrift-0.19.0/lib/nodejs/lib/thrift/binary.js0000644000000000000000000000711514303740367021032 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var POW_8 = Math.pow(2, 8); var POW_16 = Math.pow(2, 16); var POW_24 = Math.pow(2, 24); var POW_32 = Math.pow(2, 32); var POW_40 = Math.pow(2, 40); var POW_48 = Math.pow(2, 48); var POW_52 = Math.pow(2, 52); var POW_1022 = Math.pow(2, 1022); exports.readByte = function(b){ return b > 127 ? b-256 : b; }; exports.readI16 = function(buff, off) { off = off || 0; var v = buff[off + 1]; v += buff[off] << 8; if (buff[off] & 128) { v -= POW_16; } return v; }; exports.readI32 = function(buff, off) { off = off || 0; var v = buff[off + 3]; v += buff[off + 2] << 8; v += buff[off + 1] << 16; v += buff[off] * POW_24; if (buff[off] & 0x80) { v -= POW_32; } return v; }; exports.writeI16 = function(buff, v) { buff[1] = v & 0xff; v >>= 8; buff[0] = v & 0xff; return buff; }; exports.writeI32 = function(buff, v) { buff[3] = v & 0xff; v >>= 8; buff[2] = v & 0xff; v >>= 8; buff[1] = v & 0xff; v >>= 8; buff[0] = v & 0xff; return buff; }; exports.readDouble = function(buff, off) { off = off || 0; var signed = buff[off] & 0x80; var e = (buff[off+1] & 0xF0) >> 4; e += (buff[off] & 0x7F) << 4; var m = buff[off+7]; m += buff[off+6] << 8; m += buff[off+5] << 16; m += buff[off+4] * POW_24; m += buff[off+3] * POW_32; m += buff[off+2] * POW_40; m += (buff[off+1] & 0x0F) * POW_48; switch (e) { case 0: e = -1022; break; case 2047: return m ? NaN : (signed ? -Infinity : Infinity); default: m += POW_52; e -= 1023; } if (signed) { m *= -1; } return m * Math.pow(2, e - 52); }; /* * Based on code from the jspack module: * http://code.google.com/p/jspack/ */ exports.writeDouble = function(buff, v) { var m, e, c; buff[0] = (v < 0 ? 0x80 : 0x00); v = Math.abs(v); if (v !== v) { // NaN, use QNaN IEEE format m = 2251799813685248; e = 2047; } else if (v === Infinity) { m = 0; e = 2047; } else { e = Math.floor(Math.log(v) / Math.LN2); c = Math.pow(2, -e); if (v * c < 1) { e--; c *= 2; } if (e + 1023 >= 2047) { // Overflow m = 0; e = 2047; } else if (e + 1023 >= 1) { // Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow m = (v*c-1) * POW_52; e += 1023; } else { // Denormalized - also catches the '0' case, somewhat by chance m = (v * POW_1022) * POW_52; e = 0; } } buff[1] = (e << 4) & 0xf0; buff[0] |= (e >> 4) & 0x7f; buff[7] = m & 0xff; m = Math.floor(m / POW_8); buff[6] = m & 0xff; m = Math.floor(m / POW_8); buff[5] = m & 0xff; m = Math.floor(m / POW_8); buff[4] = m & 0xff; m >>= 8; buff[3] = m & 0xff; m >>= 8; buff[2] = m & 0xff; m >>= 8; buff[1] |= m & 0x0f; return buff; }; thrift-0.19.0/lib/nodejs/lib/thrift/create_client.js0000644000000000000000000000361314303740367022346 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ module.exports = createClient; /** * Creates a new client object for the specified Thrift service. * @param {object} ServiceClient - The module containing the generated service client * @param {Connection} Connection - The connection to use. * @returns {object} The client object. */ function createClient(ServiceClient, connection) { // TODO validate required options and throw otherwise if (ServiceClient.Client) { ServiceClient = ServiceClient.Client; } // TODO detangle these initialization calls // creating "client" requires // - new service client instance // // New service client instance requires // - new transport instance // - protocol class reference // // New transport instance requires // - Buffer to use (or none) // - Callback to call on flush // Wrap the write method var writeCb = function(buf, seqid) { connection.write(buf, seqid); }; var transport = new connection.transport(undefined, writeCb); var client = new ServiceClient(transport, connection.protocol); transport.client = client; connection.client = client; return client; }; thrift-0.19.0/lib/nodejs/lib/thrift/protocol.js0000644000000000000000000000174014303740367021405 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ module.exports.TBinaryProtocol = require('./binary_protocol'); module.exports.TCompactProtocol = require('./compact_protocol'); module.exports.TJSONProtocol = require('./json_protocol'); thrift-0.19.0/lib/nodejs/lib/thrift/json_parse.js0000644000000000000000000001712614303740367021714 0ustar00rootroot00000000000000/* * Imported from Douglas Crockford's reference implementation with minimum modification * to handle Int64. * * https://github.com/douglascrockford/JSON-js/blob/c98948ae1944a28e2e8ebc3717894e580aeaaa05/json_parse.js * * Original license header: * * json_parse.js * 2015-05-02 * Public Domain. * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. */ /*jslint for */ /*property at, b, call, charAt, f, fromCharCode, hasOwnProperty, message, n, name, prototype, push, r, t, text */ var Int64 = require('node-int64'); var Int64Util = require('./int64_util'); var json_parse = module.exports = (function () { "use strict"; // This is a function that can parse a JSON text, producing a JavaScript // data structure. It is a simple, recursive descent parser. It does not use // eval or regular expressions, so it can be used as a model for implementing // a JSON parser in other languages. // We are defining the function inside of another function to avoid creating // global variables. var at, // The index of the current character ch, // The current character escapee = { '"': '"', '\\': '\\', '/': '/', b: '\b', f: '\f', n: '\n', r: '\r', t: '\t' }, text, error = function (m) { // Call error when something is wrong. throw new SyntaxError(m); }, next = function (c) { // If a c parameter is provided, verify that it matches the current character. if (c && c !== ch) { error("Expected '" + c + "' instead of '" + ch + "'"); } // Get the next character. When there are no more characters, // return the empty string. ch = text.charAt(at); at += 1; return ch; }, number = function () { // Parse a number value. var number, string = ''; if (ch === '-') { string = '-'; next('-'); } while (ch >= '0' && ch <= '9') { string += ch; next(); } if (ch === '.') { string += '.'; while (next() && ch >= '0' && ch <= '9') { string += ch; } } if (ch === 'e' || ch === 'E') { string += ch; next(); if (ch === '-' || ch === '+') { string += ch; next(); } while (ch >= '0' && ch <= '9') { string += ch; next(); } } number = +string; if (!isFinite(number)) { error("Bad number"); } else if (number >= Int64.MAX_INT || number <= Int64.MIN_INT) { // Return raw string for further process in TJSONProtocol return string; } else { return number; } }, string = function () { // Parse a string value. var hex, i, string = '', uffff; // When parsing for string values, we must look for " and \ characters. if (ch === '"') { while (next()) { if (ch === '"') { next(); return string; } if (ch === '\\') { next(); if (ch === 'u') { uffff = 0; for (i = 0; i < 4; i += 1) { hex = parseInt(next(), 16); if (!isFinite(hex)) { break; } uffff = uffff * 16 + hex; } string += String.fromCharCode(uffff); } else if (typeof escapee[ch] === 'string') { string += escapee[ch]; } else { break; } } else { string += ch; } } } error("Bad string"); }, white = function () { // Skip whitespace. while (ch && ch <= ' ') { next(); } }, word = function () { // true, false, or null. switch (ch) { case 't': next('t'); next('r'); next('u'); next('e'); return true; case 'f': next('f'); next('a'); next('l'); next('s'); next('e'); return false; case 'n': next('n'); next('u'); next('l'); next('l'); return null; } error("Unexpected '" + ch + "'"); }, value, // Place holder for the value function. array = function () { // Parse an array value. var array = []; if (ch === '[') { next('['); white(); if (ch === ']') { next(']'); return array; // empty array } while (ch) { array.push(value()); white(); if (ch === ']') { next(']'); return array; } next(','); white(); } } error("Bad array"); }, object = function () { // Parse an object value. var key, object = {}; if (ch === '{') { next('{'); white(); if (ch === '}') { next('}'); return object; // empty object } while (ch) { key = string(); white(); next(':'); if (Object.hasOwnProperty.call(object, key)) { error('Duplicate key "' + key + '"'); } object[key] = value(); white(); if (ch === '}') { next('}'); return object; } next(','); white(); } } error("Bad object"); }; value = function () { // Parse a JSON value. It could be an object, an array, a string, a number, // or a word. white(); switch (ch) { case '{': return object(); case '[': return array(); case '"': return string(); case '-': return number(); default: return ch >= '0' && ch <= '9' ? number() : word(); } }; // Return the json_parse function. It will have access to all of the above // functions and variables. return function (source) { var result; text = source; at = 0; ch = ' '; result = value(); white(); if (ch) { error("Syntax error"); } return result; }; }()); thrift-0.19.0/lib/nodejs/lib/thrift/thrift.js0000644000000000000000000001247014303740367021046 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var Type = exports.Type = { STOP: 0, VOID: 1, BOOL: 2, BYTE: 3, I08: 3, DOUBLE: 4, I16: 6, I32: 8, I64: 10, STRING: 11, UTF7: 11, STRUCT: 12, MAP: 13, SET: 14, LIST: 15, UTF8: 16, UTF16: 17 }; exports.MessageType = { CALL: 1, REPLY: 2, EXCEPTION: 3, ONEWAY: 4 }; exports.TException = TException; function TException(message) { Error.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.name = this.constructor.name; this.message = message; }; util.inherits(TException, Error); var TApplicationExceptionType = exports.TApplicationExceptionType = { UNKNOWN: 0, UNKNOWN_METHOD: 1, INVALID_MESSAGE_TYPE: 2, WRONG_METHOD_NAME: 3, BAD_SEQUENCE_ID: 4, MISSING_RESULT: 5, INTERNAL_ERROR: 6, PROTOCOL_ERROR: 7, INVALID_TRANSFORM: 8, INVALID_PROTOCOL: 9, UNSUPPORTED_CLIENT_TYPE: 10 }; exports.TApplicationException = TApplicationException; function TApplicationException(type, message) { TException.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.type = type || TApplicationExceptionType.UNKNOWN; this.name = this.constructor.name; this.message = message; }; util.inherits(TApplicationException, TException); TApplicationException.prototype.read = function(input) { var ftype; var ret = input.readStructBegin('TApplicationException'); while(1){ ret = input.readFieldBegin(); if(ret.ftype == Type.STOP) break; switch(ret.fid){ case 1: if( ret.ftype == Type.STRING ){ ret = input.readString(); this.message = ret; } else { ret = input.skip(ret.ftype); } break; case 2: if( ret.ftype == Type.I32 ){ ret = input.readI32(); this.type = ret; } else { ret = input.skip(ret.ftype); } break; default: ret = input.skip(ret.ftype); break; } input.readFieldEnd(); } input.readStructEnd(); }; TApplicationException.prototype.write = function(output){ output.writeStructBegin('TApplicationException'); if (this.message) { output.writeFieldBegin('message', Type.STRING, 1); output.writeString(this.message); output.writeFieldEnd(); } if (this.code) { output.writeFieldBegin('type', Type.I32, 2); output.writeI32(this.code); output.writeFieldEnd(); } output.writeFieldStop(); output.writeStructEnd(); }; var TProtocolExceptionType = exports.TProtocolExceptionType = { UNKNOWN: 0, INVALID_DATA: 1, NEGATIVE_SIZE: 2, SIZE_LIMIT: 3, BAD_VERSION: 4, NOT_IMPLEMENTED: 5, DEPTH_LIMIT: 6 }; exports.TProtocolException = TProtocolException; function TProtocolException(type, message) { Error.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.name = this.constructor.name; this.type = type; this.message = message; }; util.inherits(TProtocolException, Error); exports.objectLength = function(obj) { return Object.keys(obj).length; }; exports.inherits = function(constructor, superConstructor) { util.inherits(constructor, superConstructor); }; var copyList, copyMap; copyList = function(lst, types) { if (!lst) {return lst; } var type; if (types.shift === undefined) { type = types; } else { type = types[0]; } var Type = type; var len = lst.length, result = [], i, val; for (i = 0; i < len; i++) { val = lst[i]; if (type === null) { result.push(val); } else if (type === copyMap || type === copyList) { result.push(type(val, types.slice(1))); } else { result.push(new Type(val)); } } return result; }; copyMap = function(obj, types){ if (!obj) {return obj; } var type; if (types.shift === undefined) { type = types; } else { type = types[0]; } var Type = type; var result = {}, val; for(var prop in obj) { if(obj.hasOwnProperty(prop)) { val = obj[prop]; if (type === null) { result[prop] = val; } else if (type === copyMap || type === copyList) { result[prop] = type(val, types.slice(1)); } else { result[prop] = new Type(val); } } } return result; }; module.exports.copyMap = copyMap; module.exports.copyList = copyList; thrift-0.19.0/lib/nodejs/lib/thrift/binary_protocol.js0000644000000000000000000002303314303740367022750 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var log = require('./log'); var binary = require('./binary'); var Int64 = require('node-int64'); var Thrift = require('./thrift'); var Type = Thrift.Type; module.exports = TBinaryProtocol; // JavaScript supports only numeric doubles, therefore even hex values are always signed. // The largest integer value which can be represented in JavaScript is +/-2^53. // Bitwise operations convert numbers to 32 bit integers but perform sign extension // upon assigning values back to variables. var VERSION_MASK = -65536, // 0xffff0000 VERSION_1 = -2147418112, // 0x80010000 TYPE_MASK = 0x000000ff; TBinaryProtocol.VERSION_MASK = VERSION_MASK; TBinaryProtocol.VERSION_1 = VERSION_1; TBinaryProtocol.TYPE_MASK = TYPE_MASK function TBinaryProtocol(trans, strictRead, strictWrite) { this.trans = trans; this.strictRead = (strictRead !== undefined ? strictRead : false); this.strictWrite = (strictWrite !== undefined ? strictWrite : true); this._seqid = null; }; TBinaryProtocol.prototype.flush = function() { return this.trans.flush(); }; TBinaryProtocol.prototype.writeMessageBegin = function(name, type, seqid) { if (this.strictWrite) { this.writeI32(VERSION_1 | type); this.writeString(name); this.writeI32(seqid); } else { this.writeString(name); this.writeByte(type); this.writeI32(seqid); } // Record client seqid to find callback again if (this._seqid !== null) { log.warning('SeqId already set', { 'name': name }); } else { this._seqid = seqid; this.trans.setCurrSeqId(seqid); } }; TBinaryProtocol.prototype.writeMessageEnd = function() { if (this._seqid !== null) { this._seqid = null; } else { log.warning('No seqid to unset'); } }; TBinaryProtocol.prototype.writeStructBegin = function(name) { }; TBinaryProtocol.prototype.writeStructEnd = function() { }; TBinaryProtocol.prototype.writeFieldBegin = function(name, type, id) { this.writeByte(type); this.writeI16(id); }; TBinaryProtocol.prototype.writeFieldEnd = function() { }; TBinaryProtocol.prototype.writeFieldStop = function() { this.writeByte(Type.STOP); }; TBinaryProtocol.prototype.writeMapBegin = function(ktype, vtype, size) { this.writeByte(ktype); this.writeByte(vtype); this.writeI32(size); }; TBinaryProtocol.prototype.writeMapEnd = function() { }; TBinaryProtocol.prototype.writeListBegin = function(etype, size) { this.writeByte(etype); this.writeI32(size); }; TBinaryProtocol.prototype.writeListEnd = function() { }; TBinaryProtocol.prototype.writeSetBegin = function(etype, size) { this.writeByte(etype); this.writeI32(size); }; TBinaryProtocol.prototype.writeSetEnd = function() { }; TBinaryProtocol.prototype.writeBool = function(bool) { if (bool) { this.writeByte(1); } else { this.writeByte(0); } }; TBinaryProtocol.prototype.writeByte = function(b) { this.trans.write(new Buffer([b])); }; TBinaryProtocol.prototype.writeI16 = function(i16) { this.trans.write(binary.writeI16(new Buffer(2), i16)); }; TBinaryProtocol.prototype.writeI32 = function(i32) { this.trans.write(binary.writeI32(new Buffer(4), i32)); }; TBinaryProtocol.prototype.writeI64 = function(i64) { if (i64.buffer) { this.trans.write(i64.buffer); } else { this.trans.write(new Int64(i64).buffer); } }; TBinaryProtocol.prototype.writeDouble = function(dub) { this.trans.write(binary.writeDouble(new Buffer(8), dub)); }; TBinaryProtocol.prototype.writeStringOrBinary = function(name, encoding, arg) { if (typeof(arg) === 'string') { this.writeI32(Buffer.byteLength(arg, encoding)); this.trans.write(new Buffer(arg, encoding)); } else if ((arg instanceof Buffer) || (Object.prototype.toString.call(arg) == '[object Uint8Array]')) { // Buffers in Node.js under Browserify may extend UInt8Array instead of // defining a new object. We detect them here so we can write them // correctly this.writeI32(arg.length); this.trans.write(arg); } else { throw new Error(name + ' called without a string/Buffer argument: ' + arg); } }; TBinaryProtocol.prototype.writeString = function(arg) { this.writeStringOrBinary('writeString', 'utf8', arg); }; TBinaryProtocol.prototype.writeBinary = function(arg) { this.writeStringOrBinary('writeBinary', 'binary', arg); }; TBinaryProtocol.prototype.readMessageBegin = function() { var sz = this.readI32(); var type, name, seqid; if (sz < 0) { var version = sz & VERSION_MASK; if (version != VERSION_1) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad version in readMessageBegin: " + sz); } type = sz & TYPE_MASK; name = this.readString(); seqid = this.readI32(); } else { if (this.strictRead) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "No protocol version header"); } name = this.trans.read(sz); type = this.readByte(); seqid = this.readI32(); } return {fname: name, mtype: type, rseqid: seqid}; }; TBinaryProtocol.prototype.readMessageEnd = function() { }; TBinaryProtocol.prototype.readStructBegin = function() { return {fname: ''}; }; TBinaryProtocol.prototype.readStructEnd = function() { }; TBinaryProtocol.prototype.readFieldBegin = function() { var type = this.readByte(); if (type == Type.STOP) { return {fname: null, ftype: type, fid: 0}; } var id = this.readI16(); return {fname: null, ftype: type, fid: id}; }; TBinaryProtocol.prototype.readFieldEnd = function() { }; TBinaryProtocol.prototype.readMapBegin = function() { var ktype = this.readByte(); var vtype = this.readByte(); var size = this.readI32(); return {ktype: ktype, vtype: vtype, size: size}; }; TBinaryProtocol.prototype.readMapEnd = function() { }; TBinaryProtocol.prototype.readListBegin = function() { var etype = this.readByte(); var size = this.readI32(); return {etype: etype, size: size}; }; TBinaryProtocol.prototype.readListEnd = function() { }; TBinaryProtocol.prototype.readSetBegin = function() { var etype = this.readByte(); var size = this.readI32(); return {etype: etype, size: size}; }; TBinaryProtocol.prototype.readSetEnd = function() { }; TBinaryProtocol.prototype.readBool = function() { var b = this.readByte(); if (b === 0) { return false; } return true; }; TBinaryProtocol.prototype.readByte = function() { return this.trans.readByte(); }; TBinaryProtocol.prototype.readI16 = function() { return this.trans.readI16(); }; TBinaryProtocol.prototype.readI32 = function() { return this.trans.readI32(); }; TBinaryProtocol.prototype.readI64 = function() { var buff = this.trans.read(8); return new Int64(buff); }; TBinaryProtocol.prototype.readDouble = function() { return this.trans.readDouble(); }; TBinaryProtocol.prototype.readBinary = function() { var len = this.readI32(); if (len === 0) { return new Buffer(0); } if (len < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative binary size"); } return this.trans.read(len); }; TBinaryProtocol.prototype.readString = function() { var len = this.readI32(); if (len === 0) { return ""; } if (len < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative string size"); } return this.trans.readString(len); }; TBinaryProtocol.prototype.getTransport = function() { return this.trans; }; TBinaryProtocol.prototype.skip = function(type) { switch (type) { case Type.BOOL: this.readBool(); break; case Type.BYTE: this.readByte(); break; case Type.I16: this.readI16(); break; case Type.I32: this.readI32(); break; case Type.I64: this.readI64(); break; case Type.DOUBLE: this.readDouble(); break; case Type.STRING: this.readString(); break; case Type.STRUCT: this.readStructBegin(); while (true) { var r = this.readFieldBegin(); if (r.ftype === Type.STOP) { break; } this.skip(r.ftype); this.readFieldEnd(); } this.readStructEnd(); break; case Type.MAP: var mapBegin = this.readMapBegin(); for (var i = 0; i < mapBegin.size; ++i) { this.skip(mapBegin.ktype); this.skip(mapBegin.vtype); } this.readMapEnd(); break; case Type.SET: var setBegin = this.readSetBegin(); for (var i2 = 0; i2 < setBegin.size; ++i2) { this.skip(setBegin.etype); } this.readSetEnd(); break; case Type.LIST: var listBegin = this.readListBegin(); for (var i3 = 0; i3 < listBegin.size; ++i3) { this.skip(listBegin.etype); } this.readListEnd(); break; default: throw new Error("Invalid type: " + type); } }; thrift-0.19.0/lib/nodejs/lib/thrift/multiplexed_protocol.js0000644000000000000000000000475014303740367024025 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var Thrift = require('./thrift'); exports.Multiplexer = Multiplexer; function Wrapper(serviceName, protocol, connection) { function MultiplexProtocol(trans, strictRead, strictWrite) { protocol.call(this, trans, strictRead, strictWrite); }; util.inherits(MultiplexProtocol, protocol); MultiplexProtocol.prototype.writeMessageBegin = function(name, type, seqid) { if (type == Thrift.MessageType.CALL || type == Thrift.MessageType.ONEWAY) { connection.seqId2Service[seqid] = serviceName; MultiplexProtocol.super_.prototype.writeMessageBegin.call(this, serviceName + ":" + name, type, seqid); } else { MultiplexProtocol.super_.prototype.writeMessageBegin.call(this, name, type, seqid); } }; return MultiplexProtocol; }; function Multiplexer() { this.seqid = 0; }; Multiplexer.prototype.createClient = function(serviceName, ServiceClient, connection) { if (ServiceClient.Client) { ServiceClient = ServiceClient.Client; } var writeCb = function(buf, seqid) { connection.write(buf,seqid); }; var transport = new connection.transport(undefined, writeCb); var protocolWrapper = new Wrapper(serviceName, connection.protocol, connection); var client = new ServiceClient(transport, protocolWrapper); var self = this; client.new_seqid = function() { self.seqid += 1; return self.seqid; }; if (typeof connection.client !== 'object') { connection.client = {}; } connection.client[serviceName] = client; return client; }; thrift-0.19.0/lib/nodejs/lib/thrift/http_connection.js0000644000000000000000000002355614303740367022753 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var http = require('http'); var https = require('https'); var EventEmitter = require('events').EventEmitter; var thrift = require('./thrift'); var TBufferedTransport = require('./buffered_transport'); var TBinaryProtocol = require('./binary_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var createClient = require('./create_client'); /** * @class * @name ConnectOptions * @property {string} transport - The Thrift layered transport to use (TBufferedTransport, etc). * @property {string} protocol - The Thrift serialization protocol to use (TBinaryProtocol, etc.). * @property {string} path - The URL path to POST to (e.g. "/", "/mySvc", "/thrift/quoteSvc", etc.). * @property {object} headers - A standard Node.js header hash, an object hash containing key/value * pairs where the key is the header name string and the value is the header value string. * @property {boolean} https - True causes the connection to use https, otherwise http is used. * @property {object} nodeOptions - Options passed on to node. * @example * //Use a connection that requires ssl/tls, closes the connection after each request, * // uses the buffered transport layer, uses the JSON protocol and directs RPC traffic * // to https://thrift.example.com:9090/hello * var thrift = require('thrift'); * var options = { * transport: thrift.TBufferedTransport, * protocol: thrift.TJSONProtocol, * path: "/hello", * headers: {"Connection": "close"}, * https: true * }; * var con = thrift.createHttpConnection("thrift.example.com", 9090, options); * var client = thrift.createHttpClient(myService, connection); * client.myServiceFunction(); */ /** * Initializes a Thrift HttpConnection instance (use createHttpConnection() rather than * instantiating directly). * @constructor * @param {ConnectOptions} options - The configuration options to use. * @throws {error} Exceptions other than InputBufferUnderrunError are rethrown * @event {error} The "error" event is fired when a Node.js error event occurs during * request or response processing, in which case the node error is passed on. An "error" * event may also be fired when the connection can not map a response back to the * appropriate client (an internal error), generating a TApplicationException. * @classdesc HttpConnection objects provide Thrift end point transport * semantics implemented over the Node.js http.request() method. * @see {@link createHttpConnection} */ var HttpConnection = exports.HttpConnection = function(options) { //Initialize the emitter base object EventEmitter.call(this); //Set configuration var self = this; this.options = options || {}; this.host = this.options.host; this.port = this.options.port; this.socketPath = this.options.socketPath; this.https = this.options.https || false; this.transport = this.options.transport || TBufferedTransport; this.protocol = this.options.protocol || TBinaryProtocol; //Prepare Node.js options this.nodeOptions = { host: this.host, port: this.port, socketPath: this.socketPath, path: this.options.path || '/', method: 'POST', headers: this.options.headers || {}, responseType: this.options.responseType || null }; for (var attrname in this.options.nodeOptions) { this.nodeOptions[attrname] = this.options.nodeOptions[attrname]; } /*jshint -W069 */ if (! this.nodeOptions.headers['Connection']) { this.nodeOptions.headers['Connection'] = 'keep-alive'; } /*jshint +W069 */ //The sequence map is used to map seqIDs back to the // calling client in multiplexed scenarios this.seqId2Service = {}; function decodeCallback(transport_with_data) { var proto = new self.protocol(transport_with_data); try { while (true) { var header = proto.readMessageBegin(); var dummy_seqid = header.rseqid * -1; var client = self.client; //The Multiplexed Protocol stores a hash of seqid to service names // in seqId2Service. If the SeqId is found in the hash we need to // lookup the appropriate client for this call. // The client var is a single client object when not multiplexing, // when using multiplexing it is a service name keyed hash of client // objects. //NOTE: The 2 way interdependencies between protocols, transports, // connections and clients in the Node.js implementation are irregular // and make the implementation difficult to extend and maintain. We // should bring this stuff inline with typical thrift I/O stack // operation soon. // --ra var service_name = self.seqId2Service[header.rseqid]; if (service_name) { client = self.client[service_name]; delete self.seqId2Service[header.rseqid]; } /*jshint -W083 */ client._reqs[dummy_seqid] = function(err, success){ transport_with_data.commitPosition(); var clientCallback = client._reqs[header.rseqid]; delete client._reqs[header.rseqid]; if (clientCallback) { process.nextTick(function() { clientCallback(err, success); }); } }; /*jshint +W083 */ if(client['recv_' + header.fname]) { client['recv_' + header.fname](proto, header.mtype, dummy_seqid); } else { delete client._reqs[dummy_seqid]; self.emit("error", new thrift.TApplicationException( thrift.TApplicationExceptionType.WRONG_METHOD_NAME, "Received a response to an unknown RPC function")); } } } catch (e) { if (e instanceof InputBufferUnderrunError) { transport_with_data.rollbackPosition(); } else { self.emit('error', e); } } } //Response handler ////////////////////////////////////////////////// this.responseCallback = function(response) { var data = []; var dataLen = 0; if (response.statusCode !== 200) { this.emit("error", new THTTPException(response)); } response.on('error', function (e) { self.emit("error", e); }); // When running directly under node, chunk will be a buffer, // however, when running in a Browser (e.g. Browserify), chunk // will be a string or an ArrayBuffer. response.on('data', function (chunk) { if ((typeof chunk == 'string') || (Object.prototype.toString.call(chunk) == '[object Uint8Array]')) { // Wrap ArrayBuffer/string in a Buffer so data[i].copy will work data.push(new Buffer(chunk)); } else { data.push(chunk); } dataLen += chunk.length; }); response.on('end', function(){ var buf = new Buffer(dataLen); for (var i=0, len=data.length, pos=0; i 0) { this.max_attempts = +this.options.max_attempts; } this.retry_max_delay = null; if (this.options.retry_max_delay !== undefined && !isNaN(this.options.retry_max_delay) && this.options.retry_max_delay > 0) { this.retry_max_delay = this.options.retry_max_delay; } this.connect_timeout = false; if (this.options.connect_timeout && !isNaN(this.options.connect_timeout) && this.options.connect_timeout > 0) { this.connect_timeout = +this.options.connect_timeout; } this.connection.addListener(this.ssl ? "secureConnect" : "connect", function() { self.connected = true; this.setTimeout(self.options.timeout || 0); this.setNoDelay(); this.frameLeft = 0; this.framePos = 0; this.frame = null; self.initialize_retry_vars(); self.flush_offline_queue(); self.emit("connect"); }); this.connection.addListener("error", function(err) { // Only emit the error if no-one else is listening on the connection // or if someone is listening on us, because Node turns unhandled // 'error' events into exceptions. if (self.connection.listeners('error').length === 1 || self.listeners('error').length > 0) { self.emit("error", err); } }); // Add a close listener this.connection.addListener("close", function() { self.connection_gone(); // handle close event. try to reconnect }); this.connection.addListener("timeout", function() { self.emit("timeout"); }); this.connection.addListener("data", self.transport.receiver(function(transport_with_data) { var message = new self.protocol(transport_with_data); try { while (true) { var header = message.readMessageBegin(); var dummy_seqid = header.rseqid * -1; var client = self.client; //The Multiplexed Protocol stores a hash of seqid to service names // in seqId2Service. If the SeqId is found in the hash we need to // lookup the appropriate client for this call. // The connection.client object is a single client object when not // multiplexing, when using multiplexing it is a service name keyed // hash of client objects. //NOTE: The 2 way interdependencies between protocols, transports, // connections and clients in the Node.js implementation are irregular // and make the implementation difficult to extend and maintain. We // should bring this stuff inline with typical thrift I/O stack // operation soon. // --ra var service_name = self.seqId2Service[header.rseqid]; if (service_name) { client = self.client[service_name]; } /*jshint -W083 */ client._reqs[dummy_seqid] = function(err, success){ transport_with_data.commitPosition(); var callback = client._reqs[header.rseqid]; delete client._reqs[header.rseqid]; if (service_name) { delete self.seqId2Service[header.rseqid]; } if (callback) { callback(err, success); } }; /*jshint +W083 */ if(client['recv_' + header.fname]) { client['recv_' + header.fname](message, header.mtype, dummy_seqid); } else { delete client._reqs[dummy_seqid]; self.emit("error", new thrift.TApplicationException(thrift.TApplicationExceptionType.WRONG_METHOD_NAME, "Received a response to an unknown RPC function")); } } } catch (e) { if (e instanceof InputBufferUnderrunError) { transport_with_data.rollbackPosition(); } else { self.emit('error', e); } } })); }; util.inherits(Connection, EventEmitter); Connection.prototype.end = function() { this.forceClose = true; this.connection.end(); }; Connection.prototype.destroy = function() { this.connection.destroy(); }; Connection.prototype.initialize_retry_vars = function () { this.retry_timer = null; this.retry_totaltime = 0; this.retry_delay = 150; this.retry_backoff = 1.7; this.attempts = 0; }; Connection.prototype.flush_offline_queue = function () { var self = this; var offline_queue = this.offline_queue; // Reset offline queue this.offline_queue = []; // Attempt to write queued items offline_queue.forEach(function(data) { self.write(data); }); }; Connection.prototype.write = function(data) { if (!this.connected) { this.offline_queue.push(data); return; } this.connection.write(data); }; Connection.prototype.connection_gone = function () { var self = this; this.connected = false; // If closed by manual, emit close event and cancel reconnect process if(this.forceClose) { if (this.retry_timer) { clearTimeout(this.retry_timer); this.retry_timer = null; } self.emit("close"); return; } // If a retry is already in progress, just let that happen if (this.retry_timer) { return; } // We cannot reconnect a secure socket. if (!this.max_attempts || this.ssl) { self.emit("close"); return; } if (this.retry_max_delay !== null && this.retry_delay >= this.retry_max_delay) { this.retry_delay = this.retry_max_delay; } else { this.retry_delay = Math.floor(this.retry_delay * this.retry_backoff); } log.debug("Retry connection in " + this.retry_delay + " ms"); if (this.max_attempts && this.attempts >= this.max_attempts) { this.retry_timer = null; console.error("thrift: Couldn't get thrift connection after " + this.max_attempts + " attempts."); self.emit("close"); return; } this.attempts += 1; this.emit("reconnecting", { delay: self.retry_delay, attempt: self.attempts }); this.retry_timer = setTimeout(function () { log.debug("Retrying connection..."); self.retry_totaltime += self.retry_delay; if (self.connect_timeout && self.retry_totaltime >= self.connect_timeout) { self.retry_timer = null; console.error("thrift: Couldn't get thrift connection after " + self.retry_totaltime + "ms."); self.emit("close"); return; } if (self.path !== undefined) { self.connection.connect(self.path); } else { self.connection.connect(self.port, self.host); } self.retry_timer = null; }, this.retry_delay); }; exports.createConnection = function(host, port, options) { var stream = net.createConnection( { port: port, host: host, timeout: options.connect_timeout || options.timeout || 0 }); var connection = new Connection(stream, options); connection.host = host; connection.port = port; return connection; }; exports.createUDSConnection = function(path, options) { var stream = net.createConnection(path); var connection = new Connection(stream, options); connection.path = path; return connection; }; exports.createSSLConnection = function(host, port, options) { if (!('secureProtocol' in options) && !('secureOptions' in options)) { options.secureProtocol = "SSLv23_method"; options.secureOptions = constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3; } var stream = tls.connect(port, host, options); var connection = new Connection(stream, options); connection.host = host; connection.port = port; return connection; }; exports.createClient = createClient; var child_process = require('child_process'); var StdIOConnection = exports.StdIOConnection = function(command, options) { var command_parts = command.split(' '); command = command_parts[0]; var args = command_parts.splice(1,command_parts.length -1); var child = this.child = child_process.spawn(command,args); var self = this; EventEmitter.call(this); this.connection = child.stdin; this.options = options || {}; this.transport = this.options.transport || TBufferedTransport; this.protocol = this.options.protocol || TBinaryProtocol; this.offline_queue = []; if (log.getLogLevel() === 'debug') { this.child.stderr.on('data', function (err) { log.debug(err.toString(), 'CHILD ERROR'); }); this.child.on('exit', function (code,signal) { log.debug(code + ':' + signal, 'CHILD EXITED'); }); } this.frameLeft = 0; this.framePos = 0; this.frame = null; this.connected = true; self.flush_offline_queue(); this.connection.addListener("error", function(err) { self.emit("error", err); }); // Add a close listener this.connection.addListener("close", function() { self.emit("close"); }); child.stdout.addListener("data", self.transport.receiver(function(transport_with_data) { var message = new self.protocol(transport_with_data); try { var header = message.readMessageBegin(); var dummy_seqid = header.rseqid * -1; var client = self.client; client._reqs[dummy_seqid] = function(err, success){ transport_with_data.commitPosition(); var callback = client._reqs[header.rseqid]; delete client._reqs[header.rseqid]; if (callback) { callback(err, success); } }; client['recv_' + header.fname](message, header.mtype, dummy_seqid); } catch (e) { if (e instanceof InputBufferUnderrunError) { transport_with_data.rollbackPosition(); } else { throw e; } } })); }; util.inherits(StdIOConnection, EventEmitter); StdIOConnection.prototype.end = function() { this.connection.end(); }; StdIOConnection.prototype.flush_offline_queue = function () { var self = this; var offline_queue = this.offline_queue; // Reset offline queue this.offline_queue = []; // Attempt to write queued items offline_queue.forEach(function(data) { self.write(data); }); }; StdIOConnection.prototype.write = function(data) { if (!this.connected) { this.offline_queue.push(data); return; } this.connection.write(data); }; exports.createStdIOConnection = function(command,options){ return new StdIOConnection(command,options); }; exports.createStdIOClient = createClient; thrift-0.19.0/lib/nodejs/lib/thrift/server.js0000644000000000000000000001115114303740367021047 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var constants = require('constants'); var net = require('net'); var tls = require('tls'); var TBufferedTransport = require('./buffered_transport'); var TBinaryProtocol = require('./binary_protocol'); var THeaderProtocol = require('./header_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); /** * Create a Thrift server which can serve one or multiple services. * @param {object} processor - A normal or multiplexedProcessor (must * be preconstructed with the desired handler). * @param {ServerOptions} options - Optional additional server configuration. * @returns {object} - The Apache Thrift Multiplex Server. */ exports.createMultiplexServer = function(processor, options) { var transport = (options && options.transport) ? options.transport : TBufferedTransport; var protocol = (options && options.protocol) ? options.protocol : TBinaryProtocol; function serverImpl(stream) { var self = this; stream.on('error', function(err) { self.emit('error', err); }); stream.on('data', transport.receiver(function(transportWithData) { var input = new protocol(transportWithData); var outputCb = function(buf) { try { stream.write(buf); } catch (err) { self.emit('error', err); stream.end(); } }; var output = new protocol(new transport(undefined, outputCb)); // Read and write need to be performed on the same transport // for THeaderProtocol because we should only respond with // headers if the request contains headers if (protocol === THeaderProtocol) { output = input; output.trans.onFlush = outputCb; } try { do { processor.process(input, output); transportWithData.commitPosition(); } while (true); } catch (err) { if (err instanceof InputBufferUnderrunError) { //The last data in the buffer was not a complete message, wait for the rest transportWithData.rollbackPosition(); } else if (err.message === "Invalid type: undefined") { //No more data in the buffer //This trap is a bit hackish //The next step to improve the node behavior here is to have // the compiler generated process method throw a more explicit // error when the network buffer is empty (regardles of the // protocol/transport stack in use) and replace this heuristic. // Also transports should probably not force upper layers to // manage their buffer positions (i.e. rollbackPosition() and // commitPosition() should be eliminated in lieu of a transport // encapsulated buffer management strategy.) transportWithData.rollbackPosition(); } else { //Unexpected error self.emit('error', err); stream.end(); } } })); stream.on('end', function() { stream.end(); }); } if (options && options.tls) { if (!('secureProtocol' in options.tls) && !('secureOptions' in options.tls)) { options.tls.secureProtocol = "SSLv23_method"; options.tls.secureOptions = constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3; } return tls.createServer(options.tls, serverImpl); } else { return net.createServer(serverImpl); } }; /** * Create a single service Apache Thrift server. * @param {object} processor - A service class or processor function. * @param {ServerOptions} options - Optional additional server configuration. * @returns {object} - The Apache Thrift Multiplex Server. */ exports.createServer = function(processor, handler, options) { if (processor.Processor) { processor = processor.Processor; } return exports.createMultiplexServer(new processor(handler), options); }; thrift-0.19.0/lib/nodejs/lib/thrift/buffered_transport.js0000644000000000000000000001231414452237057023443 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var binary = require('./binary'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var THeaderTransport = require('./header_transport'); module.exports = TBufferedTransport; function TBufferedTransport(buffer, callback) { THeaderTransport.call(this); this.defaultReadBufferSize = 1024; this.writeBufferSize = 512; // Soft Limit this.inBuf = new Buffer(this.defaultReadBufferSize); this.readCursor = 0; this.writeCursor = 0; // for input buffer this.outBuffers = []; this.outCount = 0; this.onFlush = callback; }; Object.setPrototypeOf(TBufferedTransport.prototype, THeaderTransport.prototype); TBufferedTransport.prototype.reset = function() { this.inBuf = new Buffer(this.defaultReadBufferSize); this.readCursor = 0; this.writeCursor = 0; this.outBuffers = []; this.outCount = 0; } TBufferedTransport.receiver = function(callback, seqid) { var reader = new TBufferedTransport(); return function(data) { if (reader.writeCursor + data.length > reader.inBuf.length) { var buf = new Buffer(reader.writeCursor + data.length); reader.inBuf.copy(buf, 0, 0, reader.writeCursor); reader.inBuf = buf; } data.copy(reader.inBuf, reader.writeCursor, 0); reader.writeCursor += data.length; callback(reader, seqid); }; }; TBufferedTransport.prototype.commitPosition = function(){ var unreadSize = this.writeCursor - this.readCursor; var bufSize = (unreadSize * 2 > this.defaultReadBufferSize) ? unreadSize * 2 : this.defaultReadBufferSize; var buf = new Buffer(bufSize); if (unreadSize > 0) { this.inBuf.copy(buf, 0, this.readCursor, this.writeCursor); } this.readCursor = 0; this.writeCursor = unreadSize; this.inBuf = buf; }; TBufferedTransport.prototype.rollbackPosition = function(){ this.readCursor = 0; } // TODO: Implement open/close support TBufferedTransport.prototype.isOpen = function() { return true; }; TBufferedTransport.prototype.open = function() { }; TBufferedTransport.prototype.close = function() { }; // Set the seqid of the message in the client // So that callbacks can be found TBufferedTransport.prototype.setCurrSeqId = function(seqid) { this._seqid = seqid; }; TBufferedTransport.prototype.ensureAvailable = function(len) { if (this.readCursor + len > this.writeCursor) { throw new InputBufferUnderrunError(); } }; TBufferedTransport.prototype.read = function(len) { this.ensureAvailable(len); var buf = new Buffer(len); this.inBuf.copy(buf, 0, this.readCursor, this.readCursor + len); this.readCursor += len; return buf; }; TBufferedTransport.prototype.readByte = function() { this.ensureAvailable(1); return binary.readByte(this.inBuf[this.readCursor++]); }; TBufferedTransport.prototype.readI16 = function() { this.ensureAvailable(2); var i16 = binary.readI16(this.inBuf, this.readCursor); this.readCursor += 2; return i16; }; TBufferedTransport.prototype.readI32 = function() { this.ensureAvailable(4); var i32 = binary.readI32(this.inBuf, this.readCursor); this.readCursor += 4; return i32; }; TBufferedTransport.prototype.readDouble = function() { this.ensureAvailable(8); var d = binary.readDouble(this.inBuf, this.readCursor); this.readCursor += 8; return d; }; TBufferedTransport.prototype.readString = function(len) { this.ensureAvailable(len); var str = this.inBuf.toString('utf8', this.readCursor, this.readCursor + len); this.readCursor += len; return str; }; TBufferedTransport.prototype.borrow = function() { var obj = {buf: this.inBuf, readIndex: this.readCursor, writeIndex: this.writeCursor}; return obj; }; TBufferedTransport.prototype.consume = function(bytesConsumed) { this.readCursor += bytesConsumed; }; TBufferedTransport.prototype.write = function(buf) { if (typeof(buf) === "string") { buf = new Buffer(buf, 'utf8'); } this.outBuffers.push(buf); this.outCount += buf.length; }; TBufferedTransport.prototype.flush = function() { // If the seqid of the callback is available pass it to the onFlush // Then remove the current seqid var seqid = this._seqid; this._seqid = null; if (this.outCount < 1) { return; } var msg = new Buffer(this.outCount), pos = 0; this.outBuffers.forEach(function(buf) { buf.copy(msg, pos, 0); pos += buf.length; }); if (this.onFlush) { // Passing seqid through this call to get it to the connection this.onFlush(msg, seqid); } this.outBuffers = []; this.outCount = 0; } thrift-0.19.0/lib/nodejs/lib/thrift/multiplexed_processor.js0000644000000000000000000000360314303740367024177 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var Thrift = require('./thrift'); exports.MultiplexedProcessor = MultiplexedProcessor; function MultiplexedProcessor(stream, options) { this.services = {}; }; MultiplexedProcessor.prototype.registerProcessor = function(name, handler) { this.services[name] = handler; }; MultiplexedProcessor.prototype.process = function(inp, out) { var begin = inp.readMessageBegin(); if (begin.mtype != Thrift.MessageType.CALL && begin.mtype != Thrift.MessageType.ONEWAY) { throw new Thrift.TException('TMultiplexedProcessor: Unexpected message type'); } var p = begin.fname.split(':'); var sname = p[0]; var fname = p[1]; if (! (sname in this.services)) { throw new Thrift.TException('TMultiplexedProcessor: Unknown service: ' + sname); } //construct a proxy object which stubs the readMessageBegin //for the service var inpProxy = {}; for (var attr in inp) { inpProxy[attr] = inp[attr]; } inpProxy.readMessageBegin = function() { return { fname: fname, mtype: begin.mtype, rseqid: begin.rseqid }; }; this.services[sname].process(inpProxy, out); }; thrift-0.19.0/lib/nodejs/lib/thrift/xhr_connection.js0000644000000000000000000002100314303740367022556 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var EventEmitter = require("events").EventEmitter; var thrift = require('./thrift'); var TBufferedTransport = require('./buffered_transport'); var TJSONProtocol = require('./json_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var createClient = require('./create_client'); exports.XHRConnection = XHRConnection; /** * Constructor Function for the XHR Connection. * If you do not specify a host and port then XHRConnection will default to the * host and port of the page from which this javascript is served. * @constructor * @param {string} [url] - The URL to connect to. * @classdesc TXHRConnection objects provide Thrift end point transport * semantics implemented using XHR. * @example * var transport = new Thrift.TXHRConnection('localhost', 9099, {}); */ function XHRConnection(host, port, options) { this.options = options || {}; this.wpos = 0; this.rpos = 0; this.useCORS = (options && options.useCORS); this.send_buf = ''; this.recv_buf = ''; this.transport = options.transport || TBufferedTransport; this.protocol = options.protocol || TJSONProtocol; this.headers = options.headers || {}; host = host || window.location.host; port = port || window.location.port; var prefix = options.https ? 'https://' : 'http://'; var path = options.path || '/'; if (port === '') { port = undefined; } if (!port || port === 80 || port === '80') { this.url = prefix + host + path; } else { this.url = prefix + host + ':' + port + path; } //The sequence map is used to map seqIDs back to the // calling client in multiplexed scenarios this.seqId2Service = {}; }; util.inherits(XHRConnection, EventEmitter); /** * Gets the browser specific XmlHttpRequest Object. * @returns {object} the browser XHR interface object */ XHRConnection.prototype.getXmlHttpRequestObject = function() { try { return new XMLHttpRequest(); } catch (e1) { } try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch (e2) { } try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch (e3) { } throw "Your browser doesn't support XHR."; }; /** * Sends the current XRH request if the transport was created with a URL * and the async parameter is false. If the transport was not created with * a URL, or the async parameter is True and no callback is provided, or * the URL is an empty string, the current send buffer is returned. * @param {object} async - If true the current send buffer is returned. * @param {object} callback - Optional async completion callback * @returns {undefined|string} Nothing or the current send buffer. * @throws {string} If XHR fails. */ XHRConnection.prototype.flush = function() { var self = this; if (this.url === undefined || this.url === '') { return this.send_buf; } var xreq = this.getXmlHttpRequestObject(); if (xreq.overrideMimeType) { xreq.overrideMimeType('application/json'); } xreq.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { self.setRecvBuffer(this.responseText); } }; xreq.open('POST', this.url, true); Object.keys(this.headers).forEach(function(headerKey) { xreq.setRequestHeader(headerKey, self.headers[headerKey]); }); xreq.send(this.send_buf); }; /** * Sets the buffer to provide the protocol when deserializing. * @param {string} buf - The buffer to supply the protocol. */ XHRConnection.prototype.setRecvBuffer = function(buf) { this.recv_buf = buf; this.recv_buf_sz = this.recv_buf.length; this.wpos = this.recv_buf.length; this.rpos = 0; if (Object.prototype.toString.call(buf) == "[object ArrayBuffer]") { var data = new Uint8Array(buf); } var thing = new Buffer(data || buf); this.transport.receiver(this.__decodeCallback.bind(this))(thing); }; XHRConnection.prototype.__decodeCallback = function(transport_with_data) { var proto = new this.protocol(transport_with_data); try { while (true) { var header = proto.readMessageBegin(); var dummy_seqid = header.rseqid * -1; var client = this.client; //The Multiplexed Protocol stores a hash of seqid to service names // in seqId2Service. If the SeqId is found in the hash we need to // lookup the appropriate client for this call. // The client var is a single client object when not multiplexing, // when using multiplexing it is a service name keyed hash of client // objects. //NOTE: The 2 way interdependencies between protocols, transports, // connections and clients in the Node.js implementation are irregular // and make the implementation difficult to extend and maintain. We // should bring this stuff inline with typical thrift I/O stack // operation soon. // --ra var service_name = this.seqId2Service[header.rseqid]; if (service_name) { client = this.client[service_name]; delete this.seqId2Service[header.rseqid]; } /*jshint -W083 */ client._reqs[dummy_seqid] = function(err, success) { transport_with_data.commitPosition(); var clientCallback = client._reqs[header.rseqid]; delete client._reqs[header.rseqid]; if (clientCallback) { clientCallback(err, success); } }; /*jshint +W083 */ if (client['recv_' + header.fname]) { client['recv_' + header.fname](proto, header.mtype, dummy_seqid); } else { delete client._reqs[dummy_seqid]; this.emit("error", new thrift.TApplicationException( thrift.TApplicationExceptionType.WRONG_METHOD_NAME, "Received a response to an unknown RPC function")); } } } catch (e) { if (e instanceof InputBufferUnderrunError) { transport_with_data.rollbackPosition(); } else { throw e; } } }; /** * Returns true if the transport is open, XHR always returns true. * @readonly * @returns {boolean} Always True. */ XHRConnection.prototype.isOpen = function() { return true; }; /** * Opens the transport connection, with XHR this is a nop. */ XHRConnection.prototype.open = function() {}; /** * Closes the transport connection, with XHR this is a nop. */ XHRConnection.prototype.close = function() {}; /** * Returns the specified number of characters from the response * buffer. * @param {number} len - The number of characters to return. * @returns {string} Characters sent by the server. */ XHRConnection.prototype.read = function(len) { var avail = this.wpos - this.rpos; if (avail === 0) { return ''; } var give = len; if (avail < len) { give = avail; } var ret = this.read_buf.substr(this.rpos, give); this.rpos += give; //clear buf when complete? return ret; }; /** * Returns the entire response buffer. * @returns {string} Characters sent by the server. */ XHRConnection.prototype.readAll = function() { return this.recv_buf; }; /** * Sets the send buffer to buf. * @param {string} buf - The buffer to send. */ XHRConnection.prototype.write = function(buf) { this.send_buf = buf; this.flush(); }; /** * Returns the send buffer. * @readonly * @returns {string} The send buffer. */ XHRConnection.prototype.getSendBuffer = function() { return this.send_buf; }; /** * Creates a new TXHRTransport object, used by Thrift clients to connect * to Thrift HTTP based servers. * @param {string} host - The host name or IP to connect to. * @param {number} port - The TCP port to connect to. * @param {XHRConnectOptions} options - The configuration options to use. * @returns {XHRConnection} The connection object. * @see {@link XHRConnectOptions} */ exports.createXHRConnection = function(host, port, options) { return new XHRConnection(host, port, options); }; exports.createXHRClient = createClient; thrift-0.19.0/lib/nodejs/lib/thrift/input_buffer_underrun_error.js0000644000000000000000000000221114303740367025361 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require("util"); module.exports = InputBufferUnderrunError; function InputBufferUnderrunError(message) { Error.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.name = this.constructor.name; this.message = message; }; util.inherits(InputBufferUnderrunError, Error); thrift-0.19.0/lib/nodejs/lib/thrift/int64_util.js0000644000000000000000000000632714303740367021553 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var Int64 = require('node-int64'); var Int64Util = module.exports = {}; var POW2_24 = Math.pow(2, 24); var POW2_31 = Math.pow(2, 31); var POW2_32 = Math.pow(2, 32); var POW10_11 = Math.pow(10, 11); Int64Util.toDecimalString = function(i64) { var b = i64.buffer; var o = i64.offset; if ((!b[o] && !(b[o + 1] & 0xe0)) || (!~b[o] && !~(b[o + 1] & 0xe0))) { // The magnitude is small enough. return i64.toString(); } else { var negative = b[o] & 0x80; if (negative) { // 2's complement var incremented = false; var buffer = new Buffer(8); for (var i = 7; i >= 0; --i) { buffer[i] = (~b[o + i] + (incremented ? 0 : 1)) & 0xff; incremented |= b[o + i]; } b = buffer; } var high2 = b[o + 1] + (b[o] << 8); // Lesser 11 digits with exceeding values but is under 53 bits capacity. var low = b[o + 7] + (b[o + 6] << 8) + (b[o + 5] << 16) + b[o + 4] * POW2_24 // Bit shift renders 32th bit as sign, so use multiplication + (b[o + 3] + (b[o + 2] << 8)) * POW2_32 + high2 * 74976710656; // The literal is 2^48 % 10^11 // 12th digit and greater. var high = Math.floor(low / POW10_11) + high2 * 2814; // The literal is 2^48 / 10^11 // Make it exactly 11 with leading zeros. low = ('00000000000' + String(low % POW10_11)).slice(-11); return (negative ? '-' : '') + String(high) + low; } }; Int64Util.fromDecimalString = function(text) { var negative = text.charAt(0) === '-'; if (text.length < (negative ? 17 : 16)) { // The magnitude is smaller than 2^53. return new Int64(+text); } else if (text.length > (negative ? 20 : 19)) { throw new RangeError('Too many digits for Int64: ' + text); } else { // Most significant (up to 5) digits var high5 = +text.slice(negative ? 1 : 0, -15); var low = +text.slice(-15) + high5 * 2764472320; // The literal is 10^15 % 2^32 var high = Math.floor(low / POW2_32) + high5 * 232830; // The literal is 10^15 / 2^&32 low = low % POW2_32; if (high >= POW2_31 && !(negative && high == POW2_31 && low == 0) // Allow minimum Int64 ) { throw new RangeError('The magnitude is too large for Int64.'); } if (negative) { // 2's complement high = ~high; if (low === 0) { high = (high + 1) & 0xffffffff; } else { low = ~low + 1; } high = 0x80000000 | high; } return new Int64(high, low); } }; thrift-0.19.0/lib/nodejs/lib/thrift/framed_transport.js0000644000000000000000000001214014452237057023114 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var binary = require('./binary'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var THeaderTransport = require('./header_transport'); module.exports = TFramedTransport; function TFramedTransport(buffer, callback) { THeaderTransport.call(this); this.inBuf = buffer || new Buffer(0); this.outBuffers = []; this.outCount = 0; this.readPos = 0; this.onFlush = callback; }; Object.setPrototypeOf(TFramedTransport.prototype, THeaderTransport.prototype); TFramedTransport.receiver = function(callback, seqid) { var residual = []; return function(data) { // push received data to residual for(var i = 0; i < data.length; ++i) { residual.push(data[i]) } while (residual.length > 0) { if (residual.length < 4) { // Not enough bytes to continue, save and resume on next packet return; } // get single package sieze var frameSize = binary.readI32(Buffer.from(residual.slice(0, 4)), 0); // Not enough bytes to continue, save and resume on next packet if (residual.length < 4 + frameSize) { return; } // splice first 4 bytes residual.splice(0, 4) // get package data var frame = Buffer.from(residual.splice(0, frameSize)); callback(new TFramedTransport(frame), seqid); } }; }; TFramedTransport.prototype.commitPosition = function(){}, TFramedTransport.prototype.rollbackPosition = function(){}, // TODO: Implement open/close support TFramedTransport.prototype.isOpen = function() { return true; }; TFramedTransport.prototype.open = function() {}; TFramedTransport.prototype.close = function() {}; // Set the seqid of the message in the client // So that callbacks can be found TFramedTransport.prototype.setCurrSeqId = function(seqid) { this._seqid = seqid; }; TFramedTransport.prototype.ensureAvailable = function(len) { if (this.readPos + len > this.inBuf.length) { throw new InputBufferUnderrunError(); } }; TFramedTransport.prototype.read = function(len) { // this function will be used for each frames. this.ensureAvailable(len); var end = this.readPos + len; if (this.inBuf.length < end) { throw new Error('read(' + len + ') failed - not enough data'); } var buf = this.inBuf.slice(this.readPos, end); this.readPos = end; return buf; }; TFramedTransport.prototype.readByte = function() { this.ensureAvailable(1); return binary.readByte(this.inBuf[this.readPos++]); }; TFramedTransport.prototype.readI16 = function() { this.ensureAvailable(2); var i16 = binary.readI16(this.inBuf, this.readPos); this.readPos += 2; return i16; }; TFramedTransport.prototype.readI32 = function() { this.ensureAvailable(4); var i32 = binary.readI32(this.inBuf, this.readPos); this.readPos += 4; return i32; }; TFramedTransport.prototype.readDouble = function() { this.ensureAvailable(8); var d = binary.readDouble(this.inBuf, this.readPos); this.readPos += 8; return d; }; TFramedTransport.prototype.readString = function(len) { this.ensureAvailable(len); var str = this.inBuf.toString('utf8', this.readPos, this.readPos + len); this.readPos += len; return str; }; TFramedTransport.prototype.borrow = function() { return { buf: this.inBuf, readIndex: this.readPos, writeIndex: this.inBuf.length }; }; TFramedTransport.prototype.consume = function(bytesConsumed) { this.readPos += bytesConsumed; }; TFramedTransport.prototype.write = function(buf, encoding) { if (typeof(buf) === "string") { buf = new Buffer(buf, encoding || 'utf8'); } this.outBuffers.push(buf); this.outCount += buf.length; }; TFramedTransport.prototype.flush = function() { // If the seqid of the callback is available pass it to the onFlush // Then remove the current seqid var seqid = this._seqid; this._seqid = null; var out = new Buffer(this.outCount), pos = 0; this.outBuffers.forEach(function(buf) { buf.copy(out, pos, 0); pos += buf.length; }); if (this.onFlush) { // TODO: optimize this better, allocate one buffer instead of both: var msg = new Buffer(out.length + 4); binary.writeI32(msg, out.length); out.copy(msg, 4, 0, out.length); if (this.onFlush) { // Passing seqid through this call to get it to the connection this.onFlush(msg, seqid); } } this.outBuffers = []; this.outCount = 0; }; thrift-0.19.0/lib/nodejs/lib/thrift/ohos_connection.js0000644000000000000000000002476314303740367022745 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var EventEmitter = require('events').EventEmitter; var thrift = require('./thrift'); var TBufferedTransport = require('./buffered_transport'); var TBinaryProtocol = require('./binary_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var createClient = require('./create_client'); /** * @class * @name ConnectOptions * @property {string} transport - The Thrift layered transport to use (TBufferedTransport, etc). * @property {string} protocol - The Thrift serialization protocol to use (TBinaryProtocol, etc.). * @property {string} path - The URL path to POST to (e.g. "/", "/mySvc", "/thrift/quoteSvc", etc.). * @property {object} header - A standard Node.js header hash, an object hash containing key/value * pairs where the key is the header name string and the value is the header value string. * @property {object} requestOptions - Options passed on to http request. Details: * https://developer.harmonyos.com/en/docs/documentation/doc-references/js-apis-net-http-0000001168304341#section12262183471518 * @example * //Use a connection that requires ssl/tls, closes the connection after each request, * // uses the buffered transport layer, uses the JSON protocol and directs RPC traffic * // to https://thrift.example.com:9090/hello * import http from '@ohos.net.http' // HTTP module of OpenHarmonyOS * var thrift = require('thrift'); * var options = { * transport: thrift.TBufferedTransport, * protocol: thrift.TJSONProtocol, * path: "/hello", * headers: {"Connection": "close"} * }; * // With OpenHarmonyOS HTTP module, HTTPS is supported by default. To support HTTP, See: * // https://developer.harmonyos.com/en/docs/documentation/doc-references/js-apis-net-http-0000001168304341#EN-US_TOPIC_0000001171944450__s56d19203690d4782bfc74069abb6bd71 * var con = thrift.createOhosConnection(http.createHttp, "thrift.example.com", 9090, options); * var client = thrift.createOhosClient(myService, connection); * client.myServiceFunction(); */ /** * Initializes a Thrift HttpConnection instance (use createHttpConnection() rather than * instantiating directly). * @constructor * @param {ConnectOptions} options - The configuration options to use. * @throws {error} Exceptions other than InputBufferUnderrunError are rethrown * @event {error} The "error" event is fired when a Node.js error event occurs during * request or response processing, in which case the node error is passed on. An "error" * event may also be fired when the connection can not map a response back to the * appropriate client (an internal error), generating a TApplicationException. * @classdesc OhosConnection objects provide Thrift end point transport * semantics implemented over the OpenHarmonyOS http.request() method. * @see {@link createOhosConnection} */ var OhosConnection = exports.OhosConnection = function(options) { //Initialize the emitter base object EventEmitter.call(this); //Set configuration var self = this; this.options = options || {}; this.host = this.options.host; this.port = this.options.port; this.path = this.options.path || '/'; //OpenHarmonyOS needs URL for initiating an HTTP request. this.url = this.port === 80 ? this.host.replace(/\/$/, '') + this.path : this.host.replace(/\/$/, '') + ':' + this.port + this.path; this.transport = this.options.transport || TBufferedTransport; this.protocol = this.options.protocol || TBinaryProtocol; //Inherit method from OpenHarmonyOS HTTP module this.createHttp = this.options.createHttp; //Prepare HTTP request options this.requestOptions = { method: 'POST', header: this.options.header || {}, readTimeout: this.options.readTimeout || 60000, connectTimeout: this.options.connectTimeout || 60000 }; for (var attrname in this.options.requestOptions) { this.requestOptions[attrname] = this.options.requestOptions[attrname]; } /*jshint -W069 */ if (!this.requestOptions.header['Connection']) { this.requestOptions.header['Connection'] = 'keep-alive'; } /*jshint +W069 */ //The sequence map is used to map seqIDs back to the // calling client in multiplexed scenarios this.seqId2Service = {}; function decodeCallback(transport_with_data) { var proto = new self.protocol(transport_with_data); try { while (true) { var header = proto.readMessageBegin(); var dummy_seqid = header.rseqid * -1; var client = self.client; //The Multiplexed Protocol stores a hash of seqid to service names // in seqId2Service. If the SeqId is found in the hash we need to // lookup the appropriate client for this call. // The client var is a single client object when not multiplexing, // when using multiplexing it is a service name keyed hash of client // objects. //NOTE: The 2 way interdependencies between protocols, transports, // connections and clients in the Node.js implementation are irregular // and make the implementation difficult to extend and maintain. We // should bring this stuff inline with typical thrift I/O stack // operation soon. // --ra var service_name = self.seqId2Service[header.rseqid]; if (service_name) { client = self.client[service_name]; delete self.seqId2Service[header.rseqid]; } /*jshint -W083 */ client._reqs[dummy_seqid] = function(err, success){ transport_with_data.commitPosition(); var clientCallback = client._reqs[header.rseqid]; delete client._reqs[header.rseqid]; if (clientCallback) { process.nextTick(function() { clientCallback(err, success); }); } }; /*jshint +W083 */ if(client['recv_' + header.fname]) { client['recv_' + header.fname](proto, header.mtype, dummy_seqid); } else { delete client._reqs[dummy_seqid]; self.emit("error", new thrift.TApplicationException( thrift.TApplicationExceptionType.WRONG_METHOD_NAME, "Received a response to an unknown RPC function")); } } } catch (e) { if (e instanceof InputBufferUnderrunError) { transport_with_data.rollbackPosition(); } else { self.emit('error', e); } } } //Response handler ////////////////////////////////////////////////// this.responseCallback = function(error, response) { //Response will be a struct like: // https://developer.harmonyos.com/en/docs/documentation/doc-references/js-apis-net-http-0000001168304341#section15920192914312 var data = []; var dataLen = 0; if (error) { self.emit('error', error); return; } if (!response || response.responseCode !== 200) { self.emit('error', new THTTPException(response)); } // With OpenHarmonyOS running in a Browser (e.g. Browserify), chunk // will be a string or an ArrayBuffer. if ( typeof response.result == 'string' || Object.prototype.toString.call(response.result) == '[object Uint8Array]' ) { // Wrap ArrayBuffer/string in a Buffer so data[i].copy will work data.push(Buffer.from(response.result)); } dataLen += response.result.length; var buf = Buffer.alloc(dataLen); for (var i = 0, len = data.length, pos = 0; i < len; i++) { data[i].copy(buf, pos); pos += data[i].length; } //Get the receiver function for the transport and // call it with the buffer self.transport.receiver(decodeCallback)(buf); }; /** * Writes Thrift message data to the connection * @param {Buffer} data - A Node.js Buffer containing the data to write * @returns {void} No return value. * @event {error} the "error" event is raised upon request failure passing the * Node.js error object to the listener. */ this.write = function(data) { //To initiate multiple HTTP requests, we must create an HttpRequest object // for each HTTP request var http = self.createHttp(); var opts = self.requestOptions; opts.header["Content-length"] = data.length; if (!opts.header["Content-Type"]) opts.header["Content-Type"] = "application/x-thrift"; // extraData not support array data currently opts.extraData = data.toString(); http.request(self.url, opts, self.responseCallback); }; }; util.inherits(OhosConnection, EventEmitter); /** * Creates a new OhosConnection object, used by Thrift clients to connect * to Thrift HTTP based servers. * @param {Function} createHttp - OpenHarmonyOS method to initiate or destroy an HTTP request. * @param {string} host - The host name or IP to connect to. * @param {number} port - The TCP port to connect to. * @param {ConnectOptions} options - The configuration options to use. * @returns {OhosConnection} The connection object. * @see {@link ConnectOptions} */ exports.createOhosConnection = function(createHttp, host, port, options) { options.createHttp = createHttp; options.host = host; options.port = port || 80; return new OhosConnection(options); }; exports.createOhosClient = createClient; function THTTPException(response) { thrift.TApplicationException.call(this); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } this.name = this.constructor.name; this.responseCode = response.responseCode; this.response = response; this.type = thrift.TApplicationExceptionType.PROTOCOL_ERROR; this.message = 'Received a response with a bad HTTP status code: ' + response.responseCode; } util.inherits(THTTPException, thrift.TApplicationException); thrift-0.19.0/lib/nodejs/lib/thrift/log.js0000644000000000000000000000427414303740367020332 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var util = require('util'); var disabled = function () {}; var logFunc = console.log; var logLevel = 'error'; // default level function factory(level) { return function () { // better use spread syntax, but due to compatibility, // use legacy method here. var args = ['thrift: [' + level + '] '].concat(Array.from(arguments)); return logFunc(util.format.apply(null, args)); }; } var trace = disabled; var debug = disabled; var error = disabled; var warning = disabled; var info = disabled; exports.setLogFunc = function (func) { logFunc = func; }; var setLogLevel = exports.setLogLevel = function (level) { trace = debug = error = warning = info = disabled; logLevel = level; switch (logLevel) { case 'trace': trace = factory('TRACE'); case 'debug': debug = factory('DEBUG'); case 'error': error = factory('ERROR'); case 'warning': warning = factory('WARN'); case 'info': info = factory('INFO'); } }; // set default setLogLevel(logLevel); exports.getLogLevel = function () { return logLevel; }; exports.trace = function () { return trace.apply(null, arguments); }; exports.debug = function () { return debug.apply(null, arguments); }; exports.error = function () { return error.apply(null, arguments); }; exports.warning = function () { return warning.apply(null, arguments); }; exports.info = function () { return info.apply(null, arguments); }; thrift-0.19.0/lib/nodejs/Makefile.in0000644000000000000000000004352114472652516017215 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # We call npm twice to work around npm issues VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/nodejs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ examples \ lib \ test \ coding_standards.md \ CMakeLists.txt \ README.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/nodejs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/nodejs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen js:node -o test/ $(top_srcdir)/test/v0.16/ThriftTest.thrift deps: $(top_srcdir)/package.json $(NPM) install $(top_srcdir)/ || $(NPM) install $(top_srcdir)/ all-local: deps precross: deps stubs # TODO: Lint nodejs lib and gen-code as part of build check: deps cd $(top_srcdir) && $(NPM) test && $(NPM) run lint-tests && cd lib/nodejs clean-local: $(RM) -r test/gen-* $(RM) -r $(top_srcdir)/node_modules $(RM) -r test/episodic-code-generation-test/gen* $(RM) -r test/episodic-code-generation-test/node_modules # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/0000755000000000000000000000000014472652670014306 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/Makefile.am0000644000000000000000000000307214303740367016336 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . if WITH_TESTS SUBDIRS += test SUBDIRS += test_recursive endif install: @echo '##############################################################' @echo '##############################################################' @echo 'The Rust client library should be installed via a Cargo.toml dependency - please see /lib/rs/README.md' @echo '##############################################################' @echo '##############################################################' check-local: $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) test all-local: $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) build clean-local: $(CARGO) clean -$(RM) Cargo.lock EXTRA_DIST = \ src \ Cargo.toml \ README.md \ release.sh \ RELEASING.md thrift-0.19.0/lib/rs/Cargo.toml0000644000000000000000000000125014454461475016235 0ustar00rootroot00000000000000[package] name = "thrift" description = "Rust bindings for the Apache Thrift RPC system" edition = "2021" version = "0.19.0" license = "Apache-2.0" authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" documentation = "https://docs.rs/thrift" repository = "https://github.com/apache/thrift/tree/master/lib/rs" readme = "README.md" exclude = ["Makefile*", "test/**", "*.iml"] keywords = ["thrift"] [dependencies] byteorder = "1.3" integer-encoding = "3.0.3" log = {version = "0.4", optional = true} ordered-float = "3.0" threadpool = {version = "1.7", optional = true} [features] default = ["server"] server = ["threadpool", "log"] thrift-0.19.0/lib/rs/src/0000777000000000000000000000000014303740367015073 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/src/errors.rs0000644000000000000000000005252114303740367016756 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::convert::TryFrom; use std::convert::{From, Into}; use std::fmt::{Debug, Display, Formatter}; use std::{error, fmt, io, string}; use crate::protocol::{ TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentifier, TType, }; // FIXME: should all my error structs impl error::Error as well? // FIXME: should all fields in TransportError, ProtocolError and ApplicationError be optional? /// Error type returned by all runtime library functions. /// /// `thrift::Error` is used throughout this crate as well as in auto-generated /// Rust code. It consists of four variants defined by convention across Thrift /// implementations: /// /// 1. `Transport`: errors encountered while operating on I/O channels /// 2. `Protocol`: errors encountered during runtime-library processing /// 3. `Application`: errors encountered within auto-generated code /// 4. `User`: IDL-defined exception structs /// /// The `Application` variant also functions as a catch-all: all handler errors /// are automatically turned into application errors. /// /// All error variants except `Error::User` take an eponymous struct with two /// required fields: /// /// 1. `kind`: variant-specific enum identifying the error sub-type /// 2. `message`: human-readable error info string /// /// `kind` is defined by convention while `message` is freeform. If none of the /// enumerated kinds are suitable use `Unknown`. /// /// To simplify error creation convenience constructors are defined for all /// variants, and conversions from their structs (`thrift::TransportError`, /// `thrift::ProtocolError` and `thrift::ApplicationError` into `thrift::Error`. /// /// # Examples /// /// Create a `TransportError`. /// /// ``` /// use thrift::{TransportError, TransportErrorKind}; /// /// // explicit /// let err0: thrift::Result<()> = Err( /// thrift::Error::Transport( /// TransportError { /// kind: TransportErrorKind::TimedOut, /// message: format!("connection to server timed out") /// } /// ) /// ); /// /// // use conversion /// let err1: thrift::Result<()> = Err( /// thrift::Error::from( /// TransportError { /// kind: TransportErrorKind::TimedOut, /// message: format!("connection to server timed out") /// } /// ) /// ); /// /// // use struct constructor /// let err2: thrift::Result<()> = Err( /// thrift::Error::Transport( /// TransportError::new( /// TransportErrorKind::TimedOut, /// "connection to server timed out" /// ) /// ) /// ); /// /// /// // use error variant constructor /// let err3: thrift::Result<()> = Err( /// thrift::new_transport_error( /// TransportErrorKind::TimedOut, /// "connection to server timed out" /// ) /// ); /// ``` /// /// Create an error from a string. /// /// ``` /// use thrift::{ApplicationError, ApplicationErrorKind}; /// /// // we just use `From::from` to convert a `String` into a `thrift::Error` /// let err0: thrift::Result<()> = Err( /// thrift::Error::from("This is an error") /// ); /// /// // err0 is equivalent to... /// let err1: thrift::Result<()> = Err( /// thrift::Error::Application( /// ApplicationError { /// kind: ApplicationErrorKind::Unknown, /// message: format!("This is an error") /// } /// ) /// ); /// ``` /// /// Return an IDL-defined exception. /// /// ```text /// // Thrift IDL exception definition. /// exception Xception { /// 1: i32 errorCode, /// 2: string message /// } /// ``` /// /// ``` /// use std::error::Error; /// use std::fmt; /// use std::fmt::{Display, Formatter}; /// /// // auto-generated by the Thrift compiler /// #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] /// pub struct Xception { /// pub error_code: Option, /// pub message: Option, /// } /// /// // auto-generated by the Thrift compiler /// impl Error for Xception { } /// /// // auto-generated by the Thrift compiler /// impl From for thrift::Error { /// fn from(e: Xception) -> Self { /// thrift::Error::User(Box::new(e)) /// } /// } /// /// // auto-generated by the Thrift compiler /// impl Display for Xception { /// fn fmt(&self, f: &mut Formatter) -> fmt::Result { /// write!(f, "remote service threw Xception") /// } /// } /// /// // in user code... /// let err: thrift::Result<()> = Err( /// thrift::Error::from(Xception { error_code: Some(1), message: None }) /// ); /// ``` pub enum Error { /// Errors encountered while operating on I/O channels. /// /// These include *connection closed* and *bind failure*. Transport(TransportError), /// Errors encountered during runtime-library processing. /// /// These include *message too large* and *unsupported protocol version*. Protocol(ProtocolError), /// Errors encountered within auto-generated code, or when incoming /// or outgoing messages violate the Thrift spec. /// /// These include *out-of-order messages* and *missing required struct /// fields*. /// /// This variant also functions as a catch-all: errors from handler /// functions are automatically returned as an `ApplicationError`. Application(ApplicationError), /// IDL-defined exception structs. User(Box), } impl Error { /// Create an `ApplicationError` from its wire representation. /// /// Application code **should never** call this method directly. pub fn read_application_error_from_in_protocol( i: &mut dyn TInputProtocol, ) -> crate::Result { let mut message = "general remote error".to_owned(); let mut kind = ApplicationErrorKind::Unknown; i.read_struct_begin()?; loop { let field_ident = i.read_field_begin()?; if field_ident.field_type == TType::Stop { break; } let id = field_ident .id .expect("sender should always specify id for non-STOP field"); match id { 1 => { let remote_message = i.read_string()?; i.read_field_end()?; message = remote_message; } 2 => { let remote_type_as_int = i.read_i32()?; let remote_kind: ApplicationErrorKind = TryFrom::try_from(remote_type_as_int) .unwrap_or(ApplicationErrorKind::Unknown); i.read_field_end()?; kind = remote_kind; } _ => { i.skip(field_ident.field_type)?; } } } i.read_struct_end()?; Ok(ApplicationError { kind, message }) } /// Convert an `ApplicationError` into its wire representation and write /// it to the remote. /// /// Application code **should never** call this method directly. pub fn write_application_error_to_out_protocol( e: &ApplicationError, o: &mut dyn TOutputProtocol, ) -> crate::Result<()> { o.write_struct_begin(&TStructIdentifier { name: "TApplicationException".to_owned(), })?; let message_field = TFieldIdentifier::new("message", TType::String, 1); let type_field = TFieldIdentifier::new("type", TType::I32, 2); o.write_field_begin(&message_field)?; o.write_string(&e.message)?; o.write_field_end()?; o.write_field_begin(&type_field)?; o.write_i32(e.kind as i32)?; o.write_field_end()?; o.write_field_stop()?; o.write_struct_end()?; o.flush() } } impl error::Error for Error {} impl Debug for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Error::Transport(ref e) => Debug::fmt(e, f), Error::Protocol(ref e) => Debug::fmt(e, f), Error::Application(ref e) => Debug::fmt(e, f), Error::User(ref e) => Debug::fmt(e, f), } } } impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Error::Transport(ref e) => Display::fmt(e, f), Error::Protocol(ref e) => Display::fmt(e, f), Error::Application(ref e) => Display::fmt(e, f), Error::User(ref e) => Display::fmt(e, f), } } } impl From for Error { fn from(s: String) -> Self { Error::Application(ApplicationError { kind: ApplicationErrorKind::Unknown, message: s, }) } } impl<'a> From<&'a str> for Error { fn from(s: &'a str) -> Self { Error::Application(ApplicationError { kind: ApplicationErrorKind::Unknown, message: String::from(s), }) } } impl From for Error { fn from(e: TransportError) -> Self { Error::Transport(e) } } impl From for Error { fn from(e: ProtocolError) -> Self { Error::Protocol(e) } } impl From for Error { fn from(e: ApplicationError) -> Self { Error::Application(e) } } /// Create a new `Error` instance of type `Transport` that wraps a /// `TransportError`. pub fn new_transport_error>(kind: TransportErrorKind, message: S) -> Error { Error::Transport(TransportError::new(kind, message)) } /// Information about I/O errors. #[derive(Debug, Eq, PartialEq)] pub struct TransportError { /// I/O error variant. /// /// If a specific `TransportErrorKind` does not apply use /// `TransportErrorKind::Unknown`. pub kind: TransportErrorKind, /// Human-readable error message. pub message: String, } impl TransportError { /// Create a new `TransportError`. pub fn new>(kind: TransportErrorKind, message: S) -> TransportError { TransportError { kind, message: message.into(), } } } /// I/O error categories. /// /// This list may grow, and it is not recommended to match against it. #[non_exhaustive] #[derive(Clone, Copy, Eq, Debug, PartialEq)] pub enum TransportErrorKind { /// Catch-all I/O error. Unknown = 0, /// An I/O operation was attempted when the transport channel was not open. NotOpen = 1, /// The transport channel cannot be opened because it was opened previously. AlreadyOpen = 2, /// An I/O operation timed out. TimedOut = 3, /// A read could not complete because no bytes were available. EndOfFile = 4, /// An invalid (buffer/message) size was requested or received. NegativeSize = 5, /// Too large a buffer or message size was requested or received. SizeLimit = 6, } impl Display for TransportError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let error_text = match self.kind { TransportErrorKind::Unknown => "transport error", TransportErrorKind::NotOpen => "not open", TransportErrorKind::AlreadyOpen => "already open", TransportErrorKind::TimedOut => "timed out", TransportErrorKind::EndOfFile => "end of file", TransportErrorKind::NegativeSize => "negative size message", TransportErrorKind::SizeLimit => "message too long", }; write!(f, "{}", error_text) } } impl TryFrom for TransportErrorKind { type Error = Error; fn try_from(from: i32) -> Result { match from { 0 => Ok(TransportErrorKind::Unknown), 1 => Ok(TransportErrorKind::NotOpen), 2 => Ok(TransportErrorKind::AlreadyOpen), 3 => Ok(TransportErrorKind::TimedOut), 4 => Ok(TransportErrorKind::EndOfFile), 5 => Ok(TransportErrorKind::NegativeSize), 6 => Ok(TransportErrorKind::SizeLimit), _ => Err(Error::Protocol(ProtocolError { kind: ProtocolErrorKind::Unknown, message: format!("cannot convert {} to TransportErrorKind", from), })), } } } impl From for Error { fn from(err: io::Error) -> Self { match err.kind() { io::ErrorKind::ConnectionReset | io::ErrorKind::ConnectionRefused | io::ErrorKind::NotConnected => Error::Transport(TransportError { kind: TransportErrorKind::NotOpen, message: err.to_string(), }), io::ErrorKind::AlreadyExists => Error::Transport(TransportError { kind: TransportErrorKind::AlreadyOpen, message: err.to_string(), }), io::ErrorKind::TimedOut => Error::Transport(TransportError { kind: TransportErrorKind::TimedOut, message: err.to_string(), }), io::ErrorKind::UnexpectedEof => Error::Transport(TransportError { kind: TransportErrorKind::EndOfFile, message: err.to_string(), }), _ => { Error::Transport(TransportError { kind: TransportErrorKind::Unknown, message: err.to_string(), // FIXME: use io error's debug string }) } } } } impl From for Error { fn from(err: string::FromUtf8Error) -> Self { Error::Protocol(ProtocolError { kind: ProtocolErrorKind::InvalidData, message: err.to_string(), // FIXME: use fmt::Error's debug string }) } } /// Create a new `Error` instance of type `Protocol` that wraps a /// `ProtocolError`. pub fn new_protocol_error>(kind: ProtocolErrorKind, message: S) -> Error { Error::Protocol(ProtocolError::new(kind, message)) } /// Information about errors that occur in the runtime library. #[derive(Debug, Eq, PartialEq)] pub struct ProtocolError { /// Protocol error variant. /// /// If a specific `ProtocolErrorKind` does not apply use /// `ProtocolErrorKind::Unknown`. pub kind: ProtocolErrorKind, /// Human-readable error message. pub message: String, } impl ProtocolError { /// Create a new `ProtocolError`. pub fn new>(kind: ProtocolErrorKind, message: S) -> ProtocolError { ProtocolError { kind, message: message.into(), } } } /// Runtime library error categories. /// /// This list may grow, and it is not recommended to match against it. #[non_exhaustive] #[derive(Clone, Copy, Eq, Debug, PartialEq)] pub enum ProtocolErrorKind { /// Catch-all runtime-library error. Unknown = 0, /// An invalid argument was supplied to a library function, or invalid data /// was received from a Thrift endpoint. InvalidData = 1, /// An invalid size was received in an encoded field. NegativeSize = 2, /// Thrift message or field was too long. SizeLimit = 3, /// Unsupported or unknown Thrift protocol version. BadVersion = 4, /// Unsupported Thrift protocol, server or field type. NotImplemented = 5, /// Reached the maximum nested depth to which an encoded Thrift field could /// be skipped. DepthLimit = 6, } impl Display for ProtocolError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let error_text = match self.kind { ProtocolErrorKind::Unknown => "protocol error", ProtocolErrorKind::InvalidData => "bad data", ProtocolErrorKind::NegativeSize => "negative message size", ProtocolErrorKind::SizeLimit => "message too long", ProtocolErrorKind::BadVersion => "invalid thrift version", ProtocolErrorKind::NotImplemented => "not implemented", ProtocolErrorKind::DepthLimit => "maximum skip depth reached", }; write!(f, "{}", error_text) } } impl TryFrom for ProtocolErrorKind { type Error = Error; fn try_from(from: i32) -> Result { match from { 0 => Ok(ProtocolErrorKind::Unknown), 1 => Ok(ProtocolErrorKind::InvalidData), 2 => Ok(ProtocolErrorKind::NegativeSize), 3 => Ok(ProtocolErrorKind::SizeLimit), 4 => Ok(ProtocolErrorKind::BadVersion), 5 => Ok(ProtocolErrorKind::NotImplemented), 6 => Ok(ProtocolErrorKind::DepthLimit), _ => Err(Error::Protocol(ProtocolError { kind: ProtocolErrorKind::Unknown, message: format!("cannot convert {} to ProtocolErrorKind", from), })), } } } /// Create a new `Error` instance of type `Application` that wraps an /// `ApplicationError`. pub fn new_application_error>(kind: ApplicationErrorKind, message: S) -> Error { Error::Application(ApplicationError::new(kind, message)) } /// Information about errors in auto-generated code or in user-implemented /// service handlers. #[derive(Debug, Eq, PartialEq)] pub struct ApplicationError { /// Application error variant. /// /// If a specific `ApplicationErrorKind` does not apply use /// `ApplicationErrorKind::Unknown`. pub kind: ApplicationErrorKind, /// Human-readable error message. pub message: String, } impl ApplicationError { /// Create a new `ApplicationError`. pub fn new>(kind: ApplicationErrorKind, message: S) -> ApplicationError { ApplicationError { kind, message: message.into(), } } } /// Auto-generated or user-implemented code error categories. /// /// This list may grow, and it is not recommended to match against it. #[non_exhaustive] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum ApplicationErrorKind { /// Catch-all application error. Unknown = 0, /// Made service call to an unknown service method. UnknownMethod = 1, /// Received an unknown Thrift message type. That is, not one of the /// `thrift::protocol::TMessageType` variants. InvalidMessageType = 2, /// Method name in a service reply does not match the name of the /// receiving service method. WrongMethodName = 3, /// Received an out-of-order Thrift message. BadSequenceId = 4, /// Service reply is missing required fields. MissingResult = 5, /// Auto-generated code failed unexpectedly. InternalError = 6, /// Thrift protocol error. When possible use `Error::ProtocolError` with a /// specific `ProtocolErrorKind` instead. ProtocolError = 7, /// *Unknown*. Included only for compatibility with existing Thrift implementations. InvalidTransform = 8, // ?? /// Thrift endpoint requested, or is using, an unsupported encoding. InvalidProtocol = 9, // ?? /// Thrift endpoint requested, or is using, an unsupported auto-generated client type. UnsupportedClientType = 10, // ?? } impl Display for ApplicationError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let error_text = match self.kind { ApplicationErrorKind::Unknown => "service error", ApplicationErrorKind::UnknownMethod => "unknown service method", ApplicationErrorKind::InvalidMessageType => "wrong message type received", ApplicationErrorKind::WrongMethodName => "unknown method reply received", ApplicationErrorKind::BadSequenceId => "out of order sequence id", ApplicationErrorKind::MissingResult => "missing method result", ApplicationErrorKind::InternalError => "remote service threw exception", ApplicationErrorKind::ProtocolError => "protocol error", ApplicationErrorKind::InvalidTransform => "invalid transform", ApplicationErrorKind::InvalidProtocol => "invalid protocol requested", ApplicationErrorKind::UnsupportedClientType => "unsupported protocol client", }; write!(f, "{}", error_text) } } impl TryFrom for ApplicationErrorKind { type Error = Error; fn try_from(from: i32) -> Result { match from { 0 => Ok(ApplicationErrorKind::Unknown), 1 => Ok(ApplicationErrorKind::UnknownMethod), 2 => Ok(ApplicationErrorKind::InvalidMessageType), 3 => Ok(ApplicationErrorKind::WrongMethodName), 4 => Ok(ApplicationErrorKind::BadSequenceId), 5 => Ok(ApplicationErrorKind::MissingResult), 6 => Ok(ApplicationErrorKind::InternalError), 7 => Ok(ApplicationErrorKind::ProtocolError), 8 => Ok(ApplicationErrorKind::InvalidTransform), 9 => Ok(ApplicationErrorKind::InvalidProtocol), 10 => Ok(ApplicationErrorKind::UnsupportedClientType), _ => Err(Error::Application(ApplicationError { kind: ApplicationErrorKind::Unknown, message: format!("cannot convert {} to ApplicationErrorKind", from), })), } } } thrift-0.19.0/lib/rs/src/protocol/0000777000000000000000000000000014370300523016722 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/src/protocol/mod.rs0000644000000000000000000007611114370300523020051 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //! Types used to send and receive primitives between a Thrift client and server. //! //! # Examples //! //! Create and use a `TInputProtocol`. //! //! ```no_run //! use thrift::protocol::{TBinaryInputProtocol, TInputProtocol}; //! use thrift::transport::TTcpChannel; //! //! // create the I/O channel //! let mut channel = TTcpChannel::new(); //! channel.open("127.0.0.1:9090").unwrap(); //! //! // create the protocol to decode bytes into types //! let mut protocol = TBinaryInputProtocol::new(channel, true); //! //! // read types from the wire //! let field_identifier = protocol.read_field_begin().unwrap(); //! let field_contents = protocol.read_string().unwrap(); //! let field_end = protocol.read_field_end().unwrap(); //! ``` //! //! Create and use a `TOutputProtocol`. //! //! ```no_run //! use thrift::protocol::{TBinaryOutputProtocol, TFieldIdentifier, TOutputProtocol, TType}; //! use thrift::transport::TTcpChannel; //! //! // create the I/O channel //! let mut channel = TTcpChannel::new(); //! channel.open("127.0.0.1:9090").unwrap(); //! //! // create the protocol to encode types into bytes //! let mut protocol = TBinaryOutputProtocol::new(channel, true); //! //! // write types //! protocol.write_field_begin(&TFieldIdentifier::new("string_thing", TType::String, 1)).unwrap(); //! protocol.write_string("foo").unwrap(); //! protocol.write_field_end().unwrap(); //! ``` use std::convert::{From, TryFrom}; use std::fmt; use std::fmt::{Display, Formatter}; use crate::transport::{TReadTransport, TWriteTransport}; use crate::{ProtocolError, ProtocolErrorKind}; #[cfg(test)] macro_rules! assert_eq_written_bytes { ($o_prot:ident, $expected_bytes:ident) => {{ assert_eq!($o_prot.transport.write_bytes(), &$expected_bytes); }}; } // FIXME: should take both read and write #[cfg(test)] macro_rules! copy_write_buffer_to_read_buffer { ($o_prot:ident) => {{ $o_prot.transport.copy_write_buffer_to_read_buffer(); }}; } #[cfg(test)] macro_rules! set_readable_bytes { ($i_prot:ident, $bytes:expr) => { $i_prot.transport.set_readable_bytes($bytes); }; } mod binary; mod compact; mod multiplexed; mod stored; pub use self::binary::{ TBinaryInputProtocol, TBinaryInputProtocolFactory, TBinaryOutputProtocol, TBinaryOutputProtocolFactory, }; pub use self::compact::{ TCompactInputProtocol, TCompactInputProtocolFactory, TCompactOutputProtocol, TCompactOutputProtocolFactory, }; pub use self::multiplexed::TMultiplexedOutputProtocol; pub use self::stored::TStoredInputProtocol; /// Reads and writes the struct to Thrift protocols. /// /// It is implemented in generated code for Thrift `struct`, `union`, and `enum` types. pub trait TSerializable: Sized { fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> crate::Result; fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> crate::Result<()>; } // Default maximum depth to which `TInputProtocol::skip` will skip a Thrift // field. A default is necessary because Thrift structs or collections may // contain nested structs and collections, which could result in indefinite // recursion. const MAXIMUM_SKIP_DEPTH: i8 = 64; /// Converts a stream of bytes into Thrift identifiers, primitives, /// containers, or structs. /// /// This trait does not deal with higher-level Thrift concepts like structs or /// exceptions - only with primitives and message or container boundaries. Once /// bytes are read they are deserialized and an identifier (for example /// `TMessageIdentifier`) or a primitive is returned. /// /// All methods return a `thrift::Result`. If an `Err` is returned the protocol /// instance and its underlying transport should be terminated. /// /// # Examples /// /// Create and use a `TInputProtocol` /// /// ```no_run /// use thrift::protocol::{TBinaryInputProtocol, TInputProtocol}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("127.0.0.1:9090").unwrap(); /// /// let mut protocol = TBinaryInputProtocol::new(channel, true); /// /// let field_identifier = protocol.read_field_begin().unwrap(); /// let field_contents = protocol.read_string().unwrap(); /// let field_end = protocol.read_field_end().unwrap(); /// ``` pub trait TInputProtocol { /// Read the beginning of a Thrift message. fn read_message_begin(&mut self) -> crate::Result; /// Read the end of a Thrift message. fn read_message_end(&mut self) -> crate::Result<()>; /// Read the beginning of a Thrift struct. fn read_struct_begin(&mut self) -> crate::Result>; /// Read the end of a Thrift struct. fn read_struct_end(&mut self) -> crate::Result<()>; /// Read the beginning of a Thrift struct field. fn read_field_begin(&mut self) -> crate::Result; /// Read the end of a Thrift struct field. fn read_field_end(&mut self) -> crate::Result<()>; /// Read a bool. fn read_bool(&mut self) -> crate::Result; /// Read a fixed-length byte array. fn read_bytes(&mut self) -> crate::Result>; /// Read a word. fn read_i8(&mut self) -> crate::Result; /// Read a 16-bit signed integer. fn read_i16(&mut self) -> crate::Result; /// Read a 32-bit signed integer. fn read_i32(&mut self) -> crate::Result; /// Read a 64-bit signed integer. fn read_i64(&mut self) -> crate::Result; /// Read a 64-bit float. fn read_double(&mut self) -> crate::Result; /// Read a fixed-length string (not null terminated). fn read_string(&mut self) -> crate::Result; /// Read the beginning of a list. fn read_list_begin(&mut self) -> crate::Result; /// Read the end of a list. fn read_list_end(&mut self) -> crate::Result<()>; /// Read the beginning of a set. fn read_set_begin(&mut self) -> crate::Result; /// Read the end of a set. fn read_set_end(&mut self) -> crate::Result<()>; /// Read the beginning of a map. fn read_map_begin(&mut self) -> crate::Result; /// Read the end of a map. fn read_map_end(&mut self) -> crate::Result<()>; /// Skip a field with type `field_type` recursively until the default /// maximum skip depth is reached. fn skip(&mut self, field_type: TType) -> crate::Result<()> { self.skip_till_depth(field_type, MAXIMUM_SKIP_DEPTH) } /// Skip a field with type `field_type` recursively up to `depth` levels. fn skip_till_depth(&mut self, field_type: TType, depth: i8) -> crate::Result<()> { if depth == 0 { return Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::DepthLimit, message: format!("cannot parse past {:?}", field_type), })); } match field_type { TType::Bool => self.read_bool().map(|_| ()), TType::I08 => self.read_i8().map(|_| ()), TType::I16 => self.read_i16().map(|_| ()), TType::I32 => self.read_i32().map(|_| ()), TType::I64 => self.read_i64().map(|_| ()), TType::Double => self.read_double().map(|_| ()), TType::String => self.read_string().map(|_| ()), TType::Struct => { self.read_struct_begin()?; loop { let field_ident = self.read_field_begin()?; if field_ident.field_type == TType::Stop { break; } self.skip_till_depth(field_ident.field_type, depth - 1)?; } self.read_struct_end() } TType::List => { let list_ident = self.read_list_begin()?; for _ in 0..list_ident.size { self.skip_till_depth(list_ident.element_type, depth - 1)?; } self.read_list_end() } TType::Set => { let set_ident = self.read_set_begin()?; for _ in 0..set_ident.size { self.skip_till_depth(set_ident.element_type, depth - 1)?; } self.read_set_end() } TType::Map => { let map_ident = self.read_map_begin()?; for _ in 0..map_ident.size { let key_type = map_ident .key_type .expect("non-zero sized map should contain key type"); let val_type = map_ident .value_type .expect("non-zero sized map should contain value type"); self.skip_till_depth(key_type, depth - 1)?; self.skip_till_depth(val_type, depth - 1)?; } self.read_map_end() } u => Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::Unknown, message: format!("cannot skip field type {:?}", &u), })), } } // utility (DO NOT USE IN GENERATED CODE!!!!) // /// Read an unsigned byte. /// /// This method should **never** be used in generated code. fn read_byte(&mut self) -> crate::Result; } /// Converts Thrift identifiers, primitives, containers or structs into a /// stream of bytes. /// /// This trait does not deal with higher-level Thrift concepts like structs or /// exceptions - only with primitives and message or container boundaries. /// Write methods take an identifier (for example, `TMessageIdentifier`) or a /// primitive. Any or all of the fields in an identifier may be omitted when /// writing to the transport. Write methods may even be noops. All of this is /// transparent to the caller; as long as a matching `TInputProtocol` /// implementation is used, received messages will be decoded correctly. /// /// All methods return a `thrift::Result`. If an `Err` is returned the protocol /// instance and its underlying transport should be terminated. /// /// # Examples /// /// Create and use a `TOutputProtocol` /// /// ```no_run /// use thrift::protocol::{TBinaryOutputProtocol, TFieldIdentifier, TOutputProtocol, TType}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("127.0.0.1:9090").unwrap(); /// /// let mut protocol = TBinaryOutputProtocol::new(channel, true); /// /// protocol.write_field_begin(&TFieldIdentifier::new("string_thing", TType::String, 1)).unwrap(); /// protocol.write_string("foo").unwrap(); /// protocol.write_field_end().unwrap(); /// ``` pub trait TOutputProtocol { /// Write the beginning of a Thrift message. fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()>; /// Write the end of a Thrift message. fn write_message_end(&mut self) -> crate::Result<()>; /// Write the beginning of a Thrift struct. fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> crate::Result<()>; /// Write the end of a Thrift struct. fn write_struct_end(&mut self) -> crate::Result<()>; /// Write the beginning of a Thrift field. fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()>; /// Write the end of a Thrift field. fn write_field_end(&mut self) -> crate::Result<()>; /// Write a STOP field indicating that all the fields in a struct have been /// written. fn write_field_stop(&mut self) -> crate::Result<()>; /// Write a bool. fn write_bool(&mut self, b: bool) -> crate::Result<()>; /// Write a fixed-length byte array. fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()>; /// Write an 8-bit signed integer. fn write_i8(&mut self, i: i8) -> crate::Result<()>; /// Write a 16-bit signed integer. fn write_i16(&mut self, i: i16) -> crate::Result<()>; /// Write a 32-bit signed integer. fn write_i32(&mut self, i: i32) -> crate::Result<()>; /// Write a 64-bit signed integer. fn write_i64(&mut self, i: i64) -> crate::Result<()>; /// Write a 64-bit float. fn write_double(&mut self, d: f64) -> crate::Result<()>; /// Write a fixed-length string. fn write_string(&mut self, s: &str) -> crate::Result<()>; /// Write the beginning of a list. fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()>; /// Write the end of a list. fn write_list_end(&mut self) -> crate::Result<()>; /// Write the beginning of a set. fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()>; /// Write the end of a set. fn write_set_end(&mut self) -> crate::Result<()>; /// Write the beginning of a map. fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()>; /// Write the end of a map. fn write_map_end(&mut self) -> crate::Result<()>; /// Flush buffered bytes to the underlying transport. fn flush(&mut self) -> crate::Result<()>; // utility (DO NOT USE IN GENERATED CODE!!!!) // /// Write an unsigned byte. /// /// This method should **never** be used in generated code. fn write_byte(&mut self, b: u8) -> crate::Result<()>; // FIXME: REMOVE } impl

TInputProtocol for Box

where P: TInputProtocol + ?Sized, { fn read_message_begin(&mut self) -> crate::Result { (**self).read_message_begin() } fn read_message_end(&mut self) -> crate::Result<()> { (**self).read_message_end() } fn read_struct_begin(&mut self) -> crate::Result> { (**self).read_struct_begin() } fn read_struct_end(&mut self) -> crate::Result<()> { (**self).read_struct_end() } fn read_field_begin(&mut self) -> crate::Result { (**self).read_field_begin() } fn read_field_end(&mut self) -> crate::Result<()> { (**self).read_field_end() } fn read_bool(&mut self) -> crate::Result { (**self).read_bool() } fn read_bytes(&mut self) -> crate::Result> { (**self).read_bytes() } fn read_i8(&mut self) -> crate::Result { (**self).read_i8() } fn read_i16(&mut self) -> crate::Result { (**self).read_i16() } fn read_i32(&mut self) -> crate::Result { (**self).read_i32() } fn read_i64(&mut self) -> crate::Result { (**self).read_i64() } fn read_double(&mut self) -> crate::Result { (**self).read_double() } fn read_string(&mut self) -> crate::Result { (**self).read_string() } fn read_list_begin(&mut self) -> crate::Result { (**self).read_list_begin() } fn read_list_end(&mut self) -> crate::Result<()> { (**self).read_list_end() } fn read_set_begin(&mut self) -> crate::Result { (**self).read_set_begin() } fn read_set_end(&mut self) -> crate::Result<()> { (**self).read_set_end() } fn read_map_begin(&mut self) -> crate::Result { (**self).read_map_begin() } fn read_map_end(&mut self) -> crate::Result<()> { (**self).read_map_end() } fn read_byte(&mut self) -> crate::Result { (**self).read_byte() } } impl

TOutputProtocol for Box

where P: TOutputProtocol + ?Sized, { fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> { (**self).write_message_begin(identifier) } fn write_message_end(&mut self) -> crate::Result<()> { (**self).write_message_end() } fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> crate::Result<()> { (**self).write_struct_begin(identifier) } fn write_struct_end(&mut self) -> crate::Result<()> { (**self).write_struct_end() } fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> { (**self).write_field_begin(identifier) } fn write_field_end(&mut self) -> crate::Result<()> { (**self).write_field_end() } fn write_field_stop(&mut self) -> crate::Result<()> { (**self).write_field_stop() } fn write_bool(&mut self, b: bool) -> crate::Result<()> { (**self).write_bool(b) } fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> { (**self).write_bytes(b) } fn write_i8(&mut self, i: i8) -> crate::Result<()> { (**self).write_i8(i) } fn write_i16(&mut self, i: i16) -> crate::Result<()> { (**self).write_i16(i) } fn write_i32(&mut self, i: i32) -> crate::Result<()> { (**self).write_i32(i) } fn write_i64(&mut self, i: i64) -> crate::Result<()> { (**self).write_i64(i) } fn write_double(&mut self, d: f64) -> crate::Result<()> { (**self).write_double(d) } fn write_string(&mut self, s: &str) -> crate::Result<()> { (**self).write_string(s) } fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> { (**self).write_list_begin(identifier) } fn write_list_end(&mut self) -> crate::Result<()> { (**self).write_list_end() } fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> { (**self).write_set_begin(identifier) } fn write_set_end(&mut self) -> crate::Result<()> { (**self).write_set_end() } fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> { (**self).write_map_begin(identifier) } fn write_map_end(&mut self) -> crate::Result<()> { (**self).write_map_end() } fn flush(&mut self) -> crate::Result<()> { (**self).flush() } fn write_byte(&mut self, b: u8) -> crate::Result<()> { (**self).write_byte(b) } } /// Helper type used by servers to create `TInputProtocol` instances for /// accepted client connections. /// /// # Examples /// /// Create a `TInputProtocolFactory` and use it to create a `TInputProtocol`. /// /// ```no_run /// use thrift::protocol::{TBinaryInputProtocolFactory, TInputProtocolFactory}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("127.0.0.1:9090").unwrap(); /// /// let factory = TBinaryInputProtocolFactory::new(); /// let protocol = factory.create(Box::new(channel)); /// ``` pub trait TInputProtocolFactory { // Create a `TInputProtocol` that reads bytes from `transport`. fn create(&self, transport: Box) -> Box; } impl TInputProtocolFactory for Box where T: TInputProtocolFactory + ?Sized, { fn create(&self, transport: Box) -> Box { (**self).create(transport) } } /// Helper type used by servers to create `TOutputProtocol` instances for /// accepted client connections. /// /// # Examples /// /// Create a `TOutputProtocolFactory` and use it to create a `TOutputProtocol`. /// /// ```no_run /// use thrift::protocol::{TBinaryOutputProtocolFactory, TOutputProtocolFactory}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("127.0.0.1:9090").unwrap(); /// /// let factory = TBinaryOutputProtocolFactory::new(); /// let protocol = factory.create(Box::new(channel)); /// ``` pub trait TOutputProtocolFactory { /// Create a `TOutputProtocol` that writes bytes to `transport`. fn create(&self, transport: Box) -> Box; } impl TOutputProtocolFactory for Box where T: TOutputProtocolFactory + ?Sized, { fn create( &self, transport: Box, ) -> Box { (**self).create(transport) } } /// Thrift message identifier. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TMessageIdentifier { /// Service call the message is associated with. pub name: String, /// Message type. pub message_type: TMessageType, /// Ordered sequence number identifying the message. pub sequence_number: i32, } impl TMessageIdentifier { /// Create a `TMessageIdentifier` for a Thrift service-call named `name` /// with message type `message_type` and sequence number `sequence_number`. pub fn new>( name: S, message_type: TMessageType, sequence_number: i32, ) -> TMessageIdentifier { TMessageIdentifier { name: name.into(), message_type, sequence_number, } } } /// Thrift struct identifier. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TStructIdentifier { /// Name of the encoded Thrift struct. pub name: String, } impl TStructIdentifier { /// Create a `TStructIdentifier` for a struct named `name`. pub fn new>(name: S) -> TStructIdentifier { TStructIdentifier { name: name.into() } } } /// Thrift field identifier. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TFieldIdentifier { /// Name of the Thrift field. /// /// `None` if it's not sent over the wire. pub name: Option, /// Field type. /// /// This may be a primitive, container, or a struct. pub field_type: TType, /// Thrift field id. /// /// `None` only if `field_type` is `TType::Stop`. pub id: Option, } impl TFieldIdentifier { /// Create a `TFieldIdentifier` for a field named `name` with type /// `field_type` and field id `id`. /// /// `id` should be `None` if `field_type` is `TType::Stop`. pub fn new(name: N, field_type: TType, id: I) -> TFieldIdentifier where N: Into>, S: Into, I: Into>, { TFieldIdentifier { name: name.into().map(|n| n.into()), field_type, id: id.into(), } } } /// Thrift list identifier. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TListIdentifier { /// Type of the elements in the list. pub element_type: TType, /// Number of elements in the list. pub size: i32, } impl TListIdentifier { /// Create a `TListIdentifier` for a list with `size` elements of type /// `element_type`. pub fn new(element_type: TType, size: i32) -> TListIdentifier { TListIdentifier { element_type, size } } } /// Thrift set identifier. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TSetIdentifier { /// Type of the elements in the set. pub element_type: TType, /// Number of elements in the set. pub size: i32, } impl TSetIdentifier { /// Create a `TSetIdentifier` for a set with `size` elements of type /// `element_type`. pub fn new(element_type: TType, size: i32) -> TSetIdentifier { TSetIdentifier { element_type, size } } } /// Thrift map identifier. #[derive(Clone, Debug, Eq, PartialEq)] pub struct TMapIdentifier { /// Map key type. pub key_type: Option, /// Map value type. pub value_type: Option, /// Number of entries in the map. pub size: i32, } impl TMapIdentifier { /// Create a `TMapIdentifier` for a map with `size` entries of type /// `key_type -> value_type`. pub fn new(key_type: K, value_type: V, size: i32) -> TMapIdentifier where K: Into>, V: Into>, { TMapIdentifier { key_type: key_type.into(), value_type: value_type.into(), size, } } } /// Thrift message types. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TMessageType { /// Service-call request. Call, /// Service-call response. Reply, /// Unexpected error in the remote service. Exception, /// One-way service-call request (no response is expected). OneWay, } impl Display for TMessageType { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { TMessageType::Call => write!(f, "Call"), TMessageType::Reply => write!(f, "Reply"), TMessageType::Exception => write!(f, "Exception"), TMessageType::OneWay => write!(f, "OneWay"), } } } impl From for u8 { fn from(message_type: TMessageType) -> Self { match message_type { TMessageType::Call => 0x01, TMessageType::Reply => 0x02, TMessageType::Exception => 0x03, TMessageType::OneWay => 0x04, } } } impl TryFrom for TMessageType { type Error = crate::Error; fn try_from(b: u8) -> Result { match b { 0x01 => Ok(TMessageType::Call), 0x02 => Ok(TMessageType::Reply), 0x03 => Ok(TMessageType::Exception), 0x04 => Ok(TMessageType::OneWay), unkn => Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::InvalidData, message: format!("cannot convert {} to TMessageType", unkn), })), } } } /// Thrift struct-field types. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TType { /// Indicates that there are no more serialized fields in this Thrift struct. Stop, /// Void (`()`) field. Void, /// Boolean. Bool, /// Signed 8-bit int. I08, /// Double-precision number. Double, /// Signed 16-bit int. I16, /// Signed 32-bit int. I32, /// Signed 64-bit int. I64, /// UTF-8 string. String, /// UTF-7 string. *Unsupported*. Utf7, /// Thrift struct. Struct, /// Map. Map, /// Set. Set, /// List. List, /// UTF-8 string. Utf8, /// UTF-16 string. *Unsupported*. Utf16, } impl Display for TType { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { TType::Stop => write!(f, "STOP"), TType::Void => write!(f, "void"), TType::Bool => write!(f, "bool"), TType::I08 => write!(f, "i08"), TType::Double => write!(f, "double"), TType::I16 => write!(f, "i16"), TType::I32 => write!(f, "i32"), TType::I64 => write!(f, "i64"), TType::String => write!(f, "string"), TType::Utf7 => write!(f, "UTF7"), TType::Struct => write!(f, "struct"), TType::Map => write!(f, "map"), TType::Set => write!(f, "set"), TType::List => write!(f, "list"), TType::Utf8 => write!(f, "UTF8"), TType::Utf16 => write!(f, "UTF16"), } } } /// Compare the expected message sequence number `expected` with the received /// message sequence number `actual`. /// /// Return `()` if `actual == expected`, `Err` otherwise. pub fn verify_expected_sequence_number(expected: i32, actual: i32) -> crate::Result<()> { if expected == actual { Ok(()) } else { Err(crate::Error::Application(crate::ApplicationError { kind: crate::ApplicationErrorKind::BadSequenceId, message: format!("expected {} got {}", expected, actual), })) } } /// Compare the expected service-call name `expected` with the received /// service-call name `actual`. /// /// Return `()` if `actual == expected`, `Err` otherwise. pub fn verify_expected_service_call(expected: &str, actual: &str) -> crate::Result<()> { if expected == actual { Ok(()) } else { Err(crate::Error::Application(crate::ApplicationError { kind: crate::ApplicationErrorKind::WrongMethodName, message: format!("expected {} got {}", expected, actual), })) } } /// Compare the expected message type `expected` with the received message type /// `actual`. /// /// Return `()` if `actual == expected`, `Err` otherwise. pub fn verify_expected_message_type( expected: TMessageType, actual: TMessageType, ) -> crate::Result<()> { if expected == actual { Ok(()) } else { Err(crate::Error::Application(crate::ApplicationError { kind: crate::ApplicationErrorKind::InvalidMessageType, message: format!("expected {} got {}", expected, actual), })) } } /// Check if a required Thrift struct field exists. /// /// Return `()` if it does, `Err` otherwise. pub fn verify_required_field_exists(field_name: &str, field: &Option) -> crate::Result<()> { match *field { Some(_) => Ok(()), None => Err(crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::Unknown, message: format!("missing required field {}", field_name), })), } } /// Extract the field id from a Thrift field identifier. /// /// `field_ident` must *not* have `TFieldIdentifier.field_type` of type `TType::Stop`. /// /// Return `TFieldIdentifier.id` if an id exists, `Err` otherwise. pub fn field_id(field_ident: &TFieldIdentifier) -> crate::Result { field_ident.id.ok_or_else(|| { crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::Unknown, message: format!("missing field id in {:?}", field_ident), }) }) } #[cfg(test)] mod tests { use std::io::Cursor; use super::*; use crate::transport::{TReadTransport, TWriteTransport}; #[test] fn must_create_usable_input_protocol_from_concrete_input_protocol() { let r: Box = Box::new(Cursor::new([0, 1, 2])); let mut t = TCompactInputProtocol::new(r); takes_input_protocol(&mut t) } #[test] fn must_create_usable_input_protocol_from_boxed_input() { let r: Box = Box::new(Cursor::new([0, 1, 2])); let mut t: Box = Box::new(TCompactInputProtocol::new(r)); takes_input_protocol(&mut t) } #[test] fn must_create_usable_output_protocol_from_concrete_output_protocol() { let w: Box = Box::new(vec![0u8; 10]); let mut t = TCompactOutputProtocol::new(w); takes_output_protocol(&mut t) } #[test] fn must_create_usable_output_protocol_from_boxed_output() { let w: Box = Box::new(vec![0u8; 10]); let mut t: Box = Box::new(TCompactOutputProtocol::new(w)); takes_output_protocol(&mut t) } fn takes_input_protocol(t: &mut R) where R: TInputProtocol, { t.read_byte().unwrap(); } fn takes_output_protocol(t: &mut W) where W: TOutputProtocol, { t.flush().unwrap(); } } thrift-0.19.0/lib/rs/src/protocol/multiplexed.rs0000644000000000000000000001670614303740367021644 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use super::{ TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, }; /// `TOutputProtocol` that prefixes the service name to all outgoing Thrift /// messages. /// /// A `TMultiplexedOutputProtocol` should be used when multiple Thrift services /// send messages over a single I/O channel. By prefixing service identifiers /// to outgoing messages receivers are able to demux them and route them to the /// appropriate service processor. Rust receivers must use a `TMultiplexedProcessor` /// to process incoming messages, while other languages must use their /// corresponding multiplexed processor implementations. /// /// For example, given a service `TestService` and a service call `test_call`, /// this implementation would identify messages as originating from /// `TestService:test_call`. /// /// # Examples /// /// Create and use a `TMultiplexedOutputProtocol`. /// /// ```no_run /// use thrift::protocol::{TMessageIdentifier, TMessageType, TOutputProtocol}; /// use thrift::protocol::{TBinaryOutputProtocol, TMultiplexedOutputProtocol}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("localhost:9090").unwrap(); /// /// let protocol = TBinaryOutputProtocol::new(channel, true); /// let mut protocol = TMultiplexedOutputProtocol::new("service_name", protocol); /// /// let ident = TMessageIdentifier::new("svc_call", TMessageType::Call, 1); /// protocol.write_message_begin(&ident).unwrap(); /// ``` #[derive(Debug)] pub struct TMultiplexedOutputProtocol

where P: TOutputProtocol, { service_name: String, inner: P, } impl

TMultiplexedOutputProtocol

where P: TOutputProtocol, { /// Create a `TMultiplexedOutputProtocol` that identifies outgoing messages /// as originating from a service named `service_name` and sends them over /// the `wrapped` `TOutputProtocol`. Outgoing messages are encoded and sent /// by `wrapped`, not by this instance. pub fn new(service_name: &str, wrapped: P) -> TMultiplexedOutputProtocol

{ TMultiplexedOutputProtocol { service_name: service_name.to_owned(), inner: wrapped, } } } // FIXME: avoid passthrough methods impl

TOutputProtocol for TMultiplexedOutputProtocol

where P: TOutputProtocol, { fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> { match identifier.message_type { // FIXME: is there a better way to override identifier here? TMessageType::Call | TMessageType::OneWay => { let identifier = TMessageIdentifier { name: format!("{}:{}", self.service_name, identifier.name), ..*identifier }; self.inner.write_message_begin(&identifier) } _ => self.inner.write_message_begin(identifier), } } fn write_message_end(&mut self) -> crate::Result<()> { self.inner.write_message_end() } fn write_struct_begin(&mut self, identifier: &TStructIdentifier) -> crate::Result<()> { self.inner.write_struct_begin(identifier) } fn write_struct_end(&mut self) -> crate::Result<()> { self.inner.write_struct_end() } fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> { self.inner.write_field_begin(identifier) } fn write_field_end(&mut self) -> crate::Result<()> { self.inner.write_field_end() } fn write_field_stop(&mut self) -> crate::Result<()> { self.inner.write_field_stop() } fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> { self.inner.write_bytes(b) } fn write_bool(&mut self, b: bool) -> crate::Result<()> { self.inner.write_bool(b) } fn write_i8(&mut self, i: i8) -> crate::Result<()> { self.inner.write_i8(i) } fn write_i16(&mut self, i: i16) -> crate::Result<()> { self.inner.write_i16(i) } fn write_i32(&mut self, i: i32) -> crate::Result<()> { self.inner.write_i32(i) } fn write_i64(&mut self, i: i64) -> crate::Result<()> { self.inner.write_i64(i) } fn write_double(&mut self, d: f64) -> crate::Result<()> { self.inner.write_double(d) } fn write_string(&mut self, s: &str) -> crate::Result<()> { self.inner.write_string(s) } fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> { self.inner.write_list_begin(identifier) } fn write_list_end(&mut self) -> crate::Result<()> { self.inner.write_list_end() } fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> { self.inner.write_set_begin(identifier) } fn write_set_end(&mut self) -> crate::Result<()> { self.inner.write_set_end() } fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> { self.inner.write_map_begin(identifier) } fn write_map_end(&mut self) -> crate::Result<()> { self.inner.write_map_end() } fn flush(&mut self) -> crate::Result<()> { self.inner.flush() } // utility // fn write_byte(&mut self, b: u8) -> crate::Result<()> { self.inner.write_byte(b) } } #[cfg(test)] mod tests { use crate::protocol::{ TBinaryOutputProtocol, TMessageIdentifier, TMessageType, TOutputProtocol, }; use crate::transport::{TBufferChannel, TIoChannel, WriteHalf}; use super::*; #[test] fn must_write_message_begin_with_prefixed_service_name() { let mut o_prot = test_objects(); let ident = TMessageIdentifier::new("bar", TMessageType::Call, 2); assert_success!(o_prot.write_message_begin(&ident)); #[rustfmt::skip] let expected: [u8; 19] = [ 0x80, 0x01, /* protocol identifier */ 0x00, 0x01, /* message type */ 0x00, 0x00, 0x00, 0x07, 0x66, 0x6F, 0x6F, /* "foo" */ 0x3A, /* ":" */ 0x62, 0x61, 0x72, /* "bar" */ 0x00, 0x00, 0x00, 0x02 /* sequence number */, ]; assert_eq!(o_prot.inner.transport.write_bytes(), expected); } fn test_objects() -> TMultiplexedOutputProtocol>> { let c = TBufferChannel::with_capacity(40, 40); let (_, w_chan) = c.split().unwrap(); let prot = TBinaryOutputProtocol::new(w_chan, true); TMultiplexedOutputProtocol::new("foo", prot) } } thrift-0.19.0/lib/rs/src/protocol/binary.rs0000644000000000000000000006752414303740367020600 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt}; use std::convert::{From, TryFrom}; use super::{ TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, }; use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType}; use crate::transport::{TReadTransport, TWriteTransport}; use crate::{ProtocolError, ProtocolErrorKind}; const BINARY_PROTOCOL_VERSION_1: u32 = 0x8001_0000; /// Read messages encoded in the Thrift simple binary encoding. /// /// There are two available modes: `strict` and `non-strict`, where the /// `non-strict` version does not check for the protocol version in the /// received message header. /// /// # Examples /// /// Create and use a `TBinaryInputProtocol`. /// /// ```no_run /// use thrift::protocol::{TBinaryInputProtocol, TInputProtocol}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("localhost:9090").unwrap(); /// /// let mut protocol = TBinaryInputProtocol::new(channel, true); /// /// let recvd_bool = protocol.read_bool().unwrap(); /// let recvd_string = protocol.read_string().unwrap(); /// ``` #[derive(Debug)] pub struct TBinaryInputProtocol where T: TReadTransport, { strict: bool, pub transport: T, // FIXME: shouldn't be public } impl<'a, T> TBinaryInputProtocol where T: TReadTransport, { /// Create a `TBinaryInputProtocol` that reads bytes from `transport`. /// /// Set `strict` to `true` if all incoming messages contain the protocol /// version number in the protocol header. pub fn new(transport: T, strict: bool) -> TBinaryInputProtocol { TBinaryInputProtocol { strict, transport } } } impl TInputProtocol for TBinaryInputProtocol where T: TReadTransport, { #[allow(clippy::collapsible_if)] fn read_message_begin(&mut self) -> crate::Result { let mut first_bytes = vec![0; 4]; self.transport.read_exact(&mut first_bytes[..])?; // the thrift version header is intentionally negative // so the first check we'll do is see if the sign bit is set // and if so - assume it's the protocol-version header if (first_bytes[0] & 0x80) != 0 { // apparently we got a protocol-version header - check // it, and if it matches, read the rest of the fields if first_bytes[0..2] != [0x80, 0x01] { Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::BadVersion, message: format!("received bad version: {:?}", &first_bytes[0..2]), })) } else { let message_type: TMessageType = TryFrom::try_from(first_bytes[3])?; let name = self.read_string()?; let sequence_number = self.read_i32()?; Ok(TMessageIdentifier::new(name, message_type, sequence_number)) } } else { // apparently we didn't get a protocol-version header, // which happens if the sender is not using the strict protocol if self.strict { // we're in strict mode however, and that always // requires the protocol-version header to be written first Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::BadVersion, message: format!("received bad version: {:?}", &first_bytes[0..2]), })) } else { // in the non-strict version the first message field // is the message name. strings (byte arrays) are length-prefixed, // so we've just read the length in the first 4 bytes let name_size = BigEndian::read_i32(&first_bytes) as usize; let mut name_buf: Vec = vec![0; name_size]; self.transport.read_exact(&mut name_buf)?; let name = String::from_utf8(name_buf)?; // read the rest of the fields let message_type: TMessageType = self.read_byte().and_then(TryFrom::try_from)?; let sequence_number = self.read_i32()?; Ok(TMessageIdentifier::new(name, message_type, sequence_number)) } } } fn read_message_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_struct_begin(&mut self) -> crate::Result> { Ok(None) } fn read_struct_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_field_begin(&mut self) -> crate::Result { let field_type_byte = self.read_byte()?; let field_type = field_type_from_u8(field_type_byte)?; let id = match field_type { TType::Stop => Ok(0), _ => self.read_i16(), }?; Ok(TFieldIdentifier::new::, String, i16>( None, field_type, id, )) } fn read_field_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_bytes(&mut self) -> crate::Result> { let num_bytes = self.transport.read_i32::()? as usize; let mut buf = vec![0u8; num_bytes]; self.transport .read_exact(&mut buf) .map(|_| buf) .map_err(From::from) } fn read_bool(&mut self) -> crate::Result { let b = self.read_i8()?; match b { 0 => Ok(false), _ => Ok(true), } } fn read_i8(&mut self) -> crate::Result { self.transport.read_i8().map_err(From::from) } fn read_i16(&mut self) -> crate::Result { self.transport.read_i16::().map_err(From::from) } fn read_i32(&mut self) -> crate::Result { self.transport.read_i32::().map_err(From::from) } fn read_i64(&mut self) -> crate::Result { self.transport.read_i64::().map_err(From::from) } fn read_double(&mut self) -> crate::Result { self.transport.read_f64::().map_err(From::from) } fn read_string(&mut self) -> crate::Result { let bytes = self.read_bytes()?; String::from_utf8(bytes).map_err(From::from) } fn read_list_begin(&mut self) -> crate::Result { let element_type: TType = self.read_byte().and_then(field_type_from_u8)?; let size = self.read_i32()?; Ok(TListIdentifier::new(element_type, size)) } fn read_list_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_set_begin(&mut self) -> crate::Result { let element_type: TType = self.read_byte().and_then(field_type_from_u8)?; let size = self.read_i32()?; Ok(TSetIdentifier::new(element_type, size)) } fn read_set_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_map_begin(&mut self) -> crate::Result { let key_type: TType = self.read_byte().and_then(field_type_from_u8)?; let value_type: TType = self.read_byte().and_then(field_type_from_u8)?; let size = self.read_i32()?; Ok(TMapIdentifier::new(key_type, value_type, size)) } fn read_map_end(&mut self) -> crate::Result<()> { Ok(()) } // utility // fn read_byte(&mut self) -> crate::Result { self.transport.read_u8().map_err(From::from) } } /// Factory for creating instances of `TBinaryInputProtocol`. #[derive(Default)] pub struct TBinaryInputProtocolFactory; impl TBinaryInputProtocolFactory { /// Create a `TBinaryInputProtocolFactory`. pub fn new() -> TBinaryInputProtocolFactory { TBinaryInputProtocolFactory {} } } impl TInputProtocolFactory for TBinaryInputProtocolFactory { fn create(&self, transport: Box) -> Box { Box::new(TBinaryInputProtocol::new(transport, true)) } } /// Write messages using the Thrift simple binary encoding. /// /// There are two available modes: `strict` and `non-strict`, where the /// `strict` version writes the protocol version number in the outgoing message /// header and the `non-strict` version does not. /// /// # Examples /// /// Create and use a `TBinaryOutputProtocol`. /// /// ```no_run /// use thrift::protocol::{TBinaryOutputProtocol, TOutputProtocol}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("localhost:9090").unwrap(); /// /// let mut protocol = TBinaryOutputProtocol::new(channel, true); /// /// protocol.write_bool(true).unwrap(); /// protocol.write_string("test_string").unwrap(); /// ``` #[derive(Debug)] pub struct TBinaryOutputProtocol where T: TWriteTransport, { strict: bool, pub transport: T, // FIXME: do not make public; only public for testing! } impl TBinaryOutputProtocol where T: TWriteTransport, { /// Create a `TBinaryOutputProtocol` that writes bytes to `transport`. /// /// Set `strict` to `true` if all outgoing messages should contain the /// protocol version number in the protocol header. pub fn new(transport: T, strict: bool) -> TBinaryOutputProtocol { TBinaryOutputProtocol { strict, transport } } } impl TOutputProtocol for TBinaryOutputProtocol where T: TWriteTransport, { fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> { if self.strict { let message_type: u8 = identifier.message_type.into(); let header = BINARY_PROTOCOL_VERSION_1 | (message_type as u32); self.transport.write_u32::(header)?; self.write_string(&identifier.name)?; self.write_i32(identifier.sequence_number) } else { self.write_string(&identifier.name)?; self.write_byte(identifier.message_type.into())?; self.write_i32(identifier.sequence_number) } } fn write_message_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> { Ok(()) } fn write_struct_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> { if identifier.id.is_none() && identifier.field_type != TType::Stop { return Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::Unknown, message: format!( "cannot write identifier {:?} without sequence number", &identifier ), })); } self.write_byte(field_type_to_u8(identifier.field_type))?; if let Some(id) = identifier.id { self.write_i16(id) } else { Ok(()) } } fn write_field_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_field_stop(&mut self) -> crate::Result<()> { self.write_byte(field_type_to_u8(TType::Stop)) } fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> { self.write_i32(b.len() as i32)?; self.transport.write_all(b).map_err(From::from) } fn write_bool(&mut self, b: bool) -> crate::Result<()> { if b { self.write_i8(1) } else { self.write_i8(0) } } fn write_i8(&mut self, i: i8) -> crate::Result<()> { self.transport.write_i8(i).map_err(From::from) } fn write_i16(&mut self, i: i16) -> crate::Result<()> { self.transport.write_i16::(i).map_err(From::from) } fn write_i32(&mut self, i: i32) -> crate::Result<()> { self.transport.write_i32::(i).map_err(From::from) } fn write_i64(&mut self, i: i64) -> crate::Result<()> { self.transport.write_i64::(i).map_err(From::from) } fn write_double(&mut self, d: f64) -> crate::Result<()> { self.transport.write_f64::(d).map_err(From::from) } fn write_string(&mut self, s: &str) -> crate::Result<()> { self.write_bytes(s.as_bytes()) } fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> { self.write_byte(field_type_to_u8(identifier.element_type))?; self.write_i32(identifier.size) } fn write_list_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> { self.write_byte(field_type_to_u8(identifier.element_type))?; self.write_i32(identifier.size) } fn write_set_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> { let key_type = identifier .key_type .expect("map identifier to write should contain key type"); self.write_byte(field_type_to_u8(key_type))?; let val_type = identifier .value_type .expect("map identifier to write should contain value type"); self.write_byte(field_type_to_u8(val_type))?; self.write_i32(identifier.size) } fn write_map_end(&mut self) -> crate::Result<()> { Ok(()) } fn flush(&mut self) -> crate::Result<()> { self.transport.flush().map_err(From::from) } // utility // fn write_byte(&mut self, b: u8) -> crate::Result<()> { self.transport.write_u8(b).map_err(From::from) } } /// Factory for creating instances of `TBinaryOutputProtocol`. #[derive(Default)] pub struct TBinaryOutputProtocolFactory; impl TBinaryOutputProtocolFactory { /// Create a `TBinaryOutputProtocolFactory`. pub fn new() -> TBinaryOutputProtocolFactory { TBinaryOutputProtocolFactory {} } } impl TOutputProtocolFactory for TBinaryOutputProtocolFactory { fn create( &self, transport: Box, ) -> Box { Box::new(TBinaryOutputProtocol::new(transport, true)) } } fn field_type_to_u8(field_type: TType) -> u8 { match field_type { TType::Stop => 0x00, TType::Void => 0x01, TType::Bool => 0x02, TType::I08 => 0x03, // equivalent to TType::Byte TType::Double => 0x04, TType::I16 => 0x06, TType::I32 => 0x08, TType::I64 => 0x0A, TType::String | TType::Utf7 => 0x0B, TType::Struct => 0x0C, TType::Map => 0x0D, TType::Set => 0x0E, TType::List => 0x0F, TType::Utf8 => 0x10, TType::Utf16 => 0x11, } } fn field_type_from_u8(b: u8) -> crate::Result { match b { 0x00 => Ok(TType::Stop), 0x01 => Ok(TType::Void), 0x02 => Ok(TType::Bool), 0x03 => Ok(TType::I08), // Equivalent to TType::Byte 0x04 => Ok(TType::Double), 0x06 => Ok(TType::I16), 0x08 => Ok(TType::I32), 0x0A => Ok(TType::I64), 0x0B => Ok(TType::String), // technically, also a UTF7, but we'll treat it as string 0x0C => Ok(TType::Struct), 0x0D => Ok(TType::Map), 0x0E => Ok(TType::Set), 0x0F => Ok(TType::List), 0x10 => Ok(TType::Utf8), 0x11 => Ok(TType::Utf16), unkn => Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::InvalidData, message: format!("cannot convert {} to TType", unkn), })), } } #[cfg(test)] mod tests { use crate::protocol::{ TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType, }; use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf}; use super::*; #[test] fn must_write_strict_message_call_begin() { let (_, mut o_prot) = test_objects(true); let ident = TMessageIdentifier::new("test", TMessageType::Call, 1); assert!(o_prot.write_message_begin(&ident).is_ok()); #[rustfmt::skip] let expected: [u8; 16] = [ 0x80, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x01, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_write_non_strict_message_call_begin() { let (_, mut o_prot) = test_objects(false); let ident = TMessageIdentifier::new("test", TMessageType::Call, 1); assert!(o_prot.write_message_begin(&ident).is_ok()); #[rustfmt::skip] let expected: [u8; 13] = [ 0x00, 0x00, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x01, 0x00, 0x00, 0x00, 0x01, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_write_strict_message_reply_begin() { let (_, mut o_prot) = test_objects(true); let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10); assert!(o_prot.write_message_begin(&ident).is_ok()); #[rustfmt::skip] let expected: [u8; 16] = [ 0x80, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x00, 0x00, 0x00, 0x0A, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_write_non_strict_message_reply_begin() { let (_, mut o_prot) = test_objects(false); let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10); assert!(o_prot.write_message_begin(&ident).is_ok()); #[rustfmt::skip] let expected: [u8; 13] = [ 0x00, 0x00, 0x00, 0x04, 0x74, 0x65, 0x73, 0x74, 0x02, 0x00, 0x00, 0x00, 0x0A, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_strict_message_begin() { let (mut i_prot, mut o_prot) = test_objects(true); let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1); assert!(o_prot.write_message_begin(&sent_ident).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let received_ident = assert_success!(i_prot.read_message_begin()); assert_eq!(&received_ident, &sent_ident); } #[test] fn must_round_trip_non_strict_message_begin() { let (mut i_prot, mut o_prot) = test_objects(false); let sent_ident = TMessageIdentifier::new("test", TMessageType::Call, 1); assert!(o_prot.write_message_begin(&sent_ident).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let received_ident = assert_success!(i_prot.read_message_begin()); assert_eq!(&received_ident, &sent_ident); } #[test] fn must_write_message_end() { assert_no_write(|o| o.write_message_end(), true); } #[test] fn must_write_struct_begin() { assert_no_write( |o| o.write_struct_begin(&TStructIdentifier::new("foo")), true, ); } #[test] fn must_write_struct_end() { assert_no_write(|o| o.write_struct_end(), true); } #[test] fn must_write_field_begin() { let (_, mut o_prot) = test_objects(true); assert!(o_prot .write_field_begin(&TFieldIdentifier::new("some_field", TType::String, 22)) .is_ok()); let expected: [u8; 3] = [0x0B, 0x00, 0x16]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_field_begin() { let (mut i_prot, mut o_prot) = test_objects(true); let sent_field_ident = TFieldIdentifier::new("foo", TType::I64, 20); assert!(o_prot.write_field_begin(&sent_field_ident).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let expected_ident = TFieldIdentifier { name: None, field_type: TType::I64, id: Some(20), }; // no name let received_ident = assert_success!(i_prot.read_field_begin()); assert_eq!(&received_ident, &expected_ident); } #[test] fn must_write_stop_field() { let (_, mut o_prot) = test_objects(true); assert!(o_prot.write_field_stop().is_ok()); let expected: [u8; 1] = [0x00]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_field_stop() { let (mut i_prot, mut o_prot) = test_objects(true); assert!(o_prot.write_field_stop().is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let expected_ident = TFieldIdentifier { name: None, field_type: TType::Stop, id: Some(0), }; // we get id 0 let received_ident = assert_success!(i_prot.read_field_begin()); assert_eq!(&received_ident, &expected_ident); } #[test] fn must_write_field_end() { assert_no_write(|o| o.write_field_end(), true); } #[test] fn must_write_list_begin() { let (_, mut o_prot) = test_objects(true); assert!(o_prot .write_list_begin(&TListIdentifier::new(TType::Bool, 5)) .is_ok()); let expected: [u8; 5] = [0x02, 0x00, 0x00, 0x00, 0x05]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_list_begin() { let (mut i_prot, mut o_prot) = test_objects(true); let ident = TListIdentifier::new(TType::List, 900); assert!(o_prot.write_list_begin(&ident).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let received_ident = assert_success!(i_prot.read_list_begin()); assert_eq!(&received_ident, &ident); } #[test] fn must_write_list_end() { assert_no_write(|o| o.write_list_end(), true); } #[test] fn must_write_set_begin() { let (_, mut o_prot) = test_objects(true); assert!(o_prot .write_set_begin(&TSetIdentifier::new(TType::I16, 7)) .is_ok()); let expected: [u8; 5] = [0x06, 0x00, 0x00, 0x00, 0x07]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_set_begin() { let (mut i_prot, mut o_prot) = test_objects(true); let ident = TSetIdentifier::new(TType::I64, 2000); assert!(o_prot.write_set_begin(&ident).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let received_ident_result = i_prot.read_set_begin(); assert!(received_ident_result.is_ok()); assert_eq!(&received_ident_result.unwrap(), &ident); } #[test] fn must_write_set_end() { assert_no_write(|o| o.write_set_end(), true); } #[test] fn must_write_map_begin() { let (_, mut o_prot) = test_objects(true); assert!(o_prot .write_map_begin(&TMapIdentifier::new(TType::I64, TType::Struct, 32)) .is_ok()); let expected: [u8; 6] = [0x0A, 0x0C, 0x00, 0x00, 0x00, 0x20]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_map_begin() { let (mut i_prot, mut o_prot) = test_objects(true); let ident = TMapIdentifier::new(TType::Map, TType::Set, 100); assert!(o_prot.write_map_begin(&ident).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let received_ident = assert_success!(i_prot.read_map_begin()); assert_eq!(&received_ident, &ident); } #[test] fn must_write_map_end() { assert_no_write(|o| o.write_map_end(), true); } #[test] fn must_write_bool_true() { let (_, mut o_prot) = test_objects(true); assert!(o_prot.write_bool(true).is_ok()); let expected: [u8; 1] = [0x01]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_write_bool_false() { let (_, mut o_prot) = test_objects(true); assert!(o_prot.write_bool(false).is_ok()); let expected: [u8; 1] = [0x00]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_bool_true() { let (mut i_prot, _) = test_objects(true); set_readable_bytes!(i_prot, &[0x01]); let read_bool = assert_success!(i_prot.read_bool()); assert_eq!(read_bool, true); } #[test] fn must_read_bool_false() { let (mut i_prot, _) = test_objects(true); set_readable_bytes!(i_prot, &[0x00]); let read_bool = assert_success!(i_prot.read_bool()); assert_eq!(read_bool, false); } #[test] fn must_allow_any_non_zero_value_to_be_interpreted_as_bool_true() { let (mut i_prot, _) = test_objects(true); set_readable_bytes!(i_prot, &[0xAC]); let read_bool = assert_success!(i_prot.read_bool()); assert_eq!(read_bool, true); } #[test] fn must_write_bytes() { let (_, mut o_prot) = test_objects(true); let bytes: [u8; 10] = [0x0A, 0xCC, 0xD1, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF]; assert!(o_prot.write_bytes(&bytes).is_ok()); let buf = o_prot.transport.write_bytes(); assert_eq!(&buf[0..4], [0x00, 0x00, 0x00, 0x0A]); // length assert_eq!(&buf[4..], bytes); // actual bytes } #[test] fn must_round_trip_bytes() { let (mut i_prot, mut o_prot) = test_objects(true); #[rustfmt::skip] let bytes: [u8; 25] = [ 0x20, 0xFD, 0x18, 0x84, 0x99, 0x12, 0xAB, 0xBB, 0x45, 0xDF, 0x34, 0xDC, 0x98, 0xA4, 0x6D, 0xF3, 0x99, 0xB4, 0xB7, 0xD4, 0x9C, 0xA5, 0xB3, 0xC9, 0x88, ]; assert!(o_prot.write_bytes(&bytes).is_ok()); copy_write_buffer_to_read_buffer!(o_prot); let received_bytes = assert_success!(i_prot.read_bytes()); assert_eq!(&received_bytes, &bytes); } fn test_objects( strict: bool, ) -> ( TBinaryInputProtocol>, TBinaryOutputProtocol>, ) { let mem = TBufferChannel::with_capacity(40, 40); let (r_mem, w_mem) = mem.split().unwrap(); let i_prot = TBinaryInputProtocol::new(r_mem, strict); let o_prot = TBinaryOutputProtocol::new(w_mem, strict); (i_prot, o_prot) } fn assert_no_write(mut write_fn: F, strict: bool) where F: FnMut(&mut TBinaryOutputProtocol>) -> crate::Result<()>, { let (_, mut o_prot) = test_objects(strict); assert!(write_fn(&mut o_prot).is_ok()); assert_eq!(o_prot.transport.write_bytes().len(), 0); } } thrift-0.19.0/lib/rs/src/protocol/stored.rs0000644000000000000000000001440514303740367020602 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::convert::Into; use super::{ TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier, TSetIdentifier, TStructIdentifier, }; use crate::ProtocolErrorKind; /// `TInputProtocol` required to use a `TMultiplexedProcessor`. /// /// A `TMultiplexedProcessor` reads incoming message identifiers to determine to /// which `TProcessor` requests should be forwarded. However, once read, those /// message identifier bytes are no longer on the wire. Since downstream /// processors expect to read message identifiers from the given input protocol /// we need some way of supplying a `TMessageIdentifier` with the service-name /// stripped. This implementation stores the received `TMessageIdentifier` /// (without the service name) and passes it to the wrapped `TInputProtocol` /// when `TInputProtocol::read_message_begin(...)` is called. It delegates all /// other calls directly to the wrapped `TInputProtocol`. /// /// This type **should not** be used by application code. /// /// # Examples /// /// Create and use a `TStoredInputProtocol`. /// /// ```no_run /// use thrift::protocol::{TInputProtocol, TMessageIdentifier, TMessageType, TOutputProtocol}; /// use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TStoredInputProtocol}; /// use thrift::server::TProcessor; /// use thrift::transport::{TIoChannel, TTcpChannel}; /// /// // sample processor /// struct ActualProcessor; /// impl TProcessor for ActualProcessor { /// fn process( /// &self, /// _: &mut dyn TInputProtocol, /// _: &mut dyn TOutputProtocol /// ) -> thrift::Result<()> { /// unimplemented!() /// } /// } /// let processor = ActualProcessor {}; /// /// // construct the shared transport /// let mut channel = TTcpChannel::new(); /// channel.open("localhost:9090").unwrap(); /// /// let (i_chan, o_chan) = channel.split().unwrap(); /// /// // construct the actual input and output protocols /// let mut i_prot = TBinaryInputProtocol::new(i_chan, true); /// let mut o_prot = TBinaryOutputProtocol::new(o_chan, true); /// /// // message identifier received from remote and modified to remove the service name /// let new_msg_ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1); /// /// // construct the proxy input protocol /// let mut proxy_i_prot = TStoredInputProtocol::new(&mut i_prot, new_msg_ident); /// let res = processor.process(&mut proxy_i_prot, &mut o_prot); /// ``` // FIXME: implement Debug pub struct TStoredInputProtocol<'a> { inner: &'a mut dyn TInputProtocol, message_ident: Option, } impl<'a> TStoredInputProtocol<'a> { /// Create a `TStoredInputProtocol` that delegates all calls other than /// `TInputProtocol::read_message_begin(...)` to a `wrapped` /// `TInputProtocol`. `message_ident` is the modified message identifier - /// with service name stripped - that will be passed to /// `wrapped.read_message_begin(...)`. pub fn new( wrapped: &mut dyn TInputProtocol, message_ident: TMessageIdentifier, ) -> TStoredInputProtocol<'_> { TStoredInputProtocol { inner: wrapped, message_ident: message_ident.into(), } } } impl<'a> TInputProtocol for TStoredInputProtocol<'a> { fn read_message_begin(&mut self) -> crate::Result { self.message_ident.take().ok_or_else(|| { crate::errors::new_protocol_error( ProtocolErrorKind::Unknown, "message identifier already read", ) }) } fn read_message_end(&mut self) -> crate::Result<()> { self.inner.read_message_end() } fn read_struct_begin(&mut self) -> crate::Result> { self.inner.read_struct_begin() } fn read_struct_end(&mut self) -> crate::Result<()> { self.inner.read_struct_end() } fn read_field_begin(&mut self) -> crate::Result { self.inner.read_field_begin() } fn read_field_end(&mut self) -> crate::Result<()> { self.inner.read_field_end() } fn read_bytes(&mut self) -> crate::Result> { self.inner.read_bytes() } fn read_bool(&mut self) -> crate::Result { self.inner.read_bool() } fn read_i8(&mut self) -> crate::Result { self.inner.read_i8() } fn read_i16(&mut self) -> crate::Result { self.inner.read_i16() } fn read_i32(&mut self) -> crate::Result { self.inner.read_i32() } fn read_i64(&mut self) -> crate::Result { self.inner.read_i64() } fn read_double(&mut self) -> crate::Result { self.inner.read_double() } fn read_string(&mut self) -> crate::Result { self.inner.read_string() } fn read_list_begin(&mut self) -> crate::Result { self.inner.read_list_begin() } fn read_list_end(&mut self) -> crate::Result<()> { self.inner.read_list_end() } fn read_set_begin(&mut self) -> crate::Result { self.inner.read_set_begin() } fn read_set_end(&mut self) -> crate::Result<()> { self.inner.read_set_end() } fn read_map_begin(&mut self) -> crate::Result { self.inner.read_map_begin() } fn read_map_end(&mut self) -> crate::Result<()> { self.inner.read_map_end() } // utility // fn read_byte(&mut self) -> crate::Result { self.inner.read_byte() } } thrift-0.19.0/lib/rs/src/protocol/compact.rs0000644000000000000000000027014014370300523020716 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use integer_encoding::{VarIntReader, VarIntWriter}; use std::convert::{From, TryFrom}; use std::io; use super::{ TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, }; use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIdentifier, TType}; use crate::transport::{TReadTransport, TWriteTransport}; const COMPACT_PROTOCOL_ID: u8 = 0x82; const COMPACT_VERSION: u8 = 0x01; const COMPACT_VERSION_MASK: u8 = 0x1F; /// Read messages encoded in the Thrift compact protocol. /// /// # Examples /// /// Create and use a `TCompactInputProtocol`. /// /// ```no_run /// use thrift::protocol::{TCompactInputProtocol, TInputProtocol}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("localhost:9090").unwrap(); /// /// let mut protocol = TCompactInputProtocol::new(channel); /// /// let recvd_bool = protocol.read_bool().unwrap(); /// let recvd_string = protocol.read_string().unwrap(); /// ``` #[derive(Debug)] pub struct TCompactInputProtocol where T: TReadTransport, { // Identifier of the last field deserialized for a struct. last_read_field_id: i16, // Stack of the last read field ids (a new entry is added each time a nested struct is read). read_field_id_stack: Vec, // Boolean value for a field. // Saved because boolean fields and their value are encoded in a single byte, // and reading the field only occurs after the field id is read. pending_read_bool_value: Option, // Underlying transport used for byte-level operations. transport: T, } impl TCompactInputProtocol where T: TReadTransport, { /// Create a `TCompactInputProtocol` that reads bytes from `transport`. pub fn new(transport: T) -> TCompactInputProtocol { TCompactInputProtocol { last_read_field_id: 0, read_field_id_stack: Vec::new(), pending_read_bool_value: None, transport, } } fn read_list_set_begin(&mut self) -> crate::Result<(TType, i32)> { let header = self.read_byte()?; let element_type = collection_u8_to_type(header & 0x0F)?; let possible_element_count = (header & 0xF0) >> 4; let element_count = if possible_element_count != 15 { // high bits set high if count and type encoded separately possible_element_count as i32 } else { self.transport.read_varint::()? as i32 }; Ok((element_type, element_count)) } } impl TInputProtocol for TCompactInputProtocol where T: TReadTransport, { fn read_message_begin(&mut self) -> crate::Result { let compact_id = self.read_byte()?; if compact_id != COMPACT_PROTOCOL_ID { Err(crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::BadVersion, message: format!("invalid compact protocol header {:?}", compact_id), })) } else { Ok(()) }?; let type_and_byte = self.read_byte()?; let received_version = type_and_byte & COMPACT_VERSION_MASK; if received_version != COMPACT_VERSION { Err(crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::BadVersion, message: format!( "cannot process compact protocol version {:?}", received_version ), })) } else { Ok(()) }?; // NOTE: unsigned right shift will pad with 0s let message_type: TMessageType = TMessageType::try_from(type_and_byte >> 5)?; // writing side wrote signed sequence number as u32 to avoid zigzag encoding let sequence_number = self.transport.read_varint::()? as i32; let service_call_name = self.read_string()?; self.last_read_field_id = 0; Ok(TMessageIdentifier::new( service_call_name, message_type, sequence_number, )) } fn read_message_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_struct_begin(&mut self) -> crate::Result> { self.read_field_id_stack.push(self.last_read_field_id); self.last_read_field_id = 0; Ok(None) } fn read_struct_end(&mut self) -> crate::Result<()> { self.last_read_field_id = self .read_field_id_stack .pop() .expect("should have previous field ids"); Ok(()) } fn read_field_begin(&mut self) -> crate::Result { // we can read at least one byte, which is: // - the type // - the field delta and the type let field_type = self.read_byte()?; let field_delta = (field_type & 0xF0) >> 4; let field_type = match field_type & 0x0F { 0x01 => { self.pending_read_bool_value = Some(true); Ok(TType::Bool) } 0x02 => { self.pending_read_bool_value = Some(false); Ok(TType::Bool) } ttu8 => u8_to_type(ttu8), }?; match field_type { TType::Stop => Ok( TFieldIdentifier::new::, String, Option>( None, TType::Stop, None, ), ), _ => { if field_delta != 0 { self.last_read_field_id += field_delta as i16; } else { self.last_read_field_id = self.read_i16()?; }; Ok(TFieldIdentifier { name: None, field_type, id: Some(self.last_read_field_id), }) } } } fn read_field_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_bool(&mut self) -> crate::Result { match self.pending_read_bool_value.take() { Some(b) => Ok(b), None => { let b = self.read_byte()?; match b { 0x01 => Ok(true), 0x02 => Ok(false), unkn => Err(crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::InvalidData, message: format!("cannot convert {} into bool", unkn), })), } } } } fn read_bytes(&mut self) -> crate::Result> { let len = self.transport.read_varint::()?; let mut buf = vec![0u8; len as usize]; self.transport .read_exact(&mut buf) .map_err(From::from) .map(|_| buf) } fn read_i8(&mut self) -> crate::Result { self.read_byte().map(|i| i as i8) } fn read_i16(&mut self) -> crate::Result { self.transport.read_varint::().map_err(From::from) } fn read_i32(&mut self) -> crate::Result { self.transport.read_varint::().map_err(From::from) } fn read_i64(&mut self) -> crate::Result { self.transport.read_varint::().map_err(From::from) } fn read_double(&mut self) -> crate::Result { self.transport .read_f64::() .map_err(From::from) } fn read_string(&mut self) -> crate::Result { let bytes = self.read_bytes()?; String::from_utf8(bytes).map_err(From::from) } fn read_list_begin(&mut self) -> crate::Result { let (element_type, element_count) = self.read_list_set_begin()?; Ok(TListIdentifier::new(element_type, element_count)) } fn read_list_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_set_begin(&mut self) -> crate::Result { let (element_type, element_count) = self.read_list_set_begin()?; Ok(TSetIdentifier::new(element_type, element_count)) } fn read_set_end(&mut self) -> crate::Result<()> { Ok(()) } fn read_map_begin(&mut self) -> crate::Result { let element_count = self.transport.read_varint::()? as i32; if element_count == 0 { Ok(TMapIdentifier::new(None, None, 0)) } else { let type_header = self.read_byte()?; let key_type = collection_u8_to_type((type_header & 0xF0) >> 4)?; let val_type = collection_u8_to_type(type_header & 0x0F)?; Ok(TMapIdentifier::new(key_type, val_type, element_count)) } } fn read_map_end(&mut self) -> crate::Result<()> { Ok(()) } // utility // fn read_byte(&mut self) -> crate::Result { let mut buf = [0u8; 1]; self.transport .read_exact(&mut buf) .map_err(From::from) .map(|_| buf[0]) } } impl io::Seek for TCompactInputProtocol where T: io::Seek + TReadTransport, { fn seek(&mut self, pos: io::SeekFrom) -> io::Result { self.transport.seek(pos) } } /// Factory for creating instances of `TCompactInputProtocol`. #[derive(Default)] pub struct TCompactInputProtocolFactory; impl TCompactInputProtocolFactory { /// Create a `TCompactInputProtocolFactory`. pub fn new() -> TCompactInputProtocolFactory { TCompactInputProtocolFactory {} } } impl TInputProtocolFactory for TCompactInputProtocolFactory { fn create(&self, transport: Box) -> Box { Box::new(TCompactInputProtocol::new(transport)) } } /// Write messages using the Thrift compact protocol. /// /// # Examples /// /// Create and use a `TCompactOutputProtocol`. /// /// ```no_run /// use thrift::protocol::{TCompactOutputProtocol, TOutputProtocol}; /// use thrift::transport::TTcpChannel; /// /// let mut channel = TTcpChannel::new(); /// channel.open("localhost:9090").unwrap(); /// /// let mut protocol = TCompactOutputProtocol::new(channel); /// /// protocol.write_bool(true).unwrap(); /// protocol.write_string("test_string").unwrap(); /// ``` #[derive(Debug)] pub struct TCompactOutputProtocol where T: TWriteTransport, { // Identifier of the last field serialized for a struct. last_write_field_id: i16, // Stack of the last written field ids (new entry added each time a nested struct is written). write_field_id_stack: Vec, // Field identifier of the boolean field to be written. // Saved because boolean fields and their value are encoded in a single byte pending_write_bool_field_identifier: Option, // Underlying transport used for byte-level operations. transport: T, } impl TCompactOutputProtocol where T: TWriteTransport, { /// Create a `TCompactOutputProtocol` that writes bytes to `transport`. pub fn new(transport: T) -> TCompactOutputProtocol { TCompactOutputProtocol { last_write_field_id: 0, write_field_id_stack: Vec::new(), pending_write_bool_field_identifier: None, transport, } } // FIXME: field_type as unconstrained u8 is bad fn write_field_header(&mut self, field_type: u8, field_id: i16) -> crate::Result<()> { let field_delta = field_id - self.last_write_field_id; if field_delta > 0 && field_delta < 15 { self.write_byte(((field_delta as u8) << 4) | field_type)?; } else { self.write_byte(field_type)?; self.write_i16(field_id)?; } self.last_write_field_id = field_id; Ok(()) } fn write_list_set_begin( &mut self, element_type: TType, element_count: i32, ) -> crate::Result<()> { let elem_identifier = collection_type_to_u8(element_type); if element_count <= 14 { let header = (element_count as u8) << 4 | elem_identifier; self.write_byte(header) } else { let header = 0xF0 | elem_identifier; self.write_byte(header)?; // element count is strictly positive as per the spec, so // cast i32 as u32 so that varint writing won't use zigzag encoding self.transport .write_varint(element_count as u32) .map_err(From::from) .map(|_| ()) } } fn assert_no_pending_bool_write(&self) { if let Some(ref f) = self.pending_write_bool_field_identifier { panic!("pending bool field {:?} not written", f) } } } impl TOutputProtocol for TCompactOutputProtocol where T: TWriteTransport, { fn write_message_begin(&mut self, identifier: &TMessageIdentifier) -> crate::Result<()> { self.write_byte(COMPACT_PROTOCOL_ID)?; self.write_byte((u8::from(identifier.message_type) << 5) | COMPACT_VERSION)?; // cast i32 as u32 so that varint writing won't use zigzag encoding self.transport .write_varint(identifier.sequence_number as u32)?; self.write_string(&identifier.name)?; Ok(()) } fn write_message_end(&mut self) -> crate::Result<()> { self.assert_no_pending_bool_write(); Ok(()) } fn write_struct_begin(&mut self, _: &TStructIdentifier) -> crate::Result<()> { self.write_field_id_stack.push(self.last_write_field_id); self.last_write_field_id = 0; Ok(()) } fn write_struct_end(&mut self) -> crate::Result<()> { self.assert_no_pending_bool_write(); self.last_write_field_id = self .write_field_id_stack .pop() .expect("should have previous field ids"); Ok(()) } fn write_field_begin(&mut self, identifier: &TFieldIdentifier) -> crate::Result<()> { match identifier.field_type { TType::Bool => { if self.pending_write_bool_field_identifier.is_some() { panic!( "should not have a pending bool while writing another bool with id: \ {:?}", identifier ) } self.pending_write_bool_field_identifier = Some(identifier.clone()); Ok(()) } _ => { let field_type = type_to_u8(identifier.field_type); let field_id = identifier.id.expect("non-stop field should have field id"); self.write_field_header(field_type, field_id) } } } fn write_field_end(&mut self) -> crate::Result<()> { self.assert_no_pending_bool_write(); Ok(()) } fn write_field_stop(&mut self) -> crate::Result<()> { self.assert_no_pending_bool_write(); self.write_byte(type_to_u8(TType::Stop)) } fn write_bool(&mut self, b: bool) -> crate::Result<()> { match self.pending_write_bool_field_identifier.take() { Some(pending) => { let field_id = pending.id.expect("bool field should have a field id"); let field_type_as_u8 = if b { 0x01 } else { 0x02 }; self.write_field_header(field_type_as_u8, field_id) } None => { if b { self.write_byte(0x01) } else { self.write_byte(0x02) } } } } fn write_bytes(&mut self, b: &[u8]) -> crate::Result<()> { // length is strictly positive as per the spec, so // cast i32 as u32 so that varint writing won't use zigzag encoding self.transport.write_varint(b.len() as u32)?; self.transport.write_all(b).map_err(From::from) } fn write_i8(&mut self, i: i8) -> crate::Result<()> { self.write_byte(i as u8) } fn write_i16(&mut self, i: i16) -> crate::Result<()> { self.transport .write_varint(i) .map_err(From::from) .map(|_| ()) } fn write_i32(&mut self, i: i32) -> crate::Result<()> { self.transport .write_varint(i) .map_err(From::from) .map(|_| ()) } fn write_i64(&mut self, i: i64) -> crate::Result<()> { self.transport .write_varint(i) .map_err(From::from) .map(|_| ()) } fn write_double(&mut self, d: f64) -> crate::Result<()> { self.transport .write_f64::(d) .map_err(From::from) } fn write_string(&mut self, s: &str) -> crate::Result<()> { self.write_bytes(s.as_bytes()) } fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> { self.write_list_set_begin(identifier.element_type, identifier.size) } fn write_list_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_set_begin(&mut self, identifier: &TSetIdentifier) -> crate::Result<()> { self.write_list_set_begin(identifier.element_type, identifier.size) } fn write_set_end(&mut self) -> crate::Result<()> { Ok(()) } fn write_map_begin(&mut self, identifier: &TMapIdentifier) -> crate::Result<()> { if identifier.size == 0 { self.write_byte(0) } else { // element count is strictly positive as per the spec, so // cast i32 as u32 so that varint writing won't use zigzag encoding self.transport.write_varint(identifier.size as u32)?; let key_type = identifier .key_type .expect("map identifier to write should contain key type"); let key_type_byte = collection_type_to_u8(key_type) << 4; let val_type = identifier .value_type .expect("map identifier to write should contain value type"); let val_type_byte = collection_type_to_u8(val_type); let map_type_header = key_type_byte | val_type_byte; self.write_byte(map_type_header) } } fn write_map_end(&mut self) -> crate::Result<()> { Ok(()) } fn flush(&mut self) -> crate::Result<()> { self.transport.flush().map_err(From::from) } // utility // fn write_byte(&mut self, b: u8) -> crate::Result<()> { self.transport.write(&[b]).map_err(From::from).map(|_| ()) } } /// Factory for creating instances of `TCompactOutputProtocol`. #[derive(Default)] pub struct TCompactOutputProtocolFactory; impl TCompactOutputProtocolFactory { /// Create a `TCompactOutputProtocolFactory`. pub fn new() -> TCompactOutputProtocolFactory { TCompactOutputProtocolFactory {} } } impl TOutputProtocolFactory for TCompactOutputProtocolFactory { fn create( &self, transport: Box, ) -> Box { Box::new(TCompactOutputProtocol::new(transport)) } } fn collection_type_to_u8(field_type: TType) -> u8 { match field_type { TType::Bool => 0x01, f => type_to_u8(f), } } fn type_to_u8(field_type: TType) -> u8 { match field_type { TType::Stop => 0x00, TType::I08 => 0x03, // equivalent to TType::Byte TType::I16 => 0x04, TType::I32 => 0x05, TType::I64 => 0x06, TType::Double => 0x07, TType::String => 0x08, TType::List => 0x09, TType::Set => 0x0A, TType::Map => 0x0B, TType::Struct => 0x0C, _ => panic!("should not have attempted to convert {} to u8", field_type), } } fn collection_u8_to_type(b: u8) -> crate::Result { match b { 0x01 => Ok(TType::Bool), o => u8_to_type(o), } } fn u8_to_type(b: u8) -> crate::Result { match b { 0x00 => Ok(TType::Stop), 0x03 => Ok(TType::I08), // equivalent to TType::Byte 0x04 => Ok(TType::I16), 0x05 => Ok(TType::I32), 0x06 => Ok(TType::I64), 0x07 => Ok(TType::Double), 0x08 => Ok(TType::String), 0x09 => Ok(TType::List), 0x0A => Ok(TType::Set), 0x0B => Ok(TType::Map), 0x0C => Ok(TType::Struct), unkn => Err(crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::InvalidData, message: format!("cannot convert {} into TType", unkn), })), } } #[cfg(test)] mod tests { use std::i32; use crate::protocol::{ TFieldIdentifier, TInputProtocol, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType, }; use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf}; use super::*; #[test] fn must_write_message_begin_largest_maximum_positive_sequence_number() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "bar", TMessageType::Reply, i32::MAX ))); #[rustfmt::skip] let expected: [u8; 11] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0xFF, 0xFF, 0xFF, 0xFF, 0x07, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_largest_maximum_positive_sequence_number() { let (mut i_prot, _) = test_objects(); #[rustfmt::skip] let source_bytes: [u8; 11] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0xFF, 0xFF, 0xFF, 0xFF, 0x07, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MAX); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_positive_sequence_number_0() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "foo", TMessageType::Call, 431 ))); #[rustfmt::skip] let expected: [u8; 8] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0xAF, 0x03, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_positive_sequence_number_0() { let (mut i_prot, _) = test_objects(); #[rustfmt::skip] let source_bytes: [u8; 8] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0xAF, 0x03, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("foo", TMessageType::Call, 431); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_positive_sequence_number_1() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "bar", TMessageType::Reply, 991_828 ))); #[rustfmt::skip] let expected: [u8; 9] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0xD4, 0xC4, 0x3C, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_positive_sequence_number_1() { let (mut i_prot, _) = test_objects(); #[rustfmt::skip] let source_bytes: [u8; 9] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0xD4, 0xC4, 0x3C, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 991_828); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_zero_sequence_number() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "bar", TMessageType::Reply, 0 ))); #[rustfmt::skip] let expected: [u8; 7] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0x00, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_zero_sequence_number() { let (mut i_prot, _) = test_objects(); #[rustfmt::skip] let source_bytes: [u8; 7] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0x00, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("bar", TMessageType::Reply, 0); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_largest_minimum_negative_sequence_number() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "bar", TMessageType::Reply, i32::MIN ))); // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000 #[rustfmt::skip] let expected: [u8; 11] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0x80, 0x80, 0x80, 0x80, 0x08, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_largest_minimum_negative_sequence_number() { let (mut i_prot, _) = test_objects(); // two's complement notation of i32::MIN = 1000_0000_0000_0000_0000_0000_0000_0000 #[rustfmt::skip] let source_bytes: [u8; 11] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ 0x80, 0x80, 0x80, 0x80, 0x08, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x62, 0x61, 0x72 /* "bar" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("bar", TMessageType::Reply, i32::MIN); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_negative_sequence_number_0() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "foo", TMessageType::Call, -431 ))); // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001 #[rustfmt::skip] let expected: [u8; 11] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0xD1, 0xFC, 0xFF, 0xFF, 0x0F, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_negative_sequence_number_0() { let (mut i_prot, _) = test_objects(); // signed two's complement of -431 = 1111_1111_1111_1111_1111_1110_0101_0001 #[rustfmt::skip] let source_bytes: [u8; 11] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0xD1, 0xFC, 0xFF, 0xFF, 0x0F, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("foo", TMessageType::Call, -431); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_negative_sequence_number_1() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "foo", TMessageType::Call, -73_184_125 ))); // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011 #[rustfmt::skip] let expected: [u8; 11] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0x83, 0x99, 0x8D, 0xDD, 0x0F, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_negative_sequence_number_1() { let (mut i_prot, _) = test_objects(); // signed two's complement of -73184125 = 1111_1011_1010_0011_0100_1100_1000_0011 #[rustfmt::skip] let source_bytes: [u8; 11] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0x83, 0x99, 0x8D, 0xDD, 0x0F, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("foo", TMessageType::Call, -73_184_125); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_write_message_begin_negative_sequence_number_2() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "foo", TMessageType::Call, -1_073_741_823 ))); // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001 #[rustfmt::skip] let expected: [u8; 11] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0x81, 0x80, 0x80, 0x80, 0x0C, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F /* "foo" */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_message_begin_negative_sequence_number_2() { let (mut i_prot, _) = test_objects(); // signed two's complement of -1073741823 = 1100_0000_0000_0000_0000_0000_0000_0001 #[rustfmt::skip] let source_bytes: [u8; 11] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ 0x81, 0x80, 0x80, 0x80, 0x0C, /* non-zig-zag varint sequence number */ 0x03, /* message-name length */ 0x66, 0x6F, 0x6F, /* "foo" */ ]; i_prot.transport.set_readable_bytes(&source_bytes); let expected = TMessageIdentifier::new("foo", TMessageType::Call, -1_073_741_823); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&expected, &res); } #[test] fn must_round_trip_upto_i64_maxvalue() { // See https://issues.apache.org/jira/browse/THRIFT-5131 for i in 0..64 { let (mut i_prot, mut o_prot) = test_objects(); let val: i64 = ((1u64 << i) - 1) as i64; o_prot .write_field_begin(&TFieldIdentifier::new("val", TType::I64, 1)) .unwrap(); o_prot.write_i64(val).unwrap(); o_prot.write_field_end().unwrap(); o_prot.flush().unwrap(); copy_write_buffer_to_read_buffer!(o_prot); i_prot.read_field_begin().unwrap(); assert_eq!(val, i_prot.read_i64().unwrap()); } } #[test] fn must_round_trip_message_begin() { let (mut i_prot, mut o_prot) = test_objects(); let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948); assert_success!(o_prot.write_message_begin(&ident)); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_message_begin()); assert_eq!(&res, &ident); } #[test] fn must_write_message_end() { assert_no_write(|o| o.write_message_end()); } // NOTE: structs and fields are tested together // #[test] fn must_write_struct_with_delta_fields() { let (_, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with tiny field ids // since they're small the field ids will be encoded as deltas // since this is the first field (and it's zero) it gets the full varint write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 0))); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I16, 4))); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::List, 9))); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 5] = [ 0x03, /* field type */ 0x00, /* first field id */ 0x44, /* field delta (4) | field type */ 0x59, /* field delta (5) | field type */ 0x00 /* field stop */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_struct_with_delta_fields() { let (mut i_prot, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with tiny field ids // since they're small the field ids will be encoded as deltas // since this is the first field (and it's zero) it gets the full varint write let field_ident_1 = TFieldIdentifier::new("foo", TType::I08, 0); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta let field_ident_2 = TFieldIdentifier::new("foo", TType::I16, 4); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta let field_ident_3 = TFieldIdentifier::new("foo", TType::List, 9); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read the struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_struct_with_non_zero_initial_field_and_delta_fields() { let (_, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with tiny field ids // since they're small the field ids will be encoded as deltas // gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 1))); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2))); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 6))); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 4] = [ 0x15, /* field delta (1) | field type */ 0x1A, /* field delta (1) | field type */ 0x48, /* field delta (4) | field type */ 0x00 /* field stop */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_struct_with_non_zero_initial_field_and_delta_fields() { let (mut i_prot, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with tiny field ids // since they're small the field ids will be encoded as deltas // gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta let field_ident_2 = TFieldIdentifier::new("foo", TType::Set, 2); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it can be encoded as a delta let field_ident_3 = TFieldIdentifier::new("foo", TType::String, 6); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read the struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_struct_with_long_fields() { let (_, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with field ids that cannot be encoded as deltas // since this is the first field (and it's zero) it gets the full varint write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 0))); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 16))); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 99))); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 8] = [ 0x05, /* field type */ 0x00, /* first field id */ 0x06, /* field type */ 0x20, /* zig-zag varint field id */ 0x0A, /* field type */ 0xC6, 0x01, /* zig-zag varint field id */ 0x00 /* field stop */, ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_struct_with_long_fields() { let (mut i_prot, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with field ids that cannot be encoded as deltas // since this is the first field (and it's zero) it gets the full varint write let field_ident_1 = TFieldIdentifier::new("foo", TType::I32, 0); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint let field_ident_2 = TFieldIdentifier::new("foo", TType::I64, 16); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 99); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read the struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_struct_with_mix_of_long_and_delta_fields() { let (_, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with field ids that cannot be encoded as deltas // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1))); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9))); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 1000))); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2001))); assert_success!(o_prot.write_field_end()); // since this is only 3 up from the previous it is recorded as a delta assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Set, 2004))); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 10] = [ 0x16, /* field delta (1) | field type */ 0x85, /* field delta (8) | field type */ 0x0A, /* field type */ 0xD0, 0x0F, /* zig-zag varint field id */ 0x0A, /* field type */ 0xA2, 0x1F, /* zig-zag varint field id */ 0x3A, /* field delta (3) | field type */ 0x00 /* field stop */, ]; assert_eq_written_bytes!(o_prot, expected); } #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_struct_with_mix_of_long_and_delta_fields() { let (mut i_prot, mut o_prot) = test_objects(); // no bytes should be written however let struct_ident = TStructIdentifier::new("foo"); assert_success!(o_prot.write_struct_begin(&struct_ident)); // write three fields with field ids that cannot be encoded as deltas // since the delta is > 0 and < 15 it gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it gets a delta write let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint let field_ident_3 = TFieldIdentifier::new("foo", TType::Set, 1000); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // since this delta is > 15 it is encoded as a zig-zag varint let field_ident_4 = TFieldIdentifier::new("foo", TType::Set, 2001); assert_success!(o_prot.write_field_begin(&field_ident_4)); assert_success!(o_prot.write_field_end()); // since this is only 3 up from the previous it is recorded as a delta let field_ident_5 = TFieldIdentifier::new("foo", TType::Set, 2004); assert_success!(o_prot.write_field_begin(&field_ident_5)); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read the struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, ..field_ident_4 } ); assert_success!(i_prot.read_field_end()); let read_ident_5 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_5, TFieldIdentifier { name: None, ..field_ident_5 } ); assert_success!(i_prot.read_field_end()); let read_ident_6 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_6, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_nested_structs_0() { // last field of the containing struct is a delta // first field of the the contained struct is a delta let (_, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1))); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9))); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 7))); assert_success!(o_prot.write_field_end()); // contained struct // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24))); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 7] = [ 0x16, /* field delta (1) | field type */ 0x85, /* field delta (8) | field type */ 0x73, /* field delta (7) | field type */ 0x07, /* field type */ 0x30, /* zig-zag varint field id */ 0x00, /* field stop - contained */ 0x00 /* field stop - containing */, ]; assert_eq_written_bytes!(o_prot, expected); } #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_0() { // last field of the containing struct is a delta // first field of the the contained struct is a delta let (mut i_prot, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 0 and < 15 it gets a delta write let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_3 = TFieldIdentifier::new("foo", TType::I08, 7); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // contained struct // since this delta > 15 it gets a full write let field_ident_4 = TFieldIdentifier::new("foo", TType::Double, 24); assert_success!(o_prot.write_field_begin(&field_ident_4)); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read containing struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); // read contained struct back assert_success!(i_prot.read_struct_begin()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, ..field_ident_4 } ); assert_success!(i_prot.read_field_end()); // end contained struct let read_ident_6 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_6, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); // end containing struct let read_ident_7 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_7, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_nested_structs_1() { // last field of the containing struct is a delta // first field of the the contained struct is a full write let (_, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1))); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I32, 9))); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 24))); assert_success!(o_prot.write_field_end()); // contained struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27))); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 7] = [ 0x16, /* field delta (1) | field type */ 0x85, /* field delta (8) | field type */ 0x07, /* field type */ 0x30, /* zig-zag varint field id */ 0x33, /* field delta (3) | field type */ 0x00, /* field stop - contained */ 0x00 /* field stop - containing */, ]; assert_eq_written_bytes!(o_prot, expected); } #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_1() { // last field of the containing struct is a delta // first field of the the contained struct is a full write let (mut i_prot, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 0 and < 15 it gets a delta write let field_ident_2 = TFieldIdentifier::new("foo", TType::I32, 9); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since this delta > 15 it gets a full write let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 24); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // contained struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27); assert_success!(o_prot.write_field_begin(&field_ident_4)); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read containing struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); // read contained struct back assert_success!(i_prot.read_struct_begin()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, ..field_ident_4 } ); assert_success!(i_prot.read_field_end()); // end contained struct let read_ident_6 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_6, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); // end containing struct let read_ident_7 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_7, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_nested_structs_2() { // last field of the containing struct is a full write // first field of the the contained struct is a delta write let (_, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1))); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21))); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since this delta > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 7))); assert_success!(o_prot.write_field_end()); // contained struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 10))); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 7] = [ 0x16, /* field delta (1) | field type */ 0x08, /* field type */ 0x2A, /* zig-zag varint field id */ 0x77, /* field delta(7) | field type */ 0x33, /* field delta (3) | field type */ 0x00, /* field stop - contained */ 0x00 /* field stop - containing */, ]; assert_eq_written_bytes!(o_prot, expected); } #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_2() { let (mut i_prot, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 15 it gets a full write let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since this delta > 0 and < 15 it gets a delta write let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 7); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // contained struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 10); assert_success!(o_prot.write_field_begin(&field_ident_4)); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read containing struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); // read contained struct back assert_success!(i_prot.read_struct_begin()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, ..field_ident_4 } ); assert_success!(i_prot.read_field_end()); // end contained struct let read_ident_6 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_6, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); // end containing struct let read_ident_7 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_7, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_nested_structs_3() { // last field of the containing struct is a full write // first field of the the contained struct is a full write let (_, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I64, 1))); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::String, 21))); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Double, 21))); assert_success!(o_prot.write_field_end()); // contained struct // since the delta is > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::I08, 27))); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 8] = [ 0x16, /* field delta (1) | field type */ 0x08, /* field type */ 0x2A, /* zig-zag varint field id */ 0x07, /* field type */ 0x2A, /* zig-zag varint field id */ 0x63, /* field delta (6) | field type */ 0x00, /* field stop - contained */ 0x00 /* field stop - containing */, ]; assert_eq_written_bytes!(o_prot, expected); } #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_3() { // last field of the containing struct is a full write // first field of the the contained struct is a full write let (mut i_prot, mut o_prot) = test_objects(); // start containing struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // containing struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::I64, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_field_end()); // containing struct // since this delta > 15 it gets a full write let field_ident_2 = TFieldIdentifier::new("foo", TType::String, 21); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_field_end()); // start contained struct assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // contained struct // since this delta > 15 it gets a full write let field_ident_3 = TFieldIdentifier::new("foo", TType::Double, 21); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_field_end()); // contained struct // since the delta is > 0 and < 15 it gets a delta write let field_ident_4 = TFieldIdentifier::new("foo", TType::I08, 27); assert_success!(o_prot.write_field_begin(&field_ident_4)); assert_success!(o_prot.write_field_end()); // end contained struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); // end containing struct assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read containing struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); assert_success!(i_prot.read_field_end()); // read contained struct back assert_success!(i_prot.read_struct_begin()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, ..field_ident_4 } ); assert_success!(i_prot.read_field_end()); // end contained struct let read_ident_6 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_6, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); // end containing struct let read_ident_7 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_7, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] fn must_write_bool_field() { let (_, mut o_prot) = test_objects(); // no bytes should be written however assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); // write three fields with field ids that cannot be encoded as deltas // since the delta is > 0 and < 16 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1))); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it gets a delta write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 9))); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_field_end()); // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 26))); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_field_end()); // since this delta > 15 it gets a full write assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 45))); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); #[rustfmt::skip] let expected: [u8; 7] = [ 0x11, /* field delta (1) | true */ 0x82, /* field delta (8) | false */ 0x01, /* true */ 0x34, /* field id */ 0x02, /* false */ 0x5A, /* field id */ 0x00 /* stop field */, ]; assert_eq_written_bytes!(o_prot, expected); } #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_bool_field() { let (mut i_prot, mut o_prot) = test_objects(); // no bytes should be written however let struct_ident = TStructIdentifier::new("foo"); assert_success!(o_prot.write_struct_begin(&struct_ident)); // write two fields // since the delta is > 0 and < 16 it gets a delta write let field_ident_1 = TFieldIdentifier::new("foo", TType::Bool, 1); assert_success!(o_prot.write_field_begin(&field_ident_1)); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_field_end()); // since this delta > 0 and < 15 it gets a delta write let field_ident_2 = TFieldIdentifier::new("foo", TType::Bool, 9); assert_success!(o_prot.write_field_begin(&field_ident_2)); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_field_end()); // since this delta > 15 it gets a full write let field_ident_3 = TFieldIdentifier::new("foo", TType::Bool, 26); assert_success!(o_prot.write_field_begin(&field_ident_3)); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_field_end()); // since this delta > 15 it gets a full write let field_ident_4 = TFieldIdentifier::new("foo", TType::Bool, 45); assert_success!(o_prot.write_field_begin(&field_ident_4)); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_field_end()); // now, finish the struct off assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); copy_write_buffer_to_read_buffer!(o_prot); // read the struct back assert_success!(i_prot.read_struct_begin()); let read_ident_1 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_1, TFieldIdentifier { name: None, ..field_ident_1 } ); let read_value_1 = assert_success!(i_prot.read_bool()); assert_eq!(read_value_1, true); assert_success!(i_prot.read_field_end()); let read_ident_2 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_2, TFieldIdentifier { name: None, ..field_ident_2 } ); let read_value_2 = assert_success!(i_prot.read_bool()); assert_eq!(read_value_2, false); assert_success!(i_prot.read_field_end()); let read_ident_3 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_3, TFieldIdentifier { name: None, ..field_ident_3 } ); let read_value_3 = assert_success!(i_prot.read_bool()); assert_eq!(read_value_3, true); assert_success!(i_prot.read_field_end()); let read_ident_4 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_4, TFieldIdentifier { name: None, ..field_ident_4 } ); let read_value_4 = assert_success!(i_prot.read_bool()); assert_eq!(read_value_4, false); assert_success!(i_prot.read_field_end()); let read_ident_5 = assert_success!(i_prot.read_field_begin()); assert_eq!( read_ident_5, TFieldIdentifier { name: None, field_type: TType::Stop, id: None, } ); assert_success!(i_prot.read_struct_end()); } #[test] #[should_panic] fn must_fail_if_write_field_end_without_writing_bool_value() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1))); o_prot.write_field_end().unwrap(); } #[test] #[should_panic] fn must_fail_if_write_stop_field_without_writing_bool_value() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1))); o_prot.write_field_stop().unwrap(); } #[test] #[should_panic] fn must_fail_if_write_struct_end_without_writing_bool_value() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_struct_begin(&TStructIdentifier::new("foo"))); assert_success!(o_prot.write_field_begin(&TFieldIdentifier::new("foo", TType::Bool, 1))); o_prot.write_struct_end().unwrap(); } #[test] #[should_panic] fn must_fail_if_write_struct_end_without_any_fields() { let (_, mut o_prot) = test_objects(); o_prot.write_struct_end().unwrap(); } #[test] fn must_write_field_end() { assert_no_write(|o| o.write_field_end()); } #[test] fn must_write_small_sized_list_begin() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_list_begin(&TListIdentifier::new(TType::I64, 4))); let expected: [u8; 1] = [0x46 /* size | elem_type */]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_small_sized_list_begin() { let (mut i_prot, mut o_prot) = test_objects(); let ident = TListIdentifier::new(TType::I08, 10); assert_success!(o_prot.write_list_begin(&ident)); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_list_begin()); assert_eq!(&res, &ident); } #[test] fn must_write_large_sized_list_begin() { let (_, mut o_prot) = test_objects(); let res = o_prot.write_list_begin(&TListIdentifier::new(TType::List, 9999)); assert!(res.is_ok()); let expected: [u8; 3] = [ 0xF9, /* 0xF0 | elem_type */ 0x8F, 0x4E, /* size as varint */ ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_large_sized_list_begin() { let (mut i_prot, mut o_prot) = test_objects(); let ident = TListIdentifier::new(TType::Set, 47381); assert_success!(o_prot.write_list_begin(&ident)); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_list_begin()); assert_eq!(&res, &ident); } #[test] fn must_write_list_end() { assert_no_write(|o| o.write_list_end()); } #[test] fn must_write_small_sized_set_begin() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Struct, 2))); let expected: [u8; 1] = [0x2C /* size | elem_type */]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_small_sized_set_begin() { let (mut i_prot, mut o_prot) = test_objects(); let ident = TSetIdentifier::new(TType::I16, 7); assert_success!(o_prot.write_set_begin(&ident)); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_set_begin()); assert_eq!(&res, &ident); } #[test] fn must_write_large_sized_set_begin() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_set_begin(&TSetIdentifier::new(TType::Double, 23891))); let expected: [u8; 4] = [ 0xF7, /* 0xF0 | elem_type */ 0xD3, 0xBA, 0x01, /* size as varint */ ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_large_sized_set_begin() { let (mut i_prot, mut o_prot) = test_objects(); let ident = TSetIdentifier::new(TType::Map, 3_928_429); assert_success!(o_prot.write_set_begin(&ident)); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_set_begin()); assert_eq!(&res, &ident); } #[test] fn must_write_set_end() { assert_no_write(|o| o.write_set_end()); } #[test] fn must_write_zero_sized_map_begin() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::String, TType::I32, 0))); let expected: [u8; 1] = [0x00]; // since size is zero we don't write anything assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_read_zero_sized_map_begin() { let (mut i_prot, mut o_prot) = test_objects(); assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Double, TType::I32, 0))); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_map_begin()); assert_eq!( &res, &TMapIdentifier { key_type: None, value_type: None, size: 0, } ); } #[test] fn must_write_map_begin() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_map_begin(&TMapIdentifier::new( TType::Double, TType::String, 238 ))); let expected: [u8; 3] = [ 0xEE, 0x01, /* size as varint */ 0x78, /* key type | val type */ ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_map_begin() { let (mut i_prot, mut o_prot) = test_objects(); let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349); assert_success!(o_prot.write_map_begin(&ident)); copy_write_buffer_to_read_buffer!(o_prot); let res = assert_success!(i_prot.read_map_begin()); assert_eq!(&res, &ident); } #[test] fn must_write_map_end() { assert_no_write(|o| o.write_map_end()); } #[test] fn must_write_map_with_bool_key_and_value() { let (_, mut o_prot) = test_objects(); assert_success!(o_prot.write_map_begin(&TMapIdentifier::new(TType::Bool, TType::Bool, 1))); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_map_end()); let expected: [u8; 4] = [ 0x01, /* size as varint */ 0x11, /* key type | val type */ 0x01, /* key: true */ 0x02, /* val: false */ ]; assert_eq_written_bytes!(o_prot, expected); } #[test] fn must_round_trip_map_with_bool_value() { let (mut i_prot, mut o_prot) = test_objects(); let map_ident = TMapIdentifier::new(TType::Bool, TType::Bool, 2); assert_success!(o_prot.write_map_begin(&map_ident)); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_bool(false)); assert_success!(o_prot.write_bool(true)); assert_success!(o_prot.write_map_end()); copy_write_buffer_to_read_buffer!(o_prot); // map header let rcvd_ident = assert_success!(i_prot.read_map_begin()); assert_eq!(&rcvd_ident, &map_ident); // key 1 let b = assert_success!(i_prot.read_bool()); assert_eq!(b, true); // val 1 let b = assert_success!(i_prot.read_bool()); assert_eq!(b, false); // key 2 let b = assert_success!(i_prot.read_bool()); assert_eq!(b, false); // val 2 let b = assert_success!(i_prot.read_bool()); assert_eq!(b, true); // map end assert_success!(i_prot.read_map_end()); } #[test] fn must_read_map_end() { let (mut i_prot, _) = test_objects(); assert!(i_prot.read_map_end().is_ok()); // will blow up if we try to read from empty buffer } fn test_objects() -> ( TCompactInputProtocol>, TCompactOutputProtocol>, ) { let mem = TBufferChannel::with_capacity(80, 80); let (r_mem, w_mem) = mem.split().unwrap(); let i_prot = TCompactInputProtocol::new(r_mem); let o_prot = TCompactOutputProtocol::new(w_mem); (i_prot, o_prot) } #[test] fn must_read_write_double() { let (mut i_prot, mut o_prot) = test_objects(); #[allow(clippy::approx_constant)] let double = 3.141_592_653_589_793; o_prot.write_double(double).unwrap(); copy_write_buffer_to_read_buffer!(o_prot); let read_double = i_prot.read_double().unwrap(); assert!(read_double - double < std::f64::EPSILON); } #[test] fn must_encode_double_as_other_langs() { let (_, mut o_prot) = test_objects(); let expected = [24, 45, 68, 84, 251, 33, 9, 64]; #[allow(clippy::approx_constant)] let double = 3.141_592_653_589_793; o_prot.write_double(double).unwrap(); assert_eq_written_bytes!(o_prot, expected); } fn assert_no_write(mut write_fn: F) where F: FnMut(&mut TCompactOutputProtocol>) -> crate::Result<()>, { let (_, mut o_prot) = test_objects(); assert!(write_fn(&mut o_prot).is_ok()); assert_eq!(o_prot.transport.write_bytes().len(), 0); } } thrift-0.19.0/lib/rs/src/lib.rs0000644000000000000000000000564114303740367016211 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //! Rust runtime library for the Apache Thrift RPC system. //! //! This crate implements the components required to build a working //! Thrift server and client. It is divided into the following modules: //! //! 1. errors //! 2. protocol //! 3. transport //! 4. server //! 5. autogen //! //! The modules are layered as shown in the diagram below. The `autogen'd` //! layer is generated by the Thrift compiler's Rust plugin. It uses the //! types and functions defined in this crate to serialize and deserialize //! messages and implement RPC. Users interact with these types and services //! by writing their own code that uses the auto-generated clients and //! servers. //! //! ```text //! +-----------+ //! | user app | //! +-----------+ //! | autogen'd | (uses errors, autogen) //! +-----------+ //! | protocol | //! +-----------+ //! | transport | //! +-----------+ //! ``` //! //! # Tutorial //! //! For an example of how to setup a simple client and server using this crate //! see the [tutorial]. //! //! [tutorial]: https://github.com/apache/thrift/tree/master/tutorial/rs #![crate_type = "lib"] #![doc(test(attr(allow(unused_variables), deny(warnings))))] #![deny(bare_trait_objects)] // NOTE: this macro has to be defined before any modules. See: // https://danielkeep.github.io/quick-intro-to-macros.html#some-more-gotchas /// Assert that an expression returning a `Result` is a success. If it is, /// return the value contained in the result, i.e. `expr.unwrap()`. #[cfg(test)] macro_rules! assert_success { ($e: expr) => {{ let res = $e; assert!(res.is_ok()); res.unwrap() }}; } pub mod protocol; #[cfg(feature = "server")] pub mod server; pub mod transport; mod errors; pub use crate::errors::*; mod autogen; pub use crate::autogen::*; /// Result type returned by all runtime library functions. /// /// As is convention this is a typedef of `std::result::Result` /// with `E` defined as the `thrift::Error` type. pub type Result = std::result::Result; // Re-export ordered-float, since it is used by the generator // FIXME: check the guidance around type reexports pub use ordered_float::OrderedFloat; thrift-0.19.0/lib/rs/src/autogen.rs0000644000000000000000000000414114303740367017077 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //! Thrift compiler auto-generated support. //! //! //! Types and functions used internally by the Thrift compiler's Rust plugin //! to implement required functionality. Users should never have to use code //! in this module directly. use crate::protocol::{TInputProtocol, TOutputProtocol}; /// Specifies the minimum functionality an auto-generated client should provide /// to communicate with a Thrift server. pub trait TThriftClient { /// Returns the input protocol used to read serialized Thrift messages /// from the Thrift server. fn i_prot_mut(&mut self) -> &mut dyn TInputProtocol; /// Returns the output protocol used to write serialized Thrift messages /// to the Thrift server. fn o_prot_mut(&mut self) -> &mut dyn TOutputProtocol; /// Returns the sequence number of the last message written to the Thrift /// server. Returns `0` if no messages have been written. Sequence /// numbers should *never* be negative, and this method returns an `i32` /// simply because the Thrift protocol encodes sequence numbers as `i32` on /// the wire. fn sequence_number(&self) -> i32; // FIXME: consider returning a u32 /// Increments the sequence number, indicating that a message with that /// number has been sent to the Thrift server. fn increment_sequence_number(&mut self) -> i32; } thrift-0.19.0/lib/rs/src/server/0000777000000000000000000000000014370300523016367 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/src/server/mod.rs0000644000000000000000000001016214303740367017522 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //! Types used to implement a Thrift server. use crate::protocol::{TInputProtocol, TMessageIdentifier, TMessageType, TOutputProtocol}; use crate::{ApplicationError, ApplicationErrorKind}; mod multiplexed; mod threaded; pub use self::multiplexed::TMultiplexedProcessor; pub use self::threaded::TServer; /// Handles incoming Thrift messages and dispatches them to the user-defined /// handler functions. /// /// An implementation is auto-generated for each Thrift service. When used by a /// server (for example, a `TSimpleServer`), it will demux incoming service /// calls and invoke the corresponding user-defined handler function. /// /// # Examples /// /// Create and start a server using the auto-generated `TProcessor` for /// a Thrift service `SimpleService`. /// /// ```no_run /// use thrift::protocol::{TInputProtocol, TOutputProtocol}; /// use thrift::server::TProcessor; /// /// // /// // auto-generated /// // /// /// // processor for `SimpleService` /// struct SimpleServiceSyncProcessor; /// impl SimpleServiceSyncProcessor { /// fn new(processor: H) -> SimpleServiceSyncProcessor { /// unimplemented!(); /// } /// } /// /// // `TProcessor` implementation for `SimpleService` /// impl TProcessor for SimpleServiceSyncProcessor { /// fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> thrift::Result<()> { /// unimplemented!(); /// } /// } /// /// // service functions for SimpleService /// trait SimpleServiceSyncHandler { /// fn service_call(&self) -> thrift::Result<()>; /// } /// /// // /// // user-code follows /// // /// /// // define a handler that will be invoked when `service_call` is received /// struct SimpleServiceHandlerImpl; /// impl SimpleServiceSyncHandler for SimpleServiceHandlerImpl { /// fn service_call(&self) -> thrift::Result<()> { /// unimplemented!(); /// } /// } /// /// // instantiate the processor /// let processor = SimpleServiceSyncProcessor::new(SimpleServiceHandlerImpl {}); /// /// // at this point you can pass the processor to the server /// // let server = TServer::new(..., processor); /// ``` pub trait TProcessor { /// Process a Thrift service call. /// /// Reads arguments from `i`, executes the user's handler code, and writes /// the response to `o`. /// /// Returns `()` if the handler was executed; `Err` otherwise. fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> crate::Result<()>; } /// Convenience function used in generated `TProcessor` implementations to /// return an `ApplicationError` if thrift message processing failed. pub fn handle_process_result( msg_ident: &TMessageIdentifier, res: crate::Result<()>, o_prot: &mut dyn TOutputProtocol, ) -> crate::Result<()> { if let Err(e) = res { let e = match e { crate::Error::Application(a) => a, _ => ApplicationError::new(ApplicationErrorKind::Unknown, format!("{:?}", e)), }; let ident = TMessageIdentifier::new( msg_ident.name.clone(), TMessageType::Exception, msg_ident.sequence_number, ); o_prot.write_message_begin(&ident)?; crate::Error::write_application_error_to_out_protocol(&e, o_prot)?; o_prot.write_message_end()?; o_prot.flush() } else { Ok(()) } } thrift-0.19.0/lib/rs/src/server/multiplexed.rs0000644000000000000000000003126314370300523021272 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use log::debug; use std::collections::HashMap; use std::convert::Into; use std::fmt; use std::fmt::{Debug, Formatter}; use std::sync::{Arc, Mutex}; use crate::protocol::{TInputProtocol, TMessageIdentifier, TOutputProtocol, TStoredInputProtocol}; use super::{handle_process_result, TProcessor}; const MISSING_SEPARATOR_AND_NO_DEFAULT: &str = "missing service separator and no default processor set"; type ThreadSafeProcessor = Box; /// A `TProcessor` that can demux service calls to multiple underlying /// Thrift services. /// /// Users register service-specific `TProcessor` instances with a /// `TMultiplexedProcessor`, and then register that processor with a server /// implementation. Following that, all incoming service calls are automatically /// routed to the service-specific `TProcessor`. /// /// A `TMultiplexedProcessor` can only handle messages sent by a /// `TMultiplexedOutputProtocol`. #[derive(Default)] pub struct TMultiplexedProcessor { stored: Mutex, } #[derive(Default)] struct StoredProcessors { processors: HashMap>, default_processor: Option>, } impl TMultiplexedProcessor { /// Create a new `TMultiplexedProcessor` with no registered service-specific /// processors. pub fn new() -> TMultiplexedProcessor { TMultiplexedProcessor { stored: Mutex::new(StoredProcessors { processors: HashMap::new(), default_processor: None, }), } } /// Register a service-specific `processor` for the service named /// `service_name`. This implementation is also backwards-compatible with /// non-multiplexed clients. Set `as_default` to `true` to allow /// non-namespaced requests to be dispatched to a default processor. /// /// Returns success if a new entry was inserted. Returns an error if: /// * A processor exists for `service_name` /// * You attempt to register a processor as default, and an existing default exists #[allow(clippy::map_entry)] pub fn register>( &mut self, service_name: S, processor: Box, as_default: bool, ) -> crate::Result<()> { let mut stored = self.stored.lock().unwrap(); let name = service_name.into(); if !stored.processors.contains_key(&name) { let processor = Arc::new(processor); if as_default { if stored.default_processor.is_none() { stored.processors.insert(name, processor.clone()); stored.default_processor = Some(processor.clone()); Ok(()) } else { Err("cannot reset default processor".into()) } } else { stored.processors.insert(name, processor); Ok(()) } } else { Err(format!("cannot overwrite existing processor for service {}", name).into()) } } fn process_message( &self, msg_ident: &TMessageIdentifier, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol, ) -> crate::Result<()> { let (svc_name, svc_call) = split_ident_name(&msg_ident.name); debug!("routing svc_name {:?} svc_call {}", &svc_name, &svc_call); let processor: Option> = { let stored = self.stored.lock().unwrap(); if let Some(name) = svc_name { stored.processors.get(name).cloned() } else { stored.default_processor.clone() } }; match processor { Some(arc) => { let new_msg_ident = TMessageIdentifier::new( svc_call, msg_ident.message_type, msg_ident.sequence_number, ); let mut proxy_i_prot = TStoredInputProtocol::new(i_prot, new_msg_ident); (*arc).process(&mut proxy_i_prot, o_prot) } None => Err(missing_processor_message(svc_name).into()), } } } impl TProcessor for TMultiplexedProcessor { fn process( &self, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol, ) -> crate::Result<()> { let msg_ident = i_prot.read_message_begin()?; debug!("process incoming msg id:{:?}", &msg_ident); let res = self.process_message(&msg_ident, i_prot, o_prot); handle_process_result(&msg_ident, res, o_prot) } } impl Debug for TMultiplexedProcessor { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let stored = self.stored.lock().unwrap(); write!( f, "TMultiplexedProcess {{ registered_count: {:?} default: {:?} }}", stored.processors.keys().len(), stored.default_processor.is_some() ) } } fn split_ident_name(ident_name: &str) -> (Option<&str>, &str) { ident_name .find(':') .map(|pos| { let (svc_name, svc_call) = ident_name.split_at(pos); let (_, svc_call) = svc_call.split_at(1); // remove colon from service call name (Some(svc_name), svc_call) }) .unwrap_or((None, ident_name)) } fn missing_processor_message(svc_name: Option<&str>) -> String { match svc_name { Some(name) => format!("no processor found for service {}", name), None => MISSING_SEPARATOR_AND_NO_DEFAULT.to_owned(), } } #[cfg(test)] mod tests { use std::convert::Into; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use crate::protocol::{ TBinaryInputProtocol, TBinaryOutputProtocol, TMessageIdentifier, TMessageType, }; use crate::transport::{ReadHalf, TBufferChannel, TIoChannel, WriteHalf}; use crate::{ApplicationError, ApplicationErrorKind}; use super::*; #[test] fn should_split_name_into_proper_separator_and_service_call() { let ident_name = "foo:bar_call"; let (serv, call) = split_ident_name(&ident_name); assert_eq!(serv, Some("foo")); assert_eq!(call, "bar_call"); } #[test] fn should_return_full_ident_if_no_separator_exists() { let ident_name = "bar_call"; let (serv, call) = split_ident_name(&ident_name); assert_eq!(serv, None); assert_eq!(call, "bar_call"); } #[test] fn should_write_error_if_no_separator_found_and_no_default_processor_exists() { let (mut i, mut o) = build_objects(); let sent_ident = TMessageIdentifier::new("foo", TMessageType::Call, 10); o.write_message_begin(&sent_ident).unwrap(); o.flush().unwrap(); o.transport.copy_write_buffer_to_read_buffer(); o.transport.empty_write_buffer(); let p = TMultiplexedProcessor::new(); p.process(&mut i, &mut o).unwrap(); // at this point an error should be written out i.transport.set_readable_bytes(&o.transport.write_bytes()); let rcvd_ident = i.read_message_begin().unwrap(); let expected_ident = TMessageIdentifier::new("foo", TMessageType::Exception, 10); assert_eq!(rcvd_ident, expected_ident); let rcvd_err = crate::Error::read_application_error_from_in_protocol(&mut i).unwrap(); let expected_err = ApplicationError::new( ApplicationErrorKind::Unknown, MISSING_SEPARATOR_AND_NO_DEFAULT, ); assert_eq!(rcvd_err, expected_err); } #[test] fn should_write_error_if_separator_exists_and_no_processor_found() { let (mut i, mut o) = build_objects(); let sent_ident = TMessageIdentifier::new("missing:call", TMessageType::Call, 10); o.write_message_begin(&sent_ident).unwrap(); o.flush().unwrap(); o.transport.copy_write_buffer_to_read_buffer(); o.transport.empty_write_buffer(); let p = TMultiplexedProcessor::new(); p.process(&mut i, &mut o).unwrap(); // at this point an error should be written out i.transport.set_readable_bytes(&o.transport.write_bytes()); let rcvd_ident = i.read_message_begin().unwrap(); let expected_ident = TMessageIdentifier::new("missing:call", TMessageType::Exception, 10); assert_eq!(rcvd_ident, expected_ident); let rcvd_err = crate::Error::read_application_error_from_in_protocol(&mut i).unwrap(); let expected_err = ApplicationError::new( ApplicationErrorKind::Unknown, missing_processor_message(Some("missing")), ); assert_eq!(rcvd_err, expected_err); } #[derive(Default)] struct Service { pub invoked: Arc, } impl TProcessor for Service { fn process( &self, _: &mut dyn TInputProtocol, _: &mut dyn TOutputProtocol, ) -> crate::Result<()> { let res = self.invoked .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed); if res.is_ok() { Ok(()) } else { Err("failed swap".into()) } } } #[test] fn should_route_call_to_correct_processor() { let (mut i, mut o) = build_objects(); // build the services let svc_1 = Service { invoked: Arc::new(AtomicBool::new(false)), }; let atm_1 = svc_1.invoked.clone(); let svc_2 = Service { invoked: Arc::new(AtomicBool::new(false)), }; let atm_2 = svc_2.invoked.clone(); // register them let mut p = TMultiplexedProcessor::new(); p.register("service_1", Box::new(svc_1), false).unwrap(); p.register("service_2", Box::new(svc_2), false).unwrap(); // make the service call let sent_ident = TMessageIdentifier::new("service_1:call", TMessageType::Call, 10); o.write_message_begin(&sent_ident).unwrap(); o.flush().unwrap(); o.transport.copy_write_buffer_to_read_buffer(); o.transport.empty_write_buffer(); p.process(&mut i, &mut o).unwrap(); // service 1 should have been invoked, not service 2 assert_eq!(atm_1.load(Ordering::Relaxed), true); assert_eq!(atm_2.load(Ordering::Relaxed), false); } #[test] fn should_route_call_to_correct_processor_if_no_separator_exists_and_default_processor_set() { let (mut i, mut o) = build_objects(); // build the services let svc_1 = Service { invoked: Arc::new(AtomicBool::new(false)), }; let atm_1 = svc_1.invoked.clone(); let svc_2 = Service { invoked: Arc::new(AtomicBool::new(false)), }; let atm_2 = svc_2.invoked.clone(); // register them let mut p = TMultiplexedProcessor::new(); p.register("service_1", Box::new(svc_1), false).unwrap(); p.register("service_2", Box::new(svc_2), true).unwrap(); // second processor is default // make the service call (it's an old client, so we have to be backwards compatible) let sent_ident = TMessageIdentifier::new("old_call", TMessageType::Call, 10); o.write_message_begin(&sent_ident).unwrap(); o.flush().unwrap(); o.transport.copy_write_buffer_to_read_buffer(); o.transport.empty_write_buffer(); p.process(&mut i, &mut o).unwrap(); // service 2 should have been invoked, not service 1 assert_eq!(atm_1.load(Ordering::Relaxed), false); assert_eq!(atm_2.load(Ordering::Relaxed), true); } fn build_objects() -> ( TBinaryInputProtocol>, TBinaryOutputProtocol>, ) { let c = TBufferChannel::with_capacity(128, 128); let (r_c, w_c) = c.split().unwrap(); ( TBinaryInputProtocol::new(r_c, true), TBinaryOutputProtocol::new(w_c, true), ) } } thrift-0.19.0/lib/rs/src/server/threaded.rs0000644000000000000000000002363714303740367020536 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use log::warn; use std::net::{TcpListener, ToSocketAddrs}; use std::sync::Arc; use threadpool::ThreadPool; #[cfg(unix)] use std::os::unix::net::UnixListener; #[cfg(unix)] use std::path::Path; use crate::protocol::{ TInputProtocol, TInputProtocolFactory, TOutputProtocol, TOutputProtocolFactory, }; use crate::transport::{TIoChannel, TReadTransportFactory, TTcpChannel, TWriteTransportFactory}; use crate::{ApplicationError, ApplicationErrorKind}; use super::TProcessor; use crate::TransportErrorKind; /// Fixed-size thread-pool blocking Thrift server. /// /// A `TServer` listens on a given address and submits accepted connections /// to an **unbounded** queue. Connections from this queue are serviced by /// the first available worker thread from a **fixed-size** thread pool. Each /// accepted connection is handled by that worker thread, and communication /// over this thread occurs sequentially and synchronously (i.e. calls block). /// Accepted connections have an input half and an output half, each of which /// uses a `TTransport` and `TInputProtocol`/`TOutputProtocol` to translate /// messages to and from byes. Any combination of `TInputProtocol`, `TOutputProtocol` /// and `TTransport` may be used. /// /// # Examples /// /// Creating and running a `TServer` using Thrift-compiler-generated /// service code. /// /// ```no_run /// use thrift::protocol::{TInputProtocolFactory, TOutputProtocolFactory}; /// use thrift::protocol::{TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory}; /// use thrift::protocol::{TInputProtocol, TOutputProtocol}; /// use thrift::transport::{TBufferedReadTransportFactory, TBufferedWriteTransportFactory, /// TReadTransportFactory, TWriteTransportFactory}; /// use thrift::server::{TProcessor, TServer}; /// /// // /// // auto-generated /// // /// /// // processor for `SimpleService` /// struct SimpleServiceSyncProcessor; /// impl SimpleServiceSyncProcessor { /// fn new(processor: H) -> SimpleServiceSyncProcessor { /// unimplemented!(); /// } /// } /// /// // `TProcessor` implementation for `SimpleService` /// impl TProcessor for SimpleServiceSyncProcessor { /// fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> thrift::Result<()> { /// unimplemented!(); /// } /// } /// /// // service functions for SimpleService /// trait SimpleServiceSyncHandler { /// fn service_call(&self) -> thrift::Result<()>; /// } /// /// // /// // user-code follows /// // /// /// // define a handler that will be invoked when `service_call` is received /// struct SimpleServiceHandlerImpl; /// impl SimpleServiceSyncHandler for SimpleServiceHandlerImpl { /// fn service_call(&self) -> thrift::Result<()> { /// unimplemented!(); /// } /// } /// /// // instantiate the processor /// let processor = SimpleServiceSyncProcessor::new(SimpleServiceHandlerImpl {}); /// /// // instantiate the server /// let i_tr_fact: Box = Box::new(TBufferedReadTransportFactory::new()); /// let i_pr_fact: Box = Box::new(TBinaryInputProtocolFactory::new()); /// let o_tr_fact: Box = Box::new(TBufferedWriteTransportFactory::new()); /// let o_pr_fact: Box = Box::new(TBinaryOutputProtocolFactory::new()); /// /// let mut server = TServer::new( /// i_tr_fact, /// i_pr_fact, /// o_tr_fact, /// o_pr_fact, /// processor, /// 10 /// ); /// /// // start listening for incoming connections /// match server.listen("127.0.0.1:8080") { /// Ok(_) => println!("listen completed"), /// Err(e) => println!("listen failed with error {:?}", e), /// } /// ``` #[derive(Debug)] pub struct TServer where PRC: TProcessor + Send + Sync + 'static, RTF: TReadTransportFactory + 'static, IPF: TInputProtocolFactory + 'static, WTF: TWriteTransportFactory + 'static, OPF: TOutputProtocolFactory + 'static, { r_trans_factory: RTF, i_proto_factory: IPF, w_trans_factory: WTF, o_proto_factory: OPF, processor: Arc, worker_pool: ThreadPool, } impl TServer where PRC: TProcessor + Send + Sync + 'static, RTF: TReadTransportFactory + 'static, IPF: TInputProtocolFactory + 'static, WTF: TWriteTransportFactory + 'static, OPF: TOutputProtocolFactory + 'static, { /// Create a `TServer`. /// /// Each accepted connection has an input and output half, each of which /// requires a `TTransport` and `TProtocol`. `TServer` uses /// `read_transport_factory` and `input_protocol_factory` to create /// implementations for the input, and `write_transport_factory` and /// `output_protocol_factory` to create implementations for the output. pub fn new( read_transport_factory: RTF, input_protocol_factory: IPF, write_transport_factory: WTF, output_protocol_factory: OPF, processor: PRC, num_workers: usize, ) -> TServer { TServer { r_trans_factory: read_transport_factory, i_proto_factory: input_protocol_factory, w_trans_factory: write_transport_factory, o_proto_factory: output_protocol_factory, processor: Arc::new(processor), worker_pool: ThreadPool::with_name("Thrift service processor".to_owned(), num_workers), } } /// Listen for incoming connections on `listen_address`. /// /// `listen_address` should implement `ToSocketAddrs` trait. /// /// Return `()` if successful. /// /// Return `Err` when the server cannot bind to `listen_address` or there /// is an unrecoverable error. pub fn listen(&mut self, listen_address: A) -> crate::Result<()> { let listener = TcpListener::bind(listen_address)?; for stream in listener.incoming() { match stream { Ok(s) => { let channel = TTcpChannel::with_stream(s); self.handle_stream(channel)?; } Err(e) => { warn!("failed to accept remote connection with error {:?}", e); } } } Err(crate::Error::Application(ApplicationError { kind: ApplicationErrorKind::Unknown, message: "aborted listen loop".into(), })) } /// Listen for incoming connections on `listen_path`. /// /// `listen_path` should implement `AsRef` trait. /// /// Return `()` if successful. /// /// Return `Err` when the server cannot bind to `listen_path` or there /// is an unrecoverable error. #[cfg(unix)] pub fn listen_uds>(&mut self, listen_path: P) -> crate::Result<()> { let listener = UnixListener::bind(listen_path)?; for stream in listener.incoming() { match stream { Ok(s) => { self.handle_stream(s)?; } Err(e) => { warn!( "failed to accept connection via unix domain socket with error {:?}", e ); } } } Err(crate::Error::Application(ApplicationError { kind: ApplicationErrorKind::Unknown, message: "aborted listen loop".into(), })) } fn handle_stream(&mut self, stream: S) -> crate::Result<()> { let (i_prot, o_prot) = self.new_protocols_for_connection(stream)?; let processor = self.processor.clone(); self.worker_pool .execute(move || handle_incoming_connection(processor, i_prot, o_prot)); Ok(()) } fn new_protocols_for_connection( &mut self, stream: S, ) -> crate::Result<( Box, Box, )> { // split it into two - one to be owned by the // input tran/proto and the other by the output let (r_chan, w_chan) = stream.split()?; // input protocol and transport let r_tran = self.r_trans_factory.create(Box::new(r_chan)); let i_prot = self.i_proto_factory.create(r_tran); // output protocol and transport let w_tran = self.w_trans_factory.create(Box::new(w_chan)); let o_prot = self.o_proto_factory.create(w_tran); Ok((i_prot, o_prot)) } } fn handle_incoming_connection( processor: Arc, i_prot: Box, o_prot: Box, ) where PRC: TProcessor, { let mut i_prot = i_prot; let mut o_prot = o_prot; loop { match processor.process(&mut *i_prot, &mut *o_prot) { Ok(()) => {} Err(err) => { match err { crate::Error::Transport(ref transport_err) if transport_err.kind == TransportErrorKind::EndOfFile => {} other => warn!("processor completed with error: {:?}", other), } break; } } } } thrift-0.19.0/lib/rs/src/transport/0000777000000000000000000000000014303740367017127 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/src/transport/buffered.rs0000644000000000000000000003521014303740367021254 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::cmp; use std::io; use std::io::{Read, Write}; use super::{TReadTransport, TReadTransportFactory, TWriteTransport, TWriteTransportFactory}; /// Default capacity of the read buffer in bytes. const READ_CAPACITY: usize = 4096; /// Default capacity of the write buffer in bytes.. const WRITE_CAPACITY: usize = 4096; /// Transport that reads messages via an internal buffer. /// /// A `TBufferedReadTransport` maintains a fixed-size internal read buffer. /// On a call to `TBufferedReadTransport::read(...)` one full message - both /// fixed-length header and bytes - is read from the wrapped channel and buffered. /// Subsequent read calls are serviced from the internal buffer until it is /// exhausted, at which point the next full message is read from the wrapped /// channel. /// /// # Examples /// /// Create and use a `TBufferedReadTransport`. /// /// ```no_run /// use std::io::Read; /// use thrift::transport::{TBufferedReadTransport, TTcpChannel}; /// /// let mut c = TTcpChannel::new(); /// c.open("localhost:9090").unwrap(); /// /// let mut t = TBufferedReadTransport::new(c); /// /// t.read(&mut vec![0u8; 1]).unwrap(); /// ``` #[derive(Debug)] pub struct TBufferedReadTransport where C: Read, { buf: Box<[u8]>, pos: usize, cap: usize, chan: C, } impl TBufferedReadTransport where C: Read, { /// Create a `TBufferedTransport` with default-sized internal read and /// write buffers that wraps the given `TIoChannel`. pub fn new(channel: C) -> TBufferedReadTransport { TBufferedReadTransport::with_capacity(READ_CAPACITY, channel) } /// Create a `TBufferedTransport` with an internal read buffer of size /// `read_capacity` and an internal write buffer of size /// `write_capacity` that wraps the given `TIoChannel`. pub fn with_capacity(read_capacity: usize, channel: C) -> TBufferedReadTransport { TBufferedReadTransport { buf: vec![0; read_capacity].into_boxed_slice(), pos: 0, cap: 0, chan: channel, } } fn get_bytes(&mut self) -> io::Result<&[u8]> { if self.cap - self.pos == 0 { self.pos = 0; self.cap = self.chan.read(&mut self.buf)?; } Ok(&self.buf[self.pos..self.cap]) } fn consume(&mut self, consumed: usize) { // TODO: was a bug here += <-- test somehow self.pos = cmp::min(self.cap, self.pos + consumed); } } impl Read for TBufferedReadTransport where C: Read, { fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut bytes_read = 0; loop { let nread = { let avail_bytes = self.get_bytes()?; let avail_space = buf.len() - bytes_read; let nread = cmp::min(avail_space, avail_bytes.len()); buf[bytes_read..(bytes_read + nread)].copy_from_slice(&avail_bytes[..nread]); nread }; self.consume(nread); bytes_read += nread; if bytes_read == buf.len() || nread == 0 { break; } } Ok(bytes_read) } } /// Factory for creating instances of `TBufferedReadTransport`. #[derive(Default)] pub struct TBufferedReadTransportFactory; impl TBufferedReadTransportFactory { pub fn new() -> TBufferedReadTransportFactory { TBufferedReadTransportFactory {} } } impl TReadTransportFactory for TBufferedReadTransportFactory { /// Create a `TBufferedReadTransport`. fn create(&self, channel: Box) -> Box { Box::new(TBufferedReadTransport::new(channel)) } } /// Transport that writes messages via an internal buffer. /// /// A `TBufferedWriteTransport` maintains a fixed-size internal write buffer. /// All writes are made to this buffer and are sent to the wrapped channel only /// when `TBufferedWriteTransport::flush()` is called. On a flush a fixed-length /// header with a count of the buffered bytes is written, followed by the bytes /// themselves. /// /// # Examples /// /// Create and use a `TBufferedWriteTransport`. /// /// ```no_run /// use std::io::Write; /// use thrift::transport::{TBufferedWriteTransport, TTcpChannel}; /// /// let mut c = TTcpChannel::new(); /// c.open("localhost:9090").unwrap(); /// /// let mut t = TBufferedWriteTransport::new(c); /// /// t.write(&[0x00]).unwrap(); /// t.flush().unwrap(); /// ``` #[derive(Debug)] pub struct TBufferedWriteTransport where C: Write, { buf: Vec, cap: usize, channel: C, } impl TBufferedWriteTransport where C: Write, { /// Create a `TBufferedTransport` with default-sized internal read and /// write buffers that wraps the given `TIoChannel`. pub fn new(channel: C) -> TBufferedWriteTransport { TBufferedWriteTransport::with_capacity(WRITE_CAPACITY, channel) } /// Create a `TBufferedTransport` with an internal read buffer of size /// `read_capacity` and an internal write buffer of size /// `write_capacity` that wraps the given `TIoChannel`. pub fn with_capacity(write_capacity: usize, channel: C) -> TBufferedWriteTransport { assert!( write_capacity > 0, "write buffer size must be a positive integer" ); TBufferedWriteTransport { buf: Vec::with_capacity(write_capacity), cap: write_capacity, channel, } } } impl Write for TBufferedWriteTransport where C: Write, { fn write(&mut self, buf: &[u8]) -> io::Result { if !buf.is_empty() { let mut avail_bytes; loop { avail_bytes = cmp::min(buf.len(), self.cap - self.buf.len()); if avail_bytes == 0 { self.flush()?; } else { break; } } let avail_bytes = avail_bytes; self.buf.extend_from_slice(&buf[..avail_bytes]); assert!(self.buf.len() <= self.cap, "copy overflowed buffer"); Ok(avail_bytes) } else { Ok(0) } } fn flush(&mut self) -> io::Result<()> { self.channel.write_all(&self.buf)?; self.channel.flush()?; self.buf.clear(); Ok(()) } } /// Factory for creating instances of `TBufferedWriteTransport`. #[derive(Default)] pub struct TBufferedWriteTransportFactory; impl TBufferedWriteTransportFactory { pub fn new() -> TBufferedWriteTransportFactory { TBufferedWriteTransportFactory {} } } impl TWriteTransportFactory for TBufferedWriteTransportFactory { /// Create a `TBufferedWriteTransport`. fn create(&self, channel: Box) -> Box { Box::new(TBufferedWriteTransport::new(channel)) } } #[cfg(test)] mod tests { use std::io::{Read, Write}; use super::*; use crate::transport::TBufferChannel; #[test] fn must_return_zero_if_read_buffer_is_empty() { let mem = TBufferChannel::with_capacity(10, 0); let mut t = TBufferedReadTransport::with_capacity(10, mem); let mut b = vec![0; 10]; let read_result = t.read(&mut b); assert_eq!(read_result.unwrap(), 0); } #[test] fn must_return_zero_if_caller_reads_into_zero_capacity_buffer() { let mem = TBufferChannel::with_capacity(10, 0); let mut t = TBufferedReadTransport::with_capacity(10, mem); let read_result = t.read(&mut []); assert_eq!(read_result.unwrap(), 0); } #[test] fn must_return_zero_if_nothing_more_can_be_read() { let mem = TBufferChannel::with_capacity(4, 0); let mut t = TBufferedReadTransport::with_capacity(4, mem); t.chan.set_readable_bytes(&[0, 1, 2, 3]); // read buffer is exactly the same size as bytes available let mut buf = vec![0u8; 4]; let read_result = t.read(&mut buf); // we've read exactly 4 bytes assert_eq!(read_result.unwrap(), 4); assert_eq!(&buf, &[0, 1, 2, 3]); // try read again let buf_again = vec![0u8; 4]; let read_result = t.read(&mut buf); // this time, 0 bytes and we haven't changed the buffer assert_eq!(read_result.unwrap(), 0); assert_eq!(&buf_again, &[0, 0, 0, 0]) } #[test] fn must_fill_user_buffer_with_only_as_many_bytes_as_available() { let mem = TBufferChannel::with_capacity(4, 0); let mut t = TBufferedReadTransport::with_capacity(4, mem); t.chan.set_readable_bytes(&[0, 1, 2, 3]); // read buffer is much larger than the bytes available let mut buf = vec![0u8; 8]; let read_result = t.read(&mut buf); // we've read exactly 4 bytes assert_eq!(read_result.unwrap(), 4); assert_eq!(&buf[..4], &[0, 1, 2, 3]); // try read again let read_result = t.read(&mut buf[4..]); // this time, 0 bytes and we haven't changed the buffer assert_eq!(read_result.unwrap(), 0); assert_eq!(&buf, &[0, 1, 2, 3, 0, 0, 0, 0]) } #[test] fn must_read_successfully() { // this test involves a few loops within the buffered transport // itself where it has to drain the underlying transport in order // to service a read // we have a much smaller buffer than the // underlying transport has bytes available let mem = TBufferChannel::with_capacity(10, 0); let mut t = TBufferedReadTransport::with_capacity(2, mem); // fill the underlying transport's byte buffer let mut readable_bytes = [0u8; 10]; for (i, b) in readable_bytes.iter_mut().enumerate() { *b = i as u8; } t.chan.set_readable_bytes(&readable_bytes); // we ask to read into a buffer that's much larger // than the one the buffered transport has; as a result // it's going to have to keep asking the underlying // transport for more bytes let mut buf = [0u8; 8]; let read_result = t.read(&mut buf); // we should have read 8 bytes assert_eq!(read_result.unwrap(), 8); assert_eq!(&buf, &[0, 1, 2, 3, 4, 5, 6, 7]); // let's clear out the buffer and try read again for b in &mut buf { *b = 0; } let read_result = t.read(&mut buf); // this time we were only able to read 2 bytes // (all that's remaining from the underlying transport) // let's also check that the remaining bytes are untouched assert_eq!(read_result.unwrap(), 2); assert_eq!(&buf[0..2], &[8, 9]); assert_eq!(&buf[2..], &[0, 0, 0, 0, 0, 0]); // try read again (we should get 0) // and all the existing bytes were untouched let read_result = t.read(&mut buf); assert_eq!(read_result.unwrap(), 0); assert_eq!(&buf[0..2], &[8, 9]); assert_eq!(&buf[2..], &[0, 0, 0, 0, 0, 0]); } #[test] fn must_return_error_when_nothing_can_be_written_to_underlying_channel() { let mem = TBufferChannel::with_capacity(0, 0); let mut t = TBufferedWriteTransport::with_capacity(1, mem); let b = vec![0; 10]; let r = t.write(&b); // should have written 1 byte assert_eq!(r.unwrap(), 1); // let's try again... let r = t.write(&b[1..]); // this time we'll error out because the auto-flush failed assert!(r.is_err()); } #[test] fn must_return_zero_if_caller_calls_write_with_empty_buffer() { let mem = TBufferChannel::with_capacity(0, 10); let mut t = TBufferedWriteTransport::with_capacity(10, mem); let r = t.write(&[]); let expected: [u8; 0] = []; assert_eq!(r.unwrap(), 0); assert_eq_transport_written_bytes!(t, expected); } #[test] fn must_auto_flush_if_write_buffer_full() { let mem = TBufferChannel::with_capacity(0, 8); let mut t = TBufferedWriteTransport::with_capacity(4, mem); let b0 = [0x00, 0x01, 0x02, 0x03]; let b1 = [0x04, 0x05, 0x06, 0x07]; // write the first 4 bytes; we've now filled the transport's write buffer let r = t.write(&b0); assert_eq!(r.unwrap(), 4); // try write the next 4 bytes; this causes the transport to auto-flush the first 4 bytes let r = t.write(&b1); assert_eq!(r.unwrap(), 4); // check that in writing the second 4 bytes we auto-flushed the first 4 bytes assert_eq_transport_num_written_bytes!(t, 4); assert_eq_transport_written_bytes!(t, b0); t.channel.empty_write_buffer(); // now flush the transport to push the second 4 bytes to the underlying channel assert!(t.flush().is_ok()); // check that we wrote out the second 4 bytes assert_eq_transport_written_bytes!(t, b1); } #[test] fn must_write_to_inner_transport_on_flush() { let mem = TBufferChannel::with_capacity(10, 10); let mut t = TBufferedWriteTransport::new(mem); let b: [u8; 5] = [0, 1, 2, 3, 4]; assert_eq!(t.write(&b).unwrap(), 5); assert_eq_transport_num_written_bytes!(t, 0); assert!(t.flush().is_ok()); assert_eq_transport_written_bytes!(t, b); } #[test] fn must_write_successfully_after_flush() { let mem = TBufferChannel::with_capacity(0, 5); let mut t = TBufferedWriteTransport::with_capacity(5, mem); // write and flush let b: [u8; 5] = [0, 1, 2, 3, 4]; assert_eq!(t.write(&b).unwrap(), 5); assert!(t.flush().is_ok()); // check the flushed bytes assert_eq_transport_written_bytes!(t, b); // reset our underlying transport t.channel.empty_write_buffer(); // write and flush again assert_eq!(t.write(&b).unwrap(), 5); assert!(t.flush().is_ok()); // check the flushed bytes assert_eq_transport_written_bytes!(t, b); } } thrift-0.19.0/lib/rs/src/transport/mod.rs0000644000000000000000000001727214303740367020261 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //! Types used to send and receive bytes over an I/O channel. //! //! The core types are the `TReadTransport`, `TWriteTransport` and the //! `TIoChannel` traits, through which `TInputProtocol` or //! `TOutputProtocol` can receive and send primitives over the wire. While //! `TInputProtocol` and `TOutputProtocol` instances deal with language primitives //! the types in this module understand only bytes. use std::io; use std::io::{Read, Write}; use std::ops::{Deref, DerefMut}; #[cfg(test)] macro_rules! assert_eq_transport_num_written_bytes { ($transport:ident, $num_written_bytes:expr) => {{ assert_eq!($transport.channel.write_bytes().len(), $num_written_bytes); }}; } #[cfg(test)] macro_rules! assert_eq_transport_written_bytes { ($transport:ident, $expected_bytes:ident) => {{ assert_eq!($transport.channel.write_bytes(), &$expected_bytes); }}; } mod buffered; mod framed; mod mem; mod socket; pub use self::buffered::{ TBufferedReadTransport, TBufferedReadTransportFactory, TBufferedWriteTransport, TBufferedWriteTransportFactory, }; pub use self::framed::{ TFramedReadTransport, TFramedReadTransportFactory, TFramedWriteTransport, TFramedWriteTransportFactory, }; pub use self::mem::TBufferChannel; pub use self::socket::TTcpChannel; /// Identifies a transport used by a `TInputProtocol` to receive bytes. pub trait TReadTransport: Read {} /// Helper type used by a server to create `TReadTransport` instances for /// accepted client connections. pub trait TReadTransportFactory { /// Create a `TTransport` that wraps a channel over which bytes are to be read. fn create(&self, channel: Box) -> Box; } /// Identifies a transport used by `TOutputProtocol` to send bytes. pub trait TWriteTransport: Write {} /// Helper type used by a server to create `TWriteTransport` instances for /// accepted client connections. pub trait TWriteTransportFactory { /// Create a `TTransport` that wraps a channel over which bytes are to be sent. fn create(&self, channel: Box) -> Box; } impl TReadTransport for T where T: Read {} impl TWriteTransport for T where T: Write {} // FIXME: implement the Debug trait for boxed transports impl TReadTransportFactory for Box where T: TReadTransportFactory + ?Sized, { fn create(&self, channel: Box) -> Box { (**self).create(channel) } } impl TWriteTransportFactory for Box where T: TWriteTransportFactory + ?Sized, { fn create(&self, channel: Box) -> Box { (**self).create(channel) } } /// Identifies a splittable bidirectional I/O channel used to send and receive bytes. pub trait TIoChannel: Read + Write { /// Split the channel into a readable half and a writable half, where the /// readable half implements `io::Read` and the writable half implements /// `io::Write`. Returns `None` if the channel was not initialized, or if it /// cannot be split safely. /// /// Returned halves may share the underlying OS channel or buffer resources. /// Implementations **should ensure** that these two halves can be safely /// used independently by concurrent threads. fn split( self, ) -> crate::Result<( crate::transport::ReadHalf, crate::transport::WriteHalf, )> where Self: Sized; } /// The readable half of an object returned from `TIoChannel::split`. #[derive(Debug)] pub struct ReadHalf where C: Read, { handle: C, } /// The writable half of an object returned from `TIoChannel::split`. #[derive(Debug)] pub struct WriteHalf where C: Write, { handle: C, } impl ReadHalf where C: Read, { /// Create a `ReadHalf` associated with readable `handle` pub fn new(handle: C) -> ReadHalf { ReadHalf { handle } } } impl WriteHalf where C: Write, { /// Create a `WriteHalf` associated with writable `handle` pub fn new(handle: C) -> WriteHalf { WriteHalf { handle } } } impl Read for ReadHalf where C: Read, { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.handle.read(buf) } } impl Write for WriteHalf where C: Write, { fn write(&mut self, buf: &[u8]) -> io::Result { self.handle.write(buf) } fn flush(&mut self) -> io::Result<()> { self.handle.flush() } } impl Deref for ReadHalf where C: Read, { type Target = C; fn deref(&self) -> &Self::Target { &self.handle } } impl DerefMut for ReadHalf where C: Read, { fn deref_mut(&mut self) -> &mut C { &mut self.handle } } impl Deref for WriteHalf where C: Write, { type Target = C; fn deref(&self) -> &Self::Target { &self.handle } } impl DerefMut for WriteHalf where C: Write, { fn deref_mut(&mut self) -> &mut C { &mut self.handle } } #[cfg(test)] mod tests { use std::io::Cursor; use super::*; #[test] fn must_create_usable_read_channel_from_concrete_read_type() { let r = Cursor::new([0, 1, 2]); let _ = TBufferedReadTransport::new(r); } #[test] fn must_create_usable_read_channel_from_boxed_read() { let r: Box = Box::new(Cursor::new([0, 1, 2])); let _ = TBufferedReadTransport::new(r); } #[test] fn must_create_usable_write_channel_from_concrete_write_type() { let w = vec![0u8; 10]; let _ = TBufferedWriteTransport::new(w); } #[test] fn must_create_usable_write_channel_from_boxed_write() { let w: Box = Box::new(vec![0u8; 10]); let _ = TBufferedWriteTransport::new(w); } #[test] fn must_create_usable_read_transport_from_concrete_read_transport() { let r = Cursor::new([0, 1, 2]); let mut t = TBufferedReadTransport::new(r); takes_read_transport(&mut t) } #[test] fn must_create_usable_read_transport_from_boxed_read() { let r = Cursor::new([0, 1, 2]); let mut t: Box = Box::new(TBufferedReadTransport::new(r)); takes_read_transport(&mut t) } #[test] fn must_create_usable_write_transport_from_concrete_write_transport() { let w = vec![0u8; 10]; let mut t = TBufferedWriteTransport::new(w); takes_write_transport(&mut t) } #[test] fn must_create_usable_write_transport_from_boxed_write() { let w = vec![0u8; 10]; let mut t: Box = Box::new(TBufferedWriteTransport::new(w)); takes_write_transport(&mut t) } fn takes_read_transport(t: &mut R) where R: TReadTransport, { t.bytes(); } fn takes_write_transport(t: &mut W) where W: TWriteTransport, { t.flush().unwrap(); } } thrift-0.19.0/lib/rs/src/transport/framed.rs0000644000000000000000000003400714303740367020733 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use std::cmp; use std::io; use std::io::{Read, Write}; use super::{TReadTransport, TReadTransportFactory, TWriteTransport, TWriteTransportFactory}; /// Default capacity of the read buffer in bytes. const READ_CAPACITY: usize = 4096; /// Default capacity of the write buffer in bytes. const WRITE_CAPACITY: usize = 4096; /// Transport that reads framed messages. /// /// A `TFramedReadTransport` maintains a fixed-size internal read buffer. /// On a call to `TFramedReadTransport::read(...)` one full message - both /// fixed-length header and bytes - is read from the wrapped channel and /// buffered. Subsequent read calls are serviced from the internal buffer /// until it is exhausted, at which point the next full message is read /// from the wrapped channel. /// /// # Examples /// /// Create and use a `TFramedReadTransport`. /// /// ```no_run /// use std::io::Read; /// use thrift::transport::{TFramedReadTransport, TTcpChannel}; /// /// let mut c = TTcpChannel::new(); /// c.open("localhost:9090").unwrap(); /// /// let mut t = TFramedReadTransport::new(c); /// /// t.read(&mut vec![0u8; 1]).unwrap(); /// ``` #[derive(Debug)] pub struct TFramedReadTransport where C: Read, { buf: Vec, pos: usize, cap: usize, chan: C, } impl TFramedReadTransport where C: Read, { /// Create a `TFramedReadTransport` with a default-sized /// internal read buffer that wraps the given `TIoChannel`. pub fn new(channel: C) -> TFramedReadTransport { TFramedReadTransport::with_capacity(READ_CAPACITY, channel) } /// Create a `TFramedTransport` with an internal read buffer /// of size `read_capacity` that wraps the given `TIoChannel`. pub fn with_capacity(read_capacity: usize, channel: C) -> TFramedReadTransport { TFramedReadTransport { buf: vec![0; read_capacity], // FIXME: do I actually have to do this? pos: 0, cap: 0, chan: channel, } } } impl Read for TFramedReadTransport where C: Read, { fn read(&mut self, b: &mut [u8]) -> io::Result { if self.cap - self.pos == 0 { let message_size = self.chan.read_i32::()? as usize; let buf_capacity = cmp::max(message_size, READ_CAPACITY); self.buf.resize(buf_capacity, 0); self.chan.read_exact(&mut self.buf[..message_size])?; self.cap = message_size as usize; self.pos = 0; } let nread = cmp::min(b.len(), self.cap - self.pos); b[..nread].clone_from_slice(&self.buf[self.pos..self.pos + nread]); self.pos += nread; Ok(nread) } } /// Factory for creating instances of `TFramedReadTransport`. #[derive(Default)] pub struct TFramedReadTransportFactory; impl TFramedReadTransportFactory { pub fn new() -> TFramedReadTransportFactory { TFramedReadTransportFactory {} } } impl TReadTransportFactory for TFramedReadTransportFactory { /// Create a `TFramedReadTransport`. fn create(&self, channel: Box) -> Box { Box::new(TFramedReadTransport::new(channel)) } } /// Transport that writes framed messages. /// /// A `TFramedWriteTransport` maintains a fixed-size internal write buffer. All /// writes are made to this buffer and are sent to the wrapped channel only /// when `TFramedWriteTransport::flush()` is called. On a flush a fixed-length /// header with a count of the buffered bytes is written, followed by the bytes /// themselves. /// /// # Examples /// /// Create and use a `TFramedWriteTransport`. /// /// ```no_run /// use std::io::Write; /// use thrift::transport::{TFramedWriteTransport, TTcpChannel}; /// /// let mut c = TTcpChannel::new(); /// c.open("localhost:9090").unwrap(); /// /// let mut t = TFramedWriteTransport::new(c); /// /// t.write(&[0x00]).unwrap(); /// t.flush().unwrap(); /// ``` #[derive(Debug)] pub struct TFramedWriteTransport where C: Write, { buf: Vec, channel: C, } impl TFramedWriteTransport where C: Write, { /// Create a `TFramedWriteTransport` with default-sized internal /// write buffer that wraps the given `TIoChannel`. pub fn new(channel: C) -> TFramedWriteTransport { TFramedWriteTransport::with_capacity(WRITE_CAPACITY, channel) } /// Create a `TFramedWriteTransport` with an internal write buffer /// of size `write_capacity` that wraps the given `TIoChannel`. pub fn with_capacity(write_capacity: usize, channel: C) -> TFramedWriteTransport { TFramedWriteTransport { buf: Vec::with_capacity(write_capacity), channel, } } } impl Write for TFramedWriteTransport where C: Write, { fn write(&mut self, b: &[u8]) -> io::Result { let current_capacity = self.buf.capacity(); let available_space = current_capacity - self.buf.len(); if b.len() > available_space { let additional_space = cmp::max(b.len() - available_space, current_capacity); self.buf.reserve(additional_space); } self.buf.extend_from_slice(b); Ok(b.len()) } fn flush(&mut self) -> io::Result<()> { let message_size = self.buf.len(); if let 0 = message_size { return Ok(()); } else { self.channel.write_i32::(message_size as i32)?; } // will spin if the underlying channel can't be written to let mut byte_index = 0; while byte_index < message_size { let nwrite = self.channel.write(&self.buf[byte_index..message_size])?; byte_index = cmp::min(byte_index + nwrite, message_size); } let buf_capacity = cmp::min(self.buf.capacity(), WRITE_CAPACITY); self.buf.resize(buf_capacity, 0); self.buf.clear(); self.channel.flush() } } /// Factory for creating instances of `TFramedWriteTransport`. #[derive(Default)] pub struct TFramedWriteTransportFactory; impl TFramedWriteTransportFactory { pub fn new() -> TFramedWriteTransportFactory { TFramedWriteTransportFactory {} } } impl TWriteTransportFactory for TFramedWriteTransportFactory { /// Create a `TFramedWriteTransport`. fn create(&self, channel: Box) -> Box { Box::new(TFramedWriteTransport::new(channel)) } } #[cfg(test)] mod tests { use super::*; use crate::transport::mem::TBufferChannel; // FIXME: test a forced reserve #[test] fn must_read_message_smaller_than_initial_buffer_size() { let c = TBufferChannel::with_capacity(10, 10); let mut t = TFramedReadTransport::with_capacity(8, c); t.chan.set_readable_bytes(&[ 0x00, 0x00, 0x00, 0x04, /* message size */ 0x00, 0x01, 0x02, 0x03, /* message body */ ]); let mut buf = vec![0; 8]; // we've read exactly 4 bytes assert_eq!(t.read(&mut buf).unwrap(), 4); assert_eq!(&buf[..4], &[0x00, 0x01, 0x02, 0x03]); } #[test] fn must_read_message_greater_than_initial_buffer_size() { let c = TBufferChannel::with_capacity(10, 10); let mut t = TFramedReadTransport::with_capacity(2, c); t.chan.set_readable_bytes(&[ 0x00, 0x00, 0x00, 0x04, /* message size */ 0x00, 0x01, 0x02, 0x03, /* message body */ ]); let mut buf = vec![0; 8]; // we've read exactly 4 bytes assert_eq!(t.read(&mut buf).unwrap(), 4); assert_eq!(&buf[..4], &[0x00, 0x01, 0x02, 0x03]); } #[test] fn must_read_multiple_messages_in_sequence_correctly() { let c = TBufferChannel::with_capacity(10, 10); let mut t = TFramedReadTransport::with_capacity(2, c); // // 1st message // t.chan.set_readable_bytes(&[ 0x00, 0x00, 0x00, 0x04, /* message size */ 0x00, 0x01, 0x02, 0x03, /* message body */ ]); let mut buf = vec![0; 8]; // we've read exactly 4 bytes assert_eq!(t.read(&mut buf).unwrap(), 4); assert_eq!(&buf, &[0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00]); // // 2nd message // t.chan.set_readable_bytes(&[ 0x00, 0x00, 0x00, 0x01, /* message size */ 0x04, /* message body */ ]); let mut buf = vec![0; 8]; // we've read exactly 1 byte assert_eq!(t.read(&mut buf).unwrap(), 1); assert_eq!(&buf, &[0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); } #[test] fn must_write_message_smaller_than_buffer_size() { let mem = TBufferChannel::with_capacity(0, 0); let mut t = TFramedWriteTransport::with_capacity(20, mem); let b = vec![0; 10]; // should have written 10 bytes assert_eq!(t.write(&b).unwrap(), 10); } #[test] fn must_return_zero_if_caller_calls_write_with_empty_buffer() { let mem = TBufferChannel::with_capacity(0, 10); let mut t = TFramedWriteTransport::with_capacity(10, mem); let expected: [u8; 0] = []; assert_eq!(t.write(&[]).unwrap(), 0); assert_eq_transport_written_bytes!(t, expected); } #[test] fn must_write_to_inner_transport_on_flush() { let mem = TBufferChannel::with_capacity(10, 10); let mut t = TFramedWriteTransport::new(mem); let b: [u8; 5] = [0x00, 0x01, 0x02, 0x03, 0x04]; assert_eq!(t.write(&b).unwrap(), 5); assert_eq_transport_num_written_bytes!(t, 0); assert!(t.flush().is_ok()); let expected_bytes = [ 0x00, 0x00, 0x00, 0x05, /* message size */ 0x00, 0x01, 0x02, 0x03, 0x04, /* message body */ ]; assert_eq_transport_written_bytes!(t, expected_bytes); } #[test] fn must_write_message_greater_than_buffer_size_00() { let mem = TBufferChannel::with_capacity(0, 10); // IMPORTANT: DO **NOT** CHANGE THE WRITE_CAPACITY OR THE NUMBER OF BYTES TO BE WRITTEN! // these lengths were chosen to be just long enough // that doubling the capacity is a **worse** choice than // simply resizing the buffer to b.len() let mut t = TFramedWriteTransport::with_capacity(1, mem); let b = [0x00, 0x01, 0x02]; // should have written 3 bytes assert_eq!(t.write(&b).unwrap(), 3); assert_eq_transport_num_written_bytes!(t, 0); assert!(t.flush().is_ok()); let expected_bytes = [ 0x00, 0x00, 0x00, 0x03, /* message size */ 0x00, 0x01, 0x02, /* message body */ ]; assert_eq_transport_written_bytes!(t, expected_bytes); } #[test] fn must_write_message_greater_than_buffer_size_01() { let mem = TBufferChannel::with_capacity(0, 10); // IMPORTANT: DO **NOT** CHANGE THE WRITE_CAPACITY OR THE NUMBER OF BYTES TO BE WRITTEN! // these lengths were chosen to be just long enough // that doubling the capacity is a **better** choice than // simply resizing the buffer to b.len() let mut t = TFramedWriteTransport::with_capacity(2, mem); let b = [0x00, 0x01, 0x02]; // should have written 3 bytes assert_eq!(t.write(&b).unwrap(), 3); assert_eq_transport_num_written_bytes!(t, 0); assert!(t.flush().is_ok()); let expected_bytes = [ 0x00, 0x00, 0x00, 0x03, /* message size */ 0x00, 0x01, 0x02, /* message body */ ]; assert_eq_transport_written_bytes!(t, expected_bytes); } #[test] fn must_return_error_if_nothing_can_be_written_to_inner_transport_on_flush() { let mem = TBufferChannel::with_capacity(0, 0); let mut t = TFramedWriteTransport::with_capacity(1, mem); let b = vec![0; 10]; // should have written 10 bytes assert_eq!(t.write(&b).unwrap(), 10); // let's flush let r = t.flush(); // this time we'll error out because the flush can't write to the underlying channel assert!(r.is_err()); } #[test] fn must_write_successfully_after_flush() { // IMPORTANT: write capacity *MUST* be greater // than message sizes used in this test + 4-byte frame header let mem = TBufferChannel::with_capacity(0, 10); let mut t = TFramedWriteTransport::with_capacity(5, mem); // write and flush let first_message: [u8; 5] = [0x00, 0x01, 0x02, 0x03, 0x04]; assert_eq!(t.write(&first_message).unwrap(), 5); assert!(t.flush().is_ok()); let mut expected = Vec::new(); expected.write_all(&[0x00, 0x00, 0x00, 0x05]).unwrap(); // message size expected.extend_from_slice(&first_message); // check the flushed bytes assert_eq!(t.channel.write_bytes(), expected); // reset our underlying transport t.channel.empty_write_buffer(); let second_message: [u8; 3] = [0x05, 0x06, 0x07]; assert_eq!(t.write(&second_message).unwrap(), 3); assert!(t.flush().is_ok()); expected.clear(); expected.write_all(&[0x00, 0x00, 0x00, 0x03]).unwrap(); // message size expected.extend_from_slice(&second_message); // check the flushed bytes assert_eq!(t.channel.write_bytes(), expected); } } thrift-0.19.0/lib/rs/src/transport/mem.rs0000644000000000000000000003307014303740367020252 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::cmp; use std::io; use std::sync::{Arc, Mutex}; use super::{ReadHalf, TIoChannel, WriteHalf}; /// In-memory read and write channel with fixed-size read and write buffers. /// /// On a `write` bytes are written to the internal write buffer. Writes are no /// longer accepted once this buffer is full. Callers must `empty_write_buffer()` /// before subsequent writes are accepted. /// /// You can set readable bytes in the internal read buffer by filling it with /// `set_readable_bytes(...)`. Callers can then read until the buffer is /// depleted. No further reads are accepted until the internal read buffer is /// replenished again. #[derive(Clone, Debug)] pub struct TBufferChannel { read: Arc>, write: Arc>, } #[derive(Debug)] struct ReadData { buf: Box<[u8]>, pos: usize, idx: usize, cap: usize, } #[derive(Debug)] struct WriteData { buf: Box<[u8]>, pos: usize, cap: usize, } impl TBufferChannel { /// Constructs a new, empty `TBufferChannel` with the given /// read buffer capacity and write buffer capacity. pub fn with_capacity(read_capacity: usize, write_capacity: usize) -> TBufferChannel { TBufferChannel { read: Arc::new(Mutex::new(ReadData { buf: vec![0; read_capacity].into_boxed_slice(), idx: 0, pos: 0, cap: read_capacity, })), write: Arc::new(Mutex::new(WriteData { buf: vec![0; write_capacity].into_boxed_slice(), pos: 0, cap: write_capacity, })), } } /// Return a copy of the bytes held by the internal read buffer. /// Returns an empty vector if no readable bytes are present. pub fn read_bytes(&self) -> Vec { let rdata = self.read.as_ref().lock().unwrap(); let mut buf = vec![0u8; rdata.idx]; buf.copy_from_slice(&rdata.buf[..rdata.idx]); buf } // FIXME: do I really need this API call? // FIXME: should this simply reset to the last set of readable bytes? /// Reset the number of readable bytes to zero. /// /// Subsequent calls to `read` will return nothing. pub fn empty_read_buffer(&mut self) { let mut rdata = self.read.as_ref().lock().unwrap(); rdata.pos = 0; rdata.idx = 0; } /// Copy bytes from the source buffer `buf` into the internal read buffer, /// overwriting any existing bytes. Returns the number of bytes copied, /// which is `min(buf.len(), internal_read_buf.len())`. pub fn set_readable_bytes(&mut self, buf: &[u8]) -> usize { self.empty_read_buffer(); let mut rdata = self.read.as_ref().lock().unwrap(); let max_bytes = cmp::min(rdata.cap, buf.len()); rdata.buf[..max_bytes].clone_from_slice(&buf[..max_bytes]); rdata.idx = max_bytes; max_bytes } /// Return a copy of the bytes held by the internal write buffer. /// Returns an empty vector if no bytes were written. pub fn write_bytes(&self) -> Vec { let wdata = self.write.as_ref().lock().unwrap(); let mut buf = vec![0u8; wdata.pos]; buf.copy_from_slice(&wdata.buf[..wdata.pos]); buf } /// Resets the internal write buffer, making it seem like no bytes were /// written. Calling `write_buffer` after this returns an empty vector. pub fn empty_write_buffer(&mut self) { let mut wdata = self.write.as_ref().lock().unwrap(); wdata.pos = 0; } /// Overwrites the contents of the read buffer with the contents of the /// write buffer. The write buffer is emptied after this operation. pub fn copy_write_buffer_to_read_buffer(&mut self) { // FIXME: redo this entire method let buf = { let wdata = self.write.as_ref().lock().unwrap(); let b = &wdata.buf[..wdata.pos]; let mut b_ret = vec![0; b.len()]; b_ret.copy_from_slice(b); b_ret }; let bytes_copied = self.set_readable_bytes(&buf); assert_eq!(bytes_copied, buf.len()); self.empty_write_buffer(); } } impl TIoChannel for TBufferChannel { fn split(self) -> crate::Result<(ReadHalf, WriteHalf)> where Self: Sized, { Ok(( ReadHalf { handle: TBufferChannel { read: self.read.clone(), write: self.write.clone(), }, }, WriteHalf { handle: TBufferChannel { read: self.read.clone(), // NOTE: not cloning here, since this is the last statement // in this method and `write` can take ownership of `self.write` write: self.write, }, }, )) } } impl io::Read for TBufferChannel { fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut rdata = self.read.as_ref().lock().unwrap(); let nread = cmp::min(buf.len(), rdata.idx - rdata.pos); buf[..nread].clone_from_slice(&rdata.buf[rdata.pos..rdata.pos + nread]); rdata.pos += nread; Ok(nread) } } impl io::Write for TBufferChannel { fn write(&mut self, buf: &[u8]) -> io::Result { let mut wdata = self.write.as_ref().lock().unwrap(); let nwrite = cmp::min(buf.len(), wdata.cap - wdata.pos); let (start, end) = (wdata.pos, wdata.pos + nwrite); wdata.buf[start..end].clone_from_slice(&buf[..nwrite]); wdata.pos += nwrite; Ok(nwrite) } fn flush(&mut self) -> io::Result<()> { Ok(()) // nothing to do on flush } } #[cfg(test)] mod tests { use std::io::{Read, Write}; use super::TBufferChannel; #[test] fn must_empty_write_buffer() { let mut t = TBufferChannel::with_capacity(0, 1); let bytes_to_write: [u8; 1] = [0x01]; let result = t.write(&bytes_to_write); assert_eq!(result.unwrap(), 1); assert_eq!(&t.write_bytes(), &bytes_to_write); t.empty_write_buffer(); assert_eq!(t.write_bytes().len(), 0); } #[test] fn must_accept_writes_after_buffer_emptied() { let mut t = TBufferChannel::with_capacity(0, 2); let bytes_to_write: [u8; 2] = [0x01, 0x02]; // first write (all bytes written) let result = t.write(&bytes_to_write); assert_eq!(result.unwrap(), 2); assert_eq!(&t.write_bytes(), &bytes_to_write); // try write again (nothing should be written) let result = t.write(&bytes_to_write); assert_eq!(result.unwrap(), 0); assert_eq!(&t.write_bytes(), &bytes_to_write); // still the same as before // now reset the buffer t.empty_write_buffer(); assert_eq!(t.write_bytes().len(), 0); // now try write again - the write should succeed let result = t.write(&bytes_to_write); assert_eq!(result.unwrap(), 2); assert_eq!(&t.write_bytes(), &bytes_to_write); } #[test] fn must_accept_multiple_writes_until_buffer_is_full() { let mut t = TBufferChannel::with_capacity(0, 10); // first write (all bytes written) let bytes_to_write_0: [u8; 2] = [0x01, 0x41]; let write_0_result = t.write(&bytes_to_write_0); assert_eq!(write_0_result.unwrap(), 2); assert_eq!(t.write_bytes(), &bytes_to_write_0); // second write (all bytes written, starting at index 2) let bytes_to_write_1: [u8; 7] = [0x24, 0x41, 0x32, 0x33, 0x11, 0x98, 0xAF]; let write_1_result = t.write(&bytes_to_write_1); assert_eq!(write_1_result.unwrap(), 7); assert_eq!(&t.write_bytes()[2..], &bytes_to_write_1); // third write (only 1 byte written - that's all we have space for) let bytes_to_write_2: [u8; 3] = [0xBF, 0xDA, 0x98]; let write_2_result = t.write(&bytes_to_write_2); assert_eq!(write_2_result.unwrap(), 1); assert_eq!(&t.write_bytes()[9..], &bytes_to_write_2[0..1]); // how does this syntax work?! // fourth write (no writes are accepted) let bytes_to_write_3: [u8; 3] = [0xBF, 0xAA, 0xFD]; let write_3_result = t.write(&bytes_to_write_3); assert_eq!(write_3_result.unwrap(), 0); // check the full write buffer let mut expected: Vec = Vec::with_capacity(10); expected.extend_from_slice(&bytes_to_write_0); expected.extend_from_slice(&bytes_to_write_1); expected.extend_from_slice(&bytes_to_write_2[0..1]); assert_eq!(t.write_bytes(), &expected[..]); } #[test] fn must_empty_read_buffer() { let mut t = TBufferChannel::with_capacity(1, 0); let bytes_to_read: [u8; 1] = [0x01]; let result = t.set_readable_bytes(&bytes_to_read); assert_eq!(result, 1); assert_eq!(t.read_bytes(), &bytes_to_read); t.empty_read_buffer(); assert_eq!(t.read_bytes().len(), 0); } #[test] fn must_allow_readable_bytes_to_be_set_after_read_buffer_emptied() { let mut t = TBufferChannel::with_capacity(1, 0); let bytes_to_read_0: [u8; 1] = [0x01]; let result = t.set_readable_bytes(&bytes_to_read_0); assert_eq!(result, 1); assert_eq!(t.read_bytes(), &bytes_to_read_0); t.empty_read_buffer(); assert_eq!(t.read_bytes().len(), 0); let bytes_to_read_1: [u8; 1] = [0x02]; let result = t.set_readable_bytes(&bytes_to_read_1); assert_eq!(result, 1); assert_eq!(t.read_bytes(), &bytes_to_read_1); } #[test] fn must_accept_multiple_reads_until_all_bytes_read() { let mut t = TBufferChannel::with_capacity(10, 0); let readable_bytes: [u8; 10] = [0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0x00, 0x1A, 0x2B, 0x3C, 0x4D]; // check that we're able to set the bytes to be read let result = t.set_readable_bytes(&readable_bytes); assert_eq!(result, 10); assert_eq!(t.read_bytes(), &readable_bytes); // first read let mut read_buf_0 = vec![0; 5]; let read_result = t.read(&mut read_buf_0); assert_eq!(read_result.unwrap(), 5); assert_eq!(read_buf_0.as_slice(), &(readable_bytes[0..5])); // second read let mut read_buf_1 = vec![0; 4]; let read_result = t.read(&mut read_buf_1); assert_eq!(read_result.unwrap(), 4); assert_eq!(read_buf_1.as_slice(), &(readable_bytes[5..9])); // third read (only 1 byte remains to be read) let mut read_buf_2 = vec![0; 3]; let read_result = t.read(&mut read_buf_2); assert_eq!(read_result.unwrap(), 1); read_buf_2.truncate(1); // FIXME: does the caller have to do this? assert_eq!(read_buf_2.as_slice(), &(readable_bytes[9..])); // fourth read (nothing should be readable) let mut read_buf_3 = vec![0; 10]; let read_result = t.read(&mut read_buf_3); assert_eq!(read_result.unwrap(), 0); read_buf_3.truncate(0); // check that all the bytes we received match the original (again!) let mut bytes_read = Vec::with_capacity(10); bytes_read.extend_from_slice(&read_buf_0); bytes_read.extend_from_slice(&read_buf_1); bytes_read.extend_from_slice(&read_buf_2); bytes_read.extend_from_slice(&read_buf_3); assert_eq!(&bytes_read, &readable_bytes); } #[test] fn must_allow_reads_to_succeed_after_read_buffer_replenished() { let mut t = TBufferChannel::with_capacity(3, 0); let readable_bytes_0: [u8; 3] = [0x02, 0xAB, 0x33]; // check that we're able to set the bytes to be read let result = t.set_readable_bytes(&readable_bytes_0); assert_eq!(result, 3); assert_eq!(t.read_bytes(), &readable_bytes_0); let mut read_buf = vec![0; 4]; // drain the read buffer let read_result = t.read(&mut read_buf); assert_eq!(read_result.unwrap(), 3); assert_eq!(t.read_bytes(), &read_buf[0..3]); // check that a subsequent read fails let read_result = t.read(&mut read_buf); assert_eq!(read_result.unwrap(), 0); // we don't modify the read buffer on failure let mut expected_bytes = Vec::with_capacity(4); expected_bytes.extend_from_slice(&readable_bytes_0); expected_bytes.push(0x00); assert_eq!(&read_buf, &expected_bytes); // replenish the read buffer again let readable_bytes_1: [u8; 2] = [0x91, 0xAA]; // check that we're able to set the bytes to be read let result = t.set_readable_bytes(&readable_bytes_1); assert_eq!(result, 2); assert_eq!(t.read_bytes(), &readable_bytes_1); // read again let read_result = t.read(&mut read_buf); assert_eq!(read_result.unwrap(), 2); assert_eq!(t.read_bytes(), &read_buf[0..2]); } } thrift-0.19.0/lib/rs/src/transport/socket.rs0000644000000000000000000001237114303740367020765 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use std::convert::From; use std::io; use std::io::{ErrorKind, Read, Write}; use std::net::{Shutdown, TcpStream, ToSocketAddrs}; #[cfg(unix)] use std::os::unix::net::UnixStream; use super::{ReadHalf, TIoChannel, WriteHalf}; use crate::{new_transport_error, TransportErrorKind}; /// Bidirectional TCP/IP channel. /// /// # Examples /// /// Create a `TTcpChannel`. /// /// ```no_run /// use std::io::{Read, Write}; /// use thrift::transport::TTcpChannel; /// /// let mut c = TTcpChannel::new(); /// c.open("localhost:9090").unwrap(); /// /// let mut buf = vec![0u8; 4]; /// c.read(&mut buf).unwrap(); /// c.write(&vec![0, 1, 2]).unwrap(); /// ``` /// /// Create a `TTcpChannel` by wrapping an existing `TcpStream`. /// /// ```no_run /// use std::io::{Read, Write}; /// use std::net::TcpStream; /// use thrift::transport::TTcpChannel; /// /// let stream = TcpStream::connect("127.0.0.1:9189").unwrap(); /// /// // no need to call c.open() since we've already connected above /// let mut c = TTcpChannel::with_stream(stream); /// /// let mut buf = vec![0u8; 4]; /// c.read(&mut buf).unwrap(); /// c.write(&vec![0, 1, 2]).unwrap(); /// ``` #[derive(Debug, Default)] pub struct TTcpChannel { stream: Option, } impl TTcpChannel { /// Create an uninitialized `TTcpChannel`. /// /// The returned instance must be opened using `TTcpChannel::open(...)` /// before it can be used. pub fn new() -> TTcpChannel { TTcpChannel { stream: None } } /// Create a `TTcpChannel` that wraps an existing `TcpStream`. /// /// The passed-in stream is assumed to have been opened before being wrapped /// by the created `TTcpChannel` instance. pub fn with_stream(stream: TcpStream) -> TTcpChannel { TTcpChannel { stream: Some(stream), } } /// Connect to `remote_address`, which should implement `ToSocketAddrs` trait. pub fn open(&mut self, remote_address: A) -> crate::Result<()> { if self.stream.is_some() { Err(new_transport_error( TransportErrorKind::AlreadyOpen, "tcp connection previously opened", )) } else { match TcpStream::connect(&remote_address) { Ok(s) => { self.stream = Some(s); Ok(()) } Err(e) => Err(From::from(e)), } } } /// Shut down this channel. /// /// Both send and receive halves are closed, and this instance can no /// longer be used to communicate with another endpoint. pub fn close(&mut self) -> crate::Result<()> { self.if_set(|s| s.shutdown(Shutdown::Both)) .map_err(From::from) } fn if_set(&mut self, mut stream_operation: F) -> io::Result where F: FnMut(&mut TcpStream) -> io::Result, { if let Some(ref mut s) = self.stream { stream_operation(s) } else { Err(io::Error::new( ErrorKind::NotConnected, "tcp endpoint not connected", )) } } } impl TIoChannel for TTcpChannel { fn split(self) -> crate::Result<(ReadHalf, WriteHalf)> where Self: Sized, { let mut s = self; s.stream .as_mut() .and_then(|s| s.try_clone().ok()) .map(|cloned| { let read_half = ReadHalf::new(TTcpChannel { stream: s.stream.take(), }); let write_half = WriteHalf::new(TTcpChannel { stream: Some(cloned), }); (read_half, write_half) }) .ok_or_else(|| { new_transport_error( TransportErrorKind::Unknown, "cannot clone underlying tcp stream", ) }) } } impl Read for TTcpChannel { fn read(&mut self, b: &mut [u8]) -> io::Result { self.if_set(|s| s.read(b)) } } impl Write for TTcpChannel { fn write(&mut self, b: &[u8]) -> io::Result { self.if_set(|s| s.write(b)) } fn flush(&mut self) -> io::Result<()> { self.if_set(|s| s.flush()) } } #[cfg(unix)] impl TIoChannel for UnixStream { fn split(self) -> crate::Result<(ReadHalf, WriteHalf)> where Self: Sized, { let socket_rx = self.try_clone().unwrap(); Ok((ReadHalf::new(self), WriteHalf::new(socket_rx))) } } thrift-0.19.0/lib/rs/README.md0000644000000000000000000001472714370300523015560 0ustar00rootroot00000000000000# Rust Thrift library ## Overview This crate implements the components required to build a working Thrift server and client. It is divided into the following modules: 1. errors 2. protocol 3. transport 4. server 5. autogen The modules are layered as shown. The `generated` layer is code generated by the Thrift compiler's Rust plugin. It uses the components defined in this crate to serialize and deserialize types and implement RPC. Users interact with these types and services by writing their own code on top. ```text +-----------+ | app dev | +-----------+ | generated | <-> errors/results +-----------+ | protocol | +-----------+ | transport | +-----------+ ``` ## Using this crate Add `thrift = "x.y.z"` to your `Cargo.toml`, where `x.y.z` is the version of the Thrift compiler you're using. ## API Documentation Full [Rustdoc](https://docs.rs/thrift/) ## Compatibility The Rust library and auto-generated code targets Rust versions 1.28+. It does not currently use any Rust 2021 features. ### Breaking Changes Breaking changes are minimized. When they are made they will be outlined below with transition guidelines. ##### Thrift 0.15.0 * **[THRIFT-5360]** - No longer define OR generate `description()` methods for `Error` types. `Error.description()` was soft-deprecated in 1.27, and deprecated as of 1.41. Library error types also do not implement `Error.description()`. Also, as a result of this change the generated Rust representation of an Error no longer implements the `Error.description()` method. Instead, it generates a `Display` impl with the same information. For example: ```thrift exception Xception { 1: i32 errorCode, 2: string message } ``` used to generate: ```rust use std::error::Error; use std::fmt; use std::fmt::{Display, Formatter}; // auto-generated by the Thrift compiler #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct Xception { pub error_code: Option, pub message: Option, } // auto-generated by the Thrift compiler impl Error for Xception { fn description(&self) -> &str { "remote service threw Xception" } } // auto-generated by the Thrift compiler impl From for thrift::Error { fn from(e: Xception) -> Self { thrift::Error::User(Box::new(e)) } } // auto-generated by the Thrift compiler impl Display for Xception { fn fmt(&self, f: &mut Formatter) -> fmt::Result { self.description().format(f) } } ``` It *now* generates: ```rust use std::error::Error; use std::fmt; use std::fmt::{Display, Formatter}; // auto-generated by the Thrift compiler #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct Xception { pub error_code: Option, pub message: Option, } // auto-generated by the Thrift compiler impl Error for Xception { } // auto-generated by the Thrift compiler impl From for thrift::Error { fn from(e: Xception) -> Self { thrift::Error::User(Box::new(e)) } } // auto-generated by the Thrift compiler impl Display for Xception { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "remote service threw Xception") } } ``` * **[THRIFT-5314]** - Generate enums implementations that are forward compatible (i.e. don't error on unknown values) As a result of this change the Rust representation of an enum changes from a standard Rust enum into a newtype struct with associated constants. For example: ```thrift // THRIFT enum Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE, } ``` used to generate: ```rust // OLD AUTO-GENERATED RUST pub enum Operation { Add, Subtract, Multiply, Divide, } ``` It *now* generates: ```rust // NEW AUTO-GENERATED RUST pub struct Operation(pub i32); impl Operation { pub const ADD: Operation = Operation(0); pub const SUBTRACT: Operation = Operation(1); pub const MULTIPLY: Operation = Operation(2); pub const DIVIDE: Operation = Operation(3); } ``` ##### Thrift 0.14.0 * **[THRIFT-5158]** - Rust library and generator now support Rust 2021 only. Required rust 1.61.0 or higher The Rust `thrift` library was updated to Rust 2021 via `cargo fix --edition`. All test code in the repo was updated as well. The code generator was also updated to support Rust 2021 only. ##### Thrift 0.13.0 * **[THRIFT-4536]** - Use TryFrom from std, required rust 1.34.0 or higher Previously TryFrom was from try_from crate, it is now from the std library, but this functionality is only available in rust 1.34.0. Additionally, ordered-float is now re-exported under the thrift module to reduce possible dependency mismatches. ##### Thrift 0.12.0 * **[THRIFT-4529]** - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions Previously, enum variants were uppercased in the auto-generated code. For example, the following thrift enum: ```thrift // THRIFT enum Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE, } ``` used to generate: ```rust // OLD AUTO-GENERATED RUST pub enum Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE, } ``` It *now* generates: ```rust // NEW AUTO-GENERATED RUST pub enum Operation { Add, Subtract, Multiply, Divide, } ``` You will have to change all enum variants in your code to use camel-cased names. This should be a search and replace. ## Contributing Bug reports and PRs are always welcome! Please see the [Thrift website](https://thrift.apache.org/) for more details. Thrift Rust support requires code in several directories: * `compiler/cpp/src/thrift/generate/t_rs_generator.cc`: binding code generator * `lib/rs`: runtime library * `lib/rs/test`: supplemental tests * `tutorial/rs`: tutorial client and server * `test/rs`: cross-language test client and server All library code, test code and auto-generated code compiles and passes clippy without warnings. All new code must do the same! When making changes ensure that: * `rustc` does does output any warnings * `clippy` with default settings does not output any warnings (includes auto-generated code) * `cargo test` is successful * `make precross` and `make check` are successful * `tutorial/bin/tutorial_client` and `tutorial/bin/tutorial_server` communicate thrift-0.19.0/lib/rs/test/0000755000000000000000000000000014472652670015265 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test/thrifts/0000755000000000000000000000000014472652670016750 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test/thrifts/Base_Two.thrift0000644000000000000000000000247314303740367021675 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ const i32 WaterWeight = 200 enum brothType { Miso, shouyu, } struct Ramen { 1: optional string ramenType 2: required i32 noodleCount 3: brothType broth } struct Napkin { // empty } service NapkinService { Napkin napkin() } service RamenService extends NapkinService { Ramen ramen(1: i32 requestedNoodleCount) } /* const struct CookedRamen = { "bar": 10 } */ thrift-0.19.0/lib/rs/test/thrifts/Midlayer.thrift0000644000000000000000000000362014303740367021733 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ include "Base_One.thrift" include "Base_Two.thrift" const i32 WaterBoilingPoint = Base_One.BoilingPoint const map TemperatureNames = { "freezing": 0, "boiling": 100 } const map, map, string>> MyConstNestedMap = { [0, 1, 2, 3]: { ["foo"]: "bar" }, [20]: { ["nut", "ton"] : "bar" }, [30, 40]: { ["bouncy", "tinkly"]: "castle" } } const list> MyConstNestedList = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ] const set> MyConstNestedSet = [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ] enum Pie { PUMPKIN, apple, // intentionally poorly cased STRAWBERRY_RHUBARB, Key_Lime, // intentionally poorly cased coconut_Cream, // intentionally poorly cased mississippi_mud, // intentionally poorly cased } struct Meal { 1: Base_One.Noodle noodle 2: Base_Two.Ramen ramen } union Dessert { 1: string port 2: string iceWine } service MealService extends Base_Two.RamenService { Meal meal() } thrift-0.19.0/lib/rs/test/thrifts/Base_One.thrift0000644000000000000000000000416714303740367021647 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ typedef i64 Temperature typedef i8 Size typedef string Location const i32 BoilingPoint = 100 const list Temperatures = [10, 11, 22, 33] // IMPORTANT: temps should end with ".0" because this tests // that we don't have a problem with const float list generation const list CommonTemperatures = [300.0, 450.0] const double MealsPerDay = 2.5; const string DefaultRecipeName = "Soup-rise of the Day" const binary DefaultRecipeBinary = "Soup-rise of the 01010101" struct Noodle { 1: string flourType 2: Temperature cookTemp } struct Spaghetti { 1: optional list noodles } const Noodle SpeltNoodle = { "flourType": "spelt", "cookTemp": 110 } struct MeasuringSpoon { 1: Size size } struct MeasuringCup { 1: double millis } union MeasuringAids { 1: MeasuringSpoon spoon 2: MeasuringCup cup } struct CookingTemperatures { 1: set commonTemperatures 2: list usedTemperatures 3: map fahrenheitToCentigradeConversions } struct Recipe { 1: string recipeName 2: string cuisine 3: i8 page } union CookingTools { 1: set measuringSpoons 2: map measuringCups, 3: list recipes } thrift-0.19.0/lib/rs/test/thrifts/Ultimate.thrift0000644000000000000000000000355014303740367021753 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ include "Midlayer.thrift" enum Drink { WATER, WHISKEY, WINE, scotch, // intentionally poorly cased LATE_HARVEST_WINE, India_Pale_Ale, // intentionally poorly cased apple_cider, // intentially poorly cased belgian_Ale, // intentionally poorly cased Canadian_whisky, // intentionally poorly cased } const map RankedPies = { 1: Midlayer.Pie.PUMPKIN, 2: Midlayer.Pie.STRAWBERRY_RHUBARB, 3: Midlayer.Pie.apple, 4: Midlayer.Pie.mississippi_mud, 5: Midlayer.Pie.coconut_Cream, 6: Midlayer.Pie.Key_Lime, } struct FullMeal { 1: required Midlayer.Meal meal 2: required Midlayer.Dessert dessert } struct FullMealAndDrinks { 1: required FullMeal fullMeal 2: optional Drink drink } service FullMealService extends Midlayer.MealService { FullMeal fullMeal() } service FullMealAndDrinksService extends FullMealService { FullMealAndDrinks fullMealAndDrinks() Midlayer.Pie bestPie() } thrift-0.19.0/lib/rs/test/Makefile.am0000644000000000000000000000405014303740367017312 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: thrifts/Base_One.thrift thrifts/Base_Two.thrift thrifts/Midlayer.thrift thrifts/Ultimate.thrift $(top_builddir)/test/Recursive.thrift $(THRIFT) $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Base_One.thrift $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Base_Two.thrift $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Midlayer.thrift $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Ultimate.thrift $(THRIFT) -out src --gen rs $(top_builddir)/test/Recursive.thrift $(THRIFT) -out src --gen rs $(top_builddir)/test/Identifiers.thrift #THRIFT-4953 check: stubs $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) build $(CARGO) test [ -d bin ] || mkdir bin cp target/debug/kitchen_sink_server bin/kitchen_sink_server cp target/debug/kitchen_sink_client bin/kitchen_sink_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/base_one.rs -$(RM) src/base_two.rs -$(RM) src/midlayer.rs -$(RM) src/ultimate.rs -$(RM) src/recursive.rs -$(RM) src/identifiers.rs -$(RM) -r bin EXTRA_DIST = \ Cargo.toml \ thrifts/Base_One.thrift \ thrifts/Base_Two.thrift \ thrifts/Midlayer.thrift \ thrifts/Ultimate.thrift \ src/lib.rs \ src/bin/kitchen_sink_server.rs \ src/bin/kitchen_sink_client.rs thrift-0.19.0/lib/rs/test/Cargo.toml0000644000000000000000000000041314370300523017173 0ustar00rootroot00000000000000[package] name = "kitchen-sink" version = "0.1.0" edition = "2021" license = "Apache-2.0" authors = ["Apache Thrift Developers "] publish = false [dependencies] clap = "~2.33" bitflags = "=1.2" log = "0.4" [dependencies.thrift] path = "../" thrift-0.19.0/lib/rs/test/src/0000755000000000000000000000000014472652670016054 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test/src/bin/0000755000000000000000000000000014472652670016624 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test/src/bin/kitchen_sink_server.rs0000644000000000000000000002450014370300523023212 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use clap::{clap_app, value_t}; use log::*; use thrift::protocol::{ TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory, TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory, }; use thrift::server::TServer; use thrift::transport::{ TFramedReadTransportFactory, TFramedWriteTransportFactory, TReadTransportFactory, TWriteTransportFactory, }; use crate::Socket::{ListenAddress, UnixDomainSocket}; use kitchen_sink::base_one::Noodle; use kitchen_sink::base_two::{ BrothType, Napkin, NapkinServiceSyncHandler, Ramen, RamenServiceSyncHandler, }; use kitchen_sink::midlayer::{ Dessert, Meal, MealServiceSyncHandler, MealServiceSyncProcessor, Pie, }; use kitchen_sink::recursive; use kitchen_sink::ultimate::FullMealAndDrinksServiceSyncHandler; use kitchen_sink::ultimate::{ Drink, FullMeal, FullMealAndDrinks, FullMealAndDrinksServiceSyncProcessor, FullMealServiceSyncHandler, }; enum Socket { ListenAddress(String), UnixDomainSocket(String), } fn main() { match run() { Ok(()) => println!("kitchen sink server completed successfully"), Err(e) => { println!("kitchen sink server failed with error {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { let matches = clap_app!(rust_kitchen_sink_server => (version: "0.1.0") (author: "Apache Thrift Developers ") (about: "Thrift Rust kitchen sink test server") (@arg port: --port +takes_value "Port on which the Thrift test server listens") (@arg domain_socket: --("domain-socket") + takes_value "Unix Domain Socket on which the Thrift test server listens") (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\")") (@arg service: --service +takes_value "Service type to contact (\"part\", \"full\", \"recursive\")") ) .get_matches(); let port = value_t!(matches, "port", u16).unwrap_or(9090); let domain_socket = matches.value_of("domain_socket"); let protocol = matches.value_of("protocol").unwrap_or("compact"); let service = matches.value_of("service").unwrap_or("part"); let listen_address = format!("127.0.0.1:{}", port); let socket = match domain_socket { None => { info!("Server is binding to {}", listen_address); Socket::ListenAddress(listen_address) } Some(domain_socket) => { info!("Server is binding to {} (UDS)", domain_socket); Socket::UnixDomainSocket(domain_socket.to_string()) } }; let r_transport_factory = TFramedReadTransportFactory::new(); let w_transport_factory = TFramedWriteTransportFactory::new(); let (i_protocol_factory, o_protocol_factory): ( Box, Box, ) = match &*protocol { "binary" => ( Box::new(TBinaryInputProtocolFactory::new()), Box::new(TBinaryOutputProtocolFactory::new()), ), "compact" => ( Box::new(TCompactInputProtocolFactory::new()), Box::new(TCompactOutputProtocolFactory::new()), ), unknown => { return Err(format!("unsupported transport type {}", unknown).into()); } }; // FIXME: should processor be boxed as well? // // [sigh] I hate Rust generics implementation // // I would have preferred to build a server here, return it, and then do // the common listen-and-handle stuff, but since the server doesn't have a // common type (because each match arm instantiates a server with a // different processor) this isn't possible. // // Since what I'm doing is uncommon I'm just going to duplicate the code match &*service { "part" => run_meal_server( socket, r_transport_factory, i_protocol_factory, w_transport_factory, o_protocol_factory, ), "full" => run_full_meal_server( socket, r_transport_factory, i_protocol_factory, w_transport_factory, o_protocol_factory, ), "recursive" => run_recursive_server( socket, r_transport_factory, i_protocol_factory, w_transport_factory, o_protocol_factory, ), unknown => Err(format!("unsupported service type {}", unknown).into()), } } fn run_meal_server( socket: Socket, r_transport_factory: RTF, i_protocol_factory: IPF, w_transport_factory: WTF, o_protocol_factory: OPF, ) -> thrift::Result<()> where RTF: TReadTransportFactory + 'static, IPF: TInputProtocolFactory + 'static, WTF: TWriteTransportFactory + 'static, OPF: TOutputProtocolFactory + 'static, { let processor = MealServiceSyncProcessor::new(PartHandler {}); let mut server = TServer::new( r_transport_factory, i_protocol_factory, w_transport_factory, o_protocol_factory, processor, 1, ); match socket { ListenAddress(listen_address) => server.listen(listen_address), UnixDomainSocket(s) => server.listen_uds(s), } } fn run_full_meal_server( socket: Socket, r_transport_factory: RTF, i_protocol_factory: IPF, w_transport_factory: WTF, o_protocol_factory: OPF, ) -> thrift::Result<()> where RTF: TReadTransportFactory + 'static, IPF: TInputProtocolFactory + 'static, WTF: TWriteTransportFactory + 'static, OPF: TOutputProtocolFactory + 'static, { let processor = FullMealAndDrinksServiceSyncProcessor::new(FullHandler {}); let mut server = TServer::new( r_transport_factory, i_protocol_factory, w_transport_factory, o_protocol_factory, processor, 1, ); match socket { ListenAddress(listen_address) => server.listen(listen_address), UnixDomainSocket(s) => server.listen_uds(s), } } struct PartHandler; impl MealServiceSyncHandler for PartHandler { fn handle_meal(&self) -> thrift::Result { println!("part: handling meal call"); Ok(meal()) } } impl RamenServiceSyncHandler for PartHandler { fn handle_ramen(&self, _: i32) -> thrift::Result { println!("part: handling ramen call"); Ok(ramen()) } } impl NapkinServiceSyncHandler for PartHandler { fn handle_napkin(&self) -> thrift::Result { println!("part: handling napkin call"); Ok(napkin()) } } // full service // struct FullHandler; impl FullMealAndDrinksServiceSyncHandler for FullHandler { fn handle_full_meal_and_drinks(&self) -> thrift::Result { println!("full_meal_and_drinks: handling full meal and drinks call"); Ok(FullMealAndDrinks::new(full_meal(), Drink::CANADIAN_WHISKY)) } fn handle_best_pie(&self) -> thrift::Result { println!("full_meal_and_drinks: handling pie call"); Ok(Pie::MISSISSIPPI_MUD) // I prefer Pie::Pumpkin, but I have to check that casing works } } impl FullMealServiceSyncHandler for FullHandler { fn handle_full_meal(&self) -> thrift::Result { println!("full: handling full meal call"); Ok(full_meal()) } } impl MealServiceSyncHandler for FullHandler { fn handle_meal(&self) -> thrift::Result { println!("full: handling meal call"); Ok(meal()) } } impl RamenServiceSyncHandler for FullHandler { fn handle_ramen(&self, _: i32) -> thrift::Result { println!("full: handling ramen call"); Ok(ramen()) } } impl NapkinServiceSyncHandler for FullHandler { fn handle_napkin(&self) -> thrift::Result { println!("full: handling napkin call"); Ok(napkin()) } } fn full_meal() -> FullMeal { FullMeal::new(meal(), Dessert::Port("Graham's Tawny".to_owned())) } fn meal() -> Meal { Meal::new(noodle(), ramen()) } fn noodle() -> Noodle { Noodle::new("spelt".to_owned(), 100) } fn ramen() -> Ramen { Ramen::new("Mr Ramen".to_owned(), 72, BrothType::MISO) } fn napkin() -> Napkin { Napkin {} } fn run_recursive_server( socket: Socket, r_transport_factory: RTF, i_protocol_factory: IPF, w_transport_factory: WTF, o_protocol_factory: OPF, ) -> thrift::Result<()> where RTF: TReadTransportFactory + 'static, IPF: TInputProtocolFactory + 'static, WTF: TWriteTransportFactory + 'static, OPF: TOutputProtocolFactory + 'static, { let processor = recursive::TestServiceSyncProcessor::new(RecursiveTestServerHandler {}); let mut server = TServer::new( r_transport_factory, i_protocol_factory, w_transport_factory, o_protocol_factory, processor, 1, ); match socket { ListenAddress(listen_address) => server.listen(listen_address), UnixDomainSocket(s) => server.listen_uds(s), } } struct RecursiveTestServerHandler; impl recursive::TestServiceSyncHandler for RecursiveTestServerHandler { fn handle_echo_tree(&self, tree: recursive::RecTree) -> thrift::Result { println!("{:?}", tree); Ok(tree) } fn handle_echo_list(&self, lst: recursive::RecList) -> thrift::Result { println!("{:?}", lst); Ok(lst) } fn handle_echo_co_rec(&self, item: recursive::CoRec) -> thrift::Result { println!("{:?}", item); Ok(item) } } thrift-0.19.0/lib/rs/test/src/bin/kitchen_sink_client.rs0000644000000000000000000002223014370300523023160 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. use clap::{clap_app, value_t}; use log::*; use std::convert::Into; use std::net::TcpStream; use std::net::ToSocketAddrs; #[cfg(unix)] use std::os::unix::net::UnixStream; #[cfg(unix)] use std::path::Path; use kitchen_sink::base_two::{TNapkinServiceSyncClient, TRamenServiceSyncClient}; use kitchen_sink::midlayer::{MealServiceSyncClient, TMealServiceSyncClient}; use kitchen_sink::recursive; use kitchen_sink::recursive::{CoRec, CoRec2, RecList, RecTree, TTestServiceSyncClient}; use kitchen_sink::ultimate::{FullMealServiceSyncClient, TFullMealServiceSyncClient}; use thrift::protocol::{ TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol, TInputProtocol, TOutputProtocol, }; use thrift::transport::{TFramedReadTransport, TFramedWriteTransport, TIoChannel, TTcpChannel}; type IoProtocol = (Box, Box); fn main() { match run() { Ok(()) => println!("kitchen sink client completed successfully"), Err(e) => { println!("kitchen sink client failed with error {:?}", e); std::process::exit(1); } } } fn run() -> thrift::Result<()> { let matches = clap_app!(rust_kitchen_sink_client => (version: "0.1.0") (author: "Apache Thrift Developers ") (about: "Thrift Rust kitchen sink client") (@arg host: --host +takes_value "Host on which the Thrift test server is located") (@arg port: --port +takes_value "Port on which the Thrift test server is listening") (@arg domain_socket: --("domain-socket") + takes_value "Unix Domain Socket on which the Thrift test server is listening") (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\")") (@arg service: --service +takes_value "Service type to contact (\"part\", \"full\", \"recursive\")") ) .get_matches(); let host = matches.value_of("host").unwrap_or("127.0.0.1"); let port = value_t!(matches, "port", u16).unwrap_or(9090); let domain_socket = matches.value_of("domain_socket"); let protocol = matches.value_of("protocol").unwrap_or("compact"); let service = matches.value_of("service").unwrap_or("part"); let (i_prot, o_prot) = match domain_socket { None => { let listen_address = format!("{}:{}", host, port); info!("Client binds to {} with {}", listen_address, protocol); bind(listen_address, protocol)? } Some(domain_socket) => { info!("Client binds to {} (UDS) with {}", domain_socket, protocol); bind_uds(domain_socket, protocol)? } }; run_client(service, i_prot, o_prot) } fn bind(listen_address: A, protocol: &str) -> Result { let stream = TcpStream::connect(listen_address)?; let channel = TTcpChannel::with_stream(stream); let (i_prot, o_prot) = build(channel, protocol)?; Ok((i_prot, o_prot)) } #[cfg(unix)] fn bind_uds>(domain_socket: P, protocol: &str) -> Result { let stream = UnixStream::connect(domain_socket)?; let (i_prot, o_prot) = build(stream, protocol)?; Ok((i_prot, o_prot)) } fn build( channel: C, protocol: &str, ) -> thrift::Result<(Box, Box)> { let (i_chan, o_chan) = channel.split()?; let (i_tran, o_tran) = ( TFramedReadTransport::new(i_chan), TFramedWriteTransport::new(o_chan), ); let (i_prot, o_prot): (Box, Box) = match protocol { "binary" => ( Box::new(TBinaryInputProtocol::new(i_tran, true)), Box::new(TBinaryOutputProtocol::new(o_tran, true)), ), "compact" => ( Box::new(TCompactInputProtocol::new(i_tran)), Box::new(TCompactOutputProtocol::new(o_tran)), ), unmatched => return Err(format!("unsupported protocol {}", unmatched).into()), }; Ok((i_prot, o_prot)) } fn run_client( service: &str, i_prot: Box, o_prot: Box, ) -> thrift::Result<()> { match service { "full" => exec_full_meal_client(i_prot, o_prot), "part" => exec_meal_client(i_prot, o_prot), "recursive" => exec_recursive_client(i_prot, o_prot), _ => Err(thrift::Error::from(format!( "unknown service type {}", service ))), } } fn exec_meal_client( i_prot: Box, o_prot: Box, ) -> thrift::Result<()> { let mut client = MealServiceSyncClient::new(i_prot, o_prot); // client.full_meal(); // <-- IMPORTANT: if you uncomment this, compilation *should* fail // this is because the MealService struct does not contain the appropriate service marker // only the following three calls work execute_call("part", "ramen", || client.ramen(50)).map(|_| ())?; execute_call("part", "meal", || client.meal()).map(|_| ())?; execute_call("part", "napkin", || client.napkin()).map(|_| ())?; Ok(()) } fn exec_full_meal_client( i_prot: Box, o_prot: Box, ) -> thrift::Result<()> { let mut client = FullMealServiceSyncClient::new(i_prot, o_prot); execute_call("full", "ramen", || client.ramen(100)).map(|_| ())?; execute_call("full", "meal", || client.meal()).map(|_| ())?; execute_call("full", "napkin", || client.napkin()).map(|_| ())?; execute_call("full", "full meal", || client.full_meal()).map(|_| ())?; Ok(()) } fn exec_recursive_client( i_prot: Box, o_prot: Box, ) -> thrift::Result<()> { let mut client = recursive::TestServiceSyncClient::new(i_prot, o_prot); let tree = RecTree { children: Some(vec![Box::new(RecTree { children: Some(vec![ Box::new(RecTree { children: None, item: Some(3), }), Box::new(RecTree { children: None, item: Some(4), }), ]), item: Some(2), })]), item: Some(1), }; let expected_tree = RecTree { children: Some(vec![Box::new(RecTree { children: Some(vec![ Box::new(RecTree { children: Some(Vec::new()), // remote returns an empty list item: Some(3), }), Box::new(RecTree { children: Some(Vec::new()), // remote returns an empty list item: Some(4), }), ]), item: Some(2), })]), item: Some(1), }; let returned_tree = execute_call("recursive", "echo_tree", || client.echo_tree(tree.clone()))?; if returned_tree != expected_tree { return Err(format!( "mismatched recursive tree {:?} {:?}", expected_tree, returned_tree ) .into()); } let list = RecList { nextitem: Some(Box::new(RecList { nextitem: Some(Box::new(RecList { nextitem: None, item: Some(3), })), item: Some(2), })), item: Some(1), }; let returned_list = execute_call("recursive", "echo_list", || client.echo_list(list.clone()))?; if returned_list != list { return Err(format!("mismatched recursive list {:?} {:?}", list, returned_list).into()); } let co_rec = CoRec { other: Some(Box::new(CoRec2 { other: Some(CoRec { other: Some(Box::new(CoRec2 { other: None })), }), })), }; let returned_co_rec = execute_call("recursive", "echo_co_rec", || { client.echo_co_rec(co_rec.clone()) })?; if returned_co_rec != co_rec { return Err(format!("mismatched co_rec {:?} {:?}", co_rec, returned_co_rec).into()); } Ok(()) } fn execute_call(service_type: &str, call_name: &str, mut f: F) -> thrift::Result where F: FnMut() -> thrift::Result, { let res = f(); match res { Ok(_) => println!("{}: completed {} call", service_type, call_name), Err(ref e) => println!( "{}: failed {} call with error {:?}", service_type, call_name, e ), } res } thrift-0.19.0/lib/rs/test/src/lib.rs0000644000000000000000000000305314370300523017151 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. pub mod base_one; pub mod base_two; pub mod midlayer; pub mod recursive; pub mod ultimate; #[cfg(test)] mod tests { use std::default::Default; use super::*; #[test] fn must_be_able_to_use_constructor() { let _ = midlayer::Meal::new(Some(base_one::Noodle::default()), None); } #[test] fn must_be_able_to_use_constructor_with_no_fields() { let _ = midlayer::Meal::new(None, None); } #[test] fn must_be_able_to_use_constructor_without_option_wrap() { let _ = midlayer::Meal::new(base_one::Noodle::default(), None); } #[test] fn must_be_able_to_use_defaults() { let _ = midlayer::Meal { noodle: Some(base_one::Noodle::default()), ..Default::default() }; } } thrift-0.19.0/lib/rs/test/Makefile.in0000644000000000000000000004455314472652517017345 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ Cargo.toml \ thrifts/Base_One.thrift \ thrifts/Base_Two.thrift \ thrifts/Midlayer.thrift \ thrifts/Ultimate.thrift \ src/lib.rs \ src/bin/kitchen_sink_server.rs \ src/bin/kitchen_sink_client.rs all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: thrifts/Base_One.thrift thrifts/Base_Two.thrift thrifts/Midlayer.thrift thrifts/Ultimate.thrift $(top_builddir)/test/Recursive.thrift $(THRIFT) $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Base_One.thrift $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Base_Two.thrift $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Midlayer.thrift $(THRIFT) -I ./thrifts -out src --gen rs thrifts/Ultimate.thrift $(THRIFT) -out src --gen rs $(top_builddir)/test/Recursive.thrift $(THRIFT) -out src --gen rs $(top_builddir)/test/Identifiers.thrift #THRIFT-4953 check: stubs $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) build $(CARGO) test [ -d bin ] || mkdir bin cp target/debug/kitchen_sink_server bin/kitchen_sink_server cp target/debug/kitchen_sink_client bin/kitchen_sink_client clean-local: $(CARGO) clean -$(RM) Cargo.lock -$(RM) src/base_one.rs -$(RM) src/base_two.rs -$(RM) src/midlayer.rs -$(RM) src/ultimate.rs -$(RM) src/recursive.rs -$(RM) src/identifiers.rs -$(RM) -r bin # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/test_recursive/0000755000000000000000000000000014472652670017354 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test_recursive/Makefile.am0000644000000000000000000000173114303740367021404 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = src check: $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) build $(CARGO) test clean-local: $(CARGO) clean -$(RM) Cargo.lock EXTRA_DIST = \ Cargo.toml thrift-0.19.0/lib/rs/test_recursive/Cargo.toml0000644000000000000000000000043714370300523021270 0ustar00rootroot00000000000000[package] name = "thrift_4098_custom_rust_namespace_support" description = "Test namespace support in generated thrift files using recursive Make generation" version = "0.1.0" authors = ["Allen George "] edition = "2021" [dependencies] thrift = { path = "../" } thrift-0.19.0/lib/rs/test_recursive/src/0000755000000000000000000000000014472652670020143 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test_recursive/src/transit/0000755000000000000000000000000014472652670021627 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test_recursive/src/transit/Makefile.am0000644000000000000000000000272314303740367023661 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # intentionally added a cyclic dependency between '.' and 'light' SUBDIRS = . light services THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: ../Vehicles.thrift Buses.thrift Trains.thrift Transporters.thrift services/CityServices.thrift light/LightRail.thrift light/Streetcars.thrift $(THRIFT) $(THRIFT) -I . -I ../ -I ./services -I ./light -out . --gen rs Buses.thrift $(THRIFT) -I . -I ../ -I ./services -I ./light -out . --gen rs Trains.thrift $(THRIFT) -I . -I ../ -I ./services -I ./light -out . --gen rs Transporters.thrift check: stubs clean-local: -$(RM) buses.rs -$(RM) trains.rs -$(RM) transporters.rs EXTRA_DIST = \ mod.rs \ Buses.thrift \ Trains.thrift \ Transporters.thrift thrift-0.19.0/lib/rs/test_recursive/src/transit/mod.rs0000644000000000000000000000156414303740367022754 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. pub mod buses; pub mod light; pub mod services; pub mod trains; pub mod transporters; thrift-0.19.0/lib/rs/test_recursive/src/transit/Buses.thrift0000644000000000000000000000307014303740367024124 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace rs transit include "CityServices.thrift" include "Vehicles.thrift" const Vehicles.Capacity DEFAULT4WHEELCAPACITY = 30 enum Powertrain { DIESEL = 0 BIO_DIESEL = 1 COMPRESSED_NATURAL_GAS = 2 TROLLEY = 3 HYBRID = 4 BATTERY = 5 } struct Bus { 1: Vehicles.VehicleIdentifier identifier 2: Vehicles.Capacity capacity 3: Powertrain powertrain 4: list materials } struct Route { 1: string routeId 2: list improvements } service Garage { Bus upgradeBus(1: Bus bus) list improvementsForRoute(1: Route route) }thrift-0.19.0/lib/rs/test_recursive/src/transit/light/0000755000000000000000000000000014472652670022736 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test_recursive/src/transit/light/Makefile.am0000644000000000000000000000236414303740367024771 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: ../../Vehicles.thrift ../Trains.thrift ../services/CityServices.thrift LightRail.thrift Streetcars.thrift $(THRIFT) $(THRIFT) -I . -I ../../ -I ../ -I ../services -out . --gen rs LightRail.thrift $(THRIFT) -I . -I ../../ -I ../ -I ../services -out . --gen rs Streetcars.thrift check: stubs clean-local: -$(RM) light_rail.rs -$(RM) streetcars.rs EXTRA_DIST = \ mod.rs \ LightRail.thrift \ Streetcars.thrift thrift-0.19.0/lib/rs/test_recursive/src/transit/light/mod.rs0000644000000000000000000000150614303740367024057 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. pub mod light_rail; pub mod streetcars; thrift-0.19.0/lib/rs/test_recursive/src/transit/light/Streetcars.thrift0000644000000000000000000000336514303740367026300 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ include "CityServices.thrift" include "Trains.thrift" include "Vehicles.thrift" namespace rs transit.light struct CLRV { 1: list materials 2: Trains.Locomotive locomotive } struct Flexity { 1: list materials 2: Trains.Locomotive locomotive } union RollingStock { 1: CLRV clrv 2: Flexity flexity } enum RouteNumber { Queen = 501 Downtowner = 502 Kingston = 503 King = 504 Dundas = 505 Carlton = 506 Lakeshore = 508 Harbourfront = 509 Spadina = 510 Bathurst = 511 StClair = 512 } struct Route { 1: RouteNumber id 2: list improvements = [] // ABSOLUTELY NONE! } struct Streetcar { 1: i16 id 2: RollingStock stock 3: Route route } service Barn { Streetcar upgradeStreetcar(1: Streetcar streetcar) }thrift-0.19.0/lib/rs/test_recursive/src/transit/light/LightRail.thrift0000644000000000000000000000256214303740367026036 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ include "CityServices.thrift" include "Trains.thrift" include "Vehicles.thrift" namespace rs transit.light struct Lrt { 1: list materials 2: Trains.Locomotive locomotive } enum Route { EglintonCrosstown = 0 FinchWest = 1 } struct Line { 1: Lrt lrt 2: Route route 3: list improvements = [] // ABSOLUTELY NONE BY DEFAULT! } service Msf { Lrt fixLrt(1: Lrt lrt) }thrift-0.19.0/lib/rs/test_recursive/src/transit/light/Makefile.in0000644000000000000000000005760214472652517025015 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test_recursive/src/transit/light ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . EXTRA_DIST = \ mod.rs \ LightRail.thrift \ Streetcars.thrift all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test_recursive/src/transit/light/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test_recursive/src/transit/light/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../../Vehicles.thrift ../Trains.thrift ../services/CityServices.thrift LightRail.thrift Streetcars.thrift $(THRIFT) $(THRIFT) -I . -I ../../ -I ../ -I ../services -out . --gen rs LightRail.thrift $(THRIFT) -I . -I ../../ -I ../ -I ../services -out . --gen rs Streetcars.thrift check: stubs clean-local: -$(RM) light_rail.rs -$(RM) streetcars.rs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/test_recursive/src/transit/Transporters.thrift0000644000000000000000000000236614303740367025560 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace rs transit include "Buses.thrift" include "LightRail.thrift" include "Streetcars.thrift" union FlatcarConsist { 1: LightRail.Lrt lrt 2: Streetcars.Streetcar streetcar 3: Buses.Bus bus } struct SingleVehicleTransporter { 1: FlatcarConsist consist 2: string source 3: string destination } thrift-0.19.0/lib/rs/test_recursive/src/transit/Trains.thrift0000644000000000000000000000214414303740367024304 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace rs transit enum Locomotive { Steam = 0 ElectricPole = 1 ElectricPantograph = 2 ElectricThirdRail = 3 DieselMechanical = 4 DieselElectric = 5 } thrift-0.19.0/lib/rs/test_recursive/src/transit/Makefile.in0000644000000000000000000006012014472652517023673 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test_recursive/src/transit ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # intentionally added a cyclic dependency between '.' and 'light' SUBDIRS = . light services EXTRA_DIST = \ mod.rs \ Buses.thrift \ Trains.thrift \ Transporters.thrift all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test_recursive/src/transit/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test_recursive/src/transit/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../Vehicles.thrift Buses.thrift Trains.thrift Transporters.thrift services/CityServices.thrift light/LightRail.thrift light/Streetcars.thrift $(THRIFT) $(THRIFT) -I . -I ../ -I ./services -I ./light -out . --gen rs Buses.thrift $(THRIFT) -I . -I ../ -I ./services -I ./light -out . --gen rs Trains.thrift $(THRIFT) -I . -I ../ -I ./services -I ./light -out . --gen rs Transporters.thrift check: stubs clean-local: -$(RM) buses.rs -$(RM) trains.rs -$(RM) transporters.rs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/test_recursive/src/transit/services/0000755000000000000000000000000014472652670023452 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test_recursive/src/transit/services/Makefile.am0000644000000000000000000000201214303740367025473 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: CityServices.thrift $(THRIFT) $(THRIFT) -I . -out . --gen rs CityServices.thrift check: stubs clean-local: -$(RM) city_services.rs EXTRA_DIST = \ mod.rs \ CityServices.thrift thrift-0.19.0/lib/rs/test_recursive/src/transit/services/mod.rs0000644000000000000000000000146514303740367024577 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. pub mod city_services; thrift-0.19.0/lib/rs/test_recursive/src/transit/services/CityServices.thrift0000644000000000000000000000206014303740367027300 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace rs transit.services enum TransitImprovements { TransitSignalPriority = 1 DedicatedRightOfWay = 2 } thrift-0.19.0/lib/rs/test_recursive/src/transit/services/Makefile.in0000644000000000000000000005724114472652517025530 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test_recursive/src/transit/services ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . EXTRA_DIST = \ mod.rs \ CityServices.thrift all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test_recursive/src/transit/services/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test_recursive/src/transit/services/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: CityServices.thrift $(THRIFT) $(THRIFT) -I . -out . --gen rs CityServices.thrift check: stubs clean-local: -$(RM) city_services.rs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/test_recursive/src/Makefile.am0000644000000000000000000000201514303740367022167 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . transit maintenance THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: Vehicles.thrift $(THRIFT) $(THRIFT) -I . -out . --gen rs Vehicles.thrift check: stubs clean-local: -$(RM) vehicles.rs EXTRA_DIST = \ lib.rs \ Vehicles.thrift thrift-0.19.0/lib/rs/test_recursive/src/lib.rs0000644000000000000000000002342514370300523021245 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. #![allow(dead_code)] pub mod maintenance; pub mod transit; pub mod vehicles; mod server { use crate::maintenance::maintenance_facility::{ BigBarnSyncHandler, MultimodalFacilitySyncHandler, }; use crate::transit::buses::{Bus, GarageSyncHandler}; use crate::transit::buses::{Powertrain, Route as BusRoute}; use crate::transit::light::streetcars::{ BarnSyncHandler, Flexity, RollingStock, Route, RouteNumber, Streetcar, }; use crate::transit::services::city_services::TransitImprovements; use crate::transit::trains::Locomotive; use crate::transit::transporters::{FlatcarConsist, SingleVehicleTransporter}; use crate::vehicles::Material; use thrift::Result; // // implement a whole bunch of handler methods just to make sure I can, and that everything compiles // pub struct AllInOneHandler; impl BigBarnSyncHandler for AllInOneHandler { fn handle_add_streetcar(&self, route: Route) -> Result { if let Some(route_number) = route.id { match route_number { RouteNumber::LAKESHORE => Ok(Streetcar { id: Some(4417), stock: Some(RollingStock::Flexity(Flexity { materials: Some(vec![Material::STEEL, Material::ALUMINUM]), locomotive: Some(Locomotive::ELECTRIC_PANTOGRAPH), })), route: Some(Route { id: Some(RouteNumber::LAKESHORE), improvements: None, }), }), _ => Err(thrift::Error::from(format!( "Cannot create streetcar for route number {}", route_number.0 ))), } } else { Err(thrift::Error::from("Can't add a streetcar")) } } } impl BarnSyncHandler for AllInOneHandler { fn handle_upgrade_streetcar(&self, streetcar: Streetcar) -> Result { if let Some(rolling_stock) = streetcar.stock { match rolling_stock { RollingStock::Clrv(_) => Ok(Streetcar { stock: Some(RollingStock::Flexity(Flexity { materials: Some(vec![Material::STEEL, Material::ALUMINUM]), locomotive: Some(Locomotive::ELECTRIC_PANTOGRAPH), })), ..streetcar }), RollingStock::Flexity(_) => { Err(thrift::Error::from("Streetcar already upgraded")) } } } else { Err(thrift::Error::from("Can't upgrade streetcar")) } } } impl MultimodalFacilitySyncHandler for AllInOneHandler { fn handle_build_transporter( &self, source: String, destination: String, consist: FlatcarConsist, ) -> Result { Ok(SingleVehicleTransporter { consist: Some(consist), source: Some(source), destination: Some(destination), }) } } impl GarageSyncHandler for AllInOneHandler { fn handle_upgrade_bus(&self, bus: Bus) -> Result { if let Some(p) = bus.powertrain { match p { Powertrain::COMPRESSED_NATURAL_GAS => Ok(Bus { powertrain: Some(Powertrain::DIESEL), ..bus }), _ => Err(thrift::Error::from("Cannot upgrade from this powertrain")), } } else { Err(thrift::Error::from("Cannot upgrade bus")) } } fn handle_improvements_for_route( &self, route: BusRoute, ) -> Result> { Ok(route .improvements .expect("Expecting a list of improvements")) } } } #[cfg(test)] mod tests { // // TODO: consider using the generated client/server and doing a round-trip // use crate::server::AllInOneHandler; use crate::transit::buses::{Bus, Powertrain, Route as BusRoute, DEFAULT4WHEELCAPACITY}; use crate::transit::light::light_rail::Lrt; use crate::transit::light::streetcars::{ BarnSyncHandler, Flexity, RollingStock, Route, RouteNumber, Streetcar, CLRV, }; use crate::transit::services::city_services::TransitImprovements; use crate::transit::trains::Locomotive; use crate::transit::transporters::{FlatcarConsist, SingleVehicleTransporter}; use crate::vehicles::{Material, VehicleIdentifier}; use crate::maintenance::maintenance_facility::{ BigBarnSyncHandler, MultimodalFacilitySyncHandler, }; use crate::transit::buses::GarageSyncHandler; #[test] fn handle_add_streetcar_compiles_and_returns_expected_value() { let expected = Streetcar { id: Some(4417), stock: Some(RollingStock::Flexity(Flexity { materials: Some(vec![Material::STEEL, Material::ALUMINUM]), locomotive: Some(Locomotive::ELECTRIC_PANTOGRAPH), })), route: Some(Route { id: Some(RouteNumber::LAKESHORE), improvements: None, }), }; let handler = AllInOneHandler {}; let actual = handler .handle_add_streetcar(Route { id: Some(RouteNumber::LAKESHORE), improvements: None, }) .expect("Expected a result"); assert_eq!(expected, actual) } #[test] fn handle_upgrade_streetcar_compiles_and_returns_expected_value() { let input = Streetcar { stock: Some(RollingStock::Clrv(CLRV { materials: Some(vec![Material::STEEL, Material::ALUMINUM]), locomotive: Some(Locomotive::ELECTRIC_POLE), })), id: Some(4415), route: Some(Route { id: Some(RouteNumber::SPADINA), improvements: Some(vec![TransitImprovements::DEDICATED_RIGHT_OF_WAY]), }), }; let expected = Streetcar { stock: Some(RollingStock::Flexity(Flexity { materials: Some(vec![Material::STEEL, Material::ALUMINUM]), locomotive: Some(Locomotive::ELECTRIC_PANTOGRAPH), })), id: Some(4415), route: Some(Route { id: Some(RouteNumber::SPADINA), improvements: Some(vec![TransitImprovements::DEDICATED_RIGHT_OF_WAY]), }), }; let handler = AllInOneHandler {}; let actual = handler .handle_upgrade_streetcar(input) .expect("Expected an upgraded streetcar"); assert_eq!(expected, actual) } #[test] fn handle_build_transporter_compiles_and_returns_expected_value() { let consist = FlatcarConsist::Lrt(Lrt { materials: Some(vec![Material::STEEL, Material::ALUMINUM]), locomotive: Some(Locomotive::ELECTRIC_PANTOGRAPH), }); let expected = SingleVehicleTransporter { consist: Some(consist.clone()), source: Some("905".to_owned()), destination: Some("416".to_owned()), }; let handler = AllInOneHandler {}; let actual = handler .handle_build_transporter("905".to_owned(), "416".to_owned(), consist) .expect("Expected a transporter"); assert_eq!(expected, actual) } #[test] fn handle_upgrade_bus_compiles_and_returns_expected_value() { let bus = Bus { identifier: Some(VehicleIdentifier { manufacturer: Some("Orion".to_owned()), model: Some("Orion 07.501 NG HEV".to_owned()), qualifiers: None, }), capacity: Some(DEFAULT4WHEELCAPACITY), powertrain: Some(Powertrain::COMPRESSED_NATURAL_GAS), materials: Some(vec![Material::STEEL, Material::ALUMINUM]), }; let expected = Bus { powertrain: Some(Powertrain::DIESEL), ..(bus.clone()) }; let handler = AllInOneHandler {}; let actual = handler .handle_upgrade_bus(bus) .expect("Expected improved bus"); assert_eq!(expected, actual) } #[test] fn handle_improvements_for_route_compiles_and_returns_expected_value() { let expected = vec![TransitImprovements::TRANSIT_SIGNAL_PRIORITY]; let bus_route = BusRoute { route_id: Some("320".to_owned()), improvements: Some(expected.clone()), }; let handler = AllInOneHandler {}; let actual = handler .handle_improvements_for_route(bus_route) .expect("Expected list of transit improvements"); assert_eq!(expected, actual) } } thrift-0.19.0/lib/rs/test_recursive/src/Vehicles.thrift0000644000000000000000000000214714303740367023125 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ typedef i16 Capacity enum Material { Steel = 0 Aluminum = 1 } struct VehicleIdentifier { 1: string manufacturer 2: string model 3: list qualifiers } thrift-0.19.0/lib/rs/test_recursive/src/maintenance/0000755000000000000000000000000014472652670022425 5ustar00rootroot00000000000000thrift-0.19.0/lib/rs/test_recursive/src/maintenance/Makefile.am0000644000000000000000000000243314303740367024455 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . THRIFT = $(top_builddir)/compiler/cpp/thrift stubs: ../Vehicles.thrift ../transit/Buses.thrift ../transit/Trains.thrift ../transit/Transporters.thrift ../transit/services/CityServices.thrift ../transit/light/LightRail.thrift ../transit/light/Streetcars.thrift $(THRIFT) $(THRIFT) -I . -I ../ -I ../transit -I ../transit/services -I ../transit/light -out . --gen rs MaintenanceFacility.thrift check: stubs clean-local: -$(RM) maintenance_facility.rs EXTRA_DIST = \ mod.rs \ MaintenanceFacility.thrift thrift-0.19.0/lib/rs/test_recursive/src/maintenance/mod.rs0000644000000000000000000000147414303740367023552 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. pub mod maintenance_facility; thrift-0.19.0/lib/rs/test_recursive/src/maintenance/Makefile.in0000644000000000000000000005764314472652517024511 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test_recursive/src/maintenance ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . EXTRA_DIST = \ mod.rs \ MaintenanceFacility.thrift all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test_recursive/src/maintenance/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test_recursive/src/maintenance/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../Vehicles.thrift ../transit/Buses.thrift ../transit/Trains.thrift ../transit/Transporters.thrift ../transit/services/CityServices.thrift ../transit/light/LightRail.thrift ../transit/light/Streetcars.thrift $(THRIFT) $(THRIFT) -I . -I ../ -I ../transit -I ../transit/services -I ../transit/light -out . --gen rs MaintenanceFacility.thrift check: stubs clean-local: -$(RM) maintenance_facility.rs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/test_recursive/src/maintenance/MaintenanceFacility.thrift0000644000000000000000000000256214303740367027555 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace rs maintenance include "Buses.thrift" include "LightRail.thrift" include "Streetcars.thrift" include "Transporters.thrift" service BigBarn extends Streetcars.Barn { Streetcars.Streetcar addStreetcar(1: Streetcars.Route route) } service MultimodalFacility extends Buses.Garage { Transporters.SingleVehicleTransporter buildTransporter(1: string source, 2: string destination, 3: Transporters.FlatcarConsist consist) }thrift-0.19.0/lib/rs/test_recursive/src/Makefile.in0000644000000000000000000005716114472652517022222 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test_recursive/src ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . transit maintenance EXTRA_DIST = \ lib.rs \ Vehicles.thrift all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test_recursive/src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test_recursive/src/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: Vehicles.thrift $(THRIFT) $(THRIFT) -I . -out . --gen rs Vehicles.thrift check: stubs clean-local: -$(RM) vehicles.rs # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/test_recursive/Makefile.in0000644000000000000000000005710414472652517021430 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rs/test_recursive ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src EXTRA_DIST = \ Cargo.toml all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/test_recursive/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/test_recursive/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags tags-am uninstall uninstall-am .PRECIOUS: Makefile check: $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) build $(CARGO) test clean-local: $(CARGO) clean -$(RM) Cargo.lock # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/release.sh0000777000000000000000000000137514062750226016266 0ustar00rootroot00000000000000#!/bin/bash set -o errexit set -o pipefail set -o nounset if ! [[ $# -eq 1 && $1 =~ ^[0-9](\.[0-9][0-9]*){2}$ ]]; then (>&2 echo "Usage: ./publish-crate.sh [THRIFT_RELEASE_VERSION] ") (>&2 echo " THRIFT_RELEASE_VERSION is in semantic versioning format, i.e. #.##.##") exit 1 fi THRIFT_RELEASE_VERSION=${1:-} echo "Updating Cargo.toml to ${THRIFT_RELEASE_VERSION}" sed -i.old -e "s/^version = .*$/version = \"${THRIFT_RELEASE_VERSION}\"/g" Cargo.toml rm Cargo.toml.old echo "Committing updated Cargo.toml" git add Cargo.toml git commit -m "Update thrift crate version to ${THRIFT_RELEASE_VERSION}" -m "Client: rs" echo "Packaging and releasing rust thrift crate with version ${THRIFT_RELEASE_VERSION}" cargo clean cargo package cargo publish thrift-0.19.0/lib/rs/Makefile.in0000644000000000000000000006027214472652517016362 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_TESTS_TRUE@am__append_1 = test test_recursive subdir = lib/rs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . test test_recursive am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . $(am__append_1) EXTRA_DIST = \ src \ Cargo.toml \ README.md \ release.sh \ RELEASING.md all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rs/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ check check-am check-local clean clean-generic clean-libtool \ clean-local cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile install: @echo '##############################################################' @echo '##############################################################' @echo 'The Rust client library should be installed via a Cargo.toml dependency - please see /lib/rs/README.md' @echo '##############################################################' @echo '##############################################################' check-local: $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) test all-local: $(CARGO) fmt --all -- --check $(CARGO) clippy --all -- -D warnings $(CARGO) build clean-local: $(CARGO) clean -$(RM) Cargo.lock # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/rs/RELEASING.md0000644000000000000000000000354314303740367016140 0ustar00rootroot00000000000000# Publishing the thrift crate Publishing the Rust thrift crate is straightforward, and involves two major steps: 1. Setting up your [crates.io](https://www.crates.io) account _(one-time)_ 2. Packaging/publishing the Rust thrift crate itself ## Set up your crates.io account (one-time) 1. Go to [crates.io](https://www.crates.io) and click the `Log In` button at the top right. Log in **as the Github user with write permissions to the thrift repo!** 2. Click your user icon button at the top right and select `Account Settings`. 3. Click `New Token` next to `API Access`. This generates a new API key that cargo uses to publish packages to crates.io. Store this API key somewhere safe. If you will only use this Github account to publish crates to crates.io you can follow the instructions to save the generated key to `~/.cargo/credentials`. ## Package and Publish You can use the automated script or run the release steps manually. **Important**: `cargo` expects that version numbers follow the semantic versioning format. This means that `THRIFT_RELEASE_VERSION` must have a major, minor and patch number, i.e., must be in the form `#.##.##`. #### Automated Run `./release.sh [THRIFT_RELEASE_VERSION]`. _Requires you to have stored your credentials in `~/.cargo/credentials`._ #### Manual 1. Edit `Cargo.toml` and update the `version = 1.0` key to `version = [THRIFT_RELEASE_VERSION]` 2. `git add Cargo.toml` 3. `git commit -m "Update thrift crate version to [THRIFT_RELEASE_VERSION]" -m "Client: rs"` 4. `cargo login` _(not required if you have stored your credentials in `~/.cargo/credentials`)_ 5. `cargo clean` 6. `cargo package` This step fails if there are any uncommitted or ignored files. Do **not** use the `--allow-dirty` flag! Instead, add the highlighted files as entries in the `Cargo.toml` `exclude` key. 7. `cargo publish` thrift-0.19.0/lib/rb/0000755000000000000000000000000014472652660014264 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/ext/0000777000000000000000000000000014303740367015063 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/ext/constants.h0000644000000000000000000000613614303740367017252 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ extern int TTYPE_STOP; extern int TTYPE_BOOL; extern int TTYPE_BYTE; extern int TTYPE_I16; extern int TTYPE_I32; extern int TTYPE_I64; extern int TTYPE_DOUBLE; extern int TTYPE_STRING; extern int TTYPE_MAP; extern int TTYPE_SET; extern int TTYPE_LIST; extern int TTYPE_STRUCT; extern ID validate_method_id; extern ID write_struct_begin_method_id; extern ID write_struct_end_method_id; extern ID write_field_begin_method_id; extern ID write_field_end_method_id; extern ID write_boolean_method_id; extern ID write_byte_method_id; extern ID write_i16_method_id; extern ID write_i32_method_id; extern ID write_i64_method_id; extern ID write_double_method_id; extern ID write_string_method_id; extern ID write_binary_method_id; extern ID write_map_begin_method_id; extern ID write_map_end_method_id; extern ID write_list_begin_method_id; extern ID write_list_end_method_id; extern ID write_set_begin_method_id; extern ID write_set_end_method_id; extern ID read_bool_method_id; extern ID read_byte_method_id; extern ID read_i16_method_id; extern ID read_i32_method_id; extern ID read_i64_method_id; extern ID read_string_method_id; extern ID read_binary_method_id; extern ID read_double_method_id; extern ID read_map_begin_method_id; extern ID read_map_end_method_id; extern ID read_list_begin_method_id; extern ID read_list_end_method_id; extern ID read_set_begin_method_id; extern ID read_set_end_method_id; extern ID read_struct_begin_method_id; extern ID read_struct_end_method_id; extern ID read_field_begin_method_id; extern ID read_field_end_method_id; extern ID keys_method_id; extern ID entries_method_id; extern ID write_field_stop_method_id; extern ID skip_method_id; extern ID write_method_id; extern ID read_all_method_id; extern ID read_into_buffer_method_id; extern ID force_binary_encoding_id; extern ID convert_to_utf8_byte_buffer_id; extern ID convert_to_string_id; extern ID fields_const_id; extern ID transport_ivar_id; extern ID strict_read_ivar_id; extern ID strict_write_ivar_id; extern VALUE type_sym; extern VALUE name_sym; extern VALUE key_sym; extern VALUE value_sym; extern VALUE element_sym; extern VALUE class_sym; extern VALUE binary_sym; extern VALUE rb_cSet; extern VALUE thrift_module; extern VALUE thrift_types_module; extern VALUE thrift_bytes_module; extern VALUE class_thrift_protocol; extern VALUE protocol_exception_class; thrift-0.19.0/lib/rb/ext/thrift_native.c0000644000000000000000000001720114303740367020072 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include // cached classes/modules VALUE rb_cSet; VALUE thrift_module; VALUE thrift_bytes_module; VALUE thrift_types_module; // TType constants int TTYPE_STOP; int TTYPE_BOOL; int TTYPE_BYTE; int TTYPE_I16; int TTYPE_I32; int TTYPE_I64; int TTYPE_DOUBLE; int TTYPE_STRING; int TTYPE_MAP; int TTYPE_SET; int TTYPE_LIST; int TTYPE_STRUCT; // method ids ID validate_method_id; ID write_struct_begin_method_id; ID write_struct_end_method_id; ID write_field_begin_method_id; ID write_field_end_method_id; ID write_boolean_method_id; ID write_byte_method_id; ID write_i16_method_id; ID write_i32_method_id; ID write_i64_method_id; ID write_double_method_id; ID write_string_method_id; ID write_binary_method_id; ID write_map_begin_method_id; ID write_map_end_method_id; ID write_list_begin_method_id; ID write_list_end_method_id; ID write_set_begin_method_id; ID write_set_end_method_id; ID read_bool_method_id; ID read_byte_method_id; ID read_i16_method_id; ID read_i32_method_id; ID read_i64_method_id; ID read_string_method_id; ID read_binary_method_id; ID read_double_method_id; ID read_map_begin_method_id; ID read_map_end_method_id; ID read_list_begin_method_id; ID read_list_end_method_id; ID read_set_begin_method_id; ID read_set_end_method_id; ID read_struct_begin_method_id; ID read_struct_end_method_id; ID read_field_begin_method_id; ID read_field_end_method_id; ID keys_method_id; ID entries_method_id; ID write_field_stop_method_id; ID skip_method_id; ID write_method_id; ID read_all_method_id; ID read_into_buffer_method_id; ID force_binary_encoding_id; ID convert_to_utf8_byte_buffer_id; ID convert_to_string_id; // constant ids ID fields_const_id; ID transport_ivar_id; ID strict_read_ivar_id; ID strict_write_ivar_id; // cached symbols VALUE type_sym; VALUE name_sym; VALUE key_sym; VALUE value_sym; VALUE element_sym; VALUE class_sym; VALUE binary_sym; VALUE protocol_exception_class; void Init_thrift_native() { // cached classes thrift_module = rb_const_get(rb_cObject, rb_intern("Thrift")); rb_global_variable(&thrift_module); thrift_bytes_module = rb_const_get(thrift_module, rb_intern("Bytes")); rb_global_variable(&thrift_bytes_module); thrift_types_module = rb_const_get(thrift_module, rb_intern("Types")); rb_global_variable(&thrift_types_module); rb_cSet = rb_const_get(rb_cObject, rb_intern("Set")); rb_global_variable(&rb_cSet); protocol_exception_class = rb_const_get(thrift_module, rb_intern("ProtocolException")); rb_global_variable(&protocol_exception_class); // Init ttype constants TTYPE_BOOL = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BOOL"))); TTYPE_BYTE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("BYTE"))); TTYPE_I16 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I16"))); TTYPE_I32 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I32"))); TTYPE_I64 = FIX2INT(rb_const_get(thrift_types_module, rb_intern("I64"))); TTYPE_DOUBLE = FIX2INT(rb_const_get(thrift_types_module, rb_intern("DOUBLE"))); TTYPE_STRING = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRING"))); TTYPE_MAP = FIX2INT(rb_const_get(thrift_types_module, rb_intern("MAP"))); TTYPE_SET = FIX2INT(rb_const_get(thrift_types_module, rb_intern("SET"))); TTYPE_LIST = FIX2INT(rb_const_get(thrift_types_module, rb_intern("LIST"))); TTYPE_STRUCT = FIX2INT(rb_const_get(thrift_types_module, rb_intern("STRUCT"))); // method ids validate_method_id = rb_intern("validate"); write_struct_begin_method_id = rb_intern("write_struct_begin"); write_struct_end_method_id = rb_intern("write_struct_end"); write_field_begin_method_id = rb_intern("write_field_begin"); write_field_end_method_id = rb_intern("write_field_end"); write_boolean_method_id = rb_intern("write_bool"); write_byte_method_id = rb_intern("write_byte"); write_i16_method_id = rb_intern("write_i16"); write_i32_method_id = rb_intern("write_i32"); write_i64_method_id = rb_intern("write_i64"); write_double_method_id = rb_intern("write_double"); write_string_method_id = rb_intern("write_string"); write_binary_method_id = rb_intern("write_binary"); write_map_begin_method_id = rb_intern("write_map_begin"); write_map_end_method_id = rb_intern("write_map_end"); write_list_begin_method_id = rb_intern("write_list_begin"); write_list_end_method_id = rb_intern("write_list_end"); write_set_begin_method_id = rb_intern("write_set_begin"); write_set_end_method_id = rb_intern("write_set_end"); read_bool_method_id = rb_intern("read_bool"); read_byte_method_id = rb_intern("read_byte"); read_i16_method_id = rb_intern("read_i16"); read_i32_method_id = rb_intern("read_i32"); read_i64_method_id = rb_intern("read_i64"); read_string_method_id = rb_intern("read_string"); read_binary_method_id = rb_intern("read_binary"); read_double_method_id = rb_intern("read_double"); read_map_begin_method_id = rb_intern("read_map_begin"); read_map_end_method_id = rb_intern("read_map_end"); read_list_begin_method_id = rb_intern("read_list_begin"); read_list_end_method_id = rb_intern("read_list_end"); read_set_begin_method_id = rb_intern("read_set_begin"); read_set_end_method_id = rb_intern("read_set_end"); read_struct_begin_method_id = rb_intern("read_struct_begin"); read_struct_end_method_id = rb_intern("read_struct_end"); read_field_begin_method_id = rb_intern("read_field_begin"); read_field_end_method_id = rb_intern("read_field_end"); keys_method_id = rb_intern("keys"); entries_method_id = rb_intern("entries"); write_field_stop_method_id = rb_intern("write_field_stop"); skip_method_id = rb_intern("skip"); write_method_id = rb_intern("write"); read_all_method_id = rb_intern("read_all"); read_into_buffer_method_id = rb_intern("read_into_buffer"); force_binary_encoding_id = rb_intern("force_binary_encoding"); convert_to_utf8_byte_buffer_id = rb_intern("convert_to_utf8_byte_buffer"); convert_to_string_id = rb_intern("convert_to_string"); // constant ids fields_const_id = rb_intern("FIELDS"); transport_ivar_id = rb_intern("@trans"); strict_read_ivar_id = rb_intern("@strict_read"); strict_write_ivar_id = rb_intern("@strict_write"); // cached symbols type_sym = ID2SYM(rb_intern("type")); name_sym = ID2SYM(rb_intern("name")); key_sym = ID2SYM(rb_intern("key")); value_sym = ID2SYM(rb_intern("value")); element_sym = ID2SYM(rb_intern("element")); class_sym = ID2SYM(rb_intern("class")); binary_sym = ID2SYM(rb_intern("binary")); rb_global_variable(&type_sym); rb_global_variable(&name_sym); rb_global_variable(&key_sym); rb_global_variable(&value_sym); rb_global_variable(&element_sym); rb_global_variable(&class_sym); rb_global_variable(&binary_sym); Init_struct(); Init_binary_protocol_accelerated(); Init_compact_protocol(); Init_memory_buffer(); } thrift-0.19.0/lib/rb/ext/macros.h0000644000000000000000000000311614303740367016515 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define GET_TRANSPORT(obj) rb_ivar_get(obj, transport_ivar_id) #define GET_STRICT_READ(obj) rb_ivar_get(obj, strict_read_ivar_id) #define GET_STRICT_WRITE(obj) rb_ivar_get(obj, strict_write_ivar_id) #define WRITE(obj, data, length) rb_funcall(obj, write_method_id, 1, rb_str_new(data, length)) #define CHECK_NIL(obj) if (NIL_P(obj)) { rb_raise(rb_eStandardError, "nil argument not allowed!");} #define READ(obj, length) rb_funcall(GET_TRANSPORT(obj), read_all_method_id, 1, INT2FIX(length)) #ifndef RFLOAT_VALUE # define RFLOAT_VALUE(v) RFLOAT(rb_Float(v))->value #endif #ifndef RSTRING_LEN # define RSTRING_LEN(v) RSTRING(rb_String(v))->len #endif #ifndef RSTRING_PTR # define RSTRING_PTR(v) RSTRING(rb_String(v))->ptr #endif #ifndef RARRAY_LEN # define RARRAY_LEN(v) RARRAY(rb_Array(v))->len #endif thrift-0.19.0/lib/rb/ext/extconf.rb0000644000000000000000000000224514303740367017055 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ File.open('Makefile', 'w'){|f| f.puts "all:\n\ninstall:\n" } else require 'mkmf' require 'rbconfig' $ARCH_FLAGS = RbConfig::CONFIG['CFLAGS'].scan( /(-arch )(\S+)/ ).map{|x,y| x + y + ' ' }.join('') $CFLAGS = "-fsigned-char -g -O2 -Wall -Werror " + $ARCH_FLAGS have_func("strlcpy", "string.h") create_makefile 'thrift_native' end thrift-0.19.0/lib/rb/ext/bytes.c0000644000000000000000000000242514303740367016354 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #ifdef HAVE_RUBY_ENCODING_H #include #endif #include VALUE force_binary_encoding(VALUE buffer) { return rb_funcall(thrift_bytes_module, force_binary_encoding_id, 1, buffer); } VALUE convert_to_utf8_byte_buffer(VALUE string) { return rb_funcall(thrift_bytes_module, convert_to_utf8_byte_buffer_id, 1, string); } VALUE convert_to_string(VALUE utf8_buffer) { return rb_funcall(thrift_bytes_module, convert_to_string_id, 1, utf8_buffer); } thrift-0.19.0/lib/rb/ext/protocol.c0000644000000000000000000000000014303740367017052 0ustar00rootroot00000000000000thrift-0.19.0/lib/rb/ext/strlcpy.h0000644000000000000000000000210114303740367016722 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #ifndef __has_builtin #define __has_builtin(x) 0 #endif #ifndef HAVE_STRLCPY size_t strlcpy (char *dst, const char *src, size_t dst_sz); #else #if !__has_builtin(strlcpy) extern size_t strlcpy(char *, const char *, size_t); #endif #endif thrift-0.19.0/lib/rb/ext/strlcpy.c0000644000000000000000000000220314303740367016720 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "strlcpy.h" #ifndef HAVE_STRLCPY #define HAVE_STRLCPY size_t strlcpy (char *dst, const char *src, size_t dst_sz) { size_t n; for (n = 0; n < dst_sz; n++) { if ((*dst++ = *src++) == '\0') break; } if (n < dst_sz) return n; if (n > 0) *(dst - 1) = '\0'; return n + strlen (src); } #endif thrift-0.19.0/lib/rb/ext/bytes.h0000644000000000000000000000217214303740367016360 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include /* * A collection of utilities for working with bytes and byte buffers. * * These methods are the native analogies to some of the methods in * Thrift::Bytes (thrift/bytes.rb). */ VALUE force_binary_encoding(VALUE buffer); VALUE convert_to_utf8_byte_buffer(VALUE string); VALUE convert_to_string(VALUE utf8_buffer); thrift-0.19.0/lib/rb/ext/memory_buffer.h0000644000000000000000000000150014303740367020065 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void Init_memory_buffer(); thrift-0.19.0/lib/rb/ext/protocol.h0000644000000000000000000000000014303740367017057 0ustar00rootroot00000000000000thrift-0.19.0/lib/rb/ext/binary_protocol_accelerated.h0000644000000000000000000000151614303740367022754 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void Init_binary_protocol_accelerated(); thrift-0.19.0/lib/rb/ext/struct.h0000644000000000000000000000156514303740367016563 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include void Init_struct(); void Init_union(); thrift-0.19.0/lib/rb/ext/memory_buffer.c0000644000000000000000000001061714303740367020071 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include ID buf_ivar_id; ID index_ivar_id; ID slice_method_id; int GARBAGE_BUFFER_SIZE; #define GET_BUF(self) rb_ivar_get(self, buf_ivar_id) VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str); VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value); VALUE rb_thrift_memory_buffer_read_byte(VALUE self); VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value); VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) { VALUE buf = GET_BUF(self); str = force_binary_encoding(str); rb_str_buf_cat(buf, StringValuePtr(str), RSTRING_LEN(str)); return Qnil; } VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) { int length = FIX2INT(length_value); VALUE index_value = rb_ivar_get(self, index_ivar_id); int index = FIX2INT(index_value); VALUE buf = GET_BUF(self); VALUE data = rb_funcall(buf, slice_method_id, 2, index_value, length_value); index += length; if (index > RSTRING_LEN(buf)) { index = RSTRING_LEN(buf); } if (index >= GARBAGE_BUFFER_SIZE) { rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); index = 0; } rb_ivar_set(self, index_ivar_id, INT2FIX(index)); if (RSTRING_LEN(data) < length) { rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); } return data; } VALUE rb_thrift_memory_buffer_read_byte(VALUE self) { VALUE index_value = rb_ivar_get(self, index_ivar_id); int index = FIX2INT(index_value); VALUE buf = GET_BUF(self); if (index >= RSTRING_LEN(buf)) { rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); } char byte = RSTRING_PTR(buf)[index++]; if (index >= GARBAGE_BUFFER_SIZE) { rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); index = 0; } rb_ivar_set(self, index_ivar_id, INT2FIX(index)); int result = (int) byte; return INT2FIX(result); } VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value) { int i = 0; int size = FIX2INT(size_value); int index; VALUE buf = GET_BUF(self); index = FIX2INT(rb_ivar_get(self, index_ivar_id)); while (i < size) { if (index >= RSTRING_LEN(buf)) { rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer"); } char byte = RSTRING_PTR(buf)[index++]; if (i >= RSTRING_LEN(buffer_value)) { rb_raise(rb_eIndexError, "index %d out of string", i); } ((char*)RSTRING_PTR(buffer_value))[i] = byte; i++; } if (index >= GARBAGE_BUFFER_SIZE) { rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1))); index = 0; } rb_ivar_set(self, index_ivar_id, INT2FIX(index)); return INT2FIX(i); } void Init_memory_buffer() { VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport")); rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1); rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1); rb_define_method(thrift_memory_buffer_class, "read_byte", rb_thrift_memory_buffer_read_byte, 0); rb_define_method(thrift_memory_buffer_class, "read_into_buffer", rb_thrift_memory_buffer_read_into_buffer, 2); buf_ivar_id = rb_intern("@buf"); index_ivar_id = rb_intern("@index"); slice_method_id = rb_intern("slice"); GARBAGE_BUFFER_SIZE = FIX2INT(rb_const_get(thrift_memory_buffer_class, rb_intern("GARBAGE_BUFFER_SIZE"))); } thrift-0.19.0/lib/rb/ext/binary_protocol_accelerated.c0000644000000000000000000003654614303740367022762 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include VALUE rb_thrift_binary_proto_native_qmark(VALUE self) { return Qtrue; } static int VERSION_1; static int VERSION_MASK; static int TYPE_MASK; static int BAD_VERSION; static ID rbuf_ivar_id; static void write_byte_direct(VALUE trans, int8_t b) { WRITE(trans, (char*)&b, 1); } static void write_i16_direct(VALUE trans, int16_t value) { char data[2]; data[1] = value; data[0] = (value >> 8); WRITE(trans, data, 2); } static void write_i32_direct(VALUE trans, int32_t value) { char data[4]; data[3] = value; data[2] = (value >> 8); data[1] = (value >> 16); data[0] = (value >> 24); WRITE(trans, data, 4); } static void write_i64_direct(VALUE trans, int64_t value) { char data[8]; data[7] = value; data[6] = (value >> 8); data[5] = (value >> 16); data[4] = (value >> 24); data[3] = (value >> 32); data[2] = (value >> 40); data[1] = (value >> 48); data[0] = (value >> 56); WRITE(trans, data, 8); } static void write_string_direct(VALUE trans, VALUE str) { if (TYPE(str) != T_STRING) { rb_raise(rb_eStandardError, "Value should be a string"); } str = convert_to_utf8_byte_buffer(str); write_i32_direct(trans, RSTRING_LEN(str)); rb_funcall(trans, write_method_id, 1, str); } //-------------------------------- // interface writing methods //-------------------------------- VALUE rb_thrift_binary_proto_write_message_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_write_struct_begin(VALUE self, VALUE name) { return Qnil; } VALUE rb_thrift_binary_proto_write_struct_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_write_field_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_write_map_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_write_list_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_write_set_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) { VALUE trans = GET_TRANSPORT(self); VALUE strict_write = GET_STRICT_WRITE(self); if (strict_write == Qtrue) { write_i32_direct(trans, VERSION_1 | FIX2INT(type)); write_string_direct(trans, name); write_i32_direct(trans, FIX2INT(seqid)); } else { write_string_direct(trans, name); write_byte_direct(trans, FIX2INT(type)); write_i32_direct(trans, FIX2INT(seqid)); } return Qnil; } VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) { VALUE trans = GET_TRANSPORT(self); write_byte_direct(trans, FIX2INT(type)); write_i16_direct(trans, FIX2INT(id)); return Qnil; } VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) { write_byte_direct(GET_TRANSPORT(self), TTYPE_STOP); return Qnil; } VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) { VALUE trans = GET_TRANSPORT(self); write_byte_direct(trans, FIX2INT(ktype)); write_byte_direct(trans, FIX2INT(vtype)); write_i32_direct(trans, FIX2INT(size)); return Qnil; } VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) { VALUE trans = GET_TRANSPORT(self); write_byte_direct(trans, FIX2INT(etype)); write_i32_direct(trans, FIX2INT(size)); return Qnil; } VALUE rb_thrift_binary_proto_write_set_begin(VALUE self, VALUE etype, VALUE size) { rb_thrift_binary_proto_write_list_begin(self, etype, size); return Qnil; } VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) { write_byte_direct(GET_TRANSPORT(self), RTEST(b) ? 1 : 0); return Qnil; } VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) { CHECK_NIL(byte); write_byte_direct(GET_TRANSPORT(self), NUM2INT(byte)); return Qnil; } VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) { CHECK_NIL(i16); write_i16_direct(GET_TRANSPORT(self), FIX2INT(i16)); return Qnil; } VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) { CHECK_NIL(i32); write_i32_direct(GET_TRANSPORT(self), NUM2INT(i32)); return Qnil; } VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) { CHECK_NIL(i64); write_i64_direct(GET_TRANSPORT(self), NUM2LL(i64)); return Qnil; } VALUE rb_thrift_binary_proto_write_double(VALUE self, VALUE dub) { CHECK_NIL(dub); // Unfortunately, bitwise_cast doesn't work in C. Bad C! union { double f; int64_t t; } transfer; transfer.f = RFLOAT_VALUE(rb_Float(dub)); write_i64_direct(GET_TRANSPORT(self), transfer.t); return Qnil; } VALUE rb_thrift_binary_proto_write_string(VALUE self, VALUE str) { CHECK_NIL(str); VALUE trans = GET_TRANSPORT(self); write_string_direct(trans, str); return Qnil; } VALUE rb_thrift_binary_proto_write_binary(VALUE self, VALUE buf) { CHECK_NIL(buf); VALUE trans = GET_TRANSPORT(self); buf = force_binary_encoding(buf); write_i32_direct(trans, RSTRING_LEN(buf)); rb_funcall(trans, write_method_id, 1, buf); return Qnil; } //--------------------------------------- // interface reading methods //--------------------------------------- VALUE rb_thrift_binary_proto_read_string(VALUE self); VALUE rb_thrift_binary_proto_read_binary(VALUE self); VALUE rb_thrift_binary_proto_read_byte(VALUE self); VALUE rb_thrift_binary_proto_read_i32(VALUE self); VALUE rb_thrift_binary_proto_read_i16(VALUE self); static char read_byte_direct(VALUE self) { VALUE byte = rb_funcall(GET_TRANSPORT(self), read_byte_method_id, 0); return (char)(FIX2INT(byte)); } static int16_t read_i16_direct(VALUE self) { VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(2)); return (int16_t)(((uint8_t)(RSTRING_PTR(rbuf)[1])) | ((uint16_t)((RSTRING_PTR(rbuf)[0]) << 8))); } static int32_t read_i32_direct(VALUE self) { VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(4)); return ((uint8_t)(RSTRING_PTR(rbuf)[3])) | (((uint8_t)(RSTRING_PTR(rbuf)[2])) << 8) | (((uint8_t)(RSTRING_PTR(rbuf)[1])) << 16) | (((uint8_t)(RSTRING_PTR(rbuf)[0])) << 24); } static int64_t read_i64_direct(VALUE self) { VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8)); uint64_t hi = ((uint8_t)(RSTRING_PTR(rbuf)[3])) | (((uint8_t)(RSTRING_PTR(rbuf)[2])) << 8) | (((uint8_t)(RSTRING_PTR(rbuf)[1])) << 16) | (((uint8_t)(RSTRING_PTR(rbuf)[0])) << 24); uint32_t lo = ((uint8_t)(RSTRING_PTR(rbuf)[7])) | (((uint8_t)(RSTRING_PTR(rbuf)[6])) << 8) | (((uint8_t)(RSTRING_PTR(rbuf)[5])) << 16) | (((uint8_t)(RSTRING_PTR(rbuf)[4])) << 24); return (hi << 32) | lo; } static VALUE get_protocol_exception(VALUE code, VALUE message) { VALUE args[2]; args[0] = code; args[1] = message; return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class); } VALUE rb_thrift_binary_proto_read_message_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_struct_begin(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_struct_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_field_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_map_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_list_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_set_end(VALUE self) { return Qnil; } VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) { VALUE strict_read = GET_STRICT_READ(self); VALUE name, seqid; int type; int version = read_i32_direct(self); if (version < 0) { if ((version & VERSION_MASK) != VERSION_1) { rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("Missing version identifier"))); } type = version & TYPE_MASK; name = rb_thrift_binary_proto_read_string(self); seqid = rb_thrift_binary_proto_read_i32(self); } else { if (strict_read == Qtrue) { rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("No version identifier, old protocol client?"))); } name = READ(self, version); type = read_byte_direct(self); seqid = rb_thrift_binary_proto_read_i32(self); } return rb_ary_new3(3, name, INT2FIX(type), seqid); } VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) { int type = read_byte_direct(self); if (type == TTYPE_STOP) { return rb_ary_new3(3, Qnil, INT2FIX(type), INT2FIX(0)); } else { VALUE id = rb_thrift_binary_proto_read_i16(self); return rb_ary_new3(3, Qnil, INT2FIX(type), id); } } VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) { VALUE ktype = rb_thrift_binary_proto_read_byte(self); VALUE vtype = rb_thrift_binary_proto_read_byte(self); VALUE size = rb_thrift_binary_proto_read_i32(self); return rb_ary_new3(3, ktype, vtype, size); } VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) { VALUE etype = rb_thrift_binary_proto_read_byte(self); VALUE size = rb_thrift_binary_proto_read_i32(self); return rb_ary_new3(2, etype, size); } VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) { return rb_thrift_binary_proto_read_list_begin(self); } VALUE rb_thrift_binary_proto_read_bool(VALUE self) { char byte = read_byte_direct(self); return byte != 0 ? Qtrue : Qfalse; } VALUE rb_thrift_binary_proto_read_byte(VALUE self) { return INT2FIX(read_byte_direct(self)); } VALUE rb_thrift_binary_proto_read_i16(VALUE self) { return INT2FIX(read_i16_direct(self)); } VALUE rb_thrift_binary_proto_read_i32(VALUE self) { return INT2NUM(read_i32_direct(self)); } VALUE rb_thrift_binary_proto_read_i64(VALUE self) { return LL2NUM(read_i64_direct(self)); } VALUE rb_thrift_binary_proto_read_double(VALUE self) { union { double f; int64_t t; } transfer; transfer.t = read_i64_direct(self); return rb_float_new(transfer.f); } VALUE rb_thrift_binary_proto_read_string(VALUE self) { VALUE buffer = rb_thrift_binary_proto_read_binary(self); return convert_to_string(buffer); } VALUE rb_thrift_binary_proto_read_binary(VALUE self) { int size = read_i32_direct(self); return READ(self, size); } void Init_binary_protocol_accelerated() { VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol")); VERSION_1 = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_1"))); VERSION_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_MASK"))); TYPE_MASK = rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("TYPE_MASK"))); VALUE bpa_class = rb_define_class_under(thrift_module, "BinaryProtocolAccelerated", thrift_binary_protocol_class); rb_define_method(bpa_class, "native?", rb_thrift_binary_proto_native_qmark, 0); rb_define_method(bpa_class, "write_message_begin", rb_thrift_binary_proto_write_message_begin, 3); rb_define_method(bpa_class, "write_field_begin", rb_thrift_binary_proto_write_field_begin, 3); rb_define_method(bpa_class, "write_field_stop", rb_thrift_binary_proto_write_field_stop, 0); rb_define_method(bpa_class, "write_map_begin", rb_thrift_binary_proto_write_map_begin, 3); rb_define_method(bpa_class, "write_list_begin", rb_thrift_binary_proto_write_list_begin, 2); rb_define_method(bpa_class, "write_set_begin", rb_thrift_binary_proto_write_set_begin, 2); rb_define_method(bpa_class, "write_byte", rb_thrift_binary_proto_write_byte, 1); rb_define_method(bpa_class, "write_bool", rb_thrift_binary_proto_write_bool, 1); rb_define_method(bpa_class, "write_i16", rb_thrift_binary_proto_write_i16, 1); rb_define_method(bpa_class, "write_i32", rb_thrift_binary_proto_write_i32, 1); rb_define_method(bpa_class, "write_i64", rb_thrift_binary_proto_write_i64, 1); rb_define_method(bpa_class, "write_double", rb_thrift_binary_proto_write_double, 1); rb_define_method(bpa_class, "write_string", rb_thrift_binary_proto_write_string, 1); rb_define_method(bpa_class, "write_binary", rb_thrift_binary_proto_write_binary, 1); // unused methods rb_define_method(bpa_class, "write_message_end", rb_thrift_binary_proto_write_message_end, 0); rb_define_method(bpa_class, "write_struct_begin", rb_thrift_binary_proto_write_struct_begin, 1); rb_define_method(bpa_class, "write_struct_end", rb_thrift_binary_proto_write_struct_end, 0); rb_define_method(bpa_class, "write_field_end", rb_thrift_binary_proto_write_field_end, 0); rb_define_method(bpa_class, "write_map_end", rb_thrift_binary_proto_write_map_end, 0); rb_define_method(bpa_class, "write_list_end", rb_thrift_binary_proto_write_list_end, 0); rb_define_method(bpa_class, "write_set_end", rb_thrift_binary_proto_write_set_end, 0); rb_define_method(bpa_class, "read_message_begin", rb_thrift_binary_proto_read_message_begin, 0); rb_define_method(bpa_class, "read_field_begin", rb_thrift_binary_proto_read_field_begin, 0); rb_define_method(bpa_class, "read_map_begin", rb_thrift_binary_proto_read_map_begin, 0); rb_define_method(bpa_class, "read_list_begin", rb_thrift_binary_proto_read_list_begin, 0); rb_define_method(bpa_class, "read_set_begin", rb_thrift_binary_proto_read_set_begin, 0); rb_define_method(bpa_class, "read_byte", rb_thrift_binary_proto_read_byte, 0); rb_define_method(bpa_class, "read_bool", rb_thrift_binary_proto_read_bool, 0); rb_define_method(bpa_class, "read_i16", rb_thrift_binary_proto_read_i16, 0); rb_define_method(bpa_class, "read_i32", rb_thrift_binary_proto_read_i32, 0); rb_define_method(bpa_class, "read_i64", rb_thrift_binary_proto_read_i64, 0); rb_define_method(bpa_class, "read_double", rb_thrift_binary_proto_read_double, 0); rb_define_method(bpa_class, "read_string", rb_thrift_binary_proto_read_string, 0); rb_define_method(bpa_class, "read_binary", rb_thrift_binary_proto_read_binary, 0); // unused methods rb_define_method(bpa_class, "read_message_end", rb_thrift_binary_proto_read_message_end, 0); rb_define_method(bpa_class, "read_struct_begin", rb_thrift_binary_proto_read_struct_begin, 0); rb_define_method(bpa_class, "read_struct_end", rb_thrift_binary_proto_read_struct_end, 0); rb_define_method(bpa_class, "read_field_end", rb_thrift_binary_proto_read_field_end, 0); rb_define_method(bpa_class, "read_map_end", rb_thrift_binary_proto_read_map_end, 0); rb_define_method(bpa_class, "read_list_end", rb_thrift_binary_proto_read_list_end, 0); rb_define_method(bpa_class, "read_set_end", rb_thrift_binary_proto_read_set_end, 0); rbuf_ivar_id = rb_intern("@rbuf"); } thrift-0.19.0/lib/rb/ext/struct.c0000644000000000000000000005402514303740367016555 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "struct.h" #include "constants.h" #include "macros.h" #include "strlcpy.h" VALUE thrift_union_class; ID setfield_id; ID setvalue_id; ID to_s_method_id; ID name_to_id_method_id; static ID sorted_field_ids_method_id; #define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET) #define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id) //------------------------------------------- // Writing section //------------------------------------------- // default fn pointers for protocol stuff here VALUE default_write_bool(VALUE protocol, VALUE value) { rb_funcall(protocol, write_boolean_method_id, 1, value); return Qnil; } VALUE default_write_byte(VALUE protocol, VALUE value) { rb_funcall(protocol, write_byte_method_id, 1, value); return Qnil; } VALUE default_write_i16(VALUE protocol, VALUE value) { rb_funcall(protocol, write_i16_method_id, 1, value); return Qnil; } VALUE default_write_i32(VALUE protocol, VALUE value) { rb_funcall(protocol, write_i32_method_id, 1, value); return Qnil; } VALUE default_write_i64(VALUE protocol, VALUE value) { rb_funcall(protocol, write_i64_method_id, 1, value); return Qnil; } VALUE default_write_double(VALUE protocol, VALUE value) { rb_funcall(protocol, write_double_method_id, 1, value); return Qnil; } VALUE default_write_string(VALUE protocol, VALUE value) { rb_funcall(protocol, write_string_method_id, 1, value); return Qnil; } VALUE default_write_binary(VALUE protocol, VALUE value) { rb_funcall(protocol, write_binary_method_id, 1, value); return Qnil; } VALUE default_write_list_begin(VALUE protocol, VALUE etype, VALUE length) { rb_funcall(protocol, write_list_begin_method_id, 2, etype, length); return Qnil; } VALUE default_write_list_end(VALUE protocol) { rb_funcall(protocol, write_list_end_method_id, 0); return Qnil; } VALUE default_write_set_begin(VALUE protocol, VALUE etype, VALUE length) { rb_funcall(protocol, write_set_begin_method_id, 2, etype, length); return Qnil; } VALUE default_write_set_end(VALUE protocol) { rb_funcall(protocol, write_set_end_method_id, 0); return Qnil; } VALUE default_write_map_begin(VALUE protocol, VALUE ktype, VALUE vtype, VALUE length) { rb_funcall(protocol, write_map_begin_method_id, 3, ktype, vtype, length); return Qnil; } VALUE default_write_map_end(VALUE protocol) { rb_funcall(protocol, write_map_end_method_id, 0); return Qnil; } VALUE default_write_struct_begin(VALUE protocol, VALUE struct_name) { rb_funcall(protocol, write_struct_begin_method_id, 1, struct_name); return Qnil; } VALUE default_write_struct_end(VALUE protocol) { rb_funcall(protocol, write_struct_end_method_id, 0); return Qnil; } VALUE default_write_field_begin(VALUE protocol, VALUE name, VALUE type, VALUE id) { rb_funcall(protocol, write_field_begin_method_id, 3, name, type, id); return Qnil; } VALUE default_write_field_end(VALUE protocol) { rb_funcall(protocol, write_field_end_method_id, 0); return Qnil; } VALUE default_write_field_stop(VALUE protocol) { rb_funcall(protocol, write_field_stop_method_id, 0); return Qnil; } VALUE default_read_field_begin(VALUE protocol) { return rb_funcall(protocol, read_field_begin_method_id, 0); } VALUE default_read_field_end(VALUE protocol) { return rb_funcall(protocol, read_field_end_method_id, 0); } VALUE default_read_map_begin(VALUE protocol) { return rb_funcall(protocol, read_map_begin_method_id, 0); } VALUE default_read_map_end(VALUE protocol) { return rb_funcall(protocol, read_map_end_method_id, 0); } VALUE default_read_list_begin(VALUE protocol) { return rb_funcall(protocol, read_list_begin_method_id, 0); } VALUE default_read_list_end(VALUE protocol) { return rb_funcall(protocol, read_list_end_method_id, 0); } VALUE default_read_set_begin(VALUE protocol) { return rb_funcall(protocol, read_set_begin_method_id, 0); } VALUE default_read_set_end(VALUE protocol) { return rb_funcall(protocol, read_set_end_method_id, 0); } VALUE default_read_byte(VALUE protocol) { return rb_funcall(protocol, read_byte_method_id, 0); } VALUE default_read_bool(VALUE protocol) { return rb_funcall(protocol, read_bool_method_id, 0); } VALUE default_read_i16(VALUE protocol) { return rb_funcall(protocol, read_i16_method_id, 0); } VALUE default_read_i32(VALUE protocol) { return rb_funcall(protocol, read_i32_method_id, 0); } VALUE default_read_i64(VALUE protocol) { return rb_funcall(protocol, read_i64_method_id, 0); } VALUE default_read_double(VALUE protocol) { return rb_funcall(protocol, read_double_method_id, 0); } VALUE default_read_string(VALUE protocol) { return rb_funcall(protocol, read_string_method_id, 0); } VALUE default_read_binary(VALUE protocol) { return rb_funcall(protocol, read_binary_method_id, 0); } VALUE default_read_struct_begin(VALUE protocol) { return rb_funcall(protocol, read_struct_begin_method_id, 0); } VALUE default_read_struct_end(VALUE protocol) { return rb_funcall(protocol, read_struct_end_method_id, 0); } // end default protocol methods static VALUE rb_thrift_union_write (VALUE self, VALUE protocol); static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol); static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info); VALUE get_field_value(VALUE obj, VALUE field_name) { char name_buf[RSTRING_LEN(field_name) + 2]; name_buf[0] = '@'; strlcpy(&name_buf[1], RSTRING_PTR(field_name), RSTRING_LEN(field_name) + 1); VALUE value = rb_ivar_get(obj, rb_intern(name_buf)); return value; } static void write_container(int ttype, VALUE field_info, VALUE value, VALUE protocol) { int sz, i; if (ttype == TTYPE_MAP) { VALUE keys; VALUE key; VALUE val; Check_Type(value, T_HASH); VALUE key_info = rb_hash_aref(field_info, key_sym); VALUE keytype_value = rb_hash_aref(key_info, type_sym); int keytype = FIX2INT(keytype_value); VALUE value_info = rb_hash_aref(field_info, value_sym); VALUE valuetype_value = rb_hash_aref(value_info, type_sym); int valuetype = FIX2INT(valuetype_value); keys = rb_funcall(value, keys_method_id, 0); sz = RARRAY_LEN(keys); default_write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz)); for (i = 0; i < sz; i++) { key = rb_ary_entry(keys, i); val = rb_hash_aref(value, key); if (IS_CONTAINER(keytype)) { write_container(keytype, key_info, key, protocol); } else { write_anything(keytype, key, protocol, key_info); } if (IS_CONTAINER(valuetype)) { write_container(valuetype, value_info, val, protocol); } else { write_anything(valuetype, val, protocol, value_info); } } default_write_map_end(protocol); } else if (ttype == TTYPE_LIST) { Check_Type(value, T_ARRAY); sz = RARRAY_LEN(value); VALUE element_type_info = rb_hash_aref(field_info, element_sym); VALUE element_type_value = rb_hash_aref(element_type_info, type_sym); int element_type = FIX2INT(element_type_value); default_write_list_begin(protocol, element_type_value, INT2FIX(sz)); for (i = 0; i < sz; ++i) { VALUE val = rb_ary_entry(value, i); if (IS_CONTAINER(element_type)) { write_container(element_type, element_type_info, val, protocol); } else { write_anything(element_type, val, protocol, element_type_info); } } default_write_list_end(protocol); } else if (ttype == TTYPE_SET) { VALUE items; if (TYPE(value) == T_ARRAY) { items = value; } else { if (rb_cSet == CLASS_OF(value)) { items = rb_funcall(value, entries_method_id, 0); } else { Check_Type(value, T_HASH); items = rb_funcall(value, keys_method_id, 0); } } sz = RARRAY_LEN(items); VALUE element_type_info = rb_hash_aref(field_info, element_sym); VALUE element_type_value = rb_hash_aref(element_type_info, type_sym); int element_type = FIX2INT(element_type_value); default_write_set_begin(protocol, element_type_value, INT2FIX(sz)); for (i = 0; i < sz; i++) { VALUE val = rb_ary_entry(items, i); if (IS_CONTAINER(element_type)) { write_container(element_type, element_type_info, val, protocol); } else { write_anything(element_type, val, protocol, element_type_info); } } default_write_set_end(protocol); } else { rb_raise(rb_eNotImpError, "can't write container of type: %d", ttype); } } static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info) { if (ttype == TTYPE_BOOL) { default_write_bool(protocol, value); } else if (ttype == TTYPE_BYTE) { default_write_byte(protocol, value); } else if (ttype == TTYPE_I16) { default_write_i16(protocol, value); } else if (ttype == TTYPE_I32) { default_write_i32(protocol, value); } else if (ttype == TTYPE_I64) { default_write_i64(protocol, value); } else if (ttype == TTYPE_DOUBLE) { default_write_double(protocol, value); } else if (ttype == TTYPE_STRING) { VALUE is_binary = rb_hash_aref(field_info, binary_sym); if (is_binary != Qtrue) { default_write_string(protocol, value); } else { default_write_binary(protocol, value); } } else if (IS_CONTAINER(ttype)) { write_container(ttype, field_info, value, protocol); } else if (ttype == TTYPE_STRUCT) { if (rb_obj_is_kind_of(value, thrift_union_class)) { rb_thrift_union_write(value, protocol); } else { rb_thrift_struct_write(value, protocol); } } else { rb_raise(rb_eNotImpError, "Unknown type for binary_encoding: %d", ttype); } } static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) { // call validate rb_funcall(self, validate_method_id, 0); // write struct begin default_write_struct_begin(protocol, rb_class_name(CLASS_OF(self))); // iterate through all the fields here VALUE struct_fields = STRUCT_FIELDS(self); VALUE sorted_field_ids = rb_funcall(self, sorted_field_ids_method_id, 0); int i = 0; for (i=0; i < RARRAY_LEN(sorted_field_ids); i++) { VALUE field_id = rb_ary_entry(sorted_field_ids, i); VALUE field_info = rb_hash_aref(struct_fields, field_id); VALUE ttype_value = rb_hash_aref(field_info, type_sym); int ttype = FIX2INT(ttype_value); VALUE field_name = rb_hash_aref(field_info, name_sym); VALUE field_value = get_field_value(self, field_name); if (!NIL_P(field_value)) { default_write_field_begin(protocol, field_name, ttype_value, field_id); write_anything(ttype, field_value, protocol, field_info); default_write_field_end(protocol); } } default_write_field_stop(protocol); // write struct end default_write_struct_end(protocol); return Qnil; } //------------------------------------------- // Reading section //------------------------------------------- static VALUE rb_thrift_union_read(VALUE self, VALUE protocol); static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol); static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size); static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size); static void set_field_value(VALUE obj, VALUE field_name, VALUE value) { char name_buf[RSTRING_LEN(field_name) + 2]; name_buf[0] = '@'; strlcpy(&name_buf[1], RSTRING_PTR(field_name), RSTRING_LEN(field_name)+1); rb_ivar_set(obj, rb_intern(name_buf), value); } // Helper method to skip the contents of a map (assumes the map header has been read). static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size) { int i; for (i = 0; i < size; i++) { rb_funcall(protocol, skip_method_id, 1, key_type_value); rb_funcall(protocol, skip_method_id, 1, value_type_value); } } // Helper method to skip the contents of a list or set (assumes the list/set header has been read). static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size) { int i; for (i = 0; i < size; i++) { rb_funcall(protocol, skip_method_id, 1, element_type_value); } } static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) { VALUE result = Qnil; if (ttype == TTYPE_BOOL) { result = default_read_bool(protocol); } else if (ttype == TTYPE_BYTE) { result = default_read_byte(protocol); } else if (ttype == TTYPE_I16) { result = default_read_i16(protocol); } else if (ttype == TTYPE_I32) { result = default_read_i32(protocol); } else if (ttype == TTYPE_I64) { result = default_read_i64(protocol); } else if (ttype == TTYPE_STRING) { VALUE is_binary = rb_hash_aref(field_info, binary_sym); if (is_binary != Qtrue) { result = default_read_string(protocol); } else { result = default_read_binary(protocol); } } else if (ttype == TTYPE_DOUBLE) { result = default_read_double(protocol); } else if (ttype == TTYPE_STRUCT) { VALUE klass = rb_hash_aref(field_info, class_sym); result = rb_class_new_instance(0, NULL, klass); if (rb_obj_is_kind_of(result, thrift_union_class)) { rb_thrift_union_read(result, protocol); } else { rb_thrift_struct_read(result, protocol); } } else if (ttype == TTYPE_MAP) { int i; VALUE map_header = default_read_map_begin(protocol); int key_ttype = FIX2INT(rb_ary_entry(map_header, 0)); int value_ttype = FIX2INT(rb_ary_entry(map_header, 1)); int num_entries = FIX2INT(rb_ary_entry(map_header, 2)); // Check the declared key and value types against the expected ones and skip the map contents // if the types don't match. VALUE key_info = rb_hash_aref(field_info, key_sym); VALUE value_info = rb_hash_aref(field_info, value_sym); if (!NIL_P(key_info) && !NIL_P(value_info)) { int specified_key_type = FIX2INT(rb_hash_aref(key_info, type_sym)); int specified_value_type = FIX2INT(rb_hash_aref(value_info, type_sym)); if (num_entries == 0 || (specified_key_type == key_ttype && specified_value_type == value_ttype)) { result = rb_hash_new(); for (i = 0; i < num_entries; ++i) { VALUE key, val; key = read_anything(protocol, key_ttype, key_info); val = read_anything(protocol, value_ttype, value_info); rb_hash_aset(result, key, val); } } else { skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries); } } else { skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries); } default_read_map_end(protocol); } else if (ttype == TTYPE_LIST) { int i; VALUE list_header = default_read_list_begin(protocol); int element_ttype = FIX2INT(rb_ary_entry(list_header, 0)); int num_elements = FIX2INT(rb_ary_entry(list_header, 1)); // Check the declared element type against the expected one and skip the list contents // if the types don't match. VALUE element_info = rb_hash_aref(field_info, element_sym); if (!NIL_P(element_info)) { int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym)); if (specified_element_type == element_ttype) { result = rb_ary_new2(num_elements); for (i = 0; i < num_elements; ++i) { rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym))); } } else { skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); } } else { skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); } default_read_list_end(protocol); } else if (ttype == TTYPE_SET) { VALUE items; int i; VALUE set_header = default_read_set_begin(protocol); int element_ttype = FIX2INT(rb_ary_entry(set_header, 0)); int num_elements = FIX2INT(rb_ary_entry(set_header, 1)); // Check the declared element type against the expected one and skip the set contents // if the types don't match. VALUE element_info = rb_hash_aref(field_info, element_sym); if (!NIL_P(element_info)) { int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym)); if (specified_element_type == element_ttype) { items = rb_ary_new2(num_elements); for (i = 0; i < num_elements; ++i) { rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym))); } result = rb_class_new_instance(1, &items, rb_cSet); } else { skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); } } else { skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements); } default_read_set_end(protocol); } else { rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype); } return result; } static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol) { // read struct begin default_read_struct_begin(protocol); VALUE struct_fields = STRUCT_FIELDS(self); // read each field while (true) { VALUE field_header = default_read_field_begin(protocol); VALUE field_type_value = rb_ary_entry(field_header, 1); int field_type = FIX2INT(field_type_value); if (field_type == TTYPE_STOP) { break; } // make sure we got a type we expected VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2)); if (!NIL_P(field_info)) { int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym)); if (field_type == specified_type) { // read the value VALUE name = rb_hash_aref(field_info, name_sym); set_field_value(self, name, read_anything(protocol, field_type, field_info)); } else { rb_funcall(protocol, skip_method_id, 1, field_type_value); } } else { rb_funcall(protocol, skip_method_id, 1, field_type_value); } // read field end default_read_field_end(protocol); } // read struct end default_read_struct_end(protocol); // call validate rb_funcall(self, validate_method_id, 0); return Qnil; } // -------------------------------- // Union section // -------------------------------- static VALUE rb_thrift_union_read(VALUE self, VALUE protocol) { // read struct begin default_read_struct_begin(protocol); VALUE struct_fields = STRUCT_FIELDS(self); VALUE field_header = default_read_field_begin(protocol); VALUE field_type_value = rb_ary_entry(field_header, 1); int field_type = FIX2INT(field_type_value); // make sure we got a type we expected VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2)); if (!NIL_P(field_info)) { int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym)); if (field_type == specified_type) { // read the value VALUE name = rb_hash_aref(field_info, name_sym); rb_iv_set(self, "@setfield", rb_str_intern(name)); rb_iv_set(self, "@value", read_anything(protocol, field_type, field_info)); } else { rb_funcall(protocol, skip_method_id, 1, field_type_value); } } else { rb_funcall(protocol, skip_method_id, 1, field_type_value); } // read field end default_read_field_end(protocol); field_header = default_read_field_begin(protocol); field_type_value = rb_ary_entry(field_header, 1); field_type = FIX2INT(field_type_value); if (field_type != TTYPE_STOP) { rb_raise(rb_eRuntimeError, "too many fields in union!"); } // read struct end default_read_struct_end(protocol); // call validate rb_funcall(self, validate_method_id, 0); return Qnil; } static VALUE rb_thrift_union_write(VALUE self, VALUE protocol) { // call validate rb_funcall(self, validate_method_id, 0); // write struct begin default_write_struct_begin(protocol, rb_class_name(CLASS_OF(self))); VALUE struct_fields = STRUCT_FIELDS(self); VALUE setfield = rb_ivar_get(self, setfield_id); VALUE setvalue = rb_ivar_get(self, setvalue_id); VALUE field_id = rb_funcall(self, name_to_id_method_id, 1, rb_funcall(setfield, to_s_method_id, 0)); VALUE field_info = rb_hash_aref(struct_fields, field_id); if(NIL_P(field_info)) { rb_raise(rb_eRuntimeError, "set_field is not valid for this union!"); } VALUE ttype_value = rb_hash_aref(field_info, type_sym); int ttype = FIX2INT(ttype_value); default_write_field_begin(protocol, setfield, ttype_value, field_id); write_anything(ttype, setvalue, protocol, field_info); default_write_field_end(protocol); default_write_field_stop(protocol); // write struct end default_write_struct_end(protocol); return Qnil; } void Init_struct() { VALUE struct_module = rb_const_get(thrift_module, rb_intern("Struct")); rb_define_method(struct_module, "write", rb_thrift_struct_write, 1); rb_define_method(struct_module, "read", rb_thrift_struct_read, 1); thrift_union_class = rb_const_get(thrift_module, rb_intern("Union")); rb_global_variable(&thrift_union_class); rb_define_method(thrift_union_class, "write", rb_thrift_union_write, 1); rb_define_method(thrift_union_class, "read", rb_thrift_union_read, 1); setfield_id = rb_intern("@setfield"); rb_global_variable(&setfield_id); setvalue_id = rb_intern("@value"); rb_global_variable(&setvalue_id); to_s_method_id = rb_intern("to_s"); rb_global_variable(&to_s_method_id); name_to_id_method_id = rb_intern("name_to_id"); rb_global_variable(&name_to_id_method_id); sorted_field_ids_method_id = rb_intern("sorted_field_ids"); rb_global_variable(&sorted_field_ids_method_id); } thrift-0.19.0/lib/rb/ext/compact_protocol.c0000644000000000000000000005500414303740367020576 0ustar00rootroot00000000000000/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #define LAST_ID(obj) FIX2INT(rb_ary_pop(rb_ivar_get(obj, last_field_id))) #define SET_LAST_ID(obj, val) rb_ary_push(rb_ivar_get(obj, last_field_id), val) VALUE rb_thrift_compact_proto_native_qmark(VALUE self) { return Qtrue; } static ID last_field_id; static ID boolean_field_id; static ID bool_value_id; static ID rbuf_ivar_id; static int VERSION; static int VERSION_MASK; static int TYPE_MASK; static int TYPE_BITS; static int TYPE_SHIFT_AMOUNT; static int PROTOCOL_ID; static VALUE thrift_compact_protocol_class; static int CTYPE_BOOLEAN_TRUE = 0x01; static int CTYPE_BOOLEAN_FALSE = 0x02; static int CTYPE_BYTE = 0x03; static int CTYPE_I16 = 0x04; static int CTYPE_I32 = 0x05; static int CTYPE_I64 = 0x06; static int CTYPE_DOUBLE = 0x07; static int CTYPE_BINARY = 0x08; static int CTYPE_LIST = 0x09; static int CTYPE_SET = 0x0A; static int CTYPE_MAP = 0x0B; static int CTYPE_STRUCT = 0x0C; VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16); // TODO: implement this static int get_compact_type(VALUE type_value) { int type = FIX2INT(type_value); if (type == TTYPE_BOOL) { return CTYPE_BOOLEAN_TRUE; } else if (type == TTYPE_BYTE) { return CTYPE_BYTE; } else if (type == TTYPE_I16) { return CTYPE_I16; } else if (type == TTYPE_I32) { return CTYPE_I32; } else if (type == TTYPE_I64) { return CTYPE_I64; } else if (type == TTYPE_DOUBLE) { return CTYPE_DOUBLE; } else if (type == TTYPE_STRING) { return CTYPE_BINARY; } else if (type == TTYPE_LIST) { return CTYPE_LIST; } else if (type == TTYPE_SET) { return CTYPE_SET; } else if (type == TTYPE_MAP) { return CTYPE_MAP; } else if (type == TTYPE_STRUCT) { return CTYPE_STRUCT; } else { char str[50]; sprintf(str, "don't know what type: %d", type); rb_raise(rb_eStandardError, "%s", str); return 0; } } static void write_byte_direct(VALUE transport, int8_t b) { WRITE(transport, (char*)&b, 1); } static void write_field_begin_internal(VALUE self, VALUE type, VALUE id_value, VALUE type_override) { int id = FIX2INT(id_value); int last_id = LAST_ID(self); VALUE transport = GET_TRANSPORT(self); // if there's a type override, use that. int8_t type_to_write = RTEST(type_override) ? FIX2INT(type_override) : get_compact_type(type); // check if we can use delta encoding for the field id int diff = id - last_id; if (diff > 0 && diff <= 15) { // write them together write_byte_direct(transport, diff << 4 | (type_to_write & 0x0f)); } else { // write them separate write_byte_direct(transport, type_to_write & 0x0f); rb_thrift_compact_proto_write_i16(self, id_value); } SET_LAST_ID(self, id_value); } static int32_t int_to_zig_zag(int32_t n) { return (n << 1) ^ (n >> 31); } static uint64_t ll_to_zig_zag(int64_t n) { return (n << 1) ^ (n >> 63); } static void write_varint32(VALUE transport, uint32_t n) { while (true) { if ((n & ~0x7F) == 0) { write_byte_direct(transport, n & 0x7f); break; } else { write_byte_direct(transport, (n & 0x7F) | 0x80); n = n >> 7; } } } static void write_varint64(VALUE transport, uint64_t n) { while (true) { if ((n & ~0x7F) == 0) { write_byte_direct(transport, n & 0x7f); break; } else { write_byte_direct(transport, (n & 0x7F) | 0x80); n = n >> 7; } } } static void write_collection_begin(VALUE transport, VALUE elem_type, VALUE size_value) { int size = FIX2INT(size_value); if (size <= 14) { write_byte_direct(transport, size << 4 | get_compact_type(elem_type)); } else { write_byte_direct(transport, 0xf0 | get_compact_type(elem_type)); write_varint32(transport, size); } } //-------------------------------- // interface writing methods //-------------------------------- VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32); VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str); VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf); VALUE rb_thrift_compact_proto_write_message_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_write_struct_begin(VALUE self, VALUE name) { rb_ary_push(rb_ivar_get(self, last_field_id), INT2FIX(0)); return Qnil; } VALUE rb_thrift_compact_proto_write_struct_end(VALUE self) { rb_ary_pop(rb_ivar_get(self, last_field_id)); return Qnil; } VALUE rb_thrift_compact_proto_write_field_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_write_map_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_write_list_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_write_set_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE type, VALUE seqid) { VALUE transport = GET_TRANSPORT(self); write_byte_direct(transport, PROTOCOL_ID); write_byte_direct(transport, (VERSION & VERSION_MASK) | ((FIX2INT(type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); write_varint32(transport, FIX2INT(seqid)); rb_thrift_compact_proto_write_string(self, name); return Qnil; } VALUE rb_thrift_compact_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) { if (FIX2INT(type) == TTYPE_BOOL) { // we want to possibly include the value, so we'll wait. rb_ivar_set(self, boolean_field_id, rb_ary_new3(2, type, id)); } else { write_field_begin_internal(self, type, id, Qnil); } return Qnil; } VALUE rb_thrift_compact_proto_write_field_stop(VALUE self) { write_byte_direct(GET_TRANSPORT(self), TTYPE_STOP); return Qnil; } VALUE rb_thrift_compact_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size_value) { int size = FIX2INT(size_value); VALUE transport = GET_TRANSPORT(self); if (size == 0) { write_byte_direct(transport, 0); } else { write_varint32(transport, size); write_byte_direct(transport, get_compact_type(ktype) << 4 | get_compact_type(vtype)); } return Qnil; } VALUE rb_thrift_compact_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) { write_collection_begin(GET_TRANSPORT(self), etype, size); return Qnil; } VALUE rb_thrift_compact_proto_write_set_begin(VALUE self, VALUE etype, VALUE size) { write_collection_begin(GET_TRANSPORT(self), etype, size); return Qnil; } VALUE rb_thrift_compact_proto_write_bool(VALUE self, VALUE b) { int8_t type = b == Qtrue ? CTYPE_BOOLEAN_TRUE : CTYPE_BOOLEAN_FALSE; VALUE boolean_field = rb_ivar_get(self, boolean_field_id); if (NIL_P(boolean_field)) { // we're not part of a field, so just write the value. write_byte_direct(GET_TRANSPORT(self), type); } else { // we haven't written the field header yet write_field_begin_internal(self, rb_ary_entry(boolean_field, 0), rb_ary_entry(boolean_field, 1), INT2FIX(type)); rb_ivar_set(self, boolean_field_id, Qnil); } return Qnil; } VALUE rb_thrift_compact_proto_write_byte(VALUE self, VALUE byte) { CHECK_NIL(byte); write_byte_direct(GET_TRANSPORT(self), FIX2INT(byte)); return Qnil; } VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16) { rb_thrift_compact_proto_write_i32(self, i16); return Qnil; } VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32) { CHECK_NIL(i32); write_varint32(GET_TRANSPORT(self), int_to_zig_zag(NUM2INT(i32))); return Qnil; } VALUE rb_thrift_compact_proto_write_i64(VALUE self, VALUE i64) { CHECK_NIL(i64); write_varint64(GET_TRANSPORT(self), ll_to_zig_zag(NUM2LL(i64))); return Qnil; } VALUE rb_thrift_compact_proto_write_double(VALUE self, VALUE dub) { CHECK_NIL(dub); // Unfortunately, bitwise_cast doesn't work in C. Bad C! union { double f; int64_t l; } transfer; transfer.f = RFLOAT_VALUE(rb_Float(dub)); char buf[8]; buf[0] = transfer.l & 0xff; buf[1] = (transfer.l >> 8) & 0xff; buf[2] = (transfer.l >> 16) & 0xff; buf[3] = (transfer.l >> 24) & 0xff; buf[4] = (transfer.l >> 32) & 0xff; buf[5] = (transfer.l >> 40) & 0xff; buf[6] = (transfer.l >> 48) & 0xff; buf[7] = (transfer.l >> 56) & 0xff; WRITE(GET_TRANSPORT(self), buf, 8); return Qnil; } VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str) { str = convert_to_utf8_byte_buffer(str); rb_thrift_compact_proto_write_binary(self, str); return Qnil; } VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf) { buf = force_binary_encoding(buf); VALUE transport = GET_TRANSPORT(self); write_varint32(transport, RSTRING_LEN(buf)); WRITE(transport, StringValuePtr(buf), RSTRING_LEN(buf)); return Qnil; } //--------------------------------------- // interface reading methods //--------------------------------------- #define is_bool_type(ctype) (((ctype) & 0x0F) == CTYPE_BOOLEAN_TRUE || ((ctype) & 0x0F) == CTYPE_BOOLEAN_FALSE) VALUE rb_thrift_compact_proto_read_string(VALUE self); VALUE rb_thrift_compact_proto_read_binary(VALUE self); VALUE rb_thrift_compact_proto_read_byte(VALUE self); VALUE rb_thrift_compact_proto_read_i32(VALUE self); VALUE rb_thrift_compact_proto_read_i16(VALUE self); static int8_t get_ttype(int8_t ctype) { if (ctype == TTYPE_STOP) { return TTYPE_STOP; } else if (ctype == CTYPE_BOOLEAN_TRUE || ctype == CTYPE_BOOLEAN_FALSE) { return TTYPE_BOOL; } else if (ctype == CTYPE_BYTE) { return TTYPE_BYTE; } else if (ctype == CTYPE_I16) { return TTYPE_I16; } else if (ctype == CTYPE_I32) { return TTYPE_I32; } else if (ctype == CTYPE_I64) { return TTYPE_I64; } else if (ctype == CTYPE_DOUBLE) { return TTYPE_DOUBLE; } else if (ctype == CTYPE_BINARY) { return TTYPE_STRING; } else if (ctype == CTYPE_LIST) { return TTYPE_LIST; } else if (ctype == CTYPE_SET) { return TTYPE_SET; } else if (ctype == CTYPE_MAP) { return TTYPE_MAP; } else if (ctype == CTYPE_STRUCT) { return TTYPE_STRUCT; } else { char str[50]; sprintf(str, "don't know what type: %d", ctype); rb_raise(rb_eStandardError, "%s", str); return 0; } } static char read_byte_direct(VALUE self) { VALUE byte = rb_funcall(GET_TRANSPORT(self), read_byte_method_id, 0); return (char)(FIX2INT(byte)); } static int64_t zig_zag_to_ll(int64_t n) { return (((uint64_t)n) >> 1) ^ -(n & 1); } static int32_t zig_zag_to_int(int32_t n) { return (((uint32_t)n) >> 1) ^ -(n & 1); } static int64_t read_varint64(VALUE self) { int shift = 0; int64_t result = 0; while (true) { int8_t b = read_byte_direct(self); result = result | ((uint64_t)(b & 0x7f) << shift); if ((b & 0x80) != 0x80) { break; } shift += 7; } return result; } static int16_t read_i16(VALUE self) { return zig_zag_to_int((int32_t)read_varint64(self)); } static VALUE get_protocol_exception(VALUE code, VALUE message) { VALUE args[2]; args[0] = code; args[1] = message; return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class); } VALUE rb_thrift_compact_proto_read_message_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_read_struct_begin(VALUE self) { rb_ary_push(rb_ivar_get(self, last_field_id), INT2FIX(0)); return Qnil; } VALUE rb_thrift_compact_proto_read_struct_end(VALUE self) { rb_ary_pop(rb_ivar_get(self, last_field_id)); return Qnil; } VALUE rb_thrift_compact_proto_read_field_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_read_map_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_read_list_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_read_set_end(VALUE self) { return Qnil; } VALUE rb_thrift_compact_proto_read_message_begin(VALUE self) { int8_t protocol_id = read_byte_direct(self); if (protocol_id != PROTOCOL_ID) { char buf[100]; int len = sprintf(buf, "Expected protocol id %d but got %d", PROTOCOL_ID, protocol_id); buf[len] = 0; rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf))); } int8_t version_and_type = read_byte_direct(self); int8_t version = version_and_type & VERSION_MASK; if (version != VERSION) { char buf[100]; int len = sprintf(buf, "Expected version id %d but got %d", version, VERSION); buf[len] = 0; rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf))); } int8_t type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS; int32_t seqid = read_varint64(self); VALUE messageName = rb_thrift_compact_proto_read_string(self); return rb_ary_new3(3, messageName, INT2FIX(type), INT2NUM(seqid)); } VALUE rb_thrift_compact_proto_read_field_begin(VALUE self) { int8_t type = read_byte_direct(self); // if it's a stop, then we can return immediately, as the struct is over. if ((type & 0x0f) == TTYPE_STOP) { return rb_ary_new3(3, Qnil, INT2FIX(0), INT2FIX(0)); } else { int field_id = 0; // mask off the 4 MSB of the type header. it could contain a field id delta. uint8_t modifier = ((type & 0xf0) >> 4); if (modifier == 0) { // not a delta. look ahead for the zigzag varint field id. (void) LAST_ID(self); field_id = read_i16(self); } else { // has a delta. add the delta to the last read field id. field_id = LAST_ID(self) + modifier; } // if this happens to be a boolean field, the value is encoded in the type if (is_bool_type(type)) { // save the boolean value in a special instance variable. rb_ivar_set(self, bool_value_id, (type & 0x0f) == CTYPE_BOOLEAN_TRUE ? Qtrue : Qfalse); } // push the new field onto the field stack so we can keep the deltas going. SET_LAST_ID(self, INT2FIX(field_id)); return rb_ary_new3(3, Qnil, INT2FIX(get_ttype(type & 0x0f)), INT2FIX(field_id)); } } VALUE rb_thrift_compact_proto_read_map_begin(VALUE self) { int32_t size = read_varint64(self); uint8_t key_and_value_type = size == 0 ? 0 : read_byte_direct(self); return rb_ary_new3(3, INT2FIX(get_ttype(key_and_value_type >> 4)), INT2FIX(get_ttype(key_and_value_type & 0xf)), INT2FIX(size)); } VALUE rb_thrift_compact_proto_read_list_begin(VALUE self) { uint8_t size_and_type = read_byte_direct(self); int32_t size = (size_and_type >> 4) & 0x0f; if (size == 15) { size = read_varint64(self); } uint8_t type = get_ttype(size_and_type & 0x0f); return rb_ary_new3(2, INT2FIX(type), INT2FIX(size)); } VALUE rb_thrift_compact_proto_read_set_begin(VALUE self) { return rb_thrift_compact_proto_read_list_begin(self); } VALUE rb_thrift_compact_proto_read_bool(VALUE self) { VALUE bool_value = rb_ivar_get(self, bool_value_id); if (NIL_P(bool_value)) { return read_byte_direct(self) == CTYPE_BOOLEAN_TRUE ? Qtrue : Qfalse; } else { rb_ivar_set(self, bool_value_id, Qnil); return bool_value; } } VALUE rb_thrift_compact_proto_read_byte(VALUE self) { return INT2FIX(read_byte_direct(self)); } VALUE rb_thrift_compact_proto_read_i16(VALUE self) { return INT2FIX(read_i16(self)); } VALUE rb_thrift_compact_proto_read_i32(VALUE self) { return INT2NUM(zig_zag_to_int(read_varint64(self))); } VALUE rb_thrift_compact_proto_read_i64(VALUE self) { return LL2NUM(zig_zag_to_ll(read_varint64(self))); } VALUE rb_thrift_compact_proto_read_double(VALUE self) { union { double f; int64_t l; } transfer; VALUE rbuf = rb_ivar_get(self, rbuf_ivar_id); rb_funcall(GET_TRANSPORT(self), read_into_buffer_method_id, 2, rbuf, INT2FIX(8)); uint32_t lo = ((uint8_t)(RSTRING_PTR(rbuf)[0])) | (((uint8_t)(RSTRING_PTR(rbuf)[1])) << 8) | (((uint8_t)(RSTRING_PTR(rbuf)[2])) << 16) | (((uint8_t)(RSTRING_PTR(rbuf)[3])) << 24); uint64_t hi = (((uint8_t)(RSTRING_PTR(rbuf)[4]))) | (((uint8_t)(RSTRING_PTR(rbuf)[5])) << 8) | (((uint8_t)(RSTRING_PTR(rbuf)[6])) << 16) | (((uint8_t)(RSTRING_PTR(rbuf)[7])) << 24); transfer.l = (hi << 32) | lo; return rb_float_new(transfer.f); } VALUE rb_thrift_compact_proto_read_string(VALUE self) { VALUE buffer = rb_thrift_compact_proto_read_binary(self); return convert_to_string(buffer); } VALUE rb_thrift_compact_proto_read_binary(VALUE self) { int64_t size = read_varint64(self); return READ(self, size); } static void Init_constants() { thrift_compact_protocol_class = rb_const_get(thrift_module, rb_intern("CompactProtocol")); rb_global_variable(&thrift_compact_protocol_class); VERSION = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("VERSION"))); VERSION_MASK = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("VERSION_MASK"))); TYPE_MASK = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("TYPE_MASK"))); TYPE_BITS = rb_num2ll(rb_const_get(thrift_compact_protocol_class, rb_intern("TYPE_BITS"))); TYPE_SHIFT_AMOUNT = FIX2INT(rb_const_get(thrift_compact_protocol_class, rb_intern("TYPE_SHIFT_AMOUNT"))); PROTOCOL_ID = FIX2INT(rb_const_get(thrift_compact_protocol_class, rb_intern("PROTOCOL_ID"))); last_field_id = rb_intern("@last_field"); boolean_field_id = rb_intern("@boolean_field"); bool_value_id = rb_intern("@bool_value"); rbuf_ivar_id = rb_intern("@rbuf"); } static void Init_rb_methods() { rb_define_method(thrift_compact_protocol_class, "native?", rb_thrift_compact_proto_native_qmark, 0); rb_define_method(thrift_compact_protocol_class, "write_message_begin", rb_thrift_compact_proto_write_message_begin, 3); rb_define_method(thrift_compact_protocol_class, "write_field_begin", rb_thrift_compact_proto_write_field_begin, 3); rb_define_method(thrift_compact_protocol_class, "write_field_stop", rb_thrift_compact_proto_write_field_stop, 0); rb_define_method(thrift_compact_protocol_class, "write_map_begin", rb_thrift_compact_proto_write_map_begin, 3); rb_define_method(thrift_compact_protocol_class, "write_list_begin", rb_thrift_compact_proto_write_list_begin, 2); rb_define_method(thrift_compact_protocol_class, "write_set_begin", rb_thrift_compact_proto_write_set_begin, 2); rb_define_method(thrift_compact_protocol_class, "write_byte", rb_thrift_compact_proto_write_byte, 1); rb_define_method(thrift_compact_protocol_class, "write_bool", rb_thrift_compact_proto_write_bool, 1); rb_define_method(thrift_compact_protocol_class, "write_i16", rb_thrift_compact_proto_write_i16, 1); rb_define_method(thrift_compact_protocol_class, "write_i32", rb_thrift_compact_proto_write_i32, 1); rb_define_method(thrift_compact_protocol_class, "write_i64", rb_thrift_compact_proto_write_i64, 1); rb_define_method(thrift_compact_protocol_class, "write_double", rb_thrift_compact_proto_write_double, 1); rb_define_method(thrift_compact_protocol_class, "write_string", rb_thrift_compact_proto_write_string, 1); rb_define_method(thrift_compact_protocol_class, "write_binary", rb_thrift_compact_proto_write_binary, 1); rb_define_method(thrift_compact_protocol_class, "write_message_end", rb_thrift_compact_proto_write_message_end, 0); rb_define_method(thrift_compact_protocol_class, "write_struct_begin", rb_thrift_compact_proto_write_struct_begin, 1); rb_define_method(thrift_compact_protocol_class, "write_struct_end", rb_thrift_compact_proto_write_struct_end, 0); rb_define_method(thrift_compact_protocol_class, "write_field_end", rb_thrift_compact_proto_write_field_end, 0); rb_define_method(thrift_compact_protocol_class, "write_map_end", rb_thrift_compact_proto_write_map_end, 0); rb_define_method(thrift_compact_protocol_class, "write_list_end", rb_thrift_compact_proto_write_list_end, 0); rb_define_method(thrift_compact_protocol_class, "write_set_end", rb_thrift_compact_proto_write_set_end, 0); rb_define_method(thrift_compact_protocol_class, "read_message_begin", rb_thrift_compact_proto_read_message_begin, 0); rb_define_method(thrift_compact_protocol_class, "read_field_begin", rb_thrift_compact_proto_read_field_begin, 0); rb_define_method(thrift_compact_protocol_class, "read_map_begin", rb_thrift_compact_proto_read_map_begin, 0); rb_define_method(thrift_compact_protocol_class, "read_list_begin", rb_thrift_compact_proto_read_list_begin, 0); rb_define_method(thrift_compact_protocol_class, "read_set_begin", rb_thrift_compact_proto_read_set_begin, 0); rb_define_method(thrift_compact_protocol_class, "read_byte", rb_thrift_compact_proto_read_byte, 0); rb_define_method(thrift_compact_protocol_class, "read_bool", rb_thrift_compact_proto_read_bool, 0); rb_define_method(thrift_compact_protocol_class, "read_i16", rb_thrift_compact_proto_read_i16, 0); rb_define_method(thrift_compact_protocol_class, "read_i32", rb_thrift_compact_proto_read_i32, 0); rb_define_method(thrift_compact_protocol_class, "read_i64", rb_thrift_compact_proto_read_i64, 0); rb_define_method(thrift_compact_protocol_class, "read_double", rb_thrift_compact_proto_read_double, 0); rb_define_method(thrift_compact_protocol_class, "read_string", rb_thrift_compact_proto_read_string, 0); rb_define_method(thrift_compact_protocol_class, "read_binary", rb_thrift_compact_proto_read_binary, 0); rb_define_method(thrift_compact_protocol_class, "read_message_end", rb_thrift_compact_proto_read_message_end, 0); rb_define_method(thrift_compact_protocol_class, "read_struct_begin", rb_thrift_compact_proto_read_struct_begin, 0); rb_define_method(thrift_compact_protocol_class, "read_struct_end", rb_thrift_compact_proto_read_struct_end, 0); rb_define_method(thrift_compact_protocol_class, "read_field_end", rb_thrift_compact_proto_read_field_end, 0); rb_define_method(thrift_compact_protocol_class, "read_map_end", rb_thrift_compact_proto_read_map_end, 0); rb_define_method(thrift_compact_protocol_class, "read_list_end", rb_thrift_compact_proto_read_list_end, 0); rb_define_method(thrift_compact_protocol_class, "read_set_end", rb_thrift_compact_proto_read_set_end, 0); } void Init_compact_protocol() { Init_constants(); Init_rb_methods(); } thrift-0.19.0/lib/rb/ext/compact_protocol.h0000644000000000000000000000150314303740367020576 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ void Init_compact_protocol(); thrift-0.19.0/lib/rb/spec/0000777000000000000000000000000014370300523015203 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/spec/types_spec.rb0000644000000000000000000002033014303740367017712 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe Thrift::Types do before(:each) do Thrift.type_checking = true end after(:each) do Thrift.type_checking = false end context 'type checking' do it "should return the proper name for each type" do expect(Thrift.type_name(Thrift::Types::I16)).to eq("Types::I16") expect(Thrift.type_name(Thrift::Types::VOID)).to eq("Types::VOID") expect(Thrift.type_name(Thrift::Types::LIST)).to eq("Types::LIST") expect(Thrift.type_name(42)).to be_nil end it "should check types properly" do # lambda { Thrift.check_type(nil, Thrift::Types::STOP) }.should raise_error(Thrift::TypeError) expect { Thrift.check_type(3, {:type => Thrift::Types::STOP}, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::VOID}, :foo) }.not_to raise_error expect { Thrift.check_type(3, {:type => Thrift::Types::VOID}, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(true, {:type => Thrift::Types::BOOL}, :foo) }.not_to raise_error expect { Thrift.check_type(3, {:type => Thrift::Types::BOOL}, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(42, {:type => Thrift::Types::BYTE}, :foo) }.not_to raise_error expect { Thrift.check_type(42, {:type => Thrift::Types::I16}, :foo) }.not_to raise_error expect { Thrift.check_type(42, {:type => Thrift::Types::I32}, :foo) }.not_to raise_error expect { Thrift.check_type(42, {:type => Thrift::Types::I64}, :foo) }.not_to raise_error expect { Thrift.check_type(3.14, {:type => Thrift::Types::I32}, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(3.14, {:type => Thrift::Types::DOUBLE}, :foo) }.not_to raise_error expect { Thrift.check_type(3, {:type => Thrift::Types::DOUBLE}, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type("3", {:type => Thrift::Types::STRING}, :foo) }.not_to raise_error expect { Thrift.check_type(3, {:type => Thrift::Types::STRING}, :foo) }.to raise_error(Thrift::TypeError) hello = SpecNamespace::Hello.new expect { Thrift.check_type(hello, {:type => Thrift::Types::STRUCT, :class => SpecNamespace::Hello}, :foo) }.not_to raise_error expect { Thrift.check_type("foo", {:type => Thrift::Types::STRUCT}, :foo) }.to raise_error(Thrift::TypeError) field = {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRING}} expect { Thrift.check_type({1 => "one"}, field, :foo) }.not_to raise_error expect { Thrift.check_type([1], field, :foo) }.to raise_error(Thrift::TypeError) field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::I32}} expect { Thrift.check_type([1], field, :foo) }.not_to raise_error expect { Thrift.check_type({:foo => 1}, field, :foo) }.to raise_error(Thrift::TypeError) field = {:type => Thrift::Types::SET, :element => {:type => Thrift::Types::I32}} expect { Thrift.check_type(Set.new([1,2]), field, :foo) }.not_to raise_error expect { Thrift.check_type([1,2], field, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type({:foo => true}, field, :foo) }.to raise_error(Thrift::TypeError) end it "should error out if nil is passed and skip_types is false" do expect { Thrift.check_type(nil, {:type => Thrift::Types::BOOL}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::BYTE}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::I16}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::I32}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::I64}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::DOUBLE}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::STRING}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::STRUCT}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::LIST}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::SET}, :foo, false) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(nil, {:type => Thrift::Types::MAP}, :foo, false) }.to raise_error(Thrift::TypeError) end it "should check element types on containers" do field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::I32}} expect { Thrift.check_type([1, 2], field, :foo) }.not_to raise_error expect { Thrift.check_type([1, nil, 2], field, :foo) }.to raise_error(Thrift::TypeError) field = {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::STRING}} expect { Thrift.check_type({1 => "one", 2 => "two"}, field, :foo) }.not_to raise_error expect { Thrift.check_type({1 => "one", nil => "nil"}, field, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type({1 => nil, 2 => "two"}, field, :foo) }.to raise_error(Thrift::TypeError) field = {:type => Thrift::Types::SET, :element => {:type => Thrift::Types::I32}} expect { Thrift.check_type(Set.new([1, 2]), field, :foo) }.not_to raise_error expect { Thrift.check_type(Set.new([1, nil, 2]), field, :foo) }.to raise_error(Thrift::TypeError) expect { Thrift.check_type(Set.new([1, 2.3, 2]), field, :foo) }.to raise_error(Thrift::TypeError) field = {:type => Thrift::Types::STRUCT, :class => SpecNamespace::Hello} expect { Thrift.check_type(SpecNamespace::BoolStruct, field, :foo) }.to raise_error(Thrift::TypeError) end it "should give the Thrift::TypeError a readable message" do msg = /Expected Types::STRING, received (Integer|Fixnum) for field foo/ expect { Thrift.check_type(3, {:type => Thrift::Types::STRING}, :foo) }.to raise_error(Thrift::TypeError, msg) msg = /Expected Types::STRING, received (Integer|Fixnum) for field foo.element/ field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::STRING}} expect { Thrift.check_type([3], field, :foo) }.to raise_error(Thrift::TypeError, msg) msg = "Expected Types::I32, received NilClass for field foo.element.key" field = {:type => Thrift::Types::LIST, :element => {:type => Thrift::Types::MAP, :key => {:type => Thrift::Types::I32}, :value => {:type => Thrift::Types::I32}}} expect { Thrift.check_type([{nil => 3}], field, :foo) }.to raise_error(Thrift::TypeError, msg) msg = "Expected Types::I32, received NilClass for field foo.element.value" expect { Thrift.check_type([{1 => nil}], field, :foo) }.to raise_error(Thrift::TypeError, msg) end end end thrift-0.19.0/lib/rb/spec/union_spec.rb0000644000000000000000000001777614303740367017722 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Union' do describe Thrift::Union do it "should return nil value in unset union" do union = SpecNamespace::My_union.new expect(union.get_set_field).to eq(nil) expect(union.get_value).to eq(nil) end it "should set a field and be accessible through get_value and the named field accessor" do union = SpecNamespace::My_union.new union.integer32 = 25 expect(union.get_set_field).to eq(:integer32) expect(union.get_value).to eq(25) expect(union.integer32).to eq(25) end it "should work correctly when instantiated with static field constructors" do union = SpecNamespace::My_union.integer32(5) expect(union.get_set_field).to eq(:integer32) expect(union.integer32).to eq(5) end it "should raise for wrong set field" do union = SpecNamespace::My_union.new union.integer32 = 25 expect { union.some_characters }.to raise_error(RuntimeError, "some_characters is not union's set field.") end it "should raise for wrong set field when hash initialized and type checking is off" do Thrift.type_checking = false union = SpecNamespace::My_union.new({incorrect_field: :incorrect}) expect { Thrift::Serializer.new.serialize(union) }.to raise_error(RuntimeError, "set_field is not valid for this union!") end it "should not be equal to nil" do union = SpecNamespace::My_union.new expect(union).not_to eq(nil) end it "should not be equal with an empty String" do union = SpecNamespace::My_union.new expect(union).not_to eq('') end it "should not equate two different unions, i32 vs. string" do union = SpecNamespace::My_union.new(:integer32, 25) other_union = SpecNamespace::My_union.new(:some_characters, "blah!") expect(union).not_to eq(other_union) end it "should properly reset setfield and setvalue" do union = SpecNamespace::My_union.new(:integer32, 25) expect(union.get_set_field).to eq(:integer32) union.some_characters = "blah!" expect(union.get_set_field).to eq(:some_characters) expect(union.get_value).to eq("blah!") expect { union.integer32 }.to raise_error(RuntimeError, "integer32 is not union's set field.") end it "should not equate two different unions with different values" do union = SpecNamespace::My_union.new(:integer32, 25) other_union = SpecNamespace::My_union.new(:integer32, 400) expect(union).not_to eq(other_union) end it "should not equate two different unions with different fields" do union = SpecNamespace::My_union.new(:integer32, 25) other_union = SpecNamespace::My_union.new(:other_i32, 25) expect(union).not_to eq(other_union) end it "should inspect properly" do union = SpecNamespace::My_union.new(:integer32, 25) expect(union.inspect).to eq("") end it "should not allow setting with instance_variable_set" do union = SpecNamespace::My_union.new(:integer32, 27) union.instance_variable_set(:@some_characters, "hallo!") expect(union.get_set_field).to eq(:integer32) expect(union.get_value).to eq(27) expect { union.some_characters }.to raise_error(RuntimeError, "some_characters is not union's set field.") end it "should serialize to binary correctly" do trans = Thrift::MemoryBufferTransport.new proto = Thrift::BinaryProtocol.new(trans) union = SpecNamespace::My_union.new(:integer32, 25) union.write(proto) other_union = SpecNamespace::My_union.new(:integer32, 25) other_union.read(proto) expect(other_union).to eq(union) end it "should serialize to json correctly" do trans = Thrift::MemoryBufferTransport.new proto = Thrift::JsonProtocol.new(trans) union = SpecNamespace::My_union.new(:integer32, 25) union.write(proto) other_union = SpecNamespace::My_union.new(:integer32, 25) other_union.read(proto) expect(other_union).to eq(union) end it "should raise when validating unset union" do union = SpecNamespace::My_union.new expect { union.validate }.to raise_error(StandardError, "Union fields are not set.") other_union = SpecNamespace::My_union.new(:integer32, 1) expect { other_union.validate }.not_to raise_error end it "should validate an enum field properly" do union = SpecNamespace::TestUnion.new(:enum_field, 3) expect(union.get_set_field).to eq(:enum_field) expect { union.validate }.to raise_error(Thrift::ProtocolException, "Invalid value of field enum_field!") other_union = SpecNamespace::TestUnion.new(:enum_field, 1) expect { other_union.validate }.not_to raise_error end it "should properly serialize and match structs with a union" do union = SpecNamespace::My_union.new(:integer32, 26) swu = SpecNamespace::Struct_with_union.new(:fun_union => union) trans = Thrift::MemoryBufferTransport.new proto = Thrift::CompactProtocol.new(trans) swu.write(proto) other_union = SpecNamespace::My_union.new(:some_characters, "hello there") swu2 = SpecNamespace::Struct_with_union.new(:fun_union => other_union) expect(swu2).not_to eq(swu) swu2.read(proto) expect(swu2).to eq(swu) end it "should support old style constructor" do union = SpecNamespace::My_union.new(:integer32 => 26) expect(union.get_set_field).to eq(:integer32) expect(union.get_value).to eq(26) end it "should not throw an error when inspected and unset" do expect{SpecNamespace::TestUnion.new().inspect}.not_to raise_error end it "should print enum value name when inspected" do expect(SpecNamespace::My_union.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect).to eq("") expect(SpecNamespace::My_union.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect).to eq("") end it "should offer field? methods" do expect(SpecNamespace::My_union.new.some_enum?).to be_falsey expect(SpecNamespace::My_union.new(:some_enum => SpecNamespace::SomeEnum::ONE).some_enum?).to be_truthy expect(SpecNamespace::My_union.new(:im_true => false).im_true?).to be_truthy expect(SpecNamespace::My_union.new(:im_true => true).im_true?).to be_truthy end it "should pretty print binary fields" do expect(SpecNamespace::TestUnion.new(:binary_field => "\001\002\003").inspect).to eq("") end it "should be comparable" do relationships = [ [0, -1, -1, -1], [1, 0, -1, -1], [1, 1, 0, -1], [1, 1, 1, 0]] objs = [ SpecNamespace::TestUnion.new(:string_field, "blah"), SpecNamespace::TestUnion.new(:string_field, "blahblah"), SpecNamespace::TestUnion.new(:i32_field, 1), SpecNamespace::TestUnion.new()] for y in 0..3 for x in 0..3 # puts "#{objs[y].inspect} <=> #{objs[x].inspect} should == #{relationships[y][x]}" expect(objs[y] <=> objs[x]).to eq(relationships[y][x]) end end end end end thrift-0.19.0/lib/rb/spec/ThriftSpec.thrift0000644000000000000000000000771414303740367020517 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace rb SpecNamespace struct Hello { 1: string greeting = "hello world" } enum SomeEnum { ONE TWO } struct StructWithSomeEnum { 1: SomeEnum some_enum; } union TestUnion { /** * A doc string */ 1: string string_field; 2: i32 i32_field; 3: i32 other_i32_field; 4: SomeEnum enum_field; 5: binary binary_field; } struct Foo { 1: i32 simple = 53, 2: string words = "words", 3: Hello hello = {'greeting' : "hello, world!"}, 4: list ints = [1, 2, 2, 3], 5: map> complex, 6: set shorts = [5, 17, 239], 7: optional string opt_string 8: bool my_bool } struct Foo2 { 1: binary my_binary } struct BoolStruct { 1: bool yesno = 1 } struct SimpleList { 1: list bools, 2: list bytes, 3: list i16s, 4: list i32s, 5: list i64s, 6: list doubles, 7: list strings, 8: list> maps, 9: list> lists, 10: list> sets, 11: list hellos } exception Xception { 1: string message, 2: i32 code = 1 } service NonblockingService { Hello greeting(1:bool english) bool block() oneway void unblock(1:i32 n) oneway void shutdown() void sleep(1:double seconds) } union My_union { 1: bool im_true, 2: byte a_bite, 3: i16 integer16, 4: i32 integer32, 5: i64 integer64, 6: double double_precision, 7: string some_characters, 8: i32 other_i32 9: SomeEnum some_enum; 10: map> my_map; } struct Struct_with_union { 1: My_union fun_union 2: i32 integer32 3: string some_characters } struct StructWithEnumMap { 1: map> my_map; } # Nested lists struct NestedListInList { 1: list> value } struct NestedListInSet { 1: set> value } struct NestedListInMapKey { 1: map, byte> value } struct NestedListInMapValue { 1: map> value } # Nested sets struct NestedSetInList { 1: list> value } struct NestedSetInSet { 1: set> value } struct NestedSetInMapKey { 1: map, byte> value } struct NestedSetInMapValue { 1: map> value } # Nested maps struct NestedMapInList { 1: list> value } struct NestedMapInSet { 1: set> value } struct NestedMapInMapKey { 2: map, byte> value } struct NestedMapInMapValue { 2: map> value } thrift-0.19.0/lib/rb/spec/spec_helper.rb0000644000000000000000000000423414303740367020032 0ustar00rootroot00000000000000# encoding: UTF-8 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'rubygems' require 'rspec' $:.unshift File.join(File.dirname(__FILE__), *%w[.. ext]) # pretend we already loaded fastthread, otherwise the nonblocking_server_spec # will get screwed up # $" << 'fastthread.bundle' require 'thrift' unless Object.method_defined? :tap # if Object#tap isn't defined, then add it; this should only happen in Ruby < 1.8.7 class Object def tap(&block) block.call(self) self end end end RSpec.configure do |configuration| configuration.before(:each) do Thrift.type_checking = true end end $:.unshift File.join(File.dirname(__FILE__), *%w[.. test debug_proto gen-rb]) require 'srv' require 'debug_proto_test_constants' $:.unshift File.join(File.dirname(__FILE__), *%w[gen-rb]) require 'thrift_spec_types' require 'nonblocking_service' module Fixtures COMPACT_PROTOCOL_TEST_STRUCT = Thrift::Test::COMPACT_TEST.dup COMPACT_PROTOCOL_TEST_STRUCT.a_binary = [0,1,2,3,4,5,6,7,8].pack('c*') COMPACT_PROTOCOL_TEST_STRUCT.set_byte_map = nil COMPACT_PROTOCOL_TEST_STRUCT.map_byte_map = nil end $:.unshift File.join(File.dirname(__FILE__), *%w[gen-rb/flat]) if defined?(GC.verify_compaction_references) == 'method' # This method was added in Ruby 3.0.0. Calling it this way asks the GC to # move objects around, helping to find object movement bugs. GC.verify_compaction_references(double_heap: true, toward: :empty) end thrift-0.19.0/lib/rb/spec/binary_protocol_accelerated_spec.rb0000644000000000000000000000332014303740367024267 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/binary_protocol_spec_shared") if defined? Thrift::BinaryProtocolAccelerated describe 'BinaryProtocolAccelerated' do # since BinaryProtocolAccelerated should be directly equivalent to # BinaryProtocol, we don't need any custom specs! it_should_behave_like 'a binary protocol' def protocol_class Thrift::BinaryProtocolAccelerated end describe Thrift::BinaryProtocolAcceleratedFactory do it "should create a BinaryProtocolAccelerated" do expect(Thrift::BinaryProtocolAcceleratedFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::BinaryProtocolAccelerated) end it "should provide a reasonable to_s" do expect(Thrift::BinaryProtocolAcceleratedFactory.new.to_s).to eq("binary-accel") end end end else puts "skipping BinaryProtocolAccelerated spec because it is not defined." end thrift-0.19.0/lib/rb/spec/ssl_socket_spec.rb0000644000000000000000000000646714303740367020736 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared") describe 'SSLSocket' do describe Thrift::SSLSocket do before(:each) do @context = OpenSSL::SSL::SSLContext.new @socket = Thrift::SSLSocket.new @simple_socket_handle = double("Handle", :closed? => false) allow(@simple_socket_handle).to receive(:close) allow(@simple_socket_handle).to receive(:connect_nonblock) allow(@simple_socket_handle).to receive(:setsockopt) @handle = double(double("SSLHandle", :connect_nonblock => true, :post_connection_check => true), :closed? => false) allow(@handle).to receive(:connect_nonblock) allow(@handle).to receive(:close) allow(@handle).to receive(:post_connection_check) allow(::Socket).to receive(:new).and_return(@simple_socket_handle) allow(OpenSSL::SSL::SSLSocket).to receive(:new).and_return(@handle) end it_should_behave_like "a socket" it "should raise a TransportException when it cannot open a ssl socket" do expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]]) expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) } end it "should open a ::Socket with default args" do expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(@simple_socket_handle, nil).and_return(@handle) expect(@handle).to receive(:post_connection_check).with('localhost') @socket.open end it "should accept host/port options" do handle = double("Handle", :connect_nonblock => true, :setsockopt => nil) allow(::Socket).to receive(:new).and_return(handle) expect(::Socket).to receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]]) expect(::Socket).to receive(:sockaddr_in) expect(OpenSSL::SSL::SSLSocket).to receive(:new).with(handle, nil).and_return(@handle) expect(@handle).to receive(:post_connection_check).with('my.domain') Thrift::SSLSocket.new('my.domain', 1234, 6000, nil).open end it "should accept an optional timeout" do expect(Thrift::SSLSocket.new('localhost', 8080, 5).timeout).to eq(5) end it "should accept an optional context" do expect(Thrift::SSLSocket.new('localhost', 8080, 5, @context).ssl_context).to eq(@context) end it "should provide a reasonable to_s" do expect(Thrift::SSLSocket.new('myhost', 8090).to_s).to eq("ssl(socket(myhost:8090))") end end end thrift-0.19.0/lib/rb/spec/http_client_spec.rb0000644000000000000000000001351614303740367021073 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Thrift::HTTPClientTransport' do describe Thrift::HTTPClientTransport do before(:each) do @client = Thrift::HTTPClientTransport.new("http://my.domain.com/path/to/service?param=value") end it "should provide a reasonable to_s" do @client.to_s == "http://my.domain.com/path/to/service?param=value" end it "should always be open" do expect(@client).to be_open @client.close expect(@client).to be_open end it "should post via HTTP and return the results" do @client.write "a test" @client.write " frame" expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do double("Net::HTTP").tap do |http| expect(http).to receive(:use_ssl=).with(false) expect(http).to receive(:post).with("/path/to/service?param=value", "a test frame", {"Content-Type"=>"application/x-thrift"}) do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" expect(response).to receive(:code).and_return "200" end end end end @client.flush expect(@client.read(10)).to eq("data") end it "should send custom headers if defined" do @client.write "test" custom_headers = {"Cookie" => "Foo"} headers = {"Content-Type"=>"application/x-thrift"}.merge(custom_headers) @client.add_headers(custom_headers) expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do double("Net::HTTP").tap do |http| expect(http).to receive(:use_ssl=).with(false) expect(http).to receive(:post).with("/path/to/service?param=value", "test", headers) do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" expect(response).to receive(:code).and_return "200" end end end end @client.flush end it 'should reset the outbuf on HTTP failures' do @client.write "test" expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do double("Net::HTTP").tap do |http| expect(http).to receive(:use_ssl=).with(false) expect(http).to receive(:post).with("/path/to/service?param=value", "test", {"Content-Type"=>"application/x-thrift"}) { raise Net::ReadTimeout } end end @client.flush rescue expect(@client.instance_variable_get(:@outbuf)).to eq(Thrift::Bytes.empty_byte_buffer) end it 'should raise TransportError on HTTP failures' do @client.write "test" expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do double("Net::HTTP").tap do |http| expect(http).to receive(:use_ssl=).with(false) expect(http).to receive(:post).with("/path/to/service?param=value", "test", {"Content-Type"=>"application/x-thrift"}) do double("Net::HTTPOK").tap do |response| expect(response).not_to receive(:body) expect(response).to receive(:code).at_least(:once).and_return "503" end end end end expect { @client.flush }.to raise_error(Thrift::TransportException) end end describe 'ssl enabled' do before(:each) do @service_path = "/path/to/service?param=value" @server_uri = "https://my.domain.com" end it "should use SSL for https" do client = Thrift::HTTPClientTransport.new("#{@server_uri}#{@service_path}") client.write "test" expect(Net::HTTP).to receive(:new).with("my.domain.com", 443) do double("Net::HTTP").tap do |http| expect(http).to receive(:use_ssl=).with(true) expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_PEER) expect(http).to receive(:post).with(@service_path, "test", "Content-Type" => "application/x-thrift") do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" expect(response).to receive(:code).and_return "200" end end end end client.flush expect(client.read(4)).to eq("data") end it "should set SSL verify mode when specified" do client = Thrift::HTTPClientTransport.new("#{@server_uri}#{@service_path}", :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE) client.write "test" expect(Net::HTTP).to receive(:new).with("my.domain.com", 443) do double("Net::HTTP").tap do |http| expect(http).to receive(:use_ssl=).with(true) expect(http).to receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE) expect(http).to receive(:post).with(@service_path, "test", "Content-Type" => "application/x-thrift") do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" expect(response).to receive(:code).and_return "200" end end end end client.flush expect(client.read(4)).to eq("data") end end end thrift-0.19.0/lib/rb/spec/flat_spec.rb0000644000000000000000000000413714303740367017503 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'generation' do before do require 'namespaced_nonblocking_service' end it "did not generate the wrong files" do prefix = File.expand_path("../gen-rb/flat", __FILE__) ["namespaced_spec_namespace/namespaced_nonblocking_service.rb", "namespaced_spec_namespace/thrift_namespaced_spec_constants.rb", "namespaced_spec_namespace/thrift_namespaced_spec_types.rb", "other_namespace/referenced_constants.rb", "other_namespace/referenced_types.rb" ].each do |name| expect(File.exist?(File.join(prefix, name))).not_to be_truthy end end it "generated the right files" do prefix = File.expand_path("../gen-rb/flat", __FILE__) ["namespaced_nonblocking_service.rb", "thrift_namespaced_spec_constants.rb", "thrift_namespaced_spec_types.rb", "referenced_constants.rb", "referenced_types.rb" ].each do |name| expect(File.exist?(File.join(prefix, name))).to be_truthy end end it "has a service class in the right place" do expect(defined?(NamespacedSpecNamespace::NamespacedNonblockingService)).to be_truthy end it "has a struct in the right place" do expect(defined?(NamespacedSpecNamespace::Hello)).to be_truthy end it "required an included file" do expect(defined?(OtherNamespace::SomeEnum)).to be_truthy end end thrift-0.19.0/lib/rb/spec/server_socket_spec.rb0000644000000000000000000000551714303740367021436 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared") describe 'Thrift::ServerSocket' do describe Thrift::ServerSocket do before(:each) do @socket = Thrift::ServerSocket.new(1234) end it "should create a handle when calling listen" do expect(TCPServer).to receive(:new).with(nil, 1234) @socket.listen end it "should accept an optional host argument" do @socket = Thrift::ServerSocket.new('localhost', 1234) expect(TCPServer).to receive(:new).with('localhost', 1234) @socket.to_s == "server(localhost:1234)" @socket.listen end it "should create a Thrift::Socket to wrap accepted sockets" do handle = double("TCPServer") expect(TCPServer).to receive(:new).with(nil, 1234).and_return(handle) @socket.listen sock = double("sock") expect(handle).to receive(:accept).and_return(sock) trans = double("Socket") expect(Thrift::Socket).to receive(:new).and_return(trans) expect(trans).to receive(:handle=).with(sock) expect(@socket.accept).to eq(trans) end it "should close the handle when closed" do handle = double("TCPServer", :closed? => false) expect(TCPServer).to receive(:new).with(nil, 1234).and_return(handle) @socket.listen expect(handle).to receive(:close) @socket.close end it "should return nil when accepting if there is no handle" do expect(@socket.accept).to be_nil end it "should return true for closed? when appropriate" do handle = double("TCPServer", :closed? => false) allow(TCPServer).to receive(:new).and_return(handle) @socket.listen expect(@socket).not_to be_closed allow(handle).to receive(:close) @socket.close expect(@socket).to be_closed @socket.listen expect(@socket).not_to be_closed allow(handle).to receive(:closed?).and_return(true) expect(@socket).to be_closed end it "should provide a reasonable to_s" do expect(@socket.to_s).to eq("socket(:1234)") end end end thrift-0.19.0/lib/rb/spec/bytes_spec.rb0000644000000000000000000001167414303740367017707 0ustar00rootroot00000000000000# encoding: UTF-8 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe Thrift::Bytes do if RUBY_VERSION >= '1.9' describe '.empty_byte_buffer' do it 'should create an empty buffer' do b = Thrift::Bytes.empty_byte_buffer expect(b.length).to eq(0) expect(b.encoding).to eq(Encoding::BINARY) end it 'should create an empty buffer of given size' do b = Thrift::Bytes.empty_byte_buffer 2 expect(b.length).to eq(2) expect(b.getbyte(0)).to eq(0) expect(b.getbyte(1)).to eq(0) expect(b.encoding).to eq(Encoding::BINARY) end end describe '.force_binary_encoding' do it 'should change encoding' do e = 'STRING'.encode('UTF-8') expect(e.encoding).not_to eq(Encoding::BINARY) a = Thrift::Bytes.force_binary_encoding e expect(a.encoding).to eq(Encoding::BINARY) end end describe '.get_string_byte' do it 'should get the byte at index' do s = "\x41\x42" expect(Thrift::Bytes.get_string_byte(s, 0)).to eq(0x41) expect(Thrift::Bytes.get_string_byte(s, 1)).to eq(0x42) end end describe '.set_string_byte' do it 'should set byte value at index' do s = "\x41\x42" Thrift::Bytes.set_string_byte(s, 0, 0x43) expect(s.getbyte(0)).to eq(0x43) expect(s).to eq('CB') end end describe '.convert_to_utf8_byte_buffer' do it 'should convert UTF-8 String to byte buffer' do e = "\u20AC".encode('UTF-8') # a string with euro sign character U+20AC expect(e.length).to eq(1) a = Thrift::Bytes.convert_to_utf8_byte_buffer e expect(a.encoding).to eq(Encoding::BINARY) expect(a.length).to eq(3) expect(a.unpack('C*')).to eq([0xE2, 0x82, 0xAC]) end it 'should convert ISO-8859-15 String to UTF-8 byte buffer' do # Assumptions e = "\u20AC".encode('ISO-8859-15') # a string with euro sign character U+20AC, then converted to ISO-8859-15 expect(e.length).to eq(1) expect(e.unpack('C*')).to eq([0xA4]) # euro sign is a different code point in ISO-8859-15 a = Thrift::Bytes.convert_to_utf8_byte_buffer e expect(a.encoding).to eq(Encoding::BINARY) expect(a.length).to eq(3) expect(a.unpack('C*')).to eq([0xE2, 0x82, 0xAC]) end end describe '.convert_to_string' do it 'should convert UTF-8 byte buffer to a UTF-8 String' do e = [0xE2, 0x82, 0xAC].pack("C*") expect(e.encoding).to eq(Encoding::BINARY) a = Thrift::Bytes.convert_to_string e expect(a.encoding).to eq(Encoding::UTF_8) expect(a).to eq("\u20AC") end end else # RUBY_VERSION describe '.empty_byte_buffer' do it 'should create an empty buffer' do b = Thrift::Bytes.empty_byte_buffer expect(b.length).to eq(0) end it 'should create an empty buffer of given size' do b = Thrift::Bytes.empty_byte_buffer 2 expect(b.length).to eq(2) expect(b[0]).to eq(0) expect(b[1]).to eq(0) end end describe '.force_binary_encoding' do it 'should be a no-op' do e = 'STRING' a = Thrift::Bytes.force_binary_encoding e expect(a).to eq(e) expect(a).to be(e) end end describe '.get_string_byte' do it 'should get the byte at index' do s = "\x41\x42" expect(Thrift::Bytes.get_string_byte(s, 0)).to eq(0x41) expect(Thrift::Bytes.get_string_byte(s, 1)).to eq(0x42) end end describe '.set_string_byte' do it 'should set byte value at index' do s = "\x41\x42" Thrift::Bytes.set_string_byte(s, 0, 0x43) expect(s[0]).to eq(0x43) expect(s).to eq('CB') end end describe '.convert_to_utf8_byte_buffer' do it 'should be a no-op' do e = 'STRING' a = Thrift::Bytes.convert_to_utf8_byte_buffer e expect(a).to eq(e) expect(a).to be(e) end end describe '.convert_to_string' do it 'should be a no-op' do e = 'STRING' a = Thrift::Bytes.convert_to_string e expect(a).to eq(e) expect(a).to be(e) end end end end thrift-0.19.0/lib/rb/spec/binary_protocol_spec.rb0000644000000000000000000000531514303740367021761 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/binary_protocol_spec_shared") describe 'BinaryProtocol' do it_should_behave_like 'a binary protocol' def protocol_class Thrift::BinaryProtocol end describe Thrift::BinaryProtocol do before(:each) do @trans = Thrift::MemoryBufferTransport.new @prot = protocol_class.new(@trans) end it "should read a message header" do @trans.write([protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::REPLY].pack('N')) @trans.write([42].pack('N')) expect(@prot).to receive(:read_string).and_return('testMessage') expect(@prot.read_message_begin).to eq(['testMessage', Thrift::MessageTypes::REPLY, 42]) end it "should raise an exception if the message header has the wrong version" do expect(@prot).to receive(:read_i32).and_return(-1) expect { @prot.read_message_begin }.to raise_error(Thrift::ProtocolException, 'Missing version identifier') do |e| e.type == Thrift::ProtocolException::BAD_VERSION end end it "should raise an exception if the message header does not exist and strict_read is enabled" do expect(@prot).to receive(:read_i32).and_return(42) expect(@prot).to receive(:strict_read).and_return(true) expect { @prot.read_message_begin }.to raise_error(Thrift::ProtocolException, 'No version identifier, old protocol client?') do |e| e.type == Thrift::ProtocolException::BAD_VERSION end end it "should provide a reasonable to_s" do expect(@prot.to_s).to eq("binary(memory)") end end describe Thrift::BinaryProtocolFactory do it "should create a BinaryProtocol" do expect(Thrift::BinaryProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::BinaryProtocol) end it "should provide a reasonable to_s" do expect(Thrift::BinaryProtocolFactory.new.to_s).to eq("binary") end end end thrift-0.19.0/lib/rb/spec/socket_spec.rb0000644000000000000000000000541014303740367020040 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared") describe 'Socket' do describe Thrift::Socket do before(:each) do @socket = Thrift::Socket.new @handle = double("Handle", :closed? => false) allow(@handle).to receive(:close) allow(@handle).to receive(:connect_nonblock) allow(@handle).to receive(:setsockopt) allow(::Socket).to receive(:new).and_return(@handle) end it_should_behave_like "a socket" it "should raise a TransportException when it cannot open a socket" do expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]]) expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) } end it "should open a ::Socket with default args" do expect(::Socket).to receive(:new).and_return(double("Handle", :connect_nonblock => true, :setsockopt => nil)) expect(::Socket).to receive(:getaddrinfo).with("localhost", 9090, nil, ::Socket::SOCK_STREAM).and_return([[]]) expect(::Socket).to receive(:sockaddr_in) @socket.to_s == "socket(localhost:9090)" @socket.open end it "should accept host/port options" do expect(::Socket).to receive(:new).and_return(double("Handle", :connect_nonblock => true, :setsockopt => nil)) expect(::Socket).to receive(:getaddrinfo).with("my.domain", 1234, nil, ::Socket::SOCK_STREAM).and_return([[]]) expect(::Socket).to receive(:sockaddr_in) @socket = Thrift::Socket.new('my.domain', 1234).open @socket.to_s == "socket(my.domain:1234)" end it "should accept an optional timeout" do allow(::Socket).to receive(:new) expect(Thrift::Socket.new('localhost', 8080, 5).timeout).to eq(5) end it "should provide a reasonable to_s" do allow(::Socket).to receive(:new) expect(Thrift::Socket.new('myhost', 8090).to_s).to eq("socket(myhost:8090)") end end end thrift-0.19.0/lib/rb/spec/struct_spec.rb0000644000000000000000000003234614303740367020104 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Struct' do describe Thrift::Struct do it "should iterate over all fields properly" do fields = {} SpecNamespace::Foo.new.each_field { |fid,field_info| fields[fid] = field_info } expect(fields).to eq(SpecNamespace::Foo::FIELDS) end it "should initialize all fields to defaults" do validate_default_arguments(SpecNamespace::Foo.new) end it "should initialize all fields to defaults and accept a block argument" do SpecNamespace::Foo.new do |f| validate_default_arguments(f) end end def validate_default_arguments(object) expect(object.simple).to eq(53) expect(object.words).to eq("words") expect(object.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!')) expect(object.ints).to eq([1, 2, 2, 3]) expect(object.complex).to be_nil expect(object.shorts).to eq(Set.new([5, 17, 239])) end it "should not share default values between instances" do begin struct = SpecNamespace::Foo.new struct.ints << 17 expect(SpecNamespace::Foo.new.ints).to eq([1,2,2,3]) ensure # ensure no leakage to other tests SpecNamespace::Foo::FIELDS[4][:default] = [1,2,2,3] end end it "should properly initialize boolean values" do struct = SpecNamespace::BoolStruct.new(:yesno => false) expect(struct.yesno).to be_falsey end it "should have proper == semantics" do expect(SpecNamespace::Foo.new).not_to eq(SpecNamespace::Hello.new) expect(SpecNamespace::Foo.new).to eq(SpecNamespace::Foo.new) expect(SpecNamespace::Foo.new(:simple => 52)).not_to eq(SpecNamespace::Foo.new) end it "should print enum value names in inspect" do expect(SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE).inspect).to eq("") expect(SpecNamespace::StructWithEnumMap.new(:my_map => {SpecNamespace::SomeEnum::ONE => [SpecNamespace::SomeEnum::TWO]}).inspect).to eq("") end it "should pretty print binary fields" do expect(SpecNamespace::Foo2.new(:my_binary => "\001\002\003").inspect).to eq("") end it "should offer field? methods" do expect(SpecNamespace::Foo.new.opt_string?).to be_falsey expect(SpecNamespace::Foo.new(:simple => 52).simple?).to be_truthy expect(SpecNamespace::Foo.new(:my_bool => false).my_bool?).to be_truthy expect(SpecNamespace::Foo.new(:my_bool => true).my_bool?).to be_truthy end it "should be comparable" do s1 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::ONE) s2 = SpecNamespace::StructWithSomeEnum.new(:some_enum => SpecNamespace::SomeEnum::TWO) expect(s1 <=> s2).to eq(-1) expect(s2 <=> s1).to eq(1) expect(s1 <=> s1).to eq(0) expect(s1 <=> SpecNamespace::StructWithSomeEnum.new()).to eq(-1) end it "should read itself off the wire" do struct = SpecNamespace::Foo.new prot = Thrift::BaseProtocol.new(double("transport")) expect(prot).to receive(:read_struct_begin).twice expect(prot).to receive(:read_struct_end).twice expect(prot).to receive(:read_field_begin).and_return( ['complex', Thrift::Types::MAP, 5], # Foo ['words', Thrift::Types::STRING, 2], # Foo ['hello', Thrift::Types::STRUCT, 3], # Foo ['greeting', Thrift::Types::STRING, 1], # Hello [nil, Thrift::Types::STOP, 0], # Hello ['simple', Thrift::Types::I32, 1], # Foo ['ints', Thrift::Types::LIST, 4], # Foo ['shorts', Thrift::Types::SET, 6], # Foo [nil, Thrift::Types::STOP, 0] # Hello ) expect(prot).to receive(:read_field_end).exactly(7).times expect(prot).to receive(:read_map_begin).and_return( [Thrift::Types::I32, Thrift::Types::MAP, 2], # complex [Thrift::Types::STRING, Thrift::Types::DOUBLE, 2], # complex/1/value [Thrift::Types::STRING, Thrift::Types::DOUBLE, 1] # complex/2/value ) expect(prot).to receive(:read_map_end).exactly(3).times expect(prot).to receive(:read_list_begin).and_return([Thrift::Types::I32, 4]) expect(prot).to receive(:read_list_end) expect(prot).to receive(:read_set_begin).and_return([Thrift::Types::I16, 2]) expect(prot).to receive(:read_set_end) expect(prot).to receive(:read_i32).and_return( 1, 14, # complex keys 42, # simple 4, 23, 4, 29 # ints ) expect(prot).to receive(:read_string).and_return("pi", "e", "feigenbaum", "apple banana", "what's up?") expect(prot).to receive(:read_double).and_return(Math::PI, Math::E, 4.669201609) expect(prot).to receive(:read_i16).and_return(2, 3) expect(prot).not_to receive(:skip) struct.read(prot) expect(struct.simple).to eq(42) expect(struct.complex).to eq({1 => {"pi" => Math::PI, "e" => Math::E}, 14 => {"feigenbaum" => 4.669201609}}) expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => "what's up?")) expect(struct.words).to eq("apple banana") expect(struct.ints).to eq([4, 23, 4, 29]) expect(struct.shorts).to eq(Set.new([3, 2])) end it "should serialize false boolean fields correctly" do b = SpecNamespace::BoolStruct.new(:yesno => false) prot = Thrift::BinaryProtocol.new(Thrift::MemoryBufferTransport.new) expect(prot).to receive(:write_bool).with(false) b.write(prot) end it "should skip unexpected fields in structs and use default values" do struct = SpecNamespace::Foo.new prot = Thrift::BaseProtocol.new(double("transport")) expect(prot).to receive(:read_struct_begin) expect(prot).to receive(:read_struct_end) expect(prot).to receive(:read_field_begin).and_return( ['simple', Thrift::Types::I32, 1], ['complex', Thrift::Types::STRUCT, 5], ['thinz', Thrift::Types::MAP, 7], ['foobar', Thrift::Types::I32, 3], ['words', Thrift::Types::STRING, 2], [nil, Thrift::Types::STOP, 0] ) expect(prot).to receive(:read_field_end).exactly(5).times expect(prot).to receive(:read_i32).and_return(42) expect(prot).to receive(:read_string).and_return("foobar") expect(prot).to receive(:skip).with(Thrift::Types::STRUCT) expect(prot).to receive(:skip).with(Thrift::Types::MAP) # prot.should_receive(:read_map_begin).and_return([Thrift::Types::I32, Thrift::Types::I32, 0]) # prot.should_receive(:read_map_end) expect(prot).to receive(:skip).with(Thrift::Types::I32) struct.read(prot) expect(struct.simple).to eq(42) expect(struct.complex).to be_nil expect(struct.words).to eq("foobar") expect(struct.hello).to eq(SpecNamespace::Hello.new(:greeting => 'hello, world!')) expect(struct.ints).to eq([1, 2, 2, 3]) expect(struct.shorts).to eq(Set.new([5, 17, 239])) end it "should write itself to the wire" do prot = Thrift::BaseProtocol.new(double("transport")) #mock("Protocol") expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Foo") expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Hello") expect(prot).to receive(:write_struct_end).twice expect(prot).to receive(:write_field_begin).with('ints', Thrift::Types::LIST, 4) expect(prot).to receive(:write_i32).with(1) expect(prot).to receive(:write_i32).with(2).twice expect(prot).to receive(:write_i32).with(3) expect(prot).to receive(:write_field_begin).with('complex', Thrift::Types::MAP, 5) expect(prot).to receive(:write_i32).with(5) expect(prot).to receive(:write_string).with('foo') expect(prot).to receive(:write_double).with(1.23) expect(prot).to receive(:write_field_begin).with('shorts', Thrift::Types::SET, 6) expect(prot).to receive(:write_i16).with(5) expect(prot).to receive(:write_i16).with(17) expect(prot).to receive(:write_i16).with(239) expect(prot).to receive(:write_field_stop).twice expect(prot).to receive(:write_field_end).exactly(6).times expect(prot).to receive(:write_field_begin).with('simple', Thrift::Types::I32, 1) expect(prot).to receive(:write_i32).with(53) expect(prot).to receive(:write_field_begin).with('hello', Thrift::Types::STRUCT, 3) expect(prot).to receive(:write_field_begin).with('greeting', Thrift::Types::STRING, 1) expect(prot).to receive(:write_string).with('hello, world!') expect(prot).to receive(:write_map_begin).with(Thrift::Types::I32, Thrift::Types::MAP, 1) expect(prot).to receive(:write_map_begin).with(Thrift::Types::STRING, Thrift::Types::DOUBLE, 1) expect(prot).to receive(:write_map_end).twice expect(prot).to receive(:write_list_begin).with(Thrift::Types::I32, 4) expect(prot).to receive(:write_list_end) expect(prot).to receive(:write_set_begin).with(Thrift::Types::I16, 3) expect(prot).to receive(:write_set_end) struct = SpecNamespace::Foo.new struct.words = nil struct.complex = {5 => {"foo" => 1.23}} struct.write(prot) end it "should raise an exception if presented with an unknown container" do # yeah this is silly, but I'm going for code coverage here struct = SpecNamespace::Foo.new expect { struct.send :write_container, nil, nil, {:type => "foo"} }.to raise_error(StandardError, "Not a container type: foo") end it "should support optional type-checking in Thrift::Struct.new" do Thrift.type_checking = true begin expect { SpecNamespace::Hello.new(:greeting => 3) }.to raise_error(Thrift::TypeError, /Expected Types::STRING, received (Integer|Fixnum) for field greeting/) ensure Thrift.type_checking = false end expect { SpecNamespace::Hello.new(:greeting => 3) }.not_to raise_error end it "should support optional type-checking in field accessors" do Thrift.type_checking = true begin hello = SpecNamespace::Hello.new expect { hello.greeting = 3 }.to raise_error(Thrift::TypeError, /Expected Types::STRING, received (Integer|Fixnum) for field greeting/) ensure Thrift.type_checking = false end expect { hello.greeting = 3 }.not_to raise_error end it "should raise an exception when unknown types are given to Thrift::Struct.new" do expect { SpecNamespace::Hello.new(:fish => 'salmon') }.to raise_error(Exception, "Unknown key given to SpecNamespace::Hello.new: fish") end it "should support `raise Xception, 'message'` for Exception structs" do begin raise SpecNamespace::Xception, "something happened" rescue Thrift::Exception => e expect(e.message).to eq("something happened") expect(e.code).to eq(1) # ensure it gets serialized properly, this is the really important part prot = Thrift::BaseProtocol.new(double("trans")) expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception") expect(prot).to receive(:write_struct_end) expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1)#, "something happened") expect(prot).to receive(:write_string).with("something happened") expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2)#, 1) expect(prot).to receive(:write_i32).with(1) expect(prot).to receive(:write_field_stop) expect(prot).to receive(:write_field_end).twice e.write(prot) end end it "should support the regular initializer for exception structs" do begin raise SpecNamespace::Xception, :message => "something happened", :code => 5 rescue Thrift::Exception => e expect(e.message).to eq("something happened") expect(e.code).to eq(5) prot = Thrift::BaseProtocol.new(double("trans")) expect(prot).to receive(:write_struct_begin).with("SpecNamespace::Xception") expect(prot).to receive(:write_struct_end) expect(prot).to receive(:write_field_begin).with('message', Thrift::Types::STRING, 1) expect(prot).to receive(:write_string).with("something happened") expect(prot).to receive(:write_field_begin).with('code', Thrift::Types::I32, 2) expect(prot).to receive(:write_i32).with(5) expect(prot).to receive(:write_field_stop) expect(prot).to receive(:write_field_end).twice e.write(prot) end end end end thrift-0.19.0/lib/rb/spec/exception_spec.rb0000644000000000000000000001412414303740367020550 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Exception' do describe Thrift::Exception do it "should have an accessible message" do e = Thrift::Exception.new("test message") expect(e.message).to eq("test message") end end describe Thrift::ApplicationException do it "should inherit from Thrift::Exception" do expect(Thrift::ApplicationException.superclass).to eq(Thrift::Exception) end it "should have an accessible type and message" do e = Thrift::ApplicationException.new expect(e.type).to eq(Thrift::ApplicationException::UNKNOWN) expect(e.message).to be_nil e = Thrift::ApplicationException.new(Thrift::ApplicationException::UNKNOWN_METHOD, "test message") expect(e.type).to eq(Thrift::ApplicationException::UNKNOWN_METHOD) expect(e.message).to eq("test message") end it "should read a struct off of a protocol" do prot = double("MockProtocol") expect(prot).to receive(:read_struct_begin).ordered expect(prot).to receive(:read_field_begin).exactly(3).times.and_return( ["message", Thrift::Types::STRING, 1], ["type", Thrift::Types::I32, 2], [nil, Thrift::Types::STOP, 0] ) expect(prot).to receive(:read_string).ordered.and_return "test message" expect(prot).to receive(:read_i32).ordered.and_return Thrift::ApplicationException::BAD_SEQUENCE_ID expect(prot).to receive(:read_field_end).exactly(2).times expect(prot).to receive(:read_struct_end).ordered e = Thrift::ApplicationException.new e.read(prot) expect(e.message).to eq("test message") expect(e.type).to eq(Thrift::ApplicationException::BAD_SEQUENCE_ID) end it "should skip bad fields when reading a struct" do prot = double("MockProtocol") expect(prot).to receive(:read_struct_begin).ordered expect(prot).to receive(:read_field_begin).exactly(5).times.and_return( ["type", Thrift::Types::I32, 2], ["type", Thrift::Types::STRING, 2], ["message", Thrift::Types::MAP, 1], ["message", Thrift::Types::STRING, 3], [nil, Thrift::Types::STOP, 0] ) expect(prot).to receive(:read_i32).and_return Thrift::ApplicationException::INVALID_MESSAGE_TYPE expect(prot).to receive(:skip).with(Thrift::Types::STRING).twice expect(prot).to receive(:skip).with(Thrift::Types::MAP) expect(prot).to receive(:read_field_end).exactly(4).times expect(prot).to receive(:read_struct_end).ordered e = Thrift::ApplicationException.new e.read(prot) expect(e.message).to be_nil expect(e.type).to eq(Thrift::ApplicationException::INVALID_MESSAGE_TYPE) end it "should write a Thrift::ApplicationException struct to the oprot" do prot = double("MockProtocol") expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered expect(prot).to receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered expect(prot).to receive(:write_string).with("test message").ordered expect(prot).to receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered expect(prot).to receive(:write_i32).with(Thrift::ApplicationException::UNKNOWN_METHOD).ordered expect(prot).to receive(:write_field_end).twice expect(prot).to receive(:write_field_stop).ordered expect(prot).to receive(:write_struct_end).ordered e = Thrift::ApplicationException.new(Thrift::ApplicationException::UNKNOWN_METHOD, "test message") e.write(prot) end it "should skip nil fields when writing to the oprot" do prot = double("MockProtocol") expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered expect(prot).to receive(:write_field_begin).with("message", Thrift::Types::STRING, 1).ordered expect(prot).to receive(:write_string).with("test message").ordered expect(prot).to receive(:write_field_end).ordered expect(prot).to receive(:write_field_stop).ordered expect(prot).to receive(:write_struct_end).ordered e = Thrift::ApplicationException.new(nil, "test message") e.write(prot) prot = double("MockProtocol") expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered expect(prot).to receive(:write_field_begin).with("type", Thrift::Types::I32, 2).ordered expect(prot).to receive(:write_i32).with(Thrift::ApplicationException::BAD_SEQUENCE_ID).ordered expect(prot).to receive(:write_field_end).ordered expect(prot).to receive(:write_field_stop).ordered expect(prot).to receive(:write_struct_end).ordered e = Thrift::ApplicationException.new(Thrift::ApplicationException::BAD_SEQUENCE_ID) e.write(prot) prot = double("MockProtocol") expect(prot).to receive(:write_struct_begin).with("Thrift::ApplicationException").ordered expect(prot).to receive(:write_field_stop).ordered expect(prot).to receive(:write_struct_end).ordered e = Thrift::ApplicationException.new(nil) e.write(prot) end end describe Thrift::ProtocolException do it "should have an accessible type" do prot = Thrift::ProtocolException.new(Thrift::ProtocolException::SIZE_LIMIT, "message") expect(prot.type).to eq(Thrift::ProtocolException::SIZE_LIMIT) expect(prot.message).to eq("message") end end end thrift-0.19.0/lib/rb/spec/thin_http_server_spec.rb0000644000000000000000000001042214303740367022136 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require 'rack/test' require 'thrift/server/thin_http_server' describe Thrift::ThinHTTPServer do let(:processor) { double('processor') } describe "#initialize" do context "when using the defaults" do it "binds to port 80, with host 0.0.0.0, a path of '/'" do expect(Thin::Server).to receive(:new).with('0.0.0.0', 80, an_instance_of(Rack::Builder)) Thrift::ThinHTTPServer.new(processor) end it 'creates a ThinHTTPServer::RackApplicationContext' do expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::BinaryProtocolFactory)).and_return(anything) Thrift::ThinHTTPServer.new(processor) end it "uses the BinaryProtocolFactory" do expect(Thrift::BinaryProtocolFactory).to receive(:new) Thrift::ThinHTTPServer.new(processor) end end context "when using the options" do it 'accepts :ip, :port, :path' do ip = "192.168.0.1" port = 3000 path = "/thin" expect(Thin::Server).to receive(:new).with(ip, port, an_instance_of(Rack::Builder)) Thrift::ThinHTTPServer.new(processor, :ip => ip, :port => port, :path => path) end it 'creates a ThinHTTPServer::RackApplicationContext with a different protocol factory' do expect(Thrift::ThinHTTPServer::RackApplication).to receive(:for).with("/", processor, an_instance_of(Thrift::JsonProtocolFactory)).and_return(anything) Thrift::ThinHTTPServer.new(processor, :protocol_factory => Thrift::JsonProtocolFactory.new) end end end describe "#serve" do it 'starts the Thin server' do underlying_thin_server = double('thin server', :start => true) allow(Thin::Server).to receive(:new).and_return(underlying_thin_server) thin_thrift_server = Thrift::ThinHTTPServer.new(processor) expect(underlying_thin_server).to receive(:start) thin_thrift_server.serve end end end describe Thrift::ThinHTTPServer::RackApplication do include Rack::Test::Methods let(:processor) { double('processor') } let(:protocol_factory) { double('protocol factory') } def app Thrift::ThinHTTPServer::RackApplication.for("/", processor, protocol_factory) end context "404 response" do it 'receives a non-POST' do header('Content-Type', "application/x-thrift") get "/" expect(last_response.status).to be 404 end it 'receives a header other than application/x-thrift' do header('Content-Type', "application/json") post "/" expect(last_response.status).to be 404 end end context "200 response" do before do allow(protocol_factory).to receive(:get_protocol) allow(processor).to receive(:process) end it 'creates an IOStreamTransport' do header('Content-Type', "application/x-thrift") expect(Thrift::IOStreamTransport).to receive(:new).with(an_instance_of(Rack::Lint::InputWrapper), an_instance_of(Rack::Response)) post "/" end it 'fetches the right protocol based on the Transport' do header('Content-Type', "application/x-thrift") expect(protocol_factory).to receive(:get_protocol).with(an_instance_of(Thrift::IOStreamTransport)) post "/" end it 'status code 200' do header('Content-Type', "application/x-thrift") post "/" expect(last_response.ok?).to be_truthy end end end thrift-0.19.0/lib/rb/spec/BaseService.thrift0000644000000000000000000000162314303740367020630 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace rb Base struct Hello { 1: string greeting = "hello world" } service BaseService { Hello greeting(1:bool english) } thrift-0.19.0/lib/rb/spec/compact_protocol_spec.rb0000644000000000000000000001310214303740367022114 0ustar00rootroot00000000000000# encoding: UTF-8 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe Thrift::CompactProtocol do TESTS = { :byte => (-127..127).to_a, :i16 => (0..14).map {|shift| [1 << shift, -(1 << shift)]}.flatten.sort, :i32 => (0..30).map {|shift| [1 << shift, -(1 << shift)]}.flatten.sort, :i64 => (0..62).map {|shift| [1 << shift, -(1 << shift)]}.flatten.sort, :string => ["", "1", "short", "fourteen123456", "fifteen12345678", "unicode characters: \u20AC \u20AD", "1" * 127, "1" * 3000], :binary => ["", "\001", "\001" * 5, "\001" * 14, "\001" * 15, "\001" * 127, "\001" * 3000], :double => [0.0, 1.0, -1.0, 1.1, -1.1, 10000000.1, 1.0/0.0, -1.0/0.0], :bool => [true, false] } it "should encode and decode naked primitives correctly" do TESTS.each_pair do |primitive_type, test_values| test_values.each do |value| # puts "testing #{value}" if primitive_type == :i64 trans = Thrift::MemoryBufferTransport.new proto = Thrift::CompactProtocol.new(trans) proto.send(writer(primitive_type), value) # puts "buf: #{trans.inspect_buffer}" if primitive_type == :i64 read_back = proto.send(reader(primitive_type)) expect(read_back).to eq(value) end end end it "should encode and decode primitives in fields correctly" do TESTS.each_pair do |primitive_type, test_values| final_primitive_type = primitive_type == :binary ? :string : primitive_type thrift_type = Thrift::Types.const_get(final_primitive_type.to_s.upcase) # puts primitive_type test_values.each do |value| trans = Thrift::MemoryBufferTransport.new proto = Thrift::CompactProtocol.new(trans) proto.write_field_begin(nil, thrift_type, 15) proto.send(writer(primitive_type), value) proto.write_field_end proto = Thrift::CompactProtocol.new(trans) name, type, id = proto.read_field_begin expect(type).to eq(thrift_type) expect(id).to eq(15) read_back = proto.send(reader(primitive_type)) expect(read_back).to eq(value) proto.read_field_end end end end it "should encode and decode a monster struct correctly" do trans = Thrift::MemoryBufferTransport.new proto = Thrift::CompactProtocol.new(trans) struct = Thrift::Test::CompactProtoTestStruct.new # sets and maps don't hash well... not sure what to do here. struct.write(proto) struct2 = Thrift::Test::CompactProtoTestStruct.new struct2.read(proto) expect(struct2).to eq(struct) end it "should make method calls correctly" do client_out_trans = Thrift::MemoryBufferTransport.new client_out_proto = Thrift::CompactProtocol.new(client_out_trans) client_in_trans = Thrift::MemoryBufferTransport.new client_in_proto = Thrift::CompactProtocol.new(client_in_trans) processor = Thrift::Test::Srv::Processor.new(JankyHandler.new) client = Thrift::Test::Srv::Client.new(client_in_proto, client_out_proto) client.send_Janky(1) # puts client_out_trans.inspect_buffer processor.process(client_out_proto, client_in_proto) expect(client.recv_Janky).to eq(2) end it "should deal with fields following fields that have non-delta ids" do brcp = Thrift::Test::BreaksRubyCompactProtocol.new( :field1 => "blah", :field2 => Thrift::Test::BigFieldIdStruct.new( :field1 => "string1", :field2 => "string2"), :field3 => 3) ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new) bytes = ser.serialize(brcp) deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new) brcp2 = Thrift::Test::BreaksRubyCompactProtocol.new deser.deserialize(brcp2, bytes) expect(brcp2).to eq(brcp) end it "should deserialize an empty map to an empty hash" do struct = Thrift::Test::SingleMapTestStruct.new(:i32_map => {}) ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new) bytes = ser.serialize(struct) deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new) struct2 = Thrift::Test::SingleMapTestStruct.new deser.deserialize(struct2, bytes) expect(struct).to eq(struct2) end it "should provide a reasonable to_s" do trans = Thrift::MemoryBufferTransport.new expect(Thrift::CompactProtocol.new(trans).to_s).to eq("compact(memory)") end class JankyHandler def Janky(i32arg) i32arg * 2 end end def writer(sym) "write_#{sym.to_s}" end def reader(sym) "read_#{sym.to_s}" end end describe Thrift::CompactProtocolFactory do it "should create a CompactProtocol" do expect(Thrift::CompactProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::CompactProtocol) end it "should provide a reasonable to_s" do expect(Thrift::CompactProtocolFactory.new.to_s).to eq("compact") end end thrift-0.19.0/lib/rb/spec/namespaced_spec.rb0000644000000000000000000000430714303740367020654 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'namespaced generation' do before do require 'namespaced_spec_namespace/namespaced_nonblocking_service' end it "generated the right files" do prefix = File.expand_path("../gen-rb", __FILE__) ["namespaced_spec_namespace/namespaced_nonblocking_service.rb", "namespaced_spec_namespace/thrift_namespaced_spec_constants.rb", "namespaced_spec_namespace/thrift_namespaced_spec_types.rb", "other_namespace/referenced_constants.rb", "other_namespace/referenced_types.rb" ].each do |name| expect(File.exist?(File.join(prefix, name))).to be_truthy end end it "did not generate the wrong files" do prefix = File.expand_path("../gen-rb", __FILE__) ["namespaced_nonblocking_service.rb", "thrift_namespaced_spec_constants.rb", "thrift_namespaced_spec_types.rb", "referenced_constants.rb", "referenced_types.rb" ].each do |name| expect(File.exist?(File.join(prefix, name))).not_to be_truthy end end it "has a service class in the right place" do expect(defined?(NamespacedSpecNamespace::NamespacedNonblockingService)).to be_truthy end it "has a struct in the right place" do expect(defined?(NamespacedSpecNamespace::Hello)).to be_truthy end it "required an included file" do expect(defined?(OtherNamespace::SomeEnum)).to be_truthy end it "extended a service" do require "extended/extended_service" end end thrift-0.19.0/lib/rb/spec/processor_spec.rb0000644000000000000000000000632214303740367020572 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Processor' do class ProcessorSpec include Thrift::Processor end describe Thrift::Processor do before(:each) do @processor = ProcessorSpec.new(double("MockHandler")) @prot = double("MockProtocol") end def mock_trans(obj) expect(obj).to receive(:trans).ordered do double("trans").tap do |trans| expect(trans).to receive(:flush).ordered end end end it "should call process_ when it receives that message" do expect(@prot).to receive(:read_message_begin).ordered.and_return ['testMessage', Thrift::MessageTypes::CALL, 17] expect(@processor).to receive(:process_testMessage).with(17, @prot, @prot).ordered expect(@processor.process(@prot, @prot)).to eq(true) end it "should raise an ApplicationException when the received message cannot be processed" do expect(@prot).to receive(:read_message_begin).ordered.and_return ['testMessage', Thrift::MessageTypes::CALL, 4] expect(@prot).to receive(:skip).with(Thrift::Types::STRUCT).ordered expect(@prot).to receive(:read_message_end).ordered expect(@prot).to receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::EXCEPTION, 4).ordered e = double(Thrift::ApplicationException) expect(e).to receive(:write).with(@prot).ordered expect(Thrift::ApplicationException).to receive(:new).with(Thrift::ApplicationException::UNKNOWN_METHOD, "Unknown function testMessage").and_return(e) expect(@prot).to receive(:write_message_end).ordered mock_trans(@prot) @processor.process(@prot, @prot) end it "should pass args off to the args class" do args_class = double("MockArgsClass") args = double("#").tap do |args| expect(args).to receive(:read).with(@prot).ordered end expect(args_class).to receive(:new).and_return args expect(@prot).to receive(:read_message_end).ordered expect(@processor.read_args(@prot, args_class)).to eql(args) end it "should write out a reply when asked" do expect(@prot).to receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::REPLY, 23).ordered result = double("MockResult") expect(result).to receive(:write).with(@prot).ordered expect(@prot).to receive(:write_message_end).ordered mock_trans(@prot) @processor.write_result(result, @prot, 'testMessage', 23) end end end thrift-0.19.0/lib/rb/spec/ssl_server_socket_spec.rb0000644000000000000000000000217514303740367022314 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared") describe 'SSLServerSocket' do describe Thrift::SSLServerSocket do before(:each) do @socket = Thrift::SSLServerSocket.new(1234) end it "should provide a reasonable to_s" do expect(@socket.to_s).to eq("ssl(socket(:1234))") end end end thrift-0.19.0/lib/rb/spec/ExtendedService.thrift0000644000000000000000000000161714303740367021521 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace rb Extended include "BaseService.thrift" service ExtendedService extends BaseService.BaseService { void ping() } thrift-0.19.0/lib/rb/spec/binary_protocol_spec_shared.rb0000644000000000000000000003605614303740367023315 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' shared_examples_for 'a binary protocol' do before(:each) do @trans = Thrift::MemoryBufferTransport.new @prot = protocol_class.new(@trans) end it "should define the proper VERSION_1, VERSION_MASK AND TYPE_MASK" do expect(protocol_class.const_get(:VERSION_MASK)).to eq(0xffff0000) expect(protocol_class.const_get(:VERSION_1)).to eq(0x80010000) expect(protocol_class.const_get(:TYPE_MASK)).to eq(0x000000ff) end it "should make strict_read readable" do expect(@prot.strict_read).to eql(true) end it "should make strict_write readable" do expect(@prot.strict_write).to eql(true) end it "should write the message header" do @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17) expect(@trans.read(@trans.available)).to eq([protocol_class.const_get(:VERSION_1) | Thrift::MessageTypes::CALL, "testMessage".size, "testMessage", 17].pack("NNa11N")) end it "should write the message header without version when writes are not strict" do @prot = protocol_class.new(@trans, true, false) # no strict write @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17) expect(@trans.read(@trans.available)).to eq("\000\000\000\vtestMessage\001\000\000\000\021") end it "should write the message header with a version when writes are strict" do @prot = protocol_class.new(@trans) # strict write @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17) expect(@trans.read(@trans.available)).to eq("\200\001\000\001\000\000\000\vtestMessage\000\000\000\021") end # message footer is a noop it "should write the field header" do @prot.write_field_begin('foo', Thrift::Types::DOUBLE, 3) expect(@trans.read(@trans.available)).to eq([Thrift::Types::DOUBLE, 3].pack("cn")) end # field footer is a noop it "should write the STOP field" do @prot.write_field_stop expect(@trans.read(1)).to eq("\000") end it "should write the map header" do @prot.write_map_begin(Thrift::Types::STRING, Thrift::Types::LIST, 17) expect(@trans.read(@trans.available)).to eq([Thrift::Types::STRING, Thrift::Types::LIST, 17].pack("ccN")); end # map footer is a noop it "should write the list header" do @prot.write_list_begin(Thrift::Types::I16, 42) expect(@trans.read(@trans.available)).to eq([Thrift::Types::I16, 42].pack("cN")) end # list footer is a noop it "should write the set header" do @prot.write_set_begin(Thrift::Types::I16, 42) expect(@trans.read(@trans.available)).to eq([Thrift::Types::I16, 42].pack("cN")) end it "should write a bool" do @prot.write_bool(true) @prot.write_bool(false) expect(@trans.read(@trans.available)).to eq("\001\000") end it "should treat a nil bool as false" do @prot.write_bool(nil) expect(@trans.read(1)).to eq("\000") end it "should write a byte" do # byte is small enough, let's check -128..127 (-128..127).each do |i| @prot.write_byte(i) expect(@trans.read(1)).to eq([i].pack('c')) end end it "should clip numbers out of signed range" do (128..255).each do |i| @prot.write_byte(i) expect(@trans.read(1)).to eq([i].pack('c')) end end it "errors out with a Bignum" do expect { @prot.write_byte(2**65) }.to raise_error(RangeError) end it "should error gracefully when trying to write a nil byte" do expect { @prot.write_byte(nil) }.to raise_error end it "should write an i16" do # try a random scattering of values # include the signed i16 minimum/maximum [-2**15, -1024, 17, 0, -10000, 1723, 2**15-1].each do |i| @prot.write_i16(i) end # and try something out of signed range, it should clip @prot.write_i16(2**15 + 5) expect(@trans.read(@trans.available)).to eq("\200\000\374\000\000\021\000\000\330\360\006\273\177\377\200\005") # a Bignum should error # lambda { @prot.write_i16(2**65) }.should raise_error(RangeError) end it "should error gracefully when trying to write a nil i16" do expect { @prot.write_i16(nil) }.to raise_error end it "should write an i32" do # try a random scattering of values # include the signed i32 minimum/maximum [-2**31, -123123, -2532, -3, 0, 2351235, 12331, 2**31-1].each do |i| @prot.write_i32(i) end # try something out of signed range, it should clip expect(@trans.read(@trans.available)).to eq("\200\000\000\000" + "\377\376\037\r" + "\377\377\366\034" + "\377\377\377\375" + "\000\000\000\000" + "\000#\340\203" + "\000\0000+" + "\177\377\377\377") [2 ** 31 + 5, 2 ** 65 + 5].each do |i| expect { @prot.write_i32(i) }.to raise_error(RangeError) end end it "should error gracefully when trying to write a nil i32" do expect { @prot.write_i32(nil) }.to raise_error end it "should write an i64" do # try a random scattering of values # try the signed i64 minimum/maximum [-2**63, -12356123612323, -23512351, -234, 0, 1231, 2351236, 12361236213, 2**63-1].each do |i| @prot.write_i64(i) end # try something out of signed range, it should clip expect(@trans.read(@trans.available)).to eq(["\200\000\000\000\000\000\000\000", "\377\377\364\303\035\244+]", "\377\377\377\377\376\231:\341", "\377\377\377\377\377\377\377\026", "\000\000\000\000\000\000\000\000", "\000\000\000\000\000\000\004\317", "\000\000\000\000\000#\340\204", "\000\000\000\002\340\311~\365", "\177\377\377\377\377\377\377\377"].join("")) expect { @prot.write_i64(2 ** 65 + 5) }.to raise_error(RangeError) end it "should error gracefully when trying to write a nil i64" do expect { @prot.write_i64(nil) }.to raise_error end it "should write a double" do # try a random scattering of values, including min/max values = [Float::MIN,-1231.15325, -123123.23, -23.23515123, 0, 12351.1325, 523.23, Float::MAX] values.each do |f| @prot.write_double(f) expect(@trans.read(@trans.available)).to eq([f].pack("G")) end end it "should error gracefully when trying to write a nil double" do expect { @prot.write_double(nil) }.to raise_error end if RUBY_VERSION >= '1.9' it 'should write a string' do str = 'abc' @prot.write_string(str) a = @trans.read(@trans.available) expect(a.encoding).to eq(Encoding::BINARY) expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63]) end it 'should write a string with unicode characters' do str = "abc \u20AC \u20AD".encode('UTF-8') @prot.write_string(str) a = @trans.read(@trans.available) expect(a.encoding).to eq(Encoding::BINARY) expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x0B, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC, 0x20, 0xE2, 0x82, 0xAD]) end it 'should write should write a string with unicode characters and transcoding' do str = "abc \u20AC".encode('ISO-8859-15') @prot.write_string(str) a = @trans.read(@trans.available) expect(a.encoding).to eq(Encoding::BINARY) expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x07, 0x61, 0x62, 0x63, 0x20, 0xE2, 0x82, 0xAC]) end it 'should write a binary string' do buffer = [0, 1, 2, 3].pack('C*') @prot.write_binary(buffer) a = @trans.read(@trans.available) expect(a.encoding).to eq(Encoding::BINARY) expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03]) end else it 'should write a string' do str = 'abc' @prot.write_string(str) a = @trans.read(@trans.available) expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63]) end it 'should write a binary string' do buffer = [0, 1, 2, 3].pack('C*') @prot.write_binary(buffer) a = @trans.read(@trans.available) expect(a.unpack('C*')).to eq([0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03]) end end it "should error gracefully when trying to write a nil string" do expect { @prot.write_string(nil) }.to raise_error end it "should write the message header without version when writes are not strict" do @prot = protocol_class.new(@trans, true, false) # no strict write @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17) expect(@trans.read(@trans.available)).to eq("\000\000\000\vtestMessage\001\000\000\000\021") end it "should write the message header with a version when writes are strict" do @prot = protocol_class.new(@trans) # strict write @prot.write_message_begin('testMessage', Thrift::MessageTypes::CALL, 17) expect(@trans.read(@trans.available)).to eq("\200\001\000\001\000\000\000\vtestMessage\000\000\000\021") end # message footer is a noop it "should read a field header" do @trans.write([Thrift::Types::STRING, 3].pack("cn")) expect(@prot.read_field_begin).to eq([nil, Thrift::Types::STRING, 3]) end # field footer is a noop it "should read a stop field" do @trans.write([Thrift::Types::STOP].pack("c")); expect(@prot.read_field_begin).to eq([nil, Thrift::Types::STOP, 0]) end it "should read a map header" do @trans.write([Thrift::Types::DOUBLE, Thrift::Types::I64, 42].pack("ccN")) expect(@prot.read_map_begin).to eq([Thrift::Types::DOUBLE, Thrift::Types::I64, 42]) end # map footer is a noop it "should read a list header" do @trans.write([Thrift::Types::STRING, 17].pack("cN")) expect(@prot.read_list_begin).to eq([Thrift::Types::STRING, 17]) end # list footer is a noop it "should read a set header" do @trans.write([Thrift::Types::STRING, 17].pack("cN")) expect(@prot.read_set_begin).to eq([Thrift::Types::STRING, 17]) end # set footer is a noop it "should read a bool" do @trans.write("\001\000"); expect(@prot.read_bool).to eq(true) expect(@prot.read_bool).to eq(false) end it "should read a byte" do [-128, -57, -3, 0, 17, 24, 127].each do |i| @trans.write([i].pack("c")) expect(@prot.read_byte).to eq(i) end end it "should read an i16" do # try a scattering of values, including min/max [-2**15, -5237, -353, 0, 1527, 2234, 2**15-1].each do |i| @trans.write([i].pack("n")); expect(@prot.read_i16).to eq(i) end end it "should read an i32" do # try a scattering of values, including min/max [-2**31, -235125, -6236, 0, 2351, 123123, 2**31-1].each do |i| @trans.write([i].pack("N")) expect(@prot.read_i32).to eq(i) end end it "should read an i64" do # try a scattering of values, including min/max [-2**63, -123512312, -6346, 0, 32, 2346322323, 2**63-1].each do |i| @trans.write([i >> 32, i & 0xFFFFFFFF].pack("NN")) expect(@prot.read_i64).to eq(i) end end it "should read a double" do # try a random scattering of values, including min/max [Float::MIN, -231231.12351, -323.233513, 0, 123.2351235, 2351235.12351235, Float::MAX].each do |f| @trans.write([f].pack("G")); expect(@prot.read_double).to eq(f) end end if RUBY_VERSION >= '1.9' it 'should read a string' do # i32 of value 3, followed by three characters/UTF-8 bytes 'a', 'b', 'c' buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*') @trans.write(buffer) a = @prot.read_string expect(a).to eq('abc'.encode('UTF-8')) expect(a.encoding).to eq(Encoding::UTF_8) end it 'should read a string containing unicode characters from UTF-8 encoded buffer' do # i32 of value 3, followed by one character U+20AC made up of three bytes buffer = [0x00, 0x00, 0x00, 0x03, 0xE2, 0x82, 0xAC].pack('C*') @trans.write(buffer) a = @prot.read_string expect(a).to eq("\u20AC".encode('UTF-8')) expect(a.encoding).to eq(Encoding::UTF_8) end it 'should read a binary string' do buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*') @trans.write(buffer) a = @prot.read_binary expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*')) expect(a.encoding).to eq(Encoding::BINARY) end else it 'should read a string' do # i32 of value 3, followed by three characters/UTF-8 bytes 'a', 'b', 'c' buffer = [0x00, 0x00, 0x00, 0x03, 0x61, 0x62, 0x63].pack('C*') @trans.write(buffer) expect(@prot.read_string).to eq('abc') end it 'should read a binary string' do buffer = [0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03].pack('C*') @trans.write(buffer) a = @prot.read_binary expect(a).to eq([0x00, 0x01, 0x02, 0x03].pack('C*')) end end it "should perform a complete rpc with no args or return" do srv_test( proc {|client| client.send_voidMethod()}, proc {|client| expect(client.recv_voidMethod).to eq(nil)} ) end it "should perform a complete rpc with a primitive return type" do srv_test( proc {|client| client.send_primitiveMethod()}, proc {|client| expect(client.recv_primitiveMethod).to eq(1)} ) end it "should perform a complete rpc with a struct return type" do srv_test( proc {|client| client.send_structMethod()}, proc {|client| result = client.recv_structMethod result.set_byte_map = nil result.map_byte_map = nil expect(result).to eq(Fixtures::COMPACT_PROTOCOL_TEST_STRUCT) } ) end def get_socket_connection server = Thrift::ServerSocket.new("localhost", 9090) server.listen clientside = Thrift::Socket.new("localhost", 9090) clientside.open serverside = server.accept [clientside, serverside, server] end def srv_test(firstblock, secondblock) clientside, serverside, server = get_socket_connection clientproto = protocol_class.new(clientside) serverproto = protocol_class.new(serverside) processor = Thrift::Test::Srv::Processor.new(SrvHandler.new) client = Thrift::Test::Srv::Client.new(clientproto, clientproto) # first block firstblock.call(client) processor.process(serverproto, serverproto) # second block secondblock.call(client) ensure clientside.close serverside.close server.close end class SrvHandler def voidMethod() end def primitiveMethod 1 end def structMethod Fixtures::COMPACT_PROTOCOL_TEST_STRUCT end end end thrift-0.19.0/lib/rb/spec/struct_nested_containers_spec.rb0000644000000000000000000001440614303740367023670 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'StructNestedContainers' do def with_type_checking saved_type_checking, Thrift.type_checking = Thrift.type_checking, true begin yield ensure Thrift.type_checking = saved_type_checking end end describe Thrift::Struct do # Nested container tests, see THRIFT-369. it "should support nested lists inside lists" do with_type_checking do a, b = SpecNamespace::NestedListInList.new, SpecNamespace::NestedListInList.new [a, b].each do |thrift_struct| thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ] thrift_struct.validate end expect(a).to eq(b) b.value.push [3, 4, 5] expect(a).not_to eq(b) end end it "should support nested lists inside sets" do with_type_checking do a, b = SpecNamespace::NestedListInSet.new, SpecNamespace::NestedListInSet.new [a, b].each do |thrift_struct| thrift_struct.value = [ [1, 2, 3], [2, 3, 4] ].to_set thrift_struct.validate end expect(a).to eq(b) b.value.add [3, 4, 5] expect(a).not_to eq(b) end end it "should support nested lists in map keys" do with_type_checking do a, b = SpecNamespace::NestedListInMapKey.new, SpecNamespace::NestedListInMapKey.new [a, b].each do |thrift_struct| thrift_struct.value = { [1, 2, 3] => 1, [2, 3, 4] => 2 } thrift_struct.validate end expect(a).to eq(b) b.value[[3, 4, 5]] = 3 expect(a).not_to eq(b) end end it "should support nested lists in map values" do with_type_checking do a, b = SpecNamespace::NestedListInMapValue.new, SpecNamespace::NestedListInMapValue.new [a, b].each do |thrift_struct| thrift_struct.value = { 1 => [1, 2, 3], 2 => [2, 3, 4] } thrift_struct.validate end expect(a).to eq(b) b.value[3] = [3, 4, 5] expect(a).not_to eq(b) end end it "should support nested sets inside lists" do with_type_checking do a, b = SpecNamespace::NestedSetInList.new, SpecNamespace::NestedSetInList.new [a, b].each do |thrift_struct| thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ] thrift_struct.validate end expect(a).to eq(b) b.value.push([3, 4, 5].to_set) expect(a).not_to eq(b) end end it "should support nested sets inside sets" do with_type_checking do a, b = SpecNamespace::NestedSetInSet.new, SpecNamespace::NestedSetInSet.new [a, b].each do |thrift_struct| thrift_struct.value = [ [1, 2, 3].to_set, [2, 3, 4].to_set ].to_set thrift_struct.validate end expect(a).to eq(b) b.value.add([3, 4, 5].to_set) expect(a).not_to eq(b) end end it "should support nested sets in map keys" do with_type_checking do a, b = SpecNamespace::NestedSetInMapKey.new, SpecNamespace::NestedSetInMapKey.new [a, b].each do |thrift_struct| thrift_struct.value = { [1, 2, 3].to_set => 1, [2, 3, 4].to_set => 2 } thrift_struct.validate end expect(a).to eq(b) b.value[[3, 4, 5].to_set] = 3 expect(a).not_to eq(b) end end it "should support nested sets in map values" do with_type_checking do a, b = SpecNamespace::NestedSetInMapValue.new, SpecNamespace::NestedSetInMapValue.new [a, b].each do |thrift_struct| thrift_struct.value = { 1 => [1, 2, 3].to_set, 2 => [2, 3, 4].to_set } thrift_struct.validate end expect(a).to eq(b) b.value[3] = [3, 4, 5].to_set expect(a).not_to eq(b) end end it "should support nested maps inside lists" do with_type_checking do a, b = SpecNamespace::NestedMapInList.new, SpecNamespace::NestedMapInList.new [a, b].each do |thrift_struct| thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ] thrift_struct.validate end expect(a).to eq(b) b.value.push({ 3 => 4, 5 => 6 }) expect(a).not_to eq(b) end end it "should support nested maps inside sets" do with_type_checking do a, b = SpecNamespace::NestedMapInSet.new, SpecNamespace::NestedMapInSet.new [a, b].each do |thrift_struct| thrift_struct.value = [ {1 => 2, 3 => 4}, {2 => 3, 4 => 5} ].to_set thrift_struct.validate end expect(a).to eq(b) b.value.add({ 3 => 4, 5 => 6 }) expect(a).not_to eq(b) end end it "should support nested maps in map keys" do with_type_checking do a, b = SpecNamespace::NestedMapInMapKey.new, SpecNamespace::NestedMapInMapKey.new [a, b].each do |thrift_struct| thrift_struct.value = { { 1 => 2, 3 => 4} => 1, {2 => 3, 4 => 5} => 2 } thrift_struct.validate end expect(a).to eq(b) b.value[{3 => 4, 5 => 6}] = 3 expect(a).not_to eq(b) end end it "should support nested maps in map values" do with_type_checking do a, b = SpecNamespace::NestedMapInMapValue.new, SpecNamespace::NestedMapInMapValue.new [a, b].each do |thrift_struct| thrift_struct.value = { 1 => { 1 => 2, 3 => 4}, 2 => {2 => 3, 4 => 5} } thrift_struct.validate end expect(a).to eq(b) b.value[3] = { 3 => 4, 5 => 6 } expect(a).not_to eq(b) end end end end thrift-0.19.0/lib/rb/spec/base_protocol_spec.rb0000644000000000000000000002433214303740367021407 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'BaseProtocol' do before(:each) do @trans = double("MockTransport") @prot = Thrift::BaseProtocol.new(@trans) end describe Thrift::BaseProtocol do # most of the methods are stubs, so we can ignore them it "should provide a reasonable to_s" do expect(@trans).to receive(:to_s).once.and_return("trans") expect(@prot.to_s).to eq("trans") end it "should make trans accessible" do expect(@prot.trans).to eql(@trans) end it 'should write out a field nicely (deprecated write_field signature)' do expect(@prot).to receive(:write_field_begin).with('field', 'type', 'fid').ordered expect(@prot).to receive(:write_type).with({:name => 'field', :type => 'type'}, 'value').ordered expect(@prot).to receive(:write_field_end).ordered @prot.write_field('field', 'type', 'fid', 'value') end it 'should write out a field nicely' do expect(@prot).to receive(:write_field_begin).with('field', 'type', 'fid').ordered expect(@prot).to receive(:write_type).with({:name => 'field', :type => 'type', :binary => false}, 'value').ordered expect(@prot).to receive(:write_field_end).ordered @prot.write_field({:name => 'field', :type => 'type', :binary => false}, 'fid', 'value') end it 'should write out the different types (deprecated write_type signature)' do expect(@prot).to receive(:write_bool).with('bool').ordered expect(@prot).to receive(:write_byte).with('byte').ordered expect(@prot).to receive(:write_double).with('double').ordered expect(@prot).to receive(:write_i16).with('i16').ordered expect(@prot).to receive(:write_i32).with('i32').ordered expect(@prot).to receive(:write_i64).with('i64').ordered expect(@prot).to receive(:write_string).with('string').ordered struct = double('Struct') expect(struct).to receive(:write).with(@prot).ordered @prot.write_type(Thrift::Types::BOOL, 'bool') @prot.write_type(Thrift::Types::BYTE, 'byte') @prot.write_type(Thrift::Types::DOUBLE, 'double') @prot.write_type(Thrift::Types::I16, 'i16') @prot.write_type(Thrift::Types::I32, 'i32') @prot.write_type(Thrift::Types::I64, 'i64') @prot.write_type(Thrift::Types::STRING, 'string') @prot.write_type(Thrift::Types::STRUCT, struct) # all other types are not implemented [Thrift::Types::STOP, Thrift::Types::VOID, Thrift::Types::MAP, Thrift::Types::SET, Thrift::Types::LIST].each do |type| expect { @prot.write_type(type, type.to_s) }.to raise_error(NotImplementedError) end end it 'should write out the different types' do expect(@prot).to receive(:write_bool).with('bool').ordered expect(@prot).to receive(:write_byte).with('byte').ordered expect(@prot).to receive(:write_double).with('double').ordered expect(@prot).to receive(:write_i16).with('i16').ordered expect(@prot).to receive(:write_i32).with('i32').ordered expect(@prot).to receive(:write_i64).with('i64').ordered expect(@prot).to receive(:write_string).with('string').ordered expect(@prot).to receive(:write_binary).with('binary').ordered struct = double('Struct') expect(struct).to receive(:write).with(@prot).ordered @prot.write_type({:type => Thrift::Types::BOOL}, 'bool') @prot.write_type({:type => Thrift::Types::BYTE}, 'byte') @prot.write_type({:type => Thrift::Types::DOUBLE}, 'double') @prot.write_type({:type => Thrift::Types::I16}, 'i16') @prot.write_type({:type => Thrift::Types::I32}, 'i32') @prot.write_type({:type => Thrift::Types::I64}, 'i64') @prot.write_type({:type => Thrift::Types::STRING}, 'string') @prot.write_type({:type => Thrift::Types::STRING, :binary => true}, 'binary') @prot.write_type({:type => Thrift::Types::STRUCT}, struct) # all other types are not implemented [Thrift::Types::STOP, Thrift::Types::VOID, Thrift::Types::MAP, Thrift::Types::SET, Thrift::Types::LIST].each do |type| expect { @prot.write_type({:type => type}, type.to_s) }.to raise_error(NotImplementedError) end end it 'should read the different types (deprecated read_type signature)' do expect(@prot).to receive(:read_bool).ordered expect(@prot).to receive(:read_byte).ordered expect(@prot).to receive(:read_i16).ordered expect(@prot).to receive(:read_i32).ordered expect(@prot).to receive(:read_i64).ordered expect(@prot).to receive(:read_double).ordered expect(@prot).to receive(:read_string).ordered @prot.read_type(Thrift::Types::BOOL) @prot.read_type(Thrift::Types::BYTE) @prot.read_type(Thrift::Types::I16) @prot.read_type(Thrift::Types::I32) @prot.read_type(Thrift::Types::I64) @prot.read_type(Thrift::Types::DOUBLE) @prot.read_type(Thrift::Types::STRING) # all other types are not implemented [Thrift::Types::STOP, Thrift::Types::VOID, Thrift::Types::MAP, Thrift::Types::SET, Thrift::Types::LIST, Thrift::Types::STRUCT].each do |type| expect { @prot.read_type(type) }.to raise_error(NotImplementedError) end end it 'should read the different types' do expect(@prot).to receive(:read_bool).ordered expect(@prot).to receive(:read_byte).ordered expect(@prot).to receive(:read_i16).ordered expect(@prot).to receive(:read_i32).ordered expect(@prot).to receive(:read_i64).ordered expect(@prot).to receive(:read_double).ordered expect(@prot).to receive(:read_string).ordered expect(@prot).to receive(:read_binary).ordered @prot.read_type({:type => Thrift::Types::BOOL}) @prot.read_type({:type => Thrift::Types::BYTE}) @prot.read_type({:type => Thrift::Types::I16}) @prot.read_type({:type => Thrift::Types::I32}) @prot.read_type({:type => Thrift::Types::I64}) @prot.read_type({:type => Thrift::Types::DOUBLE}) @prot.read_type({:type => Thrift::Types::STRING}) @prot.read_type({:type => Thrift::Types::STRING, :binary => true}) # all other types are not implemented [Thrift::Types::STOP, Thrift::Types::VOID, Thrift::Types::MAP, Thrift::Types::SET, Thrift::Types::LIST, Thrift::Types::STRUCT].each do |type| expect { @prot.read_type({:type => type}) }.to raise_error(NotImplementedError) end end it "should skip the basic types" do expect(@prot).to receive(:read_bool).ordered expect(@prot).to receive(:read_byte).ordered expect(@prot).to receive(:read_i16).ordered expect(@prot).to receive(:read_i32).ordered expect(@prot).to receive(:read_i64).ordered expect(@prot).to receive(:read_double).ordered expect(@prot).to receive(:read_string).ordered @prot.skip(Thrift::Types::BOOL) @prot.skip(Thrift::Types::BYTE) @prot.skip(Thrift::Types::I16) @prot.skip(Thrift::Types::I32) @prot.skip(Thrift::Types::I64) @prot.skip(Thrift::Types::DOUBLE) @prot.skip(Thrift::Types::STRING) end it "should skip structs" do real_skip = @prot.method(:skip) expect(@prot).to receive(:read_struct_begin).ordered expect(@prot).to receive(:read_field_begin).exactly(4).times.and_return( ['field 1', Thrift::Types::STRING, 1], ['field 2', Thrift::Types::I32, 2], ['field 3', Thrift::Types::MAP, 3], [nil, Thrift::Types::STOP, 0] ) expect(@prot).to receive(:read_field_end).exactly(3).times expect(@prot).to receive(:read_string).exactly(3).times expect(@prot).to receive(:read_i32).ordered expect(@prot).to receive(:read_map_begin).ordered.and_return([Thrift::Types::STRING, Thrift::Types::STRING, 1]) # @prot.should_receive(:read_string).exactly(2).times expect(@prot).to receive(:read_map_end).ordered expect(@prot).to receive(:read_struct_end).ordered real_skip.call(Thrift::Types::STRUCT) end it "should skip maps" do real_skip = @prot.method(:skip) expect(@prot).to receive(:read_map_begin).ordered.and_return([Thrift::Types::STRING, Thrift::Types::STRUCT, 1]) expect(@prot).to receive(:read_string).ordered expect(@prot).to receive(:read_struct_begin).ordered.and_return(["some_struct"]) expect(@prot).to receive(:read_field_begin).ordered.and_return([nil, Thrift::Types::STOP, nil]); expect(@prot).to receive(:read_struct_end).ordered expect(@prot).to receive(:read_map_end).ordered real_skip.call(Thrift::Types::MAP) end it "should skip sets" do real_skip = @prot.method(:skip) expect(@prot).to receive(:read_set_begin).ordered.and_return([Thrift::Types::I64, 9]) expect(@prot).to receive(:read_i64).ordered.exactly(9).times expect(@prot).to receive(:read_set_end) real_skip.call(Thrift::Types::SET) end it "should skip lists" do real_skip = @prot.method(:skip) expect(@prot).to receive(:read_list_begin).ordered.and_return([Thrift::Types::DOUBLE, 11]) expect(@prot).to receive(:read_double).ordered.exactly(11).times expect(@prot).to receive(:read_list_end) real_skip.call(Thrift::Types::LIST) end end describe Thrift::BaseProtocolFactory do it "should raise NotImplementedError" do # returning nil since Protocol is just an abstract class expect {Thrift::BaseProtocolFactory.new.get_protocol(double("MockTransport"))}.to raise_error(NotImplementedError) end it "should provide a reasonable to_s" do expect(Thrift::BaseProtocolFactory.new.to_s).to eq("base") end end end thrift-0.19.0/lib/rb/spec/serializer_spec.rb0000644000000000000000000000630114303740367020721 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Serializer' do describe Thrift::Serializer do it "should serialize structs to binary by default" do serializer = Thrift::Serializer.new(Thrift::BinaryProtocolAcceleratedFactory.new) data = serializer.serialize(SpecNamespace::Hello.new(:greeting => "'Ello guv'nor!")) expect(data).to eq("\x0B\x00\x01\x00\x00\x00\x0E'Ello guv'nor!\x00") end it "should serialize structs to the given protocol" do protocol = Thrift::BaseProtocol.new(double("transport")) expect(protocol).to receive(:write_struct_begin).with("SpecNamespace::Hello") expect(protocol).to receive(:write_field_begin).with("greeting", Thrift::Types::STRING, 1) expect(protocol).to receive(:write_string).with("Good day") expect(protocol).to receive(:write_field_end) expect(protocol).to receive(:write_field_stop) expect(protocol).to receive(:write_struct_end) protocol_factory = double("ProtocolFactory") allow(protocol_factory).to receive(:get_protocol).and_return(protocol) serializer = Thrift::Serializer.new(protocol_factory) serializer.serialize(SpecNamespace::Hello.new(:greeting => "Good day")) end end describe Thrift::Deserializer do it "should deserialize structs from binary by default" do deserializer = Thrift::Deserializer.new data = "\x0B\x00\x01\x00\x00\x00\x0E'Ello guv'nor!\x00" expect(deserializer.deserialize(SpecNamespace::Hello.new, data)).to eq(SpecNamespace::Hello.new(:greeting => "'Ello guv'nor!")) end it "should deserialize structs from the given protocol" do protocol = Thrift::BaseProtocol.new(double("transport")) expect(protocol).to receive(:read_struct_begin).and_return("SpecNamespace::Hello") expect(protocol).to receive(:read_field_begin).and_return(["greeting", Thrift::Types::STRING, 1], [nil, Thrift::Types::STOP, 0]) expect(protocol).to receive(:read_string).and_return("Good day") expect(protocol).to receive(:read_field_end) expect(protocol).to receive(:read_struct_end) protocol_factory = double("ProtocolFactory") allow(protocol_factory).to receive(:get_protocol).and_return(protocol) deserializer = Thrift::Deserializer.new(protocol_factory) expect(deserializer.deserialize(SpecNamespace::Hello.new, "")).to eq(SpecNamespace::Hello.new(:greeting => "Good day")) end end end thrift-0.19.0/lib/rb/spec/json_protocol_spec.rb0000644000000000000000000004454214303740367021453 0ustar00rootroot00000000000000# encoding: UTF-8 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'JsonProtocol' do describe Thrift::JsonProtocol do before(:each) do @trans = Thrift::MemoryBufferTransport.new @prot = Thrift::JsonProtocol.new(@trans) end it "should write json escaped char" do @prot.write_json_escape_char("\n") expect(@trans.read(@trans.available)).to eq('\u000a') @prot.write_json_escape_char(" ") expect(@trans.read(@trans.available)).to eq('\u0020') end it "should write json char" do @prot.write_json_char("\n") expect(@trans.read(@trans.available)).to eq('\\n') @prot.write_json_char(" ") expect(@trans.read(@trans.available)).to eq(' ') @prot.write_json_char("\\") expect(@trans.read(@trans.available)).to eq("\\\\") @prot.write_json_char("@") expect(@trans.read(@trans.available)).to eq('@') end it "should write json string" do @prot.write_json_string("this is a \\ json\nstring") expect(@trans.read(@trans.available)).to eq("\"this is a \\\\ json\\nstring\"") end it "should write json base64" do @prot.write_json_base64("this is a base64 string") expect(@trans.read(@trans.available)).to eq("\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\"") end it "should write json integer" do @prot.write_json_integer(45) expect(@trans.read(@trans.available)).to eq("45") @prot.write_json_integer(33000) expect(@trans.read(@trans.available)).to eq("33000") @prot.write_json_integer(3000000000) expect(@trans.read(@trans.available)).to eq("3000000000") @prot.write_json_integer(6000000000) expect(@trans.read(@trans.available)).to eq("6000000000") end it "should write json double" do @prot.write_json_double(12.3) expect(@trans.read(@trans.available)).to eq("12.3") @prot.write_json_double(-3.21) expect(@trans.read(@trans.available)).to eq("-3.21") @prot.write_json_double(((+1.0/0.0)/(+1.0/0.0))) expect(@trans.read(@trans.available)).to eq("\"NaN\"") @prot.write_json_double((+1.0/0.0)) expect(@trans.read(@trans.available)).to eq("\"Infinity\"") @prot.write_json_double((-1.0/0.0)) expect(@trans.read(@trans.available)).to eq("\"-Infinity\"") end it "should write json object start" do @prot.write_json_object_start expect(@trans.read(@trans.available)).to eq("{") end it "should write json object end" do @prot.write_json_object_end expect(@trans.read(@trans.available)).to eq("}") end it "should write json array start" do @prot.write_json_array_start expect(@trans.read(@trans.available)).to eq("[") end it "should write json array end" do @prot.write_json_array_end expect(@trans.read(@trans.available)).to eq("]") end it "should write message begin" do @prot.write_message_begin("name", 12, 32) expect(@trans.read(@trans.available)).to eq("[1,\"name\",12,32") end it "should write message end" do @prot.write_message_end expect(@trans.read(@trans.available)).to eq("]") end it "should write struct begin" do @prot.write_struct_begin("name") expect(@trans.read(@trans.available)).to eq("{") end it "should write struct end" do @prot.write_struct_end expect(@trans.read(@trans.available)).to eq("}") end it "should write field begin" do @prot.write_field_begin("name", Thrift::Types::STRUCT, 32) expect(@trans.read(@trans.available)).to eq("32{\"rec\"") end it "should write field end" do @prot.write_field_end expect(@trans.read(@trans.available)).to eq("}") end it "should write field stop" do @prot.write_field_stop expect(@trans.read(@trans.available)).to eq("") end it "should write map begin" do @prot.write_map_begin(Thrift::Types::STRUCT, Thrift::Types::LIST, 32) expect(@trans.read(@trans.available)).to eq("[\"rec\",\"lst\",32,{") end it "should write map end" do @prot.write_map_end expect(@trans.read(@trans.available)).to eq("}]") end it "should write list begin" do @prot.write_list_begin(Thrift::Types::STRUCT, 32) expect(@trans.read(@trans.available)).to eq("[\"rec\",32") end it "should write list end" do @prot.write_list_end expect(@trans.read(@trans.available)).to eq("]") end it "should write set begin" do @prot.write_set_begin(Thrift::Types::STRUCT, 32) expect(@trans.read(@trans.available)).to eq("[\"rec\",32") end it "should write set end" do @prot.write_set_end expect(@trans.read(@trans.available)).to eq("]") end it "should write bool" do @prot.write_bool(true) expect(@trans.read(@trans.available)).to eq("1") @prot.write_bool(false) expect(@trans.read(@trans.available)).to eq("0") end it "should write byte" do @prot.write_byte(100) expect(@trans.read(@trans.available)).to eq("100") end it "should write i16" do @prot.write_i16(1000) expect(@trans.read(@trans.available)).to eq("1000") end it "should write i32" do @prot.write_i32(3000000000) expect(@trans.read(@trans.available)).to eq("3000000000") end it "should write i64" do @prot.write_i64(6000000000) expect(@trans.read(@trans.available)).to eq("6000000000") end it "should write double" do @prot.write_double(1.23) expect(@trans.read(@trans.available)).to eq("1.23") @prot.write_double(-32.1) expect(@trans.read(@trans.available)).to eq("-32.1") @prot.write_double(((+1.0/0.0)/(+1.0/0.0))) expect(@trans.read(@trans.available)).to eq("\"NaN\"") @prot.write_double((+1.0/0.0)) expect(@trans.read(@trans.available)).to eq("\"Infinity\"") @prot.write_double((-1.0/0.0)) expect(@trans.read(@trans.available)).to eq("\"-Infinity\"") end if RUBY_VERSION >= '1.9' it 'should write string' do @prot.write_string('this is a test string') a = @trans.read(@trans.available) expect(a).to eq('"this is a test string"'.force_encoding(Encoding::BINARY)) expect(a.encoding).to eq(Encoding::BINARY) end it 'should write string with unicode characters' do @prot.write_string("this is a test string with unicode characters: \u20AC \u20AD") a = @trans.read(@trans.available) expect(a).to eq("\"this is a test string with unicode characters: \u20AC \u20AD\"".force_encoding(Encoding::BINARY)) expect(a.encoding).to eq(Encoding::BINARY) end else it 'should write string' do @prot.write_string('this is a test string') expect(@trans.read(@trans.available)).to eq('"this is a test string"') end end it "should write binary" do @prot.write_binary("this is a base64 string") expect(@trans.read(@trans.available)).to eq("\"dGhpcyBpcyBhIGJhc2U2NCBzdHJpbmc=\"") end it "should write long binary" do @prot.write_binary((0...256).to_a.pack('C*')) expect(@trans.read(@trans.available)).to eq("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"") end it "should get type name for type id" do expect {@prot.get_type_name_for_type_id(Thrift::Types::STOP)}.to raise_error(NotImplementedError) expect {@prot.get_type_name_for_type_id(Thrift::Types::VOID)}.to raise_error(NotImplementedError) expect(@prot.get_type_name_for_type_id(Thrift::Types::BOOL)).to eq("tf") expect(@prot.get_type_name_for_type_id(Thrift::Types::BYTE)).to eq("i8") expect(@prot.get_type_name_for_type_id(Thrift::Types::DOUBLE)).to eq("dbl") expect(@prot.get_type_name_for_type_id(Thrift::Types::I16)).to eq("i16") expect(@prot.get_type_name_for_type_id(Thrift::Types::I32)).to eq("i32") expect(@prot.get_type_name_for_type_id(Thrift::Types::I64)).to eq("i64") expect(@prot.get_type_name_for_type_id(Thrift::Types::STRING)).to eq("str") expect(@prot.get_type_name_for_type_id(Thrift::Types::STRUCT)).to eq("rec") expect(@prot.get_type_name_for_type_id(Thrift::Types::MAP)).to eq("map") expect(@prot.get_type_name_for_type_id(Thrift::Types::SET)).to eq("set") expect(@prot.get_type_name_for_type_id(Thrift::Types::LIST)).to eq("lst") end it "should get type id for type name" do expect {@prot.get_type_id_for_type_name("pp")}.to raise_error(NotImplementedError) expect(@prot.get_type_id_for_type_name("tf")).to eq(Thrift::Types::BOOL) expect(@prot.get_type_id_for_type_name("i8")).to eq(Thrift::Types::BYTE) expect(@prot.get_type_id_for_type_name("dbl")).to eq(Thrift::Types::DOUBLE) expect(@prot.get_type_id_for_type_name("i16")).to eq(Thrift::Types::I16) expect(@prot.get_type_id_for_type_name("i32")).to eq(Thrift::Types::I32) expect(@prot.get_type_id_for_type_name("i64")).to eq(Thrift::Types::I64) expect(@prot.get_type_id_for_type_name("str")).to eq(Thrift::Types::STRING) expect(@prot.get_type_id_for_type_name("rec")).to eq(Thrift::Types::STRUCT) expect(@prot.get_type_id_for_type_name("map")).to eq(Thrift::Types::MAP) expect(@prot.get_type_id_for_type_name("set")).to eq(Thrift::Types::SET) expect(@prot.get_type_id_for_type_name("lst")).to eq(Thrift::Types::LIST) end it "should read json syntax char" do @trans.write('F') expect {@prot.read_json_syntax_char('G')}.to raise_error(Thrift::ProtocolException) @trans.write('H') @prot.read_json_syntax_char('H') end it "should read json escape char" do @trans.write('0054') expect(@prot.read_json_escape_char).to eq('T') @trans.write("\"\\\"\"") expect(@prot.read_json_string(false)).to eq("\"") @trans.write("\"\\\\\"") expect(@prot.read_json_string(false)).to eq("\\") @trans.write("\"\\/\"") expect(@prot.read_json_string(false)).to eq("\/") @trans.write("\"\\b\"") expect(@prot.read_json_string(false)).to eq("\b") @trans.write("\"\\f\"") expect(@prot.read_json_string(false)).to eq("\f") @trans.write("\"\\n\"") expect(@prot.read_json_string(false)).to eq("\n") @trans.write("\"\\r\"") expect(@prot.read_json_string(false)).to eq("\r") @trans.write("\"\\t\"") expect(@prot.read_json_string(false)).to eq("\t") end it "should read json string" do @trans.write("\"\\P") expect {@prot.read_json_string(false)}.to raise_error(Thrift::ProtocolException) @trans.write("\"this is a test string\"") expect(@prot.read_json_string).to eq("this is a test string") end it "should read json base64" do @trans.write("\"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n\"") expect(@prot.read_json_base64).to eq("this is a test string") end it "should is json numeric" do expect(@prot.is_json_numeric("A")).to eq(false) expect(@prot.is_json_numeric("+")).to eq(true) expect(@prot.is_json_numeric("-")).to eq(true) expect(@prot.is_json_numeric(".")).to eq(true) expect(@prot.is_json_numeric("0")).to eq(true) expect(@prot.is_json_numeric("1")).to eq(true) expect(@prot.is_json_numeric("2")).to eq(true) expect(@prot.is_json_numeric("3")).to eq(true) expect(@prot.is_json_numeric("4")).to eq(true) expect(@prot.is_json_numeric("5")).to eq(true) expect(@prot.is_json_numeric("6")).to eq(true) expect(@prot.is_json_numeric("7")).to eq(true) expect(@prot.is_json_numeric("8")).to eq(true) expect(@prot.is_json_numeric("9")).to eq(true) expect(@prot.is_json_numeric("E")).to eq(true) expect(@prot.is_json_numeric("e")).to eq(true) end it "should read json numeric chars" do @trans.write("1.453E45T") expect(@prot.read_json_numeric_chars).to eq("1.453E45") end it "should read json integer" do @trans.write("1.45\"\"") expect {@prot.read_json_integer}.to raise_error(Thrift::ProtocolException) @prot.read_string @trans.write("1453T") expect(@prot.read_json_integer).to eq(1453) end it "should read json double" do @trans.write("1.45e3e01\"\"") expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException) @prot.read_string @trans.write("\"1.453e01\"") expect {@prot.read_json_double}.to raise_error(Thrift::ProtocolException) @trans.write("1.453e01\"\"") expect(@prot.read_json_double).to eq(14.53) @prot.read_string @trans.write("\"NaN\"") expect(@prot.read_json_double.nan?).to eq(true) @trans.write("\"Infinity\"") expect(@prot.read_json_double).to eq(+1.0/0.0) @trans.write("\"-Infinity\"") expect(@prot.read_json_double).to eq(-1.0/0.0) end it "should read json object start" do @trans.write("{") expect(@prot.read_json_object_start).to eq(nil) end it "should read json object end" do @trans.write("}") expect(@prot.read_json_object_end).to eq(nil) end it "should read json array start" do @trans.write("[") expect(@prot.read_json_array_start).to eq(nil) end it "should read json array end" do @trans.write("]") expect(@prot.read_json_array_end).to eq(nil) end it "should read_message_begin" do @trans.write("[2,") expect {@prot.read_message_begin}.to raise_error(Thrift::ProtocolException) @trans.write("[1,\"name\",12,32\"\"") expect(@prot.read_message_begin).to eq(["name", 12, 32]) end it "should read message end" do @trans.write("]") expect(@prot.read_message_end).to eq(nil) end it "should read struct begin" do @trans.write("{") expect(@prot.read_struct_begin).to eq(nil) end it "should read struct end" do @trans.write("}") expect(@prot.read_struct_end).to eq(nil) end it "should read field begin" do @trans.write("1{\"rec\"") expect(@prot.read_field_begin).to eq([nil, 12, 1]) end it "should read field end" do @trans.write("}") expect(@prot.read_field_end).to eq(nil) end it "should read map begin" do @trans.write("[\"rec\",\"lst\",2,{") expect(@prot.read_map_begin).to eq([12, 15, 2]) end it "should read map end" do @trans.write("}]") expect(@prot.read_map_end).to eq(nil) end it "should read list begin" do @trans.write("[\"rec\",2\"\"") expect(@prot.read_list_begin).to eq([12, 2]) end it "should read list end" do @trans.write("]") expect(@prot.read_list_end).to eq(nil) end it "should read set begin" do @trans.write("[\"rec\",2\"\"") expect(@prot.read_set_begin).to eq([12, 2]) end it "should read set end" do @trans.write("]") expect(@prot.read_set_end).to eq(nil) end it "should read bool" do @trans.write("0\"\"") expect(@prot.read_bool).to eq(false) @prot.read_string @trans.write("1\"\"") expect(@prot.read_bool).to eq(true) end it "should read byte" do @trans.write("60\"\"") expect(@prot.read_byte).to eq(60) end it "should read i16" do @trans.write("1000\"\"") expect(@prot.read_i16).to eq(1000) end it "should read i32" do @trans.write("3000000000\"\"") expect(@prot.read_i32).to eq(3000000000) end it "should read i64" do @trans.write("6000000000\"\"") expect(@prot.read_i64).to eq(6000000000) end it "should read double" do @trans.write("12.23\"\"") expect(@prot.read_double).to eq(12.23) end if RUBY_VERSION >= '1.9' it 'should read string' do @trans.write('"this is a test string"'.force_encoding(Encoding::BINARY)) a = @prot.read_string expect(a).to eq('this is a test string') expect(a.encoding).to eq(Encoding::UTF_8) end it 'should read string with unicode characters' do @trans.write('"this is a test string with unicode characters: \u20AC \u20AD"'.force_encoding(Encoding::BINARY)) a = @prot.read_string expect(a).to eq("this is a test string with unicode characters: \u20AC \u20AD") expect(a.encoding).to eq(Encoding::UTF_8) end else it 'should read string' do @trans.write('"this is a test string"') expect(@prot.read_string).to eq('this is a test string') end end it "should read binary" do @trans.write("\"dGhpcyBpcyBhIHRlc3Qgc3RyaW5n\"") expect(@prot.read_binary).to eq("this is a test string") end it "should read long binary" do @trans.write("\"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==\"") expect(@prot.read_binary.bytes.to_a).to eq((0...256).to_a) end it "should provide a reasonable to_s" do expect(@prot.to_s).to eq("json(memory)") end end describe Thrift::JsonProtocolFactory do it "should create a JsonProtocol" do expect(Thrift::JsonProtocolFactory.new.get_protocol(double("MockTransport"))).to be_instance_of(Thrift::JsonProtocol) end it "should provide a reasonable to_s" do expect(Thrift::JsonProtocolFactory.new.to_s).to eq("json") end end end thrift-0.19.0/lib/rb/spec/base_transport_spec.rb0000644000000000000000000003366614303740367021614 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'BaseTransport' do describe Thrift::TransportException do it "should make type accessible" do exc = Thrift::TransportException.new(Thrift::TransportException::ALREADY_OPEN, "msg") expect(exc.type).to eq(Thrift::TransportException::ALREADY_OPEN) expect(exc.message).to eq("msg") end end describe Thrift::BaseTransport do it "should read the specified size" do transport = Thrift::BaseTransport.new expect(transport).to receive(:read).with(40).ordered.and_return("10 letters") expect(transport).to receive(:read).with(30).ordered.and_return("fifteen letters") expect(transport).to receive(:read).with(15).ordered.and_return("more characters") expect(transport.read_all(40)).to eq("10 lettersfifteen lettersmore characters") end it "should stub out the rest of the methods" do # can't test for stubbiness, so just make sure they're defined [:open?, :open, :close, :read, :write, :flush].each do |sym| expect(Thrift::BaseTransport.method_defined?(sym)).to be_truthy end end it "should alias << to write" do expect(Thrift::BaseTransport.instance_method(:<<)).to eq(Thrift::BaseTransport.instance_method(:write)) end it "should provide a reasonable to_s" do expect(Thrift::BaseTransport.new.to_s).to eq("base") end end describe Thrift::BaseServerTransport do it "should stub out its methods" do [:listen, :accept, :close].each do |sym| expect(Thrift::BaseServerTransport.method_defined?(sym)).to be_truthy end end end describe Thrift::BaseTransportFactory do it "should return the transport it's given" do transport = double("Transport") expect(Thrift::BaseTransportFactory.new.get_transport(transport)).to eql(transport) end it "should provide a reasonable to_s" do expect(Thrift::BaseTransportFactory.new.to_s).to eq("base") end end describe Thrift::BufferedTransport do it "should provide a to_s that describes the encapsulation" do trans = double("Transport") expect(trans).to receive(:to_s).and_return("mock") expect(Thrift::BufferedTransport.new(trans).to_s).to eq("buffered(mock)") end it "should pass through everything but write/flush/read" do trans = double("Transport") expect(trans).to receive(:open?).ordered.and_return("+ open?") expect(trans).to receive(:open).ordered.and_return("+ open") expect(trans).to receive(:flush).ordered # from the close expect(trans).to receive(:close).ordered.and_return("+ close") btrans = Thrift::BufferedTransport.new(trans) expect(btrans.open?).to eq("+ open?") expect(btrans.open).to eq("+ open") expect(btrans.close).to eq("+ close") end it "should buffer reads in chunks of #{Thrift::BufferedTransport::DEFAULT_BUFFER}" do trans = double("Transport") expect(trans).to receive(:read).with(Thrift::BufferedTransport::DEFAULT_BUFFER).and_return("lorum ipsum dolor emet") btrans = Thrift::BufferedTransport.new(trans) expect(btrans.read(6)).to eq("lorum ") expect(btrans.read(6)).to eq("ipsum ") expect(btrans.read(6)).to eq("dolor ") expect(btrans.read(6)).to eq("emet") end it "should buffer writes and send them on flush" do trans = double("Transport") btrans = Thrift::BufferedTransport.new(trans) btrans.write("one/") btrans.write("two/") btrans.write("three/") expect(trans).to receive(:write).with("one/two/three/").ordered expect(trans).to receive(:flush).ordered btrans.flush end it "should only send buffered data once" do trans = double("Transport") btrans = Thrift::BufferedTransport.new(trans) btrans.write("one/") btrans.write("two/") btrans.write("three/") expect(trans).to receive(:write).with("one/two/three/") allow(trans).to receive(:flush) btrans.flush # Nothing to flush with no data btrans.flush end it "should flush on close" do trans = double("Transport") expect(trans).to receive(:close) btrans = Thrift::BufferedTransport.new(trans) expect(btrans).to receive(:flush) btrans.close end it "should not write to socket if there's no data" do trans = double("Transport") expect(trans).to receive(:flush) btrans = Thrift::BufferedTransport.new(trans) btrans.flush end end describe Thrift::BufferedTransportFactory do it "should wrap the given transport in a BufferedTransport" do trans = double("Transport") btrans = double("BufferedTransport") expect(Thrift::BufferedTransport).to receive(:new).with(trans).and_return(btrans) expect(Thrift::BufferedTransportFactory.new.get_transport(trans)).to eq(btrans) end it "should provide a reasonable to_s" do expect(Thrift::BufferedTransportFactory.new.to_s).to eq("buffered") end end describe Thrift::FramedTransport do before(:each) do @trans = double("Transport") end it "should provide a to_s that describes the encapsulation" do trans = double("Transport") expect(trans).to receive(:to_s).and_return("mock") expect(Thrift::FramedTransport.new(trans).to_s).to eq("framed(mock)") end it "should pass through open?/open/close" do ftrans = Thrift::FramedTransport.new(@trans) expect(@trans).to receive(:open?).ordered.and_return("+ open?") expect(@trans).to receive(:open).ordered.and_return("+ open") expect(@trans).to receive(:close).ordered.and_return("+ close") expect(ftrans.open?).to eq("+ open?") expect(ftrans.open).to eq("+ open") expect(ftrans.close).to eq("+ close") end it "should pass through read when read is turned off" do ftrans = Thrift::FramedTransport.new(@trans, false, true) expect(@trans).to receive(:read).with(17).ordered.and_return("+ read") expect(ftrans.read(17)).to eq("+ read") end it "should pass through write/flush when write is turned off" do ftrans = Thrift::FramedTransport.new(@trans, true, false) expect(@trans).to receive(:write).with("foo").ordered.and_return("+ write") expect(@trans).to receive(:flush).ordered.and_return("+ flush") expect(ftrans.write("foo")).to eq("+ write") expect(ftrans.flush).to eq("+ flush") end it "should return a full frame if asked for >= the frame's length" do frame = "this is a frame" expect(@trans).to receive(:read_all).with(4).and_return("\000\000\000\017") expect(@trans).to receive(:read_all).with(frame.length).and_return(frame) expect(Thrift::FramedTransport.new(@trans).read(frame.length + 10)).to eq(frame) end it "should return slices of the frame when asked for < the frame's length" do frame = "this is a frame" expect(@trans).to receive(:read_all).with(4).and_return("\000\000\000\017") expect(@trans).to receive(:read_all).with(frame.length).and_return(frame) ftrans = Thrift::FramedTransport.new(@trans) expect(ftrans.read(4)).to eq("this") expect(ftrans.read(4)).to eq(" is ") expect(ftrans.read(16)).to eq("a frame") end it "should return nothing if asked for <= 0" do expect(Thrift::FramedTransport.new(@trans).read(-2)).to eq("") end it "should pull a new frame when the first is exhausted" do frame = "this is a frame" frame2 = "yet another frame" expect(@trans).to receive(:read_all).with(4).and_return("\000\000\000\017", "\000\000\000\021") expect(@trans).to receive(:read_all).with(frame.length).and_return(frame) expect(@trans).to receive(:read_all).with(frame2.length).and_return(frame2) ftrans = Thrift::FramedTransport.new(@trans) expect(ftrans.read(4)).to eq("this") expect(ftrans.read(8)).to eq(" is a fr") expect(ftrans.read(6)).to eq("ame") expect(ftrans.read(4)).to eq("yet ") expect(ftrans.read(16)).to eq("another frame") end it "should buffer writes" do ftrans = Thrift::FramedTransport.new(@trans) expect(@trans).not_to receive(:write) ftrans.write("foo") ftrans.write("bar") ftrans.write("this is a frame") end it "should write slices of the buffer" do ftrans = Thrift::FramedTransport.new(@trans) ftrans.write("foobar", 3) ftrans.write("barfoo", 1) allow(@trans).to receive(:flush) expect(@trans).to receive(:write).with("\000\000\000\004foob") ftrans.flush end it "should flush frames with a 4-byte header" do ftrans = Thrift::FramedTransport.new(@trans) expect(@trans).to receive(:write).with("\000\000\000\035one/two/three/this is a frame").ordered expect(@trans).to receive(:flush).ordered ftrans.write("one/") ftrans.write("two/") ftrans.write("three/") ftrans.write("this is a frame") ftrans.flush end it "should not flush the same buffered data twice" do ftrans = Thrift::FramedTransport.new(@trans) expect(@trans).to receive(:write).with("\000\000\000\007foo/bar") allow(@trans).to receive(:flush) ftrans.write("foo") ftrans.write("/bar") ftrans.flush expect(@trans).to receive(:write).with("\000\000\000\000") ftrans.flush end end describe Thrift::FramedTransportFactory do it "should wrap the given transport in a FramedTransport" do trans = double("Transport") expect(Thrift::FramedTransport).to receive(:new).with(trans) Thrift::FramedTransportFactory.new.get_transport(trans) end it "should provide a reasonable to_s" do expect(Thrift::FramedTransportFactory.new.to_s).to eq("framed") end end describe Thrift::MemoryBufferTransport do before(:each) do @buffer = Thrift::MemoryBufferTransport.new end it "should provide a reasonable to_s" do expect(@buffer.to_s).to eq("memory") end it "should accept a buffer on input and use it directly" do s = "this is a test" @buffer = Thrift::MemoryBufferTransport.new(s) expect(@buffer.read(4)).to eq("this") s.slice!(-4..-1) expect(@buffer.read(@buffer.available)).to eq(" is a ") end it "should always remain open" do expect(@buffer).to be_open @buffer.close expect(@buffer).to be_open end it "should respond to peek and available" do @buffer.write "some data" expect(@buffer.peek).to be_truthy expect(@buffer.available).to eq(9) @buffer.read(4) expect(@buffer.peek).to be_truthy expect(@buffer.available).to eq(5) @buffer.read(5) expect(@buffer.peek).to be_falsey expect(@buffer.available).to eq(0) end it "should be able to reset the buffer" do @buffer.write "test data" @buffer.reset_buffer("foobar") expect(@buffer.available).to eq(6) expect(@buffer.read(@buffer.available)).to eq("foobar") @buffer.reset_buffer expect(@buffer.available).to eq(0) end it "should copy the given string when resetting the buffer" do s = "this is a test" @buffer.reset_buffer(s) expect(@buffer.available).to eq(14) @buffer.read(10) expect(@buffer.available).to eq(4) expect(s).to eq("this is a test") end it "should return from read what was given in write" do @buffer.write "test data" expect(@buffer.read(4)).to eq("test") expect(@buffer.read(@buffer.available)).to eq(" data") @buffer.write "foo" @buffer.write " bar" expect(@buffer.read(@buffer.available)).to eq("foo bar") end it "should throw an EOFError when there isn't enough data in the buffer" do @buffer.reset_buffer("") expect{@buffer.read(1)}.to raise_error(EOFError) @buffer.reset_buffer("1234") expect{@buffer.read(5)}.to raise_error(EOFError) end end describe Thrift::IOStreamTransport do before(:each) do @input = double("Input", :closed? => false) @output = double("Output", :closed? => false) @trans = Thrift::IOStreamTransport.new(@input, @output) end it "should provide a reasonable to_s" do expect(@input).to receive(:to_s).and_return("mock_input") expect(@output).to receive(:to_s).and_return("mock_output") expect(@trans.to_s).to eq("iostream(input=mock_input,output=mock_output)") end it "should be open as long as both input or output are open" do expect(@trans).to be_open allow(@input).to receive(:closed?).and_return(true) expect(@trans).to be_open allow(@input).to receive(:closed?).and_return(false) allow(@output).to receive(:closed?).and_return(true) expect(@trans).to be_open allow(@input).to receive(:closed?).and_return(true) expect(@trans).not_to be_open end it "should pass through read/write to input/output" do expect(@input).to receive(:read).with(17).and_return("+ read") expect(@output).to receive(:write).with("foobar").and_return("+ write") expect(@trans.read(17)).to eq("+ read") expect(@trans.write("foobar")).to eq("+ write") end it "should close both input and output when closed" do expect(@input).to receive(:close) expect(@output).to receive(:close) @trans.close end end end thrift-0.19.0/lib/rb/spec/nonblocking_server_spec.rb0000644000000000000000000001623014303740367022443 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'NonblockingServer' do class Handler def initialize @queue = Queue.new end attr_accessor :server def greeting(english) if english SpecNamespace::Hello.new else SpecNamespace::Hello.new(:greeting => "Aloha!") end end def block @queue.pop end def unblock(n) n.times { @queue.push true } end def sleep(time) Kernel.sleep time end def shutdown @server.shutdown(0, false) end end class SpecTransport < Thrift::BaseTransport def initialize(transport, queue) @transport = transport @queue = queue @flushed = false end def open? @transport.open? end def open @transport.open end def close @transport.close end def read(sz) @transport.read(sz) end def write(buf,sz=nil) @transport.write(buf, sz) end def flush @queue.push :flushed unless @flushed or @queue.nil? @flushed = true @transport.flush end end class SpecServerSocket < Thrift::ServerSocket def initialize(host, port, queue) super(host, port) @queue = queue end def listen super @queue.push :listen end end describe Thrift::NonblockingServer do before(:each) do @port = 43251 handler = Handler.new processor = SpecNamespace::NonblockingService::Processor.new(handler) queue = Queue.new @transport = SpecServerSocket.new('localhost', @port, queue) transport_factory = Thrift::FramedTransportFactory.new logger = Logger.new(STDERR) logger.level = Logger::WARN @server = Thrift::NonblockingServer.new(processor, @transport, transport_factory, nil, 5, logger) handler.server = @server @server_thread = Thread.new(Thread.current) do |master_thread| begin @server.serve rescue => e p e puts e.backtrace * "\n" master_thread.raise e end end queue.pop @clients = [] @catch_exceptions = false end after(:each) do @clients.each { |client, trans| trans.close } # @server.shutdown(1) @server_thread.kill @transport.close end def setup_client(queue = nil) transport = SpecTransport.new(Thrift::FramedTransport.new(Thrift::Socket.new('localhost', @port)), queue) protocol = Thrift::BinaryProtocol.new(transport) client = SpecNamespace::NonblockingService::Client.new(protocol) transport.open @clients << [client, transport] client end def setup_client_thread(result) queue = Queue.new Thread.new do begin client = setup_client while (cmd = queue.pop) msg, *args = cmd case msg when :block result << client.block when :unblock client.unblock(args.first) when :hello result << client.greeting(true) # ignore result when :sleep client.sleep(args[0] || 0.5) result << :slept when :shutdown client.shutdown when :exit result << :done break end end @clients.each { |c,t| t.close and break if c == client } #close the transport rescue => e raise e unless @catch_exceptions end end queue end it "should handle basic message passing" do client = setup_client expect(client.greeting(true)).to eq(SpecNamespace::Hello.new) expect(client.greeting(false)).to eq(SpecNamespace::Hello.new(:greeting => 'Aloha!')) @server.shutdown end it "should handle concurrent clients" do queue = Queue.new trans_queue = Queue.new 4.times do Thread.new(Thread.current) do |main_thread| begin queue.push setup_client(trans_queue).block rescue => e main_thread.raise e end end end 4.times { trans_queue.pop } setup_client.unblock(4) 4.times { expect(queue.pop).to be_truthy } @server.shutdown end it "should handle messages from more than 5 long-lived connections" do queues = [] result = Queue.new 7.times do |i| queues << setup_client_thread(result) Thread.pass if i == 4 # give the server time to accept connections end client = setup_client # block 4 connections 4.times { |i| queues[i] << :block } queues[4] << :hello queues[5] << :hello queues[6] << :hello 3.times { expect(result.pop).to eq(SpecNamespace::Hello.new) } expect(client.greeting(true)).to eq(SpecNamespace::Hello.new) queues[5] << [:unblock, 4] 4.times { expect(result.pop).to be_truthy } queues[2] << :hello expect(result.pop).to eq(SpecNamespace::Hello.new) expect(client.greeting(false)).to eq(SpecNamespace::Hello.new(:greeting => 'Aloha!')) 7.times { queues.shift << :exit } expect(client.greeting(true)).to eq(SpecNamespace::Hello.new) @server.shutdown end it "should shut down when asked" do # connect first to ensure it's running client = setup_client client.greeting(false) # force a message pass @server.shutdown expect(@server_thread.join(2)).to be_an_instance_of(Thread) end it "should continue processing active messages when shutting down" do result = Queue.new client = setup_client_thread(result) client << :sleep sleep 0.1 # give the server time to start processing the client's message @server.shutdown expect(@server_thread.join(2)).to be_an_instance_of(Thread) expect(result.pop).to eq(:slept) end it "should kill active messages when they don't expire while shutting down" do result = Queue.new client = setup_client_thread(result) client << [:sleep, 10] sleep 0.1 # start processing the client's message @server.shutdown(1) @catch_exceptions = true expect(@server_thread.join(3)).not_to be_nil expect(result).to be_empty end it "should allow shutting down in response to a message" do client = setup_client expect(client.greeting(true)).to eq(SpecNamespace::Hello.new) client.shutdown expect(@server_thread.join(2)).not_to be_nil end end end thrift-0.19.0/lib/rb/spec/Referenced.thrift0000644000000000000000000000316214303740367020477 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace rb OtherNamespace enum SomeEnum { ONE TWO } thrift-0.19.0/lib/rb/spec/unix_socket_spec.rb0000644000000000000000000000773614303740367021120 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' require File.expand_path("#{File.dirname(__FILE__)}/socket_spec_shared") describe 'UNIXSocket' do describe Thrift::UNIXSocket do before(:each) do @path = '/tmp/thrift_spec_socket' @socket = Thrift::UNIXSocket.new(@path) @handle = double("Handle", :closed? => false) allow(@handle).to receive(:close) allow(::UNIXSocket).to receive(:new).and_return(@handle) end it_should_behave_like "a socket" it "should raise a TransportException when it cannot open a socket" do expect(::UNIXSocket).to receive(:new).and_raise(StandardError) expect { @socket.open }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) } end it "should accept an optional timeout" do allow(::UNIXSocket).to receive(:new) expect(Thrift::UNIXSocket.new(@path, 5).timeout).to eq(5) end it "should provide a reasonable to_s" do allow(::UNIXSocket).to receive(:new) expect(Thrift::UNIXSocket.new(@path).to_s).to eq("domain(#{@path})") end end describe Thrift::UNIXServerSocket do before(:each) do @path = '/tmp/thrift_spec_socket' @socket = Thrift::UNIXServerSocket.new(@path) end it "should create a handle when calling listen" do expect(UNIXServer).to receive(:new).with(@path) @socket.listen end it "should create a Thrift::UNIXSocket to wrap accepted sockets" do handle = double("UNIXServer") expect(UNIXServer).to receive(:new).with(@path).and_return(handle) @socket.listen sock = double("sock") expect(handle).to receive(:accept).and_return(sock) trans = double("UNIXSocket") expect(Thrift::UNIXSocket).to receive(:new).and_return(trans) expect(trans).to receive(:handle=).with(sock) expect(@socket.accept).to eq(trans) end it "should close the handle when closed" do handle = double("UNIXServer", :closed? => false) expect(UNIXServer).to receive(:new).with(@path).and_return(handle) @socket.listen expect(handle).to receive(:close) allow(File).to receive(:delete) @socket.close end it "should delete the socket when closed" do handle = double("UNIXServer", :closed? => false) expect(UNIXServer).to receive(:new).with(@path).and_return(handle) @socket.listen allow(handle).to receive(:close) expect(File).to receive(:delete).with(@path) @socket.close end it "should return nil when accepting if there is no handle" do expect(@socket.accept).to be_nil end it "should return true for closed? when appropriate" do handle = double("UNIXServer", :closed? => false) allow(UNIXServer).to receive(:new).and_return(handle) allow(File).to receive(:delete) @socket.listen expect(@socket).not_to be_closed allow(handle).to receive(:close) @socket.close expect(@socket).to be_closed @socket.listen expect(@socket).not_to be_closed allow(handle).to receive(:closed?).and_return(true) expect(@socket).to be_closed end it "should provide a reasonable to_s" do expect(@socket.to_s).to eq("domain(#{@path})") end end end thrift-0.19.0/lib/rb/spec/socket_spec_shared.rb0000644000000000000000000001013714303740367021370 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' shared_examples_for "a socket" do it "should open a socket" do expect(@socket.open).to eq(@handle) end it "should be open whenever it has a handle" do expect(@socket).not_to be_open @socket.open expect(@socket).to be_open @socket.handle = nil expect(@socket).not_to be_open @socket.handle = @handle @socket.close expect(@socket).not_to be_open end it "should write data to the handle" do @socket.open expect(@handle).to receive(:write).with("foobar") @socket.write("foobar") expect(@handle).to receive(:write).with("fail").and_raise(StandardError) expect { @socket.write("fail") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) } end it "should raise an error when it cannot read from the handle" do @socket.open expect(@handle).to receive(:readpartial).with(17).and_raise(StandardError) expect { @socket.read(17) }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) } end it "should return the data read when reading from the handle works" do @socket.open expect(@handle).to receive(:readpartial).with(17).and_return("test data") expect(@socket.read(17)).to eq("test data") end it "should declare itself as closed when it has an error" do @socket.open expect(@handle).to receive(:write).with("fail").and_raise(StandardError) expect(@socket).to be_open expect { @socket.write("fail") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::NOT_OPEN) } expect(@socket).not_to be_open end it "should raise an error when the stream is closed" do @socket.open allow(@handle).to receive(:closed?).and_return(true) expect(@socket).not_to be_open expect { @socket.write("fail") }.to raise_error(IOError, "closed stream") expect { @socket.read(10) }.to raise_error(IOError, "closed stream") end it "should support the timeout accessor for read" do @socket.timeout = 3 @socket.open expect(IO).to receive(:select).with([@handle], nil, nil, 3).and_return([[@handle], [], []]) expect(@handle).to receive(:readpartial).with(17).and_return("test data") expect(@socket.read(17)).to eq("test data") end it "should support the timeout accessor for write" do @socket.timeout = 3 @socket.open expect(IO).to receive(:select).with(nil, [@handle], nil, 3).twice.and_return([[], [@handle], []]) expect(@handle).to receive(:write_nonblock).with("test data").and_return(4) expect(@handle).to receive(:write_nonblock).with(" data").and_return(5) expect(@socket.write("test data")).to eq(9) end it "should raise an error when read times out" do @socket.timeout = 0.5 @socket.open expect(IO).to receive(:select).once {sleep(0.5); nil} expect { @socket.read(17) }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::TIMED_OUT) } end it "should raise an error when write times out" do @socket.timeout = 0.5 @socket.open allow(IO).to receive(:select).with(nil, [@handle], nil, 0.5).and_return(nil) expect { @socket.write("test data") }.to raise_error(Thrift::TransportException) { |e| expect(e.type).to eq(Thrift::TransportException::TIMED_OUT) } end end thrift-0.19.0/lib/rb/spec/ThriftNamespacedSpec.thrift0000644000000000000000000000354114303740367022472 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace rb NamespacedSpecNamespace include "Referenced.thrift" struct Hello { 1: string greeting = "hello world" } service NamespacedNonblockingService { Hello greeting(1:bool english) bool block() oneway void unblock(1:i32 n) oneway void shutdown() void sleep(1:double seconds) } thrift-0.19.0/lib/rb/spec/server_spec.rb0000644000000000000000000001732414303740367020065 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Server' do describe Thrift::BaseServer do before(:each) do @processor = double("Processor") @serverTrans = double("ServerTransport") @trans = double("BaseTransport") @prot = double("BaseProtocol") @server = described_class.new(@processor, @serverTrans, @trans, @prot) end it "should default to BaseTransportFactory and BinaryProtocolFactory when not specified" do @server = Thrift::BaseServer.new(double("Processor"), double("BaseServerTransport")) expect(@server.instance_variable_get(:'@transport_factory')).to be_an_instance_of(Thrift::BaseTransportFactory) expect(@server.instance_variable_get(:'@protocol_factory')).to be_an_instance_of(Thrift::BinaryProtocolFactory) end it "should not serve" do expect { @server.serve()}.to raise_error(NotImplementedError) end it "should provide a reasonable to_s" do expect(@serverTrans).to receive(:to_s).once.and_return("serverTrans") expect(@trans).to receive(:to_s).once.and_return("trans") expect(@prot).to receive(:to_s).once.and_return("prot") expect(@server.to_s).to eq("server(prot(trans(serverTrans)))") end end describe Thrift::SimpleServer do before(:each) do @processor = double("Processor") @serverTrans = double("ServerTransport") @trans = double("BaseTransport") @prot = double("BaseProtocol") @client = double("Client") @server = described_class.new(@processor, @serverTrans, @trans, @prot) end it "should provide a reasonable to_s" do expect(@serverTrans).to receive(:to_s).once.and_return("serverTrans") expect(@trans).to receive(:to_s).once.and_return("trans") expect(@prot).to receive(:to_s).once.and_return("prot") expect(@server.to_s).to eq("simple(server(prot(trans(serverTrans))))") end it "should serve in the main thread" do expect(@serverTrans).to receive(:listen).ordered expect(@serverTrans).to receive(:accept).exactly(3).times.and_return(@client) expect(@trans).to receive(:get_transport).exactly(3).times.with(@client).and_return(@trans) expect(@prot).to receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot) x = 0 expect(@processor).to receive(:process).exactly(3).times.with(@prot, @prot) do case (x += 1) when 1 then raise Thrift::TransportException when 2 then raise Thrift::ProtocolException when 3 then throw :stop end end expect(@trans).to receive(:close).exactly(3).times expect(@serverTrans).to receive(:close).ordered expect { @server.serve }.to throw_symbol(:stop) end end describe Thrift::ThreadedServer do before(:each) do @processor = double("Processor") @serverTrans = double("ServerTransport") @trans = double("BaseTransport") @prot = double("BaseProtocol") @client = double("Client") @server = described_class.new(@processor, @serverTrans, @trans, @prot) end it "should provide a reasonable to_s" do expect(@serverTrans).to receive(:to_s).once.and_return("serverTrans") expect(@trans).to receive(:to_s).once.and_return("trans") expect(@prot).to receive(:to_s).once.and_return("prot") expect(@server.to_s).to eq("threaded(server(prot(trans(serverTrans))))") end it "should serve using threads" do expect(@serverTrans).to receive(:listen).ordered expect(@serverTrans).to receive(:accept).exactly(3).times.and_return(@client) expect(@trans).to receive(:get_transport).exactly(3).times.with(@client).and_return(@trans) expect(@prot).to receive(:get_protocol).exactly(3).times.with(@trans).and_return(@prot) expect(Thread).to receive(:new).with(@prot, @trans).exactly(3).times.and_yield(@prot, @trans) x = 0 expect(@processor).to receive(:process).exactly(3).times.with(@prot, @prot) do case (x += 1) when 1 then raise Thrift::TransportException when 2 then raise Thrift::ProtocolException when 3 then throw :stop end end expect(@trans).to receive(:close).exactly(3).times expect(@serverTrans).to receive(:close).ordered expect { @server.serve }.to throw_symbol(:stop) end end describe Thrift::ThreadPoolServer do before(:each) do @processor = double("Processor") @server_trans = double("ServerTransport") @trans = double("BaseTransport") @prot = double("BaseProtocol") @client = double("Client") @server = described_class.new(@processor, @server_trans, @trans, @prot) sleep(0.15) end it "should provide a reasonable to_s" do expect(@server_trans).to receive(:to_s).once.and_return("server_trans") expect(@trans).to receive(:to_s).once.and_return("trans") expect(@prot).to receive(:to_s).once.and_return("prot") expect(@server.to_s).to eq("threadpool(server(prot(trans(server_trans))))") end it "should serve inside a thread" do exception_q = @server.instance_variable_get(:@exception_q) expect_any_instance_of(described_class).to receive(:serve) do exception_q.push(StandardError.new('ERROR')) end expect { @server.rescuable_serve }.to(raise_error('ERROR')) sleep(0.15) end it "should avoid running the server twice when retrying rescuable_serve" do exception_q = @server.instance_variable_get(:@exception_q) expect_any_instance_of(described_class).to receive(:serve) do exception_q.push(StandardError.new('ERROR1')) exception_q.push(StandardError.new('ERROR2')) end expect { @server.rescuable_serve }.to(raise_error('ERROR1')) expect { @server.rescuable_serve }.to(raise_error('ERROR2')) end it "should serve using a thread pool" do thread_q = double("SizedQueue") exception_q = double("Queue") @server.instance_variable_set(:@thread_q, thread_q) @server.instance_variable_set(:@exception_q, exception_q) expect(@server_trans).to receive(:listen).ordered expect(thread_q).to receive(:push).with(:token) expect(thread_q).to receive(:pop) expect(Thread).to receive(:new).and_yield expect(@server_trans).to receive(:accept).exactly(3).times.and_return(@client) expect(@trans).to receive(:get_transport).exactly(3).times.and_return(@trans) expect(@prot).to receive(:get_protocol).exactly(3).times.and_return(@prot) x = 0 error = RuntimeError.new("Stopped") expect(@processor).to receive(:process).exactly(3).times.with(@prot, @prot) do case (x += 1) when 1 then raise Thrift::TransportException when 2 then raise Thrift::ProtocolException when 3 then raise error end end expect(@trans).to receive(:close).exactly(3).times expect(exception_q).to receive(:push).with(error).and_throw(:stop) expect(@server_trans).to receive(:close) expect { @server.serve }.to(throw_symbol(:stop)) end end end thrift-0.19.0/lib/rb/spec/client_spec.rb0000644000000000000000000001030114370300523020007 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'spec_helper' describe 'Client' do class ClientSpec include Thrift::Client end before(:each) do @prot = double("MockProtocol") @client = ClientSpec.new(@prot) end describe Thrift::Client do it "should re-use iprot for oprot if not otherwise specified" do expect(@client.instance_variable_get(:'@iprot')).to eql(@prot) expect(@client.instance_variable_get(:'@oprot')).to eql(@prot) end it "should send a test message" do expect(@prot).to receive(:write_message_begin).with('testMessage', Thrift::MessageTypes::CALL, 0) mock_args = double('#') expect(mock_args).to receive(:foo=).with('foo') expect(mock_args).to receive(:bar=).with(42) expect(mock_args).to receive(:write).with(@prot) expect(@prot).to receive(:write_message_end) expect(@prot).to receive(:trans) do double('trans').tap do |trans| expect(trans).to receive(:flush) end end klass = double("TestMessage_args", :new => mock_args) @client.send_message('testMessage', klass, :foo => 'foo', :bar => 42) end it "should increment the sequence id when sending messages" do pending "it seems sequence ids are completely ignored right now" @prot.expect(:write_message_begin).with('testMessage', Thrift::MessageTypes::CALL, 0).ordered @prot.expect(:write_message_begin).with('testMessage2', Thrift::MessageTypes::CALL, 1).ordered @prot.expect(:write_message_begin).with('testMessage3', Thrift::MessageTypes::CALL, 2).ordered @prot.stub!(:write_message_end) @prot.stub!(:trans).and_return double("trans").as_null_object @client.send_message('testMessage', double("args class").as_null_object) @client.send_message('testMessage2', double("args class").as_null_object) @client.send_message('testMessage3', double("args class").as_null_object) end it "should receive a test message" do expect(@prot).to receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::CALL, 0] expect(@prot).to receive(:read_message_end) mock_klass = double("#") expect(mock_klass).to receive(:read).with(@prot) @client.receive_message_begin() @client.receive_message(double("MockClass", :new => mock_klass)) end it "should handle received exceptions" do expect(@prot).to receive(:read_message_begin).and_return [nil, Thrift::MessageTypes::EXCEPTION, 0] expect(@prot).to receive(:read_message_end) expect(Thrift::ApplicationException).to receive(:new) do StandardError.new.tap do |mock_exc| expect(mock_exc).to receive(:read).with(@prot) end end fname, mtype, sqeid = @client.receive_message_begin() expect { @client.handle_exception(mtype) }.to raise_error(StandardError) end it "should close the transport if an error occurs while sending a message" do allow(@prot).to receive(:write_message_begin) expect(@prot).not_to receive(:write_message_end) mock_args = double("#") expect(mock_args).to receive(:write).with(@prot).and_raise(StandardError) trans = double("MockTransport") allow(@prot).to receive(:trans).and_return(trans) expect(trans).to receive(:close) klass = double("TestMessage_args", :new => mock_args) expect { @client.send_message("testMessage", klass) }.to raise_error(StandardError) end end end thrift-0.19.0/lib/rb/thrift.gemspec0000644000000000000000000000303714454461475017136 0ustar00rootroot00000000000000# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' s.version = '0.19.0' s.authors = ['Apache Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' s.summary = %q{Ruby bindings for Apache Thrift} s.description = %q{Ruby bindings for the Apache Thrift RPC system} s.license = 'Apache-2.0' s.extensions = ['ext/extconf.rb'] s.has_rdoc = true s.rdoc_options = %w[--line-numbers --inline-source --title Thrift --main README] s.rubyforge_project = 'thrift' dir = File.expand_path(File.dirname(__FILE__)) s.files = Dir.glob("{lib,spec}/**/*") s.test_files = Dir.glob("{test,spec,benchmark}/**/*") s.executables = Dir.glob("{bin}/**/*") s.extra_rdoc_files = %w[README.md] + Dir.glob("{ext,lib}/**/*.{c,h,rb}") s.require_paths = %w[lib ext] s.add_development_dependency 'bundler', '>= 1.11' s.add_development_dependency 'pry', '~> 0.11.3' s.add_development_dependency 'pry-byebug', '~> 3.6' s.add_development_dependency 'pry-stack_explorer', '~> 0.4.9.2' s.add_development_dependency 'rack', '= 2.2.6.4' s.add_development_dependency 'rack-test', '~> 0.8.3' s.add_development_dependency 'rake', '~> 12.3' s.add_development_dependency 'rspec', '~> 3.7' s.add_development_dependency 'srv', '~> 1.0' s.add_development_dependency 'thin', '~> 1.7' end thrift-0.19.0/lib/rb/Rakefile0000644000000000000000000000755214370300523015723 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'rubygems' require 'rake' require 'rake/clean' require 'rspec/core/rake_task' THRIFT = '../../compiler/cpp/thrift' task :default => [:gem] task :spec => [:'gen-rb', :build_ext, :realspec] RSpec::Core::RakeTask.new(:realspec) do |t| t.rspec_opts = ['--color', '--format d'] end RSpec::Core::RakeTask.new(:'spec:rcov') do |t| t.rspec_opts = ['--color', '--format d'] t.rcov = true t.rcov_opts = ['--exclude', '^spec,/gems/'] end desc 'Compile the .thrift files for the specs' task :'gen-rb' => [:'gen-rb:spec', :'gen-rb:namespaced_spec', :'gen-rb:flat_spec', :'gen-rb:benchmark', :'gen-rb:debug_proto'] namespace :'gen-rb' do task :'spec' do dir = File.dirname(__FILE__) + '/spec' sh THRIFT, '--gen', 'rb', '-o', dir, "#{dir}/ThriftSpec.thrift" end task :'namespaced_spec' do dir = File.dirname(__FILE__) + '/spec' sh THRIFT, '--gen', 'rb:namespaced', '--recurse', '-o', dir, "#{dir}/ThriftNamespacedSpec.thrift" sh THRIFT, '--gen', 'rb:namespaced', '--recurse', '-o', dir, "#{dir}/BaseService.thrift" sh THRIFT, '--gen', 'rb:namespaced', '--recurse', '-o', dir, "#{dir}/ExtendedService.thrift" end task :'flat_spec' do dir = File.dirname(__FILE__) + '/spec' FileUtils.mkdir_p("#{dir}/gen-rb/flat") sh THRIFT, '--gen', 'rb', '--recurse', '-out', "#{dir}/gen-rb/flat", "#{dir}/ThriftNamespacedSpec.thrift" end task :'benchmark' do dir = File.dirname(__FILE__) + '/benchmark' sh THRIFT, '--gen', 'rb', '-o', dir, "#{dir}/Benchmark.thrift" end task :'debug_proto' do sh "mkdir", "-p", "test/debug_proto" sh THRIFT, '--gen', 'rb', "-o", "test/debug_proto", "../../test/v0.16/DebugProtoTest.thrift" end end desc "Build the native library" task :build_ext => :'gen-rb' do next if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ Dir::chdir(File::dirname('ext/extconf.rb')) do unless sh "ruby #{File::basename('ext/extconf.rb')}" $stderr.puts "Failed to run extconf" break end unless sh "make" $stderr.puts "make failed" break end end end desc 'Run the compiler tests (requires full thrift checkout)' task :test do # ensure this is a full thrift checkout and not a tarball of the ruby libs cmd = 'head -1 ../../README.md 2>/dev/null | grep Thrift >/dev/null 2>/dev/null' system(cmd) or fail "rake test requires a full thrift checkout" sh 'make', '-C', File.dirname(__FILE__) + "/../../test/rb", "check" end desc 'Run benchmarking of NonblockingServer' task :benchmark do ruby 'benchmark/benchmark.rb' end desc 'Builds the thrift gem' task :gem => [:spec, :build_ext] do unless sh 'gem', 'build', 'thrift.gemspec' $stderr.puts "Failed to build thrift gem" break end end desc 'Install the thrift gem' task :install => [:gem] do unless sh 'gem', 'install', Dir.glob('thrift-*.gem').last $stderr.puts "Failed to install thrift gem" break end end CLEAN.include [ '.bundle', 'benchmark/gen-rb', 'coverage', 'ext/*.{o,bundle,so,dll}', 'ext/mkmf.log', 'ext/Makefile', 'ext/conftest.dSYM', 'Gemfile.lock', 'mkmf.log', 'pkg', 'spec/gen-rb', 'test', 'thrift-*.gem' ] thrift-0.19.0/lib/rb/benchmark/0000777000000000000000000000000014303740367016215 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/benchmark/benchmark.rb0000644000000000000000000002077414303740367020502 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'rubygems' $:.unshift File.dirname(__FILE__) + '/../lib' require 'thrift' require 'stringio' HOST = '127.0.0.1' PORT = 42587 ############### ## Server ############### class Server attr_accessor :serverclass attr_accessor :interpreter attr_accessor :host attr_accessor :port def initialize(opts) @serverclass = opts.fetch(:class, Thrift::NonblockingServer) @interpreter = opts.fetch(:interpreter, "ruby") @host = opts.fetch(:host, ::HOST) @port = opts.fetch(:port, ::PORT) end def start return if @serverclass == Object args = (File.basename(@interpreter) == "jruby" ? "-J-server" : "") @pipe = IO.popen("#{@interpreter} #{args} #{File.dirname(__FILE__)}/server.rb #{@host} #{@port} #{@serverclass.name}", "r+") Marshal.load(@pipe) # wait until the server has started sleep 0.4 # give the server time to actually start spawning sockets end def shutdown return unless @pipe Marshal.dump(:shutdown, @pipe) begin @pipe.read(10) # block until the server shuts down rescue EOFError end @pipe.close @pipe = nil end end class BenchmarkManager def initialize(opts, server) @socket = opts.fetch(:socket) do @host = opts.fetch(:host, 'localhost') @port = opts.fetch(:port) nil end @num_processes = opts.fetch(:num_processes, 40) @clients_per_process = opts.fetch(:clients_per_process, 10) @calls_per_client = opts.fetch(:calls_per_client, 50) @interpreter = opts.fetch(:interpreter, "ruby") @server = server @log_exceptions = opts.fetch(:log_exceptions, false) end def run @pool = [] @benchmark_start = Time.now puts "Spawning benchmark processes..." @num_processes.times do spawn sleep 0.02 # space out spawns end collect_output @benchmark_end = Time.now # we know the procs are done here translate_output analyze_output report_output end def spawn pipe = IO.popen("#{@interpreter} #{File.dirname(__FILE__)}/client.rb #{"-log-exceptions" if @log_exceptions} #{@host} #{@port} #{@clients_per_process} #{@calls_per_client}") @pool << pipe end def socket_class if @socket Thrift::UNIXSocket else Thrift::Socket end end def collect_output puts "Collecting output..." # read from @pool until all sockets are closed @buffers = Hash.new { |h,k| h[k] = '' } until @pool.empty? rd, = select(@pool) next if rd.nil? rd.each do |fd| begin @buffers[fd] << fd.readpartial(4096) rescue EOFError @pool.delete fd end end end end def translate_output puts "Translating output..." @output = [] @buffers.each do |fd, buffer| strio = StringIO.new(buffer) logs = [] begin loop do logs << Marshal.load(strio) end rescue EOFError @output << logs end end end def analyze_output puts "Analyzing output..." call_times = [] client_times = [] connection_failures = [] connection_errors = [] shortest_call = 0 shortest_client = 0 longest_call = 0 longest_client = 0 @output.each do |logs| cur_call, cur_client = nil logs.each do |tok, time| case tok when :start cur_client = time when :call_start cur_call = time when :call_end delta = time - cur_call call_times << delta longest_call = delta unless longest_call > delta shortest_call = delta if shortest_call == 0 or delta < shortest_call cur_call = nil when :end delta = time - cur_client client_times << delta longest_client = delta unless longest_client > delta shortest_client = delta if shortest_client == 0 or delta < shortest_client cur_client = nil when :connection_failure connection_failures << time when :connection_error connection_errors << time end end end @report = {} @report[:total_calls] = call_times.inject(0.0) { |a,t| a += t } @report[:avg_calls] = @report[:total_calls] / call_times.size @report[:total_clients] = client_times.inject(0.0) { |a,t| a += t } @report[:avg_clients] = @report[:total_clients] / client_times.size @report[:connection_failures] = connection_failures.size @report[:connection_errors] = connection_errors.size @report[:shortest_call] = shortest_call @report[:shortest_client] = shortest_client @report[:longest_call] = longest_call @report[:longest_client] = longest_client @report[:total_benchmark_time] = @benchmark_end - @benchmark_start @report[:fastthread] = $".include?('fastthread.bundle') end def report_output fmt = "%.4f seconds" puts tabulate "%d", [["Server class", "%s"], @server.serverclass == Object ? "" : @server.serverclass], [["Server interpreter", "%s"], @server.interpreter], [["Client interpreter", "%s"], @interpreter], [["Socket class", "%s"], socket_class], ["Number of processes", @num_processes], ["Clients per process", @clients_per_process], ["Calls per client", @calls_per_client], [["Using fastthread", "%s"], @report[:fastthread] ? "yes" : "no"] puts failures = (@report[:connection_failures] > 0) tabulate fmt, [["Connection failures", "%d", [:red, :bold]], @report[:connection_failures]], [["Connection errors", "%d", [:red, :bold]], @report[:connection_errors]], ["Average time per call", @report[:avg_calls]], ["Average time per client (%d calls)" % @calls_per_client, @report[:avg_clients]], ["Total time for all calls", @report[:total_calls]], ["Real time for benchmarking", @report[:total_benchmark_time]], ["Shortest call time", @report[:shortest_call]], ["Longest call time", @report[:longest_call]], ["Shortest client time (%d calls)" % @calls_per_client, @report[:shortest_client]], ["Longest client time (%d calls)" % @calls_per_client, @report[:longest_client]] end ANSI = { :reset => 0, :bold => 1, :black => 30, :red => 31, :green => 32, :yellow => 33, :blue => 34, :magenta => 35, :cyan => 36, :white => 37 } def tabulate(fmt, *labels_and_values) labels = labels_and_values.map { |l| Array === l ? l.first : l } label_width = labels.inject(0) { |w,l| l.size > w ? l.size : w } labels_and_values.each do |(l,v)| f = fmt l, f, c = l if Array === l fmtstr = "%-#{label_width+1}s #{f}" if STDOUT.tty? and c and v.to_i > 0 fmtstr = "\e[#{[*c].map { |x| ANSI[x] } * ";"}m" + fmtstr + "\e[#{ANSI[:reset]}m" end puts fmtstr % [l+":", v] end end end def resolve_const(const) const and const.split('::').inject(Object) { |k,c| k.const_get(c) } end puts "Starting server..." args = {} args[:interpreter] = ENV['THRIFT_SERVER_INTERPRETER'] || ENV['THRIFT_INTERPRETER'] || "ruby" args[:class] = resolve_const(ENV['THRIFT_SERVER']) || Thrift::NonblockingServer args[:host] = ENV['THRIFT_HOST'] || HOST args[:port] = (ENV['THRIFT_PORT'] || PORT).to_i server = Server.new(args) server.start args = {} args[:host] = ENV['THRIFT_HOST'] || HOST args[:port] = (ENV['THRIFT_PORT'] || PORT).to_i args[:num_processes] = (ENV['THRIFT_NUM_PROCESSES'] || 40).to_i args[:clients_per_process] = (ENV['THRIFT_NUM_CLIENTS'] || 5).to_i args[:calls_per_client] = (ENV['THRIFT_NUM_CALLS'] || 50).to_i args[:interpreter] = ENV['THRIFT_CLIENT_INTERPRETER'] || ENV['THRIFT_INTERPRETER'] || "ruby" args[:log_exceptions] = !!ENV['THRIFT_LOG_EXCEPTIONS'] BenchmarkManager.new(args, server).run server.shutdown thrift-0.19.0/lib/rb/benchmark/server.rb0000644000000000000000000000451014303740367020044 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.unshift File.dirname(__FILE__) + '/../lib' require 'thrift' $:.unshift File.dirname(__FILE__) + "/gen-rb" require 'benchmark_service' module Server include Thrift class BenchmarkHandler # 1-based index into the fibonacci sequence def fibonacci(n) seq = [1, 1] 3.upto(n) do seq << seq[-1] + seq[-2] end seq[n-1] # n is 1-based end end def self.start_server(host, port, serverClass) handler = BenchmarkHandler.new processor = ThriftBenchmark::BenchmarkService::Processor.new(handler) transport = ServerSocket.new(host, port) transport_factory = FramedTransportFactory.new args = [processor, transport, transport_factory, nil, 20] if serverClass == NonblockingServer logger = Logger.new(STDERR) logger.level = Logger::WARN args << logger end server = serverClass.new(*args) @server_thread = Thread.new do server.serve end @server = server end def self.shutdown return if @server.nil? if @server.respond_to? :shutdown @server.shutdown else @server_thread.kill end end end def resolve_const(const) const and const.split('::').inject(Object) { |k,c| k.const_get(c) } end host, port, serverklass = ARGV Server.start_server(host, port.to_i, resolve_const(serverklass)) # let our host know that the interpreter has started # ideally we'd wait until the server was serving, but we don't have a hook for that Marshal.dump(:started, STDOUT) STDOUT.flush Marshal.load(STDIN) # wait until we're instructed to shut down Server.shutdown thrift-0.19.0/lib/rb/benchmark/thin_server.rb0000644000000000000000000000274714303740367021100 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.unshift File.dirname(__FILE__) + '/../lib' require 'thrift' $:.unshift File.dirname(__FILE__) + "/gen-rb" require 'benchmark_service' HOST = 'localhost' PORT = 42587 class BenchmarkHandler # 1-based index into the fibonacci sequence def fibonacci(n) seq = [1, 1] 3.upto(n) do seq << seq[-1] + seq[-2] end seq[n-1] # n is 1-based end end handler = BenchmarkHandler.new processor = ThriftBenchmark::BenchmarkService::Processor.new(handler) transport = Thrift::ServerSocket.new(HOST, PORT) transport_factory = Thrift::FramedTransportFactory.new logger = Logger.new(STDERR) logger.level = Logger::WARN Thrift::NonblockingServer.new(processor, transport, transport_factory, nil, 20, logger).serve thrift-0.19.0/lib/rb/benchmark/client.rb0000644000000000000000000000472614303740367020025 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # $:.unshift File.dirname(__FILE__) + '/../lib' require 'thrift' $:.unshift File.dirname(__FILE__) + "/gen-rb" require 'benchmark_service' class Client def initialize(host, port, clients_per_process, calls_per_client, log_exceptions) @host = host @port = port @clients_per_process = clients_per_process @calls_per_client = calls_per_client @log_exceptions = log_exceptions end def run @clients_per_process.times do socket = Thrift::Socket.new(@host, @port) transport = Thrift::FramedTransport.new(socket) protocol = Thrift::BinaryProtocol.new(transport) client = ThriftBenchmark::BenchmarkService::Client.new(protocol) begin start = Time.now transport.open Marshal.dump [:start, start], STDOUT rescue => e Marshal.dump [:connection_failure, Time.now], STDOUT print_exception e if @log_exceptions else begin @calls_per_client.times do Marshal.dump [:call_start, Time.now], STDOUT client.fibonacci(15) Marshal.dump [:call_end, Time.now], STDOUT end transport.close Marshal.dump [:end, Time.now], STDOUT rescue Thrift::TransportException => e Marshal.dump [:connection_error, Time.now], STDOUT print_exception e if @log_exceptions end end end end def print_exception(e) STDERR.puts "ERROR: #{e.message}" STDERR.puts "\t#{e.backtrace * "\n\t"}" end end log_exceptions = true if ARGV[0] == '-log-exceptions' and ARGV.shift host, port, clients_per_process, calls_per_client = ARGV Client.new(host, port.to_i, clients_per_process.to_i, calls_per_client.to_i, log_exceptions).run thrift-0.19.0/lib/rb/benchmark/Benchmark.thrift0000644000000000000000000000154714303740367021334 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # namespace rb ThriftBenchmark service BenchmarkService { i32 fibonacci(1:byte n) } thrift-0.19.0/lib/rb/Makefile.am0000644000000000000000000000236014303740367016314 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # DESTDIR ?= / if HAVE_BUNDLER all-local: $(BUNDLER) install $(BUNDLER) exec rake build_ext install-exec-hook: $(BUNDLER) exec rake install clean-local: $(BUNDLER) install $(BUNDLER) exec rake clean $(RM) -r spec/gen-rb/ check-local: all $(BUNDLER) install $(BUNDLER) exec rake endif dist-hook: $(RM) -r $(distdir)/spec/gen-rb/ EXTRA_DIST = \ coding_standards.md \ Rakefile \ Gemfile \ thrift.gemspec \ lib \ ext \ benchmark \ script \ spec \ README.md thrift-0.19.0/lib/rb/script/0000777000000000000000000000000014303740367015567 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/script/read_struct.rb0000644000000000000000000000256314303740367020435 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require "spec/spec_helper" path, factory_class = ARGV factory = eval(factory_class).new deser = Thrift::Deserializer.new(factory) cpts = CompactProtoTestStruct.new CompactProtoTestStruct.constants.each do |const| cpts.instance_variable_set("@#{const}", nil) end data = File.read(path) deser.deserialize(cpts, data) if cpts == Fixtures::COMPACT_PROTOCOL_TEST_STRUCT puts "Object verified successfully!" else puts "Object failed verification! Expected #{Fixtures::COMPACT_PROTOCOL_TEST_STRUCT.inspect} but got #{cpts.inspect}" puts cpts.differences(Fixtures::COMPACT_PROTOCOL_TEST_STRUCT) end thrift-0.19.0/lib/rb/script/proto_benchmark.rb0000644000000000000000000000712514303740367021272 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require File.dirname(__FILE__) + "/../spec/spec_helper.rb" require "benchmark" # require "ruby-prof" obj = Fixtures::COMPACT_PROTOCOL_TEST_STRUCT HOW_MANY = 1_000 binser = Thrift::Serializer.new bin_data = binser.serialize(obj) bindeser = Thrift::Deserializer.new accel_bin_ser = Thrift::Serializer.new(Thrift::BinaryProtocolAcceleratedFactory.new) accel_bin_deser = Thrift::Deserializer.new(Thrift::BinaryProtocolAcceleratedFactory.new) compact_ser = Thrift::Serializer.new(Thrift::CompactProtocolFactory.new) compact_data = compact_ser.serialize(obj) compact_deser = Thrift::Deserializer.new(Thrift::CompactProtocolFactory.new) Benchmark.bm(60) do |reporter| reporter.report("binary protocol, write") do HOW_MANY.times do binser.serialize(obj) end end reporter.report("accelerated binary protocol, write") do HOW_MANY.times do accel_bin_ser.serialize(obj) end end reporter.report("compact protocol, write") do # RubyProf.start HOW_MANY.times do compact_ser.serialize(obj) end # result = RubyProf.stop # printer = RubyProf::GraphHtmlPrinter.new(result) # file = File.open("profile.html", "w+") # printer.print(file, 0) # file.close end reporter.report("binary protocol, read") do HOW_MANY.times do bindeser.deserialize(obj, bin_data) end end reporter.report("accelerated binary protocol, read") do HOW_MANY.times do accel_bin_deser.deserialize(obj, bin_data) end end reporter.report("compact protocol, read") do HOW_MANY.times do compact_deser.deserialize(obj, compact_data) end end # f = File.new("/tmp/testfile", "w") # proto = Thrift::BinaryProtocolAccelerated.new(Thrift::IOStreamTransport.new(Thrift::MemoryBufferTransport.new, f)) # reporter.report("accelerated binary protocol, write (to disk)") do # HOW_MANY.times do # obj.write(proto) # end # f.flush # end # f.close # # f = File.new("/tmp/testfile", "r") # proto = Thrift::BinaryProtocolAccelerated.new(Thrift::IOStreamTransport.new(f, Thrift::MemoryBufferTransport.new)) # reporter.report("accelerated binary protocol, read (from disk)") do # HOW_MANY.times do # obj.read(proto) # end # end # f.close # # f = File.new("/tmp/testfile", "w") # reporter.report("compact protocol, write (to disk)") do # proto = Thrift::CompactProtocol.new(Thrift::IOStreamTransport.new(Thrift::MemoryBufferTransport.new, f)) # HOW_MANY.times do # obj.write(proto) # end # f.flush # end # f.close # # f = File.new("/tmp/testfile", "r") # reporter.report("compact protocol, read (from disk)") do # proto = Thrift::CompactProtocol.new(Thrift::IOStreamTransport.new(f, Thrift::MemoryBufferTransport.new)) # HOW_MANY.times do # obj.read(proto) # end # end # f.close end thrift-0.19.0/lib/rb/script/write_struct.rb0000644000000000000000000000177214303740367020655 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require "spec/spec_helper" path, factory_class = ARGV factory = eval(factory_class).new ser = Thrift::Serializer.new(factory) File.open(path, "w") do |file| file.write(ser.serialize(Fixtures::COMPACT_PROTOCOL_TEST_STRUCT)) endthrift-0.19.0/lib/rb/README.md0000644000000000000000000000267314303740367015546 0ustar00rootroot00000000000000Thrift Ruby Software Library http://thrift.apache.org == LICENSE: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. == DESCRIPTION: Thrift is a strongly-typed language-agnostic RPC system. This library is the ruby implementation for both clients and servers. == INSTALL: $ gem install thrift == CAVEATS: This library provides the client and server implementations of thrift. It does not provide the compiler for the .thrift files. To compile .thrift files into language-specific implementations, please download the full thrift software package. == USAGE: This section should get written by someone with the time and inclination. In the meantime, look at existing code, such as the benchmark or the tutorial in the full thrift distribution. thrift-0.19.0/lib/rb/coding_standards.md0000644000000000000000000000010314303740367020101 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/rb/Gemfile0000644000000000000000000000004714303740367015553 0ustar00rootroot00000000000000source "http://rubygems.org" gemspec thrift-0.19.0/lib/rb/lib/0000777000000000000000000000000014303740367015031 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/0000777000000000000000000000000014370300523016317 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/struct_union.rb0000644000000000000000000001361614303740367021415 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'set' module Thrift module Struct_Union def name_to_id(name) names_to_ids = self.class.instance_variable_get(:@names_to_ids) unless names_to_ids names_to_ids = {} struct_fields.each do |fid, field_def| names_to_ids[field_def[:name]] = fid end self.class.instance_variable_set(:@names_to_ids, names_to_ids) end names_to_ids[name] end def sorted_field_ids sorted_field_ids = self.class.instance_variable_get(:@sorted_field_ids) unless sorted_field_ids sorted_field_ids = struct_fields.keys.sort self.class.instance_variable_set(:@sorted_field_ids, sorted_field_ids) end sorted_field_ids end def each_field sorted_field_ids.each do |fid| data = struct_fields[fid] yield fid, data end end def read_field(iprot, field = {}) case field[:type] when Types::STRUCT value = field[:class].new value.read(iprot) when Types::MAP key_type, val_type, size = iprot.read_map_begin # Skip the map contents if the declared key or value types don't match the expected ones. if (size != 0 && (key_type != field[:key][:type] || val_type != field[:value][:type])) size.times do iprot.skip(key_type) iprot.skip(val_type) end value = nil else value = {} size.times do k = read_field(iprot, field_info(field[:key])) v = read_field(iprot, field_info(field[:value])) value[k] = v end end iprot.read_map_end when Types::LIST e_type, size = iprot.read_list_begin # Skip the list contents if the declared element type doesn't match the expected one. if (e_type != field[:element][:type]) size.times do iprot.skip(e_type) end value = nil else value = Array.new(size) do |n| read_field(iprot, field_info(field[:element])) end end iprot.read_list_end when Types::SET e_type, size = iprot.read_set_begin # Skip the set contents if the declared element type doesn't match the expected one. if (e_type != field[:element][:type]) size.times do iprot.skip(e_type) end else value = Set.new size.times do element = read_field(iprot, field_info(field[:element])) value << element end end iprot.read_set_end else value = iprot.read_type(field) end value end def write_data(oprot, value, field) if is_container? field[:type] write_container(oprot, value, field) else oprot.write_type(field, value) end end def write_container(oprot, value, field = {}) case field[:type] when Types::MAP oprot.write_map_begin(field[:key][:type], field[:value][:type], value.size) value.each do |k, v| write_data(oprot, k, field[:key]) write_data(oprot, v, field[:value]) end oprot.write_map_end when Types::LIST oprot.write_list_begin(field[:element][:type], value.size) value.each do |elem| write_data(oprot, elem, field[:element]) end oprot.write_list_end when Types::SET oprot.write_set_begin(field[:element][:type], value.size) value.each do |v,| # the , is to preserve compatibility with the old Hash-style sets write_data(oprot, v, field[:element]) end oprot.write_set_end else raise "Not a container type: #{field[:type]}" end end CONTAINER_TYPES = [] CONTAINER_TYPES[Types::LIST] = true CONTAINER_TYPES[Types::MAP] = true CONTAINER_TYPES[Types::SET] = true def is_container?(type) CONTAINER_TYPES[type] end def field_info(field) { :type => field[:type], :class => field[:class], :key => field[:key], :value => field[:value], :element => field[:element] } end def inspect_field(value, field_info) if enum_class = field_info[:enum_class] "#{enum_class.const_get(:VALUE_MAP)[value]} (#{value})" elsif value.is_a? Hash if field_info[:type] == Types::MAP map_buf = [] value.each do |k, v| map_buf << inspect_field(k, field_info[:key]) + ": " + inspect_field(v, field_info[:value]) end "{" + map_buf.join(", ") + "}" else # old-style set inspect_collection(value.keys, field_info) end elsif value.is_a? Array inspect_collection(value, field_info) elsif value.is_a? Set inspect_collection(value, field_info) elsif value.is_a?(String) && field_info[:binary] value.unpack("H*").first else value.inspect end end def inspect_collection(collection, field_info) buf = [] collection.each do |k| buf << inspect_field(k, field_info[:element]) end "[" + buf.join(", ") + "]" end end endthrift-0.19.0/lib/rb/lib/thrift/struct.rb0000644000000000000000000001674214303740367020210 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'set' module Thrift module Struct def initialize(d={}, &block) # get a copy of the default values to work on, removing defaults in favor of arguments fields_with_defaults = fields_with_default_values.dup # check if the defaults is empty, or if there are no parameters for this # instantiation, and if so, don't bother overriding defaults. unless fields_with_defaults.empty? || d.empty? d.each_key do |name| fields_with_defaults.delete(name.to_s) end end # assign all the user-specified arguments unless d.empty? d.each do |name, value| unless name_to_id(name.to_s) raise Exception, "Unknown key given to #{self.class}.new: #{name}" end Thrift.check_type(value, struct_fields[name_to_id(name.to_s)], name) if Thrift.type_checking instance_variable_set("@#{name}", value) end end # assign all the default values unless fields_with_defaults.empty? fields_with_defaults.each do |name, default_value| instance_variable_set("@#{name}", (default_value.dup rescue default_value)) end end yield self if block_given? end def fields_with_default_values fields_with_default_values = self.class.instance_variable_get(:@fields_with_default_values) unless fields_with_default_values fields_with_default_values = {} struct_fields.each do |fid, field_def| unless field_def[:default].nil? fields_with_default_values[field_def[:name]] = field_def[:default] end end self.class.instance_variable_set(:@fields_with_default_values, fields_with_default_values) end fields_with_default_values end def inspect(skip_optional_nulls = true) fields = [] each_field do |fid, field_info| name = field_info[:name] value = instance_variable_get("@#{name}") unless skip_optional_nulls && field_info[:optional] && value.nil? fields << "#{name}:#{inspect_field(value, field_info)}" end end "<#{self.class} #{fields.join(", ")}>" end def read(iprot) iprot.read_struct_begin loop do fname, ftype, fid = iprot.read_field_begin break if (ftype == Types::STOP) handle_message(iprot, fid, ftype) iprot.read_field_end end iprot.read_struct_end validate end def write(oprot) validate oprot.write_struct_begin(self.class.name) each_field do |fid, field_info| name = field_info[:name] type = field_info[:type] value = instance_variable_get("@#{name}") unless value.nil? if is_container? type oprot.write_field_begin(name, type, fid) write_container(oprot, value, field_info) oprot.write_field_end else oprot.write_field(field_info, fid, value) end end end oprot.write_field_stop oprot.write_struct_end end def ==(other) return false if other.nil? each_field do |fid, field_info| name = field_info[:name] return false unless other.respond_to?(name) && self.send(name) == other.send(name) end true end def eql?(other) self.class == other.class && self == other end # This implementation of hash() is inspired by Apache's Java HashCodeBuilder class. def hash total = 17 each_field do |fid, field_info| name = field_info[:name] value = self.send(name) total = (total * 37 + value.hash) & 0xffffffff end total end def differences(other) diffs = [] unless other.is_a?(self.class) diffs << "Different class!" else each_field do |fid, field_info| name = field_info[:name] diffs << "#{name} differs!" unless self.instance_variable_get("@#{name}") == other.instance_variable_get("@#{name}") end end diffs end def self.field_accessor(klass, field_info) field_name_sym = field_info[:name].to_sym klass.send :attr_reader, field_name_sym klass.send :define_method, "#{field_info[:name]}=" do |value| Thrift.check_type(value, field_info, field_info[:name]) if Thrift.type_checking instance_variable_set("@#{field_name_sym}", value) end end def self.generate_accessors(klass) klass::FIELDS.values.each do |field_info| field_accessor(klass, field_info) qmark_isset_method(klass, field_info) end end def self.qmark_isset_method(klass, field_info) klass.send :define_method, "#{field_info[:name]}?" do !self.send(field_info[:name].to_sym).nil? end end def <=>(other) if self.class == other.class each_field do |fid, field_info| v1 = self.send(field_info[:name]) v1_set = !v1.nil? v2 = other.send(field_info[:name]) v2_set = !v2.nil? if v1_set && !v2_set return -1 elsif !v1_set && v2_set return 1 elsif v1_set && v2_set cmp = v1 <=> v2 if cmp != 0 return cmp end end end 0 else self.class <=> other.class end end protected def self.append_features(mod) if mod.ancestors.include? ::Exception mod.send :class_variable_set, :'@@__thrift_struct_real_initialize', mod.instance_method(:initialize) super # set up our custom initializer so `raise Xception, 'message'` works mod.send :define_method, :struct_initialize, mod.instance_method(:initialize) mod.send :define_method, :initialize, mod.instance_method(:exception_initialize) else super end end def exception_initialize(*args, &block) if args.size == 1 and args.first.is_a? Hash # looks like it's a regular Struct initialize method(:struct_initialize).call(args.first) else # call the Struct initializer first with no args # this will set our field default values method(:struct_initialize).call() # now give it to the exception self.class.send(:class_variable_get, :'@@__thrift_struct_real_initialize').bind(self).call(*args, &block) if args.size > 0 # self.class.instance_method(:initialize).bind(self).call(*args, &block) end end def handle_message(iprot, fid, ftype) field = struct_fields[fid] if field and field[:type] == ftype value = read_field(iprot, field) instance_variable_set("@#{field[:name]}", value) else iprot.skip(ftype) end end end end thrift-0.19.0/lib/rb/lib/thrift/processor.rb0000644000000000000000000000441714303740367020677 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'logger' module Thrift module Processor def initialize(handler, logger=nil) @handler = handler if logger.nil? @logger = Logger.new(STDERR) @logger.level = Logger::WARN else @logger = logger end end def process(iprot, oprot) name, type, seqid = iprot.read_message_begin if respond_to?("process_#{name}") begin send("process_#{name}", seqid, iprot, oprot) rescue => e x = ApplicationException.new(ApplicationException::INTERNAL_ERROR, 'Internal error') @logger.debug "Internal error : #{e.message}\n#{e.backtrace.join("\n")}" write_error(x, oprot, name, seqid) end true else iprot.skip(Types::STRUCT) iprot.read_message_end x = ApplicationException.new(ApplicationException::UNKNOWN_METHOD, 'Unknown function '+name) write_error(x, oprot, name, seqid) false end end def read_args(iprot, args_class) args = args_class.new args.read(iprot) iprot.read_message_end args end def write_result(result, oprot, name, seqid) oprot.write_message_begin(name, MessageTypes::REPLY, seqid) result.write(oprot) oprot.write_message_end oprot.trans.flush end def write_error(err, oprot, name, seqid) oprot.write_message_begin(name, MessageTypes::EXCEPTION, seqid) err.write(oprot) oprot.write_message_end oprot.trans.flush end end end thrift-0.19.0/lib/rb/lib/thrift/protocol/0000777000000000000000000000000014303740367020172 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/protocol/json_protocol.rb0000644000000000000000000004527014303740367023415 0ustar00rootroot00000000000000# encoding: UTF-8 # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'base64' module Thrift class LookaheadReader def initialize(trans) @trans = trans @hasData = false @data = nil end def read if @hasData @hasData = false else @data = @trans.read(1) end return @data end def peek if !@hasData @data = @trans.read(1) end @hasData = true return @data end end # # Class to serve as base JSON context and as base class for other context # implementations # class JSONContext @@kJSONElemSeparator = ',' # # Write context data to the trans. Default is to do nothing. # def write(trans) end # # Read context data from the trans. Default is to do nothing. # def read(reader) end # # Return true if numbers need to be escaped as strings in this context. # Default behavior is to return false. # def escapeNum return false end end # Context class for object member key-value pairs class JSONPairContext < JSONContext @@kJSONPairSeparator = ':' def initialize @first = true @colon = true end def write(trans) if (@first) @first = false @colon = true else trans.write(@colon ? @@kJSONPairSeparator : @@kJSONElemSeparator) @colon = !@colon end end def read(reader) if (@first) @first = false @colon = true else ch = (@colon ? @@kJSONPairSeparator : @@kJSONElemSeparator) @colon = !@colon JsonProtocol::read_syntax_char(reader, ch) end end # Numbers must be turned into strings if they are the key part of a pair def escapeNum return @colon end end # Context class for lists class JSONListContext < JSONContext def initialize @first = true end def write(trans) if (@first) @first = false else trans.write(@@kJSONElemSeparator) end end def read(reader) if (@first) @first = false else JsonProtocol::read_syntax_char(reader, @@kJSONElemSeparator) end end end class JsonProtocol < BaseProtocol @@kJSONObjectStart = '{' @@kJSONObjectEnd = '}' @@kJSONArrayStart = '[' @@kJSONArrayEnd = ']' @@kJSONNewline = '\n' @@kJSONBackslash = '\\' @@kJSONStringDelimiter = '"' @@kThriftVersion1 = 1 @@kThriftNan = "NaN" @@kThriftInfinity = "Infinity" @@kThriftNegativeInfinity = "-Infinity" def initialize(trans) super(trans) @context = JSONContext.new @contexts = Array.new @reader = LookaheadReader.new(trans) end def get_type_name_for_type_id(id) case id when Types::BOOL "tf" when Types::BYTE "i8" when Types::I16 "i16" when Types::I32 "i32" when Types::I64 "i64" when Types::DOUBLE "dbl" when Types::STRING "str" when Types::STRUCT "rec" when Types::MAP "map" when Types::SET "set" when Types::LIST "lst" else raise NotImplementedError end end def get_type_id_for_type_name(name) if (name == "tf") result = Types::BOOL elsif (name == "i8") result = Types::BYTE elsif (name == "i16") result = Types::I16 elsif (name == "i32") result = Types::I32 elsif (name == "i64") result = Types::I64 elsif (name == "dbl") result = Types::DOUBLE elsif (name == "str") result = Types::STRING elsif (name == "rec") result = Types::STRUCT elsif (name == "map") result = Types::MAP elsif (name == "set") result = Types::SET elsif (name == "lst") result = Types::LIST else result = Types::STOP end if (result == Types::STOP) raise NotImplementedError end return result end # Static helper functions # Read 1 character from the trans and verify that it is the expected character ch. # Throw a protocol exception if it is not. def self.read_syntax_char(reader, ch) ch2 = reader.read if (ch2 != ch) raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected \'#{ch}\' got \'#{ch2}\'.") end end # Return true if the character ch is in [-+0-9.Ee]; false otherwise def is_json_numeric(ch) case ch when '+', '-', '.', '0' .. '9', 'E', "e" return true else return false end end def push_context(context) @contexts.push(@context) @context = context end def pop_context @context = @contexts.pop end # Write the character ch as a JSON escape sequence ("\u00xx") def write_json_escape_char(ch) trans.write('\\u') ch_value = ch[0] if (ch_value.kind_of? String) ch_value = ch.bytes.first end trans.write(ch_value.to_s(16).rjust(4,'0')) end # Write the character ch as part of a JSON string, escaping as appropriate. def write_json_char(ch) # This table describes the handling for the first 0x30 characters # 0 : escape using "\u00xx" notation # 1 : just output index # : escape using "\" notation kJSONCharTable = [ # 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 0, 0, 0, 0, 0, 0, 0,'b','t','n', 0,'f','r', 0, 0, # 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 1 1, 1,'"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 2 ] ch_value = ch[0] if (ch_value.kind_of? String) ch_value = ch.bytes.first end if (ch_value >= 0x30) if (ch == @@kJSONBackslash) # Only special character >= 0x30 is '\' trans.write(@@kJSONBackslash) trans.write(@@kJSONBackslash) else trans.write(ch) end else outCh = kJSONCharTable[ch_value]; # Check if regular character, backslash escaped, or JSON escaped if outCh.kind_of? String trans.write(@@kJSONBackslash) trans.write(outCh) elsif outCh == 1 trans.write(ch) else write_json_escape_char(ch) end end end # Write out the contents of the string str as a JSON string, escaping characters as appropriate. def write_json_string(str) @context.write(trans) trans.write(@@kJSONStringDelimiter) str.split('').each do |ch| write_json_char(ch) end trans.write(@@kJSONStringDelimiter) end # Write out the contents of the string as JSON string, base64-encoding # the string's contents, and escaping as appropriate def write_json_base64(str) @context.write(trans) trans.write(@@kJSONStringDelimiter) trans.write(Base64.strict_encode64(str)) trans.write(@@kJSONStringDelimiter) end # Convert the given integer type to a JSON number, or a string # if the context requires it (eg: key in a map pair). def write_json_integer(num) @context.write(trans) escapeNum = @context.escapeNum if (escapeNum) trans.write(@@kJSONStringDelimiter) end trans.write(num.to_s); if (escapeNum) trans.write(@@kJSONStringDelimiter) end end # Convert the given double to a JSON string, which is either the number, # "NaN" or "Infinity" or "-Infinity". def write_json_double(num) @context.write(trans) # Normalize output of thrift::to_string for NaNs and Infinities special = false; if (num.nan?) special = true; val = @@kThriftNan; elsif (num.infinite?) special = true; val = @@kThriftInfinity; if (num < 0.0) val = @@kThriftNegativeInfinity; end else val = num.to_s end escapeNum = special || @context.escapeNum if (escapeNum) trans.write(@@kJSONStringDelimiter) end trans.write(val) if (escapeNum) trans.write(@@kJSONStringDelimiter) end end def write_json_object_start @context.write(trans) trans.write(@@kJSONObjectStart) push_context(JSONPairContext.new); end def write_json_object_end pop_context trans.write(@@kJSONObjectEnd) end def write_json_array_start @context.write(trans) trans.write(@@kJSONArrayStart) push_context(JSONListContext.new); end def write_json_array_end pop_context trans.write(@@kJSONArrayEnd) end def write_message_begin(name, type, seqid) write_json_array_start write_json_integer(@@kThriftVersion1) write_json_string(name) write_json_integer(type) write_json_integer(seqid) end def write_message_end write_json_array_end end def write_struct_begin(name) write_json_object_start end def write_struct_end write_json_object_end end def write_field_begin(name, type, id) write_json_integer(id) write_json_object_start write_json_string(get_type_name_for_type_id(type)) end def write_field_end write_json_object_end end def write_field_stop; nil; end def write_map_begin(ktype, vtype, size) write_json_array_start write_json_string(get_type_name_for_type_id(ktype)) write_json_string(get_type_name_for_type_id(vtype)) write_json_integer(size) write_json_object_start end def write_map_end write_json_object_end write_json_array_end end def write_list_begin(etype, size) write_json_array_start write_json_string(get_type_name_for_type_id(etype)) write_json_integer(size) end def write_list_end write_json_array_end end def write_set_begin(etype, size) write_json_array_start write_json_string(get_type_name_for_type_id(etype)) write_json_integer(size) end def write_set_end write_json_array_end end def write_bool(bool) write_json_integer(bool ? 1 : 0) end def write_byte(byte) write_json_integer(byte) end def write_i16(i16) write_json_integer(i16) end def write_i32(i32) write_json_integer(i32) end def write_i64(i64) write_json_integer(i64) end def write_double(dub) write_json_double(dub) end def write_string(str) write_json_string(str) end def write_binary(str) write_json_base64(str) end ## # Reading functions ## # Reads 1 byte and verifies that it matches ch. def read_json_syntax_char(ch) JsonProtocol::read_syntax_char(@reader, ch) end # Decodes the four hex parts of a JSON escaped string character and returns # the character via out. # # Note - this only supports Unicode characters in the BMP (U+0000 to U+FFFF); # characters above the BMP are encoded as two escape sequences (surrogate pairs), # which is not yet implemented def read_json_escape_char str = @reader.read str += @reader.read str += @reader.read str += @reader.read if RUBY_VERSION >= '1.9' str.hex.chr(Encoding::UTF_8) else str.hex.chr end end # Decodes a JSON string, including unescaping, and returns the string via str def read_json_string(skipContext = false) # This string's characters must match up with the elements in escape_char_vals. # I don't have '/' on this list even though it appears on www.json.org -- # it is not in the RFC -> it is. See RFC 4627 escape_chars = "\"\\/bfnrt" # The elements of this array must match up with the sequence of characters in # escape_chars escape_char_vals = [ "\"", "\\", "\/", "\b", "\f", "\n", "\r", "\t", ] if !skipContext @context.read(@reader) end read_json_syntax_char(@@kJSONStringDelimiter) ch = "" str = "" while (true) ch = @reader.read if (ch == @@kJSONStringDelimiter) break end if (ch == @@kJSONBackslash) ch = @reader.read if (ch == 'u') ch = read_json_escape_char else pos = escape_chars.index(ch); if (pos.nil?) # not found raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected control char, got \'#{ch}\'.") end ch = escape_char_vals[pos] end end str += ch end return str end # Reads a block of base64 characters, decoding it, and returns via str def read_json_base64 str = read_json_string m = str.length % 4 if m != 0 # Add missing padding (4 - m).times do str += '=' end end Base64.strict_decode64(str) end # Reads a sequence of characters, stopping at the first one that is not # a valid JSON numeric character. def read_json_numeric_chars str = "" while (true) ch = @reader.peek if (!is_json_numeric(ch)) break; end ch = @reader.read str += ch end return str end # Reads a sequence of characters and assembles them into a number, # returning them via num def read_json_integer @context.read(@reader) if (@context.escapeNum) read_json_syntax_char(@@kJSONStringDelimiter) end str = read_json_numeric_chars begin num = Integer(str); rescue raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"") end if (@context.escapeNum) read_json_syntax_char(@@kJSONStringDelimiter) end return num end # Reads a JSON number or string and interprets it as a double. def read_json_double @context.read(@reader) num = 0 if (@reader.peek == @@kJSONStringDelimiter) str = read_json_string(true) # Check for NaN, Infinity and -Infinity if (str == @@kThriftNan) num = (+1.0/0.0)/(+1.0/0.0) elsif (str == @@kThriftInfinity) num = +1.0/0.0 elsif (str == @@kThriftNegativeInfinity) num = -1.0/0.0 else if (!@context.escapeNum) # Raise exception -- we should not be in a string in this case raise ProtocolException.new(ProtocolException::INVALID_DATA, "Numeric data unexpectedly quoted") end begin num = Float(str) rescue raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"") end end else if (@context.escapeNum) # This will throw - we should have had a quote if escapeNum == true read_json_syntax_char(@@kJSONStringDelimiter) end str = read_json_numeric_chars begin num = Float(str) rescue raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"") end end return num end def read_json_object_start @context.read(@reader) read_json_syntax_char(@@kJSONObjectStart) push_context(JSONPairContext.new) nil end def read_json_object_end read_json_syntax_char(@@kJSONObjectEnd) pop_context nil end def read_json_array_start @context.read(@reader) read_json_syntax_char(@@kJSONArrayStart) push_context(JSONListContext.new) nil end def read_json_array_end read_json_syntax_char(@@kJSONArrayEnd) pop_context nil end def read_message_begin read_json_array_start version = read_json_integer if (version != @@kThriftVersion1) raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Message contained bad version.') end name = read_json_string message_type = read_json_integer seqid = read_json_integer [name, message_type, seqid] end def read_message_end read_json_array_end nil end def read_struct_begin read_json_object_start nil end def read_struct_end read_json_object_end nil end def read_field_begin # Check if we hit the end of the list ch = @reader.peek if (ch == @@kJSONObjectEnd) field_type = Types::STOP else field_id = read_json_integer read_json_object_start field_type = get_type_id_for_type_name(read_json_string) end [nil, field_type, field_id] end def read_field_end read_json_object_end end def read_map_begin read_json_array_start key_type = get_type_id_for_type_name(read_json_string) val_type = get_type_id_for_type_name(read_json_string) size = read_json_integer read_json_object_start [key_type, val_type, size] end def read_map_end read_json_object_end read_json_array_end end def read_list_begin read_json_array_start [get_type_id_for_type_name(read_json_string), read_json_integer] end def read_list_end read_json_array_end end def read_set_begin read_json_array_start [get_type_id_for_type_name(read_json_string), read_json_integer] end def read_set_end read_json_array_end end def read_bool byte = read_byte byte != 0 end def read_byte read_json_integer end def read_i16 read_json_integer end def read_i32 read_json_integer end def read_i64 read_json_integer end def read_double read_json_double end def read_string read_json_string end def read_binary read_json_base64 end def to_s "json(#{super.to_s})" end end class JsonProtocolFactory < BaseProtocolFactory def get_protocol(trans) return Thrift::JsonProtocol.new(trans) end def to_s "json" end end end thrift-0.19.0/lib/rb/lib/thrift/protocol/multiplexed_protocol.rb0000644000000000000000000000257114303740367024775 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. require 'thrift/protocol/protocol_decorator' module Thrift class MultiplexedProtocol < BaseProtocol include ProtocolDecorator def initialize(protocol, service_name) super(protocol) @service_name = service_name end def write_message_begin(name, type, seqid) case type when MessageTypes::CALL, MessageTypes::ONEWAY @protocol.write_message_begin("#{@service_name}:#{name}", type, seqid) else @protocol.write_message_begin(name, type, seqid) end end def to_s "multiplexed(#{@service_name=@protocol.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/protocol/protocol_decorator.rb0000644000000000000000000000716114303740367024423 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. module Thrift module ProtocolDecorator def initialize(protocol) @protocol = protocol end def trans @protocol.trans end def write_message_begin(name, type, seqid) @protocol.write_message_begin end def write_message_end @protocol.write_message_end end def write_struct_begin(name) @protocol.write_struct_begin(name) end def write_struct_end @protocol.write_struct_end end def write_field_begin(name, type, id) @protocol.write_field_begin(name, type, id) end def write_field_end @protocol.write_field_end end def write_field_stop @protocol.write_field_stop end def write_map_begin(ktype, vtype, size) @protocol.write_map_begin(ktype, vtype, size) end def write_map_end @protocol.write_map_end end def write_list_begin(etype, size) @protocol.write_list_begin(etype, size) end def write_list_end @protocol.write_list_end end def write_set_begin(etype, size) @protocol.write_set_begin(etype, size) end def write_set_end @protocol.write_set_end end def write_bool(bool) @protocol.write_bool(bool) end def write_byte(byte) @protocol.write_byte(byte) end def write_i16(i16) @protocol.write_i16(i16) end def write_i32(i32) @protocol.write_i32(i32) end def write_i64(i64) @protocol.write_i64(i64) end def write_double(dub) @protocol.write_double(dub) end def write_string(str) @protocol.write_string(str) end def write_binary(buf) @protocol.write_binary(buf) end def read_message_begin @protocol.read_message_begin end def read_message_end @protocol.read_message_end end def read_struct_begin @protocol.read_struct_begin end def read_struct_end @protocol.read_struct_end end def read_field_begin @protocol.read_field_begin end def read_field_end @protocol.read_field_end end def read_map_begin @protocol.read_map_begin end def read_map_end @protocol.read_map_end end def read_list_begin @protocol.read_list_begin end def read_list_end @protocol.read_list_end end def read_set_begin @protocol.read_set_begin end def read_set_end @protocol.read_set_end end def read_bool @protocol.read_bool end def read_byte @protocol.read_byte end def read_i16 @protocol.read_i16 end def read_i32 @protocol.read_i32 end def read_i64 @protocol.read_i64 end def read_double @protocol.read_double end def read_string @protocol.read_string end def read_binary @protocol.read_binary end end endthrift-0.19.0/lib/rb/lib/thrift/protocol/compact_protocol.rb0000644000000000000000000002600314303740367024063 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class CompactProtocol < BaseProtocol PROTOCOL_ID = [0x82].pack('c').unpack('c').first VERSION = 1 VERSION_MASK = 0x1f TYPE_MASK = 0xE0 TYPE_BITS = 0x07 TYPE_SHIFT_AMOUNT = 5 TSTOP = ["", Types::STOP, 0] # # All of the on-wire type codes. # class CompactTypes BOOLEAN_TRUE = 0x01 BOOLEAN_FALSE = 0x02 BYTE = 0x03 I16 = 0x04 I32 = 0x05 I64 = 0x06 DOUBLE = 0x07 BINARY = 0x08 LIST = 0x09 SET = 0x0A MAP = 0x0B STRUCT = 0x0C def self.is_bool_type?(b) (b & 0x0f) == BOOLEAN_TRUE || (b & 0x0f) == BOOLEAN_FALSE end COMPACT_TO_TTYPE = { Types::STOP => Types::STOP, BOOLEAN_FALSE => Types::BOOL, BOOLEAN_TRUE => Types::BOOL, BYTE => Types::BYTE, I16 => Types::I16, I32 => Types::I32, I64 => Types::I64, DOUBLE => Types::DOUBLE, BINARY => Types::STRING, LIST => Types::LIST, SET => Types::SET, MAP => Types::MAP, STRUCT => Types::STRUCT } TTYPE_TO_COMPACT = { Types::STOP => Types::STOP, Types::BOOL => BOOLEAN_TRUE, Types::BYTE => BYTE, Types::I16 => I16, Types::I32 => I32, Types::I64 => I64, Types::DOUBLE => DOUBLE, Types::STRING => BINARY, Types::LIST => LIST, Types::SET => SET, Types::MAP => MAP, Types::STRUCT => STRUCT } def self.get_ttype(compact_type) val = COMPACT_TO_TTYPE[compact_type & 0x0f] raise "don't know what type: #{compact_type & 0x0f}" unless val val end def self.get_compact_type(ttype) val = TTYPE_TO_COMPACT[ttype] raise "don't know what type: #{ttype & 0x0f}" unless val val end end def initialize(transport) super(transport) @last_field = [0] @boolean_value = nil # Pre-allocated read buffer for read_double(). @rbuf = Bytes.empty_byte_buffer(8) end def write_message_begin(name, type, seqid) write_byte(PROTOCOL_ID) write_byte((VERSION & VERSION_MASK) | ((type << TYPE_SHIFT_AMOUNT) & TYPE_MASK)) write_varint32(seqid) write_string(name) nil end def write_struct_begin(name) @last_field.push(0) nil end def write_struct_end @last_field.pop nil end def write_field_begin(name, type, id) if type == Types::BOOL # we want to possibly include the value, so we'll wait. @boolean_field = [type, id] else write_field_begin_internal(type, id) end nil end # # The workhorse of writeFieldBegin. It has the option of doing a # 'type override' of the type header. This is used specifically in the # boolean field case. # def write_field_begin_internal(type, id, type_override=nil) last_id = @last_field.pop # if there's a type override, use that. typeToWrite = type_override || CompactTypes.get_compact_type(type) # check if we can use delta encoding for the field id if id > last_id && id - last_id <= 15 # write them together write_byte((id - last_id) << 4 | typeToWrite) else # write them separate write_byte(typeToWrite) write_i16(id) end @last_field.push(id) nil end def write_field_stop write_byte(Types::STOP) end def write_map_begin(ktype, vtype, size) if (size == 0) write_byte(0) else write_varint32(size) write_byte(CompactTypes.get_compact_type(ktype) << 4 | CompactTypes.get_compact_type(vtype)) end end def write_list_begin(etype, size) write_collection_begin(etype, size) end def write_set_begin(etype, size) write_collection_begin(etype, size); end def write_bool(bool) type = bool ? CompactTypes::BOOLEAN_TRUE : CompactTypes::BOOLEAN_FALSE unless @boolean_field.nil? # we haven't written the field header yet write_field_begin_internal(@boolean_field.first, @boolean_field.last, type) @boolean_field = nil else # we're not part of a field, so just write the value. write_byte(type) end end def write_byte(byte) @trans.write([byte].pack('c')) end def write_i16(i16) write_varint32(int_to_zig_zag(i16)) end def write_i32(i32) write_varint32(int_to_zig_zag(i32)) end def write_i64(i64) write_varint64(long_to_zig_zag(i64)) end def write_double(dub) @trans.write([dub].pack("G").reverse) end def write_string(str) buf = Bytes.convert_to_utf8_byte_buffer(str) write_binary(buf) end def write_binary(buf) write_varint32(buf.bytesize) @trans.write(buf) end def read_message_begin protocol_id = read_byte() if protocol_id != PROTOCOL_ID raise ProtocolException.new("Expected protocol id #{PROTOCOL_ID} but got #{protocol_id}") end version_and_type = read_byte() version = version_and_type & VERSION_MASK if (version != VERSION) raise ProtocolException.new("Expected version #{VERSION} but got #{version}"); end type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS seqid = read_varint32() messageName = read_string() [messageName, type, seqid] end def read_struct_begin @last_field.push(0) "" end def read_struct_end @last_field.pop() nil end def read_field_begin type = read_byte() # if it's a stop, then we can return immediately, as the struct is over. if (type & 0x0f) == Types::STOP TSTOP else field_id = nil # mask off the 4 MSB of the type header. it could contain a field id delta. modifier = (type & 0xf0) >> 4 if modifier == 0 # not a delta. look ahead for the zigzag varint field id. @last_field.pop field_id = read_i16() else # has a delta. add the delta to the last read field id. field_id = @last_field.pop + modifier end # if this happens to be a boolean field, the value is encoded in the type if CompactTypes.is_bool_type?(type) # save the boolean value in a special instance variable. @bool_value = (type & 0x0f) == CompactTypes::BOOLEAN_TRUE end # push the new field onto the field stack so we can keep the deltas going. @last_field.push(field_id) ["", CompactTypes.get_ttype(type & 0x0f), field_id] end end def read_map_begin size = read_varint32() key_and_value_type = size == 0 ? 0 : read_byte() [CompactTypes.get_ttype(key_and_value_type >> 4), CompactTypes.get_ttype(key_and_value_type & 0xf), size] end def read_list_begin size_and_type = read_byte() size = (size_and_type >> 4) & 0x0f if size == 15 size = read_varint32() end type = CompactTypes.get_ttype(size_and_type) [type, size] end def read_set_begin read_list_begin end def read_bool unless @bool_value.nil? bv = @bool_value @bool_value = nil bv else read_byte() == CompactTypes::BOOLEAN_TRUE end end def read_byte val = trans.read_byte if (val > 0x7f) val = 0 - ((val - 1) ^ 0xff) end val end def read_i16 zig_zag_to_int(read_varint32()) end def read_i32 zig_zag_to_int(read_varint32()) end def read_i64 zig_zag_to_long(read_varint64()) end def read_double trans.read_into_buffer(@rbuf, 8) val = @rbuf.reverse.unpack('G').first val end def read_string buffer = read_binary Bytes.convert_to_string(buffer) end def read_binary size = read_varint32() trans.read_all(size) end def to_s "compact(#{super.to_s})" end private # # Abstract method for writing the start of lists and sets. List and sets on # the wire differ only by the type indicator. # def write_collection_begin(elem_type, size) if size <= 14 write_byte(size << 4 | CompactTypes.get_compact_type(elem_type)) else write_byte(0xf0 | CompactTypes.get_compact_type(elem_type)) write_varint32(size) end end def write_varint32(n) # int idx = 0; while true if (n & ~0x7F) == 0 # i32buf[idx++] = (byte)n; write_byte(n) break # return; else # i32buf[idx++] = (byte)((n & 0x7F) | 0x80); write_byte((n & 0x7F) | 0x80) n = n >> 7 end end # trans_.write(i32buf, 0, idx); end SEVEN_BIT_MASK = 0x7F EVERYTHING_ELSE_MASK = ~SEVEN_BIT_MASK def write_varint64(n) while true if (n & EVERYTHING_ELSE_MASK) == 0 #TODO need to find a way to make this into a long... write_byte(n) break else write_byte((n & SEVEN_BIT_MASK) | 0x80) n >>= 7 end end end def read_varint32() read_varint64() end def read_varint64() shift = 0 result = 0 while true b = read_byte() result |= (b & 0x7f) << shift break if (b & 0x80) != 0x80 shift += 7 end result end def int_to_zig_zag(n) (n << 1) ^ (n >> 31) end def long_to_zig_zag(l) # puts "zz encoded #{l} to #{(l << 1) ^ (l >> 63)}" (l << 1) ^ (l >> 63) end def zig_zag_to_int(n) (n >> 1) ^ -(n & 1) end def zig_zag_to_long(n) (n >> 1) ^ -(n & 1) end end class CompactProtocolFactory < BaseProtocolFactory def get_protocol(trans) CompactProtocol.new(trans) end def to_s "compact" end end end thrift-0.19.0/lib/rb/lib/thrift/protocol/binary_protocol_accelerated.rb0000644000000000000000000000311014303740367026227 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # =begin The only change required for a transport to support BinaryProtocolAccelerated is to implement 2 methods: * borrow(size), which takes an optional argument and returns atleast _size_ bytes from the transport, or the default buffer size if no argument is given * consume!(size), which removes size bytes from the front of the buffer See MemoryBuffer and BufferedTransport for examples. =end module Thrift class BinaryProtocolAcceleratedFactory < BaseProtocolFactory def get_protocol(trans) if (defined? BinaryProtocolAccelerated) BinaryProtocolAccelerated.new(trans) else BinaryProtocol.new(trans) end end def to_s if (defined? BinaryProtocolAccelerated) "binary-accel" else "binary" end end end end thrift-0.19.0/lib/rb/lib/thrift/protocol/binary_protocol.rb0000644000000000000000000001275614303740367023733 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class BinaryProtocol < BaseProtocol VERSION_MASK = 0xffff0000 VERSION_1 = 0x80010000 TYPE_MASK = 0x000000ff attr_reader :strict_read, :strict_write def initialize(trans, strict_read=true, strict_write=true) super(trans) @strict_read = strict_read @strict_write = strict_write # Pre-allocated read buffer for fixed-size read methods. Needs to be at least 8 bytes long for # read_i64() and read_double(). @rbuf = Bytes.empty_byte_buffer(8) end def write_message_begin(name, type, seqid) # this is necessary because we added (needed) bounds checking to # write_i32, and 0x80010000 is too big for that. if strict_write write_i16(VERSION_1 >> 16) write_i16(type) write_string(name) write_i32(seqid) else write_string(name) write_byte(type) write_i32(seqid) end end def write_struct_begin(name); nil; end def write_field_begin(name, type, id) write_byte(type) write_i16(id) end def write_field_stop write_byte(Thrift::Types::STOP) end def write_map_begin(ktype, vtype, size) write_byte(ktype) write_byte(vtype) write_i32(size) end def write_list_begin(etype, size) write_byte(etype) write_i32(size) end def write_set_begin(etype, size) write_byte(etype) write_i32(size) end def write_bool(bool) write_byte(bool ? 1 : 0) end def write_byte(byte) raise RangeError if byte < -2**31 || byte >= 2**32 trans.write([byte].pack('c')) end def write_i16(i16) trans.write([i16].pack('n')) end def write_i32(i32) raise RangeError if i32 < -2**31 || i32 >= 2**31 trans.write([i32].pack('N')) end def write_i64(i64) raise RangeError if i64 < -2**63 || i64 >= 2**64 hi = i64 >> 32 lo = i64 & 0xffffffff trans.write([hi, lo].pack('N2')) end def write_double(dub) trans.write([dub].pack('G')) end def write_string(str) buf = Bytes.convert_to_utf8_byte_buffer(str) write_binary(buf) end def write_binary(buf) write_i32(buf.bytesize) trans.write(buf) end def read_message_begin version = read_i32 if version < 0 if (version & VERSION_MASK != VERSION_1) raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Missing version identifier') end type = version & TYPE_MASK name = read_string seqid = read_i32 [name, type, seqid] else if strict_read raise ProtocolException.new(ProtocolException::BAD_VERSION, 'No version identifier, old protocol client?') end name = trans.read_all(version) type = read_byte seqid = read_i32 [name, type, seqid] end end def read_struct_begin; nil; end def read_field_begin type = read_byte if (type == Types::STOP) [nil, type, 0] else id = read_i16 [nil, type, id] end end def read_map_begin ktype = read_byte vtype = read_byte size = read_i32 [ktype, vtype, size] end def read_list_begin etype = read_byte size = read_i32 [etype, size] end def read_set_begin etype = read_byte size = read_i32 [etype, size] end def read_bool byte = read_byte byte != 0 end def read_byte val = trans.read_byte if (val > 0x7f) val = 0 - ((val - 1) ^ 0xff) end val end def read_i16 trans.read_into_buffer(@rbuf, 2) val, = @rbuf.unpack('n') if (val > 0x7fff) val = 0 - ((val - 1) ^ 0xffff) end val end def read_i32 trans.read_into_buffer(@rbuf, 4) val, = @rbuf.unpack('N') if (val > 0x7fffffff) val = 0 - ((val - 1) ^ 0xffffffff) end val end def read_i64 trans.read_into_buffer(@rbuf, 8) hi, lo = @rbuf.unpack('N2') if (hi > 0x7fffffff) hi ^= 0xffffffff lo ^= 0xffffffff 0 - (hi << 32) - lo - 1 else (hi << 32) + lo end end def read_double trans.read_into_buffer(@rbuf, 8) val = @rbuf.unpack('G').first val end def read_string buffer = read_binary Bytes.convert_to_string(buffer) end def read_binary size = read_i32 trans.read_all(size) end def to_s "binary(#{super.to_s})" end end class BinaryProtocolFactory < BaseProtocolFactory def get_protocol(trans) return Thrift::BinaryProtocol.new(trans) end def to_s "binary" end end end thrift-0.19.0/lib/rb/lib/thrift/protocol/base_protocol.rb0000644000000000000000000002241514303740367023352 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # this require is to make generated struct definitions happy require 'set' module Thrift class ProtocolException < Exception UNKNOWN = 0 INVALID_DATA = 1 NEGATIVE_SIZE = 2 SIZE_LIMIT = 3 BAD_VERSION = 4 NOT_IMPLEMENTED = 5 DEPTH_LIMIT = 6 attr_reader :type def initialize(type=UNKNOWN, message=nil) super(message) @type = type end end class BaseProtocol attr_reader :trans def initialize(trans) @trans = trans end def native? puts "wrong method is being called!" false end def write_message_begin(name, type, seqid) raise NotImplementedError end def write_message_end; nil; end def write_struct_begin(name) raise NotImplementedError end def write_struct_end; nil; end def write_field_begin(name, type, id) raise NotImplementedError end def write_field_end; nil; end def write_field_stop raise NotImplementedError end def write_map_begin(ktype, vtype, size) raise NotImplementedError end def write_map_end; nil; end def write_list_begin(etype, size) raise NotImplementedError end def write_list_end; nil; end def write_set_begin(etype, size) raise NotImplementedError end def write_set_end; nil; end def write_bool(bool) raise NotImplementedError end def write_byte(byte) raise NotImplementedError end def write_i16(i16) raise NotImplementedError end def write_i32(i32) raise NotImplementedError end def write_i64(i64) raise NotImplementedError end def write_double(dub) raise NotImplementedError end # Writes a Thrift String. In Ruby 1.9+, the String passed will be transcoded to UTF-8. # # str - The String to write. # # Raises EncodingError if the transcoding to UTF-8 fails. # # Returns nothing. def write_string(str) raise NotImplementedError end # Writes a Thrift Binary (Thrift String with no encoding). In Ruby 1.9+, the String passed # will forced into BINARY encoding. # # buf - The String to write. # # Returns nothing. def write_binary(buf) raise NotImplementedError end def read_message_begin raise NotImplementedError end def read_message_end; nil; end def read_struct_begin raise NotImplementedError end def read_struct_end; nil; end def read_field_begin raise NotImplementedError end def read_field_end; nil; end def read_map_begin raise NotImplementedError end def read_map_end; nil; end def read_list_begin raise NotImplementedError end def read_list_end; nil; end def read_set_begin raise NotImplementedError end def read_set_end; nil; end def read_bool raise NotImplementedError end def read_byte raise NotImplementedError end def read_i16 raise NotImplementedError end def read_i32 raise NotImplementedError end def read_i64 raise NotImplementedError end def read_double raise NotImplementedError end # Reads a Thrift String. In Ruby 1.9+, all Strings will be returned with an Encoding of UTF-8. # # Returns a String. def read_string raise NotImplementedError end # Reads a Thrift Binary (Thrift String without encoding). In Ruby 1.9+, all Strings will be returned # with an Encoding of BINARY. # # Returns a String. def read_binary raise NotImplementedError end # Writes a field based on the field information, field ID and value. # # field_info - A Hash containing the definition of the field: # :name - The name of the field. # :type - The type of the field, which must be a Thrift::Types constant. # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding). # fid - The ID of the field. # value - The field's value to write; object type varies based on :type. # # Returns nothing. def write_field(*args) if args.size == 3 # handles the documented method signature - write_field(field_info, fid, value) field_info = args[0] fid = args[1] value = args[2] elsif args.size == 4 # handles the deprecated method signature - write_field(name, type, fid, value) field_info = {:name => args[0], :type => args[1]} fid = args[2] value = args[3] else raise ArgumentError, "wrong number of arguments (#{args.size} for 3)" end write_field_begin(field_info[:name], field_info[:type], fid) write_type(field_info, value) write_field_end end # Writes a field value based on the field information. # # field_info - A Hash containing the definition of the field: # :type - The Thrift::Types constant that determines how the value is written. # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding). # value - The field's value to write; object type varies based on field_info[:type]. # # Returns nothing. def write_type(field_info, value) # if field_info is a Fixnum, assume it is a Thrift::Types constant # convert it into a field_info Hash for backwards compatibility if field_info.is_a? Fixnum field_info = {:type => field_info} end case field_info[:type] when Types::BOOL write_bool(value) when Types::BYTE write_byte(value) when Types::DOUBLE write_double(value) when Types::I16 write_i16(value) when Types::I32 write_i32(value) when Types::I64 write_i64(value) when Types::STRING if field_info[:binary] write_binary(value) else write_string(value) end when Types::STRUCT value.write(self) else raise NotImplementedError end end # Reads a field value based on the field information. # # field_info - A Hash containing the pertinent data to write: # :type - The Thrift::Types constant that determines how the value is written. # :binary - A flag that indicates if Thrift::Types::STRING is a binary string (string without encoding). # # Returns the value read; object type varies based on field_info[:type]. def read_type(field_info) # if field_info is a Fixnum, assume it is a Thrift::Types constant # convert it into a field_info Hash for backwards compatibility if field_info.is_a? Fixnum field_info = {:type => field_info} end case field_info[:type] when Types::BOOL read_bool when Types::BYTE read_byte when Types::DOUBLE read_double when Types::I16 read_i16 when Types::I32 read_i32 when Types::I64 read_i64 when Types::STRING if field_info[:binary] read_binary else read_string end else raise NotImplementedError end end def skip(type) case type when Types::BOOL read_bool when Types::BYTE read_byte when Types::I16 read_i16 when Types::I32 read_i32 when Types::I64 read_i64 when Types::DOUBLE read_double when Types::STRING read_string when Types::STRUCT read_struct_begin while true name, type, id = read_field_begin break if type == Types::STOP skip(type) read_field_end end read_struct_end when Types::MAP ktype, vtype, size = read_map_begin size.times do skip(ktype) skip(vtype) end read_map_end when Types::SET etype, size = read_set_begin size.times do skip(etype) end read_set_end when Types::LIST etype, size = read_list_begin size.times do skip(etype) end read_list_end else raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Invalid data') end end def to_s "#{trans.to_s}" end end class BaseProtocolFactory def get_protocol(trans) raise NotImplementedError end def to_s "base" end end end thrift-0.19.0/lib/rb/lib/thrift/types.rb0000644000000000000000000000537714303740367020032 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'set' module Thrift module Types STOP = 0 VOID = 1 BOOL = 2 BYTE = 3 DOUBLE = 4 I16 = 6 I32 = 8 I64 = 10 STRING = 11 STRUCT = 12 MAP = 13 SET = 14 LIST = 15 end class << self attr_accessor :type_checking end class TypeError < Exception end def self.check_type(value, field, name, skip_nil=true) return if value.nil? and skip_nil klasses = case field[:type] when Types::VOID NilClass when Types::BOOL [TrueClass, FalseClass] when Types::BYTE, Types::I16, Types::I32, Types::I64 Integer when Types::DOUBLE Float when Types::STRING String when Types::STRUCT [Struct, Union] when Types::MAP Hash when Types::SET Set when Types::LIST Array end valid = klasses && [*klasses].any? { |klass| klass === value } raise TypeError, "Expected #{type_name(field[:type])}, received #{value.class} for field #{name}" unless valid # check elements now case field[:type] when Types::MAP value.each_pair do |k,v| check_type(k, field[:key], "#{name}.key", false) check_type(v, field[:value], "#{name}.value", false) end when Types::SET, Types::LIST value.each do |el| check_type(el, field[:element], "#{name}.element", false) end when Types::STRUCT raise TypeError, "Expected #{field[:class]}, received #{value.class} for field #{name}" unless field[:class] == value.class end end def self.type_name(type) Types.constants.each do |const| return "Types::#{const}" if Types.const_get(const) == type end nil end module MessageTypes CALL = 1 REPLY = 2 EXCEPTION = 3 ONEWAY = 4 end end Thrift.type_checking = false if Thrift.type_checking.nil? thrift-0.19.0/lib/rb/lib/thrift/thrift_native.rb0000644000000000000000000000163214303740367021522 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # begin require "thrift_native" rescue LoadError puts "Unable to load thrift_native extension. Defaulting to pure Ruby libraries." endthrift-0.19.0/lib/rb/lib/thrift/union.rb0000644000000000000000000001202514303740367020002 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class Union def initialize(name=nil, value=nil) if name if name.is_a? Hash if name.size > 1 raise "#{self.class} cannot be instantiated with more than one field!" end name, value = name.keys.first, name.values.first end if Thrift.type_checking raise Exception, "#{self.class} does not contain a field named #{name}!" unless name_to_id(name.to_s) end if value.nil? raise Exception, "Union #{self.class} cannot be instantiated with setfield and nil value!" end Thrift.check_type(value, struct_fields[name_to_id(name.to_s)], name) if Thrift.type_checking elsif !value.nil? raise Exception, "Value provided, but no name!" end @setfield = name @value = value end def inspect if get_set_field "<#{self.class} #{@setfield}: #{inspect_field(@value, struct_fields[name_to_id(@setfield.to_s)])}>" else "<#{self.class} >" end end def read(iprot) iprot.read_struct_begin fname, ftype, fid = iprot.read_field_begin handle_message(iprot, fid, ftype) iprot.read_field_end fname, ftype, fid = iprot.read_field_begin raise "Too many fields for union" unless (ftype == Types::STOP) iprot.read_struct_end validate end def write(oprot) validate oprot.write_struct_begin(self.class.name) fid = self.name_to_id(@setfield.to_s) field_info = struct_fields[fid] type = field_info[:type] if is_container? type oprot.write_field_begin(@setfield, type, fid) write_container(oprot, @value, field_info) oprot.write_field_end else oprot.write_field(@setfield, type, fid, @value) end oprot.write_field_stop oprot.write_struct_end end def ==(other) other.equal?(self) || other.instance_of?(self.class) && @setfield == other.get_set_field && @value == other.get_value end alias_method :eql?, :== def hash [self.class.name, @setfield, @value].hash end def self.field_accessor(klass, field_info) klass.send :define_method, field_info[:name] do if field_info[:name].to_sym == @setfield @value else raise RuntimeError, "#{field_info[:name]} is not union's set field." end end klass.send :define_method, "#{field_info[:name]}=" do |value| Thrift.check_type(value, field_info, field_info[:name]) if Thrift.type_checking @setfield = field_info[:name].to_sym @value = value end end def self.qmark_isset_method(klass, field_info) klass.send :define_method, "#{field_info[:name]}?" do get_set_field == field_info[:name].to_sym && !get_value.nil? end end def self.generate_accessors(klass) klass::FIELDS.values.each do |field_info| field_accessor(klass, field_info) qmark_isset_method(klass, field_info) end end # get the symbol that indicates what the currently set field type is. def get_set_field @setfield end # get the current value of this union, regardless of what the set field is. # generally, you should only use this method when you don't know in advance # what field to expect. def get_value @value end def <=>(other) if self.class == other.class if get_set_field == other.get_set_field if get_set_field.nil? 0 else get_value <=> other.get_value end else if get_set_field && other.get_set_field.nil? -1 elsif get_set_field.nil? && other.get_set_field 1 elsif get_set_field.nil? && other.get_set_field.nil? 0 else name_to_id(get_set_field.to_s) <=> name_to_id(other.get_set_field.to_s) end end else self.class <=> other.class end end protected def handle_message(iprot, fid, ftype) field = struct_fields[fid] if field and field[:type] == ftype @value = read_field(iprot, field) name = field[:name].to_sym @setfield = name else iprot.skip(ftype) end end end end thrift-0.19.0/lib/rb/lib/thrift/bytes.rb0000644000000000000000000001050514303740367020001 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift # A collection of utilities for working with bytes and byte buffers. module Bytes if RUBY_VERSION >= '1.9' # Creates and empty byte buffer (String with BINARY encoding) # # size - The Integer size of the buffer (default: nil) to create # # Returns a String with BINARY encoding, filled with null characters # if size is greater than zero def self.empty_byte_buffer(size = nil) if (size && size > 0) "\0".force_encoding(Encoding::BINARY) * size else ''.force_encoding(Encoding::BINARY) end end # Forces the encoding of the buffer to BINARY. If the buffer # passed is frozen, then it will be duplicated. # # buffer - The String to force the encoding of. # # Returns the String passed with an encoding of BINARY; returned # String may be a duplicate. def self.force_binary_encoding(buffer) buffer = buffer.dup if buffer.frozen? buffer.force_encoding(Encoding::BINARY) end # Gets the byte value of a given position in a String. # # string - The String to retrive the byte value from. # index - The Integer location of the byte value to retrieve. # # Returns an Integer value between 0 and 255. def self.get_string_byte(string, index) string.getbyte(index) end # Sets the byte value given to a given index in a String. # # string - The String to set the byte value in. # index - The Integer location to set the byte value at. # byte - The Integer value (0 to 255) to set in the string. # # Returns an Integer value of the byte value to set. def self.set_string_byte(string, index, byte) string.setbyte(index, byte) end # Converts the given String to a UTF-8 byte buffer. # # string - The String to convert. # # Returns a new String with BINARY encoding, containing the UTF-8 # bytes of the original string. def self.convert_to_utf8_byte_buffer(string) if string.encoding != Encoding::UTF_8 # transcode to UTF-8 string = string.encode(Encoding::UTF_8) else # encoding is already UTF-8, but a duplicate is needed string = string.dup end string.force_encoding(Encoding::BINARY) end # Converts the given UTF-8 byte buffer into a String # # utf8_buffer - A String, with BINARY encoding, containing UTF-8 bytes # # Returns a new String with UTF-8 encoding, def self.convert_to_string(utf8_buffer) # duplicate the buffer, force encoding to UTF-8 utf8_buffer.dup.force_encoding(Encoding::UTF_8) end else def self.empty_byte_buffer(size = nil) if (size && size > 0) "\0" * size else '' end end def self.force_binary_encoding(buffer) buffer end def self.get_string_byte(string, index) string[index] end def self.set_string_byte(string, index, byte) string[index] = byte end def self.convert_to_utf8_byte_buffer(string) # This assumes $KCODE is 'UTF8'/'U', which would mean the String is already a UTF-8 byte buffer # TODO consider handling other $KCODE values and transcoding with iconv string end def self.convert_to_string(utf8_buffer) # See comment in 'convert_to_utf8_byte_buffer' for relevant assumptions. utf8_buffer end end end end thrift-0.19.0/lib/rb/lib/thrift/client.rb0000644000000000000000000000420514370300523020117 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift module Client def initialize(iprot, oprot=nil) @iprot = iprot @oprot = oprot || iprot @seqid = 0 end def send_message(name, args_class, args = {}) @oprot.write_message_begin(name, MessageTypes::CALL, @seqid) send_message_args(args_class, args) end def send_oneway_message(name, args_class, args = {}) @oprot.write_message_begin(name, MessageTypes::ONEWAY, @seqid) send_message_args(args_class, args) end def send_message_args(args_class, args) data = args_class.new args.each do |k, v| data.send("#{k.to_s}=", v) end begin data.write(@oprot) rescue StandardError => e @oprot.trans.close raise e end @oprot.write_message_end @oprot.trans.flush end def receive_message_begin() fname, mtype, rseqid = @iprot.read_message_begin [fname, mtype, rseqid] end def reply_seqid(rseqid) result = (rseqid==@seqid)?true:false result end def receive_message(result_klass) result = result_klass.new result.read(@iprot) @iprot.read_message_end result end def handle_exception(mtype) if mtype == MessageTypes::EXCEPTION x = ApplicationException.new x.read(@iprot) @iprot.read_message_end raise x end end end end thrift-0.19.0/lib/rb/lib/thrift/multiplexed_processor.rb0000644000000000000000000000451614303740367023313 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. require 'thrift/protocol/protocol_decorator' require 'thrift/protocol/base_protocol' module Thrift class MultiplexedProcessor def initialize @actual_processors = {} end def register_processor(service_name, processor) @actual_processors[service_name] = processor end def process(iprot, oprot) name, type, seqid = iprot.read_message_begin check_type(type) check_separator(name) service_name, method = name.split(':') processor(service_name).process(StoredMessageProtocol.new(iprot, [method, type, seqid]), oprot) end protected def processor(service_name) if @actual_processors.has_key?(service_name) @actual_processors[service_name] else raise Thrift::Exception.new("Service name not found: #{service_name}. Did you forget to call #{self.class.name}#register_processor?") end end def check_type(type) unless [MessageTypes::CALL, MessageTypes::ONEWAY].include?(type) raise Thrift::Exception.new('This should not have happened!?') end end def check_separator(name) if name.count(':') < 1 raise Thrift::Exception.new("Service name not found in message name: #{name}. Did you forget to use a Thrift::Protocol::MultiplexedProtocol in your client?") end end end class StoredMessageProtocol < BaseProtocol include ProtocolDecorator def initialize(protocol, message_begin) super(protocol) @message_begin = message_begin end def read_message_begin @message_begin end end end thrift-0.19.0/lib/rb/lib/thrift/server/0000777000000000000000000000000014303740367017637 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/server/thin_http_server.rb0000644000000000000000000000533014303740367023550 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'rack' require 'thin' ## # Wraps the Thin web server to provide a Thrift server over HTTP. module Thrift class ThinHTTPServer < BaseServer ## # Accepts a Thrift::Processor # Options include: # * :port # * :ip # * :path # * :protocol_factory def initialize(processor, options={}) port = options[:port] || 80 ip = options[:ip] || "0.0.0.0" path = options[:path] || "/" protocol_factory = options[:protocol_factory] || BinaryProtocolFactory.new app = RackApplication.for(path, processor, protocol_factory) @server = Thin::Server.new(ip, port, app) end ## # Starts the server def serve @server.start end class RackApplication THRIFT_HEADER = "application/x-thrift" def self.for(path, processor, protocol_factory) Rack::Builder.new do use Rack::CommonLogger use Rack::ShowExceptions use Rack::Lint map path do run lambda { |env| request = Rack::Request.new(env) if RackApplication.valid_thrift_request?(request) RackApplication.successful_request(request, processor, protocol_factory) else RackApplication.failed_request end } end end end def self.successful_request(rack_request, processor, protocol_factory) response = Rack::Response.new([], 200, {'Content-Type' => THRIFT_HEADER}) transport = IOStreamTransport.new rack_request.body, response protocol = protocol_factory.get_protocol transport processor.process protocol, protocol response end def self.failed_request Rack::Response.new(['Not Found'], 404, {'Content-Type' => THRIFT_HEADER}) end def self.valid_thrift_request?(rack_request) rack_request.post? && rack_request.env["CONTENT_TYPE"] == THRIFT_HEADER end end end end thrift-0.19.0/lib/rb/lib/thrift/server/simple_server.rb0000644000000000000000000000263214303740367023042 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class SimpleServer < BaseServer def serve begin @server_transport.listen loop do client = @server_transport.accept trans = @transport_factory.get_transport(client) prot = @protocol_factory.get_protocol(trans) begin loop do @processor.process(prot, prot) end rescue Thrift::TransportException, Thrift::ProtocolException ensure trans.close end end ensure @server_transport.close end end def to_s "simple(#{super.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/server/thread_pool_server.rb0000644000000000000000000000475014303740367024054 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'thread' module Thrift class ThreadPoolServer < BaseServer def initialize(processor, server_transport, transport_factory=nil, protocol_factory=nil, num=20) super(processor, server_transport, transport_factory, protocol_factory) @thread_q = SizedQueue.new(num) @exception_q = Queue.new @running = false end ## exceptions that happen in worker threads will be relayed here and ## must be caught. 'retry' can be used to continue. (threads will ## continue to run while the exception is being handled.) def rescuable_serve Thread.new { serve } unless @running @running = true raise @exception_q.pop end ## exceptions that happen in worker threads simply cause that thread ## to die and another to be spawned in its place. def serve @server_transport.listen begin loop do @thread_q.push(:token) Thread.new do begin loop do client = @server_transport.accept trans = @transport_factory.get_transport(client) prot = @protocol_factory.get_protocol(trans) begin loop do @processor.process(prot, prot) end rescue Thrift::TransportException, Thrift::ProtocolException => e ensure trans.close end end rescue => e @exception_q.push(e) ensure @thread_q.pop # thread died! end end end ensure @server_transport.close end end def to_s "threadpool(#{super.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/server/threaded_server.rb0000644000000000000000000000276014303740367023333 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'thread' module Thrift class ThreadedServer < BaseServer def serve begin @server_transport.listen loop do client = @server_transport.accept trans = @transport_factory.get_transport(client) prot = @protocol_factory.get_protocol(trans) Thread.new(prot, trans) do |p, t| begin loop do @processor.process(p, p) end rescue Thrift::TransportException, Thrift::ProtocolException ensure t.close end end end ensure @server_transport.close end end def to_s "threaded(#{super.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/server/mongrel_http_server.rb0000644000000000000000000000417614303740367024260 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'mongrel' ## Sticks a service on a URL, using mongrel to do the HTTP work # DEPRECATED: Please use Thrift::ThinHTTPServer instead. module Thrift class MongrelHTTPServer < BaseServer class Handler < Mongrel::HttpHandler def initialize(processor, protocol_factory) @processor = processor @protocol_factory = protocol_factory end def process(request, response) if request.params["REQUEST_METHOD"] == "POST" response.start(200) do |head, out| head["Content-Type"] = "application/x-thrift" transport = IOStreamTransport.new request.body, out protocol = @protocol_factory.get_protocol transport @processor.process protocol, protocol end else response.start(404) { } end end end def initialize(processor, opts={}) Kernel.warn "[DEPRECATION WARNING] `Thrift::MongrelHTTPServer` is deprecated. Please use `Thrift::ThinHTTPServer` instead." port = opts[:port] || 80 ip = opts[:ip] || "0.0.0.0" path = opts[:path] || "" protocol_factory = opts[:protocol_factory] || BinaryProtocolFactory.new @server = Mongrel::HttpServer.new ip, port @server.register "/#{path}", Handler.new(processor, protocol_factory) end def serve @server.run.join end end end thrift-0.19.0/lib/rb/lib/thrift/server/base_server.rb0000644000000000000000000000254114303740367022462 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class BaseServer def initialize(processor, server_transport, transport_factory=nil, protocol_factory=nil) @processor = processor @server_transport = server_transport @transport_factory = transport_factory ? transport_factory : Thrift::BaseTransportFactory.new @protocol_factory = protocol_factory ? protocol_factory : Thrift::BinaryProtocolFactory.new end def serve raise NotImplementedError end def to_s "server(#{@protocol_factory.to_s}(#{@transport_factory.to_s}(#{@server_transport.to_s})))" end end end thrift-0.19.0/lib/rb/lib/thrift/server/nonblocking_server.rb0000644000000000000000000002166014303740367024056 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'logger' require 'thread' module Thrift # this class expects to always use a FramedTransport for reading messages class NonblockingServer < BaseServer def initialize(processor, server_transport, transport_factory=nil, protocol_factory=nil, num=20, logger=nil) super(processor, server_transport, transport_factory, protocol_factory) @num_threads = num if logger.nil? @logger = Logger.new(STDERR) @logger.level = Logger::WARN else @logger = logger end @shutdown_semaphore = Mutex.new @transport_semaphore = Mutex.new end def serve @logger.info "Starting #{self}" @server_transport.listen @io_manager = start_io_manager begin loop do break if @server_transport.closed? begin rd, = select([@server_transport], nil, nil, 0.1) rescue Errno::EBADF => e # In Ruby 1.9, calling @server_transport.close in shutdown paths causes the select() to raise an # Errno::EBADF. If this happens, ignore it and retry the loop. break end next if rd.nil? socket = @server_transport.accept @logger.debug "Accepted socket: #{socket.inspect}" @io_manager.add_connection socket end rescue IOError => e end # we must be shutting down @logger.info "#{self} is shutting down, goodbye" ensure @transport_semaphore.synchronize do @server_transport.close end @io_manager.ensure_closed unless @io_manager.nil? end def shutdown(timeout = 0, block = true) @shutdown_semaphore.synchronize do return if @is_shutdown @is_shutdown = true end # nonblocking is intended for calling from within a Handler # but we can't change the order of operations here, so lets thread shutdown_proc = lambda do @io_manager.shutdown(timeout) @transport_semaphore.synchronize do @server_transport.close # this will break the accept loop end end if block shutdown_proc.call else Thread.new &shutdown_proc end end private def start_io_manager iom = IOManager.new(@processor, @server_transport, @transport_factory, @protocol_factory, @num_threads, @logger) iom.spawn iom end class IOManager # :nodoc: DEFAULT_BUFFER = 2**20 def initialize(processor, server_transport, transport_factory, protocol_factory, num, logger) @processor = processor @server_transport = server_transport @transport_factory = transport_factory @protocol_factory = protocol_factory @num_threads = num @logger = logger @connections = [] @buffers = Hash.new { |h,k| h[k] = '' } @signal_queue = Queue.new @signal_pipes = IO.pipe @signal_pipes[1].sync = true @worker_queue = Queue.new @shutdown_queue = Queue.new end def add_connection(socket) signal [:connection, socket] end def spawn @iom_thread = Thread.new do @logger.debug "Starting #{self}" run end end def shutdown(timeout = 0) @logger.debug "#{self} is shutting down workers" @worker_queue.clear @num_threads.times { @worker_queue.push [:shutdown] } signal [:shutdown, timeout] @shutdown_queue.pop @signal_pipes[0].close @signal_pipes[1].close @logger.debug "#{self} is shutting down, goodbye" end def ensure_closed kill_worker_threads if @worker_threads @iom_thread.kill end private def run spin_worker_threads loop do rd, = select([@signal_pipes[0], *@connections]) if rd.delete @signal_pipes[0] break if read_signals == :shutdown end rd.each do |fd| begin if fd.handle.eof? remove_connection fd else read_connection fd end rescue Errno::ECONNRESET remove_connection fd end end end join_worker_threads(@shutdown_timeout) ensure @shutdown_queue.push :shutdown end def read_connection(fd) @buffers[fd] << fd.read(DEFAULT_BUFFER) while(frame = slice_frame!(@buffers[fd])) @logger.debug "#{self} is processing a frame" @worker_queue.push [:frame, fd, frame] end end def spin_worker_threads @logger.debug "#{self} is spinning up worker threads" @worker_threads = [] @num_threads.times do @worker_threads << spin_thread end end def spin_thread Worker.new(@processor, @transport_factory, @protocol_factory, @logger, @worker_queue).spawn end def signal(msg) @signal_queue << msg @signal_pipes[1].write " " end def read_signals # clear the signal pipe # note that since read_nonblock is broken in jruby, # we can only read up to a set number of signals at once sigstr = @signal_pipes[0].readpartial(1024) # now read the signals begin sigstr.length.times do signal, obj = @signal_queue.pop(true) case signal when :connection @connections << obj when :shutdown @shutdown_timeout = obj return :shutdown end end rescue ThreadError # out of signals # note that in a perfect world this would never happen, since we're # only reading the number of signals pushed on the pipe, but given the lack # of locks, in theory we could clear the pipe/queue while a new signal is being # placed on the pipe, at which point our next read_signals would hit this error end end def remove_connection(fd) # don't explicitly close it, a thread may still be writing to it @connections.delete fd @buffers.delete fd end def join_worker_threads(shutdown_timeout) start = Time.now @worker_threads.each do |t| if shutdown_timeout > 0 timeout = (start + shutdown_timeout) - Time.now break if timeout <= 0 t.join(timeout) else t.join end end kill_worker_threads end def kill_worker_threads @worker_threads.each do |t| t.kill if t.status end @worker_threads.clear end def slice_frame!(buf) if buf.length >= 4 size = buf.unpack('N').first if buf.length >= size + 4 buf.slice!(0, size + 4) else nil end else nil end end class Worker # :nodoc: def initialize(processor, transport_factory, protocol_factory, logger, queue) @processor = processor @transport_factory = transport_factory @protocol_factory = protocol_factory @logger = logger @queue = queue end def spawn Thread.new do @logger.debug "#{self} is spawning" run end end private def run loop do cmd, *args = @queue.pop case cmd when :shutdown @logger.debug "#{self} is shutting down, goodbye" break when :frame fd, frame = args begin otrans = @transport_factory.get_transport(fd) oprot = @protocol_factory.get_protocol(otrans) membuf = MemoryBufferTransport.new(frame) itrans = @transport_factory.get_transport(membuf) iprot = @protocol_factory.get_protocol(itrans) @processor.process(iprot, oprot) rescue => e @logger.error "#{Thread.current.inspect} raised error: #{e.inspect}\n#{e.backtrace.join("\n")}" end end end end end end end end thrift-0.19.0/lib/rb/lib/thrift/transport/0000777000000000000000000000000014303740367020365 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/transport/ssl_socket.rb0000644000000000000000000000316014303740367023057 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. module Thrift class SSLSocket < Socket def initialize(host='localhost', port=9090, timeout=nil, ssl_context=nil) super(host, port, timeout) @ssl_context = ssl_context end attr_accessor :ssl_context def open socket = super @handle = OpenSSL::SSL::SSLSocket.new(socket, @ssl_context) begin @handle.connect_nonblock @handle.post_connection_check(@host) @handle rescue IO::WaitReadable IO.select([ @handle ], nil, nil, @timeout) retry rescue IO::WaitWritable IO.select(nil, [ @handle ], nil, @timeout) retry rescue StandardError => e raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}") end end def to_s "ssl(#{super.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/memory_buffer_transport.rb0000644000000000000000000000627214303740367025672 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class MemoryBufferTransport < BaseTransport GARBAGE_BUFFER_SIZE = 4*(2**10) # 4kB # If you pass a string to this, you should #dup that string # unless you want it to be modified by #read and #write #-- # this behavior is no longer required. If you wish to change it # go ahead, just make sure the specs pass def initialize(buffer = nil) @buf = buffer ? Bytes.force_binary_encoding(buffer) : Bytes.empty_byte_buffer @index = 0 end def open? return true end def open end def close end def peek @index < @buf.size end # this method does not use the passed object directly but copies it def reset_buffer(new_buf = '') @buf.replace Bytes.force_binary_encoding(new_buf) @index = 0 end def available @buf.length - @index end def read(len) data = @buf.slice(@index, len) @index += len @index = @buf.size if @index > @buf.size if @index >= GARBAGE_BUFFER_SIZE @buf = @buf.slice(@index..-1) @index = 0 end if data.size < len raise EOFError, "Not enough bytes remain in buffer" end data end def read_byte raise EOFError.new("Not enough bytes remain in buffer") if @index >= @buf.size val = Bytes.get_string_byte(@buf, @index) @index += 1 if @index >= GARBAGE_BUFFER_SIZE @buf = @buf.slice(@index..-1) @index = 0 end val end def read_into_buffer(buffer, size) i = 0 while i < size raise EOFError.new("Not enough bytes remain in buffer") if @index >= @buf.size # The read buffer has some data now, so copy bytes over to the output buffer. byte = Bytes.get_string_byte(@buf, @index) Bytes.set_string_byte(buffer, i, byte) @index += 1 i += 1 end if @index >= GARBAGE_BUFFER_SIZE @buf = @buf.slice(@index..-1) @index = 0 end i end def write(wbuf) @buf << Bytes.force_binary_encoding(wbuf) end def flush end def inspect_buffer out = [] for idx in 0...(@buf.size) # if idx != 0 # out << " " # end if idx == @index out << ">" end out << @buf[idx].ord.to_s(16) end out.join(" ") end def to_s "memory" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/buffered_transport.rb0000644000000000000000000000635414303740367024614 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class BufferedTransport < BaseTransport DEFAULT_BUFFER = 4096 def initialize(transport) @transport = transport @wbuf = Bytes.empty_byte_buffer @rbuf = Bytes.empty_byte_buffer @index = 0 end def open? return @transport.open? end def open @transport.open end def close flush @transport.close end def read(sz) @index += sz ret = @rbuf.slice(@index - sz, sz) || Bytes.empty_byte_buffer if ret.length == 0 @rbuf = @transport.read([sz, DEFAULT_BUFFER].max) @index = sz ret = @rbuf.slice(0, sz) || Bytes.empty_byte_buffer end ret end def read_byte # If the read buffer is exhausted, try to read up to DEFAULT_BUFFER more bytes into it. if @index >= @rbuf.size @rbuf = @transport.read(DEFAULT_BUFFER) @index = 0 end # The read buffer has some data now, read a single byte. Using get_string_byte() avoids # allocating a temp string of size 1 unnecessarily. @index += 1 return Bytes.get_string_byte(@rbuf, @index - 1) end # Reads a number of bytes from the transport into the buffer passed. # # buffer - The String (byte buffer) to write data to; this is assumed to have a BINARY encoding. # size - The number of bytes to read from the transport and write to the buffer. # # Returns the number of bytes read. def read_into_buffer(buffer, size) i = 0 while i < size # If the read buffer is exhausted, try to read up to DEFAULT_BUFFER more bytes into it. if @index >= @rbuf.size @rbuf = @transport.read(DEFAULT_BUFFER) @index = 0 end # The read buffer has some data now, so copy bytes over to the output buffer. byte = Bytes.get_string_byte(@rbuf, @index) Bytes.set_string_byte(buffer, i, byte) @index += 1 i += 1 end i end def write(buf) @wbuf << Bytes.force_binary_encoding(buf) end def flush unless @wbuf.empty? @transport.write(@wbuf) @wbuf = Bytes.empty_byte_buffer end @transport.flush end def to_s "buffered(#{@transport.to_s})" end end class BufferedTransportFactory < BaseTransportFactory def get_transport(transport) return BufferedTransport.new(transport) end def to_s "buffered" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/socket.rb0000644000000000000000000001073114303740367022200 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'socket' module Thrift class Socket < BaseTransport def initialize(host='localhost', port=9090, timeout=nil) @host = host @port = port @timeout = timeout @desc = "#{host}:#{port}" @handle = nil end attr_accessor :handle, :timeout def open for addrinfo in ::Socket::getaddrinfo(@host, @port, nil, ::Socket::SOCK_STREAM) do begin socket = ::Socket.new(addrinfo[4], ::Socket::SOCK_STREAM, 0) socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1) sockaddr = ::Socket.sockaddr_in(addrinfo[1], addrinfo[3]) begin socket.connect_nonblock(sockaddr) rescue Errno::EINPROGRESS unless IO.select(nil, [ socket ], nil, @timeout) next end begin socket.connect_nonblock(sockaddr) rescue Errno::EISCONN end end return @handle = socket rescue StandardError => e next end end raise TransportException.new(TransportException::NOT_OPEN, "Could not connect to #{@desc}: #{e}") end def open? !@handle.nil? and !@handle.closed? end def write(str) raise IOError, "closed stream" unless open? str = Bytes.force_binary_encoding(str) begin if @timeout.nil? or @timeout == 0 @handle.write(str) else len = 0 start = Time.now while Time.now - start < @timeout rd, wr, = IO.select(nil, [@handle], nil, @timeout) if wr and not wr.empty? len += @handle.write_nonblock(str[len..-1]) break if len >= str.length end end if len < str.length raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out writing #{str.length} bytes to #{@desc}") else len end end rescue TransportException => e # pass this on raise e rescue StandardError => e @handle.close @handle = nil raise TransportException.new(TransportException::NOT_OPEN, e.message) end end def read(sz) raise IOError, "closed stream" unless open? begin if @timeout.nil? or @timeout == 0 data = @handle.readpartial(sz) else # it's possible to interrupt select for something other than the timeout # so we need to ensure we've waited long enough, but not too long start = Time.now timespent = 0 rd = loop do rd, = IO.select([@handle], nil, nil, @timeout - timespent) timespent = Time.now - start break rd if (rd and not rd.empty?) or timespent >= @timeout end if rd.nil? or rd.empty? raise TransportException.new(TransportException::TIMED_OUT, "Socket: Timed out reading #{sz} bytes from #{@desc}") else data = @handle.readpartial(sz) end end rescue TransportException => e # don't let this get caught by the StandardError handler raise e rescue StandardError => e @handle.close unless @handle.closed? @handle = nil raise TransportException.new(TransportException::NOT_OPEN, e.message) end if (data.nil? or data.length == 0) raise TransportException.new(TransportException::UNKNOWN, "Socket: Could not read #{sz} bytes from #{@desc}") end data end def close @handle.close unless @handle.nil? or @handle.closed? @handle = nil end alias to_io handle def to_s "socket(#{@host}:#{@port})" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/framed_transport.rb0000644000000000000000000000622714303740367024267 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class FramedTransport < BaseTransport def initialize(transport, read=true, write=true) @transport = transport @rbuf = Bytes.empty_byte_buffer @wbuf = Bytes.empty_byte_buffer @read = read @write = write @index = 0 end def open? @transport.open? end def open @transport.open end def close @transport.close end def read(sz) return @transport.read(sz) unless @read return Bytes.empty_byte_buffer if sz <= 0 read_frame if @index >= @rbuf.length @index += sz @rbuf.slice(@index - sz, sz) || Bytes.empty_byte_buffer end def read_byte return @transport.read_byte() unless @read read_frame if @index >= @rbuf.length # The read buffer has some data now, read a single byte. Using get_string_byte() avoids # allocating a temp string of size 1 unnecessarily. @index += 1 return Bytes.get_string_byte(@rbuf, @index - 1) end def read_into_buffer(buffer, size) i = 0 while i < size read_frame if @index >= @rbuf.length # The read buffer has some data now, so copy bytes over to the output buffer. byte = Bytes.get_string_byte(@rbuf, @index) Bytes.set_string_byte(buffer, i, byte) @index += 1 i += 1 end i end def write(buf, sz=nil) return @transport.write(buf) unless @write buf = Bytes.force_binary_encoding(buf) @wbuf << (sz ? buf[0...sz] : buf) end # # Writes the output buffer to the stream in the format of a 4-byte length # followed by the actual data. # def flush return @transport.flush unless @write out = [@wbuf.length].pack('N') # Array#pack should return a BINARY encoded String, so it shouldn't be necessary to force encoding out << @wbuf @transport.write(out) @transport.flush @wbuf = Bytes.empty_byte_buffer end def to_s "framed(#{@transport.to_s})" end private def read_frame sz = @transport.read_all(4).unpack('N').first @index = 0 @rbuf = @transport.read_all(sz) end end class FramedTransportFactory < BaseTransportFactory def get_transport(transport) return FramedTransport.new(transport) end def to_s "framed" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/http_client_transport.rb0000644000000000000000000000401514303740367025337 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'net/http' require 'net/https' require 'openssl' require 'uri' require 'stringio' module Thrift class HTTPClientTransport < BaseTransport def initialize(url, opts = {}) @url = URI url @headers = {'Content-Type' => 'application/x-thrift'} @outbuf = Bytes.empty_byte_buffer @ssl_verify_mode = opts.fetch(:ssl_verify_mode, OpenSSL::SSL::VERIFY_PEER) end def open?; true end def read(sz); @inbuf.read sz end def write(buf); @outbuf << Bytes.force_binary_encoding(buf) end def add_headers(headers) @headers = @headers.merge(headers) end def flush http = Net::HTTP.new @url.host, @url.port http.use_ssl = @url.scheme == 'https' http.verify_mode = @ssl_verify_mode if @url.scheme == 'https' resp = http.post(@url.request_uri, @outbuf, @headers) raise TransportException.new(TransportException::UNKNOWN, "#{self.class.name} Could not connect to #{@url}, HTTP status code #{resp.code.to_i}") unless (200..299).include?(resp.code.to_i) data = resp.body data = Bytes.force_binary_encoding(data) @inbuf = StringIO.new data ensure @outbuf = Bytes.empty_byte_buffer end def to_s "@{self.url}" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/base_server_transport.rb0000644000000000000000000000205014303740367025317 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class BaseServerTransport def listen raise NotImplementedError end def accept raise NotImplementedError end def close; nil; end def closed? raise NotImplementedError end end end thrift-0.19.0/lib/rb/lib/thrift/transport/ssl_server_socket.rb0000644000000000000000000000233514303740367024450 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'socket' module Thrift class SSLServerSocket < ServerSocket def initialize(host_or_port, port = nil, ssl_context = nil) super(host_or_port, port) @ssl_context = ssl_context end attr_accessor :ssl_context def listen socket = TCPServer.new(@host, @port) @handle = OpenSSL::SSL::SSLServer.new(socket, @ssl_context) end def to_s "ssl(#{super.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/unix_server_socket.rb0000644000000000000000000000307214303740367024631 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'socket' module Thrift class UNIXServerSocket < BaseServerTransport def initialize(path) @path = path @handle = nil end attr_accessor :handle def listen @handle = ::UNIXServer.new(@path) end def accept unless @handle.nil? sock = @handle.accept trans = UNIXSocket.new(nil) trans.handle = sock trans end end def close if @handle @handle.close unless @handle.closed? @handle = nil # UNIXServer doesn't delete the socket file, so we have to do it ourselves File.delete(@path) end end def closed? @handle.nil? or @handle.closed? end alias to_io handle def to_s "domain(#{@path})" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/base_transport.rb0000644000000000000000000000547714303740367023751 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class TransportException < Exception UNKNOWN = 0 NOT_OPEN = 1 ALREADY_OPEN = 2 TIMED_OUT = 3 END_OF_FILE = 4 attr_reader :type def initialize(type=UNKNOWN, message=nil) super(message) @type = type end end module TransportUtils # Deprecated: Use Thrift::Bytes instead def self.get_string_byte(string, index) Bytes.get_string_byte(string, index) end # Deprecated: Use Thrift::Bytes instead def self.set_string_byte(string, index, byte) Bytes.set_string_byte(string, index, byte) end end class BaseTransport def open?; end def open; end def close; end # Reads a number of bytes from the transports. In Ruby 1.9+, the String returned will have a BINARY (aka ASCII8BIT) encoding. # # sz - The number of bytes to read from the transport. # # Returns a String acting as a byte buffer. def read(sz) raise NotImplementedError end # Returns an unsigned byte as a Fixnum in the range (0..255). def read_byte buf = read_all(1) return Bytes.get_string_byte(buf, 0) end # Reads size bytes and copies them into buffer[0..size]. def read_into_buffer(buffer, size) tmp = read_all(size) i = 0 tmp.each_byte do |byte| Bytes.set_string_byte(buffer, i, byte) i += 1 end i end def read_all(size) return Bytes.empty_byte_buffer if size <= 0 buf = read(size) while (buf.length < size) chunk = read(size - buf.length) buf << chunk end buf end # Writes the byte buffer to the transport. In Ruby 1.9+, the buffer will be forced into BINARY encoding. # # buf - A String acting as a byte buffer. # # Returns nothing. def write(buf); end alias_method :<<, :write def flush; end def to_s "base" end end class BaseTransportFactory def get_transport(trans) return trans end def to_s "base" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/io_stream_transport.rb0000644000000000000000000000304414303740367025005 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Very very simple implementation of wrapping two objects, one with a #read # method and one with a #write method, into a transport for thrift. # # Assumes both objects are open, remain open, don't require flushing, etc. # module Thrift class IOStreamTransport < BaseTransport def initialize(input, output) @input = input @output = output end def open?; not @input.closed? or not @output.closed? end def read(sz); @input.read(sz) end def write(buf); @output.write(Bytes.force_binary_encoding(buf)) end def close; @input.close; @output.close end def to_io; @input end # we're assuming this is used in a IO.select for reading def to_s "iostream(input=#{@input.to_s},output=#{@output.to_s})" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/server_socket.rb0000644000000000000000000000315614303740367023571 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'socket' module Thrift class ServerSocket < BaseServerTransport # call-seq: initialize(host = nil, port) def initialize(host_or_port, port = nil) if port @host = host_or_port @port = port else @host = nil @port = host_or_port end @handle = nil end attr_reader :handle def listen @handle = TCPServer.new(@host, @port) end def accept unless @handle.nil? sock = @handle.accept trans = Socket.new trans.handle = sock trans end end def close @handle.close unless @handle.nil? or @handle.closed? @handle = nil end def closed? @handle.nil? or @handle.closed? end alias to_io handle def to_s "socket(#{@host}:#{@port})" end end end thrift-0.19.0/lib/rb/lib/thrift/transport/unix_socket.rb0000644000000000000000000000243314303740367023243 0ustar00rootroot00000000000000# encoding: ascii-8bit # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # require 'socket' module Thrift class UNIXSocket < Socket def initialize(path, timeout=nil) @path = path @timeout = timeout @desc = @path # for read()'s error @handle = nil end def open begin @handle = ::UNIXSocket.new(@path) rescue StandardError raise TransportException.new(TransportException::NOT_OPEN, "Could not open UNIX socket at #{@path}") end end def to_s "domain(#{@path})" end end end thrift-0.19.0/lib/rb/lib/thrift/exceptions.rb0000644000000000000000000000442514303740367021040 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class Exception < StandardError def initialize(message) super @message = message end attr_reader :message end class ApplicationException < Exception UNKNOWN = 0 UNKNOWN_METHOD = 1 INVALID_MESSAGE_TYPE = 2 WRONG_METHOD_NAME = 3 BAD_SEQUENCE_ID = 4 MISSING_RESULT = 5 INTERNAL_ERROR = 6 PROTOCOL_ERROR = 7 INVALID_TRANSFORM = 8 INVALID_PROTOCOL = 9 UNSUPPORTED_CLIENT_TYPE = 10 attr_reader :type def initialize(type=UNKNOWN, message=nil) super(message) @type = type end def read(iprot) iprot.read_struct_begin while true fname, ftype, fid = iprot.read_field_begin if ftype == Types::STOP break end if fid == 1 and ftype == Types::STRING @message = iprot.read_string elsif fid == 2 and ftype == Types::I32 @type = iprot.read_i32 else iprot.skip(ftype) end iprot.read_field_end end iprot.read_struct_end end def write(oprot) oprot.write_struct_begin('Thrift::ApplicationException') unless @message.nil? oprot.write_field_begin('message', Types::STRING, 1) oprot.write_string(@message) oprot.write_field_end end unless @type.nil? oprot.write_field_begin('type', Types::I32, 2) oprot.write_i32(@type) oprot.write_field_end end oprot.write_field_stop oprot.write_struct_end end end end thrift-0.19.0/lib/rb/lib/thrift/core_ext.rb0000644000000000000000000000163414303740367020466 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each do |file| name = File.basename(file, '.rb') require "thrift/core_ext/#{name}" end thrift-0.19.0/lib/rb/lib/thrift/core_ext/0000777000000000000000000000000014303740367020141 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/core_ext/fixnum.rb0000644000000000000000000000170114303740367021767 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Versions of ruby pre 1.8.7 do not have an .ord method available in the Fixnum # class. # if RUBY_VERSION < "1.8.7" class Fixnum def ord self end end endthrift-0.19.0/lib/rb/lib/thrift/serializer/0000777000000000000000000000000014303740367020502 5ustar00rootroot00000000000000thrift-0.19.0/lib/rb/lib/thrift/serializer/deserializer.rb0000644000000000000000000000215314303740367023506 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class Deserializer def initialize(protocol_factory = BinaryProtocolFactory.new) @transport = MemoryBufferTransport.new @protocol = protocol_factory.get_protocol(@transport) end def deserialize(base, buffer) @transport.reset_buffer(buffer) base.read(@protocol) base end end endthrift-0.19.0/lib/rb/lib/thrift/serializer/serializer.rb0000644000000000000000000000217314303740367023177 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # module Thrift class Serializer def initialize(protocol_factory = BinaryProtocolFactory.new) @transport = MemoryBufferTransport.new @protocol = protocol_factory.get_protocol(@transport) end def serialize(base) @transport.reset_buffer base.write(@protocol) @transport.read(@transport.available) end end end thrift-0.19.0/lib/rb/lib/thrift.rb0000644000000000000000000000460114303740367016653 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Contains some contributions under the Thrift Software License. # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. $:.unshift File.dirname(__FILE__) require 'thrift/bytes' require 'thrift/core_ext' require 'thrift/exceptions' require 'thrift/types' require 'thrift/processor' require 'thrift/multiplexed_processor' require 'thrift/client' require 'thrift/struct' require 'thrift/union' require 'thrift/struct_union' # serializer require 'thrift/serializer/serializer' require 'thrift/serializer/deserializer' # protocol require 'thrift/protocol/base_protocol' require 'thrift/protocol/binary_protocol' require 'thrift/protocol/binary_protocol_accelerated' require 'thrift/protocol/compact_protocol' require 'thrift/protocol/json_protocol' require 'thrift/protocol/multiplexed_protocol' # transport require 'thrift/transport/base_transport' require 'thrift/transport/base_server_transport' require 'thrift/transport/socket' require 'thrift/transport/ssl_socket' require 'thrift/transport/server_socket' require 'thrift/transport/ssl_server_socket' require 'thrift/transport/unix_socket' require 'thrift/transport/unix_server_socket' require 'thrift/transport/buffered_transport' require 'thrift/transport/framed_transport' require 'thrift/transport/http_client_transport' require 'thrift/transport/io_stream_transport' require 'thrift/transport/memory_buffer_transport' # server require 'thrift/server/base_server' require 'thrift/server/nonblocking_server' require 'thrift/server/simple_server' require 'thrift/server/threaded_server' require 'thrift/server/thread_pool_server' require 'thrift/thrift_native' thrift-0.19.0/lib/rb/Makefile.in0000644000000000000000000004424614472652517016344 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/rb ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ coding_standards.md \ Rakefile \ Gemfile \ thrift.gemspec \ lib \ ext \ benchmark \ script \ spec \ README.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/rb/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/rb/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook @HAVE_BUNDLER_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am @HAVE_BUNDLER_FALSE@all-local: all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." @HAVE_BUNDLER_FALSE@clean-local: @HAVE_BUNDLER_FALSE@install-exec-hook: clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-exec-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ dist-hook distclean distclean-generic distclean-libtool \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile DESTDIR ?= / @HAVE_BUNDLER_TRUE@all-local: @HAVE_BUNDLER_TRUE@ $(BUNDLER) install @HAVE_BUNDLER_TRUE@ $(BUNDLER) exec rake build_ext @HAVE_BUNDLER_TRUE@install-exec-hook: @HAVE_BUNDLER_TRUE@ $(BUNDLER) exec rake install @HAVE_BUNDLER_TRUE@clean-local: @HAVE_BUNDLER_TRUE@ $(BUNDLER) install @HAVE_BUNDLER_TRUE@ $(BUNDLER) exec rake clean @HAVE_BUNDLER_TRUE@ $(RM) -r spec/gen-rb/ @HAVE_BUNDLER_TRUE@check-local: all @HAVE_BUNDLER_TRUE@ $(BUNDLER) install @HAVE_BUNDLER_TRUE@ $(BUNDLER) exec rake dist-hook: $(RM) -r $(distdir)/spec/gen-rb/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/cl/0000755000000000000000000000000014472652671014261 5ustar00rootroot00000000000000thrift-0.19.0/lib/cl/READMES/0000755000000000000000000000000014370300523015320 5ustar00rootroot00000000000000thrift-0.19.0/lib/cl/READMES/readme-cassandra.lisp0000644000000000000000000000523014370300523021403 0ustar00rootroot00000000000000(in-package :cl-user) #+(or ccl sbcl) /development/source/library/ (load "build-init.lisp") ;;; ! first, select the api version in the cassandra system definition ;;; as only one should be loaded at a time. (asdf:load-system :de.setf.cassandra) (in-package :de.setf.cassandra) (defparameter *c-location* ;; remote ;; #u"thrift://ec2-174-129-66-148.compute-1.amazonaws.com:9160" ;; local #u"thrift://127.0.0.1:9160" "A cassandra service location - either the local one or a remote service - always a 'thrift' uri.") (defparameter *c* (thrift:client *c-location*)) (cassandra:describe-keyspaces *c*) ;; => ("Keyspace1" "system") (cassandra:describe-cluster-name *c*) ;; =>"Test Cluster" (cassandra:describe-version *c*) ;; => "2.1.0" (loop for space in (cassandra:describe-keyspaces *c*) collect (loop for key being each hash-key of (cassandra:describe-keyspace *c* space) using (hash-value value) collect (cons key (loop for key being each hash-key of value using (hash-value value) collect (cons key value))))) (close *c*) (defun describe-cassandra (location &optional (stream *standard-output*)) "Print the first-order store metadata for a cassandra LOCATION." (thrift:with-client (cassandra location) (let* ((keyspace-names (cassandra:describe-keyspaces cassandra)) (cluster (cassandra:describe-cluster-name cassandra)) (version (cassandra:describe-version cassandra)) (keyspace-descriptions (loop for space in keyspace-names collect (cons space (loop for key being each hash-key of (cassandra:describe-keyspace cassandra space) using (hash-value value) collect (cons key (loop for key being each hash-key of value using (hash-value value) collect (cons key value)))))))) (format stream "~&connection to : ~a" cassandra) (format stream "~&version : ~a" version) (format stream "~&cluster : ~a" cluster) (format stream "~&keyspaces~{~{~%~%space: ~a~@{~% ~{~a :~@{~20t~:w~^~%~}~}~}~}~}" keyspace-descriptions)))) ;;; (describe-cassandra *c-location*) thrift-0.19.0/lib/cl/load-locally.lisp0000644000000000000000000000172214370300523017507 0ustar00rootroot00000000000000(in-package #:cl-user) ;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. ;;;; Just a script for loading the library itself, using bundled dependencies. ;;;; This is here for when we want to build the self-test and cross-test ;;;; binaries. (require "asdf") (load (merge-pathnames "externals/bundle.lisp" *load-truename*)) (asdf:load-asd (merge-pathnames "lib/de.setf.thrift-backport-update/thrift.asd" *load-truename*)) (asdf:load-system :thrift) thrift-0.19.0/lib/cl/Makefile.am0000644000000000000000000000223514370300523016276 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = $(top_builddir)/compiler/cpp/thrift all-local: bash ensure-externals.sh run-tests: test/make-test-binary.lisp $(SBCL) --script test/make-test-binary.lisp check-local: run-tests ./run-tests clean-local: $(RM) run-tests quicklisp.lisp backport-update.zip $(RM) -rf lib externals quicklisp EXTRA_DIST = \ README.md \ READMES \ load-locally.lisp \ test \ ensure-externals.sh thrift-0.19.0/lib/cl/ensure-externals.sh0000755000000000000000000000131714370300523020105 0ustar00rootroot00000000000000#!/bin/bash set -e if [[ ! -e quicklisp.lisp ]]; then curl -O https://beta.quicklisp.org/quicklisp.lisp; fi sbcl --load quicklisp.lisp \ --eval "(ignore-errors (quicklisp-quickstart:install :path \"quicklisp/\"))" \ --eval "(load \"quicklisp/setup.lisp\")" \ --eval "(quicklisp:bundle-systems '(#:puri #:usocket #:closer-mop #:trivial-utf-8 #:ieee-floats #:trivial-gray-streams #:alexandria #:bordeaux-threads #:cl-ppcre #:fiasco #:net.didierverna.clon) :to \"externals/\")" \ --eval "(quit)" \ --no-userinit if [[ ! -e backport-update.zip ]]; then curl -O -L https://github.com/TurtleWarePL/de.setf.thrift/archive/backport-update.zip; fi mkdir -p lib unzip -u backport-update.zip -d lib thrift-0.19.0/lib/cl/README.md0000644000000000000000000002366214370300523015530 0ustar00rootroot00000000000000Thrift Common Lisp Library License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Using Thrift with Common Lisp ============================ Thrift is a protocol and library for language-independent communication between cooperating processes. The communication takes the form of request and response messages, of which the forms are specified in advance throufh a shared interface definition. A Thrift definition file is translated into Lisp source files, which comprise several definitions: * Three packages, one for the namespace of the implementation operators, and one each for request and response operators. * Various type definitions as implementations for Thrift typedef and enum definitions. * DEF-STRUCT and DEF-EXCEPTION forms for Thrift struct and exception definitions. * DEF-SERVICE forms for thrift service definitions. Each service definition expands in a collection of generic function definitions. For each `op` in the service definition, two functions are defined * `op`-request is defined for use by a client. It accepts an additional initial `protocol` argument, to act as the client proxy for the operation and mediate the interaction with a remote process through a Thrift-encoded transport stream. * `op`-response is defined for use by a server. It accepts a single `protocol` argument. A server uses it to decode the request message, invoke the base `op` function with the message arguments, encode and send the the result as a response, and handles exceptions. The client interface is one operator * `with-client (variable location) . body` : creates a connection in a dynamic context and closes it upon exit. The variable is bound to a client proxy stream/protocol instance, which wraps the base i/o stream - socket, file, etc, with an operators which implement the Thrift protocol and transport mechanisms. The server interface combines server and service objects * `serve (location service)` : accepts connections on the designated port and responds to requests of the service's operations. Building -------- The Thrift Common Lisp library is packaged as the ASDF[[1]] system `thrift`. It depends on the systems * puri[[2]] : for the thrift uri class * closer-mop[[3]] : for class metadata * trivial-utf-8[[4]] : for string codecs * usocket[[5]] : for the socket transport * ieee-floats[[6]] : for conversion between ints and floats * trivial-gray-streams[[7]] : an abstraction layer for gray streams * alexandria[[8]] : handy utilities The dependencies are bundled for local builds of tests and tutorial binaries - it is possible to use those bundles to load the library, too. In order to build it, register those systems with ASDF and evaluate: (asdf:load-system :thrift) This will compile and load the Lisp compiler for Thrift definition files, the transport and protocol implementations, and the client and server interface functions. In order to use Thrift in an application, one must also author and/or load the interface definitions for the remote service.[[9]] If one is implementing a service, one must also define the actual functions to which Thrift is to act as the proxy interface. The remainder of this document follows the Thrift tutorial to illustrate how to perform the steps * implement the service * translate the Thrift IDL * load the Lisp service interfaces * run a server for the service * use a client to access the service remotely Note that, if one is to implement a new service, one will also need to author the IDL files, as there is no facility to generate them from a service implementation. Implement the Service --------------------- The tutorial comprises serveral functions: `add`, `ping`, `zip`, and `calculate`. Each translated IDL file generates three packages for every service. In the case of the tutorial file, the relevant packages are: * tutorial.calculator * tutorial.calculator-implementation * tutorial.calculator-response This is to separate the request (generated), response (generated) and implementation (meant to be implemented by the programmer) functions for defined Thrift methods. It is suggested to work in the `tutorial-implementation` package while implementing the services - it imports the `common-lisp` package, while the service-specific ones don't (to avoid conflicts between Thrift method names and function names in `common-lisp`). ;; define the base operations (in-package :tutorial-implementation) (defun tutorial.calculator-implementation:add (num1 num2) (format t "~&Asked to add ~A and ~A." num1 num2) (+ num1 num2)) (defun tutorial.calculator-implementation:ping () (print :ping)) (defun tutorial.calculator-implementation:zip () (print :zip)) (defun tutorial.calculator-implementation:calculate (logid task) (calculate-op (work-op task) (work-num1 task) (work-num2 task))) (defgeneric calculate-op (op arg1 arg2) (:method :around (op arg1 arg2) (let ((result (call-next-method))) (format t "~&Asked to calculate: ~d on ~A and ~A = ~d." op arg1 arg2 result) result)) (:method ((op (eql operation.add)) arg1 arg2) (+ arg1 arg2)) (:method ((op (eql operation.subtract)) arg1 arg2) (- arg1 arg2)) (:method ((op (eql operation.multiply)) arg1 arg2) (* arg1 arg2)) (:method ((op (eql operation.divide)) arg1 arg2) (/ arg1 arg2))) (defun zip () (print 'zip)) Translate the Thrift IDL ------------------------ IDL files employ the file extension `thrift`. In this case, there are two files to translate * `tutorial.thrift` * `shared.thrift` As the former includes the latter, one uses it to generate the interfaces: $THRIFT/bin/thrift -r --gen cl $THRIFT/tutorial/tutorial.thrift `-r` stands for recursion, while `--gen` lets one choose the language to translate to. Load the Lisp translated service interfaces ------------------------------------------- The translator generates three files for each IDL file. For example `tutorial-types.lisp`, `tutorial-vars.lisp` and an `.asd` file that can be used to load them both and pull in other includes (like `shared` within the tutorial) as dependencies. Run a Server for the Service ---------------------------- The actual service name, as specified in the `def-service` form in `tutorial.lisp`, is `calculator`. Each service definition defines a global variable with the service name and binds it to a service instance whch describes the operations. In order to start a service, specify a location and the service instance. (in-package :tutorial) (serve #u"thrift://127.0.0.1:9091" calculator) Use a Client to Access the Service Remotely ------------------------------------------- [in some other process] run the client (in-package :cl-user) (macrolet ((show (form) `(format *trace-output* "~%~s =>~{ ~s~}" ',form (multiple-value-list (ignore-errors ,form))))) (with-client (protocol #u"thrift://127.0.0.1:9091") (show (tutorial.calculator:ping protocol)) (show (tutorial.calculator:add protocol 1 2)) (show (tutorial.calculator:add protocol 1 4)) (let ((task (make-instance 'tutorial:work :op operation.subtract :num1 15 :num2 10))) (show (tutorial.calculator:calculate protocol 1 task)) (setf (tutorial:work-op task) operation.divide (tutorial:work-num1 task) 1 (tutorial:work-num2 task) 0) (show (tutorial.calculator:calculate protocol 1 task))) (show (shared.shared-service:get-struct protocol 1)) (show (zip protocol)))) Issues ------ ### optional fields Where the IDL declares a field options, the def-struct form includes no initform for the slot and the encoding operator skips an unbound slot. This leave some ambiguity with bool fields. ### instantiation protocol : struct classes are standard classes and exception classes are whatever the implementation prescribes. decoders apply make-struct to an initargs list. particularly at the service end, there are advantages to resourcing structs and decoding with direct side-effects on slot-values ### maps: Maps are now represented as hash tables. As data through the call/reply interface is all statically typed, it is not necessary for the objects to themselves indicate the coding form. Association lists would be sufficient. As the key type is arbitrary, property lists offer no additional convenience: as `getf` operates with `eq` a new access interface would be necessary and they would not be available for function application. [1]: www.common-lisp.net/asdf [2]: http://github.com/lisp/com.b9.puri.ppcre [3]: www.common-lisp.net/closer-mop [4]: trivial-utf-8 [5]: https://github.com/usocket/usocket [6]: https://github.com/marijnh/ieee-floats [7]: https://github.com/trivial-gray-streams/trivial-gray-streams [8]: https://gitlab.common-lisp.net/alexandria/alexandria [9]: http://wiki.apache.org/thrift/ThriftGeneration * usocket[[5]] : for the socket transport * ieee-floats[[6]] : for conversion between ints and floats * trivial-gray-streams[[7]] : an abstraction layer for gray streams * alexandria[[8]] : handy utilities thrift-0.19.0/lib/cl/test/0000755000000000000000000000000014370300523015217 5ustar00rootroot00000000000000thrift-0.19.0/lib/cl/test/make-test-binary.lisp0000644000000000000000000000273014370300523021266 0ustar00rootroot00000000000000;;;; Licensed under the Apache License, Version 2.0 (the "License"); ;;;; you may not use this file except in compliance with the License. ;;;; You may obtain a copy of the License at ;;;; ;;;; http://www.apache.org/licenses/LICENSE-2.0 ;;;; ;;;; Unless required by applicable law or agreed to in writing, software ;;;; distributed under the License is distributed on an "AS IS" BASIS, ;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;;;; See the License for the specific language governing permissions and ;;;; limitations under the License. ;;;; This file is used to build the binary that runs all self-tests. The ;;;; binary is then meant to be hooked up to Thrift's `make check` facility, ;;;; but can easily be run on its own as well. (in-package #:cl-user) (require "asdf") (load (merge-pathnames "../load-locally.lisp" *load-truename*)) (asdf:load-asd (merge-pathnames "../lib/de.setf.thrift-backport-update/test/thrift-test.asd" *load-truename*)) (asdf:load-system :thrift-test) (require "sb-grovel") ;; necessary for :net.didierverna.clon.termio (asdf:load-asd (first (directory (merge-pathnames "../externals/software/clon-*/termio/net.didierverna.clon.termio.asd" *load-truename*)))) (asdf:load-system :net.didierverna.clon) (net.didierverna.clon:nickname-package) (defun main () (let ((result (if (fiasco:run-tests 'thrift-test) 0 -1))) (clon:exit result))) (clon:dump "run-tests" main) thrift-0.19.0/lib/cl/Makefile.in0000644000000000000000000004304314472652515016327 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/cl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = $(top_builddir)/compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ README.md \ READMES \ load-locally.lisp \ test \ ensure-externals.sh all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/cl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/cl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile all-local: bash ensure-externals.sh run-tests: test/make-test-binary.lisp $(SBCL) --script test/make-test-binary.lisp check-local: run-tests ./run-tests clean-local: $(RM) run-tests quicklisp.lisp backport-update.zip $(RM) -rf lib externals quicklisp # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/xml/0000755000000000000000000000000014472652646014465 5ustar00rootroot00000000000000thrift-0.19.0/lib/xml/Makefile.am0000644000000000000000000000162314303740367016512 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = if WITH_JAVA # Schema validation test depends on java SUBDIRS += test endif EXTRA_DIST = \ thrift-idl.xsd \ test thrift-0.19.0/lib/xml/test/0000777000000000000000000000000014472652606015444 5ustar00rootroot00000000000000thrift-0.19.0/lib/xml/test/Makefile.am0000644000000000000000000000171214303740367017470 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # check: $(ANT) $(ANT_FLAGS) test # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean thrift-0.19.0/lib/xml/test/Makefile0000644000000000000000000004335614472652606017113 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # lib/xml/test/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = lib/xml/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/lib/xml/test abs_srcdir = /thrift/src/lib/xml/test abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../../ top_builddir = ../../.. top_srcdir = ../../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/xml/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/xml/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile check: $(ANT) $(ANT_FLAGS) test # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/xml/test/build.xml0000644000000000000000000001007214303740367017254 0ustar00rootroot00000000000000 XML Schema Validation Test Thrift compiler is missing ! thrift-0.19.0/lib/xml/test/Makefile.in0000644000000000000000000004244414472652520017510 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/xml/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/xml/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/xml/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile check: $(ANT) $(ANT_FLAGS) test # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/xml/thrift-idl.xsd0000644000000000000000000002305414370300523017234 0ustar00rootroot00000000000000 thrift-0.19.0/lib/xml/Makefile.in0000644000000000000000000005670714472652520016540 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ # Schema validation test depends on java @WITH_JAVA_TRUE@am__append_1 = test subdir = lib/xml ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = test am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = $(am__append_1) EXTRA_DIST = \ thrift-idl.xsd \ test all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/xml/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/xml/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/php/0000755000000000000000000000000014472652661014451 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/Makefile.am0000644000000000000000000001144614303740367016505 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # if WITH_TESTS SUBDIRS = test endif if WITH_PHP_EXTENSION %.so: cd src/ext/thrift_protocol/ && $(MAKE) phpconfdir=$(PHP_CONFIG_PREFIX) phpconf_DATA=thrift_protocol.ini phpmoduledir = `php-config --extension-dir` phpmodule_SCRIPTS = src/ext/thrift_protocol/modules/thrift_protocol.so distclean-local: if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) distclean; fi cd $(phpmodule_SCRIPTS) && $(PHPIZE) --clean endif phpdir = $(PHP_PREFIX)/ php_DATA = \ lib/TMultiplexedProcessor.php phpbasedir = $(phpdir)/Base phpbase_DATA = \ lib/Base/TBase.php phpclassloaderdir = $(phpdir)/ClassLoader phpclassloader_DATA = \ lib/ClassLoader/ThriftClassLoader.php phpexceptiondir = $(phpdir)/Exception phpexception_DATA = \ lib/Exception/TApplicationException.php \ lib/Exception/TException.php \ lib/Exception/TProtocolException.php \ lib/Exception/TTransportException.php phpfactorydir = $(phpdir)/Factory phpfactory_DATA = \ lib/Factory/TBinaryProtocolFactory.php \ lib/Factory/TCompactProtocolFactory.php \ lib/Factory/TJSONProtocolFactory.php \ lib/Factory/TProtocolFactory.php \ lib/Factory/TStringFuncFactory.php \ lib/Factory/TTransportFactory.php phpprotocoldir = $(phpdir)/Protocol phpprotocol_DATA = \ lib/Protocol/TBinaryProtocolAccelerated.php \ lib/Protocol/TBinaryProtocol.php \ lib/Protocol/TCompactProtocol.php \ lib/Protocol/TJSONProtocol.php \ lib/Protocol/TMultiplexedProtocol.php \ lib/Protocol/TProtocol.php \ lib/Protocol/TProtocolDecorator.php \ lib/Protocol/TSimpleJSONProtocol.php phpprotocoljsondir = $(phpprotocoldir)/JSON phpprotocoljson_DATA = \ lib/Protocol/JSON/BaseContext.php \ lib/Protocol/JSON/ListContext.php \ lib/Protocol/JSON/LookaheadReader.php \ lib/Protocol/JSON/PairContext.php phpprotocolsimplejsondir = $(phpprotocoldir)/SimpleJSON phpprotocolsimplejson_DATA = \ lib/Protocol/SimpleJSON/CollectionMapKeyException.php \ lib/Protocol/SimpleJSON/Context.php \ lib/Protocol/SimpleJSON/ListContext.php \ lib/Protocol/SimpleJSON/MapContext.php \ lib/Protocol/SimpleJSON/StructContext.php phpserializerdir = $(phpdir)/Serializer phpserializer_DATA = \ lib/Serializer/TBinarySerializer.php phpserverdir = $(phpdir)/Server phpserver_DATA = \ lib/Server/TServerSocket.php \ lib/Server/TForkingServer.php \ lib/Server/TServer.php \ lib/Server/TServerTransport.php \ lib/Server/TSimpleServer.php phpstringfuncdir = $(phpdir)/StringFunc phpstringfunc_DATA = \ lib/StringFunc/Mbstring.php \ lib/StringFunc/Core.php \ lib/StringFunc/TStringFunc.php phptransportdir = $(phpdir)/Transport phptransport_DATA = \ lib/Transport/TBufferedTransport.php \ lib/Transport/TCurlClient.php \ lib/Transport/TFramedTransport.php \ lib/Transport/THttpClient.php \ lib/Transport/TMemoryBuffer.php \ lib/Transport/TNullTransport.php \ lib/Transport/TPhpStream.php \ lib/Transport/TSocket.php \ lib/Transport/TSocketPool.php \ lib/Transport/TTransport.php phptypedir = $(phpdir)/Type phptype_DATA = \ lib/Type/TMessageType.php \ lib/Type/TType.php \ lib/Type/TConstant.php clean-local: if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) clean; fi EXTRA_DIST = \ lib \ src/autoload.php \ src/ext/thrift_protocol/config.m4 \ src/ext/thrift_protocol/config.w32 \ src/ext/thrift_protocol/php_thrift_protocol.cpp \ src/ext/thrift_protocol/php_thrift_protocol.h \ src/ext/thrift_protocol/php_thrift_protocol.stub.php \ src/ext/thrift_protocol/php_thrift_protocol_arginfo.h \ src/Thrift.php \ src/TStringUtils.php \ coding_standards.md \ thrift_protocol.ini \ README.apache.md \ README.md \ test/Fixtures.php \ test/TestValidators.thrift \ test/JsonSerialize/JsonSerializeTest.php \ test/Protocol/BinarySerializerTest.php \ test/Protocol/TJSONProtocolFixtures.php \ test/Protocol/TJSONProtocolTest.php \ test/Protocol/TSimpleJSONProtocolFixtures.php \ test/Protocol/TSimpleJSONProtocolTest.php \ test/Validator/BaseValidatorTest.php \ test/Validator/ValidatorTest.php \ test/Validator/ValidatorTestOop.php MAINTAINERCLEANFILES = \ Makefile.in thrift-0.19.0/lib/php/src/0000755000000000000000000000000014472652661015240 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/src/ext/0000755000000000000000000000000014472652661016040 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/src/ext/thrift_protocol/0000755000000000000000000000000014472652661021261 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/src/ext/thrift_protocol/config.m40000644000000000000000000000270514303740367022766 0ustar00rootroot00000000000000dnl Copyright (C) 2009 Facebook dnl Copying and distribution of this file, with or without modification, dnl are permitted in any medium without royalty provided the copyright dnl notice and this notice are preserved. dnl dnl Licensed to the Apache Software Foundation (ASF) under one dnl or more contributor license agreements. See the NOTICE file dnl distributed with this work for additional information dnl regarding copyright ownership. The ASF licenses this file dnl to you under the Apache License, Version 2.0 (the dnl "License"); you may not use this file except in compliance dnl with the License. You may obtain a copy of the License at dnl dnl http://www.apache.org/licenses/LICENSE-2.0 dnl dnl Unless required by applicable law or agreed to in writing, dnl software distributed under the License is distributed on an dnl "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY dnl KIND, either express or implied. See the License for the dnl specific language governing permissions and limitations dnl under the License. PHP_ARG_ENABLE(thrift_protocol, whether to enable the thrift_protocol extension, [ --enable-thrift_protocol Enable the thrift_protocol extension]) if test "$PHP_THRIFT_PROTOCOL" != "no"; then PHP_REQUIRE_CXX() PHP_ADD_LIBRARY_WITH_PATH(stdc++, "", THRIFT_PROTOCOL_SHARED_LIBADD) PHP_SUBST(THRIFT_PROTOCOL_SHARED_LIBADD) CXXFLAGS="$CXXFLAGS -std=c++11" PHP_NEW_EXTENSION(thrift_protocol, php_thrift_protocol.cpp, $ext_shared) fi thrift-0.19.0/lib/php/src/ext/thrift_protocol/php_thrift_protocol_arginfo.h0000644000000000000000000000266114303740367027226 0ustar00rootroot00000000000000/* This is a generated file, edit the .stub.php file instead. * Stub hash: 3bd6e0bc99143d614ddb80ee0aec192e385c8927 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_thrift_protocol_write_binary, 0, 6, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, protocol, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, method_name, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, msgtype, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, request_struct, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, seqID, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, strict_write, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_thrift_protocol_read_binary, 0, 3, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, protocol, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, obj_typename, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, strict_read, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, buffer_size, IS_LONG, 0, "8192") ZEND_END_ARG_INFO() #define arginfo_thrift_protocol_read_binary_after_message_begin arginfo_thrift_protocol_read_binary ZEND_FUNCTION(thrift_protocol_write_binary); ZEND_FUNCTION(thrift_protocol_read_binary); ZEND_FUNCTION(thrift_protocol_read_binary_after_message_begin); static const zend_function_entry ext_functions[] = { ZEND_FE(thrift_protocol_write_binary, arginfo_thrift_protocol_write_binary) ZEND_FE(thrift_protocol_read_binary, arginfo_thrift_protocol_read_binary) ZEND_FE(thrift_protocol_read_binary_after_message_begin, arginfo_thrift_protocol_read_binary_after_message_begin) ZEND_FE_END }; thrift-0.19.0/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp0000644000000000000000000010457014303740367026056 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "zend_interfaces.h" #include "zend_exceptions.h" #include "php_thrift_protocol.h" #if PHP_VERSION_ID >= 70000 #include #include #include #include #include #ifndef bswap_64 #define bswap_64(x) (((uint64_t)(x) << 56) | \ (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \ (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \ (((uint64_t)(x) << 8) & 0xff00000000ULL) | \ (((uint64_t)(x) >> 8) & 0xff000000ULL) | \ (((uint64_t)(x) >> 24) & 0xff0000ULL) | \ (((uint64_t)(x) >> 40) & 0xff00ULL) | \ ((uint64_t)(x) >> 56)) #endif #if __BYTE_ORDER == __LITTLE_ENDIAN #define htonll(x) bswap_64(x) #define ntohll(x) bswap_64(x) #elif __BYTE_ORDER == __BIG_ENDIAN #define htonll(x) x #define ntohll(x) x #else #error Unknown __BYTE_ORDER #endif enum TType { T_STOP = 0, T_VOID = 1, T_BOOL = 2, T_BYTE = 3, T_I08 = 3, T_I16 = 6, T_I32 = 8, T_U64 = 9, T_I64 = 10, T_DOUBLE = 4, T_STRING = 11, T_UTF7 = 11, T_STRUCT = 12, T_MAP = 13, T_SET = 14, T_LIST = 15, T_UTF8 = 16, T_UTF16 = 17 }; const int32_t VERSION_MASK = 0xffff0000; const int32_t VERSION_1 = 0x80010000; const int8_t T_CALL = 1; const int8_t T_REPLY = 2; const int8_t T_EXCEPTION = 3; // tprotocolexception const int INVALID_DATA = 1; const int BAD_VERSION = 4; zend_module_entry thrift_protocol_module_entry = { STANDARD_MODULE_HEADER, "thrift_protocol", ext_functions, nullptr, nullptr, nullptr, nullptr, nullptr, "1.0", STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_THRIFT_PROTOCOL ZEND_GET_MODULE(thrift_protocol) #endif class PHPExceptionWrapper : public std::exception { public: PHPExceptionWrapper(zval* _ex) throw() { ZVAL_COPY(&ex, _ex); snprintf(_what, 40, "PHP exception zval=%p", _ex); } PHPExceptionWrapper(zend_object* _exobj) throw() { ZVAL_OBJ(&ex, _exobj); snprintf(_what, 40, "PHP exception zval=%p", _exobj); } ~PHPExceptionWrapper() throw() { zval_dtor(&ex); } const char* what() const throw() { return _what; } operator zval*() const throw() { return const_cast(&ex); } // Zend API doesn't do 'const'... protected: zval ex; char _what[40]; } ; class PHPTransport { protected: PHPTransport(zval* _p, size_t _buffer_size) { assert(Z_TYPE_P(_p) == IS_OBJECT); ZVAL_UNDEF(&t); buffer = reinterpret_cast(emalloc(_buffer_size)); buffer_ptr = buffer; buffer_used = 0; buffer_size = _buffer_size; // Get the transport for the passed protocol zval gettransport; ZVAL_STRING(&gettransport, "getTransport"); call_user_function(nullptr, _p, &gettransport, &t, 0, nullptr); zval_dtor(&gettransport); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } assert(Z_TYPE(t) == IS_OBJECT); } ~PHPTransport() { efree(buffer); zval_dtor(&t); } char* buffer; char* buffer_ptr; size_t buffer_used; size_t buffer_size; zval t; }; class PHPOutputTransport : public PHPTransport { public: PHPOutputTransport(zval* _p, size_t _buffer_size = 8192) : PHPTransport(_p, _buffer_size) { } ~PHPOutputTransport() { } void write(const char* data, size_t len) { if ((len + buffer_used) > buffer_size) { internalFlush(); } if (len > buffer_size) { directWrite(data, len); } else { memcpy(buffer_ptr, data, len); buffer_used += len; buffer_ptr += len; } } void writeI64(int64_t i) { i = htonll(i); write((const char*)&i, 8); } void writeU32(uint32_t i) { i = htonl(i); write((const char*)&i, 4); } void writeI32(int32_t i) { i = htonl(i); write((const char*)&i, 4); } void writeI16(int16_t i) { i = htons(i); write((const char*)&i, 2); } void writeI8(int8_t i) { write((const char*)&i, 1); } void writeString(const char* str, size_t len) { writeU32(len); write(str, len); } void flush() { internalFlush(); directFlush(); } protected: void internalFlush() { if (buffer_used) { directWrite(buffer, buffer_used); buffer_ptr = buffer; buffer_used = 0; } } void directFlush() { zval ret, flushfn; ZVAL_NULL(&ret); ZVAL_STRING(&flushfn, "flush"); call_user_function(EG(function_table), &(this->t), &flushfn, &ret, 0, nullptr); zval_dtor(&flushfn); zval_dtor(&ret); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } } void directWrite(const char* data, size_t len) { zval args[1], ret, writefn; ZVAL_STRING(&writefn, "write"); ZVAL_STRINGL(&args[0], data, len); ZVAL_NULL(&ret); call_user_function(EG(function_table), &(this->t), &writefn, &ret, 1, args); zval_dtor(&writefn); zval_dtor(&ret); zval_dtor(&args[0]); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } } }; class PHPInputTransport : public PHPTransport { public: PHPInputTransport(zval* _p, size_t _buffer_size = 8192) : PHPTransport(_p, _buffer_size) { } ~PHPInputTransport() { put_back(); } void put_back() { if (buffer_used) { zval args[1], ret, putbackfn; ZVAL_STRINGL(&args[0], buffer_ptr, buffer_used); ZVAL_STRING(&putbackfn, "putBack"); ZVAL_NULL(&ret); call_user_function(EG(function_table), &(this->t), &putbackfn, &ret, 1, args); zval_dtor(&putbackfn); zval_dtor(&ret); zval_dtor(&args[0]); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } } buffer_used = 0; buffer_ptr = buffer; } void skip(size_t len) { while (len) { size_t chunk_size = (std::min)(len, buffer_used); if (chunk_size) { buffer_ptr = reinterpret_cast(buffer_ptr) + chunk_size; buffer_used -= chunk_size; len -= chunk_size; } if (! len) break; refill(); } } void readBytes(void* buf, size_t len) { while (len) { size_t chunk_size = (std::min)(len, buffer_used); if (chunk_size) { memcpy(buf, buffer_ptr, chunk_size); buffer_ptr = reinterpret_cast(buffer_ptr) + chunk_size; buffer_used -= chunk_size; buf = reinterpret_cast(buf) + chunk_size; len -= chunk_size; } if (! len) break; refill(); } } int8_t readI8() { int8_t c; readBytes(&c, 1); return c; } int16_t readI16() { int16_t c; readBytes(&c, 2); return (int16_t)ntohs(c); } uint32_t readU32() { uint32_t c; readBytes(&c, 4); return (uint32_t)ntohl(c); } int32_t readI32() { int32_t c; readBytes(&c, 4); return (int32_t)ntohl(c); } protected: void refill() { assert(buffer_used == 0); zval retval; zval args[1]; zval funcname; ZVAL_NULL(&retval); ZVAL_LONG(&args[0], buffer_size); ZVAL_STRING(&funcname, "read"); call_user_function(EG(function_table), &(this->t), &funcname, &retval, 1, args); zval_dtor(&args[0]); zval_dtor(&funcname); if (EG(exception)) { zval_dtor(&retval); zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } buffer_used = Z_STRLEN(retval); memcpy(buffer, Z_STRVAL(retval), buffer_used); zval_dtor(&retval); buffer_ptr = buffer; } }; static void binary_deserialize_spec(zval* zthis, PHPInputTransport& transport, HashTable* spec); static void binary_serialize_spec(zval* zthis, PHPOutputTransport& transport, HashTable* spec); static void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* value, HashTable* fieldspec); static inline bool ttype_is_scalar(int8_t t); // Create a PHP object given a typename and call the ctor, optionally passing up to 2 arguments static void createObject(const char* obj_typename, zval* return_value, int nargs = 0, zval* arg1 = nullptr, zval* arg2 = nullptr) { /* is there a better way to do that on the stack ? */ zend_string *obj_name = zend_string_init(obj_typename, strlen(obj_typename), 0); zend_class_entry* ce = zend_fetch_class(obj_name, ZEND_FETCH_CLASS_DEFAULT); zend_string_release(obj_name); if (! ce) { php_error_docref(nullptr, E_ERROR, "Class %s does not exist", obj_typename); RETURN_NULL(); } object_and_properties_init(return_value, ce, nullptr); zend_function* constructor = zend_std_get_constructor(Z_OBJ_P(return_value)); zval ctor_rv; zend_call_method(Z4_OBJ_P(return_value), ce, &constructor, nullptr, 0, &ctor_rv, nargs, arg1, arg2); zval_dtor(&ctor_rv); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } } static void throw_tprotocolexception(const char* what, long errorcode) { zval zwhat, zerrorcode; ZVAL_STRING(&zwhat, what); ZVAL_LONG(&zerrorcode, errorcode); zval ex; createObject("\\Thrift\\Exception\\TProtocolException", &ex, 2, &zwhat, &zerrorcode); zval_dtor(&zwhat); zval_dtor(&zerrorcode); throw PHPExceptionWrapper(&ex); } // Sets EG(exception), call this and then RETURN_NULL(); static void throw_zend_exception_from_std_exception(const std::exception& ex) { zend_throw_exception(zend_exception_get_default(), const_cast(ex.what()), 0); } static void skip_element(long thrift_typeID, PHPInputTransport& transport) { switch (thrift_typeID) { case T_STOP: case T_VOID: return; case T_STRUCT: while (true) { int8_t ttype = transport.readI8(); // get field type if (ttype == T_STOP) break; transport.skip(2); // skip field number, I16 skip_element(ttype, transport); // skip field payload } return; case T_BOOL: case T_BYTE: transport.skip(1); return; case T_I16: transport.skip(2); return; case T_I32: transport.skip(4); return; case T_U64: case T_I64: case T_DOUBLE: transport.skip(8); return; //case T_UTF7: // aliases T_STRING case T_UTF8: case T_UTF16: case T_STRING: { uint32_t len = transport.readU32(); transport.skip(len); } return; case T_MAP: { int8_t keytype = transport.readI8(); int8_t valtype = transport.readI8(); uint32_t size = transport.readU32(); for (uint32_t i = 0; i < size; ++i) { skip_element(keytype, transport); skip_element(valtype, transport); } } return; case T_LIST: case T_SET: { int8_t valtype = transport.readI8(); uint32_t size = transport.readU32(); for (uint32_t i = 0; i < size; ++i) { skip_element(valtype, transport); } } return; }; char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %ld", thrift_typeID); throw_tprotocolexception(errbuf, INVALID_DATA); } static inline bool zval_is_bool(zval* v) { return Z_TYPE_P(v) == IS_TRUE || Z_TYPE_P(v) == IS_FALSE; } static void binary_deserialize(int8_t thrift_typeID, PHPInputTransport& transport, zval* return_value, HashTable* fieldspec) { ZVAL_NULL(return_value); switch (thrift_typeID) { case T_STOP: case T_VOID: RETURN_NULL(); return; case T_STRUCT: { zval* val_ptr = zend_hash_str_find(fieldspec, "class", sizeof("class")-1); if (val_ptr == nullptr) { throw_tprotocolexception("no class type in spec", INVALID_DATA); skip_element(T_STRUCT, transport); RETURN_NULL(); } char* structType = Z_STRVAL_P(val_ptr); // Create an object in PHP userland based on our spec createObject(structType, return_value); if (Z_TYPE_P(return_value) == IS_NULL) { // unable to create class entry skip_element(T_STRUCT, transport); RETURN_NULL(); } zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, false); ZVAL_DEREF(spec); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } if (Z_TYPE_P(spec) != IS_ARRAY) { char errbuf[128]; snprintf(errbuf, 128, "spec for %s is wrong type: %d\n", structType, Z_TYPE_P(spec)); throw_tprotocolexception(errbuf, INVALID_DATA); RETURN_NULL(); } binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec)); return; } break; case T_BOOL: { uint8_t c; transport.readBytes(&c, 1); RETURN_BOOL(c != 0); } //case T_I08: // same numeric value as T_BYTE case T_BYTE: { uint8_t c; transport.readBytes(&c, 1); RETURN_LONG((int8_t)c); } case T_I16: { uint16_t c; transport.readBytes(&c, 2); RETURN_LONG((int16_t)ntohs(c)); } case T_I32: { uint32_t c; transport.readBytes(&c, 4); RETURN_LONG((int32_t)ntohl(c)); } case T_U64: case T_I64: { uint64_t c; transport.readBytes(&c, 8); RETURN_LONG((int64_t)ntohll(c)); } case T_DOUBLE: { union { uint64_t c; double d; } a; transport.readBytes(&(a.c), 8); a.c = ntohll(a.c); RETURN_DOUBLE(a.d); } //case T_UTF7: // aliases T_STRING case T_UTF8: case T_UTF16: case T_STRING: { uint32_t size = transport.readU32(); if (size) { char strbuf[size+1]; transport.readBytes(strbuf, size); strbuf[size] = '\0'; ZVAL_STRINGL(return_value, strbuf, size); } else { ZVAL_EMPTY_STRING(return_value); } return; } case T_MAP: { // array of key -> value uint8_t types[2]; transport.readBytes(types, 2); uint32_t size = transport.readU32(); array_init(return_value); zval *val_ptr; val_ptr = zend_hash_str_find(fieldspec, "key", sizeof("key")-1); HashTable* keyspec = Z_ARRVAL_P(val_ptr); val_ptr = zend_hash_str_find(fieldspec, "val", sizeof("val")-1); HashTable* valspec = Z_ARRVAL_P(val_ptr); for (uint32_t s = 0; s < size; ++s) { zval key, value; binary_deserialize(types[0], transport, &key, keyspec); binary_deserialize(types[1], transport, &value, valspec); if (Z_TYPE(key) == IS_LONG) { zend_hash_index_update(Z_ARR_P(return_value), Z_LVAL(key), &value); } else { if (Z_TYPE(key) != IS_STRING) convert_to_string(&key); zend_symtable_update(Z_ARR_P(return_value), Z_STR(key), &value); } zval_dtor(&key); } return; // return_value already populated } case T_LIST: { // array with autogenerated numeric keys int8_t type = transport.readI8(); uint32_t size = transport.readU32(); zval *val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1); HashTable* elemspec = Z_ARRVAL_P(val_ptr); array_init(return_value); for (uint32_t s = 0; s < size; ++s) { zval value; binary_deserialize(type, transport, &value, elemspec); zend_hash_next_index_insert(Z_ARR_P(return_value), &value); } return; } case T_SET: { // array of key -> TRUE uint8_t type; uint32_t size; transport.readBytes(&type, 1); transport.readBytes(&size, 4); size = ntohl(size); zval *val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1); HashTable* elemspec = Z_ARRVAL_P(val_ptr); array_init(return_value); for (uint32_t s = 0; s < size; ++s) { zval key, value; ZVAL_TRUE(&value); binary_deserialize(type, transport, &key, elemspec); if (Z_TYPE(key) == IS_LONG) { zend_hash_index_update(Z_ARR_P(return_value), Z_LVAL(key), &value); } else { if (Z_TYPE(key) != IS_STRING) convert_to_string(&key); zend_symtable_update(Z_ARR_P(return_value), Z_STR(key), &value); } zval_dtor(&key); } return; } }; char errbuf[128]; sprintf(errbuf, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(errbuf, INVALID_DATA); } static void binary_serialize_hashtable_key(int8_t keytype, PHPOutputTransport& transport, HashTable* ht, HashPosition& ht_pos, HashTable* spec) { bool keytype_is_numeric = (!((keytype == T_STRING) || (keytype == T_UTF8) || (keytype == T_UTF16))); zend_string* key; uint key_len; long index = 0; zval z; int res = zend_hash_get_current_key_ex(ht, &key, (zend_ulong*)&index, &ht_pos); if (res == HASH_KEY_IS_STRING) { ZVAL_STR_COPY(&z, key); } else { ZVAL_LONG(&z, index); } binary_serialize(keytype, transport, &z, spec); zval_dtor(&z); } static void binary_serialize(int8_t thrift_typeID, PHPOutputTransport& transport, zval* value, HashTable* fieldspec) { if (value) { ZVAL_DEREF(value); } // At this point the typeID (and field num, if applicable) should've already been written to the output so all we need to do is write the payload. switch (thrift_typeID) { case T_STOP: case T_VOID: return; case T_STRUCT: { if (Z_TYPE_P(value) != IS_OBJECT) { throw_tprotocolexception("Attempt to send non-object type as a T_STRUCT", INVALID_DATA); } zval* spec = zend_read_static_property(Z_OBJCE_P(value), "_TSPEC", sizeof("_TSPEC")-1, true); if (spec && Z_TYPE_P(spec) == IS_REFERENCE) { ZVAL_DEREF(spec); } if (!spec || Z_TYPE_P(spec) != IS_ARRAY) { throw_tprotocolexception("Attempt to send non-Thrift object as a T_STRUCT", INVALID_DATA); } binary_serialize_spec(value, transport, Z_ARRVAL_P(spec)); } return; case T_BOOL: if (!zval_is_bool(value)) convert_to_boolean(value); transport.writeI8(Z_TYPE_INFO_P(value) == IS_TRUE ? 1 : 0); return; case T_BYTE: if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value); transport.writeI8(Z_LVAL_P(value)); return; case T_I16: if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value); transport.writeI16(Z_LVAL_P(value)); return; case T_I32: if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value); transport.writeI32(Z_LVAL_P(value)); return; case T_I64: case T_U64: { int64_t l_data; #if defined(_LP64) || defined(_WIN64) if (Z_TYPE_P(value) != IS_LONG) convert_to_long(value); l_data = Z_LVAL_P(value); #else if (Z_TYPE_P(value) != IS_DOUBLE) convert_to_double(value); l_data = (int64_t)Z_DVAL_P(value); #endif transport.writeI64(l_data); } return; case T_DOUBLE: { union { int64_t c; double d; } a; if (Z_TYPE_P(value) != IS_DOUBLE) convert_to_double(value); a.d = Z_DVAL_P(value); transport.writeI64(a.c); } return; case T_UTF8: case T_UTF16: case T_STRING: if (Z_TYPE_P(value) != IS_STRING) convert_to_string(value); transport.writeString(Z_STRVAL_P(value), Z_STRLEN_P(value)); return; case T_MAP: { if (Z_TYPE_P(value) != IS_ARRAY) convert_to_array(value); if (Z_TYPE_P(value) != IS_ARRAY) { throw_tprotocolexception("Attempt to send an incompatible type as an array (T_MAP)", INVALID_DATA); } HashTable* ht = Z_ARRVAL_P(value); zval* val_ptr; val_ptr = zend_hash_str_find(fieldspec, "ktype", sizeof("ktype")-1); if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr); uint8_t keytype = Z_LVAL_P(val_ptr); transport.writeI8(keytype); val_ptr = zend_hash_str_find(fieldspec, "vtype", sizeof("vtype")-1); if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr); uint8_t valtype = Z_LVAL_P(val_ptr); transport.writeI8(valtype); val_ptr = zend_hash_str_find(fieldspec, "val", sizeof("val")-1); HashTable* valspec = Z_ARRVAL_P(val_ptr); HashTable* keyspec = Z_ARRVAL_P(zend_hash_str_find(fieldspec, "key", sizeof("key")-1)); transport.writeI32(zend_hash_num_elements(ht)); HashPosition key_ptr; for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); (val_ptr = zend_hash_get_current_data_ex(ht, &key_ptr)) != nullptr; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize_hashtable_key(keytype, transport, ht, key_ptr, keyspec); binary_serialize(valtype, transport, val_ptr, valspec); } } return; case T_LIST: { if (Z_TYPE_P(value) != IS_ARRAY) convert_to_array(value); if (Z_TYPE_P(value) != IS_ARRAY) { throw_tprotocolexception("Attempt to send an incompatible type as an array (T_LIST)", INVALID_DATA); } HashTable* ht = Z_ARRVAL_P(value); zval* val_ptr; val_ptr = zend_hash_str_find(fieldspec, "etype", sizeof("etype")-1); if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr); uint8_t valtype = Z_LVAL_P(val_ptr); transport.writeI8(valtype); val_ptr = zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1); HashTable* valspec = Z_ARRVAL_P(val_ptr); transport.writeI32(zend_hash_num_elements(ht)); HashPosition key_ptr; for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); (val_ptr = zend_hash_get_current_data_ex(ht, &key_ptr)) != nullptr; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize(valtype, transport, val_ptr, valspec); } } return; case T_SET: { if (Z_TYPE_P(value) != IS_ARRAY) convert_to_array(value); if (Z_TYPE_P(value) != IS_ARRAY) { throw_tprotocolexception("Attempt to send an incompatible type as an array (T_SET)", INVALID_DATA); } HashTable* ht = Z_ARRVAL_P(value); zval* val_ptr; val_ptr = zend_hash_str_find(fieldspec, "etype", sizeof("etype")-1); HashTable* spec = Z_ARRVAL_P(zend_hash_str_find(fieldspec, "elem", sizeof("elem")-1)); if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr); uint8_t keytype = Z_LVAL_P(val_ptr); transport.writeI8(keytype); transport.writeI32(zend_hash_num_elements(ht)); HashPosition key_ptr; if(ttype_is_scalar(keytype)){ for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); (val_ptr = zend_hash_get_current_data_ex(ht, &key_ptr)) != nullptr; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize_hashtable_key(keytype, transport, ht, key_ptr, spec); } } else { for (zend_hash_internal_pointer_reset_ex(ht, &key_ptr); (val_ptr = zend_hash_get_current_data_ex(ht, &key_ptr)) != nullptr; zend_hash_move_forward_ex(ht, &key_ptr)) { binary_serialize(keytype, transport, val_ptr, spec); } } } return; }; char errbuf[128]; snprintf(errbuf, 128, "Unknown thrift typeID %d", thrift_typeID); throw_tprotocolexception(errbuf, INVALID_DATA); } static void protocol_writeMessageBegin(zval* transport, zend_string* method_name, int32_t msgtype, int32_t seqID) { zval args[3]; zval ret; zval writeMessagefn; ZVAL_STR_COPY(&args[0], method_name); ZVAL_LONG(&args[1], msgtype); ZVAL_LONG(&args[2], seqID); ZVAL_NULL(&ret); ZVAL_STRING(&writeMessagefn, "writeMessageBegin"); call_user_function(EG(function_table), transport, &writeMessagefn, &ret, 3, args); zval_dtor(&writeMessagefn); zval_dtor(&args[2]); zval_dtor(&args[1]); zval_dtor(&args[0]); zval_dtor(&ret); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } } static inline bool ttype_is_int(int8_t t) { return ((t == T_BYTE) || ((t >= T_I16) && (t <= T_I64))); } static inline bool ttype_is_scalar(int8_t t) { return !((t == T_STRUCT) || ( t== T_MAP) || (t == T_SET) || (t == T_LIST)); } static inline bool ttypes_are_compatible(int8_t t1, int8_t t2) { // Integer types of different widths are considered compatible; // otherwise the typeID must match. return ((t1 == t2) || (ttype_is_int(t1) && ttype_is_int(t2))); } //is used to validate objects before serialization and after deserialization. For now, only required fields are validated. static void validate_thrift_object(zval* object) { zend_class_entry* object_class_entry = Z_OBJCE_P(object); zval* is_validate = zend_read_static_property(object_class_entry, "isValidate", sizeof("isValidate")-1, true); if (is_validate) { ZVAL_DEREF(is_validate); } zval* spec = zend_read_static_property(object_class_entry, "_TSPEC", sizeof("_TSPEC")-1, true); if (spec) { ZVAL_DEREF(spec); } HashPosition key_ptr; zval* val_ptr; if (is_validate && Z_TYPE_INFO_P(is_validate) == IS_TRUE) { for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(spec), &key_ptr); (val_ptr = zend_hash_get_current_data_ex(Z_ARRVAL_P(spec), &key_ptr)) != nullptr; zend_hash_move_forward_ex(Z_ARRVAL_P(spec), &key_ptr)) { zend_ulong fieldno; if (zend_hash_get_current_key_ex(Z_ARRVAL_P(spec), nullptr, &fieldno, &key_ptr) != HASH_KEY_IS_LONG) { throw_tprotocolexception("Bad keytype in TSPEC (expected 'long')", INVALID_DATA); return; } HashTable* fieldspec = Z_ARRVAL_P(val_ptr); // field name zval* zvarname = zend_hash_str_find(fieldspec, "var", sizeof("var")-1); char* varname = Z_STRVAL_P(zvarname); zval* is_required = zend_hash_str_find(fieldspec, "isRequired", sizeof("isRequired")-1); zval rv; zval* prop = zend_read_property(object_class_entry, Z4_OBJ_P(object), varname, strlen(varname), false, &rv); if (Z_TYPE_INFO_P(is_required) == IS_TRUE && Z_TYPE_P(prop) == IS_NULL) { char errbuf[128]; snprintf(errbuf, 128, "Required field %s.%s is unset!", ZSTR_VAL(object_class_entry->name), varname); throw_tprotocolexception(errbuf, INVALID_DATA); } } } } static void binary_deserialize_spec(zval* zthis, PHPInputTransport& transport, HashTable* spec) { // SET and LIST have 'elem' => array('type', [optional] 'class') // MAP has 'val' => array('type', [optiona] 'class') zend_class_entry* ce = Z_OBJCE_P(zthis); while (true) { int8_t ttype = transport.readI8(); if (ttype == T_STOP) { validate_thrift_object(zthis); return; } int16_t fieldno = transport.readI16(); zval* val_ptr = zend_hash_index_find(spec, fieldno); if (val_ptr != nullptr) { HashTable* fieldspec = Z_ARRVAL_P(val_ptr); // pull the field name val_ptr = zend_hash_str_find(fieldspec, "var", sizeof("var")-1); char* varname = Z_STRVAL_P(val_ptr); // and the type val_ptr = zend_hash_str_find(fieldspec, "type", sizeof("type")-1); if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr); int8_t expected_ttype = Z_LVAL_P(val_ptr); if (ttypes_are_compatible(ttype, expected_ttype)) { zval rv; ZVAL_UNDEF(&rv); binary_deserialize(ttype, transport, &rv, fieldspec); zend_update_property(ce, Z4_OBJ_P(zthis), varname, strlen(varname), &rv); zval_ptr_dtor(&rv); } else { skip_element(ttype, transport); } } else { skip_element(ttype, transport); } } } static void binary_serialize_spec(zval* zthis, PHPOutputTransport& transport, HashTable* spec) { validate_thrift_object(zthis); HashPosition key_ptr; zval* val_ptr; for (zend_hash_internal_pointer_reset_ex(spec, &key_ptr); (val_ptr = zend_hash_get_current_data_ex(spec, &key_ptr)) != nullptr; zend_hash_move_forward_ex(spec, &key_ptr)) { zend_ulong fieldno; if (zend_hash_get_current_key_ex(spec, nullptr, &fieldno, &key_ptr) != HASH_KEY_IS_LONG) { throw_tprotocolexception("Bad keytype in TSPEC (expected 'long')", INVALID_DATA); return; } HashTable* fieldspec = Z_ARRVAL_P(val_ptr); // field name val_ptr = zend_hash_str_find(fieldspec, "var", sizeof("var")-1); char* varname = Z_STRVAL_P(val_ptr); // thrift type val_ptr = zend_hash_str_find(fieldspec, "type", sizeof("type")-1); if (Z_TYPE_P(val_ptr) != IS_LONG) convert_to_long(val_ptr); int8_t ttype = Z_LVAL_P(val_ptr); zval rv; zval* prop = zend_read_property(Z_OBJCE_P(zthis), Z4_OBJ_P(zthis), varname, strlen(varname), false, &rv); if (Z_TYPE_P(prop) == IS_REFERENCE){ ZVAL_DEREF(prop); } if (Z_TYPE_P(prop) != IS_NULL) { transport.writeI8(ttype); transport.writeI16(fieldno); binary_serialize(ttype, transport, prop, fieldspec); } } transport.writeI8(T_STOP); // struct end } // 6 params: $transport $method_name $ttype $request_struct $seqID $strict_write PHP_FUNCTION(thrift_protocol_write_binary) { zval *protocol; zval *request_struct; zend_string *method_name; long msgtype, seqID; zend_bool strict_write; if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "oSlolb", &protocol, &method_name, &msgtype, &request_struct, &seqID, &strict_write) == FAILURE) { return; } try { zval* spec = zend_read_static_property(Z_OBJCE_P(request_struct), "_TSPEC", sizeof("_TSPEC")-1, true); if (spec) { ZVAL_DEREF(spec); } if (!spec || Z_TYPE_P(spec) != IS_ARRAY) { throw_tprotocolexception("Attempt serialize from non-Thrift object", INVALID_DATA); } PHPOutputTransport transport(protocol); protocol_writeMessageBegin(protocol, method_name, (int32_t) msgtype, (int32_t) seqID); binary_serialize_spec(request_struct, transport, Z_ARRVAL_P(spec)); transport.flush(); } catch (const PHPExceptionWrapper& ex) { // ex will be destructed, so copy to a zval that zend_throw_exception_object can take ownership of zval myex; ZVAL_COPY(&myex, ex); zend_throw_exception_object(&myex); RETURN_NULL(); } catch (const std::exception& ex) { throw_zend_exception_from_std_exception(ex); RETURN_NULL(); } } // 4 params: $transport $response_Typename $strict_read $buffer_size PHP_FUNCTION(thrift_protocol_read_binary) { zval *protocol; zend_string *obj_typename; zend_bool strict_read; size_t buffer_size = 8192; if (zend_parse_parameters(ZEND_NUM_ARGS(), "oSb|l", &protocol, &obj_typename, &strict_read, &buffer_size) == FAILURE) { return; } try { PHPInputTransport transport(protocol, buffer_size); int8_t messageType = 0; int32_t sz = transport.readI32(); if (sz < 0) { // Check for correct version number int32_t version = sz & VERSION_MASK; if (version != VERSION_1) { throw_tprotocolexception("Bad version identifier", BAD_VERSION); } messageType = (sz & 0x000000ff); int32_t namelen = transport.readI32(); // skip the name string and the sequence ID, we don't care about those transport.skip(namelen + 4); } else { if (strict_read) { throw_tprotocolexception("No version identifier... old protocol client in strict mode?", BAD_VERSION); } else { // Handle pre-versioned input transport.skip(sz); // skip string body messageType = transport.readI8(); transport.skip(4); // skip sequence number } } if (messageType == T_EXCEPTION) { zval ex; createObject("\\Thrift\\Exception\\TApplicationException", &ex); zval* spec = zend_read_static_property(Z_OBJCE(ex), "_TSPEC", sizeof("_TPSEC")-1, false); ZVAL_DEREF(spec); if (EG(exception)) { zend_object *ex = EG(exception); EG(exception) = nullptr; throw PHPExceptionWrapper(ex); } binary_deserialize_spec(&ex, transport, Z_ARRVAL_P(spec)); throw PHPExceptionWrapper(&ex); } createObject(ZSTR_VAL(obj_typename), return_value); zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, true); if (spec) { ZVAL_DEREF(spec); } if (!spec || Z_TYPE_P(spec) != IS_ARRAY) { throw_tprotocolexception("Attempt deserialize to non-Thrift object", INVALID_DATA); } binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec)); } catch (const PHPExceptionWrapper& ex) { // ex will be destructed, so copy to a zval that zend_throw_exception_object can ownership of zval myex; ZVAL_COPY(&myex, ex); zval_dtor(return_value); zend_throw_exception_object(&myex); RETURN_NULL(); } catch (const std::exception& ex) { throw_zend_exception_from_std_exception(ex); RETURN_NULL(); } } // 4 params: $transport $response_Typename $strict_read $buffer_size PHP_FUNCTION(thrift_protocol_read_binary_after_message_begin) { zval *protocol; zend_string *obj_typename; zend_bool strict_read; size_t buffer_size = 8192; if (zend_parse_parameters(ZEND_NUM_ARGS(), "oSb|l", &protocol, &obj_typename, &strict_read, &buffer_size) == FAILURE) { return; } try { PHPInputTransport transport(protocol, buffer_size); createObject(ZSTR_VAL(obj_typename), return_value); zval* spec = zend_read_static_property(Z_OBJCE_P(return_value), "_TSPEC", sizeof("_TSPEC")-1, false); ZVAL_DEREF(spec); binary_deserialize_spec(return_value, transport, Z_ARRVAL_P(spec)); } catch (const PHPExceptionWrapper& ex) { // ex will be destructed, so copy to a zval that zend_throw_exception_object can take ownership of zval myex; ZVAL_COPY(&myex, ex); zend_throw_exception_object(&myex); RETURN_NULL(); } catch (const std::exception& ex) { throw_zend_exception_from_std_exception(ex); RETURN_NULL(); } } #endif /* PHP_VERSION_ID >= 70000 */ thrift-0.19.0/lib/php/src/ext/thrift_protocol/php_thrift_protocol.h0000644000000000000000000000543714303740367025525 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #pragma once /* backward compat macros */ #if PHP_VERSION_ID >= 80000 # define Z4_OBJ_P(zval) (Z_OBJ_P(zval)) #else # define Z4_OBJ_P(zval) (zval) #endif #ifndef IS_MIXED # define IS_MIXED 0 #endif #ifndef ZEND_PARSE_PARAMETERS_NONE #define ZEND_PARSE_PARAMETERS_NONE() \ ZEND_PARSE_PARAMETERS_START(0, 0) \ ZEND_PARSE_PARAMETERS_END() #endif #ifndef ZEND_ARG_INFO_WITH_DEFAULT_VALUE #define ZEND_ARG_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, default_value) \ ZEND_ARG_INFO(pass_by_ref, name) #endif #if PHP_VERSION_ID < 70200 #undef ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX #define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ static const zend_internal_arg_info name[] = { \ { (const char*)(zend_uintptr_t)(required_num_args), ( #class_name ), 0, return_reference, allow_null, 0 }, #endif #ifndef ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX # define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) \ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(name, return_reference, required_num_args, class_name, allow_null) #endif #ifndef ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX # define ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(name, return_reference, num_args, type) \ ZEND_BEGIN_ARG_INFO_EX(name, 0, return_reference, num_args) #endif #ifndef ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX # define ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(name, return_reference, required_num_args, class_name, type) \ ZEND_BEGIN_ARG_INFO_EX(name, 0, return_reference, required_num_args) #endif #ifndef ZEND_ARG_TYPE_MASK # define ZEND_ARG_TYPE_MASK(pass_by_ref, name, type_mask, default_value) \ ZEND_ARG_TYPE_INFO(pass_by_ref, name, 0, 0) #endif #ifndef ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE # define ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(pass_by_ref, name, type_hint, allow_null, default_value) \ ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) #endif #include "php_thrift_protocol_arginfo.h" thrift-0.19.0/lib/php/src/ext/thrift_protocol/config.w320000644000000000000000000000041014303740367023050 0ustar00rootroot00000000000000// $Id: config.w32 250404 2008-01-11 13:37:24Z rrichards $ // vim:ft=javascript ARG_WITH("thrift_protocol", "whether to enable the thrift_protocol extension", "yes"); if (PHP_THRIFT_PROTOCOL == "yes"){ EXTENSION("thrift_protocol", "php_thrift_protocol.cpp") } thrift-0.19.0/lib/php/src/ext/thrift_protocol/php_thrift_protocol.stub.php0000644000000000000000000000111014303740367027021 0ustar00rootroot00000000000000strlen($str) - $start; } return mb_substr($str, $start, $length, '8bit'); } public function strlen($str) { return mb_strlen($str, '8bit'); } } class TStringFuncFactory { private static $_instance; /** * Get the Singleton instance of TStringFunc implementation that is * compatible with the current system's mbstring.func_overload settings. * * @return TStringFunc */ public static function create() { if (!self::$_instance) { self::_setInstance(); } return self::$_instance; } private static function _setInstance() { /** * Cannot use str* functions for byte counting because multibyte * characters will be read a single bytes. * * See: http://us.php.net/manual/en/mbstring.overload.php */ if (ini_get('mbstring.func_overload') & 2) { self::$_instance = new TStringFunc_Mbstring(); } /** * mbstring is not installed or does not have function overloading * of the str* functions enabled so use PHP core str* functions for * byte counting. */ else { self::$_instance = new TStringFunc_Core(); } } } thrift-0.19.0/lib/php/src/Thrift.php0000644000000000000000000005503114452237057017211 0ustar00rootroot00000000000000 $fspec) { $var = $fspec['var']; if (isset($vals[$var])) { $this->$var = $vals[$var]; } } } else { parent::__construct((string)$p1, $p2); } } static $tmethod = array(TType::BOOL => 'Bool', TType::BYTE => 'Byte', TType::I16 => 'I16', TType::I32 => 'I32', TType::I64 => 'I64', TType::DOUBLE => 'Double', TType::STRING => 'String'); private function _readMap(&$var, $spec, $input) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kread = $vread = null; if (isset(TBase::$tmethod[$ktype])) { $kread = 'read'.TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vread = 'read'.TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $var = array(); $_ktype = $_vtype = $size = 0; $xfer += $input->readMapBegin($_ktype, $_vtype, $size); for ($i = 0; $i < $size; ++$i) { $key = $val = null; if ($kread !== null) { $xfer += $input->$kread($key); } else { switch ($ktype) { case TType::STRUCT: $class = $kspec['class']; $key = new $class(); $xfer += $key->read($input); break; case TType::MAP: $xfer += $this->_readMap($key, $kspec, $input); break; case TType::LST: $xfer += $this->_readList($key, $kspec, $input, false); break; case TType::SET: $xfer += $this->_readList($key, $kspec, $input, true); break; } } if ($vread !== null) { $xfer += $input->$vread($val); } else { switch ($vtype) { case TType::STRUCT: $class = $vspec['class']; $val = new $class(); $xfer += $val->read($input); break; case TType::MAP: $xfer += $this->_readMap($val, $vspec, $input); break; case TType::LST: $xfer += $this->_readList($val, $vspec, $input, false); break; case TType::SET: $xfer += $this->_readList($val, $vspec, $input, true); break; } } $var[$key] = $val; } $xfer += $input->readMapEnd(); return $xfer; } private function _readList(&$var, $spec, $input, $set=false) { $xfer = 0; $etype = $spec['etype']; $eread = $vread = null; if (isset(TBase::$tmethod[$etype])) { $eread = 'read'.TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } $var = array(); $_etype = $size = 0; if ($set) { $xfer += $input->readSetBegin($_etype, $size); } else { $xfer += $input->readListBegin($_etype, $size); } for ($i = 0; $i < $size; ++$i) { $elem = null; if ($eread !== null) { $xfer += $input->$eread($elem); } else { $espec = $spec['elem']; switch ($etype) { case TType::STRUCT: $class = $espec['class']; $elem = new $class(); $xfer += $elem->read($input); break; case TType::MAP: $xfer += $this->_readMap($elem, $espec, $input); break; case TType::LST: $xfer += $this->_readList($elem, $espec, $input, false); break; case TType::SET: $xfer += $this->_readList($elem, $espec, $input, true); break; } } if ($set) { $var[$elem] = true; } else { $var []= $elem; } } if ($set) { $xfer += $input->readSetEnd(); } else { $xfer += $input->readListEnd(); } return $xfer; } protected function _read($class, $spec, $input) { $xfer = 0; $fname = null; $ftype = 0; $fid = 0; $xfer += $input->readStructBegin($fname); while (true) { $xfer += $input->readFieldBegin($fname, $ftype, $fid); if ($ftype == TType::STOP) { break; } if (isset($spec[$fid])) { $fspec = $spec[$fid]; $var = $fspec['var']; if ($ftype == $fspec['type']) { $xfer = 0; if (isset(TBase::$tmethod[$ftype])) { $func = 'read'.TBase::$tmethod[$ftype]; $xfer += $input->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $class = $fspec['class']; $this->$var = new $class(); $xfer += $this->$var->read($input); break; case TType::MAP: $xfer += $this->_readMap($this->$var, $fspec, $input); break; case TType::LST: $xfer += $this->_readList($this->$var, $fspec, $input, false); break; case TType::SET: $xfer += $this->_readList($this->$var, $fspec, $input, true); break; } } } else { $xfer += $input->skip($ftype); } } else { $xfer += $input->skip($ftype); } $xfer += $input->readFieldEnd(); } $xfer += $input->readStructEnd(); return $xfer; } private function _writeMap($var, $spec, $output) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kwrite = $vwrite = null; if (isset(TBase::$tmethod[$ktype])) { $kwrite = 'write'.TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vwrite = 'write'.TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $xfer += $output->writeMapBegin($ktype, $vtype, count($var)); foreach ($var as $key => $val) { if (isset($kwrite)) { $xfer += $output->$kwrite($key); } else { switch ($ktype) { case TType::STRUCT: $xfer += $key->write($output); break; case TType::MAP: $xfer += $this->_writeMap($key, $kspec, $output); break; case TType::LST: $xfer += $this->_writeList($key, $kspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($key, $kspec, $output, true); break; } } if (isset($vwrite)) { $xfer += $output->$vwrite($val); } else { switch ($vtype) { case TType::STRUCT: $xfer += $val->write($output); break; case TType::MAP: $xfer += $this->_writeMap($val, $vspec, $output); break; case TType::LST: $xfer += $this->_writeList($val, $vspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($val, $vspec, $output, true); break; } } } $xfer += $output->writeMapEnd(); return $xfer; } private function _writeList($var, $spec, $output, $set=false) { $xfer = 0; $etype = $spec['etype']; $ewrite = null; if (isset(TBase::$tmethod[$etype])) { $ewrite = 'write'.TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } if ($set) { $xfer += $output->writeSetBegin($etype, count($var)); } else { $xfer += $output->writeListBegin($etype, count($var)); } foreach ($var as $key => $val) { $elem = $set ? $key : $val; if (isset($ewrite)) { $xfer += $output->$ewrite($elem); } else { switch ($etype) { case TType::STRUCT: $xfer += $elem->write($output); break; case TType::MAP: $xfer += $this->_writeMap($elem, $espec, $output); break; case TType::LST: $xfer += $this->_writeList($elem, $espec, $output, false); break; case TType::SET: $xfer += $this->_writeList($elem, $espec, $output, true); break; } } } if ($set) { $xfer += $output->writeSetEnd(); } else { $xfer += $output->writeListEnd(); } return $xfer; } protected function _write($class, $spec, $output) { $xfer = 0; $xfer += $output->writeStructBegin($class); foreach ($spec as $fid => $fspec) { $var = $fspec['var']; if ($this->$var !== null) { $ftype = $fspec['type']; $xfer += $output->writeFieldBegin($var, $ftype, $fid); if (isset(TBase::$tmethod[$ftype])) { $func = 'write'.TBase::$tmethod[$ftype]; $xfer += $output->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $xfer += $this->$var->write($output); break; case TType::MAP: $xfer += $this->_writeMap($this->$var, $fspec, $output); break; case TType::LST: $xfer += $this->_writeList($this->$var, $fspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($this->$var, $fspec, $output, true); break; } } $xfer += $output->writeFieldEnd(); } } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } } /** * Base class from which other Thrift structs extend. This is so that we can * cut back on the size of the generated code which is turning out to have a * nontrivial cost just to load thanks to the wondrously abysmal implementation * of PHP. Note that code is intentionally duplicated in here to avoid making * function calls for every field or member of a container.. */ abstract class TBase { static $tmethod = array(TType::BOOL => 'Bool', TType::BYTE => 'Byte', TType::I16 => 'I16', TType::I32 => 'I32', TType::I64 => 'I64', TType::DOUBLE => 'Double', TType::STRING => 'String'); abstract public function read($input); abstract public function write($output); public function __construct($spec=null, $vals=null) { if (is_array($spec) && is_array($vals)) { foreach ($spec as $fid => $fspec) { $var = $fspec['var']; if (isset($vals[$var])) { $this->$var = $vals[$var]; } } } } private function _readMap(&$var, $spec, $input) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kread = $vread = null; if (isset(TBase::$tmethod[$ktype])) { $kread = 'read'.TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vread = 'read'.TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $var = array(); $_ktype = $_vtype = $size = 0; $xfer += $input->readMapBegin($_ktype, $_vtype, $size); for ($i = 0; $i < $size; ++$i) { $key = $val = null; if ($kread !== null) { $xfer += $input->$kread($key); } else { switch ($ktype) { case TType::STRUCT: $class = $kspec['class']; $key = new $class(); $xfer += $key->read($input); break; case TType::MAP: $xfer += $this->_readMap($key, $kspec, $input); break; case TType::LST: $xfer += $this->_readList($key, $kspec, $input, false); break; case TType::SET: $xfer += $this->_readList($key, $kspec, $input, true); break; } } if ($vread !== null) { $xfer += $input->$vread($val); } else { switch ($vtype) { case TType::STRUCT: $class = $vspec['class']; $val = new $class(); $xfer += $val->read($input); break; case TType::MAP: $xfer += $this->_readMap($val, $vspec, $input); break; case TType::LST: $xfer += $this->_readList($val, $vspec, $input, false); break; case TType::SET: $xfer += $this->_readList($val, $vspec, $input, true); break; } } $var[$key] = $val; } $xfer += $input->readMapEnd(); return $xfer; } private function _readList(&$var, $spec, $input, $set=false) { $xfer = 0; $etype = $spec['etype']; $eread = $vread = null; if (isset(TBase::$tmethod[$etype])) { $eread = 'read'.TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } $var = array(); $_etype = $size = 0; if ($set) { $xfer += $input->readSetBegin($_etype, $size); } else { $xfer += $input->readListBegin($_etype, $size); } for ($i = 0; $i < $size; ++$i) { $elem = null; if ($eread !== null) { $xfer += $input->$eread($elem); } else { $espec = $spec['elem']; switch ($etype) { case TType::STRUCT: $class = $espec['class']; $elem = new $class(); $xfer += $elem->read($input); break; case TType::MAP: $xfer += $this->_readMap($elem, $espec, $input); break; case TType::LST: $xfer += $this->_readList($elem, $espec, $input, false); break; case TType::SET: $xfer += $this->_readList($elem, $espec, $input, true); break; } } if ($set) { $var[$elem] = true; } else { $var []= $elem; } } if ($set) { $xfer += $input->readSetEnd(); } else { $xfer += $input->readListEnd(); } return $xfer; } protected function _read($class, $spec, $input) { $xfer = 0; $fname = null; $ftype = 0; $fid = 0; $xfer += $input->readStructBegin($fname); while (true) { $xfer += $input->readFieldBegin($fname, $ftype, $fid); if ($ftype == TType::STOP) { break; } if (isset($spec[$fid])) { $fspec = $spec[$fid]; $var = $fspec['var']; if ($ftype == $fspec['type']) { $xfer = 0; if (isset(TBase::$tmethod[$ftype])) { $func = 'read'.TBase::$tmethod[$ftype]; $xfer += $input->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $class = $fspec['class']; $this->$var = new $class(); $xfer += $this->$var->read($input); break; case TType::MAP: $xfer += $this->_readMap($this->$var, $fspec, $input); break; case TType::LST: $xfer += $this->_readList($this->$var, $fspec, $input, false); break; case TType::SET: $xfer += $this->_readList($this->$var, $fspec, $input, true); break; } } } else { $xfer += $input->skip($ftype); } } else { $xfer += $input->skip($ftype); } $xfer += $input->readFieldEnd(); } $xfer += $input->readStructEnd(); return $xfer; } private function _writeMap($var, $spec, $output) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kwrite = $vwrite = null; if (isset(TBase::$tmethod[$ktype])) { $kwrite = 'write'.TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vwrite = 'write'.TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $xfer += $output->writeMapBegin($ktype, $vtype, count($var)); foreach ($var as $key => $val) { if (isset($kwrite)) { $xfer += $output->$kwrite($key); } else { switch ($ktype) { case TType::STRUCT: $xfer += $key->write($output); break; case TType::MAP: $xfer += $this->_writeMap($key, $kspec, $output); break; case TType::LST: $xfer += $this->_writeList($key, $kspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($key, $kspec, $output, true); break; } } if (isset($vwrite)) { $xfer += $output->$vwrite($val); } else { switch ($vtype) { case TType::STRUCT: $xfer += $val->write($output); break; case TType::MAP: $xfer += $this->_writeMap($val, $vspec, $output); break; case TType::LST: $xfer += $this->_writeList($val, $vspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($val, $vspec, $output, true); break; } } } $xfer += $output->writeMapEnd(); return $xfer; } private function _writeList($var, $spec, $output, $set=false) { $xfer = 0; $etype = $spec['etype']; $ewrite = null; if (isset(TBase::$tmethod[$etype])) { $ewrite = 'write'.TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } if ($set) { $xfer += $output->writeSetBegin($etype, count($var)); } else { $xfer += $output->writeListBegin($etype, count($var)); } foreach ($var as $key => $val) { $elem = $set ? $key : $val; if (isset($ewrite)) { $xfer += $output->$ewrite($elem); } else { switch ($etype) { case TType::STRUCT: $xfer += $elem->write($output); break; case TType::MAP: $xfer += $this->_writeMap($elem, $espec, $output); break; case TType::LST: $xfer += $this->_writeList($elem, $espec, $output, false); break; case TType::SET: $xfer += $this->_writeList($elem, $espec, $output, true); break; } } } if ($set) { $xfer += $output->writeSetEnd(); } else { $xfer += $output->writeListEnd(); } return $xfer; } protected function _write($class, $spec, $output) { $xfer = 0; $xfer += $output->writeStructBegin($class); foreach ($spec as $fid => $fspec) { $var = $fspec['var']; if ($this->$var !== null) { $ftype = $fspec['type']; $xfer += $output->writeFieldBegin($var, $ftype, $fid); if (isset(TBase::$tmethod[$ftype])) { $func = 'write'.TBase::$tmethod[$ftype]; $xfer += $output->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $xfer += $this->$var->write($output); break; case TType::MAP: $xfer += $this->_writeMap($this->$var, $fspec, $output); break; case TType::LST: $xfer += $this->_writeList($this->$var, $fspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($this->$var, $fspec, $output, true); break; } } $xfer += $output->writeFieldEnd(); } } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } } class TApplicationException extends TException { static $_TSPEC = array(1 => array('var' => 'message', 'type' => TType::STRING), 2 => array('var' => 'code', 'type' => TType::I32)); const UNKNOWN = 0; const UNKNOWN_METHOD = 1; const INVALID_MESSAGE_TYPE = 2; const WRONG_METHOD_NAME = 3; const BAD_SEQUENCE_ID = 4; const MISSING_RESULT = 5; const INTERNAL_ERROR = 6; const PROTOCOL_ERROR = 7; public function __construct($message=null, $code=0) { parent::__construct($message, $code); } public function read($output) { return $this->_read('TApplicationException', self::$_TSPEC, $output); } public function write($output) { $xfer = 0; $xfer += $output->writeStructBegin('TApplicationException'); if ($message = $this->getMessage()) { $xfer += $output->writeFieldBegin('message', TType::STRING, 1); $xfer += $output->writeString($message); $xfer += $output->writeFieldEnd(); } if ($code = $this->getCode()) { $xfer += $output->writeFieldBegin('type', TType::I32, 2); $xfer += $output->writeI32($code); $xfer += $output->writeFieldEnd(); } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } } /** * Set global THRIFT ROOT automatically via inclusion here */ if (!isset($GLOBALS['THRIFT_ROOT'])) { $GLOBALS['THRIFT_ROOT'] = dirname(__FILE__); } include_once $GLOBALS['THRIFT_ROOT'].'/protocol/TProtocol.php'; include_once $GLOBALS['THRIFT_ROOT'].'/transport/TTransport.php'; include_once $GLOBALS['THRIFT_ROOT'].'/TStringUtils.php'; thrift-0.19.0/lib/php/src/autoload.php0000644000000000000000000000357214303740367017562 0ustar00rootroot00000000000000registerNamespace('namespace', '')` instead of `$thriftClassLoader->registerDefinition('namespace', '')`. thrift-0.19.0/lib/php/coding_standards.md0000644000000000000000000000022514303740367020272 0ustar00rootroot00000000000000## PHP Coding Standards Please follow: * [Thrift General Coding Standards](/doc/coding_standards.md) * [PSR-2](http://www.php-fig.org/psr/psr-2/) thrift-0.19.0/lib/php/thrift_protocol.ini0000644000000000000000000000003514303740367020363 0ustar00rootroot00000000000000extension=thrift_protocol.so thrift-0.19.0/lib/php/test/0000755000000000000000000000000014472652662015431 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/test/Makefile.am0000644000000000000000000000351014370300523017443 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # PHPUNIT=php $(top_srcdir)/vendor/bin/phpunit stubs: ../../../test/v0.16/ThriftTest.thrift TestValidators.thrift mkdir -p ./packages/php $(THRIFT) --gen php -r --out ./packages/php ../../../test/v0.16/ThriftTest.thrift mkdir -p ./packages/phpv mkdir -p ./packages/phpvo mkdir -p ./packages/phpjs $(THRIFT) --gen php:validate -r --out ./packages/phpv TestValidators.thrift $(THRIFT) --gen php:validate,oop -r --out ./packages/phpvo TestValidators.thrift $(THRIFT) --gen php:json -r --out ./packages/phpjs TestValidators.thrift deps: $(top_srcdir)/composer.json composer install --working-dir=$(top_srcdir) all-local: deps check-json-serializer: deps stubs $(PHPUNIT) --log-junit=TEST-log-json-serializer.xml JsonSerialize/ check-validator: deps stubs $(PHPUNIT) --log-junit=TEST-log-validator.xml Validator/ check-protocol: deps stubs $(PHPUNIT) --log-junit=TEST-log-protocol.xml Protocol/ check: deps stubs \ check-protocol \ check-validator \ check-json-serializer distclean-local: clean-local: $(RM) -r ./packages $(RM) TEST-*.xml thrift-0.19.0/lib/php/test/JsonSerialize/0000755000000000000000000000000014472652662020212 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/test/JsonSerialize/JsonSerializeTest.php0000644000000000000000000001020114303740367024327 0ustar00rootroot00000000000000markTestSkipped('Requires PHP 5.4 or newer!'); } /** @var \Composer\Autoload\ClassLoader $loader */ $loader = require __DIR__ . '/../../../../vendor/autoload.php'; $loader->addPsr4('', __DIR__ . '/../packages/phpjs'); } public function testEmptyStruct() { $empty = new \ThriftTest\EmptyStruct(array('non_existing_key' => 'bar')); $this->assertEquals(new stdClass(), json_decode(json_encode($empty))); } public function testStringsAndInts() { $input = array( 'string_thing' => 'foo', 'i64_thing' => 1234567890, ); $xtruct = new \ThriftTest\Xtruct($input); // Xtruct's 'i32_thing' and 'byte_thing' fields should not be present here! $expected = new stdClass(); $expected->string_thing = $input['string_thing']; $expected->i64_thing = $input['i64_thing']; $this->assertEquals($expected, json_decode(json_encode($xtruct))); } public function testNestedStructs() { $xtruct2 = new \ThriftTest\Xtruct2(array( 'byte_thing' => 42, 'struct_thing' => new \ThriftTest\Xtruct(array( 'i32_thing' => 123456, )), )); $expected = new stdClass(); $expected->byte_thing = $xtruct2->byte_thing; $expected->struct_thing = new stdClass(); $expected->struct_thing->i32_thing = $xtruct2->struct_thing->i32_thing; $this->assertEquals($expected, json_decode(json_encode($xtruct2))); } public function testInsanity() { $xinput = array('string_thing' => 'foo'); $xtruct = new \ThriftTest\Xtruct($xinput); $insanity = new \ThriftTest\Insanity(array( 'xtructs' => array($xtruct, $xtruct, $xtruct) )); $expected = new stdClass(); $expected->xtructs = array((object)$xinput, (object)$xinput, (object)$xinput); $this->assertEquals($expected, json_decode(json_encode($insanity))); } public function testNestedLists() { $bonk = new \ThriftTest\Bonk(array('message' => 'foo')); $nested = new \ThriftTest\NestedListsBonk(array('bonk' => array(array(array($bonk))))); $expected = new stdClass(); $expected->bonk = array(array(array((object)array('message' => 'foo')))); $this->assertEquals($expected, json_decode(json_encode($nested))); } public function testMaps() { $intmap = new \ThriftTest\ThriftTest_testMap_args(['thing' => [0 => 'zero']]); $emptymap = new \ThriftTest\ThriftTest_testMap_args([]); $this->assertEquals('{"thing":{"0":"zero"}}', json_encode($intmap)); $this->assertEquals('{}', json_encode($emptymap)); } public function testScalarTypes() { $b = new \ThriftTest\Bools(['im_true' => '1', 'im_false' => '0']); $this->assertEquals('{"im_true":true,"im_false":false}', json_encode($b)); $s = new \ThriftTest\StructA(['s' => 42]); $this->assertEquals('{"s":"42"}', json_encode($s)); } } thrift-0.19.0/lib/php/test/Protocol/0000755000000000000000000000000014472652662017232 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/test/Protocol/TSimpleJSONProtocolFixtures.php0000644000000000000000000003176314303740367025271 0ustar00rootroot00000000000000<><"}'; self::$testArgsJSON['testDouble'] = '{"thing":3.1415926535898}'; self::$testArgsJSON['testByte'] = '{"thing":1}'; self::$testArgsJSON['testI32'] = '{"thing":1073741824}'; if (PHP_INT_SIZE == 8) { self::$testArgsJSON['testI64'] = '{"thing":' . pow(2, 60) . '}'; self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '}}'; self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":' . pow(2, 60) . '},"i32_thing":32768}}'; } else { self::$testArgsJSON['testI64'] = '{"thing":1152921504606847000}'; self::$testArgsJSON['testStruct'] = '{"thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000}}'; self::$testArgsJSON['testNest'] = '{"thing":{"byte_thing":1,"struct_thing":{"string_thing":"worked","byte_thing":1,"i32_thing":1073741824,"i64_thing":1152921504606847000},"i32_thing":32768}}'; } self::$testArgsJSON['testMap'] = '{"thing":{"7":77,"8":88,"9":99}}'; self::$testArgsJSON['testStringMap'] = '{"thing":{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}}'; self::$testArgsJSON['testSet'] = '{"thing":[1,5,6]}'; self::$testArgsJSON['testList'] = '{"thing":[1,2,3]}'; self::$testArgsJSON['testEnum'] = '{"thing":1}'; self::$testArgsJSON['testTypedef'] = '{"thing":69}'; } } thrift-0.19.0/lib/php/test/Protocol/TSimpleJSONProtocolTest.php0000644000000000000000000001734314303740367024375 0ustar00rootroot00000000000000addPsr4('', __DIR__ . '/../packages/php'); Fixtures::populateTestArgs(); TSimpleJSONProtocolFixtures::populateTestArgsSimpleJSON(); } public function setUp() { $this->transport = new TMemoryBuffer(); $this->protocol = new TSimpleJSONProtocol($this->transport); $this->transport->open(); } /** * WRITE TESTS */ public function testVoidWrite() { $args = new \ThriftTest\ThriftTest_testVoid_args(); $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testVoid']; $this->assertEquals($expected, $actual); } public function testString1Write() { $args = new \ThriftTest\ThriftTest_testString_args(); $args->thing = Fixtures::$testArgs['testString1']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testString1']; $this->assertEquals($expected, $actual); } public function testString2Write() { $args = new \ThriftTest\ThriftTest_testString_args(); $args->thing = Fixtures::$testArgs['testString2']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testString2']; $this->assertEquals($expected, $actual); } public function testDoubleWrite() { $args = new \ThriftTest\ThriftTest_testDouble_args(); $args->thing = Fixtures::$testArgs['testDouble']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testDouble']; $this->assertEquals($expected, $actual); } public function testByteWrite() { $args = new \ThriftTest\ThriftTest_testByte_args(); $args->thing = Fixtures::$testArgs['testByte']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testByte']; $this->assertEquals($expected, $actual); } public function testI32Write() { $args = new \ThriftTest\ThriftTest_testI32_args(); $args->thing = Fixtures::$testArgs['testI32']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testI32']; $this->assertEquals($expected, $actual); } public function testI64Write() { $args = new \ThriftTest\ThriftTest_testI64_args(); $args->thing = Fixtures::$testArgs['testI64']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testI64']; $this->assertEquals($expected, $actual); } public function testStructWrite() { $args = new \ThriftTest\ThriftTest_testStruct_args(); $args->thing = Fixtures::$testArgs['testStruct']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testStruct']; $this->assertEquals($expected, $actual); } public function testNestWrite() { $args = new \ThriftTest\ThriftTest_testNest_args(); $args->thing = Fixtures::$testArgs['testNest']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testNest']; $this->assertEquals($expected, $actual); } public function testMapWrite() { $args = new \ThriftTest\ThriftTest_testMap_args(); $args->thing = Fixtures::$testArgs['testMap']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testMap']; $this->assertEquals($expected, $actual); } public function testStringMapWrite() { $args = new \ThriftTest\ThriftTest_testStringMap_args(); $args->thing = Fixtures::$testArgs['testStringMap']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testStringMap']; $this->assertEquals($expected, $actual); } public function testSetWrite() { $args = new \ThriftTest\ThriftTest_testSet_args(); $args->thing = Fixtures::$testArgs['testSet']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testSet']; $this->assertEquals($expected, $actual); } public function testListWrite() { $args = new \ThriftTest\ThriftTest_testList_args(); $args->thing = Fixtures::$testArgs['testList']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testList']; $this->assertEquals($expected, $actual); } public function testEnumWrite() { $args = new \ThriftTest\ThriftTest_testEnum_args(); $args->thing = Fixtures::$testArgs['testEnum']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testEnum']; $this->assertEquals($expected, $actual); } public function testTypedefWrite() { $args = new \ThriftTest\ThriftTest_testTypedef_args(); $args->thing = Fixtures::$testArgs['testTypedef']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TSimpleJSONProtocolFixtures::$testArgsJSON['testTypedef']; $this->assertEquals($expected, $actual); } } thrift-0.19.0/lib/php/test/Protocol/BinarySerializerTest.php0000644000000000000000000000376414303740367024064 0ustar00rootroot00000000000000addPsr4('', __DIR__ . '/../packages/php'); } /** * We try to serialize and deserialize a random object to make sure no exceptions are thrown. * @see THRIFT-1579 */ public function testBinarySerializer() { $struct = new \ThriftTest\Xtruct(array('string_thing' => 'abc')); $serialized = TBinarySerializer::serialize($struct, 'ThriftTest\\Xtruct'); $deserialized = TBinarySerializer::deserialize($serialized, 'ThriftTest\\Xtruct'); $this->assertEquals($struct, $deserialized); } } thrift-0.19.0/lib/php/test/Protocol/TJSONProtocolFixtures.php0000644000000000000000000003112414303740367024106 0ustar00rootroot00000000000000<><"}}'; self::$testArgsJSON['testString3'] = '{"1":{"str":"string that ends in double-backslash \\\\\\\\"}}'; self::$testArgsJSON['testUnicodeStringWithNonBMP'] = '{"1":{"str":"สวัสดี\/ð’¯"}}'; self::$testArgsJSON['testDouble'] = '{"1":{"dbl":3.1415926535898}}'; self::$testArgsJSON['testByte'] = '{"1":{"i8":1}}'; self::$testArgsJSON['testI32'] = '{"1":{"i32":1073741824}}'; if (PHP_INT_SIZE == 8) { self::$testArgsJSON['testI64'] = '{"1":{"i64":' . pow(2, 60) . '}}'; self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}}}'; self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":' . pow(2, 60) . '}}},"3":{"i32":32768}}}}'; } else { self::$testArgsJSON['testI64'] = '{"1":{"i64":1152921504606847000}}'; self::$testArgsJSON['testStruct'] = '{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}'; self::$testArgsJSON['testNest'] = '{"1":{"rec":{"1":{"i8":1},"2":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}},"3":{"i32":32768}}}}'; } self::$testArgsJSON['testMap'] = '{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}'; self::$testArgsJSON['testStringMap'] = '{"1":{"map":["str","str",6,{"a":"123","a b":"with spaces ","same":"same","0":"numeric key","longValue":"Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e","Afrikaans, Alemannisch, Aragon\u00e9s, \u0627\u0644\u0639\u0631\u0628\u064a\u0629, \u0645\u0635\u0631\u0649, Asturianu, Aymar aru, Az\u0259rbaycan, \u0411\u0430\u0448\u04a1\u043e\u0440\u0442, Boarisch, \u017demait\u0117\u0161ka, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f, \u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430), \u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438, Bamanankan, \u09ac\u09be\u0982\u09b2\u09be, Brezhoneg, Bosanski, Catal\u00e0, M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304, \u041d\u043e\u0445\u0447\u0438\u0439\u043d, Cebuano, \u13e3\u13b3\u13a9, \u010cesky, \u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f, \u0427\u04d1\u0432\u0430\u0448\u043b\u0430, Cymraeg, Dansk, Zazaki, \u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0, \u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac, Emili\u00e0n e rumagn\u00f2l, English, Esperanto, Espa\u00f1ol, Eesti, Euskara, \u0641\u0627\u0631\u0633\u06cc, Suomi, V\u00f5ro, F\u00f8royskt, Fran\u00e7ais, Arpetan, Furlan, Frysk, Gaeilge, \u8d1b\u8a9e, G\u00e0idhlig, Galego, Ava\u00f1e\'\u1ebd, \u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0, Gaelg, \u05e2\u05d1\u05e8\u05d9\u05ea, \u0939\u093f\u0928\u094d\u0926\u0940, Fiji Hindi, Hrvatski, Krey\u00f2l ayisyen, Magyar, \u0540\u0561\u0575\u0565\u0580\u0565\u0576, Interlingua, Bahasa Indonesia, Ilokano, Ido, \u00cdslenska, Italiano, \u65e5\u672c\u8a9e, Lojban, Basa Jawa, \u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8, Kongo, Kalaallisut, \u0c95\u0ca8\u0ccd\u0ca8\u0ca1, \ud55c\uad6d\uc5b4, \u041a\u044a\u0430\u0440\u0430\u0447\u0430\u0439-\u041c\u0430\u043b\u043a\u044a\u0430\u0440, Ripoarisch, Kurd\u00ee, \u041a\u043e\u043c\u0438, Kernewek, \u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430, Latina, Ladino, L\u00ebtzebuergesch, Limburgs, Ling\u00e1la, \u0ea5\u0eb2\u0ea7, Lietuvi\u0173, Latvie\u0161u, Basa Banyumasan, Malagasy, \u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438, \u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02, \u092e\u0930\u093e\u0920\u0940, Bahasa Melayu, \u0645\u0627\u0632\u0650\u0631\u0648\u0646\u06cc, Nnapulitano, Nedersaksisch, \u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e, Nederlands, \u202aNorsk (nynorsk)\u202c, \u202aNorsk (bokm\u00e5l)\u202c, Nouormand, Din\u00e9 bizaad, Occitan, \u0418\u0440\u043e\u043d\u0430\u0443, Papiamentu, Deitsch, Norfuk \/ Pitkern, Polski, \u067e\u0646\u062c\u0627\u0628\u06cc, \u067e\u069a\u062a\u0648, Portugu\u00eas, Runa Simi, Rumantsch, Romani, Rom\u00e2n\u0103, \u0420\u0443\u0441\u0441\u043a\u0438\u0439, \u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430, Sardu, Sicilianu, Scots, S\u00e1megiella, Simple English, Sloven\u010dina, Sloven\u0161\u010dina, \u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski, Seeltersk, Svenska, Kiswahili, \u0ba4\u0bae\u0bbf\u0bb4\u0bcd, \u0c24\u0c46\u0c32\u0c41\u0c17\u0c41, \u0422\u043e\u04b7\u0438\u043a\u04e3, \u0e44\u0e17\u0e22, T\u00fcrkmen\u00e7e, Tagalog, T\u00fcrk\u00e7e, \u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a, \u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430, \u0627\u0631\u062f\u0648, Ti\u1ebfng Vi\u1ec7t, Volap\u00fck, Walon, Winaray, \u5434\u8bed, isiXhosa, \u05d9\u05d9\u05b4\u05d3\u05d9\u05e9, Yor\u00f9b\u00e1, Ze\u00eauws, \u4e2d\u6587, B\u00e2n-l\u00e2m-g\u00fa, \u7cb5\u8a9e":"long key"}]}}'; self::$testArgsJSON['testSet'] = '{"1":{"set":["i32",3,1,5,6]}}'; self::$testArgsJSON['testList'] = '{"1":{"lst":["i32",3,1,2,3]}}'; self::$testArgsJSON['testEnum'] = '{"1":{"i32":1}}'; self::$testArgsJSON['testTypedef'] = '{"1":{"i64":69}}'; self::$testArgsJSON['testMapMap'] = '{"0":{"map":["i32","map",2,{"4":["i32","i32",4,{"1":1,"2":2,"3":3,"4":4}],"-4":["i32","i32",4,{"-4":-4,"-3":-3,"-2":-2,"-1":-1}]}]}}'; self::$testArgsJSON['testInsanity'] = '{"0":{"map":["i64","map",2,{"1":["i32","rec",2,{"2":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}},"3":{"1":{"map":["i32","i64",2,{"5":5,"8":8}]},"2":{"lst":["rec",2,{"1":{"str":"Goodbye4"},"4":{"i8":4},"9":{"i32":4},"11":{"i64":4}},{"1":{"str":"Hello2"},"4":{"i8":2},"9":{"i32":2},"11":{"i64":2}}]}}}],"2":["i32","rec",1,{"6":{}}]}]}}'; } } thrift-0.19.0/lib/php/test/Protocol/TJSONProtocolTest.php0000644000000000000000000003607714303740367023230 0ustar00rootroot00000000000000addPsr4('', __DIR__ . '/../packages/php'); Fixtures::populateTestArgs(); TJSONProtocolFixtures::populateTestArgsJSON(); } public function setUp() { $this->transport = new TMemoryBuffer(); $this->protocol = new TJSONProtocol($this->transport); $this->transport->open(); } /** * WRITE TESTS */ public function testVoidWrite() { $args = new \ThriftTest\ThriftTest_testVoid_args(); $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testVoid']; $this->assertEquals($expected, $actual); } public function testString1Write() { $args = new \ThriftTest\ThriftTest_testString_args(); $args->thing = Fixtures::$testArgs['testString1']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testString1']; $this->assertEquals($expected, $actual); } public function testString2Write() { $args = new \ThriftTest\ThriftTest_testString_args(); $args->thing = Fixtures::$testArgs['testString2']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testString2']; $this->assertEquals($expected, $actual); } public function testDoubleWrite() { $args = new \ThriftTest\ThriftTest_testDouble_args(); $args->thing = Fixtures::$testArgs['testDouble']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testDouble']; $this->assertEquals($expected, $actual); } public function testByteWrite() { $args = new \ThriftTest\ThriftTest_testByte_args(); $args->thing = Fixtures::$testArgs['testByte']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testByte']; $this->assertEquals($expected, $actual); } public function testI32Write() { $args = new \ThriftTest\ThriftTest_testI32_args(); $args->thing = Fixtures::$testArgs['testI32']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testI32']; $this->assertEquals($expected, $actual); } public function testI64Write() { $args = new \ThriftTest\ThriftTest_testI64_args(); $args->thing = Fixtures::$testArgs['testI64']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testI64']; $this->assertEquals($expected, $actual); } public function testStructWrite() { $args = new \ThriftTest\ThriftTest_testStruct_args(); $args->thing = Fixtures::$testArgs['testStruct']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testStruct']; $this->assertEquals($expected, $actual); } public function testNestWrite() { $args = new \ThriftTest\ThriftTest_testNest_args(); $args->thing = Fixtures::$testArgs['testNest']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testNest']; $this->assertEquals($expected, $actual); } public function testMapWrite() { $args = new \ThriftTest\ThriftTest_testMap_args(); $args->thing = Fixtures::$testArgs['testMap']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testMap']; $this->assertEquals($expected, $actual); } public function testStringMapWrite() { $args = new \ThriftTest\ThriftTest_testStringMap_args(); $args->thing = Fixtures::$testArgs['testStringMap']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testStringMap']; /* * The $actual returns unescaped string. * It is required to to decode then encode it again * to get the expected escaped unicode. */ $this->assertEquals($expected, json_encode(json_decode($actual))); } public function testSetWrite() { $args = new \ThriftTest\ThriftTest_testSet_args(); $args->thing = Fixtures::$testArgs['testSet']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testSet']; $this->assertEquals($expected, $actual); } public function testListWrite() { $args = new \ThriftTest\ThriftTest_testList_args(); $args->thing = Fixtures::$testArgs['testList']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testList']; $this->assertEquals($expected, $actual); } public function testEnumWrite() { $args = new \ThriftTest\ThriftTest_testEnum_args(); $args->thing = Fixtures::$testArgs['testEnum']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testEnum']; $this->assertEquals($expected, $actual); } public function testTypedefWrite() { $args = new \ThriftTest\ThriftTest_testTypedef_args(); $args->thing = Fixtures::$testArgs['testTypedef']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testTypedef']; $this->assertEquals($expected, $actual); } /** * READ TESTS */ public function testVoidRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testVoid'] ); $args = new \ThriftTest\ThriftTest_testVoid_args(); $args->read($this->protocol); } public function testString1Read() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testString1'] ); $args = new \ThriftTest\ThriftTest_testString_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testString1']; $this->assertEquals($expected, $actual); } public function testString2Read() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testString2'] ); $args = new \ThriftTest\ThriftTest_testString_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testString2']; $this->assertEquals($expected, $actual); } public function testString3Write() { $args = new \ThriftTest\ThriftTest_testString_args(); $args->thing = Fixtures::$testArgs['testString3']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testString3']; $this->assertEquals($expected, $actual); } public function testString4Write() { $args = new \ThriftTest\ThriftTest_testString_args(); $args->thing = Fixtures::$testArgs['testUnicodeStringWithNonBMP']; $args->write($this->protocol); $actual = $this->transport->read(Fixtures::$bufsize); $expected = TJSONProtocolFixtures::$testArgsJSON['testUnicodeStringWithNonBMP']; $this->assertEquals($expected, $actual); } public function testDoubleRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testDouble'] ); $args = new \ThriftTest\ThriftTest_testDouble_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testDouble']; $this->assertEquals($expected, $actual); } public function testByteRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testByte'] ); $args = new \ThriftTest\ThriftTest_testByte_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testByte']; $this->assertEquals($expected, $actual); } public function testI32Read() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testI32'] ); $args = new \ThriftTest\ThriftTest_testI32_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testI32']; $this->assertEquals($expected, $actual); } public function testI64Read() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testI64'] ); $args = new \ThriftTest\ThriftTest_testI64_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testI64']; $this->assertEquals($expected, $actual); } public function testStructRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testStruct'] ); $args = new \ThriftTest\ThriftTest_testStruct_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testStruct']; $this->assertEquals($expected, $actual); } public function testNestRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testNest'] ); $args = new \ThriftTest\ThriftTest_testNest_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testNest']; $this->assertEquals($expected, $actual); } public function testMapRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testMap'] ); $args = new \ThriftTest\ThriftTest_testMap_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testMap']; $this->assertEquals($expected, $actual); } public function testStringMapRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testStringMap'] ); $args = new \ThriftTest\ThriftTest_testStringMap_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testStringMap']; $this->assertEquals($expected, $actual); } public function testSetRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testSet'] ); $args = new \ThriftTest\ThriftTest_testSet_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testSet']; $this->assertEquals($expected, $actual); } public function testListRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testList'] ); $args = new \ThriftTest\ThriftTest_testList_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testList']; $this->assertEquals($expected, $actual); } public function testEnumRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testEnum'] ); $args = new \ThriftTest\ThriftTest_testEnum_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testEnum']; $this->assertEquals($expected, $actual); } public function testTypedefRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testTypedef'] ); $args = new \ThriftTest\ThriftTest_testTypedef_args(); $args->read($this->protocol); $actual = $args->thing; $expected = Fixtures::$testArgs['testTypedef']; $this->assertEquals($expected, $actual); } public function testMapMapRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testMapMap'] ); $result = new \ThriftTest\ThriftTest_testMapMap_result(); $result->read($this->protocol); $actual = $result->success; $expected = Fixtures::$testArgs['testMapMapExpectedResult']; $this->assertEquals($expected, $actual); } public function testInsanityRead() { $this->transport->write( TJSONProtocolFixtures::$testArgsJSON['testInsanity'] ); $result = new \ThriftTest\ThriftTest_testInsanity_result(); $result->read($this->protocol); $actual = $result->success; $expected = Fixtures::$testArgs['testInsanityExpectedResult']; $this->assertEquals($expected, $actual); } } thrift-0.19.0/lib/php/test/Fixtures.php0000644000000000000000000001667714303740367017765 0ustar00rootroot00000000000000<><"; self::$testArgs['testString3'] = "string that ends in double-backslash \\\\"; self::$testArgs['testUnicodeStringWithNonBMP'] = "สวัสดี/ð’¯"; self::$testArgs['testDouble'] = 3.1415926535898; // TODO: add testBinary() call self::$testArgs['testByte'] = 0x01; self::$testArgs['testI32'] = pow(2, 30); if (PHP_INT_SIZE == 8) { self::$testArgs['testI64'] = pow(2, 60); } else { self::$testArgs['testI64'] = "1152921504606847000"; } self::$testArgs['testStruct'] = new Xtruct( array( 'string_thing' => 'worked', 'byte_thing' => 0x01, 'i32_thing' => pow(2, 30), 'i64_thing' => self::$testArgs['testI64'] ) ); self::$testArgs['testNestNested'] = new Xtruct( array( 'string_thing' => 'worked', 'byte_thing' => 0x01, 'i32_thing' => pow(2, 30), 'i64_thing' => self::$testArgs['testI64'] ) ); self::$testArgs['testNest'] = new Xtruct2( array( 'byte_thing' => 0x01, 'struct_thing' => self::$testArgs['testNestNested'], 'i32_thing' => pow(2, 15) ) ); self::$testArgs['testMap'] = array( 7 => 77, 8 => 88, 9 => 99 ); self::$testArgs['testStringMap'] = array( "a" => "123", "a b" => "with spaces ", "same" => "same", "0" => "numeric key", "longValue" => self::$testArgs['testString1'], self::$testArgs['testString1'] => "long key" ); self::$testArgs['testSet'] = array(1 => true, 5 => true, 6 => true); self::$testArgs['testList'] = array(1, 2, 3); self::$testArgs['testEnum'] = Numberz::ONE; self::$testArgs['testTypedef'] = 69; self::$testArgs['testMapMapExpectedResult'] = array( 4 => array( 1 => 1, 2 => 2, 3 => 3, 4 => 4, ), -4 => array( -4 => -4, -3 => -3, -2 => -2, -1 => -1 ) ); // testInsanity ... takes a few steps to set up! $xtruct1 = new Xtruct( array( 'string_thing' => 'Goodbye4', 'byte_thing' => 4, 'i32_thing' => 4, 'i64_thing' => 4 ) ); $xtruct2 = new Xtruct( array( 'string_thing' => 'Hello2', 'byte_thing' => 2, 'i32_thing' => 2, 'i64_thing' => 2 ) ); $userMap = array( Numberz::FIVE => 5, Numberz::EIGHT => 8 ); $insanity2 = new Insanity( array( 'userMap' => $userMap, 'xtructs' => array($xtruct1, $xtruct2) ) ); $insanity3 = $insanity2; $insanity6 = new Insanity( array( 'userMap' => null, 'xtructs' => null ) ); self::$testArgs['testInsanityExpectedResult'] = array( "1" => array( Numberz::TWO => $insanity2, Numberz::THREE => $insanity3 ), "2" => array( Numberz::SIX => $insanity6 ) ); } } thrift-0.19.0/lib/php/test/TestValidators.thrift0000644000000000000000000000177714370300523021616 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace php TestValidators include "../../../test/v0.16/ThriftTest.thrift" union UnionOfStrings { 1: string aa; 2: string bb; } service TestService { void test() throws(1: ThriftTest.Xception xception); } thrift-0.19.0/lib/php/test/Validator/0000755000000000000000000000000014472652662017356 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/test/Validator/ValidatorTestOop.php0000644000000000000000000000244614303740367023331 0ustar00rootroot00000000000000addPsr4('', __DIR__ . '/../packages/phpvo'); } } thrift-0.19.0/lib/php/test/Validator/BaseValidatorTest.php0000644000000000000000000001134014303740367023437 0ustar00rootroot00000000000000assertNoReadValidator('ThriftTest\EmptyStruct'); $this->assertNoWriteValidator('ThriftTest\EmptyStruct'); } public function testBonkValidator() { $this->assertNoReadValidator('ThriftTest\Bonk'); $this->assertHasWriteValidator('ThriftTest\Bonk'); } public function testStructAValidator() { $this->assertHasReadValidator('ThriftTest\StructA'); $this->assertHasWriteValidator('ThriftTest\StructA'); } public function testUnionOfStringsValidator() { $this->assertNoWriteValidator('TestValidators\UnionOfStrings'); } public function testServiceResultValidator() { $this->assertNoReadValidator('TestValidators\TestService_test_result'); $this->assertNoWriteValidator('TestValidators\TestService_test_result'); } public function testReadEmpty() { $bonk = new \ThriftTest\Bonk(); $transport = new TMemoryBuffer("\000"); $protocol = new TBinaryProtocol($transport); $bonk->read($protocol); } public function testWriteEmpty() { $bonk = new \ThriftTest\Bonk(); $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocol($transport); try { $bonk->write($protocol); $this->fail('Bonk was able to write an empty object'); } catch (TProtocolException $e) { } } public function testWriteWithMissingRequired() { // Check that we are not able to write StructA with a missing required field $structa = new \ThriftTest\StructA(); $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocol($transport); try { $structa->write($protocol); $this->fail('StructA was able to write an empty object'); } catch (TProtocolException $e) { } } public function testReadStructA() { $transport = new TMemoryBuffer(base64_decode('CwABAAAAA2FiYwA=')); $protocol = new TBinaryProtocol($transport); $structa = new \ThriftTest\StructA(); $structa->read($protocol); $this->assertEquals("abc", $structa->s); } public function testWriteStructA() { $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocol($transport); $structa = new \ThriftTest\StructA(); $structa->s = "abc"; $structa->write($protocol); $writeResult = base64_encode($transport->getBuffer()); $this->assertEquals('CwABAAAAA2FiYwA=', $writeResult); } protected static function assertHasReadValidator($class) { if (!static::hasReadValidator($class)) { static::fail($class . ' class should have a read validator'); } } protected static function assertNoReadValidator($class) { if (static::hasReadValidator($class)) { static::fail($class . ' class should not have a write validator'); } } protected static function assertHasWriteValidator($class) { if (!static::hasWriteValidator($class)) { static::fail($class . ' class should have a write validator'); } } protected static function assertNoWriteValidator($class) { if (static::hasWriteValidator($class)) { static::fail($class . ' class should not have a write validator'); } } private static function hasReadValidator($class) { $rc = new \ReflectionClass($class); return $rc->hasMethod('_validateForRead'); } private static function hasWriteValidator($class) { $rc = new \ReflectionClass($class); return $rc->hasMethod('_validateForWrite'); } } thrift-0.19.0/lib/php/test/Validator/ValidatorTest.php0000644000000000000000000000243214303740367022646 0ustar00rootroot00000000000000addPsr4('', __DIR__ . '/../packages/phpv'); } } thrift-0.19.0/lib/php/test/Makefile.in0000644000000000000000000004433214472652517017503 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/php/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ PHPUNIT = php $(top_srcdir)/vendor/bin/phpunit all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/php/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/php/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distclean-local distdir \ dvi dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: ../../../test/v0.16/ThriftTest.thrift TestValidators.thrift mkdir -p ./packages/php $(THRIFT) --gen php -r --out ./packages/php ../../../test/v0.16/ThriftTest.thrift mkdir -p ./packages/phpv mkdir -p ./packages/phpvo mkdir -p ./packages/phpjs $(THRIFT) --gen php:validate -r --out ./packages/phpv TestValidators.thrift $(THRIFT) --gen php:validate,oop -r --out ./packages/phpvo TestValidators.thrift $(THRIFT) --gen php:json -r --out ./packages/phpjs TestValidators.thrift deps: $(top_srcdir)/composer.json composer install --working-dir=$(top_srcdir) all-local: deps check-json-serializer: deps stubs $(PHPUNIT) --log-junit=TEST-log-json-serializer.xml JsonSerialize/ check-validator: deps stubs $(PHPUNIT) --log-junit=TEST-log-validator.xml Validator/ check-protocol: deps stubs $(PHPUNIT) --log-junit=TEST-log-protocol.xml Protocol/ check: deps stubs \ check-protocol \ check-validator \ check-json-serializer distclean-local: clean-local: $(RM) -r ./packages $(RM) TEST-*.xml # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/php/README.apache.md0000644000000000000000000000405114303740367017142 0ustar00rootroot00000000000000Thrift PHP/Apache Integration License ======= Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Building PHP Thrift Services with Apache ======================================== Thrift can be embedded in the Apache webserver with PHP installed. Sample code is provided below. Note that to make requests to this type of server you must use a THttpClient transport. Sample Code =========== registerNamespace('Thrift', $THRIFT_ROOT); $loader->registerDefinition('Thrift', $THRIFT_ROOT . '/packages'); $loader->register(); use Thrift\Transport\TPhpStream; use Thrift\Protocol\TBinaryProtocol; /** * Example of how to build a Thrift server in Apache/PHP */ class ServiceHandler implements ServiceIf { // Implement your interface and methods here } header('Content-Type: application/x-thrift'); $handler = new ServiceHandler(); $processor = new ServiceProcessor($handler); // Use the TPhpStream transport to read/write directly from HTTP $transport = new TPhpStream(TPhpStream::MODE_R | TPhpStream::MODE_W); $protocol = new TBinaryProtocol($transport); $transport->open(); $processor->process($protocol, $protocol); $transport->close(); thrift-0.19.0/lib/php/lib/0000777000000000000000000000000014303740367015215 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Type/0000777000000000000000000000000014303740367016136 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Type/TType.php0000644000000000000000000000250514303740367017712 0ustar00rootroot00000000000000apcu = $apc; $this->apcu_prefix = $apcu_prefix; } /** * Registers a namespace. * * @param string $namespace The namespace * @param array|string $paths The location(s) of the namespace */ public function registerNamespace($namespace, $paths) { $this->namespaces[$namespace] = (array)$paths; } /** * Registers a Thrift definition namespace. * * @param string $namespace The definition namespace * @param array|string $paths The location(s) of the definition namespace */ public function registerDefinition($namespace, $paths) { $this->definitions[$namespace] = (array)$paths; } /** * Registers this instance as an autoloader. * * @param Boolean $prepend Whether to prepend the autoloader or not */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Loads the given class, definition or interface. * * @param string $class The name of the class */ public function loadClass($class) { if ((true === $this->apcu && ($file = $this->findFileInApcu($class))) or ($file = $this->findFile($class)) ) { require_once $file; } } /** * Loads the given class or interface in APCu. * @param string $class The name of the class * @return string */ protected function findFileInApcu($class) { if (false === $file = apcu_fetch($this->apcu_prefix . $class)) { apcu_store($this->apcu_prefix . $class, $file = $this->findFile($class)); } return $file; } /** * Find class in namespaces or definitions directories * @param string $class * @return string */ public function findFile($class) { // Remove first backslash if ('\\' == $class[0]) { $class = substr($class, 1); } if (false !== $pos = strrpos($class, '\\')) { // Namespaced class name $namespace = substr($class, 0, $pos); // Iterate in normal namespaces foreach ($this->namespaces as $ns => $dirs) { //Don't interfere with other autoloaders if (0 !== strpos($namespace, $ns)) { continue; } foreach ($dirs as $dir) { $className = substr($class, $pos + 1); $file = $dir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR . $className . '.php'; if (file_exists($file)) { return $file; } } } // Iterate in Thrift namespaces // Remove first part of namespace $m = explode('\\', $class); // Ignore wrong call if (count($m) <= 1) { return; } $class = array_pop($m); $namespace = implode('\\', $m); foreach ($this->definitions as $ns => $dirs) { //Don't interfere with other autoloaders if (0 !== strpos($namespace, $ns)) { continue; } foreach ($dirs as $dir) { /** * Available in service: Interface, Client, Processor, Rest * And every service methods (_.+) */ if (0 === preg_match('#(.+)(if|client|processor|rest)$#i', $class, $n) and 0 === preg_match('#(.+)_[a-z0-9]+_(args|result)$#i', $class, $n) ) { $className = 'Types'; } else { $className = $n[1]; } $file = $dir . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR . $className . '.php'; if (file_exists($file)) { return $file; } } } } } } thrift-0.19.0/lib/php/lib/Base/0000777000000000000000000000000014303740367016067 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Base/TBase.php0000644000000000000000000003214414303740367017576 0ustar00rootroot00000000000000 'Bool', TType::BYTE => 'Byte', TType::I16 => 'I16', TType::I32 => 'I32', TType::I64 => 'I64', TType::DOUBLE => 'Double', TType::STRING => 'String' ); abstract public function read($input); abstract public function write($output); public function __construct($spec = null, $vals = null) { if (is_array($spec) && is_array($vals)) { foreach ($spec as $fid => $fspec) { $var = $fspec['var']; if (isset($vals[$var])) { $this->$var = $vals[$var]; } } } } public function __wakeup() { $this->__construct(get_object_vars($this)); } private function _readMap(&$var, $spec, $input) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kread = $vread = null; if (isset(TBase::$tmethod[$ktype])) { $kread = 'read' . TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vread = 'read' . TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $var = array(); $_ktype = $_vtype = $size = 0; $xfer += $input->readMapBegin($_ktype, $_vtype, $size); for ($i = 0; $i < $size; ++$i) { $key = $val = null; if ($kread !== null) { $xfer += $input->$kread($key); } else { switch ($ktype) { case TType::STRUCT: $class = $kspec['class']; $key = new $class(); $xfer += $key->read($input); break; case TType::MAP: $xfer += $this->_readMap($key, $kspec, $input); break; case TType::LST: $xfer += $this->_readList($key, $kspec, $input, false); break; case TType::SET: $xfer += $this->_readList($key, $kspec, $input, true); break; } } if ($vread !== null) { $xfer += $input->$vread($val); } else { switch ($vtype) { case TType::STRUCT: $class = $vspec['class']; $val = new $class(); $xfer += $val->read($input); break; case TType::MAP: $xfer += $this->_readMap($val, $vspec, $input); break; case TType::LST: $xfer += $this->_readList($val, $vspec, $input, false); break; case TType::SET: $xfer += $this->_readList($val, $vspec, $input, true); break; } } $var[$key] = $val; } $xfer += $input->readMapEnd(); return $xfer; } private function _readList(&$var, $spec, $input, $set = false) { $xfer = 0; $etype = $spec['etype']; $eread = $vread = null; if (isset(TBase::$tmethod[$etype])) { $eread = 'read' . TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } $var = array(); $_etype = $size = 0; if ($set) { $xfer += $input->readSetBegin($_etype, $size); } else { $xfer += $input->readListBegin($_etype, $size); } for ($i = 0; $i < $size; ++$i) { $elem = null; if ($eread !== null) { $xfer += $input->$eread($elem); } else { $espec = $spec['elem']; switch ($etype) { case TType::STRUCT: $class = $espec['class']; $elem = new $class(); $xfer += $elem->read($input); break; case TType::MAP: $xfer += $this->_readMap($elem, $espec, $input); break; case TType::LST: $xfer += $this->_readList($elem, $espec, $input, false); break; case TType::SET: $xfer += $this->_readList($elem, $espec, $input, true); break; } } if ($set) { $var[$elem] = true; } else { $var [] = $elem; } } if ($set) { $xfer += $input->readSetEnd(); } else { $xfer += $input->readListEnd(); } return $xfer; } protected function _read($class, $spec, $input) { $xfer = 0; $fname = null; $ftype = 0; $fid = 0; $xfer += $input->readStructBegin($fname); while (true) { $xfer += $input->readFieldBegin($fname, $ftype, $fid); if ($ftype == TType::STOP) { break; } if (isset($spec[$fid])) { $fspec = $spec[$fid]; $var = $fspec['var']; if ($ftype == $fspec['type']) { $xfer = 0; if (isset(TBase::$tmethod[$ftype])) { $func = 'read' . TBase::$tmethod[$ftype]; $xfer += $input->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $class = $fspec['class']; $this->$var = new $class(); $xfer += $this->$var->read($input); break; case TType::MAP: $xfer += $this->_readMap($this->$var, $fspec, $input); break; case TType::LST: $xfer += $this->_readList($this->$var, $fspec, $input, false); break; case TType::SET: $xfer += $this->_readList($this->$var, $fspec, $input, true); break; } } } else { $xfer += $input->skip($ftype); } } else { $xfer += $input->skip($ftype); } $xfer += $input->readFieldEnd(); } $xfer += $input->readStructEnd(); return $xfer; } private function _writeMap($var, $spec, $output) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kwrite = $vwrite = null; if (isset(TBase::$tmethod[$ktype])) { $kwrite = 'write' . TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vwrite = 'write' . TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $xfer += $output->writeMapBegin($ktype, $vtype, count($var)); foreach ($var as $key => $val) { if (isset($kwrite)) { $xfer += $output->$kwrite($key); } else { switch ($ktype) { case TType::STRUCT: $xfer += $key->write($output); break; case TType::MAP: $xfer += $this->_writeMap($key, $kspec, $output); break; case TType::LST: $xfer += $this->_writeList($key, $kspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($key, $kspec, $output, true); break; } } if (isset($vwrite)) { $xfer += $output->$vwrite($val); } else { switch ($vtype) { case TType::STRUCT: $xfer += $val->write($output); break; case TType::MAP: $xfer += $this->_writeMap($val, $vspec, $output); break; case TType::LST: $xfer += $this->_writeList($val, $vspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($val, $vspec, $output, true); break; } } } $xfer += $output->writeMapEnd(); return $xfer; } private function _writeList($var, $spec, $output, $set = false) { $xfer = 0; $etype = $spec['etype']; $ewrite = null; if (isset(TBase::$tmethod[$etype])) { $ewrite = 'write' . TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } if ($set) { $xfer += $output->writeSetBegin($etype, count($var)); } else { $xfer += $output->writeListBegin($etype, count($var)); } foreach ($var as $key => $val) { $elem = $set ? $key : $val; if (isset($ewrite)) { $xfer += $output->$ewrite($elem); } else { switch ($etype) { case TType::STRUCT: $xfer += $elem->write($output); break; case TType::MAP: $xfer += $this->_writeMap($elem, $espec, $output); break; case TType::LST: $xfer += $this->_writeList($elem, $espec, $output, false); break; case TType::SET: $xfer += $this->_writeList($elem, $espec, $output, true); break; } } } if ($set) { $xfer += $output->writeSetEnd(); } else { $xfer += $output->writeListEnd(); } return $xfer; } protected function _write($class, $spec, $output) { $xfer = 0; $xfer += $output->writeStructBegin($class); foreach ($spec as $fid => $fspec) { $var = $fspec['var']; if ($this->$var !== null) { $ftype = $fspec['type']; $xfer += $output->writeFieldBegin($var, $ftype, $fid); if (isset(TBase::$tmethod[$ftype])) { $func = 'write' . TBase::$tmethod[$ftype]; $xfer += $output->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $xfer += $this->$var->write($output); break; case TType::MAP: $xfer += $this->_writeMap($this->$var, $fspec, $output); break; case TType::LST: $xfer += $this->_writeList($this->$var, $fspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($this->$var, $fspec, $output, true); break; } } $xfer += $output->writeFieldEnd(); } } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } } thrift-0.19.0/lib/php/lib/Protocol/0000777000000000000000000000000014303740367017016 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Protocol/TProtocol.php0000644000000000000000000002421514303740367021454 0ustar00rootroot00000000000000trans_ = $trans; } /** * Accessor for transport * * @return TTransport */ public function getTransport() { return $this->trans_; } /** * Writes the message header * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @param int $seqid The sequence id of this message */ abstract public function writeMessageBegin($name, $type, $seqid); /** * Close the message */ abstract public function writeMessageEnd(); /** * Writes a struct header. * * @param string $name Struct name * @throws TException on write error * @return int How many bytes written */ abstract public function writeStructBegin($name); /** * Close a struct. * * @throws TException on write error * @return int How many bytes written */ abstract public function writeStructEnd(); /* * Starts a field. * * @param string $name Field name * @param int $type Field type * @param int $fid Field id * @throws TException on write error * @return int How many bytes written */ abstract public function writeFieldBegin($fieldName, $fieldType, $fieldId); abstract public function writeFieldEnd(); abstract public function writeFieldStop(); abstract public function writeMapBegin($keyType, $valType, $size); abstract public function writeMapEnd(); abstract public function writeListBegin($elemType, $size); abstract public function writeListEnd(); abstract public function writeSetBegin($elemType, $size); abstract public function writeSetEnd(); abstract public function writeBool($bool); abstract public function writeByte($byte); abstract public function writeI16($i16); abstract public function writeI32($i32); abstract public function writeI64($i64); abstract public function writeDouble($dub); abstract public function writeString($str); /** * Reads the message header * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @parem int $seqid The sequence id of this message */ abstract public function readMessageBegin(&$name, &$type, &$seqid); /** * Read the close of message */ abstract public function readMessageEnd(); abstract public function readStructBegin(&$name); abstract public function readStructEnd(); abstract public function readFieldBegin(&$name, &$fieldType, &$fieldId); abstract public function readFieldEnd(); abstract public function readMapBegin(&$keyType, &$valType, &$size); abstract public function readMapEnd(); abstract public function readListBegin(&$elemType, &$size); abstract public function readListEnd(); abstract public function readSetBegin(&$elemType, &$size); abstract public function readSetEnd(); abstract public function readBool(&$bool); abstract public function readByte(&$byte); abstract public function readI16(&$i16); abstract public function readI32(&$i32); abstract public function readI64(&$i64); abstract public function readDouble(&$dub); abstract public function readString(&$str); /** * The skip function is a utility to parse over unrecognized date without * causing corruption. * * @param TType $type What type is it */ public function skip($type) { switch ($type) { case TType::BOOL: return $this->readBool($bool); case TType::BYTE: return $this->readByte($byte); case TType::I16: return $this->readI16($i16); case TType::I32: return $this->readI32($i32); case TType::I64: return $this->readI64($i64); case TType::DOUBLE: return $this->readDouble($dub); case TType::STRING: return $this->readString($str); case TType::STRUCT: $result = $this->readStructBegin($name); while (true) { $result += $this->readFieldBegin($name, $ftype, $fid); if ($ftype == TType::STOP) { break; } $result += $this->skip($ftype); $result += $this->readFieldEnd(); } $result += $this->readStructEnd(); return $result; case TType::MAP: $result = $this->readMapBegin($keyType, $valType, $size); for ($i = 0; $i < $size; $i++) { $result += $this->skip($keyType); $result += $this->skip($valType); } $result += $this->readMapEnd(); return $result; case TType::SET: $result = $this->readSetBegin($elemType, $size); for ($i = 0; $i < $size; $i++) { $result += $this->skip($elemType); } $result += $this->readSetEnd(); return $result; case TType::LST: $result = $this->readListBegin($elemType, $size); for ($i = 0; $i < $size; $i++) { $result += $this->skip($elemType); } $result += $this->readListEnd(); return $result; default: throw new TProtocolException( 'Unknown field type: ' . $type, TProtocolException::INVALID_DATA ); } } /** * Utility for skipping binary data * * @param TTransport $itrans TTransport object * @param int $type Field type */ public static function skipBinary($itrans, $type) { switch ($type) { case TType::BOOL: return $itrans->readAll(1); case TType::BYTE: return $itrans->readAll(1); case TType::I16: return $itrans->readAll(2); case TType::I32: return $itrans->readAll(4); case TType::I64: return $itrans->readAll(8); case TType::DOUBLE: return $itrans->readAll(8); case TType::STRING: $len = unpack('N', $itrans->readAll(4)); $len = $len[1]; if ($len > 0x7fffffff) { $len = 0 - (($len - 1) ^ 0xffffffff); } return 4 + $itrans->readAll($len); case TType::STRUCT: $result = 0; while (true) { $ftype = 0; $fid = 0; $data = $itrans->readAll(1); $arr = unpack('c', $data); $ftype = $arr[1]; if ($ftype == TType::STOP) { break; } // I16 field id $result += $itrans->readAll(2); $result += self::skipBinary($itrans, $ftype); } return $result; case TType::MAP: // Ktype $data = $itrans->readAll(1); $arr = unpack('c', $data); $ktype = $arr[1]; // Vtype $data = $itrans->readAll(1); $arr = unpack('c', $data); $vtype = $arr[1]; // Size $data = $itrans->readAll(4); $arr = unpack('N', $data); $size = $arr[1]; if ($size > 0x7fffffff) { $size = 0 - (($size - 1) ^ 0xffffffff); } $result = 6; for ($i = 0; $i < $size; $i++) { $result += self::skipBinary($itrans, $ktype); $result += self::skipBinary($itrans, $vtype); } return $result; case TType::SET: case TType::LST: // Vtype $data = $itrans->readAll(1); $arr = unpack('c', $data); $vtype = $arr[1]; // Size $data = $itrans->readAll(4); $arr = unpack('N', $data); $size = $arr[1]; if ($size > 0x7fffffff) { $size = 0 - (($size - 1) ^ 0xffffffff); } $result = 5; for ($i = 0; $i < $size; $i++) { $result += self::skipBinary($itrans, $vtype); } return $result; default: throw new TProtocolException( 'Unknown field type: ' . $type, TProtocolException::INVALID_DATA ); } } } thrift-0.19.0/lib/php/lib/Protocol/TMultiplexedProtocol.php0000644000000000000000000000546714303740367023701 0ustar00rootroot00000000000000TMultiplexedProtocol is a protocol-independent concrete decorator * that allows a Thrift client to communicate with a multiplexing Thrift server, * by prepending the service name to the function name during function calls. * * @package Thrift\Protocol */ class TMultiplexedProtocol extends TProtocolDecorator { /** * Separator between service name and function name. * Should be the same as used at multiplexed Thrift server. * * @var string */ const SEPARATOR = ":"; /** * The name of service. * * @var string */ private $serviceName_; /** * Constructor of TMultiplexedProtocol class. * * Wrap the specified protocol, allowing it to be used to communicate with a * multiplexing server. The $serviceName is required as it is * prepended to the message header so that the multiplexing server can broker * the function call to the proper service. * * @param TProtocol $protocol * @param string $serviceName The name of service. */ public function __construct(TProtocol $protocol, $serviceName) { parent::__construct($protocol); $this->serviceName_ = $serviceName; } /** * Writes the message header. * Prepends the service name to the function name, separated by TMultiplexedProtocol::SEPARATOR. * * @param string $name Function name. * @param int $type Message type. * @param int $seqid The sequence id of this message. */ public function writeMessageBegin($name, $type, $seqid) { if ($type == TMessageType::CALL || $type == TMessageType::ONEWAY) { $nameWithService = $this->serviceName_ . self::SEPARATOR . $name; parent::writeMessageBegin($nameWithService, $type, $seqid); } else { parent::writeMessageBegin($name, $type, $seqid); } } } thrift-0.19.0/lib/php/lib/Protocol/TBinaryProtocol.php0000644000000000000000000002505014303740367022617 0ustar00rootroot00000000000000strictRead_ = $strictRead; $this->strictWrite_ = $strictWrite; } public function writeMessageBegin($name, $type, $seqid) { if ($this->strictWrite_) { $version = self::VERSION_1 | $type; return $this->writeI32($version) + $this->writeString($name) + $this->writeI32($seqid); } else { return $this->writeString($name) + $this->writeByte($type) + $this->writeI32($seqid); } } public function writeMessageEnd() { return 0; } public function writeStructBegin($name) { return 0; } public function writeStructEnd() { return 0; } public function writeFieldBegin($fieldName, $fieldType, $fieldId) { return $this->writeByte($fieldType) + $this->writeI16($fieldId); } public function writeFieldEnd() { return 0; } public function writeFieldStop() { return $this->writeByte(TType::STOP); } public function writeMapBegin($keyType, $valType, $size) { return $this->writeByte($keyType) + $this->writeByte($valType) + $this->writeI32($size); } public function writeMapEnd() { return 0; } public function writeListBegin($elemType, $size) { return $this->writeByte($elemType) + $this->writeI32($size); } public function writeListEnd() { return 0; } public function writeSetBegin($elemType, $size) { return $this->writeByte($elemType) + $this->writeI32($size); } public function writeSetEnd() { return 0; } public function writeBool($value) { $data = pack('c', $value ? 1 : 0); $this->trans_->write($data, 1); return 1; } public function writeByte($value) { $data = pack('c', $value); $this->trans_->write($data, 1); return 1; } public function writeI16($value) { $data = pack('n', $value); $this->trans_->write($data, 2); return 2; } public function writeI32($value) { $data = pack('N', $value); $this->trans_->write($data, 4); return 4; } public function writeI64($value) { // If we are on a 32bit architecture we have to explicitly deal with // 64-bit twos-complement arithmetic since PHP wants to treat all ints // as signed and any int over 2^31 - 1 as a float if (PHP_INT_SIZE == 4) { $neg = $value < 0; if ($neg) { $value *= -1; } $hi = (int)($value / 4294967296); $lo = (int)$value; if ($neg) { $hi = ~$hi; $lo = ~$lo; if (($lo & (int)0xffffffff) == (int)0xffffffff) { $lo = 0; $hi++; } else { $lo++; } } $data = pack('N2', $hi, $lo); } else { $hi = $value >> 32; $lo = $value & 0xFFFFFFFF; $data = pack('N2', $hi, $lo); } $this->trans_->write($data, 8); return 8; } public function writeDouble($value) { $data = pack('d', $value); $this->trans_->write(strrev($data), 8); return 8; } public function writeString($value) { $len = TStringFuncFactory::create()->strlen($value); $result = $this->writeI32($len); if ($len) { $this->trans_->write($value, $len); } return $result + $len; } public function readMessageBegin(&$name, &$type, &$seqid) { $result = $this->readI32($sz); if ($sz < 0) { $version = (int)($sz & self::VERSION_MASK); if ($version != (int)self::VERSION_1) { throw new TProtocolException('Bad version identifier: ' . $sz, TProtocolException::BAD_VERSION); } $type = $sz & 0x000000ff; $result += $this->readString($name) + $this->readI32($seqid); } else { if ($this->strictRead_) { throw new TProtocolException( 'No version identifier, old protocol client?', TProtocolException::BAD_VERSION ); } else { // Handle pre-versioned input $name = $this->trans_->readAll($sz); $result += $sz + $this->readByte($type) + $this->readI32($seqid); } } return $result; } public function readMessageEnd() { return 0; } public function readStructBegin(&$name) { $name = ''; return 0; } public function readStructEnd() { return 0; } public function readFieldBegin(&$name, &$fieldType, &$fieldId) { $result = $this->readByte($fieldType); if ($fieldType == TType::STOP) { $fieldId = 0; return $result; } $result += $this->readI16($fieldId); return $result; } public function readFieldEnd() { return 0; } public function readMapBegin(&$keyType, &$valType, &$size) { return $this->readByte($keyType) + $this->readByte($valType) + $this->readI32($size); } public function readMapEnd() { return 0; } public function readListBegin(&$elemType, &$size) { return $this->readByte($elemType) + $this->readI32($size); } public function readListEnd() { return 0; } public function readSetBegin(&$elemType, &$size) { return $this->readByte($elemType) + $this->readI32($size); } public function readSetEnd() { return 0; } public function readBool(&$value) { $data = $this->trans_->readAll(1); $arr = unpack('c', $data); $value = $arr[1] == 1; return 1; } public function readByte(&$value) { $data = $this->trans_->readAll(1); $arr = unpack('c', $data); $value = $arr[1]; return 1; } public function readI16(&$value) { $data = $this->trans_->readAll(2); $arr = unpack('n', $data); $value = $arr[1]; if ($value > 0x7fff) { $value = 0 - (($value - 1) ^ 0xffff); } return 2; } public function readI32(&$value) { $data = $this->trans_->readAll(4); $arr = unpack('N', $data); $value = $arr[1]; if ($value > 0x7fffffff) { $value = 0 - (($value - 1) ^ 0xffffffff); } return 4; } public function readI64(&$value) { $data = $this->trans_->readAll(8); $arr = unpack('N2', $data); // If we are on a 32bit architecture we have to explicitly deal with // 64-bit twos-complement arithmetic since PHP wants to treat all ints // as signed and any int over 2^31 - 1 as a float if (PHP_INT_SIZE == 4) { $hi = $arr[1]; $lo = $arr[2]; $isNeg = $hi < 0; // Check for a negative if ($isNeg) { $hi = ~$hi & (int)0xffffffff; $lo = ~$lo & (int)0xffffffff; if ($lo == (int)0xffffffff) { $hi++; $lo = 0; } else { $lo++; } } // Force 32bit words in excess of 2G to pe positive - we deal wigh sign // explicitly below if ($hi & (int)0x80000000) { $hi &= (int)0x7fffffff; $hi += 0x80000000; } if ($lo & (int)0x80000000) { $lo &= (int)0x7fffffff; $lo += 0x80000000; } $value = $hi * 4294967296 + $lo; if ($isNeg) { $value = 0 - $value; } } else { // Upcast negatives in LSB bit if ($arr[2] & 0x80000000) { $arr[2] = $arr[2] & 0xffffffff; } // Check for a negative if ($arr[1] & 0x80000000) { $arr[1] = $arr[1] & 0xffffffff; $arr[1] = $arr[1] ^ 0xffffffff; $arr[2] = $arr[2] ^ 0xffffffff; $value = 0 - $arr[1] * 4294967296 - $arr[2] - 1; } else { $value = $arr[1] * 4294967296 + $arr[2]; } } return 8; } public function readDouble(&$value) { $data = strrev($this->trans_->readAll(8)); $arr = unpack('d', $data); $value = $arr[1]; return 8; } public function readString(&$value) { $result = $this->readI32($len); if ($len) { $value = $this->trans_->readAll($len); } else { $value = ''; } return $result + $len; } } thrift-0.19.0/lib/php/lib/Protocol/TCompactProtocol.php0000644000000000000000000004700714303740367022767 0ustar00rootroot00000000000000 TCompactProtocol::COMPACT_STOP, TType::BOOL => TCompactProtocol::COMPACT_TRUE, // used for collection TType::BYTE => TCompactProtocol::COMPACT_BYTE, TType::I16 => TCompactProtocol::COMPACT_I16, TType::I32 => TCompactProtocol::COMPACT_I32, TType::I64 => TCompactProtocol::COMPACT_I64, TType::DOUBLE => TCompactProtocol::COMPACT_DOUBLE, TType::STRING => TCompactProtocol::COMPACT_BINARY, TType::STRUCT => TCompactProtocol::COMPACT_STRUCT, TType::LST => TCompactProtocol::COMPACT_LIST, TType::SET => TCompactProtocol::COMPACT_SET, TType::MAP => TCompactProtocol::COMPACT_MAP, ); protected static $ttypes = array( TCompactProtocol::COMPACT_STOP => TType::STOP, TCompactProtocol::COMPACT_TRUE => TType::BOOL, // used for collection TCompactProtocol::COMPACT_FALSE => TType::BOOL, TCompactProtocol::COMPACT_BYTE => TType::BYTE, TCompactProtocol::COMPACT_I16 => TType::I16, TCompactProtocol::COMPACT_I32 => TType::I32, TCompactProtocol::COMPACT_I64 => TType::I64, TCompactProtocol::COMPACT_DOUBLE => TType::DOUBLE, TCompactProtocol::COMPACT_BINARY => TType::STRING, TCompactProtocol::COMPACT_STRUCT => TType::STRUCT, TCompactProtocol::COMPACT_LIST => TType::LST, TCompactProtocol::COMPACT_SET => TType::SET, TCompactProtocol::COMPACT_MAP => TType::MAP, ); protected $state = TCompactProtocol::STATE_CLEAR; protected $lastFid = 0; protected $boolFid = null; protected $boolValue = null; protected $structs = array(); protected $containers = array(); // Some varint / zigzag helper methods public function toZigZag($n, $bits) { return ($n << 1) ^ ($n >> ($bits - 1)); } public function fromZigZag($n) { return ($n >> 1) ^ -($n & 1); } public function getVarint($data) { $out = ""; while (true) { if (($data & ~0x7f) === 0) { $out .= chr($data); break; } else { $out .= chr(($data & 0xff) | 0x80); $data = $data >> 7; } } return $out; } public function writeVarint($data) { $out = $this->getVarint($data); $result = TStringFuncFactory::create()->strlen($out); $this->trans_->write($out, $result); return $result; } public function readVarint(&$result) { $idx = 0; $shift = 0; $result = 0; while (true) { $x = $this->trans_->readAll(1); $arr = unpack('C', $x); $byte = $arr[1]; $idx += 1; $result |= ($byte & 0x7f) << $shift; if (($byte >> 7) === 0) { return $idx; } $shift += 7; } return $idx; } public function __construct($trans) { parent::__construct($trans); } public function writeMessageBegin($name, $type, $seqid) { $written = $this->writeUByte(TCompactProtocol::PROTOCOL_ID) + $this->writeUByte(TCompactProtocol::VERSION | ($type << TCompactProtocol::TYPE_SHIFT_AMOUNT)) + $this->writeVarint($seqid) + $this->writeString($name); $this->state = TCompactProtocol::STATE_VALUE_WRITE; return $written; } public function writeMessageEnd() { $this->state = TCompactProtocol::STATE_CLEAR; return 0; } public function writeStructBegin($name) { $this->structs[] = array($this->state, $this->lastFid); $this->state = TCompactProtocol::STATE_FIELD_WRITE; $this->lastFid = 0; return 0; } public function writeStructEnd() { $old_values = array_pop($this->structs); $this->state = $old_values[0]; $this->lastFid = $old_values[1]; return 0; } public function writeFieldStop() { return $this->writeByte(0); } public function writeFieldHeader($type, $fid) { $written = 0; $delta = $fid - $this->lastFid; if (0 < $delta && $delta <= 15) { $written = $this->writeUByte(($delta << 4) | $type); } else { $written = $this->writeByte($type) + $this->writeI16($fid); } $this->lastFid = $fid; return $written; } public function writeFieldBegin($field_name, $field_type, $field_id) { if ($field_type == TTYPE::BOOL) { $this->state = TCompactProtocol::STATE_BOOL_WRITE; $this->boolFid = $field_id; return 0; } else { $this->state = TCompactProtocol::STATE_VALUE_WRITE; return $this->writeFieldHeader(self::$ctypes[$field_type], $field_id); } } public function writeFieldEnd() { $this->state = TCompactProtocol::STATE_FIELD_WRITE; return 0; } public function writeCollectionBegin($etype, $size) { $written = 0; if ($size <= 14) { $written = $this->writeUByte($size << 4 | self::$ctypes[$etype]); } else { $written = $this->writeUByte(0xf0 | self::$ctypes[$etype]) + $this->writeVarint($size); } $this->containers[] = $this->state; $this->state = TCompactProtocol::STATE_CONTAINER_WRITE; return $written; } public function writeMapBegin($key_type, $val_type, $size) { $written = 0; if ($size == 0) { $written = $this->writeByte(0); } else { $written = $this->writeVarint($size) + $this->writeUByte(self::$ctypes[$key_type] << 4 | self::$ctypes[$val_type]); } $this->containers[] = $this->state; return $written; } public function writeCollectionEnd() { $this->state = array_pop($this->containers); return 0; } public function writeMapEnd() { return $this->writeCollectionEnd(); } public function writeListBegin($elem_type, $size) { return $this->writeCollectionBegin($elem_type, $size); } public function writeListEnd() { return $this->writeCollectionEnd(); } public function writeSetBegin($elem_type, $size) { return $this->writeCollectionBegin($elem_type, $size); } public function writeSetEnd() { return $this->writeCollectionEnd(); } public function writeBool($value) { if ($this->state == TCompactProtocol::STATE_BOOL_WRITE) { $ctype = TCompactProtocol::COMPACT_FALSE; if ($value) { $ctype = TCompactProtocol::COMPACT_TRUE; } return $this->writeFieldHeader($ctype, $this->boolFid); } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_WRITE) { return $this->writeByte($value ? 1 : 0); } else { throw new TProtocolException('Invalid state in compact protocol'); } } public function writeByte($value) { $data = pack('c', $value); $this->trans_->write($data, 1); return 1; } public function writeUByte($byte) { $this->trans_->write(pack('C', $byte), 1); return 1; } public function writeI16($value) { $thing = $this->toZigZag($value, 16); return $this->writeVarint($thing); } public function writeI32($value) { $thing = $this->toZigZag($value, 32); return $this->writeVarint($thing); } public function writeDouble($value) { $data = pack('d', $value); $this->trans_->write($data, 8); return 8; } public function writeString($value) { $len = TStringFuncFactory::create()->strlen($value); $result = $this->writeVarint($len); if ($len) { $this->trans_->write($value, $len); } return $result + $len; } public function readFieldBegin(&$name, &$field_type, &$field_id) { $result = $this->readUByte($compact_type_and_delta); $compact_type = $compact_type_and_delta & 0x0f; if ($compact_type == TType::STOP) { $field_type = $compact_type; $field_id = 0; return $result; } $delta = $compact_type_and_delta >> 4; if ($delta == 0) { $result += $this->readI16($field_id); } else { $field_id = $this->lastFid + $delta; } $this->lastFid = $field_id; $field_type = $this->getTType($compact_type); if ($compact_type == TCompactProtocol::COMPACT_TRUE) { $this->state = TCompactProtocol::STATE_BOOL_READ; $this->boolValue = true; } elseif ($compact_type == TCompactProtocol::COMPACT_FALSE) { $this->state = TCompactProtocol::STATE_BOOL_READ; $this->boolValue = false; } else { $this->state = TCompactProtocol::STATE_VALUE_READ; } return $result; } public function readFieldEnd() { $this->state = TCompactProtocol::STATE_FIELD_READ; return 0; } public function readUByte(&$value) { $data = $this->trans_->readAll(1); $arr = unpack('C', $data); $value = $arr[1]; return 1; } public function readByte(&$value) { $data = $this->trans_->readAll(1); $arr = unpack('c', $data); $value = $arr[1]; return 1; } public function readZigZag(&$value) { $result = $this->readVarint($value); $value = $this->fromZigZag($value); return $result; } public function readMessageBegin(&$name, &$type, &$seqid) { $protoId = 0; $result = $this->readUByte($protoId); if ($protoId != TCompactProtocol::PROTOCOL_ID) { throw new TProtocolException('Bad protocol id in TCompact message'); } $verType = 0; $result += $this->readUByte($verType); $type = ($verType >> TCompactProtocol::TYPE_SHIFT_AMOUNT) & TCompactProtocol::TYPE_BITS; $version = $verType & TCompactProtocol::VERSION_MASK; if ($version != TCompactProtocol::VERSION) { throw new TProtocolException('Bad version in TCompact message'); } $result += $this->readVarint($seqid); $result += $this->readString($name); return $result; } public function readMessageEnd() { return 0; } public function readStructBegin(&$name) { $name = ''; // unused $this->structs[] = array($this->state, $this->lastFid); $this->state = TCompactProtocol::STATE_FIELD_READ; $this->lastFid = 0; return 0; } public function readStructEnd() { $last = array_pop($this->structs); $this->state = $last[0]; $this->lastFid = $last[1]; return 0; } public function readCollectionBegin(&$type, &$size) { $sizeType = 0; $result = $this->readUByte($sizeType); $size = $sizeType >> 4; $type = $this->getTType($sizeType); if ($size == 15) { $result += $this->readVarint($size); } $this->containers[] = $this->state; $this->state = TCompactProtocol::STATE_CONTAINER_READ; return $result; } public function readMapBegin(&$key_type, &$val_type, &$size) { $result = $this->readVarint($size); $types = 0; if ($size > 0) { $result += $this->readUByte($types); } $val_type = $this->getTType($types); $key_type = $this->getTType($types >> 4); $this->containers[] = $this->state; $this->state = TCompactProtocol::STATE_CONTAINER_READ; return $result; } public function readCollectionEnd() { $this->state = array_pop($this->containers); return 0; } public function readMapEnd() { return $this->readCollectionEnd(); } public function readListBegin(&$elem_type, &$size) { return $this->readCollectionBegin($elem_type, $size); } public function readListEnd() { return $this->readCollectionEnd(); } public function readSetBegin(&$elem_type, &$size) { return $this->readCollectionBegin($elem_type, $size); } public function readSetEnd() { return $this->readCollectionEnd(); } public function readBool(&$value) { if ($this->state == TCompactProtocol::STATE_BOOL_READ) { $value = $this->boolValue; return 0; } elseif ($this->state == TCompactProtocol::STATE_CONTAINER_READ) { return $this->readByte($value); } else { throw new TProtocolException('Invalid state in compact protocol'); } } public function readI16(&$value) { return $this->readZigZag($value); } public function readI32(&$value) { return $this->readZigZag($value); } public function readDouble(&$value) { $data = $this->trans_->readAll(8); $arr = unpack('d', $data); $value = $arr[1]; return 8; } public function readString(&$value) { $result = $this->readVarint($len); if ($len) { $value = $this->trans_->readAll($len); } else { $value = ''; } return $result + $len; } public function getTType($byte) { return self::$ttypes[$byte & 0x0f]; } // If we are on a 32bit architecture we have to explicitly deal with // 64-bit twos-complement arithmetic since PHP wants to treat all ints // as signed and any int over 2^31 - 1 as a float // Read and write I64 as two 32 bit numbers $hi and $lo public function readI64(&$value) { // Read varint from wire $hi = 0; $lo = 0; $idx = 0; $shift = 0; while (true) { $x = $this->trans_->readAll(1); $arr = unpack('C', $x); $byte = $arr[1]; $idx += 1; // Shift hi and lo together. if ($shift < 28) { $lo |= (($byte & 0x7f) << $shift); } elseif ($shift == 28) { $lo |= (($byte & 0x0f) << 28); $hi |= (($byte & 0x70) >> 4); } else { $hi |= (($byte & 0x7f) << ($shift - 32)); } if (($byte >> 7) === 0) { break; } $shift += 7; } // Now, unzig it. $xorer = 0; if ($lo & 1) { $xorer = 0xffffffff; } $lo = ($lo >> 1) & 0x7fffffff; $lo = $lo | (($hi & 1) << 31); $hi = ($hi >> 1) ^ $xorer; $lo = $lo ^ $xorer; // Now put $hi and $lo back together $isNeg = $hi < 0 || $hi & 0x80000000; // Check for a negative if ($isNeg) { $hi = ~$hi & (int)0xffffffff; $lo = ~$lo & (int)0xffffffff; if ($lo == (int)0xffffffff) { $hi++; $lo = 0; } else { $lo++; } } // Force 32bit words in excess of 2G to be positive - we deal with sign // explicitly below if ($hi & (int)0x80000000) { $hi &= (int)0x7fffffff; $hi += 0x80000000; } if ($lo & (int)0x80000000) { $lo &= (int)0x7fffffff; $lo += 0x80000000; } // Create as negative value first, since we can store -2^63 but not 2^63 $value = -$hi * 4294967296 - $lo; if (!$isNeg) { $value = -$value; } return $idx; } public function writeI64($value) { // If we are in an I32 range, use the easy method below. if (($value > 4294967296) || ($value < -4294967296)) { // Convert $value to $hi and $lo $neg = $value < 0; if ($neg) { $value *= -1; } $hi = (int)$value >> 32; $lo = (int)$value & 0xffffffff; if ($neg) { $hi = ~$hi; $lo = ~$lo; if (($lo & (int)0xffffffff) == (int)0xffffffff) { $lo = 0; $hi++; } else { $lo++; } } // Now do the zigging and zagging. $xorer = 0; if ($neg) { $xorer = 0xffffffff; } $lowbit = ($lo >> 31) & 1; $hi = ($hi << 1) | $lowbit; $lo = ($lo << 1); $lo = ($lo ^ $xorer) & 0xffffffff; $hi = ($hi ^ $xorer) & 0xffffffff; // now write out the varint, ensuring we shift both hi and lo $out = ""; while (true) { if (($lo & ~0x7f) === 0 && $hi === 0) { $out .= chr($lo); break; } else { $out .= chr(($lo & 0xff) | 0x80); $lo = $lo >> 7; $lo = $lo | ($hi << 25); $hi = $hi >> 7; // Right shift carries sign, but we don't want it to. $hi = $hi & (127 << 25); } } $ret = TStringFuncFactory::create()->strlen($out); $this->trans_->write($out, $ret); return $ret; } else { return $this->writeVarint($this->toZigZag($value, 64)); } } } thrift-0.19.0/lib/php/lib/Protocol/JSON/0000777000000000000000000000000014303740367017567 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Protocol/JSON/BaseContext.php0000644000000000000000000000202414303740367022511 0ustar00rootroot00000000000000p_ = $p; } public function read() { if ($this->hasData_) { $this->hasData_ = false; } else { $this->data_ = $this->p_->getTransport()->readAll(1); } return substr($this->data_, 0, 1); } public function peek() { if (!$this->hasData_) { $this->data_ = $this->p_->getTransport()->readAll(1); } $this->hasData_ = true; return substr($this->data_, 0, 1); } } thrift-0.19.0/lib/php/lib/Protocol/JSON/PairContext.php0000644000000000000000000000342314303740367022536 0ustar00rootroot00000000000000p_ = $p; } public function write() { if ($this->first_) { $this->first_ = false; $this->colon_ = true; } else { $this->p_->getTransport()->write($this->colon_ ? TJSONProtocol::COLON : TJSONProtocol::COMMA); $this->colon_ = !$this->colon_; } } public function read() { if ($this->first_) { $this->first_ = false; $this->colon_ = true; } else { $this->p_->readJSONSyntaxChar($this->colon_ ? TJSONProtocol::COLON : TJSONProtocol::COMMA); $this->colon_ = !$this->colon_; } } public function escapeNum() { return $this->colon_; } } thrift-0.19.0/lib/php/lib/Protocol/JSON/ListContext.php0000644000000000000000000000267314303740367022564 0ustar00rootroot00000000000000p_ = $p; } public function write() { if ($this->first_) { $this->first_ = false; } else { $this->p_->getTransport()->write(TJSONProtocol::COMMA); } } public function read() { if ($this->first_) { $this->first_ = false; } else { $this->p_->readJSONSyntaxChar(TJSONProtocol::COMMA); } } } thrift-0.19.0/lib/php/lib/Protocol/TJSONProtocol.php0000644000000000000000000005107314303740367022150 0ustar00rootroot00000000000000 1) { switch (substr($name, 0, 1)) { case 'd': $result = TType::DOUBLE; break; case 'i': switch (substr($name, 1, 1)) { case '8': $result = TType::BYTE; break; case '1': $result = TType::I16; break; case '3': $result = TType::I32; break; case '6': $result = TType::I64; break; } break; case 'l': $result = TType::LST; break; case 'm': $result = TType::MAP; break; case 'r': $result = TType::STRUCT; break; case 's': if (substr($name, 1, 1) == 't') { $result = TType::STRING; } elseif (substr($name, 1, 1) == 'e') { $result = TType::SET; } break; case 't': $result = TType::BOOL; break; } } if ($result == TType::STOP) { throw new TProtocolException("Unrecognized type", TProtocolException::INVALID_DATA); } return $result; } public $contextStack_ = array(); public $context_; public $reader_; private function pushContext($c) { array_push($this->contextStack_, $this->context_); $this->context_ = $c; } private function popContext() { $this->context_ = array_pop($this->contextStack_); } public function __construct($trans) { parent::__construct($trans); $this->context_ = new BaseContext(); $this->reader_ = new LookaheadReader($this); } public function reset() { $this->contextStack_ = array(); $this->context_ = new BaseContext(); $this->reader_ = new LookaheadReader($this); } private $tmpbuf_ = array(4); public function readJSONSyntaxChar($b) { $ch = $this->reader_->read(); if (substr($ch, 0, 1) != $b) { throw new TProtocolException("Unexpected character: " . $ch, TProtocolException::INVALID_DATA); } } private function hexVal($s) { for ($i = 0; $i < strlen($s); $i++) { $ch = substr($s, $i, 1); if (!($ch >= "a" && $ch <= "f") && !($ch >= "0" && $ch <= "9")) { throw new TProtocolException("Expected hex character " . $ch, TProtocolException::INVALID_DATA); } } return hexdec($s); } private function hexChar($val) { return dechex($val); } private function hasJSONUnescapedUnicode() { if (PHP_MAJOR_VERSION > 5 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4)) { return true; } return false; } private function unescapedUnicode($str) { if ($this->hasJSONUnescapedUnicode()) { return json_encode($str, JSON_UNESCAPED_UNICODE); } $json = json_encode($str); /* * Unescaped character outside the Basic Multilingual Plane * High surrogate: 0xD800 - 0xDBFF * Low surrogate: 0xDC00 - 0xDFFF */ $json = preg_replace_callback( '/\\\\u(d[89ab][0-9a-f]{2})\\\\u(d[cdef][0-9a-f]{2})/i', function ($matches) { return mb_convert_encoding(pack('H*', $matches[1] . $matches[2]), 'UTF-8', 'UTF-16BE'); }, $json ); /* * Unescaped characters within the Basic Multilingual Plane */ $json = preg_replace_callback( '/\\\\u([0-9a-f]{4})/i', function ($matches) { return mb_convert_encoding(pack('H*', $matches[1]), 'UTF-8', 'UTF-16BE'); }, $json ); return $json; } private function writeJSONString($b) { $this->context_->write(); if (is_numeric($b) && $this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); } $this->trans_->write($this->unescapedUnicode($b)); if (is_numeric($b) && $this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); } } private function writeJSONInteger($num) { $this->context_->write(); if ($this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); } $this->trans_->write($num); if ($this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); } } private function writeJSONDouble($num) { $this->context_->write(); if ($this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); } $this->trans_->write(json_encode($num)); if ($this->context_->escapeNum()) { $this->trans_->write(self::QUOTE); } } private function writeJSONBase64($data) { $this->context_->write(); $this->trans_->write(self::QUOTE); $this->trans_->write(json_encode(base64_encode($data))); $this->trans_->write(self::QUOTE); } private function writeJSONObjectStart() { $this->context_->write(); $this->trans_->write(self::LBRACE); $this->pushContext(new PairContext($this)); } private function writeJSONObjectEnd() { $this->popContext(); $this->trans_->write(self::RBRACE); } private function writeJSONArrayStart() { $this->context_->write(); $this->trans_->write(self::LBRACKET); $this->pushContext(new ListContext($this)); } private function writeJSONArrayEnd() { $this->popContext(); $this->trans_->write(self::RBRACKET); } private function readJSONString($skipContext) { if (!$skipContext) { $this->context_->read(); } $jsonString = ''; $lastChar = null; while (true) { $ch = $this->reader_->read(); $jsonString .= $ch; if ($ch == self::QUOTE && $lastChar !== null && $lastChar !== self::ESCSEQ) { break; } if ($ch == self::ESCSEQ && $lastChar == self::ESCSEQ) { $lastChar = self::DOUBLEESC; } else { $lastChar = $ch; } } return json_decode($jsonString); } private function isJSONNumeric($b) { switch ($b) { case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'E': case 'e': return true; } return false; } private function readJSONNumericChars() { $strbld = array(); while (true) { $ch = $this->reader_->peek(); if (!$this->isJSONNumeric($ch)) { break; } $strbld[] = $this->reader_->read(); } return implode("", $strbld); } private function readJSONInteger() { $this->context_->read(); if ($this->context_->escapeNum()) { $this->readJSONSyntaxChar(self::QUOTE); } $str = $this->readJSONNumericChars(); if ($this->context_->escapeNum()) { $this->readJSONSyntaxChar(self::QUOTE); } if (!is_numeric($str)) { throw new TProtocolException("Invalid data in numeric: " . $str, TProtocolException::INVALID_DATA); } return intval($str); } /** * Identical to readJSONInteger but without the final cast. * Needed for proper handling of i64 on 32 bit machines. Why a * separate function? So we don't have to force the rest of the * use cases through the extra conditional. */ private function readJSONIntegerAsString() { $this->context_->read(); if ($this->context_->escapeNum()) { $this->readJSONSyntaxChar(self::QUOTE); } $str = $this->readJSONNumericChars(); if ($this->context_->escapeNum()) { $this->readJSONSyntaxChar(self::QUOTE); } if (!is_numeric($str)) { throw new TProtocolException("Invalid data in numeric: " . $str, TProtocolException::INVALID_DATA); } return $str; } private function readJSONDouble() { $this->context_->read(); if (substr($this->reader_->peek(), 0, 1) == self::QUOTE) { $arr = $this->readJSONString(true); if ($arr == "NaN") { return NAN; } elseif ($arr == "Infinity") { return INF; } elseif (!$this->context_->escapeNum()) { throw new TProtocolException( "Numeric data unexpectedly quoted " . $arr, TProtocolException::INVALID_DATA ); } return floatval($arr); } else { if ($this->context_->escapeNum()) { $this->readJSONSyntaxChar(self::QUOTE); } return floatval($this->readJSONNumericChars()); } } private function readJSONBase64() { $arr = $this->readJSONString(false); $data = base64_decode($arr, true); if ($data === false) { throw new TProtocolException("Invalid base64 data " . $arr, TProtocolException::INVALID_DATA); } return $data; } private function readJSONObjectStart() { $this->context_->read(); $this->readJSONSyntaxChar(self::LBRACE); $this->pushContext(new PairContext($this)); } private function readJSONObjectEnd() { $this->readJSONSyntaxChar(self::RBRACE); $this->popContext(); } private function readJSONArrayStart() { $this->context_->read(); $this->readJSONSyntaxChar(self::LBRACKET); $this->pushContext(new ListContext($this)); } private function readJSONArrayEnd() { $this->readJSONSyntaxChar(self::RBRACKET); $this->popContext(); } /** * Writes the message header * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @param int $seqid The sequence id of this message */ public function writeMessageBegin($name, $type, $seqid) { $this->writeJSONArrayStart(); $this->writeJSONInteger(self::VERSION); $this->writeJSONString($name); $this->writeJSONInteger($type); $this->writeJSONInteger($seqid); } /** * Close the message */ public function writeMessageEnd() { $this->writeJSONArrayEnd(); } /** * Writes a struct header. * * @param string $name Struct name * @throws TException on write error * @return int How many bytes written */ public function writeStructBegin($name) { $this->writeJSONObjectStart(); } /** * Close a struct. * * @throws TException on write error * @return int How many bytes written */ public function writeStructEnd() { $this->writeJSONObjectEnd(); } public function writeFieldBegin($fieldName, $fieldType, $fieldId) { $this->writeJSONInteger($fieldId); $this->writeJSONObjectStart(); $this->writeJSONString($this->getTypeNameForTypeID($fieldType)); } public function writeFieldEnd() { $this->writeJsonObjectEnd(); } public function writeFieldStop() { } public function writeMapBegin($keyType, $valType, $size) { $this->writeJSONArrayStart(); $this->writeJSONString($this->getTypeNameForTypeID($keyType)); $this->writeJSONString($this->getTypeNameForTypeID($valType)); $this->writeJSONInteger($size); $this->writeJSONObjectStart(); } public function writeMapEnd() { $this->writeJSONObjectEnd(); $this->writeJSONArrayEnd(); } public function writeListBegin($elemType, $size) { $this->writeJSONArrayStart(); $this->writeJSONString($this->getTypeNameForTypeID($elemType)); $this->writeJSONInteger($size); } public function writeListEnd() { $this->writeJSONArrayEnd(); } public function writeSetBegin($elemType, $size) { $this->writeJSONArrayStart(); $this->writeJSONString($this->getTypeNameForTypeID($elemType)); $this->writeJSONInteger($size); } public function writeSetEnd() { $this->writeJSONArrayEnd(); } public function writeBool($bool) { $this->writeJSONInteger($bool ? 1 : 0); } public function writeByte($byte) { $this->writeJSONInteger($byte); } public function writeI16($i16) { $this->writeJSONInteger($i16); } public function writeI32($i32) { $this->writeJSONInteger($i32); } public function writeI64($i64) { $this->writeJSONInteger($i64); } public function writeDouble($dub) { $this->writeJSONDouble($dub); } public function writeString($str) { $this->writeJSONString($str); } /** * Reads the message header * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @parem int $seqid The sequence id of this message */ public function readMessageBegin(&$name, &$type, &$seqid) { $this->readJSONArrayStart(); if ($this->readJSONInteger() != self::VERSION) { throw new TProtocolException("Message contained bad version", TProtocolException::BAD_VERSION); } $name = $this->readJSONString(false); $type = $this->readJSONInteger(); $seqid = $this->readJSONInteger(); return true; } /** * Read the close of message */ public function readMessageEnd() { $this->readJSONArrayEnd(); } public function readStructBegin(&$name) { $this->readJSONObjectStart(); return 0; } public function readStructEnd() { $this->readJSONObjectEnd(); } public function readFieldBegin(&$name, &$fieldType, &$fieldId) { $ch = $this->reader_->peek(); $name = ""; if (substr($ch, 0, 1) == self::RBRACE) { $fieldType = TType::STOP; } else { $fieldId = $this->readJSONInteger(); $this->readJSONObjectStart(); $fieldType = $this->getTypeIDForTypeName($this->readJSONString(false)); } } public function readFieldEnd() { $this->readJSONObjectEnd(); } public function readMapBegin(&$keyType, &$valType, &$size) { $this->readJSONArrayStart(); $keyType = $this->getTypeIDForTypeName($this->readJSONString(false)); $valType = $this->getTypeIDForTypeName($this->readJSONString(false)); $size = $this->readJSONInteger(); $this->readJSONObjectStart(); } public function readMapEnd() { $this->readJSONObjectEnd(); $this->readJSONArrayEnd(); } public function readListBegin(&$elemType, &$size) { $this->readJSONArrayStart(); $elemType = $this->getTypeIDForTypeName($this->readJSONString(false)); $size = $this->readJSONInteger(); return true; } public function readListEnd() { $this->readJSONArrayEnd(); } public function readSetBegin(&$elemType, &$size) { $this->readJSONArrayStart(); $elemType = $this->getTypeIDForTypeName($this->readJSONString(false)); $size = $this->readJSONInteger(); return true; } public function readSetEnd() { $this->readJSONArrayEnd(); } public function readBool(&$bool) { $bool = $this->readJSONInteger() == 0 ? false : true; return true; } public function readByte(&$byte) { $byte = $this->readJSONInteger(); return true; } public function readI16(&$i16) { $i16 = $this->readJSONInteger(); return true; } public function readI32(&$i32) { $i32 = $this->readJSONInteger(); return true; } public function readI64(&$i64) { if (PHP_INT_SIZE === 4) { $i64 = $this->readJSONIntegerAsString(); } else { $i64 = $this->readJSONInteger(); } return true; } public function readDouble(&$dub) { $dub = $this->readJSONDouble(); return true; } public function readString(&$str) { $str = $this->readJSONString(false); return true; } } thrift-0.19.0/lib/php/lib/Protocol/TSimpleJSONProtocol.php0000644000000000000000000002134314303740367023317 0ustar00rootroot00000000000000writeContextStack_[] = $this->writeContext_; $this->writeContext_ = $c; } /** * Pop the last write context off the stack */ protected function popWriteContext() { $this->writeContext_ = array_pop($this->writeContextStack_); } /** * Used to make sure that we are not encountering a map whose keys are containers */ protected function assertContextIsNotMapKey($invalidKeyType) { if ($this->writeContext_->isMapKey()) { throw new CollectionMapKeyException( "Cannot serialize a map with keys that are of type " . $invalidKeyType ); } } private function writeJSONString($b) { $this->writeContext_->write(); $this->trans_->write(json_encode((string)$b)); } private function writeJSONInteger($num) { $isMapKey = $this->writeContext_->isMapKey(); $this->writeContext_->write(); if ($isMapKey) { $this->trans_->write(self::QUOTE); } $this->trans_->write((int)$num); if ($isMapKey) { $this->trans_->write(self::QUOTE); } } private function writeJSONDouble($num) { $isMapKey = $this->writeContext_->isMapKey(); $this->writeContext_->write(); if ($isMapKey) { $this->trans_->write(self::QUOTE); } $this->trans_->write(json_encode((float)$num)); if ($isMapKey) { $this->trans_->write(self::QUOTE); } } /** * Constructor */ public function __construct($trans) { parent::__construct($trans); $this->writeContext_ = new Context(); } /** * Writes the message header * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @param int $seqid The sequence id of this message */ public function writeMessageBegin($name, $type, $seqid) { $this->trans_->write(self::LBRACKET); $this->pushWriteContext(new ListContext($this)); $this->writeJSONString($name); $this->writeJSONInteger($type); $this->writeJSONInteger($seqid); } /** * Close the message */ public function writeMessageEnd() { $this->popWriteContext(); $this->trans_->write(self::RBRACKET); } /** * Writes a struct header. * * @param string $name Struct name */ public function writeStructBegin($name) { $this->writeContext_->write(); $this->trans_->write(self::LBRACE); $this->pushWriteContext(new StructContext($this)); } /** * Close a struct. */ public function writeStructEnd() { $this->popWriteContext(); $this->trans_->write(self::RBRACE); } public function writeFieldBegin($fieldName, $fieldType, $fieldId) { $this->writeJSONString($fieldName); } public function writeFieldEnd() { } public function writeFieldStop() { } public function writeMapBegin($keyType, $valType, $size) { $this->assertContextIsNotMapKey(self::NAME_MAP); $this->writeContext_->write(); $this->trans_->write(self::LBRACE); $this->pushWriteContext(new MapContext($this)); } public function writeMapEnd() { $this->popWriteContext(); $this->trans_->write(self::RBRACE); } public function writeListBegin($elemType, $size) { $this->assertContextIsNotMapKey(self::NAME_LIST); $this->writeContext_->write(); $this->trans_->write(self::LBRACKET); $this->pushWriteContext(new ListContext($this)); // No metadata! } public function writeListEnd() { $this->popWriteContext(); $this->trans_->write(self::RBRACKET); } public function writeSetBegin($elemType, $size) { $this->assertContextIsNotMapKey(self::NAME_SET); $this->writeContext_->write(); $this->trans_->write(self::LBRACKET); $this->pushWriteContext(new ListContext($this)); // No metadata! } public function writeSetEnd() { $this->popWriteContext(); $this->trans_->write(self::RBRACKET); } public function writeBool($bool) { $this->writeJSONInteger($bool ? 1 : 0); } public function writeByte($byte) { $this->writeJSONInteger($byte); } public function writeI16($i16) { $this->writeJSONInteger($i16); } public function writeI32($i32) { $this->writeJSONInteger($i32); } public function writeI64($i64) { $this->writeJSONInteger($i64); } public function writeDouble($dub) { $this->writeJSONDouble($dub); } public function writeString($str) { $this->writeJSONString($str); } /** * Reading methods. * * simplejson is not meant to be read back into thrift * - see http://wiki.apache.org/thrift/ThriftUsageJava * - use JSON instead */ public function readMessageBegin(&$name, &$type, &$seqid) { throw new TException("Not implemented"); } public function readMessageEnd() { throw new TException("Not implemented"); } public function readStructBegin(&$name) { throw new TException("Not implemented"); } public function readStructEnd() { throw new TException("Not implemented"); } public function readFieldBegin(&$name, &$fieldType, &$fieldId) { throw new TException("Not implemented"); } public function readFieldEnd() { throw new TException("Not implemented"); } public function readMapBegin(&$keyType, &$valType, &$size) { throw new TException("Not implemented"); } public function readMapEnd() { throw new TException("Not implemented"); } public function readListBegin(&$elemType, &$size) { throw new TException("Not implemented"); } public function readListEnd() { throw new TException("Not implemented"); } public function readSetBegin(&$elemType, &$size) { throw new TException("Not implemented"); } public function readSetEnd() { throw new TException("Not implemented"); } public function readBool(&$bool) { throw new TException("Not implemented"); } public function readByte(&$byte) { throw new TException("Not implemented"); } public function readI16(&$i16) { throw new TException("Not implemented"); } public function readI32(&$i32) { throw new TException("Not implemented"); } public function readI64(&$i64) { throw new TException("Not implemented"); } public function readDouble(&$dub) { throw new TException("Not implemented"); } public function readString(&$str) { throw new TException("Not implemented"); } } thrift-0.19.0/lib/php/lib/Protocol/TBinaryProtocolAccelerated.php0000644000000000000000000000513214303740367024733 0ustar00rootroot00000000000000strictRead_; } public function isStrictWrite() { return $this->strictWrite_; } } thrift-0.19.0/lib/php/lib/Protocol/TProtocolDecorator.php0000644000000000000000000001637314303740367023325 0ustar00rootroot00000000000000TProtocolDecorator forwards all requests to an enclosed * TProtocol instance, providing a way to author concise * concrete decorator subclasses. While it has no abstract methods, it * is marked abstract as a reminder that by itself, it does not modify * the behaviour of the enclosed TProtocol. * * @package Thrift\Protocol */ abstract class TProtocolDecorator extends TProtocol { /** * Instance of protocol, to which all operations will be forwarded. * * @var TProtocol */ private $concreteProtocol_; /** * Constructor of TProtocolDecorator class. * Encloses the specified protocol. * * @param TProtocol $protocol All operations will be forward to this instance. Must be non-null. */ protected function __construct(TProtocol $protocol) { parent::__construct($protocol->getTransport()); $this->concreteProtocol_ = $protocol; } /** * Writes the message header. * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @param int $seqid The sequence id of this message */ public function writeMessageBegin($name, $type, $seqid) { return $this->concreteProtocol_->writeMessageBegin($name, $type, $seqid); } /** * Closes the message. */ public function writeMessageEnd() { return $this->concreteProtocol_->writeMessageEnd(); } /** * Writes a struct header. * * @param string $name Struct name * * @throws TException on write error * @return int How many bytes written */ public function writeStructBegin($name) { return $this->concreteProtocol_->writeStructBegin($name); } /** * Close a struct. * * @throws TException on write error * @return int How many bytes written */ public function writeStructEnd() { return $this->concreteProtocol_->writeStructEnd(); } public function writeFieldBegin($fieldName, $fieldType, $fieldId) { return $this->concreteProtocol_->writeFieldBegin($fieldName, $fieldType, $fieldId); } public function writeFieldEnd() { return $this->concreteProtocol_->writeFieldEnd(); } public function writeFieldStop() { return $this->concreteProtocol_->writeFieldStop(); } public function writeMapBegin($keyType, $valType, $size) { return $this->concreteProtocol_->writeMapBegin($keyType, $valType, $size); } public function writeMapEnd() { return $this->concreteProtocol_->writeMapEnd(); } public function writeListBegin($elemType, $size) { return $this->concreteProtocol_->writeListBegin($elemType, $size); } public function writeListEnd() { return $this->concreteProtocol_->writeListEnd(); } public function writeSetBegin($elemType, $size) { return $this->concreteProtocol_->writeSetBegin($elemType, $size); } public function writeSetEnd() { return $this->concreteProtocol_->writeSetEnd(); } public function writeBool($bool) { return $this->concreteProtocol_->writeBool($bool); } public function writeByte($byte) { return $this->concreteProtocol_->writeByte($byte); } public function writeI16($i16) { return $this->concreteProtocol_->writeI16($i16); } public function writeI32($i32) { return $this->concreteProtocol_->writeI32($i32); } public function writeI64($i64) { return $this->concreteProtocol_->writeI64($i64); } public function writeDouble($dub) { return $this->concreteProtocol_->writeDouble($dub); } public function writeString($str) { return $this->concreteProtocol_->writeString($str); } /** * Reads the message header * * @param string $name Function name * @param int $type message type TMessageType::CALL or TMessageType::REPLY * @param int $seqid The sequence id of this message */ public function readMessageBegin(&$name, &$type, &$seqid) { return $this->concreteProtocol_->readMessageBegin($name, $type, $seqid); } /** * Read the close of message */ public function readMessageEnd() { return $this->concreteProtocol_->readMessageEnd(); } public function readStructBegin(&$name) { return $this->concreteProtocol_->readStructBegin($name); } public function readStructEnd() { return $this->concreteProtocol_->readStructEnd(); } public function readFieldBegin(&$name, &$fieldType, &$fieldId) { return $this->concreteProtocol_->readFieldBegin($name, $fieldType, $fieldId); } public function readFieldEnd() { return $this->concreteProtocol_->readFieldEnd(); } public function readMapBegin(&$keyType, &$valType, &$size) { $this->concreteProtocol_->readMapBegin($keyType, $valType, $size); } public function readMapEnd() { return $this->concreteProtocol_->readMapEnd(); } public function readListBegin(&$elemType, &$size) { $this->concreteProtocol_->readListBegin($elemType, $size); } public function readListEnd() { return $this->concreteProtocol_->readListEnd(); } public function readSetBegin(&$elemType, &$size) { return $this->concreteProtocol_->readSetBegin($elemType, $size); } public function readSetEnd() { return $this->concreteProtocol_->readSetEnd(); } public function readBool(&$bool) { return $this->concreteProtocol_->readBool($bool); } public function readByte(&$byte) { return $this->concreteProtocol_->readByte($byte); } public function readI16(&$i16) { return $this->concreteProtocol_->readI16($i16); } public function readI32(&$i32) { return $this->concreteProtocol_->readI32($i32); } public function readI64(&$i64) { return $this->concreteProtocol_->readI64($i64); } public function readDouble(&$dub) { return $this->concreteProtocol_->readDouble($dub); } public function readString(&$str) { return $this->concreteProtocol_->readString($str); } } thrift-0.19.0/lib/php/lib/Protocol/SimpleJSON/0000777000000000000000000000000014303740367020741 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Protocol/SimpleJSON/Context.php0000644000000000000000000000175514303740367023102 0ustar00rootroot00000000000000isKey = !$this->isKey; } public function isMapKey() { // we want to coerce map keys to json strings regardless // of their type return $this->isKey; } } thrift-0.19.0/lib/php/lib/Protocol/SimpleJSON/StructContext.php0000644000000000000000000000275014303740367024303 0ustar00rootroot00000000000000p_ = $p; } public function write() { if ($this->first_) { $this->first_ = false; $this->colon_ = true; } else { $this->p_->getTransport()->write( $this->colon_ ? TSimpleJSONProtocol::COLON : TSimpleJSONProtocol::COMMA ); $this->colon_ = !$this->colon_; } } } thrift-0.19.0/lib/php/lib/Protocol/SimpleJSON/ListContext.php0000644000000000000000000000240714303740367023731 0ustar00rootroot00000000000000p_ = $p; } public function write() { if ($this->first_) { $this->first_ = false; } else { $this->p_->getTransport()->write(TSimpleJSONProtocol::COMMA); } } } thrift-0.19.0/lib/php/lib/Serializer/0000777000000000000000000000000014303740367017326 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Serializer/TBinarySerializer.php0000644000000000000000000000627314303740367023445 0ustar00rootroot00000000000000getName(), TMessageType::REPLY, $object, 0, $protocol->isStrictWrite() ); $protocol->readMessageBegin($unused_name, $unused_type, $unused_seqid); } else { $object->write($protocol); } $protocol->getTransport()->flush(); return $transport->getBuffer(); } public static function deserialize($string_object, $class_name, $buffer_size = 8192) { $transport = new TMemoryBuffer(); $protocol = new TBinaryProtocolAccelerated($transport); if (function_exists('thrift_protocol_read_binary')) { // NOTE (t.heintz) TBinaryProtocolAccelerated internally wraps our TMemoryBuffer in a // TBufferedTransport, so we have to retrieve it again or risk losing data when writing // less than 512 bytes to the transport (see the comment there as well). // @see THRIFT-1579 $protocol->writeMessageBegin('', TMessageType::REPLY, 0); $protocolTransport = $protocol->getTransport(); $protocolTransport->write($string_object); $protocolTransport->flush(); return thrift_protocol_read_binary($protocol, $class_name, $protocol->isStrictRead(), $buffer_size); } else { $transport->write($string_object); $object = new $class_name(); $object->read($protocol); return $object; } } } thrift-0.19.0/lib/php/lib/StringFunc/0000777000000000000000000000000014303740367017277 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/StringFunc/Mbstring.php0000644000000000000000000000300314303740367021565 0ustar00rootroot00000000000000strlen($str) - $start; } return mb_substr($str, $start, $length, '8bit'); } public function strlen($str) { return mb_strlen($str, '8bit'); } } thrift-0.19.0/lib/php/lib/StringFunc/TStringFunc.php0000644000000000000000000000170214303740367022212 0ustar00rootroot00000000000000 $fspec) { $var = $fspec['var']; if (isset($vals[$var])) { $this->$var = $vals[$var]; } } } else { parent::__construct((string)$p1, $p2); } } public static $tmethod = array( TType::BOOL => 'Bool', TType::BYTE => 'Byte', TType::I16 => 'I16', TType::I32 => 'I32', TType::I64 => 'I64', TType::DOUBLE => 'Double', TType::STRING => 'String' ); private function _readMap(&$var, $spec, $input) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kread = $vread = null; if (isset(TBase::$tmethod[$ktype])) { $kread = 'read' . TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vread = 'read' . TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $var = array(); $_ktype = $_vtype = $size = 0; $xfer += $input->readMapBegin($_ktype, $_vtype, $size); for ($i = 0; $i < $size; ++$i) { $key = $val = null; if ($kread !== null) { $xfer += $input->$kread($key); } else { switch ($ktype) { case TType::STRUCT: $class = $kspec['class']; $key = new $class(); $xfer += $key->read($input); break; case TType::MAP: $xfer += $this->_readMap($key, $kspec, $input); break; case TType::LST: $xfer += $this->_readList($key, $kspec, $input, false); break; case TType::SET: $xfer += $this->_readList($key, $kspec, $input, true); break; } } if ($vread !== null) { $xfer += $input->$vread($val); } else { switch ($vtype) { case TType::STRUCT: $class = $vspec['class']; $val = new $class(); $xfer += $val->read($input); break; case TType::MAP: $xfer += $this->_readMap($val, $vspec, $input); break; case TType::LST: $xfer += $this->_readList($val, $vspec, $input, false); break; case TType::SET: $xfer += $this->_readList($val, $vspec, $input, true); break; } } $var[$key] = $val; } $xfer += $input->readMapEnd(); return $xfer; } private function _readList(&$var, $spec, $input, $set = false) { $xfer = 0; $etype = $spec['etype']; $eread = $vread = null; if (isset(TBase::$tmethod[$etype])) { $eread = 'read' . TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } $var = array(); $_etype = $size = 0; if ($set) { $xfer += $input->readSetBegin($_etype, $size); } else { $xfer += $input->readListBegin($_etype, $size); } for ($i = 0; $i < $size; ++$i) { $elem = null; if ($eread !== null) { $xfer += $input->$eread($elem); } else { $espec = $spec['elem']; switch ($etype) { case TType::STRUCT: $class = $espec['class']; $elem = new $class(); $xfer += $elem->read($input); break; case TType::MAP: $xfer += $this->_readMap($elem, $espec, $input); break; case TType::LST: $xfer += $this->_readList($elem, $espec, $input, false); break; case TType::SET: $xfer += $this->_readList($elem, $espec, $input, true); break; } } if ($set) { $var[$elem] = true; } else { $var [] = $elem; } } if ($set) { $xfer += $input->readSetEnd(); } else { $xfer += $input->readListEnd(); } return $xfer; } protected function _read($class, $spec, $input) { $xfer = 0; $fname = null; $ftype = 0; $fid = 0; $xfer += $input->readStructBegin($fname); while (true) { $xfer += $input->readFieldBegin($fname, $ftype, $fid); if ($ftype == TType::STOP) { break; } if (isset($spec[$fid])) { $fspec = $spec[$fid]; $var = $fspec['var']; if ($ftype == $fspec['type']) { $xfer = 0; if (isset(TBase::$tmethod[$ftype])) { $func = 'read' . TBase::$tmethod[$ftype]; $xfer += $input->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $class = $fspec['class']; $this->$var = new $class(); $xfer += $this->$var->read($input); break; case TType::MAP: $xfer += $this->_readMap($this->$var, $fspec, $input); break; case TType::LST: $xfer += $this->_readList($this->$var, $fspec, $input, false); break; case TType::SET: $xfer += $this->_readList($this->$var, $fspec, $input, true); break; } } } else { $xfer += $input->skip($ftype); } } else { $xfer += $input->skip($ftype); } $xfer += $input->readFieldEnd(); } $xfer += $input->readStructEnd(); return $xfer; } private function _writeMap($var, $spec, $output) { $xfer = 0; $ktype = $spec['ktype']; $vtype = $spec['vtype']; $kwrite = $vwrite = null; if (isset(TBase::$tmethod[$ktype])) { $kwrite = 'write' . TBase::$tmethod[$ktype]; } else { $kspec = $spec['key']; } if (isset(TBase::$tmethod[$vtype])) { $vwrite = 'write' . TBase::$tmethod[$vtype]; } else { $vspec = $spec['val']; } $xfer += $output->writeMapBegin($ktype, $vtype, count($var)); foreach ($var as $key => $val) { if (isset($kwrite)) { $xfer += $output->$kwrite($key); } else { switch ($ktype) { case TType::STRUCT: $xfer += $key->write($output); break; case TType::MAP: $xfer += $this->_writeMap($key, $kspec, $output); break; case TType::LST: $xfer += $this->_writeList($key, $kspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($key, $kspec, $output, true); break; } } if (isset($vwrite)) { $xfer += $output->$vwrite($val); } else { switch ($vtype) { case TType::STRUCT: $xfer += $val->write($output); break; case TType::MAP: $xfer += $this->_writeMap($val, $vspec, $output); break; case TType::LST: $xfer += $this->_writeList($val, $vspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($val, $vspec, $output, true); break; } } } $xfer += $output->writeMapEnd(); return $xfer; } private function _writeList($var, $spec, $output, $set = false) { $xfer = 0; $etype = $spec['etype']; $ewrite = null; if (isset(TBase::$tmethod[$etype])) { $ewrite = 'write' . TBase::$tmethod[$etype]; } else { $espec = $spec['elem']; } if ($set) { $xfer += $output->writeSetBegin($etype, count($var)); } else { $xfer += $output->writeListBegin($etype, count($var)); } foreach ($var as $key => $val) { $elem = $set ? $key : $val; if (isset($ewrite)) { $xfer += $output->$ewrite($elem); } else { switch ($etype) { case TType::STRUCT: $xfer += $elem->write($output); break; case TType::MAP: $xfer += $this->_writeMap($elem, $espec, $output); break; case TType::LST: $xfer += $this->_writeList($elem, $espec, $output, false); break; case TType::SET: $xfer += $this->_writeList($elem, $espec, $output, true); break; } } } if ($set) { $xfer += $output->writeSetEnd(); } else { $xfer += $output->writeListEnd(); } return $xfer; } protected function _write($class, $spec, $output) { $xfer = 0; $xfer += $output->writeStructBegin($class); foreach ($spec as $fid => $fspec) { $var = $fspec['var']; if ($this->$var !== null) { $ftype = $fspec['type']; $xfer += $output->writeFieldBegin($var, $ftype, $fid); if (isset(TBase::$tmethod[$ftype])) { $func = 'write' . TBase::$tmethod[$ftype]; $xfer += $output->$func($this->$var); } else { switch ($ftype) { case TType::STRUCT: $xfer += $this->$var->write($output); break; case TType::MAP: $xfer += $this->_writeMap($this->$var, $fspec, $output); break; case TType::LST: $xfer += $this->_writeList($this->$var, $fspec, $output, false); break; case TType::SET: $xfer += $this->_writeList($this->$var, $fspec, $output, true); break; } } $xfer += $output->writeFieldEnd(); } } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } } thrift-0.19.0/lib/php/lib/Exception/TApplicationException.php0000644000000000000000000000455614303740367024140 0ustar00rootroot00000000000000 array('var' => 'message', 'type' => TType::STRING), 2 => array('var' => 'code', 'type' => TType::I32)); const UNKNOWN = 0; const UNKNOWN_METHOD = 1; const INVALID_MESSAGE_TYPE = 2; const WRONG_METHOD_NAME = 3; const BAD_SEQUENCE_ID = 4; const MISSING_RESULT = 5; const INTERNAL_ERROR = 6; const PROTOCOL_ERROR = 7; const INVALID_TRANSFORM = 8; const INVALID_PROTOCOL = 9; const UNSUPPORTED_CLIENT_TYPE = 10; public function __construct($message = null, $code = 0) { parent::__construct($message, $code); } public function read($output) { return $this->_read('TApplicationException', self::$_TSPEC, $output); } public function write($output) { $xfer = 0; $xfer += $output->writeStructBegin('TApplicationException'); if ($message = $this->getMessage()) { $xfer += $output->writeFieldBegin('message', TType::STRING, 1); $xfer += $output->writeString($message); $xfer += $output->writeFieldEnd(); } if ($code = $this->getCode()) { $xfer += $output->writeFieldBegin('type', TType::I32, 2); $xfer += $output->writeI32($code); $xfer += $output->writeFieldEnd(); } $xfer += $output->writeFieldStop(); $xfer += $output->writeStructEnd(); return $xfer; } } thrift-0.19.0/lib/php/lib/Exception/TProtocolException.php0000644000000000000000000000265714303740367023476 0ustar00rootroot00000000000000strictRead_ = $strictRead; $this->strictWrite_ = $strictWrite; } public function getProtocol($trans) { return new TBinaryProtocol($trans, $this->strictRead_, $this->strictWrite_); } } thrift-0.19.0/lib/php/lib/Factory/TProtocolFactory.php0000644000000000000000000000215314303740367022607 0ustar00rootroot00000000000000getSSLHost($host); parent::__construct($ssl_host, $port); $this->context_ = $context; } public function getSSLHost($host) { $transport_protocol_loc = strpos($host, "://"); if ($transport_protocol_loc === false) { $host = 'ssl://' . $host; } return $host; } /** * Opens a new socket server handle * * @return void */ public function listen() { $this->listener_ = @stream_socket_server( $this->host_ . ':' . $this->port_, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $this->context_ ); } /** * Implementation of accept. If not client is accepted in the given time * * @return TSocket */ protected function acceptImpl() { $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0); if (!$handle) { return null; } $socket = new TSSLSocket(); $socket->setHandle($handle); return $socket; } } thrift-0.19.0/lib/php/lib/Server/TServerTransport.php0000644000000000000000000000177114303740367022505 0ustar00rootroot00000000000000acceptImpl(); if ($transport == null) { throw new TTransportException("accept() may not return NULL"); } return $transport; } } thrift-0.19.0/lib/php/lib/Server/TServerSocket.php0000644000000000000000000000537514303740367021745 0ustar00rootroot00000000000000host_ = $host; $this->port_ = $port; } /** * Sets the accept timeout * * @param int $acceptTimeout * @return void */ public function setAcceptTimeout($acceptTimeout) { $this->acceptTimeout_ = $acceptTimeout; } /** * Opens a new socket server handle * * @return void */ public function listen() { $this->listener_ = stream_socket_server('tcp://' . $this->host_ . ':' . $this->port_); } /** * Closes the socket server handle * * @return void */ public function close() { @fclose($this->listener_); $this->listener_ = null; } /** * Implementation of accept. If not client is accepted in the given time * * @return TSocket */ protected function acceptImpl() { $handle = @stream_socket_accept($this->listener_, $this->acceptTimeout_ / 1000.0); if (!$handle) { return null; } $socket = new TSocket(); $socket->setHandle($handle); return $socket; } } thrift-0.19.0/lib/php/lib/Server/TForkingServer.php0000644000000000000000000000571014303740367022105 0ustar00rootroot00000000000000transport_->listen(); while (!$this->stop_) { try { $transport = $this->transport_->accept(); if ($transport != null) { $pid = pcntl_fork(); if ($pid > 0) { $this->handleParent($transport, $pid); } elseif ($pid === 0) { $this->handleChild($transport); } else { throw new TException('Failed to fork'); } } } catch (TTransportException $e) { } $this->collectChildren(); } } /** * Code run by the parent * * @param TTransport $transport * @param int $pid * @return void */ private function handleParent(TTransport $transport, $pid) { $this->children_[$pid] = $transport; } /** * Code run by the child. * * @param TTransport $transport * @return void */ private function handleChild(TTransport $transport) { try { $inputTransport = $this->inputTransportFactory_->getTransport($transport); $outputTransport = $this->outputTransportFactory_->getTransport($transport); $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport); $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport); while ($this->processor_->process($inputProtocol, $outputProtocol)) { } @$transport->close(); } catch (TTransportException $e) { } exit(0); } /** * Collects any children we may have * * @return void */ private function collectChildren() { foreach ($this->children_ as $pid => $transport) { if (pcntl_waitpid($pid, $status, WNOHANG) > 0) { unset($this->children_[$pid]); if ($transport) { @$transport->close(); } } } } /** * Stops the server running. Kills the transport * and then stops the main serving loop * * @return void */ public function stop() { $this->transport_->close(); $this->stop_ = true; } } thrift-0.19.0/lib/php/lib/Server/TSimpleServer.php0000644000000000000000000000301514303740367021733 0ustar00rootroot00000000000000transport_->listen(); while (!$this->stop_) { try { $transport = $this->transport_->accept(); if ($transport != null) { $inputTransport = $this->inputTransportFactory_->getTransport($transport); $outputTransport = $this->outputTransportFactory_->getTransport($transport); $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport); $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport); while ($this->processor_->process($inputProtocol, $outputProtocol)) { } } } catch (TTransportException $e) { } } } /** * Stops the server running. Kills the transport * and then stops the main serving loop * * @return void */ public function stop() { $this->transport_->close(); $this->stop_ = true; } } thrift-0.19.0/lib/php/lib/Server/TServer.php0000644000000000000000000000446414303740367020572 0ustar00rootroot00000000000000processor_ = $processor; $this->transport_ = $transport; $this->inputTransportFactory_ = $inputTransportFactory; $this->outputTransportFactory_ = $outputTransportFactory; $this->inputProtocolFactory_ = $inputProtocolFactory; $this->outputProtocolFactory_ = $outputProtocolFactory; } /** * Serves the server. This should never return * unless a problem permits it to do so or it * is interrupted intentionally * * @abstract * @return void */ abstract public function serve(); /** * Stops the server serving * * @abstract * @return void */ abstract public function stop(); } thrift-0.19.0/lib/php/lib/StoredMessageProtocol.php0000644000000000000000000000324414303740367022214 0ustar00rootroot00000000000000fname_ = $fname; $this->mtype_ = $mtype; $this->rseqid_ = $rseqid; } public function readMessageBegin(&$name, &$type, &$seqid) { $name = $this->fname_; $type = $this->mtype_; $seqid = $this->rseqid_; } } thrift-0.19.0/lib/php/lib/TMultiplexedProcessor.php0000644000000000000000000001072114303740367022243 0ustar00rootroot00000000000000TMultiplexedProcessor is a Processor allowing * a single TServer to provide multiple services. * *

To do so, you instantiate the processor and then register additional * processors with it, as shown in the following example:

* *
* $processor = new TMultiplexedProcessor(); * * processor->registerProcessor( * "Calculator", * new \tutorial\CalculatorProcessor(new CalculatorHandler())); * * processor->registerProcessor( * "WeatherReport", * new \tutorial\WeatherReportProcessor(new WeatherReportHandler())); * * $processor->process($protocol, $protocol); *
*/ class TMultiplexedProcessor { private $serviceProcessorMap_; /** * 'Register' a service with this TMultiplexedProcessor. This * allows us to broker requests to individual services by using the service * name to select them at request time. * * @param serviceName Name of a service, has to be identical to the name * declared in the Thrift IDL, e.g. "WeatherReport". * @param processor Implementation of a service, usually referred to * as "handlers", e.g. WeatherReportHandler implementing WeatherReport.Iface. */ public function registerProcessor($serviceName, $processor) { $this->serviceProcessorMap_[$serviceName] = $processor; } /** * This implementation of process performs the following steps: * *
    *
  1. Read the beginning of the message.
  2. *
  3. Extract the service name from the message.
  4. *
  5. Using the service name to locate the appropriate processor.
  6. *
  7. Dispatch to the processor, with a decorated instance of TProtocol * that allows readMessageBegin() to return the original Message.
  8. *
* * @throws TException If the message type is not CALL or ONEWAY, if * the service name was not found in the message, or if the service * name was not found in the service map. */ public function process(TProtocol $input, TProtocol $output) { /* Use the actual underlying protocol (e.g. TBinaryProtocol) to read the message header. This pulls the message "off the wire", which we'll deal with at the end of this method. */ $input->readMessageBegin($fname, $mtype, $rseqid); if ($mtype !== TMessageType::CALL && $mtype != TMessageType::ONEWAY) { throw new TException("This should not have happened!?"); } // Extract the service name and the new Message name. if (strpos($fname, TMultiplexedProtocol::SEPARATOR) === false) { throw new TException("Service name not found in message name: {$fname}. Did you " . "forget to use a TMultiplexProtocol in your client?"); } list($serviceName, $messageName) = explode(':', $fname, 2); if (!array_key_exists($serviceName, $this->serviceProcessorMap_)) { throw new TException("Service name not found: {$serviceName}. Did you forget " . "to call registerProcessor()?"); } // Dispatch processing to the stored processor $processor = $this->serviceProcessorMap_[$serviceName]; return $processor->process( new StoredMessageProtocol($input, $messageName, $mtype, $rseqid), $output ); } } thrift-0.19.0/lib/php/lib/Transport/0000777000000000000000000000000014303740367017211 5ustar00rootroot00000000000000thrift-0.19.0/lib/php/lib/Transport/TPhpStream.php0000644000000000000000000000651514303740367021754 0ustar00rootroot00000000000000read_ = $mode & self::MODE_R; $this->write_ = $mode & self::MODE_W; } public function open() { if ($this->read_) { $this->inStream_ = @fopen(self::inStreamName(), 'r'); if (!is_resource($this->inStream_)) { throw new TException('TPhpStream: Could not open php://input'); } } if ($this->write_) { $this->outStream_ = @fopen('php://output', 'w'); if (!is_resource($this->outStream_)) { throw new TException('TPhpStream: Could not open php://output'); } } } public function close() { if ($this->read_) { @fclose($this->inStream_); $this->inStream_ = null; } if ($this->write_) { @fclose($this->outStream_); $this->outStream_ = null; } } public function isOpen() { return (!$this->read_ || is_resource($this->inStream_)) && (!$this->write_ || is_resource($this->outStream_)); } public function read($len) { $data = @fread($this->inStream_, $len); if ($data === false || $data === '') { throw new TException('TPhpStream: Could not read ' . $len . ' bytes'); } return $data; } public function write($buf) { while (TStringFuncFactory::create()->strlen($buf) > 0) { $got = @fwrite($this->outStream_, $buf); if ($got === 0 || $got === false) { throw new TException( 'TPhpStream: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes' ); } $buf = TStringFuncFactory::create()->substr($buf, $got); } } public function flush() { @fflush($this->outStream_); } private static function inStreamName() { if (php_sapi_name() == 'cli') { return 'php://stdin'; } return 'php://input'; } } thrift-0.19.0/lib/php/lib/Transport/TSocketPool.php0000644000000000000000000002227614303740367022135 0ustar00rootroot00000000000000 $val) { $ports[$key] = $port; } } foreach ($hosts as $key => $host) { $this->servers_ [] = array('host' => $host, 'port' => $ports[$key]); } } /** * Add a server to the pool * * This function does not prevent you from adding a duplicate server entry. * * @param string $host hostname or IP * @param int $port port */ public function addServer($host, $port) { $this->servers_[] = array('host' => $host, 'port' => $port); } /** * Sets how many time to keep retrying a host in the connect function. * * @param int $numRetries */ public function setNumRetries($numRetries) { $this->numRetries_ = $numRetries; } /** * Sets how long to wait until retrying a host if it was marked down * * @param int $numRetries */ public function setRetryInterval($retryInterval) { $this->retryInterval_ = $retryInterval; } /** * Sets how many time to keep retrying a host before marking it as down. * * @param int $numRetries */ public function setMaxConsecutiveFailures($maxConsecutiveFailures) { $this->maxConsecutiveFailures_ = $maxConsecutiveFailures; } /** * Turns randomization in connect order on or off. * * @param bool $randomize */ public function setRandomize($randomize) { $this->randomize_ = $randomize; } /** * Whether to always try the last server. * * @param bool $alwaysTryLast */ public function setAlwaysTryLast($alwaysTryLast) { $this->alwaysTryLast_ = $alwaysTryLast; } /** * Connects the socket by iterating through all the servers in the pool * and trying to find one that works. */ public function open() { // Check if we want order randomization if ($this->randomize_) { shuffle($this->servers_); } // Count servers to identify the "last" one $numServers = count($this->servers_); for ($i = 0; $i < $numServers; ++$i) { // This extracts the $host and $port variables extract($this->servers_[$i]); // Check APCu cache for a record of this server being down $failtimeKey = 'thrift_failtime:' . $host . ':' . $port . '~'; // Cache miss? Assume it's OK $lastFailtime = apcu_fetch($failtimeKey); if ($lastFailtime === false) { $lastFailtime = 0; } $retryIntervalPassed = false; // Cache hit...make sure enough the retry interval has elapsed if ($lastFailtime > 0) { $elapsed = time() - $lastFailtime; if ($elapsed > $this->retryInterval_) { $retryIntervalPassed = true; if ($this->debug_) { call_user_func( $this->debugHandler_, 'TSocketPool: retryInterval ' . '(' . $this->retryInterval_ . ') ' . 'has passed for host ' . $host . ':' . $port ); } } } // Only connect if not in the middle of a fail interval, OR if this // is the LAST server we are trying, just hammer away on it $isLastServer = false; if ($this->alwaysTryLast_) { $isLastServer = ($i == ($numServers - 1)); } if (($lastFailtime === 0) || ($isLastServer) || ($lastFailtime > 0 && $retryIntervalPassed)) { // Set underlying TSocket params to this one $this->host_ = $host; $this->port_ = $port; // Try up to numRetries_ connections per server for ($attempt = 0; $attempt < $this->numRetries_; $attempt++) { try { // Use the underlying TSocket open function parent::open(); // Only clear the failure counts if required to do so if ($lastFailtime > 0) { apcu_store($failtimeKey, 0); } // Successful connection, return now return; } catch (TException $tx) { // Connection failed } } // Mark failure of this host in the cache $consecfailsKey = 'thrift_consecfails:' . $host . ':' . $port . '~'; // Ignore cache misses $consecfails = apcu_fetch($consecfailsKey); if ($consecfails === false) { $consecfails = 0; } // Increment by one $consecfails++; // Log and cache this failure if ($consecfails >= $this->maxConsecutiveFailures_) { if ($this->debug_) { call_user_func( $this->debugHandler_, 'TSocketPool: marking ' . $host . ':' . $port . ' as down for ' . $this->retryInterval_ . ' secs ' . 'after ' . $consecfails . ' failed attempts.' ); } // Store the failure time apcu_store($failtimeKey, time()); // Clear the count of consecutive failures apcu_store($consecfailsKey, 0); } else { apcu_store($consecfailsKey, $consecfails); } } } // Oh no; we failed them all. The system is totally ill! $error = 'TSocketPool: All hosts in pool are down. '; $hosts = array(); foreach ($this->servers_ as $server) { $hosts [] = $server['host'] . ':' . $server['port']; } $hostlist = implode(',', $hosts); $error .= '(' . $hostlist . ')'; if ($this->debug_) { call_user_func($this->debugHandler_, $error); } throw new TException($error); } } thrift-0.19.0/lib/php/lib/Transport/TFramedTransport.php0000644000000000000000000001140614303740367023157 0ustar00rootroot00000000000000transport_ = $transport; $this->read_ = $read; $this->write_ = $write; } public function isOpen() { return $this->transport_->isOpen(); } public function open() { $this->transport_->open(); } public function close() { $this->transport_->close(); } /** * Reads from the buffer. When more data is required reads another entire * chunk and serves future reads out of that. * * @param int $len How much data */ public function read($len) { if (!$this->read_) { return $this->transport_->read($len); } if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) { $this->readFrame(); } // Just return full buff if ($len >= TStringFuncFactory::create()->strlen($this->rBuf_)) { $out = $this->rBuf_; $this->rBuf_ = null; return $out; } // Return TStringFuncFactory::create()->substr $out = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len); $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len); return $out; } /** * Put previously read data back into the buffer * * @param string $data data to return */ public function putBack($data) { if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) { $this->rBuf_ = $data; } else { $this->rBuf_ = ($data . $this->rBuf_); } } /** * Reads a chunk of data into the internal read buffer. */ private function readFrame() { $buf = $this->transport_->readAll(4); $val = unpack('N', $buf); $sz = $val[1]; $this->rBuf_ = $this->transport_->readAll($sz); } /** * Writes some data to the pending output buffer. * * @param string $buf The data * @param int $len Limit of bytes to write */ public function write($buf, $len = null) { if (!$this->write_) { return $this->transport_->write($buf, $len); } if ($len !== null && $len < TStringFuncFactory::create()->strlen($buf)) { $buf = TStringFuncFactory::create()->substr($buf, 0, $len); } $this->wBuf_ .= $buf; } /** * Writes the output buffer to the stream in the format of a 4-byte length * followed by the actual data. */ public function flush() { if (!$this->write_ || TStringFuncFactory::create()->strlen($this->wBuf_) == 0) { return $this->transport_->flush(); } $out = pack('N', TStringFuncFactory::create()->strlen($this->wBuf_)); $out .= $this->wBuf_; // Note that we clear the internal wBuf_ prior to the underlying write // to ensure we're in a sane state (i.e. internal buffer cleaned) // if the underlying write throws up an exception $this->wBuf_ = ''; $this->transport_->write($out); $this->transport_->flush(); } } thrift-0.19.0/lib/php/lib/Transport/TCurlClient.php0000644000000000000000000002053414303740367022112 0ustar00rootroot00000000000000strlen($uri) > 0) && ($uri[0] != '/')) { $uri = '/' . $uri; } $this->scheme_ = $scheme; $this->host_ = $host; $this->port_ = $port; $this->uri_ = $uri; $this->request_ = ''; $this->response_ = null; $this->timeout_ = null; $this->connectionTimeout_ = null; $this->headers_ = array(); } /** * Set read timeout * * @param float $timeout */ public function setTimeoutSecs($timeout) { $this->timeout_ = $timeout; } /** * Set connection timeout * * @param float $connectionTimeout */ public function setConnectionTimeoutSecs($connectionTimeout) { $this->connectionTimeout_ = $connectionTimeout; } /** * Whether this transport is open. * * @return boolean true if open */ public function isOpen() { return true; } /** * Open the transport for reading/writing * * @throws TTransportException if cannot open */ public function open() { } /** * Close the transport. */ public function close() { $this->request_ = ''; $this->response_ = null; } /** * Read some data into the array. * * @param int $len How much to read * @return string The data that has been read * @throws TTransportException if cannot read any more data */ public function read($len) { if ($len >= strlen($this->response_)) { return $this->response_; } else { $ret = substr($this->response_, 0, $len); $this->response_ = substr($this->response_, $len); return $ret; } } /** * Guarantees that the full amount of data is read. Since TCurlClient gets entire payload at * once, parent readAll cannot be used. * * @return string The data, of exact length * @throws TTransportException if cannot read data */ public function readAll($len) { $data = $this->read($len); if (TStringFuncFactory::create()->strlen($data) !== $len) { throw new TTransportException('TCurlClient could not read '.$len.' bytes'); } return $data; } /** * Writes some data into the pending buffer * * @param string $buf The data to write * @throws TTransportException if writing fails */ public function write($buf) { $this->request_ .= $buf; } /** * Opens and sends the actual request over the HTTP connection * * @throws TTransportException if a writing error occurs */ public function flush() { if (!self::$curlHandle) { register_shutdown_function(array('Thrift\\Transport\\TCurlClient', 'closeCurlHandle')); self::$curlHandle = curl_init(); curl_setopt(self::$curlHandle, CURLOPT_RETURNTRANSFER, true); curl_setopt(self::$curlHandle, CURLOPT_BINARYTRANSFER, true); curl_setopt(self::$curlHandle, CURLOPT_USERAGENT, 'PHP/TCurlClient'); curl_setopt(self::$curlHandle, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt(self::$curlHandle, CURLOPT_FOLLOWLOCATION, true); curl_setopt(self::$curlHandle, CURLOPT_MAXREDIRS, 1); } // God, PHP really has some esoteric ways of doing simple things. $host = $this->host_ . ($this->port_ != 80 ? ':' . $this->port_ : ''); $fullUrl = $this->scheme_ . "://" . $host . $this->uri_; $headers = array(); $defaultHeaders = array('Accept' => 'application/x-thrift', 'Content-Type' => 'application/x-thrift', 'Content-Length' => TStringFuncFactory::create()->strlen($this->request_)); foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) { $headers[] = "$key: $value"; } curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers); if ($this->timeout_ > 0) { if ($this->timeout_ < 1.0) { // Timestamps smaller than 1 second are ignored when CURLOPT_TIMEOUT is used curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT_MS, 1000 * $this->timeout_); } else { curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_); } } if ($this->connectionTimeout_ > 0) { if ($this->connectionTimeout_ < 1.0) { // Timestamps smaller than 1 second are ignored when CURLOPT_CONNECTTIMEOUT is used curl_setopt(self::$curlHandle, CURLOPT_CONNECTTIMEOUT_MS, 1000 * $this->connectionTimeout_); } else { curl_setopt(self::$curlHandle, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout_); } } curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_); $this->request_ = ''; curl_setopt(self::$curlHandle, CURLOPT_URL, $fullUrl); $this->response_ = curl_exec(self::$curlHandle); $responseError = curl_error(self::$curlHandle); $code = curl_getinfo(self::$curlHandle, CURLINFO_HTTP_CODE); // Handle non 200 status code / connect failure if ($this->response_ === false || $code !== 200) { curl_close(self::$curlHandle); self::$curlHandle = null; $this->response_ = null; $error = 'TCurlClient: Could not connect to ' . $fullUrl; if ($responseError) { $error .= ', ' . $responseError; } if ($code) { $error .= ', HTTP status code: ' . $code; } throw new TTransportException($error, TTransportException::UNKNOWN); } } public static function closeCurlHandle() { try { if (self::$curlHandle) { curl_close(self::$curlHandle); self::$curlHandle = null; } } catch (\Exception $x) { error_log('There was an error closing the curl handle: ' . $x->getMessage()); } } public function addHeaders($headers) { $this->headers_ = array_merge($this->headers_, $headers); } } thrift-0.19.0/lib/php/lib/Transport/TBufferedTransport.php0000644000000000000000000001273014303740367023504 0ustar00rootroot00000000000000transport_ = $transport; $this->rBufSize_ = $rBufSize; $this->wBufSize_ = $wBufSize; } public function isOpen() { return $this->transport_->isOpen(); } /** * @inheritdoc * * @throws TTransportException */ public function open() { $this->transport_->open(); } public function close() { $this->transport_->close(); } public function putBack($data) { if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) { $this->rBuf_ = $data; } else { $this->rBuf_ = ($data . $this->rBuf_); } } /** * The reason that we customize readAll here is that the majority of PHP * streams are already internally buffered by PHP. The socket stream, for * example, buffers internally and blocks if you call read with $len greater * than the amount of data available, unlike recv() in C. * * Therefore, use the readAll method of the wrapped transport inside * the buffered readAll. * * @throws TTransportException */ public function readAll($len) { $have = TStringFuncFactory::create()->strlen($this->rBuf_); if ($have == 0) { $data = $this->transport_->readAll($len); } elseif ($have < $len) { $data = $this->rBuf_; $this->rBuf_ = ''; $data .= $this->transport_->readAll($len - $have); } elseif ($have == $len) { $data = $this->rBuf_; $this->rBuf_ = ''; } elseif ($have > $len) { $data = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len); $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len); } return $data; } /** * @inheritdoc * * @param int $len * @return string * @throws TTransportException */ public function read($len) { if (TStringFuncFactory::create()->strlen($this->rBuf_) === 0) { $this->rBuf_ = $this->transport_->read($this->rBufSize_); } if (TStringFuncFactory::create()->strlen($this->rBuf_) <= $len) { $ret = $this->rBuf_; $this->rBuf_ = ''; return $ret; } $ret = TStringFuncFactory::create()->substr($this->rBuf_, 0, $len); $this->rBuf_ = TStringFuncFactory::create()->substr($this->rBuf_, $len); return $ret; } /** * @inheritdoc * * @param string $buf * @throws TTransportException */ public function write($buf) { $this->wBuf_ .= $buf; if (TStringFuncFactory::create()->strlen($this->wBuf_) >= $this->wBufSize_) { $out = $this->wBuf_; // Note that we clear the internal wBuf_ prior to the underlying write // to ensure we're in a sane state (i.e. internal buffer cleaned) // if the underlying write throws up an exception $this->wBuf_ = ''; $this->transport_->write($out); } } /** * @inheritdoc * * @throws TTransportException */ public function flush() { if (TStringFuncFactory::create()->strlen($this->wBuf_) > 0) { $out = $this->wBuf_; // Note that we clear the internal wBuf_ prior to the underlying write // to ensure we're in a sane state (i.e. internal buffer cleaned) // if the underlying write throws up an exception $this->wBuf_ = ''; $this->transport_->write($out); } $this->transport_->flush(); } } thrift-0.19.0/lib/php/lib/Transport/TTransport.php0000644000000000000000000000474314303740367022046 0ustar00rootroot00000000000000read($len); $data = ''; $got = 0; while (($got = TStringFuncFactory::create()->strlen($data)) < $len) { $data .= $this->read($len - $got); } return $data; } /** * Writes the given data out. * * @param string $buf The data to write * @throws TTransportException if writing fails */ abstract public function write($buf); /** * Flushes any pending data out of a buffer * * @throws TTransportException if a writing error occurs */ public function flush() { } } thrift-0.19.0/lib/php/lib/Transport/TSocket.php0000644000000000000000000002350514303740367021277 0ustar00rootroot00000000000000host_ = $host; $this->port_ = $port; $this->persist_ = $persist; $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log'; } /** * @param resource $handle * @return void */ public function setHandle($handle) { $this->handle_ = $handle; stream_set_blocking($this->handle_, false); } /** * Sets the send timeout. * * @param int $timeout Timeout in milliseconds. */ public function setSendTimeout($timeout) { $this->sendTimeoutSec_ = floor($timeout / 1000); $this->sendTimeoutUsec_ = ($timeout - ($this->sendTimeoutSec_ * 1000)) * 1000; } /** * Sets the receive timeout. * * @param int $timeout Timeout in milliseconds. */ public function setRecvTimeout($timeout) { $this->recvTimeoutSec_ = floor($timeout / 1000); $this->recvTimeoutUsec_ = ($timeout - ($this->recvTimeoutSec_ * 1000)) * 1000; } /** * Sets debugging output on or off * * @param bool $debug */ public function setDebug($debug) { $this->debug_ = $debug; } /** * Get the host that this socket is connected to * * @return string host */ public function getHost() { return $this->host_; } /** * Get the remote port that this socket is connected to * * @return int port */ public function getPort() { return $this->port_; } /** * Tests whether this is open * * @return bool true if the socket is open */ public function isOpen() { return is_resource($this->handle_); } /** * Connects the socket. */ public function open() { if ($this->isOpen()) { throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN); } if (empty($this->host_)) { throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN); } if ($this->port_ <= 0) { throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN); } if ($this->persist_) { $this->handle_ = @pfsockopen( $this->host_, $this->port_, $errno, $errstr, $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000) ); } else { $this->handle_ = @fsockopen( $this->host_, $this->port_, $errno, $errstr, $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000) ); } // Connect failed? if ($this->handle_ === false) { $error = 'TSocket: Could not connect to ' . $this->host_ . ':' . $this->port_ . ' (' . $errstr . ' [' . $errno . '])'; if ($this->debug_) { call_user_func($this->debugHandler_, $error); } throw new TException($error); } if (function_exists('socket_import_stream') && function_exists('socket_set_option')) { // warnings silenced due to bug https://bugs.php.net/bug.php?id=70939 $socket = @socket_import_stream($this->handle_); @socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1); } } /** * Closes the socket. */ public function close() { @fclose($this->handle_); $this->handle_ = null; } /** * Read from the socket at most $len bytes. * * This method will not wait for all the requested data, it will return as * soon as any data is received. * * @param int $len Maximum number of bytes to read. * @return string Binary data */ public function read($len) { $null = null; $read = array($this->handle_); $readable = @stream_select( $read, $null, $null, $this->recvTimeoutSec_, $this->recvTimeoutUsec_ ); if ($readable > 0) { $data = fread($this->handle_, $len); if ($data === false) { throw new TTransportException('TSocket: Could not read ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_); } elseif ($data == '' && feof($this->handle_)) { throw new TTransportException('TSocket read 0 bytes'); } return $data; } elseif ($readable === 0) { throw new TTransportException('TSocket: timed out reading ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_); } else { throw new TTransportException('TSocket: Could not read ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_); } } /** * Write to the socket. * * @param string $buf The data to write */ public function write($buf) { $null = null; $write = array($this->handle_); // keep writing until all the data has been written while (TStringFuncFactory::create()->strlen($buf) > 0) { // wait for stream to become available for writing $writable = @stream_select( $null, $write, $null, $this->sendTimeoutSec_, $this->sendTimeoutUsec_ ); if ($writable > 0) { // write buffer to stream $written = fwrite($this->handle_, $buf); $closed_socket = $written === 0 && feof($this->handle_); if ($written === -1 || $written === false || $closed_socket) { throw new TTransportException( 'TSocket: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes ' . $this->host_ . ':' . $this->port_ ); } // determine how much of the buffer is left to write $buf = TStringFuncFactory::create()->substr($buf, $written); } elseif ($writable === 0) { throw new TTransportException( 'TSocket: timed out writing ' . TStringFuncFactory::create()->strlen($buf) . ' bytes from ' . $this->host_ . ':' . $this->port_ ); } else { throw new TTransportException( 'TSocket: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes ' . $this->host_ . ':' . $this->port_ ); } } } /** * Flush output to the socket. * * Since read(), readAll() and write() operate on the sockets directly, * this is a no-op * * If you wish to have flushable buffering behaviour, wrap this TSocket * in a TBufferedTransport. */ public function flush() { // no-op } } thrift-0.19.0/lib/php/lib/Transport/TSSLSocket.php0000644000000000000000000000672214303740367021663 0ustar00rootroot00000000000000host_ = $this->getSSLHost($host); $this->port_ = $port; $this->context_ = $context; $this->debugHandler_ = $debugHandler ? $debugHandler : 'error_log'; } /** * Creates a host name with SSL transport protocol * if no transport protocol already specified in * the host name. * * @param string $host Host to listen on * @return string $host Host name with transport protocol */ private function getSSLHost($host) { $transport_protocol_loc = strpos($host, "://"); if ($transport_protocol_loc === false) { $host = 'ssl://' . $host; } return $host; } /** * Connects the socket. */ public function open() { if ($this->isOpen()) { throw new TTransportException('Socket already connected', TTransportException::ALREADY_OPEN); } if (empty($this->host_)) { throw new TTransportException('Cannot open null host', TTransportException::NOT_OPEN); } if ($this->port_ <= 0) { throw new TTransportException('Cannot open without port', TTransportException::NOT_OPEN); } $this->handle_ = @stream_socket_client( $this->host_ . ':' . $this->port_, $errno, $errstr, $this->sendTimeoutSec_ + ($this->sendTimeoutUsec_ / 1000000), STREAM_CLIENT_CONNECT, $this->context_ ); // Connect failed? if ($this->handle_ === false) { $error = 'TSocket: Could not connect to ' . $this->host_ . ':' . $this->port_ . ' (' . $errstr . ' [' . $errno . '])'; if ($this->debug_) { call_user_func($this->debugHandler_, $error); } throw new TException($error); } } } thrift-0.19.0/lib/php/lib/Transport/TMemoryBuffer.php0000644000000000000000000000511614303740367022447 0ustar00rootroot00000000000000buf_ = $buf; } protected $buf_ = ''; public function isOpen() { return true; } public function open() { } public function close() { } public function write($buf) { $this->buf_ .= $buf; } public function read($len) { $bufLength = TStringFuncFactory::create()->strlen($this->buf_); if ($bufLength === 0) { throw new TTransportException( 'TMemoryBuffer: Could not read ' . $len . ' bytes from buffer.', TTransportException::UNKNOWN ); } if ($bufLength <= $len) { $ret = $this->buf_; $this->buf_ = ''; return $ret; } $ret = TStringFuncFactory::create()->substr($this->buf_, 0, $len); $this->buf_ = TStringFuncFactory::create()->substr($this->buf_, $len); return $ret; } public function getBuffer() { return $this->buf_; } public function available() { return TStringFuncFactory::create()->strlen($this->buf_); } public function putBack($data) { $this->buf_ = $data . $this->buf_; } } thrift-0.19.0/lib/php/lib/Transport/TNullTransport.php0000644000000000000000000000262414303740367022675 0ustar00rootroot00000000000000strlen($uri) > 0) && ($uri[0] != '/')) { $uri = '/' . $uri; } $this->scheme_ = $scheme; $this->host_ = $host; $this->port_ = $port; $this->uri_ = $uri; $this->buf_ = ''; $this->handle_ = null; $this->timeout_ = null; $this->headers_ = array(); $this->context_ = $context; } /** * Set read timeout * * @param float $timeout */ public function setTimeoutSecs($timeout) { $this->timeout_ = $timeout; } /** * Whether this transport is open. * * @return boolean true if open */ public function isOpen() { return true; } /** * Open the transport for reading/writing * * @throws TTransportException if cannot open */ public function open() { } /** * Close the transport. */ public function close() { if ($this->handle_) { @fclose($this->handle_); $this->handle_ = null; } } /** * Read some data into the array. * * @param int $len How much to read * @return string The data that has been read * @throws TTransportException if cannot read any more data */ public function read($len) { $data = @fread($this->handle_, $len); if ($data === false || $data === '') { $md = stream_get_meta_data($this->handle_); if ($md['timed_out']) { throw new TTransportException( 'THttpClient: timed out reading ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_ . $this->uri_, TTransportException::TIMED_OUT ); } else { throw new TTransportException( 'THttpClient: Could not read ' . $len . ' bytes from ' . $this->host_ . ':' . $this->port_ . $this->uri_, TTransportException::UNKNOWN ); } } return $data; } /** * Writes some data into the pending buffer * * @param string $buf The data to write * @throws TTransportException if writing fails */ public function write($buf) { $this->buf_ .= $buf; } /** * Opens and sends the actual request over the HTTP connection * * @throws TTransportException if a writing error occurs */ public function flush() { // God, PHP really has some esoteric ways of doing simple things. $host = $this->host_ . ($this->port_ != 80 ? ':' . $this->port_ : ''); $headers = array(); $defaultHeaders = array('Host' => $host, 'Accept' => 'application/x-thrift', 'User-Agent' => 'PHP/THttpClient', 'Content-Type' => 'application/x-thrift', 'Content-Length' => TStringFuncFactory::create()->strlen($this->buf_)); foreach (array_merge($defaultHeaders, $this->headers_) as $key => $value) { $headers[] = "$key: $value"; } $options = $this->context_; $baseHttpOptions = isset($options["http"]) ? $options["http"] : array(); $httpOptions = $baseHttpOptions + array('method' => 'POST', 'header' => implode("\r\n", $headers), 'max_redirects' => 1, 'content' => $this->buf_); if ($this->timeout_ > 0) { $httpOptions['timeout'] = $this->timeout_; } $this->buf_ = ''; $options["http"] = $httpOptions; $contextid = stream_context_create($options); $this->handle_ = @fopen( $this->scheme_ . '://' . $host . $this->uri_, 'r', false, $contextid ); // Connect failed? if ($this->handle_ === false) { $this->handle_ = null; $error = 'THttpClient: Could not connect to ' . $host . $this->uri_; throw new TTransportException($error, TTransportException::NOT_OPEN); } } public function addHeaders($headers) { $this->headers_ = array_merge($this->headers_, $headers); } } thrift-0.19.0/lib/php/Makefile.in0000644000000000000000000013121514472652517016521 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/php ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(phpmoduledir)" "$(DESTDIR)$(phpdir)" \ "$(DESTDIR)$(phpbasedir)" "$(DESTDIR)$(phpclassloaderdir)" \ "$(DESTDIR)$(phpconfdir)" "$(DESTDIR)$(phpexceptiondir)" \ "$(DESTDIR)$(phpfactorydir)" "$(DESTDIR)$(phpprotocoldir)" \ "$(DESTDIR)$(phpprotocoljsondir)" \ "$(DESTDIR)$(phpprotocolsimplejsondir)" \ "$(DESTDIR)$(phpserializerdir)" "$(DESTDIR)$(phpserverdir)" \ "$(DESTDIR)$(phpstringfuncdir)" "$(DESTDIR)$(phptransportdir)" \ "$(DESTDIR)$(phptypedir)" SCRIPTS = $(phpmodule_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(php_DATA) $(phpbase_DATA) $(phpclassloader_DATA) \ $(phpconf_DATA) $(phpexception_DATA) $(phpfactory_DATA) \ $(phpprotocol_DATA) $(phpprotocoljson_DATA) \ $(phpprotocolsimplejson_DATA) $(phpserializer_DATA) \ $(phpserver_DATA) $(phpstringfunc_DATA) $(phptransport_DATA) \ $(phptype_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = test am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @WITH_TESTS_TRUE@SUBDIRS = test @WITH_PHP_EXTENSION_TRUE@phpconfdir = $(PHP_CONFIG_PREFIX) @WITH_PHP_EXTENSION_TRUE@phpconf_DATA = thrift_protocol.ini @WITH_PHP_EXTENSION_TRUE@phpmoduledir = `php-config --extension-dir` @WITH_PHP_EXTENSION_TRUE@phpmodule_SCRIPTS = src/ext/thrift_protocol/modules/thrift_protocol.so phpdir = $(PHP_PREFIX)/ php_DATA = \ lib/TMultiplexedProcessor.php phpbasedir = $(phpdir)/Base phpbase_DATA = \ lib/Base/TBase.php phpclassloaderdir = $(phpdir)/ClassLoader phpclassloader_DATA = \ lib/ClassLoader/ThriftClassLoader.php phpexceptiondir = $(phpdir)/Exception phpexception_DATA = \ lib/Exception/TApplicationException.php \ lib/Exception/TException.php \ lib/Exception/TProtocolException.php \ lib/Exception/TTransportException.php phpfactorydir = $(phpdir)/Factory phpfactory_DATA = \ lib/Factory/TBinaryProtocolFactory.php \ lib/Factory/TCompactProtocolFactory.php \ lib/Factory/TJSONProtocolFactory.php \ lib/Factory/TProtocolFactory.php \ lib/Factory/TStringFuncFactory.php \ lib/Factory/TTransportFactory.php phpprotocoldir = $(phpdir)/Protocol phpprotocol_DATA = \ lib/Protocol/TBinaryProtocolAccelerated.php \ lib/Protocol/TBinaryProtocol.php \ lib/Protocol/TCompactProtocol.php \ lib/Protocol/TJSONProtocol.php \ lib/Protocol/TMultiplexedProtocol.php \ lib/Protocol/TProtocol.php \ lib/Protocol/TProtocolDecorator.php \ lib/Protocol/TSimpleJSONProtocol.php phpprotocoljsondir = $(phpprotocoldir)/JSON phpprotocoljson_DATA = \ lib/Protocol/JSON/BaseContext.php \ lib/Protocol/JSON/ListContext.php \ lib/Protocol/JSON/LookaheadReader.php \ lib/Protocol/JSON/PairContext.php phpprotocolsimplejsondir = $(phpprotocoldir)/SimpleJSON phpprotocolsimplejson_DATA = \ lib/Protocol/SimpleJSON/CollectionMapKeyException.php \ lib/Protocol/SimpleJSON/Context.php \ lib/Protocol/SimpleJSON/ListContext.php \ lib/Protocol/SimpleJSON/MapContext.php \ lib/Protocol/SimpleJSON/StructContext.php phpserializerdir = $(phpdir)/Serializer phpserializer_DATA = \ lib/Serializer/TBinarySerializer.php phpserverdir = $(phpdir)/Server phpserver_DATA = \ lib/Server/TServerSocket.php \ lib/Server/TForkingServer.php \ lib/Server/TServer.php \ lib/Server/TServerTransport.php \ lib/Server/TSimpleServer.php phpstringfuncdir = $(phpdir)/StringFunc phpstringfunc_DATA = \ lib/StringFunc/Mbstring.php \ lib/StringFunc/Core.php \ lib/StringFunc/TStringFunc.php phptransportdir = $(phpdir)/Transport phptransport_DATA = \ lib/Transport/TBufferedTransport.php \ lib/Transport/TCurlClient.php \ lib/Transport/TFramedTransport.php \ lib/Transport/THttpClient.php \ lib/Transport/TMemoryBuffer.php \ lib/Transport/TNullTransport.php \ lib/Transport/TPhpStream.php \ lib/Transport/TSocket.php \ lib/Transport/TSocketPool.php \ lib/Transport/TTransport.php phptypedir = $(phpdir)/Type phptype_DATA = \ lib/Type/TMessageType.php \ lib/Type/TType.php \ lib/Type/TConstant.php EXTRA_DIST = \ lib \ src/autoload.php \ src/ext/thrift_protocol/config.m4 \ src/ext/thrift_protocol/config.w32 \ src/ext/thrift_protocol/php_thrift_protocol.cpp \ src/ext/thrift_protocol/php_thrift_protocol.h \ src/ext/thrift_protocol/php_thrift_protocol.stub.php \ src/ext/thrift_protocol/php_thrift_protocol_arginfo.h \ src/Thrift.php \ src/TStringUtils.php \ coding_standards.md \ thrift_protocol.ini \ README.apache.md \ README.md \ test/Fixtures.php \ test/TestValidators.thrift \ test/JsonSerialize/JsonSerializeTest.php \ test/Protocol/BinarySerializerTest.php \ test/Protocol/TJSONProtocolFixtures.php \ test/Protocol/TJSONProtocolTest.php \ test/Protocol/TSimpleJSONProtocolFixtures.php \ test/Protocol/TSimpleJSONProtocolTest.php \ test/Validator/BaseValidatorTest.php \ test/Validator/ValidatorTest.php \ test/Validator/ValidatorTestOop.php MAINTAINERCLEANFILES = \ Makefile.in all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/php/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/php/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-phpmoduleSCRIPTS: $(phpmodule_SCRIPTS) @$(NORMAL_INSTALL) @list='$(phpmodule_SCRIPTS)'; test -n "$(phpmoduledir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpmoduledir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpmoduledir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(phpmoduledir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(phpmoduledir)$$dir" || exit $$?; \ } \ ; done uninstall-phpmoduleSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(phpmodule_SCRIPTS)'; test -n "$(phpmoduledir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(phpmoduledir)'; $(am__uninstall_files_from_dir) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-phpDATA: $(php_DATA) @$(NORMAL_INSTALL) @list='$(php_DATA)'; test -n "$(phpdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpdir)" || exit $$?; \ done uninstall-phpDATA: @$(NORMAL_UNINSTALL) @list='$(php_DATA)'; test -n "$(phpdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpdir)'; $(am__uninstall_files_from_dir) install-phpbaseDATA: $(phpbase_DATA) @$(NORMAL_INSTALL) @list='$(phpbase_DATA)'; test -n "$(phpbasedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpbasedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpbasedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpbasedir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpbasedir)" || exit $$?; \ done uninstall-phpbaseDATA: @$(NORMAL_UNINSTALL) @list='$(phpbase_DATA)'; test -n "$(phpbasedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpbasedir)'; $(am__uninstall_files_from_dir) install-phpclassloaderDATA: $(phpclassloader_DATA) @$(NORMAL_INSTALL) @list='$(phpclassloader_DATA)'; test -n "$(phpclassloaderdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpclassloaderdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpclassloaderdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpclassloaderdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpclassloaderdir)" || exit $$?; \ done uninstall-phpclassloaderDATA: @$(NORMAL_UNINSTALL) @list='$(phpclassloader_DATA)'; test -n "$(phpclassloaderdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpclassloaderdir)'; $(am__uninstall_files_from_dir) install-phpconfDATA: $(phpconf_DATA) @$(NORMAL_INSTALL) @list='$(phpconf_DATA)'; test -n "$(phpconfdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpconfdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpconfdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpconfdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpconfdir)" || exit $$?; \ done uninstall-phpconfDATA: @$(NORMAL_UNINSTALL) @list='$(phpconf_DATA)'; test -n "$(phpconfdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpconfdir)'; $(am__uninstall_files_from_dir) install-phpexceptionDATA: $(phpexception_DATA) @$(NORMAL_INSTALL) @list='$(phpexception_DATA)'; test -n "$(phpexceptiondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpexceptiondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpexceptiondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpexceptiondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpexceptiondir)" || exit $$?; \ done uninstall-phpexceptionDATA: @$(NORMAL_UNINSTALL) @list='$(phpexception_DATA)'; test -n "$(phpexceptiondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpexceptiondir)'; $(am__uninstall_files_from_dir) install-phpfactoryDATA: $(phpfactory_DATA) @$(NORMAL_INSTALL) @list='$(phpfactory_DATA)'; test -n "$(phpfactorydir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpfactorydir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpfactorydir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpfactorydir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpfactorydir)" || exit $$?; \ done uninstall-phpfactoryDATA: @$(NORMAL_UNINSTALL) @list='$(phpfactory_DATA)'; test -n "$(phpfactorydir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpfactorydir)'; $(am__uninstall_files_from_dir) install-phpprotocolDATA: $(phpprotocol_DATA) @$(NORMAL_INSTALL) @list='$(phpprotocol_DATA)'; test -n "$(phpprotocoldir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpprotocoldir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpprotocoldir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpprotocoldir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpprotocoldir)" || exit $$?; \ done uninstall-phpprotocolDATA: @$(NORMAL_UNINSTALL) @list='$(phpprotocol_DATA)'; test -n "$(phpprotocoldir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpprotocoldir)'; $(am__uninstall_files_from_dir) install-phpprotocoljsonDATA: $(phpprotocoljson_DATA) @$(NORMAL_INSTALL) @list='$(phpprotocoljson_DATA)'; test -n "$(phpprotocoljsondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpprotocoljsondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpprotocoljsondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpprotocoljsondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpprotocoljsondir)" || exit $$?; \ done uninstall-phpprotocoljsonDATA: @$(NORMAL_UNINSTALL) @list='$(phpprotocoljson_DATA)'; test -n "$(phpprotocoljsondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpprotocoljsondir)'; $(am__uninstall_files_from_dir) install-phpprotocolsimplejsonDATA: $(phpprotocolsimplejson_DATA) @$(NORMAL_INSTALL) @list='$(phpprotocolsimplejson_DATA)'; test -n "$(phpprotocolsimplejsondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpprotocolsimplejsondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpprotocolsimplejsondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpprotocolsimplejsondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpprotocolsimplejsondir)" || exit $$?; \ done uninstall-phpprotocolsimplejsonDATA: @$(NORMAL_UNINSTALL) @list='$(phpprotocolsimplejson_DATA)'; test -n "$(phpprotocolsimplejsondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpprotocolsimplejsondir)'; $(am__uninstall_files_from_dir) install-phpserializerDATA: $(phpserializer_DATA) @$(NORMAL_INSTALL) @list='$(phpserializer_DATA)'; test -n "$(phpserializerdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpserializerdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpserializerdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpserializerdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpserializerdir)" || exit $$?; \ done uninstall-phpserializerDATA: @$(NORMAL_UNINSTALL) @list='$(phpserializer_DATA)'; test -n "$(phpserializerdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpserializerdir)'; $(am__uninstall_files_from_dir) install-phpserverDATA: $(phpserver_DATA) @$(NORMAL_INSTALL) @list='$(phpserver_DATA)'; test -n "$(phpserverdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpserverdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpserverdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpserverdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpserverdir)" || exit $$?; \ done uninstall-phpserverDATA: @$(NORMAL_UNINSTALL) @list='$(phpserver_DATA)'; test -n "$(phpserverdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpserverdir)'; $(am__uninstall_files_from_dir) install-phpstringfuncDATA: $(phpstringfunc_DATA) @$(NORMAL_INSTALL) @list='$(phpstringfunc_DATA)'; test -n "$(phpstringfuncdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phpstringfuncdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phpstringfuncdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phpstringfuncdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phpstringfuncdir)" || exit $$?; \ done uninstall-phpstringfuncDATA: @$(NORMAL_UNINSTALL) @list='$(phpstringfunc_DATA)'; test -n "$(phpstringfuncdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phpstringfuncdir)'; $(am__uninstall_files_from_dir) install-phptransportDATA: $(phptransport_DATA) @$(NORMAL_INSTALL) @list='$(phptransport_DATA)'; test -n "$(phptransportdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phptransportdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phptransportdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phptransportdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phptransportdir)" || exit $$?; \ done uninstall-phptransportDATA: @$(NORMAL_UNINSTALL) @list='$(phptransport_DATA)'; test -n "$(phptransportdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phptransportdir)'; $(am__uninstall_files_from_dir) install-phptypeDATA: $(phptype_DATA) @$(NORMAL_INSTALL) @list='$(phptype_DATA)'; test -n "$(phptypedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(phptypedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(phptypedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(phptypedir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(phptypedir)" || exit $$?; \ done uninstall-phptypeDATA: @$(NORMAL_UNINSTALL) @list='$(phptype_DATA)'; test -n "$(phptypedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(phptypedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(SCRIPTS) $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(phpmoduledir)" "$(DESTDIR)$(phpdir)" "$(DESTDIR)$(phpbasedir)" "$(DESTDIR)$(phpclassloaderdir)" "$(DESTDIR)$(phpconfdir)" "$(DESTDIR)$(phpexceptiondir)" "$(DESTDIR)$(phpfactorydir)" "$(DESTDIR)$(phpprotocoldir)" "$(DESTDIR)$(phpprotocoljsondir)" "$(DESTDIR)$(phpprotocolsimplejsondir)" "$(DESTDIR)$(phpserializerdir)" "$(DESTDIR)$(phpserverdir)" "$(DESTDIR)$(phpstringfuncdir)" "$(DESTDIR)$(phptransportdir)" "$(DESTDIR)$(phptypedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) @WITH_PHP_EXTENSION_FALSE@distclean-local: clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-phpDATA install-phpbaseDATA \ install-phpclassloaderDATA install-phpconfDATA \ install-phpexceptionDATA install-phpfactoryDATA \ install-phpmoduleSCRIPTS install-phpprotocolDATA \ install-phpprotocoljsonDATA install-phpprotocolsimplejsonDATA \ install-phpserializerDATA install-phpserverDATA \ install-phpstringfuncDATA install-phptransportDATA \ install-phptypeDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: uninstall-phpDATA uninstall-phpbaseDATA \ uninstall-phpclassloaderDATA uninstall-phpconfDATA \ uninstall-phpexceptionDATA uninstall-phpfactoryDATA \ uninstall-phpmoduleSCRIPTS uninstall-phpprotocolDATA \ uninstall-phpprotocoljsonDATA \ uninstall-phpprotocolsimplejsonDATA \ uninstall-phpserializerDATA uninstall-phpserverDATA \ uninstall-phpstringfuncDATA uninstall-phptransportDATA \ uninstall-phptypeDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am distclean distclean-generic \ distclean-libtool distclean-local distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-phpDATA install-phpbaseDATA \ install-phpclassloaderDATA install-phpconfDATA \ install-phpexceptionDATA install-phpfactoryDATA \ install-phpmoduleSCRIPTS install-phpprotocolDATA \ install-phpprotocoljsonDATA install-phpprotocolsimplejsonDATA \ install-phpserializerDATA install-phpserverDATA \ install-phpstringfuncDATA install-phptransportDATA \ install-phptypeDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am \ uninstall-phpDATA uninstall-phpbaseDATA \ uninstall-phpclassloaderDATA uninstall-phpconfDATA \ uninstall-phpexceptionDATA uninstall-phpfactoryDATA \ uninstall-phpmoduleSCRIPTS uninstall-phpprotocolDATA \ uninstall-phpprotocoljsonDATA \ uninstall-phpprotocolsimplejsonDATA \ uninstall-phpserializerDATA uninstall-phpserverDATA \ uninstall-phpstringfuncDATA uninstall-phptransportDATA \ uninstall-phptypeDATA .PRECIOUS: Makefile @WITH_PHP_EXTENSION_TRUE@%.so: @WITH_PHP_EXTENSION_TRUE@ cd src/ext/thrift_protocol/ && $(MAKE) @WITH_PHP_EXTENSION_TRUE@distclean-local: @WITH_PHP_EXTENSION_TRUE@ if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) distclean; fi @WITH_PHP_EXTENSION_TRUE@ cd $(phpmodule_SCRIPTS) && $(PHPIZE) --clean clean-local: if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) clean; fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/erl/0000755000000000000000000000000014472652657014451 5ustar00rootroot00000000000000thrift-0.19.0/lib/erl/include/0000777000000000000000000000000014303740367016065 5ustar00rootroot00000000000000thrift-0.19.0/lib/erl/include/thrift_protocol.hrl0000644000000000000000000000511014303740367022006 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -ifndef(THRIFT_PROTOCOL_INCLUDED). -define(THRIFT_PROTOCOL_INCLUDED, true). -record(protocol_message_begin, {name :: string(), type :: integer(), seqid :: integer()}). -record(protocol_struct_begin, {name :: string()}). -record(protocol_field_begin, {name :: string(), type :: integer(), id :: integer()}). -record(protocol_map_begin, {ktype :: integer(), vtype :: integer(), size :: integer()}). -record(protocol_list_begin, {etype :: integer(), size :: integer()}). -record(protocol_set_begin, {etype :: integer(), size :: integer()}). -type tprot_header_val() :: #protocol_message_begin{} | #protocol_struct_begin{} | #protocol_field_begin{} | #protocol_map_begin{} | #protocol_list_begin{} | #protocol_set_begin{} . -type tprot_empty_tag() :: message_end | struct_begin | struct_end | field_end | map_end | list_end | set_end . -type tprot_header_tag() :: message_begin | field_begin | map_begin | list_begin | set_begin . -type tprot_data_tag() :: ui32 | bool | byte | i16 | i32 | i64 | double | string . -type tprot_cont_tag() :: {list, _Type} | {map, _KType, _VType} | {set, _Type} . -endif. thrift-0.19.0/lib/erl/include/thrift_constants.hrl0000644000000000000000000000415414303740367022170 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% TType -define(tType_STOP, 0). -define(tType_VOID, 1). -define(tType_BOOL, 2). -define(tType_BYTE, 3). -define(tType_I8, 3). -define(tType_DOUBLE, 4). -define(tType_I16, 6). -define(tType_I32, 8). -define(tType_I64, 10). -define(tType_STRING, 11). -define(tType_STRUCT, 12). -define(tType_MAP, 13). -define(tType_SET, 14). -define(tType_LIST, 15). % TMessageType -define(tMessageType_CALL, 1). -define(tMessageType_REPLY, 2). -define(tMessageType_EXCEPTION, 3). -define(tMessageType_ONEWAY, 4). % TApplicationException -define(TApplicationException_Structure, {struct, [{1, string}, {2, i32}]}). -record('TApplicationException', {message, type}). -define(TApplicationException_UNKNOWN, 0). -define(TApplicationException_UNKNOWN_METHOD, 1). -define(TApplicationException_INVALID_MESSAGE_TYPE, 2). -define(TApplicationException_WRONG_METHOD_NAME, 3). -define(TApplicationException_BAD_SEQUENCE_ID, 4). -define(TApplicationException_MISSING_RESULT, 5). -define(TApplicationException_INTERNAL_ERROR, 6). -define(TApplicationException_PROTOCOL_ERROR, 7). -define(TApplicationException_INVALID_TRANSFORM, 8). -define(TApplicationException_INVALID_PROTOCOL, 9). -define(TApplicationException_UNSUPPORTED_CLIENT_TYPE, 10). -define (MULTIPLEXED_SERVICE_SEPARATOR, ":"). -define (MULTIPLEXED_ERROR_HANDLER_KEY, "error_handler"). thrift-0.19.0/lib/erl/include/thrift_transport_behaviour.hrl0000644000000000000000000000235014303740367024250 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% Signature specifications for transport implementations. -ifndef(THRIFT_TRANSPORT_BEHAVIOUR_INCLUDED). -define(THRIFT_TRANSPORT_BEHAVIOUR_INCLUDED, true). -spec write(state(), iolist() | binary()) -> {state(), ok | {error, _Reason}}. -spec read(state(), non_neg_integer()) -> {state(), {ok, binary()} | {error, _Reason}}. -spec flush(state()) -> {state(), ok | {error, _Reason}}. -spec close(state()) -> {state(), ok | {error, _Reason}}. -endif. thrift-0.19.0/lib/erl/include/thrift_protocol_behaviour.hrl0000644000000000000000000000277114303740367024064 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% Signature specifications for protocol implementations. -ifndef(THRIFT_PROTOCOL_BEHAVIOUR_INCLUDED). -define(THRIFT_PROTOCOL_BEHAVIOUR_INCLUDED, true). -spec flush_transport(state()) -> {state(), ok | {error, _Reason}}. -spec close_transport(state()) -> {state(), ok | {error, _Reason}}. -spec write(state(), any()) -> {state(), ok | {error, _Reason}}. %% NOTE: Keep this in sync with thrift_protocol:read and read_specific. -spec read (state(), tprot_empty_tag()) -> {state(), ok | {error, _Reason}}; (state(), tprot_header_tag()) -> {state(), tprot_header_val() | {error, _Reason}}; (state(), tprot_data_tag()) -> {state(), {ok, any()} | {error, _Reason}}. -endif. thrift-0.19.0/lib/erl/Makefile.am0000644000000000000000000000507514370300523016467 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # THRIFT = ../../compiler/cpp/thrift THRIFT_OMIT_FILE = test/Thrift_omit_without.thrift THRIFT_FILES = $(wildcard test/*.thrift) \ $(THRIFT_OMIT_FILE) \ ../../test/v0.16/ConstantsDemo.thrift \ ../../test/v0.16/NameConflictTest.thrift \ ../../test/DoubleConstantsTest.thrift \ ../../test/v0.16/ThriftTest.thrift ERL_FLAG = erl ERL_FLAG_LEGACY = erl:legacynames ERL_FLAG_MAPS = erl:maps $(THRIFT_OMIT_FILE): test/Thrift_omit_with.thrift grep -v omit $< >$@ .generated: $(THRIFT) $(THRIFT_FILES) for f in $(THRIFT_FILES) ; do \ $(THRIFT) --gen $(ERL_FLAG) -o test $$f ; \ done $(THRIFT) --gen $(ERL_FLAG_LEGACY) -o test test/flags/LegacyNames.thrift $(THRIFT) --gen $(ERL_FLAG_MAPS) -o test test/flags/Thrift3214.thrift touch .generated all: .generated $(REBAR) compile check: .generated $(REBAR) eunit install: all mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) ; \ mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/ebin ; \ mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/include ; \ mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/src ; \ for p in ebin/*.app* ebin/*.beam include/*.hrl src/*.erl ; \ do $(INSTALL) $$p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/$$p ; \ done uninstall: $(RM) -rf $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) clean-local: $(REBAR) clean $(RM) .generated $(RM) -r .rebar/ $(RM) -r _build/ $(RM) -r test/gen-erl/ $(RM) $(THRIFT_OMIT_FILE) maintainer-clean-local: $(RM) -r ebin/ dist-hook: $(RM) $(distdir)/.generated $(RM) -r $(distdir)/.rebar/ $(RM) -r $(distdir)/_build/ $(RM) -r $(distdir)/ebin/ $(RM) -r $(distdir)/test/gen-erl/ $(RM) $(distdir)/$(THRIFT_OMIT_FILE) EXTRA_DIST = \ include \ src \ coding_standards.md \ rebar.config \ rebar.config.script \ test \ README.md MAINTAINERCLEANFILES = Makefile.in thrift-0.19.0/lib/erl/src/0000777000000000000000000000000014454461475015240 5ustar00rootroot00000000000000thrift-0.19.0/lib/erl/src/thrift_binary_protocol.erl0000644000000000000000000002612714303740367022526 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_binary_protocol). -behaviour(thrift_protocol). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -export([new/1, new/2, read/2, write/2, flush_transport/1, close_transport/1, new_protocol_factory/2 ]). -record(binary_protocol, {transport, strict_read=true, strict_write=true }). -type state() :: #binary_protocol{}. -include("thrift_protocol_behaviour.hrl"). -define(VERSION_MASK, 16#FFFF0000). -define(VERSION_1, 16#80010000). -define(TYPE_MASK, 16#000000ff). new(Transport) -> new(Transport, _Options = []). new(Transport, Options) -> State = #binary_protocol{transport = Transport}, State1 = parse_options(Options, State), thrift_protocol:new(?MODULE, State1). parse_options([], State) -> State; parse_options([{strict_read, Bool} | Rest], State) when is_boolean(Bool) -> parse_options(Rest, State#binary_protocol{strict_read=Bool}); parse_options([{strict_write, Bool} | Rest], State) when is_boolean(Bool) -> parse_options(Rest, State#binary_protocol{strict_write=Bool}). flush_transport(This = #binary_protocol{transport = Transport}) -> {NewTransport, Result} = thrift_transport:flush(Transport), {This#binary_protocol{transport = NewTransport}, Result}. close_transport(This = #binary_protocol{transport = Transport}) -> {NewTransport, Result} = thrift_transport:close(Transport), {This#binary_protocol{transport = NewTransport}, Result}. %%% %%% instance methods %%% write(This0, #protocol_message_begin{ name = Name, type = Type, seqid = Seqid}) -> case This0#binary_protocol.strict_write of true -> {This1, ok} = write(This0, {i32, ?VERSION_1 bor Type}), {This2, ok} = write(This1, {string, Name}), {This3, ok} = write(This2, {i32, Seqid}), {This3, ok}; false -> {This1, ok} = write(This0, {string, Name}), {This2, ok} = write(This1, {byte, Type}), {This3, ok} = write(This2, {i32, Seqid}), {This3, ok} end; write(This, message_end) -> {This, ok}; write(This0, #protocol_field_begin{ name = _Name, type = Type, id = Id}) -> {This1, ok} = write(This0, {byte, Type}), {This2, ok} = write(This1, {i16, Id}), {This2, ok}; write(This, field_stop) -> write(This, {byte, ?tType_STOP}); write(This, field_end) -> {This, ok}; write(This0, #protocol_map_begin{ ktype = Ktype, vtype = Vtype, size = Size}) -> {This1, ok} = write(This0, {byte, Ktype}), {This2, ok} = write(This1, {byte, Vtype}), {This3, ok} = write(This2, {i32, Size}), {This3, ok}; write(This, map_end) -> {This, ok}; write(This0, #protocol_list_begin{ etype = Etype, size = Size}) -> {This1, ok} = write(This0, {byte, Etype}), {This2, ok} = write(This1, {i32, Size}), {This2, ok}; write(This, list_end) -> {This, ok}; write(This0, #protocol_set_begin{ etype = Etype, size = Size}) -> {This1, ok} = write(This0, {byte, Etype}), {This2, ok} = write(This1, {i32, Size}), {This2, ok}; write(This, set_end) -> {This, ok}; write(This, #protocol_struct_begin{}) -> {This, ok}; write(This, struct_end) -> {This, ok}; write(This, {bool, true}) -> write(This, {byte, 1}); write(This, {bool, false}) -> write(This, {byte, 0}); write(This, {byte, Byte}) -> write(This, <>); write(This, {i16, I16}) -> write(This, <>); write(This, {i32, I32}) -> write(This, <>); write(This, {i64, I64}) -> write(This, <>); write(This, {double, Double}) -> write(This, <>); write(This0, {string, Str}) when is_list(Str) -> {This1, ok} = write(This0, {i32, length(Str)}), {This2, ok} = write(This1, list_to_binary(Str)), {This2, ok}; write(This0, {string, Bin}) when is_binary(Bin) -> {This1, ok} = write(This0, {i32, size(Bin)}), {This2, ok} = write(This1, Bin), {This2, ok}; %% Data :: iolist() write(This = #binary_protocol{transport = Trans}, Data) -> {NewTransport, Result} = thrift_transport:write(Trans, Data), {This#binary_protocol{transport = NewTransport}, Result}. %% read(This0, message_begin) -> {This1, Initial} = read(This0, ui32), case Initial of {ok, Sz} when Sz band ?VERSION_MASK =:= ?VERSION_1 -> %% we're at version 1 {This2, {ok, Name}} = read(This1, string), {This3, {ok, SeqId}} = read(This2, i32), Type = Sz band ?TYPE_MASK, {This3, #protocol_message_begin{name = binary_to_list(Name), type = Type, seqid = SeqId}}; {ok, Sz} when Sz < 0 -> %% there's a version number but it's unexpected {This1, {error, {bad_binary_protocol_version, Sz}}}; {ok, _Sz} when This1#binary_protocol.strict_read =:= true -> %% strict_read is true and there's no version header; that's an error {This1, {error, no_binary_protocol_version}}; {ok, Sz} when This1#binary_protocol.strict_read =:= false -> %% strict_read is false, so just read the old way {This2, {ok, Name}} = read_data(This1, Sz), {This3, {ok, Type}} = read(This2, byte), {This4, {ok, SeqId}} = read(This3, i32), {This4, #protocol_message_begin{name = binary_to_list(Name), type = Type, seqid = SeqId}}; Else -> {This1, Else} end; read(This, message_end) -> {This, ok}; read(This, struct_begin) -> {This, ok}; read(This, struct_end) -> {This, ok}; read(This0, field_begin) -> {This1, Result} = read(This0, byte), case Result of {ok, Type = ?tType_STOP} -> {This1, #protocol_field_begin{type = Type}}; {ok, Type} -> {This2, {ok, Id}} = read(This1, i16), {This2, #protocol_field_begin{type = Type, id = Id}} end; read(This, field_end) -> {This, ok}; read(This0, map_begin) -> {This1, {ok, Ktype}} = read(This0, byte), {This2, {ok, Vtype}} = read(This1, byte), {This3, {ok, Size}} = read(This2, i32), {This3, #protocol_map_begin{ktype = Ktype, vtype = Vtype, size = Size}}; read(This, map_end) -> {This, ok}; read(This0, list_begin) -> {This1, {ok, Etype}} = read(This0, byte), {This2, {ok, Size}} = read(This1, i32), {This2, #protocol_list_begin{etype = Etype, size = Size}}; read(This, list_end) -> {This, ok}; read(This0, set_begin) -> {This1, {ok, Etype}} = read(This0, byte), {This2, {ok, Size}} = read(This1, i32), {This2, #protocol_set_begin{etype = Etype, size = Size}}; read(This, set_end) -> {This, ok}; read(This0, field_stop) -> {This1, {ok, ?tType_STOP}} = read(This0, byte), {This1, ok}; %% read(This0, bool) -> {This1, Result} = read(This0, byte), case Result of {ok, Byte} -> {This1, {ok, Byte /= 0}}; Else -> {This1, Else} end; read(This0, byte) -> {This1, Bytes} = read_data(This0, 1), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; read(This0, i16) -> {This1, Bytes} = read_data(This0, 2), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; read(This0, i32) -> {This1, Bytes} = read_data(This0, 4), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; %% unsigned ints aren't used by thrift itself, but it's used for the parsing %% of the packet version header. Without this special function BEAM works fine %% but hipe thinks it received a bad version header. read(This0, ui32) -> {This1, Bytes} = read_data(This0, 4), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; read(This0, i64) -> {This1, Bytes} = read_data(This0, 8), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; read(This0, double) -> {This1, Bytes} = read_data(This0, 8), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; % returns a binary directly, call binary_to_list if necessary read(This0, string) -> {This1, {ok, Sz}} = read(This0, i32), read_data(This1, Sz). -spec read_data(#binary_protocol{}, non_neg_integer()) -> {#binary_protocol{}, {ok, binary()} | {error, _Reason}}. read_data(This, 0) -> {This, {ok, <<>>}}; read_data(This = #binary_protocol{transport = Trans}, Len) when is_integer(Len) andalso Len > 0 -> {NewTransport, Result} = thrift_transport:read(Trans, Len), {This#binary_protocol{transport = NewTransport}, Result}. %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -record(tbp_opts, {strict_read = true, strict_write = true}). parse_factory_options([], Opts) -> Opts; parse_factory_options([{strict_read, Bool} | Rest], Opts) when is_boolean(Bool) -> parse_factory_options(Rest, Opts#tbp_opts{strict_read=Bool}); parse_factory_options([{strict_write, Bool} | Rest], Opts) when is_boolean(Bool) -> parse_factory_options(Rest, Opts#tbp_opts{strict_write=Bool}). %% returns a (fun() -> thrift_protocol()) new_protocol_factory(TransportFactory, Options) -> ParsedOpts = parse_factory_options(Options, #tbp_opts{}), F = fun() -> case TransportFactory() of {ok, Transport} -> thrift_binary_protocol:new( Transport, [{strict_read, ParsedOpts#tbp_opts.strict_read}, {strict_write, ParsedOpts#tbp_opts.strict_write}]); {error, Error} -> {error, Error} end end, {ok, F}. thrift-0.19.0/lib/erl/src/thrift_json_parser.erl0000644000000000000000000004655214303740367021652 0ustar00rootroot00000000000000%% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% The json parser implementation was created by %% alisdair sullivan based on %% the jsx json library -module(thrift_json_parser). -export([parser/0, handle_event/2]). -record(config, {strict_utf8 = false :: boolean()}). parser() -> fun(JSON) -> start(JSON, {?MODULE, []}, [], #config{}) end. handle_event(Event, {Handler, State}, _Config) -> {Handler, Handler:handle_event(Event, State)}. handle_event(end_json, State) -> lists:reverse([end_json] ++ State); handle_event(Event, State) -> [Event] ++ State. %% whitespace -define(space, 16#20). -define(tab, 16#09). -define(cr, 16#0D). -define(newline, 16#0A). %% object delimiters -define(start_object, 16#7B). -define(end_object, 16#7D). %% array delimiters -define(start_array, 16#5B). -define(end_array, 16#5D). %% kv seperator -define(comma, 16#2C). -define(doublequote, 16#22). -define(singlequote, 16#27). -define(colon, 16#3A). %% string escape sequences -define(rsolidus, 16#5C). -define(solidus, 16#2F). %% math -define(zero, 16#30). -define(decimalpoint, 16#2E). -define(negative, 16#2D). -define(positive, 16#2B). %% comments -define(star, 16#2A). %% some useful guards -define(is_hex(Symbol), (Symbol >= $a andalso Symbol =< $f) orelse (Symbol >= $A andalso Symbol =< $F) orelse (Symbol >= $0 andalso Symbol =< $9) ). -define(is_nonzero(Symbol), Symbol >= $1 andalso Symbol =< $9 ). -define(is_whitespace(Symbol), Symbol =:= ?space; Symbol =:= ?tab; Symbol =:= ?cr; Symbol =:= ?newline ). %% lists are benchmarked to be faster (tho higher in memory usage) than binaries new_seq() -> []. new_seq(C) -> [C]. acc_seq(Seq, C) when is_list(C) -> lists:reverse(C) ++ Seq; acc_seq(Seq, C) -> [C] ++ Seq. end_seq(Seq) -> unicode:characters_to_binary(lists:reverse(Seq)). end_seq(Seq, _) -> end_seq(Seq). start(<<16#ef, 16#bb, 16#bf, Rest/binary>>, Handler, Stack, Config) -> value(Rest, Handler, Stack, Config); start(Bin, Handler, Stack, Config) -> value(Bin, Handler, Stack, Config). value(<>, Handler, Stack, Config) -> string(Rest, Handler, new_seq(), Stack, Config); value(<<$t, Rest/binary>>, Handler, Stack, Config) -> true(Rest, Handler, Stack, Config); value(<<$f, Rest/binary>>, Handler, Stack, Config) -> false(Rest, Handler, Stack, Config); value(<<$n, Rest/binary>>, Handler, Stack, Config) -> null(Rest, Handler, Stack, Config); value(<>, Handler, Stack, Config) -> negative(Rest, Handler, new_seq($-), Stack, Config); value(<>, Handler, Stack, Config) -> zero(Rest, Handler, new_seq($0), Stack, Config); value(<>, Handler, Stack, Config) when ?is_nonzero(S) -> integer(Rest, Handler, new_seq(S), Stack, Config); value(<>, Handler, Stack, Config) -> object(Rest, handle_event(start_object, Handler, Config), [key|Stack], Config); value(<>, Handler, Stack, Config) -> array(Rest, handle_event(start_array, Handler, Config), [array|Stack], Config); value(<>, Handler, Stack, Config) when ?is_whitespace(S) -> value(Rest, Handler, Stack, Config); value(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). object(<>, Handler, Stack, Config) -> string(Rest, Handler, new_seq(), Stack, Config); object(<>, Handler, [key|Stack], Config) -> maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); object(<>, Handler, Stack, Config) when ?is_whitespace(S) -> object(Rest, Handler, Stack, Config); object(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). array(<>, Handler, [array|Stack], Config) -> maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); array(<>, Handler, Stack, Config) when ?is_whitespace(S) -> array(Rest, Handler, Stack, Config); array(Bin, Handler, Stack, Config) -> value(Bin, Handler, Stack, Config). colon(<>, Handler, [key|Stack], Config) -> value(Rest, Handler, [object|Stack], Config); colon(<>, Handler, Stack, Config) when ?is_whitespace(S) -> colon(Rest, Handler, Stack, Config); colon(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). key(<>, Handler, Stack, Config) -> string(Rest, Handler, new_seq(), Stack, Config); key(<>, Handler, Stack, Config) when ?is_whitespace(S) -> key(Rest, Handler, Stack, Config); key(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). %% note that if you encounter an error from string and you can't find the clause that %% caused it here, it might be in unescape below string(<>, Handler, Acc, Stack, Config) -> doublequote(Rest, Handler, Acc, Stack, Config); string(<>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, ?solidus), Stack, Config); string(<>, Handler, Acc, Stack, Config) -> unescape(Rest, Handler, Acc, Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#20, X < 16#2028 -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X == 16#2028; X == 16#2029 -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X > 16#2029, X < 16#d800 -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X > 16#dfff, X < 16#fdd0 -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X > 16#fdef, X < 16#fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#10000, X < 16#1fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#20000, X < 16#2fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#30000, X < 16#3fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#40000, X < 16#4fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#50000, X < 16#5fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#60000, X < 16#6fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#70000, X < 16#7fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#80000, X < 16#8fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#90000, X < 16#9fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#a0000, X < 16#afffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#b0000, X < 16#bfffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#c0000, X < 16#cfffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#d0000, X < 16#dfffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#e0000, X < 16#efffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#f0000, X < 16#ffffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); string(<>, Handler, Acc, Stack, Config) when X >= 16#100000, X < 16#10fffe -> string(Rest, Handler, acc_seq(Acc, X), Stack, Config); %% surrogates string(<<237, X, _, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) when X >= 160 -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); %% u+xfffe, u+xffff, control codes and other noncharacters string(<<_/utf8, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); %% u+fffe and u+ffff for R14BXX (subsequent runtimes will happily match the %% preceding clause string(<<239, 191, X, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) when X == 190; X == 191 -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); %% overlong encodings and missing continuations of a 2 byte sequence string(<>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) when X >= 192, X =< 223 -> strip_continuations(Rest, Handler, Acc, Stack, Config, 1); %% overlong encodings and missing continuations of a 3 byte sequence string(<>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) when X >= 224, X =< 239 -> strip_continuations(Rest, Handler, Acc, Stack, Config, 2); %% overlong encodings and missing continuations of a 4 byte sequence string(<>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) when X >= 240, X =< 247 -> strip_continuations(Rest, Handler, Acc, Stack, Config, 3); %% incompletes and unexpected bytes, including orphan continuations string(<<_, Rest/binary>>, Handler, Acc, Stack, Config=#config{strict_utf8=false}) -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); string(_Bin, _Handler, _Acc, _Stack, _Config) -> erlang:error(badarg). doublequote(Rest, Handler, Acc, [key|_] = Stack, Config) -> colon(Rest, handle_event({key, end_seq(Acc, Config)}, Handler, Config), Stack, Config); doublequote(Rest, Handler, Acc, Stack, Config) -> maybe_done(Rest, handle_event({string, end_seq(Acc, Config)}, Handler, Config), Stack, Config). %% strips continuation bytes after bad utf bytes, guards against both too short %% and overlong sequences. N is the maximum number of bytes to strip strip_continuations(<>, Handler, Acc, Stack, Config, 0) -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config); strip_continuations(<>, Handler, Acc, Stack, Config, N) when X >= 128, X =< 191 -> strip_continuations(Rest, Handler, Acc, Stack, Config, N - 1); %% not a continuation byte, insert a replacement character for sequence thus %% far and dispatch back to string strip_continuations(<>, Handler, Acc, Stack, Config, _) -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config). %% this all gets really gross and should probably eventually be folded into %% but for now it fakes being part of string on incompletes and errors unescape(<<$b, Rest/binary>>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\b), Stack, Config); unescape(<<$f, Rest/binary>>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\f), Stack, Config); unescape(<<$n, Rest/binary>>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\n), Stack, Config); unescape(<<$r, Rest/binary>>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\r), Stack, Config); unescape(<<$t, Rest/binary>>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\t), Stack, Config); unescape(<>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\"), Stack, Config); unescape(<>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $\\), Stack, Config); unescape(<>, Handler, Acc, Stack, Config) -> string(Rest, Handler, acc_seq(Acc, $/), Stack, Config); unescape(<<$u, $d, A, B, C, ?rsolidus, $u, $d, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config) when (A == $8 orelse A == $9 orelse A == $a orelse A == $b), (X == $c orelse X == $d orelse X == $e orelse X == $f), ?is_hex(B), ?is_hex(C), ?is_hex(Y), ?is_hex(Z) -> High = erlang:list_to_integer([$d, A, B, C], 16), Low = erlang:list_to_integer([$d, X, Y, Z], 16), Codepoint = (High - 16#d800) * 16#400 + (Low - 16#dc00) + 16#10000, string(Rest, Handler, acc_seq(Acc, Codepoint), Stack, Config); unescape(<<$u, $d, A, B, C, ?rsolidus, $u, W, X, Y, Z, Rest/binary>>, Handler, Acc, Stack, Config) when (A == $8 orelse A == $9 orelse A == $a orelse A == $b), ?is_hex(B), ?is_hex(C), ?is_hex(W), ?is_hex(X), ?is_hex(Y), ?is_hex(Z) -> string(Rest, Handler, acc_seq(Acc, [16#fffd, 16#fffd]), Stack, Config); unescape(<<$u, A, B, C, D, Rest/binary>>, Handler, Acc, Stack, Config) when ?is_hex(A), ?is_hex(B), ?is_hex(C), ?is_hex(D) -> case erlang:list_to_integer([A, B, C, D], 16) of Codepoint when Codepoint < 16#d800; Codepoint > 16#dfff -> string(Rest, Handler, acc_seq(Acc, Codepoint), Stack, Config); _ -> string(Rest, Handler, acc_seq(Acc, 16#fffd), Stack, Config) end; unescape(_Bin, _Handler, _Acc, _Stack, _Config) -> erlang:error(badarg). %% like in strings, there's some pseudo states in here that will never %% show up in errors or incompletes. some show up in value, some show %% up in integer, decimal or exp negative(<<$0, Rest/binary>>, Handler, Acc, Stack, Config) -> zero(Rest, Handler, acc_seq(Acc, $0), Stack, Config); negative(<>, Handler, Acc, Stack, Config) when ?is_nonzero(S) -> integer(Rest, Handler, acc_seq(Acc, S), Stack, Config); negative(_Bin, _Handler, _Acc, _Stack, _Config) -> erlang:error(badarg). zero(<>, Handler, Acc, Stack, Config) -> decimal(Rest, Handler, acc_seq(Acc, ?decimalpoint), Stack, Config); zero(<>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E -> e(Rest, Handler, acc_seq(Acc, ".0e"), Stack, Config); zero(Bin, Handler, Acc, Stack, Config) -> finish_number(Bin, Handler, {zero, Acc}, Stack, Config). integer(<>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> integer(Rest, Handler, acc_seq(Acc, S), Stack, Config); integer(<>, Handler, Acc, Stack, Config) -> initialdecimal(Rest, Handler, acc_seq(Acc, ?decimalpoint), Stack, Config); integer(<>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E -> e(Rest, Handler, acc_seq(Acc, ".0e"), Stack, Config); integer(Bin, Handler, Acc, Stack, Config) -> finish_number(Bin, Handler, {integer, Acc}, Stack, Config). initialdecimal(<>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> decimal(Rest, Handler, acc_seq(Acc, S), Stack, Config); initialdecimal(_Bin, _Handler, _Acc, _Stack, _Config) -> erlang:error(badarg). decimal(<>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> decimal(Rest, Handler, acc_seq(Acc, S), Stack, Config); decimal(<>, Handler, Acc, Stack, Config) when S =:= $e; S =:= $E -> e(Rest, Handler, acc_seq(Acc, $e), Stack, Config); decimal(Bin, Handler, Acc, Stack, Config) -> finish_number(Bin, Handler, {decimal, Acc}, Stack, Config). e(<>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> exp(Rest, Handler, acc_seq(Acc, S), Stack, Config); e(<>, Handler, Acc, Stack, Config) when Sign =:= ?positive; Sign =:= ?negative -> ex(Rest, Handler, acc_seq(Acc, Sign), Stack, Config); e(_Bin, _Handler, _Acc, _Stack, _Config) -> erlang:error(badarg). ex(<>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> exp(Rest, Handler, acc_seq(Acc, S), Stack, Config); ex(_Bin, _Handler, _Acc, _Stack, _Config) -> erlang:error(badarg). exp(<>, Handler, Acc, Stack, Config) when S =:= ?zero; ?is_nonzero(S) -> exp(Rest, Handler, acc_seq(Acc, S), Stack, Config); exp(Bin, Handler, Acc, Stack, Config) -> finish_number(Bin, Handler, {exp, Acc}, Stack, Config). finish_number(Rest, Handler, Acc, [], Config) -> maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), [], Config); finish_number(Rest, Handler, Acc, Stack, Config) -> maybe_done(Rest, handle_event(format_number(Acc), Handler, Config), Stack, Config). format_number({zero, Acc}) -> {integer, list_to_integer(lists:reverse(Acc))}; format_number({integer, Acc}) -> {integer, list_to_integer(lists:reverse(Acc))}; format_number({decimal, Acc}) -> {float, list_to_float(lists:reverse(Acc))}; format_number({exp, Acc}) -> {float, list_to_float(lists:reverse(Acc))}. true(<<$r, $u, $e, Rest/binary>>, Handler, Stack, Config) -> maybe_done(Rest, handle_event({literal, true}, Handler, Config), Stack, Config); true(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). false(<<$a, $l, $s, $e, Rest/binary>>, Handler, Stack, Config) -> maybe_done(Rest, handle_event({literal, false}, Handler, Config), Stack, Config); false(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). null(<<$u, $l, $l, Rest/binary>>, Handler, Stack, Config) -> maybe_done(Rest, handle_event({literal, null}, Handler, Config), Stack, Config); null(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). maybe_done(<>, Handler, [], Config) -> done(Rest, handle_event(end_json, Handler, Config), [], Config); maybe_done(<>, Handler, [object|Stack], Config) -> maybe_done(Rest, handle_event(end_object, Handler, Config), Stack, Config); maybe_done(<>, Handler, [array|Stack], Config) -> maybe_done(Rest, handle_event(end_array, Handler, Config), Stack, Config); maybe_done(<>, Handler, [object|Stack], Config) -> key(Rest, Handler, [key|Stack], Config); maybe_done(<>, Handler, [array|_] = Stack, Config) -> value(Rest, Handler, Stack, Config); maybe_done(<>, Handler, Stack, Config) when ?is_whitespace(S) -> maybe_done(Rest, Handler, Stack, Config); maybe_done(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). done(<>, Handler, [], Config) when ?is_whitespace(S) -> done(Rest, Handler, [], Config); done(<<>>, {_Handler, State}, [], _Config) -> State; done(_Bin, _Handler, _Stack, _Config) -> erlang:error(badarg). thrift-0.19.0/lib/erl/src/thrift_transport.erl0000644000000000000000000000746714303740367021363 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_transport). -export([behaviour_info/1]). %% constructors -export([new/1, new/2]). %% transport callbacks -export([read/2, read_exact/2, write/2, flush/1, close/1]). -export_type([t_transport/0]). behaviour_info(callbacks) -> [{read, 2}, {write, 2}, {flush, 1}, {close, 1}]. -record(t_transport, { module, state }). -type state() :: #t_transport{}. -type t_transport() :: #t_transport{}. -ifdef(transport_wrapper_module). -define(debug_wrap(Transport), case Transport#t_transport.module of ?transport_wrapper_module -> Transport; _Else -> {ok, Result} = ?transport_wrapper_module:new(Transport), Result end ). -else. -define(debug_wrap(Transport), Transport). -endif. -type wrappable() :: binary() | list() | {membuffer, binary() | list()} | {tcp, port()} | {tcp, port(), list()} | {file, file:io_device()} | {file, file:io_device(), list()} | {file, file:filename()} | {file, file:filename(), list()}. -spec new(wrappable()) -> {ok, #t_transport{}}. new({membuffer, Membuffer}) when is_binary(Membuffer); is_list(Membuffer) -> thrift_membuffer_transport:new(Membuffer); new({membuffer, Membuffer, []}) when is_binary(Membuffer); is_list(Membuffer) -> thrift_membuffer_transport:new(Membuffer); new({tcp, Socket}) when is_port(Socket) -> new({tcp, Socket, []}); new({tcp, Socket, Opts}) when is_port(Socket) -> thrift_socket_transport:new(Socket, Opts); new({file, Filename}) when is_list(Filename); is_binary(Filename) -> new({file, Filename, []}); new({file, Filename, Opts}) when is_list(Filename); is_binary(Filename) -> {ok, File} = file:open(Filename, [raw, binary]), new({file, File, Opts}); new({file, File, Opts}) -> thrift_file_transport:new(File, Opts). -spec new(Module::module(), State::any()) -> {ok, #t_transport{}}. new(Module, State) when is_atom(Module) -> {ok, ?debug_wrap(#t_transport{module = Module, state = State})}. -include("thrift_transport_behaviour.hrl"). read(Transport = #t_transport{module = Module}, Len) when is_integer(Len), Len >= 0 -> {NewState, Result} = Module:read(Transport#t_transport.state, Len), {Transport#t_transport{state = NewState}, Result}. read_exact(Transport = #t_transport{module = Module}, Len) when is_integer(Len), Len >= 0 -> case lists:keyfind(read_exact, 1, Module:module_info(exports)) of {read_exact, 2} -> {NewState, Result} = Module:read_exact(Transport#t_transport.state, Len), {Transport#t_transport{state = NewState}, Result}; _ -> read(Transport, Len) end. write(Transport = #t_transport{module = Module}, Data) -> {NewState, Result} = Module:write(Transport#t_transport.state, Data), {Transport#t_transport{state = NewState}, Result}. flush(Transport = #t_transport{module = Module}) -> {NewState, Result} = Module:flush(Transport#t_transport.state), {Transport#t_transport{state = NewState}, Result}. close(Transport = #t_transport{module = Module}) -> {NewState, Result} = Module:close(Transport#t_transport.state), {Transport#t_transport{state = NewState}, Result}. thrift-0.19.0/lib/erl/src/thrift.app.src0000644000000000000000000000477014454461475020034 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %%% -*- mode:erlang -*- {application, thrift, [ % A quick description of the application. {description, "Thrift bindings"}, % The version of the applicaton {vsn, "0.19.0"}, % All modules used by the application. {modules, [ thrift_base64_transport, thrift_binary_protocol, thrift_buffered_transport, thrift_client_util, thrift_client, thrift_disk_log_transport, thrift_file_transport, thrift_framed_transport, thrift_http_transport, thrift_json_parser, thrift_json_protocol, thrift_membuffer_transport, thrift_memory_buffer, thrift_processor, thrift_protocol, thrift_reconnecting_client, thrift_server, thrift_service, thrift_socket_server, thrift_socket_transport, thrift_transport_state_test, thrift_transport ]}, % All of the registered names the application uses. This can be ignored. {registered, []}, % Applications that are to be started prior to this one. This can be ignored % leave it alone unless you understand it well and let the .rel files in % your release handle this. {applications, [kernel, stdlib]}, % OTP application loader will load, but not start, included apps. Again % this can be ignored as well. To load but not start an application it % is easier to include it in the .rel file followed by the atom 'none' {included_applications, []}, % configuration parameters similar to those in the config file specified % on the command line. can be fetched with gas:get_env {env, [ % If an error/crash occurs during processing of a function, % should the TApplicationException serialized back to the client % include the erlang backtrace? {exceptions_include_traces, true} ]} ]}. thrift-0.19.0/lib/erl/src/thrift_base64_transport.erl0000644000000000000000000000433214303740367022513 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_base64_transport). -behaviour(thrift_transport). %% API -export([new/1, new_transport_factory/1]). %% thrift_transport callbacks -export([write/2, read/2, flush/1, close/1]). %% State -record(b64_transport, {wrapped}). -type state() :: #b64_transport{}. -include("thrift_transport_behaviour.hrl"). new(Wrapped) -> State = #b64_transport{wrapped = Wrapped}, thrift_transport:new(?MODULE, State). write(This = #b64_transport{wrapped = Wrapped}, Data) -> {NewWrapped, Result} = thrift_transport:write(Wrapped, base64:encode(iolist_to_binary(Data))), {This#b64_transport{wrapped = NewWrapped}, Result}. %% base64 doesn't support reading quite yet since it would involve %% nasty buffering and such read(This = #b64_transport{}, _Data) -> {This, {error, no_reads_allowed}}. flush(This = #b64_transport{wrapped = Wrapped0}) -> {Wrapped1, ok} = thrift_transport:write(Wrapped0, <<"\n">>), {Wrapped2, ok} = thrift_transport:flush(Wrapped1), {This#b64_transport{wrapped = Wrapped2}, ok}. close(This0) -> {This1 = #b64_transport{wrapped = Wrapped}, ok} = flush(This0), {NewWrapped, ok} = thrift_transport:close(Wrapped), {This1#b64_transport{wrapped = NewWrapped}, ok}. %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% new_transport_factory(WrapFactory) -> F = fun() -> {ok, Wrapped} = WrapFactory(), new(Wrapped) end, {ok, F}. thrift-0.19.0/lib/erl/src/thrift_compact_protocol.erl0000644000000000000000000003154514303740367022670 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_compact_protocol). -behaviour(thrift_protocol). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -export([new/1, new/2, read/2, write/2, flush_transport/1, close_transport/1, new_protocol_factory/2 ]). -define(ID_NONE, 16#10000). -define(CBOOL_NONE, 0). -define(CBOOL_TRUE, 1). -define(CBOOL_FALSE, 2). -record(t_compact, {transport, % state for pending boolean fields read_stack=[], read_value=?CBOOL_NONE, write_stack=[], write_id=?ID_NONE }). -type state() :: #t_compact{}. -include("thrift_protocol_behaviour.hrl"). -define(PROTOCOL_ID, 16#82). -define(VERSION_MASK, 16#1f). -define(VERSION_1, 16#01). -define(TYPE_MASK, 16#E0). -define(TYPE_BITS, 16#07). -define(TYPE_SHIFT_AMOUNT, 5). typeid_to_compact(?tType_STOP) -> 16#0; typeid_to_compact(?tType_BOOL) -> 16#2; typeid_to_compact(?tType_I8) -> 16#3; typeid_to_compact(?tType_I16) -> 16#4; typeid_to_compact(?tType_I32) -> 16#5; typeid_to_compact(?tType_I64) -> 16#6; typeid_to_compact(?tType_DOUBLE) -> 16#7; typeid_to_compact(?tType_STRING) -> 16#8; typeid_to_compact(?tType_STRUCT) -> 16#C; typeid_to_compact(?tType_MAP) -> 16#B; typeid_to_compact(?tType_SET) -> 16#A; typeid_to_compact(?tType_LIST) -> 16#9. compact_to_typeid(16#0) -> ?tType_STOP; compact_to_typeid(?CBOOL_FALSE) -> ?tType_BOOL; compact_to_typeid(?CBOOL_TRUE) -> ?tType_BOOL; compact_to_typeid(16#7) -> ?tType_DOUBLE; compact_to_typeid(16#3) -> ?tType_I8; compact_to_typeid(16#4) -> ?tType_I16; compact_to_typeid(16#5) -> ?tType_I32; compact_to_typeid(16#6) -> ?tType_I64; compact_to_typeid(16#8) -> ?tType_STRING; compact_to_typeid(16#C) -> ?tType_STRUCT; compact_to_typeid(16#B) -> ?tType_MAP; compact_to_typeid(16#A) -> ?tType_SET; compact_to_typeid(16#9) -> ?tType_LIST. bool_to_cbool(Value) when Value -> ?CBOOL_TRUE; bool_to_cbool(_) -> ?CBOOL_FALSE. cbool_to_bool(Value) -> Value =:= ?CBOOL_TRUE. new(Transport) -> new(Transport, _Options = []). new(Transport, _Options) -> State = #t_compact{transport = Transport}, thrift_protocol:new(?MODULE, State). flush_transport(This = #t_compact{transport = Transport}) -> {NewTransport, Result} = thrift_transport:flush(Transport), {This#t_compact{transport = NewTransport}, Result}. close_transport(This = #t_compact{transport = Transport}) -> {NewTransport, Result} = thrift_transport:close(Transport), {This#t_compact{transport = NewTransport}, Result}. %%% %%% instance methods %%% write_field_begin(This0 = #t_compact{write_stack=[LastId|T]}, CompactType, Id) -> IdDiff = Id - LastId, This1 = This0#t_compact{write_stack=[Id|T]}, case (IdDiff > 0) and (IdDiff < 16) of true -> write(This1, {byte, (IdDiff bsl 4) bor CompactType}); false -> {This2, ok} = write(This1, {byte, CompactType}), write(This2, {i16, Id}) end. -spec to_zigzag(integer()) -> non_neg_integer(). to_zigzag(Value) -> 16#FFFFFFFFFFFFFFFF band ((Value bsl 1) bxor (Value bsr 63)). -spec from_zigzag(non_neg_integer()) -> integer(). from_zigzag(Value) -> (Value bsr 1) bxor -(Value band 1). -spec to_varint(non_neg_integer(), iolist()) -> iolist(). to_varint(Value, Acc) when (Value < 16#80) -> [Acc, Value]; to_varint(Value, Acc) -> to_varint(Value bsr 7, [Acc, ((Value band 16#7F) bor 16#80)]). -spec read_varint(#t_compact{}, non_neg_integer(), non_neg_integer()) -> non_neg_integer(). read_varint(This0, Acc, Count) -> {This1, {ok, Byte}} = read(This0, byte), case (Byte band 16#80) of 0 -> {This1, {ok, (Byte bsl (7 * Count)) + Acc}}; _ -> read_varint(This1, ((Byte band 16#7f) bsl (7 * Count)) + Acc, Count + 1) end. write(This0, #protocol_message_begin{ name = Name, type = Type, seqid = Seqid}) -> {This1, ok} = write(This0, {byte, ?PROTOCOL_ID}), {This2, ok} = write(This1, {byte, (?VERSION_1 band ?VERSION_MASK) bor (Type bsl ?TYPE_SHIFT_AMOUNT)}), {This3, ok} = write(This2, {ui32, Seqid}), {This4, ok} = write(This3, {string, Name}), {This4, ok}; write(This, message_end) -> {This, ok}; write(This0, #protocol_field_begin{ name = _Name, type = Type, id = Id}) when (Type =:= ?tType_BOOL) -> {This0#t_compact{write_id = Id}, ok}; write(This0, #protocol_field_begin{ name = _Name, type = Type, id = Id}) -> write_field_begin(This0, typeid_to_compact(Type), Id); write(This, field_stop) -> write(This, {byte, ?tType_STOP}); write(This, field_end) -> {This, ok}; write(This0, #protocol_map_begin{ ktype = _Ktype, vtype = _Vtype, size = Size}) when Size =:= 0 -> write(This0, {byte, 0}); write(This0, #protocol_map_begin{ ktype = Ktype, vtype = Vtype, size = Size}) -> {This1, ok} = write(This0, {ui32, Size}), write(This1, {byte, (typeid_to_compact(Ktype) bsl 4) bor typeid_to_compact(Vtype)}); write(This, map_end) -> {This, ok}; write(This0, #protocol_list_begin{ etype = Etype, size = Size}) when Size < 16#f -> write(This0, {byte, (Size bsl 4) bor typeid_to_compact(Etype)}); write(This0, #protocol_list_begin{ etype = Etype, size = Size}) -> {This1, ok} = write(This0, {byte, 16#f0 bor typeid_to_compact(Etype)}), write(This1, {ui32, Size}); write(This, list_end) -> {This, ok}; write(This0, #protocol_set_begin{ etype = Etype, size = Size}) -> write(This0, #protocol_list_begin{etype = Etype, size = Size}); write(This, set_end) -> {This, ok}; write(This = #t_compact{write_stack = Stack}, #protocol_struct_begin{}) -> {This#t_compact{write_stack = [0|Stack]}, ok}; write(This = #t_compact{write_stack = [_|T]}, struct_end) -> {This#t_compact{write_stack = T}, ok}; write(This = #t_compact{write_id = ?ID_NONE}, {bool, Value}) -> write(This, {byte, bool_to_cbool(Value)}); write(This0 = #t_compact{write_id = Id}, {bool, Value}) -> {This1, ok} = write_field_begin(This0, bool_to_cbool(Value), Id), {This1#t_compact{write_id = ?ID_NONE}, ok}; write(This, {byte, Value}) when is_integer(Value) -> write(This, <>); write(This, {i16, Value}) when is_integer(Value) -> write(This, to_varint(to_zigzag(Value), [])); write(This, {ui32, Value}) when is_integer(Value) -> write(This, to_varint(Value, [])); write(This, {i32, Value}) when is_integer(Value) -> write(This, to_varint(to_zigzag(Value), [])); write(This, {i64, Value}) when is_integer(Value) -> write(This, to_varint(to_zigzag(Value), [])); write(This, {double, Double}) -> write(This, <>); write(This0, {string, Str}) when is_list(Str) -> % TODO: limit length {This1, ok} = write(This0, {ui32, length(Str)}), {This2, ok} = write(This1, list_to_binary(Str)), {This2, ok}; write(This0, {string, Bin}) when is_binary(Bin) -> % TODO: limit length {This1, ok} = write(This0, {ui32, size(Bin)}), {This2, ok} = write(This1, Bin), {This2, ok}; %% Data :: iolist() write(This = #t_compact{transport = Trans}, Data) -> {NewTransport, Result} = thrift_transport:write(Trans, Data), {This#t_compact{transport = NewTransport}, Result}. %% %% read(This0, message_begin) -> {This1, {ok, ?PROTOCOL_ID}} = read(This0, ubyte), {This2, {ok, VerAndType}} = read(This1, ubyte), ?VERSION_1 = VerAndType band ?VERSION_MASK, {This3, {ok, SeqId}} = read(This2, ui32), {This4, {ok, Name}} = read(This3, string), {This4, #protocol_message_begin{ name = binary_to_list(Name), type = (VerAndType bsr ?TYPE_SHIFT_AMOUNT) band ?TYPE_BITS, seqid = SeqId}}; read(This, message_end) -> {This, ok}; read(This = #t_compact{read_stack = Stack}, struct_begin) -> {This#t_compact{read_stack = [0|Stack]}, ok}; read(This = #t_compact{read_stack = [_H|T]}, struct_end) -> {This#t_compact{read_stack = T}, ok}; read(This0 = #t_compact{read_stack = [LastId|T]}, field_begin) -> {This1, {ok, Byte}} = read(This0, ubyte), case Byte band 16#f of CompactType = ?tType_STOP -> {This1, #protocol_field_begin{type = CompactType}}; CompactType -> {This2, {ok, Id}} = case Byte bsr 4 of 0 -> read(This1, i16); IdDiff -> {This1, {ok, LastId + IdDiff}} end, case compact_to_typeid(CompactType) of ?tType_BOOL -> {This2#t_compact{read_stack = [Id|T], read_value = cbool_to_bool(CompactType)}, #protocol_field_begin{type = ?tType_BOOL, id = Id}}; Type -> {This2#t_compact{read_stack = [Id|T]}, #protocol_field_begin{type = Type, id = Id}} end end; read(This, field_end) -> {This, ok}; read(This0, map_begin) -> {This1, {ok, Size}} = read(This0, ui32), {This2, {ok, KV}} = case Size of 0 -> {This1, {ok, 0}}; _ -> read(This1, ubyte) end, {This2, #protocol_map_begin{ktype = compact_to_typeid(KV bsr 4), vtype = compact_to_typeid(KV band 16#f), size = Size}}; read(This, map_end) -> {This, ok}; read(This0, list_begin) -> {This1, {ok, SizeAndType}} = read(This0, ubyte), {This2, {ok, Size}} = case (SizeAndType bsr 4) band 16#f of 16#f -> read(This1, ui32); Else -> {This1, {ok, Else}} end, {This2, #protocol_list_begin{etype = compact_to_typeid(SizeAndType band 16#f), size = Size}}; read(This, list_end) -> {This, ok}; read(This0, set_begin) -> {This1, {ok, SizeAndType}} = read(This0, ubyte), {This2, {ok, Size}} = case (SizeAndType bsr 4) band 16#f of 16#f -> read(This1, ui32); Else -> {This1, {ok, Else}} end, {This2, #protocol_set_begin{etype = compact_to_typeid(SizeAndType band 16#f), size = Size}}; read(This, set_end) -> {This, ok}; read(This0, field_stop) -> {This1, {ok, ?tType_STOP}} = read(This0, ubyte), {This1, ok}; %% read(This0 = #t_compact{read_value = ?CBOOL_NONE}, bool) -> {This1, {ok, Byte}} = read(This0, ubyte), {This1, {ok, cbool_to_bool(Byte)}}; read(This0 = #t_compact{read_value = Bool}, bool) -> {This0#t_compact{read_value = ?CBOOL_NONE}, {ok, Bool}}; read(This0, ubyte) -> {This1, {ok, <>}} = read_data(This0, 1), {This1, {ok, Val}}; read(This0, byte) -> {This1, Bytes} = read_data(This0, 1), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; read(This0, i16) -> {This1, {ok, Zigzag}} = read_varint(This0, 0, 0), {This1, {ok, from_zigzag(Zigzag)}}; read(This0, ui32) -> read_varint(This0, 0, 0); read(This0, i32) -> {This1, {ok, Zigzag}} = read_varint(This0, 0, 0), {This1, {ok, from_zigzag(Zigzag)}}; read(This0, i64) -> {This1, {ok, Zigzag}} = read_varint(This0, 0, 0), {This1, {ok, from_zigzag(Zigzag)}}; read(This0, double) -> {This1, Bytes} = read_data(This0, 8), case Bytes of {ok, <>} -> {This1, {ok, Val}}; Else -> {This1, Else} end; % returns a binary directly, call binary_to_list if necessary read(This0, string) -> {This1, {ok, Sz}} = read(This0, ui32), read_data(This1, Sz). -spec read_data(#t_compact{}, non_neg_integer()) -> {#t_compact{}, {ok, binary()} | {error, _Reason}}. read_data(This, 0) -> {This, {ok, <<>>}}; read_data(This = #t_compact{transport = Trans}, Len) when is_integer(Len) andalso Len > 0 -> {NewTransport, Result} = thrift_transport:read(Trans, Len), {This#t_compact{transport = NewTransport}, Result}. %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% returns a (fun() -> thrift_protocol()) new_protocol_factory(TransportFactory, _Options) -> F = fun() -> case TransportFactory() of {ok, Transport} -> thrift_compact_protocol:new( Transport, []); {error, Error} -> {error, Error} end end, {ok, F}. thrift-0.19.0/lib/erl/src/thrift_framed_transport.erl0000644000000000000000000000751614303740367022674 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_framed_transport). -behaviour(thrift_transport). %% constructor -export([new/1]). %% protocol callbacks -export([read/2, read_exact/2, write/2, flush/1, close/1]). -record(t_framed, { wrapped, read_buffer, write_buffer }). -type state() :: #t_framed{}. -spec new(Transport::thrift_transport:t_transport()) -> thrift_transport:t_transport(). new(Wrapped) -> State = #t_framed{ wrapped = Wrapped, read_buffer = [], write_buffer = [] }, thrift_transport:new(?MODULE, State). -include("thrift_transport_behaviour.hrl"). read(State = #t_framed{wrapped = Wrapped, read_buffer = Buffer}, Len) when is_integer(Len), Len >= 0 -> Binary = iolist_to_binary(Buffer), case Binary of <<>> when Len > 0 -> case next_frame(Wrapped) of {NewState, {ok, Frame}} -> NewBinary = iolist_to_binary([Binary, Frame]), Give = min(iolist_size(NewBinary), Len), {Result, Remaining} = split_binary(NewBinary, Give), {State#t_framed{wrapped = NewState, read_buffer = Remaining}, {ok, Result}}; {NewState, Error} -> {State#t_framed{wrapped = NewState}, Error} end; %% read of zero bytes <<>> -> {State, {ok, <<>>}}; %% read buffer is nonempty _ -> Give = min(iolist_size(Binary), Len), {Result, Remaining} = split_binary(Binary, Give), {State#t_framed{read_buffer = Remaining}, {ok, Result}} end. read_exact(State = #t_framed{wrapped = Wrapped, read_buffer = Buffer}, Len) when is_integer(Len), Len >= 0 -> Binary = iolist_to_binary(Buffer), case iolist_size(Binary) of %% read buffer is larger than requested read size X when X >= Len -> {Result, Remaining} = split_binary(Binary, Len), {State#t_framed{read_buffer = Remaining}, {ok, Result}}; %% read buffer is insufficient for requested read size _ -> case next_frame(Wrapped) of {NewState, {ok, Frame}} -> read_exact( State#t_framed{wrapped = NewState, read_buffer = [Buffer, Frame]}, Len ); {NewState, Error} -> {State#t_framed{wrapped = NewState}, Error} end end. next_frame(Transport) -> case thrift_transport:read_exact(Transport, 4) of {NewState, {ok, <>}} -> thrift_transport:read_exact(NewState, FrameLength); Error -> Error end. write(State = #t_framed{write_buffer = Buffer}, Data) -> {State#t_framed{write_buffer = [Buffer, Data]}, ok}. flush(State = #t_framed{write_buffer = Buffer, wrapped = Wrapped}) -> case iolist_size(Buffer) of %% if write buffer is empty, do nothing 0 -> {State, ok}; FrameLen -> Data = [<>, Buffer], {Written, Response} = thrift_transport:write(Wrapped, Data), {Flushed, ok} = thrift_transport:flush(Written), {State#t_framed{wrapped = Flushed, write_buffer = []}, Response} end. close(State = #t_framed{wrapped = Wrapped}) -> {Closed, Result} = thrift_transport:close(Wrapped), {State#t_framed{wrapped = Closed}, Result}. thrift-0.19.0/lib/erl/src/thrift_reconnecting_client.erl0000644000000000000000000002226414303740367023333 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_reconnecting_client). -behaviour(gen_server). %% API -export([ call/3, get_stats/1, get_and_reset_stats/1 ]). -export([ start_link/6 ]). %% gen_server callbacks -export([ init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3 ]). -record( state, { client = nil, host, port, thrift_svc, thrift_opts, reconn_min, reconn_max, reconn_time = 0, op_cnt_dict, op_time_dict } ). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link( Host, Port, ThriftSvc, ThriftOpts, ReconnMin, ReconnMax ) -> gen_server:start_link( ?MODULE, [ Host, Port, ThriftSvc, ThriftOpts, ReconnMin, ReconnMax ], [] ). call( Pid, Op, Args ) -> gen_server:call( Pid, { call, Op, Args } ). get_stats( Pid ) -> gen_server:call( Pid, get_stats ). get_and_reset_stats( Pid ) -> gen_server:call( Pid, get_and_reset_stats ). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Start the server. %%-------------------------------------------------------------------- init( [ Host, Port, TSvc, TOpts, ReconnMin, ReconnMax ] ) -> process_flag( trap_exit, true ), State = #state{ host = Host, port = Port, thrift_svc = TSvc, thrift_opts = TOpts, reconn_min = ReconnMin, reconn_max = ReconnMax, op_cnt_dict = dict:new(), op_time_dict = dict:new() }, { ok, try_connect( State ) }. %%-------------------------------------------------------------------- %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- handle_call( { call, Op, _ }, _From, State = #state{ client = nil } ) -> { reply, { error, noconn }, incr_stats( Op, "failfast", 1, State ) }; handle_call( { call, Op, Args }, _From, State=#state{ client = Client } ) -> Timer = timer_fun(), Result = ( catch thrift_client:call( Client, Op, Args) ), Time = Timer(), case Result of { C, { ok, Reply } } -> S = incr_stats( Op, "success", Time, State#state{ client = C } ), { reply, {ok, Reply }, S }; { _, { E, Msg } } when E == error; E == exception -> S = incr_stats( Op, "error", Time, try_connect( State ) ), { reply, { E, Msg }, S }; Other -> S = incr_stats( Op, "error", Time, try_connect( State ) ), { reply, Other, S } end; handle_call( get_stats, _From, State = #state{} ) -> { reply, stats( State ), State }; handle_call( get_and_reset_stats, _From, State = #state{} ) -> { reply, stats( State ), reset_stats( State ) }. %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- handle_cast( _Msg, State ) -> { noreply, State }. %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- handle_info( try_connect, State ) -> { noreply, try_connect( State ) }; handle_info( _Info, State ) -> { noreply, State }. %%-------------------------------------------------------------------- %% Function: terminate(Reason, State) -> void() %% Description: This function is called by a gen_server when it is about to %% terminate. It should be the opposite of Module:init/1 and do any necessary %% cleaning up. When it returns, the gen_server terminates with Reason. %% The return value is ignored. %%-------------------------------------------------------------------- terminate( _Reason, #state{ client = Client } ) -> thrift_client:close( Client ), ok. %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} %% Description: Convert process state when code is changed %%-------------------------------------------------------------------- code_change( _OldVsn, State, _Extra ) -> { ok, State }. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- try_connect( State = #state{ client = OldClient, host = Host, port = Port, thrift_svc = TSvc, thrift_opts = TOpts } ) -> case OldClient of nil -> ok; _ -> ( catch thrift_client:close( OldClient ) ) end, case catch thrift_client_util:new( Host, Port, TSvc, TOpts ) of { ok, Client } -> State#state{ client = Client, reconn_time = 0 }; { E, Msg } when E == error; E == exception -> ReconnTime = reconn_time( State ), error_logger:error_msg( "[~w] ~w connect failed (~w), trying again in ~w ms~n", [ self(), TSvc, Msg, ReconnTime ] ), erlang:send_after( ReconnTime, self(), try_connect ), State#state{ client = nil, reconn_time = ReconnTime } end. reconn_time( #state{ reconn_min = ReconnMin, reconn_time = 0 } ) -> ReconnMin; reconn_time( #state{ reconn_max = ReconnMax, reconn_time = ReconnMax } ) -> ReconnMax; reconn_time( #state{ reconn_max = ReconnMax, reconn_time = R } ) -> Backoff = 2 * R, case Backoff > ReconnMax of true -> ReconnMax; false -> Backoff end. -ifdef(time_correction). timer_fun() -> T1 = erlang:monotonic_time(), fun() -> T2 = erlang:monotonic_time(), erlang:convert_time_unit(T2 - T1, native, micro_seconds) end. -else. timer_fun() -> T1 = erlang:timestamp(), fun() -> T2 = erlang:timestamp(), timer:now_diff(T2, T1) end. -endif. incr_stats( Op, Result, Time, State = #state{ op_cnt_dict = OpCntDict, op_time_dict = OpTimeDict } ) -> Key = lists:flatten( [ atom_to_list( Op ), [ "_" | Result ] ] ), State#state{ op_cnt_dict = dict:update_counter( Key, 1, OpCntDict ), op_time_dict = dict:update_counter( Key, Time, OpTimeDict ) }. stats( #state{ thrift_svc = TSvc, op_cnt_dict = OpCntDict, op_time_dict = OpTimeDict } ) -> Svc = atom_to_list(TSvc), F = fun( Key, Count, Stats ) -> Name = lists:flatten( [ Svc, [ "_" | Key ] ] ), Micros = dict:fetch( Key, OpTimeDict ), [ { Name, Count, Micros } | Stats ] end, dict:fold( F, [], OpCntDict ). reset_stats( State = #state{} ) -> State#state{ op_cnt_dict = dict:new(), op_time_dict = dict:new() }. thrift-0.19.0/lib/erl/src/thrift_disk_log_transport.erl0000644000000000000000000001012714303740367023221 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %%% Todo: this might be better off as a gen_server type of transport %%% that handles stuff like group commit, similar to TFileTransport %%% in cpp land -module(thrift_disk_log_transport). -behaviour(thrift_transport). %% API -export([new/2, new_transport_factory/2, new_transport_factory/3]). %% thrift_transport callbacks -export([read/2, write/2, force_flush/1, flush/1, close/1]). %% state -record(dl_transport, {log, close_on_close = false, sync_every = infinity, sync_tref}). -type state() :: #dl_transport{}. -include("thrift_transport_behaviour.hrl"). %% Create a transport attached to an already open log. %% If you'd like this transport to close the disk_log using disk_log:lclose() %% when the transport is closed, pass a {close_on_close, true} tuple in the %% Opts list. new(LogName, Opts) when is_atom(LogName), is_list(Opts) -> State = parse_opts(Opts, #dl_transport{log = LogName}), State2 = case State#dl_transport.sync_every of N when is_integer(N), N > 0 -> {ok, TRef} = timer:apply_interval(N, ?MODULE, force_flush, [State]), State#dl_transport{sync_tref = TRef}; _ -> State end, thrift_transport:new(?MODULE, State2). parse_opts([], State) -> State; parse_opts([{close_on_close, Bool} | Rest], State) when is_boolean(Bool) -> parse_opts(Rest, State#dl_transport{close_on_close = Bool}); parse_opts([{sync_every, Int} | Rest], State) when is_integer(Int), Int > 0 -> parse_opts(Rest, State#dl_transport{sync_every = Int}). %%%% TRANSPORT IMPLENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% disk_log_transport is write-only read(State, _Len) -> {State, {error, no_read_from_disk_log}}. write(This = #dl_transport{log = Log}, Data) -> {This, disk_log:balog(Log, erlang:iolist_to_binary(Data))}. force_flush(#dl_transport{log = Log}) -> error_logger:info_msg("~p syncing~n", [?MODULE]), disk_log:sync(Log). flush(This = #dl_transport{log = Log, sync_every = SE}) -> case SE of undefined -> % no time-based sync disk_log:sync(Log); _Else -> % sync will happen automagically ok end, {This, ok}. %% On close, close the underlying log if we're configured to do so. close(This = #dl_transport{close_on_close = false}) -> {This, ok}; close(This = #dl_transport{log = Log}) -> {This, disk_log:lclose(Log)}. %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% new_transport_factory(Name, ExtraLogOpts) -> new_transport_factory(Name, ExtraLogOpts, [{close_on_close, true}, {sync_every, 500}]). new_transport_factory(Name, ExtraLogOpts, TransportOpts) -> F = fun() -> factory_impl(Name, ExtraLogOpts, TransportOpts) end, {ok, F}. factory_impl(Name, ExtraLogOpts, TransportOpts) -> LogOpts = [{name, Name}, {format, external}, {type, wrap} | ExtraLogOpts], Log = case disk_log:open(LogOpts) of {ok, LogS} -> LogS; {repaired, LogS, Info1, Info2} -> error_logger:info_msg("Disk log ~p repaired: ~p, ~p~n", [LogS, Info1, Info2]), LogS end, new(Log, TransportOpts). thrift-0.19.0/lib/erl/src/thrift_multiplexed_protocol.erl0000644000000000000000000000766614303740367023605 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_multiplexed_protocol). -behaviour(thrift_protocol). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -include("thrift_protocol_behaviour.hrl"). -export([new/2, read/2, write/2, flush_transport/1, close_transport/1 ]). -record(protocol, {module, data}). -type protocol() :: #protocol{}. -record (multiplexed_protocol, {protocol_module_to_decorate::atom(), protocol_data_to_decorate::term(), service_name::nonempty_string()}). -type state() :: #multiplexed_protocol{}. -spec new(ProtocolToDecorate::protocol(), ServiceName::nonempty_string()) -> {ok, Protocol::protocol()}. new(ProtocolToDecorate, ServiceName) when is_record(ProtocolToDecorate, protocol), is_list(ServiceName) -> State = #multiplexed_protocol{protocol_module_to_decorate = ProtocolToDecorate#protocol.module, protocol_data_to_decorate = ProtocolToDecorate#protocol.data, service_name = ServiceName}, thrift_protocol:new(?MODULE, State). flush_transport(State = #multiplexed_protocol{protocol_module_to_decorate = ProtocolModuleToDecorate, protocol_data_to_decorate = State0}) -> {State1, ok} = ProtocolModuleToDecorate:flush_transport(State0), {State#multiplexed_protocol{protocol_data_to_decorate = State1}, ok}. close_transport(State = #multiplexed_protocol{protocol_module_to_decorate = ProtocolModuleToDecorate, protocol_data_to_decorate = State0}) -> {State1, ok} = ProtocolModuleToDecorate:close_transport(State0), {State#multiplexed_protocol{protocol_data_to_decorate = State1}, ok}. write(State = #multiplexed_protocol{protocol_module_to_decorate = ProtocolModuleToDecorate, protocol_data_to_decorate = State0, service_name = ServiceName}, Message = #protocol_message_begin{name = Name}) -> {State1, ok} = ProtocolModuleToDecorate:write(State0, Message#protocol_message_begin{name=ServiceName ++ ?MULTIPLEXED_SERVICE_SEPARATOR ++ Name}), {State#multiplexed_protocol{protocol_data_to_decorate = State1}, ok}; write(State = #multiplexed_protocol{protocol_module_to_decorate = ProtocolModuleToDecorate, protocol_data_to_decorate = State0}, Message) -> {State1, ok} = ProtocolModuleToDecorate:write(State0, Message), {State#multiplexed_protocol{protocol_data_to_decorate = State1}, ok}. read(State = #multiplexed_protocol{protocol_module_to_decorate = ProtocolModuleToDecorate, protocol_data_to_decorate = State0}, Message) -> {State1, Result} = ProtocolModuleToDecorate:read(State0, Message), {State#multiplexed_protocol{protocol_data_to_decorate = State1}, Result}. thrift-0.19.0/lib/erl/src/thrift_server.erl0000644000000000000000000001720414303740367020623 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_server). -behaviour(gen_server). %% API -export([start_link/3, stop/1, take_socket/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(SERVER, ?MODULE). -record(state, {listen_socket, acceptor_ref, service, handler}). %%==================================================================== %% API %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link() -> {ok,Pid} | ignore | {error,Error} %% Description: Starts the server %%-------------------------------------------------------------------- start_link(Port, Service, HandlerModule) when is_integer(Port), is_atom(HandlerModule) -> gen_server:start_link({local, ?SERVER}, ?MODULE, {Port, Service, HandlerModule}, []). %%-------------------------------------------------------------------- %% Function: stop(Pid) -> ok, {error, Reason} %% Description: Stops the server. %%-------------------------------------------------------------------- stop(Pid) when is_pid(Pid) -> gen_server:call(Pid, stop). take_socket(Server, Socket) -> gen_server:call(Server, {take_socket, Socket}). %%==================================================================== %% gen_server callbacks %%==================================================================== %%-------------------------------------------------------------------- %% Function: init(Args) -> {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %% Description: Initiates the server %%-------------------------------------------------------------------- init({Port, Service, Handler}) -> {ok, Socket} = gen_tcp:listen(Port, [binary, {packet, 0}, {active, false}, {nodelay, true}, {reuseaddr, true}]), {ok, Ref} = prim_inet:async_accept(Socket, -1), {ok, #state{listen_socket = Socket, acceptor_ref = Ref, service = Service, handler = Handler}}. %%-------------------------------------------------------------------- %% Function: %% handle_call(Request, From, State) -> {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | %% {stop, Reason, State} %% Description: Handling call messages %%-------------------------------------------------------------------- handle_call(stop, _From, State) -> {stop, stopped, ok, State}; handle_call({take_socket, Socket}, {FromPid, _Tag}, State) -> Result = gen_tcp:controlling_process(Socket, FromPid), {reply, Result, State}. %%-------------------------------------------------------------------- %% Function: handle_cast(Msg, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling cast messages %%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info(Info, State) -> {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} %% Description: Handling all non call/cast messages %%-------------------------------------------------------------------- handle_info({inet_async, ListenSocket, Ref, {ok, ClientSocket}}, State = #state{listen_socket = ListenSocket, acceptor_ref = Ref, service = Service, handler = Handler}) -> case set_sockopt(ListenSocket, ClientSocket) of ok -> %% New client connected - start processor start_processor(ClientSocket, Service, Handler), {ok, NewRef} = prim_inet:async_accept(ListenSocket, -1), {noreply, State#state{acceptor_ref = NewRef}}; {error, Reason} -> error_logger:error_msg("Couldn't set socket opts: ~p~n", [Reason]), {stop, Reason, State} end; handle_info({inet_async, _ListenSocket, _Ref, Error}, State) -> error_logger:error_msg("Error in acceptor: ~p~n", [Error]), {stop, Error, State}; handle_info(_Info, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: terminate(Reason, State) -> void() %% Description: This function is called by a gen_server when it is about to %% terminate. It should be the opposite of Module:init/1 and do any necessary %% cleaning up. When it returns, the gen_server terminates with Reason. %% The return value is ignored. %%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. %%-------------------------------------------------------------------- %% Func: code_change(OldVsn, State, Extra) -> {ok, NewState} %% Description: Convert process state when code is changed %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- set_sockopt(ListenSocket, ClientSocket) -> true = inet_db:register_socket(ClientSocket, inet_tcp), case prim_inet:getopts(ListenSocket, [active, nodelay, keepalive, delay_send, priority, tos]) of {ok, Opts} -> case prim_inet:setopts(ClientSocket, Opts) of ok -> ok; Error -> gen_tcp:close(ClientSocket), Error end; Error -> gen_tcp:close(ClientSocket), Error end. start_processor(Socket, Service, Handler) -> Server = self(), ProtoGen = fun() -> % Become the controlling process ok = take_socket(Server, Socket), {ok, SocketTransport} = thrift_socket_transport:new(Socket), {ok, BufferedTransport} = thrift_buffered_transport:new(SocketTransport), {ok, Protocol} = thrift_binary_protocol:new(BufferedTransport), {ok, Protocol} end, spawn(thrift_processor, init, [{Server, ProtoGen, Service, Handler}]). thrift-0.19.0/lib/erl/src/thrift_buffered_transport.erl0000644000000000000000000000554614303740367023221 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_buffered_transport). -behaviour(thrift_transport). %% constructor -export([new/1]). %% protocol callbacks -export([read/2, read_exact/2, write/2, flush/1, close/1]). %% legacy api -export([new_transport_factory/1]). -record(t_buffered, { wrapped, write_buffer }). -type state() :: #t_buffered{}. -spec new(Transport::thrift_transport:t_transport()) -> thrift_transport:t_transport(). new(Wrapped) -> State = #t_buffered{ wrapped = Wrapped, write_buffer = [] }, thrift_transport:new(?MODULE, State). -include("thrift_transport_behaviour.hrl"). %% reads data through from the wrapped transport read(State = #t_buffered{wrapped = Wrapped}, Len) when is_integer(Len), Len >= 0 -> {NewState, Response} = thrift_transport:read(Wrapped, Len), {State#t_buffered{wrapped = NewState}, Response}. %% reads data through from the wrapped transport read_exact(State = #t_buffered{wrapped = Wrapped}, Len) when is_integer(Len), Len >= 0 -> {NewState, Response} = thrift_transport:read_exact(Wrapped, Len), {State#t_buffered{wrapped = NewState}, Response}. write(State = #t_buffered{write_buffer = Buffer}, Data) -> {State#t_buffered{write_buffer = [Buffer, Data]}, ok}. flush(State = #t_buffered{wrapped = Wrapped, write_buffer = Buffer}) -> case iolist_size(Buffer) of %% if write buffer is empty, do nothing 0 -> {State, ok}; _ -> {Written, Response} = thrift_transport:write(Wrapped, Buffer), {Flushed, ok} = thrift_transport:flush(Written), {State#t_buffered{wrapped = Flushed, write_buffer = []}, Response} end. close(State = #t_buffered{wrapped = Wrapped}) -> {Closed, Result} = thrift_transport:close(Wrapped), {State#t_buffered{wrapped = Closed}, Result}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% new_transport_factory(WrapFactory) -> F = fun() -> {ok, Wrapped} = WrapFactory(), new(Wrapped) end, {ok, F}. thrift-0.19.0/lib/erl/src/thrift_protocol.erl0000644000000000000000000003702414303740367021160 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_protocol). -export([new/2, write/2, read/2, read/3, skip/2, flush_transport/1, close_transport/1, typeid_to_atom/1 ]). -export([behaviour_info/1]). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -record(protocol, {module, data}). behaviour_info(callbacks) -> [ {read, 2}, {write, 2}, {flush_transport, 1}, {close_transport, 1} ]; behaviour_info(_Else) -> undefined. new(Module, Data) when is_atom(Module) -> {ok, #protocol{module = Module, data = Data}}. -spec flush_transport(#protocol{}) -> {#protocol{}, ok}. flush_transport(Proto = #protocol{module = Module, data = Data}) -> {NewData, Result} = Module:flush_transport(Data), {Proto#protocol{data = NewData}, Result}. -spec close_transport(#protocol{}) -> ok. close_transport(#protocol{module = Module, data = Data}) -> Module:close_transport(Data). typeid_to_atom(?tType_STOP) -> field_stop; typeid_to_atom(?tType_VOID) -> void; typeid_to_atom(?tType_BOOL) -> bool; typeid_to_atom(?tType_DOUBLE) -> double; typeid_to_atom(?tType_I8) -> byte; typeid_to_atom(?tType_I16) -> i16; typeid_to_atom(?tType_I32) -> i32; typeid_to_atom(?tType_I64) -> i64; typeid_to_atom(?tType_STRING) -> string; typeid_to_atom(?tType_STRUCT) -> struct; typeid_to_atom(?tType_MAP) -> map; typeid_to_atom(?tType_SET) -> set; typeid_to_atom(?tType_LIST) -> list. term_to_typeid(void) -> ?tType_VOID; term_to_typeid(bool) -> ?tType_BOOL; term_to_typeid(byte) -> ?tType_I8; term_to_typeid(double) -> ?tType_DOUBLE; term_to_typeid(i8) -> ?tType_I8; term_to_typeid(i16) -> ?tType_I16; term_to_typeid(i32) -> ?tType_I32; term_to_typeid(i64) -> ?tType_I64; term_to_typeid(string) -> ?tType_STRING; term_to_typeid({struct, _}) -> ?tType_STRUCT; term_to_typeid({map, _, _}) -> ?tType_MAP; term_to_typeid({set, _}) -> ?tType_SET; term_to_typeid({list, _}) -> ?tType_LIST. %% Structure is like: %% [{Fid, Type}, ...] -spec read(#protocol{}, {struct, _StructDef}, atom()) -> {#protocol{}, {ok, tuple()}}. read(IProto0, {struct, Structure}, Tag) when is_list(Structure), is_atom(Tag) -> % If we want a tagged tuple, we need to offset all the tuple indices % by 1 to avoid overwriting the tag. Offset = if Tag =/= undefined -> 1; true -> 0 end, IndexList = case length(Structure) of N when N > 0 -> lists:seq(1 + Offset, N + Offset); _ -> [] end, SWithIndices = [{Fid, {Type, Index}} || {{Fid, Type}, Index} <- lists:zip(Structure, IndexList)], % Fid -> {Type, Index} SDict = dict:from_list(SWithIndices), {IProto1, ok} = read(IProto0, struct_begin), RTuple0 = erlang:make_tuple(length(Structure) + Offset, undefined), RTuple1 = if Tag =/= undefined -> setelement(1, RTuple0, Tag); true -> RTuple0 end, {IProto2, RTuple2} = read_struct_loop(IProto1, SDict, RTuple1), {IProto2, {ok, RTuple2}}. %% NOTE: Keep this in sync with thrift_protocol_behaviour:read -spec read (#protocol{}, {struct, _Info}) -> {#protocol{}, {ok, tuple()} | {error, _Reason}}; (#protocol{}, tprot_cont_tag()) -> {#protocol{}, {ok, any()} | {error, _Reason}}; (#protocol{}, tprot_empty_tag()) -> {#protocol{}, ok | {error, _Reason}}; (#protocol{}, tprot_header_tag()) -> {#protocol{}, tprot_header_val() | {error, _Reason}}; (#protocol{}, tprot_data_tag()) -> {#protocol{}, {ok, any()} | {error, _Reason}}. read(IProto, {struct, {Module, StructureName}}) when is_atom(Module), is_atom(StructureName) -> read(IProto, Module:struct_info(StructureName), StructureName); read(IProto, S={struct, Structure}) when is_list(Structure) -> read(IProto, S, undefined); read(IProto0, {list, Type}) -> {IProto1, #protocol_list_begin{etype = EType, size = Size}} = read(IProto0, list_begin), {EType, EType} = {term_to_typeid(Type), EType}, {List, IProto2} = lists:mapfoldl(fun(_, ProtoS0) -> {ProtoS1, {ok, Item}} = read(ProtoS0, Type), {Item, ProtoS1} end, IProto1, lists:duplicate(Size, 0)), {IProto3, ok} = read(IProto2, list_end), {IProto3, {ok, List}}; read(IProto0, {map, KeyType, ValType}) -> {IProto1, #protocol_map_begin{size = Size, ktype = KType, vtype = VType}} = read(IProto0, map_begin), _ = case Size of 0 -> 0; _ -> {KType, KType} = {term_to_typeid(KeyType), KType}, {VType, VType} = {term_to_typeid(ValType), VType} end, {List, IProto2} = lists:mapfoldl(fun(_, ProtoS0) -> {ProtoS1, {ok, Key}} = read(ProtoS0, KeyType), {ProtoS2, {ok, Val}} = read(ProtoS1, ValType), {{Key, Val}, ProtoS2} end, IProto1, lists:duplicate(Size, 0)), {IProto3, ok} = read(IProto2, map_end), {IProto3, {ok, dict:from_list(List)}}; read(IProto0, {set, Type}) -> {IProto1, #protocol_set_begin{etype = EType, size = Size}} = read(IProto0, set_begin), {EType, EType} = {term_to_typeid(Type), EType}, {List, IProto2} = lists:mapfoldl(fun(_, ProtoS0) -> {ProtoS1, {ok, Item}} = read(ProtoS0, Type), {Item, ProtoS1} end, IProto1, lists:duplicate(Size, 0)), {IProto3, ok} = read(IProto2, set_end), {IProto3, {ok, sets:from_list(List)}}; read(Protocol, ProtocolType) -> read_specific(Protocol, ProtocolType). %% NOTE: Keep this in sync with thrift_protocol_behaviour:read -spec read_specific (#protocol{}, tprot_empty_tag()) -> {#protocol{}, ok | {error, _Reason}}; (#protocol{}, tprot_header_tag()) -> {#protocol{}, tprot_header_val() | {error, _Reason}}; (#protocol{}, tprot_data_tag()) -> {#protocol{}, {ok, any()} | {error, _Reason}}. read_specific(Proto = #protocol{module = Module, data = ModuleData}, ProtocolType) -> {NewData, Result} = Module:read(ModuleData, ProtocolType), {Proto#protocol{data = NewData}, Result}. read_struct_loop(IProto0, SDict, RTuple) -> {IProto1, #protocol_field_begin{type = FType, id = Fid}} = thrift_protocol:read(IProto0, field_begin), case {FType, Fid} of {?tType_STOP, _} -> {IProto2, ok} = read(IProto1, struct_end), {IProto2, RTuple}; _Else -> case dict:find(Fid, SDict) of {ok, {Type, Index}} -> case term_to_typeid(Type) of FType -> {IProto2, {ok, Val}} = read(IProto1, Type), {IProto3, ok} = thrift_protocol:read(IProto2, field_end), NewRTuple = setelement(Index, RTuple, Val), read_struct_loop(IProto3, SDict, NewRTuple); Expected -> error_logger:info_msg( "Skipping field ~p with wrong type (~p != ~p)~n", [Fid, FType, Expected]), skip_field(FType, IProto1, SDict, RTuple) end; _Else2 -> skip_field(FType, IProto1, SDict, RTuple) end end. skip_field(FType, IProto0, SDict, RTuple) -> {IProto1, ok} = skip(IProto0, typeid_to_atom(FType)), {IProto2, ok} = read(IProto1, field_end), read_struct_loop(IProto2, SDict, RTuple). -spec skip(#protocol{}, atom()) -> {#protocol{}, ok}. skip(Proto0, struct) -> {Proto1, ok} = read(Proto0, struct_begin), {Proto2, ok} = skip_struct_loop(Proto1), {Proto3, ok} = read(Proto2, struct_end), {Proto3, ok}; skip(Proto0, map) -> {Proto1, Map} = read(Proto0, map_begin), {Proto2, ok} = skip_map_loop(Proto1, Map), {Proto3, ok} = read(Proto2, map_end), {Proto3, ok}; skip(Proto0, set) -> {Proto1, Set} = read(Proto0, set_begin), {Proto2, ok} = skip_set_loop(Proto1, Set), {Proto3, ok} = read(Proto2, set_end), {Proto3, ok}; skip(Proto0, list) -> {Proto1, List} = read(Proto0, list_begin), {Proto2, ok} = skip_list_loop(Proto1, List), {Proto3, ok} = read(Proto2, list_end), {Proto3, ok}; skip(Proto0, Type) when is_atom(Type) -> {Proto1, _Ignore} = read(Proto0, Type), {Proto1, ok}. skip_struct_loop(Proto0) -> {Proto1, #protocol_field_begin{type = Type}} = read(Proto0, field_begin), case Type of ?tType_STOP -> {Proto1, ok}; _Else -> {Proto2, ok} = skip(Proto1, typeid_to_atom(Type)), {Proto3, ok} = read(Proto2, field_end), skip_struct_loop(Proto3) end. skip_map_loop(Proto0, Map = #protocol_map_begin{ktype = Ktype, vtype = Vtype, size = Size}) -> case Size of N when N > 0 -> {Proto1, ok} = skip(Proto0, typeid_to_atom(Ktype)), {Proto2, ok} = skip(Proto1, typeid_to_atom(Vtype)), skip_map_loop(Proto2, Map#protocol_map_begin{size = Size - 1}); 0 -> {Proto0, ok} end. skip_set_loop(Proto0, Map = #protocol_set_begin{etype = Etype, size = Size}) -> case Size of N when N > 0 -> {Proto1, ok} = skip(Proto0, typeid_to_atom(Etype)), skip_set_loop(Proto1, Map#protocol_set_begin{size = Size - 1}); 0 -> {Proto0, ok} end. skip_list_loop(Proto0, Map = #protocol_list_begin{etype = Etype, size = Size}) -> case Size of N when N > 0 -> {Proto1, ok} = skip(Proto0, typeid_to_atom(Etype)), skip_list_loop(Proto1, Map#protocol_list_begin{size = Size - 1}); 0 -> {Proto0, ok} end. %%-------------------------------------------------------------------- %% Function: write(OProto, {Type, Data}) -> ok %% %% Type = {struct, StructDef} | %% {list, Type} | %% {map, KeyType, ValType} | %% {set, Type} | %% BaseType %% %% Data = %% tuple() -- for struct %% | list() -- for list %% | dictionary() -- for map %% | set() -- for set %% | any() -- for base types %% %% Description: %%-------------------------------------------------------------------- -spec write(#protocol{}, any()) -> {#protocol{}, ok | {error, _Reason}}. write(Proto0, {{struct, StructDef}, Data}) when is_list(StructDef), is_tuple(Data), length(StructDef) == size(Data) - 1 -> [StructName | Elems] = tuple_to_list(Data), {Proto1, ok} = write(Proto0, #protocol_struct_begin{name = StructName}), {Proto2, ok} = struct_write_loop(Proto1, StructDef, Elems), {Proto3, ok} = write(Proto2, struct_end), {Proto3, ok}; write(Proto, {{struct, {Module, StructureName}}, Data}) when is_atom(Module), is_atom(StructureName), element(1, Data) =:= StructureName -> write(Proto, {Module:struct_info(StructureName), Data}); write(_, {{struct, {Module, StructureName}}, Data}) when is_atom(Module), is_atom(StructureName) -> erlang:error(struct_unmatched, {{provided, element(1, Data)}, {expected, StructureName}}); write(Proto0, {{list, Type}, Data}) when is_list(Data) -> {Proto1, ok} = write(Proto0, #protocol_list_begin{ etype = term_to_typeid(Type), size = length(Data) }), Proto2 = lists:foldl(fun(Elem, ProtoIn) -> {ProtoOut, ok} = write(ProtoIn, {Type, Elem}), ProtoOut end, Proto1, Data), {Proto3, ok} = write(Proto2, list_end), {Proto3, ok}; write(Proto0, {{map, KeyType, ValType}, Data}) -> {Proto1, ok} = write(Proto0, #protocol_map_begin{ ktype = term_to_typeid(KeyType), vtype = term_to_typeid(ValType), size = dict:size(Data) }), Proto2 = dict:fold(fun(KeyData, ValData, ProtoS0) -> {ProtoS1, ok} = write(ProtoS0, {KeyType, KeyData}), {ProtoS2, ok} = write(ProtoS1, {ValType, ValData}), ProtoS2 end, Proto1, Data), {Proto3, ok} = write(Proto2, map_end), {Proto3, ok}; write(Proto0, {{set, Type}, Data}) -> true = sets:is_set(Data), {Proto1, ok} = write(Proto0, #protocol_set_begin{ etype = term_to_typeid(Type), size = sets:size(Data) }), Proto2 = sets:fold(fun(Elem, ProtoIn) -> {ProtoOut, ok} = write(ProtoIn, {Type, Elem}), ProtoOut end, Proto1, Data), {Proto3, ok} = write(Proto2, set_end), {Proto3, ok}; write(Proto = #protocol{module = Module, data = ModuleData}, Data) -> {NewData, Result} = Module:write(ModuleData, Data), {Proto#protocol{data = NewData}, Result}. struct_write_loop(Proto0, [{Fid, Type} | RestStructDef], [Data | RestData]) -> NewProto = case Data of undefined -> Proto0; % null fields are skipped in response _ -> {Proto1, ok} = write(Proto0, #protocol_field_begin{ type = term_to_typeid(Type), id = Fid }), {Proto2, ok} = write(Proto1, {Type, Data}), {Proto3, ok} = write(Proto2, field_end), Proto3 end, struct_write_loop(NewProto, RestStructDef, RestData); struct_write_loop(Proto, [], []) -> write(Proto, field_stop). thrift-0.19.0/lib/erl/src/thrift_transport_state_test.erl0000644000000000000000000000762414303740367023615 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_transport_state_test). -behaviour(gen_server). -behaviour(thrift_transport). %% API -export([new/1]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). %% thrift_transport callbacks -export([write/2, read/2, flush/1, close/1]). -record(trans, {wrapped, % #thrift_transport{} version :: integer(), counter :: pid() }). -type state() :: #trans{}. -include("thrift_transport_behaviour.hrl"). -record(state, {cversion :: integer()}). new(WrappedTransport) -> case gen_server:start_link(?MODULE, [], []) of {ok, Pid} -> Trans = #trans{wrapped = WrappedTransport, version = 0, counter = Pid}, thrift_transport:new(?MODULE, Trans); Else -> Else end. %%==================================================================== %% thrift_transport callbacks %%==================================================================== write(Transport0 = #trans{wrapped = Wrapped0}, Data) -> Transport1 = check_version(Transport0), {Wrapped1, Result} = thrift_transport:write(Wrapped0, Data), Transport2 = Transport1#trans{wrapped = Wrapped1}, {Transport2, Result}. flush(Transport0 = #trans{wrapped = Wrapped0}) -> Transport1 = check_version(Transport0), {Wrapped1, Result} = thrift_transport:flush(Wrapped0), Transport2 = Transport1#trans{wrapped = Wrapped1}, {Transport2, Result}. close(Transport0 = #trans{wrapped = Wrapped0}) -> Transport1 = check_version(Transport0), shutdown_counter(Transport1), {Wrapped1, Result} = thrift_transport:close(Wrapped0), Transport2 = Transport1#trans{wrapped = Wrapped1}, {Transport2, Result}. read(Transport0 = #trans{wrapped = Wrapped0}, Len) -> Transport1 = check_version(Transport0), {Wrapped1, Result} = thrift_transport:read(Wrapped0, Len), Transport2 = Transport1#trans{wrapped = Wrapped1}, {Transport2, Result}. %%==================================================================== %% gen_server callbacks %%==================================================================== init([]) -> {ok, #state{cversion = 0}}. handle_call(check_version, _From, State = #state{cversion = Version}) -> {reply, Version, State#state{cversion = Version+1}}. handle_cast(shutdown, State) -> {stop, normal, State}. handle_info(_Info, State) -> {noreply, State}. code_change(_OldVsn, State, _Extra) -> {ok, State}. terminate(_Reason, _State) -> ok. %%-------------------------------------------------------------------- %% Internal functions %%-------------------------------------------------------------------- check_version(Transport = #trans{version = Version, counter = Counter}) -> case gen_server:call(Counter, check_version) of Version -> Transport#trans{version = Version+1}; _Else -> % State wasn't propagated properly. Die. erlang:error(state_not_propagated) end. shutdown_counter(#trans{counter = Counter}) -> gen_server:cast(Counter, shutdown). thrift-0.19.0/lib/erl/src/thrift_client_util.erl0000644000000000000000000001157214303740367021632 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_client_util). -export([new/4]). -export([new_multiplexed/3, new_multiplexed/4]). -type service_name() :: nonempty_string(). -type service_module() :: atom(). -type multiplexed_service_map() :: [{ServiceName::service_name(), ServiceModule::service_module()}]. %% %% Splits client options into client, protocol, and transport options %% %% split_options([Options...]) -> {ProtocolOptions, TransportOptions} %% split_options(Options) -> split_options(Options, [], []). split_options([], ProtoIn, TransIn) -> {ProtoIn, TransIn}; split_options([Opt = {OptKey, _} | Rest], ProtoIn, TransIn) when OptKey =:= strict_read; OptKey =:= strict_write; OptKey =:= protocol -> split_options(Rest, [Opt | ProtoIn], TransIn); split_options([Opt = {OptKey, _} | Rest], ProtoIn, TransIn) when OptKey =:= framed; OptKey =:= connect_timeout; OptKey =:= recv_timeout; OptKey =:= sockopts; OptKey =:= ssltransport; OptKey =:= ssloptions-> split_options(Rest, ProtoIn, [Opt | TransIn]). %% Client constructor for the common-case of socket transports new(Host, Port, Service, Options) when is_integer(Port), is_atom(Service), is_list(Options) -> {ProtoOpts, TransOpts0} = split_options(Options), {TransportModule, TransOpts2} = case lists:keytake(ssltransport, 1, TransOpts0) of {value, {_, true}, TransOpts1} -> {thrift_sslsocket_transport, TransOpts1}; false -> {thrift_socket_transport, TransOpts0} end, {ProtocolModule, ProtoOpts1} = case lists:keytake(protocol, 1, ProtoOpts) of {value, {_, compact}, Opts} -> {thrift_compact_protocol, Opts}; {value, {_, json}, Opts} -> {thrift_json_protocol, Opts}; {value, {_, binary}, Opts} -> {thrift_binary_protocol, Opts}; false -> {thrift_binary_protocol, ProtoOpts} end, {ok, TransportFactory} = TransportModule:new_transport_factory(Host, Port, TransOpts2), {ok, ProtocolFactory} = ProtocolModule:new_protocol_factory( TransportFactory, ProtoOpts1), case ProtocolFactory() of {ok, Protocol} -> thrift_client:new(Protocol, Service); {error, Error} -> {error, Error} end. -spec new_multiplexed(Host, Port, Services, Options) -> {ok, ServiceThriftClientList} when Host :: nonempty_string(), Port :: non_neg_integer(), Services :: multiplexed_service_map(), Options :: list(), ServiceThriftClientList :: [{ServiceName::list(), ThriftClient::term()}]. new_multiplexed(Host, Port, Services, Options) when is_integer(Port), is_list(Services), is_list(Options) -> new_multiplexed(thrift_socket_transport:new_transport_factory(Host, Port, Options), Services, Options). -spec new_multiplexed(TransportFactoryTuple, Services, Options) -> {ok, ServiceThriftClientList} when TransportFactoryTuple :: {ok, TransportFactory::term()}, Services :: multiplexed_service_map(), Options :: list(), ServiceThriftClientList :: [{ServiceName::service_name(), ThriftClient::term()}]. new_multiplexed(TransportFactoryTuple, Services, Options) when is_list(Services), is_list(Options), is_tuple(TransportFactoryTuple) -> {ProtoOpts, _} = split_options(Options), {ok, TransportFactory} = TransportFactoryTuple, {ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(TransportFactory, ProtoOpts), {ok, Protocol} = ProtocolFactory(), {ok, [{ServiceName, element(2, thrift_client:new(element(2, thrift_multiplexed_protocol:new(Protocol, ServiceName)), Service))} || {ServiceName, Service} <- Services]}. thrift-0.19.0/lib/erl/src/thrift_service.erl0000644000000000000000000000162314303740367020753 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_service). -export([behaviour_info/1]). behaviour_info(callbacks) -> [{function_info, 2}]. thrift-0.19.0/lib/erl/src/thrift_socket_server.erl0000644000000000000000000003256714303740367022204 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_socket_server). -behaviour(gen_server). -include ("thrift_constants.hrl"). -ifdef(TEST). -compile(export_all). -export_records([thrift_socket_server]). -else. -export([start/1, stop/1]). -export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3, handle_info/2]). -export([acceptor_loop/1]). -endif. -record(thrift_socket_server, {port, service, handler, name, max=2048, ip=any, listen=null, acceptor=null, socket_opts=[{recv_timeout, 500}], protocol=binary, framed=false, ssltransport=false, ssloptions=[] }). start(State=#thrift_socket_server{}) -> start_server(State); start(Options) -> start(parse_options(Options)). stop(Name) when is_atom(Name) -> gen_server:cast(Name, stop); stop(Pid) when is_pid(Pid) -> gen_server:cast(Pid, stop); stop({local, Name}) -> stop(Name); stop({global, Name}) -> stop(Name); stop(Options) -> State = parse_options(Options), stop(State#thrift_socket_server.name). %% Internal API parse_options(Options) -> parse_options(Options, #thrift_socket_server{}). parse_options([], State) -> State; parse_options([{name, L} | Rest], State) when is_list(L) -> Name = {local, list_to_atom(L)}, parse_options(Rest, State#thrift_socket_server{name=Name}); parse_options([{name, A} | Rest], State) when is_atom(A) -> Name = {local, A}, parse_options(Rest, State#thrift_socket_server{name=Name}); parse_options([{name, Name} | Rest], State) -> parse_options(Rest, State#thrift_socket_server{name=Name}); parse_options([{port, L} | Rest], State) when is_list(L) -> Port = list_to_integer(L), parse_options(Rest, State#thrift_socket_server{port=Port}); parse_options([{port, Port} | Rest], State) -> parse_options(Rest, State#thrift_socket_server{port=Port}); parse_options([{ip, Ip} | Rest], State) -> ParsedIp = case Ip of any -> any; Ip when is_tuple(Ip) -> Ip; Ip when is_list(Ip) -> {ok, IpTuple} = inet_parse:address(Ip), IpTuple end, parse_options(Rest, State#thrift_socket_server{ip=ParsedIp}); parse_options([{socket_opts, L} | Rest], State) when is_list(L), length(L) > 0 -> parse_options(Rest, State#thrift_socket_server{socket_opts=L}); parse_options([{handler, []} | _Rest], _State) -> throw("At least an error handler must be defined."); parse_options([{handler, ServiceHandlerPropertyList} | Rest], State) when is_list(ServiceHandlerPropertyList) -> ServiceHandlerMap = case State#thrift_socket_server.handler of undefined -> lists:foldl( fun ({ServiceName, ServiceHandler}, Acc) when is_list(ServiceName), is_atom(ServiceHandler) -> thrift_multiplexed_map_wrapper:store(ServiceName, ServiceHandler, Acc); (_, _Acc) -> throw("The handler option is not properly configured for multiplexed services. It should be a kind of [{\"error_handler\", Module::atom()}, {SericeName::list(), Module::atom()}, ...]") end, thrift_multiplexed_map_wrapper:new(), ServiceHandlerPropertyList); _ -> throw("Error while parsing the handler option.") end, case thrift_multiplexed_map_wrapper:find(?MULTIPLEXED_ERROR_HANDLER_KEY, ServiceHandlerMap) of {ok, _ErrorHandler} -> parse_options(Rest, State#thrift_socket_server{handler=ServiceHandlerMap}); error -> throw("The handler option is not properly configured for multiplexed services. It should be a kind of [{\"error_handler\", Module::atom()}, {SericeName::list(), Module::atom()}, ...]") end; parse_options([{handler, Handler} | Rest], State) when State#thrift_socket_server.handler == undefined, is_atom(Handler) -> parse_options(Rest, State#thrift_socket_server{handler=Handler}); parse_options([{service, []} | _Rest], _State) -> throw("At least one service module must be defined."); parse_options([{service, ServiceModulePropertyList} | Rest], State) when is_list(ServiceModulePropertyList) -> ServiceModuleMap = case State#thrift_socket_server.service of undefined -> lists:foldl( fun ({ServiceName, ServiceModule}, Acc) when is_list(ServiceName), is_atom(ServiceModule) -> thrift_multiplexed_map_wrapper:store(ServiceName, ServiceModule, Acc); (_, _Acc) -> throw("The service option is not properly configured for multiplexed services. It should be a kind of [{SericeName::list(), ServiceModule::atom()}, ...]") end, thrift_multiplexed_map_wrapper:new(), ServiceModulePropertyList); _ -> throw("Error while parsing the service option.") end, parse_options(Rest, State#thrift_socket_server{service=ServiceModuleMap}); parse_options([{service, Service} | Rest], State) when State#thrift_socket_server.service == undefined, is_atom(Service) -> parse_options(Rest, State#thrift_socket_server{service=Service}); parse_options([{max, Max} | Rest], State) -> MaxInt = case Max of Max when is_list(Max) -> list_to_integer(Max); Max when is_integer(Max) -> Max end, parse_options(Rest, State#thrift_socket_server{max=MaxInt}); parse_options([{protocol, Proto} | Rest], State) when is_atom(Proto) -> parse_options(Rest, State#thrift_socket_server{protocol=Proto}); parse_options([{framed, Framed} | Rest], State) when is_boolean(Framed) -> parse_options(Rest, State#thrift_socket_server{framed=Framed}); parse_options([{ssltransport, SSLTransport} | Rest], State) when is_boolean(SSLTransport) -> parse_options(Rest, State#thrift_socket_server{ssltransport=SSLTransport}); parse_options([{ssloptions, SSLOptions} | Rest], State) when is_list(SSLOptions) -> parse_options(Rest, State#thrift_socket_server{ssloptions=SSLOptions}). start_server(State=#thrift_socket_server{name=Name}) -> case Name of undefined -> gen_server:start_link(?MODULE, State, []); _ -> gen_server:start_link(Name, ?MODULE, State, []) end. init(State=#thrift_socket_server{ip=Ip, port=Port}) -> process_flag(trap_exit, true), BaseOpts = [binary, {reuseaddr, true}, {packet, 0}, {backlog, 4096}, {recbuf, 8192}, {active, false}], Opts = case Ip of any -> BaseOpts; Ip -> [{ip, Ip} | BaseOpts] end, case gen_tcp_listen(Port, Opts, State) of {stop, eacces} -> %% fdsrv module allows another shot to bind %% ports which require root access case Port < 1024 of true -> case fdsrv:start() of {ok, _} -> case fdsrv:bind_socket(tcp, Port) of {ok, Fd} -> gen_tcp_listen(Port, [{fd, Fd} | Opts], State); _ -> {stop, fdsrv_bind_failed} end; _ -> {stop, fdsrv_start_failed} end; false -> {stop, eacces} end; Other -> error_logger:info_msg("thrift service listening on port ~p", [Port]), Other end. gen_tcp_listen(Port, Opts, State) -> case gen_tcp:listen(Port, Opts) of {ok, Listen} -> {ok, ListenPort} = inet:port(Listen), {ok, new_acceptor(State#thrift_socket_server{listen=Listen, port=ListenPort})}; {error, Reason} -> {stop, Reason} end. new_acceptor(State=#thrift_socket_server{max=0}) -> error_logger:error_msg("Not accepting new connections"), State#thrift_socket_server{acceptor=null}; new_acceptor(State=#thrift_socket_server{listen=Listen, service=Service, handler=Handler, socket_opts=Opts, framed=Framed, protocol=Proto, ssltransport=SslTransport, ssloptions=SslOptions }) -> Pid = proc_lib:spawn_link(?MODULE, acceptor_loop, [{self(), Listen, Service, Handler, Opts, Framed, SslTransport, SslOptions, Proto}]), State#thrift_socket_server{acceptor=Pid}. acceptor_loop({Server, Listen, Service, Handler, SocketOpts, Framed, SslTransport, SslOptions, Proto}) when is_pid(Server), is_list(SocketOpts) -> case catch gen_tcp:accept(Listen) of % infinite timeout {ok, Socket} -> gen_server:cast(Server, {accepted, self()}), ProtoGen = fun() -> {ok, SocketTransport} = case SslTransport of true -> thrift_sslsocket_transport:new(Socket, SocketOpts, SslOptions); false -> thrift_socket_transport:new(Socket, SocketOpts) end, {ok, Transport} = case Framed of true -> thrift_framed_transport:new(SocketTransport); false -> thrift_buffered_transport:new(SocketTransport) end, {ok, Protocol} = case Proto of compact -> thrift_compact_protocol:new(Transport); json -> thrift_json_protocol:new(Transport); _ -> thrift_binary_protocol:new(Transport) end, {ok, Protocol} end, thrift_processor:init({Server, ProtoGen, Service, Handler}); {error, closed} -> exit({error, closed}); Other -> error_logger:error_report( [{application, thrift}, "Accept failed error", lists:flatten(io_lib:format("~p", [Other]))]), exit({error, accept_failed}) end. handle_call({get, port}, _From, State=#thrift_socket_server{port=Port}) -> {reply, Port, State}; handle_call(_Message, _From, State) -> Res = error, {reply, Res, State}. handle_cast({accepted, Pid}, State=#thrift_socket_server{acceptor=Pid, max=Max}) -> % io:format("accepted ~p~n", [Pid]), State1 = State#thrift_socket_server{max=Max - 1}, {noreply, new_acceptor(State1)}; handle_cast(stop, State) -> {stop, normal, State}. terminate(Reason, #thrift_socket_server{listen=Listen, port=Port}) -> gen_tcp:close(Listen), case Reason of normal -> ok; shutdown -> ok; _ -> {backtrace, Bt} = erlang:process_info(self(), backtrace), error_logger:error_report({?MODULE, ?LINE, {child_error, Reason, Bt}}) end, case Port < 1024 of true -> catch fdsrv:stop(), ok; false -> ok end. code_change(_OldVsn, State, _Extra) -> State. handle_info({'EXIT', Pid, normal}, State=#thrift_socket_server{acceptor=Pid}) -> {noreply, new_acceptor(State)}; handle_info({'EXIT', Pid, Reason}, State=#thrift_socket_server{acceptor=Pid}) -> error_logger:error_report({?MODULE, ?LINE, {acceptor_error, Reason}}), timer:sleep(100), {noreply, new_acceptor(State)}; handle_info({'EXIT', _LoopPid, Reason}, State=#thrift_socket_server{acceptor=Pid, max=Max}) -> case Reason of normal -> ok; shutdown -> ok; _ -> error_logger:error_report({?MODULE, ?LINE, {child_error, Reason, erlang:get_stacktrace()}}) end, State1 = State#thrift_socket_server{max=Max + 1}, State2 = case Pid of null -> new_acceptor(State1); _ -> State1 end, {noreply, State2}; handle_info(Info, State) -> error_logger:info_report([{'INFO', Info}, {'State', State}]), {noreply, State}. thrift-0.19.0/lib/erl/src/thrift_processor.erl0000644000000000000000000002236314303740367021336 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_processor). -export([init/1]). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -record(thrift_processor, {handler, protocol, service}). init({_Server, ProtoGen, Service, Handler}) when is_function(ProtoGen, 0) -> {ok, Proto} = ProtoGen(), loop(#thrift_processor{protocol = Proto, service = Service, handler = Handler}). loop(State0 = #thrift_processor{protocol = Proto0, handler = Handler, service = Service}) -> {Proto1, MessageBegin} = thrift_protocol:read(Proto0, message_begin), State1 = State0#thrift_processor{protocol = Proto1}, ErrorHandler = fun (HandlerModules) when is_list(HandlerModules) -> thrift_multiplexed_map_wrapper:fetch(?MULTIPLEXED_ERROR_HANDLER_KEY, HandlerModules); (HandlerModule) -> HandlerModule end, case MessageBegin of #protocol_message_begin{name = Function, type = Type, seqid = Seqid} when Type =:= ?tMessageType_CALL; Type =:= ?tMessageType_ONEWAY -> case string:tokens(Function, ?MULTIPLEXED_SERVICE_SEPARATOR) of [ServiceName, FunctionName] -> ServiceModule = thrift_multiplexed_map_wrapper:fetch(ServiceName, Service), ServiceHandler = thrift_multiplexed_map_wrapper:fetch(ServiceName, Handler), case handle_function(State1#thrift_processor{service=ServiceModule, handler=ServiceHandler}, list_to_atom(FunctionName), Seqid) of {State2, ok} -> loop(State2#thrift_processor{service=Service, handler=Handler}); {_State2, {error, Reason}} -> apply(ErrorHandler(Handler), handle_error, [list_to_atom(Function), Reason]), thrift_protocol:close_transport(Proto1), ok end; _ -> case handle_function(State1, list_to_atom(Function), Seqid) of {State2, ok} -> loop(State2); {_State2, {error, Reason}} -> apply(ErrorHandler(Handler), handle_error, [list_to_atom(Function), Reason]), thrift_protocol:close_transport(Proto1), ok end end; {error, timeout = Reason} -> apply(ErrorHandler(Handler), handle_error, [undefined, Reason]), thrift_protocol:close_transport(Proto1), ok; {error, closed = Reason} -> %% error_logger:info_msg("Client disconnected~n"), apply(ErrorHandler(Handler), handle_error, [undefined, Reason]), thrift_protocol:close_transport(Proto1), exit(shutdown); {error, Reason} -> apply(ErrorHandler(Handler), handle_error, [undefined, Reason]), thrift_protocol:close_transport(Proto1), exit(shutdown) end. handle_function(State0=#thrift_processor{protocol = Proto0, handler = Handler, service = Service}, Function, Seqid) -> InParams = Service:function_info(Function, params_type), {Proto1, {ok, Params}} = thrift_protocol:read(Proto0, InParams), State1 = State0#thrift_processor{protocol = Proto1}, try Result = Handler:handle_function(Function, Params), %% {Micro, Result} = better_timer(Handler, handle_function, [Function, Params]), %% error_logger:info_msg("Processed ~p(~p) in ~.4fms~n", %% [Function, Params, Micro/1000.0]), handle_success(State1, Function, Result, Seqid) catch Type:Data when Type =:= throw orelse Type =:= error -> handle_function_catch(State1, Function, Type, Data, Seqid) end. handle_function_catch(State = #thrift_processor{service = Service}, Function, ErrType, ErrData, Seqid) -> IsOneway = Service:function_info(Function, reply_type) =:= oneway_void, case {ErrType, ErrData} of _ when IsOneway -> Stack = erlang:get_stacktrace(), error_logger:warning_msg( "oneway void ~p threw error which must be ignored: ~p", [Function, {ErrType, ErrData, Stack}]), {State, ok}; {throw, Exception} when is_tuple(Exception), size(Exception) > 0 -> %error_logger:warning_msg("~p threw exception: ~p~n", [Function, Exception]), handle_exception(State, Function, Exception, Seqid); % we still want to accept more requests from this client {error, Error} -> handle_error(State, Function, Error, Seqid) end. handle_success(State = #thrift_processor{service = Service}, Function, Result, Seqid) -> ReplyType = Service:function_info(Function, reply_type), StructName = atom_to_list(Function) ++ "_result", case Result of {reply, ReplyData} -> Reply = {{struct, [{0, ReplyType}]}, {StructName, ReplyData}}, send_reply(State, Function, ?tMessageType_REPLY, Reply, Seqid); ok when ReplyType == {struct, []} -> send_reply(State, Function, ?tMessageType_REPLY, {ReplyType, {StructName}}, Seqid); ok when ReplyType == oneway_void -> %% no reply for oneway void {State, ok} end. handle_exception(State = #thrift_processor{service = Service}, Function, Exception, Seqid) -> ExceptionType = element(1, Exception), %% Fetch a structure like {struct, [{-2, {struct, {Module, Type}}}, %% {-3, {struct, {Module, Type}}}]} ReplySpec = Service:function_info(Function, exceptions), {struct, XInfo} = ReplySpec, true = is_list(XInfo), %% Assuming we had a type1 exception, we'd get: [undefined, Exception, undefined] %% e.g.: [{-1, type0}, {-2, type1}, {-3, type2}] ExceptionList = [case Type of ExceptionType -> Exception; _ -> undefined end || {_Fid, {struct, {_Module, Type}}} <- XInfo], ExceptionTuple = list_to_tuple([Function | ExceptionList]), % Make sure we got at least one defined case lists:all(fun(X) -> X =:= undefined end, ExceptionList) of true -> handle_unknown_exception(State, Function, Exception, Seqid); false -> send_reply(State, Function, ?tMessageType_REPLY, {ReplySpec, ExceptionTuple}, Seqid) end. %% %% Called when an exception has been explicitly thrown by the service, but it was %% not one of the exceptions that was defined for the function. %% handle_unknown_exception(State, Function, Exception, Seqid) -> handle_error(State, Function, {exception_not_declared_as_thrown, Exception}, Seqid). handle_error(State, Function, Error, Seqid) -> Stack = erlang:get_stacktrace(), error_logger:error_msg("~p had an error: ~p~n", [Function, {Error, Stack}]), Message = case application:get_env(thrift, exceptions_include_traces) of {ok, true} -> lists:flatten(io_lib:format("An error occurred: ~p~n", [{Error, Stack}])); _ -> "An unknown handler error occurred." end, Reply = {?TApplicationException_Structure, #'TApplicationException'{ message = Message, type = ?TApplicationException_UNKNOWN}}, send_reply(State, Function, ?tMessageType_EXCEPTION, Reply, Seqid). send_reply(State = #thrift_processor{protocol = Proto0}, Function, ReplyMessageType, Reply, Seqid) -> try {Proto1, ok} = thrift_protocol:write(Proto0, #protocol_message_begin{ name = atom_to_list(Function), type = ReplyMessageType, seqid = Seqid}), {Proto2, ok} = thrift_protocol:write(Proto1, Reply), {Proto3, ok} = thrift_protocol:write(Proto2, message_end), {Proto4, ok} = thrift_protocol:flush_transport(Proto3), {State#thrift_processor{protocol = Proto4}, ok} catch error:{badmatch, {_, {error, _} = Error}} -> {State, Error} end. thrift-0.19.0/lib/erl/src/thrift_multiplexed_map_wrapper.erl0000644000000000000000000000367114303740367024251 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_multiplexed_map_wrapper). -export([ new/0 ,store/3 ,find/2 ,fetch/2 ]). -type service_handler() :: nonempty_string(). -type module_() :: atom(). -type service_handler_map() :: [{ServiceHandler::service_handler(), Module::module_()}]. -spec new() -> service_handler_map(). new() -> orddict:new(). -spec store(ServiceHandler, Module, Map) -> NewMap when ServiceHandler :: service_handler(), Module :: module_(), Map :: service_handler_map(), NewMap :: service_handler_map(). store(ServiceHandler, Module, Map) -> orddict:store(ServiceHandler, Module, Map). -spec find(ServiceHandler, Map) -> {ok, Module} | error when ServiceHandler :: service_handler(), Module :: module_(), Map :: service_handler_map(). find(ServiceHandler, Map) -> orddict:find(ServiceHandler, Map). -spec fetch(ServiceHandler, Map) -> Module when ServiceHandler :: service_handler(), Module :: module_(), Map :: service_handler_map(). fetch(ServiceHandler, Map) -> orddict:fetch(ServiceHandler, Map). thrift-0.19.0/lib/erl/src/thrift_client.erl0000644000000000000000000001445014303740367020573 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_client). %% API -export([new/2, call/3, send_call/3, close/1]). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -record(tclient, {service, protocol, seqid}). new(Protocol, Service) when is_atom(Service) -> {ok, #tclient{protocol = Protocol, service = Service, seqid = 0}}. -spec call(#tclient{}, atom(), list()) -> {#tclient{}, {ok, any()} | {error, any()}}. call(Client = #tclient{}, Function, Args) when is_atom(Function), is_list(Args) -> case send_function_call(Client, Function, Args) of {ok, Client1} -> receive_function_result(Client1, Function); {{error, X}, Client1} -> {Client1, {error, X}}; Else -> Else end. %% Sends a function call but does not read the result. This is useful %% if you're trying to log non-oneway function calls to write-only %% transports like thrift_disk_log_transport. -spec send_call(#tclient{}, atom(), list()) -> {#tclient{}, ok}. send_call(Client = #tclient{}, Function, Args) when is_atom(Function), is_list(Args) -> case send_function_call(Client, Function, Args) of {ok, Client1} -> {Client1, ok}; Else -> Else end. -spec close(#tclient{}) -> ok. close(#tclient{protocol=Protocol}) -> thrift_protocol:close_transport(Protocol). %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- -spec send_function_call(#tclient{}, atom(), list()) -> {ok | {error, any()}, #tclient{}}. send_function_call(Client = #tclient{service = Service}, Function, Args) -> {Params, Reply} = try {Service:function_info(Function, params_type), Service:function_info(Function, reply_type)} catch error:function_clause -> {no_function, 0} end, MsgType = case Reply of oneway_void -> ?tMessageType_ONEWAY; _ -> ?tMessageType_CALL end, case Params of no_function -> {{error, {no_function, Function}}, Client}; {struct, PList} when length(PList) =/= length(Args) -> {{error, {bad_args, Function, Args}}, Client}; {struct, _PList} -> write_message(Client, Function, Args, Params, MsgType) end. -spec write_message(#tclient{}, atom(), list(), {struct, list()}, integer()) -> {ok | {error, any()}, #tclient{}}. write_message(Client = #tclient{protocol = P0, seqid = Seq}, Function, Args, Params, MsgType) -> try {P1, ok} = thrift_protocol:write(P0, #protocol_message_begin{ name = atom_to_list(Function), type = MsgType, seqid = Seq }), {P2, ok} = thrift_protocol:write(P1, {Params, list_to_tuple([Function|Args])}), {P3, ok} = thrift_protocol:write(P2, message_end), {P4, ok} = thrift_protocol:flush_transport(P3), {ok, Client#tclient{protocol = P4}} catch error:{badmatch, {_, {error, _} = Error}} -> {Error, Client} end. -spec receive_function_result(#tclient{}, atom()) -> {#tclient{}, {ok, any()} | {error, any()}}. receive_function_result(Client = #tclient{service = Service}, Function) -> ResultType = Service:function_info(Function, reply_type), read_result(Client, Function, ResultType). read_result(Client, _Function, oneway_void) -> {Client, {ok, ok}}; read_result(Client = #tclient{protocol = Proto0, seqid = SeqId}, Function, ReplyType) -> case thrift_protocol:read(Proto0, message_begin) of {Proto1, {error, Reason}} -> NewClient = Client#tclient{protocol = Proto1}, {NewClient, {error, Reason}}; {Proto1, MessageBegin} -> NewClient = Client#tclient{protocol = Proto1}, case MessageBegin of #protocol_message_begin{seqid = RetSeqId} when RetSeqId =/= SeqId -> {NewClient, {error, {bad_seq_id, SeqId}}}; #protocol_message_begin{type = ?tMessageType_EXCEPTION} -> handle_application_exception(NewClient); #protocol_message_begin{type = ?tMessageType_REPLY} -> handle_reply(NewClient, Function, ReplyType) end end. handle_reply(Client = #tclient{protocol = Proto0, service = Service}, Function, ReplyType) -> {struct, ExceptionFields} = Service:function_info(Function, exceptions), ReplyStructDef = {struct, [{0, ReplyType}] ++ ExceptionFields}, {Proto1, {ok, Reply}} = thrift_protocol:read(Proto0, ReplyStructDef), {Proto2, ok} = thrift_protocol:read(Proto1, message_end), NewClient = Client#tclient{protocol = Proto2}, ReplyList = tuple_to_list(Reply), true = length(ReplyList) == length(ExceptionFields) + 1, ExceptionVals = tl(ReplyList), Thrown = [X || X <- ExceptionVals, X =/= undefined], case Thrown of [] when ReplyType == {struct, []} -> {NewClient, {ok, ok}}; [] -> {NewClient, {ok, hd(ReplyList)}}; [Exception] -> throw({NewClient, {exception, Exception}}) end. handle_application_exception(Client = #tclient{protocol = Proto0}) -> {Proto1, {ok, Exception}} = thrift_protocol:read(Proto0, ?TApplicationException_Structure), {Proto2, ok} = thrift_protocol:read(Proto1, message_end), XRecord = list_to_tuple( ['TApplicationException' | tuple_to_list(Exception)]), error_logger:error_msg("X: ~p~n", [XRecord]), true = is_record(XRecord, 'TApplicationException'), NewClient = Client#tclient{protocol = Proto2}, throw({NewClient, {exception, XRecord}}). thrift-0.19.0/lib/erl/src/thrift_http_transport.erl0000644000000000000000000001052414303740367022406 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_http_transport). -behaviour(thrift_transport). %% API -export([new/2, new/3]). %% thrift_transport callbacks -export([write/2, read/2, flush/1, close/1]). -record(http_transport, {host, % string() path, % string() read_buffer, % iolist() write_buffer, % iolist() http_options, % see http(3) extra_headers % [{str(), str()}, ...] }). -type state() :: #http_transport{}. -include("thrift_transport_behaviour.hrl"). new(Host, Path) -> new(Host, Path, _Options = []). %%-------------------------------------------------------------------- %% Options include: %% {http_options, HttpOptions} = See http(3) %% {extra_headers, ExtraHeaders} = List of extra HTTP headers %%-------------------------------------------------------------------- new(Host, Path, Options) -> State1 = #http_transport{host = Host, path = Path, read_buffer = [], write_buffer = [], http_options = [], extra_headers = []}, ApplyOption = fun ({http_options, HttpOpts}, State = #http_transport{}) -> State#http_transport{http_options = HttpOpts}; ({extra_headers, ExtraHeaders}, State = #http_transport{}) -> State#http_transport{extra_headers = ExtraHeaders}; (Other, #http_transport{}) -> {invalid_option, Other}; (_, Error) -> Error end, case lists:foldl(ApplyOption, State1, Options) of State2 = #http_transport{} -> thrift_transport:new(?MODULE, State2); Else -> {error, Else} end. %% Writes data into the buffer write(State = #http_transport{write_buffer = WBuf}, Data) -> {State#http_transport{write_buffer = [WBuf, Data]}, ok}. %% Flushes the buffer, making a request flush(State = #http_transport{host = Host, path = Path, read_buffer = Rbuf, write_buffer = Wbuf, http_options = HttpOptions, extra_headers = ExtraHeaders}) -> case iolist_to_binary(Wbuf) of <<>> -> %% Don't bother flushing empty buffers. {State, ok}; WBinary -> {ok, {{_Version, 200, _ReasonPhrase}, _Headers, Body}} = httpc:request(post, {"http://" ++ Host ++ Path, [{"User-Agent", "Erlang/thrift_http_transport"} | ExtraHeaders], "application/x-thrift", WBinary}, HttpOptions, [{body_format, binary}]), State1 = State#http_transport{read_buffer = [Rbuf, Body], write_buffer = []}, {State1, ok} end. close(State) -> {State, ok}. read(State = #http_transport{read_buffer = RBuf}, Len) when is_integer(Len) -> %% Pull off Give bytes, return them to the user, leave the rest in the buffer. Give = min(iolist_size(RBuf), Len), case iolist_to_binary(RBuf) of <> -> Response = {ok, Data}, State1 = State#http_transport{read_buffer=RBuf1}, {State1, Response}; _ -> {State, {error, 'EOF'}} end. thrift-0.19.0/lib/erl/src/thrift_membuffer_transport.erl0000644000000000000000000000433614303740367023403 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_membuffer_transport). -behaviour(thrift_transport). %% constructors -export([new/0, new/1]). %% protocol callbacks -export([read/2, read_exact/2, write/2, flush/1, close/1]). -record(t_membuffer, { buffer = [] }). -type state() :: #t_membuffer{}. -spec new() -> thrift_transport:t_transport(). new() -> new([]). -spec new(Buf::iodata()) -> thrift_transport:t_transport(). new(Buf) when is_list(Buf) -> State = #t_membuffer{buffer = Buf}, thrift_transport:new(?MODULE, State); new(Buf) when is_binary(Buf) -> State = #t_membuffer{buffer = [Buf]}, thrift_transport:new(?MODULE, State). -include("thrift_transport_behaviour.hrl"). read(State = #t_membuffer{buffer = Buf}, Len) when is_integer(Len), Len >= 0 -> Binary = iolist_to_binary(Buf), Give = min(iolist_size(Binary), Len), {Result, Remaining} = split_binary(Binary, Give), {State#t_membuffer{buffer = Remaining}, {ok, Result}}. read_exact(State = #t_membuffer{buffer = Buf}, Len) when is_integer(Len), Len >= 0 -> Binary = iolist_to_binary(Buf), case iolist_size(Binary) of X when X >= Len -> {Result, Remaining} = split_binary(Binary, Len), {State#t_membuffer{buffer = Remaining}, {ok, Result}}; _ -> {State, {error, eof}} end. write(State = #t_membuffer{buffer = Buf}, Data) when is_list(Data); is_binary(Data) -> {State#t_membuffer{buffer = [Buf, Data]}, ok}. flush(State) -> {State, ok}. close(State) -> {State, ok}. thrift-0.19.0/lib/erl/src/thrift_json_protocol.erl0000644000000000000000000004254514303740367022215 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% %% The JSON protocol implementation was created by %% Peter Neumark based on %% the binary protocol implementation. -module(thrift_json_protocol). -behaviour(thrift_protocol). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). -export([new/1, new/2, read/2, write/2, flush_transport/1, close_transport/1, new_protocol_factory/2 ]). -record(json_context, { % the type of json_context: array or object type, % fields read or written fields_processed = 0 }). -record(json_protocol, { transport, context_stack = [], jsx }). -type state() :: #json_protocol{}. -include("thrift_protocol_behaviour.hrl"). -define(VERSION_1, 1). -define(JSON_DOUBLE_PRECISION, 16). typeid_to_json(?tType_BOOL) -> "tf"; typeid_to_json(?tType_BYTE) -> "i8"; typeid_to_json(?tType_DOUBLE) -> "dbl"; typeid_to_json(?tType_I8) -> "i8"; typeid_to_json(?tType_I16) -> "i16"; typeid_to_json(?tType_I32) -> "i32"; typeid_to_json(?tType_I64) -> "i64"; typeid_to_json(?tType_STRING) -> "str"; typeid_to_json(?tType_STRUCT) -> "rec"; typeid_to_json(?tType_MAP) -> "map"; typeid_to_json(?tType_SET) -> "set"; typeid_to_json(?tType_LIST) -> "lst". json_to_typeid("tf") -> ?tType_BOOL; json_to_typeid("dbl") -> ?tType_DOUBLE; json_to_typeid("i8") -> ?tType_I8; json_to_typeid("i16") -> ?tType_I16; json_to_typeid("i32") -> ?tType_I32; json_to_typeid("i64") -> ?tType_I64; json_to_typeid("str") -> ?tType_STRING; json_to_typeid("rec") -> ?tType_STRUCT; json_to_typeid("map") -> ?tType_MAP; json_to_typeid("set") -> ?tType_SET; json_to_typeid("lst") -> ?tType_LIST. start_context(object) -> "{"; start_context(array) -> "[". end_context(object) -> "}"; end_context(array) -> "]". new(Transport) -> new(Transport, _Options = []). new(Transport, _Options) -> State = #json_protocol{transport = Transport}, thrift_protocol:new(?MODULE, State). flush_transport(This = #json_protocol{transport = Transport}) -> {NewTransport, Result} = thrift_transport:flush(Transport), {This#json_protocol{ transport = NewTransport, context_stack = [] }, Result}. close_transport(This = #json_protocol{transport = Transport}) -> {NewTransport, Result} = thrift_transport:close(Transport), {This#json_protocol{ transport = NewTransport, context_stack = [], jsx = undefined }, Result}. %%% %%% instance methods %%% % places a new context on the stack: write(#json_protocol{context_stack = Stack} = State0, {enter_context, Type}) -> {State1, ok} = write_values(State0, [{context_pre_item, false}]), State2 = State1#json_protocol{context_stack = [ #json_context{type=Type}|Stack]}, write_values(State2, [list_to_binary(start_context(Type))]); % removes the topmost context from stack write(#json_protocol{context_stack = [CurrCtxt|Stack]} = State0, {exit_context}) -> Type = CurrCtxt#json_context.type, State1 = State0#json_protocol{context_stack = Stack}, write_values(State1, [ list_to_binary(end_context(Type)), {context_post_item, false} ]); % writes necessary prelude to field or container depending on current context write(#json_protocol{context_stack = []} = This0, {context_pre_item, _}) -> {This0, ok}; write(#json_protocol{context_stack = [Context|_CtxtTail]} = This0, {context_pre_item, MayNeedQuotes}) -> FieldNo = Context#json_context.fields_processed, CtxtType = Context#json_context.type, Rem = FieldNo rem 2, case {CtxtType, FieldNo, Rem, MayNeedQuotes} of {array, N, _, _} when N > 0 -> % array element (not first) write(This0, <<",">>); {object, 0, _, true} -> % non-string object key (first) write(This0, <<"\"">>); {object, N, 0, true} when N > 0 -> % non-string object key (not first) write(This0, <<",\"">>); {object, N, 0, false} when N > 0-> % string object key (not first) write(This0, <<",">>); _ -> % no pre-field necessary {This0, ok} end; % writes necessary postlude to field or container depending on current context write(#json_protocol{context_stack = []} = This0, {context_post_item, _}) -> {This0, ok}; write(#json_protocol{context_stack = [Context|CtxtTail]} = This0, {context_post_item, MayNeedQuotes}) -> FieldNo = Context#json_context.fields_processed, CtxtType = Context#json_context.type, Rem = FieldNo rem 2, {This1, ok} = case {CtxtType, Rem, MayNeedQuotes} of {object, 0, true} -> % non-string object key write(This0, <<"\":">>); {object, 0, false} -> % string object key write(This0, <<":">>); _ -> % no pre-field necessary {This0, ok} end, NewContext = Context#json_context{fields_processed = FieldNo + 1}, {This1#json_protocol{context_stack=[NewContext|CtxtTail]}, ok}; write(This0, #protocol_message_begin{ name = Name, type = Type, seqid = Seqid}) -> write_values(This0, [ {enter_context, array}, {i32, ?VERSION_1}, {string, Name}, {i32, Type}, {i32, Seqid} ]); write(This, message_end) -> write_values(This, [{exit_context}]); % Example field expression: "1":{"dbl":3.14} write(This0, #protocol_field_begin{ name = _Name, type = Type, id = Id}) -> write_values(This0, [ % entering 'outer' object {i16, Id}, % entering 'outer' object {enter_context, object}, {string, typeid_to_json(Type)} ]); write(This, field_stop) -> {This, ok}; write(This, field_end) -> write_values(This,[{exit_context}]); % Example message with map: [1,"testMap",1,0,{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}] write(This0, #protocol_map_begin{ ktype = Ktype, vtype = Vtype, size = Size}) -> write_values(This0, [ {enter_context, array}, {string, typeid_to_json(Ktype)}, {string, typeid_to_json(Vtype)}, {i32, Size}, {enter_context, object} ]); write(This, map_end) -> write_values(This,[ {exit_context}, {exit_context} ]); write(This0, #protocol_list_begin{ etype = Etype, size = Size}) -> write_values(This0, [ {enter_context, array}, {string, typeid_to_json(Etype)}, {i32, Size} ]); write(This, list_end) -> write_values(This,[ {exit_context} ]); % example message with set: [1,"testSet",1,0,{"1":{"set":["i32",3,1,2,3]}}] write(This0, #protocol_set_begin{ etype = Etype, size = Size}) -> write_values(This0, [ {enter_context, array}, {string, typeid_to_json(Etype)}, {i32, Size} ]); write(This, set_end) -> write_values(This,[ {exit_context} ]); % example message with struct: [1,"testStruct",1,0,{"1":{"rec":{"1":{"str":"worked"},"4":{"i8":1},"9":{"i32":1073741824},"11":{"i64":1152921504606847000}}}}] write(This, #protocol_struct_begin{}) -> write_values(This, [ {enter_context, object} ]); write(This, struct_end) -> write_values(This,[ {exit_context} ]); write(This, {bool, true}) -> write_values(This, [ {context_pre_item, true}, <<"true">>, {context_post_item, true} ]); write(This, {bool, false}) -> write_values(This, [ {context_pre_item, true}, <<"false">>, {context_post_item, true} ]); write(This, {byte, Byte}) -> write_values(This, [ {context_pre_item, true}, list_to_binary(integer_to_list(Byte)), {context_post_item, true} ]); write(This, {i16, I16}) -> write(This, {byte, I16}); write(This, {i32, I32}) -> write(This, {byte, I32}); write(This, {i64, I64}) -> write(This, {byte, I64}); write(This, {double, Double}) -> write_values(This, [ {context_pre_item, true}, list_to_binary(io_lib:format("~.*f", [?JSON_DOUBLE_PRECISION,Double])), {context_post_item, true} ]); write(This0, {string, Str}) -> write_values(This0, [ {context_pre_item, false}, case is_binary(Str) of true -> Str; false -> <<"\"", (list_to_binary(Str))/binary, "\"">> end, {context_post_item, false} ]); %% TODO: binary fields should be base64 encoded? %% Data :: iolist() write(This = #json_protocol{transport = Trans}, Data) -> %io:format("Data ~p Ctxt ~p~n~n", [Data, This#json_protocol.context_stack]), {NewTransport, Result} = thrift_transport:write(Trans, Data), {This#json_protocol{transport = NewTransport}, Result}. write_values(This0, ValueList) -> FinalState = lists:foldl( fun(Val, ThisIn) -> {ThisOut, ok} = write(ThisIn, Val), ThisOut end, This0, ValueList), {FinalState, ok}. %% I wish the erlang version of the transport interface included a %% read_all function (like eg. the java implementation). Since it doesn't, %% here's my version (even though it probably shouldn't be in this file). %% %% The resulting binary is immediately send to the JSX stream parser. %% Subsequent calls to read actually operate on the events returned by JSX. read_all(#json_protocol{transport = Transport0} = State) -> {Transport1, Bin} = read_all_1(Transport0, []), P = thrift_json_parser:parser(), [First|Rest] = P(Bin), State#json_protocol{ transport = Transport1, jsx = {event, First, Rest} }. read_all_1(Transport0, IoList) -> {Transport1, Result} = thrift_transport:read(Transport0, 1), case Result of {ok, <<>>} -> % nothing read: assume we're done {Transport1, iolist_to_binary(lists:reverse(IoList))}; {ok, Data} -> % character successfully read; read more read_all_1(Transport1, [Data|IoList]); {error, 'EOF'} -> % we're done {Transport1, iolist_to_binary(lists:reverse(IoList))} end. % Expect reads an event from the JSX event stream. It receives an event or data % type as input. Comparing the read event from the one is was passed, it % returns an error if something other than the expected value is encountered. % Expect also maintains the context stack in #json_protocol. expect(#json_protocol{jsx={event, {Type, Data}=Ev, [Next|Rest]}}=State, ExpectedType) -> NextState = State#json_protocol{jsx={event, Next, Rest}}, case Type == ExpectedType of true -> {NextState, {ok, convert_data(Type, Data)}}; false -> {NextState, {error, {unexpected_json_event, Ev}}} end; expect(#json_protocol{jsx={event, Event, Next}}=State, ExpectedEvent) -> expect(State#json_protocol{jsx={event, {Event, none}, Next}}, ExpectedEvent). convert_data(integer, I) -> list_to_integer(I); convert_data(float, F) -> list_to_float(F); convert_data(_, D) -> D. expect_many(State, ExpectedList) -> expect_many_1(State, ExpectedList, [], ok). expect_many_1(State, [], ResultList, Status) -> {State, {Status, lists:reverse(ResultList)}}; expect_many_1(State, [Expected|ExpTail], ResultList, _PrevStatus) -> {State1, {Status, Data}} = expect(State, Expected), NewResultList = [Data|ResultList], case Status of % in case of error, end prematurely error -> expect_many_1(State1, [], NewResultList, Status); ok -> expect_many_1(State1, ExpTail, NewResultList, Status) end. % wrapper around expect to make life easier for container opening/closing functions expect_nodata(This, ExpectedList) -> case expect_many(This, ExpectedList) of {State, {ok, _}} -> {State, ok}; Error -> Error end. read_field(#json_protocol{jsx={event, Field, [Next|Rest]}} = State) -> NewState = State#json_protocol{jsx={event, Next, Rest}}, {NewState, Field}. read(This0, message_begin) -> % call read_all to get the contents of the transport buffer into JSX. This1 = read_all(This0), case expect_many(This1, [start_array, integer, string, integer, integer]) of {This2, {ok, [_, Version, Name, Type, SeqId]}} -> case Version =:= ?VERSION_1 of true -> {This2, #protocol_message_begin{name = Name, type = Type, seqid = SeqId}}; false -> {This2, {error, no_json_protocol_version}} end; Other -> Other end; read(This, message_end) -> expect_nodata(This, [end_array]); read(This, struct_begin) -> expect_nodata(This, [start_object]); read(This, struct_end) -> expect_nodata(This, [end_object]); read(This0, field_begin) -> {This1, Read} = expect_many(This0, [%field id key, % {} surrounding field start_object, % type of field key]), case Read of {ok, [FieldIdStr, _, FieldType]} -> {This1, #protocol_field_begin{ type = json_to_typeid(FieldType), id = list_to_integer(FieldIdStr)}}; % TODO: do we need to wrap this in a try/catch? {error,[{unexpected_json_event, {end_object,none}}]} -> {This1, #protocol_field_begin{type = ?tType_STOP}}; Other -> io:format("**** OTHER branch selected ****"), {This1, Other} end; read(This, field_end) -> expect_nodata(This, [end_object]); % Example message with map: [1,"testMap",1,0,{"1":{"map":["i32","i32",3,{"7":77,"8":88,"9":99}]}}] read(This0, map_begin) -> case expect_many(This0, [start_array, % key type string, % value type string, % size integer, % the following object contains the map start_object]) of {This1, {ok, [_, Ktype, Vtype, Size, _]}} -> {This1, #protocol_map_begin{ktype = Ktype, vtype = Vtype, size = Size}}; Other -> Other end; read(This, map_end) -> expect_nodata(This, [end_object, end_array]); read(This0, list_begin) -> case expect_many(This0, [start_array, % element type string, % size integer]) of {This1, {ok, [_, Etype, Size]}} -> {This1, #protocol_list_begin{ etype = Etype, size = Size}}; Other -> Other end; read(This, list_end) -> expect_nodata(This, [end_array]); % example message with set: [1,"testSet",1,0,{"1":{"set":["i32",3,1,2,3]}}] read(This0, set_begin) -> case expect_many(This0, [start_array, % element type string, % size integer]) of {This1, {ok, [_, Etype, Size]}} -> {This1, #protocol_set_begin{ etype = Etype, size = Size}}; Other -> Other end; read(This, set_end) -> expect_nodata(This, [end_array]); read(This0, field_stop) -> {This0, ok}; %% read(This0, bool) -> {This1, Field} = read_field(This0), Value = case Field of {literal, I} -> {ok, I}; _Other -> {error, unexpected_event_for_boolean} end, {This1, Value}; read(This0, byte) -> {This1, Field} = read_field(This0), Value = case Field of {key, K} -> {ok, list_to_integer(K)}; {integer, I} -> {ok, list_to_integer(I)}; _Other -> {error, unexpected_event_for_integer} end, {This1, Value}; read(This0, i16) -> read(This0, byte); read(This0, i32) -> read(This0, byte); read(This0, i64) -> read(This0, byte); read(This0, double) -> {This1, Field} = read_field(This0), Value = case Field of {float, I} -> {ok, list_to_float(I)}; _Other -> {error, unexpected_event_for_double} end, {This1, Value}; % returns a binary directly, call binary_to_list if necessary read(This0, string) -> {This1, Field} = read_field(This0), Value = case Field of {string, I} -> {ok, I}; {key, J} -> {ok, J}; _Other -> {error, unexpected_event_for_string} end, {This1, Value}. %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% returns a (fun() -> thrift_protocol()) new_protocol_factory(TransportFactory, _Options) -> % Only strice read/write are implemented F = fun() -> {ok, Transport} = TransportFactory(), thrift_json_protocol:new(Transport, []) end, {ok, F}. thrift-0.19.0/lib/erl/src/thrift_sslsocket_transport.erl0000644000000000000000000001351514303740367023444 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_sslsocket_transport). -include("thrift_transport_behaviour.hrl"). -behaviour(thrift_transport). -export([new/3, write/2, read/2, flush/1, close/1, new_transport_factory/3]). %% Export only for the transport factory -export([new/2]). -record(data, {socket, recv_timeout=infinity}). -type state() :: #data{}. %% The following "local" record is filled in by parse_factory_options/2 %% below. These options can be passed to new_protocol_factory/3 in a %% proplists-style option list. They're parsed like this so it is an O(n) %% operation instead of O(n^2) -record(factory_opts, {connect_timeout = infinity, sockopts = [], framed = false, ssloptions = []}). parse_factory_options([], Opts) -> Opts; parse_factory_options([{framed, Bool} | Rest], Opts) when is_boolean(Bool) -> parse_factory_options(Rest, Opts#factory_opts{framed=Bool}); parse_factory_options([{sockopts, OptList} | Rest], Opts) when is_list(OptList) -> parse_factory_options(Rest, Opts#factory_opts{sockopts=OptList}); parse_factory_options([{connect_timeout, TO} | Rest], Opts) when TO =:= infinity; is_integer(TO) -> parse_factory_options(Rest, Opts#factory_opts{connect_timeout=TO}); parse_factory_options([{ssloptions, SslOptions} | Rest], Opts) when is_list(SslOptions) -> parse_factory_options(Rest, Opts#factory_opts{ssloptions=SslOptions}). new(Socket, SockOpts, SslOptions) when is_list(SockOpts), is_list(SslOptions) -> inet:setopts(Socket, [{active, false}]), %% => prevent the ssl handshake messages get lost %% upgrade to an ssl socket case catch ssl:ssl_accept(Socket, SslOptions) of % infinite timeout {ok, SslSocket} -> new(SslSocket, SockOpts); {error, Reason} -> exit({error, Reason}); Other -> error_logger:error_report( [{application, thrift}, "SSL accept failed error", lists:flatten(io_lib:format("~p", [Other]))]), exit({error, ssl_accept_failed}) end. new(SslSocket, SockOpts) -> State = case lists:keysearch(recv_timeout, 1, SockOpts) of {value, {recv_timeout, Timeout}} when is_integer(Timeout), Timeout > 0 -> #data{socket=SslSocket, recv_timeout=Timeout}; _ -> #data{socket=SslSocket} end, thrift_transport:new(?MODULE, State). %% Data :: iolist() write(This = #data{socket = Socket}, Data) -> {This, ssl:send(Socket, Data)}. read(This = #data{socket=Socket, recv_timeout=Timeout}, Len) when is_integer(Len), Len >= 0 -> case ssl:recv(Socket, Len, Timeout) of Err = {error, timeout} -> error_logger:info_msg("read timeout: peer conn ~p", [inet:peername(Socket)]), ssl:close(Socket), {This, Err}; Data -> {This, Data} end. %% We can't really flush - everything is flushed when we write flush(This) -> {This, ok}. close(This = #data{socket = Socket}) -> {This, ssl:close(Socket)}. %%%% FACTORY GENERATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% Generates a "transport factory" function - a fun which returns a thrift_transport() %% instance. %% This can be passed into a protocol factory to generate a connection to a %% thrift server over a socket. %% new_transport_factory(Host, Port, Options) -> ParsedOpts = parse_factory_options(Options, #factory_opts{}), F = fun() -> SockOpts = [binary, {packet, 0}, {active, false}, {nodelay, true} | ParsedOpts#factory_opts.sockopts], case catch gen_tcp:connect(Host, Port, SockOpts, ParsedOpts#factory_opts.connect_timeout) of {ok, Sock} -> SslSock = case catch ssl:connect(Sock, ParsedOpts#factory_opts.ssloptions, ParsedOpts#factory_opts.connect_timeout) of {ok, SslSocket} -> SslSocket; Other -> error_logger:info_msg("error while connecting over ssl - reason: ~p~n", [Other]), catch gen_tcp:close(Sock), exit(error) end, {ok, Transport} = thrift_sslsocket_transport:new(SslSock, SockOpts), {ok, BufTransport} = case ParsedOpts#factory_opts.framed of true -> thrift_framed_transport:new(Transport); false -> thrift_buffered_transport:new(Transport) end, {ok, BufTransport}; Error -> Error end end, {ok, F}.thrift-0.19.0/lib/erl/src/thrift_file_transport.erl0000644000000000000000000000611214303740367022344 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_file_transport). -behaviour(thrift_transport). %% constructors -export([new/1, new/2]). %% protocol callbacks -export([read/2, read_exact/2, write/2, flush/1, close/1]). %% legacy api -export([new_reader/1]). -record(t_file, { device, should_close = true, mode = write }). -type state() :: #t_file{}. -spec new(Device::file:io_device()) -> thrift_transport:t_transport(). new(Device) -> new(Device, []). -spec new(Device::file:io_device(), Opts::list()) -> thrift_transport:t_transport(). %% Device should be opened in raw and binary mode. new(Device, Opts) when is_list(Opts) -> State = parse_opts(Opts, #t_file{device = Device}), thrift_transport:new(?MODULE, State). parse_opts([{should_close, Bool}|Rest], State) when is_boolean(Bool) -> parse_opts(Rest, State#t_file{should_close = Bool}); parse_opts([{mode, Mode}|Rest], State) when Mode =:= write; Mode =:= read -> parse_opts(Rest, State#t_file{mode = Mode}); parse_opts([], State) -> State. -include("thrift_transport_behaviour.hrl"). read(State = #t_file{device = Device, mode = read}, Len) when is_integer(Len), Len >= 0 -> case file:read(Device, Len) of eof -> {State, {error, eof}}; {ok, Result} -> {State, {ok, iolist_to_binary(Result)}} end; read(State, _) -> {State, {error, write_mode}}. read_exact(State = #t_file{device = Device, mode = read}, Len) when is_integer(Len), Len >= 0 -> case file:read(Device, Len) of eof -> {State, {error, eof}}; {ok, Result} -> case iolist_size(Result) of X when X < Len -> {State, {error, eof}}; _ -> {State, {ok, iolist_to_binary(Result)}} end end; read_exact(State, _) -> {State, {error, write_mode}}. write(State = #t_file{device = Device, mode = write}, Data) -> {State, file:write(Device, Data)}; write(State, _) -> {State, {error, read_mode}}. flush(State = #t_file{device = Device, mode = write}) -> {State, file:sync(Device)}. close(State = #t_file{device = Device, should_close = SC}) -> case SC of true -> {State, file:close(Device)}; false -> {State, ok} end. %% legacy api. left for compatibility new_reader(Filename) -> case file:open(Filename, [read, binary, {read_ahead, 1024*1024}]) of {ok, IODevice} -> new(IODevice, [{should_close, true}, {mode, read}]); Error -> Error end. thrift-0.19.0/lib/erl/src/thrift_memory_buffer.erl0000644000000000000000000000273314303740367022157 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_memory_buffer). -behaviour(thrift_transport). %% constructors -export([new/0, new/1]). %% protocol callbacks -export([read/2, write/2, flush/1, close/1]). %% legacy api -export([new_transport_factory/0]). %% wrapper around thrift_membuffer_transport for legacy reasons new() -> thrift_membuffer_transport:new(). new(State) -> thrift_membuffer_transport:new(State). new_transport_factory() -> {ok, fun() -> new() end}. write(State, Data) -> thrift_membuffer_transport:write(State, Data). read(State, Data) -> thrift_membuffer_transport:read(State, Data). flush(State) -> thrift_membuffer_transport:flush(State). close(State) -> thrift_membuffer_transport:close(State). thrift-0.19.0/lib/erl/src/thrift_socket_transport.erl0000644000000000000000000001413614303740367022722 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(thrift_socket_transport). -behaviour(thrift_transport). %% constructors -export([new/1, new/2]). %% transport callbacks -export([read/2, read_exact/2, write/2, flush/1, close/1]). %% legacy api -export([new_transport_factory/3]). -record(t_socket, { socket, recv_timeout=60000, buffer = [] }). -type state() :: #t_socket{}. -spec new(Socket::any()) -> thrift_transport:t_transport(). new(Socket) -> new(Socket, []). -spec new(Socket::any(), Opts::list()) -> thrift_transport:t_transport(). new(Socket, Opts) when is_list(Opts) -> State = parse_opts(Opts, #t_socket{socket = Socket}), thrift_transport:new(?MODULE, State). parse_opts([{recv_timeout, Timeout}|Rest], State) when is_integer(Timeout), Timeout > 0 -> parse_opts(Rest, State#t_socket{recv_timeout = Timeout}); parse_opts([{recv_timeout, infinity}|Rest], State) -> parse_opts(Rest, State#t_socket{recv_timeout = infinity}); parse_opts([], State) -> State. -include("thrift_transport_behaviour.hrl"). read(State = #t_socket{buffer = Buf}, Len) when is_integer(Len), Len >= 0 -> Binary = iolist_to_binary(Buf), case iolist_size(Binary) of X when X >= Len -> {Result, Remaining} = split_binary(Binary, Len), {State#t_socket{buffer = Remaining}, {ok, Result}}; _ -> %%recv(State, Len) loop_recv(State,Len,Len) end. loop_recv(State=#t_socket{buffer = Buf},ReadLen,NextReadLen) when NextReadLen =< 0-> {Result,Remaining}=split_binary(Buf,ReadLen), {State#t_socket{buffer = Remaining},{ok,Result}}; loop_recv(State=#t_socket{socket = Socket,buffer = Buf},ReadLen,NextReadLen) when NextReadLen >0 -> case gen_tcp:recv(Socket,0,State#t_socket.recv_timeout) of {error,Error}-> gen_tcp:close(Socket), {State,{error,Error}}; {ok,Data}-> Binary=iolist_to_binary([Buf,Data]), Give=min(iolist_size(Binary),ReadLen), loop_recv(State#t_socket{buffer = Binary},ReadLen,ReadLen-Give) end. recv(State = #t_socket{socket = Socket, buffer = Buf}, Len) -> case gen_tcp:recv(Socket, 0, State#t_socket.recv_timeout) of {error, Error} -> gen_tcp:close(Socket), {State, {error, Error}}; {ok, Data} -> Binary = iolist_to_binary([Buf, Data]), Give = min(iolist_size(Binary), Len), {Result, Remaining} = split_binary(Binary, Give), {State#t_socket{buffer = Remaining}, {ok, Result}} end. read_exact(State = #t_socket{buffer = Buf}, Len) when is_integer(Len), Len >= 0 -> Binary = iolist_to_binary(Buf), case iolist_size(Binary) of X when X >= Len -> read(State, Len); X -> case gen_tcp:recv(State#t_socket.socket, Len - X, State#t_socket.recv_timeout) of {error, Error} -> gen_tcp:close(State#t_socket.socket), {State, {error, Error}}; {ok, Data} -> {State#t_socket{buffer = []}, {ok, <>}} end end. write(State = #t_socket{socket = Socket}, Data) -> case gen_tcp:send(Socket, Data) of {error, Error} -> gen_tcp:close(Socket), {State, {error, Error}}; ok -> {State, ok} end. flush(State) -> {State#t_socket{buffer = []}, ok}. close(State = #t_socket{socket = Socket}) -> {State, gen_tcp:close(Socket)}. %% legacy api. left for compatibility %% The following "local" record is filled in by parse_factory_options/2 %% below. These options can be passed to new_protocol_factory/3 in a %% proplists-style option list. They're parsed like this so it is an O(n) %% operation instead of O(n^2) -record(factory_opts, { connect_timeout = infinity, sockopts = [], framed = false }). parse_factory_options([], FactoryOpts, TransOpts) -> {FactoryOpts, TransOpts}; parse_factory_options([{framed, Bool}|Rest], FactoryOpts, TransOpts) when is_boolean(Bool) -> parse_factory_options(Rest, FactoryOpts#factory_opts{framed = Bool}, TransOpts); parse_factory_options([{sockopts, OptList}|Rest], FactoryOpts, TransOpts) when is_list(OptList) -> parse_factory_options(Rest, FactoryOpts#factory_opts{sockopts = OptList}, TransOpts); parse_factory_options([{connect_timeout, TO}|Rest], FactoryOpts, TransOpts) when TO =:= infinity; is_integer(TO) -> parse_factory_options(Rest, FactoryOpts#factory_opts{connect_timeout = TO}, TransOpts); parse_factory_options([{recv_timeout, TO}|Rest], FactoryOpts, TransOpts) when TO =:= infinity; is_integer(TO) -> parse_factory_options(Rest, FactoryOpts, [{recv_timeout, TO}] ++ TransOpts). %% Generates a "transport factory" function - a fun which returns a thrift_transport() %% instance. %% State can be passed into a protocol factory to generate a connection to a %% thrift server over a socket. new_transport_factory(Host, Port, Options) -> {FactoryOpts, TransOpts} = parse_factory_options(Options, #factory_opts{}, []), {ok, fun() -> SockOpts = [binary, {packet, 0}, {active, false}, {nodelay, true}|FactoryOpts#factory_opts.sockopts ], case catch gen_tcp:connect( Host, Port, SockOpts, FactoryOpts#factory_opts.connect_timeout ) of {ok, Sock} -> {ok, Transport} = thrift_socket_transport:new(Sock, TransOpts), {ok, BufTransport} = case FactoryOpts#factory_opts.framed of true -> thrift_framed_transport:new(Transport); false -> thrift_buffered_transport:new(Transport) end, {ok, BufTransport}; Error -> Error end end}. thrift-0.19.0/lib/erl/README.md0000644000000000000000000000332714303740367015722 0ustar00rootroot00000000000000# Thrift Erlang Software Library # ## License ## Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ## Release Notes ## ### 0.9.2 ### as of 0.9.2 struct and function naming conventions have changed. to retain the old naming conventions (for backwards compatibility) use the compiler option `legacynames` ## Example ## Example session using thrift_client: ```erl 1> {ok, C0} = thrift_client_util:new("localhost", 9090, thrift_test_thrift, []), ok. ok 2> {C1, R1} = thrift_client:call(C0, testVoid, []), R1. {ok,ok} 3> {C2, R2} = thrift_client:call(C1, testVoid, [asdf]), R2. {error,{bad_args,testVoid,[asdf]}} 4> {C3, R3} = thrift_client:call(C2, testI32, [123]), R3. {ok,123} 5> {C4, R4} = thrift_client:call(C3, testOneway, [1]), R4. {ok,ok} 6> {C5, R5} = thrift_client:call(C4, testXception, ["foo"]), R5. {error,{no_function,testXception}} 7> {C6, R6} = thrift_client:call(C5, testException, ["foo"]), R6. {ok,ok} 8> {C7, R7} = (catch thrift_client:call(C6, testException, ["Xception"])), R7. {exception,{xception,1001,<<"Xception">>}} ``` thrift-0.19.0/lib/erl/coding_standards.md0000644000000000000000000000031514303740367020265 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) Particularly for Erlang please follow the Erlang [Programming Rules and Conventions](http://www.erlang.se/doc/programming_rules.shtml). thrift-0.19.0/lib/erl/test/0000777000000000000000000000000014370300523015407 5ustar00rootroot00000000000000thrift-0.19.0/lib/erl/test/thrift_test_test.erl0000644000000000000000000005611414303740367021526 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% % don't rename this thrift_test, it clobbers generated files -module(thrift_test_test). -compile(export_all). -include_lib("eunit/include/eunit.hrl"). -include("gen-erl/thrift_test_constants.hrl"). constant_test_() -> [ {"myNumberz equals 1", ?_assertEqual(1, ?THRIFT_TEST_MYNUMBERZ)} ]. record_generation_test_() -> [ {"Bonk record", ?_assertMatch( {'thrift.test.Bonk', _, _}, #'thrift.test.Bonk'{message=null,type=null} )}, {"Bools record", ?_assertMatch( {'thrift.test.Bools', _, _}, #'thrift.test.Bools'{im_true=null,im_false=null} )}, {"Xtruct record", ?_assertMatch( {'thrift.test.Xtruct', _, _, _, _}, #'thrift.test.Xtruct'{string_thing=null,byte_thing=null,i32_thing=null,i64_thing=null} )}, {"Xtruct2 record", ?_assertMatch( {'thrift.test.Xtruct2', _, _, _}, #'thrift.test.Xtruct2'{byte_thing=null,struct_thing=null,i32_thing=null} )}, {"Xtruct3 record", ?_assertMatch( {'thrift.test.Xtruct3', _, _, _, _}, #'thrift.test.Xtruct3'{string_thing=null,changed=null,i32_thing=null,i64_thing=null} )}, {"Insanity record", ?_assertMatch( {'thrift.test.Insanity', _, _}, #'thrift.test.Insanity'{userMap=null,xtructs=null} )}, {"CrazyNesting record", ?_assertMatch( {'thrift.test.CrazyNesting', _, _, _, _}, #'thrift.test.CrazyNesting'{ string_field=null, set_field=null, list_field=null, binary_field=null } )}, {"Xception record", ?_assertMatch( {'thrift.test.Xception', _, _}, #'thrift.test.Xception'{errorCode=null,message=null} )}, {"Xception2 record", ?_assertMatch( {'thrift.test.Xception2', _, _}, #'thrift.test.Xception2'{errorCode=null,struct_thing=null} )}, {"EmptyStruct record", ?_assertMatch({'thrift.test.EmptyStruct'}, #'thrift.test.EmptyStruct'{})}, {"OneField record", ?_assertMatch({'thrift.test.OneField', _}, #'thrift.test.OneField'{field=null})}, {"VersioningTestV1 record", ?_assertMatch( {'thrift.test.VersioningTestV1', _, _, _}, #'thrift.test.VersioningTestV1'{begin_in_both=null,old_string=null,end_in_both=null} )}, {"VersioningTestV2 record", ?_assertMatch( {'thrift.test.VersioningTestV2', _, _, _, _, _, _, _, _, _, _, _, _}, #'thrift.test.VersioningTestV2'{ begin_in_both=null, newint=null, newbyte=null, newshort=null, newlong=null, newdouble=null, newstruct=null, newlist=null, newset=null, newmap=null, newstring=null, end_in_both=null } )}, {"ListTypeVersioningV1 record", ?_assertMatch( {'thrift.test.ListTypeVersioningV1', _, _}, #'thrift.test.ListTypeVersioningV1'{myints=null,hello=null} )}, {"ListTypeVersioningV2 record", ?_assertMatch( {'thrift.test.ListTypeVersioningV2', _, _}, #'thrift.test.ListTypeVersioningV2'{strings=null,hello=null} )}, {"GuessProtocolStruct record", ?_assertMatch( {'thrift.test.GuessProtocolStruct', _}, #'thrift.test.GuessProtocolStruct'{map_field=null} )}, {"LargeDeltas record", ?_assertMatch( {'thrift.test.LargeDeltas', _, _, _, _, _, _, _, _, _, _}, #'thrift.test.LargeDeltas'{ b1=null, b10=null, b100=null, check_true=null, b1000=null, check_false=null, vertwo2000=null, a_set2500=null, vertwo3000=null, big_numbers=null } )}, {"NestedListsI32x2 record", ?_assertMatch( {'thrift.test.NestedListsI32x2', _}, #'thrift.test.NestedListsI32x2'{integerlist=null} )}, {"NestedListsI32x3 record", ?_assertMatch( {'thrift.test.NestedListsI32x3', _}, #'thrift.test.NestedListsI32x3'{integerlist=null} )}, {"NestedMixedx2 record", ?_assertMatch( {'thrift.test.NestedMixedx2', _, _, _}, #'thrift.test.NestedMixedx2'{ int_set_list=null, map_int_strset=null, map_int_strset_list=null } )}, {"ListBonks record", ?_assertMatch({'thrift.test.ListBonks', _}, #'thrift.test.ListBonks'{bonk=null})}, {"NestedListsBonk record", ?_assertMatch( {'thrift.test.NestedListsBonk', _}, #'thrift.test.NestedListsBonk'{bonk=null} )}, {"BoolTest record", ?_assertMatch( {'thrift.test.BoolTest', _, _}, #'thrift.test.BoolTest'{b=null,s=null} )}, {"StructA record", ?_assertMatch({'thrift.test.StructA', _}, #'thrift.test.StructA'{s=null})}, {"StructB record", ?_assertMatch( {'thrift.test.StructB', _, _}, #'thrift.test.StructB'{aa=null,ab=null} )} ]. struct_info_test_() -> [ {"Bonk definition (short version)", ?_assertEqual( {struct, [{1, string}, {2, i32}]}, thrift_test_types:struct_info('thrift.test.Bonk') )}, {"Bonk definition", ?_assertEqual( {struct, [ {1, undefined, string, message, undefined}, {2, undefined, i32, type, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.Bonk') )}, {"Bools definition", ?_assertEqual( {struct, [ {1, undefined, bool, im_true, undefined}, {2, undefined, bool, im_false, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.Bools') )}, {"Xtruct definition", ?_assertEqual( {struct, [ {1, undefined, string, string_thing, undefined}, {4, undefined, byte, byte_thing, undefined}, {9, undefined, i32, i32_thing, undefined}, {11, undefined, i64, i64_thing, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.Xtruct') )}, {"Xtruct2 definition", ?_assertEqual( {struct, [ {1, undefined, byte, byte_thing, undefined}, {2, undefined, {struct, {'thrift_test_types', 'thrift.test.Xtruct'}}, struct_thing, #'thrift.test.Xtruct'{}}, {3, undefined, i32, i32_thing, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.Xtruct2') )}, {"Xtruct3 definition", ?_assertEqual( {struct, [ {1, undefined, string, string_thing, undefined}, {4, undefined, i32, changed, undefined}, {9, undefined, i32, i32_thing, undefined}, {11, undefined, i64, i64_thing, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.Xtruct3') )}, {"Insanity definition", ?_assertEqual( {struct, [ {1, undefined, {map, i32, i64}, userMap, dict:new()}, {2, undefined, {list, {struct, {'thrift_test_types', 'thrift.test.Xtruct'}}}, xtructs, []} ]}, thrift_test_types:struct_info_ext('thrift.test.Insanity') )}, {"CrazyNesting definition", ?_assertEqual( {struct, [ {1, undefined, string, string_field, undefined}, {2, optional, {set, {struct, {'thrift_test_types', 'thrift.test.Insanity'}}}, set_field, sets:new()}, {3, required, {list, {map, {set, i32}, {map, i32, {set, {list, {map, {struct, {'thrift_test_types', 'thrift.test.Insanity'}}, string}}}} }}, list_field, []}, {4, undefined, string, binary_field, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.CrazyNesting') )}, {"Xception definition", ?_assertEqual( {struct, [ {1, undefined, i32, errorCode, undefined}, {2, undefined, string, message, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.Xception') )}, {"Xception2 definition", ?_assertEqual( {struct, [ {1, undefined, i32, errorCode, undefined}, {2, undefined, {struct, {'thrift_test_types', 'thrift.test.Xtruct'}}, struct_thing, #'thrift.test.Xtruct'{}} ]}, thrift_test_types:struct_info_ext('thrift.test.Xception2') )}, {"EmptyStruct definition", ?_assertEqual( {struct, []}, thrift_test_types:struct_info_ext('thrift.test.EmptyStruct') )}, {"OneField definition", ?_assertEqual( {struct, [ {1, undefined, {struct, {'thrift_test_types', 'thrift.test.EmptyStruct'}}, field, #'thrift.test.EmptyStruct'{}} ]}, thrift_test_types:struct_info_ext('thrift.test.OneField') )}, {"VersioningTestV1 definition", ?_assertEqual( {struct, [ {1, undefined, i32, begin_in_both, undefined}, {3, undefined, string, old_string, undefined}, {12, undefined, i32, end_in_both, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.VersioningTestV1') )}, {"VersioningTestV2 definition", ?_assertEqual( {struct, [ {1, undefined, i32, begin_in_both, undefined}, {2, undefined, i32, newint, undefined}, {3, undefined, byte, newbyte, undefined}, {4, undefined, i16, newshort, undefined}, {5, undefined, i64, newlong, undefined}, {6, undefined, double, newdouble, undefined}, {7, undefined, {struct, {thrift_test_types, 'thrift.test.Bonk'}}, newstruct, #'thrift.test.Bonk'{}}, {8, undefined, {list, i32}, newlist, []}, {9, undefined, {set, i32}, newset, sets:new()}, {10, undefined, {map, i32, i32}, newmap, dict:new()}, {11, undefined, string, newstring, undefined}, {12, undefined, i32, end_in_both, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.VersioningTestV2') )}, {"ListTypeVersioningV1 definition", ?_assertEqual( {struct, [ {1, undefined, {list, i32}, myints, []}, {2, undefined, string, hello, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.ListTypeVersioningV1') )}, {"ListTypeVersioningV2 definition", ?_assertEqual( {struct, [ {1, undefined, {list, string}, strings, []}, {2, undefined, string, hello, undefined} ]}, thrift_test_types:struct_info_ext('thrift.test.ListTypeVersioningV2') )}, {"GuessProtocolStruct definition", ?_assertEqual( {struct, [ {7, undefined, {map, string, string}, map_field, dict:new()} ]}, thrift_test_types:struct_info_ext('thrift.test.GuessProtocolStruct') )}, {"LargeDeltas definition", ?_assertEqual( {struct, [ {1, undefined, {struct, {thrift_test_types, 'thrift.test.Bools'}}, b1, #'thrift.test.Bools'{}}, {10, undefined, {struct, {thrift_test_types, 'thrift.test.Bools'}}, b10, #'thrift.test.Bools'{}}, {100, undefined, {struct, {thrift_test_types, 'thrift.test.Bools'}}, b100, #'thrift.test.Bools'{}}, {500, undefined, bool, check_true, undefined}, {1000, undefined, {struct, {thrift_test_types, 'thrift.test.Bools'}}, b1000, #'thrift.test.Bools'{}}, {1500, undefined, bool, check_false, undefined}, {2000, undefined, {struct, {thrift_test_types, 'thrift.test.VersioningTestV2'}}, vertwo2000, #'thrift.test.VersioningTestV2'{}}, {2500, undefined, {set, string}, a_set2500, sets:new()}, {3000, undefined, {struct, {thrift_test_types, 'thrift.test.VersioningTestV2'}}, vertwo3000, #'thrift.test.VersioningTestV2'{}}, {4000, undefined, {list, i32}, big_numbers, []} ]}, thrift_test_types:struct_info_ext('thrift.test.LargeDeltas') )}, {"NestedListsI32x2 definition", ?_assertEqual( {struct, [ {1, undefined, {list, {list, i32}}, integerlist, []} ]}, thrift_test_types:struct_info_ext('thrift.test.NestedListsI32x2') )}, {"NestedListsI32x3 definition", ?_assertEqual( {struct, [ {1, undefined, {list, {list, {list, i32}}}, integerlist, []} ]}, thrift_test_types:struct_info_ext('thrift.test.NestedListsI32x3') )}, {"NestedMixedx2 definition", ?_assertEqual( {struct, [ {1, undefined, {list, {set, i32}}, int_set_list, []}, {2, undefined, {map, i32, {set, string}}, map_int_strset, dict:new()}, {3, undefined, {list, {map, i32, {set, string}}}, map_int_strset_list, []} ]}, thrift_test_types:struct_info_ext('thrift.test.NestedMixedx2') )}, {"ListBonks definition", ?_assertEqual( {struct, [ {1, undefined, {list, {struct, {thrift_test_types, 'thrift.test.Bonk'}}}, bonk, []} ]}, thrift_test_types:struct_info_ext('thrift.test.ListBonks') )}, {"NestedListsBonk definition", ?_assertEqual( {struct, [ {1, undefined, {list, {list, {list, {struct, {thrift_test_types, 'thrift.test.Bonk'}}}}}, bonk, []} ]}, thrift_test_types:struct_info_ext('thrift.test.NestedListsBonk') )}, {"BoolTest definition", ?_assertEqual( {struct, [ {1, optional, bool, b, true}, {2, optional, string, s, "true"} ]}, thrift_test_types:struct_info_ext('thrift.test.BoolTest') )}, {"StructA definition", ?_assertEqual( {struct, [{1, required, string, s, undefined}]}, thrift_test_types:struct_info_ext('thrift.test.StructA') )}, {"StructB definition", ?_assertEqual( {struct, [ {1, optional, {struct, {thrift_test_types, 'thrift.test.StructA'}}, aa, #'thrift.test.StructA'{}}, {2, required, {struct, {thrift_test_types, 'thrift.test.StructA'}}, ab, #'thrift.test.StructA'{}} ]}, thrift_test_types:struct_info_ext('thrift.test.StructB') )} ]. service_info_test_() -> [ {"testVoid params", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testVoid, params_type) )}, {"testVoid reply", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testVoid, reply_type) )}, {"testVoid exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testVoid, exceptions) )}, {"testString params", ?_assertEqual( {struct, [{1, string}]}, thrift_test_thrift:function_info(testString, params_type) )}, {"testString reply", ?_assertEqual( string, thrift_test_thrift:function_info(testString, reply_type) )}, {"testString exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testString, exceptions) )}, {"testByte params", ?_assertEqual( {struct, [{1, byte}]}, thrift_test_thrift:function_info(testByte, params_type) )}, {"testByte reply", ?_assertEqual( byte, thrift_test_thrift:function_info(testByte, reply_type) )}, {"testByte exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testByte, exceptions) )}, {"testI32 params", ?_assertEqual( {struct, [{1, i32}]}, thrift_test_thrift:function_info(testI32, params_type) )}, {"testI32 reply", ?_assertEqual( i32, thrift_test_thrift:function_info(testI32, reply_type) )}, {"testI32 exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testI32, exceptions) )}, {"testI64 params", ?_assertEqual( {struct, [{1, i64}]}, thrift_test_thrift:function_info(testI64, params_type) )}, {"testI64 reply", ?_assertEqual( i64, thrift_test_thrift:function_info(testI64, reply_type) )}, {"testI64 exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testI64, exceptions) )}, {"testDouble params", ?_assertEqual( {struct, [{1, double}]}, thrift_test_thrift:function_info(testDouble, params_type) )}, {"testDouble reply", ?_assertEqual( double, thrift_test_thrift:function_info(testDouble, reply_type) )}, {"testDouble exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testDouble, exceptions) )}, {"testStruct params", ?_assertEqual( {struct, [ {1, {struct, {thrift_test_types, 'thrift.test.Xtruct'}}} ]}, thrift_test_thrift:function_info(testStruct, params_type) )}, {"testStruct reply", ?_assertEqual( {struct, {thrift_test_types, 'thrift.test.Xtruct'}}, thrift_test_thrift:function_info(testStruct, reply_type) )}, {"testStruct exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testStruct, exceptions) )}, {"testNest params", ?_assertEqual( {struct, [ {1, {struct, {thrift_test_types, 'thrift.test.Xtruct2'}}} ]}, thrift_test_thrift:function_info(testNest, params_type) )}, {"testNest reply", ?_assertEqual( {struct, {thrift_test_types, 'thrift.test.Xtruct2'}}, thrift_test_thrift:function_info(testNest, reply_type) )}, {"testNest exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testNest, exceptions) )}, {"testMap params", ?_assertEqual( {struct, [ {1, {map, i32, i32}} ]}, thrift_test_thrift:function_info(testMap, params_type) )}, {"testMap reply", ?_assertEqual( {map, i32, i32}, thrift_test_thrift:function_info(testMap, reply_type) )}, {"testMap exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testMap, exceptions) )}, {"testStringMap params", ?_assertEqual( {struct, [ {1, {map, string, string}} ]}, thrift_test_thrift:function_info(testStringMap, params_type) )}, {"testStringMap reply", ?_assertEqual( {map, string, string}, thrift_test_thrift:function_info(testStringMap, reply_type) )}, {"testStringMap exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testStringMap, exceptions) )}, {"testSet params", ?_assertEqual( {struct, [ {1, {set, i32}} ]}, thrift_test_thrift:function_info(testSet, params_type) )}, {"testSet reply", ?_assertEqual( {set, i32}, thrift_test_thrift:function_info(testSet, reply_type) )}, {"testSet exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testSet, exceptions) )}, {"testList params", ?_assertEqual( {struct, [ {1, {list, i32}} ]}, thrift_test_thrift:function_info(testList, params_type) )}, {"testList reply", ?_assertEqual( {list, i32}, thrift_test_thrift:function_info(testList, reply_type) )}, {"testList exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testList, exceptions) )}, {"testEnum params", ?_assertEqual( {struct, [ {1, i32} ]}, thrift_test_thrift:function_info(testEnum, params_type) )}, {"testEnum reply", ?_assertEqual( i32, thrift_test_thrift:function_info(testEnum, reply_type) )}, {"testEnum exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testEnum, exceptions) )}, {"testTypedef params", ?_assertEqual( {struct, [{1, i64}]}, thrift_test_thrift:function_info(testTypedef, params_type) )}, {"testTypedef reply", ?_assertEqual( i64, thrift_test_thrift:function_info(testTypedef, reply_type) )}, {"testTypedef exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testTypedef, exceptions) )}, {"testMapMap params", ?_assertEqual( {struct, [ {1, i32} ]}, thrift_test_thrift:function_info(testMapMap, params_type) )}, {"testMapMap reply", ?_assertEqual( {map, i32, {map, i32,i32}}, thrift_test_thrift:function_info(testMapMap, reply_type) )}, {"testMapMap exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testMapMap, exceptions) )}, {"testInsanity params", ?_assertEqual( {struct, [ {1, {struct, {thrift_test_types, 'thrift.test.Insanity'}}} ]}, thrift_test_thrift:function_info(testInsanity, params_type) )}, {"testInsanity reply", ?_assertEqual( {map, i64, {map, i32, {struct, {'thrift_test_types', 'thrift.test.Insanity'}}}}, thrift_test_thrift:function_info(testInsanity, reply_type) )}, {"testInsanity exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testInsanity, exceptions) )}, {"testMulti params", ?_assertEqual( {struct, [ {1, byte}, {2, i32}, {3, i64}, {4, {map, i16, string}}, {5, i32}, {6, i64} ]}, thrift_test_thrift:function_info(testMulti, params_type) )}, {"testMulti reply", ?_assertEqual( {struct, {thrift_test_types, 'thrift.test.Xtruct'}}, thrift_test_thrift:function_info(testMulti, reply_type) )}, {"testMulti exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testMulti, exceptions) )}, {"testException params", ?_assertEqual( {struct, [{1, string}]}, thrift_test_thrift:function_info(testException, params_type) )}, {"testException reply", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testException, reply_type) )}, {"testException exceptions", ?_assertEqual( {struct, [ {1, {struct, {thrift_test_types, 'thrift.test.Xception'}}} ]}, thrift_test_thrift:function_info(testException, exceptions) )}, {"testMultiException params", ?_assertEqual( {struct, [{1, string}, {2, string}]}, thrift_test_thrift:function_info(testMultiException, params_type) )}, {"testMultiException reply", ?_assertEqual( {struct, {thrift_test_types, 'thrift.test.Xtruct'}}, thrift_test_thrift:function_info(testMultiException, reply_type) )}, {"testMultiException exceptions", ?_assertEqual( {struct, [ {1, {struct, {thrift_test_types, 'thrift.test.Xception'}}}, {2, {struct, {thrift_test_types, 'thrift.test.Xception2'}}} ]}, thrift_test_thrift:function_info(testMultiException, exceptions) )}, {"testOneway params", ?_assertEqual( {struct, [{1, i32}]}, thrift_test_thrift:function_info(testOneway, params_type) )}, {"testOneway reply", ?_assertEqual( oneway_void, thrift_test_thrift:function_info(testOneway, reply_type) )}, {"testOneway exceptions", ?_assertEqual( {struct, []}, thrift_test_thrift:function_info(testOneway, exceptions) )}, {"secondtestString params", ?_assertEqual( {struct, [{1, string}]}, second_service_thrift:function_info(secondtestString, params_type) )}, {"secondtestString reply", ?_assertEqual( string, second_service_thrift:function_info(secondtestString, reply_type) )}, {"secondtestString exceptions", ?_assertEqual( {struct, []}, second_service_thrift:function_info(secondtestString, exceptions) )} ]. thrift-0.19.0/lib/erl/test/thrift_socket_server_test.erl0000644000000000000000000000765614303740367023434 0ustar00rootroot00000000000000-module (thrift_socket_server_test). -include_lib("eunit/include/eunit.hrl"). -include ("thrift_constants.hrl"). parse_handler_options_test_() -> CorrectServiceHandlerOptionList = [{?MULTIPLEXED_ERROR_HANDLER_KEY, ?MODULE}, {"Service1", ?MODULE}, {"Service2", ?MODULE}], MissingErrorHandlerOptionList = [{"Service1", ?MODULE}, {"Service2", ?MODULE}], WrongService2HandlerOptionList = [{?MULTIPLEXED_ERROR_HANDLER_KEY, ?MODULE}, {"Service1", ?MODULE}, {"Service2", "Module"}], WrongServiceKeyOptionList = [{?MULTIPLEXED_ERROR_HANDLER_KEY, ?MODULE}, {'service1', ?MODULE}, {"Service2", ?MODULE}], CorrectHandlerTestFunction = fun() -> ?assertMatch({thrift_socket_server,_,_,_,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{handler, CorrectServiceHandlerOptionList}])), {thrift_socket_server,_,_, HandlerList,_,_,_,_,_,_,_,_,_,_} = thrift_socket_server:parse_options([{handler, CorrectServiceHandlerOptionList}]), lists:foreach(fun ({ServiceName, HandlerModule}) -> ?assertMatch({ok, HandlerModule} when is_atom(HandlerModule), thrift_multiplexed_map_wrapper:find(ServiceName, HandlerList)) end, CorrectServiceHandlerOptionList) end, [ {"Bad argument for the handler option", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, []}]))}, {"Try to parse the handler option twice", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, ?MODULE}, {handler, CorrectServiceHandlerOptionList}]))}, {"Parse the handler option as a non multiplexed service handler", ?_assertMatch({thrift_socket_server,_,_,?MODULE,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{handler, ?MODULE}]))}, {"No error handler was defined", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, MissingErrorHandlerOptionList}]))}, {"Bad handler module for Service2", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, WrongService2HandlerOptionList}]))}, {"Bad service key for Service1", ?_assertThrow(_, thrift_socket_server:parse_options([{handler, WrongServiceKeyOptionList}]))}, {"Try to parse a correct handler option list", CorrectHandlerTestFunction} ]. parse_service_options_test_() -> CorrectServiceModuleOptionList = [{"Service1", ?MODULE}, {"Service2", ?MODULE}], WrongService2ModuleOptionList = [{"Service1", ?MODULE}, {"Service2", "thrift_service_module"}], WrongServiceKeyOptionList = [{'service1', ?MODULE}, {"Service2", ?MODULE}], CorrectServiceModuleTestFunction = fun() -> ?assertMatch({thrift_socket_server,_,_,_,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{service, CorrectServiceModuleOptionList}])), {thrift_socket_server,_, ServiceModuleList,_,_,_,_,_,_,_,_,_,_,_} = thrift_socket_server:parse_options([{service, CorrectServiceModuleOptionList}]), lists:foreach(fun ({ServiceName, ServiceModule}) -> ?assertMatch({ok, ServiceModule} when is_atom(ServiceModule), thrift_multiplexed_map_wrapper:find(ServiceName, ServiceModuleList)) end, CorrectServiceModuleOptionList) end, [ {"Bad argument for the service option", ?_assertThrow(_, thrift_socket_server:parse_options([{service, []}]))}, {"Try to parse the service option twice", ?_assertThrow(_, thrift_socket_server:parse_options([{service, ?MODULE}, {service, CorrectServiceModuleOptionList}]))}, {"Parse a service module for a non multiplexed service", ?_assertMatch({thrift_socket_server,_,?MODULE,_,_,_,_,_,_,_,_,_,_,_}, thrift_socket_server:parse_options([{service, ?MODULE}]))}, {"Bad service module for Service2", ?_assertThrow(_, thrift_socket_server:parse_options([{service, WrongService2ModuleOptionList}]))}, {"Bad service key for Service1", ?_assertThrow(_, thrift_socket_server:parse_options([{service, WrongServiceKeyOptionList}]))}, {"Try to parse a correct service option list", CorrectServiceModuleTestFunction} ]. thrift-0.19.0/lib/erl/test/test_thrift_3214.erl0000644000000000000000000000334714303740367021140 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_3214). -compile(export_all). -include("gen-erl/thrift3214_types.hrl"). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). record_generation_test_() -> [ {"StringMap record", ?_assertMatch( {'StringMap', _}, #'StringMap'{data=#{50 => "foo"}} )}, {"StringMap record defaults", ?_assertEqual( {'StringMap', #{1 => "a", 2 => "b"}}, #'StringMap'{} )}, {"StringMap record dict from list", ?_assertNotEqual( {'StringMap', dict:from_list([{1, "a"}, {2, "b"}])}, #'StringMap'{} )}, {"StringMap record map from list", ?_assertEqual( {'StringMap', maps:from_list([{1, "a"}, {2, "b"}])}, #'StringMap'{} )} ]. struct_info_test_() -> [ {"StringMap extended definition", ?_assertEqual( {struct, [ {1, undefined, {map, i32, string}, 'data', #{1 => "a", 2 => "b"}} ]}, thrift3214_types:struct_info_ext('StringMap') )} ]. -endif. thrift-0.19.0/lib/erl/test/legacy_names_test.erl0000644000000000000000000000440114303740367021606 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(legacy_names_test). -compile(export_all). -include_lib("eunit/include/eunit.hrl"). -include("gen-erl/legacyNames_constants.hrl"). record_generation_test_() -> [ {"capitalizedStruct record", ?_assertMatch( {capitalizedStruct, _, _}, #capitalizedStruct{id=null,message=null} )} ]. struct_info_test_() -> [ {"capitalizedStruct extended definition", ?_assertEqual( {struct, [ {1, undefined, i32, 'id', undefined}, {2, undefined, string, 'message', undefined} ]}, legacyNames_types:struct_info_ext(capitalizedStruct) )}, {"listCapitalizedStructs extended definition", ?_assertEqual( {struct, [ {1, undefined, {list, {struct, {'legacyNames_types', 'capitalizedStruct'}}}, 'structs', []} ]}, legacyNames_types:struct_info_ext(listCapitalizedStructs) )} ]. service_info_test_() -> [ {"names params", ?_assertEqual( {struct, [ {1, {struct, {'legacyNames_types', 'capitalizedStruct'}}}, {2, {struct, {'legacyNames_types', 'capitalizedStruct'}}} ]}, legacyNames_thrift:function_info(names, params_type) )}, {"names reply", ?_assertEqual( {struct, {'legacyNames_types', 'listCapitalizedStructs'}}, legacyNames_thrift:function_info(names, reply_type) )}, {"names exceptions", ?_assertEqual( {struct, [{1, {struct, {'legacyNames_types', 'xception'}}}]}, legacyNames_thrift:function_info(names, exceptions) )} ]. thrift-0.19.0/lib/erl/test/test_thrift_1151.erl0000644000000000000000000000146714303740367021137 0ustar00rootroot00000000000000-module(test_thrift_1151). -include("gen-erl/thrift1151_types.hrl"). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). unmatched_struct_test() -> S1 = #'StructC'{x=#'StructB'{x=1}}, {ok, Transport} = thrift_memory_buffer:new(), {ok, Protocol} = thrift_binary_protocol:new(Transport), ?assertException( error, struct_unmatched, thrift_protocol:write( Protocol, {{struct, element(2, thrift1151_types:struct_info('StructC'))}, S1} ) ). badarg_test() -> S2 = #'StructC'{x=#'StructA'{x="1"}}, {ok, Transport} = thrift_memory_buffer:new(), {ok, Protocol} = thrift_binary_protocol:new(Transport), ?assertException( error, badarg, thrift_protocol:write( Protocol, {{struct, element(2, thrift1151_types:struct_info('StructC'))}, S2} ) ). -endif. thrift-0.19.0/lib/erl/test/test_thrift_buffered_transport.erl0000644000000000000000000002147514303740367024447 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_buffered_transport). -include_lib("eunit/include/eunit.hrl"). new(Transport) -> thrift_buffered_transport:new(Transport). new_test_() -> [ {"new buffered membuffer", ?_assertMatch( {ok, {t_transport, thrift_buffered_transport, {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, []}}, [] }}}, new({t_transport, thrift_membuffer_transport, {t_membuffer, []}}) )} ]. read(Frame, Bytes) -> thrift_buffered_transport:read(Frame, Bytes). read_test_() -> [ {"read zero bytes from an empty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, {ok, <<>>} }, read( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, 0 ) )}, {"read 1 byte from an empty buffered membuffer", ?_assertMatch( {_, {ok, <<>>}}, read( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, 1 ) )}, {"read zero bytes from nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">> }}, [] }, {ok, <<>>} }, read( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">> }}, [] }, 0 ) )}, {"read 1 byte from nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"allo world">>}}, [] }, {ok, <<"h">>} }, read( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, 1 ) )}, {"read 1 byte from nonempty buffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"allo world">>}}, [] }, {ok, <<"h">>} }, read( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, 1 ) )}, {"read a zillion bytes from nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, {ok, <<"hallo world">>} }, read( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, 65536 ) )} ]. read_exact(Frame, Bytes) -> thrift_buffered_transport:read_exact(Frame, Bytes). read_exact_test_() -> [ {"read exactly zero bytes from an empty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, {ok, <<>>} }, read_exact( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, 0 ) )}, {"read exactly 1 byte from an empty buffered membuffer", ?_assertMatch( {_, {error, eof}}, read_exact( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, 1 ) )}, {"read exactly zero bytes from nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, {ok, <<>>} }, read_exact( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, 0 ) )}, {"read exactly 1 byte from nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"allo world">>}}, [] }, {ok, <<"h">>} }, read_exact( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">> }}, [] }, 1 ) )}, {"read exactly 1 byte from nonempty buffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"allo world">>}}, [] }, {ok, <<"h">>} }, read_exact( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, 1 ) )}, {"read exactly a zillion bytes from nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">>}}, [] }, {error, eof} }, read_exact( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<"hallo world">> }}, [] }, 65536 ) )} ]. write(Framed, Data) -> thrift_buffered_transport:write(Framed, Data). write_test_() -> [ {"write empty list to empty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [[], []] }, ok }, write( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, [] ) )}, {"write empty list to nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [["hallo world"], []] }, ok }, write( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, ["hallo world"] }, [] ) )}, {"write empty binary to empty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [[], <<>>] }, ok }, write( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, <<>> ) )}, {"write empty binary to nonempty buffered membuffer", ?_assertMatch( { {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [["hallo world"], <<>>] }, ok }, write( {t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, ["hallo world"] }, <<>> ) )} ]. flush(Transport) -> thrift_buffered_transport:flush(Transport). flush_test_() -> [ {"flush empty buffered membuffer", ?_assertMatch( {{t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, ok }, flush({t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }) )}, {"flush nonempty buffered membuffer", ?_assertMatch( {{t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, [<<>>, <<"hallo world">>] }}, [] }, ok }, flush({t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"hallo world">> }) )} ]. close(Transport) -> thrift_buffered_transport:close(Transport). close_test_() -> {"close buffered membuffer", ?_assertMatch( {{t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }, ok }, close({t_buffered, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [] }) )}. thrift-0.19.0/lib/erl/test/test_thrift_socket_transport.erl0000644000000000000000000001601214370300523024132 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_socket_transport). -include_lib("eunit/include/eunit.hrl"). new(Socket) -> thrift_socket_transport:new(Socket). new(Socket, Opts) -> thrift_socket_transport:new(Socket, Opts). new_test_() -> [ {"new socket", ?_assertMatch( {ok, {_, thrift_socket_transport, {t_socket, a_fake_socket, 60000, []}}}, new(a_fake_socket) )}, {"new socket with no options", ?_assertMatch( {ok, {_, thrift_socket_transport, {t_socket, a_fake_socket, 60000, []}}}, new(a_fake_socket, []) )}, {"new socket with integer timeout", ?_assertMatch( {ok, {_, thrift_socket_transport, {t_socket, a_fake_socket, 5000, []}}}, new(a_fake_socket, [{recv_timeout, 5000}]) )}, {"new socket with infinity timeout", ?_assertMatch( {ok, {_, thrift_socket_transport, {t_socket, a_fake_socket, infinity, []}}}, new(a_fake_socket, [{recv_timeout, infinity}]) )} ]. read(Socket, Bytes) -> thrift_socket_transport:read(Socket, Bytes). read_test_() -> {setup, fun() -> meck:new(gen_tcp, [unstick, passthrough]), meck:expect(gen_tcp, recv, fun(Bin, 0, _) -> case Bin of <<"empty">> -> {error, timeout}; _ -> {ok, Bin} end end), meck:expect(gen_tcp, close, fun(_) -> ok end) end, fun(_) -> meck:unload(gen_tcp) end, [ {"read zero bytes from empty socket", ?_assertMatch( {_, {ok, <<>>}}, read({t_socket, <<>>, 60000, []}, 0) )}, {"read 1 byte from empty socket", ?_assertMatch( {_, {error, timeout}}, read({t_socket, <<"empty">>, 60000, []}, 1) )}, {"read zero bytes from nonempty socket", ?_assertMatch( {{t_socket, _, _, _}, {ok, <<>>}}, read({t_socket, <<"hallo world">>, 60000, []}, 0) )}, {"read 1 byte from nonempty socket", ?_assertMatch( {{t_socket, _, _, <<"allo world">>}, {ok, <<"h">>}}, read({t_socket, <<"hallo world">>, 60000, []}, 1) )}, {"read a zillion bytes from nonempty socket", ?_assertMatch( {{t_socket, _, _, <<"ld">>}, {ok, <<"hallo world world world world wor">>}}, read({t_socket, <<"hallo world world world world world">>, 60000, []}, 33) )}, {"read 1 byte from previously buffered socket", ?_assertMatch( {{t_socket, _, _, <<"allo">>}, {ok, <<"h">>}}, read({t_socket, <<" world">>, 60000, <<"hallo">>}, 1) )}, {"read 6 byte from previously buffered socket", ?_assertMatch( {{t_socket, _, _, <<"world">>}, {ok, <<"hallo ">>}}, read({t_socket, <<" world">>, 60000, <<"hallo">>}, 6) )}, {"read a zillion bytes from previously buffered socket", ?_assertMatch( {{t_socket, _, _, <<"ld">>}, {ok, <<"hallo world world world world wor">>}}, read({t_socket, <<" world">>, 60000, <<"hallo">>}, 33) )} ] }. read_exact(Socket, Bytes) -> thrift_socket_transport:read_exact(Socket, Bytes). read_exact_test_() -> {setup, fun() -> meck:new(gen_tcp, [unstick, passthrough]), meck:expect(gen_tcp, recv, fun(Bin, N, _) -> case N of 0 -> {ok, Bin}; 1 -> {ok, <<"h">>}; N when N > 2 -> {error, timeout} end end), meck:expect(gen_tcp, close, fun(_) -> ok end) end, fun(_) -> meck:unload(gen_tcp) end, [ {"read_exact zero bytes from empty socket", ?_assertMatch( {_, {ok, <<>>}}, read_exact({t_socket, <<>>, 60000, []}, 0) )}, {"read_exact zero bytes from nonempty socket", ?_assertMatch( {{t_socket, _, _, _}, {ok, <<>>}}, read_exact({t_socket, <<"hallo world">>, 60000, []}, 0) )}, {"read_exact 1 byte from nonempty socket", ?_assertMatch( {{t_socket, _, _, []}, {ok, <<"h">>}}, read_exact({t_socket, <<"hallo world">>, 60000, []}, 1) )}, {"read_exact a zillion bytes from nonempty socket", ?_assertMatch( {{t_socket, _, _, []}, {error, timeout}}, read_exact({t_socket, <<"hallo world">>, 60000, []}, 65536) )}, {"read_exact 1 byte from previously buffered socket", ?_assertMatch( {{t_socket, _, _, <<"allo">>}, {ok, <<"h">>}}, read_exact({t_socket, <<" world">>, 60000, <<"hallo">>}, 1) )}, {"read_exact 6 byte from previously buffered socket", ?_assertMatch( {{t_socket, _, _, []}, {ok, <<"more h">>}}, read_exact({t_socket, <<"hallo">>, 60000, <<"more ">>}, 6) )}, {"read_exact a zillion bytes from previously buffered socket", ?_assertMatch( {{t_socket, _, _, <<"hallo">>}, {error, timeout}}, read_exact({t_socket, <<" world">>, 60000, <<"hallo">>}, 65536) )} ] }. write(Socket, Data) -> thrift_socket_transport:write(Socket, Data). write_test_() -> {setup, fun() -> meck:new(gen_tcp, [unstick, passthrough]), meck:expect(gen_tcp, send, fun(_, _) -> ok end) end, fun(_) -> meck:unload(gen_tcp) end, [ {"write empty list to socket", ?_assertMatch( {{t_socket, a_fake_socket, 60000, []}, ok}, write({t_socket, a_fake_socket, 60000, []}, []) )}, {"write empty binary to socket", ?_assertMatch( {{t_socket, a_fake_socket, 60000, []}, ok}, write({t_socket, a_fake_socket, 60000, []}, <<>>) )}, {"write a list to socket", ?_assertMatch( {{t_socket, a_fake_socket, 60000, []}, ok}, write({t_socket, a_fake_socket, 60000, []}, "hallo world") )}, {"write a binary to socket", ?_assertMatch( {{t_socket, a_fake_socket, 60000, []}, ok}, write({t_socket, a_fake_socket, 60000, []}, <<"hallo world">>) )} ] }. flush(Transport) -> thrift_socket_transport:flush(Transport). flush_test_() -> [ {"flush socket", ?_assertMatch( {{t_socket, a_fake_socket, 60000, []}, ok}, flush({t_socket, a_fake_socket, 60000, []}) )} ]. close(Transport) -> thrift_socket_transport:close(Transport). close_test_() -> {setup, fun() -> meck:new(gen_tcp, [unstick, passthrough]), meck:expect(gen_tcp, close, fun(_) -> ok end) end, fun(_) -> meck:unload(gen_tcp) end, [ {"close membuffer", ?_assertMatch( {{t_socket, a_fake_socket, 60000, []}, ok}, close({t_socket, a_fake_socket, 60000, []}) )} ] }. thrift-0.19.0/lib/erl/test/Thrift_omit_with.thrift0000644000000000000000000000213714370300523022153 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct test1 { 1: i32 one 2: i32 two // omit 3: i32 three } struct test2 { 1: i32 one 2: test2 two // omit 3: i32 three } struct test3 { 1: i32 one 2: list two // omit } struct test4 { 1: i32 one 2: map two // omit } thrift-0.19.0/lib/erl/test/multiplexing_test.erl0000644000000000000000000000362314303740367021705 0ustar00rootroot00000000000000-module(multiplexing_test). -include_lib("eunit/include/eunit.hrl"). -export([ handle_function/2 ,handle_error/2 ]). start_multiplexed_server_test() -> Port = 9090, Services = [ {"Multiplexing_Calculator", multiplexing__calculator_thrift}, {"Multiplexing_WeatherReport", multiplexing__weather_report_thrift} ], {ok, Pid} = thrift_socket_server:start([ {ip, "127.0.0.1"}, {port, Port}, {name, ?MODULE}, {service, Services}, {handler, [ {"error_handler", ?MODULE}, {"Multiplexing_Calculator", ?MODULE}, {"Multiplexing_WeatherReport", ?MODULE} ]} ]), {ok, [{"Multiplexing_Calculator", CalculatorClient0}, {"Multiplexing_WeatherReport", WeatherReportClient0}]} = thrift_client_util:new_multiplexed("127.0.0.1", Port, Services, []), ?assertMatch({_, {error, {bad_args, _, _}}}, thrift_client:call(WeatherReportClient0, getTemperature, [1])), ?assertMatch({_, {error, {bad_args, _, _}}}, thrift_client:call(CalculatorClient0, add, [1])), ?assertMatch({_, {error, {bad_args, _, _}}}, thrift_client:call(CalculatorClient0, add, [1,1,1])), ?assertMatch({_, {error, {no_function, _}}}, thrift_client:call(CalculatorClient0, getTemperature, [])), ?assertMatch({_, {error, {no_function, _}}}, thrift_client:call(WeatherReportClient0, add, [41, 1])), ?assertMatch({_, {ok, 42}}, thrift_client:call(CalculatorClient0, add, [41, 1])), ?assertMatch({_, {ok, 42.0}}, thrift_client:call(WeatherReportClient0, getTemperature, [])), thrift_socket_server:stop(Pid). %% HANDLE FUNCTIONS %% Calculator handles handle_function(add, {X, Y}) -> {reply, X + Y}; %% WeatherReport handles handle_function(getTemperature, {}) -> {reply, 42.0}. handle_error(_F, _Reason) -> %% ?debugHere, ?debugVal({_F, _Reason}), ok.thrift-0.19.0/lib/erl/test/test_thrift_file_transport.erl0000644000000000000000000001533314303740367023600 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_file_transport). -include_lib("eunit/include/eunit.hrl"). new(File) -> thrift_file_transport:new(File). new(File, Opts) -> thrift_file_transport:new(File, Opts). new_test_() -> [ {"new file", ?_assertMatch( {ok, {_, thrift_file_transport, {t_file, a_fake_file, true, write}}}, new(a_fake_file) )}, {"new file in read mode", ?_assertMatch( {ok, {_, thrift_file_transport, {t_file, a_fake_file, true, read}}}, new(a_fake_file, [{mode, read}]) )}, {"new file in write mode", ?_assertMatch( {ok, {_, thrift_file_transport, {t_file, a_fake_file, true, write}}}, new(a_fake_file, [{mode, write}]) )}, {"new file in should_close true mode", ?_assertMatch( {ok, {_, thrift_file_transport, {t_file, a_fake_file, true, write}}}, new(a_fake_file, [{should_close, true}]) )}, {"new file in should_close false mode", ?_assertMatch( {ok, {_, thrift_file_transport, {t_file, a_fake_file, false, write}}}, new(a_fake_file, [{should_close, false}]) )} ]. read(File, Bytes) -> thrift_file_transport:read(File, Bytes). read_test_() -> {setup, fun() -> meck:new(file, [unstick, passthrough]), meck:expect(file, read, fun(Bin, N) -> {Result, _} = split_binary(Bin, min(iolist_size(Bin), N)), {ok, Result} end) end, fun(_) -> meck:unload(file) end, [ {"read zero bytes from empty file", ?_assertMatch( {_, {ok, <<>>}}, read({t_file, <<>>, true, read}, 0) )}, {"read 1 byte from empty file", ?_assertMatch( {_, {ok, <<>>}}, read({t_file, <<>>, true, read}, 1) )}, {"read zero bytes from nonempty file", ?_assertMatch( {_, {ok, <<>>}}, read({t_file, <<"hallo world">>, true, read}, 0) )}, {"read 1 byte from nonempty file", ?_assertMatch( {_, {ok, <<"h">>}}, read({t_file, <<"hallo world">>, true, read}, 1) )}, {"read a zillion bytes from nonempty file", ?_assertMatch( {_, {ok, <<"hallo world">>}}, read({t_file, <<"hallo world">>, true, read}, 65536) )}, {"read 0 byte from file in write mode", ?_assertMatch( {_, {error, write_mode}}, read({t_file, <<>>, true, write}, 0) )}, {"read 1 byte from file in write mode", ?_assertMatch( {_, {error, write_mode}}, read({t_file, <<>>, true, write}, 1) )} ] }. read_exact(File, Bytes) -> thrift_file_transport:read_exact(File, Bytes). read_exact_test_() -> {setup, fun() -> meck:new(file, [unstick, passthrough]), meck:expect(file, read, fun(Bin, N) -> {Result, _} = split_binary(Bin, min(iolist_size(Bin), N)), {ok, Result} end) end, fun(_) -> meck:unload(file) end, [ {"read exactly zero bytes from empty file", ?_assertMatch( {_, {ok, <<>>}}, read_exact({t_file, <<>>, true, read}, 0) )}, {"read exactly 1 byte from empty file", ?_assertMatch( {_, {error, eof}}, read_exact({t_file, <<>>, true, read}, 1) )}, {"read exactly zero bytes from nonempty file", ?_assertMatch( {_, {ok, <<>>}}, read_exact({t_file, <<"hallo world">>, true, read}, 0) )}, {"read exactly 1 byte from nonempty file", ?_assertMatch( {_, {ok, <<"h">>}}, read_exact({t_file, <<"hallo world">>, true, read}, 1) )}, {"read exactly a zillion bytes from nonempty file", ?_assertMatch( {_, {error, eof}}, read_exact({t_file, <<"hallo world">>, true, read}, 65536) )}, {"read exactly 0 byte from file in write mode", ?_assertMatch( {_, {error, write_mode}}, read_exact({t_file, <<>>, true, write}, 0) )}, {"read exactly 1 byte from file in write mode", ?_assertMatch( {_, {error, write_mode}}, read_exact({t_file, <<>>, true, write}, 1) )} ] }. write(File, Data) -> thrift_file_transport:write(File, Data). write_test_() -> {setup, fun() -> meck:new(file, [unstick, passthrough]), meck:expect(file, write, fun(_, _) -> ok end) end, fun(_) -> meck:unload(file) end, [ {"write empty list to file", ?_assertMatch( {{t_file, a_fake_file, true, write}, ok}, write({t_file, a_fake_file, true, write}, []) )}, {"write empty binary to file", ?_assertMatch( {{t_file, a_fake_file, true, write}, ok}, write({t_file, a_fake_file, true, write}, <<>>) )}, {"write a list to file", ?_assertMatch( {{t_file, a_fake_file, true, write}, ok}, write({t_file, a_fake_file, true, write}, "hallo world") )}, {"write a binary to file", ?_assertMatch( {{t_file, a_fake_file, true, write}, ok}, write({t_file, a_fake_file, true, write}, <<"hallo world">>) )}, {"write a binary to file in read mode", ?_assertMatch( {_, {error, read_mode}}, write({t_file, a_fake_file, true, read}, <<"hallo world">>) )}, {"write a list to file in read mode", ?_assertMatch( {_, {error, read_mode}}, write({t_file, a_fake_file, true, read}, "hallo world") )} ] }. flush(Transport) -> thrift_file_transport:flush(Transport). flush_test_() -> {setup, fun() -> meck:new(file, [unstick, passthrough]), meck:expect(file, sync, fun(_File) -> ok end) end, fun(_) -> meck:unload(file) end, [ {"flush file", ?_assertMatch( {{t_file, a_fake_file, true, write}, ok}, flush({t_file, a_fake_file, true, write}) )} ] }. close(Transport) -> thrift_file_transport:close(Transport). close_test_() -> {setup, fun() -> meck:new(file, [unstick, passthrough]), meck:expect(file, close, fun(_) -> ok end) end, fun(_) -> meck:unload(file) end, [ {"close file", ?_assertMatch( {{t_file, a_fake_file, true, write}, ok}, close({t_file, a_fake_file, true, write}) )} ] }.thrift-0.19.0/lib/erl/test/name_conflict_test.erl0000644000000000000000000002367714303740367022000 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(name_conflict_test). -compile(export_all). -include_lib("eunit/include/eunit.hrl"). -include("gen-erl/name_conflict_test_constants.hrl"). record_generation_test_() -> [ {"using record", ?_assertMatch( {using, _, _}, #using{single=null,integer=null} )}, {"delegate record", ?_assertMatch( {delegate, _, _}, #delegate{partial=null,delegate=null} )}, {"get record", ?_assertMatch( {get, _}, #get{sbyte=null} )}, {"partial record", ?_assertMatch( {partial, _, _, _}, #partial{using=null} )}, {"ClassAndProp record", ?_assertMatch( {'ClassAndProp', _, _, _, _}, #'ClassAndProp'{ 'ClassAndProp'=null, 'ClassAndProp_'=null, 'ClassAndProp__'=null, 'ClassAndProper'=null } )}, {"second_chance record", ?_assertMatch( {second_chance, _, _, _, _}, #second_chance{ 'SECOND_CHANCE'=null, 'SECOND_CHANCE_'=null, 'SECOND_CHANCE__'=null, 'SECOND_CHANCES'=null } )}, {"NOW_EAT_THIS record", ?_assertMatch( {'NOW_EAT_THIS', _, _, _, _}, #'NOW_EAT_THIS'{ now_eat_this=null, now_eat_this_=null, now_eat_this__=null, now_eat_this_and_this=null } )}, {"TheEdgeCase record", ?_assertMatch( {'TheEdgeCase', _, _, _, _, _, _}, #'TheEdgeCase'{ theEdgeCase=null, theEdgeCase_=null, theEdgeCase__=null, 'TheEdgeCase'=null, 'TheEdgeCase_'=null, 'TheEdgeCase__'=null } )}, {"Tricky_ record", ?_assertMatch( {'Tricky_', _, _}, #'Tricky_'{tricky=null,'Tricky'=null} )}, {"Nested record", ?_assertMatch( {'Nested', _, _, _, _, _, _}, #'Nested'{ 'ClassAndProp'=null, second_chance=null, 'NOW_EAT_THIS'=null, 'TheEdgeCase'=null, 'Tricky_'=null, 'Nested'=null } )}, {"Problem_ record", ?_assertMatch( {'Problem_', _, _}, #'Problem_'{problem=null,'Problem'=null} )} ]. struct_info_test_() -> [ {"using definition", ?_assertEqual( {struct, [{1, double},{2, double}]}, name_conflict_test_types:struct_info(using) )}, {"delegate definition", ?_assertEqual( {struct, [ {1, string}, {2, {struct, {name_conflict_test_types, delegate}}} ]}, name_conflict_test_types:struct_info(delegate) )}, {"get definition", ?_assertEqual( {struct, [{1, bool}]}, name_conflict_test_types:struct_info(get) )}, {"partial definition", ?_assertEqual( {struct, [ {1, {struct, {name_conflict_test_types, using}}}, {2, bool}, {3, bool} ]}, name_conflict_test_types:struct_info(partial) )}, {"ClassAndProp definition", ?_assertEqual( {struct, [{1, bool},{2, bool},{3, bool},{4, bool}]}, name_conflict_test_types:struct_info('ClassAndProp') )}, {"second_chance definition", ?_assertEqual( {struct, [{1, bool},{2, bool},{3, bool},{4, bool}]}, name_conflict_test_types:struct_info(second_chance) )}, {"NOW_EAT_THIS definition", ?_assertEqual( {struct, [{1, bool},{2, bool},{3, bool},{4, bool}]}, name_conflict_test_types:struct_info('NOW_EAT_THIS') )}, {"TheEdgeCase definition", ?_assertEqual( {struct, [{1, bool},{2, bool},{3, bool},{4, bool},{5, bool},{6, bool}]}, name_conflict_test_types:struct_info('TheEdgeCase') )}, {"Tricky_ definition", ?_assertEqual( {struct, [{1, bool},{2, bool}]}, name_conflict_test_types:struct_info('Tricky_') )}, {"Nested definition", ?_assertEqual( {struct, [ {1, {struct, {name_conflict_test_types, 'ClassAndProp'}}}, {2, {struct, {name_conflict_test_types, second_chance}}}, {3, {struct, {name_conflict_test_types, 'NOW_EAT_THIS'}}}, {4, {struct, {name_conflict_test_types, 'TheEdgeCase'}}}, {5, {struct, {name_conflict_test_types, 'Tricky_'}}}, {6, {struct, {name_conflict_test_types, 'Nested'}}} ]}, name_conflict_test_types:struct_info('Nested') )}, {"Problem_ definition", ?_assertEqual( {struct, [{1, bool},{2, bool}]}, name_conflict_test_types:struct_info('Problem_') )}, {"using extended definition", ?_assertEqual( {struct, [ {1, undefined, double, single, undefined}, {2, undefined, double, integer, undefined} ]}, name_conflict_test_types:struct_info_ext(using) )}, {"delegate extended definition", ?_assertEqual( {struct, [ {1, undefined, string, partial, undefined}, {2, undefined, {struct, {name_conflict_test_types, delegate}}, delegate, undefined} ]}, name_conflict_test_types:struct_info_ext(delegate) )}, {"get extended definition", ?_assertEqual( {struct, [{1, undefined, bool, sbyte, undefined}]}, name_conflict_test_types:struct_info_ext(get) )}, {"partial extended definition", ?_assertEqual( {struct, [ {1, undefined, {struct, {name_conflict_test_types, using}}, using, #using{}}, {2, undefined, bool, read, undefined}, {3, undefined, bool, write, undefined} ]}, name_conflict_test_types:struct_info_ext(partial) )}, {"ClassAndProp extended definition", ?_assertEqual( {struct, [ {1, undefined, bool, 'ClassAndProp', undefined}, {2, undefined, bool, 'ClassAndProp_', undefined}, {3, undefined, bool, 'ClassAndProp__', undefined}, {4, undefined, bool, 'ClassAndProper', undefined} ]}, name_conflict_test_types:struct_info_ext('ClassAndProp') )}, {"second_chance extended definition", ?_assertEqual( {struct, [ {1, undefined, bool, 'SECOND_CHANCE', undefined}, {2, undefined, bool, 'SECOND_CHANCE_', undefined}, {3, undefined, bool, 'SECOND_CHANCE__', undefined}, {4, undefined, bool, 'SECOND_CHANCES', undefined} ]}, name_conflict_test_types:struct_info_ext(second_chance) )}, {"NOW_EAT_THIS extended definition", ?_assertEqual( {struct, [ {1, undefined, bool, now_eat_this, undefined}, {2, undefined, bool, now_eat_this_, undefined}, {3, undefined, bool, now_eat_this__, undefined}, {4, undefined, bool, now_eat_this_and_this, undefined} ]}, name_conflict_test_types:struct_info_ext('NOW_EAT_THIS') )}, {"TheEdgeCase extended definition", ?_assertEqual( {struct, [ {1, undefined, bool, theEdgeCase, undefined}, {2, undefined, bool, theEdgeCase_, undefined}, {3, undefined, bool, theEdgeCase__, undefined}, {4, undefined, bool, 'TheEdgeCase', undefined}, {5, undefined, bool, 'TheEdgeCase_', undefined}, {6, undefined, bool, 'TheEdgeCase__', undefined} ]}, name_conflict_test_types:struct_info_ext('TheEdgeCase') )}, {"Tricky_ extended definition", ?_assertEqual( {struct, [ {1, undefined, bool, tricky, undefined}, {2, undefined, bool, 'Tricky', undefined} ]}, name_conflict_test_types:struct_info_ext('Tricky_') )}, {"Nested extended definition", ?_assertEqual( {struct, [ {1, undefined, {struct, { name_conflict_test_types, 'ClassAndProp' }}, 'ClassAndProp', #'ClassAndProp'{}}, {2, undefined, {struct, { name_conflict_test_types, second_chance }}, second_chance, #second_chance{}}, {3, undefined, {struct, { name_conflict_test_types, 'NOW_EAT_THIS' }}, 'NOW_EAT_THIS', #'NOW_EAT_THIS'{}}, {4, undefined, {struct, { name_conflict_test_types, 'TheEdgeCase' }}, 'TheEdgeCase', #'TheEdgeCase'{}}, {5, undefined, {struct, { name_conflict_test_types, 'Tricky_' }}, 'Tricky_', #'Tricky_'{}}, {6, undefined, {struct, { name_conflict_test_types, 'Nested' }}, 'Nested', undefined} ]}, name_conflict_test_types:struct_info_ext('Nested') )}, {"Problem_ extended definition", ?_assertEqual( {struct, [ {1, undefined, bool, problem, undefined}, {2, undefined, bool, 'Problem', undefined} ]}, name_conflict_test_types:struct_info_ext('Problem_') )} ]. service_info_test_() -> [ {"event params", ?_assertEqual( {struct, [{1, {struct, {name_conflict_test_types, partial}}}]}, extern_thrift:function_info(event, params_type) )}, {"event reply", ?_assertEqual( {struct, {name_conflict_test_types, delegate}}, extern_thrift:function_info(event, reply_type) )}, {"event exceptions", ?_assertEqual( {struct, []}, extern_thrift:function_info(event, exceptions) )}, {"Foo params", ?_assertEqual( {struct, [{1, {struct, {name_conflict_test_types, 'Nested'}}}]}, extern_thrift:function_info('Foo', params_type) )}, {"Foo reply", ?_assertEqual( {struct, []}, extern_thrift:function_info('Foo', reply_type) )}, {"Foo exceptions", ?_assertEqual( {struct, [{1, {struct, {name_conflict_test_types, 'Problem_'}}}]}, extern_thrift:function_info('Foo', exceptions) )} ]. thrift-0.19.0/lib/erl/test/Thrift1475.thrift0000644000000000000000000000302014370300523020401 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct StructB { 1: string x } struct StructA { 1: string a, 2: binary b, 3: optional string c, 4: optional binary d, 5: required string e, 6: required binary f, 7: string g = "foo", 8: i32 h, 9: optional i32 i, 10: required i32 j, 11: required i32 k = 5, 12: double l, 13: optional double m, 14: required double n, 15: double o = 3.14159, 16: list string_list, 17: list byte_list = [1, 2, 3], 18: required list rsl, 19: optional list osl, 20: set string_set, 21: required set rss, 22: optional set oss, 23: map string_map, 24: required map rsm, 25: optional map osm, 26: StructB structb } thrift-0.19.0/lib/erl/test/test_omit.erl0000644000000000000000000000616114303740367020134 0ustar00rootroot00000000000000-module(test_omit). -include("gen-erl/thrift_omit_with_types.hrl"). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). omit_struct1_test() -> %% In this test, the field that is deleted is a basic type (an i32). A = #test1{one = 1, three = 3}, B = #test1{one = 1, two = 2, three = 3}, {ok, Transport} = thrift_membuffer_transport:new(), {ok, P0} = thrift_binary_protocol:new(Transport), {P1, ok} = thrift_protocol:write(P0, {{struct, {thrift_omit_with_types, element(1, A)}}, A}), {P2, {ok, O0}} = thrift_protocol:read(P1, {struct, {thrift_omit_without_types, element(1, A)}}), ?assertEqual(element(1, A), element(1, O0)), ?assertEqual(element(2, A), element(2, O0)), ?assertEqual(element(4, A), element(3, O0)), {P3, ok} = thrift_protocol:write(P2, {{struct, {thrift_omit_with_types, element(1, B)}}, B}), {_P4, {ok, O1}} = thrift_protocol:read(P3, {struct, {thrift_omit_without_types, element(1, A)}}), ?assertEqual(element(1, A), element(1, O1)), ?assertEqual(element(2, A), element(2, O1)), ?assertEqual(element(4, A), element(3, O1)), ok. omit_struct2_test() -> %% In this test, the field that is deleted is a struct. A = #test2{one = 1, two = #test2{one = 10, three = 30}, three = 3}, B = #test2{one = 1, two = #test2{one = 10, two = #test2{one = 100}, three = 30}, three = 3}, {ok, Transport} = thrift_membuffer_transport:new(), {ok, P0} = thrift_binary_protocol:new(Transport), {P1, ok} = thrift_protocol:write(P0, {{struct, {thrift_omit_with_types, element(1, A)}}, A}), {P2, {ok, O0}} = thrift_protocol:read(P1, {struct, {thrift_omit_without_types, element(1, A)}}), ?assertEqual(element(1, A), element(1, O0)), ?assertEqual(element(2, A), element(2, O0)), ?assertEqual(element(4, A), element(3, O0)), {P3, ok} = thrift_protocol:write(P2, {{struct, {thrift_omit_with_types, element(1, B)}}, B}), {_P4, {ok, O1}} = thrift_protocol:read(P3, {struct, {thrift_omit_without_types, element(1, A)}}), ?assertEqual(element(1, A), element(1, O1)), ?assertEqual(element(2, A), element(2, O1)), ?assertEqual(element(4, A), element(3, O1)), ok. omit_list_test() -> %% In this test, the field that is deleted is a list. A = #test1{one = 1, two = 2, three = 3}, B = #test3{one = 1, two = [ A ]}, {ok, Transport} = thrift_membuffer_transport:new(), {ok, P0} = thrift_binary_protocol:new(Transport), {P1, ok} = thrift_protocol:write(P0, {{struct, {thrift_omit_with_types, element(1, B)}}, B}), {_P2, {ok, O0}} = thrift_protocol:read(P1, {struct, {thrift_omit_without_types, element(1, B)}}), ?assertEqual(element(2, B), element(2, O0)), ok. omit_map_test() -> %% In this test, the field that is deleted is a map. A = #test1{one = 1, two = 2, three = 3}, B = #test4{one = 1, two = dict:from_list([ {2, A} ])}, {ok, Transport} = thrift_membuffer_transport:new(), {ok, P0} = thrift_binary_protocol:new(Transport), {P1, ok} = thrift_protocol:write(P0, {{struct, {thrift_omit_with_types, element(1, B)}}, B}), {_P2, {ok, O0}} = thrift_protocol:read(P1, {struct, {thrift_omit_without_types, element(1, B)}}), ?assertEqual(element(2, B), element(2, O0)), ok. -endif. %% TEST thrift-0.19.0/lib/erl/test/test_disklog.erl0000644000000000000000000000633214303740367020620 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_disklog). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). disklog_test() -> {ok, TransportFactory} = thrift_disk_log_transport:new_transport_factory( test_disklog, [{file, "./test_log"}, {size, {1024*1024, 10}}]), {ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory( TransportFactory, []), {ok, Proto} = ProtocolFactory(), {ok, Client0} = thrift_client:new(Proto, thrift_test_thrift), io:format("Client started~n"), % We have to make oneway calls into this client only since otherwise it % will try to read from the disklog and go boom. {Client1, {ok, ok}} = thrift_client:call(Client0, testOneway, [16#deadbeef]), io:format("Call written~n"), % Use the send_call method to write a non-oneway call into the log {Client2, ok} = thrift_client:send_call(Client1, testString, [<<"hello world">>]), io:format("Non-oneway call sent~n"), {_Client3, ok} = thrift_client:close(Client2), io:format("Client closed~n"), lists:foreach(fun(File) -> file:delete(File) end, [ "./test_log.1", "./test_log.idx", "./test_log.siz" ]), io:format("Cleaning up test files~n"), ok. disklog_base64_test() -> {ok, TransportFactory} = thrift_disk_log_transport:new_transport_factory( test_disklog, [{file, "./test_b64_log"}, {size, {1024*1024, 10}}]), {ok, B64Factory} = thrift_base64_transport:new_transport_factory(TransportFactory), {ok, BufFactory} = thrift_buffered_transport:new_transport_factory(B64Factory), {ok, ProtocolFactory} = thrift_binary_protocol:new_protocol_factory(BufFactory, []), {ok, Proto} = ProtocolFactory(), {ok, Client0} = thrift_client:new(Proto, thrift_test_thrift), io:format("Client started~n"), % We have to make oneway calls into this client only since otherwise % it will try to read from the disklog and go boom. {Client1, {ok, ok}} = thrift_client:call(Client0, testOneway, [16#deadbeef]), io:format("Call written~n"), % Use the send_call method to write a non-oneway call into the log {Client2, ok} = thrift_client:send_call(Client1, testString, [<<"hello world">>]), io:format("Non-oneway call sent~n"), {_Client3, ok} = thrift_client:close(Client2), io:format("Client closed~n"), lists:foreach(fun(File) -> file:delete(File) end, [ "./test_b64_log.1", "./test_b64_log.idx", "./test_b64_log.siz" ]), io:format("Cleaning up test files~n"), ok. -endif. thrift-0.19.0/lib/erl/test/test_thrift_compact_protocol.erl0000644000000000000000000002077414303740367024121 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_compact_protocol). -include_lib("eunit/include/eunit.hrl"). -include("thrift_constants.hrl"). -include("thrift_protocol.hrl"). new(Transport) -> thrift_compact_protocol:new(Transport). new() -> {ok, Transport} = thrift_membuffer_transport:new(), thrift_compact_protocol:new(Transport). new_test() -> new(thrift_membuffer_transport:new()). write(This, Value) -> thrift_protocol:write(This, Value). read(This, Type) -> thrift_protocol:read(This, Type). str(This0, Value0) -> {This1, ok} = write(This0, {string, Value0}), {This2, {ok, Value1}} = read(This1, string), ?assertEqual(Value0, binary_to_list(Value1)), {This2, ok}. string_test() -> {ok, This0} = new(), {This1, ok} = str(This0, "aaa"), {This2, ok} = str(This1, ""), {This2, ok}. round_trip(This0, Type, Value0) -> {This1, ok} = write(This0, {Type, Value0}), {This2, {ok, Value1}} = read(This1, Type), ?assertEqual(Value0, Value1), {This2, ok}. bool_test() -> {ok, This0} = new(), {This1, ok} = round_trip(This0, bool, true), {This2, ok} = round_trip(This1, bool, false), {This2, ok}. byte(This0, Value0) -> round_trip(This0, byte, Value0). byte_test() -> {ok, This0} = new(), {This1, ok} = byte(This0, 0), {This2, ok} = byte(This1, 42), {This3, ok} = byte(This2, -1), {This4, ok} = byte(This3, -128), {This4, ok}. i16(This0, Value0) -> round_trip(This0, i16, Value0). i16_test() -> {ok, This0} = new(), {This1, ok} = i16(This0, 0), {This2, ok} = i16(This1, 42), {This3, ok} = i16(This2, 30000), {This4, ok} = i16(This3, -1), {This5, ok} = i16(This4, -128), {This6, ok} = i16(This5, -30000), {This6, ok}. i32(This0, Value0) -> round_trip(This0, i32, Value0). i32_test() -> {ok, This0} = new(), {This1, ok} = i32(This0, 0), {This2, ok} = i32(This1, 42), {This3, ok} = i32(This2, 30000), {This4, ok} = i32(This3, 2000000002), {This5, ok} = i32(This4, -1), {This6, ok} = i32(This5, -128), {This7, ok} = i32(This6, -30000), {This8, ok} = i32(This7, -2000000002), {This8, ok}. i64(This0, Value0) -> round_trip(This0, i64, Value0). i64_test() -> {ok, This0} = new(), {This1, ok} = i64(This0, 0), {This2, ok} = i64(This1, 42), {This3, ok} = i64(This2, 30000), {This4, ok} = i64(This3, 2000000002), {This5, ok} = i64(This4, 100000000000000064), {This6, ok} = i64(This5, -1), {This7, ok} = i64(This6, -128), {This8, ok} = i64(This7, -30000), {This9, ok} = i64(This8, -2000000002), {This10, ok} = i64(This9, -100000000000000064), {This10, ok}. struct_test() -> {ok, P0} = new(), {P1, ok} = write(P0, #protocol_message_begin{ name = "Message1", type = ?tType_I8, seqid = 3}), {P2, ok} = write(P1, #protocol_struct_begin{}), {P3, ok} = write(P2, #protocol_field_begin{ name = "field1", type = ?tType_I8, id = 1}), {P4, ok} = write(P3, {byte, 42}), {P5, ok} = write(P4, field_end), {P6, ok} = write(P5, #protocol_field_begin{ name = "field2", type = ?tType_I8, id = 14}), {P7, ok} = write(P6, {byte, 3}), {P8, ok} = write(P7, field_end), {P9, ok} = write(P8, #protocol_field_begin{ name = "field3", type = ?tType_I8, id = 42}), {P10, ok} = write(P9, {byte, 8}), {P11, ok} = write(P10, field_end), {P12, ok} = write(P11, field_stop), {P13, ok} = write(P12, struct_end), {P14, ok} = write(P13, message_end), {P15, #protocol_message_begin{ name = "Message1", type = ?tType_I8, seqid = 3}} = read(P14, message_begin), {P16, ok} = read(P15, struct_begin), {P17, #protocol_field_begin{ type = ?tType_I8, id = 1 }} = read(P16, field_begin), {P18, {ok, 42}} = read(P17, byte), {P19, ok} = read(P18, field_end), {P20, #protocol_field_begin{ type = ?tType_I8, id = 14 }} = read(P19, field_begin), {P21, {ok, 3}} = read(P20, byte), {P22, ok} = read(P21, field_end), {P23, #protocol_field_begin{ type = ?tType_I8, id = 42 }} = read(P22, field_begin), {P24, {ok, 8}} = read(P23, byte), {P25, ok} = read(P24, field_end), {P26, #protocol_field_begin{ type = ?tType_STOP}} = read(P25, field_begin), {P27, ok} = read(P26, struct_end), {P28, ok} = read(P27, message_end), {P28, ok}. bool_field_test() -> {ok, P0} = new(), {P1, ok} = write(P0, #protocol_message_begin{ name = "Message1", type = ?tType_I8, seqid = 3}), {P2, ok} = write(P1, #protocol_struct_begin{}), {P3, ok} = write(P2, #protocol_field_begin{ name = "field1", type = ?tType_BOOL, id = 1}), {P4, ok} = write(P3, {bool, true}), {P5, ok} = write(P4, field_end), {P6, ok} = write(P5, #protocol_field_begin{ name = "field2", type = ?tType_BOOL, id = 14}), {P7, ok} = write(P6, {bool, false}), {P8, ok} = write(P7, field_end), {P9, ok} = write(P8, #protocol_field_begin{ name = "field3", type = ?tType_BOOL, id = 42}), {P10, ok} = write(P9, {bool, true}), {P11, ok} = write(P10, field_end), {P12, ok} = write(P11, field_stop), {P13, ok} = write(P12, struct_end), {P14, ok} = write(P13, message_end), {P15, #protocol_message_begin{ name = "Message1", type = ?tType_I8, seqid = 3}} = read(P14, message_begin), {P16, ok} = read(P15, struct_begin), {P17, #protocol_field_begin{ type = ?tType_BOOL, id = 1 }} = read(P16, field_begin), {P18, {ok, true}} = read(P17, bool), {P19, ok} = read(P18, field_end), {P20, #protocol_field_begin{ type = ?tType_BOOL, id = 14 }} = read(P19, field_begin), {P21, {ok, false}} = read(P20, bool), {P22, ok} = read(P21, field_end), {P23, #protocol_field_begin{ type = ?tType_BOOL, id = 42 }} = read(P22, field_begin), {P24, {ok, true}} = read(P23, bool), {P25, ok} = read(P24, field_end), {P26, #protocol_field_begin{ type = ?tType_STOP}} = read(P25, field_begin), {P27, ok} = read(P26, struct_end), {P28, ok} = read(P27, message_end), {P28, ok}. nesting_test() -> {ok, P0} = new(), {P1, ok} = write(P0, #protocol_message_begin{ name = "Message1", type = ?tType_I8, seqid = 3}), {P2, ok} = write(P1, #protocol_struct_begin{}), {P3, ok} = write(P2, #protocol_field_begin{ name = "field1", type = ?tType_BOOL, id = 14}), {P4, ok} = write(P3, {bool, true}), {P5, ok} = write(P4, field_end), {P6, ok} = write(P5, #protocol_field_begin{ name = "field2", type = ?tType_STRUCT, id = 28}), {P7, ok} = write(P6, #protocol_struct_begin{}), {P8, ok} = write(P7, #protocol_field_begin{ name = "field2_1", type = ?tType_BOOL, id = 30000}), {P9, ok} = write(P8, {bool, false}), {P10, ok} = write(P9, field_end), {P11, ok} = write(P10, field_stop), {P12, ok} = write(P11, struct_end), {P13, ok} = write(P12, field_end), {P14, ok} = write(P13, #protocol_field_begin{ name = "field3", type = ?tType_BOOL, id = 42}), {P15, ok} = write(P14, {bool, true}), {P16, ok} = write(P15, field_end), {P17, ok} = write(P16, field_stop), {P18, ok} = write(P17, struct_end), {P19, ok} = write(P18, message_end), {P20, #protocol_message_begin{ name = "Message1", type = ?tType_I8, seqid = 3}} = read(P19, message_begin), {P21, ok} = read(P20, struct_begin), {P22, #protocol_field_begin{ type = ?tType_BOOL, id = 14 }} = read(P21, field_begin), {P23, {ok, true}} = read(P22, bool), {P24, ok} = read(P23, field_end), {P25, #protocol_field_begin{ type = ?tType_STRUCT, id = 28 }} = read(P24, field_begin), {P26, ok} = read(P25, struct_begin), {P27, #protocol_field_begin{ type = ?tType_BOOL, id = 30000 }} = read(P26, field_begin), {P28, {ok, false}} = read(P27, bool), {P29, ok} = read(P28, field_end), {P30, #protocol_field_begin{ type = ?tType_STOP }} = read(P29, field_begin), {P31, ok} = read(P30, struct_end), {P32, ok} = read(P31, field_end), {P33, #protocol_field_begin{ type = ?tType_BOOL, id = 42 }} = read(P32, field_begin), {P34, {ok, true}} = read(P33, bool), {P35, ok} = read(P34, field_end), {P36, #protocol_field_begin{ type = ?tType_STOP }} = read(P35, field_begin), {P37, ok} = read(P36, struct_end), {P38, ok} = read(P37, message_end), {P38, ok}. thrift-0.19.0/lib/erl/test/test_thrift_membuffer_transport.erl0000644000000000000000000001254214303740367024630 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_membuffer_transport). -include_lib("eunit/include/eunit.hrl"). new() -> thrift_membuffer_transport:new(). new(Data) -> thrift_membuffer_transport:new(Data). new_test_() -> [ {"new empty membuffer", ?_assertMatch( {ok, {_, _, {t_membuffer, []}}}, new() )}, {"new membuffer with <<>>", ?_assertMatch( {ok, {_, _, {t_membuffer, [<<>>]}}}, new(<<>>) )}, {"new membuffer with []", ?_assertMatch( {ok, {_, _, {t_membuffer, []}}}, new([]) )}, {"new membuffer with <<\"hallo world\">>", ?_assertMatch( {ok, {_, _, {t_membuffer, [<<"hallo world">>]}}}, new(<<"hallo world">>) )}, {"new membuffer with \"hallo world\"", ?_assertMatch( {ok, {_, _, {t_membuffer, "hallo world"}}}, new("hallo world") )} ]. read(Membuffer, Bytes) -> thrift_membuffer_transport:read(Membuffer, Bytes). read_test_() -> [ {"read zero bytes from an empty membuffer", ?_assertMatch( {_, {ok, <<>>}}, read({t_membuffer, []}, 0) )}, {"read 1 byte from an empty membuffer", ?_assertMatch( {_, {ok, <<>>}}, read({t_membuffer, []}, 1) )}, {"read zero bytes from nonempty membuffer", ?_assertMatch( {{t_membuffer, <<"hallo world">>}, {ok, <<>>}}, read({t_membuffer, [["hallo", " "], "world"]}, 0) )}, {"read 1 byte from nonempty membuffer", ?_assertMatch( {{t_membuffer, <<"allo world">>}, {ok, <<"h">>}}, read({t_membuffer, [["hallo", " "], "world"]}, 1) )}, {"read a zillion bytes from nonempty buffer", ?_assertMatch( {{t_membuffer, <<>>}, {ok, <<"hallo world">>}}, read({t_membuffer, [["hallo", " "], "world"]}, 65536) )} ]. read_exact(Membuffer, Bytes) -> thrift_membuffer_transport:read_exact(Membuffer, Bytes). read_exact_test_() -> [ {"read exactly zero bytes from an empty membuffer", ?_assertMatch( {_, {ok, <<>>}}, read_exact({t_membuffer, []}, 0) )}, {"read exactly 1 byte from an empty membuffer", ?_assertMatch( {_, {error, eof}}, read_exact({t_membuffer, []}, 1) )}, {"read exactly zero bytes from nonempty membuffer", ?_assertMatch( {{t_membuffer, <<"hallo world">>}, {ok, <<>>}}, read_exact({t_membuffer, [["hallo", " "], "world"]}, 0) )}, {"read exactly 1 byte from nonempty membuffer", ?_assertMatch( {{t_membuffer, <<"allo world">>}, {ok, <<"h">>}}, read_exact({t_membuffer, [["hallo", " "], "world"]}, 1) )}, {"read exactly a zillion bytes from nonempty buffer", ?_assertMatch( {{t_membuffer, [["hallo", " "], "world"]}, {error, eof}}, read_exact({t_membuffer, [["hallo", " "], "world"]}, 65536) )} ]. write(Membuffer, Data) -> thrift_membuffer_transport:write(Membuffer, Data). write_test_() -> [ {"write empty list to empty membuffer", ?_assertMatch( {{t_membuffer, [[], []]}, ok}, write({t_membuffer, []}, []) )}, {"write empty list to nonempty membuffer", ?_assertMatch( {{t_membuffer, ["hallo world", []]}, ok}, write({t_membuffer, "hallo world"}, []) )}, {"write empty binary to empty membuffer", ?_assertMatch( {{t_membuffer, [[], <<>>]}, ok}, write({t_membuffer, []}, <<>>) )}, {"write empty binary to nonempty membuffer", ?_assertMatch( {{t_membuffer, ["hallo world", <<>>]}, ok}, write({t_membuffer, "hallo world"}, <<>>) )}, {"write a list to empty membuffer", ?_assertMatch( {{t_membuffer, [[], "hallo world"]}, ok}, write({t_membuffer, []}, "hallo world") )}, {"write a list to nonempty membuffer", ?_assertMatch( {{t_membuffer, [["hallo", " "], "world"]}, ok}, write({t_membuffer, ["hallo", " "]}, "world") )}, {"write a binary to empty membuffer", ?_assertMatch( {{t_membuffer, [[], <<"hallo world">>]}, ok}, write({t_membuffer, []}, <<"hallo world">>) )}, {"write a binary to nonempty membuffer", ?_assertMatch( {{t_membuffer, [["hallo", " "], <<"world">>]}, ok}, write({t_membuffer, ["hallo", " "]}, <<"world">>) )} ]. flush(Transport) -> thrift_membuffer_transport:flush(Transport). flush_test_() -> [ {"flush empty membuffer", ?_assertMatch( {{t_membuffer, []}, ok}, flush({t_membuffer, []}) )}, {"flush nonempty membuffer", ?_assertMatch( {{t_membuffer, [<<"hallo world">>]}, ok}, flush({t_membuffer, [<<"hallo world">>]}) )} ]. close(Transport) -> thrift_membuffer_transport:close(Transport). close_test_() -> {"close membuffer", ?_assertMatch( {{t_membuffer, _}, ok}, close({t_membuffer, []}) )}.thrift-0.19.0/lib/erl/test/flags/0000777000000000000000000000000014370300523016503 5ustar00rootroot00000000000000thrift-0.19.0/lib/erl/test/flags/LegacyNames.thrift0000644000000000000000000000234614370300523022116 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ enum Numberz { ONE = 1, TWO, THREE, FIVE = 5, SIX, EIGHT = 8 } const Numberz myNumberz = Numberz.ONE; struct CapitalizedStruct { 1: i32 Id, 2: binary message } struct ListCapitalizedStructs { 1: list structs } exception Xception { 1: i32 errorCode, 2: binary message } service LegacyNames { ListCapitalizedStructs Names(1: CapitalizedStruct foo, 2: CapitalizedStruct bar) throws(1: Xception err) }thrift-0.19.0/lib/erl/test/flags/Thrift3214.thrift0000644000000000000000000000155114303740367021507 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct StringMap { 1: map data = {1: "a", 2: "b"}; } thrift-0.19.0/lib/erl/test/test_rendered_double_constants.erl0000644000000000000000000001073714303740367024406 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_rendered_double_constants). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -include("gen-erl/double_constants_test_constants.hrl"). -define(EPSILON, 0.0000001). rendered_double_constants_test() -> ?assert(abs(1.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST) =< ?EPSILON), ?assert(abs(-100.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST) =< ?EPSILON), ?assert(abs(9223372036854775807.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST) =< ?EPSILON), ?assert(abs(-9223372036854775807.0 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST) =< ?EPSILON), ?assert(abs(3.14159265359 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST) =< ?EPSILON), ?assert(abs(1000000.1 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), ?assert(abs(-1000000.1 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), ?assert(abs(1.7e+308 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST) =< ?EPSILON), ?assert(abs(9223372036854775816.43 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), ?assert(abs(-1.7e+308 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST) =< ?EPSILON), ?assert(abs(-9223372036854775816.43 - ?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) =< ?EPSILON), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST)), ?assert(is_float(?DOUBLE_CONSTANTS_TEST_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST)). rendered_double_list_test() -> ?assertEqual(12, length(?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)), ?assert(abs(1.0 - lists:nth(1, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(-100.0 - lists:nth(2, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(100.0 - lists:nth(3, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(9223372036854775807.0 - lists:nth(4, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(-9223372036854775807.0 - lists:nth(5, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(3.14159265359 - lists:nth(6, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(1000000.1 - lists:nth(7, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(-1000000.1 - lists:nth(8, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(1.7e+308 - lists:nth(9, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(-1.7e+308 - lists:nth(10, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(9223372036854775816.43 - lists:nth(11, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON), ?assert(abs(-9223372036854775816.43 - lists:nth(12, ?DOUBLE_CONSTANTS_TEST_DOUBLE_LIST_TEST)) =< ?EPSILON). -endif. %% TESTthrift-0.19.0/lib/erl/test/Thrift1151.thrift0000644000000000000000000000160014370300523020372 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ struct StructA { 1: i16 x; } struct StructB { 1: i32 x; } struct StructC { 1: StructA x; } thrift-0.19.0/lib/erl/test/stress_server.erl0000644000000000000000000000271314303740367021035 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(stress_server). -export([start_link/1, handle_function/2, echoVoid/0, echoByte/1, echoI32/1, echoI64/1, echoString/1, echoList/1, echoSet/1, echoMap/1 ]). start_link(Port) -> thrift_server:start_link(Port, service_thrift, ?MODULE). handle_function(Function, Args) -> case apply(?MODULE, Function, tuple_to_list(Args)) of ok -> ok; Else -> {reply, Else} end. echoVoid() -> ok. echoByte(X) -> X. echoI32(X) -> X. echoI64(X) -> X. echoString(X) -> X. echoList(X) -> X. echoSet(X) -> X. echoMap(X) -> X. thrift-0.19.0/lib/erl/test/test_const.erl0000644000000000000000000000412214303740367020305 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_const). -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). -include("gen-erl/constants_demo_types.hrl"). namespace_test() -> %% Verify that records produced by ConstantsDemo.thrift have the right namespace. io:format(user, "in namespace_test()\n", []), {struct, _} = constants_demo_types:struct_info('consts_thing'), {struct, _} = constants_demo_types:struct_info('consts_Blah'), ok. const_map_test() -> ?assertEqual(233, constants_demo_constants:gen_map(35532)), ?assertError(function_clause, constants_demo_constants:gen_map(0)), ?assertEqual(853, constants_demo_constants:gen_map(43523, default)), ?assertEqual(default, constants_demo_constants:gen_map(10110, default)), ?assertEqual(98325, constants_demo_constants:gen_map2("lkjsdf")), ?assertError(function_clause, constants_demo_constants:gen_map2("nonexist")), ?assertEqual(233, constants_demo_constants:gen_map2("hello", 321)), ?assertEqual(321, constants_demo_constants:gen_map2("goodbye", 321)). const_list_test() -> ?assertEqual(23598352, constants_demo_constants:gen_list(2)), ?assertError(function_clause, constants_demo_constants:gen_list(0)), ?assertEqual(3253523, constants_demo_constants:gen_list(3, default)), ?assertEqual(default, constants_demo_constants:gen_list(10, default)). -endif. %% TEST thrift-0.19.0/lib/erl/test/multiplexing.thrift0000644000000000000000000000165514370300523021355 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ service Multiplexing_Calculator { i32 add(1: i32 x, 2: i32 y) } service Multiplexing_WeatherReport { double getTemperature() } thrift-0.19.0/lib/erl/test/test_thrift_framed_transport.erl0000644000000000000000000002265314303740367024122 0ustar00rootroot00000000000000%% %% Licensed to the Apache Software Foundation (ASF) under one %% or more contributor license agreements. See the NOTICE file %% distributed with this work for additional information %% regarding copyright ownership. The ASF licenses this file %% to you under the Apache License, Version 2.0 (the %% "License"); you may not use this file except in compliance %% with the License. You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, %% software distributed under the License is distributed on an %% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY %% KIND, either express or implied. See the License for the %% specific language governing permissions and limitations %% under the License. %% -module(test_thrift_framed_transport). -include_lib("eunit/include/eunit.hrl"). new(Transport) -> thrift_framed_transport:new(Transport). new_test_() -> [ {"new framed membuffer", ?_assertMatch( {ok, {t_transport, thrift_framed_transport, {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, []}}, [], [] }}}, new({t_transport, thrift_membuffer_transport, {t_membuffer, []}}) )} ]. read(Frame, Bytes) -> thrift_framed_transport:read(Frame, Bytes). read_test_() -> [ {"read zero bytes from an empty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, {ok, <<>>} }, read( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, 0 ) )}, {"read 1 byte from an empty framed membuffer", ?_assertMatch( {_, {error, eof}}, read( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, 1 ) )}, {"read zero bytes from nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, {ok, <<>>} }, read( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, 0 ) )}, {"read 1 byte from nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"allo world">>, [] }, {ok, <<"h">>} }, read( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, 1 ) )}, {"read 1 byte from nonempty buffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"allo world">>, [] }, {ok, <<"h">>} }, read( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"hallo world">>, [] }, 1 ) )}, {"read a zillion bytes from nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<>>, [] }, {ok, <<"hallo world">>} }, read( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, 65536 ) )} ]. read_exact(Frame, Bytes) -> thrift_framed_transport:read_exact(Frame, Bytes). read_exact_test_() -> [ {"read exactly zero bytes from an empty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<>>, [] }, {ok, <<>>} }, read_exact( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, 0 ) )}, {"read exactly 1 byte from an empty framed membuffer", ?_assertMatch( {_, {error, eof}}, read_exact( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, 1 ) )}, {"read exactly zero bytes from nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, <<>>, [] }, {ok, <<>>} }, read_exact( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, 0 ) )}, {"read exactly 1 byte from nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"allo world">>, [] }, {ok, <<"h">>} }, read_exact( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, 1 ) )}, {"read exactly 1 byte from nonempty buffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"allo world">>, [] }, {ok, <<"h">>} }, read_exact( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, <<"hallo world">>, [] }, 1 ) )}, {"read exactly a zillion bytes from nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [[],<<"hallo world">>], [] }, {error, eof} }, read_exact( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<0, 0, 0, 11, "hallo world">> }}, [], [] }, 65536 ) )} ]. write(Framed, Data) -> thrift_framed_transport:write(Framed, Data). write_test_() -> [ {"write empty list to empty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [[], []] }, ok }, write( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, [] ) )}, {"write empty list to nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [["hallo world"], []] }, ok }, write( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], ["hallo world"] }, [] ) )}, {"write empty binary to empty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [[], <<>>] }, ok }, write( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, <<>> ) )}, {"write empty binary to nonempty framed membuffer", ?_assertMatch( { {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [["hallo world"], <<>>] }, ok }, write( {t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], ["hallo world"] }, <<>> ) )} ]. flush(Transport) -> thrift_framed_transport:flush(Transport). flush_test_() -> [ {"flush empty framed membuffer", ?_assertMatch( {{t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, ok }, flush({t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }) )}, {"flush nonempty framed membuffer", ?_assertMatch( {{t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, [<<>>, [<<0, 0, 0, 11>>, <<"hallo world">>]] }}, [], [] }, ok }, flush({t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], <<"hallo world">> }) )} ]. close(Transport) -> thrift_framed_transport:close(Transport). close_test_() -> {"close framed membuffer", ?_assertMatch( {{t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }, ok }, close({t_framed, {t_transport, thrift_membuffer_transport, {t_membuffer, <<>>}}, [], [] }) )}. thrift-0.19.0/lib/erl/rebar.config0000644000000000000000000000027014303740367016717 0ustar00rootroot00000000000000{erl_opts, [debug_info]}. {profiles, [ {test, [ {deps, [meck]}, {eunit_tests, [ {dir, "test"}, {dir, "test/gen-erl"} ]} ]} ]}. thrift-0.19.0/lib/erl/rebar.config.script0000644000000000000000000000041614303740367020224 0ustar00rootroot00000000000000Def0 = case not erlang:is_builtin(erlang, monotonic_time, 0) of true -> []; false -> [{d, time_correction}] end, Defs = Def0, lists:keystore(erl_opts, 1, CONFIG, {erl_opts, proplists:get_value(erl_opts, CONFIG, []) ++ Defs}). thrift-0.19.0/lib/erl/Makefile.in0000644000000000000000000004605214472652516016517 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/erl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = ../../compiler/cpp/thrift TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ THRIFT_OMIT_FILE = test/Thrift_omit_without.thrift THRIFT_FILES = $(wildcard test/*.thrift) \ $(THRIFT_OMIT_FILE) \ ../../test/v0.16/ConstantsDemo.thrift \ ../../test/v0.16/NameConflictTest.thrift \ ../../test/DoubleConstantsTest.thrift \ ../../test/v0.16/ThriftTest.thrift ERL_FLAG = erl ERL_FLAG_LEGACY = erl:legacynames ERL_FLAG_MAPS = erl:maps EXTRA_DIST = \ include \ src \ coding_standards.md \ rebar.config \ rebar.config.script \ test \ README.md MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/erl/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/erl/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am all-am: Makefile installdirs: install-exec: install-exec-am install-data: install-data-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am dist-hook distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic maintainer-clean-local mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile $(THRIFT_OMIT_FILE): test/Thrift_omit_with.thrift grep -v omit $< >$@ .generated: $(THRIFT) $(THRIFT_FILES) for f in $(THRIFT_FILES) ; do \ $(THRIFT) --gen $(ERL_FLAG) -o test $$f ; \ done $(THRIFT) --gen $(ERL_FLAG_LEGACY) -o test test/flags/LegacyNames.thrift $(THRIFT) --gen $(ERL_FLAG_MAPS) -o test test/flags/Thrift3214.thrift touch .generated all: .generated $(REBAR) compile check: .generated $(REBAR) eunit install: all mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) ; \ mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/ebin ; \ mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/include ; \ mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/src ; \ for p in ebin/*.app* ebin/*.beam include/*.hrl src/*.erl ; \ do $(INSTALL) $$p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/$$p ; \ done uninstall: $(RM) -rf $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) clean-local: $(REBAR) clean $(RM) .generated $(RM) -r .rebar/ $(RM) -r _build/ $(RM) -r test/gen-erl/ $(RM) $(THRIFT_OMIT_FILE) maintainer-clean-local: $(RM) -r ebin/ dist-hook: $(RM) $(distdir)/.generated $(RM) -r $(distdir)/.rebar/ $(RM) -r $(distdir)/_build/ $(RM) -r $(distdir)/ebin/ $(RM) -r $(distdir)/test/gen-erl/ $(RM) $(distdir)/$(THRIFT_OMIT_FILE) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/json/0000755000000000000000000000000014472652646014636 5ustar00rootroot00000000000000thrift-0.19.0/lib/json/Makefile.am0000644000000000000000000000173114303740367016663 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # if WITH_JAVA # Schema validation test depends on java SUBDIRS = test endif clean-local: $(RM) -r test/build/ dist-hook: $(RM) -r $(distdir)/test/build/ EXTRA_DIST = \ schema.json \ test thrift-0.19.0/lib/json/schema.json0000644000000000000000000002062114370300523016747 0ustar00rootroot00000000000000{ "$schema": "http://json-schema.org/draft-04/schema#", "id": "http://thrift.apache.org/schema.json#", "description": "Schema for Apache Thrift protocol descriptors", "definitions": { "type-id": { "title": "Any type id (name)", "enum": [ "void", "string", "bool", "byte", "i8", "i16", "i32", "i64", "double", "list", "set", "map", "union", "struct", "binary", "uuid", "enum" ] }, "base-type": { "title": "Base type schema", "type": "object", "properties": { "typeId": { "enum": ["void", "string", "bool", "byte", "i8", "i16", "i32", "i64", "double", "binary", "uuid" ] } }, "required": [ "typeId" ] }, "list-type": { "title": "List and set schema", "type": "object", "properties": { "typeId": { "enum": [ "list", "set" ] }, "elemTypeId": { "$ref": "#/definitions/type-id" }, "elemType": { "$ref": "#/definitions/type-desc" } }, "required": [ "typeId", "elemTypeId" ] }, "map-type": { "title": "Map schema", "type": "object", "properties": { "typeId": { "enum": [ "map" ] }, "keyTypeId": { "$ref": "#/definitions/type-id" }, "keyType": { "$ref": "#/definitions/type-desc" }, "valueTypeId": { "$ref": "#/definitions/type-id" }, "valueType": { "$ref": "#/definitions/type-desc" } }, "required": [ "typeId", "keyTypeId", "valueTypeId" ] }, "struct-type": { "title": "Struct, union and exception schema", "type": "object", "properties": { "typeId": { "enum": [ "union", "struct", "exception", "enum" ] } }, "required": [ "typeId", "class" ] }, "type-desc": { "title": "Type descriptor schema", "allOf": [ { "type": "object", "properties": { "typeId": { "type": "string" }, "class": { "type": "string" } } }, { "oneOf": [ { "$ref": "#/definitions/base-type" }, { "$ref": "#/definitions/list-type" }, { "$ref": "#/definitions/map-type" }, { "$ref": "#/definitions/struct-type" } ] } ] }, "name-and-doc": { "title": "Name and documentation sub-schema", "type": "object", "properties": { "name": { "type": "string" }, "doc": { "type": "string" } }, "required": [ "name" ] }, "enum": { "title": "Thrift 'enum' definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "required": [ "members" ], "properties": { "members": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "value": { "type": "integer" } }, "required": [ "name", "value" ] } } } } ] }, "typedef": { "title": "Thrift typedef definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "properties": { "typeId": { "$ref": "#/definitions/type-id" }, "type": { "$ref": "#/definitions/type-desc" } }, "required": [ "typeId" ] } ] }, "constant": { "title": "Thrift constant definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "$ref": "#/definitions/type-desc" }, { "properties": { "value": { "oneOf": [ { "type": "string" }, { "type": "number" }, { "type": "array" }, { "type": "object" } ] } }, "required": [ "value" ] } ] }, "field": { "title": "Thrift struct field definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "properties": { "key": { "type": "integer", "minimum": 1, "maximum": 65535 }, "required": { "enum": [ "required", "optional", "req_out" ] }, "typeId": { "$ref": "#/definitions/type-id" }, "type": { "$ref": "#/definitions/type-desc" }, "default": { "oneOf": [ { "type": "string" }, { "type": "number" }, { "type": "array" }, { "type": "object" } ] } }, "required": [ "key", "required" ] } ] }, "struct": { "title": "Thrift struct definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "properties": { "isException": { "type": "boolean" }, "isUnion": { "type": "boolean" }, "fields": { "type": "array", "items": { "$ref": "#/definitions/field" } } }, "required": [ "isException", "isUnion", "fields" ] } ] }, "union": { "title": "Thrift union definition schema", "$ref": "#/definitions/struct" }, "exception": { "title": "Thrift exception definition schema", "type": "object", "properties": { "key": { "type": "integer", "minimum": 1, "maximum": 65535 }, "name": { "type": "string" }, "typeId": { "enum": [ "exception" ] }, "type": { "$ref": "#/definitions/struct-type" } }, "required": [ "key", "name", "typeId" ] }, "function": { "title": "Thrift service function definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "properties": { "oneway": { "type": "boolean" }, "returnType": { "$ref": "#/definitions/type-desc" }, "arguments": { "type": "array", "items": { "$ref": "#/definitions/field" } }, "exceptions": { "type": "array", "items": { "$ref": "#/definitions/exception" } } }, "required": [ "oneway", "arguments", "exceptions" ] } ] }, "service": { "title": "Thrift service definition schema", "type": "object", "allOf": [ { "$ref": "#/definitions/name-and-doc" }, { "properties": { "functions": { "type": "array", "items": { "$ref": "#/definitions/function" } } }, "required": [ "functions" ] } ] }, "annotations": { "title": "Map of annotation names to values", "type": "object", "additionalProperties": { "type": "string" } } }, "type": "object", "required": [ "name", "enums", "typedefs", "structs", "constants", "services" ], "properties": { "name": { "type": "string" }, "includes": { "type": "array", "items": { "type": "string" }, "uniqueItems": true }, "namespaces": { "type": "object", "additionalProperties": { "type": "string" } }, "enums": { "type": "array", "items": { "$ref": "#/definitions/enum" } }, "typedefs": { "type": "array", "items": { "$ref": "#/definitions/typedef" } }, "structs": { "type": "array", "items": { "$ref": "#/definitions/struct" } }, "constants": { "type": "array", "items": { "$ref": "#/definitions/constant" } }, "services": { "type": "array", "items": { "$ref": "#/definitions/service" } } }, "additionalProperties": false } thrift-0.19.0/lib/json/test/0000777000000000000000000000000014472652604015613 5ustar00rootroot00000000000000thrift-0.19.0/lib/json/test/Makefile.am0000644000000000000000000000171214303740367017641 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # check: $(ANT) $(ANT_FLAGS) test # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean thrift-0.19.0/lib/json/test/Makefile0000644000000000000000000004336414472652604017261 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # lib/json/test/Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/thrift pkgincludedir = $(includedir)/thrift pkglibdir = $(libdir)/thrift pkglibexecdir = $(libexecdir)/thrift am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = x86_64-pc-linux-gnu host_triplet = x86_64-pc-linux-gnu subdir = lib/json/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_$(V)) am__v_P_ = $(am__v_P_$(AM_DEFAULT_VERBOSITY)) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_$(V)) am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_$(V)) am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = ${SHELL} /thrift/src/missing aclocal-1.15 ALLOCA = AMTAR = $${TAR-tar} AM_DEFAULT_VERBOSITY = 1 ANT = /usr/bin/ant ANT_FLAGS = AR = ar AUTOCONF = ${SHELL} /thrift/src/missing autoconf AUTOHEADER = ${SHELL} /thrift/src/missing autoheader AUTOMAKE = ${SHELL} /thrift/src/missing automake-1.15 AWK = mawk BISON = bison BOOST_CHRONO_LDADD = /usr/lib/x86_64-linux-gnu/libboost_chrono.a BOOST_CPPFLAGS = -I/usr/include BOOST_FILESYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_filesystem.a BOOST_LDFLAGS = -L/usr/lib/x86_64-linux-gnu BOOST_LIB_DIR = /usr/lib/x86_64-linux-gnu BOOST_SYSTEM_LDADD = /usr/lib/x86_64-linux-gnu/libboost_system.a BOOST_TEST_LDADD = /usr/lib/x86_64-linux-gnu/libboost_unit_test_framework.a BOOST_THREAD_LDADD = /usr/lib/x86_64-linux-gnu/libboost_thread.a BUNDLER = /usr/bin/bundle CARGO = /root/.cargo/bin/cargo CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CLASSPATH = CPP = gcc -E CPPFLAGS = CPPSTYLE_CMD = find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \; CXX = g++ -std=c++11 CXXCPP = g++ -E -std=c++11 CXXDEPMODE = depmode=gcc3 CXXFLAGS = -g -O2 CYGPATH_W = echo DART = /usr/lib/dart/bin/dart DARTPUB = /usr/lib/dart/bin/pub DEFS = -DHAVE_CONFIG_H DEPDIR = .deps DLLTOOL = false DMD = dmd DMD_LIBEVENT_FLAGS = -L-fuse-ld=gold -L-levent DMD_OF_DIRSEP = / DMD_OPENSSL_FLAGS = -L-fuse-ld=gold -L-lssl -L-lcrypto DOTNETCORE = /usr/bin/dotnet DOTNETCORE_VERSION = 6.0.405 DSYMUTIL = DUMPBIN = D_EVENT_LIB_NAME = libthriftd-event.a D_IMPORT_PREFIX = ${prefix}/include/d2 D_LIB_NAME = libthriftd.a D_SSL_LIB_NAME = libthriftd-ssl.a ECHO_C = ECHO_N = -n ECHO_T = EGREP = /bin/grep -E ENABLE_COVERAGE = 2 ERL = /usr/local/lib/otp/bin/erl ERLANG_INSTALL_LIB_DIR = /usr/local/lib/otp/lib ERLANG_INSTALL_LIB_DIR_thrift = ${ERLANG_INSTALL_LIB_DIR}/thrift-0.19.0 ERLANG_LIB_DIR = /usr/local/lib/otp/lib ERLC = /usr/local/lib/otp/bin/erlc ERLCFLAGS = EXEEXT = FGREP = /bin/grep -F GCOV_CFLAGS = GCOV_CXXFLAGS = GCOV_LDFLAGS = GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GLIB_LIBS = -lglib-2.0 GO = /usr/local/bin/go GOBJECT_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include GOBJECT_LIBS = -lgobject-2.0 -lglib-2.0 GRADLE = /usr/local/bin/gradle GRADLE_OPTS = GREP = /bin/grep GSETTINGS = /usr/bin/gsettings HAVE_CXX11 = 1 HAXE = /usr/bin/haxe HAXE_VERSION = 3.4.4 INSTALL = /usr/bin/install -c INSTALLDIRS = vendor INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s JAVA_PREFIX = /usr/local/lib LD = /usr/bin/ld -m elf_x86_64 LDFLAGS = LEX = flex LEXLIB = LEX_OUTPUT_ROOT = lex.yy LIBEVENT_CPPFLAGS = LIBEVENT_LDFLAGS = LIBEVENT_LIBS = -levent LIBOBJS = LIBS = -lrt -lpthread LIBTOOL = $(SHELL) $(top_builddir)/libtool LIPO = LN_S = ln -s LTLIBOBJS = LT_SYS_LIBRARY_PATH = LUA = /usr/bin/lua LUA_EXEC_PREFIX = ${exec_prefix} LUA_INCLUDE = -I/usr/include/lua5.2 LUA_LIB = -llua5.2 -ldl LUA_PLATFORM = unknown LUA_PREFIX = ${prefix} LUA_SHORT_VERSION = 52 LUA_VERSION = 5.2 MAKEINFO = ${SHELL} /thrift/src/missing makeinfo MANIFEST_TOOL = : MAYBE_CL = cl MAYBE_CPP = cpp MAYBE_C_GLIB = c_glib MAYBE_D = d MAYBE_DART = dart MAYBE_ERLANG = erl MAYBE_GO = go MAYBE_JAVA = java MAYBE_KOTLIN = MAYBE_LUA = lua MAYBE_NETSTD = MAYBE_NODEJS = nodejs MAYBE_NODETS = nodets MAYBE_PERL = perl MAYBE_PHP = php MAYBE_PY3 = py3 MAYBE_PYTHON = py MAYBE_RS = rs MAYBE_RUBY = rb MAYBE_SWIFT = swift MKDIR_P = /bin/mkdir -p NM = /usr/bin/nm -B NMEDIT = NODEJS = /usr/bin/nodejs NODETS = /usr/bin/node NPM = /usr/bin/npm OBJDUMP = objdump OBJEXT = o OPENSSL_INCLUDES = OPENSSL_LDFLAGS = OPENSSL_LIBS = -lssl -lcrypto OTOOL = OTOOL64 = PACKAGE = thrift PACKAGE_BUGREPORT = PACKAGE_NAME = thrift PACKAGE_STRING = thrift 0.19.0 PACKAGE_TARNAME = thrift PACKAGE_URL = PACKAGE_VERSION = 0.19.0 PATH_SEPARATOR = : PERL = /usr/bin/perl PERL_PREFIX = /usr/local PHP = /usr/bin/php PHP_CONFIG = /usr/bin/php-config PHP_CONFIG_PREFIX = /etc/php.d PHP_PREFIX = /usr/lib/php PKG_CONFIG = /usr/bin/pkg-config PKG_CONFIG_LIBDIR = PKG_CONFIG_PATH = PYTHON = /usr/bin/python PYTHON3 = /usr/bin/python3 PYTHON_EXEC_PREFIX = ${exec_prefix} PYTHON_PLATFORM = linux2 PYTHON_PREFIX = ${prefix} PYTHON_VERSION = 2.7 PY_PREFIX = /usr QT5_CFLAGS = -I/usr/include/x86_64-linux-gnu/qt5/QtNetwork -I/usr/include/x86_64-linux-gnu/qt5 -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5 QT5_LIBS = -lQt5Network -lQt5Core QT5_MOC = /usr/bin/moc RANLIB = ranlib REBAR = /usr/local/bin/rebar3 RUBY = /usr/bin/ruby RUBY_PREFIX = RUSTC = /root/.cargo/bin/rustc SBCL = /usr/local/bin/sbcl SED = /bin/sed SET_MAKE = SHELL = /bin/bash STRIP = strip SWIFT = /usr/share/swift/usr/bin/swift THRIFT = /thrift/src/compiler/cpp/thrift TRIAL = /usr/bin/trial VERSION = 0.19.0 YACC = bison -y YFLAGS = ZLIB_CPPFLAGS = ZLIB_LDFLAGS = ZLIB_LIBS = -lz abs_builddir = /thrift/src/lib/json/test abs_srcdir = /thrift/src/lib/json/test abs_top_builddir = /thrift/src abs_top_srcdir = /thrift/src ac_ct_AR = ar ac_ct_CC = gcc ac_ct_CXX = g++ ac_ct_DUMPBIN = am__include = include am__leading_dot = . am__quote = am__tar = tar --hard-dereference --format=ustar -chf - "$$tardir" am__untar = tar -xf - bindir = ${exec_prefix}/bin build = x86_64-pc-linux-gnu build_alias = build_cpu = x86_64 build_os = linux-gnu build_vendor = pc builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE_TARNAME} dvidir = ${docdir} exec_prefix = ${prefix} golang_version = go version go1.19.5 linux/amd64 have_prog_bison = yes host = x86_64-pc-linux-gnu host_alias = host_cpu = x86_64 host_os = linux-gnu host_vendor = pc htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = ${SHELL} /thrift/src/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var luadir = ${prefix}/share/lua/5.2 luaexecdir = ${exec_prefix}/lib/lua/5.2 mandir = ${datarootdir}/man mkdir_p = $(MKDIR_P) oldincludedir = /usr/include pdfdir = ${docdir} pkgluadir = ${luadir}/thrift pkgluaexecdir = ${luaexecdir}/thrift pkgpyexecdir = ${pyexecdir}/thrift pkgpythondir = ${pythondir}/thrift prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} pyexecdir = ${exec_prefix}/lib/python2.7/dist-packages pythondir = ${prefix}/lib/python2.7/dist-packages runstatedir = ${localstatedir}/run rustc_version = rustc 1.61.0 (fe5b13d68 2022-05-18) sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . subdirs = lib/php/src/ext/thrift_protocol sysconfdir = ${prefix}/etc target_alias = top_build_prefix = ../../../ top_builddir = ../../.. top_srcdir = ../../.. all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/json/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/json/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile check: $(ANT) $(ANT_FLAGS) test # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/json/test/build.xml0000644000000000000000000001207214370300523017415 0ustar00rootroot00000000000000 JSON Schema Validation Test Thrift compiler is missing ! thrift-0.19.0/lib/json/test/build.properties0000644000000000000000000000050714303740367021023 0ustar00rootroot00000000000000# Jar versions mvn.ant.task.version=2.1.3 # Dependency versions json-schema-validator.version=2.2.6 # Maven dependency download locations mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar thrift-0.19.0/lib/json/test/Makefile.in0000644000000000000000000004244714472652516017671 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/json/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/json/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/json/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ clean-local cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags-am uninstall uninstall-am .PRECIOUS: Makefile check: $(ANT) $(ANT_FLAGS) test # Make sure this doesn't fail if ant is not configured. clean-local: ANT=$(ANT) ; if test -z "$$ANT" ; then ANT=: ; fi ; \ $$ANT $(ANT_FLAGS) clean # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/json/Makefile.in0000644000000000000000000005717614472652516016717 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/json ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = test am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # Schema validation test depends on java @WITH_JAVA_TRUE@SUBDIRS = test EXTRA_DIST = \ schema.json \ test all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/json/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/json/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool clean-local \ cscopelist-am ctags ctags-am dist-hook distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile clean-local: $(RM) -r test/build/ dist-hook: $(RM) -r $(distdir)/test/build/ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/Makefile.in0000644000000000000000000006172414472652514015736 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_CPP_TRUE@am__append_1 = cpp @WITH_C_GLIB_TRUE@am__append_2 = c_glib # JavaScript unit test depends on java # so test only if java, ant & co is available @WITH_JAVA_TRUE@am__append_3 = java js @WITH_JAVA_TRUE@am__append_4 = precross-java @WITH_KOTLIN_TRUE@am__append_5 = kotlin @WITH_KOTLIN_TRUE@am__append_6 = precross-kotlin @WITH_PYTHON_TRUE@am__append_7 = py @WITH_ERLANG_TRUE@am__append_8 = erl @WITH_RUBY_TRUE@am__append_9 = rb @WITH_PERL_TRUE@am__append_10 = perl @WITH_PHP_TRUE@am__append_11 = php @WITH_DART_TRUE@am__append_12 = dart @WITH_DOTNET_TRUE@am__append_13 = netstd @WITH_GO_TRUE@am__append_14 = go @WITH_D_TRUE@am__append_15 = d @WITH_D_TRUE@am__append_16 = precross-d @WITH_NODEJS_TRUE@am__append_17 = nodejs nodets @WITH_NODEJS_TRUE@am__append_18 = precross-nodejs @WITH_LUA_TRUE@am__append_19 = lua @WITH_RS_TRUE@am__append_20 = rs @WITH_CL_TRUE@am__append_21 = cl @WITH_SWIFT_TRUE@am__append_22 = swift subdir = lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = json xml cpp c_glib java js kotlin py erl rb perl php \ dart netstd go d nodejs nodets lua rs cl swift am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = json xml $(am__append_1) $(am__append_2) $(am__append_3) \ $(am__append_5) $(am__append_7) $(am__append_8) \ $(am__append_9) $(am__append_10) $(am__append_11) \ $(am__append_12) $(am__append_13) $(am__append_14) \ $(am__append_15) $(am__append_17) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) PRECROSS_TARGET = $(am__append_4) $(am__append_6) $(am__append_16) \ $(am__append_18) # All of the libs that don't use Automake need to go in here # so they will end up in our release tarballs. EXTRA_DIST = \ d \ dart \ delphi \ haxe \ javame \ js \ ocaml \ st \ ts all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile precross-%: $(MAKE) -C $* precross precross: $(PRECROSS_TARGET) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/nodets/0000755000000000000000000000000014472652666015163 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodets/Makefile.am0000644000000000000000000000332614370300523017176 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # We call npm twice to work around npm issues stubs: $(top_srcdir)/test/v0.16/ThriftTest.thrift mkdir -p test-compiled $(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/v0.16/ThriftTest.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/Int64Test.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/Int64Test.thrift ts-compile: stubs mkdir -p test-compiled ../../node_modules/typescript/bin/tsc --outDir test-compiled/ --project test/tsconfig.json deps: $(top_srcdir)/package.json $(NPM) install $(top_srcdir)/ || $(NPM) install $(top_srcdir)/ all-local: deps ts-compile precross: deps stubs ts-compile check: deps ts-compile cd $(top_srcdir) && $(NPM) run test-ts && cd lib/nodets clean-local: $(RM) -r test/gen-nodejs $(RM) -r $(top_srcdir)/node_modules $(RM) -r test-compiled EXTRA_DIST = \ test \ coding_standards.md thrift-0.19.0/lib/nodets/coding_standards.md0000644000000000000000000000010314303740367020772 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) thrift-0.19.0/lib/nodets/test/0000777000000000000000000000000014370300523016121 5ustar00rootroot00000000000000thrift-0.19.0/lib/nodets/test/test-cases.ts0000644000000000000000000001051214303740367020551 0ustar00rootroot00000000000000'use strict'; import ttypes = require('./gen-nodejs/ThriftTest_types'); import Int64 = require('node-int64'); //all Languages in UTF-8 /*jshint -W100 */ export var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, " + "Asturianu, Aymar aru, AzÉ™rbaycan, Башҡорт, Boarisch, ŽemaitÄ—Å¡ka, " + "БеларуÑкаÑ, БеларуÑÐºÐ°Ñ (тарашкевіца), БългарÑки, Bamanankan, " + "বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Ðохчийн, " + "Cebuano, á£áŽ³áŽ©, ÄŒesky, СловѣÌньÑкъ / ⰔⰎⰑⰂⰡâ°â° â°”â°â°Ÿ, Чӑвашла, Cymraeg, " + "Dansk, Zazaki, Þ‹Þ¨ÞˆÞ¬Þ€Þ¨Þ„Þ¦ÞÞ°, Ελληνικά, Emiliàn e rumagnòl, English, " + "Esperanto, Español, Eesti, Euskara, ÙØ§Ø±Ø³ÛŒ, Suomi, Võro, Føroyskt, " + "Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, " + "Avañe'ẽ, ગà«àªœàª°àª¾àª¤à«€, Gaelg, עברית, हिनà¥à¤¦à¥€, Fiji Hindi, Hrvatski, " + "Kreyòl ayisyen, Magyar, Õ€Õ¡ÕµÕ¥Ö€Õ¥Õ¶, Interlingua, Bahasa Indonesia, " + "Ilokano, Ido, Ãslenska, Italiano, 日本語, Lojban, Basa Jawa, " + "ქáƒáƒ áƒ—ული, Kongo, Kalaallisut, ಕನà³à²¨à²¡, 한국어, Къарачай-Малкъар, " + "Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, " + "Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, LatvieÅ¡u, Basa " + "Banyumasan, Malagasy, МакедонÑки, മലയാളം, मराठी, Ù…Ø§Ø²ÙØ±ÙˆÙ†ÛŒ, Bahasa " + "Melayu, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪" + "Norsk (nynorsk)‬, ‪Norsk (bokmÃ¥l)‬, Nouormand, Diné bizaad, " + "Occitan, Иронау, Papiamentu, Deitsch, Polski, پنجابی, پښتو, " + "Norfuk / Pitkern, Português, Runa Simi, Rumantsch, Romani, Română, " + "РуÑÑкий, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple " + "English, SlovenÄina, SlovenÅ¡Äina, СрпÑки / Srpski, Seeltersk, " + "Svenska, Kiswahili, தமிழà¯, తెలà±à°—à±, Тоҷикӣ, ไทย, Türkmençe, Tagalog, " + "Türkçe, Татарча/Tatarça, УкраїнÑька, اردو, Tiếng Việt, Volapük, " + "Walon, Winaray, å´è¯­, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, " + "Bân-lâm-gú, 粵語"; /*jshint +W100 */ export var specialCharacters = 'quote: \" backslash:' + ' forwardslash-escaped: \/ ' + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + ' now-all-of-them-together: "\\\/\b\n\r\t' + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><' + ' char-to-test-json-parsing: ]] \"]] \\" }}}{ [[[ '; export var mapTestInput = { "a":"123", "a b":"with spaces ", "same":"same", "0":"numeric key", "longValue":stringTest, stringTest:"long key" }; export var simple = [ ['testVoid', undefined], ['testString', 'Test'], ['testString', ''], ['testString', stringTest], ['testString', specialCharacters], ['testByte', 1], ['testByte', 0], ['testByte', -1], ['testByte', -127], ['testI32', -1], ['testDouble', -5.2098523], ['testDouble', 7.012052175215044], ['testEnum', ttypes.Numberz.ONE] ]; export var simpleLoose = [ ['testI64', 5], ['testI64', -5], ['testI64', 734359738368], ['testI64', -34359738368], ['testI64', -734359738368], ['testTypedef', 69] ] var mapout: {[key: number]: number; } = {}; for (var i = 0; i < 5; ++i) { mapout[i] = i-10; } export var deep = [ ['testMap', mapout], ['testSet', [1,2,3]], ['testList', [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]], ['testStringMap', mapTestInput] ]; export var out = new ttypes.Xtruct({ string_thing: 'Zero', byte_thing: 1, i32_thing: -3, i64_thing: new Int64(1000000) }); export var out2 = new ttypes.Xtruct2(); out2.byte_thing = 1; out2.struct_thing = out; out2.i32_thing = 5; export var crazy = new ttypes.Insanity({ "userMap":{ "5":new Int64(5), "8":new Int64(8) }, "xtructs":[new ttypes.Xtruct({ "string_thing":"Goodbye4", "byte_thing":4, "i32_thing":4, "i64_thing":new Int64(4) }), new ttypes.Xtruct({ "string_thing":"Hello2", "byte_thing":2, "i32_thing":2, "i64_thing":new Int64(2) })] }); export var insanity: any = { "1":{ "2": crazy, "3": crazy }, "2":{ "6":{ "userMap":{}, "xtructs":[] } } }; thrift-0.19.0/lib/nodets/test/test_handler.ts0000644000000000000000000002260114303740367021154 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ //This is the server side Node test handler for the standard // Apache Thrift test service. import ttypes = require("./gen-nodejs/ThriftTest_types"); import thrift = require("thrift"); import Thrift = thrift.Thrift; import Q = require("q"); import Int64 = require("node-int64"); export class SyncThriftTestHandler { testVoid(): Q.IPromise { //console.log('testVoid()'); return Q.resolve(undefined); } testMapMap(hello: number) { //console.log('testMapMap(' + hello + ')'); var mapmap: {[key: number]: {[key: number]: number; }} = []; var pos: {[key: number]: number; } = []; var neg: {[key: number]: number; } = []; for (var i = 1; i < 5; i++) { pos[i] = i; neg[-i] = -i; } mapmap[4] = pos; mapmap[-4] = neg; return Q.resolve(mapmap); } testInsanity(argument: ttypes.Insanity): Q.IPromise<{ [k: number]: any; }> { const first_map: { [k: number]: any; } = []; const second_map: { [k: number]: any; } = []; first_map[ttypes.Numberz.TWO] = argument; first_map[ttypes.Numberz.THREE] = argument; const looney = new ttypes.Insanity(); second_map[ttypes.Numberz.SIX] = looney; const insane: { [k: number]: any; } = []; insane[1] = first_map; insane[2] = second_map; return Q.resolve(insane); } testMulti(arg0: any, arg1: number, arg2: Int64, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number) { var hello = new ttypes.Xtruct(); hello.string_thing = 'Hello2'; hello.byte_thing = arg0; hello.i32_thing = arg1; hello.i64_thing = arg2; return Q.resolve(hello); } testException(arg: string): Q.IPromise { if (arg === 'Xception') { var x = new ttypes.Xception(); x.errorCode = 1001; x.message = arg; throw x; } else if (arg === 'TException') { throw new Thrift.TException(arg); } else { return Q.resolve(); } } testMultiException(arg0: string, arg1: string) { if (arg0 === ('Xception')) { var x = new ttypes.Xception(); x.errorCode = 1001; x.message = 'This is an Xception'; throw x; } else if (arg0 === ('Xception2')) { var x2 = new ttypes.Xception2(); x2.errorCode = 2002; x2.struct_thing = new ttypes.Xtruct(); x2.struct_thing.string_thing = 'This is an Xception2'; throw x2; } var res = new ttypes.Xtruct(); res.string_thing = arg1; return Q.resolve(res); } testOneway(sleepFor: number) { } testString(thing: string) { return Q.resolve(thing); } testBool(thing: boolean) { return Q.resolve(thing); } testByte(thing: number) { return Q.resolve(thing); } testI32(thing: number) { return Q.resolve(thing); } testI64(thing: number) { return Q.resolve(thing); } testDouble(thing: number) { return Q.resolve(thing); } testBinary(thing: Buffer) { return Q.resolve(thing); } testStruct(thing: ttypes.Xtruct) { return Q.resolve(thing); } testNest(thing: ttypes.Xtruct2) { return Q.resolve(thing); } testMap(thing: { [k: number]: number; }) { return Q.resolve(thing); } testStringMap(thing: { [k: string]: string; }) { return Q.resolve(thing); } testSet(thing: number[]) { return Q.resolve(thing); } testList(thing: number[]) { return Q.resolve(thing); } testEnum(thing: ttypes.Numberz) { return Q.resolve(thing); } testTypedef(thing: number) { return Q.resolve(thing); } } export class AsyncThriftTestHandler { private syncHandler: SyncThriftTestHandler; constructor() { this.syncHandler = new SyncThriftTestHandler(); } testVoid(callback: (result: void) => void): Q.IPromise { callback(undefined); return Q.resolve(); } testMapMap(hello: number, callback: (err: any, result: { [k: number]: { [k: number]: number; }; }) => void): Q.IPromise<{ [k: number]: { [k: number]: number; }; }> { var mapmap: {[key: number]: {[key: number]: number; }} = []; var pos: {[key: number]: number; } = []; var neg: {[key: number]: number; } = []; for (var i = 1; i < 5; i++) { pos[i] = i; neg[-i] = -i; } mapmap[4] = pos; mapmap[-4] = neg; callback(null, mapmap); return Q.resolve(); } testInsanity(argument: ttypes.Insanity, callback?: (err: any, result: { [k: number]: any; }) => void): Q.IPromise<{ [k: number]: any; }> { const first_map: { [k: number]: any; } = []; const second_map: { [k: number]: any; } = []; first_map[ttypes.Numberz.TWO] = argument; first_map[ttypes.Numberz.THREE] = argument; const looney = new ttypes.Insanity(); second_map[ttypes.Numberz.SIX] = looney; const insane: { [k: number]: any; } = []; insane[1] = first_map; insane[2] = second_map; if (callback !== undefined){ callback(null, insane); } return Q.resolve(); } testMulti(arg0: any, arg1: number, arg2: Int64, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number, result: Function): Q.IPromise { var hello = this.syncHandler.testMulti(arg0, arg1, arg2, arg3, arg4, arg5); hello.then(hello => result(null, hello)); return Q.resolve(); } testException(arg: string, result: (err: any) => void): Q.IPromise { if (arg === 'Xception') { var x = new ttypes.Xception(); x.errorCode = 1001; x.message = arg; result(x); } else if (arg === 'TException') { result(new Thrift.TException(arg)); } else { result(null); } return Q.resolve(); } testMultiException(arg0: string, arg1: string, result: (err: any, res?: ttypes.Xtruct) => void): Q.IPromise { if (arg0 === ('Xception')) { var x = new ttypes.Xception(); x.errorCode = 1001; x.message = 'This is an Xception'; result(x); } else if (arg0 === ('Xception2')) { var x2 = new ttypes.Xception2(); x2.errorCode = 2002; x2.struct_thing = new ttypes.Xtruct(); x2.struct_thing.string_thing = 'This is an Xception2'; result(x2); } else { var res = new ttypes.Xtruct(); res.string_thing = arg1; result(null, res); } return Q.resolve(); } testOneway(sleepFor: number, result: Function) { this.syncHandler.testOneway(sleepFor); } testString(thing: string, callback: (err: any, result: string) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testByte(thing: number, callback: (err: any, result: number) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testBool(thing: boolean, callback: (err: any, result: boolean) => void ): Q.IPromise { callback(null, thing); return Q.resolve(); } testI32(thing: number, callback: (err: any, result: number) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testI64(thing: number, callback: (err: any, result: number) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testDouble(thing: number, callback: (err: any, result: number) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testBinary(thing: Buffer, callback: (err: any, result: Buffer) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testStruct(thing: ttypes.Xtruct, callback: (err: any, result: ttypes.Xtruct) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testNest(thing: ttypes.Xtruct2, callback: (err: any, result: ttypes.Xtruct2) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testMap(thing: { [k: number]: number; }, callback: (err: any, result: { [k: number]: number; }) => void): Q.IPromise<{ [k: number]: number; }> { callback(null, thing); return Q.resolve(); } testStringMap(thing: { [k: string]: string; }, callback: (err: any, result: { [k: string]: string; }) => void): Q.IPromise<{ [k: string]: string; }> { callback(null, thing); return Q.resolve(); } testSet(thing: number[], callback: (err: any, result: number[]) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testList(thing: number[], callback: (err: any, result: number[]) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testEnum(thing: ttypes.Numberz, callback: (err: any, result: ttypes.Numberz) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } testTypedef(thing: number, callback: (err: any, result: number) => void): Q.IPromise { callback(null, thing); return Q.resolve(); } } thrift-0.19.0/lib/nodets/test/int64.test.ts0000644000000000000000000000656114303740367020431 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import Int64 = require("node-int64"); import JSONInt64 = require('json-int64'); import i64types = require("./gen-nodejs/Int64Test_types"); import test = require("tape"); const cases = { "should correctly generate Int64 constants": function(assert) { const EXPECTED_SMALL_INT64_AS_NUMBER: number = 42; const EXPECTED_SMALL_INT64: Int64 = new Int64(42); const EXPECTED_MAX_JS_SAFE_INT64: Int64 = new Int64(Number.MAX_SAFE_INTEGER); const EXPECTED_MIN_JS_SAFE_INT64: Int64 = new Int64(Number.MIN_SAFE_INTEGER); const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64: Int64 = new Int64("0020000000000000"); // hex-encoded const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64: Int64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement const EXPECTED_MAX_SIGNED_INT64: Int64 = new Int64("7fffffffffffffff"); // hex-encoded const EXPECTED_MIN_SIGNED_INT64: Int64 = new Int64("8000000000000000"); // hex-encoded 2's complement const EXPECTED_INT64_LIST: Int64[] = [ EXPECTED_SMALL_INT64, EXPECTED_MAX_JS_SAFE_INT64, EXPECTED_MIN_JS_SAFE_INT64, EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, EXPECTED_MAX_SIGNED_INT64, EXPECTED_MIN_SIGNED_INT64 ]; assert.ok(EXPECTED_SMALL_INT64.equals(i64types.SMALL_INT64)); assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(i64types.MAX_JS_SAFE_INT64)); assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(i64types.MIN_JS_SAFE_INT64)); assert.ok( EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( i64types.MAX_JS_SAFE_PLUS_ONE_INT64 ) ); assert.ok( EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( i64types.MIN_JS_SAFE_MINUS_ONE_INT64 ) ); assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(i64types.MAX_SIGNED_INT64)); assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(i64types.MIN_SIGNED_INT64)); assert.equal( EXPECTED_SMALL_INT64_AS_NUMBER, i64types.SMALL_INT64.toNumber() ); assert.equal( Number.MAX_SAFE_INTEGER, i64types.MAX_JS_SAFE_INT64.toNumber() ); assert.equal( Number.MIN_SAFE_INTEGER, i64types.MIN_JS_SAFE_INT64.toNumber() ); for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); } for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i){ let int64Object = EXPECTED_INT64_LIST[i]; assert.ok(i64types.INT64_2_INT64_MAP[JSONInt64.toDecimalString(int64Object)].equals(int64Object)); } assert.end(); } }; Object.keys(cases).forEach(function(caseName) { test(caseName, cases[caseName]); }); thrift-0.19.0/lib/nodets/test/server.ts0000644000000000000000000000151314303740367020005 0ustar00rootroot00000000000000import thrift = require("thrift"); var program = require('commander'); import ThriftTest = require('./gen-nodejs/ThriftTest'); import test_handler = require('./test_handler'); program .option('--port ', 'Set thrift server port', 9090) .option('--promise', 'test with promise style functions') .option('--protocol', '"Set thrift protocol (binary) [protocol]"') .parse(process.argv); var port: number = program.port; var options: thrift.ServerOptions = { transport: thrift.TBufferedTransport, protocol: thrift.TBinaryProtocol }; var server: thrift.Server; if (program.promise) { server = thrift.createServer(ThriftTest.Processor, new test_handler.AsyncThriftTestHandler(), options); } else { server = thrift.createServer(ThriftTest.Processor, new test_handler.SyncThriftTestHandler(), options); } server.listen(port); thrift-0.19.0/lib/nodets/test/tsconfig.json0000644000000000000000000000112414303740367020634 0ustar00rootroot00000000000000{ "compilerOptions": { "allowJs": false, "alwaysStrict": true, "baseUrl": ".", "declaration": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "module": "commonjs", "moduleResolution": "node", "noImplicitThis": true, "noUnusedLocals": true, "preserveConstEnums": true, "removeComments": true, "strictFunctionTypes": true, "strictNullChecks": true, "target": "es6", "paths": { "thrift": ["../../nodejs/lib/thrift"] } } } thrift-0.19.0/lib/nodets/test/runServer.sh0000755000000000000000000000100514370300523020443 0ustar00rootroot00000000000000#! /bin/sh DIR="$( cd "$( dirname "$0" )" && pwd )" mkdir -p $DIR/../test-compiled COMPILEDDIR="$(cd $DIR && cd ../test-compiled && pwd)" export NODE_PATH="${DIR}:${DIR}/../../nodejs/lib:${NODE_PATH}" compile() { #generating thrift code ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/v0.16/ThriftTest.thrift ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/v0.16/ThriftTest.thrift } compile node ${COMPILEDDIR}/server.js $* thrift-0.19.0/lib/nodets/test/testAll.sh0000755000000000000000000000213514370300523020065 0ustar00rootroot00000000000000#! /bin/sh DIR="$( cd "$( dirname "$0" )" && pwd )" mkdir -p $DIR/../test-compiled COMPILEDDIR="$(cd $DIR && cd ../test-compiled && pwd)" export NODE_PATH="${DIR}:${DIR}/../../nodejs/lib:${NODE_PATH}" compile() { #generating thrift code ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/v0.16/ThriftTest.thrift ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/Int64Test.thrift ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/v0.16/ThriftTest.thrift ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/Int64Test.thrift tsc --outDir $COMPILEDDIR --project $DIR/tsconfig.json } compile testServer() { echo "start server $1" RET=0 node ${COMPILEDDIR}/server.js $1 & SERVERPID=$! sleep 1 echo "start client $1" node ${COMPILEDDIR}/client.js $1 || RET=1 kill -2 $SERVERPID || RET=1 return $RET } node ${COMPILEDDIR}/int64.test.js || TESTOK=1 #integration tests testServer || TESTOK=1 testServer --promise || TESTOK=1 exit $TESTOK thrift-0.19.0/lib/nodets/test/runClient.sh0000755000000000000000000000100314370300523020411 0ustar00rootroot00000000000000#! /bin/sh DIR="$( cd "$( dirname "$0" )" && pwd )" mkdir -p $DIR/../test-compiled COMPILEDDIR="$(cd $DIR && cd ../test-compiled && pwd)" export NODE_PATH="${DIR}:${DIR}/../../nodejs/lib:${NODE_PATH}" compile() { #generating thrift code ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/v0.16/ThriftTest.thrift ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/v0.16/ThriftTest.thrift } compile node ${COMPILEDDIR}/client.js $* thrift-0.19.0/lib/nodets/test/client.ts0000644000000000000000000000403014303740367017752 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import assert = require("assert"); import thrift = require("thrift"); import Thrift = thrift.Thrift; import ThriftTest = require("./gen-nodejs/ThriftTest"); import test_driver = require("./test_driver"); import ThriftTestDriver = test_driver.ThriftTestDriver; import ThriftTestDriverPromise = test_driver.ThriftTestDriverPromise; // var program = require("commander"); import * as program from "commander"; program .option("--port ", "Set thrift server port number to connect", 9090) .option("--promise", "test with promise style functions") .option("--protocol", "Set thrift protocol (binary) [protocol]") .parse(process.argv); var port: number = program.port; var promise = program.promise; var options = { transport: Thrift.TBufferedTransport, protocol: Thrift.TBinaryProtocol }; var testDriver = promise ? ThriftTestDriverPromise : ThriftTestDriver; var connection = thrift.createConnection("localhost", port, options); connection.on("error", function(err: string) { assert(false, err); }); var client = thrift.createClient(ThriftTest.Client, connection); runTests(); function runTests() { testDriver(client, function (status: string) { console.log(status); process.exit(0); }); } exports.expressoTest = function() {}; thrift-0.19.0/lib/nodets/test/test_driver.ts0000644000000000000000000002246314303740367021040 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * 'License'); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // This is the Node.js test driver for the standard Apache Thrift // test service. The driver invokes every function defined in the // Thrift Test service with a representative range of parameters. // // The ThriftTestDriver function requires a client object // connected to a server hosting the Thrift Test service and // supports an optional callback function which is called with // a status message when the test is complete. import test = require("tape"); import ttypes = require("./gen-nodejs/ThriftTest_types"); import ThriftTest = require("./gen-nodejs/ThriftTest"); import thrift = require("thrift"); import Q = thrift.Q; import TException = thrift.Thrift.TException; var Int64 = require("node-int64"); import testCases = require("./test-cases"); export function ThriftTestDriver(client: ThriftTest.Client, callback: (status: string) => void) { test("NodeJS Style Callback Client Tests", function(assert) { var checkRecursively = makeRecursiveCheck(assert); function makeAsserter(assertionFn: (a: any, b: any, msg?: string) => void) { return function(c: (string | any)[]) { var fnName = c[0]; var expected = c[1]; (client)[fnName](expected, function(err: any, actual: any) { assert.error(err, fnName + ": no callback error"); assertionFn(actual, expected, fnName); }) }; } testCases.simple.forEach(makeAsserter(assert.equal)); testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){ assert.ok(a == e, m); })); testCases.deep.forEach(makeAsserter(assert.deepEqual)); client.testMapMap(42, function(err, response) { var expected: typeof response = { "4": {"1":1, "2":2, "3":3, "4":4}, "-4": {"-4":-4, "-3":-3, "-2":-2, "-1":-1} }; assert.error(err, 'testMapMap: no callback error'); assert.deepEqual(expected, response, "testMapMap"); }); client.testStruct(testCases.out, function(err, response) { assert.error(err, "testStruct: no callback error"); checkRecursively(testCases.out, response, "testStruct"); }); client.testNest(testCases.out2, function(err, response) { assert.error(err, "testNest: no callback error"); checkRecursively(testCases.out2, response, "testNest"); }); client.testInsanity(testCases.crazy, function(err, response) { assert.error(err, "testInsanity: no callback error"); checkRecursively(testCases.insanity, response, "testInsanity"); }); client.testException("TException", function(err, response) { assert.ok(err instanceof TException, 'testException: correct error type'); assert.ok(!Boolean(response), 'testException: no response'); }); client.testException("Xception", function(err, response) { assert.ok(err instanceof ttypes.Xception, 'testException: correct error type'); assert.ok(!Boolean(response), 'testException: no response'); assert.equal(err.errorCode, 1001, 'testException: correct error code'); assert.equal('Xception', err.message, 'testException: correct error message'); }); client.testException("no Exception", function(err, response) { assert.error(err, 'testException: no callback error'); assert.ok(!Boolean(response), 'testException: no response'); }); client.testOneway(0, function(err, response) { assert.error(err, 'testOneway: no callback error'); assert.strictEqual(response, undefined, 'testOneway: void response'); }); checkOffByOne(function(done) { client.testI32(-1, function(err, response) { assert.error(err, "checkOffByOne: no callback error"); assert.equal(-1, response); assert.end(); done(); }); }, callback); }); }; export function ThriftTestDriverPromise(client: ThriftTest.Client, callback: (status: string) => void) { test("Q Promise Client Tests", function(assert) { var checkRecursively = makeRecursiveCheck(assert); function fail(msg: string) { return function(error, response) { if (error !== null) { assert.fail(msg); } } } function makeAsserter(assertionFn: (a: any, b: any, msg?: string) => void) { return function(c: (string | any)[]) { var fnName = c[0]; var expected = c[1]; (client)[fnName](expected) .then(function(actual: any) { assertionFn(actual, expected, fnName); }) .fail(fail("fnName")); }; } testCases.simple.forEach(makeAsserter(assert.equal)); testCases.simpleLoose.forEach(makeAsserter(function(a, e, m){ assert.ok(a == e, m); })); testCases.deep.forEach(makeAsserter(assert.deepEqual)); Q.resolve(client.testStruct(testCases.out)) .then(function(response) { checkRecursively(testCases.out, response, "testStruct"); }) .fail(fail("testStruct")); Q.resolve(client.testNest(testCases.out2)) .then(function(response) { checkRecursively(testCases.out2, response, "testNest"); }) .fail(fail("testNest")); Q.resolve(client.testInsanity(testCases.crazy)) .then(function(response) { checkRecursively(testCases.insanity, response, "testInsanity"); }) .fail(fail("testInsanity")); Q.resolve(client.testException("TException")) .then(function(response) { fail("testException: TException"); }) .fail(function(err) { assert.ok(err instanceof TException); }); Q.resolve(client.testException("Xception")) .then(function(response) { fail("testException: Xception"); }) .fail(function(err) { assert.ok(err instanceof ttypes.Xception); assert.equal(err.errorCode, 1001); assert.equal("Xception", err.message); }); Q.resolve(client.testException("no Exception")) .then(function(response) { assert.equal(undefined, response); //void }) .fail(fail("testException")); client.testOneway(0, fail("testOneway: should not answer")); checkOffByOne(function(done) { Q.resolve(client.testI32(-1)) .then(function(response) { assert.equal(-1, response); assert.end(); done(); }) .fail(fail("checkOffByOne")); }, callback); }); }; // Helper Functions // ========================================================= function makeRecursiveCheck(assert: test.Test) { return function (map1: any, map2: any, msg: string) { var equal = true; var equal = checkRecursively(map1, map2); assert.ok(equal, msg); // deepEqual doesn't work with fields using node-int64 function checkRecursively(map1: any, map2: any) : boolean { if (!(typeof map1 !== "function" && typeof map2 !== "function")) { return false; } if (!map1 || typeof map1 !== "object") { //Handle int64 types (which use node-int64 in Node.js JavaScript) if ((typeof map1 === "number") && (typeof map2 === "object") && (map2.buffer) && (map2.buffer instanceof Buffer) && (map2.buffer.length === 8)) { var n = new Int64(map2.buffer); return map1 === n.toNumber(); } else { return map1 == map2; } } else { return Object.keys(map1).every(function(key) { return checkRecursively(map1[key], map2[key]); }); } } } } function checkOffByOne(done: (callback: () => void) => void, callback: (message: string) => void) { var retry_limit = 30; var retry_interval = 100; var test_complete = false; var retrys = 0; /** * redo a simple test after the oneway to make sure we aren't "off by one" -- * if the server treated oneway void like normal void, this next test will * fail since it will get the void confirmation rather than the correct * result. In this circumstance, the client will throw the exception: * * Because this is the last test against the server, when it completes * the entire suite is complete by definition (the tests run serially). */ done(function() { test_complete = true; }); //We wait up to retry_limit * retry_interval for the test suite to complete function TestForCompletion() { if(test_complete && callback) { callback("Server successfully tested!"); } else { if (++retrys < retry_limit) { setTimeout(TestForCompletion, retry_interval); } else if (callback) { callback("Server test failed to complete after " + (retry_limit * retry_interval / 1000) + " seconds"); } } } setTimeout(TestForCompletion, retry_interval); } thrift-0.19.0/lib/nodets/Makefile.in0000644000000000000000000004410114472652516017222 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # We call npm twice to work around npm issues VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/nodets ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ test \ coding_standards.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/nodets/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/nodets/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am distclean \ distclean-generic distclean-libtool distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile stubs: $(top_srcdir)/test/v0.16/ThriftTest.thrift mkdir -p test-compiled $(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/v0.16/ThriftTest.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/Int64Test.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/Int64Test.thrift ts-compile: stubs mkdir -p test-compiled ../../node_modules/typescript/bin/tsc --outDir test-compiled/ --project test/tsconfig.json deps: $(top_srcdir)/package.json $(NPM) install $(top_srcdir)/ || $(NPM) install $(top_srcdir)/ all-local: deps ts-compile precross: deps stubs ts-compile check: deps ts-compile cd $(top_srcdir) && $(NPM) run test-ts && cd lib/nodets clean-local: $(RM) -r test/gen-nodejs $(RM) -r $(top_srcdir)/node_modules $(RM) -r test-compiled # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/netstd/0000755000000000000000000000000014472652663015165 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Benchmarks/0000755000000000000000000000000014472652662017241 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Benchmarks/Thrift.Benchmarks/0000777000000000000000000000000014452237057022554 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj0000644000000000000000000000266014452237057027312 0ustar00rootroot00000000000000 Exe net7.0 false true enable thrift-0.19.0/lib/netstd/Benchmarks/Thrift.Benchmarks/Program.cs0000644000000000000000000000177414303740367024515 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using BenchmarkDotNet.Running; namespace Thrift.Benchmarks { internal static class Program { public static void Main(string[] args) { BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); } } } thrift-0.19.0/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs0000644000000000000000000000470414303740367030210 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.IO; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Thrift.Protocol; using Thrift.Transport.Client; namespace Thrift.Benchmarks { [MemoryDiagnoser] public class CompactProtocolBenchmarks { private MemoryStream? _Stream; private TProtocol? _Protocol; [Params(10000)] public int NumberOfOperationsPerIteration { get; set; } [GlobalSetup] public void GlobalSetup() { _Stream = new MemoryStream(); var transport = new TStreamTransport(_Stream, _Stream, null); _Protocol = new TCompactProtocol(transport); } [GlobalCleanup] public void GlobalCleanup() { _Protocol?.Dispose(); } [Benchmark] public async Task WriteString() { if ((_Protocol is null) || (_Stream is null)) throw new System.Exception("unexpected internal state"); for (int i = 0; i < NumberOfOperationsPerIteration; i++) { await _Protocol.WriteStringAsync("Thrift String Benchmark"); _Stream.Seek(0, SeekOrigin.Begin); } } [Benchmark] public async Task ReadString() { if ((_Protocol is null) || (_Stream is null)) throw new System.Exception("unexpected internal state"); await _Protocol.WriteStringAsync("Thrift String Benchmark"); for (int i = 0; i < NumberOfOperationsPerIteration; i++) { _Stream.Seek(0, SeekOrigin.Begin); await _Protocol.ReadStringAsync(); } } } } thrift-0.19.0/lib/netstd/Makefile.am0000644000000000000000000000512214303740367017211 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # SUBDIRS = . all-local: $(DOTNETCORE) build -c Release check-local: $(DOTNETCORE) test Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj $(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj clean-local: $(RM) -r Thrift/bin $(RM) -r Thrift/obj $(RM) -r Benchmarks/Thrift.Benchmarks/bin $(RM) -r Benchmarks/Thrift.Benchmarks/obj $(RM) -r Tests/Thrift.Tests/bin $(RM) -r Tests/Thrift.Tests/obj $(RM) -r Tests/Thrift.IntegrationTests/bin $(RM) -r Tests/Thrift.IntegrationTests/obj $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj EXTRA_DIST = \ README.md \ Directory.Build.props \ Benchmarks/Thrift.Benchmarks \ Tests/Thrift.IntegrationTests/Protocols \ Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj \ Tests/Thrift.PublicInterfaces.Compile.Tests \ Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift \ Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift \ Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \ Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \ Tests/Thrift.Tests/Collections \ Tests/Thrift.Tests/DataModel \ Tests/Thrift.Tests/Protocols \ Tests/Thrift.Tests/Transports \ Tests/Thrift.Tests/Thrift.Tests.csproj \ Thrift/.editorconfig \ Thrift/Collections \ Thrift/Processor \ Thrift/Properties \ Thrift/Protocol \ Thrift/Server \ Thrift/GlobalSuppressions.cs \ Thrift/TApplicationException.cs \ Thrift/TBaseClient.cs \ Thrift/TConfiguration.cs \ Thrift/TException.cs \ Thrift/Thrift.csproj \ Thrift/Transport \ Thrift/*.snk \ Thrift.sln \ build.cmd \ build.sh \ runtests.cmd \ runtests.sh thrift-0.19.0/lib/netstd/Thrift/0000755000000000000000000000000014472652663016425 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/thrift.snk0000644000000000000000000000112414303740367020430 0ustar00rootroot00000000000000$RSA2ÑhŸ‚A¬nÀ,Ïó.ÓÚ RÕ}…¥aÒ¼bÜ ö®|ceØã5ÿÎ+ª9ÝÉàì\åòØòê_zY¹5€T$€±äö'°¬f{ÁGÞëF­ißä­ìPÎfÈ×_¦ue0JÑ,ÔˆW¹‰D¸.9Ââ°“ÌWÁQ¥à¬Ã8†œ€\Wªãj eb"ê2¦Ü¢8M`8¥eçÞM [oJ8ô¨ÆˆQC¯ÛGDK¢Ë&À Çkbƒ€©è|³-ß)£¾Gßßbÿ>¦Ùh0â®ÃPl>É€ÐD‚MqS‰YÅU8„ÒFÍ­#ûÿžÄHÝ@j(¤à7ɨîÿS©ö†`8XýÏ{´Fk3àlÇsÂíÛJM¾ö™ ×Ú÷ÌpÌ~pã5KØK®',Ÿ©K+îB%C6Šëˆ‚Ë+_)>5>ˆqfsGò@æZ_±"Èòk1Á8#žw Z#¹í!îµÑðìNü@³;`³öW}Ùy·iC‚Ç“;W‡Á“³D$;Þäˆ(š8Ëô~ÅcžÕÊB×Ó¥Å=@çhR°н¸*¯Qnñ73øB¶=¢W%˜5Œ_åÏ˜Ű·Á ßP¤ ­[‚Èê¡Xæ·ü×Ì-Q¿¨k$oð0Îw_ŸVlÇ$2Œ^mCqU›äxà\ËL»é¥|› ´/ì+ãó¬T)ªÙÚƒàGŽ—I˲íßµ‡Ã’×#»"dthrift-0.19.0/lib/netstd/Thrift/TBaseClient.cs0000644000000000000000000000553314303740367021107 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol; namespace Thrift { // ReSharper disable once InconsistentNaming /// /// TBaseClient. /// Base client for generated clients. /// Do not change this class without checking generated code (namings, etc.) /// public abstract class TBaseClient { private readonly TProtocol _inputProtocol; private readonly TProtocol _outputProtocol; private bool _isDisposed; private int _seqId; public readonly Guid ClientId = Guid.NewGuid(); protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol) { _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol)); _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol)); } public TProtocol InputProtocol => _inputProtocol; public TProtocol OutputProtocol => _outputProtocol; public int SeqId { get { return ++_seqId; } } public virtual async Task OpenTransportAsync() { await OpenTransportAsync(CancellationToken.None); } public virtual async Task OpenTransportAsync(CancellationToken cancellationToken) { if (!_inputProtocol.Transport.IsOpen) { await _inputProtocol.Transport.OpenAsync(cancellationToken); } if (!_outputProtocol.Transport.IsOpen) { await _outputProtocol.Transport.OpenAsync(cancellationToken); } } public void Dispose() { Dispose(true); } protected virtual void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { _inputProtocol?.Dispose(); _outputProtocol?.Dispose(); } } _isDisposed = true; } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/0000777000000000000000000000000014370300523020210 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Protocol/TJSONProtocol.cs0000644000000000000000000011712214370300523023156 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; using Thrift.Protocol.Utilities; using Thrift.Transport; namespace Thrift.Protocol { /// /// JSON protocol implementation for thrift. /// This is a full-featured protocol supporting Write and Read. /// Please see the C++ class header for a detailed description of the /// protocol's wire format. /// Adapted from the Java version. /// // ReSharper disable once InconsistentNaming public class TJsonProtocol : TProtocol { private const long Version = 1; // Temporary buffer used by several methods private readonly byte[] _tempBuffer = new byte[4]; // Current context that we are in protected JSONBaseContext Context; // Stack of nested contexts that we may be in protected Stack ContextStack = new Stack(); // Reader that manages a 1-byte buffer protected LookaheadReader Reader; // Default encoding protected Encoding Utf8Encoding = Encoding.UTF8; /// /// TJsonProtocol Constructor /// public TJsonProtocol(TTransport trans) : base(trans) { Context = new JSONBaseContext(this); Reader = new LookaheadReader(this); } /// /// Push a new JSON context onto the stack. /// protected void PushContext(JSONBaseContext c) { ContextStack.Push(Context); Context = c; } /// /// Pop the last JSON context off the stack /// protected void PopContext() { Context = ContextStack.Pop(); } /// /// Resets the context stack to pristine state. Allows for reusal of the protocol /// even in cases where the protocol instance was in an undefined state due to /// dangling/stale/obsolete contexts /// private void ResetContext() { ContextStack.Clear(); Context = new JSONBaseContext(this); } /// /// Read a byte that must match b[0]; otherwise an exception is thrown. /// Marked protected to avoid synthetic accessor in JSONListContext.Read /// and JSONPairContext.Read /// protected async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken) { var ch = await Reader.ReadAsync(cancellationToken); if (ch != bytes[0]) { throw new TProtocolException(TProtocolException.INVALID_DATA, $"Unexpected character: {(char) ch}"); } } /// /// Write the bytes in array buf as a JSON characters, escaping as needed /// private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken) { await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); var len = bytes.Length; for (var i = 0; i < len; i++) { if ((bytes[i] & 0x00FF) >= 0x30) { if (bytes[i] == TJSONProtocolConstants.Backslash[0]) { await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); } else { await Trans.WriteAsync(bytes, i, 1, cancellationToken); } } else { _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]]; if (_tempBuffer[0] == 1) { await Trans.WriteAsync(bytes, i, 1, cancellationToken); } else if (_tempBuffer[0] > 1) { await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken); } else { await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken); _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4)); _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]); await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken); } } } await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); } /// /// Write out number as a JSON value. If the context dictates so, it will be /// wrapped in quotes to output as a JSON string. /// private async Task WriteJsonIntegerAsync(long num, CancellationToken cancellationToken) { await Context.WriteConditionalDelimiterAsync(cancellationToken); var str = num.ToString(); var escapeNum = Context.EscapeNumbers(); if (escapeNum) { await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); } var bytes = Utf8Encoding.GetBytes(str); await Trans.WriteAsync(bytes, cancellationToken); if (escapeNum) { await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); } } /// /// Write out a double as a JSON value. If it is NaN or infinity or if the /// context dictates escaping, Write out as JSON string. /// private async Task WriteJsonDoubleAsync(double num, CancellationToken cancellationToken) { await Context.WriteConditionalDelimiterAsync(cancellationToken); var str = num.ToString("G17", CultureInfo.InvariantCulture); var special = false; switch (str[0]) { case 'N': // NaN case 'I': // Infinity special = true; break; case '-': if (str[1] == 'I') { // -Infinity special = true; } break; } var escapeNum = special || Context.EscapeNumbers(); if (escapeNum) { await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); } await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken); if (escapeNum) { await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); } } /// /// Write out contents of byte array b as a JSON string with base-64 encoded /// data /// private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken) { await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); var len = bytes.Length; var off = 0; while (len >= 3) { // Encode 3 bytes at a time TBase64Utils.Encode(bytes, off, 3, _tempBuffer, 0); await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken); off += 3; len -= 3; } if (len > 0) { // Encode remainder TBase64Utils.Encode(bytes, off, len, _tempBuffer, 0); await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken); } await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); } private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken) { await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); PushContext(new JSONPairContext(this)); } private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken) { PopContext(); await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken); } private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken) { await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); PushContext(new JSONListContext(this)); } private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken) { PopContext(); await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken); } public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { ResetContext(); await WriteJsonArrayStartAsync(cancellationToken); await WriteJsonIntegerAsync(Version, cancellationToken); var b = Utf8Encoding.GetBytes(message.Name); await WriteJsonStringAsync(b, cancellationToken); await WriteJsonIntegerAsync((long) message.Type, cancellationToken); await WriteJsonIntegerAsync(message.SeqID, cancellationToken); } public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) { await WriteJsonArrayEndAsync(cancellationToken); } public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) { await WriteJsonObjectStartAsync(cancellationToken); } public override async Task WriteStructEndAsync(CancellationToken cancellationToken) { await WriteJsonObjectEndAsync(cancellationToken); } public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) { await WriteJsonIntegerAsync(field.ID, cancellationToken); await WriteJsonObjectStartAsync(cancellationToken); await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken); } public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) { await WriteJsonObjectEndAsync(cancellationToken); } public override Task WriteFieldStopAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) { await WriteJsonArrayStartAsync(cancellationToken); await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken); await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken); await WriteJsonIntegerAsync(map.Count, cancellationToken); await WriteJsonObjectStartAsync(cancellationToken); } public override async Task WriteMapEndAsync(CancellationToken cancellationToken) { await WriteJsonObjectEndAsync(cancellationToken); await WriteJsonArrayEndAsync(cancellationToken); } public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) { await WriteJsonArrayStartAsync(cancellationToken); await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken); await WriteJsonIntegerAsync(list.Count, cancellationToken); } public override async Task WriteListEndAsync(CancellationToken cancellationToken) { await WriteJsonArrayEndAsync(cancellationToken); } public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) { await WriteJsonArrayStartAsync(cancellationToken); await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken); await WriteJsonIntegerAsync(set.Count, cancellationToken); } public override async Task WriteSetEndAsync(CancellationToken cancellationToken) { await WriteJsonArrayEndAsync(cancellationToken); } public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) { await WriteJsonIntegerAsync(b ? 1 : 0, cancellationToken); } public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { await WriteJsonIntegerAsync(b, cancellationToken); } public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { await WriteJsonIntegerAsync(i16, cancellationToken); } public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) { await WriteJsonIntegerAsync(i32, cancellationToken); } public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { await WriteJsonIntegerAsync(i64, cancellationToken); } public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) { await WriteJsonDoubleAsync(d, cancellationToken); } public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) { var b = Utf8Encoding.GetBytes(s); await WriteJsonStringAsync(b, cancellationToken); } public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { await WriteJsonBase64Async(bytes, cancellationToken); } public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken = default) { await WriteStringAsync(uuid.ToString("D"), cancellationToken); // no curly braces } /// /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the /// context if skipContext is true. /// private async ValueTask ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) { using (var buffer = new MemoryStream()) { var codeunits = new List(); if (!skipContext) { await Context.ReadConditionalDelimiterAsync(cancellationToken); } await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); while (true) { var ch = await Reader.ReadAsync(cancellationToken); if (ch == TJSONProtocolConstants.Quote[0]) { break; } // escaped? if (ch != TJSONProtocolConstants.EscSequences[0]) { #if NETSTANDARD2_0 await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken); #else var wbuf = new[] { ch }; await buffer.WriteAsync(wbuf.AsMemory(0, 1), cancellationToken); #endif continue; } // distinguish between \uXXXX and \? ch = await Reader.ReadAsync(cancellationToken); if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n { var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch); if (off == -1) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); } ch = TJSONProtocolConstants.EscapeCharValues[off]; #if NETSTANDARD2_0 await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken); #else var wbuf = new[] { ch }; await buffer.WriteAsync( wbuf.AsMemory(0, 1), cancellationToken); #endif continue; } // it's \uXXXX await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken); var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) + (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) + (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) + TJSONProtocolHelper.ToHexVal(_tempBuffer[3])); if (char.IsHighSurrogate((char) wch)) { if (codeunits.Count > 0) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); } codeunits.Add((char) wch); } else if (char.IsLowSurrogate((char) wch)) { if (codeunits.Count == 0) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected high surrogate char"); } codeunits.Add((char) wch); var tmp = Utf8Encoding.GetBytes(codeunits.ToArray()); #if NETSTANDARD2_0 await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); #else await buffer.WriteAsync(tmp.AsMemory(0, tmp.Length), cancellationToken); #endif codeunits.Clear(); } else { var tmp = Utf8Encoding.GetBytes(new[] { (char)wch }); #if NETSTANDARD2_0 await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); #else await buffer.WriteAsync(tmp.AsMemory( 0, tmp.Length), cancellationToken); #endif } } if (codeunits.Count > 0) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); } return buffer.ToArray(); } } /// /// Read in a sequence of characters that are all valid in JSON numbers. Does /// not do a complete regex check to validate that this is actually a number. /// private async ValueTask ReadJsonNumericCharsAsync(CancellationToken cancellationToken) { var strbld = new StringBuilder(); while (true) { //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions try { var ch = await Reader.PeekAsync(cancellationToken); if (!TJSONProtocolHelper.IsJsonNumeric(ch)) { break; } var c = (char)await Reader.ReadAsync(cancellationToken); strbld.Append(c); } catch (TTransportException) { break; } } return strbld.ToString(); } /// /// Read in a JSON number. If the context dictates, Read in enclosing quotes. /// private async ValueTask ReadJsonIntegerAsync(CancellationToken cancellationToken) { await Context.ReadConditionalDelimiterAsync(cancellationToken); if (Context.EscapeNumbers()) { await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); } var str = await ReadJsonNumericCharsAsync(cancellationToken); if (Context.EscapeNumbers()) { await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); } try { return long.Parse(str); } catch (FormatException) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); } } /// /// Read in a JSON double value. Throw if the value is not wrapped in quotes /// when expected or if wrapped in quotes when not expected. /// private async ValueTask ReadJsonDoubleAsync(CancellationToken cancellationToken) { await Context.ReadConditionalDelimiterAsync(cancellationToken); if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) { var arr = await ReadJsonStringAsync(true, cancellationToken); var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); if (!Context.EscapeNumbers() && !double.IsNaN(dub) && !double.IsInfinity(dub)) { // Throw exception -- we should not be in a string in this case throw new TProtocolException(TProtocolException.INVALID_DATA, "Numeric data unexpectedly quoted"); } return dub; } if (Context.EscapeNumbers()) { // This will throw - we should have had a quote if escapeNum == true await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); } try { return double.Parse(await ReadJsonNumericCharsAsync(cancellationToken), CultureInfo.InvariantCulture); } catch (FormatException) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Bad data encounted in numeric data"); } } /// /// Read in a JSON string containing base-64 encoded data and decode it. /// private async ValueTask ReadJsonBase64Async(CancellationToken cancellationToken) { var b = await ReadJsonStringAsync(false, cancellationToken); var len = b.Length; var off = 0; var size = 0; // reduce len to ignore fill bytes while ((len > 0) && (b[len - 1] == '=')) { --len; } // read & decode full byte triplets = 4 source bytes while (len > 4) { // Decode 4 bytes at a time TBase64Utils.Decode(b, off, 4, b, size); // NB: decoded in place off += 4; len -= 4; size += 3; } // Don't decode if we hit the end or got a single leftover byte (invalid // base64 but legal for skip of regular string exType) if (len > 1) { // Decode remainder TBase64Utils.Decode(b, off, len, b, size); // NB: decoded in place size += len - 1; } // Sadly we must copy the byte[] (any way around this?) var result = new byte[size]; Array.Copy(b, 0, result, 0, size); return result; } private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken) { await Context.ReadConditionalDelimiterAsync(cancellationToken); await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); PushContext(new JSONPairContext(this)); } private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken) { await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken); PopContext(); } private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken) { await Context.ReadConditionalDelimiterAsync(cancellationToken); await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); PushContext(new JSONListContext(this)); } private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) { await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken); PopContext(); } public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { var message = new TMessage(); ResetContext(); await ReadJsonArrayStartAsync(cancellationToken); if (await ReadJsonIntegerAsync(cancellationToken) != Version) { throw new TProtocolException(TProtocolException.BAD_VERSION, "Message contained bad version."); } var buf = await ReadJsonStringAsync(false, cancellationToken); message.Name = Utf8Encoding.GetString(buf, 0, buf.Length); message.Type = (TMessageType) await ReadJsonIntegerAsync(cancellationToken); message.SeqID = (int) await ReadJsonIntegerAsync(cancellationToken); return message; } public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await ReadJsonArrayEndAsync(cancellationToken); Transport.ResetConsumedMessageSize(); } public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { await ReadJsonObjectStartAsync(cancellationToken); return AnonymousStruct; } public override async Task ReadStructEndAsync(CancellationToken cancellationToken) { await ReadJsonObjectEndAsync(cancellationToken); } public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { var ch = await Reader.PeekAsync(cancellationToken); if (ch == TJSONProtocolConstants.RightBrace[0]) { return StopField; } var field = new TField() { ID = (short)await ReadJsonIntegerAsync(cancellationToken) }; await ReadJsonObjectStartAsync(cancellationToken); field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); return field; } public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) { await ReadJsonObjectEndAsync(cancellationToken); } public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { var map = new TMap(); await ReadJsonArrayStartAsync(cancellationToken); map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); map.Count = (int) await ReadJsonIntegerAsync(cancellationToken); CheckReadBytesAvailable(map); await ReadJsonObjectStartAsync(cancellationToken); return map; } public override async Task ReadMapEndAsync(CancellationToken cancellationToken) { await ReadJsonObjectEndAsync(cancellationToken); await ReadJsonArrayEndAsync(cancellationToken); } public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { var list = new TList(); await ReadJsonArrayStartAsync(cancellationToken); list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); list.Count = (int) await ReadJsonIntegerAsync(cancellationToken); CheckReadBytesAvailable(list); return list; } public override async Task ReadListEndAsync(CancellationToken cancellationToken) { await ReadJsonArrayEndAsync(cancellationToken); } public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { var set = new TSet(); await ReadJsonArrayStartAsync(cancellationToken); set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); set.Count = (int) await ReadJsonIntegerAsync(cancellationToken); CheckReadBytesAvailable(set); return set; } public override async Task ReadSetEndAsync(CancellationToken cancellationToken) { await ReadJsonArrayEndAsync(cancellationToken); } public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { return await ReadJsonIntegerAsync(cancellationToken) != 0; } public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { return (sbyte) await ReadJsonIntegerAsync(cancellationToken); } public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { return (short) await ReadJsonIntegerAsync(cancellationToken); } public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { return (int) await ReadJsonIntegerAsync(cancellationToken); } public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { return await ReadJsonIntegerAsync(cancellationToken); } public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { return await ReadJsonDoubleAsync(cancellationToken); } public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { var buf = await ReadJsonStringAsync(false, cancellationToken); return Utf8Encoding.GetString(buf, 0, buf.Length); } public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { return await ReadJsonBase64Async(cancellationToken); } public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken = default) { return new Guid( await ReadStringAsync(cancellationToken)); } // Return the minimum number of bytes a type will consume on the wire public override int GetMinSerializedSize(TType type) { switch (type) { case TType.Stop: return 0; case TType.Void: return 0; case TType.Bool: return 1; // written as int case TType.Byte: return 1; case TType.Double: return 1; case TType.I16: return 1; case TType.I32: return 1; case TType.I64: return 1; case TType.String: return 2; // empty string case TType.Struct: return 2; // empty struct case TType.Map: return 2; // empty map case TType.Set: return 2; // empty set case TType.List: return 2; // empty list case TType.Uuid: return 36; // "E236974D-F0B0-4E05-8F29-0B455D41B1A1" default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code"); } } /// /// Factory for JSON protocol objects /// public class Factory : TProtocolFactory { public override TProtocol GetProtocol(TTransport trans) { return new TJsonProtocol(trans); } } /// /// Base class for tracking JSON contexts that may require /// inserting/Reading additional JSON syntax characters /// This base context does nothing. /// protected class JSONBaseContext { protected TJsonProtocol Proto; public JSONBaseContext(TJsonProtocol proto) { Proto = proto; } public virtual Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public virtual Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public virtual bool EscapeNumbers() { return false; } } /// /// Context for JSON lists. Will insert/Read commas before each item except /// for the first one /// protected class JSONListContext : JSONBaseContext { private bool _first = true; public JSONListContext(TJsonProtocol protocol) : base(protocol) { } public override async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { _first = false; } else { await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken); } } public override async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { _first = false; } else { await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken); } } } /// /// Context for JSON records. Will insert/Read colons before the value portion /// of each record pair, and commas before each key except the first. In /// addition, will indicate that numbers in the key position need to be /// escaped in quotes (since JSON keys must be strings). /// // ReSharper disable once InconsistentNaming protected class JSONPairContext : JSONBaseContext { private bool _colon = true; private bool _first = true; public JSONPairContext(TJsonProtocol proto) : base(proto) { } public override async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { _first = false; _colon = true; } else { await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); _colon = !_colon; } } public override async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { _first = false; _colon = true; } else { await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); _colon = !_colon; } } public override bool EscapeNumbers() { return _colon; } } /// /// Holds up to one byte from the transport /// protected class LookaheadReader { private readonly byte[] _data = new byte[1]; private bool _hasData; protected TJsonProtocol Proto; public LookaheadReader(TJsonProtocol proto) { Proto = proto; } /// /// Return and consume the next byte to be Read, either taking it from the /// data buffer if present or getting it from the transport otherwise. /// public async ValueTask ReadAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_hasData) { _hasData = false; } else { // find more easy way to avoid exception on reading primitive types await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); } return _data[0]; } /// /// Return the next byte to be Read without consuming, filling the data /// buffer if it has not been filled alReady. /// public async ValueTask PeekAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (!_hasData) { // find more easy way to avoid exception on reading primitive types await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); _hasData = true; } return _data[0]; } } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/0000777000000000000000000000000014370300523021774 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TMessage.cs0000644000000000000000000000244214303740367024043 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public struct TMessage { public TMessage(string name, TMessageType type, int seqid) { Name = name; Type = type; SeqID = seqid; } public string Name { get; set; } public TMessageType Type { get; set; } // ReSharper disable once InconsistentNaming - do not rename - it used for generation public int SeqID { get; set; } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TField.cs0000644000000000000000000000241014303740367023475 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public struct TField { public TField(string name, TType type, short id) { Name = name; Type = type; ID = id; } public string Name { get; set; } public TType Type { get; set; } // ReSharper disable once InconsistentNaming - do not rename - it used for generation public short ID { get; set; } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TType.cs0000644000000000000000000000224314370300523023365 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public enum TType : byte { Stop = 0, Void = 1, Bool = 2, Byte = 3, Double = 4, I16 = 6, I32 = 8, I64 = 10, String = 11, Struct = 12, Map = 13, Set = 14, List = 15, Uuid = 16 } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TMessageType.cs0000644000000000000000000000175614303740367024714 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public enum TMessageType { Call = 1, Reply = 2, Exception = 3, Oneway = 4 } }thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TStruct.cs0000644000000000000000000000203514303740367023741 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public readonly struct TStruct { public TStruct(string name) { Name = name; } public string Name { get; } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TList.cs0000644000000000000000000000217314303740367023373 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public struct TList { public TList(TType elementType, int count) { ElementType = elementType; Count = count; } public TType ElementType { get; set; } public int Count { get; set; } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TSet.cs0000644000000000000000000000233714303740367023215 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public struct TSet { public TSet(TType elementType, int count) { ElementType = elementType; Count = count; } public TSet(TList list) : this(list.ElementType, list.Count) { } public TType ElementType { get; set; } public int Count { get; set; } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/Entities/TMap.cs0000644000000000000000000000231314303740367023171 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming public struct TMap { public TMap(TType keyType, TType valueType, int count) { KeyType = keyType; ValueType = valueType; Count = count; } public TType KeyType { get; set; } public TType ValueType { get; set; } public int Count { get; set; } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs0000644000000000000000000004444214370300523023635 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Buffers.Binary; using System.Text; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; using Thrift.Protocol.Utilities; using Thrift.Transport; namespace Thrift.Protocol { // ReSharper disable once InconsistentNaming public class TBinaryProtocol : TProtocol { protected const uint VersionMask = 0xffff0000; protected const uint Version1 = 0x80010000; protected bool StrictRead; protected bool StrictWrite; // minimize memory allocations by means of an preallocated bytes buffer // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) private readonly byte[] PreAllocatedBuffer = new byte[128]; public TBinaryProtocol(TTransport trans) : this(trans, false, true) { } public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) : base(trans) { StrictRead = strictRead; StrictWrite = strictWrite; } public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (StrictWrite) { var version = Version1 | (uint) message.Type; await WriteI32Async((int) version, cancellationToken); await WriteStringAsync(message.Name, cancellationToken); await WriteI32Async(message.SeqID, cancellationToken); } else { await WriteStringAsync(message.Name, cancellationToken); await WriteByteAsync((sbyte) message.Type, cancellationToken); await WriteI32Async(message.SeqID, cancellationToken); } } public override Task WriteMessageEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override Task WriteStructEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) field.Type, cancellationToken); await WriteI16Async(field.ID, cancellationToken); } public override Task WriteFieldEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) TType.Stop, cancellationToken); } public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = (byte)map.KeyType; PreAllocatedBuffer[1] = (byte)map.ValueType; await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); await WriteI32Async(map.Count, cancellationToken); } public override Task WriteMapEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) list.ElementType, cancellationToken); await WriteI32Async(list.Count, cancellationToken); } public override Task WriteListEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) set.ElementType, cancellationToken); await WriteI32Async(set.Count, cancellationToken); } public override Task WriteSetEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken); } public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = (byte)b; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); BinaryPrimitives.WriteInt16BigEndian(PreAllocatedBuffer, i16); await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); } public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); BinaryPrimitives.WriteInt32BigEndian(PreAllocatedBuffer, i32); await Trans.WriteAsync(PreAllocatedBuffer, 0, 4, cancellationToken); } public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); BinaryPrimitives.WriteInt64BigEndian(PreAllocatedBuffer, i64); await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken); } public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteI32Async(bytes.Length, cancellationToken); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var bytes = uuid.SwapByteOrder().ToByteArray(); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var message = new TMessage(); var size = await ReadI32Async(cancellationToken); if (size < 0) { var version = (uint) size & VersionMask; if (version != Version1) { throw new TProtocolException(TProtocolException.BAD_VERSION, $"Bad version in ReadMessageBegin: {version}"); } message.Type = (TMessageType) (size & 0x000000ff); message.Name = await ReadStringAsync(cancellationToken); message.SeqID = await ReadI32Async(cancellationToken); } else { if (StrictRead) { throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in ReadMessageBegin, old client?"); } message.Name = (size > 0) ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; message.Type = (TMessageType) await ReadByteAsync(cancellationToken); message.SeqID = await ReadI32Async(cancellationToken); } return message; } public override Task ReadMessageEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Transport.ResetConsumedMessageSize(); return Task.CompletedTask; } public override ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return new ValueTask(AnonymousStruct); } public override Task ReadStructEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var type = (TType)await ReadByteAsync(cancellationToken); if (type == TType.Stop) { return StopField; } return new TField { Type = type, ID = await ReadI16Async(cancellationToken) }; } public override Task ReadFieldEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var map = new TMap { KeyType = (TType) await ReadByteAsync(cancellationToken), ValueType = (TType) await ReadByteAsync(cancellationToken), Count = await ReadI32Async(cancellationToken) }; CheckReadBytesAvailable(map); return map; } public override Task ReadMapEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var list = new TList { ElementType = (TType) await ReadByteAsync(cancellationToken), Count = await ReadI32Async(cancellationToken) }; CheckReadBytesAvailable(list); return list; } public override Task ReadListEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var set = new TSet { ElementType = (TType) await ReadByteAsync(cancellationToken), Count = await ReadI32Async(cancellationToken) }; CheckReadBytesAvailable(set); return set; } public override Task ReadSetEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return await ReadByteAsync(cancellationToken) == 1; } public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); return (sbyte)PreAllocatedBuffer[0]; } public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 2, cancellationToken); var result = BinaryPrimitives.ReadInt16BigEndian(PreAllocatedBuffer); return result; } public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 4, cancellationToken); var result = BinaryPrimitives.ReadInt32BigEndian(PreAllocatedBuffer); return result; } public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); return BinaryPrimitives.ReadInt64BigEndian(PreAllocatedBuffer); } public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var d = await ReadI64Async(cancellationToken); return BitConverter.Int64BitsToDouble(d); } public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var size = await ReadI32Async(cancellationToken); Transport.CheckReadBytesAvailable(size); var buf = new byte[size]; await Trans.ReadAllAsync(buf, 0, size, cancellationToken); return buf; } public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Transport.CheckReadBytesAvailable(16); // = sizeof(uuid) var buf = new byte[16]; await Trans.ReadAllAsync(buf, 0, 16, cancellationToken); return new Guid(buf).SwapByteOrder(); } public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var size = await ReadI32Async(cancellationToken); return size > 0 ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; } private async ValueTask ReadStringBodyAsync(int size, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (size <= PreAllocatedBuffer.Length) { await Trans.ReadAllAsync(PreAllocatedBuffer, 0, size, cancellationToken); return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, size); } Transport.CheckReadBytesAvailable(size); var buf = new byte[size]; await Trans.ReadAllAsync(buf, 0, size, cancellationToken); return Encoding.UTF8.GetString(buf, 0, buf.Length); } // Return the minimum number of bytes a type will consume on the wire public override int GetMinSerializedSize(TType type) { switch (type) { case TType.Stop: return 0; case TType.Void: return 0; case TType.Bool: return sizeof(byte); case TType.Byte: return sizeof(byte); case TType.Double: return sizeof(double); case TType.I16: return sizeof(short); case TType.I32: return sizeof(int); case TType.I64: return sizeof(long); case TType.String: return sizeof(int); // string length case TType.Struct: return 0; // empty struct case TType.Map: return sizeof(int); // element count case TType.Set: return sizeof(int); // element count case TType.List: return sizeof(int); // element count case TType.Uuid: return 16; // uuid bytes default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code"); } } public class Factory : TProtocolFactory { protected bool StrictRead; protected bool StrictWrite; public Factory() : this(false, true) { } public Factory(bool strictRead, bool strictWrite) { StrictRead = strictRead; StrictWrite = strictWrite; } public override TProtocol GetProtocol(TTransport trans) { return new TBinaryProtocol(trans, StrictRead, StrictWrite); } } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs0000644000000000000000000002431614370300523024331 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; namespace Thrift.Protocol { // ReSharper disable once InconsistentNaming /// /// TProtocolDecorator forwards all requests to an enclosed TProtocol instance, /// providing a way to author concise concrete decorator subclasses.While it has /// no abstract methods, it is marked abstract as a reminder that by itself, /// it does not modify the behaviour of the enclosed TProtocol. /// public abstract class TProtocolDecorator : TProtocol { private readonly TProtocol _wrappedProtocol; protected TProtocolDecorator(TProtocol protocol) : base(protocol.Transport) { _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol)); } public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { await _wrappedProtocol.WriteMessageBeginAsync(message, cancellationToken); } public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteMessageEndAsync(cancellationToken); } public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) { await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken); } public override async Task WriteStructEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteStructEndAsync(cancellationToken); } public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) { await _wrappedProtocol.WriteFieldBeginAsync(field, cancellationToken); } public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteFieldEndAsync(cancellationToken); } public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteFieldStopAsync(cancellationToken); } public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) { await _wrappedProtocol.WriteMapBeginAsync(map, cancellationToken); } public override async Task WriteMapEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteMapEndAsync(cancellationToken); } public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) { await _wrappedProtocol.WriteListBeginAsync(list, cancellationToken); } public override async Task WriteListEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteListEndAsync(cancellationToken); } public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) { await _wrappedProtocol.WriteSetBeginAsync(set, cancellationToken); } public override async Task WriteSetEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.WriteSetEndAsync(cancellationToken); } public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) { await _wrappedProtocol.WriteBoolAsync(b, cancellationToken); } public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { await _wrappedProtocol.WriteByteAsync(b, cancellationToken); } public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { await _wrappedProtocol.WriteI16Async(i16, cancellationToken); } public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) { await _wrappedProtocol.WriteI32Async(i32, cancellationToken); } public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { await _wrappedProtocol.WriteI64Async(i64, cancellationToken); } public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) { await _wrappedProtocol.WriteDoubleAsync(d, cancellationToken); } public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) { await _wrappedProtocol.WriteStringAsync(s, cancellationToken); } public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken); } public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken) { await _wrappedProtocol.WriteUuidAsync(uuid, cancellationToken); } public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadMessageBeginAsync(cancellationToken); } public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await _wrappedProtocol.ReadMessageEndAsync(cancellationToken); Transport.ResetConsumedMessageSize(); } public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadStructBeginAsync(cancellationToken); } public override async Task ReadStructEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.ReadStructEndAsync(cancellationToken); } public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadFieldBeginAsync(cancellationToken); } public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.ReadFieldEndAsync(cancellationToken); } public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadMapBeginAsync(cancellationToken); } public override async Task ReadMapEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.ReadMapEndAsync(cancellationToken); } public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadListBeginAsync(cancellationToken); } public override async Task ReadListEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.ReadListEndAsync(cancellationToken); } public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadSetBeginAsync(cancellationToken); } public override async Task ReadSetEndAsync(CancellationToken cancellationToken) { await _wrappedProtocol.ReadSetEndAsync(cancellationToken); } public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadBoolAsync(cancellationToken); } public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadByteAsync(cancellationToken); } public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadI16Async(cancellationToken); } public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadI32Async(cancellationToken); } public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadI64Async(cancellationToken); } public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadDoubleAsync(cancellationToken); } public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadStringAsync(cancellationToken); } public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadBinaryAsync(cancellationToken); } public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadUuidAsync(cancellationToken); } // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. public override int GetMinSerializedSize(TType type) { return _wrappedProtocol.GetMinSerializedSize(type); } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/ToString.cs0000644000000000000000000000523114370300523022305 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Text; using Thrift.Protocol; namespace Thrift.Protocol { public static class ToStringExtensions { public static void ToString(this object self, StringBuilder sb, bool first = true) { if (!first) sb.Append(", "); bool first_child = true; if (self is string) // string is IEnumerable { sb.Append('"'); sb.Append(self); sb.Append('"'); } else if (self is IDictionary) { sb.Append("{ "); foreach (DictionaryEntry pair in (self as IDictionary)) { if (first_child) first_child = false; else sb.Append(','); sb.Append("{ "); pair.Key.ToString(sb); sb.Append(", "); pair.Value.ToString(sb); sb.Append('}'); } sb.Append('}'); } else if (self is IEnumerable) { sb.Append("{ "); foreach (var elm in (self as IEnumerable)) { elm.ToString(sb, first_child); first_child = false; } sb.Append('}'); } else if (self is TBase) { sb.Append((self as TBase).ToString()); } else if (self is double) { sb.Append(((double)self).ToString(CultureInfo.InvariantCulture)); } else { sb.Append(self != null ? self.ToString() : ""); } } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Utilities/0000777000000000000000000000000014370300523022163 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs0000644000000000000000000001154314370300523025275 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; namespace Thrift.Protocol.Utilities { // ReSharper disable once InconsistentNaming public static class TProtocolUtil { public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); protocol.IncrementRecursionDepth(); try { switch (type) { case TType.Bool: await protocol.ReadBoolAsync(cancellationToken); break; case TType.Byte: await protocol.ReadByteAsync(cancellationToken); break; case TType.I16: await protocol.ReadI16Async(cancellationToken); break; case TType.I32: await protocol.ReadI32Async(cancellationToken); break; case TType.I64: await protocol.ReadI64Async(cancellationToken); break; case TType.Double: await protocol.ReadDoubleAsync(cancellationToken); break; case TType.String: // Don't try to decode the string, just skip it. await protocol.ReadBinaryAsync(cancellationToken); break; case TType.Uuid: await protocol.ReadUuidAsync(cancellationToken); break; case TType.Struct: await protocol.ReadStructBeginAsync(cancellationToken); while (true) { var field = await protocol.ReadFieldBeginAsync(cancellationToken); if (field.Type == TType.Stop) { break; } await SkipAsync(protocol, field.Type, cancellationToken); await protocol.ReadFieldEndAsync(cancellationToken); } await protocol.ReadStructEndAsync(cancellationToken); break; case TType.Map: var map = await protocol.ReadMapBeginAsync(cancellationToken); for (var i = 0; i < map.Count; i++) { await SkipAsync(protocol, map.KeyType, cancellationToken); await SkipAsync(protocol, map.ValueType, cancellationToken); } await protocol.ReadMapEndAsync(cancellationToken); break; case TType.Set: var set = await protocol.ReadSetBeginAsync(cancellationToken); for (var i = 0; i < set.Count; i++) { await SkipAsync(protocol, set.ElementType, cancellationToken); } await protocol.ReadSetEndAsync(cancellationToken); break; case TType.List: var list = await protocol.ReadListBeginAsync(cancellationToken); for (var i = 0; i < list.Count; i++) { await SkipAsync(protocol, list.ElementType, cancellationToken); } await protocol.ReadListEndAsync(cancellationToken); break; default: throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); } } finally { protocol.DecrementRecursionDepth(); } } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Utilities/TBase64Utils.cs0000644000000000000000000001041614303740367024713 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; namespace Thrift.Protocol.Utilities { // ReSharper disable once InconsistentNaming internal static class TBase64Utils { //TODO: Constants //TODO: Check for args //TODO: Unitests internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; private static readonly int[] DecodeTable = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) { if (src == null) { throw new ArgumentNullException(nameof(src)); } dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; if (len == 3) { dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; } else if (len == 2) { dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; } else { // len == 1 dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; } } internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) { if (src == null) { throw new ArgumentNullException(nameof(src)); } dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); if (len > 2) { dst[dstOff + 1] = (byte) (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); if (len > 3) { dst[dstOff + 2] = (byte) (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); } } } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolConstants.cs0000644000000000000000000000663314370300523027172 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Protocol.Utilities { // ReSharper disable once InconsistentNaming public static class TJSONProtocolConstants { //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/) // can be possible to get better performance and also better GC public static readonly byte[] Comma = {(byte) ','}; public static readonly byte[] Colon = {(byte) ':'}; public static readonly byte[] LeftBrace = {(byte) '{'}; public static readonly byte[] RightBrace = {(byte) '}'}; public static readonly byte[] LeftBracket = {(byte) '['}; public static readonly byte[] RightBracket = {(byte) ']'}; public static readonly byte[] Quote = {(byte) '"'}; public static readonly byte[] Backslash = {(byte) '\\'}; public static readonly byte[] JsonCharTable = { 0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray(); public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'}; public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'}; public static class TypeNames { public static readonly byte[] NameBool = { (byte)'t', (byte)'f' }; public static readonly byte[] NameByte = { (byte)'i', (byte)'8' }; public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' }; public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' }; public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' }; public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' }; public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' }; public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' }; public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' }; public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' }; public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' }; public static readonly byte[] NameUuid = { (byte)'u', (byte)'i', (byte)'d' }; } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolHelper.cs0000644000000000000000000001456214370300523026435 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using Thrift.Protocol.Entities; namespace Thrift.Protocol.Utilities { // ReSharper disable once InconsistentNaming public static class TJSONProtocolHelper { public static byte[] GetTypeNameForTypeId(TType typeId) { switch (typeId) { case TType.Bool: return TJSONProtocolConstants.TypeNames.NameBool; case TType.Byte: return TJSONProtocolConstants.TypeNames.NameByte; case TType.I16: return TJSONProtocolConstants.TypeNames.NameI16; case TType.I32: return TJSONProtocolConstants.TypeNames.NameI32; case TType.I64: return TJSONProtocolConstants.TypeNames.NameI64; case TType.Double: return TJSONProtocolConstants.TypeNames.NameDouble; case TType.String: return TJSONProtocolConstants.TypeNames.NameString; case TType.Struct: return TJSONProtocolConstants.TypeNames.NameStruct; case TType.Map: return TJSONProtocolConstants.TypeNames.NameMap; case TType.Set: return TJSONProtocolConstants.TypeNames.NameSet; case TType.List: return TJSONProtocolConstants.TypeNames.NameList; case TType.Uuid: return TJSONProtocolConstants.TypeNames.NameUuid; default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); } } public static TType GetTypeIdForTypeName(byte[] name) { var result = TType.Stop; if (name.Length > 1) { switch (name[0]) { case (byte) 'd': result = TType.Double; break; case (byte) 'i': switch (name[1]) { case (byte) '8': result = TType.Byte; break; case (byte) '1': result = TType.I16; break; case (byte) '3': result = TType.I32; break; case (byte) '6': result = TType.I64; break; } break; case (byte) 'l': result = TType.List; break; case (byte) 'm': result = TType.Map; break; case (byte) 'r': result = TType.Struct; break; case (byte) 's': if (name[1] == (byte) 't') { result = TType.String; } else if (name[1] == (byte) 'e') { result = TType.Set; } break; case (byte) 't': result = TType.Bool; break; case (byte)'u': result = TType.Uuid; break; } } if (result == TType.Stop) { throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); } return result; } /// /// Return true if the given byte could be a valid part of a JSON number. /// public static bool IsJsonNumeric(byte b) { switch (b) { case (byte)'+': case (byte)'-': case (byte)'.': case (byte)'0': case (byte)'1': case (byte)'2': case (byte)'3': case (byte)'4': case (byte)'5': case (byte)'6': case (byte)'7': case (byte)'8': case (byte)'9': case (byte)'E': case (byte)'e': return true; default: return false; } } /// /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its /// corresponding hex value /// public static byte ToHexVal(byte ch) { if (ch >= '0' && ch <= '9') { return (byte)((char)ch - '0'); } if (ch >= 'a' && ch <= 'f') { ch += 10; return (byte)((char)ch - 'a'); } throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); } /// /// Convert a byte containing a hex value to its corresponding hex character /// public static byte ToHexChar(byte val) { val &= 0x0F; if (val < 10) { return (byte)((char)val + '0'); } val -= 10; return (byte)((char)val + 'a'); } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/Utilities/TGuidExtensions.cs0000644000000000000000000000462714370300523025613 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace Thrift.Protocol.Utilities { public static class TGuidExtensions { public static Guid SwapByteOrder(this Guid self) { var bytes = self.ToByteArray(); // already network order on BigEndian machines if (BitConverter.IsLittleEndian) { SwapBytes(ref bytes[0], ref bytes[3]); SwapBytes(ref bytes[1], ref bytes[2]); SwapBytes(ref bytes[4], ref bytes[5]); SwapBytes(ref bytes[6], ref bytes[7]); } return new Guid(bytes); } private static void SwapBytes(ref byte one, ref byte two) { var tmp = one; one = two; two = tmp; } #region SelfTest #if DEBUG static private readonly Guid TEST_GUID = new Guid("{00112233-4455-6677-8899-aabbccddeeff}"); static TGuidExtensions() { SelfTest(); } private static void SelfTest() { // host to network var guid = TEST_GUID; guid = guid.SwapByteOrder(); // validate network order var bytes = guid.ToByteArray(); for (var i = 0; i < 10; ++i) { var expected = i * 0x11; Debug.Assert( bytes[i] == expected); } // network to host and final validation guid = guid.SwapByteOrder(); Debug.Assert(guid.Equals(TEST_GUID)); } #endif #endregion } } thrift-0.19.0/lib/netstd/Thrift/Protocol/TMultiplexedProtocol.cs0000644000000000000000000000711314303740367024711 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; namespace Thrift.Protocol { /** * TMultiplexedProtocol is a protocol-independent concrete decorator that allows a Thrift * client to communicate with a multiplexing Thrift server, by prepending the service name * to the function name during function calls. * * NOTE: THIS IS NOT TO BE USED BY SERVERS. * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. * * This example uses a single socket transport to invoke two services: * * TSocketTransport transport = new TSocketTransport("localhost", 9090); * transport.open(); * * TBinaryProtocol protocol = new TBinaryProtocol(transport); * * TMultiplexedProtocol mp = new TMultiplexedProtocol(protocol, "Calculator"); * Calculator.Client service = new Calculator.Client(mp); * * TMultiplexedProtocol mp2 = new TMultiplexedProtocol(protocol, "WeatherReport"); * WeatherReport.Client service2 = new WeatherReport.Client(mp2); * * System.out.println(service.add(2,2)); * System.out.println(service2.getTemperature()); * */ //TODO: implementation of TProtocol // ReSharper disable once InconsistentNaming public class TMultiplexedProtocol : TProtocolDecorator { /** Used to delimit the service name from the function name */ public const string Separator = ":"; private readonly string _serviceName; /** * Wrap the specified protocol, allowing it to be used to communicate with a * multiplexing server. The serviceName is required as it is * prepended to the message header so that the multiplexing server can broker * the function call to the proper service. * * Args: * protocol Your communication protocol of choice, e.g. TBinaryProtocol * serviceName The service name of the service communicating via this protocol. */ public TMultiplexedProtocol(TProtocol protocol, string serviceName) : base(protocol) { _serviceName = serviceName; } public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { switch (message.Type) { case TMessageType.Call: case TMessageType.Oneway: await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken); break; default: await base.WriteMessageBeginAsync(message, cancellationToken); break; } } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/TProtocol.cs0000644000000000000000000001754214370300523022471 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Text; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; using Thrift.Transport; namespace Thrift.Protocol { // ReSharper disable once InconsistentNaming public abstract class TProtocol : IDisposable { private bool _isDisposed; protected int RecursionDepth; protected TTransport Trans; protected static readonly TStruct AnonymousStruct = new TStruct(string.Empty); protected static readonly TField StopField = new TField() { Type = TType.Stop }; protected TProtocol(TTransport trans) { Trans = trans; RecursionLimit = trans.Configuration.RecursionLimit; RecursionDepth = 0; } public TTransport Transport => Trans; protected int RecursionLimit { get; set; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void IncrementRecursionDepth() { if (RecursionDepth < RecursionLimit) { ++RecursionDepth; } else { throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); } } public void DecrementRecursionDepth() { --RecursionDepth; } protected virtual void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { (Trans as IDisposable)?.Dispose(); } } _isDisposed = true; } protected void CheckReadBytesAvailable(TSet set) { Transport.CheckReadBytesAvailable(set.Count * GetMinSerializedSize(set.ElementType)); } protected void CheckReadBytesAvailable(TList list) { Transport.CheckReadBytesAvailable(list.Count * GetMinSerializedSize(list.ElementType)); } protected void CheckReadBytesAvailable(TMap map) { var elmSize = GetMinSerializedSize(map.KeyType) + GetMinSerializedSize(map.ValueType); Transport.CheckReadBytesAvailable(map.Count * elmSize); } // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. public abstract int GetMinSerializedSize(TType type); public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken = default); public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken = default); public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken = default); public abstract Task WriteStructEndAsync(CancellationToken cancellationToken = default); public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken = default); public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken = default); public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken = default); public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken = default); public abstract Task WriteMapEndAsync(CancellationToken cancellationToken = default); public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken = default); public abstract Task WriteListEndAsync(CancellationToken cancellationToken = default); public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken = default); public abstract Task WriteSetEndAsync(CancellationToken cancellationToken = default); public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken = default); public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken = default); public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken = default); public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken = default); public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken = default); public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken = default); public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken = default) { var bytes = Encoding.UTF8.GetBytes(s); await WriteBinaryAsync(bytes, cancellationToken); } public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken = default); public abstract Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken = default); public abstract ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken = default); public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadStructBeginAsync(CancellationToken cancellationToken = default); public abstract Task ReadStructEndAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken = default); public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadMapBeginAsync(CancellationToken cancellationToken = default); public abstract Task ReadMapEndAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadListBeginAsync(CancellationToken cancellationToken = default); public abstract Task ReadListEndAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadSetBeginAsync(CancellationToken cancellationToken = default); public abstract Task ReadSetEndAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadBoolAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadByteAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadI16Async(CancellationToken cancellationToken = default); public abstract ValueTask ReadI32Async(CancellationToken cancellationToken = default); public abstract ValueTask ReadI64Async(CancellationToken cancellationToken = default); public abstract ValueTask ReadDoubleAsync(CancellationToken cancellationToken = default); public virtual async ValueTask ReadStringAsync(CancellationToken cancellationToken = default) { var buf = await ReadBinaryAsync(cancellationToken); return Encoding.UTF8.GetString(buf, 0, buf.Length); } public abstract ValueTask ReadBinaryAsync(CancellationToken cancellationToken = default); public abstract ValueTask ReadUuidAsync(CancellationToken cancellationToken = default); } } thrift-0.19.0/lib/netstd/Thrift/Protocol/TProtocolFactory.cs0000644000000000000000000000177714303740367024036 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using Thrift.Transport; namespace Thrift.Protocol { // ReSharper disable once InconsistentNaming public abstract class TProtocolFactory { public abstract TProtocol GetProtocol(TTransport trans); } } thrift-0.19.0/lib/netstd/Thrift/Protocol/TCompactProtocol.cs0000644000000000000000000010003714370300523023770 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Buffers; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol.Entities; using Thrift.Protocol.Utilities; using Thrift.Transport; namespace Thrift.Protocol { // ReSharper disable once InconsistentNaming public class TCompactProtocol : TProtocol { private const byte ProtocolId = 0x82; private const byte Version = 1; private const byte VersionMask = 0x1f; // 0001 1111 private const byte TypeMask = 0xE0; // 1110 0000 private const byte TypeBits = 0x07; // 0000 0111 private const int TypeShiftAmount = 5; private const byte NoTypeOverride = 0xFF; // ReSharper disable once InconsistentNaming private static readonly byte[] TTypeToCompactType = new byte[17]; private static readonly TType[] CompactTypeToTType = new TType[14]; /// /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff. /// private readonly Stack _lastField = new Stack(15); /// /// If we encounter a boolean field begin, save the TField here so it can have the value incorporated. /// private TField? _booleanField; /// /// If we Read a field header, and it's a boolean field, save the boolean value here so that ReadBool can use it. /// private bool? _boolValue; private short _lastFieldId; // minimize memory allocations by means of an preallocated bytes buffer // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) private readonly byte[] PreAllocatedBuffer = new byte[128]; private struct VarInt { public byte[] bytes; public int count; } // minimize memory allocations by means of an preallocated VarInt buffer private VarInt PreAllocatedVarInt = new VarInt() { bytes = new byte[10], // see Int64ToVarInt() count = 0 }; public TCompactProtocol(TTransport trans) : base(trans) { TTypeToCompactType[(int)TType.Stop] = Types.Stop; TTypeToCompactType[(int)TType.Bool] = Types.BooleanTrue; TTypeToCompactType[(int)TType.Byte] = Types.Byte; TTypeToCompactType[(int)TType.I16] = Types.I16; TTypeToCompactType[(int)TType.I32] = Types.I32; TTypeToCompactType[(int)TType.I64] = Types.I64; TTypeToCompactType[(int)TType.Double] = Types.Double; TTypeToCompactType[(int)TType.String] = Types.Binary; TTypeToCompactType[(int)TType.List] = Types.List; TTypeToCompactType[(int)TType.Set] = Types.Set; TTypeToCompactType[(int)TType.Map] = Types.Map; TTypeToCompactType[(int)TType.Struct] = Types.Struct; TTypeToCompactType[(int)TType.Uuid] = Types.Uuid; CompactTypeToTType[Types.Stop] = TType.Stop; CompactTypeToTType[Types.BooleanTrue] = TType.Bool; CompactTypeToTType[Types.BooleanFalse] = TType.Bool; CompactTypeToTType[Types.Byte] = TType.Byte; CompactTypeToTType[Types.I16] = TType.I16; CompactTypeToTType[Types.I32] = TType.I32; CompactTypeToTType[Types.I64] = TType.I64; CompactTypeToTType[Types.Double] = TType.Double; CompactTypeToTType[Types.Binary] = TType.String; CompactTypeToTType[Types.List] = TType.List; CompactTypeToTType[Types.Set] = TType.Set; CompactTypeToTType[Types.Map] = TType.Map; CompactTypeToTType[Types.Struct] = TType.Struct; CompactTypeToTType[Types.Uuid] = TType.Uuid; } public void Reset() { _lastField.Clear(); _lastFieldId = 0; } public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { PreAllocatedBuffer[0] = ProtocolId; PreAllocatedBuffer[1] = (byte)((Version & VersionMask) | (((uint)message.Type << TypeShiftAmount) & TypeMask)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); Int32ToVarInt((uint) message.SeqID, ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); await WriteStringAsync(message.Name, cancellationToken); } public override Task WriteMessageEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } /// /// Write a struct begin. This doesn't actually put anything on the wire. We /// use it as an opportunity to put special placeholder markers on the field /// stack so we can get the field id deltas correct. /// public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _lastField.Push(_lastFieldId); _lastFieldId = 0; return Task.CompletedTask; } public override Task WriteStructEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _lastFieldId = _lastField.Pop(); return Task.CompletedTask; } private async Task WriteFieldBeginInternalAsync(TField field, byte fieldType, CancellationToken cancellationToken) { // if there's a exType override passed in, use that. Otherwise ask GetCompactType(). if (fieldType == NoTypeOverride) fieldType = GetCompactType(field.Type); // check if we can use delta encoding for the field id if (field.ID > _lastFieldId) { var delta = field.ID - _lastFieldId; if (delta <= 15) { // Write them together PreAllocatedBuffer[0] = (byte)((delta << 4) | fieldType); await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); _lastFieldId = field.ID; return; } } // Write them separate PreAllocatedBuffer[0] = fieldType; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); await WriteI16Async(field.ID, cancellationToken); _lastFieldId = field.ID; } public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) { if (field.Type == TType.Bool) { _booleanField = field; } else { await WriteFieldBeginInternalAsync(field, NoTypeOverride, cancellationToken); } } public override Task WriteFieldEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = Types.Stop; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Abstract method for writing the start of lists and sets. List and sets on the wire differ only by the exType indicator. */ if (size <= 14) { PreAllocatedBuffer[0] = (byte)((size << 4) | GetCompactType(elemType)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } else { PreAllocatedBuffer[0] = (byte)(0xf0 | GetCompactType(elemType)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); Int32ToVarInt((uint) size, ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } } public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) { await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken); } public override Task WriteListEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken); } public override Task WriteSetEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Write a boolean value. Potentially, this could be a boolean field, in which case the field header info isn't written yet. If so, decide what the right exType header is for the value and then Write the field header. Otherwise, Write a single byte. */ if (_booleanField != null) { // we haven't written the field header yet var type = b ? Types.BooleanTrue : Types.BooleanFalse; await WriteFieldBeginInternalAsync(_booleanField.Value, type, cancellationToken); _booleanField = null; } else { // we're not part of a field, so just write the value. PreAllocatedBuffer[0] = b ? Types.BooleanTrue : Types.BooleanFalse; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } } public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = (byte)b; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Int32ToVarInt(IntToZigzag(i16), ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } private static void Int32ToVarInt(uint n, ref VarInt varint) { // Write an i32 as a varint. Results in 1 - 5 bytes on the wire. varint.count = 0; Debug.Assert(varint.bytes.Length >= 5); while (true) { if ((n & ~0x7F) == 0) { varint.bytes[varint.count++] = (byte)n; break; } varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80); n >>= 7; } } public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Int32ToVarInt(IntToZigzag(i32), ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } static private void Int64ToVarInt(ulong n, ref VarInt varint) { // Write an i64 as a varint. Results in 1-10 bytes on the wire. varint.count = 0; Debug.Assert(varint.bytes.Length >= 10); while (true) { if ((n & ~(ulong)0x7FL) == 0) { varint.bytes[varint.count++] = (byte)n; break; } varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80); n >>= 7; } } public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Int64ToVarInt(LongToZigzag(i64), ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); BinaryPrimitives.WriteInt64LittleEndian(PreAllocatedBuffer, BitConverter.DoubleToInt64Bits(d)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var buf = ArrayPool.Shared.Rent(Encoding.UTF8.GetByteCount(str)); try { var numberOfBytes = Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0); Int32ToVarInt((uint)numberOfBytes, ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); await Trans.WriteAsync(buf, 0, numberOfBytes, cancellationToken); } finally { ArrayPool.Shared.Return(buf); } } public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } public override async Task WriteUuidAsync(Guid uuid, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var bytes = uuid.SwapByteOrder().ToByteArray(); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (map.Count == 0) { PreAllocatedBuffer[0] = 0; await Trans.WriteAsync( PreAllocatedBuffer, 0, 1, cancellationToken); } else { Int32ToVarInt((uint) map.Count, ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); PreAllocatedBuffer[0] = (byte)((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } } public override Task WriteMapEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); var protocolId = (byte) await ReadByteAsync(cancellationToken); if (protocolId != ProtocolId) { throw new TProtocolException($"Expected protocol id {ProtocolId:X} but got {protocolId:X}"); } var versionAndType = (byte) await ReadByteAsync(cancellationToken); var version = (byte) (versionAndType & VersionMask); if (version != Version) { throw new TProtocolException($"Expected version {Version} but got {version}"); } var type = (byte) ((versionAndType >> TypeShiftAmount) & TypeBits); var seqid = (int) await ReadVarInt32Async(cancellationToken); var messageName = await ReadStringAsync(cancellationToken); return new TMessage(messageName, (TMessageType) type, seqid); } public override Task ReadMessageEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Transport.ResetConsumedMessageSize(); return Task.CompletedTask; } public override ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _lastField.Push(_lastFieldId); _lastFieldId = 0; return new ValueTask(AnonymousStruct); } public override Task ReadStructEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Doesn't actually consume any wire data, just removes the last field for this struct from the field stack. */ // consume the last field we Read off the wire. _lastFieldId = _lastField.Pop(); return Task.CompletedTask; } public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { // Read a field header off the wire. var type = (byte) await ReadByteAsync(cancellationToken); // if it's a stop, then we can return immediately, as the struct is over. if (type == Types.Stop) { return StopField; } // mask off the 4 MSB of the exType header. it could contain a field id delta. var modifier = (short) ((type & 0xf0) >> 4); var compactType = (byte)(type & 0x0f); short fieldId; if (modifier == 0) { fieldId = await ReadI16Async(cancellationToken); } else { fieldId = (short) (_lastFieldId + modifier); } var ttype = GetTType(compactType); var field = new TField(string.Empty, ttype, fieldId); // if this happens to be a boolean field, the value is encoded in the exType if( ttype == TType.Bool) { _boolValue = (compactType == Types.BooleanTrue); } // push the new field onto the field stack so we can keep the deltas going. _lastFieldId = field.ID; return field; } public override Task ReadFieldEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Read a map header off the wire. If the size is zero, skip Reading the key and value exType. This means that 0-length maps will yield TMaps without the "correct" types. */ var size = (int) await ReadVarInt32Async(cancellationToken); var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken); var map = new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); CheckReadBytesAvailable(map); return map; } public override Task ReadMapEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { /* Read a set header off the wire. If the set size is 0-14, the size will be packed into the element exType header. If it's a longer set, the 4 MSB of the element exType header will be 0xF, and a varint will follow with the true size. */ return new TSet(await ReadListBeginAsync(cancellationToken)); } public override ValueTask ReadBoolAsync(CancellationToken cancellationToken) { /* Read a boolean off the wire. If this is a boolean field, the value should already have been Read during ReadFieldBegin, so we'll just consume the pre-stored value. Otherwise, Read a byte. */ if (_boolValue != null) { var result = _boolValue.Value; _boolValue = null; return new ValueTask(result); } return InternalCall(); async ValueTask InternalCall() { var data = await ReadByteAsync(cancellationToken); return (data == Types.BooleanTrue); } } public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { // Read a single byte off the wire. Nothing interesting here. await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); return (sbyte)PreAllocatedBuffer[0]; } public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken)); } public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return ZigzagToInt(await ReadVarInt32Async(cancellationToken)); } public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return ZigzagToLong(await ReadVarInt64Async(cancellationToken)); } public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(PreAllocatedBuffer)); } public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { // read length var length = (int) await ReadVarInt32Async(cancellationToken); if (length == 0) { return string.Empty; } // read and decode data if (length < PreAllocatedBuffer.Length) { await Trans.ReadAllAsync(PreAllocatedBuffer, 0, length, cancellationToken); return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, length); } Transport.CheckReadBytesAvailable(length); var buf = ArrayPool.Shared.Rent(length); try { await Trans.ReadAllAsync(buf, 0, length, cancellationToken); return Encoding.UTF8.GetString(buf, 0, length); } finally { ArrayPool.Shared.Return(buf); } } public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { // read length var length = (int) await ReadVarInt32Async(cancellationToken); if (length == 0) { return Array.Empty(); } // read data Transport.CheckReadBytesAvailable(length); var buf = new byte[length]; await Trans.ReadAllAsync(buf, 0, length, cancellationToken); return buf; } public override async ValueTask ReadUuidAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); Transport.CheckReadBytesAvailable(16); // = sizeof(uuid) var buf = new byte[16]; await Trans.ReadAllAsync(buf, 0, 16, cancellationToken); return new Guid(buf).SwapByteOrder(); } public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Read a list header off the wire. If the list size is 0-14, the size will be packed into the element exType header. If it's a longer list, the 4 MSB of the element exType header will be 0xF, and a varint will follow with the true size. */ var sizeAndType = (byte) await ReadByteAsync(cancellationToken); var size = (sizeAndType >> 4) & 0x0f; if (size == 15) { size = (int) await ReadVarInt32Async(cancellationToken); } var type = GetTType(sizeAndType); var list = new TList(type, size); CheckReadBytesAvailable(list); return list; } public override Task ReadListEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override Task ReadSetEndAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } private static byte GetCompactType(TType ttype) { // Given a TType value, find the appropriate TCompactProtocol.Types constant. return TTypeToCompactType[(int) ttype]; } private async ValueTask ReadVarInt32Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Read an i32 from the wire as a varint. The MSB of each byte is set if there is another byte to follow. This can Read up to 5 bytes. */ uint result = 0; var shift = 0; while (true) { var b = (byte) await ReadByteAsync(cancellationToken); result |= (uint) (b & 0x7f) << shift; if ((b & 0x80) != 0x80) { break; } shift += 7; } return result; } private async ValueTask ReadVarInt64Async(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); /* Read an i64 from the wire as a proper varint. The MSB of each byte is set if there is another byte to follow. This can Read up to 10 bytes. */ var shift = 0; ulong result = 0; while (true) { var b = (byte) await ReadByteAsync(cancellationToken); result |= (ulong) (b & 0x7f) << shift; if ((b & 0x80) != 0x80) { break; } shift += 7; } return result; } private static int ZigzagToInt(uint n) { return (int) (n >> 1) ^ -(int) (n & 1); } private static long ZigzagToLong(ulong n) { return (long) (n >> 1) ^ -(long) (n & 1); } private static TType GetTType(byte type) { // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. return CompactTypeToTType[type & 0x0f]; } private static ulong LongToZigzag(long n) { // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint return (ulong) (n << 1) ^ (ulong) (n >> 63); } private static uint IntToZigzag(int n) { // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint return (uint) (n << 1) ^ (uint) (n >> 31); } // Return the minimum number of bytes a type will consume on the wire public override int GetMinSerializedSize(TType type) { switch (type) { case TType.Stop: return 0; case TType.Void: return 0; case TType.Bool: return sizeof(byte); case TType.Double: return 8; // uses fixedLongToBytes() which always writes 8 bytes case TType.Byte: return sizeof(byte); case TType.I16: return sizeof(byte); // zigzag case TType.I32: return sizeof(byte); // zigzag case TType.I64: return sizeof(byte); // zigzag case TType.String: return sizeof(byte); // string length case TType.Struct: return 0; // empty struct case TType.Map: return sizeof(byte); // element count case TType.Set: return sizeof(byte); // element count case TType.List: return sizeof(byte); // element count case TType.Uuid: return 16; // uuid bytes default: throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "unrecognized type code"); } } public class Factory : TProtocolFactory { public override TProtocol GetProtocol(TTransport trans) { return new TCompactProtocol(trans); } } /// /// All of the on-wire exType codes. /// private static class Types { public const byte Stop = 0x00; public const byte BooleanTrue = 0x01; public const byte BooleanFalse = 0x02; public const byte Byte = 0x03; public const byte I16 = 0x04; public const byte I32 = 0x05; public const byte I64 = 0x06; public const byte Double = 0x07; public const byte Binary = 0x08; public const byte List = 0x09; public const byte Set = 0x0A; public const byte Map = 0x0B; public const byte Struct = 0x0C; public const byte Uuid = 0x0D; } } } thrift-0.19.0/lib/netstd/Thrift/Protocol/TProtocolException.cs0000644000000000000000000000363114303740367024354 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // ReSharper disable InconsistentNaming using System; namespace Thrift.Protocol { public class TProtocolException : TException { // do not rename public constants - they used in generated files public const int UNKNOWN = 0; public const int INVALID_DATA = 1; public const int NEGATIVE_SIZE = 2; public const int SIZE_LIMIT = 3; public const int BAD_VERSION = 4; public const int NOT_IMPLEMENTED = 5; public const int DEPTH_LIMIT = 6; protected int Type = UNKNOWN; public TProtocolException() { } public TProtocolException(int type, Exception inner = null) : base(string.Empty, inner) { Type = type; } public TProtocolException(int type, string message, Exception inner = null) : base(message, inner) { Type = type; } public TProtocolException(string message, Exception inner = null) : base(message, inner) { } public int GetExceptionType() { return Type; } } }thrift-0.19.0/lib/netstd/Thrift/Protocol/TBase.cs0000644000000000000000000000243514303740367021547 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; #pragma warning disable IDE1006 // some interfaces here are intentionally not I-prefixed namespace Thrift.Protocol { public interface TUnionBase { Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken = default); } // ReSharper disable once InconsistentNaming public interface TBase : TUnionBase { Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken = default); } } thrift-0.19.0/lib/netstd/Thrift/GlobalSuppressions.cs0000644000000000000000000000305314303740367022603 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; // suppress certain messages for compatibility reasons with older C# versions we want to support [assembly: SuppressMessage("Style", "IDE0057", Justification = "compatibility", Scope = "module")] [assembly: SuppressMessage("Style", "IDE0066", Justification = "compatibility", Scope = "module")] [assembly: SuppressMessage("Style", "IDE0090", Justification = "compatibility", Scope = "module")] [assembly: SuppressMessage("Style", "IDE0063", Justification = "compatibility", Scope = "module")] thrift-0.19.0/lib/netstd/Thrift/TConfiguration.cs0000644000000000000000000000267314303740367021707 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Text; namespace Thrift { public class TConfiguration { public const int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; public const int DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries public const int DEFAULT_RECURSION_DEPTH = 64; public int MaxMessageSize { get; set; } = DEFAULT_MAX_MESSAGE_SIZE; public int MaxFrameSize { get; set; } = DEFAULT_MAX_FRAME_SIZE; public int RecursionLimit { get; set; } = DEFAULT_RECURSION_DEPTH; // TODO(JensG): add connection and i/o timeouts } } thrift-0.19.0/lib/netstd/Thrift/Processor/0000777000000000000000000000000014303740367020400 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs0000644000000000000000000001274714303740367025256 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using Thrift.Protocol; using Thrift.Protocol.Entities; namespace Thrift.Processor { // ReSharper disable once InconsistentNaming public class TMultiplexedProcessor : ITAsyncProcessor { //TODO: Localization private readonly Dictionary _serviceProcessorMap = new Dictionary(); public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) { return await ProcessAsync(iprot, oprot, CancellationToken.None); } public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); try { var message = await iprot.ReadMessageBeginAsync(cancellationToken); if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) { await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidMessageType, "Message exType CALL or ONEWAY expected", cancellationToken); return false; } // Extract the service name var index = message.Name.IndexOf(TMultiplexedProtocol.Separator, StringComparison.Ordinal); if (index < 0) { await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidProtocol, $"Service name not found in message name: {message.Name}. Did you forget to use a TMultiplexProtocol in your client?", cancellationToken); return false; } // Create a new TMessage, something that can be consumed by any TProtocol var serviceName = message.Name.Substring(0, index); if (!_serviceProcessorMap.TryGetValue(serviceName, out ITAsyncProcessor actualProcessor)) { await FailAsync(oprot, message, TApplicationException.ExceptionType.InternalError, $"Service name not found: {serviceName}. Did you forget to call RegisterProcessor()?", cancellationToken); return false; } // Create a new TMessage, removing the service name var newMessage = new TMessage( message.Name.Substring(serviceName.Length + TMultiplexedProtocol.Separator.Length), message.Type, message.SeqID); // Dispatch processing to the stored processor return await actualProcessor.ProcessAsync(new StoredMessageProtocol(iprot, newMessage), oprot, cancellationToken); } catch (IOException) { return false; // similar to all other processors } } public void RegisterProcessor(string serviceName, ITAsyncProcessor processor) { if (_serviceProcessorMap.ContainsKey(serviceName)) { throw new InvalidOperationException( $"Processor map already contains processor with name: '{serviceName}'"); } _serviceProcessorMap.Add(serviceName, processor); } private static async Task FailAsync(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt, CancellationToken cancellationToken) { var appex = new TApplicationException(extype, etxt); var newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); await oprot.WriteMessageBeginAsync(newMessage, cancellationToken); await appex.WriteAsync(oprot, cancellationToken); await oprot.WriteMessageEndAsync(cancellationToken); await oprot.Transport.FlushAsync(cancellationToken); } private class StoredMessageProtocol : TProtocolDecorator { readonly TMessage _msgBegin; public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) : base(protocol) { _msgBegin = messageBegin; } public override ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return new ValueTask(_msgBegin); } } } } thrift-0.19.0/lib/netstd/Thrift/Processor/ITProcessorFactory.cs0000644000000000000000000000205414303740367024470 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using Thrift.Server; using Thrift.Transport; namespace Thrift.Processor { // ReSharper disable once InconsistentNaming public interface ITProcessorFactory { ITAsyncProcessor GetAsyncProcessor(TTransport trans, TServer baseServer = null); } }thrift-0.19.0/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs0000644000000000000000000000206014303740367024133 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; using Thrift.Protocol; namespace Thrift.Processor { public interface ITAsyncProcessor { Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken = default); } } thrift-0.19.0/lib/netstd/Thrift/Processor/TSingletonProcessorFactory.cs0000644000000000000000000000251514303740367026244 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using Thrift.Server; using Thrift.Transport; namespace Thrift.Processor { // ReSharper disable once InconsistentNaming public class TSingletonProcessorFactory : ITProcessorFactory { private readonly ITAsyncProcessor _asyncProcessor; public TSingletonProcessorFactory(ITAsyncProcessor asyncProcessor) { _asyncProcessor = asyncProcessor; } public ITAsyncProcessor GetAsyncProcessor(TTransport trans, TServer baseServer = null) { return _asyncProcessor; } } }thrift-0.19.0/lib/netstd/Thrift/Properties/0000777000000000000000000000000014454461475020564 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Properties/AssemblyInfo.cs0000644000000000000000000000431314454461475023503 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("Thrift")] [assembly: AssemblyDescription("C# .NET Core bindings for the Apache Thrift RPC system")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("The Apache Software Foundation")] [assembly: AssemblyProduct("Thrift")] [assembly: AssemblyCopyright("The Apache Software Foundation")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] //@TODO where to put License information? // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a exType in this assembly from // COM, set the ComVisible attribute to true on that exType. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: [assembly: AssemblyVersion("0.19.0.0")] [assembly: AssemblyFileVersion("0.19.0.0")] thrift-0.19.0/lib/netstd/Thrift/TException.cs0000644000000000000000000000211214303740367021022 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; namespace Thrift { // ReSharper disable once InconsistentNaming public class TException : Exception { public TException() { } public TException(string message, Exception inner) : base(message, inner) { } } }thrift-0.19.0/lib/netstd/Thrift/Collections/0000777000000000000000000000000014303740367020677 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Collections/THashSet.cs0000644000000000000000000000271714303740367022714 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections; using System.Collections.Generic; namespace Thrift.Collections { // ReSharper disable once InconsistentNaming [Obsolete("deprecated, use HashSet instead")] public class THashSet : System.Collections.Generic.HashSet { public THashSet() : base() { } public THashSet(int capacity) #if NET5_0_OR_GREATER : base(capacity) #elif NETFRAMEWORK || NETSTANDARD : base(/*capacity not supported*/) #else #error Unknown platform #endif { } public THashSet(IEnumerable collection) : base(collection) { } } } thrift-0.19.0/lib/netstd/Thrift/Collections/TCollections.cs0000644000000000000000000000717614303740367023637 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Collections; using System.Collections.Generic; namespace Thrift.Collections { // ReSharper disable once InconsistentNaming public static class TCollections { /// /// This will return true if the two collections are value-wise the same. /// If the collection contains a collection, the collections will be compared using this method. /// public static bool Equals(IEnumerable first, IEnumerable second) { if (first == null && second == null) { return true; } if (first == null || second == null) { return false; } // for dictionaries, we need to compare keys and values separately // because KeyValuePair.Equals() will not do what we want var fdict = first as IDictionary; var sdict = second as IDictionary; if ((fdict != null) || (sdict != null)) { if ((fdict == null) || (sdict == null)) return false; return TCollections.Equals(fdict.Keys, sdict.Keys) && TCollections.Equals(fdict.Values, sdict.Values); } var fiter = first.GetEnumerator(); var siter = second.GetEnumerator(); var fnext = fiter.MoveNext(); var snext = siter.MoveNext(); while (fnext && snext) { var fenum = fiter.Current as IEnumerable; var senum = siter.Current as IEnumerable; if (fenum != null && senum != null) { if (!Equals(fenum, senum)) { return false; } } else if (fenum == null ^ senum == null) { return false; } else if (!Equals(fiter.Current, siter.Current)) { return false; } fnext = fiter.MoveNext(); snext = siter.MoveNext(); } return fnext == snext; } /// /// This returns a hashcode based on the value of the enumerable. /// public static int GetHashCode(IEnumerable enumerable) { if (enumerable == null) { return 0; } var hashcode = 0; foreach (var obj in enumerable) { var objHash = (obj is IEnumerable enum2) ? GetHashCode(enum2) : obj.GetHashCode(); unchecked { hashcode = (hashcode * 397) ^ (objHash); } } return hashcode; } } } thrift-0.19.0/lib/netstd/Thrift/TApplicationException.cs0000644000000000000000000001250714303740367023217 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; using Thrift.Protocol; using Thrift.Protocol.Entities; using Thrift.Protocol.Utilities; namespace Thrift { // ReSharper disable once InconsistentNaming public class TApplicationException : TException { public enum ExceptionType { Unknown, UnknownMethod, InvalidMessageType, WrongMethodName, BadSequenceId, MissingResult, InternalError, ProtocolError, InvalidTransform, InvalidProtocol, UnsupportedClientType } private const int MessageTypeFieldId = 1; private const int ExTypeFieldId = 2; public ExceptionType Type { get; private set; } public TApplicationException() { } public TApplicationException(ExceptionType type) { Type = type; } public TApplicationException(ExceptionType type, string message) : base(message, null) // TApplicationException is serializable, but we never serialize InnerException { Type = type; } public static async ValueTask ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) { string message = null; var type = ExceptionType.Unknown; await inputProtocol.ReadStructBeginAsync(cancellationToken); while (true) { var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken); if (field.Type == TType.Stop) { break; } switch (field.ID) { case MessageTypeFieldId: if (field.Type == TType.String) { message = await inputProtocol.ReadStringAsync(cancellationToken); } else { await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); } break; case ExTypeFieldId: if (field.Type == TType.I32) { type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken); } else { await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); } break; default: await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); break; } await inputProtocol.ReadFieldEndAsync(cancellationToken); } await inputProtocol.ReadStructEndAsync(cancellationToken); return new TApplicationException(type, message); } public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); const string messageTypeFieldName = "message"; const string exTypeFieldName = "exType"; const string structApplicationExceptionName = "TApplicationException"; var struc = new TStruct(structApplicationExceptionName); var field = new TField(); await outputProtocol.WriteStructBeginAsync(struc, cancellationToken); if (!string.IsNullOrEmpty(Message)) { field.Name = messageTypeFieldName; field.Type = TType.String; field.ID = MessageTypeFieldId; await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); await outputProtocol.WriteStringAsync(Message, cancellationToken); await outputProtocol.WriteFieldEndAsync(cancellationToken); } field.Name = exTypeFieldName; field.Type = TType.I32; field.ID = ExTypeFieldId; await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); await outputProtocol.WriteI32Async((int) Type, cancellationToken); await outputProtocol.WriteFieldEndAsync(cancellationToken); await outputProtocol.WriteFieldStopAsync(cancellationToken); await outputProtocol.WriteStructEndAsync(cancellationToken); } } } thrift-0.19.0/lib/netstd/Thrift/Thrift.csproj0000644000000000000000000001057714454461475021120 0ustar00rootroot00000000000000 netstandard2.1;netstandard2.0;net6.0;net7.0 Thrift ApacheThrift true true false false false false false false false false true true true thrift.snk false Apache Thrift 0.19.0 0.19.0.0 false http://thrift.apache.org/ Apache Thrift Developers false Apache-2.0 C# .NET Core bindings for the Apache Thrift RPC system Apache Thrift RPC https://github.com/apache/thrift/blob/0.19.0/CHANGES.md README.md Copyright 2023 The Apache Software Foundation $(IntermediateOutputPath)$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension) thrift-0.19.0/lib/netstd/Thrift/Server/0000777000000000000000000000000014303740367017667 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Server/TServer.cs0000644000000000000000000000637414303740367021616 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using Thrift.Protocol; using Thrift.Transport; using Thrift.Processor; namespace Thrift.Server { // ReSharper disable once InconsistentNaming public abstract class TServer { protected readonly ILogger Logger; protected TProtocolFactory InputProtocolFactory; protected TTransportFactory InputTransportFactory; protected ITProcessorFactory ProcessorFactory; protected TProtocolFactory OutputProtocolFactory; protected TTransportFactory OutputTransportFactory; protected ITServerEventHandler ServerEventHandler; protected TServerTransport ServerTransport; protected TServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILogger logger = null) { ProcessorFactory = processorFactory ?? throw new ArgumentNullException(nameof(processorFactory)); ServerTransport = serverTransport; InputTransportFactory = inputTransportFactory ?? new TTransportFactory(); OutputTransportFactory = outputTransportFactory ?? new TTransportFactory(); InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); Logger = logger; // null is absolutely legal } public void SetEventHandler(ITServerEventHandler seh) { ServerEventHandler = seh; } public ITServerEventHandler GetEventHandler() { return ServerEventHandler; } // Log delegation? deprecated, use ILogger protected void LogError( string msg) { if (Logger != null) Logger.LogError("{Msg}",msg); // NOTE: Log message template, not string interpolation! } public abstract void Stop(); public virtual void Start() { // do nothing } public virtual Task ServeAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } } } thrift-0.19.0/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs0000644000000000000000000002114414303740367023756 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Threading; using Thrift.Protocol; using Thrift.Transport; using Thrift.Processor; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace Thrift.Server { // ReSharper disable once InconsistentNaming public class TSimpleAsyncServer : TServer { private volatile bool stop = false; private CancellationToken ServerCancellationToken; public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILogger logger) : base(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, logger) { } public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILoggerFactory loggerFactory) : this(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, loggerFactory.CreateLogger()) { } public TSimpleAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILoggerFactory loggerFactory) : this(new TSingletonProcessorFactory(processor), serverTransport, null, // defaults to TTransportFactory() null, // defaults to TTransportFactory() inputProtocolFactory, outputProtocolFactory, loggerFactory.CreateLogger(nameof(TSimpleAsyncServer))) { } public override async Task ServeAsync(CancellationToken cancellationToken) { ServerCancellationToken = cancellationToken; try { try { ServerTransport.Listen(); } catch (TTransportException ttx) { LogError("Error, could not listen on ServerTransport: " + ttx); return; } //Fire the preServe server event when server is up but before any client connections if (ServerEventHandler != null) await ServerEventHandler.PreServeAsync(cancellationToken); while (!(stop || ServerCancellationToken.IsCancellationRequested)) { try { using (TTransport client = await ServerTransport.AcceptAsync(cancellationToken)) { await ExecuteAsync(client); } } catch (TaskCanceledException) { stop = true; } catch (TTransportException ttx) { if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) { LogError(ttx.ToString()); } } } if (stop) { try { ServerTransport.Close(); } catch (TTransportException ttx) { LogError("TServerTransport failed on close: " + ttx.Message); } stop = false; } } finally { ServerCancellationToken = default; } } /// /// Loops on processing a client forever /// client will be a TTransport instance /// /// private async Task ExecuteAsync(TTransport client) { var cancellationToken = ServerCancellationToken; var processor = ProcessorFactory.GetAsyncProcessor(client, this); TTransport inputTransport = null; TTransport outputTransport = null; TProtocol inputProtocol = null; TProtocol outputProtocol = null; object connectionContext = null; try { try { inputTransport = InputTransportFactory.GetTransport(client); outputTransport = OutputTransportFactory.GetTransport(client); inputProtocol = InputProtocolFactory.GetProtocol(inputTransport); outputProtocol = OutputProtocolFactory.GetProtocol(outputTransport); //Recover event handler (if any) and fire createContext server event when a client connects if (ServerEventHandler != null) connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken); //Process client requests until client disconnects while (!(stop || cancellationToken.IsCancellationRequested)) { if (!await inputTransport.PeekAsync(cancellationToken)) break; //Fire processContext server event //N.B. This is the pattern implemented in C++ and the event fires provisionally. //That is to say it may be many minutes between the event firing and the client request //actually arriving or the client may hang up without ever makeing a request. if (ServerEventHandler != null) await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken); //Process client request (blocks until transport is readable) if (!await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken)) break; } } catch (TTransportException) { //Usually a client disconnect, expected } catch (Exception x) { //Unexpected LogError("Error: " + x); } //Fire deleteContext server event after client disconnects if (ServerEventHandler != null) await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken); } finally { //Close transports inputTransport?.Close(); outputTransport?.Close(); // disposable stuff should be disposed inputProtocol?.Dispose(); outputProtocol?.Dispose(); inputTransport?.Dispose(); outputTransport?.Dispose(); } } public override void Stop() { stop = true; ServerTransport?.Close(); } } } thrift-0.19.0/lib/netstd/Thrift/Server/TServerEventHandler.cs0000644000000000000000000000456714303740367024120 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; using Thrift.Protocol; using Thrift.Transport; namespace Thrift.Server { //TODO: replacement by event? /// /// Interface implemented by server users to handle events from the server /// /// Replaced by ITServerEventHandler // ReSharper disable once InconsistentNaming #pragma warning disable IDE1006 public interface TServerEventHandler : ITServerEventHandler { } #pragma warning restore IDE1006 /// /// Interface implemented by server users to handle events from the server /// public interface ITServerEventHandler { /// /// Called before the server begins */ /// Task PreServeAsync(CancellationToken cancellationToken); /// /// Called when a new client has connected and is about to being processing */ /// Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken); /// /// Called when a client has finished request-handling to delete server context */ /// Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, CancellationToken cancellationToken); /// /// Called when a client is about to call the processor */ /// Task ProcessContextAsync(object serverContext, TTransport transport, CancellationToken cancellationToken); } } thrift-0.19.0/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs0000644000000000000000000003011714303740367024566 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ using System; using System.Threading; using Thrift.Protocol; using Thrift.Transport; using Thrift.Processor; using System.Threading.Tasks; using Microsoft.Extensions.Logging; namespace Thrift.Server { /// /// Server that uses C# built-in ThreadPool to spawn threads when handling requests. /// public class TThreadPoolAsyncServer : TServer { private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults private volatile bool stop = false; private CancellationToken ServerCancellationToken; public struct Configuration { public int MinWorkerThreads; public int MaxWorkerThreads; public int MinIOThreads; public int MaxIOThreads; public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS) { MinWorkerThreads = min; MaxWorkerThreads = max; MinIOThreads = min; MaxIOThreads = max; } public Configuration(int minWork, int maxWork, int minIO, int maxIO) { MinWorkerThreads = minWork; MaxWorkerThreads = maxWork; MinIOThreads = minIO; MaxIOThreads = maxIO; } } public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, ILogger logger = null) : this(new TSingletonProcessorFactory(processor), serverTransport, null, null, // defaults to TTransportFactory() new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), new Configuration(), logger) { } public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, TTransportFactory transportFactory, TProtocolFactory protocolFactory) : this(new TSingletonProcessorFactory(processor), serverTransport, transportFactory, transportFactory, protocolFactory, protocolFactory, new Configuration()) { } public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory transportFactory, TProtocolFactory protocolFactory) : this(processorFactory, serverTransport, transportFactory, transportFactory, protocolFactory, protocolFactory, new Configuration()) { } public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, int minThreadPoolThreads, int maxThreadPoolThreads, ILogger logger = null) : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, new Configuration(minThreadPoolThreads, maxThreadPoolThreads), logger) { } public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, Configuration threadConfig, ILogger logger = null) : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, logger) { lock (typeof(TThreadPoolAsyncServer)) { if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0)) { ThreadPool.GetMaxThreads(out int work, out int comm); if (threadConfig.MaxWorkerThreads > 0) work = threadConfig.MaxWorkerThreads; if (threadConfig.MaxIOThreads > 0) comm = threadConfig.MaxIOThreads; if (!ThreadPool.SetMaxThreads(work, comm)) throw new Exception("Error: could not SetMaxThreads in ThreadPool"); } if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0)) { ThreadPool.GetMinThreads(out int work, out int comm); if (threadConfig.MinWorkerThreads > 0) work = threadConfig.MinWorkerThreads; if (threadConfig.MinIOThreads > 0) comm = threadConfig.MinIOThreads; if (!ThreadPool.SetMinThreads(work, comm)) throw new Exception("Error: could not SetMinThreads in ThreadPool"); } } } /// /// Use new ThreadPool thread for each new client connection. /// public override async Task ServeAsync(CancellationToken cancellationToken) { ServerCancellationToken = cancellationToken; try { try { ServerTransport.Listen(); } catch (TTransportException ttx) { LogError("Error, could not listen on ServerTransport: " + ttx); return; } //Fire the preServe server event when server is up but before any client connections if (ServerEventHandler != null) await ServerEventHandler.PreServeAsync(cancellationToken); while (!(stop || ServerCancellationToken.IsCancellationRequested)) { try { TTransport client = await ServerTransport.AcceptAsync(cancellationToken); _ = Task.Run(async () => await ExecuteAsync(client), cancellationToken); // intentionally ignoring retval } catch (TaskCanceledException) { stop = true; } catch (TTransportException ttx) { if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) { LogError(ttx.ToString()); } } } if (stop) { try { ServerTransport.Close(); } catch (TTransportException ttx) { LogError("TServerTransport failed on close: " + ttx.Message); } stop = false; } } finally { ServerCancellationToken = default; } } /// /// Loops on processing a client forever /// client will be a TTransport instance /// /// private async Task ExecuteAsync(TTransport client) { var cancellationToken = ServerCancellationToken; using (client) { ITAsyncProcessor processor = ProcessorFactory.GetAsyncProcessor(client, this); TTransport inputTransport = null; TTransport outputTransport = null; TProtocol inputProtocol = null; TProtocol outputProtocol = null; object connectionContext = null; try { try { inputTransport = InputTransportFactory.GetTransport(client); outputTransport = OutputTransportFactory.GetTransport(client); inputProtocol = InputProtocolFactory.GetProtocol(inputTransport); outputProtocol = OutputProtocolFactory.GetProtocol(outputTransport); //Recover event handler (if any) and fire createContext server event when a client connects if (ServerEventHandler != null) connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken); //Process client requests until client disconnects while (!(stop || cancellationToken.IsCancellationRequested)) { if (!await inputTransport.PeekAsync(cancellationToken)) break; //Fire processContext server event //N.B. This is the pattern implemented in C++ and the event fires provisionally. //That is to say it may be many minutes between the event firing and the client request //actually arriving or the client may hang up without ever makeing a request. if (ServerEventHandler != null) await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken); //Process client request (blocks until transport is readable) if (!await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken)) break; } } catch (TTransportException) { //Usually a client disconnect, expected } catch (Exception x) { //Unexpected LogError("Error: " + x); } //Fire deleteContext server event after client disconnects if (ServerEventHandler != null) await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken); } finally { //Close transports inputTransport?.Close(); outputTransport?.Close(); // disposable stuff should be disposed inputProtocol?.Dispose(); outputProtocol?.Dispose(); inputTransport?.Dispose(); outputTransport?.Dispose(); } } } public override void Stop() { stop = true; ServerTransport?.Close(); } } } thrift-0.19.0/lib/netstd/Thrift/.editorconfig0000644000000000000000000000014414303740367021071 0ustar00rootroot00000000000000[*.cs] # CS1591: missing XML comment for public element dotnet_diagnostic.CS1591.severity = silent thrift-0.19.0/lib/netstd/Thrift/Transport/0000777000000000000000000000000014370300523020403 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Transport/TTransportFactory.cs0000644000000000000000000000262114303740367024411 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. namespace Thrift.Transport { /// /// From Mark Slee & Aditya Agarwal of Facebook: /// Factory class used to create wrapped instance of Transports. /// This is used primarily in servers, which get Transports from /// a ServerTransport and then may want to mutate them (i.e. create /// a BufferedTransport from the underlying base transport) /// // ReSharper disable once InconsistentNaming public class TTransportFactory { public virtual TTransport GetTransport(TTransport trans) { return trans; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Client/0000777000000000000000000000000014370300523021621 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs0000644000000000000000000001162614370300523026055 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.IO.Pipes; using System.Security.Principal; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming public class TNamedPipeTransport : TEndpointTransport { private NamedPipeClientStream PipeStream; private readonly int ConnectTimeout; private const int DEFAULT_CONNECT_TIMEOUT = 60 * 1000; // Timeout.Infinite is not a good default public TNamedPipeTransport(string pipe, TConfiguration config, int timeout = DEFAULT_CONNECT_TIMEOUT) : this(".", pipe, config, timeout) { } public TNamedPipeTransport(string server, string pipe, TConfiguration config, int timeout = DEFAULT_CONNECT_TIMEOUT) : base(config) { var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; ConnectTimeout = (timeout > 0) ? timeout : DEFAULT_CONNECT_TIMEOUT; PipeStream = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None, TokenImpersonationLevel.Anonymous); } public override bool IsOpen => PipeStream != null && PipeStream.IsConnected; public override async Task OpenAsync(CancellationToken cancellationToken) { if (IsOpen) { throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); } await PipeStream.ConnectAsync( ConnectTimeout, cancellationToken); ResetConsumedMessageSize(); } public override void Close() { if (PipeStream != null) { if (PipeStream.IsConnected) PipeStream.Close(); PipeStream.Dispose(); PipeStream = null; } } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } CheckReadBytesAvailable(length); #if NETSTANDARD2_0 var numRead = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); #else var numRead = await PipeStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); #endif CountConsumedMessageBytes(numRead); return numRead; } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } // if necessary, send the data in chunks // there's a system limit around 0x10000 bytes that we hit otherwise // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." var nBytes = Math.Min(15 * 4096, length); // 16 would exceed the limit while (nBytes > 0) { #if NETSTANDARD2_0 await PipeStream.WriteAsync(buffer, offset, nBytes, cancellationToken); #else await PipeStream.WriteAsync(buffer.AsMemory(offset, nBytes), cancellationToken); #endif offset += nBytes; length -= nBytes; nBytes = Math.Min(nBytes, length); } } public override async Task FlushAsync(CancellationToken cancellationToken) { await PipeStream.FlushAsync(cancellationToken); ResetConsumedMessageSize(); } protected override void Dispose(bool disposing) { if (disposing) { if (PipeStream != null) { if (PipeStream.IsConnected) PipeStream.Close(); PipeStream.Dispose(); PipeStream = null; } } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Client/THttpTransport.cs0000644000000000000000000002627014303740367025145 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming public class THttpTransport : TEndpointTransport { private readonly X509Certificate[] _certificates; private readonly Uri _uri; private int _connectTimeout = 30000; // Timeouts in milliseconds private HttpClient _httpClient; private Stream _inputStream; private MemoryStream _outputStream = new MemoryStream(); private bool _isDisposed; public THttpTransport(Uri uri, TConfiguration config, IDictionary customRequestHeaders = null, string userAgent = null) : this(uri, config, Enumerable.Empty(), customRequestHeaders, userAgent) { } public THttpTransport(Uri uri, TConfiguration config, IEnumerable certificates, IDictionary customRequestHeaders, string userAgent = null) : base(config) { _uri = uri; _certificates = (certificates ?? Enumerable.Empty()).ToArray(); if (!string.IsNullOrEmpty(userAgent)) UserAgent = userAgent; // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 // this can be switched to default way (create client->use->dispose per flush) later _httpClient = CreateClient(customRequestHeaders); ConfigureClient(_httpClient); } /// /// Constructor that takes a HttpClient instance to support using IHttpClientFactory. /// /// As the HttpMessageHandler of the client must be configured at the time of creation, it /// is assumed that the consumer has already added any certificates and configured decompression methods. The /// consumer can use the CreateHttpClientHandler method to get a handler with these set. /// Client configured with the desired message handler, user agent, and URI if not /// specified in the uri parameter. A default user agent will be used if not set. /// Thrift configuration object /// Optional URI to use for requests, if not specified the base address of httpClient /// is used. public THttpTransport(HttpClient httpClient, TConfiguration config, Uri uri = null) : base(config) { _httpClient = httpClient; _uri = uri ?? httpClient.BaseAddress; httpClient.BaseAddress = _uri; var userAgent = _httpClient.DefaultRequestHeaders.UserAgent.ToString(); if (!string.IsNullOrEmpty(userAgent)) UserAgent = userAgent; ConfigureClient(_httpClient); } // According to RFC 2616 section 3.8, the "User-Agent" header may not carry a version number public readonly string UserAgent = "Thrift netstd THttpClient"; public int ConnectTimeout { set { _connectTimeout = value; if(_httpClient != null) _httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); } get { if (_httpClient == null) return _connectTimeout; return (int)_httpClient.Timeout.TotalMilliseconds; } } public override bool IsOpen => true; public HttpRequestHeaders RequestHeaders => _httpClient.DefaultRequestHeaders; public MediaTypeHeaderValue ContentType { get; set; } public override Task OpenAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override void Close() { if (_inputStream != null) { _inputStream.Dispose(); _inputStream = null; } if (_outputStream != null) { _outputStream.Dispose(); _outputStream = null; } if (_httpClient != null) { _httpClient.Dispose(); _httpClient = null; } } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_inputStream == null) throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); CheckReadBytesAvailable(length); try { #if NETSTANDARD2_0 var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); #else var ret = await _inputStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); #endif if (ret == -1) { throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); } CountConsumedMessageBytes(ret); return ret; } catch (IOException iox) { throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); } } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); #if NETSTANDARD2_0 await _outputStream.WriteAsync(buffer, offset, length, cancellationToken); #else await _outputStream.WriteAsync(buffer.AsMemory(offset, length), cancellationToken); #endif } /// /// Get a client handler configured with recommended properties to use with the HttpClient constructor /// and an IHttpClientFactory. /// /// An optional array of client certificates to associate with the handler. /// /// A client handler with deflate and gZip compression-decompression algorithms and any client /// certificates passed in via certificates. /// public virtual HttpClientHandler CreateHttpClientHandler(X509Certificate[] certificates = null) { var handler = new HttpClientHandler(); if (certificates != null) handler.ClientCertificates.AddRange(certificates); handler.AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip; return handler; } private HttpClient CreateClient(IDictionary customRequestHeaders) { var handler = CreateHttpClientHandler(_certificates); var httpClient = new HttpClient(handler); if (customRequestHeaders != null) { foreach (var item in customRequestHeaders) { httpClient.DefaultRequestHeaders.Add(item.Key, item.Value); } } return httpClient; } private void ConfigureClient(HttpClient httpClient) { if (_connectTimeout > 0) { httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); // Clear any user agent values to avoid drift with the field value httpClient.DefaultRequestHeaders.UserAgent.Clear(); httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd(UserAgent); httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate")); httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); } public override async Task FlushAsync(CancellationToken cancellationToken) { try { _outputStream.Seek(0, SeekOrigin.Begin); using (var contentStream = new StreamContent(_outputStream)) { contentStream.Headers.ContentType = ContentType ?? new MediaTypeHeaderValue(@"application/x-thrift"); var response = (await _httpClient.PostAsync(_uri, contentStream, cancellationToken)).EnsureSuccessStatusCode(); _inputStream?.Dispose(); #if NETSTANDARD2_0 || NETSTANDARD2_1 _inputStream = await response.Content.ReadAsStreamAsync(); #else _inputStream = await response.Content.ReadAsStreamAsync(cancellationToken); #endif if (_inputStream.CanSeek) { _inputStream.Seek(0, SeekOrigin.Begin); } } } catch (IOException iox) { throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); } catch (HttpRequestException wx) { throw new TTransportException(TTransportException.ExceptionType.Unknown, "Couldn't connect to server: " + wx); } catch (Exception ex) { throw new TTransportException(TTransportException.ExceptionType.Unknown, ex.Message); } finally { _outputStream = new MemoryStream(); ResetConsumedMessageSize(); } } // IDisposable protected override void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { _inputStream?.Dispose(); _outputStream?.Dispose(); _httpClient?.Dispose(); } } _isDisposed = true; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs0000644000000000000000000001266714303740367026635 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming public class TMemoryBufferTransport : TEndpointTransport { private bool IsDisposed; private byte[] Bytes; private int _bytesUsed; public TMemoryBufferTransport(TConfiguration config, int initialCapacity = 2048) : base(config) { Bytes = new byte[initialCapacity]; } public TMemoryBufferTransport(byte[] buf, TConfiguration config) :base(config) { Bytes = (byte[])buf.Clone(); _bytesUsed = Bytes.Length; UpdateKnownMessageSize(_bytesUsed); } public int Position { get; set; } public int Capacity { get { Debug.Assert(_bytesUsed <= Bytes.Length); return Bytes.Length; } set { Array.Resize(ref Bytes, value); _bytesUsed = value; } } public int Length { get { Debug.Assert(_bytesUsed <= Bytes.Length); return _bytesUsed; } set { if ((Bytes.Length < value) || (Bytes.Length > (10 * value))) Array.Resize(ref Bytes, Math.Max(2048, (int)(value * 1.25))); _bytesUsed = value; } } public void SetLength(int value) { Length = value; Position = Math.Min(Position, value); } public override bool IsOpen => true; public override Task OpenAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override void Close() { /* do nothing */ } public void Seek(int delta, SeekOrigin origin) { int newPos; switch (origin) { case SeekOrigin.Begin: newPos = delta; break; case SeekOrigin.Current: newPos = Position + delta; break; case SeekOrigin.End: newPos = _bytesUsed + delta; break; default: throw new ArgumentException("Unrecognized value",nameof(origin)); } if ((0 > newPos) || (newPos > _bytesUsed)) throw new ArgumentException("Cannot seek outside of the valid range",nameof(origin)); Position = newPos; ResetConsumedMessageSize(); CountConsumedMessageBytes(Position); } public override ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { var count = Math.Min(Length - Position, length); Buffer.BlockCopy(Bytes, Position, buffer, offset, count); Position += count; CountConsumedMessageBytes(count); return new ValueTask(count); } public override Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) { return WriteAsync(buffer, 0, buffer.Length, cancellationToken); } public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { var free = Length - Position; Length = Length + count - free; Buffer.BlockCopy(buffer, offset, Bytes, Position, count); Position += count; return Task.CompletedTask; } public override Task FlushAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); ResetConsumedMessageSize(); return Task.CompletedTask; } public byte[] GetBuffer() { var retval = new byte[Length]; Buffer.BlockCopy(Bytes, 0, retval, 0, Length); return retval; } internal bool TryGetBuffer(out ArraySegment bufSegment) { bufSegment = new ArraySegment(Bytes, 0, _bytesUsed); return true; } // IDisposable protected override void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { // nothing to do } } IsDisposed = true; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs0000644000000000000000000000764214303740367025463 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming public class TStreamTransport : TEndpointTransport { private bool _isDisposed; protected TStreamTransport(TConfiguration config) :base(config) { } public TStreamTransport(Stream inputStream, Stream outputStream, TConfiguration config) : base(config) { InputStream = inputStream; OutputStream = outputStream; } protected Stream OutputStream { get; set; } private Stream _InputStream = null; protected Stream InputStream { get => _InputStream; set { _InputStream = value; ResetConsumedMessageSize(); } } public override bool IsOpen => true; public override Task OpenAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override void Close() { if (InputStream != null) { InputStream.Dispose(); InputStream = null; } if (OutputStream != null) { OutputStream.Dispose(); OutputStream = null; } } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (InputStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot read from null inputstream"); } #if NETSTANDARD2_0 return await InputStream.ReadAsync(buffer, offset, length, cancellationToken); #else return await InputStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); #endif } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (OutputStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot write to null outputstream"); } #if NETSTANDARD2_0 await OutputStream.WriteAsync(buffer, offset, length, cancellationToken); #else await OutputStream.WriteAsync(buffer.AsMemory(offset, length), cancellationToken); #endif } public override async Task FlushAsync(CancellationToken cancellationToken) { await OutputStream.FlushAsync(cancellationToken); ResetConsumedMessageSize(); } // IDisposable protected override void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { InputStream?.Dispose(); OutputStream?.Dispose(); } } _isDisposed = true; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs0000644000000000000000000002014514370300523025437 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming public class TSocketTransport : TStreamTransport { private bool _isDisposed; public TSocketTransport(TcpClient client, TConfiguration config) : base(config) { TcpClient = client ?? throw new ArgumentNullException(nameof(client)); SetInputOutputStream(); } /// /// The constructor for a TSocketTransport which takes an IPAddress object. /// /// The IP address. /// The TcpClient port number. /// The . /// The TcpClient send timeout. /// /// The TcpClient is not connected automatically. You are required to use . /// public TSocketTransport(IPAddress host, int port, TConfiguration config, int timeout = 0) : base(config) { Host = host; Port = port; TcpClient = new TcpClient(); TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; TcpClient.Client.NoDelay = true; SetInputOutputStream(); } /// /// The constructor for a TSocketTransport which takes either a host name, e.g. 'host.example.com' and port number. /// If host is not found using Dns.GetHostEntry(host) an exception will be thrown. /// /// The host name. /// The TcpClient port number. /// The . /// The TcpClient send timeout. /// /// /// The TcpClient is connected automatically. /// public TSocketTransport(string host, int port, TConfiguration config, int timeout = 0) : base(config) { try { var entry = Dns.GetHostEntry(host); if (entry.AddressList.Length == 0) throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); Host = entry.AddressList[0]; Port = port; TcpClient = new TcpClient(host, port); TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; TcpClient.Client.NoDelay = true; SetInputOutputStream(); } catch (SocketException e) { throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); } } /// /// The constructor for a TSocketTransport which takes either a host name, e.g. 'host.example.com' or and IP address string, e.g '123.456.789' and port number. /// If hostNameOrIpAddress represents a valid IP address this will be used directly. /// If hostNameOrIpAddress does not represent a valid IP address an IP address will be retrieved using Dns.GetHostEntry(hostNameOrIpAddress). /// If that fails an exception will be thrown. /// /// The host name or IP address. /// The TcpClient port number. /// If true attempt to connect the TcpClient. /// The . /// The TcpClient send timeout. /// /// /// The TcpClient is connected dependent on the value of ./>. /// public TSocketTransport(string hostNameOrIpAddress, int port, bool connectClient, TConfiguration config, int timeout = 0) : base(config) { try { if (!IPAddress.TryParse(hostNameOrIpAddress, out var address)) { var entry = Dns.GetHostEntry(hostNameOrIpAddress); if (entry.AddressList.Length == 0) throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); address = entry.AddressList[0]; } Host = address; Port = port; TcpClient = new TcpClient(); TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; TcpClient.Client.NoDelay = true; if (connectClient) { TcpClient.Connect(Host, Port); } SetInputOutputStream(); } catch (SocketException e) { throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); } } private void SetInputOutputStream() { if (IsOpen) { InputStream = TcpClient.GetStream(); OutputStream = TcpClient.GetStream(); } } public TcpClient TcpClient { get; private set; } public IPAddress Host { get; } public int Port { get; } public int Timeout { set { if (TcpClient != null) { TcpClient.ReceiveTimeout = TcpClient.SendTimeout = value; } } } public override bool IsOpen { get { return (TcpClient != null) && TcpClient.Connected; } } public override async Task OpenAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (IsOpen) { throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); } if (Port <= 0) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); } if (TcpClient == null) { throw new InvalidOperationException("Invalid or not initialized tcp client"); } await TcpClient.ConnectAsync(Host, Port); SetInputOutputStream(); } public override void Close() { base.Close(); if (TcpClient != null) { TcpClient.Dispose(); TcpClient = null; } } // IDisposable protected override void Dispose(bool disposing) { if (!_isDisposed) { if (disposing) { TcpClient?.Dispose(); base.Dispose(disposing); } } _isDisposed = true; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs0000644000000000000000000002257514303740367026145 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport.Client { //TODO: check for correct work // ReSharper disable once InconsistentNaming public class TTlsSocketTransport : TStreamTransport { private readonly X509Certificate2 _certificate; private readonly RemoteCertificateValidationCallback _certValidator; private readonly IPAddress _host; private readonly bool _isServer; private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; private readonly int _port; private readonly SslProtocols _sslProtocols; private readonly string _targetHost; private TcpClient _client; private SslStream _secureStream; private int _timeout; public TTlsSocketTransport(TcpClient client, TConfiguration config, X509Certificate2 certificate, bool isServer = false, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : base(config) { _client = client; _certificate = certificate; _certValidator = certValidator; _localCertificateSelectionCallback = localCertificateSelectionCallback; _sslProtocols = sslProtocols; _isServer = isServer; if (isServer && certificate == null) { throw new ArgumentException("TTlsSocketTransport needs certificate to be used for server", nameof(certificate)); } if (IsOpen) { InputStream = client.GetStream(); OutputStream = client.GetStream(); } } public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, string certificatePath, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : this(host, port, config, 0, new X509Certificate2(certificatePath), certValidator, localCertificateSelectionCallback, sslProtocols) { } public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, X509Certificate2 certificate = null, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : this(host, port, config, 0, certificate, certValidator, localCertificateSelectionCallback, sslProtocols) { } public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, int timeout, X509Certificate2 certificate, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : base(config) { _host = host; _port = port; _timeout = timeout; _certificate = certificate; _certValidator = certValidator; _localCertificateSelectionCallback = localCertificateSelectionCallback; _sslProtocols = sslProtocols; InitSocket(); } public TTlsSocketTransport(string host, int port, TConfiguration config, int timeout, X509Certificate2 certificate, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : base(config) { try { _targetHost = host; var entry = Dns.GetHostEntry(host); if (entry.AddressList.Length == 0) throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); _host = entry.AddressList[0]; _port = port; _timeout = timeout; _certificate = certificate; _certValidator = certValidator; _localCertificateSelectionCallback = localCertificateSelectionCallback; _sslProtocols = sslProtocols; InitSocket(); } catch (SocketException e) { throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); } } public int Timeout { set { _client.ReceiveTimeout = _client.SendTimeout = _timeout = value; } } public TcpClient TcpClient => _client; public IPAddress Host => _host; public int Port => _port; public override bool IsOpen { get { if (_client == null) { return false; } return _client.Connected; } } private void InitSocket() { _client = new TcpClient(); _client.ReceiveTimeout = _client.SendTimeout = _timeout; _client.Client.NoDelay = true; } private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors) { return sslValidationErrors == SslPolicyErrors.None; } public override async Task OpenAsync(CancellationToken cancellationToken) { if (IsOpen) { throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); } if (_host == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); } if (_port <= 0) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); } if (_client == null) { InitSocket(); } if (_client != null) { await _client.ConnectAsync(_host, _port); await SetupTlsAsync(); } } public async Task SetupTlsAsync() { var validator = _certValidator ?? DefaultCertificateValidator; if (_localCertificateSelectionCallback != null) { _secureStream = new SslStream(_client.GetStream(), false, validator, _localCertificateSelectionCallback); } else { _secureStream = new SslStream(_client.GetStream(), false, validator); } try { if (_isServer) { // Server authentication await _secureStream.AuthenticateAsServerAsync(_certificate, _certValidator != null, _sslProtocols, true); } else { // Client authentication var certs = _certificate != null ? new X509CertificateCollection {_certificate} : new X509CertificateCollection(); var targetHost = _targetHost ?? _host.ToString(); await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true); } } catch (Exception) { Close(); throw; } InputStream = _secureStream; OutputStream = _secureStream; } public override void Close() { base.Close(); if (_client != null) { _client.Dispose(); _client = null; } if (_secureStream != null) { _secureStream.Dispose(); _secureStream = null; } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/TEndpointTransport.cs0000644000000000000000000000753314370300523024557 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace Thrift.Transport { abstract public class TEndpointTransport : TTransport { protected long MaxMessageSize { get => Configuration.MaxMessageSize; } protected long KnownMessageSize { get; private set; } protected long RemainingMessageSize { get; private set; } private readonly TConfiguration _configuration; public override TConfiguration Configuration { get => _configuration; } public TEndpointTransport( TConfiguration config) { _configuration = config ?? new TConfiguration(); Debug.Assert(Configuration != null); ResetConsumedMessageSize(); } /// /// Resets RemainingMessageSize to the configured maximum /// public override void ResetConsumedMessageSize(long newSize = -1) { // full reset if (newSize < 0) { KnownMessageSize = MaxMessageSize; RemainingMessageSize = MaxMessageSize; return; } // update only: message size can shrink, but not grow Debug.Assert(KnownMessageSize <= MaxMessageSize); if (newSize > KnownMessageSize) throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); KnownMessageSize = newSize; RemainingMessageSize = newSize; } /// /// Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). /// Will throw if we already consumed too many bytes or if the new size is larger than allowed. /// /// public override void UpdateKnownMessageSize(long size) { var consumed = KnownMessageSize - RemainingMessageSize; ResetConsumedMessageSize(size); CountConsumedMessageBytes(consumed); } /// /// Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data /// /// public override void CheckReadBytesAvailable(long numBytes) { if (RemainingMessageSize < numBytes) throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); } /// /// Consumes numBytes from the RemainingMessageSize. /// /// protected void CountConsumedMessageBytes(long numBytes) { if (RemainingMessageSize >= numBytes) { RemainingMessageSize -= numBytes; } else { RemainingMessageSize = 0; throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/TTransport.cs0000644000000000000000000001312214370300523023045 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport { //TODO: think about client info // ReSharper disable once InconsistentNaming public abstract class TTransport : IDisposable { //TODO: think how to avoid peek byte private readonly byte[] _peekBuffer = new byte[1]; private bool _hasPeekByte; public abstract bool IsOpen { get; } public abstract TConfiguration Configuration { get; } public abstract void UpdateKnownMessageSize(long size); public abstract void CheckReadBytesAvailable(long numBytes); public abstract void ResetConsumedMessageSize(long newSize = -1); public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public async ValueTask PeekAsync(CancellationToken cancellationToken) { //If we already have a byte read but not consumed, do nothing. if (_hasPeekByte) { return true; } //If transport closed we can't peek. if (!IsOpen) { return false; } //Try to read one byte. If succeeds we will need to store it for the next read. try { var bytes = await ReadAsync(_peekBuffer, 0, 1, cancellationToken); if (bytes == 0) { return false; } } catch (IOException) { return false; } _hasPeekByte = true; return true; } public abstract Task OpenAsync(CancellationToken cancellationToken = default); public abstract void Close(); protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) { if (buffer == null) { throw new ArgumentNullException(nameof(buffer)); } #if DEBUG // let it fail with OutOfRange in RELEASE mode if (offset < 0) { throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset must be >= 0"); } if (length < 0) { throw new ArgumentOutOfRangeException(nameof(length), "Buffer length must be >= 0"); } if (offset + length > buffer.Length) { throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data"); } #endif } public abstract ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); ValidateBufferArgs(buffer, offset, length); if (length <= 0) return 0; // If we previously peeked a byte, we need to use that first. var totalBytes = 0; if (_hasPeekByte) { buffer[offset++] = _peekBuffer[0]; _hasPeekByte = false; if (1 == length) { return 1; // we're done } ++totalBytes; } var remaining = length - totalBytes; Debug.Assert(remaining > 0); // any other possible cases should have been handled already while (true) { var numBytes = await ReadAsync(buffer, offset, remaining, cancellationToken); totalBytes += numBytes; if (totalBytes >= length) { return totalBytes; // we're done } if (numBytes <= 0) { throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "Cannot read, Remote side has closed"); } remaining -= numBytes; offset += numBytes; } } public virtual async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) { await WriteAsync(buffer, 0, buffer.Length, CancellationToken.None); } public virtual async Task WriteAsync(byte[] buffer, int offset, int length) { await WriteAsync(buffer, offset, length, CancellationToken.None); } public abstract Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); public abstract Task FlushAsync(CancellationToken cancellationToken); protected abstract void Dispose(bool disposing); } } thrift-0.19.0/lib/netstd/Thrift/Transport/Layered/0000777000000000000000000000000014370300523021770 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs0000644000000000000000000001505514370300523025560 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Buffers.Binary; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport { // ReSharper disable once InconsistentNaming public class TFramedTransport : TLayeredTransport { private const int HeaderSize = 4; private readonly byte[] HeaderBuf = new byte[HeaderSize]; private readonly Client.TMemoryBufferTransport ReadBuffer; private readonly Client.TMemoryBufferTransport WriteBuffer; private bool IsDisposed; public class Factory : TTransportFactory { public override TTransport GetTransport(TTransport trans) { return new TFramedTransport(trans); } } public TFramedTransport(TTransport transport) : base(transport) { ReadBuffer = new Client.TMemoryBufferTransport(Configuration); WriteBuffer = new Client.TMemoryBufferTransport(Configuration); InitWriteBuffer(); } public override bool IsOpen => !IsDisposed && InnerTransport.IsOpen; public override async Task OpenAsync(CancellationToken cancellationToken) { CheckNotDisposed(); await InnerTransport.OpenAsync(cancellationToken); } public override void Close() { CheckNotDisposed(); InnerTransport.Close(); } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); ValidateBufferArgs(buffer, offset, length); if (!IsOpen) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } // Read another frame of data if we run out of bytes if (ReadBuffer.Position >= ReadBuffer.Length) { await ReadFrameAsync(cancellationToken); } return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); } private async ValueTask ReadFrameAsync(CancellationToken cancellationToken) { UpdateKnownMessageSize(-1); await InnerTransport.ReadAllAsync(HeaderBuf, 0, HeaderSize, cancellationToken); int size = BinaryPrimitives.ReadInt32BigEndian(HeaderBuf); if ((0 > size) || (size > Configuration.MaxFrameSize)) // size must be in the range 0 to allowed max throw new TTransportException(TTransportException.ExceptionType.Unknown, $"Maximum frame size exceeded ({size} bytes)"); UpdateKnownMessageSize(size + HeaderSize); ReadBuffer.SetLength(size); ReadBuffer.Seek(0, SeekOrigin.Begin); ReadBuffer.TryGetBuffer(out ArraySegment bufSegment); await InnerTransport.ReadAllAsync(bufSegment.Array, 0, size, cancellationToken); } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); ValidateBufferArgs(buffer, offset, length); if (!IsOpen) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } if (WriteBuffer.Length > (int.MaxValue - length)) { await FlushAsync(cancellationToken); } await WriteBuffer.WriteAsync(buffer, offset, length, cancellationToken); } public override async Task FlushAsync(CancellationToken cancellationToken) { CheckNotDisposed(); if (!IsOpen) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } WriteBuffer.TryGetBuffer(out ArraySegment bufSegment); int dataLen = bufSegment.Count - HeaderSize; if (dataLen < 0) { throw new InvalidOperationException(); // logic error actually } // Inject message header into the reserved buffer space BinaryPrimitives.WriteInt32BigEndian(bufSegment.Array, dataLen); // Send the entire message at once await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); InitWriteBuffer(); await InnerTransport.FlushAsync(cancellationToken); } private void InitWriteBuffer() { // Reserve space for message header to be put right before sending it out WriteBuffer.SetLength(HeaderSize); WriteBuffer.Seek(0, SeekOrigin.End); } public override void CheckReadBytesAvailable(long numBytes) { var buffered = ReadBuffer.Length - ReadBuffer.Position; if (buffered < numBytes) { numBytes -= buffered; InnerTransport.CheckReadBytesAvailable(numBytes); } } private void CheckNotDisposed() { if (IsDisposed) { throw new ObjectDisposedException(this.GetType().Name); } } // IDisposable protected override void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { ReadBuffer?.Dispose(); WriteBuffer?.Dispose(); InnerTransport?.Dispose(); } } IsDisposed = true; } public override void ResetConsumedMessageSize(long newSize = -1) { base.ResetConsumedMessageSize(newSize); ReadBuffer.ResetConsumedMessageSize(newSize); } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs0000644000000000000000000001606614370300523026107 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport { // ReSharper disable once InconsistentNaming public class TBufferedTransport : TLayeredTransport { private readonly int DesiredBufferSize; private readonly Client.TMemoryBufferTransport ReadBuffer; private readonly Client.TMemoryBufferTransport WriteBuffer; private bool IsDisposed; public class Factory : TTransportFactory { public override TTransport GetTransport(TTransport trans) { return new TBufferedTransport(trans); } } //TODO: should support only specified input transport? public TBufferedTransport(TTransport transport, int bufSize = 1024) : base(transport) { if (bufSize <= 0) { throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); } DesiredBufferSize = bufSize; WriteBuffer = new Client.TMemoryBufferTransport(InnerTransport.Configuration, bufSize); ReadBuffer = new Client.TMemoryBufferTransport(InnerTransport.Configuration, bufSize); Debug.Assert(DesiredBufferSize == ReadBuffer.Capacity); Debug.Assert(DesiredBufferSize == WriteBuffer.Capacity); } public TTransport UnderlyingTransport { get { CheckNotDisposed(); return InnerTransport; } } public override bool IsOpen => !IsDisposed && InnerTransport.IsOpen; public override async Task OpenAsync(CancellationToken cancellationToken) { CheckNotDisposed(); await InnerTransport.OpenAsync(cancellationToken); } public override void Close() { CheckNotDisposed(); InnerTransport.Close(); } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); ValidateBufferArgs(buffer, offset, length); if (!IsOpen) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } // do we have something buffered? var count = ReadBuffer.Length - ReadBuffer.Position; if (count > 0) { return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); } // does the request even fit into the buffer? // Note we test for >= instead of > to avoid nonsense buffering if (length >= ReadBuffer.Capacity) { return await InnerTransport.ReadAsync(buffer, offset, length, cancellationToken); } // buffer a new chunk of bytes from the underlying transport ReadBuffer.Length = ReadBuffer.Capacity; ReadBuffer.TryGetBuffer(out ArraySegment bufSegment); ReadBuffer.Length = await InnerTransport.ReadAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); ReadBuffer.Position = 0; // deliver the bytes return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); ValidateBufferArgs(buffer, offset, length); if (!IsOpen) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } // enough space left in buffer? var free = WriteBuffer.Capacity - WriteBuffer.Length; if (length > free) { WriteBuffer.TryGetBuffer(out ArraySegment bufSegment); await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); WriteBuffer.SetLength(0); } // do the data even fit into the buffer? // Note we test for < instead of <= to avoid nonsense buffering if (length < WriteBuffer.Capacity) { await WriteBuffer.WriteAsync(buffer, offset, length, cancellationToken); return; } // write thru await InnerTransport.WriteAsync(buffer, offset, length, cancellationToken); } public override async Task FlushAsync(CancellationToken cancellationToken) { CheckNotDisposed(); if (!IsOpen) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } if (WriteBuffer.Length > 0) { WriteBuffer.TryGetBuffer(out ArraySegment bufSegment); await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); WriteBuffer.SetLength(0); } await InnerTransport.FlushAsync(cancellationToken); } public override void CheckReadBytesAvailable(long numBytes) { var buffered = ReadBuffer.Length - ReadBuffer.Position; if (buffered < numBytes) { numBytes -= buffered; InnerTransport.CheckReadBytesAvailable(numBytes); } } public override void ResetConsumedMessageSize(long newSize = -1) { base.ResetConsumedMessageSize(newSize); ReadBuffer.ResetConsumedMessageSize(newSize); } private void CheckNotDisposed() { if (IsDisposed) { throw new ObjectDisposedException(nameof(InnerTransport)); } } // IDisposable protected override void Dispose(bool disposing) { if (!IsDisposed) { if (disposing) { ReadBuffer?.Dispose(); WriteBuffer?.Dispose(); InnerTransport?.Dispose(); } } IsDisposed = true; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs0000644000000000000000000000330614370300523025743 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Text; namespace Thrift.Transport { public abstract class TLayeredTransport : TTransport { public readonly TTransport InnerTransport; public override TConfiguration Configuration { get => InnerTransport.Configuration; } public TLayeredTransport(TTransport transport) { InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); } public override void UpdateKnownMessageSize(long size) { InnerTransport.UpdateKnownMessageSize(size); } public override void CheckReadBytesAvailable(long numBytes) { InnerTransport.CheckReadBytesAvailable(numBytes); } public override void ResetConsumedMessageSize(long newSize = -1) { InnerTransport.ResetConsumedMessageSize(newSize); } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Server/0000777000000000000000000000000014452237057021665 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Thrift/Transport/Server/NullLogger.cs0000644000000000000000000000321514303740367024261 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using Microsoft.Extensions.Logging; using System; namespace Thrift.Transport.Server { // sometimes we just don't want to log anything internal class NullLogger : IDisposable, ILogger, ILogger { internal class NullScope : IDisposable { public void Dispose() { // nothing to do } } public IDisposable BeginScope(TState state) { return new NullScope(); } public void Dispose() { // nothing to do } public bool IsEnabled(LogLevel logLevel) { return false; // no } public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { // do nothing } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Server/TServerTransport.cs0000644000000000000000000000352314303740367025520 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Threading; using System.Threading.Tasks; namespace Thrift.Transport { // ReSharper disable once InconsistentNaming public abstract class TServerTransport { public readonly TConfiguration Configuration; public TServerTransport(TConfiguration config) { Configuration = config ?? new TConfiguration(); } public abstract bool IsOpen(); public abstract void Listen(); public abstract void Close(); public abstract bool IsClientPending(); protected abstract ValueTask AcceptImplementationAsync(CancellationToken cancellationToken = default); public async ValueTask AcceptAsync(CancellationToken cancellationToken = default) { var transport = await AcceptImplementationAsync(cancellationToken); if (transport == null) { throw new TTransportException($"{nameof(AcceptImplementationAsync)} should not return null"); } return transport; } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs0000644000000000000000000001273414303740367026364 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Thrift.Processor; using Thrift.Protocol; using Thrift.Transport.Client; namespace Thrift.Transport.Server { // ReSharper disable once InconsistentNaming public class THttpServerTransport { protected const string ContentType = "application/x-thrift"; /* never used private readonly ILogger _logger; private readonly RequestDelegate _next; */ protected Encoding Encoding = Encoding.UTF8; protected TProtocolFactory InputProtocolFactory; protected TProtocolFactory OutputProtocolFactory; protected TTransportFactory InputTransportFactory; protected TTransportFactory OutputTransportFactory; protected ITAsyncProcessor Processor; protected TConfiguration Configuration; public THttpServerTransport( ITAsyncProcessor processor, TConfiguration config, RequestDelegate next = null, ILoggerFactory loggerFactory = null) : this(processor, config, new TBinaryProtocol.Factory(), null, next, loggerFactory) { } public THttpServerTransport( ITAsyncProcessor processor, TConfiguration config, TProtocolFactory protocolFactory, TTransportFactory transFactory = null, RequestDelegate next = null, ILoggerFactory loggerFactory = null) : this(processor, config, protocolFactory, protocolFactory, transFactory, transFactory, next, loggerFactory) { } public THttpServerTransport( ITAsyncProcessor processor, TConfiguration config, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, TTransportFactory inputTransFactory = null, TTransportFactory outputTransFactory = null, RequestDelegate next = null, ILoggerFactory loggerFactory = null) { // loggerFactory == null is not illegal anymore Processor = processor ?? throw new ArgumentNullException(nameof(processor)); Configuration = config; // may be null InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); InputTransportFactory = inputTransFactory; OutputTransportFactory = outputTransFactory; // never used _ = next; _ = loggerFactory; /* never used _next = next; _logger = (loggerFactory != null) ? loggerFactory.CreateLogger() : new NullLogger(); */ } public async Task Invoke(HttpContext context) { await ProcessRequestAsync(context, context.RequestAborted); //TODO: check for correct logic } public async Task ProcessRequestAsync(HttpContext context, CancellationToken cancellationToken) { var transport = new TStreamTransport(context.Request.Body, context.Response.Body, Configuration); try { var intrans = (InputTransportFactory != null) ? InputTransportFactory.GetTransport(transport) : transport; var outtrans = (OutputTransportFactory != null) ? OutputTransportFactory.GetTransport(transport) : transport; var input = InputProtocolFactory.GetProtocol(intrans); var output = OutputProtocolFactory.GetProtocol(outtrans); context.Response.ContentType = ContentType; while (await Processor.ProcessAsync(input, output, cancellationToken)) { if (!context.Response.HasStarted) // oneway method called await context.Response.Body.FlushAsync(cancellationToken); } } catch (TTransportException) { if (!context.Response.HasStarted) // if something goes bust, let the client know context.Response.StatusCode = 500; // internal server error } catch (TProtocolException) { if (!context.Response.HasStarted) // if something goes bust, let the client know context.Response.StatusCode = 400; // bad request, e.g. required field missing } finally { transport.Close(); } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs0000644000000000000000000001231114370300523026652 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; using Thrift.Transport.Client; namespace Thrift.Transport.Server { // ReSharper disable once InconsistentNaming public class TServerSocketTransport : TServerTransport { private readonly int _clientTimeout; private TcpListener _server; public TServerSocketTransport(TcpListener listener, TConfiguration config, int clientTimeout = 0) : base(config) { _server = listener; _clientTimeout = clientTimeout; } public TServerSocketTransport(int port, TConfiguration config, int clientTimeout = 0) : this(null, config, clientTimeout) { try { // Make server socket _server = new TcpListener(IPAddress.IPv6Any, port); _server.Server.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false); _server.Server.NoDelay = true; } catch (Exception) { _server = null; throw new TTransportException("Could not create ServerSocket on port " + port + "."); } } public override bool IsOpen() { return (_server != null) && (_server.Server != null) && _server.Server.IsBound; } public int GetPort() { if ((_server != null) && (_server.Server != null) && (_server.Server.LocalEndPoint != null)) { if (_server.Server.LocalEndPoint is IPEndPoint server) { return server.Port; } else { throw new TTransportException("ServerSocket is not a network socket"); } } else { throw new TTransportException("ServerSocket is not open"); } } public override void Listen() { // Make sure not to block on accept if (_server != null) { try { _server.Start(); } catch (SocketException sx) { throw new TTransportException("Could not accept on listening socket: " + sx.Message); } } } public override bool IsClientPending() { return _server.Pending(); } protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_server == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); } try { TTransport tSocketTransport = null; #if NET6_0_OR_GREATER var tcpClient = await _server.AcceptTcpClientAsync(cancellationToken); #else var tcpClient = await _server.AcceptTcpClientAsync(); #endif try { tSocketTransport = new TSocketTransport(tcpClient, Configuration) { Timeout = _clientTimeout }; return tSocketTransport; } catch (Exception) { if (tSocketTransport != null) { tSocketTransport.Dispose(); } else // Otherwise, clean it up ourselves. { ((IDisposable)tcpClient).Dispose(); } throw; } } catch (Exception ex) { throw new TTransportException(ex.ToString()); } } public override void Close() { if (_server != null) { try { _server.Stop(); } catch (Exception ex) { throw new TTransportException("WARNING: Could not close server socket: " + ex); } _server = null; } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs0000644000000000000000000004112214452237057027302 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using Microsoft.Win32.SafeHandles; using System; using System.IO.Pipes; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.ComponentModel; using System.Security.AccessControl; using System.Security.Principal; using System.Collections.Generic; using System.IO; using System.Diagnostics; #pragma warning disable CS1998 // async no await namespace Thrift.Transport.Server { [Flags] public enum NamedPipeServerFlags { None = 0x00, OnlyLocalClients = 0x01, }; // ReSharper disable once InconsistentNaming public class TNamedPipeServerTransport : TServerTransport { // to manage incoming connections, we set up a task for each stream to listen on private struct TaskStreamPair { public NamedPipeServerStream Stream; public Task Task; public TaskStreamPair(NamedPipeServerStream stream, Task task) { Stream = stream; Task = task; } } /// /// This is the address of the Pipe on the localhost. /// private readonly string _pipeAddress; private bool _asyncMode = true; private volatile bool _isPending = true; private readonly List _streams = new List(); private readonly bool _onlyLocalClients = false; // compatibility default private readonly byte _numListenPipes = 1; // compatibility default public TNamedPipeServerTransport(string pipeAddress, TConfiguration config, NamedPipeServerFlags flags, int numListenPipes) : base(config) { if ((numListenPipes < 1) || (numListenPipes > 254)) throw new ArgumentOutOfRangeException(nameof(numListenPipes), "Value must be in the range of [1..254]"); _pipeAddress = pipeAddress; _onlyLocalClients = flags.HasFlag(NamedPipeServerFlags.OnlyLocalClients); _numListenPipes = (byte)numListenPipes; } public override bool IsOpen() { return true; } public override void Listen() { // nothing to do here } private static void Close(NamedPipeServerStream pipe) { if (pipe != null) { try { if (pipe.IsConnected) pipe.Disconnect(); } finally { pipe.Dispose(); } } } public override void Close() { try { if (_streams != null) { while(_streams.Count > 0) { Close(_streams[0].Stream); _streams.RemoveAt(0); } } } finally { _streams.Clear(); _isPending = false; } } public override bool IsClientPending() { return _isPending; } private void EnsurePipeInstances() { // set up a pool for accepting multiple calls when in multithread mode // once connected, we hand that stream over to the processor and create a fresh one try { while (_streams.Count < _numListenPipes) _streams.Add(CreatePipeInstance()); } catch { // we might not be able to create all requested instances, e.g. due to some existing instances already processing calls // if we have at least one pipe to listen on -> Good Enough(tm) if (_streams.Count < 1) throw; // no pipes is really bad } } private TaskStreamPair CreatePipeInstance() { const PipeDirection direction = PipeDirection.InOut; const int maxconn = NamedPipeServerStream.MaxAllowedServerInstances; const PipeTransmissionMode mode = PipeTransmissionMode.Byte; const int inbuf = 4096; const int outbuf = 4096; var options = _asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; // TODO: "CreatePipeNative" ist only a workaround, and there are have basically two possible outcomes: // - once NamedPipeServerStream() gets a CTOR that supports pipesec, remove CreatePipeNative() // - if 31190 gets resolved before, use _stream.SetAccessControl(pipesec) instead of CreatePipeNative() // EITHER WAY, // - if CreatePipeNative() finally gets removed, also remove "allow unsafe code" from the project settings NamedPipeServerStream instance; try { var handle = CreatePipeNative(_pipeAddress, inbuf, outbuf, _onlyLocalClients); if ((handle != null) && (!handle.IsInvalid)) { instance = new NamedPipeServerStream(PipeDirection.InOut, _asyncMode, false, handle); handle = null; // we don't own it any longer } else { handle?.Dispose(); instance = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf/*, pipesec*/); } } catch (NotImplementedException) // Mono still does not support async, fallback to sync { if (_asyncMode) { options &= (~PipeOptions.Asynchronous); instance = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf); _asyncMode = false; } else { throw; } } // the task gets added later return new TaskStreamPair( instance, null); } #region CreatePipeNative workaround [StructLayout(LayoutKind.Sequential)] internal class SECURITY_ATTRIBUTES { internal int nLength = 0; internal IntPtr lpSecurityDescriptor = IntPtr.Zero; internal int bInheritHandle = 0; } private const string Kernel32 = "kernel32.dll"; [DllImport(Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] internal static extern IntPtr CreateNamedPipe( string lpName, uint dwOpenMode, uint dwPipeMode, uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize, uint nDefaultTimeOut, SECURITY_ATTRIBUTES pipeSecurityDescriptor ); // Workaround: create the pipe via API call // we have to do it this way, since NamedPipeServerStream() for netstd still lacks a few CTORs and/or arguments // and _stream.SetAccessControl(pipesec); only keeps throwing ACCESS_DENIED errors at us // References: // - https://github.com/dotnet/corefx/issues/30170 (closed, continued in 31190) // - https://github.com/dotnet/corefx/issues/31190 System.IO.Pipes.AccessControl package does not work // - https://github.com/dotnet/corefx/issues/24040 NamedPipeServerStream: Provide support for WRITE_DAC // - https://github.com/dotnet/corefx/issues/34400 Have a mechanism for lower privileged user to connect to a privileged user's pipe private static SafePipeHandle CreatePipeNative(string name, int inbuf, int outbuf, bool OnlyLocalClients) { if (! RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return null; // Windows only var pinningHandle = new GCHandle(); try { // owner gets full access, everyone else read/write var pipesec = new PipeSecurity(); using (var currentIdentity = WindowsIdentity.GetCurrent()) { var sidOwner = currentIdentity.Owner; var sidWorld = new SecurityIdentifier(WellKnownSidType.WorldSid, null); pipesec.SetOwner(sidOwner); pipesec.AddAccessRule(new PipeAccessRule(sidOwner, PipeAccessRights.FullControl, AccessControlType.Allow)); pipesec.AddAccessRule(new PipeAccessRule(sidWorld, PipeAccessRights.ReadWrite, AccessControlType.Allow)); } // create a security descriptor and assign it to the security attribs var secAttrs = new SECURITY_ATTRIBUTES(); byte[] sdBytes = pipesec.GetSecurityDescriptorBinaryForm(); pinningHandle = GCHandle.Alloc(sdBytes, GCHandleType.Pinned); unsafe { fixed (byte* pSD = sdBytes) { secAttrs.lpSecurityDescriptor = (IntPtr)pSD; } } // a bunch of constants we will need shortly const uint PIPE_ACCESS_DUPLEX = 0x00000003; const uint FILE_FLAG_OVERLAPPED = 0x40000000; const uint WRITE_DAC = 0x00040000; const uint PIPE_TYPE_BYTE = 0x00000000; const uint PIPE_READMODE_BYTE = 0x00000000; const uint PIPE_UNLIMITED_INSTANCES = 255; const uint PIPE_ACCEPT_REMOTE_CLIENTS = 0x00000000; // Connections from remote clients can be accepted and checked against the security descriptor for the pipe. const uint PIPE_REJECT_REMOTE_CLIENTS = 0x00000008; // Connections from remote clients are automatically rejected. // any extra flags we want to add uint dwPipeModeXtra = (OnlyLocalClients ? PIPE_REJECT_REMOTE_CLIENTS : PIPE_ACCEPT_REMOTE_CLIENTS) ; // create the pipe via API call var rawHandle = CreateNamedPipe( @"\\.\pipe\" + name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | dwPipeModeXtra, PIPE_UNLIMITED_INSTANCES, (uint)inbuf, (uint)outbuf, 5 * 1000, secAttrs ); // make a SafePipeHandle() from it var handle = new SafePipeHandle(rawHandle, true); if (handle.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error()); // return it (to be packaged) return handle; } finally { if (pinningHandle.IsAllocated) pinningHandle.Free(); } } #endregion protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { try { EnsurePipeInstances(); // fill the list and wait for any task to be completed var tasks = new List(); for (var i = 0; i < _streams.Count; ++i) { if (_streams[i].Task == null) { var pair = _streams[i]; pair.Task = Task.Run(async () => await pair.Stream.WaitForConnectionAsync(cancellationToken), cancellationToken); _streams[i] = pair; } tasks.Add(_streams[i].Task); } // there must be an exact mapping between task index and stream index Debug.Assert(_streams.Count == tasks.Count); var index = Task.WaitAny(tasks.ToArray(), cancellationToken); var trans = new ServerTransport(_streams[index].Stream, Configuration); _streams.RemoveAt(index); // pass stream ownership to ServerTransport return trans; } catch (TTransportException) { Close(); throw; } catch (TaskCanceledException) { Close(); throw; // let it bubble up } catch (Exception e) { Close(); throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message); } } private class ServerTransport : TEndpointTransport { private NamedPipeServerStream PipeStream; public ServerTransport(NamedPipeServerStream stream, TConfiguration config) : base(config) { PipeStream = stream; } public override bool IsOpen => PipeStream != null && PipeStream.IsConnected; public override Task OpenAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); return Task.CompletedTask; } public override void Close() { if (PipeStream != null) { if (PipeStream.IsConnected) PipeStream.Disconnect(); PipeStream.Dispose(); PipeStream = null; } } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } CheckReadBytesAvailable(length); #if NETSTANDARD2_0 var numBytes = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); #else var numBytes = await PipeStream.ReadAsync(buffer.AsMemory(offset, length), cancellationToken); #endif CountConsumedMessageBytes(numBytes); return numBytes; } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } // if necessary, send the data in chunks // there's a system limit around 0x10000 bytes that we hit otherwise // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." var nBytes = Math.Min(15 * 4096, length); // 16 would exceed the limit while (nBytes > 0) { #if NET5_0_OR_GREATER await PipeStream.WriteAsync(buffer.AsMemory(offset, nBytes), cancellationToken); #else await PipeStream.WriteAsync(buffer, offset, nBytes, cancellationToken); #endif offset += nBytes; length -= nBytes; nBytes = Math.Min(nBytes, length); } } public override async Task FlushAsync(CancellationToken cancellationToken) { await PipeStream.FlushAsync(cancellationToken); ResetConsumedMessageSize(); } protected override void Dispose(bool disposing) { if (disposing) { if (PipeStream != null) { if (PipeStream.IsConnected) PipeStream.Disconnect(); PipeStream.Dispose(); PipeStream = null; } } } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs0000644000000000000000000001440214303740367027352 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Net; using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Thrift.Transport.Client; namespace Thrift.Transport.Server { // ReSharper disable once InconsistentNaming public class TTlsServerSocketTransport : TServerTransport { private readonly RemoteCertificateValidationCallback _clientCertValidator; private readonly int _clientTimeout = 0; private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; private readonly X509Certificate2 _serverCertificate; private readonly SslProtocols _sslProtocols; private TcpListener _server; public TTlsServerSocketTransport( TcpListener listener, TConfiguration config, X509Certificate2 certificate, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : base(config) { if (!certificate.HasPrivateKey) { throw new TTransportException(TTransportException.ExceptionType.Unknown, "Your server-certificate needs to have a private key"); } _serverCertificate = certificate; _clientCertValidator = clientCertValidator; _localCertificateSelectionCallback = localCertificateSelectionCallback; _sslProtocols = sslProtocols; _server = listener; } public TTlsServerSocketTransport( int port, TConfiguration config, X509Certificate2 certificate, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) : this(null, config, certificate, clientCertValidator, localCertificateSelectionCallback, sslProtocols) { try { // Create server socket _server = new TcpListener(IPAddress.Any, port); _server.Server.NoDelay = true; } catch (Exception) { _server = null; throw new TTransportException($"Could not create ServerSocket on port {port}."); } } public override bool IsOpen() { return (_server != null) && (_server.Server != null) && _server.Server.IsBound; } public int GetPort() { if ((_server != null) && (_server.Server != null) && (_server.Server.LocalEndPoint != null)) { if (_server.Server.LocalEndPoint is IPEndPoint server) { return server.Port; } else { throw new TTransportException("ServerSocket is not a network socket"); } } else { throw new TTransportException("ServerSocket is not open"); } } public override void Listen() { // Make sure accept is not blocking if (_server != null) { try { _server.Start(); } catch (SocketException sx) { throw new TTransportException($"Could not accept on listening socket: {sx.Message}"); } } } public override bool IsClientPending() { return _server.Pending(); } protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (_server == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); } try { #if NET6_0_OR_GREATER var client = await _server.AcceptTcpClientAsync(cancellationToken); #else var client = await _server.AcceptTcpClientAsync(); #endif client.SendTimeout = client.ReceiveTimeout = _clientTimeout; //wrap the client in an SSL Socket passing in the SSL cert var tTlsSocket = new TTlsSocketTransport( client, Configuration, _serverCertificate, true, _clientCertValidator, _localCertificateSelectionCallback, _sslProtocols); await tTlsSocket.SetupTlsAsync(); return tTlsSocket; } catch (Exception ex) { throw new TTransportException(ex.ToString()); } } public override void Close() { if (_server != null) { try { _server.Stop(); } catch (Exception ex) { throw new TTransportException($"WARNING: Could not close server socket: {ex}"); } _server = null; } } } } thrift-0.19.0/lib/netstd/Thrift/Transport/TTransportException.cs0000644000000000000000000000340014303740367024734 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; namespace Thrift.Transport { // ReSharper disable once InconsistentNaming public class TTransportException : TException { public enum ExceptionType { Unknown, NotOpen, AlreadyOpen, TimedOut, EndOfFile, Interrupted } public ExceptionType ExType { get; private set; } public TTransportException() { } public TTransportException(ExceptionType exType, Exception inner = null) : base(string.Empty, inner) { ExType = exType; } public TTransportException(ExceptionType exType, string message, Exception inner = null) : base(message, inner) { ExType = exType; } public TTransportException(string message, Exception inner = null) : base(message, inner) { } public ExceptionType Type => ExType; } }thrift-0.19.0/lib/netstd/Thrift.sln0000644000000000000000000001561414303740367017142 0ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29905.134 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{ED5A45B0-07D1-4507-96B7-83FBD3D031CA}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "Thrift\Thrift.csproj", "{5B501D21-D428-408D-AB5C-32D6F5355294}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.IntegrationTests", "Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj", "{837F4084-AAD7-45F5-BC96-10E05A669DB4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "Tests\Thrift.Tests\Thrift.Tests.csproj", "{0790D388-1A3C-4423-8CF2-C97074A8B68B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{A6AE021D-61CB-4D84-A103-0B663C62AE2C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{BF7B896B-8BB6-447C-84F8-26871882A14A}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.Benchmarks", "Benchmarks\Thrift.Benchmarks\Thrift.Benchmarks.csproj", "{D0559DFF-6632-446C-9EFC-C750DA20B1D9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|Any CPU.Build.0 = Debug|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x64.ActiveCfg = Debug|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x64.Build.0 = Debug|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x86.ActiveCfg = Debug|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x86.Build.0 = Debug|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|Any CPU.ActiveCfg = Release|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|Any CPU.Build.0 = Release|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x64.ActiveCfg = Release|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x64.Build.0 = Release|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x86.ActiveCfg = Release|Any CPU {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x86.Build.0 = Release|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x64.ActiveCfg = Debug|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x64.Build.0 = Debug|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x86.ActiveCfg = Debug|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x86.Build.0 = Debug|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|Any CPU.Build.0 = Release|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x64.ActiveCfg = Release|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x64.Build.0 = Release|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x86.ActiveCfg = Release|Any CPU {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x86.Build.0 = Release|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|Any CPU.Build.0 = Debug|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x64.ActiveCfg = Debug|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x64.Build.0 = Debug|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x86.ActiveCfg = Debug|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x86.Build.0 = Debug|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|Any CPU.ActiveCfg = Release|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|Any CPU.Build.0 = Release|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x64.ActiveCfg = Release|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x64.Build.0 = Release|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x86.ActiveCfg = Release|Any CPU {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x86.Build.0 = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x64.ActiveCfg = Debug|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x64.Build.0 = Debug|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x86.ActiveCfg = Debug|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x86.Build.0 = Debug|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|Any CPU.Build.0 = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x64.ActiveCfg = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x64.Build.0 = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x86.ActiveCfg = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x86.Build.0 = Release|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x64.ActiveCfg = Debug|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x64.Build.0 = Debug|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x86.ActiveCfg = Debug|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x86.Build.0 = Debug|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|Any CPU.Build.0 = Release|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x64.ActiveCfg = Release|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x64.Build.0 = Release|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x86.ActiveCfg = Release|Any CPU {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {837F4084-AAD7-45F5-BC96-10E05A669DB4} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} {0790D388-1A3C-4423-8CF2-C97074A8B68B} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} {A6AE021D-61CB-4D84-A103-0B663C62AE2C} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} {D0559DFF-6632-446C-9EFC-C750DA20B1D9} = {BF7B896B-8BB6-447C-84F8-26871882A14A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9} EndGlobalSection EndGlobal thrift-0.19.0/lib/netstd/Directory.Build.props0000644000000000000000000000024614303740367021246 0ustar00rootroot00000000000000 thrift-0.19.0/lib/netstd/README.md0000644000000000000000000000651714303740367016445 0ustar00rootroot00000000000000# Apache Thrift netstd Thrift client library for Microsoft .NET Standard # Build the library ## How to build on Windows - Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable - Open the Thrift.sln project with Visual Studio and build. or - Build with scripts ## How to build on Unix/Linux - Ensure you have .NET Core SDK 3.1 (LTS) installed, or use the [Ubuntu docker image](../../build/docker/README.md) - Follow common automake build practice: `./ bootstrap && ./ configure && make` ## Known issues - In trace logging mode you can see some not important internal exceptions # Migration to netstd ## ... from netcore If you are migrating your code from netcore library, you will have to: - Switch to `thrift -gen netstd` - the following compiler flags are no longer needed or supported: `hashcode` is now standard, while `nullable` is no longer supported. - the `Thrift.Transport` and `Thrift.Protocol` namespaces now use the singular form - add `using Thrift.Processor;` in the server code where appropriate - rename all `T*ClientTransport` to `T*Transport` - rename all `TBaseServer` occurrences in your code to `TServer` - the `SingletonTProcessorFactory` is now called `TSingletonProcessorFactory` - and the `AsyncBaseServer` is now the `TSimpleAsyncServer` You may wonder why we changed so many names. The naming scheme has been revised for two reasons: First, we want to get back the established, well-known naming consistency across the Thrift libraries which the netcore library did not fully respect. Second, by achieving that first objective, we get the additional benefit of making migration at least a bit easier for C# projects. ## ... from csharp Because of the different environment requirements, migration from C# takes slightly more efforts. While the code changes related to Thrift itself are moderate, you may need to upgrade certain dependencies, components or even modules to more recent versions. 1. Client and server applications must use at least framework 4.6.1, any version below will not work. 1. Switch to `thrift -gen netstd`. The following compiler flags are no longer needed or supported: `hashcode` and `async` are now standard, while `nullable` is no longer supported. 1. [Familiarize yourself with the `async/await` model](https://msdn.microsoft.com/en-us/magazine/jj991977.aspx), if you have not already done so. As netstd does not support `ISync` anymore, async is mandatory. The synchronous model is simply no longer available (that's also the reason why we don't need the `async` flag anymore). 1. Consider proper use of `cancellationToken` parameters. They are optional but may be quite helpful. 1. As you probably already guessed, there are a few names that have been changed: - add `using Thrift.Processor;` in the server code where appropriate - the `TServerSocket` is now called `TServerSocketTransport` - change `IProtocolFactory` into `ITProtocolFactory` - if you are looking for `TSimpleServer`, try `TSimpleAsyncServer` instead - similarly, the `TThreadPoolServer` is now a `TThreadPoolAsyncServer` - the server's `Serve()` method does now `ServeAsync()` - In case you are using Thrift server event handlers: the `SetEventHandler` method now starts with an uppercase letter - and you will also have to revise the method names of all `TServerEventHandler` descendants you have in your code thrift-0.19.0/lib/netstd/build.cmd0000644000000000000000000000166314303740367016747 0ustar00rootroot00000000000000@echo off rem /* rem * Licensed to the Apache Software Foundation (ASF) under one rem * or more contributor license agreements. See the NOTICE file rem * distributed with this work for additional information rem * regarding copyright ownership. The ASF licenses this file rem * to you under the Apache License, Version 2.0 (the rem * "License"); you may not use this file except in compliance rem * with the License. You may obtain a copy of the License at rem * rem * http://www.apache.org/licenses/LICENSE-2.0 rem * rem * Unless required by applicable law or agreed to in writing, rem * software distributed under the License is distributed on an rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY rem * KIND, either express or implied. See the License for the rem * specific language governing permissions and limitations rem * under the License. rem */ setlocal thrift -version dotnet --info dotnet build :eof thrift-0.19.0/lib/netstd/runtests.cmd0000644000000000000000000000204114303740367017526 0ustar00rootroot00000000000000@echo off rem /* rem * Licensed to the Apache Software Foundation (ASF) under one rem * or more contributor license agreements. See the NOTICE file rem * distributed with this work for additional information rem * regarding copyright ownership. The ASF licenses this file rem * to you under the Apache License, Version 2.0 (the rem * "License"); you may not use this file except in compliance rem * with the License. You may obtain a copy of the License at rem * rem * http://www.apache.org/licenses/LICENSE-2.0 rem * rem * Unless required by applicable law or agreed to in writing, rem * software distributed under the License is distributed on an rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY rem * KIND, either express or implied. See the License for the rem * specific language governing permissions and limitations rem * under the License. rem */ setlocal thrift -version dotnet --info dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj :eof thrift-0.19.0/lib/netstd/runtests.sh0000644000000000000000000000170114303740367017377 0ustar00rootroot00000000000000#!/usr/bin/env bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # thrift -version dotnet --info dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj dotnet test Tests\Thrift.Tests\Thrift.Tests.csprojthrift-0.19.0/lib/netstd/Makefile.in0000644000000000000000000006235014472652516017235 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/netstd ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . EXTRA_DIST = \ README.md \ Directory.Build.props \ Benchmarks/Thrift.Benchmarks \ Tests/Thrift.IntegrationTests/Protocols \ Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj \ Tests/Thrift.PublicInterfaces.Compile.Tests \ Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift \ Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift \ Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \ Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \ Tests/Thrift.Tests/Collections \ Tests/Thrift.Tests/DataModel \ Tests/Thrift.Tests/Protocols \ Tests/Thrift.Tests/Transports \ Tests/Thrift.Tests/Thrift.Tests.csproj \ Thrift/.editorconfig \ Thrift/Collections \ Thrift/Processor \ Thrift/Properties \ Thrift/Protocol \ Thrift/Server \ Thrift/GlobalSuppressions.cs \ Thrift/TApplicationException.cs \ Thrift/TBaseClient.cs \ Thrift/TConfiguration.cs \ Thrift/TException.cs \ Thrift/Thrift.csproj \ Thrift/Transport \ Thrift/*.snk \ Thrift.sln \ build.cmd \ build.sh \ runtests.cmd \ runtests.sh all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/netstd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/netstd/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-recursive all-am: Makefile all-local installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ check check-am check-local clean clean-generic clean-libtool \ clean-local cscopelist-am ctags ctags-am distclean \ distclean-generic distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile all-local: $(DOTNETCORE) build -c Release check-local: $(DOTNETCORE) test Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj $(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj clean-local: $(RM) -r Thrift/bin $(RM) -r Thrift/obj $(RM) -r Benchmarks/Thrift.Benchmarks/bin $(RM) -r Benchmarks/Thrift.Benchmarks/obj $(RM) -r Tests/Thrift.Tests/bin $(RM) -r Tests/Thrift.Tests/obj $(RM) -r Tests/Thrift.IntegrationTests/bin $(RM) -r Tests/Thrift.IntegrationTests/obj $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/netstd/build.sh0000644000000000000000000000202714303740367016611 0ustar00rootroot00000000000000#!/usr/bin/env bash # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # #exit if any command fails #set -e thrift --version dotnet --info dotnet build #revision=${TRAVIS_JOB_ID:=1} #revision=$(printf "%04d" $revision) #dotnet pack ./src/PROJECT_NAME -c Release -o ./artifacts --version-suffix=$revision thrift-0.19.0/lib/netstd/Tests/0000755000000000000000000000000014472652662016266 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/0000755000000000000000000000000014472652662020627 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Transports/0000777000000000000000000000000014303740367023003 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Transports/THttpTransportTests.cs0000644000000000000000000000265014303740367027334 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Net.Http; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Transport.Client; namespace Thrift.Tests.Transports { [TestClass] public class THttpTransportTests { [TestMethod] public void THttpTransport_Uses_Configured_ConnectionTimeout_Test() { var client = new HttpClient(); var httpClientTransport = new THttpTransport(client, null) { ConnectTimeout = 5000 }; Assert.IsTrue(client.Timeout.TotalMilliseconds == 5000); Assert.IsTrue(httpClientTransport.ConnectTimeout == 5000); } } } thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Protocols/0000777000000000000000000000000014303740367022610 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs0000644000000000000000000000505714303740367026744 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Protocol; using Thrift.Protocol.Entities; using Thrift.Transport; using Thrift.Transport.Client; namespace Thrift.Tests.Protocols { // ReSharper disable once InconsistentNaming [TestClass] public class TJSONProtocolTests { [TestMethod] public void TJSONProtocol_Can_Create_Instance_Test() { var httpClientTransport = new THttpTransport( new Uri("http://localhost"), null, null, null); var result = new TJSONProtocolWrapper(httpClientTransport); Assert.IsNotNull(result); Assert.IsNotNull(result.WrappedContext); Assert.IsNotNull(result.WrappedReader); Assert.IsNotNull(result.Transport); Assert.IsTrue(result.WrappedRecursionDepth == 0); Assert.IsTrue(result.WrappedRecursionLimit == TConfiguration.DEFAULT_RECURSION_DEPTH); Assert.IsTrue(result.Transport.Equals(httpClientTransport)); Assert.IsTrue(result.WrappedContext.GetType().Name.Equals("JSONBaseContext", StringComparison.OrdinalIgnoreCase)); Assert.IsTrue(result.WrappedReader.GetType().Name.Equals("LookaheadReader", StringComparison.OrdinalIgnoreCase)); } private class TJSONProtocolWrapper : TJsonProtocol { public TJSONProtocolWrapper(TTransport trans) : base(trans) { } public object WrappedContext => Context; public object WrappedReader => Reader; public int WrappedRecursionDepth => RecursionDepth; public int WrappedRecursionLimit => RecursionLimit; } } } thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs0000644000000000000000000001642514303740367030105 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Protocol; using Thrift.Protocol.Entities; using Thrift.Protocol.Utilities; namespace Thrift.Tests.Protocols { [TestClass] public class TJSONProtocolHelperTests { [TestMethod] public void GetTypeNameForTypeId_Test() { // input/output var sets = new List> { new Tuple(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool), new Tuple(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte), new Tuple(TType.I16, TJSONProtocolConstants.TypeNames.NameI16), new Tuple(TType.I32, TJSONProtocolConstants.TypeNames.NameI32), new Tuple(TType.I64, TJSONProtocolConstants.TypeNames.NameI64), new Tuple(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble), new Tuple(TType.String, TJSONProtocolConstants.TypeNames.NameString), new Tuple(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct), new Tuple(TType.Map, TJSONProtocolConstants.TypeNames.NameMap), new Tuple(TType.Set, TJSONProtocolConstants.TypeNames.NameSet), new Tuple(TType.List, TJSONProtocolConstants.TypeNames.NameList), }; foreach (var t in sets) { Assert.IsTrue(TJSONProtocolHelper.GetTypeNameForTypeId(t.Item1) == t.Item2, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}"); } } [TestMethod] [ExpectedException(typeof(TProtocolException))] public void GetTypeNameForTypeId_TStop_Test() { TJSONProtocolHelper.GetTypeNameForTypeId(TType.Stop); } [TestMethod] [ExpectedException(typeof(TProtocolException))] public void GetTypeNameForTypeId_NonExistingTType_Test() { TJSONProtocolHelper.GetTypeNameForTypeId((TType)100); } [TestMethod] public void GetTypeIdForTypeName_Test() { // input/output var sets = new List> { new Tuple(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool), new Tuple(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte), new Tuple(TType.I16, TJSONProtocolConstants.TypeNames.NameI16), new Tuple(TType.I32, TJSONProtocolConstants.TypeNames.NameI32), new Tuple(TType.I64, TJSONProtocolConstants.TypeNames.NameI64), new Tuple(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble), new Tuple(TType.String, TJSONProtocolConstants.TypeNames.NameString), new Tuple(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct), new Tuple(TType.Map, TJSONProtocolConstants.TypeNames.NameMap), new Tuple(TType.Set, TJSONProtocolConstants.TypeNames.NameSet), new Tuple(TType.List, TJSONProtocolConstants.TypeNames.NameList), }; foreach (var t in sets) { Assert.IsTrue(TJSONProtocolHelper.GetTypeIdForTypeName(t.Item2) == t.Item1, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}"); } } [TestMethod] [ExpectedException(typeof(TProtocolException))] public void GetTypeIdForTypeName_TStopTypeName_Test() { TJSONProtocolHelper.GetTypeIdForTypeName(new []{(byte)TType.Stop, (byte)TType.Stop}); } [TestMethod] [ExpectedException(typeof(TProtocolException))] public void GetTypeIdForTypeName_NonExistingTypeName_Test() { TJSONProtocolHelper.GetTypeIdForTypeName(new byte[]{100}); } [TestMethod] [ExpectedException(typeof(TProtocolException))] public void GetTypeIdForTypeName_EmptyName_Test() { TJSONProtocolHelper.GetTypeIdForTypeName(new byte[] {}); } [TestMethod] public void IsJsonNumeric_Test() { // input/output var correctJsonNumeric = "+-.0123456789Ee"; var incorrectJsonNumeric = "AaBcDd/*\\"; var sets = correctJsonNumeric.Select(ch => new Tuple((byte) ch, true)).ToList(); sets.AddRange(incorrectJsonNumeric.Select(ch => new Tuple((byte) ch, false))); foreach (var t in sets) { Assert.IsTrue(TJSONProtocolHelper.IsJsonNumeric(t.Item1) == t.Item2, $"Wrong mapping of Char {t.Item1} to bool: {t.Item2}"); } } [TestMethod] public void ToHexVal_Test() { // input/output var chars = "0123456789abcdef"; var expectedHexValues = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; var sets = chars.Select((ch, i) => new Tuple(ch, expectedHexValues[i])).ToList(); foreach (var t in sets) { var actualResult = TJSONProtocolHelper.ToHexVal((byte)t.Item1); Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of char byte {t.Item1} to it expected hex value: {t.Item2}. Actual hex value: {actualResult}"); } } [TestMethod] [ExpectedException(typeof(TProtocolException))] public void ToHexVal_WrongInputChar_Test() { TJSONProtocolHelper.ToHexVal((byte)'s'); } [TestMethod] public void ToHexChar_Test() { // input/output var hexValues = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; var expectedChars = "0123456789abcdef"; var sets = hexValues.Select((hv, i) => new Tuple(hv, expectedChars[i])).ToList(); foreach (var t in sets) { var actualResult = TJSONProtocolHelper.ToHexChar(t.Item1); Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of hex value {t.Item1} to it expected char: {t.Item2}. Actual hex value: {actualResult}"); } } } }thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Collections/0000777000000000000000000000000014303740367023102 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs0000644000000000000000000002351214303740367027055 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography.Xml; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Collections; namespace Thrift.Tests.Collections { // ReSharper disable once InconsistentNaming [TestClass] public class TCollectionsTests { //TODO: Add tests for IEnumerable with objects and primitive values inside [TestMethod] public void TCollection_List_Equals_Primitive_Test() { var collection1 = new List {1,2,3}; var collection2 = new List {1,2,3}; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_List_Equals_Primitive_Different_Test() { var collection1 = new List { 1, 2, 3 }; var collection2 = new List { 1, 2 }; Assert.IsFalse(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); collection2.Add(4); Assert.IsFalse(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_List_Equals_Objects_Test() { var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; var collection2 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_List_List_Equals_Objects_Test() { var collection1 = new List> { new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; var collection2 = new List> { new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual() } [TestMethod] public void TCollection_List_Equals_OneAndTheSameObject_Test() { var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; var collection2 = collection1; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Set_Equals_Primitive_Test() { var collection1 = new HashSet {1,2,3}; var collection2 = new HashSet {1,2,3}; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Set_Equals_Primitive_Different_Test() { var collection1 = new HashSet { 1, 2, 3 }; var collection2 = new HashSet { 1, 2 }; Assert.IsFalse(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); collection2.Add(4); Assert.IsFalse(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Set_Equals_Objects_Test() { var collection1 = new HashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; var collection2 = new HashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Set_Set_Equals_Objects_Test() { var collection1 = new HashSet> { new HashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; var collection2 = new HashSet> { new HashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual() } [TestMethod] public void TCollection_Set_Equals_OneAndTheSameObject_Test() { var collection1 = new HashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; var collection2 = collection1; // references to one and the same collection Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Map_Equals_Primitive_Test() { var collection1 = new Dictionary { [1] = 1, [2] = 2, [3] = 3 }; var collection2 = new Dictionary { [1] = 1, [2] = 2, [3] = 3 }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Map_Equals_Primitive_Different_Test() { var collection1 = new Dictionary { [1] = 1, [2] = 2, [3] = 3 }; var collection2 = new Dictionary { [1] = 1, [2] = 2 }; Assert.IsFalse(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); collection2[3] = 3; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); collection2[3] = 4; Assert.IsFalse(TCollections.Equals(collection1, collection2)); } [TestMethod] public void TCollection_Map_Equals_Objects_Test() { var collection1 = new Dictionary { [1] = new ExampleClass { X = 1 }, [-1] = new ExampleClass { X = 2 } }; var collection2 = new Dictionary { [1] = new ExampleClass { X = 1 }, [-1] = new ExampleClass { X = 2 } }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] public void TCollection_Map_Map_Equals_Objects_Test() { var collection1 = new Dictionary> { [0] = new Dictionary { [1] = new ExampleClass { X = 1 }, [-1] = new ExampleClass { X = 2 } } }; var collection2 = new Dictionary> { [0] = new Dictionary { [1] = new ExampleClass { X = 1 }, [-1] = new ExampleClass { X = 2 } } }; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual() } [TestMethod] public void TCollection_Map_Equals_OneAndTheSameObject_Test() { var collection1 = new Dictionary { [1] = new ExampleClass { X = 1 }, [-1] = new ExampleClass { X = 2 } }; var collection2 = collection1; Assert.IsTrue(TCollections.Equals(collection1, collection2)); Assert.IsTrue(collection1.SequenceEqual(collection2)); } private class ExampleClass { public int X { get; set; } // all Thrift-generated classes override Equals(), we do just the same public override bool Equals(object? that) { if (that is not ExampleClass other) return false; if (ReferenceEquals(this, other)) return true; return this.X == other.X; } // overriding Equals() requires GetHashCode() as well public override int GetHashCode() { int hashcode = 157; unchecked { hashcode = (hashcode * 397) + X.GetHashCode(); } return hashcode; } } } } thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Collections/THashSetTests.cs0000644000000000000000000000414314303740367026135 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Collections; #pragma warning disable IDE0063 // simplify using namespace Thrift.Tests.Collections { // ReSharper disable once InconsistentNaming [TestClass] public class THashSetTests { [TestMethod] public void THashSet_Equals_Primitive_Test() { const int value = 1; var hashSet = new HashSet {value}; Assert.IsTrue(hashSet.Contains(value)); hashSet.Remove(value); Assert.IsTrue(hashSet.Count == 0); hashSet.Add(value); Assert.IsTrue(hashSet.Contains(value)); hashSet.Clear(); Assert.IsTrue(hashSet.Count == 0); var newArr = new int[1]; hashSet.Add(value); hashSet.CopyTo(newArr, 0); Assert.IsTrue(newArr.Contains(value)); var en = hashSet.GetEnumerator(); en.MoveNext(); Assert.IsTrue((int)en.Current == value); using (var ien = ((IEnumerable)hashSet).GetEnumerator()) { ien.MoveNext(); Assert.IsTrue(ien.Current == value); } } } } thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/DataModel/0000777000000000000000000000000014370300523022444 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs0000644000000000000000000007472414370300523024515 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using OptReqDefTest; using Thrift.Collections; namespace Thrift.Tests.DataModel { // ReSharper disable once InconsistentNaming [TestClass] public class DeepCopyTests { [TestMethod] public void Test_Complex_DeepCopy() { var first = InitializeInstance(new RaceDetails()); VerifyIdenticalContent(first, InitializeInstance(new RaceDetails())); var second = first.DeepCopy(); VerifyIdenticalContent(first, second); ModifyInstance(second,0); VerifyDifferentContent(first, second); VerifyIdenticalContent(first, InitializeInstance(new RaceDetails())); var third = second.DeepCopy(); VerifyIdenticalContent(second, third); ModifyInstance(third,0); VerifyDifferentContent(second, third); VerifyIdenticalContent(first, InitializeInstance(new RaceDetails())); } private RaceDetails? MakeNestedRaceDetails(int nesting) { if (++nesting > 1) return null; var instance = new RaceDetails(); InitializeInstance(instance,nesting); return instance; } private jack? MakeNestedUnion(int nesting) { if (++nesting > 1) return null; var details = new RaceDetails(); InitializeInstance(details,nesting); return new jack.nested_struct(details); } private RaceDetails InitializeInstance(RaceDetails instance, int nesting = 0) { // at init, we intentionally leave all non-required fields unset Assert.IsFalse(instance.__isset.opt_one); Assert.IsFalse(instance.__isset.opt_two); Assert.IsFalse(instance.__isset.opt_three); Assert.IsFalse(instance.__isset.opt_four); Assert.IsFalse(instance.__isset.opt_five); Assert.IsFalse(instance.__isset.opt_six); Assert.IsFalse(instance.__isset.opt_seven); Assert.IsFalse(instance.__isset.opt_eight); Assert.IsFalse(instance.__isset.opt_nine); // set all required to null/default instance.Req_one = default; instance.Req_two = default; instance.Req_three = default; Assert.IsNotNull(instance.Req_four); instance.Req_five = default; instance.Req_six = default; instance.Req_seven = default; instance.Req_eight = default; Assert.IsNotNull(instance.Req_nine); // leave non-required fields unset again Assert.IsFalse(instance.__isset.def_one); Assert.IsFalse(instance.__isset.def_two); Assert.IsFalse(instance.__isset.def_three); Assert.IsFalse(instance.__isset.def_four); Assert.IsFalse(instance.__isset.def_five); Assert.IsFalse(instance.__isset.def_six); Assert.IsFalse(instance.__isset.def_seven); Assert.IsFalse(instance.__isset.def_eight); Assert.IsFalse(instance.__isset.def_nine); // these should have IDL defaults set Assert.IsTrue(instance.__isset.opt_one_with_value); Assert.IsTrue(instance.__isset.opt_two_with_value); Assert.IsTrue(instance.__isset.opt_three_with_value); Assert.IsTrue(instance.__isset.opt_four_with_value); Assert.IsTrue(instance.__isset.opt_five_with_value); Assert.IsTrue(instance.__isset.opt_six_with_value); Assert.IsTrue(instance.__isset.opt_seven_with_value); Assert.IsTrue(instance.__isset.opt_eight_with_value); Assert.IsTrue(instance.__isset.opt_nine_with_value); Assert.AreEqual(instance.Req_one_with_value, (Distance)1); Assert.AreEqual(instance.Req_two_with_value, 2.22); Assert.AreEqual(instance.Req_three_with_value, 3); Assert.AreEqual(instance.Req_four_with_value, "four"); Assert.AreEqual(new Guid("55555555-5555-5555-5555-000000000000"), instance.Req_five_with_value); Assert.IsTrue(instance.Req_six_with_value!.Count == 1); Assert.AreEqual(instance.Req_six_with_value[0], 6 ); Assert.IsTrue(instance.Req_seven_with_value!.Count == 1); Assert.IsTrue(instance.Req_seven_with_value.Contains(7)); Assert.IsTrue(instance.Req_eight_with_value!.Count == 1); Assert.IsTrue(instance.Req_eight_with_value[8] == 8); Assert.AreEqual("nine", Encoding.UTF8.GetString(instance.Req_nine_with_value!)); Assert.IsTrue(instance.__isset.def_one_with_value); Assert.IsTrue(instance.__isset.def_two_with_value); Assert.IsTrue(instance.__isset.def_three_with_value); Assert.IsTrue(instance.__isset.def_four_with_value); Assert.IsTrue(instance.__isset.def_five_with_value); Assert.IsTrue(instance.__isset.def_six_with_value); Assert.IsTrue(instance.__isset.def_seven_with_value); Assert.IsTrue(instance.__isset.def_eight_with_value); Assert.IsTrue(instance.__isset.def_nine_with_value); instance.Last_of_the_mohicans = true; if (nesting < 2) { instance.Far_list = new List() { Distance.foo, Distance.bar, Distance.baz }; instance.Far_set = new HashSet() { Distance.foo, Distance.bar, Distance.baz }; instance.Far_map = new Dictionary() { [Distance.foo] = Distance.foo, [Distance.bar] = Distance.bar, [Distance.baz] = Distance.baz }; instance.Far_set_list = new HashSet>() { new List() { Distance.foo } }; instance.Far_list_map_set = new List>>() { new Dictionary>() { [1] = new HashSet() { Distance.baz } } }; instance.Far_map_dist_to_rds = new Dictionary>() { [Distance.bar] = new List() }; var details = MakeNestedRaceDetails(nesting); if (details != null) instance.Far_map_dist_to_rds[Distance.bar].Add(details); instance.Req_nested = MakeNestedRaceDetails(nesting); Assert.IsFalse(instance.__isset.opt_nested); Assert.IsFalse(instance.__isset.def_nested); instance.Req_union = MakeNestedUnion(nesting); Assert.IsFalse(instance.__isset.opt_union); Assert.IsFalse(instance.__isset.def_union); } instance.Triplesix = (Distance)666; return instance; } private void ModifyInstance(RaceDetails instance, int level) { if ((instance == null) || (++level > 4)) return; instance.Opt_one = ModifyValue(instance.Opt_one); instance.Opt_two = ModifyValue(instance.Opt_two); instance.Opt_three = ModifyValue(instance.Opt_three); instance.Opt_four = ModifyValue(instance.Opt_four); instance.Opt_five = ModifyValue(instance.Opt_five); instance.Opt_six = ModifyValue(instance.Opt_six); instance.Opt_seven = ModifyValue(instance.Opt_seven); instance.Opt_eight = ModifyValue(instance.Opt_eight); instance.Opt_nine = ModifyValue(instance.Opt_nine); instance.Req_one = ModifyValue(instance.Req_one); instance.Req_two = ModifyValue(instance.Req_two); instance.Req_three = ModifyValue(instance.Req_three); instance.Req_four = ModifyValue(instance.Req_four); instance.Req_five = ModifyValue(instance.Req_five); instance.Req_six = ModifyValue(instance.Req_six); instance.Req_seven = ModifyValue(instance.Req_seven); instance.Req_eight = ModifyValue(instance.Req_eight); instance.Req_nine = ModifyValue(instance.Req_nine); instance.Def_one = ModifyValue(instance.Def_one); instance.Def_two = ModifyValue(instance.Def_two); instance.Def_three = ModifyValue(instance.Def_three); instance.Def_four = ModifyValue(instance.Def_four); instance.Def_five = ModifyValue(instance.Def_five); instance.Def_six = ModifyValue(instance.Def_six); instance.Def_seven = ModifyValue(instance.Def_seven); instance.Def_eight = ModifyValue(instance.Def_eight); instance.Def_nine = ModifyValue(instance.Def_nine); instance.Opt_one_with_value = ModifyValue(instance.Opt_one_with_value); instance.Opt_two_with_value = ModifyValue(instance.Opt_two_with_value); instance.Opt_three_with_value = ModifyValue(instance.Opt_three_with_value); instance.Opt_four_with_value = ModifyValue(instance.Opt_four_with_value); instance.Opt_five_with_value = ModifyValue(instance.Opt_five_with_value); instance.Opt_six_with_value = ModifyValue(instance.Opt_six_with_value); instance.Opt_seven_with_value = ModifyValue(instance.Opt_seven_with_value); instance.Opt_eight_with_value = ModifyValue(instance.Opt_eight_with_value); instance.Opt_nine_with_value = ModifyValue(instance.Opt_nine_with_value); instance.Req_one_with_value = ModifyValue(instance.Req_one_with_value); instance.Req_two_with_value = ModifyValue(instance.Req_two_with_value); instance.Req_three_with_value = ModifyValue(instance.Req_three_with_value); instance.Req_four_with_value = ModifyValue(instance.Req_four_with_value); instance.Req_five_with_value = ModifyValue(instance.Req_five_with_value); instance.Req_six_with_value = ModifyValue(instance.Req_six_with_value); instance.Req_seven_with_value = ModifyValue(instance.Req_seven_with_value); instance.Req_eight_with_value = ModifyValue(instance.Req_eight_with_value); instance.Req_nine_with_value = ModifyValue(instance.Req_nine_with_value); instance.Def_one_with_value = ModifyValue(instance.Def_one_with_value); instance.Def_two_with_value = ModifyValue(instance.Def_two_with_value); instance.Def_three_with_value = ModifyValue(instance.Def_three_with_value); instance.Def_four_with_value = ModifyValue(instance.Def_four_with_value); instance.Def_five_with_value = ModifyValue(instance.Def_five_with_value); instance.Def_six_with_value = ModifyValue(instance.Def_six_with_value); instance.Def_seven_with_value = ModifyValue(instance.Def_seven_with_value); instance.Def_eight_with_value = ModifyValue(instance.Def_eight_with_value); instance.Def_nine_with_value = ModifyValue(instance.Def_nine_with_value); instance.Last_of_the_mohicans = ModifyValue(instance.Last_of_the_mohicans); instance.Far_list = ModifyValue(instance.Far_list); instance.Far_set = ModifyValue(instance.Far_set); instance.Far_map = ModifyValue(instance.Far_map); instance.Far_set_list = ModifyValue(instance.Far_set_list); instance.Far_list_map_set = ModifyValue(instance.Far_list_map_set); instance.Far_map_dist_to_rds = ModifyValue(instance.Far_map_dist_to_rds, level); instance.Req_nested = ModifyValue(instance.Req_nested, level); instance.Opt_nested = ModifyValue(instance.Opt_nested, level); instance.Def_nested = ModifyValue(instance.Def_nested, level); instance.Req_union = ModifyValue(instance.Req_union, level); instance.Opt_union = ModifyValue(instance.Opt_union, level); instance.Def_union = ModifyValue(instance.Def_union, level); instance.Triplesix = ModifyValue(instance.Triplesix); } private jack? ModifyValue(jack? value, int level) { if (++level > 4) return value; if (value == null) value = MakeNestedUnion(0); Debug.Assert(value?.As_nested_struct != null); ModifyInstance(value.As_nested_struct, level); return value; } private RaceDetails? ModifyValue(RaceDetails? value, int level) { if (++level > 4) return value; if (value == null) value = new RaceDetails(); ModifyInstance(value,level); return value; } private Dictionary> ModifyValue(Dictionary>? value, int level) { if (value == null) value = new Dictionary>(); if (++level > 4) return value; var details = new RaceDetails(); InitializeInstance(details); value[Distance.foo] = new List() { details }; if (value.TryGetValue(Distance.bar, out var list) && (list.Count > 0)) { ModifyInstance(list[0], level); //list.Add(null); -- Thrift does not allow null values in containers } // Thrift does not allow null values in containers //value[Distance.baz] = null; return value; } private static List>> ModifyValue(List>>? value) { if (value == null) value = new List>>(); if (value.Count == 0) value.Add(new Dictionary>()); //else //value.Add(null); --Thrift does not allow null values in containers sbyte key = (sbyte)(value[0].Count + 10); if (value[0].Count == 0) value[0].Add(key, new HashSet()); //else //value[0].Add(key, null); --Thrift does not allow null values in containers foreach (var entry in value) { if (entry != null) { foreach (var pair in entry) { if (pair.Value != null) { if (pair.Value.Contains(Distance.baz)) pair.Value.Remove(Distance.baz); else pair.Value.Add(Distance.baz); } } } } return value; } private static HashSet> ModifyValue(HashSet>? value) { if (value == null) value = new HashSet>(); if (value.Count == 0) value.Add(new List()); //else //value.Add(null); -- Thrift does not allow null values in containers foreach (var entry in value) if( entry != null) entry.Add(Distance.baz); return value; } private static Dictionary ModifyValue(Dictionary? value) { if (value == null) value = new Dictionary(); value[Distance.foo] = value.ContainsKey(Distance.foo) ? ++value[Distance.foo] : Distance.foo; value[Distance.bar] = value.ContainsKey(Distance.bar) ? ++value[Distance.bar] : Distance.bar; value[Distance.baz] = value.ContainsKey(Distance.baz) ? ++value[Distance.baz] : Distance.baz; return value; } private static HashSet ModifyValue(HashSet? value) { if (value == null) value = new HashSet(); if (value.Contains(Distance.foo)) value.Remove(Distance.foo); else value.Add(Distance.foo); if (value.Contains(Distance.bar)) value.Remove(Distance.bar); else value.Add(Distance.bar); if (value.Contains(Distance.baz)) value.Remove(Distance.baz); else value.Add(Distance.baz); return value; } private static List ModifyValue(List? value) { if (value == null) value = new List(); value.Add(Distance.foo); value.Add(Distance.bar); value.Add(Distance.baz); return value; } private static bool ModifyValue(bool value) { return !value; } private static Dictionary ModifyValue(Dictionary? value) { if (value == null) value = new Dictionary(); value.Add((sbyte)(value.Count + 10), (short)value.Count); return value; } private static HashSet ModifyValue(HashSet? value) { if (value == null) value = new HashSet(); value.Add(value.Count+100); return value; } private static List ModifyValue(List? value) { if (value == null) value = new List(); value.Add(value.Count); return value; } private static byte[] ModifyValue(byte[]? value) { if (value == null) value = new byte[1] { 0 }; if (value.Length > 0) value[0] = (value[0] < 0xFF) ? ++value[0] : (byte)0; else value = new byte[1] { 0 }; return value; } private static string ModifyValue(string? value) { return value + "1"; } private static Guid ModifyValue(Guid value) { return new Guid( ModifyValue(value.ToByteArray())); } private static double ModifyValue(double value) { return value + 1.1; } private static short ModifyValue(short value) { return ++value; } private static Distance ModifyValue(Distance value) { return ++value; } private static void VerifyDifferentContent(RaceDetails first, RaceDetails second) { Assert.AreNotEqual(first, second); Assert.AreNotEqual(first.Opt_two, second.Opt_two); Assert.AreNotEqual(first.Opt_three, second.Opt_three); Assert.AreNotEqual(first.Opt_four, second.Opt_four); Assert.IsFalse(TCollections.Equals(first.Opt_five, second.Opt_five)); Assert.IsFalse(TCollections.Equals(first.Opt_six, second.Opt_six)); Assert.IsFalse(TCollections.Equals(first.Opt_seven, second.Opt_seven)); Assert.IsFalse(TCollections.Equals(first.Opt_eight, second.Opt_eight)); Assert.IsFalse(TCollections.Equals(first.Opt_nine, second.Opt_nine)); Assert.AreNotEqual(first.Req_one, second.Req_one); Assert.AreNotEqual(first.Req_two, second.Req_two); Assert.AreNotEqual(first.Req_three, second.Req_three); Assert.AreNotEqual(first.Req_four, second.Req_four); Assert.IsFalse(TCollections.Equals(first.Req_five, second.Req_five)); Assert.IsFalse(TCollections.Equals(first.Req_six, second.Req_six)); Assert.IsFalse(TCollections.Equals(first.Req_seven, second.Req_seven)); Assert.IsFalse(TCollections.Equals(first.Req_eight, second.Req_eight)); Assert.IsFalse(TCollections.Equals(first.Req_nine, second.Req_nine)); Assert.AreNotEqual(first.Def_one, second.Def_one); Assert.AreNotEqual(first.Def_two, second.Def_two); Assert.AreNotEqual(first.Def_three, second.Def_three); Assert.AreNotEqual(first.Def_four, second.Def_four); Assert.IsFalse(TCollections.Equals(first.Def_five, second.Def_five)); Assert.IsFalse(TCollections.Equals(first.Def_six, second.Def_six)); Assert.IsFalse(TCollections.Equals(first.Def_seven, second.Def_seven)); Assert.IsFalse(TCollections.Equals(first.Def_eight, second.Def_eight)); Assert.IsFalse(TCollections.Equals(first.Def_nine, second.Def_nine)); Assert.AreNotEqual(first.Opt_one_with_value, second.Opt_one_with_value); Assert.AreNotEqual(first.Opt_two_with_value, second.Opt_two_with_value); Assert.AreNotEqual(first.Opt_three_with_value, second.Opt_three_with_value); Assert.AreNotEqual(first.Opt_four_with_value, second.Opt_four_with_value); Assert.IsFalse(TCollections.Equals(first.Opt_five_with_value, second.Opt_five_with_value)); Assert.IsFalse(TCollections.Equals(first.Opt_six_with_value, second.Opt_six_with_value)); Assert.IsFalse(TCollections.Equals(first.Opt_seven_with_value, second.Opt_seven_with_value)); Assert.IsFalse(TCollections.Equals(first.Opt_eight_with_value, second.Opt_eight_with_value)); Assert.IsFalse(TCollections.Equals(first.Opt_nine_with_value, second.Opt_nine_with_value)); Assert.AreNotEqual(first.Req_one_with_value, second.Req_one_with_value); Assert.AreNotEqual(first.Req_two_with_value, second.Req_two_with_value); Assert.AreNotEqual(first.Req_three_with_value, second.Req_three_with_value); Assert.AreNotEqual(first.Req_four_with_value, second.Req_four_with_value); Assert.IsFalse(TCollections.Equals(first.Req_five_with_value, second.Req_five_with_value)); Assert.IsFalse(TCollections.Equals(first.Req_six_with_value, second.Req_six_with_value)); Assert.IsFalse(TCollections.Equals(first.Req_seven_with_value, second.Req_seven_with_value)); Assert.IsFalse(TCollections.Equals(first.Req_eight_with_value, second.Req_eight_with_value)); Assert.IsFalse(TCollections.Equals(first.Req_nine_with_value, second.Req_nine_with_value)); Assert.AreNotEqual(first.Def_one_with_value, second.Def_one_with_value); Assert.AreNotEqual(first.Def_two_with_value, second.Def_two_with_value); Assert.AreNotEqual(first.Def_three_with_value, second.Def_three_with_value); Assert.AreNotEqual(first.Def_four_with_value, second.Def_four_with_value); Assert.IsFalse(TCollections.Equals(first.Def_five_with_value, second.Def_five_with_value)); Assert.IsFalse(TCollections.Equals(first.Def_six_with_value, second.Def_six_with_value)); Assert.IsFalse(TCollections.Equals(first.Def_seven_with_value, second.Def_seven_with_value)); Assert.IsFalse(TCollections.Equals(first.Def_eight_with_value, second.Def_eight_with_value)); Assert.IsFalse(TCollections.Equals(first.Def_nine_with_value, second.Def_nine_with_value)); Assert.AreNotEqual(first.Last_of_the_mohicans, second.Last_of_the_mohicans); Assert.IsFalse(TCollections.Equals(first.Far_list, second.Far_list)); Assert.IsFalse(TCollections.Equals(first.Far_set, second.Far_set)); Assert.IsFalse(TCollections.Equals(first.Far_map, second.Far_map)); Assert.IsFalse(TCollections.Equals(first.Far_set_list, second.Far_set_list)); Assert.IsFalse(TCollections.Equals(first.Far_list_map_set, second.Far_list_map_set)); Assert.IsFalse(TCollections.Equals(first.Far_map_dist_to_rds, second.Far_map_dist_to_rds)); Assert.AreNotEqual(first.Req_nested, second.Req_nested); Assert.AreNotEqual(first.Opt_nested, second.Opt_nested); Assert.AreNotEqual(first.Def_nested, second.Def_nested); Assert.AreNotEqual(first.Req_union, second.Req_union); Assert.AreNotEqual(first.Opt_union, second.Opt_union); Assert.AreNotEqual(first.Def_union, second.Def_union); Assert.AreNotEqual(first.Triplesix, second.Triplesix); } private static void VerifyIdenticalContent(RaceDetails first, RaceDetails second) { Assert.AreEqual(first, second); Assert.AreEqual(first.Opt_two, second.Opt_two); Assert.AreEqual(first.Opt_three, second.Opt_three); Assert.AreEqual(first.Opt_four, second.Opt_four); Assert.IsTrue(TCollections.Equals(first.Opt_five, second.Opt_five)); Assert.IsTrue(TCollections.Equals(first.Opt_six, second.Opt_six)); Assert.IsTrue(TCollections.Equals(first.Opt_seven, second.Opt_seven)); Assert.IsTrue(TCollections.Equals(first.Opt_eight, second.Opt_eight)); Assert.IsTrue(TCollections.Equals(first.Opt_nine, second.Opt_nine)); Assert.AreEqual(first.Req_one, second.Req_one); Assert.AreEqual(first.Req_two, second.Req_two); Assert.AreEqual(first.Req_three, second.Req_three); Assert.AreEqual(first.Req_four, second.Req_four); Assert.IsTrue(TCollections.Equals(first.Req_five, second.Req_five)); Assert.IsTrue(TCollections.Equals(first.Req_six, second.Req_six)); Assert.IsTrue(TCollections.Equals(first.Req_seven, second.Req_seven)); Assert.IsTrue(TCollections.Equals(first.Req_eight, second.Req_eight)); Assert.IsTrue(TCollections.Equals(first.Req_nine, second.Req_nine)); Assert.AreEqual(first.Def_one, second.Def_one); Assert.AreEqual(first.Def_two, second.Def_two); Assert.AreEqual(first.Def_three, second.Def_three); Assert.AreEqual(first.Def_four, second.Def_four); Assert.IsTrue(TCollections.Equals(first.Def_five, second.Def_five)); Assert.IsTrue(TCollections.Equals(first.Def_six, second.Def_six)); Assert.IsTrue(TCollections.Equals(first.Def_seven, second.Def_seven)); Assert.IsTrue(TCollections.Equals(first.Def_eight, second.Def_eight)); Assert.IsTrue(TCollections.Equals(first.Def_nine, second.Def_nine)); Assert.AreEqual(first.Opt_one_with_value, second.Opt_one_with_value); Assert.AreEqual(first.Opt_two_with_value, second.Opt_two_with_value); Assert.AreEqual(first.Opt_three_with_value, second.Opt_three_with_value); Assert.AreEqual(first.Opt_four_with_value, second.Opt_four_with_value); Assert.IsTrue(TCollections.Equals(first.Opt_five_with_value, second.Opt_five_with_value)); Assert.IsTrue(TCollections.Equals(first.Opt_six_with_value, second.Opt_six_with_value)); Assert.IsTrue(TCollections.Equals(first.Opt_seven_with_value, second.Opt_seven_with_value)); Assert.IsTrue(TCollections.Equals(first.Opt_eight_with_value, second.Opt_eight_with_value)); Assert.IsTrue(TCollections.Equals(first.Opt_nine_with_value, second.Opt_nine_with_value)); Assert.AreEqual(first.Req_one_with_value, second.Req_one_with_value); Assert.AreEqual(first.Req_two_with_value, second.Req_two_with_value); Assert.AreEqual(first.Req_three_with_value, second.Req_three_with_value); Assert.AreEqual(first.Req_four_with_value, second.Req_four_with_value); Assert.IsTrue(TCollections.Equals(first.Req_five_with_value, second.Req_five_with_value)); Assert.IsTrue(TCollections.Equals(first.Req_six_with_value, second.Req_six_with_value)); Assert.IsTrue(TCollections.Equals(first.Req_seven_with_value, second.Req_seven_with_value)); Assert.IsTrue(TCollections.Equals(first.Req_eight_with_value, second.Req_eight_with_value)); Assert.IsTrue(TCollections.Equals(first.Req_nine_with_value, second.Req_nine_with_value)); Assert.AreEqual(first.Def_one_with_value, second.Def_one_with_value); Assert.AreEqual(first.Def_two_with_value, second.Def_two_with_value); Assert.AreEqual(first.Def_three_with_value, second.Def_three_with_value); Assert.AreEqual(first.Def_four_with_value, second.Def_four_with_value); Assert.IsTrue(TCollections.Equals(first.Def_five_with_value, second.Def_five_with_value)); Assert.IsTrue(TCollections.Equals(first.Def_six_with_value, second.Def_six_with_value)); Assert.IsTrue(TCollections.Equals(first.Def_seven_with_value, second.Def_seven_with_value)); Assert.IsTrue(TCollections.Equals(first.Def_eight_with_value, second.Def_eight_with_value)); Assert.IsTrue(TCollections.Equals(first.Def_nine_with_value, second.Def_nine_with_value)); Assert.AreEqual(first.Last_of_the_mohicans, second.Last_of_the_mohicans); Assert.IsTrue(TCollections.Equals(first.Far_list, second.Far_list)); Assert.IsTrue(TCollections.Equals(first.Far_set, second.Far_set)); Assert.IsTrue(TCollections.Equals(first.Far_map, second.Far_map)); Assert.IsTrue(TCollections.Equals(first.Far_set_list, second.Far_set_list)); Assert.IsTrue(TCollections.Equals(first.Far_list_map_set, second.Far_list_map_set)); Assert.IsTrue(TCollections.Equals(first.Far_map_dist_to_rds, second.Far_map_dist_to_rds)); Assert.AreEqual(first.Req_nested, second.Req_nested); Assert.AreEqual(first.Opt_nested, second.Opt_nested); Assert.AreEqual(first.Def_nested, second.Def_nested); Assert.AreEqual(first.Req_union, second.Req_union); Assert.AreEqual(first.Opt_union, second.Opt_union); Assert.AreEqual(first.Def_union, second.Def_union); Assert.AreEqual(first.Triplesix, second.Triplesix); } } } thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/DataModel/NullValuesSet.cs0000644000000000000000000000717114370300523025543 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestTools.UnitTesting; using OptReqDefTest; using Thrift.Collections; #pragma warning disable IDE0017 // init can be simplified - we don't want that here namespace Thrift.Tests.DataModel { // ReSharper disable once InconsistentNaming [TestClass] public class Thrift_5238 { private static void CheckInstance(RaceDetails instance) { // object Assert.IsTrue(instance.__isset.def_nested); Assert.IsTrue(instance.__isset.opt_nested); Assert.IsNull(instance.Def_nested); Assert.IsNull(instance.Opt_nested); // string Assert.IsTrue(instance.__isset.def_four); Assert.IsTrue(instance.__isset.opt_four); Assert.IsTrue(string.IsNullOrEmpty(instance.Req_four)); Assert.IsNull(instance.Def_four); Assert.IsNull(instance.Opt_four); // list<> Assert.IsTrue(instance.__isset.def_six); Assert.IsTrue(instance.__isset.opt_six); Assert.IsNull(instance.Req_six); Assert.IsNull(instance.Opt_six); Assert.IsNull(instance.Def_six); // byte[] Assert.IsTrue(instance.__isset.def_nine); Assert.IsTrue(instance.__isset.opt_nine); Assert.IsTrue((instance.Req_nine == null) || (instance.Req_nine.Length == 0)); Assert.IsNull(instance.Def_nine); Assert.IsNull(instance.Opt_nine); } [TestMethod] public void Thrift_5238_ProperNullChecks() { var instance = new OptReqDefTest.RaceDetails(); // the following code INTENTIONALLY assigns null to non.nullable reftypes #pragma warning disable CS8625 // object instance.Def_nested = null; instance.Opt_nested = null; // string instance.Req_four = null; instance.Def_four = null; instance.Opt_four = null; // list<> instance.Req_six = null; instance.Opt_six = null; instance.Def_six = null; // byte[] instance.Req_nine = null; instance.Def_nine = null; instance.Opt_nine = null; // back to normal #pragma warning restore CS8625 // test the setup CheckInstance(instance); // validate proper null checks, any of these throws if not instance.ToString(); instance.GetHashCode(); // validate proper null checks, any of these throws if not var copy = instance.DeepCopy(); CheckInstance(copy); } } } thrift-0.19.0/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj0000644000000000000000000000344314454461475024416 0ustar00rootroot00000000000000 net7.0 0.19.0.0 enable thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/0000777000000000000000000000000014454461475025443 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5253.thrift0000644000000000000000000000336014370300523030421 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5253 using Result in result name generates wrong IAsync interface namespace * Thrift5253 // this works struct WorksArrrgs { 1: i32 foo } struct WorksRslt { 1: i32 foo } // this does not struct BrokenResult{ 1: i32 foo } struct BrokenArgs { 1: i32 foo } struct InternalStructs { 1: optional i32 foo } struct AsyncProcessor { 1: optional i32 foo } struct Client { 1: optional i32 foo } struct IAsync { 1: optional i32 foo } struct ReservedMemberName { 1: optional i32 Isset } service MyService{ BrokenResult Broken( 1 : BrokenArgs foo) WorksRslt Works( 1 : WorksArrrgs foo) InternalStructs InternalStructs( 1: InternalStructs foo) AsyncProcessor AsyncProcessor ( 1: AsyncProcessor foo) Client Client ( 1: Client foo) IAsync IAsync ( 1: IAsync foo) // inconsistent treatment of methods ending in "Async" void TestXsync() void TestAsync() } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift0000644000000000000000000007212614370300523031407 0ustar00rootroot00000000000000#!/usr/local/bin/thrift --java --php --py # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # *** PLEASE REMEMBER TO EDIT THE VERSION CONSTANT WHEN MAKING CHANGES *** # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Interface definition for Cassandra Service # namespace netstd Apache.Cassandra.Test # Thrift.rb has a bug where top-level modules that include modules # with the same name are not properly referenced, so we can't do # Cassandra::Cassandra::Client. namespace rb CassandraThrift # The API version (NOT the product version), composed as a dot delimited # string with major, minor, and patch level components. # # - Major: Incremented for backward incompatible changes. An example would # be changes to the number or disposition of method arguments. # - Minor: Incremented for backward compatible changes. An example would # be the addition of a new (optional) method. # - Patch: Incremented for bug fixes. The patch level should be increased # for every edit that doesn't result in a change to major/minor. # # See the Semantic Versioning Specification (SemVer) http://semver.org. const string VERSION = "19.24.0" # # data structures # /** Basic unit of data within a ColumnFamily. * @param name, the name by which this column is set and retrieved. Maximum 64KB long. * @param value. The data associated with the name. Maximum 2GB long, but in practice you should limit it to small numbers of MB (since Thrift must read the full value into memory to operate on it). * @param timestamp. The timestamp is used for conflict detection/resolution when two columns with same name need to be compared. * @param ttl. An optional, positive delay (in seconds) after which the column will be automatically deleted. */ struct Column { 1: required binary name, 2: optional binary value, 3: optional i64 timestamp, 4: optional i32 ttl, } /** A named list of columns. * @param name. see Column.name. * @param columns. A collection of standard Columns. The columns within a super column are defined in an adhoc manner. * Columns within a super column do not have to have matching structures (similarly named child columns). */ struct SuperColumn { 1: required binary name, 2: required list columns, } struct CounterColumn { 1: required binary name, 2: required i64 value } struct CounterSuperColumn { 1: required binary name, 2: required list columns } /** Methods for fetching rows/records from Cassandra will return either a single instance of ColumnOrSuperColumn or a list of ColumnOrSuperColumns (get_slice()). If you're looking up a SuperColumn (or list of SuperColumns) then the resulting instances of ColumnOrSuperColumn will have the requested SuperColumn in the attribute super_column. For queries resulting in Columns, those values will be in the attribute column. This change was made between 0.3 and 0.4 to standardize on single query methods that may return either a SuperColumn or Column. If the query was on a counter column family, you will either get a counter_column (instead of a column) or a counter_super_column (instead of a super_column) @param column. The Column returned by get() or get_slice(). @param super_column. The SuperColumn returned by get() or get_slice(). @param counter_column. The Counterolumn returned by get() or get_slice(). @param counter_super_column. The CounterSuperColumn returned by get() or get_slice(). */ struct ColumnOrSuperColumn { 1: optional Column column, 2: optional SuperColumn super_column, 3: optional CounterColumn counter_column, 4: optional CounterSuperColumn counter_super_column } # # Exceptions # (note that internal server errors will raise a TApplicationException, courtesy of Thrift) # /** A specific column was requested that does not exist. */ exception NotFoundException { } /** Invalid request could mean keyspace or column family does not exist, required parameters are missing, or a parameter is malformed. why contains an associated error message. */ exception InvalidRequestException { 1: required string why } /** Not all the replicas required could be created and/or read. */ exception UnavailableException { } /** RPC timeout was exceeded. either a node failed mid-operation, or load was too high, or the requested op was too large. */ exception TimedOutException { } /** invalid authentication request (invalid keyspace, user does not exist, or credentials invalid) */ exception AuthenticationException { 1: required string why } /** invalid authorization request (user does not have access to keyspace) */ exception AuthorizationException { 1: required string why } /** schemas are not in agreement across all nodes */ exception SchemaDisagreementException { } # # service api # /** * The ConsistencyLevel is an enum that controls both read and write * behavior based on the ReplicationFactor of the keyspace. The * different consistency levels have different meanings, depending on * if you're doing a write or read operation. * * If W + R > ReplicationFactor, where W is the number of nodes to * block for on write, and R the number to block for on reads, you * will have strongly consistent behavior; that is, readers will * always see the most recent write. Of these, the most interesting is * to do QUORUM reads and writes, which gives you consistency while * still allowing availability in the face of node failures up to half * of . Of course if latency is more important than * consistency then you can use lower values for either or both. * * Some ConsistencyLevels (ONE, TWO, THREE) refer to a specific number * of replicas rather than a logical concept that adjusts * automatically with the replication factor. Of these, only ONE is * commonly used; TWO and (even more rarely) THREE are only useful * when you care more about guaranteeing a certain level of * durability, than consistency. * * Write consistency levels make the following guarantees before reporting success to the client: * ANY Ensure that the write has been written once somewhere, including possibly being hinted in a non-target node. * ONE Ensure that the write has been written to at least 1 node's commit log and memory table * TWO Ensure that the write has been written to at least 2 node's commit log and memory table * THREE Ensure that the write has been written to at least 3 node's commit log and memory table * QUORUM Ensure that the write has been written to / 2 + 1 nodes * LOCAL_QUORUM Ensure that the write has been written to / 2 + 1 nodes, within the local datacenter (requires NetworkTopologyStrategy) * EACH_QUORUM Ensure that the write has been written to / 2 + 1 nodes in each datacenter (requires NetworkTopologyStrategy) * ALL Ensure that the write is written to <ReplicationFactor> nodes before responding to the client. * * Read consistency levels make the following guarantees before returning successful results to the client: * ANY Not supported. You probably want ONE instead. * ONE Returns the record obtained from a single replica. * TWO Returns the record with the most recent timestamp once two replicas have replied. * THREE Returns the record with the most recent timestamp once three replicas have replied. * QUORUM Returns the record with the most recent timestamp once a majority of replicas have replied. * LOCAL_QUORUM Returns the record with the most recent timestamp once a majority of replicas within the local datacenter have replied. * EACH_QUORUM Returns the record with the most recent timestamp once a majority of replicas within each datacenter have replied. * ALL Returns the record with the most recent timestamp once all replicas have replied (implies no replica may be down).. */ enum ConsistencyLevel { ONE = 1, QUORUM = 2, LOCAL_QUORUM = 3, EACH_QUORUM = 4, ALL = 5, ANY = 6, TWO = 7, THREE = 8, } /** ColumnParent is used when selecting groups of columns from the same ColumnFamily. In directory structure terms, imagine ColumnParent as ColumnPath + '/../'. See also ColumnPath */ struct ColumnParent { 3: required string column_family, 4: optional binary super_column, } /** The ColumnPath is the path to a single column in Cassandra. It might make sense to think of ColumnPath and * ColumnParent in terms of a directory structure. * * ColumnPath is used to looking up a single column. * * @param column_family. The name of the CF of the column being looked up. * @param super_column. The super column name. * @param column. The column name. */ struct ColumnPath { 3: required string column_family, 4: optional binary super_column, 5: optional binary column, } /** A slice range is a structure that stores basic range, ordering and limit information for a query that will return multiple columns. It could be thought of as Cassandra's version of LIMIT and ORDER BY @param start. The column name to start the slice with. This attribute is not required, though there is no default value, and can be safely set to '', i.e., an empty byte array, to start with the first column name. Otherwise, it must a valid value under the rules of the Comparator defined for the given ColumnFamily. @param finish. The column name to stop the slice at. This attribute is not required, though there is no default value, and can be safely set to an empty byte array to not stop until 'count' results are seen. Otherwise, it must also be a valid value to the ColumnFamily Comparator. @param reversed. Whether the results should be ordered in reversed order. Similar to ORDER BY blah DESC in SQL. @param count. How many columns to return. Similar to LIMIT in SQL. May be arbitrarily large, but Thrift will materialize the whole result into memory before returning it to the client, so be aware that you may be better served by iterating through slices by passing the last value of one call in as the 'start' of the next instead of increasing 'count' arbitrarily large. */ struct SliceRange { 1: required binary start, 2: required binary finish, 3: required bool reversed=0, 4: required i32 count=100, } /** A SlicePredicate is similar to a mathematic predicate (see http://en.wikipedia.org/wiki/Predicate_(mathematical_logic)), which is described as "a property that the elements of a set have in common." SlicePredicate's in Cassandra are described with either a list of column_names or a SliceRange. If column_names is specified, slice_range is ignored. @param column_name. A list of column names to retrieve. This can be used similar to Memcached's "multi-get" feature to fetch N known column names. For instance, if you know you wish to fetch columns 'Joe', 'Jack', and 'Jim' you can pass those column names as a list to fetch all three at once. @param slice_range. A SliceRange describing how to range, order, and/or limit the slice. */ struct SlicePredicate { 1: optional list column_names, 2: optional SliceRange slice_range, } enum IndexOperator { EQ, GTE, GT, LTE, LT } struct IndexExpression { 1: required binary column_name, 2: required IndexOperator op, 3: required binary value, } struct IndexClause { 1: required list expressions 2: required binary start_key, 3: required i32 count=100, } /** The semantics of start keys and tokens are slightly different. Keys are start-inclusive; tokens are start-exclusive. Token ranges may also wrap -- that is, the end token may be less than the start one. Thus, a range from keyX to keyX is a one-element range, but a range from tokenY to tokenY is the full ring. */ struct KeyRange { 1: optional binary start_key, 2: optional binary end_key, 3: optional string start_token, 4: optional string end_token, 5: required i32 count=100 } /** A KeySlice is key followed by the data it maps to. A collection of KeySlice is returned by the get_range_slice operation. @param key. a row key @param columns. List of data represented by the key. Typically, the list is pared down to only the columns specified by a SlicePredicate. */ struct KeySlice { 1: required binary key, 2: required list columns, } struct KeyCount { 1: required binary key, 2: required i32 count } /** * Note that the timestamp is only optional in case of counter deletion. */ struct Deletion { 1: optional i64 timestamp, 2: optional binary super_column, 3: optional SlicePredicate predicate, } /** A Mutation is either an insert (represented by filling column_or_supercolumn) or a deletion (represented by filling the deletion attribute). @param column_or_supercolumn. An insert to a column or supercolumn (possibly counter column or supercolumn) @param deletion. A deletion of a column or supercolumn */ struct Mutation { 1: optional ColumnOrSuperColumn column_or_supercolumn, 2: optional Deletion deletion, } struct EndpointDetails { 1: string host, 2: string datacenter, 3: optional string rack } /** A TokenRange describes part of the Cassandra ring, it is a mapping from a range to endpoints responsible for that range. @param start_token The first token in the range @param end_token The last token in the range @param endpoints The endpoints responsible for the range (listed by their configured listen_address) @param rpc_endpoints The endpoints responsible for the range (listed by their configured rpc_address) */ struct TokenRange { 1: required string start_token, 2: required string end_token, 3: required list endpoints, 4: optional list rpc_endpoints 5: optional list endpoint_details, } /** Authentication requests can contain any data, dependent on the IAuthenticator used */ struct AuthenticationRequest { 1: required map credentials } enum IndexType { KEYS, CUSTOM } /* describes a column in a column family. */ struct ColumnDef { 1: required binary name, 2: required string validation_class, 3: optional IndexType index_type, 4: optional string index_name, 5: optional map index_options } /* describes a column family. */ struct CfDef { 1: required string keyspace, 2: required string name, 3: optional string column_type="Standard", 5: optional string comparator_type="BytesType", 6: optional string subcomparator_type, 8: optional string comment, 12: optional double read_repair_chance=1.0, 13: optional list column_metadata, 14: optional i32 gc_grace_seconds, 15: optional string default_validation_class, 16: optional i32 id, 17: optional i32 min_compaction_threshold, 18: optional i32 max_compaction_threshold, 24: optional bool replicate_on_write, 25: optional double merge_shards_chance, 26: optional string key_validation_class, 28: optional binary key_alias, 29: optional string compaction_strategy, 30: optional map compaction_strategy_options, 32: optional map compression_options, 33: optional double bloom_filter_fp_chance, } /* describes a keyspace. */ struct KsDef { 1: required string name, 2: required string strategy_class, 3: optional map strategy_options, /** @deprecated */ 4: optional i32 replication_factor, 5: required list cf_defs, 6: optional bool durable_writes=1, } /** CQL query compression */ enum Compression { GZIP = 1, NONE = 2 } enum CqlResultType { ROWS = 1, VOID = 2, INT = 3 } /** Row returned from a CQL query */ struct CqlRow { 1: required binary key, 2: required list columns } struct CqlMetadata { 1: required map name_types, 2: required map value_types, 3: required string default_name_type, 4: required string default_value_type } struct CqlResult { 1: required CqlResultType type, 2: optional list rows, 3: optional i32 num, 4: optional CqlMetadata schema } struct CqlPreparedResult { 1: required i32 itemId, 2: required i32 count } service Cassandra { # auth methods void login(1: required AuthenticationRequest auth_request) throws (1:AuthenticationException authnx, 2:AuthorizationException authzx), # set keyspace void set_keyspace(1: required string keyspace) throws (1:InvalidRequestException ire), # retrieval methods /** Get the Column or SuperColumn at the given column_path. If no value is present, NotFoundException is thrown. (This is the only method that can throw an exception under non-failure conditions.) */ ColumnOrSuperColumn get(1:required binary key, 2:required ColumnPath column_path, 3:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:NotFoundException nfe, 3:UnavailableException ue, 4:TimedOutException te), /** Get the group of columns contained by column_parent (either a ColumnFamily name or a ColumnFamily/SuperColumn name pair) specified by the given SlicePredicate. If no matching values are found, an empty list is returned. */ list get_slice(1:required binary key, 2:required ColumnParent column_parent, 3:required SlicePredicate predicate, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** returns the number of columns matching predicate for a particular key, ColumnFamily and optionally SuperColumn. */ i32 get_count(1:required binary key, 2:required ColumnParent column_parent, 3:required SlicePredicate predicate, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** Performs a get_slice for column_parent and predicate for the given keys in parallel. */ map> multiget_slice(1:required list keys, 2:required ColumnParent column_parent, 3:required SlicePredicate predicate, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** Perform a get_count in parallel on the given list keys. The return value maps keys to the count found. */ map multiget_count(1:required list keys, 2:required ColumnParent column_parent, 3:required SlicePredicate predicate, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** returns a subset of columns for a contiguous range of keys. */ list get_range_slices(1:required ColumnParent column_parent, 2:required SlicePredicate predicate, 3:required KeyRange range, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** Returns the subset of columns specified in SlicePredicate for the rows matching the IndexClause */ list get_indexed_slices(1:required ColumnParent column_parent, 2:required IndexClause index_clause, 3:required SlicePredicate column_predicate, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), # modification methods /** * Insert a Column at the given column_parent.column_family and optional column_parent.super_column. */ void insert(1:required binary key, 2:required ColumnParent column_parent, 3:required Column column, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** * Increment or decrement a counter. */ void add(1:required binary key, 2:required ColumnParent column_parent, 3:required CounterColumn column, 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** Remove data from the row specified by key at the granularity specified by column_path, and the given timestamp. Note that all the values in column_path besides column_path.column_family are truly optional: you can remove the entire row by just specifying the ColumnFamily, or you can remove a SuperColumn or a single Column by specifying those levels too. */ void remove(1:required binary key, 2:required ColumnPath column_path, 3:required i64 timestamp, 4:ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** * Remove a counter at the specified location. * Note that counters have limited support for deletes: if you remove a counter, you must wait to issue any following update * until the delete has reached all the nodes and all of them have been fully compacted. */ void remove_counter(1:required binary key, 2:required ColumnPath path, 3:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** Mutate many columns or super columns for many row keys. See also: Mutation. mutation_map maps key to column family to a list of Mutation objects to take place at that scope. **/ void batch_mutate(1:required map>> mutation_map, 2:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), /** Truncate will mark and entire column family as deleted. From the user's perspective a successful call to truncate will result complete data deletion from cfname. Internally, however, disk space will not be immediatily released, as with all deletes in cassandra, this one only marks the data as deleted. The operation succeeds only if all hosts in the cluster at available and will throw an UnavailableException if some hosts are down. */ void truncate(1:required string cfname) throws (1: InvalidRequestException ire, 2: UnavailableException ue, 3: TimedOutException te), // Meta-APIs -- APIs to get information about the node or cluster, // rather than user data. The nodeprobe program provides usage examples. /** * for each schema version present in the cluster, returns a list of nodes at that version. * hosts that do not respond will be under the key DatabaseDescriptor.INITIAL_VERSION. * the cluster is all on the same version if the size of the map is 1. */ map> describe_schema_versions() throws (1: InvalidRequestException ire), /** list the defined keyspaces in this cluster */ list describe_keyspaces() throws (1:InvalidRequestException ire), /** get the cluster name */ string describe_cluster_name(), /** get the thrift api version */ string describe_version(), /** get the token ring: a map of ranges to host addresses, represented as a set of TokenRange instead of a map from range to list of endpoints, because you can't use Thrift structs as map keys: https://issues.apache.org/jira/browse/THRIFT-162 for the same reason, we can't return a set here, even though order is neither important nor predictable. */ list describe_ring(1:required string keyspace) throws (1:InvalidRequestException ire), /** returns the partitioner used by this cluster */ string describe_partitioner(), /** returns the snitch used by this cluster */ string describe_snitch(), /** describe specified keyspace */ KsDef describe_keyspace(1:required string keyspace) throws (1:NotFoundException nfe, 2:InvalidRequestException ire), /** experimental API for hadoop/parallel query support. may change violently and without warning. returns list of token strings such that first subrange is (list[0], list[1]], next is (list[1], list[2]], etc. */ list describe_splits(1:required string cfName, 2:required string start_token, 3:required string end_token, 4:required i32 keys_per_split) throws (1:InvalidRequestException ire), /** adds a column family. returns the new schema id. */ string system_add_column_family(1:required CfDef cf_def) throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), /** drops a column family. returns the new schema id. */ string system_drop_column_family(1:required string column_family) throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), /** adds a keyspace and any column families that are part of it. returns the new schema id. */ string system_add_keyspace(1:required KsDef ks_def) throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), /** drops a keyspace and any column families that are part of it. returns the new schema id. */ string system_drop_keyspace(1:required string keyspace) throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), /** updates properties of a keyspace. returns the new schema id. */ string system_update_keyspace(1:required KsDef ks_def) throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), /** updates properties of a column family. returns the new schema id. */ string system_update_column_family(1:required CfDef cf_def) throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), /** * Executes a CQL (Cassandra Query Language) statement and returns a * CqlResult containing the results. */ CqlResult execute_cql_query(1:required binary query, 2:required Compression compression) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te, 4:SchemaDisagreementException sde) /** * Prepare a CQL (Cassandra Query Language) statement by compiling and returning * - the type of CQL statement * - an id token of the compiled CQL stored on the server side. * - a count of the discovered bound markers in the statement */ CqlPreparedResult prepare_cql_query(1:required binary query, 2:required Compression compression) throws (1:InvalidRequestException ire) /** * Executes a prepared CQL (Cassandra Query Language) statement by passing an id token and a list of variables * to bind and returns a CqlResult containing the results. */ CqlResult execute_prepared_cql_query(1:required i32 itemId, 2:required list values) throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te, 4:SchemaDisagreementException sde) } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/GlobalSuppressions.cs0000644000000000000000000000240714303740367031620 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given // a specific target and scoped to a namespace, type, member, etc. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Performance", "CA1822", Justification = "", Scope = "module")] [assembly: SuppressMessage("Style", "IDE0090", Justification = "", Scope = "module")] thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/0000777000000000000000000000000014062750226026332 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/Thrift5253/0000777000000000000000000000000014303740367030114 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Impl/Thrift5253/MyService.cs0000644000000000000000000000511014303740367032342 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; using Thrift5253; namespace Thrift.PublicInterfaces.Compile.Tests.Impl.Thrift5253 { class MyServiceImpl : MyService.IAsync { public Task AsyncProcessor_(AsyncProcessor? input, CancellationToken cancellationToken = default) { return Task.FromResult(new AsyncProcessor() { Foo = input?.Foo ?? 0 }); } public Task Broken(BrokenArgs? input, CancellationToken cancellationToken = default) { return Task.FromResult(new BrokenResult() { Foo = input?.Foo ?? 0 }); } public Task Client_(Client? input, CancellationToken cancellationToken = default) { _ = cancellationToken; return Task.FromResult(new Client() { Foo = input?.Foo ?? 0 }); } public Task IAsync_(IAsync? input, CancellationToken cancellationToken = default) { return Task.FromResult(new IAsync() { Foo = input?.Foo ?? 0 }); } public Task InternalStructs_(InternalStructs? input, CancellationToken cancellationToken = default) { return Task.FromResult(new InternalStructs() { Foo = input?.Foo ?? 0 }); } public Task TestAsync(CancellationToken cancellationToken = default) { return Task.CompletedTask; } public Task TestXsync(CancellationToken cancellationToken = default) { return Task.CompletedTask; } public Task Works(WorksArrrgs? input, CancellationToken cancellationToken = default) { return Task.FromResult(new WorksRslt() { Foo = input?.Foo ?? 0 }); } } } optional_required_default.thrift0000644000000000000000000001432514370300523034017 0ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5216 generate DeepCopy methods namespace netstd OptReqDefTest enum Distance { foo = 0, bar = 1, baz = 2 } struct RaceDetails { // this is really the max field index used here, intentionally placed at the beginning 666: required Distance triplesix // without default values 1: optional Distance opt_one 2: optional double opt_two 3: optional i16 opt_three 4: optional string opt_four 5: optional uuid opt_five 6: optional list opt_six 7: optional set opt_seven 8: optional map opt_eight 9: optional binary opt_nine 11: required Distance req_one 12: required double req_two 13: required i16 req_three 14: required string req_four 15: required uuid req_five 16: required list req_six 17: required set req_seven 18: required map req_eight 19: required binary req_nine 21: Distance def_one 22: double def_two 23: i16 def_three 24: string def_four 25: uuid def_five 26: list def_six 27: set def_seven 28: map def_eight 29: binary def_nine // having default values 31: optional Distance opt_one_with_value = Distance.bar 32: optional double opt_two_with_value = 2.22 33: optional i16 opt_three_with_value = 3 34: optional string opt_four_with_value = "four" 35: optional uuid opt_five_with_value = "55555555-5555-5555-5555-000000000000" 36: optional list opt_six_with_value = [6] 37: optional set opt_seven_with_value = [7] 38: optional map opt_eight_with_value = { 8 : 8 } 39: optional binary opt_nine_with_value = "nine\t" 41: required Distance req_one_with_value = Distance.bar 42: required double req_two_with_value = 2.22 43: required i16 req_three_with_value = 3 44: required string req_four_with_value = "four" 45: required uuid req_five_with_value = "55555555-5555-5555-5555-000000000000" 46: required list req_six_with_value = [6] 47: required set req_seven_with_value = [7] 48: required map req_eight_with_value = { 8 : 8 } 49: required binary req_nine_with_value = "nine" 51: Distance def_one_with_value = Distance.bar 52: double def_two_with_value = 2.22 53: i16 def_three_with_value = 3 54: string def_four_with_value = "four" 55: uuid def_five_with_value = "55555555-5555-5555-5555-000000000000" 56: list def_six_with_value = [6] 57: set def_seven_with_value = [7] 58: map def_eight_with_value = { 8 : 8 } 59: binary def_nine_with_value = "nine" 90: optional bool last_of_the_mohicans // some more complicated ones, including recursion 300: required list far_list 301: optional set far_set 302: map far_map 310: required set> far_set_list 311: optional list>> far_list_map_set 312: map far_map_dist_to_rds 320: required RaceDetails req_nested 321: optional RaceDetails opt_nested 322: RaceDetails def_nested 330: required jack req_union 331: optional jack opt_union 332: jack def_union } union jack { 1: list stars 2: list stripes 310: set> far_set_list 311: list>> far_list_map_set 312: map far_map_dist_to_rds 320: jack nested_union 321: RaceDetails nested_struct 401: optional Distance opt_one 402: optional double opt_two 403: optional i16 opt_three 404: optional string opt_four 405: optional uuid opt_five 406: optional list opt_six 407: optional set opt_seven 408: optional map opt_eight 409: optional binary opt_nine } typedef RaceDetails RaceDetails2 typedef list RDs exception CrashBoomBang { 1 : i32 MyErrorCode } service foobar { set>> DoItNow( 1 : list>> rd, 2: i32 mitDefault = 42) throws (1: CrashBoomBang cbb) } service deprecate_everything { void Foo( ) ( deprecated = "This method has neither 'x' nor \"y\"" ) void Bar( ) ( deprecated = "Fails to deliver 中文 колбаÑа" ) void Baz( ) ( deprecated = "Need this to work with tabs (\t) or Umlauts (äöüÄÖÜß) too" ) void Deprecated() ( deprecated ) // no comment } Thrift.PublicInterfaces.Compile.Tests.csproj0000644000000000000000000001055514454461475035761 0ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests 0.19.0 Thrift version $(ThriftVersion) net7.0 $(ThriftVersion).0 Thrift.PublicInterfaces.Compile.Tests Thrift.PublicInterfaces.Compile.Tests false false false false enable thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.exception.thrift0000644000000000000000000000173214370300523032412 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code namespace * Thrift5320.exceptions exception Task { 1: Task left 2: Task right } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.enum.thrift0000644000000000000000000000167314370300523031364 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code namespace * Thrift5320.enums enum Task { Zero, More } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5382.objs.thrift0000644000000000000000000000171114370300523031356 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5382 Netstd default list/set enums values are generated incorrectly namespace * Thrift5382.objs enum FoobarEnum { Val_1 = 0, Val_2 = 1 } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/0000777000000000000000000000000014303740367027570 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs0000644000000000000000000000326114303740367032510 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("The Apache Software Foundation")] [assembly: AssemblyProduct("Thrift")] [assembly: AssemblyCopyright("The Apache Software Foundation")] [assembly: AssemblyTrademark("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("d0d3706b-fed5-4cf5-b984-04f448de9d7b")]thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/name_conflicts.thrift0000644000000000000000000000332014370300523031622 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcases for // - THRIFT-5091 Netstd generator produces uncompileable code for struct names ending with "_result" or "_args" // - THRIFT-5444 netstd generator produces uncompileable code for enums ending with "_result" or "_args" // - THRIFT-5445 "cancellationToken" cannot be used as argument name namespace * name_conflicts include "name_conflicts.enum.thrift" struct some_struct_args { 1: name_conflicts.enum.some_args some_args 2: name_conflicts.enum.some_result some_result 3: required i32 cancellationToken } exception some_error_result { 1: name_conflicts.enum.some_args some_args 2: name_conflicts.enum.some_result some_result 3: optional i32 cancellationToken } service some_service { name_conflicts.enum.some_result some_method( 1: name_conflicts.enum.some_args some_args 2: some_struct_args more_args 3: i32 cancellationToken ) throws ( 1: some_error_result cancellationToken ) } // EOF thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/name_conflicts.enum.thrift0000644000000000000000000000220614370300523032567 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcases for // - THRIFT-5091 Netstd generator produces uncompileable code for struct names ending with "_result" or "_args" // - THRIFT-5444 netstd generator produces uncompileable code for enums ending with "_result" or "_args" namespace * name_conflicts_enum enum some_result { foo, bar, baz } enum some_args { foo, bar, baz } // EOF thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.struct.thrift0000644000000000000000000000172314370300523031740 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code namespace * Thrift5320.structs struct Task { 1: Task left 2: Task right } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.thrift0000644000000000000000000000230114370300523030406 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code namespace * Thrift5320.Task include "Thrift5320.enum.thrift" include "Thrift5320.exception.thrift" include "Thrift5320.struct.thrift" enum Foobar { Task = 0 } service Task { Thrift5320.enum.Task Task( 1 : Thrift5320.struct.Task foo, 2: Foobar bar ) throws ( 1: Thrift5320.exception.Task error ) } thrift-0.19.0/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5382.thrift0000644000000000000000000000246114370300523030425 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Testcase for THRIFT-5382 Netstd default list/set enums values are generated incorrectly namespace * Thrift5382 include "Thrift5382.objs.thrift" struct RequestModel { // Breaks 1: optional set data_1 = [ FoobarEnum.Val_1, FoobarEnum.Val_2 ], // Breaks 2: optional list data_2 = [ FoobarEnum.Val_1, FoobarEnum.Val_2 ], // Works 3: optional Thrift5382.objs.FoobarEnum data_3 = FoobarEnum.Val_1 } service Test { void CallMe( 1 : RequestModel foo, ) } thrift-0.19.0/lib/netstd/Tests/Thrift.IntegrationTests/0000755000000000000000000000000014472652662023033 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/0000777000000000000000000000000014303740367025014 5ustar00rootroot00000000000000thrift-0.19.0/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs0000644000000000000000000004336014303740367032420 0ustar00rootroot00000000000000// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. using System; using System.IO; using System.Text; using System.Threading.Tasks; using KellermanSoftware.CompareNetObjects; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Protocol; using Thrift.Protocol.Entities; using Thrift.Transport.Client; #pragma warning disable IDE0063 // using namespace Thrift.IntegrationTests.Protocols { [TestClass] public class ProtocolsOperationsTests { private readonly CompareLogic _compareLogic = new(); private static readonly TConfiguration Configuration = new(); [DataTestMethod] [DataRow(typeof(TBinaryProtocol), TMessageType.Call)] [DataRow(typeof(TBinaryProtocol), TMessageType.Exception)] [DataRow(typeof(TBinaryProtocol), TMessageType.Oneway)] [DataRow(typeof(TBinaryProtocol), TMessageType.Reply)] [DataRow(typeof(TCompactProtocol), TMessageType.Call)] [DataRow(typeof(TCompactProtocol), TMessageType.Exception)] [DataRow(typeof(TCompactProtocol), TMessageType.Oneway)] [DataRow(typeof(TCompactProtocol), TMessageType.Reply)] [DataRow(typeof(TJsonProtocol), TMessageType.Call)] [DataRow(typeof(TJsonProtocol), TMessageType.Exception)] [DataRow(typeof(TJsonProtocol), TMessageType.Oneway)] [DataRow(typeof(TJsonProtocol), TMessageType.Reply)] public async Task WriteReadMessage_Test(Type protocolType, TMessageType messageType) { var expected = new TMessage(nameof(TMessage), messageType, 1); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteMessageBeginAsync(expected, default); await protocol.WriteMessageEndAsync(default); stream.Seek(0, SeekOrigin.Begin); var actualMessage = await protocol.ReadMessageBeginAsync(default); await protocol.ReadMessageEndAsync(default); var result = _compareLogic.Compare(expected, actualMessage); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] [ExpectedException(typeof(Exception))] public async Task WriteReadStruct_Test(Type protocolType) { var expected = new TStruct(nameof(TStruct)); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteStructBeginAsync(expected, default); await protocol.WriteStructEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadStructBeginAsync(default); await protocol.ReadStructEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] [ExpectedException(typeof(Exception))] public async Task WriteReadField_Test(Type protocolType) { var expected = new TField(nameof(TField), TType.String, 1); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteFieldBeginAsync(expected, default); await protocol.WriteFieldEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadFieldBeginAsync(default); await protocol.ReadFieldEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadMap_Test(Type protocolType) { var expected = new TMap(TType.String, TType.String, 1); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteMapBeginAsync(expected, default); await protocol.WriteMapEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadMapBeginAsync(default); await protocol.ReadMapEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadList_Test(Type protocolType) { var expected = new TList(TType.String, 1); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteListBeginAsync(expected, default); await protocol.WriteListEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadListBeginAsync(default); await protocol.ReadListEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadSet_Test(Type protocolType) { var expected = new TSet(TType.String, 1); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteSetBeginAsync(expected, default); await protocol.WriteSetEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadSetBeginAsync(default); await protocol.ReadSetEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadBool_Test(Type protocolType) { var expected = true; try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteBoolAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadBoolAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadByte_Test(Type protocolType) { var expected = sbyte.MaxValue; try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteByteAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadByteAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadI16_Test(Type protocolType) { var expected = short.MaxValue; try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteI16Async(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadI16Async(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadI32_Test(Type protocolType) { var expected = int.MaxValue; try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteI32Async(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadI32Async(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadI64_Test(Type protocolType) { var expected = long.MaxValue; try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteI64Async(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadI64Async(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadDouble_Test(Type protocolType) { var expected = double.MaxValue; try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteDoubleAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadDoubleAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadString_Test(Type protocolType) { var expected = nameof(String); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteStringAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadStringAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } [DataTestMethod] [DataRow(typeof(TBinaryProtocol))] [DataRow(typeof(TCompactProtocol))] [DataRow(typeof(TJsonProtocol))] public async Task WriteReadBinary_Test(Type protocolType) { var expected = Encoding.UTF8.GetBytes(nameof(String)); try { var tuple = GetProtocolInstance(protocolType); using (var stream = tuple.Item1) { var protocol = tuple.Item2; await protocol.WriteBinaryAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); var actual = await protocol.ReadBinaryAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); } } catch (Exception e) { throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); } } private static Tuple GetProtocolInstance(Type protocolType) { var memoryStream = new MemoryStream(); var streamClientTransport = new TStreamTransport(memoryStream, memoryStream,Configuration); if( Activator.CreateInstance(protocolType, streamClientTransport) is TProtocol protocol) return new Tuple(memoryStream, protocol); throw new Exception("Unexpected"); } } } thrift-0.19.0/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj0000644000000000000000000000447214454461475031031 0ustar00rootroot00000000000000 net7.0 Thrift.IntegrationTests Thrift.IntegrationTests 0.19.0.0 Exe false false false false false false enable thrift-0.19.0/lib/kotlin/0000755000000000000000000000000014472652656015166 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/Makefile.am0000644000000000000000000000266514303742350017213 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # export CLASSPATH all-local: $(GRADLE) $(GRADLE_OPTS) assemble \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain clean-local: $(GRADLE) $(GRADLE_OPTS) clean --console=plain precross: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) installDist \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain check-local: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) test \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain EXTRA_DIST = \ build.gradle.kts \ CMakeLists.txt \ cross-test-client \ cross-test-server \ gradle.properties \ README.md \ settings.gradle.kts \ src thrift-0.19.0/lib/kotlin/CMakeLists.txt0000644000000000000000000000157114303740367017720 0ustar00rootroot00000000000000# Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. file(GLOB_RECURSE THRIFTKOTLIN_SOURCES LIST_DIRECTORIES false "${CMAKE_CURRENT_SOURCE_DIR}/src/*") thrift-0.19.0/lib/kotlin/gradle.properties0000644000000000000000000000165414303740367020536 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # slf4jVersion=1.7.35 httpcoreVersion=4.4.15 httpclientVersion=4.5.13 logbackVersion=1.3.0-alpha14 kotlinxCoroutinesJdk8Version=1.6.1 cliktVersion=3.4.2 thrift-0.19.0/lib/kotlin/src/0000777000000000000000000000000014303472263015744 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/0000777000000000000000000000000014303472263016723 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/resources/0000777000000000000000000000000014370300523020726 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/resources/AnnotationTest.thrift0000644000000000000000000000173014370300523025117 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace java org.apache.thrift.kotlin.annotation.test struct Person { 1: required i64 id (min="1", max="100000") 2: required string name 3: optional string phoneNumber } thrift-0.19.0/lib/kotlin/src/test/kotlin/0000777000000000000000000000000014303472263020223 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/kotlin/org/0000777000000000000000000000000014303472263021012 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/kotlin/org/apache/0000777000000000000000000000000014303472263022233 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/kotlin/org/apache/thrift/0000777000000000000000000000000014303740367023536 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/src/test/kotlin/org/apache/thrift/MetaDataTest.kt0000644000000000000000000000272414303740367026417 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift import kotlin.test.assertEquals import org.apache.thrift.kotlin.annotation.test.Person import org.apache.thrift.meta_data.FieldMetaData import org.junit.jupiter.api.Test internal class MetaDataTest { @Test internal fun testAnnotation() { val personMetadata = FieldMetaData.getStructMetaDataMap(Person::class.java) assertEquals(3, personMetadata.size) val idField = personMetadata[Person._Fields.ID]!! assertEquals("id", idField.fieldName) assertEquals( mapOf( "max" to "100000", "min" to "1", ), idField.fieldAnnotations ) } } thrift-0.19.0/lib/kotlin/README.md0000644000000000000000000000244114303740367016434 0ustar00rootroot00000000000000# Test Only Library for Kotlin This directory (`/lib/kotlin`) contains test only library code for Kotlin code gen. Because Kotlin code gen produces code that works on top of libthrift (i.e. Java library), the purpose of this library is to encode the cross test server and client to make sure it conforms to the thrift specifications. The output artifact in this library is _not_ published to Maven central. Unlike the Java library where: 1. source code is put under `main` sources set i.e. `src/main`, 2. unit test code is put under `test` sources set i.e. `src/test`, 3. cross test code is put under `crossTest` sources set, i.e. `src/crossTest` directory which, unlike the default `main` and `test`, is created and configured on demand; this kotlin library uses a multi-module project setup for separation of concern: 1. root module for configuring unit tests, 2. `cross-test-client` module for bundling a standalone test client, 3. `cross-test-server` module for bundling a standalone test server ## How to compile This library is managed using Gradle 6.9.2, run the following command (requires C++ thrift compiler): ```bash gradle build ``` ```bash gradle installDist ``` ## How to run cross test server / client ```bash gradle :cross-test-server:run ``` ```bash gradle :cross-test-client:run ``` thrift-0.19.0/lib/kotlin/cross-test-server/0000777000000000000000000000000014472647462020603 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/0000777000000000000000000000000014303472263021356 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/0000777000000000000000000000000014303472263022302 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/resources/0000777000000000000000000000000014303740367024317 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/resources/logback.xml0000644000000000000000000000237314303740367026444 0ustar00rootroot00000000000000 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/0000777000000000000000000000000014303472263023602 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/org/0000777000000000000000000000000014303472263024371 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/org/apache/0000777000000000000000000000000014303472263025612 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/org/apache/thrift/0000777000000000000000000000000014303472263027112 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/org/apache/thrift/test/0000777000000000000000000000000014472647462030105 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/org/apache/thrift/test/TestHandler.kt0000644000000000000000000002036014370300523032634 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test import java.nio.ByteBuffer import java.util.* import kotlin.collections.HashMap import kotlinx.coroutines.delay import org.apache.thrift.TException import org.slf4j.Logger import org.slf4j.LoggerFactory import thrift.test.Insanity import thrift.test.Numberz import thrift.test.ThriftTest import thrift.test.Xception import thrift.test.Xception2 import thrift.test.Xtruct import thrift.test.Xtruct2 class TestHandler : ThriftTest { companion object { private val logger: Logger = LoggerFactory.getLogger(TestHandler::class.java) } override suspend fun testVoid() { logger.info("testVoid()\n") } override suspend fun testString(thing: String): String { logger.info("testString(\"$thing\")\n") return thing } override suspend fun testBool(thing: Boolean): Boolean { logger.info("testBool($thing)\n") return thing } override suspend fun testByte(thing: Byte): Byte { logger.info("testByte($thing)\n") return thing } override suspend fun testI32(thing: Int): Int { logger.info("testI32($thing)\n") return thing } override suspend fun testI64(thing: Long): Long { logger.info("testI64($thing)\n") return thing } override suspend fun testDouble(thing: Double): Double { logger.info("testDouble($thing)\n") return thing } override suspend fun testBinary(thing: ByteArray): ByteArray { val buffer = ByteBuffer.wrap(thing) val sb = StringBuilder(buffer.remaining() * 3) buffer.mark() var limit = 0 // limit output to keep the log size sane while (buffer.remaining() > 0 && ++limit < 1024) { sb.append(String.format("%02X ", buffer.get())) } if (buffer.remaining() > 0) { sb.append("...") // indicate we have more date } logger.info("testBinary($sb)\n") buffer.reset() return buffer.array() } override suspend fun testUuid(thing: UUID): UUID { logger.info("testUuid($thing)\n") return thing } override suspend fun testStruct(thing: Xtruct): Xtruct { logger.info( """testStruct({"${thing.string_thing}", ${thing.byte_thing}, ${thing.i32_thing}, ${thing.i64_thing}})""" ) return thing } override suspend fun testNest(thing: Xtruct2): Xtruct2 { val thing2: Xtruct = thing.struct_thing!! logger.info( """testNest({${thing.byte_thing}, {"${thing2.string_thing}", ${thing2.byte_thing}, ${thing2.i32_thing}, ${thing2.i64_thing}}, ${thing.i32_thing}})""".trimIndent() ) return thing } override suspend fun testMap(thing: Map): Map { logger.info("testMap({") logger.info("{}", thing) logger.info("})\n") return thing } override suspend fun testStringMap(thing: Map): Map { logger.info("testStringMap({") logger.info("{}", thing) logger.info("})\n") return thing } override suspend fun testSet(thing: Set): Set { logger.info("testSet({") var first = true for (elem in thing) { if (first) { first = false } else { logger.info(", ") } logger.info("{}", elem) } logger.info("})\n") return thing } override suspend fun testList(thing: List): List { logger.info("testList({") var first = true for (elem in thing) { if (first) { first = false } else { logger.info(", ") } logger.info("{}", elem) } logger.info("})\n") return thing } override suspend fun testEnum(thing: Numberz): Numberz { logger.info("testEnum($thing)\n") return thing } override suspend fun testTypedef(thing: Long): Long { logger.info("testTypedef($thing)\n") return thing } override suspend fun testMapMap(hello: Int): Map> { logger.info("testMapMap($hello)\n") val mapmap: MutableMap> = HashMap() val pos = HashMap() val neg = HashMap() for (i in 1..4) { pos[i] = i neg[-i] = -i } mapmap[4] = pos mapmap[-4] = neg return mapmap } override suspend fun testInsanity(argument: Insanity): Map> { logger.info("testInsanity()\n") val firstMap = mutableMapOf() val secondMap = mutableMapOf() firstMap[Numberz.TWO] = argument firstMap[Numberz.THREE] = argument val looney = Insanity().apply { userMap = HashMap() xtructs = listOf() } secondMap[Numberz.SIX] = looney val insane: MutableMap> = HashMap() insane[1L] = firstMap insane[2L] = secondMap return insane } override suspend fun testMulti( arg0: Byte, arg1: Int, arg2: Long, arg3: Map, arg4: Numberz, arg5: Long ): Xtruct { logger.info("testMulti()\n") val hello = Xtruct() hello.string_thing = "Hello2" hello.byte_thing = arg0 hello.i32_thing = arg1 hello.i64_thing = arg2 return hello } @Throws(Xception::class, TException::class) override suspend fun testException(arg: String) { logger.info("testException($arg)\n") when (arg) { "Xception" -> { val x = Xception() x.errorCode = 1001 x.setFieldValue(Xception._Fields.MESSAGE, arg) throw x } "TException" -> { // Unspecified exception should yield a TApplicationException on client side throw RuntimeException(arg) } else -> { val result = Xtruct() result.string_thing = arg } } return } @Throws(Xception::class, Xception2::class) override suspend fun testMultiException(arg0: String, arg1: String): Xtruct { logger.info("testMultiException($arg0, $arg1)\n") if (arg0 == "Xception") { val x = Xception() x.errorCode = 1001 x.setFieldValue(Xception._Fields.MESSAGE, "This is an Xception") throw x } else if (arg0 == "Xception2") { val x = Xception2() x.errorCode = 2002 x.struct_thing = Xtruct().apply { string_thing = "This is an Xception2" byte_thing = 0 i32_thing = 0 i64_thing = 0 } throw x } val result = Xtruct() result.string_thing = arg1 result.byte_thing = 0 result.i32_thing = 0 result.i64_thing = 0 return result } override suspend fun testOneway(secondsToSleep: Int) { logger.info("testOneway($secondsToSleep) => sleeping...") try { delay(secondsToSleep * 1000L) logger.info("Done sleeping!") } catch (ie: InterruptedException) { throw RuntimeException(ie) } } } thrift-0.19.0/lib/kotlin/cross-test-server/src/main/kotlin/org/apache/thrift/test/TestServer.kt0000644000000000000000000003061514472647462032554 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.enum import com.github.ajalt.clikt.parameters.types.int import com.github.ajalt.clikt.parameters.types.long import kotlinx.coroutines.GlobalScope import org.apache.thrift.TException import org.apache.thrift.TMultiplexedProcessor import org.apache.thrift.protocol.TBinaryProtocol import org.apache.thrift.protocol.TCompactProtocol import org.apache.thrift.protocol.TJSONProtocol import org.apache.thrift.protocol.TProtocol import org.apache.thrift.protocol.TProtocolFactory import org.apache.thrift.server.ServerContext import org.apache.thrift.server.TNonblockingServer import org.apache.thrift.server.TServer import org.apache.thrift.server.TServerEventHandler import org.apache.thrift.server.TSimpleServer import org.apache.thrift.server.TThreadPoolServer import org.apache.thrift.server.TThreadedSelectorServer import org.apache.thrift.transport.TNonblockingServerSocket import org.apache.thrift.transport.TNonblockingServerSocket.NonblockingAbstractServerSocketArgs import org.apache.thrift.transport.TSSLTransportFactory import org.apache.thrift.transport.TServerSocket import org.apache.thrift.transport.TServerSocket.ServerSocketTransportArgs import org.apache.thrift.transport.TTransport import org.apache.thrift.transport.TTransportFactory import org.apache.thrift.transport.TZlibTransport import org.apache.thrift.transport.layered.TFastFramedTransport import org.apache.thrift.transport.layered.TFramedTransport import thrift.test.SecondService import thrift.test.SecondServiceProcessor import thrift.test.ThriftTestProcessor object TestServer { // Multiplexed Protocol Support Details: // // For multiplexed testing we always use binary protocol underneath. // // "ThriftTest" named service implements "ThriftTest" from ThriftTest.thrift // "SecondService" named service implements "SecondService" from ThriftTest.thrift // In addition, to support older non-multiplexed clients using the same concrete protocol // the multiplexed processor is taught to use "ThriftTest" if the incoming request has no // multiplexed call name decoration. internal class SecondHandler : SecondService { @Throws(TException::class) override suspend fun secondtestString(thing: String): String { return "testString(\"$thing\")" } } internal class TestServerContext(var connectionId: Int) : ServerContext { override fun unwrap(iface: Class): T { try { return if (isWrapperFor(iface)) { iface.cast(this) } else { throw RuntimeException("The context is not a wrapper for " + iface.name) } } catch (e: Exception) { throw RuntimeException( "The context is not a wrapper and does not implement the interface" ) } } override fun isWrapperFor(iface: Class<*>): Boolean { return iface.isInstance(this) } } internal class TestServerEventHandler() : TServerEventHandler { private var nextConnectionId = 1 override fun preServe() { println( "TServerEventHandler.preServe - called only once before server starts accepting connections" ) } override fun createContext(input: TProtocol, output: TProtocol): ServerContext { // we can create some connection level data which is stored while connection is alive & // served val ctx = TestServerContext(nextConnectionId++) println( "TServerEventHandler.createContext - connection #" + ctx.connectionId + " established" ) return ctx } override fun deleteContext( serverContext: ServerContext, input: TProtocol, output: TProtocol ) { val ctx = serverContext.unwrap(TestServerContext::class.java) println( "TServerEventHandler.deleteContext - connection #" + ctx.connectionId + " terminated" ) } override fun processContext( serverContext: ServerContext, inputTransport: TTransport, outputTransport: TTransport ) { val ctx = serverContext.unwrap(TestServerContext::class.java) println( "TServerEventHandler.processContext - connection #" + ctx.connectionId + " is ready to process next request" ) } } } enum class ServerType(val key: String) { Simple("simple"), ThreadPool("thread-pool"), NonBlocking("nonblocking"), ThreadedSelector("threaded-selector") } enum class ProtocolType(val key: String) { Binary("binary"), Multi("multi"), Json("json"), MultiJson("multij"), Compact("compact"), MultiCompact("multic") } enum class TransportType(val key: String) { Buffered("buffered"), FastFramed("fastframed"), Framed("framed"), Zlib("zlib") } class TestServerCommand : CliktCommand() { private val port: Int by option(help = "The cross test port to connect to").int().default(9090) private val protocolType: ProtocolType by option("--protocol", help = "Protocol type") .enum { it.key } .default(ProtocolType.Binary) private val transportType: TransportType by option("--transport", help = "Transport type") .enum { it.key } .default(TransportType.Buffered) private val serverType: ServerType by option("--server-type").enum { it.key }.default(ServerType.NonBlocking) private val useSSL: Boolean by option("--ssl", help = "Use SSL for encrypted transport").flag(default = false) private val stringLimit: Long by option("--string-limit").long().default(-1) private val containerLimit: Long by option("--container-limit").long().default(-1) @Suppress("OPT_IN_USAGE") override fun run() { val testHandler = TestHandler() val testProcessor = ThriftTestProcessor(testHandler, scope = GlobalScope) val secondHandler = TestServer.SecondHandler() val secondProcessor = SecondServiceProcessor(secondHandler, scope = GlobalScope) val serverEngine: TServer = getServerEngine( testProcessor, secondProcessor, serverType, port, protocolType, getProtocolFactory(), getTransportFactory(), useSSL ) // Set server event handler serverEngine.setServerEventHandler(TestServer.TestServerEventHandler()) // Run it println( "Starting the ${if (useSSL) "ssl server" else "server"} [$protocolType/$transportType/$serverType] on port $port" ) serverEngine.serve() } private fun getTransportFactory(): TTransportFactory = when (transportType) { TransportType.Framed -> { TFramedTransport.Factory() } TransportType.FastFramed -> { TFastFramedTransport.Factory() } TransportType.Zlib -> { TZlibTransport.Factory() } TransportType.Buffered -> { TTransportFactory() } } private fun getProtocolFactory(): TProtocolFactory = when (protocolType) { ProtocolType.Json, ProtocolType.MultiJson -> TJSONProtocol.Factory() ProtocolType.Compact, ProtocolType.MultiCompact -> TCompactProtocol.Factory(stringLimit, containerLimit) ProtocolType.Binary, ProtocolType.Multi -> TBinaryProtocol.Factory(stringLimit, containerLimit) } } fun main(args: Array) { TestServerCommand().main(args) } private fun getServerEngine( testProcessor: ThriftTestProcessor, secondProcessor: SecondServiceProcessor, serverType: ServerType, port: Int, protocolType: ProtocolType, tProtocolFactory: TProtocolFactory, tTransportFactory: TTransportFactory, ssl: Boolean ): TServer { val isMulti = protocolType == ProtocolType.Multi || protocolType == ProtocolType.MultiCompact || protocolType == ProtocolType.MultiJson // If we are multiplexing services in one server... val multiplexedProcessor = TMultiplexedProcessor() multiplexedProcessor.registerDefault(testProcessor) multiplexedProcessor.registerProcessor("ThriftTest", testProcessor) multiplexedProcessor.registerProcessor("SecondService", secondProcessor) when (serverType) { ServerType.NonBlocking, ServerType.ThreadedSelector -> { val tNonblockingServerSocket = TNonblockingServerSocket(NonblockingAbstractServerSocketArgs().port(port)) when (serverType) { ServerType.NonBlocking -> { val tNonblockingServerArgs = TNonblockingServer.Args(tNonblockingServerSocket) tNonblockingServerArgs.processor( if (isMulti) multiplexedProcessor else testProcessor ) tNonblockingServerArgs.protocolFactory(tProtocolFactory) tNonblockingServerArgs.transportFactory(tTransportFactory) return TNonblockingServer(tNonblockingServerArgs) } else -> { val tThreadedSelectorServerArgs = TThreadedSelectorServer.Args(tNonblockingServerSocket) tThreadedSelectorServerArgs.processor( if (isMulti) multiplexedProcessor else testProcessor ) tThreadedSelectorServerArgs.protocolFactory(tProtocolFactory) tThreadedSelectorServerArgs.transportFactory(tTransportFactory) return TThreadedSelectorServer(tThreadedSelectorServerArgs) } } } ServerType.Simple, ServerType.ThreadPool -> { // SSL socket val tServerSocket: TServerSocket = if (ssl) { TSSLTransportFactory.getServerSocket(port, 0) } else { TServerSocket(ServerSocketTransportArgs().port(port)) } when (serverType) { ServerType.Simple -> { val tServerArgs = TServer.Args(tServerSocket) tServerArgs.processor(if (isMulti) multiplexedProcessor else testProcessor) tServerArgs.protocolFactory(tProtocolFactory) tServerArgs.transportFactory(tTransportFactory) return TSimpleServer(tServerArgs) } else -> { val tThreadPoolServerArgs = TThreadPoolServer.Args(tServerSocket) tThreadPoolServerArgs.processor( if (isMulti) multiplexedProcessor else testProcessor ) tThreadPoolServerArgs.protocolFactory(tProtocolFactory) tThreadPoolServerArgs.transportFactory(tTransportFactory) return TThreadPoolServer(tThreadPoolServerArgs) } } } } } thrift-0.19.0/lib/kotlin/cross-test-server/build.gradle.kts0000644000000000000000000000602014472647462023654 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ plugins { kotlin("jvm") java application id("com.ncorti.ktfmt.gradle") } repositories { mavenCentral() } val slf4jVersion: String by project val httpcoreVersion: String by project val logbackVersion: String by project val kotlinxCoroutinesJdk8Version: String by project val cliktVersion: String by project dependencies { implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") // clikt is used to drive command line parsing and validation implementation("com.github.ajalt.clikt:clikt:$cliktVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlinxCoroutinesJdk8Version") implementation("org.apache.thrift:libthrift:INCLUDED") implementation("org.slf4j:slf4j-api:$slf4jVersion") implementation("org.apache.httpcomponents:httpcore:$httpcoreVersion") implementation("ch.qos.logback:logback-classic:$logbackVersion") testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit") } kotlin { jvmToolchain { (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(8)) } } tasks { application { applicationName = "TestServer" mainClass.set("org.apache.thrift.test.TestServerKt") } if (JavaVersion.current().isJava11Compatible) { ktfmt { kotlinLangStyle() } } task("compileThrift") { val thriftBin = if (hasProperty("thrift.compiler")) { file(property("thrift.compiler")) } else { project.rootDir.resolve("../../compiler/cpp/thrift") } val outputDir = layout.buildDirectory.dir("generated-sources") doFirst { mkdir(outputDir) } commandLine = listOf( thriftBin.absolutePath, "-gen", "kotlin", "-out", outputDir.get().toString(), project.rootDir.resolve("../../test/ThriftTest.thrift").absolutePath ) group = LifecycleBasePlugin.BUILD_GROUP } compileKotlin { dependsOn("compileThrift") } } sourceSets["main"].java { srcDir(layout.buildDirectory.dir("generated-sources")) } thrift-0.19.0/lib/kotlin/settings.gradle.kts0000644000000000000000000000204214472647462021003 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ pluginManagement { plugins { kotlin("jvm") version "1.8.22" id("com.ncorti.ktfmt.gradle") version "0.12.0" } } rootProject.name = "libthrift-kotlin" include("cross-test-client", "cross-test-server") includeBuild("../java") thrift-0.19.0/lib/kotlin/build.gradle.kts0000644000000000000000000000465114472647462020252 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ plugins { kotlin("jvm") id("com.ncorti.ktfmt.gradle") } repositories { mavenCentral() } dependencies { implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.7.1") implementation("org.apache.thrift:libthrift:INCLUDED") testImplementation(kotlin("test")) } kotlin { jvmToolchain { (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(8)) } } tasks.withType { kotlinOptions.jvmTarget = "1.8" } tasks { if (JavaVersion.current().isJava11Compatible) { ktfmt { kotlinLangStyle() } } test { useJUnitPlatform() } task("compileThrift") { val thriftBin = if (hasProperty("thrift.compiler")) { file(property("thrift.compiler")!!) } else { project.rootDir.resolve("../../compiler/cpp/thrift") } val outputDir = layout.buildDirectory.dir("generated-sources") doFirst { mkdir(outputDir) } commandLine = listOf( thriftBin.absolutePath, "-gen", "kotlin", "-out", outputDir.get().toString(), layout.projectDirectory.file("src/test/resources/AnnotationTest.thrift").asFile.absolutePath ) group = LifecycleBasePlugin.BUILD_GROUP } compileKotlin { dependsOn("compileThrift") } } sourceSets["main"].java { srcDir(layout.buildDirectory.dir("generated-sources")) } thrift-0.19.0/lib/kotlin/cross-test-client/0000777000000000000000000000000014472647462020553 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/0000777000000000000000000000000014303472263021326 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/0000777000000000000000000000000014303472263022252 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/resources/0000777000000000000000000000000014303740367024267 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/resources/logback.xml0000644000000000000000000000237414303740367026415 0ustar00rootroot00000000000000 %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n thrift-0.19.0/lib/kotlin/cross-test-client/src/main/kotlin/0000777000000000000000000000000014303472263023552 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/kotlin/org/0000777000000000000000000000000014303472263024341 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/kotlin/org/apache/0000777000000000000000000000000014303472263025562 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/kotlin/org/apache/thrift/0000777000000000000000000000000014303472263027062 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/kotlin/org/apache/thrift/test/0000777000000000000000000000000014472647462030055 5ustar00rootroot00000000000000thrift-0.19.0/lib/kotlin/cross-test-client/src/main/kotlin/org/apache/thrift/test/TestClient.kt0000644000000000000000000006777114472647462032511 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.thrift.test import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.flag import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.types.enum import com.github.ajalt.clikt.parameters.types.int import java.nio.ByteBuffer import kotlin.math.abs import kotlin.system.exitProcess import kotlinx.coroutines.runBlocking import org.apache.thrift.TApplicationException import org.apache.thrift.TException import org.apache.thrift.TSerializer import org.apache.thrift.async.TAsyncClientManager import org.apache.thrift.protocol.TBinaryProtocol import org.apache.thrift.protocol.TCompactProtocol import org.apache.thrift.protocol.TJSONProtocol import org.apache.thrift.protocol.TProtocol import org.apache.thrift.protocol.TSimpleJSONProtocol import org.apache.thrift.transport.TNonblockingSocket import org.apache.thrift.transport.TNonblockingTransport import org.apache.thrift.transport.TTransport import thrift.test.Insanity import thrift.test.Numberz import thrift.test.SecondServiceClient import thrift.test.ThriftTestClient import thrift.test.Xception import thrift.test.Xception2 import thrift.test.Xtruct import thrift.test.Xtruct2 /** * Test Java client for thrift. Essentially just a copy of the C++ version, this makes a variety of * requests to enable testing for both performance and correctness of the output. */ const val ERR_BASETYPES = 1 const val ERR_STRUCTS = 2 const val ERR_CONTAINERS = 4 const val ERR_EXCEPTIONS = 8 const val ERR_PROTOCOLS = 16 const val ERR_UNKNOWN = 64 enum class ProtocolType(val key: String) { Binary("binary"), Multi("multi"), Json("json"), MultiJson("multij"), Compact("compact"), MultiCompact("multic") } enum class TransportType(val key: String) { Buffered("buffered"), Framed("framed"), FastFramed("fastframed"), Http("http") } class TestClient : CliktCommand() { private val host: String by option(help = "The cross test host to connect to").default("localhost") private val port: Int by option(help = "The cross test port to connect to").int().default(9090) private val numTests: Int by option("--testloops", "--n", help = "Number of runs in this test").int().default(1) private val protocolType: ProtocolType by option("--protocol", help = "Protocol type") .enum { it.key } .default(ProtocolType.Binary) private val transportType: TransportType by option("--transport", help = "Transport type") .enum { it.key } .default(TransportType.Buffered) private val useHttpClient: Boolean by option("--client", help = "Use http client").flag(default = false) private val useSSL: Boolean by option("--ssl", help = "Use SSL for encrypted transport").flag(default = false) private val useZlib: Boolean by option("--zlib", help = "Use zlib wrapper for compressed transport").flag(default = false) private val socketTimeout: Int by option("--timeout", help = "Socket timeout").int().default(1000) private fun createProtocol(transport: TTransport): TProtocol = when (protocolType) { ProtocolType.Binary, ProtocolType.Multi -> TBinaryProtocol(transport) ProtocolType.Compact, ProtocolType.MultiCompact -> TCompactProtocol(transport) ProtocolType.Json, ProtocolType.MultiJson -> TJSONProtocol(transport) } private fun createTransport(): TNonblockingTransport = when (transportType) { TransportType.Framed -> TNonblockingSocket(host, port, socketTimeout) else -> throw UnsupportedOperationException( "only frame transport type is supported for now, got $transportType" ) } private val clientManager = TAsyncClientManager() private fun createClient(): ThriftTestClient = ThriftTestClient({ createProtocol(it) }, clientManager, createTransport()) private fun createSecondServiceClient(): SecondServiceClient = SecondServiceClient({ createProtocol(it) }, clientManager, createTransport()) override fun run() = runBlocking { var testClient = createClient() val insane = Insanity() var timeMin: Long = 0 var timeMax: Long = 0 var timeTot: Long = 0 var returnCode = 0 for (test in 0 until numTests) { try { /** CONNECT TEST */ /** CONNECT TEST */ // if (!transport.isOpen) { // try { // transport.open() // } catch (ttx: TTransportException) { // ttx.printStackTrace() // println("Connect failed: " + ttx.message) // exitProcess(ERR_UNKNOWN) // } // } println("Test #${test + 1}, connect $host:$port") val start = System.nanoTime() /** VOID TEST */ /** VOID TEST */ returnCode = testClient.voidTest(returnCode) /** STRING TEST */ /** STRING TEST */ returnCode = testClient.stringTest(returnCode) /** Multiplexed test */ /** Multiplexed test */ returnCode = multiplexTest(returnCode) /** BYTE TEST */ /** BYTE TEST */ returnCode = testClient.byteTest(returnCode) /** I32 TEST */ /** I32 TEST */ returnCode = testClient.i32Test(returnCode) /** I64 TEST */ /** I64 TEST */ returnCode = testClient.i64Test(returnCode) /** DOUBLE TEST */ /** DOUBLE TEST */ returnCode = testClient.doubleTest(returnCode) /** BINARY TEST */ /** BINARY TEST */ returnCode = testClient.binaryTest(returnCode) /** STRUCT TEST */ /** STRUCT TEST */ val pair = testClient.structTest(returnCode) val out = pair.first returnCode = pair.second /** NESTED STRUCT TEST */ /** NESTED STRUCT TEST */ returnCode = testClient.nestedStructTest(out, returnCode) /** MAP TEST */ /** MAP TEST */ val testMapParam = (0..4).associateBy { 10 - it } printMap(testMapParam) val testMapResult: Map = testClient.testMap(testMapParam) printMap(testMapResult) if (testMapParam != testMapResult) { returnCode = returnCode or ERR_CONTAINERS println("*** FAILURE ***\n") } /** STRING MAP TEST */ /** STRING MAP TEST */ returnCode = testClient.stringMapTest(returnCode) /** SET TEST */ /** SET TEST */ val setout: MutableSet = HashSet() for (i in -2..2) { setout.add(i) } val setin: Set = testClient.testSet(setout) if (setout != setin) { returnCode = returnCode or ERR_CONTAINERS println("*** FAILURE ***\n") } /** LIST TEST */ /** LIST TEST */ val listout: MutableList = ArrayList() for (i in -2..2) { listout.add(i) } val listin: List = testClient.testList(listout) if (listout != listin) { returnCode = returnCode or ERR_CONTAINERS println("*** FAILURE ***\n") } /** ENUM TEST */ /** ENUM TEST */ returnCode = testClient.enumTest(returnCode) /** TYPEDEF TEST */ /** TYPEDEF TEST */ returnCode = testClient.typedefTest(returnCode) /** NESTED MAP TEST */ /** NESTED MAP TEST */ returnCode = testClient.nestedMapTest(returnCode) /** INSANITY TEST */ /** INSANITY TEST */ var insanityFailed = true try { val hello = Xtruct() hello.string_thing = "Hello2" hello.byte_thing = 2 hello.i32_thing = 2 hello.i64_thing = 2 val goodbye = Xtruct() goodbye.string_thing = "Goodbye4" goodbye.byte_thing = 4.toByte() goodbye.i32_thing = 4 goodbye.i64_thing = 4L insane.userMap = HashMap().apply { put(Numberz.EIGHT, 8L) put(Numberz.FIVE, 5L) } insane.xtructs = ArrayList().apply { add(goodbye) add(hello) } print("testInsanity()") val whoa: Map> = testClient.testInsanity(insane) print(" = {") for (key in whoa.keys) { val `val` = whoa[key]!! print("$key => {") for (k2 in `val`.keys) { val v2 = `val`[k2] print("$k2 => {") val userMap = v2!!.userMap print("{") if (userMap != null) { for (k3 in userMap.keys) { print(k3.toString() + " => " + userMap[k3] + ", ") } } print("}, ") val xtructs = v2.xtructs print("{") if (xtructs != null) { for ((string_thing, byte_thing, i32_thing, i64_thing) in xtructs) { print( "{\"$string_thing\", $byte_thing, $i32_thing, $i64_thing}, " ) } } print("}") print("}, ") } print("}, ") } print("}\n") if (whoa.size == 2 && whoa.containsKey(1L) && whoa.containsKey(2L)) { val firstMap = whoa[1L]!! val secondMap = whoa[2L]!! if ( firstMap.size == 2 && firstMap.containsKey(Numberz.TWO) && firstMap.containsKey(Numberz.THREE) && secondMap.size == 1 && secondMap.containsKey(Numberz.SIX) && insane == firstMap[Numberz.TWO] && insane == firstMap[Numberz.THREE] ) { val six = secondMap[Numberz.SIX]!! // Cannot use "new Insanity().equals(six)" because as of now, // struct/container // fields with default requiredness have isset=false for local instances // and // yet // received empty values from other languages like C++ have isset=true . if ((six.userMap?.size ?: 0) == 0 && (six.xtructs?.size ?: 0) == 0) { // OK insanityFailed = false } } } } catch (ex: Exception) { returnCode = returnCode or ERR_STRUCTS println("*** FAILURE ***\n") ex.printStackTrace(System.out) insanityFailed = false } if (insanityFailed) { returnCode = returnCode or ERR_STRUCTS println("*** FAILURE ***\n") } /** EXECPTION TEST */ /** EXECPTION TEST */ val pair2 = exceptionTest(testClient, returnCode) returnCode = pair2.first testClient = pair2.second /** MULTI EXCEPTION TEST */ /** MULTI EXCEPTION TEST */ val pair3 = multiExceptionTest(testClient, returnCode) returnCode = pair3.first testClient = pair3.second /** ONEWAY TEST */ /** ONEWAY TEST */ returnCode = testClient.onewayTest(returnCode) val stop = System.nanoTime() val tot = stop - start println("Total time: " + tot / 1000 + "us") if (timeMin == 0L || tot < timeMin) { timeMin = tot } if (tot > timeMax) { timeMax = tot } timeTot += tot // transport.close() } catch (x: Exception) { System.out.printf("*** FAILURE ***\n") x.printStackTrace() returnCode = returnCode or ERR_UNKNOWN } } val timeAvg = timeTot / numTests println("Min time: " + timeMin / 1000 + "us") println("Max time: " + timeMax / 1000 + "us") println("Avg time: " + timeAvg / 1000 + "us") try { val json = TSerializer(TSimpleJSONProtocol.Factory()).toString(insane) println("\nSample TSimpleJSONProtocol output:\n$json") } catch (x: TException) { println("*** FAILURE ***") x.printStackTrace() returnCode = returnCode or ERR_BASETYPES } exitProcess(returnCode) } private suspend fun multiplexTest(returnCode: Int): Int { var code = returnCode if ( protocolType == ProtocolType.Multi || protocolType == ProtocolType.MultiJson || protocolType == ProtocolType.MultiCompact ) { val secondClient: SecondServiceClient = createSecondServiceClient() print("secondtestString(\"Test2\")") val s = secondClient.secondtestString("Test2") print(" = \"$s\"\n") if (s != "testString(\"Test2\")") { code = code or ERR_PROTOCOLS println("*** FAILURE ***\n") } } return code } private suspend fun ThriftTestClient.enumTest(returnCode: Int): Int { var returnCode1 = returnCode print("testEnum(ONE)") var ret: Numberz = testEnum(Numberz.ONE) print(" = $ret\n") if (ret !== Numberz.ONE) { returnCode1 = returnCode1 or ERR_STRUCTS println("*** FAILURE ***\n") } print("testEnum(TWO)") ret = testEnum(Numberz.TWO) print(" = $ret\n") if (ret !== Numberz.TWO) { returnCode1 = returnCode1 or ERR_STRUCTS println("*** FAILURE ***\n") } print("testEnum(THREE)") ret = testEnum(Numberz.THREE) print(" = $ret\n") if (ret !== Numberz.THREE) { returnCode1 = returnCode1 or ERR_STRUCTS println("*** FAILURE ***\n") } print("testEnum(FIVE)") ret = testEnum(Numberz.FIVE) print(" = $ret\n") if (ret !== Numberz.FIVE) { returnCode1 = returnCode1 or ERR_STRUCTS println("*** FAILURE ***\n") } print("testEnum(EIGHT)") ret = testEnum(Numberz.EIGHT) print(" = $ret\n") if (ret !== Numberz.EIGHT) { returnCode1 = returnCode1 or ERR_STRUCTS println("*** FAILURE ***\n") } return returnCode1 } private fun printMap(testMapParam: Map) { print("testMap({") var first = true for (key in testMapParam.keys) { if (first) { first = false } else { print(", ") } print(key.toString() + " => " + testMapParam[key]) } print("})") } private suspend fun exceptionTest( testClient: ThriftTestClient, returnCode: Int ): Pair { var client = testClient var code = returnCode try { print("testClient.testException(\"Xception\") =>") client.testException("Xception") print(" void\n*** FAILURE ***\n") code = code or ERR_EXCEPTIONS } catch (e: Xception) { System.out.printf(" {%d, \"%s\"}\n", e.errorCode, e.message) client = createClient() } try { print("testClient.testException(\"TException\") =>") client.testException("TException") print(" void\n*** FAILURE ***\n") code = code or ERR_EXCEPTIONS } catch (e: TException) { System.out.printf(" {\"%s\"}\n", e.message) client = createClient() } try { print("testClient.testException(\"success\") =>") client.testException("success") print(" void\n") } catch (e: Exception) { System.out.printf(" exception\n*** FAILURE ***\n") code = code or ERR_EXCEPTIONS } return code to client } private suspend fun multiExceptionTest( testClient: ThriftTestClient, returnCode: Int ): Pair { var client = testClient var code = returnCode try { System.out.printf("testClient.testMultiException(\"Xception\", \"test 1\") =>") client.testMultiException("Xception", "test 1") print(" result\n*** FAILURE ***\n") code = code or ERR_EXCEPTIONS } catch (e: Xception) { System.out.printf(" {%d, \"%s\"}\n", e.errorCode, e.message) client = createClient() } try { System.out.printf("testClient.testMultiException(\"Xception2\", \"test 2\") =>") client.testMultiException("Xception2", "test 2") print(" result\n*** FAILURE ***\n") code = code or ERR_EXCEPTIONS } catch (e: Xception2) { System.out.printf(" {%d, {\"%s\"}}\n", e.errorCode, e.struct_thing!!.string_thing) client = createClient() } try { print("testClient.testMultiException(\"success\", \"test 3\") =>") val result: Xtruct = client.testMultiException("success", "test 3") System.out.printf(" {{\"%s\"}}\n", result.string_thing) } catch (e: Exception) { System.out.printf(" exception\n*** FAILURE ***\n") code = code or ERR_EXCEPTIONS } return code to client } } private suspend fun ThriftTestClient.typedefTest(returnCode: Int): Int { var returnCode1 = returnCode print("testTypedef(309858235082523)") val uid: Long = testTypedef(309858235082523L) print(" = $uid\n") if (uid != 309858235082523L) { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } return returnCode1 } private suspend fun ThriftTestClient.structTest(returnCode: Int): Pair { var code = returnCode print("testStruct({\"Zero\", 1, -3, -5})") val out = Xtruct() out.string_thing = "Zero" out.byte_thing = 1.toByte() out.i32_thing = -3 out.i64_thing = -5 val input: Xtruct = testStruct(out) print( """ = {"${input.string_thing}",${input.byte_thing}, ${input.i32_thing}, ${input.i64_thing}}""" ) if (input != out) { code = code or ERR_STRUCTS println("*** FAILURE ***\n") } return out to code } private suspend fun ThriftTestClient.onewayTest(returnCode: Int): Int { var returnCode1 = returnCode print("testOneway(3)...") val startOneway = System.nanoTime() testOneway(3) val onewayElapsedMillis = (System.nanoTime() - startOneway) / 1000000 if (onewayElapsedMillis > 200) { println("Oneway test took too long to execute failed: took " + onewayElapsedMillis + "ms") println("oneway calls are 'fire and forget' and therefore should not cause blocking.") println("Some transports (HTTP) have a required response, and typically this failure") println("means the transport response was delayed until after the execution") println("of the RPC. The server should post the transport response immediately and") println("before executing the RPC.") println("*** FAILURE ***") returnCode1 = returnCode1 or ERR_BASETYPES } else { println("Success - fire and forget only took " + onewayElapsedMillis + "ms") } return returnCode1 } private suspend fun ThriftTestClient.nestedMapTest(returnCode: Int): Int { var returnCode1 = returnCode print("testMapMap(1)") val mm: Map> = testMapMap(1) print(" = {") for (key in mm.keys) { print("$key => {") val m2 = mm[key]!! for (k2 in m2.keys) { print(k2.toString() + " => " + m2[k2] + ", ") } print("}, ") } print("}\n") if (mm.size != 2 || !mm.containsKey(4) || !mm.containsKey(-4)) { returnCode1 = returnCode1 or ERR_CONTAINERS println("*** FAILURE ***\n") } else { val m1 = mm[4]!! val m2 = mm[-4]!! if ( m1[1] != 1 || m1[2] != 2 || m1[3] != 3 || m1[4] != 4 || m2[-1] != -1 || m2[-2] != -2 || m2[-3] != -3 || m2[-4] != -4 ) { returnCode1 = returnCode1 or ERR_CONTAINERS println("*** FAILURE ***\n") } } return returnCode1 } private suspend fun ThriftTestClient.stringMapTest(returnCode: Int): Int { var returnCode1 = returnCode try { val smapout: MutableMap = HashMap() smapout["a"] = "2" smapout["b"] = "blah" smapout["some"] = "thing" var first = true for (key in smapout.keys) { if (first) { first = false } else { print(", ") } print(key + " => " + smapout[key]) } print("})") val smapin: Map = testStringMap(smapout) print(" = {") first = true for (key in smapin.keys) { if (first) { first = false } else { print(", ") } print(key + " => " + smapout[key]) } print("}\n") if (smapout != smapin) { returnCode1 = returnCode1 or ERR_CONTAINERS println("*** FAILURE ***\n") } } catch (ex: Exception) { returnCode1 = returnCode1 or ERR_CONTAINERS println("*** FAILURE ***\n") ex.printStackTrace(System.out) } return returnCode1 } private suspend fun ThriftTestClient.nestedStructTest(out: Xtruct, returnCode: Int): Int { var code = returnCode print("testNest({1, {\"Zero\", 1, -3, -5}), 5}") val out2 = Xtruct2() out2.byte_thing = 1.toShort().toByte() out2.struct_thing = out out2.i32_thing = 5 val xstruct2: Xtruct2 = testNest(out2) val input = xstruct2.struct_thing!! print( """ = {${xstruct2.byte_thing}, {"${input.string_thing}", ${input.byte_thing}, ${input.i32_thing}, ${input.i64_thing}}, ${xstruct2.i32_thing}} """ ) if (xstruct2 != out2) { code = code or ERR_STRUCTS println("*** FAILURE ***\n") } return code } private suspend fun ThriftTestClient.binaryTest(returnCode: Int): Int { var returnCode1 = returnCode try { print("testBinary(-128...127) = ") val data = testByteArray val bin: ByteBuffer = ByteBuffer.wrap(testBinary(data)) bin.mark() val bytes = ByteArray(bin.limit() - bin.position()) bin[bytes] bin.reset() print("{") var first = true for (i in bytes.indices) { if (first) first = false else print(", ") print(bytes[i]) } println("}") if (ByteBuffer.wrap(data) != bin) { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } } catch (ex: Exception) { returnCode1 = returnCode1 or ERR_BASETYPES println("\n*** FAILURE ***\n") ex.printStackTrace(System.out) } return returnCode1 } private suspend fun ThriftTestClient.doubleTest(returnCode: Int): Int { var returnCode1 = returnCode print("testDouble(-5.325098235)") val dub: Double = testDouble(-5.325098235) print(" = $dub\n") if (abs(dub - -5.325098235) > 0.001) { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } return returnCode1 } private suspend fun ThriftTestClient.i64Test(returnCode: Int): Int { var returnCode1 = returnCode print("testI64(-34359738368)") val i64: Long = testI64(-34359738368L) print(" = $i64\n") if (i64 != -34359738368L) { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } return returnCode1 } private suspend fun ThriftTestClient.i32Test(returnCode: Int): Int { var returnCode1 = returnCode print("testI32(-1)") val i32: Int = testI32(-1) print(" = $i32\n") if (i32 != -1) { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } return returnCode1 } private suspend fun ThriftTestClient.byteTest(returnCode: Int): Int { var returnCode1 = returnCode print("testByte(1)") val i8: Byte = testByte(1.toByte()) print(" = $i8\n") if (i8.toInt() != 1) { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } return returnCode1 } private suspend fun ThriftTestClient.stringTest(returnCode: Int): Int { var returnCode1 = returnCode print("testString(\"Test\")") val s: String = testString("Test") print(" = \"$s\"\n") if (s != "Test") { returnCode1 = returnCode1 or ERR_BASETYPES println("*** FAILURE ***\n") } return returnCode1 } private suspend fun ThriftTestClient.voidTest(returnCode: Int): Int { var returnCode1 = returnCode try { print("testVoid()") testVoid() print(" = void\n") } catch (tax: TApplicationException) { tax.printStackTrace() returnCode1 = returnCode1 or ERR_BASETYPES } return returnCode1 } fun main(args: Array) { TestClient().main(args) } private val testByteArray = (-128..127).map { it.toByte() }.toByteArray() thrift-0.19.0/lib/kotlin/cross-test-client/build.gradle.kts0000644000000000000000000000621114472647462023626 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ plugins { kotlin("jvm") java application id("com.ncorti.ktfmt.gradle") } repositories { mavenCentral() } val slf4jVersion: String by project val httpclientVersion: String by project val httpcoreVersion: String by project val logbackVersion: String by project val kotlinxCoroutinesJdk8Version: String by project val cliktVersion: String by project dependencies { implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") // clikt is used to drive command line parsing and validation implementation("com.github.ajalt.clikt:clikt:$cliktVersion") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlinxCoroutinesJdk8Version") implementation("org.apache.thrift:libthrift:INCLUDED") implementation("org.slf4j:slf4j-api:$slf4jVersion") implementation("org.apache.httpcomponents:httpclient:$httpclientVersion") implementation("org.apache.httpcomponents:httpcore:$httpcoreVersion") implementation("ch.qos.logback:logback-classic:$logbackVersion") testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit") } kotlin { jvmToolchain { (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(8)) } } tasks { application { applicationName = "TestClient" mainClass.set("org.apache.thrift.test.TestClientKt") } if (JavaVersion.current().isJava11Compatible) { ktfmt { kotlinLangStyle() } } task("compileThrift") { val thriftBin = if (hasProperty("thrift.compiler")) { file(property("thrift.compiler")!!) } else { project.rootDir.resolve("../../compiler/cpp/thrift") } val outputDir = layout.buildDirectory.dir("generated-sources") doFirst { mkdir(outputDir) } commandLine = listOf( thriftBin.absolutePath, "-gen", "kotlin", "-out", outputDir.get().toString(), project.rootDir.resolve("../../test/ThriftTest.thrift").absolutePath ) group = LifecycleBasePlugin.BUILD_GROUP } compileKotlin { dependsOn("compileThrift") } } sourceSets["main"].java { srcDir(layout.buildDirectory.dir("generated-sources")) } thrift-0.19.0/lib/kotlin/Makefile.in0000644000000000000000000004353214472652516017235 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = lib/kotlin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ EXTRA_DIST = \ build.gradle.kts \ CMakeLists.txt \ cross-test-client \ cross-test-server \ gradle.properties \ README.md \ settings.gradle.kts \ src all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/kotlin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/kotlin/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs style-local: tags TAGS: ctags CTAGS: cscope cscopelist: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local check: check-am all-am: Makefile all-local installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: check-am install-am install-strip .PHONY: all all-am all-local check check-am check-local clean \ clean-generic clean-libtool clean-local cscopelist-am ctags-am \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am style-am style-local \ tags-am uninstall uninstall-am .PRECIOUS: Makefile export CLASSPATH all-local: $(GRADLE) $(GRADLE_OPTS) assemble \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain clean-local: $(GRADLE) $(GRADLE_OPTS) clean --console=plain precross: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) installDist \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain check-local: $(THRIFT) $(GRADLE) $(GRADLE_OPTS) test \ -Pthrift.version=$(PACKAGE_VERSION) \ -Pthrift.compiler=$(THRIFT) \ --console=plain # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/cpp/0000755000000000000000000000000014472652650014442 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/thrift.pc.in0000644000000000000000000000172414303740367016673 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Thrift Description: Thrift C++ API Version: @VERSION@ Libs: -L${libdir} -lthrift Cflags: -I${includedir} thrift-0.19.0/lib/cpp/Makefile.am0000644000000000000000000003043714370300523016467 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects nostdinc moc__%.cpp: %.h $(QT5_MOC) $(QT5_CFLAGS) $< -o $@ SUBDIRS = . if WITH_TESTS SUBDIRS += test endif pkgconfigdir = $(libdir)/pkgconfig lib_LTLIBRARIES = libthrift.la pkgconfig_DATA = thrift.pc libthrift_la_LDFLAGS = -release $(VERSION) libthrift_la_LIBADD = $(BOOST_LDFLAGS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) ## We only build the extra libraries if we have the dependencies, ## but we install all of the headers unconditionally. if AMX_HAVE_LIBEVENT lib_LTLIBRARIES += libthriftnb.la pkgconfig_DATA += thrift-nb.pc endif if AMX_HAVE_ZLIB lib_LTLIBRARIES += libthriftz.la pkgconfig_DATA += thrift-z.pc endif if AMX_HAVE_QT5 lib_LTLIBRARIES += libthriftqt5.la pkgconfig_DATA += thrift-qt5.pc endif AM_CXXFLAGS = -Wall -Wextra -pedantic AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(OPENSSL_INCLUDES) -I$(srcdir)/src -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS # Define the source files for the module libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \ src/thrift/TOutput.cpp \ src/thrift/VirtualProfiling.cpp \ src/thrift/async/TAsyncChannel.cpp \ src/thrift/async/TAsyncProtocolProcessor.cpp \ src/thrift/async/TConcurrentClientSyncInfo.cpp \ src/thrift/concurrency/ThreadManager.cpp \ src/thrift/concurrency/TimerManager.cpp \ src/thrift/processor/PeekProcessor.cpp \ src/thrift/protocol/TDebugProtocol.cpp \ src/thrift/protocol/TJSONProtocol.cpp \ src/thrift/protocol/TBase64Utils.cpp \ src/thrift/protocol/TMultiplexedProtocol.cpp \ src/thrift/protocol/TProtocol.cpp \ src/thrift/transport/TTransportException.cpp \ src/thrift/transport/TFDTransport.cpp \ src/thrift/transport/TFileTransport.cpp \ src/thrift/transport/TSimpleFileTransport.cpp \ src/thrift/transport/THttpTransport.cpp \ src/thrift/transport/THttpClient.cpp \ src/thrift/transport/THttpServer.cpp \ src/thrift/transport/TSocket.cpp \ src/thrift/transport/TPipe.cpp \ src/thrift/transport/TPipeServer.cpp \ src/thrift/transport/TSSLSocket.cpp \ src/thrift/transport/TSocketPool.cpp \ src/thrift/transport/TServerSocket.cpp \ src/thrift/transport/TSSLServerSocket.cpp \ src/thrift/transport/TNonblockingServerSocket.cpp \ src/thrift/transport/TNonblockingSSLServerSocket.cpp \ src/thrift/transport/TTransportUtils.cpp \ src/thrift/transport/TBufferTransports.cpp \ src/thrift/transport/TWebSocketServer.cpp \ src/thrift/transport/SocketCommon.cpp \ src/thrift/server/TConnectedClient.cpp \ src/thrift/server/TServer.cpp \ src/thrift/server/TServerFramework.cpp \ src/thrift/server/TSimpleServer.cpp \ src/thrift/server/TThreadPoolServer.cpp \ src/thrift/server/TThreadedServer.cpp libthrift_la_SOURCES += src/thrift/concurrency/Mutex.cpp \ src/thrift/concurrency/ThreadFactory.cpp \ src/thrift/concurrency/Thread.cpp \ src/thrift/concurrency/Monitor.cpp libthriftnb_la_SOURCES = src/thrift/server/TNonblockingServer.cpp \ src/thrift/async/TEvhttpServer.cpp \ src/thrift/async/TEvhttpClientChannel.cpp libthriftz_la_SOURCES = src/thrift/transport/TZlibTransport.cpp \ src/thrift/transport/THeaderTransport.cpp \ src/thrift/protocol/THeaderProtocol.cpp libthriftqt5_la_MOC = src/thrift/qt/moc__TQTcpServer.cpp nodist_libthriftqt5_la_SOURCES = $(libthriftqt5_la_MOC) libthriftqt5_la_SOURCES = src/thrift/qt/TQIODeviceTransport.cpp \ src/thrift/qt/TQTcpServer.cpp CLEANFILES = $(libthriftqt5_la_MOC) # Flags for the various libraries libthriftnb_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBEVENT_CPPFLAGS) libthriftz_la_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CPPFLAGS) libthriftqt5_la_CPPFLAGS = $(AM_CPPFLAGS) $(QT5_CFLAGS) if QT5_REDUCE_RELOCATIONS libthriftqt5_la_CPPFLAGS += -fPIC endif libthriftnb_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftz_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftqt5_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftnb_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LDFLAGS) $(ZLIB_LIBS) libthriftqt5_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS) include_thriftdir = $(includedir)/thrift include_thrift_HEADERS = \ $(top_builddir)/config.h \ src/thrift/numeric_cast.h \ src/thrift/thrift-config.h \ src/thrift/thrift_export.h \ src/thrift/TDispatchProcessor.h \ src/thrift/Thrift.h \ src/thrift/TOutput.h \ src/thrift/TProcessor.h \ src/thrift/TApplicationException.h \ src/thrift/TLogging.h \ src/thrift/TToString.h \ src/thrift/TBase.h \ src/thrift/TConfiguration.h \ src/thrift/TNonCopyable.h include_concurrencydir = $(include_thriftdir)/concurrency include_concurrency_HEADERS = \ src/thrift/concurrency/Exception.h \ src/thrift/concurrency/Mutex.h \ src/thrift/concurrency/Monitor.h \ src/thrift/concurrency/ThreadFactory.h \ src/thrift/concurrency/Thread.h \ src/thrift/concurrency/ThreadManager.h \ src/thrift/concurrency/TimerManager.h \ src/thrift/concurrency/FunctionRunner.h include_protocoldir = $(include_thriftdir)/protocol include_protocol_HEADERS = \ src/thrift/protocol/TEnum.h \ src/thrift/protocol/TList.h \ src/thrift/protocol/TSet.h \ src/thrift/protocol/TMap.h \ src/thrift/protocol/TBinaryProtocol.h \ src/thrift/protocol/TBinaryProtocol.tcc \ src/thrift/protocol/TCompactProtocol.h \ src/thrift/protocol/TCompactProtocol.tcc \ src/thrift/protocol/TDebugProtocol.h \ src/thrift/protocol/THeaderProtocol.h \ src/thrift/protocol/TBase64Utils.h \ src/thrift/protocol/TJSONProtocol.h \ src/thrift/protocol/TMultiplexedProtocol.h \ src/thrift/protocol/TProtocolDecorator.h \ src/thrift/protocol/TProtocolTap.h \ src/thrift/protocol/TProtocolTypes.h \ src/thrift/protocol/TProtocolException.h \ src/thrift/protocol/TVirtualProtocol.h \ src/thrift/protocol/TProtocol.h include_transportdir = $(include_thriftdir)/transport include_transport_HEADERS = \ src/thrift/transport/PlatformSocket.h \ src/thrift/transport/TFDTransport.h \ src/thrift/transport/TFileTransport.h \ src/thrift/transport/THeaderTransport.h \ src/thrift/transport/TSimpleFileTransport.h \ src/thrift/transport/TServerSocket.h \ src/thrift/transport/TSSLServerSocket.h \ src/thrift/transport/TServerTransport.h \ src/thrift/transport/TNonblockingServerTransport.h \ src/thrift/transport/TNonblockingServerSocket.h \ src/thrift/transport/TNonblockingSSLServerSocket.h \ src/thrift/transport/THttpTransport.h \ src/thrift/transport/THttpClient.h \ src/thrift/transport/THttpServer.h \ src/thrift/transport/TSocket.h \ src/thrift/transport/TSocketUtils.h \ src/thrift/transport/TPipe.h \ src/thrift/transport/TPipeServer.h \ src/thrift/transport/TSSLSocket.h \ src/thrift/transport/TSocketPool.h \ src/thrift/transport/TVirtualTransport.h \ src/thrift/transport/TTransport.h \ src/thrift/transport/TTransportException.h \ src/thrift/transport/TTransportUtils.h \ src/thrift/transport/TBufferTransports.h \ src/thrift/transport/TShortReadTransport.h \ src/thrift/transport/TZlibTransport.h \ src/thrift/transport/TWebSocketServer.h \ src/thrift/transport/SocketCommon.h include_serverdir = $(include_thriftdir)/server include_server_HEADERS = \ src/thrift/server/TConnectedClient.h \ src/thrift/server/TServer.h \ src/thrift/server/TServerFramework.h \ src/thrift/server/TSimpleServer.h \ src/thrift/server/TThreadPoolServer.h \ src/thrift/server/TThreadedServer.h \ src/thrift/server/TNonblockingServer.h include_processordir = $(include_thriftdir)/processor include_processor_HEADERS = \ src/thrift/processor/PeekProcessor.h \ src/thrift/processor/StatsProcessor.h \ src/thrift/processor/TMultiplexedProcessor.h include_asyncdir = $(include_thriftdir)/async include_async_HEADERS = \ src/thrift/async/TAsyncChannel.h \ src/thrift/async/TAsyncDispatchProcessor.h \ src/thrift/async/TAsyncProcessor.h \ src/thrift/async/TAsyncBufferProcessor.h \ src/thrift/async/TAsyncProtocolProcessor.h \ src/thrift/async/TConcurrentClientSyncInfo.h \ src/thrift/async/TEvhttpClientChannel.h \ src/thrift/async/TEvhttpServer.h include_qtdir = $(include_thriftdir)/qt include_qt_HEADERS = \ src/thrift/qt/TQIODeviceTransport.h \ src/thrift/qt/TQTcpServer.h WINDOWS_DIST = \ src/thrift/windows \ thrift.sln \ libthrift.vcxproj \ libthrift.vcxproj.filters \ libthriftnb.vcxproj \ libthriftnb.vcxproj.filters \ 3rdparty.props EXTRA_DIST = \ CMakeLists.txt \ coding_standards.md \ README.md \ thrift-nb.pc.in \ thrift.pc.in \ thrift-z.pc.in \ thrift-qt5.pc.in \ src/thrift/qt/CMakeLists.txt \ $(WINDOWS_DIST) style-local: $(CPPSTYLE_CMD) thrift-0.19.0/lib/cpp/CMakeLists.txt0000644000000000000000000001554614370300523017177 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Remove the following once lib/cpp no longer depends on boost headers: include(BoostMacros) REQUIRE_BOOST_HEADERS() include_directories(src) if(NOT BUILD_SHARED_LIBS) add_definitions("-DTHRIFT_STATIC_DEFINE") endif() # Create the thrift C++ library set(thriftcpp_SOURCES src/thrift/TApplicationException.cpp src/thrift/TOutput.cpp src/thrift/async/TAsyncChannel.cpp src/thrift/async/TAsyncProtocolProcessor.cpp src/thrift/async/TConcurrentClientSyncInfo.h src/thrift/async/TConcurrentClientSyncInfo.cpp src/thrift/concurrency/ThreadManager.cpp src/thrift/concurrency/TimerManager.cpp src/thrift/processor/PeekProcessor.cpp src/thrift/protocol/TBase64Utils.cpp src/thrift/protocol/TDebugProtocol.cpp src/thrift/protocol/TJSONProtocol.cpp src/thrift/protocol/TMultiplexedProtocol.cpp src/thrift/protocol/TProtocol.cpp src/thrift/transport/TTransportException.cpp src/thrift/transport/TFDTransport.cpp src/thrift/transport/TSimpleFileTransport.cpp src/thrift/transport/THttpTransport.cpp src/thrift/transport/THttpClient.cpp src/thrift/transport/THttpServer.cpp src/thrift/transport/TSocket.cpp src/thrift/transport/TSocketPool.cpp src/thrift/transport/TServerSocket.cpp src/thrift/transport/TTransportUtils.cpp src/thrift/transport/TBufferTransports.cpp src/thrift/transport/SocketCommon.cpp src/thrift/server/TConnectedClient.cpp src/thrift/server/TServerFramework.cpp src/thrift/server/TSimpleServer.cpp src/thrift/server/TThreadPoolServer.cpp src/thrift/server/TThreadedServer.cpp ) # These files don't work on Windows CE as there is no pipe support # TODO: These files won't work with UNICODE support on windows. If fixed this can be re-added. if (NOT WINCE) list(APPEND thriftcpp_SOURCES src/thrift/transport/TPipe.cpp src/thrift/transport/TPipeServer.cpp src/thrift/transport/TFileTransport.cpp ) endif() if (WIN32) list(APPEND thriftcpp_SOURCES src/thrift/windows/TWinsockSingleton.cpp src/thrift/windows/SocketPair.cpp src/thrift/windows/GetTimeOfDay.cpp src/thrift/windows/WinFcntl.cpp ) if(NOT WINCE) # This file uses pipes so it currently won't work on Windows CE list(APPEND thriftcpp_SOURCES src/thrift/windows/OverlappedSubmissionThread.cpp ) endif() else() # These files evaluate to nothing on Windows, so omit them from the # Windows build list(APPEND thriftcpp_SOURCES src/thrift/VirtualProfiling.cpp src/thrift/server/TServer.cpp ) endif() # If OpenSSL is not found or disabled just ignore the OpenSSL stuff if(OPENSSL_FOUND AND WITH_OPENSSL) list(APPEND thriftcpp_SOURCES src/thrift/transport/TSSLSocket.cpp src/thrift/transport/TSSLServerSocket.cpp src/thrift/transport/TWebSocketServer.h src/thrift/transport/TWebSocketServer.cpp ) if(TARGET OpenSSL::SSL OR TARGET OpenSSL::Crypto) if(TARGET OpenSSL::SSL) list(APPEND SYSLIBS OpenSSL::SSL) endif() if(TARGET OpenSSL::Crypto) list(APPEND SYSLIBS OpenSSL::Crypto) endif() else() include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") list(APPEND SYSLIBS "${OPENSSL_LIBRARIES}") endif() endif() if(UNIX) if(ANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") else() list(APPEND SYSLIBS pthread) endif() endif() set(thriftcpp_threads_SOURCES src/thrift/concurrency/ThreadFactory.cpp src/thrift/concurrency/Thread.cpp src/thrift/concurrency/Monitor.cpp src/thrift/concurrency/Mutex.cpp ) # Thrift non blocking server set(thriftcppnb_SOURCES src/thrift/server/TNonblockingServer.cpp src/thrift/transport/TNonblockingServerSocket.cpp src/thrift/async/TEvhttpServer.cpp src/thrift/async/TEvhttpClientChannel.cpp ) # If OpenSSL is not found or disabled just ignore the OpenSSL stuff if(OPENSSL_FOUND AND WITH_OPENSSL) list(APPEND thriftcppnb_SOURCES src/thrift/transport/TNonblockingSSLServerSocket.cpp ) endif() # Thrift zlib transport set(thriftcppz_SOURCES src/thrift/transport/TZlibTransport.cpp src/thrift/protocol/THeaderProtocol.cpp src/thrift/transport/THeaderTransport.cpp src/thrift/protocol/THeaderProtocol.cpp src/thrift/transport/THeaderTransport.cpp ) # Contains the thrift specific ADD_LIBRARY_THRIFT macro include(ThriftMacros) ADD_LIBRARY_THRIFT(thrift ${thriftcpp_SOURCES} ${thriftcpp_threads_SOURCES}) target_link_libraries(thrift PUBLIC ${SYSLIBS}) if(WIN32) target_link_libraries(thrift PUBLIC ws2_32) endif() ADD_PKGCONFIG_THRIFT(thrift) if(WITH_LIBEVENT) find_package(Libevent REQUIRED) # Libevent comes with CMake support from upstream include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS}) ADD_LIBRARY_THRIFT(thriftnb ${thriftcppnb_SOURCES}) target_link_libraries(thriftnb PUBLIC thrift) if(TARGET libevent::core AND TARGET libevent::extra) # libevent was found via its cmake config, use modern style targets target_link_libraries(thriftnb PUBLIC libevent::core libevent::extra) else() target_link_libraries(thriftnb PUBLIC ${LIBEVENT_LIBRARIES}) endif() ADD_PKGCONFIG_THRIFT(thrift-nb) endif() if(WITH_ZLIB) find_package(ZLIB REQUIRED) ADD_LIBRARY_THRIFT(thriftz ${thriftcppz_SOURCES}) target_link_libraries(thriftz PUBLIC thrift) if(TARGET ZLIB::ZLIB) target_link_libraries(thriftz PUBLIC ZLIB::ZLIB) else() include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS}) target_link_libraries(thriftz PUBLIC ${ZLIB_LIBRARIES}) endif() ADD_PKGCONFIG_THRIFT(thrift-z) endif() if(WITH_QT5) add_subdirectory(src/thrift/qt) ADD_PKGCONFIG_THRIFT(thrift-qt5) endif() if(MSVC) add_definitions("-DUNICODE -D_UNICODE") endif() # Install the headers install(DIRECTORY "src/thrift" DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h" PATTERN "*.tcc") # Copy config.h file install(DIRECTORY "${CMAKE_BINARY_DIR}/thrift" DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h") if(BUILD_TESTING) add_subdirectory(test) endif() thrift-0.19.0/lib/cpp/3rdparty.props0000644000000000000000000000172414303740367017277 0ustar00rootroot00000000000000 $(THIRD_PARTY)\boost\boost_1_47_0 $(THIRD_PARTY)\openssl\OpenSSL-Win32 $(THIRD_PARTY)\libevent-2.0.21-stable $(BOOST_ROOT) true $(OPENSSL_ROOT_DIR) true $(LIBEVENT_ROOT) true thrift-0.19.0/lib/cpp/libthriftnb.vcxproj.filters0000644000000000000000000000502414452237057022034 0ustar00rootroot00000000000000 {bf449d92-4be8-4f6f-a010-c536f57c6f13} {0294d0a6-ce46-4be8-a659-826d6e98ae41} {60fc9e5e-0866-4aba-8662-439bb4a461d3} {23fe2fde-a7c9-43ec-a409-7f53df5eee64} server async async async transport transport server async async async windows windows windows transport transport transport thrift-0.19.0/lib/cpp/thrift-nb.pc.in0000644000000000000000000000177314303740367017274 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Thrift Description: Thrift Nonblocking API Version: @VERSION@ Requires: thrift = @VERSION@ Libs: -L${libdir} -lthriftnb Cflags: -I${includedir} thrift-0.19.0/lib/cpp/src/0000755000000000000000000000000014472652647015237 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/0000755000000000000000000000000014472652650016531 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/thrift_export.h0000644000000000000000000000071414303740367021601 0ustar00rootroot00000000000000#ifndef THRIFT_EXPORT_H #define THRIFT_EXPORT_H #ifdef THRIFT_STATIC_DEFINE # define THRIFT_EXPORT #elif defined(_MSC_VER ) # ifndef THRIFT_EXPORT # ifdef thrift_EXPORTS /* We are building this library */ # define THRIFT_EXPORT __declspec(dllexport) # else /* We are using this library */ # define THRIFT_EXPORT __declspec(dllimport) # endif # endif #else # define THRIFT_EXPORT #endif #endif /* THRIFT_EXPORT_H */ thrift-0.19.0/lib/cpp/src/thrift/TOutput.h0000644000000000000000000000347014303740367020326 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_OUTPUT_H_ #define _THRIFT_OUTPUT_H_ 1 #include namespace apache { namespace thrift { class TOutput { public: TOutput(); inline void setOutputFunction(void (*function)(const char*)) { f_ = function; } inline void operator()(const char* message) { f_(message); } // It is important to have a const char* overload here instead of // just the string version, otherwise errno could be corrupted // if there is some problem allocating memory when constructing // the string. void perror(const char* message, int errno_copy); inline void perror(const std::string& message, int errno_copy) { perror(message.c_str(), errno_copy); } void printf(const char* message, ...); static void errorTimeWrapper(const char* msg); /** Just like strerror_r but returns a C++ string object. */ static std::string strerror_s(int errno_copy); private: void (*f_)(const char*); }; THRIFT_EXPORT extern TOutput GlobalOutput; } } // namespace apache::thrift #endif //_THRIFT_OUTPUT_H_ thrift-0.19.0/lib/cpp/src/thrift/windows/0000777000000000000000000000000014303740367020223 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/windows/WinFcntl.h0000644000000000000000000000243414303740367022117 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_FCNTL_H_ #define _THRIFT_WINDOWS_FCNTL_H_ 1 #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #ifndef _WIN32 #error This is a MSVC header only. #endif #ifdef _WIN32_WCE #include #endif // Win32 #include #include extern "C" { int thrift_fcntl(THRIFT_SOCKET fd, int cmd, int flags); } #ifdef _WIN32_WCE std::string thrift_wstr2str(std::wstring ws); #endif #endif // _THRIFT_WINDOWS_FCNTL_H_ thrift-0.19.0/lib/cpp/src/thrift/windows/WinFcntl.cpp0000644000000000000000000000263214303740367022452 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include int thrift_fcntl(THRIFT_SOCKET fd, int cmd, int flags) { if (cmd != THRIFT_F_GETFL && cmd != THRIFT_F_SETFL) { return -1; } if (flags != THRIFT_O_NONBLOCK && flags != 0) { return -1; } if (cmd == THRIFT_F_GETFL) { return 0; } int res; if (flags) { res = ioctlsocket(fd, FIONBIO, reinterpret_cast(&(flags = 1))); } else { res = ioctlsocket(fd, FIONBIO, reinterpret_cast(&(flags = 0))); } return res; } #ifdef _WIN32_WCE std::string thrift_wstr2str(std::wstring ws) { std::string s(ws.begin(), ws.end()); return s; } #endif thrift-0.19.0/lib/cpp/src/thrift/windows/GetTimeOfDay.h0000644000000000000000000000255714303740367022662 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_GETTIMEOFDAY_H_ #define _THRIFT_WINDOWS_GETTIMEOFDAY_H_ #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #ifndef _WIN32 #error This is a MSVC header only. #endif #include #include struct thrift_timespec { int64_t tv_sec; int64_t tv_nsec; }; int thrift_gettimeofday(struct timeval* tv, struct timezone* tz); int thrift_sleep(unsigned int seconds); int thrift_usleep(unsigned int micro_seconds); char* thrift_ctime_r(const time_t* _clock, char* _buf); #endif // _THRIFT_WINDOWS_GETTIMEOFDAY_H_ thrift-0.19.0/lib/cpp/src/thrift/windows/TWinsockSingleton.h0000644000000000000000000000345014303740367024016 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_WINDOWS_TWINSOCKSINGLETON_H_ #define _THRIFT_TRANSPORT_WINDOWS_TWINSOCKSINGLETON_H_ 1 #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #ifndef _WIN32 #error This is a MSVC header only. #endif #include // boost #include #include #include namespace apache { namespace thrift { namespace transport { /** * Winsock2 must be intialised once only in order to create sockets. This class * performs a one time initialisation when create is called. */ class TWinsockSingleton : private apache::thrift::TNonCopyable { public: typedef std::shared_ptr instance_ptr; private: TWinsockSingleton(void); public: ~TWinsockSingleton(void); public: static void create(void); private: static void init(void); private: static instance_ptr instance_ptr_; static std::once_flag flags_; }; } } } // apache::thrift::transport #endif // _THRIFT_TRANSPORT_WINDOWS_TWINSOCKSINGLETON_H_ thrift-0.19.0/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.cpp0000644000000000000000000001077514303740367026242 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include namespace apache { namespace thrift { namespace transport { TOverlappedWorkItem::TOverlappedWorkItem() : SLIST_ENTRY(), action(UNKNOWN), h(INVALID_HANDLE_VALUE), buffer(NULL), buffer_len(0), overlap(), last_error(0), success(TRUE) { } void TOverlappedWorkItem::reset(uint8_t* buf, uint32_t len, HANDLE event) { memset(&overlap, 0, sizeof(overlap)); overlap.hEvent = event; buffer = buf; buffer_len = len; last_error = 0; success = FALSE; } uint32_t TOverlappedWorkItem::overlappedResults(bool signal_failure) { DWORD bytes = 0; BOOL result = ::GetOverlappedResult(h, &overlap, &bytes, TRUE); if (signal_failure && !result) // get overlapped error case { GlobalOutput.perror("TPipe ::GetOverlappedResult errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::UNKNOWN, "TPipe: GetOverlappedResult failed"); } return bytes; } bool TOverlappedWorkItem::process() { BOOST_SCOPE_EXIT((&doneSubmittingEvent)) { SetEvent(doneSubmittingEvent.h); } BOOST_SCOPE_EXIT_END switch (action) { case (CONNECT): success = ::ConnectNamedPipe(h, &overlap); if (success == FALSE) last_error = ::GetLastError(); return true; case (READ): success = ::ReadFile(h, buffer, buffer_len, NULL, &overlap); if (success == FALSE) last_error = ::GetLastError(); return true; case (CANCELIO): success = ::CancelIo(h); if (success == FALSE) last_error = ::GetLastError(); return true; case (STOP): default: return false; } } void TOverlappedSubmissionThread::addWorkItem(TOverlappedWorkItem* item) { InterlockedPushEntrySList(&workList_, item); SetEvent(workAvailableEvent_.h); WaitForSingleObject(item->doneSubmittingEvent.h, INFINITE); } TOverlappedSubmissionThread* TOverlappedSubmissionThread::acquire_instance() { TAutoCrit lock(instanceGuard_); if (instance_ == NULL) { assert(instanceRefCount_ == 0); instance_ = new TOverlappedSubmissionThread; } ++instanceRefCount_; return instance_; } void TOverlappedSubmissionThread::release_instance() { TAutoCrit lock(instanceGuard_); if (--instanceRefCount_ == 0) { delete instance_; instance_ = NULL; } } TOverlappedSubmissionThread::TOverlappedSubmissionThread() { stopItem_.action = TOverlappedWorkItem::STOP; InitializeSListHead(&workList_); thread_ = (HANDLE)_beginthreadex(NULL, 0, thread_proc, this, 0, NULL); if (thread_ == 0) { GlobalOutput.perror("TOverlappedSubmissionThread unable to create thread, errno=", errno); throw TTransportException(TTransportException::NOT_OPEN, " TOverlappedSubmissionThread unable to create thread"); } } TOverlappedSubmissionThread::~TOverlappedSubmissionThread() { addWorkItem(&stopItem_); ::WaitForSingleObject(thread_, INFINITE); CloseHandle(thread_); } void TOverlappedSubmissionThread::run() { for (;;) { WaitForSingleObject(workAvailableEvent_.h, INFINITE); // todo check result SLIST_ENTRY* entry = NULL; while ((entry = InterlockedPopEntrySList(&workList_)) != NULL) { TOverlappedWorkItem& item = *static_cast(entry); if (!item.process()) return; } } } unsigned __stdcall TOverlappedSubmissionThread::thread_proc(void* addr) { static_cast(addr)->run(); return 0; } TCriticalSection TOverlappedSubmissionThread::instanceGuard_; TOverlappedSubmissionThread* TOverlappedSubmissionThread::instance_; uint32_t TOverlappedSubmissionThread::instanceRefCount_ = 0; } } } // apach::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp0000644000000000000000000000352414303740367024353 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include // boost #include namespace apache { namespace thrift { namespace transport { TWinsockSingleton::instance_ptr TWinsockSingleton::instance_ptr_(nullptr); std::once_flag TWinsockSingleton::flags_; //------------------------------------------------------------------------------ TWinsockSingleton::TWinsockSingleton(void) { WORD version(MAKEWORD(2, 2)); WSAData data = {0}; int error(WSAStartup(version, &data)); if (error != 0) { throw std::runtime_error("Failed to initialise Winsock."); } } //------------------------------------------------------------------------------ TWinsockSingleton::~TWinsockSingleton(void) { WSACleanup(); } //------------------------------------------------------------------------------ void TWinsockSingleton::create(void) { std::call_once(flags_, init); } //------------------------------------------------------------------------------ void TWinsockSingleton::init(void) { instance_ptr_.reset(new TWinsockSingleton); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.h0000644000000000000000000001117314303740367025700 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_OverlappedSubmissionThread_H_ #define _THRIFT_WINDOWS_OverlappedSubmissionThread_H_ 1 #ifndef _WIN32 #error "OverlappedSubmissionThread.h is only usable on Windows" #endif #include #include /* *** Why does this class exist? In short, because we want to enable something similar to a "select" loop, on Windows, with named pipes. The core of the "select" loop is a call to WaitForMultipleObjects. So that means we need a signalable object that indicates when data is available. A pipe handle doesn't do that. A pipe handle is signaled when a read or write completes, and if no one has called read or write, then the pipe handle is useless in WaitForMultipleObjects. So instead, we use overlapped I/O. With overlapped I/O, you call read, and associate an event with the read. When the read finishes, the event is signaled. This means that when you create a pipe, you start a read. When the customer calls read on your transport object, you wait for the last read to finish, and then kick off another. There is one big caveat to this though. The thread that initiated the read must stay alive. If the thread that initiated the read exits, then the read completes in an error state. To ensure that the initiating thread stays alive, we create a singleton thread whose sole responsibility is to manage this overlapped I/O requests. This introduces some overhead, but it is overhead that is necessary for correct behavior. This thread currently supports connect, read, and cancel io. So far, I haven't needed to put any writes on this thread, but if needed, it could be done. The client write buffer would need to be copied to ensure that it doesn't get invalidated. *** How does one use this class? Create a TOverlappedWorkItem, and fill in the action and "h", then call reset(). Your work item is now ready to be submitted to the overlapped submission thread. Create a TAutoOverlapThread, and call thread->addWorkItem with your work item. After addWorkItem completes, you may inspect last_error and success. At some point in the future, call workItem.overlappedResults to wait until the operation has completed. */ namespace apache { namespace thrift { namespace transport { struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) TOverlappedWorkItem : public SLIST_ENTRY { TOverlappedWorkItem(); enum action_t { UNKNOWN = 3000, CONNECT, READ, CANCELIO, STOP, }; TAutoResetEvent doneSubmittingEvent; action_t action; HANDLE h; uint8_t* buffer; uint32_t buffer_len; OVERLAPPED overlap; DWORD last_error; BOOL success; void reset(uint8_t* buf, uint32_t len, HANDLE event); uint32_t overlappedResults(bool signal_failure = true); bool process(); }; class TOverlappedSubmissionThread : apache::thrift::TNonCopyable { public: void addWorkItem(TOverlappedWorkItem* item); // singleton stuff public: static TOverlappedSubmissionThread* acquire_instance(); static void release_instance(); private: static TCriticalSection instanceGuard_; static TOverlappedSubmissionThread* instance_; static uint32_t instanceRefCount_; // thread details private: TOverlappedSubmissionThread(); ~TOverlappedSubmissionThread(); void run(); static unsigned __stdcall thread_proc(void* addr); private: DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) SLIST_HEADER workList_; TOverlappedWorkItem stopItem_; TAutoResetEvent workAvailableEvent_; HANDLE thread_; }; class TAutoOverlapThread : apache::thrift::TNonCopyable { private: TOverlappedSubmissionThread* p; public: TAutoOverlapThread() : p(TOverlappedSubmissionThread::acquire_instance()) {} ~TAutoOverlapThread() { TOverlappedSubmissionThread::release_instance(); } TOverlappedSubmissionThread* operator->() { return p; } }; } } } // apache::thrift::transport #endif thrift-0.19.0/lib/cpp/src/thrift/windows/SocketPair.h0000644000000000000000000000226014303740367022434 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_SOCKETPAIR_H_ #define _THRIFT_WINDOWS_SOCKETPAIR_H_ 1 #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #ifndef _WIN32 #error This is a MSVC header only. #endif // Win32 #include #include int thrift_socketpair(int d, int type, int protocol, THRIFT_SOCKET sv[2]); #endif // _THRIFT_WINDOWS_SOCKETPAIR_H_ thrift-0.19.0/lib/cpp/src/thrift/windows/Sync.h0000644000000000000000000000663214303740367021313 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_Sync_H_ #define _THRIFT_WINDOWS_Sync_H_ 1 #ifndef _WIN32 #error "windows/Sync.h is only usable on Windows" #endif #include #include // Including Windows.h can conflict with Winsock2 usage, and also // adds problematic macros like min() and max(). Try to work around: #ifndef NOMINMAX #define NOMINMAX #define _THRIFT_UNDEF_NOMINMAX #endif #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #define _THRIFT_UNDEF_WIN32_LEAN_AND_MEAN #endif #include #ifdef _THRIFT_UNDEF_NOMINMAX #undef NOMINMAX #undef _THRIFT_UNDEF_NOMINMAX #endif #ifdef _THRIFT_UNDEF_WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN #undef _THRIFT_UNDEF_WIN32_LEAN_AND_MEAN #endif /* Lightweight synchronization objects that only make sense on Windows. For cross-platform code, use the classes found in the concurrency namespace */ namespace apache { namespace thrift { struct TCriticalSection : apache::thrift::TNonCopyable { CRITICAL_SECTION cs; TCriticalSection() { InitializeCriticalSection(&cs); } ~TCriticalSection() { DeleteCriticalSection(&cs); } }; class TAutoCrit : apache::thrift::TNonCopyable { private: CRITICAL_SECTION* cs_; public: explicit TAutoCrit(TCriticalSection& cs) : cs_(&cs.cs) { EnterCriticalSection(cs_); } ~TAutoCrit() { LeaveCriticalSection(cs_); } }; struct TAutoResetEvent : apache::thrift::TNonCopyable { HANDLE h; TAutoResetEvent() { h = CreateEvent(nullptr, FALSE, FALSE, nullptr); if (h == nullptr) { GlobalOutput.perror("TAutoResetEvent unable to create event, GLE=", GetLastError()); throw apache::thrift::concurrency::SystemResourceException("CreateEvent failed"); } } ~TAutoResetEvent() { CloseHandle(h); } }; struct TManualResetEvent : apache::thrift::TNonCopyable { HANDLE h; TManualResetEvent() { h = CreateEvent(nullptr, TRUE, FALSE, nullptr); if (h == nullptr) { GlobalOutput.perror("TManualResetEvent unable to create event, GLE=", GetLastError()); throw apache::thrift::concurrency::SystemResourceException("CreateEvent failed"); } } ~TManualResetEvent() { CloseHandle(h); } }; struct TAutoHandle : apache::thrift::TNonCopyable { HANDLE h; explicit TAutoHandle(HANDLE h_ = INVALID_HANDLE_VALUE) : h(h_) {} ~TAutoHandle() { if (h != INVALID_HANDLE_VALUE) CloseHandle(h); } HANDLE release() { HANDLE retval = h; h = INVALID_HANDLE_VALUE; return retval; } void reset(HANDLE h_ = INVALID_HANDLE_VALUE) { if (h_ == h) return; if (h != INVALID_HANDLE_VALUE) CloseHandle(h); h = h_; } }; } } // apache::thrift #endif thrift-0.19.0/lib/cpp/src/thrift/windows/SocketPair.cpp0000644000000000000000000000615514303740367022776 0ustar00rootroot00000000000000/* socketpair.c * Copyright 2007 by Nathan C. Myers ; some rights reserved. * This code is Free Software. It may be copied freely, in original or * modified form, subject only to the restrictions that (1) the author is * relieved from all responsibilities for any use for any purpose, and (2) * this copyright notice must be retained, unchanged, in its entirety. If * for any reason the author might be held responsible for any consequences * of copying or use, license is withheld. */ /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include // stl #include // Win32 #include int thrift_socketpair(int d, int type, int protocol, THRIFT_SOCKET sv[2]) { THRIFT_UNUSED_VARIABLE(protocol); THRIFT_UNUSED_VARIABLE(type); THRIFT_UNUSED_VARIABLE(d); union { struct sockaddr_in inaddr; struct sockaddr addr; } a; THRIFT_SOCKET listener; int e; socklen_t addrlen = sizeof(a.inaddr); DWORD flags = 0; int reuse = 1; if (sv == 0) { WSASetLastError(WSAEINVAL); return SOCKET_ERROR; } listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listener == INVALID_SOCKET) return SOCKET_ERROR; memset(&a, 0, sizeof(a)); a.inaddr.sin_family = AF_INET; a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); a.inaddr.sin_port = 0; sv[0] = sv[1] = INVALID_SOCKET; do { // ignore errors coming out of this setsockopt. This is because // SO_EXCLUSIVEADDRUSE requires admin privileges on WinXP, but we don't // want to force socket pairs to be an admin. setsockopt(listener, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&reuse, (socklen_t)sizeof(reuse)); if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) break; if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) break; if (listen(listener, 1) == SOCKET_ERROR) break; sv[0] = WSASocket(AF_INET, SOCK_STREAM, 0, nullptr, 0, flags); if (sv[0] == INVALID_SOCKET) break; if (connect(sv[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) break; sv[1] = accept(listener, nullptr, nullptr); if (sv[1] == INVALID_SOCKET) break; closesocket(listener); return 0; } while (0); e = WSAGetLastError(); closesocket(listener); closesocket(sv[0]); closesocket(sv[1]); WSASetLastError(e); return SOCKET_ERROR; } thrift-0.19.0/lib/cpp/src/thrift/windows/config.h0000644000000000000000000000506614303740367021644 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_CONFIG_H_ #define _THRIFT_WINDOWS_CONFIG_H_ 1 #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER #ifndef _WIN32 #error "This is a Windows header only" #endif // Something that defines PRId64 is required to build #define HAVE_INTTYPES_H 1 #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0601 #endif #if defined(_M_IX86) || defined(_M_X64) #define ARITHMETIC_RIGHT_SHIFT 1 #define SIGNED_RIGHT_SHIFT_IS 1 #endif #ifndef __MINGW32__ #pragma warning(disable : 4996) // Deprecated posix name. #endif #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 #include #include #include #include #include #include #include // windows #include #include #ifndef __MINGW32__ #ifdef _WIN32_WCE #pragma comment(lib, "Ws2.lib") #else #pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "gdi32.lib") // For static OpenSSL #pragma comment(lib, "crypt32.lib") // For static OpenSSL #pragma comment(lib, "user32.lib") // For static OpenSSL #pragma comment(lib, "advapi32.lib") // For security APIs in TPipeServer #pragma comment(lib, "Shlwapi.lib") // For StrStrIA in TPipeServer #endif #endif // __MINGW32__ // Replicate the logic of afunix.h on Windows (the header is only present on // newer Windows SDKs) #ifdef HAVE_AF_UNIX_H #include #else #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 108 #endif typedef struct sockaddr_un { ADDRESS_FAMILY sun_family; // AF_UNIX char sun_path[UNIX_PATH_MAX]; // pathname } SOCKADDR_UN, *PSOCKADDR_UN; #endif // HAVE_AF_UNIX_H #endif // _THRIFT_WINDOWS_CONFIG_H_ thrift-0.19.0/lib/cpp/src/thrift/windows/GetTimeOfDay.cpp0000644000000000000000000000615214303740367023210 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include // win32 #if defined(__MINGW32__) #include #endif #if !defined(__MINGW32__) struct timezone { int tz_minuteswest; /* minutes W of Greenwich */ int tz_dsttime; /* type of dst correction */ }; #endif #if defined(__MINGW32__) int thrift_gettimeofday(struct timeval* tv, struct timezone* tz) { return gettimeofday(tv,tz); } #else #define WIN32_LEAN_AND_MEAN #include #include #include #include // This code started from a "FREE implementation" posted to Stack Overflow at: // https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows // added: assert // added: error handling // added: C++ style casts int thrift_gettimeofday(struct timeval * tp, struct timezone * tzp) { // We don't fill it in so prove nobody is looking for the data assert(tzp == nullptr); // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) // until 00:00:00 January 1, 1970 static const uint64_t EPOCH = static_cast(116444736000000000ULL); SYSTEMTIME system_time; FILETIME file_time; uint64_t time; GetSystemTime( &system_time ); if (!SystemTimeToFileTime( &system_time, &file_time )) { DWORD lastError = GetLastError(); std::stringstream ss; ss << "SystemTimeToFileTime failed: 0x" << std::hex << lastError; using apache::thrift::transport::TTransportException; throw TTransportException(TTransportException::INTERNAL_ERROR, ss.str()); } time = static_cast(file_time.dwLowDateTime ) ; time += static_cast(file_time.dwHighDateTime) << 32; tp->tv_sec = static_cast((time - EPOCH) / 10000000L); tp->tv_usec = static_cast(system_time.wMilliseconds * 1000); return 0; } #endif int thrift_sleep(unsigned int seconds) { ::Sleep(seconds * 1000); return 0; } int thrift_usleep(unsigned int microseconds) { unsigned int milliseconds = (microseconds + 999) / 1000; ::Sleep(milliseconds); return 0; } char* thrift_ctime_r(const time_t* _clock, char* _buf) { strcpy(_buf, ctime(_clock)); return _buf; } thrift-0.19.0/lib/cpp/src/thrift/windows/Operators.h0000644000000000000000000000242014303740367022344 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_WINDOWS_OPERATORS_H_ #define _THRIFT_WINDOWS_OPERATORS_H_ #if defined(_MSC_VER) && (_MSC_VER > 1200) #pragma once #endif // _MSC_VER namespace apache { namespace thrift { class TEnumIterator; inline bool operator==(const TEnumIterator&, const TEnumIterator&) { // Not entirely sure what the test should be here. It is only to enable // iterator debugging and is not used in release mode. return true; } } } // apache::thrift #endif // _THRIFT_WINDOWS_OPERATORS_H_ thrift-0.19.0/lib/cpp/src/thrift/numeric_cast.h0000644000000000000000000000406714370300523021347 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_NUMERIC_CAST_H #define THRIFT_NUMERIC_CAST_H #include #include #if defined(_MSC_VER) // avoid compiler warnings and errors in MSVC if max is defined as a macro #undef max #endif namespace apache { namespace thrift { /** * @brief Perform a safe numeric cast * * Previously this was provided by `boost::numeric_cast`. This * implementation reduces the dependency on `boost`. * * @tparam Dst The destination type * @tparam Src The source type * @param value The value to be converted * @return Dst The converted value * * @see SA49658182 */ template inline Dst numeric_cast(Src value) { typedef std::numeric_limits DstLim; typedef std::numeric_limits SrcLim; const bool positive_overflow_possible = DstLim::max() < SrcLim::max(); const bool negative_overflow_possible = DstLim::lowest() > SrcLim::lowest(); if (positive_overflow_possible && value > DstLim::max()) { throw std::bad_cast(); } if (negative_overflow_possible && (value < DstLim::lowest())) { throw std::bad_cast(); } // limits have been checked, therefore safe to cast return static_cast(value); } } // namespace thrift } // namespace apache #endif thrift-0.19.0/lib/cpp/src/thrift/TBase.h0000644000000000000000000000225614303740367017701 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TBASE_H_ #define _THRIFT_TBASE_H_ 1 #include #include namespace apache { namespace thrift { class TBase { public: virtual ~TBase() = default; virtual uint32_t read(protocol::TProtocol* iprot) = 0; virtual uint32_t write(protocol::TProtocol* oprot) const = 0; }; } } // apache::thrift #endif // #ifndef _THRIFT_TBASE_H_ thrift-0.19.0/lib/cpp/src/thrift/async/0000755000000000000000000000000014472652650017646 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncChannel.h0000644000000000000000000000416714303740367022515 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_ #define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1 #include #include #include namespace apache { namespace thrift { namespace transport { class TMemoryBuffer; } } } namespace apache { namespace thrift { namespace async { using apache::thrift::transport::TMemoryBuffer; class TAsyncChannel { public: typedef std::function VoidCallback; virtual ~TAsyncChannel() = default; // is the channel in a good state? virtual bool good() const = 0; virtual bool error() const = 0; virtual bool timedOut() const = 0; /** * Send a message over the channel. */ virtual void sendMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) = 0; /** * Receive a message from the channel. */ virtual void recvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) = 0; /** * Send a message over the channel and receive a response. */ virtual void sendAndRecvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, apache::thrift::transport::TMemoryBuffer* recvBuf); }; } } } // apache::thrift::async #endif // #ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TEvhttpServer.cpp0000644000000000000000000001140714303740367023136 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #ifndef HTTP_INTERNAL // libevent < 2 #define HTTP_INTERNAL 500 #endif using apache::thrift::transport::TMemoryBuffer; using std::shared_ptr; namespace apache { namespace thrift { namespace async { struct TEvhttpServer::RequestContext { struct evhttp_request* req; std::shared_ptr ibuf; std::shared_ptr obuf; RequestContext(struct evhttp_request* req); }; TEvhttpServer::TEvhttpServer(std::shared_ptr processor) : processor_(processor), eb_(nullptr), eh_(nullptr) { } TEvhttpServer::TEvhttpServer(std::shared_ptr processor, int port) : processor_(processor), eb_(nullptr), eh_(nullptr) { // Create event_base and evhttp. eb_ = event_base_new(); if (eb_ == nullptr) { throw TException("event_base_new failed"); } eh_ = evhttp_new(eb_); if (eh_ == nullptr) { event_base_free(eb_); throw TException("evhttp_new failed"); } // Bind to port. int ret = evhttp_bind_socket(eh_, nullptr, port); if (ret < 0) { evhttp_free(eh_); event_base_free(eb_); throw TException("evhttp_bind_socket failed"); } // Register a handler. If you use the other constructor, // you will want to do this yourself. // Don't forget to unregister before destorying this TEvhttpServer. evhttp_set_cb(eh_, "/", request, (void*)this); } TEvhttpServer::~TEvhttpServer() { if (eh_ != nullptr) { evhttp_free(eh_); } if (eb_ != nullptr) { event_base_free(eb_); } } int TEvhttpServer::serve() { if (eb_ == nullptr) { throw TException("Unexpected call to TEvhttpServer::serve"); } return event_base_dispatch(eb_); } TEvhttpServer::RequestContext::RequestContext(struct evhttp_request* req) : req(req), ibuf(new TMemoryBuffer(EVBUFFER_DATA(req->input_buffer), static_cast(EVBUFFER_LENGTH(req->input_buffer)))), obuf(new TMemoryBuffer()) { } void TEvhttpServer::request(struct evhttp_request* req, void* self) { try { static_cast(self)->process(req); } catch (std::exception& e) { evhttp_send_reply(req, HTTP_INTERNAL, e.what(), nullptr); } } void TEvhttpServer::process(struct evhttp_request* req) { auto* ctx = new RequestContext(req); return processor_->process(std::bind(&TEvhttpServer::complete, this, ctx, std::placeholders::_1), ctx->ibuf, ctx->obuf); } void TEvhttpServer::complete(RequestContext* ctx, bool success) { (void)success; std::unique_ptr ptr(ctx); int code = success ? 200 : 400; const char* reason = success ? "OK" : "Bad Request"; int rv = evhttp_add_header(ctx->req->output_headers, "Content-Type", "application/x-thrift"); if (rv != 0) { // TODO: Log an error. std::cerr << "evhttp_add_header failed " << __FILE__ << ":" << __LINE__ << std::endl; } struct evbuffer* buf = evbuffer_new(); if (buf == nullptr) { // TODO: Log an error. std::cerr << "evbuffer_new failed " << __FILE__ << ":" << __LINE__ << std::endl; } else { uint8_t* obuf; uint32_t sz; ctx->obuf->getBuffer(&obuf, &sz); int ret = evbuffer_add(buf, obuf, sz); if (ret != 0) { // TODO: Log an error. std::cerr << "evhttp_add failed with " << ret << " " << __FILE__ << ":" << __LINE__ << std::endl; } } evhttp_send_reply(ctx->req, code, reason, buf); if (buf != nullptr) { evbuffer_free(buf); } } struct event_base* TEvhttpServer::getEventBase() { return eb_; } } } } // apache::thrift::async thrift-0.19.0/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp0000644000000000000000000001523114303740367025426 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include namespace apache { namespace thrift { namespace async { using namespace ::apache::thrift::concurrency; TConcurrentClientSyncInfo::TConcurrentClientSyncInfo() : stop_(false), seqidMutex_(), // test rollover all the time nextseqid_((std::numeric_limits::max)()-10), seqidToMonitorMap_(), freeMonitors_(), writeMutex_(), readMutex_(), recvPending_(false), wakeupSomeone_(false), seqidPending_(0), fnamePending_(), mtypePending_(::apache::thrift::protocol::T_CALL) { freeMonitors_.reserve(MONITOR_CACHE_SIZE); } bool TConcurrentClientSyncInfo::getPending( std::string &fname, ::apache::thrift::protocol::TMessageType &mtype, int32_t &rseqid) { if(stop_) throwDeadConnection_(); wakeupSomeone_ = false; if(recvPending_) { recvPending_ = false; rseqid = seqidPending_; fname = fnamePending_; mtype = mtypePending_; return true; } return false; } void TConcurrentClientSyncInfo::updatePending( const std::string &fname, ::apache::thrift::protocol::TMessageType mtype, int32_t rseqid) { recvPending_ = true; seqidPending_ = rseqid; fnamePending_ = fname; mtypePending_ = mtype; MonitorPtr monitor; { Guard seqidGuard(seqidMutex_); auto i = seqidToMonitorMap_.find(rseqid); if(i == seqidToMonitorMap_.end()) throwBadSeqId_(); monitor = i->second; } monitor->notify(); } void TConcurrentClientSyncInfo::waitForWork(int32_t seqid) { MonitorPtr m; { Guard seqidGuard(seqidMutex_); m = seqidToMonitorMap_[seqid]; } while(true) { // be very careful about setting state in this loop that affects waking up. You may exit // this function, attempt to grab some work, and someone else could have beaten you (or not // left) the read mutex, and that will put you right back in this loop, with the mangled // state you left behind. if(stop_) throwDeadConnection_(); if(wakeupSomeone_) return; if(recvPending_ && seqidPending_ == seqid) return; m->waitForever(); } } void TConcurrentClientSyncInfo::throwBadSeqId_() { throw apache::thrift::TApplicationException( TApplicationException::BAD_SEQUENCE_ID, "server sent a bad seqid"); } void TConcurrentClientSyncInfo::throwDeadConnection_() { throw apache::thrift::transport::TTransportException( apache::thrift::transport::TTransportException::NOT_OPEN, "this client died on another thread, and is now in an unusable state"); } void TConcurrentClientSyncInfo::wakeupAnyone_(const Guard &) { wakeupSomeone_ = true; if(!seqidToMonitorMap_.empty()) { // The monitor map maps integers to monitors. Larger integers are more recent // messages. Since this is ordered, it means that the last element is the most recent. // We are trying to guess which thread will have its message complete next, so we are picking // the most recent. The oldest message is likely to be some polling, long lived message. // If we guess right, the thread we wake up will handle the message that comes in. // If we guess wrong, the thread we wake up will hand off the work to the correct thread, // costing us an extra context switch. seqidToMonitorMap_.rbegin()->second->notify(); } } void TConcurrentClientSyncInfo::markBad_(const Guard &) { wakeupSomeone_ = true; stop_ = true; for(auto & i : seqidToMonitorMap_) i.second->notify(); } TConcurrentClientSyncInfo::MonitorPtr TConcurrentClientSyncInfo::newMonitor_(const Guard &) { if(freeMonitors_.empty()) return std::make_shared(&readMutex_); MonitorPtr retval; //swapping to avoid an atomic operation retval.swap(freeMonitors_.back()); freeMonitors_.pop_back(); return retval; } void TConcurrentClientSyncInfo::deleteMonitor_( const Guard &, TConcurrentClientSyncInfo::MonitorPtr &m) /*noexcept*/ { if(freeMonitors_.size() > MONITOR_CACHE_SIZE) { m.reset(); return; } //freeMonitors_ was reserved up to MONITOR_CACHE_SIZE in the ctor, //so this shouldn't throw freeMonitors_.push_back(TConcurrentClientSyncInfo::MonitorPtr()); //swapping to avoid an atomic operation m.swap(freeMonitors_.back()); } int32_t TConcurrentClientSyncInfo::generateSeqId() { Guard seqidGuard(seqidMutex_); if(stop_) throwDeadConnection_(); if(!seqidToMonitorMap_.empty()) if(nextseqid_ == seqidToMonitorMap_.begin()->first) throw apache::thrift::TApplicationException( TApplicationException::BAD_SEQUENCE_ID, "about to repeat a seqid"); int32_t newSeqId = nextseqid_; if (nextseqid_ == (std::numeric_limits::max)()) nextseqid_ = (std::numeric_limits::min)(); else ++nextseqid_; seqidToMonitorMap_[newSeqId] = newMonitor_(seqidGuard); return newSeqId; } TConcurrentRecvSentry::TConcurrentRecvSentry(TConcurrentClientSyncInfo *sync, int32_t seqid) : sync_(*sync), seqid_(seqid), committed_(false) { sync_.getReadMutex().lock(); } TConcurrentRecvSentry::~TConcurrentRecvSentry() { { Guard seqidGuard(sync_.seqidMutex_); sync_.deleteMonitor_(seqidGuard, sync_.seqidToMonitorMap_[seqid_]); sync_.seqidToMonitorMap_.erase(seqid_); if(committed_) sync_.wakeupAnyone_(seqidGuard); else sync_.markBad_(seqidGuard); } sync_.getReadMutex().unlock(); } void TConcurrentRecvSentry::commit() { committed_ = true; } TConcurrentSendSentry::TConcurrentSendSentry(TConcurrentClientSyncInfo *sync) : sync_(*sync), committed_(false) { sync_.getWriteMutex().lock(); } TConcurrentSendSentry::~TConcurrentSendSentry() { if(!committed_) { Guard seqidGuard(sync_.seqidMutex_); sync_.markBad_(seqidGuard); } sync_.getWriteMutex().unlock(); } void TConcurrentSendSentry::commit() { committed_ = true; } }}} // apache::thrift::async thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h0000644000000000000000000000372614303740367024646 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TNAME_ME_H_ #define _THRIFT_TNAME_ME_H_ 1 #include #include #include namespace apache { namespace thrift { namespace async { class TAsyncProtocolProcessor : public TAsyncBufferProcessor { public: TAsyncProtocolProcessor(std::shared_ptr underlying, std::shared_ptr pfact) : underlying_(underlying), pfact_(pfact) {} void process(std::function _return, std::shared_ptr ibuf, std::shared_ptr obuf) override; ~TAsyncProtocolProcessor() override = default; private: static void finish(std::function _return, std::shared_ptr oprot, bool healthy); std::shared_ptr underlying_; std::shared_ptr pfact_; }; } } } // apache::thrift::async #endif // #ifndef _THRIFT_TNAME_ME_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TEvhttpClientChannel.h0000644000000000000000000000531214303740367024042 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ #define _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ 1 #include #include #include #include #include struct event_base; struct evdns_base; struct evhttp_connection; struct evhttp_request; namespace apache { namespace thrift { namespace transport { class TMemoryBuffer; } } } namespace apache { namespace thrift { namespace async { class TEvhttpClientChannel : public TAsyncChannel { public: using TAsyncChannel::VoidCallback; TEvhttpClientChannel(const std::string& host, const std::string& path, const char* address, int port, struct event_base* eb, struct evdns_base *dnsbase = nullptr); ~TEvhttpClientChannel() override; void sendAndRecvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, apache::thrift::transport::TMemoryBuffer* recvBuf) override; void sendMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) override; void recvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) override; void finish(struct evhttp_request* req); // XXX bool good() const override { return true; } bool error() const override { return false; } bool timedOut() const override { return false; } private: static void response(struct evhttp_request* req, void* arg); std::string host_; std::string path_; typedef std::pair Completion; typedef std::queue CompletionQueue; CompletionQueue completionQueue_; struct evhttp_connection* conn_; }; } } } // apache::thrift::async #endif // #ifndef _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncChannel.cpp0000644000000000000000000000236214303740367023043 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include namespace apache { namespace thrift { namespace async { void TAsyncChannel::sendAndRecvMessage(const VoidCallback& cob, TMemoryBuffer* sendBuf, TMemoryBuffer* recvBuf) { std::function send_done = std::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf); sendMessage(send_done, sendBuf); } } } } // apache::thrift::async thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h0000644000000000000000000000321714370300523024237 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ #define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1 #include #include #include namespace apache { namespace thrift { namespace async { class TAsyncBufferProcessor { public: // Process data in "in", putting the result in "out". // Call _return(true) when done, or _return(false) to // forcefully close the connection (if applicable). // "in" and "out" should be TMemoryBuffer or similar, // not a wrapper around a socket. virtual void process(std::function _return, std::shared_ptr ibuf, std::shared_ptr obuf) = 0; virtual ~TAsyncBufferProcessor() = default; }; } } } // apache::thrift::async #endif // #ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp0000644000000000000000000001210014303740367024366 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include using namespace apache::thrift::protocol; using apache::thrift::transport::TTransportException; namespace apache { namespace thrift { namespace async { TEvhttpClientChannel::TEvhttpClientChannel(const std::string& host, const std::string& path, const char* address, int port, struct event_base* eb, struct evdns_base* dnsbase) : host_(host), path_(path), conn_(nullptr) { conn_ = evhttp_connection_base_new(eb, dnsbase, address, port); if (conn_ == nullptr) { throw TException("evhttp_connection_new failed"); } } TEvhttpClientChannel::~TEvhttpClientChannel() { if (conn_ != nullptr) { evhttp_connection_free(conn_); } } void TEvhttpClientChannel::sendAndRecvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, apache::thrift::transport::TMemoryBuffer* recvBuf) { struct evhttp_request* req = evhttp_request_new(response, this); if (req == nullptr) { throw TException("evhttp_request_new failed"); } int rv; rv = evhttp_add_header(req->output_headers, "Host", host_.c_str()); if (rv != 0) { throw TException("evhttp_add_header failed"); } rv = evhttp_add_header(req->output_headers, "Content-Type", "application/x-thrift"); if (rv != 0) { throw TException("evhttp_add_header failed"); } uint8_t* obuf; uint32_t sz; sendBuf->getBuffer(&obuf, &sz); rv = evbuffer_add(req->output_buffer, obuf, sz); if (rv != 0) { throw TException("evbuffer_add failed"); } rv = evhttp_make_request(conn_, req, EVHTTP_REQ_POST, path_.c_str()); if (rv != 0) { throw TException("evhttp_make_request failed"); } completionQueue_.push(Completion(cob, recvBuf)); } void TEvhttpClientChannel::sendMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) { (void)cob; (void)message; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unexpected call to TEvhttpClientChannel::sendMessage"); } void TEvhttpClientChannel::recvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) { (void)cob; (void)message; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unexpected call to TEvhttpClientChannel::recvMessage"); } void TEvhttpClientChannel::finish(struct evhttp_request* req) { assert(!completionQueue_.empty()); Completion completion = completionQueue_.front(); completionQueue_.pop(); if (req == nullptr) { try { completion.first(); } catch (const TTransportException& e) { if (e.getType() == TTransportException::END_OF_FILE) throw TException("connect failed"); else throw; } return; } else if (req->response_code != 200) { try { completion.first(); } catch (const TTransportException& e) { std::stringstream ss; ss << "server returned code " << req->response_code; if (req->response_code_line) ss << ": " << req->response_code_line; if (e.getType() == TTransportException::END_OF_FILE) throw TException(ss.str()); else throw; } return; } completion.second->resetBuffer(EVBUFFER_DATA(req->input_buffer), static_cast(EVBUFFER_LENGTH(req->input_buffer))); completion.first(); return; } /* static */ void TEvhttpClientChannel::response(struct evhttp_request* req, void* arg) { auto* self = (TEvhttpClientChannel*)arg; try { self->finish(req); } catch (std::exception& e) { // don't propagate a C++ exception in C code (e.g. libevent) std::cerr << "TEvhttpClientChannel::response exception thrown (ignored): " << e.what() << std::endl; } } } } } // apache::thrift::async thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncProcessor.h0000644000000000000000000000507014370300523023104 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TASYNCPROCESSOR_H_ #define _THRIFT_TASYNCPROCESSOR_H_ 1 #include #include #include #include namespace apache { namespace thrift { namespace async { /** * Async version of a TProcessor. It is not expected to complete by the time * the call to process returns. Instead, it calls a cob to signal completion. */ class TAsyncProcessor { public: virtual ~TAsyncProcessor() = default; virtual void process(std::function _return, std::shared_ptr in, std::shared_ptr out) = 0; void process(std::function _return, std::shared_ptr io) { return process(_return, io, io); } std::shared_ptr getEventHandler() const { return eventHandler_; } void setEventHandler(std::shared_ptr eventHandler) { eventHandler_ = eventHandler; } protected: TAsyncProcessor() = default; std::shared_ptr eventHandler_; }; class TAsyncProcessorFactory { public: virtual ~TAsyncProcessorFactory() = default; /** * Get the TAsyncProcessor to use for a particular connection. * * This method is always invoked in the same thread that the connection was * accepted on. This generally means that this call does not need to be * thread safe, as it will always be invoked from a single thread. */ virtual std::shared_ptr getProcessor(const TConnectionInfo& connInfo) = 0; }; } } } // apache::thrift::async namespace apache { namespace thrift { using apache::thrift::async::TAsyncProcessor; } } #endif // #ifndef _THRIFT_TASYNCPROCESSOR_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp0000644000000000000000000000364214303740367025176 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include using apache::thrift::transport::TBufferBase; using apache::thrift::protocol::TProtocol; namespace apache { namespace thrift { namespace async { void TAsyncProtocolProcessor::process(std::function _return, std::shared_ptr ibuf, std::shared_ptr obuf) { std::shared_ptr iprot(pfact_->getProtocol(ibuf)); std::shared_ptr oprot(pfact_->getProtocol(obuf)); return underlying_ ->process(std::bind(&TAsyncProtocolProcessor::finish, _return, oprot, std::placeholders::_1), iprot, oprot); } /* static */ void TAsyncProtocolProcessor::finish( std::function _return, std::shared_ptr oprot, bool healthy) { (void)oprot; // This is a stub function to hold a reference to oprot. return _return(healthy); } } } } // apache::thrift::async thrift-0.19.0/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h0000644000000000000000000000741714303740367025102 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TCONCURRENTCLIENTSYNCINFO_H_ #define _THRIFT_TCONCURRENTCLIENTSYNCINFO_H_ 1 #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace async { class TConcurrentClientSyncInfo; class TConcurrentSendSentry { public: explicit TConcurrentSendSentry(TConcurrentClientSyncInfo* sync); ~TConcurrentSendSentry(); void commit(); private: TConcurrentClientSyncInfo& sync_; bool committed_; }; class TConcurrentRecvSentry { public: TConcurrentRecvSentry(TConcurrentClientSyncInfo* sync, int32_t seqid); ~TConcurrentRecvSentry(); void commit(); private: TConcurrentClientSyncInfo& sync_; int32_t seqid_; bool committed_; }; class TConcurrentClientSyncInfo { private: // typedefs typedef std::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr; typedef std::map MonitorMap; public: TConcurrentClientSyncInfo(); int32_t generateSeqId(); bool getPending(std::string& fname, ::apache::thrift::protocol::TMessageType& mtype, int32_t& rseqid); /* requires readMutex_ */ void updatePending(const std::string& fname, ::apache::thrift::protocol::TMessageType mtype, int32_t rseqid); /* requires readMutex_ */ void waitForWork(int32_t seqid); /* requires readMutex_ */ ::apache::thrift::concurrency::Mutex& getReadMutex() { return readMutex_; } ::apache::thrift::concurrency::Mutex& getWriteMutex() { return writeMutex_; } private: // constants enum { MONITOR_CACHE_SIZE = 10 }; private: // functions MonitorPtr newMonitor_( const ::apache::thrift::concurrency::Guard& seqidGuard); /* requires seqidMutex_ */ void deleteMonitor_(const ::apache::thrift::concurrency::Guard& seqidGuard, MonitorPtr& m); /*noexcept*/ /* requires seqidMutex_ */ void wakeupAnyone_( const ::apache::thrift::concurrency::Guard& seqidGuard); /* requires seqidMutex_ */ void markBad_(const ::apache::thrift::concurrency::Guard& seqidGuard); /* requires seqidMutex_ */ void throwBadSeqId_(); void throwDeadConnection_(); private: // data members volatile bool stop_; ::apache::thrift::concurrency::Mutex seqidMutex_; // begin seqidMutex_ protected members int32_t nextseqid_; MonitorMap seqidToMonitorMap_; std::vector freeMonitors_; // end seqidMutex_ protected members ::apache::thrift::concurrency::Mutex writeMutex_; ::apache::thrift::concurrency::Mutex readMutex_; // begin readMutex_ protected members bool recvPending_; bool wakeupSomeone_; int32_t seqidPending_; std::string fnamePending_; ::apache::thrift::protocol::TMessageType mtypePending_; // end readMutex_ protected members friend class TConcurrentSendSentry; friend class TConcurrentRecvSentry; }; } } } // apache::thrift::async #endif // _THRIFT_TCONCURRENTCLIENTSYNCINFO_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TEvhttpServer.h0000644000000000000000000000412614303740367022603 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEVHTTP_SERVER_H_ #define _THRIFT_TEVHTTP_SERVER_H_ 1 #include struct event_base; struct evhttp; struct evhttp_request; namespace apache { namespace thrift { namespace async { class TAsyncBufferProcessor; class TEvhttpServer { public: /** * Create a TEvhttpServer for use with an external evhttp instance. * Must be manually installed with evhttp_set_cb, using * TEvhttpServer::request as the callback and the * address of the server as the extra arg. * Do not call "serve" on this server. */ TEvhttpServer(std::shared_ptr processor); /** * Create a TEvhttpServer with an embedded event_base and evhttp, * listening on port and responding on the endpoint "/". * Call "serve" on this server to serve forever. */ TEvhttpServer(std::shared_ptr processor, int port); ~TEvhttpServer(); static void request(struct evhttp_request* req, void* self); int serve(); struct event_base* getEventBase(); private: struct RequestContext; void process(struct evhttp_request* req); void complete(RequestContext* ctx, bool success); std::shared_ptr processor_; struct event_base* eb_; struct evhttp* eh_; }; } } } // apache::thrift::async #endif // #ifndef _THRIFT_TEVHTTP_SERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h0000644000000000000000000001306014303740367024574 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ #define _THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ 1 #include namespace apache { namespace thrift { namespace async { /** * TAsyncDispatchProcessor is a helper class to parse the message header then * call another function to dispatch based on the function name. * * Subclasses must implement dispatchCall() to dispatch on the function name. */ template class TAsyncDispatchProcessorT : public TAsyncProcessor { public: void process(std::function _return, std::shared_ptr in, std::shared_ptr out) override { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); // Try to dynamic cast to the template protocol type auto* specificIn = dynamic_cast(inRaw); auto* specificOut = dynamic_cast(outRaw); if (specificIn && specificOut) { return processFast(_return, specificIn, specificOut); } // Log the fact that we have to use the slow path T_GENERIC_PROTOCOL(this, inRaw, specificIn); T_GENERIC_PROTOCOL(this, outRaw, specificOut); std::string fname; protocol::TMessageType mtype; int32_t seqid; inRaw->readMessageBegin(fname, mtype, seqid); // If this doesn't look like a valid call, log an error and return false so // that the server will close the connection. // // (The old generated processor code used to try to skip a T_STRUCT and // continue. However, that seems unsafe.) if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { GlobalOutput.printf("received invalid message type %d from client", mtype); _return(false); return; } return this->dispatchCall(_return, inRaw, outRaw, fname, seqid); } void processFast(std::function _return, Protocol_* in, Protocol_* out) { std::string fname; protocol::TMessageType mtype; int32_t seqid; in->readMessageBegin(fname, mtype, seqid); if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { GlobalOutput.printf("received invalid message type %d from client", mtype); _return(false); return; } return this->dispatchCallTemplated(_return, in, out, fname, seqid); } virtual void dispatchCall(std::function _return, apache::thrift::protocol::TProtocol* in, apache::thrift::protocol::TProtocol* out, const std::string& fname, int32_t seqid) = 0; virtual void dispatchCallTemplated(std::function _return, Protocol_* in, Protocol_* out, const std::string& fname, int32_t seqid) = 0; }; /** * Non-templatized version of TAsyncDispatchProcessor, * that doesn't bother trying to perform a dynamic_cast. */ class TAsyncDispatchProcessor : public TAsyncProcessor { public: void process(std::function _return, std::shared_ptr in, std::shared_ptr out) override { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); std::string fname; protocol::TMessageType mtype; int32_t seqid; inRaw->readMessageBegin(fname, mtype, seqid); // If this doesn't look like a valid call, log an error and return false so // that the server will close the connection. // // (The old generated processor code used to try to skip a T_STRUCT and // continue. However, that seems unsafe.) if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { GlobalOutput.printf("received invalid message type %d from client", mtype); _return(false); return; } return dispatchCall(_return, inRaw, outRaw, fname, seqid); } virtual void dispatchCall(std::function _return, apache::thrift::protocol::TProtocol* in, apache::thrift::protocol::TProtocol* out, const std::string& fname, int32_t seqid) = 0; }; // Specialize TAsyncDispatchProcessorT for TProtocol and TDummyProtocol just to // use the generic TDispatchProcessor. template <> class TAsyncDispatchProcessorT : public TAsyncDispatchProcessor {}; template <> class TAsyncDispatchProcessorT : public TAsyncDispatchProcessor {}; } } } // apache::thrift::async #endif // _THRIFT_ASYNC_TASYNCDISPATCHPROCESSOR_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/0000755000000000000000000000000014472652650020372 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/protocol/TBase64Utils.h0000644000000000000000000000313514303740367022732 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TBASE64UTILS_H_ #define _THRIFT_PROTOCOL_TBASE64UTILS_H_ #include #include namespace apache { namespace thrift { namespace protocol { // in must be at least len bytes // len must be 1, 2, or 3 // buf must be a buffer of at least 4 bytes and may not overlap in // the data is not padded with '='; the caller can do this if desired void base64_encode(const uint8_t* in, uint32_t len, uint8_t* buf); // buf must be a buffer of at least 4 bytes and contain base64 encoded values // buf will be changed to contain output bytes // len is number of bytes to consume from input (must be 2, 3, or 4) // no '=' padding should be included in the input void base64_decode(uint8_t* buf, uint32_t len); } } } // apache::thrift::protocol #endif // #define _THRIFT_PROTOCOL_TBASE64UTILS_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/THeaderProtocol.h0000644000000000000000000001355014303740367023601 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_H_ #define THRIFT_PROTOCOL_THEADERPROTOCOL_H_ 1 #include #include #include #include #include using apache::thrift::transport::THeaderTransport; namespace apache { namespace thrift { namespace protocol { /** * The header protocol for thrift. Reads unframed, framed, header format, * and http * */ class THeaderProtocol : public TVirtualProtocol { protected: public: void resetProtocol(); explicit THeaderProtocol(const std::shared_ptr& trans, uint16_t protoId = T_COMPACT_PROTOCOL) : TVirtualProtocol(std::shared_ptr(new THeaderTransport(trans))), trans_(std::dynamic_pointer_cast(getTransport())), protoId_(protoId) { trans_->setProtocolId(protoId); resetProtocol(); } THeaderProtocol(const std::shared_ptr& inTrans, const std::shared_ptr& outTrans, uint16_t protoId = T_COMPACT_PROTOCOL) : TVirtualProtocol( std::shared_ptr(new THeaderTransport(inTrans, outTrans))), trans_(std::dynamic_pointer_cast(getTransport())), protoId_(protoId) { trans_->setProtocolId(protoId); resetProtocol(); } ~THeaderProtocol() override = default; /** * Functions to work with headers by calling into THeaderTransport */ void setProtocolId(uint16_t protoId) { trans_->setProtocolId(protoId); resetProtocol(); } typedef THeaderTransport::StringToStringMap StringToStringMap; // these work with write headers void setHeader(const std::string& key, const std::string& value) { trans_->setHeader(key, value); } void clearHeaders() { trans_->clearHeaders(); } StringToStringMap& getWriteHeaders() { return trans_->getWriteHeaders(); } // these work with read headers const StringToStringMap& getHeaders() const { return trans_->getHeaders(); } /** * Writing functions. */ /*ol*/ uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqId); /*ol*/ uint32_t writeMessageEnd(); uint32_t writeStructBegin(const char* name); uint32_t writeStructEnd(); uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId); uint32_t writeFieldEnd(); uint32_t writeFieldStop(); uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size); uint32_t writeMapEnd(); uint32_t writeListBegin(const TType elemType, const uint32_t size); uint32_t writeListEnd(); uint32_t writeSetBegin(const TType elemType, const uint32_t size); uint32_t writeSetEnd(); uint32_t writeBool(const bool value); uint32_t writeByte(const int8_t byte); uint32_t writeI16(const int16_t i16); uint32_t writeI32(const int32_t i32); uint32_t writeI64(const int64_t i64); uint32_t writeDouble(const double dub); uint32_t writeString(const std::string& str); uint32_t writeBinary(const std::string& str); /** * Reading functions */ /*ol*/ uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqId); /*ol*/ uint32_t readMessageEnd(); uint32_t readStructBegin(std::string& name); uint32_t readStructEnd(); uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId); uint32_t readFieldEnd(); uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size); uint32_t readMapEnd(); uint32_t readListBegin(TType& elemType, uint32_t& size); uint32_t readListEnd(); uint32_t readSetBegin(TType& elemType, uint32_t& size); uint32_t readSetEnd(); uint32_t readBool(bool& value); // Provide the default readBool() implementation for std::vector using TVirtualProtocol::readBool; uint32_t readByte(int8_t& byte); uint32_t readI16(int16_t& i16); uint32_t readI32(int32_t& i32); uint32_t readI64(int64_t& i64); uint32_t readDouble(double& dub); uint32_t readString(std::string& str); uint32_t readBinary(std::string& binary); protected: std::shared_ptr trans_; std::shared_ptr proto_; uint32_t protoId_; }; class THeaderProtocolFactory : public TProtocolFactory { public: std::shared_ptr getProtocol(std::shared_ptr trans) override { auto* headerProtocol = new THeaderProtocol(trans, trans, T_BINARY_PROTOCOL); return std::shared_ptr(headerProtocol); } std::shared_ptr getProtocol( std::shared_ptr inTrans, std::shared_ptr outTrans) override { auto* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL); return std::shared_ptr(headerProtocol); } }; } } } // apache::thrift::protocol #endif // #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TProtocolTap.h0000644000000000000000000001126714303740367023140 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ #define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1 #include namespace apache { namespace thrift { namespace protocol { using apache::thrift::transport::TTransport; /** * Puts a wiretap on a protocol object. Any reads to this class are passed * through to an enclosed protocol object, but also mirrored as write to a * second protocol object. * */ class TProtocolTap : public TVirtualProtocol { public: TProtocolTap(std::shared_ptr source, std::shared_ptr sink) : TVirtualProtocol(source->getTransport()), source_(source), sink_(sink) {} uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t rv = source_->readMessageBegin(name, messageType, seqid); sink_->writeMessageBegin(name, messageType, seqid); return rv; } uint32_t readMessageEnd() { uint32_t rv = source_->readMessageEnd(); sink_->writeMessageEnd(); return rv; } uint32_t readStructBegin(std::string& name) { uint32_t rv = source_->readStructBegin(name); sink_->writeStructBegin(name.c_str()); return rv; } uint32_t readStructEnd() { uint32_t rv = source_->readStructEnd(); sink_->writeStructEnd(); return rv; } uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { uint32_t rv = source_->readFieldBegin(name, fieldType, fieldId); if (fieldType == T_STOP) { sink_->writeFieldStop(); } else { sink_->writeFieldBegin(name.c_str(), fieldType, fieldId); } return rv; } uint32_t readFieldEnd() { uint32_t rv = source_->readFieldEnd(); sink_->writeFieldEnd(); return rv; } uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { uint32_t rv = source_->readMapBegin(keyType, valType, size); sink_->writeMapBegin(keyType, valType, size); return rv; } uint32_t readMapEnd() { uint32_t rv = source_->readMapEnd(); sink_->writeMapEnd(); return rv; } uint32_t readListBegin(TType& elemType, uint32_t& size) { uint32_t rv = source_->readListBegin(elemType, size); sink_->writeListBegin(elemType, size); return rv; } uint32_t readListEnd() { uint32_t rv = source_->readListEnd(); sink_->writeListEnd(); return rv; } uint32_t readSetBegin(TType& elemType, uint32_t& size) { uint32_t rv = source_->readSetBegin(elemType, size); sink_->writeSetBegin(elemType, size); return rv; } uint32_t readSetEnd() { uint32_t rv = source_->readSetEnd(); sink_->writeSetEnd(); return rv; } uint32_t readBool(bool& value) { uint32_t rv = source_->readBool(value); sink_->writeBool(value); return rv; } // Provide the default readBool() implementation for std::vector using TVirtualProtocol::readBool; uint32_t readByte(int8_t& byte) { uint32_t rv = source_->readByte(byte); sink_->writeByte(byte); return rv; } uint32_t readI16(int16_t& i16) { uint32_t rv = source_->readI16(i16); sink_->writeI16(i16); return rv; } uint32_t readI32(int32_t& i32) { uint32_t rv = source_->readI32(i32); sink_->writeI32(i32); return rv; } uint32_t readI64(int64_t& i64) { uint32_t rv = source_->readI64(i64); sink_->writeI64(i64); return rv; } uint32_t readDouble(double& dub) { uint32_t rv = source_->readDouble(dub); sink_->writeDouble(dub); return rv; } uint32_t readString(std::string& str) { uint32_t rv = source_->readString(str); sink_->writeString(str); return rv; } uint32_t readBinary(std::string& str) { uint32_t rv = source_->readBinary(str); sink_->writeBinary(str); return rv; } private: std::shared_ptr source_; std::shared_ptr sink_; }; } } } // apache::thrift::protocol #endif // #define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1 thrift-0.19.0/lib/cpp/src/thrift/protocol/TList.h0000644000000000000000000000240014303740367021572 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TLIST_H_ #define _THRIFT_TLIST_H_ #include namespace apache { namespace thrift { namespace protocol { /** * Helper class that encapsulates list metadata. * */ class TList { public: TList() : elemType_(T_STOP), size_(0) { } TList(TType t = T_STOP, int s = 0) : elemType_(t), size_(s) { } TType elemType_; int size_; }; } } } // apache::thrift::protocol #endif // #ifndef _THRIFT_TLIST_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TProtocol.cpp0000644000000000000000000000214514303740367023021 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include namespace apache { namespace thrift { namespace protocol { TProtocol::~TProtocol() = default; uint32_t TProtocol::skip_virt(TType type) { return ::apache::thrift::protocol::skip(*this, type); } TProtocolFactory::~TProtocolFactory() = default; }}} // apache::thrift::protocol thrift-0.19.0/lib/cpp/src/thrift/protocol/TCompactProtocol.h0000644000000000000000000002044614370300523023767 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ #define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ 1 #include #include #include namespace apache { namespace thrift { namespace protocol { /** * C++ Implementation of the Compact Protocol as described in THRIFT-110 */ template class TCompactProtocolT : public TVirtualProtocol > { public: static const int8_t PROTOCOL_ID = (int8_t)0x82u; static const int8_t VERSION_N = 1; static const int8_t VERSION_MASK = 0x1f; // 0001 1111 protected: static const int8_t TYPE_MASK = (int8_t)0xE0u; // 1110 0000 static const int8_t TYPE_BITS = 0x07; // 0000 0111 static const int32_t TYPE_SHIFT_AMOUNT = 5; Transport_* trans_; /** * (Writing) If we encounter a boolean field begin, save the TField here * so it can have the value incorporated. */ struct { const char* name; TType fieldType; int16_t fieldId; } booleanField_; /** * (Reading) If we read a field header, and it's a boolean field, save * the boolean value here so that readBool can use it. */ struct { bool hasBoolValue; bool boolValue; } boolValue_; /** * Used to keep track of the last field for the current and previous structs, * so we can do the delta stuff. */ std::stack lastField_; int16_t lastFieldId_; public: TCompactProtocolT(std::shared_ptr trans) : TVirtualProtocol >(trans), trans_(trans.get()), lastFieldId_(0), string_limit_(0), string_buf_(nullptr), string_buf_size_(0), container_limit_(0) { booleanField_.name = nullptr; boolValue_.hasBoolValue = false; } TCompactProtocolT(std::shared_ptr trans, int32_t string_limit, int32_t container_limit) : TVirtualProtocol >(trans), trans_(trans.get()), lastFieldId_(0), string_limit_(string_limit), string_buf_(nullptr), string_buf_size_(0), container_limit_(container_limit) { booleanField_.name = nullptr; boolValue_.hasBoolValue = false; } ~TCompactProtocolT() override { free(string_buf_); } /** * Writing functions */ virtual uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid); uint32_t writeStructBegin(const char* name); uint32_t writeStructEnd(); uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId); uint32_t writeFieldStop(); uint32_t writeListBegin(const TType elemType, const uint32_t size); uint32_t writeSetBegin(const TType elemType, const uint32_t size); virtual uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size); uint32_t writeBool(const bool value); uint32_t writeByte(const int8_t byte); uint32_t writeI16(const int16_t i16); uint32_t writeI32(const int32_t i32); uint32_t writeI64(const int64_t i64); uint32_t writeDouble(const double dub); uint32_t writeString(const std::string& str); uint32_t writeBinary(const std::string& str); int getMinSerializedSize(TType type) override; void checkReadBytesAvailable(TSet& set) override { trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_)); } void checkReadBytesAvailable(TList& list) override { trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_)); } void checkReadBytesAvailable(TMap& map) override { int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_); trans_->checkReadBytesAvailable(map.size_ * elmSize); } /** * These methods are called by structs, but don't actually have any wired * output or purpose */ virtual uint32_t writeMessageEnd() { return 0; } uint32_t writeMapEnd() { return 0; } uint32_t writeListEnd() { return 0; } uint32_t writeSetEnd() { return 0; } uint32_t writeFieldEnd() { return 0; } protected: int32_t writeFieldBeginInternal(const char* name, const TType fieldType, const int16_t fieldId, int8_t typeOverride); uint32_t writeCollectionBegin(const TType elemType, int32_t size); uint32_t writeVarint32(uint32_t n); uint32_t writeVarint64(uint64_t n); uint64_t i64ToZigzag(const int64_t l); uint32_t i32ToZigzag(const int32_t n); inline int8_t getCompactType(const TType ttype); public: uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid); uint32_t readStructBegin(std::string& name); uint32_t readStructEnd(); uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId); uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size); uint32_t readListBegin(TType& elemType, uint32_t& size); uint32_t readSetBegin(TType& elemType, uint32_t& size); uint32_t readBool(bool& value); // Provide the default readBool() implementation for std::vector using TVirtualProtocol >::readBool; uint32_t readByte(int8_t& byte); uint32_t readI16(int16_t& i16); uint32_t readI32(int32_t& i32); uint32_t readI64(int64_t& i64); uint32_t readDouble(double& dub); uint32_t readString(std::string& str); uint32_t readBinary(std::string& str); /* *These methods are here for the struct to call, but don't have any wire * encoding. */ uint32_t readMessageEnd() { return 0; } uint32_t readFieldEnd() { return 0; } uint32_t readMapEnd() { return 0; } uint32_t readListEnd() { return 0; } uint32_t readSetEnd() { return 0; } protected: uint32_t readVarint32(int32_t& i32); uint32_t readVarint64(int64_t& i64); int32_t zigzagToI32(uint32_t n); int64_t zigzagToI64(uint64_t n); TType getTType(int8_t type); // Buffer for reading strings, save for the lifetime of the protocol to // avoid memory churn allocating memory on every string read int32_t string_limit_; uint8_t* string_buf_; int32_t string_buf_size_; int32_t container_limit_; }; typedef TCompactProtocolT TCompactProtocol; /** * Constructs compact protocol handlers */ template class TCompactProtocolFactoryT : public TProtocolFactory { public: TCompactProtocolFactoryT() : string_limit_(0), container_limit_(0) {} TCompactProtocolFactoryT(int32_t string_limit, int32_t container_limit) : string_limit_(string_limit), container_limit_(container_limit) {} ~TCompactProtocolFactoryT() override = default; void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; } void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; } std::shared_ptr getProtocol(std::shared_ptr trans) override { std::shared_ptr specific_trans = std::dynamic_pointer_cast(trans); TProtocol* prot; if (specific_trans) { prot = new TCompactProtocolT(specific_trans, string_limit_, container_limit_); } else { prot = new TCompactProtocol(trans, string_limit_, container_limit_); } return std::shared_ptr(prot); } private: int32_t string_limit_; int32_t container_limit_; }; typedef TCompactProtocolFactoryT TCompactProtocolFactory; } } } // apache::thrift::protocol #include #endif thrift-0.19.0/lib/cpp/src/thrift/protocol/TProtocolDecorator.h0000644000000000000000000001433414303740367024334 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_TPROTOCOLDECORATOR_H_ #define THRIFT_TPROTOCOLDECORATOR_H_ 1 #include #include namespace apache { namespace thrift { namespace protocol { using std::shared_ptr; /** * TProtocolDecorator forwards all requests to an enclosed * TProtocol instance, providing a way to author concise * concrete decorator subclasses. * *

See p.175 of Design Patterns (by Gamma et al.)

* * @see apache::thrift::protocol::TMultiplexedProtocol */ class TProtocolDecorator : public TProtocol { public: ~TProtocolDecorator() override = default; // Desc: Initializes the protocol decorator object. TProtocolDecorator(shared_ptr proto) : TProtocol(proto->getTransport()), protocol(proto) {} uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, const int32_t seqid) override { return protocol->writeMessageBegin(name, messageType, seqid); } uint32_t writeMessageEnd_virt() override { return protocol->writeMessageEnd(); } uint32_t writeStructBegin_virt(const char* name) override { return protocol->writeStructBegin(name); } uint32_t writeStructEnd_virt() override { return protocol->writeStructEnd(); } uint32_t writeFieldBegin_virt(const char* name, const TType fieldType, const int16_t fieldId) override { return protocol->writeFieldBegin(name, fieldType, fieldId); } uint32_t writeFieldEnd_virt() override { return protocol->writeFieldEnd(); } uint32_t writeFieldStop_virt() override { return protocol->writeFieldStop(); } uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size) override { return protocol->writeMapBegin(keyType, valType, size); } uint32_t writeMapEnd_virt() override { return protocol->writeMapEnd(); } uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) override { return protocol->writeListBegin(elemType, size); } uint32_t writeListEnd_virt() override { return protocol->writeListEnd(); } uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) override { return protocol->writeSetBegin(elemType, size); } uint32_t writeSetEnd_virt() override { return protocol->writeSetEnd(); } uint32_t writeBool_virt(const bool value) override { return protocol->writeBool(value); } uint32_t writeByte_virt(const int8_t byte) override { return protocol->writeByte(byte); } uint32_t writeI16_virt(const int16_t i16) override { return protocol->writeI16(i16); } uint32_t writeI32_virt(const int32_t i32) override { return protocol->writeI32(i32); } uint32_t writeI64_virt(const int64_t i64) override { return protocol->writeI64(i64); } uint32_t writeDouble_virt(const double dub) override { return protocol->writeDouble(dub); } uint32_t writeString_virt(const std::string& str) override { return protocol->writeString(str); } uint32_t writeBinary_virt(const std::string& str) override { return protocol->writeBinary(str); } uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, int32_t& seqid) override { return protocol->readMessageBegin(name, messageType, seqid); } uint32_t readMessageEnd_virt() override { return protocol->readMessageEnd(); } uint32_t readStructBegin_virt(std::string& name) override { return protocol->readStructBegin(name); } uint32_t readStructEnd_virt() override { return protocol->readStructEnd(); } uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) override { return protocol->readFieldBegin(name, fieldType, fieldId); } uint32_t readFieldEnd_virt() override { return protocol->readFieldEnd(); } uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) override { return protocol->readMapBegin(keyType, valType, size); } uint32_t readMapEnd_virt() override { return protocol->readMapEnd(); } uint32_t readListBegin_virt(TType& elemType, uint32_t& size) override { return protocol->readListBegin(elemType, size); } uint32_t readListEnd_virt() override { return protocol->readListEnd(); } uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) override { return protocol->readSetBegin(elemType, size); } uint32_t readSetEnd_virt() override { return protocol->readSetEnd(); } uint32_t readBool_virt(bool& value) override { return protocol->readBool(value); } uint32_t readBool_virt(std::vector::reference value) override { return protocol->readBool(value); } uint32_t readByte_virt(int8_t& byte) override { return protocol->readByte(byte); } uint32_t readI16_virt(int16_t& i16) override { return protocol->readI16(i16); } uint32_t readI32_virt(int32_t& i32) override { return protocol->readI32(i32); } uint32_t readI64_virt(int64_t& i64) override { return protocol->readI64(i64); } uint32_t readDouble_virt(double& dub) override { return protocol->readDouble(dub); } uint32_t readString_virt(std::string& str) override { return protocol->readString(str); } uint32_t readBinary_virt(std::string& str) override { return protocol->readBinary(str); } private: shared_ptr protocol; }; } } } #endif // THRIFT_TPROTOCOLDECORATOR_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TSet.h0000644000000000000000000000255114303740367021421 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TSET_H_ #define _THRIFT_TSET_H_ #include #include namespace apache { namespace thrift { namespace protocol { /** * Helper class that encapsulates set metadata. * */ class TSet { public: TSet() : elemType_(T_STOP), size_(0) { } TSet(TType t, int s) : elemType_(t), size_(s) { } TSet(TList list) : elemType_(list.elemType_), size_(list.size_) { } TType elemType_; int size_; }; } } } // apache::thrift::protocol #endif // #ifndef _THRIFT_TSET_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TProtocol.h0000644000000000000000000005210214370300523022452 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_ #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 #ifdef _WIN32 // Need to come before any Windows.h includes #include #endif #include #include #include #include #include #include #include #ifdef HAVE_NETINET_IN_H #include #endif #include #include #include #include #include // Use this to get around strict aliasing rules. // For example, uint64_t i = bitwise_cast(returns_double()); // The most obvious implementation is to just cast a pointer, // but that doesn't work. // For a pretty in-depth explanation of the problem, see // http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html template static inline To bitwise_cast(From from) { static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)"); // BAD!!! These are all broken with -O2. //return *reinterpret_cast(&from); // BAD!!! //return *static_cast(static_cast(&from)); // BAD!!! //return *(To*)(void*)&from; // BAD!!! // Super clean and paritally blessed by section 3.9 of the standard. //unsigned char c[sizeof(from)]; //memcpy(c, &from, sizeof(from)); //To to; //memcpy(&to, c, sizeof(c)); //return to; // Slightly more questionable. // Same code emitted by GCC. //To to; //memcpy(&to, &from, sizeof(from)); //return to; // Technically undefined, but almost universally supported, // and the most efficient implementation. union { From f; To t; } u; u.f = from; return u.t; } #ifdef HAVE_SYS_PARAM_H #include #endif #ifdef __ZEPHYR__ # include # define __THRIFT_BYTE_ORDER __BYTE_ORDER__ # define __THRIFT_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ # define __THRIFT_BIG_ENDIAN __ORDER_BIG_ENDIAN__ # if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN # undef bswap_64 # undef bswap_32 # undef bswap_16 # endif #endif #ifndef __THRIFT_BYTE_ORDER # if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) # define __THRIFT_BYTE_ORDER BYTE_ORDER # define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN # define __THRIFT_BIG_ENDIAN BIG_ENDIAN # else # include # if BOOST_ENDIAN_BIG_BYTE # define __THRIFT_BYTE_ORDER 4321 # define __THRIFT_LITTLE_ENDIAN 0 # define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER # elif BOOST_ENDIAN_LITTLE_BYTE # define __THRIFT_BYTE_ORDER 1234 # define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER # define __THRIFT_BIG_ENDIAN 0 # endif # ifdef BOOST_LITTLE_ENDIAN # else # endif # endif #endif #if __THRIFT_BYTE_ORDER == __THRIFT_BIG_ENDIAN # if !defined(THRIFT_ntohll) # define THRIFT_ntohll(n) (n) # define THRIFT_htonll(n) (n) # endif # if defined(__GNUC__) && defined(__GLIBC__) # include # define THRIFT_htolell(n) bswap_64(n) # define THRIFT_letohll(n) bswap_64(n) # define THRIFT_htolel(n) bswap_32(n) # define THRIFT_letohl(n) bswap_32(n) # define THRIFT_htoles(n) bswap_16(n) # define THRIFT_letohs(n) bswap_16(n) # else /* GNUC & GLIBC */ # define bswap_64(n) \ ( (((n) & 0xff00000000000000ull) >> 56) \ | (((n) & 0x00ff000000000000ull) >> 40) \ | (((n) & 0x0000ff0000000000ull) >> 24) \ | (((n) & 0x000000ff00000000ull) >> 8) \ | (((n) & 0x00000000ff000000ull) << 8) \ | (((n) & 0x0000000000ff0000ull) << 24) \ | (((n) & 0x000000000000ff00ull) << 40) \ | (((n) & 0x00000000000000ffull) << 56) ) # define bswap_32(n) \ ( (((n) & 0xff000000ul) >> 24) \ | (((n) & 0x00ff0000ul) >> 8) \ | (((n) & 0x0000ff00ul) << 8) \ | (((n) & 0x000000fful) << 24) ) # define bswap_16(n) \ ( (((n) & ((unsigned short)0xff00ul)) >> 8) \ | (((n) & ((unsigned short)0x00fful)) << 8) ) # define THRIFT_htolell(n) bswap_64(n) # define THRIFT_letohll(n) bswap_64(n) # define THRIFT_htolel(n) bswap_32(n) # define THRIFT_letohl(n) bswap_32(n) # define THRIFT_htoles(n) bswap_16(n) # define THRIFT_letohs(n) bswap_16(n) # endif /* GNUC & GLIBC */ #elif __THRIFT_BYTE_ORDER == __THRIFT_LITTLE_ENDIAN # define THRIFT_htolell(n) (n) # define THRIFT_letohll(n) (n) # define THRIFT_htolel(n) (n) # define THRIFT_letohl(n) (n) # define THRIFT_htoles(n) (n) # define THRIFT_letohs(n) (n) # if defined(__GNUC__) && defined(__GLIBC__) # include # define THRIFT_ntohll(n) bswap_64(n) # define THRIFT_htonll(n) bswap_64(n) # elif defined(_MSC_VER) /* Microsoft Visual C++ */ # define THRIFT_ntohll(n) ( _byteswap_uint64((uint64_t)n) ) # define THRIFT_htonll(n) ( _byteswap_uint64((uint64_t)n) ) # elif !defined(THRIFT_ntohll) /* Not GNUC/GLIBC or MSVC */ # define THRIFT_ntohll(n) ( (((uint64_t)ntohl((uint32_t)n)) << 32) + ntohl((uint32_t)(n >> 32)) ) # define THRIFT_htonll(n) ( (((uint64_t)htonl((uint32_t)n)) << 32) + htonl((uint32_t)(n >> 32)) ) # endif /* GNUC/GLIBC or MSVC or something else */ #else /* __THRIFT_BYTE_ORDER */ # error "Can't define THRIFT_htonll or THRIFT_ntohll!" #endif namespace apache { namespace thrift { namespace protocol { using apache::thrift::transport::TTransport; /** * Abstract class for a thrift protocol driver. These are all the methods that * a protocol must implement. Essentially, there must be some way of reading * and writing all the base types, plus a mechanism for writing out structs * with indexed fields. * * TProtocol objects should not be shared across multiple encoding contexts, * as they may need to maintain internal state in some protocols (i.e. XML). * Note that is is acceptable for the TProtocol module to do its own internal * buffered reads/writes to the underlying TTransport where appropriate (i.e. * when parsing an input XML stream, reading should be batched rather than * looking ahead character by character for a close tag). * */ class TProtocol { public: virtual ~TProtocol(); /** * Writing functions. */ virtual uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, const int32_t seqid) = 0; virtual uint32_t writeMessageEnd_virt() = 0; virtual uint32_t writeStructBegin_virt(const char* name) = 0; virtual uint32_t writeStructEnd_virt() = 0; virtual uint32_t writeFieldBegin_virt(const char* name, const TType fieldType, const int16_t fieldId) = 0; virtual uint32_t writeFieldEnd_virt() = 0; virtual uint32_t writeFieldStop_virt() = 0; virtual uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size) = 0; virtual uint32_t writeMapEnd_virt() = 0; virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) = 0; virtual uint32_t writeListEnd_virt() = 0; virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) = 0; virtual uint32_t writeSetEnd_virt() = 0; virtual uint32_t writeBool_virt(const bool value) = 0; virtual uint32_t writeByte_virt(const int8_t byte) = 0; virtual uint32_t writeI16_virt(const int16_t i16) = 0; virtual uint32_t writeI32_virt(const int32_t i32) = 0; virtual uint32_t writeI64_virt(const int64_t i64) = 0; virtual uint32_t writeDouble_virt(const double dub) = 0; virtual uint32_t writeString_virt(const std::string& str) = 0; virtual uint32_t writeBinary_virt(const std::string& str) = 0; uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid) { T_VIRTUAL_CALL(); return writeMessageBegin_virt(name, messageType, seqid); } uint32_t writeMessageEnd() { T_VIRTUAL_CALL(); return writeMessageEnd_virt(); } uint32_t writeStructBegin(const char* name) { T_VIRTUAL_CALL(); return writeStructBegin_virt(name); } uint32_t writeStructEnd() { T_VIRTUAL_CALL(); return writeStructEnd_virt(); } uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { T_VIRTUAL_CALL(); return writeFieldBegin_virt(name, fieldType, fieldId); } uint32_t writeFieldEnd() { T_VIRTUAL_CALL(); return writeFieldEnd_virt(); } uint32_t writeFieldStop() { T_VIRTUAL_CALL(); return writeFieldStop_virt(); } uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { T_VIRTUAL_CALL(); return writeMapBegin_virt(keyType, valType, size); } uint32_t writeMapEnd() { T_VIRTUAL_CALL(); return writeMapEnd_virt(); } uint32_t writeListBegin(const TType elemType, const uint32_t size) { T_VIRTUAL_CALL(); return writeListBegin_virt(elemType, size); } uint32_t writeListEnd() { T_VIRTUAL_CALL(); return writeListEnd_virt(); } uint32_t writeSetBegin(const TType elemType, const uint32_t size) { T_VIRTUAL_CALL(); return writeSetBegin_virt(elemType, size); } uint32_t writeSetEnd() { T_VIRTUAL_CALL(); return writeSetEnd_virt(); } uint32_t writeBool(const bool value) { T_VIRTUAL_CALL(); return writeBool_virt(value); } uint32_t writeByte(const int8_t byte) { T_VIRTUAL_CALL(); return writeByte_virt(byte); } uint32_t writeI16(const int16_t i16) { T_VIRTUAL_CALL(); return writeI16_virt(i16); } uint32_t writeI32(const int32_t i32) { T_VIRTUAL_CALL(); return writeI32_virt(i32); } uint32_t writeI64(const int64_t i64) { T_VIRTUAL_CALL(); return writeI64_virt(i64); } uint32_t writeDouble(const double dub) { T_VIRTUAL_CALL(); return writeDouble_virt(dub); } uint32_t writeString(const std::string& str) { T_VIRTUAL_CALL(); return writeString_virt(str); } uint32_t writeBinary(const std::string& str) { T_VIRTUAL_CALL(); return writeBinary_virt(str); } /** * Reading functions */ virtual uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, int32_t& seqid) = 0; virtual uint32_t readMessageEnd_virt() = 0; virtual uint32_t readStructBegin_virt(std::string& name) = 0; virtual uint32_t readStructEnd_virt() = 0; virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) = 0; virtual uint32_t readFieldEnd_virt() = 0; virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) = 0; virtual uint32_t readMapEnd_virt() = 0; virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) = 0; virtual uint32_t readListEnd_virt() = 0; virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) = 0; virtual uint32_t readSetEnd_virt() = 0; virtual uint32_t readBool_virt(bool& value) = 0; virtual uint32_t readBool_virt(std::vector::reference value) = 0; virtual uint32_t readByte_virt(int8_t& byte) = 0; virtual uint32_t readI16_virt(int16_t& i16) = 0; virtual uint32_t readI32_virt(int32_t& i32) = 0; virtual uint32_t readI64_virt(int64_t& i64) = 0; virtual uint32_t readDouble_virt(double& dub) = 0; virtual uint32_t readString_virt(std::string& str) = 0; virtual uint32_t readBinary_virt(std::string& str) = 0; uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { T_VIRTUAL_CALL(); return readMessageBegin_virt(name, messageType, seqid); } uint32_t readMessageEnd() { T_VIRTUAL_CALL(); return readMessageEnd_virt(); } uint32_t readStructBegin(std::string& name) { T_VIRTUAL_CALL(); return readStructBegin_virt(name); } uint32_t readStructEnd() { T_VIRTUAL_CALL(); return readStructEnd_virt(); } uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { T_VIRTUAL_CALL(); return readFieldBegin_virt(name, fieldType, fieldId); } uint32_t readFieldEnd() { T_VIRTUAL_CALL(); return readFieldEnd_virt(); } uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { T_VIRTUAL_CALL(); return readMapBegin_virt(keyType, valType, size); } uint32_t readMapEnd() { T_VIRTUAL_CALL(); return readMapEnd_virt(); } uint32_t readListBegin(TType& elemType, uint32_t& size) { T_VIRTUAL_CALL(); return readListBegin_virt(elemType, size); } uint32_t readListEnd() { T_VIRTUAL_CALL(); return readListEnd_virt(); } uint32_t readSetBegin(TType& elemType, uint32_t& size) { T_VIRTUAL_CALL(); return readSetBegin_virt(elemType, size); } uint32_t readSetEnd() { T_VIRTUAL_CALL(); return readSetEnd_virt(); } uint32_t readBool(bool& value) { T_VIRTUAL_CALL(); return readBool_virt(value); } uint32_t readByte(int8_t& byte) { T_VIRTUAL_CALL(); return readByte_virt(byte); } uint32_t readI16(int16_t& i16) { T_VIRTUAL_CALL(); return readI16_virt(i16); } uint32_t readI32(int32_t& i32) { T_VIRTUAL_CALL(); return readI32_virt(i32); } uint32_t readI64(int64_t& i64) { T_VIRTUAL_CALL(); return readI64_virt(i64); } uint32_t readDouble(double& dub) { T_VIRTUAL_CALL(); return readDouble_virt(dub); } uint32_t readString(std::string& str) { T_VIRTUAL_CALL(); return readString_virt(str); } uint32_t readBinary(std::string& str) { T_VIRTUAL_CALL(); return readBinary_virt(str); } /* * std::vector is specialized for bool, and its elements are individual bits * rather than bools. We need to define a different version of readBool() * to work with std::vector. */ uint32_t readBool(std::vector::reference value) { T_VIRTUAL_CALL(); return readBool_virt(value); } /** * Method to arbitrarily skip over data. */ uint32_t skip(TType type) { T_VIRTUAL_CALL(); return skip_virt(type); } virtual uint32_t skip_virt(TType type); inline std::shared_ptr getTransport() { return ptrans_; } // TODO: remove these two calls, they are for backwards // compatibility inline std::shared_ptr getInputTransport() { return ptrans_; } inline std::shared_ptr getOutputTransport() { return ptrans_; } // input and output recursion depth are kept separate so that one protocol // can be used concurrently for both input and output. void incrementInputRecursionDepth() { if (recursion_limit_ < ++input_recursion_depth_) { throw TProtocolException(TProtocolException::DEPTH_LIMIT); } } void decrementInputRecursionDepth() { --input_recursion_depth_; } void incrementOutputRecursionDepth() { if (recursion_limit_ < ++output_recursion_depth_) { throw TProtocolException(TProtocolException::DEPTH_LIMIT); } } void decrementOutputRecursionDepth() { --output_recursion_depth_; } uint32_t getRecursionLimit() const {return recursion_limit_;} void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;} // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. virtual int getMinSerializedSize(TType type) { THRIFT_UNUSED_VARIABLE(type); return 0; } protected: TProtocol(std::shared_ptr ptrans) : ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0), recursion_limit_(ptrans->getConfiguration()->getRecursionLimit()) {} virtual void checkReadBytesAvailable(TSet& set) { ptrans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_)); } virtual void checkReadBytesAvailable(TList& list) { ptrans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_)); } virtual void checkReadBytesAvailable(TMap& map) { int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_); ptrans_->checkReadBytesAvailable(map.size_ * elmSize); } std::shared_ptr ptrans_; private: TProtocol() = default; uint32_t input_recursion_depth_; uint32_t output_recursion_depth_; uint32_t recursion_limit_; }; /** * Constructs input and output protocol objects given transports. */ class TProtocolFactory { public: TProtocolFactory() = default; virtual ~TProtocolFactory(); virtual std::shared_ptr getProtocol(std::shared_ptr trans) = 0; virtual std::shared_ptr getProtocol(std::shared_ptr inTrans, std::shared_ptr outTrans) { (void)outTrans; return getProtocol(inTrans); } }; /** * Dummy protocol class. * * This class does nothing, and should never be instantiated. * It is used only by the generator code. */ class TDummyProtocol : public TProtocol {}; // This is the default / legacy choice struct TNetworkBigEndian { static uint16_t toWire16(uint16_t x) {return htons(x);} static uint32_t toWire32(uint32_t x) {return htonl(x);} static uint64_t toWire64(uint64_t x) {return THRIFT_htonll(x);} static uint16_t fromWire16(uint16_t x) {return ntohs(x);} static uint32_t fromWire32(uint32_t x) {return ntohl(x);} static uint64_t fromWire64(uint64_t x) {return THRIFT_ntohll(x);} }; // On most systems, this will be a bit faster than TNetworkBigEndian struct TNetworkLittleEndian { static uint16_t toWire16(uint16_t x) {return THRIFT_htoles(x);} static uint32_t toWire32(uint32_t x) {return THRIFT_htolel(x);} static uint64_t toWire64(uint64_t x) {return THRIFT_htolell(x);} static uint16_t fromWire16(uint16_t x) {return THRIFT_letohs(x);} static uint32_t fromWire32(uint32_t x) {return THRIFT_letohl(x);} static uint64_t fromWire64(uint64_t x) {return THRIFT_letohll(x);} }; struct TOutputRecursionTracker { TProtocol &prot_; TOutputRecursionTracker(TProtocol &prot) : prot_(prot) { prot_.incrementOutputRecursionDepth(); } ~TOutputRecursionTracker() { prot_.decrementOutputRecursionDepth(); } }; struct TInputRecursionTracker { TProtocol &prot_; TInputRecursionTracker(TProtocol &prot) : prot_(prot) { prot_.incrementInputRecursionDepth(); } ~TInputRecursionTracker() { prot_.decrementInputRecursionDepth(); } }; /** * Helper template for implementing TProtocol::skip(). * * Templatized to avoid having to make virtual function calls. */ template uint32_t skip(Protocol_& prot, TType type) { TInputRecursionTracker tracker(prot); switch (type) { case T_BOOL: { bool boolv; return prot.readBool(boolv); } case T_BYTE: { int8_t bytev = 0; return prot.readByte(bytev); } case T_I16: { int16_t i16; return prot.readI16(i16); } case T_I32: { int32_t i32; return prot.readI32(i32); } case T_I64: { int64_t i64; return prot.readI64(i64); } case T_DOUBLE: { double dub; return prot.readDouble(dub); } case T_STRING: { std::string str; return prot.readBinary(str); } case T_STRUCT: { uint32_t result = 0; std::string name; int16_t fid; TType ftype; result += prot.readStructBegin(name); while (true) { result += prot.readFieldBegin(name, ftype, fid); if (ftype == T_STOP) { break; } result += skip(prot, ftype); result += prot.readFieldEnd(); } result += prot.readStructEnd(); return result; } case T_MAP: { uint32_t result = 0; TType keyType; TType valType; uint32_t i, size; result += prot.readMapBegin(keyType, valType, size); for (i = 0; i < size; i++) { result += skip(prot, keyType); result += skip(prot, valType); } result += prot.readMapEnd(); return result; } case T_SET: { uint32_t result = 0; TType elemType; uint32_t i, size; result += prot.readSetBegin(elemType, size); for (i = 0; i < size; i++) { result += skip(prot, elemType); } result += prot.readSetEnd(); return result; } case T_LIST: { uint32_t result = 0; TType elemType; uint32_t i, size; result += prot.readListBegin(elemType, size); for (i = 0; i < size; i++) { result += skip(prot, elemType); } result += prot.readListEnd(); return result; } default: break; } throw TProtocolException(TProtocolException::INVALID_DATA, "invalid TType"); } }}} // apache::thrift::protocol #endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 thrift-0.19.0/lib/cpp/src/thrift/protocol/TDebugProtocol.h0000644000000000000000000001276714303740367023450 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ #define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1 #include #include namespace apache { namespace thrift { namespace protocol { /* !!! EXPERIMENTAL CODE !!! This protocol is very much a work in progress. It doesn't handle many cases properly. It throws exceptions in many cases. It probably segfaults in many cases. Bug reports and feature requests are welcome. Complaints are not. :R */ /** * Protocol that prints the payload in a nice human-readable format. * Reading from this protocol is not supported. * */ class TDebugProtocol : public TVirtualProtocol { private: enum write_state_t { UNINIT, STRUCT, LIST, SET, MAP_KEY, MAP_VALUE }; public: TDebugProtocol(std::shared_ptr trans) : TVirtualProtocol(trans), trans_(trans.get()), string_limit_(DEFAULT_STRING_LIMIT), string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE) { write_state_.push_back(UNINIT); } static const int32_t DEFAULT_STRING_LIMIT = 256; static const int32_t DEFAULT_STRING_PREFIX_SIZE = 16; void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; } void setStringPrefixSize(int32_t string_prefix_size) { string_prefix_size_ = string_prefix_size; } uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid); uint32_t writeMessageEnd(); uint32_t writeStructBegin(const char* name); uint32_t writeStructEnd(); uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId); uint32_t writeFieldEnd(); uint32_t writeFieldStop(); uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size); uint32_t writeMapEnd(); uint32_t writeListBegin(const TType elemType, const uint32_t size); uint32_t writeListEnd(); uint32_t writeSetBegin(const TType elemType, const uint32_t size); uint32_t writeSetEnd(); uint32_t writeBool(const bool value); uint32_t writeByte(const int8_t byte); uint32_t writeI16(const int16_t i16); uint32_t writeI32(const int32_t i32); uint32_t writeI64(const int64_t i64); uint32_t writeDouble(const double dub); uint32_t writeString(const std::string& str); uint32_t writeBinary(const std::string& str); private: void indentUp(); void indentDown(); uint32_t writePlain(const std::string& str); uint32_t writeIndented(const std::string& str); uint32_t startItem(); uint32_t endItem(); uint32_t writeItem(const std::string& str); static std::string fieldTypeName(TType type); TTransport* trans_; int32_t string_limit_; int32_t string_prefix_size_; std::string indent_str_; static const int indent_inc = 2; std::vector write_state_; std::vector list_idx_; }; /** * Constructs debug protocol handlers */ class TDebugProtocolFactory : public TProtocolFactory { public: TDebugProtocolFactory() = default; ~TDebugProtocolFactory() override = default; std::shared_ptr getProtocol(std::shared_ptr trans) override { return std::shared_ptr(new TDebugProtocol(trans)); } }; } } } // apache::thrift::protocol // TODO(dreiss): Move (part of) ThriftDebugString into a .cpp file and remove this. #include namespace apache { namespace thrift { template std::string ThriftDebugString(const ThriftStruct& ts) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; auto* buffer = new TMemoryBuffer; std::shared_ptr trans(buffer); TDebugProtocol protocol(trans); ts.write(&protocol); uint8_t* buf; uint32_t size; buffer->getBuffer(&buf, &size); return std::string((char*)buf, (unsigned int)size); } // TODO(dreiss): This is badly broken. Don't use it unless you are me. #if 0 template std::string DebugString(const std::vector& vec) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; TMemoryBuffer* buffer = new TMemoryBuffer; std::shared_ptr trans(buffer); TDebugProtocol protocol(trans); // I am gross! protocol.writeStructBegin("SomeRandomVector"); // TODO: Fix this with a trait. protocol.writeListBegin((TType)99, vec.size()); typename std::vector::const_iterator it; for (it = vec.begin(); it != vec.end(); ++it) { it->write(&protocol); } protocol.writeListEnd(); uint8_t* buf; uint32_t size; buffer->getBuffer(&buf, &size); return std::string((char*)buf, (unsigned int)size); } #endif // 0 } } // apache::thrift #endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TBinaryProtocol.h0000644000000000000000000002053614370300523023625 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ #define _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1 #include #include #include namespace apache { namespace thrift { namespace protocol { /** * The default binary protocol for thrift. Writes all data in a very basic * binary format, essentially just spitting out the raw bytes. * */ template class TBinaryProtocolT : public TVirtualProtocol > { public: static const int32_t VERSION_MASK = ((int32_t)0xffff0000); static const int32_t VERSION_1 = ((int32_t)0x80010000); // VERSION_2 (0x80020000) was taken by TDenseProtocol (which has since been removed) TBinaryProtocolT(std::shared_ptr trans) : TVirtualProtocol >(trans), trans_(trans.get()), string_limit_(0), container_limit_(0), strict_read_(false), strict_write_(true) {} TBinaryProtocolT(std::shared_ptr trans, int32_t string_limit, int32_t container_limit, bool strict_read, bool strict_write) : TVirtualProtocol >(trans), trans_(trans.get()), string_limit_(string_limit), container_limit_(container_limit), strict_read_(strict_read), strict_write_(strict_write) {} void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; } void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; } void setStrict(bool strict_read, bool strict_write) { strict_read_ = strict_read; strict_write_ = strict_write; } /** * Writing functions. */ /*ol*/ uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid); /*ol*/ uint32_t writeMessageEnd(); inline uint32_t writeStructBegin(const char* name); inline uint32_t writeStructEnd(); inline uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId); inline uint32_t writeFieldEnd(); inline uint32_t writeFieldStop(); inline uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size); inline uint32_t writeMapEnd(); inline uint32_t writeListBegin(const TType elemType, const uint32_t size); inline uint32_t writeListEnd(); inline uint32_t writeSetBegin(const TType elemType, const uint32_t size); inline uint32_t writeSetEnd(); inline uint32_t writeBool(const bool value); inline uint32_t writeByte(const int8_t byte); inline uint32_t writeI16(const int16_t i16); inline uint32_t writeI32(const int32_t i32); inline uint32_t writeI64(const int64_t i64); inline uint32_t writeDouble(const double dub); template inline uint32_t writeString(const StrType& str); inline uint32_t writeBinary(const std::string& str); /** * Reading functions */ /*ol*/ uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid); /*ol*/ uint32_t readMessageEnd(); inline uint32_t readStructBegin(std::string& name); inline uint32_t readStructEnd(); inline uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId); inline uint32_t readFieldEnd(); inline uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size); inline uint32_t readMapEnd(); inline uint32_t readListBegin(TType& elemType, uint32_t& size); inline uint32_t readListEnd(); inline uint32_t readSetBegin(TType& elemType, uint32_t& size); inline uint32_t readSetEnd(); inline uint32_t readBool(bool& value); // Provide the default readBool() implementation for std::vector using TVirtualProtocol >::readBool; inline uint32_t readByte(int8_t& byte); inline uint32_t readI16(int16_t& i16); inline uint32_t readI32(int32_t& i32); inline uint32_t readI64(int64_t& i64); inline uint32_t readDouble(double& dub); template inline uint32_t readString(StrType& str); inline uint32_t readBinary(std::string& str); int getMinSerializedSize(TType type) override; void checkReadBytesAvailable(TSet& set) override { trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_)); } void checkReadBytesAvailable(TList& list) override { trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_)); } void checkReadBytesAvailable(TMap& map) override { int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_); trans_->checkReadBytesAvailable(map.size_ * elmSize); } protected: template uint32_t readStringBody(StrType& str, int32_t sz); Transport_* trans_; int32_t string_limit_; int32_t container_limit_; // Enforce presence of version identifier bool strict_read_; bool strict_write_; }; typedef TBinaryProtocolT TBinaryProtocol; typedef TBinaryProtocolT TLEBinaryProtocol; /** * Constructs binary protocol handlers */ template class TBinaryProtocolFactoryT : public TProtocolFactory { public: TBinaryProtocolFactoryT() : string_limit_(0), container_limit_(0), strict_read_(false), strict_write_(true) {} TBinaryProtocolFactoryT(int32_t string_limit, int32_t container_limit, bool strict_read, bool strict_write) : string_limit_(string_limit), container_limit_(container_limit), strict_read_(strict_read), strict_write_(strict_write) {} ~TBinaryProtocolFactoryT() override = default; void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; } void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; } void setStrict(bool strict_read, bool strict_write) { strict_read_ = strict_read; strict_write_ = strict_write; } std::shared_ptr getProtocol(std::shared_ptr trans) override { std::shared_ptr specific_trans = std::dynamic_pointer_cast(trans); TProtocol* prot; if (specific_trans) { prot = new TBinaryProtocolT(specific_trans, string_limit_, container_limit_, strict_read_, strict_write_); } else { prot = new TBinaryProtocolT(trans, string_limit_, container_limit_, strict_read_, strict_write_); } return std::shared_ptr(prot); } private: int32_t string_limit_; int32_t container_limit_; bool strict_read_; bool strict_write_; }; typedef TBinaryProtocolFactoryT TBinaryProtocolFactory; typedef TBinaryProtocolFactoryT TLEBinaryProtocolFactory; } } } // apache::thrift::protocol #include #endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TBase64Utils.cpp0000644000000000000000000001106114303740367023262 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include using std::string; namespace apache { namespace thrift { namespace protocol { static const uint8_t* kBase64EncodeTable = (const uint8_t*)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; void base64_encode(const uint8_t* in, uint32_t len, uint8_t* buf) { buf[0] = kBase64EncodeTable[(in[0] >> 2) & 0x3f]; if (len == 3) { buf[1] = kBase64EncodeTable[((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f)]; buf[2] = kBase64EncodeTable[((in[1] << 2) & 0x3c) | ((in[2] >> 6) & 0x03)]; buf[3] = kBase64EncodeTable[in[2] & 0x3f]; } else if (len == 2) { buf[1] = kBase64EncodeTable[((in[0] << 4) & 0x30) | ((in[1] >> 4) & 0x0f)]; buf[2] = kBase64EncodeTable[(in[1] << 2) & 0x3c]; } else { // len == 1 buf[1] = kBase64EncodeTable[(in[0] << 4) & 0x30]; } } static const uint8_t kBase64DecodeTable[256] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; void base64_decode(uint8_t* buf, uint32_t len) { buf[0] = (kBase64DecodeTable[buf[0]] << 2) | (kBase64DecodeTable[buf[1]] >> 4); if (len > 2) { buf[1] = ((kBase64DecodeTable[buf[1]] << 4) & 0xf0) | (kBase64DecodeTable[buf[2]] >> 2); if (len > 3) { buf[2] = ((kBase64DecodeTable[buf[2]] << 6) & 0xc0) | (kBase64DecodeTable[buf[3]]); } } } } } } // apache::thrift::protocol thrift-0.19.0/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h0000644000000000000000000000716414303740367024711 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_TMULTIPLEXEDPROTOCOL_H_ #define THRIFT_TMULTIPLEXEDPROTOCOL_H_ 1 #include namespace apache { namespace thrift { namespace protocol { using std::shared_ptr; /** * TMultiplexedProtocol is a protocol-independent concrete decorator * that allows a Thrift client to communicate with a multiplexing Thrift server, * by prepending the service name to the function name during function calls. * * \note THIS IS NOT USED BY SERVERS. On the server, use * {@link apache::thrift::TMultiplexedProcessor TMultiplexedProcessor} to handle requests * from a multiplexing client. * * This example uses a single socket transport to invoke two services: * *
* shared_ptr transport(new TSocket("localhost", 9090)); * transport->open(); * * shared_ptr protocol(new TBinaryProtocol(transport)); * * shared_ptr mp1(new TMultiplexedProtocol(protocol, "Calculator")); * shared_ptr service1(new CalculatorClient(mp1)); * * shared_ptr mp2(new TMultiplexedProtocol(protocol, "WeatherReport")); * shared_ptr service2(new WeatherReportClient(mp2)); * * service1->add(2,2); * int temp = service2->getTemperature(); *
* * @see apache::thrift::protocol::TProtocolDecorator */ class TMultiplexedProtocol : public TProtocolDecorator { public: /** * Wrap the specified protocol, allowing it to be used to communicate with a * multiplexing server. The serviceName is required as it is * prepended to the message header so that the multiplexing server can broker * the function call to the proper service. * * \param _protocol Your communication protocol of choice, e.g. TBinaryProtocol. * \param _serviceName The service name of the service communicating via this protocol. */ TMultiplexedProtocol(shared_ptr _protocol, const std::string& _serviceName) : TProtocolDecorator(_protocol), serviceName(_serviceName), separator(":") {} ~TMultiplexedProtocol() override = default; /** * Prepends the service name to the function name, separated by TMultiplexedProtocol::SEPARATOR. * * \param [in] _name The name of the method to be called in the service. * \param [in] _type The type of message * \param [in] _name The sequential id of the message * * \throws TException Passed through from wrapped TProtocol instance. */ uint32_t writeMessageBegin_virt(const std::string& _name, const TMessageType _type, const int32_t _seqid) override; private: const std::string serviceName; const std::string separator; }; } } } #endif // THRIFT_TMULTIPLEXEDPROTOCOL_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TJSONProtocol.h0000644000000000000000000002326714370300523023156 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 #include #include namespace apache { namespace thrift { namespace protocol { // Forward declaration class TJSONContext; /** * JSON protocol for Thrift. * * Implements a protocol which uses JSON as the wire-format. * * Thrift types are represented as described below: * * 1. Every Thrift integer type is represented as a JSON number. * * 2. Thrift doubles are represented as JSON numbers. Some special values are * represented as strings: * a. "NaN" for not-a-number values * b. "Infinity" for positive infinity * c. "-Infinity" for negative infinity * * 3. Thrift string values are emitted as JSON strings, with appropriate * escaping. * * 4. Thrift binary values are encoded into Base64 and emitted as JSON strings. * The readBinary() method is written such that it will properly skip if * called on a Thrift string (although it will decode garbage data). * * NOTE: Base64 padding is optional for Thrift binary value encoding. So * the readBinary() method needs to decode both input strings with padding * and those without one. * * 5. Thrift structs are represented as JSON objects, with the field ID as the * key, and the field value represented as a JSON object with a single * key-value pair. The key is a short string identifier for that type, * followed by the value. The valid type identifiers are: "tf" for bool, * "i8" for byte, "i16" for 16-bit integer, "i32" for 32-bit integer, "i64" * for 64-bit integer, "dbl" for double-precision loating point, "str" for * string (including binary), "rec" for struct ("records"), "map" for map, * "lst" for list, "set" for set. * * 6. Thrift lists and sets are represented as JSON arrays, with the first * element of the JSON array being the string identifier for the Thrift * element type and the second element of the JSON array being the count of * the Thrift elements. The Thrift elements then follow. * * 7. Thrift maps are represented as JSON arrays, with the first two elements * of the JSON array being the string identifiers for the Thrift key type * and value type, followed by the count of the Thrift pairs, followed by a * JSON object containing the key-value pairs. Note that JSON keys can only * be strings, which means that the key type of the Thrift map should be * restricted to numeric or string types -- in the case of numerics, they * are serialized as strings. * * 8. Thrift messages are represented as JSON arrays, with the protocol * version #, the message name, the message type, and the sequence ID as * the first 4 elements. * * More discussion of the double handling is probably warranted. The aim of * the current implementation is to match as closely as possible the behavior * of Java's Double.toString(), which has no precision loss. Implementors in * other languages should strive to achieve that where possible. I have not * yet verified whether std::istringstream::operator>>, which is doing that * work for me in C++, loses any precision, but I am leaving this as a future * improvement. I may try to provide a C component for this, so that other * languages could bind to the same underlying implementation for maximum * consistency. * */ class TJSONProtocol : public TVirtualProtocol { public: TJSONProtocol(std::shared_ptr ptrans); ~TJSONProtocol() override; private: void pushContext(std::shared_ptr c); void popContext(); uint32_t writeJSONEscapeChar(uint8_t ch); uint32_t writeJSONChar(uint8_t ch); uint32_t writeJSONString(const std::string& str); uint32_t writeJSONBase64(const std::string& str); template uint32_t writeJSONInteger(NumberType num); uint32_t writeJSONDouble(double num); uint32_t writeJSONObjectStart(); uint32_t writeJSONObjectEnd(); uint32_t writeJSONArrayStart(); uint32_t writeJSONArrayEnd(); uint32_t readJSONSyntaxChar(uint8_t ch); uint32_t readJSONEscapeChar(uint16_t* out); uint32_t readJSONString(std::string& str, bool skipContext = false); uint32_t readJSONBase64(std::string& str); uint32_t readJSONNumericChars(std::string& str); template uint32_t readJSONInteger(NumberType& num); uint32_t readJSONDouble(double& num); uint32_t readJSONObjectStart(); uint32_t readJSONObjectEnd(); uint32_t readJSONArrayStart(); uint32_t readJSONArrayEnd(); public: /** * Writing functions. */ uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid); uint32_t writeMessageEnd(); uint32_t writeStructBegin(const char* name); uint32_t writeStructEnd(); uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId); uint32_t writeFieldEnd(); uint32_t writeFieldStop(); uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size); uint32_t writeMapEnd(); uint32_t writeListBegin(const TType elemType, const uint32_t size); uint32_t writeListEnd(); uint32_t writeSetBegin(const TType elemType, const uint32_t size); uint32_t writeSetEnd(); uint32_t writeBool(const bool value); uint32_t writeByte(const int8_t byte); uint32_t writeI16(const int16_t i16); uint32_t writeI32(const int32_t i32); uint32_t writeI64(const int64_t i64); uint32_t writeDouble(const double dub); uint32_t writeString(const std::string& str); uint32_t writeBinary(const std::string& str); /** * Reading functions */ uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid); uint32_t readMessageEnd(); uint32_t readStructBegin(std::string& name); uint32_t readStructEnd(); uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId); uint32_t readFieldEnd(); uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size); uint32_t readMapEnd(); uint32_t readListBegin(TType& elemType, uint32_t& size); uint32_t readListEnd(); uint32_t readSetBegin(TType& elemType, uint32_t& size); uint32_t readSetEnd(); uint32_t readBool(bool& value); // Provide the default readBool() implementation for std::vector using TVirtualProtocol::readBool; uint32_t readByte(int8_t& byte); uint32_t readI16(int16_t& i16); uint32_t readI32(int32_t& i32); uint32_t readI64(int64_t& i64); uint32_t readDouble(double& dub); uint32_t readString(std::string& str); uint32_t readBinary(std::string& str); int getMinSerializedSize(TType type) override; void checkReadBytesAvailable(TSet& set) override { trans_->checkReadBytesAvailable(set.size_ * getMinSerializedSize(set.elemType_)); } void checkReadBytesAvailable(TList& list) override { trans_->checkReadBytesAvailable(list.size_ * getMinSerializedSize(list.elemType_)); } void checkReadBytesAvailable(TMap& map) override { int elmSize = getMinSerializedSize(map.keyType_) + getMinSerializedSize(map.valueType_); trans_->checkReadBytesAvailable(map.size_ * elmSize); } class LookaheadReader { public: LookaheadReader(TTransport& trans) : trans_(&trans), hasData_(false), data_(0) {} uint8_t read() { if (hasData_) { hasData_ = false; } else { trans_->readAll(&data_, 1); } return data_; } uint8_t peek() { if (!hasData_) { trans_->readAll(&data_, 1); } hasData_ = true; return data_; } private: TTransport* trans_; bool hasData_; uint8_t data_; }; private: TTransport* trans_; std::stack > contexts_; std::shared_ptr context_; LookaheadReader reader_; }; /** * Constructs input and output protocol objects given transports. */ class TJSONProtocolFactory : public TProtocolFactory { public: TJSONProtocolFactory() = default; ~TJSONProtocolFactory() override = default; std::shared_ptr getProtocol(std::shared_ptr trans) override { return std::shared_ptr(new TJSONProtocol(trans)); } }; } } } // apache::thrift::protocol // TODO(dreiss): Move part of ThriftJSONString into a .cpp file and remove this. #include namespace apache { namespace thrift { template std::string ThriftJSONString(const ThriftStruct& ts) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; auto* buffer = new TMemoryBuffer; std::shared_ptr trans(buffer); TJSONProtocol protocol(trans); ts.write(&protocol); uint8_t* buf; uint32_t size; buffer->getBuffer(&buf, &size); return std::string((char*)buf, (unsigned int)size); } } } // apache::thrift #endif // #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 thrift-0.19.0/lib/cpp/src/thrift/protocol/TEnum.h0000644000000000000000000000333214303740367021570 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_ENUM_H_ #define _THRIFT_ENUM_H_ namespace apache { namespace thrift { namespace protocol { /** * Enumerated definition of the types that the Thrift protocol supports. * Take special note of the T_END type which is used specifically to mark * the end of a sequence of fields. */ enum TType { T_STOP = 0, T_VOID = 1, T_BOOL = 2, T_BYTE = 3, T_I08 = 3, T_I16 = 6, T_I32 = 8, T_U64 = 9, T_I64 = 10, T_DOUBLE = 4, T_STRING = 11, T_UTF7 = 11, T_STRUCT = 12, T_MAP = 13, T_SET = 14, T_LIST = 15, T_UTF8 = 16, T_UTF16 = 17 }; /** * Enumerated definition of the message types that the Thrift protocol * supports. */ enum TMessageType { T_CALL = 1, T_REPLY = 2, T_EXCEPTION = 3, T_ONEWAY = 4 }; }}} // apache::thrift::protocol #endif // #define _THRIFT_ENUM_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp0000644000000000000000000001553114303740367024135 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_CPP_ #define THRIFT_PROTOCOL_THEADERPROTOCOL_CPP_ 1 #include #include #include #include #include #include namespace apache { namespace thrift { namespace protocol { void THeaderProtocol::resetProtocol() { if (proto_ && protoId_ == trans_->getProtocolId()) { return; } protoId_ = trans_->getProtocolId(); switch (protoId_) { case T_BINARY_PROTOCOL: proto_ = std::make_shared >(trans_); break; case T_COMPACT_PROTOCOL: proto_ = std::make_shared >(trans_); break; default: throw TApplicationException(TApplicationException::INVALID_PROTOCOL, "Unknown protocol requested"); } } uint32_t THeaderProtocol::writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqId) { resetProtocol(); // Reset in case we changed protocols trans_->setSequenceNumber(seqId); return proto_->writeMessageBegin(name, messageType, seqId); } uint32_t THeaderProtocol::writeMessageEnd() { return proto_->writeMessageEnd(); } uint32_t THeaderProtocol::writeStructBegin(const char* name) { return proto_->writeStructBegin(name); } uint32_t THeaderProtocol::writeStructEnd() { return proto_->writeStructEnd(); } uint32_t THeaderProtocol::writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { return proto_->writeFieldBegin(name, fieldType, fieldId); } uint32_t THeaderProtocol::writeFieldEnd() { return proto_->writeFieldEnd(); } uint32_t THeaderProtocol::writeFieldStop() { return proto_->writeFieldStop(); } uint32_t THeaderProtocol::writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { return proto_->writeMapBegin(keyType, valType, size); } uint32_t THeaderProtocol::writeMapEnd() { return proto_->writeMapEnd(); } uint32_t THeaderProtocol::writeListBegin(const TType elemType, const uint32_t size) { return proto_->writeListBegin(elemType, size); } uint32_t THeaderProtocol::writeListEnd() { return proto_->writeListEnd(); } uint32_t THeaderProtocol::writeSetBegin(const TType elemType, const uint32_t size) { return proto_->writeSetBegin(elemType, size); } uint32_t THeaderProtocol::writeSetEnd() { return proto_->writeSetEnd(); } uint32_t THeaderProtocol::writeBool(const bool value) { return proto_->writeBool(value); } uint32_t THeaderProtocol::writeByte(const int8_t byte) { return proto_->writeByte(byte); } uint32_t THeaderProtocol::writeI16(const int16_t i16) { return proto_->writeI16(i16); } uint32_t THeaderProtocol::writeI32(const int32_t i32) { return proto_->writeI32(i32); } uint32_t THeaderProtocol::writeI64(const int64_t i64) { return proto_->writeI64(i64); } uint32_t THeaderProtocol::writeDouble(const double dub) { return proto_->writeDouble(dub); } uint32_t THeaderProtocol::writeString(const std::string& str) { return proto_->writeString(str); } uint32_t THeaderProtocol::writeBinary(const std::string& str) { return proto_->writeBinary(str); } /** * Reading functions */ uint32_t THeaderProtocol::readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqId) { // Read the next frame, and change protocols if needed try { trans_->resetProtocol(); resetProtocol(); } catch (const TApplicationException& ex) { writeMessageBegin("", T_EXCEPTION, 0); ex.write((TProtocol*)this); writeMessageEnd(); trans_->flush(); // The framing is still good, but we don't know about this protocol. // In the future, this could be made a client-side only error if // connection pooling is used. throw ex; } return proto_->readMessageBegin(name, messageType, seqId); } uint32_t THeaderProtocol::readMessageEnd() { return proto_->readMessageEnd(); } uint32_t THeaderProtocol::readStructBegin(std::string& name) { return proto_->readStructBegin(name); } uint32_t THeaderProtocol::readStructEnd() { return proto_->readStructEnd(); } uint32_t THeaderProtocol::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { return proto_->readFieldBegin(name, fieldType, fieldId); } uint32_t THeaderProtocol::readFieldEnd() { return proto_->readFieldEnd(); } uint32_t THeaderProtocol::readMapBegin(TType& keyType, TType& valType, uint32_t& size) { return proto_->readMapBegin(keyType, valType, size); } uint32_t THeaderProtocol::readMapEnd() { return proto_->readMapEnd(); } uint32_t THeaderProtocol::readListBegin(TType& elemType, uint32_t& size) { return proto_->readListBegin(elemType, size); } uint32_t THeaderProtocol::readListEnd() { return proto_->readListEnd(); } uint32_t THeaderProtocol::readSetBegin(TType& elemType, uint32_t& size) { return proto_->readSetBegin(elemType, size); } uint32_t THeaderProtocol::readSetEnd() { return proto_->readSetEnd(); } uint32_t THeaderProtocol::readBool(bool& value) { return proto_->readBool(value); } uint32_t THeaderProtocol::readByte(int8_t& byte) { return proto_->readByte(byte); } uint32_t THeaderProtocol::readI16(int16_t& i16) { return proto_->readI16(i16); } uint32_t THeaderProtocol::readI32(int32_t& i32) { return proto_->readI32(i32); } uint32_t THeaderProtocol::readI64(int64_t& i64) { return proto_->readI64(i64); } uint32_t THeaderProtocol::readDouble(double& dub) { return proto_->readDouble(dub); } uint32_t THeaderProtocol::readString(std::string& str) { return proto_->readString(str); } uint32_t THeaderProtocol::readBinary(std::string& binary) { return proto_->readBinary(binary); } } } } // apache::thrift::protocol #endif // #ifndef THRIFT_PROTOCOL_THEADERPROTOCOL_CPP_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TProtocolException.h0000644000000000000000000000630014303740367024342 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ #define _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1 #include namespace apache { namespace thrift { namespace protocol { /** * Class to encapsulate all the possible types of protocol errors that may * occur in various protocol systems. This provides a sort of generic * wrapper around the vague UNIX E_ error codes that lets a common code * base of error handling to be used for various types of protocols, i.e. * pipes etc. * */ class TProtocolException : public apache::thrift::TException { public: /** * Error codes for the various types of exceptions. */ enum TProtocolExceptionType { UNKNOWN = 0, INVALID_DATA = 1, NEGATIVE_SIZE = 2, SIZE_LIMIT = 3, BAD_VERSION = 4, NOT_IMPLEMENTED = 5, DEPTH_LIMIT = 6 }; TProtocolException() : apache::thrift::TException(), type_(UNKNOWN) {} TProtocolException(TProtocolExceptionType type) : apache::thrift::TException(), type_(type) {} TProtocolException(const std::string& message) : apache::thrift::TException(message), type_(UNKNOWN) {} TProtocolException(TProtocolExceptionType type, const std::string& message) : apache::thrift::TException(message), type_(type) {} ~TProtocolException() noexcept override = default; /** * Returns an error code that provides information about the type of error * that has occurred. * * @return Error code */ TProtocolExceptionType getType() const { return type_; } const char* what() const noexcept override { if (message_.empty()) { switch (type_) { case UNKNOWN: return "TProtocolException: Unknown protocol exception"; case INVALID_DATA: return "TProtocolException: Invalid data"; case NEGATIVE_SIZE: return "TProtocolException: Negative size"; case SIZE_LIMIT: return "TProtocolException: Exceeded size limit"; case BAD_VERSION: return "TProtocolException: Invalid version"; case NOT_IMPLEMENTED: return "TProtocolException: Not implemented"; case DEPTH_LIMIT: return "TProtocolException: Exceeded depth limit"; default: return "TProtocolException: (Invalid exception type)"; } } else { return message_.c_str(); } } protected: /** * Error code */ TProtocolExceptionType type_; }; } } } // apache::thrift::protocol #endif // #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TVirtualProtocol.h0000644000000000000000000004350114303740367024036 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ #define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1 #include namespace apache { namespace thrift { namespace protocol { using apache::thrift::transport::TTransport; /** * Helper class that provides default implementations of TProtocol methods. * * This class provides default implementations of the non-virtual TProtocol * methods. It exists primarily so TVirtualProtocol can derive from it. It * prevents TVirtualProtocol methods from causing infinite recursion if the * non-virtual methods are not overridden by the TVirtualProtocol subclass. * * You probably don't want to use this class directly. Use TVirtualProtocol * instead. */ class TProtocolDefaults : public TProtocol { public: uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { (void)name; (void)messageType; (void)seqid; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readMessageEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readStructBegin(std::string& name) { (void)name; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readStructEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { (void)name; (void)fieldType; (void)fieldId; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readFieldEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { (void)keyType; (void)valType; (void)size; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readMapEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readListBegin(TType& elemType, uint32_t& size) { (void)elemType; (void)size; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readListEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readSetBegin(TType& elemType, uint32_t& size) { (void)elemType; (void)size; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readSetEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readBool(bool& value) { (void)value; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readBool(std::vector::reference value) { (void)value; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readByte(int8_t& byte) { (void)byte; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readI16(int16_t& i16) { (void)i16; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readI32(int32_t& i32) { (void)i32; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readI64(int64_t& i64) { (void)i64; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readDouble(double& dub) { (void)dub; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readString(std::string& str) { (void)str; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t readBinary(std::string& str) { (void)str; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support reading (yet)."); } uint32_t writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid) { (void)name; (void)messageType; (void)seqid; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeMessageEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeStructBegin(const char* name) { (void)name; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeStructEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { (void)name; (void)fieldType; (void)fieldId; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeFieldEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeFieldStop() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { (void)keyType; (void)valType; (void)size; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeMapEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeListBegin(const TType elemType, const uint32_t size) { (void)elemType; (void)size; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeListEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeSetBegin(const TType elemType, const uint32_t size) { (void)elemType; (void)size; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeSetEnd() { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeBool(const bool value) { (void)value; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeByte(const int8_t byte) { (void)byte; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeI16(const int16_t i16) { (void)i16; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeI32(const int32_t i32) { (void)i32; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeI64(const int64_t i64) { (void)i64; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeDouble(const double dub) { (void)dub; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeString(const std::string& str) { (void)str; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t writeBinary(const std::string& str) { (void)str; throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "this protocol does not support writing (yet)."); } uint32_t skip(TType type) { return ::apache::thrift::protocol::skip(*this, type); } protected: TProtocolDefaults(std::shared_ptr ptrans) : TProtocol(ptrans) {} }; /** * Concrete TProtocol classes should inherit from TVirtualProtocol * so they don't have to manually override virtual methods. */ template class TVirtualProtocol : public Super_ { public: /** * Writing functions. */ uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, const int32_t seqid) override { return static_cast(this)->writeMessageBegin(name, messageType, seqid); } uint32_t writeMessageEnd_virt() override { return static_cast(this)->writeMessageEnd(); } uint32_t writeStructBegin_virt(const char* name) override { return static_cast(this)->writeStructBegin(name); } uint32_t writeStructEnd_virt() override { return static_cast(this)->writeStructEnd(); } uint32_t writeFieldBegin_virt(const char* name, const TType fieldType, const int16_t fieldId) override { return static_cast(this)->writeFieldBegin(name, fieldType, fieldId); } uint32_t writeFieldEnd_virt() override { return static_cast(this)->writeFieldEnd(); } uint32_t writeFieldStop_virt() override { return static_cast(this)->writeFieldStop(); } uint32_t writeMapBegin_virt(const TType keyType, const TType valType, const uint32_t size) override { return static_cast(this)->writeMapBegin(keyType, valType, size); } uint32_t writeMapEnd_virt() override { return static_cast(this)->writeMapEnd(); } uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) override { return static_cast(this)->writeListBegin(elemType, size); } uint32_t writeListEnd_virt() override { return static_cast(this)->writeListEnd(); } uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) override { return static_cast(this)->writeSetBegin(elemType, size); } uint32_t writeSetEnd_virt() override { return static_cast(this)->writeSetEnd(); } uint32_t writeBool_virt(const bool value) override { return static_cast(this)->writeBool(value); } uint32_t writeByte_virt(const int8_t byte) override { return static_cast(this)->writeByte(byte); } uint32_t writeI16_virt(const int16_t i16) override { return static_cast(this)->writeI16(i16); } uint32_t writeI32_virt(const int32_t i32) override { return static_cast(this)->writeI32(i32); } uint32_t writeI64_virt(const int64_t i64) override { return static_cast(this)->writeI64(i64); } uint32_t writeDouble_virt(const double dub) override { return static_cast(this)->writeDouble(dub); } uint32_t writeString_virt(const std::string& str) override { return static_cast(this)->writeString(str); } uint32_t writeBinary_virt(const std::string& str) override { return static_cast(this)->writeBinary(str); } /** * Reading functions */ uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, int32_t& seqid) override { return static_cast(this)->readMessageBegin(name, messageType, seqid); } uint32_t readMessageEnd_virt() override { return static_cast(this)->readMessageEnd(); } uint32_t readStructBegin_virt(std::string& name) override { return static_cast(this)->readStructBegin(name); } uint32_t readStructEnd_virt() override { return static_cast(this)->readStructEnd(); } uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) override { return static_cast(this)->readFieldBegin(name, fieldType, fieldId); } uint32_t readFieldEnd_virt() override { return static_cast(this)->readFieldEnd(); } uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) override { return static_cast(this)->readMapBegin(keyType, valType, size); } uint32_t readMapEnd_virt() override { return static_cast(this)->readMapEnd(); } uint32_t readListBegin_virt(TType& elemType, uint32_t& size) override { return static_cast(this)->readListBegin(elemType, size); } uint32_t readListEnd_virt() override { return static_cast(this)->readListEnd(); } uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) override { return static_cast(this)->readSetBegin(elemType, size); } uint32_t readSetEnd_virt() override { return static_cast(this)->readSetEnd(); } uint32_t readBool_virt(bool& value) override { return static_cast(this)->readBool(value); } uint32_t readBool_virt(std::vector::reference value) override { return static_cast(this)->readBool(value); } uint32_t readByte_virt(int8_t& byte) override { return static_cast(this)->readByte(byte); } uint32_t readI16_virt(int16_t& i16) override { return static_cast(this)->readI16(i16); } uint32_t readI32_virt(int32_t& i32) override { return static_cast(this)->readI32(i32); } uint32_t readI64_virt(int64_t& i64) override { return static_cast(this)->readI64(i64); } uint32_t readDouble_virt(double& dub) override { return static_cast(this)->readDouble(dub); } uint32_t readString_virt(std::string& str) override { return static_cast(this)->readString(str); } uint32_t readBinary_virt(std::string& str) override { return static_cast(this)->readBinary(str); } uint32_t skip_virt(TType type) override { return static_cast(this)->skip(type); } /* * Provide a default skip() implementation that uses non-virtual read * methods. * * Note: subclasses that use TVirtualProtocol to derive from another protocol * implementation (i.e., not TProtocolDefaults) should beware that this may * override any non-default skip() implementation provided by the parent * transport class. They may need to explicitly redefine skip() to call the * correct parent implementation, if desired. */ uint32_t skip(TType type) { auto* const prot = static_cast(this); return ::apache::thrift::protocol::skip(*prot, type); } /* * Provide a default readBool() implementation for use with * std::vector, that behaves the same as reading into a normal bool. * * Subclasses can override this if desired, but there normally shouldn't * be a need to. */ uint32_t readBool(std::vector::reference value) { bool b = false; uint32_t ret = static_cast(this)->readBool(b); value = b; return ret; } using Super_::readBool; // so we don't hide readBool(bool&) protected: TVirtualProtocol(std::shared_ptr ptrans) : Super_(ptrans) {} }; } } } // apache::thrift::protocol #endif // #define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1 thrift-0.19.0/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.cpp0000644000000000000000000000311214303740367025231 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include namespace apache { namespace thrift { namespace protocol { uint32_t TMultiplexedProtocol::writeMessageBegin_virt(const std::string& _name, const TMessageType _type, const int32_t _seqid) { if (_type == T_CALL || _type == T_ONEWAY) { return TProtocolDecorator::writeMessageBegin_virt(serviceName + separator + _name, _type, _seqid); } else { return TProtocolDecorator::writeMessageBegin_virt(_name, _type, _seqid); } } } } } thrift-0.19.0/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc0000644000000000000000000006126214303740367024324 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ #define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ 1 #include #include #include "thrift/config.h" /* * TCompactProtocol::i*ToZigzag depend on the fact that the right shift * operator on a signed integer is an arithmetic (sign-extending) shift. * If this is not the case, the current implementation will not work. * If anyone encounters this error, we can try to figure out the best * way to implement an arithmetic right shift on their platform. */ #if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT) # error "Unable to determine the behavior of a signed right shift" #endif #if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT # error "TCompactProtocol currently only works if a signed right shift is arithmetic" #endif #ifdef __GNUC__ #define UNLIKELY(val) (__builtin_expect((val), 0)) #else #define UNLIKELY(val) (val) #endif namespace apache { namespace thrift { namespace protocol { namespace detail { namespace compact { enum Types { CT_STOP = 0x00, CT_BOOLEAN_TRUE = 0x01, CT_BOOLEAN_FALSE = 0x02, CT_BYTE = 0x03, CT_I16 = 0x04, CT_I32 = 0x05, CT_I64 = 0x06, CT_DOUBLE = 0x07, CT_BINARY = 0x08, CT_LIST = 0x09, CT_SET = 0x0A, CT_MAP = 0x0B, CT_STRUCT = 0x0C }; const int8_t TTypeToCType[16] = { CT_STOP, // T_STOP 0, // unused CT_BOOLEAN_TRUE, // T_BOOL CT_BYTE, // T_BYTE CT_DOUBLE, // T_DOUBLE 0, // unused CT_I16, // T_I16 0, // unused CT_I32, // T_I32 0, // unused CT_I64, // T_I64 CT_BINARY, // T_STRING CT_STRUCT, // T_STRUCT CT_MAP, // T_MAP CT_SET, // T_SET CT_LIST, // T_LIST }; }} // end detail::compact namespace template uint32_t TCompactProtocolT::writeMessageBegin( const std::string& name, const TMessageType messageType, const int32_t seqid) { uint32_t wsize = 0; wsize += writeByte(PROTOCOL_ID); wsize += writeByte((VERSION_N & VERSION_MASK) | (((int32_t)messageType << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); wsize += writeVarint32(seqid); wsize += writeString(name); return wsize; } /** * Write a field header containing the field id and field type. If the * difference between the current field id and the last one is small (< 15), * then the field id will be encoded in the 4 MSB as a delta. Otherwise, the * field id will follow the type header as a zigzag varint. */ template uint32_t TCompactProtocolT::writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { if (fieldType == T_BOOL) { booleanField_.name = name; booleanField_.fieldType = fieldType; booleanField_.fieldId = fieldId; } else { return writeFieldBeginInternal(name, fieldType, fieldId, -1); } return 0; } /** * Write the STOP symbol so we know there are no more fields in this struct. */ template uint32_t TCompactProtocolT::writeFieldStop() { return writeByte(T_STOP); } /** * Write a struct begin. This doesn't actually put anything on the wire. We * use it as an opportunity to put special placeholder markers on the field * stack so we can get the field id deltas correct. */ template uint32_t TCompactProtocolT::writeStructBegin(const char* name) { (void) name; lastField_.push(lastFieldId_); lastFieldId_ = 0; return 0; } /** * Write a struct end. This doesn't actually put anything on the wire. We use * this as an opportunity to pop the last field from the current struct off * of the field stack. */ template uint32_t TCompactProtocolT::writeStructEnd() { lastFieldId_ = lastField_.top(); lastField_.pop(); return 0; } /** * Write a List header. */ template uint32_t TCompactProtocolT::writeListBegin(const TType elemType, const uint32_t size) { return writeCollectionBegin(elemType, size); } /** * Write a set header. */ template uint32_t TCompactProtocolT::writeSetBegin(const TType elemType, const uint32_t size) { return writeCollectionBegin(elemType, size); } /** * Write a map header. If the map is empty, omit the key and value type * headers, as we don't need any additional information to skip it. */ template uint32_t TCompactProtocolT::writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { uint32_t wsize = 0; if (size == 0) { wsize += writeByte(0); } else { wsize += writeVarint32(size); wsize += writeByte(getCompactType(keyType) << 4 | getCompactType(valType)); } return wsize; } /** * Write a boolean value. Potentially, this could be a boolean field, in * which case the field header info isn't written yet. If so, decide what the * right type header is for the value and then write the field header. * Otherwise, write a single byte. */ template uint32_t TCompactProtocolT::writeBool(const bool value) { uint32_t wsize = 0; if (booleanField_.name != nullptr) { // we haven't written the field header yet wsize += writeFieldBeginInternal(booleanField_.name, booleanField_.fieldType, booleanField_.fieldId, static_cast(value ? detail::compact::CT_BOOLEAN_TRUE : detail::compact::CT_BOOLEAN_FALSE)); booleanField_.name = nullptr; } else { // we're not part of a field, so just write the value wsize += writeByte(static_cast(value ? detail::compact::CT_BOOLEAN_TRUE : detail::compact::CT_BOOLEAN_FALSE)); } return wsize; } template uint32_t TCompactProtocolT::writeByte(const int8_t byte) { trans_->write((uint8_t*)&byte, 1); return 1; } /** * Write an i16 as a zigzag varint. */ template uint32_t TCompactProtocolT::writeI16(const int16_t i16) { return writeVarint32(i32ToZigzag(i16)); } /** * Write an i32 as a zigzag varint. */ template uint32_t TCompactProtocolT::writeI32(const int32_t i32) { return writeVarint32(i32ToZigzag(i32)); } /** * Write an i64 as a zigzag varint. */ template uint32_t TCompactProtocolT::writeI64(const int64_t i64) { return writeVarint64(i64ToZigzag(i64)); } /** * Write a double to the wire as 8 bytes. */ template uint32_t TCompactProtocolT::writeDouble(const double dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); auto bits = bitwise_cast(dub); bits = THRIFT_htolell(bits); trans_->write((uint8_t*)&bits, 8); return 8; } /** * Write a string to the wire with a varint size preceding. */ template uint32_t TCompactProtocolT::writeString(const std::string& str) { return writeBinary(str); } template uint32_t TCompactProtocolT::writeBinary(const std::string& str) { if(str.size() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); auto ssize = static_cast(str.size()); uint32_t wsize = writeVarint32(ssize) ; // checking ssize + wsize > uint_max, but we don't want to overflow while checking for overflows. // transforming the check to ssize > uint_max - wsize if(ssize > (std::numeric_limits::max)() - wsize) throw TProtocolException(TProtocolException::SIZE_LIMIT); wsize += ssize; trans_->write((uint8_t*)str.data(), ssize); return wsize; } // // Internal Writing methods // /** * The workhorse of writeFieldBegin. It has the option of doing a * 'type override' of the type header. This is used specifically in the * boolean field case. */ template int32_t TCompactProtocolT::writeFieldBeginInternal( const char* name, const TType fieldType, const int16_t fieldId, int8_t typeOverride) { (void) name; uint32_t wsize = 0; // if there's a type override, use that. int8_t typeToWrite = (typeOverride == -1 ? getCompactType(fieldType) : typeOverride); // check if we can use delta encoding for the field id if (fieldId > lastFieldId_ && fieldId - lastFieldId_ <= 15) { // write them together wsize += writeByte(static_cast((fieldId - lastFieldId_) << 4 | typeToWrite)); } else { // write them separate wsize += writeByte(typeToWrite); wsize += writeI16(fieldId); } lastFieldId_ = fieldId; return wsize; } /** * Abstract method for writing the start of lists and sets. List and sets on * the wire differ only by the type indicator. */ template uint32_t TCompactProtocolT::writeCollectionBegin(const TType elemType, int32_t size) { uint32_t wsize = 0; if (size <= 14) { wsize += writeByte(static_cast(size << 4 | getCompactType(elemType))); } else { wsize += writeByte(0xf0 | getCompactType(elemType)); wsize += writeVarint32(size); } return wsize; } /** * Write an i32 as a varint. Results in 1-5 bytes on the wire. */ template uint32_t TCompactProtocolT::writeVarint32(uint32_t n) { uint8_t buf[5]; uint32_t wsize = 0; while (true) { if ((n & ~0x7F) == 0) { buf[wsize++] = (int8_t)n; break; } else { buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); n >>= 7; } } trans_->write(buf, wsize); return wsize; } /** * Write an i64 as a varint. Results in 1-10 bytes on the wire. */ template uint32_t TCompactProtocolT::writeVarint64(uint64_t n) { uint8_t buf[10]; uint32_t wsize = 0; while (true) { if ((n & ~0x7FL) == 0) { buf[wsize++] = (int8_t)n; break; } else { buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); n >>= 7; } } trans_->write(buf, wsize); return wsize; } /** * Convert l into a zigzag long. This allows negative numbers to be * represented compactly as a varint. */ template uint64_t TCompactProtocolT::i64ToZigzag(const int64_t l) { return (static_cast(l) << 1) ^ (l >> 63); } /** * Convert n into a zigzag int. This allows negative numbers to be * represented compactly as a varint. */ template uint32_t TCompactProtocolT::i32ToZigzag(const int32_t n) { return (static_cast(n) << 1) ^ (n >> 31); } /** * Given a TType value, find the appropriate detail::compact::Types value */ template int8_t TCompactProtocolT::getCompactType(const TType ttype) { return detail::compact::TTypeToCType[ttype]; } // // Reading Methods // /** * Read a message header. */ template uint32_t TCompactProtocolT::readMessageBegin( std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t rsize = 0; int8_t protocolId; int8_t versionAndType; int8_t version; rsize += readByte(protocolId); if (protocolId != PROTOCOL_ID) { throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol identifier"); } rsize += readByte(versionAndType); version = (int8_t)(versionAndType & VERSION_MASK); if (version != VERSION_N) { throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol version"); } messageType = (TMessageType)((versionAndType >> TYPE_SHIFT_AMOUNT) & TYPE_BITS); rsize += readVarint32(seqid); rsize += readString(name); return rsize; } /** * Read a struct begin. There's nothing on the wire for this, but it is our * opportunity to push a new struct begin marker on the field stack. */ template uint32_t TCompactProtocolT::readStructBegin(std::string& name) { name = ""; lastField_.push(lastFieldId_); lastFieldId_ = 0; return 0; } /** * Doesn't actually consume any wire data, just removes the last field for * this struct from the field stack. */ template uint32_t TCompactProtocolT::readStructEnd() { lastFieldId_ = lastField_.top(); lastField_.pop(); return 0; } /** * Read a field header off the wire. */ template uint32_t TCompactProtocolT::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { (void) name; uint32_t rsize = 0; int8_t byte; int8_t type; rsize += readByte(byte); type = (byte & 0x0f); // if it's a stop, then we can return immediately, as the struct is over. if (type == T_STOP) { fieldType = T_STOP; fieldId = 0; return rsize; } // mask off the 4 MSB of the type header. it could contain a field id delta. auto modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4); if (modifier == 0) { // not a delta, look ahead for the zigzag varint field id. rsize += readI16(fieldId); } else { fieldId = (int16_t)(lastFieldId_ + modifier); } fieldType = getTType(type); // if this happens to be a boolean field, the value is encoded in the type if (type == detail::compact::CT_BOOLEAN_TRUE || type == detail::compact::CT_BOOLEAN_FALSE) { // save the boolean value in a special instance variable. boolValue_.hasBoolValue = true; boolValue_.boolValue = (type == detail::compact::CT_BOOLEAN_TRUE ? true : false); } // push the new field onto the field stack so we can keep the deltas going. lastFieldId_ = fieldId; return rsize; } /** * Read a map header off the wire. If the size is zero, skip reading the key * and value type. This means that 0-length maps will yield TMaps without the * "correct" types. */ template uint32_t TCompactProtocolT::readMapBegin(TType& keyType, TType& valType, uint32_t& size) { uint32_t rsize = 0; int8_t kvType = 0; int32_t msize = 0; rsize += readVarint32(msize); if (msize != 0) rsize += readByte(kvType); if (msize < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (container_limit_ && msize > container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } keyType = getTType((int8_t)((uint8_t)kvType >> 4)); valType = getTType((int8_t)((uint8_t)kvType & 0xf)); size = (uint32_t)msize; TMap map(keyType, valType, size); checkReadBytesAvailable(map); return rsize; } /** * Read a list header off the wire. If the list size is 0-14, the size will * be packed into the element type header. If it's a longer list, the 4 MSB * of the element type header will be 0xF, and a varint will follow with the * true size. */ template uint32_t TCompactProtocolT::readListBegin(TType& elemType, uint32_t& size) { int8_t size_and_type; uint32_t rsize = 0; int32_t lsize; rsize += readByte(size_and_type); lsize = ((uint8_t)size_and_type >> 4) & 0x0f; if (lsize == 15) { rsize += readVarint32(lsize); } if (lsize < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (container_limit_ && lsize > container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } elemType = getTType((int8_t)(size_and_type & 0x0f)); size = (uint32_t)lsize; TList list(elemType, size); checkReadBytesAvailable(list); return rsize; } /** * Read a set header off the wire. If the set size is 0-14, the size will * be packed into the element type header. If it's a longer set, the 4 MSB * of the element type header will be 0xF, and a varint will follow with the * true size. */ template uint32_t TCompactProtocolT::readSetBegin(TType& elemType, uint32_t& size) { return readListBegin(elemType, size); } /** * Read a boolean off the wire. If this is a boolean field, the value should * already have been read during readFieldBegin, so we'll just consume the * pre-stored value. Otherwise, read a byte. */ template uint32_t TCompactProtocolT::readBool(bool& value) { if (boolValue_.hasBoolValue == true) { value = boolValue_.boolValue; boolValue_.hasBoolValue = false; return 0; } else { int8_t val; readByte(val); value = (val == detail::compact::CT_BOOLEAN_TRUE); return 1; } } /** * Read a single byte off the wire. Nothing interesting here. */ template uint32_t TCompactProtocolT::readByte(int8_t& byte) { uint8_t b[1]; trans_->readAll(b, 1); byte = *(int8_t*)b; return 1; } /** * Read an i16 from the wire as a zigzag varint. */ template uint32_t TCompactProtocolT::readI16(int16_t& i16) { int32_t value; uint32_t rsize = readVarint32(value); i16 = (int16_t)zigzagToI32(value); return rsize; } /** * Read an i32 from the wire as a zigzag varint. */ template uint32_t TCompactProtocolT::readI32(int32_t& i32) { int32_t value; uint32_t rsize = readVarint32(value); i32 = zigzagToI32(value); return rsize; } /** * Read an i64 from the wire as a zigzag varint. */ template uint32_t TCompactProtocolT::readI64(int64_t& i64) { int64_t value; uint32_t rsize = readVarint64(value); i64 = zigzagToI64(value); return rsize; } /** * No magic here - just read a double off the wire. */ template uint32_t TCompactProtocolT::readDouble(double& dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); union { uint64_t bits; uint8_t b[8]; } u; trans_->readAll(u.b, 8); u.bits = THRIFT_letohll(u.bits); dub = bitwise_cast(u.bits); return 8; } template uint32_t TCompactProtocolT::readString(std::string& str) { return readBinary(str); } /** * Read a byte[] from the wire. */ template uint32_t TCompactProtocolT::readBinary(std::string& str) { int32_t rsize = 0; int32_t size; rsize += readVarint32(size); // Catch empty string case if (size == 0) { str = ""; return rsize; } // Catch error cases if (size < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } if (string_limit_ > 0 && size > string_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } // Use the heap here to prevent stack overflow for v. large strings if (size > string_buf_size_ || string_buf_ == nullptr) { void* new_string_buf = std::realloc(string_buf_, (uint32_t)size); if (new_string_buf == nullptr) { throw std::bad_alloc(); } string_buf_ = (uint8_t*)new_string_buf; string_buf_size_ = size; } trans_->readAll(string_buf_, size); str.assign((char*)string_buf_, size); trans_->checkReadBytesAvailable(rsize + (uint32_t)size); return rsize + (uint32_t)size; } /** * Read an i32 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 5 bytes. */ template uint32_t TCompactProtocolT::readVarint32(int32_t& i32) { int64_t val; uint32_t rsize = readVarint64(val); i32 = (int32_t)val; return rsize; } /** * Read an i64 from the wire as a proper varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 10 bytes. */ template uint32_t TCompactProtocolT::readVarint64(int64_t& i64) { uint32_t rsize = 0; uint64_t val = 0; int shift = 0; uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes. uint32_t buf_size = sizeof(buf); const uint8_t* borrowed = trans_->borrow(buf, &buf_size); // Fast path. if (borrowed != nullptr) { while (true) { uint8_t byte = borrowed[rsize]; rsize++; val |= (uint64_t)(byte & 0x7f) << shift; shift += 7; if (!(byte & 0x80)) { i64 = val; trans_->consume(rsize); return rsize; } // Have to check for invalid data so we don't crash. if (UNLIKELY(rsize == sizeof(buf))) { throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); } } } // Slow path. else { while (true) { uint8_t byte; rsize += trans_->readAll(&byte, 1); val |= (uint64_t)(byte & 0x7f) << shift; shift += 7; if (!(byte & 0x80)) { i64 = val; return rsize; } // Might as well check for invalid data on the slow path too. if (UNLIKELY(rsize >= sizeof(buf))) { throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); } } } } /** * Convert from zigzag int to int. */ template int32_t TCompactProtocolT::zigzagToI32(uint32_t n) { return (n >> 1) ^ static_cast(-static_cast(n & 1)); } /** * Convert from zigzag long to long. */ template int64_t TCompactProtocolT::zigzagToI64(uint64_t n) { return (n >> 1) ^ static_cast(-static_cast(n & 1)); } template TType TCompactProtocolT::getTType(int8_t type) { switch (type) { case T_STOP: return T_STOP; case detail::compact::CT_BOOLEAN_FALSE: case detail::compact::CT_BOOLEAN_TRUE: return T_BOOL; case detail::compact::CT_BYTE: return T_BYTE; case detail::compact::CT_I16: return T_I16; case detail::compact::CT_I32: return T_I32; case detail::compact::CT_I64: return T_I64; case detail::compact::CT_DOUBLE: return T_DOUBLE; case detail::compact::CT_BINARY: return T_STRING; case detail::compact::CT_LIST: return T_LIST; case detail::compact::CT_SET: return T_SET; case detail::compact::CT_MAP: return T_MAP; case detail::compact::CT_STRUCT: return T_STRUCT; default: throw TException(std::string("don't know what type: ") + (char)type); } } // Return the minimum number of bytes a type will consume on the wire template int TCompactProtocolT::getMinSerializedSize(TType type) { switch (type) { case T_STOP: return 0; case T_VOID: return 0; case T_BOOL: return sizeof(int8_t); case T_DOUBLE: return 8; // uses fixedLongToBytes() which always writes 8 bytes case T_BYTE: return sizeof(int8_t); case T_I16: return sizeof(int8_t); // zigzag case T_I32: return sizeof(int8_t); // zigzag case T_I64: return sizeof(int8_t); // zigzag case T_STRING: return sizeof(int8_t); // string length case T_STRUCT: return 0; // empty struct case T_MAP: return sizeof(int8_t); // element count case T_SET: return sizeof(int8_t); // element count case T_LIST: return sizeof(int8_t); // element count default: throw TProtocolException(TProtocolException::UNKNOWN, "unrecognized type code"); } } }}} // apache::thrift::protocol #endif // _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc0000644000000000000000000003631014452237057024160 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ #define _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ 1 #include #include #include namespace apache { namespace thrift { namespace protocol { template uint32_t TBinaryProtocolT::writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid) { if (this->strict_write_) { int32_t version = (VERSION_1) | ((int32_t)messageType); uint32_t wsize = 0; wsize += writeI32(version); wsize += writeString(name); wsize += writeI32(seqid); return wsize; } else { uint32_t wsize = 0; wsize += writeString(name); wsize += writeByte((int8_t)messageType); wsize += writeI32(seqid); return wsize; } } template uint32_t TBinaryProtocolT::writeMessageEnd() { return 0; } template uint32_t TBinaryProtocolT::writeStructBegin(const char* name) { (void)name; return 0; } template uint32_t TBinaryProtocolT::writeStructEnd() { return 0; } template uint32_t TBinaryProtocolT::writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { (void)name; uint32_t wsize = 0; wsize += writeByte((int8_t)fieldType); wsize += writeI16(fieldId); return wsize; } template uint32_t TBinaryProtocolT::writeFieldEnd() { return 0; } template uint32_t TBinaryProtocolT::writeFieldStop() { return writeByte((int8_t)T_STOP); } template uint32_t TBinaryProtocolT::writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { uint32_t wsize = 0; wsize += writeByte((int8_t)keyType); wsize += writeByte((int8_t)valType); wsize += writeI32((int32_t)size); return wsize; } template uint32_t TBinaryProtocolT::writeMapEnd() { return 0; } template uint32_t TBinaryProtocolT::writeListBegin(const TType elemType, const uint32_t size) { uint32_t wsize = 0; wsize += writeByte((int8_t)elemType); wsize += writeI32((int32_t)size); return wsize; } template uint32_t TBinaryProtocolT::writeListEnd() { return 0; } template uint32_t TBinaryProtocolT::writeSetBegin(const TType elemType, const uint32_t size) { uint32_t wsize = 0; wsize += writeByte((int8_t)elemType); wsize += writeI32((int32_t)size); return wsize; } template uint32_t TBinaryProtocolT::writeSetEnd() { return 0; } template uint32_t TBinaryProtocolT::writeBool(const bool value) { uint8_t tmp = value ? 1 : 0; this->trans_->write(&tmp, 1); return 1; } template uint32_t TBinaryProtocolT::writeByte(const int8_t byte) { this->trans_->write((uint8_t*)&byte, 1); return 1; } template uint32_t TBinaryProtocolT::writeI16(const int16_t i16) { auto net = (int16_t)ByteOrder_::toWire16(i16); this->trans_->write((uint8_t*)&net, 2); return 2; } template uint32_t TBinaryProtocolT::writeI32(const int32_t i32) { auto net = (int32_t)ByteOrder_::toWire32(i32); this->trans_->write((uint8_t*)&net, 4); return 4; } template uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { auto net = (int64_t)ByteOrder_::toWire64(i64); this->trans_->write((uint8_t*)&net, 8); return 8; } template uint32_t TBinaryProtocolT::writeDouble(const double dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); auto bits = bitwise_cast(dub); bits = ByteOrder_::toWire64(bits); this->trans_->write((uint8_t*)&bits, 8); return 8; } template template uint32_t TBinaryProtocolT::writeString(const StrType& str) { if (str.size() > static_cast((std::numeric_limits::max)())) throw TProtocolException(TProtocolException::SIZE_LIMIT); auto size = static_cast(str.size()); uint32_t result = writeI32((int32_t)size); if (size > 0) { this->trans_->write((uint8_t*)str.data(), size); } return result + size; } template uint32_t TBinaryProtocolT::writeBinary(const std::string& str) { return TBinaryProtocolT::writeString(str); } /** * Reading functions */ template uint32_t TBinaryProtocolT::readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t result = 0; int32_t sz; result += readI32(sz); if (sz < 0) { // Check for correct version number int32_t version = sz & VERSION_MASK; if (version != VERSION_1) { throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier"); } messageType = (TMessageType)(sz & 0x000000ff); result += readString(name); result += readI32(seqid); } else { if (this->strict_read_) { throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?"); } else { // Handle pre-versioned input int8_t type; result += readStringBody(name, sz); result += readByte(type); messageType = (TMessageType)type; result += readI32(seqid); } } return result; } template uint32_t TBinaryProtocolT::readMessageEnd() { return 0; } template uint32_t TBinaryProtocolT::readStructBegin(std::string& name) { name = ""; return 0; } template uint32_t TBinaryProtocolT::readStructEnd() { return 0; } template uint32_t TBinaryProtocolT::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { (void)name; uint32_t result = 0; int8_t type; result += readByte(type); fieldType = (TType)type; if (fieldType == T_STOP) { fieldId = 0; return result; } result += readI16(fieldId); return result; } template uint32_t TBinaryProtocolT::readFieldEnd() { return 0; } template uint32_t TBinaryProtocolT::readMapBegin(TType& keyType, TType& valType, uint32_t& size) { int8_t k, v; uint32_t result = 0; int32_t sizei; result += readByte(k); keyType = (TType)k; result += readByte(v); valType = (TType)v; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (this->container_limit_ && sizei > this->container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; TMap map(keyType, valType, size); checkReadBytesAvailable(map); return result; } template uint32_t TBinaryProtocolT::readMapEnd() { return 0; } template uint32_t TBinaryProtocolT::readListBegin(TType& elemType, uint32_t& size) { int8_t e; uint32_t result = 0; int32_t sizei; result += readByte(e); elemType = (TType)e; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (this->container_limit_ && sizei > this->container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; TList list(elemType, size); checkReadBytesAvailable(list); return result; } template uint32_t TBinaryProtocolT::readListEnd() { return 0; } template uint32_t TBinaryProtocolT::readSetBegin(TType& elemType, uint32_t& size) { int8_t e; uint32_t result = 0; int32_t sizei; result += readByte(e); elemType = (TType)e; result += readI32(sizei); if (sizei < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } else if (this->container_limit_ && sizei > this->container_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } size = (uint32_t)sizei; TSet set(elemType, size); checkReadBytesAvailable(set); return result; } template uint32_t TBinaryProtocolT::readSetEnd() { return 0; } template uint32_t TBinaryProtocolT::readBool(bool& value) { uint8_t b[1]; this->trans_->readAll(b, 1); value = *(int8_t*)b != 0; return 1; } template uint32_t TBinaryProtocolT::readByte(int8_t& byte) { uint8_t b[1]; this->trans_->readAll(b, 1); byte = *(int8_t*)b; return 1; } template uint32_t TBinaryProtocolT::readI16(int16_t& i16) { union bytes { uint8_t b[2]; int16_t all; } theBytes; this->trans_->readAll(theBytes.b, 2); i16 = (int16_t)ByteOrder_::fromWire16(theBytes.all); return 2; } template uint32_t TBinaryProtocolT::readI32(int32_t& i32) { union bytes { uint8_t b[4]; int32_t all; } theBytes; this->trans_->readAll(theBytes.b, 4); i32 = (int32_t)ByteOrder_::fromWire32(theBytes.all); return 4; } template uint32_t TBinaryProtocolT::readI64(int64_t& i64) { union bytes { uint8_t b[8]; int64_t all; } theBytes; this->trans_->readAll(theBytes.b, 8); i64 = (int64_t)ByteOrder_::fromWire64(theBytes.all); return 8; } template uint32_t TBinaryProtocolT::readDouble(double& dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); union bytes { uint8_t b[8]; uint64_t all; } theBytes; this->trans_->readAll(theBytes.b, 8); theBytes.all = ByteOrder_::fromWire64(theBytes.all); dub = bitwise_cast(theBytes.all); return 8; } template template uint32_t TBinaryProtocolT::readString(StrType& str) { uint32_t result; int32_t size; result = readI32(size); return result + readStringBody(str, size); } template uint32_t TBinaryProtocolT::readBinary(std::string& str) { return TBinaryProtocolT::readString(str); } template template uint32_t TBinaryProtocolT::readStringBody(StrType& str, int32_t size) { uint32_t result = 0; // Catch error cases if (size < 0) { throw TProtocolException(TProtocolException::NEGATIVE_SIZE); } if (this->string_limit_ > 0 && size > this->string_limit_) { throw TProtocolException(TProtocolException::SIZE_LIMIT); } // Catch empty string case if (size == 0) { str.clear(); return result; } // Try to borrow first uint32_t got = size; const uint8_t* borrow_buf = this->trans_->borrow(nullptr, &got); if (borrow_buf) { str.assign((const char*)borrow_buf, size); this->trans_->consume(size); return size; } str.resize(size); this->trans_->readAll(reinterpret_cast(&str[0]), size); return (uint32_t)size; } // Return the minimum number of bytes a type will consume on the wire template int TBinaryProtocolT::getMinSerializedSize(TType type) { switch (type) { case T_STOP: return 0; case T_VOID: return 0; case T_BOOL: return sizeof(int8_t); case T_BYTE: return sizeof(int8_t); case T_DOUBLE: return sizeof(double); case T_I16: return sizeof(short); case T_I32: return sizeof(int); case T_I64: return sizeof(long); case T_STRING: return sizeof(int); // string length case T_STRUCT: return 0; // empty struct case T_MAP: return sizeof(int); // element count case T_SET: return sizeof(int); // element count case T_LIST: return sizeof(int); // element count default: throw TProtocolException(TProtocolException::UNKNOWN, "unrecognized type code"); } } } } } // apache::thrift::protocol #endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp0000644000000000000000000007401614303740367023521 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include using namespace apache::thrift::transport; namespace apache { namespace thrift { namespace protocol { // Static data static const uint8_t kJSONObjectStart = '{'; static const uint8_t kJSONObjectEnd = '}'; static const uint8_t kJSONArrayStart = '['; static const uint8_t kJSONArrayEnd = ']'; static const uint8_t kJSONPairSeparator = ':'; static const uint8_t kJSONElemSeparator = ','; static const uint8_t kJSONBackslash = '\\'; static const uint8_t kJSONStringDelimiter = '"'; static const uint8_t kJSONEscapeChar = 'u'; static const std::string kJSONEscapePrefix("\\u00"); static const uint32_t kThriftVersion1 = 1; static const std::string kThriftNan("NaN"); static const std::string kThriftInfinity("Infinity"); static const std::string kThriftNegativeInfinity("-Infinity"); static const std::string kTypeNameBool("tf"); static const std::string kTypeNameByte("i8"); static const std::string kTypeNameI16("i16"); static const std::string kTypeNameI32("i32"); static const std::string kTypeNameI64("i64"); static const std::string kTypeNameDouble("dbl"); static const std::string kTypeNameStruct("rec"); static const std::string kTypeNameString("str"); static const std::string kTypeNameMap("map"); static const std::string kTypeNameList("lst"); static const std::string kTypeNameSet("set"); static const std::string& getTypeNameForTypeID(TType typeID) { switch (typeID) { case T_BOOL: return kTypeNameBool; case T_BYTE: return kTypeNameByte; case T_I16: return kTypeNameI16; case T_I32: return kTypeNameI32; case T_I64: return kTypeNameI64; case T_DOUBLE: return kTypeNameDouble; case T_STRING: return kTypeNameString; case T_STRUCT: return kTypeNameStruct; case T_MAP: return kTypeNameMap; case T_SET: return kTypeNameSet; case T_LIST: return kTypeNameList; default: throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unrecognized type"); } } static TType getTypeIDForTypeName(const std::string& name) { TType result = T_STOP; // Sentinel value if (name.length() > 1) { switch (name[0]) { case 'd': result = T_DOUBLE; break; case 'i': switch (name[1]) { case '8': result = T_BYTE; break; case '1': result = T_I16; break; case '3': result = T_I32; break; case '6': result = T_I64; break; } break; case 'l': result = T_LIST; break; case 'm': result = T_MAP; break; case 'r': result = T_STRUCT; break; case 's': if (name[1] == 't') { result = T_STRING; } else if (name[1] == 'e') { result = T_SET; } break; case 't': result = T_BOOL; break; } } if (result == T_STOP) { throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, "Unrecognized type"); } return result; } // This table describes the handling for the first 0x30 characters // 0 : escape using "\u00xx" notation // 1 : just output index // : escape using "\" notation static const uint8_t kJSONCharTable[0x30] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0, 0, 0, 0, 0, 0, 0, 0, 'b', 't', 'n', 0, 'f', 'r', 0, 0, // 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 1, 1, '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 }; // This string's characters must match up with the elements in kEscapeCharVals. // I don't have '/' on this list even though it appears on www.json.org -- // it is not in the RFC const static std::string kEscapeChars("\"\\bfnrt"); // The elements of this array must match up with the sequence of characters in // kEscapeChars const static uint8_t kEscapeCharVals[7] = { '"', '\\', '\b', '\f', '\n', '\r', '\t', }; // Static helper functions // Read 1 character from the transport trans and verify that it is the // expected character ch. // Throw a protocol exception if it is not. static uint32_t readSyntaxChar(TJSONProtocol::LookaheadReader& reader, uint8_t ch) { uint8_t ch2 = reader.read(); if (ch2 != ch) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected \'" + std::string((char*)&ch, 1) + "\'; got \'" + std::string((char*)&ch2, 1) + "\'."); } return 1; } // Return the integer value of a hex character ch. // Throw a protocol exception if the character is not [0-9a-f]. static uint8_t hexVal(uint8_t ch) { if ((ch >= '0') && (ch <= '9')) { return ch - '0'; } else if ((ch >= 'a') && (ch <= 'f')) { return ch - 'a' + 10; } else { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected hex val ([0-9a-f]); got \'" + std::string((char*)&ch, 1) + "\'."); } } // Return the hex character representing the integer val. The value is masked // to make sure it is in the correct range. static uint8_t hexChar(uint8_t val) { val &= 0x0F; if (val < 10) { return val + '0'; } else { return val - 10 + 'a'; } } // Return true if the character ch is in [-+0-9.Ee]; false otherwise static bool isJSONNumeric(uint8_t ch) { switch (ch) { case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'E': case 'e': return true; } return false; } // Return true if the code unit is high surrogate static bool isHighSurrogate(uint16_t val) { return val >= 0xD800 && val <= 0xDBFF; } // Return true if the code unit is low surrogate static bool isLowSurrogate(uint16_t val) { return val >= 0xDC00 && val <= 0xDFFF; } /** * Class to serve as base JSON context and as base class for other context * implementations */ class TJSONContext { public: TJSONContext() = default; virtual ~TJSONContext() = default; /** * Write context data to the transport. Default is to do nothing. */ virtual uint32_t write(TTransport& trans) { (void)trans; return 0; }; /** * Read context data from the transport. Default is to do nothing. */ virtual uint32_t read(TJSONProtocol::LookaheadReader& reader) { (void)reader; return 0; }; /** * Return true if numbers need to be escaped as strings in this context. * Default behavior is to return false. */ virtual bool escapeNum() { return false; } }; // Context class for object member key-value pairs class JSONPairContext : public TJSONContext { public: JSONPairContext() : first_(true), colon_(true) {} uint32_t write(TTransport& trans) override { if (first_) { first_ = false; colon_ = true; return 0; } else { trans.write(colon_ ? &kJSONPairSeparator : &kJSONElemSeparator, 1); colon_ = !colon_; return 1; } } uint32_t read(TJSONProtocol::LookaheadReader& reader) override { if (first_) { first_ = false; colon_ = true; return 0; } else { uint8_t ch = (colon_ ? kJSONPairSeparator : kJSONElemSeparator); colon_ = !colon_; return readSyntaxChar(reader, ch); } } // Numbers must be turned into strings if they are the key part of a pair bool escapeNum() override { return colon_; } private: bool first_; bool colon_; }; // Context class for lists class JSONListContext : public TJSONContext { public: JSONListContext() : first_(true) {} uint32_t write(TTransport& trans) override { if (first_) { first_ = false; return 0; } else { trans.write(&kJSONElemSeparator, 1); return 1; } } uint32_t read(TJSONProtocol::LookaheadReader& reader) override { if (first_) { first_ = false; return 0; } else { return readSyntaxChar(reader, kJSONElemSeparator); } } private: bool first_; }; TJSONProtocol::TJSONProtocol(std::shared_ptr ptrans) : TVirtualProtocol(ptrans), trans_(ptrans.get()), context_(new TJSONContext()), reader_(*ptrans) { } TJSONProtocol::~TJSONProtocol() = default; void TJSONProtocol::pushContext(std::shared_ptr c) { contexts_.push(context_); context_ = c; } void TJSONProtocol::popContext() { context_ = contexts_.top(); contexts_.pop(); } // Write the character ch as a JSON escape sequence ("\u00xx") uint32_t TJSONProtocol::writeJSONEscapeChar(uint8_t ch) { trans_->write((const uint8_t*)kJSONEscapePrefix.c_str(), static_cast(kJSONEscapePrefix.length())); uint8_t outCh = hexChar(ch >> 4); trans_->write(&outCh, 1); outCh = hexChar(ch); trans_->write(&outCh, 1); return 6; } // Write the character ch as part of a JSON string, escaping as appropriate. uint32_t TJSONProtocol::writeJSONChar(uint8_t ch) { if (ch >= 0x30) { if (ch == kJSONBackslash) { // Only special character >= 0x30 is '\' trans_->write(&kJSONBackslash, 1); trans_->write(&kJSONBackslash, 1); return 2; } else { trans_->write(&ch, 1); return 1; } } else { uint8_t outCh = kJSONCharTable[ch]; // Check if regular character, backslash escaped, or JSON escaped if (outCh == 1) { trans_->write(&ch, 1); return 1; } else if (outCh > 1) { trans_->write(&kJSONBackslash, 1); trans_->write(&outCh, 1); return 2; } else { return writeJSONEscapeChar(ch); } } } // Write out the contents of the string str as a JSON string, escaping // characters as appropriate. uint32_t TJSONProtocol::writeJSONString(const std::string& str) { uint32_t result = context_->write(*trans_); result += 2; // For quotes trans_->write(&kJSONStringDelimiter, 1); std::string::const_iterator iter(str.begin()); std::string::const_iterator end(str.end()); while (iter != end) { result += writeJSONChar(*iter++); } trans_->write(&kJSONStringDelimiter, 1); return result; } // Write out the contents of the string as JSON string, base64-encoding // the string's contents, and escaping as appropriate uint32_t TJSONProtocol::writeJSONBase64(const std::string& str) { uint32_t result = context_->write(*trans_); result += 2; // For quotes trans_->write(&kJSONStringDelimiter, 1); uint8_t b[4]; const auto* bytes = (const uint8_t*)str.c_str(); if (str.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); auto len = static_cast(str.length()); while (len >= 3) { // Encode 3 bytes at a time base64_encode(bytes, 3, b); trans_->write(b, 4); result += 4; bytes += 3; len -= 3; } if (len) { // Handle remainder base64_encode(bytes, len, b); trans_->write(b, len + 1); result += len + 1; } trans_->write(&kJSONStringDelimiter, 1); return result; } // Convert the given integer type to a JSON number, or a string // if the context requires it (eg: key in a map pair). template uint32_t TJSONProtocol::writeJSONInteger(NumberType num) { uint32_t result = context_->write(*trans_); std::string val(to_string(num)); bool escapeNum = context_->escapeNum(); if (escapeNum) { trans_->write(&kJSONStringDelimiter, 1); result += 1; } if (val.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); trans_->write((const uint8_t*)val.c_str(), static_cast(val.length())); result += static_cast(val.length()); if (escapeNum) { trans_->write(&kJSONStringDelimiter, 1); result += 1; } return result; } namespace { std::string doubleToString(double d) { std::ostringstream str; str.imbue(std::locale::classic()); const std::streamsize max_digits10 = 2 + std::numeric_limits::digits10; str.precision(max_digits10); str << d; return str.str(); } } // Convert the given double to a JSON string, which is either the number, // "NaN" or "Infinity" or "-Infinity". uint32_t TJSONProtocol::writeJSONDouble(double num) { uint32_t result = context_->write(*trans_); std::string val; bool special = false; switch (std::fpclassify(num)) { case FP_INFINITE: if (std::signbit(num)) { val = kThriftNegativeInfinity; } else { val = kThriftInfinity; } special = true; break; case FP_NAN: val = kThriftNan; special = true; break; default: val = doubleToString(num); break; } bool escapeNum = special || context_->escapeNum(); if (escapeNum) { trans_->write(&kJSONStringDelimiter, 1); result += 1; } if (val.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); trans_->write((const uint8_t*)val.c_str(), static_cast(val.length())); result += static_cast(val.length()); if (escapeNum) { trans_->write(&kJSONStringDelimiter, 1); result += 1; } return result; } uint32_t TJSONProtocol::writeJSONObjectStart() { uint32_t result = context_->write(*trans_); trans_->write(&kJSONObjectStart, 1); pushContext(std::shared_ptr(new JSONPairContext())); return result + 1; } uint32_t TJSONProtocol::writeJSONObjectEnd() { popContext(); trans_->write(&kJSONObjectEnd, 1); return 1; } uint32_t TJSONProtocol::writeJSONArrayStart() { uint32_t result = context_->write(*trans_); trans_->write(&kJSONArrayStart, 1); pushContext(std::shared_ptr(new JSONListContext())); return result + 1; } uint32_t TJSONProtocol::writeJSONArrayEnd() { popContext(); trans_->write(&kJSONArrayEnd, 1); return 1; } uint32_t TJSONProtocol::writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid) { uint32_t result = writeJSONArrayStart(); result += writeJSONInteger(kThriftVersion1); result += writeJSONString(name); result += writeJSONInteger(messageType); result += writeJSONInteger(seqid); return result; } uint32_t TJSONProtocol::writeMessageEnd() { return writeJSONArrayEnd(); } uint32_t TJSONProtocol::writeStructBegin(const char* name) { (void)name; return writeJSONObjectStart(); } uint32_t TJSONProtocol::writeStructEnd() { return writeJSONObjectEnd(); } uint32_t TJSONProtocol::writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { (void)name; uint32_t result = writeJSONInteger(fieldId); result += writeJSONObjectStart(); result += writeJSONString(getTypeNameForTypeID(fieldType)); return result; } uint32_t TJSONProtocol::writeFieldEnd() { return writeJSONObjectEnd(); } uint32_t TJSONProtocol::writeFieldStop() { return 0; } uint32_t TJSONProtocol::writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { uint32_t result = writeJSONArrayStart(); result += writeJSONString(getTypeNameForTypeID(keyType)); result += writeJSONString(getTypeNameForTypeID(valType)); result += writeJSONInteger((int64_t)size); result += writeJSONObjectStart(); return result; } uint32_t TJSONProtocol::writeMapEnd() { uint32_t result = writeJSONObjectEnd(); result += writeJSONArrayEnd(); return result; } uint32_t TJSONProtocol::writeListBegin(const TType elemType, const uint32_t size) { uint32_t result = writeJSONArrayStart(); result += writeJSONString(getTypeNameForTypeID(elemType)); result += writeJSONInteger((int64_t)size); return result; } uint32_t TJSONProtocol::writeListEnd() { return writeJSONArrayEnd(); } uint32_t TJSONProtocol::writeSetBegin(const TType elemType, const uint32_t size) { uint32_t result = writeJSONArrayStart(); result += writeJSONString(getTypeNameForTypeID(elemType)); result += writeJSONInteger((int64_t)size); return result; } uint32_t TJSONProtocol::writeSetEnd() { return writeJSONArrayEnd(); } uint32_t TJSONProtocol::writeBool(const bool value) { return writeJSONInteger(value); } uint32_t TJSONProtocol::writeByte(const int8_t byte) { // writeByte() must be handled specially because to_string sees // int8_t as a text type instead of an integer type return writeJSONInteger((int16_t)byte); } uint32_t TJSONProtocol::writeI16(const int16_t i16) { return writeJSONInteger(i16); } uint32_t TJSONProtocol::writeI32(const int32_t i32) { return writeJSONInteger(i32); } uint32_t TJSONProtocol::writeI64(const int64_t i64) { return writeJSONInteger(i64); } uint32_t TJSONProtocol::writeDouble(const double dub) { return writeJSONDouble(dub); } uint32_t TJSONProtocol::writeString(const std::string& str) { return writeJSONString(str); } uint32_t TJSONProtocol::writeBinary(const std::string& str) { return writeJSONBase64(str); } /** * Reading functions */ // Reads 1 byte and verifies that it matches ch. uint32_t TJSONProtocol::readJSONSyntaxChar(uint8_t ch) { return readSyntaxChar(reader_, ch); } // Decodes the four hex parts of a JSON escaped string character and returns // the UTF-16 code unit via out. uint32_t TJSONProtocol::readJSONEscapeChar(uint16_t* out) { uint8_t b[4]; b[0] = reader_.read(); b[1] = reader_.read(); b[2] = reader_.read(); b[3] = reader_.read(); *out = (hexVal(b[0]) << 12) + (hexVal(b[1]) << 8) + (hexVal(b[2]) << 4) + hexVal(b[3]); return 4; } // Decodes a JSON string, including unescaping, and returns the string via str uint32_t TJSONProtocol::readJSONString(std::string& str, bool skipContext) { uint32_t result = (skipContext ? 0 : context_->read(reader_)); result += readJSONSyntaxChar(kJSONStringDelimiter); std::vector codeunits; uint8_t ch; str.clear(); while (true) { ch = reader_.read(); ++result; if (ch == kJSONStringDelimiter) { break; } if (ch == kJSONBackslash) { ch = reader_.read(); ++result; if (ch == kJSONEscapeChar) { uint16_t cp; result += readJSONEscapeChar(&cp); if (isHighSurrogate(cp)) { codeunits.push_back(cp); } else { if (isLowSurrogate(cp) && codeunits.empty()) { throw TProtocolException(TProtocolException::INVALID_DATA, "Missing UTF-16 high surrogate pair."); } codeunits.push_back(cp); codeunits.push_back(0); str += boost::locale::conv::utf_to_utf(codeunits.data()); codeunits.clear(); } continue; } else { size_t pos = kEscapeChars.find(ch); if (pos == kEscapeChars.npos) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected control char, got '" + std::string((const char*)&ch, 1) + "'."); } ch = kEscapeCharVals[pos]; } } if (!codeunits.empty()) { throw TProtocolException(TProtocolException::INVALID_DATA, "Missing UTF-16 low surrogate pair."); } str += ch; } if (!codeunits.empty()) { throw TProtocolException(TProtocolException::INVALID_DATA, "Missing UTF-16 low surrogate pair."); } return result; } // Reads a block of base64 characters, decoding it, and returns via str uint32_t TJSONProtocol::readJSONBase64(std::string& str) { std::string tmp; uint32_t result = readJSONString(tmp); auto* b = (uint8_t*)tmp.c_str(); if (tmp.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); auto len = static_cast(tmp.length()); str.clear(); // Ignore padding if (len >= 2) { uint32_t bound = len - 2; for (uint32_t i = len - 1; i >= bound && b[i] == '='; --i) { --len; } } while (len >= 4) { base64_decode(b, 4); str.append((const char*)b, 3); b += 4; len -= 4; } // Don't decode if we hit the end or got a single leftover byte (invalid // base64 but legal for skip of regular string type) if (len > 1) { base64_decode(b, len); str.append((const char*)b, len - 1); } return result; } // Reads a sequence of characters, stopping at the first one that is not // a valid JSON numeric character. uint32_t TJSONProtocol::readJSONNumericChars(std::string& str) { uint32_t result = 0; str.clear(); while (true) { uint8_t ch = reader_.peek(); if (!isJSONNumeric(ch)) { break; } reader_.read(); str += ch; ++result; } return result; } namespace { template T fromString(const std::string& s) { T t; std::istringstream str(s); str.imbue(std::locale::classic()); str >> t; if (str.bad() || !str.eof()) throw std::runtime_error(s); return t; } } // Reads a sequence of characters and assembles them into a number, // returning them via num template uint32_t TJSONProtocol::readJSONInteger(NumberType& num) { uint32_t result = context_->read(reader_); if (context_->escapeNum()) { result += readJSONSyntaxChar(kJSONStringDelimiter); } std::string str; result += readJSONNumericChars(str); try { num = fromString(str); } catch (const std::runtime_error&) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected numeric value; got \"" + str + "\""); } if (context_->escapeNum()) { result += readJSONSyntaxChar(kJSONStringDelimiter); } return result; } // Reads a JSON number or string and interprets it as a double. uint32_t TJSONProtocol::readJSONDouble(double& num) { uint32_t result = context_->read(reader_); std::string str; if (reader_.peek() == kJSONStringDelimiter) { result += readJSONString(str, true); // Check for NaN, Infinity and -Infinity if (str == kThriftNan) { num = HUGE_VAL / HUGE_VAL; // generates NaN } else if (str == kThriftInfinity) { num = HUGE_VAL; } else if (str == kThriftNegativeInfinity) { num = -HUGE_VAL; } else { if (!context_->escapeNum()) { // Throw exception -- we should not be in a string in this case throw TProtocolException(TProtocolException::INVALID_DATA, "Numeric data unexpectedly quoted"); } try { num = fromString(str); } catch (const std::runtime_error&) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected numeric value; got \"" + str + "\""); } } } else { if (context_->escapeNum()) { // This will throw - we should have had a quote if escapeNum == true readJSONSyntaxChar(kJSONStringDelimiter); } result += readJSONNumericChars(str); try { num = fromString(str); } catch (const std::runtime_error&) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected numeric value; got \"" + str + "\""); } } return result; } uint32_t TJSONProtocol::readJSONObjectStart() { uint32_t result = context_->read(reader_); result += readJSONSyntaxChar(kJSONObjectStart); pushContext(std::shared_ptr(new JSONPairContext())); return result; } uint32_t TJSONProtocol::readJSONObjectEnd() { uint32_t result = readJSONSyntaxChar(kJSONObjectEnd); popContext(); return result; } uint32_t TJSONProtocol::readJSONArrayStart() { uint32_t result = context_->read(reader_); result += readJSONSyntaxChar(kJSONArrayStart); pushContext(std::shared_ptr(new JSONListContext())); return result; } uint32_t TJSONProtocol::readJSONArrayEnd() { uint32_t result = readJSONSyntaxChar(kJSONArrayEnd); popContext(); return result; } uint32_t TJSONProtocol::readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t result = readJSONArrayStart(); int64_t tmpVal = 0; result += readJSONInteger(tmpVal); if (tmpVal != kThriftVersion1) { throw TProtocolException(TProtocolException::BAD_VERSION, "Message contained bad version."); } result += readJSONString(name); result += readJSONInteger(tmpVal); messageType = (TMessageType)tmpVal; result += readJSONInteger(tmpVal); if (tmpVal > (std::numeric_limits::max)() || tmpVal < (std::numeric_limits::min)()) throw TProtocolException(TProtocolException::INVALID_DATA, "sequence id is not int32_t"); seqid = static_cast(tmpVal); return result; } uint32_t TJSONProtocol::readMessageEnd() { return readJSONArrayEnd(); } uint32_t TJSONProtocol::readStructBegin(std::string& name) { (void)name; return readJSONObjectStart(); } uint32_t TJSONProtocol::readStructEnd() { return readJSONObjectEnd(); } uint32_t TJSONProtocol::readFieldBegin(std::string& name, TType& fieldType, int16_t& fieldId) { (void)name; uint32_t result = 0; // Check if we hit the end of the list uint8_t ch = reader_.peek(); if (ch == kJSONObjectEnd) { fieldType = apache::thrift::protocol::T_STOP; } else { uint64_t tmpVal = 0; std::string tmpStr; result += readJSONInteger(tmpVal); if (tmpVal > static_cast((std::numeric_limits::max)())) throw TProtocolException(TProtocolException::SIZE_LIMIT); fieldId = static_cast(tmpVal); result += readJSONObjectStart(); result += readJSONString(tmpStr); fieldType = getTypeIDForTypeName(tmpStr); } return result; } uint32_t TJSONProtocol::readFieldEnd() { return readJSONObjectEnd(); } uint32_t TJSONProtocol::readMapBegin(TType& keyType, TType& valType, uint32_t& size) { uint64_t tmpVal = 0; std::string tmpStr; uint32_t result = readJSONArrayStart(); result += readJSONString(tmpStr); keyType = getTypeIDForTypeName(tmpStr); result += readJSONString(tmpStr); valType = getTypeIDForTypeName(tmpStr); result += readJSONInteger(tmpVal); if (tmpVal > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); size = static_cast(tmpVal); result += readJSONObjectStart(); TMap map(keyType, valType, size); checkReadBytesAvailable(map); return result; } uint32_t TJSONProtocol::readMapEnd() { uint32_t result = readJSONObjectEnd(); result += readJSONArrayEnd(); return result; } uint32_t TJSONProtocol::readListBegin(TType& elemType, uint32_t& size) { uint64_t tmpVal = 0; std::string tmpStr; uint32_t result = readJSONArrayStart(); result += readJSONString(tmpStr); elemType = getTypeIDForTypeName(tmpStr); result += readJSONInteger(tmpVal); if (tmpVal > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); size = static_cast(tmpVal); TList list(elemType, size); checkReadBytesAvailable(list); return result; } uint32_t TJSONProtocol::readListEnd() { return readJSONArrayEnd(); } uint32_t TJSONProtocol::readSetBegin(TType& elemType, uint32_t& size) { uint64_t tmpVal = 0; std::string tmpStr; uint32_t result = readJSONArrayStart(); result += readJSONString(tmpStr); elemType = getTypeIDForTypeName(tmpStr); result += readJSONInteger(tmpVal); if (tmpVal > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); size = static_cast(tmpVal); TSet set(elemType, size); checkReadBytesAvailable(set); return result; } uint32_t TJSONProtocol::readSetEnd() { return readJSONArrayEnd(); } uint32_t TJSONProtocol::readBool(bool& value) { return readJSONInteger(value); } // readByte() must be handled properly because boost::lexical cast sees int8_t // as a text type instead of an integer type uint32_t TJSONProtocol::readByte(int8_t& byte) { auto tmp = (int16_t)byte; uint32_t result = readJSONInteger(tmp); assert(tmp < 256); byte = (int8_t)tmp; return result; } uint32_t TJSONProtocol::readI16(int16_t& i16) { return readJSONInteger(i16); } uint32_t TJSONProtocol::readI32(int32_t& i32) { return readJSONInteger(i32); } uint32_t TJSONProtocol::readI64(int64_t& i64) { return readJSONInteger(i64); } uint32_t TJSONProtocol::readDouble(double& dub) { return readJSONDouble(dub); } uint32_t TJSONProtocol::readString(std::string& str) { return readJSONString(str); } uint32_t TJSONProtocol::readBinary(std::string& str) { return readJSONBase64(str); } // Return the minimum number of bytes a type will consume on the wire int TJSONProtocol::getMinSerializedSize(TType type) { switch (type) { case T_STOP: return 0; case T_VOID: return 0; case T_BOOL: return 1; // written as int case T_BYTE: return 1; case T_DOUBLE: return 1; case T_I16: return 1; case T_I32: return 1; case T_I64: return 1; case T_STRING: return 2; // empty string case T_STRUCT: return 2; // empty struct case T_MAP: return 2; // empty map case T_SET: return 2; // empty set case T_LIST: return 2; // empty list default: throw TProtocolException(TProtocolException::UNKNOWN, "unrecognized type code"); } } } } } // apache::thrift::protocol thrift-0.19.0/lib/cpp/src/thrift/protocol/TMap.h0000644000000000000000000000246714303740367021411 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TMAP_H_ #define _THRIFT_TMAP_H_ #include namespace apache { namespace thrift { namespace protocol { /** * Helper class that encapsulates map metadata. * */ class TMap { public: TMap() : keyType_(T_STOP), valueType_(T_STOP), size_(0) { } TMap(TType k, TType v, int s) : keyType_(k), valueType_(v), size_(s) { } TType keyType_; TType valueType_; int size_; }; } } } // apache::thrift::protocol #endif // #ifndef _THRIFT_TMAP_H_ thrift-0.19.0/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp0000644000000000000000000002347114303740367023775 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include using std::string; static string byte_to_hex(const uint8_t byte) { char buf[3]; int ret = std::sprintf(buf, "%02x", (int)byte); THRIFT_UNUSED_VARIABLE(ret); assert(ret == 2); assert(buf[2] == '\0'); return buf; } namespace apache { namespace thrift { namespace protocol { string TDebugProtocol::fieldTypeName(TType type) { switch (type) { case T_STOP: return "stop"; case T_VOID: return "void"; case T_BOOL: return "bool"; case T_BYTE: return "byte"; case T_I16: return "i16"; case T_I32: return "i32"; case T_U64: return "u64"; case T_I64: return "i64"; case T_DOUBLE: return "double"; case T_STRING: return "string"; case T_STRUCT: return "struct"; case T_MAP: return "map"; case T_SET: return "set"; case T_LIST: return "list"; case T_UTF8: return "utf8"; case T_UTF16: return "utf16"; default: return "unknown"; } } void TDebugProtocol::indentUp() { indent_str_ += string(indent_inc, ' '); } void TDebugProtocol::indentDown() { if (indent_str_.length() < (string::size_type)indent_inc) { throw TProtocolException(TProtocolException::INVALID_DATA); } indent_str_.erase(indent_str_.length() - indent_inc); } uint32_t TDebugProtocol::writePlain(const string& str) { if (str.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); trans_->write((uint8_t*)str.data(), static_cast(str.length())); return static_cast(str.length()); } uint32_t TDebugProtocol::writeIndented(const string& str) { if (str.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); if (indent_str_.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); uint64_t total_len = indent_str_.length() + str.length(); if (total_len > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); trans_->write((uint8_t*)indent_str_.data(), static_cast(indent_str_.length())); trans_->write((uint8_t*)str.data(), static_cast(str.length())); return static_cast(indent_str_.length() + str.length()); } uint32_t TDebugProtocol::startItem() { uint32_t size; switch (write_state_.back()) { case UNINIT: // XXX figure out what to do here. // throw TProtocolException(TProtocolException::INVALID_DATA); // return writeIndented(str); return 0; case STRUCT: return 0; case SET: return writeIndented(""); case MAP_KEY: return writeIndented(""); case MAP_VALUE: return writePlain(" -> "); case LIST: size = writeIndented("[" + to_string(list_idx_.back()) + "] = "); list_idx_.back()++; return size; default: throw std::logic_error("Invalid enum value."); } } uint32_t TDebugProtocol::endItem() { // uint32_t size; switch (write_state_.back()) { case UNINIT: // XXX figure out what to do here. // throw TProtocolException(TProtocolException::INVALID_DATA); // return writeIndented(str); return 0; case STRUCT: return writePlain(",\n"); case SET: return writePlain(",\n"); case MAP_KEY: write_state_.back() = MAP_VALUE; return 0; case MAP_VALUE: write_state_.back() = MAP_KEY; return writePlain(",\n"); case LIST: return writePlain(",\n"); default: throw std::logic_error("Invalid enum value."); } } uint32_t TDebugProtocol::writeItem(const std::string& str) { uint32_t size = 0; size += startItem(); size += writePlain(str); size += endItem(); return size; } uint32_t TDebugProtocol::writeMessageBegin(const std::string& name, const TMessageType messageType, const int32_t seqid) { (void)seqid; string mtype; switch (messageType) { case T_CALL: mtype = "call"; break; case T_REPLY: mtype = "reply"; break; case T_EXCEPTION: mtype = "exn"; break; case T_ONEWAY: mtype = "oneway"; break; } uint32_t size = writeIndented("(" + mtype + ") " + name + "("); indentUp(); return size; } uint32_t TDebugProtocol::writeMessageEnd() { indentDown(); return writeIndented(")\n"); } uint32_t TDebugProtocol::writeStructBegin(const char* name) { uint32_t size = 0; size += startItem(); size += writePlain(string(name) + " {\n"); indentUp(); write_state_.push_back(STRUCT); return size; } uint32_t TDebugProtocol::writeStructEnd() { indentDown(); write_state_.pop_back(); uint32_t size = 0; size += writeIndented("}"); size += endItem(); return size; } uint32_t TDebugProtocol::writeFieldBegin(const char* name, const TType fieldType, const int16_t fieldId) { // sprintf(id_str, "%02d", fieldId); string id_str = to_string(fieldId); if (id_str.length() == 1) id_str = '0' + id_str; return writeIndented(id_str + ": " + name + " (" + fieldTypeName(fieldType) + ") = "); } uint32_t TDebugProtocol::writeFieldEnd() { assert(write_state_.back() == STRUCT); return 0; } uint32_t TDebugProtocol::writeFieldStop() { return 0; // writeIndented("***STOP***\n"); } uint32_t TDebugProtocol::writeMapBegin(const TType keyType, const TType valType, const uint32_t size) { // TODO(dreiss): Optimize short maps? uint32_t bsize = 0; bsize += startItem(); bsize += writePlain( "map<" + fieldTypeName(keyType) + "," + fieldTypeName(valType) + ">" "[" + to_string(size) + "] {\n"); indentUp(); write_state_.push_back(MAP_KEY); return bsize; } uint32_t TDebugProtocol::writeMapEnd() { indentDown(); write_state_.pop_back(); uint32_t size = 0; size += writeIndented("}"); size += endItem(); return size; } uint32_t TDebugProtocol::writeListBegin(const TType elemType, const uint32_t size) { // TODO(dreiss): Optimize short arrays. uint32_t bsize = 0; bsize += startItem(); bsize += writePlain( "list<" + fieldTypeName(elemType) + ">" "[" + to_string(size) + "] {\n"); indentUp(); write_state_.push_back(LIST); list_idx_.push_back(0); return bsize; } uint32_t TDebugProtocol::writeListEnd() { indentDown(); write_state_.pop_back(); list_idx_.pop_back(); uint32_t size = 0; size += writeIndented("}"); size += endItem(); return size; } uint32_t TDebugProtocol::writeSetBegin(const TType elemType, const uint32_t size) { // TODO(dreiss): Optimize short sets. uint32_t bsize = 0; bsize += startItem(); bsize += writePlain( "set<" + fieldTypeName(elemType) + ">" "[" + to_string(size) + "] {\n"); indentUp(); write_state_.push_back(SET); return bsize; } uint32_t TDebugProtocol::writeSetEnd() { indentDown(); write_state_.pop_back(); uint32_t size = 0; size += writeIndented("}"); size += endItem(); return size; } uint32_t TDebugProtocol::writeBool(const bool value) { return writeItem(value ? "true" : "false"); } uint32_t TDebugProtocol::writeByte(const int8_t byte) { return writeItem("0x" + byte_to_hex(byte)); } uint32_t TDebugProtocol::writeI16(const int16_t i16) { return writeItem(to_string(i16)); } uint32_t TDebugProtocol::writeI32(const int32_t i32) { return writeItem(to_string(i32)); } uint32_t TDebugProtocol::writeI64(const int64_t i64) { return writeItem(to_string(i64)); } uint32_t TDebugProtocol::writeDouble(const double dub) { return writeItem(to_string(dub)); } uint32_t TDebugProtocol::writeString(const string& str) { // XXX Raw/UTF-8? string to_show = str; if (to_show.length() > (string::size_type)string_limit_) { to_show = str.substr(0, string_prefix_size_); to_show += "[...](" + to_string(str.length()) + ")"; } string output = "\""; for (string::const_iterator it = to_show.begin(); it != to_show.end(); ++it) { if (*it == '\\') { output += "\\\\"; } else if (*it == '"') { output += "\\\""; // passing characters <0 to std::isprint causes asserts. isprint takes an // int, so we need to be careful of sign extension } else if (std::isprint((unsigned char)*it)) { output += *it; } else { switch (*it) { case '\a': output += "\\a"; break; case '\b': output += "\\b"; break; case '\f': output += "\\f"; break; case '\n': output += "\\n"; break; case '\r': output += "\\r"; break; case '\t': output += "\\t"; break; case '\v': output += "\\v"; break; default: output += "\\x"; output += byte_to_hex(*it); } } } output += '\"'; return writeItem(output); } uint32_t TDebugProtocol::writeBinary(const string& str) { // XXX Hex? return TDebugProtocol::writeString(str); } } } } // apache::thrift::protocol thrift-0.19.0/lib/cpp/src/thrift/protocol/TProtocolTypes.h0000644000000000000000000000216514303740367023515 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ #define THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1 namespace apache { namespace thrift { namespace protocol { enum PROTOCOL_TYPES { T_BINARY_PROTOCOL = 0, T_JSON_PROTOCOL = 1, T_COMPACT_PROTOCOL = 2, }; } } } // apache::thrift::protocol #endif // #define _THRIFT_PROTOCOL_TPROTOCOLTYPES_H_ 1 thrift-0.19.0/lib/cpp/src/thrift/TApplicationException.h0000644000000000000000000000673114303740367023153 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_ #define _THRIFT_TAPPLICATIONEXCEPTION_H_ 1 #include namespace apache { namespace thrift { namespace protocol { class TProtocol; } class TApplicationException : public TException { public: /** * Error codes for the various types of exceptions. */ enum TApplicationExceptionType { UNKNOWN = 0, UNKNOWN_METHOD = 1, INVALID_MESSAGE_TYPE = 2, WRONG_METHOD_NAME = 3, BAD_SEQUENCE_ID = 4, MISSING_RESULT = 5, INTERNAL_ERROR = 6, PROTOCOL_ERROR = 7, INVALID_TRANSFORM = 8, INVALID_PROTOCOL = 9, UNSUPPORTED_CLIENT_TYPE = 10 }; TApplicationException() : TException(), type_(UNKNOWN) {} TApplicationException(TApplicationExceptionType type) : TException(), type_(type) {} TApplicationException(const std::string& message) : TException(message), type_(UNKNOWN) {} TApplicationException(TApplicationExceptionType type, const std::string& message) : TException(message), type_(type) {} ~TApplicationException() noexcept override = default; /** * Returns an error code that provides information about the type of error * that has occurred. * * @return Error code */ TApplicationExceptionType getType() const { return type_; } const char* what() const noexcept override { if (message_.empty()) { switch (type_) { case UNKNOWN: return "TApplicationException: Unknown application exception"; case UNKNOWN_METHOD: return "TApplicationException: Unknown method"; case INVALID_MESSAGE_TYPE: return "TApplicationException: Invalid message type"; case WRONG_METHOD_NAME: return "TApplicationException: Wrong method name"; case BAD_SEQUENCE_ID: return "TApplicationException: Bad sequence identifier"; case MISSING_RESULT: return "TApplicationException: Missing result"; case INTERNAL_ERROR: return "TApplicationException: Internal error"; case PROTOCOL_ERROR: return "TApplicationException: Protocol error"; case INVALID_TRANSFORM: return "TApplicationException: Invalid transform"; case INVALID_PROTOCOL: return "TApplicationException: Invalid protocol"; case UNSUPPORTED_CLIENT_TYPE: return "TApplicationException: Unsupported client type"; default: return "TApplicationException: (Invalid exception type)"; }; } else { return message_.c_str(); } } uint32_t read(protocol::TProtocol* iprot); uint32_t write(protocol::TProtocol* oprot) const; protected: /** * Error code */ TApplicationExceptionType type_; }; } } // apache::thrift #endif // #ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_ thrift-0.19.0/lib/cpp/src/thrift/TConfiguration.h0000644000000000000000000000417414303740367021637 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_TCONFIGURATION_H #define THRIFT_TCONFIGURATION_H namespace apache { namespace thrift { class TConfiguration { public: TConfiguration(int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE, int maxFrameSize = DEFAULT_MAX_FRAME_SIZE, int recursionLimit = DEFAULT_RECURSION_DEPTH) : maxMessageSize_(maxMessageSize), maxFrameSize_(maxFrameSize), recursionLimit_(recursionLimit) {} const static int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; const static int DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries const static int DEFAULT_RECURSION_DEPTH = 64; inline int getMaxMessageSize() { return maxMessageSize_; } inline void setMaxMessageSize(int maxMessageSize) { maxMessageSize_ = maxMessageSize; } inline int getMaxFrameSize() { return maxFrameSize_; } inline void setMaxFrameSize(int maxFrameSize) { maxFrameSize_ = maxFrameSize; } inline int getRecursionLimit() { return recursionLimit_; } inline void setRecursionLimit(int recursionLimit) { recursionLimit_ = recursionLimit; } private: int maxMessageSize_ = DEFAULT_MAX_MESSAGE_SIZE; int maxFrameSize_ = DEFAULT_MAX_FRAME_SIZE; int recursionLimit_ = DEFAULT_RECURSION_DEPTH; // TODO(someone_smart): add connection and i/o timeouts }; } } // apache::thrift #endif /* THRIFT_TCONFIGURATION_H */ thrift-0.19.0/lib/cpp/src/thrift/thrift-config.h0000644000000000000000000000157014303740367021444 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifdef _WIN32 #include #endif #include thrift-0.19.0/lib/cpp/src/thrift/concurrency/0000755000000000000000000000000014472652650021063 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/concurrency/FunctionRunner.h0000644000000000000000000000733214370300523024202 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H #define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1 #include #include #include namespace apache { namespace thrift { namespace concurrency { /** * Convenient implementation of Runnable that will execute arbitrary callbacks. * Interfaces are provided to accept both a generic 'void(void)' callback, and * a 'void* (void*)' pthread_create-style callback. * * Example use: * void* my_thread_main(void* arg); * shared_ptr factory = ...; * // To create a thread that executes my_thread_main once: * shared_ptr thread = factory->newThread( * FunctionRunner::create(my_thread_main, some_argument)); * thread->start(); * * bool A::foo(); * A* a = new A(); * // To create a thread that executes a.foo() every 100 milliseconds: * factory->newThread(FunctionRunner::create( * std::bind(&A::foo, a), 100))->start(); * */ class FunctionRunner : public Runnable { public: // This is the type of callback 'pthread_create()' expects. typedef void* (*PthreadFuncPtr)(void* arg); // This a fully-generic void(void) callback for custom bindings. typedef std::function VoidFunc; typedef std::function BoolFunc; /** * Syntactic sugar to make it easier to create new FunctionRunner * objects wrapped in shared_ptr. */ static std::shared_ptr create(const VoidFunc& cob) { return std::shared_ptr(new FunctionRunner(cob)); } static std::shared_ptr create(PthreadFuncPtr func, void* arg) { return std::shared_ptr(new FunctionRunner(func, arg)); } private: static void pthread_func_wrapper(PthreadFuncPtr func, void* arg) { // discard return value func(arg); } public: /** * Given a 'pthread_create' style callback, this FunctionRunner will * execute the given callback. Note that the 'void*' return value is ignored. */ FunctionRunner(PthreadFuncPtr func, void* arg) : func_(std::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {} /** * Given a generic callback, this FunctionRunner will execute it. */ FunctionRunner(const VoidFunc& cob) : func_(cob), intervalMs_(-1) {} /** * Given a bool foo(...) type callback, FunctionRunner will execute * the callback repeatedly with 'intervalMs' milliseconds between the calls, * until it returns false. Note that the actual interval between calls will * be intervalMs plus execution time of the callback. */ FunctionRunner(const BoolFunc& cob, int intervalMs) : repFunc_(cob), intervalMs_(intervalMs) {} void run() override { if (repFunc_) { while (repFunc_()) { THRIFT_SLEEP_USEC(intervalMs_ * 1000); } } else { func_(); } } private: VoidFunc func_; BoolFunc repFunc_; int intervalMs_; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H thrift-0.19.0/lib/cpp/src/thrift/concurrency/ThreadManager.cpp0000644000000000000000000004004314303740367024266 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace concurrency { using std::shared_ptr; using std::unique_ptr; using std::dynamic_pointer_cast; /** * ThreadManager class * * This class manages a pool of threads. It uses a ThreadFactory to create * threads. It never actually creates or destroys worker threads, rather * it maintains statistics on number of idle threads, number of active threads, * task backlog, and average wait and service times. * * There are three different monitors used for signaling different conditions * however they all share the same mutex_. * * @version $Id:$ */ class ThreadManager::Impl : public ThreadManager { public: Impl() : workerCount_(0), workerMaxCount_(0), idleCount_(0), pendingTaskCountMax_(0), expiredCount_(0), state_(ThreadManager::UNINITIALIZED), monitor_(&mutex_), maxMonitor_(&mutex_), workerMonitor_(&mutex_) {} ~Impl() override { stop(); } void start() override; void stop() override; ThreadManager::STATE state() const override { return state_; } shared_ptr threadFactory() const override { Guard g(mutex_); return threadFactory_; } void threadFactory(shared_ptr value) override { Guard g(mutex_); if (threadFactory_ && threadFactory_->isDetached() != value->isDetached()) { throw InvalidArgumentException(); } threadFactory_ = value; } void addWorker(size_t value) override; void removeWorker(size_t value) override; size_t idleWorkerCount() const override { return idleCount_; } size_t workerCount() const override { Guard g(mutex_); return workerCount_; } size_t pendingTaskCount() const override { Guard g(mutex_); return tasks_.size(); } size_t totalTaskCount() const override { Guard g(mutex_); return tasks_.size() + workerCount_ - idleCount_; } size_t pendingTaskCountMax() const override { Guard g(mutex_); return pendingTaskCountMax_; } size_t expiredTaskCount() const override { Guard g(mutex_); return expiredCount_; } void pendingTaskCountMax(const size_t value) { Guard g(mutex_); pendingTaskCountMax_ = value; } void add(shared_ptr value, int64_t timeout, int64_t expiration) override; void remove(shared_ptr task) override; shared_ptr removeNextPending() override; void removeExpiredTasks() override { removeExpired(false); } void setExpireCallback(ExpireCallback expireCallback) override; private: /** * Remove one or more expired tasks. * \param[in] justOne if true, try to remove just one task and return */ void removeExpired(bool justOne); /** * \returns whether it is acceptable to block, depending on the current thread id */ bool canSleep() const; /** * Lowers the maximum worker count and blocks until enough worker threads complete * to get to the new maximum worker limit. The caller is responsible for acquiring * a lock on the class mutex_. */ void removeWorkersUnderLock(size_t value); size_t workerCount_; size_t workerMaxCount_; size_t idleCount_; size_t pendingTaskCountMax_; size_t expiredCount_; ExpireCallback expireCallback_; ThreadManager::STATE state_; shared_ptr threadFactory_; friend class ThreadManager::Task; typedef std::deque > TaskQueue; TaskQueue tasks_; Mutex mutex_; Monitor monitor_; Monitor maxMonitor_; Monitor workerMonitor_; // used to synchronize changes in worker count friend class ThreadManager::Worker; std::set > workers_; std::set > deadWorkers_; std::map > idMap_; }; class ThreadManager::Task : public Runnable { public: enum STATE { WAITING, EXECUTING, TIMEDOUT, COMPLETE }; Task(shared_ptr runnable, uint64_t expiration = 0ULL) : runnable_(runnable), state_(WAITING) { if (expiration != 0ULL) { expireTime_.reset(new std::chrono::steady_clock::time_point(std::chrono::steady_clock::now() + std::chrono::milliseconds(expiration))); } } ~Task() override = default; void run() override { if (state_ == EXECUTING) { runnable_->run(); state_ = COMPLETE; } } shared_ptr getRunnable() { return runnable_; } const unique_ptr & getExpireTime() const { return expireTime_; } private: shared_ptr runnable_; friend class ThreadManager::Worker; STATE state_; unique_ptr expireTime_; }; class ThreadManager::Worker : public Runnable { enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED }; public: Worker(ThreadManager::Impl* manager) : manager_(manager), state_(UNINITIALIZED) {} ~Worker() override = default; private: bool isActive() const { return (manager_->workerCount_ <= manager_->workerMaxCount_) || (manager_->state_ == JOINING && !manager_->tasks_.empty()); } public: /** * Worker entry point * * As long as worker thread is running, pull tasks off the task queue and * execute. */ void run() override { Guard g(manager_->mutex_); /** * This method has three parts; one is to check for and account for * admitting a task which happens under a lock. Then the lock is released * and the task itself is executed. Finally we do some accounting * under lock again when the task completes. */ /** * Admitting */ /** * Increment worker semaphore and notify manager if worker count reached * desired max */ bool active = manager_->workerCount_ < manager_->workerMaxCount_; if (active) { if (++manager_->workerCount_ == manager_->workerMaxCount_) { manager_->workerMonitor_.notify(); } } while (active) { /** * While holding manager monitor block for non-empty task queue (Also * check that the thread hasn't been requested to stop). Once the queue * is non-empty, dequeue a task, release monitor, and execute. If the * worker max count has been decremented such that we exceed it, mark * ourself inactive, decrement the worker count and notify the manager * (technically we're notifying the next blocked thread but eventually * the manager will see it. */ active = isActive(); while (active && manager_->tasks_.empty()) { manager_->idleCount_++; manager_->monitor_.wait(); active = isActive(); manager_->idleCount_--; } shared_ptr task; if (active) { if (!manager_->tasks_.empty()) { task = manager_->tasks_.front(); manager_->tasks_.pop_front(); if (task->state_ == ThreadManager::Task::WAITING) { // If the state is changed to anything other than EXECUTING or TIMEDOUT here // then the execution loop needs to be changed below. task->state_ = (task->getExpireTime() && *(task->getExpireTime()) < std::chrono::steady_clock::now()) ? ThreadManager::Task::TIMEDOUT : ThreadManager::Task::EXECUTING; } } /* If we have a pending task max and we just dropped below it, wakeup any thread that might be blocked on add. */ if (manager_->pendingTaskCountMax_ != 0 && manager_->tasks_.size() <= manager_->pendingTaskCountMax_ - 1) { manager_->maxMonitor_.notify(); } } /** * Execution - not holding a lock */ if (task) { if (task->state_ == ThreadManager::Task::EXECUTING) { // Release the lock so we can run the task without blocking the thread manager manager_->mutex_.unlock(); try { task->run(); } catch (const std::exception& e) { GlobalOutput.printf("[ERROR] task->run() raised an exception: %s", e.what()); } catch (...) { GlobalOutput.printf("[ERROR] task->run() raised an unknown exception"); } // Re-acquire the lock to proceed in the thread manager manager_->mutex_.lock(); } else if (manager_->expireCallback_) { // The only other state the task could have been in is TIMEDOUT (see above) manager_->mutex_.unlock(); manager_->expireCallback_(task->getRunnable()); manager_->mutex_.lock(); manager_->expiredCount_++; } } } /** * Final accounting for the worker thread that is done working */ manager_->deadWorkers_.insert(this->thread()); if (--manager_->workerCount_ == manager_->workerMaxCount_) { manager_->workerMonitor_.notify(); } } private: ThreadManager::Impl* manager_; friend class ThreadManager::Impl; STATE state_; }; void ThreadManager::Impl::addWorker(size_t value) { std::set > newThreads; for (size_t ix = 0; ix < value; ix++) { shared_ptr worker = std::make_shared(this); newThreads.insert(threadFactory_->newThread(worker)); } Guard g(mutex_); workerMaxCount_ += value; workers_.insert(newThreads.begin(), newThreads.end()); for (const auto & newThread : newThreads) { shared_ptr worker = dynamic_pointer_cast(newThread->runnable()); worker->state_ = ThreadManager::Worker::STARTING; newThread->start(); idMap_.insert(std::pair >(newThread->getId(), newThread)); } while (workerCount_ != workerMaxCount_) { workerMonitor_.wait(); } } void ThreadManager::Impl::start() { Guard g(mutex_); if (state_ == ThreadManager::STOPPED) { return; } if (state_ == ThreadManager::UNINITIALIZED) { if (!threadFactory_) { throw InvalidArgumentException(); } state_ = ThreadManager::STARTED; monitor_.notifyAll(); } while (state_ == STARTING) { monitor_.wait(); } } void ThreadManager::Impl::stop() { Guard g(mutex_); bool doStop = false; if (state_ != ThreadManager::STOPPING && state_ != ThreadManager::JOINING && state_ != ThreadManager::STOPPED) { doStop = true; state_ = ThreadManager::JOINING; } if (doStop) { removeWorkersUnderLock(workerCount_); } state_ = ThreadManager::STOPPED; } void ThreadManager::Impl::removeWorker(size_t value) { Guard g(mutex_); removeWorkersUnderLock(value); } void ThreadManager::Impl::removeWorkersUnderLock(size_t value) { if (value > workerMaxCount_) { throw InvalidArgumentException(); } workerMaxCount_ -= value; if (idleCount_ > value) { // There are more idle workers than we need to remove, // so notify enough of them so they can terminate. for (size_t ix = 0; ix < value; ix++) { monitor_.notify(); } } else { // There are as many or less idle workers than we need to remove, // so just notify them all so they can terminate. monitor_.notifyAll(); } while (workerCount_ != workerMaxCount_) { workerMonitor_.wait(); } for (const auto & deadWorker : deadWorkers_) { // when used with a joinable thread factory, we join the threads as we remove them if (!threadFactory_->isDetached()) { deadWorker->join(); } idMap_.erase(deadWorker->getId()); workers_.erase(deadWorker); } deadWorkers_.clear(); } bool ThreadManager::Impl::canSleep() const { const Thread::id_t id = threadFactory_->getCurrentThreadId(); return idMap_.find(id) == idMap_.end(); } void ThreadManager::Impl::add(shared_ptr value, int64_t timeout, int64_t expiration) { Guard g(mutex_, timeout); if (!g) { throw TimedOutException(); } if (state_ != ThreadManager::STARTED) { throw IllegalStateException( "ThreadManager::Impl::add ThreadManager " "not started"); } // if we're at a limit, remove an expired task to see if the limit clears if (pendingTaskCountMax_ > 0 && (tasks_.size() >= pendingTaskCountMax_)) { removeExpired(true); } if (pendingTaskCountMax_ > 0 && (tasks_.size() >= pendingTaskCountMax_)) { if (canSleep() && timeout >= 0) { while (pendingTaskCountMax_ > 0 && tasks_.size() >= pendingTaskCountMax_) { // This is thread safe because the mutex is shared between monitors. maxMonitor_.wait(timeout); } } else { throw TooManyPendingTasksException(); } } tasks_.push_back(std::make_shared(value, expiration)); // If idle thread is available notify it, otherwise all worker threads are // running and will get around to this task in time. if (idleCount_ > 0) { monitor_.notify(); } } void ThreadManager::Impl::remove(shared_ptr task) { Guard g(mutex_); if (state_ != ThreadManager::STARTED) { throw IllegalStateException( "ThreadManager::Impl::remove ThreadManager not " "started"); } for (auto it = tasks_.begin(); it != tasks_.end(); ++it) { if ((*it)->getRunnable() == task) { tasks_.erase(it); return; } } } std::shared_ptr ThreadManager::Impl::removeNextPending() { Guard g(mutex_); if (state_ != ThreadManager::STARTED) { throw IllegalStateException( "ThreadManager::Impl::removeNextPending " "ThreadManager not started"); } if (tasks_.empty()) { return std::shared_ptr(); } shared_ptr task = tasks_.front(); tasks_.pop_front(); return task->getRunnable(); } void ThreadManager::Impl::removeExpired(bool justOne) { // this is always called under a lock if (tasks_.empty()) { return; } auto now = std::chrono::steady_clock::now(); for (auto it = tasks_.begin(); it != tasks_.end(); ) { if ((*it)->getExpireTime() && *((*it)->getExpireTime()) < now) { if (expireCallback_) { expireCallback_((*it)->getRunnable()); } it = tasks_.erase(it); ++expiredCount_; if (justOne) { return; } } else { ++it; } } } void ThreadManager::Impl::setExpireCallback(ExpireCallback expireCallback) { Guard g(mutex_); expireCallback_ = expireCallback; } class SimpleThreadManager : public ThreadManager::Impl { public: SimpleThreadManager(size_t workerCount = 4, size_t pendingTaskCountMax = 0) : workerCount_(workerCount), pendingTaskCountMax_(pendingTaskCountMax) {} void start() override { ThreadManager::Impl::pendingTaskCountMax(pendingTaskCountMax_); ThreadManager::Impl::start(); addWorker(workerCount_); } private: const size_t workerCount_; const size_t pendingTaskCountMax_; }; shared_ptr ThreadManager::newThreadManager() { return shared_ptr(new ThreadManager::Impl()); } shared_ptr ThreadManager::newSimpleThreadManager(size_t count, size_t pendingTaskCountMax) { return shared_ptr(new SimpleThreadManager(count, pendingTaskCountMax)); } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/src/thrift/concurrency/Thread.cpp0000644000000000000000000000222614303740367022774 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include namespace apache { namespace thrift { namespace concurrency { void Thread::threadMain(std::shared_ptr thread) { thread->setState(started); thread->runnable()->run(); if (thread->getState() != stopping && thread->getState() != stopped) { thread->setState(stopping); } } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/src/thrift/concurrency/TimerManager.h0000644000000000000000000001053714303740367023611 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ #define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1 #include #include #include #include namespace apache { namespace thrift { namespace concurrency { /** * Timer Manager * * This class dispatches timer tasks when they fall due. * * @version $Id:$ */ class TimerManager { public: class Task; typedef std::weak_ptr Timer; TimerManager(); virtual ~TimerManager(); virtual std::shared_ptr threadFactory() const; virtual void threadFactory(std::shared_ptr value); /** * Starts the timer manager service * * @throws IllegalArgumentException Missing thread factory attribute */ virtual void start(); /** * Stops the timer manager service */ virtual void stop(); virtual size_t taskCount() const; /** * Adds a task to be executed at some time in the future by a worker thread. * * @param task The task to execute * @param timeout Time in milliseconds to delay before executing task * @return Handle of the timer, which can be used to remove the timer. */ virtual Timer add(std::shared_ptr task, const std::chrono::milliseconds &timeout); Timer add(std::shared_ptr task, uint64_t timeout) { return add(task,std::chrono::milliseconds(timeout)); } /** * Adds a task to be executed at some time in the future by a worker thread. * * @param task The task to execute * @param abstime Absolute time in the future to execute task. * @return Handle of the timer, which can be used to remove the timer. */ virtual Timer add(std::shared_ptr task, const std::chrono::time_point& abstime); /** * Removes a pending task * * @param task The task to remove. All timers which execute this task will * be removed. * @throws NoSuchTaskException Specified task doesn't exist. It was either * processed already or this call was made for a * task that was never added to this timer * * @throws UncancellableTaskException Specified task is already being * executed or has completed execution. */ virtual void remove(std::shared_ptr task); /** * Removes a single pending task * * @param timer The timer to remove. The timer is returned when calling the * add() method. * @throws NoSuchTaskException Specified task doesn't exist. It was either * processed already or this call was made for a * task that was never added to this timer * * @throws UncancellableTaskException Specified task is already being * executed or has completed execution. */ virtual void remove(Timer timer); enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED }; virtual STATE state() const; private: std::shared_ptr threadFactory_; friend class Task; std::multimap, std::shared_ptr > taskMap_; size_t taskCount_; Monitor monitor_; STATE state_; class Dispatcher; friend class Dispatcher; std::shared_ptr dispatcher_; std::shared_ptr dispatcherThread_; using task_iterator = decltype(taskMap_)::iterator; typedef std::pair task_range; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ thrift-0.19.0/lib/cpp/src/thrift/concurrency/TimerManager.cpp0000644000000000000000000002040014303740367024132 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include namespace apache { namespace thrift { namespace concurrency { using std::shared_ptr; using std::weak_ptr; /** * TimerManager class * * @version $Id:$ */ class TimerManager::Task : public Runnable { public: enum STATE { WAITING, EXECUTING, CANCELLED, COMPLETE }; Task(shared_ptr runnable) : runnable_(runnable), state_(WAITING) {} ~Task() override = default; void run() override { if (state_ == EXECUTING) { runnable_->run(); state_ = COMPLETE; } } bool operator==(const shared_ptr & runnable) const { return runnable_ == runnable; } task_iterator it_; private: shared_ptr runnable_; friend class TimerManager::Dispatcher; STATE state_; }; class TimerManager::Dispatcher : public Runnable { public: Dispatcher(TimerManager* manager) : manager_(manager) {} ~Dispatcher() override = default; /** * Dispatcher entry point * * As long as dispatcher thread is running, pull tasks off the task taskMap_ * and execute. */ void run() override { { Synchronized s(manager_->monitor_); if (manager_->state_ == TimerManager::STARTING) { manager_->state_ = TimerManager::STARTED; manager_->monitor_.notifyAll(); } } do { std::set > expiredTasks; { Synchronized s(manager_->monitor_); task_iterator expiredTaskEnd; auto now = std::chrono::steady_clock::now(); while (manager_->state_ == TimerManager::STARTED && (expiredTaskEnd = manager_->taskMap_.upper_bound(now)) == manager_->taskMap_.begin()) { std::chrono::milliseconds timeout(0); if (!manager_->taskMap_.empty()) { timeout = std::chrono::duration_cast(manager_->taskMap_.begin()->first - now); //because the unit of steady_clock is smaller than millisecond,timeout may be 0. if (timeout.count() == 0) { timeout = std::chrono::milliseconds(1); } manager_->monitor_.waitForTimeRelative(timeout); } else { manager_->monitor_.waitForTimeRelative(0); } now = std::chrono::steady_clock::now(); } if (manager_->state_ == TimerManager::STARTED) { for (auto ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) { shared_ptr task = ix->second; expiredTasks.insert(task); task->it_ = manager_->taskMap_.end(); if (task->state_ == TimerManager::Task::WAITING) { task->state_ = TimerManager::Task::EXECUTING; } manager_->taskCount_--; } manager_->taskMap_.erase(manager_->taskMap_.begin(), expiredTaskEnd); } } for (const auto & expiredTask : expiredTasks) { expiredTask->run(); } } while (manager_->state_ == TimerManager::STARTED); { Synchronized s(manager_->monitor_); if (manager_->state_ == TimerManager::STOPPING) { manager_->state_ = TimerManager::STOPPED; manager_->monitor_.notifyAll(); } } return; } private: TimerManager* manager_; friend class TimerManager; }; #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4355) // 'this' used in base member initializer list #endif TimerManager::TimerManager() : taskCount_(0), state_(TimerManager::UNINITIALIZED), dispatcher_(std::make_shared(this)) { } #if defined(_MSC_VER) #pragma warning(pop) #endif TimerManager::~TimerManager() { // If we haven't been explicitly stopped, do so now. We don't need to grab // the monitor here, since stop already takes care of reentrancy. if (state_ != STOPPED) { try { stop(); } catch (...) { // We're really hosed. } } } void TimerManager::start() { bool doStart = false; { Synchronized s(monitor_); if (!threadFactory_) { throw InvalidArgumentException(); } if (state_ == TimerManager::UNINITIALIZED) { state_ = TimerManager::STARTING; doStart = true; } } if (doStart) { dispatcherThread_ = threadFactory_->newThread(dispatcher_); dispatcherThread_->start(); } { Synchronized s(monitor_); while (state_ == TimerManager::STARTING) { monitor_.wait(); } assert(state_ != TimerManager::STARTING); } } void TimerManager::stop() { bool doStop = false; { Synchronized s(monitor_); if (state_ == TimerManager::UNINITIALIZED) { state_ = TimerManager::STOPPED; } else if (state_ != STOPPING && state_ != STOPPED) { doStop = true; state_ = STOPPING; monitor_.notifyAll(); } while (state_ != STOPPED) { monitor_.wait(); } } if (doStop) { // Clean up any outstanding tasks taskMap_.clear(); // Remove dispatcher's reference to us. dispatcher_->manager_ = nullptr; } } shared_ptr TimerManager::threadFactory() const { Synchronized s(monitor_); return threadFactory_; } void TimerManager::threadFactory(shared_ptr value) { Synchronized s(monitor_); threadFactory_ = value; } size_t TimerManager::taskCount() const { return taskCount_; } TimerManager::Timer TimerManager::add(shared_ptr task, const std::chrono::milliseconds &timeout) { return add(task, std::chrono::steady_clock::now() + timeout); } TimerManager::Timer TimerManager::add(shared_ptr task, const std::chrono::time_point& abstime) { auto now = std::chrono::steady_clock::now(); if (abstime < now) { throw InvalidArgumentException(); } Synchronized s(monitor_); if (state_ != TimerManager::STARTED) { throw IllegalStateException(); } // If the task map is empty, we will kick the dispatcher for sure. Otherwise, we kick him // if the expiration time is shorter than the current value. Need to test before we insert, // because the new task might insert at the front. bool notifyRequired = (taskCount_ == 0) ? true : abstime < taskMap_.begin()->first; shared_ptr timer(new Task(task)); taskCount_++; timer->it_ = taskMap_.emplace(abstime, timer); // If the task map was empty, or if we have an expiration that is earlier // than any previously seen, kick the dispatcher so it can update its // timeout if (notifyRequired) { monitor_.notify(); } return timer; } void TimerManager::remove(shared_ptr task) { Synchronized s(monitor_); if (state_ != TimerManager::STARTED) { throw IllegalStateException(); } bool found = false; for (auto ix = taskMap_.begin(); ix != taskMap_.end();) { if (*ix->second == task) { found = true; taskCount_--; taskMap_.erase(ix++); } else { ++ix; } } if (!found) { throw NoSuchTaskException(); } } void TimerManager::remove(Timer handle) { Synchronized s(monitor_); if (state_ != TimerManager::STARTED) { throw IllegalStateException(); } shared_ptr task = handle.lock(); if (!task) { throw NoSuchTaskException(); } if (task->it_ == taskMap_.end()) { // Task is being executed throw UncancellableTaskException(); } taskMap_.erase(task->it_); taskCount_--; } TimerManager::STATE TimerManager::state() const { return state_; } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/src/thrift/concurrency/Monitor.h0000644000000000000000000001013214303740367022654 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ #define _THRIFT_CONCURRENCY_MONITOR_H_ 1 #include #include #include #include namespace apache { namespace thrift { namespace concurrency { /** * A monitor is a combination mutex and condition-event. Waiting and * notifying condition events requires that the caller own the mutex. Mutex * lock and unlock operations can be performed independently of condition * events. This is more or less analogous to java.lang.Object multi-thread * operations. * * Note the Monitor can create a new, internal mutex; alternatively, a * separate Mutex can be passed in and the Monitor will re-use it without * taking ownership. It's the user's responsibility to make sure that the * Mutex is not deallocated before the Monitor. * * Note that all methods are const. Monitors implement logical constness, not * bit constness. This allows const methods to call monitor methods without * needing to cast away constness or change to non-const signatures. * * @version $Id:$ */ class Monitor : apache::thrift::TNonCopyable { public: /** Creates a new mutex, and takes ownership of it. */ Monitor(); /** Uses the provided mutex without taking ownership. */ explicit Monitor(Mutex* mutex); /** Uses the mutex inside the provided Monitor without taking ownership. */ explicit Monitor(Monitor* monitor); /** Deallocates the mutex only if we own it. */ virtual ~Monitor(); Mutex& mutex() const; virtual void lock() const; virtual void unlock() const; /** * Waits a maximum of the specified timeout in milliseconds for the condition * to occur, or waits forever if timeout is zero. * * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ int waitForTimeRelative(const std::chrono::milliseconds &timeout) const; int waitForTimeRelative(uint64_t timeout_ms) const { return waitForTimeRelative(std::chrono::milliseconds(timeout_ms)); } /** * Waits until the absolute time specified by abstime. * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ int waitForTime(const std::chrono::time_point& abstime) const; /** * Waits forever until the condition occurs. * Returns 0 if condition occurs, or an error code otherwise. */ int waitForever() const; /** * Exception-throwing version of waitForTimeRelative(), called simply * wait(std::chrono::milliseconds) for historical reasons. Timeout is in milliseconds. * * If the condition occurs, this function returns cleanly; on timeout or * error an exception is thrown. */ void wait(const std::chrono::milliseconds &timeout) const; void wait(uint64_t timeout_ms = 0ULL) const { this->wait(std::chrono::milliseconds(timeout_ms)); } /** Wakes up one thread waiting on this monitor. */ virtual void notify() const; /** Wakes up all waiting threads on this monitor. */ virtual void notifyAll() const; private: class Impl; Impl* impl_; }; class Synchronized { public: Synchronized(const Monitor* monitor) : g(monitor->mutex()) {} Synchronized(const Monitor& monitor) : g(monitor.mutex()) {} private: Guard g; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ thrift-0.19.0/lib/cpp/src/thrift/concurrency/Mutex.h0000644000000000000000000000410314303740367022330 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ #define _THRIFT_CONCURRENCY_MUTEX_H_ 1 #include #include namespace apache { namespace thrift { namespace concurrency { /** * NOTE: All mutex implementations throw an exception on failure. See each * specific implementation to understand the exception type(s) used. */ /** * A simple mutex class * * @version $Id:$ */ class Mutex { public: Mutex(); virtual ~Mutex() = default; virtual void lock() const; virtual bool trylock() const; virtual bool timedlock(int64_t milliseconds) const; virtual void unlock() const; void* getUnderlyingImpl() const; private: class impl; std::shared_ptr impl_; }; class Guard : apache::thrift::TNonCopyable { public: Guard(const Mutex& value, int64_t timeout = 0) : mutex_(&value) { if (timeout == 0) { value.lock(); } else if (timeout < 0) { if (!value.trylock()) { mutex_ = nullptr; } } else { if (!value.timedlock(timeout)) { mutex_ = nullptr; } } } ~Guard() { if (mutex_) { mutex_->unlock(); } } operator bool() const { return (mutex_ != nullptr); } private: const Mutex* mutex_; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ thrift-0.19.0/lib/cpp/src/thrift/concurrency/Mutex.cpp0000644000000000000000000000301214303740367022661 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include namespace apache { namespace thrift { namespace concurrency { /** * Implementation of Mutex class using C++11 std::timed_mutex * * Methods throw std::system_error on error. * * @version $Id:$ */ class Mutex::impl : public std::timed_mutex {}; Mutex::Mutex() : impl_(new Mutex::impl()) { } void* Mutex::getUnderlyingImpl() const { return impl_.get(); } void Mutex::lock() const { impl_->lock(); } bool Mutex::trylock() const { return impl_->try_lock(); } bool Mutex::timedlock(int64_t ms) const { return impl_->try_lock_for(std::chrono::milliseconds(ms)); } void Mutex::unlock() const { impl_->unlock(); } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/src/thrift/concurrency/Monitor.cpp0000644000000000000000000001262714303740367023222 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace concurrency { /** * Monitor implementation using the std thread library * * @version $Id:$ */ class Monitor::Impl { public: Impl() : ownedMutex_(new Mutex()), conditionVariable_(), mutex_(nullptr) { init(ownedMutex_.get()); } Impl(Mutex* mutex) : ownedMutex_(), conditionVariable_(), mutex_(nullptr) { init(mutex); } Impl(Monitor* monitor) : ownedMutex_(), conditionVariable_(), mutex_(nullptr) { init(&(monitor->mutex())); } Mutex& mutex() { return *mutex_; } void lock() { mutex_->lock(); } void unlock() { mutex_->unlock(); } /** * Exception-throwing version of waitForTimeRelative(), called simply * wait(int64) for historical reasons. Timeout is in milliseconds. * * If the condition occurs, this function returns cleanly; on timeout or * error an exception is thrown. */ void wait(const std::chrono::milliseconds &timeout) { int result = waitForTimeRelative(timeout); if (result == THRIFT_ETIMEDOUT) { throw TimedOutException(); } else if (result != 0) { throw TException("Monitor::wait() failed"); } } /** * Waits until the specified timeout in milliseconds for the condition to * occur, or waits forever if timeout is zero. * * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ int waitForTimeRelative(const std::chrono::milliseconds &timeout) { if (timeout.count() == 0) { return waitForever(); } assert(mutex_); auto* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); bool timedout = (conditionVariable_.wait_for(lock, timeout) == std::cv_status::timeout); lock.release(); return (timedout ? THRIFT_ETIMEDOUT : 0); } /** * Waits until the absolute time specified by abstime. * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ int waitForTime(const std::chrono::time_point& abstime) { assert(mutex_); auto* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); bool timedout = (conditionVariable_.wait_until(lock, abstime) == std::cv_status::timeout); lock.release(); return (timedout ? THRIFT_ETIMEDOUT : 0); } /** * Waits forever until the condition occurs. * Returns 0 if condition occurs, or an error code otherwise. */ int waitForever() { assert(mutex_); auto* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); conditionVariable_.wait(lock); lock.release(); return 0; } void notify() { conditionVariable_.notify_one(); } void notifyAll() { conditionVariable_.notify_all(); } private: void init(Mutex* mutex) { mutex_ = mutex; } const std::unique_ptr ownedMutex_; std::condition_variable_any conditionVariable_; Mutex* mutex_; }; Monitor::Monitor() : impl_(new Monitor::Impl()) { } Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) { } Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) { } Monitor::~Monitor() { delete impl_; } Mutex& Monitor::mutex() const { return const_cast(impl_)->mutex(); } void Monitor::lock() const { const_cast(impl_)->lock(); } void Monitor::unlock() const { const_cast(impl_)->unlock(); } void Monitor::wait(const std::chrono::milliseconds &timeout) const { const_cast(impl_)->wait(timeout); } int Monitor::waitForTime(const std::chrono::time_point& abstime) const { return const_cast(impl_)->waitForTime(abstime); } int Monitor::waitForTimeRelative(const std::chrono::milliseconds &timeout) const { return const_cast(impl_)->waitForTimeRelative(timeout); } int Monitor::waitForever() const { return const_cast(impl_)->waitForever(); } void Monitor::notify() const { const_cast(impl_)->notify(); } void Monitor::notifyAll() const { const_cast(impl_)->notifyAll(); } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/src/thrift/concurrency/Exception.h0000644000000000000000000000414614303740367023173 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ #define _THRIFT_CONCURRENCY_EXCEPTION_H_ 1 #include #include namespace apache { namespace thrift { namespace concurrency { class NoSuchTaskException : public apache::thrift::TException {}; class UncancellableTaskException : public apache::thrift::TException {}; class InvalidArgumentException : public apache::thrift::TException {}; class IllegalStateException : public apache::thrift::TException { public: IllegalStateException() = default; IllegalStateException(const std::string& message) : TException(message) {} }; class TimedOutException : public apache::thrift::TException { public: TimedOutException() : TException("TimedOutException"){}; TimedOutException(const std::string& message) : TException(message) {} }; class TooManyPendingTasksException : public apache::thrift::TException { public: TooManyPendingTasksException() : TException("TooManyPendingTasksException"){}; TooManyPendingTasksException(const std::string& message) : TException(message) {} }; class SystemResourceException : public apache::thrift::TException { public: SystemResourceException() = default; SystemResourceException(const std::string& message) : TException(message) {} }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ thrift-0.19.0/lib/cpp/src/thrift/concurrency/ThreadManager.h0000644000000000000000000001536714303740367023746 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ #define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1 #include #include #include namespace apache { namespace thrift { namespace concurrency { /** * Thread Pool Manager and related classes * * @version $Id:$ */ class ThreadManager; /** * ThreadManager class * * This class manages a pool of threads. It uses a ThreadFactory to create * threads. It never actually creates or destroys worker threads, rather * it maintains statistics on number of idle threads, number of active threads, * task backlog, and average wait and service times and informs the PoolPolicy * object bound to instances of this manager of interesting transitions. It is * then up the PoolPolicy object to decide if the thread pool size needs to be * adjusted and call this object addWorker and removeWorker methods to make * changes. * * This design allows different policy implementations to use this code to * handle basic worker thread management and worker task execution and focus on * policy issues. The simplest policy, StaticPolicy, does nothing other than * create a fixed number of threads. */ class ThreadManager { protected: ThreadManager() = default; public: typedef std::function)> ExpireCallback; virtual ~ThreadManager() = default; /** * Starts the thread manager. Verifies all attributes have been properly * initialized, then allocates necessary resources to begin operation */ virtual void start() = 0; /** * Stops the thread manager. Aborts all remaining unprocessed task, shuts * down all created worker threads, and releases all allocated resources. * This method blocks for all worker threads to complete, thus it can * potentially block forever if a worker thread is running a task that * won't terminate. * * Worker threads will be joined depending on the threadFactory's detached * disposition. */ virtual void stop() = 0; enum STATE { UNINITIALIZED, STARTING, STARTED, JOINING, STOPPING, STOPPED }; virtual STATE state() const = 0; /** * \returns the current thread factory */ virtual std::shared_ptr threadFactory() const = 0; /** * Set the thread factory. * \throws InvalidArgumentException if the new thread factory has a different * detached disposition than the one replacing it */ virtual void threadFactory(std::shared_ptr value) = 0; /** * Adds worker thread(s). */ virtual void addWorker(size_t value = 1) = 0; /** * Removes worker thread(s). * Threads are joined if the thread factory detached disposition allows it. * Blocks until the number of worker threads reaches the new limit. * \param[in] value the number to remove * \throws InvalidArgumentException if the value is greater than the number * of workers */ virtual void removeWorker(size_t value = 1) = 0; /** * Gets the current number of idle worker threads */ virtual size_t idleWorkerCount() const = 0; /** * Gets the current number of total worker threads */ virtual size_t workerCount() const = 0; /** * Gets the current number of pending tasks */ virtual size_t pendingTaskCount() const = 0; /** * Gets the current number of pending and executing tasks */ virtual size_t totalTaskCount() const = 0; /** * Gets the maximum pending task count. 0 indicates no maximum */ virtual size_t pendingTaskCountMax() const = 0; /** * Gets the number of tasks which have been expired without being run * since start() was called. */ virtual size_t expiredTaskCount() const = 0; /** * Adds a task to be executed at some time in the future by a worker thread. * * This method will block if pendingTaskCountMax() in not zero and pendingTaskCount() * is greater than or equalt to pendingTaskCountMax(). If this method is called in the * context of a ThreadManager worker thread it will throw a * TooManyPendingTasksException * * @param task The task to queue for execution * * @param timeout Time to wait in milliseconds to add a task when a pending-task-count * is specified. Specific cases: * timeout = 0 : Wait forever to queue task. * timeout = -1 : Return immediately if pending task count exceeds specified max * @param expiration when nonzero, the number of milliseconds the task is valid * to be run; if exceeded, the task will be dropped off the queue and not run. * * @throws TooManyPendingTasksException Pending task count exceeds max pending task count */ virtual void add(std::shared_ptr task, int64_t timeout = 0LL, int64_t expiration = 0LL) = 0; /** * Removes a pending task */ virtual void remove(std::shared_ptr task) = 0; /** * Remove the next pending task which would be run. * * @return the task removed. */ virtual std::shared_ptr removeNextPending() = 0; /** * Remove tasks from front of task queue that have expired. */ virtual void removeExpiredTasks() = 0; /** * Set a callback to be called when a task is expired and not run. * * @param expireCallback a function called with the shared_ptr for * the expired task. */ virtual void setExpireCallback(ExpireCallback expireCallback) = 0; static std::shared_ptr newThreadManager(); /** * Creates a simple thread manager the uses count number of worker threads and has * a pendingTaskCountMax maximum pending tasks. The default, 0, specified no limit * on pending tasks */ static std::shared_ptr newSimpleThreadManager(size_t count = 4, size_t pendingTaskCountMax = 0); class Task; class Worker; class Impl; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ thrift-0.19.0/lib/cpp/src/thrift/concurrency/ThreadFactory.h0000644000000000000000000000420614303740367023771 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_THREADFACTORY_H_ #define _THRIFT_CONCURRENCY_THREADFACTORY_H_ 1 #include #include namespace apache { namespace thrift { namespace concurrency { /** * Factory to create thread object and bind them to Runnable * object for execution */ class ThreadFactory { public: /** * All threads created by a factory are reference-counted * via std::shared_ptr. The factory guarantees that threads and the Runnable tasks * they host will be properly cleaned up once the last strong reference * to both is given up. * * By default threads are not joinable. */ ThreadFactory(bool detached = true) : detached_(detached) { } virtual ~ThreadFactory() = default; /** * Gets current detached mode */ bool isDetached() const { return detached_; } /** * Sets the detached disposition of newly created threads. */ void setDetached(bool detached) { detached_ = detached; } /** * Create a new thread. */ virtual std::shared_ptr newThread(std::shared_ptr runnable) const; /** * Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread */ Thread::id_t getCurrentThreadId() const; private: bool detached_; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_THREADFACTORY_H_ thrift-0.19.0/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp0000644000000000000000000000245714303740367024332 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include namespace apache { namespace thrift { namespace concurrency { std::shared_ptr ThreadFactory::newThread(std::shared_ptr runnable) const { std::shared_ptr result = std::make_shared(isDetached(), runnable); runnable->thread(result); return result; } Thread::id_t ThreadFactory::getCurrentThreadId() const { return std::this_thread::get_id(); } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/src/thrift/concurrency/Thread.h0000644000000000000000000001153214303740367022441 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_CONCURRENCY_THREAD_H_ #define _THRIFT_CONCURRENCY_THREAD_H_ 1 #include #include #include namespace apache { namespace thrift { namespace concurrency { class Thread; /** * Minimal runnable class. More or less analogous to java.lang.Runnable. * * @version $Id:$ */ class Runnable { public: virtual ~Runnable() = default; virtual void run() = 0; /** * Gets the thread object that is hosting this runnable object - can return * an empty boost::shared pointer if no references remain on that thread object */ virtual std::shared_ptr thread() { return thread_.lock(); } /** * Sets the thread that is executing this object. This is only meant for * use by concrete implementations of Thread. */ virtual void thread(std::shared_ptr value) { thread_ = value; } private: std::weak_ptr thread_; }; /** * Minimal thread class. Returned by thread factory bound to a Runnable object * and ready to start execution. More or less analogous to java.lang.Thread * (minus all the thread group, priority, mode and other baggage, since that * is difficult to abstract across platforms and is left for platform-specific * ThreadFactory implementations to deal with * * @see apache::thrift::concurrency::ThreadFactory) */ class Thread : public std::enable_shared_from_this { public: typedef std::thread::id id_t; typedef void (*thread_funct_t)(std::shared_ptr ); enum STATE { uninitialized, starting, started, stopping, stopped }; static void threadMain(std::shared_ptr thread); static inline bool is_current(id_t t) { return t == std::this_thread::get_id(); } static inline id_t get_current() { return std::this_thread::get_id(); } Thread(bool detached, std::shared_ptr runnable) : state_(uninitialized), detached_(detached) { this->_runnable = runnable; } virtual ~Thread() { if (!detached_ && thread_->joinable()) { try { join(); } catch (...) { // We're really hosed. } } } STATE getState() const { Synchronized sync(monitor_); return state_; } void setState(STATE newState) { Synchronized sync(monitor_); state_ = newState; // unblock start() with the knowledge that the thread has actually // started running, which avoids a race in detached threads. if (newState == started) { monitor_.notify(); } } /** * Starts the thread. Does platform specific thread creation and * configuration then invokes the run method of the Runnable object bound * to this thread. */ virtual void start() { if (getState() != uninitialized) { return; } std::shared_ptr selfRef = shared_from_this(); setState(starting); Synchronized sync(monitor_); thread_ = std::unique_ptr(new std::thread(getThreadFunc(), selfRef)); if (detached_) thread_->detach(); // Wait for the thread to start and get far enough to grab everything // that it needs from the calling context, thus absolving the caller // from being required to hold on to runnable indefinitely. monitor_.wait(); } /** * Join this thread. If this thread is joinable, the calling thread blocks * until this thread completes. If the target thread is not joinable, then * nothing happens. */ virtual void join() { if (!detached_ && state_ != uninitialized) { thread_->join(); } } /** * Gets the thread's platform-specific ID */ Thread::id_t getId() const { return thread_.get() ? thread_->get_id() : std::thread::id(); } /** * Gets the runnable object this thread is hosting */ std::shared_ptr runnable() const { return _runnable; } protected: virtual thread_funct_t getThreadFunc() const { return threadMain; } private: std::shared_ptr _runnable; std::unique_ptr thread_; Monitor monitor_; STATE state_; bool detached_; }; } } } // apache::thrift::concurrency #endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_ thrift-0.19.0/lib/cpp/src/thrift/qt/0000755000000000000000000000000014472652650017155 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/qt/CMakeLists.txt0000644000000000000000000000211314303740367021706 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # set( thriftcppqt5_SOURCES TQIODeviceTransport.cpp TQTcpServer.cpp ) set(CMAKE_AUTOMOC ON) find_package(Qt5 REQUIRED COMPONENTS Core Network) ADD_LIBRARY_THRIFT(thriftqt5 ${thriftcppqt5_SOURCES}) target_link_libraries(thriftqt5 PUBLIC thrift) target_link_libraries(thriftqt5 PUBLIC Qt5::Core Qt5::Network) thrift-0.19.0/lib/cpp/src/thrift/qt/TQIODeviceTransport.h0000644000000000000000000000372114303740367023136 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ #define _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ 1 #include #include class QIODevice; namespace apache { namespace thrift { namespace transport { /** * Transport that operates on a QIODevice (socket, file, etc). */ class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport { public: explicit TQIODeviceTransport(std::shared_ptr dev); ~TQIODeviceTransport() override; void open() override; bool isOpen() const override; bool peek() override; void close() override; uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t read(uint8_t* buf, uint32_t len); void write(const uint8_t* buf, uint32_t len); uint32_t write_partial(const uint8_t* buf, uint32_t len); void flush() override; uint8_t* borrow(uint8_t* buf, uint32_t* len); void consume(uint32_t len); private: TQIODeviceTransport(const TQIODeviceTransport&); TQIODeviceTransport& operator=(const TQIODeviceTransport&); std::shared_ptr dev_; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/qt/TQTcpServer.cpp0000644000000000000000000001203714303740367022042 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TQIODeviceTransport; using std::bind; using std::function; using std::placeholders::_1; using std::shared_ptr; QT_USE_NAMESPACE namespace apache { namespace thrift { namespace async { struct TQTcpServer::ConnectionContext { shared_ptr connection_; shared_ptr transport_; shared_ptr iprot_; shared_ptr oprot_; explicit ConnectionContext(shared_ptr connection, shared_ptr transport, shared_ptr iprot, shared_ptr oprot) : connection_(connection), transport_(transport), iprot_(iprot), oprot_(oprot) {} }; TQTcpServer::TQTcpServer(shared_ptr server, shared_ptr processor, shared_ptr pfact, QObject* parent) : QObject(parent), server_(server), processor_(processor), pfact_(pfact) { qRegisterMetaType("QTcpSocket*"); connect(server.get(), SIGNAL(newConnection()), SLOT(processIncoming())); } TQTcpServer::~TQTcpServer() = default; void TQTcpServer::processIncoming() { while (server_->hasPendingConnections()) { // take ownership of the QTcpSocket; technically it could be deleted // when the QTcpServer is destroyed, but any real app should delete this // class before deleting the QTcpServer that we are using shared_ptr connection(server_->nextPendingConnection()); shared_ptr transport; shared_ptr iprot; shared_ptr oprot; try { transport = shared_ptr(new TQIODeviceTransport(connection)); iprot = shared_ptr(pfact_->getProtocol(transport)); oprot = shared_ptr(pfact_->getProtocol(transport)); } catch (...) { qWarning("[TQTcpServer] Failed to initialize transports/protocols"); continue; } ctxMap_[connection.get()] = std::make_shared(connection, transport, iprot, oprot); connect(connection.get(), SIGNAL(readyRead()), SLOT(beginDecode())); connect(connection.get(), SIGNAL(disconnected()), SLOT(socketClosed())); } } void TQTcpServer::beginDecode() { auto* connection(qobject_cast(sender())); Q_ASSERT(connection); if (ctxMap_.find(connection) == ctxMap_.end()) { qWarning("[TQTcpServer] Got data on an unknown QTcpSocket"); return; } shared_ptr ctx = ctxMap_[connection]; try { processor_ ->process(bind(&TQTcpServer::finish, this, ctx, _1), ctx->iprot_, ctx->oprot_); } catch (const TTransportException& ex) { qWarning("[TQTcpServer] TTransportException during processing: '%s'", ex.what()); scheduleDeleteConnectionContext(connection); } catch (...) { qWarning("[TQTcpServer] Unknown processor exception"); scheduleDeleteConnectionContext(connection); } } void TQTcpServer::socketClosed() { auto* connection(qobject_cast(sender())); Q_ASSERT(connection); scheduleDeleteConnectionContext(connection); } void TQTcpServer::deleteConnectionContext(QTcpSocket* connection) { const ConnectionContextMap::size_type deleted = ctxMap_.erase(connection); if (0 == deleted) { qWarning("[TQTcpServer] Unknown QTcpSocket"); } } void TQTcpServer::scheduleDeleteConnectionContext(QTcpSocket* connection) { QMetaObject::invokeMethod(this, "deleteConnectionContext", Qt::QueuedConnection, Q_ARG(QTcpSocket*, connection)); } void TQTcpServer::finish(shared_ptr ctx, bool healthy) { if (!healthy) { qWarning("[TQTcpServer] Processor failed to process data successfully"); deleteConnectionContext(ctx->connection_.get()); } } } } } // apache::thrift::async thrift-0.19.0/lib/cpp/src/thrift/qt/TQTcpServer.h0000644000000000000000000000451214303740367021506 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TASYNC_QTCP_SERVER_H_ #define _THRIFT_TASYNC_QTCP_SERVER_H_ #include #include #include namespace apache { namespace thrift { namespace protocol { class TProtocolFactory; } } } // apache::thrift::protocol namespace apache { namespace thrift { namespace async { class TAsyncProcessor; /** * Server that uses Qt to listen for connections. * Simply give it a QTcpServer that is listening, along with an async * processor and a protocol factory, and then run the Qt event loop. */ class TQTcpServer : public QObject { Q_OBJECT public: TQTcpServer(std::shared_ptr server, std::shared_ptr processor, std::shared_ptr protocolFactory, QObject* parent = nullptr); ~TQTcpServer() override; private Q_SLOTS: void processIncoming(); void beginDecode(); void socketClosed(); void deleteConnectionContext(QTcpSocket* connection); private: Q_DISABLE_COPY(TQTcpServer) struct ConnectionContext; void scheduleDeleteConnectionContext(QTcpSocket* connection); void finish(std::shared_ptr ctx, bool healthy); std::shared_ptr server_; std::shared_ptr processor_; std::shared_ptr pfact_; typedef std::map > ConnectionContextMap; ConnectionContextMap ctxMap_; }; } } } // apache::thrift::async #endif // #ifndef _THRIFT_TASYNC_QTCP_SERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp0000644000000000000000000001105614303740367023471 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include namespace apache { namespace thrift { using std::shared_ptr; namespace transport { TQIODeviceTransport::TQIODeviceTransport(shared_ptr dev) : dev_(dev) { } TQIODeviceTransport::~TQIODeviceTransport() { dev_->close(); } void TQIODeviceTransport::open() { if (!isOpen()) { throw TTransportException(TTransportException::NOT_OPEN, "open(): underlying QIODevice isn't open"); } } bool TQIODeviceTransport::isOpen() const { return dev_->isOpen(); } bool TQIODeviceTransport::peek() { return dev_->bytesAvailable() > 0; } void TQIODeviceTransport::close() { dev_->close(); } uint32_t TQIODeviceTransport::readAll(uint8_t* buf, uint32_t len) { uint32_t requestLen = len; while (len) { uint32_t readSize; try { readSize = read(buf, len); } catch (...) { if (len != requestLen) { // something read already return requestLen - len; } // error but nothing read yet throw; } if (readSize == 0) { dev_->waitForReadyRead(50); } else { buf += readSize; len -= readSize; } } return requestLen; } uint32_t TQIODeviceTransport::read(uint8_t* buf, uint32_t len) { uint32_t actualSize; qint64 readSize; if (!dev_->isOpen()) { throw TTransportException(TTransportException::NOT_OPEN, "read(): underlying QIODevice is not open"); } actualSize = (uint32_t)(std::min)((qint64)len, dev_->bytesAvailable()); readSize = dev_->read(reinterpret_cast(buf), actualSize); if (readSize < 0) { QAbstractSocket* socket; if ((socket = qobject_cast(dev_.get()))) { throw TTransportException(TTransportException::UNKNOWN, "Failed to read() from QAbstractSocket", socket->error()); } throw TTransportException(TTransportException::UNKNOWN, "Failed to read from from QIODevice"); } return (uint32_t)readSize; } void TQIODeviceTransport::write(const uint8_t* buf, uint32_t len) { while (len) { uint32_t written = write_partial(buf, len); len -= written; dev_->waitForBytesWritten(50); } } uint32_t TQIODeviceTransport::write_partial(const uint8_t* buf, uint32_t len) { qint64 written; if (!dev_->isOpen()) { throw TTransportException(TTransportException::NOT_OPEN, "write_partial(): underlying QIODevice is not open"); } written = dev_->write(reinterpret_cast(buf), len); if (written < 0) { QAbstractSocket* socket; if ((socket = qobject_cast(dev_.get()))) { throw TTransportException(TTransportException::UNKNOWN, "write_partial(): failed to write to QAbstractSocket", socket->error()); } throw TTransportException(TTransportException::UNKNOWN, "write_partial(): failed to write to underlying QIODevice"); } return (uint32_t)written; } void TQIODeviceTransport::flush() { if (!dev_->isOpen()) { throw TTransportException(TTransportException::NOT_OPEN, "flush(): underlying QIODevice is not open"); } QAbstractSocket* socket; if ((socket = qobject_cast(dev_.get()))) { socket->flush(); } else { dev_->waitForBytesWritten(1); } } uint8_t* TQIODeviceTransport::borrow(uint8_t* buf, uint32_t* len) { (void)buf; (void)len; return nullptr; } void TQIODeviceTransport::consume(uint32_t len) { (void)len; throw TTransportException(TTransportException::UNKNOWN); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/server/0000755000000000000000000000000014472652650020037 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/server/TNonblockingServer.h0000644000000000000000000007271514303740367023776 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ #define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include namespace apache { namespace thrift { namespace server { using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TSocket; using apache::thrift::transport::TNonblockingServerTransport; using apache::thrift::protocol::TProtocol; using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::ThreadManager; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::Mutex; using apache::thrift::concurrency::Guard; #ifdef LIBEVENT_VERSION_NUMBER #define LIBEVENT_VERSION_MAJOR (LIBEVENT_VERSION_NUMBER >> 24) #define LIBEVENT_VERSION_MINOR ((LIBEVENT_VERSION_NUMBER >> 16) & 0xFF) #define LIBEVENT_VERSION_REL ((LIBEVENT_VERSION_NUMBER >> 8) & 0xFF) #else // assume latest version 1 series #define LIBEVENT_VERSION_MAJOR 1 #define LIBEVENT_VERSION_MINOR 14 #define LIBEVENT_VERSION_REL 13 #define LIBEVENT_VERSION_NUMBER \ ((LIBEVENT_VERSION_MAJOR << 24) | (LIBEVENT_VERSION_MINOR << 16) | (LIBEVENT_VERSION_REL << 8)) #endif #if LIBEVENT_VERSION_NUMBER < 0x02000000 typedef THRIFT_SOCKET evutil_socket_t; #endif #ifndef SOCKOPT_CAST_T #ifndef _WIN32 #define SOCKOPT_CAST_T void #else #define SOCKOPT_CAST_T char #endif // _WIN32 #endif template inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { return reinterpret_cast(v); } template inline SOCKOPT_CAST_T* cast_sockopt(T* v) { return reinterpret_cast(v); } /** * This is a non-blocking server in C++ for high performance that * operates a set of IO threads (by default only one). It assumes that * all incoming requests are framed with a 4 byte length indicator and * writes out responses using the same framing. */ /// Overload condition actions. enum TOverloadAction { T_OVERLOAD_NO_ACTION, ///< Don't handle overload */ T_OVERLOAD_CLOSE_ON_ACCEPT, ///< Drop new connections immediately */ T_OVERLOAD_DRAIN_TASK_QUEUE ///< Drop some tasks from head of task queue */ }; class TNonblockingIOThread; class TNonblockingServer : public TServer { private: class TConnection; friend class TNonblockingIOThread; private: /// Listen backlog static const int LISTEN_BACKLOG = 1024; /// Default limit on size of idle connection pool static const size_t CONNECTION_STACK_LIMIT = 1024; /// Default limit on frame size static const int MAX_FRAME_SIZE = 256 * 1024 * 1024; /// Default limit on total number of connected sockets static const int MAX_CONNECTIONS = INT_MAX; /// Default limit on connections in handler/task processing static const int MAX_ACTIVE_PROCESSORS = INT_MAX; /// Default size of write buffer static const int WRITE_BUFFER_DEFAULT_SIZE = 1024; /// Maximum size of read buffer allocated to idle connection (0 = unlimited) static const int IDLE_READ_BUFFER_LIMIT = 1024; /// Maximum size of write buffer allocated to idle connection (0 = unlimited) static const int IDLE_WRITE_BUFFER_LIMIT = 1024; /// # of calls before resizing oversized buffers (0 = check only on close) static const int RESIZE_BUFFER_EVERY_N = 512; /// # of IO threads to use by default static const int DEFAULT_IO_THREADS = 1; /// # of IO threads this server will use size_t numIOThreads_; /// Whether to set high scheduling priority for IO threads bool useHighPriorityIOThreads_; /// Server socket file descriptor THRIFT_SOCKET serverSocket_; /// The optional user-provided event-base (for single-thread servers) event_base* userEventBase_; /// For processing via thread pool, may be nullptr std::shared_ptr threadManager_; /// Is thread pool processing? bool threadPoolProcessing_; // Factory to create the IO threads std::shared_ptr ioThreadFactory_; // Vector of IOThread objects that will handle our IO std::vector > ioThreads_; // Index of next IO Thread to be used (for round-robin) uint32_t nextIOThread_; // Synchronizes access to connection stack and similar data Mutex connMutex_; /// Number of TConnection object we've created size_t numTConnections_; /// Number of Connections processing or waiting to process size_t numActiveProcessors_; /// Limit for how many TConnection objects to cache size_t connectionStackLimit_; /// Limit for number of connections processing or waiting to process size_t maxActiveProcessors_; /// Limit for number of open connections size_t maxConnections_; /// Limit for frame size size_t maxFrameSize_; /// Time in milliseconds before an unperformed task expires (0 == infinite). int64_t taskExpireTime_; /** * Hysteresis for overload state. This is the fraction of the overload * value that needs to be reached before the overload state is cleared; * must be <= 1.0. */ double overloadHysteresis_; /// Action to take when we're overloaded. TOverloadAction overloadAction_; /** * The write buffer is initialized (and when idleWriteBufferLimit_ is checked * and found to be exceeded, reinitialized) to this size. */ size_t writeBufferDefaultSize_; /** * Max read buffer size for an idle TConnection. When we place an idle * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls, * we will free the buffer (such that it will be reinitialized by the next * received frame) if it has exceeded this limit. 0 disables this check. */ size_t idleReadBufferLimit_; /** * Max write buffer size for an idle connection. When we place an idle * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls, * we insure that its write buffer is <= to this size; otherwise we * replace it with a new one of writeBufferDefaultSize_ bytes to insure that * idle connections don't hog memory. 0 disables this check. */ size_t idleWriteBufferLimit_; /** * Every N calls we check the buffer size limits on a connected TConnection. * 0 disables (i.e. the checks are only done when a connection closes). */ int32_t resizeBufferEveryN_; /// Set if we are currently in an overloaded state. bool overloaded_; /// Count of connections dropped since overload started uint32_t nConnectionsDropped_; /// Count of connections dropped on overload since server started uint64_t nTotalConnectionsDropped_; /** * This is a stack of all the objects that have been created but that * are NOT currently in use. When we close a connection, we place it on this * stack so that the object can be reused later, rather than freeing the * memory and reallocating a new object later. */ std::stack connectionStack_; /** * This container holds pointers to all active connections. This container * allows the server to clean up unlcosed connection objects at destruction, * which in turn allows their transports, protocols, processors and handlers * to deallocate and clean up correctly. */ std::vector activeConnections_; /* */ std::shared_ptr serverTransport_; /** * Called when server socket had something happen. We accept all waiting * client connections on listen socket fd and assign TConnection objects * to handle those requests. * * @param which the event flag that triggered the handler. */ void handleEvent(THRIFT_SOCKET fd, short which); void init() { serverSocket_ = THRIFT_INVALID_SOCKET; numIOThreads_ = DEFAULT_IO_THREADS; nextIOThread_ = 0; useHighPriorityIOThreads_ = false; userEventBase_ = nullptr; threadPoolProcessing_ = false; numTConnections_ = 0; numActiveProcessors_ = 0; connectionStackLimit_ = CONNECTION_STACK_LIMIT; maxActiveProcessors_ = MAX_ACTIVE_PROCESSORS; maxConnections_ = MAX_CONNECTIONS; maxFrameSize_ = MAX_FRAME_SIZE; taskExpireTime_ = 0; overloadHysteresis_ = 0.8; overloadAction_ = T_OVERLOAD_NO_ACTION; writeBufferDefaultSize_ = WRITE_BUFFER_DEFAULT_SIZE; idleReadBufferLimit_ = IDLE_READ_BUFFER_LIMIT; idleWriteBufferLimit_ = IDLE_WRITE_BUFFER_LIMIT; resizeBufferEveryN_ = RESIZE_BUFFER_EVERY_N; overloaded_ = false; nConnectionsDropped_ = 0; nTotalConnectionsDropped_ = 0; } public: TNonblockingServer(const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport) : TServer(processorFactory), serverTransport_(serverTransport) { init(); } TNonblockingServer(const std::shared_ptr& processor, const std::shared_ptr& serverTransport) : TServer(processor), serverTransport_(serverTransport) { init(); } TNonblockingServer(const std::shared_ptr& processorFactory, const std::shared_ptr& protocolFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& threadManager = std::shared_ptr()) : TServer(processorFactory), serverTransport_(serverTransport) { init(); setInputProtocolFactory(protocolFactory); setOutputProtocolFactory(protocolFactory); setThreadManager(threadManager); } TNonblockingServer(const std::shared_ptr& processor, const std::shared_ptr& protocolFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& threadManager = std::shared_ptr()) : TServer(processor), serverTransport_(serverTransport) { init(); setInputProtocolFactory(protocolFactory); setOutputProtocolFactory(protocolFactory); setThreadManager(threadManager); } TNonblockingServer(const std::shared_ptr& processorFactory, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& threadManager = std::shared_ptr()) : TServer(processorFactory), serverTransport_(serverTransport) { init(); setInputTransportFactory(inputTransportFactory); setOutputTransportFactory(outputTransportFactory); setInputProtocolFactory(inputProtocolFactory); setOutputProtocolFactory(outputProtocolFactory); setThreadManager(threadManager); } TNonblockingServer(const std::shared_ptr& processor, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& threadManager = std::shared_ptr()) : TServer(processor), serverTransport_(serverTransport) { init(); setInputTransportFactory(inputTransportFactory); setOutputTransportFactory(outputTransportFactory); setInputProtocolFactory(inputProtocolFactory); setOutputProtocolFactory(outputProtocolFactory); setThreadManager(threadManager); } ~TNonblockingServer() override; void setThreadManager(std::shared_ptr threadManager); int getListenPort() { return serverTransport_->getListenPort(); } std::shared_ptr getThreadManager() { return threadManager_; } /** * Sets the number of IO threads used by this server. Can only be used before * the call to serve() and has no effect afterwards. */ void setNumIOThreads(size_t numThreads) { numIOThreads_ = numThreads; // User-provided event-base doesn't works for multi-threaded servers assert(numIOThreads_ <= 1 || !userEventBase_); } /** Return whether the IO threads will get high scheduling priority */ bool useHighPriorityIOThreads() const { return useHighPriorityIOThreads_; } /** Set whether the IO threads will get high scheduling priority. */ void setUseHighPriorityIOThreads(bool val) { useHighPriorityIOThreads_ = val; } /** Return the number of IO threads used by this server. */ size_t getNumIOThreads() const { return numIOThreads_; } /** * Get the maximum number of unused TConnection we will hold in reserve. * * @return the current limit on TConnection pool size. */ size_t getConnectionStackLimit() const { return connectionStackLimit_; } /** * Set the maximum number of unused TConnection we will hold in reserve. * * @param sz the new limit for TConnection pool size. */ void setConnectionStackLimit(size_t sz) { connectionStackLimit_ = sz; } bool isThreadPoolProcessing() const { return threadPoolProcessing_; } void addTask(std::shared_ptr task) { threadManager_->add(task, 0LL, taskExpireTime_); } /** * Return the count of sockets currently connected to. * * @return count of connected sockets. */ size_t getNumConnections() const { return numTConnections_; } /** * Return the count of sockets currently connected to. * * @return count of connected sockets. */ size_t getNumActiveConnections() const { return getNumConnections() - getNumIdleConnections(); } /** * Return the count of connection objects allocated but not in use. * * @return count of idle connection objects. */ size_t getNumIdleConnections() const { return connectionStack_.size(); } /** * Return count of number of connections which are currently processing. * This is defined as a connection where all data has been received and * either assigned a task (when threading) or passed to a handler (when * not threading), and where the handler has not yet returned. * * @return # of connections currently processing. */ size_t getNumActiveProcessors() const { return numActiveProcessors_; } /// Increment the count of connections currently processing. void incrementActiveProcessors() { Guard g(connMutex_); ++numActiveProcessors_; } /// Decrement the count of connections currently processing. void decrementActiveProcessors() { Guard g(connMutex_); if (numActiveProcessors_ > 0) { --numActiveProcessors_; } } /** * Get the maximum # of connections allowed before overload. * * @return current setting. */ size_t getMaxConnections() const { return maxConnections_; } /** * Set the maximum # of connections allowed before overload. * * @param maxConnections new setting for maximum # of connections. */ void setMaxConnections(size_t maxConnections) { maxConnections_ = maxConnections; } /** * Get the maximum # of connections waiting in handler/task before overload. * * @return current setting. */ size_t getMaxActiveProcessors() const { return maxActiveProcessors_; } /** * Set the maximum # of connections waiting in handler/task before overload. * * @param maxActiveProcessors new setting for maximum # of active processes. */ void setMaxActiveProcessors(size_t maxActiveProcessors) { maxActiveProcessors_ = maxActiveProcessors; } /** * Get the maximum allowed frame size. * * If a client tries to send a message larger than this limit, * its connection will be closed. * * @return Maxium frame size, in bytes. */ size_t getMaxFrameSize() const { return maxFrameSize_; } /** * Set the maximum allowed frame size. * * @param maxFrameSize The new maximum frame size. */ void setMaxFrameSize(size_t maxFrameSize) { maxFrameSize_ = maxFrameSize; } /** * Get fraction of maximum limits before an overload condition is cleared. * * @return hysteresis fraction */ double getOverloadHysteresis() const { return overloadHysteresis_; } /** * Set fraction of maximum limits before an overload condition is cleared. * A good value would probably be between 0.5 and 0.9. * * @param hysteresisFraction fraction <= 1.0. */ void setOverloadHysteresis(double hysteresisFraction) { if (hysteresisFraction <= 1.0 && hysteresisFraction > 0.0) { overloadHysteresis_ = hysteresisFraction; } } /** * Get the action the server will take on overload. * * @return a TOverloadAction enum value for the currently set action. */ TOverloadAction getOverloadAction() const { return overloadAction_; } /** * Set the action the server is to take on overload. * * @param overloadAction a TOverloadAction enum value for the action. */ void setOverloadAction(TOverloadAction overloadAction) { overloadAction_ = overloadAction; } /** * Get the time in milliseconds after which a task expires (0 == infinite). * * @return a 64-bit time in milliseconds. */ int64_t getTaskExpireTime() const { return taskExpireTime_; } /** * Set the time in milliseconds after which a task expires (0 == infinite). * * @param taskExpireTime a 64-bit time in milliseconds. */ void setTaskExpireTime(int64_t taskExpireTime) { taskExpireTime_ = taskExpireTime; } /** * Determine if the server is currently overloaded. * This function checks the maximums for open connections and connections * currently in processing, and sets an overload condition if they are * exceeded. The overload will persist until both values are below the * current hysteresis fraction of their maximums. * * @return true if an overload condition exists, false if not. */ bool serverOverloaded(); /** Pop and discard next task on threadpool wait queue. * * @return true if a task was discarded, false if the wait queue was empty. */ bool drainPendingTask(); /** * Get the starting size of a TConnection object's write buffer. * * @return # bytes we initialize a TConnection object's write buffer to. */ size_t getWriteBufferDefaultSize() const { return writeBufferDefaultSize_; } /** * Set the starting size of a TConnection object's write buffer. * * @param size # bytes we initialize a TConnection object's write buffer to. */ void setWriteBufferDefaultSize(size_t size) { writeBufferDefaultSize_ = size; } /** * Get the maximum size of read buffer allocated to idle TConnection objects. * * @return # bytes beyond which we will dealloc idle buffer. */ size_t getIdleReadBufferLimit() const { return idleReadBufferLimit_; } /** * [NOTE: This is for backwards compatibility, use getIdleReadBufferLimit().] * Get the maximum size of read buffer allocated to idle TConnection objects. * * @return # bytes beyond which we will dealloc idle buffer. */ size_t getIdleBufferMemLimit() const { return idleReadBufferLimit_; } /** * Set the maximum size read buffer allocated to idle TConnection objects. * If a TConnection object is found (either on connection close or between * calls when resizeBufferEveryN_ is set) with more than this much memory * allocated to its read buffer, we free it and allow it to be reinitialized * on the next received frame. * * @param limit of bytes beyond which we will shrink buffers when checked. */ void setIdleReadBufferLimit(size_t limit) { idleReadBufferLimit_ = limit; } /** * [NOTE: This is for backwards compatibility, use setIdleReadBufferLimit().] * Set the maximum size read buffer allocated to idle TConnection objects. * If a TConnection object is found (either on connection close or between * calls when resizeBufferEveryN_ is set) with more than this much memory * allocated to its read buffer, we free it and allow it to be reinitialized * on the next received frame. * * @param limit of bytes beyond which we will shrink buffers when checked. */ void setIdleBufferMemLimit(size_t limit) { idleReadBufferLimit_ = limit; } /** * Get the maximum size of write buffer allocated to idle TConnection objects. * * @return # bytes beyond which we will reallocate buffers when checked. */ size_t getIdleWriteBufferLimit() const { return idleWriteBufferLimit_; } /** * Set the maximum size write buffer allocated to idle TConnection objects. * If a TConnection object is found (either on connection close or between * calls when resizeBufferEveryN_ is set) with more than this much memory * allocated to its write buffer, we destroy and construct that buffer with * writeBufferDefaultSize_ bytes. * * @param limit of bytes beyond which we will shrink buffers when idle. */ void setIdleWriteBufferLimit(size_t limit) { idleWriteBufferLimit_ = limit; } /** * Get # of calls made between buffer size checks. 0 means disabled. * * @return # of calls between buffer size checks. */ int32_t getResizeBufferEveryN() const { return resizeBufferEveryN_; } /** * Check buffer sizes every "count" calls. This allows buffer limits * to be enforced for persistent connections with a controllable degree * of overhead. 0 disables checks except at connection close. * * @param count the number of calls between checks, or 0 to disable */ void setResizeBufferEveryN(int32_t count) { resizeBufferEveryN_ = count; } /** * Main workhorse function, starts up the server listening on a port and * loops over the libevent handler. */ void serve() override; /** * Causes the server to terminate gracefully (can be called from any thread). */ void stop() override; /// Creates a socket to listen on and binds it to the local port. void createAndListenOnSocket(); /** * Register the optional user-provided event-base (for single-thread servers) * * This method should be used when the server is running in a single-thread * mode, and the event base is provided by the user (i.e., the caller). * * @param user_event_base the user-provided event-base. The user is * responsible for freeing the event base memory. */ void registerEvents(event_base* user_event_base); /** * Returns the optional user-provided event-base (for single-thread servers). */ event_base* getUserEventBase() const { return userEventBase_; } /** Some transports, like THeaderTransport, require passing through * the framing size instead of stripping it. */ bool getHeaderTransport(); private: /** * Callback function that the threadmanager calls when a task reaches * its expiration time. It is needed to clean up the expired connection. * * @param task the runnable associated with the expired task. */ void expireClose(std::shared_ptr task); /** * Return an initialized connection object. Creates or recovers from * pool a TConnection and initializes it with the provided socket FD * and flags. * * @param socket FD of socket associated with this connection. * @param addr the sockaddr of the client * @param addrLen the length of addr * @return pointer to initialized TConnection object. */ TConnection* createConnection(std::shared_ptr socket); /** * Returns a connection to pool or deletion. If the connection pool * (a stack) isn't full, place the connection object on it, otherwise * just delete it. * * @param connection the TConection being returned. */ void returnConnection(TConnection* connection); }; class TNonblockingIOThread : public Runnable { public: // Creates an IO thread and sets up the event base. The listenSocket should // be a valid FD on which listen() has already been called. If the // listenSocket is < 0, accepting will not be done. TNonblockingIOThread(TNonblockingServer* server, int number, THRIFT_SOCKET listenSocket, bool useHighPriority); ~TNonblockingIOThread() override; // Returns the event-base for this thread. event_base* getEventBase() const { return eventBase_; } // Returns the server for this thread. TNonblockingServer* getServer() const { return server_; } // Returns the number of this IO thread. int getThreadNumber() const { return number_; } // Returns the thread id associated with this object. This should // only be called after the thread has been started. Thread::id_t getThreadId() const { return threadId_; } // Returns the send-fd for task complete notifications. evutil_socket_t getNotificationSendFD() const { return notificationPipeFDs_[1]; } // Returns the read-fd for task complete notifications. evutil_socket_t getNotificationRecvFD() const { return notificationPipeFDs_[0]; } // Returns the actual thread object associated with this IO thread. std::shared_ptr getThread() const { return thread_; } // Sets the actual thread object associated with this IO thread. void setThread(const std::shared_ptr& t) { thread_ = t; } // Used by TConnection objects to indicate processing has finished. bool notify(TNonblockingServer::TConnection* conn); // Enters the event loop and does not return until a call to stop(). void run() override; // Exits the event loop as soon as possible. void stop(); // Ensures that the event-loop thread is fully finished and shut down. void join(); /// Registers the events for the notification & listen sockets void registerEvents(); private: /** * C-callable event handler for signaling task completion. Provides a * callback that libevent can understand that will read a connection * object's address from a pipe and call connection->transition() for * that object. * * @param fd the descriptor the event occurred on. */ static void notifyHandler(evutil_socket_t fd, short which, void* v); /** * C-callable event handler for listener events. Provides a callback * that libevent can understand which invokes server->handleEvent(). * * @param fd the descriptor the event occurred on. * @param which the flags associated with the event. * @param v void* callback arg where we placed TNonblockingServer's "this". */ static void listenHandler(evutil_socket_t fd, short which, void* v) { ((TNonblockingServer*)v)->handleEvent(fd, which); } /// Exits the loop ASAP in case of shutdown or error. void breakLoop(bool error); /// Create the pipe used to notify I/O process of task completion. void createNotificationPipe(); /// Unregisters our events for notification and listen sockets. void cleanupEvents(); /// Sets (or clears) high priority scheduling status for the current thread. void setCurrentThreadHighPriority(bool value); private: /// associated server TNonblockingServer* server_; /// thread number (for debugging). const int number_; /// The actual physical thread id. Thread::id_t threadId_; /// If listenSocket_ >= 0, adds an event on the event_base to accept conns THRIFT_SOCKET listenSocket_; /// Sets a high scheduling priority when running bool useHighPriority_; /// pointer to eventbase to be used for looping event_base* eventBase_; /// Set to true if this class is responsible for freeing the event base /// memory. bool ownEventBase_; /// Used with eventBase_ for connection events (only in listener thread) struct event serverEvent_; /// Used with eventBase_ for task completion notification struct event notificationEvent_; /// File descriptors for pipe used for task completion notification. evutil_socket_t notificationPipeFDs_[2]; /// Actual IO Thread std::shared_ptr thread_; }; } } } // apache::thrift::server #endif // #ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TServerFramework.h0000644000000000000000000001542614303740367023464 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TSERVERFRAMEWORK_H_ #define _THRIFT_SERVER_TSERVERFRAMEWORK_H_ 1 #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace server { /** * TServerFramework provides a single consolidated processing loop for * servers. By having a single processing loop, behavior between servers * is more predictable and maintenance cost is lowered. Implementations * of TServerFramework must provide a method to deal with a client that * connects and one that disconnects. * * While this functionality could be rolled directly into TServer, and * probably should be, it would break the TServer interface contract so * to maintain backwards compatibility for third party servers, no TServers * were harmed in the making of this class. */ class TServerFramework : public TServer { public: TServerFramework( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory); TServerFramework( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory); TServerFramework( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory); TServerFramework( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory); ~TServerFramework() override; /** * Accept clients from the TServerTransport and add them for processing. * Call stop() on another thread to interrupt processing * and return control to the caller. * Post-conditions (return guarantees): * The serverTransport will be closed. */ void serve() override; /** * Interrupt serve() so that it meets post-conditions and returns. */ void stop() override; /** * Get the concurrent client limit. * \returns the concurrent client limit */ virtual int64_t getConcurrentClientLimit() const; /** * Get the number of currently connected clients. * \returns the number of currently connected clients */ virtual int64_t getConcurrentClientCount() const; /** * Get the highest number of concurrent clients. * \returns the highest number of concurrent clients */ virtual int64_t getConcurrentClientCountHWM() const; /** * Set the concurrent client limit. This can be changed while * the server is serving however it will not necessarily be * enforced until the next client is accepted and added. If the * limit is lowered below the number of connected clients, no * action is taken to disconnect the clients. * The default value used if this is not called is INT64_MAX. * \param[in] newLimit the new limit of concurrent clients * \throws std::invalid_argument if newLimit is less than 1 */ virtual void setConcurrentClientLimit(int64_t newLimit); protected: /** * A client has connected. The implementation is responsible for managing the * lifetime of the client object. This is called during the serve() thread, * therefore a failure to return quickly will result in new client connection * delays. * * \param[in] pClient the newly connected client */ virtual void onClientConnected(const std::shared_ptr& pClient) = 0; /** * A client has disconnected. * When called: * The server no longer tracks the client. * The client TTransport has already been closed. * The implementation must not delete the pointer. * * \param[in] pClient the disconnected client */ virtual void onClientDisconnected(TConnectedClient* pClient) = 0; private: /** * Common handling for new connected clients. Implements concurrent * client rate limiting after onClientConnected returns by blocking the * serve() thread if the limit has been reached. */ void newlyConnectedClient(const std::shared_ptr& pClient); /** * Smart pointer client deletion. * Calls onClientDisconnected and then deletes pClient. */ void disposeConnectedClient(TConnectedClient* pClient); /** * Monitor for limiting the number of concurrent clients. */ apache::thrift::concurrency::Monitor mon_; /** * The number of concurrent clients. */ int64_t clients_; /** * The high water mark of concurrent clients. */ int64_t hwm_; /** * The limit on the number of concurrent clients. */ int64_t limit_; }; } } } // apache::thrift::server #endif // #ifndef _THRIFT_SERVER_TSERVERFRAMEWORK_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TThreadedServer.h0000644000000000000000000001376614303740367023254 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ #define _THRIFT_SERVER_TTHREADEDSERVER_H_ 1 #include #include #include #include #include namespace apache { namespace thrift { namespace server { /** * Manage clients using threads - threads are created one for each client and are * released when the client disconnects. This server is used to make a dynamically * scalable server up to the concurrent connection limit. */ class TThreadedServer : public TServerFramework { public: TThreadedServer( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( new apache::thrift::concurrency::ThreadFactory(false))); TThreadedServer( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( new apache::thrift::concurrency::ThreadFactory(false))); TThreadedServer( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( new apache::thrift::concurrency::ThreadFactory(false))); TThreadedServer( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( new apache::thrift::concurrency::ThreadFactory(false))); ~TThreadedServer() override; /** * Post-conditions (return guarantees): * There will be no clients connected. */ void serve() override; protected: /** * Drain recently connected clients by joining their threads - this is done lazily because * we cannot do it inside the thread context that is disconnecting. */ virtual void drainDeadClients(); /** * Implementation of TServerFramework::onClientConnected */ void onClientConnected(const std::shared_ptr& pClient) override /* override */; /** * Implementation of TServerFramework::onClientDisconnected */ void onClientDisconnected(TConnectedClient *pClient) override /* override */; std::shared_ptr threadFactory_; /** * A helper wrapper used to wrap the client in something we can use to maintain * the lifetime of the connected client within a detached thread. We cannot simply * track the threads because a shared_ptr hangs on to the Runnable it is * passed, and TServerFramework requires the runnable (TConnectedClient) to be * destroyed in order to work properly. */ class TConnectedClientRunner : public apache::thrift::concurrency::Runnable { public: TConnectedClientRunner(const std::shared_ptr& pClient); ~TConnectedClientRunner() override; void run() override /* override */; private: std::shared_ptr pClient_; }; apache::thrift::concurrency::Monitor clientMonitor_; typedef std::map > ClientMap; /** * A map of active clients */ ClientMap activeClientMap_; /** * A map of clients that have disconnected but their threads have not been joined */ ClientMap deadClientMap_; }; } } } // apache::thrift::server #endif // #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TThreadedServer.cpp0000644000000000000000000001415514303740367023600 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include namespace apache { namespace thrift { namespace server { using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::Synchronized; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using std::make_shared; using std::shared_ptr; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; TThreadedServer::TThreadedServer(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory, const shared_ptr& threadFactory) : TServerFramework(processorFactory, serverTransport, transportFactory, protocolFactory), threadFactory_(threadFactory) { } TThreadedServer::TThreadedServer(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory, const shared_ptr& threadFactory) : TServerFramework(processor, serverTransport, transportFactory, protocolFactory), threadFactory_(threadFactory) { } TThreadedServer::TThreadedServer(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory, const shared_ptr& threadFactory) : TServerFramework(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory), threadFactory_(threadFactory) { } TThreadedServer::TThreadedServer(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory, const shared_ptr& threadFactory) : TServerFramework(processor, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory), threadFactory_(threadFactory) { } TThreadedServer::~TThreadedServer() = default; void TThreadedServer::serve() { TServerFramework::serve(); // Ensure post-condition of no active clients Synchronized s(clientMonitor_); while (!activeClientMap_.empty()) { clientMonitor_.wait(); } drainDeadClients(); } void TThreadedServer::drainDeadClients() { // we're in a monitor here while (!deadClientMap_.empty()) { auto it = deadClientMap_.begin(); it->second->join(); deadClientMap_.erase(it); } } void TThreadedServer::onClientConnected(const shared_ptr& pClient) { Synchronized sync(clientMonitor_); shared_ptr pRunnable = make_shared(pClient); shared_ptr pThread = threadFactory_->newThread(pRunnable); pRunnable->thread(pThread); activeClientMap_.insert(ClientMap::value_type(pClient.get(), pThread)); pThread->start(); } void TThreadedServer::onClientDisconnected(TConnectedClient* pClient) { Synchronized sync(clientMonitor_); drainDeadClients(); // use the outgoing thread to do some maintenance on our dead client backlog auto it = activeClientMap_.find(pClient); if (it != activeClientMap_.end()) { auto end = it; deadClientMap_.insert(it, ++end); activeClientMap_.erase(it); } if (activeClientMap_.empty()) { clientMonitor_.notify(); } } TThreadedServer::TConnectedClientRunner::TConnectedClientRunner(const shared_ptr& pClient) : pClient_(pClient) { } TThreadedServer::TConnectedClientRunner::~TConnectedClientRunner() = default; void TThreadedServer::TConnectedClientRunner::run() /* override */ { pClient_->run(); // Run the client pClient_.reset(); // The client is done - release it here rather than in the destructor for safety } } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/server/TSimpleServer.cpp0000644000000000000000000001066714303740367023315 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include namespace apache { namespace thrift { namespace server { using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; using std::shared_ptr; using std::string; TSimpleServer::TSimpleServer(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory) : TServerFramework(processorFactory, serverTransport, transportFactory, protocolFactory) { TServerFramework::setConcurrentClientLimit(1); } TSimpleServer::TSimpleServer(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory) : TServerFramework(processor, serverTransport, transportFactory, protocolFactory) { TServerFramework::setConcurrentClientLimit(1); } TSimpleServer::TSimpleServer(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory) : TServerFramework(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory) { TServerFramework::setConcurrentClientLimit(1); } TSimpleServer::TSimpleServer(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory) : TServerFramework(processor, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory) { TServerFramework::setConcurrentClientLimit(1); } TSimpleServer::~TSimpleServer() = default; /** * The main body of customized implementation for TSimpleServer is quite simple: * When a client connects, use the serve() thread to drive it to completion thus * blocking new connections. */ void TSimpleServer::onClientConnected(const shared_ptr& pClient) { pClient->run(); } /** * TSimpleServer does not track clients so there is nothing to do here. */ void TSimpleServer::onClientDisconnected(TConnectedClient*) { } /** * This makes little sense to the simple server because it is not capable * of having more than one client at a time, so we hide it. */ void TSimpleServer::setConcurrentClientLimit(int64_t) { } } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/server/TConnectedClient.h0000644000000000000000000000744214303740367023400 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TCONNECTEDCLIENT_H_ #define _THRIFT_SERVER_TCONNECTEDCLIENT_H_ 1 #include #include #include #include #include namespace apache { namespace thrift { namespace server { /** * This represents a client connected to a TServer. The * processing loop for a client must provide some required * functionality common to all implementations so it is * encapsulated here. */ class TConnectedClient : public apache::thrift::concurrency::Runnable { public: /** * Constructor. * * @param[in] processor the TProcessor * @param[in] inputProtocol the input TProtocol * @param[in] outputProtocol the output TProtocol * @param[in] eventHandler the server event handler * @param[in] client the TTransport representing the client */ TConnectedClient( const std::shared_ptr& processor, const std::shared_ptr& inputProtocol, const std::shared_ptr& outputProtocol, const std::shared_ptr& eventHandler, const std::shared_ptr& client); /** * Destructor. */ ~TConnectedClient() override; /** * Drive the client until it is done. * The client processing loop is: * * [optional] call eventHandler->createContext once * [optional] call eventHandler->processContext per request * call processor->process per request * handle expected transport exceptions: * END_OF_FILE means the client is gone * INTERRUPTED means the client was interrupted * by TServerTransport::interruptChildren() * handle unexpected transport exceptions by logging * handle standard exceptions by logging * handle unexpected exceptions by logging * cleanup() */ void run() override /* override */; protected: /** * Cleanup after a client. This happens if the client disconnects, * or if the server is stopped, or if an exception occurs. * * The cleanup processing is: * [optional] call eventHandler->deleteContext once * close the inputProtocol's TTransport * close the outputProtocol's TTransport * close the client */ virtual void cleanup(); private: std::shared_ptr processor_; std::shared_ptr inputProtocol_; std::shared_ptr outputProtocol_; std::shared_ptr eventHandler_; std::shared_ptr client_; /** * Context acquired from the eventHandler_ if one exists. */ void* opaqueContext_; }; } } } #endif // #ifndef _THRIFT_SERVER_TCONNECTEDCLIENT_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TConnectedClient.cpp0000644000000000000000000000763014303740367023732 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include namespace apache { namespace thrift { namespace server { using apache::thrift::TProcessor; using apache::thrift::protocol::TProtocol; using apache::thrift::server::TServerEventHandler; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using std::shared_ptr; using std::string; TConnectedClient::TConnectedClient(const shared_ptr& processor, const shared_ptr& inputProtocol, const shared_ptr& outputProtocol, const shared_ptr& eventHandler, const shared_ptr& client) : processor_(processor), inputProtocol_(inputProtocol), outputProtocol_(outputProtocol), eventHandler_(eventHandler), client_(client), opaqueContext_(nullptr) { } TConnectedClient::~TConnectedClient() = default; void TConnectedClient::run() { if (eventHandler_) { opaqueContext_ = eventHandler_->createContext(inputProtocol_, outputProtocol_); } for (bool done = false; !done;) { if (eventHandler_) { eventHandler_->processContext(opaqueContext_, client_); } try { if (!processor_->process(inputProtocol_, outputProtocol_, opaqueContext_)) { break; } } catch (const TTransportException& ttx) { switch (ttx.getType()) { case TTransportException::END_OF_FILE: case TTransportException::INTERRUPTED: case TTransportException::TIMED_OUT: // Client disconnected or was interrupted or did not respond within the receive timeout. // No logging needed. Done. done = true; break; default: { // All other transport exceptions are logged. // State of connection is unknown. Done. string errStr = string("TConnectedClient died: ") + ttx.what(); GlobalOutput(errStr.c_str()); done = true; break; } } } catch (const TException& tex) { string errStr = string("TConnectedClient processing exception: ") + tex.what(); GlobalOutput(errStr.c_str()); // Disconnect from client, because we could not process the message. done = true; } } cleanup(); } void TConnectedClient::cleanup() { if (eventHandler_) { eventHandler_->deleteContext(opaqueContext_, inputProtocol_, outputProtocol_); } try { inputProtocol_->getTransport()->close(); } catch (const TTransportException& ttx) { string errStr = string("TConnectedClient input close failed: ") + ttx.what(); GlobalOutput(errStr.c_str()); } try { outputProtocol_->getTransport()->close(); } catch (const TTransportException& ttx) { string errStr = string("TConnectedClient output close failed: ") + ttx.what(); GlobalOutput(errStr.c_str()); } try { client_->close(); } catch (const TTransportException& ttx) { string errStr = string("TConnectedClient client close failed: ") + ttx.what(); GlobalOutput(errStr.c_str()); } } } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/server/TNonblockingServer.cpp0000644000000000000000000013427014303740367024324 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #ifdef HAVE_POLL_H #include #elif HAVE_SYS_POLL_H #include #elif HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NETINET_IN_H #include #include #endif #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #include #ifdef HAVE_SCHED_H #include #endif #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX #endif #ifdef HAVE_INTTYPES_H #include #endif #ifdef HAVE_STDINT_H #include #endif namespace apache { namespace thrift { namespace server { using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::concurrency; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransportException; using std::shared_ptr; /// Three states for sockets: recv frame size, recv data, and send mode enum TSocketState { SOCKET_RECV_FRAMING, SOCKET_RECV, SOCKET_SEND }; /** * Five states for the nonblocking server: * 1) initialize * 2) read 4 byte frame size * 3) read frame of data * 4) send back data (if any) * 5) force immediate connection close */ enum TAppState { APP_INIT, APP_READ_FRAME_SIZE, APP_READ_REQUEST, APP_WAIT_TASK, APP_SEND_RESULT, APP_CLOSE_CONNECTION }; /** * Represents a connection that is handled via libevent. This connection * essentially encapsulates a socket that has some associated libevent state. */ class TNonblockingServer::TConnection { private: /// Server IO Thread handling this connection TNonblockingIOThread* ioThread_; /// Server handle TNonblockingServer* server_; /// TProcessor std::shared_ptr processor_; /// Object wrapping network socket std::shared_ptr tSocket_; /// Libevent object struct event event_; /// Libevent flags short eventFlags_; /// Socket mode TSocketState socketState_; /// Application state TAppState appState_; /// How much data needed to read uint32_t readWant_; /// Where in the read buffer are we uint32_t readBufferPos_; /// Read buffer uint8_t* readBuffer_; /// Read buffer size uint32_t readBufferSize_; /// Write buffer uint8_t* writeBuffer_; /// Write buffer size uint32_t writeBufferSize_; /// How far through writing are we? uint32_t writeBufferPos_; /// Largest size of write buffer seen since buffer was constructed size_t largestWriteBufferSize_; /// Count of the number of calls for use with getResizeBufferEveryN(). int32_t callsForResize_; /// Transport to read from std::shared_ptr inputTransport_; /// Transport that processor writes to std::shared_ptr outputTransport_; /// extra transport generated by transport factory (e.g. BufferedRouterTransport) std::shared_ptr factoryInputTransport_; std::shared_ptr factoryOutputTransport_; /// Protocol decoder std::shared_ptr inputProtocol_; /// Protocol encoder std::shared_ptr outputProtocol_; /// Server event handler, if any std::shared_ptr serverEventHandler_; /// Thrift call context, if any void* connectionContext_; /// Go into read mode void setRead() { setFlags(EV_READ | EV_PERSIST); } /// Go into write mode void setWrite() { setFlags(EV_WRITE | EV_PERSIST); } /// Set socket idle void setIdle() { setFlags(0); } /** * Set event flags for this connection. * * @param eventFlags flags we pass to libevent for the connection. */ void setFlags(short eventFlags); /** * Libevent handler called (via our static wrapper) when the connection * socket had something happen. Rather than use the flags libevent passed, * we use the connection state to determine whether we need to read or * write the socket. */ void workSocket(); public: class Task; /// Constructor TConnection(std::shared_ptr socket, TNonblockingIOThread* ioThread) { readBuffer_ = nullptr; readBufferSize_ = 0; ioThread_ = ioThread; server_ = ioThread->getServer(); // Allocate input and output transports these only need to be allocated // once per TConnection (they don't need to be reallocated on init() call) inputTransport_.reset(new TMemoryBuffer(readBuffer_, readBufferSize_)); outputTransport_.reset( new TMemoryBuffer(static_cast(server_->getWriteBufferDefaultSize()))); tSocket_ = socket; init(ioThread); } ~TConnection() { std::free(readBuffer_); } /// Close this connection and free or reset its resources. void close(); /** * Check buffers against any size limits and shrink it if exceeded. * * @param readLimit we reduce read buffer size to this (if nonzero). * @param writeLimit if nonzero and write buffer is larger, replace it. */ void checkIdleBufferMemLimit(size_t readLimit, size_t writeLimit); /// Initialize void init(TNonblockingIOThread* ioThread); /// set socket for connection void setSocket(std::shared_ptr socket); /** * This is called when the application transitions from one state into * another. This means that it has finished writing the data that it needed * to, or finished receiving the data that it needed to. */ void transition(); /** * C-callable event handler for connection events. Provides a callback * that libevent can understand which invokes connection_->workSocket(). * * @param fd the descriptor the event occurred on. * @param which the flags associated with the event. * @param v void* callback arg where we placed TConnection's "this". */ static void eventHandler(evutil_socket_t fd, short /* which */, void* v) { assert(fd == static_cast(((TConnection*)v)->getTSocket()->getSocketFD())); ((TConnection*)v)->workSocket(); } /** * Notification to server that processing has ended on this request. * Can be called either when processing is completed or when a waiting * task has been preemptively terminated (on overload). * * Don't call this from the IO thread itself. * * @return true if successful, false if unable to notify (check THRIFT_GET_SOCKET_ERROR). */ bool notifyIOThread() { return ioThread_->notify(this); } /* * Returns the number of this connection's currently assigned IO * thread. */ int getIOThreadNumber() const { return ioThread_->getThreadNumber(); } /// Force connection shutdown for this connection. void forceClose() { appState_ = APP_CLOSE_CONNECTION; if (!notifyIOThread()) { server_->decrementActiveProcessors(); close(); throw TException("TConnection::forceClose: failed write on notify pipe"); } } /// return the server this connection was initialized for. TNonblockingServer* getServer() const { return server_; } /// get state of connection. TAppState getState() const { return appState_; } /// return the TSocket transport wrapping this network connection std::shared_ptr getTSocket() const { return tSocket_; } /// return the server event handler if any std::shared_ptr getServerEventHandler() { return serverEventHandler_; } /// return the Thrift connection context if any void* getConnectionContext() { return connectionContext_; } }; class TNonblockingServer::TConnection::Task : public Runnable { public: Task(std::shared_ptr processor, std::shared_ptr input, std::shared_ptr output, TConnection* connection) : processor_(processor), input_(input), output_(output), connection_(connection), serverEventHandler_(connection_->getServerEventHandler()), connectionContext_(connection_->getConnectionContext()) {} void run() override { try { for (;;) { if (serverEventHandler_) { serverEventHandler_->processContext(connectionContext_, connection_->getTSocket()); } if (!processor_->process(input_, output_, connectionContext_) || !input_->getTransport()->peek()) { break; } } } catch (const TTransportException& ttx) { GlobalOutput.printf("TNonblockingServer: client died: %s", ttx.what()); } catch (const std::bad_alloc&) { GlobalOutput("TNonblockingServer: caught bad_alloc exception."); exit(1); } catch (const std::exception& x) { GlobalOutput.printf("TNonblockingServer: process() exception: %s: %s", typeid(x).name(), x.what()); } catch (...) { GlobalOutput.printf("TNonblockingServer: unknown exception while processing."); } // Signal completion back to the libevent thread via a pipe if (!connection_->notifyIOThread()) { GlobalOutput.printf("TNonblockingServer: failed to notifyIOThread, closing."); connection_->server_->decrementActiveProcessors(); connection_->close(); throw TException("TNonblockingServer::Task::run: failed write on notify pipe"); } } TConnection* getTConnection() { return connection_; } private: std::shared_ptr processor_; std::shared_ptr input_; std::shared_ptr output_; TConnection* connection_; std::shared_ptr serverEventHandler_; void* connectionContext_; }; void TNonblockingServer::TConnection::init(TNonblockingIOThread* ioThread) { ioThread_ = ioThread; server_ = ioThread->getServer(); appState_ = APP_INIT; eventFlags_ = 0; readBufferPos_ = 0; readWant_ = 0; writeBuffer_ = nullptr; writeBufferSize_ = 0; writeBufferPos_ = 0; largestWriteBufferSize_ = 0; socketState_ = SOCKET_RECV_FRAMING; callsForResize_ = 0; // get input/transports factoryInputTransport_ = server_->getInputTransportFactory()->getTransport(inputTransport_); factoryOutputTransport_ = server_->getOutputTransportFactory()->getTransport(outputTransport_); // Create protocol if (server_->getHeaderTransport()) { inputProtocol_ = server_->getInputProtocolFactory()->getProtocol(factoryInputTransport_, factoryOutputTransport_); outputProtocol_ = inputProtocol_; } else { inputProtocol_ = server_->getInputProtocolFactory()->getProtocol(factoryInputTransport_); outputProtocol_ = server_->getOutputProtocolFactory()->getProtocol(factoryOutputTransport_); } // Set up for any server event handler serverEventHandler_ = server_->getEventHandler(); if (serverEventHandler_) { connectionContext_ = serverEventHandler_->createContext(inputProtocol_, outputProtocol_); } else { connectionContext_ = nullptr; } // Get the processor processor_ = server_->getProcessor(inputProtocol_, outputProtocol_, tSocket_); } void TNonblockingServer::TConnection::setSocket(std::shared_ptr socket) { tSocket_ = socket; } void TNonblockingServer::TConnection::workSocket() { while (true) { int got = 0, left = 0, sent = 0; uint32_t fetch = 0; switch (socketState_) { case SOCKET_RECV_FRAMING: union { uint8_t buf[sizeof(uint32_t)]; uint32_t size; } framing; // if we've already received some bytes we kept them here framing.size = readWant_; // determine size of this frame try { // Read from the socket fetch = tSocket_->read(&framing.buf[readBufferPos_], uint32_t(sizeof(framing.size) - readBufferPos_)); if (fetch == 0) { // Whenever we get here it means a remote disconnect close(); return; } readBufferPos_ += fetch; } catch (TTransportException& te) { //In Nonblocking SSLSocket some operations need to be retried again. //Current approach is parsing exception message, but a better solution needs to be investigated. if(!strstr(te.what(), "retry")) { GlobalOutput.printf("TConnection::workSocket(): %s", te.what()); close(); return; } } if (readBufferPos_ < sizeof(framing.size)) { // more needed before frame size is known -- save what we have so far readWant_ = framing.size; return; } readWant_ = ntohl(framing.size); if (readWant_ > server_->getMaxFrameSize()) { // Don't allow giant frame sizes. This prevents bad clients from // causing us to try and allocate a giant buffer. GlobalOutput.printf( "TNonblockingServer: frame size too large " "(%" PRIu32 " > %" PRIu64 ") from client %s. " "Remote side not using TFramedTransport?", readWant_, (uint64_t)server_->getMaxFrameSize(), tSocket_->getSocketInfo().c_str()); close(); return; } // size known; now get the rest of the frame transition(); // If the socket has more data than the frame header, continue to work on it. This is not strictly necessary for // regular sockets, because if there is more data, libevent will fire the event handler registered for read // readiness, which will in turn call workSocket(). However, some socket types (such as TSSLSocket) may have the // data sitting in their internal buffers and from libevent's perspective, there is no further data available. In // that case, not trying another processing cycle here would result in a hang as we will never get to work the socket, // despite having more data. if (tSocket_->hasPendingDataToRead()) { continue; } return; case SOCKET_RECV: // It is an error to be in this state if we already have all the data if (!(readBufferPos_ < readWant_)) { GlobalOutput.printf("TNonblockingServer: frame size too short"); close(); return; } try { // Read from the socket fetch = readWant_ - readBufferPos_; got = tSocket_->read(readBuffer_ + readBufferPos_, fetch); } catch (TTransportException& te) { //In Nonblocking SSLSocket some operations need to be retried again. //Current approach is parsing exception message, but a better solution needs to be investigated. if(!strstr(te.what(), "retry")) { GlobalOutput.printf("TConnection::workSocket(): %s", te.what()); close(); } return; } if (got > 0) { // Move along in the buffer readBufferPos_ += got; // Check that we did not overdo it assert(readBufferPos_ <= readWant_); // We are done reading, move onto the next state if (readBufferPos_ == readWant_) { transition(); if (socketState_ == SOCKET_RECV_FRAMING && tSocket_->hasPendingDataToRead()) { continue; } } return; } // Whenever we get down here it means a remote disconnect close(); return; case SOCKET_SEND: // Should never have position past size assert(writeBufferPos_ <= writeBufferSize_); // If there is no data to send, then let us move on if (writeBufferPos_ == writeBufferSize_) { GlobalOutput("WARNING: Send state with no data to send"); transition(); return; } try { left = writeBufferSize_ - writeBufferPos_; sent = tSocket_->write_partial(writeBuffer_ + writeBufferPos_, left); } catch (TTransportException& te) { GlobalOutput.printf("TConnection::workSocket(): %s ", te.what()); close(); return; } writeBufferPos_ += sent; // Did we overdo it? assert(writeBufferPos_ <= writeBufferSize_); // We are done! if (writeBufferPos_ == writeBufferSize_) { transition(); } return; default: GlobalOutput.printf("Unexpected Socket State %d", socketState_); assert(0); return; } } } bool TNonblockingServer::getHeaderTransport() { // Currently if there is no output protocol factory, // we assume header transport (without having to create // a new transport and check) return getOutputProtocolFactory() == nullptr; } /** * This is called when the application transitions from one state into * another. This means that it has finished writing the data that it needed * to, or finished receiving the data that it needed to. */ void TNonblockingServer::TConnection::transition() { // ensure this connection is active right now assert(ioThread_); assert(server_); // Switch upon the state that we are currently in and move to a new state switch (appState_) { case APP_READ_REQUEST: // We are done reading the request, package the read buffer into transport // and get back some data from the dispatch function if (server_->getHeaderTransport()) { inputTransport_->resetBuffer(readBuffer_, readBufferPos_); outputTransport_->resetBuffer(); } else { // We saved room for the framing size in case header transport needed it, // but just skip it for the non-header case inputTransport_->resetBuffer(readBuffer_ + 4, readBufferPos_ - 4); outputTransport_->resetBuffer(); // Prepend four bytes of blank space to the buffer so we can // write the frame size there later. outputTransport_->getWritePtr(4); outputTransport_->wroteBytes(4); } server_->incrementActiveProcessors(); if (server_->isThreadPoolProcessing()) { // We are setting up a Task to do this work and we will wait on it // Create task and dispatch to the thread manager std::shared_ptr task = std::shared_ptr( new Task(processor_, inputProtocol_, outputProtocol_, this)); // The application is now waiting on the task to finish appState_ = APP_WAIT_TASK; // Set this connection idle so that libevent doesn't process more // data on it while we're still waiting for the threadmanager to // finish this task setIdle(); try { server_->addTask(task); } catch (IllegalStateException& ise) { // The ThreadManager is not ready to handle any more tasks (it's probably shutting down). GlobalOutput.printf("IllegalStateException: Server::process() %s", ise.what()); server_->decrementActiveProcessors(); close(); } catch (TimedOutException& to) { GlobalOutput.printf("[ERROR] TimedOutException: Server::process() %s", to.what()); server_->decrementActiveProcessors(); close(); } return; } else { try { if (serverEventHandler_) { serverEventHandler_->processContext(connectionContext_, getTSocket()); } // Invoke the processor processor_->process(inputProtocol_, outputProtocol_, connectionContext_); } catch (const TTransportException& ttx) { GlobalOutput.printf( "TNonblockingServer transport error in " "process(): %s", ttx.what()); server_->decrementActiveProcessors(); close(); return; } catch (const std::exception& x) { GlobalOutput.printf("Server::process() uncaught exception: %s: %s", typeid(x).name(), x.what()); server_->decrementActiveProcessors(); close(); return; } catch (...) { GlobalOutput.printf("Server::process() unknown exception"); server_->decrementActiveProcessors(); close(); return; } } // fallthrough // Intentionally fall through here, the call to process has written into // the writeBuffer_ case APP_WAIT_TASK: // We have now finished processing a task and the result has been written // into the outputTransport_, so we grab its contents and place them into // the writeBuffer_ for actual writing by the libevent thread server_->decrementActiveProcessors(); // Get the result of the operation outputTransport_->getBuffer(&writeBuffer_, &writeBufferSize_); // If the function call generated return data, then move into the send // state and get going // 4 bytes were reserved for frame size if (writeBufferSize_ > 4) { // Move into write state writeBufferPos_ = 0; socketState_ = SOCKET_SEND; // Put the frame size into the write buffer auto frameSize = (int32_t)htonl(writeBufferSize_ - 4); memcpy(writeBuffer_, &frameSize, 4); // Socket into write mode appState_ = APP_SEND_RESULT; setWrite(); return; } // In this case, the request was oneway and we should fall through // right back into the read frame header state goto LABEL_APP_INIT; case APP_SEND_RESULT: // it's now safe to perform buffer size housekeeping. if (writeBufferSize_ > largestWriteBufferSize_) { largestWriteBufferSize_ = writeBufferSize_; } if (server_->getResizeBufferEveryN() > 0 && ++callsForResize_ >= server_->getResizeBufferEveryN()) { checkIdleBufferMemLimit(server_->getIdleReadBufferLimit(), server_->getIdleWriteBufferLimit()); callsForResize_ = 0; } // fallthrough // N.B.: We also intentionally fall through here into the INIT state! LABEL_APP_INIT: case APP_INIT: // Clear write buffer variables writeBuffer_ = nullptr; writeBufferPos_ = 0; writeBufferSize_ = 0; // Into read4 state we go socketState_ = SOCKET_RECV_FRAMING; appState_ = APP_READ_FRAME_SIZE; readBufferPos_ = 0; // Register read event setRead(); return; case APP_READ_FRAME_SIZE: readWant_ += 4; // We just read the request length // Double the buffer size until it is big enough if (readWant_ > readBufferSize_) { if (readBufferSize_ == 0) { readBufferSize_ = 1; } uint32_t newSize = readBufferSize_; while (readWant_ > newSize) { newSize *= 2; } auto* newBuffer = (uint8_t*)std::realloc(readBuffer_, newSize); if (newBuffer == nullptr) { // nothing else to be done... throw std::bad_alloc(); } readBuffer_ = newBuffer; readBufferSize_ = newSize; } readBufferPos_ = 4; *((uint32_t*)readBuffer_) = htonl(readWant_ - 4); // Move into read request state socketState_ = SOCKET_RECV; appState_ = APP_READ_REQUEST; return; case APP_CLOSE_CONNECTION: server_->decrementActiveProcessors(); close(); return; default: GlobalOutput.printf("Unexpected Application State %d", appState_); assert(0); } } void TNonblockingServer::TConnection::setFlags(short eventFlags) { // Catch the do nothing case if (eventFlags_ == eventFlags) { return; } // Delete a previously existing event if (eventFlags_ && event_del(&event_) == -1) { GlobalOutput.perror("TConnection::setFlags() event_del", THRIFT_GET_SOCKET_ERROR); return; } // Update in memory structure eventFlags_ = eventFlags; // Do not call event_set if there are no flags if (!eventFlags_) { return; } /* * event_set: * * Prepares the event structure &event to be used in future calls to * event_add() and event_del(). The event will be prepared to call the * eventHandler using the 'sock' file descriptor to monitor events. * * The events can be either EV_READ, EV_WRITE, or both, indicating * that an application can read or write from the file respectively without * blocking. * * The eventHandler will be called with the file descriptor that triggered * the event and the type of event which will be one of: EV_TIMEOUT, * EV_SIGNAL, EV_READ, EV_WRITE. * * The additional flag EV_PERSIST makes an event_add() persistent until * event_del() has been called. * * Once initialized, the &event struct can be used repeatedly with * event_add() and event_del() and does not need to be reinitialized unless * the eventHandler and/or the argument to it are to be changed. However, * when an ev structure has been added to libevent using event_add() the * structure must persist until the event occurs (assuming EV_PERSIST * is not set) or is removed using event_del(). You may not reuse the same * ev structure for multiple monitored descriptors; each descriptor needs * its own ev. */ event_set(&event_, tSocket_->getSocketFD(), eventFlags_, TConnection::eventHandler, this); event_base_set(ioThread_->getEventBase(), &event_); // Add the event if (event_add(&event_, nullptr) == -1) { GlobalOutput.perror("TConnection::setFlags(): could not event_add", THRIFT_GET_SOCKET_ERROR); } } /** * Closes a connection */ void TNonblockingServer::TConnection::close() { setIdle(); if (serverEventHandler_) { serverEventHandler_->deleteContext(connectionContext_, inputProtocol_, outputProtocol_); } ioThread_ = nullptr; // Close the socket tSocket_->close(); // close any factory produced transports factoryInputTransport_->close(); factoryOutputTransport_->close(); // release processor and handler processor_.reset(); // Give this object back to the server that owns it server_->returnConnection(this); } void TNonblockingServer::TConnection::checkIdleBufferMemLimit(size_t readLimit, size_t writeLimit) { if (readLimit > 0 && readBufferSize_ > readLimit) { free(readBuffer_); readBuffer_ = nullptr; readBufferSize_ = 0; } if (writeLimit > 0 && largestWriteBufferSize_ > writeLimit) { // just start over outputTransport_->resetBuffer(static_cast(server_->getWriteBufferDefaultSize())); largestWriteBufferSize_ = 0; } } TNonblockingServer::~TNonblockingServer() { // Close any active connections (moves them to the idle connection stack) while (activeConnections_.size()) { activeConnections_.front()->close(); } // Clean up unused TConnection objects in connectionStack_ while (!connectionStack_.empty()) { TConnection* connection = connectionStack_.top(); connectionStack_.pop(); delete connection; } // The TNonblockingIOThread objects have shared_ptrs to the Thread // objects and the Thread objects have shared_ptrs to the TNonblockingIOThread // objects (as runnable) so these objects will never deallocate without help. while (!ioThreads_.empty()) { std::shared_ptr iot = ioThreads_.back(); ioThreads_.pop_back(); iot->setThread(std::shared_ptr()); } } /** * Creates a new connection either by reusing an object off the stack or * by allocating a new one entirely */ TNonblockingServer::TConnection* TNonblockingServer::createConnection(std::shared_ptr socket) { // Check the stack Guard g(connMutex_); // pick an IO thread to handle this connection -- currently round robin assert(nextIOThread_ < ioThreads_.size()); int selectedThreadIdx = nextIOThread_; nextIOThread_ = static_cast((nextIOThread_ + 1) % ioThreads_.size()); TNonblockingIOThread* ioThread = ioThreads_[selectedThreadIdx].get(); // Check the connection stack to see if we can re-use TConnection* result = nullptr; if (connectionStack_.empty()) { result = new TConnection(socket, ioThread); ++numTConnections_; } else { result = connectionStack_.top(); connectionStack_.pop(); result->setSocket(socket); result->init(ioThread); } activeConnections_.push_back(result); return result; } /** * Returns a connection to the stack */ void TNonblockingServer::returnConnection(TConnection* connection) { Guard g(connMutex_); activeConnections_.erase(std::remove(activeConnections_.begin(), activeConnections_.end(), connection), activeConnections_.end()); if (connectionStackLimit_ && (connectionStack_.size() >= connectionStackLimit_)) { delete connection; --numTConnections_; } else { connection->checkIdleBufferMemLimit(idleReadBufferLimit_, idleWriteBufferLimit_); connectionStack_.push(connection); } } /** * Server socket had something happen. We accept all waiting client * connections on fd and assign TConnection objects to handle those requests. */ void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which) { (void)which; // Make sure that libevent didn't mess up the socket handles assert(fd == serverSocket_); // Going to accept a new client socket std::shared_ptr clientSocket; clientSocket = serverTransport_->accept(); if (clientSocket) { // If we're overloaded, take action here if (overloadAction_ != T_OVERLOAD_NO_ACTION && serverOverloaded()) { Guard g(connMutex_); nConnectionsDropped_++; nTotalConnectionsDropped_++; if (overloadAction_ == T_OVERLOAD_CLOSE_ON_ACCEPT) { clientSocket->close(); return; } else if (overloadAction_ == T_OVERLOAD_DRAIN_TASK_QUEUE) { if (!drainPendingTask()) { // Nothing left to discard, so we drop connection instead. clientSocket->close(); return; } } } // Create a new TConnection for this client socket. TConnection* clientConnection = createConnection(clientSocket); // Fail fast if we could not create a TConnection object if (clientConnection == nullptr) { GlobalOutput.printf("thriftServerEventHandler: failed TConnection factory"); clientSocket->close(); return; } /* * Either notify the ioThread that is assigned this connection to * start processing, or if it is us, we'll just ask this * connection to do its initial state change here. * * (We need to avoid writing to our own notification pipe, to * avoid possible deadlocks if the pipe is full.) * * The IO thread #0 is the only one that handles these listen * events, so unless the connection has been assigned to thread #0 * we know it's not on our thread. */ if (clientConnection->getIOThreadNumber() == 0) { clientConnection->transition(); } else { if (!clientConnection->notifyIOThread()) { GlobalOutput.perror("[ERROR] notifyIOThread failed on fresh connection, closing", errno); clientConnection->close(); } } } } /** * Creates a socket to listen on and binds it to the local port. */ void TNonblockingServer::createAndListenOnSocket() { serverTransport_->listen(); serverSocket_ = serverTransport_->getSocketFD(); } void TNonblockingServer::setThreadManager(std::shared_ptr threadManager) { threadManager_ = threadManager; if (threadManager) { threadManager->setExpireCallback( std::bind(&TNonblockingServer::expireClose, this, std::placeholders::_1)); threadPoolProcessing_ = true; } else { threadPoolProcessing_ = false; } } bool TNonblockingServer::serverOverloaded() { size_t activeConnections = numTConnections_ - connectionStack_.size(); if (numActiveProcessors_ > maxActiveProcessors_ || activeConnections > maxConnections_) { if (!overloaded_) { GlobalOutput.printf("TNonblockingServer: overload condition begun."); overloaded_ = true; } } else { if (overloaded_ && (numActiveProcessors_ <= overloadHysteresis_ * maxActiveProcessors_) && (activeConnections <= overloadHysteresis_ * maxConnections_)) { GlobalOutput.printf( "TNonblockingServer: overload ended; " "%u dropped (%llu total)", nConnectionsDropped_, nTotalConnectionsDropped_); nConnectionsDropped_ = 0; overloaded_ = false; } } return overloaded_; } bool TNonblockingServer::drainPendingTask() { if (threadManager_) { std::shared_ptr task = threadManager_->removeNextPending(); if (task) { TConnection* connection = static_cast(task.get())->getTConnection(); assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK); connection->forceClose(); return true; } } return false; } void TNonblockingServer::expireClose(std::shared_ptr task) { TConnection* connection = static_cast(task.get())->getTConnection(); assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK); connection->forceClose(); } void TNonblockingServer::stop() { // Breaks the event loop in all threads so that they end ASAP. for (auto & ioThread : ioThreads_) { ioThread->stop(); } } void TNonblockingServer::registerEvents(event_base* user_event_base) { userEventBase_ = user_event_base; // init listen socket if (serverSocket_ == THRIFT_INVALID_SOCKET) createAndListenOnSocket(); // set up the IO threads assert(ioThreads_.empty()); if (!numIOThreads_) { numIOThreads_ = DEFAULT_IO_THREADS; } // User-provided event-base doesn't works for multi-threaded servers assert(numIOThreads_ == 1 || !userEventBase_); for (uint32_t id = 0; id < numIOThreads_; ++id) { // the first IO thread also does the listening on server socket THRIFT_SOCKET listenFd = (id == 0 ? serverSocket_ : THRIFT_INVALID_SOCKET); shared_ptr thread( new TNonblockingIOThread(this, id, listenFd, useHighPriorityIOThreads_)); ioThreads_.push_back(thread); } // Notify handler of the preServe event if (eventHandler_) { eventHandler_->preServe(); } // Start all of our helper IO threads. Note that the threads run forever, // only terminating if stop() is called. assert(ioThreads_.size() == numIOThreads_); assert(ioThreads_.size() > 0); GlobalOutput.printf("TNonblockingServer: Serving with %d io threads.", ioThreads_.size()); // Launch all the secondary IO threads in separate threads if (ioThreads_.size() > 1) { ioThreadFactory_.reset(new ThreadFactory( false // detached )); assert(ioThreadFactory_.get()); // intentionally starting at thread 1, not 0 for (uint32_t i = 1; i < ioThreads_.size(); ++i) { shared_ptr thread = ioThreadFactory_->newThread(ioThreads_[i]); ioThreads_[i]->setThread(thread); thread->start(); } } // Register the events for the primary (listener) IO thread ioThreads_[0]->registerEvents(); } /** * Main workhorse function, starts up the server listening on a port and * loops over the libevent handler. */ void TNonblockingServer::serve() { if (ioThreads_.empty()) registerEvents(nullptr); // Run the primary (listener) IO thread loop in our main thread; this will // only return when the server is shutting down. ioThreads_[0]->run(); // Ensure all threads are finished before exiting serve() for (uint32_t i = 0; i < ioThreads_.size(); ++i) { ioThreads_[i]->join(); GlobalOutput.printf("TNonblocking: join done for IO thread #%d", i); } } TNonblockingIOThread::TNonblockingIOThread(TNonblockingServer* server, int number, THRIFT_SOCKET listenSocket, bool useHighPriority) : server_(server), number_(number), threadId_{}, listenSocket_(listenSocket), useHighPriority_(useHighPriority), eventBase_(nullptr), ownEventBase_(false), serverEvent_{}, notificationEvent_{} { notificationPipeFDs_[0] = -1; notificationPipeFDs_[1] = -1; } TNonblockingIOThread::~TNonblockingIOThread() { // make sure our associated thread is fully finished join(); if (eventBase_ && ownEventBase_) { event_base_free(eventBase_); ownEventBase_ = false; } if (listenSocket_ != THRIFT_INVALID_SOCKET) { if (0 != ::THRIFT_CLOSESOCKET(listenSocket_)) { GlobalOutput.perror("TNonblockingIOThread listenSocket_ close(): ", THRIFT_GET_SOCKET_ERROR); } listenSocket_ = THRIFT_INVALID_SOCKET; } for (auto notificationPipeFD : notificationPipeFDs_) { if (notificationPipeFD >= 0) { if (0 != ::THRIFT_CLOSESOCKET(notificationPipeFD)) { GlobalOutput.perror("TNonblockingIOThread notificationPipe close(): ", THRIFT_GET_SOCKET_ERROR); } notificationPipeFD = THRIFT_INVALID_SOCKET; } } } void TNonblockingIOThread::createNotificationPipe() { if (evutil_socketpair(AF_LOCAL, SOCK_STREAM, 0, notificationPipeFDs_) == -1) { GlobalOutput.perror("TNonblockingServer::createNotificationPipe ", EVUTIL_SOCKET_ERROR()); throw TException("can't create notification pipe"); } if (evutil_make_socket_nonblocking(notificationPipeFDs_[0]) < 0 || evutil_make_socket_nonblocking(notificationPipeFDs_[1]) < 0) { ::THRIFT_CLOSESOCKET(notificationPipeFDs_[0]); ::THRIFT_CLOSESOCKET(notificationPipeFDs_[1]); throw TException("TNonblockingServer::createNotificationPipe() THRIFT_O_NONBLOCK"); } for (auto notificationPipeFD : notificationPipeFDs_) { #if LIBEVENT_VERSION_NUMBER < 0x02000000 int flags; if ((flags = THRIFT_FCNTL(notificationPipeFD, F_GETFD, 0)) < 0 || THRIFT_FCNTL(notificationPipeFD, F_SETFD, flags | FD_CLOEXEC) < 0) { #else if (evutil_make_socket_closeonexec(notificationPipeFD) < 0) { #endif ::THRIFT_CLOSESOCKET(notificationPipeFDs_[0]); ::THRIFT_CLOSESOCKET(notificationPipeFDs_[1]); throw TException( "TNonblockingServer::createNotificationPipe() " "FD_CLOEXEC"); } } } /** * Register the core libevent events onto the proper base. */ void TNonblockingIOThread::registerEvents() { threadId_ = Thread::get_current(); assert(eventBase_ == nullptr); eventBase_ = getServer()->getUserEventBase(); if (eventBase_ == nullptr) { eventBase_ = event_base_new(); ownEventBase_ = true; } // Print some libevent stats if (number_ == 0) { GlobalOutput.printf("TNonblockingServer: using libevent %s method %s", event_get_version(), event_base_get_method(eventBase_)); } if (listenSocket_ != THRIFT_INVALID_SOCKET) { // Register the server event event_set(&serverEvent_, listenSocket_, EV_READ | EV_PERSIST, TNonblockingIOThread::listenHandler, server_); event_base_set(eventBase_, &serverEvent_); // Add the event and start up the server if (-1 == event_add(&serverEvent_, nullptr)) { throw TException( "TNonblockingServer::serve(): " "event_add() failed on server listen event"); } GlobalOutput.printf("TNonblocking: IO thread #%d registered for listen.", number_); } createNotificationPipe(); // Create an event to be notified when a task finishes event_set(¬ificationEvent_, getNotificationRecvFD(), EV_READ | EV_PERSIST, TNonblockingIOThread::notifyHandler, this); // Attach to the base event_base_set(eventBase_, ¬ificationEvent_); // Add the event and start up the server if (-1 == event_add(¬ificationEvent_, nullptr)) { throw TException( "TNonblockingServer::serve(): " "event_add() failed on task-done notification event"); } GlobalOutput.printf("TNonblocking: IO thread #%d registered for notify.", number_); } bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) { auto fd = getNotificationSendFD(); if (fd < 0) { return false; } int ret = -1; long kSize = sizeof(conn); const char * pos = (const char *)const_cast_sockopt(&conn); #if defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H) struct pollfd pfd = {fd, POLLOUT, 0}; while (kSize > 0) { pfd.revents = 0; ret = poll(&pfd, 1, -1); if (ret < 0) { return false; } else if (ret == 0) { continue; } if (pfd.revents & POLLHUP || pfd.revents & POLLERR) { ::THRIFT_CLOSESOCKET(fd); return false; } if (pfd.revents & POLLOUT) { ret = send(fd, pos, kSize, 0); if (ret < 0) { if (errno == EAGAIN) { continue; } ::THRIFT_CLOSESOCKET(fd); return false; } kSize -= ret; pos += ret; } } #else fd_set wfds, efds; while (kSize > 0) { FD_ZERO(&wfds); FD_ZERO(&efds); FD_SET(fd, &wfds); FD_SET(fd, &efds); ret = select(static_cast(fd + 1), nullptr, &wfds, &efds, nullptr); if (ret < 0) { return false; } else if (ret == 0) { continue; } if (FD_ISSET(fd, &efds)) { ::THRIFT_CLOSESOCKET(fd); return false; } if (FD_ISSET(fd, &wfds)) { ret = send(fd, pos, kSize, 0); if (ret < 0) { if (errno == EAGAIN) { continue; } ::THRIFT_CLOSESOCKET(fd); return false; } kSize -= ret; pos += ret; } } #endif return true; } /* static */ void TNonblockingIOThread::notifyHandler(evutil_socket_t fd, short which, void* v) { auto* ioThread = (TNonblockingIOThread*)v; assert(ioThread); (void)which; while (true) { TNonblockingServer::TConnection* connection = nullptr; const int kSize = sizeof(connection); long nBytes = recv(fd, cast_sockopt(&connection), kSize, 0); if (nBytes == kSize) { if (connection == nullptr) { // this is the command to stop our thread, exit the handler! ioThread->breakLoop(false); return; } connection->transition(); } else if (nBytes > 0) { // throw away these bytes and hope that next time we get a solid read GlobalOutput.printf("notifyHandler: Bad read of %d bytes, wanted %d", nBytes, kSize); ioThread->breakLoop(true); return; } else if (nBytes == 0) { GlobalOutput.printf("notifyHandler: Notify socket closed!"); ioThread->breakLoop(false); // exit the loop break; } else { // nBytes < 0 if (THRIFT_GET_SOCKET_ERROR != THRIFT_EWOULDBLOCK && THRIFT_GET_SOCKET_ERROR != THRIFT_EAGAIN) { GlobalOutput.perror("TNonblocking: notifyHandler read() failed: ", THRIFT_GET_SOCKET_ERROR); ioThread->breakLoop(true); return; } // exit the loop break; } } } void TNonblockingIOThread::breakLoop(bool error) { if (error) { GlobalOutput.printf("TNonblockingServer: IO thread #%d exiting with error.", number_); // TODO: figure out something better to do here, but for now kill the // whole process. GlobalOutput.printf("TNonblockingServer: aborting process."); ::abort(); } // If we're running in the same thread, we can't use the notify(0) // mechanism to stop the thread, but happily if we're running in the // same thread, this means the thread can't be blocking in the event // loop either. if (!Thread::is_current(threadId_)) { notify(nullptr); } else { // cause the loop to stop ASAP - even if it has things to do in it event_base_loopbreak(eventBase_); } } void TNonblockingIOThread::setCurrentThreadHighPriority(bool value) { #ifdef HAVE_SCHED_H // Start out with a standard, low-priority setup for the sched params. struct sched_param sp; memset(static_cast(&sp), 0, sizeof(sp)); int policy = SCHED_OTHER; // If desired, set up high-priority sched params structure. if (value) { // FIFO scheduler, ranked above default SCHED_OTHER queue policy = SCHED_FIFO; // The priority only compares us to other SCHED_FIFO threads, so we // just pick a random priority halfway between min & max. const int priority = (sched_get_priority_max(policy) + sched_get_priority_min(policy)) / 2; sp.sched_priority = priority; } // Actually set the sched params for the current thread. if (0 == pthread_setschedparam(pthread_self(), policy, &sp)) { GlobalOutput.printf("TNonblocking: IO Thread #%d using high-priority scheduler!", number_); } else { GlobalOutput.perror("TNonblocking: pthread_setschedparam(): ", THRIFT_GET_SOCKET_ERROR); } #else THRIFT_UNUSED_VARIABLE(value); #endif } void TNonblockingIOThread::run() { if (eventBase_ == nullptr) { registerEvents(); } if (useHighPriority_) { setCurrentThreadHighPriority(true); } if (eventBase_ != nullptr) { GlobalOutput.printf("TNonblockingServer: IO thread #%d entering loop...", number_); // Run libevent engine, never returns, invokes calls to eventHandler event_base_loop(eventBase_, 0); if (useHighPriority_) { setCurrentThreadHighPriority(false); } // cleans up our registered events cleanupEvents(); } GlobalOutput.printf("TNonblockingServer: IO thread #%d run() done!", number_); } void TNonblockingIOThread::cleanupEvents() { // stop the listen socket, if any if (listenSocket_ != THRIFT_INVALID_SOCKET) { if (event_del(&serverEvent_) == -1) { GlobalOutput.perror("TNonblockingIOThread::stop() event_del: ", THRIFT_GET_SOCKET_ERROR); } } event_del(¬ificationEvent_); } void TNonblockingIOThread::stop() { // This should cause the thread to fall out of its event loop ASAP. breakLoop(false); } void TNonblockingIOThread::join() { // If this was a thread created by a factory (not the thread that called // serve()), we join() it to make sure we shut down fully. if (thread_) { try { // Note that it is safe to both join() ourselves twice, as well as join // the current thread as the pthread implementation checks for deadlock. thread_->join(); } catch (...) { // swallow everything } } } } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/server/TServer.h0000644000000000000000000002512014303740367021576 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TSERVER_H_ #define _THRIFT_SERVER_TSERVER_H_ 1 #include #include #include #include #include namespace apache { namespace thrift { namespace server { using apache::thrift::TProcessor; using apache::thrift::protocol::TBinaryProtocolFactory; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportFactory; /** * Virtual interface class that can handle events from the server core. To * use this you should subclass it and implement the methods that you care * about. Your subclass can also store local data that you may care about, * such as additional "arguments" to these methods (stored in the object * instance's state). */ class TServerEventHandler { public: virtual ~TServerEventHandler() = default; /** * Called before the server begins. */ virtual void preServe() {} /** * Called when a new client has connected and is about to being processing. */ virtual void* createContext(std::shared_ptr input, std::shared_ptr output) { (void)input; (void)output; return nullptr; } /** * Called when a client has finished request-handling to delete server * context. */ virtual void deleteContext(void* serverContext, std::shared_ptr input, std::shared_ptr output) { (void)serverContext; (void)input; (void)output; } /** * Called when a client is about to call the processor. */ virtual void processContext(void* serverContext, std::shared_ptr transport) { (void)serverContext; (void)transport; } protected: /** * Prevent direct instantiation. */ TServerEventHandler() = default; }; /** * Thrift server. * */ class TServer : public concurrency::Runnable { public: ~TServer() override = default; virtual void serve() = 0; virtual void stop() {} // Allows running the server as a Runnable thread void run() override { serve(); } std::shared_ptr getProcessorFactory() { return processorFactory_; } std::shared_ptr getServerTransport() { return serverTransport_; } std::shared_ptr getInputTransportFactory() { return inputTransportFactory_; } std::shared_ptr getOutputTransportFactory() { return outputTransportFactory_; } std::shared_ptr getInputProtocolFactory() { return inputProtocolFactory_; } std::shared_ptr getOutputProtocolFactory() { return outputProtocolFactory_; } std::shared_ptr getEventHandler() { return eventHandler_; } protected: TServer(const std::shared_ptr& processorFactory) : processorFactory_(processorFactory) { setInputTransportFactory(std::shared_ptr(new TTransportFactory())); setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } TServer(const std::shared_ptr& processor) : processorFactory_(new TSingletonProcessorFactory(processor)) { setInputTransportFactory(std::shared_ptr(new TTransportFactory())); setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } TServer(const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport) : processorFactory_(processorFactory), serverTransport_(serverTransport) { setInputTransportFactory(std::shared_ptr(new TTransportFactory())); setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } TServer(const std::shared_ptr& processor, const std::shared_ptr& serverTransport) : processorFactory_(new TSingletonProcessorFactory(processor)), serverTransport_(serverTransport) { setInputTransportFactory(std::shared_ptr(new TTransportFactory())); setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } TServer(const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) : processorFactory_(processorFactory), serverTransport_(serverTransport), inputTransportFactory_(transportFactory), outputTransportFactory_(transportFactory), inputProtocolFactory_(protocolFactory), outputProtocolFactory_(protocolFactory) {} TServer(const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) : processorFactory_(new TSingletonProcessorFactory(processor)), serverTransport_(serverTransport), inputTransportFactory_(transportFactory), outputTransportFactory_(transportFactory), inputProtocolFactory_(protocolFactory), outputProtocolFactory_(protocolFactory) {} TServer(const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory) : processorFactory_(processorFactory), serverTransport_(serverTransport), inputTransportFactory_(inputTransportFactory), outputTransportFactory_(outputTransportFactory), inputProtocolFactory_(inputProtocolFactory), outputProtocolFactory_(outputProtocolFactory) {} TServer(const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory) : processorFactory_(new TSingletonProcessorFactory(processor)), serverTransport_(serverTransport), inputTransportFactory_(inputTransportFactory), outputTransportFactory_(outputTransportFactory), inputProtocolFactory_(inputProtocolFactory), outputProtocolFactory_(outputProtocolFactory) {} /** * Get a TProcessor to handle calls on a particular connection. * * This method should only be called once per connection (never once per * call). This allows the TProcessorFactory to return a different processor * for each connection if it desires. */ std::shared_ptr getProcessor(std::shared_ptr inputProtocol, std::shared_ptr outputProtocol, std::shared_ptr transport) { TConnectionInfo connInfo; connInfo.input = inputProtocol; connInfo.output = outputProtocol; connInfo.transport = transport; return processorFactory_->getProcessor(connInfo); } // Class variables std::shared_ptr processorFactory_; std::shared_ptr serverTransport_; std::shared_ptr inputTransportFactory_; std::shared_ptr outputTransportFactory_; std::shared_ptr inputProtocolFactory_; std::shared_ptr outputProtocolFactory_; std::shared_ptr eventHandler_; public: void setInputTransportFactory(std::shared_ptr inputTransportFactory) { inputTransportFactory_ = inputTransportFactory; } void setOutputTransportFactory(std::shared_ptr outputTransportFactory) { outputTransportFactory_ = outputTransportFactory; } void setInputProtocolFactory(std::shared_ptr inputProtocolFactory) { inputProtocolFactory_ = inputProtocolFactory; } void setOutputProtocolFactory(std::shared_ptr outputProtocolFactory) { outputProtocolFactory_ = outputProtocolFactory; } void setServerEventHandler(std::shared_ptr eventHandler) { eventHandler_ = eventHandler; } }; /** * Helper function to increase the max file descriptors limit * for the current process and all of its children. * By default, tries to increase it to as much as 2^24. */ #ifdef HAVE_SYS_RESOURCE_H int increase_max_fds(int max_fds = (1 << 24)); #endif } } } // apache::thrift::server #endif // #ifndef _THRIFT_SERVER_TSERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TSimpleServer.h0000644000000000000000000000671014303740367022754 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ #define _THRIFT_SERVER_TSIMPLESERVER_H_ 1 #include namespace apache { namespace thrift { namespace server { /** * This is the most basic simple server. It is single-threaded and runs a * continuous loop of accepting a single connection, processing requests on * that connection until it closes, and then repeating. */ class TSimpleServer : public TServerFramework { public: TSimpleServer( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory); TSimpleServer( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory); TSimpleServer( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory); TSimpleServer( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory); ~TSimpleServer() override; protected: void onClientConnected(const std::shared_ptr& pClient) override /* override */; void onClientDisconnected(TConnectedClient* pClient) override /* override */; private: void setConcurrentClientLimit(int64_t newLimit) override; // hide }; } } } // apache::thrift::server #endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TServer.cpp0000644000000000000000000000266214303740367022137 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_RESOURCE_H #include #endif #ifdef HAVE_UNISTD_H #include #endif namespace apache { namespace thrift { namespace server { #ifdef HAVE_SYS_RESOURCE_H int increase_max_fds(int max_fds = (1 << 24)) { struct rlimit fdmaxrl; for (fdmaxrl.rlim_cur = max_fds, fdmaxrl.rlim_max = max_fds; max_fds && (setrlimit(RLIMIT_NOFILE, &fdmaxrl) < 0); fdmaxrl.rlim_cur = max_fds, fdmaxrl.rlim_max = max_fds) { max_fds /= 2; } return static_cast(fdmaxrl.rlim_cur); } #endif } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/server/TThreadPoolServer.h0000644000000000000000000001076014303740367023564 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ #define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1 #include #include #include namespace apache { namespace thrift { namespace server { /** * Manage clients using a thread pool. */ class TThreadPoolServer : public TServerFramework { public: TThreadPoolServer( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory, const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); TThreadPoolServer( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory, const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); TThreadPoolServer( const std::shared_ptr& processorFactory, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); TThreadPoolServer( const std::shared_ptr& processor, const std::shared_ptr& serverTransport, const std::shared_ptr& inputTransportFactory, const std::shared_ptr& outputTransportFactory, const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); ~TThreadPoolServer() override; /** * Post-conditions (return guarantees): * There will be no clients connected. */ void serve() override; virtual int64_t getTimeout() const; virtual void setTimeout(int64_t value); virtual int64_t getTaskExpiration() const; virtual void setTaskExpiration(int64_t value); virtual std::shared_ptr getThreadManager() const; protected: void onClientConnected(const std::shared_ptr& pClient) override /* override */; void onClientDisconnected(TConnectedClient* pClient) override /* override */; std::shared_ptr threadManager_; std::atomic timeout_; std::atomic taskExpiration_; }; } } } // apache::thrift::server #endif // #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/server/TThreadPoolServer.cpp0000644000000000000000000001231714303740367024117 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include namespace apache { namespace thrift { namespace server { using apache::thrift::concurrency::ThreadManager; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; using std::shared_ptr; using std::string; TThreadPoolServer::TThreadPoolServer(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory, const shared_ptr& threadManager) : TServerFramework(processorFactory, serverTransport, transportFactory, protocolFactory), threadManager_(threadManager), timeout_(0), taskExpiration_(0) { } TThreadPoolServer::TThreadPoolServer(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory, const shared_ptr& threadManager) : TServerFramework(processor, serverTransport, transportFactory, protocolFactory), threadManager_(threadManager), timeout_(0), taskExpiration_(0) { } TThreadPoolServer::TThreadPoolServer(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory, const shared_ptr& threadManager) : TServerFramework(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory), threadManager_(threadManager), timeout_(0), taskExpiration_(0) { } TThreadPoolServer::TThreadPoolServer(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory, const shared_ptr& threadManager) : TServerFramework(processor, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory), threadManager_(threadManager), timeout_(0), taskExpiration_(0) { } TThreadPoolServer::~TThreadPoolServer() = default; void TThreadPoolServer::serve() { TServerFramework::serve(); threadManager_->stop(); } int64_t TThreadPoolServer::getTimeout() const { return timeout_; } void TThreadPoolServer::setTimeout(int64_t value) { timeout_ = value; } int64_t TThreadPoolServer::getTaskExpiration() const { return taskExpiration_; } void TThreadPoolServer::setTaskExpiration(int64_t value) { taskExpiration_ = value; } std::shared_ptr TThreadPoolServer::getThreadManager() const { return threadManager_; } void TThreadPoolServer::onClientConnected(const shared_ptr& pClient) { threadManager_->add(pClient, getTimeout(), getTaskExpiration()); } void TThreadPoolServer::onClientDisconnected(TConnectedClient*) { } } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/server/TServerFramework.cpp0000644000000000000000000002074114370300523024001 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include namespace apache { namespace thrift { namespace server { using apache::thrift::concurrency::Synchronized; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using std::bind; using std::shared_ptr; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; using std::string; TServerFramework::TServerFramework(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory) : TServer(processorFactory, serverTransport, transportFactory, protocolFactory), clients_(0), hwm_(0), limit_(INT64_MAX) { } TServerFramework::TServerFramework(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& transportFactory, const shared_ptr& protocolFactory) : TServer(processor, serverTransport, transportFactory, protocolFactory), clients_(0), hwm_(0), limit_(INT64_MAX) { } TServerFramework::TServerFramework(const shared_ptr& processorFactory, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory) : TServer(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory), clients_(0), hwm_(0), limit_(INT64_MAX) { } TServerFramework::TServerFramework(const shared_ptr& processor, const shared_ptr& serverTransport, const shared_ptr& inputTransportFactory, const shared_ptr& outputTransportFactory, const shared_ptr& inputProtocolFactory, const shared_ptr& outputProtocolFactory) : TServer(processor, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory), clients_(0), hwm_(0), limit_(INT64_MAX) { } TServerFramework::~TServerFramework() = default; template static void releaseOneDescriptor(const string& name, T& pTransport) { if (pTransport) { try { pTransport->close(); } catch (const TTransportException& ttx) { string errStr = string("TServerFramework " + name + " close failed: ") + ttx.what(); GlobalOutput(errStr.c_str()); } } } void TServerFramework::serve() { shared_ptr client; shared_ptr inputTransport; shared_ptr outputTransport; shared_ptr inputProtocol; shared_ptr outputProtocol; // Start the server listening serverTransport_->listen(); // Run the preServe event to indicate server is now listening // and that it is safe to connect. if (eventHandler_) { eventHandler_->preServe(); } // Fetch client from server for (;;) { try { // Dereference any resources from any previous client creation // such that a blocking accept does not hold them indefinitely. outputProtocol.reset(); inputProtocol.reset(); outputTransport.reset(); inputTransport.reset(); client.reset(); // If we have reached the limit on the number of concurrent // clients allowed, wait for one or more clients to drain before // accepting another. { Synchronized sync(mon_); while (clients_ >= limit_) { mon_.wait(); } } client = serverTransport_->accept(); inputTransport = inputTransportFactory_->getTransport(client); outputTransport = outputTransportFactory_->getTransport(client); if (!outputProtocolFactory_) { inputProtocol = inputProtocolFactory_->getProtocol(inputTransport, outputTransport); outputProtocol = inputProtocol; } else { inputProtocol = inputProtocolFactory_->getProtocol(inputTransport); outputProtocol = outputProtocolFactory_->getProtocol(outputTransport); } newlyConnectedClient(shared_ptr( new TConnectedClient(getProcessor(inputProtocol, outputProtocol, client), inputProtocol, outputProtocol, eventHandler_, client), bind(&TServerFramework::disposeConnectedClient, this, std::placeholders::_1))); } catch (TTransportException& ttx) { releaseOneDescriptor("inputTransport", inputTransport); releaseOneDescriptor("outputTransport", outputTransport); releaseOneDescriptor("client", client); if (ttx.getType() == TTransportException::TIMED_OUT || ttx.getType() == TTransportException::CLIENT_DISCONNECT) { // Accept timeout and client disconnect - continue processing. continue; } else if (ttx.getType() == TTransportException::END_OF_FILE || ttx.getType() == TTransportException::INTERRUPTED) { // Server was interrupted. This only happens when stopping. break; } else { // All other transport exceptions are logged. // State of connection is unknown. Done. string errStr = string("TServerTransport died: ") + ttx.what(); GlobalOutput(errStr.c_str()); break; } } } releaseOneDescriptor("serverTransport", serverTransport_); } int64_t TServerFramework::getConcurrentClientLimit() const { Synchronized sync(mon_); return limit_; } int64_t TServerFramework::getConcurrentClientCount() const { Synchronized sync(mon_); return clients_; } int64_t TServerFramework::getConcurrentClientCountHWM() const { Synchronized sync(mon_); return hwm_; } void TServerFramework::setConcurrentClientLimit(int64_t newLimit) { if (newLimit < 1) { throw std::invalid_argument("newLimit must be greater than zero"); } Synchronized sync(mon_); limit_ = newLimit; if (limit_ - clients_ > 0) { mon_.notify(); } } void TServerFramework::stop() { // Order is important because serve() releases serverTransport_ when it is // interrupted, which closes the socket that interruptChildren uses. serverTransport_->interruptChildren(); serverTransport_->interrupt(); } void TServerFramework::newlyConnectedClient(const shared_ptr& pClient) { { Synchronized sync(mon_); ++clients_; hwm_ = (std::max)(hwm_, clients_); } onClientConnected(pClient); } void TServerFramework::disposeConnectedClient(TConnectedClient* pClient) { onClientDisconnected(pClient); delete pClient; Synchronized sync(mon_); if (limit_ - --clients_ > 0) { mon_.notify(); } } } } } // apache::thrift::server thrift-0.19.0/lib/cpp/src/thrift/transport/0000755000000000000000000000000014472652650020565 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/transport/TPipeServer.cpp0000644000000000000000000004071114303740367023500 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #ifdef _WIN32 #include #include #include #include #include #endif //_WIN32 namespace apache { namespace thrift { namespace transport { #ifdef _WIN32 using std::shared_ptr; class TPipeServerImpl : apache::thrift::TNonCopyable { public: TPipeServerImpl() {} virtual ~TPipeServerImpl() {} virtual void interrupt() = 0; virtual std::shared_ptr acceptImpl() = 0; virtual HANDLE getPipeHandle() = 0; virtual HANDLE getWrtPipeHandle() = 0; virtual HANDLE getClientRdPipeHandle() = 0; virtual HANDLE getClientWrtPipeHandle() = 0; virtual HANDLE getNativeWaitHandle() { return nullptr; } }; class TAnonPipeServer : public TPipeServerImpl { public: TAnonPipeServer() { // The anonymous pipe needs to be created first so that the server can // pass the handles on to the client before the serve (acceptImpl) // blocking call. if (!createAnonPipe()) { GlobalOutput.perror("TPipeServer Create(Anon)Pipe failed, GLE=", GetLastError()); throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer Create(Anon)Pipe failed"); } } virtual ~TAnonPipeServer() { PipeR_.reset(); PipeW_.reset(); ClientAnonRead_.reset(); ClientAnonWrite_.reset(); } virtual void interrupt() {} // not currently implemented virtual std::shared_ptr acceptImpl(); virtual HANDLE getPipeHandle() { return PipeR_.h; } virtual HANDLE getWrtPipeHandle() { return PipeW_.h; } virtual HANDLE getClientRdPipeHandle() { return ClientAnonRead_.h; } virtual HANDLE getClientWrtPipeHandle() { return ClientAnonWrite_.h; } private: bool createAnonPipe(); TAutoHandle PipeR_; // Anonymous Pipe (R) TAutoHandle PipeW_; // Anonymous Pipe (W) // Client side anonymous pipe handles //? Do we need duplicates to send to client? TAutoHandle ClientAnonRead_; TAutoHandle ClientAnonWrite_; }; class TNamedPipeServer : public TPipeServerImpl { public: TNamedPipeServer(const std::string& pipename, uint32_t bufsize, uint32_t maxconnections, const std::string& securityDescriptor) : stopping_(false), pipename_(pipename), bufsize_(bufsize), maxconns_(maxconnections), securityDescriptor_(securityDescriptor) { connectOverlap_.action = TOverlappedWorkItem::CONNECT; cancelOverlap_.action = TOverlappedWorkItem::CANCELIO; TAutoCrit lock(pipe_protect_); initiateNamedConnect(lock); } virtual ~TNamedPipeServer() {} virtual void interrupt() { TAutoCrit lock(pipe_protect_); cached_client_.reset(); if (Pipe_.h != INVALID_HANDLE_VALUE) { stopping_ = true; cancelOverlap_.h = Pipe_.h; // This should wake up GetOverlappedResult thread_->addWorkItem(&cancelOverlap_); } } virtual std::shared_ptr acceptImpl(); virtual HANDLE getPipeHandle() { return Pipe_.h; } virtual HANDLE getWrtPipeHandle() { return INVALID_HANDLE_VALUE; } virtual HANDLE getClientRdPipeHandle() { return INVALID_HANDLE_VALUE; } virtual HANDLE getClientWrtPipeHandle() { return INVALID_HANDLE_VALUE; } virtual HANDLE getNativeWaitHandle() { return listen_event_.h; } private: bool createNamedPipe(const TAutoCrit &lockProof); void initiateNamedConnect(const TAutoCrit &lockProof); TAutoOverlapThread thread_; TOverlappedWorkItem connectOverlap_; TOverlappedWorkItem cancelOverlap_; bool stopping_; std::string pipename_; std::string securityDescriptor_; uint32_t bufsize_; uint32_t maxconns_; TManualResetEvent listen_event_; TCriticalSection pipe_protect_; // only read or write these variables underneath a locked pipe_protect_ std::shared_ptr cached_client_; TAutoHandle Pipe_; }; HANDLE TPipeServer::getNativeWaitHandle() { if (impl_) return impl_->getNativeWaitHandle(); return nullptr; } //---- Constructors ---- TPipeServer::TPipeServer(const std::string& pipename, uint32_t bufsize) : bufsize_(bufsize), isAnonymous_(false) { setMaxConnections(TPIPE_SERVER_MAX_CONNS_DEFAULT); setPipename(pipename); setSecurityDescriptor(DEFAULT_PIPE_SECURITY); } TPipeServer::TPipeServer(const std::string& pipename, uint32_t bufsize, uint32_t maxconnections) : bufsize_(bufsize), isAnonymous_(false) { setMaxConnections(maxconnections); setPipename(pipename); setSecurityDescriptor(DEFAULT_PIPE_SECURITY); } TPipeServer::TPipeServer(const std::string& pipename, uint32_t bufsize, uint32_t maxconnections, const std::string& securityDescriptor) : bufsize_(bufsize), isAnonymous_(false) { setMaxConnections(maxconnections); setPipename(pipename); setSecurityDescriptor(securityDescriptor); } TPipeServer::TPipeServer(const std::string& pipename) : bufsize_(1024), isAnonymous_(false) { setMaxConnections(TPIPE_SERVER_MAX_CONNS_DEFAULT); setPipename(pipename); setSecurityDescriptor(DEFAULT_PIPE_SECURITY); } TPipeServer::TPipeServer(int bufsize) : bufsize_(bufsize), isAnonymous_(true) { setMaxConnections(1); impl_.reset(new TAnonPipeServer); } TPipeServer::TPipeServer() : bufsize_(1024), isAnonymous_(true) { setMaxConnections(1); impl_.reset(new TAnonPipeServer); } //---- Destructor ---- TPipeServer::~TPipeServer() {} bool TPipeServer::isOpen() const { return (impl_->getPipeHandle() != INVALID_HANDLE_VALUE); } //--------------------------------------------------------- // Transport callbacks //--------------------------------------------------------- void TPipeServer::listen() { if (isAnonymous_) return; impl_.reset(new TNamedPipeServer(pipename_, bufsize_, maxconns_, securityDescriptor_)); } shared_ptr TPipeServer::acceptImpl() { return impl_->acceptImpl(); } shared_ptr TAnonPipeServer::acceptImpl() { // This 0-byte read serves merely as a blocking call. byte buf; DWORD br; int fSuccess = ReadFile(PipeR_.h, // pipe handle &buf, // buffer to receive reply 0, // size of buffer &br, // number of bytes read nullptr); // not overlapped if (!fSuccess && GetLastError() != ERROR_MORE_DATA) { GlobalOutput.perror("TPipeServer unable to initiate pipe comms, GLE=", GetLastError()); throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer unable to initiate pipe comms"); } shared_ptr client(new TPipe(PipeR_.h, PipeW_.h)); return client; } void TNamedPipeServer::initiateNamedConnect(const TAutoCrit &lockProof) { if (stopping_) return; if (!createNamedPipe(lockProof)) { GlobalOutput.perror("TPipeServer CreateNamedPipe failed, GLE=", GetLastError()); throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer CreateNamedPipe failed"); } // The prior connection has been handled, so close the gate ResetEvent(listen_event_.h); connectOverlap_.reset(nullptr, 0, listen_event_.h); connectOverlap_.h = Pipe_.h; thread_->addWorkItem(&connectOverlap_); // Wait for the client to connect; if it succeeds, the // function returns a nonzero value. If the function returns // zero, GetLastError should return ERROR_PIPE_CONNECTED. if (connectOverlap_.success) { GlobalOutput.printf("Client connected."); cached_client_.reset(new TPipe(Pipe_)); // make sure people know that a connection is ready SetEvent(listen_event_.h); return; } DWORD dwErr = connectOverlap_.last_error; switch (dwErr) { case ERROR_PIPE_CONNECTED: GlobalOutput.printf("Client connected."); cached_client_.reset(new TPipe(Pipe_)); // make sure people know that a connection is ready SetEvent(listen_event_.h); return; case ERROR_IO_PENDING: return; // acceptImpl will do the appropriate WaitForMultipleObjects default: GlobalOutput.perror("TPipeServer ConnectNamedPipe failed, GLE=", dwErr); throw TTransportException(TTransportException::NOT_OPEN, " TPipeServer ConnectNamedPipe failed"); } } shared_ptr TNamedPipeServer::acceptImpl() { { TAutoCrit lock(pipe_protect_); if (cached_client_.get() != nullptr) { shared_ptr client; // zero out cached_client, since we are about to return it. client.swap(cached_client_); // kick off the next connection before returning initiateNamedConnect(lock); return client; // success! } } if (Pipe_.h == INVALID_HANDLE_VALUE) { throw TTransportException(TTransportException::NOT_OPEN, "TNamedPipeServer: someone called accept on a closed pipe server"); } DWORD dwDummy = 0; // For the most part, Pipe_ should be protected with pipe_protect_. We can't // reasonably do that here though without breaking interruptability. However, // this should be safe, though I'm not happy about it. We only need to ensure // that no one writes / modifies Pipe_.h while we are reading it. Well, the // only two things that should be modifying Pipe_ are acceptImpl, the // functions it calls, and the destructor. Those things shouldn't be run // concurrently anyway. So this call is 'really' just a read that may happen // concurrently with interrupt, and that should be fine. if (GetOverlappedResult(Pipe_.h, &connectOverlap_.overlap, &dwDummy, TRUE)) { TAutoCrit lock(pipe_protect_); shared_ptr client; try { client.reset(new TPipe(Pipe_)); } catch (TTransportException& ttx) { if (ttx.getType() == TTransportException::INTERRUPTED) { throw; } GlobalOutput.perror("Client connection failed. TTransportExceptionType=", ttx.getType()); // kick off the next connection before throwing initiateNamedConnect(lock); throw TTransportException(TTransportException::CLIENT_DISCONNECT, ttx.what()); } GlobalOutput.printf("Client connected."); // kick off the next connection before returning initiateNamedConnect(lock); return client; // success! } // if we got here, then we are in an error / shutdown case DWORD gle = GetLastError(); // save error before doing cleanup GlobalOutput.perror("TPipeServer ConnectNamedPipe GLE=", gle); if(gle == ERROR_OPERATION_ABORTED) { TAutoCrit lock(pipe_protect_); // Needed to insure concurrent thread to be out of interrupt. throw TTransportException(TTransportException::INTERRUPTED, "TPipeServer: server interupted"); } throw TTransportException(TTransportException::NOT_OPEN, "TPipeServer: client connection failed"); } void TPipeServer::interrupt() { if (impl_) impl_->interrupt(); } void TPipeServer::close() { impl_.reset(); } bool TNamedPipeServer::createNamedPipe(const TAutoCrit& /*lockProof*/) { PSECURITY_DESCRIPTOR psd = nullptr; ULONG size = 0; if (!ConvertStringSecurityDescriptorToSecurityDescriptorA(securityDescriptor_.c_str(), SDDL_REVISION_1, &psd, &size)) { DWORD lastError = GetLastError(); GlobalOutput.perror("TPipeServer::ConvertStringSecurityDescriptorToSecurityDescriptorA() GLE=", lastError); throw TTransportException( TTransportException::NOT_OPEN, "TPipeServer::ConvertStringSecurityDescriptorToSecurityDescriptorA() failed", lastError); } SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = psd; sa.bInheritHandle = FALSE; // Create an instance of the named pipe TAutoHandle hPipe(CreateNamedPipeA(pipename_.c_str(), // pipe name PIPE_ACCESS_DUPLEX | // read/write access FILE_FLAG_OVERLAPPED, // async mode PIPE_TYPE_BYTE | // byte type pipe PIPE_READMODE_BYTE, // byte read mode maxconns_, // max. instances bufsize_, // output buffer size bufsize_, // input buffer size 0, // client time-out &sa)); // security attributes auto lastError = GetLastError(); if (psd) LocalFree(psd); if (hPipe.h == INVALID_HANDLE_VALUE) { Pipe_.reset(); GlobalOutput.perror("TPipeServer::TCreateNamedPipe() GLE=", lastError); throw TTransportException(TTransportException::NOT_OPEN, "TCreateNamedPipe() failed", lastError); } Pipe_.reset(hPipe.release()); return true; } bool TAnonPipeServer::createAnonPipe() { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; // security information for pipes if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { GlobalOutput.perror("TPipeServer InitializeSecurityDescriptor (anon) failed, GLE=", GetLastError()); return false; } if (!SetSecurityDescriptorDacl(&sd, true, nullptr, false)) { GlobalOutput.perror("TPipeServer SetSecurityDescriptorDacl (anon) failed, GLE=", GetLastError()); return false; } sa.lpSecurityDescriptor = &sd; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = true; // allow passing handle to child HANDLE ClientAnonReadH, PipeW_H, ClientAnonWriteH, Pipe_H; if (!CreatePipe(&ClientAnonReadH, &PipeW_H, &sa, 0)) // create stdin pipe { GlobalOutput.perror("TPipeServer CreatePipe (anon) failed, GLE=", GetLastError()); return false; } if (!CreatePipe(&Pipe_H, &ClientAnonWriteH, &sa, 0)) // create stdout pipe { GlobalOutput.perror("TPipeServer CreatePipe (anon) failed, GLE=", GetLastError()); CloseHandle(ClientAnonReadH); CloseHandle(PipeW_H); return false; } ClientAnonRead_.reset(ClientAnonReadH); ClientAnonWrite_.reset(ClientAnonWriteH); PipeR_.reset(Pipe_H); PipeW_.reset(PipeW_H); return true; } //--------------------------------------------------------- // Accessors //--------------------------------------------------------- std::string TPipeServer::getPipename() { return pipename_; } void TPipeServer::setPipename(const std::string& pipename) { if (pipename.find("\\\\") == std::string::npos) pipename_ = "\\\\.\\pipe\\" + pipename; else pipename_ = pipename; } int TPipeServer::getBufferSize() { return bufsize_; } void TPipeServer::setBufferSize(int bufsize) { bufsize_ = bufsize; } HANDLE TPipeServer::getPipeHandle() { return impl_ ? impl_->getPipeHandle() : INVALID_HANDLE_VALUE; } HANDLE TPipeServer::getWrtPipeHandle() { return impl_ ? impl_->getWrtPipeHandle() : INVALID_HANDLE_VALUE; } HANDLE TPipeServer::getClientRdPipeHandle() { return impl_ ? impl_->getClientRdPipeHandle() : INVALID_HANDLE_VALUE; } HANDLE TPipeServer::getClientWrtPipeHandle() { return impl_ ? impl_->getClientWrtPipeHandle() : INVALID_HANDLE_VALUE; } bool TPipeServer::getAnonymous() { return isAnonymous_; } void TPipeServer::setAnonymous(bool anon) { isAnonymous_ = anon; } void TPipeServer::setSecurityDescriptor(const std::string& securityDescriptor) { securityDescriptor_ = securityDescriptor; } void TPipeServer::setMaxConnections(uint32_t maxconnections) { if (maxconnections == 0) maxconns_ = 1; else if (maxconnections > PIPE_UNLIMITED_INSTANCES) maxconns_ = PIPE_UNLIMITED_INSTANCES; else maxconns_ = maxconnections; } #endif //_WIN32 } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TBufferTransports.cpp0000644000000000000000000003265514452237057024737 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include using std::string; namespace apache { namespace thrift { namespace transport { uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) { auto have = static_cast(rBound_ - rBase_); // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. assert(have < len); // If we have some data in the buffer, copy it out and return it. // We have to return it without attempting to read more, since we aren't // guaranteed that the underlying transport actually has more data, so // attempting to read from it could block. if (have > 0) { memcpy(buf, rBase_, have); setReadBuffer(rBuf_.get(), 0); return have; } // No data is available in our buffer. // Get more from underlying transport up to buffer size. // Note that this makes a lot of sense if len < rBufSize_ // and almost no sense otherwise. TODO(dreiss): Fix that // case (possibly including some readv hotness). setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); // Hand over whatever we have. uint32_t give = (std::min)(len, static_cast(rBound_ - rBase_)); memcpy(buf, rBase_, give); rBase_ += give; return give; } void TBufferedTransport::writeSlow(const uint8_t* buf, uint32_t len) { auto have_bytes = static_cast(wBase_ - wBuf_.get()); auto space = static_cast(wBound_ - wBase_); // We should only take the slow path if we can't accommodate the write // with the free space already in the buffer. assert(wBound_ - wBase_ < static_cast(len)); // Now here's the tricky question: should we copy data from buf into our // internal buffer and write it from there, or should we just write out // the current internal buffer in one syscall and write out buf in another. // If our currently buffered data plus buf is at least double our buffer // size, we will have to do two syscalls no matter what (except in the // degenerate case when our buffer is empty), so there is no use copying. // Otherwise, there is sort of a sliding scale. If we have N-1 bytes // buffered and need to write 2, it would be crazy to do two syscalls. // On the other hand, if we have 2 bytes buffered and are writing 2N-3, // we can save a syscall in the short term by loading up our buffer, writing // it out, and copying the rest of the bytes into our buffer. Of course, // if we get another 2-byte write, we haven't saved any syscalls at all, // and have just copied nearly 2N bytes for nothing. Finding a perfect // policy would require predicting the size of future writes, so we're just // going to always eschew syscalls if we have less than 2N bytes to write. // The case where we have to do two syscalls. // This case also covers the case where the buffer is empty, // but it is clearer (I think) to think of it as two separate cases. if ((have_bytes + len >= 2 * wBufSize_) || (have_bytes == 0)) { // TODO(dreiss): writev if (have_bytes > 0) { transport_->write(wBuf_.get(), have_bytes); } transport_->write(buf, len); wBase_ = wBuf_.get(); return; } // Fill up our internal buffer for a write. memcpy(wBase_, buf, space); buf += space; len -= space; transport_->write(wBuf_.get(), wBufSize_); // Copy the rest into our buffer. assert(len < wBufSize_); memcpy(wBuf_.get(), buf, len); wBase_ = wBuf_.get() + len; return; } const uint8_t* TBufferedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { (void)buf; (void)len; // Simply return nullptr. We don't know if there is actually data available on // the underlying transport, so calling read() might block. return nullptr; } void TBufferedTransport::flush() { resetConsumedMessageSize(); // Write out any data waiting in the write buffer. auto have_bytes = static_cast(wBase_ - wBuf_.get()); if (have_bytes > 0) { // Note that we reset wBase_ prior to the underlying write // to ensure we're in a sane state (i.e. internal buffer cleaned) // if the underlying write throws up an exception wBase_ = wBuf_.get(); transport_->write(wBuf_.get(), have_bytes); } // Flush the underlying transport. transport_->flush(); } uint32_t TFramedTransport::readSlow(uint8_t* buf, uint32_t len) { uint32_t want = len; auto have = static_cast(rBound_ - rBase_); // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. assert(have < want); // If we have some data in the buffer, copy it out and return it. // We have to return it without attempting to read more, since we aren't // guaranteed that the underlying transport actually has more data, so // attempting to read from it could block. if (have > 0) { memcpy(buf, rBase_, have); setReadBuffer(rBuf_.get(), 0); return have; } // Read another frame. if (!readFrame()) { // EOF. No frame available. return 0; } // TODO(dreiss): Should we warn when reads cross frames? // Hand over whatever we have. uint32_t give = (std::min)(want, static_cast(rBound_ - rBase_)); memcpy(buf, rBase_, give); rBase_ += give; want -= give; return (len - want); } bool TFramedTransport::readFrame() { // TODO(dreiss): Think about using readv here, even though it would // result in (gasp) read-ahead. // Read the size of the next frame. // We can't use readAll(&sz, sizeof(sz)), since that always throws an // exception on EOF. We want to throw an exception only if EOF occurs after // partial size data. int32_t sz = -1; uint32_t size_bytes_read = 0; while (size_bytes_read < sizeof(sz)) { uint8_t* szp = reinterpret_cast(&sz) + size_bytes_read; uint32_t bytes_read = transport_->read(szp, static_cast(sizeof(sz)) - size_bytes_read); if (bytes_read == 0) { if (size_bytes_read == 0) { // EOF before any data was read. return false; } else { // EOF after a partial frame header. Raise an exception. throw TTransportException(TTransportException::END_OF_FILE, "No more data to read after " "partial frame header."); } } size_bytes_read += bytes_read; } sz = ntohl(sz); if (sz < 0) { throw TTransportException("Frame size has negative value"); } // Check for oversized frame if (sz > static_cast(maxFrameSize_)) throw TTransportException(TTransportException::CORRUPTED_DATA, "Received an oversized frame"); // Read the frame payload, and reset markers. if (sz > static_cast(rBufSize_)) { rBuf_.reset(new uint8_t[sz]); rBufSize_ = sz; } transport_->readAll(rBuf_.get(), sz); setReadBuffer(rBuf_.get(), sz); return true; } void TFramedTransport::writeSlow(const uint8_t* buf, uint32_t len) { // Double buffer size until sufficient. auto have = static_cast(wBase_ - wBuf_.get()); uint32_t new_size = wBufSize_; if (len + have < have /* overflow */ || len + have > 0x7fffffff) { throw TTransportException(TTransportException::BAD_ARGS, "Attempted to write over 2 GB to TFramedTransport."); } while (new_size < len + have) { new_size = new_size > 0 ? new_size * 2 : 1; } // TODO(dreiss): Consider modifying this class to use malloc/free // so we can use realloc here. // Allocate new buffer. auto* new_buf = new uint8_t[new_size]; // Copy the old buffer to the new one. memcpy(new_buf, wBuf_.get(), have); // Now point buf to the new one. wBuf_.reset(new_buf); wBufSize_ = new_size; wBase_ = wBuf_.get() + have; wBound_ = wBuf_.get() + wBufSize_; // Copy the data into the new buffer. memcpy(wBase_, buf, len); wBase_ += len; } void TFramedTransport::flush() { resetConsumedMessageSize(); int32_t sz_hbo, sz_nbo; assert(wBufSize_ > sizeof(sz_nbo)); // Slip the frame size into the start of the buffer. sz_hbo = static_cast(wBase_ - (wBuf_.get() + sizeof(sz_nbo))); sz_nbo = (int32_t)htonl((uint32_t)(sz_hbo)); memcpy(wBuf_.get(), (uint8_t*)&sz_nbo, sizeof(sz_nbo)); if (sz_hbo > 0) { // Note that we reset wBase_ (with a pad for the frame size) // prior to the underlying write to ensure we're in a sane state // (i.e. internal buffer cleaned) if the underlying write throws // up an exception wBase_ = wBuf_.get() + sizeof(sz_nbo); // Write size and frame body. transport_->write(wBuf_.get(), static_cast(sizeof(sz_nbo)) + sz_hbo); } // Flush the underlying transport. transport_->flush(); // reclaim write buffer if (wBufSize_ > bufReclaimThresh_) { wBufSize_ = DEFAULT_BUFFER_SIZE; wBuf_.reset(new uint8_t[wBufSize_]); setWriteBuffer(wBuf_.get(), wBufSize_); // reset wBase_ with a pad for the frame size int32_t pad = 0; wBase_ = wBuf_.get() + sizeof(pad); } } uint32_t TFramedTransport::writeEnd() { return static_cast(wBase_ - wBuf_.get()); } const uint8_t* TFramedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { (void)buf; (void)len; // Don't try to be clever with shifting buffers. // If the fast path failed let the protocol use its slow path. // Besides, who is going to try to borrow across messages? return nullptr; } uint32_t TFramedTransport::readEnd() { // include framing bytes auto bytes_read = static_cast(rBound_ - rBuf_.get() + sizeof(uint32_t)); if (rBufSize_ > bufReclaimThresh_) { rBufSize_ = 0; rBuf_.reset(); setReadBuffer(rBuf_.get(), rBufSize_); } return bytes_read; } void TMemoryBuffer::computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give) { // Correct rBound_ so we can use the fast path in the future. rBound_ = wBase_; // Decide how much to give. uint32_t give = (std::min)(len, available_read()); *out_start = rBase_; *out_give = give; // Preincrement rBase_ so the caller doesn't have to. rBase_ += give; } uint32_t TMemoryBuffer::readSlow(uint8_t* buf, uint32_t len) { uint8_t* start; uint32_t give; computeRead(len, &start, &give); // Copy into the provided buffer. memcpy(buf, start, give); return give; } uint32_t TMemoryBuffer::readAppendToString(std::string& str, uint32_t len) { // Don't get some stupid assertion failure. if (buffer_ == nullptr) { return 0; } uint8_t* start; uint32_t give; computeRead(len, &start, &give); // Append to the provided string. str.append((char*)start, give); return give; } void TMemoryBuffer::ensureCanWrite(uint32_t len) { // Check available space uint32_t avail = available_write(); if (len <= avail) { return; } if (!owner_) { throw TTransportException("Insufficient space in external MemoryBuffer"); } // Grow the buffer as necessary. Use uint64_t to avoid overflow. const uint64_t current_used = bufferSize_ - avail; const uint64_t required_buffer_size = len + current_used; if (required_buffer_size > maxBufferSize_) { throw TTransportException(TTransportException::BAD_ARGS, "Internal buffer size overflow when requesting a buffer of size " + std::to_string(required_buffer_size)); } // Always grow to the next bigger power of two: const double suggested_buffer_size = std::exp2(std::ceil(std::log2(required_buffer_size))); // Unless the power of two exceeds maxBufferSize_: const uint64_t new_size = static_cast((std::min)(suggested_buffer_size, static_cast(maxBufferSize_))); // Allocate into a new pointer so we don't bork ours if it fails. auto* new_buffer = static_cast(std::realloc(buffer_, static_cast(new_size))); if (new_buffer == nullptr) { throw std::bad_alloc(); } rBase_ = new_buffer + (rBase_ - buffer_); rBound_ = new_buffer + (rBound_ - buffer_); wBase_ = new_buffer + (wBase_ - buffer_); wBound_ = new_buffer + new_size; // Note: with realloc() we do not need to free the previous buffer: buffer_ = new_buffer; bufferSize_ = static_cast(new_size); } void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) { ensureCanWrite(len); // Copy into the buffer and increment wBase_. memcpy(wBase_, buf, len); wBase_ += len; } void TMemoryBuffer::wroteBytes(uint32_t len) { uint32_t avail = available_write(); if (len > avail) { throw TTransportException("Client wrote more bytes than size of buffer."); } wBase_ += len; } const uint8_t* TMemoryBuffer::borrowSlow(uint8_t* buf, uint32_t* len) { (void)buf; rBound_ = wBase_; if (available_read() >= *len) { *len = available_read(); return rBase_; } return nullptr; } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TBufferTransports.h0000644000000000000000000005540214370300523024363 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ #define _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ 1 #include #include #include #include #include #ifdef __GNUC__ #define TDB_LIKELY(val) (__builtin_expect((val), 1)) #define TDB_UNLIKELY(val) (__builtin_expect((val), 0)) #else #define TDB_LIKELY(val) (val) #define TDB_UNLIKELY(val) (val) #endif namespace apache { namespace thrift { namespace transport { /** * Base class for all transports that use read/write buffers for performance. * * TBufferBase is designed to implement the fast-path "memcpy" style * operations that work in the common case. It does so with small and * (eventually) nonvirtual, inlinable methods. TBufferBase is an abstract * class. Subclasses are expected to define the "slow path" operations * that have to be done when the buffers are full or empty. * */ class TBufferBase : public TVirtualTransport { public: /** * Fast-path read. * * When we have enough data buffered to fulfill the read, we can satisfy it * with a single memcpy, then adjust our internal pointers. If the buffer * is empty, we call out to our slow path, implemented by a subclass. * This method is meant to eventually be nonvirtual and inlinable. */ uint32_t read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); uint8_t* new_rBase = rBase_ + len; if (TDB_LIKELY(new_rBase <= rBound_)) { std::memcpy(buf, rBase_, len); rBase_ = new_rBase; return len; } return readSlow(buf, len); } /** * Shortcutted version of readAll. */ uint32_t readAll(uint8_t* buf, uint32_t len) { uint8_t* new_rBase = rBase_ + len; if (TDB_LIKELY(new_rBase <= rBound_)) { std::memcpy(buf, rBase_, len); rBase_ = new_rBase; return len; } return apache::thrift::transport::readAll(*this, buf, len); } /** * Fast-path write. * * When we have enough empty space in our buffer to accommodate the write, we * can satisfy it with a single memcpy, then adjust our internal pointers. * If the buffer is full, we call out to our slow path, implemented by a * subclass. This method is meant to eventually be nonvirtual and * inlinable. */ void write(const uint8_t* buf, uint32_t len) { uint8_t* new_wBase = wBase_ + len; if (TDB_LIKELY(new_wBase <= wBound_)) { std::memcpy(wBase_, buf, len); wBase_ = new_wBase; return; } writeSlow(buf, len); } /** * Fast-path borrow. A lot like the fast-path read. */ const uint8_t* borrow(uint8_t* buf, uint32_t* len) { if (TDB_LIKELY(static_cast(*len) <= rBound_ - rBase_)) { // With strict aliasing, writing to len shouldn't force us to // refetch rBase_ from memory. TODO(dreiss): Verify this. *len = static_cast(rBound_ - rBase_); return rBase_; } return borrowSlow(buf, len); } /** * Consume doesn't require a slow path. */ void consume(uint32_t len) { countConsumedMessageBytes(len); if (TDB_LIKELY(static_cast(len) <= rBound_ - rBase_)) { rBase_ += len; } else { throw TTransportException(TTransportException::BAD_ARGS, "consume did not follow a borrow."); } } protected: /// Slow path read. virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0; /// Slow path write. virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0; /** * Slow path borrow. * * POSTCONDITION: return == nullptr || rBound_ - rBase_ >= *len */ virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0; /** * Trivial constructor. * * Initialize pointers safely. Constructing is not a very * performance-sensitive operation, so it is okay to just leave it to * the concrete class to set up pointers correctly. */ TBufferBase(std::shared_ptr config = nullptr) : TVirtualTransport(config), rBase_(nullptr), rBound_(nullptr), wBase_(nullptr), wBound_(nullptr) {} /// Convenience mutator for setting the read buffer. void setReadBuffer(uint8_t* buf, uint32_t len) { rBase_ = buf; rBound_ = buf + len; } /// Convenience mutator for setting the write buffer. void setWriteBuffer(uint8_t* buf, uint32_t len) { wBase_ = buf; wBound_ = buf + len; } ~TBufferBase() override = default; /// Reads begin here. uint8_t* rBase_; /// Reads may extend to just before here. uint8_t* rBound_; /// Writes begin here. uint8_t* wBase_; /// Writes may extend to just before here. uint8_t* wBound_; }; /** * Buffered transport. For reads it will read more data than is requested * and will serve future data out of a local buffer. For writes, data is * stored to an in memory buffer before being written out. * */ class TBufferedTransport : public TVirtualTransport { public: static const int DEFAULT_BUFFER_SIZE = 512; /// Use default buffer sizes. TBufferedTransport(std::shared_ptr transport, std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), rBufSize_(DEFAULT_BUFFER_SIZE), wBufSize_(DEFAULT_BUFFER_SIZE), rBuf_(new uint8_t[rBufSize_]), wBuf_(new uint8_t[wBufSize_]) { initPointers(); } /// Use specified buffer sizes. TBufferedTransport(std::shared_ptr transport, uint32_t sz, std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), rBufSize_(sz), wBufSize_(sz), rBuf_(new uint8_t[rBufSize_]), wBuf_(new uint8_t[wBufSize_]) { initPointers(); } /// Use specified read and write buffer sizes. TBufferedTransport(std::shared_ptr transport, uint32_t rsz, uint32_t wsz, std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), rBufSize_(rsz), wBufSize_(wsz), rBuf_(new uint8_t[rBufSize_]), wBuf_(new uint8_t[wBufSize_]) { initPointers(); } void open() override { transport_->open(); } bool isOpen() const override { return transport_->isOpen(); } bool peek() override { if (rBase_ == rBound_) { setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); } return (rBound_ > rBase_); } void close() override { flush(); transport_->close(); } uint32_t readSlow(uint8_t* buf, uint32_t len) override; void writeSlow(const uint8_t* buf, uint32_t len) override; void flush() override; /** * Returns the origin of the underlying transport */ const std::string getOrigin() const override { return transport_->getOrigin(); } /** * The following behavior is currently implemented by TBufferedTransport, * but that may change in a future version: * 1/ If len is at most rBufSize_, borrow will never return nullptr. * Depending on the underlying transport, it could throw an exception * or hang forever. * 2/ Some borrow requests may copy bytes internally. However, * if len is at most rBufSize_/2, none of the copied bytes * will ever have to be copied again. For optimial performance, * stay under this limit. */ const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) override; std::shared_ptr getUnderlyingTransport() { return transport_; } /* * TVirtualTransport provides a default implementation of readAll(). * We want to use the TBufferBase version instead. */ uint32_t readAll(uint8_t* buf, uint32_t len) { return TBufferBase::readAll(buf, len); } protected: void initPointers() { setReadBuffer(rBuf_.get(), 0); setWriteBuffer(wBuf_.get(), wBufSize_); // Write size never changes. } std::shared_ptr transport_; uint32_t rBufSize_; uint32_t wBufSize_; std::unique_ptr rBuf_; std::unique_ptr wBuf_; }; /** * Wraps a transport into a buffered one. * */ class TBufferedTransportFactory : public TTransportFactory { public: TBufferedTransportFactory() = default; ~TBufferedTransportFactory() override = default; /** * Wraps the transport into a buffered one. */ std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TBufferedTransport(trans)); } }; /** * Framed transport. All writes go into an in-memory buffer until flush is * called, at which point the transport writes the length of the entire * binary chunk followed by the data payload. This allows the receiver on the * other end to always do fixed-length reads. * */ class TFramedTransport : public TVirtualTransport { public: static const int DEFAULT_BUFFER_SIZE = 512; static const int DEFAULT_MAX_FRAME_SIZE = 256 * 1024 * 1024; /// Use default buffer sizes. TFramedTransport(std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(), rBufSize_(0), wBufSize_(DEFAULT_BUFFER_SIZE), rBuf_(), wBuf_(new uint8_t[wBufSize_]), bufReclaimThresh_((std::numeric_limits::max)()) { initPointers(); } TFramedTransport(std::shared_ptr transport, std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), rBufSize_(0), wBufSize_(DEFAULT_BUFFER_SIZE), rBuf_(), wBuf_(new uint8_t[wBufSize_]), bufReclaimThresh_((std::numeric_limits::max)()), maxFrameSize_(configuration_->getMaxFrameSize()) { initPointers(); } TFramedTransport(std::shared_ptr transport, uint32_t sz, uint32_t bufReclaimThresh = (std::numeric_limits::max)(), std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), rBufSize_(0), wBufSize_(sz), rBuf_(), wBuf_(new uint8_t[wBufSize_]), bufReclaimThresh_(bufReclaimThresh), maxFrameSize_(configuration_->getMaxFrameSize()) { initPointers(); } void open() override { transport_->open(); } bool isOpen() const override { return transport_->isOpen(); } bool peek() override { return (rBase_ < rBound_) || transport_->peek(); } void close() override { flush(); transport_->close(); } uint32_t readSlow(uint8_t* buf, uint32_t len) override; void writeSlow(const uint8_t* buf, uint32_t len) override; void flush() override; uint32_t readEnd() override; uint32_t writeEnd() override; const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) override; std::shared_ptr getUnderlyingTransport() { return transport_; } /* * TVirtualTransport provides a default implementation of readAll(). * We want to use the TBufferBase version instead. */ using TBufferBase::readAll; /** * Returns the origin of the underlying transport */ const std::string getOrigin() const override { return transport_->getOrigin(); } /** * Set the maximum size of the frame at read */ void setMaxFrameSize(uint32_t maxFrameSize) { maxFrameSize_ = maxFrameSize; } /** * Get the maximum size of the frame at read */ uint32_t getMaxFrameSize() { return maxFrameSize_; } protected: /** * Reads a frame of input from the underlying stream. * * Returns true if a frame was read successfully, or false on EOF. * (Raises a TTransportException if EOF occurs after a partial frame.) */ virtual bool readFrame(); void initPointers() { setReadBuffer(nullptr, 0); setWriteBuffer(wBuf_.get(), wBufSize_); // Pad the buffer so we can insert the size later. int32_t pad = 0; this->write((uint8_t*)&pad, sizeof(pad)); } std::shared_ptr transport_; uint32_t rBufSize_; uint32_t wBufSize_; std::unique_ptr rBuf_; std::unique_ptr wBuf_; uint32_t bufReclaimThresh_; uint32_t maxFrameSize_; }; /** * Wraps a transport into a framed one. * */ class TFramedTransportFactory : public TTransportFactory { public: TFramedTransportFactory() = default; ~TFramedTransportFactory() override = default; /** * Wraps the transport into a framed one. */ std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TFramedTransport(trans)); } }; /** * A memory buffer is a tranpsort that simply reads from and writes to an * in memory buffer. Anytime you call write on it, the data is simply placed * into a buffer, and anytime you call read, data is read from that buffer. * * The buffers are allocated using C constructs malloc,realloc, and the size * doubles as necessary. We've considered using scoped * */ class TMemoryBuffer : public TVirtualTransport { private: // Common initialization done by all constructors. void initCommon(uint8_t* buf, uint32_t size, bool owner, uint32_t wPos) { maxBufferSize_ = (std::numeric_limits::max)(); if (buf == nullptr && size != 0) { assert(owner); buf = (uint8_t*)std::malloc(size); if (buf == nullptr) { throw std::bad_alloc(); } } buffer_ = buf; bufferSize_ = size; rBase_ = buffer_; rBound_ = buffer_ + wPos; // TODO(dreiss): Investigate NULL-ing this if !owner. wBase_ = buffer_ + wPos; wBound_ = buffer_ + bufferSize_; owner_ = owner; // rBound_ is really an artifact. In principle, it should always be // equal to wBase_. We update it in a few places (computeRead, etc.). } public: static const uint32_t defaultSize = 1024; /** * This enum specifies how a TMemoryBuffer should treat * memory passed to it via constructors or resetBuffer. * * OBSERVE: * TMemoryBuffer will simply store a pointer to the memory. * It is the callers responsibility to ensure that the pointer * remains valid for the lifetime of the TMemoryBuffer, * and that it is properly cleaned up. * Note that no data can be written to observed buffers. * * COPY: * TMemoryBuffer will make an internal copy of the buffer. * The caller has no responsibilities. * * TAKE_OWNERSHIP: * TMemoryBuffer will become the "owner" of the buffer, * and will be responsible for freeing it. * The memory must have been allocated with malloc. */ enum MemoryPolicy { OBSERVE = 1, COPY = 2, TAKE_OWNERSHIP = 3 }; /** * Construct a TMemoryBuffer with a default-sized buffer, * owned by the TMemoryBuffer object. */ TMemoryBuffer(std::shared_ptr config = nullptr) : TVirtualTransport(config) { initCommon(nullptr, defaultSize, true, 0); } /** * Construct a TMemoryBuffer with a buffer of a specified size, * owned by the TMemoryBuffer object. * * @param sz The initial size of the buffer. */ TMemoryBuffer(uint32_t sz, std::shared_ptr config = nullptr) : TVirtualTransport(config) { initCommon(nullptr, sz, true, 0); } /** * Construct a TMemoryBuffer with buf as its initial contents. * * @param buf The initial contents of the buffer. * Note that, while buf is a non-const pointer, * TMemoryBuffer will not write to it if policy == OBSERVE, * so it is safe to const_cast(whatever). * @param sz The size of @c buf. * @param policy See @link MemoryPolicy @endlink . */ TMemoryBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE, std::shared_ptr config = nullptr) : TVirtualTransport(config) { if (buf == nullptr && sz != 0) { throw TTransportException(TTransportException::BAD_ARGS, "TMemoryBuffer given null buffer with non-zero size."); } switch (policy) { case OBSERVE: case TAKE_OWNERSHIP: initCommon(buf, sz, policy == TAKE_OWNERSHIP, sz); break; case COPY: initCommon(nullptr, sz, true, 0); this->write(buf, sz); break; default: throw TTransportException(TTransportException::BAD_ARGS, "Invalid MemoryPolicy for TMemoryBuffer"); } } ~TMemoryBuffer() override { if (owner_) { std::free(buffer_); } } bool isOpen() const override { return true; } bool peek() override { return (rBase_ < wBase_); } void open() override {} void close() override {} // TODO(dreiss): Make bufPtr const. void getBuffer(uint8_t** bufPtr, uint32_t* sz) { *bufPtr = rBase_; *sz = static_cast(wBase_ - rBase_); } std::string getBufferAsString() { if (buffer_ == nullptr) { return ""; } uint8_t* buf; uint32_t sz; getBuffer(&buf, &sz); return std::string((char*)buf, (std::string::size_type)sz); } void appendBufferToString(std::string& str) { if (buffer_ == nullptr) { return; } uint8_t* buf; uint32_t sz; getBuffer(&buf, &sz); str.append((char*)buf, sz); } void resetBuffer() { rBase_ = buffer_; rBound_ = buffer_; wBase_ = buffer_; // It isn't safe to write into a buffer we don't own. if (!owner_) { wBound_ = wBase_; bufferSize_ = 0; } } /// See constructor documentation. void resetBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) { // Use a variant of the copy-and-swap trick for assignment operators. // This is sub-optimal in terms of performance for two reasons: // 1/ The constructing and swapping of the (small) values // in the temporary object takes some time, and is not necessary. // 2/ If policy == COPY, we allocate the new buffer before // freeing the old one, precluding the possibility of // reusing that memory. // I doubt that either of these problems could be optimized away, // but the second is probably no a common case, and the first is minor. // I don't expect resetBuffer to be a common operation, so I'm willing to // bite the performance bullet to make the method this simple. // Construct the new buffer. TMemoryBuffer new_buffer(buf, sz, policy); // Move it into ourself. this->swap(new_buffer); // Our old self gets destroyed. } /// See constructor documentation. void resetBuffer(uint32_t sz) { // Construct the new buffer. TMemoryBuffer new_buffer(sz); // Move it into ourself. this->swap(new_buffer); // Our old self gets destroyed. } std::string readAsString(uint32_t len) { std::string str; (void)readAppendToString(str, len); return str; } uint32_t readAppendToString(std::string& str, uint32_t len); // return number of bytes read uint32_t readEnd() override { // This cast should be safe, because buffer_'s size is a uint32_t auto bytes = static_cast(rBase_ - buffer_); if (rBase_ == wBase_) { resetBuffer(); } resetConsumedMessageSize(); return bytes; } // Return number of bytes written uint32_t writeEnd() override { // This cast should be safe, because buffer_'s size is a uint32_t return static_cast(wBase_ - buffer_); } uint32_t available_read() const { // Remember, wBase_ is the real rBound_. return static_cast(wBase_ - rBase_); } uint32_t available_write() const { return static_cast(wBound_ - wBase_); } // Returns a pointer to where the client can write data to append to // the TMemoryBuffer, and ensures the buffer is big enough to accommodate a // write of the provided length. The returned pointer is very convenient for // passing to read(), recv(), or similar. You must call wroteBytes() as soon // as data is written or the buffer will not be aware that data has changed. uint8_t* getWritePtr(uint32_t len) { ensureCanWrite(len); return wBase_; } // Informs the buffer that the client has written 'len' bytes into storage // that had been provided by getWritePtr(). void wroteBytes(uint32_t len); /* * TVirtualTransport provides a default implementation of readAll(). * We want to use the TBufferBase version instead. */ uint32_t readAll(uint8_t* buf, uint32_t len) { return TBufferBase::readAll(buf, len); } //! \brief Get the current buffer size //! \returns the current buffer size uint32_t getBufferSize() const { return bufferSize_; } //! \brief Get the current maximum buffer size //! \returns the current maximum buffer size uint32_t getMaxBufferSize() const { return maxBufferSize_; } //! \brief Change the maximum buffer size //! \param[in] maxSize the new maximum buffer size allowed to grow to //! \throws TTransportException(BAD_ARGS) if maxSize is less than the current buffer size void setMaxBufferSize(uint32_t maxSize) { if (maxSize < bufferSize_) { throw TTransportException(TTransportException::BAD_ARGS, "Maximum buffer size would be less than current buffer size"); } maxBufferSize_ = maxSize; } protected: void swap(TMemoryBuffer& that) { using std::swap; swap(buffer_, that.buffer_); swap(bufferSize_, that.bufferSize_); swap(rBase_, that.rBase_); swap(rBound_, that.rBound_); swap(wBase_, that.wBase_); swap(wBound_, that.wBound_); swap(owner_, that.owner_); } // Make sure there's at least 'len' bytes available for writing. void ensureCanWrite(uint32_t len); // Compute the position and available data for reading. void computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give); uint32_t readSlow(uint8_t* buf, uint32_t len) override; void writeSlow(const uint8_t* buf, uint32_t len) override; const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) override; // Data buffer uint8_t* buffer_; // Allocated buffer size uint32_t bufferSize_; // Maximum allowed size uint32_t maxBufferSize_; // Is this object the owner of the buffer? bool owner_; // Don't forget to update constrctors, initCommon, and swap if // you add new members. }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TServerSocket.h0000644000000000000000000001300314370300523023460 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ #define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1 #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NETDB_H #include #endif namespace apache { namespace thrift { namespace transport { class TSocket; /** * Server socket implementation of TServerTransport. Wrapper around a unix * socket listen and accept calls. * */ class TServerSocket : public TServerTransport { public: typedef std::function socket_func_t; const static int DEFAULT_BACKLOG = 1024; /** * Constructor. * * @param port Port number to bind to */ TServerSocket(int port); /** * Constructor. * * @param port Port number to bind to * @param sendTimeout Socket send timeout * @param recvTimeout Socket receive timeout */ TServerSocket(int port, int sendTimeout, int recvTimeout); /** * Constructor. * * @param address Address to bind to * @param port Port number to bind to */ TServerSocket(const std::string& address, int port); /** * Constructor used for unix sockets. * * @param path Pathname for unix socket. */ TServerSocket(const std::string& path); ~TServerSocket() override; bool isOpen() const override; void setSendTimeout(int sendTimeout); void setRecvTimeout(int recvTimeout); void setAcceptTimeout(int accTimeout); void setAcceptBacklog(int accBacklog); void setRetryLimit(int retryLimit); void setRetryDelay(int retryDelay); void setKeepAlive(bool keepAlive) { keepAlive_ = keepAlive; } void setTcpSendBuffer(int tcpSendBuffer); void setTcpRecvBuffer(int tcpRecvBuffer); // listenCallback gets called just before listen, and after all Thrift // setsockopt calls have been made. If you have custom setsockopt // things that need to happen on the listening socket, this is the place to do it. void setListenCallback(const socket_func_t& listenCallback) { listenCallback_ = listenCallback; } // acceptCallback gets called after each accept call, on the newly created socket. // It is called after all Thrift setsockopt calls have been made. If you have // custom setsockopt things that need to happen on the accepted // socket, this is the place to do it. void setAcceptCallback(const socket_func_t& acceptCallback) { acceptCallback_ = acceptCallback; } // When enabled (the default), new children TSockets will be constructed so // they can be interrupted by TServerTransport::interruptChildren(). // This is more expensive in terms of system calls (poll + recv) however // ensures a connected client cannot interfere with TServer::stop(). // // When disabled, TSocket children do not incur an additional poll() call. // Server-side reads are more efficient, however a client can interfere with // the server's ability to shutdown properly by staying connected. // // Must be called before listen(); mode cannot be switched after that. // \throws std::logic_error if listen() has been called void setInterruptableChildren(bool enable); THRIFT_SOCKET getSocketFD() override { return serverSocket_; } int getPort() const; std::string getPath() const; bool isUnixDomainSocket() const; void listen() override; void interrupt() override; void interruptChildren() override; void close() override; protected: std::shared_ptr acceptImpl() override; virtual std::shared_ptr createSocket(THRIFT_SOCKET client); bool interruptableChildren_; std::shared_ptr pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets private: void notify(THRIFT_SOCKET notifySock); void _setup_sockopts(); void _setup_unixdomain_sockopts(); void _setup_tcp_sockopts(); int port_; std::string address_; std::string path_; THRIFT_SOCKET serverSocket_; int acceptBacklog_; int sendTimeout_; int recvTimeout_; int accTimeout_; int retryLimit_; int retryDelay_; int tcpSendBuffer_; int tcpRecvBuffer_; bool keepAlive_; bool listening_; concurrency::Mutex rwMutex_; // thread-safe interrupt THRIFT_SOCKET interruptSockWriter_; // is notified on interrupt() THRIFT_SOCKET interruptSockReader_; // is used in select/poll with serverSocket_ for interruptability THRIFT_SOCKET childInterruptSockWriter_; // is notified on interruptChildren() socket_func_t listenCallback_; socket_func_t acceptCallback_; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TSocket.cpp0000644000000000000000000006576514370300523022652 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #ifdef HAVE_SYS_IOCTL_H #include #ifdef __sun #include #endif // __sun #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif #include #ifdef HAVE_NETINET_IN_H #include #include #endif #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #ifndef SOCKOPT_CAST_T #ifndef _WIN32 #define SOCKOPT_CAST_T void #else #define SOCKOPT_CAST_T char #endif // _WIN32 #endif template inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { return reinterpret_cast(v); } template inline SOCKOPT_CAST_T* cast_sockopt(T* v) { return reinterpret_cast(v); } using std::string; namespace apache { namespace thrift { namespace transport { /** * TSocket implementation. * */ TSocket::TSocket(const string& host, int port, std::shared_ptr config) : TVirtualTransport(config), host_(host), port_(port), socket_(THRIFT_INVALID_SOCKET), peerPort_(0), connTimeout_(0), sendTimeout_(0), recvTimeout_(0), keepAlive_(false), lingerOn_(1), lingerVal_(0), noDelay_(1), maxRecvRetries_(5) { } TSocket::TSocket(const string& path, std::shared_ptr config) : TVirtualTransport(config), port_(0), path_(path), socket_(THRIFT_INVALID_SOCKET), peerPort_(0), connTimeout_(0), sendTimeout_(0), recvTimeout_(0), keepAlive_(false), lingerOn_(1), lingerVal_(0), noDelay_(1), maxRecvRetries_(5) { cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; } TSocket::TSocket(std::shared_ptr config) : TVirtualTransport(config), port_(0), socket_(THRIFT_INVALID_SOCKET), peerPort_(0), connTimeout_(0), sendTimeout_(0), recvTimeout_(0), keepAlive_(false), lingerOn_(1), lingerVal_(0), noDelay_(1), maxRecvRetries_(5) { cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; } TSocket::TSocket(THRIFT_SOCKET socket, std::shared_ptr config) : TVirtualTransport(config), port_(0), socket_(socket), peerPort_(0), connTimeout_(0), sendTimeout_(0), recvTimeout_(0), keepAlive_(false), lingerOn_(1), lingerVal_(0), noDelay_(1), maxRecvRetries_(5) { cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; #ifdef SO_NOSIGPIPE { int one = 1; setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); } #endif } TSocket::TSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener, std::shared_ptr config) : TVirtualTransport(config), port_(0), socket_(socket), peerPort_(0), interruptListener_(interruptListener), connTimeout_(0), sendTimeout_(0), recvTimeout_(0), keepAlive_(false), lingerOn_(1), lingerVal_(0), noDelay_(1), maxRecvRetries_(5) { cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; #ifdef SO_NOSIGPIPE { int one = 1; setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); } #endif } TSocket::~TSocket() { close(); } bool TSocket::hasPendingDataToRead() { if (!isOpen()) { return false; } int32_t retries = 0; THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE numBytesAvailable; try_again: int r = THRIFT_IOCTL_SOCKET(socket_, FIONREAD, &numBytesAvailable); if (r == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; if (errno_copy == THRIFT_EINTR && (retries++ < maxRecvRetries_)) { goto try_again; } GlobalOutput.perror("TSocket::hasPendingDataToRead() THRIFT_IOCTL_SOCKET() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); } return numBytesAvailable > 0; } bool TSocket::isOpen() const { return (socket_ != THRIFT_INVALID_SOCKET); } bool TSocket::peek() { if (!isOpen()) { return false; } if (interruptListener_) { for (int retries = 0;;) { struct THRIFT_POLLFD fds[2]; std::memset(fds, 0, sizeof(fds)); fds[0].fd = socket_; fds[0].events = THRIFT_POLLIN; fds[1].fd = *(interruptListener_.get()); fds[1].events = THRIFT_POLLIN; int ret = THRIFT_POLL(fds, 2, (recvTimeout_ == 0) ? -1 : recvTimeout_); int errno_copy = THRIFT_GET_SOCKET_ERROR; if (ret < 0) { // error cases if (errno_copy == THRIFT_EINTR && (retries++ < maxRecvRetries_)) { continue; } GlobalOutput.perror("TSocket::peek() THRIFT_POLL() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); } else if (ret > 0) { // Check the interruptListener if (fds[1].revents & THRIFT_POLLIN) { return false; } // There must be data or a disconnection, fall through to the PEEK break; } else { // timeout return false; } } } // Check to see if data is available or if the remote side closed uint8_t buf; int r = static_cast(recv(socket_, cast_sockopt(&buf), 1, MSG_PEEK)); if (r == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; #if defined __FreeBSD__ || defined __MACH__ /* shigin: * freebsd returns -1 and THRIFT_ECONNRESET if socket was closed by * the other side */ if (errno_copy == THRIFT_ECONNRESET) { return false; } #endif GlobalOutput.perror("TSocket::peek() recv() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::UNKNOWN, "recv()", errno_copy); } return (r > 0); } void TSocket::openConnection(struct addrinfo* res) { if (isOpen()) { return; } if (isUnixDomainSocket()) { socket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); } else { socket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); } if (socket_ == THRIFT_INVALID_SOCKET) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() socket() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "socket()", errno_copy); } // Send timeout if (sendTimeout_ > 0) { setSendTimeout(sendTimeout_); } // Recv timeout if (recvTimeout_ > 0) { setRecvTimeout(recvTimeout_); } if (keepAlive_) { setKeepAlive(keepAlive_); } // Linger setLinger(lingerOn_, lingerVal_); // No delay setNoDelay(noDelay_); #ifdef SO_NOSIGPIPE { int one = 1; setsockopt(socket_, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one)); } #endif // Uses a low min RTO if asked to. #ifdef TCP_LOW_MIN_RTO if (getUseLowMinRto()) { int one = 1; setsockopt(socket_, IPPROTO_TCP, TCP_LOW_MIN_RTO, &one, sizeof(one)); } #endif // Set the socket to be non blocking for connect if a timeout exists int flags = THRIFT_FCNTL(socket_, THRIFT_F_GETFL, 0); if (connTimeout_ > 0) { if (-1 == THRIFT_FCNTL(socket_, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() THRIFT_FCNTL() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() failed", errno_copy); } } else { if (-1 == THRIFT_FCNTL(socket_, THRIFT_F_SETFL, flags & ~THRIFT_O_NONBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() THRIFT_FCNTL " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() failed", errno_copy); } } // Connect the socket int ret; if (isUnixDomainSocket()) { // Windows supports Unix domain sockets since it ships the header // HAVE_AF_UNIX_H (see https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/) #if (!defined(_WIN32) || defined(HAVE_AF_UNIX_H)) struct sockaddr_un address; socklen_t structlen = fillUnixSocketAddr(address, path_); ret = connect(socket_, (struct sockaddr*)&address, structlen); #else GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on this version of Windows", -99); throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported"); #endif } else { ret = connect(socket_, res->ai_addr, static_cast(res->ai_addrlen)); } // success case if (ret == 0) { goto done; } if ((THRIFT_GET_SOCKET_ERROR != THRIFT_EINPROGRESS) && (THRIFT_GET_SOCKET_ERROR != THRIFT_EWOULDBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() connect() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "connect() failed", errno_copy); } struct THRIFT_POLLFD fds[1]; std::memset(fds, 0, sizeof(fds)); fds[0].fd = socket_; fds[0].events = THRIFT_POLLOUT; ret = THRIFT_POLL(fds, 1, connTimeout_); if (ret > 0) { // Ensure the socket is connected and that there are no errors set int val; socklen_t lon; lon = sizeof(int); int ret2 = getsockopt(socket_, SOL_SOCKET, SO_ERROR, cast_sockopt(&val), &lon); if (ret2 == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() getsockopt() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "getsockopt()", errno_copy); } // no errors on socket, go to town if (val == 0) { goto done; } GlobalOutput.perror("TSocket::open() error on socket (after THRIFT_POLL) " + getSocketInfo(), val); throw TTransportException(TTransportException::NOT_OPEN, "socket open() error", val); } else if (ret == 0) { // socket timed out string errStr = "TSocket::open() timed out " + getSocketInfo(); GlobalOutput(errStr.c_str()); throw TTransportException(TTransportException::NOT_OPEN, "open() timed out"); } else { // error on THRIFT_POLL() int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() THRIFT_POLL() " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_POLL() failed", errno_copy); } done: // Set socket back to normal mode (blocking) if (-1 == THRIFT_FCNTL(socket_, THRIFT_F_SETFL, flags)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() THRIFT_FCNTL " + getSocketInfo(), errno_copy); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() failed", errno_copy); } if (!isUnixDomainSocket()) { setCachedAddress(res->ai_addr, static_cast(res->ai_addrlen)); } } void TSocket::open() { if (isOpen()) { return; } if (isUnixDomainSocket()) { unix_open(); } else { local_open(); } } void TSocket::unix_open() { if (isUnixDomainSocket()) { // Unix Domain Socket does not need addrinfo struct, so we pass NULL openConnection(nullptr); } } void TSocket::local_open() { #ifdef _WIN32 TWinsockSingleton::create(); #endif // _WIN32 if (isOpen()) { return; } // Validate port number if (port_ < 0 || port_ > 0xFFFF) { throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid"); } struct addrinfo hints, *res, *res0; res = nullptr; res0 = nullptr; int error; char port[sizeof("65535")]; std::memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; sprintf(port, "%d", port_); error = getaddrinfo(host_.c_str(), port, &hints, &res0); if ( #ifdef _WIN32 error == WSANO_DATA #else error == EAI_NODATA #endif ) { hints.ai_flags &= ~AI_ADDRCONFIG; error = getaddrinfo(host_.c_str(), port, &hints, &res0); } if (error) { string errStr = "TSocket::open() getaddrinfo() " + getSocketInfo() + string(THRIFT_GAI_STRERROR(error)); GlobalOutput(errStr.c_str()); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for client socket."); } // Cycle through all the returned addresses until one // connects or push the exception up. for (res = res0; res; res = res->ai_next) { try { openConnection(res); break; } catch (TTransportException&) { if (res->ai_next) { close(); } else { close(); freeaddrinfo(res0); // cleanup on failure throw; } } } // Free address structure memory freeaddrinfo(res0); } void TSocket::close() { if (socket_ != THRIFT_INVALID_SOCKET) { shutdown(socket_, THRIFT_SHUT_RDWR); ::THRIFT_CLOSESOCKET(socket_); } socket_ = THRIFT_INVALID_SOCKET; } void TSocket::setSocketFD(THRIFT_SOCKET socket) { if (socket_ != THRIFT_INVALID_SOCKET) { close(); } socket_ = socket; } uint32_t TSocket::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); if (socket_ == THRIFT_INVALID_SOCKET) { throw TTransportException(TTransportException::NOT_OPEN, "Called read on non-open socket"); } int32_t retries = 0; // THRIFT_EAGAIN can be signalled both when a timeout has occurred and when // the system is out of resources (an awesome undocumented feature). // The following is an approximation of the time interval under which // THRIFT_EAGAIN is taken to indicate an out of resources error. uint32_t eagainThresholdMicros = 0; if (recvTimeout_) { // if a readTimeout is specified along with a max number of recv retries, then // the threshold will ensure that the read timeout is not exceeded even in the // case of resource errors eagainThresholdMicros = (recvTimeout_ * 1000) / ((maxRecvRetries_ > 0) ? maxRecvRetries_ : 2); } try_again: // Read from the socket struct timeval begin; if (recvTimeout_ > 0) { THRIFT_GETTIMEOFDAY(&begin, nullptr); } else { // if there is no read timeout we don't need the TOD to determine whether // an THRIFT_EAGAIN is due to a timeout or an out-of-resource condition. begin.tv_sec = begin.tv_usec = 0; } int got = 0; if (interruptListener_) { struct THRIFT_POLLFD fds[2]; std::memset(fds, 0, sizeof(fds)); fds[0].fd = socket_; fds[0].events = THRIFT_POLLIN; fds[1].fd = *(interruptListener_.get()); fds[1].events = THRIFT_POLLIN; int ret = THRIFT_POLL(fds, 2, (recvTimeout_ == 0) ? -1 : recvTimeout_); int errno_copy = THRIFT_GET_SOCKET_ERROR; if (ret < 0) { // error cases if (errno_copy == THRIFT_EINTR && (retries++ < maxRecvRetries_)) { goto try_again; } GlobalOutput.perror("TSocket::read() THRIFT_POLL() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); } else if (ret > 0) { // Check the interruptListener if (fds[1].revents & THRIFT_POLLIN) { throw TTransportException(TTransportException::INTERRUPTED, "Interrupted"); } } else /* ret == 0 */ { GlobalOutput.perror("TSocket::read() THRIFT_EAGAIN (timed out) after %f ms", recvTimeout_); throw TTransportException(TTransportException::TIMED_OUT, "THRIFT_EAGAIN (timed out)"); } // falling through means there is something to recv and it cannot block } got = static_cast(recv(socket_, cast_sockopt(buf), len, 0)); // THRIFT_GETTIMEOFDAY can change THRIFT_GET_SOCKET_ERROR int errno_copy = THRIFT_GET_SOCKET_ERROR; // Check for error on read if (got < 0) { if (errno_copy == THRIFT_EAGAIN) { // if no timeout we can assume that resource exhaustion has occurred. if (recvTimeout_ == 0) { throw TTransportException(TTransportException::TIMED_OUT, "THRIFT_EAGAIN (unavailable resources)"); } // check if this is the lack of resources or timeout case struct timeval end; THRIFT_GETTIMEOFDAY(&end, nullptr); auto readElapsedMicros = static_cast(((end.tv_sec - begin.tv_sec) * 1000 * 1000) + (end.tv_usec - begin.tv_usec)); if (!eagainThresholdMicros || (readElapsedMicros < eagainThresholdMicros)) { if (retries++ < maxRecvRetries_) { THRIFT_SLEEP_USEC(50); goto try_again; } else { throw TTransportException(TTransportException::TIMED_OUT, "THRIFT_EAGAIN (unavailable resources)"); } } else { // infer that timeout has been hit throw TTransportException(TTransportException::TIMED_OUT, "THRIFT_EAGAIN (timed out)"); } } // If interrupted, try again if (errno_copy == THRIFT_EINTR && retries++ < maxRecvRetries_) { goto try_again; } if (errno_copy == THRIFT_ECONNRESET) { return 0; } // This ish isn't open if (errno_copy == THRIFT_ENOTCONN) { throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_ENOTCONN"); } // Timed out! if (errno_copy == THRIFT_ETIMEDOUT) { throw TTransportException(TTransportException::TIMED_OUT, "THRIFT_ETIMEDOUT"); } // Now it's not a try again case, but a real probblez GlobalOutput.perror("TSocket::read() recv() " + getSocketInfo(), errno_copy); // Some other error, whatevz throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); } return got; } void TSocket::write(const uint8_t* buf, uint32_t len) { uint32_t sent = 0; while (sent < len) { uint32_t b = write_partial(buf + sent, len - sent); if (b == 0) { // This should only happen if the timeout set with SO_SNDTIMEO expired. // Raise an exception. throw TTransportException(TTransportException::TIMED_OUT, "send timeout expired"); } sent += b; } } uint32_t TSocket::write_partial(const uint8_t* buf, uint32_t len) { if (socket_ == THRIFT_INVALID_SOCKET) { throw TTransportException(TTransportException::NOT_OPEN, "Called write on non-open socket"); } uint32_t sent = 0; int flags = 0; #ifdef MSG_NOSIGNAL // Note the use of MSG_NOSIGNAL to suppress SIGPIPE errors, instead we // check for the THRIFT_EPIPE return condition and close the socket in that case flags |= MSG_NOSIGNAL; #endif // ifdef MSG_NOSIGNAL int b = static_cast(send(socket_, const_cast_sockopt(buf + sent), len - sent, flags)); if (b < 0) { if (THRIFT_GET_SOCKET_ERROR == THRIFT_EWOULDBLOCK || THRIFT_GET_SOCKET_ERROR == THRIFT_EAGAIN) { return 0; } // Fail on a send error int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::write_partial() send() " + getSocketInfo(), errno_copy); if (errno_copy == THRIFT_EPIPE || errno_copy == THRIFT_ECONNRESET || errno_copy == THRIFT_ENOTCONN) { throw TTransportException(TTransportException::NOT_OPEN, "write() send()", errno_copy); } throw TTransportException(TTransportException::UNKNOWN, "write() send()", errno_copy); } // Fail on blocked send if (b == 0) { throw TTransportException(TTransportException::NOT_OPEN, "Socket send returned 0."); } return b; } std::string TSocket::getHost() const { return host_; } int TSocket::getPort() const { return port_; } std::string TSocket::getPath() const { return path_; } bool TSocket::isUnixDomainSocket() const { return !path_.empty(); } void TSocket::setHost(string host) { host_ = host; } void TSocket::setPort(int port) { port_ = port; } void TSocket::setPath(std::string path) { path_ = path; } void TSocket::setLinger(bool on, int linger) { lingerOn_ = on; lingerVal_ = linger; if (socket_ == THRIFT_INVALID_SOCKET) { return; } #ifndef _WIN32 struct linger l = {(lingerOn_ ? 1 : 0), lingerVal_}; #else struct linger l = {static_cast(lingerOn_ ? 1 : 0), static_cast(lingerVal_)}; #endif int ret = setsockopt(socket_, SOL_SOCKET, SO_LINGER, cast_sockopt(&l), sizeof(l)); if (ret == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; // Copy THRIFT_GET_SOCKET_ERROR because we're allocating memory. GlobalOutput.perror("TSocket::setLinger() setsockopt() " + getSocketInfo(), errno_copy); } } void TSocket::setNoDelay(bool noDelay) { noDelay_ = noDelay; if (socket_ == THRIFT_INVALID_SOCKET || isUnixDomainSocket()) { return; } // Set socket to NODELAY int v = noDelay_ ? 1 : 0; int ret = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, cast_sockopt(&v), sizeof(v)); if (ret == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; // Copy THRIFT_GET_SOCKET_ERROR because we're allocating memory. GlobalOutput.perror("TSocket::setNoDelay() setsockopt() " + getSocketInfo(), errno_copy); } } void TSocket::setConnTimeout(int ms) { connTimeout_ = ms; } void setGenericTimeout(THRIFT_SOCKET s, int timeout_ms, int optname) { if (timeout_ms < 0) { char errBuf[512]; sprintf(errBuf, "TSocket::setGenericTimeout with negative input: %d\n", timeout_ms); GlobalOutput(errBuf); return; } if (s == THRIFT_INVALID_SOCKET) { return; } #ifdef _WIN32 DWORD platform_time = static_cast(timeout_ms); #else struct timeval platform_time = {(int)(timeout_ms / 1000), (int)((timeout_ms % 1000) * 1000)}; #endif int ret = setsockopt(s, SOL_SOCKET, optname, cast_sockopt(&platform_time), sizeof(platform_time)); if (ret == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; // Copy THRIFT_GET_SOCKET_ERROR because we're allocating memory. GlobalOutput.perror("TSocket::setGenericTimeout() setsockopt() ", errno_copy); } } void TSocket::setRecvTimeout(int ms) { setGenericTimeout(socket_, ms, SO_RCVTIMEO); recvTimeout_ = ms; } void TSocket::setSendTimeout(int ms) { setGenericTimeout(socket_, ms, SO_SNDTIMEO); sendTimeout_ = ms; } void TSocket::setKeepAlive(bool keepAlive) { keepAlive_ = keepAlive; if (socket_ == THRIFT_INVALID_SOCKET) { return; } #ifdef _WIN32 if (isUnixDomainSocket()) { // Windows Domain sockets do not support SO_KEEPALIVE. return; } #endif int value = keepAlive_; int ret = setsockopt(socket_, SOL_SOCKET, SO_KEEPALIVE, const_cast_sockopt(&value), sizeof(value)); if (ret == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; // Copy THRIFT_GET_SOCKET_ERROR because we're allocating memory. GlobalOutput.perror("TSocket::setKeepAlive() setsockopt() " + getSocketInfo(), errno_copy); } } void TSocket::setMaxRecvRetries(int maxRecvRetries) { maxRecvRetries_ = maxRecvRetries; } string TSocket::getSocketInfo() const { std::ostringstream oss; if (!isUnixDomainSocket()) { if (host_.empty() || port_ == 0) { oss << ""; } else { oss << ""; } } else { std::string fmt_path_ = path_; // Handle printing abstract sockets (first character is a '\0' char): if (!fmt_path_.empty() && fmt_path_[0] == '\0') fmt_path_[0] = '@'; oss << ""; } return oss.str(); } std::string TSocket::getPeerHost() const { if (peerHost_.empty() && !isUnixDomainSocket()) { struct sockaddr_storage addr; struct sockaddr* addrPtr; socklen_t addrLen; if (socket_ == THRIFT_INVALID_SOCKET) { return host_; } addrPtr = getCachedAddress(&addrLen); if (addrPtr == nullptr) { addrLen = sizeof(addr); if (getpeername(socket_, (sockaddr*)&addr, &addrLen) != 0) { return peerHost_; } addrPtr = (sockaddr*)&addr; const_cast(*this).setCachedAddress(addrPtr, addrLen); } char clienthost[NI_MAXHOST]; char clientservice[NI_MAXSERV]; getnameinfo((sockaddr*)addrPtr, addrLen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), 0); peerHost_ = clienthost; } return peerHost_; } std::string TSocket::getPeerAddress() const { if (peerAddress_.empty() && !isUnixDomainSocket()) { struct sockaddr_storage addr; struct sockaddr* addrPtr; socklen_t addrLen; if (socket_ == THRIFT_INVALID_SOCKET) { return peerAddress_; } addrPtr = getCachedAddress(&addrLen); if (addrPtr == nullptr) { addrLen = sizeof(addr); if (getpeername(socket_, (sockaddr*)&addr, &addrLen) != 0) { return peerAddress_; } addrPtr = (sockaddr*)&addr; const_cast(*this).setCachedAddress(addrPtr, addrLen); } char clienthost[NI_MAXHOST]; char clientservice[NI_MAXSERV]; getnameinfo(addrPtr, addrLen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST | NI_NUMERICSERV); peerAddress_ = clienthost; peerPort_ = std::atoi(clientservice); } return peerAddress_; } int TSocket::getPeerPort() const { getPeerAddress(); return peerPort_; } void TSocket::setCachedAddress(const sockaddr* addr, socklen_t len) { if (isUnixDomainSocket()) { return; } switch (addr->sa_family) { case AF_INET: if (len == sizeof(sockaddr_in)) { memcpy((void*)&cachedPeerAddr_.ipv4, (void*)addr, len); } break; case AF_INET6: if (len == sizeof(sockaddr_in6)) { memcpy((void*)&cachedPeerAddr_.ipv6, (void*)addr, len); } break; } peerAddress_.clear(); peerHost_.clear(); } sockaddr* TSocket::getCachedAddress(socklen_t* len) const { switch (cachedPeerAddr_.ipv4.sin_family) { case AF_INET: *len = sizeof(sockaddr_in); return (sockaddr*)&cachedPeerAddr_.ipv4; case AF_INET6: *len = sizeof(sockaddr_in6); return (sockaddr*)&cachedPeerAddr_.ipv6; default: return nullptr; } } bool TSocket::useLowMinRto_ = false; void TSocket::setUseLowMinRto(bool useLowMinRto) { useLowMinRto_ = useLowMinRto; } bool TSocket::getUseLowMinRto() { return useLowMinRto_; } const std::string TSocket::getOrigin() const { std::ostringstream oss; oss << getPeerHost() << ":" << getPeerPort(); return oss.str(); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TShortReadTransport.h0000644000000000000000000000526414303740367024675 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ #define _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ 1 #include #include #include namespace apache { namespace thrift { namespace transport { namespace test { /** * This class is only meant for testing. It wraps another transport. * Calls to read are passed through with some probability. Otherwise, * the read amount is randomly reduced before being passed through. * */ class TShortReadTransport : public TVirtualTransport { public: TShortReadTransport(std::shared_ptr transport, double full_prob, std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), fullProb_(full_prob) { } bool isOpen() const override { return transport_->isOpen(); } bool peek() override { return transport_->peek(); } void open() override { transport_->open(); } void close() override { transport_->close(); } uint32_t read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); if (len == 0) { return 0; } if (rand() / (double)RAND_MAX >= fullProb_) { len = 1 + rand() % len; } return transport_->read(buf, len); } void write(const uint8_t* buf, uint32_t len) { transport_->write(buf, len); } void flush() override { resetConsumedMessageSize(); transport_->flush(); } const uint8_t* borrow(uint8_t* buf, uint32_t* len) { return transport_->borrow(buf, len); } void consume(uint32_t len) { countConsumedMessageBytes(len); return transport_->consume(len); } std::shared_ptr getUnderlyingTransport() { return transport_; } protected: std::shared_ptr transport_; double fullProb_; }; } } } } // apache::thrift::transport::test #endif // #ifndef _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TZlibTransport.h0000644000000000000000000001631614303740367023702 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ #define _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ 1 #include #include #include #include struct z_stream_s; namespace apache { namespace thrift { namespace transport { class TZlibTransportException : public TTransportException { public: TZlibTransportException(int status, const char* msg) : TTransportException(TTransportException::INTERNAL_ERROR, errorMessage(status, msg)), zlib_status_(status), zlib_msg_(msg == nullptr ? "(null)" : msg) {} ~TZlibTransportException() noexcept override = default; int getZlibStatus() { return zlib_status_; } std::string getZlibMessage() { return zlib_msg_; } static std::string errorMessage(int status, const char* msg) { std::string rv = "zlib error: "; if (msg) { rv += msg; } else { rv += "(no message)"; } rv += " (status = "; rv += to_string(status); rv += ")"; return rv; } int zlib_status_; std::string zlib_msg_; }; /** * This transport uses zlib to compress on write and decompress on read * * TODO(dreiss): Don't do an extra copy of the compressed data if * the underlying transport is TBuffered or TMemory. * */ class TZlibTransport : public TVirtualTransport { public: /** * @param transport The transport to read compressed data from * and write compressed data to. * @param urbuf_size Uncompressed buffer size for reading. * @param crbuf_size Compressed buffer size for reading. * @param uwbuf_size Uncompressed buffer size for writing. * @param cwbuf_size Compressed buffer size for writing. * @param comp_level Compression level (0=none[fast], 6=default, 9=max[slow]). */ TZlibTransport(std::shared_ptr transport, int urbuf_size = DEFAULT_URBUF_SIZE, int crbuf_size = DEFAULT_CRBUF_SIZE, int uwbuf_size = DEFAULT_UWBUF_SIZE, int cwbuf_size = DEFAULT_CWBUF_SIZE, int16_t comp_level = Z_DEFAULT_COMPRESSION, std::shared_ptr config = nullptr) : TVirtualTransport(config), transport_(transport), urpos_(0), uwpos_(0), input_ended_(false), output_finished_(false), urbuf_size_(urbuf_size), crbuf_size_(crbuf_size), uwbuf_size_(uwbuf_size), cwbuf_size_(cwbuf_size), urbuf_(nullptr), crbuf_(nullptr), uwbuf_(nullptr), cwbuf_(nullptr), rstream_(nullptr), wstream_(nullptr), comp_level_(comp_level) { if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE) { // Have to copy this into a local because of a linking issue. int minimum = MIN_DIRECT_DEFLATE_SIZE; throw TTransportException(TTransportException::BAD_ARGS, "TZLibTransport: uncompressed write buffer must be at least" + to_string(minimum) + "."); } try { urbuf_ = new uint8_t[urbuf_size]; crbuf_ = new uint8_t[crbuf_size]; uwbuf_ = new uint8_t[uwbuf_size]; cwbuf_ = new uint8_t[cwbuf_size]; // Don't call this outside of the constructor. initZlib(); } catch (...) { delete[] urbuf_; delete[] crbuf_; delete[] uwbuf_; delete[] cwbuf_; throw; } } // Don't call this outside of the constructor. void initZlib(); /** * TZlibTransport destructor. * * Warning: Destroying a TZlibTransport object may discard any written but * unflushed data. You must explicitly call flush() or finish() to ensure * that data is actually written and flushed to the underlying transport. */ ~TZlibTransport() override; bool isOpen() const override; bool peek() override; void open() override { transport_->open(); } void close() override { transport_->close(); } uint32_t read(uint8_t* buf, uint32_t len); void write(const uint8_t* buf, uint32_t len); void flush() override; /** * Finalize the zlib stream. * * This causes zlib to flush any pending write data and write end-of-stream * information, including the checksum. Once finish() has been called, no * new data can be written to the stream. */ void finish(); const uint8_t* borrow(uint8_t* buf, uint32_t* len); void consume(uint32_t len); /** * Verify the checksum at the end of the zlib stream. * * This may only be called after all data has been read. * It verifies the checksum that was written by the finish() call. */ void verifyChecksum(); /** * TODO(someone_smart): Choose smart defaults. */ static const int DEFAULT_URBUF_SIZE = 128; static const int DEFAULT_CRBUF_SIZE = 1024; static const int DEFAULT_UWBUF_SIZE = 128; static const int DEFAULT_CWBUF_SIZE = 1024; std::shared_ptr getUnderlyingTransport() const { return transport_; } protected: inline void checkZlibRv(int status, const char* msg); inline void checkZlibRvNothrow(int status, const char* msg); inline int readAvail() const; void flushToTransport(int flush); void flushToZlib(const uint8_t* buf, int len, int flush); bool readFromZlib(); protected: // Writes smaller than this are buffered up. // Larger (or equal) writes are dumped straight to zlib. static const uint32_t MIN_DIRECT_DEFLATE_SIZE = 32; std::shared_ptr transport_; int urpos_; int uwpos_; /// True iff zlib has reached the end of the input stream. bool input_ended_; /// True iff we have finished the output stream. bool output_finished_; uint32_t urbuf_size_; uint32_t crbuf_size_; uint32_t uwbuf_size_; uint32_t cwbuf_size_; uint8_t* urbuf_; uint8_t* crbuf_; uint8_t* uwbuf_; uint8_t* cwbuf_; struct z_stream_s* rstream_; struct z_stream_s* wstream_; const int comp_level_; }; /** * Wraps a transport into a zlibbed one. * */ class TZlibTransportFactory : public TTransportFactory { public: TZlibTransportFactory() = default; /** * Wraps a transport factory into a zlibbed one. */ TZlibTransportFactory(std::shared_ptr transportFactory); ~TZlibTransportFactory() override = default; std::shared_ptr getTransport(std::shared_ptr trans) override; protected: std::shared_ptr transportFactory_; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/THeaderTransport.cpp0000644000000000000000000004716214303740367024530 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include using std::map; using std::string; using std::vector; namespace apache { namespace thrift { using std::shared_ptr; namespace transport { using namespace apache::thrift::protocol; using apache::thrift::protocol::TBinaryProtocol; uint32_t THeaderTransport::readSlow(uint8_t* buf, uint32_t len) { if (clientType == THRIFT_UNFRAMED_BINARY || clientType == THRIFT_UNFRAMED_COMPACT) { return transport_->read(buf, len); } return TFramedTransport::readSlow(buf, len); } uint16_t THeaderTransport::getProtocolId() const { if (clientType == THRIFT_HEADER_CLIENT_TYPE) { return protoId; } else if (clientType == THRIFT_UNFRAMED_COMPACT || clientType == THRIFT_FRAMED_COMPACT) { return T_COMPACT_PROTOCOL; } else { return T_BINARY_PROTOCOL; // Assume other transports use TBinary } } void THeaderTransport::ensureReadBuffer(uint32_t sz) { if (sz > rBufSize_) { rBuf_.reset(new uint8_t[sz]); rBufSize_ = sz; } } bool THeaderTransport::readFrame() { // szN is network byte order of sz uint32_t szN; uint32_t sz; // Read the size of the next frame. // We can't use readAll(&sz, sizeof(sz)), since that always throws an // exception on EOF. We want to throw an exception only if EOF occurs after // partial size data. uint32_t sizeBytesRead = 0; while (sizeBytesRead < sizeof(szN)) { uint8_t* szp = reinterpret_cast(&szN) + sizeBytesRead; uint32_t bytesRead = transport_->read(szp, sizeof(szN) - sizeBytesRead); if (bytesRead == 0) { if (sizeBytesRead == 0) { // EOF before any data was read. return false; } else { // EOF after a partial frame header. Raise an exception. throw TTransportException(TTransportException::END_OF_FILE, "No more data to read after " "partial frame header."); } } sizeBytesRead += bytesRead; } sz = ntohl(szN); ensureReadBuffer(4); if ((sz & TBinaryProtocol::VERSION_MASK) == (uint32_t)TBinaryProtocol::VERSION_1) { // unframed clientType = THRIFT_UNFRAMED_BINARY; memcpy(rBuf_.get(), &szN, sizeof(szN)); setReadBuffer(rBuf_.get(), 4); } else if (static_cast(sz >> 24) == TCompactProtocol::PROTOCOL_ID && (static_cast(sz >> 16) & TCompactProtocol::VERSION_MASK) == TCompactProtocol::VERSION_N) { clientType = THRIFT_UNFRAMED_COMPACT; memcpy(rBuf_.get(), &szN, sizeof(szN)); setReadBuffer(rBuf_.get(), 4); } else { // Could be header format or framed. Check next uint32 uint32_t magic_n; uint32_t magic; if (sz > MAX_FRAME_SIZE) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Header transport frame is too large"); } ensureReadBuffer(sz); // We can use readAll here, because it would be an invalid frame otherwise transport_->readAll(reinterpret_cast(&magic_n), sizeof(magic_n)); memcpy(rBuf_.get(), &magic_n, sizeof(magic_n)); magic = ntohl(magic_n); if ((magic & TBinaryProtocol::VERSION_MASK) == (uint32_t)TBinaryProtocol::VERSION_1) { // framed clientType = THRIFT_FRAMED_BINARY; transport_->readAll(rBuf_.get() + 4, sz - 4); setReadBuffer(rBuf_.get(), sz); } else if (static_cast(magic >> 24) == TCompactProtocol::PROTOCOL_ID && (static_cast(magic >> 16) & TCompactProtocol::VERSION_MASK) == TCompactProtocol::VERSION_N) { clientType = THRIFT_FRAMED_COMPACT; transport_->readAll(rBuf_.get() + 4, sz - 4); setReadBuffer(rBuf_.get(), sz); } else if (HEADER_MAGIC == (magic & HEADER_MASK)) { if (sz < 10) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Header transport frame is too small"); } transport_->readAll(rBuf_.get() + 4, sz - 4); // header format clientType = THRIFT_HEADER_CLIENT_TYPE; // flags flags = magic & FLAGS_MASK; // seqId uint32_t seqId_n; memcpy(&seqId_n, rBuf_.get() + 4, sizeof(seqId_n)); seqId = ntohl(seqId_n); // header size uint16_t headerSize_n; memcpy(&headerSize_n, rBuf_.get() + 8, sizeof(headerSize_n)); uint16_t headerSize = ntohs(headerSize_n); setReadBuffer(rBuf_.get(), sz); readHeaderFormat(headerSize, sz); } else { clientType = THRIFT_UNKNOWN_CLIENT_TYPE; throw TTransportException(TTransportException::BAD_ARGS, "Could not detect client transport type"); } } return true; } /** * Reads a string from ptr, taking care not to reach headerBoundary * Advances ptr on success * * @param str output string * @throws CORRUPTED_DATA if size of string exceeds boundary */ void THeaderTransport::readString(uint8_t*& ptr, /* out */ string& str, uint8_t const* headerBoundary) { int32_t strLen; uint32_t bytes = readVarint32(ptr, &strLen, headerBoundary); if (strLen > headerBoundary - ptr) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Info header length exceeds header size"); } ptr += bytes; str.assign(reinterpret_cast(ptr), strLen); ptr += strLen; } void THeaderTransport::readHeaderFormat(uint16_t headerSize, uint32_t sz) { readTrans_.clear(); // Clear out any previous transforms. readHeaders_.clear(); // Clear out any previous headers. // skip over already processed magic(4), seqId(4), headerSize(2) auto* ptr = reinterpret_cast(rBuf_.get() + 10); // Catch integer overflow, check for reasonable header size if (headerSize >= 16384) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Header size is unreasonable"); } headerSize *= 4; const uint8_t* const headerBoundary = ptr + headerSize; if (headerSize > sz) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Header size is larger than frame"); } uint8_t* data = ptr + headerSize; ptr += readVarint16(ptr, &protoId, headerBoundary); int16_t numTransforms; ptr += readVarint16(ptr, &numTransforms, headerBoundary); // For now all transforms consist of only the ID, not data. for (int i = 0; i < numTransforms; i++) { int32_t transId; ptr += readVarint32(ptr, &transId, headerBoundary); readTrans_.push_back(transId); } // Info headers while (ptr < headerBoundary) { int32_t infoId; ptr += readVarint32(ptr, &infoId, headerBoundary); if (infoId == 0) { // header padding break; } if (infoId >= infoIdType::END) { // cannot handle infoId break; } switch (infoId) { case infoIdType::KEYVALUE: // Process key-value headers uint32_t numKVHeaders; ptr += readVarint32(ptr, (int32_t*)&numKVHeaders, headerBoundary); // continue until we reach (padded) end of packet while (numKVHeaders-- && ptr < headerBoundary) { // format: key; value // both: length (varint32); value (string) string key, value; readString(ptr, key, headerBoundary); // value readString(ptr, value, headerBoundary); // save to headers readHeaders_[key] = value; } break; } } // Untransform the data section. rBuf will contain result. untransform(data, safe_numeric_cast(static_cast(sz) - (data - rBuf_.get()))); } void THeaderTransport::untransform(uint8_t* ptr, uint32_t sz) { // Update the transform buffer size if needed resizeTransformBuffer(); for (vector::const_iterator it = readTrans_.begin(); it != readTrans_.end(); ++it) { const uint16_t transId = *it; if (transId == ZLIB_TRANSFORM) { z_stream stream; int err; stream.next_in = ptr; stream.avail_in = sz; // Setting these to 0 means use the default free/alloc functions stream.zalloc = (alloc_func)nullptr; stream.zfree = (free_func)nullptr; stream.opaque = (voidpf)nullptr; err = inflateInit(&stream); if (err != Z_OK) { throw TApplicationException(TApplicationException::MISSING_RESULT, "Error while zlib deflateInit"); } stream.next_out = tBuf_.get(); stream.avail_out = tBufSize_; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END || stream.avail_out == 0) { throw TApplicationException(TApplicationException::MISSING_RESULT, "Error while zlib deflate"); } sz = stream.total_out; err = inflateEnd(&stream); if (err != Z_OK) { throw TApplicationException(TApplicationException::MISSING_RESULT, "Error while zlib deflateEnd"); } memcpy(ptr, tBuf_.get(), sz); } else { throw TApplicationException(TApplicationException::MISSING_RESULT, "Unknown transform"); } } setReadBuffer(ptr, sz); } /** * We may have updated the wBuf size, update the tBuf size to match. * Should be called in transform. * * The buffer should be slightly larger than write buffer size due to * compression transforms (that may slightly grow on small frame sizes) */ void THeaderTransport::resizeTransformBuffer(uint32_t additionalSize) { if (tBufSize_ < wBufSize_ + DEFAULT_BUFFER_SIZE) { uint32_t new_size = wBufSize_ + DEFAULT_BUFFER_SIZE + additionalSize; auto* new_buf = new uint8_t[new_size]; tBuf_.reset(new_buf); tBufSize_ = new_size; } } void THeaderTransport::transform(uint8_t* ptr, uint32_t sz) { // Update the transform buffer size if needed resizeTransformBuffer(); for (vector::const_iterator it = writeTrans_.begin(); it != writeTrans_.end(); ++it) { const uint16_t transId = *it; if (transId == ZLIB_TRANSFORM) { z_stream stream; int err; stream.next_in = ptr; stream.avail_in = sz; stream.zalloc = (alloc_func)nullptr; stream.zfree = (free_func)nullptr; stream.opaque = (voidpf)nullptr; err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); if (err != Z_OK) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Error while zlib deflateInit"); } uint32_t tbuf_size = 0; while (err == Z_OK) { resizeTransformBuffer(tbuf_size); stream.next_out = tBuf_.get(); stream.avail_out = tBufSize_; err = deflate(&stream, Z_FINISH); tbuf_size += DEFAULT_BUFFER_SIZE; } sz = stream.total_out; err = deflateEnd(&stream); if (err != Z_OK) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Error while zlib deflateEnd"); } memcpy(ptr, tBuf_.get(), sz); } else { throw TTransportException(TTransportException::CORRUPTED_DATA, "Unknown transform"); } } wBase_ = wBuf_.get() + sz; } void THeaderTransport::resetProtocol() { // Set to anything except HTTP type so we don't flush again clientType = THRIFT_HEADER_CLIENT_TYPE; // Read the header and decide which protocol to go with readFrame(); } uint32_t THeaderTransport::getWriteBytes() { return safe_numeric_cast(wBase_ - wBuf_.get()); } /** * Writes a string to a byte buffer, as size (varint32) + string (non-null * terminated) * Automatically advances ptr to after the written portion */ void THeaderTransport::writeString(uint8_t*& ptr, const string& str) { auto strLen = safe_numeric_cast(str.length()); ptr += writeVarint32(strLen, ptr); memcpy(ptr, str.c_str(), strLen); // no need to write \0 ptr += strLen; } void THeaderTransport::setHeader(const string& key, const string& value) { writeHeaders_[key] = value; } uint32_t THeaderTransport::getMaxWriteHeadersSize() const { size_t maxWriteHeadersSize = 0; THeaderTransport::StringToStringMap::const_iterator it; for (it = writeHeaders_.begin(); it != writeHeaders_.end(); ++it) { // add sizes of key and value to maxWriteHeadersSize // 2 varints32 + the strings themselves maxWriteHeadersSize += 5 + 5 + (it->first).length() + (it->second).length(); } return safe_numeric_cast(maxWriteHeadersSize); } void THeaderTransport::clearHeaders() { writeHeaders_.clear(); } void THeaderTransport::flush() { resetConsumedMessageSize(); // Write out any data waiting in the write buffer. uint32_t haveBytes = getWriteBytes(); if (clientType == THRIFT_HEADER_CLIENT_TYPE) { transform(wBuf_.get(), haveBytes); haveBytes = getWriteBytes(); // transform may have changed the size } // Note that we reset wBase_ prior to the underlying write // to ensure we're in a sane state (i.e. internal buffer cleaned) // if the underlying write throws up an exception wBase_ = wBuf_.get(); if (haveBytes > MAX_FRAME_SIZE) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Attempting to send frame that is too large"); } if (clientType == THRIFT_HEADER_CLIENT_TYPE) { // header size will need to be updated at the end because of varints. // Make it big enough here for max varint size, plus 4 for padding. uint32_t headerSize = (2 + getNumTransforms()) * THRIFT_MAX_VARINT32_BYTES + 4; // add approximate size of info headers headerSize += getMaxWriteHeadersSize(); // Pkt size uint32_t maxSzHbo = headerSize + haveBytes // thrift header + payload + 10; // common header section uint8_t* pkt = tBuf_.get(); uint8_t* headerStart; uint8_t* headerSizePtr; uint8_t* pktStart = pkt; if (maxSzHbo > tBufSize_) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Attempting to header frame that is too large"); } uint32_t szHbo; uint32_t szNbo; uint16_t headerSizeN; // Fixup szHbo later pkt += sizeof(szNbo); uint16_t headerN = htons(HEADER_MAGIC >> 16); memcpy(pkt, &headerN, sizeof(headerN)); pkt += sizeof(headerN); uint16_t flagsN = htons(flags); memcpy(pkt, &flagsN, sizeof(flagsN)); pkt += sizeof(flagsN); uint32_t seqIdN = htonl(seqId); memcpy(pkt, &seqIdN, sizeof(seqIdN)); pkt += sizeof(seqIdN); headerSizePtr = pkt; // Fixup headerSizeN later pkt += sizeof(headerSizeN); headerStart = pkt; pkt += writeVarint32(protoId, pkt); pkt += writeVarint32(getNumTransforms(), pkt); // For now, each transform is only the ID, no following data. for (vector::const_iterator it = writeTrans_.begin(); it != writeTrans_.end(); ++it) { pkt += writeVarint32(*it, pkt); } // write info headers // for now only write kv-headers auto headerCount = safe_numeric_cast(writeHeaders_.size()); if (headerCount > 0) { pkt += writeVarint32(infoIdType::KEYVALUE, pkt); // Write key-value headers count pkt += writeVarint32(static_cast(headerCount), pkt); // Write info headers map::const_iterator it; for (it = writeHeaders_.begin(); it != writeHeaders_.end(); ++it) { writeString(pkt, it->first); // key writeString(pkt, it->second); // value } writeHeaders_.clear(); } // Fixups after varint size calculations headerSize = safe_numeric_cast(pkt - headerStart); uint8_t padding = 4 - (headerSize % 4); headerSize += padding; // Pad out pkt with 0x00 for (int i = 0; i < padding; i++) { *(pkt++) = 0x00; } // Pkt size ptrdiff_t szHbp = (headerStart - pktStart - 4); if (static_cast(szHbp) > static_cast((std::numeric_limits().max)()) - (headerSize + haveBytes)) { throw TTransportException(TTransportException::CORRUPTED_DATA, "Header section size is unreasonable"); } szHbo = headerSize + haveBytes // thrift header + payload + static_cast(szHbp); // common header section headerSizeN = htons(headerSize / 4); memcpy(headerSizePtr, &headerSizeN, sizeof(headerSizeN)); // Set framing size. szNbo = htonl(szHbo); memcpy(pktStart, &szNbo, sizeof(szNbo)); outTransport_->write(pktStart, szHbo - haveBytes + 4); outTransport_->write(wBuf_.get(), haveBytes); } else if (clientType == THRIFT_FRAMED_BINARY || clientType == THRIFT_FRAMED_COMPACT) { auto szHbo = (uint32_t)haveBytes; uint32_t szNbo = htonl(szHbo); outTransport_->write(reinterpret_cast(&szNbo), 4); outTransport_->write(wBuf_.get(), haveBytes); } else if (clientType == THRIFT_UNFRAMED_BINARY || clientType == THRIFT_UNFRAMED_COMPACT) { outTransport_->write(wBuf_.get(), haveBytes); } else { throw TTransportException(TTransportException::BAD_ARGS, "Unknown client type"); } // Flush the underlying transport. outTransport_->flush(); } /** * Read an i16 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 3 bytes. */ uint32_t THeaderTransport::readVarint16(uint8_t const* ptr, int16_t* i16, uint8_t const* boundary) { int32_t val; uint32_t rsize = readVarint32(ptr, &val, boundary); *i16 = (int16_t)val; return rsize; } /** * Read an i32 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 5 bytes. */ uint32_t THeaderTransport::readVarint32(uint8_t const* ptr, int32_t* i32, uint8_t const* boundary) { uint32_t rsize = 0; uint32_t val = 0; int shift = 0; while (true) { if (ptr == boundary) { throw TApplicationException(TApplicationException::INVALID_MESSAGE_TYPE, "Trying to read past header boundary"); } uint8_t byte = *(ptr++); rsize++; val |= (uint64_t)(byte & 0x7f) << shift; shift += 7; if (!(byte & 0x80)) { *i32 = val; return rsize; } } } /** * Write an i32 as a varint. Results in 1-5 bytes on the wire. */ uint32_t THeaderTransport::writeVarint32(int32_t n, uint8_t* pkt) { uint8_t buf[5]; uint32_t wsize = 0; while (true) { if ((n & ~0x7F) == 0) { buf[wsize++] = (int8_t)n; break; } else { buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); n >>= 7; } } // Caller will advance pkt. for (uint32_t i = 0; i < wsize; i++) { pkt[i] = buf[i]; } return wsize; } uint32_t THeaderTransport::writeVarint16(int16_t n, uint8_t* pkt) { return writeVarint32(n, pkt); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/THeaderTransport.h0000644000000000000000000002006114370300523024150 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_TRANSPORT_THEADERTRANSPORT_H_ #define THRIFT_TRANSPORT_THEADERTRANSPORT_H_ 1 #include #include #include #include #include #include #ifdef HAVE_STDINT_H #include #elif HAVE_INTTYPES_H #include #endif #include #include #include #include enum CLIENT_TYPE { THRIFT_HEADER_CLIENT_TYPE = 0, THRIFT_FRAMED_BINARY = 1, THRIFT_UNFRAMED_BINARY = 2, THRIFT_FRAMED_COMPACT = 3, THRIFT_UNFRAMED_COMPACT = 4, THRIFT_UNKNOWN_CLIENT_TYPE = 5, }; namespace apache { namespace thrift { namespace transport { using apache::thrift::protocol::T_COMPACT_PROTOCOL; /** * Header transport. All writes go into an in-memory buffer until flush is * called, at which point the transport writes the length of the entire * binary chunk followed by the data payload. This allows the receiver on the * other end to always do fixed-length reads. * * Subclass TFramedTransport because most of the read/write methods are similar * and need similar buffers. Major changes are readFrame & flush. * * Header Transport *must* be the same transport for both input and * output when used on the server side - client responses should be * the same protocol as those in the request. */ class THeaderTransport : public TVirtualTransport { public: static const int DEFAULT_BUFFER_SIZE = 512u; static const int THRIFT_MAX_VARINT32_BYTES = 5; /// Use default buffer sizes. explicit THeaderTransport(const std::shared_ptr& transport, std::shared_ptr config = nullptr) : TVirtualTransport(transport, config), outTransport_(transport), protoId(T_COMPACT_PROTOCOL), clientType(THRIFT_HEADER_CLIENT_TYPE), seqId(0), flags(0), tBufSize_(0), tBuf_(nullptr) { if (!transport_) throw std::invalid_argument("transport is empty"); initBuffers(); } THeaderTransport(const std::shared_ptr inTransport, const std::shared_ptr outTransport, std::shared_ptr config = nullptr) : TVirtualTransport(inTransport, config), outTransport_(outTransport), protoId(T_COMPACT_PROTOCOL), clientType(THRIFT_HEADER_CLIENT_TYPE), seqId(0), flags(0), tBufSize_(0), tBuf_(nullptr) { if (!transport_) throw std::invalid_argument("inTransport is empty"); if (!outTransport_) throw std::invalid_argument("outTransport is empty"); initBuffers(); } uint32_t readSlow(uint8_t* buf, uint32_t len) override; void flush() override; void resizeTransformBuffer(uint32_t additionalSize = 0); uint16_t getProtocolId() const; void setProtocolId(uint16_t protoId) { this->protoId = protoId; } void resetProtocol(); /** * We know we got a packet in header format here, try to parse the header * * @param headerSize size of the header portion * @param sz Size of the whole message, including header */ void readHeaderFormat(uint16_t headerSize, uint32_t sz); /** * Untransform the data based on the received header flags * On conclusion of function, setReadBuffer is called with the * untransformed data. * * @param ptr ptr to data * @param size of data */ void untransform(uint8_t* ptr, uint32_t sz); /** * Transform the data based on our write transform flags * At conclusion of function the write buffer is set to the * transformed data. * * @param ptr Ptr to data to transform * @param sz Size of data buffer */ void transform(uint8_t* ptr, uint32_t sz); uint16_t getNumTransforms() const { return safe_numeric_cast(writeTrans_.size()); } void setTransform(uint16_t transId) { writeTrans_.push_back(transId); } // Info headers typedef std::map StringToStringMap; // these work with write headers void setHeader(const std::string& key, const std::string& value); void clearHeaders(); StringToStringMap& getWriteHeaders() { return writeHeaders_; } // these work with read headers const StringToStringMap& getHeaders() const { return readHeaders_; } // accessors for seqId int32_t getSequenceNumber() const { return seqId; } void setSequenceNumber(int32_t seqId) { this->seqId = seqId; } enum TRANSFORMS { ZLIB_TRANSFORM = 0x01, }; protected: /** * Reads a frame of input from the underlying stream. * * Returns true if a frame was read successfully, or false on EOF. * (Raises a TTransportException if EOF occurs after a partial frame.) */ bool readFrame() override; void ensureReadBuffer(uint32_t sz); uint32_t getWriteBytes(); void initBuffers() { setReadBuffer(nullptr, 0); setWriteBuffer(wBuf_.get(), wBufSize_); } std::shared_ptr outTransport_; // 0 and 16th bits must be 0 to differentiate from framed & unframed static const uint32_t HEADER_MAGIC = 0x0FFF0000; static const uint32_t HEADER_MASK = 0xFFFF0000; static const uint32_t FLAGS_MASK = 0x0000FFFF; static const uint32_t MAX_FRAME_SIZE = 0x3FFFFFFF; int16_t protoId; uint16_t clientType; uint32_t seqId; uint16_t flags; std::vector readTrans_; std::vector writeTrans_; // Map to use for headers StringToStringMap readHeaders_; StringToStringMap writeHeaders_; /** * Returns the maximum number of bytes that write k/v headers can take */ uint32_t getMaxWriteHeadersSize() const; struct infoIdType { enum idType { // start at 1 to avoid confusing header padding for an infoId KEYVALUE = 1, END // signal the end of infoIds we can handle }; }; // Buffers to use for transform processing uint32_t tBufSize_; std::unique_ptr tBuf_; void readString(uint8_t*& ptr, /* out */ std::string& str, uint8_t const* headerBoundary); void writeString(uint8_t*& ptr, const std::string& str); // Varint utils /** * Read an i16 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 3 bytes. */ uint32_t readVarint16(uint8_t const* ptr, int16_t* i16, uint8_t const* boundary); /** * Read an i32 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 5 bytes. */ uint32_t readVarint32(uint8_t const* ptr, int32_t* i32, uint8_t const* boundary); /** * Write an i32 as a varint. Results in 1-5 bytes on the wire. */ uint32_t writeVarint32(int32_t n, uint8_t* pkt); /** * Write an i16 as a varint. Results in 1-3 bytes on the wire. */ uint32_t writeVarint16(int16_t n, uint8_t* pkt); }; /** * Wraps a transport into a header one. * */ class THeaderTransportFactory : public TTransportFactory { public: THeaderTransportFactory() = default; ~THeaderTransportFactory() override = default; /** * Wraps the transport into a header one. */ std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new THeaderTransport(trans)); } }; } } } // apache::thrift::transport #endif // #ifndef THRIFT_TRANSPORT_THEADERTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TSSLServerSocket.h0000644000000000000000000000433314303740367024062 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ #define _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ 1 #include namespace apache { namespace thrift { namespace transport { class TSSLSocketFactory; /** * Server socket that accepts SSL connections. */ class TSSLServerSocket : public TServerSocket { public: /** * Constructor. Binds to all interfaces. * * @param port Listening port * @param factory SSL socket factory implementation */ TSSLServerSocket(int port, std::shared_ptr factory); /** * Constructor. Binds to the specified address. * * @param address Address to bind to * @param port Listening port * @param factory SSL socket factory implementation */ TSSLServerSocket(const std::string& address, int port, std::shared_ptr factory); /** * Constructor. Binds to all interfaces. * * @param port Listening port * @param sendTimeout Socket send timeout * @param recvTimeout Socket receive timeout * @param factory SSL socket factory implementation */ TSSLServerSocket(int port, int sendTimeout, int recvTimeout, std::shared_ptr factory); protected: std::shared_ptr createSocket(THRIFT_SOCKET socket) override; std::shared_ptr factory_; }; } } } #endif thrift-0.19.0/lib/cpp/src/thrift/transport/TFDTransport.h0000644000000000000000000000421114303740367023262 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_ #define _THRIFT_TRANSPORT_TFDTRANSPORT_H_ 1 #include #ifdef HAVE_SYS_TIME_H #include #endif #include #include namespace apache { namespace thrift { namespace transport { /** * Dead-simple wrapper around a file descriptor. * */ class TFDTransport : public TVirtualTransport { public: enum ClosePolicy { NO_CLOSE_ON_DESTROY = 0, CLOSE_ON_DESTROY = 1 }; TFDTransport(int fd, ClosePolicy close_policy = NO_CLOSE_ON_DESTROY, std::shared_ptr config = nullptr) : TVirtualTransport(config), fd_(fd), close_policy_(close_policy) { } ~TFDTransport() override { if (close_policy_ == CLOSE_ON_DESTROY) { try { close(); } catch (TTransportException& ex) { GlobalOutput.printf("~TFDTransport TTransportException: '%s'", ex.what()); } } } bool isOpen() const override { return fd_ >= 0; } void open() override {} void close() override; uint32_t read(uint8_t* buf, uint32_t len); void write(const uint8_t* buf, uint32_t len); void setFD(int fd) { fd_ = fd; } int getFD() { return fd_; } protected: int fd_; ClosePolicy close_policy_; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/THttpServer.cpp0000644000000000000000000001256614303740367023531 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #if defined(_MSC_VER) || defined(__MINGW32__) #include #endif using std::string; namespace apache { namespace thrift { namespace transport { THttpServer::THttpServer(std::shared_ptr transport, std::shared_ptr config) : THttpTransport(transport, config) { } THttpServer::~THttpServer() = default; #if defined(_MSC_VER) || defined(__MINGW32__) #define THRIFT_GMTIME(TM, TIME) gmtime_s(&TM, &TIME) #define THRIFT_strncasecmp(str1, str2, len) _strnicmp(str1, str2, len) #define THRIFT_strcasestr(haystack, needle) StrStrIA(haystack, needle) #else #define THRIFT_GMTIME(TM, TIME) gmtime_r(&TIME, &TM) #define THRIFT_strncasecmp(str1, str2, len) strncasecmp(str1, str2, len) #define THRIFT_strcasestr(haystack, needle) strcasestr(haystack, needle) #endif void THttpServer::parseHeader(char* header) { char* colon = strchr(header, ':'); if (colon == nullptr) { return; } size_t sz = colon - header; char* value = colon + 1; if (THRIFT_strncasecmp(header, "Transfer-Encoding", sz) == 0) { if (THRIFT_strcasestr(value, "chunked") != nullptr) { chunked_ = true; } } else if (THRIFT_strncasecmp(header, "Content-length", sz) == 0) { chunked_ = false; contentLength_ = atoi(value); } else if (strncmp(header, "X-Forwarded-For", sz) == 0) { origin_ = value; } } bool THttpServer::parseStatusLine(char* status) { char* method = status; char* path = strchr(method, ' '); if (path == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *path = '\0'; while (*(++path) == ' ') { }; char* http = strchr(path, ' '); if (http == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *http = '\0'; if (strcmp(method, "POST") == 0) { // POST method ok, looking for content. return true; } else if (strcmp(method, "OPTIONS") == 0) { // preflight OPTIONS method, we don't need further content. // how to graciously close connection? uint8_t* buf; uint32_t len; writeBuffer_.getBuffer(&buf, &len); // Construct the HTTP header std::ostringstream h; h << "HTTP/1.1 200 OK" << CRLF << "Date: " << getTimeRFC1123() << CRLF << "Access-Control-Allow-Origin: *" << CRLF << "Access-Control-Allow-Methods: POST, OPTIONS" << CRLF << "Access-Control-Allow-Headers: Content-Type" << CRLF << CRLF; string header = h.str(); // Write the header, then the data, then flush transport_->write((const uint8_t*)header.c_str(), static_cast(header.size())); transport_->write(buf, len); transport_->flush(); // Reset the buffer and header variables writeBuffer_.resetBuffer(); readHeaders_ = true; return true; } throw TTransportException(string("Bad Status (unsupported method): ") + status); } void THttpServer::flush() { resetConsumedMessageSize(); // Fetch the contents of the write buffer uint8_t* buf; uint32_t len; writeBuffer_.getBuffer(&buf, &len); // Construct the HTTP header string header = getHeader(len); // Write the header, then the data, then flush // cast should be fine, because none of "header" is under attacker control transport_->write((const uint8_t*)header.c_str(), static_cast(header.size())); transport_->write(buf, len); transport_->flush(); // Reset the buffer and header variables writeBuffer_.resetBuffer(); readHeaders_ = true; } std::string THttpServer::getHeader(uint32_t len) { std::ostringstream h; h << "HTTP/1.1 200 OK" << CRLF << "Date: " << getTimeRFC1123() << CRLF << "Server: Thrift/" << PACKAGE_VERSION << CRLF << "Access-Control-Allow-Origin: *" << CRLF << "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF << "Connection: Keep-Alive" << CRLF << CRLF; return h.str(); } std::string THttpServer::getTimeRFC1123() { static const char* Days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char* Months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char buff[128]; time_t t = time(nullptr); struct tm tmb; THRIFT_GMTIME(tmb, t); sprintf(buff, "%s, %d %s %d %d:%d:%d GMT", Days[tmb.tm_wday], tmb.tm_mday, Months[tmb.tm_mon], tmb.tm_year + 1900, tmb.tm_hour, tmb.tm_min, tmb.tm_sec); return std::string(buff); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/SocketCommon.h0000644000000000000000000000255114303740367023336 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * @author: David Suárez */ #ifndef THRIFT_SOCKETCOMMON_H #define THRIFT_SOCKETCOMMON_H #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_AF_UNIX_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #include namespace apache { namespace thrift { namespace transport { socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path); } } } // apache::thrift::transport #endif //THRIFT_SOCKETCOMMON_H thrift-0.19.0/lib/cpp/src/thrift/transport/TWebSocketServer.cpp0000644000000000000000000000317714303740367024476 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include using std::string; namespace apache { namespace thrift { namespace transport { std::string base64Encode(unsigned char* data, int length) { std::unique_ptr> base64(BIO_new(BIO_f_base64()), [](BIO* b) { BIO_free_all(b); }); BIO_set_flags(base64.get(), BIO_FLAGS_BASE64_NO_NL); BIO* dest = BIO_new(BIO_s_mem()); BIO_push(base64.get(), dest); BIO_write(base64.get(), data, length); int ret = BIO_flush(base64.get()); THRIFT_UNUSED_VARIABLE(ret); char* encoded; length = BIO_get_mem_data(dest, &encoded); return std::string(encoded, length); } } // namespace transport } // namespace thrift } // namespace apache thrift-0.19.0/lib/cpp/src/thrift/transport/SocketCommon.cpp0000644000000000000000000000452714303740367023676 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * @author: David Suárez */ #include #include #include #include #include namespace apache { namespace thrift { namespace transport { socklen_t fillUnixSocketAddr(struct sockaddr_un& address, std::string& path) { // abstract namespace socket ? bool isAbstractNamespace = path[0] == 0; #ifndef __linux__ if (isAbstractNamespace) { GlobalOutput.perror("TSocket::open() Abstract Namespace Domain sockets only supported on linux: ", -99); throw TTransportException(TTransportException::NOT_OPEN, " Abstract Namespace Domain socket path not supported"); } #endif /* * For abstract namespace sockets, the path string is not null-terminated (as opposite to path based), so we * rely in pass the string size, to the bind() call. */ size_t addr_len = isAbstractNamespace ? path.size() : path.size() + 1; if (addr_len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() Unix Domain socket path too long", errno_copy); throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long"); } address.sun_family = AF_UNIX; memcpy(address.sun_path, path.c_str(), addr_len); return static_cast(sizeof((sockaddr_un*)nullptr)->sun_family + addr_len); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TZlibTransport.cpp0000644000000000000000000003130614303740367024231 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include using std::string; namespace apache { namespace thrift { namespace transport { // Don't call this outside of the constructor. void TZlibTransport::initZlib() { int rv; bool r_init = false; try { rstream_ = new z_stream; wstream_ = new z_stream; rstream_->zalloc = Z_NULL; wstream_->zalloc = Z_NULL; rstream_->zfree = Z_NULL; wstream_->zfree = Z_NULL; rstream_->opaque = Z_NULL; wstream_->opaque = Z_NULL; rstream_->next_in = crbuf_; wstream_->next_in = uwbuf_; rstream_->next_out = urbuf_; wstream_->next_out = cwbuf_; rstream_->avail_in = 0; wstream_->avail_in = 0; rstream_->avail_out = urbuf_size_; wstream_->avail_out = cwbuf_size_; rv = inflateInit(rstream_); checkZlibRv(rv, rstream_->msg); // Have to set this flag so we know whether to de-initialize. r_init = true; rv = deflateInit(wstream_, comp_level_); checkZlibRv(rv, wstream_->msg); } catch (...) { if (r_init) { rv = inflateEnd(rstream_); checkZlibRvNothrow(rv, rstream_->msg); } // There is no way we can get here if wstream_ was initialized. throw; } } inline void TZlibTransport::checkZlibRv(int status, const char* message) { if (status != Z_OK) { throw TZlibTransportException(status, message); } } inline void TZlibTransport::checkZlibRvNothrow(int status, const char* message) { if (status != Z_OK) { string output = "TZlibTransport: zlib failure in destructor: " + TZlibTransportException::errorMessage(status, message); GlobalOutput(output.c_str()); } } TZlibTransport::~TZlibTransport() { int rv; rv = inflateEnd(rstream_); checkZlibRvNothrow(rv, rstream_->msg); rv = deflateEnd(wstream_); // Z_DATA_ERROR may be returned if the caller has written data, but not // called flush() to actually finish writing the data out to the underlying // transport. The defined TTransport behavior in this case is that this data // may be discarded, so we ignore the error and silently discard the data. // For other erros, log a message. if (rv != Z_DATA_ERROR) { checkZlibRvNothrow(rv, wstream_->msg); } delete[] urbuf_; delete[] crbuf_; delete[] uwbuf_; delete[] cwbuf_; delete rstream_; delete wstream_; } bool TZlibTransport::isOpen() const { return (readAvail() > 0) || (rstream_->avail_in > 0) || transport_->isOpen(); } bool TZlibTransport::peek() { return (readAvail() > 0) || (rstream_->avail_in > 0) || transport_->peek(); } // READING STRATEGY // // We have two buffers for reading: one containing the compressed data (crbuf_) // and one containing the uncompressed data (urbuf_). When read is called, // we repeat the following steps until we have satisfied the request: // - Copy data from urbuf_ into the caller's buffer. // - If we had enough, return. // - If urbuf_ is empty, read some data into it from the underlying transport. // - Inflate data from crbuf_ into urbuf_. // // In standalone objects, we set input_ended_ to true when inflate returns // Z_STREAM_END. This allows to make sure that a checksum was verified. inline int TZlibTransport::readAvail() const { return urbuf_size_ - rstream_->avail_out - urpos_; } uint32_t TZlibTransport::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); uint32_t need = len; // TODO(dreiss): Skip urbuf on big reads. while (true) { // Copy out whatever we have available, then give them the min of // what we have and what they want, then advance indices. int give = (std::min)((uint32_t)readAvail(), need); memcpy(buf, urbuf_ + urpos_, give); need -= give; buf += give; urpos_ += give; // If they were satisfied, we are done. if (need == 0) { return len; } // If we will need to read from the underlying transport to get more data, // but we already have some data available, return it now. Reading from // the underlying transport may block, and read() is only allowed to block // when no data is available. if (need < len && rstream_->avail_in == 0) { return len - need; } // If we get to this point, we need to get some more data. // If zlib has reported the end of a stream, we can't really do any more. if (input_ended_) { return len - need; } // The uncompressed read buffer is empty, so reset the stream fields. rstream_->next_out = urbuf_; rstream_->avail_out = urbuf_size_; urpos_ = 0; // Call inflate() to uncompress some more data if (!readFromZlib()) { // no data available from underlying transport return len - need; } // Okay. The read buffer should have whatever we can give it now. // Loop back to the start and try to give some more. } } bool TZlibTransport::readFromZlib() { assert(!input_ended_); // If we don't have any more compressed data available, // read some from the underlying transport. if (rstream_->avail_in == 0) { uint32_t got = transport_->read(crbuf_, crbuf_size_); if (got == 0) { return false; } rstream_->next_in = crbuf_; rstream_->avail_in = got; } // We have some compressed data now. Uncompress it. int zlib_rv = inflate(rstream_, Z_SYNC_FLUSH); if (zlib_rv == Z_STREAM_END) { input_ended_ = true; } else { checkZlibRv(zlib_rv, rstream_->msg); } return true; } // WRITING STRATEGY // // We buffer up small writes before sending them to zlib, so our logic is: // - Is the write big? // - Send the buffer to zlib. // - Send this data to zlib. // - Is the write small? // - Is there insufficient space in the buffer for it? // - Send the buffer to zlib. // - Copy the data to the buffer. // // We have two buffers for writing also: the uncompressed buffer (mentioned // above) and the compressed buffer. When sending data to zlib we loop over // the following until the source (uncompressed buffer or big write) is empty: // - Is there no more space in the compressed buffer? // - Write the compressed buffer to the underlying transport. // - Deflate from the source into the compressed buffer. void TZlibTransport::write(const uint8_t* buf, uint32_t len) { if (output_finished_) { throw TTransportException(TTransportException::BAD_ARGS, "write() called after finish()"); } // zlib's "deflate" function has enough logic in it that I think // we're better off (performance-wise) buffering up small writes. if (len > MIN_DIRECT_DEFLATE_SIZE) { flushToZlib(uwbuf_, uwpos_, Z_NO_FLUSH); uwpos_ = 0; flushToZlib(buf, len, Z_NO_FLUSH); } else if (len > 0) { if (uwbuf_size_ - uwpos_ < len) { flushToZlib(uwbuf_, uwpos_, Z_NO_FLUSH); uwpos_ = 0; } memcpy(uwbuf_ + uwpos_, buf, len); uwpos_ += len; } } void TZlibTransport::flush() { if (output_finished_) { throw TTransportException(TTransportException::BAD_ARGS, "flush() called after finish()"); } flushToZlib(uwbuf_, uwpos_, Z_BLOCK); uwpos_ = 0; if(wstream_->avail_out < 6){ transport_->write(cwbuf_, cwbuf_size_ - wstream_->avail_out); wstream_->next_out = cwbuf_; wstream_->avail_out = cwbuf_size_; } flushToTransport(Z_FULL_FLUSH); resetConsumedMessageSize(); } void TZlibTransport::finish() { if (output_finished_) { throw TTransportException(TTransportException::BAD_ARGS, "finish() called more than once"); } flushToTransport(Z_FINISH); } void TZlibTransport::flushToTransport(int flush) { // write pending data in uwbuf_ to zlib flushToZlib(uwbuf_, uwpos_, flush); uwpos_ = 0; // write all available data from zlib to the transport transport_->write(cwbuf_, cwbuf_size_ - wstream_->avail_out); wstream_->next_out = cwbuf_; wstream_->avail_out = cwbuf_size_; // flush the transport transport_->flush(); } void TZlibTransport::flushToZlib(const uint8_t* buf, int len, int flush) { wstream_->next_in = const_cast(buf); wstream_->avail_in = len; while (true) { if ((flush == Z_NO_FLUSH || flush == Z_BLOCK) && wstream_->avail_in == 0) { break; } // If our ouput buffer is full, flush to the underlying transport. if (wstream_->avail_out == 0) { transport_->write(cwbuf_, cwbuf_size_); wstream_->next_out = cwbuf_; wstream_->avail_out = cwbuf_size_; } int zlib_rv = deflate(wstream_, flush); if (flush == Z_FINISH && zlib_rv == Z_STREAM_END) { assert(wstream_->avail_in == 0); output_finished_ = true; break; } checkZlibRv(zlib_rv, wstream_->msg); if ((flush == Z_SYNC_FLUSH || flush == Z_FULL_FLUSH) && wstream_->avail_in == 0 && wstream_->avail_out != 0) { break; } } } const uint8_t* TZlibTransport::borrow(uint8_t* buf, uint32_t* len) { (void)buf; // Don't try to be clever with shifting buffers. // If we have enough data, give a pointer to it, // otherwise let the protcol use its slow path. if (readAvail() >= (int)*len) { *len = (uint32_t)readAvail(); return urbuf_ + urpos_; } return nullptr; } void TZlibTransport::consume(uint32_t len) { countConsumedMessageBytes(len); if (readAvail() >= (int)len) { urpos_ += len; } else { throw TTransportException(TTransportException::BAD_ARGS, "consume did not follow a borrow."); } } void TZlibTransport::verifyChecksum() { // If zlib has already reported the end of the stream, // it has verified the checksum. if (input_ended_) { return; } // This should only be called when reading is complete. // If the caller still has unread data, throw an exception. if (readAvail() > 0) { throw TTransportException(TTransportException::CORRUPTED_DATA, "verifyChecksum() called before end of zlib stream"); } // Reset the rstream fields, in case avail_out is 0. // (Since readAvail() is 0, we know there is no unread data in urbuf_) rstream_->next_out = urbuf_; rstream_->avail_out = urbuf_size_; urpos_ = 0; // Call inflate() // This will throw an exception if the checksum is bad. bool performed_inflate = readFromZlib(); if (!performed_inflate) { // We needed to read from the underlying transport, and the read() call // returned 0. // // Not all TTransport implementations behave the same way here, so we'll // end up with different behavior depending on the underlying transport. // // For some transports (e.g., TFDTransport), read() blocks if no more data // is available. They only return 0 if EOF has been reached, or if the // remote endpoint has closed the connection. For those transports, // verifyChecksum() will block until the checksum becomes available. // // Other transport types (e.g., TMemoryBuffer) always return 0 immediately // if no more data is available. For those transport types, verifyChecksum // will raise the following exception if the checksum is not available from // the underlying transport yet. throw TTransportException(TTransportException::CORRUPTED_DATA, "checksum not available yet in " "verifyChecksum()"); } // If input_ended_ is true now, the checksum has been verified if (input_ended_) { return; } // The caller invoked us before the actual end of the data stream assert(rstream_->avail_out < urbuf_size_); throw TTransportException(TTransportException::CORRUPTED_DATA, "verifyChecksum() called before end of " "zlib stream"); } TZlibTransportFactory::TZlibTransportFactory(std::shared_ptr transportFactory) :transportFactory_(transportFactory) { } std::shared_ptr TZlibTransportFactory::getTransport(std::shared_ptr trans) { if (transportFactory_) { return std::shared_ptr(new TZlibTransport(transportFactory_->getTransport(trans))); } else { return std::shared_ptr(new TZlibTransport(trans)); } } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TSocket.h0000644000000000000000000002202014303740367022302 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ #define _THRIFT_TRANSPORT_TSOCKET_H_ 1 #include #include #include #include #include #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_NETDB_H #include #endif namespace apache { namespace thrift { namespace transport { /** * TCP Socket implementation of the TTransport interface. * */ class TSocket : public TVirtualTransport { public: /** * Constructs a new socket. Note that this does NOT actually connect the * socket. * */ TSocket(std::shared_ptr config = nullptr); /** * Constructs a new socket. Note that this does NOT actually connect the * socket. * * @param host An IP address or hostname to connect to * @param port The port to connect on */ TSocket(const std::string& host, int port, std::shared_ptr config = nullptr); /** * Constructs a new Unix domain socket. * Note that this does NOT actually connect the socket. * * @param path The Unix domain socket e.g. "/tmp/ThriftTest.binary.thrift" * or a zero-prefixed string to create an abstract domain socket on Linux. */ TSocket(const std::string& path, std::shared_ptr config = nullptr); /** * Destroyes the socket object, closing it if necessary. */ ~TSocket() override; /** * Whether the socket is alive. * * @return Is the socket alive? */ bool isOpen() const override; /** * Checks whether there is more data available in the socket to read. * * This call blocks until at least one byte is available or the socket is closed. */ bool peek() override; /** * Creates and opens the UNIX socket. * * @throws TTransportException If the socket could not connect */ void open() override; /** * Shuts down communications on the socket. */ void close() override; /** * Determines whether there is pending data to read or not. * * This call does not block. * \throws TTransportException of types: * NOT_OPEN means the socket has been closed * UNKNOWN means something unexpected happened * \returns true if there is pending data to read, false otherwise */ virtual bool hasPendingDataToRead(); /** * Reads from the underlying socket. * \returns the number of bytes read or 0 indicates EOF * \throws TTransportException of types: * INTERRUPTED means the socket was interrupted * out of a blocking call * NOT_OPEN means the socket has been closed * TIMED_OUT means the receive timeout expired * UNKNOWN means something unexpected happened */ virtual uint32_t read(uint8_t* buf, uint32_t len); /** * Writes to the underlying socket. Loops until done or fail. */ virtual void write(const uint8_t* buf, uint32_t len); /** * Writes to the underlying socket. Does single send() and returns result. */ virtual uint32_t write_partial(const uint8_t* buf, uint32_t len); /** * Get the host that the socket is connected to * * @return string host identifier */ std::string getHost() const; /** * Get the port that the socket is connected to * * @return int port number */ int getPort() const; /** * Get the Unix domain socket path that the socket is connected to * * @return std::string path */ std::string getPath() const; /** * Whether the socket is a Unix domain socket. This is the same as checking * if getPath() is not empty. * * @return Is the socket a Unix domain socket? */ bool isUnixDomainSocket() const; /** * Set the host that socket will connect to * * @param host host identifier */ void setHost(std::string host); /** * Set the port that socket will connect to * * @param port port number */ void setPort(int port); /** * Set the Unix domain socket path for the socket * * @param path std::string path */ void setPath(std::string path); /** * Controls whether the linger option is set on the socket. * * @param on Whether SO_LINGER is on * @param linger If linger is active, the number of seconds to linger for */ void setLinger(bool on, int linger); /** * Whether to enable/disable Nagle's algorithm. * * @param noDelay Whether or not to disable the algorithm. * @return */ void setNoDelay(bool noDelay); /** * Set the connect timeout */ void setConnTimeout(int ms); /** * Set the receive timeout */ void setRecvTimeout(int ms); /** * Set the send timeout */ void setSendTimeout(int ms); /** * Set the max number of recv retries in case of an THRIFT_EAGAIN * error */ void setMaxRecvRetries(int maxRecvRetries); /** * Set SO_KEEPALIVE */ void setKeepAlive(bool keepAlive); /** * Get socket information formatted as a string */ std::string getSocketInfo() const; /** * Returns the DNS name of the host to which the socket is connected */ std::string getPeerHost() const; /** * Returns the address of the host to which the socket is connected */ std::string getPeerAddress() const; /** * Returns the port of the host to which the socket is connected **/ int getPeerPort() const; /** * Returns the underlying socket file descriptor. */ THRIFT_SOCKET getSocketFD() { return socket_; } /** * (Re-)initialize a TSocket for the supplied descriptor. This is only * intended for use by TNonblockingServer -- other use may result in * unfortunate surprises. * * @param fd the descriptor for an already-connected socket */ void setSocketFD(THRIFT_SOCKET fd); /* * Returns a cached copy of the peer address. */ sockaddr* getCachedAddress(socklen_t* len) const; /** * Sets whether to use a low minimum TCP retransmission timeout. */ static void setUseLowMinRto(bool useLowMinRto); /** * Gets whether to use a low minimum TCP retransmission timeout. */ static bool getUseLowMinRto(); /** * Get the origin the socket is connected to * * @return string peer host identifier and port */ const std::string getOrigin() const override; /** * Constructor to create socket from file descriptor. */ TSocket(THRIFT_SOCKET socket, std::shared_ptr config = nullptr); /** * Constructor to create socket from file descriptor that * can be interrupted safely. */ TSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener, std::shared_ptr config = nullptr); /** * Set a cache of the peer address (used when trivially available: e.g. * accept() or connect()). Only caches IPV4 and IPV6; unset for others. */ void setCachedAddress(const sockaddr* addr, socklen_t len); protected: /** connect, called by open */ void openConnection(struct addrinfo* res); /** Host to connect to */ std::string host_; /** Port number to connect on */ int port_; /** UNIX domain socket path */ std::string path_; /** Underlying socket handle */ THRIFT_SOCKET socket_; /** Peer hostname */ mutable std::string peerHost_; /** Peer address */ mutable std::string peerAddress_; /** Peer port */ mutable int peerPort_; /** * A shared socket pointer that will interrupt a blocking read if data * becomes available on it */ std::shared_ptr interruptListener_; /** Connect timeout in ms */ int connTimeout_; /** Send timeout in ms */ int sendTimeout_; /** Recv timeout in ms */ int recvTimeout_; /** Keep alive on */ bool keepAlive_; /** Linger on */ bool lingerOn_; /** Linger val */ int lingerVal_; /** Nodelay */ bool noDelay_; /** Recv EGAIN retries */ int maxRecvRetries_; /** Cached peer address */ union { sockaddr_in ipv4; sockaddr_in6 ipv6; } cachedPeerAddr_; /** Whether to use low minimum TCP retransmission timeout */ static bool useLowMinRto_; private: void unix_open(); void local_open(); }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TServerTransport.h0000644000000000000000000000722614303740367024250 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ #define _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ 1 #include #include namespace apache { namespace thrift { namespace transport { /** * Server transport framework. A server needs to have some facility for * creating base transports to read/write from. The server is expected * to keep track of TTransport children that it creates for purposes of * controlling their lifetime. */ class TServerTransport { public: virtual ~TServerTransport() = default; /** * Whether this transport is open. */ virtual bool isOpen() const { return false; } /** * Starts the server transport listening for new connections. Prior to this * call most transports will not return anything when accept is called. * * @throws TTransportException if we were unable to listen */ virtual void listen() {} /** * Gets a new dynamically allocated transport object and passes it to the * caller. Note that it is the explicit duty of the caller to free the * allocated object. The returned TTransport object must always be in the * opened state. nullptr should never be returned, instead an Exception should * always be thrown. * * @return A new TTransport object * @throws TTransportException if there is an error */ std::shared_ptr accept() { std::shared_ptr result = acceptImpl(); if (!result) { throw TTransportException("accept() may not return nullptr"); } return result; } /** * For "smart" TServerTransport implementations that work in a multi * threaded context this can be used to break out of an accept() call. * It is expected that the transport will throw a TTransportException * with the INTERRUPTED error code. * * This will not make an attempt to interrupt any TTransport children. */ virtual void interrupt() {} /** * This will interrupt the children created by the server transport. * allowing them to break out of any blocking data reception call. * It is expected that the children will throw a TTransportException * with the INTERRUPTED error code. */ virtual void interruptChildren() {} /** * Utility method * * @return server socket file descriptor * @throw TTransportException If an error occurs */ virtual THRIFT_SOCKET getSocketFD() { return -1; } /** * Closes this transport such that future calls to accept will do nothing. */ virtual void close() = 0; protected: TServerTransport() = default; /** * Subclasses should implement this function for accept. * * @return A newly allocated TTransport object * @throw TTransportException If an error occurs */ virtual std::shared_ptr acceptImpl() = 0; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h0000644000000000000000000000600214303740367026423 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERTRANSPORT_H_ #define _THRIFT_TRANSPORT_TNONBLOCKINGSERVERTRANSPORT_H_ 1 #include #include namespace apache { namespace thrift { namespace transport { /** * Server transport framework. A server needs to have some facility for * creating base transports to read/write from. The server is expected * to keep track of TTransport children that it creates for purposes of * controlling their lifetime. */ class TNonblockingServerTransport { public: virtual ~TNonblockingServerTransport() = default; /** * Starts the server transport listening for new connections. Prior to this * call most transports will not return anything when accept is called. * * @throws TTransportException if we were unable to listen */ virtual void listen() {} /** * Gets a new dynamically allocated transport object and passes it to the * caller. Note that it is the explicit duty of the caller to free the * allocated object. The returned TTransport object must always be in the * opened state. nullptr should never be returned, instead an Exception should * always be thrown. * * @return A new TTransport object * @throws TTransportException if there is an error */ std::shared_ptr accept() { std::shared_ptr result = acceptImpl(); if (!result) { throw TTransportException("accept() may not return nullptr"); } return result; } /** * Utility method * * @return server socket file descriptor * @throw TTransportException If an error occurs */ virtual THRIFT_SOCKET getSocketFD() = 0; virtual int getPort() = 0; virtual int getListenPort() = 0; /** * Closes this transport such that future calls to accept will do nothing. */ virtual void close() = 0; protected: TNonblockingServerTransport() = default; /** * Subclasses should implement this function for accept. * * @return A newly allocated TTransport object * @throw TTransportException If an error occurs */ virtual std::shared_ptr acceptImpl() = 0; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TVirtualTransport.h0000644000000000000000000001214014303740367024417 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ #define _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1 #include namespace apache { namespace thrift { namespace transport { /** * Helper class that provides default implementations of TTransport methods. * * This class provides default implementations of read(), readAll(), write(), * borrow() and consume(). * * In the TTransport base class, each of these methods simply invokes its * virtual counterpart. This class overrides them to always perform the * default behavior, without a virtual function call. * * The primary purpose of this class is to serve as a base class for * TVirtualTransport, and prevent infinite recursion if one of its subclasses * does not override the TTransport implementation of these methods. (Since * TVirtualTransport::read_virt() calls read(), and TTransport::read() calls * read_virt().) */ class TTransportDefaults : public TTransport { public: /* * TTransport *_virt() methods provide reasonable default implementations. * Invoke them non-virtually. */ uint32_t read(uint8_t* buf, uint32_t len) { return this->TTransport::read_virt(buf, len); } uint32_t readAll(uint8_t* buf, uint32_t len) { return this->TTransport::readAll_virt(buf, len); } void write(const uint8_t* buf, uint32_t len) { this->TTransport::write_virt(buf, len); } const uint8_t* borrow(uint8_t* buf, uint32_t* len) { return this->TTransport::borrow_virt(buf, len); } void consume(uint32_t len) { this->TTransport::consume_virt(len); } protected: TTransportDefaults(std::shared_ptr config = nullptr) : TTransport(config) {} }; /** * Helper class to provide polymorphism for subclasses of TTransport. * * This class implements *_virt() methods of TTransport, to call the * non-virtual versions of these functions in the proper subclass. * * To define your own transport class using TVirtualTransport: * 1) Derive your subclass from TVirtualTransport * e.g: class MyTransport : public TVirtualTransport { * 2) Provide your own implementations of read(), readAll(), etc. * These methods should be non-virtual. * * Transport implementations that need to use virtual inheritance when * inheriting from TTransport cannot use TVirtualTransport. * * @author Chad Walters */ template class TVirtualTransport : public Super_ { public: /* * Implementations of the *_virt() functions, to call the subclass's * non-virtual implementation function. */ uint32_t read_virt(uint8_t* buf, uint32_t len) override { return static_cast(this)->read(buf, len); } uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { return static_cast(this)->readAll(buf, len); } void write_virt(const uint8_t* buf, uint32_t len) override { static_cast(this)->write(buf, len); } const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) override { return static_cast(this)->borrow(buf, len); } void consume_virt(uint32_t len) override { static_cast(this)->consume(len); } /* * Provide a default readAll() implementation that invokes * read() non-virtually. * * Note: subclasses that use TVirtualTransport to derive from another * transport implementation (i.e., not TTransportDefaults) should beware that * this may override any non-default readAll() implementation provided by * the parent transport class. They may need to redefine readAll() to call * the correct parent implementation, if desired. */ uint32_t readAll(uint8_t* buf, uint32_t len) { auto* trans = static_cast(this); return ::apache::thrift::transport::readAll(*trans, buf, len); } protected: TVirtualTransport() : Super_() {} /* * Templatized constructors, to allow arguments to be passed to the Super_ * constructor. Currently we only support 0, 1, or 2 arguments, but * additional versions can be added as needed. */ template TVirtualTransport(Arg_ const& arg) : Super_(arg) {} template TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2) : Super_(a1, a2) {} }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/THttpClient.cpp0000644000000000000000000000734714303740367023502 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include using std::string; namespace apache { namespace thrift { namespace transport { THttpClient::THttpClient(std::shared_ptr transport, std::string host, std::string path, std::shared_ptr config) : THttpTransport(transport, config), host_(host), path_(path) { } THttpClient::THttpClient(string host, int port, string path, std::shared_ptr config) : THttpTransport(std::shared_ptr(new TSocket(host, port)), config), host_(host), path_(path) { } THttpClient::~THttpClient() = default; void THttpClient::parseHeader(char* header) { char* colon = strchr(header, ':'); if (colon == nullptr) { return; } char* value = colon + 1; if (boost::istarts_with(header, "Transfer-Encoding")) { if (boost::iends_with(value, "chunked")) { chunked_ = true; } } else if (boost::istarts_with(header, "Content-Length")) { chunked_ = false; contentLength_ = atoi(value); } } bool THttpClient::parseStatusLine(char* status) { char* http = status; char* code = strchr(http, ' '); if (code == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *code = '\0'; while (*(code++) == ' ') { }; char* msg = strchr(code, ' '); if (msg == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *msg = '\0'; if (strcmp(code, "200") == 0) { // HTTP 200 = OK, we got the response return true; } else if (strcmp(code, "100") == 0) { // HTTP 100 = continue, just keep reading return false; } else { throw TTransportException(string("Bad Status: ") + status); } } void THttpClient::flush() { resetConsumedMessageSize(); // Fetch the contents of the write buffer uint8_t* buf; uint32_t len; writeBuffer_.getBuffer(&buf, &len); // Construct the HTTP header std::ostringstream h; h << "POST " << path_ << " HTTP/1.1" << CRLF << "Host: " << host_ << CRLF << "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF << "Accept: application/x-thrift" << CRLF << "User-Agent: Thrift/" << PACKAGE_VERSION << " (C++/THttpClient)" << CRLF << CRLF; string header = h.str(); if (header.size() > (std::numeric_limits::max)()) throw TTransportException("Header too big"); // Write the header, then the data, then flush transport_->write((const uint8_t*)header.c_str(), static_cast(header.size())); transport_->write(buf, len); transport_->flush(); // Reset the buffer and header variables writeBuffer_.resetBuffer(); readHeaders_ = true; } void THttpClient::setPath(std::string path) { path_ = path; } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/THttpTransport.cpp0000644000000000000000000001422314303740367024247 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include using std::string; namespace apache { namespace thrift { namespace transport { // Yeah, yeah, hacky to put these here, I know. const char* THttpTransport::CRLF = "\r\n"; const int THttpTransport::CRLF_LEN = 2; THttpTransport::THttpTransport(std::shared_ptr transport, std::shared_ptr config) : TVirtualTransport(config), transport_(transport), origin_(""), readHeaders_(true), chunked_(false), chunkedDone_(false), chunkSize_(0), contentLength_(0), httpBuf_(nullptr), httpPos_(0), httpBufLen_(0), httpBufSize_(1024) { init(); } void THttpTransport::init() { httpBuf_ = (char*)std::malloc(httpBufSize_ + 1); if (httpBuf_ == nullptr) { throw std::bad_alloc(); } httpBuf_[httpBufLen_] = '\0'; } THttpTransport::~THttpTransport() { if (httpBuf_ != nullptr) { std::free(httpBuf_); } } uint32_t THttpTransport::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); if (readBuffer_.available_read() == 0) { readBuffer_.resetBuffer(); uint32_t got = readMoreData(); if (got == 0) { return 0; } } return readBuffer_.read(buf, len); } uint32_t THttpTransport::readEnd() { // Read any pending chunked data (footers etc.) if (chunked_) { while (!chunkedDone_) { readChunked(); } } return 0; } uint32_t THttpTransport::readMoreData() { uint32_t size; if (httpPos_ == httpBufLen_) { // Get more data! refill(); } if (readHeaders_) { readHeaders(); } if (chunked_) { size = readChunked(); } else { size = readContent(contentLength_); readHeaders_ = true; } return size; } uint32_t THttpTransport::readChunked() { uint32_t length = 0; char* line = readLine(); uint32_t chunkSize = parseChunkSize(line); if (chunkSize == 0) { readChunkedFooters(); } else { // Read data content length += readContent(chunkSize); // Read trailing CRLF after content readLine(); } return length; } void THttpTransport::readChunkedFooters() { // End of data, read footer lines until a blank one appears while (true) { char* line = readLine(); if (strlen(line) == 0) { chunkedDone_ = true; break; } } } uint32_t THttpTransport::parseChunkSize(char* line) { char* semi = strchr(line, ';'); if (semi != nullptr) { *semi = '\0'; } uint32_t size = 0; sscanf(line, "%x", &size); return size; } uint32_t THttpTransport::readContent(uint32_t size) { uint32_t need = size; while (need > 0) { uint32_t avail = httpBufLen_ - httpPos_; if (avail == 0) { // We have given all the data, reset position to head of the buffer httpPos_ = 0; httpBufLen_ = 0; refill(); // Now have available however much we read avail = httpBufLen_; } uint32_t give = avail; if (need < give) { give = need; } readBuffer_.write((uint8_t*)(httpBuf_ + httpPos_), give); httpPos_ += give; need -= give; } return size; } char* THttpTransport::readLine() { while (true) { char* eol = nullptr; eol = strstr(httpBuf_ + httpPos_, CRLF); // No CRLF yet? if (eol == nullptr) { // Shift whatever we have now to front and refill shift(); refill(); } else { // Return pointer to next line *eol = '\0'; char* line = httpBuf_ + httpPos_; httpPos_ = static_cast((eol - httpBuf_) + CRLF_LEN); return line; } } } void THttpTransport::shift() { if (httpBufLen_ > httpPos_) { // Shift down remaining data and read more uint32_t length = httpBufLen_ - httpPos_; memmove(httpBuf_, httpBuf_ + httpPos_, length); httpBufLen_ = length; } else { httpBufLen_ = 0; } httpPos_ = 0; httpBuf_[httpBufLen_] = '\0'; } void THttpTransport::refill() { uint32_t avail = httpBufSize_ - httpBufLen_; if (avail <= (httpBufSize_ / 4)) { httpBufSize_ *= 2; char* tmpBuf = (char*)std::realloc(httpBuf_, httpBufSize_ + 1); if (tmpBuf == nullptr) { throw std::bad_alloc(); } httpBuf_ = tmpBuf; } // Read more data uint32_t got = transport_->read((uint8_t*)(httpBuf_ + httpBufLen_), httpBufSize_ - httpBufLen_); httpBufLen_ += got; httpBuf_[httpBufLen_] = '\0'; if (got == 0) { throw TTransportException(TTransportException::END_OF_FILE, "Could not refill buffer"); } } void THttpTransport::readHeaders() { // Initialize headers state variables contentLength_ = 0; chunked_ = false; chunkedDone_ = false; chunkSize_ = 0; // Control state flow bool statusLine = true; bool finished = false; // Loop until headers are finished while (true) { char* line = readLine(); if (strlen(line) == 0) { if (finished) { readHeaders_ = false; return; } else { // Must have been an HTTP 100, keep going for another status line statusLine = true; } } else { if (statusLine) { statusLine = false; finished = parseStatusLine(line); } else { parseHeader(line); } } } } void THttpTransport::write(const uint8_t* buf, uint32_t len) { writeBuffer_.write(buf, len); } const std::string THttpTransport::getOrigin() const { std::ostringstream oss; if (!origin_.empty()) { oss << origin_ << ", "; } oss << transport_->getOrigin(); return oss.str(); } } } } thrift-0.19.0/lib/cpp/src/thrift/transport/PlatformSocket.h0000644000000000000000000001050614303740367023671 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // clang-format off #ifndef _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ # define _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ #ifdef _WIN32 # include # define THRIFT_GET_SOCKET_ERROR ::WSAGetLastError() # define THRIFT_ERRNO (*_errno()) # define THRIFT_EINPROGRESS WSAEINPROGRESS # define THRIFT_EAGAIN WSAEWOULDBLOCK # define THRIFT_EINTR WSAEINTR # define THRIFT_ECONNRESET WSAECONNRESET # define THRIFT_ENOTCONN WSAENOTCONN # define THRIFT_ETIMEDOUT WSAETIMEDOUT # define THRIFT_EWOULDBLOCK WSAEWOULDBLOCK # define THRIFT_EPIPE WSAECONNRESET # define THRIFT_NO_SOCKET_CACHING SO_EXCLUSIVEADDRUSE # define THRIFT_SOCKET SOCKET # define THRIFT_INVALID_SOCKET INVALID_SOCKET # define THRIFT_SOCKETPAIR thrift_socketpair # define THRIFT_FCNTL thrift_fcntl # define THRIFT_O_NONBLOCK 1 # define THRIFT_F_GETFL 0 # define THRIFT_F_SETFL 1 # define THRIFT_GETTIMEOFDAY thrift_gettimeofday # define THRIFT_CLOSESOCKET closesocket # define THRIFT_CLOSE _close # define THRIFT_OPEN _open # define THRIFT_FTRUNCATE _chsize_s # define THRIFT_FSYNC _commit # define THRIFT_LSEEK _lseek # define THRIFT_WRITE _write # define THRIFT_READ _read # define THRIFT_IOCTL_SOCKET ioctlsocket # define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE u_long # define THRIFT_FSTAT _fstat # define THRIFT_STAT _stat # ifdef _WIN32_WCE # define THRIFT_GAI_STRERROR(...) thrift_wstr2str(gai_strerrorW(__VA_ARGS__)) # else # define THRIFT_GAI_STRERROR gai_strerrorA # endif # define THRIFT_SSIZET ptrdiff_t # if (_MSC_VER < 1900) # define THRIFT_SNPRINTF _snprintf # else # define THRIFT_SNPRINTF snprintf # endif # define THRIFT_SLEEP_SEC thrift_sleep # define THRIFT_SLEEP_USEC thrift_usleep # define THRIFT_TIMESPEC thrift_timespec # define THRIFT_CTIME_R thrift_ctime_r # define THRIFT_POLL WSAPoll # define THRIFT_POLLFD pollfd # define THRIFT_POLLIN POLLIN # define THRIFT_POLLOUT POLLOUT # define THRIFT_SHUT_RDWR SD_BOTH # if !defined(AI_ADDRCONFIG) # define AI_ADDRCONFIG 0x00000400 # endif #else //not _WIN32 # include # define THRIFT_GET_SOCKET_ERROR errno # define THRIFT_ERRNO errno # define THRIFT_EINTR EINTR # define THRIFT_EINPROGRESS EINPROGRESS # define THRIFT_ECONNRESET ECONNRESET # define THRIFT_ENOTCONN ENOTCONN # define THRIFT_ETIMEDOUT ETIMEDOUT # define THRIFT_EWOULDBLOCK EWOULDBLOCK # define THRIFT_EAGAIN EAGAIN # define THRIFT_EPIPE EPIPE # define THRIFT_NO_SOCKET_CACHING SO_REUSEADDR # define THRIFT_SOCKET int # define THRIFT_INVALID_SOCKET (-1) # define THRIFT_SOCKETPAIR socketpair # define THRIFT_FCNTL fcntl # define THRIFT_O_NONBLOCK O_NONBLOCK # define THRIFT_F_GETFL F_GETFL # define THRIFT_F_SETFL F_SETFL # define THRIFT_GETTIMEOFDAY gettimeofday # define THRIFT_CLOSESOCKET close # define THRIFT_CLOSE close # define THRIFT_OPEN open # define THRIFT_FTRUNCATE ftruncate # define THRIFT_FSYNC fsync # define THRIFT_LSEEK lseek # define THRIFT_WRITE write # define THRIFT_READ read # define THRIFT_IOCTL_SOCKET ioctl # define THRIFT_IOCTL_SOCKET_NUM_BYTES_TYPE int # define THRIFT_STAT stat # define THRIFT_FSTAT fstat # define THRIFT_GAI_STRERROR gai_strerror # define THRIFT_SSIZET ssize_t # define THRIFT_SNPRINTF snprintf # define THRIFT_SLEEP_SEC sleep # define THRIFT_SLEEP_USEC usleep # define THRIFT_TIMESPEC timespec # define THRIFT_CTIME_R ctime_r # define THRIFT_POLL poll # define THRIFT_POLLFD pollfd # define THRIFT_POLLIN POLLIN # define THRIFT_POLLOUT POLLOUT # define THRIFT_SHUT_RDWR SHUT_RDWR #endif #endif // _THRIFT_TRANSPORT_PLATFORM_SOCKET_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TSSLSocket.cpp0000644000000000000000000011166414452237057023236 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #ifdef HAVE_ARPA_INET_H #include #endif #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif #ifdef HAVE_FCNTL_H #include #endif #define OPENSSL_VERSION_NO_THREAD_ID_BEFORE 0x10000000L #define OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE 0x10100000L #include #include #if (OPENSSL_VERSION_NUMBER < OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE) #include #endif #include #include #include #include #include #include #include #include using namespace apache::thrift::concurrency; using std::string; struct CRYPTO_dynlock_value { Mutex mutex; }; namespace apache { namespace thrift { namespace transport { // OpenSSL initialization/cleanup static bool openSSLInitialized = false; static boost::shared_array mutexes; static void callbackLocking(int mode, int n, const char*, int) { if (mode & CRYPTO_LOCK) { // assertion of (px != 0) here typically means that a TSSLSocket's lifetime // exceeded the lifetime of the TSSLSocketFactory that created it, and the // TSSLSocketFactory already ran cleanupOpenSSL(), which deleted "mutexes". mutexes[n].lock(); } else { mutexes[n].unlock(); } } #if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID_BEFORE) static unsigned long callbackThreadID() { #ifdef _WIN32 return (unsigned long)GetCurrentThreadId(); #else return (unsigned long)pthread_self(); #endif } #endif static CRYPTO_dynlock_value* dyn_create(const char*, int) { return new CRYPTO_dynlock_value; } static void dyn_lock(int mode, struct CRYPTO_dynlock_value* lock, const char*, int) { if (lock != nullptr) { if (mode & CRYPTO_LOCK) { lock->mutex.lock(); } else { lock->mutex.unlock(); } } } static void dyn_destroy(struct CRYPTO_dynlock_value* lock, const char*, int) { delete lock; } void initializeOpenSSL() { if (openSSLInitialized) { return; } openSSLInitialized = true; SSL_library_init(); SSL_load_error_strings(); ERR_load_crypto_strings(); // static locking // newer versions of OpenSSL changed CRYPTO_num_locks - see THRIFT-3878 #ifdef CRYPTO_num_locks mutexes = boost::shared_array(new Mutex[CRYPTO_num_locks()]); #else mutexes = boost::shared_array(new Mutex[ ::CRYPTO_num_locks()]); #endif #if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID_BEFORE) CRYPTO_set_id_callback(callbackThreadID); #endif CRYPTO_set_locking_callback(callbackLocking); // dynamic locking CRYPTO_set_dynlock_create_callback(dyn_create); CRYPTO_set_dynlock_lock_callback(dyn_lock); CRYPTO_set_dynlock_destroy_callback(dyn_destroy); } void cleanupOpenSSL() { if (!openSSLInitialized) { return; } openSSLInitialized = false; // https://wiki.openssl.org/index.php/Library_Initialization#Cleanup // we purposefully do NOT call FIPS_mode_set(0) and leave it up to the enclosing application to manage FIPS entirely #if (OPENSSL_VERSION_NUMBER < OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE) ENGINE_cleanup(); // https://www.openssl.org/docs/man1.1.0/crypto/ENGINE_cleanup.html - cleanup call is needed before 1.1.0 #endif CONF_modules_unload(1); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); #if OPENSSL_VERSION_NUMBER >= 0x10100000 // https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_thread_stop.html OPENSSL_thread_stop(); #else // ERR_remove_state() was deprecated in OpenSSL 1.0.0 and ERR_remove_thread_state() // was deprecated in OpenSSL 1.1.0; these functions and should not be used. // https://www.openssl.org/docs/manmaster/man3/ERR_remove_state.html ERR_remove_state(0); #endif ERR_free_strings(); mutexes.reset(); } static void buildErrors(string& message, int errno_copy = 0, int sslerrno = 0); static bool matchName(const char* host, const char* pattern, int size); static char uppercase(char c); // SSLContext implementation SSLContext::SSLContext(const SSLProtocol& protocol) { if (protocol == SSLTLS) { ctx_ = SSL_CTX_new(SSLv23_method()); #ifndef OPENSSL_NO_SSL3 } else if (protocol == SSLv3) { ctx_ = SSL_CTX_new(SSLv3_method()); #endif } else if (protocol == TLSv1_0) { ctx_ = SSL_CTX_new(TLSv1_method()); } else if (protocol == TLSv1_1) { ctx_ = SSL_CTX_new(TLSv1_1_method()); } else if (protocol == TLSv1_2) { ctx_ = SSL_CTX_new(TLSv1_2_method()); } else { /// UNKNOWN PROTOCOL! throw TSSLException("SSL_CTX_new: Unknown protocol"); } if (ctx_ == nullptr) { string errors; buildErrors(errors); throw TSSLException("SSL_CTX_new: " + errors); } SSL_CTX_set_mode(ctx_, SSL_MODE_AUTO_RETRY); // Disable horribly insecure SSLv2 and SSLv3 protocols but allow a handshake // with older clients so they get a graceful denial. if (protocol == SSLTLS) { SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv2); SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv3); // THRIFT-3164 } } SSLContext::~SSLContext() { if (ctx_ != nullptr) { SSL_CTX_free(ctx_); ctx_ = nullptr; } } SSL* SSLContext::createSSL() { SSL* ssl = SSL_new(ctx_); if (ssl == nullptr) { string errors; buildErrors(errors); throw TSSLException("SSL_new: " + errors); } return ssl; } // TSSLSocket implementation TSSLSocket::TSSLSocket(std::shared_ptr ctx, std::shared_ptr config) : TSocket(config), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, std::shared_ptr interruptListener, std::shared_ptr config) : TSocket(config), server_(false), ssl_(nullptr), ctx_(ctx) { init(); interruptListener_ = interruptListener; } TSSLSocket::TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr config) : TSocket(socket, config), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr interruptListener, std::shared_ptr config) : TSocket(socket, interruptListener, config), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, string host, int port, std::shared_ptr config) : TSocket(host, port, config), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, string host, int port, std::shared_ptr interruptListener, std::shared_ptr config) : TSocket(host, port, config), server_(false), ssl_(nullptr), ctx_(ctx) { init(); interruptListener_ = interruptListener; } TSSLSocket::~TSSLSocket() { close(); } bool TSSLSocket::hasPendingDataToRead() { if (!isOpen()) { return false; } initializeHandshake(); if (!checkHandshake()) throw TSSLException("TSSLSocket::hasPendingDataToRead: Handshake is not completed"); // data may be available in SSL buffers (note: SSL_pending does not have a failure mode) return SSL_pending(ssl_) > 0 || TSocket::hasPendingDataToRead(); } void TSSLSocket::init() { handshakeCompleted_ = false; readRetryCount_ = 0; eventSafe_ = false; } bool TSSLSocket::isOpen() const { if (ssl_ == nullptr || !TSocket::isOpen()) { return false; } int shutdown = SSL_get_shutdown(ssl_); // "!!" is squelching C4800 "forcing bool -> true or false" performance warning bool shutdownReceived = !!(shutdown & SSL_RECEIVED_SHUTDOWN); bool shutdownSent = !!(shutdown & SSL_SENT_SHUTDOWN); if (shutdownReceived && shutdownSent) { return false; } return true; } /* * Note: This method is not libevent safe. */ bool TSSLSocket::peek() { if (!isOpen()) { return false; } initializeHandshake(); if (!checkHandshake()) throw TSSLException("SSL_peek: Handshake is not completed"); int rc; do { uint8_t byte; rc = SSL_peek(ssl_, &byte, 1); if (rc < 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; int error = SSL_get_error(ssl_, rc); switch (error) { case SSL_ERROR_SYSCALL: if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: // in the case of SSL_ERROR_SYSCALL we want to wait for an read event again waitForEvent(error != SSL_ERROR_WANT_WRITE); continue; default:;// do nothing } string errors; buildErrors(errors, errno_copy, error); throw TSSLException("SSL_peek: " + errors); } else if (rc == 0) { ERR_clear_error(); break; } else { break; } } while (true); return (rc > 0); } void TSSLSocket::open() { if (isOpen() || server()) { throw TTransportException(TTransportException::BAD_ARGS); } TSocket::open(); } /* * Note: This method is not libevent safe. */ void TSSLSocket::close() { if (ssl_ != nullptr) { try { int rc; int errno_copy = 0; int error = 0; do { rc = SSL_shutdown(ssl_); if (rc <= 0) { errno_copy = THRIFT_GET_SOCKET_ERROR; error = SSL_get_error(ssl_, rc); switch (error) { case SSL_ERROR_SYSCALL: if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: // in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again waitForEvent(error == SSL_ERROR_WANT_READ); rc = 2; default:;// do nothing } } } while (rc == 2); if (rc < 0) { string errors; buildErrors(errors, errno_copy, error); GlobalOutput(("SSL_shutdown: " + errors).c_str()); } } catch (TTransportException& te) { // Don't emit an exception because this method is called by the // destructor. There's also not much that a user can do to recover, so // just clean up as much as possible without throwing, similar to the rc // < 0 case above. GlobalOutput.printf("SSL_shutdown: %s", te.what()); } SSL_free(ssl_); ssl_ = nullptr; handshakeCompleted_ = false; #if OPENSSL_VERSION_NUMBER >= 0x10100000 // https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_thread_stop.html OPENSSL_thread_stop(); #else // ERR_remove_state() was deprecated in OpenSSL 1.0.0 and ERR_remove_thread_state() // was deprecated in OpenSSL 1.1.0; these functions and should not be used. // https://www.openssl.org/docs/manmaster/man3/ERR_remove_state.html ERR_remove_state(0); #endif } TSocket::close(); } /* * Returns number of bytes read in SSL Socket. * If eventSafe is set, and it may returns 0 bytes then read method * needs to be called again until it is successfull or it throws * exception incase of failure. */ uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); initializeHandshake(); if (!checkHandshake()) throw TTransportException(TTransportException::UNKNOWN, "retry again"); int32_t bytes = 0; while (readRetryCount_ < maxRecvRetries_) { bytes = SSL_read(ssl_, buf, len); int32_t errno_copy = THRIFT_GET_SOCKET_ERROR; int32_t error = SSL_get_error(ssl_, bytes); readRetryCount_++; if (error == SSL_ERROR_NONE) { readRetryCount_ = 0; break; } unsigned int waitEventReturn; bool breakout = false; switch (error) { case SSL_ERROR_ZERO_RETURN: throw TTransportException(TTransportException::END_OF_FILE, "client disconnected"); case SSL_ERROR_SYSCALL: if (errno_copy == 0 && ERR_peek_error() == 0) { breakout = true; break; } if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } if (readRetryCount_ >= maxRecvRetries_) { // THRIFT_EINTR needs to be handled manually and we can tolerate // a certain number break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { if (readRetryCount_ < maxRecvRetries_) { // THRIFT_EINTR needs to be handled manually and we can tolerate // a certain number throw TTransportException(TTransportException::UNKNOWN, "retry again"); } throw TTransportException(TTransportException::INTERNAL_ERROR, "too much recv retries"); } // in the case of SSL_ERROR_SYSCALL we want to wait for an read event again else if ((waitEventReturn = waitForEvent(error != SSL_ERROR_WANT_WRITE)) == TSSL_EINTR ) { // repeat operation if (readRetryCount_ < maxRecvRetries_) { // THRIFT_EINTR needs to be handled manually and we can tolerate // a certain number continue; } throw TTransportException(TTransportException::INTERNAL_ERROR, "too much recv retries"); } else if (waitEventReturn == TSSL_DATA) { // in case of SSL and huge thrift packets, there may be a number of // socket operations, before any data becomes available by SSL_read(). // Therefore the number of retries should not be increased and // the operation should be repeated. readRetryCount_--; continue; } throw TTransportException(TTransportException::INTERNAL_ERROR, "unkown waitForEvent return value"); default:;// do nothing } if (breakout) { break; } string errors; buildErrors(errors, errno_copy, error); throw TSSLException("SSL_read: " + errors); } return bytes; } void TSSLSocket::write(const uint8_t* buf, uint32_t len) { initializeHandshake(); if (!checkHandshake()) return; // loop in case SSL_MODE_ENABLE_PARTIAL_WRITE is set in SSL_CTX. uint32_t written = 0; while (written < len) { ERR_clear_error(); int32_t bytes = SSL_write(ssl_, &buf[written], len - written); if (bytes <= 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; int error = SSL_get_error(ssl_, bytes); switch (error) { case SSL_ERROR_SYSCALL: if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { return; } else { // in the case of SSL_ERROR_SYSCALL we want to wait for an write event again waitForEvent(error == SSL_ERROR_WANT_READ); continue; } default:;// do nothing } string errors; buildErrors(errors, errno_copy, error); throw TSSLException("SSL_write: " + errors); } written += bytes; } } /* * Returns number of bytes written in SSL Socket. * If eventSafe is set, and it may returns 0 bytes then write method * needs to be called again until it is successfull or it throws * exception incase of failure. */ uint32_t TSSLSocket::write_partial(const uint8_t* buf, uint32_t len) { initializeHandshake(); if (!checkHandshake()) return 0; // loop in case SSL_MODE_ENABLE_PARTIAL_WRITE is set in SSL_CTX. uint32_t written = 0; while (written < len) { ERR_clear_error(); int32_t bytes = SSL_write(ssl_, &buf[written], len - written); if (bytes <= 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; int error = SSL_get_error(ssl_, bytes); switch (error) { case SSL_ERROR_SYSCALL: if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { return 0; } else { // in the case of SSL_ERROR_SYSCALL we want to wait for an write event again waitForEvent(error == SSL_ERROR_WANT_READ); continue; } default:;// do nothing } string errors; buildErrors(errors, errno_copy, error); throw TSSLException("SSL_write: " + errors); } written += bytes; } return written; } void TSSLSocket::flush() { resetConsumedMessageSize(); // Don't throw exception if not open. Thrift servers close socket twice. if (ssl_ == nullptr) { return; } initializeHandshake(); if (!checkHandshake()) throw TSSLException("BIO_flush: Handshake is not completed"); BIO* bio = SSL_get_wbio(ssl_); if (bio == nullptr) { throw TSSLException("SSL_get_wbio returns nullptr"); } if (BIO_flush(bio) != 1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("BIO_flush: " + errors); } } void TSSLSocket::initializeHandshakeParams() { // set underlying socket to non-blocking int flags; if ((flags = THRIFT_FCNTL(socket_, THRIFT_F_GETFL, 0)) < 0 || THRIFT_FCNTL(socket_, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK) < 0) { GlobalOutput.perror("thriftServerEventHandler: set THRIFT_O_NONBLOCK (THRIFT_FCNTL) ", THRIFT_GET_SOCKET_ERROR); ::THRIFT_CLOSESOCKET(socket_); return; } ssl_ = ctx_->createSSL(); SSL_set_fd(ssl_, static_cast(socket_)); } bool TSSLSocket::checkHandshake() { return handshakeCompleted_; } void TSSLSocket::initializeHandshake() { if (!TSocket::isOpen()) { throw TTransportException(TTransportException::NOT_OPEN); } if (checkHandshake()) { return; } if (ssl_ == nullptr) { initializeHandshakeParams(); } int rc; int errno_copy = 0; int error = 0; if (server()) { do { rc = SSL_accept(ssl_); if (rc <= 0) { errno_copy = THRIFT_GET_SOCKET_ERROR; error = SSL_get_error(ssl_, rc); switch (error) { case SSL_ERROR_SYSCALL: if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { return; } else { // repeat operation // in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again waitForEvent(error == SSL_ERROR_WANT_READ); rc = 2; } default:;// do nothing } } } while (rc == 2); } else { // OpenSSL < 0.9.8f does not have SSL_set_tlsext_host_name() #if defined(SSL_set_tlsext_host_name) // set the SNI hostname SSL_set_tlsext_host_name(ssl_, getHost().c_str()); #endif do { rc = SSL_connect(ssl_); if (rc <= 0) { errno_copy = THRIFT_GET_SOCKET_ERROR; error = SSL_get_error(ssl_, rc); switch (error) { case SSL_ERROR_SYSCALL: if ((errno_copy != THRIFT_EINTR) && (errno_copy != THRIFT_EAGAIN)) { break; } // fallthrough case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: if (isLibeventSafe()) { return; } else { // repeat operation // in the case of SSL_ERROR_SYSCALL we want to wait for an write/read event again waitForEvent(error == SSL_ERROR_WANT_READ); rc = 2; } default:;// do nothing } } } while (rc == 2); } if (rc <= 0) { string fname(server() ? "SSL_accept" : "SSL_connect"); string errors; buildErrors(errors, errno_copy, error); throw TSSLException(fname + ": " + errors); } authorize(); handshakeCompleted_ = true; } void TSSLSocket::authorize() { int rc = SSL_get_verify_result(ssl_); if (rc != X509_V_OK) { // verify authentication result throw TSSLException(string("SSL_get_verify_result(), ") + X509_verify_cert_error_string(rc)); } X509* cert = SSL_get_peer_certificate(ssl_); if (cert == nullptr) { // certificate is not present if (SSL_get_verify_mode(ssl_) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { throw TSSLException("authorize: required certificate not present"); } // certificate was optional: didn't intend to authorize remote if (server() && access_ != nullptr) { throw TSSLException("authorize: certificate required for authorization"); } return; } // certificate is present if (access_ == nullptr) { X509_free(cert); return; } // both certificate and access manager are present string host; sockaddr_storage sa; socklen_t saLength = sizeof(sa); if (getpeername(socket_, (sockaddr*)&sa, &saLength) != 0) { sa.ss_family = AF_UNSPEC; } AccessManager::Decision decision = access_->verify(sa); if (decision != AccessManager::SKIP) { X509_free(cert); if (decision != AccessManager::ALLOW) { throw TSSLException("authorize: access denied based on remote IP"); } return; } // extract subjectAlternativeName auto* alternatives = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr); if (alternatives != nullptr) { const int count = sk_GENERAL_NAME_num(alternatives); for (int i = 0; decision == AccessManager::SKIP && i < count; i++) { const GENERAL_NAME* name = sk_GENERAL_NAME_value(alternatives, i); if (name == nullptr) { continue; } char* data = (char*)ASN1_STRING_data(name->d.ia5); int length = ASN1_STRING_length(name->d.ia5); switch (name->type) { case GEN_DNS: if (host.empty()) { host = (server() ? getPeerHost() : getHost()); } decision = access_->verify(host, data, length); break; case GEN_IPADD: decision = access_->verify(sa, data, length); break; } } sk_GENERAL_NAME_pop_free(alternatives, GENERAL_NAME_free); } if (decision != AccessManager::SKIP) { X509_free(cert); if (decision != AccessManager::ALLOW) { throw TSSLException("authorize: access denied"); } return; } // extract commonName X509_NAME* name = X509_get_subject_name(cert); if (name != nullptr) { X509_NAME_ENTRY* entry; unsigned char* utf8; int last = -1; while (decision == AccessManager::SKIP) { last = X509_NAME_get_index_by_NID(name, NID_commonName, last); if (last == -1) break; entry = X509_NAME_get_entry(name, last); if (entry == nullptr) continue; ASN1_STRING* common = X509_NAME_ENTRY_get_data(entry); int size = ASN1_STRING_to_UTF8(&utf8, common); if (host.empty()) { host = (server() ? getPeerHost() : getHost()); } decision = access_->verify(host, (char*)utf8, size); OPENSSL_free(utf8); } } X509_free(cert); if (decision != AccessManager::ALLOW) { throw TSSLException("authorize: cannot authorize peer"); } } /* * Note: This method is not libevent safe. */ unsigned int TSSLSocket::waitForEvent(bool wantRead) { int fdSocket; BIO* bio; if (wantRead) { bio = SSL_get_rbio(ssl_); } else { bio = SSL_get_wbio(ssl_); } if (bio == nullptr) { throw TSSLException("SSL_get_?bio returned nullptr"); } if (BIO_get_fd(bio, &fdSocket) < 0) { throw TSSLException("BIO_get_fd failed"); } struct THRIFT_POLLFD fds[2]; memset(fds, 0, sizeof(fds)); fds[0].fd = fdSocket; // use POLLIN also on write operations too, this is needed for operations // which requires read and write on the socket. fds[0].events = wantRead ? THRIFT_POLLIN : THRIFT_POLLIN | THRIFT_POLLOUT; if (interruptListener_) { fds[1].fd = *(interruptListener_.get()); fds[1].events = THRIFT_POLLIN; } int timeout = -1; if (wantRead && recvTimeout_) { timeout = recvTimeout_; } if (!wantRead && sendTimeout_) { timeout = sendTimeout_; } int ret = THRIFT_POLL(fds, interruptListener_ ? 2 : 1, timeout); if (ret < 0) { // error cases if (THRIFT_GET_SOCKET_ERROR == THRIFT_EINTR) { return TSSL_EINTR; // repeat operation } int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSSLSocket::read THRIFT_POLL() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); } else if (ret > 0){ if (fds[1].revents & THRIFT_POLLIN) { throw TTransportException(TTransportException::INTERRUPTED, "Interrupted"); } return TSSL_DATA; } else { throw TTransportException(TTransportException::TIMED_OUT, "THRIFT_POLL (timed out)"); } } // TSSLSocketFactory implementation uint64_t TSSLSocketFactory::count_ = 0; Mutex TSSLSocketFactory::mutex_; bool TSSLSocketFactory::manualOpenSSLInitialization_ = false; TSSLSocketFactory::TSSLSocketFactory(SSLProtocol protocol) : server_(false) { Guard guard(mutex_); if (count_ == 0) { if (!manualOpenSSLInitialization_) { initializeOpenSSL(); } randomize(); } count_++; ctx_ = std::make_shared(protocol); } TSSLSocketFactory::~TSSLSocketFactory() { Guard guard(mutex_); ctx_.reset(); count_--; if (count_ == 0 && !manualOpenSSLInitialization_) { cleanupOpenSSL(); } } std::shared_ptr TSSLSocketFactory::createSocket() { std::shared_ptr ssl(new TSSLSocket(ctx_)); setup(ssl); return ssl; } std::shared_ptr TSSLSocketFactory::createSocket(std::shared_ptr interruptListener) { std::shared_ptr ssl(new TSSLSocket(ctx_, interruptListener)); setup(ssl); return ssl; } std::shared_ptr TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) { std::shared_ptr ssl(new TSSLSocket(ctx_, socket)); setup(ssl); return ssl; } std::shared_ptr TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener) { std::shared_ptr ssl(new TSSLSocket(ctx_, socket, interruptListener)); setup(ssl); return ssl; } std::shared_ptr TSSLSocketFactory::createSocket(const string& host, int port) { std::shared_ptr ssl(new TSSLSocket(ctx_, host, port)); setup(ssl); return ssl; } std::shared_ptr TSSLSocketFactory::createSocket(const string& host, int port, std::shared_ptr interruptListener) { std::shared_ptr ssl(new TSSLSocket(ctx_, host, port, interruptListener)); setup(ssl); return ssl; } void TSSLSocketFactory::setup(std::shared_ptr ssl) { ssl->server(server()); if (access_ == nullptr && !server()) { access_ = std::shared_ptr(new DefaultClientAccessManager); } if (access_ != nullptr) { ssl->access(access_); } } void TSSLSocketFactory::ciphers(const string& enable) { int rc = SSL_CTX_set_cipher_list(ctx_->get(), enable.c_str()); if (ERR_peek_error() != 0) { string errors; buildErrors(errors); throw TSSLException("SSL_CTX_set_cipher_list: " + errors); } if (rc == 0) { throw TSSLException("None of specified ciphers are supported"); } } void TSSLSocketFactory::authenticate(bool required) { int mode; if (required) { mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; } else { mode = SSL_VERIFY_NONE; } SSL_CTX_set_verify(ctx_->get(), mode, nullptr); } void TSSLSocketFactory::loadCertificate(const char* path, const char* format) { if (path == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadCertificateChain: either or is nullptr"); } if (strcmp(format, "PEM") == 0) { if (SSL_CTX_use_certificate_chain_file(ctx_->get(), path) == 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("SSL_CTX_use_certificate_chain_file: " + errors); } } else { throw TSSLException("Unsupported certificate format: " + string(format)); } } void TSSLSocketFactory::loadCertificateFromBuffer(const char* aCertificate, const char* format) { if (aCertificate == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadCertificate: either or is nullptr"); } if (strcmp(format, "PEM") == 0) { BIO* mem = BIO_new(BIO_s_mem()); BIO_puts(mem, aCertificate); X509* cert = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr); BIO_free(mem); const int status = SSL_CTX_use_certificate(ctx_->get(), cert); X509_free(cert); if (status != 1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("SSL_CTX_use_certificate: " + errors); } } else { throw TSSLException("Unsupported certificate format: " + string(format)); } } void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) { if (path == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadPrivateKey: either or is nullptr"); } if (strcmp(format, "PEM") == 0) { if (SSL_CTX_use_PrivateKey_file(ctx_->get(), path, SSL_FILETYPE_PEM) == 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("SSL_CTX_use_PrivateKey_file: " + errors); } } } void TSSLSocketFactory::loadPrivateKeyFromBuffer(const char* aPrivateKey, const char* format) { if (aPrivateKey == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadPrivateKey: either or is nullptr"); } if (strcmp(format, "PEM") == 0) { EVP_PKEY* cert; BIO* mem; mem = BIO_new(BIO_s_mem()); BIO_puts(mem, aPrivateKey); cert = PEM_read_bio_PrivateKey(mem, nullptr, nullptr, nullptr); BIO_free(mem); const int status = SSL_CTX_use_PrivateKey(ctx_->get(), cert); EVP_PKEY_free(cert); if (status == 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("SSL_CTX_use_PrivateKey: " + errors); } } else { throw TSSLException("Unsupported certificate format: " + string(format)); } } void TSSLSocketFactory::loadTrustedCertificates(const char* path, const char* capath) { if (path == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadTrustedCertificates: is nullptr"); } if (SSL_CTX_load_verify_locations(ctx_->get(), path, capath) == 0) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("SSL_CTX_load_verify_locations: " + errors); } } void TSSLSocketFactory::loadTrustedCertificatesFromBuffer(const char* aCertificate, const char* aChain) { if (aCertificate == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadTrustedCertificates: aCertificate is empty"); } X509_STORE* vX509Store = SSL_CTX_get_cert_store(ctx_->get()); BIO* mem = BIO_new(BIO_s_mem()); BIO_puts(mem, aCertificate); X509* cert = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr); BIO_free(mem); const int status = X509_STORE_add_cert(vX509Store, cert); X509_free(cert); if (status != 1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("X509_STORE_add_cert: " + errors); } if (aChain) { mem = BIO_new(BIO_s_mem()); BIO_puts(mem, aChain); cert = PEM_read_bio_X509(mem, nullptr, nullptr, nullptr); BIO_free(mem); // NOTE: The x509 certificate provided to SSL_CTX_add_extra_chain_cert() // will be freed by the library when the SSL_CTX is destroyed. Do not free // the x509 object manually here. if (SSL_CTX_add_extra_chain_cert(ctx_->get(), cert) == 0) { X509_free(cert); int errno_copy = THRIFT_GET_SOCKET_ERROR; string errors; buildErrors(errors, errno_copy); throw TSSLException("X509_STORE_add_cert: " + errors); } } } void TSSLSocketFactory::randomize() { RAND_poll(); } void TSSLSocketFactory::overrideDefaultPasswordCallback() { SSL_CTX_set_default_passwd_cb(ctx_->get(), passwordCallback); SSL_CTX_set_default_passwd_cb_userdata(ctx_->get(), this); } int TSSLSocketFactory::passwordCallback(char* password, int size, int, void* data) { auto* factory = (TSSLSocketFactory*)data; string userPassword; factory->getPassword(userPassword, size); int length = static_cast(userPassword.size()); if (length > size) { length = size; } strncpy(password, userPassword.c_str(), length); userPassword.assign(userPassword.size(), '*'); return length; } // extract error messages from error queue void buildErrors(string& errors, int errno_copy, int sslerrno) { unsigned long errorCode; char message[256]; errors.reserve(512); while ((errorCode = ERR_get_error()) != 0) { if (!errors.empty()) { errors += "; "; } const char* reason = ERR_reason_error_string(errorCode); if (reason == nullptr) { THRIFT_SNPRINTF(message, sizeof(message) - 1, "SSL error # %lu", errorCode); reason = message; } errors += reason; } if (errors.empty()) { if (errno_copy != 0) { errors += TOutput::strerror_s(errno_copy); } } if (errors.empty()) { errors = "error code: " + to_string(errno_copy); } if (sslerrno) { errors += " (SSL_error_code = " + to_string(sslerrno) + ")"; if (sslerrno == SSL_ERROR_SYSCALL) { char buf[4096]; int err; while ((err = ERR_get_error()) != 0) { errors += " "; errors += ERR_error_string(err, buf); } } } } /** * Default implementation of AccessManager */ Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) noexcept { (void)sa; return SKIP; } Decision DefaultClientAccessManager::verify(const string& host, const char* name, int size) noexcept { if (host.empty() || name == nullptr || size <= 0) { return SKIP; } return (matchName(host.c_str(), name, size) ? ALLOW : SKIP); } Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa, const char* data, int size) noexcept { bool match = false; if (sa.ss_family == AF_INET && size == sizeof(in_addr)) { match = (memcmp(&((sockaddr_in*)&sa)->sin_addr, data, size) == 0); } else if (sa.ss_family == AF_INET6 && size == sizeof(in6_addr)) { match = (memcmp(&((sockaddr_in6*)&sa)->sin6_addr, data, size) == 0); } return (match ? ALLOW : SKIP); } /** * Match a name with a pattern. The pattern may include wildcard. A single * wildcard "*" can match up to one component in the domain name. * * @param host Host name, typically the name of the remote host * @param pattern Name retrieved from certificate * @param size Size of "pattern" * @return True, if "host" matches "pattern". False otherwise. */ bool matchName(const char* host, const char* pattern, int size) { bool match = false; int i = 0, j = 0; while (i < size && host[j] != '\0') { if (uppercase(pattern[i]) == uppercase(host[j])) { i++; j++; continue; } if (pattern[i] == '*') { while (host[j] != '.' && host[j] != '\0') { j++; } i++; continue; } break; } if (i == size && host[j] == '\0') { match = true; } return match; } // This is to work around the Turkish locale issue, i.e., // toupper('i') != toupper('I') if locale is "tr_TR" char uppercase(char c) { if ('a' <= c && c <= 'z') { return c + ('A' - 'a'); } return c; } } } } thrift-0.19.0/lib/cpp/src/thrift/transport/TTransportException.h0000644000000000000000000000636714370300523024733 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ #define _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1 #include #include #include namespace apache { namespace thrift { namespace transport { /** * Class to encapsulate all the possible types of transport errors that may * occur in various transport systems. This provides a sort of generic * wrapper around the vague UNIX E_ error codes that lets a common code * base of error handling to be used for various types of transports, i.e. * pipes etc. * */ class TTransportException : public apache::thrift::TException { public: /** * Error codes for the various types of exceptions. */ enum TTransportExceptionType { UNKNOWN = 0, NOT_OPEN = 1, TIMED_OUT = 2, END_OF_FILE = 3, INTERRUPTED = 4, BAD_ARGS = 5, CORRUPTED_DATA = 6, INTERNAL_ERROR = 7, CLIENT_DISCONNECT = 8 }; TTransportException() : apache::thrift::TException(), type_(UNKNOWN) {} TTransportException(TTransportExceptionType type) : apache::thrift::TException(), type_(type) {} TTransportException(const std::string& message) : apache::thrift::TException(message), type_(UNKNOWN) {} TTransportException(TTransportExceptionType type, const std::string& message) : apache::thrift::TException(message), type_(type) {} TTransportException(TTransportExceptionType type, const std::string& message, int errno_copy) : apache::thrift::TException(message + ": " + TOutput::strerror_s(errno_copy)), type_(type) {} ~TTransportException() noexcept override = default; /** * Returns an error code that provides information about the type of error * that has occurred. * * @return Error code */ TTransportExceptionType getType() const noexcept { return type_; } const char* what() const noexcept override; protected: /** Just like strerror_r but returns a C++ string object. */ std::string strerror_s(int errno_copy); /** Error code */ TTransportExceptionType type_; }; /** * Legacy code in transport implementations have overflow issues * that need to be enforced. */ template To safe_numeric_cast(From i) { try { return apache::thrift::numeric_cast(i); } catch (const std::bad_cast& bc) { throw TTransportException(TTransportException::CORRUPTED_DATA, bc.what()); } } } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TPipe.h0000644000000000000000000000701714303740367021760 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TPIPE_H_ #define _THRIFT_TRANSPORT_TPIPE_H_ 1 #include #include #ifndef _WIN32 #include #endif #ifdef _WIN32 #include #endif #include #ifdef _WIN32 #include #endif namespace apache { namespace thrift { namespace transport { /** * Windows Pipes implementation of the TTransport interface. * Don't destroy a TPipe at global scope, as that will cause a thread join * during DLLMain. That also means that client objects using TPipe shouldn't be at global * scope. */ #ifdef _WIN32 class TPipeImpl; class TPipe : public TVirtualTransport { public: // Constructs a new pipe object. TPipe(std::shared_ptr config = nullptr); // Named pipe constructors - explicit TPipe(HANDLE Pipe, std::shared_ptr config = nullptr); // HANDLE is a void* explicit TPipe(TAutoHandle& Pipe, std::shared_ptr config = nullptr); // this ctor will clear out / move from Pipe // need a const char * overload so string literals don't go to the HANDLE overload explicit TPipe(const char* pipename, std::shared_ptr config = nullptr); explicit TPipe(const std::string& pipename, std::shared_ptr config = nullptr); // Anonymous pipe - TPipe(HANDLE PipeRd, HANDLE PipeWrt, std::shared_ptr config = nullptr); // Destroys the pipe object, closing it if necessary. virtual ~TPipe(); // Returns whether the pipe is open & valid. bool isOpen() const override; // Checks whether more data is available in the pipe. bool peek() override; // Creates and opens the named/anonymous pipe. void open() override; // Shuts down communications on the pipe. void close() override; // Reads from the pipe. virtual uint32_t read(uint8_t* buf, uint32_t len); // Writes to the pipe. virtual void write(const uint8_t* buf, uint32_t len); // Accessors std::string getPipename(); void setPipename(const std::string& pipename); HANDLE getPipeHandle(); // doubles as the read handle for anon pipe void setPipeHandle(HANDLE pipehandle); HANDLE getWrtPipeHandle(); void setWrtPipeHandle(HANDLE pipehandle); long getConnTimeout(); void setConnTimeout(long seconds); // this function is intended to be used in generic / template situations, // so its name needs to be the same as TPipeServer's HANDLE getNativeWaitHandle(); private: std::shared_ptr impl_; std::string pipename_; long TimeoutSeconds_; bool isAnonymous_; }; #else typedef TSocket TPipe; #endif } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TPIPE_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp0000644000000000000000000000411514303740367026577 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include namespace apache { namespace thrift { namespace transport { /** * Nonblocking SSL server socket implementation. */ TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, std::shared_ptr factory) : TNonblockingServerSocket(port), factory_(factory) { factory_->server(true); } TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(const std::string& address, int port, std::shared_ptr factory) : TNonblockingServerSocket(address, port), factory_(factory) { factory_->server(true); } TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, int sendTimeout, int recvTimeout, std::shared_ptr factory) : TNonblockingServerSocket(port, sendTimeout, recvTimeout), factory_(factory) { factory_->server(true); } std::shared_ptr TNonblockingSSLServerSocket::createSocket(THRIFT_SOCKET client) { std::shared_ptr tSSLSocket; tSSLSocket = factory_->createSocket(client); tSSLSocket->setLibeventSafe(); return tSSLSocket; } } } } thrift-0.19.0/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h0000644000000000000000000001013714303740367025663 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERSOCKET_H_ #define _THRIFT_TRANSPORT_TNONBLOCKINGSERVERSOCKET_H_ 1 #include #include namespace apache { namespace thrift { namespace transport { class TSocket; /** * Nonblocking Server socket implementation of TNonblockingServerTransport. Wrapper around a unix * socket listen and accept calls. * */ class TNonblockingServerSocket : public TNonblockingServerTransport { public: typedef std::function socket_func_t; const static int DEFAULT_BACKLOG = 1024; /** * Constructor. * * @param port Port number to bind to */ TNonblockingServerSocket(int port); /** * Constructor. * * @param port Port number to bind to * @param sendTimeout Socket send timeout * @param recvTimeout Socket receive timeout */ TNonblockingServerSocket(int port, int sendTimeout, int recvTimeout); /** * Constructor. * * @param address Address to bind to * @param port Port number to bind to */ TNonblockingServerSocket(const std::string& address, int port); /** * Constructor used for unix sockets. * * @param path Pathname for unix socket. */ TNonblockingServerSocket(const std::string& path); ~TNonblockingServerSocket() override; bool isOpen() const; void setSendTimeout(int sendTimeout); void setRecvTimeout(int recvTimeout); void setAcceptBacklog(int accBacklog); void setRetryLimit(int retryLimit); void setRetryDelay(int retryDelay); void setKeepAlive(bool keepAlive) { keepAlive_ = keepAlive; } void setTcpSendBuffer(int tcpSendBuffer); void setTcpRecvBuffer(int tcpRecvBuffer); // listenCallback gets called just before listen, and after all Thrift // setsockopt calls have been made. If you have custom setsockopt // things that need to happen on the listening socket, this is the place to do it. void setListenCallback(const socket_func_t& listenCallback) { listenCallback_ = listenCallback; } // acceptCallback gets called after each accept call, on the newly created socket. // It is called after all Thrift setsockopt calls have been made. If you have // custom setsockopt things that need to happen on the accepted // socket, this is the place to do it. void setAcceptCallback(const socket_func_t& acceptCallback) { acceptCallback_ = acceptCallback; } THRIFT_SOCKET getSocketFD() override { return serverSocket_; } int getPort() override; int getListenPort() override; std::string getPath() const; bool isUnixDomainSocket() const; void listen() override; void close() override; protected: std::shared_ptr acceptImpl() override; virtual std::shared_ptr createSocket(THRIFT_SOCKET client); private: void _setup_sockopts(); void _setup_unixdomain_sockopts(); void _setup_tcp_sockopts(); int port_; int listenPort_; std::string address_; std::string path_; THRIFT_SOCKET serverSocket_; int acceptBacklog_; int sendTimeout_; int recvTimeout_; int retryLimit_; int retryDelay_; int tcpSendBuffer_; int tcpRecvBuffer_; bool keepAlive_; bool listening_; socket_func_t listenCallback_; socket_func_t acceptCallback_; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSERVERSOCKET_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TFileTransport.h0000644000000000000000000003114514303740367023656 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TFILETRANSPORT_H_ #define _THRIFT_TRANSPORT_TFILETRANSPORT_H_ 1 #include #include #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace transport { using apache::thrift::TProcessor; using apache::thrift::protocol::TProtocolFactory; using apache::thrift::concurrency::Mutex; using apache::thrift::concurrency::Monitor; // Data pertaining to a single event typedef struct eventInfo { uint8_t* eventBuff_; uint32_t eventSize_; uint32_t eventBuffPos_; eventInfo() : eventBuff_(nullptr), eventSize_(0), eventBuffPos_(0){}; ~eventInfo() { if (eventBuff_) { delete[] eventBuff_; } } } eventInfo; // information about current read state typedef struct readState { eventInfo* event_; // keep track of event size uint8_t eventSizeBuff_[4]; uint8_t eventSizeBuffPos_; bool readingSize_; // read buffer variables int32_t bufferPtr_; int32_t bufferLen_; // last successful dispatch point int32_t lastDispatchPtr_; void resetState(uint32_t lastDispatchPtr) { readingSize_ = true; eventSizeBuffPos_ = 0; lastDispatchPtr_ = lastDispatchPtr; } void resetAllValues() { resetState(0); bufferPtr_ = 0; bufferLen_ = 0; if (event_) { delete (event_); } event_ = nullptr; } inline uint32_t getEventSize() { const void* buffer = reinterpret_cast(eventSizeBuff_); return *reinterpret_cast(buffer); } readState() { event_ = nullptr; resetAllValues(); } ~readState() { if (event_) { delete (event_); } } } readState; /** * TFileTransportBuffer - buffer class used by TFileTransport for queueing up events * to be written to disk. Should be used in the following way: * 1) Buffer created * 2) Buffer written to (addEvent) * 3) Buffer read from (getNext) * 4) Buffer reset (reset) * 5) Go back to 2, or destroy buffer * * The buffer should never be written to after it is read from, unless it is reset first. * Note: The above rules are enforced mainly for debugging its sole client TFileTransport * which uses the buffer in this way. * */ class TFileTransportBuffer { public: TFileTransportBuffer(uint32_t size); ~TFileTransportBuffer(); bool addEvent(eventInfo* event); eventInfo* getNext(); void reset(); bool isFull(); bool isEmpty(); private: TFileTransportBuffer(); // should not be used enum mode { WRITE, READ }; mode bufferMode_; uint32_t writePoint_; uint32_t readPoint_; uint32_t size_; eventInfo** buffer_; }; /** * Abstract interface for transports used to read files */ class TFileReaderTransport : virtual public TTransport { public: virtual int32_t getReadTimeout() = 0; virtual void setReadTimeout(int32_t readTimeout) = 0; virtual uint32_t getNumChunks() = 0; virtual uint32_t getCurChunk() = 0; virtual void seekToChunk(int32_t chunk) = 0; virtual void seekToEnd() = 0; }; /** * Abstract interface for transports used to write files */ class TFileWriterTransport : virtual public TTransport { public: virtual uint32_t getChunkSize() = 0; virtual void setChunkSize(uint32_t chunkSize) = 0; }; /** * File implementation of a transport. Reads and writes are done to a * file on disk. * */ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport { public: TFileTransport(std::string path, bool readOnly = false, std::shared_ptr config = nullptr); ~TFileTransport() override; // TODO: what is the correct behaviour for this? // the log file is generally always open bool isOpen() const override { return true; } void write(const uint8_t* buf, uint32_t len); void flush() override; uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t read(uint8_t* buf, uint32_t len); bool peek() override; // log-file specific functions void seekToChunk(int32_t chunk) override; void seekToEnd() override; uint32_t getNumChunks() override; uint32_t getCurChunk() override; // for changing the output file void resetOutputFile(int fd, std::string filename, off_t offset); // Setter/Getter functions for user-controllable options void setReadBuffSize(uint32_t readBuffSize) { if (readBuffSize) { readBuffSize_ = readBuffSize; } } uint32_t getReadBuffSize() { return readBuffSize_; } static const int32_t TAIL_READ_TIMEOUT = -1; static const int32_t NO_TAIL_READ_TIMEOUT = 0; void setReadTimeout(int32_t readTimeout) override { readTimeout_ = readTimeout; } int32_t getReadTimeout() override { return readTimeout_; } void setChunkSize(uint32_t chunkSize) override { if (chunkSize) { chunkSize_ = chunkSize; } } uint32_t getChunkSize() override { return chunkSize_; } void setEventBufferSize(uint32_t bufferSize) { if (bufferAndThreadInitialized_) { GlobalOutput("Cannot change the buffer size after writer thread started"); return; } eventBufferSize_ = bufferSize; } uint32_t getEventBufferSize() { return eventBufferSize_; } void setFlushMaxUs(uint32_t flushMaxUs) { if (flushMaxUs) { flushMaxUs_ = flushMaxUs; } } uint32_t getFlushMaxUs() { return flushMaxUs_; } void setFlushMaxBytes(uint32_t flushMaxBytes) { if (flushMaxBytes) { flushMaxBytes_ = flushMaxBytes; } } uint32_t getFlushMaxBytes() { return flushMaxBytes_; } void setMaxEventSize(uint32_t maxEventSize) { maxEventSize_ = maxEventSize; } uint32_t getMaxEventSize() { return maxEventSize_; } void setMaxCorruptedEvents(uint32_t maxCorruptedEvents) { maxCorruptedEvents_ = maxCorruptedEvents; } uint32_t getMaxCorruptedEvents() { return maxCorruptedEvents_; } void setEofSleepTimeUs(uint32_t eofSleepTime) { if (eofSleepTime) { eofSleepTime_ = eofSleepTime; } } uint32_t getEofSleepTimeUs() { return eofSleepTime_; } /* * Override TTransport *_virt() functions to invoke our implementations. * We cannot use TVirtualTransport to provide these, since we need to inherit * virtually from TTransport. */ uint32_t read_virt(uint8_t* buf, uint32_t len) override { return this->read(buf, len); } uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { return this->readAll(buf, len); } void write_virt(const uint8_t* buf, uint32_t len) override { this->write(buf, len); } private: // helper functions for writing to a file void enqueueEvent(const uint8_t* buf, uint32_t eventLen); bool swapEventBuffers(const std::chrono::time_point *deadline); bool initBufferAndWriteThread(); // control for writer thread static void* startWriterThread(void* ptr) { static_cast(ptr)->writerThread(); return nullptr; } void writerThread(); // helper functions for reading from a file eventInfo* readEvent(); // event corruption-related functions bool isEventCorrupted(); void performRecovery(); // Utility functions void openLogFile(); std::chrono::time_point getNextFlushTime(); // Class variables readState readState_; uint8_t* readBuff_; eventInfo* currentEvent_; uint32_t readBuffSize_; static const uint32_t DEFAULT_READ_BUFF_SIZE = 1 * 1024 * 1024; int32_t readTimeout_; static const int32_t DEFAULT_READ_TIMEOUT_MS = 200; // size of chunks that file will be split up into uint32_t chunkSize_; static const uint32_t DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; // size of event buffers uint32_t eventBufferSize_; static const uint32_t DEFAULT_EVENT_BUFFER_SIZE = 10000; // max number of microseconds that can pass without flushing uint32_t flushMaxUs_; static const uint32_t DEFAULT_FLUSH_MAX_US = 3000000; // max number of bytes that can be written without flushing uint32_t flushMaxBytes_; static const uint32_t DEFAULT_FLUSH_MAX_BYTES = 1000 * 1024; // max event size uint32_t maxEventSize_; static const uint32_t DEFAULT_MAX_EVENT_SIZE = 0; // max number of corrupted events per chunk uint32_t maxCorruptedEvents_; static const uint32_t DEFAULT_MAX_CORRUPTED_EVENTS = 0; // sleep duration when EOF is hit uint32_t eofSleepTime_; static const uint32_t DEFAULT_EOF_SLEEP_TIME_US = 500 * 1000; // sleep duration when a corrupted event is encountered uint32_t corruptedEventSleepTime_; static const uint32_t DEFAULT_CORRUPTED_SLEEP_TIME_US = 1 * 1000 * 1000; // sleep duration in seconds when an IO error is encountered in the writer thread uint32_t writerThreadIOErrorSleepTime_; static const uint32_t DEFAULT_WRITER_THREAD_SLEEP_TIME_US = 60 * 1000 * 1000; // writer thread apache::thrift::concurrency::ThreadFactory threadFactory_; std::shared_ptr writerThread_; // buffers to hold data before it is flushed. Each element of the buffer stores a msg that // needs to be written to the file. The buffers are swapped by the writer thread. TFileTransportBuffer* dequeueBuffer_; TFileTransportBuffer* enqueueBuffer_; // conditions used to block when the buffer is full or empty Monitor notFull_, notEmpty_; std::atomic closing_; // To keep track of whether the buffer has been flushed Monitor flushed_; std::atomic forceFlush_; // Mutex that is grabbed when enqueueing and swapping the read/write buffers Mutex mutex_; // File information std::string filename_; int fd_; // Whether the writer thread and buffers have been initialized bool bufferAndThreadInitialized_; // Offset within the file off_t offset_; // event corruption information uint32_t lastBadChunk_; uint32_t numCorruptedEventsInChunk_; bool readOnly_; }; // Exception thrown when EOF is hit class TEOFException : public TTransportException { public: TEOFException() : TTransportException(TTransportException::END_OF_FILE){}; }; // wrapper class to process events from a file containing thrift events class TFileProcessor { public: /** * Constructor that defaults output transport to null transport * * @param processor processes log-file events * @param protocolFactory protocol factory * @param inputTransport file transport */ TFileProcessor(std::shared_ptr processor, std::shared_ptr protocolFactory, std::shared_ptr inputTransport); TFileProcessor(std::shared_ptr processor, std::shared_ptr inputProtocolFactory, std::shared_ptr outputProtocolFactory, std::shared_ptr inputTransport); /** * Constructor * * @param processor processes log-file events * @param protocolFactory protocol factory * @param inputTransport input file transport * @param output output transport */ TFileProcessor(std::shared_ptr processor, std::shared_ptr protocolFactory, std::shared_ptr inputTransport, std::shared_ptr outputTransport); /** * processes events from the file * * @param numEvents number of events to process (0 for unlimited) * @param tail tails the file if true */ void process(uint32_t numEvents, bool tail); /** * process events until the end of the chunk * */ void processChunk(); private: std::shared_ptr processor_; std::shared_ptr inputProtocolFactory_; std::shared_ptr outputProtocolFactory_; std::shared_ptr inputTransport_; std::shared_ptr outputTransport_; }; } } } // apache::thrift::transport #endif // _THRIFT_TRANSPORT_TFILETRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TSocketPool.h0000644000000000000000000001074614303740367023150 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ #define _THRIFT_TRANSPORT_TSOCKETPOOL_H_ 1 #include #include namespace apache { namespace thrift { namespace transport { /** * Class to hold server information for TSocketPool * */ class TSocketPoolServer { public: /** * Default constructor for server info */ TSocketPoolServer(); /** * Constructor for TSocketPool server */ TSocketPoolServer(const std::string& host, int port); // Host name std::string host_; // Port to connect on int port_; // Socket for the server THRIFT_SOCKET socket_; // Last time connecting to this server failed time_t lastFailTime_; // Number of consecutive times connecting to this server failed int consecutiveFailures_; }; /** * TCP Socket implementation of the TTransport interface. * */ class TSocketPool : public TSocket { public: /** * Socket pool constructor */ TSocketPool(); /** * Socket pool constructor * * @param hosts list of host names * @param ports list of port names */ TSocketPool(const std::vector& hosts, const std::vector& ports); /** * Socket pool constructor * * @param servers list of pairs of host name and port */ TSocketPool(const std::vector >& servers); /** * Socket pool constructor * * @param servers list of TSocketPoolServers */ TSocketPool(const std::vector >& servers); /** * Socket pool constructor * * @param host single host * @param port single port */ TSocketPool(const std::string& host, int port); /** * Destroyes the socket object, closing it if necessary. */ ~TSocketPool() override; /** * Add a server to the pool */ void addServer(const std::string& host, int port); /** * Add a server to the pool */ void addServer(std::shared_ptr& server); /** * Set list of servers in this pool */ void setServers(const std::vector >& servers); /** * Get list of servers in this pool */ void getServers(std::vector >& servers); /** * Sets how many times to keep retrying a host in the connect function. */ void setNumRetries(int numRetries); /** * Sets how long to wait until retrying a host if it was marked down */ void setRetryInterval(int retryInterval); /** * Sets how many times to keep retrying a host before marking it as down. */ void setMaxConsecutiveFailures(int maxConsecutiveFailures); /** * Turns randomization in connect order on or off. */ void setRandomize(bool randomize); /** * Whether to always try the last server. */ void setAlwaysTryLast(bool alwaysTryLast); /** * Creates and opens the UNIX socket. */ void open() override; /* * Closes the UNIX socket */ void close() override; protected: void setCurrentServer(const std::shared_ptr& server); /** List of servers to connect to */ std::vector > servers_; /** Current server */ std::shared_ptr currentServer_; /** How many times to retry each host in connect */ int numRetries_; /** Retry interval in seconds, how long to not try a host if it has been * marked as down. */ time_t retryInterval_; /** Max consecutive failures before marking a host down. */ int maxConsecutiveFailures_; /** Try hosts in order? or Randomized? */ bool randomize_; /** Always try last host, even if marked down? */ bool alwaysTryLast_; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TTransportUtils.h0000644000000000000000000002253314303740367024100 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ #define _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ 1 #include #include #include #include #include // Include the buffered transports that used to be defined here. #include #include namespace apache { namespace thrift { namespace transport { /** * The null transport is a dummy transport that doesn't actually do anything. * It's sort of an analogy to /dev/null, you can never read anything from it * and it will let you write anything you want to it, though it won't actually * go anywhere. * */ class TNullTransport : public TVirtualTransport { public: TNullTransport() = default; ~TNullTransport() override = default; bool isOpen() const override { return true; } void open() override {} void write(const uint8_t* /* buf */, uint32_t /* len */) { return; } }; /** * TPipedTransport. This transport allows piping of a request from one * transport to another either when readEnd() or writeEnd(). The typical * use case for this is to log a request or a reply to disk. * The underlying buffer expands to a keep a copy of the entire * request/response. * */ class TPipedTransport : virtual public TTransport { public: TPipedTransport(std::shared_ptr srcTrans, std::shared_ptr dstTrans, std::shared_ptr config = nullptr) : TTransport(config), srcTrans_(srcTrans), dstTrans_(dstTrans), rBufSize_(512), rPos_(0), rLen_(0), wBufSize_(512), wLen_(0) { // default is to to pipe the request when readEnd() is called pipeOnRead_ = true; pipeOnWrite_ = false; rBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * rBufSize_); if (rBuf_ == nullptr) { throw std::bad_alloc(); } wBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * wBufSize_); if (wBuf_ == nullptr) { throw std::bad_alloc(); } } TPipedTransport(std::shared_ptr srcTrans, std::shared_ptr dstTrans, uint32_t sz, std::shared_ptr config = nullptr) : TTransport(config), srcTrans_(srcTrans), dstTrans_(dstTrans), rBufSize_(512), rPos_(0), rLen_(0), wBufSize_(sz), wLen_(0) { rBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * rBufSize_); if (rBuf_ == nullptr) { throw std::bad_alloc(); } wBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * wBufSize_); if (wBuf_ == nullptr) { throw std::bad_alloc(); } } ~TPipedTransport() override { std::free(rBuf_); std::free(wBuf_); } bool isOpen() const override { return srcTrans_->isOpen(); } bool peek() override { if (rPos_ >= rLen_) { // Double the size of the underlying buffer if it is full if (rLen_ == rBufSize_) { rBufSize_ *= 2; auto * tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); if (tmpBuf == nullptr) { throw std::bad_alloc(); } rBuf_ = tmpBuf; } // try to fill up the buffer rLen_ += srcTrans_->read(rBuf_ + rPos_, rBufSize_ - rPos_); } return (rLen_ > rPos_); } void open() override { srcTrans_->open(); } void close() override { srcTrans_->close(); } void setPipeOnRead(bool pipeVal) { pipeOnRead_ = pipeVal; } void setPipeOnWrite(bool pipeVal) { pipeOnWrite_ = pipeVal; } uint32_t read(uint8_t* buf, uint32_t len); uint32_t readEnd() override { if (pipeOnRead_) { dstTrans_->write(rBuf_, rPos_); dstTrans_->flush(); } srcTrans_->readEnd(); // If requests are being pipelined, copy down our read-ahead data, // then reset our state. int read_ahead = rLen_ - rPos_; uint32_t bytes = rPos_; memcpy(rBuf_, rBuf_ + rPos_, read_ahead); rPos_ = 0; rLen_ = read_ahead; return bytes; } void write(const uint8_t* buf, uint32_t len); uint32_t writeEnd() override { if (pipeOnWrite_) { dstTrans_->write(wBuf_, wLen_); dstTrans_->flush(); } return wLen_; } void flush() override; std::shared_ptr getTargetTransport() { return dstTrans_; } /* * Override TTransport *_virt() functions to invoke our implementations. * We cannot use TVirtualTransport to provide these, since we need to inherit * virtually from TTransport. */ uint32_t read_virt(uint8_t* buf, uint32_t len) override { return this->read(buf, len); } void write_virt(const uint8_t* buf, uint32_t len) override { this->write(buf, len); } protected: std::shared_ptr srcTrans_; std::shared_ptr dstTrans_; uint8_t* rBuf_; uint32_t rBufSize_; uint32_t rPos_; uint32_t rLen_; uint8_t* wBuf_; uint32_t wBufSize_; uint32_t wLen_; bool pipeOnRead_; bool pipeOnWrite_; }; /** * Wraps a transport into a pipedTransport instance. * */ class TPipedTransportFactory : public TTransportFactory { public: TPipedTransportFactory() = default; TPipedTransportFactory(std::shared_ptr dstTrans) { initializeTargetTransport(dstTrans); } ~TPipedTransportFactory() override = default; /** * Wraps the base transport into a piped transport. */ std::shared_ptr getTransport(std::shared_ptr srcTrans) override { return std::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); } virtual void initializeTargetTransport(std::shared_ptr dstTrans) { if (dstTrans_.get() == nullptr) { dstTrans_ = dstTrans; } else { throw TException("Target transport already initialized"); } } protected: std::shared_ptr dstTrans_; }; /** * TPipedFileTransport. This is just like a TTransport, except that * it is a templatized class, so that clients who rely on a specific * TTransport can still access the original transport. * */ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTransport { public: TPipedFileReaderTransport(std::shared_ptr srcTrans, std::shared_ptr dstTrans, std::shared_ptr config = nullptr); ~TPipedFileReaderTransport() override; // TTransport functions bool isOpen() const override; bool peek() override; void open() override; void close() override; uint32_t read(uint8_t* buf, uint32_t len); uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t readEnd() override; void write(const uint8_t* buf, uint32_t len); uint32_t writeEnd() override; void flush() override; // TFileReaderTransport functions int32_t getReadTimeout() override; void setReadTimeout(int32_t readTimeout) override; uint32_t getNumChunks() override; uint32_t getCurChunk() override; void seekToChunk(int32_t chunk) override; void seekToEnd() override; /* * Override TTransport *_virt() functions to invoke our implementations. * We cannot use TVirtualTransport to provide these, since we need to inherit * virtually from TTransport. */ uint32_t read_virt(uint8_t* buf, uint32_t len) override { return this->read(buf, len); } uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { return this->readAll(buf, len); } void write_virt(const uint8_t* buf, uint32_t len) override { this->write(buf, len); } protected: // shouldn't be used TPipedFileReaderTransport(); std::shared_ptr srcTrans_; }; /** * Creates a TPipedFileReaderTransport from a filepath and a destination transport * */ class TPipedFileReaderTransportFactory : public TPipedTransportFactory { public: TPipedFileReaderTransportFactory() = default; TPipedFileReaderTransportFactory(std::shared_ptr dstTrans) : TPipedTransportFactory(dstTrans) {} ~TPipedFileReaderTransportFactory() override = default; std::shared_ptr getTransport(std::shared_ptr srcTrans) override { std::shared_ptr pFileReaderTransport = std::dynamic_pointer_cast(srcTrans); if (pFileReaderTransport.get() != nullptr) { return getFileReaderTransport(pFileReaderTransport); } else { return std::shared_ptr(); } } std::shared_ptr getFileReaderTransport( std::shared_ptr srcTrans) { return std::shared_ptr( new TPipedFileReaderTransport(srcTrans, dstTrans_)); } }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TFileTransport.cpp0000644000000000000000000010001214370300523024165 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #ifdef HAVE_SYS_TIME_H #include #else #include #endif #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #include #include #include #include #include #ifdef HAVE_SYS_STAT_H #include #endif #ifdef _WIN32 #include #endif #include #include #include #include namespace apache { namespace thrift { namespace transport { using std::shared_ptr; using std::cerr; using std::cout; using std::endl; using std::string; using namespace apache::thrift::protocol; using namespace apache::thrift::concurrency; TFileTransport::TFileTransport(string path, bool readOnly, std::shared_ptr config) : TTransport(config), readState_(), readBuff_(nullptr), currentEvent_(nullptr), readBuffSize_(DEFAULT_READ_BUFF_SIZE), readTimeout_(NO_TAIL_READ_TIMEOUT), chunkSize_(DEFAULT_CHUNK_SIZE), eventBufferSize_(DEFAULT_EVENT_BUFFER_SIZE), flushMaxUs_(DEFAULT_FLUSH_MAX_US), flushMaxBytes_(DEFAULT_FLUSH_MAX_BYTES), maxEventSize_(DEFAULT_MAX_EVENT_SIZE), maxCorruptedEvents_(DEFAULT_MAX_CORRUPTED_EVENTS), eofSleepTime_(DEFAULT_EOF_SLEEP_TIME_US), corruptedEventSleepTime_(DEFAULT_CORRUPTED_SLEEP_TIME_US), writerThreadIOErrorSleepTime_(DEFAULT_WRITER_THREAD_SLEEP_TIME_US), dequeueBuffer_(nullptr), enqueueBuffer_(nullptr), notFull_(&mutex_), notEmpty_(&mutex_), closing_(false), flushed_(&mutex_), forceFlush_(false), filename_(path), fd_(0), bufferAndThreadInitialized_(false), offset_(0), lastBadChunk_(0), numCorruptedEventsInChunk_(0), readOnly_(readOnly) { threadFactory_.setDetached(false); openLogFile(); } void TFileTransport::resetOutputFile(int fd, string filename, off_t offset) { filename_ = filename; offset_ = offset; // check if current file is still open if (fd_ > 0) { // flush any events in the queue flush(); GlobalOutput.printf("error, current file (%s) not closed", filename_.c_str()); if (-1 == ::THRIFT_CLOSE(fd_)) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: resetOutputFile() ::close() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "TFileTransport: error in file close", errno_copy); } else { // successfully closed fd fd_ = 0; } } if (fd) { fd_ = fd; } else { // open file if the input fd is 0 openLogFile(); } } TFileTransport::~TFileTransport() { // flush the buffer if a writer thread is active if (writerThread_.get()) { // set state to closing closing_ = true; // wake up the writer thread // Since closing_ is true, it will attempt to flush all data, then exit. notEmpty_.notify(); writerThread_->join(); writerThread_.reset(); } if (dequeueBuffer_) { delete dequeueBuffer_; dequeueBuffer_ = nullptr; } if (enqueueBuffer_) { delete enqueueBuffer_; enqueueBuffer_ = nullptr; } if (readBuff_) { delete[] readBuff_; readBuff_ = nullptr; } if (currentEvent_) { delete currentEvent_; currentEvent_ = nullptr; } // close logfile if (fd_ > 0) { if (-1 == ::THRIFT_CLOSE(fd_)) { GlobalOutput.perror("TFileTransport: ~TFileTransport() ::close() ", THRIFT_ERRNO); } else { // successfully closed fd fd_ = 0; } } } bool TFileTransport::initBufferAndWriteThread() { if (bufferAndThreadInitialized_) { T_ERROR("%s", "Trying to double-init TFileTransport"); return false; } if (!writerThread_.get()) { writerThread_ = threadFactory_.newThread( apache::thrift::concurrency::FunctionRunner::create(startWriterThread, this)); writerThread_->start(); } dequeueBuffer_ = new TFileTransportBuffer(eventBufferSize_); enqueueBuffer_ = new TFileTransportBuffer(eventBufferSize_); bufferAndThreadInitialized_ = true; return true; } void TFileTransport::write(const uint8_t* buf, uint32_t len) { if (readOnly_) { throw TTransportException("TFileTransport: attempting to write to file opened readonly"); } enqueueEvent(buf, len); } template struct uniqueDeleter { void operator()(_T *ptr) const { delete ptr; } }; void TFileTransport::enqueueEvent(const uint8_t* buf, uint32_t eventLen) { // can't enqueue more events if file is going to close if (closing_) { return; } // make sure that event size is valid if ((maxEventSize_ > 0) && (eventLen > maxEventSize_)) { T_ERROR("msg size is greater than max event size: %u > %u\n", eventLen, maxEventSize_); return; } if (eventLen == 0) { T_ERROR("%s", "cannot enqueue an empty event"); return; } std::unique_ptr > toEnqueue(new eventInfo()); toEnqueue->eventBuff_ = new uint8_t[(sizeof(uint8_t) * eventLen) + 4]; // first 4 bytes is the event length memcpy(toEnqueue->eventBuff_, (void*)(&eventLen), 4); // actual event contents memcpy(toEnqueue->eventBuff_ + 4, buf, eventLen); toEnqueue->eventSize_ = eventLen + 4; // lock mutex Guard g(mutex_); // make sure that enqueue buffer is initialized and writer thread is running if (!bufferAndThreadInitialized_) { if (!initBufferAndWriteThread()) { return; } } // Can't enqueue while buffer is full while (enqueueBuffer_->isFull()) { notFull_.wait(); } // We shouldn't be trying to enqueue new data while a forced flush is // requested. (Otherwise the writer thread might not ever be able to finish // the flush if more data keeps being enqueued.) assert(!forceFlush_); // add to the buffer eventInfo* pEvent = toEnqueue.release(); if (!enqueueBuffer_->addEvent(pEvent)) { delete pEvent; return; } // signal anybody who's waiting for the buffer to be non-empty notEmpty_.notify(); // this really should be a loop where it makes sure it got flushed // because condition variables can get triggered by the os for no reason // it is probably a non-factor for the time being } bool TFileTransport::swapEventBuffers(const std::chrono::time_point *deadline) { bool swap; Guard g(mutex_); if (!enqueueBuffer_->isEmpty()) { swap = true; } else if (closing_) { // even though there is no data to write, // return immediately if the transport is closing swap = false; } else { if (deadline != nullptr) { // if we were handed a deadline time struct, do a timed wait notEmpty_.waitForTime(*deadline); } else { // just wait until the buffer gets an item notEmpty_.wait(); } // could be empty if we timed out swap = enqueueBuffer_->isEmpty(); } if (swap) { TFileTransportBuffer* temp = enqueueBuffer_; enqueueBuffer_ = dequeueBuffer_; dequeueBuffer_ = temp; } if (swap) { notFull_.notify(); } return swap; } void TFileTransport::writerThread() { bool hasIOError = false; // open file if it is not open if (!fd_) { try { openLogFile(); } catch (...) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() openLogFile() ", errno_copy); fd_ = 0; hasIOError = true; } } // set the offset to the correct value (EOF) if (!hasIOError) { try { seekToEnd(); // throw away any partial events offset_ += readState_.lastDispatchPtr_; if (0 == THRIFT_FTRUNCATE(fd_, offset_)) { readState_.resetAllValues(); } else { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() truncate ", errno_copy); hasIOError = true; } } catch (...) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() initialization ", errno_copy); hasIOError = true; } } // Figure out the next time by which a flush must take place auto ts_next_flush = getNextFlushTime(); uint32_t unflushed = 0; while (1) { // this will only be true when the destructor is being invoked if (closing_) { if (hasIOError) { return; } // Try to empty buffers before exit if (enqueueBuffer_->isEmpty() && dequeueBuffer_->isEmpty()) { ::THRIFT_FSYNC(fd_); if (-1 == ::THRIFT_CLOSE(fd_)) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() ::close() ", errno_copy); } else { // fd successfully closed fd_ = 0; } return; } } if (swapEventBuffers(&ts_next_flush)) { eventInfo* outEvent; while (nullptr != (outEvent = dequeueBuffer_->getNext())) { // Remove an event from the buffer and write it out to disk. If there is any IO error, for // instance, // the output file is unmounted or deleted, then this event is dropped. However, the writer // thread // will: (1) sleep for a short while; (2) try to reopen the file; (3) if successful then // start writing // from the end. while (hasIOError) { T_ERROR( "TFileTransport: writer thread going to sleep for %u microseconds due to IO errors", writerThreadIOErrorSleepTime_); THRIFT_SLEEP_USEC(writerThreadIOErrorSleepTime_); if (closing_) { return; } if (!fd_) { ::THRIFT_CLOSE(fd_); fd_ = 0; } try { openLogFile(); seekToEnd(); unflushed = 0; hasIOError = false; T_LOG_OPER( "TFileTransport: log file %s reopened by writer thread during error recovery", filename_.c_str()); } catch (...) { T_ERROR("TFileTransport: unable to reopen log file %s during error recovery", filename_.c_str()); } } // sanity check on event if ((maxEventSize_ > 0) && (outEvent->eventSize_ > maxEventSize_)) { T_ERROR("msg size is greater than max event size: %u > %u\n", outEvent->eventSize_, maxEventSize_); continue; } // If chunking is required, then make sure that msg does not cross chunk boundary if ((outEvent->eventSize_ > 0) && (chunkSize_ != 0)) { // event size must be less than chunk size if (outEvent->eventSize_ > chunkSize_) { T_ERROR("TFileTransport: event size(%u) > chunk size(%u): skipping event", outEvent->eventSize_, chunkSize_); continue; } int64_t chunk1 = offset_ / chunkSize_; int64_t chunk2 = (offset_ + outEvent->eventSize_ - 1) / chunkSize_; // if adding this event will cross a chunk boundary, pad the chunk with zeros if (chunk1 != chunk2) { // refetch the offset to keep in sync offset_ = THRIFT_LSEEK(fd_, 0, SEEK_CUR); auto padding = (int32_t)((offset_ / chunkSize_ + 1) * chunkSize_ - offset_); auto* zeros = new uint8_t[padding]; memset(zeros, '\0', padding); std::unique_ptr array(zeros); if (-1 == ::THRIFT_WRITE(fd_, zeros, padding)) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() error while padding zeros ", errno_copy); hasIOError = true; continue; } unflushed += padding; offset_ += padding; } } // write the dequeued event to the file if (outEvent->eventSize_ > 0) { if (-1 == ::THRIFT_WRITE(fd_, outEvent->eventBuff_, outEvent->eventSize_)) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: error while writing event ", errno_copy); hasIOError = true; continue; } unflushed += outEvent->eventSize_; offset_ += outEvent->eventSize_; } } dequeueBuffer_->reset(); } if (hasIOError) { continue; } // Local variable to cache the state of forceFlush_. // // We only want to check the value of forceFlush_ once each time around the // loop. If we check it more than once without holding the lock the entire // time, it could have changed state in between. This will result in us // making inconsistent decisions. bool forced_flush = false; { Guard g(mutex_); if (forceFlush_) { if (!enqueueBuffer_->isEmpty()) { // If forceFlush_ is true, we need to flush all available data. // If enqueueBuffer_ is not empty, go back to the start of the loop to // write it out. // // We know the main thread is waiting on forceFlush_ to be cleared, // so no new events will be added to enqueueBuffer_ until we clear // forceFlush_. Therefore the next time around the loop enqueueBuffer_ // is guaranteed to be empty. (I.e., we're guaranteed to make progress // and clear forceFlush_ the next time around the loop.) continue; } forced_flush = true; } } // determine if we need to perform an fsync bool flush = false; if (forced_flush || unflushed > flushMaxBytes_) { flush = true; } else { if (std::chrono::steady_clock::now() > ts_next_flush) { if (unflushed > 0) { flush = true; } else { // If there is no new data since the last fsync, // don't perform the fsync, but do reset the timer. ts_next_flush = getNextFlushTime(); } } } if (flush) { // sync (force flush) file to disk THRIFT_FSYNC(fd_); unflushed = 0; ts_next_flush = getNextFlushTime(); // notify anybody waiting for flush completion if (forced_flush) { Guard g(mutex_); forceFlush_ = false; assert(enqueueBuffer_->isEmpty()); assert(dequeueBuffer_->isEmpty()); flushed_.notifyAll(); } } } } void TFileTransport::flush() { resetConsumedMessageSize(); // file must be open for writing for any flushing to take place if (!writerThread_.get()) { return; } // wait for flush to take place Guard g(mutex_); // Indicate that we are requesting a flush forceFlush_ = true; // Wake up the writer thread so it will perform the flush immediately notEmpty_.notify(); while (forceFlush_) { flushed_.wait(); } } uint32_t TFileTransport::readAll(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); uint32_t have = 0; uint32_t get = 0; while (have < len) { get = read(buf + have, len - have); if (get <= 0) { throw TEOFException(); } have += get; } return have; } bool TFileTransport::peek() { // check if there is an event ready to be read if (!currentEvent_) { currentEvent_ = readEvent(); } // did not manage to read an event from the file. This could have happened // if the timeout expired or there was some other error if (!currentEvent_) { return false; } // check if there is anything to read return (currentEvent_->eventSize_ - currentEvent_->eventBuffPos_) > 0; } uint32_t TFileTransport::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); // check if there an event is ready to be read if (!currentEvent_) { currentEvent_ = readEvent(); } // did not manage to read an event from the file. This could have happened // if the timeout expired or there was some other error if (!currentEvent_) { return 0; } // read as much of the current event as possible int32_t remaining = currentEvent_->eventSize_ - currentEvent_->eventBuffPos_; if (remaining <= (int32_t)len) { // copy over anything thats remaining if (remaining > 0) { memcpy(buf, currentEvent_->eventBuff_ + currentEvent_->eventBuffPos_, remaining); } delete (currentEvent_); currentEvent_ = nullptr; return remaining; } // read as much as possible memcpy(buf, currentEvent_->eventBuff_ + currentEvent_->eventBuffPos_, len); currentEvent_->eventBuffPos_ += len; return len; } // note caller is responsible for freeing returned events eventInfo* TFileTransport::readEvent() { int readTries = 0; if (!readBuff_) { readBuff_ = new uint8_t[readBuffSize_]; } while (1) { // read from the file if read buffer is exhausted if (readState_.bufferPtr_ == readState_.bufferLen_) { // advance the offset pointer offset_ += readState_.bufferLen_; readState_.bufferLen_ = static_cast(::THRIFT_READ(fd_, readBuff_, readBuffSize_)); // if (readState_.bufferLen_) { // T_DEBUG_L(1, "Amount read: %u (offset: %lu)", readState_.bufferLen_, offset_); // } readState_.bufferPtr_ = 0; readState_.lastDispatchPtr_ = 0; // read error if (readState_.bufferLen_ == -1) { readState_.resetAllValues(); GlobalOutput("TFileTransport: error while reading from file"); throw TTransportException("TFileTransport: error while reading from file"); } else if (readState_.bufferLen_ == 0) { // EOF // wait indefinitely if there is no timeout if (readTimeout_ == TAIL_READ_TIMEOUT) { THRIFT_SLEEP_USEC(eofSleepTime_); continue; } else if (readTimeout_ == NO_TAIL_READ_TIMEOUT) { // reset state readState_.resetState(0); return nullptr; } else if (readTimeout_ > 0) { // timeout already expired once if (readTries > 0) { readState_.resetState(0); return nullptr; } else { THRIFT_SLEEP_USEC(readTimeout_ * 1000); readTries++; continue; } } } } readTries = 0; // attempt to read an event from the buffer while (readState_.bufferPtr_ < readState_.bufferLen_) { if (readState_.readingSize_) { if (readState_.eventSizeBuffPos_ == 0) { if ((offset_ + readState_.bufferPtr_) / chunkSize_ != ((offset_ + readState_.bufferPtr_ + 3) / chunkSize_)) { // skip one byte towards chunk boundary // T_DEBUG_L(1, "Skipping a byte"); readState_.bufferPtr_++; continue; } } readState_.eventSizeBuff_[readState_.eventSizeBuffPos_++] = readBuff_[readState_.bufferPtr_++]; if (readState_.eventSizeBuffPos_ == 4) { if (readState_.getEventSize() == 0) { // 0 length event indicates padding // T_DEBUG_L(1, "Got padding"); readState_.resetState(readState_.lastDispatchPtr_); continue; } // got a valid event readState_.readingSize_ = false; if (readState_.event_) { delete (readState_.event_); } readState_.event_ = new eventInfo(); readState_.event_->eventSize_ = readState_.getEventSize(); // check if the event is corrupted and perform recovery if required if (isEventCorrupted()) { performRecovery(); // start from the top break; } } } else { if (!readState_.event_->eventBuff_) { readState_.event_->eventBuff_ = new uint8_t[readState_.event_->eventSize_]; readState_.event_->eventBuffPos_ = 0; } // take either the entire event or the remaining bytes in the buffer int reclaimBuffer = (std::min)((uint32_t)(readState_.bufferLen_ - readState_.bufferPtr_), readState_.event_->eventSize_ - readState_.event_->eventBuffPos_); // copy data from read buffer into event buffer memcpy(readState_.event_->eventBuff_ + readState_.event_->eventBuffPos_, readBuff_ + readState_.bufferPtr_, reclaimBuffer); // increment position ptrs readState_.event_->eventBuffPos_ += reclaimBuffer; readState_.bufferPtr_ += reclaimBuffer; // check if the event has been read in full if (readState_.event_->eventBuffPos_ == readState_.event_->eventSize_) { // set the completed event to the current event eventInfo* completeEvent = readState_.event_; completeEvent->eventBuffPos_ = 0; readState_.event_ = nullptr; readState_.resetState(readState_.bufferPtr_); // exit criteria return completeEvent; } } } } } bool TFileTransport::isEventCorrupted() { // an error is triggered if: if ((maxEventSize_ > 0) && (readState_.event_->eventSize_ > maxEventSize_)) { // 1. Event size is larger than user-speficied max-event size T_ERROR("Read corrupt event. Event size(%u) greater than max event size (%u)", readState_.event_->eventSize_, maxEventSize_); return true; } else if (readState_.event_->eventSize_ > chunkSize_) { // 2. Event size is larger than chunk size T_ERROR("Read corrupt event. Event size(%u) greater than chunk size (%u)", readState_.event_->eventSize_, chunkSize_); return true; } else if (((offset_ + readState_.bufferPtr_ - 4) / chunkSize_) != ((offset_ + readState_.bufferPtr_ + readState_.event_->eventSize_ - 1) / chunkSize_)) { // 3. size indicates that event crosses chunk boundary T_ERROR("Read corrupt event. Event crosses chunk boundary. Event size:%u Offset:%lu", readState_.event_->eventSize_, static_cast(offset_ + readState_.bufferPtr_ + 4)); return true; } return false; } void TFileTransport::performRecovery() { // perform some kickass recovery uint32_t curChunk = getCurChunk(); if (lastBadChunk_ == curChunk) { numCorruptedEventsInChunk_++; } else { lastBadChunk_ = curChunk; numCorruptedEventsInChunk_ = 1; } if (numCorruptedEventsInChunk_ < maxCorruptedEvents_) { // maybe there was an error in reading the file from disk // seek to the beginning of chunk and try again seekToChunk(curChunk); } else { // just skip ahead to the next chunk if we not already at the last chunk if (curChunk != (getNumChunks() - 1)) { seekToChunk(curChunk + 1); } else if (readTimeout_ == TAIL_READ_TIMEOUT) { // if tailing the file, wait until there is enough data to start // the next chunk while (curChunk == (getNumChunks() - 1)) { THRIFT_SLEEP_USEC(corruptedEventSleepTime_); } seekToChunk(curChunk + 1); } else { // pretty hosed at this stage, rewind the file back to the last successful // point and punt on the error readState_.resetState(readState_.lastDispatchPtr_); currentEvent_ = nullptr; char errorMsg[1024]; sprintf(errorMsg, "TFileTransport: log file corrupted at offset: %lu", static_cast(offset_ + readState_.lastDispatchPtr_)); GlobalOutput(errorMsg); throw TTransportException(errorMsg); } } } void TFileTransport::seekToChunk(int32_t chunk) { if (fd_ <= 0) { throw TTransportException("File not open"); } int32_t numChunks = getNumChunks(); // file is empty, seeking to chunk is pointless if (numChunks == 0) { return; } // negative indicates reverse seek (from the end) if (chunk < 0) { chunk += numChunks; } // too large a value for reverse seek, just seek to beginning if (chunk < 0) { T_DEBUG("%s", "Incorrect value for reverse seek. Seeking to beginning..."); chunk = 0; } // cannot seek past EOF bool seekToEnd = false; off_t minEndOffset = 0; if (chunk >= numChunks) { T_DEBUG("%s", "Trying to seek past EOF. Seeking to EOF instead..."); seekToEnd = true; chunk = numChunks - 1; // this is the min offset to process events till minEndOffset = ::THRIFT_LSEEK(fd_, 0, SEEK_END); } off_t newOffset = off_t(chunk) * chunkSize_; offset_ = ::THRIFT_LSEEK(fd_, newOffset, SEEK_SET); readState_.resetAllValues(); currentEvent_ = nullptr; if (offset_ == -1) { GlobalOutput("TFileTransport: lseek error in seekToChunk"); throw TTransportException("TFileTransport: lseek error in seekToChunk"); } // seek to EOF if user wanted to go to last chunk if (seekToEnd) { uint32_t oldReadTimeout = getReadTimeout(); setReadTimeout(NO_TAIL_READ_TIMEOUT); // keep on reading unti the last event at point of seekChunk call shared_ptr event; while ((offset_ + readState_.bufferPtr_) < minEndOffset) { event.reset(readEvent()); if (event.get() == nullptr) { break; } } setReadTimeout(oldReadTimeout); } } void TFileTransport::seekToEnd() { seekToChunk(getNumChunks()); } uint32_t TFileTransport::getNumChunks() { if (fd_ <= 0) { return 0; } struct THRIFT_STAT f_info; int rv = ::THRIFT_FSTAT(fd_, &f_info); if (rv < 0) { int errno_copy = THRIFT_ERRNO; throw TTransportException(TTransportException::UNKNOWN, "TFileTransport::getNumChunks() (fstat)", errno_copy); } if (f_info.st_size > 0) { size_t numChunks = ((f_info.st_size) / chunkSize_) + 1; if (numChunks > (std::numeric_limits::max)()) throw TTransportException("Too many chunks"); return static_cast(numChunks); } // empty file has no chunks return 0; } uint32_t TFileTransport::getCurChunk() { return static_cast(offset_ / chunkSize_); } // Utility Functions void TFileTransport::openLogFile() { #ifndef _WIN32 mode_t mode = readOnly_ ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; int flags = readOnly_ ? O_RDONLY : O_RDWR | O_CREAT | O_APPEND; #else int mode = readOnly_ ? _S_IREAD : _S_IREAD | _S_IWRITE; int flags = readOnly_ ? _O_RDONLY : _O_RDWR | _O_CREAT | _O_APPEND; #endif fd_ = ::THRIFT_OPEN(filename_.c_str(), flags, mode); offset_ = 0; // make sure open call was successful if (fd_ == -1) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: openLogFile() ::open() file: " + filename_, errno_copy); throw TTransportException(TTransportException::NOT_OPEN, filename_, errno_copy); } } std::chrono::time_point TFileTransport::getNextFlushTime() { return std::chrono::steady_clock::now() + std::chrono::microseconds(flushMaxUs_); } TFileTransportBuffer::TFileTransportBuffer(uint32_t size) : bufferMode_(WRITE), writePoint_(0), readPoint_(0), size_(size) { buffer_ = new eventInfo* [size]; } TFileTransportBuffer::~TFileTransportBuffer() { if (buffer_) { for (uint32_t i = 0; i < writePoint_; i++) { delete buffer_[i]; } delete[] buffer_; buffer_ = nullptr; } } bool TFileTransportBuffer::addEvent(eventInfo* event) { if (bufferMode_ == READ) { GlobalOutput("Trying to write to a buffer in read mode"); } if (writePoint_ < size_) { buffer_[writePoint_++] = event; return true; } else { // buffer is full return false; } } eventInfo* TFileTransportBuffer::getNext() { if (bufferMode_ == WRITE) { bufferMode_ = READ; } if (readPoint_ < writePoint_) { return buffer_[readPoint_++]; } else { // no more entries return nullptr; } } void TFileTransportBuffer::reset() { if (bufferMode_ == WRITE || writePoint_ > readPoint_) { T_DEBUG("%s", "Resetting a buffer with unread entries"); } // Clean up the old entries for (uint32_t i = 0; i < writePoint_; i++) { delete buffer_[i]; } bufferMode_ = WRITE; writePoint_ = 0; readPoint_ = 0; } bool TFileTransportBuffer::isFull() { return writePoint_ == size_; } bool TFileTransportBuffer::isEmpty() { return writePoint_ == 0; } TFileProcessor::TFileProcessor(shared_ptr processor, shared_ptr protocolFactory, shared_ptr inputTransport) : processor_(processor), inputProtocolFactory_(protocolFactory), outputProtocolFactory_(protocolFactory), inputTransport_(inputTransport) { // default the output transport to a null transport (common case) outputTransport_ = std::make_shared(); } TFileProcessor::TFileProcessor(shared_ptr processor, shared_ptr inputProtocolFactory, shared_ptr outputProtocolFactory, shared_ptr inputTransport) : processor_(processor), inputProtocolFactory_(inputProtocolFactory), outputProtocolFactory_(outputProtocolFactory), inputTransport_(inputTransport) { // default the output transport to a null transport (common case) outputTransport_ = std::make_shared(); } TFileProcessor::TFileProcessor(shared_ptr processor, shared_ptr protocolFactory, shared_ptr inputTransport, shared_ptr outputTransport) : processor_(processor), inputProtocolFactory_(protocolFactory), outputProtocolFactory_(protocolFactory), inputTransport_(inputTransport), outputTransport_(outputTransport) { } void TFileProcessor::process(uint32_t numEvents, bool tail) { shared_ptr inputProtocol = inputProtocolFactory_->getProtocol(inputTransport_); shared_ptr outputProtocol = outputProtocolFactory_->getProtocol(outputTransport_); // set the read timeout to 0 if tailing is required int32_t oldReadTimeout = inputTransport_->getReadTimeout(); if (tail) { // save old read timeout so it can be restored inputTransport_->setReadTimeout(TFileTransport::TAIL_READ_TIMEOUT); } uint32_t numProcessed = 0; while (1) { // bad form to use exceptions for flow control but there is really // no other way around it try { processor_->process(inputProtocol, outputProtocol, nullptr); numProcessed++; if ((numEvents > 0) && (numProcessed == numEvents)) { return; } } catch (TEOFException&) { if (!tail) { break; } } catch (TException& te) { cerr << te.what() << endl; break; } } // restore old read timeout if (tail) { inputTransport_->setReadTimeout(oldReadTimeout); } } void TFileProcessor::processChunk() { shared_ptr inputProtocol = inputProtocolFactory_->getProtocol(inputTransport_); shared_ptr outputProtocol = outputProtocolFactory_->getProtocol(outputTransport_); uint32_t curChunk = inputTransport_->getCurChunk(); while (1) { // bad form to use exceptions for flow control but there is really // no other way around it try { processor_->process(inputProtocol, outputProtocol, nullptr); if (curChunk != inputTransport_->getCurChunk()) { break; } } catch (TEOFException&) { break; } catch (TException& te) { cerr << te.what() << endl; break; } } } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp0000644000000000000000000005060414370300523026207 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif #ifdef HAVE_NETINET_IN_H #include #include #endif #ifdef HAVE_NETDB_H #include #endif #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #include #include #include #include #include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX #endif #ifndef SOCKOPT_CAST_T #ifndef _WIN32 #define SOCKOPT_CAST_T void #else #define SOCKOPT_CAST_T char #endif // _WIN32 #endif template inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { return reinterpret_cast(v); } template inline SOCKOPT_CAST_T* cast_sockopt(T* v) { return reinterpret_cast(v); } using std::shared_ptr; using std::string; namespace apache { namespace thrift { namespace transport { TNonblockingServerSocket::TNonblockingServerSocket(int port) : port_(port), listenPort_(port), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(0), recvTimeout_(0), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false) { } TNonblockingServerSocket::TNonblockingServerSocket(int port, int sendTimeout, int recvTimeout) : port_(port), listenPort_(port), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(sendTimeout), recvTimeout_(recvTimeout), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false) { } TNonblockingServerSocket::TNonblockingServerSocket(const string& address, int port) : port_(port), listenPort_(port), address_(address), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(0), recvTimeout_(0), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false) { } TNonblockingServerSocket::TNonblockingServerSocket(const string& path) : port_(0), listenPort_(0), path_(path), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(0), recvTimeout_(0), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false) { } TNonblockingServerSocket::~TNonblockingServerSocket() { close(); } bool TNonblockingServerSocket::isOpen() const { if (serverSocket_ == THRIFT_INVALID_SOCKET) return false; if (!listening_) return false; if (isUnixDomainSocket() && (path_[0] != '\0')) { // On some platforms the domain socket file may not be instantly // available yet, i.e. the Windows file system can be slow. Therefore // we should check that the domain socket file actually exists. #ifdef _MSC_VER // Currently there is a bug in ClangCl on Windows so the stat() call // does not work. Workaround is a Windows-specific call if file exists: DWORD const f_attrib = GetFileAttributesA(path_.c_str()); if (f_attrib == INVALID_FILE_ATTRIBUTES) { #else struct THRIFT_STAT path_info; if (::THRIFT_STAT(path_.c_str(), &path_info) < 0) { #endif const std::string vError = "TNonblockingServerSocket::isOpen(): The domain socket path '" + path_ + "' does not exist (yet)."; GlobalOutput.perror(vError.c_str(), THRIFT_GET_SOCKET_ERROR); return false; } } return true; } void TNonblockingServerSocket::setSendTimeout(int sendTimeout) { sendTimeout_ = sendTimeout; } void TNonblockingServerSocket::setRecvTimeout(int recvTimeout) { recvTimeout_ = recvTimeout; } void TNonblockingServerSocket::setAcceptBacklog(int accBacklog) { acceptBacklog_ = accBacklog; } void TNonblockingServerSocket::setRetryLimit(int retryLimit) { retryLimit_ = retryLimit; } void TNonblockingServerSocket::setRetryDelay(int retryDelay) { retryDelay_ = retryDelay; } void TNonblockingServerSocket::setTcpSendBuffer(int tcpSendBuffer) { tcpSendBuffer_ = tcpSendBuffer; } void TNonblockingServerSocket::setTcpRecvBuffer(int tcpRecvBuffer) { tcpRecvBuffer_ = tcpRecvBuffer; } void TNonblockingServerSocket::_setup_sockopts() { int one = 1; if (!isUnixDomainSocket()) { // Set THRIFT_NO_SOCKET_CACHING to prevent 2MSL delay on accept. // This does not work with Domain sockets on most platforms. And // on Windows it completely breaks the socket. Therefore do not // use this on Domain sockets. if (-1 == setsockopt(serverSocket_, SOL_SOCKET, THRIFT_NO_SOCKET_CACHING, cast_sockopt(&one), sizeof(one))) { // NOTE: SO_EXCLUSIVEADDRUSE socket option can only be used by members // of the Administrators security group on Windows XP and earlier. But // we do not target WinXP anymore so no special checks required. int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() THRIFT_NO_SOCKET_CACHING ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set THRIFT_NO_SOCKET_CACHING", errno_copy); } } // Set TCP buffer sizes if (tcpSendBuffer_ > 0) { if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_SNDBUF, cast_sockopt(&tcpSendBuffer_), sizeof(tcpSendBuffer_))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_SNDBUF", errno_copy); } } if (tcpRecvBuffer_ > 0) { if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_RCVBUF, cast_sockopt(&tcpRecvBuffer_), sizeof(tcpRecvBuffer_))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_RCVBUF", errno_copy); } } // Turn linger off, don't want to block on calls to close struct linger ling = {0, 0}; if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER, cast_sockopt(&ling), sizeof(ling))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_LINGER ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy); } // Keepalive to ensure full result flushing if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_KEEPALIVE, const_cast_sockopt(&one), sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_KEEPALIVE ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy); } #ifdef SO_NOSIGPIPE if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() SO_NOSIGPIPE", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_NOSIGPIPE", errno_copy); } #endif // Set NONBLOCK on the accept socket int flags = THRIFT_FCNTL(serverSocket_, THRIFT_F_GETFL, 0); if (flags == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() THRIFT_F_GETFL failed", errno_copy); } if (-1 == THRIFT_FCNTL(serverSocket_, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() THRIFT_FCNTL() THRIFT_O_NONBLOCK ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() THRIFT_F_SETFL THRIFT_O_NONBLOCK failed", errno_copy); } } void TNonblockingServerSocket::_setup_unixdomain_sockopts() { } void TNonblockingServerSocket::_setup_tcp_sockopts() { int one = 1; // Set TCP nodelay if available, MAC OS X Hack // See http://lists.danga.com/pipermail/memcached/2005-March/001240.html #ifndef TCP_NOPUSH // TCP Nodelay, speed over bandwidth if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY, cast_sockopt(&one), sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy); } #endif #ifdef TCP_LOW_MIN_RTO if (TSocket::getUseLowMinRto()) { if (-1 == setsockopt(s, IPPROTO_TCP, TCP_LOW_MIN_RTO, const_cast_sockopt(&one), sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() setsockopt() TCP_LOW_MIN_RTO ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy); } } #endif } // _setup_tcp_sockopts() void TNonblockingServerSocket::listen() { #ifdef _WIN32 TWinsockSingleton::create(); #endif // _WIN32 // Validate port number if (port_ < 0 || port_ > 0xFFFF) { throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid"); } // Resolve host:port strings into an iterable of struct addrinfo* AddressResolutionHelper resolved_addresses; if (!isUnixDomainSocket()) { try { resolved_addresses.resolve(address_, std::to_string(port_), SOCK_STREAM, #ifdef ANDROID AI_PASSIVE | AI_ADDRCONFIG); #else AI_PASSIVE | AI_V4MAPPED); #endif } catch (const std::system_error& e) { GlobalOutput.printf("getaddrinfo() -> %d; %s", e.code().value(), e.what()); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for server socket."); } } // we may want to try to bind more than once, since THRIFT_NO_SOCKET_CACHING doesn't // always seem to work. The client can configure the retry variables. int retries = 0; int errno_copy = 0; if (isUnixDomainSocket()) { // -- Unix Domain Socket -- // serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); if (serverSocket_ == THRIFT_INVALID_SOCKET) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() socket() ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy); } _setup_sockopts(); _setup_unixdomain_sockopts(); // Windows supports Unix domain sockets since it ships the header // HAVE_AF_UNIX_H (see https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/) #if (!defined(_WIN32) || defined(HAVE_AF_UNIX_H)) struct sockaddr_un address; socklen_t structlen = fillUnixSocketAddr(address, path_); do { if (0 == ::bind(serverSocket_, (struct sockaddr*)&address, structlen)) { break; } errno_copy = THRIFT_GET_SOCKET_ERROR; // use short circuit evaluation here to only sleep if we need to } while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0)); #else GlobalOutput.perror("TNonblockingServerSocket::open() Unix Domain socket path not supported on this version of Windows", -99); throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported"); #endif } else { // -- TCP socket -- // auto addr_iter = AddressResolutionHelper::Iter{}; // Via DNS or somehow else, single hostname can resolve into many addresses. // Results may contain perhaps a mix of IPv4 and IPv6. Here, we iterate // over what system gave us, picking the first address that works. do { if (!addr_iter) { // init + recycle over many retries addr_iter = resolved_addresses.iterate(); } auto trybind = *addr_iter++; serverSocket_ = socket(trybind->ai_family, trybind->ai_socktype, trybind->ai_protocol); if (serverSocket_ == -1) { errno_copy = THRIFT_GET_SOCKET_ERROR; continue; } _setup_sockopts(); _setup_tcp_sockopts(); #ifdef IPV6_V6ONLY if (trybind->ai_family == AF_INET6) { int zero = 0; if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, IPV6_V6ONLY, cast_sockopt(&zero), sizeof(zero))) { GlobalOutput.perror("TNonblockingServerSocket::listen() IPV6_V6ONLY ", THRIFT_GET_SOCKET_ERROR); } } #endif // #ifdef IPV6_V6ONLY if (0 == ::bind(serverSocket_, trybind->ai_addr, static_cast(trybind->ai_addrlen))) { break; } errno_copy = THRIFT_GET_SOCKET_ERROR; // use short circuit evaluation here to only sleep if we need to } while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0)); // retrieve bind info if (port_ == 0 && retries <= retryLimit_) { struct sockaddr_storage sa; socklen_t len = sizeof(sa); std::memset(&sa, 0, len); if (::getsockname(serverSocket_, reinterpret_cast(&sa), &len) < 0) { errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::getPort() getsockname() ", errno_copy); } else { if (sa.ss_family == AF_INET6) { const auto* sin = reinterpret_cast(&sa); listenPort_ = ntohs(sin->sin6_port); } else { const auto* sin = reinterpret_cast(&sa); listenPort_ = ntohs(sin->sin_port); } } } } // TCP socket // // throw error if socket still wasn't created successfully if (serverSocket_ == THRIFT_INVALID_SOCKET) { GlobalOutput.perror("TNonblockingServerSocket::listen() socket() ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy); } // throw an error if we failed to bind properly if (retries > retryLimit_) { char errbuf[1024]; if (isUnixDomainSocket()) { #ifdef _WIN32 THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TNonblockingServerSocket::listen() Could not bind to domain socket path %s, error %d", path_.c_str(), WSAGetLastError()); #else // Fixme: This does not currently handle abstract domain sockets: THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TNonblockingServerSocket::listen() Could not bind to domain socket path %s", path_.c_str()); #endif } else { THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TNonblockingServerSocket::listen() Could not bind to port %d", port_); } GlobalOutput(errbuf); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not bind", errno_copy); } if (listenCallback_) listenCallback_(serverSocket_); // Call listen if (-1 == ::listen(serverSocket_, acceptBacklog_)) { errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::listen() listen() ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy); } // The socket is now listening! listening_ = true; } int TNonblockingServerSocket::getPort() { return port_; } int TNonblockingServerSocket::getListenPort() { return listenPort_; } std::string TNonblockingServerSocket::getPath() const { return path_; } bool TNonblockingServerSocket::isUnixDomainSocket() const { return !path_.empty(); } shared_ptr TNonblockingServerSocket::acceptImpl() { if (serverSocket_ == THRIFT_INVALID_SOCKET) { throw TTransportException(TTransportException::NOT_OPEN, "TNonblockingServerSocket not listening"); } struct sockaddr_storage clientAddress; int size = sizeof(clientAddress); THRIFT_SOCKET clientSocket = ::accept(serverSocket_, (struct sockaddr*)&clientAddress, (socklen_t*)&size); if (clientSocket == THRIFT_INVALID_SOCKET) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TNonblockingServerSocket::acceptImpl() ::accept() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy); } // Explicitly set this socket to NONBLOCK mode int flags = THRIFT_FCNTL(clientSocket, THRIFT_F_GETFL, 0); if (flags == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; ::THRIFT_CLOSESOCKET(clientSocket); GlobalOutput.perror("TNonblockingServerSocket::acceptImpl() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "THRIFT_FCNTL(THRIFT_F_GETFL)", errno_copy); } if (-1 == THRIFT_FCNTL(clientSocket, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; ::THRIFT_CLOSESOCKET(clientSocket); GlobalOutput .perror("TNonblockingServerSocket::acceptImpl() THRIFT_FCNTL() THRIFT_F_SETFL ~THRIFT_O_NONBLOCK ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "THRIFT_FCNTL(THRIFT_F_SETFL)", errno_copy); } shared_ptr client = createSocket(clientSocket); client->setPath(path_); if (sendTimeout_ > 0) { client->setSendTimeout(sendTimeout_); } if (recvTimeout_ > 0) { client->setRecvTimeout(recvTimeout_); } if (keepAlive_) { client->setKeepAlive(keepAlive_); } client->setCachedAddress((sockaddr*)&clientAddress, size); if (acceptCallback_) acceptCallback_(clientSocket); return client; } shared_ptr TNonblockingServerSocket::createSocket(THRIFT_SOCKET clientSocket) { return std::make_shared(clientSocket); } void TNonblockingServerSocket::close() { if (serverSocket_ != THRIFT_INVALID_SOCKET) { shutdown(serverSocket_, THRIFT_SHUT_RDWR); ::THRIFT_CLOSESOCKET(serverSocket_); } serverSocket_ = THRIFT_INVALID_SOCKET; listening_ = false; } } // namespace transport } // namespace thrift } // namespace apache thrift-0.19.0/lib/cpp/src/thrift/transport/TFDTransport.cpp0000644000000000000000000000570614370300523023615 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #ifdef _WIN32 #include #endif #include #ifdef HAVE_UNISTD_H #include #endif #include #include using std::string; namespace apache { namespace thrift { namespace transport { void TFDTransport::close() { if (!isOpen()) { return; } int rv = ::THRIFT_CLOSE(fd_); int errno_copy = THRIFT_ERRNO; fd_ = -1; // Have to check uncaught_exception because this is called in the destructor. #ifdef __cpp_lib_uncaught_exceptions if (rv < 0 && !std::uncaught_exceptions()) { #else if (rv < 0 && !std::uncaught_exception()) { #endif throw TTransportException(TTransportException::UNKNOWN, "TFDTransport::close()", errno_copy); } } uint32_t TFDTransport::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); unsigned int maxRetries = 5; // same as the TSocket default unsigned int retries = 0; while (true) { THRIFT_SSIZET rv = ::THRIFT_READ(fd_, buf, len); if (rv < 0) { if (THRIFT_ERRNO == THRIFT_EINTR && retries < maxRetries) { // If interrupted, try again ++retries; continue; } int errno_copy = THRIFT_ERRNO; throw TTransportException(TTransportException::UNKNOWN, "TFDTransport::read()", errno_copy); } // this should be fine, since we already checked for negative values, // and ::read should only return a 32-bit value since len is 32-bit. return static_cast(rv); } } void TFDTransport::write(const uint8_t* buf, uint32_t len) { while (len > 0) { THRIFT_SSIZET rv = ::THRIFT_WRITE(fd_, buf, len); if (rv < 0) { int errno_copy = THRIFT_ERRNO; throw TTransportException(TTransportException::UNKNOWN, "TFDTransport::write()", errno_copy); } else if (rv == 0) { throw TTransportException(TTransportException::END_OF_FILE, "TFDTransport::write()"); } buf += rv; // this should be fine, as we've already checked for negative values, and //::write shouldn't return more than a uint32_t since len is a uint32_t len -= static_cast(rv); } } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TSimpleFileTransport.cpp0000644000000000000000000000353714303740367025367 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #ifdef HAVE_SYS_STAT_H #include #endif #include #ifdef _WIN32 #include #endif namespace apache { namespace thrift { namespace transport { TSimpleFileTransport::TSimpleFileTransport(const std::string& path, bool read, bool write, std::shared_ptr config) : TFDTransport(-1, TFDTransport::CLOSE_ON_DESTROY, config) { int flags = 0; if (read && write) { flags = O_RDWR; } else if (read) { flags = O_RDONLY; } else if (write) { flags = O_WRONLY; } else { throw TTransportException("Neither READ nor WRITE specified"); } if (write) { flags |= O_CREAT | O_APPEND; } #ifndef _WIN32 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; #else int mode = _S_IREAD | _S_IWRITE; #endif int fd = ::THRIFT_OPEN(path.c_str(), flags, mode); if (fd < 0) { throw TTransportException("failed to open file for writing: " + path); } setFD(fd); open(); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TTransport.h0000644000000000000000000002706114303740367023060 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ #define _THRIFT_TRANSPORT_TTRANSPORT_H_ 1 #include #include #include #include #include namespace apache { namespace thrift { namespace transport { /** * Helper template to hoist readAll implementation out of TTransport */ template uint32_t readAll(Transport_& trans, uint8_t* buf, uint32_t len) { uint32_t have = 0; uint32_t get = 0; while (have < len) { get = trans.read(buf + have, len - have); if (get <= 0) { throw TTransportException(TTransportException::END_OF_FILE, "No more data to read."); } have += get; } return have; } /** * Generic interface for a method of transporting data. A TTransport may be * capable of either reading or writing, but not necessarily both. * */ class TTransport { public: TTransport(std::shared_ptr config = nullptr) { if(config == nullptr) { configuration_ = std::shared_ptr (new TConfiguration()); } else { configuration_ = config; } resetConsumedMessageSize(); } /** * Virtual deconstructor. */ virtual ~TTransport() = default; /** * Whether this transport is open. */ virtual bool isOpen() const { return false; } /** * Tests whether there is more data to read or if the remote side is * still open. By default this is true whenever the transport is open, * but implementations should add logic to test for this condition where * possible (i.e. on a socket). * This is used by a server to check if it should listen for another * request. */ virtual bool peek() { return isOpen(); } /** * Opens the transport for communications. * * @return bool Whether the transport was successfully opened * @throws TTransportException if opening failed */ virtual void open() { throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport."); } /** * Closes the transport. */ virtual void close() { throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport."); } /** * Attempt to read up to the specified number of bytes into the string. * * @param buf Reference to the location to write the data * @param len How many bytes to read * @return How many bytes were actually read * @throws TTransportException If an error occurs */ uint32_t read(uint8_t* buf, uint32_t len) { T_VIRTUAL_CALL(); return read_virt(buf, len); } virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */) { throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot read."); } /** * Reads the given amount of data in its entirety no matter what. * * @param s Reference to location for read data * @param len How many bytes to read * @return How many bytes read, which must be equal to size * @throws TTransportException If insufficient data was read */ uint32_t readAll(uint8_t* buf, uint32_t len) { T_VIRTUAL_CALL(); return readAll_virt(buf, len); } virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { return apache::thrift::transport::readAll(*this, buf, len); } /** * Called when read is completed. * This can be over-ridden to perform a transport-specific action * e.g. logging the request to a file * * @return number of bytes read if available, 0 otherwise. */ virtual uint32_t readEnd() { // default behaviour is to do nothing return 0; } /** * Writes the string in its entirety to the buffer. * * Note: You must call flush() to ensure the data is actually written, * and available to be read back in the future. Destroying a TTransport * object does not automatically flush pending data--if you destroy a * TTransport object with written but unflushed data, that data may be * discarded. * * @param buf The data to write out * @throws TTransportException if an error occurs */ void write(const uint8_t* buf, uint32_t len) { T_VIRTUAL_CALL(); write_virt(buf, len); } virtual void write_virt(const uint8_t* /* buf */, uint32_t /* len */) { throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot write."); } /** * Called when write is completed. * This can be over-ridden to perform a transport-specific action * at the end of a request. * * @return number of bytes written if available, 0 otherwise */ virtual uint32_t writeEnd() { // default behaviour is to do nothing return 0; } /** * Flushes any pending data to be written. Typically used with buffered * transport mechanisms. * * @throws TTransportException if an error occurs */ virtual void flush() { // default behaviour is to do nothing } /** * Attempts to return a pointer to \c len bytes, possibly copied into \c buf. * Does not consume the bytes read (i.e.: a later read will return the same * data). This method is meant to support protocols that need to read * variable-length fields. They can attempt to borrow the maximum amount of * data that they will need, then consume (see next method) what they * actually use. Some transports will not support this method and others * will fail occasionally, so protocols must be prepared to use read if * borrow fails. * * @oaram buf A buffer where the data can be stored if needed. * If borrow doesn't return buf, then the contents of * buf after the call are undefined. This parameter may be * nullptr to indicate that the caller is not supplying storage, * but would like a pointer into an internal buffer, if * available. * @param len *len should initially contain the number of bytes to borrow. * If borrow succeeds, *len will contain the number of bytes * available in the returned pointer. This will be at least * what was requested, but may be more if borrow returns * a pointer to an internal buffer, rather than buf. * If borrow fails, the contents of *len are undefined. * @return If the borrow succeeds, return a pointer to the borrowed data. * This might be equal to \c buf, or it might be a pointer into * the transport's internal buffers. * @throws TTransportException if an error occurs */ const uint8_t* borrow(uint8_t* buf, uint32_t* len) { T_VIRTUAL_CALL(); return borrow_virt(buf, len); } virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) { return nullptr; } /** * Remove len bytes from the transport. This should always follow a borrow * of at least len bytes, and should always succeed. * TODO(dreiss): Is there any transport that could borrow but fail to * consume, or that would require a buffer to dump the consumed data? * * @param len How many bytes to consume * @throws TTransportException If an error occurs */ void consume(uint32_t len) { T_VIRTUAL_CALL(); consume_virt(len); } virtual void consume_virt(uint32_t /* len */) { throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot consume."); } /** * Returns the origin of the transports call. The value depends on the * transport used. An IP based transport for example will return the * IP address of the client making the request. * If the transport doesn't know the origin Unknown is returned. * * The returned value can be used in a log message for example */ virtual const std::string getOrigin() const { return "Unknown"; } std::shared_ptr getConfiguration() { return configuration_; } void setConfiguration(std::shared_ptr config) { if (config != nullptr) configuration_ = config; } /** * Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). * Will throw if we already consumed too many bytes or if the new size is larger than allowed. * * @param size real message size */ void updateKnownMessageSize(long int size) { long int consumed = knownMessageSize_ - remainingMessageSize_; resetConsumedMessageSize(size); countConsumedMessageBytes(consumed); } /** * Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data * * @param numBytes numBytes bytes of data */ void checkReadBytesAvailable(long int numBytes) { if (remainingMessageSize_ < numBytes) throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); } protected: std::shared_ptr configuration_; long int remainingMessageSize_; long int knownMessageSize_; inline long int getRemainingMessageSize() { return remainingMessageSize_; } inline void setRemainingMessageSize(long int remainingMessageSize) { remainingMessageSize_ = remainingMessageSize; } inline int getMaxMessageSize() { return configuration_->getMaxMessageSize(); } inline long int getKnownMessageSize() { return knownMessageSize_; } void setKnownMessageSize(long int knownMessageSize) { knownMessageSize_ = knownMessageSize; } /** * Resets RemainingMessageSize to the configured maximum * * @param newSize configured size */ void resetConsumedMessageSize(long newSize = -1) { // full reset if (newSize < 0) { knownMessageSize_ = getMaxMessageSize(); remainingMessageSize_ = getMaxMessageSize(); return; } // update only: message size can shrink, but not grow if (newSize > knownMessageSize_) throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); knownMessageSize_ = newSize; remainingMessageSize_ = newSize; } /** * Consumes numBytes from the RemainingMessageSize. * * @param numBytes Consumes numBytes */ void countConsumedMessageBytes(long int numBytes) { if (remainingMessageSize_ >= numBytes) { remainingMessageSize_ -= numBytes; } else { remainingMessageSize_ = 0; throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); } } }; /** * Generic factory class to make an input and output transport out of a * source transport. Commonly used inside servers to make input and output * streams out of raw clients. * */ class TTransportFactory { public: TTransportFactory() = default; virtual ~TTransportFactory() = default; /** * Default implementation does nothing, just returns the transport given. */ virtual std::shared_ptr getTransport(std::shared_ptr trans) { return trans; } }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TServerSocket.cpp0000644000000000000000000006077514370300523024035 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_SYS_POLL_H #include #endif #ifdef HAVE_NETINET_IN_H #include #include #endif #ifdef HAVE_NETDB_H #include #endif #include #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #include #include #include #include #include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX #endif #ifndef SOCKOPT_CAST_T #ifndef _WIN32 #define SOCKOPT_CAST_T void #else #define SOCKOPT_CAST_T char #endif // _WIN32 #endif #ifdef _WIN32 // Including Windows.h can conflict with Winsock2 usage, and also // adds problematic macros like min() and max(). Try to work around: #define NOMINMAX #define WIN32_LEAN_AND_MEAN #include #undef NOMINMAX #undef WIN32_LEAN_AND_MEAN #endif template inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { return reinterpret_cast(v); } template inline SOCKOPT_CAST_T* cast_sockopt(T* v) { return reinterpret_cast(v); } void destroyer_of_fine_sockets(THRIFT_SOCKET* ssock) { ::THRIFT_CLOSESOCKET(*ssock); delete ssock; } using std::shared_ptr; using std::string; namespace apache { namespace thrift { namespace transport { TServerSocket::TServerSocket(int port) : interruptableChildren_(true), port_(port), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(0), recvTimeout_(0), accTimeout_(-1), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false), interruptSockWriter_(THRIFT_INVALID_SOCKET), interruptSockReader_(THRIFT_INVALID_SOCKET), childInterruptSockWriter_(THRIFT_INVALID_SOCKET) { } TServerSocket::TServerSocket(int port, int sendTimeout, int recvTimeout) : interruptableChildren_(true), port_(port), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(sendTimeout), recvTimeout_(recvTimeout), accTimeout_(-1), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false), interruptSockWriter_(THRIFT_INVALID_SOCKET), interruptSockReader_(THRIFT_INVALID_SOCKET), childInterruptSockWriter_(THRIFT_INVALID_SOCKET) { } TServerSocket::TServerSocket(const string& address, int port) : interruptableChildren_(true), port_(port), address_(address), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(0), recvTimeout_(0), accTimeout_(-1), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false), interruptSockWriter_(THRIFT_INVALID_SOCKET), interruptSockReader_(THRIFT_INVALID_SOCKET), childInterruptSockWriter_(THRIFT_INVALID_SOCKET) { } TServerSocket::TServerSocket(const string& path) : interruptableChildren_(true), port_(0), path_(path), serverSocket_(THRIFT_INVALID_SOCKET), acceptBacklog_(DEFAULT_BACKLOG), sendTimeout_(0), recvTimeout_(0), accTimeout_(-1), retryLimit_(0), retryDelay_(0), tcpSendBuffer_(0), tcpRecvBuffer_(0), keepAlive_(false), listening_(false), interruptSockWriter_(THRIFT_INVALID_SOCKET), interruptSockReader_(THRIFT_INVALID_SOCKET), childInterruptSockWriter_(THRIFT_INVALID_SOCKET) { } TServerSocket::~TServerSocket() { close(); } bool TServerSocket::isOpen() const { if (serverSocket_ == THRIFT_INVALID_SOCKET) return false; if (!listening_) return false; if (isUnixDomainSocket() && (path_[0] != '\0')) { // On some platforms the domain socket file may not be instantly // available yet, i.e. the Windows file system can be slow. Therefore // we should check that the domain socket file actually exists. #ifdef _MSC_VER // Currently there is a bug in ClangCl on Windows so the stat() call // does not work. Workaround is a Windows-specific call if file exists: DWORD const f_attrib = GetFileAttributesA(path_.c_str()); if (f_attrib == INVALID_FILE_ATTRIBUTES) { #else struct THRIFT_STAT path_info; if (::THRIFT_STAT(path_.c_str(), &path_info) < 0) { #endif const std::string vError = "TServerSocket::isOpen(): The domain socket path '" + path_ + "' does not exist (yet)."; GlobalOutput.perror(vError.c_str(), THRIFT_GET_SOCKET_ERROR); return false; } } return true; } void TServerSocket::setSendTimeout(int sendTimeout) { sendTimeout_ = sendTimeout; } void TServerSocket::setRecvTimeout(int recvTimeout) { recvTimeout_ = recvTimeout; } void TServerSocket::setAcceptTimeout(int accTimeout) { accTimeout_ = accTimeout; } void TServerSocket::setAcceptBacklog(int accBacklog) { acceptBacklog_ = accBacklog; } void TServerSocket::setRetryLimit(int retryLimit) { retryLimit_ = retryLimit; } void TServerSocket::setRetryDelay(int retryDelay) { retryDelay_ = retryDelay; } void TServerSocket::setTcpSendBuffer(int tcpSendBuffer) { tcpSendBuffer_ = tcpSendBuffer; } void TServerSocket::setTcpRecvBuffer(int tcpRecvBuffer) { tcpRecvBuffer_ = tcpRecvBuffer; } void TServerSocket::setInterruptableChildren(bool enable) { if (listening_) { throw std::logic_error("setInterruptableChildren cannot be called after listen()"); } interruptableChildren_ = enable; } void TServerSocket::_setup_sockopts() { int one = 1; if (!isUnixDomainSocket()) { // Set THRIFT_NO_SOCKET_CACHING to prevent 2MSL delay on accept. // This does not work with Domain sockets on most platforms. And // on Windows it completely breaks the socket. Therefore do not // use this on Domain sockets. if (-1 == setsockopt(serverSocket_, SOL_SOCKET, THRIFT_NO_SOCKET_CACHING, cast_sockopt(&one), sizeof(one))) { // NOTE: SO_EXCLUSIVEADDRUSE socket option can only be used by members // of the Administrators security group on Windows XP and earlier. But // we do not target WinXP anymore so no special checks required. int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() THRIFT_NO_SOCKET_CACHING ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set THRIFT_NO_SOCKET_CACHING", errno_copy); } } // Set TCP buffer sizes if (tcpSendBuffer_ > 0) { if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_SNDBUF, cast_sockopt(&tcpSendBuffer_), sizeof(tcpSendBuffer_))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_SNDBUF", errno_copy); } } if (tcpRecvBuffer_ > 0) { if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_RCVBUF, cast_sockopt(&tcpRecvBuffer_), sizeof(tcpRecvBuffer_))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_RCVBUF", errno_copy); } } // Turn linger off, don't want to block on calls to close struct linger ling = {0, 0}; if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER, cast_sockopt(&ling), sizeof(ling))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_LINGER ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy); } #ifdef SO_NOSIGPIPE if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_NOSIGPIPE", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_NOSIGPIPE", errno_copy); } #endif // Set NONBLOCK on the accept socket int flags = THRIFT_FCNTL(serverSocket_, THRIFT_F_GETFL, 0); if (flags == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() THRIFT_F_GETFL failed", errno_copy); } if (-1 == THRIFT_FCNTL(serverSocket_, THRIFT_F_SETFL, flags | THRIFT_O_NONBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() THRIFT_FCNTL() THRIFT_O_NONBLOCK ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "THRIFT_FCNTL() THRIFT_F_SETFL THRIFT_O_NONBLOCK failed", errno_copy); } } void TServerSocket::_setup_unixdomain_sockopts() { } void TServerSocket::_setup_tcp_sockopts() { int one = 1; // Defer accept #ifdef TCP_DEFER_ACCEPT if (!isUnixDomainSocket()) { if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_DEFER_ACCEPT, &one, sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_DEFER_ACCEPT ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_DEFER_ACCEPT", errno_copy); } } #endif // #ifdef TCP_DEFER_ACCEPT // TCP Nodelay, speed over bandwidth if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY, cast_sockopt(&one), sizeof(one))) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy); } } void TServerSocket::listen() { #ifdef _WIN32 TWinsockSingleton::create(); #endif // _WIN32 THRIFT_SOCKET sv[2]; // Create the socket pair used to interrupt if (-1 == THRIFT_SOCKETPAIR(AF_LOCAL, SOCK_STREAM, 0, sv)) { GlobalOutput.perror("TServerSocket::listen() socketpair() interrupt", THRIFT_GET_SOCKET_ERROR); interruptSockWriter_ = THRIFT_INVALID_SOCKET; interruptSockReader_ = THRIFT_INVALID_SOCKET; } else { interruptSockWriter_ = sv[1]; interruptSockReader_ = sv[0]; } // Create the socket pair used to interrupt all clients if (-1 == THRIFT_SOCKETPAIR(AF_LOCAL, SOCK_STREAM, 0, sv)) { GlobalOutput.perror("TServerSocket::listen() socketpair() childInterrupt", THRIFT_GET_SOCKET_ERROR); childInterruptSockWriter_ = THRIFT_INVALID_SOCKET; pChildInterruptSockReader_.reset(); } else { childInterruptSockWriter_ = sv[1]; pChildInterruptSockReader_ = std::shared_ptr(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets); } // Validate port number if (port_ < 0 || port_ > 0xFFFF) { throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid"); } // Resolve host:port strings into an iterable of struct addrinfo* AddressResolutionHelper resolved_addresses; if (!isUnixDomainSocket()) { try { resolved_addresses.resolve(address_, std::to_string(port_), SOCK_STREAM, #ifdef ANDROID AI_PASSIVE | AI_ADDRCONFIG); #else AI_PASSIVE | AI_V4MAPPED); #endif } catch (const std::system_error& e) { GlobalOutput.printf("getaddrinfo() -> %d; %s", e.code().value(), e.what()); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for server socket."); } } // we may want to try to bind more than once, since THRIFT_NO_SOCKET_CACHING doesn't // always seem to work. The client can configure the retry variables. int retries = 0; int errno_copy = 0; if (isUnixDomainSocket()) { // -- Unix Domain Socket -- // serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); if (serverSocket_ == THRIFT_INVALID_SOCKET) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() socket() ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy); } _setup_sockopts(); _setup_unixdomain_sockopts(); // Windows supports Unix domain sockets since it ships the header // HAVE_AF_UNIX_H (see https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/) #if (!defined(_WIN32) || defined(HAVE_AF_UNIX_H)) struct sockaddr_un address; socklen_t structlen = fillUnixSocketAddr(address, path_); do { if (0 == ::bind(serverSocket_, (struct sockaddr*)&address, structlen)) { break; } errno_copy = THRIFT_GET_SOCKET_ERROR; // use short circuit evaluation here to only sleep if we need to } while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0)); #else GlobalOutput.perror("TServerSocket::open() Unix Domain socket path not supported on this version of Windows", -99); throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported"); #endif } else { // -- TCP socket -- // auto addr_iter = AddressResolutionHelper::Iter{}; // Via DNS or somehow else, single hostname can resolve into many addresses. // Results may contain perhaps a mix of IPv4 and IPv6. Here, we iterate // over what system gave us, picking the first address that works. do { if (!addr_iter) { // init + recycle over many retries addr_iter = resolved_addresses.iterate(); } auto trybind = *addr_iter++; serverSocket_ = socket(trybind->ai_family, trybind->ai_socktype, trybind->ai_protocol); if (serverSocket_ == -1) { errno_copy = THRIFT_GET_SOCKET_ERROR; continue; } _setup_sockopts(); _setup_tcp_sockopts(); #ifdef IPV6_V6ONLY if (trybind->ai_family == AF_INET6) { int zero = 0; if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, IPV6_V6ONLY, cast_sockopt(&zero), sizeof(zero))) { GlobalOutput.perror("TServerSocket::listen() IPV6_V6ONLY ", THRIFT_GET_SOCKET_ERROR); } } #endif // #ifdef IPV6_V6ONLY if (0 == ::bind(serverSocket_, trybind->ai_addr, static_cast(trybind->ai_addrlen))) { break; } errno_copy = THRIFT_GET_SOCKET_ERROR; // use short circuit evaluation here to only sleep if we need to } while ((retries++ < retryLimit_) && (THRIFT_SLEEP_SEC(retryDelay_) == 0)); // retrieve bind info if (port_ == 0 && retries <= retryLimit_) { struct sockaddr_storage sa; socklen_t len = sizeof(sa); std::memset(&sa, 0, len); if (::getsockname(serverSocket_, reinterpret_cast(&sa), &len) < 0) { errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::getPort() getsockname() ", errno_copy); } else { if (sa.ss_family == AF_INET6) { const auto* sin = reinterpret_cast(&sa); port_ = ntohs(sin->sin6_port); } else { const auto* sin = reinterpret_cast(&sa); port_ = ntohs(sin->sin_port); } } } } // TCP socket // // throw error if socket still wasn't created successfully if (serverSocket_ == THRIFT_INVALID_SOCKET) { GlobalOutput.perror("TServerSocket::listen() socket() ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy); } // throw an error if we failed to bind properly if (retries > retryLimit_) { char errbuf[1024]; if (isUnixDomainSocket()) { #ifdef _WIN32 THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() Could not bind to domain socket path %s, error %d", path_.c_str(), WSAGetLastError()); #else // Fixme: This does not currently handle abstract domain sockets: THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() Could not bind to domain socket path %s", path_.c_str()); #endif } else { THRIFT_SNPRINTF(errbuf, sizeof(errbuf), "TServerSocket::listen() Could not bind to port %d", port_); } GlobalOutput(errbuf); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not bind", errno_copy); } if (listenCallback_) listenCallback_(serverSocket_); // Call listen if (-1 == ::listen(serverSocket_, acceptBacklog_)) { errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::listen() listen() ", errno_copy); close(); throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy); } // The socket is now listening! listening_ = true; } int TServerSocket::getPort() const { return port_; } std::string TServerSocket::getPath() const { return path_; } bool TServerSocket::isUnixDomainSocket() const { return !path_.empty(); } shared_ptr TServerSocket::acceptImpl() { if (serverSocket_ == THRIFT_INVALID_SOCKET) { throw TTransportException(TTransportException::NOT_OPEN, "TServerSocket not listening"); } struct THRIFT_POLLFD fds[2]; int maxEintrs = 5; int numEintrs = 0; while (true) { std::memset(fds, 0, sizeof(fds)); fds[0].fd = serverSocket_; fds[0].events = THRIFT_POLLIN; if (interruptSockReader_ != THRIFT_INVALID_SOCKET) { fds[1].fd = interruptSockReader_; fds[1].events = THRIFT_POLLIN; } /* TODO: if THRIFT_EINTR is received, we'll restart the timeout. To be accurate, we need to fix this in the future. */ int ret = THRIFT_POLL(fds, 2, accTimeout_); if (ret < 0) { // error cases if (THRIFT_GET_SOCKET_ERROR == THRIFT_EINTR && (numEintrs++ < maxEintrs)) { // THRIFT_EINTR needs to be handled manually and we can tolerate // a certain number continue; } int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::acceptImpl() THRIFT_POLL() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); } else if (ret > 0) { // Check for an interrupt signal if (interruptSockReader_ != THRIFT_INVALID_SOCKET && (fds[1].revents & THRIFT_POLLIN)) { int8_t buf; if (-1 == recv(interruptSockReader_, cast_sockopt(&buf), sizeof(int8_t), 0)) { GlobalOutput.perror("TServerSocket::acceptImpl() recv() interrupt ", THRIFT_GET_SOCKET_ERROR); } throw TTransportException(TTransportException::INTERRUPTED); } // Check for the actual server socket being ready if (fds[0].revents & THRIFT_POLLIN) { break; } } else { GlobalOutput("TServerSocket::acceptImpl() THRIFT_POLL 0"); throw TTransportException(TTransportException::UNKNOWN); } } struct sockaddr_storage clientAddress; int size = sizeof(clientAddress); THRIFT_SOCKET clientSocket = ::accept(serverSocket_, (struct sockaddr*)&clientAddress, (socklen_t*)&size); if (clientSocket == THRIFT_INVALID_SOCKET) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TServerSocket::acceptImpl() ::accept() ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy); } // Make sure client socket is blocking int flags = THRIFT_FCNTL(clientSocket, THRIFT_F_GETFL, 0); if (flags == -1) { int errno_copy = THRIFT_GET_SOCKET_ERROR; ::THRIFT_CLOSESOCKET(clientSocket); GlobalOutput.perror("TServerSocket::acceptImpl() THRIFT_FCNTL() THRIFT_F_GETFL ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "THRIFT_FCNTL(THRIFT_F_GETFL)", errno_copy); } if (-1 == THRIFT_FCNTL(clientSocket, THRIFT_F_SETFL, flags & ~THRIFT_O_NONBLOCK)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; ::THRIFT_CLOSESOCKET(clientSocket); GlobalOutput .perror("TServerSocket::acceptImpl() THRIFT_FCNTL() THRIFT_F_SETFL ~THRIFT_O_NONBLOCK ", errno_copy); throw TTransportException(TTransportException::UNKNOWN, "THRIFT_FCNTL(THRIFT_F_SETFL)", errno_copy); } shared_ptr client = createSocket(clientSocket); client->setPath(path_); if (sendTimeout_ > 0) { client->setSendTimeout(sendTimeout_); } if (recvTimeout_ > 0) { client->setRecvTimeout(recvTimeout_); } if (keepAlive_) { client->setKeepAlive(keepAlive_); } client->setCachedAddress((sockaddr*)&clientAddress, size); if (acceptCallback_) acceptCallback_(clientSocket); return client; } shared_ptr TServerSocket::createSocket(THRIFT_SOCKET clientSocket) { if (interruptableChildren_) { return std::make_shared(clientSocket, pChildInterruptSockReader_); } else { return std::make_shared(clientSocket); } } void TServerSocket::notify(THRIFT_SOCKET notifySocket) { if (notifySocket != THRIFT_INVALID_SOCKET) { int8_t byte = 0; if (-1 == send(notifySocket, cast_sockopt(&byte), sizeof(int8_t), 0)) { GlobalOutput.perror("TServerSocket::notify() send() ", THRIFT_GET_SOCKET_ERROR); } } } void TServerSocket::interrupt() { concurrency::Guard g(rwMutex_); if (interruptSockWriter_ != THRIFT_INVALID_SOCKET) { notify(interruptSockWriter_); } } void TServerSocket::interruptChildren() { concurrency::Guard g(rwMutex_); if (childInterruptSockWriter_ != THRIFT_INVALID_SOCKET) { notify(childInterruptSockWriter_); } } void TServerSocket::close() { concurrency::Guard g(rwMutex_); if (serverSocket_ != THRIFT_INVALID_SOCKET) { shutdown(serverSocket_, THRIFT_SHUT_RDWR); ::THRIFT_CLOSESOCKET(serverSocket_); } if (interruptSockWriter_ != THRIFT_INVALID_SOCKET) { ::THRIFT_CLOSESOCKET(interruptSockWriter_); } if (interruptSockReader_ != THRIFT_INVALID_SOCKET) { ::THRIFT_CLOSESOCKET(interruptSockReader_); } if (childInterruptSockWriter_ != THRIFT_INVALID_SOCKET) { ::THRIFT_CLOSESOCKET(childInterruptSockWriter_); } serverSocket_ = THRIFT_INVALID_SOCKET; interruptSockWriter_ = THRIFT_INVALID_SOCKET; interruptSockReader_ = THRIFT_INVALID_SOCKET; childInterruptSockWriter_ = THRIFT_INVALID_SOCKET; pChildInterruptSockReader_.reset(); listening_ = false; } } // namespace transport } // namespace thrift } // namespace apache thrift-0.19.0/lib/cpp/src/thrift/transport/TSocketUtils.h0000644000000000000000000001133414303740367023331 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_SOCKETUTILS_H_ #define _THRIFT_TRANSPORT_SOCKETUTILS_H_ 1 #include #include #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NETDB_H #include #endif #include namespace apache { namespace thrift { /** * A helper to resolve hostnames to struct addrinfo's -- and not leak memory. * * Use like this: * * apache::thrift::AddressResolutionHelper addresses("localhost", "80"); * * for (auto addr : addresses.iterate()) { * connect(sock, addr->ai_addr, addr->ai_addrlen); * // ... * } */ struct AddressResolutionHelper { private: struct addrinfo_deleter { void operator()(addrinfo* addr) { ::freeaddrinfo(addr); // frees the whole list } }; public: using PtrOwnedList = std::unique_ptr; struct Iter : std::iterator { value_type ptr = nullptr; Iter() = default; Iter(const addrinfo* head) : ptr(head) {} value_type operator*() const { return ptr; } bool operator==(const Iter& other) { return this->ptr == other.ptr; } bool operator!=(const Iter& other) { return this->ptr != other.ptr; } operator bool() { return this->ptr != nullptr; } bool operator!() { return this->ptr == nullptr; } Iter& operator++() { if (ptr == nullptr) { throw std::out_of_range("won't go pass end of linked list"); } ptr = ptr->ai_next; return *this; } Iter operator++(int) { Iter tmp(*this); ++(*this); return tmp; } }; struct gai_error : std::error_category { virtual const char* name() const noexcept override { return "getaddrinfo"; } virtual std::string message(int code) const override { return THRIFT_GAI_STRERROR(code); } }; private: PtrOwnedList gai_results; addrinfo* query(const std::string& host, const std::string& port, int socktype, int flags) { addrinfo hints{}; hints.ai_flags = flags; hints.ai_family = AF_UNSPEC; hints.ai_socktype = socktype; addrinfo* head; int ret = ::getaddrinfo(host.empty() ? NULL : host.c_str(), port.c_str(), &hints, &head); if (ret == 0) { return head; #ifdef _WIN32 } else { throw std::system_error{THRIFT_GET_SOCKET_ERROR, std::system_category()}; #else } else if (ret == EAI_SYSTEM) { throw std::system_error{THRIFT_GET_SOCKET_ERROR, std::system_category()}; } else { throw std::system_error{ret, gai_error()}; #endif } } public: /** * Constructor. May block. Throws errors. * * @param port Port number, or service name, as a string. * @param socktype Socket type, SOCK_STREAM or SOCK_DGRAM. * @param flags Standard getaddrinfo() flags. */ AddressResolutionHelper(const std::string& host, const std::string& port, // pass "25" or "smtp" for port 25 int socktype = SOCK_STREAM, int flags = AI_V4MAPPED | AI_ADDRCONFIG) : gai_results(query(host, port, socktype, flags)) {} AddressResolutionHelper() = default; /** * Manual query. May block. Throws errors. * * @param port Port number, or service name, as a string. * @param socktype Socket type, SOCK_STREAM or SOCK_DGRAM. * @param flags Standard getaddrinfo() flags. */ AddressResolutionHelper& resolve(const std::string& host, const std::string& port, // pass "25" or "smtp" for port 25 int socktype = SOCK_STREAM, int flags = AI_V4MAPPED | AI_ADDRCONFIG) { gai_results.reset(query(host, port, socktype, flags)); return *this; } /** * Return ForwardIterator to struct addrinfo* results. */ Iter iterate() const { return Iter{gai_results.get()}; } }; } // namespace thrift } // namespace apache #endif thrift-0.19.0/lib/cpp/src/thrift/transport/TSocketPool.cpp0000644000000000000000000001551214303740367023477 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #if __cplusplus >= 201703L #include #endif #include using std::pair; using std::string; using std::vector; namespace apache { namespace thrift { namespace transport { using std::shared_ptr; /** * TSocketPoolServer implementation * */ TSocketPoolServer::TSocketPoolServer() : host_(""), port_(0), socket_(THRIFT_INVALID_SOCKET), lastFailTime_(0), consecutiveFailures_(0) { } /** * Constructor for TSocketPool server */ TSocketPoolServer::TSocketPoolServer(const string& host, int port) : host_(host), port_(port), socket_(THRIFT_INVALID_SOCKET), lastFailTime_(0), consecutiveFailures_(0) { } /** * TSocketPool implementation. * */ TSocketPool::TSocketPool() : TSocket(), numRetries_(1), retryInterval_(60), maxConsecutiveFailures_(1), randomize_(true), alwaysTryLast_(true) { } TSocketPool::TSocketPool(const vector& hosts, const vector& ports) : TSocket(), numRetries_(1), retryInterval_(60), maxConsecutiveFailures_(1), randomize_(true), alwaysTryLast_(true) { if (hosts.size() != ports.size()) { GlobalOutput("TSocketPool::TSocketPool: hosts.size != ports.size"); throw TTransportException(TTransportException::BAD_ARGS); } for (unsigned int i = 0; i < hosts.size(); ++i) { addServer(hosts[i], ports[i]); } } TSocketPool::TSocketPool(const vector >& servers) : TSocket(), numRetries_(1), retryInterval_(60), maxConsecutiveFailures_(1), randomize_(true), alwaysTryLast_(true) { for (const auto & server : servers) { addServer(server.first, server.second); } } TSocketPool::TSocketPool(const vector >& servers) : TSocket(), servers_(servers), numRetries_(1), retryInterval_(60), maxConsecutiveFailures_(1), randomize_(true), alwaysTryLast_(true) { } TSocketPool::TSocketPool(const string& host, int port) : TSocket(), numRetries_(1), retryInterval_(60), maxConsecutiveFailures_(1), randomize_(true), alwaysTryLast_(true) { addServer(host, port); } TSocketPool::~TSocketPool() { vector >::const_iterator iter = servers_.begin(); vector >::const_iterator iterEnd = servers_.end(); for (; iter != iterEnd; ++iter) { setCurrentServer(*iter); TSocketPool::close(); } } void TSocketPool::addServer(const string& host, int port) { servers_.push_back(std::make_shared(host, port)); } void TSocketPool::addServer(shared_ptr& server) { if (server) { servers_.push_back(server); } } void TSocketPool::setServers(const vector >& servers) { servers_ = servers; } void TSocketPool::getServers(vector >& servers) { servers = servers_; } void TSocketPool::setNumRetries(int numRetries) { numRetries_ = numRetries; } void TSocketPool::setRetryInterval(int retryInterval) { retryInterval_ = retryInterval; } void TSocketPool::setMaxConsecutiveFailures(int maxConsecutiveFailures) { maxConsecutiveFailures_ = maxConsecutiveFailures; } void TSocketPool::setRandomize(bool randomize) { randomize_ = randomize; } void TSocketPool::setAlwaysTryLast(bool alwaysTryLast) { alwaysTryLast_ = alwaysTryLast; } void TSocketPool::setCurrentServer(const shared_ptr& server) { currentServer_ = server; host_ = server->host_; port_ = server->port_; socket_ = server->socket_; } /** * This function throws an exception if socket open fails. When socket * opens fails, the socket in the current server is reset. */ /* TODO: without apcu we ignore a lot of functionality from the php version */ void TSocketPool::open() { size_t numServers = servers_.size(); if (numServers == 0) { socket_ = THRIFT_INVALID_SOCKET; throw TTransportException(TTransportException::NOT_OPEN); } if (isOpen()) { return; } if (randomize_ && numServers > 1) { #if __cplusplus >= 201703L std::random_device rng; std::mt19937 urng(rng()); std::shuffle(servers_.begin(), servers_.end(), urng); #else std::random_shuffle(servers_.begin(), servers_.end()); #endif } for (size_t i = 0; i < numServers; ++i) { shared_ptr& server = servers_[i]; // Impersonate the server socket setCurrentServer(server); if (isOpen()) { // already open means we're done return; } bool retryIntervalPassed = (server->lastFailTime_ == 0); bool isLastServer = alwaysTryLast_ ? (i == (numServers - 1)) : false; if (server->lastFailTime_ > 0) { // The server was marked as down, so check if enough time has elapsed to retry time_t elapsedTime = time(nullptr) - server->lastFailTime_; if (elapsedTime > retryInterval_) { retryIntervalPassed = true; } } if (retryIntervalPassed || isLastServer) { for (int j = 0; j < numRetries_; ++j) { try { TSocket::open(); } catch (const TException &e) { string errStr = "TSocketPool::open failed " + getSocketInfo() + ": " + e.what(); GlobalOutput(errStr.c_str()); socket_ = THRIFT_INVALID_SOCKET; continue; } // Copy over the opened socket so that we can keep it persistent server->socket_ = socket_; // reset lastFailTime_ is required server->lastFailTime_ = 0; // success return; } ++server->consecutiveFailures_; if (server->consecutiveFailures_ > maxConsecutiveFailures_) { // Mark server as down server->consecutiveFailures_ = 0; server->lastFailTime_ = time(nullptr); } } } GlobalOutput("TSocketPool::open: all connections failed"); throw TTransportException(TTransportException::NOT_OPEN); } void TSocketPool::close() { TSocket::close(); if (currentServer_) { currentServer_->socket_ = THRIFT_INVALID_SOCKET; } } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/THttpClient.h0000644000000000000000000000433614303740367023142 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ #define _THRIFT_TRANSPORT_THTTPCLIENT_H_ 1 #include namespace apache { namespace thrift { namespace transport { /** * @brief Client transport using HTTP. The path is an optional field that is * not required by Thrift HTTP server or client. It can be used i.e. with HTTP * redirection, load balancing or forwarding on the server. */ class THttpClient : public THttpTransport { public: /** * @brief Constructor that wraps an existing transport, but also sets the * host and path. The host and path are not used for the connection but are * set in the HTTP header of the transport. */ THttpClient(std::shared_ptr transport, std::string host = "localhost", std::string path = "/service", std::shared_ptr config = nullptr); /** * @brief Constructor that will create a new socket transport using the host * and port. */ THttpClient(std::string host, int port, std::string path = "", std::shared_ptr config = nullptr); ~THttpClient() override; void flush() override; void setPath(std::string path); protected: std::string host_; std::string path_; void parseHeader(char* header) override; bool parseStatusLine(char* status) override; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/THttpTransport.h0000644000000000000000000000556614303740367023726 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ #define _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ 1 #include #include namespace apache { namespace thrift { namespace transport { /** * HTTP implementation of the thrift transport. This was irritating * to write, but the alternatives in C++ land are daunting. Linking CURL * requires 23 dynamic libraries last time I checked (WTF?!?). All we have * here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue, * chunked transfer encoding, keepalive, etc. Tested against Apache. */ class THttpTransport : public TVirtualTransport { public: THttpTransport(std::shared_ptr transport, std::shared_ptr config = nullptr); ~THttpTransport() override; void open() override { transport_->open(); } bool isOpen() const override { return transport_->isOpen(); } bool peek() override { return transport_->peek(); } void close() override { transport_->close(); } uint32_t read(uint8_t* buf, uint32_t len); uint32_t readEnd() override; void write(const uint8_t* buf, uint32_t len); void flush() override { resetConsumedMessageSize(); }; const std::string getOrigin() const override; protected: std::shared_ptr transport_; std::string origin_; TMemoryBuffer writeBuffer_; TMemoryBuffer readBuffer_; bool readHeaders_; bool chunked_; bool chunkedDone_; uint32_t chunkSize_; uint32_t contentLength_; char* httpBuf_; uint32_t httpPos_; uint32_t httpBufLen_; uint32_t httpBufSize_; virtual void init(); uint32_t readMoreData(); char* readLine(); void readHeaders(); virtual void parseHeader(char* header) = 0; virtual bool parseStatusLine(char* status) = 0; uint32_t readChunked(); void readChunkedFooters(); uint32_t parseChunkSize(char* line); uint32_t readContent(uint32_t size); void refill(); void shift(); static const char* CRLF; static const int CRLF_LEN; }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TTransportException.cpp0000644000000000000000000000347414303740367025274 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include using std::string; namespace apache { namespace thrift { namespace transport { const char* TTransportException::what() const noexcept { if (message_.empty()) { switch (type_) { case UNKNOWN: return "TTransportException: Unknown transport exception"; case NOT_OPEN: return "TTransportException: Transport not open"; case TIMED_OUT: return "TTransportException: Timed out"; case END_OF_FILE: return "TTransportException: End of file"; case INTERRUPTED: return "TTransportException: Interrupted"; case BAD_ARGS: return "TTransportException: Invalid arguments"; case CORRUPTED_DATA: return "TTransportException: Corrupted Data"; case INTERNAL_ERROR: return "TTransportException: Internal error"; default: return "TTransportException: (Invalid exception type)"; } } else { return message_.c_str(); } } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp0000644000000000000000000000400114303740367024405 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include namespace apache { namespace thrift { namespace transport { /** * SSL server socket implementation. */ TSSLServerSocket::TSSLServerSocket(int port, std::shared_ptr factory) : TServerSocket(port), factory_(factory) { factory_->server(true); } TSSLServerSocket::TSSLServerSocket(const std::string& address, int port, std::shared_ptr factory) : TServerSocket(address, port), factory_(factory) { factory_->server(true); } TSSLServerSocket::TSSLServerSocket(int port, int sendTimeout, int recvTimeout, std::shared_ptr factory) : TServerSocket(port, sendTimeout, recvTimeout), factory_(factory) { factory_->server(true); } std::shared_ptr TSSLServerSocket::createSocket(THRIFT_SOCKET client) { if (interruptableChildren_) { return factory_->createSocket(client, pChildInterruptSockReader_); } else { return factory_->createSocket(client); } } } } } thrift-0.19.0/lib/cpp/src/thrift/transport/THttpServer.h0000644000000000000000000000362014303740367023165 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ #define _THRIFT_TRANSPORT_THTTPSERVER_H_ 1 #include namespace apache { namespace thrift { namespace transport { class THttpServer : public THttpTransport { public: THttpServer(std::shared_ptr transport, std::shared_ptr config = nullptr); ~THttpServer() override; void flush() override; protected: virtual std::string getHeader(uint32_t len); void readHeaders(); void parseHeader(char* header) override; bool parseStatusLine(char* status) override; std::string getTimeRFC1123(); }; /** * Wraps a transport into HTTP protocol */ class THttpServerTransportFactory : public TTransportFactory { public: THttpServerTransportFactory() = default; ~THttpServerTransportFactory() override = default; /** * Wraps the transport into a buffered one. */ std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new THttpServer(trans)); } }; } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TWebSocketServer.h0000644000000000000000000003034014303740367024133 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TWEBSOCKETSERVER_H_ #define _THRIFT_TRANSPORT_TWEBSOCKETSERVER_H_ 1 #include #include #include #include #include #include #include #include #if defined(_MSC_VER) || defined(__MINGW32__) #include #define THRIFT_strncasecmp(str1, str2, len) _strnicmp(str1, str2, len) #define THRIFT_strcasestr(haystack, needle) StrStrIA(haystack, needle) #else #define THRIFT_strncasecmp(str1, str2, len) strncasecmp(str1, str2, len) #define THRIFT_strcasestr(haystack, needle) strcasestr(haystack, needle) #endif #if defined(__CYGWIN__) #include #endif using std::string; namespace apache { namespace thrift { namespace transport { std::string base64Encode(unsigned char* data, int length); template class TWebSocketServer : public THttpServer { public: TWebSocketServer(std::shared_ptr transport, std::shared_ptr config = nullptr) : THttpServer(transport, config) { resetHandshake(); } ~TWebSocketServer() override = default; uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { // If we do not have a good handshake, the client will attempt one. if (!handshakeComplete()) { resetHandshake(); THttpServer::read(buf, len); // If we did not get everything we expected, the handshake failed // and we need to send a 400 response back. if (!handshakeComplete()) { sendBadRequest(); return 0; } // Otherwise, send back the 101 response. THttpServer::flush(); } uint32_t want = len; auto have = readBuffer_.available_read(); // If we have some data in the buffer, copy it out and return it. // We have to return it without attempting to read more, since we aren't // guaranteed that the underlying transport actually has more data, so // attempting to read from it could block. if (have > 0 && have >= want) { return readBuffer_.read(buf, want); } // Read another frame. if (!readFrame()) { // EOF. No frame available. return 0; } // Hand over whatever we have. uint32_t give = (std::min)(want, readBuffer_.available_read()); return readBuffer_.read(buf, give); } void flush() override { resetConsumedMessageSize(); writeFrameHeader(); uint8_t* buffer; uint32_t length; writeBuffer_.getBuffer(&buffer, &length); transport_->write(buffer, length); transport_->flush(); writeBuffer_.resetBuffer(); } protected: std::string getHeader(uint32_t len) override { THRIFT_UNUSED_VARIABLE(len); std::ostringstream h; h << "HTTP/1.1 101 Switching Protocols" << CRLF << "Server: Thrift/" << PACKAGE_VERSION << CRLF << "Upgrade: websocket" << CRLF << "Connection: Upgrade" << CRLF << "Sec-WebSocket-Accept: " << acceptKey_ << CRLF << CRLF; return h.str(); } void parseHeader(char* header) override { char* colon = strchr(header, ':'); if (colon == nullptr) { return; } size_t sz = colon - header; char* value = colon + 1; if (THRIFT_strncasecmp(header, "Upgrade", sz) == 0) { if (THRIFT_strcasestr(value, "websocket") != nullptr) { upgrade_ = true; } } else if (THRIFT_strncasecmp(header, "Connection", sz) == 0) { if (THRIFT_strcasestr(value, "Upgrade") != nullptr) { connection_ = true; } } else if (THRIFT_strncasecmp(header, "Sec-WebSocket-Key", sz) == 0) { std::string toHash = value + 1; toHash += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; unsigned char hash[20]; SHA1((const unsigned char*)toHash.c_str(), toHash.length(), hash); acceptKey_ = base64Encode(hash, 20); secWebSocketKey_ = true; } else if (THRIFT_strncasecmp(header, "Sec-WebSocket-Version", sz) == 0) { if (THRIFT_strcasestr(value, "13") != nullptr) { secWebSocketVersion_ = true; } } } bool parseStatusLine(char* status) override { char* method = status; char* path = strchr(method, ' '); if (path == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *path = '\0'; while (*(++path) == ' ') { }; char* http = strchr(path, ' '); if (http == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *http = '\0'; if (strcmp(method, "GET") == 0) { // GET method ok, looking for content. return true; } throw TTransportException(string("Bad Status (unsupported method): ") + status); } private: enum class CloseCode : uint16_t { NormalClosure = 1000, GoingAway = 1001, ProtocolError = 1002, UnsupportedDataType = 1003, NoStatusCode = 1005, AbnormalClosure = 1006, InvalidData = 1007, PolicyViolation = 1008, MessageTooBig = 1009, ExtensionExpected = 1010, UnexpectedError = 1011, NotSecure = 1015 }; enum class Opcode : uint8_t { Continuation = 0x0, Text = 0x1, Binary = 0x2, Close = 0x8, Ping = 0x9, Pong = 0xA }; void failConnection(CloseCode reason) { writeFrameHeader(Opcode::Close); auto buffer = htons(static_cast(reason)); transport_->write(reinterpret_cast(&buffer), 2); transport_->flush(); transport_->close(); } bool handshakeComplete() { return upgrade_ && connection_ && secWebSocketKey_ && secWebSocketVersion_; } void pong() { writeFrameHeader(Opcode::Pong); uint8_t* buffer; uint32_t size; readBuffer_.getBuffer(&buffer, &size); transport_->write(buffer, size); transport_->flush(); } bool readFrame() { uint8_t headerBuffer[8]; auto read = transport_->read(headerBuffer, 2); if (read < 2) { return false; } // Since Thrift has its own message end marker and we read frame by frame, // it doesn't really matter if the frame is marked as FIN. // Capture it only for debugging only. auto fin = (headerBuffer[0] & 0x80) != 0; THRIFT_UNUSED_VARIABLE(fin); // RSV1, RSV2, RSV3 if ((headerBuffer[0] & 0x70) != 0) { failConnection(CloseCode::ProtocolError); throw TTransportException(TTransportException::CORRUPTED_DATA, "Reserved bits must be zeroes"); } auto opcode = (Opcode)(headerBuffer[0] & 0x0F); // Mask if ((headerBuffer[1] & 0x80) == 0) { failConnection(CloseCode::ProtocolError); throw TTransportException(TTransportException::CORRUPTED_DATA, "Messages from the client must be masked"); } // Read the length uint64_t payloadLength = headerBuffer[1] & 0x7F; if (payloadLength == 126) { read = transport_->read(headerBuffer, 2); if (read < 2) { return false; } payloadLength = ntohs(*reinterpret_cast(headerBuffer)); } else if (payloadLength == 127) { read = transport_->read(headerBuffer, 8); if (read < 8) { return false; } payloadLength = THRIFT_ntohll(*reinterpret_cast(headerBuffer)); if ((payloadLength & 0x8000000000000000) != 0) { failConnection(CloseCode::ProtocolError); throw TTransportException( TTransportException::CORRUPTED_DATA, "The most significant bit of the payload length must be zero"); } } // size_t is smaller than a ulong on a 32-bit system if (payloadLength > UINT32_MAX) { failConnection(CloseCode::MessageTooBig); return false; } auto length = static_cast(payloadLength); if (length > 0) { // Read the masking key read = transport_->read(headerBuffer, 4); if (read < 4) { return false; } readBuffer_.resetBuffer(length); uint8_t* buffer = readBuffer_.getWritePtr(length); read = transport_->read(buffer, length); readBuffer_.wroteBytes(read); if (read < length) { return false; } // Unmask the data for (size_t i = 0; i < length; i++) { buffer[i] ^= headerBuffer[i % 4]; } T_DEBUG("FIN=%d, Opcode=%X, length=%d, payload=%s", fin, opcode, length, binary ? readBuffer_.toHexString() : cast(string) readBuffer_); } switch (opcode) { case Opcode::Close: if (length >= 2) { uint8_t buffer[2]; readBuffer_.read(buffer, 2); CloseCode closeCode = static_cast(ntohs(*reinterpret_cast(buffer))); THRIFT_UNUSED_VARIABLE(closeCode); string closeReason = readBuffer_.readAsString(length - 2); T_DEBUG("Connection closed: %d %s", closeCode, closeReason); } transport_->close(); return false; case Opcode::Ping: pong(); return readFrame(); default: return true; } } void resetHandshake() { connection_ = false; secWebSocketKey_ = false; secWebSocketVersion_ = false; upgrade_ = false; } void sendBadRequest() { std::ostringstream h; h << "HTTP/1.1 400 Bad Request" << CRLF << "Server: Thrift/" << PACKAGE_VERSION << CRLF << CRLF; std::string header = h.str(); transport_->write(reinterpret_cast(header.data()), static_cast(header.length())); transport_->flush(); transport_->close(); } void writeFrameHeader(Opcode opcode = Opcode::Continuation) { uint32_t headerSize = 1; uint32_t length = writeBuffer_.available_read(); if (length < 126) { ++headerSize; } else if (length < 65536) { headerSize += 3; } else { headerSize += 9; } // The server does not mask the response uint8_t* header = static_cast(alloca(headerSize)); if (opcode == Opcode::Continuation) { opcode = binary ? Opcode::Binary : Opcode::Text; } header[0] = static_cast(opcode) | 0x80; if (length < 126) { header[1] = static_cast(length); } else if (length < 65536) { header[1] = 126; *reinterpret_cast(header + 2) = htons(length); } else { header[1] = 127; *reinterpret_cast(header + 2) = THRIFT_htonll(length); } transport_->write(header, headerSize); } // Add constant here to avoid a linker error on Windows constexpr static const char* CRLF = "\r\n"; std::string acceptKey_; bool connection_; bool secWebSocketKey_; bool secWebSocketVersion_; bool upgrade_; }; /** * Wraps a transport into binary WebSocket protocol */ class TBinaryWebSocketServerTransportFactory : public TTransportFactory { public: TBinaryWebSocketServerTransportFactory() = default; ~TBinaryWebSocketServerTransportFactory() override = default; /** * Wraps the transport into a buffered one. */ std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TWebSocketServer(trans)); } }; /** * Wraps a transport into text WebSocket protocol */ class TTextWebSocketServerTransportFactory : public TTransportFactory { public: TTextWebSocketServerTransportFactory() = default; ~TTextWebSocketServerTransportFactory() override = default; /** * Wraps the transport into a buffered one. */ std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TWebSocketServer(trans)); } }; } // namespace transport } // namespace thrift } // namespace apache #endif thrift-0.19.0/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h0000644000000000000000000000447714303740367026257 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TNONBLOCKINGSSLSERVERSOCKET_H_ #define _THRIFT_TRANSPORT_TNONBLOCKINGSSLSERVERSOCKET_H_ 1 #include namespace apache { namespace thrift { namespace transport { class TSSLSocketFactory; /** * Nonblocking Server socket that accepts SSL connections. */ class TNonblockingSSLServerSocket : public TNonblockingServerSocket { public: /** * Constructor. Binds to all interfaces. * * @param port Listening port * @param factory SSL socket factory implementation */ TNonblockingSSLServerSocket(int port, std::shared_ptr factory); /** * Constructor. Binds to the specified address. * * @param address Address to bind to * @param port Listening port * @param factory SSL socket factory implementation */ TNonblockingSSLServerSocket(const std::string& address, int port, std::shared_ptr factory); /** * Constructor. Binds to all interfaces. * * @param port Listening port * @param sendTimeout Socket send timeout * @param recvTimeout Socket receive timeout * @param factory SSL socket factory implementation */ TNonblockingSSLServerSocket(int port, int sendTimeout, int recvTimeout, std::shared_ptr factory); protected: std::shared_ptr createSocket(THRIFT_SOCKET socket) override; std::shared_ptr factory_; }; } } } #endif thrift-0.19.0/lib/cpp/src/thrift/transport/TTransportUtils.cpp0000644000000000000000000001123614303740367024431 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include using std::string; namespace apache { namespace thrift { namespace transport { uint32_t TPipedTransport::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); uint32_t need = len; // We don't have enough data yet if (rLen_ - rPos_ < need) { // Copy out whatever we have if (rLen_ - rPos_ > 0) { memcpy(buf, rBuf_ + rPos_, rLen_ - rPos_); need -= rLen_ - rPos_; buf += rLen_ - rPos_; rPos_ = rLen_; } // Double the size of the underlying buffer if it is full if (rLen_ == rBufSize_) { rBufSize_ *= 2; auto *tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); if (tmpBuf == nullptr) { throw std::bad_alloc(); } rBuf_ = tmpBuf; } // try to fill up the buffer rLen_ += srcTrans_->read(rBuf_ + rPos_, rBufSize_ - rPos_); } // Hand over whatever we have uint32_t give = need; if (rLen_ - rPos_ < give) { give = rLen_ - rPos_; } if (give > 0) { memcpy(buf, rBuf_ + rPos_, give); rPos_ += give; need -= give; } return (len - need); } void TPipedTransport::write(const uint8_t* buf, uint32_t len) { if (len == 0) { return; } // Make the buffer as big as it needs to be if ((len + wLen_) >= wBufSize_) { uint32_t newBufSize = wBufSize_ * 2; while ((len + wLen_) >= newBufSize) { newBufSize *= 2; } auto *tmpBuf= (uint8_t*)std::realloc(wBuf_, sizeof(uint8_t) * newBufSize); if (tmpBuf == nullptr) { throw std::bad_alloc(); } wBuf_ = tmpBuf; wBufSize_ = newBufSize; } // Copy into the buffer memcpy(wBuf_ + wLen_, buf, len); wLen_ += len; } void TPipedTransport::flush() { // Write out any data waiting in the write buffer if (wLen_ > 0) { srcTrans_->write(wBuf_, wLen_); wLen_ = 0; } // Flush the underlying transport srcTrans_->flush(); } TPipedFileReaderTransport::TPipedFileReaderTransport( std::shared_ptr srcTrans, std::shared_ptr dstTrans, std::shared_ptr config) : TPipedTransport(srcTrans, dstTrans, config), srcTrans_(srcTrans) { } TPipedFileReaderTransport::~TPipedFileReaderTransport() = default; bool TPipedFileReaderTransport::isOpen() const { return TPipedTransport::isOpen(); } bool TPipedFileReaderTransport::peek() { return TPipedTransport::peek(); } void TPipedFileReaderTransport::open() { TPipedTransport::open(); } void TPipedFileReaderTransport::close() { TPipedTransport::close(); } uint32_t TPipedFileReaderTransport::read(uint8_t* buf, uint32_t len) { return TPipedTransport::read(buf, len); } uint32_t TPipedFileReaderTransport::readAll(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); uint32_t have = 0; uint32_t get = 0; while (have < len) { get = read(buf + have, len - have); if (get <= 0) { throw TEOFException(); } have += get; } return have; } uint32_t TPipedFileReaderTransport::readEnd() { return TPipedTransport::readEnd(); } void TPipedFileReaderTransport::write(const uint8_t* buf, uint32_t len) { TPipedTransport::write(buf, len); } uint32_t TPipedFileReaderTransport::writeEnd() { return TPipedTransport::writeEnd(); } void TPipedFileReaderTransport::flush() { TPipedTransport::flush(); } int32_t TPipedFileReaderTransport::getReadTimeout() { return srcTrans_->getReadTimeout(); } void TPipedFileReaderTransport::setReadTimeout(int32_t readTimeout) { srcTrans_->setReadTimeout(readTimeout); } uint32_t TPipedFileReaderTransport::getNumChunks() { return srcTrans_->getNumChunks(); } uint32_t TPipedFileReaderTransport::getCurChunk() { return srcTrans_->getCurChunk(); } void TPipedFileReaderTransport::seekToChunk(int32_t chunk) { srcTrans_->seekToChunk(chunk); } void TPipedFileReaderTransport::seekToEnd() { srcTrans_->seekToEnd(); } } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/transport/TSimpleFileTransport.h0000644000000000000000000000264314303740367025031 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ #define _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ 1 #include namespace apache { namespace thrift { namespace transport { /** * Dead-simple wrapper around a file. * * Writeable files are opened with O_CREAT and O_APPEND */ class TSimpleFileTransport : public TFDTransport { public: TSimpleFileTransport(const std::string& path, bool read = true, bool write = false, std::shared_ptr config = nullptr); }; } } } // apache::thrift::transport #endif // _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TPipeServer.h0000644000000000000000000000657014303740367023152 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ #define _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ 1 #include #include #ifndef _WIN32 #include #endif #define TPIPE_SERVER_MAX_CONNS_DEFAULT PIPE_UNLIMITED_INSTANCES // Windows - set security to allow non-elevated apps // to access pipes created by elevated apps. // Full access to everyone const std::string DEFAULT_PIPE_SECURITY{"D:(A;;FA;;;WD)"}; namespace apache { namespace thrift { namespace transport { /** * Windows Pipes implementation of TServerTransport. * Don't destroy a TPipeServer at global scope, as that will cause a thread join * during DLLMain. That also means that TServer's using TPipeServer shouldn't be at global * scope. */ #ifdef _WIN32 class TPipeServerImpl; class TPipe; class TPipeServer : public TServerTransport { public: // Constructors // Named Pipe - TPipeServer(const std::string& pipename, uint32_t bufsize); TPipeServer(const std::string& pipename, uint32_t bufsize, uint32_t maxconnections); TPipeServer(const std::string& pipename, uint32_t bufsize, uint32_t maxconnections, const std::string& securityDescriptor); TPipeServer(const std::string& pipename); // Anonymous pipe - TPipeServer(int bufsize); TPipeServer(); // Destructor virtual ~TPipeServer(); bool isOpen() const override; // Standard transport callbacks void interrupt() override; void close() override; void listen() override; // Accessors std::string getPipename(); void setPipename(const std::string& pipename); int getBufferSize(); void setBufferSize(int bufsize); HANDLE getPipeHandle(); // Named Pipe R/W -or- Anonymous pipe Read handle HANDLE getWrtPipeHandle(); HANDLE getClientRdPipeHandle(); HANDLE getClientWrtPipeHandle(); bool getAnonymous(); void setAnonymous(bool anon); void setMaxConnections(uint32_t maxconnections); void setSecurityDescriptor(const std::string& securityDescriptor); // this function is intended to be used in generic / template situations, // so its name needs to be the same as TPipe's HANDLE getNativeWaitHandle(); protected: virtual std::shared_ptr acceptImpl(); private: std::shared_ptr impl_; std::string pipename_; std::string securityDescriptor_; uint32_t bufsize_; uint32_t maxconns_; bool isAnonymous_; }; #else //_WIN32 //*NIX named pipe implementation uses domain socket typedef TServerSocket TPipeServer; #endif } } } // apache::thrift::transport #endif // #ifndef _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ thrift-0.19.0/lib/cpp/src/thrift/transport/TSSLSocket.h0000644000000000000000000003421114303740367022671 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TRANSPORT_TSSLSOCKET_H_ #define _THRIFT_TRANSPORT_TSSLSOCKET_H_ 1 // Put this first to avoid WIN32 build failure #include #include #include #include namespace apache { namespace thrift { namespace transport { class AccessManager; class SSLContext; enum SSLProtocol { SSLTLS = 0, // Supports SSLv2 and SSLv3 handshake but only negotiates at TLSv1_0 or later. //SSLv2 = 1, // HORRIBLY INSECURE! SSLv3 = 2, // Supports SSLv3 only - also horribly insecure! TLSv1_0 = 3, // Supports TLSv1_0 or later. TLSv1_1 = 4, // Supports TLSv1_1 or later. TLSv1_2 = 5, // Supports TLSv1_2 or later. LATEST = TLSv1_2 }; #define TSSL_EINTR 0 #define TSSL_DATA 1 /** * Initialize OpenSSL library. This function, or some other * equivalent function to initialize OpenSSL, must be called before * TSSLSocket is used. If you set TSSLSocketFactory to use manual * OpenSSL initialization, you should call this function or otherwise * ensure OpenSSL is initialized yourself. */ void initializeOpenSSL(); /** * Cleanup OpenSSL library. This function should be called to clean * up OpenSSL after use of OpenSSL functionality is finished. If you * set TSSLSocketFactory to use manual OpenSSL initialization, you * should call this function yourself or ensure that whatever * initialized OpenSSL cleans it up too. */ void cleanupOpenSSL(); /** * OpenSSL implementation for SSL socket interface. */ class TSSLSocket : public TSocket { public: ~TSSLSocket() override; /** * TTransport interface. */ bool isOpen() const override; bool peek() override; void open() override; void close() override; bool hasPendingDataToRead() override; uint32_t read(uint8_t* buf, uint32_t len) override; void write(const uint8_t* buf, uint32_t len) override; uint32_t write_partial(const uint8_t* buf, uint32_t len) override; void flush() override; /** * Set whether to use client or server side SSL handshake protocol. * * @param flag Use server side handshake protocol if true. */ void server(bool flag) { server_ = flag; } /** * Determine whether the SSL socket is server or client mode. */ bool server() const { return server_; } /** * Set AccessManager. * * @param manager Instance of AccessManager */ virtual void access(std::shared_ptr manager) { access_ = manager; } /** * Set eventSafe flag if libevent is used. */ void setLibeventSafe() { eventSafe_ = true; } /** * Determines whether SSL Socket is libevent safe or not. */ bool isLibeventSafe() const { return eventSafe_; } protected: /** * Constructor. */ TSSLSocket(std::shared_ptr ctx, std::shared_ptr config = nullptr); /** * Constructor with an interrupt signal. */ TSSLSocket(std::shared_ptr ctx, std::shared_ptr interruptListener, std::shared_ptr config = nullptr); /** * Constructor, create an instance of TSSLSocket given an existing socket. * * @param socket An existing socket */ TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr config = nullptr); /** * Constructor, create an instance of TSSLSocket given an existing socket that can be interrupted. * * @param socket An existing socket */ TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr interruptListener, std::shared_ptr config = nullptr); /** * Constructor. * * @param host Remote host name * @param port Remote port number */ TSSLSocket(std::shared_ptr ctx, std::string host, int port, std::shared_ptr config = nullptr); /** * Constructor with an interrupt signal. * * @param host Remote host name * @param port Remote port number */ TSSLSocket(std::shared_ptr ctx, std::string host, int port, std::shared_ptr interruptListener, std::shared_ptr config = nullptr); /** * Authorize peer access after SSL handshake completes. */ virtual void authorize(); /** * Initiate SSL handshake if not already initiated. */ void initializeHandshake(); /** * Initiate SSL handshake params. */ void initializeHandshakeParams(); /** * Check if SSL handshake is completed or not. */ bool checkHandshake(); /** * Waits for an socket or shutdown event. * * @throw TTransportException::INTERRUPTED if interrupted is signaled. * * @return TSSL_EINTR if EINTR happened on the underlying socket * TSSL_DATA if data is available on the socket. */ unsigned int waitForEvent(bool wantRead); bool server_; SSL* ssl_; std::shared_ptr ctx_; std::shared_ptr access_; friend class TSSLSocketFactory; private: bool handshakeCompleted_; int readRetryCount_; bool eventSafe_; void init(); }; /** * SSL socket factory. SSL sockets should be created via SSL factory. * The factory will automatically initialize and cleanup openssl as long as * there is a TSSLSocketFactory instantiated, and as long as the static * boolean manualOpenSSLInitialization_ is set to false, the default. * * If you would like to initialize and cleanup openssl yourself, set * manualOpenSSLInitialization_ to true and TSSLSocketFactory will no * longer be responsible for openssl initialization and teardown. * * It is the responsibility of the code using TSSLSocketFactory to * ensure that the factory lifetime exceeds the lifetime of any sockets * it might create. If this is not guaranteed, a socket may call into * openssl after the socket factory has cleaned up openssl! This * guarantee is unnecessary if manualOpenSSLInitialization_ is true, * however, since it would be up to the consuming application instead. */ class TSSLSocketFactory { public: /** * Constructor/Destructor * * @param protocol The SSL/TLS protocol to use. */ TSSLSocketFactory(SSLProtocol protocol = SSLTLS); virtual ~TSSLSocketFactory(); /** * Create an instance of TSSLSocket with a fresh new socket. */ virtual std::shared_ptr createSocket(); /** * Create an instance of TSSLSocket with a fresh new socket, which is interruptable. */ virtual std::shared_ptr createSocket(std::shared_ptr interruptListener); /** * Create an instance of TSSLSocket with the given socket. * * @param socket An existing socket. */ virtual std::shared_ptr createSocket(THRIFT_SOCKET socket); /** * Create an instance of TSSLSocket with the given socket which is interruptable. * * @param socket An existing socket. */ virtual std::shared_ptr createSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener); /** * Create an instance of TSSLSocket. * * @param host Remote host to be connected to * @param port Remote port to be connected to */ virtual std::shared_ptr createSocket(const std::string& host, int port); /** * Create an instance of TSSLSocket. * * @param host Remote host to be connected to * @param port Remote port to be connected to */ virtual std::shared_ptr createSocket(const std::string& host, int port, std::shared_ptr interruptListener); /** * Set ciphers to be used in SSL handshake process. * * @param ciphers A list of ciphers */ virtual void ciphers(const std::string& enable); /** * Enable/Disable authentication. * * @param required Require peer to present valid certificate if true */ virtual void authenticate(bool required); /** * Load server certificate. * * @param path Path to the certificate file * @param format Certificate file format */ virtual void loadCertificate(const char* path, const char* format = "PEM"); virtual void loadCertificateFromBuffer(const char* aCertificate, const char* format = "PEM"); /** * Load private key. * * @param path Path to the private key file * @param format Private key file format */ virtual void loadPrivateKey(const char* path, const char* format = "PEM"); virtual void loadPrivateKeyFromBuffer(const char* aPrivateKey, const char* format = "PEM"); /** * Load trusted certificates from specified file. * * @param path Path to trusted certificate file */ virtual void loadTrustedCertificates(const char* path, const char* capath = nullptr); virtual void loadTrustedCertificatesFromBuffer(const char* aCertificate, const char* aChain = nullptr); /** * Default randomize method. */ virtual void randomize(); /** * Override default OpenSSL password callback with getPassword(). */ void overrideDefaultPasswordCallback(); /** * Set/Unset server mode. * * @param flag Server mode if true */ virtual void server(bool flag) { server_ = flag; } /** * Determine whether the socket is in server or client mode. * * @return true, if server mode, or, false, if client mode */ virtual bool server() const { return server_; } /** * Set AccessManager. * * @param manager The AccessManager instance */ virtual void access(std::shared_ptr manager) { access_ = manager; } static void setManualOpenSSLInitialization(bool manualOpenSSLInitialization) { manualOpenSSLInitialization_ = manualOpenSSLInitialization; } protected: std::shared_ptr ctx_; /** * Override this method for custom password callback. It may be called * multiple times at any time during a session as necessary. * * @param password Pass collected password to OpenSSL * @param size Maximum length of password including NULL character */ virtual void getPassword(std::string& /* password */, int /* size */) {} private: bool server_; std::shared_ptr access_; static concurrency::Mutex mutex_; static uint64_t count_; THRIFT_EXPORT static bool manualOpenSSLInitialization_; void setup(std::shared_ptr ssl); static int passwordCallback(char* password, int size, int, void* data); }; /** * SSL exception. */ class TSSLException : public TTransportException { public: TSSLException(const std::string& message) : TTransportException(TTransportException::INTERNAL_ERROR, message) {} const char* what() const noexcept override { if (message_.empty()) { return "TSSLException"; } else { return message_.c_str(); } } }; /** * Wrap OpenSSL SSL_CTX into a class. */ class SSLContext { public: SSLContext(const SSLProtocol& protocol = SSLTLS); virtual ~SSLContext(); SSL* createSSL(); SSL_CTX* get() { return ctx_; } private: SSL_CTX* ctx_; }; /** * Callback interface for access control. It's meant to verify the remote host. * It's constructed when application starts and set to TSSLSocketFactory * instance. It's passed onto all TSSLSocket instances created by this factory * object. */ class AccessManager { public: enum Decision { DENY = -1, // deny access SKIP = 0, // cannot make decision, move on to next (if any) ALLOW = 1 // allow access }; /** * Destructor */ virtual ~AccessManager() = default; /** * Determine whether the peer should be granted access or not. It's called * once after the SSL handshake completes successfully, before peer certificate * is examined. * * If a valid decision (ALLOW or DENY) is returned, the peer certificate is * not to be verified. * * @param sa Peer IP address * @return True if the peer is trusted, false otherwise */ virtual Decision verify(const sockaddr_storage& /* sa */) noexcept { return DENY; } /** * Determine whether the peer should be granted access or not. It's called * every time a DNS subjectAltName/common name is extracted from peer's * certificate. * * @param host Client mode: host name returned by TSocket::getHost() * Server mode: host name returned by TSocket::getPeerHost() * @param name SubjectAltName or common name extracted from peer certificate * @param size Length of name * @return True if the peer is trusted, false otherwise * * Note: The "name" parameter may be UTF8 encoded. */ virtual Decision verify(const std::string& /* host */, const char* /* name */, int /* size */) noexcept { return DENY; } /** * Determine whether the peer should be granted access or not. It's called * every time an IP subjectAltName is extracted from peer's certificate. * * @param sa Peer IP address retrieved from the underlying socket * @param data IP address extracted from certificate * @param size Length of the IP address * @return True if the peer is trusted, false otherwise */ virtual Decision verify(const sockaddr_storage& /* sa */, const char* /* data */, int /* size */) noexcept { return DENY; } }; typedef AccessManager::Decision Decision; class DefaultClientAccessManager : public AccessManager { public: // AccessManager interface Decision verify(const sockaddr_storage& sa) noexcept override; Decision verify(const std::string& host, const char* name, int size) noexcept override; Decision verify(const sockaddr_storage& sa, const char* data, int size) noexcept override; }; } } } #endif thrift-0.19.0/lib/cpp/src/thrift/transport/TPipe.cpp0000644000000000000000000003244714303740367022320 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #ifdef _WIN32 #include #include #endif namespace apache { namespace thrift { namespace transport { /** * TPipe implementation. */ #ifdef _WIN32 uint32_t pipe_read(HANDLE pipe, uint8_t* buf, uint32_t len); void pipe_write(HANDLE pipe, const uint8_t* buf, uint32_t len); uint32_t pseudo_sync_read(HANDLE pipe, HANDLE event, uint8_t* buf, uint32_t len); void pseudo_sync_write(HANDLE pipe, HANDLE event, const uint8_t* buf, uint32_t len); class TPipeImpl : apache::thrift::TNonCopyable { public: TPipeImpl() {} virtual ~TPipeImpl() {} virtual uint32_t read(uint8_t* buf, uint32_t len) = 0; virtual void write(const uint8_t* buf, uint32_t len) = 0; virtual HANDLE getPipeHandle() = 0; // doubles as the read handle for anon pipe virtual void setPipeHandle(HANDLE pipehandle) = 0; virtual HANDLE getWrtPipeHandle() { return INVALID_HANDLE_VALUE; } virtual void setWrtPipeHandle(HANDLE) {} virtual bool isBufferedDataAvailable() { return false; } virtual HANDLE getNativeWaitHandle() { return INVALID_HANDLE_VALUE; } }; class TNamedPipeImpl : public TPipeImpl { public: explicit TNamedPipeImpl(TAutoHandle &pipehandle) : Pipe_(pipehandle.release()) {} virtual ~TNamedPipeImpl() {} virtual uint32_t read(uint8_t* buf, uint32_t len) { return pseudo_sync_read(Pipe_.h, read_event_.h, buf, len); } virtual void write(const uint8_t* buf, uint32_t len) { pseudo_sync_write(Pipe_.h, write_event_.h, buf, len); } virtual HANDLE getPipeHandle() { return Pipe_.h; } virtual void setPipeHandle(HANDLE pipehandle) { Pipe_.reset(pipehandle); } private: TManualResetEvent read_event_; TManualResetEvent write_event_; TAutoHandle Pipe_; }; class TAnonPipeImpl : public TPipeImpl { public: TAnonPipeImpl(HANDLE PipeRd, HANDLE PipeWrt) : PipeRd_(PipeRd), PipeWrt_(PipeWrt) {} virtual ~TAnonPipeImpl() {} virtual uint32_t read(uint8_t* buf, uint32_t len) { return pipe_read(PipeRd_.h, buf, len); } virtual void write(const uint8_t* buf, uint32_t len) { pipe_write(PipeWrt_.h, buf, len); } virtual HANDLE getPipeHandle() { return PipeRd_.h; } virtual void setPipeHandle(HANDLE PipeRd) { PipeRd_.reset(PipeRd); } virtual HANDLE getWrtPipeHandle() { return PipeWrt_.h; } virtual void setWrtPipeHandle(HANDLE PipeWrt) { PipeWrt_.reset(PipeWrt); } private: TAutoHandle PipeRd_; TAutoHandle PipeWrt_; }; // If you want a select-like loop to work, use this subclass. Be warned... // the read implementation has several context switches, so this is slower // than using the regular named pipe implementation class TWaitableNamedPipeImpl : public TPipeImpl { public: explicit TWaitableNamedPipeImpl(TAutoHandle &pipehandle) : begin_unread_idx_(0), end_unread_idx_(0) { readOverlap_.action = TOverlappedWorkItem::READ; readOverlap_.h = pipehandle.h; cancelOverlap_.action = TOverlappedWorkItem::CANCELIO; cancelOverlap_.h = pipehandle.h; buffer_.resize(1024 /*arbitrary buffer size*/, '\0'); beginAsyncRead(&buffer_[0], static_cast(buffer_.size())); Pipe_.reset(pipehandle.release()); } virtual ~TWaitableNamedPipeImpl() { // see if there is an outstanding read request if (begin_unread_idx_ == end_unread_idx_) { // if so, cancel it, and wait for the dead completion thread_->addWorkItem(&cancelOverlap_); readOverlap_.overlappedResults(false /*ignore errors*/); } } virtual uint32_t read(uint8_t* buf, uint32_t len); virtual void write(const uint8_t* buf, uint32_t len) { pseudo_sync_write(Pipe_.h, write_event_.h, buf, len); } virtual HANDLE getPipeHandle() { return Pipe_.h; } virtual void setPipeHandle(HANDLE pipehandle) { Pipe_.reset(pipehandle); } virtual bool isBufferedDataAvailable() { return begin_unread_idx_ < end_unread_idx_; } virtual HANDLE getNativeWaitHandle() { return ready_event_.h; } private: void beginAsyncRead(uint8_t* buf, uint32_t len); uint32_t endAsyncRead(); TAutoOverlapThread thread_; TAutoHandle Pipe_; TOverlappedWorkItem readOverlap_; TOverlappedWorkItem cancelOverlap_; TManualResetEvent ready_event_; TManualResetEvent write_event_; std::vector buffer_; uint32_t begin_unread_idx_; uint32_t end_unread_idx_; }; void TWaitableNamedPipeImpl::beginAsyncRead(uint8_t* buf, uint32_t len) { begin_unread_idx_ = end_unread_idx_ = 0; readOverlap_.reset(buf, len, ready_event_.h); thread_->addWorkItem(&readOverlap_); if (readOverlap_.success == FALSE && readOverlap_.last_error != ERROR_IO_PENDING) { GlobalOutput.perror("TPipe ::ReadFile errored GLE=", readOverlap_.last_error); throw TTransportException(TTransportException::UNKNOWN, "TPipe: ReadFile failed"); } } uint32_t TWaitableNamedPipeImpl::endAsyncRead() { return readOverlap_.overlappedResults(); } uint32_t TWaitableNamedPipeImpl::read(uint8_t* buf, uint32_t len) { if (begin_unread_idx_ == end_unread_idx_) { end_unread_idx_ = endAsyncRead(); } uint32_t __idxsize = end_unread_idx_ - begin_unread_idx_; uint32_t bytes_to_copy = (len < __idxsize) ? len : __idxsize; memcpy(buf, &buffer_[begin_unread_idx_], bytes_to_copy); begin_unread_idx_ += bytes_to_copy; if (begin_unread_idx_ != end_unread_idx_) { assert(len == bytes_to_copy); // we were able to fulfill the read with just the bytes in our // buffer, and we still have buffer left return bytes_to_copy; } uint32_t bytes_copied = bytes_to_copy; // all of the requested data has been read. Kick off an async read for the next round. beginAsyncRead(&buffer_[0], static_cast(buffer_.size())); return bytes_copied; } void pseudo_sync_write(HANDLE pipe, HANDLE event, const uint8_t* buf, uint32_t len) { OVERLAPPED tempOverlap; memset(&tempOverlap, 0, sizeof(tempOverlap)); tempOverlap.hEvent = event; uint32_t written = 0; while (written < len) { BOOL result = ::WriteFile(pipe, buf + written, len - written, nullptr, &tempOverlap); if (result == FALSE && ::GetLastError() != ERROR_IO_PENDING) { GlobalOutput.perror("TPipe ::WriteFile errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::UNKNOWN, "TPipe: write failed"); } DWORD bytes = 0; result = ::GetOverlappedResult(pipe, &tempOverlap, &bytes, TRUE); if (!result) { GlobalOutput.perror("TPipe ::GetOverlappedResult errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::UNKNOWN, "TPipe: GetOverlappedResult failed"); } written += bytes; } } uint32_t pseudo_sync_read(HANDLE pipe, HANDLE event, uint8_t* buf, uint32_t len) { OVERLAPPED tempOverlap; memset(&tempOverlap, 0, sizeof(tempOverlap)); tempOverlap.hEvent = event; BOOL result = ::ReadFile(pipe, buf, len, nullptr, &tempOverlap); if (result == FALSE && ::GetLastError() != ERROR_IO_PENDING) { GlobalOutput.perror("TPipe ::ReadFile errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::UNKNOWN, "TPipe: read failed"); } DWORD bytes = 0; result = ::GetOverlappedResult(pipe, &tempOverlap, &bytes, TRUE); if (!result) { GlobalOutput.perror("TPipe ::GetOverlappedResult errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::UNKNOWN, "TPipe: GetOverlappedResult failed"); } return bytes; } //---- Constructors ---- TPipe::TPipe(TAutoHandle &Pipe, std::shared_ptr config) : impl_(new TWaitableNamedPipeImpl(Pipe)), TimeoutSeconds_(3), isAnonymous_(false), TVirtualTransport(config) { } TPipe::TPipe(HANDLE Pipe, std::shared_ptr config) : TimeoutSeconds_(3), isAnonymous_(false), TVirtualTransport(config) { TAutoHandle pipeHandle(Pipe); impl_.reset(new TWaitableNamedPipeImpl(pipeHandle)); } TPipe::TPipe(const char* pipename, std::shared_ptr config) : TimeoutSeconds_(3), isAnonymous_(false), TVirtualTransport(config) { setPipename(pipename); } TPipe::TPipe(const std::string& pipename, std::shared_ptr config) : TimeoutSeconds_(3), isAnonymous_(false), TVirtualTransport(config) { setPipename(pipename); } TPipe::TPipe(HANDLE PipeRd, HANDLE PipeWrt, std::shared_ptr config) : impl_(new TAnonPipeImpl(PipeRd, PipeWrt)), TimeoutSeconds_(3), isAnonymous_(true), TVirtualTransport(config) { } TPipe::TPipe(std::shared_ptr config) : TimeoutSeconds_(3), isAnonymous_(false), TVirtualTransport(config) { } TPipe::~TPipe() { } //--------------------------------------------------------- // Transport callbacks //--------------------------------------------------------- bool TPipe::isOpen() const { return impl_.get() != nullptr; } bool TPipe::peek() { return isOpen(); } void TPipe::open() { if (isOpen()) return; TAutoHandle hPipe; do { DWORD flags = FILE_FLAG_OVERLAPPED; // async mode, so we can do reads at the same time as writes hPipe.reset(CreateFileA(pipename_.c_str(), GENERIC_READ | GENERIC_WRITE, 0, // no sharing nullptr, // default security attributes OPEN_EXISTING, // opens existing pipe flags, nullptr)); // no template file if (hPipe.h != INVALID_HANDLE_VALUE) break; // success! if (::GetLastError() != ERROR_PIPE_BUSY) { GlobalOutput.perror("TPipe::open ::CreateFile errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::NOT_OPEN, "Unable to open pipe"); } } while (::WaitNamedPipeA(pipename_.c_str(), TimeoutSeconds_ * 1000)); if (hPipe.h == INVALID_HANDLE_VALUE) { GlobalOutput.perror("TPipe::open ::CreateFile errored GLE=", ::GetLastError()); throw TTransportException(TTransportException::NOT_OPEN, "Unable to open pipe"); } impl_.reset(new TNamedPipeImpl(hPipe)); } void TPipe::close() { impl_.reset(); } uint32_t TPipe::read(uint8_t* buf, uint32_t len) { checkReadBytesAvailable(len); if (!isOpen()) throw TTransportException(TTransportException::NOT_OPEN, "Called read on non-open pipe"); return impl_->read(buf, len); } uint32_t pipe_read(HANDLE pipe, uint8_t* buf, uint32_t len) { DWORD cbRead; int fSuccess = ReadFile(pipe, // pipe handle buf, // buffer to receive reply len, // size of buffer &cbRead, // number of bytes read nullptr); // not overlapped if (!fSuccess && GetLastError() != ERROR_MORE_DATA) return 0; // No more data, possibly because client disconnected. return cbRead; } void TPipe::write(const uint8_t* buf, uint32_t len) { if (!isOpen()) throw TTransportException(TTransportException::NOT_OPEN, "Called write on non-open pipe"); impl_->write(buf, len); } void pipe_write(HANDLE pipe, const uint8_t* buf, uint32_t len) { DWORD cbWritten; int fSuccess = WriteFile(pipe, // pipe handle buf, // message len, // message length &cbWritten, // bytes written nullptr); // not overlapped if (!fSuccess) throw TTransportException(TTransportException::NOT_OPEN, "Write to pipe failed"); } //--------------------------------------------------------- // Accessors //--------------------------------------------------------- std::string TPipe::getPipename() { return pipename_; } void TPipe::setPipename(const std::string& pipename) { if (pipename.find("\\\\") == std::string::npos) pipename_ = "\\\\.\\pipe\\" + pipename; else pipename_ = pipename; } HANDLE TPipe::getPipeHandle() { if (impl_) return impl_->getPipeHandle(); return INVALID_HANDLE_VALUE; } void TPipe::setPipeHandle(HANDLE pipehandle) { if (isAnonymous_) impl_->setPipeHandle(pipehandle); else { TAutoHandle pipe(pipehandle); impl_.reset(new TNamedPipeImpl(pipe)); } } HANDLE TPipe::getWrtPipeHandle() { if (impl_) return impl_->getWrtPipeHandle(); return INVALID_HANDLE_VALUE; } void TPipe::setWrtPipeHandle(HANDLE pipehandle) { if (impl_) impl_->setWrtPipeHandle(pipehandle); } HANDLE TPipe::getNativeWaitHandle() { if (impl_) return impl_->getNativeWaitHandle(); return INVALID_HANDLE_VALUE; } long TPipe::getConnTimeout() { return TimeoutSeconds_; } void TPipe::setConnTimeout(long seconds) { TimeoutSeconds_ = seconds; } #endif //_WIN32 } } } // apache::thrift::transport thrift-0.19.0/lib/cpp/src/thrift/TApplicationException.cpp0000644000000000000000000000466714303740367023514 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include namespace apache { namespace thrift { uint32_t TApplicationException::read(apache::thrift::protocol::TProtocol* iprot) { uint32_t xfer = 0; std::string fname; apache::thrift::protocol::TType ftype; int16_t fid; xfer += iprot->readStructBegin(fname); while (true) { xfer += iprot->readFieldBegin(fname, ftype, fid); if (ftype == apache::thrift::protocol::T_STOP) { break; } switch (fid) { case 1: if (ftype == apache::thrift::protocol::T_STRING) { xfer += iprot->readString(message_); } else { xfer += iprot->skip(ftype); } break; case 2: if (ftype == apache::thrift::protocol::T_I32) { int32_t type; xfer += iprot->readI32(type); type_ = (TApplicationExceptionType)type; } else { xfer += iprot->skip(ftype); } break; default: xfer += iprot->skip(ftype); break; } xfer += iprot->readFieldEnd(); } xfer += iprot->readStructEnd(); return xfer; } uint32_t TApplicationException::write(apache::thrift::protocol::TProtocol* oprot) const { uint32_t xfer = 0; xfer += oprot->writeStructBegin("TApplicationException"); xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 1); xfer += oprot->writeString(message_); xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldBegin("type", apache::thrift::protocol::T_I32, 2); xfer += oprot->writeI32(type_); xfer += oprot->writeFieldEnd(); xfer += oprot->writeFieldStop(); xfer += oprot->writeStructEnd(); return xfer; } } } // apache::thrift thrift-0.19.0/lib/cpp/src/thrift/TToString.h0000644000000000000000000000660614452237057020605 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TOSTRING_H_ #define _THRIFT_TOSTRING_H_ 1 #include #include #include #include #include #include #include #include namespace apache { namespace thrift { // unnamed namespace to enforce internal linkage - could be done with 'inline' when once have C++17 namespace { const auto default_locale = std::locale("C"); } template std::string to_string(const T& t) { std::ostringstream o; o.imbue(default_locale); o << t; return o.str(); } // TODO: replace the computations below with std::numeric_limits::max_digits10 once C++11 // is enabled. inline std::string to_string(const float& t) { std::ostringstream o; o.imbue(default_locale); o.precision(static_cast(std::ceil(static_cast(std::numeric_limits::digits * std::log10(2.0f) + 1)))); o << t; return o.str(); } inline std::string to_string(const double& t) { std::ostringstream o; o.imbue(default_locale); o.precision(static_cast(std::ceil(static_cast(std::numeric_limits::digits * std::log10(2.0f) + 1)))); o << t; return o.str(); } inline std::string to_string(const long double& t) { std::ostringstream o; o.imbue(default_locale); o.precision(static_cast(std::ceil(static_cast(std::numeric_limits::digits * std::log10(2.0f) + 1)))); o << t; return o.str(); } template std::string to_string(const std::map& m); template std::string to_string(const std::set& s); template std::string to_string(const std::vector& t); template std::string to_string(const typename std::pair& v) { std::ostringstream o; o << to_string(v.first) << ": " << to_string(v.second); return o.str(); } template std::string to_string(const T& beg, const T& end) { std::ostringstream o; for (T it = beg; it != end; ++it) { if (it != beg) o << ", "; o << to_string(*it); } return o.str(); } template std::string to_string(const std::vector& t) { std::ostringstream o; o << "[" << to_string(t.begin(), t.end()) << "]"; return o.str(); } template std::string to_string(const std::map& m) { std::ostringstream o; o << "{" << to_string(m.begin(), m.end()) << "}"; return o.str(); } template std::string to_string(const std::set& s) { std::ostringstream o; o << "{" << to_string(s.begin(), s.end()) << "}"; return o.str(); } } } // apache::thrift #endif // _THRIFT_TOSTRING_H_ thrift-0.19.0/lib/cpp/src/thrift/processor/0000755000000000000000000000000014472652650020550 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/src/thrift/processor/StatsProcessor.h0000644000000000000000000001411414303740367023714 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef STATSPROCESSOR_H #define STATSPROCESSOR_H #include #include #include #include namespace apache { namespace thrift { namespace processor { /* * Class for keeping track of function call statistics and printing them if desired * */ class StatsProcessor : public apache::thrift::TProcessor { public: StatsProcessor(bool print, bool frequency) : print_(print), frequency_(frequency) {} virtual ~StatsProcessor(){}; virtual bool process(std::shared_ptr piprot, std::shared_ptr poprot, void* serverContext) { piprot_ = piprot; std::string fname; apache::thrift::protocol::TMessageType mtype; int32_t seqid; piprot_->readMessageBegin(fname, mtype, seqid); if (mtype != apache::thrift::protocol::T_CALL && mtype != apache::thrift::protocol::T_ONEWAY) { if (print_) { printf("Unknown message type\n"); } throw apache::thrift::TException("Unexpected message type"); } if (print_) { printf("%s (", fname.c_str()); } if (frequency_) { if (frequency_map_.find(fname) != frequency_map_.end()) { frequency_map_[fname]++; } else { frequency_map_[fname] = 1; } } apache::thrift::protocol::TType ftype; int16_t fid; while (true) { piprot_->readFieldBegin(fname, ftype, fid); if (ftype == apache::thrift::protocol::T_STOP) { break; } printAndPassToBuffer(ftype); if (print_) { printf(", "); } } if (print_) { printf("\b\b)\n"); } return true; } const std::map& get_frequency_map() { return frequency_map_; } protected: void printAndPassToBuffer(apache::thrift::protocol::TType ftype) { switch (ftype) { case apache::thrift::protocol::T_BOOL: { bool boolv; piprot_->readBool(boolv); if (print_) { printf("%d", boolv); } } break; case apache::thrift::protocol::T_BYTE: { int8_t bytev; piprot_->readByte(bytev); if (print_) { printf("%d", bytev); } } break; case apache::thrift::protocol::T_I16: { int16_t i16; piprot_->readI16(i16); if (print_) { printf("%d", i16); } } break; case apache::thrift::protocol::T_I32: { int32_t i32; piprot_->readI32(i32); if (print_) { printf("%d", i32); } } break; case apache::thrift::protocol::T_I64: { int64_t i64; piprot_->readI64(i64); if (print_) { printf("%ld", i64); } } break; case apache::thrift::protocol::T_DOUBLE: { double dub; piprot_->readDouble(dub); if (print_) { printf("%f", dub); } } break; case apache::thrift::protocol::T_STRING: { std::string str; piprot_->readString(str); if (print_) { printf("%s", str.c_str()); } } break; case apache::thrift::protocol::T_STRUCT: { std::string name; int16_t fid; apache::thrift::protocol::TType ftype; piprot_->readStructBegin(name); if (print_) { printf("<"); } while (true) { piprot_->readFieldBegin(name, ftype, fid); if (ftype == apache::thrift::protocol::T_STOP) { break; } printAndPassToBuffer(ftype); if (print_) { printf(","); } piprot_->readFieldEnd(); } piprot_->readStructEnd(); if (print_) { printf("\b>"); } } break; case apache::thrift::protocol::T_MAP: { apache::thrift::protocol::TType keyType; apache::thrift::protocol::TType valType; uint32_t i, size; piprot_->readMapBegin(keyType, valType, size); if (print_) { printf("{"); } for (i = 0; i < size; i++) { printAndPassToBuffer(keyType); if (print_) { printf("=>"); } printAndPassToBuffer(valType); if (print_) { printf(","); } } piprot_->readMapEnd(); if (print_) { printf("\b}"); } } break; case apache::thrift::protocol::T_SET: { apache::thrift::protocol::TType elemType; uint32_t i, size; piprot_->readSetBegin(elemType, size); if (print_) { printf("{"); } for (i = 0; i < size; i++) { printAndPassToBuffer(elemType); if (print_) { printf(","); } } piprot_->readSetEnd(); if (print_) { printf("\b}"); } } break; case apache::thrift::protocol::T_LIST: { apache::thrift::protocol::TType elemType; uint32_t i, size; piprot_->readListBegin(elemType, size); if (print_) { printf("["); } for (i = 0; i < size; i++) { printAndPassToBuffer(elemType); if (print_) { printf(","); } } piprot_->readListEnd(); if (print_) { printf("\b]"); } } break; default: break; } } std::shared_ptr piprot_; std::map frequency_map_; bool print_; bool frequency_; }; } } } // apache::thrift::processor #endif thrift-0.19.0/lib/cpp/src/thrift/processor/PeekProcessor.h0000644000000000000000000000631614303740367023507 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef PEEKPROCESSOR_H #define PEEKPROCESSOR_H #include #include #include #include #include #include namespace apache { namespace thrift { namespace processor { /* * Class for peeking at the raw data that is being processed by another processor * and gives the derived class a chance to change behavior accordingly * */ class PeekProcessor : public apache::thrift::TProcessor { public: PeekProcessor(); ~PeekProcessor() override; // Input here: actualProcessor - the underlying processor // protocolFactory - the protocol factory used to wrap the memory buffer // transportFactory - this TPipedTransportFactory is used to wrap the source transport // via a call to getPipedTransport void initialize( std::shared_ptr actualProcessor, std::shared_ptr protocolFactory, std::shared_ptr transportFactory); std::shared_ptr getPipedTransport( std::shared_ptr in); void setTargetTransport(std::shared_ptr targetTransport); bool process(std::shared_ptr in, std::shared_ptr out, void* connectionContext) override; // The following three functions can be overloaded by child classes to // achieve desired peeking behavior virtual void peekName(const std::string& fname); virtual void peekBuffer(uint8_t* buffer, uint32_t size); virtual void peek(std::shared_ptr in, apache::thrift::protocol::TType ftype, int16_t fid); virtual void peekEnd(); private: std::shared_ptr actualProcessor_; std::shared_ptr pipedProtocol_; std::shared_ptr transportFactory_; std::shared_ptr memoryBuffer_; std::shared_ptr targetTransport_; }; } } } // apache::thrift::processor #endif thrift-0.19.0/lib/cpp/src/thrift/processor/PeekProcessor.cpp0000644000000000000000000000747314303740367024047 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include using namespace apache::thrift::transport; using namespace apache::thrift::protocol; using namespace apache::thrift; namespace apache { namespace thrift { namespace processor { PeekProcessor::PeekProcessor() { memoryBuffer_.reset(new TMemoryBuffer()); targetTransport_ = memoryBuffer_; } PeekProcessor::~PeekProcessor() = default; void PeekProcessor::initialize(std::shared_ptr actualProcessor, std::shared_ptr protocolFactory, std::shared_ptr transportFactory) { actualProcessor_ = actualProcessor; pipedProtocol_ = protocolFactory->getProtocol(targetTransport_); transportFactory_ = transportFactory; transportFactory_->initializeTargetTransport(targetTransport_); } std::shared_ptr PeekProcessor::getPipedTransport(std::shared_ptr in) { return transportFactory_->getTransport(in); } void PeekProcessor::setTargetTransport(std::shared_ptr targetTransport) { targetTransport_ = targetTransport; if (std::dynamic_pointer_cast(targetTransport_)) { memoryBuffer_ = std::dynamic_pointer_cast(targetTransport); } else if (std::dynamic_pointer_cast(targetTransport_)) { memoryBuffer_ = std::dynamic_pointer_cast( std::dynamic_pointer_cast(targetTransport_)->getTargetTransport()); } if (!memoryBuffer_) { throw TException( "Target transport must be a TMemoryBuffer or a TPipedTransport with TMemoryBuffer"); } } bool PeekProcessor::process(std::shared_ptr in, std::shared_ptr out, void* connectionContext) { std::string fname; TMessageType mtype; int32_t seqid; in->readMessageBegin(fname, mtype, seqid); if (mtype != T_CALL && mtype != T_ONEWAY) { throw TException("Unexpected message type"); } // Peek at the name peekName(fname); TType ftype; int16_t fid; while (true) { in->readFieldBegin(fname, ftype, fid); if (ftype == T_STOP) { break; } // Peek at the variable peek(in, ftype, fid); in->readFieldEnd(); } in->readMessageEnd(); in->getTransport()->readEnd(); // // All the data is now in memoryBuffer_ and ready to be processed // // Let's first take a peek at the full data in memory uint8_t* buffer; uint32_t size; memoryBuffer_->getBuffer(&buffer, &size); peekBuffer(buffer, size); // Done peeking at variables peekEnd(); bool ret = actualProcessor_->process(pipedProtocol_, out, connectionContext); memoryBuffer_->resetBuffer(); return ret; } void PeekProcessor::peekName(const std::string& fname) { (void)fname; } void PeekProcessor::peekBuffer(uint8_t* buffer, uint32_t size) { (void)buffer; (void)size; } void PeekProcessor::peek(std::shared_ptr in, TType ftype, int16_t fid) { (void)fid; in->skip(ftype); } void PeekProcessor::peekEnd() { } } } } thrift-0.19.0/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h0000644000000000000000000002042714303740367025242 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef THRIFT_TMULTIPLEXEDPROCESSOR_H_ #define THRIFT_TMULTIPLEXEDPROCESSOR_H_ 1 #include #include #include #include namespace apache { namespace thrift { namespace protocol { /** * To be able to work with any protocol, we needed * to allow them to call readMessageBegin() and get a TMessage in exactly * the standard format, without the service name prepended to TMessage.name. */ class StoredMessageProtocol : public TProtocolDecorator { public: StoredMessageProtocol(std::shared_ptr _protocol, const std::string& _name, const TMessageType _type, const int32_t _seqid) : TProtocolDecorator(_protocol), name(_name), type(_type), seqid(_seqid) {} uint32_t readMessageBegin_virt(std::string& _name, TMessageType& _type, int32_t& _seqid) override { _name = name; _type = type; _seqid = seqid; return 0; // (Normal TProtocol read functions return number of bytes read) } std::string name; TMessageType type; int32_t seqid; }; } // namespace protocol /** * TMultiplexedProcessor is a TProcessor allowing * a single TServer to provide multiple services. * *

To do so, you instantiate the processor and then register additional * processors with it, as shown in the following example:

* *
* std::shared_ptr processor(new TMultiplexedProcessor()); * * processor->registerProcessor( * "Calculator", * std::shared_ptr( new CalculatorProcessor( * std::shared_ptr( new CalculatorHandler())))); * * processor->registerProcessor( * "WeatherReport", * std::shared_ptr( new WeatherReportProcessor( * std::shared_ptr( new WeatherReportHandler())))); * * std::shared_ptr transport(new TServerSocket(9090)); * TSimpleServer server(processor, transport); * * server.serve(); *
*/ class TMultiplexedProcessor : public TProcessor { public: typedef std::map > services_t; /** * 'Register' a service with this TMultiplexedProcessor. This * allows us to broker requests to individual services by using the service * name to select them at request time. * * \param [in] serviceName Name of a service, has to be identical to the name * declared in the Thrift IDL, e.g. "WeatherReport". * \param [in] processor Implementation of a service, usually referred to * as "handlers", e.g. WeatherReportHandler, * implementing WeatherReportIf interface. */ void registerProcessor(const std::string& serviceName, std::shared_ptr processor) { services[serviceName] = processor; } /** * Register a service to be called to process queries without service name * \param [in] processor Implementation of a service. */ void registerDefault(const std::shared_ptr& processor) { defaultProcessor = processor; } /** * Chew up invalid input and return an exception to throw. */ TException protocol_error(std::shared_ptr in, std::shared_ptr out, const std::string& name, int32_t seqid, const std::string& msg) const { in->skip(::apache::thrift::protocol::T_STRUCT); in->readMessageEnd(); in->getTransport()->readEnd(); ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::PROTOCOL_ERROR, "TMultiplexedProcessor: " + msg); out->writeMessageBegin(name, ::apache::thrift::protocol::T_EXCEPTION, seqid); x.write(out.get()); out->writeMessageEnd(); out->getTransport()->writeEnd(); out->getTransport()->flush(); return TException(msg); } /** * This implementation of process performs the following steps: * *
    *
  1. Read the beginning of the message.
  2. *
  3. Extract the service name from the message.
  4. *
  5. Using the service name to locate the appropriate processor.
  6. *
  7. Dispatch to the processor, with a decorated instance of TProtocol * that allows readMessageBegin() to return the original TMessage.
  8. *
* * \throws TException If the message type is not T_CALL or T_ONEWAY, if * the service name was not found in the message, or if the service * name was not found in the service map. */ bool process(std::shared_ptr in, std::shared_ptr out, void* connectionContext) override { std::string name; protocol::TMessageType type; int32_t seqid; // Use the actual underlying protocol (e.g. TBinaryProtocol) to read the // message header. This pulls the message "off the wire", which we'll // deal with at the end of this method. in->readMessageBegin(name, type, seqid); if (type != protocol::T_CALL && type != protocol::T_ONEWAY) { // Unexpected message type. throw protocol_error(in, out, name, seqid, "Unexpected message type"); } // Extract the service name boost::tokenizer > tok(name, boost::char_separator(":")); std::vector tokens; std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); // A valid message should consist of two tokens: the service // name and the name of the method to call. if (tokens.size() == 2) { // Search for a processor associated with this service name. auto it = services.find(tokens[0]); if (it != services.end()) { std::shared_ptr processor = it->second; // Let the processor registered for this service name // process the message. return processor ->process(std::shared_ptr( new protocol::StoredMessageProtocol(in, tokens[1], type, seqid)), out, connectionContext); } else { // Unknown service. throw protocol_error(in, out, name, seqid, "Unknown service: " + tokens[0] + ". Did you forget to call registerProcessor()?"); } } else if (tokens.size() == 1) { if (defaultProcessor) { // non-multiplexed client forwards to default processor return defaultProcessor ->process(std::shared_ptr( new protocol::StoredMessageProtocol(in, tokens[0], type, seqid)), out, connectionContext); } else { throw protocol_error(in, out, name, seqid, "Non-multiplexed client request dropped. " "Did you forget to call defaultProcessor()?"); } } else { throw protocol_error(in, out, name, seqid, "Wrong number of tokens."); } } private: /** Map of service processor objects, indexed by service names. */ services_t services; //! If a non-multi client requests something, it goes to the //! default processor (if one is defined) for backwards compatibility. std::shared_ptr defaultProcessor; }; } } #endif // THRIFT_TMULTIPLEXEDPROCESSOR_H_ thrift-0.19.0/lib/cpp/src/thrift/TProcessor.h0000644000000000000000000001520214303740367021001 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TPROCESSOR_H_ #define _THRIFT_TPROCESSOR_H_ 1 #include #include namespace apache { namespace thrift { /** * Virtual interface class that can handle events from the processor. To * use this you should subclass it and implement the methods that you care * about. Your subclass can also store local data that you may care about, * such as additional "arguments" to these methods (stored in the object * instance's state). */ class TProcessorEventHandler { public: virtual ~TProcessorEventHandler() = default; /** * Called before calling other callback methods. * Expected to return some sort of context object. * The return value is passed to all other callbacks * for that function invocation. */ virtual void* getContext(const char* fn_name, void* serverContext) { (void)fn_name; (void)serverContext; return nullptr; } /** * Expected to free resources associated with a context. */ virtual void freeContext(void* ctx, const char* fn_name) { (void)ctx; (void)fn_name; } /** * Called before reading arguments. */ virtual void preRead(void* ctx, const char* fn_name) { (void)ctx; (void)fn_name; } /** * Called between reading arguments and calling the handler. */ virtual void postRead(void* ctx, const char* fn_name, uint32_t bytes) { (void)ctx; (void)fn_name; (void)bytes; } /** * Called between calling the handler and writing the response. */ virtual void preWrite(void* ctx, const char* fn_name) { (void)ctx; (void)fn_name; } /** * Called after writing the response. */ virtual void postWrite(void* ctx, const char* fn_name, uint32_t bytes) { (void)ctx; (void)fn_name; (void)bytes; } /** * Called when an async function call completes successfully. */ virtual void asyncComplete(void* ctx, const char* fn_name) { (void)ctx; (void)fn_name; } /** * Called if the handler throws an undeclared exception. */ virtual void handlerError(void* ctx, const char* fn_name) { (void)ctx; (void)fn_name; } protected: TProcessorEventHandler() = default; }; /** * A helper class used by the generated code to free each context. */ class TProcessorContextFreer { public: TProcessorContextFreer(TProcessorEventHandler* handler, void* context, const char* method) : handler_(handler), context_(context), method_(method) {} ~TProcessorContextFreer() { if (handler_ != nullptr) handler_->freeContext(context_, method_); } void unregister() { handler_ = nullptr; } private: apache::thrift::TProcessorEventHandler* handler_; void* context_; const char* method_; }; /** * A processor is a generic object that acts upon two streams of data, one * an input and the other an output. The definition of this object is loose, * though the typical case is for some sort of server that either generates * responses to an input stream or forwards data from one pipe onto another. * */ class TProcessor { public: virtual ~TProcessor() = default; virtual bool process(std::shared_ptr in, std::shared_ptr out, void* connectionContext) = 0; bool process(std::shared_ptr io, void* connectionContext) { return process(io, io, connectionContext); } std::shared_ptr getEventHandler() const { return eventHandler_; } void setEventHandler(std::shared_ptr eventHandler) { eventHandler_ = eventHandler; } protected: TProcessor() = default; std::shared_ptr eventHandler_; }; /** * This is a helper class to allow std::shared_ptr to be used with handler * pointers returned by the generated handler factories. * * The handler factory classes generated by the thrift compiler return raw * pointers, and factory->releaseHandler() must be called when the handler is * no longer needed. * * A ReleaseHandler object can be instantiated and passed as the second * parameter to a shared_ptr, so that factory->releaseHandler() will be called * when the object is no longer needed, instead of deleting the pointer. */ template class ReleaseHandler { public: ReleaseHandler(const std::shared_ptr& handlerFactory) : handlerFactory_(handlerFactory) {} void operator()(typename HandlerFactory_::Handler* handler) { if (handler) { handlerFactory_->releaseHandler(handler); } } private: std::shared_ptr handlerFactory_; }; struct TConnectionInfo { // The input and output protocols std::shared_ptr input; std::shared_ptr output; // The underlying transport used for the connection // This is the transport that was returned by TServerTransport::accept(), // and it may be different than the transport pointed to by the input and // output protocols. std::shared_ptr transport; }; class TProcessorFactory { public: virtual ~TProcessorFactory() = default; /** * Get the TProcessor to use for a particular connection. * * This method is always invoked in the same thread that the connection was * accepted on. This generally means that this call does not need to be * thread safe, as it will always be invoked from a single thread. */ virtual std::shared_ptr getProcessor(const TConnectionInfo& connInfo) = 0; }; class TSingletonProcessorFactory : public TProcessorFactory { public: TSingletonProcessorFactory(std::shared_ptr processor) : processor_(processor) {} std::shared_ptr getProcessor(const TConnectionInfo&) override { return processor_; } private: std::shared_ptr processor_; }; } } // apache::thrift #endif // #ifndef _THRIFT_TPROCESSOR_H_ thrift-0.19.0/lib/cpp/src/thrift/TLogging.h0000644000000000000000000002427514303740367020422 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TLOGGING_H_ #define _THRIFT_TLOGGING_H_ 1 #include /** * Contains utility macros for debugging and logging. * */ #include #ifdef HAVE_STDINT_H #include #endif /** * T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined * T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on */ #define T_GLOBAL_DEBUGGING_LEVEL 0 /** * T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined * T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on */ #define T_GLOBAL_LOGGING_LEVEL 1 /** * Standard wrapper around fprintf what will prefix the file name and line * number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is * turned on or off. * * @param format_string */ #if T_GLOBAL_DEBUGGING_LEVEL > 0 #define T_DEBUG(format_string, ...) \ if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ fprintf(stderr, "[%s,%d] " format_string " \n", __FILE__, __LINE__, ##__VA_ARGS__); \ } #else #define T_DEBUG(format_string, ...) #endif /** * analogous to T_DEBUG but also prints the time * * @param string format_string input: printf style format string */ #if T_GLOBAL_DEBUGGING_LEVEL > 0 #define T_DEBUG_T(format_string, ...) \ { \ if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ time_t now; \ char dbgtime[26]; \ time(&now); \ THRIFT_CTIME_R(&now, dbgtime); \ dbgtime[24] = '\0'; \ fprintf(stderr, \ "[%s,%d] [%s] " format_string " \n", \ __FILE__, \ __LINE__, \ dbgtime, \ ##__VA_ARGS__); \ } \ } #else #define T_DEBUG_T(format_string, ...) #endif /** * analogous to T_DEBUG but uses input level to determine whether or not the string * should be logged. * * @param int level: specified debug level * @param string format_string input: format string */ #define T_DEBUG_L(level, format_string, ...) \ if ((level) > 0) { \ fprintf(stderr, "[%s,%d] " format_string " \n", __FILE__, __LINE__, ##__VA_ARGS__); \ } /** * Explicit error logging. Prints time, file name and line number * * @param string format_string input: printf style format string */ #define T_ERROR(format_string, ...) \ { \ time_t now; \ char dbgtime[26]; \ time(&now); \ THRIFT_CTIME_R(&now, dbgtime); \ dbgtime[24] = '\0'; \ fprintf(stderr, \ "[%s,%d] [%s] ERROR: " format_string " \n", \ __FILE__, \ __LINE__, \ dbgtime, \ ##__VA_ARGS__); \ } /** * Analogous to T_ERROR, additionally aborting the process. * WARNING: macro calls abort(), ending program execution * * @param string format_string input: printf style format string */ #define T_ERROR_ABORT(format_string, ...) \ { \ time_t now; \ char dbgtime[26]; \ time(&now); \ THRIFT_CTIME_R(&now, dbgtime); \ dbgtime[24] = '\0'; \ fprintf(stderr, \ "[%s,%d] [%s] ERROR: Going to abort " format_string " \n", \ __FILE__, \ __LINE__, \ dbgtime, \ ##__VA_ARGS__); \ exit(1); \ } /** * Log input message * * @param string format_string input: printf style format string */ #if T_GLOBAL_LOGGING_LEVEL > 0 #define T_LOG_OPER(format_string, ...) \ { \ if (T_GLOBAL_LOGGING_LEVEL > 0) { \ time_t now; \ char dbgtime[26]; \ time(&now); \ THRIFT_CTIME_R(&now, dbgtime); \ dbgtime[24] = '\0'; \ fprintf(stderr, "[%s] " format_string " \n", dbgtime, ##__VA_ARGS__); \ } \ } #else #define T_LOG_OPER(format_string, ...) #endif /** * T_GLOBAL_DEBUG_VIRTUAL = 0 or unset: normal operation, * virtual call debug messages disabled * T_GLOBAL_DEBUG_VIRTUAL = 1: log a debug messages whenever an * avoidable virtual call is made * T_GLOBAL_DEBUG_VIRTUAL = 2: record detailed info that can be * printed by calling * apache::thrift::profile_print_info() */ #if T_GLOBAL_DEBUG_VIRTUAL > 1 #define T_VIRTUAL_CALL() ::apache::thrift::profile_virtual_call(typeid(*this)) #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \ do { \ if (!(specific_prot)) { \ ::apache::thrift::profile_generic_protocol(typeid(*template_class), typeid(*generic_prot)); \ } \ } while (0) #elif T_GLOBAL_DEBUG_VIRTUAL == 1 #define T_VIRTUAL_CALL() fprintf(stderr, "[%s,%d] virtual call\n", __FILE__, __LINE__) #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \ do { \ if (!(specific_prot)) { \ fprintf(stderr, "[%s,%d] failed to cast to specific protocol type\n", __FILE__, __LINE__); \ } \ } while (0) #else #define T_VIRTUAL_CALL() #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) #endif #endif // #ifndef _THRIFT_TLOGGING_H_ thrift-0.19.0/lib/cpp/src/thrift/TDispatchProcessor.h0000644000000000000000000001203314303740367022460 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TDISPATCHPROCESSOR_H_ #define _THRIFT_TDISPATCHPROCESSOR_H_ 1 #include namespace apache { namespace thrift { /** * TDispatchProcessor is a helper class to parse the message header then call * another function to dispatch based on the function name. * * Subclasses must implement dispatchCall() to dispatch on the function name. */ template class TDispatchProcessorT : public TProcessor { public: bool process(std::shared_ptr in, std::shared_ptr out, void* connectionContext) override { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); // Try to dynamic cast to the template protocol type auto* specificIn = dynamic_cast(inRaw); auto* specificOut = dynamic_cast(outRaw); if (specificIn && specificOut) { return processFast(specificIn, specificOut, connectionContext); } // Log the fact that we have to use the slow path T_GENERIC_PROTOCOL(this, inRaw, specificIn); T_GENERIC_PROTOCOL(this, outRaw, specificOut); std::string fname; protocol::TMessageType mtype; int32_t seqid; inRaw->readMessageBegin(fname, mtype, seqid); // If this doesn't look like a valid call, log an error and return false so // that the server will close the connection. // // (The old generated processor code used to try to skip a T_STRUCT and // continue. However, that seems unsafe.) if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { GlobalOutput.printf("received invalid message type %d from client", mtype); return false; } return this->dispatchCall(inRaw, outRaw, fname, seqid, connectionContext); } protected: bool processFast(Protocol_* in, Protocol_* out, void* connectionContext) { std::string fname; protocol::TMessageType mtype; int32_t seqid; in->readMessageBegin(fname, mtype, seqid); if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { GlobalOutput.printf("received invalid message type %d from client", mtype); return false; } return this->dispatchCallTemplated(in, out, fname, seqid, connectionContext); } /** * dispatchCall() methods must be implemented by subclasses */ virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in, apache::thrift::protocol::TProtocol* out, const std::string& fname, int32_t seqid, void* callContext) = 0; virtual bool dispatchCallTemplated(Protocol_* in, Protocol_* out, const std::string& fname, int32_t seqid, void* callContext) = 0; }; /** * Non-templatized version of TDispatchProcessor, that doesn't bother trying to * perform a dynamic_cast. */ class TDispatchProcessor : public TProcessor { public: bool process(std::shared_ptr in, std::shared_ptr out, void* connectionContext) override { std::string fname; protocol::TMessageType mtype; int32_t seqid; in->readMessageBegin(fname, mtype, seqid); if (mtype != protocol::T_CALL && mtype != protocol::T_ONEWAY) { GlobalOutput.printf("received invalid message type %d from client", mtype); return false; } return dispatchCall(in.get(), out.get(), fname, seqid, connectionContext); } protected: virtual bool dispatchCall(apache::thrift::protocol::TProtocol* in, apache::thrift::protocol::TProtocol* out, const std::string& fname, int32_t seqid, void* callContext) = 0; }; // Specialize TDispatchProcessorT for TProtocol and TDummyProtocol just to use // the generic TDispatchProcessor. template <> class TDispatchProcessorT : public TDispatchProcessor {}; template <> class TDispatchProcessorT : public TDispatchProcessor {}; } } // apache::thrift #endif // _THRIFT_TDISPATCHPROCESSOR_H_ thrift-0.19.0/lib/cpp/src/thrift/TNonCopyable.h0000644000000000000000000000236014303740367021234 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef TNONCOPYABLE_H #define TNONCOPYABLE_H /** * @brief A simple non-copyable base class pattern. Derive from TNonCopyable to * make a class non-copyable and prohibit assignment and copy-construction. */ namespace apache { namespace thrift { class TNonCopyable { protected: TNonCopyable() = default; ~TNonCopyable() = default; TNonCopyable(const TNonCopyable&) = delete; TNonCopyable& operator=(const TNonCopyable&) = delete; }; } } #endif thrift-0.19.0/lib/cpp/src/thrift/VirtualProfiling.cpp0000644000000000000000000003065014303740367022535 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include // Do nothing if virtual call profiling is not enabled #if T_GLOBAL_DEBUG_VIRTUAL > 1 // TODO: This code only works with g++ (since we rely on the fact // that all std::type_info instances referring to a particular type // always return the exact same pointer value from name().) #ifndef __GNUG__ #error "Thrift virtual function profiling currently only works with gcc" #endif // !__GNUG__ // TODO: We also require glibc for the backtrace() and backtrace_symbols() // functions. #ifndef __GLIBC__ #error "Thrift virtual function profiling currently requires glibc" #endif // !__GLIBC__ #include #include #include #include namespace apache { namespace thrift { using ::apache::thrift::concurrency::Mutex; using ::apache::thrift::concurrency::Guard; static const unsigned int MAX_STACK_DEPTH = 15; /** * A stack trace */ class Backtrace { public: Backtrace(int skip = 0); Backtrace(Backtrace const& bt); void operator=(Backtrace const& bt) { numCallers_ = bt.numCallers_; if (numCallers_ >= 0) { memcpy(callers_, bt.callers_, numCallers_ * sizeof(void*)); } } bool operator==(Backtrace const& bt) const { return (cmp(bt) == 0); } size_t hash() const { intptr_t ret = 0; for (int n = 0; n < numCallers_; ++n) { ret ^= reinterpret_cast(callers_[n]); } return static_cast(ret); } int cmp(Backtrace const& bt) const { int depth_diff = (numCallers_ - bt.numCallers_); if (depth_diff != 0) { return depth_diff; } for (int n = 0; n < numCallers_; ++n) { int diff = reinterpret_cast(callers_[n]) - reinterpret_cast(bt.callers_[n]); if (diff != 0) { return diff; } } return 0; } void print(FILE* f, int indent = 0, int start = 0) const { char** strings = backtrace_symbols(callers_, numCallers_); if (strings) { start += skip_; if (start < 0) { start = 0; } for (int n = start; n < numCallers_; ++n) { fprintf(f, "%*s#%-2d %s\n", indent, "", n, strings[n]); } free(strings); } else { fprintf(f, "%*s\n", indent, ""); } } int getDepth() const { return numCallers_ - skip_; } void* getFrame(int index) const { int adjusted_index = index + skip_; if (adjusted_index < 0 || adjusted_index >= numCallers_) { return nullptr; } return callers_[adjusted_index]; } private: void* callers_[MAX_STACK_DEPTH]; int numCallers_; int skip_; }; // Define the constructors non-inline, so they consistently add a single // frame to the stack trace, regardless of whether optimization is enabled Backtrace::Backtrace(int skip) : skip_(skip + 1) // ignore the constructor itself { numCallers_ = backtrace(callers_, MAX_STACK_DEPTH); if (skip_ > numCallers_) { skip_ = numCallers_; } } Backtrace::Backtrace(Backtrace const& bt) : numCallers_(bt.numCallers_), skip_(bt.skip_) { if (numCallers_ >= 0) { memcpy(callers_, bt.callers_, numCallers_ * sizeof(void*)); } } /** * A backtrace, plus one or two type names */ class Key { public: class Hash { public: size_t operator()(Key const& k) const { return k.hash(); } }; Key(const Backtrace* bt, const std::type_info& type_info) : backtrace_(bt), typeName1_(type_info.name()), typeName2_(nullptr) {} Key(const Backtrace* bt, const std::type_info& type_info1, const std::type_info& type_info2) : backtrace_(bt), typeName1_(type_info1.name()), typeName2_(type_info2.name()) {} Key(const Key& k) : backtrace_(k.backtrace_), typeName1_(k.typeName1_), typeName2_(k.typeName2_) {} void operator=(const Key& k) { backtrace_ = k.backtrace_; typeName1_ = k.typeName1_; typeName2_ = k.typeName2_; } const Backtrace* getBacktrace() const { return backtrace_; } const char* getTypeName() const { return typeName1_; } const char* getTypeName2() const { return typeName2_; } void makePersistent() { // Copy the Backtrace object backtrace_ = new Backtrace(*backtrace_); // NOTE: We don't copy the type name. // The GNU libstdc++ implementation of type_info::name() returns a value // that will be valid for the lifetime of the program. (Although the C++ // standard doesn't guarantee this will be true on all implementations.) } /** * Clean up memory allocated by makePersistent() * * Should only be invoked if makePersistent() has previously been called. * The Key should no longer be used after cleanup() is called. */ void cleanup() { delete backtrace_; backtrace_ = nullptr; } int cmp(const Key& k) const { int ret = backtrace_->cmp(*k.backtrace_); if (ret != 0) { return ret; } // NOTE: We compare just the name pointers. // With GNU libstdc++, every type_info object for the same type points to // exactly the same name string. (Although this isn't guaranteed by the // C++ standard.) ret = k.typeName1_ - typeName1_; if (ret != 0) { return ret; } return k.typeName2_ - typeName2_; } bool operator==(const Key& k) const { return cmp(k) == 0; } size_t hash() const { // NOTE: As above, we just use the name pointer value. // Works with GNU libstdc++, but not guaranteed to be correct on all // implementations. return backtrace_->hash() ^ reinterpret_cast(typeName1_) ^ reinterpret_cast(typeName2_); } private: const Backtrace* backtrace_; const char* typeName1_; const char* typeName2_; }; /** * A functor that determines which of two BacktraceMap entries * has a higher count. */ class CountGreater { public: bool operator()(std::pair bt1, std::pair bt2) const { return bt1.second > bt2.second; } }; typedef __gnu_cxx::hash_map BacktraceMap; /** * A map describing how many times T_VIRTUAL_CALL() has been invoked. */ BacktraceMap virtual_calls; Mutex virtual_calls_mutex; /** * A map describing how many times T_GENERIC_PROTOCOL() has been invoked. */ BacktraceMap generic_calls; Mutex generic_calls_mutex; void _record_backtrace(BacktraceMap* map, const Mutex& mutex, Key* k) { Guard guard(mutex); BacktraceMap::iterator it = map->find(*k); if (it == map->end()) { k->makePersistent(); map->insert(std::make_pair(*k, 1)); } else { // increment the count // NOTE: we could assert if it->second is 0 afterwards, since that would // mean we've wrapped. ++(it->second); } } /** * Record an unnecessary virtual function call. * * This method is invoked by the T_VIRTUAL_CALL() macro. */ void profile_virtual_call(const std::type_info& type) { int const skip = 1; // ignore this frame Backtrace bt(skip); Key k(&bt, type); _record_backtrace(&virtual_calls, virtual_calls_mutex, &k); } /** * Record a call to a template processor with a protocol that is not the one * specified in the template parameter. * * This method is invoked by the T_GENERIC_PROTOCOL() macro. */ void profile_generic_protocol(const std::type_info& template_type, const std::type_info& prot_type) { int const skip = 1; // ignore this frame Backtrace bt(skip); Key k(&bt, template_type, prot_type); _record_backtrace(&generic_calls, generic_calls_mutex, &k); } /** * Print the recorded profiling information to the specified file. */ void profile_print_info(FILE* f) { typedef std::vector > BacktraceVector; CountGreater is_greater; // Grab both locks for the duration of the print operation, // to ensure the output is a consistent snapshot of a single point in time Guard generic_calls_guard(generic_calls_mutex); Guard virtual_calls_guard(virtual_calls_mutex); // print the info from generic_calls, sorted by frequency // // We print the generic_calls info ahead of virtual_calls, since it is more // useful in some cases. All T_GENERIC_PROTOCOL calls can be eliminated // from most programs. Not all T_VIRTUAL_CALLs will be eliminated by // converting to templates. BacktraceVector gp_sorted(generic_calls.begin(), generic_calls.end()); std::sort(gp_sorted.begin(), gp_sorted.end(), is_greater); for (BacktraceVector::const_iterator it = gp_sorted.begin(); it != gp_sorted.end(); ++it) { Key const& key = it->first; size_t const count = it->second; fprintf(f, "T_GENERIC_PROTOCOL: %zu calls to %s with a %s:\n", count, key.getTypeName(), key.getTypeName2()); key.getBacktrace()->print(f, 2); fprintf(f, "\n"); } // print the info from virtual_calls, sorted by frequency BacktraceVector vc_sorted(virtual_calls.begin(), virtual_calls.end()); std::sort(vc_sorted.begin(), vc_sorted.end(), is_greater); for (BacktraceVector::const_iterator it = vc_sorted.begin(); it != vc_sorted.end(); ++it) { Key const& key = it->first; size_t const count = it->second; fprintf(f, "T_VIRTUAL_CALL: %zu calls on %s:\n", count, key.getTypeName()); key.getBacktrace()->print(f, 2); fprintf(f, "\n"); } } /** * Print the recorded profiling information to stdout. */ void profile_print_info() { profile_print_info(stdout); } /** * Write a BacktraceMap as Google CPU profiler binary data. */ static void profile_write_pprof_file(FILE* f, BacktraceMap const& map) { // Write the header uintptr_t header[5] = {0, 3, 0, 0, 0}; fwrite(&header, sizeof(header), 1, f); // Write the profile records for (BacktraceMap::const_iterator it = map.begin(); it != map.end(); ++it) { uintptr_t count = it->second; fwrite(&count, sizeof(count), 1, f); Backtrace const* bt = it->first.getBacktrace(); uintptr_t num_pcs = bt->getDepth(); fwrite(&num_pcs, sizeof(num_pcs), 1, f); for (uintptr_t n = 0; n < num_pcs; ++n) { void* pc = bt->getFrame(n); fwrite(&pc, sizeof(pc), 1, f); } } // Write the trailer uintptr_t trailer[3] = {0, 1, 0}; fwrite(&trailer, sizeof(trailer), 1, f); // Write /proc/self/maps // TODO(simpkins): This only works on linux FILE* proc_maps = fopen("/proc/self/maps", "r"); if (proc_maps) { uint8_t buf[4096]; while (true) { size_t bytes_read = fread(buf, 1, sizeof(buf), proc_maps); if (bytes_read == 0) { break; } fwrite(buf, 1, bytes_read, f); } fclose(proc_maps); } } /** * Write the recorded profiling information as pprof files. * * This writes the information using the Google CPU profiler binary data * format, so it can be analyzed with pprof. Note that information about the * protocol/transport data types cannot be stored in this file format. * * See http://code.google.com/p/google-perftools/ for more details. * * @param gen_calls_f The information about calls to * profile_generic_protocol() will be written to this * file. * @param virtual_calls_f The information about calls to * profile_virtual_call() will be written to this file. */ void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f) { typedef std::vector > BacktraceVector; CountGreater is_greater; // Grab both locks for the duration of the print operation, // to ensure the output is a consistent snapshot of a single point in time Guard generic_calls_guard(generic_calls_mutex); Guard virtual_calls_guard(virtual_calls_mutex); // write the info from generic_calls profile_write_pprof_file(gen_calls_f, generic_calls); // write the info from virtual_calls profile_write_pprof_file(virtual_calls_f, virtual_calls); } } } // apache::thrift #endif // T_GLOBAL_PROFILE_VIRTUAL > 0 thrift-0.19.0/lib/cpp/src/thrift/TOutput.cpp0000644000000000000000000001004114370300523020637 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #ifdef _WIN32 #include #endif namespace apache { namespace thrift { THRIFT_EXPORT TOutput GlobalOutput; TOutput::TOutput() : f_(&errorTimeWrapper) {} void TOutput::printf(const char* message, ...) { #ifndef THRIFT_SQUELCH_CONSOLE_OUTPUT // Try to reduce heap usage, even if printf is called rarely. static const int STACK_BUF_SIZE = 256; char stack_buf[STACK_BUF_SIZE]; va_list ap; #ifdef _MSC_VER va_start(ap, message); int need = _vscprintf(message, ap); va_end(ap); if (need < STACK_BUF_SIZE) { va_start(ap, message); vsnprintf_s(stack_buf, STACK_BUF_SIZE, _TRUNCATE, message, ap); va_end(ap); f_(stack_buf); return; } #else va_start(ap, message); int need = vsnprintf(stack_buf, STACK_BUF_SIZE, message, ap); va_end(ap); if (need < STACK_BUF_SIZE) { f_(stack_buf); return; } #endif char* heap_buf = (char*)malloc((need + 1) * sizeof(char)); if (heap_buf == nullptr) { #ifdef _MSC_VER va_start(ap, message); vsnprintf_s(stack_buf, STACK_BUF_SIZE, _TRUNCATE, message, ap); va_end(ap); #endif // Malloc failed. We might as well print the stack buffer. f_(stack_buf); return; } va_start(ap, message); int rval = vsnprintf(heap_buf, need + 1, message, ap); va_end(ap); // TODO(shigin): inform user if (rval != -1) { f_(heap_buf); } free(heap_buf); #endif } void TOutput::errorTimeWrapper(const char* msg) { #ifndef THRIFT_SQUELCH_CONSOLE_OUTPUT time_t now; char dbgtime[26]; time(&now); THRIFT_CTIME_R(&now, dbgtime); dbgtime[24] = 0; fprintf(stderr, "Thrift: %s %s\n", dbgtime, msg); #endif } void TOutput::perror(const char* message, int errno_copy) { std::string out = message + std::string(": ") + strerror_s(errno_copy); f_(out.c_str()); } std::string TOutput::strerror_s(int errno_copy) { #ifdef __ZEPHYR__ return std::string(strerror(errno_copy)); #else char b_errbuf[1024] = {'\0'}; #ifdef HAVE_STRERROR_R #ifdef STRERROR_R_CHAR_P char* b_error = ::strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); #else // STRERROR_R_CHAR_P char* b_error = b_errbuf; int rv = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); if (rv == -1) { // strerror_r failed. omgwtfbbq. return "XSI-compliant strerror_r() failed with errno = " + to_string(errno_copy); } #endif // STRERROR_R_CHAR_P #else // HAVE_STRERROR_R #ifdef _WIN32 const size_t size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errno_copy, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), b_errbuf, sizeof(b_errbuf), nullptr); if (size > 2 && b_errbuf[size-2] == '\r' && b_errbuf[size-1] == '\n') { b_errbuf[size-2] = '\0'; b_errbuf[size-1] = '\0'; } #else // _WIN32 ::strerror_s(b_errbuf, sizeof(b_errbuf), errno_copy); #endif // _WIN32 char* b_error = b_errbuf; #endif // HAVE_STRERROR_R // Can anyone prove that explicit cast is probably not necessary // to ensure that the string object is constructed before // b_error becomes invalid? return std::string(b_error); #endif // __ZEPHYR__ } } } // apache::thrift thrift-0.19.0/lib/cpp/src/thrift/Thrift.h0000644000000000000000000000632614303740367020145 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_THRIFT_H_ #define _THRIFT_THRIFT_H_ 1 #include #include #include #include #include #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif #include #include #include #include #include #include #include #include #include #define THRIFT_UNUSED_VARIABLE(x) ((void)(x)) namespace apache { namespace thrift { class TEnumIterator : public std::iterator > { public: TEnumIterator(int n, int* enums, const char** names) : ii_(0), n_(n), enums_(enums), names_(names) {} int operator++() { return ++ii_; } bool operator!=(const TEnumIterator& end) { THRIFT_UNUSED_VARIABLE(end); assert(end.n_ == -1); return (ii_ != n_); } std::pair operator*() const { return std::make_pair(enums_[ii_], names_[ii_]); } private: int ii_; const int n_; int* enums_; const char** names_; }; class TException : public std::exception { public: TException() : message_() {} TException(const std::string& message) : message_(message) {} virtual ~TException() noexcept override = default; const char* what() const noexcept override { if (message_.empty()) { return "Default TException."; } else { return message_.c_str(); } } protected: std::string message_; }; class TDelayedException { public: template static TDelayedException* delayException(const E& e); virtual void throw_it() = 0; virtual ~TDelayedException() = default; }; template class TExceptionWrapper : public TDelayedException { public: TExceptionWrapper(const E& e) : e_(e) {} void throw_it() override { E temp(e_); delete this; throw temp; } private: E e_; }; template TDelayedException* TDelayedException::delayException(const E& e) { return new TExceptionWrapper(e); } #if T_GLOBAL_DEBUG_VIRTUAL > 1 void profile_virtual_call(const std::type_info& info); void profile_generic_protocol(const std::type_info& template_type, const std::type_info& prot_type); void profile_print_info(FILE* f); void profile_print_info(); void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f); #endif } } // apache::thrift #endif // #ifndef _THRIFT_THRIFT_H_ thrift-0.19.0/lib/cpp/libthrift.vcxproj0000644000000000000000000005037214452237057020053 0ustar00rootroot00000000000000 Debug-mt Win32 Debug-mt x64 Debug Win32 Debug x64 Release-mt Win32 Release-mt x64 Release Win32 Release x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F} Win32Proj thrift libthrift StaticLibrary true MultiByte v140 StaticLibrary true MultiByte v140 StaticLibrary true MultiByte v140 StaticLibrary true MultiByte v140 StaticLibrary false true MultiByte v140 StaticLibrary false true MultiByte v140 StaticLibrary false true MultiByte v140 StaticLibrary false true MultiByte v140 $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(OPENSSL_ROOT_DIR)\include\;$(IncludePath) NotUsing Level3 Disabled HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthrift.pdb MultiThreadedDebugDLL Windows true NotUsing Level3 Disabled HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthrift.pdb MultiThreadedDebugDll Windows true NotUsing Level3 Disabled HAVE_CONFIG_H=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDebugDll Windows true NotUsing Level3 Disabled HAVE_CONFIG_H=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDebugDll Windows true Level3 NotUsing MaxSpeed true true HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthrift.pdb MultiThreadedDll Windows true true true Level3 NotUsing MaxSpeed true true HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthrift.pdb MultiThreadedDll Windows true true true Level3 NotUsing MaxSpeed true true HAVE_CONFIG_H=1;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDll Windows true true true Level3 NotUsing MaxSpeed true true HAVE_CONFIG_H=1;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDll Windows true true true thrift-0.19.0/lib/cpp/README.md0000644000000000000000000002636214303740367015726 0ustar00rootroot00000000000000Thrift C++ Software Library # License Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. # Using Thrift with C++ The Thrift C++ libraries are built using the GNU tools. Follow the instructions in the top-level README.md In case you do not want to open another README.md file, do this thrift src: ./bootstrap.sh ./configure (--with-boost=/usr/local) make sudo make install Thrift is divided into two libraries. * libthrift - The core Thrift library contains all the core Thrift code. This requires openssl, pthreads, and librt. * libthriftnb - This library contains the Thrift nonblocking server, which uses libevent. To link this library you will also need to link libevent. ## Linking Against Thrift After you build and install Thrift the libraries are installed to /usr/local/lib by default. Make sure this is in your LDPATH. On Linux, the best way to do this is to ensure that /usr/local/lib is in your /etc/ld.so.conf and then run /sbin/ldconfig. Depending upon whether you are linking dynamically or statically and how your build environment it set up, you may need to include additional libraries when linking against thrift, such as librt and/or libpthread. If you are using libthriftnb you will also need libevent. ## Dependencies C++11 is required at a minimum. C++03/C++98 are not supported after version 0.12.0. Boost is required to run the C++ unit tests. It is not necessary to link against the runtime library. libevent (for libthriftnb only) - most linux distributions have dev packages for this: http://monkey.org/~provos/libevent/ # Using Thrift with C++ on Windows Both the autoconf and cmake build systems are able to automatically detect many system configurations without the need to specify library locations, however if you run into problems or want to redirect thrift to build and link against your own provided third party libraries: BOOST_ROOT : For boost, e.g. D:\boost_1_55_0 OPENSSL_ROOT_DIR : For OpenSSL, e.g. D:\OpenSSL-Win32 only required by libthriftnb: LIBEVENT_ROOT_DIR : For Libevent e.g. D:\libevent-2.0.21-stable See /3rdparty.user for more details. The same linking guidelines described above for libthriftnb apply to windows as well. ## Linking Against Thrift You need to link your project that uses thrift against all the thrift dependencies; in the case of libthrift, openssl, pthreads, and librt and for libthriftnb, libevent. In the project properties you must also set HAVE_CONFIG_H as force include the config header: "windows/config.h" ## Dependencies libevent (for libthriftnb only) http://monkey.org/~provos/libevent/ ## Windows version compatibility The Thrift library targets Windows 7 or latter versions. The supports for windows XP and Vista are avaiable until 0.12.0. ## Thrift and the VCPKG Package manager You can download and install thrift using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: git clone https://github.com/Microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install thrift The thrift port in vcpkg is kept up to date by Microsoft team members and community contributors. The Apache Thrift project is *not* responsible for the vcpkg port. Therefore, if the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. ## Named Pipes Named Pipe transport has been added in the TPipe and TPipeServer classes. This is currently Windows-only. Named pipe transport for *NIX has not been implemented. Domain sockets are a better choice for local IPC under non-Windows OS's. *NIX named pipes only support 1:1 client-server connection. # Thrift/SSL ## Scope This SSL only supports blocking mode socket I/O. It can only be used with TSimpleServer, TThreadedServer, and TThreadPoolServer. ## Implementation There are two main classes TSSLSocketFactory and TSSLSocket. Instances of TSSLSocket are always created from TSSLSocketFactory. ## How to use SSL APIs See the TestClient.cpp and TestServer.cpp files for examples. ### AccessManager (certificate validation) An example of certificate validation can be found in TestServer.cpp. AccessManager defines a callback interface. It has three callback methods: (a) Decision verify(const sockaddr_storage& sa); (b) Decision verify(const string& host, const char* name, int size); (c) Decision verify(const sockaddr_storage& sa, const char* data, int size); After SSL handshake completes, additional checks are conducted. Application is given the chance to decide whether or not to continue the conversation with the remote. Application is queried through the above three "verify" method. They are called at different points of the verification process. Decisions can be one of ALLOW, DENY, and SKIP. ALLOW and DENY means the conversation should be continued or disconnected, respectively. ALLOW and DENY decision stops the verification process. SKIP means there's no decision based on the given input, continue the verification process. First, (a) is called with the remote IP. It is called once at the beginning. "sa" is the IP address of the remote peer. Then, the certificate of remote peer is loaded. SubjectAltName extensions are extracted and sent to application for verification. When a DNS subjectAltName field is extracted, (b) is called. When an IP subjectAltName field is extracted, (c) is called. The "host" in (b) is the value from TSocket::getHost() if this is a client side socket, or TSocket::getPeerHost() if this is a server side socket. The reason is client side socket initiates the connection. TSocket::getHost() is the remote host name. On server side, the remote host name is unknown unless it's retrieved through TSocket::getPeerHost(). Either way, "host" should be the remote host name. Keep in mind, if TSocket::getPeerHost() failed, it would return the remote host name in numeric format. If all subjectAltName extensions were "skipped", the common name field would be checked. It is sent to application through (c), where "sa" is the remote IP address. "data" is the IP address extracted from subjectAltName IP extension, and "size" is the length of the extension data. If any of the above "verify" methods returned a decision ALLOW or DENY, the verification process would be stopped. If any of the above "verify" methods returned SKIP, that decision would be ignored and the verification process would move on till the last item is examined. At that point, if there's still no decision, the connection is terminated. Thread safety, an access manager should not store state information if it's to be used by many SSL sockets. ## SIGPIPE signal Applications running OpenSSL over network connections may crash if SIGPIPE is not ignored. This happens when they receive a connection reset by remote peer exception, which somehow triggers a SIGPIPE signal. If not handled, this signal would kill the application. ## How to run test client/server in SSL mode The server and client expects the followings from the directory /test/ - keys/server.crt - keys/server.key - keys/CA.pem The file names are hard coded in the source code. You need to create these certificates before you can run the test code in SSL mode. Make sure at least one of the followings is included in "keys/server.crt", - subjectAltName, DNS localhost - subjectAltName, IP 127.0.0.1 - common name, localhost Run within /test/ folder, ./cpp/TestServer --ssl & ./cpp/TestClient --ssl If "-h " is used to run client, the above "localhost" in the above keys/server.crt has to be replaced with that host name. ## TSSLSocketFactory::randomize() The default implementation of OpenSSLSocketFactory::randomize() simply calls OpenSSL's RAND_poll() when OpenSSL library is first initialized. The PRNG seed is key to the application security. This method should be overridden if it's not strong enough for you. # Deprecations ## 0.12.0 Support for C++03/C++98 was deprecated. Support for Boost at runtime was deprecated. # Breaking Changes ## 1.0.0 THRIFT-4720: The classes Monitor and TimerManager now use std::chrono::milliseconds for timeout, the methods and functions involving THRIFT_TIMESPEC and timeval have been removed, the related tests have been modified. Support for Windows XP/Vista has been dropped. Support for C++03/C++98 has been dropped. Use version 0.12.0 to support that language level. As a consequence, boost is no longer required as a runtime library depenedency, but is is still required to build the runtime library and to run the unit tests. We will work towards removing boost as a build dependency for folks who just want to build the runtime and not run the tests. This means the header thrift/stdcxx.h has been removed and anything that relied on it has been changed to directly use C++11 concepts. THRIFT-4730: The classes BoostThreadFactory, PosixThreadFactory, StdThreadFactory, and PlatformThreadFactory have been removed, and we will use a ThreadFactory based on C++11 (essentially StdThreadFactory was renamed ThreadFactory). THRIFT-4732: The CMake build options WITH_SHARED_LIBS and WITH_STATIC_LIBS are deprecated. The project no longer performs a side-by-side static and shared build; you tell CMake through BUILD_SHARED_LIBS whether to make shared or static libraries now. This is CMake standard behavior. THRIFT-4735: Qt4 support was removed. THRIFT-4762: Added `const` specifier to `TTransport::getOrigin()`. This changes its function signature. It's recommended to add the `override` specifier in implementations derived from `TTransport`. ## 0.11.0 Older versions of thrift depended on the classes which were used in thrift headers to define interfaces. Thrift now detects C++11 at build time and will prefer to use classes from C++11 instead. You can force the library to build with boost memory classes by defining the preprocessor macro `FORCE_BOOST_SMART_PTR`. (THRIFT-2221) In the pthread mutex implementation, the contention profiling code was enabled by default in all builds. This changed to be disabled by default. (THRIFT-4151) In older releases, if a TSSLSocketFactory's lifetime was not at least as long as the TSSLSockets it created, we silently reverted openssl to unsafe multithread behavior and so the results were undefined. Changes were made in 0.11.0 that cause either an assertion or a core instead of undefined behavior. The lifetime of a TSSLSocketFactory *must* be longer than any TSSLSocket that it creates, otherwise openssl will be cleaned up too early. If the static boolean is set to disable openssl initialization and cleanup and leave it up to the consuming application, this requirement is not needed. (THRIFT-4164) thrift-0.19.0/lib/cpp/coding_standards.md0000644000000000000000000000034514303740367020270 0ustar00rootroot00000000000000Please follow [General Coding Standards](/doc/coding_standards.md) * see .clang-format in root dir for settings of accepted format * clang-format (3.5 or newer) can be used to automaticaly reformat code ('make style' command) thrift-0.19.0/lib/cpp/test/0000755000000000000000000000000014472652651015422 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/test/RenderedDoubleConstantsTest.cpp0000644000000000000000000001541214303740367023544 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define EPSILON 0.0000001 #include #include #include #include "gen-cpp/DoubleConstantsTest_constants.h" using namespace thrift::test; #define BOOST_TEST_MODULE RenderedDoubleConstantsTest #include BOOST_AUTO_TEST_SUITE(RenderedDoubleConstantsTest) BOOST_AUTO_TEST_CASE(test_rendered_double_constants) { const double EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT = 1.0; const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT = -100.0; const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT = 9223372036854775807.0; const double EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT = -9223372036854775807.0; const double EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS = 3.14159265359; const double EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE = 1000000.1; const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE = -1000000.1; const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE = 1.7e+308; const double EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE = 9223372036854775816.43; const double EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE = -1.7e+308; const double EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE = -9223372036854775816.43; BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE, EPSILON); BOOST_CHECK_CLOSE( g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST, EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE, EPSILON); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_INT_CONSTANT_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_INT_CONSTANT).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_INT_CONSTANT).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGEST_INT_CONSTANT).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_SMALLEST_INT_CONSTANT).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_DOUBLE_WITH_MANY_DECIMALS).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_FRACTIONAL_DOUBLE).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_FRACTIONAL_DOUBLE).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_DOUBLE_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_DOUBLE).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_LARGE_FRACTIONAL_DOUBLE).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_SMALL_DOUBLE_TEST).hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_SMALL_DOUBLE).hash_code()); BOOST_CHECK( typeid(g_DoubleConstantsTest_constants.DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE_TEST) .hash_code() == typeid(EXPECTED_DOUBLE_ASSIGNED_TO_NEGATIVE_BUT_LARGE_FRACTIONAL_DOUBLE).hash_code()); } BOOST_AUTO_TEST_CASE(test_rendered_double_list) { const std::vector EXPECTED_DOUBLE_LIST{1.0,-100.0,100.0,9223372036854775807.0,-9223372036854775807.0, 3.14159265359,1000000.1,-1000000.1,1.7e+308,-1.7e+308,9223372036854775816.43,-9223372036854775816.43}; BOOST_CHECK_EQUAL(g_DoubleConstantsTest_constants.DOUBLE_LIST_TEST.size(), EXPECTED_DOUBLE_LIST.size()); for (unsigned int i = 0; i < EXPECTED_DOUBLE_LIST.size(); ++i) { BOOST_CHECK_CLOSE(g_DoubleConstantsTest_constants.DOUBLE_LIST_TEST[i], EXPECTED_DOUBLE_LIST[i], EPSILON); } } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/AnnotationTest.cpp0000644000000000000000000000403314303740367021073 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE AnnotationTest #include #include "gen-cpp/AnnotationTest_types.h" #include #include // Normally thrift generates ostream operators, however // with the annotation "cpp.customostream" one can tell the // compiler they are going to provide their own, and not // emit operator << or printTo(). std::ostream& operator<<(std::ostream& os, const ostr_custom& osc) { os << "{ bar = " << osc.bar << "; }"; return os; } BOOST_AUTO_TEST_SUITE(BOOST_TEST_MODULE) BOOST_AUTO_TEST_CASE(test_cpp_compiler_generated_ostream_operator) { ostr_default def; def.__set_bar(10); std::stringstream ssd; ssd << def; BOOST_CHECK_EQUAL(ssd.str(), "ostr_default(bar=10)"); } BOOST_AUTO_TEST_CASE(test_cpp_customostream_uses_consuming_application_definition) { ostr_custom cus; cus.__set_bar(10); std::stringstream csd; csd << cus; BOOST_CHECK_EQUAL(csd.str(), "{ bar = 10; }"); } /** * Disabled; see THRIFT-1567 - not sure what it is supposed to do BOOST_AUTO_TEST_CASE(test_cpp_type) { // Check that the "cpp.type" annotation changes "struct foo" to "DenseFoo" // This won't compile if the annotation is mishandled DenseFoo foo; foo.__set_bar(5); } */ BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/AllProtocolTests.tcc0000644000000000000000000001741014303740367021370 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_GENERICPROTOCOLTEST_TCC_ #define _THRIFT_TEST_GENERICPROTOCOLTEST_TCC_ 1 #include #include #include #include #include "GenericHelpers.h" using std::shared_ptr; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; #define ERR_LEN 512 extern char errorMessage[ERR_LEN]; template void testNaked(Val val) { shared_ptr transport(new TMemoryBuffer()); shared_ptr protocol(new TProto(transport)); GenericIO::write(protocol, val); Val out; GenericIO::read(protocol, out); if (out != val) { THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid naked test (type: %s)", ClassNames::getName()); throw TException(errorMessage); } } template void testField(const Val val) { shared_ptr transport(new TMemoryBuffer()); shared_ptr protocol(new TProto(transport)); protocol->writeStructBegin("test_struct"); protocol->writeFieldBegin("test_field", type, (int16_t)15); GenericIO::write(protocol, val); protocol->writeFieldEnd(); protocol->writeStructEnd(); std::string name; TType fieldType; int16_t fieldId; protocol->readStructBegin(name); protocol->readFieldBegin(name, fieldType, fieldId); if (fieldId != 15) { THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid ID (type: %s)", typeid(val).name()); throw TException(errorMessage); } if (fieldType != type) { THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid Field Type (type: %s)", typeid(val).name()); throw TException(errorMessage); } Val out; GenericIO::read(protocol, out); if (out != val) { THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid value read (type: %s)", typeid(val).name()); throw TException(errorMessage); } protocol->readFieldEnd(); protocol->readStructEnd(); } template void testMessage() { struct TMessage { const char* name; TMessageType type; int32_t seqid; } messages[] = {{"short message name", T_CALL, 0}, {"1", T_REPLY, 12345}, {"loooooooooooooooooooooooooooooooooong", T_EXCEPTION, 1 << 16}, {"one way push", T_ONEWAY, 12}, {"Janky", T_CALL, 0}}; const int messages_count = sizeof(messages) / sizeof(TMessage); for (int i = 0; i < messages_count; i++) { shared_ptr transport(new TMemoryBuffer()); shared_ptr protocol(new TProto(transport)); protocol->writeMessageBegin(messages[i].name, messages[i].type, messages[i].seqid); protocol->writeMessageEnd(); std::string name; TMessageType type; int32_t seqid; protocol->readMessageBegin(name, type, seqid); if (name != messages[i].name || type != messages[i].type || seqid != messages[i].seqid) { throw TException("readMessageBegin failed."); } } } template void testProtocol(const char* protoname) { try { testNaked((int8_t)123); for (int32_t i = 0; i < 128; i++) { testField((int8_t)i); testField((int8_t)-i); } testNaked((int16_t)0); testNaked((int16_t)1); testNaked((int16_t)15000); testNaked((int16_t)0x7fff); testNaked((int16_t)-1); testNaked((int16_t)-15000); testNaked((int16_t)-0x7fff); testNaked((std::numeric_limits::min)()); testNaked((std::numeric_limits::max)()); testField((int16_t)0); testField((int16_t)1); testField((int16_t)7); testField((int16_t)150); testField((int16_t)15000); testField((int16_t)0x7fff); testField((int16_t)-1); testField((int16_t)-7); testField((int16_t)-150); testField((int16_t)-15000); testField((int16_t)-0x7fff); testNaked(0); testNaked(1); testNaked(15000); testNaked(0xffff); testNaked(-1); testNaked(-15000); testNaked(-0xffff); testNaked((std::numeric_limits::min)()); testNaked((std::numeric_limits::max)()); testField(0); testField(1); testField(7); testField(150); testField(15000); testField(31337); testField(0xffff); testField(0xffffff); testField(-1); testField(-7); testField(-150); testField(-15000); testField(-0xffff); testField(-0xffffff); testNaked((std::numeric_limits::min)()); testNaked((std::numeric_limits::max)()); testNaked((std::numeric_limits::min)() + 10); testNaked((std::numeric_limits::max)() - 16); testNaked((std::numeric_limits::min)()); testNaked((std::numeric_limits::max)()); testNaked(0); for (int64_t i = 0; i < 62; i++) { testNaked(1LL << i); testNaked(-(1LL << i)); } testField(0); for (int i = 0; i < 62; i++) { testField(1LL << i); testField(-(1LL << i)); } testNaked(123.456); testNaked(""); testNaked("short"); testNaked("borderlinetiny"); testNaked("a bit longer than the smallest possible"); testNaked("\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA"); // kinda binary test testField(""); testField("short"); testField("borderlinetiny"); testField("a bit longer than the smallest possible"); testMessage(); printf("%s => OK\n", protoname); } catch (const TException &e) { THRIFT_SNPRINTF(errorMessage, ERR_LEN, "%s => Test FAILED: %s", protoname, e.what()); throw TException(errorMessage); } } #endif thrift-0.19.0/lib/cpp/test/TSocketInterruptTest.cpp0000644000000000000000000001261414303740367022256 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE TSocketInterruptTest #include #include #include #include #include #include #include using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using namespace apache::thrift; BOOST_AUTO_TEST_SUITE(TSocketInterruptTest) void readerWorker(std::shared_ptr tt, uint32_t expectedResult) { uint8_t buf[4]; BOOST_CHECK_EQUAL(expectedResult, tt->read(buf, 4)); } void readerWorkerMustThrow(std::shared_ptr tt) { try { uint8_t buf[4]; tt->read(buf, 4); BOOST_ERROR("should not have gotten here"); } catch (const TTransportException& tx) { BOOST_CHECK_EQUAL(TTransportException::INTERRUPTED, tx.getType()); } } BOOST_AUTO_TEST_CASE(test_interruptable_child_read) { TServerSocket sock1("localhost", 0); sock1.listen(); BOOST_CHECK(sock1.isOpen()); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); std::shared_ptr accepted = sock1.accept(); boost::thread readThread(std::bind(readerWorkerMustThrow, accepted)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(readThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren did not interrupt child read"); clientSock.close(); accepted->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_non_interruptable_child_read) { TServerSocket sock1("localhost", 0); sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior sock1.listen(); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); std::shared_ptr accepted = sock1.accept(); boost::thread readThread(std::bind(readerWorker, accepted, 0)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking here sock1.interruptChildren(); BOOST_CHECK_MESSAGE(!readThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren interrupted child read"); // only way to proceed is to have the client disconnect clientSock.close(); readThread.join(); accepted->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_cannot_change_after_listen) { TServerSocket sock1("localhost", 0); sock1.listen(); BOOST_CHECK_THROW(sock1.setInterruptableChildren(false), std::logic_error); sock1.close(); } void peekerWorker(std::shared_ptr tt, bool expectedResult) { BOOST_CHECK_EQUAL(expectedResult, tt->peek()); } BOOST_AUTO_TEST_CASE(test_interruptable_child_peek) { TServerSocket sock1("localhost", 0); sock1.listen(); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); std::shared_ptr accepted = sock1.accept(); // peek() will return false if child is interrupted boost::thread peekThread(std::bind(peekerWorker, accepted, false)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(peekThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren did not interrupt child peek"); clientSock.close(); accepted->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_non_interruptable_child_peek) { TServerSocket sock1("localhost", 0); sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior sock1.listen(); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); std::shared_ptr accepted = sock1.accept(); // peek() will return false when remote side is closed boost::thread peekThread(std::bind(peekerWorker, accepted, false)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(!peekThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren interrupted child peek"); // only way to proceed is to have the client disconnect clientSock.close(); peekThread.join(); accepted->close(); sock1.close(); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/OneWayHTTPTest.cpp0000644000000000000000000001647514303740367020700 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gen-cpp/OneWayService.h" BOOST_AUTO_TEST_SUITE(OneWayHTTPTest) using namespace apache::thrift; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TBinaryProtocol; using apache::thrift::protocol::TBinaryProtocolFactory; using apache::thrift::protocol::TJSONProtocol; using apache::thrift::protocol::TJSONProtocolFactory; using apache::thrift::server::TThreadedServer; using apache::thrift::server::TServerEventHandler; using apache::thrift::transport::TTransport; using apache::thrift::transport::THttpServer; using apache::thrift::transport::THttpServerTransportFactory; using apache::thrift::transport::THttpClient; using apache::thrift::transport::TBufferedTransport; using apache::thrift::transport::TBufferedTransportFactory; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransportException; using std::shared_ptr; using std::cout; using std::cerr; using std::endl; using std::string; namespace utf = boost::unit_test; // Define this env var to enable some logging (in case you need to debug) #undef ENABLE_STDERR_LOGGING class OneWayServiceHandler : public onewaytest::OneWayServiceIf { public: OneWayServiceHandler() = default; void roundTripRPC() override { #ifdef ENABLE_STDERR_LOGGING cerr << "roundTripRPC()" << endl; #endif } void oneWayRPC() override { #ifdef ENABLE_STDERR_LOGGING cerr << "oneWayRPC()" << std::endl ; #endif } }; class OneWayServiceCloneFactory : virtual public onewaytest::OneWayServiceIfFactory { public: ~OneWayServiceCloneFactory() override = default; onewaytest::OneWayServiceIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override { (void)connInfo ; return new OneWayServiceHandler; } void releaseHandler( onewaytest::OneWayServiceIf* handler) override { delete handler; } }; class RPC0ThreadClass { public: RPC0ThreadClass(TThreadedServer& server) : server_(server) { } // Constructor ~RPC0ThreadClass() = default; // Destructor void Run() { server_.serve() ; } TThreadedServer& server_ ; } ; using apache::thrift::concurrency::Monitor; using apache::thrift::concurrency::Mutex; using apache::thrift::concurrency::Synchronized; // copied from IntegrationTest class TServerReadyEventHandler : public TServerEventHandler, public Monitor { public: TServerReadyEventHandler() : isListening_(false), accepted_(0) {} ~TServerReadyEventHandler() override = default; void preServe() override { Synchronized sync(*this); isListening_ = true; notify(); } void* createContext(shared_ptr input, shared_ptr output) override { Synchronized sync(*this); ++accepted_; notify(); (void)input; (void)output; return nullptr; } bool isListening() const { return isListening_; } uint64_t acceptedCount() const { return accepted_; } private: bool isListening_; uint64_t accepted_; }; class TBlockableBufferedTransport : public TBufferedTransport { public: TBlockableBufferedTransport(std::shared_ptr transport) : TBufferedTransport(transport, 10240), blocked_(false) { } uint32_t write_buffer_length() { auto have_bytes = static_cast(wBase_ - wBuf_.get()); return have_bytes ; } void block() { blocked_ = true ; #ifdef ENABLE_STDERR_LOGGING cerr << "block flushing\n" ; #endif } void unblock() { blocked_ = false ; #ifdef ENABLE_STDERR_LOGGING cerr << "unblock flushing, buffer is\n<<" << std::string((char *)wBuf_.get(), write_buffer_length()) << ">>\n" ; #endif } void flush() override { if (blocked_) { #ifdef ENABLE_STDERR_LOGGING cerr << "flush was blocked\n" ; #endif return ; } TBufferedTransport::flush() ; } bool blocked_ ; } ; BOOST_AUTO_TEST_CASE( JSON_BufferedHTTP ) { std::shared_ptr ss = std::make_shared(0) ; TThreadedServer server( std::make_shared(std::make_shared()), ss, //port std::make_shared(), std::make_shared()); std::shared_ptr pEventHandler(new TServerReadyEventHandler) ; server.setServerEventHandler(pEventHandler); #ifdef ENABLE_STDERR_LOGGING cerr << "Starting the server...\n"; #endif RPC0ThreadClass t(server) ; boost::thread thread(&RPC0ThreadClass::Run, &t); { Synchronized sync(*(pEventHandler.get())); while (!pEventHandler->isListening()) { pEventHandler->wait(); } } int port = ss->getPort() ; #ifdef ENABLE_STDERR_LOGGING cerr << "port " << port << endl ; #endif { std::shared_ptr socket(new TSocket("localhost", port)); socket->setRecvTimeout(10000) ; // 1000msec should be enough std::shared_ptr blockable_transport(new TBlockableBufferedTransport(socket)); std::shared_ptr transport(new THttpClient(blockable_transport, "localhost", "/service")); std::shared_ptr protocol(new TJSONProtocol(transport)); onewaytest::OneWayServiceClient client(protocol); transport->open(); client.roundTripRPC(); blockable_transport->block() ; uint32_t size0 = blockable_transport->write_buffer_length() ; client.send_oneWayRPC() ; uint32_t size1 = blockable_transport->write_buffer_length() ; client.send_oneWayRPC() ; uint32_t size2 = blockable_transport->write_buffer_length() ; BOOST_CHECK((size1 - size0) == (size2 - size1)) ; blockable_transport->unblock() ; client.send_roundTripRPC() ; blockable_transport->flush() ; try { client.recv_roundTripRPC() ; } catch (const TTransportException &e) { BOOST_ERROR( "we should not get a transport exception -- this means we failed: " + std::string(e.what()) ) ; } transport->close(); } server.stop(); thread.join() ; #ifdef ENABLE_STDERR_LOGGING cerr << "finished.\n"; #endif } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/Makefile.am0000644000000000000000000002575714370300523017457 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/AnnotationTest_types.h \ gen-cpp/DebugProtoTest_types.h \ gen-cpp/EnumTest_types.h \ gen-cpp/OptionalRequiredTest_types.h \ gen-cpp/Recursive_types.h \ gen-cpp/ThriftTest_types.h \ gen-cpp/TypedefTest_types.h \ gen-cpp/ChildService.h \ gen-cpp/EmptyService.h \ gen-cpp/ParentService.h \ gen-cpp/OneWayTest_types.h \ gen-cpp/OneWayService.h \ gen-cpp/proc_types.h noinst_LTLIBRARIES = libtestgencpp.la libprocessortest.la nodist_libtestgencpp_la_SOURCES = \ gen-cpp/AnnotationTest_types.cpp \ gen-cpp/AnnotationTest_types.h \ gen-cpp/DebugProtoTest_types.cpp \ gen-cpp/DebugProtoTest_types.h \ gen-cpp/DoubleConstantsTest_constants.cpp \ gen-cpp/DoubleConstantsTest_constants.h \ gen-cpp/EnumTest_types.cpp \ gen-cpp/EnumTest_types.h \ gen-cpp/OptionalRequiredTest_types.cpp \ gen-cpp/OptionalRequiredTest_types.h \ gen-cpp/Recursive_types.cpp \ gen-cpp/Recursive_types.h \ gen-cpp/ThriftTest_types.cpp \ gen-cpp/ThriftTest_types.h \ gen-cpp/ThriftTest_constants.cpp \ gen-cpp/ThriftTest_constants.h \ gen-cpp/TypedefTest_types.cpp \ gen-cpp/TypedefTest_types.h \ gen-cpp/OneWayService.cpp \ gen-cpp/OneWayTest_types.h \ gen-cpp/OneWayService.h \ ThriftTest_extras.cpp \ DebugProtoTest_extras.cpp nodist_libprocessortest_la_SOURCES = \ gen-cpp/ChildService.cpp \ gen-cpp/ChildService.h \ gen-cpp/EmptyService.cpp \ gen-cpp/EmptyService.h \ gen-cpp/ParentService.cpp \ gen-cpp/ParentService.h \ gen-cpp/proc_types.cpp \ gen-cpp/proc_types.h ThriftTest_extras.o: gen-cpp/ThriftTest_types.h DebugProtoTest_extras.o: gen-cpp/DebugProtoTest_types.h libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la noinst_PROGRAMS = Benchmark \ concurrency_test Benchmark_SOURCES = \ Benchmark.cpp Benchmark_LDADD = libtestgencpp.la check_PROGRAMS = \ UnitTests \ TFDTransportTest \ TPipedTransportTest \ DebugProtoTest \ JSONProtoTest \ OptionalRequiredTest \ RecursiveTest \ SpecializationTest \ AllProtocolsTest \ TransportTest \ TInterruptTest \ TServerIntegrationTest \ SecurityTest \ SecurityFromBufferTest \ ZlibTest \ TFileTransportTest \ link_test \ OpenSSLManualInitTest \ EnumTest \ RenderedDoubleConstantsTest \ AnnotationTest if AMX_HAVE_LIBEVENT noinst_PROGRAMS += \ processor_test check_PROGRAMS += \ TNonblockingServerTest \ TNonblockingSSLServerTest endif TESTS_ENVIRONMENT= \ BOOST_TEST_LOG_SINK=tests.xml \ BOOST_TEST_LOG_LEVEL=test_suite \ BOOST_TEST_LOG_FORMAT=XML TESTS = \ $(check_PROGRAMS) UnitTests_SOURCES = \ UnitTestMain.cpp \ OneWayHTTPTest.cpp \ TMemoryBufferTest.cpp \ TBufferBaseTest.cpp \ Base64Test.cpp \ ToStringTest.cpp \ TypedefTest.cpp \ TServerSocketTest.cpp \ TServerTransportTest.cpp \ TTransportCheckThrow.h \ ThrifttReadCheckTests.cpp UnitTests_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) TInterruptTest_SOURCES = \ TSocketInterruptTest.cpp \ TSSLSocketInterruptTest.cpp TInterruptTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_CHRONO_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) TServerIntegrationTest_SOURCES = \ TServerIntegrationTest.cpp TServerIntegrationTest_LDADD = \ libtestgencpp.la \ libprocessortest.la \ $(BOOST_TEST_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) SecurityTest_SOURCES = \ SecurityTest.cpp SecurityTest_LDADD = \ libtestgencpp.la \ libprocessortest.la \ $(BOOST_TEST_LDADD) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) SecurityFromBufferTest_SOURCES = \ SecurityFromBufferTest.cpp SecurityFromBufferTest_LDADD = \ libtestgencpp.la \ libprocessortest.la \ $(BOOST_TEST_LDADD) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) TransportTest_SOURCES = \ TransportTest.cpp TransportTest_LDADD = \ libtestgencpp.la \ $(top_builddir)/lib/cpp/libthriftz.la \ $(BOOST_TEST_LDADD) \ -lz ZlibTest_SOURCES = \ ZlibTest.cpp ZlibTest_LDADD = \ libtestgencpp.la \ $(top_builddir)/lib/cpp/libthriftz.la \ $(BOOST_TEST_LDADD) \ -lz EnumTest_SOURCES = \ EnumTest.cpp EnumTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) RenderedDoubleConstantsTest_SOURCES = RenderedDoubleConstantsTest.cpp RenderedDoubleConstantsTest_LDADD = libtestgencpp.la $(BOOST_TEST_LDADD) AnnotationTest_SOURCES = \ AnnotationTest.cpp AnnotationTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) TFileTransportTest_SOURCES = \ TFileTransportTest.cpp TFileTransportTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # TFDTransportTest # TFDTransportTest_SOURCES = \ TFDTransportTest.cpp TFDTransportTest_LDADD = \ $(top_builddir)/lib/cpp/libthrift.la \ $(BOOST_TEST_LDADD) # # TPipedTransportTest # TPipedTransportTest_SOURCES = \ TPipedTransportTest.cpp \ TPipeInterruptTest.cpp TPipedTransportTest_LDADD = \ libtestgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(BOOST_TEST_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) # # AllProtocolsTest # AllProtocolsTest_SOURCES = \ AllProtocolTests.cpp \ AllProtocolTests.tcc \ GenericHelpers.h AllProtocolsTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # DebugProtoTest # DebugProtoTest_SOURCES = \ DebugProtoTest.cpp DebugProtoTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # JSONProtoTest # JSONProtoTest_SOURCES = \ JSONProtoTest.cpp JSONProtoTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # TNonblockingServerTest # TNonblockingServerTest_SOURCES = TNonblockingServerTest.cpp TNonblockingServerTest_LDADD = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la \ $(BOOST_TEST_LDADD) \ $(BOOST_LDFLAGS) \ $(LIBEVENT_LIBS) # # TNonblockingSSLServerTest # TNonblockingSSLServerTest_SOURCES = TNonblockingSSLServerTest.cpp TNonblockingSSLServerTest_LDADD = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la \ $(BOOST_TEST_LDADD) \ $(BOOST_LDFLAGS) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_CHRONO_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) \ $(LIBEVENT_LIBS) # # OptionalRequiredTest # OptionalRequiredTest_SOURCES = \ OptionalRequiredTest.cpp OptionalRequiredTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # OptionalRequiredTest # RecursiveTest_SOURCES = \ RecursiveTest.cpp RecursiveTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # SpecializationTest # SpecializationTest_SOURCES = \ SpecializationTest.cpp SpecializationTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) concurrency_test_SOURCES = \ concurrency/Tests.cpp \ concurrency/ThreadFactoryTests.h \ concurrency/ThreadManagerTests.h \ concurrency/TimerManagerTests.h concurrency_test_LDADD = \ $(top_builddir)/lib/cpp/libthrift.la link_test_SOURCES = \ link/LinkTest.cpp \ link/TemplatedService1.cpp \ link/TemplatedService2.cpp processor_test_SOURCES = \ processor/ProcessorTest.cpp \ processor/EventLog.cpp \ processor/ServerThread.cpp \ processor/EventLog.h \ processor/Handlers.h \ processor/ServerThread.h processor_test_LDADD = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la \ $(BOOST_TEST_LDADD) \ $(BOOST_LDFLAGS) \ $(LIBEVENT_LIBS) OpenSSLManualInitTest_SOURCES = \ OpenSSLManualInitTest.cpp OpenSSLManualInitTest_LDADD = \ $(top_builddir)/lib/cpp/libthrift.la \ $(BOOST_TEST_LDADD) \ $(OPENSSL_LDFLAGS) \ $(OPENSSL_LIBS) # # Common thrift code generation rules # gen-cpp/AnnotationTest_constants.cpp gen-cpp/AnnotationTest_constants.h gen-cpp/AnnotationTest_types.cpp gen-cpp/AnnotationTest_types.h: $(top_srcdir)/test/AnnotationTest.thrift $(THRIFT) --gen cpp $< gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h: $(top_srcdir)/test/v0.16/DebugProtoTest.thrift $(THRIFT) --gen cpp $< gen-cpp/DoubleConstantsTest_constants.cpp gen-cpp/DoubleConstantsTest_constants.h: $(top_srcdir)/test/DoubleConstantsTest.thrift $(THRIFT) --gen cpp $< gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h: $(top_srcdir)/test/EnumTest.thrift $(THRIFT) --gen cpp $< gen-cpp/TypedefTest_types.cpp gen-cpp/TypedefTest_types.h: $(top_srcdir)/test/TypedefTest.thrift $(THRIFT) --gen cpp $< gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h: $(top_srcdir)/test/OptionalRequiredTest.thrift $(THRIFT) --gen cpp $< gen-cpp/Recursive_types.cpp gen-cpp/Recursive_types.h: $(top_srcdir)/test/Recursive.thrift $(THRIFT) --gen cpp $< gen-cpp/Service.cpp gen-cpp/StressTest_types.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) --gen cpp $< gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen cpp $< gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h: OneWayTest.thrift $(THRIFT) --gen cpp $< gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h: processor/proc.thrift $(THRIFT) --gen cpp:templates,cob_style $< AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -I$(top_srcdir)/lib/cpp/src/thrift -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. AM_LDFLAGS = $(BOOST_LDFLAGS) AM_CXXFLAGS = -Wall -Wextra -pedantic clean-local: $(RM) gen-cpp/* EXTRA_DIST = \ concurrency \ processor \ qt \ CMakeLists.txt \ DebugProtoTest_extras.cpp \ ThriftTest_extras.cpp \ OneWayTest.thrift thrift-0.19.0/lib/cpp/test/CMakeLists.txt0000644000000000000000000003201514370300523020144 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Unit tests still require boost include(BoostMacros) REQUIRE_BOOST_HEADERS() set(BOOST_COMPONENTS filesystem thread unit_test_framework chrono) REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) include(ThriftMacros) # Make sure gen-cpp files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") # Create the thrift C++ test library set(testgencpp_SOURCES gen-cpp/AnnotationTest_types.cpp gen-cpp/AnnotationTest_types.h gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h gen-cpp/Recursive_types.cpp gen-cpp/Recursive_types.h gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.cpp gen-cpp/OneWayService.h gen-cpp/TypedefTest_types.cpp gen-cpp/TypedefTest_types.h ThriftTest_extras.cpp DebugProtoTest_extras.cpp ) add_library(testgencpp STATIC ${testgencpp_SOURCES}) set(testgencpp_cob_SOURCES gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h ) add_library(testgencpp_cob STATIC ${testgencpp_cob_SOURCES}) add_executable(Benchmark Benchmark.cpp) target_link_libraries(Benchmark testgencpp) target_link_libraries(Benchmark thrift) add_test(NAME Benchmark COMMAND Benchmark) target_link_libraries(Benchmark testgencpp) set(UnitTest_SOURCES UnitTestMain.cpp OneWayHTTPTest.cpp TMemoryBufferTest.cpp TBufferBaseTest.cpp Base64Test.cpp ToStringTest.cpp TypedefTest.cpp TServerSocketTest.cpp TServerTransportTest.cpp ThrifttReadCheckTests.cpp ) add_executable(UnitTests ${UnitTest_SOURCES}) target_link_libraries(UnitTests testgencpp ${Boost_LIBRARIES}) target_link_libraries(UnitTests thrift) add_test(NAME UnitTests COMMAND UnitTests) if(MSVC) # Disable C4503: decorated name length exceeded, name was truncated # 'insanity' results in very long decorated names set_property( TARGET UnitTests APPEND_STRING PROPERTY COMPILE_FLAGS /wd4503 ) endif() set( TInterruptTest_SOURCES TSocketInterruptTest.cpp TSSLSocketInterruptTest.cpp ) if (WIN32) list(APPEND TInterruptTest_SOURCES TPipeInterruptTest.cpp ) endif() add_executable(TInterruptTest ${TInterruptTest_SOURCES}) target_link_libraries(TInterruptTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(TInterruptTest thrift) if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW) target_link_libraries(TInterruptTest -lrt) endif () add_test(NAME TInterruptTest COMMAND TInterruptTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys") add_executable(TServerIntegrationTest TServerIntegrationTest.cpp) target_link_libraries(TServerIntegrationTest testgencpp_cob ${Boost_LIBRARIES} ) target_link_libraries(TServerIntegrationTest thrift) if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW) target_link_libraries(TServerIntegrationTest -lrt) endif () add_test(NAME TServerIntegrationTest COMMAND TServerIntegrationTest) if(WITH_ZLIB) include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}") add_executable(TransportTest TransportTest.cpp) target_link_libraries(TransportTest testgencpp ${Boost_LIBRARIES} ${ZLIB_LIBRARIES} ) target_link_libraries(TransportTest thrift) target_link_libraries(TransportTest thriftz) add_test(NAME TransportTest COMMAND TransportTest) add_executable(ZlibTest ZlibTest.cpp) target_link_libraries(ZlibTest testgencpp ${Boost_LIBRARIES} ${ZLIB_LIBRARIES} ) target_link_libraries(ZlibTest thrift) target_link_libraries(ZlibTest thriftz) add_test(NAME ZlibTest COMMAND ZlibTest) endif(WITH_ZLIB) add_executable(AnnotationTest AnnotationTest.cpp) target_link_libraries(AnnotationTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(AnnotationTest thrift) add_test(NAME AnnotationTest COMMAND AnnotationTest) add_executable(EnumTest EnumTest.cpp) target_link_libraries(EnumTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(EnumTest thrift) add_test(NAME EnumTest COMMAND EnumTest) if(HAVE_GETOPT_H) add_executable(TFileTransportTest TFileTransportTest.cpp) target_link_libraries(TFileTransportTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(TFileTransportTest thrift) add_test(NAME TFileTransportTest COMMAND TFileTransportTest) endif() add_executable(TFDTransportTest TFDTransportTest.cpp) target_link_libraries(TFDTransportTest ${Boost_LIBRARIES} ) target_link_libraries(TFDTransportTest thrift) add_test(NAME TFDTransportTest COMMAND TFDTransportTest) add_executable(TPipedTransportTest TPipedTransportTest.cpp) target_link_libraries(TPipedTransportTest ${Boost_LIBRARIES} ) target_link_libraries(TPipedTransportTest thrift) add_test(NAME TPipedTransportTest COMMAND TPipedTransportTest) set(AllProtocolsTest_SOURCES AllProtocolTests.cpp AllProtocolTests.tcc GenericHelpers.h ) add_executable(AllProtocolsTest ${AllProtocolsTest_SOURCES}) target_link_libraries(AllProtocolsTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(AllProtocolsTest thrift) add_test(NAME AllProtocolsTest COMMAND AllProtocolsTest) # The debug run-time in Windows asserts on isprint() with negative inputs if (NOT MSVC OR (MSVC AND CMAKE_BUILD_TYPE EQUAL "DEBUG")) add_executable(DebugProtoTest DebugProtoTest.cpp) target_link_libraries(DebugProtoTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(DebugProtoTest thrift) add_test(NAME DebugProtoTest COMMAND DebugProtoTest) endif() add_executable(JSONProtoTest JSONProtoTest.cpp) target_link_libraries(JSONProtoTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(JSONProtoTest thrift) add_test(NAME JSONProtoTest COMMAND JSONProtoTest) add_executable(OptionalRequiredTest OptionalRequiredTest.cpp) target_link_libraries(OptionalRequiredTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(OptionalRequiredTest thrift) add_test(NAME OptionalRequiredTest COMMAND OptionalRequiredTest) add_executable(RecursiveTest RecursiveTest.cpp) target_link_libraries(RecursiveTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(RecursiveTest thrift) add_test(NAME RecursiveTest COMMAND RecursiveTest) add_executable(SpecializationTest SpecializationTest.cpp) target_link_libraries(SpecializationTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(SpecializationTest thrift) add_test(NAME SpecializationTest COMMAND SpecializationTest) set(concurrency_test_SOURCES concurrency/Tests.cpp concurrency/ThreadFactoryTests.h concurrency/ThreadManagerTests.h concurrency/TimerManagerTests.h ) add_executable(concurrency_test ${concurrency_test_SOURCES}) target_link_libraries(concurrency_test thrift) add_test(NAME concurrency_test COMMAND concurrency_test) set(link_test_SOURCES link/LinkTest.cpp gen-cpp/ParentService.h link/TemplatedService1.cpp link/TemplatedService2.cpp ) add_executable(link_test ${link_test_SOURCES}) target_link_libraries(link_test testgencpp_cob) target_link_libraries(link_test thrift) target_link_libraries(link_test testgencpp) add_test(NAME link_test COMMAND link_test) if(WITH_LIBEVENT) set(processor_test_SOURCES processor/ProcessorTest.cpp processor/EventLog.cpp processor/ServerThread.cpp processor/EventLog.h processor/Handlers.h processor/ServerThread.h ) add_executable(processor_test ${processor_test_SOURCES}) target_link_libraries(processor_test testgencpp_cob ${Boost_LIBRARIES} ) target_link_libraries(processor_test thriftnb) add_test(NAME processor_test COMMAND processor_test) set(TNonblockingServerTest_SOURCES TNonblockingServerTest.cpp) add_executable(TNonblockingServerTest ${TNonblockingServerTest_SOURCES}) include_directories(${LIBEVENT_INCLUDE_DIRS}) target_link_libraries(TNonblockingServerTest testgencpp_cob ${Boost_LIBRARIES} ) target_link_libraries(TNonblockingServerTest thriftnb) add_test(NAME TNonblockingServerTest COMMAND TNonblockingServerTest) if(OPENSSL_FOUND AND WITH_OPENSSL) set(TNonblockingSSLServerTest_SOURCES TNonblockingSSLServerTest.cpp) add_executable(TNonblockingSSLServerTest ${TNonblockingSSLServerTest_SOURCES}) include_directories(${LIBEVENT_INCLUDE_DIRS}) target_link_libraries(TNonblockingSSLServerTest testgencpp_cob ${Boost_LIBRARIES} ) target_link_libraries(TNonblockingSSLServerTest thriftnb) add_test(NAME TNonblockingSSLServerTest COMMAND TNonblockingSSLServerTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys") endif(OPENSSL_FOUND AND WITH_OPENSSL) endif() if(OPENSSL_FOUND AND WITH_OPENSSL) add_executable(OpenSSLManualInitTest OpenSSLManualInitTest.cpp) target_link_libraries(OpenSSLManualInitTest ${OPENSSL_LIBRARIES} ${Boost_LIBRARIES} ) target_link_libraries(OpenSSLManualInitTest thrift) add_test(NAME OpenSSLManualInitTest COMMAND OpenSSLManualInitTest) add_executable(SecurityTest SecurityTest.cpp) target_link_libraries(SecurityTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(SecurityTest thrift) if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW) target_link_libraries(SecurityTest -lrt) endif () add_test(NAME SecurityTest COMMAND SecurityTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys") add_executable(SecurityFromBufferTest SecurityFromBufferTest.cpp) target_link_libraries(SecurityFromBufferTest testgencpp ${Boost_LIBRARIES} ) target_link_libraries(SecurityFromBufferTest thrift) if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW) target_link_libraries(SecurityFromBufferTest -lrt) endif () add_test(NAME SecurityFromBufferTest COMMAND SecurityFromBufferTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys") endif() if(WITH_QT5) add_subdirectory(qt) endif() # # Common thrift code generation rules # add_custom_command(OUTPUT gen-cpp/AnnotationTest_constants.cpp gen-cpp/AnnotationTest_constants.h gen-cpp/AnnotationTest_types.cpp gen-cpp/AnnotationTest_types.h gen-cpp/foo_service.cpp gen-cpp/foo_service.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/AnnotationTest.thrift ) add_custom_command(OUTPUT gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/v0.16/DebugProtoTest.thrift ) add_custom_command(OUTPUT gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/EnumTest.thrift ) add_custom_command(OUTPUT gen-cpp/TypedefTest_types.cpp gen-cpp/TypedefTest_types.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/TypedefTest.thrift ) add_custom_command(OUTPUT gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/OptionalRequiredTest.thrift ) add_custom_command(OUTPUT gen-cpp/Recursive_types.cpp gen-cpp/Recursive_types.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/Recursive.thrift ) add_custom_command(OUTPUT gen-cpp/Service.cpp gen-cpp/StressTest_types.cpp COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/StressTest.thrift ) add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/v0.16/ThriftTest.thrift ) add_custom_command(OUTPUT gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h COMMAND ${THRIFT_COMPILER} --gen cpp ${CMAKE_CURRENT_SOURCE_DIR}/OneWayTest.thrift ) add_custom_command(OUTPUT gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style ${CMAKE_CURRENT_SOURCE_DIR}/processor/proc.thrift ) thrift-0.19.0/lib/cpp/test/ToStringTest.cpp0000644000000000000000000001112714303740367020534 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include "gen-cpp/ThriftTest_types.h" #include "gen-cpp/OptionalRequiredTest_types.h" #include "gen-cpp/DebugProtoTest_types.h" using apache::thrift::to_string; BOOST_AUTO_TEST_SUITE(ToStringTest) BOOST_AUTO_TEST_CASE(base_types_to_string) { BOOST_CHECK_EQUAL(to_string(10), "10"); BOOST_CHECK_EQUAL(to_string(true), "1"); BOOST_CHECK_EQUAL(to_string('a'), "a"); BOOST_CHECK_EQUAL(to_string(1.2), "1.2"); BOOST_CHECK_EQUAL(to_string("abc"), "abc"); } // NOTE: Currently (as of 2021.08.12) the locale-based tests do not work on // Windows in the AppVeyor Thrift CI build correctly. Therefore disabled on // Windows: #ifndef _WIN32 BOOST_AUTO_TEST_CASE(locale_en_US_int_to_string) { #ifdef _WIN32 std::locale::global(std::locale("en-US.UTF-8")); #else std::locale::global(std::locale("en_US.UTF-8")); #endif BOOST_CHECK_EQUAL(to_string(1000000), "1000000"); } BOOST_AUTO_TEST_CASE(locale_de_DE_floating_point_to_string) { #ifdef _WIN32 std::locale::global(std::locale("de-DE.UTF-8")); #else std::locale::global(std::locale("de_DE.UTF-8")); #endif BOOST_CHECK_EQUAL(to_string(1.5), "1.5"); BOOST_CHECK_EQUAL(to_string(1.5f), "1.5"); BOOST_CHECK_EQUAL(to_string(1.5L), "1.5"); } #endif BOOST_AUTO_TEST_CASE(empty_vector_to_string) { std::vector l; BOOST_CHECK_EQUAL(to_string(l), "[]"); } BOOST_AUTO_TEST_CASE(single_item_vector_to_string) { std::vector l; l.push_back(100); BOOST_CHECK_EQUAL(to_string(l), "[100]"); } BOOST_AUTO_TEST_CASE(multiple_item_vector_to_string) { std::vector l; l.push_back(100); l.push_back(150); BOOST_CHECK_EQUAL(to_string(l), "[100, 150]"); } BOOST_AUTO_TEST_CASE(empty_map_to_string) { std::map m; BOOST_CHECK_EQUAL(to_string(m), "{}"); } BOOST_AUTO_TEST_CASE(single_item_map_to_string) { std::map m; m[12] = "abc"; BOOST_CHECK_EQUAL(to_string(m), "{12: abc}"); } BOOST_AUTO_TEST_CASE(multi_item_map_to_string) { std::map m; m[12] = "abc"; m[31] = "xyz"; BOOST_CHECK_EQUAL(to_string(m), "{12: abc, 31: xyz}"); } BOOST_AUTO_TEST_CASE(empty_set_to_string) { std::set s; BOOST_CHECK_EQUAL(to_string(s), "{}"); } BOOST_AUTO_TEST_CASE(single_item_set_to_string) { std::set s; s.insert('c'); BOOST_CHECK_EQUAL(to_string(s), "{c}"); } BOOST_AUTO_TEST_CASE(multi_item_set_to_string) { std::set s; s.insert('a'); s.insert('z'); BOOST_CHECK_EQUAL(to_string(s), "{a, z}"); } BOOST_AUTO_TEST_CASE(generated_empty_object_to_string) { thrift::test::EmptyStruct e; BOOST_CHECK_EQUAL(to_string(e), "EmptyStruct()"); } BOOST_AUTO_TEST_CASE(generated_single_basic_field_object_to_string) { thrift::test::StructA a; a.__set_s("abcd"); BOOST_CHECK_EQUAL(to_string(a), "StructA(s=abcd)"); } BOOST_AUTO_TEST_CASE(generated_two_basic_fields_object_to_string) { thrift::test::Bonk a; a.__set_message("abcd"); a.__set_type(1234); BOOST_CHECK_EQUAL(to_string(a), "Bonk(message=abcd, type=1234)"); } BOOST_AUTO_TEST_CASE(generated_optional_fields_object_to_string) { thrift::test::Tricky2 a; BOOST_CHECK_EQUAL(to_string(a), "Tricky2(im_optional=)"); a.__set_im_optional(123); BOOST_CHECK_EQUAL(to_string(a), "Tricky2(im_optional=123)"); } BOOST_AUTO_TEST_CASE(generated_nested_object_to_string) { thrift::test::OneField a; BOOST_CHECK_EQUAL(to_string(a), "OneField(field=EmptyStruct())"); } BOOST_AUTO_TEST_CASE(generated_nested_list_object_to_string) { thrift::test::ListBonks l; l.bonk.assign(2, thrift::test::Bonk()); l.bonk[0].__set_message("a"); l.bonk[1].__set_message("b"); BOOST_CHECK_EQUAL(to_string(l), "ListBonks(bonk=[Bonk(message=a, type=0), Bonk(message=b, type=0)])"); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/TPipeInterruptTest.cpp0000644000000000000000000000520014303740367021714 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifdef _WIN32 #include #include #include #include #include #include #include #include using apache::thrift::transport::TPipeServer; using apache::thrift::transport::TPipe; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using namespace apache::thrift; BOOST_AUTO_TEST_SUITE(TPipeInterruptTest) // TODO: duplicate the test cases in TSocketInterruptTest for pipes, // once pipes implement interruptChildren BOOST_AUTO_TEST_CASE(test_interrupt_before_accept) { TPipeServer pipe1("TPipeInterruptTest"); pipe1.listen(); pipe1.interrupt(); BOOST_CHECK_THROW(pipe1.accept(), TTransportException); } static void acceptWorker(TPipeServer *pipe) { try { for (;;) { std::shared_ptr temp = pipe->accept(); } } catch (...) {/*just want to make sure nothing crashes*/ } } static void interruptWorker(TPipeServer *pipe) { boost::this_thread::sleep(boost::posix_time::milliseconds(10)); pipe->interrupt(); } BOOST_AUTO_TEST_CASE(stress_pipe_accept_interruption) { int interruptIters = 10; for (int i = 0; i < interruptIters; ++i) { TPipeServer pipeServer("TPipeInterruptTest"); pipeServer.listen(); boost::thread acceptThread(std::bind(acceptWorker, &pipeServer)); boost::thread interruptThread(std::bind(interruptWorker, &pipeServer)); try { for (;;) { TPipe client("TPipeInterruptTest"); client.setConnTimeout(1); client.open(); } } catch (...) { /*just testing for crashes*/ } interruptThread.join(); acceptThread.join(); } } BOOST_AUTO_TEST_SUITE_END() #endif thrift-0.19.0/lib/cpp/test/DebugProtoTest_extras.cpp0000644000000000000000000000210214303740367022414 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Extra functions required for DebugProtoTest_types to work #include "gen-cpp/DebugProtoTest_types.h" namespace thrift { namespace test { namespace debug { bool Empty::operator<(Empty const& other) const { (void)other; // It is empty, so all are equal. return false; } } } } thrift-0.19.0/lib/cpp/test/SecurityFromBufferTest.cpp0000644000000000000000000002254114452237057022554 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE SecurityFromBufferTest #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SIGNAL_H #include #endif using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TSSLServerSocket; using apache::thrift::transport::TSSLSocket; using apache::thrift::transport::TSSLSocketFactory; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; using std::bind; using std::shared_ptr; boost::filesystem::path keyDir; boost::filesystem::path certFile(const std::string& filename) { return keyDir / filename; } std::string certString(const std::string& filename) { std::ifstream ifs(certFile(filename).string()); if(!ifs.is_open() || !ifs.good()) { throw(std::runtime_error("Failed to open key file " + filename + " for reading")); } std::stringstream buffer; buffer << ifs.rdbuf(); return buffer.str(); } boost::mutex gMutex; struct GlobalFixture { GlobalFixture() { using namespace boost::unit_test::framework; for (int i = 0; i < master_test_suite().argc; ++i) { BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]); } #ifdef __linux__ // OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has // disconnected can cause a SIGPIPE signal... signal(SIGPIPE, SIG_IGN); #endif TSSLSocketFactory::setManualOpenSSLInitialization(true); apache::thrift::transport::initializeOpenSSL(); keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys"; if (!boost::filesystem::exists(certFile("server.crt"))) { keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]); if (!boost::filesystem::exists(certFile("server.crt"))) { throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s)."); } } } virtual ~GlobalFixture() { apache::thrift::transport::cleanupOpenSSL(); #ifdef __linux__ signal(SIGPIPE, SIG_DFL); #endif } }; #if (BOOST_VERSION >= 105900) BOOST_GLOBAL_FIXTURE(GlobalFixture); #else BOOST_GLOBAL_FIXTURE(GlobalFixture) #endif struct SecurityFromBufferFixture { void server(apache::thrift::transport::SSLProtocol protocol) { try { boost::mutex::scoped_lock lock(mMutex); shared_ptr pServerSocketFactory; shared_ptr pServerSocket; pServerSocketFactory.reset(new TSSLSocketFactory(static_cast(protocol))); pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); pServerSocketFactory->loadCertificateFromBuffer(certString("server.crt").c_str()); pServerSocketFactory->loadPrivateKeyFromBuffer(certString("server.key").c_str()); pServerSocketFactory->server(true); pServerSocket.reset(new TSSLServerSocket("localhost", 0, pServerSocketFactory)); shared_ptr connectedClient; try { pServerSocket->listen(); mPort = pServerSocket->getPort(); mCVar.notify_one(); lock.unlock(); connectedClient = pServerSocket->accept(); uint8_t buf[2]; buf[0] = 'O'; buf[1] = 'K'; connectedClient->write(&buf[0], 2); connectedClient->flush(); } catch (apache::thrift::transport::TTransportException& ex) { boost::mutex::scoped_lock lock(gMutex); BOOST_TEST_MESSAGE(boost::format("SRV %1% Exception: %2%") % boost::this_thread::get_id() % ex.what()); } if (connectedClient) { connectedClient->close(); connectedClient.reset(); } pServerSocket->close(); pServerSocket.reset(); } catch (std::exception& ex) { BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); } } void client(apache::thrift::transport::SSLProtocol protocol) { try { shared_ptr pClientSocketFactory; shared_ptr pClientSocket; try { pClientSocketFactory.reset(new TSSLSocketFactory(static_cast(protocol))); pClientSocketFactory->authenticate(true); pClientSocketFactory->loadCertificateFromBuffer(certString("client.crt").c_str()); pClientSocketFactory->loadPrivateKeyFromBuffer(certString("client.key").c_str()); pClientSocketFactory->loadTrustedCertificatesFromBuffer(certString("CA.pem").c_str()); pClientSocket = pClientSocketFactory->createSocket("localhost", mPort); pClientSocket->open(); uint8_t buf[3]; buf[0] = 0; buf[1] = 0; BOOST_CHECK_EQUAL(2, pClientSocket->read(&buf[0], 2)); BOOST_CHECK_EQUAL(0, memcmp(&buf[0], "OK", 2)); mConnected = true; } catch (apache::thrift::transport::TTransportException& ex) { boost::mutex::scoped_lock lock(gMutex); BOOST_TEST_MESSAGE(boost::format("CLI %1% Exception: %2%") % boost::this_thread::get_id() % ex.what()); } if (pClientSocket) { pClientSocket->close(); pClientSocket.reset(); } } catch (std::exception& ex) { BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); } } static const char* protocol2str(size_t protocol) { static const char* strings[apache::thrift::transport::LATEST + 1] = {"SSLTLS", "SSLv2", "SSLv3", "TLSv1_0", "TLSv1_1", "TLSv1_2"}; return strings[protocol]; } boost::mutex mMutex; boost::condition_variable mCVar; int mPort; bool mConnected; }; BOOST_FIXTURE_TEST_SUITE(BOOST_TEST_MODULE, SecurityFromBufferFixture) BOOST_AUTO_TEST_CASE(ssl_security_matrix) { try { // matrix of connection success between client and server with different SSLProtocol selections static_assert(apache::thrift::transport::LATEST == 5, "Mismatch in assumed number of ssl protocols"); bool ossl1 = OPENSSL_VERSION_MAJOR == 1; bool matrix[apache::thrift::transport::LATEST + 1][apache::thrift::transport::LATEST + 1] = { // server = SSLTLS SSLv2 SSLv3 TLSv1_0 TLSv1_1 TLSv1_2 // client /* SSLTLS */ { true, false, false, ossl1, ossl1, true }, /* SSLv2 */ { false, false, false, false, false, false }, /* SSLv3 */ { false, false, true, false, false, false }, /* TLSv1_0 */ { ossl1, false, false, ossl1, false, false }, /* TLSv1_1 */ { ossl1, false, false, false, ossl1, false }, /* TLSv1_2 */ { true, false, false, false, false, true } }; for (size_t si = 0; si <= apache::thrift::transport::LATEST; ++si) { for (size_t ci = 0; ci <= apache::thrift::transport::LATEST; ++ci) { if (si == 1 || ci == 1) { // Skip all SSLv2 cases - protocol not supported continue; } #ifdef OPENSSL_NO_SSL3 if (si == 2 || ci == 2) { // Skip all SSLv3 cases - protocol not supported continue; } #endif boost::mutex::scoped_lock lock(mMutex); BOOST_TEST_MESSAGE(boost::format("TEST: Server = %1%, Client = %2%") % protocol2str(si) % protocol2str(ci)); mConnected = false; // thread_group manages the thread lifetime - ignore the return value of create_thread boost::thread_group threads; (void)threads.create_thread(bind(&SecurityFromBufferFixture::server, this, static_cast(si))); mCVar.wait(lock); // wait for listen() to succeed lock.unlock(); (void)threads.create_thread(bind(&SecurityFromBufferFixture::client, this, static_cast(ci))); threads.join_all(); BOOST_CHECK_MESSAGE(mConnected == matrix[ci][si], boost::format(" Server = %1%, Client = %2% expected mConnected == %3% but was %4%") % protocol2str(si) % protocol2str(ci) % matrix[ci][si] % mConnected); } } } catch (std::exception& ex) { BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); } } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/TPipedTransportTest.cpp0000644000000000000000000000367114303740367022072 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #define BOOST_TEST_MODULE TPipedTransportTest #include using apache::thrift::transport::TTransportException; using apache::thrift::transport::TPipedTransport; using apache::thrift::transport::TMemoryBuffer; using namespace apache::thrift; BOOST_AUTO_TEST_CASE(test_read_write) { std::shared_ptr underlying(new TMemoryBuffer); std::shared_ptr pipe(new TMemoryBuffer); std::shared_ptr trans(new TPipedTransport(underlying, pipe)); uint8_t buffer[4]; underlying->write((uint8_t*)"abcd", 4); trans->readAll(buffer, 2); BOOST_CHECK(std::string((char*)buffer, 2) == "ab"); trans->readEnd(); BOOST_CHECK(pipe->getBufferAsString() == "ab"); pipe->resetBuffer(); underlying->write((uint8_t*)"ef", 2); trans->readAll(buffer, 2); BOOST_CHECK(std::string((char*)buffer, 2) == "cd"); trans->readAll(buffer, 2); BOOST_CHECK(std::string((char*)buffer, 2) == "ef"); trans->readEnd(); BOOST_CHECK(pipe->getBufferAsString() == "cdef"); } thrift-0.19.0/lib/cpp/test/TypedefTest.cpp0000644000000000000000000000224714303740367020366 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include "gen-cpp/TypedefTest_types.h" BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT((boost::is_same::value)); BOOST_STATIC_ASSERT( (boost::is_same::value)); thrift-0.19.0/lib/cpp/test/SpecializationTest.cpp0000644000000000000000000000561514303740367021746 0ustar00rootroot00000000000000#define _USE_MATH_DEFINES #include #include #include #include using namespace thrift::test::debug; using namespace apache::thrift::transport; using namespace apache::thrift::protocol; #define BOOST_TEST_MODULE SpecializationTest #include typedef TBinaryProtocolT MyProtocol; // typedef TBinaryProtocolT MyProtocol; BOOST_AUTO_TEST_CASE(test_specialization_1) { OneOfEach ooe; ooe.im_true = true; ooe.im_false = false; ooe.a_bite = 0x7f; ooe.integer16 = 27000; ooe.integer32 = 1 << 24; ooe.integer64 = (uint64_t)6000 * 1000 * 1000; ooe.double_precision = M_PI; ooe.some_characters = "JSON THIS! \"\1"; ooe.zomg_unicode = "\xd7\n\a\t"; ooe.base64 = "\1\2\3\255"; Nesting n; n.my_ooe = ooe; n.my_ooe.integer16 = 16; n.my_ooe.integer32 = 32; n.my_ooe.integer64 = 64; n.my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2; n.my_ooe.some_characters = ":R (me going \"rrrr\")"; n.my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce" "\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0" "\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74" "\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80" "\xbc"; n.my_bonk.type = 31337; n.my_bonk.message = "I am a bonk... xor!"; HolyMoley hm; hm.big.push_back(ooe); hm.big.push_back(n.my_ooe); hm.big[0].a_bite = 0x22; hm.big[1].a_bite = 0x33; std::vector stage1; stage1.push_back("and a one"); stage1.push_back("and a two"); hm.contain.insert(stage1); stage1.clear(); stage1.push_back("then a one, two"); stage1.push_back("three!"); stage1.push_back("FOUR!!"); hm.contain.insert(stage1); stage1.clear(); hm.contain.insert(stage1); std::vector stage2; hm.bonks["nothing"] = stage2; stage2.resize(stage2.size() + 1); stage2.back().type = 1; stage2.back().message = "Wait."; stage2.resize(stage2.size() + 1); stage2.back().type = 2; stage2.back().message = "What?"; hm.bonks["something"] = stage2; stage2.clear(); stage2.resize(stage2.size() + 1); stage2.back().type = 3; stage2.back().message = "quoth"; stage2.resize(stage2.size() + 1); stage2.back().type = 4; stage2.back().message = "the raven"; stage2.resize(stage2.size() + 1); stage2.back().type = 5; stage2.back().message = "nevermore"; hm.bonks["poe"] = stage2; std::shared_ptr buffer(new TMemoryBuffer()); std::shared_ptr proto(new MyProtocol(buffer)); ooe.write(proto.get()); OneOfEach ooe2; ooe2.read(proto.get()); BOOST_CHECK(ooe == ooe2); hm.write(proto.get()); HolyMoley hm2; hm2.read(proto.get()); BOOST_CHECK(hm == hm2); hm2.big[0].a_bite = 0x00; BOOST_CHECK(hm != hm2); } thrift-0.19.0/lib/cpp/test/EnumTest.cpp0000644000000000000000000000651014303740367017667 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE EnumTest #include #include "gen-cpp/EnumTest_types.h" std::ostream& operator <<(std::ostream& os, const MyEnumWithCustomOstream::type& val) { os << "{" << (int)val << ":CUSTOM!" << "}"; return os; } std::string to_string(const MyEnumWithCustomOstream::type& val) { std::ostringstream os; os << val; return os.str(); } BOOST_AUTO_TEST_SUITE(EnumTest) BOOST_AUTO_TEST_CASE(test_enum_value) { // Check that all the enum values match what we expect BOOST_CHECK_EQUAL(MyEnum1::ME1_0, 0); BOOST_CHECK_EQUAL(MyEnum1::ME1_1, 1); BOOST_CHECK_EQUAL(MyEnum1::ME1_2, 2); BOOST_CHECK_EQUAL(MyEnum1::ME1_3, 3); BOOST_CHECK_EQUAL(MyEnum1::ME1_5, 5); BOOST_CHECK_EQUAL(MyEnum1::ME1_6, 6); BOOST_CHECK_EQUAL(MyEnum2::ME2_0, 0); BOOST_CHECK_EQUAL(MyEnum2::ME2_1, 1); BOOST_CHECK_EQUAL(MyEnum2::ME2_2, 2); BOOST_CHECK_EQUAL(MyEnum3::ME3_0, 0); BOOST_CHECK_EQUAL(MyEnum3::ME3_1, 1); BOOST_CHECK_EQUAL(MyEnum3::ME3_N2, -2); BOOST_CHECK_EQUAL(MyEnum3::ME3_N1, -1); BOOST_CHECK_EQUAL(MyEnum3::ME3_D0, 0); BOOST_CHECK_EQUAL(MyEnum3::ME3_D1, 1); BOOST_CHECK_EQUAL(MyEnum3::ME3_9, 9); BOOST_CHECK_EQUAL(MyEnum3::ME3_10, 10); BOOST_CHECK_EQUAL(MyEnum4::ME4_A, 0x7ffffffd); BOOST_CHECK_EQUAL(MyEnum4::ME4_B, 0x7ffffffe); BOOST_CHECK_EQUAL(MyEnum4::ME4_C, 0x7fffffff); BOOST_CHECK_EQUAL(MyEnum5::e1, 0); BOOST_CHECK_EQUAL(MyEnum5::e2, 42); } template std::string EnumToString(_T e) { std::stringstream ss; ss << e; return ss.str(); } BOOST_AUTO_TEST_CASE(test_enum_ostream) { BOOST_CHECK_EQUAL(EnumToString(MyEnum1::ME1_0), "ME1_0"); BOOST_CHECK_EQUAL(EnumToString(MyEnum5::e2), "e2"); BOOST_CHECK_EQUAL(EnumToString(MyEnum3::ME3_N1), "ME3_N1"); BOOST_CHECK_EQUAL(EnumToString(MyEnumWithCustomOstream::CustoM2), "{2:CUSTOM!}"); // some invalid or unknown value auto uut = static_cast(44); BOOST_CHECK_EQUAL(EnumToString(uut), "44"); } BOOST_AUTO_TEST_CASE(test_enum_to_string) { BOOST_CHECK_EQUAL(::to_string(MyEnum1::ME1_0), "ME1_0"); BOOST_CHECK_EQUAL(::to_string(MyEnum5::e2), "e2"); BOOST_CHECK_EQUAL(::to_string(MyEnum3::ME3_N1), "ME3_N1"); BOOST_CHECK_EQUAL(::to_string(MyEnumWithCustomOstream::CustoM2), "{2:CUSTOM!}"); // some invalid or unknown value auto uut = static_cast(44); BOOST_CHECK_EQUAL(::to_string(uut), "44"); } BOOST_AUTO_TEST_CASE(test_enum_constant) { MyStruct ms; BOOST_CHECK_EQUAL(ms.me2_2, 2); BOOST_CHECK_EQUAL(ms.me3_n2, -2); BOOST_CHECK_EQUAL(ms.me3_d1, 1); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/OptionalRequiredTest.cpp0000644000000000000000000002473314303740367022260 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include #include #include #include #include "gen-cpp/OptionalRequiredTest_types.h" #define BOOST_TEST_MODULE OptionalRequiredTest #include using namespace thrift::test; using namespace apache::thrift; using namespace apache::thrift::transport; using namespace apache::thrift::protocol; /* template void trywrite(const Struct& s, bool should_work) { bool worked; try { TBinaryProtocol protocol(std::shared_ptr(new TMemoryBuffer)); s.write(&protocol); worked = true; } catch (TProtocolException & ex) { worked = false; } BOOST_CHECK(worked == should_work); } */ template void write_to_read(const Struct1& w, Struct2& r) { TBinaryProtocol protocol(std::shared_ptr(new TMemoryBuffer)); w.write(&protocol); r.read(&protocol); } BOOST_AUTO_TEST_CASE(test_optional_required_1) { OldSchool o; const std::string expected_result( "OldSchool {\n" " 01: im_int (i16) = 0,\n" " 02: im_str (string) = \"\",\n" " 03: im_big (list) = list[0] {\n" " },\n" "}"); const std::string result(apache::thrift::ThriftDebugString(o)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_2_1) { Simple s; const std::string expected_result( "Simple {\n" " 01: im_default (i16) = 0,\n" " 02: im_required (i16) = 0,\n" "}"); const std::string result(apache::thrift::ThriftDebugString(s)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_2_2) { Simple s; s.im_optional = 10; const std::string expected_result( "Simple {\n" " 01: im_default (i16) = 0,\n" " 02: im_required (i16) = 0,\n" "}"); const std::string result(apache::thrift::ThriftDebugString(s)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_2_3) { Simple s; s.im_optional = 10; s.__isset.im_optional = true; const std::string expected_result( "Simple {\n" " 01: im_default (i16) = 0,\n" " 02: im_required (i16) = 0,\n" " 03: im_optional (i16) = 10,\n" "}"); const std::string result(apache::thrift::ThriftDebugString(s)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_2_4) { Simple s; s.__isset.im_optional = true; const std::string expected_result( "Simple {\n" " 01: im_default (i16) = 0,\n" " 02: im_required (i16) = 0,\n" " 03: im_optional (i16) = 0,\n" "}"); const std::string result(apache::thrift::ThriftDebugString(s)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_2_5) { Simple s; s.__isset.im_optional = true; s.im_optional = 10; const std::string expected_result( "Simple {\n" " 01: im_default (i16) = 0,\n" " 02: im_required (i16) = 0,\n" " 03: im_optional (i16) = 10,\n" "}"); const std::string result(apache::thrift::ThriftDebugString(s)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_3) { // assign/copy-construct with non-required fields Simple s1, s2; s1.__isset.im_default = true; s1.__set_im_optional(10); BOOST_CHECK(s1.__isset.im_default); BOOST_CHECK(s1.__isset.im_optional); s2 = s1; BOOST_CHECK(s2.__isset.im_default); BOOST_CHECK(s2.__isset.im_optional); Simple s3(s1); BOOST_CHECK(s3.__isset.im_default); BOOST_CHECK(s3.__isset.im_optional); } BOOST_AUTO_TEST_CASE(test_optional_required_4) { // Write-to-read with optional fields. Simple s1, s2, s3; s1.im_optional = 10; BOOST_CHECK(!s1.__isset.im_default); // BOOST_CHECK(!s1.__isset.im_required); // Compile error. BOOST_CHECK(!s1.__isset.im_optional); write_to_read(s1, s2); BOOST_CHECK(s2.__isset.im_default); // BOOST_CHECK( s2.__isset.im_required); // Compile error. BOOST_CHECK(!s2.__isset.im_optional); BOOST_CHECK(s3.im_optional == 0); s1.__isset.im_optional = true; write_to_read(s1, s3); BOOST_CHECK(s3.__isset.im_default); // BOOST_CHECK( s3.__isset.im_required); // Compile error. BOOST_CHECK(s3.__isset.im_optional); BOOST_CHECK(s3.im_optional == 10); } BOOST_AUTO_TEST_CASE(test_optional_required_5) { // Writing between optional and default. Tricky1 t1; Tricky2 t2; t2.im_optional = 10; write_to_read(t2, t1); write_to_read(t1, t2); BOOST_CHECK(!t1.__isset.im_default); BOOST_CHECK(t2.__isset.im_optional); BOOST_CHECK(t1.im_default == t2.im_optional); BOOST_CHECK(t1.im_default == 0); } BOOST_AUTO_TEST_CASE(test_optional_required_6) { // Writing between default and required. Tricky1 t1; Tricky3 t3; write_to_read(t1, t3); write_to_read(t3, t1); BOOST_CHECK(t1.__isset.im_default); } BOOST_AUTO_TEST_CASE(test_optional_required_7) { // Writing between optional and required. Tricky2 t2; Tricky3 t3; t2.__isset.im_optional = true; write_to_read(t2, t3); write_to_read(t3, t2); } BOOST_AUTO_TEST_CASE(test_optional_required_8) { // Mu-hu-ha-ha-ha! Tricky2 t2; Tricky3 t3; try { write_to_read(t2, t3); abort(); } catch (const TProtocolException&) { } write_to_read(t3, t2); BOOST_CHECK(t2.__isset.im_optional); } BOOST_AUTO_TEST_CASE(test_optional_required_9) { Complex c; const std::string expected_result( "Complex {\n" " 01: cp_default (i16) = 0,\n" " 02: cp_required (i16) = 0,\n" " 04: the_map (map) = map[0] {\n" " },\n" " 05: req_simp (struct) = Simple {\n" " 01: im_default (i16) = 0,\n" " 02: im_required (i16) = 0,\n" " },\n" "}"); const std::string result(apache::thrift::ThriftDebugString(c)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_10) { Tricky1 t1; Tricky2 t2; // Compile error. //(void)(t1 == t2); } BOOST_AUTO_TEST_CASE(test_optional_required_11) { OldSchool o1, o2, o3; BOOST_CHECK(o1 == o2); o1.im_int = o2.im_int = 10; BOOST_CHECK(o1 == o2); o1.__isset.im_int = true; o2.__isset.im_int = false; BOOST_CHECK(o1 == o2); o1.im_int = 20; o1.__isset.im_int = false; BOOST_CHECK(o1 != o2); o1.im_int = 10; BOOST_CHECK(o1 == o2); o1.im_str = o2.im_str = "foo"; BOOST_CHECK(o1 == o2); o1.__isset.im_str = o2.__isset.im_str = true; BOOST_CHECK(o1 == o2); std::map mymap; mymap[1] = "bar"; mymap[2] = "baz"; o1.im_big.push_back(std::map()); BOOST_CHECK(o1 != o2); o2.im_big.push_back(std::map()); BOOST_CHECK(o1 == o2); o2.im_big.push_back(mymap); BOOST_CHECK(o1 != o2); o1.im_big.push_back(mymap); BOOST_CHECK(o1 == o2); TBinaryProtocol protocol(std::shared_ptr(new TMemoryBuffer)); o1.write(&protocol); o1.im_big.push_back(mymap); mymap[3] = "qux"; o2.im_big.push_back(mymap); BOOST_CHECK(o1 != o2); o1.im_big.back()[3] = "qux"; BOOST_CHECK(o1 == o2); o3.read(&protocol); o3.im_big.push_back(mymap); BOOST_CHECK(o1 == o3); const std::string expected_result( "OldSchool {\n" " 01: im_int (i16) = 10,\n" " 02: im_str (string) = \"foo\",\n" " 03: im_big (list) = list[3] {\n" " [0] = map[0] {\n" " },\n" " [1] = map[2] {\n" " 1 -> \"bar\",\n" " 2 -> \"baz\",\n" " },\n" " [2] = map[3] {\n" " 1 -> \"bar\",\n" " 2 -> \"baz\",\n" " 3 -> \"qux\",\n" " },\n" " },\n" "}"); const std::string result(apache::thrift::ThriftDebugString(o3)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_optional_required_12) { Tricky2 t1, t2; BOOST_CHECK(t1.__isset.im_optional == false); BOOST_CHECK(t2.__isset.im_optional == false); BOOST_CHECK(t1 == t2); t1.im_optional = 5; BOOST_CHECK(t1 == t2); t2.im_optional = 5; BOOST_CHECK(t1 == t2); t1.__isset.im_optional = true; BOOST_CHECK(t1 != t2); t2.__isset.im_optional = true; BOOST_CHECK(t1 == t2); t1.im_optional = 10; BOOST_CHECK(t1 != t2); t2.__isset.im_optional = false; BOOST_CHECK(t1 != t2); } BOOST_AUTO_TEST_CASE(test_optional_required_13) { OptionalDefault t1, t2; BOOST_CHECK(t1.__isset.opt_int == true); BOOST_CHECK(t1.__isset.opt_str == true); BOOST_CHECK(t1.opt_int == t2.opt_int); BOOST_CHECK(t1.opt_str == t2.opt_str); write_to_read(t1, t2); BOOST_CHECK(t2.__isset.opt_int == true); BOOST_CHECK(t2.__isset.opt_str == true); BOOST_CHECK(t1.opt_int == t2.opt_int); BOOST_CHECK(t1.opt_str == t2.opt_str); const std::string expected_result( "OptionalDefault {\n" " 01: opt_int (i16) = 1234,\n" " 02: opt_str (string) = \"default\",\n" "}"); const std::string result(apache::thrift::ThriftDebugString(t2)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } thrift-0.19.0/lib/cpp/test/TTransportCheckThrow.h0000644000000000000000000000544014303740367021673 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #pragma once #define TTRANSPORT_CHECK_THROW(_CALL, _TYPE) \ { \ bool caught = false; \ try { \ (_CALL); \ } catch (TTransportException & ex) { \ BOOST_CHECK_EQUAL(ex.getType(), _TYPE); \ caught = true; \ } \ BOOST_CHECK_MESSAGE(caught, "expected TTransportException but nothing was thrown"); \ } #define TTRANSPORT_REQUIRE_THROW(_CALL, _TYPE) \ { \ bool caught = false; \ try { \ (_CALL); \ } catch (TTransportException & ex) { \ BOOST_REQUIRE_EQUAL(ex.getType(), _TYPE); \ caught = true; \ } \ BOOST_REQUIRE_MESSAGE(caught, "expected TTransportException but nothing was thrown"); \ } thrift-0.19.0/lib/cpp/test/TBufferBaseTest.cpp0000644000000000000000000005441114303740367021116 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include using std::shared_ptr; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TBufferedTransport; using apache::thrift::transport::TFramedTransport; using apache::thrift::transport::test::TShortReadTransport; using std::string; // Shamelessly copied from ZlibTransport. TODO: refactor. unsigned int dist[][5000] = { { 1<<15 }, { 5,13,9,1,8,9,11,13,18,48,24,13,21,13,5,11,35,2,4,20,17,72,27,14,15,4,7,26, 12,1,14,9,2,16,29,41,7,24,4,27,14,4,1,4,25,3,6,34,10,8,50,2,14,13,55,29,3, 43,53,49,14,4,10,32,27,48,1,3,1,11,5,17,16,51,17,30,15,11,9,2,2,11,52,12,2, 13,94,1,19,1,38,2,8,43,8,33,7,30,8,17,22,2,15,14,12,34,2,12,6,37,29,74,3, 165,16,11,17,5,14,3,10,7,37,11,24,7,1,3,12,37,8,9,34,17,12,8,21,13,37,1,4, 30,14,78,4,15,2,40,37,17,12,36,82,14,4,1,4,7,17,11,16,88,77,2,3,15,3,34,11, 5,79,22,34,8,4,4,40,22,24,28,9,13,3,34,27,9,16,39,16,39,13,2,4,3,41,26,10,4, 33,4,7,12,5,6,3,10,30,8,21,16,58,19,9,0,47,7,13,11,19,15,7,53,57,2,13,28,22, 3,16,9,25,33,12,40,7,12,64,7,14,24,44,9,2,14,11,2,58,1,26,30,11,9,5,24,7,9, 94,2,10,21,5,5,4,5,6,179,9,18,2,7,13,31,41,17,4,36,3,21,6,26,8,15,18,44,27, 11,9,25,7,0,14,2,12,20,23,13,2,163,9,5,15,65,2,14,6,8,98,11,15,14,34,2,3,10, 22,9,92,7,10,32,67,13,3,4,35,8,2,1,5,0,26,381,7,27,8,2,16,93,4,19,5,8,25,9, 31,14,4,21,5,3,9,22,56,4,18,3,11,18,6,4,3,40,12,16,110,8,35,14,1,18,40,9,12, 14,3,11,7,57,13,18,116,53,19,22,7,16,11,5,8,21,16,1,75,21,20,1,28,2,6,1,7, 19,38,5,6,9,9,4,1,7,55,36,62,5,4,4,24,15,1,12,35,48,20,5,17,1,5,26,15,4,54, 13,5,5,15,5,19,32,29,31,7,6,40,7,80,11,18,8,128,48,6,12,84,13,4,7,2,13,9,16, 17,3,254,1,4,181,8,44,7,6,24,27,9,23,14,34,16,22,25,10,3,3,4,4,12,2,12,6,7, 13,58,13,6,11,19,53,11,66,18,19,10,4,13,2,5,49,58,1,67,7,21,64,14,11,14,8,3, 26,33,91,31,20,7,9,42,39,4,3,55,11,10,0,7,4,75,8,12,0,27,3,8,9,0,12,12,23, 28,23,20,4,13,30,2,22,20,19,30,6,22,2,6,4,24,7,19,55,86,5,33,2,161,6,7,1,62, 13,3,72,12,12,9,7,12,10,5,10,29,1,5,22,13,13,5,2,12,3,7,14,18,2,3,46,21,17, 15,19,3,27,5,16,45,31,10,8,17,18,18,3,7,24,6,55,9,3,6,12,10,12,8,91,9,4,4,4, 27,29,16,5,7,22,43,28,11,14,8,11,28,109,55,71,40,3,8,22,26,15,44,3,25,29,5, 3,32,17,12,3,29,27,25,15,11,8,40,39,38,17,3,9,11,2,32,11,6,20,48,75,27,3,7, 54,12,95,12,7,24,23,2,13,8,15,16,5,12,4,17,7,19,88,2,6,13,115,45,12,21,2,86, 74,9,7,5,16,32,16,2,21,18,6,34,5,18,260,7,12,16,44,19,92,31,7,8,2,9,0,0,15, 8,38,4,8,20,18,2,83,3,3,4,9,5,3,10,3,5,29,15,7,11,8,48,17,23,2,17,4,11,22, 21,64,8,8,4,19,95,0,17,28,9,11,20,71,5,11,18,12,13,45,49,4,1,33,32,23,13,5, 52,2,2,16,3,4,7,12,2,1,12,6,24,1,22,155,21,3,45,4,12,44,26,5,40,36,9,9,8,20, 35,31,3,2,32,50,10,8,37,2,75,35,22,15,192,8,11,23,1,4,29,6,8,8,5,12,18,32,4, 7,12,2,0,0,9,5,48,11,35,3,1,123,6,29,8,11,8,23,51,16,6,63,12,2,5,4,14,2,15, 7,14,3,2,7,17,32,8,8,10,1,23,62,2,49,6,49,47,23,3,20,7,11,39,10,24,6,15,5,5, 11,8,16,36,8,13,20,3,10,44,7,52,7,10,36,6,15,10,5,11,4,14,19,17,10,12,3,6, 23,4,13,94,70,7,36,7,38,7,28,8,4,15,3,19,4,33,39,21,109,4,80,6,40,4,432,4,4, 7,8,3,31,8,28,37,34,10,2,21,5,22,0,7,36,14,12,6,24,1,21,5,9,2,29,20,54,113, 13,31,39,27,6,0,27,4,5,2,43,7,8,57,8,62,7,9,12,22,90,30,6,19,7,10,20,6,5,58, 32,30,41,4,10,25,13,3,8,7,10,2,9,6,151,44,16,12,16,20,8,3,18,11,17,4,10,45, 15,8,56,38,52,25,40,14,4,17,15,8,2,19,7,8,26,30,2,3,180,8,26,17,38,35,5,16, 28,5,15,56,13,14,18,9,15,83,27,3,9,4,11,8,27,27,44,10,12,8,3,48,14,7,9,4,4, 8,4,5,9,122,8,14,12,19,17,21,4,29,63,21,17,10,12,18,47,10,10,53,4,18,16,4,8, 118,9,5,12,9,11,9,3,12,32,3,23,2,15,3,3,30,3,17,235,15,22,9,299,14,17,1,5, 16,8,3,7,3,13,2,7,6,4,8,66,2,13,6,15,16,47,3,36,5,7,10,24,1,9,9,8,13,16,26, 12,7,24,21,18,49,23,39,10,41,4,13,4,27,11,12,12,19,4,147,8,10,9,40,21,2,83, 10,5,6,11,25,9,50,57,40,12,12,21,1,3,24,23,9,3,9,13,2,3,12,57,8,11,13,15,26, 15,10,47,36,4,25,1,5,8,5,4,0,12,49,5,19,4,6,16,14,6,10,69,10,33,29,7,8,61, 12,4,0,3,7,6,3,16,29,27,38,4,21,0,24,3,2,1,19,16,22,2,8,138,11,7,7,3,12,22, 3,16,5,7,3,53,9,10,32,14,5,7,3,6,22,9,59,26,8,7,58,5,16,11,55,7,4,11,146,91, 8,13,18,14,6,8,8,31,26,22,6,11,30,11,30,15,18,31,3,48,17,7,6,4,9,2,25,3,35, 13,13,7,8,4,31,10,8,10,4,3,45,10,23,2,7,259,17,21,13,14,3,26,3,8,27,4,18,9, 66,7,12,5,8,17,4,23,55,41,51,2,32,26,66,4,21,14,12,65,16,22,17,5,14,2,29,24, 7,3,36,2,43,53,86,5,28,4,58,13,49,121,6,2,73,2,1,47,4,2,27,10,35,28,27,10, 17,10,56,7,10,14,28,20,24,40,7,4,7,3,10,11,32,6,6,3,15,11,54,573,2,3,6,2,3, 14,64,4,16,12,16,42,10,26,4,6,11,69,18,27,2,2,17,22,9,13,22,11,6,1,15,49,3, 14,1 }, { 11,11,11,15,47,1,3,1,23,5,8,18,3,23,15,21,1,7,19,10,26,1,17,11,31,21,41,18, 34,4,9,58,19,3,3,36,5,18,13,3,14,4,9,10,4,19,56,15,3,5,3,11,27,9,4,10,13,4, 11,6,9,2,18,3,10,19,11,4,53,4,2,2,3,4,58,16,3,0,5,30,2,11,93,10,2,14,10,6,2, 115,2,25,16,22,38,101,4,18,13,2,145,51,45,15,14,15,13,20,7,24,5,13,14,30,40, 10,4,107,12,24,14,39,12,6,13,20,7,7,11,5,18,18,45,22,6,39,3,2,1,51,9,11,4, 13,9,38,44,8,11,9,15,19,9,23,17,17,17,13,9,9,1,10,4,18,6,2,9,5,27,32,72,8, 37,9,4,10,30,17,20,15,17,66,10,4,73,35,37,6,4,16,117,45,13,4,75,5,24,65,10, 4,9,4,13,46,5,26,29,10,4,4,52,3,13,18,63,6,14,9,24,277,9,88,2,48,27,123,14, 61,7,5,10,8,7,90,3,10,3,3,48,17,13,10,18,33,2,19,36,6,21,1,16,12,5,6,2,16, 15,29,88,28,2,15,6,11,4,6,11,3,3,4,18,9,53,5,4,3,33,8,9,8,6,7,36,9,62,14,2, 1,10,1,16,7,32,7,23,20,11,10,23,2,1,0,9,16,40,2,81,5,22,8,5,4,37,51,37,10, 19,57,11,2,92,31,6,39,10,13,16,8,20,6,9,3,10,18,25,23,12,30,6,2,26,7,64,18, 6,30,12,13,27,7,10,5,3,33,24,99,4,23,4,1,27,7,27,49,8,20,16,3,4,13,9,22,67, 28,3,10,16,3,2,10,4,8,1,8,19,3,85,6,21,1,9,16,2,30,10,33,12,4,9,3,1,60,38,6, 24,32,3,14,3,40,8,34,115,5,9,27,5,96,3,40,6,15,5,8,22,112,5,5,25,17,58,2,7, 36,21,52,1,3,95,12,21,4,11,8,59,24,5,21,4,9,15,8,7,21,3,26,5,11,6,7,17,65, 14,11,10,2,17,5,12,22,4,4,2,21,8,112,3,34,63,35,2,25,1,2,15,65,23,0,3,5,15, 26,27,9,5,48,11,15,4,9,5,33,20,15,1,18,19,11,24,40,10,21,74,6,6,32,30,40,5, 4,7,44,10,25,46,16,12,5,40,7,18,5,18,9,12,8,4,25,5,6,36,4,43,8,9,12,35,17,4, 8,9,11,27,5,10,17,40,8,12,4,18,9,18,12,20,25,39,42,1,24,13,22,15,7,112,35,3, 7,17,33,2,5,5,19,8,4,12,24,14,13,2,1,13,6,5,19,11,7,57,0,19,6,117,48,14,8, 10,51,17,12,14,2,5,8,9,15,4,48,53,13,22,4,25,12,11,19,45,5,2,6,54,22,9,15,9, 13,2,7,11,29,82,16,46,4,26,14,26,40,22,4,26,6,18,13,4,4,20,3,3,7,12,17,8,9, 23,6,20,7,25,23,19,5,15,6,23,15,11,19,11,3,17,59,8,18,41,4,54,23,44,75,13, 20,6,11,2,3,1,13,10,3,7,12,3,4,7,8,30,6,6,7,3,32,9,5,28,6,114,42,13,36,27, 59,6,93,13,74,8,69,140,3,1,17,48,105,6,11,5,15,1,10,10,14,8,53,0,8,24,60,2, 6,35,2,12,32,47,16,17,75,2,5,4,37,28,10,5,9,57,4,59,5,12,13,7,90,5,11,5,24, 22,13,30,1,2,10,9,6,19,3,18,47,2,5,7,9,35,15,3,6,1,21,14,14,18,14,9,12,8,73, 6,19,3,32,9,14,17,17,5,55,23,6,16,28,3,11,48,4,6,6,6,12,16,30,10,30,27,51, 18,29,2,3,15,1,76,0,16,33,4,27,3,62,4,10,2,4,8,15,9,41,26,22,2,4,20,4,49,0, 8,1,57,13,12,39,3,63,10,19,34,35,2,7,8,29,72,4,10,0,77,8,6,7,9,15,21,9,4,1, 20,23,1,9,18,9,15,36,4,7,6,15,5,7,7,40,2,9,22,2,3,20,4,12,34,13,6,18,15,1, 38,20,12,7,16,3,19,85,12,16,18,16,2,17,1,13,8,6,12,15,97,17,12,9,3,21,15,12, 23,44,81,26,30,2,5,17,6,6,0,22,42,19,6,19,41,14,36,7,3,56,7,9,3,2,6,9,69,3, 15,4,30,28,29,7,9,15,17,17,6,1,6,153,9,33,5,12,14,16,28,3,8,7,14,12,4,6,36, 9,24,13,13,4,2,9,15,19,9,53,7,13,4,150,17,9,2,6,12,7,3,5,58,19,58,28,8,14,3, 20,3,0,32,56,7,5,4,27,1,68,4,29,13,5,58,2,9,65,41,27,16,15,12,14,2,10,9,24, 3,2,9,2,2,3,14,32,10,22,3,13,11,4,6,39,17,0,10,5,5,10,35,16,19,14,1,8,63,19, 14,8,56,10,2,12,6,12,6,7,16,2,9,9,12,20,73,25,13,21,17,24,5,32,8,12,25,8,14, 16,5,23,3,7,6,3,11,24,6,30,4,21,13,28,4,6,29,15,5,17,6,26,8,15,8,3,7,7,50, 11,30,6,2,28,56,16,24,25,23,24,89,31,31,12,7,22,4,10,17,3,3,8,11,13,5,3,27, 1,12,1,14,8,10,29,2,5,2,2,20,10,0,31,10,21,1,48,3,5,43,4,5,18,13,5,18,25,34, 18,3,5,22,16,3,4,20,3,9,3,25,6,6,44,21,3,12,7,5,42,3,2,14,4,36,5,3,45,51,15, 9,11,28,9,7,6,6,12,26,5,14,10,11,42,55,13,21,4,28,6,7,23,27,11,1,41,36,0,32, 15,26,2,3,23,32,11,2,15,7,29,26,144,33,20,12,7,21,10,7,11,65,46,10,13,20,32, 4,4,5,19,2,19,15,49,41,1,75,10,11,25,1,2,45,11,8,27,18,10,60,28,29,12,30,19, 16,4,24,11,19,27,17,49,18,7,40,13,19,22,8,55,12,11,3,6,5,11,8,10,22,5,9,9, 25,7,17,7,64,1,24,2,12,17,44,4,12,27,21,11,10,7,47,5,9,13,12,38,27,21,7,29, 7,1,17,3,3,5,48,62,10,3,11,17,15,15,6,3,8,10,8,18,19,13,3,9,7,6,44,9,10,4, 43,8,6,6,14,20,38,24,2,4,5,5,7,5,9,39,8,44,40,9,19,7,3,15,25,2,37,18,15,9,5, 8,32,10,5,18,4,7,46,20,17,23,4,11,16,18,31,11,3,11,1,14,1,25,4,27,13,13,39, 14,6,6,35,6,16,13,11,122,21,15,20,24,10,5,152,15,39,5,20,16,9,14,7,53,6,3,8, 19,63,32,6,2,3,20,1,19,5,13,42,15,4,6,68,31,46,11,38,10,24,5,5,8,9,12,3,35, 46,26,16,2,8,4,74,16,44,4,5,1,16,4,14,23,16,69,15,42,31,14,7,7,6,97,14,40,1, 8,7,34,9,39,19,13,15,10,21,18,10,5,15,38,7,5,12,7,20,15,4,11,6,14,5,17,7,39, 35,36,18,20,26,22,4,2,36,21,64,0,5,9,10,6,4,1,7,3,1,3,3,4,10,20,90,2,22,48, 16,23,2,33,40,1,21,21,17,20,8,8,12,4,83,14,48,4,21,3,9,27,5,11,40,15,9,3,16, 17,9,11,4,24,31,17,3,4,2,11,1,8,4,8,6,41,17,4,13,3,7,17,8,27,5,13,6,10,7,13, 12,18,13,60,18,3,8,1,12,125,2,7,16,2,11,2,4,7,26,5,9,14,14,16,8,14,7,14,6,9, 13,9,6,4,26,35,49,36,55,3,9,6,40,26,23,31,19,41,2,10,31,6,54,5,69,16,7,8,16, 1,5,7,4,22,7,7,5,4,48,11,13,3,98,4,11,19,4,2,14,7,34,7,10,3,2,12,7,6,2,5,118 }, }; uint8_t data[1<<15]; string data_str; void init_data() { static bool initted = false; if (initted) return; initted = true; // Repeatability. Kind of. std::srand(42); for (unsigned char & i : data) { i = (uint8_t)rand(); } data_str.assign((char*)data, sizeof(data)); } BOOST_AUTO_TEST_SUITE( TBufferBaseTest ) BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_GetBuffer ) { init_data(); for (auto & d1 : dist) { TMemoryBuffer buffer(16); int offset = 0; int index = 0; while (offset < 1<<15) { buffer.write(&data[offset], d1[index]); offset += d1[index]; index++; } string output = buffer.getBufferAsString(); BOOST_CHECK_EQUAL(data_str, output); } } BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read ) { init_data(); for (auto & d1 : dist) { for (auto & d2 : dist) { TMemoryBuffer buffer(16); uint8_t data_out[1<<15]; int offset; int index; offset = 0; index = 0; while (offset < 1<<15) { buffer.write(&data[offset], d1[index]); offset += d1[index]; index++; } offset = 0; index = 0; while (offset < 1<<15) { unsigned int got = buffer.read(&data_out[offset], d2[index]); BOOST_CHECK_EQUAL(got, d2[index]); offset += d2[index]; index++; } BOOST_CHECK(!memcmp(data, data_out, sizeof(data))); } } } BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_ReadString ) { init_data(); for (auto & d1 : dist) { for (auto & d2 : dist) { TMemoryBuffer buffer(16); string output; int offset; int index; offset = 0; index = 0; while (offset < 1<<15) { buffer.write(&data[offset], d1[index]); offset += d1[index]; index++; } offset = 0; index = 0; while (offset < 1<<15) { unsigned int got = buffer.readAppendToString(output, d2[index]); BOOST_CHECK_EQUAL(got, d2[index]); offset += d2[index]; index++; } BOOST_CHECK_EQUAL(output, data_str); } } } BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi1 ) { init_data(); // Do shorter writes and reads so we don't align to power-of-two boundaries. for (auto & d1 : dist) { for (auto & d2 : dist) { TMemoryBuffer buffer(16); uint8_t data_out[1<<15]; int offset; int index; for (int iter = 0; iter < 6; iter++) { offset = 0; index = 0; while (offset < (1<<15)-42) { buffer.write(&data[offset], d1[index]); offset += d1[index]; index++; } offset = 0; index = 0; while (offset < (1<<15)-42) { buffer.read(&data_out[offset], d2[index]); offset += d2[index]; index++; } BOOST_CHECK(!memcmp(data, data_out, (1<<15)-42)); // Pull out the extra data. buffer.read(data_out, 42); } } } } BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi2 ) { init_data(); // Do shorter writes and reads so we don't align to power-of-two boundaries. // Pull the buffer out of the loop so its state gets worked harder. TMemoryBuffer buffer(16); for (auto & d1 : dist) { for (auto & d2 : dist) { uint8_t data_out[1<<15]; int offset; int index; for (int iter = 0; iter < 6; iter++) { offset = 0; index = 0; while (offset < (1<<15)-42) { buffer.write(&data[offset], d1[index]); offset += d1[index]; index++; } offset = 0; index = 0; while (offset < (1<<15)-42) { buffer.read(&data_out[offset], d2[index]); offset += d2[index]; index++; } BOOST_CHECK(!memcmp(data, data_out, (1<<15)-42)); // Pull out the extra data. buffer.read(data_out, 42); } } } } BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Incomplete ) { init_data(); // Do shorter writes and reads so we don't align to power-of-two boundaries. // Pull the buffer out of the loop so its state gets worked harder. for (auto & d1 : dist) { for (auto & d2 : dist) { TMemoryBuffer buffer(16); uint8_t data_out[1<<13]; int write_offset = 0; int write_index = 0; unsigned int to_write = (1<<14)-42; while (to_write > 0) { int write_amt = (std::min)(d1[write_index], to_write); buffer.write(&data[write_offset], write_amt); write_offset += write_amt; write_index++; to_write -= write_amt; } int read_offset = 0; int read_index = 0; unsigned int to_read = (1<<13)-42; while (to_read > 0) { int read_amt = (std::min)(d2[read_index], to_read); int got = buffer.read(&data_out[read_offset], read_amt); BOOST_CHECK_EQUAL(got, read_amt); read_offset += read_amt; read_index++; to_read -= read_amt; } BOOST_CHECK(!memcmp(data, data_out, (1<<13)-42)); int second_offset = write_offset; int second_index = write_index-1; unsigned int to_second = (1<<14)+42; while (to_second > 0) { int second_amt = (std::min)(d1[second_index], to_second); //printf("%d\n", second_amt); buffer.write(&data[second_offset], second_amt); second_offset += second_amt; second_index++; to_second -= second_amt; } string output = buffer.getBufferAsString(); BOOST_CHECK_EQUAL(data_str.substr((1<<13)-42), output); } } } BOOST_AUTO_TEST_CASE( test_BufferedTransport_Write ) { init_data(); int sizes[] = { 12, 15, 16, 17, 20, 501, 512, 523, 2000, 2048, 2096, 1<<14, 1<<17, }; for (int size : sizes) { for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(16)); TBufferedTransport trans(buffer, size); int offset = 0; int index = 0; while (offset < 1<<15) { trans.write(&data[offset], d1[index]); offset += d1[index]; index++; } trans.flush(); string output = buffer->getBufferAsString(); BOOST_CHECK_EQUAL(data_str, output); } } } BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Full ) { init_data(); int sizes[] = { 12, 15, 16, 17, 20, 501, 512, 523, 2000, 2048, 2096, 1<<14, 1<<17, }; for (int size : sizes) { for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(data, sizeof(data))); TBufferedTransport trans(buffer, size); uint8_t data_out[1<<15]; int offset = 0; int index = 0; while (offset < 1<<15) { // Note: this doesn't work with "read" because TBufferedTransport // doesn't try loop over reads, so we get short reads. We don't // check the return value, so that messes us up. trans.readAll(&data_out[offset], d1[index]); offset += d1[index]; index++; } BOOST_CHECK(!memcmp(data, data_out, sizeof(data))); } } } BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Short ) { init_data(); int sizes[] = { 12, 15, 16, 17, 20, 501, 512, 523, 2000, 2048, 2096, 1<<14, 1<<17, }; for (int size : sizes) { for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(data, sizeof(data))); shared_ptr tshort(new TShortReadTransport(buffer, 0.125)); TBufferedTransport trans(buffer, size); uint8_t data_out[1<<15]; int offset = 0; int index = 0; while (offset < 1<<15) { // Note: this doesn't work with "read" because TBufferedTransport // doesn't try loop over reads, so we get short reads. We don't // check the return value, so that messes us up. trans.readAll(&data_out[offset], d1[index]); offset += d1[index]; index++; } BOOST_CHECK(!memcmp(data, data_out, sizeof(data))); } } } BOOST_AUTO_TEST_CASE( test_FramedTransport_Write ) { init_data(); int sizes[] = { 12, 15, 16, 17, 20, 501, 512, 523, 2000, 2048, 2096, 1<<14, 1<<17, }; for (int size : sizes) { for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(16)); TFramedTransport trans(buffer, size); int offset = 0; int index = 0; while (offset < 1<<15) { trans.write(&data[offset], d1[index]); offset += d1[index]; index++; } trans.flush(); int32_t frame_size = -1; buffer->read(reinterpret_cast(&frame_size), sizeof(frame_size)); frame_size = (int32_t)ntohl((uint32_t)frame_size); BOOST_CHECK_EQUAL(frame_size, 1<<15); BOOST_CHECK_EQUAL(data_str.size(), (unsigned int)frame_size); string output = buffer->getBufferAsString(); BOOST_CHECK_EQUAL(data_str, output); } } } BOOST_AUTO_TEST_CASE( test_FramedTransport_Read ) { init_data(); for (auto & d1 : dist) { uint8_t data_out[1<<15]; shared_ptr buffer(new TMemoryBuffer()); TFramedTransport trans(buffer); int32_t length = sizeof(data); length = (int32_t)htonl((uint32_t)length); buffer->write(reinterpret_cast(&length), sizeof(length)); buffer->write(data, sizeof(data)); int offset = 0; int index = 0; while (offset < 1<<15) { // This should work with read because we have one huge frame. trans.read(&data_out[offset], d1[index]); offset += d1[index]; index++; } BOOST_CHECK(!memcmp(data, data_out, sizeof(data))); } } BOOST_AUTO_TEST_CASE( test_FramedTransport_Write_Read ) { init_data(); int sizes[] = { 12, 15, 16, 17, 20, 501, 512, 523, 2000, 2048, 2096, 1<<14, 1<<17, }; int probs[] = { 1, 2, 4, 8, 16, 32, }; for (int size : sizes) { for (int prob : probs) { for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(16)); TFramedTransport trans(buffer, size); std::vector data_out(1<<17, 0); std::vector flush_sizes; int write_offset = 0; int write_index = 0; int flush_size = 0; while (write_offset < 1<<15) { trans.write(&data[write_offset], d1[write_index]); write_offset += d1[write_index]; flush_size += d1[write_index]; write_index++; if (flush_size > 0 && rand()%prob == 0) { flush_sizes.push_back(flush_size); flush_size = 0; trans.flush(); } } if (flush_size != 0) { flush_sizes.push_back(flush_size); flush_size = 0; trans.flush(); } int read_offset = 0; int read_index = 0; for (int fsize : flush_sizes) { // We are exploiting an implementation detail of TFramedTransport. // The read buffer starts empty and it will never do more than one // readFrame per read, so we should always get exactly one frame. int got = trans.read(&data_out[read_offset], 1<<15); BOOST_CHECK_EQUAL(got, fsize); read_offset += got; read_index++; } BOOST_CHECK_EQUAL((unsigned int)read_offset, sizeof(data)); BOOST_CHECK(!memcmp(data, &data_out[0], sizeof(data))); } } } } BOOST_AUTO_TEST_CASE( test_FramedTransport_Empty_Flush ) { init_data(); string output1("\x00\x00\x00\x01""a", 5); string output2("\x00\x00\x00\x01""a\x00\x00\x00\x02""bc", 11); shared_ptr buffer(new TMemoryBuffer()); TFramedTransport trans(buffer); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), ""); trans.flush(); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), ""); trans.flush(); trans.flush(); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), ""); trans.write((const uint8_t*)"a", 1); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), ""); trans.flush(); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output1); trans.flush(); trans.flush(); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output1); trans.write((const uint8_t*)"bc", 2); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output1); trans.flush(); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output2); trans.flush(); trans.flush(); BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output2); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/Base64Test.cpp0000644000000000000000000000412514303740367020007 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include using apache::thrift::protocol::base64_encode; using apache::thrift::protocol::base64_decode; BOOST_AUTO_TEST_SUITE(Base64Test) void setupTestData(int i, uint8_t* data, int& len) { len = 0; do { data[len] = (uint8_t)(i & 0xFF); i >>= 8; len++; } while ((len < 3) && (i != 0)); BOOST_ASSERT(i == 0); } void checkEncoding(uint8_t* data, int len) { #ifdef NDEBUG ((void)data); #endif for (int i = 0; i < len; i++) { BOOST_ASSERT(isalnum(data[i]) || data[i] == '/' || data[i] == '+'); } } BOOST_AUTO_TEST_CASE(test_Base64_Encode_Decode) { int len; uint8_t testInput[3]; uint8_t testOutput[4]; // Test all possible encoding / decoding cases given the // three byte limit for base64_encode. for (int i = 0xFFFFFF; i >= 0; i--) { // fill testInput based on i setupTestData(i, testInput, len); // encode the test data, then decode it again base64_encode(testInput, len, testOutput); // verify each byte has a valid Base64 value (alphanumeric or either + or /) checkEncoding(testOutput, len); // decode output and check that it matches input base64_decode(testOutput, len + 1); BOOST_ASSERT(0 == memcmp(testInput, testOutput, len)); } } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/concurrency/0000777000000000000000000000000014472652702017755 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/test/concurrency/Tests.cpp0000644000000000000000000001530114303740367021555 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include "ThreadFactoryTests.h" #include "TimerManagerTests.h" #include "ThreadManagerTests.h" // The test weight, where 10 is 10 times more threads than baseline // and the baseline is optimized for running in valgrind static int WEIGHT = 10; int main(int argc, char** argv) { std::vector args(argc - 1 > 1 ? argc - 1 : 1); args[0] = "all"; for (int ix = 1; ix < argc; ix++) { args[ix - 1] = std::string(argv[ix]); } if (getenv("VALGRIND") != nullptr) { // lower the scale of every test WEIGHT = 1; } bool runAll = args[0].compare("all") == 0; if (runAll || args[0].compare("thread-factory") == 0) { ThreadFactoryTests threadFactoryTests; std::cout << "ThreadFactory tests..." << std::endl; int reapLoops = 2 * WEIGHT; int reapCount = 100 * WEIGHT; size_t floodLoops = 3; size_t floodCount = 500 * WEIGHT; std::cout << "\t\tThreadFactory reap N threads test: N = " << reapLoops << "x" << reapCount << std::endl; if (!threadFactoryTests.reapNThreads(reapLoops, reapCount)) { std::cerr << "\t\ttThreadFactory reap N threads FAILED" << std::endl; return 1; } std::cout << "\t\tThreadFactory flood N threads test: N = " << floodLoops << "x" << floodCount << std::endl; if (!threadFactoryTests.floodNTest(floodLoops, floodCount)) { std::cerr << "\t\ttThreadFactory flood N threads FAILED" << std::endl; return 1; } std::cout << "\t\tThreadFactory synchronous start test" << std::endl; if (!threadFactoryTests.synchStartTest()) { std::cerr << "\t\ttThreadFactory synchronous start FAILED" << std::endl; return 1; } std::cout << "\t\tThreadFactory monitor timeout test" << std::endl; if (!threadFactoryTests.monitorTimeoutTest()) { std::cerr << "\t\ttThreadFactory monitor timeout FAILED" << std::endl; return 1; } } if (runAll || args[0].compare("util") == 0) { std::cout << "Util tests..." << std::endl; std::cout << "\t\tUtil minimum time" << std::endl; int64_t time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); int64_t time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); std::cout << "\t\t\tMinimum time: " << time01 - time00 << "ms" << std::endl; time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); time01 = time00; size_t count = 0; while (time01 < time00 + 10) { count++; time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } std::cout << "\t\t\tscall per ms: " << count / (time01 - time00) << std::endl; } if (runAll || args[0].compare("timer-manager") == 0) { std::cout << "TimerManager tests..." << std::endl; std::cout << "\t\tTimerManager test00" << std::endl; TimerManagerTests timerManagerTests; if (!timerManagerTests.test00()) { std::cerr << "\t\tTimerManager tests FAILED" << std::endl; return 1; } std::cout << "\t\tTimerManager test01" << std::endl; if (!timerManagerTests.test01()) { std::cerr << "\t\tTimerManager tests FAILED" << std::endl; return 1; } std::cout << "\t\tTimerManager test02" << std::endl; if (!timerManagerTests.test02()) { std::cerr << "\t\tTimerManager tests FAILED" << std::endl; return 1; } std::cout << "\t\tTimerManager test03" << std::endl; if (!timerManagerTests.test03()) { std::cerr << "\t\tTimerManager tests FAILED" << std::endl; return 1; } std::cout << "\t\tTimerManager test04" << std::endl; if (!timerManagerTests.test04()) { std::cerr << "\t\tTimerManager tests FAILED" << std::endl; return 1; } } if (runAll || args[0].compare("thread-manager") == 0) { std::cout << "ThreadManager tests..." << std::endl; { size_t workerCount = 10 * WEIGHT; size_t taskCount = 500 * WEIGHT; int64_t delay = 10LL; ThreadManagerTests threadManagerTests; std::cout << "\t\tThreadManager api test:" << std::endl; if (!threadManagerTests.apiTest()) { std::cerr << "\t\tThreadManager apiTest FAILED" << std::endl; return 1; } std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; if (!threadManagerTests.loadTest(taskCount, delay, workerCount)) { std::cerr << "\t\tThreadManager loadTest FAILED" << std::endl; return 1; } std::cout << "\t\tThreadManager block test: worker count: " << workerCount << " delay: " << delay << std::endl; if (!threadManagerTests.blockTest(delay, workerCount)) { std::cerr << "\t\tThreadManager blockTest FAILED" << std::endl; return 1; } } } if (runAll || args[0].compare("thread-manager-benchmark") == 0) { std::cout << "ThreadManager benchmark tests..." << std::endl; { size_t minWorkerCount = 2; size_t maxWorkerCount = 8; size_t tasksPerWorker = 100 * WEIGHT; int64_t delay = 5LL; for (size_t workerCount = minWorkerCount; workerCount <= maxWorkerCount; workerCount *= 4) { size_t taskCount = workerCount * tasksPerWorker; std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; ThreadManagerTests threadManagerTests; if (!threadManagerTests.loadTest(taskCount, delay, workerCount)) { std::cerr << "\t\tThreadManager loadTest FAILED" << std::endl; return 1; } } } } std::cout << "ALL TESTS PASSED" << std::endl; return 0; } thrift-0.19.0/lib/cpp/test/concurrency/TimerManagerTests.h0000644000000000000000000002175014303740367023523 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace concurrency { namespace test { using namespace apache::thrift::concurrency; class TimerManagerTests { public: class Task : public Runnable { public: Task(Monitor& monitor, uint64_t timeout) : _timeout(timeout), _startTime(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()), _endTime(0), _monitor(monitor), _success(false), _done(false) {} ~Task() override { std::cerr << this << std::endl; } void run() override { _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _success = (_endTime - _startTime) >= _timeout; { Synchronized s(_monitor); _done = true; _monitor.notifyAll(); } } int64_t _timeout; int64_t _startTime; int64_t _endTime; Monitor& _monitor; bool _success; bool _done; }; /** * This test creates two tasks and waits for the first to expire within 10% * of the expected expiration time. It then verifies that the timer manager * properly clean up itself and the remaining orphaned timeout task when the * manager goes out of scope and its destructor is called. */ bool test00(uint64_t timeout = 1000LL) { shared_ptr orphanTask = shared_ptr(new TimerManagerTests::Task(_monitor, 10 * timeout)); { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); if (timerManager.state() != TimerManager::STARTED) { std::cerr << "timerManager is not in the STARTED state, but should be" << std::endl; return false; } // Don't create task yet, because its constructor sets the expected completion time, and we // need to delay between inserting the two tasks into the run queue. shared_ptr task; { Synchronized s(_monitor); timerManager.add(orphanTask, 10 * timeout); std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); task.reset(new TimerManagerTests::Task(_monitor, timeout)); timerManager.add(task, timeout); _monitor.wait(); } if (!task->_done) { std::cerr << "task is not done, but it should have executed" << std::endl; return false; } std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl; } if (orphanTask->_done) { std::cerr << "orphan task is done, but it should not have executed" << std::endl; return false; } return true; } /** * This test creates two tasks, removes the first one then waits for the second one. It then * verifies that the timer manager properly clean up itself and the remaining orphaned timeout * task when the manager goes out of scope and its destructor is called. */ bool test01(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); Synchronized s(_monitor); // Setup the two tasks shared_ptr taskToRemove = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 2)); timerManager.add(taskToRemove, taskToRemove->_timeout); shared_ptr task = shared_ptr(new TimerManagerTests::Task(_monitor, timeout)); timerManager.add(task, task->_timeout); // Remove one task and wait until the other has completed timerManager.remove(taskToRemove); _monitor.wait(timeout * 2); assert(!taskToRemove->_done); assert(task->_done); return true; } /** * This test creates two tasks with the same callback and another one, then removes the two * duplicated then waits for the last one. It then verifies that the timer manager properly * clean up itself and the remaining orphaned timeout task when the manager goes out of scope * and its destructor is called. */ bool test02(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); Synchronized s(_monitor); // Setup the one tasks and add it twice shared_ptr taskToRemove = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 3)); timerManager.add(taskToRemove, taskToRemove->_timeout); timerManager.add(taskToRemove, taskToRemove->_timeout * 2); shared_ptr task = shared_ptr(new TimerManagerTests::Task(_monitor, timeout)); timerManager.add(task, task->_timeout); // Remove the first task (e.g. two timers) and wait until the other has completed timerManager.remove(taskToRemove); _monitor.wait(timeout * 2); assert(!taskToRemove->_done); assert(task->_done); return true; } /** * This test creates two tasks, removes the first one then waits for the second one. It then * verifies that the timer manager properly clean up itself and the remaining orphaned timeout * task when the manager goes out of scope and its destructor is called. */ bool test03(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); Synchronized s(_monitor); // Setup the two tasks shared_ptr taskToRemove = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 2)); TimerManager::Timer timer = timerManager.add(taskToRemove, taskToRemove->_timeout); shared_ptr task = shared_ptr(new TimerManagerTests::Task(_monitor, timeout)); timerManager.add(task, task->_timeout); // Remove one task and wait until the other has completed timerManager.remove(timer); _monitor.wait(timeout * 2); assert(!taskToRemove->_done); assert(task->_done); // Verify behavior when removing the removed task try { timerManager.remove(timer); assert(nullptr == "ERROR: This remove should send a NoSuchTaskException exception."); } catch (NoSuchTaskException&) { } return true; } /** * This test creates one task, and tries to remove it after it has expired. */ bool test04(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); Synchronized s(_monitor); // Setup the task shared_ptr task = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 10)); TimerManager::Timer timer = timerManager.add(task, task->_timeout); task.reset(); // Wait until the task has completed _monitor.wait(timeout); // Verify behavior when removing the expired task // notify is called inside the task so the task may still // be running when we get here, so we need to loop... for (;;) { try { timerManager.remove(timer); assert(nullptr == "ERROR: This remove should throw NoSuchTaskException, or UncancellableTaskException."); } catch (const NoSuchTaskException&) { break; } catch (const UncancellableTaskException&) { // the thread was still exiting; try again... std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } return true; } friend class TestTask; Monitor _monitor; }; } } } } // apache::thrift::concurrency thrift-0.19.0/lib/cpp/test/concurrency/ThreadManagerTests.h0000644000000000000000000004607314303740367023657 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace concurrency { namespace test { using namespace apache::thrift::concurrency; static std::deque > m_expired; static void expiredNotifier(std::shared_ptr runnable) { m_expired.push_back(runnable); } static void sleep_(int64_t millisec) { Monitor _sleep; Synchronized s(_sleep); try { _sleep.wait(millisec); } catch (TimedOutException&) { ; } catch (...) { assert(0); } } class ThreadManagerTests { public: class Task : public Runnable { public: Task(Monitor& monitor, size_t& count, int64_t timeout) : _monitor(monitor), _count(count), _timeout(timeout), _startTime(0), _endTime(0), _done(false) {} void run() override { _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); sleep_(_timeout); _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _done = true; { Synchronized s(_monitor); // std::cout << "Thread " << _count << " completed " << std::endl; _count--; if (_count % 10000 == 0) { _monitor.notify(); } } } Monitor& _monitor; size_t& _count; int64_t _timeout; int64_t _startTime; int64_t _endTime; bool _done; Monitor _sleep; }; /** * Dispatch count tasks, each of which blocks for timeout milliseconds then * completes. Verify that all tasks completed and that thread manager cleans * up properly on delete. */ bool loadTest(size_t count = 100, int64_t timeout = 100LL, size_t workerCount = 4) { Monitor monitor; size_t activeCount = count; shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); shared_ptr threadFactory = shared_ptr(new ThreadFactory(false)); threadManager->threadFactory(threadFactory); threadManager->start(); std::set > tasks; for (size_t ix = 0; ix < count; ix++) { tasks.insert(shared_ptr( new ThreadManagerTests::Task(monitor, activeCount, timeout))); } int64_t time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); for (auto ix = tasks.begin(); ix != tasks.end(); ix++) { threadManager->add(*ix); } std::cout << "\t\t\t\tloaded " << count << " tasks to execute" << std::endl; { Synchronized s(monitor); while (activeCount > 0) { std::cout << "\t\t\t\tactiveCount = " << activeCount << std::endl; monitor.wait(); } } int64_t time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); int64_t firstTime = 9223372036854775807LL; int64_t lastTime = 0; double averageTime = 0; int64_t minTime = 9223372036854775807LL; int64_t maxTime = 0; for (auto ix = tasks.begin(); ix != tasks.end(); ix++) { shared_ptr task = *ix; int64_t delta = task->_endTime - task->_startTime; assert(delta > 0); if (task->_startTime < firstTime) { firstTime = task->_startTime; } if (task->_endTime > lastTime) { lastTime = task->_endTime; } if (delta < minTime) { minTime = delta; } if (delta > maxTime) { maxTime = delta; } averageTime += delta; } averageTime /= count; std::cout << "\t\t\tfirst start: " << firstTime << " Last end: " << lastTime << " min: " << minTime << "ms max: " << maxTime << "ms average: " << averageTime << "ms" << std::endl; bool success = (time01 - time00) >= ((int64_t)count * timeout) / (int64_t)workerCount; std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << ((int64_t)count * timeout) / (int64_t)workerCount << "ms elapsed time: " << time01 - time00 << "ms" << std::endl; return success; } class BlockTask : public Runnable { public: BlockTask(Monitor& entryMonitor, Monitor& blockMonitor, bool& blocked, Monitor& doneMonitor, size_t& count) : _entryMonitor(entryMonitor), _entered(false), _blockMonitor(blockMonitor), _blocked(blocked), _doneMonitor(doneMonitor), _count(count) {} void run() override { { Synchronized s(_entryMonitor); _entered = true; _entryMonitor.notify(); } { Synchronized s(_blockMonitor); while (_blocked) { _blockMonitor.wait(); } } { Synchronized s(_doneMonitor); if (--_count == 0) { _doneMonitor.notify(); } } } Monitor& _entryMonitor; bool _entered; Monitor& _blockMonitor; bool& _blocked; Monitor& _doneMonitor; size_t& _count; }; /** * Block test. Create pendingTaskCountMax tasks. Verify that we block adding the * pendingTaskCountMax + 1th task. Verify that we unblock when a task completes */ bool blockTest(int64_t timeout = 100LL, size_t workerCount = 2) { (void)timeout; bool success = false; try { Monitor entryMonitor; // not used by this test Monitor blockMonitor; bool blocked[] = {true, true, true}; Monitor doneMonitor; size_t pendingTaskMaxCount = workerCount; size_t activeCounts[] = {workerCount, pendingTaskMaxCount, 1}; shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount, pendingTaskMaxCount); shared_ptr threadFactory = shared_ptr(new ThreadFactory()); threadManager->threadFactory(threadFactory); threadManager->start(); std::vector > tasks; tasks.reserve(workerCount + pendingTaskMaxCount); for (size_t ix = 0; ix < workerCount; ix++) { tasks.push_back(shared_ptr( new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[0], doneMonitor, activeCounts[0]))); } for (size_t ix = 0; ix < pendingTaskMaxCount; ix++) { tasks.push_back(shared_ptr( new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[1], doneMonitor, activeCounts[1]))); } for (auto ix = tasks.begin(); ix != tasks.end(); ix++) { threadManager->add(*ix); } if (!(success = (threadManager->totalTaskCount() == pendingTaskMaxCount + workerCount))) { throw TException("Unexpected pending task count"); } shared_ptr extraTask( new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[2], doneMonitor, activeCounts[2])); try { threadManager->add(extraTask, 1); throw TException("Unexpected success adding task in excess of pending task count"); } catch (TooManyPendingTasksException&) { throw TException("Should have timed out adding task in excess of pending task count"); } catch (TimedOutException&) { // Expected result } try { threadManager->add(extraTask, -1); throw TException("Unexpected success adding task in excess of pending task count"); } catch (TimedOutException&) { throw TException("Unexpected timeout adding task in excess of pending task count"); } catch (TooManyPendingTasksException&) { // Expected result } std::cout << "\t\t\t" << "Pending tasks " << threadManager->pendingTaskCount() << std::endl; { Synchronized s(blockMonitor); blocked[0] = false; blockMonitor.notifyAll(); } { Synchronized s(doneMonitor); while (activeCounts[0] != 0) { doneMonitor.wait(); } } std::cout << "\t\t\t" << "Pending tasks " << threadManager->pendingTaskCount() << std::endl; try { threadManager->add(extraTask, 1); } catch (TimedOutException&) { std::cout << "\t\t\t" << "add timed out unexpectedly" << std::endl; throw TException("Unexpected timeout adding task"); } catch (TooManyPendingTasksException&) { std::cout << "\t\t\t" << "add encountered too many pending exepctions" << std::endl; throw TException("Unexpected timeout adding task"); } // Wake up tasks that were pending before and wait for them to complete { Synchronized s(blockMonitor); blocked[1] = false; blockMonitor.notifyAll(); } { Synchronized s(doneMonitor); while (activeCounts[1] != 0) { doneMonitor.wait(); } } // Wake up the extra task and wait for it to complete { Synchronized s(blockMonitor); blocked[2] = false; blockMonitor.notifyAll(); } { Synchronized s(doneMonitor); while (activeCounts[2] != 0) { doneMonitor.wait(); } } threadManager->stop(); if (!(success = (threadManager->totalTaskCount() == 0))) { throw TException("Unexpected total task count"); } } catch (TException& e) { std::cout << "ERROR: " << e.what() << std::endl; } std::cout << "\t\t\t" << (success ? "Success" : "Failure") << std::endl; return success; } bool apiTest() { // prove currentTime has milliseconds granularity since many other things depend on it int64_t a = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); sleep_(100); int64_t b = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); if (b - a < 50 || b - a > 150) { std::cerr << "\t\t\texpected 100ms gap, found " << (b-a) << "ms gap instead." << std::endl; return false; } return apiTestWithThreadFactory(shared_ptr(new ThreadFactory())); } bool apiTestWithThreadFactory(shared_ptr threadFactory) { shared_ptr threadManager = ThreadManager::newSimpleThreadManager(1); threadManager->threadFactory(threadFactory); std::cout << "\t\t\t\tstarting.. " << std::endl; threadManager->start(); threadManager->setExpireCallback(expiredNotifier); // std::bind(&ThreadManagerTests::expiredNotifier, this)); #define EXPECT(FUNC, COUNT) { size_t c = FUNC; if (c != COUNT) { std::cerr << "expected " #FUNC" to be " #COUNT ", but was " << c << std::endl; return false; } } EXPECT(threadManager->workerCount(), 1); EXPECT(threadManager->idleWorkerCount(), 1); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tadd 2nd worker.. " << std::endl; threadManager->addWorker(); EXPECT(threadManager->workerCount(), 2); EXPECT(threadManager->idleWorkerCount(), 2); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tremove 2nd worker.. " << std::endl; threadManager->removeWorker(); EXPECT(threadManager->workerCount(), 1); EXPECT(threadManager->idleWorkerCount(), 1); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tremove 1st worker.. " << std::endl; threadManager->removeWorker(); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tadd blocking task.. " << std::endl; // We're going to throw a blocking task into the mix Monitor entryMonitor; // signaled when task is running Monitor blockMonitor; // to be signaled to unblock the task bool blocked(true); // set to false before notifying Monitor doneMonitor; // signaled when count reaches zero size_t activeCount = 1; shared_ptr blockingTask( new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked, doneMonitor, activeCount)); threadManager->add(blockingTask); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 1); std::cout << "\t\t\t\tadd other task.. " << std::endl; shared_ptr otherTask( new ThreadManagerTests::Task(doneMonitor, activeCount, 0)); threadManager->add(otherTask); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 2); std::cout << "\t\t\t\tremove blocking task specifically.. " << std::endl; threadManager->remove(blockingTask); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 1); std::cout << "\t\t\t\tremove next pending task.." << std::endl; shared_ptr nextTask = threadManager->removeNextPending(); if (nextTask != otherTask) { std::cerr << "\t\t\t\t\texpected removeNextPending to return otherTask" << std::endl; return false; } EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tremove next pending task (none left).." << std::endl; nextTask = threadManager->removeNextPending(); if (nextTask) { std::cerr << "\t\t\t\t\texpected removeNextPending to return an empty Runnable" << std::endl; return false; } std::cout << "\t\t\t\tadd 2 expired tasks and 1 not.." << std::endl; shared_ptr expiredTask( new ThreadManagerTests::Task(doneMonitor, activeCount, 0)); threadManager->add(expiredTask, 0, 1); threadManager->add(blockingTask); // add one that hasn't expired to make sure it gets skipped threadManager->add(expiredTask, 0, 1); // add a second expired to ensure removeExpiredTasks removes both sleep_(50); // make sure enough time elapses for it to expire - the shortest expiration time is 1 millisecond EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 3); EXPECT(threadManager->expiredTaskCount(), 0); std::cout << "\t\t\t\tremove expired tasks.." << std::endl; if (!m_expired.empty()) { std::cerr << "\t\t\t\t\texpected m_expired to be empty" << std::endl; return false; } threadManager->removeExpiredTasks(); if (m_expired.size() != 2) { std::cerr << "\t\t\t\t\texpected m_expired to be set" << std::endl; return false; } if (m_expired.front() != expiredTask) { std::cerr << "\t\t\t\t\texpected m_expired[0] to be the expired task" << std::endl; return false; } m_expired.pop_front(); if (m_expired.front() != expiredTask) { std::cerr << "\t\t\t\t\texpected m_expired[1] to be the expired task" << std::endl; return false; } m_expired.clear(); threadManager->remove(blockingTask); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 0); EXPECT(threadManager->expiredTaskCount(), 2); std::cout << "\t\t\t\tadd expired task (again).." << std::endl; threadManager->add(expiredTask, 0, 1); // expires in 1ms sleep_(50); // make sure enough time elapses for it to expire - the shortest expiration time is 1ms std::cout << "\t\t\t\tadd worker to consume expired task.." << std::endl; threadManager->addWorker(); sleep_(100); // make sure it has time to spin up and expire the task if (m_expired.empty()) { std::cerr << "\t\t\t\t\texpected m_expired to be set" << std::endl; return false; } if (m_expired.front() != expiredTask) { std::cerr << "\t\t\t\t\texpected m_expired to be the expired task" << std::endl; return false; } m_expired.clear(); EXPECT(threadManager->workerCount(), 1); EXPECT(threadManager->idleWorkerCount(), 1); EXPECT(threadManager->pendingTaskCount(), 0); EXPECT(threadManager->expiredTaskCount(), 3); std::cout << "\t\t\t\ttry to remove too many workers" << std::endl; try { threadManager->removeWorker(2); std::cerr << "\t\t\t\t\texpected InvalidArgumentException" << std::endl; return false; } catch (const InvalidArgumentException&) { /* expected */ } std::cout << "\t\t\t\tremove worker.. " << std::endl; threadManager->removeWorker(); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 0); EXPECT(threadManager->expiredTaskCount(), 3); std::cout << "\t\t\t\tadd blocking task.. " << std::endl; threadManager->add(blockingTask); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 1); std::cout << "\t\t\t\tadd worker.. " << std::endl; threadManager->addWorker(); { Synchronized s(entryMonitor); while (!blockingTask->_entered) { entryMonitor.wait(); } } EXPECT(threadManager->workerCount(), 1); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tunblock task and remove worker.. " << std::endl; { Synchronized s(blockMonitor); blocked = false; blockMonitor.notifyAll(); } threadManager->removeWorker(); EXPECT(threadManager->workerCount(), 0); EXPECT(threadManager->idleWorkerCount(), 0); EXPECT(threadManager->pendingTaskCount(), 0); std::cout << "\t\t\t\tcleanup.. " << std::endl; blockingTask.reset(); threadManager.reset(); return true; } }; } } } } // apache::thrift::concurrency using namespace apache::thrift::concurrency::test; thrift-0.19.0/lib/cpp/test/concurrency/ThreadFactoryTests.h0000644000000000000000000001710314303740367023704 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include namespace apache { namespace thrift { namespace concurrency { namespace test { using std::shared_ptr; using namespace apache::thrift::concurrency; /** * ThreadManagerTests class * * @version $Id:$ */ class ThreadFactoryTests { public: /** * Reap N threads */ class ReapNTask : public Runnable { public: ReapNTask(Monitor& monitor, int& activeCount) : _monitor(monitor), _count(activeCount) {} void run() override { Synchronized s(_monitor); if (--_count == 0) { _monitor.notify(); } } Monitor& _monitor; int& _count; }; bool reapNThreads(int loop = 1, int count = 10) { ThreadFactory threadFactory = ThreadFactory(); shared_ptr monitor(new Monitor); for (int lix = 0; lix < loop; lix++) { int activeCount = 0; std::vector > threads; int tix; for (tix = 0; tix < count; tix++) { try { ++activeCount; threads.push_back( threadFactory.newThread(shared_ptr(new ReapNTask(*monitor, activeCount)))); } catch (SystemResourceException& e) { std::cout << "\t\t\tfailed to create " << lix* count + tix << " thread " << e.what() << std::endl; throw; } } tix = 0; for (std::vector >::const_iterator thread = threads.begin(); thread != threads.end(); tix++, ++thread) { try { (*thread)->start(); } catch (SystemResourceException& e) { std::cout << "\t\t\tfailed to start " << lix* count + tix << " thread " << e.what() << std::endl; throw; } } { Synchronized s(*monitor); while (activeCount > 0) { monitor->wait(1000); } } std::cout << "\t\t\treaped " << lix* count << " threads" << std::endl; } std::cout << "\t\t\tSuccess!" << std::endl; return true; } class SynchStartTask : public Runnable { public: enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED }; SynchStartTask(Monitor& monitor, volatile STATE& state) : _monitor(monitor), _state(state) {} void run() override { { Synchronized s(_monitor); if (_state == SynchStartTask::STARTING) { _state = SynchStartTask::STARTED; _monitor.notify(); } } { Synchronized s(_monitor); while (_state == SynchStartTask::STARTED) { _monitor.wait(); } if (_state == SynchStartTask::STOPPING) { _state = SynchStartTask::STOPPED; _monitor.notifyAll(); } } } private: Monitor& _monitor; volatile STATE& _state; }; bool synchStartTest() { Monitor monitor; SynchStartTask::STATE state = SynchStartTask::UNINITIALIZED; shared_ptr task = shared_ptr(new SynchStartTask(monitor, state)); ThreadFactory threadFactory = ThreadFactory(); shared_ptr thread = threadFactory.newThread(task); if (state == SynchStartTask::UNINITIALIZED) { state = SynchStartTask::STARTING; thread->start(); } { Synchronized s(monitor); while (state == SynchStartTask::STARTING) { monitor.wait(); } } assert(state != SynchStartTask::STARTING); { Synchronized s(monitor); try { monitor.wait(100); } catch (TimedOutException&) { } if (state == SynchStartTask::STARTED) { state = SynchStartTask::STOPPING; monitor.notify(); } while (state == SynchStartTask::STOPPING) { monitor.wait(); } } assert(state == SynchStartTask::STOPPED); bool success = true; std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "!" << std::endl; return true; } /** * The only guarantee a monitor timeout can give you is that * it will take "at least" as long as the timeout, no less. * There is absolutely no guarantee around regaining execution * near the timeout. On a busy system (like inside a third party * CI environment) it could take quite a bit longer than the * requested timeout, and that's ok. */ bool monitorTimeoutTest(int64_t count = 1000, int64_t timeout = 2) { Monitor monitor; int64_t startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); for (int64_t ix = 0; ix < count; ix++) { { Synchronized s(monitor); try { monitor.wait(timeout); } catch (TimedOutException&) { } } } int64_t endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); bool success = (endTime - startTime) >= (count * timeout); std::cout << "\t\t\t" << (success ? "Success" : "Failure") << ": minimum required time to elapse " << count * timeout << "ms; actual elapsed time " << endTime - startTime << "ms" << std::endl; return success; } class FloodTask : public Runnable { public: FloodTask(const size_t id, Monitor& mon) : _id(id), _mon(mon) {} ~FloodTask() override { if (_id % 10000 == 0) { Synchronized sync(_mon); std::cout << "\t\tthread " << _id << " done" << std::endl; } } void run() override { if (_id % 10000 == 0) { Synchronized sync(_mon); std::cout << "\t\tthread " << _id << " started" << std::endl; } } const size_t _id; Monitor& _mon; }; void foo(ThreadFactory* tf) { (void)tf; } bool floodNTest(size_t loop = 1, size_t count = 100000) { bool success = false; Monitor mon; for (size_t lix = 0; lix < loop; lix++) { ThreadFactory threadFactory = ThreadFactory(); threadFactory.setDetached(true); for (size_t tix = 0; tix < count; tix++) { try { shared_ptr task(new FloodTask(lix * count + tix, mon)); shared_ptr thread = threadFactory.newThread(task); thread->start(); } catch (TException& e) { std::cout << "\t\t\tfailed to start " << lix* count + tix << " thread " << e.what() << std::endl; return success; } } Synchronized sync(mon); std::cout << "\t\t\tflooded " << (lix + 1) * count << " threads" << std::endl; success = true; } return success; } }; } } } } // apache::thrift::concurrency::test thrift-0.19.0/lib/cpp/test/qt/0000777000000000000000000000000014303740367016045 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/test/qt/CMakeLists.txt0000644000000000000000000000237314303740367020606 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # set(CMAKE_AUTOMOC ON) find_package(Qt5 REQUIRED COMPONENTS Test Network) set(TQTcpServerTest_Qt5_SOURCES TQTcpServerTest.cpp ) add_executable(TQTcpServerTest_Qt5 ${TQTcpServerTest_Qt5_SOURCES}) target_link_libraries(TQTcpServerTest_Qt5 testgencpp_cob) target_link_libraries(TQTcpServerTest_Qt5 thriftqt5) target_link_libraries(TQTcpServerTest_Qt5 thrift) target_link_libraries(TQTcpServerTest_Qt5 Qt5::Test Qt5::Network) add_test(NAME TQTcpServerTest_Qt5 COMMAND TQTcpServerTest_Qt5) thrift-0.19.0/lib/cpp/test/qt/TQTcpServerTest.cpp0000644000000000000000000000704214303740367021572 0ustar00rootroot00000000000000#define BOOST_TEST_MODULE TQTcpServerTest #include #include #include #include #include #include #ifndef Q_MOC_RUN #include "thrift/protocol/TBinaryProtocol.h" #include "thrift/async/TAsyncProcessor.h" #include "thrift/qt/TQTcpServer.h" #include "thrift/qt/TQIODeviceTransport.h" #include "gen-cpp/ParentService.h" #endif using namespace apache::thrift; struct AsyncHandler : public test::ParentServiceCobSvIf { std::vector strings; void addString(std::function cob, const std::string& s) override { strings.push_back(s); cob(); } void getStrings(std::function const& _return)> cob) override { cob(strings); } // Overrides not used in this test void incrementGeneration(std::function cob) override {} void getGeneration(std::function cob) override {} void getDataWait(std::function cob, const int32_t length) override {} void onewayWait(std::function cob) override {} void exceptionWait( std::function cob, std::function /* exn_cob */, const std::string& message) override {} void unexpectedExceptionWait(std::function cob, const std::string& message) override {} }; class TQTcpServerTest : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void test_communicate(); private: std::shared_ptr serverThread; std::shared_ptr server; std::shared_ptr client; }; void TQTcpServerTest::initTestCase() { // setup server std::shared_ptr serverSocket = std::make_shared(); server.reset(new async::TQTcpServer(serverSocket, std::make_shared( std::make_shared()), std::make_shared())); QVERIFY(serverSocket->listen(QHostAddress::LocalHost)); int port = serverSocket->serverPort(); QVERIFY(port > 0); //setup server thread and move server to it serverThread.reset(new QThread()); serverSocket->moveToThread(serverThread.get()); server->moveToThread(serverThread.get()); serverThread->start(); // setup client std::shared_ptr socket = std::make_shared(); client.reset(new test::ParentServiceClient(std::make_shared( std::make_shared(socket)))); socket->connectToHost(QHostAddress::LocalHost, port); QVERIFY(socket->waitForConnected()); } void TQTcpServerTest::cleanupTestCase() { //first, stop the thread which holds the server serverThread->quit(); serverThread->wait(); // now, it is safe to delete the server server.reset(); // delete thread now serverThread.reset(); // cleanup client client.reset(); } void TQTcpServerTest::test_communicate() { client->addString("foo"); client->addString("bar"); std::vector reply; client->getStrings(reply); QCOMPARE(QString::fromStdString(reply[0]), QString("foo")); QCOMPARE(QString::fromStdString(reply[1]), QString("bar")); } #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) QTEST_GUILESS_MAIN(TQTcpServerTest); #else #undef QT_GUI_LIB QTEST_MAIN(TQTcpServerTest); #endif #include "TQTcpServerTest.moc" thrift-0.19.0/lib/cpp/test/TransportTest.cpp0000644000000000000000000011375014370300523020752 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #ifdef HAVE_SYS_SOCKET_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if _WIN32 #include #include #endif using namespace apache::thrift::transport; using namespace apache::thrift; static boost::mt19937 rng; void initrand(unsigned int seed) { rng.seed(seed); } class SizeGenerator { public: virtual ~SizeGenerator() = default; virtual uint32_t nextSize() = 0; virtual std::string describe() const = 0; }; class ConstantSizeGenerator : public SizeGenerator { public: ConstantSizeGenerator(uint32_t value) : value_(value) {} uint32_t nextSize() override { return value_; } std::string describe() const override { std::ostringstream desc; desc << value_; return desc.str(); } private: uint32_t value_; }; class RandomSizeGenerator : public SizeGenerator { public: RandomSizeGenerator(uint32_t min, uint32_t max) : generator_(rng, boost::uniform_int(min, max)) {} uint32_t nextSize() override { return generator_(); } std::string describe() const override { std::ostringstream desc; desc << "rand(" << getMin() << ", " << getMax() << ")"; return desc.str(); } uint32_t getMin() const { return (generator_.distribution().min)(); } uint32_t getMax() const { return (generator_.distribution().max)(); } private: boost::variate_generator > generator_; }; /** * This class exists solely to make the TEST_RW() macro easier to use. * - it can be constructed implicitly from an integer * - it can contain either a ConstantSizeGenerator or a RandomSizeGenerator * (TEST_RW can't take a SizeGenerator pointer or reference, since it needs * to make a copy of the generator to bind it to the test function.) */ class GenericSizeGenerator : public SizeGenerator { public: GenericSizeGenerator(uint32_t value) : generator_(new ConstantSizeGenerator(value)) {} GenericSizeGenerator(uint32_t min, uint32_t max) : generator_(new RandomSizeGenerator(min, max)) {} uint32_t nextSize() override { return generator_->nextSize(); } std::string describe() const override { return generator_->describe(); } private: std::shared_ptr generator_; }; /************************************************************************** * Classes to set up coupled transports **************************************************************************/ /** * Helper class to represent a coupled pair of transports. * * Data written to the out transport can be read from the in transport. * * This is used as the base class for the various coupled transport * implementations. It shouldn't be instantiated directly. */ template class CoupledTransports { public: virtual ~CoupledTransports() = default; typedef Transport_ TransportType; CoupledTransports() : in(), out() {} std::shared_ptr in; std::shared_ptr out; private: CoupledTransports(const CoupledTransports&) = delete; CoupledTransports& operator=(const CoupledTransports&) = delete; }; /** * Coupled TMemoryBuffers */ class CoupledMemoryBuffers : public CoupledTransports { public: CoupledMemoryBuffers() : buf(new TMemoryBuffer) { in = buf; out = buf; } std::shared_ptr buf; }; /** * Helper template class for creating coupled transports that wrap * another transport. */ template class CoupledWrapperTransportsT : public CoupledTransports { public: CoupledWrapperTransportsT() { if (inner_.in) { this->in.reset(new WrapperTransport_(inner_.in)); } if (inner_.out) { this->out.reset(new WrapperTransport_(inner_.out)); } } InnerCoupledTransports_ inner_; }; /** * Coupled TBufferedTransports. */ template class CoupledBufferedTransportsT : public CoupledWrapperTransportsT {}; typedef CoupledBufferedTransportsT CoupledBufferedTransports; /** * Coupled TFramedTransports. */ template class CoupledFramedTransportsT : public CoupledWrapperTransportsT {}; typedef CoupledFramedTransportsT CoupledFramedTransports; /** * Coupled TZlibTransports. */ template class CoupledZlibTransportsT : public CoupledWrapperTransportsT {}; typedef CoupledZlibTransportsT CoupledZlibTransports; #ifndef _WIN32 // FD transport doesn't make much sense on Windows. /** * Coupled TFDTransports. */ class CoupledFDTransports : public CoupledTransports { public: CoupledFDTransports() { int pipes[2]; if (pipe(pipes) != 0) { return; } in.reset(new TFDTransport(pipes[0], TFDTransport::CLOSE_ON_DESTROY)); out.reset(new TFDTransport(pipes[1], TFDTransport::CLOSE_ON_DESTROY)); } }; #else /** * Coupled pipe transports */ class CoupledPipeTransports : public CoupledTransports { public: HANDLE hRead; HANDLE hWrite; CoupledPipeTransports() { BOOST_REQUIRE(CreatePipe(&hRead, &hWrite, nullptr, 1048576 * 2)); in.reset(new TPipe(hRead, hWrite)); in->open(); out = in; } }; #endif /** * Coupled TSockets */ class CoupledSocketTransports : public CoupledTransports { public: CoupledSocketTransports() { THRIFT_SOCKET sockets[2] = {0}; if (THRIFT_SOCKETPAIR(PF_UNIX, SOCK_STREAM, 0, sockets) != 0) { return; } in.reset(new TSocket(sockets[0])); out.reset(new TSocket(sockets[1])); out->setSendTimeout(100); } }; // These could be made to work on Windows, but I don't care enough to make it happen #ifndef _WIN32 /** * Coupled TFileTransports */ class CoupledFileTransports : public CoupledTransports { public: CoupledFileTransports() { #ifndef _WIN32 const char* tmp_dir = "/tmp"; #define FILENAME_SUFFIX "/thrift.transport_test" #else const char* tmp_dir = getenv("TMP"); #define FILENAME_SUFFIX "\\thrift.transport_test" #endif // Create a temporary file to use filename.resize(strlen(tmp_dir) + strlen(FILENAME_SUFFIX)); THRIFT_SNPRINTF(&filename[0], filename.size(), "%s" FILENAME_SUFFIX, tmp_dir); #undef FILENAME_SUFFIX { std::ofstream dummy_creation(filename.c_str(), std::ofstream::trunc); } in.reset(new TFileTransport(filename, true)); out.reset(new TFileTransport(filename)); } ~CoupledFileTransports() override { remove(filename.c_str()); } std::string filename; }; #endif /** * Wrapper around another CoupledTransports implementation that exposes the * transports as TTransport pointers. * * This is used since accessing a transport via a "TTransport*" exercises a * different code path than using the base pointer class. As part of the * template code changes, most transport methods are no longer virtual. */ template class CoupledTTransports : public CoupledTransports { public: CoupledTTransports() : transports() { in = transports.in; out = transports.out; } CoupledTransports_ transports; }; /** * Wrapper around another CoupledTransports implementation that exposes the * transports as TBufferBase pointers. * * This can only be instantiated with a transport type that is a subclass of * TBufferBase. */ template class CoupledBufferBases : public CoupledTransports { public: CoupledBufferBases() : transports() { in = transports.in; out = transports.out; } CoupledTransports_ transports; }; /************************************************************************** * Alarm handling code for use in tests that check the transport blocking * semantics. * * If the transport ends up blocking, we don't want to hang forever. We use * SIGALRM to fire schedule signal to wake up and try to write data so the * transport will unblock. * * It isn't really the safest thing in the world to be mucking around with * complicated global data structures in a signal handler. It should probably * be okay though, since we know the main thread should always be blocked in a * read() request when the signal handler is running. **************************************************************************/ struct TriggerInfo { TriggerInfo(int seconds, const std::shared_ptr& transport, uint32_t writeLength) : timeoutSeconds(seconds), transport(transport), writeLength(writeLength), next(nullptr) {} int timeoutSeconds; std::shared_ptr transport; uint32_t writeLength; TriggerInfo* next; }; apache::thrift::concurrency::Monitor g_alarm_monitor; TriggerInfo* g_triggerInfo; unsigned int g_numTriggersFired; bool g_teardown = false; void alarm_handler() { TriggerInfo* info = nullptr; { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); // The alarm timed out, which almost certainly means we're stuck // on a transport that is incorrectly blocked. ++g_numTriggersFired; // Note: we print messages to stdout instead of stderr, since // tools/test/runner only records stdout messages in the failure messages for // boost tests. (boost prints its test info to stdout.) printf("Timeout alarm expired; attempting to unblock transport\n"); if (g_triggerInfo == nullptr) { printf(" trigger stack is empty!\n"); } // Pop off the first TriggerInfo. // If there is another one, schedule an alarm for it. info = g_triggerInfo; g_triggerInfo = info->next; } // Write some data to the transport to hopefully unblock it. auto* buf = new uint8_t[info->writeLength]; memset(buf, 'b', info->writeLength); std::unique_ptr array(buf); info->transport->write(buf, info->writeLength); info->transport->flush(); delete info; } void alarm_handler_wrapper() { int64_t timeout = 0; // timeout of 0 means wait forever while (true) { bool fireHandler = false; { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); if (g_teardown) return; // calculate timeout if (g_triggerInfo == nullptr) { timeout = 0; } else { timeout = g_triggerInfo->timeoutSeconds * 1000; } int waitResult = g_alarm_monitor.waitForTimeRelative(timeout); if (waitResult == THRIFT_ETIMEDOUT) fireHandler = true; } if (fireHandler) alarm_handler(); // calling outside the lock } } /** * Add a trigger to be scheduled "seconds" seconds after the * last currently scheduled trigger. * * (Note that this is not "seconds" from now. That might be more logical, but * would require slightly more complicated sorting, rather than just appending * to the end.) */ void add_trigger(unsigned int seconds, const std::shared_ptr& transport, uint32_t write_len) { auto* info = new TriggerInfo(seconds, transport, write_len); { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); if (g_triggerInfo == nullptr) { // This is the first trigger. // Set g_triggerInfo, and schedule the alarm g_triggerInfo = info; g_alarm_monitor.notify(); } else { // Add this trigger to the end of the list TriggerInfo* prev = g_triggerInfo; while (prev->next) { prev = prev->next; } prev->next = info; } } } void clear_triggers() { TriggerInfo* info = nullptr; { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); info = g_triggerInfo; g_triggerInfo = nullptr; g_numTriggersFired = 0; g_alarm_monitor.notify(); } while (info != nullptr) { TriggerInfo* next = info->next; delete info; info = next; } } void set_trigger(unsigned int seconds, const std::shared_ptr& transport, uint32_t write_len) { clear_triggers(); add_trigger(seconds, transport, write_len); } /************************************************************************** * Test functions **************************************************************************/ /** * Test interleaved write and read calls. * * Generates a buffer totalSize bytes long, then writes it to the transport, * and verifies the written data can be read back correctly. * * Mode of operation: * - call wChunkGenerator to figure out how large of a chunk to write * - call wSizeGenerator to get the size for individual write() calls, * and do this repeatedly until the entire chunk is written. * - call rChunkGenerator to figure out how large of a chunk to read * - call rSizeGenerator to get the size for individual read() calls, * and do this repeatedly until the entire chunk is read. * - repeat until the full buffer is written and read back, * then compare the data read back against the original buffer * * * - If any of the size generators return 0, this means to use the maximum * possible size. * * - If maxOutstanding is non-zero, write chunk sizes will be chosen such that * there are never more than maxOutstanding bytes waiting to be read back. */ template void test_rw(uint32_t totalSize, SizeGenerator& wSizeGenerator, SizeGenerator& rSizeGenerator, SizeGenerator& wChunkGenerator, SizeGenerator& rChunkGenerator, uint32_t maxOutstanding) { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); boost::shared_array wbuf = boost::shared_array(new uint8_t[totalSize]); boost::shared_array rbuf = boost::shared_array(new uint8_t[totalSize]); // store some data in wbuf for (uint32_t n = 0; n < totalSize; ++n) { wbuf[n] = (n & 0xff); } // clear rbuf memset(rbuf.get(), 0, totalSize); uint32_t total_written = 0; uint32_t total_read = 0; while (total_read < totalSize) { // Determine how large a chunk of data to write uint32_t wchunk_size = wChunkGenerator.nextSize(); if (wchunk_size == 0 || wchunk_size > totalSize - total_written) { wchunk_size = totalSize - total_written; } // Make sure (total_written - total_read) + wchunk_size // is less than maxOutstanding if (maxOutstanding > 0 && wchunk_size > maxOutstanding - (total_written - total_read)) { wchunk_size = maxOutstanding - (total_written - total_read); } // Write the chunk uint32_t chunk_written = 0; while (chunk_written < wchunk_size) { uint32_t write_size = wSizeGenerator.nextSize(); if (write_size == 0 || write_size > wchunk_size - chunk_written) { write_size = wchunk_size - chunk_written; } try { transports.out->write(wbuf.get() + total_written, write_size); } catch (TTransportException& te) { if (te.getType() == TTransportException::TIMED_OUT) break; throw te; } chunk_written += write_size; total_written += write_size; } // Flush the data, so it will be available in the read transport // Don't flush if wchunk_size is 0. (This should only happen if // total_written == totalSize already, and we're only reading now.) if (wchunk_size > 0) { transports.out->flush(); } // Determine how large a chunk of data to read back uint32_t rchunk_size = rChunkGenerator.nextSize(); if (rchunk_size == 0 || rchunk_size > total_written - total_read) { rchunk_size = total_written - total_read; } // Read the chunk uint32_t chunk_read = 0; while (chunk_read < rchunk_size) { uint32_t read_size = rSizeGenerator.nextSize(); if (read_size == 0 || read_size > rchunk_size - chunk_read) { read_size = rchunk_size - chunk_read; } int bytes_read = -1; try { bytes_read = transports.in->read(rbuf.get() + total_read, read_size); } catch (TTransportException& e) { BOOST_FAIL("read(pos=" << total_read << ", size=" << read_size << ") threw exception \"" << e.what() << "\"; written so far: " << total_written << " / " << totalSize << " bytes"); } BOOST_REQUIRE_MESSAGE(bytes_read > 0, "read(pos=" << total_read << ", size=" << read_size << ") returned " << bytes_read << "; written so far: " << total_written << " / " << totalSize << " bytes"); chunk_read += bytes_read; total_read += bytes_read; } } // make sure the data read back is identical to the data written BOOST_CHECK_EQUAL(memcmp(rbuf.get(), wbuf.get(), totalSize), 0); } template void test_read_part_available() { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; memset(write_buf, 'a', sizeof(write_buf)); // Attemping to read 10 bytes when only 9 are available should return 9 // immediately. transports.out->write(write_buf, 9); transports.out->flush(); set_trigger(3, transports.out, 1); uint32_t bytes_read = transports.in->read(read_buf, 10); BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)0); BOOST_CHECK_EQUAL(bytes_read, (uint32_t)9); clear_triggers(); } template void test_read_part_available_in_chunks() { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; memset(write_buf, 'a', sizeof(write_buf)); // Write 10 bytes (in a single frame, for transports that use framing) transports.out->write(write_buf, 10); transports.out->flush(); // Read 1 byte, to force the transport to read the frame uint32_t bytes_read = transports.in->read(read_buf, 1); BOOST_CHECK_EQUAL(bytes_read, 1u); // Read more than what is remaining and verify the transport does not block set_trigger(3, transports.out, 1); bytes_read = transports.in->read(read_buf, 10); BOOST_CHECK_EQUAL(g_numTriggersFired, 0u); BOOST_CHECK_EQUAL(bytes_read, 9u); clear_triggers(); } template void test_read_partial_midframe() { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; memset(write_buf, 'a', sizeof(write_buf)); // Attempt to read 10 bytes, when only 9 are available, but after we have // already read part of the data that is available. This exercises a // different code path for several of the transports. // // For transports that add their own framing (e.g., TFramedTransport and // TFileTransport), the two flush calls break up the data in to a 10 byte // frame and a 3 byte frame. The first read then puts us partway through the // first frame, and then we attempt to read past the end of that frame, and // through the next frame, too. // // For buffered transports that perform read-ahead (e.g., // TBufferedTransport), the read-ahead will most likely see all 13 bytes // written on the first read. The next read will then attempt to read past // the end of the read-ahead buffer. // // Flush 10 bytes, then 3 bytes. This creates 2 separate frames for // transports that track framing internally. transports.out->write(write_buf, 10); transports.out->flush(); transports.out->write(write_buf, 3); transports.out->flush(); // Now read 4 bytes, so that we are partway through the written data. uint32_t bytes_read = transports.in->read(read_buf, 4); BOOST_CHECK_EQUAL(bytes_read, (uint32_t)4); // Now attempt to read 10 bytes. Only 9 more are available. // // We should be able to get all 9 bytes, but it might take multiple read // calls, since it is valid for read() to return fewer bytes than requested. // (Most transports do immediately return 9 bytes, but the framing transports // tend to only return to the end of the current frame, which is 6 bytes in // this case.) uint32_t total_read = 0; while (total_read < 9) { set_trigger(3, transports.out, 1); bytes_read = transports.in->read(read_buf, 10); BOOST_REQUIRE_EQUAL(g_numTriggersFired, (unsigned int)0); BOOST_REQUIRE_GT(bytes_read, (uint32_t)0); total_read += bytes_read; BOOST_REQUIRE_LE(total_read, (uint32_t)9); } BOOST_CHECK_EQUAL(total_read, (uint32_t)9); clear_triggers(); } template void test_borrow_part_available() { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; memset(write_buf, 'a', sizeof(write_buf)); // Attemping to borrow 10 bytes when only 9 are available should return nullptr // immediately. transports.out->write(write_buf, 9); transports.out->flush(); set_trigger(3, transports.out, 1); uint32_t borrow_len = 10; const uint8_t* borrowed_buf = transports.in->borrow(read_buf, &borrow_len); BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)0); BOOST_CHECK(borrowed_buf == nullptr); clear_triggers(); } template void test_read_none_available() { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); uint8_t read_buf[16]; // Attempting to read when no data is available should either block until // some data is available, or fail immediately. (e.g., TSocket blocks, // TMemoryBuffer just fails.) // // If the transport blocks, it should succeed once some data is available, // even if less than the amount requested becomes available. set_trigger(1, transports.out, 2); add_trigger(1, transports.out, 8); uint32_t bytes_read = transports.in->read(read_buf, 10); if (bytes_read == 0) { BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)0); clear_triggers(); } else { BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)1); BOOST_CHECK_EQUAL(bytes_read, (uint32_t)2); } clear_triggers(); } template void test_borrow_none_available() { CoupledTransports transports; BOOST_REQUIRE(transports.in != nullptr); BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; memset(write_buf, 'a', sizeof(write_buf)); // Attempting to borrow when no data is available should fail immediately set_trigger(1, transports.out, 10); uint32_t borrow_len = 10; const uint8_t* borrowed_buf = transports.in->borrow(nullptr, &borrow_len); BOOST_CHECK(borrowed_buf == nullptr); BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)0); clear_triggers(); } /************************************************************************** * Test case generation * * Pretty ugly and annoying. This would be much easier if we the unit test * framework didn't force each test to be a separate function. * - Writing a completely separate function definition for each of these would * result in a lot of repetitive boilerplate code. * - Combining many tests into a single function makes it more difficult to * tell precisely which tests failed. It also means you can't get a progress * update after each test, and the tests are already fairly slow. * - Similar registration could be achieved with BOOST_TEST_CASE_TEMPLATE, * but it requires a lot of awkward MPL code, and results in useless test * case names. (The names are generated from std::type_info::name(), which * is compiler-dependent. gcc returns mangled names.) **************************************************************************/ #define ADD_TEST_RW(CoupledTransports, totalSize, ...) \ addTestRW(BOOST_STRINGIZE(CoupledTransports), totalSize, ##__VA_ARGS__); #define TEST_RW(CoupledTransports, totalSize, ...) \ do { \ /* Add the test as specified, to test the non-virtual function calls */ \ ADD_TEST_RW(CoupledTransports, totalSize, ##__VA_ARGS__); \ /* \ * Also test using the transport as a TTransport*, to test \ * the read_virt()/write_virt() calls \ */ \ ADD_TEST_RW(CoupledTTransports, totalSize, ##__VA_ARGS__); \ /* Test wrapping the transport with TBufferedTransport */ \ ADD_TEST_RW(CoupledBufferedTransportsT, totalSize, ##__VA_ARGS__); \ /* Test wrapping the transport with TFramedTransports */ \ ADD_TEST_RW(CoupledFramedTransportsT, totalSize, ##__VA_ARGS__); \ /* Test wrapping the transport with TZlibTransport */ \ ADD_TEST_RW(CoupledZlibTransportsT, totalSize, ##__VA_ARGS__); \ } while (0) #define ADD_TEST_BLOCKING(CoupledTransports) \ addTestBlocking(BOOST_STRINGIZE(CoupledTransports)); #define TEST_BLOCKING_BEHAVIOR(CoupledTransports) \ ADD_TEST_BLOCKING(CoupledTransports); \ ADD_TEST_BLOCKING(CoupledTTransports); \ ADD_TEST_BLOCKING(CoupledBufferedTransportsT); \ ADD_TEST_BLOCKING(CoupledFramedTransportsT); \ ADD_TEST_BLOCKING(CoupledZlibTransportsT); class TransportTestGen { public: TransportTestGen(boost::unit_test::test_suite* suite, float sizeMultiplier) : suite_(suite), sizeMultiplier_(sizeMultiplier) {} void generate() { GenericSizeGenerator rand4k(1, 4096); /* * We do the basically the same set of tests for each transport type, * although we tweak the parameters in some places. */ // TMemoryBuffer tests TEST_RW(CoupledMemoryBuffers, 1024 * 1024, 0, 0); TEST_RW(CoupledMemoryBuffers, 1024 * 256, rand4k, rand4k); TEST_RW(CoupledMemoryBuffers, 1024 * 256, 167, 163); TEST_RW(CoupledMemoryBuffers, 1024 * 16, 1, 1); TEST_RW(CoupledMemoryBuffers, 1024 * 256, 0, 0, rand4k, rand4k); TEST_RW(CoupledMemoryBuffers, 1024 * 256, rand4k, rand4k, rand4k, rand4k); TEST_RW(CoupledMemoryBuffers, 1024 * 256, 167, 163, rand4k, rand4k); TEST_RW(CoupledMemoryBuffers, 1024 * 16, 1, 1, rand4k, rand4k); TEST_BLOCKING_BEHAVIOR(CoupledMemoryBuffers); #ifndef _WIN32 // TFDTransport tests // Since CoupledFDTransports tests with a pipe, writes will block // if there is too much outstanding unread data in the pipe. uint32_t fd_max_outstanding = 4096; TEST_RW(CoupledFDTransports, 1024 * 1024, 0, 0, 0, 0, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 256, rand4k, rand4k, 0, 0, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 256, 167, 163, 0, 0, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 16, 1, 1, 0, 0, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 256, 0, 0, rand4k, rand4k, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 256, rand4k, rand4k, rand4k, rand4k, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 256, 167, 163, rand4k, rand4k, fd_max_outstanding); TEST_RW(CoupledFDTransports, 1024 * 16, 1, 1, rand4k, rand4k, fd_max_outstanding); TEST_BLOCKING_BEHAVIOR(CoupledFDTransports); #else // TPipe tests (WIN32 only) TEST_RW(CoupledPipeTransports, 1024 * 1024, 0, 0); TEST_RW(CoupledPipeTransports, 1024 * 256, rand4k, rand4k); TEST_RW(CoupledPipeTransports, 1024 * 256, 167, 163); TEST_RW(CoupledPipeTransports, 1024 * 16, 1, 1); TEST_RW(CoupledPipeTransports, 1024 * 256, 0, 0, rand4k, rand4k); TEST_RW(CoupledPipeTransports, 1024 * 256, rand4k, rand4k, rand4k, rand4k); TEST_RW(CoupledPipeTransports, 1024 * 256, 167, 163, rand4k, rand4k); TEST_RW(CoupledPipeTransports, 1024 * 16, 1, 1, rand4k, rand4k); TEST_BLOCKING_BEHAVIOR(CoupledPipeTransports); #endif //_WIN32 // TSocket tests uint32_t socket_max_outstanding = 4096; TEST_RW(CoupledSocketTransports, 1024 * 1024, 0, 0, 0, 0, socket_max_outstanding); TEST_RW(CoupledSocketTransports, 1024 * 256, rand4k, rand4k, 0, 0, socket_max_outstanding); TEST_RW(CoupledSocketTransports, 1024 * 256, 167, 163, 0, 0, socket_max_outstanding); // Doh. Apparently writing to a socket has some additional overhead for // each send() call. If we have more than ~400 outstanding 1-byte write // requests, additional send() calls start blocking. TEST_RW(CoupledSocketTransports, 1024 * 16, 1, 1, 0, 0, socket_max_outstanding); TEST_RW(CoupledSocketTransports, 1024 * 256, 0, 0, rand4k, rand4k, socket_max_outstanding); TEST_RW(CoupledSocketTransports, 1024 * 256, rand4k, rand4k, rand4k, rand4k, socket_max_outstanding); TEST_RW(CoupledSocketTransports, 1024 * 256, 167, 163, rand4k, rand4k, socket_max_outstanding); TEST_RW(CoupledSocketTransports, 1024 * 16, 1, 1, rand4k, rand4k, socket_max_outstanding); TEST_BLOCKING_BEHAVIOR(CoupledSocketTransports); // These could be made to work on Windows, but I don't care enough to make it happen #ifndef _WIN32 // TFileTransport tests // We use smaller buffer sizes here, since TFileTransport is fairly slow. // // TFileTransport can't write more than 16MB at once uint32_t max_write_at_once = 1024 * 1024 * 16 - 4; TEST_RW(CoupledFileTransports, 1024 * 1024, max_write_at_once, 0); TEST_RW(CoupledFileTransports, 1024 * 128, rand4k, rand4k); TEST_RW(CoupledFileTransports, 1024 * 128, 167, 163); TEST_RW(CoupledFileTransports, 1024 * 2, 1, 1); TEST_RW(CoupledFileTransports, 1024 * 64, 0, 0, rand4k, rand4k); TEST_RW(CoupledFileTransports, 1024 * 64, rand4k, rand4k, rand4k, rand4k); TEST_RW(CoupledFileTransports, 1024 * 64, 167, 163, rand4k, rand4k); TEST_RW(CoupledFileTransports, 1024 * 2, 1, 1, rand4k, rand4k); TEST_BLOCKING_BEHAVIOR(CoupledFileTransports); #endif // Add some tests that access TBufferedTransport and TFramedTransport // via TTransport pointers and TBufferBase pointers. ADD_TEST_RW(CoupledTTransports, 1024 * 1024, rand4k, rand4k, rand4k, rand4k); ADD_TEST_RW(CoupledBufferBases, 1024 * 1024, rand4k, rand4k, rand4k, rand4k); ADD_TEST_RW(CoupledTTransports, 1024 * 1024, rand4k, rand4k, rand4k, rand4k); ADD_TEST_RW(CoupledBufferBases, 1024 * 1024, rand4k, rand4k, rand4k, rand4k); // Test using TZlibTransport via a TTransport pointer ADD_TEST_RW(CoupledTTransports, 1024 * 1024, rand4k, rand4k, rand4k, rand4k); } #if (BOOST_VERSION >= 105900) #define MAKE_TEST_CASE(_FUNC, _NAME) boost::unit_test::make_test_case(_FUNC, _NAME, __FILE__, __LINE__) #else #define MAKE_TEST_CASE(_FUNC, _NAME) boost::unit_test::make_test_case(_FUNC, _NAME) #endif private: template void addTestRW(const char* transport_name, uint32_t totalSize, GenericSizeGenerator wSizeGen, GenericSizeGenerator rSizeGen, GenericSizeGenerator wChunkSizeGen = 0, GenericSizeGenerator rChunkSizeGen = 0, uint32_t maxOutstanding = 0, uint32_t expectedFailures = 0) { // adjust totalSize by the specified sizeMultiplier_ first totalSize = static_cast(totalSize * sizeMultiplier_); std::ostringstream name; name << transport_name << "::test_rw(" << totalSize << ", " << wSizeGen.describe() << ", " << rSizeGen.describe() << ", " << wChunkSizeGen.describe() << ", " << rChunkSizeGen.describe() << ", " << maxOutstanding << ")"; #if (BOOST_VERSION >= 105900) std::function test_func #else boost::unit_test::callback0<> test_func #endif = std::bind(test_rw, totalSize, wSizeGen, rSizeGen, wChunkSizeGen, rChunkSizeGen, maxOutstanding); suite_->add(MAKE_TEST_CASE(test_func, name.str()), expectedFailures); } template void addTestBlocking(const char* transportName, uint32_t expectedFailures = 0) { char name[1024]; THRIFT_SNPRINTF(name, sizeof(name), "%s::test_read_part_available()", transportName); suite_->add(MAKE_TEST_CASE(test_read_part_available, name), expectedFailures); THRIFT_SNPRINTF(name, sizeof(name), "%s::test_read_part_available_in_chunks()", transportName); suite_->add(MAKE_TEST_CASE(test_read_part_available_in_chunks, name), expectedFailures); THRIFT_SNPRINTF(name, sizeof(name), "%s::test_read_partial_midframe()", transportName); suite_->add(MAKE_TEST_CASE(test_read_partial_midframe, name), expectedFailures); THRIFT_SNPRINTF(name, sizeof(name), "%s::test_read_none_available()", transportName); suite_->add(MAKE_TEST_CASE(test_read_none_available, name), expectedFailures); THRIFT_SNPRINTF(name, sizeof(name), "%s::test_borrow_part_available()", transportName); suite_->add(MAKE_TEST_CASE(test_borrow_part_available, name), expectedFailures); THRIFT_SNPRINTF(name, sizeof(name), "%s::test_borrow_none_available()", transportName); suite_->add(MAKE_TEST_CASE(test_borrow_none_available, name), expectedFailures); } boost::unit_test::test_suite* suite_; // sizeMultiplier_ is configurable via the command line, and allows the // user to adjust between smaller buffers that can be tested quickly, // or larger buffers that more thoroughly exercise the code, but take // longer. float sizeMultiplier_; }; /************************************************************************** * General Initialization **************************************************************************/ struct global_fixture { std::shared_ptr alarmThread_; global_fixture() { #if _WIN32 apache::thrift::transport::TWinsockSingleton::create(); #endif apache::thrift::concurrency::ThreadFactory factory; factory.setDetached(false); alarmThread_ = factory.newThread( apache::thrift::concurrency::FunctionRunner::create(alarm_handler_wrapper)); alarmThread_->start(); } ~global_fixture() { { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); g_teardown = true; g_alarm_monitor.notify(); } alarmThread_->join(); } }; #if (BOOST_VERSION >= 105900) BOOST_GLOBAL_FIXTURE(global_fixture); #else BOOST_GLOBAL_FIXTURE(global_fixture) #endif #ifdef BOOST_TEST_DYN_LINK bool init_unit_test_suite() { struct timeval tv; THRIFT_GETTIMEOFDAY(&tv, nullptr); int seed = tv.tv_sec ^ tv.tv_usec; initrand(seed); boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); suite->p_name.value = "TransportTest"; TransportTestGen transport_test_generator(suite, 1); transport_test_generator.generate(); return true; } int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv); } #else boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { THRIFT_UNUSED_VARIABLE(argc); THRIFT_UNUSED_VARIABLE(argv); struct timeval tv; THRIFT_GETTIMEOFDAY(&tv, nullptr); int seed = tv.tv_sec ^ tv.tv_usec; initrand(seed); boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); suite->p_name.value = "TransportTest"; TransportTestGen transport_test_generator(suite, 1); transport_test_generator.generate(); return nullptr; } #endif thrift-0.19.0/lib/cpp/test/OpenSSLManualInitTest.cpp0000644000000000000000000000563614303740367022240 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // To show that this test actually tests something, you can change // MANUAL_OPENSSL_INIT to 0 to cause automatic OpenSSL init/cleanup, // which will cause the test to fail #define MANUAL_OPENSSL_INIT 1 #ifdef _WIN32 #include #endif #include #include #include using namespace apache::thrift::transport; void make_isolated_sslsocketfactory() { // Here we create an isolated TSSLSocketFactory to ensure the // constructor and destructor of TSSLSocketFactory get run. Thus // without manual initialization normally OpenSSL would be // uninitialized after this function. TSSLSocketFactory factory; } void openssl_init() { #if MANUAL_OPENSSL_INIT TSSLSocketFactory::setManualOpenSSLInitialization(true); initializeOpenSSL(); #endif } void openssl_cleanup() { #if MANUAL_OPENSSL_INIT cleanupOpenSSL(); #endif } void test_openssl_availability() { // Check whether Thrift leaves OpenSSL functionality available after // the last TSSLSocketFactory is destroyed when manual // initialization is set openssl_init(); make_isolated_sslsocketfactory(); // The following function is one that will fail if OpenSSL is // uninitialized. It might also fail on very old versions of // OpenSSL... const EVP_MD* md = EVP_get_digestbyname("SHA256"); BOOST_CHECK(md != nullptr); openssl_cleanup(); } #ifdef BOOST_TEST_DYN_LINK bool init_unit_test_suite() { boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); suite->p_name.value = "OpenSSLManualInit"; suite->add(BOOST_TEST_CASE(test_openssl_availability)); return true; } int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv); } #else boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { THRIFT_UNUSED_VARIABLE(argc); THRIFT_UNUSED_VARIABLE(argv); boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); suite->p_name.value = "OpenSSLManualInit"; suite->add(BOOST_TEST_CASE(test_openssl_availability)); return nullptr; } #endifthrift-0.19.0/lib/cpp/test/ZlibTest.cpp0000644000000000000000000004166414303740367017674 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE // needed for getopt_long #endif #if defined(_MSC_VER) && (_MSC_VER <= 1700) // polynomial and std::fill_t warning happens in MSVC 2010, 2013, maybe others // https://svn.boost.org/trac/boost/ticket/11426 #pragma warning(disable:4996) #endif #ifdef HAVE_STDINT_H #include #endif #ifdef HAVE_INTTYPES_H #include #endif #include #include #include #include #include #include #include #include #include #include using namespace apache::thrift::transport; using std::shared_ptr; using std::string; boost::mt19937 rng; /* * Utility code */ class SizeGenerator { public: virtual ~SizeGenerator() = default; virtual unsigned int getSize() = 0; }; class ConstantSizeGenerator : public SizeGenerator { public: ConstantSizeGenerator(unsigned int value) : value_(value) {} unsigned int getSize() override { return value_; } private: unsigned int value_; }; class LogNormalSizeGenerator : public SizeGenerator { public: LogNormalSizeGenerator(double mean, double std_dev) : gen_(rng, boost::lognormal_distribution(mean, std_dev)) {} unsigned int getSize() override { // Loop until we get a size of 1 or more while (true) { auto value = static_cast(gen_()); if (value >= 1) { return value; } } } private: boost::variate_generator > gen_; }; boost::shared_array gen_uniform_buffer(uint32_t buf_len, uint8_t c) { auto* buf = new uint8_t[buf_len]; memset(buf, c, buf_len); return boost::shared_array(buf); } boost::shared_array gen_compressible_buffer(uint32_t buf_len) { auto* buf = new uint8_t[buf_len]; // Generate small runs of alternately increasing and decreasing bytes boost::uniform_smallint run_length_distribution(1, 64); boost::uniform_smallint byte_distribution(0, UINT8_MAX); boost::variate_generator > byte_generator(rng, byte_distribution); boost::variate_generator > run_len_generator(rng, run_length_distribution); uint32_t idx = 0; int8_t step = 1; while (idx < buf_len) { uint32_t run_length = run_len_generator(); if (idx + run_length > buf_len) { run_length = buf_len - idx; } uint8_t byte = byte_generator(); for (uint32_t n = 0; n < run_length; ++n) { buf[idx] = byte; ++idx; byte += step; } step *= -1; } return boost::shared_array(buf); } boost::shared_array gen_random_buffer(uint32_t buf_len) { auto* buf = new uint8_t[buf_len]; boost::uniform_smallint distribution(0, UINT8_MAX); boost::variate_generator > generator(rng, distribution); for (uint32_t n = 0; n < buf_len; ++n) { buf[n] = generator(); } return boost::shared_array(buf); } /* * Test functions */ void test_write_then_read(const boost::shared_array buf, uint32_t buf_len) { shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); zlib_trans->write(buf.get(), buf_len); zlib_trans->finish(); boost::shared_array mirror(new uint8_t[buf_len]); uint32_t got = zlib_trans->readAll(mirror.get(), buf_len); BOOST_REQUIRE_EQUAL(got, buf_len); BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); zlib_trans->verifyChecksum(); } void test_separate_checksum(const boost::shared_array buf, uint32_t buf_len) { // This one is tricky. I separate the last byte of the stream out // into a separate crbuf_. The last byte is part of the checksum, // so the entire read goes fine, but when I go to verify the checksum // it isn't there. The original implementation complained that // the stream was not complete. I'm about to go fix that. // It worked. Awesome. shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); zlib_trans->write(buf.get(), buf_len); zlib_trans->finish(); string tmp_buf; membuf->appendBufferToString(tmp_buf); zlib_trans.reset(new TZlibTransport(membuf, TZlibTransport::DEFAULT_URBUF_SIZE, static_cast(tmp_buf.length() - 1))); boost::shared_array mirror(new uint8_t[buf_len]); uint32_t got = zlib_trans->readAll(mirror.get(), buf_len); BOOST_REQUIRE_EQUAL(got, buf_len); BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); zlib_trans->verifyChecksum(); } void test_incomplete_checksum(const boost::shared_array buf, uint32_t buf_len) { // Make sure we still get that "not complete" error if // it really isn't complete. shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); zlib_trans->write(buf.get(), buf_len); zlib_trans->finish(); string tmp_buf; membuf->appendBufferToString(tmp_buf); tmp_buf.erase(tmp_buf.length() - 1); membuf->resetBuffer(const_cast(reinterpret_cast(tmp_buf.data())), static_cast(tmp_buf.length())); boost::shared_array mirror(new uint8_t[buf_len]); uint32_t got = zlib_trans->readAll(mirror.get(), buf_len); BOOST_REQUIRE_EQUAL(got, buf_len); BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); try { zlib_trans->verifyChecksum(); BOOST_ERROR("verifyChecksum() did not report an error"); } catch (TTransportException& ex) { BOOST_CHECK_EQUAL(ex.getType(), TTransportException::CORRUPTED_DATA); } } void test_read_write_mix(const boost::shared_array buf, uint32_t buf_len, const shared_ptr& write_gen, const shared_ptr& read_gen) { // Try it with a mix of read/write sizes. shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); unsigned int tot; tot = 0; while (tot < buf_len) { uint32_t write_len = write_gen->getSize(); if (tot + write_len > buf_len) { write_len = buf_len - tot; } zlib_trans->write(buf.get() + tot, write_len); tot += write_len; } zlib_trans->finish(); tot = 0; boost::shared_array mirror(new uint8_t[buf_len]); while (tot < buf_len) { uint32_t read_len = read_gen->getSize(); uint32_t expected_read_len = read_len; if (tot + read_len > buf_len) { expected_read_len = buf_len - tot; } uint32_t got = zlib_trans->read(mirror.get() + tot, read_len); BOOST_REQUIRE_LE(got, expected_read_len); BOOST_REQUIRE_NE(got, (uint32_t)0); tot += got; } BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0); zlib_trans->verifyChecksum(); } void test_invalid_checksum(const boost::shared_array buf, uint32_t buf_len) { // Verify checksum checking. shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); zlib_trans->write(buf.get(), buf_len); zlib_trans->finish(); string tmp_buf; membuf->appendBufferToString(tmp_buf); // Modify a byte at the end of the buffer (part of the checksum). // On rare occasions, modifying a byte in the middle of the buffer // isn't caught by the checksum. // // (This happens especially often for the uniform buffer. The // re-inflated data is correct, however. I suspect in this case that // we're more likely to modify bytes that are part of zlib metadata // instead of the actual compressed data.) // // I've also seen some failure scenarios where a checksum failure isn't // reported, but zlib keeps trying to decode past the end of the data. // (When this occurs, verifyChecksum() throws an exception indicating // that the end of the data hasn't been reached.) I haven't seen this // error when only modifying checksum bytes. int index = static_cast(tmp_buf.size() - 1); tmp_buf[index]++; membuf->resetBuffer(const_cast(reinterpret_cast(tmp_buf.data())), static_cast(tmp_buf.length())); boost::shared_array mirror(new uint8_t[buf_len]); try { zlib_trans->readAll(mirror.get(), buf_len); zlib_trans->verifyChecksum(); BOOST_ERROR("verifyChecksum() did not report an error"); } catch (TZlibTransportException& ex) { BOOST_CHECK_EQUAL(ex.getType(), TTransportException::INTERNAL_ERROR); } } void test_write_after_flush(const boost::shared_array buf, uint32_t buf_len) { // write some data shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); zlib_trans->write(buf.get(), buf_len); // call finish() zlib_trans->finish(); // make sure write() throws an error try { uint8_t write_buf[] = "a"; zlib_trans->write(write_buf, 1); BOOST_ERROR("write() after finish() did not raise an exception"); } catch (TTransportException& ex) { BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS); } // make sure flush() throws an error try { zlib_trans->flush(); BOOST_ERROR("flush() after finish() did not raise an exception"); } catch (TTransportException& ex) { BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS); } // make sure finish() throws an error try { zlib_trans->finish(); BOOST_ERROR("finish() after finish() did not raise an exception"); } catch (TTransportException& ex) { BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS); } } void test_no_write() { // Verify that no data is written to the underlying transport if we // never write data to the TZlibTransport. shared_ptr membuf(new TMemoryBuffer()); { // Create a TZlibTransport object, and immediately destroy it // when it goes out of scope. TZlibTransport w_zlib_trans(membuf); } BOOST_CHECK_EQUAL(membuf->available_read(), (uint32_t)0); } void test_get_underlying_transport() { shared_ptr membuf(new TMemoryBuffer()); shared_ptr zlib_trans(new TZlibTransport(membuf)); BOOST_CHECK_EQUAL(membuf.get(), zlib_trans->getUnderlyingTransport().get()); } /* * Initialization */ #if (BOOST_VERSION >= 105900) #define ADD_TEST_CASE(suite, name, _FUNC, ...) \ do { \ ::std::ostringstream name_ss; \ name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \ ::std::function test_func = \ ::std::bind(_FUNC, ##__VA_ARGS__); \ ::boost::unit_test::test_case* tc \ = ::boost::unit_test::make_test_case(test_func, name_ss.str(), __FILE__, __LINE__); \ (suite)->add(tc); \ } while (0) #else #define ADD_TEST_CASE(suite, name, _FUNC, ...) \ do { \ ::std::ostringstream name_ss; \ name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \ ::boost::unit_test::test_case* tc \ = ::boost::unit_test::make_test_case(::std::bind(_FUNC, \ ##__VA_ARGS__), \ name_ss.str()); \ (suite)->add(tc); \ } while (0) #endif void add_tests(boost::unit_test::test_suite* suite, const boost::shared_array& buf, uint32_t buf_len, const char* name) { ADD_TEST_CASE(suite, name, test_write_then_read, buf, buf_len); ADD_TEST_CASE(suite, name, test_separate_checksum, buf, buf_len); ADD_TEST_CASE(suite, name, test_incomplete_checksum, buf, buf_len); ADD_TEST_CASE(suite, name, test_invalid_checksum, buf, buf_len); ADD_TEST_CASE(suite, name, test_write_after_flush, buf, buf_len); shared_ptr size_32k(new ConstantSizeGenerator(1 << 15)); shared_ptr size_lognormal(new LogNormalSizeGenerator(20, 30)); ADD_TEST_CASE(suite, name << "-constant", test_read_write_mix, buf, buf_len, size_32k, size_32k); ADD_TEST_CASE(suite, name << "-lognormal-write", test_read_write_mix, buf, buf_len, size_lognormal, size_32k); ADD_TEST_CASE(suite, name << "-lognormal-read", test_read_write_mix, buf, buf_len, size_32k, size_lognormal); ADD_TEST_CASE(suite, name << "-lognormal-both", test_read_write_mix, buf, buf_len, size_lognormal, size_lognormal); // Test with a random size distribution, // but use the exact same distribution for reading as for writing. // // Because the SizeGenerator makes a copy of the random number generator, // both SizeGenerators should return the exact same set of values, since they // both start with random number generators in the same state. shared_ptr write_size_gen(new LogNormalSizeGenerator(20, 30)); shared_ptr read_size_gen(new LogNormalSizeGenerator(20, 30)); ADD_TEST_CASE(suite, name << "-lognormal-same-distribution", test_read_write_mix, buf, buf_len, write_size_gen, read_size_gen); } void print_usage(FILE* f, const char* argv0) { fprintf(f, "Usage: %s [boost_options] [options]\n", argv0); fprintf(f, "Options:\n"); fprintf(f, " --seed=, -s \n"); fprintf(f, " --help\n"); } #ifdef BOOST_TEST_DYN_LINK bool init_unit_test_suite() { auto seed = static_cast(time(nullptr)); #ifdef HAVE_INTTYPES_H printf("seed: %" PRIu32 "\n", seed); #endif rng.seed(seed); boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); suite->p_name.value = "ZlibTest"; uint32_t buf_len = 1024 * 32; add_tests(suite, gen_uniform_buffer(buf_len, 'a'), buf_len, "uniform"); add_tests(suite, gen_compressible_buffer(buf_len), buf_len, "compressible"); add_tests(suite, gen_random_buffer(buf_len), buf_len, "random"); suite->add(BOOST_TEST_CASE(test_no_write)); suite->add(BOOST_TEST_CASE(test_get_underlying_transport)); return true; } int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv); } #else boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { THRIFT_UNUSED_VARIABLE(argc); THRIFT_UNUSED_VARIABLE(argv); uint32_t seed = static_cast(time(nullptr)); #ifdef HAVE_INTTYPES_H printf("seed: %" PRIu32 "\n", seed); #endif rng.seed(seed); boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite(); suite->p_name.value = "ZlibTest"; uint32_t buf_len = 1024 * 32; add_tests(suite, gen_uniform_buffer(buf_len, 'a'), buf_len, "uniform"); add_tests(suite, gen_compressible_buffer(buf_len), buf_len, "compressible"); add_tests(suite, gen_random_buffer(buf_len), buf_len, "random"); suite->add(BOOST_TEST_CASE(test_no_write)); return nullptr; } #endif thrift-0.19.0/lib/cpp/test/AllProtocolTests.cpp0000644000000000000000000000300214303740367021371 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #define BOOST_TEST_MODULE AllProtocolTests #include #include "AllProtocolTests.tcc" using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; char errorMessage[ERR_LEN]; BOOST_AUTO_TEST_CASE(test_binary_protocol) { testProtocol("TBinaryProtocol"); } BOOST_AUTO_TEST_CASE(test_little_binary_protocol) { testProtocol("TLEBinaryProtocol"); } BOOST_AUTO_TEST_CASE(test_compact_protocol) { testProtocol("TCompactProtocol"); } thrift-0.19.0/lib/cpp/test/TSSLSocketInterruptTest.cpp0000644000000000000000000002534514303740367022645 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SIGNAL_H #include #endif using apache::thrift::transport::TSSLServerSocket; using apache::thrift::transport::TSSLSocket; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TSSLSocketFactory; using std::static_pointer_cast; using std::shared_ptr; BOOST_AUTO_TEST_SUITE(TSSLSocketInterruptTest) boost::filesystem::path keyDir; boost::filesystem::path certFile(const std::string& filename) { return keyDir / filename; } boost::mutex gMutex; struct GlobalFixtureSSL { GlobalFixtureSSL() { using namespace boost::unit_test::framework; for (int i = 0; i < master_test_suite().argc; ++i) { BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]); } #ifdef __linux__ // OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has // disconnected can cause a SIGPIPE signal... signal(SIGPIPE, SIG_IGN); #endif TSSLSocketFactory::setManualOpenSSLInitialization(true); apache::thrift::transport::initializeOpenSSL(); keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys"; if (!boost::filesystem::exists(certFile("server.crt"))) { keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]); if (!boost::filesystem::exists(certFile("server.crt"))) { throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s)."); } } } virtual ~GlobalFixtureSSL() { apache::thrift::transport::cleanupOpenSSL(); #ifdef __linux__ signal(SIGPIPE, SIG_DFL); #endif } }; #if (BOOST_VERSION >= 105900) BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL); #else BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL) #endif void readerWorker(shared_ptr tt, uint32_t expectedResult) { uint8_t buf[4]; try { tt->read(buf, 1); BOOST_CHECK_EQUAL(expectedResult, tt->read(buf, 4)); } catch (const TTransportException& tx) { BOOST_CHECK_EQUAL(TTransportException::TIMED_OUT, tx.getType()); } } void readerWorkerMustThrow(shared_ptr tt) { try { uint8_t buf[400]; tt->read(buf, 1); tt->read(buf, 400); BOOST_ERROR("should not have gotten here"); } catch (const TTransportException& tx) { BOOST_CHECK_EQUAL(TTransportException::INTERRUPTED, tx.getType()); } } shared_ptr createServerSocketFactory() { shared_ptr pServerSocketFactory; pServerSocketFactory.reset(new TSSLSocketFactory()); pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); pServerSocketFactory->loadCertificate(certFile("server.crt").string().c_str()); pServerSocketFactory->loadPrivateKey(certFile("server.key").string().c_str()); pServerSocketFactory->server(true); return pServerSocketFactory; } shared_ptr createClientSocketFactory() { shared_ptr pClientSocketFactory; pClientSocketFactory.reset(new TSSLSocketFactory()); pClientSocketFactory->authenticate(true); pClientSocketFactory->loadCertificate(certFile("client.crt").string().c_str()); pClientSocketFactory->loadPrivateKey(certFile("client.key").string().c_str()); pClientSocketFactory->loadTrustedCertificates(certFile("CA.pem").string().c_str()); return pClientSocketFactory; } BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_read_while_handshaking) { shared_ptr pServerSocketFactory = createServerSocketFactory(); TSSLServerSocket sock1("localhost", 0, pServerSocketFactory); sock1.listen(); int port = sock1.getPort(); shared_ptr pClientSocketFactory = createClientSocketFactory(); shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); boost::thread readThread(std::bind(readerWorkerMustThrow, accepted)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(readThread.try_join_for(boost::chrono::milliseconds(20)), "server socket interruptChildren did not interrupt child read"); clientSock->close(); accepted->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_read) { shared_ptr pServerSocketFactory = createServerSocketFactory(); TSSLServerSocket sock1("localhost", 0, pServerSocketFactory); sock1.listen(); int port = sock1.getPort(); shared_ptr pClientSocketFactory = createClientSocketFactory(); shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); boost::thread readThread(std::bind(readerWorkerMustThrow, accepted)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(readThread.try_join_for(boost::chrono::milliseconds(20)), "server socket interruptChildren did not interrupt child read"); accepted->close(); clientSock->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_ssl_non_interruptable_child_read) { shared_ptr pServerSocketFactory = createServerSocketFactory(); TSSLServerSocket sock1("localhost", 0, pServerSocketFactory); sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior sock1.listen(); int port = sock1.getPort(); shared_ptr pClientSocketFactory = createClientSocketFactory(); shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); static_pointer_cast(accepted)->setRecvTimeout(1000); boost::thread readThread(std::bind(readerWorker, accepted, 0)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking here sock1.interruptChildren(); BOOST_CHECK_MESSAGE(!readThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren interrupted child read"); // wait for receive timeout to kick in readThread.join(); accepted->close(); clientSock->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_ssl_cannot_change_after_listen) { shared_ptr pServerSocketFactory = createServerSocketFactory(); TSSLServerSocket sock1("localhost", 0, pServerSocketFactory); sock1.listen(); BOOST_CHECK_THROW(sock1.setInterruptableChildren(false), std::logic_error); sock1.close(); } void peekerWorker(shared_ptr tt, bool expectedResult) { uint8_t buf[400]; try { tt->read(buf, 1); BOOST_CHECK_EQUAL(expectedResult, tt->peek()); } catch (const TTransportException& tx) { BOOST_CHECK_EQUAL(TTransportException::TIMED_OUT, tx.getType()); } } void peekerWorkerInterrupt(shared_ptr tt) { uint8_t buf[400]; try { tt->read(buf, 1); tt->peek(); } catch (const TTransportException& tx) { BOOST_CHECK_EQUAL(TTransportException::INTERRUPTED, tx.getType()); } } BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_peek) { shared_ptr pServerSocketFactory = createServerSocketFactory(); TSSLServerSocket sock1("localhost", 0, pServerSocketFactory); sock1.listen(); int port = sock1.getPort(); shared_ptr pClientSocketFactory = createClientSocketFactory(); shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); boost::thread peekThread(std::bind(peekerWorkerInterrupt, accepted)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(peekThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren did not interrupt child peek"); accepted->close(); clientSock->close(); sock1.close(); } BOOST_AUTO_TEST_CASE(test_ssl_non_interruptable_child_peek) { shared_ptr pServerSocketFactory = createServerSocketFactory(); TSSLServerSocket sock1("localhost", 0, pServerSocketFactory); sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior sock1.listen(); int port = sock1.getPort(); shared_ptr pClientSocketFactory = createClientSocketFactory(); shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); static_pointer_cast(accepted)->setRecvTimeout(1000); boost::thread peekThread(std::bind(peekerWorker, accepted, false)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now sock1.interruptChildren(); BOOST_CHECK_MESSAGE(!peekThread.try_join_for(boost::chrono::milliseconds(200)), "server socket interruptChildren interrupted child peek"); // wait for the receive timeout to kick in peekThread.join(); accepted->close(); clientSock->close(); sock1.close(); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/ThrifttReadCheckTests.cpp0000644000000000000000000002147214303740367022330 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define MAX_MESSAGE_SIZE 2 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include BOOST_AUTO_TEST_SUITE(ThriftReadCheckExceptionTest) using apache::thrift::TConfiguration; using apache::thrift::protocol::TBinaryProtocol; using apache::thrift::protocol::TCompactProtocol; using apache::thrift::protocol::TJSONProtocol; using apache::thrift::protocol::TType; using apache::thrift::transport::TPipedTransport; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TSimpleFileTransport; using apache::thrift::transport::TFileTransport; using apache::thrift::transport::TFDTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TBufferedTransport; using apache::thrift::transport::TFramedTransport; using std::shared_ptr; using std::cout; using std::endl; using std::string; using std::memset; using namespace apache::thrift; using namespace apache::thrift::protocol; BOOST_AUTO_TEST_CASE(test_tmemorybuffer_read_check_exception) { std::shared_ptr config(new TConfiguration(MAX_MESSAGE_SIZE)); TMemoryBuffer trans_out(config); uint8_t buffer[6] = {1, 2, 3, 4, 5, 6}; trans_out.write((const uint8_t*)buffer, sizeof(buffer)); trans_out.close(); TMemoryBuffer trans_in(config); memset(buffer, 0, sizeof(buffer)); BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException); trans_in.close(); } BOOST_AUTO_TEST_CASE(test_tpipedtransport_read_check_exception) { std::shared_ptr config(new TConfiguration(MAX_MESSAGE_SIZE)); std::shared_ptr pipe(new TMemoryBuffer); std::shared_ptr underlying(new TMemoryBuffer); std::shared_ptr trans(new TPipedTransport(underlying, pipe, config)); uint8_t buffer[4]; underlying->write((uint8_t*)"abcd", 4); BOOST_CHECK_THROW(trans->read(buffer, sizeof(buffer)), TTransportException); BOOST_CHECK_THROW(trans->readAll(buffer, sizeof(buffer)), TTransportException); trans->readEnd(); pipe->resetBuffer(); underlying->write((uint8_t*)"ef", 2); BOOST_CHECK_THROW(trans->read(buffer, sizeof(buffer)), TTransportException); BOOST_CHECK_THROW(trans->readAll(buffer, sizeof(buffer)), TTransportException); trans->readEnd(); } BOOST_AUTO_TEST_CASE(test_tsimplefiletransport_read_check_exception) { std::shared_ptr config(new TConfiguration(MAX_MESSAGE_SIZE)); TSimpleFileTransport trans_out("data", false, true, config); uint8_t buffer[6] = {1, 2, 3, 4, 5, 6}; trans_out.write((const uint8_t*)buffer, sizeof(buffer)); trans_out.close(); TSimpleFileTransport trans_in("data",true, false, config); memset(buffer, 0, sizeof(buffer)); BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException); trans_in.close(); remove("./data"); } BOOST_AUTO_TEST_CASE(test_tfiletransport_read_check_exception) { std::shared_ptr config(new TConfiguration(MAX_MESSAGE_SIZE)); TFileTransport trans_out("data", false, config); uint8_t buffer[6] = {1, 2, 3, 4, 5, 6}; trans_out.write((const uint8_t*)buffer, sizeof(buffer)); TFileTransport trans_in("data", false, config); memset(buffer, 0, sizeof(buffer)); BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException); remove("./data"); } BOOST_AUTO_TEST_CASE(test_tbufferedtransport_read_check_exception) { uint8_t arr[4] = {1, 2, 3, 4}; std::shared_ptr buffer (new TMemoryBuffer(arr, sizeof(arr))); std::shared_ptr config (new TConfiguration(MAX_MESSAGE_SIZE)); std::shared_ptr trans (new TBufferedTransport(buffer, config)); trans->write((const uint8_t*)arr, sizeof(arr)); BOOST_CHECK_THROW(trans->read(arr, sizeof(arr)), TTransportException); } BOOST_AUTO_TEST_CASE(test_tframedtransport_read_check_exception) { uint8_t arr[4] = {1, 2, 3, 4}; std::shared_ptr buffer (new TMemoryBuffer(arr, sizeof(arr))); std::shared_ptr config (new TConfiguration(MAX_MESSAGE_SIZE)); std::shared_ptr trans (new TFramedTransport(buffer, config)); trans->write((const uint8_t*)arr, sizeof(arr)); BOOST_CHECK_THROW(trans->read(arr, sizeof(arr)), TTransportException); } BOOST_AUTO_TEST_CASE(test_tthriftbinaryprotocol_read_check_exception) { std::shared_ptr config (new TConfiguration(MAX_MESSAGE_SIZE)); std::shared_ptr transport(new TMemoryBuffer(config)); std::shared_ptr protocol(new TBinaryProtocol(transport)); uint32_t val = 0; TType elemType = apache::thrift::protocol::T_STOP; TType elemType1 = apache::thrift::protocol::T_STOP; TList list(T_I32, 8); protocol->writeListBegin(list.elemType_, list.size_); protocol->writeListEnd(); BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException); protocol->readListEnd(); TSet set(T_I32, 8); protocol->writeSetBegin(set.elemType_, set.size_); protocol->writeSetEnd(); BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException); protocol->readSetEnd(); TMap map(T_I32, T_I32, 8); protocol->writeMapBegin(map.keyType_, map.valueType_, map.size_); protocol->writeMapEnd(); BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException); protocol->readMapEnd(); } BOOST_AUTO_TEST_CASE(test_tthriftcompactprotocol_read_check_exception) { std::shared_ptr config (new TConfiguration(MAX_MESSAGE_SIZE)); std::shared_ptr transport(new TMemoryBuffer(config)); std::shared_ptr protocol(new TCompactProtocol(transport)); uint32_t val = 0; TType elemType = apache::thrift::protocol::T_STOP; TType elemType1 = apache::thrift::protocol::T_STOP; TList list(T_I32, 8); protocol->writeListBegin(list.elemType_, list.size_); protocol->writeListEnd(); BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException); protocol->readListEnd(); TSet set(T_I32, 8); protocol->writeSetBegin(set.elemType_, set.size_); protocol->writeSetEnd(); BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException); protocol->readSetEnd(); TMap map(T_I32, T_I32, 8); protocol->writeMapBegin(map.keyType_, map.valueType_, map.size_); protocol->writeMapEnd(); BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException); protocol->readMapEnd(); } BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_read_check_exception) { std::shared_ptr config (new TConfiguration(MAX_MESSAGE_SIZE)); std::shared_ptr transport(new TMemoryBuffer(config)); std::shared_ptr protocol(new TJSONProtocol(transport)); uint32_t val = 0; TType elemType = apache::thrift::protocol::T_STOP; TType elemType1 = apache::thrift::protocol::T_STOP; TList list(T_I32, 8); protocol->writeListBegin(list.elemType_, list.size_); protocol->writeListEnd(); BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException); protocol->readListEnd(); TSet set(T_I32, 8); protocol->writeSetBegin(set.elemType_, set.size_); protocol->writeSetEnd(); BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException); protocol->readSetEnd(); TMap map(T_I32, T_I32, 8); protocol->writeMapBegin(map.keyType_, map.valueType_, map.size_); protocol->writeMapEnd(); BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException); protocol->readMapEnd(); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/TFDTransportTest.cpp0000644000000000000000000000314314303740367021314 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #define BOOST_TEST_MODULE TFDTransportTest #include // Disabled on MSVC because the RTL asserts on an invalid file descriptor // in both debug and release mode; at least in MSVCR100 (Visual Studio 2010) #if !defined(WIN32) using apache::thrift::transport::TTransportException; using apache::thrift::transport::TFDTransport; BOOST_AUTO_TEST_CASE(test_tfdtransport_1) { BOOST_CHECK_NO_THROW(TFDTransport t(256, TFDTransport::CLOSE_ON_DESTROY)); } BOOST_AUTO_TEST_CASE(test_tfdtransport_2) { TFDTransport t(256, TFDTransport::CLOSE_ON_DESTROY); BOOST_CHECK_THROW(t.close(), TTransportException); } #else BOOST_AUTO_TEST_CASE(test_tfdtransport_dummy) { BOOST_CHECK(true); } #endif thrift-0.19.0/lib/cpp/test/Benchmark.cpp0000644000000000000000000001455214303740367020022 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifdef HAVE_CONFIG_H #include #endif #include #define _USE_MATH_DEFINES #include #include #include "thrift/protocol/TBinaryProtocol.h" #include "thrift/transport/TBufferTransports.h" #include "gen-cpp/DebugProtoTest_types.h" #ifdef HAVE_SYS_TIME_H #include #endif class Timer { public: timeval vStart; Timer() { THRIFT_GETTIMEOFDAY(&vStart, nullptr); } void start() { THRIFT_GETTIMEOFDAY(&vStart, nullptr); } double frame() { timeval vEnd; THRIFT_GETTIMEOFDAY(&vEnd, nullptr); double dstart = vStart.tv_sec + ((double)vStart.tv_usec / 1000000.0); double dend = vEnd.tv_sec + ((double)vEnd.tv_usec / 1000000.0); return dend - dstart; } }; int main() { using namespace thrift::test::debug; using namespace apache::thrift::transport; using namespace apache::thrift::protocol; using std::cout; using std::endl; OneOfEach ooe; ooe.im_true = true; ooe.im_false = false; ooe.a_bite = 0x7f; ooe.integer16 = 27000; ooe.integer32 = 1 << 24; ooe.integer64 = (uint64_t)6000 * 1000 * 1000; ooe.double_precision = M_PI; ooe.some_characters = "JSON THIS! \"\1"; ooe.zomg_unicode = "\xd7\n\a\t"; ooe.base64 = "\1\2\3\255"; int num = 100000; std::shared_ptr buf(new TMemoryBuffer(num*1000)); uint8_t* data = nullptr; uint32_t datasize = 0; { buf->resetBuffer(); TBinaryProtocolT prot(buf); double elapsed = 0.0; Timer timer; for (int i = 0; i < num; i++) { ooe.write(&prot); } elapsed = timer.frame(); cout << "Write big endian: " << num / (1000 * elapsed) << " kHz" << endl; } buf->getBuffer(&data, &datasize); { std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); OneOfEach ooe2; double elapsed = 0.0; Timer timer; for (int i = 0; i < num; i++) { ooe2.read(&prot); } elapsed = timer.frame(); cout << " Read big endian: " << num / (1000 * elapsed) << " kHz" << endl; } { buf->resetBuffer(); TBinaryProtocolT prot(buf); double elapsed = 0.0; Timer timer; for (int i = 0; i < num; i++) { ooe.write(&prot); } elapsed = timer.frame(); cout << "Write little endian: " << num / (1000 * elapsed) << " kHz" << endl; } { OneOfEach ooe2; std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); double elapsed = 0.0; Timer timer; for (int i = 0; i < num; i++) { ooe2.read(&prot); } elapsed = timer.frame(); cout << " Read little endian: " << num / (1000 * elapsed) << " kHz" << endl; } { buf->resetBuffer(); TBinaryProtocolT prot(buf); double elapsed = 0.0; Timer timer; for (int i = 0; i < num; i++) { ooe.write(&prot); } elapsed = timer.frame(); cout << "Write big endian: " << num / (1000 * elapsed) << " kHz" << endl; } { std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); OneOfEach ooe2; double elapsed = 0.0; Timer timer; for (int i = 0; i < num; i++) { ooe2.read(&prot); } elapsed = timer.frame(); cout << " Read big endian: " << num / (1000 * elapsed) << " kHz" << endl; } data = nullptr; datasize = 0; num = 10000000; ListDoublePerf listDoublePerf; listDoublePerf.field.reserve(num); for (int x = 0; x < num; ++x) listDoublePerf.field.push_back(double(x)); buf.reset(new TMemoryBuffer(num * 100)); { buf->resetBuffer(); TBinaryProtocolT prot(buf); double elapsed = 0.0; Timer timer; listDoublePerf.write(&prot); elapsed = timer.frame(); cout << "Double write big endian: " << num / (1000 * elapsed) << " kHz" << endl; } buf->getBuffer(&data, &datasize); { std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); ListDoublePerf listDoublePerf2; double elapsed = 0.0; Timer timer; listDoublePerf2.read(&prot); elapsed = timer.frame(); cout << " Double read big endian: " << num / (1000 * elapsed) << " kHz" << endl; } { buf->resetBuffer(); TBinaryProtocolT prot(buf); double elapsed = 0.0; Timer timer; listDoublePerf.write(&prot); elapsed = timer.frame(); cout << "Double write little endian: " << num / (1000 * elapsed) << " kHz" << endl; } { ListDoublePerf listDoublePerf2; std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); double elapsed = 0.0; Timer timer; listDoublePerf2.read(&prot); elapsed = timer.frame(); cout << " Double read little endian: " << num / (1000 * elapsed) << " kHz" << endl; } { buf->resetBuffer(); TBinaryProtocolT prot(buf); double elapsed = 0.0; Timer timer; listDoublePerf.write(&prot); elapsed = timer.frame(); cout << "Double write big endian: " << num / (1000 * elapsed) << " kHz" << endl; } { std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); ListDoublePerf listDoublePerf2; double elapsed = 0.0; Timer timer; listDoublePerf2.read(&prot); elapsed = timer.frame(); cout << " Double read big endian: " << num / (1000 * elapsed) << " kHz" << endl; } return 0; } thrift-0.19.0/lib/cpp/test/link/0000755000000000000000000000000014472652651016357 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/test/link/TemplatedService1.cpp0000644000000000000000000000174414303740367022405 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This file is a part of a link test that makes sure generated * templated service headers can be included from multiple * implementation files. */ #include "gen-cpp/ParentService.h" thrift-0.19.0/lib/cpp/test/link/LinkTest.cpp0000644000000000000000000000151314303740367020613 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ int main(int, char**) { return 0; } thrift-0.19.0/lib/cpp/test/link/TemplatedService2.cpp0000644000000000000000000000174414303740367022406 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This file is a part of a link test that makes sure generated * templated service headers can be included from multiple * implementation files. */ #include "gen-cpp/ParentService.h" thrift-0.19.0/lib/cpp/test/TServerSocketTest.cpp0000644000000000000000000000453414303740367021532 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include "TTransportCheckThrow.h" #include using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using std::shared_ptr; BOOST_AUTO_TEST_SUITE(TServerSocketTest) BOOST_AUTO_TEST_CASE(test_bind_to_address) { TServerSocket sock1("localhost", 0); sock1.listen(); BOOST_CHECK(sock1.isOpen()); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); shared_ptr accepted = sock1.accept(); accepted->close(); sock1.close(); std::cout << "An error message from getaddrinfo on the console is expected:" << std::endl; TServerSocket sock2("257.258.259.260", 0); BOOST_CHECK_THROW(sock2.listen(), TTransportException); sock2.close(); } BOOST_AUTO_TEST_CASE(test_listen_invalid_port) { TServerSocket sock1(-1); TTRANSPORT_CHECK_THROW(sock1.listen(), TTransportException::BAD_ARGS); BOOST_CHECK(!sock1.isOpen()); TServerSocket sock2(65536); TTRANSPORT_CHECK_THROW(sock2.listen(), TTransportException::BAD_ARGS); BOOST_CHECK(!sock1.isOpen()); } BOOST_AUTO_TEST_CASE(test_close_before_listen) { TServerSocket sock1("localhost", 0); sock1.close(); BOOST_CHECK(!sock1.isOpen()); } BOOST_AUTO_TEST_CASE(test_get_port) { TServerSocket sock1("localHost", 888); BOOST_CHECK_EQUAL(888, sock1.getPort()); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/DebugProtoTest.cpp0000644000000000000000000002370714303740367021044 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define _USE_MATH_DEFINES #include #include "gen-cpp/DebugProtoTest_types.h" #include #include #define BOOST_TEST_MODULE DebugProtoTest #include using namespace thrift::test::debug; static ::std::shared_ptr ooe; void testCaseSetup_1() { ooe.reset(new OneOfEach); ooe->im_true = true; ooe->im_false = false; ooe->a_bite = 0x7f; ooe->integer16 = 27000; ooe->integer32 = 1 << 24; ooe->integer64 = (uint64_t)6000 * 1000 * 1000; ooe->double_precision = M_PI; ooe->some_characters = "Debug THIS!"; ooe->zomg_unicode = "\xd7\n\a\t"; } BOOST_AUTO_TEST_CASE(test_debug_proto_1) { testCaseSetup_1(); const std::string expected_result( "OneOfEach {\n" " 01: im_true (bool) = true,\n" " 02: im_false (bool) = false,\n" " 03: a_bite (byte) = 0x7f,\n" " 04: integer16 (i16) = 27000,\n" " 05: integer32 (i32) = 16777216,\n" " 06: integer64 (i64) = 6000000000,\n" " 07: double_precision (double) = 3.1415926535897931,\n" " 08: some_characters (string) = \"Debug THIS!\",\n" " 09: zomg_unicode (string) = \"\\xd7\\n\\a\\t\",\n" " 10: what_who (bool) = false,\n" " 11: base64 (string) = \"\",\n" " 12: byte_list (list) = list[3] {\n" " [0] = 0x01,\n" " [1] = 0x02,\n" " [2] = 0x03,\n" " },\n" " 13: i16_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " 14: i64_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" "}"); const std::string result(apache::thrift::ThriftDebugString(*ooe)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } static ::std::shared_ptr n; void testCaseSetup_2() { testCaseSetup_1(); n.reset(new Nesting); n->my_ooe = *ooe; n->my_ooe.integer16 = 16; n->my_ooe.integer32 = 32; n->my_ooe.integer64 = 64; n->my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2; n->my_ooe.some_characters = ":R (me going \"rrrr\")"; n->my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce" "\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0" "\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74" "\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80" "\xbc"; n->my_bonk.type = 31337; n->my_bonk.message = "I am a bonk... xor!"; } BOOST_AUTO_TEST_CASE(test_debug_proto_2) { testCaseSetup_2(); const std::string expected_result( "Nesting {\n" " 01: my_bonk (struct) = Bonk {\n" " 01: type (i32) = 31337,\n" " 02: message (string) = \"I am a bonk... xor!\",\n" " },\n" " 02: my_ooe (struct) = OneOfEach {\n" " 01: im_true (bool) = true,\n" " 02: im_false (bool) = false,\n" " 03: a_bite (byte) = 0x7f,\n" " 04: integer16 (i16) = 16,\n" " 05: integer32 (i32) = 32,\n" " 06: integer64 (i64) = 64,\n" " 07: double_precision (double) = 1.6180339887498949,\n" " 08: some_characters (string) = \":R (me going \\\"rrrr\\\")\",\n" " 09: zomg_unicode (string) = \"\\xd3\\x80\\xe2\\x85\\xae\\xce\\x9d \\xd" "0\\x9d\\xce\\xbf\\xe2\\x85\\xbf\\xd0\\xbe\\xc9\\xa1\\xd0\\xb3\\xd0\\xb0" "\\xcf\\x81\\xe2\\x84\\x8e \\xce\\x91tt\\xce\\xb1\\xe2\\x85\\xbd\\xce\\xb" "a\\xc7\\x83\\xe2\\x80\\xbc\",\n" " 10: what_who (bool) = false,\n" " 11: base64 (string) = \"\",\n" " 12: byte_list (list) = list[3] {\n" " [0] = 0x01,\n" " [1] = 0x02,\n" " [2] = 0x03,\n" " },\n" " 13: i16_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " 14: i64_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " },\n" "}"); const std::string result(apache::thrift::ThriftDebugString(*n)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } static ::std::shared_ptr hm; void testCaseSetup_3() { testCaseSetup_2(); hm.reset(new HolyMoley); hm->big.push_back(*ooe); hm->big.push_back(n->my_ooe); hm->big[0].a_bite = 0x22; hm->big[1].a_bite = 0x33; std::vector stage1; stage1.push_back("and a one"); stage1.push_back("and a two"); hm->contain.insert(stage1); stage1.clear(); stage1.push_back("then a one, two"); stage1.push_back("three!"); stage1.push_back("FOUR!!"); hm->contain.insert(stage1); stage1.clear(); hm->contain.insert(stage1); std::vector stage2; hm->bonks["nothing"] = stage2; stage2.resize(stage2.size() + 1); stage2.back().type = 1; stage2.back().message = "Wait."; stage2.resize(stage2.size() + 1); stage2.back().type = 2; stage2.back().message = "What?"; hm->bonks["something"] = stage2; stage2.clear(); stage2.resize(stage2.size() + 1); stage2.back().type = 3; stage2.back().message = "quoth"; stage2.resize(stage2.size() + 1); stage2.back().type = 4; stage2.back().message = "the raven"; stage2.resize(stage2.size() + 1); stage2.back().type = 5; stage2.back().message = "nevermore"; hm->bonks["poe"] = stage2; } BOOST_AUTO_TEST_CASE(test_debug_proto_3) { testCaseSetup_3(); const std::string expected_result( "HolyMoley {\n" " 01: big (list) = list[2] {\n" " [0] = OneOfEach {\n" " 01: im_true (bool) = true,\n" " 02: im_false (bool) = false,\n" " 03: a_bite (byte) = 0x22,\n" " 04: integer16 (i16) = 27000,\n" " 05: integer32 (i32) = 16777216,\n" " 06: integer64 (i64) = 6000000000,\n" " 07: double_precision (double) = 3.1415926535897931,\n" " 08: some_characters (string) = \"Debug THIS!\",\n" " 09: zomg_unicode (string) = \"\\xd7\\n\\a\\t\",\n" " 10: what_who (bool) = false,\n" " 11: base64 (string) = \"\",\n" " 12: byte_list (list) = list[3] {\n" " [0] = 0x01,\n" " [1] = 0x02,\n" " [2] = 0x03,\n" " },\n" " 13: i16_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " 14: i64_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " },\n" " [1] = OneOfEach {\n" " 01: im_true (bool) = true,\n" " 02: im_false (bool) = false,\n" " 03: a_bite (byte) = 0x33,\n" " 04: integer16 (i16) = 16,\n" " 05: integer32 (i32) = 32,\n" " 06: integer64 (i64) = 64,\n" " 07: double_precision (double) = 1.6180339887498949,\n" " 08: some_characters (string) = \":R (me going \\\"rrrr\\\")\",\n" " 09: zomg_unicode (string) = \"\\xd3\\x80\\xe2\\x85\\xae\\xce\\x9d \\" "xd0\\x9d\\xce\\xbf\\xe2\\x85\\xbf\\xd0\\xbe\\xc9\\xa1\\xd0\\xb3\\xd0\\xb" "0\\xcf\\x81\\xe2\\x84\\x8e \\xce\\x91tt\\xce\\xb1\\xe2\\x85\\xbd\\xce\\x" "ba\\xc7\\x83\\xe2\\x80\\xbc\",\n" " 10: what_who (bool) = false,\n" " 11: base64 (string) = \"\",\n" " 12: byte_list (list) = list[3] {\n" " [0] = 0x01,\n" " [1] = 0x02,\n" " [2] = 0x03,\n" " },\n" " 13: i16_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " 14: i64_list (list) = list[3] {\n" " [0] = 1,\n" " [1] = 2,\n" " [2] = 3,\n" " },\n" " },\n" " },\n" " 02: contain (set) = set[3] {\n" " list[0] {\n" " },\n" " list[2] {\n" " [0] = \"and a one\",\n" " [1] = \"and a two\",\n" " },\n" " list[3] {\n" " [0] = \"then a one, two\",\n" " [1] = \"three!\",\n" " [2] = \"FOUR!!\",\n" " },\n" " },\n" " 03: bonks (map) = map[3] {\n" " \"nothing\" -> list[0] {\n" " },\n" " \"poe\" -> list[3] {\n" " [0] = Bonk {\n" " 01: type (i32) = 3,\n" " 02: message (string) = \"quoth\",\n" " },\n" " [1] = Bonk {\n" " 01: type (i32) = 4,\n" " 02: message (string) = \"the raven\",\n" " },\n" " [2] = Bonk {\n" " 01: type (i32) = 5,\n" " 02: message (string) = \"nevermore\",\n" " },\n" " },\n" " \"something\" -> list[2] {\n" " [0] = Bonk {\n" " 01: type (i32) = 1,\n" " 02: message (string) = \"Wait.\",\n" " },\n" " [1] = Bonk {\n" " 01: type (i32) = 2,\n" " 02: message (string) = \"What?\",\n" " },\n" " },\n" " },\n" "}"); const std::string result(apache::thrift::ThriftDebugString(*hm)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } thrift-0.19.0/lib/cpp/test/GenericHelpers.h0000644000000000000000000000650614303740367020474 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_GENERICHELPERS_H_ #define _THRIFT_TEST_GENERICHELPERS_H_ 1 #include #include #include /* ClassName Helper for cleaner exceptions */ class ClassNames { public: template static const char* getName() { return "Unknown type"; } }; template <> const char* ClassNames::getName() { return "byte"; } template <> const char* ClassNames::getName() { return "short"; } template <> const char* ClassNames::getName() { return "int"; } template <> const char* ClassNames::getName() { return "long"; } template <> const char* ClassNames::getName() { return "double"; } template <> const char* ClassNames::getName() { return "string"; } /* Generic Protocol I/O function for tests */ class GenericIO { public: /* Write functions */ static uint32_t write(std::shared_ptr proto, const int8_t& val) { return proto->writeByte(val); } static uint32_t write(std::shared_ptr proto, const int16_t& val) { return proto->writeI16(val); } static uint32_t write(std::shared_ptr proto, const int32_t& val) { return proto->writeI32(val); } static uint32_t write(std::shared_ptr proto, const double& val) { return proto->writeDouble(val); } static uint32_t write(std::shared_ptr proto, const int64_t& val) { return proto->writeI64(val); } static uint32_t write(std::shared_ptr proto, const std::string& val) { return proto->writeString(val); } /* Read functions */ static uint32_t read(std::shared_ptr proto, int8_t& val) { return proto->readByte(val); } static uint32_t read(std::shared_ptr proto, int16_t& val) { return proto->readI16(val); } static uint32_t read(std::shared_ptr proto, int32_t& val) { return proto->readI32(val); } static uint32_t read(std::shared_ptr proto, int64_t& val) { return proto->readI64(val); } static uint32_t read(std::shared_ptr proto, double& val) { return proto->readDouble(val); } static uint32_t read(std::shared_ptr proto, std::string& val) { return proto->readString(val); } }; #endif thrift-0.19.0/lib/cpp/test/TMemoryBufferTest.cpp0000644000000000000000000003044114452237057021513 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include #include #include #include #include #include #include "gen-cpp/ThriftTest_types.h" BOOST_AUTO_TEST_SUITE(TMemoryBufferTest) using apache::thrift::protocol::TBinaryProtocol; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TTransportException; using std::shared_ptr; using std::cout; using std::endl; using std::string; BOOST_AUTO_TEST_CASE(test_read_write_grow) { // Added to test the fix for THRIFT-1248 TMemoryBuffer uut; const int maxSize = 65536; uint8_t verify[maxSize]; std::vector buf; buf.resize(maxSize); for (uint32_t i = 0; i < maxSize; ++i) { buf[i] = static_cast(i); } for (uint32_t i = 1; i < maxSize; i *= 2) { uut.write(&buf[0], i); } for (uint32_t i = 1; i < maxSize; i *= 2) { uut.read(verify, i); BOOST_CHECK_EQUAL(0, ::memcmp(verify, &buf[0], i)); } } BOOST_AUTO_TEST_CASE(test_roundtrip) { shared_ptr strBuffer(new TMemoryBuffer()); shared_ptr binaryProtcol(new TBinaryProtocol(strBuffer)); thrift::test::Xtruct a; a.i32_thing = 10; a.i64_thing = 30; a.string_thing = "holla back a"; a.write(binaryProtcol.get()); std::string serialized = strBuffer->getBufferAsString(); shared_ptr strBuffer2(new TMemoryBuffer()); shared_ptr binaryProtcol2(new TBinaryProtocol(strBuffer2)); strBuffer2->resetBuffer((uint8_t*)serialized.data(), static_cast(serialized.length())); thrift::test::Xtruct a2; a2.read(binaryProtcol2.get()); BOOST_CHECK(a == a2); } BOOST_AUTO_TEST_CASE(test_readAppendToString) { string str1 = "abcd1234"; TMemoryBuffer buf((uint8_t*)str1.data(), static_cast(str1.length()), TMemoryBuffer::COPY); string str3 = "wxyz", str4 = "6789"; buf.readAppendToString(str3, 4); buf.readAppendToString(str4, INT_MAX); BOOST_CHECK(str3 == "wxyzabcd"); BOOST_CHECK(str4 == "67891234"); } BOOST_AUTO_TEST_CASE(test_exceptions) { char data[] = "foo\0bar"; TMemoryBuffer buf1((uint8_t*)data, 7, TMemoryBuffer::OBSERVE); string str = buf1.getBufferAsString(); BOOST_CHECK(str.length() == 7); buf1.resetBuffer(); BOOST_CHECK_THROW(buf1.write((const uint8_t*)"foo", 3), TTransportException); TMemoryBuffer buf2((uint8_t*)data, 7, TMemoryBuffer::COPY); BOOST_CHECK_NO_THROW(buf2.write((const uint8_t*)"bar", 3)); } BOOST_AUTO_TEST_CASE(test_default_maximum_buffer_size) { BOOST_CHECK_EQUAL((std::numeric_limits::max)(), TMemoryBuffer().getMaxBufferSize()); } BOOST_AUTO_TEST_CASE(test_default_buffer_size) { BOOST_CHECK_EQUAL(1024, TMemoryBuffer().getBufferSize()); } BOOST_AUTO_TEST_CASE(test_error_set_max_buffer_size_too_small) { TMemoryBuffer buf; BOOST_CHECK_THROW(buf.setMaxBufferSize(buf.getBufferSize() - 1), TTransportException); } BOOST_AUTO_TEST_CASE(test_observe) { #ifdef _MSC_VER #define N 73 #else constexpr size_t N = 73; #endif constexpr size_t M = 42; uint8_t one_byte = 42; std::vector scratch; auto filler = [=]() { std::array x; // Fill buf_mem with a sequence from 0 to N - 1 std::iota(x.begin(), x.end(), 0); return x; }; static const std::array buf_mem = filler(); BOOST_STATIC_ASSERT(M < N); TMemoryBuffer buf((uint8_t*)&buf_mem.front(), N, TMemoryBuffer::MemoryPolicy::OBSERVE); // Readable BOOST_CHECK_EQUAL(N, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Not writeable BOOST_CHECK_THROW(buf.write(&one_byte, 1), TTransportException); // Read some but not all scratch.resize(M); BOOST_CHECK_EQUAL(M, buf.read(&scratch[0], M)); // Check remaining BOOST_CHECK_EQUAL(N - M, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Not writeable BOOST_CHECK_THROW(buf.write(&one_byte, 1), TTransportException); // Contents BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), buf_mem.begin(), buf_mem.begin() + M); // Readable (drain remaining) scratch.resize(N); BOOST_CHECK_EQUAL(N - M, buf.read(&scratch[M], N - M)); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Not writeable BOOST_CHECK_THROW(buf.write(&one_byte, 1), TTransportException); // Contents BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), buf_mem.begin(), buf_mem.end()); // Not readable BOOST_CHECK_EQUAL(0, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(0, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Not writeable BOOST_CHECK_THROW(buf.write(&one_byte, 1), TTransportException); /* OBSERVE buffer cannot be reread with the default reset */ buf.resetBuffer(); // Not Readable BOOST_CHECK_EQUAL(0, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Not writeable BOOST_CHECK_THROW(buf.write(&one_byte, 1), TTransportException); /* OBSERVE buffers do not auto-resize when written to (implicit) */ /* OBSERVE buffers can be appended-to (implicit) */ } BOOST_AUTO_TEST_CASE(test_copy) { #ifdef _MSC_VER #define N 73 #else constexpr size_t N = 73; #endif constexpr size_t M = 42; uint8_t one_byte = 42; std::vector scratch; auto filler = [&]() { std::array x; // Fill buf_mem with a sequence from 0 to N - 1 std::iota(x.begin(), x.end(), 0); return x; }; static const std::array buf_mem = filler(); BOOST_STATIC_ASSERT(M < N); TMemoryBuffer buf((uint8_t*)&buf_mem.front(), N, TMemoryBuffer::MemoryPolicy::COPY); // Readable BOOST_CHECK_EQUAL(N, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Read some but not all scratch.resize(M); BOOST_CHECK_EQUAL(M, buf.read(&scratch[0], M)); // Check remaining BOOST_CHECK_EQUAL(N - M, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Contents BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), buf_mem.begin(), buf_mem.begin() + M); // Readable (drain remaining) scratch.resize(N); BOOST_CHECK_EQUAL(N - M, buf.read(&scratch[M], N - M)); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Contents BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), buf_mem.begin(), buf_mem.end()); // Not readable BOOST_CHECK_EQUAL(0, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(0, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); /* COPY buffer cannot be reread with the default reset */ buf.resetBuffer(); // Not readable BOOST_CHECK_EQUAL(0, buf.available_read()); // Has available write space BOOST_CHECK_EQUAL(N, buf.available_write()); /* COPY buffers auto-resize when written to */ // Not readable BOOST_CHECK_EQUAL(0, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(0, buf.available_read()); // No available write space BOOST_CHECK_GT(buf.available_write(), 0); // Writeable one_byte = M; BOOST_CHECK_NO_THROW(buf.write(&one_byte, 1)); // Readable one_byte = 0xff; BOOST_CHECK_EQUAL(1, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(one_byte, M); /* COPY buffers can be appended-to (and auto-resize) */ buf.resetBuffer((uint8_t*)&buf_mem.front(), N, TMemoryBuffer::MemoryPolicy::COPY); // Appendable one_byte = N + 1; BOOST_CHECK_NO_THROW(buf.write(&one_byte, 1)); BOOST_CHECK_EQUAL(N, buf.read(&scratch[0], N)); BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), buf_mem.begin(), buf_mem.begin() + N); one_byte = 0xff; BOOST_CHECK_EQUAL(1, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(one_byte, N + 1); } BOOST_AUTO_TEST_CASE(test_take_ownership) { #ifdef _MSC_VER #define N 73 #else constexpr size_t N = 73; #endif constexpr size_t M = 42; uint8_t one_byte = 42; std::vector scratch; auto filler = [&]() { /* TAKE_OWNERSHIP buffers MUST be malloc'ed */ uint8_t* x = static_cast(malloc(N)); // Fill buf_mem with a sequence from 0 to N - 1 std::iota(&x[0], &x[N], 0); return x; }; uint8_t* buf_mem = filler(); BOOST_STATIC_ASSERT(M < N); TMemoryBuffer buf(buf_mem, N, TMemoryBuffer::MemoryPolicy::TAKE_OWNERSHIP); // Readable BOOST_CHECK_EQUAL(N, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Read some but not all scratch.resize(M); BOOST_CHECK_EQUAL(M, buf.read(&scratch[0], M)); // Check remaining BOOST_CHECK_EQUAL(N - M, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Contents BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), &buf_mem[0], &buf_mem[M]); // Readable (drain remaining) scratch.resize(N); BOOST_CHECK_EQUAL(N - M, buf.read(&scratch[M], N - M)); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); // Contents BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), &buf_mem[0], &buf_mem[N]); // Not readable BOOST_CHECK_EQUAL(0, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(0, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(0, buf.available_write()); /* TAKE_OWNERSHIP buffers auto-resize when written to */ // Not readable BOOST_CHECK_EQUAL(0, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(0, buf.available_read()); // No available write space BOOST_CHECK_EQUAL(buf.available_write(), 0); // Writeable one_byte = M; BOOST_CHECK_NO_THROW(buf.write(&one_byte, 1)); // Readable one_byte = 0xff; BOOST_CHECK_EQUAL(1, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(one_byte, M); /* TAKE_OWNERSHIP buffers can be appended-to (and auto-resize) */ buf_mem = filler(); buf.resetBuffer(buf_mem, N, TMemoryBuffer::MemoryPolicy::COPY); // Appendable one_byte = N + 1; BOOST_CHECK_NO_THROW(buf.write(&one_byte, 1)); BOOST_CHECK_EQUAL(N, buf.read(&scratch[0], N)); BOOST_CHECK_EQUAL_COLLECTIONS(scratch.begin(), scratch.end(), &buf_mem[0], &buf_mem[N]); one_byte = 0xff; BOOST_CHECK_EQUAL(1, buf.read(&one_byte, 1)); BOOST_CHECK_EQUAL(one_byte, N + 1); } BOOST_AUTO_TEST_CASE(test_maximum_buffer_size) { TMemoryBuffer buf; buf.setMaxBufferSize(8192); std::vector small_buff(1); for (size_t i = 0; i < 8192; ++i) { buf.write(&small_buff[0], 1); } BOOST_CHECK_THROW(buf.write(&small_buff[0], 1), TTransportException); } BOOST_AUTO_TEST_CASE(test_buffer_overflow) { TMemoryBuffer buf; std::vector small_buff(1); buf.write(&small_buff[0], 1); BOOST_CHECK_THROW(buf.getWritePtr(std::numeric_limits::max()), TTransportException); } BOOST_AUTO_TEST_CASE(test_memory_buffer_to_get_sizeof_objects) { // This is a demonstration of how to use TMemoryBuffer to determine // the serialized size of a thrift object in the Binary protocol. // See THRIFT-3480 shared_ptr memBuffer(new TMemoryBuffer()); shared_ptr binaryProtcol(new TBinaryProtocol(memBuffer)); thrift::test::Xtruct object; object.i32_thing = 10; object.i64_thing = 30; object.string_thing = "who's your daddy?"; uint32_t size = object.write(binaryProtcol.get()); BOOST_CHECK_EQUAL(47, size); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/RecursiveTest.cpp0000644000000000000000000000533714303740367020740 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ #include "gen-cpp/Recursive_types.h" #include #include #include #define BOOST_TEST_MODULE RecursiveTest #include using apache::thrift::transport::TMemoryBuffer; using apache::thrift::protocol::TBinaryProtocol; using std::shared_ptr; BOOST_AUTO_TEST_CASE(test_recursive_1) { shared_ptr buf(new TMemoryBuffer()); shared_ptr prot(new TBinaryProtocol(buf)); RecTree tree; RecTree child; tree.children.push_back(child); tree.write(prot.get()); RecTree result; result.read(prot.get()); BOOST_CHECK(tree == result); } BOOST_AUTO_TEST_CASE(test_recursive_2) { shared_ptr buf(new TMemoryBuffer()); shared_ptr prot(new TBinaryProtocol(buf)); RecList l; shared_ptr l2(new RecList); l.nextitem = l2; l.write(prot.get()); RecList resultlist; resultlist.read(prot.get()); BOOST_CHECK(resultlist.nextitem != nullptr); BOOST_CHECK(resultlist.nextitem->nextitem == nullptr); } BOOST_AUTO_TEST_CASE(test_recursive_3) { shared_ptr buf(new TMemoryBuffer()); shared_ptr prot(new TBinaryProtocol(buf)); CoRec c; shared_ptr r(new CoRec2); c.other = r; c.write(prot.get()); c.read(prot.get()); BOOST_CHECK(c.other != nullptr); BOOST_CHECK(c.other->other.other == nullptr); } BOOST_AUTO_TEST_CASE(test_recursive_4) { shared_ptr buf(new TMemoryBuffer()); shared_ptr prot(new TBinaryProtocol(buf)); shared_ptr depthLimit(new RecList); depthLimit->nextitem = depthLimit; BOOST_CHECK_THROW(depthLimit->write(prot.get()), apache::thrift::protocol::TProtocolException); depthLimit->nextitem.reset(); } thrift-0.19.0/lib/cpp/test/UnitTestMain.cpp0000644000000000000000000000155214303740367020510 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE thrift #include thrift-0.19.0/lib/cpp/test/processor/0000777000000000000000000000000014472652702017442 5ustar00rootroot00000000000000thrift-0.19.0/lib/cpp/test/processor/proc.thrift0000644000000000000000000000241214370300523021606 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ namespace cpp apache.thrift.test exception MyError { 1: string message } service ParentService { i32 incrementGeneration() i32 getGeneration() void addString(1: string s) list getStrings() binary getDataWait(1: i32 length) oneway void onewayWait() void exceptionWait(1: string message) throws (2: MyError error) void unexpectedExceptionWait(1: string message) } service ChildService extends ParentService { i32 setValue(1: i32 value) i32 getValue() } thrift-0.19.0/lib/cpp/test/processor/Handlers.h0000644000000000000000000002374414303740367021357 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_PROCESSOR_TEST_HANDLERS_H_ #define _THRIFT_PROCESSOR_TEST_HANDLERS_H_ 1 #include "EventLog.h" #include "gen-cpp/ParentService.h" #include "gen-cpp/ChildService.h" namespace apache { namespace thrift { namespace test { class ParentHandler : virtual public ParentServiceIf { public: ParentHandler(const std::shared_ptr& log) : triggerMonitor(&mutex_), generation_(0), wait_(false), log_(log) {} int32_t incrementGeneration() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_INCREMENT_GENERATION, 0, 0); return ++generation_; } int32_t getGeneration() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_GENERATION, 0, 0); return generation_; } void addString(const std::string& s) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_ADD_STRING, 0, 0); strings_.push_back(s); } void getStrings(std::vector& _return) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_STRINGS, 0, 0); _return = strings_; } void getDataWait(std::string& _return, const int32_t length) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_DATA_WAIT, 0, 0); blockUntilTriggered(); _return.append(length, 'a'); } void onewayWait() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_ONEWAY_WAIT, 0, 0); blockUntilTriggered(); } void exceptionWait(const std::string& message) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_EXCEPTION_WAIT, 0, 0); blockUntilTriggered(); MyError e; e.message = message; throw e; } void unexpectedExceptionWait(const std::string& message) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, 0, 0); blockUntilTriggered(); MyError e; e.message = message; throw e; } /** * After prepareTriggeredCall() is invoked, calls to any of the *Wait() * functions won't return until triggerPendingCalls() is invoked * * This has to be a separate function invoked by the main test thread * in order to to avoid race conditions. */ void prepareTriggeredCall() { concurrency::Guard g(mutex_); wait_ = true; } /** * Wake up all calls waiting in blockUntilTriggered() */ void triggerPendingCalls() { concurrency::Guard g(mutex_); wait_ = false; triggerMonitor.notifyAll(); } protected: /** * blockUntilTriggered() won't return until triggerPendingCalls() is invoked * in another thread. * * This should only be called when already holding mutex_. */ void blockUntilTriggered() { while (wait_) { triggerMonitor.waitForever(); } // Log an event when we return log_->append(EventLog::ET_WAIT_RETURN, 0, 0); } concurrency::Mutex mutex_; concurrency::Monitor triggerMonitor; int32_t generation_; bool wait_; std::vector strings_; std::shared_ptr log_; }; #ifdef _MSC_VER #pragma warning( push ) #pragma warning (disable : 4250 ) //inheriting methods via dominance #endif class ChildHandler : public ParentHandler, virtual public ChildServiceIf { public: ChildHandler(const std::shared_ptr& log) : ParentHandler(log), value_(0) {} int32_t setValue(const int32_t value) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_SET_VALUE, 0, 0); int32_t oldValue = value_; value_ = value; return oldValue; } int32_t getValue() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_VALUE, 0, 0); return value_; } protected: int32_t value_; }; #ifdef _MSC_VER #pragma warning( pop ) #endif struct ConnContext { public: ConnContext(std::shared_ptr in, std::shared_ptr out, uint32_t id) : input(in), output(out), id(id) {} std::shared_ptr input; std::shared_ptr output; uint32_t id; }; struct CallContext { public: CallContext(ConnContext* context, uint32_t id, const std::string& name) : connContext(context), name(name), id(id) {} ConnContext* connContext; std::string name; uint32_t id; }; class ServerEventHandler : public server::TServerEventHandler { public: ServerEventHandler(const std::shared_ptr& log) : nextId_(1), log_(log) {} void preServe() override {} void* createContext(std::shared_ptr input, std::shared_ptr output) override { ConnContext* context = new ConnContext(input, output, nextId_); ++nextId_; log_->append(EventLog::ET_CONN_CREATED, context->id, 0); return context; } void deleteContext(void* serverContext, std::shared_ptr input, std::shared_ptr output) override { auto* context = reinterpret_cast(serverContext); if (input != context->input) { abort(); } if (output != context->output) { abort(); } log_->append(EventLog::ET_CONN_DESTROYED, context->id, 0); delete context; } void processContext(void* serverContext, std::shared_ptr transport) override { // TODO: We currently don't test the behavior of the processContext() // calls. The various server implementations call processContext() at // slightly different times, and it is too annoying to try and account for // their various differences. // // TThreadedServer, TThreadPoolServer, and TSimpleServer usually wait until // they see the first byte of a request before calling processContext(). // However, they don't wait for the first byte of the very first request, // and instead immediately call processContext() before any data is // received. // // TNonblockingServer always waits until receiving the full request before // calling processContext(). #if 0 ConnContext* context = reinterpret_cast(serverContext); log_->append(EventLog::ET_PROCESS, context->id, 0); #else THRIFT_UNUSED_VARIABLE(serverContext); THRIFT_UNUSED_VARIABLE(transport); #endif } protected: uint32_t nextId_; std::shared_ptr log_; }; class ProcessorEventHandler : public TProcessorEventHandler { public: ProcessorEventHandler(const std::shared_ptr& log) : nextId_(1), log_(log) {} void* getContext(const char* fnName, void* serverContext) override { auto* connContext = reinterpret_cast(serverContext); CallContext* context = new CallContext(connContext, nextId_, fnName); ++nextId_; log_->append(EventLog::ET_CALL_STARTED, connContext->id, context->id, fnName); return context; } void freeContext(void* ctx, const char* fnName) override { auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_CALL_FINISHED, context->connContext->id, context->id, fnName); delete context; } void preRead(void* ctx, const char* fnName) override { auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_PRE_READ, context->connContext->id, context->id, fnName); } void postRead(void* ctx, const char* fnName, uint32_t bytes) override { THRIFT_UNUSED_VARIABLE(bytes); auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_POST_READ, context->connContext->id, context->id, fnName); } void preWrite(void* ctx, const char* fnName) override { auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_PRE_WRITE, context->connContext->id, context->id, fnName); } void postWrite(void* ctx, const char* fnName, uint32_t bytes) override { THRIFT_UNUSED_VARIABLE(bytes); auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_POST_WRITE, context->connContext->id, context->id, fnName); } void asyncComplete(void* ctx, const char* fnName) override { auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_ASYNC_COMPLETE, context->connContext->id, context->id, fnName); } void handlerError(void* ctx, const char* fnName) override { auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_HANDLER_ERROR, context->connContext->id, context->id, fnName); } protected: void checkName(const CallContext* context, const char* fnName) { // Note: we can't use BOOST_CHECK_EQUAL here, since the handler runs in a // different thread from the test functions. Just abort if the names are // different if (context->name != fnName) { fprintf(stderr, "call context name mismatch: \"%s\" != \"%s\"\n", context->name.c_str(), fnName); fflush(stderr); abort(); } } uint32_t nextId_; std::shared_ptr log_; }; } } } // apache::thrift::test #endif // _THRIFT_PROCESSOR_TEST_HANDLERS_H_ thrift-0.19.0/lib/cpp/test/processor/ProcessorTest.cpp0000644000000000000000000010322114303740367022756 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * This file contains tests that ensure TProcessorEventHandler and * TServerEventHandler are invoked properly by the various server * implementations. */ #include #include #include #include #include #include #include #include #include #include #include "EventLog.h" #include "ServerThread.h" #include "Handlers.h" #include "gen-cpp/ChildService.h" using namespace apache::thrift; using namespace apache::thrift::concurrency; using namespace apache::thrift::protocol; using namespace apache::thrift::server; using namespace apache::thrift::test; using namespace apache::thrift::transport; using std::string; using std::vector; /* * Traits classes that encapsulate how to create various types of servers. */ class TSimpleServerTraits { public: typedef TSimpleServer ServerType; std::shared_ptr createServer( const std::shared_ptr& processor, uint16_t port, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) { std::shared_ptr socket(new TServerSocket(port)); return std::shared_ptr( new TSimpleServer(processor, socket, transportFactory, protocolFactory)); } }; class TThreadedServerTraits { public: typedef TThreadedServer ServerType; std::shared_ptr createServer( const std::shared_ptr& processor, uint16_t port, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) { std::shared_ptr socket(new TServerSocket(port)); return std::shared_ptr( new TThreadedServer(processor, socket, transportFactory, protocolFactory)); } }; class TThreadPoolServerTraits { public: typedef TThreadPoolServer ServerType; std::shared_ptr createServer( const std::shared_ptr& processor, uint16_t port, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) { std::shared_ptr socket(new TServerSocket(port)); std::shared_ptr threadFactory(new ThreadFactory); std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); threadManager->threadFactory(threadFactory); threadManager->start(); return std::shared_ptr( new TThreadPoolServer(processor, socket, transportFactory, protocolFactory, threadManager)); } }; class TNonblockingServerTraits { public: typedef TNonblockingServer ServerType; std::shared_ptr createServer( const std::shared_ptr& processor, uint16_t port, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) { // TNonblockingServer automatically uses TFramedTransport. // Raise an exception if the supplied transport factory is not a // TFramedTransportFactory auto* framedFactory = dynamic_cast(transportFactory.get()); if (framedFactory == nullptr) { throw TException("TNonblockingServer must use TFramedTransport"); } std::shared_ptr socket(new TNonblockingServerSocket(port)); std::shared_ptr threadFactory(new ThreadFactory); std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); threadManager->threadFactory(threadFactory); threadManager->start(); return std::shared_ptr( new TNonblockingServer(processor, protocolFactory, socket, threadManager)); } }; class TNonblockingServerNoThreadsTraits { public: typedef TNonblockingServer ServerType; std::shared_ptr createServer( const std::shared_ptr& processor, uint16_t port, const std::shared_ptr& transportFactory, const std::shared_ptr& protocolFactory) { // TNonblockingServer automatically uses TFramedTransport. // Raise an exception if the supplied transport factory is not a // TFramedTransportFactory auto* framedFactory = dynamic_cast(transportFactory.get()); if (framedFactory == nullptr) { throw TException("TNonblockingServer must use TFramedTransport"); } std::shared_ptr socket(new TNonblockingServerSocket(port)); // Use a NULL ThreadManager std::shared_ptr threadManager; return std::shared_ptr( new TNonblockingServer(processor, protocolFactory, socket, threadManager)); } }; /* * Traits classes for controlling if we instantiate templated or generic * protocol factories, processors, clients, etc. * * The goal is to allow the outer test code to select which server type is * being tested, and whether or not we are testing the templated classes, or * the generic classes. * * Each specific test case can control whether we create a child or parent * server, and whether we use TFramedTransport or TBufferedTransport. */ class UntemplatedTraits { public: typedef TBinaryProtocolFactory ProtocolFactory; typedef TBinaryProtocol Protocol; typedef ParentServiceProcessor ParentProcessor; typedef ChildServiceProcessor ChildProcessor; typedef ParentServiceClient ParentClient; typedef ChildServiceClient ChildClient; }; class TemplatedTraits { public: typedef TBinaryProtocolFactoryT ProtocolFactory; typedef TBinaryProtocolT Protocol; typedef ParentServiceProcessorT ParentProcessor; typedef ChildServiceProcessorT ChildProcessor; typedef ParentServiceClientT ParentClient; typedef ChildServiceClientT ChildClient; }; template class ParentServiceTraits { public: typedef typename TemplateTraits_::ParentProcessor Processor; typedef typename TemplateTraits_::ParentClient Client; typedef ParentHandler Handler; typedef typename TemplateTraits_::ProtocolFactory ProtocolFactory; typedef typename TemplateTraits_::Protocol Protocol; }; template class ChildServiceTraits { public: typedef typename TemplateTraits_::ChildProcessor Processor; typedef typename TemplateTraits_::ChildClient Client; typedef ChildHandler Handler; typedef typename TemplateTraits_::ProtocolFactory ProtocolFactory; typedef typename TemplateTraits_::Protocol Protocol; }; // TODO: It would be nicer if the TTransportFactory types defined a typedef, // to allow us to figure out the exact transport type without having to pass it // in as a separate template parameter here. // // It would also be niec if they used covariant return types. Unfortunately, // since they return shared_ptr instead of raw pointers, covariant return types // won't work. template class ServiceState : public ServerState { public: typedef typename ServiceTraits_::Processor Processor; typedef typename ServiceTraits_::Client Client; typedef typename ServiceTraits_::Handler Handler; ServiceState() : port_(0), log_(new EventLog), handler_(new Handler(log_)), processor_(new Processor(handler_)), transportFactory_(new TransportFactory_), protocolFactory_(new typename ServiceTraits_::ProtocolFactory), serverEventHandler_(new ServerEventHandler(log_)), processorEventHandler_(new ProcessorEventHandler(log_)) { processor_->setEventHandler(processorEventHandler_); } std::shared_ptr createServer(uint16_t port) override { ServerTraits_ serverTraits; return serverTraits.createServer(processor_, port, transportFactory_, protocolFactory_); } std::shared_ptr getServerEventHandler() override { return serverEventHandler_; } void bindSuccessful(uint16_t port) override { port_ = port; } uint16_t getPort() const { return port_; } const std::shared_ptr& getLog() const { return log_; } const std::shared_ptr& getHandler() const { return handler_; } std::shared_ptr createClient() { typedef typename ServiceTraits_::Protocol Protocol; std::shared_ptr socket(new TSocket("127.0.0.1", port_)); std::shared_ptr transport(new Transport_(socket)); std::shared_ptr protocol(new Protocol(transport)); transport->open(); std::shared_ptr client(new Client(protocol)); return client; } private: uint16_t port_; std::shared_ptr log_; std::shared_ptr handler_; std::shared_ptr processor_; std::shared_ptr transportFactory_; std::shared_ptr protocolFactory_; std::shared_ptr serverEventHandler_; std::shared_ptr processorEventHandler_; }; /** * Check that there are no more events in the log */ void checkNoEvents(const std::shared_ptr& log) { // Wait for an event with a very short timeout period. We don't expect // anything to be present, so we will normally wait for the full timeout. // On the other hand, a non-zero timeout is nice since it does give a short // window for events to arrive in case there is a problem. Event event = log->waitForEvent(10); BOOST_CHECK_EQUAL(EventLog::ET_LOG_END, event.type); } /** * Check for the events that should be logged when a new connection is created. * * Returns the connection ID allocated by the server. */ uint32_t checkNewConnEvents(const std::shared_ptr& log) { // Check for an ET_CONN_CREATED event Event event = log->waitForEvent(2500); BOOST_CHECK_EQUAL(EventLog::ET_CONN_CREATED, event.type); // Some servers call the processContext() hook immediately. // Others (TNonblockingServer) only call it once a full request is received. // We don't check for it yet, to allow either behavior. return event.connectionId; } /** * Check for the events that should be logged when a connection is closed. */ void checkCloseEvents(const std::shared_ptr& log, uint32_t connId) { // Check for an ET_CONN_DESTROYED event Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); // Make sure there are no more events checkNoEvents(log); } /** * Check for the events that should be logged when a call is received * and the handler is invoked. * * It does not check for anything after the handler invocation. * * Returns the call ID allocated by the server. */ uint32_t checkCallHandlerEvents(const std::shared_ptr& log, uint32_t connId, EventType callType, const string& callName) { // Call started Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_STARTED, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callName, event.message); uint32_t callId = event.callId; // Pre-read event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_PRE_READ, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // Post-read event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_POST_READ, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // Handler invocation event = log->waitForEvent(); BOOST_CHECK_EQUAL(callType, event.type); // The handler doesn't have any connection or call context, // so the connectionId and callId in this event aren't valid return callId; } /** * Check for the events that should be after a handler returns. */ void checkCallPostHandlerEvents(const std::shared_ptr& log, uint32_t connId, uint32_t callId, const string& callName) { // Pre-write Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_PRE_WRITE, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // Post-write event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_POST_WRITE, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // Call finished event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // It is acceptable for servers to call processContext() again immediately // to start waiting on the next request. However, some servers wait before // getting either a partial request or the full request before calling // processContext(). We don't check for the next call to processContext() // yet. } /** * Check for the events that should be logged when a call is made. * * This just calls checkCallHandlerEvents() followed by * checkCallPostHandlerEvents(). * * Returns the call ID allocated by the server. */ uint32_t checkCallEvents(const std::shared_ptr& log, uint32_t connId, EventType callType, const string& callName) { uint32_t callId = checkCallHandlerEvents(log, connId, callType, callName); checkCallPostHandlerEvents(log, connId, callId, callName); return callId; } /* * Test functions */ template void testParentService(const std::shared_ptr& state) { std::shared_ptr client = state->createClient(); int32_t gen = client->getGeneration(); int32_t newGen = client->incrementGeneration(); BOOST_CHECK_EQUAL(gen + 1, newGen); newGen = client->getGeneration(); BOOST_CHECK_EQUAL(gen + 1, newGen); client->addString("foo"); client->addString("bar"); client->addString("asdf"); vector strings; client->getStrings(strings); BOOST_REQUIRE_EQUAL(3, strings.size()); BOOST_REQUIRE_EQUAL("foo", strings[0]); BOOST_REQUIRE_EQUAL("bar", strings[1]); BOOST_REQUIRE_EQUAL("asdf", strings[2]); } template void testChildService(const std::shared_ptr& state) { std::shared_ptr client = state->createClient(); // Test calling some of the parent methids via the a child client int32_t gen = client->getGeneration(); int32_t newGen = client->incrementGeneration(); BOOST_CHECK_EQUAL(gen + 1, newGen); newGen = client->getGeneration(); BOOST_CHECK_EQUAL(gen + 1, newGen); // Test some of the child methods client->setValue(10); BOOST_CHECK_EQUAL(10, client->getValue()); BOOST_CHECK_EQUAL(10, client->setValue(99)); BOOST_CHECK_EQUAL(99, client->getValue()); } template void testBasicService() { typedef ServiceState > State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); testParentService(state); } template void testInheritedService() { typedef ServiceState > State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); testParentService(state); testChildService(state); } /** * Test to make sure that the TServerEventHandler and TProcessorEventHandler * methods are invoked in the correct order with the actual events. */ template void testEventSequencing() { // We use TBufferedTransport for this test, instead of TFramedTransport. // This way the server will start processing data as soon as it is received, // instead of waiting for the full request. This is necessary so we can // separate the preRead() and postRead() events. typedef ServiceState, TBufferedTransportFactory, TBufferedTransport> State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); const std::shared_ptr& log = state->getLog(); // Make sure we're at the end of the log checkNoEvents(log); state->getHandler()->prepareTriggeredCall(); // Make sure createContext() is called after a connection has been // established. We open a plain socket instead of creating a client. std::shared_ptr socket(new TSocket("127.0.0.1", state->getPort())); socket->open(); // Make sure the proper events occurred after a new connection uint32_t connId = checkNewConnEvents(log); // Send a message header. We manually construct the request so that we // can test the timing for the preRead() call. string requestName = "getDataWait"; string eventName = "ParentService.getDataWait"; auto seqid = int32_t(time(nullptr)); TBinaryProtocol protocol(socket); protocol.writeMessageBegin(requestName, T_CALL, seqid); socket->flush(); // Make sure we saw the call started and pre-read events Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_STARTED, event.type); BOOST_CHECK_EQUAL(eventName, event.message); BOOST_CHECK_EQUAL(connId, event.connectionId); uint32_t callId = event.callId; event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_PRE_READ, event.type); BOOST_CHECK_EQUAL(eventName, event.message); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); // Make sure there are no new events checkNoEvents(log); // Send the rest of the request protocol.writeStructBegin("ParentService_getDataNotified_pargs"); protocol.writeFieldBegin("length", apache::thrift::protocol::T_I32, 1); protocol.writeI32(8 * 1024 * 1024); protocol.writeFieldEnd(); protocol.writeFieldStop(); protocol.writeStructEnd(); protocol.writeMessageEnd(); socket->writeEnd(); socket->flush(); // We should then see postRead() event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_POST_READ, event.type); BOOST_CHECK_EQUAL(eventName, event.message); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); // Then the handler should be invoked event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_GET_DATA_WAIT, event.type); // The handler won't respond until we notify it. // Make sure there are no more events. checkNoEvents(log); // Notify the handler that it should return // We just use a global lock for now, since it is easiest state->getHandler()->triggerPendingCalls(); // The handler will log a separate event before it returns event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type); // We should then see preWrite() event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_PRE_WRITE, event.type); BOOST_CHECK_EQUAL(eventName, event.message); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); // We requested more data than can be buffered, and we aren't reading it, // so the server shouldn't be able to finish its write yet. // Make sure there are no more events. checkNoEvents(log); // Read the response header string responseName; int32_t responseSeqid = 0; apache::thrift::protocol::TMessageType responseType; protocol.readMessageBegin(responseName, responseType, responseSeqid); BOOST_CHECK_EQUAL(responseSeqid, seqid); BOOST_CHECK_EQUAL(requestName, responseName); BOOST_CHECK_EQUAL(responseType, T_REPLY); // Read the body. We just ignore it for now. protocol.skip(T_STRUCT); // Now that we have read, the server should have finished sending the data // and called the postWrite() handler event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_POST_WRITE, event.type); BOOST_CHECK_EQUAL(eventName, event.message); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); // Call finished should be last event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type); BOOST_CHECK_EQUAL(eventName, event.message); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); // There should be no more events checkNoEvents(log); // Close the connection, and make sure we get a connection destroyed event socket->close(); event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); // There should be no more events checkNoEvents(log); } template void testSeparateConnections() { typedef ServiceState > State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); const std::shared_ptr& log = state->getLog(); // Create a client std::shared_ptr client1 = state->createClient(); // Make sure the expected events were logged uint32_t client1Id = checkNewConnEvents(log); // Create a second client std::shared_ptr client2 = state->createClient(); // Make sure the expected events were logged uint32_t client2Id = checkNewConnEvents(log); // The two connections should have different IDs BOOST_CHECK_NE(client1Id, client2Id); // Make a call, and check for the proper events int32_t value = 5; client1->setValue(value); uint32_t call1 = checkCallEvents(log, client1Id, EventLog::ET_CALL_SET_VALUE, "ChildService.setValue"); // Make a call with client2 int32_t v = client2->getValue(); BOOST_CHECK_EQUAL(value, v); checkCallEvents(log, client2Id, EventLog::ET_CALL_GET_VALUE, "ChildService.getValue"); // Make another call with client1 v = client1->getValue(); BOOST_CHECK_EQUAL(value, v); uint32_t call2 = checkCallEvents(log, client1Id, EventLog::ET_CALL_GET_VALUE, "ChildService.getValue"); BOOST_CHECK_NE(call1, call2); // Close the second client, and check for the appropriate events client2.reset(); checkCloseEvents(log, client2Id); } template void testOnewayCall() { typedef ServiceState > State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); const std::shared_ptr& log = state->getLog(); // Create a client std::shared_ptr client = state->createClient(); uint32_t connId = checkNewConnEvents(log); // Make a oneway call // It should return immediately, even though the server's handler // won't return right away state->getHandler()->prepareTriggeredCall(); client->onewayWait(); string callName = "ParentService.onewayWait"; uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_ONEWAY_WAIT, callName); // There shouldn't be any more events checkNoEvents(log); // Trigger the handler to return state->getHandler()->triggerPendingCalls(); // The handler will log an ET_WAIT_RETURN event when it wakes up Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type); // Now we should see the async complete event, then call finished event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_ASYNC_COMPLETE, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // Destroy the client, and check for connection closed events client.reset(); checkCloseEvents(log, connId); checkNoEvents(log); } template void testExpectedError() { typedef ServiceState > State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); const std::shared_ptr& log = state->getLog(); // Create a client std::shared_ptr client = state->createClient(); uint32_t connId = checkNewConnEvents(log); // Send the exceptionWait() call state->getHandler()->prepareTriggeredCall(); string message = "test 1234 test"; client->send_exceptionWait(message); string callName = "ParentService.exceptionWait"; uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_EXCEPTION_WAIT, callName); // There shouldn't be any more events checkNoEvents(log); // Trigger the handler to return state->getHandler()->triggerPendingCalls(); // The handler will log an ET_WAIT_RETURN event when it wakes up Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type); // Now receive the response try { client->recv_exceptionWait(); BOOST_FAIL("expected MyError to be thrown"); } catch (const MyError& e) { BOOST_CHECK_EQUAL(message, e.message); // Check if std::exception::what() is handled properly size_t message_pos = string(e.what()).find("TException - service has thrown: MyError"); BOOST_CHECK_NE(message_pos, string::npos); } // Now we should see the events for a normal call finish checkCallPostHandlerEvents(log, connId, callId, callName); // There shouldn't be any more events checkNoEvents(log); // Destroy the client, and check for connection closed events client.reset(); checkCloseEvents(log, connId); checkNoEvents(log); } template void testUnexpectedError() { typedef ServiceState > State; // Start the server std::shared_ptr state(new State); ServerThread serverThread(state, true); const std::shared_ptr& log = state->getLog(); // Create a client std::shared_ptr client = state->createClient(); uint32_t connId = checkNewConnEvents(log); // Send the unexpectedExceptionWait() call state->getHandler()->prepareTriggeredCall(); string message = "1234 test 5678"; client->send_unexpectedExceptionWait(message); string callName = "ParentService.unexpectedExceptionWait"; uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, callName); // There shouldn't be any more events checkNoEvents(log); // Trigger the handler to return state->getHandler()->triggerPendingCalls(); // The handler will log an ET_WAIT_RETURN event when it wakes up Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type); // Now receive the response try { client->recv_unexpectedExceptionWait(); BOOST_FAIL("expected TApplicationError to be thrown"); } catch (const TApplicationException&) { } // Now we should see a handler error event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_HANDLER_ERROR, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // pre-write and post-write events aren't generated after a handler error // (Even for non-oneway calls where a response is written.) // // A call finished event is logged when the call context is destroyed event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type); BOOST_CHECK_EQUAL(connId, event.connectionId); BOOST_CHECK_EQUAL(callId, event.callId); BOOST_CHECK_EQUAL(callName, event.message); // There shouldn't be any more events checkNoEvents(log); // Destroy the client, and check for connection closed events client.reset(); checkCloseEvents(log, connId); checkNoEvents(log); } // Macro to define simple tests that can be used with all server types #define DEFINE_SIMPLE_TESTS(Server, Template) \ BOOST_AUTO_TEST_CASE(Server##_##Template##_basicService) { \ testBasicService(); \ } \ BOOST_AUTO_TEST_CASE(Server##_##Template##_inheritedService) { \ testInheritedService(); \ } \ BOOST_AUTO_TEST_CASE(Server##_##Template##_oneway) { \ testOnewayCall(); \ } \ BOOST_AUTO_TEST_CASE(Server##_##Template##_exception) { \ testExpectedError(); \ } \ BOOST_AUTO_TEST_CASE(Server##_##Template##_unexpectedException) { \ testUnexpectedError(); \ } // Tests that require the server to process multiple connections concurrently // (i.e., not TSimpleServer) #define DEFINE_CONCURRENT_SERVER_TESTS(Server, Template) \ BOOST_AUTO_TEST_CASE(Server##_##Template##_separateConnections) { \ testSeparateConnections(); \ } // The testEventSequencing() test manually generates a request for the server, // and doesn't work with TFramedTransport. Therefore we can't test it with // TNonblockingServer. #define DEFINE_NOFRAME_TESTS(Server, Template) \ BOOST_AUTO_TEST_CASE(Server##_##Template##_eventSequencing) { \ testEventSequencing(); \ } #define DEFINE_TNONBLOCKINGSERVER_TESTS(Server, Template) \ DEFINE_SIMPLE_TESTS(Server, Template) \ DEFINE_CONCURRENT_SERVER_TESTS(Server, Template) #define DEFINE_ALL_SERVER_TESTS(Server, Template) \ DEFINE_SIMPLE_TESTS(Server, Template) \ DEFINE_CONCURRENT_SERVER_TESTS(Server, Template) \ DEFINE_NOFRAME_TESTS(Server, Template) DEFINE_ALL_SERVER_TESTS(TThreadedServer, Templated) DEFINE_ALL_SERVER_TESTS(TThreadedServer, Untemplated) DEFINE_ALL_SERVER_TESTS(TThreadPoolServer, Templated) DEFINE_ALL_SERVER_TESTS(TThreadPoolServer, Untemplated) DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServer, Templated) DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServer, Untemplated) DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServerNoThreads, Templated) DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServerNoThreads, Untemplated) DEFINE_SIMPLE_TESTS(TSimpleServer, Templated) DEFINE_SIMPLE_TESTS(TSimpleServer, Untemplated) DEFINE_NOFRAME_TESTS(TSimpleServer, Templated) DEFINE_NOFRAME_TESTS(TSimpleServer, Untemplated) // TODO: We should test TEventServer in the future. // For now, it is known not to work correctly with TProcessorEventHandler. #ifdef BOOST_TEST_DYN_LINK bool init_unit_test_suite() { ::boost::unit_test::framework::master_test_suite().p_name.value = "ProcessorTest"; return true; } int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv); } #else ::boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { THRIFT_UNUSED_VARIABLE(argc); THRIFT_UNUSED_VARIABLE(argv); ::boost::unit_test::framework::master_test_suite().p_name.value = "ProcessorTest"; return nullptr; } #endif thrift-0.19.0/lib/cpp/test/processor/ServerThread.h0000644000000000000000000000731114303740367022205 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_SERVERTHREAD_H_ #define _THRIFT_TEST_SERVERTHREAD_H_ 1 #include #include #include #include #include "EventLog.h" namespace apache { namespace thrift { namespace test { /** * A helper class to tell ServerThread how to create the server */ class ServerState { public: virtual ~ServerState() = default; /** * Create a server to listen on the specified port. * * If the server returned fails to bind to the specified port when serve() is * called on it, createServer() may be called again on a different port. */ virtual std::shared_ptr createServer(uint16_t port) = 0; /** * Get the TServerEventHandler to set on the server. * * This is only called after the server successfully binds and is about to * start serving traffic. It is invoked from the server thread, rather than * the main thread. */ virtual std::shared_ptr getServerEventHandler() { return std::shared_ptr(); } /** * This method is called in the server thread after server binding succeeds. * * Subclasses may override this method if they wish to record the final * port that was used for the server. */ virtual void bindSuccessful(uint16_t /*port*/) {} }; /** * ServerThread starts a thrift server running in a separate thread. */ class ServerThread { public: ServerThread(const std::shared_ptr& state, bool autoStart) : port_(0), running_(false), serving_(false), error_(false), serverState_(state) { if (autoStart) { start(); } } void start(); void stop(); uint16_t getPort() const { return port_; } ~ServerThread() { if (running_) { try { stop(); } catch (...) { GlobalOutput.printf("error shutting down server"); } } } protected: // Annoying. thrift forces us to use shared_ptr, so we have to use // a helper class that we can allocate on the heap and give to thrift. // It would be simpler if we could just make Runnable and TServerEventHandler // private base classes of ServerThread. class Helper : public concurrency::Runnable, public server::TServerEventHandler { public: Helper(ServerThread* serverThread) : serverThread_(serverThread) {} void run() override { serverThread_->run(); } void preServe() override { serverThread_->preServe(); } private: ServerThread* serverThread_; }; void run(); void preServe(); std::shared_ptr helper_; uint16_t port_; bool running_; bool serving_; bool error_; concurrency::Monitor serverMonitor_; std::shared_ptr serverState_; std::shared_ptr server_; std::shared_ptr thread_; }; } } } // apache::thrift::test #endif // _THRIFT_TEST_SERVERTHREAD_H_ thrift-0.19.0/lib/cpp/test/processor/EventLog.h0000644000000000000000000000567214303740367021342 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_EVENTLOG_H_ #define _THRIFT_TEST_EVENTLOG_H_ 1 #include namespace apache { namespace thrift { namespace test { // Initially I made EventType an enum, but using char* results // in much more readable error messages when there is a mismatch. // It also lets users of EventLog easily define their own new types. // Comparing the literal pointer values should be safe, barring any strange // linking setup that results in duplicate symbols. typedef const char* EventType; struct Event { Event(EventType type, uint32_t connectionId, uint32_t callId, const std::string& message) : type(type), connectionId(connectionId), callId(callId), message(message) {} EventType type; uint32_t connectionId; uint32_t callId; std::string message; }; class EventLog { public: static EventType ET_LOG_END; static EventType ET_CONN_CREATED; static EventType ET_CONN_DESTROYED; static EventType ET_CALL_STARTED; static EventType ET_CALL_FINISHED; static EventType ET_PROCESS; static EventType ET_PRE_READ; static EventType ET_POST_READ; static EventType ET_PRE_WRITE; static EventType ET_POST_WRITE; static EventType ET_ASYNC_COMPLETE; static EventType ET_HANDLER_ERROR; static EventType ET_CALL_INCREMENT_GENERATION; static EventType ET_CALL_GET_GENERATION; static EventType ET_CALL_ADD_STRING; static EventType ET_CALL_GET_STRINGS; static EventType ET_CALL_GET_DATA_WAIT; static EventType ET_CALL_ONEWAY_WAIT; static EventType ET_CALL_UNEXPECTED_EXCEPTION_WAIT; static EventType ET_CALL_EXCEPTION_WAIT; static EventType ET_WAIT_RETURN; static EventType ET_CALL_SET_VALUE; static EventType ET_CALL_GET_VALUE; EventLog(); void append(EventType type, uint32_t connectionId, uint32_t callId, const std::string& message = ""); Event waitForEvent(int64_t timeout = 500); Event waitForConnEvent(uint32_t connId, int64_t timeout = 500); protected: typedef std::list EventList; concurrency::Monitor monitor_; EventList events_; uint32_t id_; static uint32_t nextId_; }; } } } // apache::thrift::test #endif // _THRIFT_TEST_EVENTLOG_H_ thrift-0.19.0/lib/cpp/test/processor/ServerThread.cpp0000644000000000000000000001135014303740367022536 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _THRIFT_TEST_SERVERTHREAD_TCC_ #define _THRIFT_TEST_SERVERTHREAD_TCC_ 1 #include "ServerThread.h" #include #include #include #include #include namespace apache { namespace thrift { namespace test { void ServerThread::start() { assert(!running_); running_ = true; helper_.reset(new Helper(this)); // Start the other thread concurrency::ThreadFactory threadFactory; threadFactory.setDetached(false); thread_ = threadFactory.newThread(helper_); thread_->start(); // Wait on the other thread to tell us that it has successfully // bound to the port and started listening (or until an error occurs). concurrency::Synchronized s(serverMonitor_); while (!serving_ && !error_) { serverMonitor_.waitForever(); } if (error_) { throw transport::TTransportException(transport::TTransportException::NOT_OPEN, "failed to bind on server socket"); } } void ServerThread::stop() { if (!running_) { return; } // Tell the server to stop server_->stop(); running_ = false; // Wait for the server thread to exit // // Note: this only works if all client connections have closed. The servers // generally wait for everything to be closed before exiting; there currently // isn't a way to tell them to just exit now, and shut down existing // connections. thread_->join(); } void ServerThread::run() { /* * Try binding to several ports, in case the one we want is already in use. */ port_ = 12345; unsigned int maxRetries = 10; for (unsigned int n = 0; n < maxRetries; ++n) { // Create the server server_ = serverState_->createServer(port_); // Install our helper as the server event handler, so that our // preServe() method will be called once we've successfully bound to // the port and are about to start listening. server_->setServerEventHandler(helper_); try { // Try to serve requests server_->serve(); } catch (const TException&) { // TNonblockingServer throws a generic TException if it fails to bind. // If we get a TException, we'll optimistically assume the bind failed. ++port_; continue; } // Seriously? serve() is pretty lame. If it fails to start serving it // just returns rather than throwing an exception. // // We have to use our preServe() hook to tell if serve() successfully // started serving and is returning because stop() is called, or if it just // failed to start serving in the first place. concurrency::Synchronized s(serverMonitor_); if (serving_) { // Oh good, we started serving and are exiting because // we're trying to stop. serving_ = false; return; } else { // We never started serving, probably because we failed to bind to the // port. Increment the port number and try again. ++port_; continue; } } // We failed to bind on any port. concurrency::Synchronized s(serverMonitor_); error_ = true; serverMonitor_.notify(); } void ServerThread::preServe() { // We bound to the port successfully, and are about to start serving requests serverState_->bindSuccessful(port_); // Set the real server event handler (replacing ourself) std::shared_ptr serverEventHandler = serverState_->getServerEventHandler(); server_->setServerEventHandler(serverEventHandler); // Notify the main thread that we have successfully started serving requests concurrency::Synchronized s(serverMonitor_); serving_ = true; serverMonitor_.notify(); // Invoke preServe() on the real event handler, since we ate // the original preServe() event. if (serverEventHandler) { serverEventHandler->preServe(); } } } } } // apache::thrift::test #endif // _THRIFT_TEST_SERVERTHREAD_TCC_ thrift-0.19.0/lib/cpp/test/processor/EventLog.cpp0000644000000000000000000000701514303740367021666 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "EventLog.h" #include #include using namespace apache::thrift::concurrency; namespace { // Define environment variable DEBUG_EVENTLOG to enable debug logging // ex: $ DEBUG_EVENTLOG=1 processor_test static const char * DEBUG_EVENTLOG = getenv("DEBUG_EVENTLOG"); void debug(const char* fmt, ...) { if (DEBUG_EVENTLOG) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); } } } namespace apache { namespace thrift { namespace test { uint32_t EventLog::nextId_ = 0; #define EVENT_TYPE(value) EventType EventLog::value = #value EVENT_TYPE(ET_LOG_END); EVENT_TYPE(ET_CONN_CREATED); EVENT_TYPE(ET_CONN_DESTROYED); EVENT_TYPE(ET_CALL_STARTED); EVENT_TYPE(ET_CALL_FINISHED); EVENT_TYPE(ET_PROCESS); EVENT_TYPE(ET_PRE_READ); EVENT_TYPE(ET_POST_READ); EVENT_TYPE(ET_PRE_WRITE); EVENT_TYPE(ET_POST_WRITE); EVENT_TYPE(ET_ASYNC_COMPLETE); EVENT_TYPE(ET_HANDLER_ERROR); EVENT_TYPE(ET_CALL_INCREMENT_GENERATION); EVENT_TYPE(ET_CALL_GET_GENERATION); EVENT_TYPE(ET_CALL_ADD_STRING); EVENT_TYPE(ET_CALL_GET_STRINGS); EVENT_TYPE(ET_CALL_GET_DATA_WAIT); EVENT_TYPE(ET_CALL_ONEWAY_WAIT); EVENT_TYPE(ET_CALL_EXCEPTION_WAIT); EVENT_TYPE(ET_CALL_UNEXPECTED_EXCEPTION_WAIT); EVENT_TYPE(ET_CALL_SET_VALUE); EVENT_TYPE(ET_CALL_GET_VALUE); EVENT_TYPE(ET_WAIT_RETURN); EventLog::EventLog() { id_ = nextId_++; debug("New log: %d", id_); } void EventLog::append(EventType type, uint32_t connectionId, uint32_t callId, const std::string& message) { Synchronized s(monitor_); debug("%d <-- %u, %u, %s \"%s\"", id_, connectionId, callId, type, message.c_str()); Event e(type, connectionId, callId, message); events_.push_back(e); monitor_.notify(); } Event EventLog::waitForEvent(int64_t timeout) { Synchronized s(monitor_); try { while (events_.empty()) { monitor_.wait(timeout); } } catch (const TimedOutException &) { return Event(ET_LOG_END, 0, 0, ""); } Event event = events_.front(); events_.pop_front(); return event; } Event EventLog::waitForConnEvent(uint32_t connId, int64_t timeout) { Synchronized s(monitor_); auto it = events_.begin(); while (true) { try { // TODO: it would be nicer to honor timeout for the duration of this // call, rather than restarting it for each call to wait(). It shouldn't // be a big problem in practice, though. while (it == events_.end()) { monitor_.wait(timeout); } } catch (const TimedOutException &) { return Event(ET_LOG_END, 0, 0, ""); } if (it->connectionId == connId) { Event event = *it; events_.erase(it); return event; } } } } } } // apache::thrift::test thrift-0.19.0/lib/cpp/test/Makefile.in0000644000000000000000000017232114472652515017474 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ noinst_PROGRAMS = Benchmark$(EXEEXT) concurrency_test$(EXEEXT) \ $(am__EXEEXT_2) check_PROGRAMS = UnitTests$(EXEEXT) TFDTransportTest$(EXEEXT) \ TPipedTransportTest$(EXEEXT) DebugProtoTest$(EXEEXT) \ JSONProtoTest$(EXEEXT) OptionalRequiredTest$(EXEEXT) \ RecursiveTest$(EXEEXT) SpecializationTest$(EXEEXT) \ AllProtocolsTest$(EXEEXT) TransportTest$(EXEEXT) \ TInterruptTest$(EXEEXT) TServerIntegrationTest$(EXEEXT) \ SecurityTest$(EXEEXT) SecurityFromBufferTest$(EXEEXT) \ ZlibTest$(EXEEXT) TFileTransportTest$(EXEEXT) \ link_test$(EXEEXT) OpenSSLManualInitTest$(EXEEXT) \ EnumTest$(EXEEXT) RenderedDoubleConstantsTest$(EXEEXT) \ AnnotationTest$(EXEEXT) $(am__EXEEXT_1) @AMX_HAVE_LIBEVENT_TRUE@am__append_1 = \ @AMX_HAVE_LIBEVENT_TRUE@ processor_test @AMX_HAVE_LIBEVENT_TRUE@am__append_2 = \ @AMX_HAVE_LIBEVENT_TRUE@ TNonblockingServerTest \ @AMX_HAVE_LIBEVENT_TRUE@ TNonblockingSSLServerTest subdir = lib/cpp/test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libprocessortest_la_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp nodist_libprocessortest_la_OBJECTS = gen-cpp/ChildService.lo \ gen-cpp/EmptyService.lo gen-cpp/ParentService.lo \ gen-cpp/proc_types.lo libprocessortest_la_OBJECTS = $(nodist_libprocessortest_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libtestgencpp_la_DEPENDENCIES = $(top_builddir)/lib/cpp/libthrift.la nodist_libtestgencpp_la_OBJECTS = gen-cpp/AnnotationTest_types.lo \ gen-cpp/DebugProtoTest_types.lo \ gen-cpp/DoubleConstantsTest_constants.lo \ gen-cpp/EnumTest_types.lo \ gen-cpp/OptionalRequiredTest_types.lo \ gen-cpp/Recursive_types.lo gen-cpp/ThriftTest_types.lo \ gen-cpp/ThriftTest_constants.lo gen-cpp/TypedefTest_types.lo \ gen-cpp/OneWayService.lo ThriftTest_extras.lo \ DebugProtoTest_extras.lo libtestgencpp_la_OBJECTS = $(nodist_libtestgencpp_la_OBJECTS) @AMX_HAVE_LIBEVENT_TRUE@am__EXEEXT_1 = \ @AMX_HAVE_LIBEVENT_TRUE@ TNonblockingServerTest$(EXEEXT) \ @AMX_HAVE_LIBEVENT_TRUE@ TNonblockingSSLServerTest$(EXEEXT) @AMX_HAVE_LIBEVENT_TRUE@am__EXEEXT_2 = processor_test$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_AllProtocolsTest_OBJECTS = AllProtocolTests.$(OBJEXT) AllProtocolsTest_OBJECTS = $(am_AllProtocolsTest_OBJECTS) am__DEPENDENCIES_1 = AllProtocolsTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) am_AnnotationTest_OBJECTS = AnnotationTest.$(OBJEXT) AnnotationTest_OBJECTS = $(am_AnnotationTest_OBJECTS) AnnotationTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) am_Benchmark_OBJECTS = Benchmark.$(OBJEXT) Benchmark_OBJECTS = $(am_Benchmark_OBJECTS) Benchmark_DEPENDENCIES = libtestgencpp.la am_DebugProtoTest_OBJECTS = DebugProtoTest.$(OBJEXT) DebugProtoTest_OBJECTS = $(am_DebugProtoTest_OBJECTS) DebugProtoTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) am_EnumTest_OBJECTS = EnumTest.$(OBJEXT) EnumTest_OBJECTS = $(am_EnumTest_OBJECTS) EnumTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) am_JSONProtoTest_OBJECTS = JSONProtoTest.$(OBJEXT) JSONProtoTest_OBJECTS = $(am_JSONProtoTest_OBJECTS) JSONProtoTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) am_OpenSSLManualInitTest_OBJECTS = OpenSSLManualInitTest.$(OBJEXT) OpenSSLManualInitTest_OBJECTS = $(am_OpenSSLManualInitTest_OBJECTS) OpenSSLManualInitTest_DEPENDENCIES = \ $(top_builddir)/lib/cpp/libthrift.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_OptionalRequiredTest_OBJECTS = OptionalRequiredTest.$(OBJEXT) OptionalRequiredTest_OBJECTS = $(am_OptionalRequiredTest_OBJECTS) OptionalRequiredTest_DEPENDENCIES = libtestgencpp.la \ $(am__DEPENDENCIES_1) am_RecursiveTest_OBJECTS = RecursiveTest.$(OBJEXT) RecursiveTest_OBJECTS = $(am_RecursiveTest_OBJECTS) RecursiveTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) am_RenderedDoubleConstantsTest_OBJECTS = \ RenderedDoubleConstantsTest.$(OBJEXT) RenderedDoubleConstantsTest_OBJECTS = \ $(am_RenderedDoubleConstantsTest_OBJECTS) RenderedDoubleConstantsTest_DEPENDENCIES = libtestgencpp.la \ $(am__DEPENDENCIES_1) am_SecurityFromBufferTest_OBJECTS = SecurityFromBufferTest.$(OBJEXT) SecurityFromBufferTest_OBJECTS = $(am_SecurityFromBufferTest_OBJECTS) SecurityFromBufferTest_DEPENDENCIES = libtestgencpp.la \ libprocessortest.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_SecurityTest_OBJECTS = SecurityTest.$(OBJEXT) SecurityTest_OBJECTS = $(am_SecurityTest_OBJECTS) SecurityTest_DEPENDENCIES = libtestgencpp.la libprocessortest.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_SpecializationTest_OBJECTS = SpecializationTest.$(OBJEXT) SpecializationTest_OBJECTS = $(am_SpecializationTest_OBJECTS) SpecializationTest_DEPENDENCIES = libtestgencpp.la \ $(am__DEPENDENCIES_1) am_TFDTransportTest_OBJECTS = TFDTransportTest.$(OBJEXT) TFDTransportTest_OBJECTS = $(am_TFDTransportTest_OBJECTS) TFDTransportTest_DEPENDENCIES = $(top_builddir)/lib/cpp/libthrift.la \ $(am__DEPENDENCIES_1) am_TFileTransportTest_OBJECTS = TFileTransportTest.$(OBJEXT) TFileTransportTest_OBJECTS = $(am_TFileTransportTest_OBJECTS) TFileTransportTest_DEPENDENCIES = libtestgencpp.la \ $(am__DEPENDENCIES_1) am_TInterruptTest_OBJECTS = TSocketInterruptTest.$(OBJEXT) \ TSSLSocketInterruptTest.$(OBJEXT) TInterruptTest_OBJECTS = $(am_TInterruptTest_OBJECTS) TInterruptTest_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_TNonblockingSSLServerTest_OBJECTS = \ TNonblockingSSLServerTest.$(OBJEXT) TNonblockingSSLServerTest_OBJECTS = \ $(am_TNonblockingSSLServerTest_OBJECTS) TNonblockingSSLServerTest_DEPENDENCIES = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_TNonblockingServerTest_OBJECTS = TNonblockingServerTest.$(OBJEXT) TNonblockingServerTest_OBJECTS = $(am_TNonblockingServerTest_OBJECTS) TNonblockingServerTest_DEPENDENCIES = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_TPipedTransportTest_OBJECTS = TPipedTransportTest.$(OBJEXT) \ TPipeInterruptTest.$(OBJEXT) TPipedTransportTest_OBJECTS = $(am_TPipedTransportTest_OBJECTS) TPipedTransportTest_DEPENDENCIES = libtestgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_TServerIntegrationTest_OBJECTS = TServerIntegrationTest.$(OBJEXT) TServerIntegrationTest_OBJECTS = $(am_TServerIntegrationTest_OBJECTS) TServerIntegrationTest_DEPENDENCIES = libtestgencpp.la \ libprocessortest.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_TransportTest_OBJECTS = TransportTest.$(OBJEXT) TransportTest_OBJECTS = $(am_TransportTest_OBJECTS) TransportTest_DEPENDENCIES = libtestgencpp.la \ $(top_builddir)/lib/cpp/libthriftz.la $(am__DEPENDENCIES_1) am_UnitTests_OBJECTS = UnitTestMain.$(OBJEXT) OneWayHTTPTest.$(OBJEXT) \ TMemoryBufferTest.$(OBJEXT) TBufferBaseTest.$(OBJEXT) \ Base64Test.$(OBJEXT) ToStringTest.$(OBJEXT) \ TypedefTest.$(OBJEXT) TServerSocketTest.$(OBJEXT) \ TServerTransportTest.$(OBJEXT) ThrifttReadCheckTests.$(OBJEXT) UnitTests_OBJECTS = $(am_UnitTests_OBJECTS) UnitTests_DEPENDENCIES = libtestgencpp.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_ZlibTest_OBJECTS = ZlibTest.$(OBJEXT) ZlibTest_OBJECTS = $(am_ZlibTest_OBJECTS) ZlibTest_DEPENDENCIES = libtestgencpp.la \ $(top_builddir)/lib/cpp/libthriftz.la $(am__DEPENDENCIES_1) am_concurrency_test_OBJECTS = concurrency/Tests.$(OBJEXT) concurrency_test_OBJECTS = $(am_concurrency_test_OBJECTS) concurrency_test_DEPENDENCIES = $(top_builddir)/lib/cpp/libthrift.la am_link_test_OBJECTS = link/LinkTest.$(OBJEXT) \ link/TemplatedService1.$(OBJEXT) \ link/TemplatedService2.$(OBJEXT) link_test_OBJECTS = $(am_link_test_OBJECTS) link_test_LDADD = $(LDADD) am_processor_test_OBJECTS = processor/ProcessorTest.$(OBJEXT) \ processor/EventLog.$(OBJEXT) processor/ServerThread.$(OBJEXT) processor_test_OBJECTS = $(am_processor_test_OBJECTS) processor_test_DEPENDENCIES = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(nodist_libprocessortest_la_SOURCES) \ $(nodist_libtestgencpp_la_SOURCES) $(AllProtocolsTest_SOURCES) \ $(AnnotationTest_SOURCES) $(Benchmark_SOURCES) \ $(DebugProtoTest_SOURCES) $(EnumTest_SOURCES) \ $(JSONProtoTest_SOURCES) $(OpenSSLManualInitTest_SOURCES) \ $(OptionalRequiredTest_SOURCES) $(RecursiveTest_SOURCES) \ $(RenderedDoubleConstantsTest_SOURCES) \ $(SecurityFromBufferTest_SOURCES) $(SecurityTest_SOURCES) \ $(SpecializationTest_SOURCES) $(TFDTransportTest_SOURCES) \ $(TFileTransportTest_SOURCES) $(TInterruptTest_SOURCES) \ $(TNonblockingSSLServerTest_SOURCES) \ $(TNonblockingServerTest_SOURCES) \ $(TPipedTransportTest_SOURCES) \ $(TServerIntegrationTest_SOURCES) $(TransportTest_SOURCES) \ $(UnitTests_SOURCES) $(ZlibTest_SOURCES) \ $(concurrency_test_SOURCES) $(link_test_SOURCES) \ $(processor_test_SOURCES) DIST_SOURCES = $(AllProtocolsTest_SOURCES) $(AnnotationTest_SOURCES) \ $(Benchmark_SOURCES) $(DebugProtoTest_SOURCES) \ $(EnumTest_SOURCES) $(JSONProtoTest_SOURCES) \ $(OpenSSLManualInitTest_SOURCES) \ $(OptionalRequiredTest_SOURCES) $(RecursiveTest_SOURCES) \ $(RenderedDoubleConstantsTest_SOURCES) \ $(SecurityFromBufferTest_SOURCES) $(SecurityTest_SOURCES) \ $(SpecializationTest_SOURCES) $(TFDTransportTest_SOURCES) \ $(TFileTransportTest_SOURCES) $(TInterruptTest_SOURCES) \ $(TNonblockingSSLServerTest_SOURCES) \ $(TNonblockingServerTest_SOURCES) \ $(TPipedTransportTest_SOURCES) \ $(TServerIntegrationTest_SOURCES) $(TransportTest_SOURCES) \ $(UnitTests_SOURCES) $(ZlibTest_SOURCES) \ $(concurrency_test_SOURCES) $(link_test_SOURCES) \ $(processor_test_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/AnnotationTest_types.h \ gen-cpp/DebugProtoTest_types.h \ gen-cpp/EnumTest_types.h \ gen-cpp/OptionalRequiredTest_types.h \ gen-cpp/Recursive_types.h \ gen-cpp/ThriftTest_types.h \ gen-cpp/TypedefTest_types.h \ gen-cpp/ChildService.h \ gen-cpp/EmptyService.h \ gen-cpp/ParentService.h \ gen-cpp/OneWayTest_types.h \ gen-cpp/OneWayService.h \ gen-cpp/proc_types.h noinst_LTLIBRARIES = libtestgencpp.la libprocessortest.la nodist_libtestgencpp_la_SOURCES = \ gen-cpp/AnnotationTest_types.cpp \ gen-cpp/AnnotationTest_types.h \ gen-cpp/DebugProtoTest_types.cpp \ gen-cpp/DebugProtoTest_types.h \ gen-cpp/DoubleConstantsTest_constants.cpp \ gen-cpp/DoubleConstantsTest_constants.h \ gen-cpp/EnumTest_types.cpp \ gen-cpp/EnumTest_types.h \ gen-cpp/OptionalRequiredTest_types.cpp \ gen-cpp/OptionalRequiredTest_types.h \ gen-cpp/Recursive_types.cpp \ gen-cpp/Recursive_types.h \ gen-cpp/ThriftTest_types.cpp \ gen-cpp/ThriftTest_types.h \ gen-cpp/ThriftTest_constants.cpp \ gen-cpp/ThriftTest_constants.h \ gen-cpp/TypedefTest_types.cpp \ gen-cpp/TypedefTest_types.h \ gen-cpp/OneWayService.cpp \ gen-cpp/OneWayTest_types.h \ gen-cpp/OneWayService.h \ ThriftTest_extras.cpp \ DebugProtoTest_extras.cpp nodist_libprocessortest_la_SOURCES = \ gen-cpp/ChildService.cpp \ gen-cpp/ChildService.h \ gen-cpp/EmptyService.cpp \ gen-cpp/EmptyService.h \ gen-cpp/ParentService.cpp \ gen-cpp/ParentService.h \ gen-cpp/proc_types.cpp \ gen-cpp/proc_types.h libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la Benchmark_SOURCES = \ Benchmark.cpp Benchmark_LDADD = libtestgencpp.la TESTS_ENVIRONMENT = \ BOOST_TEST_LOG_SINK=tests.xml \ BOOST_TEST_LOG_LEVEL=test_suite \ BOOST_TEST_LOG_FORMAT=XML TESTS = \ $(check_PROGRAMS) UnitTests_SOURCES = \ UnitTestMain.cpp \ OneWayHTTPTest.cpp \ TMemoryBufferTest.cpp \ TBufferBaseTest.cpp \ Base64Test.cpp \ ToStringTest.cpp \ TypedefTest.cpp \ TServerSocketTest.cpp \ TServerTransportTest.cpp \ TTransportCheckThrow.h \ ThrifttReadCheckTests.cpp UnitTests_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) TInterruptTest_SOURCES = \ TSocketInterruptTest.cpp \ TSSLSocketInterruptTest.cpp TInterruptTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_CHRONO_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) TServerIntegrationTest_SOURCES = \ TServerIntegrationTest.cpp TServerIntegrationTest_LDADD = \ libtestgencpp.la \ libprocessortest.la \ $(BOOST_TEST_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) SecurityTest_SOURCES = \ SecurityTest.cpp SecurityTest_LDADD = \ libtestgencpp.la \ libprocessortest.la \ $(BOOST_TEST_LDADD) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) SecurityFromBufferTest_SOURCES = \ SecurityFromBufferTest.cpp SecurityFromBufferTest_LDADD = \ libtestgencpp.la \ libprocessortest.la \ $(BOOST_TEST_LDADD) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) TransportTest_SOURCES = \ TransportTest.cpp TransportTest_LDADD = \ libtestgencpp.la \ $(top_builddir)/lib/cpp/libthriftz.la \ $(BOOST_TEST_LDADD) \ -lz ZlibTest_SOURCES = \ ZlibTest.cpp ZlibTest_LDADD = \ libtestgencpp.la \ $(top_builddir)/lib/cpp/libthriftz.la \ $(BOOST_TEST_LDADD) \ -lz EnumTest_SOURCES = \ EnumTest.cpp EnumTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) RenderedDoubleConstantsTest_SOURCES = RenderedDoubleConstantsTest.cpp RenderedDoubleConstantsTest_LDADD = libtestgencpp.la $(BOOST_TEST_LDADD) AnnotationTest_SOURCES = \ AnnotationTest.cpp AnnotationTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) TFileTransportTest_SOURCES = \ TFileTransportTest.cpp TFileTransportTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # TFDTransportTest # TFDTransportTest_SOURCES = \ TFDTransportTest.cpp TFDTransportTest_LDADD = \ $(top_builddir)/lib/cpp/libthrift.la \ $(BOOST_TEST_LDADD) # # TPipedTransportTest # TPipedTransportTest_SOURCES = \ TPipedTransportTest.cpp \ TPipeInterruptTest.cpp TPipedTransportTest_LDADD = \ libtestgencpp.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(BOOST_TEST_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) # # AllProtocolsTest # AllProtocolsTest_SOURCES = \ AllProtocolTests.cpp \ AllProtocolTests.tcc \ GenericHelpers.h AllProtocolsTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # DebugProtoTest # DebugProtoTest_SOURCES = \ DebugProtoTest.cpp DebugProtoTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # JSONProtoTest # JSONProtoTest_SOURCES = \ JSONProtoTest.cpp JSONProtoTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # TNonblockingServerTest # TNonblockingServerTest_SOURCES = TNonblockingServerTest.cpp TNonblockingServerTest_LDADD = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la \ $(BOOST_TEST_LDADD) \ $(BOOST_LDFLAGS) \ $(LIBEVENT_LIBS) # # TNonblockingSSLServerTest # TNonblockingSSLServerTest_SOURCES = TNonblockingSSLServerTest.cpp TNonblockingSSLServerTest_LDADD = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la \ $(BOOST_TEST_LDADD) \ $(BOOST_LDFLAGS) \ $(BOOST_FILESYSTEM_LDADD) \ $(BOOST_CHRONO_LDADD) \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) \ $(LIBEVENT_LIBS) # # OptionalRequiredTest # OptionalRequiredTest_SOURCES = \ OptionalRequiredTest.cpp OptionalRequiredTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # OptionalRequiredTest # RecursiveTest_SOURCES = \ RecursiveTest.cpp RecursiveTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) # # SpecializationTest # SpecializationTest_SOURCES = \ SpecializationTest.cpp SpecializationTest_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) concurrency_test_SOURCES = \ concurrency/Tests.cpp \ concurrency/ThreadFactoryTests.h \ concurrency/ThreadManagerTests.h \ concurrency/TimerManagerTests.h concurrency_test_LDADD = \ $(top_builddir)/lib/cpp/libthrift.la link_test_SOURCES = \ link/LinkTest.cpp \ link/TemplatedService1.cpp \ link/TemplatedService2.cpp processor_test_SOURCES = \ processor/ProcessorTest.cpp \ processor/EventLog.cpp \ processor/ServerThread.cpp \ processor/EventLog.h \ processor/Handlers.h \ processor/ServerThread.h processor_test_LDADD = libprocessortest.la \ $(top_builddir)/lib/cpp/libthrift.la \ $(top_builddir)/lib/cpp/libthriftnb.la \ $(BOOST_TEST_LDADD) \ $(BOOST_LDFLAGS) \ $(LIBEVENT_LIBS) OpenSSLManualInitTest_SOURCES = \ OpenSSLManualInitTest.cpp OpenSSLManualInitTest_LDADD = \ $(top_builddir)/lib/cpp/libthrift.la \ $(BOOST_TEST_LDADD) \ $(OPENSSL_LDFLAGS) \ $(OPENSSL_LIBS) AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -I$(top_srcdir)/lib/cpp/src/thrift -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. AM_LDFLAGS = $(BOOST_LDFLAGS) AM_CXXFLAGS = -Wall -Wextra -pedantic EXTRA_DIST = \ concurrency \ processor \ qt \ CMakeLists.txt \ DebugProtoTest_extras.cpp \ ThriftTest_extras.cpp \ OneWayTest.thrift all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/cpp/test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/cpp/test/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLTLIBRARIES: -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) @list='$(noinst_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } gen-cpp/$(am__dirstamp): @$(MKDIR_P) gen-cpp @: > gen-cpp/$(am__dirstamp) gen-cpp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) gen-cpp/$(DEPDIR) @: > gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/ChildService.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/EmptyService.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/ParentService.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/proc_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) libprocessortest.la: $(libprocessortest_la_OBJECTS) $(libprocessortest_la_DEPENDENCIES) $(EXTRA_libprocessortest_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libprocessortest_la_OBJECTS) $(libprocessortest_la_LIBADD) $(LIBS) gen-cpp/AnnotationTest_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/DebugProtoTest_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/DoubleConstantsTest_constants.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/EnumTest_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/OptionalRequiredTest_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/Recursive_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/ThriftTest_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/ThriftTest_constants.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/TypedefTest_types.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) gen-cpp/OneWayService.lo: gen-cpp/$(am__dirstamp) \ gen-cpp/$(DEPDIR)/$(am__dirstamp) libtestgencpp.la: $(libtestgencpp_la_OBJECTS) $(libtestgencpp_la_DEPENDENCIES) $(EXTRA_libtestgencpp_la_DEPENDENCIES) $(AM_V_CXXLD)$(CXXLINK) $(libtestgencpp_la_OBJECTS) $(libtestgencpp_la_LIBADD) $(LIBS) clean-checkPROGRAMS: @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list AllProtocolsTest$(EXEEXT): $(AllProtocolsTest_OBJECTS) $(AllProtocolsTest_DEPENDENCIES) $(EXTRA_AllProtocolsTest_DEPENDENCIES) @rm -f AllProtocolsTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(AllProtocolsTest_OBJECTS) $(AllProtocolsTest_LDADD) $(LIBS) AnnotationTest$(EXEEXT): $(AnnotationTest_OBJECTS) $(AnnotationTest_DEPENDENCIES) $(EXTRA_AnnotationTest_DEPENDENCIES) @rm -f AnnotationTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(AnnotationTest_OBJECTS) $(AnnotationTest_LDADD) $(LIBS) Benchmark$(EXEEXT): $(Benchmark_OBJECTS) $(Benchmark_DEPENDENCIES) $(EXTRA_Benchmark_DEPENDENCIES) @rm -f Benchmark$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(Benchmark_OBJECTS) $(Benchmark_LDADD) $(LIBS) DebugProtoTest$(EXEEXT): $(DebugProtoTest_OBJECTS) $(DebugProtoTest_DEPENDENCIES) $(EXTRA_DebugProtoTest_DEPENDENCIES) @rm -f DebugProtoTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(DebugProtoTest_OBJECTS) $(DebugProtoTest_LDADD) $(LIBS) EnumTest$(EXEEXT): $(EnumTest_OBJECTS) $(EnumTest_DEPENDENCIES) $(EXTRA_EnumTest_DEPENDENCIES) @rm -f EnumTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(EnumTest_OBJECTS) $(EnumTest_LDADD) $(LIBS) JSONProtoTest$(EXEEXT): $(JSONProtoTest_OBJECTS) $(JSONProtoTest_DEPENDENCIES) $(EXTRA_JSONProtoTest_DEPENDENCIES) @rm -f JSONProtoTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(JSONProtoTest_OBJECTS) $(JSONProtoTest_LDADD) $(LIBS) OpenSSLManualInitTest$(EXEEXT): $(OpenSSLManualInitTest_OBJECTS) $(OpenSSLManualInitTest_DEPENDENCIES) $(EXTRA_OpenSSLManualInitTest_DEPENDENCIES) @rm -f OpenSSLManualInitTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(OpenSSLManualInitTest_OBJECTS) $(OpenSSLManualInitTest_LDADD) $(LIBS) OptionalRequiredTest$(EXEEXT): $(OptionalRequiredTest_OBJECTS) $(OptionalRequiredTest_DEPENDENCIES) $(EXTRA_OptionalRequiredTest_DEPENDENCIES) @rm -f OptionalRequiredTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(OptionalRequiredTest_OBJECTS) $(OptionalRequiredTest_LDADD) $(LIBS) RecursiveTest$(EXEEXT): $(RecursiveTest_OBJECTS) $(RecursiveTest_DEPENDENCIES) $(EXTRA_RecursiveTest_DEPENDENCIES) @rm -f RecursiveTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(RecursiveTest_OBJECTS) $(RecursiveTest_LDADD) $(LIBS) RenderedDoubleConstantsTest$(EXEEXT): $(RenderedDoubleConstantsTest_OBJECTS) $(RenderedDoubleConstantsTest_DEPENDENCIES) $(EXTRA_RenderedDoubleConstantsTest_DEPENDENCIES) @rm -f RenderedDoubleConstantsTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(RenderedDoubleConstantsTest_OBJECTS) $(RenderedDoubleConstantsTest_LDADD) $(LIBS) SecurityFromBufferTest$(EXEEXT): $(SecurityFromBufferTest_OBJECTS) $(SecurityFromBufferTest_DEPENDENCIES) $(EXTRA_SecurityFromBufferTest_DEPENDENCIES) @rm -f SecurityFromBufferTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(SecurityFromBufferTest_OBJECTS) $(SecurityFromBufferTest_LDADD) $(LIBS) SecurityTest$(EXEEXT): $(SecurityTest_OBJECTS) $(SecurityTest_DEPENDENCIES) $(EXTRA_SecurityTest_DEPENDENCIES) @rm -f SecurityTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(SecurityTest_OBJECTS) $(SecurityTest_LDADD) $(LIBS) SpecializationTest$(EXEEXT): $(SpecializationTest_OBJECTS) $(SpecializationTest_DEPENDENCIES) $(EXTRA_SpecializationTest_DEPENDENCIES) @rm -f SpecializationTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(SpecializationTest_OBJECTS) $(SpecializationTest_LDADD) $(LIBS) TFDTransportTest$(EXEEXT): $(TFDTransportTest_OBJECTS) $(TFDTransportTest_DEPENDENCIES) $(EXTRA_TFDTransportTest_DEPENDENCIES) @rm -f TFDTransportTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TFDTransportTest_OBJECTS) $(TFDTransportTest_LDADD) $(LIBS) TFileTransportTest$(EXEEXT): $(TFileTransportTest_OBJECTS) $(TFileTransportTest_DEPENDENCIES) $(EXTRA_TFileTransportTest_DEPENDENCIES) @rm -f TFileTransportTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TFileTransportTest_OBJECTS) $(TFileTransportTest_LDADD) $(LIBS) TInterruptTest$(EXEEXT): $(TInterruptTest_OBJECTS) $(TInterruptTest_DEPENDENCIES) $(EXTRA_TInterruptTest_DEPENDENCIES) @rm -f TInterruptTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TInterruptTest_OBJECTS) $(TInterruptTest_LDADD) $(LIBS) TNonblockingSSLServerTest$(EXEEXT): $(TNonblockingSSLServerTest_OBJECTS) $(TNonblockingSSLServerTest_DEPENDENCIES) $(EXTRA_TNonblockingSSLServerTest_DEPENDENCIES) @rm -f TNonblockingSSLServerTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TNonblockingSSLServerTest_OBJECTS) $(TNonblockingSSLServerTest_LDADD) $(LIBS) TNonblockingServerTest$(EXEEXT): $(TNonblockingServerTest_OBJECTS) $(TNonblockingServerTest_DEPENDENCIES) $(EXTRA_TNonblockingServerTest_DEPENDENCIES) @rm -f TNonblockingServerTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TNonblockingServerTest_OBJECTS) $(TNonblockingServerTest_LDADD) $(LIBS) TPipedTransportTest$(EXEEXT): $(TPipedTransportTest_OBJECTS) $(TPipedTransportTest_DEPENDENCIES) $(EXTRA_TPipedTransportTest_DEPENDENCIES) @rm -f TPipedTransportTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TPipedTransportTest_OBJECTS) $(TPipedTransportTest_LDADD) $(LIBS) TServerIntegrationTest$(EXEEXT): $(TServerIntegrationTest_OBJECTS) $(TServerIntegrationTest_DEPENDENCIES) $(EXTRA_TServerIntegrationTest_DEPENDENCIES) @rm -f TServerIntegrationTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TServerIntegrationTest_OBJECTS) $(TServerIntegrationTest_LDADD) $(LIBS) TransportTest$(EXEEXT): $(TransportTest_OBJECTS) $(TransportTest_DEPENDENCIES) $(EXTRA_TransportTest_DEPENDENCIES) @rm -f TransportTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(TransportTest_OBJECTS) $(TransportTest_LDADD) $(LIBS) UnitTests$(EXEEXT): $(UnitTests_OBJECTS) $(UnitTests_DEPENDENCIES) $(EXTRA_UnitTests_DEPENDENCIES) @rm -f UnitTests$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(UnitTests_OBJECTS) $(UnitTests_LDADD) $(LIBS) ZlibTest$(EXEEXT): $(ZlibTest_OBJECTS) $(ZlibTest_DEPENDENCIES) $(EXTRA_ZlibTest_DEPENDENCIES) @rm -f ZlibTest$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(ZlibTest_OBJECTS) $(ZlibTest_LDADD) $(LIBS) concurrency/$(am__dirstamp): @$(MKDIR_P) concurrency @: > concurrency/$(am__dirstamp) concurrency/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) concurrency/$(DEPDIR) @: > concurrency/$(DEPDIR)/$(am__dirstamp) concurrency/Tests.$(OBJEXT): concurrency/$(am__dirstamp) \ concurrency/$(DEPDIR)/$(am__dirstamp) concurrency_test$(EXEEXT): $(concurrency_test_OBJECTS) $(concurrency_test_DEPENDENCIES) $(EXTRA_concurrency_test_DEPENDENCIES) @rm -f concurrency_test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(concurrency_test_OBJECTS) $(concurrency_test_LDADD) $(LIBS) link/$(am__dirstamp): @$(MKDIR_P) link @: > link/$(am__dirstamp) link/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) link/$(DEPDIR) @: > link/$(DEPDIR)/$(am__dirstamp) link/LinkTest.$(OBJEXT): link/$(am__dirstamp) \ link/$(DEPDIR)/$(am__dirstamp) link/TemplatedService1.$(OBJEXT): link/$(am__dirstamp) \ link/$(DEPDIR)/$(am__dirstamp) link/TemplatedService2.$(OBJEXT): link/$(am__dirstamp) \ link/$(DEPDIR)/$(am__dirstamp) link_test$(EXEEXT): $(link_test_OBJECTS) $(link_test_DEPENDENCIES) $(EXTRA_link_test_DEPENDENCIES) @rm -f link_test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(link_test_OBJECTS) $(link_test_LDADD) $(LIBS) processor/$(am__dirstamp): @$(MKDIR_P) processor @: > processor/$(am__dirstamp) processor/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) processor/$(DEPDIR) @: > processor/$(DEPDIR)/$(am__dirstamp) processor/ProcessorTest.$(OBJEXT): processor/$(am__dirstamp) \ processor/$(DEPDIR)/$(am__dirstamp) processor/EventLog.$(OBJEXT): processor/$(am__dirstamp) \ processor/$(DEPDIR)/$(am__dirstamp) processor/ServerThread.$(OBJEXT): processor/$(am__dirstamp) \ processor/$(DEPDIR)/$(am__dirstamp) processor_test$(EXEEXT): $(processor_test_OBJECTS) $(processor_test_DEPENDENCIES) $(EXTRA_processor_test_DEPENDENCIES) @rm -f processor_test$(EXEEXT) $(AM_V_CXXLD)$(CXXLINK) $(processor_test_OBJECTS) $(processor_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f concurrency/*.$(OBJEXT) -rm -f gen-cpp/*.$(OBJEXT) -rm -f gen-cpp/*.lo -rm -f link/*.$(OBJEXT) -rm -f processor/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllProtocolTests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnotationTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64Test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Benchmark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DebugProtoTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DebugProtoTest_extras.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EnumTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/JSONProtoTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OneWayHTTPTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OpenSSLManualInitTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/OptionalRequiredTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RecursiveTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RenderedDoubleConstantsTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SecurityFromBufferTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SecurityTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpecializationTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TBufferBaseTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TFDTransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TFileTransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TMemoryBufferTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TNonblockingSSLServerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TNonblockingServerTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TPipeInterruptTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TPipedTransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TSSLSocketInterruptTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TServerIntegrationTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TServerSocketTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TServerTransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TSocketInterruptTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ThriftTest_extras.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ThrifttReadCheckTests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ToStringTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TransportTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TypedefTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnitTestMain.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ZlibTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@concurrency/$(DEPDIR)/Tests.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/AnnotationTest_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ChildService.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/DebugProtoTest_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/DoubleConstantsTest_constants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/EmptyService.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/EnumTest_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/OneWayService.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/OptionalRequiredTest_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ParentService.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/Recursive_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ThriftTest_constants.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/ThriftTest_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/TypedefTest_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gen-cpp/$(DEPDIR)/proc_types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@link/$(DEPDIR)/LinkTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@link/$(DEPDIR)/TemplatedService1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@link/$(DEPDIR)/TemplatedService2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processor/$(DEPDIR)/EventLog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processor/$(DEPDIR)/ProcessorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@processor/$(DEPDIR)/ServerThread.Po@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf gen-cpp/.libs gen-cpp/_libs style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f concurrency/$(DEPDIR)/$(am__dirstamp) -rm -f concurrency/$(am__dirstamp) -rm -f gen-cpp/$(DEPDIR)/$(am__dirstamp) -rm -f gen-cpp/$(am__dirstamp) -rm -f link/$(DEPDIR)/$(am__dirstamp) -rm -f link/$(am__dirstamp) -rm -f processor/$(DEPDIR)/$(am__dirstamp) -rm -f processor/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) concurrency/$(DEPDIR) gen-cpp/$(DEPDIR) link/$(DEPDIR) processor/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) concurrency/$(DEPDIR) gen-cpp/$(DEPDIR) link/$(DEPDIR) processor/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: style: style-am style-am: style-local uninstall-am: .MAKE: all check check-am install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ clean-checkPROGRAMS clean-generic clean-libtool clean-local \ clean-noinstLTLIBRARIES clean-noinstPROGRAMS cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ style-am style-local tags tags-am uninstall uninstall-am .PRECIOUS: Makefile ThriftTest_extras.o: gen-cpp/ThriftTest_types.h DebugProtoTest_extras.o: gen-cpp/DebugProtoTest_types.h # # Common thrift code generation rules # gen-cpp/AnnotationTest_constants.cpp gen-cpp/AnnotationTest_constants.h gen-cpp/AnnotationTest_types.cpp gen-cpp/AnnotationTest_types.h: $(top_srcdir)/test/AnnotationTest.thrift $(THRIFT) --gen cpp $< gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h: $(top_srcdir)/test/v0.16/DebugProtoTest.thrift $(THRIFT) --gen cpp $< gen-cpp/DoubleConstantsTest_constants.cpp gen-cpp/DoubleConstantsTest_constants.h: $(top_srcdir)/test/DoubleConstantsTest.thrift $(THRIFT) --gen cpp $< gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h: $(top_srcdir)/test/EnumTest.thrift $(THRIFT) --gen cpp $< gen-cpp/TypedefTest_types.cpp gen-cpp/TypedefTest_types.h: $(top_srcdir)/test/TypedefTest.thrift $(THRIFT) --gen cpp $< gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h: $(top_srcdir)/test/OptionalRequiredTest.thrift $(THRIFT) --gen cpp $< gen-cpp/Recursive_types.cpp gen-cpp/Recursive_types.h: $(top_srcdir)/test/Recursive.thrift $(THRIFT) --gen cpp $< gen-cpp/Service.cpp gen-cpp/StressTest_types.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) --gen cpp $< gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h: $(top_srcdir)/test/v0.16/ThriftTest.thrift $(THRIFT) --gen cpp $< gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h: OneWayTest.thrift $(THRIFT) --gen cpp $< gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h: processor/proc.thrift $(THRIFT) --gen cpp:templates,cob_style $< clean-local: $(RM) gen-cpp/* # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/lib/cpp/test/TNonblockingSSLServerTest.cpp0000644000000000000000000002232414303740367023124 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE TNonblockingSSLServerTest #include #include #include #include "thrift/server/TNonblockingServer.h" #include "thrift/transport/TSSLSocket.h" #include "thrift/transport/TNonblockingSSLServerSocket.h" #include "gen-cpp/ParentService.h" #include #ifdef HAVE_SIGNAL_H #include #endif using namespace apache::thrift; using apache::thrift::concurrency::Guard; using apache::thrift::concurrency::Monitor; using apache::thrift::concurrency::Mutex; using apache::thrift::server::TServerEventHandler; using apache::thrift::transport::TSSLSocketFactory; using apache::thrift::transport::TSSLSocket; struct Handler : public test::ParentServiceIf { void addString(const std::string& s) override { strings_.push_back(s); } void getStrings(std::vector& _return) override { _return = strings_; } std::vector strings_; // dummy overrides not used in this test int32_t incrementGeneration() override { return 0; } int32_t getGeneration() override { return 0; } void getDataWait(std::string&, const int32_t) override {} void onewayWait() override {} void exceptionWait(const std::string&) override {} void unexpectedExceptionWait(const std::string&) override {} }; boost::filesystem::path keyDir; boost::filesystem::path certFile(const std::string& filename) { return keyDir / filename; } struct GlobalFixtureSSL { GlobalFixtureSSL() { using namespace boost::unit_test::framework; for (int i = 0; i < master_test_suite().argc; ++i) { BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]); } #ifdef __linux__ // OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has // disconnected can cause a SIGPIPE signal... signal(SIGPIPE, SIG_IGN); #endif TSSLSocketFactory::setManualOpenSSLInitialization(true); apache::thrift::transport::initializeOpenSSL(); keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys"; if (!boost::filesystem::exists(certFile("server.crt"))) { keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]); if (!boost::filesystem::exists(certFile("server.crt"))) { throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s)."); } } } virtual ~GlobalFixtureSSL() { apache::thrift::transport::cleanupOpenSSL(); #ifdef __linux__ signal(SIGPIPE, SIG_DFL); #endif } }; #if (BOOST_VERSION >= 105900) BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL); #else BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL) #endif std::shared_ptr createServerSocketFactory() { std::shared_ptr pServerSocketFactory; pServerSocketFactory.reset(new TSSLSocketFactory()); pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); pServerSocketFactory->loadCertificate(certFile("server.crt").string().c_str()); pServerSocketFactory->loadPrivateKey(certFile("server.key").string().c_str()); pServerSocketFactory->server(true); return pServerSocketFactory; } std::shared_ptr createClientSocketFactory() { std::shared_ptr pClientSocketFactory; pClientSocketFactory.reset(new TSSLSocketFactory()); pClientSocketFactory->authenticate(true); pClientSocketFactory->loadCertificate(certFile("client.crt").string().c_str()); pClientSocketFactory->loadPrivateKey(certFile("client.key").string().c_str()); pClientSocketFactory->loadTrustedCertificates(certFile("CA.pem").string().c_str()); return pClientSocketFactory; } class Fixture { private: struct ListenEventHandler : public TServerEventHandler { public: ListenEventHandler(Mutex* mutex) : listenMonitor_(mutex), ready_(false) {} void preServe() override /* override */ { Guard g(listenMonitor_.mutex()); ready_ = true; listenMonitor_.notify(); } Monitor listenMonitor_; bool ready_; }; struct Runner : public apache::thrift::concurrency::Runnable { int port; std::shared_ptr userEventBase; std::shared_ptr processor; std::shared_ptr server; std::shared_ptr listenHandler; std::shared_ptr pServerSocketFactory; std::shared_ptr socket; Mutex mutex_; Runner():port(0) { listenHandler.reset(new ListenEventHandler(&mutex_)); } void run() override { // When binding to explicit port, allow retrying to workaround bind failures on ports in use int retryCount = port ? 10 : 0; pServerSocketFactory = createServerSocketFactory(); startServer(retryCount); } void readyBarrier() { // block until server is listening and ready to accept connections Guard g(mutex_); while (!listenHandler->ready_) { listenHandler->listenMonitor_.wait(); } } private: void startServer(int retry_count) { try { socket.reset(new transport::TNonblockingSSLServerSocket(port, pServerSocketFactory)); server.reset(new server::TNonblockingServer(processor, socket)); server->setServerEventHandler(listenHandler); server->setNumIOThreads(1); if (userEventBase) { server->registerEvents(userEventBase.get()); } server->serve(); } catch (const transport::TTransportException&) { if (retry_count > 0) { ++port; startServer(retry_count - 1); } else { throw; } } } }; struct EventDeleter { void operator()(event_base* p) { event_base_free(p); } }; protected: Fixture() : processor(new test::ParentServiceProcessor(std::make_shared())) {} ~Fixture() { if (server) { server->stop(); } if (thread) { thread->join(); } } void setEventBase(event_base* user_event_base) { userEventBase_.reset(user_event_base, EventDeleter()); } int startServer(int port) { std::shared_ptr runner(new Runner); runner->port = port; runner->processor = processor; runner->userEventBase = userEventBase_; std::unique_ptr threadFactory( new apache::thrift::concurrency::ThreadFactory(false)); thread = threadFactory->newThread(runner); thread->start(); runner->readyBarrier(); server = runner->server; return runner->port; } bool canCommunicate(int serverPort) { std::shared_ptr pClientSocketFactory = createClientSocketFactory(); std::shared_ptr socket = pClientSocketFactory->createSocket("localhost", serverPort); socket->open(); test::ParentServiceClient client(std::make_shared( std::make_shared(socket))); client.addString("foo"); std::vector strings; client.getStrings(strings); return strings.size() == 1 && !(strings[0].compare("foo")); } private: std::shared_ptr userEventBase_; std::shared_ptr processor; protected: std::shared_ptr server; private: std::shared_ptr thread; }; BOOST_AUTO_TEST_SUITE(TNonblockingSSLServerTest) BOOST_FIXTURE_TEST_CASE(get_specified_port, Fixture) { int specified_port = startServer(12345); BOOST_REQUIRE_GE(specified_port, 12345); BOOST_REQUIRE_EQUAL(server->getListenPort(), specified_port); BOOST_CHECK(canCommunicate(specified_port)); server->stop(); } BOOST_FIXTURE_TEST_CASE(get_assigned_port, Fixture) { int specified_port = startServer(0); BOOST_REQUIRE_EQUAL(specified_port, 0); int assigned_port = server->getListenPort(); BOOST_REQUIRE_NE(assigned_port, 0); BOOST_CHECK(canCommunicate(assigned_port)); server->stop(); } BOOST_FIXTURE_TEST_CASE(provide_event_base, Fixture) { event_base* eb = event_base_new(); setEventBase(eb); startServer(0); // assert that the server works BOOST_CHECK(canCommunicate(server->getListenPort())); #if LIBEVENT_VERSION_NUMBER > 0x02010400 // also assert that the event_base is actually used when it's easy BOOST_CHECK_GT(event_base_get_num_events(eb, EVENT_BASE_COUNT_ADDED), 0); #endif } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/TFileTransportTest.cpp0000644000000000000000000002550014303740367021703 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE // needed for getopt_long #endif #include #ifdef HAVE_SYS_TIME_H #include #endif #include #include #include #ifdef __MINGW32__ #include #include #include #include #include #endif using namespace apache::thrift::transport; /************************************************************************** * Global state **************************************************************************/ static const char* tmp_dir = "/tmp"; class FsyncLog; FsyncLog* fsync_log; /************************************************************************** * Helper code **************************************************************************/ /** * Class to record calls to fsync */ class FsyncLog { public: struct FsyncCall { struct timeval time; int fd; }; typedef std::list CallList; FsyncLog() = default; void fsync(int fd) { (void)fd; FsyncCall call; THRIFT_GETTIMEOFDAY(&call.time, nullptr); calls_.push_back(call); } const CallList* getCalls() const { return &calls_; } private: CallList calls_; }; /** * Helper class to clean up temporary files */ class TempFile { public: TempFile(const char* directory, const char* prefix) { #ifdef __MINGW32__ ((void)directory); size_t path_len = strlen(prefix) + 8; path_ = new char[path_len]; snprintf(path_, path_len, "%sXXXXXX", prefix); if (_mktemp_s(path_,path_len) == 0) { fd_ = open(path_,O_CREAT | O_RDWR | O_BINARY,S_IREAD | S_IWRITE); if (fd_ < 0) { throw apache::thrift::TException("_mktemp_s() failed"); } } else { throw apache::thrift::TException("_mktemp_s() failed"); } #else size_t path_len = strlen(directory) + strlen(prefix) + 8; path_ = new char[path_len]; snprintf(path_, path_len, "%s/%sXXXXXX", directory, prefix); fd_ = mkstemp(path_); if (fd_ < 0) { throw apache::thrift::TException("mkstemp() failed"); } #endif } ~TempFile() { unlink(); close(); } const char* getPath() const { return path_; } int getFD() const { return fd_; } void unlink() { if (path_) { ::unlink(path_); delete[] path_; path_ = nullptr; } } void close() { if (fd_ < 0) { return; } ::close(fd_); fd_ = -1; } private: char* path_; int fd_; }; // Use our own version of fsync() for testing. // This returns immediately, so timing in test_destructor() isn't affected by // waiting on the actual filesystem. extern "C" int fsync(int fd) { if (fsync_log) { fsync_log->fsync(fd); } return 0; } int time_diff(const struct timeval* t1, const struct timeval* t2) { return (t2->tv_usec - t1->tv_usec) + (t2->tv_sec - t1->tv_sec) * 1000000; } /************************************************************************** * Test cases **************************************************************************/ /** * Make sure the TFileTransport destructor exits "quickly". * * Previous versions had a bug causing the writer thread not to exit * right away. * * It's kind of lame that we just check to see how long the destructor takes in * wall-clock time. This could result in false failures on slower systems, or * on heavily loaded machines. */ BOOST_AUTO_TEST_CASE(test_destructor) { TempFile f(tmp_dir, "thrift.TFileTransportTest."); unsigned int const NUM_ITERATIONS = 1000; unsigned int num_over = 0; for (unsigned int n = 0; n < NUM_ITERATIONS; ++n) { BOOST_CHECK_EQUAL(0, ftruncate(f.getFD(), 0)); TFileTransport* transport = new TFileTransport(f.getPath()); // write something so that the writer thread gets started transport->write(reinterpret_cast("foo"), 3); // Every other iteration, also call flush(), just in case that potentially // has any effect on how the writer thread wakes up. if (n & 0x1) { transport->flush(); } /* * Time the call to the destructor */ struct timeval start; struct timeval end; THRIFT_GETTIMEOFDAY(&start, nullptr); delete transport; THRIFT_GETTIMEOFDAY(&end, nullptr); int delta = time_diff(&start, &end); // If any attempt takes more than 500ms, treat that as a failure. // Treat this as a fatal failure, so we'll return now instead of // looping over a very slow operation. BOOST_WARN( delta < 500000 ); // Normally, it takes less than 100ms on my dev box. // However, if the box is heavily loaded, some of the test runs // take longer, since we're just waiting for our turn on the CPU. if (delta > 100000) { ++num_over; } } // Make sure fewer than 10% of the runs took longer than 1000us BOOST_WARN(num_over < (NUM_ITERATIONS / 10)); } /** * Make sure setFlushMaxUs() is honored. */ void test_flush_max_us_impl(uint32_t flush_us, uint32_t write_us, uint32_t test_us) { // TFileTransport only calls fsync() if data has been written, // so make sure the write interval is smaller than the flush interval. BOOST_WARN(write_us < flush_us); TempFile f(tmp_dir, "thrift.TFileTransportTest."); // Record calls to fsync() FsyncLog log; fsync_log = &log; TFileTransport* transport = new TFileTransport(f.getPath()); // Don't flush because of # of bytes written transport->setFlushMaxBytes(0xffffffff); uint8_t buf[] = "a"; uint32_t buflen = sizeof(buf); // Set the flush interval transport->setFlushMaxUs(flush_us); // Make one call to write, to start the writer thread now. // (If we just let the thread get created during our test loop, // the thread creation sometimes takes long enough to make the first // fsync interval fail the check.) transport->write(buf, buflen); // Add one entry to the fsync log, just to mark the start time log.fsync(-1); // Loop doing write(), sleep(), ... uint32_t total_time = 0; while (true) { transport->write(buf, buflen); if (total_time > test_us) { break; } usleep(write_us); total_time += write_us; } delete transport; // Stop logging new fsync() calls fsync_log = nullptr; // Examine the fsync() log // // TFileTransport uses pthread_cond_timedwait(), which only has millisecond // resolution. In my testing, it normally wakes up about 1 millisecond late. // However, sometimes it takes a bit longer. Allow 5ms leeway. int max_allowed_delta = flush_us + 5000; const FsyncLog::CallList* calls = log.getCalls(); // We added 1 fsync call above. // Make sure TFileTransport called fsync at least once BOOST_WARN_GE(calls->size(), static_cast(1)); const struct timeval* prev_time = nullptr; for (const auto & call : *calls) { if (prev_time) { int delta = time_diff(prev_time, &call.time); BOOST_WARN( delta < max_allowed_delta ); } prev_time = &call.time; } } BOOST_AUTO_TEST_CASE(test_flush_max_us1) { // fsync every 10ms, write every 5ms, for 500ms test_flush_max_us_impl(10000, 5000, 500000); } BOOST_AUTO_TEST_CASE(test_flush_max_us2) { // fsync every 50ms, write every 20ms, for 500ms test_flush_max_us_impl(50000, 20000, 500000); } BOOST_AUTO_TEST_CASE(test_flush_max_us3) { // fsync every 400ms, write every 300ms, for 1s test_flush_max_us_impl(400000, 300000, 1000000); } /** * Make sure flush() is fast when there is nothing to do. * * TFileTransport used to have a bug where flush() would wait for the fsync * timeout to expire. */ BOOST_AUTO_TEST_CASE(test_noop_flush) { TempFile f(tmp_dir, "thrift.TFileTransportTest."); TFileTransport transport(f.getPath()); // Write something to start the writer thread. uint8_t buf[] = "a"; transport.write(buf, 1); struct timeval start; THRIFT_GETTIMEOFDAY(&start, nullptr); for (unsigned int n = 0; n < 10; ++n) { transport.flush(); struct timeval now; THRIFT_GETTIMEOFDAY(&now, nullptr); // Fail if at any point we've been running for longer than half a second. // (With the buggy code, TFileTransport used to take 3 seconds per flush()) // // Use a fatal fail so we break out early, rather than continuing to make // many more slow flush() calls. int delta = time_diff(&start, &now); BOOST_WARN( delta < 2000000 ); } } /************************************************************************** * General Initialization **************************************************************************/ void print_usage(FILE* f, const char* argv0) { fprintf(f, "Usage: %s [boost_options] [options]\n", argv0); fprintf(f, "Options:\n"); fprintf(f, " --tmp-dir=DIR, -t DIR\n"); fprintf(f, " --help\n"); } void parse_args(int argc, char* argv[]) { struct option long_opts[] = {{"help", false, nullptr, 'h'}, {"tmp-dir", true, nullptr, 't'}, {nullptr, 0, nullptr, 0}}; while (true) { optopt = 1; int optchar = getopt_long(argc, argv, "ht:", long_opts, nullptr); if (optchar == -1) { break; } switch (optchar) { case 't': tmp_dir = optarg; break; case 'h': print_usage(stdout, argv[0]); exit(0); case '?': exit(1); default: // Only happens if someone adds another option to the optarg string, // but doesn't update the switch statement to handle it. fprintf(stderr, "unknown option \"-%c\"\n", optchar); exit(1); } } } #ifdef BOOST_TEST_DYN_LINK static int myArgc = 0; static char **myArgv = nullptr; bool init_unit_test_suite() { boost::unit_test::framework::master_test_suite().p_name.value = "TFileTransportTest"; // Parse arguments parse_args(myArgc,myArgv); return true; } int main( int argc, char* argv[] ) { myArgc = argc; myArgv = argv; return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv); } #else boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { boost::unit_test::framework::master_test_suite().p_name.value = "TFileTransportTest"; // Parse arguments parse_args(argc, argv); return nullptr; } #endif thrift-0.19.0/lib/cpp/test/OneWayTest.thrift0000644000000000000000000000273114303740367020704 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * Contains some contributions under the Thrift Software License. * Please see doc/old-thrift-license.txt in the Thrift distribution for * details. */ namespace c_glib OneWayTest namespace java onewaytest namespace cpp onewaytest namespace rb Onewaytest namespace perl OneWayTest namespace js OneWayTest namespace st OneWayTest namespace py OneWayTest namespace py.twisted OneWayTest namespace go onewaytest namespace php OneWayTest namespace delphi Onewaytest namespace lua OneWayTest namespace xsd test (uri = 'http://thrift.apache.org/ns/OneWayTest') // a minimal Thrift service, for use in OneWayHTTPTtest.cpp service OneWayService { void roundTripRPC(), oneway void oneWayRPC() } thrift-0.19.0/lib/cpp/test/ThriftTest_extras.cpp0000644000000000000000000000221414303740367021606 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ // Extra functions required for ThriftTest_types to work #include #include "gen-cpp/ThriftTest_types.h" namespace thrift { namespace test { bool Insanity::operator<(thrift::test::Insanity const& other) const { using apache::thrift::ThriftDebugString; return ThriftDebugString(*this) < ThriftDebugString(other); } } } thrift-0.19.0/lib/cpp/test/TServerIntegrationTest.cpp0000644000000000000000000004610214303740367022562 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE TServerIntegrationTest #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gen-cpp/ParentService.h" #include #include using apache::thrift::concurrency::Guard; using apache::thrift::concurrency::Monitor; using apache::thrift::concurrency::Mutex; using apache::thrift::concurrency::Synchronized; using apache::thrift::protocol::TBinaryProtocol; using apache::thrift::protocol::TBinaryProtocolFactory; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; using apache::thrift::server::TServer; using apache::thrift::server::TServerEventHandler; using apache::thrift::server::TSimpleServer; using apache::thrift::server::TThreadPoolServer; using apache::thrift::server::TThreadedServer; using std::dynamic_pointer_cast; using std::make_shared; using std::shared_ptr; using apache::thrift::test::ParentServiceClient; using apache::thrift::test::ParentServiceIf; using apache::thrift::test::ParentServiceIfFactory; using apache::thrift::test::ParentServiceIfSingletonFactory; using apache::thrift::test::ParentServiceProcessor; using apache::thrift::test::ParentServiceProcessorFactory; using apache::thrift::TProcessor; using apache::thrift::TProcessorFactory; using boost::posix_time::milliseconds; /** * preServe runs after listen() is successful, when we can connect */ class TServerReadyEventHandler : public TServerEventHandler, public Monitor { public: TServerReadyEventHandler() : isListening_(false), accepted_(0) {} ~TServerReadyEventHandler() override = default; void preServe() override { Synchronized sync(*this); isListening_ = true; notify(); } void* createContext(shared_ptr input, shared_ptr output) override { Synchronized sync(*this); ++accepted_; notify(); (void)input; (void)output; return nullptr; } bool isListening() const { return isListening_; } uint64_t acceptedCount() const { return accepted_; } private: bool isListening_; uint64_t accepted_; }; /** * Reusing another generated test, just something to serve up */ class ParentHandler : public ParentServiceIf { public: ParentHandler() : generation_(0) {} int32_t incrementGeneration() override { Guard g(mutex_); return ++generation_; } int32_t getGeneration() override { Guard g(mutex_); return generation_; } void addString(const std::string& s) override { Guard g(mutex_); strings_.push_back(s); } void getStrings(std::vector& _return) override { Guard g(mutex_); _return = strings_; } void getDataWait(std::string& _return, const int32_t length) override { THRIFT_UNUSED_VARIABLE(_return); THRIFT_UNUSED_VARIABLE(length); } void onewayWait() override {} void exceptionWait(const std::string& message) override { THRIFT_UNUSED_VARIABLE(message); } void unexpectedExceptionWait(const std::string& message) override { THRIFT_UNUSED_VARIABLE(message); } protected: Mutex mutex_; int32_t generation_; std::vector strings_; }; void autoSocketCloser(TSocket* pSock) { pSock->close(); delete pSock; } template class TServerIntegrationTestFixture { public: TServerIntegrationTestFixture(const shared_ptr& _processorFactory) : pServer(new TServerType(_processorFactory, shared_ptr( new TServerSocket("localhost", 0)), shared_ptr(new TTransportFactory), shared_ptr(new TBinaryProtocolFactory))), pEventHandler(shared_ptr(new TServerReadyEventHandler)), bStressDone(false), bStressConnectionCount(0), bStressRequestCount(0) { pServer->setServerEventHandler(pEventHandler); } TServerIntegrationTestFixture(const shared_ptr& _processor) : pServer( new TServerType(_processor, shared_ptr(new TServerSocket("localhost", 0)), shared_ptr(new TTransportFactory), shared_ptr(new TBinaryProtocolFactory))), pEventHandler(shared_ptr(new TServerReadyEventHandler)), bStressDone(false), bStressConnectionCount(0), bStressRequestCount(0) { pServer->setServerEventHandler(pEventHandler); } void startServer() { pServerThread.reset(new boost::thread(std::bind(&TServerType::serve, pServer.get()))); // block until listen() completes so clients will be able to connect Synchronized sync(*(pEventHandler.get())); while (!pEventHandler->isListening()) { pEventHandler->wait(); } BOOST_TEST_MESSAGE(" server is listening"); } void blockUntilAccepted(uint64_t numAccepted) { Synchronized sync(*(pEventHandler.get())); while (pEventHandler->acceptedCount() < numAccepted) { pEventHandler->wait(); } BOOST_TEST_MESSAGE(boost::format(" server has accepted %1%") % numAccepted); } void stopServer() { if (pServerThread) { pServer->stop(); BOOST_TEST_MESSAGE(" server stop completed"); pServerThread->join(); BOOST_TEST_MESSAGE(" server thread joined"); pServerThread.reset(); } } ~TServerIntegrationTestFixture() { stopServer(); } /** * Performs a baseline test where some clients are opened and issue a single operation * and then disconnect at different intervals. * \param[in] numToMake the number of concurrent clients * \param[in] expectedHWM the high water mark we expect of concurrency * \param[in] purpose a description of the test for logging purposes */ void baseline(int64_t numToMake, int64_t expectedHWM, const std::string& purpose) { BOOST_TEST_MESSAGE(boost::format("Testing %1%: %2% with %3% clients, expect %4% HWM") % typeid(TServerType).name() % purpose % numToMake % expectedHWM); startServer(); std::vector > holdSockets; std::vector > holdThreads; for (int64_t i = 0; i < numToMake; ++i) { shared_ptr pClientSock(new TSocket("localhost", getServerPort()), autoSocketCloser); holdSockets.push_back(pClientSock); shared_ptr pClientProtocol(new TBinaryProtocol(pClientSock)); ParentServiceClient client(pClientProtocol); pClientSock->open(); client.incrementGeneration(); holdThreads.push_back(shared_ptr( new boost::thread(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock, milliseconds(10 * numToMake))))); } BOOST_CHECK_EQUAL(expectedHWM, pServer->getConcurrentClientCountHWM()); BOOST_FOREACH (shared_ptr pThread, holdThreads) { pThread->join(); } holdThreads.clear(); holdSockets.clear(); stopServer(); } /** * Helper method used to close a connection after a delay. * \param[in] toClose the connection to close * \param[in] after the delay to impose */ void delayClose(shared_ptr toClose, boost::posix_time::time_duration after) { boost::this_thread::sleep(after); toClose->close(); } /** * \returns the server port number */ int getServerPort() { auto* pSock = dynamic_cast(pServer->getServerTransport().get()); if (!pSock) { throw std::logic_error("how come?"); } return pSock->getPort(); } /** * Performs a stress test by spawning threads that connect, do a number of operations * and disconnect, then a random delay, then do it over again. This is done for a fixed * period of time to test for concurrency correctness. * \param[in] numToMake the number of concurrent clients */ void stress(int64_t numToMake, const boost::posix_time::time_duration& duration) { BOOST_TEST_MESSAGE(boost::format("Stress testing %1% with %2% clients for %3% seconds") % typeid(TServerType).name() % numToMake % duration.total_seconds()); startServer(); std::vector > holdThreads; for (int64_t i = 0; i < numToMake; ++i) { holdThreads.push_back(shared_ptr( new boost::thread(std::bind(&TServerIntegrationTestFixture::stressor, this)))); } boost::this_thread::sleep(duration); bStressDone = true; BOOST_TEST_MESSAGE(boost::format(" serviced %1% connections (HWM %2%) totaling %3% requests") % bStressConnectionCount % pServer->getConcurrentClientCountHWM() % bStressRequestCount); BOOST_FOREACH (shared_ptr pThread, holdThreads) { pThread->join(); } holdThreads.clear(); BOOST_CHECK(bStressRequestCount > 0); stopServer(); } /** * Helper method to stress the system */ void stressor() { while (!bStressDone) { shared_ptr pSocket(new TSocket("localhost", getServerPort()), autoSocketCloser); shared_ptr pProtocol(new TBinaryProtocol(pSocket)); ParentServiceClient client(pProtocol); pSocket->open(); bStressConnectionCount.fetch_add(1, std::memory_order_relaxed); for (int i = 0; i < rand() % 1000; ++i) { client.incrementGeneration(); bStressRequestCount.fetch_add(1, std::memory_order_relaxed); } } } shared_ptr pServer; shared_ptr pEventHandler; shared_ptr pServerThread; std::atomic bStressDone; std::atomic bStressConnectionCount; std::atomic bStressRequestCount; }; template class TServerIntegrationProcessorFactoryTestFixture : public TServerIntegrationTestFixture { public: TServerIntegrationProcessorFactoryTestFixture() : TServerIntegrationTestFixture(make_shared( make_shared( make_shared()))) {} }; template class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture { public: TServerIntegrationProcessorTestFixture() : TServerIntegrationTestFixture( make_shared(make_shared())) {} }; BOOST_AUTO_TEST_SUITE(constructors) BOOST_FIXTURE_TEST_CASE(test_simple_factory, TServerIntegrationProcessorFactoryTestFixture) { baseline(3, 1, "factory"); } BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture) { baseline(3, 1, "processor"); } BOOST_FIXTURE_TEST_CASE(test_threaded_factory, TServerIntegrationProcessorFactoryTestFixture) { baseline(10, 10, "factory"); } BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture) { baseline(10, 10, "processor"); } BOOST_FIXTURE_TEST_CASE(test_threaded_bound, TServerIntegrationProcessorTestFixture) { pServer->setConcurrentClientLimit(4); baseline(10, 4, "limit by server framework"); } BOOST_FIXTURE_TEST_CASE(test_threaded_stress, TServerIntegrationProcessorFactoryTestFixture) { stress(10, boost::posix_time::seconds(3)); } BOOST_FIXTURE_TEST_CASE(test_threadpool_factory, TServerIntegrationProcessorFactoryTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); // thread factory has 4 threads as a default // thread factory however is a bad way to limit concurrent clients // as accept() will be called to grab a 5th client socket, in this case // and then the thread factory will block adding the thread to manage // that client. baseline(10, 5, "limit by thread manager"); } BOOST_FIXTURE_TEST_CASE(test_threadpool, TServerIntegrationProcessorTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); // thread factory has 4 threads as a default // thread factory however is a bad way to limit concurrent clients // as accept() will be called to grab a 5th client socket, in this case // and then the thread factory will block adding the thread to manage // that client. baseline(10, 5, "limit by thread manager"); } BOOST_FIXTURE_TEST_CASE(test_threadpool_bound, TServerIntegrationProcessorTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); pServer->setConcurrentClientLimit(4); baseline(10, 4, "server framework connection limit"); } BOOST_FIXTURE_TEST_CASE(test_threadpool_stress, TServerIntegrationProcessorTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); stress(10, boost::posix_time::seconds(3)); } BOOST_AUTO_TEST_SUITE_END() BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest, TServerIntegrationProcessorTestFixture) BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) { // This tests THRIFT-2441 new behavior: stopping the server disconnects clients BOOST_TEST_MESSAGE("Testing stop with interruptable clients"); startServer(); shared_ptr pClientSock1(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock1->open(); shared_ptr pClientSock2(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock2->open(); // Ensure they have been accepted blockUntilAccepted(2); // The test fixture destructor will force the sockets to disconnect // Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected stopServer(); // extra proof the server end disconnected the clients uint8_t buf[1]; BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected } BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) { // This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients // disconnect. BOOST_TEST_MESSAGE("Testing stop with uninterruptable clients"); dynamic_pointer_cast(pServer->getServerTransport()) ->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior startServer(); shared_ptr pClientSock1(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock1->open(); shared_ptr pClientSock2(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock2->open(); // Ensure they have been accepted blockUntilAccepted(2); boost::thread t1(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock1, milliseconds(250))); boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock2, milliseconds(250))); // Once the clients disconnect the server will stop stopServer(); BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0); t1.join(); t2.join(); } BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) { startServer(); BOOST_TEST_MESSAGE("Testing the concurrent client limit"); BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit()); pServer->setConcurrentClientLimit(2); BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount()); BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit()); shared_ptr pClientSock1(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock1->open(); blockUntilAccepted(1); BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount()); shared_ptr pClientSock2(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock2->open(); blockUntilAccepted(2); BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount()); // a third client cannot connect until one of the other two closes boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock2, milliseconds(250))); shared_ptr pClientSock3(new TSocket("localhost", getServerPort()), autoSocketCloser); pClientSock2->open(); blockUntilAccepted(2); BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount()); BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM()); stopServer(); BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0); t2.join(); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/SecurityTest.cpp0000644000000000000000000002360014452237057020573 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE SecurityTest #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SIGNAL_H #include #endif using apache::thrift::transport::TSSLServerSocket; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TSSLSocket; using apache::thrift::transport::TSSLSocketFactory; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; using std::bind; using std::shared_ptr; boost::filesystem::path keyDir; boost::filesystem::path certFile(const std::string& filename) { return keyDir / filename; } boost::mutex gMutex; struct GlobalFixture { GlobalFixture() { using namespace boost::unit_test::framework; for (int i = 0; i < master_test_suite().argc; ++i) { BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]); } #ifdef __linux__ // OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has // disconnected can cause a SIGPIPE signal... signal(SIGPIPE, SIG_IGN); #endif TSSLSocketFactory::setManualOpenSSLInitialization(true); apache::thrift::transport::initializeOpenSSL(); keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys"; if (!boost::filesystem::exists(certFile("server.crt"))) { keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]); if (!boost::filesystem::exists(certFile("server.crt"))) { throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s)."); } } } virtual ~GlobalFixture() { apache::thrift::transport::cleanupOpenSSL(); #ifdef __linux__ signal(SIGPIPE, SIG_DFL); #endif } }; #if (BOOST_VERSION >= 105900) BOOST_GLOBAL_FIXTURE(GlobalFixture); #else BOOST_GLOBAL_FIXTURE(GlobalFixture) #endif struct SecurityFixture { void server(apache::thrift::transport::SSLProtocol protocol) { try { boost::mutex::scoped_lock lock(mMutex); shared_ptr pServerSocketFactory; shared_ptr pServerSocket; pServerSocketFactory.reset(new TSSLSocketFactory(static_cast(protocol))); pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); pServerSocketFactory->loadCertificate(certFile("server.crt").string().c_str()); pServerSocketFactory->loadPrivateKey(certFile("server.key").string().c_str()); pServerSocketFactory->server(true); pServerSocket.reset(new TSSLServerSocket("localhost", 0, pServerSocketFactory)); shared_ptr connectedClient; try { pServerSocket->listen(); mPort = pServerSocket->getPort(); mCVar.notify_one(); lock.unlock(); connectedClient = pServerSocket->accept(); uint8_t buf[2]; buf[0] = 'O'; buf[1] = 'K'; connectedClient->write(&buf[0], 2); connectedClient->flush(); } catch (apache::thrift::transport::TTransportException& ex) { boost::mutex::scoped_lock lock(gMutex); BOOST_TEST_MESSAGE(boost::format("SRV %1% Exception: %2%") % boost::this_thread::get_id() % ex.what()); } if (connectedClient) { connectedClient->close(); connectedClient.reset(); } pServerSocket->close(); pServerSocket.reset(); } catch (std::exception& ex) { BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); } } void client(apache::thrift::transport::SSLProtocol protocol) { try { shared_ptr pClientSocketFactory; shared_ptr pClientSocket; try { pClientSocketFactory.reset(new TSSLSocketFactory(static_cast(protocol))); pClientSocketFactory->authenticate(true); pClientSocketFactory->loadCertificate(certFile("client.crt").string().c_str()); pClientSocketFactory->loadPrivateKey(certFile("client.key").string().c_str()); pClientSocketFactory->loadTrustedCertificates(certFile("CA.pem").string().c_str()); pClientSocket = pClientSocketFactory->createSocket("localhost", mPort); pClientSocket->open(); uint8_t buf[3]; buf[0] = 0; buf[1] = 0; BOOST_CHECK_EQUAL(2, pClientSocket->read(&buf[0], 2)); BOOST_CHECK_EQUAL(0, memcmp(&buf[0], "OK", 2)); mConnected = true; } catch (apache::thrift::transport::TTransportException& ex) { boost::mutex::scoped_lock lock(gMutex); BOOST_TEST_MESSAGE(boost::format("CLI %1% Exception: %2%") % boost::this_thread::get_id() % ex.what()); } if (pClientSocket) { pClientSocket->close(); pClientSocket.reset(); } } catch (std::exception& ex) { BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); } } static const char *protocol2str(size_t protocol) { static const char *strings[apache::thrift::transport::LATEST + 1] = { "SSLTLS", "SSLv2", "SSLv3", "TLSv1_0", "TLSv1_1", "TLSv1_2" }; return strings[protocol]; } boost::mutex mMutex; boost::condition_variable mCVar; int mPort; bool mConnected; }; BOOST_FIXTURE_TEST_SUITE(BOOST_TEST_MODULE, SecurityFixture) BOOST_AUTO_TEST_CASE(ssl_security_matrix) { try { // matrix of connection success between client and server with different SSLProtocol selections static_assert(apache::thrift::transport::LATEST == 5, "Mismatch in assumed number of ssl protocols"); bool ossl1 = OPENSSL_VERSION_MAJOR == 1; bool matrix[apache::thrift::transport::LATEST + 1][apache::thrift::transport::LATEST + 1] = { // server = SSLTLS SSLv2 SSLv3 TLSv1_0 TLSv1_1 TLSv1_2 // client /* SSLTLS */ { true, false, false, ossl1, ossl1, true }, /* SSLv2 */ { false, false, false, false, false, false }, /* SSLv3 */ { false, false, true, false, false, false }, /* TLSv1_0 */ { ossl1, false, false, ossl1, false, false }, /* TLSv1_1 */ { ossl1, false, false, false, ossl1, false }, /* TLSv1_2 */ { true, false, false, false, false, true } }; for (size_t si = 0; si <= apache::thrift::transport::LATEST; ++si) { for (size_t ci = 0; ci <= apache::thrift::transport::LATEST; ++ci) { if (si == 1 || ci == 1) { // Skip all SSLv2 cases - protocol not supported continue; } #ifdef OPENSSL_NO_SSL3 if (si == 2 || ci == 2) { // Skip all SSLv3 cases - protocol not supported continue; } #endif boost::mutex::scoped_lock lock(mMutex); BOOST_TEST_MESSAGE(boost::format("TEST: Server = %1%, Client = %2%") % protocol2str(si) % protocol2str(ci)); mConnected = false; // thread_group manages the thread lifetime - ignore the return value of create_thread boost::thread_group threads; (void)threads.create_thread(bind(&SecurityFixture::server, this, static_cast(si))); mCVar.wait(lock); // wait for listen() to succeed lock.unlock(); (void)threads.create_thread(bind(&SecurityFixture::client, this, static_cast(ci))); threads.join_all(); BOOST_CHECK_MESSAGE(mConnected == matrix[ci][si], boost::format(" Server = %1%, Client = %2% expected mConnected == %3% but was %4%") % protocol2str(si) % protocol2str(ci) % matrix[ci][si] % mConnected); } } } catch (std::exception& ex) { BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); } } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/JSONProtoTest.cpp0000644000000000000000000003076614303740367020572 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define _USE_MATH_DEFINES #include #include #include #include #include #include #include "gen-cpp/DebugProtoTest_types.h" #define BOOST_TEST_MODULE JSONProtoTest #include using namespace thrift::test::debug; using namespace apache::thrift; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::protocol::TJSONProtocol; static std::shared_ptr ooe; void testCaseSetup_1() { ooe.reset(new OneOfEach); ooe->im_true = true; ooe->im_false = false; ooe->a_bite = 0x7f; ooe->integer16 = 27000; ooe->integer32 = 1 << 24; ooe->integer64 = (uint64_t)6000 * 1000 * 1000; ooe->double_precision = M_PI; ooe->some_characters = "JSON THIS! \"\1"; ooe->zomg_unicode = "\xd7\n\a\t"; ooe->base64 = "\1\2\3\255"; } BOOST_AUTO_TEST_CASE(test_json_proto_1) { testCaseSetup_1(); const std::string expected_result( "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000}," "\"5\":{\"i32\":16777216},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926" "535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001\"},\"9\":{\"str\":\"\xd7\\" "n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"AQIDrQ\"},\"12\":{\"lst\"" ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"); const std::string result(apache::thrift::ThriftJSONString(*ooe)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } static std::shared_ptr n; void testCaseSetup_2() { testCaseSetup_1(); n.reset(new Nesting); n->my_ooe = *ooe; n->my_ooe.integer16 = 16; n->my_ooe.integer32 = 32; n->my_ooe.integer64 = 64; n->my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2; n->my_ooe.some_characters = ":R (me going \"rrrr\")"; n->my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce" "\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0" "\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74" "\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80" "\xbc"; n->my_bonk.type = 31337; n->my_bonk.message = "I am a bonk... xor!"; } BOOST_AUTO_TEST_CASE(test_json_proto_2) { testCaseSetup_2(); const std::string expected_result( "{\"1\":{\"rec\":{\"1\":{\"i32\":31337},\"2\":{\"str\":\"I am a bonk... xor" "!\"}}},\"2\":{\"rec\":{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127" "},\"4\":{\"i16\":16},\"5\":{\"i32\":32},\"6\":{\"i64\":64},\"7\":{\"dbl\":" "1.6180339887498949},\"8\":{\"str\":\":R (me going \\\"rrrr\\\")\"},\"9\":{" "\"str\":\"ӀⅮΠÐοⅿоɡгаÏℎ Αttαⅽκǃ‼\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"" "AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2" ",3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}}}}" ); const std::string result(apache::thrift::ThriftJSONString(*n)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } static std::shared_ptr hm; void testCaseSetup_3() { testCaseSetup_2(); hm.reset(new HolyMoley); hm->big.push_back(*ooe); hm->big.push_back(n->my_ooe); hm->big[0].a_bite = 0x22; hm->big[1].a_bite = 0x33; std::vector stage1; stage1.push_back("and a one"); stage1.push_back("and a two"); hm->contain.insert(stage1); stage1.clear(); stage1.push_back("then a one, two"); stage1.push_back("three!"); stage1.push_back("FOUR!!"); hm->contain.insert(stage1); stage1.clear(); hm->contain.insert(stage1); std::vector stage2; hm->bonks["nothing"] = stage2; stage2.resize(stage2.size() + 1); stage2.back().type = 1; stage2.back().message = "Wait."; stage2.resize(stage2.size() + 1); stage2.back().type = 2; stage2.back().message = "What?"; hm->bonks["something"] = stage2; stage2.clear(); stage2.resize(stage2.size() + 1); stage2.back().type = 3; stage2.back().message = "quoth"; stage2.resize(stage2.size() + 1); stage2.back().type = 4; stage2.back().message = "the raven"; stage2.resize(stage2.size() + 1); stage2.back().type = 5; stage2.back().message = "nevermore"; hm->bonks["poe"] = stage2; } BOOST_AUTO_TEST_CASE(test_json_proto_3) { testCaseSetup_3(); const std::string expected_result( "{\"1\":{\"lst\":[\"rec\",2,{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":" "34},\"4\":{\"i16\":27000},\"5\":{\"i32\":16777216},\"6\":{\"i64\":6000000000" "},\"7\":{\"dbl\":3.1415926535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001" "\"},\"9\":{\"str\":\"\xd7\\n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":" "\"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2" ",3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}},{\"1\":{\"tf\":1},\"2\":{\"tf\":0}," "\"3\":{\"i8\":51},\"4\":{\"i16\":16},\"5\":{\"i32\":32},\"6\":{\"i64\":64}," "\"7\":{\"dbl\":1.6180339887498949},\"8\":{\"str\":\":R (me going \\\"rrrr\\\"" ")\"},\"9\":{\"str\":\"ӀⅮΠÐοⅿоɡгаÏℎ Αttαⅽκǃ‼\"},\"10\":{\"tf\":0},\"11\":{" "\"str\":\"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16" "\",3,1,2,3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}}]},\"2\":{\"set\":[\"lst\",3" ",[\"str\",0],[\"str\",2,\"and a one\",\"and a two\"],[\"str\",3,\"then a one" ", two\",\"three!\",\"FOUR!!\"]]},\"3\":{\"map\":[\"str\",\"lst\",3,{\"nothin" "g\":[\"rec\",0],\"poe\":[\"rec\",3,{\"1\":{\"i32\":3},\"2\":{\"str\":\"quoth" "\"}},{\"1\":{\"i32\":4},\"2\":{\"str\":\"the raven\"}},{\"1\":{\"i32\":5},\"" "2\":{\"str\":\"nevermore\"}}],\"something\":[\"rec\",2,{\"1\":{\"i32\":1},\"" "2\":{\"str\":\"Wait.\"}},{\"1\":{\"i32\":2},\"2\":{\"str\":\"What?\"}}]}]}}" ); const std::string result(apache::thrift::ThriftJSONString(*hm)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); } BOOST_AUTO_TEST_CASE(test_json_proto_4) { testCaseSetup_1(); std::shared_ptr buffer(new TMemoryBuffer()); std::shared_ptr proto(new TJSONProtocol(buffer)); ooe->write(proto.get()); OneOfEach ooe2; ooe2.read(proto.get()); BOOST_CHECK(*ooe == ooe2); } BOOST_AUTO_TEST_CASE(test_json_proto_5) { testCaseSetup_3(); std::shared_ptr buffer(new TMemoryBuffer()); std::shared_ptr proto(new TJSONProtocol(buffer)); hm->write(proto.get()); HolyMoley hm2; hm2.read(proto.get()); BOOST_CHECK(*hm == hm2); hm2.big[0].a_bite = 0x00; BOOST_CHECK(*hm != hm2); } BOOST_AUTO_TEST_CASE(test_json_proto_6) { Doubles dub; dub.nan = HUGE_VAL / HUGE_VAL; dub.inf = HUGE_VAL; dub.neginf = -HUGE_VAL; dub.repeating = 10.0 / 3.0; dub.big = 1E+305; dub.tiny = 1E-305; dub.zero = 0.0; dub.negzero = -0.0; const std::string expected_result( "{\"1\":{\"dbl\":\"NaN\"},\"2\":{\"dbl\":\"Infinity\"},\"3\":{\"dbl\":\"-Infi" "nity\"},\"4\":{\"dbl\":3.3333333333333335},\"5\":{\"dbl\":9.9999999999999994e+" "304},\"6\":{\"dbl\":1e-305},\"7\":{\"dbl\":0},\"8\":{\"dbl\":-0}}" ); std::shared_ptr buffer(new TMemoryBuffer()); std::shared_ptr proto(new TJSONProtocol(buffer)); dub.write(proto.get()); Doubles dub_1; dub_1.read(proto.get()); const std::string result(apache::thrift::ThriftJSONString(dub)); const std::string result_1(apache::thrift::ThriftJSONString(dub_1)); BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); BOOST_CHECK_MESSAGE(!expected_result.compare(result_1), "Expected:\n" << expected_result << "\nGotten:\n" << result_1); } BOOST_AUTO_TEST_CASE(test_json_proto_7) { std::shared_ptr buffer(new TMemoryBuffer()); std::shared_ptr proto(new TJSONProtocol(buffer)); Base64 base; base.a = 123; base.b1 = "1"; base.b2 = "12"; base.b3 = "123"; base.b4 = "1234"; base.b5 = "12345"; base.b6 = "123456"; base.write(proto.get()); Base64 base2; base2.read(proto.get()); BOOST_CHECK(base == base2); } BOOST_AUTO_TEST_CASE(test_json_proto_8) { const char* json_string = "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000}," "\"5\":{\"i32\":16.77216},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926" "535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001\"},\"9\":{\"str\":\"\xd7\\" "n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"AQIDrQ\"},\"12\":{\"lst\"" ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"; const std::size_t bufSiz = strlen(json_string) * sizeof(char); std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), static_cast(bufSiz))); std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; BOOST_CHECK_THROW(ooe2.read(proto.get()), apache::thrift::protocol::TProtocolException); } static std::string toHexSequence(const std::string& str) { std::stringstream ss; ss << std::hex << std::setfill('0'); for (std::size_t i = 0; i < str.size(); i++) { ss << "\\x" << int(uint8_t(str[i])); } return ss.str(); } BOOST_AUTO_TEST_CASE(test_json_unicode_escaped) { const char json_string[] = "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000}," "\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926" "535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\u0e01 \\ud835\\udd3e\"}," "\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\"" ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"; const char* expected_zomg_unicode = "\xe0\xb8\x81 \xf0\x9d\x94\xbe"; std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), sizeof(json_string))); std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; ooe2.read(proto.get()); BOOST_CHECK_MESSAGE(!ooe2.zomg_unicode.compare(expected_zomg_unicode), "Expected:\n" << toHexSequence(expected_zomg_unicode) << "\nGotten:\n" << toHexSequence(ooe2.zomg_unicode)); } BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_low_surrogate) { const char json_string[] = "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000}," "\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926" "535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\ud835\"}," "\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\"" ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"; std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), sizeof(json_string))); std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; BOOST_CHECK_THROW(ooe2.read(proto.get()), apache::thrift::protocol::TProtocolException); } BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_hi_surrogate) { const char json_string[] = "{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000}," "\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926" "535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\udd3e\"}," "\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\"" ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"; std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), sizeof(json_string))); std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; BOOST_CHECK_THROW(ooe2.read(proto.get()), apache::thrift::protocol::TProtocolException); } thrift-0.19.0/lib/cpp/test/TServerTransportTest.cpp0000644000000000000000000000343314303740367022273 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using std::shared_ptr; BOOST_AUTO_TEST_SUITE(TServerTransportTest) class TestTTransport : public TTransport {}; class TestTServerTransport : public TServerTransport { public: TestTServerTransport() : valid_(true) {} void close() override {} bool valid_; protected: shared_ptr acceptImpl() override { return valid_ ? std::make_shared() : shared_ptr(); } }; BOOST_AUTO_TEST_CASE(test_positive_accept) { TestTServerTransport uut; BOOST_CHECK(uut.accept()); } BOOST_AUTO_TEST_CASE(test_negative_accept) { TestTServerTransport uut; uut.valid_ = false; BOOST_CHECK_THROW(uut.accept(), TTransportException); } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/test/TNonblockingServerTest.cpp0000644000000000000000000001466214303740367022550 0ustar00rootroot00000000000000/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #define BOOST_TEST_MODULE TNonblockingServerTest #include #include #include "thrift/concurrency/Monitor.h" #include "thrift/concurrency/Thread.h" #include "thrift/server/TNonblockingServer.h" #include "thrift/transport/TNonblockingServerSocket.h" #include "gen-cpp/ParentService.h" #include using apache::thrift::concurrency::Guard; using apache::thrift::concurrency::Monitor; using apache::thrift::concurrency::Mutex; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::server::TServerEventHandler; using std::make_shared; using std::shared_ptr; using namespace apache::thrift; struct Handler : public test::ParentServiceIf { void addString(const std::string& s) override { strings_.push_back(s); } void getStrings(std::vector& _return) override { _return = strings_; } std::vector strings_; // dummy overrides not used in this test int32_t incrementGeneration() override { return 0; } int32_t getGeneration() override { return 0; } void getDataWait(std::string&, const int32_t) override {} void onewayWait() override {} void exceptionWait(const std::string&) override {} void unexpectedExceptionWait(const std::string&) override {} }; class Fixture { private: struct ListenEventHandler : public TServerEventHandler { public: ListenEventHandler(Mutex* mutex) : listenMonitor_(mutex), ready_(false) {} void preServe() override /* override */ { Guard g(listenMonitor_.mutex()); ready_ = true; listenMonitor_.notify(); } Monitor listenMonitor_; bool ready_; }; struct Runner : public Runnable { int port; shared_ptr userEventBase; shared_ptr processor; shared_ptr server; shared_ptr listenHandler; shared_ptr socket; Mutex mutex_; Runner() { port = 0; listenHandler.reset(new ListenEventHandler(&mutex_)); } void run() override { // When binding to explicit port, allow retrying to workaround bind failures on ports in use int retryCount = port ? 10 : 0; startServer(retryCount); } void readyBarrier() { // block until server is listening and ready to accept connections Guard g(mutex_); while (!listenHandler->ready_) { listenHandler->listenMonitor_.wait(); } } private: void startServer(int retry_count) { try { socket.reset(new transport::TNonblockingServerSocket(port)); server.reset(new server::TNonblockingServer(processor, socket)); server->setServerEventHandler(listenHandler); if (userEventBase) { server->registerEvents(userEventBase.get()); } server->serve(); } catch (const transport::TTransportException&) { if (retry_count > 0) { ++port; startServer(retry_count - 1); } else { throw; } } } }; struct EventDeleter { void operator()(event_base* p) { event_base_free(p); } }; protected: Fixture() : processor(new test::ParentServiceProcessor(make_shared())) {} ~Fixture() { if (server) { server->stop(); } if (thread) { thread->join(); } } void setEventBase(event_base* user_event_base) { userEventBase_.reset(user_event_base, EventDeleter()); } int startServer(int port) { shared_ptr runner(new Runner); runner->port = port; runner->processor = processor; runner->userEventBase = userEventBase_; shared_ptr threadFactory( new ThreadFactory(false)); thread = threadFactory->newThread(runner); thread->start(); runner->readyBarrier(); server = runner->server; return runner->port; } bool canCommunicate(int serverPort) { shared_ptr socket(new transport::TSocket("localhost", serverPort)); socket->open(); test::ParentServiceClient client(make_shared( make_shared(socket))); client.addString("foo"); std::vector strings; client.getStrings(strings); return strings.size() == 1 && !(strings[0].compare("foo")); } private: shared_ptr userEventBase_; shared_ptr processor; protected: shared_ptr server; private: shared_ptr thread; }; BOOST_AUTO_TEST_SUITE(TNonblockingServerTest) BOOST_FIXTURE_TEST_CASE(get_specified_port, Fixture) { int specified_port = startServer(12345); BOOST_REQUIRE_GE(specified_port, 12345); BOOST_REQUIRE_EQUAL(server->getListenPort(), specified_port); BOOST_CHECK(canCommunicate(specified_port)); server->stop(); } BOOST_FIXTURE_TEST_CASE(get_assigned_port, Fixture) { int specified_port = startServer(0); BOOST_REQUIRE_EQUAL(specified_port, 0); int assigned_port = server->getListenPort(); BOOST_REQUIRE_NE(assigned_port, 0); BOOST_CHECK(canCommunicate(assigned_port)); server->stop(); } BOOST_FIXTURE_TEST_CASE(provide_event_base, Fixture) { event_base* eb = event_base_new(); setEventBase(eb); startServer(0); // assert that the server works BOOST_CHECK(canCommunicate(server->getListenPort())); #if LIBEVENT_VERSION_NUMBER > 0x02010400 // also assert that the event_base is actually used when it's easy BOOST_CHECK_GT(event_base_get_num_events(eb, EVENT_BASE_COUNT_ADDED), 0); #endif } BOOST_AUTO_TEST_SUITE_END() thrift-0.19.0/lib/cpp/thrift-z.pc.in0000644000000000000000000000176314303740367017145 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Thrift Description: Thrift Zlib API Version: @VERSION@ Requires: thrift = @VERSION@ Libs: -L${libdir} -lthriftz Cflags: -I${includedir} thrift-0.19.0/lib/cpp/thrift-qt5.pc.in0000644000000000000000000000176414303740367017406 0ustar00rootroot00000000000000# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: Thrift Description: Thrift Qt5 API Version: @VERSION@ Requires: thrift = @VERSION@ Libs: -L${libdir} -lthriftqt5 Cflags: -I${includedir} thrift-0.19.0/lib/cpp/libthrift.vcxproj.filters0000644000000000000000000002223614452237057021520 0ustar00rootroot00000000000000 transport transport windows concurrency concurrency protocol protocol protocol protocol transport transport transport transport transport server server server async async processor transport transport windows windows windows transport transport transport transport protocol concurrency transport transport transport windows transport windows protocol protocol server server server server async async processor processor transport transport transport transport protocol protocol protocol transport windows windows windows windows transport transport {07ced19b-b72a-4105-9ffb-6d2bcf64497e} {e9f61404-1148-4103-bd6f-e5869d37fa79} {2814002a-3c68-427e-b0eb-33acd2f406ae} {addd4707-dbaa-4d0c-bef6-fff8be7b495a} {f55a8e9b-6959-487f-a396-c31b4d6c61d6} {d526885b-1b3e-4ee3-8027-e694fe98ad63} {8f428da8-5a83-44fb-9578-de935fb415e1} {eea10406-3380-4f2d-9365-c26fa2875dae} protocol thrift-0.19.0/lib/cpp/thrift.sln0000644000000000000000000000703714303740367016463 0ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libthriftnb", "libthriftnb.vcxproj", "{D8696CCE-7D46-4659-B432-91754A41DEB0}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libthrift", "libthrift.vcxproj", "{DD26F57E-60F2-4F37-A616-D219A9BF338F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{006984E0-7CC1-47E2-ACD2-A40FE4D38693}" ProjectSection(SolutionItems) = preProject README.md = README.md EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Debug-mt|Win32 = Debug-mt|Win32 Debug-mt|x64 = Debug-mt|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 Release-mt|Win32 = Release-mt|Win32 Release-mt|x64 = Release-mt|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug|Win32.ActiveCfg = Debug|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug|Win32.Build.0 = Debug|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug|x64.ActiveCfg = Debug|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug|x64.Build.0 = Debug|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug-mt|Win32.ActiveCfg = Debug-mt|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug-mt|Win32.Build.0 = Debug-mt|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug-mt|x64.ActiveCfg = Debug-mt|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Debug-mt|x64.Build.0 = Debug-mt|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release|Win32.ActiveCfg = Release|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release|Win32.Build.0 = Release|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release|x64.ActiveCfg = Release|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release|x64.Build.0 = Release|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release-mt|Win32.ActiveCfg = Release-mt|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release-mt|Win32.Build.0 = Release-mt|Win32 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release-mt|x64.ActiveCfg = Release-mt|x64 {D8696CCE-7D46-4659-B432-91754A41DEB0}.Release-mt|x64.Build.0 = Release-mt|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug|Win32.ActiveCfg = Debug|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug|Win32.Build.0 = Debug|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug|x64.ActiveCfg = Debug|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug|x64.Build.0 = Debug|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug-mt|Win32.ActiveCfg = Debug-mt|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug-mt|Win32.Build.0 = Debug-mt|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug-mt|x64.ActiveCfg = Debug-mt|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Debug-mt|x64.Build.0 = Debug-mt|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release|Win32.ActiveCfg = Release|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release|Win32.Build.0 = Release|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release|x64.ActiveCfg = Release|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release|x64.Build.0 = Release|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release-mt|Win32.ActiveCfg = Release-mt|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release-mt|Win32.Build.0 = Release-mt|Win32 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release-mt|x64.ActiveCfg = Release-mt|x64 {DD26F57E-60F2-4F37-A616-D219A9BF338F}.Release-mt|x64.Build.0 = Release-mt|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal thrift-0.19.0/lib/cpp/libthriftnb.vcxproj0000644000000000000000000004105414452237057020370 0ustar00rootroot00000000000000 Debug-mt Win32 Debug-mt x64 Debug Win32 Debug x64 Release-mt Win32 Release-mt x64 Release Win32 Release x64 {D8696CCE-7D46-4659-B432-91754A41DEB0} Win32Proj libthriftnb StaticLibrary true MultiByte v140 StaticLibrary true MultiByte v140 StaticLibrary true MultiByte v140 StaticLibrary true MultiByte v140 StaticLibrary false true MultiByte v140 StaticLibrary false true MultiByte v140 StaticLibrary false true MultiByte v140 StaticLibrary false true MultiByte v140 $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) $(ProjectDir)\src\;$(ProjectDir)\src\thrift\windows\;$(BOOST_ROOT)\include;$(BOOST_ROOT)\;$(LIBEVENT_ROOT)\WIN32-Code\;$(LIBEVENT_ROOT)\include;$(LIBEVENT_ROOT)\;$(IncludePath) Level3 Disabled HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthriftnb.pdb MultiThreadedDebugDll Windows true Level3 Disabled HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;_DEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthriftnb.pdb MultiThreadedDebugDll Windows true Level3 Disabled HAVE_CONFIG_H=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDebugDll Windows true Level3 Disabled HAVE_CONFIG_H=1;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDebugDll Windows true Level3 MaxSpeed true true HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthriftnb.pdb MultiThreadedDll Windows true true true Level3 MaxSpeed true true HAVE_CONFIG_H=1;WIN32;thrift_EXPORTS;NDEBUG;_LIB;%(PreprocessorDefinitions) $(IntDir)libthriftnb.pdb MultiThreadedDll Windows true true true Level3 MaxSpeed true true HAVE_CONFIG_H=1;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDll Windows true true true Level3 MaxSpeed true true HAVE_CONFIG_H=1;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDll Windows true true true thrift-0.19.0/lib/cpp/Makefile.in0000644000000000000000000025024514472652515016517 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_TESTS_TRUE@am__append_1 = test @AMX_HAVE_LIBEVENT_TRUE@am__append_2 = libthriftnb.la @AMX_HAVE_LIBEVENT_TRUE@am__append_3 = thrift-nb.pc @AMX_HAVE_ZLIB_TRUE@am__append_4 = libthriftz.la @AMX_HAVE_ZLIB_TRUE@am__append_5 = thrift-z.pc @AMX_HAVE_QT5_TRUE@am__append_6 = libthriftqt5.la @AMX_HAVE_QT5_TRUE@am__append_7 = thrift-qt5.pc @QT5_REDUCE_RELOCATIONS_TRUE@am__append_8 = -fPIC subdir = lib/cpp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(include_async_HEADERS) \ $(include_concurrency_HEADERS) $(include_processor_HEADERS) \ $(include_protocol_HEADERS) $(include_qt_HEADERS) \ $(include_server_HEADERS) $(include_thrift_HEADERS) \ $(include_transport_HEADERS) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = thrift-nb.pc thrift-z.pc thrift-qt5.pc thrift.pc CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \ "$(DESTDIR)$(include_asyncdir)" \ "$(DESTDIR)$(include_concurrencydir)" \ "$(DESTDIR)$(include_processordir)" \ "$(DESTDIR)$(include_protocoldir)" \ "$(DESTDIR)$(include_qtdir)" "$(DESTDIR)$(include_serverdir)" \ "$(DESTDIR)$(include_thriftdir)" \ "$(DESTDIR)$(include_transportdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libthrift_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__dirstamp = $(am__leading_dot)dirstamp am_libthrift_la_OBJECTS = src/thrift/TApplicationException.lo \ src/thrift/TOutput.lo src/thrift/VirtualProfiling.lo \ src/thrift/async/TAsyncChannel.lo \ src/thrift/async/TAsyncProtocolProcessor.lo \ src/thrift/async/TConcurrentClientSyncInfo.lo \ src/thrift/concurrency/ThreadManager.lo \ src/thrift/concurrency/TimerManager.lo \ src/thrift/processor/PeekProcessor.lo \ src/thrift/protocol/TDebugProtocol.lo \ src/thrift/protocol/TJSONProtocol.lo \ src/thrift/protocol/TBase64Utils.lo \ src/thrift/protocol/TMultiplexedProtocol.lo \ src/thrift/protocol/TProtocol.lo \ src/thrift/transport/TTransportException.lo \ src/thrift/transport/TFDTransport.lo \ src/thrift/transport/TFileTransport.lo \ src/thrift/transport/TSimpleFileTransport.lo \ src/thrift/transport/THttpTransport.lo \ src/thrift/transport/THttpClient.lo \ src/thrift/transport/THttpServer.lo \ src/thrift/transport/TSocket.lo src/thrift/transport/TPipe.lo \ src/thrift/transport/TPipeServer.lo \ src/thrift/transport/TSSLSocket.lo \ src/thrift/transport/TSocketPool.lo \ src/thrift/transport/TServerSocket.lo \ src/thrift/transport/TSSLServerSocket.lo \ src/thrift/transport/TNonblockingServerSocket.lo \ src/thrift/transport/TNonblockingSSLServerSocket.lo \ src/thrift/transport/TTransportUtils.lo \ src/thrift/transport/TBufferTransports.lo \ src/thrift/transport/TWebSocketServer.lo \ src/thrift/transport/SocketCommon.lo \ src/thrift/server/TConnectedClient.lo \ src/thrift/server/TServer.lo \ src/thrift/server/TServerFramework.lo \ src/thrift/server/TSimpleServer.lo \ src/thrift/server/TThreadPoolServer.lo \ src/thrift/server/TThreadedServer.lo \ src/thrift/concurrency/Mutex.lo \ src/thrift/concurrency/ThreadFactory.lo \ src/thrift/concurrency/Thread.lo \ src/thrift/concurrency/Monitor.lo libthrift_la_OBJECTS = $(am_libthrift_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libthrift_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(libthrift_la_LDFLAGS) $(LDFLAGS) -o $@ libthriftnb_la_LIBADD = am_libthriftnb_la_OBJECTS = \ src/thrift/server/libthriftnb_la-TNonblockingServer.lo \ src/thrift/async/libthriftnb_la-TEvhttpServer.lo \ src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo libthriftnb_la_OBJECTS = $(am_libthriftnb_la_OBJECTS) libthriftnb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) \ $(libthriftnb_la_LDFLAGS) $(LDFLAGS) -o $@ @AMX_HAVE_LIBEVENT_TRUE@am_libthriftnb_la_rpath = -rpath $(libdir) libthriftqt5_la_LIBADD = am_libthriftqt5_la_OBJECTS = \ src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo \ src/thrift/qt/libthriftqt5_la-TQTcpServer.lo am__objects_1 = src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo nodist_libthriftqt5_la_OBJECTS = $(am__objects_1) libthriftqt5_la_OBJECTS = $(am_libthriftqt5_la_OBJECTS) \ $(nodist_libthriftqt5_la_OBJECTS) libthriftqt5_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) \ $(libthriftqt5_la_LDFLAGS) $(LDFLAGS) -o $@ @AMX_HAVE_QT5_TRUE@am_libthriftqt5_la_rpath = -rpath $(libdir) libthriftz_la_LIBADD = am_libthriftz_la_OBJECTS = \ src/thrift/transport/libthriftz_la-TZlibTransport.lo \ src/thrift/transport/libthriftz_la-THeaderTransport.lo \ src/thrift/protocol/libthriftz_la-THeaderProtocol.lo libthriftz_la_OBJECTS = $(am_libthriftz_la_OBJECTS) libthriftz_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) $(libthriftz_la_LDFLAGS) \ $(LDFLAGS) -o $@ @AMX_HAVE_ZLIB_TRUE@am_libthriftz_la_rpath = -rpath $(libdir) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CXXFLAGS) $(CXXFLAGS) AM_V_CXX = $(am__v_CXX_@AM_V@) am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) am__v_CXX_0 = @echo " CXX " $@; am__v_CXX_1 = CXXLD = $(CXX) CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = SOURCES = $(libthrift_la_SOURCES) $(libthriftnb_la_SOURCES) \ $(libthriftqt5_la_SOURCES) $(nodist_libthriftqt5_la_SOURCES) \ $(libthriftz_la_SOURCES) DIST_SOURCES = $(libthrift_la_SOURCES) $(libthriftnb_la_SOURCES) \ $(libthriftqt5_la_SOURCES) $(libthriftz_la_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(pkgconfig_DATA) HEADERS = $(include_async_HEADERS) $(include_concurrency_HEADERS) \ $(include_processor_HEADERS) $(include_protocol_HEADERS) \ $(include_qt_HEADERS) $(include_server_HEADERS) \ $(include_thrift_HEADERS) $(include_transport_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . test am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/thrift-nb.pc.in \ $(srcdir)/thrift-qt5.pc.in $(srcdir)/thrift-z.pc.in \ $(srcdir)/thrift.pc.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = subdir-objects nostdinc SUBDIRS = . $(am__append_1) pkgconfigdir = $(libdir)/pkgconfig lib_LTLIBRARIES = libthrift.la $(am__append_2) $(am__append_4) \ $(am__append_6) pkgconfig_DATA = thrift.pc $(am__append_3) $(am__append_5) \ $(am__append_7) libthrift_la_LDFLAGS = -release $(VERSION) libthrift_la_LIBADD = $(BOOST_LDFLAGS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) AM_CXXFLAGS = -Wall -Wextra -pedantic AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(OPENSSL_INCLUDES) -I$(srcdir)/src -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS # Define the source files for the module libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \ src/thrift/TOutput.cpp src/thrift/VirtualProfiling.cpp \ src/thrift/async/TAsyncChannel.cpp \ src/thrift/async/TAsyncProtocolProcessor.cpp \ src/thrift/async/TConcurrentClientSyncInfo.cpp \ src/thrift/concurrency/ThreadManager.cpp \ src/thrift/concurrency/TimerManager.cpp \ src/thrift/processor/PeekProcessor.cpp \ src/thrift/protocol/TDebugProtocol.cpp \ src/thrift/protocol/TJSONProtocol.cpp \ src/thrift/protocol/TBase64Utils.cpp \ src/thrift/protocol/TMultiplexedProtocol.cpp \ src/thrift/protocol/TProtocol.cpp \ src/thrift/transport/TTransportException.cpp \ src/thrift/transport/TFDTransport.cpp \ src/thrift/transport/TFileTransport.cpp \ src/thrift/transport/TSimpleFileTransport.cpp \ src/thrift/transport/THttpTransport.cpp \ src/thrift/transport/THttpClient.cpp \ src/thrift/transport/THttpServer.cpp \ src/thrift/transport/TSocket.cpp \ src/thrift/transport/TPipe.cpp \ src/thrift/transport/TPipeServer.cpp \ src/thrift/transport/TSSLSocket.cpp \ src/thrift/transport/TSocketPool.cpp \ src/thrift/transport/TServerSocket.cpp \ src/thrift/transport/TSSLServerSocket.cpp \ src/thrift/transport/TNonblockingServerSocket.cpp \ src/thrift/transport/TNonblockingSSLServerSocket.cpp \ src/thrift/transport/TTransportUtils.cpp \ src/thrift/transport/TBufferTransports.cpp \ src/thrift/transport/TWebSocketServer.cpp \ src/thrift/transport/SocketCommon.cpp \ src/thrift/server/TConnectedClient.cpp \ src/thrift/server/TServer.cpp \ src/thrift/server/TServerFramework.cpp \ src/thrift/server/TSimpleServer.cpp \ src/thrift/server/TThreadPoolServer.cpp \ src/thrift/server/TThreadedServer.cpp \ src/thrift/concurrency/Mutex.cpp \ src/thrift/concurrency/ThreadFactory.cpp \ src/thrift/concurrency/Thread.cpp \ src/thrift/concurrency/Monitor.cpp libthriftnb_la_SOURCES = src/thrift/server/TNonblockingServer.cpp \ src/thrift/async/TEvhttpServer.cpp \ src/thrift/async/TEvhttpClientChannel.cpp libthriftz_la_SOURCES = src/thrift/transport/TZlibTransport.cpp \ src/thrift/transport/THeaderTransport.cpp \ src/thrift/protocol/THeaderProtocol.cpp libthriftqt5_la_MOC = src/thrift/qt/moc__TQTcpServer.cpp nodist_libthriftqt5_la_SOURCES = $(libthriftqt5_la_MOC) libthriftqt5_la_SOURCES = src/thrift/qt/TQIODeviceTransport.cpp \ src/thrift/qt/TQTcpServer.cpp CLEANFILES = $(libthriftqt5_la_MOC) # Flags for the various libraries libthriftnb_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBEVENT_CPPFLAGS) libthriftz_la_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CPPFLAGS) libthriftqt5_la_CPPFLAGS = $(AM_CPPFLAGS) $(QT5_CFLAGS) \ $(am__append_8) libthriftnb_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftz_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftqt5_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftnb_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LDFLAGS) $(ZLIB_LIBS) libthriftqt5_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS) include_thriftdir = $(includedir)/thrift include_thrift_HEADERS = \ $(top_builddir)/config.h \ src/thrift/numeric_cast.h \ src/thrift/thrift-config.h \ src/thrift/thrift_export.h \ src/thrift/TDispatchProcessor.h \ src/thrift/Thrift.h \ src/thrift/TOutput.h \ src/thrift/TProcessor.h \ src/thrift/TApplicationException.h \ src/thrift/TLogging.h \ src/thrift/TToString.h \ src/thrift/TBase.h \ src/thrift/TConfiguration.h \ src/thrift/TNonCopyable.h include_concurrencydir = $(include_thriftdir)/concurrency include_concurrency_HEADERS = \ src/thrift/concurrency/Exception.h \ src/thrift/concurrency/Mutex.h \ src/thrift/concurrency/Monitor.h \ src/thrift/concurrency/ThreadFactory.h \ src/thrift/concurrency/Thread.h \ src/thrift/concurrency/ThreadManager.h \ src/thrift/concurrency/TimerManager.h \ src/thrift/concurrency/FunctionRunner.h include_protocoldir = $(include_thriftdir)/protocol include_protocol_HEADERS = \ src/thrift/protocol/TEnum.h \ src/thrift/protocol/TList.h \ src/thrift/protocol/TSet.h \ src/thrift/protocol/TMap.h \ src/thrift/protocol/TBinaryProtocol.h \ src/thrift/protocol/TBinaryProtocol.tcc \ src/thrift/protocol/TCompactProtocol.h \ src/thrift/protocol/TCompactProtocol.tcc \ src/thrift/protocol/TDebugProtocol.h \ src/thrift/protocol/THeaderProtocol.h \ src/thrift/protocol/TBase64Utils.h \ src/thrift/protocol/TJSONProtocol.h \ src/thrift/protocol/TMultiplexedProtocol.h \ src/thrift/protocol/TProtocolDecorator.h \ src/thrift/protocol/TProtocolTap.h \ src/thrift/protocol/TProtocolTypes.h \ src/thrift/protocol/TProtocolException.h \ src/thrift/protocol/TVirtualProtocol.h \ src/thrift/protocol/TProtocol.h include_transportdir = $(include_thriftdir)/transport include_transport_HEADERS = \ src/thrift/transport/PlatformSocket.h \ src/thrift/transport/TFDTransport.h \ src/thrift/transport/TFileTransport.h \ src/thrift/transport/THeaderTransport.h \ src/thrift/transport/TSimpleFileTransport.h \ src/thrift/transport/TServerSocket.h \ src/thrift/transport/TSSLServerSocket.h \ src/thrift/transport/TServerTransport.h \ src/thrift/transport/TNonblockingServerTransport.h \ src/thrift/transport/TNonblockingServerSocket.h \ src/thrift/transport/TNonblockingSSLServerSocket.h \ src/thrift/transport/THttpTransport.h \ src/thrift/transport/THttpClient.h \ src/thrift/transport/THttpServer.h \ src/thrift/transport/TSocket.h \ src/thrift/transport/TSocketUtils.h \ src/thrift/transport/TPipe.h \ src/thrift/transport/TPipeServer.h \ src/thrift/transport/TSSLSocket.h \ src/thrift/transport/TSocketPool.h \ src/thrift/transport/TVirtualTransport.h \ src/thrift/transport/TTransport.h \ src/thrift/transport/TTransportException.h \ src/thrift/transport/TTransportUtils.h \ src/thrift/transport/TBufferTransports.h \ src/thrift/transport/TShortReadTransport.h \ src/thrift/transport/TZlibTransport.h \ src/thrift/transport/TWebSocketServer.h \ src/thrift/transport/SocketCommon.h include_serverdir = $(include_thriftdir)/server include_server_HEADERS = \ src/thrift/server/TConnectedClient.h \ src/thrift/server/TServer.h \ src/thrift/server/TServerFramework.h \ src/thrift/server/TSimpleServer.h \ src/thrift/server/TThreadPoolServer.h \ src/thrift/server/TThreadedServer.h \ src/thrift/server/TNonblockingServer.h include_processordir = $(include_thriftdir)/processor include_processor_HEADERS = \ src/thrift/processor/PeekProcessor.h \ src/thrift/processor/StatsProcessor.h \ src/thrift/processor/TMultiplexedProcessor.h include_asyncdir = $(include_thriftdir)/async include_async_HEADERS = \ src/thrift/async/TAsyncChannel.h \ src/thrift/async/TAsyncDispatchProcessor.h \ src/thrift/async/TAsyncProcessor.h \ src/thrift/async/TAsyncBufferProcessor.h \ src/thrift/async/TAsyncProtocolProcessor.h \ src/thrift/async/TConcurrentClientSyncInfo.h \ src/thrift/async/TEvhttpClientChannel.h \ src/thrift/async/TEvhttpServer.h include_qtdir = $(include_thriftdir)/qt include_qt_HEADERS = \ src/thrift/qt/TQIODeviceTransport.h \ src/thrift/qt/TQTcpServer.h WINDOWS_DIST = \ src/thrift/windows \ thrift.sln \ libthrift.vcxproj \ libthrift.vcxproj.filters \ libthriftnb.vcxproj \ libthriftnb.vcxproj.filters \ 3rdparty.props EXTRA_DIST = \ CMakeLists.txt \ coding_standards.md \ README.md \ thrift-nb.pc.in \ thrift.pc.in \ thrift-z.pc.in \ thrift-qt5.pc.in \ src/thrift/qt/CMakeLists.txt \ $(WINDOWS_DIST) all: all-recursive .SUFFIXES: .SUFFIXES: .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/cpp/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign lib/cpp/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): thrift-nb.pc: $(top_builddir)/config.status $(srcdir)/thrift-nb.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ thrift-z.pc: $(top_builddir)/config.status $(srcdir)/thrift-z.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ thrift-qt5.pc: $(top_builddir)/config.status $(srcdir)/thrift-qt5.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ thrift.pc: $(top_builddir)/config.status $(srcdir)/thrift.pc.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } src/thrift/$(am__dirstamp): @$(MKDIR_P) src/thrift @: > src/thrift/$(am__dirstamp) src/thrift/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/$(DEPDIR) @: > src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/TApplicationException.lo: src/thrift/$(am__dirstamp) \ src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/TOutput.lo: src/thrift/$(am__dirstamp) \ src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/VirtualProfiling.lo: src/thrift/$(am__dirstamp) \ src/thrift/$(DEPDIR)/$(am__dirstamp) src/thrift/async/$(am__dirstamp): @$(MKDIR_P) src/thrift/async @: > src/thrift/async/$(am__dirstamp) src/thrift/async/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/async/$(DEPDIR) @: > src/thrift/async/$(DEPDIR)/$(am__dirstamp) src/thrift/async/TAsyncChannel.lo: src/thrift/async/$(am__dirstamp) \ src/thrift/async/$(DEPDIR)/$(am__dirstamp) src/thrift/async/TAsyncProtocolProcessor.lo: \ src/thrift/async/$(am__dirstamp) \ src/thrift/async/$(DEPDIR)/$(am__dirstamp) src/thrift/async/TConcurrentClientSyncInfo.lo: \ src/thrift/async/$(am__dirstamp) \ src/thrift/async/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/$(am__dirstamp): @$(MKDIR_P) src/thrift/concurrency @: > src/thrift/concurrency/$(am__dirstamp) src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/concurrency/$(DEPDIR) @: > src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/ThreadManager.lo: \ src/thrift/concurrency/$(am__dirstamp) \ src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/TimerManager.lo: \ src/thrift/concurrency/$(am__dirstamp) \ src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) src/thrift/processor/$(am__dirstamp): @$(MKDIR_P) src/thrift/processor @: > src/thrift/processor/$(am__dirstamp) src/thrift/processor/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/processor/$(DEPDIR) @: > src/thrift/processor/$(DEPDIR)/$(am__dirstamp) src/thrift/processor/PeekProcessor.lo: \ src/thrift/processor/$(am__dirstamp) \ src/thrift/processor/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/$(am__dirstamp): @$(MKDIR_P) src/thrift/protocol @: > src/thrift/protocol/$(am__dirstamp) src/thrift/protocol/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/protocol/$(DEPDIR) @: > src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/TDebugProtocol.lo: \ src/thrift/protocol/$(am__dirstamp) \ src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/TJSONProtocol.lo: \ src/thrift/protocol/$(am__dirstamp) \ src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/TBase64Utils.lo: \ src/thrift/protocol/$(am__dirstamp) \ src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/TMultiplexedProtocol.lo: \ src/thrift/protocol/$(am__dirstamp) \ src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/TProtocol.lo: src/thrift/protocol/$(am__dirstamp) \ src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/$(am__dirstamp): @$(MKDIR_P) src/thrift/transport @: > src/thrift/transport/$(am__dirstamp) src/thrift/transport/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/transport/$(DEPDIR) @: > src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TTransportException.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TFDTransport.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TFileTransport.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TSimpleFileTransport.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/THttpTransport.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/THttpClient.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/THttpServer.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TSocket.lo: src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TPipe.lo: src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TPipeServer.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TSSLSocket.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TSocketPool.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TServerSocket.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TSSLServerSocket.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TNonblockingServerSocket.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TNonblockingSSLServerSocket.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TTransportUtils.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TBufferTransports.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/TWebSocketServer.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/SocketCommon.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/server/$(am__dirstamp): @$(MKDIR_P) src/thrift/server @: > src/thrift/server/$(am__dirstamp) src/thrift/server/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/server/$(DEPDIR) @: > src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/server/TConnectedClient.lo: \ src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/server/TServer.lo: src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/server/TServerFramework.lo: \ src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/server/TSimpleServer.lo: src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/server/TThreadPoolServer.lo: \ src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/server/TThreadedServer.lo: \ src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/Mutex.lo: \ src/thrift/concurrency/$(am__dirstamp) \ src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/ThreadFactory.lo: \ src/thrift/concurrency/$(am__dirstamp) \ src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/Thread.lo: \ src/thrift/concurrency/$(am__dirstamp) \ src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) src/thrift/concurrency/Monitor.lo: \ src/thrift/concurrency/$(am__dirstamp) \ src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) libthrift.la: $(libthrift_la_OBJECTS) $(libthrift_la_DEPENDENCIES) $(EXTRA_libthrift_la_DEPENDENCIES) $(AM_V_CXXLD)$(libthrift_la_LINK) -rpath $(libdir) $(libthrift_la_OBJECTS) $(libthrift_la_LIBADD) $(LIBS) src/thrift/server/libthriftnb_la-TNonblockingServer.lo: \ src/thrift/server/$(am__dirstamp) \ src/thrift/server/$(DEPDIR)/$(am__dirstamp) src/thrift/async/libthriftnb_la-TEvhttpServer.lo: \ src/thrift/async/$(am__dirstamp) \ src/thrift/async/$(DEPDIR)/$(am__dirstamp) src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo: \ src/thrift/async/$(am__dirstamp) \ src/thrift/async/$(DEPDIR)/$(am__dirstamp) libthriftnb.la: $(libthriftnb_la_OBJECTS) $(libthriftnb_la_DEPENDENCIES) $(EXTRA_libthriftnb_la_DEPENDENCIES) $(AM_V_CXXLD)$(libthriftnb_la_LINK) $(am_libthriftnb_la_rpath) $(libthriftnb_la_OBJECTS) $(libthriftnb_la_LIBADD) $(LIBS) src/thrift/qt/$(am__dirstamp): @$(MKDIR_P) src/thrift/qt @: > src/thrift/qt/$(am__dirstamp) src/thrift/qt/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) src/thrift/qt/$(DEPDIR) @: > src/thrift/qt/$(DEPDIR)/$(am__dirstamp) src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo: \ src/thrift/qt/$(am__dirstamp) \ src/thrift/qt/$(DEPDIR)/$(am__dirstamp) src/thrift/qt/libthriftqt5_la-TQTcpServer.lo: \ src/thrift/qt/$(am__dirstamp) \ src/thrift/qt/$(DEPDIR)/$(am__dirstamp) src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo: \ src/thrift/qt/$(am__dirstamp) \ src/thrift/qt/$(DEPDIR)/$(am__dirstamp) libthriftqt5.la: $(libthriftqt5_la_OBJECTS) $(libthriftqt5_la_DEPENDENCIES) $(EXTRA_libthriftqt5_la_DEPENDENCIES) $(AM_V_CXXLD)$(libthriftqt5_la_LINK) $(am_libthriftqt5_la_rpath) $(libthriftqt5_la_OBJECTS) $(libthriftqt5_la_LIBADD) $(LIBS) src/thrift/transport/libthriftz_la-TZlibTransport.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/transport/libthriftz_la-THeaderTransport.lo: \ src/thrift/transport/$(am__dirstamp) \ src/thrift/transport/$(DEPDIR)/$(am__dirstamp) src/thrift/protocol/libthriftz_la-THeaderProtocol.lo: \ src/thrift/protocol/$(am__dirstamp) \ src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) libthriftz.la: $(libthriftz_la_OBJECTS) $(libthriftz_la_DEPENDENCIES) $(EXTRA_libthriftz_la_DEPENDENCIES) $(AM_V_CXXLD)$(libthriftz_la_LINK) $(am_libthriftz_la_rpath) $(libthriftz_la_OBJECTS) $(libthriftz_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f src/thrift/*.$(OBJEXT) -rm -f src/thrift/*.lo -rm -f src/thrift/async/*.$(OBJEXT) -rm -f src/thrift/async/*.lo -rm -f src/thrift/concurrency/*.$(OBJEXT) -rm -f src/thrift/concurrency/*.lo -rm -f src/thrift/processor/*.$(OBJEXT) -rm -f src/thrift/processor/*.lo -rm -f src/thrift/protocol/*.$(OBJEXT) -rm -f src/thrift/protocol/*.lo -rm -f src/thrift/qt/*.$(OBJEXT) -rm -f src/thrift/qt/*.lo -rm -f src/thrift/server/*.$(OBJEXT) -rm -f src/thrift/server/*.lo -rm -f src/thrift/transport/*.$(OBJEXT) -rm -f src/thrift/transport/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/$(DEPDIR)/TApplicationException.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/$(DEPDIR)/TOutput.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/$(DEPDIR)/VirtualProfiling.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/async/$(DEPDIR)/TAsyncChannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/async/$(DEPDIR)/TAsyncProtocolProcessor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/async/$(DEPDIR)/TConcurrentClientSyncInfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpClientChannel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/concurrency/$(DEPDIR)/Monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/concurrency/$(DEPDIR)/Mutex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/concurrency/$(DEPDIR)/Thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/concurrency/$(DEPDIR)/ThreadFactory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/concurrency/$(DEPDIR)/ThreadManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/concurrency/$(DEPDIR)/TimerManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/processor/$(DEPDIR)/PeekProcessor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/protocol/$(DEPDIR)/TBase64Utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/protocol/$(DEPDIR)/TDebugProtocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/protocol/$(DEPDIR)/TJSONProtocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/protocol/$(DEPDIR)/TMultiplexedProtocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/protocol/$(DEPDIR)/TProtocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/protocol/$(DEPDIR)/libthriftz_la-THeaderProtocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQIODeviceTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQTcpServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/qt/$(DEPDIR)/libthriftqt5_la-moc__TQTcpServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/TConnectedClient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/TServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/TServerFramework.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/TSimpleServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/TThreadPoolServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/TThreadedServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/server/$(DEPDIR)/libthriftnb_la-TNonblockingServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/SocketCommon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TBufferTransports.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TFDTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TFileTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/THttpClient.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/THttpServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/THttpTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TNonblockingSSLServerSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TNonblockingServerSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TPipe.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TPipeServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TSSLServerSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TSSLSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TServerSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TSimpleFileTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TSocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TSocketPool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TTransportException.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TTransportUtils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/TWebSocketServer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/libthriftz_la-THeaderTransport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/thrift/transport/$(DEPDIR)/libthriftz_la-TZlibTransport.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< .cpp.obj: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .cpp.lo: @am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< src/thrift/server/libthriftnb_la-TNonblockingServer.lo: src/thrift/server/TNonblockingServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftnb_la_CPPFLAGS) $(CPPFLAGS) $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/server/libthriftnb_la-TNonblockingServer.lo -MD -MP -MF src/thrift/server/$(DEPDIR)/libthriftnb_la-TNonblockingServer.Tpo -c -o src/thrift/server/libthriftnb_la-TNonblockingServer.lo `test -f 'src/thrift/server/TNonblockingServer.cpp' || echo '$(srcdir)/'`src/thrift/server/TNonblockingServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/server/$(DEPDIR)/libthriftnb_la-TNonblockingServer.Tpo src/thrift/server/$(DEPDIR)/libthriftnb_la-TNonblockingServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/server/TNonblockingServer.cpp' object='src/thrift/server/libthriftnb_la-TNonblockingServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftnb_la_CPPFLAGS) $(CPPFLAGS) $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/server/libthriftnb_la-TNonblockingServer.lo `test -f 'src/thrift/server/TNonblockingServer.cpp' || echo '$(srcdir)/'`src/thrift/server/TNonblockingServer.cpp src/thrift/async/libthriftnb_la-TEvhttpServer.lo: src/thrift/async/TEvhttpServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftnb_la_CPPFLAGS) $(CPPFLAGS) $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/async/libthriftnb_la-TEvhttpServer.lo -MD -MP -MF src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpServer.Tpo -c -o src/thrift/async/libthriftnb_la-TEvhttpServer.lo `test -f 'src/thrift/async/TEvhttpServer.cpp' || echo '$(srcdir)/'`src/thrift/async/TEvhttpServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpServer.Tpo src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/async/TEvhttpServer.cpp' object='src/thrift/async/libthriftnb_la-TEvhttpServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftnb_la_CPPFLAGS) $(CPPFLAGS) $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/async/libthriftnb_la-TEvhttpServer.lo `test -f 'src/thrift/async/TEvhttpServer.cpp' || echo '$(srcdir)/'`src/thrift/async/TEvhttpServer.cpp src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo: src/thrift/async/TEvhttpClientChannel.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftnb_la_CPPFLAGS) $(CPPFLAGS) $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo -MD -MP -MF src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpClientChannel.Tpo -c -o src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo `test -f 'src/thrift/async/TEvhttpClientChannel.cpp' || echo '$(srcdir)/'`src/thrift/async/TEvhttpClientChannel.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpClientChannel.Tpo src/thrift/async/$(DEPDIR)/libthriftnb_la-TEvhttpClientChannel.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/async/TEvhttpClientChannel.cpp' object='src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftnb_la_CPPFLAGS) $(CPPFLAGS) $(libthriftnb_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/async/libthriftnb_la-TEvhttpClientChannel.lo `test -f 'src/thrift/async/TEvhttpClientChannel.cpp' || echo '$(srcdir)/'`src/thrift/async/TEvhttpClientChannel.cpp src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo: src/thrift/qt/TQIODeviceTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftqt5_la_CPPFLAGS) $(CPPFLAGS) $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo -MD -MP -MF src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQIODeviceTransport.Tpo -c -o src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo `test -f 'src/thrift/qt/TQIODeviceTransport.cpp' || echo '$(srcdir)/'`src/thrift/qt/TQIODeviceTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQIODeviceTransport.Tpo src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQIODeviceTransport.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/qt/TQIODeviceTransport.cpp' object='src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftqt5_la_CPPFLAGS) $(CPPFLAGS) $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/qt/libthriftqt5_la-TQIODeviceTransport.lo `test -f 'src/thrift/qt/TQIODeviceTransport.cpp' || echo '$(srcdir)/'`src/thrift/qt/TQIODeviceTransport.cpp src/thrift/qt/libthriftqt5_la-TQTcpServer.lo: src/thrift/qt/TQTcpServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftqt5_la_CPPFLAGS) $(CPPFLAGS) $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/qt/libthriftqt5_la-TQTcpServer.lo -MD -MP -MF src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQTcpServer.Tpo -c -o src/thrift/qt/libthriftqt5_la-TQTcpServer.lo `test -f 'src/thrift/qt/TQTcpServer.cpp' || echo '$(srcdir)/'`src/thrift/qt/TQTcpServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQTcpServer.Tpo src/thrift/qt/$(DEPDIR)/libthriftqt5_la-TQTcpServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/qt/TQTcpServer.cpp' object='src/thrift/qt/libthriftqt5_la-TQTcpServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftqt5_la_CPPFLAGS) $(CPPFLAGS) $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/qt/libthriftqt5_la-TQTcpServer.lo `test -f 'src/thrift/qt/TQTcpServer.cpp' || echo '$(srcdir)/'`src/thrift/qt/TQTcpServer.cpp src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo: src/thrift/qt/moc__TQTcpServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftqt5_la_CPPFLAGS) $(CPPFLAGS) $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo -MD -MP -MF src/thrift/qt/$(DEPDIR)/libthriftqt5_la-moc__TQTcpServer.Tpo -c -o src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo `test -f 'src/thrift/qt/moc__TQTcpServer.cpp' || echo '$(srcdir)/'`src/thrift/qt/moc__TQTcpServer.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/qt/$(DEPDIR)/libthriftqt5_la-moc__TQTcpServer.Tpo src/thrift/qt/$(DEPDIR)/libthriftqt5_la-moc__TQTcpServer.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/qt/moc__TQTcpServer.cpp' object='src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftqt5_la_CPPFLAGS) $(CPPFLAGS) $(libthriftqt5_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/qt/libthriftqt5_la-moc__TQTcpServer.lo `test -f 'src/thrift/qt/moc__TQTcpServer.cpp' || echo '$(srcdir)/'`src/thrift/qt/moc__TQTcpServer.cpp src/thrift/transport/libthriftz_la-TZlibTransport.lo: src/thrift/transport/TZlibTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftz_la_CPPFLAGS) $(CPPFLAGS) $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/transport/libthriftz_la-TZlibTransport.lo -MD -MP -MF src/thrift/transport/$(DEPDIR)/libthriftz_la-TZlibTransport.Tpo -c -o src/thrift/transport/libthriftz_la-TZlibTransport.lo `test -f 'src/thrift/transport/TZlibTransport.cpp' || echo '$(srcdir)/'`src/thrift/transport/TZlibTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/transport/$(DEPDIR)/libthriftz_la-TZlibTransport.Tpo src/thrift/transport/$(DEPDIR)/libthriftz_la-TZlibTransport.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/transport/TZlibTransport.cpp' object='src/thrift/transport/libthriftz_la-TZlibTransport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftz_la_CPPFLAGS) $(CPPFLAGS) $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/transport/libthriftz_la-TZlibTransport.lo `test -f 'src/thrift/transport/TZlibTransport.cpp' || echo '$(srcdir)/'`src/thrift/transport/TZlibTransport.cpp src/thrift/transport/libthriftz_la-THeaderTransport.lo: src/thrift/transport/THeaderTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftz_la_CPPFLAGS) $(CPPFLAGS) $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/transport/libthriftz_la-THeaderTransport.lo -MD -MP -MF src/thrift/transport/$(DEPDIR)/libthriftz_la-THeaderTransport.Tpo -c -o src/thrift/transport/libthriftz_la-THeaderTransport.lo `test -f 'src/thrift/transport/THeaderTransport.cpp' || echo '$(srcdir)/'`src/thrift/transport/THeaderTransport.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/transport/$(DEPDIR)/libthriftz_la-THeaderTransport.Tpo src/thrift/transport/$(DEPDIR)/libthriftz_la-THeaderTransport.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/transport/THeaderTransport.cpp' object='src/thrift/transport/libthriftz_la-THeaderTransport.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftz_la_CPPFLAGS) $(CPPFLAGS) $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/transport/libthriftz_la-THeaderTransport.lo `test -f 'src/thrift/transport/THeaderTransport.cpp' || echo '$(srcdir)/'`src/thrift/transport/THeaderTransport.cpp src/thrift/protocol/libthriftz_la-THeaderProtocol.lo: src/thrift/protocol/THeaderProtocol.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftz_la_CPPFLAGS) $(CPPFLAGS) $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) -MT src/thrift/protocol/libthriftz_la-THeaderProtocol.lo -MD -MP -MF src/thrift/protocol/$(DEPDIR)/libthriftz_la-THeaderProtocol.Tpo -c -o src/thrift/protocol/libthriftz_la-THeaderProtocol.lo `test -f 'src/thrift/protocol/THeaderProtocol.cpp' || echo '$(srcdir)/'`src/thrift/protocol/THeaderProtocol.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) src/thrift/protocol/$(DEPDIR)/libthriftz_la-THeaderProtocol.Tpo src/thrift/protocol/$(DEPDIR)/libthriftz_la-THeaderProtocol.Plo @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='src/thrift/protocol/THeaderProtocol.cpp' object='src/thrift/protocol/libthriftz_la-THeaderProtocol.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libthriftz_la_CPPFLAGS) $(CPPFLAGS) $(libthriftz_la_CXXFLAGS) $(CXXFLAGS) -c -o src/thrift/protocol/libthriftz_la-THeaderProtocol.lo `test -f 'src/thrift/protocol/THeaderProtocol.cpp' || echo '$(srcdir)/'`src/thrift/protocol/THeaderProtocol.cpp mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf src/thrift/.libs src/thrift/_libs -rm -rf src/thrift/async/.libs src/thrift/async/_libs -rm -rf src/thrift/concurrency/.libs src/thrift/concurrency/_libs -rm -rf src/thrift/processor/.libs src/thrift/processor/_libs -rm -rf src/thrift/protocol/.libs src/thrift/protocol/_libs -rm -rf src/thrift/qt/.libs src/thrift/qt/_libs -rm -rf src/thrift/server/.libs src/thrift/server/_libs -rm -rf src/thrift/transport/.libs src/thrift/transport/_libs install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) install-include_asyncHEADERS: $(include_async_HEADERS) @$(NORMAL_INSTALL) @list='$(include_async_HEADERS)'; test -n "$(include_asyncdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_asyncdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_asyncdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_asyncdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_asyncdir)" || exit $$?; \ done uninstall-include_asyncHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_async_HEADERS)'; test -n "$(include_asyncdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_asyncdir)'; $(am__uninstall_files_from_dir) install-include_concurrencyHEADERS: $(include_concurrency_HEADERS) @$(NORMAL_INSTALL) @list='$(include_concurrency_HEADERS)'; test -n "$(include_concurrencydir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_concurrencydir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_concurrencydir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_concurrencydir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_concurrencydir)" || exit $$?; \ done uninstall-include_concurrencyHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_concurrency_HEADERS)'; test -n "$(include_concurrencydir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_concurrencydir)'; $(am__uninstall_files_from_dir) install-include_processorHEADERS: $(include_processor_HEADERS) @$(NORMAL_INSTALL) @list='$(include_processor_HEADERS)'; test -n "$(include_processordir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_processordir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_processordir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_processordir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_processordir)" || exit $$?; \ done uninstall-include_processorHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_processor_HEADERS)'; test -n "$(include_processordir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_processordir)'; $(am__uninstall_files_from_dir) install-include_protocolHEADERS: $(include_protocol_HEADERS) @$(NORMAL_INSTALL) @list='$(include_protocol_HEADERS)'; test -n "$(include_protocoldir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_protocoldir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_protocoldir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_protocoldir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_protocoldir)" || exit $$?; \ done uninstall-include_protocolHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_protocol_HEADERS)'; test -n "$(include_protocoldir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_protocoldir)'; $(am__uninstall_files_from_dir) install-include_qtHEADERS: $(include_qt_HEADERS) @$(NORMAL_INSTALL) @list='$(include_qt_HEADERS)'; test -n "$(include_qtdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_qtdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_qtdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_qtdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_qtdir)" || exit $$?; \ done uninstall-include_qtHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_qt_HEADERS)'; test -n "$(include_qtdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_qtdir)'; $(am__uninstall_files_from_dir) install-include_serverHEADERS: $(include_server_HEADERS) @$(NORMAL_INSTALL) @list='$(include_server_HEADERS)'; test -n "$(include_serverdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_serverdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_serverdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_serverdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_serverdir)" || exit $$?; \ done uninstall-include_serverHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_server_HEADERS)'; test -n "$(include_serverdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_serverdir)'; $(am__uninstall_files_from_dir) install-include_thriftHEADERS: $(include_thrift_HEADERS) @$(NORMAL_INSTALL) @list='$(include_thrift_HEADERS)'; test -n "$(include_thriftdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_thriftdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_thriftdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_thriftdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_thriftdir)" || exit $$?; \ done uninstall-include_thriftHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_thrift_HEADERS)'; test -n "$(include_thriftdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_thriftdir)'; $(am__uninstall_files_from_dir) install-include_transportHEADERS: $(include_transport_HEADERS) @$(NORMAL_INSTALL) @list='$(include_transport_HEADERS)'; test -n "$(include_transportdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_transportdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_transportdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_transportdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_transportdir)" || exit $$?; \ done uninstall-include_transportHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_transport_HEADERS)'; test -n "$(include_transportdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_transportdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(include_asyncdir)" "$(DESTDIR)$(include_concurrencydir)" "$(DESTDIR)$(include_processordir)" "$(DESTDIR)$(include_protocoldir)" "$(DESTDIR)$(include_qtdir)" "$(DESTDIR)$(include_serverdir)" "$(DESTDIR)$(include_thriftdir)" "$(DESTDIR)$(include_transportdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f src/thrift/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/$(am__dirstamp) -rm -f src/thrift/async/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/async/$(am__dirstamp) -rm -f src/thrift/concurrency/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/concurrency/$(am__dirstamp) -rm -f src/thrift/processor/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/processor/$(am__dirstamp) -rm -f src/thrift/protocol/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/protocol/$(am__dirstamp) -rm -f src/thrift/qt/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/qt/$(am__dirstamp) -rm -f src/thrift/server/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/server/$(am__dirstamp) -rm -f src/thrift/transport/$(DEPDIR)/$(am__dirstamp) -rm -f src/thrift/transport/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf src/thrift/$(DEPDIR) src/thrift/async/$(DEPDIR) src/thrift/concurrency/$(DEPDIR) src/thrift/processor/$(DEPDIR) src/thrift/protocol/$(DEPDIR) src/thrift/qt/$(DEPDIR) src/thrift/server/$(DEPDIR) src/thrift/transport/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-include_asyncHEADERS \ install-include_concurrencyHEADERS \ install-include_processorHEADERS \ install-include_protocolHEADERS install-include_qtHEADERS \ install-include_serverHEADERS install-include_thriftHEADERS \ install-include_transportHEADERS install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf src/thrift/$(DEPDIR) src/thrift/async/$(DEPDIR) src/thrift/concurrency/$(DEPDIR) src/thrift/processor/$(DEPDIR) src/thrift/protocol/$(DEPDIR) src/thrift/qt/$(DEPDIR) src/thrift/server/$(DEPDIR) src/thrift/transport/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: uninstall-include_asyncHEADERS \ uninstall-include_concurrencyHEADERS \ uninstall-include_processorHEADERS \ uninstall-include_protocolHEADERS uninstall-include_qtHEADERS \ uninstall-include_serverHEADERS \ uninstall-include_thriftHEADERS \ uninstall-include_transportHEADERS uninstall-libLTLIBRARIES \ uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libLTLIBRARIES \ clean-libtool cscopelist-am ctags ctags-am distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-include_asyncHEADERS \ install-include_concurrencyHEADERS \ install-include_processorHEADERS \ install-include_protocolHEADERS install-include_qtHEADERS \ install-include_serverHEADERS install-include_thriftHEADERS \ install-include_transportHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-pkgconfigDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am style-am style-local tags tags-am \ uninstall uninstall-am uninstall-include_asyncHEADERS \ uninstall-include_concurrencyHEADERS \ uninstall-include_processorHEADERS \ uninstall-include_protocolHEADERS uninstall-include_qtHEADERS \ uninstall-include_serverHEADERS \ uninstall-include_thriftHEADERS \ uninstall-include_transportHEADERS uninstall-libLTLIBRARIES \ uninstall-pkgconfigDATA .PRECIOUS: Makefile moc__%.cpp: %.h $(QT5_MOC) $(QT5_CFLAGS) $< -o $@ style-local: $(CPPSTYLE_CMD) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/.editorconfig0000644000000000000000000000321614303740366015564 0ustar00rootroot00000000000000# ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. ## # # EditorConfig: http://editorconfig.org # see doc/coding_standards.md root = true [*] end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true # ActionScript # [*.as] # C # [*.c] # C++ [*.cpp] indent_style = space indent_size = 2 # C-Sharp # [*.cs] # D # [*.d] # Erlang # [*.erl] # Go-lang [*.go] indent_style = tab indent_size = 8 # C header files # [*.h] # Haskell # [*.hs] # Haxe # [*.hx] # Java # [*.java] # Javascript [*.js] indent_style = space indent_size = 2 # JSON [*.json] indent_style = space indent_size = 2 # Lua # [*.lua] [*.markdown] indent_style = space trim_trailing_whitespace = false [*.md] indent_style = space trim_trailing_whitespace = false # OCaml # [*.ml] # Delphi Pascal # [*.pas] # PHP # [*.php] # Perl # [*.pm] # Python # [*.py] # Ruby # [*.rb] # Typescript # [*.ts] # XML # [*.xml] thrift-0.19.0/Makefile.in0000644000000000000000000010446714472652514015172 0ustar00rootroot00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in 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. @SET_MAKE@ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WITH_TESTS_TRUE@am__append_1 = test @WITH_TUTORIAL_TRUE@am__append_2 = tutorial subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/aclocal/ac_prog_bison.m4 \ $(top_srcdir)/aclocal/ax_boost_base.m4 \ $(top_srcdir)/aclocal/ax_check_openssl.m4 \ $(top_srcdir)/aclocal/ax_compare_version.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx.m4 \ $(top_srcdir)/aclocal/ax_cxx_compile_stdcxx_11.m4 \ $(top_srcdir)/aclocal/ax_dmd.m4 \ $(top_srcdir)/aclocal/ax_javac_and_java.m4 \ $(top_srcdir)/aclocal/ax_lib_event.m4 \ $(top_srcdir)/aclocal/ax_lib_zlib.m4 \ $(top_srcdir)/aclocal/ax_lua.m4 \ $(top_srcdir)/aclocal/ax_prog_dotnetcore_version.m4 \ $(top_srcdir)/aclocal/ax_prog_haxe_version.m4 \ $(top_srcdir)/aclocal/ax_prog_perl_modules.m4 \ $(top_srcdir)/aclocal/ax_signed_right_shift.m4 \ $(top_srcdir)/aclocal/ax_thrift_internal.m4 \ $(top_srcdir)/aclocal/libtool.m4 \ $(top_srcdir)/aclocal/ltoptions.m4 \ $(top_srcdir)/aclocal/ltsugar.m4 \ $(top_srcdir)/aclocal/ltversion.m4 \ $(top_srcdir)/aclocal/lt~obsolete.m4 \ $(top_srcdir)/aclocal/tar.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h $(top_builddir)/lib/cpp/src/thrift/config.h \ $(top_builddir)/lib/c_glib/src/thrift/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__extra_recursive_targets = style-recursive am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.hin config.hin config.hin # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = compiler/cpp lib test tutorial am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.hin compile \ config.guess config.sub depcomp install-sh ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALLOCA = @ALLOCA@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ ANT = @ANT@ ANT_FLAGS = @ANT_FLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BISON = @BISON@ BOOST_CHRONO_LDADD = @BOOST_CHRONO_LDADD@ BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ BOOST_FILESYSTEM_LDADD = @BOOST_FILESYSTEM_LDADD@ BOOST_LDFLAGS = @BOOST_LDFLAGS@ BOOST_LIB_DIR = @BOOST_LIB_DIR@ BOOST_SYSTEM_LDADD = @BOOST_SYSTEM_LDADD@ BOOST_TEST_LDADD = @BOOST_TEST_LDADD@ BOOST_THREAD_LDADD = @BOOST_THREAD_LDADD@ BUNDLER = @BUNDLER@ CARGO = @CARGO@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CLASSPATH = @CLASSPATH@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CPPSTYLE_CMD = @CPPSTYLE_CMD@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DART = @DART@ DARTPUB = @DARTPUB@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DMD = @DMD@ DMD_LIBEVENT_FLAGS = @DMD_LIBEVENT_FLAGS@ DMD_OF_DIRSEP = @DMD_OF_DIRSEP@ DMD_OPENSSL_FLAGS = @DMD_OPENSSL_FLAGS@ DOTNETCORE = @DOTNETCORE@ DOTNETCORE_VERSION = @DOTNETCORE_VERSION@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ D_EVENT_LIB_NAME = @D_EVENT_LIB_NAME@ D_IMPORT_PREFIX = @D_IMPORT_PREFIX@ D_LIB_NAME = @D_LIB_NAME@ D_SSL_LIB_NAME = @D_SSL_LIB_NAME@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ENABLE_COVERAGE = @ENABLE_COVERAGE@ ERL = @ERL@ ERLANG_INSTALL_LIB_DIR = @ERLANG_INSTALL_LIB_DIR@ ERLANG_INSTALL_LIB_DIR_thrift = @ERLANG_INSTALL_LIB_DIR_thrift@ ERLANG_LIB_DIR = @ERLANG_LIB_DIR@ ERLC = @ERLC@ ERLCFLAGS = @ERLCFLAGS@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCOV_CFLAGS = @GCOV_CFLAGS@ GCOV_CXXFLAGS = @GCOV_CXXFLAGS@ GCOV_LDFLAGS = @GCOV_LDFLAGS@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ GO = @GO@ GOBJECT_CFLAGS = @GOBJECT_CFLAGS@ GOBJECT_LIBS = @GOBJECT_LIBS@ GRADLE = @GRADLE@ GRADLE_OPTS = @GRADLE_OPTS@ GREP = @GREP@ GSETTINGS = @GSETTINGS@ HAVE_CXX11 = @HAVE_CXX11@ HAXE = @HAXE@ HAXE_VERSION = @HAXE_VERSION@ INSTALL = @INSTALL@ INSTALLDIRS = @INSTALLDIRS@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ JAVA_PREFIX = @JAVA_PREFIX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBEVENT_CPPFLAGS = @LIBEVENT_CPPFLAGS@ LIBEVENT_LDFLAGS = @LIBEVENT_LDFLAGS@ LIBEVENT_LIBS = @LIBEVENT_LIBS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ LUA = @LUA@ LUA_EXEC_PREFIX = @LUA_EXEC_PREFIX@ LUA_INCLUDE = @LUA_INCLUDE@ LUA_LIB = @LUA_LIB@ LUA_PLATFORM = @LUA_PLATFORM@ LUA_PREFIX = @LUA_PREFIX@ LUA_SHORT_VERSION = @LUA_SHORT_VERSION@ LUA_VERSION = @LUA_VERSION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MAYBE_CL = @MAYBE_CL@ MAYBE_CPP = @MAYBE_CPP@ MAYBE_C_GLIB = @MAYBE_C_GLIB@ MAYBE_D = @MAYBE_D@ MAYBE_DART = @MAYBE_DART@ MAYBE_ERLANG = @MAYBE_ERLANG@ MAYBE_GO = @MAYBE_GO@ MAYBE_JAVA = @MAYBE_JAVA@ MAYBE_KOTLIN = @MAYBE_KOTLIN@ MAYBE_LUA = @MAYBE_LUA@ MAYBE_NETSTD = @MAYBE_NETSTD@ MAYBE_NODEJS = @MAYBE_NODEJS@ MAYBE_NODETS = @MAYBE_NODETS@ MAYBE_PERL = @MAYBE_PERL@ MAYBE_PHP = @MAYBE_PHP@ MAYBE_PY3 = @MAYBE_PY3@ MAYBE_PYTHON = @MAYBE_PYTHON@ MAYBE_RS = @MAYBE_RS@ MAYBE_RUBY = @MAYBE_RUBY@ MAYBE_SWIFT = @MAYBE_SWIFT@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODEJS = @NODEJS@ NODETS = @NODETS@ NPM = @NPM@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_INCLUDES = @OPENSSL_INCLUDES@ OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@ OPENSSL_LIBS = @OPENSSL_LIBS@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PERL_PREFIX = @PERL_PREFIX@ PHP = @PHP@ PHP_CONFIG = @PHP_CONFIG@ PHP_CONFIG_PREFIX = @PHP_CONFIG_PREFIX@ PHP_PREFIX = @PHP_PREFIX@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ PYTHON = @PYTHON@ PYTHON3 = @PYTHON3@ PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ PYTHON_PLATFORM = @PYTHON_PLATFORM@ PYTHON_PREFIX = @PYTHON_PREFIX@ PYTHON_VERSION = @PYTHON_VERSION@ PY_PREFIX = @PY_PREFIX@ QT5_CFLAGS = @QT5_CFLAGS@ QT5_LIBS = @QT5_LIBS@ QT5_MOC = @QT5_MOC@ RANLIB = @RANLIB@ REBAR = @REBAR@ RUBY = @RUBY@ RUBY_PREFIX = @RUBY_PREFIX@ RUSTC = @RUSTC@ SBCL = @SBCL@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ SWIFT = @SWIFT@ THRIFT = @THRIFT@ TRIAL = @TRIAL@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ ZLIB_CPPFLAGS = @ZLIB_CPPFLAGS@ ZLIB_LDFLAGS = @ZLIB_LDFLAGS@ ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ golang_version = @golang_version@ have_prog_bison = @have_prog_bison@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ luadir = @luadir@ luaexecdir = @luaexecdir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ pkgluadir = @pkgluadir@ pkgluaexecdir = @pkgluaexecdir@ pkgpyexecdir = @pkgpyexecdir@ pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ pyexecdir = @pyexecdir@ pythondir = @pythondir@ runstatedir = @runstatedir@ rustc_version = @rustc_version@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I ./aclocal SUBDIRS = compiler/cpp lib $(am__append_1) $(am__append_2) CLEANFILES = \ composer.lock \ dub.selections.json DISTCLEANFILES = \ Makefile \ Makefile.in \ aclocal.m4 \ apache-thrift-test-library \ autoscan.log \ compile \ config.guess \ config.hin \ config.hin~ \ config.log \ config.status \ config.sub \ configure \ configure.scan \ debcomp \ install-sh \ ltmain.sh \ missing \ ylwrap empty := space := $(empty) $(empty) comma := , CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ @MAYBE_KOTLIN@ @MAYBE_SWIFT@ CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS)) @WITH_PY3_FALSE@CROSS_PY = $(PYTHON) @WITH_PY3_TRUE@CROSS_PY = $(PYTHON3) TIMES = 1 2 3 codespell_skip_files = \ *.jar \ *.class \ *.so \ *.a \ *.la \ *.o \ *.p12 \ *OCamlMakefile \ .keystore \ .truststore \ CHANGES \ config.sub \ configure \ depcomp \ libtool.m4 \ output.* \ rebar \ thrift skipped_files = $(subst $(space),$(comma),$(codespell_skip_files)) EXTRA_DIST = \ .asf.yaml \ .clang-format \ .dockerignore \ .editorconfig \ .eslintignore \ .eslintrc.json \ .flake8 \ .gitattributes \ .gitignore \ .travis.yml \ ApacheThrift.nuspec \ appveyor.yml \ bootstrap.sh \ bower.json \ build \ CHANGES.md \ CMakeLists.txt \ composer.json \ contrib \ CONTRIBUTING.md \ debian \ doap.rdf \ doc \ dub.json \ go.mod \ jitpack.yml \ LANGUAGES.md \ LICENSE \ NOTICE \ package.json \ package-lock.json \ phpcs.xml.dist \ README.md \ rust-toolchain \ sonar-project.properties \ Thrift.podspec all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.hin $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.hin: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ lib/cpp/src/thrift/config.h: lib/cpp/src/thrift/stamp-h2 @test -f $@ || rm -f lib/cpp/src/thrift/stamp-h2 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) lib/cpp/src/thrift/stamp-h2 lib/cpp/src/thrift/stamp-h2: $(srcdir)/config.hin $(top_builddir)/config.status @rm -f lib/cpp/src/thrift/stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status lib/cpp/src/thrift/config.h lib/c_glib/src/thrift/config.h: lib/c_glib/src/thrift/stamp-h3 @test -f $@ || rm -f lib/c_glib/src/thrift/stamp-h3 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) lib/c_glib/src/thrift/stamp-h3 lib/c_glib/src/thrift/stamp-h3: $(srcdir)/config.hin $(top_builddir)/config.status @rm -f lib/c_glib/src/thrift/stamp-h3 cd $(top_builddir) && $(SHELL) ./config.status lib/c_glib/src/thrift/config.h distclean-hdr: -rm -f config.h stamp-h1 lib/cpp/src/thrift/config.h lib/cpp/src/thrift/stamp-h2 lib/c_glib/src/thrift/config.h lib/c_glib/src/thrift/stamp-h3 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" style-local: ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: style: style-recursive style-am: style-local uninstall-am: .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool clean-local cscope cscopelist-am ctags ctags-am \ dist dist-all dist-bzip2 dist-gzip dist-hook dist-lzip \ dist-shar dist-tarZ dist-xz dist-zip distcheck distclean \ distclean-generic distclean-hdr distclean-libtool \ distclean-local distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am style-am style-local tags tags-am uninstall \ uninstall-am .PRECIOUS: Makefile clean-local: $(RM) -r vendor/ distclean-local: $(RM) -r .dub/ $(RM) -r autom4te.cache/ dist-hook: find $(distdir) -type f \( -iname ".DS_Store" -or -iname "._*" -or -iname ".gitignore" \) | xargs rm -f find $(distdir) -type d \( -iname ".deps" -or -iname ".libs" \) | xargs rm -rf find $(distdir) -type d \( -iname ".svn" -or -iname ".git" \) | xargs rm -rf print-version: @echo $(PACKAGE_VERSION) .PHONY: precross cross precross-%: all $(MAKE) -C $* precross precross: all precross-test precross-lib @WITH_PYTHON_TRUE@crossfeature: precross @WITH_PYTHON_TRUE@ $(CROSS_PY) test/test.py --retry-count 5 --features .* --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED) # feature test needs python build @WITH_PYTHON_FALSE@crossfeature: cross-%: precross crossfeature $(CROSS_PY) test/test.py --retry-count 5 --skip-known-failures --server $(CROSS_LANGS_COMMA_SEPARATED) --client $(CROSS_LANGS_COMMA_SEPARATED) --regex "$*" cross: cross-.* fail: precross $(CROSS_PY) test/test.py || true $(CROSS_PY) test/test.py --update-expected-failures=overwrite $(foreach var,$(TIMES),test/test.py -s || true;test/test.py --update-expected-failures=merge;) style-local: codespell --write-changes --skip=$(skipped_files) --disable-colors # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: thrift-0.19.0/bootstrap.sh0000777000000000000000000000361114102321351015450 0ustar00rootroot00000000000000#!/bin/sh # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # echo -n "make distclean... " make -k distclean >/dev/null 2>&1 echo "ok" if test -d lib/php/src/ext/thrift_protocol ; then if phpize -v >/dev/null 2>/dev/null ; then (cd lib/php/src/ext/thrift_protocol && phpize) fi fi set -e # libtoolize is called "glibtoolize" on OSX. if libtoolize --version 1 >/dev/null 2>/dev/null; then LIBTOOLIZE=libtoolize elif glibtoolize --version 1 >/dev/null 2>/dev/null; then LIBTOOLIZE=glibtoolize else echo >&2 "Couldn't find libtoolize!" exit 1 fi format_version () { printf "%03d%03d%03d%03d" $(echo $1 | tr '.' ' '); } # we require automake 1.13 or later # check must happen externally due to use of newer macro AUTOMAKE_VERSION=`automake --version | grep automake | egrep -o '([0-9]{1,}\.)+[0-9]{1,}'` if [ $(format_version $AUTOMAKE_VERSION) -lt $(format_version 1.13) ]; then echo >&2 "automake version $AUTOMAKE_VERSION is too old (need 1.13 or later)" exit 1 fi set -e autoscan $LIBTOOLIZE --copy --automake aclocal -I ./aclocal autoheader sed '/undef VERSION/d' config.hin > config.hin2 mv config.hin2 config.hin autoconf automake --copy --add-missing thrift-0.19.0/Thrift.podspec0000644000000000000000000000171714454461475015742 0ustar00rootroot00000000000000Pod::Spec.new do |s| s.name = 'Thrift' s.version = '0.19.0' s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages. DESC s.homepage = 'https://thrift.apache.org' s.license = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' } s.author = { 'Apache Thrift Developers' => 'dev@thrift.apache.org' } s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' s.source = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.19.0' } s.source_files = 'lib/swift/Sources/*.swift' end thrift-0.19.0/depcomp0000777017777601777760000005601714114740203015610 0ustar00nobodynogroup00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2016-01-11.22; # UTC # Copyright (C) 1999-2017 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 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: thrift-0.19.0/ylwrap0000755000000000000000000001531314472652514014360 0ustar00rootroot00000000000000#! /bin/sh # ylwrap - wrapper for lex/yacc invocations. scriptversion=2016-01-11.22; # UTC # Copyright (C) 1996-2017 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 # . get_dirname () { case $1 in */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';; # Otherwise, we want the empty string (not "."). esac } # guard FILE # ---------- # The CPP macro used to guard inclusion of FILE. guard () { printf '%s\n' "$1" \ | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \ -e 's/__*/_/g' } # quote_for_sed [STRING] # ---------------------- # Return STRING (or stdin) quoted to be used as a sed pattern. quote_for_sed () { case $# in 0) cat;; 1) printf '%s\n' "$1";; esac \ | sed -e 's|[][\\.*]|\\&|g' } case "$1" in '') echo "$0: No files given. Try '$0 --help' for more information." 1>&2 exit 1 ;; --basedir) basedir=$2 shift 2 ;; -h|--h*) cat <<\EOF Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... Wrapper for lex/yacc invocations, renaming files as desired. INPUT is the input file OUTPUT is one file PROG generates DESIRED is the file we actually want instead of OUTPUT PROGRAM is program to run ARGS are passed to PROG Any number of OUTPUT,DESIRED pairs may be used. Report bugs to . EOF exit $? ;; -v|--v*) echo "ylwrap $scriptversion" exit $? ;; esac # The input. input=$1 shift # We'll later need for a correct munging of "#line" directives. input_sub_rx=`get_dirname "$input" | quote_for_sed` case $input in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input=`pwd`/$input ;; esac input_rx=`get_dirname "$input" | quote_for_sed` # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot=false if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot=true fi # The parser itself, the first file, is the destination of the .y.c # rule in the Makefile. parser=$1 # A sed program to s/FROM/TO/g for all the FROM/TO so that, for # instance, we rename #include "y.tab.h" into #include "parse.h" # during the conversion from y.tab.c to parse.c. sed_fix_filenames= # Also rename header guards, as Bison 2.7 for instance uses its header # guard in its implementation file. sed_fix_header_guards= while test $# -ne 0; do if test x"$1" = x"--"; then shift break fi from=$1 # Handle y_tab.c and y_tab.h output by DOS if $y_tab_nodot; then case $from in "y.tab.c") from=y_tab.c;; "y.tab.h") from=y_tab.h;; esac fi shift to=$1 shift sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;" sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;" done # The program to run. prog=$1 shift # Make any relative path in $prog absolute. case $prog in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog=`pwd`/$prog ;; esac dirname=ylwrap$$ do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (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 mkdir $dirname || exit 1 cd $dirname case $# in 0) "$prog" "$input" ;; *) "$prog" "$@" "$input" ;; esac ret=$? if test $ret -eq 0; then for from in * do to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"` if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend '../'. case $to in [\\/]* | ?:[\\/]*) target=$to;; *) target=../$to;; esac # Do not overwrite unchanged header files to avoid useless # recompilations. Always update the parser itself: it is the # destination of the .y.c rule in the Makefile. Divert the # output of all other files to a temporary file so we can # compare them to existing versions. if test $from != $parser; then realtarget=$target target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'` fi # Munge "#line" or "#" directives. Don't let the resulting # debug information point at an absolute srcdir. Use the real # output file name, not yy.lex.c for instance. Adjust the # include guards too. sed -e "/^#/!b" \ -e "s|$input_rx|$input_sub_rx|" \ -e "$sed_fix_filenames" \ -e "$sed_fix_header_guards" \ "$from" >"$target" || ret=$? # Check whether files must be updated. if test "$from" != "$parser"; then if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then echo "$to is unchanged" rm -f "$target" else echo "updating $to" mv -f "$target" "$realtarget" fi fi else # A missing file is only an error for the parser. This is a # blatant hack to let us support using "yacc -d". If -d is not # specified, don't fail when the header file is "missing". if test "$from" = "$parser"; then ret=1 fi fi done fi # Remove the directory. cd .. rm -rf $dirname exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: thrift-0.19.0/.gitattributes0000644000000000000000000000001414303740366015773 0ustar00rootroot00000000000000* text=auto